tcg-aarch64: Use symbolic names for branches

Reviewed-by: Claudio Fontana <claudio.fontana@huawei.com>
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Richard Henderson 2013-08-14 20:05:51 -07:00 committed by Richard Henderson
parent c6e310d938
commit 81d8a5ee19

View File

@ -270,6 +270,18 @@ enum aarch64_ldst_op_type { /* type of operation */
use the section number of the architecture reference manual in which the use the section number of the architecture reference manual in which the
instruction group is described. */ instruction group is described. */
typedef enum { typedef enum {
/* Conditional branch (immediate). */
I3202_B_C = 0x54000000,
/* Unconditional branch (immediate). */
I3206_B = 0x14000000,
I3206_BL = 0x94000000,
/* Unconditional branch (register). */
I3207_BR = 0xd61f0000,
I3207_BLR = 0xd63f0000,
I3207_RET = 0xd65f0000,
/* Add/subtract immediate instructions. */ /* Add/subtract immediate instructions. */
I3401_ADDI = 0x11000000, I3401_ADDI = 0x11000000,
I3401_ADDSI = 0x31000000, I3401_ADDSI = 0x31000000,
@ -421,6 +433,22 @@ static inline uint32_t tcg_in32(TCGContext *s)
#define tcg_out_insn(S, FMT, OP, ...) \ #define tcg_out_insn(S, FMT, OP, ...) \
glue(tcg_out_insn_,FMT)(S, glue(glue(glue(I,FMT),_),OP), ## __VA_ARGS__) glue(tcg_out_insn_,FMT)(S, glue(glue(glue(I,FMT),_),OP), ## __VA_ARGS__)
static void tcg_out_insn_3202(TCGContext *s, AArch64Insn insn,
TCGCond c, int imm19)
{
tcg_out32(s, insn | tcg_cond_to_aarch64[c] | (imm19 & 0x7ffff) << 5);
}
static void tcg_out_insn_3206(TCGContext *s, AArch64Insn insn, int imm26)
{
tcg_out32(s, insn | (imm26 & 0x03ffffff));
}
static void tcg_out_insn_3207(TCGContext *s, AArch64Insn insn, TCGReg rn)
{
tcg_out32(s, insn | rn << 5);
}
static void tcg_out_insn_3401(TCGContext *s, AArch64Insn insn, TCGType ext, static void tcg_out_insn_3401(TCGContext *s, AArch64Insn insn, TCGType ext,
TCGReg rd, TCGReg rn, uint64_t aimm) TCGReg rd, TCGReg rn, uint64_t aimm)
{ {
@ -817,28 +845,24 @@ static inline void tcg_out_goto(TCGContext *s, intptr_t target)
tcg_abort(); tcg_abort();
} }
tcg_out32(s, 0x14000000 | (offset & 0x03ffffff)); tcg_out_insn(s, 3206, B, offset);
} }
static inline void tcg_out_goto_noaddr(TCGContext *s) static inline void tcg_out_goto_noaddr(TCGContext *s)
{ {
/* We pay attention here to not modify the branch target by /* We pay attention here to not modify the branch target by reading from
reading from the buffer. This ensure that caches and memory are the buffer. This ensure that caches and memory are kept coherent during
kept coherent during retranslation. retranslation. Mask away possible garbage in the high bits for the
Mask away possible garbage in the high bits for the first translation, first translation, while keeping the offset bits for retranslation. */
while keeping the offset bits for retranslation. */ uint32_t old = tcg_in32(s);
uint32_t insn; tcg_out_insn(s, 3206, B, old);
insn = (tcg_in32(s) & 0x03ffffff) | 0x14000000;
tcg_out32(s, insn);
} }
static inline void tcg_out_goto_cond_noaddr(TCGContext *s, TCGCond c) static inline void tcg_out_goto_cond_noaddr(TCGContext *s, TCGCond c)
{ {
/* see comments in tcg_out_goto_noaddr */ /* See comments in tcg_out_goto_noaddr. */
uint32_t insn; uint32_t old = tcg_in32(s) >> 5;
insn = tcg_in32(s) & (0x07ffff << 5); tcg_out_insn(s, 3202, B_C, c, old);
insn |= 0x54000000 | tcg_cond_to_aarch64[c];
tcg_out32(s, insn);
} }
static inline void tcg_out_goto_cond(TCGContext *s, TCGCond c, intptr_t target) static inline void tcg_out_goto_cond(TCGContext *s, TCGCond c, intptr_t target)
@ -850,18 +874,12 @@ static inline void tcg_out_goto_cond(TCGContext *s, TCGCond c, intptr_t target)
tcg_abort(); tcg_abort();
} }
offset &= 0x7ffff; tcg_out_insn(s, 3202, B_C, c, offset);
tcg_out32(s, 0x54000000 | tcg_cond_to_aarch64[c] | offset << 5);
} }
static inline void tcg_out_callr(TCGContext *s, TCGReg reg) static inline void tcg_out_callr(TCGContext *s, TCGReg reg)
{ {
tcg_out32(s, 0xd63f0000 | reg << 5); tcg_out_insn(s, 3207, BLR, reg);
}
static inline void tcg_out_gotor(TCGContext *s, TCGReg reg)
{
tcg_out32(s, 0xd61f0000 | reg << 5);
} }
static inline void tcg_out_call(TCGContext *s, intptr_t target) static inline void tcg_out_call(TCGContext *s, intptr_t target)
@ -872,16 +890,10 @@ static inline void tcg_out_call(TCGContext *s, intptr_t target)
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, target); tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, target);
tcg_out_callr(s, TCG_REG_TMP); tcg_out_callr(s, TCG_REG_TMP);
} else { } else {
tcg_out32(s, 0x94000000 | (offset & 0x03ffffff)); tcg_out_insn(s, 3206, BL, offset);
} }
} }
static inline void tcg_out_ret(TCGContext *s)
{
/* emit RET { LR } */
tcg_out32(s, 0xd65f03c0);
}
void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr) void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
{ {
intptr_t target = addr; intptr_t target = addr;
@ -1899,7 +1911,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
#endif #endif
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]);
tcg_out_gotor(s, tcg_target_call_iarg_regs[1]); tcg_out_insn(s, 3207, BR, tcg_target_call_iarg_regs[1]);
tb_ret_addr = s->code_ptr; tb_ret_addr = s->code_ptr;
@ -1917,5 +1929,5 @@ static void tcg_target_qemu_prologue(TCGContext *s)
/* pop (FP, LR), restore SP to previous frame, return */ /* pop (FP, LR), restore SP to previous frame, return */
tcg_out_pop_pair(s, TCG_REG_SP, tcg_out_pop_pair(s, TCG_REG_SP,
TCG_REG_FP, TCG_REG_LR, frame_size_callee_saved); TCG_REG_FP, TCG_REG_LR, frame_size_callee_saved);
tcg_out_ret(s); tcg_out_insn(s, 3207, RET, TCG_REG_LR);
} }