diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-08-10 16:40:36 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-08-10 16:40:36 +0200 |
commit | f5363206986da1454af74af354d100c3f12d4e1e (patch) | |
tree | b5c86583416185752d15e4fc0e5138105e067bef /sys/src/libmach | |
parent | fde528ace40c6ac9206da1b7db5e9f092b3a64a2 (diff) |
TEQ with S bit = 0 would be pointless, so ARM uses this case to encode "miscellaneous"
instructions like BKPT, BX and BLX. Decoding these correctly allows db/acid to
single step through BX and BLX on armv5t+, and to show a breakpoint instruction
as 'BKPT $#0' instead of 'TEQ R0@>R0,R0'.
Diffstat (limited to 'sys/src/libmach')
-rw-r--r-- | sys/src/libmach/5db.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/sys/src/libmach/5db.c b/sys/src/libmach/5db.c index b3d43008c..37a99ebdd 100644 --- a/sys/src/libmach/5db.c +++ b/sys/src/libmach/5db.c @@ -93,7 +93,7 @@ armexcep(Map *map, Rgetter rget) case 0x13: return "SVC/SWI Exception"; case 0x17: - return "Prefetch Abort/Data Abort"; + return "Prefetch Abort/Breakpoint"; case 0x18: return "Data Abort"; case 0x1b: @@ -140,6 +140,16 @@ armclass(long w) op = (w >> 25) & 0x7; switch(op) { case 0: /* data processing r,r,r */ + if((w & 0x0ff00080) == 0x01200000) { + op = (w >> 4) & 0x7; + if(op == 7) + op = 124; /* bkpt */ + else if (op > 0 && op < 4) + op += 124; /* bx, blx */ + else + op = 92; /* unk */ + break; + } op = ((w >> 4) & 0xf); if(op == 0x9) { op = 48+16; /* mul, swp or *rex */ @@ -551,6 +561,13 @@ armb(Opcode *o, Instr *i) } static void +armbpt(Opcode *o, Instr *i) +{ + i->imm = ((i->w >> 4) & 0xfff0) | (i->w &0xf); + format(o->o, i, o->a); +} + +static void armco(Opcode *o, Instr *i) /* coprocessor instructions */ { int op, p, cp; @@ -769,6 +786,19 @@ armfadd(Map *map, Rgetter rget, Instr *i, uvlong pc) } static uvlong +armfbx(Map *map, Rgetter rget, Instr *i, uvlong pc) +{ + char buf[8]; + int r; + + if(!armcondpass(map, rget, (i->w>>28)&0xf)) + return pc+4; + r = (i->w >> 0) & 0xf; + sprint(buf, "R%d", r); + return rget(map, buf); +} + +static uvlong armfmovm(Map *map, Rgetter rget, Instr *i, uvlong pc) { ulong v; @@ -983,6 +1013,12 @@ static Opcode opcodes[] = /* 122 */ "MOV%f%C", armvstdi, 0, "F%d,%I", "MOV%f%C", armvstdi, 0, "%I,F%d", + +/* 124 */ + "BKPT%C", armbpt, 0, "$#%i", + "BX%C", armdps, armfbx, "(R%s)", + "BXJ%C", armdps, armfbx, "(R%s)", + "BLX%C", armdps, armfbx, "(R%s)", }; static void |