tcg/arm: Support host code being compiled for Thumb
Although the TCG generated code is always in ARM mode, it is possible that the host code was compiled by gcc in Thumb mode (this is often the default for Linux distributions targeting ARM v7 only). Handle this by using BLX imm when doing a call from ARM into Thumb mode. Since BLX imm is not a conditionalisable instruction, we make tcg_out_call() no longer take a condition code; we were only ever using it with COND_AL anyway. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Andrzej Zaborowski <andrew.zaborowski@intel.com>
This commit is contained in:
parent
4ac8e585c8
commit
24e838b787
@ -375,6 +375,12 @@ static inline void tcg_out_blx(TCGContext *s, int cond, int rn)
|
|||||||
tcg_out32(s, (cond << 28) | 0x012fff30 | rn);
|
tcg_out32(s, (cond << 28) | 0x012fff30 | rn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void tcg_out_blx_imm(TCGContext *s, int32_t offset)
|
||||||
|
{
|
||||||
|
tcg_out32(s, 0xfa000000 | ((offset & 2) << 23) |
|
||||||
|
(((offset - 8) >> 2) & 0x00ffffff));
|
||||||
|
}
|
||||||
|
|
||||||
static inline void tcg_out_dat_reg(TCGContext *s,
|
static inline void tcg_out_dat_reg(TCGContext *s,
|
||||||
int cond, int opc, int rd, int rn, int rm, int shift)
|
int cond, int opc, int rd, int rn, int rm, int shift)
|
||||||
{
|
{
|
||||||
@ -840,6 +846,11 @@ static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
|
|||||||
{
|
{
|
||||||
int32_t val;
|
int32_t val;
|
||||||
|
|
||||||
|
if (addr & 1) {
|
||||||
|
/* goto to a Thumb destination isn't supported */
|
||||||
|
tcg_abort();
|
||||||
|
}
|
||||||
|
|
||||||
val = addr - (tcg_target_long) s->code_ptr;
|
val = addr - (tcg_target_long) s->code_ptr;
|
||||||
if (val - 8 < 0x01fffffd && val - 8 > -0x01fffffd)
|
if (val - 8 < 0x01fffffd && val - 8 > -0x01fffffd)
|
||||||
tcg_out_b(s, cond, val);
|
tcg_out_b(s, cond, val);
|
||||||
@ -860,14 +871,22 @@ static inline void tcg_out_goto(TCGContext *s, int cond, uint32_t addr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tcg_out_call(TCGContext *s, int cond, uint32_t addr)
|
static inline void tcg_out_call(TCGContext *s, uint32_t addr)
|
||||||
{
|
{
|
||||||
int32_t val;
|
int32_t val;
|
||||||
|
|
||||||
val = addr - (tcg_target_long) s->code_ptr;
|
val = addr - (tcg_target_long) s->code_ptr;
|
||||||
if (val < 0x01fffffd && val > -0x01fffffd)
|
if (val - 8 < 0x02000000 && val - 8 >= -0x02000000) {
|
||||||
tcg_out_bl(s, cond, val);
|
if (addr & 1) {
|
||||||
else {
|
/* Use BLX if the target is in Thumb mode */
|
||||||
|
if (!use_armv5_instructions) {
|
||||||
|
tcg_abort();
|
||||||
|
}
|
||||||
|
tcg_out_blx_imm(s, val);
|
||||||
|
} else {
|
||||||
|
tcg_out_bl(s, COND_AL, val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
#if 1
|
#if 1
|
||||||
tcg_abort();
|
tcg_abort();
|
||||||
#else
|
#else
|
||||||
@ -1063,8 +1082,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
|
|||||||
TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
|
TCG_REG_R1, 0, addr_reg2, SHIFT_IMM_LSL(0));
|
||||||
tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
|
tcg_out_dat_imm(s, COND_AL, ARITH_MOV, TCG_REG_R2, 0, mem_index);
|
||||||
# endif
|
# endif
|
||||||
tcg_out_bl(s, COND_AL, (tcg_target_long) qemu_ld_helpers[s_bits] -
|
tcg_out_call(s, (tcg_target_long) qemu_ld_helpers[s_bits]);
|
||||||
(tcg_target_long) s->code_ptr);
|
|
||||||
|
|
||||||
switch (opc) {
|
switch (opc) {
|
||||||
case 0 | 4:
|
case 0 | 4:
|
||||||
@ -1330,8 +1348,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
tcg_out_bl(s, COND_AL, (tcg_target_long) qemu_st_helpers[s_bits] -
|
tcg_out_call(s, (tcg_target_long) qemu_st_helpers[s_bits]);
|
||||||
(tcg_target_long) s->code_ptr);
|
|
||||||
if (opc == 3)
|
if (opc == 3)
|
||||||
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
|
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
|
||||||
|
|
||||||
@ -1443,7 +1460,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||||||
break;
|
break;
|
||||||
case INDEX_op_call:
|
case INDEX_op_call:
|
||||||
if (const_args[0])
|
if (const_args[0])
|
||||||
tcg_out_call(s, COND_AL, args[0]);
|
tcg_out_call(s, args[0]);
|
||||||
else
|
else
|
||||||
tcg_out_callr(s, COND_AL, args[0]);
|
tcg_out_callr(s, COND_AL, args[0]);
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user