Revision 398ce98e
b/tcg/ppc/tcg-target.c | ||
---|---|---|
198 | 198 |
|
199 | 199 |
ct_str = *pct_str; |
200 | 200 |
switch (ct_str[0]) { |
201 |
case 'A': case 'B': case 'C': case 'D': |
|
202 |
ct->ct |= TCG_CT_REG; |
|
203 |
tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A'); |
|
204 |
break; |
|
201 | 205 |
case 'r': |
202 | 206 |
ct->ct |= TCG_CT_REG; |
203 | 207 |
tcg_regset_set32(ct->u.regs, 0, 0xffffffff); |
... | ... | |
1014 | 1018 |
tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr); |
1015 | 1019 |
} |
1016 | 1020 |
|
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 |
static void tcg_out_div2 (TCGContext *s, int uns) |
|
1057 |
{ |
|
1058 |
void *label1_ptr, *label2_ptr; |
|
1059 |
|
|
1060 |
tcg_out32 (s, CMPLI | BF (7) | RA (3)); |
|
1061 |
label1_ptr = s->code_ptr; |
|
1062 |
tcg_out32 (s, BC | BI (7, CR_EQ) | BO_COND_TRUE); |
|
1063 |
|
|
1064 |
tcg_out_b (s, LK, (tcg_target_long) (uns ? udiv_trampoline : div_trampoline)); |
|
1065 |
|
|
1066 |
label2_ptr = s->code_ptr; |
|
1067 |
tcg_out32 (s, B); |
|
1068 |
|
|
1069 |
reloc_pc14 (label1_ptr, (tcg_target_long) s->code_ptr); |
|
1070 |
|
|
1071 |
tcg_out32 (s, (uns ? DIVWU : DIVW) | TAB (6, 4, 5)); |
|
1072 |
tcg_out32 (s, MULLW | TAB (0, 6, 5)); |
|
1073 |
tcg_out32 (s, SUBF | TAB (3, 0, 4)); |
|
1074 |
|
|
1075 |
reloc_pc24 (label2_ptr, (tcg_target_long) s->code_ptr); |
|
1076 |
} |
|
1077 |
|
|
1017 | 1078 |
static void tcg_out_op(TCGContext *s, int opc, const TCGArg *args, |
1018 | 1079 |
const int *const_args) |
1019 | 1080 |
{ |
... | ... | |
1204 | 1265 |
} |
1205 | 1266 |
break; |
1206 | 1267 |
case INDEX_op_div2_i32: |
1207 |
if (args[0] == args[2] || args[0] == args[3]) { |
|
1208 |
tcg_out32 (s, DIVW | TAB (0, args[2], args[3])); |
|
1209 |
tcg_out32 (s, MTSPR | RS (0) | CTR); |
|
1210 |
tcg_out32 (s, MULLW | TAB (0, 0, args[3])); |
|
1211 |
tcg_out32 (s, SUBF | TAB (args[1], 0, args[2])); |
|
1212 |
tcg_out32 (s, MFSPR | RT (args[0]) | CTR); |
|
1213 |
} |
|
1214 |
else { |
|
1215 |
tcg_out32 (s, DIVW | TAB (args[0], args[2], args[3])); |
|
1216 |
tcg_out32 (s, MULLW | TAB (0, args[0], args[3])); |
|
1217 |
tcg_out32 (s, SUBF | TAB (args[1], 0, args[2])); |
|
1218 |
} |
|
1268 |
tcg_out_div2 (s, 0); |
|
1219 | 1269 |
break; |
1220 | 1270 |
case INDEX_op_divu2_i32: |
1221 |
if (args[0] == args[2] || args[0] == args[3]) { |
|
1222 |
tcg_out32 (s, DIVWU | TAB (0, args[2], args[3])); |
|
1223 |
tcg_out32 (s, MTSPR | RS (0) | CTR); |
|
1224 |
tcg_out32 (s, MULLW | TAB (0, 0, args[3])); |
|
1225 |
tcg_out32 (s, SUBF | TAB (args[1], 0, args[2])); |
|
1226 |
tcg_out32 (s, MFSPR | RT (args[0]) | CTR); |
|
1227 |
} |
|
1228 |
else { |
|
1229 |
tcg_out32 (s, DIVWU | TAB (args[0], args[2], args[3])); |
|
1230 |
tcg_out32 (s, MULLW | TAB (0, args[0], args[3])); |
|
1231 |
tcg_out32 (s, SUBF | TAB (args[1], 0, args[2])); |
|
1232 |
} |
|
1271 |
tcg_out_div2 (s, 1); |
|
1233 | 1272 |
break; |
1234 | 1273 |
|
1235 | 1274 |
case INDEX_op_shl_i32: |
... | ... | |
1372 | 1411 |
{ INDEX_op_add_i32, { "r", "r", "ri" } }, |
1373 | 1412 |
{ INDEX_op_mul_i32, { "r", "r", "ri" } }, |
1374 | 1413 |
{ INDEX_op_mulu2_i32, { "r", "r", "r", "r" } }, |
1375 |
{ INDEX_op_div2_i32, { "r", "r", "r", "r", "r" } },
|
|
1376 |
{ INDEX_op_divu2_i32, { "r", "r", "r", "r", "r" } },
|
|
1414 |
{ INDEX_op_div2_i32, { "D", "A", "B", "1", "C" } },
|
|
1415 |
{ INDEX_op_divu2_i32, { "D", "A", "B", "1", "C" } },
|
|
1377 | 1416 |
{ INDEX_op_sub_i32, { "r", "r", "ri" } }, |
1378 | 1417 |
{ INDEX_op_and_i32, { "r", "r", "ri" } }, |
1379 | 1418 |
{ INDEX_op_or_i32, { "r", "r", "ri" } }, |
Also available in: Unified diff