More AArch64 simulator improvements.
* cpustate.c (aarch64_get_FP_half): New function. Read a vector register as a half precision floating point number. (aarch64_set_FP_half): New function. Similar, but for setting a half precision register. (aarch64_get_thread_id): New function. Returns the value of the CPU's TPIDR register. (aarch64_get_FPCR): New function. Returns the value of the CPU's floating point control register. (aarch64_set_FPCR): New function. Set the value of the CPU's FPCR register. * cpustate.h: Add prototypes for new functions. * sim-main.h (struct _sim_cpu): Add FPCR and tpidr fields. * memory.c: Use unaligned core access functions for all memory reads and writes. * simulator.c (HALT_NYI): Generate an error message if tracing will not tell the user why the simulator is halting. (HALT_UNREACHABLE): Delete. Delete (unneeded) uses of the macro. (INSTR): New time-saver macro. (fldrb_abs): New function. Loads an 8-bit value using a scaled offset. (fldrh_abs): New function. Likewise for 16-bit values. (do_vec_SSHL): Allow for negative shift values. (do_vec_USHL): Likewise. (do_vec_SHL): Correct computation of shift amount. (do_vec_SSHR_USHR): Correct decision of signed vs unsigned shifts and computation of shift value. (clz): New function. Counts leading zero bits. (do_vec_CLZ): New function. Implements CLZ (vector). (do_vec_MOV_element): Call do_vec_CLZ. (dexSimpleFPCondCompare): Implement. (do_FCVT_half_to_single): New function. Implements one of the FCVT operations. (do_FCVT_half_to_double): New function. Likewise. (do_FCVT_single_to_half): New function. Likewise. (do_FCVT_double_to_half): New function. Likewise. (dexSimpleFPDataProc1Source): Call new FCVT functions. (do_scalar_SHL): Handle negative shifts. (do_scalar_shift): Handle SSHR. (do_scalar_USHL): New function. (do_double_add): Simplify to just performing a double precision add operation. Move remaining code into... (do_scalar_vec): ... New function. (dexLoadUnsignedImmediate): Call new fldrb_abs and fldrh_abs functions. (system_get): Add support for TPIDR, CTR, FPCR, FPSR and CPSR registers. (system_set): New function. (do_MSR_immediate): New function. Stub for now. (do_MSR_reg): New function. Likewise. Partially implements MSR instruction. (do_SYS): New function. Stub for now, (dexSystem): Call new functions.
This commit is contained in:
parent
cc651c1cdd
commit
5ab6d79e70
|
@ -1,3 +1,58 @@
|
|||
2016-03-23 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* cpustate.c (aarch64_get_FP_half): New function. Read a vector
|
||||
register as a half precision floating point number.
|
||||
(aarch64_set_FP_half): New function. Similar, but for setting
|
||||
a half precision register.
|
||||
(aarch64_get_thread_id): New function. Returns the value of the
|
||||
CPU's TPIDR register.
|
||||
(aarch64_get_FPCR): New function. Returns the value of the CPU's
|
||||
floating point control register.
|
||||
(aarch64_set_FPCR): New function. Set the value of the CPU's FPCR
|
||||
register.
|
||||
* cpustate.h: Add prototypes for new functions.
|
||||
* sim-main.h (struct _sim_cpu): Add FPCR and tpidr fields.
|
||||
* memory.c: Use unaligned core access functions for all memory
|
||||
reads and writes.
|
||||
* simulator.c (HALT_NYI): Generate an error message if tracing
|
||||
will not tell the user why the simulator is halting.
|
||||
(HALT_UNREACHABLE): Delete. Delete (unneeded) uses of the macro.
|
||||
(INSTR): New time-saver macro.
|
||||
(fldrb_abs): New function. Loads an 8-bit value using a scaled
|
||||
offset.
|
||||
(fldrh_abs): New function. Likewise for 16-bit values.
|
||||
(do_vec_SSHL): Allow for negative shift values.
|
||||
(do_vec_USHL): Likewise.
|
||||
(do_vec_SHL): Correct computation of shift amount.
|
||||
(do_vec_SSHR_USHR): Correct decision of signed vs unsigned
|
||||
shifts and computation of shift value.
|
||||
(clz): New function. Counts leading zero bits.
|
||||
(do_vec_CLZ): New function. Implements CLZ (vector).
|
||||
(do_vec_MOV_element): Call do_vec_CLZ.
|
||||
(dexSimpleFPCondCompare): Implement.
|
||||
(do_FCVT_half_to_single): New function. Implements one of the
|
||||
FCVT operations.
|
||||
(do_FCVT_half_to_double): New function. Likewise.
|
||||
(do_FCVT_single_to_half): New function. Likewise.
|
||||
(do_FCVT_double_to_half): New function. Likewise.
|
||||
(dexSimpleFPDataProc1Source): Call new FCVT functions.
|
||||
(do_scalar_SHL): Handle negative shifts.
|
||||
(do_scalar_shift): Handle SSHR.
|
||||
(do_scalar_USHL): New function.
|
||||
(do_double_add): Simplify to just performing a double precision
|
||||
add operation. Move remaining code into...
|
||||
(do_scalar_vec): ... New function.
|
||||
(dexLoadUnsignedImmediate): Call new fldrb_abs and fldrh_abs
|
||||
functions.
|
||||
(system_get): Add support for TPIDR, CTR, FPCR, FPSR and CPSR
|
||||
registers.
|
||||
(system_set): New function.
|
||||
(do_MSR_immediate): New function. Stub for now.
|
||||
(do_MSR_reg): New function. Likewise. Partially implements MSR
|
||||
instruction.
|
||||
(do_SYS): New function. Stub for now,
|
||||
(dexSystem): Call new functions.
|
||||
|
||||
2016-03-18 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* cpustate.c: Remove spurious spaces from TRACE strings.
|
||||
|
|
|
@ -277,6 +277,21 @@ aarch64_clear_CPSR_bit (sim_cpu *cpu, FlagMask bit)
|
|||
decode_cpsr (old_flags), decode_cpsr (cpu->CPSR));
|
||||
}
|
||||
|
||||
float
|
||||
aarch64_get_FP_half (sim_cpu *cpu, VReg reg)
|
||||
{
|
||||
union
|
||||
{
|
||||
uint16_t h[2];
|
||||
float f;
|
||||
} u;
|
||||
|
||||
u.h[0] = cpu->fr[reg].h[0];
|
||||
u.h[1] = 0;
|
||||
return u.f;
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
aarch64_get_FP_float (sim_cpu *cpu, VReg reg)
|
||||
{
|
||||
|
@ -296,6 +311,21 @@ aarch64_get_FP_long_double (sim_cpu *cpu, VReg reg, FRegister *a)
|
|||
a->v[1] = cpu->fr[reg].v[1];
|
||||
}
|
||||
|
||||
void
|
||||
aarch64_set_FP_half (sim_cpu *cpu, VReg reg, float val)
|
||||
{
|
||||
union
|
||||
{
|
||||
uint16_t h[2];
|
||||
float f;
|
||||
} u;
|
||||
|
||||
u.f = val;
|
||||
cpu->fr[reg].h[0] = u.h[0];
|
||||
cpu->fr[reg].h[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
aarch64_set_FP_float (sim_cpu *cpu, VReg reg, float val)
|
||||
{
|
||||
|
@ -541,3 +571,24 @@ aarch64_test_FPSR_bit (sim_cpu *cpu, FPSRMask flag)
|
|||
{
|
||||
return cpu->FPSR & flag;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
aarch64_get_thread_id (sim_cpu * cpu)
|
||||
{
|
||||
return cpu->tpidr;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
aarch64_get_FPCR (sim_cpu * cpu)
|
||||
{
|
||||
return cpu->FPCR;
|
||||
}
|
||||
|
||||
void
|
||||
aarch64_set_FPCR (sim_cpu * cpu, uint32_t val)
|
||||
{
|
||||
if (cpu->FPCR != val)
|
||||
TRACE_REGISTER (cpu,
|
||||
"FPCR changes from %x to %x", cpu->FPCR, val);
|
||||
cpu->FPCR = val;
|
||||
}
|
||||
|
|
|
@ -168,10 +168,10 @@ typedef union FRegisterValue
|
|||
float s;
|
||||
double d;
|
||||
|
||||
uint64_t v[2];
|
||||
uint32_t w[4];
|
||||
uint16_t h[8];
|
||||
uint8_t b[16];
|
||||
uint64_t v[2];
|
||||
uint32_t w[4];
|
||||
uint16_t h[8];
|
||||
uint8_t b[16];
|
||||
|
||||
int64_t V[2];
|
||||
int32_t W[4];
|
||||
|
@ -194,10 +194,10 @@ typedef union FRegisterValue
|
|||
|
||||
typedef enum FlagIdx
|
||||
{
|
||||
V_IDX,
|
||||
C_IDX,
|
||||
Z_IDX,
|
||||
N_IDX
|
||||
V_IDX = 0,
|
||||
C_IDX = 1,
|
||||
Z_IDX = 2,
|
||||
N_IDX = 3
|
||||
} FlagIdx;
|
||||
|
||||
typedef enum FlagMask
|
||||
|
@ -216,7 +216,7 @@ typedef uint32_t FlagsRegister;
|
|||
|
||||
This register includes IDC, IXC, UFC, OFC, DZC, IOC and QC bits,
|
||||
and the floating point N, Z, C, V bits but the latter are unused in
|
||||
aarch64 mode. the sim ignores QC for now.
|
||||
aarch64 mode. The sim ignores QC for now.
|
||||
|
||||
Bit positions are as per the ARMv7 FPSCR register
|
||||
|
||||
|
@ -272,9 +272,12 @@ extern void aarch64_set_reg_u64 (sim_cpu *, GReg, int, uint64_t);
|
|||
extern void aarch64_set_reg_s64 (sim_cpu *, GReg, int, int64_t);
|
||||
|
||||
/* FP Register access functions. */
|
||||
extern float aarch64_get_FP_half (sim_cpu *, VReg);
|
||||
extern float aarch64_get_FP_float (sim_cpu *, VReg);
|
||||
extern double aarch64_get_FP_double (sim_cpu *, VReg);
|
||||
extern void aarch64_get_FP_long_double (sim_cpu *, VReg, FRegister *);
|
||||
|
||||
extern void aarch64_set_FP_half (sim_cpu *, VReg, float);
|
||||
extern void aarch64_set_FP_float (sim_cpu *, VReg, float);
|
||||
extern void aarch64_set_FP_double (sim_cpu *, VReg, double);
|
||||
extern void aarch64_set_FP_long_double (sim_cpu *, VReg, FRegister);
|
||||
|
@ -330,4 +333,9 @@ extern double aarch64_get_vec_double (sim_cpu *, VReg, unsigned);
|
|||
extern void aarch64_set_vec_float (sim_cpu *, VReg, unsigned, float);
|
||||
extern void aarch64_set_vec_double (sim_cpu *, VReg, unsigned, double);
|
||||
|
||||
/* System register accessors. */
|
||||
extern uint64_t aarch64_get_thread_id (sim_cpu *);
|
||||
extern uint32_t aarch64_get_FPCR (sim_cpu *);
|
||||
extern void aarch64_set_FPCR (sim_cpu *, uint32_t);
|
||||
|
||||
#endif /* _CPU_STATE_H */
|
||||
|
|
|
@ -42,11 +42,13 @@ mem_error (sim_cpu *cpu, const char *message, uint64_t addr)
|
|||
TRACE_MEMORY (cpu, "ERROR: %s: %" PRIx64, message, addr);
|
||||
}
|
||||
|
||||
/* FIXME: Aarch64 requires aligned memory access if SCTRLR_ELx.A is set,
|
||||
but we are not implementing that here. */
|
||||
#define FETCH_FUNC(RETURN_TYPE, ACCESS_TYPE, NAME, N) \
|
||||
RETURN_TYPE \
|
||||
aarch64_get_mem_##NAME (sim_cpu *cpu, uint64_t address) \
|
||||
{ \
|
||||
RETURN_TYPE val = (RETURN_TYPE) sim_core_read_##N (cpu, 0, read_map, address); \
|
||||
RETURN_TYPE val = (RETURN_TYPE) sim_core_read_unaligned_##N (cpu, 0, read_map, address); \
|
||||
TRACE_MEMORY (cpu, \
|
||||
"read of %" PRIx64 " (%d bytes) from %" PRIx64, \
|
||||
(uint64_t) val, N, address); \
|
||||
|
@ -54,29 +56,14 @@ mem_error (sim_cpu *cpu, const char *message, uint64_t addr)
|
|||
return val; \
|
||||
}
|
||||
|
||||
/* A variant of the FETCH_FUNC macro that uses unaligned reads.
|
||||
The AArch64 only requires 4-byte alignment for 8-byte quantities
|
||||
but the sim common core does not support this. */
|
||||
#define FETCH_FUNC_U(RETURN_TYPE, ACCESS_TYPE, NAME) \
|
||||
RETURN_TYPE \
|
||||
aarch64_get_mem_##NAME (sim_cpu *cpu, uint64_t address) \
|
||||
{ \
|
||||
RETURN_TYPE val = (RETURN_TYPE) sim_core_read_unaligned_8 (cpu, 0, read_map, address); \
|
||||
TRACE_MEMORY (cpu, \
|
||||
"read of %" PRIx64 " (%d bytes) from %" PRIx64 " (unaligned double)", \
|
||||
(uint64_t) val, N, address); \
|
||||
\
|
||||
return val; \
|
||||
}
|
||||
|
||||
FETCH_FUNC_U (uint64_t, uint64_t, u64)
|
||||
FETCH_FUNC_U (int64_t, int64_t, s64)
|
||||
FETCH_FUNC (uint32_t, uint32_t, u32, 4)
|
||||
FETCH_FUNC (int32_t, int32_t, s32, 4)
|
||||
FETCH_FUNC (uint32_t, uint16_t, u16, 2)
|
||||
FETCH_FUNC (int32_t, int16_t, s16, 2)
|
||||
FETCH_FUNC (uint32_t, uint8_t, u8, 1)
|
||||
FETCH_FUNC (int32_t, int8_t, s8, 1)
|
||||
FETCH_FUNC (uint64_t, uint64_t, u64, 8)
|
||||
FETCH_FUNC (int64_t, int64_t, s64, 8)
|
||||
FETCH_FUNC (uint32_t, uint32_t, u32, 4)
|
||||
FETCH_FUNC (int32_t, int32_t, s32, 4)
|
||||
FETCH_FUNC (uint32_t, uint16_t, u16, 2)
|
||||
FETCH_FUNC (int32_t, int16_t, s16, 2)
|
||||
FETCH_FUNC (uint32_t, uint8_t, u8, 1)
|
||||
FETCH_FUNC (int32_t, int8_t, s8, 1)
|
||||
|
||||
void
|
||||
aarch64_get_mem_long_double (sim_cpu *cpu, uint64_t address, FRegister *a)
|
||||
|
@ -85,6 +72,8 @@ aarch64_get_mem_long_double (sim_cpu *cpu, uint64_t address, FRegister *a)
|
|||
a->v[1] = sim_core_read_unaligned_8 (cpu, 0, read_map, address + 8);
|
||||
}
|
||||
|
||||
/* FIXME: Aarch64 requires aligned memory access if SCTRLR_ELx.A is set,
|
||||
but we are not implementing that here. */
|
||||
#define STORE_FUNC(TYPE, NAME, N) \
|
||||
void \
|
||||
aarch64_set_mem_##NAME (sim_cpu *cpu, uint64_t address, TYPE value) \
|
||||
|
@ -96,28 +85,14 @@ aarch64_get_mem_long_double (sim_cpu *cpu, uint64_t address, FRegister *a)
|
|||
sim_core_write_unaligned_##N (cpu, 0, write_map, address, value); \
|
||||
}
|
||||
|
||||
/* A variant of the STORE_FUNC macro that uses unaligned writes.
|
||||
The AArch64 only requires 4-byte alignment for 8-byte quantities
|
||||
but the sim common core does not support this. */
|
||||
#define STORE_FUNC_U(TYPE, NAME) \
|
||||
void \
|
||||
aarch64_set_mem_##NAME (sim_cpu *cpu, uint64_t address, TYPE value) \
|
||||
{ \
|
||||
TRACE_MEMORY (cpu, \
|
||||
"write of %" PRIx64 " (8 bytes) to %" PRIx64, \
|
||||
(uint64_t) value, address); \
|
||||
\
|
||||
sim_core_write_unaligned_8 (cpu, 0, write_map, address, value); \
|
||||
}
|
||||
|
||||
STORE_FUNC_U (uint64_t, u64)
|
||||
STORE_FUNC_U (int64_t, s64)
|
||||
STORE_FUNC (uint32_t, u32, 4)
|
||||
STORE_FUNC (int32_t, s32, 4)
|
||||
STORE_FUNC (uint16_t, u16, 2)
|
||||
STORE_FUNC (int16_t, s16, 2)
|
||||
STORE_FUNC (uint8_t, u8, 1)
|
||||
STORE_FUNC (int8_t, s8, 1)
|
||||
STORE_FUNC (uint64_t, u64, 8)
|
||||
STORE_FUNC (int64_t, s64, 8)
|
||||
STORE_FUNC (uint32_t, u32, 4)
|
||||
STORE_FUNC (int32_t, s32, 4)
|
||||
STORE_FUNC (uint16_t, u16, 2)
|
||||
STORE_FUNC (int16_t, s16, 2)
|
||||
STORE_FUNC (uint8_t, u8, 1)
|
||||
STORE_FUNC (int8_t, s8, 1)
|
||||
|
||||
void
|
||||
aarch64_set_mem_long_double (sim_cpu *cpu, uint64_t address, FRegister a)
|
||||
|
|
|
@ -37,12 +37,14 @@ struct _sim_cpu
|
|||
|
||||
uint64_t pc;
|
||||
uint32_t CPSR;
|
||||
uint32_t FPSR;
|
||||
uint32_t FPSR; /* Floating point Status register. */
|
||||
uint32_t FPCR; /* Floating point Control register. */
|
||||
|
||||
uint64_t nextpc;
|
||||
|
||||
uint32_t instr;
|
||||
|
||||
uint64_t tpidr; /* Thread pointer id. */
|
||||
|
||||
sim_cpu_base base;
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue