via llvm-dev
2019-Jul-09 18:29 UTC
[llvm-dev] Having trouble getting started on writing a WDC 65816 backend
I asked about this in IRC ~2.5 hours ago: <srnb> I'm trying to write an LLVM backend for the WDC 65816 (for usage in compiling SNES code) but I have very little experience with how C++ works and LLVM's CMakeLists. I'm trying to follow the guide but I don't know how to check if the project builds after my changes or how to test a small amount of C with it once I get it working. <srnb> I've run into some things where I'm questioning if it makes sense for an LLVM backend: <srnb> - How do I handle ROM banks? ( https://stackoverflow.com/questions/56925635/equivalent-of-org-in-llvm-ir ) <srnb> - Does it make sense to use `ENVIRONMENT` (where it's usually either `gnu` or `musl`) for the different ROM types? (`lorom`, `hirom`, `sa1`, etc) <srnb> - The assembler I want to target is one that's not very known outside of the Super Mario World RomHacking community. Who's job is it to assemble what LLVM outputs, and how? It got buried under join/leave messages and build alerts. I'm using CLion on Windows with Msys2-mingw64 (my VoidLinux-musl installation isn't that great for development yet). Importing the project works correctly, but I don't know how to build the project or test the project or test my backend. This is my first time ever using a mailing list, apologies if I get something wrong. Sent via Migadu.com, world's easiest email hosting
Tim Northover via llvm-dev
2019-Jul-10 20:29 UTC
[llvm-dev] Having trouble getting started on writing a WDC 65816 backend
Hi, On Wed, 10 Jul 2019 at 20:44, via llvm-dev <llvm-dev at lists.llvm.org> wrote:> <srnb> I'm trying to write an LLVM backend for the WDC 65816 (for usage in compiling SNES code) but I have very little experience with how C++ works and LLVM's CMakeLists. I'm trying to follow the guide but I don't know how to check if the project builds after my changes or how to test a small amount of C with it once I get it working.You might try searching the list for past discussions of 6502 since many of the problems will be similar. As I recall the big one is that LLVM isn't well adapted to instruction sets without fungible registers. One idea is to use some of bank 0 as a source of registers, maybe with a custom pass to promote things to real registers where possible after the fact. The other main one was to design a virtual machine runtime on top of the basic instructions with a more friendly instruction set; LLVM would then generate VM opcodes, and you'd always link in the runtime to actually execute it. I'm afraid I haven't thought enough to decide which approach I'd take (or why) if it was me.> <srnb> - How do I handle ROM banks? ( https://stackoverflow.com/questions/56925635/equivalent-of-org-in-llvm-ir ) > <srnb> - Does it make sense to use `ENVIRONMENT` (where it's usually either `gnu` or `musl`) for the different ROM types? (`lorom`, `hirom`, `sa1`, etc)I think it could be made to work, but the physical start address would normally be handled by a linker. If you're trying to avoid a linker entirely, many hacks are possible. The wider issue of different ROM banks (how pointers must be defined and accessed so that all possible values are in range) looks more like a CodeModel on other targets to me (with existing values of tiny, small, medium, ... but you could make your own if you don't like those).> <srnb> - The assembler I want to target is one that's not very known outside of the Super Mario World RomHacking community. Who's job is it to assemble what LLVM outputs, and how?Most LLVM targets implement an assembler too so that they don't have to call out to an external program. But you don't have to do that, and if you want to start out using an external assembler then at some point you'll probably want to teach Clang how to invoke it properly (the alternative is telling your users they have to add lines to their build system to do it, which is also fine to begin with). I believe the key code is in clang/lib/Driver/ToolChains, for copy/paste purposes.> It got buried under join/leave messages and build alerts.A perennial pain in the neck. I have join/leave suppressed and even put llvmbb on ignore most of the time. It's astonishing how much more readable IRC becomes.> I'm using CLion on Windows with Msys2-mingw64 (my VoidLinux-musl installation isn't that great for development yet). Importing the project works correctly, but I don't know how to build the project or test the project or test my backend.That I can't help you with I'm afraid. I get the impression most of us here use CMake/ninja directly to do builds (see https://llvm.org/docs/GettingStarted.html), and maybe an IDE to edit the source files. I certainly do. Cheers. Tim.
via llvm-dev
2019-Jul-12 16:14 UTC
[llvm-dev] Having trouble getting started on writing a WDC 65816 backend
Sorry about the "Sent by Migadu" message at the bottom of these emails. I looked through settings but I don't know how to get rid of it. July 10, 2019 1:29 PM, "Tim Northover" <t.p.northover at gmail.com> wrote:> As I recall the big one is that LLVM isn't well adapted to instruction > sets without fungible registers.What does this mean exactly? How does the WDC 65816 not have fungible registers, while other processors do?> One idea is to use some of bank 0 as > a source of registers, maybe with a custom pass to promote things to > real registers where possible after the fact.How would I end up doing this? Do you mean bank 0 of the actual SNES ROM?>> <srnb> - How do I handle ROM banks? ( >> https://stackoverflow.com/questions/56925635/equivalent-of-org-in-llvm-ir ) >> <srnb> - Does it make sense to use `ENVIRONMENT` (where it's usually either `gnu` or `musl`) for >> the different ROM types? (`lorom`, `hirom`, `sa1`, etc) > > I think it could be made to work, but the physical start address would > normally be handled by a linker. If you're trying to avoid a linker > entirely, many hacks are possible.I wouldn't mind a linker. The big five issues right now are: 1. Code and data cannot be split across a ROM bank 2. Code and data need to be properly addressed by the specifics mentioned in the SO post 3. The bank code should be in can't be specified by the code itself 4. The SNES starts executing instructions at $008000 (bank 0, rom$ 0) 5. Hardware addresses; SRAM, VRAM writing, etc. How would a linker solve these problems though?> The wider issue of different ROM banks (how pointers must be defined > and accessed so that all possible values are in range) looks more like > a CodeModel on other targets to me (with existing values of tiny, > small, medium, ... but you could make your own if you don't like > those).Would it be efficient then to implement a CodeModel for each Environment detailing where code/data and hardware addresses should be?> Most LLVM targets implement an assembler too so that they don't have > to call out to an external program. But you don't have to do that, and > if you want to start out using an external assembler then at some > point you'll probably want to teach Clang how to invoke it properly > (the alternative is telling your users they have to add lines to their > build system to do it, which is also fine to begin with). I believe > the key code is in clang/lib/Driver/ToolChains, for copy/paste > purposes.Does another target have an example of needing an external assembler?>> I'm using CLion on Windows with Msys2-mingw64 (my VoidLinux-musl installation isn't that great for >> development yet). Importing the project works correctly, but I don't know how to build the project >> or test the project or test my backend. > > That I can't help you with I'm afraid. I get the impression most of us > here use CMake/ninja directly to do builds (see > https://llvm.org/docs/GettingStarted.html), and maybe an IDE to edit > the source files. I certainly do.The targets listed in CLion are the same ones that you can call in CMake or Make I'm fairly certain. Sent via Migadu.com, world's easiest email hosting
Tim Northover via llvm-dev
2019-Jul-12 17:21 UTC
[llvm-dev] Having trouble getting started on writing a WDC 65816 backend
On Fri, 12 Jul 2019 at 17:14, <me at s5.pm> wrote:> What does this mean exactly? How does the WDC 65816 not have fungible registers, while other processors do?The targets LLVM supports right now have at lest 8 roughly general purpose registers that LLVM can put values in (most have more) and use for different instructions. Below that, LLVM starts to struggle. I've certainly seen compilation failures when the number is artificially constrained for some reason (certain kinds of inline assembly will do it), but I don't think anyone is really sure of how big the problem is.> > One idea is to use some of bank 0 as > > a source of registers, maybe with a custom pass to promote things to > > real registers where possible after the fact. > > How would I end up doing this? Do you mean bank 0 of the actual SNES ROM?I believe the first 256 bytes of memory are directly accessible from instructions, so part (or all) of that might be usable as pretend registers. Now that I've looked it up the term is zero "page" rather than "bank".> The big five issues right now are: > 1. Code and data cannot be split across a ROM bank > 2. Code and data need to be properly addressed by the specifics mentioned in the SO post > 3. The bank code should be in can't be specified by the code itself > 4. The SNES starts executing instructions at $008000 (bank 0, rom$ 0) > 5. Hardware addresses; SRAM, VRAM writing, etc. > > How would a linker solve these problems though?The linker's job is to lay objects out in memory. That seems to cover 1 and 3-5 pretty directly. 2 sounds like an issue for the compiler.> Would it be efficient then to implement a CodeModel for each Environment detailing where code/data and hardware addresses should be?The CodeModel would determine how far apart things can be, which affects the instructions the compiler must use to access distant objects. The actual final location of objects is still a linker issue.> Does another target have an example of needing an external assembler?I think NVPTX might, but I'm not sure that needing an external assembler is the critical point. Most targets are capable of invoking an external assembler if you tell them to via "clang -no-integrated-as" (usually it's GNU as). To make a target "need" one you just don't bother implementing the assembler bits (MCTargetDesc/XYZMCCodeEmitter.cpp principally). Cheers. Tim.
Bruce Hoult via llvm-dev
2019-Jul-15 20:16 UTC
[llvm-dev] Having trouble getting started on writing a WDC 65816 backend
On Sat, Jul 13, 2019 at 11:19 AM via llvm-dev <llvm-dev at lists.llvm.org> wrote:> July 10, 2019 1:29 PM, "Tim Northover" <t.p.northover at gmail.com> wrote: > > > As I recall the big one is that LLVM isn't well adapted to instruction > > sets without fungible registers. > > What does this mean exactly? How does the WDC 65816 not have fungible registers, while other processors do?That comes directly from the dictionary definition of fungible. You can not substitute one register for another. Take, for example, RISC-V. You have 32 registers that, in the base fixed-length 32 bits long instruction set, are absolutely interchangeable with each other. No instructions use implicit source or destination registers, any register can be used for anything. There is no fixed stack pointer register -- any register can equally well be used as a stack pointer. There is no fixed function return link register -- any register can equally well be used as a link register. The only exception is that reads from register 0 always return 0 and writes to it are discarded. In general, if the compiler needs a register or some purpose it does not matter what the purpose is, the compiler can just grab the next available register and use it, without regard for what other registers are in use or what they are being used for. Compare to 6502. There is a stack pointer that can't be directly accessed, but only used in push and pop and transferred to or from another register. There is a condition code register that can only be accessed implicitly or by pushing or popping it to the stack. Arithmetic such as add/siub/and/or/xor can only be done with the A register. Increment and decrement can only be done with the X and Y registers, not the A register. The (zp,reg) addressing mode can only be used with the X register. The (zp),reg addressing mode can only use the Y register. Yes, the 65C02 and 65816 relaxed some of these things a little, but not all that much.
Soren via llvm-dev
2019-Jul-17 19:42 UTC
[llvm-dev] Having trouble getting started on writing a WDC 65816 backend
July 15, 2019 1:16 PM, "Bruce Hoult" <brucehoult at sifive.com> wrote:> Take, for example, RISC-V. You have 32 registers that, in the base > fixed-length 32 bits long instruction set, are absolutely > interchangeable with each other. No instructions use implicit source > or destination registers, any register can be used for anything. There > is no fixed stack pointer register -- any register can equally well be > used as a stack pointer. There is no fixed function return link > register -- any register can equally well be used as a link register. > The only exception is that reads from register 0 always return 0 and > writes to it are discarded. In general, if the compiler needs a > register or some purpose it does not matter what the purpose is, the > compiler can just grab the next available register and use it, without > regard for what other registers are in use or what they are being used > for. > > Compare to 6502. There is a stack pointer that can't be directly > accessed, but only used in push and pop and transferred to or from > another register. There is a condition code register that can only be > accessed implicitly or by pushing or popping it to the stack. > Arithmetic such as add/siub/and/or/xor can only be done with the A > register. Increment and decrement can only be done with the X and Y > registers, not the A register. The (zp,reg) addressing mode can only > be used with the X register. The (zp),reg addressing mode can only use > the Y register.Is it not the job of the backend to figure out how to use the registers effectively? Or am I deeply misunderstanding how a backend is supposed to transform IR? Sent via Migadu.com, world's easiest email hosting