hlorenzi / customasm

💻 An assembler for custom, user-defined instruction sets! https://hlorenzi.github.io/customasm/web/
Apache License 2.0
704 stars 55 forks source link

Allow aliases for token substitution #200

Open EnderShadow opened 7 months ago

EnderShadow commented 7 months ago

I have CPU definition, but for various purposes I want to alias one thing to another. For example, something like this.

subruledef register
{
    %r{num: u8} => num
}

#alias reg_a = %r184

This would allow reg_a to be used anywhere a register would be used. Alternatively, being able to extend an existing subruledef would work as well.

hlorenzi commented 7 months ago

Could you give some syntax examples on the usage of reg_a? Is it to be used in a rule declaration, or among your user code?

EnderShadow commented 7 months ago

The intent was that it would be used in user code. My main use case is that I'm using customasm for writing microcode for a general microcode engine. For specific architectures that use it, I want to name some of the registers so that I don't need to remember which microarchitectural register maps to which ISA register. I have a few examples here.

https://github.com/EnderShadow/microcode-engine/blob/main/overture.asm https://github.com/EnderShadow/microcode-engine/blob/main/etca_10001E0FF_17_9.asm

In the same repo, I currently get around by using a script to parse #alias lines and do a find-replace in the file before running it through customasm, but I'm not sure how scalable an approach like that is in practice.

MineRobber9000 commented 7 months ago

Why not just:

#subruledef register
{
    %r{num: u8} => num
    reg_a => 184`8
}
EnderShadow commented 7 months ago

The reason why I can't do that is because the the microcode definition defines everything that's specific to the microcode engine and nothing more. Implementations of architectures using the microcode engine need registers for specific purposes and duplicating the microcode engine's definition file is not what I want to do. If there was a way to define multiple subrules with the same name and have them get merged, that would be a solution as well.

hlorenzi commented 6 months ago

How about something like:

#const REG_A_VALUE = 184`8

#subruledef register
{
    %r{num: u8} => num
    reg_a => REG_A_VALUE
}

You can easily redefine constants via a few methods:

EnderShadow commented 6 months ago

That's not a workable solution. As per the linked examples, there architectures using the core source file may not share names of registers and I don't want to pollute the shared definition file with registers that at best will not be used and at worst cause subtle bugs through accidental use of the wrong register.

hlorenzi commented 6 months ago

I see. To work around this on the current version, maybe you could declare your #subruledefs conditionally instead? Using one of the suggestions from my previous post. For example, declare one #subruledef per architecture in separate files, and include them conditionally through the command-line.

Though, since right now you can't merge rule blocks under a single name, you'd have to duplicate the common parts. Merging would indeed be a nice feature to have in the future as well.

MineRobber9000 commented 6 months ago

How about:

#subruledef register_direct
{
    r{num: u8} => num
    ; the other direct register definitions
}
#subruledef register
{
    {r: register_direct} => r
    {r: register_alias} => r
}
; go on using `register` in your other ruledefs

Then, in your architecture file:

#subruledef register_alias
{
    reg_a => 184`8
}
#include "common.asm"