ACC: Arm code gen improvements ++/--, &, odds and ends
Added C++-style "//..end-of-line" comments, since I kept trying to use them when writing
test programs.
The biggest known missing piece is global variables.
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index fa9a5be..50d90dd 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -412,7 +412,11 @@
virtual void storeEAXToAddressECX(bool isInt) {
fprintf(stderr, "storeEAXToAddressECX(%d);\n", isInt);
- o4(0x0188 + isInt); /* movl %eax/%al, (%ecx) */
+ if (isInt) {
+ o4(0xE5810000); // str r0, [r1]
+ } else {
+ o4(0xE5C10000); // strb r0, [r1]
+ }
}
virtual void loadEAXIndirect(bool isInt) {
@@ -424,50 +428,64 @@
}
virtual void leaEAX(int ea) {
- fprintf(stderr, "[!!! fixme !!!] leaEAX(%d);\n", ea);
- error("Unimplemented");
- if (ea < -4095 || ea > 4095) {
+ fprintf(stderr, "leaEAX(%d);\n", ea);
+ if (ea < -1023 || ea > 1023 || ((ea & 3) != 0)) {
error("Offset out of range: %08x", ea);
}
- o4(0xE59B0000 | (0x1fff & ea)); //ldr r0, [fp,#ea]
+ if (ea < 0) {
+ o4(0xE24B0F00 | (0xff & ((-ea) >> 2))); // sub r0, fp, #ea
+ } else {
+ o4(0xE28B0F00 | (0xff & (ea >> 2))); // add r0, fp, #ea
+ }
+
}
virtual void storeEAX(int ea) {
fprintf(stderr, "storeEAX(%d);\n", ea);
- int fpOffset = ea;
- if (fpOffset < -4095 || fpOffset > 4095) {
+ if (ea < -4095 || ea > 4095) {
error("Offset out of range: %08x", ea);
}
- if (fpOffset < 0) {
- o4(0xE50B0000 | (0xfff & (-fpOffset))); // str r0, [fp,#-ea]
+ if (ea < 0) {
+ o4(0xE50B0000 | (0xfff & (-ea))); // str r0, [fp,#-ea]
} else {
- o4(0xE58B0000 | (0xfff & fpOffset)); // str r0, [fp,#ea]
+ o4(0xE58B0000 | (0xfff & ea)); // str r0, [fp,#ea]
}
}
virtual void loadEAX(int ea) {
fprintf(stderr, "loadEAX(%d);\n", ea);
- int fpOffset = ea;
- if (fpOffset < -4095 || fpOffset > 4095) {
+ if (ea < -4095 || ea > 4095) {
error("Offset out of range: %08x", ea);
}
- if (fpOffset < 0) {
- o4(0xE51B0000 | (0xfff & (-fpOffset))); // ldr r0, [fp,#-ea]
+ if (ea < 0) {
+ o4(0xE51B0000 | (0xfff & (-ea))); // ldr r0, [fp,#-ea]
} else {
- o4(0xE59B0000 | (0xfff & fpOffset)); //ldr r0, [fp,#ea]
+ o4(0xE59B0000 | (0xfff & ea)); // ldr r0, [fp,#ea]
}
}
- virtual void postIncrementOrDecrement(int n, int op) {
- fprintf(stderr, "postIncrementOrDecrement(%d, %d);\n", n, op);
- /* Implement post-increment or post decrement.
+ virtual void postIncrementOrDecrement(int ea, int op) {
+ fprintf(stderr, "postIncrementOrDecrement(%d, %d);\n", ea, op);
+ /* R0 has the original value.
*/
-
- error("Unimplemented");
-#if 0
- gmov(0, n); /* 83 ADD */
- o(decodeOp(op));
-#endif
+ switch (op) {
+ case OP_INCREMENT:
+ o4(0xE2801001); // add r1, r0, #1
+ break;
+ case OP_DECREMENT:
+ o4(0xE2401001); // sub r1, r0, #1
+ break;
+ default:
+ error("unknown opcode: %d", op);
+ }
+ if (ea < -4095 || ea > 4095) {
+ error("Offset out of range: %08x", ea);
+ }
+ if (ea < 0) {
+ o4(0xE50B1000 | (0xfff & (-ea))); // str r1, [fp,#-ea]
+ } else {
+ o4(0xE58B1000 | (0xfff & ea)); // str r1, [fp,#ea]
+ }
}
virtual int beginFunctionCallArguments() {
@@ -505,14 +523,14 @@
virtual void callRelative(int t) {
fprintf(stderr, "callRelative(%d);\n", t);
int abs = t + getPC() + jumpOffset();
- fprintf(stderr, "abs=%d (0x08%x)\n", abs, abs);
+ fprintf(stderr, "abs=%d (0x%08x)\n", abs, abs);
if (t >= - (1 << 25) && t < (1 << 25)) {
o4(0xEB000000 | encodeAddress(t));
} else {
// Long call.
o4(0xE59FC000); // ldr r12, .L1
o4(0xEA000000); // b .L99
- o4(t - 16); // .L1: .word 0
+ o4(t - 12); // .L1: .word 0
o4(0xE08CC00F); // .L99: add r12,pc
o4(0xE12FFF3C); // blx r12
}
@@ -537,7 +555,7 @@
}
virtual int jumpOffset() {
- return 4;
+ return 8;
}
/* output a symbol and patch all calls to it */
@@ -949,6 +967,13 @@
}
inp();
next();
+ } else if ((tok == '/') & (ch == '/')) {
+ inp();
+ while (ch && (ch != '\n')) {
+ inp();
+ }
+ inp();
+ next();
} else {
const char* t = operatorChars;
int opIndex = 0;