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
315 stars 39 forks source link

Unknown register names #26

Closed rjobling closed 4 years ago

rjobling commented 4 years ago

When compiling inline asm I seem to always get a bunch of "unknown register name" warnings.

The sample project does this for the unpacking and player inline asm.

It hasn't been a problem until recently. I now have a few different blocks of inline asm that need to specify the registers to use for some variables because they'll be used with a "movem". I do that the usual way: "register int var asm("d0");" for example. However the compiler is not always enforcing the register specification, I suspect the optimizer is doing something because it works okay with compiling with -Og.

It seems plausible that the problem stems from those compiler warnings. Do you know why those warnings are happening and if they can be fixed correctly?

BartmanAbyss commented 4 years ago

I think these warnings are just from the IntelliSense. Microsoft's IntelliSense only officially supports Intel x86/x64 and ARM. You should probably just wrap your inline assembly in #ifndef __INTELLISENSE__ #endif.

rjobling commented 4 years ago

Okay, well I'm still getting issues with the specified register being ignored, this leads to movem doing the wrong thing. Do you have any idea what might cause that? I'll see if I can come up with an example, but I suspect it only happens when the code starts to get a little bigger than the small examples in the sample.

BartmanAbyss commented 4 years ago

Are you using too many registers? Had some issues with that, then I just stored/restored all registers in inline assembly... Can you post the problematic code?

rjobling commented 4 years ago

If you copy this block of code right at the start of main in the sample and look at the output assembly then you should see what I mean.

short vecbuf[300];
short resultbuf[200];
int numVecs = 100;
short* vecs = vecbuf;
short* results = resultbuf;
for (int i = 0; i < numVecs; i++)
{
    vecs[i * 3 + 0] = i;
    vecs[i * 3 + 1] = i * 2;
    vecs[i * 3 + 2] = i * 3;
}
int tx = 10;
int ty = 11;
int tz = 12;
register short vx asm("d1");    // Need to specify these so the movem is ordered correctly.
register short vy asm("d2");
register short vz asm("d3");
asm volatile(
"       subq.w  #1,%[num]                       \n"
"loop%=:                                        \n"
"       movem.w (%[vecs])+,%[vx]/%[vy]/%[vz]    \n"
"       add.l   %[tx],%[vx]                     \n"
"       add.l   %[ty],%[vy]                     \n"
"       add.l   %[tz],%[vz]                     \n"
"       asr.l   #8,%[vz]                        \n"
"       divs    %[vz],%[vx]                     \n"
"       divs    %[vz],%[vy]                     \n"
"       move.w  %[vx],(%[results])+             \n"
"       move.w  %[vy],(%[results])+             \n"
"       dbra    %[num],loop%=                   \n"
:
[results]   "+a"    (results),  // "result" pointer gets incremented.
[num]       "+d"    (numVecs),  // "num" count gets decremented.
[vecs]      "+a"    (vecs),     // "vecs" pointers gets incremented.
[vx]        "=&d"   (vx),       // "vx, vy, vz" holds current vector.
[vy]        "=&d"   (vy),
[vz]        "=&d"   (vz)
:
[tx]        "d"     (tx),       // "tx, ty, tz" holds the translation.
[ty]        "d"     (ty),
[tz]        "d"     (tz)
:
"cc",
"memory"
);
rjobling commented 4 years ago

One work around is to specify tx/ty/tz as input/outputs. That seems to trick the compiler into doing what is expected, but I have little confidence that such a hack will hold up over time.

BartmanAbyss commented 4 years ago

Hmm.. given that's a rather large loop, maybe the safer route would be to move that as a function call to a .s file?

rjobling commented 4 years ago

I've been persisting with the inline stuff just because I quite like having all the code in the c file and being able to name registers. I know I can work around the problem in several ways, but it seems a shame.

BartmanAbyss commented 4 years ago

I admire your perserverance ;) I'm no inline assembly expert...

rjobling commented 4 years ago

It feels like there's a bug with how gcc understands the registers. Is there some part within your control that specs out the registers for gcc?

BartmanAbyss commented 4 years ago

Not really, the sum of all my GCC patches is about 20 lines

rjobling commented 4 years ago

That's all alien to me. I seem to be able to work around it consistently by promoting inputs so they are input/outputs. This avoids the need to specify some things as early clobbers, which is a confusing at the best of times. Maybe gcc just gets confused when mixing early clobbers with specified registers. The whole early clobber thing seems sketchy. But I don't know where do go to check if something could be done about it.

BartmanAbyss commented 4 years ago

See, I don't even know about early clobbers ^_^