Skip to content

Loading…

SP+Constant #159

Closed
rickbutton opened this Issue · 6 comments

3 participants

@rickbutton

In earlier versions, the backend would just use C, and later I, to do something like [SP + 2]. This commit (5ea9161) seemed to have removed that. SP+Constant in the assembly doesn't work in every emulator I have tried. Is there a reason this was taken out?

@krasin
llvm-dcpu16 member

Hi Rick,

old DCPU16 spec prohibited the use of [SP+2], but now it's allowed: http://0x10c.com/highnerd/dcpu16.txt

--- Values: (5/6 bits) ---------------------------------------------------------
 C | VALUE     | DESCRIPTION
---+-----------+----------------------------------------------------------------
...
 0 |      0x1a | [SP + next word] / PICK n

Not all DCPU16 assemblers/emulators support that now, but they should and likely will.

@a1k0n
llvm-dcpu16 member

I have a patch to force it to use PICK n syntax instead of [SP+0x1234], but it doesn't work on inline assembly for some reason. I'll paste the patch here; let me know if you want a pull request and if so, I can add tests and so forth. But I currently have no idea why inline assembly is not affected.

diff --git a/lib/Target/DCPU16/InstPrinter/DCPU16InstPrinter.cpp b/lib/Target/DCPU16/InstPrinter/DCPU16InstPrinter.cpp
index 3fd1c82..f665083 100644
--- a/lib/Target/DCPU16/InstPrinter/DCPU16InstPrinter.cpp
+++ b/lib/Target/DCPU16/InstPrinter/DCPU16InstPrinter.cpp
@@ -64,6 +64,24 @@ void DCPU16InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo,
   const MCOperand &Base = MI->getOperand(OpNo);
   const MCOperand &Disp = MI->getOperand(OpNo+1);

+  // Special case for PICK n syntax
+  if (Base.getReg() == DCPU16::SP) {
+    if (Disp.isImm()) {
+      if (Disp.getImm() != 0) {
+        O << "PICK 0x";
+        O.write_hex(Disp.getImm() & 0xFFFF);
+      } else {
+        O << "[SP]";
+      }
+    } else {
+      assert(Disp.isExpr() &&
+             "Expected immediate or expression in displacement field");
+      O << "PICK ";
+      O << *Disp.getExpr();
+    }
+    return;
+  }
+
   O << '[';

   if (Disp.isExpr()) {
@krasin
llvm-dcpu16 member

Hi Andy,

thanks for working on this. Generally, the patch looks good (assuming that "PICK n" syntax is better supported by DCPU16 assemblers)

Could you please define which issues do you have with the inline assembly?

@a1k0n
llvm-dcpu16 member

dcpu.ru doesn't support [SP+x] but it does support PICK x. 0x10co.de supports both, but has issues with MLI. I know of no better online tools, so I'm trying to work with what I've got. It also turns out that [SP] is invalid, so PICK 0 is the only way to do it, so my patch is wrong anyhow.

As an example:

volatile int output = sintbl[angle];
asm("mli %0, %1\n"
    "set %0, EX\n" : "+g"(output) : "g"(x) );

can assemble with this patch to

SET    PICK 0x6, [sintbl+C]
SET    C, PICK 0x6
SET    PICK 0x1, B
;APP
mli C, [0x1+SP]
set C, EX
;NO_APP
SET    PICK 0x6, C
SET    C, PICK 0x6

I don't understand how that's possible; where else could that string be generated when expanding inline assembly? (Also what's with the redundant loads and stores)

This is off-topic, but it would be really nice if there were particular register constraints in inline asm, but I didn't see a way to add them. It seems like at an LLVM level, you can constrain to a particular register name with e.g. "{b}" but it's not possible from clang from what I can tell. As it is, you have to do some register gymnastics with HWI to get the args into A and B.

@krasin
llvm-dcpu16 member

From what I can see now, your patch improves the situation with the compatibility between LLVM backend output and the assemblers. I would appreciate you to send a pull request.

Thanks in advance!

@krasin
llvm-dcpu16 member

Also, I would suggest you to run make check before uploading a pull request to update tests if needed.

@krasin krasin closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.