summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorReuben Thomas <rrt@sc3d.org>2009-05-01 15:42:50 -0700
committerJack Palevich <jackpal@google.com>2009-05-01 15:44:04 -0700
commit4d480734a6d81439f7a71f432f54aaaa3111d496 (patch)
tree202bbe9a99d9431ade5484aa44ee0335ff0e6233
parent12cc0b259a5f3cb4e7658aec9e2a78943397f02f (diff)
downloadlcc-4d480734a6d81439f7a71f432f54aaaa3111d496.tar.gz
A RiscOS-specific ARM machine definition file.
From ftp://ftp.cs.princeton.edu/pub/lcc/contrib/lccsrc.zip lccsrc.zip lccbin.zip Source and binary distributions of an lcc 4.0 port to the Acorn under RISC OS. created Mon Mar 23 16:10:39 EST 1998 Reuben Thomas / rrt@sc3d.org
-rwxr-xr-xsrc/arm0.md948
1 files changed, 948 insertions, 0 deletions
diff --git a/src/arm0.md b/src/arm0.md
new file mode 100755
index 0000000..4af07bb
--- /dev/null
+++ b/src/arm0.md
@@ -0,0 +1,948 @@
+%{
+#define INTTMP 0x03f0
+#define INTVAR 0x0300
+#define FLTTMP 0x0e
+#define FLTVAR 0xf0
+
+#define savelist (0xd800) /* fp, ip, lr, pc */
+#define reslist (0xa800) /* fp, sp, pc */
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+#define readsreg(p) \
+ (generic((p)->op)==INDIR && (p)->kids[0]->op==VREG+P)
+#define setsrc(d) ((d) && (d)->x.regnode && \
+ (d)->x.regnode->set == src->x.regnode->set && \
+ (d)->x.regnode->mask&src->x.regnode->mask)
+
+#define relink(a, b) ((b)->x.prev = (a), (a)->x.next = (b))
+
+#include "c.h"
+#define NODEPTR_TYPE Node
+#define OP_LABEL(p) ((p)->op)
+#define LEFT_CHILD(p) ((p)->kids[0])
+#define RIGHT_CHILD(p) ((p)->kids[1])
+#define STATE_LABEL(p) ((p)->x.state)
+static void address(Symbol, Symbol, int);
+static void blkfetch(int, int, int, int);
+static void blkloop(int, int, int, int, int, int[]);
+static void blkstore(int, int, int, int);
+static void defaddress(Symbol);
+static void defconst(int, int, Value);
+static void defstring(int, char *);
+static void defsymbol(Symbol);
+static void doarg(Node);
+static void emit2(Node);
+static void export(Symbol);
+static void clobber(Node);
+static void function(Symbol, Symbol [], Symbol [], int);
+static void global(Symbol);
+static void import(Symbol);
+static void local(Symbol);
+static void progbeg(int, char **);
+static void progend(void);
+static void segment(int);
+static void space(int);
+static void target(Node);
+static int imm(Node);
+static int imm_const(unsigned);
+static int bitcount(unsigned);
+static void arm_blkcopy(int, int, int, int, int);
+static void arm_mov(int, int);
+static void arm_add(int, int, int);
+static char *reglist(unsigned);
+
+static Symbol ireg[32], freg[32];
+static Symbol iregw, fregw;
+static int cseg;
+static int sizeisave;
+static int bigargs;
+%}
+%start stmt
+%term CNSTF4=4113 CNSTF8=8209
+%term CNSTI1=1045 CNSTI2=2069 CNSTI4=4117
+%term CNSTP4=4119
+%term CNSTU1=1046 CNSTU2=2070 CNSTU4=4118
+%term ARGB=41
+%term ARGF4=4129 ARGF8=8225
+%term ARGI4=4133
+%term ARGP4=4135
+%term ARGU4=4134
+%term ASGNB=57
+%term ASGNF4=4145 ASGNF8=8241
+%term ASGNI1=1077 ASGNI2=2101 ASGNI4=4149
+%term ASGNP4=4151
+%term ASGNU1=1078 ASGNU2=2102 ASGNU4=4150
+%term INDIRB=73
+%term INDIRF4=4161 INDIRF8=8257
+%term INDIRI1=1093 INDIRI2=2117 INDIRI4=4165
+%term INDIRP4=4167
+%term INDIRU1=1094 INDIRU2=2118 INDIRU4=4166
+%term CVFF4=4209 CVFF8=8305
+%term CVFI4=4213
+%term CVIF4=4225 CVIF8=8321
+%term CVII1=1157 CVII2=2181 CVII4=4229
+%term CVIU1=1158 CVIU2=2182 CVIU4=4230
+%term CVPU4=4246
+%term CVUI1=1205 CVUI2=2229 CVUI4=4277
+%term CVUP4=4279
+%term CVUU1=1206 CVUU2=2230 CVUU4=4278
+%term NEGF4=4289 NEGF8=8385
+%term NEGI4=4293
+%term CALLB=217
+%term CALLF4=4305 CALLF8=8401
+%term CALLI4=4309
+%term CALLP4=4311
+%term CALLU4=4310
+%term CALLV=216
+%term RETF4=4337 RETF8=8433
+%term RETI4=4341
+%term RETP4=4343
+%term RETU4=4342
+%term RETV=248
+%term ADDRGP4=4359
+%term ADDRFP4=4375
+%term ADDRLP4=4391
+%term ADDF4=4401 ADDF8=8497
+%term ADDI4=4405
+%term ADDP4=4407
+%term ADDU4=4406
+%term SUBF4=4417 SUBF8=8513
+%term SUBI4=4421
+%term SUBP4=4423
+%term SUBU4=4422
+%term LSHI4=4437
+%term LSHU4=4438
+%term MODI4=4453
+%term MODU4=4454
+%term RSHI4=4469
+%term RSHU4=4470
+%term BANDI4=4485
+%term BANDU4=4486
+%term BCOMI4=4501
+%term BCOMU4=4502
+%term BORI4=4517
+%term BORU4=4518
+%term BXORI4=4533
+%term BXORU4=4534
+%term DIVF4=4545 DIVF8=8641
+%term DIVI4=4549
+%term DIVU4=4550
+%term MULF4=4561 MULF8=8657
+%term MULI4=4565
+%term MULU4=4566
+%term EQF4=4577 EQF8=8673
+%term EQI4=4581
+%term EQU4=4582
+%term GEF4=4593 GEF8=8689
+%term GEI4=4597
+%term GEU4=4598
+%term GTF4=4609 GTF8=8705
+%term GTI4=4613
+%term GTU4=4614
+%term LEF4=4625 LEF8=8721
+%term LEI4=4629
+%term LEU4=4630
+%term LTF4=4641 LTF8=8737
+%term LTI4=4645
+%term LTU4=4646
+%term NEF4=4657 NEF8=8753
+%term NEI4=4661
+%term NEU4=4662
+%term JUMPV=584
+%term LABELV=600
+%term LOADB=233
+%term LOADF4=4321
+%term LOADF8=8417
+%term LOADI1=1253
+%term LOADI2=2277
+%term LOADI4=4325
+%term LOADP4=4327
+%term LOADU1=1254
+%term LOADU2=2278
+%term LOADU4=4326
+%term VREGP=711
+%%
+stmt: reg ""
+
+reg: INDIRI1(VREGP) "# read register\n"
+reg: INDIRU1(VREGP) "# read register\n"
+
+reg: INDIRI2(VREGP) "# read register\n"
+reg: INDIRU2(VREGP) "# read register\n"
+
+reg: INDIRF4(VREGP) "# read register\n"
+reg: INDIRI4(VREGP) "# read register\n"
+reg: INDIRP4(VREGP) "# read register\n"
+reg: INDIRU4(VREGP) "# read register\n"
+
+reg: INDIRF8(VREGP) "# read register\n"
+
+stmt: ASGNI1(VREGP,reg) "# write register\n"
+stmt: ASGNU1(VREGP,reg) "# write register\n"
+
+stmt: ASGNI2(VREGP,reg) "# write register\n"
+stmt: ASGNU2(VREGP,reg) "# write register\n"
+
+stmt: ASGNF4(VREGP,reg) "# write register\n"
+stmt: ASGNI4(VREGP,reg) "# write register\n"
+stmt: ASGNP4(VREGP,reg) "# write register\n"
+stmt: ASGNU4(VREGP,reg) "# write register\n"
+
+stmt: ASGNF8(VREGP,reg) "# write register\n"
+
+con: CNSTI1 "%a"
+con: CNSTU1 "%a"
+
+con: CNSTI2 "%a"
+con: CNSTU2 "%a"
+
+con: CNSTI4 "%a"
+con: CNSTU4 "%a"
+con: CNSTP4 "%a"
+
+reg: con "# arbitrary constant\n" 2
+reg: ADDRGP4 "\tldr\t%c, [pc, #0]\n\tmov\tpc, pc\n\tdcd\t%a\n" 2
+reg: ADDRFP4 "# arbitrary offset\n" 2
+reg: ADDRLP4 "# arbitrary offset\n" 2
+
+rc: reg "%0"
+rc: CNSTI1 " #%a"
+rc: CNSTU1 " #%a"
+rc: CNSTI2 " #%a" imm(a)
+rc: CNSTU2 " #%a" imm(a)
+rc: CNSTI4 " #%a" imm(a)
+rc: CNSTU4 " #%a" imm(a)
+rc: CNSTP4 " #%a" imm(a)
+rc5: CNSTI1 " #%a" range(a,1,32)
+rc5: CNSTU1 " #%a" range(a,1,32)
+rc5: CNSTI2 " #%a" range(a,1,32)
+rc5: CNSTU2 " #%a" range(a,1,32)
+rc5: CNSTI4 " #%a" range(a,1,32)
+rc5: CNSTU4 " #%a" range(a,1,32)
+rc5: reg "%0"
+rc: LSHI4(reg,rc5) "%0, asl %1"
+rc: LSHU4(reg,rc5) "%0, lsl %1"
+rc: RSHI4(reg,rc5) "%0, asr %1"
+rc: RSHU4(reg,rc5) "%0, lsr %1"
+
+bra: ADDRGP4 "%a"
+bra: con "%0"
+
+reg: CVII4(reg) "\tmov\t%c, %0, lsl#8*(4-%a)\n\tmov\t%c, %c, asr#8*(4-%a)\n" 1
+reg: CVII4(INDIRI1(reg)) "\tldrb\t%c, [%0, #0]\n\tmov\t%c, %c, lsl#24\n\tmov\t%c, %c, asr#24\n" 2
+reg: CVII4(INDIRI2(reg)) "\tldrb\tip, [%0, #1]\n\tldrb\t%c, [%0, #0]\n\tadd\t%c, %c, ip, lsl#8\n\tmov\t%c, %c, lsl#16\n\tmov\t%c, %c, asr#16\n" 8
+reg: CVUI4(reg) "\tand\t%c, %0, #&ff\n" (a->syms[0]->u.c.v.i == 1 ? 1 : LBURG_MAX)
+reg: CVUI4(reg) "\tand\t%c, %0, #&ff\n\tand\t%c, %0, #&ff00\n" 2
+reg: CVUI4(INDIRU1(reg)) "\tldrb\t%c, [%0, #0]\n" 2
+reg: CVUI4(INDIRU2(reg)) "\tldrb\tip, [%0, #1]\n\tldrb\t%c, [%0, #0]\n\tadd\t%c, %c, ip, lsl#8\n" 6
+reg: CVUU4(reg) "\tand\t%c, %0, #&ff\n" (a->syms[0]->u.c.v.i == 1 ? 1 : LBURG_MAX)
+reg: CVUU4(reg) "\tand\t%c, %0, #&ff\n\tand\t%c, %0, #&ff00\n" 2
+reg: CVUU4(INDIRU1(reg)) "\tldrb\t%c, [%0, #0]\n" 2
+reg: CVUU4(INDIRU2(reg)) "\tldrb\tip, [%0, #1]\n\tldrb\t%c, [%0, #0]\n\tadd\t%c, %c, ip, lsl#8\n" 6
+
+reg: CVFF4(reg) "%0" notarget(a)
+reg: CVFF4(reg) "\tmvfs\t%c, %0\n" move(a)
+reg: CVFF8(reg) "%0" notarget(a)
+reg: CVFF8(reg) "\tmvfd\t%c, %0\n" move(a)
+
+reg: CVFI4(reg) "\tfix\t%c, %0\n" 1
+reg: CVIF4(reg) "\tflts\t%c, %0\n" 1
+reg: CVIF8(reg) "\tfltd\t%c, %0\n" 1
+
+reg: INDIRI1(reg) "\tldrb\t%c, [%0, #0]\n\tmov\t%c, %c, lsl#24\n\tmov\t%c, %c, asr#24\n" 4
+reg: INDIRU1(reg) "\tldrb\t%c, [%0, #0]\n" 2
+reg: INDIRI2(reg) "\tldrb\tip, [%0, #1]\n\tldrb\t%c, [%0, #0]\n\tadd\t%c, %c, ip, lsl#8\n\tmov\t%c, %c, lsl#16\n\tmov\t%c, %c, asr#16\n" 8
+reg: INDIRU2(reg) "\tldrb\tip, [%0, #1]\n\tldrb\t%c, [%0, #0]\n\tadd\t%c, %c, ip, lsl#8\n" 6
+reg: INDIRI4(reg) "\tldr\t%c, [%0, #0]\n" 2
+reg: INDIRU4(reg) "\tldr\t%c, [%0, #0]\n" 2
+reg: INDIRP4(reg) "\tldr\t%c, [%0, #0]\n" 2
+reg: INDIRF4(reg) "\tldfs\t%c, [%0, #0]\n" 2
+reg: INDIRF8(reg) "\tldfd\t%c, [%0, #0]\n" 2
+
+stmt: ASGNI1(reg,reg) "\tstrb\t%1, [%0, #0]\n" 2
+stmt: ASGNU1(reg,reg) "\tstrb\t%1, [%0, #0]\n" 2
+stmt: ASGNI2(reg,reg) "\tstrb\t%1, [%0, #0]\n\tmov\tip, %1, lsr#8\n\tstrb\tip, [%0, #1]\n" 5
+stmt: ASGNU2(reg,reg) "\tstrb\t%1, [%0, #0]\n\tmov\tip, %1, lsr#8\n\tstrb\tip, [%0, #1]\n" 5
+stmt: ASGNI4(reg,reg) "\tstr\t%1, [%0, #0]\n" 2
+stmt: ASGNU4(reg,reg) "\tstr\t%1, [%0, #0]\n" 2
+stmt: ASGNP4(reg,reg) "\tstr\t%1, [%0, #0]\n" 2
+stmt: ASGNF4(reg,reg) "\tstfs\t%1, [%0, #0]\n" 2
+stmt: ASGNF8(reg,reg) "\tstfd\t%1, [%0, #0]\n" 2
+stmt: ASGNB(reg,INDIRB(reg)) "# asgnb %0 %1\n" 3
+
+reg: LOADI1(reg) "\tmov\t%c, %0\n" move(a)
+reg: LOADU1(reg) "\tmov\t%c, %0\n" move(a)
+reg: LOADI2(reg) "\tmov\t%c, %0\n" move(a)
+reg: LOADU2(reg) "\tmov\t%c, %0\n" move(a)
+reg: LOADI4(reg) "\tmov\t%c, %0\n" move(a)
+reg: LOADP4(reg) "\tmov\t%c, %0\n" move(a)
+reg: LOADU4(reg) "\tmov\t%c, %0\n" move(a)
+reg: LOADF4(reg) "\tmvfs\t%c, %0\n" move(a)
+reg: LOADF8(reg) "\tmvfd\t%c, %0\n" move(a)
+
+reg: NEGI4(reg) "\trsb\t%c, %0, #0\n" 1
+reg: NEGF4(reg) "\tmnfs\t%c, %0\n" 1
+reg: NEGF8(reg) "\tmnfd\t%c, %0\n" 1
+
+reg: BCOMI4(rc) "\tmvn\t%c, %0\n" 1
+reg: BCOMU4(rc) "\tmvn\t%c, %0\n" 1
+reg: BANDI4(reg,rc) "\tand\t%c, %0, %1\n" 1
+reg: BANDU4(reg,rc) "\tand\t%c, %0, %1\n" 1
+reg: BORI4(reg,rc) "\torr\t%c, %0, %1\n" 1
+reg: BORU4(reg,rc) "\torr\t%c, %0, %1\n" 1
+reg: BXORI4(reg,rc) "\teor\t%c, %0, %1\n" 1
+reg: BXORU4(reg,rc) "\teor\t%c, %0, %1\n" 1
+
+reg: LSHI4(reg,rc) "\tmov\t%c, %0, asl %1\n" 1
+reg: LSHU4(reg,rc) "\tmov\t%c, %0, lsl %1\n" 1
+reg: RSHI4(reg,rc) "\tmov\t%c, %0, asr %1\n" 1
+reg: RSHU4(reg,rc) "\tmov\t%c, %0, lsr %1\n" 1
+
+reg: ADDI4(reg,rc) "\tadd\t%c, %0, %1\n" 1
+reg: ADDP4(reg,rc) "\tadd\t%c, %0, %1\n" 1
+reg: ADDU4(reg,rc) "\tadd\t%c, %0, %1\n" 1
+reg: ADDF4(reg,reg) "\tadfs\t%c, %0, %1\n" 1
+reg: ADDF8(reg,reg) "\tadfd\t%c, %0, %1\n" 1
+
+reg: SUBI4(reg,rc) "\tsub\t%c, %0, %1\n" 1
+reg: SUBP4(reg,rc) "\tsub\t%c, %0, %1\n" 1
+reg: SUBU4(reg,rc) "\tsub\t%c, %0, %1\n" 1
+reg: SUBF4(reg,reg) "\tsufs\t%c, %0, %1\n" 1
+reg: SUBF8(reg,reg) "\tsufd\t%c, %0, %1\n" 1
+
+reg: MULI4(reg,reg) "# mul\n" 1
+reg: MULU4(reg,reg) "# mul\n" 1
+reg: MULF4(reg,reg) "\tfmls\t%c, %0, %1\n" 1
+reg: MULF8(reg,reg) "\tmufd\t%c, %0, %1\n" 1
+
+reg: DIVI4(reg,reg) "\tbl\t|x$divide|\n" 2
+reg: DIVU4(reg,reg) "\tbl\t|x$udivide|\n" 2
+reg: DIVF4(reg,reg) "\tfdvs\t%c, %0, %1\n" 1
+reg: DIVF8(reg,reg) "\tdvfd\t%c, %0, %1\n" 1
+
+reg: MODI4(reg,reg) "\tbl\t|x$remainder|\n" 1
+reg: MODU4(reg,reg) "\tbl\t|x$uremainder|\n" 1
+
+stmt: LABELV "%a\n"
+
+stmt: JUMPV(bra) "\tb\t%0\n" 1
+stmt: JUMPV(reg) "\tmov\tpc, %0\n" 1
+
+stmt: EQI4(reg,rc) "\tcmp\t%0, %1\n\tbeq\t%a\n" 2
+stmt: EQU4(reg,rc) "\tcmp\t%0, %1\n\tbeq\t%a\n" 2
+stmt: GEI4(reg,rc) "\tcmp\t%0, %1\n\tbge\t%a\n" 2
+stmt: GEU4(reg,rc) "\tcmp\t%0, %1\n\tbhs\t%a\n" 2
+stmt: GTI4(reg,rc) "\tcmp\t%0, %1\n\tbgt\t%a\n" 2
+stmt: GTU4(reg,rc) "\tcmp\t%0, %1\n\tbhi\t%a\n" 2
+stmt: LEI4(reg,rc) "\tcmp\t%0, %1\n\tble\t%a\n" 2
+stmt: LEU4(reg,rc) "\tcmp\t%0, %1\n\tbls\t%a\n" 2
+stmt: LTI4(reg,rc) "\tcmp\t%0, %1\n\tblt\t%a\n" 2
+stmt: LTU4(reg,rc) "\tcmp\t%0, %1\n\tblo\t%a\n" 2
+stmt: NEI4(reg,rc) "\tcmp\t%0, %1\n\tbne\t%a\n" 2
+stmt: NEU4(reg,rc) "\tcmp\t%0, %1\n\tbne\t%a\n" 2
+
+stmt: EQF4(reg,reg) "\tcmf\t%0, %1\n\tbeq\t%a\n" 2
+stmt: EQF8(reg,reg) "\tcmf\t%0, %1\n\tbeq\t%a\n" 2
+stmt: LEF4(reg,reg) "\tcmfe\t%0, %1\n\tble\t%a\n" 2
+stmt: LEF8(reg,reg) "\tcmfe\t%0, %1\n\tble\t%a\n" 2
+stmt: LTF4(reg,reg) "\tcmfe\t%0, %1\n\tblt\t%a\n" 2
+stmt: LTF8(reg,reg) "\tcmfe\t%0, %1\n\tblt\t%a\n" 2
+stmt: GEF4(reg,reg) "\tcmfe\t%0, %1\n\tbge\t%a\n" 2
+stmt: GEF8(reg,reg) "\tcmfe\t%0, %1\n\tbge\t%a\n" 2
+stmt: GTF4(reg,reg) "\tcmfe\t%0, %1\n\tbgt\t%a\n" 2
+stmt: GTF8(reg,reg) "\tcmfe\t%0, %1\n\tbgt\t%a\n" 2
+stmt: NEF4(reg,reg) "\tcmf\t%0, %1\n\tbne\t%a\n" 2
+stmt: NEF8(reg,reg) "\tcmf\t%0, %1\n\tbne\t%a\n" 2
+
+stmt: ARGI4(reg) "# arg\n" 1
+stmt: ARGP4(reg) "# arg\n" 1
+stmt: ARGU4(reg) "# arg\n" 1
+stmt: ARGF4(reg) "# arg\n" 1
+stmt: ARGF8(reg) "# arg\n" 1
+stmt: ARGB(INDIRB(reg)) "# argb %0\n" 1
+
+stmt: CALLV(bra) "\tbl\t%0\n" 1
+reg: CALLI4(bra) "\tbl\t%0\n" 1
+reg: CALLP4(bra) "\tbl\t%0\n" 1
+reg: CALLU4(bra) "\tbl\t%0\n" 1
+reg: CALLF4(bra) "\tbl\t%0\n" 1
+reg: CALLF8(bra) "\tbl\t%0\n" 1
+
+stmt: CALLV(reg) "\tmov\tlr, pc\n\tmov\tpc, %0\n" 2
+reg: CALLI4(reg) "\tmov\tlr, pc\n\tmov\tpc, %0\n" 2
+reg: CALLP4(reg) "\tmov\tlr, pc\n\tmov\tpc, %0\n" 2
+reg: CALLU4(reg) "\tmov\tlr, pc\n\tmov\tpc, %0\n" 2
+reg: CALLF4(reg) "\tmov\tlr, pc\n\tmov\tpc, %0\n" 2
+reg: CALLF8(reg) "\tmov\tlr, pc\n\tmov\tpc, %0\n" 2
+
+stmt: RETV(reg) "# ret\n" 1
+stmt: RETI4(reg) "# ret\n" 1
+stmt: RETP4(reg) "# ret\n" 1
+stmt: RETU4(reg) "# ret\n" 1
+stmt: RETF4(reg) "# ret\n" 1
+stmt: RETF8(reg) "# ret\n" 1
+
+spill: ADDRLP4 "%a+%F"
+stmt: ASGNI1(spill,reg) "\tldr\tip, [pc, #0]\n\tmov\tpc, pc\n\tdcd\t%0\n\tstrb\t%1, [sp, ip]\n"
+stmt: ASGNU1(spill,reg) "\tldr\tip, [pc, #0]\n\tmov\tpc, pc\n\tdcd\t%0\n\tstrb\t%1, [sp, ip]\n"
+stmt: ASGNI2(spill,reg) "\tldr\tip, [pc, #0]\n\tmov\tpc, pc\n\tdcd\t%0\n\tadd\tip, ip, sp\n\tstr\ta1, [sp, #-4]!\n\tstrb\t%1, [ip, #0]\n\tmov\ta1, %1, lsr#8\n\tstrb\ta1, [ip, #1]\n\tldr\ta1, [sp], #4\n"
+stmt: ASGNU2(spill,reg) "\tldr\tip, [pc, #0]\n\tmov\tpc, pc\n\tdcd\t%0\n\tadd\tip, ip, sp\n\tstr\ta1, [sp, #-4]!\n\tstrb\t%1, [ip, #0]\n\tmov\ta1, %1, lsr#8\n\tstrb\ta1, [ip, #1]\n\tldr\ta1, [sp], #4\n"
+stmt: ASGNI4(spill,reg) "\tldr\tip, [pc, #0]\n\tmov\tpc, pc\n\tdcd\t%0\n\tstr\t%1, [sp, ip]\n"
+stmt: ASGNP4(spill,reg) "\tldr\tip, [pc, #0]\n\tmov\tpc, pc\n\tdcd\t%0\n\tstr\t%1, [sp, ip]\n"
+stmt: ASGNU4(spill,reg) "\tldr\tip, [pc, #0]\n\tmov\tpc, pc\n\tdcd\t%0\n\tstr\t%1, [sp, ip]\n"
+stmt: ASGNF4(spill,reg) "\tldr\tip, [pc, #0]\n\tmov\tpc, pc\n\tdcd\t%0\n\tadd\tip, ip, sp\n\tstfs\t%1, [ip, #0]\n"
+stmt: ASGNF8(spill,reg) "\tldr\tip, [pc, #0]\n\tmov\tpc, pc\n\tdcd\t%0\n\tadd\tip, ip, sp\n\tstfd\t%1, [ip, #0]\n"
+%%
+static void progend() {
+ print("\tALIGN\t4\n");
+ print("\tEND\n");
+}
+static void progbeg(argc, argv) int argc; char *argv[]; {
+ int i;
+
+ {
+ union {
+ char c;
+ int i;
+ } u;
+ u.i = 0;
+ u.c = 1;
+ swap = ((int)(u.i == 1)) != ((int)IR->little_endian);
+ }
+ parseflags(argc, argv);
+ for (i = 0; i < 8; i ++)
+ freg[i] = mkreg("f%d", i, 1, FREG);
+ for (i = 0; i < 16; i++) {
+ if (i < 4)
+ ireg[i] = mkreg(stringf("a%d", i + 1), i, 1, IREG);
+ else if (i < 10)
+ ireg[i] = mkreg(stringf("v%d", i - 3), i, 1, IREG);
+ else
+ ireg[i] = mkreg(NULL, i, 1, IREG);
+ }
+ ireg[10]->x.name = "sl";
+ ireg[11]->x.name = "fp";
+ ireg[12]->x.name = "ip";
+ ireg[13]->x.name = "sp";
+ ireg[14]->x.name = "lr";
+ ireg[15]->x.name = "pc";
+ fregw = mkwildcard(freg);
+ iregw = mkwildcard(ireg);
+ tmask[IREG] = INTTMP; tmask[FREG] = FLTTMP;
+ vmask[IREG] = INTVAR; vmask[FREG] = FLTVAR;
+}
+static Symbol rmap(int opk) {
+ switch (optype(opk)) {
+ case I: case U: case P: case B:
+ return iregw;
+ case F:
+ return fregw;
+ default:
+ return 0;
+ }
+}
+static void target(p) Node p; {
+ int n;
+
+ assert(p);
+ switch (specific(p->op)) {
+ case CALL+F:
+ setreg(p, freg[0]); break;
+ case CALL+I: case CALL+U: case CALL+P:
+ setreg(p, ireg[0]); break;
+ case RET+F:
+ rtarget(p, 0, freg[0]); break;
+ case RET+I: case RET+U: case RET+P:
+ rtarget(p, 0, ireg[0]);
+ p->kids[0]->x.registered = 1;
+ break;
+ case ARG+I: case ARG+U: case ARG+P:
+ n = p->x.argno;
+ if (n < 4) {
+ rtarget(p, 0, ireg[n]);
+ setreg(p, ireg[n]);
+ }
+ break;
+ case DIV+I: case DIV+U: case MOD+I: case MOD+U:
+ setreg(p, ireg[0]);
+ rtarget(p, 1, ireg[0]);
+ rtarget(p, 0, ireg[1]);
+ break;
+ }
+}
+static void clobber(p) Node p; {
+ int n;
+
+ assert(p);
+ switch (specific(p->op)) {
+ case CALL+F: case CALL+I: case CALL+U: case CALL+P: case CALL+V:
+ spill(0xf, FREG, p);
+ break;
+ }
+}
+static int imm(p) Node p; {
+ unsigned long v;
+ Symbol s = p->syms[0];
+
+ switch (specific(p->op)) {
+ case CNST+I: v = s->u.c.v.i; break;
+ case CNST+U: v = s->u.c.v.u; break;
+ case CNST+P: if (s->u.c.v.p == 0) return 0;
+ default: return LBURG_MAX;
+ }
+ return imm_const(v);
+}
+static int imm_const(v) unsigned v; {
+ int i;
+
+ for (i = 0; i < 32; i += 2) {
+ v = (v << 2) + (v >> 30);
+ if (v < 0x100) return 0;
+ }
+ return LBURG_MAX;
+}
+static void emit2(p) Node p; {
+ int src, dst, n, tmp;
+
+ switch (specific(p->op)) {
+ case ARG+I: case ARG+U: case ARG+P:
+ n = p->x.argno;
+ if (n >= 4) {
+ src = getregnum(p->x.kids[0]);
+ print("\tstr\t%s, [sp, #%d]\n",
+ ireg[src]->x.name, n * 4 - 16);
+ }
+ break;
+ case ARG+F:
+ n = p->x.argno;
+ src = getregnum(p->x.kids[0]);
+ if (opsize(p->op) == 4) {
+ print("\tstfs\t%s, [sp, #%d]\n",
+ freg[src]->x.name, n * 4 - 16);
+ if (n < 4)
+ print("\tldr\t%s, [sp, #%d]\n",
+ ireg[n]->x.name, n * 4 - 16);
+ } else {
+ print("\tstfd\t%s, [sp, #%d]\n",
+ freg[src]->x.name, n * 4 - 16);
+ if (n < 4)
+ print("\tldr\t%s, [sp, #%d]\n",
+ ireg[n]->x.name, n * 4 - 16);
+ if (n < 3)
+ print("\tldr\t%s, [sp, #%d]\n",
+ ireg[n + 1]->x.name,
+ (n + 1) * 4 - 16);
+ }
+ break;
+ case ARG+B:
+ {
+ int size, offset;
+ n = p->syms[RX]->u.c.v.i;
+ size = roundup(p->syms[0]->u.c.v.i, 4);
+ offset = max(16 - n, 0);
+ if (offset < size)
+ arm_blkcopy(13, n - 16 + offset + 16,
+ getregnum(p->x.kids[0]), offset,
+ size - offset);
+ if (p->x.argno < 4) {
+ tmp = min(p->x.argno + (size - 1) / 4, 3);
+ if (tmp > p->x.argno)
+ print("\tldmia\t%s, {%s-%s}\n",
+ ireg[getregnum(p->x.kids[0])]->x.name,
+ ireg[p->x.argno]->x.name,
+ ireg[tmp]->x.name);
+ else
+ print("\tldr\t%s, [%s, #0]\n",
+ ireg[p->x.argno]->x.name,
+ ireg[getregnum(p->x.kids[0])]->x.name);
+ }
+ }
+ break;
+ case ASGN+B:
+ arm_blkcopy(getregnum(p->x.kids[0]), 0,
+ getregnum(p->x.kids[1]), 0,
+ p->syms[0]->u.c.v.i);
+ break;
+ case CNST+I: case CNST+U: case CNST+P:
+ dst = getregnum(p);
+ arm_mov(dst, p->syms[0]->u.c.v.i);
+ break;
+ case ADDRF+P:
+ arm_add(getregnum(p), 11, 4 - (bigargs ? 0 : sizeisave) +
+ p->syms[0]->x.offset);
+ break;
+ case ADDRL+P:
+ arm_add(getregnum(p), 13, framesize + p->syms[0]->x.offset);
+ break;
+ case MUL+I: case MUL+U:
+ src = getregnum(p->x.kids[0]);
+ n = getregnum(p->x.kids[1]);
+ dst = getregnum(p);
+ if (src == dst && dst == n) {
+ print("\tmov\tip, %s\n", ireg[src]->x.name);
+ src = 12;
+ }
+ if (src == dst) {
+ tmp = src; src = n; n = tmp;
+ }
+ print("\tmul\t%s, %s, %s\n", ireg[dst]->x.name,
+ ireg[src]->x.name, ireg[n]->x.name);
+ break;
+ }
+}
+
+static void arm_mov(dest, con) int dest; int con; {
+ int inv = bitcount(con) > 16, n = 24;
+ unsigned v;
+
+ if (inv) con = ~con;
+ while (n > 0 && (con & (0xc0 << n)) == 0)
+ n -= 2;
+ v = con & (0xff << n);
+ if (inv) {
+ print("\tmvn\t%s, #%d\n", ireg[dest]->x.name, v);
+ con = (~con) - (~v);
+ } else {
+ print("\tmov\t%s, #%d\n", ireg[dest]->x.name, v);
+ con -= v;
+ }
+ arm_add(dest, dest, con);
+}
+static void arm_add(dest, src, con) int dest, src; int con; {
+ int n = 0;
+
+ if (con == 0 && dest == src)
+ return;
+ if (con == 0) {
+ print("\tmov\t%s, %s\n", ireg[dest]->x.name,
+ ireg[src]->x.name);
+ return;
+ }
+ do {
+ for (; (con & 3) == 0; con >>= 2, n += 2);
+ if (!(con & 0x100)) {
+ print("\tadd\t%s, %s, #&%x\n",
+ ireg[dest]->x.name, ireg[src]->x.name,
+ (con & 0xff) << n);
+ con -= con & 0xff;
+ } else {
+ print("\tsub\t%s, %s, #&%x\n",
+ ireg[dest]->x.name, ireg[src]->x.name,
+ (-con & 0xff) << n);
+ con += -con & 0xff;
+ }
+ src = dest;
+ } while (con);
+}
+
+static char *reglist(mask) unsigned mask; {
+ int i, first = 1;
+ static char list[16 * 4 + 1];
+
+ list[0] = '\0';
+ for (i = 0; i < 16; i++) {
+ if (mask & (1<<i)) {
+ if (first)
+ first = 0;
+ else
+ strcat(list, ", ");
+ strcat(list, ireg[i]->x.name);
+ }
+ }
+ return list;
+}
+
+
+static void doarg(Node p) {
+ assert(p && p->syms[0]);
+ p->syms[RX] = intconst(mkactual(4, p->syms[0]->u.c.v.i));
+ p->x.argno = p->syms[RX]->u.c.v.i / 4;
+}
+static void local(Symbol p) {
+ if (askregvar(p, rmap(ttob(p->type))) == 0)
+ mkauto(p);
+}
+static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls)
+{
+ int i, sizefsave, varargs, dumpmask = 0, reg = 0;
+
+ for (i = 0; callee[i]; i++)
+ ;
+ varargs = variadic(f->type)
+ || i > 0 && strcmp(callee[i-1]->name,
+ "__builtin_va_alist") == 0;
+ usedmask[0] = usedmask[1] = 0;
+ freemask[0] = freemask[1] = ~(unsigned)0;
+ offset = maxoffset = maxargoffset = 0;
+ for (i = 0; callee[i]; i++) {
+ Symbol p = callee[i], q = caller[i];
+ int size = roundup(q->type->size, 4);
+ assert(q);
+ if (isfloat(p->type) || reg >= 4) {
+ p->x.offset = q->x.offset = offset;
+ p->x.name = q->x.name = stringd(offset);
+ p->sclass = q->sclass = AUTO;
+ dumpmask |= 0xffff>>(15 - reg);
+ if (p->type->size == 8)
+ dumpmask |= 1<<(reg + 1);
+ }
+ else if (p->addressed || varargs || isstruct(p->type)) {
+ p->x.offset = offset;
+ p->x.name = stringd(offset);
+ p->sclass = q->sclass = AUTO;
+ dumpmask |= 0xffff>>(16 - reg - size / 4);
+ } else {
+ q->type = p->type;
+ p->sclass = q->sclass = REGISTER;
+ if (askregvar(p, rmap(ttob(p->type))))
+ q->x.name = ireg[reg]->x.name;
+ else {
+ p->sclass = q->sclass = AUTO;
+ p->x.offset = offset;
+ p->x.name = stringd(offset);
+ dumpmask |= 0xffff>>(15 - reg);
+ }
+ }
+ offset += size;
+ reg += size / 4;
+ }
+ dumpmask &= 0xf;
+ bigargs = (varargs || reg > 4) ? 1 : 0;
+ assert(!caller[i]);
+ offset = 0;
+ gencode(caller, callee);
+ maxargoffset = max(roundup(maxargoffset, 4) - 16, 0);
+ sizefsave = 12*bitcount(usedmask[FREG] & 0xf0);
+ sizeisave = 16 + 4*bitcount(usedmask[IREG] & 0x3f0) +
+ 4*bitcount(dumpmask);
+ framesize = roundup(sizefsave + sizeisave + maxargoffset + maxoffset,
+ 4);
+ segment(CODE);
+ if (glevel) {
+ print("\tALIGN\t4\n");
+ defstring(strlen(f->x.name) + 1, f->x.name);
+ print("\tALIGN\t4\n");
+ print("\tdcd\t&%x\n", 0xff000000 | ((strlen(f->x.name) + 4) &
+~3));
+ }
+ print("\tALIGN\t4\n");
+ print("%s\n", f->x.name);
+ print("\tmov\tip, sp\n");
+ if (bigargs) {
+ print("\tstmfd\tsp!, {a1-a4}\n");
+ print("\tstmfd\tsp!, {%s}\n",
+ reglist((usedmask[IREG] & 0x3f0) | savelist));
+ } else {
+ print("\tstmfd\tsp!, {%s}\n",
+ reglist(dumpmask | (usedmask[IREG] & 0x3f0)
+ | savelist));
+ }
+ for (i = 7; i >= 4; i--)
+ if (usedmask[FREG] & (1<<i))
+ print("\tstfe\t%s, [sp, #-12]!\n", freg[i]->x.name);
+ print("\tsub\tfp, ip, #%d\n", bigargs ? 20 : 4);
+ if (framesize + 16 > 256) {
+ arm_add(12, 13, -(framesize + 16));
+ print("\tcmp\tip, sl\n");
+ } else
+ print("\tcmp\tsp, sl\n");
+ print("\tbllt\t|x$stack_overflow|\n");
+ if (framesize - sizefsave - sizeisave > 0)
+ arm_add(13, 13, -(framesize - sizefsave - sizeisave));
+ for (i = 0; i < 4 && callee[i]; i++)
+ if (caller[i]->sclass == REGISTER &&
+ callee[i]->sclass == REGISTER &&
+ caller[i]->type == callee[i]->type)
+ print("\tmov\t%s, %s\n", callee[i]->x.name,
+ caller[i]->x.name);
+ i = framesize;
+ framesize -= sizefsave + sizeisave;
+ emitcode();
+ framesize = i;
+ for (i = 4; i <= 7; i++)
+ if (usedmask[FREG] & (1<<i))
+ print("\tldfe\t%s, [fp, #-%d]\n", freg[i]->x.name,
+ sizeisave - 4 * bitcount(dumpmask) +
+ (8 - i) * 12 - 4);
+ print("\tldmea\tfp, {%s}^\n",
+ reglist((usedmask[IREG] & 0x3f0) | reslist));
+}
+static void defconst(int suffix, int size, Value v) {
+ if (suffix == F && size == 4) {
+ float f = v.d;
+ print("\tdcd\t&%x\n", *(unsigned *)&f); return;
+ }
+ else if (suffix == F && size == 8) {
+ double d = v.d;
+ unsigned *p = (unsigned *)&d;
+ print("\tdcd\t&%x, &%x\n", p[swap], p[!swap]);
+ }
+ else if (suffix == P)
+ print("\tdcd\t&%x\n", v.p);
+ else if (size == 1)
+ print("\tdcb\t%d\n", suffix == I ? (signed char)v.i : (unsigned char)v.u);
+ else if (size == 2)
+ print("\tdcw\t%d\n", suffix == I ? (short)v.i : (unsigned short)v.u);
+ else if (size == 4)
+ print("\tdcd\t%d\n", suffix == I ? (int)v.i : (unsigned)v.u);
+}
+static void defaddress(Symbol p) {
+ print("\tdcd\t%s\n", p->x.name);
+}
+static void defstring(int n, char *str) {
+ int mode, oldmode = 0;
+ char *s, c;
+
+ print("\t=\t");
+ for (s = str; s < str + n; s++) {
+ c = (*s) & 0xff;
+ mode = (isprint(c) && c != '\"' && c != '\\') ? 1 : 0;
+ if (oldmode && !mode)
+ print("\",");
+ else if (!oldmode && mode)
+ print("\"");
+ print(mode ? "%c" : "&%x", c);
+ if (!mode && s < str + n - 1)
+ print(",");
+ oldmode = mode;
+ }
+ if (mode)
+ print("\"");
+ print("\n");
+}
+static void export(Symbol p) {
+ print("\tEXPORT\t%s\n", p->x.name);
+}
+static void import(Symbol p) {}
+static void defsymbol(Symbol p) {
+ if (p->scope >= LOCAL && p->sclass == STATIC)
+ p->x.name = stringf("|L..%d|", genlabel(1));
+ else if (p->generated)
+ p->x.name = stringf("|L..%s|", p->name);
+ else
+ assert(p->scope != CONSTANTS || isint(p->type) || isptr(p->type)),
+ p->x.name = p->name;
+}
+static void address(Symbol q, Symbol p, int n) {
+ q->x.offset = p->x.offset + n;
+ if (p->scope == GLOBAL
+ || p->sclass == STATIC || p->sclass == EXTERN)
+ q->x.name = stringf("%s%s%d", p->x.name,
+ n >= 0 ? "+" : "", n);
+ else
+ q->x.name = stringf("%d", q->x.offset);
+}
+static void global(Symbol p) {
+ if (p->u.seg == BSS) {
+ if (p->sclass == STATIC || Aflag >= 2) {
+ if (cseg != BSS)
+ print("\tAREA\t|C$$zidata|, DATA, NOINIT\n");
+ if (p->type->align > 1)
+ print("\tALIGN\t%d\n", p->type->align);
+ print("%s\n\t%%\t%d\n", p->x.name, p->type->size);
+ } else {
+ print("\tAREA\t%s, COMMON, NOINIT\n", p->x.name);
+ if (p->type->align > 1)
+ print("\tALIGN\t%d\n", p->type->align);
+ print("\t%%\t%d\n", p->type->size);
+ }
+ print("\tAREA\t|C$$code|, CODE, READONLY\n");
+ } else {
+ if (p->u.seg == DATA)
+ print("\tAREA\t|C$$data|, DATA\n");
+ if (p->type->align > 1)
+ print("\tALIGN\t%d\n", p->type->align);
+ print("%s\n", p->x.name);
+ }
+}
+static void segment(int n) {
+ if (cseg == n) return;
+ cseg = n;
+ switch (n) {
+ case CODE: case LIT:
+ print("\tAREA\t|C$$code|, CODE, READONLY\n"); break;
+ case BSS: print("\tAREA\t|C$$zidata|, DATA, NOINIT\n"); break;
+ }
+}
+static void space(int n) {
+ if (cseg != BSS)
+ print("\t%%\t%d\n", n);
+}
+static void arm_blkcopy(int dreg, int doffset, int sreg, int soffset, int size)
+{
+ print("\tstmfd\tsp!, {a1-a4}\n");
+ arm_add(0, dreg, doffset);
+ arm_add(1, sreg, soffset);
+ arm_mov(2, size);
+ print("\tbl\tmemcpy\n");
+ print("\tldmfd\tsp!, {a1-a4}\n");
+}
+static void blkloop(int dreg, int doff, int sreg, int soff, int size, int tmps[]) {}
+static void blkfetch(int size, int off, int reg, int tmp) {}
+static void blkstore(int size, int off, int reg, int tmp) {}
+
+static int bitcount(unsigned mask) {
+ unsigned i, n = 0;
+
+ for (i = 1; i; i <<= 1)
+ if (mask&i)
+ n++;
+ return n;
+}
+
+Interface armIR = {
+ 1, 1, 0, /* char */
+ 2, 2, 0, /* short */
+ 4, 4, 0, /* int */
+ 4, 4, 0, /* long */
+ 4, 4, 1, /* float */
+ 8, 4, 1, /* double */
+ 8, 4, 1, /* long double */
+ 4, 4, 0, /* T * */
+ 0, 4, 0, /* struct */
+ 1, /* little_endian */
+ 1, /* mulops_calls */
+ 0, /* wants_callb */
+ 1, /* wants_argb */
+ 1, /* left_to_right */
+ 0, /* wants_dag */
+ address,
+ blockbeg,
+ blockend,
+ defaddress,
+ defconst,
+ defstring,
+ defsymbol,
+ emit,
+ export,
+ function,
+ gen,
+ global,
+ import,
+ local,
+ progbeg,
+ progend,
+ segment,
+ space,
+ 0, 0, 0, 0, 0, 0, 0,
+ {
+ 1, /* max_unaligned_load */
+ rmap,
+ blkfetch, blkstore, blkloop,
+ _label,
+ _rule,
+ _nts,
+ _kids,
+ _string,
+ _templates,
+ _isinstruction,
+ _ntname,
+ emit2,
+ doarg,
+ target,
+ clobber,
+
+ }
+};