summaryrefslogtreecommitdiff
path: root/sys/src/libmach
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-08-10 16:40:36 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2013-08-10 16:40:36 +0200
commitf5363206986da1454af74af354d100c3f12d4e1e (patch)
treeb5c86583416185752d15e4fc0e5138105e067bef /sys/src/libmach
parentfde528ace40c6ac9206da1b7db5e9f092b3a64a2 (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.c38
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