Bug 127 - * corner case bug and a few observations
Summary: * corner case bug and a few observations
Alias: None
Product: RMAC
Classification: Unclassified
Component: Core (show other bugs)
Version: unspecified
Hardware: PC Linux
: High major
Assignee: Shamus Hammons
Depends on:
Reported: 2018-06-22 14:38 CDT by ggn
Modified: 2018-06-23 12:40 CDT (History)
1 user (show)

See Also:


Note You need to log in before you can comment on or make changes to this bug.
Description ggn 2018-06-22 14:38:13 CDT
Okay, so here's a nasty corner case:

bra.s *+0

will generate $6000. This is the opcode for bra.w, so this will actually generate wrong code! (the 68k will want to fetch an extra word and everything will go super bad!)

So that's one part of the equation, we can certainly fix this, and we should! But before I'd like to show what other assemblers do in this case.

First of all, rmac:

    1  00000000  6000                   bra.s *+2
    2  00000002  6002                   bra.s *+4
    3  00000004  60FC                   bra.s *-2
    4  00000006  60FE                   bra.s *+0

Turbo assembler:

6002 bra.s *+2
6004 bra.s *+4
60fe bra.s *-2
4e71 bra.s *+0

Devpac 3:

---- bra.s *+2 Error: short branch cannot be 0 bytes
6002 bra.s *+4
60fc bra.s *-2
60fe bra.s *+0


F00:0001 E2058  bra.s *+2               S01:00000000:  4D D6
F00:0002        bra.s *+4               S01:00000002:  60 02
F00:0003        bra.s *-2               S01:00000004:  60 FC
F00:0004        bra.s *+0               S01:00000006:  60 FE


So rmac, devpac 3 and vasm use more or less the same scheme (minus rmac's bug), tass has a +2 offset compared to the rest and optimises the 0 length branch to nop, while vasm outputs lea (a6),a6 instead of nop :).

Personally I'm accustomed to tass' way, i.e. offset is calculated before the word deposit but I might be the minority here.

I'd like your opinion on this. The easiest way would be to simply fix the $6000 bug. Worst case we'd have to calculate * stuff pre-deposit (which tbf makes more sense to me!)...
Comment 1 Shamus Hammons 2018-06-23 09:43:39 CDT
Well, I'd say that the "bra.s *+2" generating $6000 should be fixed regardless, and I like the handling of it by the "emitting a NOP" method. TBH, I didn't know that RMAC handled *+<expr> syntax (which will make it easier to support MAC/65 syntax in future). :-)

So, I guess it comes down to user expectations of what "*" means. To me, (coming from my MAC/65 background) it would seem the "*" means the current origin *before* anything is deposited, so yeah, it looks like RMAC, Devpac & Vasm do the right thing IMO.

Turbo Asm looks like it's taking "*" to mean the address *after* the opcodes have been deposited. If you look at the "bra.s *+0" case, it generates a NOP for that when what you would expect for that case is more like "foo: bra.s foo"--so what it's doing is arguably a wrong approach IMO.

So yeah, it looks like a simple fix on this one; emit a NOP and call it a day. :-)
Comment 2 ggn 2018-06-23 12:40:01 CDT
Yup, it's all a matter of perspective - personally I like tass' handling better. One example I use all the time is:

bra.s *-2

to create an infinite loop (i.e. I can halt execution to anywhere inside the code), or

bra.s *+4

to skip over a 4 byte instruction.

These also translate nicely to $6002 and $60fe which is very orthogonal to the offsets! If I want to do this using the other assemblers' convention I'd have to use something like bra.s *+0 and bra.s *+2, which are hardly easy to remember :). So IMO tass' version is more programmer friendly.

I'll get me coat now!