Revision fb0eaffc
b/target-ppc/cpu.h | ||
---|---|---|
152 | 152 |
/* general purpose registers */ |
153 | 153 |
uint32_t gpr[32]; |
154 | 154 |
/* floating point registers */ |
155 |
uint64_t fpr[32];
|
|
155 |
double fpr[32];
|
|
156 | 156 |
/* segment registers */ |
157 | 157 |
ppc_sr_t sr[16]; |
158 | 158 |
/* special purpose registers */ |
... | ... | |
172 | 172 |
uint32_t exception; |
173 | 173 |
|
174 | 174 |
/* qemu dedicated */ |
175 |
uint64_t ft0; /* temporary float register */ |
|
175 |
/* temporary float registers */ |
|
176 |
double ft0; |
|
177 |
double ft1; |
|
178 |
double ft2; |
|
176 | 179 |
int interrupt_request; |
177 | 180 |
jmp_buf jmp_env; |
178 | 181 |
int exception_index; |
... | ... | |
374 | 377 |
EXCP_BRANCH = 0x104, /* branch instruction */ |
375 | 378 |
}; |
376 | 379 |
|
377 |
/* |
|
378 |
* We need to put in some extra aux table entries to tell glibc what |
|
379 |
* the cache block size is, so it can use the dcbz instruction safely. |
|
380 |
*/ |
|
381 |
#define AT_DCACHEBSIZE 19 |
|
382 |
#define AT_ICACHEBSIZE 20 |
|
383 |
#define AT_UCACHEBSIZE 21 |
|
384 |
/* A special ignored type value for PPC, for glibc compatibility. */ |
|
385 |
#define AT_IGNOREPPC 22 |
|
386 |
/* |
|
387 |
* The requirements here are: |
|
388 |
* - keep the final alignment of sp (sp & 0xf) |
|
389 |
* - make sure the 32-bit value at the first 16 byte aligned position of |
|
390 |
* AUXV is greater than 16 for glibc compatibility. |
|
391 |
* AT_IGNOREPPC is used for that. |
|
392 |
* - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, |
|
393 |
* even if DLINFO_ARCH_ITEMS goes to zero or is undefined. |
|
394 |
*/ |
|
395 |
#define DLINFO_ARCH_ITEMS 3 |
|
396 |
#define ARCH_DLINFO \ |
|
397 |
do { \ |
|
398 |
/* \ |
|
399 |
* Now handle glibc compatibility. \ |
|
400 |
*/ \ |
|
401 |
NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ |
|
402 |
NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ |
|
403 |
\ |
|
404 |
NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \ |
|
405 |
NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \ |
|
406 |
NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \ |
|
407 |
} while (0) |
|
408 | 380 |
#endif /* !defined (__CPU_PPC_H__) */ |
b/target-ppc/exec.h | ||
---|---|---|
29 | 29 |
|
30 | 30 |
#define PARAM(n) ((uint32_t)PARAM##n) |
31 | 31 |
#define SPARAM(n) ((int32_t)PARAM##n) |
32 |
#define FT0 (env->ft0) |
|
33 |
#define FT1 (env->ft1) |
|
34 |
#define FT2 (env->ft2) |
|
35 |
#define FTS0 ((float)env->ft0) |
|
36 |
#define FTS1 ((float)env->ft1) |
|
37 |
#define FTS2 ((float)env->ft2) |
|
32 | 38 |
|
33 | 39 |
#define RETURN() __asm__ __volatile__(""); |
34 | 40 |
|
... | ... | |
145 | 151 |
void do_store_xer (uint32_t value); |
146 | 152 |
uint32_t do_load_msr (void); |
147 | 153 |
void do_store_msr (uint32_t msr_value); |
148 |
uint32_t do_load_fpscr (void);
|
|
149 |
void do_store_fpscr (uint8_t mask, uint32_t fp);
|
|
154 |
void do_load_fpscr (void);
|
|
155 |
void do_store_fpscr (uint32_t mask);
|
|
150 | 156 |
|
151 | 157 |
int32_t do_sraw(int32_t Ta, uint32_t Tb); |
152 | 158 |
void do_lmw (int reg, uint32_t src); |
... | ... | |
154 | 160 |
void do_lsw (uint32_t reg, int count, uint32_t src); |
155 | 161 |
void do_stsw (uint32_t reg, int count, uint32_t dest); |
156 | 162 |
|
163 |
void do_dcbz (void); |
|
164 |
void do_icbi (void); |
|
165 |
|
|
157 | 166 |
#endif /* !defined (__PPC_H__) */ |
b/target-ppc/helper.c | ||
---|---|---|
121 | 121 |
} |
122 | 122 |
|
123 | 123 |
/* The 32 MSB of the target fpr are undefined. They'll be zero... */ |
124 |
uint32_t do_load_fpscr (void) |
|
124 |
/* Floating point operations helpers */ |
|
125 |
void do_load_fpscr (void) |
|
125 | 126 |
{ |
126 |
return (fpscr_fx << FPSCR_FX) | |
|
127 |
(fpscr_fex << FPSCR_FEX) | |
|
128 |
(fpscr_vx << FPSCR_VX) | |
|
129 |
(fpscr_ox << FPSCR_OX) | |
|
130 |
(fpscr_ux << FPSCR_UX) | |
|
131 |
(fpscr_zx << FPSCR_ZX) | |
|
132 |
(fpscr_xx << FPSCR_XX) | |
|
133 |
(fpscr_vsxnan << FPSCR_VXSNAN) | |
|
134 |
(fpscr_vxisi << FPSCR_VXISI) | |
|
135 |
(fpscr_vxidi << FPSCR_VXIDI) | |
|
136 |
(fpscr_vxzdz << FPSCR_VXZDZ) | |
|
137 |
(fpscr_vximz << FPSCR_VXIMZ) | |
|
138 |
(fpscr_fr << FPSCR_FR) | |
|
139 |
(fpscr_fi << FPSCR_FI) | |
|
140 |
(fpscr_fprf << FPSCR_FPRF) | |
|
141 |
(fpscr_vxsoft << FPSCR_VXSOFT) | |
|
142 |
(fpscr_vxsqrt << FPSCR_VXSQRT) | |
|
143 |
(fpscr_oe << FPSCR_OE) | |
|
144 |
(fpscr_ue << FPSCR_UE) | |
|
145 |
(fpscr_ze << FPSCR_ZE) | |
|
146 |
(fpscr_xe << FPSCR_XE) | |
|
147 |
(fpscr_ni << FPSCR_NI) | |
|
148 |
(fpscr_rn << FPSCR_RN); |
|
127 |
/* The 32 MSB of the target fpr are undefined. |
|
128 |
* They'll be zero... |
|
129 |
*/ |
|
130 |
union { |
|
131 |
double d; |
|
132 |
struct { |
|
133 |
uint32_t u[2]; |
|
134 |
} s; |
|
135 |
} u; |
|
136 |
int i; |
|
137 |
|
|
138 |
u.s.u[0] = 0; |
|
139 |
u.s.u[1] = 0; |
|
140 |
for (i = 0; i < 8; i++) |
|
141 |
u.s.u[1] |= env->fpscr[i] << (4 * i); |
|
142 |
FT0 = u.d; |
|
149 | 143 |
} |
150 | 144 |
|
151 |
/* We keep only 32 bits of input... */ |
|
152 |
/* For now, this is COMPLETELY BUGGY ! */ |
|
153 |
void do_store_fpscr (uint8_t mask, uint32_t fp) |
|
145 |
void do_store_fpscr (uint32_t mask) |
|
154 | 146 |
{ |
147 |
/* |
|
148 |
* We use only the 32 LSB of the incoming fpr |
|
149 |
*/ |
|
150 |
union { |
|
151 |
double d; |
|
152 |
struct { |
|
153 |
uint32_t u[2]; |
|
154 |
} s; |
|
155 |
} u; |
|
155 | 156 |
int i; |
156 | 157 |
|
157 |
for (i = 0; i < 7; i++) { |
|
158 |
if ((mask & (1 << i)) == 0) |
|
159 |
fp &= ~(0xf << (4 * i)); |
|
158 |
u.d = FT0; |
|
159 |
if (mask & 0x80) |
|
160 |
env->fpscr[0] = (env->fpscr[0] & 0x9) | ((u.s.u[1] >> 28) & ~0x9); |
|
161 |
for (i = 1; i < 7; i++) { |
|
162 |
if (mask & (1 << (7 - i))) |
|
163 |
env->fpscr[i] = (u.s.u[1] >> (4 * (7 - i))) & 0xF; |
|
164 |
} |
|
165 |
/* TODO: update FEX & VX */ |
|
166 |
/* Set rounding mode */ |
|
167 |
switch (env->fpscr[0] & 0x3) { |
|
168 |
case 0: |
|
169 |
/* Best approximation (round to nearest) */ |
|
170 |
fesetround(FE_TONEAREST); |
|
171 |
break; |
|
172 |
case 1: |
|
173 |
/* Smaller magnitude (round toward zero) */ |
|
174 |
fesetround(FE_TOWARDZERO); |
|
175 |
break; |
|
176 |
case 2: |
|
177 |
/* Round toward +infinite */ |
|
178 |
fesetround(FE_UPWARD); |
|
179 |
break; |
|
180 |
case 3: |
|
181 |
/* Round toward -infinite */ |
|
182 |
fesetround(FE_DOWNWARD); |
|
183 |
break; |
|
160 | 184 |
} |
161 |
if ((mask & 80) != 0) |
|
162 |
fpscr_fx = (fp >> FPSCR_FX) & 0x01; |
|
163 |
fpscr_fex = (fp >> FPSCR_FEX) & 0x01; |
|
164 |
fpscr_vx = (fp >> FPSCR_VX) & 0x01; |
|
165 |
fpscr_ox = (fp >> FPSCR_OX) & 0x01; |
|
166 |
fpscr_ux = (fp >> FPSCR_UX) & 0x01; |
|
167 |
fpscr_zx = (fp >> FPSCR_ZX) & 0x01; |
|
168 |
fpscr_xx = (fp >> FPSCR_XX) & 0x01; |
|
169 |
fpscr_vsxnan = (fp >> FPSCR_VXSNAN) & 0x01; |
|
170 |
fpscr_vxisi = (fp >> FPSCR_VXISI) & 0x01; |
|
171 |
fpscr_vxidi = (fp >> FPSCR_VXIDI) & 0x01; |
|
172 |
fpscr_vxzdz = (fp >> FPSCR_VXZDZ) & 0x01; |
|
173 |
fpscr_vximz = (fp >> FPSCR_VXIMZ) & 0x01; |
|
174 |
fpscr_fr = (fp >> FPSCR_FR) & 0x01; |
|
175 |
fpscr_fi = (fp >> FPSCR_FI) & 0x01; |
|
176 |
fpscr_fprf = (fp >> FPSCR_FPRF) & 0x1F; |
|
177 |
fpscr_vxsoft = (fp >> FPSCR_VXSOFT) & 0x01; |
|
178 |
fpscr_vxsqrt = (fp >> FPSCR_VXSQRT) & 0x01; |
|
179 |
fpscr_oe = (fp >> FPSCR_OE) & 0x01; |
|
180 |
fpscr_ue = (fp >> FPSCR_UE) & 0x01; |
|
181 |
fpscr_ze = (fp >> FPSCR_ZE) & 0x01; |
|
182 |
fpscr_xe = (fp >> FPSCR_XE) & 0x01; |
|
183 |
fpscr_ni = (fp >> FPSCR_NI) & 0x01; |
|
184 |
fpscr_rn = (fp >> FPSCR_RN) & 0x03; |
|
185 | 185 |
} |
186 | 186 |
|
187 | 187 |
int32_t do_sraw(int32_t value, uint32_t shift) |
... | ... | |
220 | 220 |
int sh; |
221 | 221 |
|
222 | 222 |
for (; count > 3; count -= 4, src += 4) { |
223 |
if (reg == 32) |
|
224 |
reg = 0; |
|
225 | 223 |
ugpr(reg++) = ld32(src); |
224 |
if (T2 == 32) |
|
225 |
T2 = 0; |
|
226 | 226 |
} |
227 | 227 |
if (count > 0) { |
228 |
for (sh = 24, tmp = 0; count > 0; count--, src++, sh -= 8) { |
|
229 |
if (reg == 32) |
|
230 |
reg = 0; |
|
231 |
tmp |= ld8(src) << sh; |
|
232 |
if (sh == 0) { |
|
233 |
sh = 32; |
|
234 |
ugpr(reg++) = tmp; |
|
235 | 228 |
tmp = 0; |
236 |
} |
|
229 |
for (sh = 24; count > 0; count--, src++, sh -= 8) { |
|
230 |
tmp |= ld8(src) << sh; |
|
237 | 231 |
} |
238 | 232 |
ugpr(reg) = tmp; |
239 | 233 |
} |
... | ... | |
244 | 238 |
int sh; |
245 | 239 |
|
246 | 240 |
for (; count > 3; count -= 4, dest += 4) { |
241 |
st32(dest, ugpr(reg++)); |
|
247 | 242 |
if (reg == 32) |
248 | 243 |
reg = 0; |
249 |
st32(dest, ugpr(reg++)); |
|
250 | 244 |
} |
251 | 245 |
if (count > 0) { |
252 | 246 |
for (sh = 24; count > 0; count--, dest++, sh -= 8) { |
253 |
if (reg == 32) |
|
254 |
reg = 0; |
|
255 | 247 |
st8(dest, (ugpr(reg) >> sh) & 0xFF); |
256 |
if (sh == 0) { |
|
257 |
sh = 32; |
|
258 |
reg++; |
|
259 | 248 |
} |
260 | 249 |
} |
250 |
} |
|
251 |
|
|
252 |
void do_dcbz (void) |
|
253 |
{ |
|
254 |
int i; |
|
255 |
|
|
256 |
/* Assume cache line size is 32 */ |
|
257 |
for (i = 0; i < 8; i++) { |
|
258 |
st32(T0, 0); |
|
259 |
T0 += 4; |
|
261 | 260 |
} |
262 | 261 |
} |
262 |
|
|
263 |
/* Instruction cache invalidation helper */ |
|
264 |
void do_icbi (void) |
|
265 |
{ |
|
266 |
tb_invalidate_page(T0); |
|
267 |
} |
b/target-ppc/op.c | ||
---|---|---|
27 | 27 |
#define Ts2 (int32_t)T2 |
28 | 28 |
|
29 | 29 |
#define FT0 (env->ft0) |
30 |
#define FT1 (env->ft1) |
|
31 |
#define FT2 (env->ft2) |
|
32 |
|
|
33 |
#define FTS0 ((float)env->ft0) |
|
34 |
#define FTS1 ((float)env->ft1) |
|
35 |
#define FTS2 ((float)env->ft2) |
|
30 | 36 |
|
31 | 37 |
#define PPC_OP(name) void op_##name(void) |
32 | 38 |
|
... | ... | |
173 | 179 |
RETURN(); |
174 | 180 |
} |
175 | 181 |
|
182 |
/* Set Rc1 (for floating point arithmetic) */ |
|
183 |
PPC_OP(set_Rc1) |
|
184 |
{ |
|
185 |
env->crf[1] = regs->fpscr[7]; |
|
186 |
RETURN(); |
|
187 |
} |
|
188 |
|
|
176 | 189 |
PPC_OP(set_T0) |
177 | 190 |
{ |
178 | 191 |
T0 = PARAM(1); |
... | ... | |
278 | 291 |
RETURN(); |
279 | 292 |
} |
280 | 293 |
|
294 |
/* FPSCR */ |
|
295 |
PPC_OP(load_fpscr) |
|
296 |
{ |
|
297 |
do_load_fpscr(); |
|
298 |
RETURN(); |
|
299 |
} |
|
300 |
|
|
301 |
PPC_OP(store_fpscr) |
|
302 |
{ |
|
303 |
do_store_fpscr(PARAM(1)); |
|
304 |
RETURN(); |
|
305 |
} |
|
306 |
|
|
307 |
PPC_OP(reset_scrfx) |
|
308 |
{ |
|
309 |
regs->fpscr[7] &= ~0x8; |
|
310 |
RETURN(); |
|
311 |
} |
|
312 |
|
|
281 | 313 |
/* Set reservation */ |
282 | 314 |
PPC_OP(set_reservation) |
283 | 315 |
{ |
... | ... | |
988 | 1020 |
/* rotate left word immediate then mask insert */ |
989 | 1021 |
PPC_OP(rlwimi) |
990 | 1022 |
{ |
991 |
T0 = rotl(T0, PARAM(1) & PARAM(2)) | (T0 & PARAM(3));
|
|
1023 |
T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
|
|
992 | 1024 |
RETURN(); |
993 | 1025 |
} |
994 | 1026 |
|
... | ... | |
1216 | 1248 |
regs->spr[PARAM(1)] = T0; |
1217 | 1249 |
} |
1218 | 1250 |
|
1219 |
/* FPSCR */ |
|
1220 |
PPC_OP(load_fpscr) |
|
1221 |
{ |
|
1222 |
T0 = do_load_fpscr(); |
|
1223 |
} |
|
1224 |
|
|
1225 |
PPC_OP(store_fpscr) |
|
1226 |
{ |
|
1227 |
do_store_fpscr(PARAM(1), T0); |
|
1228 |
} |
|
1229 |
|
|
1230 | 1251 |
/*** Floating-point store ***/ |
1231 | 1252 |
|
1232 |
static inline uint32_t dtos(uint64_t f) |
|
1233 |
{ |
|
1234 |
unsigned int e, m, s; |
|
1235 |
e = (((f >> 52) & 0x7ff) - 1022) + 126; |
|
1236 |
s = (f >> 63); |
|
1237 |
m = (f >> 29); |
|
1238 |
return (s << 31) | (e << 23) | m; |
|
1239 |
} |
|
1240 |
|
|
1241 |
static inline uint64_t stod(uint32_t f) |
|
1242 |
{ |
|
1243 |
unsigned int e, m, s; |
|
1244 |
e = ((f >> 23) & 0xff) - 126 + 1022; |
|
1245 |
s = f >> 31; |
|
1246 |
m = f & ((1 << 23) - 1); |
|
1247 |
return ((uint64_t)s << 63) | ((uint64_t)e << 52) | ((uint64_t)m << 29); |
|
1248 |
} |
|
1249 |
|
|
1250 | 1253 |
PPC_OP(stfd_z_FT0) |
1251 | 1254 |
{ |
1252 |
st64(SPARAM(1), FT0);
|
|
1255 |
stfq((void *)SPARAM(1), FT0);
|
|
1253 | 1256 |
} |
1254 | 1257 |
|
1255 | 1258 |
PPC_OP(stfd_FT0) |
1256 | 1259 |
{ |
1257 | 1260 |
T0 += SPARAM(1); |
1258 |
st64(T0, FT0);
|
|
1261 |
stfq((void *)T0, FT0);
|
|
1259 | 1262 |
} |
1260 | 1263 |
|
1261 | 1264 |
PPC_OP(stfdx_z_FT0) |
1262 | 1265 |
{ |
1263 |
st64(T0, FT0);
|
|
1266 |
stfq((void *)T0, FT0);
|
|
1264 | 1267 |
} |
1265 | 1268 |
|
1266 | 1269 |
PPC_OP(stfdx_FT0) |
1267 | 1270 |
{ |
1268 | 1271 |
T0 += T1; |
1269 |
st64(T0, FT0);
|
|
1272 |
stfq((void *)T0, FT0);
|
|
1270 | 1273 |
} |
1271 | 1274 |
|
1272 |
|
|
1273 | 1275 |
PPC_OP(stfs_z_FT0) |
1274 | 1276 |
{ |
1275 |
st32(SPARAM(1), dtos(FT0)); |
|
1277 |
float tmp = FT0; |
|
1278 |
stfl((void *)SPARAM(1), tmp); |
|
1276 | 1279 |
} |
1277 | 1280 |
|
1278 | 1281 |
PPC_OP(stfs_FT0) |
1279 | 1282 |
{ |
1283 |
float tmp = FT0; |
|
1280 | 1284 |
T0 += SPARAM(1); |
1281 |
st32(T0, dtos(FT0));
|
|
1285 |
stfl((void *)T0, tmp);
|
|
1282 | 1286 |
} |
1283 | 1287 |
|
1284 | 1288 |
PPC_OP(stfsx_z_FT0) |
1285 | 1289 |
{ |
1286 |
st32(T0, dtos(FT0)); |
|
1290 |
float tmp = FT0; |
|
1291 |
stfl((void *)T0, tmp); |
|
1287 | 1292 |
} |
1288 | 1293 |
|
1289 | 1294 |
PPC_OP(stfsx_FT0) |
1290 | 1295 |
{ |
1296 |
float tmp = FT0; |
|
1291 | 1297 |
T0 += T1; |
1292 |
st32(T0, dtos(FT0));
|
|
1298 |
stfl((void *)T0, tmp);
|
|
1293 | 1299 |
} |
1294 | 1300 |
|
1295 | 1301 |
/*** Floating-point load ***/ |
1296 | 1302 |
PPC_OP(lfd_z_FT0) |
1297 | 1303 |
{ |
1298 |
FT0 = ld64(SPARAM(1));
|
|
1304 |
FT0 = ldfq((void *)SPARAM(1));
|
|
1299 | 1305 |
} |
1300 | 1306 |
|
1301 | 1307 |
PPC_OP(lfd_FT0) |
1302 | 1308 |
{ |
1303 | 1309 |
T0 += SPARAM(1); |
1304 |
FT0 = ld64(T0);
|
|
1310 |
FT0 = ldfq((void *)T0);
|
|
1305 | 1311 |
} |
1306 | 1312 |
|
1307 | 1313 |
PPC_OP(lfdx_z_FT0) |
1308 | 1314 |
{ |
1309 |
FT0 = ld64(T0);
|
|
1315 |
FT0 = ldfq((void *)T0);
|
|
1310 | 1316 |
} |
1311 | 1317 |
|
1312 | 1318 |
PPC_OP(lfdx_FT0) |
1313 | 1319 |
{ |
1314 | 1320 |
T0 += T1; |
1315 |
FT0 = ld64(T0);
|
|
1321 |
FT0 = ldfq((void *)T0);
|
|
1316 | 1322 |
} |
1317 | 1323 |
|
1318 | 1324 |
PPC_OP(lfs_z_FT0) |
1319 | 1325 |
{ |
1320 |
FT0 = stod(ld32(SPARAM(1))); |
|
1326 |
float tmp = ldfl((void *)SPARAM(1)); |
|
1327 |
FT0 = tmp; |
|
1321 | 1328 |
} |
1322 | 1329 |
|
1323 | 1330 |
PPC_OP(lfs_FT0) |
1324 | 1331 |
{ |
1332 |
float tmp; |
|
1325 | 1333 |
T0 += SPARAM(1); |
1326 |
FT0 = stod(ld32(T0)); |
|
1334 |
tmp = ldfl((void *)T0); |
|
1335 |
FT0 = tmp; |
|
1327 | 1336 |
} |
1328 | 1337 |
|
1329 | 1338 |
PPC_OP(lfsx_z_FT0) |
1330 | 1339 |
{ |
1331 |
FT0 = stod(ld32(T0)); |
|
1340 |
float tmp; |
|
1341 |
tmp = ldfl((void *)T0); |
|
1342 |
FT0 = tmp; |
|
1332 | 1343 |
} |
1333 | 1344 |
|
1334 | 1345 |
PPC_OP(lfsx_FT0) |
1335 | 1346 |
{ |
1347 |
float tmp; |
|
1348 |
T0 += T1; |
|
1349 |
tmp = ldfl((void *)T0); |
|
1350 |
FT0 = tmp; |
|
1351 |
} |
|
1352 |
|
|
1353 |
PPC_OP(lwarx_z) |
|
1354 |
{ |
|
1355 |
T1 = ld32(T0); |
|
1356 |
regs->reserve = T0; |
|
1357 |
RETURN(); |
|
1358 |
} |
|
1359 |
|
|
1360 |
PPC_OP(lwarx) |
|
1361 |
{ |
|
1362 |
T0 += T1; |
|
1363 |
T1 = ld32(T0); |
|
1364 |
regs->reserve = T0; |
|
1365 |
RETURN(); |
|
1366 |
} |
|
1367 |
|
|
1368 |
PPC_OP(stwcx_z) |
|
1369 |
{ |
|
1370 |
if (regs->reserve != T0) { |
|
1371 |
env->crf[0] = xer_ov; |
|
1372 |
} else { |
|
1373 |
st32(T0, T1); |
|
1374 |
env->crf[0] = xer_ov | 0x02; |
|
1375 |
} |
|
1376 |
regs->reserve = 0; |
|
1377 |
RETURN(); |
|
1378 |
} |
|
1379 |
|
|
1380 |
PPC_OP(stwcx) |
|
1381 |
{ |
|
1336 | 1382 |
T0 += T1; |
1337 |
FT0 = stod(ld32(T0)); |
|
1383 |
if (regs->reserve != (T0 & ~0x03)) { |
|
1384 |
env->crf[0] = xer_ov; |
|
1385 |
} else { |
|
1386 |
st32(T0, T2); |
|
1387 |
env->crf[0] = xer_ov | 0x02; |
|
1388 |
} |
|
1389 |
regs->reserve = 0; |
|
1390 |
RETURN(); |
|
1391 |
} |
|
1392 |
|
|
1393 |
PPC_OP(dcbz_z) |
|
1394 |
{ |
|
1395 |
do_dcbz(); |
|
1396 |
RETURN(); |
|
1397 |
} |
|
1398 |
|
|
1399 |
PPC_OP(dcbz) |
|
1400 |
{ |
|
1401 |
T0 += T1; |
|
1402 |
do_dcbz(); |
|
1403 |
RETURN(); |
|
1404 |
} |
|
1405 |
|
|
1406 |
/* Instruction cache block invalidate */ |
|
1407 |
PPC_OP(icbi_z) |
|
1408 |
{ |
|
1409 |
do_icbi(); |
|
1410 |
RETURN(); |
|
1411 |
} |
|
1412 |
|
|
1413 |
PPC_OP(icbi) |
|
1414 |
{ |
|
1415 |
T0 += T1; |
|
1416 |
do_icbi(); |
|
1417 |
RETURN(); |
|
1338 | 1418 |
} |
b/target-ppc/op_template.h | ||
---|---|---|
70 | 70 |
regs->crf[REG] = T1; |
71 | 71 |
} |
72 | 72 |
|
73 |
/* Floating point condition and status register moves */ |
|
74 |
void OPPROTO glue(op_load_fpscr_T0_fpscr, REG)(void) |
|
75 |
{ |
|
76 |
T0 = regs->fpscr[REG]; |
|
77 |
RETURN(); |
|
78 |
} |
|
79 |
|
|
80 |
#if REG == 0 |
|
81 |
void OPPROTO glue(op_store_T0_fpscr_fpscr, REG)(void) |
|
82 |
{ |
|
83 |
regs->fpscr[REG] = (regs->fpscr[REG] & 0x9) | (T0 & ~0x9); |
|
84 |
RETURN(); |
|
85 |
} |
|
86 |
|
|
87 |
void OPPROTO glue(op_store_T0_fpscri_fpscr, REG)(void) |
|
88 |
{ |
|
89 |
regs->fpscr[REG] = (regs->fpscr[REG] & ~0x9) | (PARAM(1) & 0x9); |
|
90 |
RETURN(); |
|
91 |
} |
|
92 |
|
|
93 |
void OPPROTO glue(op_clear_fpscr_fpscr, REG)(void) |
|
94 |
{ |
|
95 |
regs->fpscr[REG] = (regs->fpscr[REG] & 0x9); |
|
96 |
RETURN(); |
|
97 |
} |
|
98 |
#else |
|
99 |
void OPPROTO glue(op_store_T0_fpscr_fpscr, REG)(void) |
|
100 |
{ |
|
101 |
regs->fpscr[REG] = T0; |
|
102 |
RETURN(); |
|
103 |
} |
|
104 |
|
|
105 |
void OPPROTO glue(op_store_T0_fpscri_fpscr, REG)(void) |
|
106 |
{ |
|
107 |
regs->fpscr[REG] = PARAM(1); |
|
108 |
RETURN(); |
|
109 |
} |
|
110 |
|
|
111 |
void OPPROTO glue(op_clear_fpscr_fpscr, REG)(void) |
|
112 |
{ |
|
113 |
regs->fpscr[REG] = 0x0; |
|
114 |
RETURN(); |
|
115 |
} |
|
116 |
#endif |
|
117 |
|
|
73 | 118 |
#endif /* REG <= 7 */ |
74 | 119 |
|
75 | 120 |
/* float moves */ |
76 | 121 |
|
77 |
void OPPROTO glue(op_load_FT0_fpr, REG)(void) |
|
122 |
/* floating point registers moves */ |
|
123 |
void OPPROTO glue(op_load_fpr_FT0_fpr, REG)(void) |
|
78 | 124 |
{ |
79 | 125 |
FT0 = env->fpr[REG]; |
126 |
RETURN(); |
|
80 | 127 |
} |
81 | 128 |
|
82 |
void OPPROTO glue(op_store_FT0_fpr, REG)(void) |
|
129 |
void OPPROTO glue(op_store_FT0_fpr_fpr, REG)(void)
|
|
83 | 130 |
{ |
84 | 131 |
env->fpr[REG] = FT0; |
132 |
RETURN(); |
|
133 |
} |
|
134 |
|
|
135 |
void OPPROTO glue(op_load_fpr_FT1_fpr, REG)(void) |
|
136 |
{ |
|
137 |
FT1 = env->fpr[REG]; |
|
138 |
RETURN(); |
|
139 |
} |
|
140 |
|
|
141 |
void OPPROTO glue(op_store_FT1_fpr_fpr, REG)(void) |
|
142 |
{ |
|
143 |
env->fpr[REG] = FT1; |
|
144 |
RETURN(); |
|
145 |
} |
|
146 |
|
|
147 |
void OPPROTO glue(op_load_fpr_FT2_fpr, REG)(void) |
|
148 |
{ |
|
149 |
FT2 = env->fpr[REG]; |
|
150 |
RETURN(); |
|
151 |
} |
|
152 |
|
|
153 |
void OPPROTO glue(op_store_FT2_fpr_fpr, REG)(void) |
|
154 |
{ |
|
155 |
env->fpr[REG] = FT2; |
|
156 |
RETURN(); |
|
85 | 157 |
} |
86 | 158 |
|
87 | 159 |
#undef REG |
b/target-ppc/translate.c | ||
---|---|---|
38 | 38 |
#include "gen-op.h" |
39 | 39 |
|
40 | 40 |
typedef void (GenOpFunc)(void); |
41 |
typedef void (GenOpFunc1)(long); |
|
42 |
typedef void (GenOpFunc2)(long, long); |
|
43 |
typedef void (GenOpFunc3)(long, long, long); |
|
41 | 44 |
|
42 | 45 |
#define GEN8(func, NAME) \ |
43 | 46 |
static GenOpFunc *NAME ## _table [8] = {\ |
... | ... | |
70 | 73 |
GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf) |
71 | 74 |
GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf) |
72 | 75 |
|
76 |
/* Floating point condition and status register moves */ |
|
77 |
GEN8(gen_op_load_fpscr_T0, gen_op_load_fpscr_T0_fpscr); |
|
78 |
GEN8(gen_op_store_T0_fpscr, gen_op_store_T0_fpscr_fpscr); |
|
79 |
GEN8(gen_op_clear_fpscr, gen_op_clear_fpscr_fpscr); |
|
80 |
static GenOpFunc1 *gen_op_store_T0_fpscri_fpscr_table[8] = { |
|
81 |
&gen_op_store_T0_fpscri_fpscr0, |
|
82 |
&gen_op_store_T0_fpscri_fpscr1, |
|
83 |
&gen_op_store_T0_fpscri_fpscr2, |
|
84 |
&gen_op_store_T0_fpscri_fpscr3, |
|
85 |
&gen_op_store_T0_fpscri_fpscr4, |
|
86 |
&gen_op_store_T0_fpscri_fpscr5, |
|
87 |
&gen_op_store_T0_fpscri_fpscr6, |
|
88 |
&gen_op_store_T0_fpscri_fpscr7, |
|
89 |
}; |
|
90 |
static inline void gen_op_store_T0_fpscri(int n, uint8_t param) |
|
91 |
{ |
|
92 |
(*gen_op_store_T0_fpscri_fpscr_table[n])(param); |
|
93 |
} |
|
94 |
|
|
73 | 95 |
GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr) |
74 | 96 |
GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr) |
75 | 97 |
GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr) |
... | ... | |
78 | 100 |
GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr) |
79 | 101 |
GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr) |
80 | 102 |
|
81 |
GEN32(gen_op_load_FT0_fpr, gen_op_load_FT0_fpr) |
|
82 |
GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr) |
|
103 |
/* floating point registers moves */ |
|
104 |
GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr); |
|
105 |
GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fpr); |
|
106 |
GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fpr); |
|
107 |
GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fpr); |
|
108 |
GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fpr); |
|
109 |
GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fpr); |
|
83 | 110 |
|
84 | 111 |
static uint8_t spr_access[1024 / 2]; |
85 | 112 |
|
... | ... | |
198 | 225 |
EXTRACT_HELPER(MB, 6, 5); |
199 | 226 |
/* Mask end */ |
200 | 227 |
EXTRACT_HELPER(ME, 1, 5); |
228 |
/* Trap operand */ |
|
229 |
EXTRACT_HELPER(TO, 21, 5); |
|
201 | 230 |
|
202 | 231 |
EXTRACT_HELPER(CRM, 12, 8); |
203 | 232 |
EXTRACT_HELPER(FM, 17, 8); |
204 | 233 |
EXTRACT_HELPER(SR, 16, 4); |
234 |
EXTRACT_HELPER(FPIMM, 20, 4); |
|
235 |
|
|
205 | 236 |
/*** Jump target decoding ***/ |
206 | 237 |
/* Displacement */ |
207 | 238 |
EXTRACT_SHELPER(d, 0, 16); |
... | ... | |
597 | 628 |
mb = MB(ctx->opcode); |
598 | 629 |
me = ME(ctx->opcode); |
599 | 630 |
gen_op_load_gpr_T0(rS(ctx->opcode)); |
631 |
gen_op_load_gpr_T1(rA(ctx->opcode)); |
|
600 | 632 |
gen_op_rlwimi(SH(ctx->opcode), MASK(mb, me), ~MASK(mb, me)); |
601 | 633 |
if (Rc(ctx->opcode) != 0) |
602 | 634 |
gen_op_set_Rc0(); |
... | ... | |
847 | 879 |
/* mcrfs */ |
848 | 880 |
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT) |
849 | 881 |
{ |
850 |
SET_RETVAL(EXCP_INVAL); |
|
882 |
gen_op_load_fpscr_T0(crfS(ctx->opcode)); |
|
883 |
gen_op_store_T0_crf(crfD(ctx->opcode)); |
|
884 |
gen_op_clear_fpscr(crfS(ctx->opcode)); |
|
885 |
SET_RETVAL(0); |
|
851 | 886 |
} |
852 | 887 |
|
853 | 888 |
/* mffs */ |
854 | 889 |
GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT) |
855 | 890 |
{ |
856 | 891 |
gen_op_load_fpscr(); |
857 |
gen_op_store_T0_gpr(rD(ctx->opcode)); |
|
858 |
if (Rc(ctx->opcode)) { |
|
859 |
/* Update CR1 */ |
|
860 |
} |
|
892 |
gen_op_store_FT0_fpr(rD(ctx->opcode)); |
|
893 |
if (Rc(ctx->opcode)) |
|
894 |
gen_op_set_Rc1(); |
|
861 | 895 |
SET_RETVAL(0); |
862 | 896 |
} |
863 | 897 |
|
864 | 898 |
/* mtfsb0 */ |
865 | 899 |
GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT) |
866 | 900 |
{ |
867 |
SET_RETVAL(EXCP_INVAL); |
|
901 |
uint8_t crb; |
|
902 |
|
|
903 |
crb = crbD(ctx->opcode) >> 2; |
|
904 |
gen_op_load_fpscr_T0(crb); |
|
905 |
gen_op_andi_(~(1 << (crbD(ctx->opcode) & 0x03))); |
|
906 |
gen_op_store_T0_fpscr(crb); |
|
907 |
if (Rc(ctx->opcode)) |
|
908 |
gen_op_set_Rc1(); |
|
909 |
SET_RETVAL(0); |
|
868 | 910 |
} |
869 | 911 |
|
870 | 912 |
/* mtfsb1 */ |
871 | 913 |
GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT) |
872 | 914 |
{ |
873 |
SET_RETVAL(EXCP_INVAL); |
|
915 |
uint8_t crb; |
|
916 |
|
|
917 |
crb = crbD(ctx->opcode) >> 2; |
|
918 |
gen_op_load_fpscr_T0(crb); |
|
919 |
gen_op_ori(1 << (crbD(ctx->opcode) & 0x03)); |
|
920 |
gen_op_store_T0_fpscr(crb); |
|
921 |
if (Rc(ctx->opcode)) |
|
922 |
gen_op_set_Rc1(); |
|
923 |
SET_RETVAL(0); |
|
874 | 924 |
} |
875 | 925 |
|
876 | 926 |
/* mtfsf */ |
877 | 927 |
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT) |
878 | 928 |
{ |
879 |
gen_op_load_gpr_T0(rB(ctx->opcode));
|
|
929 |
gen_op_load_fpr_FT0(rB(ctx->opcode));
|
|
880 | 930 |
gen_op_store_fpscr(FM(ctx->opcode)); |
881 |
if (Rc(ctx->opcode)) { |
|
882 |
/* Update CR1 */ |
|
883 |
} |
|
931 |
if (Rc(ctx->opcode)) |
|
932 |
gen_op_set_Rc1(); |
|
884 | 933 |
SET_RETVAL(0); |
885 | 934 |
} |
886 | 935 |
|
887 | 936 |
/* mtfsfi */ |
888 | 937 |
GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) |
889 | 938 |
{ |
890 |
SET_RETVAL(EXCP_INVAL); |
|
939 |
gen_op_store_T0_fpscri(crbD(ctx->opcode) >> 2, FPIMM(ctx->opcode)); |
|
940 |
if (Rc(ctx->opcode)) |
|
941 |
gen_op_set_Rc1(); |
|
942 |
SET_RETVAL(0); |
|
891 | 943 |
} |
892 | 944 |
|
893 | 945 |
/*** Integer load ***/ |
... | ... | |
1179 | 1231 |
reserve = 1; |
1180 | 1232 |
if (rA(ctx->opcode) == 0) { |
1181 | 1233 |
gen_op_load_gpr_T0(rB(ctx->opcode)); |
1182 |
gen_op_lwzx_z(); |
|
1183 |
gen_op_set_reservation(); |
|
1234 |
gen_op_lwarx_z(); |
|
1184 | 1235 |
} else { |
1185 | 1236 |
gen_op_load_gpr_T0(rA(ctx->opcode)); |
1186 | 1237 |
gen_op_load_gpr_T1(rB(ctx->opcode)); |
1187 |
gen_op_lwzx(); |
|
1188 |
gen_op_set_reservation(); |
|
1238 |
gen_op_lwarx(); |
|
1189 | 1239 |
} |
1190 | 1240 |
gen_op_store_T1_gpr(rD(ctx->opcode)); |
1191 | 1241 |
SET_RETVAL(0); |
... | ... | |
1207 | 1257 |
gen_op_load_gpr_T2(rS(ctx->opcode)); |
1208 | 1258 |
gen_op_stwx(); |
1209 | 1259 |
} |
1210 |
gen_op_set_Rc0_1(); |
|
1211 |
gen_op_reset_reservation(); |
|
1212 | 1260 |
} |
1213 | 1261 |
SET_RETVAL(0); |
1214 | 1262 |
} |
... | ... | |
1294 | 1342 |
GEN_HANDLER(stf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ |
1295 | 1343 |
{ \ |
1296 | 1344 |
uint32_t simm = SIMM(ctx->opcode); \ |
1297 |
gen_op_load_FT0_fpr(rS(ctx->opcode));\
|
|
1345 |
gen_op_load_fpr_FT0(rS(ctx->opcode));\
|
|
1298 | 1346 |
if (rA(ctx->opcode) == 0) { \ |
1299 | 1347 |
gen_op_stf##width##_z_FT0(simm); \ |
1300 | 1348 |
} else { \ |
... | ... | |
1310 | 1358 |
if (rA(ctx->opcode) == 0) \ |
1311 | 1359 |
SET_RETVAL(EXCP_INVAL); \ |
1312 | 1360 |
gen_op_load_gpr_T0(rA(ctx->opcode)); \ |
1313 |
gen_op_load_FT0_fpr(rS(ctx->opcode));\
|
|
1361 |
gen_op_load_fpr_FT0(rS(ctx->opcode));\
|
|
1314 | 1362 |
gen_op_stf##width##_FT0(SIMM(ctx->opcode)); \ |
1315 | 1363 |
gen_op_store_T0_gpr(rA(ctx->opcode)); \ |
1316 | 1364 |
SET_RETVAL(0); \ |
... | ... | |
1323 | 1371 |
SET_RETVAL(EXCP_INVAL); \ |
1324 | 1372 |
gen_op_load_gpr_T0(rA(ctx->opcode)); \ |
1325 | 1373 |
gen_op_load_gpr_T1(rB(ctx->opcode)); \ |
1326 |
gen_op_load_FT0_fpr(rS(ctx->opcode));\
|
|
1374 |
gen_op_load_fpr_FT0(rS(ctx->opcode));\
|
|
1327 | 1375 |
gen_op_stf##width##x_FT0(); \ |
1328 | 1376 |
gen_op_store_T0_gpr(rA(ctx->opcode)); \ |
1329 | 1377 |
SET_RETVAL(0); \ |
... | ... | |
1332 | 1380 |
#define GEN_STFX(width, opc) \ |
1333 | 1381 |
GEN_HANDLER(stf##width##x, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ |
1334 | 1382 |
{ \ |
1335 |
gen_op_load_FT0_fpr(rS(ctx->opcode));\
|
|
1383 |
gen_op_load_fpr_FT0(rS(ctx->opcode));\
|
|
1336 | 1384 |
if (rA(ctx->opcode) == 0) { \ |
1337 | 1385 |
gen_op_load_gpr_T0(rB(ctx->opcode)); \ |
1338 | 1386 |
gen_op_stf##width##x_z_FT0(); \ |
... | ... | |
1811 | 1859 |
/* dcbz */ |
1812 | 1860 |
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x08, 0x03E00001, PPC_MEM) |
1813 | 1861 |
{ |
1862 |
if (rA(ctx->opcode) == 0) { |
|
1863 |
gen_op_load_gpr_T0(rB(ctx->opcode)); |
|
1864 |
gen_op_dcbz_z(); |
|
1865 |
} else { |
|
1866 |
gen_op_load_gpr_T0(rA(ctx->opcode)); |
|
1867 |
gen_op_load_gpr_T1(rB(ctx->opcode)); |
|
1868 |
gen_op_dcbz(); |
|
1869 |
} |
|
1814 | 1870 |
SET_RETVAL(0); |
1815 | 1871 |
} |
1816 | 1872 |
|
1817 | 1873 |
/* icbi */ |
1818 | 1874 |
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_MEM) |
1819 | 1875 |
{ |
1876 |
if (rA(ctx->opcode) == 0) { |
|
1877 |
gen_op_load_gpr_T0(rB(ctx->opcode)); |
|
1878 |
gen_op_icbi_z(); |
|
1879 |
} else { |
|
1880 |
gen_op_load_gpr_T0(rA(ctx->opcode)); |
|
1881 |
gen_op_load_gpr_T1(rB(ctx->opcode)); |
|
1882 |
gen_op_icbi(); |
|
1883 |
} |
|
1820 | 1884 |
SET_RETVAL(0); |
1821 | 1885 |
} |
1822 | 1886 |
|
... | ... | |
2252 | 2316 |
for (i = 0; i < 16; i++) { |
2253 | 2317 |
if ((i & 3) == 0) |
2254 | 2318 |
fprintf(logfile, "FPR%02d:", i); |
2255 |
fprintf(logfile, " %016llx", env->fpr[i]);
|
|
2319 |
fprintf(logfile, " %016llx", *((uint64_t *)(&env->fpr[i])));
|
|
2256 | 2320 |
if ((i & 3) == 3) |
2257 | 2321 |
fprintf(logfile, "\n"); |
2258 | 2322 |
} |
... | ... | |
2361 | 2425 |
#endif |
2362 | 2426 |
} |
2363 | 2427 |
#if defined (DO_STEP_FLUSH) |
2364 |
tb_flush();
|
|
2428 |
tb_flush(env);
|
|
2365 | 2429 |
#endif |
2366 | 2430 |
/* We need to update the time base */ |
2367 | 2431 |
if (!search_pc) |
Also available in: Unified diff