23 |
23 |
*/
|
24 |
24 |
|
25 |
25 |
static uint8_t *tb_ret_addr;
|
26 |
|
static uint8_t *udiv_addr;
|
27 |
|
static uint8_t *div_addr;
|
28 |
26 |
|
29 |
27 |
#define FAST_PATH
|
30 |
28 |
#if TARGET_PHYS_ADDR_BITS <= 32
|
... | ... | |
137 |
135 |
TCG_REG_R31
|
138 |
136 |
};
|
139 |
137 |
|
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 |
|
|
156 |
138 |
static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
|
157 |
139 |
{
|
158 |
140 |
tcg_target_long disp;
|
... | ... | |
817 |
799 |
#endif
|
818 |
800 |
}
|
819 |
801 |
|
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 |
|
|
836 |
802 |
void tcg_target_qemu_prologue (TCGContext *s)
|
837 |
803 |
{
|
838 |
804 |
int i, j, frame_size;
|
... | ... | |
871 |
837 |
tcg_out32 (s, MTSPR | RS (0) | LR);
|
872 |
838 |
tcg_out32 (s, ADDI | RT (1) | RA (1) | frame_size);
|
873 |
839 |
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 |
|
}
|
917 |
840 |
}
|
918 |
841 |
|
919 |
842 |
static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
|
... | ... | |
1095 |
1018 |
tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
|
1096 |
1019 |
}
|
1097 |
1020 |
|
1098 |
|
static void tcg_out_div2 (TCGContext *s, int uns)
|
1099 |
|
{
|
1100 |
|
void *label1_ptr, *label2_ptr;
|
1101 |
|
|
1102 |
|
if (uns)
|
1103 |
|
tcg_out32 (s, CMPLI | BF (7) | RA (3));
|
1104 |
|
else {
|
1105 |
|
tcg_out32 (s, SRAWI | RS (4) | RA (0) | 31);
|
1106 |
|
tcg_out32 (s, CMPL | BF (7) | RA (3) | RB (4));
|
1107 |
|
}
|
1108 |
|
|
1109 |
|
label1_ptr = s->code_ptr;
|
1110 |
|
tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE);
|
1111 |
|
|
1112 |
|
tcg_out_b (s, LK, (tcg_target_long) (uns ? udiv_addr : div_addr));
|
1113 |
|
|
1114 |
|
label2_ptr = s->code_ptr;
|
1115 |
|
tcg_out32 (s, B);
|
1116 |
|
|
1117 |
|
reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr);
|
1118 |
|
|
1119 |
|
tcg_out32 (s, (uns ? DIVWU : DIVW) | TAB (6, 4, 5));
|
1120 |
|
tcg_out32 (s, MULLW | TAB (0, 6, 5));
|
1121 |
|
tcg_out32 (s, SUBF | TAB (3, 0, 4));
|
1122 |
|
|
1123 |
|
reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr);
|
1124 |
|
}
|
1125 |
|
|
1126 |
1021 |
static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
|
1127 |
1022 |
const int *const_args)
|
1128 |
1023 |
{
|
... | ... | |
1301 |
1196 |
else
|
1302 |
1197 |
tcg_out32 (s, MULLW | TAB (args[0], args[1], args[2]));
|
1303 |
1198 |
break;
|
|
1199 |
|
|
1200 |
case INDEX_op_div_i32:
|
|
1201 |
tcg_out32 (s, DIVW | TAB (args[0], args[1], args[2]));
|
|
1202 |
break;
|
|
1203 |
|
|
1204 |
case INDEX_op_divu_i32:
|
|
1205 |
tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2]));
|
|
1206 |
break;
|
|
1207 |
|
|
1208 |
case INDEX_op_rem_i32:
|
|
1209 |
tcg_out32 (s, DIVW | TAB (0, args[1], args[2]));
|
|
1210 |
tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
|
|
1211 |
tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
|
|
1212 |
break;
|
|
1213 |
|
|
1214 |
case INDEX_op_remu_i32:
|
|
1215 |
tcg_out32 (s, DIVWU | TAB (0, args[1], args[2]));
|
|
1216 |
tcg_out32 (s, MULLW | TAB (0, 0, args[2]));
|
|
1217 |
tcg_out32 (s, SUBF | TAB (args[0], 0, args[1]));
|
|
1218 |
break;
|
|
1219 |
|
1304 |
1220 |
case INDEX_op_mulu2_i32:
|
1305 |
1221 |
if (args[0] == args[2] || args[0] == args[3]) {
|
1306 |
1222 |
tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
|
... | ... | |
1312 |
1228 |
tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
|
1313 |
1229 |
}
|
1314 |
1230 |
break;
|
1315 |
|
case INDEX_op_div2_i32:
|
1316 |
|
tcg_out_div2 (s, 0);
|
1317 |
|
break;
|
1318 |
|
case INDEX_op_divu2_i32:
|
1319 |
|
tcg_out_div2 (s, 1);
|
1320 |
|
break;
|
1321 |
1231 |
|
1322 |
1232 |
case INDEX_op_shl_i32:
|
1323 |
1233 |
if (const_args[2]) {
|
... | ... | |
1458 |
1368 |
|
1459 |
1369 |
{ INDEX_op_add_i32, { "r", "r", "ri" } },
|
1460 |
1370 |
{ INDEX_op_mul_i32, { "r", "r", "ri" } },
|
|
1371 |
{ INDEX_op_div_i32, { "r", "r", "r" } },
|
|
1372 |
{ INDEX_op_divu_i32, { "r", "r", "r" } },
|
|
1373 |
{ INDEX_op_rem_i32, { "r", "r", "r" } },
|
|
1374 |
{ INDEX_op_remu_i32, { "r", "r", "r" } },
|
1461 |
1375 |
{ INDEX_op_mulu2_i32, { "r", "r", "r", "r" } },
|
1462 |
|
{ INDEX_op_div2_i32, { "D", "A", "B", "1", "C" } },
|
1463 |
|
{ INDEX_op_divu2_i32, { "D", "A", "B", "1", "C" } },
|
1464 |
1376 |
{ INDEX_op_sub_i32, { "r", "r", "ri" } },
|
1465 |
1377 |
{ INDEX_op_and_i32, { "r", "r", "ri" } },
|
1466 |
1378 |
{ INDEX_op_or_i32, { "r", "r", "ri" } },
|