|
@@ -1747,6 +1747,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|
tcg_out_nop(s);
|
|
tcg_out_nop(s);
|
|
s->tb_jmp_reset_offset[a0] = tcg_current_code_size(s);
|
|
s->tb_jmp_reset_offset[a0] = tcg_current_code_size(s);
|
|
break;
|
|
break;
|
|
|
|
+ case INDEX_op_goto_ptr:
|
|
|
|
+ /* jmp to the given host address (could be epilogue) */
|
|
|
|
+ tcg_out_opc_reg(s, OPC_JR, 0, a0, 0);
|
|
|
|
+ tcg_out_nop(s);
|
|
|
|
+ break;
|
|
case INDEX_op_br:
|
|
case INDEX_op_br:
|
|
tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO,
|
|
tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO,
|
|
arg_label(a0));
|
|
arg_label(a0));
|
|
@@ -2160,6 +2165,7 @@ static const TCGTargetOpDef mips_op_defs[] = {
|
|
{ INDEX_op_exit_tb, { } },
|
|
{ INDEX_op_exit_tb, { } },
|
|
{ INDEX_op_goto_tb, { } },
|
|
{ INDEX_op_goto_tb, { } },
|
|
{ INDEX_op_br, { } },
|
|
{ INDEX_op_br, { } },
|
|
|
|
+ { INDEX_op_goto_ptr, { "r" } },
|
|
|
|
|
|
{ INDEX_op_ld8u_i32, { "r", "r" } },
|
|
{ INDEX_op_ld8u_i32, { "r", "r" } },
|
|
{ INDEX_op_ld8s_i32, { "r", "r" } },
|
|
{ INDEX_op_ld8s_i32, { "r", "r" } },
|
|
@@ -2451,6 +2457,13 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
|
/* delay slot */
|
|
/* delay slot */
|
|
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
|
tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
|
|
|
|
+ * and fall through to the rest of the epilogue.
|
|
|
|
+ */
|
|
|
|
+ s->code_gen_epilogue = s->code_ptr;
|
|
|
|
+ tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_V0, TCG_REG_ZERO);
|
|
|
|
+
|
|
/* TB epilogue */
|
|
/* TB epilogue */
|
|
tb_ret_addr = s->code_ptr;
|
|
tb_ret_addr = s->code_ptr;
|
|
for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
|
|
for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
|