71 |
71 |
|
72 |
72 |
/* dyngen register indexes */
|
73 |
73 |
static TCGv cpu_T[3];
|
74 |
|
#if defined(TARGET_PPC64)
|
75 |
|
#define cpu_T64 cpu_T
|
76 |
|
#else
|
77 |
|
static TCGv_i64 cpu_T64[3];
|
78 |
|
#endif
|
79 |
74 |
static TCGv_i64 cpu_FT[2];
|
80 |
75 |
|
81 |
76 |
#include "gen-icount.h"
|
... | ... | |
107 |
102 |
cpu_T[2] = tcg_global_reg_new(TCG_AREG3, "T2");
|
108 |
103 |
#endif
|
109 |
104 |
#endif
|
110 |
|
#if !defined(TARGET_PPC64)
|
111 |
|
cpu_T64[0] = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, t0_64),
|
112 |
|
"T0_64");
|
113 |
|
cpu_T64[1] = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, t1_64),
|
114 |
|
"T1_64");
|
115 |
|
cpu_T64[2] = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUState, t2_64),
|
116 |
|
"T2_64");
|
117 |
|
#endif
|
118 |
105 |
|
119 |
106 |
cpu_FT[0] = tcg_global_mem_new_i64(TCG_AREG0,
|
120 |
107 |
offsetof(CPUState, ft0), "FT0");
|
... | ... | |
6031 |
6018 |
GEN_EXCP_INVAL(ctx);
|
6032 |
6019 |
}
|
6033 |
6020 |
|
6034 |
|
/* SPE load and stores */
|
6035 |
|
static always_inline void gen_addr_spe_imm_index (TCGv EA, DisasContext *ctx, int sh)
|
6036 |
|
{
|
6037 |
|
target_long simm = rB(ctx->opcode);
|
6038 |
|
|
6039 |
|
if (rA(ctx->opcode) == 0)
|
6040 |
|
tcg_gen_movi_tl(EA, simm << sh);
|
6041 |
|
else if (likely(simm != 0))
|
6042 |
|
tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm << sh);
|
6043 |
|
else
|
6044 |
|
tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
|
6045 |
|
}
|
6046 |
|
|
6047 |
|
#define op_spe_ldst(name) (*gen_op_##name[ctx->mem_idx])()
|
6048 |
|
#define OP_SPE_LD_TABLE(name) \
|
6049 |
|
static GenOpFunc *gen_op_spe_l##name[NB_MEM_FUNCS] = { \
|
6050 |
|
GEN_MEM_FUNCS(spe_l##name), \
|
6051 |
|
};
|
6052 |
|
#define OP_SPE_ST_TABLE(name) \
|
6053 |
|
static GenOpFunc *gen_op_spe_st##name[NB_MEM_FUNCS] = { \
|
6054 |
|
GEN_MEM_FUNCS(spe_st##name), \
|
6055 |
|
};
|
6056 |
|
|
6057 |
|
#define GEN_SPE_LD(name, sh) \
|
6058 |
|
static always_inline void gen_evl##name (DisasContext *ctx) \
|
6059 |
|
{ \
|
6060 |
|
if (unlikely(!ctx->spe_enabled)) { \
|
6061 |
|
GEN_EXCP_NO_AP(ctx); \
|
6062 |
|
return; \
|
6063 |
|
} \
|
6064 |
|
gen_addr_spe_imm_index(cpu_T[0], ctx, sh); \
|
6065 |
|
op_spe_ldst(spe_l##name); \
|
6066 |
|
gen_store_gpr64(rD(ctx->opcode), cpu_T64[1]); \
|
6067 |
|
}
|
6068 |
|
|
6069 |
|
#define GEN_SPE_LDX(name) \
|
6070 |
|
static always_inline void gen_evl##name##x (DisasContext *ctx) \
|
6071 |
|
{ \
|
6072 |
|
if (unlikely(!ctx->spe_enabled)) { \
|
6073 |
|
GEN_EXCP_NO_AP(ctx); \
|
6074 |
|
return; \
|
6075 |
|
} \
|
6076 |
|
gen_addr_reg_index(cpu_T[0], ctx); \
|
6077 |
|
op_spe_ldst(spe_l##name); \
|
6078 |
|
gen_store_gpr64(rD(ctx->opcode), cpu_T64[1]); \
|
6079 |
|
}
|
6080 |
|
|
6081 |
|
#define GEN_SPEOP_LD(name, sh) \
|
6082 |
|
OP_SPE_LD_TABLE(name); \
|
6083 |
|
GEN_SPE_LD(name, sh); \
|
6084 |
|
GEN_SPE_LDX(name)
|
6085 |
|
|
6086 |
|
#define GEN_SPE_ST(name, sh) \
|
6087 |
|
static always_inline void gen_evst##name (DisasContext *ctx) \
|
6088 |
|
{ \
|
6089 |
|
if (unlikely(!ctx->spe_enabled)) { \
|
6090 |
|
GEN_EXCP_NO_AP(ctx); \
|
6091 |
|
return; \
|
6092 |
|
} \
|
6093 |
|
gen_addr_spe_imm_index(cpu_T[0], ctx, sh); \
|
6094 |
|
gen_load_gpr64(cpu_T64[1], rS(ctx->opcode)); \
|
6095 |
|
op_spe_ldst(spe_st##name); \
|
6096 |
|
}
|
6097 |
|
|
6098 |
|
#define GEN_SPE_STX(name) \
|
6099 |
|
static always_inline void gen_evst##name##x (DisasContext *ctx) \
|
6100 |
|
{ \
|
6101 |
|
if (unlikely(!ctx->spe_enabled)) { \
|
6102 |
|
GEN_EXCP_NO_AP(ctx); \
|
6103 |
|
return; \
|
6104 |
|
} \
|
6105 |
|
gen_addr_reg_index(cpu_T[0], ctx); \
|
6106 |
|
gen_load_gpr64(cpu_T64[1], rS(ctx->opcode)); \
|
6107 |
|
op_spe_ldst(spe_st##name); \
|
6108 |
|
}
|
6109 |
|
|
6110 |
|
#define GEN_SPEOP_ST(name, sh) \
|
6111 |
|
OP_SPE_ST_TABLE(name); \
|
6112 |
|
GEN_SPE_ST(name, sh); \
|
6113 |
|
GEN_SPE_STX(name)
|
6114 |
|
|
6115 |
|
#define GEN_SPEOP_LDST(name, sh) \
|
6116 |
|
GEN_SPEOP_LD(name, sh); \
|
6117 |
|
GEN_SPEOP_ST(name, sh)
|
6118 |
|
|
6119 |
6021 |
/* SPE logic */
|
6120 |
6022 |
#if defined(TARGET_PPC64)
|
6121 |
6023 |
#define GEN_SPEOP_LOGIC2(name, tcg_op) \
|
... | ... | |
6681 |
6583 |
GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
|
6682 |
6584 |
GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
|
6683 |
6585 |
|
6684 |
|
/* Load and stores */
|
6685 |
|
GEN_SPEOP_LDST(dd, 3);
|
6686 |
|
GEN_SPEOP_LDST(dw, 3);
|
6687 |
|
GEN_SPEOP_LDST(dh, 3);
|
6688 |
|
GEN_SPEOP_LDST(whe, 2);
|
6689 |
|
GEN_SPEOP_LD(whou, 2);
|
6690 |
|
GEN_SPEOP_LD(whos, 2);
|
6691 |
|
GEN_SPEOP_ST(who, 2);
|
6692 |
|
|
6693 |
|
#define _GEN_OP_SPE_STWWE(suffix) \
|
6694 |
|
static always_inline void gen_op_spe_stwwe_##suffix (void) \
|
6695 |
|
{ \
|
6696 |
|
gen_op_srli32_T1_64(); \
|
6697 |
|
gen_op_spe_stwwo_##suffix(); \
|
|
6586 |
/* SPE load and stores */
|
|
6587 |
static always_inline void gen_addr_spe_imm_index (TCGv EA, DisasContext *ctx, int sh)
|
|
6588 |
{
|
|
6589 |
target_ulong uimm = rB(ctx->opcode);
|
|
6590 |
|
|
6591 |
if (rA(ctx->opcode) == 0)
|
|
6592 |
tcg_gen_movi_tl(EA, uimm << sh);
|
|
6593 |
else
|
|
6594 |
tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
|
6698 |
6595 |
}
|
6699 |
|
#define _GEN_OP_SPE_STWWE_LE(suffix) \
|
6700 |
|
static always_inline void gen_op_spe_stwwe_le_##suffix (void) \
|
6701 |
|
{ \
|
6702 |
|
gen_op_srli32_T1_64(); \
|
6703 |
|
gen_op_spe_stwwo_le_##suffix(); \
|
|
6596 |
|
|
6597 |
static always_inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
|
|
6598 |
{
|
|
6599 |
#if defined(TARGET_PPC64)
|
|
6600 |
gen_qemu_ld64(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
|
|
6601 |
#else
|
|
6602 |
TCGv_i64 t0 = tcg_temp_new_i64();
|
|
6603 |
gen_qemu_ld64(t0, addr, ctx->mem_idx);
|
|
6604 |
tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
|
|
6605 |
tcg_gen_shri_i64(t0, t0, 32);
|
|
6606 |
tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
|
|
6607 |
tcg_temp_free_i64(t0);
|
|
6608 |
#endif
|
6704 |
6609 |
}
|
|
6610 |
|
|
6611 |
static always_inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
|
|
6612 |
{
|
6705 |
6613 |
#if defined(TARGET_PPC64)
|
6706 |
|
#define GEN_OP_SPE_STWWE(suffix) \
|
6707 |
|
_GEN_OP_SPE_STWWE(suffix); \
|
6708 |
|
_GEN_OP_SPE_STWWE_LE(suffix); \
|
6709 |
|
static always_inline void gen_op_spe_stwwe_64_##suffix (void) \
|
6710 |
|
{ \
|
6711 |
|
gen_op_srli32_T1_64(); \
|
6712 |
|
gen_op_spe_stwwo_64_##suffix(); \
|
6713 |
|
} \
|
6714 |
|
static always_inline void gen_op_spe_stwwe_le_64_##suffix (void) \
|
6715 |
|
{ \
|
6716 |
|
gen_op_srli32_T1_64(); \
|
6717 |
|
gen_op_spe_stwwo_le_64_##suffix(); \
|
|
6614 |
TCGv t0 = tcg_temp_new();
|
|
6615 |
gen_qemu_ld32u(t0, addr, ctx->mem_idx);
|
|
6616 |
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
|
|
6617 |
tcg_gen_addi_tl(addr, addr, 4);
|
|
6618 |
gen_qemu_ld32u(t0, addr, ctx->mem_idx);
|
|
6619 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
|
6620 |
tcg_temp_free(t0);
|
|
6621 |
#else
|
|
6622 |
gen_qemu_ld32u(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx);
|
|
6623 |
tcg_gen_addi_tl(addr, addr, 4);
|
|
6624 |
gen_qemu_ld32u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
|
|
6625 |
#endif
|
6718 |
6626 |
}
|
|
6627 |
|
|
6628 |
static always_inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
|
|
6629 |
{
|
|
6630 |
TCGv t0 = tcg_temp_new();
|
|
6631 |
#if defined(TARGET_PPC64)
|
|
6632 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6633 |
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
|
|
6634 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6635 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6636 |
tcg_gen_shli_tl(t0, t0, 32);
|
|
6637 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
|
6638 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6639 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6640 |
tcg_gen_shli_tl(t0, t0, 16);
|
|
6641 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
|
6642 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6643 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6644 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
6719 |
6645 |
#else
|
6720 |
|
#define GEN_OP_SPE_STWWE(suffix) \
|
6721 |
|
_GEN_OP_SPE_STWWE(suffix); \
|
6722 |
|
_GEN_OP_SPE_STWWE_LE(suffix)
|
|
6646 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6647 |
tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
|
|
6648 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6649 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6650 |
tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
|
|
6651 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6652 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6653 |
tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
|
|
6654 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6655 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6656 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
6723 |
6657 |
#endif
|
6724 |
|
#if defined(CONFIG_USER_ONLY)
|
6725 |
|
GEN_OP_SPE_STWWE(raw);
|
6726 |
|
#else /* defined(CONFIG_USER_ONLY) */
|
6727 |
|
GEN_OP_SPE_STWWE(user);
|
6728 |
|
GEN_OP_SPE_STWWE(kernel);
|
6729 |
|
GEN_OP_SPE_STWWE(hypv);
|
6730 |
|
#endif /* defined(CONFIG_USER_ONLY) */
|
6731 |
|
GEN_SPEOP_ST(wwe, 2);
|
6732 |
|
GEN_SPEOP_ST(wwo, 2);
|
6733 |
|
|
6734 |
|
#define GEN_SPE_LDSPLAT(name, op, suffix) \
|
6735 |
|
static always_inline void gen_op_spe_l##name##_##suffix (void) \
|
6736 |
|
{ \
|
6737 |
|
gen_op_##op##_##suffix(); \
|
6738 |
|
gen_op_splatw_T1_64(); \
|
|
6658 |
tcg_temp_free(t0);
|
6739 |
6659 |
}
|
6740 |
6660 |
|
6741 |
|
#define GEN_OP_SPE_LHE(suffix) \
|
6742 |
|
static always_inline void gen_op_spe_lhe_##suffix (void) \
|
6743 |
|
{ \
|
6744 |
|
gen_op_spe_lh_##suffix(); \
|
6745 |
|
gen_op_sli16_T1_64(); \
|
|
6661 |
static always_inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
|
|
6662 |
{
|
|
6663 |
TCGv t0 = tcg_temp_new();
|
|
6664 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6665 |
#if defined(TARGET_PPC64)
|
|
6666 |
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
|
|
6667 |
tcg_gen_shli_tl(t0, t0, 16);
|
|
6668 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
|
6669 |
#else
|
|
6670 |
tcg_gen_shli_tl(t0, t0, 16);
|
|
6671 |
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
|
|
6672 |
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
|
|
6673 |
#endif
|
|
6674 |
tcg_temp_free(t0);
|
6746 |
6675 |
}
|
6747 |
6676 |
|
6748 |
|
#define GEN_OP_SPE_LHX(suffix) \
|
6749 |
|
static always_inline void gen_op_spe_lhx_##suffix (void) \
|
6750 |
|
{ \
|
6751 |
|
gen_op_spe_lh_##suffix(); \
|
6752 |
|
gen_op_extsh_T1_64(); \
|
|
6677 |
static always_inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
|
|
6678 |
{
|
|
6679 |
TCGv t0 = tcg_temp_new();
|
|
6680 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6681 |
#if defined(TARGET_PPC64)
|
|
6682 |
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
|
|
6683 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
|
6684 |
#else
|
|
6685 |
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
|
|
6686 |
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
|
|
6687 |
#endif
|
|
6688 |
tcg_temp_free(t0);
|
6753 |
6689 |
}
|
6754 |
6690 |
|
6755 |
|
#if defined(CONFIG_USER_ONLY)
|
6756 |
|
GEN_OP_SPE_LHE(raw);
|
6757 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, raw);
|
6758 |
|
GEN_OP_SPE_LHE(le_raw);
|
6759 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_raw);
|
6760 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, raw);
|
6761 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_raw);
|
6762 |
|
GEN_OP_SPE_LHX(raw);
|
6763 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, raw);
|
6764 |
|
GEN_OP_SPE_LHX(le_raw);
|
6765 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_raw);
|
|
6691 |
static always_inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
|
|
6692 |
{
|
|
6693 |
TCGv t0 = tcg_temp_new();
|
|
6694 |
gen_qemu_ld16s(t0, addr, ctx->mem_idx);
|
|
6695 |
#if defined(TARGET_PPC64)
|
|
6696 |
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
|
|
6697 |
tcg_gen_ext32u_tl(t0, t0);
|
|
6698 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
|
6699 |
#else
|
|
6700 |
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
|
|
6701 |
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
|
|
6702 |
#endif
|
|
6703 |
tcg_temp_free(t0);
|
|
6704 |
}
|
|
6705 |
|
|
6706 |
static always_inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
|
|
6707 |
{
|
|
6708 |
TCGv t0 = tcg_temp_new();
|
|
6709 |
#if defined(TARGET_PPC64)
|
|
6710 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6711 |
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
|
|
6712 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6713 |
tcg_gen_shli_tl(t0, t0, 16);
|
|
6714 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
|
6715 |
#else
|
|
6716 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6717 |
tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
|
|
6718 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6719 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6720 |
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
|
|
6721 |
#endif
|
|
6722 |
tcg_temp_free(t0);
|
|
6723 |
}
|
|
6724 |
|
|
6725 |
static always_inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
|
|
6726 |
{
|
|
6727 |
#if defined(TARGET_PPC64)
|
|
6728 |
TCGv t0 = tcg_temp_new();
|
|
6729 |
gen_qemu_ld16u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
|
|
6730 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6731 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6732 |
tcg_gen_shli_tl(t0, t0, 32);
|
|
6733 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
|
6734 |
tcg_temp_free(t0);
|
|
6735 |
#else
|
|
6736 |
gen_qemu_ld16u(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx);
|
|
6737 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6738 |
gen_qemu_ld16u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
|
|
6739 |
#endif
|
|
6740 |
}
|
|
6741 |
|
|
6742 |
static always_inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
|
|
6743 |
{
|
|
6744 |
#if defined(TARGET_PPC64)
|
|
6745 |
TCGv t0 = tcg_temp_new();
|
|
6746 |
gen_qemu_ld16s(t0, addr, ctx->mem_idx);
|
|
6747 |
tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
|
|
6748 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6749 |
gen_qemu_ld16s(t0, addr, ctx->mem_idx);
|
|
6750 |
tcg_gen_shli_tl(t0, t0, 32);
|
|
6751 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
|
6752 |
tcg_temp_free(t0);
|
|
6753 |
#else
|
|
6754 |
gen_qemu_ld16s(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx);
|
|
6755 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6756 |
gen_qemu_ld16s(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
|
|
6757 |
#endif
|
|
6758 |
}
|
|
6759 |
|
|
6760 |
static always_inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
|
|
6761 |
{
|
|
6762 |
TCGv t0 = tcg_temp_new();
|
|
6763 |
gen_qemu_ld32u(t0, addr, ctx->mem_idx);
|
6766 |
6764 |
#if defined(TARGET_PPC64)
|
6767 |
|
GEN_OP_SPE_LHE(64_raw);
|
6768 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_raw);
|
6769 |
|
GEN_OP_SPE_LHE(le_64_raw);
|
6770 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_raw);
|
6771 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_raw);
|
6772 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_raw);
|
6773 |
|
GEN_OP_SPE_LHX(64_raw);
|
6774 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_raw);
|
6775 |
|
GEN_OP_SPE_LHX(le_64_raw);
|
6776 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_raw);
|
|
6765 |
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
|
|
6766 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
|
6767 |
#else
|
|
6768 |
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
|
|
6769 |
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
|
|
6770 |
#endif
|
|
6771 |
tcg_temp_free(t0);
|
|
6772 |
}
|
|
6773 |
|
|
6774 |
static always_inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
|
|
6775 |
{
|
|
6776 |
TCGv t0 = tcg_temp_new();
|
|
6777 |
#if defined(TARGET_PPC64)
|
|
6778 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6779 |
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
|
|
6780 |
tcg_gen_shli_tl(t0, t0, 32);
|
|
6781 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
|
6782 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6783 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6784 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
|
6785 |
tcg_gen_shli_tl(t0, t0, 16);
|
|
6786 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
|
|
6787 |
#else
|
|
6788 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6789 |
tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
|
|
6790 |
tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
|
|
6791 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6792 |
gen_qemu_ld16u(t0, addr, ctx->mem_idx);
|
|
6793 |
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
|
|
6794 |
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
|
6777 |
6795 |
#endif
|
|
6796 |
tcg_temp_free(t0);
|
|
6797 |
}
|
|
6798 |
|
|
6799 |
static always_inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
|
|
6800 |
{
|
|
6801 |
#if defined(TARGET_PPC64)
|
|
6802 |
gen_qemu_st64(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
|
6778 |
6803 |
#else
|
6779 |
|
GEN_OP_SPE_LHE(user);
|
6780 |
|
GEN_OP_SPE_LHE(kernel);
|
6781 |
|
GEN_OP_SPE_LHE(hypv);
|
6782 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, user);
|
6783 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, kernel);
|
6784 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, hypv);
|
6785 |
|
GEN_OP_SPE_LHE(le_user);
|
6786 |
|
GEN_OP_SPE_LHE(le_kernel);
|
6787 |
|
GEN_OP_SPE_LHE(le_hypv);
|
6788 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_user);
|
6789 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_kernel);
|
6790 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_hypv);
|
6791 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, user);
|
6792 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, kernel);
|
6793 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, hypv);
|
6794 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_user);
|
6795 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_kernel);
|
6796 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_hypv);
|
6797 |
|
GEN_OP_SPE_LHX(user);
|
6798 |
|
GEN_OP_SPE_LHX(kernel);
|
6799 |
|
GEN_OP_SPE_LHX(hypv);
|
6800 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, user);
|
6801 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, kernel);
|
6802 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, hypv);
|
6803 |
|
GEN_OP_SPE_LHX(le_user);
|
6804 |
|
GEN_OP_SPE_LHX(le_kernel);
|
6805 |
|
GEN_OP_SPE_LHX(le_hypv);
|
6806 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_user);
|
6807 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_kernel);
|
6808 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_hypv);
|
|
6804 |
TCGv_i64 t0 = tcg_temp_new_i64();
|
|
6805 |
tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
|
|
6806 |
gen_qemu_st64(t0, addr, ctx->mem_idx);
|
|
6807 |
tcg_temp_free_i64(t0);
|
|
6808 |
#endif
|
|
6809 |
}
|
|
6810 |
|
|
6811 |
static always_inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
|
|
6812 |
{
|
6809 |
6813 |
#if defined(TARGET_PPC64)
|
6810 |
|
GEN_OP_SPE_LHE(64_user);
|
6811 |
|
GEN_OP_SPE_LHE(64_kernel);
|
6812 |
|
GEN_OP_SPE_LHE(64_hypv);
|
6813 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_user);
|
6814 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_kernel);
|
6815 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_hypv);
|
6816 |
|
GEN_OP_SPE_LHE(le_64_user);
|
6817 |
|
GEN_OP_SPE_LHE(le_64_kernel);
|
6818 |
|
GEN_OP_SPE_LHE(le_64_hypv);
|
6819 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_user);
|
6820 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_kernel);
|
6821 |
|
GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_hypv);
|
6822 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_user);
|
6823 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_kernel);
|
6824 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_hypv);
|
6825 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_user);
|
6826 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_kernel);
|
6827 |
|
GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_hypv);
|
6828 |
|
GEN_OP_SPE_LHX(64_user);
|
6829 |
|
GEN_OP_SPE_LHX(64_kernel);
|
6830 |
|
GEN_OP_SPE_LHX(64_hypv);
|
6831 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_user);
|
6832 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_kernel);
|
6833 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_hypv);
|
6834 |
|
GEN_OP_SPE_LHX(le_64_user);
|
6835 |
|
GEN_OP_SPE_LHX(le_64_kernel);
|
6836 |
|
GEN_OP_SPE_LHX(le_64_hypv);
|
6837 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_user);
|
6838 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_kernel);
|
6839 |
|
GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_hypv);
|
6840 |
|
#endif
|
6841 |
|
#endif
|
6842 |
|
GEN_SPEOP_LD(hhesplat, 1);
|
6843 |
|
GEN_SPEOP_LD(hhousplat, 1);
|
6844 |
|
GEN_SPEOP_LD(hhossplat, 1);
|
6845 |
|
GEN_SPEOP_LD(wwsplat, 2);
|
6846 |
|
GEN_SPEOP_LD(whsplat, 2);
|
6847 |
|
|
6848 |
|
GEN_SPE(evlddx, evldd, 0x00, 0x0C, 0x00000000, PPC_SPE); //
|
6849 |
|
GEN_SPE(evldwx, evldw, 0x01, 0x0C, 0x00000000, PPC_SPE); //
|
6850 |
|
GEN_SPE(evldhx, evldh, 0x02, 0x0C, 0x00000000, PPC_SPE); //
|
6851 |
|
GEN_SPE(evlhhesplatx, evlhhesplat, 0x04, 0x0C, 0x00000000, PPC_SPE); //
|
6852 |
|
GEN_SPE(evlhhousplatx, evlhhousplat, 0x06, 0x0C, 0x00000000, PPC_SPE); //
|
6853 |
|
GEN_SPE(evlhhossplatx, evlhhossplat, 0x07, 0x0C, 0x00000000, PPC_SPE); //
|
6854 |
|
GEN_SPE(evlwhex, evlwhe, 0x08, 0x0C, 0x00000000, PPC_SPE); //
|
6855 |
|
GEN_SPE(evlwhoux, evlwhou, 0x0A, 0x0C, 0x00000000, PPC_SPE); //
|
6856 |
|
GEN_SPE(evlwhosx, evlwhos, 0x0B, 0x0C, 0x00000000, PPC_SPE); //
|
6857 |
|
GEN_SPE(evlwwsplatx, evlwwsplat, 0x0C, 0x0C, 0x00000000, PPC_SPE); //
|
6858 |
|
GEN_SPE(evlwhsplatx, evlwhsplat, 0x0E, 0x0C, 0x00000000, PPC_SPE); //
|
6859 |
|
GEN_SPE(evstddx, evstdd, 0x10, 0x0C, 0x00000000, PPC_SPE); //
|
6860 |
|
GEN_SPE(evstdwx, evstdw, 0x11, 0x0C, 0x00000000, PPC_SPE); //
|
6861 |
|
GEN_SPE(evstdhx, evstdh, 0x12, 0x0C, 0x00000000, PPC_SPE); //
|
6862 |
|
GEN_SPE(evstwhex, evstwhe, 0x18, 0x0C, 0x00000000, PPC_SPE); //
|
6863 |
|
GEN_SPE(evstwhox, evstwho, 0x1A, 0x0C, 0x00000000, PPC_SPE); //
|
6864 |
|
GEN_SPE(evstwwex, evstwwe, 0x1C, 0x0C, 0x00000000, PPC_SPE); //
|
6865 |
|
GEN_SPE(evstwwox, evstwwo, 0x1E, 0x0C, 0x00000000, PPC_SPE); //
|
|
6814 |
TCGv t0 = tcg_temp_new();
|
|
6815 |
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
|
|
6816 |
gen_qemu_st32(t0, addr, ctx->mem_idx);
|
|
6817 |
tcg_temp_free(t0);
|
|
6818 |
#else
|
|
6819 |
gen_qemu_st32(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
|
|
6820 |
#endif
|
|
6821 |
tcg_gen_addi_tl(addr, addr, 4);
|
|
6822 |
gen_qemu_st32(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
|
|
6823 |
}
|
|
6824 |
|
|
6825 |
static always_inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
|
|
6826 |
{
|
|
6827 |
TCGv t0 = tcg_temp_new();
|
|
6828 |
#if defined(TARGET_PPC64)
|
|
6829 |
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
|
|
6830 |
#else
|
|
6831 |
tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
|
|
6832 |
#endif
|
|
6833 |
gen_qemu_st16(t0, addr, ctx->mem_idx);
|
|
6834 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6835 |
#if defined(TARGET_PPC64)
|
|
6836 |
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
|
|
6837 |
gen_qemu_st16(t0, addr, ctx->mem_idx);
|
|
6838 |
#else
|
|
6839 |
gen_qemu_st16(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
|
|
6840 |
#endif
|
|
6841 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6842 |
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
|
|
6843 |
gen_qemu_st16(t0, addr, ctx->mem_idx);
|
|
6844 |
tcg_temp_free(t0);
|
|
6845 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6846 |
gen_qemu_st16(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
|
|
6847 |
}
|
|
6848 |
|
|
6849 |
static always_inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
|
|
6850 |
{
|
|
6851 |
TCGv t0 = tcg_temp_new();
|
|
6852 |
#if defined(TARGET_PPC64)
|
|
6853 |
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
|
|
6854 |
#else
|
|
6855 |
tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
|
|
6856 |
#endif
|
|
6857 |
gen_qemu_st16(t0, addr, ctx->mem_idx);
|
|
6858 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6859 |
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
|
|
6860 |
gen_qemu_st16(t0, addr, ctx->mem_idx);
|
|
6861 |
tcg_temp_free(t0);
|
|
6862 |
}
|
|
6863 |
|
|
6864 |
static always_inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
|
|
6865 |
{
|
|
6866 |
#if defined(TARGET_PPC64)
|
|
6867 |
TCGv t0 = tcg_temp_new();
|
|
6868 |
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
|
|
6869 |
gen_qemu_st16(t0, addr, ctx->mem_idx);
|
|
6870 |
tcg_temp_free(t0);
|
|
6871 |
#else
|
|
6872 |
gen_qemu_st16(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
|
|
6873 |
#endif
|
|
6874 |
tcg_gen_addi_tl(addr, addr, 2);
|
|
6875 |
gen_qemu_st16(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
|
|
6876 |
}
|
|
6877 |
|
|
6878 |
static always_inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
|
|
6879 |
{
|
|
6880 |
#if defined(TARGET_PPC64)
|
|
6881 |
TCGv t0 = tcg_temp_new();
|
|
6882 |
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
|
|
6883 |
gen_qemu_st32(t0, addr, ctx->mem_idx);
|
|
6884 |
tcg_temp_free(t0);
|
|
6885 |
#else
|
|
6886 |
gen_qemu_st32(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
|
|
6887 |
#endif
|
|
6888 |
}
|
|
6889 |
|
|
6890 |
static always_inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
|
|
6891 |
{
|
|
6892 |
gen_qemu_st32(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
|
|
6893 |
}
|
|
6894 |
|
|
6895 |
#define GEN_SPEOP_LDST(name, opc2, sh) \
|
|
6896 |
GEN_HANDLER(gen_##name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE) \
|
|
6897 |
{ \
|
|
6898 |
TCGv t0; \
|
|
6899 |
if (unlikely(!ctx->spe_enabled)) { \
|
|
6900 |
GEN_EXCP_NO_AP(ctx); \
|
|
6901 |
return; \
|
|
6902 |
} \
|
|
6903 |
t0 = tcg_temp_new(); \
|
|
6904 |
if (Rc(ctx->opcode)) { \
|
|
6905 |
gen_addr_spe_imm_index(t0, ctx, sh); \
|
|
6906 |
} else { \
|
|
6907 |
gen_addr_reg_index(t0, ctx); \
|
|
6908 |
} \
|
|
6909 |
gen_op_##name(ctx, t0); \
|
|
6910 |
tcg_temp_free(t0); \
|
|
6911 |
}
|
|
6912 |
|
|
6913 |
GEN_SPEOP_LDST(evldd, 0x00, 3);
|
|
6914 |
GEN_SPEOP_LDST(evldw, 0x01, 3);
|
|
6915 |
GEN_SPEOP_LDST(evldh, 0x02, 3);
|
|
6916 |
GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
|
|
6917 |
GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
|
|
6918 |
GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
|
|
6919 |
GEN_SPEOP_LDST(evlwhe, 0x08, 2);
|
|
6920 |
GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
|
|
6921 |
GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
|
|
6922 |
GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
|
|
6923 |
GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
|
|
6924 |
|
|
6925 |
GEN_SPEOP_LDST(evstdd, 0x10, 3);
|
|
6926 |
GEN_SPEOP_LDST(evstdw, 0x11, 3);
|
|
6927 |
GEN_SPEOP_LDST(evstdh, 0x12, 3);
|
|
6928 |
GEN_SPEOP_LDST(evstwhe, 0x18, 2);
|
|
6929 |
GEN_SPEOP_LDST(evstwho, 0x1A, 2);
|
|
6930 |
GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
|
|
6931 |
GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
|
6866 |
6932 |
|
6867 |
6933 |
/* Multiply and add - TODO */
|
6868 |
6934 |
#if 0
|