Commit fb0eaffc6d9982b5eee439b8461851bd18bf35ce
1 parent
07ad1b93
PowerPC fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@483 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
382 additions
and
180 deletions
target-ppc/cpu.h
... | ... | @@ -152,7 +152,7 @@ typedef struct CPUPPCState { |
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,7 +172,10 @@ typedef struct CPUPPCState { |
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,35 +377,4 @@ enum { |
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__) */ | ... | ... |
target-ppc/exec.h
... | ... | @@ -29,6 +29,12 @@ register uint32_t T2 asm(AREG3); |
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,8 +151,8 @@ uint32_t do_load_xer (void); |
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,4 +160,7 @@ void do_stmw (int reg, uint32_t dest); |
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__) */ | ... | ... |
target-ppc/helper.c
... | ... | @@ -121,67 +121,67 @@ void do_store_msr (uint32_t msr_value) |
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,20 +220,14 @@ void do_lsw (uint32_t reg, int count, uint32_t src) |
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,19 +238,30 @@ void do_stsw (uint32_t reg, int count, uint32_t dest) |
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 | +} | ... | ... |
target-ppc/op.c
... | ... | @@ -27,6 +27,12 @@ |
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,6 +179,13 @@ PPC_OP(set_Rc0_1) |
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,6 +291,25 @@ PPC_OP(load_lr) |
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,7 +1020,7 @@ PPC_OP(xori) |
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,123 +1248,171 @@ PPC_OP(store_spr) |
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 | } | ... | ... |
target-ppc/op_template.h
... | ... | @@ -70,18 +70,90 @@ void OPPROTO glue(op_store_T1_crf_crf, REG)(void) |
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 | ... | ... |
target-ppc/translate.c
... | ... | @@ -38,6 +38,9 @@ static uint32_t *gen_opparam_ptr; |
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,6 +73,25 @@ GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf) |
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,8 +100,13 @@ GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_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,10 +225,14 @@ EXTRACT_HELPER(SH, 11, 5); |
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,6 +628,7 @@ GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) |
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,47 +879,67 @@ GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) |
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,13 +1231,11 @@ GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_MEM) |
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,8 +1257,6 @@ GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_MEM) |
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,7 +1342,7 @@ GEN_LDF(s, 0x10); |
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,7 +1358,7 @@ GEN_HANDLER(stf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ |
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,7 +1371,7 @@ GEN_HANDLER(stf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ |
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,7 +1380,7 @@ GEN_HANDLER(stf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ |
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,12 +1859,28 @@ GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x02, 0x03E00001, PPC_MEM) |
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,7 +2316,7 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags) |
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,7 +2425,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, |
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) | ... | ... |