mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-09-02 23:11:53 -06:00
Emit trampolines manually in prologue
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4715 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
5d794885a2
commit
fa4fbfb98a
1 changed files with 80 additions and 38 deletions
|
@ -23,6 +23,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static uint8_t *tb_ret_addr;
|
static uint8_t *tb_ret_addr;
|
||||||
|
static uint8_t *udiv_addr;
|
||||||
|
static uint8_t *div_addr;
|
||||||
|
|
||||||
#define FAST_PATH
|
#define FAST_PATH
|
||||||
#if TARGET_PHYS_ADDR_BITS <= 32
|
#if TARGET_PHYS_ADDR_BITS <= 32
|
||||||
|
@ -118,7 +120,7 @@ static const int tcg_target_call_oarg_regs[2] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int tcg_target_callee_save_regs[] = {
|
static const int tcg_target_callee_save_regs[] = {
|
||||||
TCG_REG_R13, /* sould r13 be saved? */
|
TCG_REG_R13, /* should r13 be saved? */
|
||||||
TCG_REG_R14,
|
TCG_REG_R14,
|
||||||
TCG_REG_R15,
|
TCG_REG_R15,
|
||||||
TCG_REG_R16,
|
TCG_REG_R16,
|
||||||
|
@ -135,6 +137,22 @@ static const int tcg_target_callee_save_regs[] = {
|
||||||
TCG_REG_R31
|
TCG_REG_R31
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const int div_save_regs[] = {
|
||||||
|
TCG_REG_R4,
|
||||||
|
TCG_REG_R5,
|
||||||
|
TCG_REG_R7,
|
||||||
|
TCG_REG_R8,
|
||||||
|
TCG_REG_R9,
|
||||||
|
TCG_REG_R10,
|
||||||
|
TCG_REG_R11,
|
||||||
|
TCG_REG_R12,
|
||||||
|
TCG_REG_R13, /* should r13 be saved? */
|
||||||
|
TCG_REG_R24,
|
||||||
|
TCG_REG_R25,
|
||||||
|
TCG_REG_R26,
|
||||||
|
TCG_REG_R27,
|
||||||
|
};
|
||||||
|
|
||||||
static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
|
static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
|
||||||
{
|
{
|
||||||
tcg_target_long disp;
|
tcg_target_long disp;
|
||||||
|
@ -799,9 +817,25 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64_t ppc_udiv_helper (uint64_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
uint64_t rem, quo;
|
||||||
|
quo = a / b;
|
||||||
|
rem = a % b;
|
||||||
|
return (rem << 32) | (uint32_t) quo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t ppc_div_helper (int64_t a, int32_t b)
|
||||||
|
{
|
||||||
|
int64_t rem, quo;
|
||||||
|
quo = a / b;
|
||||||
|
rem = a % b;
|
||||||
|
return (rem << 32) | (uint32_t) quo;
|
||||||
|
}
|
||||||
|
|
||||||
void tcg_target_qemu_prologue (TCGContext *s)
|
void tcg_target_qemu_prologue (TCGContext *s)
|
||||||
{
|
{
|
||||||
int i, frame_size;
|
int i, j, frame_size;
|
||||||
|
|
||||||
frame_size = 0
|
frame_size = 0
|
||||||
+ 4 /* back chain */
|
+ 4 /* back chain */
|
||||||
|
@ -837,6 +871,49 @@ void tcg_target_qemu_prologue (TCGContext *s)
|
||||||
tcg_out32 (s, MTSPR | RS (0) | LR);
|
tcg_out32 (s, MTSPR | RS (0) | LR);
|
||||||
tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
|
tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
|
||||||
tcg_out32 (s, BCLR | BO_ALWAYS);
|
tcg_out32 (s, BCLR | BO_ALWAYS);
|
||||||
|
|
||||||
|
/* div trampolines */
|
||||||
|
for (j = 0; j < 2; ++j) {
|
||||||
|
tcg_target_long target;
|
||||||
|
|
||||||
|
frame_size = 8 + ARRAY_SIZE (div_save_regs) * 4;
|
||||||
|
frame_size = (frame_size + 15) & ~15;
|
||||||
|
|
||||||
|
if (j == 0) {
|
||||||
|
target = (tcg_target_long) ppc_udiv_helper;
|
||||||
|
udiv_addr = s->code_ptr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
target = (tcg_target_long) ppc_div_helper;
|
||||||
|
div_addr = s->code_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcg_out32 (s, MFSPR | RT (0) | LR);
|
||||||
|
tcg_out32 (s, STWU | RS (1) | RA (1) | (-frame_size & 0xffff));
|
||||||
|
for (i = 0; i < ARRAY_SIZE (div_save_regs); ++i)
|
||||||
|
tcg_out32 (s, (STW
|
||||||
|
| RS (div_save_regs[i])
|
||||||
|
| RA (1)
|
||||||
|
| (i * 4 + 8)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size - 4));
|
||||||
|
tcg_out_mov (s, 4, 6);
|
||||||
|
tcg_out_b (s, LK, target);
|
||||||
|
tcg_out_mov (s, 6, 4);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE (div_save_regs); ++i)
|
||||||
|
tcg_out32 (s, (LWZ
|
||||||
|
| RT (div_save_regs[i])
|
||||||
|
| RA (1)
|
||||||
|
| (i * 4 + 8)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size - 4));
|
||||||
|
tcg_out32 (s, MTSPR | RS (0) | LR);
|
||||||
|
tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
|
||||||
|
tcg_out32 (s, BCLR | BO_ALWAYS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
|
static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
|
||||||
|
@ -1018,41 +1095,6 @@ static void tcg_out_brcond2(TCGContext *s,
|
||||||
tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
|
tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t __attribute ((used)) ppc_udiv_helper (uint64_t a, uint32_t b)
|
|
||||||
{
|
|
||||||
uint64_t rem, quo;
|
|
||||||
quo = a / b;
|
|
||||||
rem = a % b;
|
|
||||||
return (rem << 32) | (uint32_t) quo;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t __attribute ((used)) ppc_div_helper (int64_t a, int32_t b)
|
|
||||||
{
|
|
||||||
int64_t rem, quo;
|
|
||||||
quo = a / b;
|
|
||||||
rem = a % b;
|
|
||||||
return (rem << 32) | (uint32_t) quo;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAKE_TRAMPOLINE(name) \
|
|
||||||
extern void name##_trampoline (void); \
|
|
||||||
asm (#name "_trampoline:\n" \
|
|
||||||
" mflr 0\n" \
|
|
||||||
" addi 1,1,-112\n" \
|
|
||||||
" mr 4,6\n" \
|
|
||||||
" stmw 7,0(1)\n" \
|
|
||||||
" stw 0,108(0)\n" \
|
|
||||||
" bl ppc_" #name "_helper\n" \
|
|
||||||
" lmw 7,0(1)\n" \
|
|
||||||
" lwz 0,108(0)\n" \
|
|
||||||
" addi 1,1,112\n" \
|
|
||||||
" mtlr 0\n" \
|
|
||||||
" blr\n" \
|
|
||||||
)
|
|
||||||
|
|
||||||
MAKE_TRAMPOLINE (div);
|
|
||||||
MAKE_TRAMPOLINE (udiv);
|
|
||||||
|
|
||||||
static void tcg_out_div2 (TCGContext *s, int uns)
|
static void tcg_out_div2 (TCGContext *s, int uns)
|
||||||
{
|
{
|
||||||
void *label1_ptr, *label2_ptr;
|
void *label1_ptr, *label2_ptr;
|
||||||
|
@ -1067,7 +1109,7 @@ static void tcg_out_div2 (TCGContext *s, int uns)
|
||||||
label1_ptr = s->code_ptr;
|
label1_ptr = s->code_ptr;
|
||||||
tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
|
tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
|
||||||
|
|
||||||
tcg_out_b (s, LK, (tcg_target_long) (uns ? udiv_trampoline : div_trampoline));
|
tcg_out_b (s, LK, (tcg_target_long) (uns ? udiv_addr : div_addr));
|
||||||
|
|
||||||
label2_ptr = s->code_ptr;
|
label2_ptr = s->code_ptr;
|
||||||
tcg_out32 (s, B);
|
tcg_out32 (s, B);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue