theandrew168 / bronzebeard

Minimal assembler and ecosystem for bare-metal RISC-V development
https://bronzebeard.readthedocs.io
MIT License
41 stars 10 forks source link

Add support for writing basic macros #16

Open aw opened 2 years ago

aw commented 2 years ago

Hi @theandrew168 ,

Would it be possible to add support for writing basic macros in the assembly programs? I wanted to see how derzforth would change in size if I inlined all the j next instructions.

For the moment my hack in derzforth.asm is to replace <4 spaces>j next with include next.asm, which contains:

# standard forth routine: next "macro"
    lw W, 0(IP)     # W <- [IP]
    addi IP, IP, 4  # IP += 4
    lw t0, 0(W)     # t0 <- [W]
    jr t0

The binary size increased by exactly 200 bytes, which I think is worth it for the performance gain.

Either way, I think it would be interesting to have a real macro syntax or something similar to what GAS and NASM provide... doesn't have to be as complex/powerful though. What do you think?

theandrew168 commented 2 years ago

I've thought a macro system for quite awhile. It'd definitely be a nice feature to have! The main limitation are semantics and implementation: how exactly does it work and how do I accomplish it given the existing architecture?

The primitive expression evaluation in the assembler defers to python's builtin eval function. Maybe python could be further utilized for macros somehow? A macro could be written as a simply python function that takes a few args and generates assembler Items? But I'd like macros to resemble regular assembler syntax, not python. Part of me has always been curious about writing an S-expression based assembler...

theandrew168 commented 2 years ago

I do want to implement some sort of simple macro system. Do you have any thoughts / ideas on what the syntax could look like for defining and using macros?

aw commented 2 years ago

My experience with Assembly macros is limited, but I think a basic syntax similar to this would be a good start:

macro mycode addr size
  li t0, %addr
  lw a0, 0(t0)
  addi a0, a0, %size
endmacro

In GNU as, they use .macro and .endm and variables are prefixed with slash: \var.

I guess what you need is a way to detect a start/end keyword for the macro, and a way to identify variables within the macro itself. Once that code is pre-processed into actual Assembly, then you can just append it where the macro is used:

mycode 0x2000, 16

would end up appending:

  li t0, 0x2000
  lw a0, 0(t0)
  addi a0, a0, 16

... something like that 🤣

efficacy commented 1 year ago

Would it be possible to use separate, stand-alone, preprocessor as a make step before assembly? There are plenty available although I haven't checked which ones preserve lines and indentation properly. Even if finding something suitable is difficult, it should be a relatively straight-forward task to write one if it doesn't have to integrate with the internals of bronzebeard.

theandrew168 commented 1 year ago

That's possible! Do you know of any high-quality, python-based preprocessors? Pulling something in off the shelf could be a nice path to success. I could write something simple myself but I'd like to avoid reinventing the wheel if possible.

Using a non-python, standalone preprocessor sounds less ideal since it'd require an implicit dependency on external programs: something that bronzebeard tries to avoid.

efficacy commented 1 year ago

I'd like to avoid reinventing the wheel if possible.

Says the person who wrote their own assembler and forth interpreter :roll_eyes: but I get the point. I'll have a look around, too.

theandrew168 commented 1 year ago

Hah, yeah good point. I suppose it's more about being picky about wheels? Either way, if there is solid option that exists, I'd consider integration.