--- /dev/null
+0, COND, 0x00000000, ".EQ",
+0, COND, 0x10000000, ".NE",
+0, COND, 0x20000000, ".CS",
+0, COND, 0x20000000, ".HS",
+0, COND, 0x30000000, ".CC",
+0, COND, 0x30000000, ".LO",
+0, COND, 0x40000000, ".MI",
+0, COND, 0x50000000, ".PL",
+0, COND, 0x60000000, ".VS",
+0, COND, 0x70000000, ".VC",
+0, COND, 0x80000000, ".HI",
+0, COND, 0x90000000, ".LS",
+0, COND, 0xA0000000, ".GE",
+0, COND, 0xB0000000, ".LT",
+0, COND, 0xC0000000, ".GT",
+0, COND, 0xD0000000, ".LE",
+0, COND, 0xE0000000, ".AL",
+0, COND, 0xF0000000, ".NV",
+
+0, LINK, 0x01000000, ".L",
+
+0, BRANCH, 0x0A000000, "BEQ",
+0, BRANCH, 0x1A000000, "BNE",
+0, BRANCH, 0x2A000000, "BCS",
+0, BRANCH, 0x2A000000, "BHS",
+0, BRANCH, 0x3A000000, "BCC",
+0, BRANCH, 0x3A000000, "BLO",
+0, BRANCH, 0x4A000000, "BMI",
+0, BRANCH, 0x5A000000, "BPL",
+0, BRANCH, 0x6A000000, "BVS",
+0, BRANCH, 0x7A000000, "BVC",
+0, BRANCH, 0x8A000000, "BHI",
+0, BRANCH, 0x9A000000, "BLS",
+0, BRANCH, 0xAA000000, "BGE",
+0, BRANCH, 0xBA000000, "BLT",
+0, BRANCH, 0xCA000000, "BGT",
+0, BRANCH, 0xDA000000, "BLE",
+0, BRANCH, 0xEA000000, "BAL",
+0, BRANCH, 0xFA000000, "BNV",
+
+0, DATA1, ADC, "ADC",
+0, DATA1, ADD, "ADD",
+0, DATA1, AND, "AND",
+0, DATA1, BIC, "BIC",
+0, DATA1, EOR, "EOR",
+0, DATA1, ORR, "ORR",
+0, DATA1, RSB, "RSB",
+0, DATA1, RSC, "RSC",
+0, DATA1, SBC, "SBC",
+0, DATA1, SUB, "SUB",
+0, DATA2, MOV, "MOV",
+0, DATA2, MVN, "MVN",
+0, DATA3, CMN, "CMN",
+0, DATA3, CMP, "CMP",
+0, DATA3, TEQ, "TEQ",
+0, DATA3, TST, "TST",
+
+0, SET, 0x00100000, ".S",
+
+0, PEE, 0x0010F000, ".P",
+
+0, REG, 0, "R0",
+0, REG, 1, "R1",
+0, REG, 2, "R2",
+0, REG, 3, "R3",
+0, REG, 4, "R4",
+0, REG, 5, "R5",
+0, REG, 6, "R6",
+0, REG, 7, "R7",
+0, REG, 8, "R8",
+0, REG, 9, "R9",
+0, REG, 10, "R10",
+0, REG, 11, "R11",
+0, REG, 12, "R12",
+0, REG, 13, "R13",
+0, REG, 14, "R14",
+0, REG, 15, "R15",
+
+0, SHIFT, 0x00000000, "LSL",
+0, SHIFT, 0x00000000, "ASL",
+0, SHIFT, 0x00000020, "LSR",
+0, SHIFT, 0x00000040, "ASR",
+0, SHIFT, 0x00000060, "ROR",
+
+0, RXX, 0x00000060, "RXX",
+
+0, SDT, 0x04100000, "LDR",
+0, SDT, 0x04000000, "STR",
+
+0, BYTE, 0x00400000, ".B",
+
+0, TRANS, 0x00200000, ".T",
+
+0, BDT, 0x09100000, "LDMDB",
+0, BDT, 0x08100000, "LDMDA",
+0, BDT, 0x09900000, "LDMIB",
+0, BDT, 0x08900000, "LDMIA",
+0, BDT, 0x08100000, "LDMFD",
+0, BDT, 0x08900000, "LDMFA",
+0, BDT, 0x09100000, "LDMED",
+0, BDT, 0x09900000, "LDMEA",
+0, BDT, 0x09000000, "STMDB",
+0, BDT, 0x08000000, "STMDA",
+0, BDT, 0x09800000, "STMIB",
+0, BDT, 0x08800000, "STMIA",
+0, BDT, 0x09000000, "STMFD",
+0, BDT, 0x09800000, "STMFA",
+0, BDT, 0x08000000, "STMED",
+0, BDT, 0x08800000, "STMEA",
+
+0, SWI, 0, "SWI",
+
+0, ADR, 0, "ADR",
+
+
--- /dev/null
+operation : BRANCH optlink expr
+ {branch($1, $2, $3.val);}
+ | DATA1 optcond opts optp REG ',' REG ',' operand
+ {data($1,$2|$3|$4|$5<<12|$7<<16,$9.val,$9.typ);}
+ | DATA2 optcond opts optp REG ',' operand
+ {data($1,$2|$3|$4|$5<<12,$7.val,$7.typ);}
+ | DATA3 optcond opts optp REG ',' operand
+ {data($1,$2|$3|$4|$5<<16,$7.val,$7.typ);}
+ | SDT optcond optb optt REG ',' address
+ {emit4($1|$2|$3|$4|$5<<12|$7);}
+ | BDT optcond REG optexc ',' reglist optpsr
+ {emit4($1|$2|$3<<16|$4|$6|$7);}
+ | SWI optcond expr
+ {emit4($1|$2);}
+ | ADR REG ',' expr
+ {calcadr($2, $4.val, $4.typ);}
+ ;
+
+optlink : {$$=0;}
+ | LINK
+ {$$=$1;}
+ ;
+
+optcond : {$$=0xE0000000;}
+ | COND
+ {$$=$1;}
+ ;
+
+opts : {$$=0;}
+ | SET
+ {$$=$1;}
+ ;
+
+optt : {$$=0;}
+ | TRANS
+ {$$=$1;}
+ ;
+
+optp : {$$=0;}
+ | PEE
+ {$$=$1;}
+ ;
+
+optb : {$$=0;}
+ | BYTE
+ {$$=$1;}
+ ;
+
+optexc : {$$=0;}
+ | '<'
+ {$$=0x00200000;}
+ ;
+
+optpsr : {$$=0;}
+ | '^'
+ {$$=0x00400000;}
+ ;
+
+operand : REG optshift
+ {$$.val = $1|$2; $$.typ = S_REG;}
+ | '#'expr
+ {$$ = $2;}
+ ;
+
+optshift : ',' SHIFT shftcnt
+ {$$ = $2|$3;}
+ | ',' RXX
+ {$$ = $2;}
+ |
+ {$$ = 0;}
+ ;
+
+shftcnt : '#' expr
+ {$$ = calcshft($2.val, $2.typ, $<y_word>0);}
+ | REG
+ {$$ = $1<<8|0x10;}
+ ;
+
+address : expr
+ {$$ = 0x01000000|calcaddress($1.val,$1.typ,$<y_word>-1);}
+ | '[' REG ']'
+ {$$ = 0x01000000|$2<<16;}
+ | '[' REG ',' offset ']' optexc
+ {$$ = $2<<16|$4|$6|0x01000000;}
+ | '[' REG ']' ',' offset
+ {$$ = $2<<16|$5;}
+ ;
+
+offset : '#' expr
+ {$$ = calcoffset($2.val);}
+ | optsign REG optshift
+ {$$ = 0x02000000|$1|$2|$3;}
+ ;
+
+optsign : {$$ = 0x00800000;}
+ | '+'
+ {$$ = 0x00800000;}
+ | '-'
+ {$$ = 0x0;}
+ ;
+
+reglist : '{' rlist '}'
+ {$$ = $2;}
+ ;
+
+rlist : REG
+ {$$ = 1<<$1;}
+ | rlist ',' REG
+ {$$ = $1|1<<$3;}
+ ;
--- /dev/null
+branch(brtyp, link, val)
+word_t brtyp;
+word_t link;
+valu_t val;
+{
+ valu_t offset;
+
+ offset = val - DOTVAL - 8;
+ if ((offset & 0xFC000000) != 0 && (offset & 0xFC000000) != 0xFC000000){
+ serror("offset out of range");
+ }
+ offset = offset>>2 & 0xFFFFFF;
+ emit4(brtyp|link|offset);
+ return;
+}
+
+data(opc, ins, val, typ)
+word_t opc, ins;
+valu_t val;
+short typ;
+{
+ valu_t tmpval;
+
+ if (typ == S_REG){
+ emit4(opc|ins|val);
+ return;
+ }
+
+ ins |= 0x02000000;
+
+ tmpval = val;
+ if (typ == S_ABS){
+ if (calcimm(&opc, &tmpval, typ)){
+ emit4(opc|ins|tmpval);
+ return;
+ }
+ }
+
+ tmpval = val;
+ if (small(calcimm(&opc, &tmpval, typ),12)){
+ emit4(opc|ins|tmpval);
+ return;
+ }
+
+ switch (opc){
+ case MOV:
+ if (small((val & 0xF0000000) == 0xF0000000, 8)){
+ emit4(0xE51F0004 | (ins & 0xF000));
+ emit4(val);
+ return;
+ }
+ if (small(1,4)){
+ emit4(0xE51F0000 | (ins & 0xF000));
+ emit4(0xEA000000);
+ emit4(val);
+ return;
+ }
+ DOTVAL += 16;
+ return;
+ case ADD:
+ if (small((val & 0xF0000000) == 0xF0000000, 4)){
+ emit4(0xE51F0004 | (ins & 0xF000));
+ emit4(val);
+ emit4(0xE2800000 | (ins&0xFF000) | (ins&0xF000)>>12);
+ return;
+ }
+ emit4(0xE51F0000 | (ins & 0xF000));
+ emit4(0xEA000000);
+ emit4(val);
+ emit4(0xE2800000 | (ins&0xFF000) | (ins&0xF000)>>12);
+ return;
+ default:
+ if (pass == PASS_1)
+ DOTVAL += 16;
+ else
+ serror("immediate value out of range");
+ return;
+ }
+}
+
+calcimm(opc,val,typ)
+word_t *opc;
+valu_t *val;
+short typ;
+{
+ int i = 0;
+
+ if (typ == S_UND) return 0;
+
+ if ((*val & ~0xFF) == 0) return 1;
+
+ if ((~*val & ~0xFF) == 0){
+ switch (*opc){
+ case AND:
+ *val = ~*val;
+ *opc = BIC;
+ return 1;
+ case MOV:
+ *val = ~*val;
+ *opc = MVN;
+ return 1;
+ case ADC:
+ *val = ~*val;
+ *opc = SBC;
+ return 1;
+ default :
+ break;
+ }
+ }
+ if ((-1**val & ~0xFF) == 0 ){
+ switch (*opc){
+ case ADD:
+ *val *= -1;
+ *opc = SUB;
+ return 1;
+ case CMP:
+ *val *= -1;
+ *opc = CMN;
+ return 1;
+ default:
+ break;
+ }
+ }
+
+ do{
+ rotateleft2(&*val);
+ i++;
+ if((*val & ~0xFF) == 0){
+ *val = *val|i<<8;
+ return 1;
+ }
+ if ((~*val & ~0xFF) == 0){
+ switch (*opc){
+ case AND:
+ *val = ~*val|i<<8;
+ *opc = BIC;
+ return 1;
+ case MOV:
+ *val = ~*val|i<<8;
+ *opc = MVN;
+ return 1;
+ case ADC:
+ *val = ~*val|i<<8;
+ *opc = SBC;
+ return 1;
+ default :
+ break;
+ }
+ }
+ }while(i<15);
+
+ return 0;
+}
+
+word_t
+calcoffset(val)
+valu_t val;
+{
+ if((val & ~0xFFF) == 0)
+ return(val|0x00800000);
+ val *= -1;
+ if((val & ~0xFFF) == 0)
+ return(val);
+ serror("offset out of range");
+ return(0);
+}
+
+word_t
+calcaddress(val,typ,reg)
+valu_t val;
+short typ;
+word_t reg;
+{
+ int tmpval;
+
+ if (typ == S_UND){
+ DOTVAL += 8;
+ return 0;
+ }
+ tmpval = val - DOTVAL - 8;
+ if(small((tmpval & ~0xFFF) == 0, 8))
+ return(val|0x008F0000);
+ tmpval *= -1;
+ if(small((tmpval & ~0xFFF) == 0, 8))
+ return(val|0x000F0000);
+ emit4(0xE51F0004 | reg << 12);
+ emit4(val | 0xF0000000);
+ return(reg << 16);
+}
+
+word_t
+calcadr(reg, val, typ)
+word_t reg;
+valu_t val;
+short typ;
+{
+ valu_t tmpval = val;
+ int i = 0;
+
+ if ((val & 0xFC000000) && (typ != S_UND)){
+ serror("address out of range");
+ return 0;
+ }
+
+ if (typ != S_ABS){
+ tmpval = val-DOTVAL-8;
+ if (small((tmpval & ~0xFF) == 0),12){
+ emit4(0xE2000000|ADD|0xF<<16|reg<<12|tmpval);
+ return 0;
+ }
+
+ tmpval *= -1;
+ if (small((tmpval & ~0xFF) == 0), 12){
+ emit4(0xE2000000|SUB|0xF<<16|reg<<12|tmpval);
+ return 0;
+ }
+ }
+
+ data(MOV, 0xE2000000||reg<<12, val, typ);
+
+ return 0;
+}
+
+
+word_t
+calcshft(val, typ, styp)
+valu_t val;
+short typ;
+word_t styp;
+{
+ if (typ=S_UND) return 0;
+ if (val & ~0x1F) serror("shiftcount out of range");
+ if (styp && !val) warning("shiftcount 0");
+ return((val & 0x1F)<<7);
+}
+
+rotateleft2(x)
+long *x;
+{
+ unsigned long bits;
+
+ bits = *x & 0xC0000000;
+ *x <<= 2 ;
+ if (bits){
+ bits >>= 30;
+ *x |= bits;
+ }
+ return;
+}