24 |
24 |
|
25 |
25 |
static uint8_t *tb_ret_addr;
|
26 |
26 |
|
27 |
|
#define TCG_CT_PC14 0x100
|
28 |
|
#define TCG_CT_PC24 0x200
|
29 |
|
|
30 |
27 |
#define FAST_PATH
|
31 |
28 |
#if TARGET_PHYS_ADDR_BITS <= 32
|
32 |
29 |
#define ADDEND_OFFSET 0
|
... | ... | |
140 |
137 |
|
141 |
138 |
static uint32_t reloc_pc24_val (void *pc, tcg_target_long target)
|
142 |
139 |
{
|
143 |
|
return (target - (tcg_target_long) pc) & 0x3fffffc;
|
|
140 |
tcg_target_long disp;
|
|
141 |
|
|
142 |
disp = target - (tcg_target_long) pc;
|
|
143 |
if ((disp << 6) >> 6 != disp)
|
|
144 |
tcg_abort ();
|
|
145 |
|
|
146 |
return disp & 0x3fffffc;
|
144 |
147 |
}
|
145 |
148 |
|
146 |
149 |
static void reloc_pc24 (void *pc, tcg_target_long target)
|
... | ... | |
151 |
154 |
|
152 |
155 |
static uint16_t reloc_pc14_val (void *pc, tcg_target_long target)
|
153 |
156 |
{
|
154 |
|
return (target - (tcg_target_long) pc) & 0xfffc;
|
|
157 |
tcg_target_long disp;
|
|
158 |
|
|
159 |
disp = target - (tcg_target_long) pc;
|
|
160 |
if (disp != (int16_t) disp)
|
|
161 |
tcg_abort ();
|
|
162 |
|
|
163 |
return disp & 0xfffc;
|
155 |
164 |
}
|
156 |
165 |
|
157 |
166 |
static void reloc_pc14 (void *pc, tcg_target_long target)
|
... | ... | |
218 |
227 |
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
|
219 |
228 |
tcg_regset_reset_reg(ct->u.regs, TCG_REG_R7);
|
220 |
229 |
break;
|
221 |
|
case 'J': /* 24 bit displacement */
|
222 |
|
ct->ct |= TCG_CT_PC24;
|
223 |
|
break;
|
224 |
|
case 'j': /* 16 bit displacement */
|
225 |
|
ct->ct |= TCG_CT_PC14;
|
226 |
|
break;
|
227 |
230 |
default:
|
228 |
231 |
return -1;
|
229 |
232 |
}
|
... | ... | |
241 |
244 |
ct = arg_ct->ct;
|
242 |
245 |
if (ct & TCG_CT_CONST)
|
243 |
246 |
return 1;
|
244 |
|
else if (ct & TCG_CT_PC14) {
|
245 |
|
return val == (int16_t) val;
|
246 |
|
}
|
247 |
|
else if (ct & TCG_CT_PC24) {
|
248 |
|
if (val < 0) return val > -0x800000;
|
249 |
|
return val < 0x7fffff;
|
250 |
|
}
|
251 |
247 |
return 0;
|
252 |
248 |
}
|
253 |
249 |
|
... | ... | |
407 |
403 |
}
|
408 |
404 |
}
|
409 |
405 |
|
|
406 |
static void tcg_out_b (TCGContext *s, int mask, tcg_target_long target)
|
|
407 |
{
|
|
408 |
tcg_target_long disp;
|
|
409 |
|
|
410 |
disp = target - (tcg_target_long) s->code_ptr;
|
|
411 |
if ((disp << 6) >> 6 == disp)
|
|
412 |
tcg_out32 (s, B | disp | mask);
|
|
413 |
else {
|
|
414 |
tcg_out_movi (s, TCG_TYPE_I32, 0, (tcg_target_long) target);
|
|
415 |
tcg_out32 (s, MTSPR | RS (0) | CTR);
|
|
416 |
tcg_out32 (s, BCCTR | BO_ALWAYS | mask);
|
|
417 |
}
|
|
418 |
}
|
|
419 |
|
410 |
420 |
#if defined(CONFIG_SOFTMMU)
|
411 |
421 |
extern void __ldb_mmu(void);
|
412 |
422 |
extern void __ldw_mmu(void);
|
... | ... | |
507 |
517 |
tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index);
|
508 |
518 |
#endif
|
509 |
519 |
|
510 |
|
tcg_out32 (s, B | reloc_pc24_val (s->code_ptr,
|
511 |
|
(tcg_target_long) qemu_ld_helpers[s_bits]) | LK);
|
|
520 |
tcg_out_b (s, LK, (tcg_target_long) qemu_ld_helpers[s_bits]);
|
512 |
521 |
switch (opc) {
|
513 |
522 |
case 0|4:
|
514 |
523 |
tcg_out32 (s, EXTSB | RA (data_reg) | RS (3));
|
... | ... | |
727 |
736 |
ir++;
|
728 |
737 |
|
729 |
738 |
tcg_out_movi (s, TCG_TYPE_I32, ir, mem_index);
|
730 |
|
tcg_out32 (s, B | reloc_pc24_val (s->code_ptr,
|
731 |
|
(tcg_target_long) qemu_st_helpers[opc]) | LK);
|
|
739 |
tcg_out_b (s, LK, (tcg_target_long) qemu_st_helpers[opc]);
|
732 |
740 |
label2_ptr = s->code_ptr;
|
733 |
741 |
tcg_out32 (s, B);
|
734 |
742 |
|
... | ... | |
932 |
940 |
}
|
933 |
941 |
|
934 |
942 |
if (l->has_value) {
|
|
943 |
tcg_target_long disp;
|
|
944 |
|
|
945 |
disp = (tcg_target_long) s->code_ptr - l->u.value;
|
|
946 |
if (disp != (int16_t) disp)
|
|
947 |
tcg_abort ();
|
|
948 |
|
935 |
949 |
tcg_out32 (s, tcg_to_bc[cond] | reloc_pc14_val (s->code_ptr,
|
936 |
950 |
l->u.value));
|
937 |
951 |
}
|
... | ... | |
1010 |
1024 |
switch (opc) {
|
1011 |
1025 |
case INDEX_op_exit_tb:
|
1012 |
1026 |
tcg_out_movi (s, TCG_TYPE_I32, TCG_REG_R3, args[0]);
|
1013 |
|
tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, (tcg_target_long) tb_ret_addr));
|
|
1027 |
tcg_out_b (s, 0, (tcg_target_long) tb_ret_addr);
|
1014 |
1028 |
break;
|
1015 |
1029 |
case INDEX_op_goto_tb:
|
1016 |
1030 |
if (s->tb_jmp_offset) {
|
1017 |
1031 |
/* direct jump method */
|
|
1032 |
uint32_t val;
|
|
1033 |
uint16_t *p;
|
|
1034 |
|
1018 |
1035 |
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
|
1019 |
|
tcg_out32 (s, B | 4);
|
1020 |
|
} else {
|
|
1036 |
/* Thanks to Andrzej Zaborowski for this */
|
|
1037 |
val = *(uint32_t *) s->code_ptr & 0x3fffffc;
|
|
1038 |
|
|
1039 |
tcg_out32 (s, B | val);
|
|
1040 |
|
|
1041 |
/* For branches outside of LL range
|
|
1042 |
This must be in concord with tb_set_jmp_target1 */
|
|
1043 |
p = (uint16_t *) s->code_ptr;
|
|
1044 |
p[0] = (ADDIS | RT (0) | RA (0)) >> 16;
|
|
1045 |
p[2] = (ORI | RT (0) | RA (0)) >> 16;
|
|
1046 |
s->code_ptr += 8;
|
|
1047 |
|
|
1048 |
tcg_out32 (s, MTSPR | RS (0) | CTR);
|
|
1049 |
tcg_out32 (s, BCCTR | BO_ALWAYS);
|
|
1050 |
}
|
|
1051 |
else {
|
1021 |
1052 |
tcg_abort ();
|
1022 |
1053 |
}
|
1023 |
1054 |
s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
|
... | ... | |
1027 |
1058 |
TCGLabel *l = &s->labels[args[0]];
|
1028 |
1059 |
|
1029 |
1060 |
if (l->has_value) {
|
1030 |
|
tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, l->u.value));
|
|
1061 |
tcg_out_b (s, 0, l->u.value);
|
1031 |
1062 |
}
|
1032 |
1063 |
else {
|
1033 |
1064 |
tcg_out32 (s, B);
|
... | ... | |
1037 |
1068 |
break;
|
1038 |
1069 |
case INDEX_op_call:
|
1039 |
1070 |
if (const_args[0]) {
|
1040 |
|
tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, args[0]) | LK);
|
|
1071 |
tcg_out_b (s, LK, args[0]);
|
1041 |
1072 |
}
|
1042 |
1073 |
else {
|
1043 |
1074 |
tcg_out32 (s, MTSPR | RS (args[0]) | LR);
|
... | ... | |
1046 |
1077 |
break;
|
1047 |
1078 |
case INDEX_op_jmp:
|
1048 |
1079 |
if (const_args[0]) {
|
1049 |
|
tcg_out32 (s, B | reloc_pc24_val (s->code_ptr, args[0]));
|
|
1080 |
tcg_out_b (s, 0, args[0]);
|
1050 |
1081 |
}
|
1051 |
1082 |
else {
|
1052 |
1083 |
tcg_out32 (s, MTSPR | RS (args[0]) | CTR);
|
... | ... | |
1122 |
1153 |
if (const_args[2]) {
|
1123 |
1154 |
if (args[2]) {
|
1124 |
1155 |
if (args[2] & 0xffff) {
|
1125 |
|
tcg_out32 (s, ORI | RS (args[1]) | RA (args[0]) | (args[2] & 0xffff));
|
|
1156 |
tcg_out32 (s, ORI | RS (args[1]) | RA (args[0])
|
|
1157 |
| (args[2] & 0xffff));
|
1126 |
1158 |
if (args[2] >> 16)
|
1127 |
1159 |
tcg_out32 (s, ORIS | RS (args[0]) | RA (args[0])
|
1128 |
1160 |
| ((args[2] >> 16) & 0xffff));
|
... | ... | |
1338 |
1370 |
static const TCGTargetOpDef ppc_op_defs[] = {
|
1339 |
1371 |
{ INDEX_op_exit_tb, { } },
|
1340 |
1372 |
{ INDEX_op_goto_tb, { } },
|
1341 |
|
{ INDEX_op_call, { "rJ" } },
|
1342 |
|
{ INDEX_op_jmp, { "rJ" } },
|
|
1373 |
{ INDEX_op_call, { "ri" } },
|
|
1374 |
{ INDEX_op_jmp, { "ri" } },
|
1343 |
1375 |
{ INDEX_op_br, { } },
|
1344 |
1376 |
|
1345 |
1377 |
{ INDEX_op_mov_i32, { "r", "r" } },
|