Revision a9d9eb8f
b/target-ppc/cpu.h | ||
---|---|---|
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 | 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 | 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]; |
b/target-ppc/exec.h | ||
---|---|---|
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) |
b/target-ppc/op_mem.h | ||
---|---|---|
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) \ |
b/target-ppc/op_template.h | ||
---|---|---|
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 | 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) |
b/target-ppc/translate.c | ||
---|---|---|
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 | 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 | 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 | 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 |
Also available in: Unified diff