mirror of https://github.com/xqemu/xqemu.git
target/arm: Tidy TBI handling in gen_a64_set_pc
We can perform this with fewer operations. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20190108223129.5570-32-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
1ae9cfbd47
commit
8733d762d5
|
@ -261,7 +261,7 @@ void gen_a64_set_pc_im(uint64_t val)
|
||||||
/* Load the PC from a generic TCG variable.
|
/* Load the PC from a generic TCG variable.
|
||||||
*
|
*
|
||||||
* If address tagging is enabled via the TCR TBI bits, then loading
|
* If address tagging is enabled via the TCR TBI bits, then loading
|
||||||
* an address into the PC will clear out any tag in the it:
|
* an address into the PC will clear out any tag in it:
|
||||||
* + for EL2 and EL3 there is only one TBI bit, and if it is set
|
* + for EL2 and EL3 there is only one TBI bit, and if it is set
|
||||||
* then the address is zero-extended, clearing bits [63:56]
|
* then the address is zero-extended, clearing bits [63:56]
|
||||||
* + for EL0 and EL1, TBI0 controls addresses with bit 55 == 0
|
* + for EL0 and EL1, TBI0 controls addresses with bit 55 == 0
|
||||||
|
@ -280,54 +280,34 @@ static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
|
||||||
int tbi = s->tbii;
|
int tbi = s->tbii;
|
||||||
|
|
||||||
if (s->current_el <= 1) {
|
if (s->current_el <= 1) {
|
||||||
/* Test if NEITHER or BOTH TBI values are set. If so, no need to
|
if (tbi != 0) {
|
||||||
* examine bit 55 of address, can just generate code.
|
/* Sign-extend from bit 55. */
|
||||||
* If mixed, then test via generated code
|
tcg_gen_sextract_i64(cpu_pc, src, 0, 56);
|
||||||
*/
|
|
||||||
if (tbi == 3) {
|
|
||||||
TCGv_i64 tmp_reg = tcg_temp_new_i64();
|
|
||||||
/* Both bits set, sign extension from bit 55 into [63:56] will
|
|
||||||
* cover both cases
|
|
||||||
*/
|
|
||||||
tcg_gen_shli_i64(tmp_reg, src, 8);
|
|
||||||
tcg_gen_sari_i64(cpu_pc, tmp_reg, 8);
|
|
||||||
tcg_temp_free_i64(tmp_reg);
|
|
||||||
} else if (tbi == 0) {
|
|
||||||
/* Neither bit set, just load it as-is */
|
|
||||||
tcg_gen_mov_i64(cpu_pc, src);
|
|
||||||
} else {
|
|
||||||
TCGv_i64 tcg_tmpval = tcg_temp_new_i64();
|
|
||||||
TCGv_i64 tcg_bit55 = tcg_temp_new_i64();
|
|
||||||
TCGv_i64 tcg_zero = tcg_const_i64(0);
|
|
||||||
|
|
||||||
tcg_gen_andi_i64(tcg_bit55, src, (1ull << 55));
|
if (tbi != 3) {
|
||||||
|
TCGv_i64 tcg_zero = tcg_const_i64(0);
|
||||||
|
|
||||||
if (tbi == 1) {
|
/*
|
||||||
/* tbi0==1, tbi1==0, so 0-fill upper byte if bit 55 = 0 */
|
* The two TBI bits differ.
|
||||||
tcg_gen_andi_i64(tcg_tmpval, src,
|
* If tbi0, then !tbi1: only use the extension if positive.
|
||||||
0x00FFFFFFFFFFFFFFull);
|
* if !tbi0, then tbi1: only use the extension if negative.
|
||||||
tcg_gen_movcond_i64(TCG_COND_EQ, cpu_pc, tcg_bit55, tcg_zero,
|
*/
|
||||||
tcg_tmpval, src);
|
tcg_gen_movcond_i64(tbi == 1 ? TCG_COND_GE : TCG_COND_LT,
|
||||||
} else {
|
cpu_pc, cpu_pc, tcg_zero, cpu_pc, src);
|
||||||
/* tbi0==0, tbi1==1, so 1-fill upper byte if bit 55 = 1 */
|
tcg_temp_free_i64(tcg_zero);
|
||||||
tcg_gen_ori_i64(tcg_tmpval, src,
|
|
||||||
0xFF00000000000000ull);
|
|
||||||
tcg_gen_movcond_i64(TCG_COND_NE, cpu_pc, tcg_bit55, tcg_zero,
|
|
||||||
tcg_tmpval, src);
|
|
||||||
}
|
}
|
||||||
tcg_temp_free_i64(tcg_zero);
|
return;
|
||||||
tcg_temp_free_i64(tcg_bit55);
|
|
||||||
tcg_temp_free_i64(tcg_tmpval);
|
|
||||||
}
|
}
|
||||||
} else { /* EL > 1 */
|
} else {
|
||||||
if (tbi != 0) {
|
if (tbi != 0) {
|
||||||
/* Force tag byte to all zero */
|
/* Force tag byte to all zero */
|
||||||
tcg_gen_andi_i64(cpu_pc, src, 0x00FFFFFFFFFFFFFFull);
|
tcg_gen_extract_i64(cpu_pc, src, 0, 56);
|
||||||
} else {
|
return;
|
||||||
/* Load unmodified address */
|
|
||||||
tcg_gen_mov_i64(cpu_pc, src);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Load unmodified address */
|
||||||
|
tcg_gen_mov_i64(cpu_pc, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct DisasCompare64 {
|
typedef struct DisasCompare64 {
|
||||||
|
|
Loading…
Reference in New Issue