diff options
author | Nick Clifton <nickc@redhat.com> | 2016-03-18 09:32:32 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2016-03-18 09:32:32 +0000 |
commit | e101a78be9388651099af079899b8654292d24f6 (patch) | |
tree | 9f498b344c2f20f72852aa4377249dbe547e08eb /sim/aarch64/cpustate.c | |
parent | 48427a77ec1c63cba605e1d6da807d5bf7c3174a (diff) | |
download | fsf-binutils-gdb-e101a78be9388651099af079899b8654292d24f6.zip fsf-binutils-gdb-e101a78be9388651099af079899b8654292d24f6.tar.gz fsf-binutils-gdb-e101a78be9388651099af079899b8654292d24f6.tar.bz2 |
Add simulation of MUL and NEG instructions to AArch64 simulator.
* cpustate.c: Remove spurious spaces from TRACE strings.
Print hex equivalents of floats and doubles.
Check element number against array size when accessing vector
registers.
* memory.c: Trace memory reads when --trace-memory is enabled.
Remove float and double load and store functions.
* memory.h (aarch64_get_mem_float): Delete prototype.
(aarch64_get_mem_double): Likewise.
(aarch64_set_mem_float): Likewise.
(aarch64_set_mem_double): Likewise.
* simulator (IS_SET): Always return either 0 or 1.
(IS_CLEAR): Likewise.
(fldrs_pcrel): Load and store floats using 32-bit memory accesses
and doubles using 64-bit memory accesses.
(fldrd_pcrel, fldrs_wb, fldrs_abs, fldrs_scale_ext): Likewise.
(fldrd_wb, fldrd_abs, fsturs, fsturd, fldurs, fldurd): Likewise.
(fstrs_abs, fstrs_wb, fstrs_scale_ext, fstrd_abs): Likewise.
(fstrd_wb, fstrd_scale_ext, store_pair_float): Likewise.
(store_pair_double, load_pair_float, load_pair_double): Likewise.
(do_vec_MUL_by_element): New function.
(do_vec_op2): Call do_vec_MUL_by_element.
(do_scalar_NEG): New function.
(do_double_add): Call do_scalar_NEG.
Diffstat (limited to 'sim/aarch64/cpustate.c')
-rw-r--r-- | sim/aarch64/cpustate.c | 302 |
1 files changed, 144 insertions, 158 deletions
diff --git a/sim/aarch64/cpustate.c b/sim/aarch64/cpustate.c index 35a60cc..86b1b15 100644 --- a/sim/aarch64/cpustate.c +++ b/sim/aarch64/cpustate.c @@ -34,13 +34,13 @@ aarch64_set_reg_u64 (sim_cpu *cpu, GReg reg, int r31_is_sp, uint64_t val) { if (reg == R31 && ! r31_is_sp) { - TRACE_REGISTER (cpu, " GR[31] NOT CHANGED!"); + TRACE_REGISTER (cpu, "GR[31] NOT CHANGED!"); return; } if (val != cpu->gr[reg].u64) TRACE_REGISTER (cpu, - " GR[%2d] changes from %16" PRIx64 " to %16" PRIx64, + "GR[%2d] changes from %16" PRIx64 " to %16" PRIx64, reg, cpu->gr[reg].u64, val); cpu->gr[reg].u64 = val; @@ -51,13 +51,13 @@ aarch64_set_reg_s64 (sim_cpu *cpu, GReg reg, int r31_is_sp, int64_t val) { if (reg == R31 && ! r31_is_sp) { - TRACE_REGISTER (cpu, " GR[31] NOT CHANGED!"); + TRACE_REGISTER (cpu, "GR[31] NOT CHANGED!"); return; } if (val != cpu->gr[reg].s64) TRACE_REGISTER (cpu, - " GR[%2d] changes from %16" PRIx64 " to %16" PRIx64, + "GR[%2d] changes from %16" PRIx64 " to %16" PRIx64, reg, cpu->gr[reg].s64, val); cpu->gr[reg].s64 = val; @@ -128,7 +128,7 @@ aarch64_set_next_PC (sim_cpu *cpu, uint64_t next) { if (next != cpu->nextpc + 4) TRACE_REGISTER (cpu, - " NextPC changes from %16" PRIx64 " to %16" PRIx64, + "NextPC changes from %16" PRIx64 " to %16" PRIx64, cpu->nextpc, next); cpu->nextpc = next; @@ -139,7 +139,7 @@ aarch64_set_next_PC_by_offset (sim_cpu *cpu, int64_t offset) { if (cpu->pc + offset != cpu->nextpc + 4) TRACE_REGISTER (cpu, - " NextPC changes from %16" PRIx64 " to %16" PRIx64, + "NextPC changes from %16" PRIx64 " to %16" PRIx64, cpu->nextpc, cpu->pc + offset); cpu->nextpc = cpu->pc + offset; @@ -163,7 +163,7 @@ aarch64_save_LR (sim_cpu *cpu) { if (cpu->gr[LR].u64 != cpu->nextpc) TRACE_REGISTER (cpu, - " LR changes from %16" PRIx64 " to %16" PRIx64, + "LR changes from %16" PRIx64 " to %16" PRIx64, cpu->gr[LR].u64, cpu->nextpc); cpu->gr[LR].u64 = cpu->nextpc; @@ -209,11 +209,11 @@ aarch64_set_CPSR (sim_cpu *cpu, uint32_t new_flags) { if (cpu->CPSR != new_flags) TRACE_REGISTER (cpu, - " CPSR changes from %s to %s", + "CPSR changes from %s to %s", decode_cpsr (cpu->CPSR), decode_cpsr (new_flags)); else TRACE_REGISTER (cpu, - " CPSR stays at %s", decode_cpsr (cpu->CPSR)); + "CPSR stays at %s", decode_cpsr (cpu->CPSR)); } cpu->CPSR = new_flags & CPSR_ALL_FLAGS; @@ -238,7 +238,7 @@ aarch64_set_CPSR_bits (sim_cpu *cpu, uint32_t mask, uint32_t value) if (old_flags != cpu->CPSR) TRACE_REGISTER (cpu, - " CPSR changes from %s to %s", + "CPSR changes from %s to %s", decode_cpsr (old_flags), decode_cpsr (cpu->CPSR)); } @@ -259,7 +259,7 @@ aarch64_set_CPSR_bit (sim_cpu *cpu, FlagMask bit) if (old_flags != cpu->CPSR) TRACE_REGISTER (cpu, - " CPSR changes from %s to %s", + "CPSR changes from %s to %s", decode_cpsr (old_flags), decode_cpsr (cpu->CPSR)); } @@ -273,7 +273,7 @@ aarch64_clear_CPSR_bit (sim_cpu *cpu, FlagMask bit) if (old_flags != cpu->CPSR) TRACE_REGISTER (cpu, - " CPSR changes from %s to %s", + "CPSR changes from %s to %s", decode_cpsr (old_flags), decode_cpsr (cpu->CPSR)); } @@ -300,9 +300,14 @@ void aarch64_set_FP_float (sim_cpu *cpu, VReg reg, float val) { if (val != cpu->fr[reg].s) - TRACE_REGISTER (cpu, - " FR[%d] changes from %f to %f", - reg, cpu->fr[reg].s, val); + { + FRegister v; + + v.s = val; + TRACE_REGISTER (cpu, + "FR[%d].s changes from %f to %f [hex: %0lx]", + reg, cpu->fr[reg].s, val, v.v[0]); + } cpu->fr[reg].s = val; } @@ -311,10 +316,14 @@ void aarch64_set_FP_double (sim_cpu *cpu, VReg reg, double val) { if (val != cpu->fr[reg].d) - TRACE_REGISTER (cpu, - " FR[%d] changes from %f to %f", - reg, cpu->fr[reg].d, val); + { + FRegister v; + v.d = val; + TRACE_REGISTER (cpu, + "FR[%d].d changes from %f to %f [hex: %0lx]", + reg, cpu->fr[reg].d, val, v.v[0]); + } cpu->fr[reg].d = val; } @@ -324,7 +333,7 @@ aarch64_set_FP_long_double (sim_cpu *cpu, VReg reg, FRegister a) if (cpu->fr[reg].v[0] != a.v[0] || cpu->fr[reg].v[1] != a.v[1]) TRACE_REGISTER (cpu, - " FR[%d] changes from [%0lx %0lx] to [%lx %lx] ", + "FR[%d].q changes from [%0lx %0lx] to [%0lx %0lx] ", reg, cpu->fr[reg].v[0], cpu->fr[reg].v[1], a.v[0], a.v[1]); @@ -333,225 +342,202 @@ aarch64_set_FP_long_double (sim_cpu *cpu, VReg reg, FRegister a) cpu->fr[reg].v[1] = a.v[1]; } +#define GET_VEC_ELEMENT(REG, ELEMENT, FIELD) \ + do \ + { \ + if (element > ARRAY_SIZE (cpu->fr[0].FIELD)) \ + { \ + TRACE_REGISTER (cpu, \ + "Internal SIM error: invalid element number: %d ",\ + ELEMENT); \ + sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu), \ + sim_stopped, SIM_SIGBUS); \ + } \ + return cpu->fr[REG].FIELD [ELEMENT]; \ + } \ + while (0) + uint64_t aarch64_get_vec_u64 (sim_cpu *cpu, VReg reg, unsigned element) { - return cpu->fr[reg].v[element]; + GET_VEC_ELEMENT (reg, element, v); } uint32_t -aarch64_get_vec_u32 (sim_cpu *cpu, VReg regno, unsigned element) +aarch64_get_vec_u32 (sim_cpu *cpu, VReg reg, unsigned element) { - return cpu->fr[regno].w[element]; + GET_VEC_ELEMENT (reg, element, w); } uint16_t -aarch64_get_vec_u16 (sim_cpu *cpu, VReg regno, unsigned element) +aarch64_get_vec_u16 (sim_cpu *cpu, VReg reg, unsigned element) { - return cpu->fr[regno].h[element]; + GET_VEC_ELEMENT (reg, element, h); } uint8_t -aarch64_get_vec_u8 (sim_cpu *cpu, VReg regno, unsigned element) +aarch64_get_vec_u8 (sim_cpu *cpu, VReg reg, unsigned element) { - return cpu->fr[regno].b[element]; + GET_VEC_ELEMENT (reg, element, b); } -void -aarch64_set_vec_u64 (sim_cpu * cpu, - VReg regno, - unsigned element, - uint64_t value) +int64_t +aarch64_get_vec_s64 (sim_cpu *cpu, VReg reg, unsigned element) { - if (value != cpu->fr[regno].v[element]) - TRACE_REGISTER (cpu, - " VR[%2d].<long>[%d] changes from %16" PRIx64 - " to %16" PRIx64, - regno, element, cpu->fr[regno].v[element], value); - - cpu->fr[regno].v[element] = value; + GET_VEC_ELEMENT (reg, element, V); } -void -aarch64_set_vec_u32 (sim_cpu * cpu, - VReg regno, - unsigned element, - uint32_t value) +int32_t +aarch64_get_vec_s32 (sim_cpu *cpu, VReg reg, unsigned element) { - if (value != cpu->fr[regno].w[element]) - TRACE_REGISTER (cpu, - " VR[%2d].<word>[%d] changes from %8x to %8x", - regno, element, cpu->fr[regno].w[element], value); - - cpu->fr[regno].w[element] = value; + GET_VEC_ELEMENT (reg, element, W); } -void -aarch64_set_vec_u16 (sim_cpu * cpu, - VReg regno, - unsigned element, - uint16_t value) +int16_t +aarch64_get_vec_s16 (sim_cpu *cpu, VReg reg, unsigned element) { - if (value != cpu->fr[regno].h[element]) - TRACE_REGISTER (cpu, - " VR[%2d].<half>[%d] changes from %4x to %4x", - regno, element, cpu->fr[regno].h[element], value); - - cpu->fr[regno].h[element] = value; + GET_VEC_ELEMENT (reg, element, H); } -void -aarch64_set_vec_u8 (sim_cpu *cpu, VReg regno, unsigned element, uint8_t value) +int8_t +aarch64_get_vec_s8 (sim_cpu *cpu, VReg reg, unsigned element) { - if (value != cpu->fr[regno].b[element]) - TRACE_REGISTER (cpu, - " VR[%2d].<byte>[%d] changes from %x to %x", - regno, element, cpu->fr[regno].b[element], value); - - cpu->fr[regno].b[element] = value; + GET_VEC_ELEMENT (reg, element, B); } -void -aarch64_set_FPSR (sim_cpu *cpu, uint32_t value) +float +aarch64_get_vec_float (sim_cpu *cpu, VReg reg, unsigned element) { - if (cpu->FPSR != value) - TRACE_REGISTER (cpu, - " FPSR changes from %x to %x", cpu->FPSR, value); - - cpu->FPSR = value & FPSR_ALL_FPSRS; + GET_VEC_ELEMENT (reg, element, S); } -uint32_t -aarch64_get_FPSR (sim_cpu *cpu) -{ - return cpu->FPSR; -} +double +aarch64_get_vec_double (sim_cpu *cpu, VReg reg, unsigned element) +{ + GET_VEC_ELEMENT (reg, element, D); +} + + +#define SET_VEC_ELEMENT(REG, ELEMENT, VAL, FIELD, PRINTER) \ + do \ + { \ + if (ELEMENT > ARRAY_SIZE (cpu->fr[0].FIELD)) \ + { \ + TRACE_REGISTER (cpu, \ + "Internal SIM error: invalid element number: %d ",\ + ELEMENT); \ + sim_engine_halt (CPU_STATE (cpu), cpu, NULL, aarch64_get_PC (cpu), \ + sim_stopped, SIM_SIGBUS); \ + } \ + if (VAL != cpu->fr[REG].FIELD [ELEMENT]) \ + TRACE_REGISTER (cpu, \ + "VR[%2d]." #FIELD " [%d] changes from " PRINTER \ + " to " PRINTER , REG, \ + ELEMENT, cpu->fr[REG].FIELD [ELEMENT], VAL); \ + \ + cpu->fr[REG].FIELD [ELEMENT] = VAL; \ + } \ + while (0) void -aarch64_set_FPSR_bits (sim_cpu *cpu, uint32_t mask, uint32_t value) -{ - uint32_t old_FPSR = cpu->FPSR; - - mask &= FPSR_ALL_FPSRS; - cpu->FPSR &= ~mask; - cpu->FPSR |= (value & mask); - - if (cpu->FPSR != old_FPSR) - TRACE_REGISTER (cpu, - " FPSR changes from %x to %x", old_FPSR, cpu->FPSR); -} - -uint32_t -aarch64_get_FPSR_bits (sim_cpu *cpu, uint32_t mask) +aarch64_set_vec_u64 (sim_cpu * cpu, VReg reg, unsigned element, uint64_t val) { - mask &= FPSR_ALL_FPSRS; - return cpu->FPSR & mask; + SET_VEC_ELEMENT (reg, element, val, v, "%16lx"); } -int -aarch64_test_FPSR_bit (sim_cpu *cpu, FPSRMask flag) +void +aarch64_set_vec_u32 (sim_cpu * cpu, VReg reg, unsigned element, uint32_t val) { - return cpu->FPSR & flag; + SET_VEC_ELEMENT (reg, element, val, w, "%8x"); } -float -aarch64_get_vec_float (sim_cpu *cpu, VReg v, unsigned e) +void +aarch64_set_vec_u16 (sim_cpu * cpu, VReg reg, unsigned element, uint16_t val) { - return cpu->fr[v].S[e]; + SET_VEC_ELEMENT (reg, element, val, h, "%4x"); } -double -aarch64_get_vec_double (sim_cpu *cpu, VReg v, unsigned e) +void +aarch64_set_vec_u8 (sim_cpu * cpu, VReg reg, unsigned element, uint8_t val) { - return cpu->fr[v].D[e]; + SET_VEC_ELEMENT (reg, element, val, b, "%x"); } void -aarch64_set_vec_float (sim_cpu *cpu, VReg v, unsigned e, float f) +aarch64_set_vec_s64 (sim_cpu *cpu, VReg reg, unsigned element, int64_t val) { - if (f != cpu->fr[v].S[e]) - TRACE_REGISTER (cpu, - " VR[%2d].<float>[%d] changes from %f to %f", - v, e, cpu->fr[v].S[e], f); - - cpu->fr[v].S[e] = f; + SET_VEC_ELEMENT (reg, element, val, V, "%16lx"); } void -aarch64_set_vec_double (sim_cpu *cpu, VReg v, unsigned e, double d) +aarch64_set_vec_s32 (sim_cpu *cpu, VReg reg, unsigned element, int32_t val) { - if (d != cpu->fr[v].D[e]) - TRACE_REGISTER (cpu, - " VR[%2d].<double>[%d] changes from %f to %f", - v, e, cpu->fr[v].D[e], d); - - cpu->fr[v].D[e] = d; + SET_VEC_ELEMENT (reg, element, val, W, "%8x"); } -int64_t -aarch64_get_vec_s64 (sim_cpu *cpu, VReg regno, unsigned element) +void +aarch64_set_vec_s16 (sim_cpu *cpu, VReg reg, unsigned element, int16_t val) { - return cpu->fr[regno].V[element]; + SET_VEC_ELEMENT (reg, element, val, H, "%4x"); } -int32_t -aarch64_get_vec_s32 (sim_cpu *cpu, VReg regno, unsigned element) +void +aarch64_set_vec_s8 (sim_cpu *cpu, VReg reg, unsigned element, int8_t val) { - return cpu->fr[regno].W[element]; + SET_VEC_ELEMENT (reg, element, val, B, "%x"); } -int16_t -aarch64_get_vec_s16 (sim_cpu *cpu, VReg regno, unsigned element) +void +aarch64_set_vec_float (sim_cpu *cpu, VReg reg, unsigned element, float val) { - return cpu->fr[regno].H[element]; + SET_VEC_ELEMENT (reg, element, val, S, "%f"); } -int8_t -aarch64_get_vec_s8 (sim_cpu *cpu, VReg regno, unsigned element) +void +aarch64_set_vec_double (sim_cpu *cpu, VReg reg, unsigned element, double val) { - return cpu->fr[regno].B[element]; + SET_VEC_ELEMENT (reg, element, val, D, "%f"); } void -aarch64_set_vec_s64 (sim_cpu *cpu, VReg regno, unsigned element, int64_t value) +aarch64_set_FPSR (sim_cpu *cpu, uint32_t value) { - if (value != cpu->fr[regno].V[element]) + if (cpu->FPSR != value) TRACE_REGISTER (cpu, - " VR[%2d].<long>[%d] changes from %16" PRIx64 " to %16" PRIx64, - regno, element, cpu->fr[regno].V[element], value); + "FPSR changes from %x to %x", cpu->FPSR, value); - cpu->fr[regno].V[element] = value; + cpu->FPSR = value & FPSR_ALL_FPSRS; } -void -aarch64_set_vec_s32 (sim_cpu *cpu, VReg regno, unsigned element, int32_t value) +uint32_t +aarch64_get_FPSR (sim_cpu *cpu) { - if (value != cpu->fr[regno].W[element]) - TRACE_REGISTER (cpu, - " VR[%2d].<word>[%d] changes from %8x to %8x", - regno, element, cpu->fr[regno].W[element], value); - - cpu->fr[regno].W[element] = value; + return cpu->FPSR; } void -aarch64_set_vec_s16 (sim_cpu *cpu, VReg regno, unsigned element, int16_t value) +aarch64_set_FPSR_bits (sim_cpu *cpu, uint32_t mask, uint32_t value) { - if (value != cpu->fr[regno].H[element]) - TRACE_REGISTER (cpu, - " VR[%2d].<half>[%d] changes from %4x to %4x", - regno, element, cpu->fr[regno].H[element], value); + uint32_t old_FPSR = cpu->FPSR; + + mask &= FPSR_ALL_FPSRS; + cpu->FPSR &= ~mask; + cpu->FPSR |= (value & mask); - cpu->fr[regno].H[element] = value; + if (cpu->FPSR != old_FPSR) + TRACE_REGISTER (cpu, + "FPSR changes from %x to %x", old_FPSR, cpu->FPSR); } -void -aarch64_set_vec_s8 (sim_cpu *cpu, VReg regno, unsigned element, int8_t value) +uint32_t +aarch64_get_FPSR_bits (sim_cpu *cpu, uint32_t mask) { - if (value != cpu->fr[regno].B[element]) - TRACE_REGISTER (cpu, - " VR[%2d].<byte>[%d] changes from %x to %x", - regno, element, cpu->fr[regno].B[element], value); + mask &= FPSR_ALL_FPSRS; + return cpu->FPSR & mask; +} - cpu->fr[regno].B[element] = value; +int +aarch64_test_FPSR_bit (sim_cpu *cpu, FPSRMask flag) +{ + return cpu->FPSR & flag; } |