diff options
author | Jens Bauer <jens@plustv.dk> | 2020-12-15 12:40:35 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2020-12-15 12:40:35 +0000 |
commit | 9f132af9e189a6c1e90b1ab7ed84c6613c8ac596 (patch) | |
tree | 052c3a3094e1ecbb08e2a7f1e0bb5d88825066ed /sim/arm/armemu.c | |
parent | 77c8aaf716d9f93dc5850f8b2481da5eb7a53662 (diff) | |
download | binutils-gdb-9f132af9e189a6c1e90b1ab7ed84c6613c8ac596.tar.gz |
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.
Diffstat (limited to 'sim/arm/armemu.c')
-rw-r--r-- | sim/arm/armemu.c | 63 |
1 files changed, 62 insertions, 1 deletions
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<c> <Rd>,<Rn>,<Rm> + UDIV<c> <Rd>,<Rn>,<Rm> + 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<c> <Rd>,<Rn>,#<lsb>,#<width>. */ { |