git: 9front

Download patch

ref: 509c4a8603b702f665102298f218c269fdbb2b6b
parent: ebe03bb26171e65c795c80dc85507579831bb7ef
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Sat Aug 10 12:40:36 EDT 2013

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'.

--- a/sys/src/libmach/5db.c
+++ b/sys/src/libmach/5db.c
@@ -93,7 +93,7 @@
 	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 @@
 	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 @@
 }
 
 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 @@
 }
 
 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 @@
 /* 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
--