aboutsummaryrefslogtreecommitdiff
path: root/sim/arm
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2005-04-25 07:48:59 +0000
committerNick Clifton <nickc@redhat.com>2005-04-25 07:48:59 +0000
commit8207e0f24ed02f921d7eb24fd80ac919e38a36f7 (patch)
tree9bb01fd4e158a04fcc06289c39d2b7a400495e6e /sim/arm
parent02ddf1568180e41117d6d2804636e64775ac37b6 (diff)
downloadgdb-8207e0f24ed02f921d7eb24fd80ac919e38a36f7.zip
gdb-8207e0f24ed02f921d7eb24fd80ac919e38a36f7.tar.gz
gdb-8207e0f24ed02f921d7eb24fd80ac919e38a36f7.tar.bz2
* armemu.c (handle_v6_insn): New function - emulate a few of the v6 instructions - the ones now generated by GCC.
(ARMulEmulate32): Call handle_v6_insn when a possible v6 insn is found. * armdefs.h (struct ARMul_State): Add new field: is_v6.# (ARM_v6_Prop): Define. * arminit.c (ARMul_NewState): Initialise the v6 flag. (ARMul_SelectProcessor): Determine if the v6 flag should be set. * wrapper.c (sim_create_inferior): For unknown architectures, default to allowing the v6 instructions.
Diffstat (limited to 'sim/arm')
-rw-r--r--sim/arm/ChangeLog14
-rw-r--r--sim/arm/armdefs.h2
-rw-r--r--sim/arm/armemu.c295
-rw-r--r--sim/arm/arminit.c2
-rw-r--r--sim/arm/wrapper.c2
5 files changed, 314 insertions, 1 deletions
diff --git a/sim/arm/ChangeLog b/sim/arm/ChangeLog
index 7a680f3..6318ed8 100644
--- a/sim/arm/ChangeLog
+++ b/sim/arm/ChangeLog
@@ -1,3 +1,17 @@
+2005-04-20 Nick Clifton <nickc@redhat.com>
+
+ * armemu.c (handle_v6_insn): New function - emulate a few of the
+ v6 instructions - the ones now generated by GCC.
+ (ARMulEmulate32): Call handle_v6_insn when a possible v6 insn is
+ found.
+ * armdefs.h (struct ARMul_State): Add new field: is_v6.
+ (ARM_v6_Prop): Define.
+ * arminit.c (ARMul_NewState): Initialise the v6 flag.
+ (ARMul_SelectProcessor): Determine if the v6 flag should be
+ set.
+ * wrapper.c (sim_create_inferior): For unknown architectures,
+ default to allowing the v6 instructions.
+
2005-04-18 Nick Clifton <nickc@redhat.com>
* iwmmxt.c (WMAC, WMADD): Move casts from the LHS of an assignment
diff --git a/sim/arm/armdefs.h b/sim/arm/armdefs.h
index a2ea405..e2d2d95 100644
--- a/sim/arm/armdefs.h
+++ b/sim/arm/armdefs.h
@@ -134,6 +134,7 @@ struct ARMul_State
unsigned is_v4; /* Are we emulating a v4 architecture (or higher) ? */
unsigned is_v5; /* Are we emulating a v5 architecture ? */
unsigned is_v5e; /* Are we emulating a v5e architecture ? */
+ unsigned is_v6; /* Are we emulating a v6 architecture ? */
unsigned is_XScale; /* Are we emulating an XScale architecture ? */
unsigned is_iWMMXt; /* Are we emulating an iWMMXt co-processor ? */
unsigned is_ep9312; /* Are we emulating a Cirrus Maverick co-processor ? */
@@ -166,6 +167,7 @@ struct ARMul_State
#define ARM_XScale_Prop 0x200
#define ARM_ep9312_Prop 0x400
#define ARM_iWMMXt_Prop 0x800
+#define ARM_v6_Prop 0x1000
/***************************************************************************\
* Macros to extract instruction fields *
diff --git a/sim/arm/armemu.c b/sim/arm/armemu.c
index b484be4..b569559 100644
--- a/sim/arm/armemu.c
+++ b/sim/arm/armemu.c
@@ -269,6 +269,211 @@ extern int stop_simulator;
break; \
}
+/* Attempt to emulate an ARMv6 instruction.
+ Returns non-zero upon success. */
+
+static int
+handle_v6_insn (ARMul_State * state, ARMword instr)
+{
+ switch (BITS (20, 27))
+ {
+#if 0
+ case 0x03: printf ("Unhandled v6 insn: ldr\n"); break;
+ case 0x04: printf ("Unhandled v6 insn: umaal\n"); break;
+ case 0x06: printf ("Unhandled v6 insn: mls/str\n"); break;
+ case 0x16: printf ("Unhandled v6 insn: smi\n"); break;
+ case 0x18: printf ("Unhandled v6 insn: strex\n"); break;
+ case 0x19: printf ("Unhandled v6 insn: ldrex\n"); break;
+ case 0x1a: printf ("Unhandled v6 insn: strexd\n"); break;
+ case 0x1b: printf ("Unhandled v6 insn: ldrexd\n"); break;
+ case 0x1c: printf ("Unhandled v6 insn: strexb\n"); break;
+ case 0x1d: printf ("Unhandled v6 insn: ldrexb\n"); break;
+ case 0x1e: printf ("Unhandled v6 insn: strexh\n"); break;
+ case 0x1f: printf ("Unhandled v6 insn: ldrexh\n"); break;
+ case 0x30: printf ("Unhandled v6 insn: movw\n"); break;
+ case 0x32: printf ("Unhandled v6 insn: nop/sev/wfe/wfi/yield\n"); break;
+ case 0x34: printf ("Unhandled v6 insn: movt\n"); break;
+ case 0x3f: printf ("Unhandled v6 insn: rbit\n"); break;
+#endif
+ case 0x61: printf ("Unhandled v6 insn: sadd/ssub\n"); break;
+ case 0x62: printf ("Unhandled v6 insn: qadd/qsub\n"); break;
+ case 0x63: printf ("Unhandled v6 insn: shadd/shsub\n"); break;
+ case 0x65: printf ("Unhandled v6 insn: uadd/usub\n"); break;
+ case 0x66: printf ("Unhandled v6 insn: uqadd/uqsub\n"); break;
+ case 0x67: printf ("Unhandled v6 insn: uhadd/uhsub\n"); break;
+ case 0x68: printf ("Unhandled v6 insn: pkh/sxtab/selsxtb\n"); break;
+ case 0x6c: printf ("Unhandled v6 insn: uxtb16/uxtab16\n"); break;
+ case 0x70: printf ("Unhandled v6 insn: smuad/smusd/smlad/smlsd\n"); break;
+ case 0x74: printf ("Unhandled v6 insn: smlald/smlsld\n"); break;
+ case 0x75: printf ("Unhandled v6 insn: smmla/smmls/smmul\n"); break;
+ case 0x78: printf ("Unhandled v6 insn: usad/usada8\n"); break;
+ case 0x7a: printf ("Unhandled v6 insn: usbfx\n"); break;
+ case 0x7c: printf ("Unhandled v6 insn: bfc/bfi\n"); break;
+
+ case 0x6a:
+ {
+ ARMword Rm;
+ int ror = -1;
+
+ switch (BITS (4, 11))
+ {
+ case 0x07: ror = 0; break;
+ case 0x47: ror = 8; break;
+ case 0x87: ror = 16; break;
+ case 0xc7: ror = 24; break;
+
+ case 0x01:
+ case 0xf3:
+ printf ("Unhandled v6 insn: ssat\n");
+ return 0;
+ default:
+ break;
+ }
+
+ if (ror == -1)
+ {
+ if (BITS (4, 6) == 0x7)
+ {
+ printf ("Unhandled v6 insn: ssat\n");
+ return 0;
+ }
+ break;
+ }
+
+ Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
+ if (Rm & 0x80)
+ Rm |= 0xffffff00;
+
+ if (BITS (16, 19) == 0xf)
+ /* SXTB */
+ state->Reg[BITS (12, 15)] = Rm;
+ else
+ /* SXTAB */
+ state->Reg[BITS (12, 15)] += Rm;
+ }
+ return 1;
+
+ case 0x6b:
+ {
+ ARMword Rm;
+ int ror = -1;
+
+ switch (BITS (4, 11))
+ {
+ case 0x07: ror = 0; break;
+ case 0x47: ror = 8; break;
+ case 0x87: ror = 16; break;
+ case 0xc7: ror = 24; break;
+
+ case 0xfb:
+ printf ("Unhandled v6 insn: rev\n");
+ return 0;
+ default:
+ break;
+ }
+
+ if (ror == -1)
+ break;
+
+ Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF);
+ if (Rm & 8000)
+ Rm |= 0xffff0000;
+
+ if (BITS (16, 19) == 0xf)
+ /* SXTH */
+ state->Reg[BITS (12, 15)] = Rm;
+ else
+ /* SXTAH */
+ state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
+ }
+ return 1;
+
+ case 0x6e:
+ {
+ ARMword Rm;
+ int ror = -1;
+
+ switch (BITS (4, 11))
+ {
+ case 0x07: ror = 0; break;
+ case 0x47: ror = 8; break;
+ case 0x87: ror = 16; break;
+ case 0xc7: ror = 24; break;
+
+ case 0x01:
+ case 0xf3:
+ printf ("Unhandled v6 insn: usat\n");
+ return 0;
+ default:
+ break;
+ }
+
+ if (ror == -1)
+ {
+ if (BITS (4, 6) == 0x7)
+ {
+ printf ("Unhandled v6 insn: usat\n");
+ return 0;
+ }
+ break;
+ }
+
+ Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFF);
+
+ if (BITS (16, 19) == 0xf)
+ /* UXTB */
+ state->Reg[BITS (12, 15)] = Rm;
+ else
+ /* UXTAB */
+ state->Reg[BITS (12, 15)] = state->Reg[BITS (16, 19)] + Rm;
+ }
+ return 1;
+
+ case 0x6f:
+ {
+ ARMword Rm;
+ int ror = -1;
+
+ switch (BITS (4, 11))
+ {
+ case 0x07: ror = 0; break;
+ case 0x47: ror = 8; break;
+ case 0x87: ror = 16; break;
+ case 0xc7: ror = 24; break;
+
+ case 0xfb:
+ printf ("Unhandled v6 insn: revsh\n");
+ return 0;
+ default:
+ break;
+ }
+
+ if (ror == -1)
+ break;
+
+ Rm = ((state->Reg[BITS (0, 3)] >> ror) & 0xFFFF);
+
+ if (BITS (16, 19) == 0xf)
+ /* UXT */
+ state->Reg[BITS (12, 15)] = Rm;
+ else
+ {
+ /* UXTAH */
+ state->Reg[BITS (12, 15)] = state->Reg [BITS (16, 19)] + Rm;
+ }
+ }
+ return 1;
+
+#if 0
+ case 0x84: printf ("Unhandled v6 insn: srs\n"); break;
+#endif
+ default:
+ break;
+ }
+ printf ("Unhandled v6 insn: UNKNOWN: %08x\n", instr);
+ return 0;
+}
+
/* EMULATION of ARM6. */
/* The PC pipeline value depends on whether ARM
@@ -2537,6 +2742,11 @@ check_PMUintr:
case 0x61: /* Load Word, No WriteBack, Post Dec, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2553,6 +2763,11 @@ check_PMUintr:
case 0x62: /* Store Word, WriteBack, Post Dec, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2570,6 +2785,11 @@ check_PMUintr:
case 0x63: /* Load Word, WriteBack, Post Dec, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2603,6 +2823,11 @@ check_PMUintr:
case 0x65: /* Load Byte, No WriteBack, Post Dec, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2619,6 +2844,11 @@ check_PMUintr:
case 0x66: /* Store Byte, WriteBack, Post Dec, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2636,6 +2866,11 @@ check_PMUintr:
case 0x67: /* Load Byte, WriteBack, Post Dec, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2654,6 +2889,11 @@ check_PMUintr:
case 0x68: /* Store Word, No WriteBack, Post Inc, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2685,6 +2925,11 @@ check_PMUintr:
case 0x6a: /* Store Word, WriteBack, Post Inc, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2702,6 +2947,11 @@ check_PMUintr:
case 0x6b: /* Load Word, WriteBack, Post Inc, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2720,6 +2970,11 @@ check_PMUintr:
case 0x6c: /* Store Byte, No WriteBack, Post Inc, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2751,6 +3006,11 @@ check_PMUintr:
case 0x6e: /* Store Byte, WriteBack, Post Inc, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2768,6 +3028,11 @@ check_PMUintr:
case 0x6f: /* Load Byte, WriteBack, Post Inc, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2787,6 +3052,11 @@ check_PMUintr:
case 0x70: /* Store Word, No WriteBack, Pre Dec, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2835,6 +3105,11 @@ check_PMUintr:
case 0x74: /* Store Byte, No WriteBack, Pre Dec, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2844,6 +3119,11 @@ check_PMUintr:
case 0x75: /* Load Byte, No WriteBack, Pre Dec, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2883,6 +3163,11 @@ check_PMUintr:
case 0x78: /* Store Word, No WriteBack, Pre Inc, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2901,6 +3186,11 @@ check_PMUintr:
case 0x7a: /* Store Word, WriteBack, Pre Inc, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
@@ -2931,6 +3221,11 @@ check_PMUintr:
case 0x7c: /* Store Byte, No WriteBack, Pre Inc, Reg. */
if (BIT (4))
{
+#ifdef MODE32
+ if (state->is_v6
+ && handle_v6_insn (state, instr))
+ break;
+#endif
ARMul_UndefInstr (state, instr);
break;
}
diff --git a/sim/arm/arminit.c b/sim/arm/arminit.c
index 4588787..544a0c1 100644
--- a/sim/arm/arminit.c
+++ b/sim/arm/arminit.c
@@ -129,6 +129,7 @@ ARMul_NewState (void)
state->is_v5e = LOW;
state->is_XScale = LOW;
state->is_iWMMXt = LOW;
+ state->is_v6 = LOW;
ARMul_Reset (state);
@@ -161,6 +162,7 @@ ARMul_SelectProcessor (ARMul_State * state, unsigned properties)
state->is_XScale = (properties & ARM_XScale_Prop) ? HIGH : LOW;
state->is_iWMMXt = (properties & ARM_iWMMXt_Prop) ? HIGH : LOW;
state->is_ep9312 = (properties & ARM_ep9312_Prop) ? HIGH : LOW;
+ state->is_v6 = (properties & ARM_v6_Prop) ? HIGH : LOW;
/* Only initialse the coprocessor support once we
know what kind of chip we are dealing with. */
diff --git a/sim/arm/wrapper.c b/sim/arm/wrapper.c
index 70cfd1e..b9ad832 100644
--- a/sim/arm/wrapper.c
+++ b/sim/arm/wrapper.c
@@ -275,7 +275,7 @@ sim_create_inferior (sd, abfd, argv, env)
removes the FPE emulator, since it conflicts with its coprocessors.
For the most generic ARM support, we want the FPE emulator in place. */
case bfd_mach_arm_XScale:
- ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop);
+ ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop | ARM_v6_Prop);
break;
case bfd_mach_arm_iWMMXt: