flamewing / asl-releases

Improved/bugfixed version of Alfred Arnold's The Macro Assembler AS
http://john.ccac.rwth-aachen.de:8000/as/
GNU General Public License v2.0
20 stars 2 forks source link

Iterating through macro arguments is horrible #5

Closed Awuwunya closed 3 years ago

Awuwunya commented 3 years ago

This has at least been an issue in older versions of AS. You can't iterate through macro arguments without recursively calling the macro! Although shift will work, it won't remap the actual macro variable names into these new values. This was never a problem in ASM68K and makes programming macros a pain in AS. This is especially the case if not every single macro argument is to be iterated through (you may have the first argument be interpreted before the actual looping portion!)

flamewing commented 3 years ago

This is a pain I know well. But from what I have seen, this is unfixable: when macros are expanded, AS loops through all lines and replaces the values of the parameters as a preprocessing step. When you reach a shift in a rept/while in a macro, it is too late because it already has the value substituted in.

But there may be a way to handle this: for iterations requiring a single argument, you can do something like this:

mymacro macro
    irp argvalue,ALLARGS
      ; code goes here, with argvalue having the value of each parameter
    endm
  endm

Maybe I can add an irpn version that allows you to specify the number (and name) of parameters used up in each step?

Awuwunya commented 3 years ago

There is also a very specific case that I had issues with back when, I am not sure if your solution would work with this: https://github.com/NatsumiFox/AMPS-Sonic-2/blob/master/AMPS/code/68k%20Commands.asm#L798

flamewing commented 3 years ago

Indeed irp does not work for that case; but here is how my proposed irpn addition would handle this macro:

dVoiceReg macro
  ; 2 is the number of parameters used in each iteration
  ; The next 2 parameters are names of these parameters
  ; All others form an array of parameters fed into those
  ; If there are not enough parameters, the parameters
  ; without values get a blank value, like in a macro
  irpn 2,offset,reg,ALLARGS
        move.b   (a4)+,(a5)     ; write value to buffer
        moveq    #reg,d3            ; load register to d3   
        or.b     d2,d3          ; add channel offset to register
        move.b   d3,(a5)+       ; write register to buffer
        if offset>1
            addq.w    #offset-1,a4      ; offset a4 by specific amount
        endif
    endm
  endm
Awuwunya commented 3 years ago

unless I'm mistaken, this would work different to my macro. The first argument is always offset, eveey other argument is reg. offset is only passed in once.

flamewing commented 3 years ago

Oh, you are correct, I misread your macro; that is what happens when you write code on your phone, I guess.

Reading it properly, plain irp would actually work for you:

dVoiceReg macro offset
._x := offset
  shift
  irp reg,ALLARGS
        move.b  (a4)+,(a5)+     ; write value to buffer
        moveq   #reg,d3         ; load register to d3
        or.b    d2,d3           ; add channel offset to register
        move.b  d3,(a5)+        ; write register to buffer
        if ._x>1
            addq.w  #._x-1,a4   ; offset a4 by specific amount
        endif
    endm
  endm

I also fixed a typo in the previous version where I had accidentally deleted the + in (a5)+.

Still, I will keep this open and implement irpn because I actually have uses for it.