Open johnwbyrd opened 8 months ago
@asiekierka wrote:
The LLVM backend does distinguish between the 4510 and 45GS02. However, that mostly means we provide correct assembler support for all 6502 subtypes. The question of what's supported for compilation by the LLVM backend is separate; for example, on 65C02 and its derivatives, we currently compile PHX/PHY/PLX/PLY, INC/DEC A, BRA, indexed indirect JMP, the non-indexed indirect addressing mode, and STZ. We only assemble, for example, TRB and TSB - while there are scenarios where these opcodes could lead to more optimized C code, the compiler is not yet "taught" on how to apply them in practice.
Likewise, we could implement something for the 45GS02 only, but not the 4510. The question is mostly that of the effort required and whether someone will put it in.
It would be great to maintain a definitive list of the use-cases that the compiler has to deal with
Your best option is to get involved with LLVM-MOS development, I'm afraid; the best way to deeply understand how the compiler thinks is to study and work with it at a low level. Note also that other compilers handle things differently (for example, SDCC has its own intermediate representation which predates the popularity of SSA), so things which work well for us might not work so well for others.
@mysterymath wrote:
Do you want this to support C= C65 prototypes with their 4510, or only the MEGA65 and its 45GS02? This has important consequences, because ... I think if there's interest in supporting the prototype, and it doesn't do horrible things to the compiler, and someone wants to do it, it's a good idea. Those three ifs multiply together though to make a probability that seems pretty low to me. I definitely have no special interest in the C65; and only a cursory one for FPGA 6502 derivatives. But I wouldn't want to stand in the way of the enthusiasm of others, excepting the cases those various enthusiasms come into conflict.
I can say I don't remember anyone expressing an interest in supporting the C65 so far.
In the above discussion, there are a lot of use-cases that introduce various challenges/limitations/interactions. They are described diffusely above. It would be great to maintain a definitive list of the use-cases that the compiler has to deal with, so that we can objectively and succinctly assess whether a given proposed solution addresses them all, and how efficiently. This is rough; as long as I've been a compiler engineer, such lists are really hard to come by, and they can usually only be created by domain experts with an absolutely ridiculous amount of experience; everyone else doesn't know how much they don't know. That's hard to come by in this space; I have a ton of compiler/linker experience (relatively speaking), but much less with the various target systems, save a couple. Others are extremely familiar with target systems, but usually lack compiler/linker experience. Lacking this, usually the best you can do is just put stuff out there "in the soup", and let it be broken. When it breaks, it breaks in a specific, tangible way; and that fosters discussion. The right people will eventually complain about it, and then you can go in and fix it.
Honestly the mega65 target is already pretty much in that state; this whole thread is the right people complaining about it. So I'd expect a simple BP management approach to be similar.
In terms of (2) above, we could, for example, add a PHB / PLB instruction pair by using an instruction prefix on one, say, PHX and PLX, to create the ability to efficiently save and restore the BP, without poisoning A, which is the main problem I see with doing, say, TBA / PHA , PLA / TAB to wrap changes to BP, e.g., for calling KERNAL functions. I think most of this is Quality of Life stuff; being able to work around stuff like that in a compiler is table stakes. Were those present, we wouldn't use them right now, just like we don't use any of the other 45GS02 extentions, just for lack of dev time. Accordingly, I don't think slosh in managing BP would compare to not using e.g. stack-relative addressing.
For far jumps and far returns there is already a half-finished mechanism for 32-bit flat address calls. It does introduce some limitations on the memory map, because it works by mapping a 16KB slab at $8000-$BFFF that contains the address, and executing the code there. Combined with the 32-bit ZP pointer instructions, this in principle gives you a means to create a flat 32-bit memory model for the MEGA65. If there was interest in having LLVM-mos support these to allow programs >64KB, I could be fairly easily convinced to finish their implementation. Similarly, getting to the point where the backend would be able to use something like this is a long ways off. I do think we want to support the equivalent of the various x86's near, far, and huge memory models for code and data, but while we've talked off and on about it at length, it's not really at the top of anyone's TODO list. (Except maybe if @asiekierka gets a new computer ;) )
@gardners wrote:
Hello, the sod responsible for the 45GS02 here :) Some key things that come to mind are:
Do you want this to support C= C65 prototypes with their 4510, or only the MEGA65 and its 45GS02? This has important consequences, because ... The 45GS02 is only implemented in FPGA at present, which means that if there are sensible measured tweaks that would be helpful to simplify things, we can absolutely consider those. In the above discussion, there are a lot of use-cases that introduce various challenges/limitations/interactions. They are described diffusely above. It would be great to maintain a definitive list of the use-cases that the compiler has to deal with, so that we can objectively and succinctly assess whether a given proposed solution addresses them all, and how efficiently. Now some thoughts of processor tweaks that I could provide at relatively low cost:
In terms of (2) above, we could, for example, add a PHB / PLB instruction pair by using an instruction prefix on one, say, PHX and PLX, to create the ability to efficiently save and restore the BP, without poisoning A, which is the main problem I see with doing, say, TBA / PHA , PLA / TAB to wrap changes to BP, e.g., for calling KERNAL functions. For far jumps and far returns there is already a half-finished mechanism for 32-bit flat address calls. It does introduce some limitations on the memory map, because it works by mapping a 16KB slab at $8000-$BFFF that contains the address, and executing the code there. Combined with the 32-bit ZP pointer instructions, this in principle gives you a means to create a flat 32-bit memory model for the MEGA65. If there was interest in having LLVM-mos support these to allow programs >64KB, I could be fairly easily convinced to finish their implementation. If finer resolution in BP would be desirable, I might be able to implement this with a prefixed TAB/TBA instruction, or in the alternative a LDB / STB instruction. But I'm more concerned about unexpected consequences of such an approach.