diff options
author | Reuben Thomas <rrt@sc3d.org> | 2009-05-01 15:42:50 -0700 |
---|---|---|
committer | Jack Palevich <jackpal@google.com> | 2009-05-01 15:44:04 -0700 |
commit | 4d480734a6d81439f7a71f432f54aaaa3111d496 (patch) | |
tree | 202bbe9a99d9431ade5484aa44ee0335ff0e6233 | |
parent | 12cc0b259a5f3cb4e7658aec9e2a78943397f02f (diff) | |
download | lcc-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-x | src/arm0.md | 948 |
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, + + } +}; |