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
1 changed files with 27 additions and 15 deletions

View File

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