BartmanAbyss / vscode-amiga-debug

One-stop Visual Studio Code Extension to compile, debug and profile Amiga C/C++ programs compiled by the bundled gcc 12.2 with the bundled WinUAE/FS-UAE.
GNU General Public License v3.0
318 stars 40 forks source link

Question about inline asm register usage. #16

Closed rjobling closed 4 years ago

rjobling commented 4 years ago

I'm adding inline asm so I can write some fast code without giving up on the convenience of C/C++. However if I use too many registers, such as 8 data register then I run into problems. I haven't taken the time to examine what exactly is going on but was wondering if you know where I can find more information about how the compiler uses the registers. Seems likely there is a stack frame pointer in a6 but from the problems I'm getting it seems like one of the data registers is also in use. I'll look more closely if you've no idea what I'm doing wrong.

BartmanAbyss commented 4 years ago

Yeah, I also had that problem when trying to implement a fast memcpy routine that used all registers. My workaround was just to store all used registers to the stack at the beginning of the asm and restoring them afterwards. Then you don't need to tell the compiler about those registers. The included version of gcc uses a5 as a frame pointer. Also check this example: https://github.com/BartmanAbyss/vscode-amiga-debug/blob/7fdd369501706c07adc599b9a9ab6a6d347119a9/template/main.c#L162-L176

rjobling commented 4 years ago

Thanks for the quick reply.

I did try pushing all the data registers and popping after but it was still locking up. I don't have any interrupt handler running so not sure what is going on.

In the example code you posted what does the "rf" constraint mean, when I looked it up it seemed to suggest "register" and "float", which seems an odd choice.

rjobling commented 4 years ago

I was able to fix my bug by moving one of the parameters from an input to an input/output. It doesn't seem like that should be necessary since I don't modify its value. But for whatever reason gcc was reusing that register inside the asm code. Maybe it's a bug in gcc or more likely it's something subtle with the operands/clobbers I specified that I don't fully understand.

rjobling commented 4 years ago

Actually I eventually figured out that if I correctly use an early-clobber the problem is fixed without any hackery. My code now happily used d0-d7/a0-a6.

BartmanAbyss commented 4 years ago

Nice! How exactly did you do that? Would be good to know.

BartmanAbyss commented 4 years ago

In the example code you posted what does the "rf" constraint mean, when I looked it up it seemed to suggest "register" and "float", which seems an odd choice.

I'm not sure, I copied that from the amiga includes. I think it's "register force" to force it to use a specific register (in that case a0, etc.)

rjobling commented 4 years ago

I've added a code snippet so you can see what I've got, should be here: https://github.com/rjobling/snippets/blob/e5f43b25e31273fbf69ac551194670e937dcaeb9/earlyclobbers.cpp

The code is a vector rotation function where I've tried to keep as much as possible in registers. As you can hopefully see, I'm listing 8 data registers and 7 address registers. But the compiler will allocate those as it sees fit, it only has 6 address registers to play with as a7 and a5 are reserved for the stack and frame (I think).

Since the compiler has to reuse at least one address register I had to mark the scratch address registers as early clobbers, otherwise it was overwriting the "rot" register before I was finished using it.

I'm still learning this stuff, but it does seem that if you get it right then letting the compiler allocate registers frees you from some of that hassle.

BartmanAbyss commented 4 years ago

Great. Thanks.