2

I'm using an 'm68k-elf-as' compiler (https://gnutoolchains.com/m68k-elf/) for assembly code that I'm patching into my car's ECU (CPU32 ISA, MC68376 processor).

Is there a simple way to control typecasting in the gnu assembler? I'm having trouble with data sign and length.

Here are examples of my troubles

1) Sign: I use a quick move instruction that takes 8-bits of immediate data, sign-extends it, and places it into a data register:

MOVEQ #136,%D0

and the assembler complains 'Error: operands mismatch -- statement `moveq #136,%D0' ignored' This only compiles if I write the two's complement: 'MOVEQ #-120,%D0'

I recognize that the value in D0 contains sign, so inflexible interpretation of this instruction requires that I write in a signed 8-bit value, but the end-use of what is in the register in my code is dictated by subsequent instructions. i.e. my next instruction acts on 8-bits of data and I use the value as unsigned. bits are bits.

Is there a simple way to make the .as compiler take whatever 8-bit value I write, rather than excluding something based on assumption of a signed value?

2) Length: I use a jump table based on in-line data to jump to code relative to the current program counter:

MOVE.W 0x6(%PC,%D0.W),%D0 |code prior to this makes sure that D0 contains an even value <=18
JMP 0x2(%PC,%D0.W)   
jump_start:
.word end_routine-jump_start    | this does not compile correctly
.word end_routine-jump_start
.word end_routine-jump_start
.word end_routine-jump_start
.word end_routine-jump_start
.word end_routine-jump_start
.word end_routine-jump_start
.word end_routine-jump_start
.word end_routine-jump_start
.word continue_routine-jump_start  |if D0 contains 18, then we continue in the routine
BRA.W end_routine
continue_routine:

When this compiles, the 'jump_start' label is at address 0x31072, and the end_routine address is at 0x314e0, so the inline data should be: 0x046e, easily fitting in the 16-bit .word directive that I wrote. However, the compiler fails to correctly calculate this unless I use a .long directive.

Is there a simple way to get the compiler to calculate the value using the necessary 32-bits and then cast or mask it to 16 bits, while still retaining the in-line jump table data?

one more thing: I explicitly added a 'branch always' command at the end of the data in the jump table, but then the compiler adds more lines of similar nature:

BRA.W $456 |branch to end_routine, added by me
BRA.W $e   |branch to continue_routine, added by compiler
BRA.L $a   |branch to continue_routine, added by compiler
BRA.L $448 |branch to end_routine, added by the compiler
continue_routine:

Is there a simple way to make the compiler not add extra code? I already avoid compiling through .gcc before using .as because of the extra code it adds...

curiousguy
  • 8,038
  • 2
  • 40
  • 58
Obeisance
  • 21
  • 3
  • did you try #0x88? – old_timer May 30 '20 at 14:13
  • binutils is open source btw... – old_timer May 30 '20 at 14:14
  • Thanks for the replies. I did try using 0x88 instead of #136, but the same error occurred. As far as editing binutils to suit my needs, I have so far not even learned how to compile my own version of a cross-compiler. I think that editing binutils and recompiling a cross-compiler may be harder for me than writing my own compiler from scratch in java or c++. Tasks like that are easy for those with experience, but I need hand-holding. – Obeisance May 30 '20 at 14:37
  • For `moveq` you could define a macro which moves `#((x ^ 128) - 128)` instead of `#x`. Not sure about the jump table -- does this also happen if the total object file is less than `0x8000`? (If that is the case, try to split your code into smaller files and link them together) – chtz Jun 03 '20 at 15:29

0 Answers0