asm: fix relocations and dangling bytes

The 6502 assembler took a different approach to relocations, wherein
jump values were stored in the subsequent byte. In this device, jump
values are stored in the current word.

Additionally, jumps only have a 1-word offset, not 2-bytes.

This necessitates several changes, which are presented here. This
includes not eating the subsequent byte, and only subtracting 1 from the
current PC rather than 2.

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2020-08-06 16:43:23 +08:00
parent 78a2fd2deb
commit 727d101adf

View File

@ -100,7 +100,7 @@ macro_rules! lockstep_replace {
// Position of a replacement reached (or: inside a replacement) // Position of a replacement reached (or: inside a replacement)
// Coupled with a seek step // Coupled with a seek step
lockstep_replace!( lockstep_replace!(
[ $($result,)* $rep1 ], [ $($result,)* $rep1 | $src1_replaced ],
[ $($src,)* ], [ $($src,)* ],
[], [],
[ $($rep_rest,)* ], [ $($rep_rest,)* ],
@ -134,7 +134,12 @@ macro_rules! lockstep_replace {
#[macro_export] #[macro_export]
#[doc(hidden)] #[doc(hidden)]
macro_rules! reloc { macro_rules! reloc {
( { $($attr:tt)* } [ $( [ $($pos:expr),* ], [ $($rep:expr),* ] ),* ], $lblmap:ident, [ $($mcode:expr),* ], [/* empty relocation list */] ) => { ( { $($attr:tt)* }
[ $( [ $($pos:expr),* ],
[ $($rep:expr),* ] ),* ],
$lblmap:ident,
[ $($mcode:expr),* ],
[/* empty relocation list */] ) => {
lockstep_replace!([], [ $($mcode,)* ], $( [ $($pos,)* ], [ $($rep,)* ], )*) lockstep_replace!([], [ $($mcode,)* ], $( [ $($pos,)* ], [ $($rep,)* ], )*)
}; };
( { start: $start:expr } [ $( [ $($pos:expr),* ], [ $($rep:expr),* ] ),* ], $lblmap:ident, [ $($mcode:expr),* ], [ { $lbl:ident as ABS16 @ [$($lockstepmcpos:expr),*] } $(,$reloc:tt)* ] ) => { ( { start: $start:expr } [ $( [ $($pos:expr),* ], [ $($rep:expr),* ] ),* ], $lblmap:ident, [ $($mcode:expr),* ], [ { $lbl:ident as ABS16 @ [$($lockstepmcpos:expr),*] } $(,$reloc:tt)* ] ) => {
@ -147,15 +152,14 @@ macro_rules! reloc {
[ $($lockstepmcpos),* ], [ ($lblmap!($lbl) + $start) as u8, (($lblmap!($lbl) + $start) >> 8) as u8 ] ], [ $($lockstepmcpos),* ], [ ($lblmap!($lbl) + $start) as u8, (($lblmap!($lbl) + $start) >> 8) as u8 ] ],
$lblmap, [ $($mcode),* ], [ $($reloc),* ]) $lblmap, [ $($mcode),* ], [ $($reloc),* ])
}; };
( { $($attr:tt)* } [ $( [ $($pos:expr),* ], [ $($rep:expr),* ] ),* ], $lblmap:ident, [ $($mcode:expr),* ], [ { $lbl:ident as PCREL @ [$($lockstepmcpos:expr),*] } $(,$reloc:tt)* ] ) => { ( { $($attr:tt)* } [ $( [ $($pos:expr),* ], [ $($rep:expr),* ] ),* ], $lblmap:ident, [ $($mcode:expr),* ], [ { $lbl:ident as PCREL @ [$($lockstepmcpos:expr,)*] } $(,$reloc:tt)* ] ) => {
// Replace 1 Byte with the PC relative address // OR in the PC-relative address to the opcode
// PC is the program counter *after* the relocated offset (the length of the
// `$lockstepmcpos` array + 1), so we need to subtract 1 additional byte.
reloc!( reloc!(
{ $($attr)* } { $($attr)* }
[ $( [ $($pos),* ], [ $($rep),* ] ,)* [ $( [ $($pos),* ], [ $($rep),* ] ,)*
[ $($lockstepmcpos),* ], [ ((( $lblmap!($lbl) as i32 - codelen!($($lockstepmcpos),*) as i32 - 1 ) & 0x3FF ) << 23) ] ], [ $($lockstepmcpos),* ], [ ((( $lblmap!($lbl) as i32 - (codelen!($($lockstepmcpos),*)) as i32 - 1 ) & 0x3FF ) << 23) ] ],
$lblmap, [ $($mcode),* ], [ $($reloc),* ]) $lblmap,
[ $($mcode),* ], [ $($reloc),* ])
}; };
} }
@ -207,17 +211,25 @@ macro_rules! asm_ {
}; };
// BRZ // BRZ
// ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ], ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
// brz $label:ident , % $ra:tt brz $label:ident , %$ra:tt
// $($rest:tt)* ) => { $($rest:tt)* ) => {
// asm_!({ $($attr)* } [ $($mcode,)* 0x0 ], asm_!({ $($attr)* } [ $($mcode,)* 0 << 23 | 0 << 11 | $ra << 6 | 0x9 ],
// [ $($lbl => $lblval),* ], [ $($reloc,)* { $label as PCREL @ [ $($mcode,)* ] } ], $($rest)*) [ $($lbl => $lblval),* ], [ $($reloc,)* { $label as PCREL @ [$($mcode,)*] } ], $($rest)*)
// }; };
( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ], ( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
brz $label:ident , #$ra:tt brz $label:ident , #$ra:tt
$($rest:tt)* ) => { $($rest:tt)* ) => {
asm_!({ $($attr)* } [ $($mcode,)* 0 << 23 | 1 << 11 | $ra << 6 | 0x9 ], asm_!({ $($attr)* } [ $($mcode,)* 0 << 23 | 1 << 11 | $ra << 6 | 0x9 ],
[ $($lbl => $lblval),* ], [ $($reloc,)* { $label as PCREL @ [$($mcode,)* 0 << 23 | 1 << 11 | $ra << 6 | 0x9] } ], $($rest)*) [ $($lbl => $lblval),* ], [ $($reloc,)* { $label as PCREL @ [$($mcode,)*] } ], $($rest)*)
};
// UDF
( { $($attr:tt)* } [ $($mcode:expr),* ], [ $($lbl:ident => $lblval:expr),* ], [ $($reloc:tt),* ],
udf
$($rest:tt)* ) => {
asm_!({ $($attr)* } [ $($mcode,)* -0x7FFF_FFFF ], [ $($lbl => $lblval),* ], [ $($reloc),* ], $($rest)*)
}; };
// ================================================================================== // ==================================================================================