Okay, so here's a nasty corner case:
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
6002 bra.s *+2
6004 bra.s *+4
60fe bra.s *-2
4e71 bra.s *+0
---- 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!)...
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. :-)
Yup, it's all a matter of perspective - personally I like tass' handling better. One example I use all the time is:
to create an infinite loop (i.e. I can halt execution to anywhere inside the code), or
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!