aboutsummaryrefslogtreecommitdiff
path: root/sim/arm/thumbemu.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2005-05-24 15:30:38 +0000
committerNick Clifton <nickc@redhat.com>2005-05-24 15:30:38 +0000
commit546aee7a22a519dca4d1efbcc33b0cb547328e35 (patch)
treec59ba95eab71da5e190c4e6840eb9214da9734a9 /sim/arm/thumbemu.c
parent18d59ab9dda96ae2c7c052466d20b1d3f6f61b10 (diff)
downloadgdb-546aee7a22a519dca4d1efbcc33b0cb547328e35.zip
gdb-546aee7a22a519dca4d1efbcc33b0cb547328e35.tar.gz
gdb-546aee7a22a519dca4d1efbcc33b0cb547328e35.tar.bz2
(handle_v6_thumb_insn): New function.
(ARMul_ThumbDecode): Call handle_v6_thumb_insn() when an undefined instruction binary is encountered.
Diffstat (limited to 'sim/arm/thumbemu.c')
-rw-r--r--sim/arm/thumbemu.c87
1 files changed, 72 insertions, 15 deletions
diff --git a/sim/arm/thumbemu.c b/sim/arm/thumbemu.c
index 0aa0f61..8707ca7 100644
--- a/sim/arm/thumbemu.c
+++ b/sim/arm/thumbemu.c
@@ -31,20 +31,74 @@ existing ARM simulator. */
#include "armemu.h"
#include "armos.h"
+/* Attempt to emulate an ARMv6 instruction.
+ Stores t_branch into PVALUE upon success or t_undefined otherwise. */
+
+static void
+handle_v6_thumb_insn (ARMul_State * state,
+ ARMword tinstr,
+ tdstate * pvalid)
+{
+ ARMword Rd;
+ ARMword Rm;
+
+ if (! state->is_v6)
+ {
+ * pvalid = t_undefined;
+ return;
+ }
+
+ switch (tinstr & 0xFFC0)
+ {
+ case 0xb660: /* cpsie */
+ case 0xb670: /* cpsid */
+ case 0x4600: /* cpy */
+ case 0xba00: /* rev */
+ case 0xba40: /* rev16 */
+ case 0xbac0: /* revsh */
+ case 0xb650: /* setend */
+ default:
+ printf ("Unhandled v6 thumb insn: %04x\n", tinstr);
+ * pvalid = t_undefined;
+ return;
+
+ case 0xb200: /* sxth */
+ Rm = state->Reg [(tinstr & 0x38) >> 3];
+ if (Rm & 0x8000)
+ state->Reg [(tinstr & 0x7)] = (Rm & 0xffff) | 0xffff0000;
+ else
+ state->Reg [(tinstr & 0x7)] = Rm & 0xffff;
+ break;
+ case 0xb240: /* sxtb */
+ Rm = state->Reg [(tinstr & 0x38) >> 3];
+ if (Rm & 0x80)
+ state->Reg [(tinstr & 0x7)] = (Rm & 0xff) | 0xffffff00;
+ else
+ state->Reg [(tinstr & 0x7)] = Rm & 0xff;
+ break;
+ case 0xb280: /* uxth */
+ Rm = state->Reg [(tinstr & 0x38) >> 3];
+ state->Reg [(tinstr & 0x7)] = Rm & 0xffff;
+ break;
+ case 0xb2c0: /* uxtb */
+ Rm = state->Reg [(tinstr & 0x38) >> 3];
+ state->Reg [(tinstr & 0x7)] = Rm & 0xff;
+ break;
+ }
+ /* Indicate that the instruction has been processed. */
+ * pvalid = t_branch;
+}
+
/* Decode a 16bit Thumb instruction. The instruction is in the low
16-bits of the tinstr field, with the following Thumb instruction
held in the high 16-bits. Passing in two Thumb instructions allows
easier simulation of the special dual BL instruction. */
-tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
- ARMul_State *
- state;
- ARMword
- pc;
- ARMword
- tinstr;
- ARMword *
- ainstr;
+tdstate
+ARMul_ThumbDecode (ARMul_State * state,
+ ARMword pc,
+ ARMword tinstr,
+ ARMword * ainstr)
{
tdstate valid = t_decoded; /* default assumes a valid instruction */
ARMword next_instr;
@@ -222,7 +276,7 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
case 0x0: /* UNDEFINED */
case 0x4: /* UNDEFINED */
case 0x8: /* UNDEFINED */
- valid = t_undefined;
+ handle_v6_thumb_insn (state, tinstr, & valid);
break;
}
}
@@ -370,7 +424,7 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
/* Drop through. */
default:
/* Everything else is an undefined instruction. */
- valid = t_undefined;
+ handle_v6_thumb_insn (state, tinstr, & valid);
break;
}
break;
@@ -460,8 +514,9 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
}
valid = t_branch;
}
- else /* UNDEFINED : cc=1110(AL) uses different format */
- valid = t_undefined;
+ else
+ /* UNDEFINED : cc=1110(AL) uses different format. */
+ handle_v6_thumb_insn (state, tinstr, & valid);
break;
case 28: /* B */
/* Format 18 */
@@ -476,7 +531,7 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
{
if (tinstr & 1)
{
- valid = t_undefined;
+ handle_v6_thumb_insn (state, tinstr, & valid);
break;
}
/* Drop through. */
@@ -499,8 +554,10 @@ tdstate ARMul_ThumbDecode (state, pc, tinstr, ainstr)
break;
}
}
- valid = t_undefined;
+
+ handle_v6_thumb_insn (state, tinstr, & valid);
break;
+
case 30: /* BL instruction 1 */
/* Format 19 */
/* There is no single ARM instruction equivalent for this Thumb