Commit a9d9eb8fd45279fa8455afa03331296dbe2871ff

Authored by j_mayer
1 parent b33c17e1

Implement PowerPC Altivec load & stores, used by Apple firmware for memcpy.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3349 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/cpu.h
... ... @@ -292,7 +292,7 @@ typedef struct CPUPPCState CPUPPCState;
292 292 typedef struct ppc_tb_t ppc_tb_t;
293 293 typedef struct ppc_spr_t ppc_spr_t;
294 294 typedef struct ppc_dcr_t ppc_dcr_t;
295   -typedef struct ppc_avr_t ppc_avr_t;
  295 +typedef union ppc_avr_t ppc_avr_t;
296 296 typedef union ppc_tlb_t ppc_tlb_t;
297 297  
298 298 /* SPR access micro-ops generations callbacks */
... ... @@ -311,8 +311,11 @@ struct ppc_spr_t {
311 311 };
312 312  
313 313 /* Altivec registers (128 bits) */
314   -struct ppc_avr_t {
315   - uint32_t u[4];
  314 +union ppc_avr_t {
  315 + uint8_t u8[16];
  316 + uint16_t u16[8];
  317 + uint32_t u32[4];
  318 + uint64_t u64[2];
316 319 };
317 320  
318 321 /* Software TLB cache */
... ... @@ -454,7 +457,7 @@ struct CPUPPCState {
454 457 */
455 458 ppc_gpr_t t0, t1, t2;
456 459 #endif
457   - ppc_avr_t t0_avr, t1_avr, t2_avr;
  460 + ppc_avr_t avr0, avr1, avr2;
458 461  
459 462 /* general purpose registers */
460 463 ppc_gpr_t gpr[32];
... ...
target-ppc/exec.h
... ... @@ -54,9 +54,9 @@ register unsigned long T2 asm(AREG3);
54 54 #define T2_64 T2
55 55 #endif
56 56 /* Provision for Altivec */
57   -#define T0_avr (env->t0_avr)
58   -#define T1_avr (env->t1_avr)
59   -#define T2_avr (env->t2_avr)
  57 +#define AVR0 (env->avr0)
  58 +#define AVR1 (env->avr1)
  59 +#define AVR2 (env->avr2)
60 60  
61 61 #define FT0 (env->ft0)
62 62 #define FT1 (env->ft1)
... ...
target-ppc/op_mem.h
... ... @@ -1054,6 +1054,66 @@ void OPPROTO glue(op_POWER2_stfq_le, MEMSUFFIX) (void)
1054 1054 RETURN();
1055 1055 }
1056 1056  
  1057 +/* Altivec vector extension */
  1058 +#if defined(WORDS_BIGENDIAN)
  1059 +#define VR_DWORD0 0
  1060 +#define VR_DWORD1 1
  1061 +#else
  1062 +#define VR_DWORD0 1
  1063 +#define VR_DWORD1 0
  1064 +#endif
  1065 +void OPPROTO glue(op_vr_lvx, MEMSUFFIX) (void)
  1066 +{
  1067 + AVR0.u64[VR_DWORD0] = glue(ldq, MEMSUFFIX)((uint32_t)T0);
  1068 + AVR0.u64[VR_DWORD1] = glue(ldq, MEMSUFFIX)((uint32_t)T0 + 8);
  1069 +}
  1070 +
  1071 +void OPPROTO glue(op_vr_lvx_le, MEMSUFFIX) (void)
  1072 +{
  1073 + AVR0.u64[VR_DWORD1] = glue(ldq, MEMSUFFIX)((uint32_t)T0);
  1074 + AVR0.u64[VR_DWORD0] = glue(ldq, MEMSUFFIX)((uint32_t)T0 + 8);
  1075 +}
  1076 +
  1077 +void OPPROTO glue(op_vr_stvx, MEMSUFFIX) (void)
  1078 +{
  1079 + glue(stq, MEMSUFFIX)((uint32_t)T0, AVR0.u64[VR_DWORD0]);
  1080 + glue(stq, MEMSUFFIX)((uint32_t)T0 + 8, AVR0.u64[VR_DWORD1]);
  1081 +}
  1082 +
  1083 +void OPPROTO glue(op_vr_stvx_le, MEMSUFFIX) (void)
  1084 +{
  1085 + glue(stq, MEMSUFFIX)((uint32_t)T0, AVR0.u64[VR_DWORD1]);
  1086 + glue(stq, MEMSUFFIX)((uint32_t)T0 + 8, AVR0.u64[VR_DWORD0]);
  1087 +}
  1088 +
  1089 +#if defined(TARGET_PPC64)
  1090 +void OPPROTO glue(op_vr_lvx_64, MEMSUFFIX) (void)
  1091 +{
  1092 + AVR0.u64[VR_DWORD0] = glue(ldq, MEMSUFFIX)((uint64_t)T0);
  1093 + AVR0.u64[VR_DWORD1] = glue(ldq, MEMSUFFIX)((uint64_t)T0 + 8);
  1094 +}
  1095 +
  1096 +void OPPROTO glue(op_vr_lvx_le_64, MEMSUFFIX) (void)
  1097 +{
  1098 + AVR0.u64[VR_DWORD1] = glue(ldq, MEMSUFFIX)((uint64_t)T0);
  1099 + AVR0.u64[VR_DWORD0] = glue(ldq, MEMSUFFIX)((uint64_t)T0 + 8);
  1100 +}
  1101 +
  1102 +void OPPROTO glue(op_vr_stvx_64, MEMSUFFIX) (void)
  1103 +{
  1104 + glue(stq, MEMSUFFIX)((uint64_t)T0, AVR0.u64[VR_DWORD0]);
  1105 + glue(stq, MEMSUFFIX)((uint64_t)T0 + 8, AVR0.u64[VR_DWORD1]);
  1106 +}
  1107 +
  1108 +void OPPROTO glue(op_vr_stvx_le_64, MEMSUFFIX) (void)
  1109 +{
  1110 + glue(stq, MEMSUFFIX)((uint64_t)T0, AVR0.u64[VR_DWORD1]);
  1111 + glue(stq, MEMSUFFIX)((uint64_t)T0 + 8, AVR0.u64[VR_DWORD0]);
  1112 +}
  1113 +#endif
  1114 +#undef VR_DWORD0
  1115 +#undef VR_DWORD1
  1116 +
1057 1117 #if defined(TARGET_PPCEMB)
1058 1118 /* SPE extension */
1059 1119 #define _PPC_SPE_LD_OP(name, op) \
... ...
target-ppc/op_template.h
... ... @@ -57,6 +57,7 @@ void OPPROTO glue(op_store_T2_gpr_gpr, REG) (void)
57 57 }
58 58 #endif
59 59  
  60 +/* General purpose registers containing vector operands moves */
60 61 #if defined(TARGET_PPCEMB)
61 62 void OPPROTO glue(op_load_gpr64_T0_gpr, REG) (void)
62 63 {
... ... @@ -99,6 +100,45 @@ void OPPROTO glue(op_store_T2_gpr64_gpr, REG) (void)
99 100 #endif
100 101 #endif /* defined(TARGET_PPCEMB) */
101 102  
  103 +/* Altivec registers moves */
  104 +void OPPROTO glue(op_load_avr_A0_avr, REG) (void)
  105 +{
  106 + AVR0 = env->avr[REG];
  107 + RETURN();
  108 +}
  109 +
  110 +void OPPROTO glue(op_load_avr_A1_avr, REG) (void)
  111 +{
  112 + AVR1 = env->avr[REG];
  113 + RETURN();
  114 +}
  115 +
  116 +void OPPROTO glue(op_load_avr_A2_avr, REG) (void)
  117 +{
  118 + AVR2 = env->avr[REG];
  119 + RETURN();
  120 +}
  121 +
  122 +void OPPROTO glue(op_store_A0_avr_avr, REG) (void)
  123 +{
  124 + env->avr[REG] = AVR0;
  125 + RETURN();
  126 +}
  127 +
  128 +void OPPROTO glue(op_store_A1_avr_avr, REG) (void)
  129 +{
  130 + env->avr[REG] = AVR1;
  131 + RETURN();
  132 +}
  133 +
  134 +#if 0 // unused
  135 +void OPPROTO glue(op_store_A2_avr_avr, REG) (void)
  136 +{
  137 + env->avr[REG] = AVR2;
  138 + RETURN();
  139 +}
  140 +#endif
  141 +
102 142 #if REG <= 7
103 143 /* Condition register moves */
104 144 void OPPROTO glue(op_load_crf_T0_crf, REG) (void)
... ...
target-ppc/translate.c
... ... @@ -164,6 +164,7 @@ typedef struct DisasContext {
164 164 int sf_mode;
165 165 #endif
166 166 int fpu_enabled;
  167 + int altivec_enabled;
167 168 #if defined(TARGET_PPCEMB)
168 169 int spe_enabled;
169 170 #endif
... ... @@ -235,6 +236,9 @@ GEN_EXCP(ctx, POWERPC_EXCP_FPU, 0)
235 236 #define GEN_EXCP_NO_AP(ctx) \
236 237 GEN_EXCP(ctx, POWERPC_EXCP_APU, 0)
237 238  
  239 +#define GEN_EXCP_NO_VR(ctx) \
  240 +GEN_EXCP(ctx, POWERPC_EXCP_VPU, 0)
  241 +
238 242 /* Stop translation */
239 243 static always_inline void GEN_STOP (DisasContext *ctx)
240 244 {
... ... @@ -5530,6 +5534,161 @@ GEN_HANDLER(icbt_440, 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
5530 5534 */
5531 5535 }
5532 5536  
  5537 +/*** Altivec vector extension ***/
  5538 +/* Altivec registers moves */
  5539 +GEN32(gen_op_load_avr_A0, gen_op_load_avr_A0_avr);
  5540 +GEN32(gen_op_load_avr_A1, gen_op_load_avr_A1_avr);
  5541 +GEN32(gen_op_load_avr_A2, gen_op_load_avr_A2_avr);
  5542 +
  5543 +GEN32(gen_op_store_A0_avr, gen_op_store_A0_avr_avr);
  5544 +GEN32(gen_op_store_A1_avr, gen_op_store_A1_avr_avr);
  5545 +#if 0 // unused
  5546 +GEN32(gen_op_store_A2_avr, gen_op_store_A2_avr_avr);
  5547 +#endif
  5548 +
  5549 +#define op_vr_ldst(name) (*gen_op_##name[ctx->mem_idx])()
  5550 +#if defined(CONFIG_USER_ONLY)
  5551 +#if defined(TARGET_PPC64)
  5552 +/* User-mode only - 64 bits mode */
  5553 +#define OP_VR_LD_TABLE(name) \
  5554 +static GenOpFunc *gen_op_vr_l##name[] = { \
  5555 + &gen_op_vr_l##name##_raw, \
  5556 + &gen_op_vr_l##name##_le_raw, \
  5557 + &gen_op_vr_l##name##_64_raw, \
  5558 + &gen_op_vr_l##name##_le_64_raw, \
  5559 +};
  5560 +#define OP_VR_ST_TABLE(name) \
  5561 +static GenOpFunc *gen_op_vr_st##name[] = { \
  5562 + &gen_op_vr_st##name##_raw, \
  5563 + &gen_op_vr_st##name##_le_raw, \
  5564 + &gen_op_vr_st##name##_64_raw, \
  5565 + &gen_op_vr_st##name##_le_64_raw, \
  5566 +};
  5567 +#else /* defined(TARGET_PPC64) */
  5568 +/* User-mode only - 32 bits mode */
  5569 +#define OP_VR_LD_TABLE(name) \
  5570 +static GenOpFunc *gen_op_vr_l##name[] = { \
  5571 + &gen_op_vr_l##name##_raw, \
  5572 + &gen_op_vr_l##name##_le_raw, \
  5573 +};
  5574 +#define OP_VR_ST_TABLE(name) \
  5575 +static GenOpFunc *gen_op_vr_st##name[] = { \
  5576 + &gen_op_vr_st##name##_raw, \
  5577 + &gen_op_vr_st##name##_le_raw, \
  5578 +};
  5579 +#endif /* defined(TARGET_PPC64) */
  5580 +#else /* defined(CONFIG_USER_ONLY) */
  5581 +#if defined(TARGET_PPC64H)
  5582 +/* Full system with hypervisor mode */
  5583 +#define OP_VR_LD_TABLE(name) \
  5584 +static GenOpFunc *gen_op_vr_l##name[] = { \
  5585 + &gen_op_vr_l##name##_user, \
  5586 + &gen_op_vr_l##name##_le_user, \
  5587 + &gen_op_vr_l##name##_64_user, \
  5588 + &gen_op_vr_l##name##_le_64_user, \
  5589 + &gen_op_vr_l##name##_kernel, \
  5590 + &gen_op_vr_l##name##_le_kernel, \
  5591 + &gen_op_vr_l##name##_64_kernel, \
  5592 + &gen_op_vr_l##name##_le_64_kernel, \
  5593 + &gen_op_vr_l##name##_hypv, \
  5594 + &gen_op_vr_l##name##_le_hypv, \
  5595 + &gen_op_vr_l##name##_64_hypv, \
  5596 + &gen_op_vr_l##name##_le_64_hypv, \
  5597 +};
  5598 +#define OP_VR_ST_TABLE(name) \
  5599 +static GenOpFunc *gen_op_vr_st##name[] = { \
  5600 + &gen_op_vr_st##name##_user, \
  5601 + &gen_op_vr_st##name##_le_user, \
  5602 + &gen_op_vr_st##name##_64_user, \
  5603 + &gen_op_vr_st##name##_le_64_user, \
  5604 + &gen_op_vr_st##name##_kernel, \
  5605 + &gen_op_vr_st##name##_le_kernel, \
  5606 + &gen_op_vr_st##name##_64_kernel, \
  5607 + &gen_op_vr_st##name##_le_64_kernel, \
  5608 + &gen_op_vr_st##name##_hypv, \
  5609 + &gen_op_vr_st##name##_le_hypv, \
  5610 + &gen_op_vr_st##name##_64_hypv, \
  5611 + &gen_op_vr_st##name##_le_64_hypv, \
  5612 +};
  5613 +#elif defined(TARGET_PPC64)
  5614 +/* Full system - 64 bits mode */
  5615 +#define OP_VR_LD_TABLE(name) \
  5616 +static GenOpFunc *gen_op_vr_l##name[] = { \
  5617 + &gen_op_vr_l##name##_user, \
  5618 + &gen_op_vr_l##name##_le_user, \
  5619 + &gen_op_vr_l##name##_64_user, \
  5620 + &gen_op_vr_l##name##_le_64_user, \
  5621 + &gen_op_vr_l##name##_kernel, \
  5622 + &gen_op_vr_l##name##_le_kernel, \
  5623 + &gen_op_vr_l##name##_64_kernel, \
  5624 + &gen_op_vr_l##name##_le_64_kernel, \
  5625 +};
  5626 +#define OP_VR_ST_TABLE(name) \
  5627 +static GenOpFunc *gen_op_vr_st##name[] = { \
  5628 + &gen_op_vr_st##name##_user, \
  5629 + &gen_op_vr_st##name##_le_user, \
  5630 + &gen_op_vr_st##name##_64_user, \
  5631 + &gen_op_vr_st##name##_le_64_user, \
  5632 + &gen_op_vr_st##name##_kernel, \
  5633 + &gen_op_vr_st##name##_le_kernel, \
  5634 + &gen_op_vr_st##name##_64_kernel, \
  5635 + &gen_op_vr_st##name##_le_64_kernel, \
  5636 +};
  5637 +#else /* defined(TARGET_PPC64) */
  5638 +/* Full system - 32 bits mode */
  5639 +#define OP_VR_LD_TABLE(name) \
  5640 +static GenOpFunc *gen_op_vr_l##name[] = { \
  5641 + &gen_op_vr_l##name##_user, \
  5642 + &gen_op_vr_l##name##_le_user, \
  5643 + &gen_op_vr_l##name##_kernel, \
  5644 + &gen_op_vr_l##name##_le_kernel, \
  5645 +};
  5646 +#define OP_VR_ST_TABLE(name) \
  5647 +static GenOpFunc *gen_op_vr_st##name[] = { \
  5648 + &gen_op_vr_st##name##_user, \
  5649 + &gen_op_vr_st##name##_le_user, \
  5650 + &gen_op_vr_st##name##_kernel, \
  5651 + &gen_op_vr_st##name##_le_kernel, \
  5652 +};
  5653 +#endif /* defined(TARGET_PPC64) */
  5654 +#endif /* defined(CONFIG_USER_ONLY) */
  5655 +
  5656 +#define GEN_VR_LDX(name, opc2, opc3) \
  5657 +GEN_HANDLER(l##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
  5658 +{ \
  5659 + if (unlikely(!ctx->altivec_enabled)) { \
  5660 + GEN_EXCP_NO_VR(ctx); \
  5661 + return; \
  5662 + } \
  5663 + gen_addr_reg_index(ctx); \
  5664 + op_vr_ldst(vr_l##name); \
  5665 + gen_op_store_A0_avr(rD(ctx->opcode)); \
  5666 +}
  5667 +
  5668 +#define GEN_VR_STX(name, opc2, opc3) \
  5669 +GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
  5670 +{ \
  5671 + if (unlikely(!ctx->altivec_enabled)) { \
  5672 + GEN_EXCP_NO_VR(ctx); \
  5673 + return; \
  5674 + } \
  5675 + gen_addr_reg_index(ctx); \
  5676 + gen_op_load_avr_A0(rS(ctx->opcode)); \
  5677 + op_vr_ldst(vr_st##name); \
  5678 +}
  5679 +
  5680 +OP_VR_LD_TABLE(vx);
  5681 +GEN_VR_LDX(vx, 0x07, 0x03);
  5682 +/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
  5683 +#define gen_op_vr_lvxl gen_op_vr_lvx
  5684 +GEN_VR_LDX(vxl, 0x07, 0x0B);
  5685 +
  5686 +OP_VR_ST_TABLE(vx);
  5687 +GEN_VR_STX(vx, 0x07, 0x07);
  5688 +/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
  5689 +#define gen_op_vr_stvxl gen_op_vr_stvx
  5690 +GEN_VR_STX(vxl, 0x07, 0x0F);
  5691 +
5533 5692 #if defined(TARGET_PPCEMB)
5534 5693 /*** SPE extension ***/
5535 5694  
... ... @@ -6553,11 +6712,15 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
6553 6712 ctx.dcache_line_size = env->dcache_line_size;
6554 6713 ctx.fpu_enabled = msr_fp;
6555 6714 #if defined(TARGET_PPCEMB)
6556   - if (env->flags & POWERPC_FLAG_SPE)
  6715 + if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
6557 6716 ctx.spe_enabled = msr_spe;
6558 6717 else
6559 6718 ctx.spe_enabled = 0;
6560 6719 #endif
  6720 + if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
  6721 + ctx.altivec_enabled = msr_vr;
  6722 + else
  6723 + ctx.altivec_enabled = 0;
6561 6724 if ((env->flags & POWERPC_FLAG_SE) && msr_se)
6562 6725 single_step = 1;
6563 6726 else
... ...