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
instruction group is described. */
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. */
I3401_ADDI = 0x11000000,
I3401_ADDSI = 0x31000000,
@ -421,6 +433,22 @@ static inline uint32_t tcg_in32(TCGContext *s)
#define tcg_out_insn(S, FMT, OP, ...) \
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,
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_out32(s, 0x14000000 | (offset & 0x03ffffff));
tcg_out_insn(s, 3206, B, offset);
}
static inline void tcg_out_goto_noaddr(TCGContext *s)
{
/* We pay attention here to not modify the branch target by
reading from the buffer. This ensure that caches and memory are
kept coherent during retranslation.
Mask away possible garbage in the high bits for the first translation,
while keeping the offset bits for retranslation. */
uint32_t insn;
insn = (tcg_in32(s) & 0x03ffffff) | 0x14000000;
tcg_out32(s, insn);
/* We pay attention here to not modify the branch target by reading from
the buffer. This ensure that caches and memory are kept coherent during
retranslation. Mask away possible garbage in the high bits for the
first translation, while keeping the offset bits for retranslation. */
uint32_t old = tcg_in32(s);
tcg_out_insn(s, 3206, B, old);
}
static inline void tcg_out_goto_cond_noaddr(TCGContext *s, TCGCond c)
{
/* see comments in tcg_out_goto_noaddr */
uint32_t insn;
insn = tcg_in32(s) & (0x07ffff << 5);
insn |= 0x54000000 | tcg_cond_to_aarch64[c];
tcg_out32(s, insn);
/* See comments in tcg_out_goto_noaddr. */
uint32_t old = tcg_in32(s) >> 5;
tcg_out_insn(s, 3202, B_C, c, old);
}
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();
}
offset &= 0x7ffff;
tcg_out32(s, 0x54000000 | tcg_cond_to_aarch64[c] | offset << 5);
tcg_out_insn(s, 3202, B_C, c, offset);
}
static inline void tcg_out_callr(TCGContext *s, TCGReg reg)
{
tcg_out32(s, 0xd63f0000 | reg << 5);
}
static inline void tcg_out_gotor(TCGContext *s, TCGReg reg)
{
tcg_out32(s, 0xd61f0000 | reg << 5);
tcg_out_insn(s, 3207, BLR, reg);
}
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_callr(s, TCG_REG_TMP);
} 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)
{
intptr_t target = addr;
@ -1899,7 +1911,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
#endif
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;
@ -1917,5 +1929,5 @@ static void tcg_target_qemu_prologue(TCGContext *s)
/* pop (FP, LR), restore SP to previous frame, return */
tcg_out_pop_pair(s, TCG_REG_SP,
TCG_REG_FP, TCG_REG_LR, frame_size_callee_saved);
tcg_out_ret(s);
tcg_out_insn(s, 3207, RET, TCG_REG_LR);
}