mirror of https://gitee.com/openkylin/qemu.git
target/openrisc: Convert memory insns
Acked-by: Stafford Horne <shorne@gmail.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
136e13ae65
commit
d80bff19f9
|
@ -38,3 +38,27 @@ l_bf 000100 n:s26
|
|||
|
||||
l_jr 010001 ---------- b:5 -----------
|
||||
l_jalr 010010 ---------- b:5 -----------
|
||||
|
||||
####
|
||||
# Memory Instructions
|
||||
####
|
||||
|
||||
&load d a i
|
||||
@load ...... d:5 a:5 i:s16 &load
|
||||
|
||||
%store_i 21:s5 0:11
|
||||
&store a b i
|
||||
@store ...... ..... a:5 b:5 ........... &store i=%store_i
|
||||
|
||||
l_lwa 011011 ..... ..... ........ ........ @load
|
||||
l_lwz 100001 ..... ..... ........ ........ @load
|
||||
l_lws 100010 ..... ..... ........ ........ @load
|
||||
l_lbz 100011 ..... ..... ........ ........ @load
|
||||
l_lbs 100100 ..... ..... ........ ........ @load
|
||||
l_lhz 100101 ..... ..... ........ ........ @load
|
||||
l_lhs 100110 ..... ..... ........ ........ @load
|
||||
|
||||
l_swa 110011 ..... ..... ........ ........ @store
|
||||
l_sw 110101 ..... ..... ........ ........ @store
|
||||
l_sb 110110 ..... ..... ........ ........ @store
|
||||
l_sh 110111 ..... ..... ........ ........ @store
|
||||
|
|
|
@ -455,51 +455,6 @@ static void gen_msbu(DisasContext *dc, TCGv srca, TCGv srcb)
|
|||
gen_ove_cy(dc);
|
||||
}
|
||||
|
||||
static void gen_lwa(DisasContext *dc, TCGv rd, TCGv ra, int32_t ofs)
|
||||
{
|
||||
TCGv ea = tcg_temp_new();
|
||||
|
||||
tcg_gen_addi_tl(ea, ra, ofs);
|
||||
tcg_gen_qemu_ld_tl(rd, ea, dc->mem_idx, MO_TEUL);
|
||||
tcg_gen_mov_tl(cpu_lock_addr, ea);
|
||||
tcg_gen_mov_tl(cpu_lock_value, rd);
|
||||
tcg_temp_free(ea);
|
||||
}
|
||||
|
||||
static void gen_swa(DisasContext *dc, int b, TCGv ra, int32_t ofs)
|
||||
{
|
||||
TCGv ea, val;
|
||||
TCGLabel *lab_fail, *lab_done;
|
||||
|
||||
ea = tcg_temp_new();
|
||||
tcg_gen_addi_tl(ea, ra, ofs);
|
||||
|
||||
/* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
|
||||
to cpu_R[0]. Since l.swa is quite often immediately followed by a
|
||||
branch, don't bother reallocating; finish the TB using the "real" R0.
|
||||
This also takes care of RB input across the branch. */
|
||||
cpu_R[0] = cpu_R0;
|
||||
|
||||
lab_fail = gen_new_label();
|
||||
lab_done = gen_new_label();
|
||||
tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
|
||||
tcg_temp_free(ea);
|
||||
|
||||
val = tcg_temp_new();
|
||||
tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
|
||||
cpu_R[b], dc->mem_idx, MO_TEUL);
|
||||
tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
|
||||
tcg_temp_free(val);
|
||||
|
||||
tcg_gen_br(lab_done);
|
||||
|
||||
gen_set_label(lab_fail);
|
||||
tcg_gen_movi_tl(cpu_sr_f, 0);
|
||||
|
||||
gen_set_label(lab_done);
|
||||
tcg_gen_movi_tl(cpu_lock_addr, -1);
|
||||
}
|
||||
|
||||
static void dec_calc(DisasContext *dc, uint32_t insn)
|
||||
{
|
||||
uint32_t op0, op1, op2;
|
||||
|
@ -738,13 +693,147 @@ static bool trans_l_jalr(DisasContext *dc, arg_l_jalr *a, uint32_t insn)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool trans_l_lwa(DisasContext *dc, arg_load *a, uint32_t insn)
|
||||
{
|
||||
TCGv ea;
|
||||
|
||||
LOG_DIS("l.lwa r%d, r%d, %d\n", a->d, a->a, a->i);
|
||||
|
||||
check_r0_write(a->d);
|
||||
ea = tcg_temp_new();
|
||||
tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
|
||||
tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, MO_TEUL);
|
||||
tcg_gen_mov_tl(cpu_lock_addr, ea);
|
||||
tcg_gen_mov_tl(cpu_lock_value, cpu_R[a->d]);
|
||||
tcg_temp_free(ea);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void do_load(DisasContext *dc, arg_load *a, TCGMemOp mop)
|
||||
{
|
||||
TCGv ea;
|
||||
|
||||
check_r0_write(a->d);
|
||||
ea = tcg_temp_new();
|
||||
tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
|
||||
tcg_gen_qemu_ld_tl(cpu_R[a->d], ea, dc->mem_idx, mop);
|
||||
tcg_temp_free(ea);
|
||||
}
|
||||
|
||||
static bool trans_l_lwz(DisasContext *dc, arg_load *a, uint32_t insn)
|
||||
{
|
||||
LOG_DIS("l.lwz r%d, r%d, %d\n", a->d, a->a, a->i);
|
||||
do_load(dc, a, MO_TEUL);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_l_lws(DisasContext *dc, arg_load *a, uint32_t insn)
|
||||
{
|
||||
LOG_DIS("l.lws r%d, r%d, %d\n", a->d, a->a, a->i);
|
||||
do_load(dc, a, MO_TESL);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_l_lbz(DisasContext *dc, arg_load *a, uint32_t insn)
|
||||
{
|
||||
LOG_DIS("l.lbz r%d, r%d, %d\n", a->d, a->a, a->i);
|
||||
do_load(dc, a, MO_UB);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_l_lbs(DisasContext *dc, arg_load *a, uint32_t insn)
|
||||
{
|
||||
LOG_DIS("l.lbs r%d, r%d, %d\n", a->d, a->a, a->i);
|
||||
do_load(dc, a, MO_SB);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_l_lhz(DisasContext *dc, arg_load *a, uint32_t insn)
|
||||
{
|
||||
LOG_DIS("l.lhz r%d, r%d, %d\n", a->d, a->a, a->i);
|
||||
do_load(dc, a, MO_TEUW);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_l_lhs(DisasContext *dc, arg_load *a, uint32_t insn)
|
||||
{
|
||||
LOG_DIS("l.lhs r%d, r%d, %d\n", a->d, a->a, a->i);
|
||||
do_load(dc, a, MO_TESW);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_l_swa(DisasContext *dc, arg_store *a, uint32_t insn)
|
||||
{
|
||||
TCGv ea, val;
|
||||
TCGLabel *lab_fail, *lab_done;
|
||||
|
||||
LOG_DIS("l.swa r%d, r%d, %d\n", a->a, a->b, a->i);
|
||||
|
||||
ea = tcg_temp_new();
|
||||
tcg_gen_addi_tl(ea, cpu_R[a->a], a->i);
|
||||
|
||||
/* For TB_FLAGS_R0_0, the branch below invalidates the temporary assigned
|
||||
to cpu_R[0]. Since l.swa is quite often immediately followed by a
|
||||
branch, don't bother reallocating; finish the TB using the "real" R0.
|
||||
This also takes care of RB input across the branch. */
|
||||
cpu_R[0] = cpu_R0;
|
||||
|
||||
lab_fail = gen_new_label();
|
||||
lab_done = gen_new_label();
|
||||
tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_lock_addr, lab_fail);
|
||||
tcg_temp_free(ea);
|
||||
|
||||
val = tcg_temp_new();
|
||||
tcg_gen_atomic_cmpxchg_tl(val, cpu_lock_addr, cpu_lock_value,
|
||||
cpu_R[a->b], dc->mem_idx, MO_TEUL);
|
||||
tcg_gen_setcond_tl(TCG_COND_EQ, cpu_sr_f, val, cpu_lock_value);
|
||||
tcg_temp_free(val);
|
||||
|
||||
tcg_gen_br(lab_done);
|
||||
|
||||
gen_set_label(lab_fail);
|
||||
tcg_gen_movi_tl(cpu_sr_f, 0);
|
||||
|
||||
gen_set_label(lab_done);
|
||||
tcg_gen_movi_tl(cpu_lock_addr, -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void do_store(DisasContext *dc, arg_store *a, TCGMemOp mop)
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
tcg_gen_addi_tl(t0, cpu_R[a->a], a->i);
|
||||
tcg_gen_qemu_st_tl(cpu_R[a->b], t0, dc->mem_idx, mop);
|
||||
tcg_temp_free(t0);
|
||||
}
|
||||
|
||||
static bool trans_l_sw(DisasContext *dc, arg_store *a, uint32_t insn)
|
||||
{
|
||||
LOG_DIS("l.sw r%d, r%d, %d\n", a->a, a->b, a->i);
|
||||
do_store(dc, a, MO_TEUL);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_l_sb(DisasContext *dc, arg_store *a, uint32_t insn)
|
||||
{
|
||||
LOG_DIS("l.sb r%d, r%d, %d\n", a->a, a->b, a->i);
|
||||
do_store(dc, a, MO_UB);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_l_sh(DisasContext *dc, arg_store *a, uint32_t insn)
|
||||
{
|
||||
LOG_DIS("l.sh r%d, r%d, %d\n", a->a, a->b, a->i);
|
||||
do_store(dc, a, MO_TEUW);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void dec_misc(DisasContext *dc, uint32_t insn)
|
||||
{
|
||||
uint32_t op0, op1;
|
||||
uint32_t ra, rb, rd;
|
||||
uint32_t L6, K5, K16, K5_11;
|
||||
int32_t I16, I5_11;
|
||||
TCGMemOp mop;
|
||||
int32_t I16;
|
||||
TCGv t0;
|
||||
|
||||
op0 = extract32(insn, 26, 6);
|
||||
|
@ -757,7 +846,6 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
|
|||
K16 = extract32(insn, 0, 16);
|
||||
I16 = (int16_t)K16;
|
||||
K5_11 = (extract32(insn, 21, 5) << 11) | extract32(insn, 0, 11);
|
||||
I5_11 = (int16_t)K5_11;
|
||||
|
||||
switch (op0) {
|
||||
case 0x05:
|
||||
|
@ -795,12 +883,6 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
|
|||
}
|
||||
break;
|
||||
|
||||
case 0x1b: /* l.lwa */
|
||||
LOG_DIS("l.lwa r%d, r%d, %d\n", rd, ra, I16);
|
||||
check_r0_write(rd);
|
||||
gen_lwa(dc, cpu_R[rd], cpu_R[ra], I16);
|
||||
break;
|
||||
|
||||
case 0x1c: /* l.cust1 */
|
||||
LOG_DIS("l.cust1\n");
|
||||
break;
|
||||
|
@ -833,53 +915,6 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
|
|||
LOG_DIS("l.cust8\n");
|
||||
break;
|
||||
|
||||
/* not used yet, open it when we need or64. */
|
||||
/*#ifdef TARGET_OPENRISC64
|
||||
case 0x20: l.ld
|
||||
LOG_DIS("l.ld r%d, r%d, %d\n", rd, ra, I16);
|
||||
check_ob64s(dc);
|
||||
mop = MO_TEQ;
|
||||
goto do_load;
|
||||
#endif*/
|
||||
|
||||
case 0x21: /* l.lwz */
|
||||
LOG_DIS("l.lwz r%d, r%d, %d\n", rd, ra, I16);
|
||||
mop = MO_TEUL;
|
||||
goto do_load;
|
||||
|
||||
case 0x22: /* l.lws */
|
||||
LOG_DIS("l.lws r%d, r%d, %d\n", rd, ra, I16);
|
||||
mop = MO_TESL;
|
||||
goto do_load;
|
||||
|
||||
case 0x23: /* l.lbz */
|
||||
LOG_DIS("l.lbz r%d, r%d, %d\n", rd, ra, I16);
|
||||
mop = MO_UB;
|
||||
goto do_load;
|
||||
|
||||
case 0x24: /* l.lbs */
|
||||
LOG_DIS("l.lbs r%d, r%d, %d\n", rd, ra, I16);
|
||||
mop = MO_SB;
|
||||
goto do_load;
|
||||
|
||||
case 0x25: /* l.lhz */
|
||||
LOG_DIS("l.lhz r%d, r%d, %d\n", rd, ra, I16);
|
||||
mop = MO_TEUW;
|
||||
goto do_load;
|
||||
|
||||
case 0x26: /* l.lhs */
|
||||
LOG_DIS("l.lhs r%d, r%d, %d\n", rd, ra, I16);
|
||||
mop = MO_TESW;
|
||||
goto do_load;
|
||||
|
||||
do_load:
|
||||
check_r0_write(rd);
|
||||
t0 = tcg_temp_new();
|
||||
tcg_gen_addi_tl(t0, cpu_R[ra], I16);
|
||||
tcg_gen_qemu_ld_tl(cpu_R[rd], t0, dc->mem_idx, mop);
|
||||
tcg_temp_free(t0);
|
||||
break;
|
||||
|
||||
case 0x27: /* l.addi */
|
||||
LOG_DIS("l.addi r%d, r%d, %d\n", rd, ra, I16);
|
||||
check_r0_write(rd);
|
||||
|
@ -957,44 +992,6 @@ static void dec_misc(DisasContext *dc, uint32_t insn)
|
|||
}
|
||||
break;
|
||||
|
||||
case 0x33: /* l.swa */
|
||||
LOG_DIS("l.swa r%d, r%d, %d\n", ra, rb, I5_11);
|
||||
gen_swa(dc, rb, cpu_R[ra], I5_11);
|
||||
break;
|
||||
|
||||
/* not used yet, open it when we need or64. */
|
||||
/*#ifdef TARGET_OPENRISC64
|
||||
case 0x34: l.sd
|
||||
LOG_DIS("l.sd r%d, r%d, %d\n", ra, rb, I5_11);
|
||||
check_ob64s(dc);
|
||||
mop = MO_TEQ;
|
||||
goto do_store;
|
||||
#endif*/
|
||||
|
||||
case 0x35: /* l.sw */
|
||||
LOG_DIS("l.sw r%d, r%d, %d\n", ra, rb, I5_11);
|
||||
mop = MO_TEUL;
|
||||
goto do_store;
|
||||
|
||||
case 0x36: /* l.sb */
|
||||
LOG_DIS("l.sb r%d, r%d, %d\n", ra, rb, I5_11);
|
||||
mop = MO_UB;
|
||||
goto do_store;
|
||||
|
||||
case 0x37: /* l.sh */
|
||||
LOG_DIS("l.sh r%d, r%d, %d\n", ra, rb, I5_11);
|
||||
mop = MO_TEUW;
|
||||
goto do_store;
|
||||
|
||||
do_store:
|
||||
{
|
||||
TCGv t0 = tcg_temp_new();
|
||||
tcg_gen_addi_tl(t0, cpu_R[ra], I5_11);
|
||||
tcg_gen_qemu_st_tl(cpu_R[rb], t0, dc->mem_idx, mop);
|
||||
tcg_temp_free(t0);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
gen_illegal_exception(dc);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue