Commit 2cade6a3f60cc203ee2b3fc44d06af3ec048e379
1 parent
a5a52cf2
Support for address masking
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4882 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
58 additions
and
33 deletions
cpu-exec.c
| ... | ... | @@ -184,8 +184,9 @@ static inline TranslationBlock *tb_find_fast(void) |
| 184 | 184 | pc = env->regs[15]; |
| 185 | 185 | #elif defined(TARGET_SPARC) |
| 186 | 186 | #ifdef TARGET_SPARC64 |
| 187 | - // Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled | |
| 188 | - flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2)) | |
| 187 | + // AM . Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled | |
| 188 | + flags = ((env->pstate & PS_AM) << 2) | |
| 189 | + | (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2)) | |
| 189 | 190 | | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2); |
| 190 | 191 | #else |
| 191 | 192 | // FPU enable . Supervisor | ... | ... |
target-sparc/op_helper.c
| ... | ... | @@ -32,12 +32,22 @@ do { printf("ASI: " fmt , ##args); } while (0) |
| 32 | 32 | #define DPRINTF_ASI(fmt, args...) do {} while (0) |
| 33 | 33 | #endif |
| 34 | 34 | |
| 35 | -#ifdef TARGET_ABI32 | |
| 36 | -#define ABI32_MASK(addr) do { (addr) &= 0xffffffffULL; } while (0) | |
| 35 | +#ifdef TARGET_SPARC64 | |
| 36 | +#ifndef TARGET_ABI32 | |
| 37 | +#define AM_CHECK(env1) ((env1)->pstate & PS_AM) | |
| 37 | 38 | #else |
| 38 | -#define ABI32_MASK(addr) do {} while (0) | |
| 39 | +#define AM_CHECK(env1) (1) | |
| 40 | +#endif | |
| 39 | 41 | #endif |
| 40 | 42 | |
| 43 | +static inline void address_mask(CPUState *env1, target_ulong *addr) | |
| 44 | +{ | |
| 45 | +#ifdef TARGET_SPARC64 | |
| 46 | + if (AM_CHECK(env1)) | |
| 47 | + *addr &= 0xffffffffULL; | |
| 48 | +#endif | |
| 49 | +} | |
| 50 | + | |
| 41 | 51 | void raise_exception(int tt) |
| 42 | 52 | { |
| 43 | 53 | env->exception_index = tt; |
| ... | ... | @@ -1381,7 +1391,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign) |
| 1381 | 1391 | raise_exception(TT_PRIV_ACT); |
| 1382 | 1392 | |
| 1383 | 1393 | helper_check_align(addr, size - 1); |
| 1384 | - ABI32_MASK(addr); | |
| 1394 | + address_mask(env, &addr); | |
| 1385 | 1395 | |
| 1386 | 1396 | switch (asi) { |
| 1387 | 1397 | case 0x80: // Primary |
| ... | ... | @@ -1470,7 +1480,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size) |
| 1470 | 1480 | raise_exception(TT_PRIV_ACT); |
| 1471 | 1481 | |
| 1472 | 1482 | helper_check_align(addr, size - 1); |
| 1473 | - ABI32_MASK(addr); | |
| 1483 | + address_mask(env, &addr); | |
| 1474 | 1484 | |
| 1475 | 1485 | /* Convert to little endian */ |
| 1476 | 1486 | switch (asi) { |
| ... | ... | @@ -2330,7 +2340,7 @@ void helper_stdf(target_ulong addr, int mem_idx) |
| 2330 | 2340 | break; |
| 2331 | 2341 | } |
| 2332 | 2342 | #else |
| 2333 | - ABI32_MASK(addr); | |
| 2343 | + address_mask(env, &addr); | |
| 2334 | 2344 | stfq_raw(addr, DT0); |
| 2335 | 2345 | #endif |
| 2336 | 2346 | } |
| ... | ... | @@ -2355,7 +2365,7 @@ void helper_lddf(target_ulong addr, int mem_idx) |
| 2355 | 2365 | break; |
| 2356 | 2366 | } |
| 2357 | 2367 | #else |
| 2358 | - ABI32_MASK(addr); | |
| 2368 | + address_mask(env, &addr); | |
| 2359 | 2369 | DT0 = ldfq_raw(addr); |
| 2360 | 2370 | #endif |
| 2361 | 2371 | } |
| ... | ... | @@ -2389,7 +2399,7 @@ void helper_ldqf(target_ulong addr, int mem_idx) |
| 2389 | 2399 | break; |
| 2390 | 2400 | } |
| 2391 | 2401 | #else |
| 2392 | - ABI32_MASK(addr); | |
| 2402 | + address_mask(env, &addr); | |
| 2393 | 2403 | u.ll.upper = ldq_raw(addr); |
| 2394 | 2404 | u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL); |
| 2395 | 2405 | QT0 = u.q; |
| ... | ... | @@ -2426,7 +2436,7 @@ void helper_stqf(target_ulong addr, int mem_idx) |
| 2426 | 2436 | } |
| 2427 | 2437 | #else |
| 2428 | 2438 | u.q = QT0; |
| 2429 | - ABI32_MASK(addr); | |
| 2439 | + address_mask(env, &addr); | |
| 2430 | 2440 | stq_raw(addr, u.ll.upper); |
| 2431 | 2441 | stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower); |
| 2432 | 2442 | #endif | ... | ... |
target-sparc/translate.c
| ... | ... | @@ -57,6 +57,7 @@ typedef struct DisasContext { |
| 57 | 57 | int is_br; |
| 58 | 58 | int mem_idx; |
| 59 | 59 | int fpu_enabled; |
| 60 | + int address_mask_32bit; | |
| 60 | 61 | struct TranslationBlock *tb; |
| 61 | 62 | uint32_t features; |
| 62 | 63 | } DisasContext; |
| ... | ... | @@ -201,12 +202,22 @@ static void gen_op_store_QT0_fpr(unsigned int dst) |
| 201 | 202 | #endif |
| 202 | 203 | #endif |
| 203 | 204 | |
| 204 | -#ifdef TARGET_ABI32 | |
| 205 | -#define ABI32_MASK(addr) tcg_gen_andi_tl(addr, addr, 0xffffffffULL); | |
| 205 | +#ifdef TARGET_SPARC64 | |
| 206 | +#ifndef TARGET_ABI32 | |
| 207 | +#define AM_CHECK(dc) ((dc)->address_mask_32bit) | |
| 206 | 208 | #else |
| 207 | -#define ABI32_MASK(addr) | |
| 209 | +#define AM_CHECK(dc) (1) | |
| 210 | +#endif | |
| 208 | 211 | #endif |
| 209 | 212 | |
| 213 | +static inline void gen_address_mask(DisasContext *dc, TCGv addr) | |
| 214 | +{ | |
| 215 | +#ifdef TARGET_SPARC64 | |
| 216 | + if (AM_CHECK(dc)) | |
| 217 | + tcg_gen_andi_tl(addr, addr, 0xffffffffULL); | |
| 218 | +#endif | |
| 219 | +} | |
| 220 | + | |
| 210 | 221 | static inline void gen_movl_reg_TN(int reg, TCGv tn) |
| 211 | 222 | { |
| 212 | 223 | if (reg == 0) |
| ... | ... | @@ -4199,15 +4210,15 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4199 | 4210 | (xop > 0x2c && xop <= 0x33) || xop == 0x1f || xop == 0x3d) { |
| 4200 | 4211 | switch (xop) { |
| 4201 | 4212 | case 0x0: /* load unsigned word */ |
| 4202 | - ABI32_MASK(cpu_addr); | |
| 4213 | + gen_address_mask(dc, cpu_addr); | |
| 4203 | 4214 | tcg_gen_qemu_ld32u(cpu_val, cpu_addr, dc->mem_idx); |
| 4204 | 4215 | break; |
| 4205 | 4216 | case 0x1: /* load unsigned byte */ |
| 4206 | - ABI32_MASK(cpu_addr); | |
| 4217 | + gen_address_mask(dc, cpu_addr); | |
| 4207 | 4218 | tcg_gen_qemu_ld8u(cpu_val, cpu_addr, dc->mem_idx); |
| 4208 | 4219 | break; |
| 4209 | 4220 | case 0x2: /* load unsigned halfword */ |
| 4210 | - ABI32_MASK(cpu_addr); | |
| 4221 | + gen_address_mask(dc, cpu_addr); | |
| 4211 | 4222 | tcg_gen_qemu_ld16u(cpu_val, cpu_addr, dc->mem_idx); |
| 4212 | 4223 | break; |
| 4213 | 4224 | case 0x3: /* load double word */ |
| ... | ... | @@ -4221,7 +4232,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4221 | 4232 | tcg_gen_helper_0_2(helper_check_align, cpu_addr, |
| 4222 | 4233 | r_const); // XXX remove |
| 4223 | 4234 | tcg_temp_free(r_const); |
| 4224 | - ABI32_MASK(cpu_addr); | |
| 4235 | + gen_address_mask(dc, cpu_addr); | |
| 4225 | 4236 | tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx); |
| 4226 | 4237 | tcg_gen_trunc_i64_tl(cpu_tmp0, cpu_tmp64); |
| 4227 | 4238 | tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffffULL); |
| ... | ... | @@ -4232,18 +4243,18 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4232 | 4243 | } |
| 4233 | 4244 | break; |
| 4234 | 4245 | case 0x9: /* load signed byte */ |
| 4235 | - ABI32_MASK(cpu_addr); | |
| 4246 | + gen_address_mask(dc, cpu_addr); | |
| 4236 | 4247 | tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx); |
| 4237 | 4248 | break; |
| 4238 | 4249 | case 0xa: /* load signed halfword */ |
| 4239 | - ABI32_MASK(cpu_addr); | |
| 4250 | + gen_address_mask(dc, cpu_addr); | |
| 4240 | 4251 | tcg_gen_qemu_ld16s(cpu_val, cpu_addr, dc->mem_idx); |
| 4241 | 4252 | break; |
| 4242 | 4253 | case 0xd: /* ldstub -- XXX: should be atomically */ |
| 4243 | 4254 | { |
| 4244 | 4255 | TCGv r_const; |
| 4245 | 4256 | |
| 4246 | - ABI32_MASK(cpu_addr); | |
| 4257 | + gen_address_mask(dc, cpu_addr); | |
| 4247 | 4258 | tcg_gen_qemu_ld8s(cpu_val, cpu_addr, dc->mem_idx); |
| 4248 | 4259 | r_const = tcg_const_tl(0xff); |
| 4249 | 4260 | tcg_gen_qemu_st8(r_const, cpu_addr, dc->mem_idx); |
| ... | ... | @@ -4254,7 +4265,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4254 | 4265 | atomically */ |
| 4255 | 4266 | CHECK_IU_FEATURE(dc, SWAP); |
| 4256 | 4267 | gen_movl_reg_TN(rd, cpu_val); |
| 4257 | - ABI32_MASK(cpu_addr); | |
| 4268 | + gen_address_mask(dc, cpu_addr); | |
| 4258 | 4269 | tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx); |
| 4259 | 4270 | tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx); |
| 4260 | 4271 | tcg_gen_extu_i32_tl(cpu_val, cpu_tmp32); |
| ... | ... | @@ -4356,11 +4367,11 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4356 | 4367 | #endif |
| 4357 | 4368 | #ifdef TARGET_SPARC64 |
| 4358 | 4369 | case 0x08: /* V9 ldsw */ |
| 4359 | - ABI32_MASK(cpu_addr); | |
| 4370 | + gen_address_mask(dc, cpu_addr); | |
| 4360 | 4371 | tcg_gen_qemu_ld32s(cpu_val, cpu_addr, dc->mem_idx); |
| 4361 | 4372 | break; |
| 4362 | 4373 | case 0x0b: /* V9 ldx */ |
| 4363 | - ABI32_MASK(cpu_addr); | |
| 4374 | + gen_address_mask(dc, cpu_addr); | |
| 4364 | 4375 | tcg_gen_qemu_ld64(cpu_val, cpu_addr, dc->mem_idx); |
| 4365 | 4376 | break; |
| 4366 | 4377 | case 0x18: /* V9 ldswa */ |
| ... | ... | @@ -4402,13 +4413,13 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4402 | 4413 | save_state(dc, cpu_cond); |
| 4403 | 4414 | switch (xop) { |
| 4404 | 4415 | case 0x20: /* load fpreg */ |
| 4405 | - ABI32_MASK(cpu_addr); | |
| 4416 | + gen_address_mask(dc, cpu_addr); | |
| 4406 | 4417 | tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx); |
| 4407 | 4418 | tcg_gen_st_i32(cpu_tmp32, cpu_env, |
| 4408 | 4419 | offsetof(CPUState, fpr[rd])); |
| 4409 | 4420 | break; |
| 4410 | 4421 | case 0x21: /* load fsr */ |
| 4411 | - ABI32_MASK(cpu_addr); | |
| 4422 | + gen_address_mask(dc, cpu_addr); | |
| 4412 | 4423 | tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx); |
| 4413 | 4424 | tcg_gen_st_i32(cpu_tmp32, cpu_env, |
| 4414 | 4425 | offsetof(CPUState, ft0)); |
| ... | ... | @@ -4443,15 +4454,15 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4443 | 4454 | gen_movl_reg_TN(rd, cpu_val); |
| 4444 | 4455 | switch (xop) { |
| 4445 | 4456 | case 0x4: /* store word */ |
| 4446 | - ABI32_MASK(cpu_addr); | |
| 4457 | + gen_address_mask(dc, cpu_addr); | |
| 4447 | 4458 | tcg_gen_qemu_st32(cpu_val, cpu_addr, dc->mem_idx); |
| 4448 | 4459 | break; |
| 4449 | 4460 | case 0x5: /* store byte */ |
| 4450 | - ABI32_MASK(cpu_addr); | |
| 4461 | + gen_address_mask(dc, cpu_addr); | |
| 4451 | 4462 | tcg_gen_qemu_st8(cpu_val, cpu_addr, dc->mem_idx); |
| 4452 | 4463 | break; |
| 4453 | 4464 | case 0x6: /* store halfword */ |
| 4454 | - ABI32_MASK(cpu_addr); | |
| 4465 | + gen_address_mask(dc, cpu_addr); | |
| 4455 | 4466 | tcg_gen_qemu_st16(cpu_val, cpu_addr, dc->mem_idx); |
| 4456 | 4467 | break; |
| 4457 | 4468 | case 0x7: /* store double word */ |
| ... | ... | @@ -4461,7 +4472,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4461 | 4472 | TCGv r_low, r_const; |
| 4462 | 4473 | |
| 4463 | 4474 | save_state(dc, cpu_cond); |
| 4464 | - ABI32_MASK(cpu_addr); | |
| 4475 | + gen_address_mask(dc, cpu_addr); | |
| 4465 | 4476 | r_const = tcg_const_i32(7); |
| 4466 | 4477 | tcg_gen_helper_0_2(helper_check_align, cpu_addr, |
| 4467 | 4478 | r_const); // XXX remove |
| ... | ... | @@ -4522,7 +4533,7 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4522 | 4533 | #endif |
| 4523 | 4534 | #ifdef TARGET_SPARC64 |
| 4524 | 4535 | case 0x0e: /* V9 stx */ |
| 4525 | - ABI32_MASK(cpu_addr); | |
| 4536 | + gen_address_mask(dc, cpu_addr); | |
| 4526 | 4537 | tcg_gen_qemu_st64(cpu_val, cpu_addr, dc->mem_idx); |
| 4527 | 4538 | break; |
| 4528 | 4539 | case 0x1e: /* V9 stxa */ |
| ... | ... | @@ -4539,13 +4550,13 @@ static void disas_sparc_insn(DisasContext * dc) |
| 4539 | 4550 | save_state(dc, cpu_cond); |
| 4540 | 4551 | switch (xop) { |
| 4541 | 4552 | case 0x24: /* store fpreg */ |
| 4542 | - ABI32_MASK(cpu_addr); | |
| 4553 | + gen_address_mask(dc, cpu_addr); | |
| 4543 | 4554 | tcg_gen_ld_i32(cpu_tmp32, cpu_env, |
| 4544 | 4555 | offsetof(CPUState, fpr[rd])); |
| 4545 | 4556 | tcg_gen_qemu_st32(cpu_tmp32, cpu_addr, dc->mem_idx); |
| 4546 | 4557 | break; |
| 4547 | 4558 | case 0x25: /* stfsr, V9 stxfsr */ |
| 4548 | - ABI32_MASK(cpu_addr); | |
| 4559 | + gen_address_mask(dc, cpu_addr); | |
| 4549 | 4560 | tcg_gen_helper_0_0(helper_stfsr); |
| 4550 | 4561 | tcg_gen_ld_i32(cpu_tmp32, cpu_env, |
| 4551 | 4562 | offsetof(CPUState, ft0)); |
| ... | ... | @@ -4739,6 +4750,9 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, |
| 4739 | 4750 | #endif |
| 4740 | 4751 | } else |
| 4741 | 4752 | dc->fpu_enabled = 0; |
| 4753 | +#ifdef TARGET_SPARC64 | |
| 4754 | + dc->address_mask_32bit = env->pstate & PS_AM; | |
| 4755 | +#endif | |
| 4742 | 4756 | gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; |
| 4743 | 4757 | |
| 4744 | 4758 | cpu_tmp0 = tcg_temp_new(TCG_TYPE_TL); | ... | ... |