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,7 +152,7 @@ typedef struct CPUPPCState { | ||
| 152 | /* general purpose registers */ | 152 | /* general purpose registers */ |
| 153 | uint32_t gpr[32]; | 153 | uint32_t gpr[32]; |
| 154 | /* floating point registers */ | 154 | /* floating point registers */ |
| 155 | - uint64_t fpr[32]; | 155 | + double fpr[32]; |
| 156 | /* segment registers */ | 156 | /* segment registers */ |
| 157 | ppc_sr_t sr[16]; | 157 | ppc_sr_t sr[16]; |
| 158 | /* special purpose registers */ | 158 | /* special purpose registers */ |
| @@ -172,7 +172,10 @@ typedef struct CPUPPCState { | @@ -172,7 +172,10 @@ typedef struct CPUPPCState { | ||
| 172 | uint32_t exception; | 172 | uint32_t exception; |
| 173 | 173 | ||
| 174 | /* qemu dedicated */ | 174 | /* qemu dedicated */ |
| 175 | - uint64_t ft0; /* temporary float register */ | 175 | + /* temporary float registers */ |
| 176 | + double ft0; | ||
| 177 | + double ft1; | ||
| 178 | + double ft2; | ||
| 176 | int interrupt_request; | 179 | int interrupt_request; |
| 177 | jmp_buf jmp_env; | 180 | jmp_buf jmp_env; |
| 178 | int exception_index; | 181 | int exception_index; |
| @@ -374,35 +377,4 @@ enum { | @@ -374,35 +377,4 @@ enum { | ||
| 374 | EXCP_BRANCH = 0x104, /* branch instruction */ | 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 | #endif /* !defined (__CPU_PPC_H__) */ | 380 | #endif /* !defined (__CPU_PPC_H__) */ |
target-ppc/exec.h
| @@ -29,6 +29,12 @@ register uint32_t T2 asm(AREG3); | @@ -29,6 +29,12 @@ register uint32_t T2 asm(AREG3); | ||
| 29 | 29 | ||
| 30 | #define PARAM(n) ((uint32_t)PARAM##n) | 30 | #define PARAM(n) ((uint32_t)PARAM##n) |
| 31 | #define SPARAM(n) ((int32_t)PARAM##n) | 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 | #define RETURN() __asm__ __volatile__(""); | 39 | #define RETURN() __asm__ __volatile__(""); |
| 34 | 40 | ||
| @@ -145,8 +151,8 @@ uint32_t do_load_xer (void); | @@ -145,8 +151,8 @@ uint32_t do_load_xer (void); | ||
| 145 | void do_store_xer (uint32_t value); | 151 | void do_store_xer (uint32_t value); |
| 146 | uint32_t do_load_msr (void); | 152 | uint32_t do_load_msr (void); |
| 147 | void do_store_msr (uint32_t msr_value); | 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 | int32_t do_sraw(int32_t Ta, uint32_t Tb); | 157 | int32_t do_sraw(int32_t Ta, uint32_t Tb); |
| 152 | void do_lmw (int reg, uint32_t src); | 158 | void do_lmw (int reg, uint32_t src); |
| @@ -154,4 +160,7 @@ void do_stmw (int reg, uint32_t dest); | @@ -154,4 +160,7 @@ void do_stmw (int reg, uint32_t dest); | ||
| 154 | void do_lsw (uint32_t reg, int count, uint32_t src); | 160 | void do_lsw (uint32_t reg, int count, uint32_t src); |
| 155 | void do_stsw (uint32_t reg, int count, uint32_t dest); | 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 | #endif /* !defined (__PPC_H__) */ | 166 | #endif /* !defined (__PPC_H__) */ |
target-ppc/helper.c
| @@ -121,67 +121,67 @@ void do_store_msr (uint32_t msr_value) | @@ -121,67 +121,67 @@ void do_store_msr (uint32_t msr_value) | ||
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | /* The 32 MSB of the target fpr are undefined. They'll be zero... */ | 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 | int i; | 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 | int32_t do_sraw(int32_t value, uint32_t shift) | 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,20 +220,14 @@ void do_lsw (uint32_t reg, int count, uint32_t src) | ||
| 220 | int sh; | 220 | int sh; |
| 221 | 221 | ||
| 222 | for (; count > 3; count -= 4, src += 4) { | 222 | for (; count > 3; count -= 4, src += 4) { |
| 223 | - if (reg == 32) | ||
| 224 | - reg = 0; | ||
| 225 | ugpr(reg++) = ld32(src); | 223 | ugpr(reg++) = ld32(src); |
| 224 | + if (T2 == 32) | ||
| 225 | + T2 = 0; | ||
| 226 | } | 226 | } |
| 227 | if (count > 0) { | 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 | tmp = 0; | 228 | tmp = 0; |
| 236 | - } | 229 | + for (sh = 24; count > 0; count--, src++, sh -= 8) { |
| 230 | + tmp |= ld8(src) << sh; | ||
| 237 | } | 231 | } |
| 238 | ugpr(reg) = tmp; | 232 | ugpr(reg) = tmp; |
| 239 | } | 233 | } |
| @@ -244,19 +238,30 @@ void do_stsw (uint32_t reg, int count, uint32_t dest) | @@ -244,19 +238,30 @@ void do_stsw (uint32_t reg, int count, uint32_t dest) | ||
| 244 | int sh; | 238 | int sh; |
| 245 | 239 | ||
| 246 | for (; count > 3; count -= 4, dest += 4) { | 240 | for (; count > 3; count -= 4, dest += 4) { |
| 241 | + st32(dest, ugpr(reg++)); | ||
| 247 | if (reg == 32) | 242 | if (reg == 32) |
| 248 | reg = 0; | 243 | reg = 0; |
| 249 | - st32(dest, ugpr(reg++)); | ||
| 250 | } | 244 | } |
| 251 | if (count > 0) { | 245 | if (count > 0) { |
| 252 | for (sh = 24; count > 0; count--, dest++, sh -= 8) { | 246 | for (sh = 24; count > 0; count--, dest++, sh -= 8) { |
| 253 | - if (reg == 32) | ||
| 254 | - reg = 0; | ||
| 255 | st8(dest, (ugpr(reg) >> sh) & 0xFF); | 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,6 +27,12 @@ | ||
| 27 | #define Ts2 (int32_t)T2 | 27 | #define Ts2 (int32_t)T2 |
| 28 | 28 | ||
| 29 | #define FT0 (env->ft0) | 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 | #define PPC_OP(name) void op_##name(void) | 37 | #define PPC_OP(name) void op_##name(void) |
| 32 | 38 | ||
| @@ -173,6 +179,13 @@ PPC_OP(set_Rc0_1) | @@ -173,6 +179,13 @@ PPC_OP(set_Rc0_1) | ||
| 173 | RETURN(); | 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 | PPC_OP(set_T0) | 189 | PPC_OP(set_T0) |
| 177 | { | 190 | { |
| 178 | T0 = PARAM(1); | 191 | T0 = PARAM(1); |
| @@ -278,6 +291,25 @@ PPC_OP(load_lr) | @@ -278,6 +291,25 @@ PPC_OP(load_lr) | ||
| 278 | RETURN(); | 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 | /* Set reservation */ | 313 | /* Set reservation */ |
| 282 | PPC_OP(set_reservation) | 314 | PPC_OP(set_reservation) |
| 283 | { | 315 | { |
| @@ -988,7 +1020,7 @@ PPC_OP(xori) | @@ -988,7 +1020,7 @@ PPC_OP(xori) | ||
| 988 | /* rotate left word immediate then mask insert */ | 1020 | /* rotate left word immediate then mask insert */ |
| 989 | PPC_OP(rlwimi) | 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 | RETURN(); | 1024 | RETURN(); |
| 993 | } | 1025 | } |
| 994 | 1026 | ||
| @@ -1216,123 +1248,171 @@ PPC_OP(store_spr) | @@ -1216,123 +1248,171 @@ PPC_OP(store_spr) | ||
| 1216 | regs->spr[PARAM(1)] = T0; | 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 | /*** Floating-point store ***/ | 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 | PPC_OP(stfd_z_FT0) | 1253 | PPC_OP(stfd_z_FT0) |
| 1251 | { | 1254 | { |
| 1252 | - st64(SPARAM(1), FT0); | 1255 | + stfq((void *)SPARAM(1), FT0); |
| 1253 | } | 1256 | } |
| 1254 | 1257 | ||
| 1255 | PPC_OP(stfd_FT0) | 1258 | PPC_OP(stfd_FT0) |
| 1256 | { | 1259 | { |
| 1257 | T0 += SPARAM(1); | 1260 | T0 += SPARAM(1); |
| 1258 | - st64(T0, FT0); | 1261 | + stfq((void *)T0, FT0); |
| 1259 | } | 1262 | } |
| 1260 | 1263 | ||
| 1261 | PPC_OP(stfdx_z_FT0) | 1264 | PPC_OP(stfdx_z_FT0) |
| 1262 | { | 1265 | { |
| 1263 | - st64(T0, FT0); | 1266 | + stfq((void *)T0, FT0); |
| 1264 | } | 1267 | } |
| 1265 | 1268 | ||
| 1266 | PPC_OP(stfdx_FT0) | 1269 | PPC_OP(stfdx_FT0) |
| 1267 | { | 1270 | { |
| 1268 | T0 += T1; | 1271 | T0 += T1; |
| 1269 | - st64(T0, FT0); | 1272 | + stfq((void *)T0, FT0); |
| 1270 | } | 1273 | } |
| 1271 | 1274 | ||
| 1272 | - | ||
| 1273 | PPC_OP(stfs_z_FT0) | 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 | PPC_OP(stfs_FT0) | 1281 | PPC_OP(stfs_FT0) |
| 1279 | { | 1282 | { |
| 1283 | + float tmp = FT0; | ||
| 1280 | T0 += SPARAM(1); | 1284 | T0 += SPARAM(1); |
| 1281 | - st32(T0, dtos(FT0)); | 1285 | + stfl((void *)T0, tmp); |
| 1282 | } | 1286 | } |
| 1283 | 1287 | ||
| 1284 | PPC_OP(stfsx_z_FT0) | 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 | PPC_OP(stfsx_FT0) | 1294 | PPC_OP(stfsx_FT0) |
| 1290 | { | 1295 | { |
| 1296 | + float tmp = FT0; | ||
| 1291 | T0 += T1; | 1297 | T0 += T1; |
| 1292 | - st32(T0, dtos(FT0)); | 1298 | + stfl((void *)T0, tmp); |
| 1293 | } | 1299 | } |
| 1294 | 1300 | ||
| 1295 | /*** Floating-point load ***/ | 1301 | /*** Floating-point load ***/ |
| 1296 | PPC_OP(lfd_z_FT0) | 1302 | PPC_OP(lfd_z_FT0) |
| 1297 | { | 1303 | { |
| 1298 | - FT0 = ld64(SPARAM(1)); | 1304 | + FT0 = ldfq((void *)SPARAM(1)); |
| 1299 | } | 1305 | } |
| 1300 | 1306 | ||
| 1301 | PPC_OP(lfd_FT0) | 1307 | PPC_OP(lfd_FT0) |
| 1302 | { | 1308 | { |
| 1303 | T0 += SPARAM(1); | 1309 | T0 += SPARAM(1); |
| 1304 | - FT0 = ld64(T0); | 1310 | + FT0 = ldfq((void *)T0); |
| 1305 | } | 1311 | } |
| 1306 | 1312 | ||
| 1307 | PPC_OP(lfdx_z_FT0) | 1313 | PPC_OP(lfdx_z_FT0) |
| 1308 | { | 1314 | { |
| 1309 | - FT0 = ld64(T0); | 1315 | + FT0 = ldfq((void *)T0); |
| 1310 | } | 1316 | } |
| 1311 | 1317 | ||
| 1312 | PPC_OP(lfdx_FT0) | 1318 | PPC_OP(lfdx_FT0) |
| 1313 | { | 1319 | { |
| 1314 | T0 += T1; | 1320 | T0 += T1; |
| 1315 | - FT0 = ld64(T0); | 1321 | + FT0 = ldfq((void *)T0); |
| 1316 | } | 1322 | } |
| 1317 | 1323 | ||
| 1318 | PPC_OP(lfs_z_FT0) | 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 | PPC_OP(lfs_FT0) | 1330 | PPC_OP(lfs_FT0) |
| 1324 | { | 1331 | { |
| 1332 | + float tmp; | ||
| 1325 | T0 += SPARAM(1); | 1333 | T0 += SPARAM(1); |
| 1326 | - FT0 = stod(ld32(T0)); | 1334 | + tmp = ldfl((void *)T0); |
| 1335 | + FT0 = tmp; | ||
| 1327 | } | 1336 | } |
| 1328 | 1337 | ||
| 1329 | PPC_OP(lfsx_z_FT0) | 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 | PPC_OP(lfsx_FT0) | 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 | T0 += T1; | 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,18 +70,90 @@ void OPPROTO glue(op_store_T1_crf_crf, REG)(void) | ||
| 70 | regs->crf[REG] = T1; | 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 | #endif /* REG <= 7 */ | 118 | #endif /* REG <= 7 */ |
| 74 | 119 | ||
| 75 | /* float moves */ | 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 | FT0 = env->fpr[REG]; | 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 | env->fpr[REG] = FT0; | 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 | #undef REG | 159 | #undef REG |
target-ppc/translate.c
| @@ -38,6 +38,9 @@ static uint32_t *gen_opparam_ptr; | @@ -38,6 +38,9 @@ static uint32_t *gen_opparam_ptr; | ||
| 38 | #include "gen-op.h" | 38 | #include "gen-op.h" |
| 39 | 39 | ||
| 40 | typedef void (GenOpFunc)(void); | 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 | #define GEN8(func, NAME) \ | 45 | #define GEN8(func, NAME) \ |
| 43 | static GenOpFunc *NAME ## _table [8] = {\ | 46 | static GenOpFunc *NAME ## _table [8] = {\ |
| @@ -70,6 +73,25 @@ GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf) | @@ -70,6 +73,25 @@ GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf) | ||
| 70 | GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf) | 73 | GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf) |
| 71 | GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf) | 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 | GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr) | 95 | GEN32(gen_op_load_gpr_T0, gen_op_load_gpr_T0_gpr) |
| 74 | GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr) | 96 | GEN32(gen_op_load_gpr_T1, gen_op_load_gpr_T1_gpr) |
| 75 | GEN32(gen_op_load_gpr_T2, gen_op_load_gpr_T2_gpr) | 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,8 +100,13 @@ GEN32(gen_op_store_T0_gpr, gen_op_store_T0_gpr_gpr) | ||
| 78 | GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr) | 100 | GEN32(gen_op_store_T1_gpr, gen_op_store_T1_gpr_gpr) |
| 79 | GEN32(gen_op_store_T2_gpr, gen_op_store_T2_gpr_gpr) | 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 | static uint8_t spr_access[1024 / 2]; | 111 | static uint8_t spr_access[1024 / 2]; |
| 85 | 112 | ||
| @@ -198,10 +225,14 @@ EXTRACT_HELPER(SH, 11, 5); | @@ -198,10 +225,14 @@ EXTRACT_HELPER(SH, 11, 5); | ||
| 198 | EXTRACT_HELPER(MB, 6, 5); | 225 | EXTRACT_HELPER(MB, 6, 5); |
| 199 | /* Mask end */ | 226 | /* Mask end */ |
| 200 | EXTRACT_HELPER(ME, 1, 5); | 227 | EXTRACT_HELPER(ME, 1, 5); |
| 228 | +/* Trap operand */ | ||
| 229 | +EXTRACT_HELPER(TO, 21, 5); | ||
| 201 | 230 | ||
| 202 | EXTRACT_HELPER(CRM, 12, 8); | 231 | EXTRACT_HELPER(CRM, 12, 8); |
| 203 | EXTRACT_HELPER(FM, 17, 8); | 232 | EXTRACT_HELPER(FM, 17, 8); |
| 204 | EXTRACT_HELPER(SR, 16, 4); | 233 | EXTRACT_HELPER(SR, 16, 4); |
| 234 | +EXTRACT_HELPER(FPIMM, 20, 4); | ||
| 235 | + | ||
| 205 | /*** Jump target decoding ***/ | 236 | /*** Jump target decoding ***/ |
| 206 | /* Displacement */ | 237 | /* Displacement */ |
| 207 | EXTRACT_SHELPER(d, 0, 16); | 238 | EXTRACT_SHELPER(d, 0, 16); |
| @@ -597,6 +628,7 @@ GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) | @@ -597,6 +628,7 @@ GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) | ||
| 597 | mb = MB(ctx->opcode); | 628 | mb = MB(ctx->opcode); |
| 598 | me = ME(ctx->opcode); | 629 | me = ME(ctx->opcode); |
| 599 | gen_op_load_gpr_T0(rS(ctx->opcode)); | 630 | gen_op_load_gpr_T0(rS(ctx->opcode)); |
| 631 | + gen_op_load_gpr_T1(rA(ctx->opcode)); | ||
| 600 | gen_op_rlwimi(SH(ctx->opcode), MASK(mb, me), ~MASK(mb, me)); | 632 | gen_op_rlwimi(SH(ctx->opcode), MASK(mb, me), ~MASK(mb, me)); |
| 601 | if (Rc(ctx->opcode) != 0) | 633 | if (Rc(ctx->opcode) != 0) |
| 602 | gen_op_set_Rc0(); | 634 | gen_op_set_Rc0(); |
| @@ -847,47 +879,67 @@ GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) | @@ -847,47 +879,67 @@ GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT) | ||
| 847 | /* mcrfs */ | 879 | /* mcrfs */ |
| 848 | GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT) | 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 | /* mffs */ | 888 | /* mffs */ |
| 854 | GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT) | 889 | GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT) |
| 855 | { | 890 | { |
| 856 | gen_op_load_fpscr(); | 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 | SET_RETVAL(0); | 895 | SET_RETVAL(0); |
| 862 | } | 896 | } |
| 863 | 897 | ||
| 864 | /* mtfsb0 */ | 898 | /* mtfsb0 */ |
| 865 | GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT) | 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 | /* mtfsb1 */ | 912 | /* mtfsb1 */ |
| 871 | GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT) | 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 | /* mtfsf */ | 926 | /* mtfsf */ |
| 877 | GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT) | 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 | gen_op_store_fpscr(FM(ctx->opcode)); | 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 | SET_RETVAL(0); | 933 | SET_RETVAL(0); |
| 885 | } | 934 | } |
| 886 | 935 | ||
| 887 | /* mtfsfi */ | 936 | /* mtfsfi */ |
| 888 | GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT) | 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 | /*** Integer load ***/ | 945 | /*** Integer load ***/ |
| @@ -1179,13 +1231,11 @@ GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_MEM) | @@ -1179,13 +1231,11 @@ GEN_HANDLER(lwarx, 0x1F, 0x14, 0xFF, 0x00000001, PPC_MEM) | ||
| 1179 | reserve = 1; | 1231 | reserve = 1; |
| 1180 | if (rA(ctx->opcode) == 0) { | 1232 | if (rA(ctx->opcode) == 0) { |
| 1181 | gen_op_load_gpr_T0(rB(ctx->opcode)); | 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 | } else { | 1235 | } else { |
| 1185 | gen_op_load_gpr_T0(rA(ctx->opcode)); | 1236 | gen_op_load_gpr_T0(rA(ctx->opcode)); |
| 1186 | gen_op_load_gpr_T1(rB(ctx->opcode)); | 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 | gen_op_store_T1_gpr(rD(ctx->opcode)); | 1240 | gen_op_store_T1_gpr(rD(ctx->opcode)); |
| 1191 | SET_RETVAL(0); | 1241 | SET_RETVAL(0); |
| @@ -1207,8 +1257,6 @@ GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_MEM) | @@ -1207,8 +1257,6 @@ GEN_HANDLER(stwcx_, 0x1F, 0x16, 0x04, 0x00000000, PPC_MEM) | ||
| 1207 | gen_op_load_gpr_T2(rS(ctx->opcode)); | 1257 | gen_op_load_gpr_T2(rS(ctx->opcode)); |
| 1208 | gen_op_stwx(); | 1258 | gen_op_stwx(); |
| 1209 | } | 1259 | } |
| 1210 | - gen_op_set_Rc0_1(); | ||
| 1211 | - gen_op_reset_reservation(); | ||
| 1212 | } | 1260 | } |
| 1213 | SET_RETVAL(0); | 1261 | SET_RETVAL(0); |
| 1214 | } | 1262 | } |
| @@ -1294,7 +1342,7 @@ GEN_LDF(s, 0x10); | @@ -1294,7 +1342,7 @@ GEN_LDF(s, 0x10); | ||
| 1294 | GEN_HANDLER(stf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ | 1342 | GEN_HANDLER(stf##width, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ |
| 1295 | { \ | 1343 | { \ |
| 1296 | uint32_t simm = SIMM(ctx->opcode); \ | 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 | if (rA(ctx->opcode) == 0) { \ | 1346 | if (rA(ctx->opcode) == 0) { \ |
| 1299 | gen_op_stf##width##_z_FT0(simm); \ | 1347 | gen_op_stf##width##_z_FT0(simm); \ |
| 1300 | } else { \ | 1348 | } else { \ |
| @@ -1310,7 +1358,7 @@ GEN_HANDLER(stf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ | @@ -1310,7 +1358,7 @@ GEN_HANDLER(stf##width##u, opc, 0xFF, 0xFF, 0x00000000, PPC_FLOAT) \ | ||
| 1310 | if (rA(ctx->opcode) == 0) \ | 1358 | if (rA(ctx->opcode) == 0) \ |
| 1311 | SET_RETVAL(EXCP_INVAL); \ | 1359 | SET_RETVAL(EXCP_INVAL); \ |
| 1312 | gen_op_load_gpr_T0(rA(ctx->opcode)); \ | 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 | gen_op_stf##width##_FT0(SIMM(ctx->opcode)); \ | 1362 | gen_op_stf##width##_FT0(SIMM(ctx->opcode)); \ |
| 1315 | gen_op_store_T0_gpr(rA(ctx->opcode)); \ | 1363 | gen_op_store_T0_gpr(rA(ctx->opcode)); \ |
| 1316 | SET_RETVAL(0); \ | 1364 | SET_RETVAL(0); \ |
| @@ -1323,7 +1371,7 @@ GEN_HANDLER(stf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ | @@ -1323,7 +1371,7 @@ GEN_HANDLER(stf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ | ||
| 1323 | SET_RETVAL(EXCP_INVAL); \ | 1371 | SET_RETVAL(EXCP_INVAL); \ |
| 1324 | gen_op_load_gpr_T0(rA(ctx->opcode)); \ | 1372 | gen_op_load_gpr_T0(rA(ctx->opcode)); \ |
| 1325 | gen_op_load_gpr_T1(rB(ctx->opcode)); \ | 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 | gen_op_stf##width##x_FT0(); \ | 1375 | gen_op_stf##width##x_FT0(); \ |
| 1328 | gen_op_store_T0_gpr(rA(ctx->opcode)); \ | 1376 | gen_op_store_T0_gpr(rA(ctx->opcode)); \ |
| 1329 | SET_RETVAL(0); \ | 1377 | SET_RETVAL(0); \ |
| @@ -1332,7 +1380,7 @@ GEN_HANDLER(stf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ | @@ -1332,7 +1380,7 @@ GEN_HANDLER(stf##width##ux, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ | ||
| 1332 | #define GEN_STFX(width, opc) \ | 1380 | #define GEN_STFX(width, opc) \ |
| 1333 | GEN_HANDLER(stf##width##x, 0x1F, 0x17, opc, 0x00000001, PPC_FLOAT) \ | 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 | if (rA(ctx->opcode) == 0) { \ | 1384 | if (rA(ctx->opcode) == 0) { \ |
| 1337 | gen_op_load_gpr_T0(rB(ctx->opcode)); \ | 1385 | gen_op_load_gpr_T0(rB(ctx->opcode)); \ |
| 1338 | gen_op_stf##width##x_z_FT0(); \ | 1386 | gen_op_stf##width##x_z_FT0(); \ |
| @@ -1811,12 +1859,28 @@ GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x02, 0x03E00001, PPC_MEM) | @@ -1811,12 +1859,28 @@ GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x02, 0x03E00001, PPC_MEM) | ||
| 1811 | /* dcbz */ | 1859 | /* dcbz */ |
| 1812 | GEN_HANDLER(dcbz, 0x1F, 0x16, 0x08, 0x03E00001, PPC_MEM) | 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 | SET_RETVAL(0); | 1870 | SET_RETVAL(0); |
| 1815 | } | 1871 | } |
| 1816 | 1872 | ||
| 1817 | /* icbi */ | 1873 | /* icbi */ |
| 1818 | GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_MEM) | 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 | SET_RETVAL(0); | 1884 | SET_RETVAL(0); |
| 1821 | } | 1885 | } |
| 1822 | 1886 | ||
| @@ -2252,7 +2316,7 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags) | @@ -2252,7 +2316,7 @@ void cpu_ppc_dump_state(CPUPPCState *env, FILE *f, int flags) | ||
| 2252 | for (i = 0; i < 16; i++) { | 2316 | for (i = 0; i < 16; i++) { |
| 2253 | if ((i & 3) == 0) | 2317 | if ((i & 3) == 0) |
| 2254 | fprintf(logfile, "FPR%02d:", i); | 2318 | fprintf(logfile, "FPR%02d:", i); |
| 2255 | - fprintf(logfile, " %016llx", env->fpr[i]); | 2319 | + fprintf(logfile, " %016llx", *((uint64_t *)(&env->fpr[i]))); |
| 2256 | if ((i & 3) == 3) | 2320 | if ((i & 3) == 3) |
| 2257 | fprintf(logfile, "\n"); | 2321 | fprintf(logfile, "\n"); |
| 2258 | } | 2322 | } |
| @@ -2361,7 +2425,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, | @@ -2361,7 +2425,7 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, | ||
| 2361 | #endif | 2425 | #endif |
| 2362 | } | 2426 | } |
| 2363 | #if defined (DO_STEP_FLUSH) | 2427 | #if defined (DO_STEP_FLUSH) |
| 2364 | - tb_flush(); | 2428 | + tb_flush(env); |
| 2365 | #endif | 2429 | #endif |
| 2366 | /* We need to update the time base */ | 2430 | /* We need to update the time base */ |
| 2367 | if (!search_pc) | 2431 | if (!search_pc) |