|
@@ -708,11 +708,18 @@ static void record_unaligned_ess(DisasContext *dc, int rd,
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+static inline MemOp mo_endian(DisasContext *dc)
|
|
|
+{
|
|
|
+ return dc->cfg->endi ? MO_LE : MO_BE;
|
|
|
+}
|
|
|
+
|
|
|
static bool do_load(DisasContext *dc, int rd, TCGv addr, MemOp mop,
|
|
|
int mem_index, bool rev)
|
|
|
{
|
|
|
MemOp size = mop & MO_SIZE;
|
|
|
|
|
|
+ mop |= mo_endian(dc);
|
|
|
+
|
|
|
/*
|
|
|
* When doing reverse accesses we need to do two things.
|
|
|
*
|
|
@@ -780,13 +787,13 @@ static bool trans_lbui(DisasContext *dc, arg_typeb *arg)
|
|
|
static bool trans_lhu(DisasContext *dc, arg_typea *arg)
|
|
|
{
|
|
|
TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
|
|
|
- return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
|
|
|
+ return do_load(dc, arg->rd, addr, MO_UW, dc->mem_index, false);
|
|
|
}
|
|
|
|
|
|
static bool trans_lhur(DisasContext *dc, arg_typea *arg)
|
|
|
{
|
|
|
TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
|
|
|
- return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, true);
|
|
|
+ return do_load(dc, arg->rd, addr, MO_UW, dc->mem_index, true);
|
|
|
}
|
|
|
|
|
|
static bool trans_lhuea(DisasContext *dc, arg_typea *arg)
|
|
@@ -798,26 +805,26 @@ static bool trans_lhuea(DisasContext *dc, arg_typea *arg)
|
|
|
return true;
|
|
|
#else
|
|
|
TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
|
|
|
- return do_load(dc, arg->rd, addr, MO_TEUW, MMU_NOMMU_IDX, false);
|
|
|
+ return do_load(dc, arg->rd, addr, MO_UW, MMU_NOMMU_IDX, false);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
static bool trans_lhui(DisasContext *dc, arg_typeb *arg)
|
|
|
{
|
|
|
TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
|
|
|
- return do_load(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
|
|
|
+ return do_load(dc, arg->rd, addr, MO_UW, dc->mem_index, false);
|
|
|
}
|
|
|
|
|
|
static bool trans_lw(DisasContext *dc, arg_typea *arg)
|
|
|
{
|
|
|
TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
|
|
|
- return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
|
|
|
+ return do_load(dc, arg->rd, addr, MO_UL, dc->mem_index, false);
|
|
|
}
|
|
|
|
|
|
static bool trans_lwr(DisasContext *dc, arg_typea *arg)
|
|
|
{
|
|
|
TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
|
|
|
- return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, true);
|
|
|
+ return do_load(dc, arg->rd, addr, MO_UL, dc->mem_index, true);
|
|
|
}
|
|
|
|
|
|
static bool trans_lwea(DisasContext *dc, arg_typea *arg)
|
|
@@ -829,14 +836,14 @@ static bool trans_lwea(DisasContext *dc, arg_typea *arg)
|
|
|
return true;
|
|
|
#else
|
|
|
TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
|
|
|
- return do_load(dc, arg->rd, addr, MO_TEUL, MMU_NOMMU_IDX, false);
|
|
|
+ return do_load(dc, arg->rd, addr, MO_UL, MMU_NOMMU_IDX, false);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
static bool trans_lwi(DisasContext *dc, arg_typeb *arg)
|
|
|
{
|
|
|
TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
|
|
|
- return do_load(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
|
|
|
+ return do_load(dc, arg->rd, addr, MO_UL, dc->mem_index, false);
|
|
|
}
|
|
|
|
|
|
static bool trans_lwx(DisasContext *dc, arg_typea *arg)
|
|
@@ -846,7 +853,8 @@ static bool trans_lwx(DisasContext *dc, arg_typea *arg)
|
|
|
/* lwx does not throw unaligned access errors, so force alignment */
|
|
|
tcg_gen_andi_tl(addr, addr, ~3);
|
|
|
|
|
|
- tcg_gen_qemu_ld_i32(cpu_res_val, addr, dc->mem_index, MO_TEUL);
|
|
|
+ tcg_gen_qemu_ld_i32(cpu_res_val, addr, dc->mem_index,
|
|
|
+ mo_endian(dc) | MO_UL);
|
|
|
tcg_gen_mov_tl(cpu_res_addr, addr);
|
|
|
|
|
|
if (arg->rd) {
|
|
@@ -863,6 +871,8 @@ static bool do_store(DisasContext *dc, int rd, TCGv addr, MemOp mop,
|
|
|
{
|
|
|
MemOp size = mop & MO_SIZE;
|
|
|
|
|
|
+ mop |= mo_endian(dc);
|
|
|
+
|
|
|
/*
|
|
|
* When doing reverse accesses we need to do two things.
|
|
|
*
|
|
@@ -930,13 +940,13 @@ static bool trans_sbi(DisasContext *dc, arg_typeb *arg)
|
|
|
static bool trans_sh(DisasContext *dc, arg_typea *arg)
|
|
|
{
|
|
|
TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
|
|
|
- return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
|
|
|
+ return do_store(dc, arg->rd, addr, MO_UW, dc->mem_index, false);
|
|
|
}
|
|
|
|
|
|
static bool trans_shr(DisasContext *dc, arg_typea *arg)
|
|
|
{
|
|
|
TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
|
|
|
- return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, true);
|
|
|
+ return do_store(dc, arg->rd, addr, MO_UW, dc->mem_index, true);
|
|
|
}
|
|
|
|
|
|
static bool trans_shea(DisasContext *dc, arg_typea *arg)
|
|
@@ -948,26 +958,26 @@ static bool trans_shea(DisasContext *dc, arg_typea *arg)
|
|
|
return true;
|
|
|
#else
|
|
|
TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
|
|
|
- return do_store(dc, arg->rd, addr, MO_TEUW, MMU_NOMMU_IDX, false);
|
|
|
+ return do_store(dc, arg->rd, addr, MO_UW, MMU_NOMMU_IDX, false);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
static bool trans_shi(DisasContext *dc, arg_typeb *arg)
|
|
|
{
|
|
|
TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
|
|
|
- return do_store(dc, arg->rd, addr, MO_TEUW, dc->mem_index, false);
|
|
|
+ return do_store(dc, arg->rd, addr, MO_UW, dc->mem_index, false);
|
|
|
}
|
|
|
|
|
|
static bool trans_sw(DisasContext *dc, arg_typea *arg)
|
|
|
{
|
|
|
TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
|
|
|
- return do_store(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
|
|
|
+ return do_store(dc, arg->rd, addr, MO_UL, dc->mem_index, false);
|
|
|
}
|
|
|
|
|
|
static bool trans_swr(DisasContext *dc, arg_typea *arg)
|
|
|
{
|
|
|
TCGv addr = compute_ldst_addr_typea(dc, arg->ra, arg->rb);
|
|
|
- return do_store(dc, arg->rd, addr, MO_TEUL, dc->mem_index, true);
|
|
|
+ return do_store(dc, arg->rd, addr, MO_UL, dc->mem_index, true);
|
|
|
}
|
|
|
|
|
|
static bool trans_swea(DisasContext *dc, arg_typea *arg)
|
|
@@ -979,14 +989,14 @@ static bool trans_swea(DisasContext *dc, arg_typea *arg)
|
|
|
return true;
|
|
|
#else
|
|
|
TCGv addr = compute_ldst_addr_ea(dc, arg->ra, arg->rb);
|
|
|
- return do_store(dc, arg->rd, addr, MO_TEUL, MMU_NOMMU_IDX, false);
|
|
|
+ return do_store(dc, arg->rd, addr, MO_UL, MMU_NOMMU_IDX, false);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
static bool trans_swi(DisasContext *dc, arg_typeb *arg)
|
|
|
{
|
|
|
TCGv addr = compute_ldst_addr_typeb(dc, arg->ra, arg->imm);
|
|
|
- return do_store(dc, arg->rd, addr, MO_TEUL, dc->mem_index, false);
|
|
|
+ return do_store(dc, arg->rd, addr, MO_UL, dc->mem_index, false);
|
|
|
}
|
|
|
|
|
|
static bool trans_swx(DisasContext *dc, arg_typea *arg)
|
|
@@ -1015,7 +1025,7 @@ static bool trans_swx(DisasContext *dc, arg_typea *arg)
|
|
|
|
|
|
tcg_gen_atomic_cmpxchg_i32(tval, cpu_res_addr, cpu_res_val,
|
|
|
reg_for_write(dc, arg->rd),
|
|
|
- dc->mem_index, MO_TEUL);
|
|
|
+ dc->mem_index, mo_endian(dc) | MO_UL);
|
|
|
|
|
|
tcg_gen_brcond_i32(TCG_COND_NE, cpu_res_val, tval, swx_fail);
|
|
|
|
|
@@ -1637,7 +1647,8 @@ static void mb_tr_translate_insn(DisasContextBase *dcb, CPUState *cs)
|
|
|
|
|
|
dc->tb_flags_to_set = 0;
|
|
|
|
|
|
- ir = translator_ldl(cpu_env(cs), &dc->base, dc->base.pc_next);
|
|
|
+ ir = translator_ldl_swap(cpu_env(cs), &dc->base, dc->base.pc_next,
|
|
|
+ mb_cpu_is_big_endian(cs) != TARGET_BIG_ENDIAN);
|
|
|
if (!decode(dc, ir)) {
|
|
|
trap_illegal(dc, true);
|
|
|
}
|