📄 asm.c
字号:
rt = 0; /* CMP[FD] */ else if(o1 & (1<<15)) r = 0; /* monadic */ else if(r == NREG) r = rt; o1 |= rf | (r<<16) | (rt<<12); break; case 55: /* floating point fix and float */ o1 = oprrr(p->as, p->scond); rf = p->from.reg; rt = p->to.reg; if(p->to.type == D_NONE){ rt = 0; diag("to.type==D_NONE (asm/fp)"); } if(p->from.type == D_REG) o1 |= (rf<<12) | (rt<<16); else o1 |= rf | (rt<<12); break; case 56: /* move to FP[CS]R */ o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4); o1 |= ((p->to.reg+1)<<21) | (p->from.reg << 12); break; case 57: /* move from FP[CS]R */ o1 = ((p->scond & C_SCOND) << 28) | (0xe << 24) | (1<<8) | (1<<4); o1 |= ((p->from.reg+1)<<21) | (p->to.reg<<12) | (1<<20); break; case 58: /* movbu R,R */ o1 = oprrr(AAND, p->scond); o1 |= immrot(0xff); rt = p->to.reg; r = p->from.reg; if(p->to.type == D_NONE) rt = 0; if(r == NREG) r = rt; o1 |= (r<<16) | (rt<<12); break; case 59: /* movw/bu R<<I(R),R -> ldr indexed */ if(p->from.reg == NREG) { if(p->as != AMOVW) diag("byte MOV from shifter operand"); goto mov; } if(p->from.offset&(1<<4)) diag("bad shift in LDR"); o1 = olrr(p->from.offset, p->from.reg, p->to.reg, p->scond); if(p->as == AMOVBU) o1 |= 1<<22; break; case 60: /* movb R(R),R -> ldrsb indexed */ if(p->from.reg == NREG) { diag("byte MOV from shifter operand"); goto mov; } if(p->from.offset&(~0xf)) diag("bad shift in LDRSB"); o1 = olhrr(p->from.offset, p->from.reg, p->to.reg, p->scond); o1 ^= (1<<5)|(1<<6); break; case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */ if(p->to.reg == NREG) diag("MOV to shifter operand"); o1 = osrr(p->from.reg, p->to.offset, p->to.reg, p->scond); if(p->as == AMOVB || p->as == AMOVBU) o1 |= 1<<22; break; case 62: /* case R -> movw R<<2(PC),PC */ o1 = olrr(p->from.reg, REGPC, REGPC, p->scond); o1 |= 2<<7; break; case 63: /* bcase */ if(p->cond != P) { o1 = p->cond->pc; if(dlm) dynreloc(S, p->pc, 1); } break; /* reloc ops */ case 64: /* mov/movb/movbu R,addr */ o1 = omvl(p, &p->to, REGTMP); if(!o1) break; o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); break; case 65: /* mov/movbu addr,R */ case 66: /* movh/movhu/movb addr,R */ o1 = omvl(p, &p->from, REGTMP); if(!o1) break; o2 = olr(0, REGTMP, p->to.reg, p->scond); if(p->as == AMOVBU || p->as == AMOVB) o2 |= 1<<22; if(o->type == 65) break; o3 = oprrr(ASLL, p->scond); if(p->as == AMOVBU || p->as == AMOVHU) o4 = oprrr(ASRL, p->scond); else o4 = oprrr(ASRA, p->scond); r = p->to.reg; o3 |= (r)|(r<<12); o4 |= (r)|(r<<12); if(p->as == AMOVB || p->as == AMOVBU) { o3 |= (24<<7); o4 |= (24<<7); } else { o3 |= (16<<7); o4 |= (16<<7); } break; case 67: /* movh/movhu R,addr -> sb, sb */ o1 = omvl(p, &p->to, REGTMP); if(!o1) break; o2 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); o3 = oprrr(ASRL, p->scond); o3 |= (8<<7)|(p->from.reg)|(p->from.reg<<12); o3 |= (1<<6); /* ROR 8 */ o4 = oprrr(AADD, p->scond); o4 |= (REGTMP << 12) | (REGTMP << 16); o4 |= immrot(1); o5 = osr(p->as, p->from.reg, 0, REGTMP, p->scond); o6 = oprrr(ASRL, p->scond); o6 |= (24<<7)|(p->from.reg)|(p->from.reg<<12); o6 |= (1<<6); /* ROL 8 */ break; case 68: /* floating point store -> ADDR */ o1 = omvl(p, &p->to, REGTMP); if(!o1) break; o2 = ofsr(p->as, p->from.reg, 0, REGTMP, p->scond, p); break; case 69: /* floating point load <- ADDR */ o1 = omvl(p, &p->from, REGTMP); if(!o1) break; o2 = ofsr(p->as, p->to.reg, 0, REGTMP, p->scond, p) | (1<<20); break; /* ArmV4 ops: */ case 70: /* movh/movhu R,O(R) -> strh */ aclass(&p->to); r = p->to.reg; if(r == NREG) r = o->param; o1 = oshr(p->from.reg, instoffset, r, p->scond); break; case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */ aclass(&p->from); r = p->from.reg; if(r == NREG) r = o->param; o1 = olhr(instoffset, r, p->to.reg, p->scond); if(p->as == AMOVB) o1 ^= (1<<5)|(1<<6); else if(p->as == AMOVH) o1 ^= (1<<6); break; case 72: /* movh/movhu R,L(R) -> strh */ o1 = omvl(p, &p->to, REGTMP); if(!o1) break; r = p->to.reg; if(r == NREG) r = o->param; o2 = oshrr(p->from.reg, REGTMP,r, p->scond); break; case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */ o1 = omvl(p, &p->from, REGTMP); if(!o1) break; r = p->from.reg; if(r == NREG) r = o->param; o2 = olhrr(REGTMP, r, p->to.reg, p->scond); if(p->as == AMOVB) o2 ^= (1<<5)|(1<<6); else if(p->as == AMOVH) o2 ^= (1<<6); break; } if(debug['a'] > 1) Bprint(&bso, "%2d ", o->type); v = p->pc; switch(o->size) { default: if(debug['a']) Bprint(&bso, " %.8lux:\t\t%P\n", v, p); break; case 4: if(debug['a']) Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p); lputl(o1); break; case 8: if(debug['a']) Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p); lputl(o1); lputl(o2); break; case 12: if(debug['a']) Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p); lputl(o1); lputl(o2); lputl(o3); break; case 16: if(debug['a']) Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, o4, p); lputl(o1); lputl(o2); lputl(o3); lputl(o4); break; case 20: if(debug['a']) Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, o4, o5, p); lputl(o1); lputl(o2); lputl(o3); lputl(o4); lputl(o5); break; case 24: if(debug['a']) Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, o4, o5, o6, p); lputl(o1); lputl(o2); lputl(o3); lputl(o4); lputl(o5); lputl(o6); break; }}longoprrr(int a, int sc){ long o; o = (sc & C_SCOND) << 28; if(sc & C_SBIT) o |= 1 << 20; if(sc & (C_PBIT|C_WBIT)) diag(".P/.W on dp instruction"); switch(a) { case AMULU: case AMUL: return o | (0x0<<21) | (0x9<<4); case AMULA: return o | (0x1<<21) | (0x9<<4); case AMULLU: return o | (0x4<<21) | (0x9<<4); case AMULL: return o | (0x6<<21) | (0x9<<4); case AMULALU: return o | (0x5<<21) | (0x9<<4); case AMULAL: return o | (0x7<<21) | (0x9<<4); case AAND: return o | (0x0<<21); case AEOR: return o | (0x1<<21); case ASUB: return o | (0x2<<21); case ARSB: return o | (0x3<<21); case AADD: return o | (0x4<<21); case AADC: return o | (0x5<<21); case ASBC: return o | (0x6<<21); case ARSC: return o | (0x7<<21); case ATST: return o | (0x8<<21) | (1<<20); case ATEQ: return o | (0x9<<21) | (1<<20); case ACMP: return o | (0xa<<21) | (1<<20); case ACMN: return o | (0xb<<21) | (1<<20); case AORR: return o | (0xc<<21); case AMOVW: return o | (0xd<<21); case ABIC: return o | (0xe<<21); case AMVN: return o | (0xf<<21); case ASLL: return o | (0xd<<21) | (0<<5); case ASRL: return o | (0xd<<21) | (1<<5); case ASRA: return o | (0xd<<21) | (2<<5); case ASWI: return o | (0xf<<24); case AADDD: return o | (0xe<<24) | (0x0<<20) | (1<<8) | (1<<7); case AADDF: return o | (0xe<<24) | (0x0<<20) | (1<<8); case AMULD: return o | (0xe<<24) | (0x1<<20) | (1<<8) | (1<<7); case AMULF: return o | (0xe<<24) | (0x1<<20) | (1<<8); case ASUBD: return o | (0xe<<24) | (0x2<<20) | (1<<8) | (1<<7); case ASUBF: return o | (0xe<<24) | (0x2<<20) | (1<<8); case ADIVD: return o | (0xe<<24) | (0x4<<20) | (1<<8) | (1<<7); case ADIVF: return o | (0xe<<24) | (0x4<<20) | (1<<8); case ACMPD: case ACMPF: return o | (0xe<<24) | (0x9<<20) | (0xF<<12) | (1<<8) | (1<<4); /* arguably, ACMPF should expand to RNDF, CMPD */ case AMOVF: case AMOVDF: return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8); case AMOVD: case AMOVFD: return o | (0xe<<24) | (0x0<<20) | (1<<15) | (1<<8) | (1<<7); case AMOVWF: return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4); case AMOVWD: return o | (0xe<<24) | (0<<20) | (1<<8) | (1<<4) | (1<<7); case AMOVFW: return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4); case AMOVDW: return o | (0xe<<24) | (1<<20) | (1<<8) | (1<<4) | (1<<7); } diag("bad rrr %d", a); prasm(curp); return 0;}longopbra(int a, int sc){ if(sc & (C_SBIT|C_PBIT|C_WBIT)) diag(".S/.P/.W on bra instruction"); sc &= C_SCOND; if(a == ABL) return (sc<<28)|(0x5<<25)|(0x1<<24); if(sc != 0xe) diag(".COND on bcond instruction"); switch(a) { case ABEQ: return (0x0<<28)|(0x5<<25); case ABNE: return (0x1<<28)|(0x5<<25); case ABCS: return (0x2<<28)|(0x5<<25); case ABHS: return (0x2<<28)|(0x5<<25); case ABCC: return (0x3<<28)|(0x5<<25); case ABLO: return (0x3<<28)|(0x5<<25); case ABMI: return (0x4<<28)|(0x5<<25); case ABPL: return (0x5<<28)|(0x5<<25); case ABVS: return (0x6<<28)|(0x5<<25); case ABVC: return (0x7<<28)|(0x5<<25); case ABHI: return (0x8<<28)|(0x5<<25); case ABLS: return (0x9<<28)|(0x5<<25); case ABGE: return (0xa<<28)|(0x5<<25); case ABLT: return (0xb<<28)|(0x5<<25); case ABGT: return (0xc<<28)|(0x5<<25); case ABLE: return (0xd<<28)|(0x5<<25); case AB: return (0xe<<28)|(0x5<<25); } diag("bad bra %A", a); prasm(curp); return 0;}longolr(long v, int b, int r, int sc){ long o; if(sc & C_SBIT) diag(".S on LDR/STR instruction"); o = (sc & C_SCOND) << 28; if(!(sc & C_PBIT)) o |= 1 << 24; if(!(sc & C_UBIT)) o |= 1 << 23; if(sc & C_WBIT) o |= 1 << 21; o |= (0x1<<26) | (1<<20); if(v < 0) { v = -v; o ^= 1 << 23; } if(v >= (1<<12)) diag("literal span too large: %d (R%d)\n%P", v, b, PP); o |= v; o |= b << 16; o |= r << 12; return o;}longolhr(long v, int b, int r, int sc){ long o; if(sc & C_SBIT) diag(".S on LDRH/STRH instruction"); o = (sc & C_SCOND) << 28; if(!(sc & C_PBIT)) o |= 1 << 24; if(sc & C_WBIT) o |= 1 << 21; o |= (1<<23) | (1<<20)|(0xb<<4); if(v < 0) { v = -v; o ^= 1 << 23; } if(v >= (1<<8)) diag("literal span too large: %d (R%d)\n%P", v, b, PP); o |= (v&0xf)|((v>>4)<<8)|(1<<22); o |= b << 16; o |= r << 12; return o;}longosr(int a, int r, long v, int b, int sc){ long o; o = olr(v, b, r, sc) ^ (1<<20); if(a != AMOVW) o |= 1<<22; return o;}longoshr(int r, long v, int b, int sc){ long o; o = olhr(v, b, r, sc) ^ (1<<20); return o;} longosrr(int r, int i, int b, int sc){ return olr(i, b, r, sc) ^ ((1<<25) | (1<<20));}longoshrr(int r, int i, int b, int sc){ return olhr(i, b, r, sc) ^ ((1<<22) | (1<<20));}longolrr(int i, int b, int r, int sc){ return olr(i, b, r, sc) ^ (1<<25);}longolhrr(int i, int b, int r, int sc){ return olhr(i, b, r, sc) ^ (1<<22);}longofsr(int a, int r, long v, int b, int sc, Prog *p){ long o; if(sc & C_SBIT) diag(".S on FLDR/FSTR instruction"); o = (sc & C_SCOND) << 28; if(!(sc & C_PBIT)) o |= 1 << 24; if(sc & C_WBIT) o |= 1 << 21; o |= (6<<25) | (1<<24) | (1<<23); if(v < 0) { v = -v; o ^= 1 << 23; } if(v & 3) diag("odd offset for floating point op: %d\n%P", v, p); else if(v >= (1<<10)) diag("literal span too large: %d\n%P", v, p); o |= (v>>2) & 0xFF; o |= b << 16; o |= r << 12; o |= 1 << 8; switch(a) { default: diag("bad fst %A", a); case AMOVD: o |= 1<<15; case AMOVF: break; } return o;}longomvl(Prog *p, Adr *a, int dr){ long v, o1; if(!p->cond) { aclass(a); v = immrot(~instoffset); if(v == 0) { diag("missing literal"); prasm(p); return 0; } o1 = oprrr(AMVN, p->scond&C_SCOND); o1 |= v; o1 |= dr << 12; } else { v = p->cond->pc - p->pc - 8; o1 = olr(v, REGPC, dr, p->scond&C_SCOND); } return o1;}static Ieee chipfloats[] = { {0x00000000, 0x00000000}, /* 0 */ {0x00000000, 0x3ff00000}, /* 1 */ {0x00000000, 0x40000000}, /* 2 */ {0x00000000, 0x40080000}, /* 3 */ {0x00000000, 0x40100000}, /* 4 */ {0x00000000, 0x40140000}, /* 5 */ {0x00000000, 0x3fe00000}, /* .5 */ {0x00000000, 0x40240000}, /* 10 */};intchipfloat(Ieee *e){ Ieee *p; int n; for(n = sizeof(chipfloats)/sizeof(chipfloats[0]); --n >= 0;){ p = &chipfloats[n]; if(p->l == e->l && p->h == e->h) return n; } return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -