From 9f132af9e189a6c1e90b1ab7ed84c6613c8ac596 Mon Sep 17 00:00:00 2001 From: Jens Bauer Date: Tue, 15 Dec 2020 12:40:35 +0000 Subject: [PATCH] Add support for the SDIV and UDIV instructions to the ARM simulator. * armemu.c (handle_v6_insn): Add support for SDIV and UDIV. * thumbemu.c (handle_T2_insn): Likewise. --- sim/arm/ChangeLog | 9 ++++++ sim/arm/armemu.c | 63 +++++++++++++++++++++++++++++++++++++++- sim/arm/thumbemu.c | 71 ++++++++++++++++++++++++++++++++++------------ sim/arm/wrapper.c | 8 ++++++ 4 files changed, 132 insertions(+), 19 deletions(-) diff --git a/sim/arm/ChangeLog b/sim/arm/ChangeLog index 92dfabadad0..64171d65c0d 100644 --- a/sim/arm/ChangeLog +++ b/sim/arm/ChangeLog @@ -1,3 +1,12 @@ +2020-12-15 Nick Clifton + + * wrapper.c (sim_create_inferior): Accept some more ARM machine numbers. + +2020-12-15 Jens Bauer + + * armemu.c (handle_v6_insn): Add support for SDIV and UDIV. + * thumbemu.c (handle_T2_insn): Likewise. + 2020-10-20 Dr. David Alan Gilbert * armos.c (SWIread): Fix printf format. diff --git a/sim/arm/armemu.c b/sim/arm/armemu.c index 3a72277683e..922c2e498db 100644 --- a/sim/arm/armemu.c +++ b/sim/arm/armemu.c @@ -915,6 +915,68 @@ handle_v6_insn (ARMul_State * state, ARMword instr) } return 1; + case 0x71: + case 0x73: + { + ARMword valn, valm; + /* SDIV ,, + UDIV ,, + instr[31,28] = cond + instr[27,20] = 0111 0001 (SDIV), 0111 0011 (UDIV) + instr[21,21] = sign + instr[19,16] = Rn + instr[15,12] = 1111 + instr[11, 8] = Rd + instr[ 7, 4] = 1111 + instr[ 3, 0] = Rm */ + /* These bit-positions are confusing! + instr[15,12] = Rd + instr[11, 8] = 1111 */ + +#if 0 /* This is what I would expect: */ + Rn = BITS (16, 19); + Rd = BITS (8, 11); + Rm = BITS (0, 3); +#else /* This seem to work: */ + Rd = BITS (16, 19); + Rm = BITS (8, 11); + Rn = BITS (0, 3); +#endif + if (Rn == 15 || Rd == 15 || Rm == 15 + || Rn == 13 || Rd == 13 || Rm == 13) + { + ARMul_UndefInstr (state, instr); + state->Emulate = FALSE; + break; + } + + valn = state->Reg[Rn]; + valm = state->Reg[Rm]; + + if (valm == 0) + { +#if 0 + /* Exceptions: UsageFault, address 20 + Note: UsageFault is for Cortex-M; I don't know what it would be on non-Cortex-M. */ + ARMul_Abort (state, address); +#endif + printf ("Unhandled v6 insn: %cDIV divide by zero exception\n", "SU"[BIT(21)]); + } + else + { + if(BIT(21)) + { + val = valn / valm; + } + else + { + val = ((ARMsword)valn / (ARMsword)valm); + } + state->Reg[Rd] = val; + } + return 1; + } + case 0x7c: case 0x7d: { @@ -963,7 +1025,6 @@ handle_v6_insn (ARMul_State * state, ARMword instr) } return 1; } - case 0x7b: case 0x7a: /* SBFX ,,#,#. */ { diff --git a/sim/arm/thumbemu.c b/sim/arm/thumbemu.c index 72929c76b52..fa70d5bfcfb 100644 --- a/sim/arm/thumbemu.c +++ b/sim/arm/thumbemu.c @@ -1759,26 +1759,60 @@ handle_T2_insn (ARMul_State * state, break; } - case 0xDC: // SMULL - tASSERT (tBIT (4) == 0); - tASSERT (ntBITS (4, 7) == 0); - * ainstr = 0xE0C00090; - * ainstr |= (ntBITS (8, 11) << 16); // RdHi - * ainstr |= (ntBITS (12, 15) << 12); // RdLo - * ainstr |= (ntBITS (0, 3) << 8); // Rm - * ainstr |= tBITS (0, 3); // Rn - * pvalid = t_decoded; + case 0xDC: + if (tBIT (4) == 0 && ntBITS (4, 7) == 0) + { + // SMULL + * ainstr = 0xE0C00090; + * ainstr |= (ntBITS (8, 11) << 16); // RdHi + * ainstr |= (ntBITS (12, 15) << 12); // RdLo + * ainstr |= (ntBITS (0, 3) << 8); // Rm + * ainstr |= tBITS (0, 3); // Rn + * pvalid = t_decoded; + } + else if (tBIT (4) == 1 && ntBITS (4, 7) == 0xF) + { + // SDIV + * ainstr = 0xE710F010; + * ainstr |= (ntBITS (8, 11) << 16); // Rd + * ainstr |= (ntBITS (0, 3) << 8); // Rm + * ainstr |= tBITS (0, 3); // Rn + * pvalid = t_decoded; + } + else + { + fprintf (stderr, "(op = %x) ", tBITS (5,12)); + tASSERT (0); + return; + } break; - case 0xDD: // UMULL - tASSERT (tBIT (4) == 0); - tASSERT (ntBITS (4, 7) == 0); - * ainstr = 0xE0800090; - * ainstr |= (ntBITS (8, 11) << 16); // RdHi - * ainstr |= (ntBITS (12, 15) << 12); // RdLo - * ainstr |= (ntBITS (0, 3) << 8); // Rm - * ainstr |= tBITS (0, 3); // Rn - * pvalid = t_decoded; + case 0xDD: + if (tBIT (4) == 0 && ntBITS (4, 7) == 0) + { + // UMULL + * ainstr = 0xE0800090; + * ainstr |= (ntBITS (8, 11) << 16); // RdHi + * ainstr |= (ntBITS (12, 15) << 12); // RdLo + * ainstr |= (ntBITS (0, 3) << 8); // Rm + * ainstr |= tBITS (0, 3); // Rn + * pvalid = t_decoded; + } + else if (tBIT (4) == 1 && ntBITS (4, 7) == 0xF) + { + // UDIV + * ainstr = 0xE730F010; + * ainstr |= (ntBITS (8, 11) << 16); // Rd + * ainstr |= (ntBITS (0, 3) << 8); // Rm + * ainstr |= tBITS (0, 3); // Rn + * pvalid = t_decoded; + } + else + { + fprintf (stderr, "(op = %x) ", tBITS (5,12)); + tASSERT (0); + return; + } break; case 0xDF: // UMLAL @@ -1896,6 +1930,7 @@ handle_v6_thumb_insn (ARMul_State * state, case 0xEB80: // SUB case 0xEBC0: // RSB case 0xFA80: // UADD, SEL + case 0xFBC0: // UMULL, SMULL, SDIV, UDIV handle_T2_insn (state, tinstr, next_instr, pc, ainstr, pvalid); return; diff --git a/sim/arm/wrapper.c b/sim/arm/wrapper.c index 68f8242288f..cc184981512 100644 --- a/sim/arm/wrapper.c +++ b/sim/arm/wrapper.c @@ -241,6 +241,14 @@ sim_create_inferior (SIM_DESC sd ATTRIBUTE_UNUSED, ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_v6_Prop); break; +#if 1 + case bfd_mach_arm_6T2: + case bfd_mach_arm_7: + case bfd_mach_arm_7EM: + ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_v6_Prop); + break; +#endif + case bfd_mach_arm_XScale: ARMul_SelectProcessor (state, ARM_v5_Prop | ARM_v5e_Prop | ARM_XScale_Prop | ARM_v6_Prop); break; -- 2.30.2