提交 ab39ee45 编写于 作者: Y Yongbok Kim 提交者: Leon Alrae

target-mips: microMIPS32 R6 Major instructions

Add new microMIPS32 Release 6 Major opcode instructions
Signed-off-by: NYongbok Kim <yongbok.kim@imgtec.com>
Reviewed-by: NAurelien Jarno <aurelien@aurel32.net>
Signed-off-by: NLeon Alrae <leon.alrae@imgtec.com>
上级 3b4a5489
...@@ -3209,45 +3209,46 @@ static inline void gen_r6_ld(target_long addr, int reg, int memidx, ...@@ -3209,45 +3209,46 @@ static inline void gen_r6_ld(target_long addr, int reg, int memidx,
tcg_temp_free(t0); tcg_temp_free(t0);
} }
static inline void gen_pcrel(DisasContext *ctx, int rs, int16_t imm) static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
int rs)
{ {
target_long offset; target_long offset;
target_long addr; target_long addr;
switch (MASK_OPC_PCREL_TOP2BITS(ctx->opcode)) { switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
case OPC_ADDIUPC: case OPC_ADDIUPC:
if (rs != 0) { if (rs != 0) {
offset = sextract32(ctx->opcode << 2, 0, 21); offset = sextract32(ctx->opcode << 2, 0, 21);
addr = addr_add(ctx, ctx->pc, offset); addr = addr_add(ctx, pc, offset);
tcg_gen_movi_tl(cpu_gpr[rs], addr); tcg_gen_movi_tl(cpu_gpr[rs], addr);
} }
break; break;
case R6_OPC_LWPC: case R6_OPC_LWPC:
offset = sextract32(ctx->opcode << 2, 0, 21); offset = sextract32(ctx->opcode << 2, 0, 21);
addr = addr_add(ctx, ctx->pc, offset); addr = addr_add(ctx, pc, offset);
gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL); gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
break; break;
#if defined(TARGET_MIPS64) #if defined(TARGET_MIPS64)
case OPC_LWUPC: case OPC_LWUPC:
check_mips_64(ctx); check_mips_64(ctx);
offset = sextract32(ctx->opcode << 2, 0, 21); offset = sextract32(ctx->opcode << 2, 0, 21);
addr = addr_add(ctx, ctx->pc, offset); addr = addr_add(ctx, pc, offset);
gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL); gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
break; break;
#endif #endif
default: default:
switch (MASK_OPC_PCREL_TOP5BITS(ctx->opcode)) { switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
case OPC_AUIPC: case OPC_AUIPC:
if (rs != 0) { if (rs != 0) {
offset = imm << 16; offset = sextract32(ctx->opcode, 0, 16) << 16;
addr = addr_add(ctx, ctx->pc, offset); addr = addr_add(ctx, pc, offset);
tcg_gen_movi_tl(cpu_gpr[rs], addr); tcg_gen_movi_tl(cpu_gpr[rs], addr);
} }
break; break;
case OPC_ALUIPC: case OPC_ALUIPC:
if (rs != 0) { if (rs != 0) {
offset = imm << 16; offset = sextract32(ctx->opcode, 0, 16) << 16;
addr = ~0xFFFF & addr_add(ctx, ctx->pc, offset); addr = ~0xFFFF & addr_add(ctx, pc, offset);
tcg_gen_movi_tl(cpu_gpr[rs], addr); tcg_gen_movi_tl(cpu_gpr[rs], addr);
} }
break; break;
...@@ -3258,7 +3259,7 @@ static inline void gen_pcrel(DisasContext *ctx, int rs, int16_t imm) ...@@ -3258,7 +3259,7 @@ static inline void gen_pcrel(DisasContext *ctx, int rs, int16_t imm)
case R6_OPC_LDPC + (3 << 16): case R6_OPC_LDPC + (3 << 16):
check_mips_64(ctx); check_mips_64(ctx);
offset = sextract32(ctx->opcode << 3, 0, 21); offset = sextract32(ctx->opcode << 3, 0, 21);
addr = addr_add(ctx, (ctx->pc & ~0x7), offset); addr = addr_add(ctx, (pc & ~0x7), offset);
gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ); gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
break; break;
#endif #endif
...@@ -14837,9 +14838,16 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) ...@@ -14837,9 +14838,16 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
break; break;
} }
break; break;
case ADDI32: case ADDI32: /* AUI, LUI */
mips32_op = OPC_ADDI; if (ctx->insn_flags & ISA_MIPS32R6) {
goto do_addi; /* AUI, LUI */
gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
} else {
/* ADDI32 */
mips32_op = OPC_ADDI;
goto do_addi;
}
break;
case ADDIU32: case ADDIU32:
mips32_op = OPC_ADDIU; mips32_op = OPC_ADDIU;
do_addi: do_addi:
...@@ -14968,8 +14976,28 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx) ...@@ -14968,8 +14976,28 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
do_cop1: do_cop1:
gen_cop1_ldst(ctx, mips32_op, rt, rs, imm); gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
break; break;
case ADDIUPC: case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
{ if (ctx->insn_flags & ISA_MIPS32R6) {
/* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
switch ((ctx->opcode >> 16) & 0x1f) {
case ADDIUPC_00 ... ADDIUPC_07:
gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
break;
case AUIPC:
gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
break;
case ALUIPC:
gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
break;
case LWPC_08 ... LWPC_0F:
gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
break;
default:
generate_exception(ctx, EXCP_RI);
break;
}
} else {
/* ADDIUPC */
int reg = mmreg(ZIMM(ctx->opcode, 23, 3)); int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
int offset = SIMM(ctx->opcode, 0, 23) << 2; int offset = SIMM(ctx->opcode, 0, 23) << 2;
...@@ -19989,7 +20017,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) ...@@ -19989,7 +20017,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
break; break;
case OPC_PCREL: case OPC_PCREL:
check_insn(ctx, ISA_MIPS32R6); check_insn(ctx, ISA_MIPS32R6);
gen_pcrel(ctx, rs, imm); gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
break; break;
default: /* Invalid */ default: /* Invalid */
MIPS_INVAL("major opcode"); MIPS_INVAL("major opcode");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册