Revision fa4fbfb9
b/tcg/ppc/tcg-target.c | ||
---|---|---|
23 | 23 |
*/ |
24 | 24 |
|
25 | 25 |
static uint8_t *tb_ret_addr; |
26 |
static uint8_t *udiv_addr; |
|
27 |
static uint8_t *div_addr; |
|
26 | 28 |
|
27 | 29 |
#define FAST_PATH |
28 | 30 |
#if TARGET_PHYS_ADDR_BITS <= 32 |
... | ... | |
118 | 120 |
}; |
119 | 121 |
|
120 | 122 |
static const int tcg_target_callee_save_regs[] = { |
121 |
TCG_REG_R13, /* sould r13 be saved? */ |
|
123 |
TCG_REG_R13, /* should r13 be saved? */
|
|
122 | 124 |
TCG_REG_R14, |
123 | 125 |
TCG_REG_R15, |
124 | 126 |
TCG_REG_R16, |
... | ... | |
135 | 137 |
TCG_REG_R31 |
136 | 138 |
}; |
137 | 139 |
|
140 |
static const int div_save_regs[] = { |
|
141 |
TCG_REG_R4, |
|
142 |
TCG_REG_R5, |
|
143 |
TCG_REG_R7, |
|
144 |
TCG_REG_R8, |
|
145 |
TCG_REG_R9, |
|
146 |
TCG_REG_R10, |
|
147 |
TCG_REG_R11, |
|
148 |
TCG_REG_R12, |
|
149 |
TCG_REG_R13, /* should r13 be saved? */ |
|
150 |
TCG_REG_R24, |
|
151 |
TCG_REG_R25, |
|
152 |
TCG_REG_R26, |
|
153 |
TCG_REG_R27, |
|
154 |
}; |
|
155 |
|
|
138 | 156 |
static uint32_t reloc_pc24_val (void *pc, tcg_target_long target) |
139 | 157 |
{ |
140 | 158 |
tcg_target_long disp; |
... | ... | |
799 | 817 |
#endif |
800 | 818 |
} |
801 | 819 |
|
820 |
static uint64_t ppc_udiv_helper (uint64_t a, uint32_t b) |
|
821 |
{ |
|
822 |
uint64_t rem, quo; |
|
823 |
quo = a / b; |
|
824 |
rem = a % b; |
|
825 |
return (rem << 32) | (uint32_t) quo; |
|
826 |
} |
|
827 |
|
|
828 |
static uint64_t ppc_div_helper (int64_t a, int32_t b) |
|
829 |
{ |
|
830 |
int64_t rem, quo; |
|
831 |
quo = a / b; |
|
832 |
rem = a % b; |
|
833 |
return (rem << 32) | (uint32_t) quo; |
|
834 |
} |
|
835 |
|
|
802 | 836 |
void tcg_target_qemu_prologue (TCGContext *s) |
803 | 837 |
{ |
804 |
int i, frame_size; |
|
838 |
int i, j, frame_size;
|
|
805 | 839 |
|
806 | 840 |
frame_size = 0 |
807 | 841 |
+ 4 /* back chain */ |
... | ... | |
837 | 871 |
tcg_out32 (s, MTSPR | RS (0) | LR); |
838 | 872 |
tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size); |
839 | 873 |
tcg_out32 (s, BCLR | BO_ALWAYS); |
874 |
|
|
875 |
/* div trampolines */ |
|
876 |
for (j = 0; j < 2; ++j) { |
|
877 |
tcg_target_long target; |
|
878 |
|
|
879 |
frame_size = 8 + ARRAY_SIZE (div_save_regs) * 4; |
|
880 |
frame_size = (frame_size + 15) & ~15; |
|
881 |
|
|
882 |
if (j == 0) { |
|
883 |
target = (tcg_target_long) ppc_udiv_helper; |
|
884 |
udiv_addr = s->code_ptr; |
|
885 |
} |
|
886 |
else { |
|
887 |
target = (tcg_target_long) ppc_div_helper; |
|
888 |
div_addr = s->code_ptr; |
|
889 |
} |
|
890 |
|
|
891 |
tcg_out32 (s, MFSPR | RT (0) | LR); |
|
892 |
tcg_out32 (s, STWU | RS (1) | RA (1) | (-frame_size & 0xffff)); |
|
893 |
for (i = 0; i < ARRAY_SIZE (div_save_regs); ++i) |
|
894 |
tcg_out32 (s, (STW |
|
895 |
| RS (div_save_regs[i]) |
|
896 |
| RA (1) |
|
897 |
| (i * 4 + 8) |
|
898 |
) |
|
899 |
); |
|
900 |
tcg_out32 (s, STW | RS (0) | RA (1) | (frame_size - 4)); |
|
901 |
tcg_out_mov (s, 4, 6); |
|
902 |
tcg_out_b (s, LK, target); |
|
903 |
tcg_out_mov (s, 6, 4); |
|
904 |
|
|
905 |
for (i = 0; i < ARRAY_SIZE (div_save_regs); ++i) |
|
906 |
tcg_out32 (s, (LWZ |
|
907 |
| RT (div_save_regs[i]) |
|
908 |
| RA (1) |
|
909 |
| (i * 4 + 8) |
|
910 |
) |
|
911 |
); |
|
912 |
tcg_out32 (s, LWZ | RT (0) | RA (1) | (frame_size - 4)); |
|
913 |
tcg_out32 (s, MTSPR | RS (0) | LR); |
|
914 |
tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size); |
|
915 |
tcg_out32 (s, BCLR | BO_ALWAYS); |
|
916 |
} |
|
840 | 917 |
} |
841 | 918 |
|
842 | 919 |
static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1, |
... | ... | |
1018 | 1095 |
tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr); |
1019 | 1096 |
} |
1020 | 1097 |
|
1021 |
static uint64_t __attribute ((used)) ppc_udiv_helper (uint64_t a, uint32_t b) |
|
1022 |
{ |
|
1023 |
uint64_t rem, quo; |
|
1024 |
quo = a / b; |
|
1025 |
rem = a % b; |
|
1026 |
return (rem << 32) | (uint32_t) quo; |
|
1027 |
} |
|
1028 |
|
|
1029 |
static uint64_t __attribute ((used)) ppc_div_helper (int64_t a, int32_t b) |
|
1030 |
{ |
|
1031 |
int64_t rem, quo; |
|
1032 |
quo = a / b; |
|
1033 |
rem = a % b; |
|
1034 |
return (rem << 32) | (uint32_t) quo; |
|
1035 |
} |
|
1036 |
|
|
1037 |
#define MAKE_TRAMPOLINE(name) \ |
|
1038 |
extern void name##_trampoline (void); \ |
|
1039 |
asm (#name "_trampoline:\n" \ |
|
1040 |
" mflr 0\n" \ |
|
1041 |
" addi 1,1,-112\n" \ |
|
1042 |
" mr 4,6\n" \ |
|
1043 |
" stmw 7,0(1)\n" \ |
|
1044 |
" stw 0,108(0)\n" \ |
|
1045 |
" bl ppc_" #name "_helper\n" \ |
|
1046 |
" lmw 7,0(1)\n" \ |
|
1047 |
" lwz 0,108(0)\n" \ |
|
1048 |
" addi 1,1,112\n" \ |
|
1049 |
" mtlr 0\n" \ |
|
1050 |
" blr\n" \ |
|
1051 |
) |
|
1052 |
|
|
1053 |
MAKE_TRAMPOLINE (div); |
|
1054 |
MAKE_TRAMPOLINE (udiv); |
|
1055 |
|
|
1056 | 1098 |
static void tcg_out_div2 (TCGContext *s, int uns) |
1057 | 1099 |
{ |
1058 | 1100 |
void *label1_ptr, *label2_ptr; |
... | ... | |
1067 | 1109 |
label1_ptr = s->code_ptr; |
1068 | 1110 |
tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE); |
1069 | 1111 |
|
1070 |
tcg_out_b (s, LK, (tcg_target_long) (uns ? udiv_trampoline : div_trampoline));
|
|
1112 |
tcg_out_b (s, LK, (tcg_target_long) (uns ? udiv_addr : div_addr));
|
|
1071 | 1113 |
|
1072 | 1114 |
label2_ptr = s->code_ptr; |
1073 | 1115 |
tcg_out32 (s, B); |
Also available in: Unified diff