mirror of https://gitee.com/openkylin/qemu.git
target/xtensa updates for v6.1:
- don't generate extra EXCP_DEBUG on exception - fix l32ex access ring - clean up unaligned access -----BEGIN PGP SIGNATURE----- iQJHBAABCgAxFiEEK2eFS5jlMn3N6xfYUfnMkfg/oEQFAmCnvMITHGpjbXZia2Jj QGdtYWlsLmNvbQAKCRBR+cyR+D+gRHCVEACR5nXm21Y7Jc9R+Pkpe5rd8xyw5J/m 2PKM8uAH6XSo/DGanuzXUW345NmVbpL0DWSmWI6WQ7LfXpqgkO/UM76DeZGrWlTB lqQXTbVBv+crkYmxFlnYAaoVYEmSZb900RaKyFiWG95edjV/YoPnq6qzT8Xy3N6K jYRGh+cWnzxTLCsscEK8DySA79yox+Kw+49gmHddXdjhwYDs0ekT3cGhQyK8vlTU Zpu7tVwQvE3SxwSgNDrg5eG12dLTfnfLrE/wFAyQdlDUTNxjpF36mvWKUm9BmnNT L8AedMMbdqH2+0gcFfetoVOcSmquDT4axiQq/eCaudBqUzhBncaDEHeXZVpMoADI +Je5awz9pr0JStPvMANfpczRmf3WrD/de9olwRYfSZmaZ0O1w0RV8SAa4/9YPpHl H0B5bNN9fl69nGdM6Nm+ERp2evrk2qnqH9/TXJC/waU7QphbkGC2MO5BmKjRNyWj 7hxWTAW1R5/BJLgFIEkuVkVV8G6a+Jz17olhGKiXgWTJORBQE9ACWmOK/A17Nh09 LUX0nTA5eVWUgV78P599naT0Xx6SLK9QHUw6tZs3US3hrZDQvjmrrxFsf1b6qaF/ 1D0XRQlqxdEZvdgvqJcW0AlMz2eFx1/vjgHPzVbHK7L4sA6XK2UFskuttgk2g9m9 8Ro/rH/zK6Qgmw== =fLOY -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/xtensa/tags/20210521-xtensa' into staging target/xtensa updates for v6.1: - don't generate extra EXCP_DEBUG on exception - fix l32ex access ring - clean up unaligned access # gpg: Signature made Fri 21 May 2021 14:59:30 BST # gpg: using RSA key 2B67854B98E5327DCDEB17D851F9CC91F83FA044 # gpg: issuer "jcmvbkbc@gmail.com" # gpg: Good signature from "Max Filippov <filippov@cadence.com>" [unknown] # gpg: aka "Max Filippov <max.filippov@cogentembedded.com>" [full] # gpg: aka "Max Filippov <jcmvbkbc@gmail.com>" [full] # Primary key fingerprint: 2B67 854B 98E5 327D CDEB 17D8 51F9 CC91 F83F A044 * remotes/xtensa/tags/20210521-xtensa: target/xtensa: clean up unaligned access target/xtensa: fix access ring in l32ex target/xtensa: don't generate extra EXCP_DEBUG on exception Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
371ebfe286
|
@ -1,5 +1,4 @@
|
|||
TARGET_ARCH=xtensa
|
||||
TARGET_SYSTBL_ABI=common
|
||||
TARGET_SYSTBL=syscall.tbl
|
||||
TARGET_ALIGNED_ONLY=y
|
||||
TARGET_HAS_BFLT=y
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
TARGET_ARCH=xtensa
|
||||
TARGET_ALIGNED_ONLY=y
|
||||
TARGET_SUPPORTS_MTTCG=y
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
TARGET_ARCH=xtensa
|
||||
TARGET_SYSTBL_ABI=common
|
||||
TARGET_SYSTBL=syscall.tbl
|
||||
TARGET_ALIGNED_ONLY=y
|
||||
TARGET_WORDS_BIGENDIAN=y
|
||||
TARGET_HAS_BFLT=y
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
TARGET_ARCH=xtensa
|
||||
TARGET_ALIGNED_ONLY=y
|
||||
TARGET_WORDS_BIGENDIAN=y
|
||||
TARGET_SUPPORTS_MTTCG=y
|
||||
|
|
|
@ -79,7 +79,6 @@ static void xtensa_cpu_reset(DeviceState *dev)
|
|||
|
||||
xcc->parent_reset(dev);
|
||||
|
||||
env->exception_taken = 0;
|
||||
env->pc = env->config->exception_vector[EXC_RESET0 + env->static_vectors];
|
||||
env->sregs[LITBASE] &= ~1;
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
|
|
@ -540,7 +540,6 @@ typedef struct CPUXtensaState {
|
|||
uint32_t ccount_base;
|
||||
#endif
|
||||
|
||||
int exception_taken;
|
||||
int yield_needed;
|
||||
unsigned static_vectors;
|
||||
|
||||
|
@ -711,7 +710,6 @@ static inline int cpu_mmu_index(CPUXtensaState *env, bool ifetch)
|
|||
#define XTENSA_TBFLAG_ICOUNT 0x20
|
||||
#define XTENSA_TBFLAG_CPENABLE_MASK 0x3fc0
|
||||
#define XTENSA_TBFLAG_CPENABLE_SHIFT 6
|
||||
#define XTENSA_TBFLAG_EXCEPTION 0x4000
|
||||
#define XTENSA_TBFLAG_WINDOW_MASK 0x18000
|
||||
#define XTENSA_TBFLAG_WINDOW_SHIFT 15
|
||||
#define XTENSA_TBFLAG_YIELD 0x20000
|
||||
|
@ -732,8 +730,6 @@ typedef XtensaCPU ArchCPU;
|
|||
static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
*pc = env->pc;
|
||||
*cs_base = 0;
|
||||
*flags = 0;
|
||||
|
@ -782,9 +778,6 @@ static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
|
|||
if (xtensa_option_enabled(env->config, XTENSA_OPTION_COPROCESSOR)) {
|
||||
*flags |= env->sregs[CPENABLE] << XTENSA_TBFLAG_CPENABLE_SHIFT;
|
||||
}
|
||||
if (cs->singlestep_enabled && env->exception_taken) {
|
||||
*flags |= XTENSA_TBFLAG_EXCEPTION;
|
||||
}
|
||||
if (xtensa_option_enabled(env->config, XTENSA_OPTION_WINDOWED_REGISTER) &&
|
||||
(env->sregs[PS] & (PS_WOE | PS_EXCM)) == PS_WOE) {
|
||||
uint32_t windowstart = xtensa_replicate_windowstart(env) >>
|
||||
|
|
|
@ -40,9 +40,6 @@ void HELPER(exception)(CPUXtensaState *env, uint32_t excp)
|
|||
if (excp == EXCP_YIELD) {
|
||||
env->yield_needed = 0;
|
||||
}
|
||||
if (excp == EXCP_DEBUG) {
|
||||
env->exception_taken = 0;
|
||||
}
|
||||
cpu_loop_exit(cs);
|
||||
}
|
||||
|
||||
|
@ -197,7 +194,6 @@ static void handle_interrupt(CPUXtensaState *env)
|
|||
}
|
||||
env->sregs[PS] |= PS_EXCM;
|
||||
}
|
||||
env->exception_taken = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +238,6 @@ void xtensa_cpu_do_interrupt(CPUState *cs)
|
|||
|
||||
vector = env->config->exception_vector[cs->exception_index];
|
||||
env->pc = relocated_vector(env, vector);
|
||||
env->exception_taken = 1;
|
||||
} else {
|
||||
qemu_log_mask(CPU_LOG_INT,
|
||||
"%s(pc = %08x) bad exception_index: %d\n",
|
||||
|
|
|
@ -270,13 +270,12 @@ void xtensa_cpu_do_unaligned_access(CPUState *cs,
|
|||
XtensaCPU *cpu = XTENSA_CPU(cs);
|
||||
CPUXtensaState *env = &cpu->env;
|
||||
|
||||
if (xtensa_option_enabled(env->config, XTENSA_OPTION_UNALIGNED_EXCEPTION) &&
|
||||
!xtensa_option_enabled(env->config, XTENSA_OPTION_HW_ALIGNMENT)) {
|
||||
cpu_restore_state(CPU(cpu), retaddr, true);
|
||||
HELPER(exception_cause_vaddr)(env,
|
||||
env->pc, LOAD_STORE_ALIGNMENT_CAUSE,
|
||||
addr);
|
||||
}
|
||||
assert(xtensa_option_enabled(env->config,
|
||||
XTENSA_OPTION_UNALIGNED_EXCEPTION));
|
||||
cpu_restore_state(CPU(cpu), retaddr, true);
|
||||
HELPER(exception_cause_vaddr)(env,
|
||||
env->pc, LOAD_STORE_ALIGNMENT_CAUSE,
|
||||
addr);
|
||||
}
|
||||
|
||||
bool xtensa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
|
|
|
@ -339,16 +339,6 @@ static void gen_exception_cause(DisasContext *dc, uint32_t cause)
|
|||
}
|
||||
}
|
||||
|
||||
static void gen_exception_cause_vaddr(DisasContext *dc, uint32_t cause,
|
||||
TCGv_i32 vaddr)
|
||||
{
|
||||
TCGv_i32 tpc = tcg_const_i32(dc->pc);
|
||||
TCGv_i32 tcause = tcg_const_i32(cause);
|
||||
gen_helper_exception_cause_vaddr(cpu_env, tpc, tcause, vaddr);
|
||||
tcg_temp_free(tpc);
|
||||
tcg_temp_free(tcause);
|
||||
}
|
||||
|
||||
static void gen_debug_exception(DisasContext *dc, uint32_t cause)
|
||||
{
|
||||
TCGv_i32 tpc = tcg_const_i32(dc->pc);
|
||||
|
@ -554,21 +544,20 @@ static uint32_t test_exceptions_hpi(DisasContext *dc, const OpcodeArg arg[],
|
|||
return test_exceptions_sr(dc, arg, par);
|
||||
}
|
||||
|
||||
static void gen_load_store_alignment(DisasContext *dc, int shift,
|
||||
TCGv_i32 addr, bool no_hw_alignment)
|
||||
static MemOp gen_load_store_alignment(DisasContext *dc, MemOp mop,
|
||||
TCGv_i32 addr)
|
||||
{
|
||||
if (!option_enabled(dc, XTENSA_OPTION_UNALIGNED_EXCEPTION)) {
|
||||
tcg_gen_andi_i32(addr, addr, ~0 << shift);
|
||||
} else if (option_enabled(dc, XTENSA_OPTION_HW_ALIGNMENT) &&
|
||||
no_hw_alignment) {
|
||||
TCGLabel *label = gen_new_label();
|
||||
TCGv_i32 tmp = tcg_temp_new_i32();
|
||||
tcg_gen_andi_i32(tmp, addr, ~(~0 << shift));
|
||||
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
|
||||
gen_exception_cause_vaddr(dc, LOAD_STORE_ALIGNMENT_CAUSE, addr);
|
||||
gen_set_label(label);
|
||||
tcg_temp_free(tmp);
|
||||
if ((mop & MO_SIZE) == MO_8) {
|
||||
return mop;
|
||||
}
|
||||
if ((mop & MO_AMASK) == MO_UNALN &&
|
||||
!option_enabled(dc, XTENSA_OPTION_HW_ALIGNMENT)) {
|
||||
mop |= MO_ALIGN;
|
||||
}
|
||||
if (!option_enabled(dc, XTENSA_OPTION_UNALIGNED_EXCEPTION)) {
|
||||
tcg_gen_andi_i32(addr, addr, ~0 << get_alignment_bits(mop));
|
||||
}
|
||||
return mop;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
@ -1279,12 +1268,6 @@ static void xtensa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
|||
dc->base.is_jmp = DISAS_NORETURN;
|
||||
return;
|
||||
}
|
||||
if (dc->base.tb->flags & XTENSA_TBFLAG_EXCEPTION) {
|
||||
gen_exception(dc, EXCP_DEBUG);
|
||||
dc->base.pc_next = dc->pc + 1;
|
||||
dc->base.is_jmp = DISAS_NORETURN;
|
||||
return;
|
||||
}
|
||||
|
||||
if (dc->icount) {
|
||||
TCGLabel *label = gen_new_label();
|
||||
|
@ -1787,10 +1770,11 @@ static void translate_l32e(DisasContext *dc, const OpcodeArg arg[],
|
|||
const uint32_t par[])
|
||||
{
|
||||
TCGv_i32 addr = tcg_temp_new_i32();
|
||||
MemOp mop;
|
||||
|
||||
tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
|
||||
gen_load_store_alignment(dc, 2, addr, false);
|
||||
tcg_gen_qemu_ld_tl(arg[0].out, addr, dc->ring, MO_TEUL);
|
||||
mop = gen_load_store_alignment(dc, MO_TEUL, addr);
|
||||
tcg_gen_qemu_ld_tl(arg[0].out, addr, dc->ring, mop);
|
||||
tcg_temp_free(addr);
|
||||
}
|
||||
|
||||
|
@ -1816,11 +1800,12 @@ static void translate_l32ex(DisasContext *dc, const OpcodeArg arg[],
|
|||
const uint32_t par[])
|
||||
{
|
||||
TCGv_i32 addr = tcg_temp_new_i32();
|
||||
MemOp mop;
|
||||
|
||||
tcg_gen_mov_i32(addr, arg[1].in);
|
||||
gen_load_store_alignment(dc, 2, addr, true);
|
||||
mop = gen_load_store_alignment(dc, MO_TEUL | MO_ALIGN, addr);
|
||||
gen_check_exclusive(dc, addr, false);
|
||||
tcg_gen_qemu_ld_i32(arg[0].out, addr, dc->ring, MO_TEUL);
|
||||
tcg_gen_qemu_ld_i32(arg[0].out, addr, dc->cring, mop);
|
||||
tcg_gen_mov_i32(cpu_exclusive_addr, addr);
|
||||
tcg_gen_mov_i32(cpu_exclusive_val, arg[0].out);
|
||||
tcg_temp_free(addr);
|
||||
|
@ -1830,18 +1815,18 @@ static void translate_ldst(DisasContext *dc, const OpcodeArg arg[],
|
|||
const uint32_t par[])
|
||||
{
|
||||
TCGv_i32 addr = tcg_temp_new_i32();
|
||||
MemOp mop;
|
||||
|
||||
tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
|
||||
if (par[0] & MO_SIZE) {
|
||||
gen_load_store_alignment(dc, par[0] & MO_SIZE, addr, par[1]);
|
||||
}
|
||||
mop = gen_load_store_alignment(dc, par[0], addr);
|
||||
|
||||
if (par[2]) {
|
||||
if (par[1]) {
|
||||
tcg_gen_mb(TCG_BAR_STRL | TCG_MO_ALL);
|
||||
}
|
||||
tcg_gen_qemu_st_tl(arg[0].in, addr, dc->cring, par[0]);
|
||||
tcg_gen_qemu_st_tl(arg[0].in, addr, dc->cring, mop);
|
||||
} else {
|
||||
tcg_gen_qemu_ld_tl(arg[0].out, addr, dc->cring, par[0]);
|
||||
tcg_gen_qemu_ld_tl(arg[0].out, addr, dc->cring, mop);
|
||||
if (par[1]) {
|
||||
tcg_gen_mb(TCG_BAR_LDAQ | TCG_MO_ALL);
|
||||
}
|
||||
|
@ -1912,9 +1897,11 @@ static void translate_mac16(DisasContext *dc, const OpcodeArg arg[],
|
|||
TCGv_i32 mem32 = tcg_temp_new_i32();
|
||||
|
||||
if (ld_offset) {
|
||||
MemOp mop;
|
||||
|
||||
tcg_gen_addi_i32(vaddr, arg[1].in, ld_offset);
|
||||
gen_load_store_alignment(dc, 2, vaddr, false);
|
||||
tcg_gen_qemu_ld32u(mem32, vaddr, dc->cring);
|
||||
mop = gen_load_store_alignment(dc, MO_TEUL, vaddr);
|
||||
tcg_gen_qemu_ld_tl(mem32, vaddr, dc->cring, mop);
|
||||
}
|
||||
if (op != MAC16_NONE) {
|
||||
TCGv_i32 m1 = gen_mac16_m(arg[off].in,
|
||||
|
@ -2360,13 +2347,14 @@ static void translate_s32c1i(DisasContext *dc, const OpcodeArg arg[],
|
|||
{
|
||||
TCGv_i32 tmp = tcg_temp_local_new_i32();
|
||||
TCGv_i32 addr = tcg_temp_local_new_i32();
|
||||
MemOp mop;
|
||||
|
||||
tcg_gen_mov_i32(tmp, arg[0].in);
|
||||
tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
|
||||
gen_load_store_alignment(dc, 2, addr, true);
|
||||
mop = gen_load_store_alignment(dc, MO_TEUL | MO_ALIGN, addr);
|
||||
gen_check_atomctl(dc, addr);
|
||||
tcg_gen_atomic_cmpxchg_i32(arg[0].out, addr, cpu_SR[SCOMPARE1],
|
||||
tmp, dc->cring, MO_TEUL);
|
||||
tmp, dc->cring, mop);
|
||||
tcg_temp_free(addr);
|
||||
tcg_temp_free(tmp);
|
||||
}
|
||||
|
@ -2375,10 +2363,11 @@ static void translate_s32e(DisasContext *dc, const OpcodeArg arg[],
|
|||
const uint32_t par[])
|
||||
{
|
||||
TCGv_i32 addr = tcg_temp_new_i32();
|
||||
MemOp mop;
|
||||
|
||||
tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
|
||||
gen_load_store_alignment(dc, 2, addr, false);
|
||||
tcg_gen_qemu_st_tl(arg[0].in, addr, dc->ring, MO_TEUL);
|
||||
mop = gen_load_store_alignment(dc, MO_TEUL, addr);
|
||||
tcg_gen_qemu_st_tl(arg[0].in, addr, dc->ring, mop);
|
||||
tcg_temp_free(addr);
|
||||
}
|
||||
|
||||
|
@ -2389,14 +2378,15 @@ static void translate_s32ex(DisasContext *dc, const OpcodeArg arg[],
|
|||
TCGv_i32 addr = tcg_temp_local_new_i32();
|
||||
TCGv_i32 res = tcg_temp_local_new_i32();
|
||||
TCGLabel *label = gen_new_label();
|
||||
MemOp mop;
|
||||
|
||||
tcg_gen_movi_i32(res, 0);
|
||||
tcg_gen_mov_i32(addr, arg[1].in);
|
||||
gen_load_store_alignment(dc, 2, addr, true);
|
||||
mop = gen_load_store_alignment(dc, MO_TEUL | MO_ALIGN, addr);
|
||||
tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, label);
|
||||
gen_check_exclusive(dc, addr, true);
|
||||
tcg_gen_atomic_cmpxchg_i32(prev, cpu_exclusive_addr, cpu_exclusive_val,
|
||||
arg[0].in, dc->cring, MO_TEUL);
|
||||
arg[0].in, dc->cring, mop);
|
||||
tcg_gen_setcond_i32(TCG_COND_EQ, res, prev, cpu_exclusive_val);
|
||||
tcg_gen_movcond_i32(TCG_COND_EQ, cpu_exclusive_val,
|
||||
prev, cpu_exclusive_val, prev, cpu_exclusive_val);
|
||||
|
@ -3383,7 +3373,7 @@ static const XtensaOpcodeOps core_ops[] = {
|
|||
}, {
|
||||
.name = "l32ai",
|
||||
.translate = translate_ldst,
|
||||
.par = (const uint32_t[]){MO_TEUL, true, false},
|
||||
.par = (const uint32_t[]){MO_TEUL | MO_ALIGN, true, false},
|
||||
.op_flags = XTENSA_OP_LOAD,
|
||||
}, {
|
||||
.name = "l32e",
|
||||
|
@ -4710,7 +4700,7 @@ static const XtensaOpcodeOps core_ops[] = {
|
|||
}, {
|
||||
.name = "s32ri",
|
||||
.translate = translate_ldst,
|
||||
.par = (const uint32_t[]){MO_TEUL, true, true},
|
||||
.par = (const uint32_t[]){MO_TEUL | MO_ALIGN, true, true},
|
||||
.op_flags = XTENSA_OP_STORE,
|
||||
}, {
|
||||
.name = "s8i",
|
||||
|
@ -6645,13 +6635,14 @@ static void translate_ldsti(DisasContext *dc, const OpcodeArg arg[],
|
|||
const uint32_t par[])
|
||||
{
|
||||
TCGv_i32 addr = tcg_temp_new_i32();
|
||||
MemOp mop;
|
||||
|
||||
tcg_gen_addi_i32(addr, arg[1].in, arg[2].imm);
|
||||
gen_load_store_alignment(dc, 2, addr, false);
|
||||
mop = gen_load_store_alignment(dc, MO_TEUL, addr);
|
||||
if (par[0]) {
|
||||
tcg_gen_qemu_st32(arg[0].in, addr, dc->cring);
|
||||
tcg_gen_qemu_st_tl(arg[0].in, addr, dc->cring, mop);
|
||||
} else {
|
||||
tcg_gen_qemu_ld32u(arg[0].out, addr, dc->cring);
|
||||
tcg_gen_qemu_ld_tl(arg[0].out, addr, dc->cring, mop);
|
||||
}
|
||||
if (par[1]) {
|
||||
tcg_gen_mov_i32(arg[1].out, addr);
|
||||
|
@ -6663,13 +6654,14 @@ static void translate_ldstx(DisasContext *dc, const OpcodeArg arg[],
|
|||
const uint32_t par[])
|
||||
{
|
||||
TCGv_i32 addr = tcg_temp_new_i32();
|
||||
MemOp mop;
|
||||
|
||||
tcg_gen_add_i32(addr, arg[1].in, arg[2].in);
|
||||
gen_load_store_alignment(dc, 2, addr, false);
|
||||
mop = gen_load_store_alignment(dc, MO_TEUL, addr);
|
||||
if (par[0]) {
|
||||
tcg_gen_qemu_st32(arg[0].in, addr, dc->cring);
|
||||
tcg_gen_qemu_st_tl(arg[0].in, addr, dc->cring, mop);
|
||||
} else {
|
||||
tcg_gen_qemu_ld32u(arg[0].out, addr, dc->cring);
|
||||
tcg_gen_qemu_ld_tl(arg[0].out, addr, dc->cring, mop);
|
||||
}
|
||||
if (par[1]) {
|
||||
tcg_gen_mov_i32(arg[1].out, addr);
|
||||
|
@ -7107,6 +7099,7 @@ static void translate_ldsti_d(DisasContext *dc, const OpcodeArg arg[],
|
|||
const uint32_t par[])
|
||||
{
|
||||
TCGv_i32 addr;
|
||||
MemOp mop;
|
||||
|
||||
if (par[1]) {
|
||||
addr = tcg_temp_new_i32();
|
||||
|
@ -7114,11 +7107,11 @@ static void translate_ldsti_d(DisasContext *dc, const OpcodeArg arg[],
|
|||
} else {
|
||||
addr = arg[1].in;
|
||||
}
|
||||
gen_load_store_alignment(dc, 3, addr, false);
|
||||
mop = gen_load_store_alignment(dc, MO_TEQ, addr);
|
||||
if (par[0]) {
|
||||
tcg_gen_qemu_st64(arg[0].in, addr, dc->cring);
|
||||
tcg_gen_qemu_st_i64(arg[0].in, addr, dc->cring, mop);
|
||||
} else {
|
||||
tcg_gen_qemu_ld64(arg[0].out, addr, dc->cring);
|
||||
tcg_gen_qemu_ld_i64(arg[0].out, addr, dc->cring, mop);
|
||||
}
|
||||
if (par[2]) {
|
||||
if (par[1]) {
|
||||
|
@ -7137,6 +7130,7 @@ static void translate_ldsti_s(DisasContext *dc, const OpcodeArg arg[],
|
|||
{
|
||||
TCGv_i32 addr;
|
||||
OpcodeArg arg32[1];
|
||||
MemOp mop;
|
||||
|
||||
if (par[1]) {
|
||||
addr = tcg_temp_new_i32();
|
||||
|
@ -7144,14 +7138,14 @@ static void translate_ldsti_s(DisasContext *dc, const OpcodeArg arg[],
|
|||
} else {
|
||||
addr = arg[1].in;
|
||||
}
|
||||
gen_load_store_alignment(dc, 2, addr, false);
|
||||
mop = gen_load_store_alignment(dc, MO_TEUL, addr);
|
||||
if (par[0]) {
|
||||
get_f32_i1(arg, arg32, 0);
|
||||
tcg_gen_qemu_st32(arg32[0].in, addr, dc->cring);
|
||||
tcg_gen_qemu_st_tl(arg32[0].in, addr, dc->cring, mop);
|
||||
put_f32_i1(arg, arg32, 0);
|
||||
} else {
|
||||
get_f32_o1(arg, arg32, 0);
|
||||
tcg_gen_qemu_ld32u(arg32[0].out, addr, dc->cring);
|
||||
tcg_gen_qemu_ld_tl(arg32[0].out, addr, dc->cring, mop);
|
||||
put_f32_o1(arg, arg32, 0);
|
||||
}
|
||||
if (par[2]) {
|
||||
|
@ -7170,6 +7164,7 @@ static void translate_ldstx_d(DisasContext *dc, const OpcodeArg arg[],
|
|||
const uint32_t par[])
|
||||
{
|
||||
TCGv_i32 addr;
|
||||
MemOp mop;
|
||||
|
||||
if (par[1]) {
|
||||
addr = tcg_temp_new_i32();
|
||||
|
@ -7177,11 +7172,11 @@ static void translate_ldstx_d(DisasContext *dc, const OpcodeArg arg[],
|
|||
} else {
|
||||
addr = arg[1].in;
|
||||
}
|
||||
gen_load_store_alignment(dc, 3, addr, false);
|
||||
mop = gen_load_store_alignment(dc, MO_TEQ, addr);
|
||||
if (par[0]) {
|
||||
tcg_gen_qemu_st64(arg[0].in, addr, dc->cring);
|
||||
tcg_gen_qemu_st_i64(arg[0].in, addr, dc->cring, mop);
|
||||
} else {
|
||||
tcg_gen_qemu_ld64(arg[0].out, addr, dc->cring);
|
||||
tcg_gen_qemu_ld_i64(arg[0].out, addr, dc->cring, mop);
|
||||
}
|
||||
if (par[2]) {
|
||||
if (par[1]) {
|
||||
|
@ -7200,6 +7195,7 @@ static void translate_ldstx_s(DisasContext *dc, const OpcodeArg arg[],
|
|||
{
|
||||
TCGv_i32 addr;
|
||||
OpcodeArg arg32[1];
|
||||
MemOp mop;
|
||||
|
||||
if (par[1]) {
|
||||
addr = tcg_temp_new_i32();
|
||||
|
@ -7207,14 +7203,14 @@ static void translate_ldstx_s(DisasContext *dc, const OpcodeArg arg[],
|
|||
} else {
|
||||
addr = arg[1].in;
|
||||
}
|
||||
gen_load_store_alignment(dc, 2, addr, false);
|
||||
mop = gen_load_store_alignment(dc, MO_TEUL, addr);
|
||||
if (par[0]) {
|
||||
get_f32_i1(arg, arg32, 0);
|
||||
tcg_gen_qemu_st32(arg32[0].in, addr, dc->cring);
|
||||
tcg_gen_qemu_st_tl(arg32[0].in, addr, dc->cring, mop);
|
||||
put_f32_i1(arg, arg32, 0);
|
||||
} else {
|
||||
get_f32_o1(arg, arg32, 0);
|
||||
tcg_gen_qemu_ld32u(arg32[0].out, addr, dc->cring);
|
||||
tcg_gen_qemu_ld_tl(arg32[0].out, addr, dc->cring, mop);
|
||||
put_f32_o1(arg, arg32, 0);
|
||||
}
|
||||
if (par[2]) {
|
||||
|
|
|
@ -0,0 +1,221 @@
|
|||
#include "macros.inc"
|
||||
|
||||
test_suite load_store
|
||||
|
||||
.macro load_ok_test op, type, data, value
|
||||
.data
|
||||
.align 4
|
||||
1:
|
||||
\type \data
|
||||
.previous
|
||||
|
||||
reset_ps
|
||||
set_vector kernel, 0
|
||||
movi a3, 1b
|
||||
addi a4, a4, 1
|
||||
mov a5, a4
|
||||
\op a5, a3, 0
|
||||
movi a6, \value
|
||||
assert eq, a5, a6
|
||||
.endm
|
||||
|
||||
#if XCHAL_UNALIGNED_LOAD_EXCEPTION
|
||||
.macro load_unaligned_test will_trap, op, type, data, value
|
||||
.data
|
||||
.align 4
|
||||
.byte 0
|
||||
1:
|
||||
\type \data
|
||||
.previous
|
||||
|
||||
reset_ps
|
||||
.ifeq \will_trap
|
||||
set_vector kernel, 0
|
||||
.else
|
||||
set_vector kernel, 2f
|
||||
.endif
|
||||
movi a3, 1b
|
||||
addi a4, a4, 1
|
||||
mov a5, a4
|
||||
1:
|
||||
\op a5, a3, 0
|
||||
.ifeq \will_trap
|
||||
movi a6, \value
|
||||
assert eq, a5, a6
|
||||
.else
|
||||
test_fail
|
||||
2:
|
||||
rsr a6, exccause
|
||||
movi a7, 9
|
||||
assert eq, a6, a7
|
||||
rsr a6, epc1
|
||||
movi a7, 1b
|
||||
assert eq, a6, a7
|
||||
rsr a6, excvaddr
|
||||
assert eq, a6, a3
|
||||
assert eq, a5, a4
|
||||
.endif
|
||||
reset_ps
|
||||
.endm
|
||||
#else
|
||||
.macro load_unaligned_test will_trap, op, type, data, value
|
||||
.data
|
||||
.align 4
|
||||
1:
|
||||
\type \data
|
||||
.previous
|
||||
|
||||
reset_ps
|
||||
set_vector kernel, 0
|
||||
movi a3, 1b + 1
|
||||
addi a4, a4, 1
|
||||
mov a5, a4
|
||||
\op a5, a3, 0
|
||||
movi a6, \value
|
||||
assert eq, a5, a6
|
||||
.endm
|
||||
#endif
|
||||
|
||||
.macro store_ok_test op, type, value
|
||||
.data
|
||||
.align 4
|
||||
.byte 0, 0, 0, 0x55
|
||||
1:
|
||||
\type 0
|
||||
2:
|
||||
.byte 0xaa
|
||||
.previous
|
||||
|
||||
reset_ps
|
||||
set_vector kernel, 0
|
||||
movi a3, 1b
|
||||
movi a5, \value
|
||||
\op a5, a3, 0
|
||||
movi a3, 2b
|
||||
l8ui a5, a3, 0
|
||||
movi a6, 0xaa
|
||||
assert eq, a5, a6
|
||||
movi a3, 1b - 1
|
||||
l8ui a5, a3, 0
|
||||
movi a6, 0x55
|
||||
assert eq, a5, a6
|
||||
.endm
|
||||
|
||||
#if XCHAL_UNALIGNED_STORE_EXCEPTION
|
||||
.macro store_unaligned_test will_trap, op, nop, type, value
|
||||
.data
|
||||
.align 4
|
||||
.byte 0x55
|
||||
1:
|
||||
\type 0
|
||||
2:
|
||||
.byte 0xaa
|
||||
.previous
|
||||
|
||||
reset_ps
|
||||
.ifeq \will_trap
|
||||
set_vector kernel, 0
|
||||
.else
|
||||
set_vector kernel, 4f
|
||||
.endif
|
||||
movi a3, 1b
|
||||
movi a5, \value
|
||||
3:
|
||||
\op a5, a3, 0
|
||||
.ifne \will_trap
|
||||
test_fail
|
||||
4:
|
||||
rsr a6, exccause
|
||||
movi a7, 9
|
||||
assert eq, a6, a7
|
||||
rsr a6, epc1
|
||||
movi a7, 3b
|
||||
assert eq, a6, a7
|
||||
rsr a6, excvaddr
|
||||
assert eq, a6, a3
|
||||
l8ui a5, a3, 0
|
||||
assert eqi, a5, 0
|
||||
.endif
|
||||
reset_ps
|
||||
movi a3, 2b
|
||||
l8ui a5, a3, 0
|
||||
movi a6, 0xaa
|
||||
assert eq, a5, a6
|
||||
movi a3, 1b - 1
|
||||
l8ui a5, a3, 0
|
||||
movi a6, 0x55
|
||||
assert eq, a5, a6
|
||||
.endm
|
||||
#else
|
||||
.macro store_unaligned_test will_trap, sop, lop, type, value
|
||||
.data
|
||||
.align 4
|
||||
.byte 0x55
|
||||
1:
|
||||
\type 0
|
||||
.previous
|
||||
|
||||
reset_ps
|
||||
set_vector kernel, 0
|
||||
movi a3, 1b
|
||||
movi a5, \value
|
||||
\sop a5, a3, 0
|
||||
movi a3, 1b - 1
|
||||
\lop a6, a3, 0
|
||||
assert eq, a5, a6
|
||||
.endm
|
||||
#endif
|
||||
|
||||
test load_ok
|
||||
load_ok_test l16si, .short, 0x00001234, 0x00001234
|
||||
load_ok_test l16si, .short, 0x000089ab, 0xffff89ab
|
||||
load_ok_test l16ui, .short, 0x00001234, 0x00001234
|
||||
load_ok_test l16ui, .short, 0x000089ab, 0x000089ab
|
||||
load_ok_test l32i, .word, 0x12345678, 0x12345678
|
||||
#if XCHAL_HAVE_RELEASE_SYNC
|
||||
load_ok_test l32ai, .word, 0x12345678, 0x12345678
|
||||
#endif
|
||||
test_end
|
||||
|
||||
#undef WILL_TRAP
|
||||
#if XCHAL_UNALIGNED_LOAD_HW
|
||||
#define WILL_TRAP 0
|
||||
#else
|
||||
#define WILL_TRAP 1
|
||||
#endif
|
||||
|
||||
test load_unaligned
|
||||
load_unaligned_test WILL_TRAP, l16si, .short, 0x00001234, 0x00001234
|
||||
load_unaligned_test WILL_TRAP, l16si, .short, 0x000089ab, 0xffff89ab
|
||||
load_unaligned_test WILL_TRAP, l16ui, .short, 0x00001234, 0x00001234
|
||||
load_unaligned_test WILL_TRAP, l16ui, .short, 0x000089ab, 0x000089ab
|
||||
load_unaligned_test WILL_TRAP, l32i, .word, 0x12345678, 0x12345678
|
||||
#if XCHAL_HAVE_RELEASE_SYNC
|
||||
load_unaligned_test 1, l32ai, .word, 0x12345678, 0x12345678
|
||||
#endif
|
||||
test_end
|
||||
|
||||
test store_ok
|
||||
store_ok_test s16i, .short, 0x00001234
|
||||
store_ok_test s32i, .word, 0x12345678
|
||||
#if XCHAL_HAVE_RELEASE_SYNC
|
||||
store_ok_test s32ri, .word, 0x12345678
|
||||
#endif
|
||||
test_end
|
||||
|
||||
#undef WILL_TRAP
|
||||
#if XCHAL_UNALIGNED_STORE_HW
|
||||
#define WILL_TRAP 0
|
||||
#else
|
||||
#define WILL_TRAP 1
|
||||
#endif
|
||||
|
||||
test store_unaligned
|
||||
store_unaligned_test WILL_TRAP, s16i, l16ui, .short, 0x00001234
|
||||
store_unaligned_test WILL_TRAP, s32i, l32i, .word, 0x12345678
|
||||
#if XCHAL_HAVE_RELEASE_SYNC
|
||||
store_unaligned_test 1, s32ri, l32i, .word, 0x12345678
|
||||
#endif
|
||||
test_end
|
||||
|
||||
test_suite_end
|
Loading…
Reference in New Issue