target/mips: Add emulation of nanoMIPS 16-bit save and restore instructions
Add emulation of SAVE16 and RESTORE.JRC16 instructions. Routines gen_save(), gen_restore(), and gen_adjust_sp() are provided to support this feature. This patch at the same time provides function gen_op_addr_addi(). This function will be used in emulation of some other nanoMIPS instructions. Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Yongbok Kim <yongbok.kim@mips.com> Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com> Signed-off-by: Stefan Markovic <smarkovic@wavecomp.com>
This commit is contained in:
parent
80845edf37
commit
bf0718c59a
@ -1746,6 +1746,18 @@ static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
|
||||
target_long ofs)
|
||||
{
|
||||
tcg_gen_addi_tl(ret, base, ofs);
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
if (ctx->hflags & MIPS_HFLAG_AWRAP) {
|
||||
tcg_gen_ext32s_i64(ret, ret);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Addresses computation (translation time) */
|
||||
static target_long addr_add(DisasContext *ctx, target_long base,
|
||||
target_long offset)
|
||||
@ -16770,6 +16782,62 @@ static inline int decode_gpr_gpr4_zero(int r)
|
||||
#define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
|
||||
|
||||
|
||||
static void gen_adjust_sp(DisasContext *ctx, int u)
|
||||
{
|
||||
gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
|
||||
}
|
||||
|
||||
static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
|
||||
uint8_t gp, uint16_t u)
|
||||
{
|
||||
int counter = 0;
|
||||
TCGv va = tcg_temp_new();
|
||||
TCGv t0 = tcg_temp_new();
|
||||
|
||||
while (counter != count) {
|
||||
bool use_gp = gp && (counter == count - 1);
|
||||
int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
|
||||
int this_offset = -((counter + 1) << 2);
|
||||
gen_base_offset_addr(ctx, va, 29, this_offset);
|
||||
gen_load_gpr(t0, this_rt);
|
||||
tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
|
||||
(MO_TEUL | ctx->default_tcg_memop_mask));
|
||||
counter++;
|
||||
}
|
||||
|
||||
/* adjust stack pointer */
|
||||
gen_adjust_sp(ctx, -u);
|
||||
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(va);
|
||||
}
|
||||
|
||||
static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
|
||||
uint8_t gp, uint16_t u)
|
||||
{
|
||||
int counter = 0;
|
||||
TCGv va = tcg_temp_new();
|
||||
TCGv t0 = tcg_temp_new();
|
||||
|
||||
while (counter != count) {
|
||||
bool use_gp = gp && (counter == count - 1);
|
||||
int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
|
||||
int this_offset = u - ((counter + 1) << 2);
|
||||
gen_base_offset_addr(ctx, va, 29, this_offset);
|
||||
tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
|
||||
ctx->default_tcg_memop_mask);
|
||||
tcg_gen_ext32s_tl(t0, t0);
|
||||
gen_store_gpr(t0, this_rt);
|
||||
counter++;
|
||||
}
|
||||
|
||||
/* adjust stack pointer */
|
||||
gen_adjust_sp(ctx, u);
|
||||
|
||||
tcg_temp_free(t0);
|
||||
tcg_temp_free(va);
|
||||
}
|
||||
|
||||
static void gen_pool16c_nanomips_insn(DisasContext *ctx)
|
||||
{
|
||||
int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
|
||||
@ -17087,6 +17155,21 @@ static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
|
||||
}
|
||||
break;
|
||||
case NM_P16_SR:
|
||||
{
|
||||
int count = extract32(ctx->opcode, 0, 4);
|
||||
int u = extract32(ctx->opcode, 4, 4) << 4;
|
||||
|
||||
rt = 30 + extract32(ctx->opcode, 9, 1);
|
||||
switch (extract32(ctx->opcode, 8, 1)) {
|
||||
case NM_SAVE16:
|
||||
gen_save(ctx, rt, count, 0, u);
|
||||
break;
|
||||
case NM_RESTORE_JRC16:
|
||||
gen_restore(ctx, rt, count, 0, u);
|
||||
gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NM_MOVEP:
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user