From 8207e0f24ed02f921d7eb24fd80ac919e38a36f7 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Mon, 25 Apr 2005 07:48:59 +0000 Subject: [PATCH] * 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. --- sim/arm/ChangeLog | 14 +++ sim/arm/armdefs.h | 2 + sim/arm/armemu.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++ sim/arm/arminit.c | 2 + sim/arm/wrapper.c | 2 +- 5 files changed, 314 insertions(+), 1 deletion(-) diff --git a/sim/arm/ChangeLog b/sim/arm/ChangeLog index 7a680f3d38..6318ed8b4d 100644 --- a/sim/arm/ChangeLog +++ b/sim/arm/ChangeLog @@ -1,3 +1,17 @@ +2005-04-20 Nick Clifton + + * 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 * 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 a2ea405903..e2d2d95134 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 b484be4908..b569559050 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 45887879c3..544a0c183f 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 70cfd1e9dd..b9ad832eff 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: