📄 run.c
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <mach.h>#include "arm.h"static int dummy;static char* shtype[4] ={ "<<", ">>", "->", "@>",};static char* cond[16] ={ ".EQ", ".NE", ".HS", ".LO", ".MI", ".PL", ".VS", ".VC", ".HI", ".LS", ".GE", ".LT", ".GT", ".LE", "", ".NO",};void Idp0(ulong);void Idp1(ulong);void Idp2(ulong);void Idp3(ulong);void Imul(ulong);void Imula(ulong);void Imull(ulong);void Iswap(ulong);void Imem1(ulong);void Imem2(ulong);void Ilsm(ulong inst);void Ib(ulong);void Ibl(ulong);void Ssyscall(ulong);Inst itab[] ={ { Idp0, "AND", Iarith }, /* 00 - r,r,r */ { Idp0, "EOR", Iarith }, /* 01 */ { Idp0, "SUB", Iarith }, /* 02 */ { Idp0, "RSB", Iarith }, /* 03 */ { Idp0, "ADD", Iarith }, /* 04 */ { Idp0, "ADC", Iarith }, /* 05 */ { Idp0, "SBC", Iarith }, /* 06 */ { Idp0, "RSC", Iarith }, /* 07 */ { Idp0, "TST", Iarith }, /* 08 */ { Idp0, "TEQ", Iarith }, /* 09 */ { Idp0, "CMP", Iarith }, /* 10 */ { Idp0, "CMN", Iarith }, /* 11 */ { Idp0, "ORR", Iarith }, /* 12 */ { Idp0, "MOV", Iarith }, /* 13 */ { Idp0, "BIC", Iarith }, /* 14 */ { Idp0, "MVN", Iarith }, /* 15 */ { Idp1, "AND", Iarith }, /* 16 */ { Idp1, "EOR", Iarith }, /* 17 */ { Idp1, "SUB", Iarith }, /* 18 */ { Idp1, "RSB", Iarith }, /* 19 */ { Idp1, "ADD", Iarith }, /* 20 */ { Idp1, "ADC", Iarith }, /* 21 */ { Idp1, "SBC", Iarith }, /* 22 */ { Idp1, "RSC", Iarith }, /* 23 */ { Idp1, "TST", Iarith }, /* 24 */ { Idp1, "TEQ", Iarith }, /* 25 */ { Idp1, "CMP", Iarith }, /* 26 */ { Idp1, "CMN", Iarith }, /* 27 */ { Idp1, "ORR", Iarith }, /* 28 */ { Idp1, "MOV", Iarith }, /* 29 */ { Idp1, "BIC", Iarith }, /* 30 */ { Idp1, "MVN", Iarith }, /* 31 */ { Idp2, "AND", Iarith }, /* 32 */ { Idp2, "EOR", Iarith }, /* 33 */ { Idp2, "SUB", Iarith }, /* 34 */ { Idp2, "RSB", Iarith }, /* 35 */ { Idp2, "ADD", Iarith }, /* 36 */ { Idp2, "ADC", Iarith }, /* 37 */ { Idp2, "SBC", Iarith }, /* 38 */ { Idp2, "RSC", Iarith }, /* 39 */ { Idp2, "TST", Iarith }, /* 40 */ { Idp2, "TEQ", Iarith }, /* 41 */ { Idp2, "CMP", Iarith }, /* 42 */ { Idp2, "CMN", Iarith }, /* 43 */ { Idp2, "ORR", Iarith }, /* 44 */ { Idp2, "MOV", Iarith }, /* 45 */ { Idp2, "BIC", Iarith }, /* 46 */ { Idp2, "MVN", Iarith }, /* 47 */ { Idp3, "AND", Iarith }, /* 48 - i,r,r */ { Idp3, "EOR", Iarith }, /* 49 */ { Idp3, "SUB", Iarith }, /* 50 */ { Idp3, "RSB", Iarith }, /* 51 */ { Idp3, "ADD", Iarith }, /* 52 */ { Idp3, "ADC", Iarith }, /* 53 */ { Idp3, "SBC", Iarith }, /* 54 */ { Idp3, "RSC", Iarith }, /* 55 */ { Idp3, "TST", Iarith }, /* 56 */ { Idp3, "TEQ", Iarith }, /* 57 */ { Idp3, "CMP", Iarith }, /* 58 */ { Idp3, "CMN", Iarith }, /* 59 */ { Idp3, "ORR", Iarith }, /* 60 */ { Idp3, "MOV", Iarith }, /* 61 */ { Idp3, "BIC", Iarith }, /* 62 */ { Idp3, "MVN", Iarith }, /* 63 */ { Imul, "MUL", Iarith }, /* 64 */ { Imula, "MULA", Iarith }, /* 65 */ { Iswap, "SWPW", Imem }, /* 66 */ { Iswap, "SWPBU", Imem }, /* 67 */ { Imem2, "MOV", Imem }, /* 68 load/store h/sb */ { Imem2, "MOV", Imem }, /* 69 */ { Imem2, "MOV", Imem }, /* 70 */ { Imem2, "MOV", Imem }, /* 71 */ { Imem1, "MOVW", Imem }, /* 72 load/store w/ub i,r */ { Imem1, "MOVB", Imem }, /* 73 */ { Imem1, "MOVW", Imem }, /* 74 */ { Imem1, "MOVB", Imem }, /* 75 */ { Imem1, "MOVW", Imem }, /* 76 load/store r,r */ { Imem1, "MOVB", Imem }, /* 77 */ { Imem1, "MOVW", Imem }, /* 78 */ { Imem1, "MOVB", Imem }, /* 79 */ { Ilsm, "LDM", Imem }, /* 80 block move r,r */ { Ilsm, "STM", Imem }, /* 81 */ { Ib, "B", Ibranch }, /* 82 branch */ { Ibl, "BL", Ibranch }, /* 83 */ { Ssyscall, "SWI", Isyscall }, /* 84 co processor */ { undef, "undef" }, /* 85 */ { undef, "undef" }, /* 86 */ { undef, "undef" }, /* 87 */ { Imull, "MULLU", Iarith }, /* 88 */ { Imull, "MULALU", Iarith }, /* 89 */ { Imull, "MULL", Iarith }, /* 90 */ { Imull, "MULAL", Iarith }, /* 91 */ { undef, "undef" }, /* 92 */ { 0 }};intruncmp(void){ switch(reg.cond) { case 0x0: /* eq */ return (reg.cc1 == reg.cc2); case 0x1: /* ne */ return (reg.cc1 != reg.cc2); case 0x2: /* hs */ return ((ulong)reg.cc1 >= (ulong)reg.cc2); case 0x3: /* lo */ return ((ulong)reg.cc1 < (ulong)reg.cc2); case 0x4: /* mi */ return (reg.cc1 - reg.cc2 < 0); case 0x5: /* pl */ return (reg.cc1 - reg.cc2 >= 0); case 0x8: /* hi */ return ((ulong)reg.cc1 > (ulong)reg.cc2); case 0x9: /* ls */ return ((ulong)reg.cc1 <= (ulong)reg.cc2); case 0xa: /* ge */ return (reg.cc1 >= reg.cc2); case 0xb: /* lt */ return (reg.cc1 < reg.cc2); case 0xc: /* gt */ return (reg.cc1 > reg.cc2); case 0xd: /* le */ return (reg.cc1 <= reg.cc2); case 0xe: /* al */ return 1; case 0xf: /* nv */ return 0; default: Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n", reg.cond, reg.cc1, reg.cc2); undef(reg.ir); return 0; }}intrunteq(void){ long res = reg.cc1 ^ reg.cc2; switch(reg.cond) { case 0x0: /* eq */ return res == 0; case 0x1: /* ne */ return res != 0; case 0x4: /* mi */ return (res & SIGNBIT) != 0; case 0x5: /* pl */ return (res & SIGNBIT) == 0; case 0xe: /* al */ return 1; case 0xf: /* nv */ return 0; default: Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n", reg.cond, reg.cc1, reg.cc2); undef(reg.ir); return 0; }}intruntst(void){ long res = reg.cc1 & reg.cc2; switch(reg.cond) { case 0x0: /* eq */ return res == 0; case 0x1: /* ne */ return res != 0; case 0x4: /* mi */ return (res & SIGNBIT) != 0; case 0x5: /* pl */ return (res & SIGNBIT) == 0; case 0xe: /* al */ return 1; case 0xf: /* nv */ return 0; default: Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n", reg.cond, reg.cc1, reg.cc2); undef(reg.ir); return 0; }}voidrun(void){ int execute; do { if(trace) Bflush(bioout); reg.ar = reg.r[REGPC]; reg.ir = ifetch(reg.ar); reg.class = armclass(reg.ir); reg.ip = &itab[reg.class]; reg.cond = (reg.ir>>28) & 0xf; switch(reg.compare_op) { case CCcmp: execute = runcmp(); break; case CCteq: execute = runteq(); break; case CCtst: execute = runtst(); break; default: Bprint(bioout, "unimplemented compare operation %x\n", reg.compare_op); return; } if(execute) { reg.ip->count++; (*reg.ip->func)(reg.ir); } else { if(trace) itrace("%s%s IGNORED", reg.ip->name, cond[reg.cond]); } reg.r[REGPC] += 4; if(bplist) brkchk(reg.r[REGPC], Instruction); } while(--count);}voidundef(ulong inst){ Bprint(bioout, "undefined instruction trap pc #%lux inst %.8lux class %d\n", reg.r[REGPC], inst, reg.class); longjmp(errjmp, 0);}longshift(long v, int st, int sc, int isreg){ if(sc == 0) { switch(st) { case 0: /* logical left */ reg.cout = reg.cbit; break; case 1: /* logical right */ reg.cout = (v >> 31) & 1; break; case 2: /* arith right */ reg.cout = reg.cbit; break; case 3: /* rotate right */ if(isreg) { reg.cout = reg.cbit; } else { reg.cout = v & 1; v = ((ulong)v >> 1) | (reg.cbit << 31); } } } else { switch(st) { case 0: /* logical left */ reg.cout = (v >> (32 - sc)) & 1; v = v << sc; break; case 1: /* logical right */ reg.cout = (v >> (sc - 1)) & 1; v = (ulong)v >> sc; break; case 2: /* arith right */ if(sc >= 32) { reg.cout = (v >> 31) & 1; if(reg.cout) v = 0xFFFFFFFF; else v = 0; } else { reg.cout = (v >> (sc - 1)) & 1; v = (long)v >> sc; } break; case 3: /* rotate right */ reg.cout = (v >> (sc - 1)) & 1; v = (v << (32-sc)) | ((ulong)v >> sc); break; } } return v;}voiddpex(long inst, long o1, long o2, int rd){ int cbit; cbit = 0; switch((inst>>21) & 0xf) { case 0: /* and */ reg.r[rd] = o1 & o2; cbit = 1; break; case 1: /* eor */ reg.r[rd] = o1 ^ o2; cbit = 1; break; case 2: /* sub */ reg.r[rd] = o1 - o2; case 10: /* cmp */ if(inst & Sbit) { reg.cc1 = o1; reg.cc2 = o2; reg.compare_op = CCcmp; } return; case 3: /* rsb */ reg.r[rd] = o2 - o1; if(inst & Sbit) { reg.cc1 = o2; reg.cc2 = o1; reg.compare_op = CCcmp; } return; case 4: /* add */ if(calltree && rd == REGPC && o2 == 0) { Symbol s; findsym(o1 + o2, CTEXT, &s); Bprint(bioout, "%8lux return to %lux %s r0=%lux\n", reg.r[REGPC], o1 + o2, s.name, reg.r[REGRET]); } reg.r[rd] = o1 + o2; if(inst & Sbit) { if(((uvlong)(ulong)o1 + (uvlong)(ulong)o2) & (1LL << 32)) reg.cbit = 1; else reg.cbit = 0; reg.cc1 = o2; reg.cc2 = -o1; reg.compare_op = CCcmp; } return; case 5: /* adc */ case 6: /* sbc */ case 7: /* rsc */ undef(inst); case 8: /* tst */ if(inst & Sbit) { reg.cc1 = o1; reg.cc2 = o2; reg.compare_op = CCtst; } return; case 9: /* teq */ if(inst & Sbit) { reg.cc1 = o1; reg.cc2 = o2; reg.compare_op = CCteq; } return; case 11: /* cmn */ if(inst & Sbit) { reg.cc1 = o1; reg.cc2 = -o2; reg.compare_op = CCcmp; } return; case 12: /* orr */ reg.r[rd] = o1 | o2; cbit = 1; break; case 13: /* mov */ reg.r[rd] = o2; cbit = 1; break; case 14: /* bic */ reg.r[rd] = o1 & ~o2; cbit = 1; break; case 15: /* mvn */ reg.r[rd] = ~o2; cbit = 1; break; } if(inst & Sbit) { if(cbit) reg.cbit = reg.cout; reg.cc1 = reg.r[rd]; reg.cc2 = 0; reg.compare_op = CCcmp; }}/* * data processing instruction R,R,R */voidIdp0(ulong inst){ int rn, rd, rm; long o1, o2; rn = (inst>>16) & 0xf; rd = (inst>>12) & 0xf; rm = inst & 0xf; o1 = reg.r[rn]; if(rn == REGPC) o1 += 8; o2 = reg.r[rm]; if(rm == REGPC) o2 += 8; dpex(inst, o1, o2, rd); if(trace) itrace("%s%s\tR%d,R%d,R%d =#%x", reg.ip->name, cond[reg.cond], rm, rn, rd, reg.r[rd]); if(rd == REGPC) reg.r[rd] -= 4;}/* * data processing instruction (R<>#),R,R */voidIdp1(ulong inst){ int rn, rd, rm, st, sc; long o1, o2; rn = (inst>>16) & 0xf; rd = (inst>>12) & 0xf; rm = inst & 0xf; st = (inst>>5) & 0x3; sc = (inst>>7) & 0x1f; o1 = reg.r[rn]; if(rn == REGPC) o1 += 8; o2 = reg.r[rm]; if(rm == REGPC) o2 += 8; o2 = shift(o2, st, sc, 0); dpex(inst, o1, o2, rd); if(trace)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -