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; }