mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-03-24 22:15:07 +00:00
target/arm: [tcg] Port to tb_start
Incrementally paves the way towards using the generic instruction translation loop. Backports commit b14768544fd715a3f1742c10fc36ae81c703cbc1 from qemu
This commit is contained in:
parent
529c6c17f1
commit
b3878f117e
|
@ -12102,6 +12102,50 @@ static int arm_tr_init_disas_context(DisasContextBase *dcbase,
|
||||||
return max_insns;
|
return max_insns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
|
{
|
||||||
|
DisasContext *dc = container_of(dcbase, DisasContext, base);
|
||||||
|
TCGContext *tcg_ctx = cpu->uc->tcg_ctx;
|
||||||
|
|
||||||
|
/* A note on handling of the condexec (IT) bits:
|
||||||
|
*
|
||||||
|
* We want to avoid the overhead of having to write the updated condexec
|
||||||
|
* bits back to the CPUARMState for every instruction in an IT block. So:
|
||||||
|
* (1) if the condexec bits are not already zero then we write
|
||||||
|
* zero back into the CPUARMState now. This avoids complications trying
|
||||||
|
* to do it at the end of the block. (For example if we don't do this
|
||||||
|
* it's hard to identify whether we can safely skip writing condexec
|
||||||
|
* at the end of the TB, which we definitely want to do for the case
|
||||||
|
* where a TB doesn't do anything with the IT state at all.)
|
||||||
|
* (2) if we are going to leave the TB then we call gen_set_condexec()
|
||||||
|
* which will write the correct value into CPUARMState if zero is wrong.
|
||||||
|
* This is done both for leaving the TB at the end, and for leaving
|
||||||
|
* it because of an exception we know will happen, which is done in
|
||||||
|
* gen_exception_insn(). The latter is necessary because we need to
|
||||||
|
* leave the TB with the PC/IT state just prior to execution of the
|
||||||
|
* instruction which caused the exception.
|
||||||
|
* (3) if we leave the TB unexpectedly (eg a data abort on a load)
|
||||||
|
* then the CPUARMState will be wrong and we need to reset it.
|
||||||
|
* This is handled in the same way as restoration of the
|
||||||
|
* PC in these situations; we save the value of the condexec bits
|
||||||
|
* for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
|
||||||
|
* then uses this to restore them after an exception.
|
||||||
|
*
|
||||||
|
* Note that there are no instructions which can read the condexec
|
||||||
|
* bits, and none which can write non-static values to them, so
|
||||||
|
* we don't need to care about whether CPUARMState is correct in the
|
||||||
|
* middle of a TB.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Reset the conditional execution bits immediately. This avoids
|
||||||
|
complications trying to do it at the end of the block. */
|
||||||
|
if (dc->condexec_mask || dc->condexec_cond) {
|
||||||
|
TCGv_i32 tmp = tcg_temp_new_i32(tcg_ctx);
|
||||||
|
tcg_gen_movi_i32(tcg_ctx, tmp, 0);
|
||||||
|
store_cpu_field(tcg_ctx, tmp, condexec_bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* generate intermediate code for basic block 'tb'. */
|
/* generate intermediate code for basic block 'tb'. */
|
||||||
void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
|
void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
|
||||||
{
|
{
|
||||||
|
@ -12163,45 +12207,8 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
|
||||||
}
|
}
|
||||||
|
|
||||||
gen_tb_start(tcg_ctx, tb);
|
gen_tb_start(tcg_ctx, tb);
|
||||||
|
arm_tr_tb_start(&dc->base, cs);
|
||||||
|
|
||||||
/* A note on handling of the condexec (IT) bits:
|
|
||||||
*
|
|
||||||
* We want to avoid the overhead of having to write the updated condexec
|
|
||||||
* bits back to the CPUARMState for every instruction in an IT block. So:
|
|
||||||
* (1) if the condexec bits are not already zero then we write
|
|
||||||
* zero back into the CPUARMState now. This avoids complications trying
|
|
||||||
* to do it at the end of the block. (For example if we don't do this
|
|
||||||
* it's hard to identify whether we can safely skip writing condexec
|
|
||||||
* at the end of the TB, which we definitely want to do for the case
|
|
||||||
* where a TB doesn't do anything with the IT state at all.)
|
|
||||||
* (2) if we are going to leave the TB then we call gen_set_condexec()
|
|
||||||
* which will write the correct value into CPUARMState if zero is wrong.
|
|
||||||
* This is done both for leaving the TB at the end, and for leaving
|
|
||||||
* it because of an exception we know will happen, which is done in
|
|
||||||
* gen_exception_insn(). The latter is necessary because we need to
|
|
||||||
* leave the TB with the PC/IT state just prior to execution of the
|
|
||||||
* instruction which caused the exception.
|
|
||||||
* (3) if we leave the TB unexpectedly (eg a data abort on a load)
|
|
||||||
* then the CPUARMState will be wrong and we need to reset it.
|
|
||||||
* This is handled in the same way as restoration of the
|
|
||||||
* PC in these situations; we save the value of the condexec bits
|
|
||||||
* for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
|
|
||||||
* then uses this to restore them after an exception.
|
|
||||||
*
|
|
||||||
* Note that there are no instructions which can read the condexec
|
|
||||||
* bits, and none which can write non-static values to them, so
|
|
||||||
* we don't need to care about whether CPUARMState is correct in the
|
|
||||||
* middle of a TB.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Reset the conditional execution bits immediately. This avoids
|
|
||||||
complications trying to do it at the end of the block. */
|
|
||||||
if (dc->condexec_mask || dc->condexec_cond)
|
|
||||||
{
|
|
||||||
TCGv_i32 tmp = tcg_temp_new_i32(tcg_ctx);
|
|
||||||
tcg_gen_movi_i32(tcg_ctx, tmp, 0);
|
|
||||||
store_cpu_field(tcg_ctx, tmp, condexec_bits);
|
|
||||||
}
|
|
||||||
do {
|
do {
|
||||||
dc->base.num_insns++;
|
dc->base.num_insns++;
|
||||||
dc->insn_start_idx = tcg_op_buf_count(tcg_ctx);
|
dc->insn_start_idx = tcg_op_buf_count(tcg_ctx);
|
||||||
|
|
Loading…
Reference in a new issue