aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/arm/kvm.c4
-rw-r--r--target/arm/kvm_arm.h6
-rw-r--r--target/arm/sve_helper.c107
-rw-r--r--target/arm/translate-sve.c26
-rw-r--r--target/mips/meson.build18
-rw-r--r--target/mips/mxu_translate.c1609
-rw-r--r--target/mips/translate.c3663
-rw-r--r--target/mips/translate.h10
-rw-r--r--target/mips/tx79.decode39
-rw-r--r--target/mips/tx79_translate.c303
-rw-r--r--target/mips/txx9_translate.c20
11 files changed, 2097 insertions, 3708 deletions
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index bebea90122..d8381ba224 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -230,12 +230,14 @@ bool kvm_arm_pmu_supported(void)
return kvm_check_extension(kvm_state, KVM_CAP_ARM_PMU_V3);
}
-int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
{
KVMState *s = KVM_STATE(ms->accelerator);
int ret;
ret = kvm_check_extension(s, KVM_CAP_ARM_VM_IPA_SIZE);
+ *fixed_ipa = ret <= 0;
+
return ret > 0 ? ret : 40;
}
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 68ec970c4f..34f8daa377 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -311,10 +311,12 @@ bool kvm_arm_sve_supported(void);
/**
* kvm_arm_get_max_vm_ipa_size:
* @ms: Machine state handle
+ * @fixed_ipa: True when the IPA limit is fixed at 40. This is the case
+ * for legacy KVM.
*
* Returns the number of bits in the IPA address space supported by KVM
*/
-int kvm_arm_get_max_vm_ipa_size(MachineState *ms);
+int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa);
/**
* kvm_arm_sync_mpstate_to_kvm:
@@ -409,7 +411,7 @@ static inline void kvm_arm_add_vcpu_properties(Object *obj)
g_assert_not_reached();
}
-static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
+static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms, bool *fixed_ipa)
{
g_assert_not_reached();
}
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
index 844db08bd5..fd6c58f96a 100644
--- a/target/arm/sve_helper.c
+++ b/target/arm/sve_helper.c
@@ -1871,6 +1871,7 @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
int esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
intptr_t high = FIELD_EX32(pred_desc, PREDDESC, DATA);
+ int esize = 1 << esz;
uint64_t *d = vd;
intptr_t i;
@@ -1883,33 +1884,35 @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
mm = extract64(mm, high * half, half);
nn = expand_bits(nn, esz);
mm = expand_bits(mm, esz);
- d[0] = nn + (mm << (1 << esz));
+ d[0] = nn | (mm << esize);
} else {
- ARMPredicateReg tmp_n, tmp_m;
+ ARMPredicateReg tmp;
/* We produce output faster than we consume input.
Therefore we must be mindful of possible overlap. */
- if ((vn - vd) < (uintptr_t)oprsz) {
- vn = memcpy(&tmp_n, vn, oprsz);
- }
- if ((vm - vd) < (uintptr_t)oprsz) {
- vm = memcpy(&tmp_m, vm, oprsz);
+ if (vd == vn) {
+ vn = memcpy(&tmp, vn, oprsz);
+ if (vd == vm) {
+ vm = vn;
+ }
+ } else if (vd == vm) {
+ vm = memcpy(&tmp, vm, oprsz);
}
if (high) {
high = oprsz >> 1;
}
- if ((high & 3) == 0) {
+ if ((oprsz & 7) == 0) {
uint32_t *n = vn, *m = vm;
high >>= 2;
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
+ for (i = 0; i < oprsz / 8; i++) {
uint64_t nn = n[H4(high + i)];
uint64_t mm = m[H4(high + i)];
nn = expand_bits(nn, esz);
mm = expand_bits(mm, esz);
- d[i] = nn + (mm << (1 << esz));
+ d[i] = nn | (mm << esize);
}
} else {
uint8_t *n = vn, *m = vm;
@@ -1921,7 +1924,7 @@ void HELPER(sve_zip_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
nn = expand_bits(nn, esz);
mm = expand_bits(mm, esz);
- d16[H2(i)] = nn + (mm << (1 << esz));
+ d16[H2(i)] = nn | (mm << esize);
}
}
}
@@ -1939,7 +1942,7 @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
if (oprsz <= 8) {
l = compress_bits(n[0] >> odd, esz);
h = compress_bits(m[0] >> odd, esz);
- d[0] = extract64(l + (h << (4 * oprsz)), 0, 8 * oprsz);
+ d[0] = l | (h << (4 * oprsz));
} else {
ARMPredicateReg tmp_m;
intptr_t oprsz_16 = oprsz / 16;
@@ -1953,23 +1956,35 @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
h = n[2 * i + 1];
l = compress_bits(l >> odd, esz);
h = compress_bits(h >> odd, esz);
- d[i] = l + (h << 32);
+ d[i] = l | (h << 32);
}
- /* For VL which is not a power of 2, the results from M do not
- align nicely with the uint64_t for D. Put the aligned results
- from M into TMP_M and then copy it into place afterward. */
+ /*
+ * For VL which is not a multiple of 512, the results from M do not
+ * align nicely with the uint64_t for D. Put the aligned results
+ * from M into TMP_M and then copy it into place afterward.
+ */
if (oprsz & 15) {
- d[i] = compress_bits(n[2 * i] >> odd, esz);
+ int final_shift = (oprsz & 15) * 2;
+
+ l = n[2 * i + 0];
+ h = n[2 * i + 1];
+ l = compress_bits(l >> odd, esz);
+ h = compress_bits(h >> odd, esz);
+ d[i] = l | (h << final_shift);
for (i = 0; i < oprsz_16; i++) {
l = m[2 * i + 0];
h = m[2 * i + 1];
l = compress_bits(l >> odd, esz);
h = compress_bits(h >> odd, esz);
- tmp_m.p[i] = l + (h << 32);
+ tmp_m.p[i] = l | (h << 32);
}
- tmp_m.p[i] = compress_bits(m[2 * i] >> odd, esz);
+ l = m[2 * i + 0];
+ h = m[2 * i + 1];
+ l = compress_bits(l >> odd, esz);
+ h = compress_bits(h >> odd, esz);
+ tmp_m.p[i] = l | (h << final_shift);
swap_memmove(vd + oprsz / 2, &tmp_m, oprsz / 2);
} else {
@@ -1978,7 +1993,7 @@ void HELPER(sve_uzp_p)(void *vd, void *vn, void *vm, uint32_t pred_desc)
h = m[2 * i + 1];
l = compress_bits(l >> odd, esz);
h = compress_bits(h >> odd, esz);
- d[oprsz_16 + i] = l + (h << 32);
+ d[oprsz_16 + i] = l | (h << 32);
}
}
}
@@ -2090,11 +2105,11 @@ void HELPER(sve_punpk_p)(void *vd, void *vn, uint32_t pred_desc)
high = oprsz >> 1;
}
- if ((high & 3) == 0) {
+ if ((oprsz & 7) == 0) {
uint32_t *n = vn;
high >>= 2;
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); i++) {
+ for (i = 0; i < oprsz / 8; i++) {
uint64_t nn = n[H4(high + i)];
d[i] = expand_bits(nn, 0);
}
@@ -2222,10 +2237,10 @@ void HELPER(sve_compact_d)(void *vd, void *vn, void *vg, uint32_t desc)
*/
int32_t HELPER(sve_last_active_element)(void *vg, uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
+ intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
- return last_active_element(vg, DIV_ROUND_UP(oprsz, 8), esz);
+ return last_active_element(vg, words, esz);
}
void HELPER(sve_splice)(void *vd, void *vn, void *vm, void *vg, uint32_t desc)
@@ -2695,7 +2710,7 @@ static uint32_t do_zero(ARMPredicateReg *d, intptr_t oprsz)
void HELPER(sve_brkpa)(void *vd, void *vn, void *vm, void *vg,
uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
if (last_active_pred(vn, vg, oprsz)) {
compute_brk_z(vd, vm, vg, oprsz, true);
} else {
@@ -2706,7 +2721,7 @@ void HELPER(sve_brkpa)(void *vd, void *vn, void *vm, void *vg,
uint32_t HELPER(sve_brkpas)(void *vd, void *vn, void *vm, void *vg,
uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
if (last_active_pred(vn, vg, oprsz)) {
return compute_brks_z(vd, vm, vg, oprsz, true);
} else {
@@ -2717,7 +2732,7 @@ uint32_t HELPER(sve_brkpas)(void *vd, void *vn, void *vm, void *vg,
void HELPER(sve_brkpb)(void *vd, void *vn, void *vm, void *vg,
uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
if (last_active_pred(vn, vg, oprsz)) {
compute_brk_z(vd, vm, vg, oprsz, false);
} else {
@@ -2728,7 +2743,7 @@ void HELPER(sve_brkpb)(void *vd, void *vn, void *vm, void *vg,
uint32_t HELPER(sve_brkpbs)(void *vd, void *vn, void *vm, void *vg,
uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
if (last_active_pred(vn, vg, oprsz)) {
return compute_brks_z(vd, vm, vg, oprsz, false);
} else {
@@ -2738,56 +2753,55 @@ uint32_t HELPER(sve_brkpbs)(void *vd, void *vn, void *vm, void *vg,
void HELPER(sve_brka_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
compute_brk_z(vd, vn, vg, oprsz, true);
}
uint32_t HELPER(sve_brkas_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
return compute_brks_z(vd, vn, vg, oprsz, true);
}
void HELPER(sve_brkb_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
compute_brk_z(vd, vn, vg, oprsz, false);
}
uint32_t HELPER(sve_brkbs_z)(void *vd, void *vn, void *vg, uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
return compute_brks_z(vd, vn, vg, oprsz, false);
}
void HELPER(sve_brka_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
compute_brk_m(vd, vn, vg, oprsz, true);
}
uint32_t HELPER(sve_brkas_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
return compute_brks_m(vd, vn, vg, oprsz, true);
}
void HELPER(sve_brkb_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
compute_brk_m(vd, vn, vg, oprsz, false);
}
uint32_t HELPER(sve_brkbs_m)(void *vd, void *vn, void *vg, uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
return compute_brks_m(vd, vn, vg, oprsz, false);
}
void HELPER(sve_brkn)(void *vd, void *vn, void *vg, uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
-
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
if (!last_active_pred(vn, vg, oprsz)) {
do_zero(vd, oprsz);
}
@@ -2812,8 +2826,7 @@ static uint32_t predtest_ones(ARMPredicateReg *d, intptr_t oprsz,
uint32_t HELPER(sve_brkns)(void *vd, void *vn, void *vg, uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
-
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
if (last_active_pred(vn, vg, oprsz)) {
return predtest_ones(vd, oprsz, -1);
} else {
@@ -2823,12 +2836,12 @@ uint32_t HELPER(sve_brkns)(void *vd, void *vn, void *vg, uint32_t pred_desc)
uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
{
- intptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
+ intptr_t words = DIV_ROUND_UP(FIELD_EX32(pred_desc, PREDDESC, OPRSZ), 8);
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
uint64_t *n = vn, *g = vg, sum = 0, mask = pred_esz_masks[esz];
intptr_t i;
- for (i = 0; i < DIV_ROUND_UP(oprsz, 8); ++i) {
+ for (i = 0; i < words; ++i) {
uint64_t t = n[i] & g[i] & mask;
sum += ctpop64(t);
}
@@ -2837,8 +2850,8 @@ uint64_t HELPER(sve_cntp)(void *vn, void *vg, uint32_t pred_desc)
uint32_t HELPER(sve_while)(void *vd, uint32_t count, uint32_t pred_desc)
{
- uintptr_t oprsz = extract32(pred_desc, 0, SIMD_OPRSZ_BITS) + 2;
- intptr_t esz = extract32(pred_desc, SIMD_DATA_SHIFT, 2);
+ intptr_t oprsz = FIELD_EX32(pred_desc, PREDDESC, OPRSZ);
+ intptr_t esz = FIELD_EX32(pred_desc, PREDDESC, ESZ);
uint64_t esz_mask = pred_esz_masks[esz];
ARMPredicateReg *d = vd;
uint32_t flags;
@@ -2883,7 +2896,7 @@ static TYPE NAME##_reduce(TYPE *data, float_status *status, uintptr_t n) \
} \
uint64_t HELPER(NAME)(void *vn, void *vg, void *vs, uint32_t desc) \
{ \
- uintptr_t i, oprsz = simd_oprsz(desc), maxsz = simd_maxsz(desc); \
+ uintptr_t i, oprsz = simd_oprsz(desc), maxsz = simd_data(desc); \
TYPE data[sizeof(ARMVectorReg) / sizeof(TYPE)]; \
for (i = 0; i < oprsz; ) { \
uint16_t pg = *(uint16_t *)(vg + H1_2(i >> 3)); \
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
index 27402af23c..0eefb61214 100644
--- a/target/arm/translate-sve.c
+++ b/target/arm/translate-sve.c
@@ -2302,11 +2302,10 @@ static void find_last_active(DisasContext *s, TCGv_i32 ret, int esz, int pg)
*/
TCGv_ptr t_p = tcg_temp_new_ptr();
TCGv_i32 t_desc;
- unsigned vsz = pred_full_reg_size(s);
- unsigned desc;
+ unsigned desc = 0;
- desc = vsz - 2;
- desc = deposit32(desc, SIMD_DATA_SHIFT, 2, esz);
+ desc = FIELD_DP32(desc, PREDDESC, OPRSZ, pred_full_reg_size(s));
+ desc = FIELD_DP32(desc, PREDDESC, ESZ, esz);
tcg_gen_addi_ptr(t_p, cpu_env, pred_full_reg_offset(s, pg));
t_desc = tcg_const_i32(desc);
@@ -2851,7 +2850,7 @@ static bool do_brk3(DisasContext *s, arg_rprr_s *a,
TCGv_ptr n = tcg_temp_new_ptr();
TCGv_ptr m = tcg_temp_new_ptr();
TCGv_ptr g = tcg_temp_new_ptr();
- TCGv_i32 t = tcg_const_i32(vsz - 2);
+ TCGv_i32 t = tcg_const_i32(FIELD_DP32(0, PREDDESC, OPRSZ, vsz));
tcg_gen_addi_ptr(d, cpu_env, pred_full_reg_offset(s, a->rd));
tcg_gen_addi_ptr(n, cpu_env, pred_full_reg_offset(s, a->rn));
@@ -2885,7 +2884,7 @@ static bool do_brk2(DisasContext *s, arg_rpr_s *a,
TCGv_ptr d = tcg_temp_new_ptr();
TCGv_ptr n = tcg_temp_new_ptr();
TCGv_ptr g = tcg_temp_new_ptr();
- TCGv_i32 t = tcg_const_i32(vsz - 2);
+ TCGv_i32 t = tcg_const_i32(FIELD_DP32(0, PREDDESC, OPRSZ, vsz));
tcg_gen_addi_ptr(d, cpu_env, pred_full_reg_offset(s, a->rd));
tcg_gen_addi_ptr(n, cpu_env, pred_full_reg_offset(s, a->rn));
@@ -2968,11 +2967,11 @@ static void do_cntp(DisasContext *s, TCGv_i64 val, int esz, int pn, int pg)
} else {
TCGv_ptr t_pn = tcg_temp_new_ptr();
TCGv_ptr t_pg = tcg_temp_new_ptr();
- unsigned desc;
+ unsigned desc = 0;
TCGv_i32 t_desc;
- desc = psz - 2;
- desc = deposit32(desc, SIMD_DATA_SHIFT, 2, esz);
+ desc = FIELD_DP32(desc, PREDDESC, OPRSZ, psz);
+ desc = FIELD_DP32(desc, PREDDESC, ESZ, esz);
tcg_gen_addi_ptr(t_pn, cpu_env, pred_full_reg_offset(s, pn));
tcg_gen_addi_ptr(t_pg, cpu_env, pred_full_reg_offset(s, pg));
@@ -3098,7 +3097,8 @@ static bool trans_WHILE(DisasContext *s, arg_WHILE *a)
TCGv_i64 op0, op1, t0, t1, tmax;
TCGv_i32 t2, t3;
TCGv_ptr ptr;
- unsigned desc, vsz = vec_full_reg_size(s);
+ unsigned vsz = vec_full_reg_size(s);
+ unsigned desc = 0;
TCGCond cond;
if (!sve_access_check(s)) {
@@ -3162,8 +3162,8 @@ static bool trans_WHILE(DisasContext *s, arg_WHILE *a)
/* Scale elements to bits. */
tcg_gen_shli_i32(t2, t2, a->esz);
- desc = (vsz / 8) - 2;
- desc = deposit32(desc, SIMD_DATA_SHIFT, 2, a->esz);
+ desc = FIELD_DP32(desc, PREDDESC, OPRSZ, vsz / 8);
+ desc = FIELD_DP32(desc, PREDDESC, ESZ, a->esz);
t3 = tcg_const_i32(desc);
ptr = tcg_temp_new_ptr();
@@ -3440,7 +3440,7 @@ static void do_reduce(DisasContext *s, arg_rpr_esz *a,
{
unsigned vsz = vec_full_reg_size(s);
unsigned p2vsz = pow2ceil(vsz);
- TCGv_i32 t_desc = tcg_const_i32(simd_desc(vsz, p2vsz, 0));
+ TCGv_i32 t_desc = tcg_const_i32(simd_desc(vsz, vsz, p2vsz));
TCGv_ptr t_zn, t_pg, status;
TCGv_i64 temp;
diff --git a/target/mips/meson.build b/target/mips/meson.build
index 9741545440..3b131c4a7f 100644
--- a/target/mips/meson.build
+++ b/target/mips/meson.build
@@ -3,15 +3,17 @@ gen = [
decodetree.process('mips64r6.decode', extra_args: '--static-decode=decode_mips64r6'),
decodetree.process('msa32.decode', extra_args: '--static-decode=decode_msa32'),
decodetree.process('msa64.decode', extra_args: '--static-decode=decode_msa64'),
+ decodetree.process('tx79.decode', extra_args: '--static-decode=decode_tx79'),
]
mips_ss = ss.source_set()
-mips_ss.add(gen)
mips_ss.add(files(
'cpu.c',
'gdbstub.c',
))
-mips_ss.add(when: 'CONFIG_TCG', if_true: files(
+mips_tcg_ss = ss.source_set()
+mips_tcg_ss.add(gen)
+mips_tcg_ss.add(files(
'dsp_helper.c',
'fpu_helper.c',
'lmmi_helper.c',
@@ -22,7 +24,15 @@ mips_ss.add(when: 'CONFIG_TCG', if_true: files(
'tlb_helper.c',
'translate.c',
'translate_addr_const.c',
+ 'txx9_translate.c',
))
+mips_ss.add(when: ['CONFIG_TCG', 'TARGET_MIPS64'], if_true: files(
+ 'tx79_translate.c',
+))
+mips_tcg_ss.add(when: 'TARGET_MIPS64', if_false: files(
+ 'mxu_translate.c',
+))
+
mips_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
mips_softmmu_ss = ss.source_set()
@@ -30,11 +40,13 @@ mips_softmmu_ss.add(files(
'addr.c',
'cp0_timer.c',
'machine.c',
- 'mips-semi.c',
))
mips_softmmu_ss.add(when: 'CONFIG_TCG', if_true: files(
'cp0_helper.c',
+ 'mips-semi.c',
))
+mips_ss.add_all(when: 'CONFIG_TCG', if_true: [mips_tcg_ss])
+
target_arch += {'mips': mips_ss}
target_softmmu_arch += {'mips': mips_softmmu_ss}
diff --git a/target/mips/mxu_translate.c b/target/mips/mxu_translate.c
new file mode 100644
index 0000000000..afc008eeee
--- /dev/null
+++ b/target/mips/mxu_translate.c
@@ -0,0 +1,1609 @@
+/*
+ * Ingenic XBurst Media eXtension Unit (MXU) translation routines.
+ *
+ * Copyright (c) 2004-2005 Jocelyn Mayer
+ * Copyright (c) 2006 Marius Groeger (FPU operations)
+ * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
+ * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
+ * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * Datasheet:
+ *
+ * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
+ * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
+ */
+
+#include "qemu/osdep.h"
+#include "tcg/tcg-op.h"
+#include "exec/helper-gen.h"
+#include "translate.h"
+
+/*
+ *
+ * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
+ * ============================================
+ *
+ *
+ * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
+ * instructions set. It is designed to fit the needs of signal, graphical and
+ * video processing applications. MXU instruction set is used in Xburst family
+ * of microprocessors by Ingenic.
+ *
+ * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
+ * the control register.
+ *
+ *
+ * The notation used in MXU assembler mnemonics
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Register operands:
+ *
+ * XRa, XRb, XRc, XRd - MXU registers
+ * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
+ *
+ * Non-register operands:
+ *
+ * aptn1 - 1-bit accumulate add/subtract pattern
+ * aptn2 - 2-bit accumulate add/subtract pattern
+ * eptn2 - 2-bit execute add/subtract pattern
+ * optn2 - 2-bit operand pattern
+ * optn3 - 3-bit operand pattern
+ * sft4 - 4-bit shift amount
+ * strd2 - 2-bit stride amount
+ *
+ * Prefixes:
+ *
+ * Level of parallelism: Operand size:
+ * S - single operation at a time 32 - word
+ * D - two operations in parallel 16 - half word
+ * Q - four operations in parallel 8 - byte
+ *
+ * Operations:
+ *
+ * ADD - Add or subtract
+ * ADDC - Add with carry-in
+ * ACC - Accumulate
+ * ASUM - Sum together then accumulate (add or subtract)
+ * ASUMC - Sum together then accumulate (add or subtract) with carry-in
+ * AVG - Average between 2 operands
+ * ABD - Absolute difference
+ * ALN - Align data
+ * AND - Logical bitwise 'and' operation
+ * CPS - Copy sign
+ * EXTR - Extract bits
+ * I2M - Move from GPR register to MXU register
+ * LDD - Load data from memory to XRF
+ * LDI - Load data from memory to XRF (and increase the address base)
+ * LUI - Load unsigned immediate
+ * MUL - Multiply
+ * MULU - Unsigned multiply
+ * MADD - 64-bit operand add 32x32 product
+ * MSUB - 64-bit operand subtract 32x32 product
+ * MAC - Multiply and accumulate (add or subtract)
+ * MAD - Multiply and add or subtract
+ * MAX - Maximum between 2 operands
+ * MIN - Minimum between 2 operands
+ * M2I - Move from MXU register to GPR register
+ * MOVZ - Move if zero
+ * MOVN - Move if non-zero
+ * NOR - Logical bitwise 'nor' operation
+ * OR - Logical bitwise 'or' operation
+ * STD - Store data from XRF to memory
+ * SDI - Store data from XRF to memory (and increase the address base)
+ * SLT - Set of less than comparison
+ * SAD - Sum of absolute differences
+ * SLL - Logical shift left
+ * SLR - Logical shift right
+ * SAR - Arithmetic shift right
+ * SAT - Saturation
+ * SFL - Shuffle
+ * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
+ * XOR - Logical bitwise 'exclusive or' operation
+ *
+ * Suffixes:
+ *
+ * E - Expand results
+ * F - Fixed point multiplication
+ * L - Low part result
+ * R - Doing rounding
+ * V - Variable instead of immediate
+ * W - Combine above L and V
+ *
+ *
+ * The list of MXU instructions grouped by functionality
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Load/Store instructions Multiplication instructions
+ * ----------------------- ---------------------------
+ *
+ * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
+ * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
+ * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
+ * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
+ * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
+ * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
+ * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
+ * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
+ * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
+ * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
+ * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
+ * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
+ * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
+ * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
+ * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
+ * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
+ * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
+ * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
+ * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
+ * S16SDI XRa, Rb, s10, eptn2
+ * S8LDD XRa, Rb, s8, eptn3
+ * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
+ * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
+ * S8SDI XRa, Rb, s8, eptn3
+ * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
+ * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
+ * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
+ * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
+ * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
+ * S32CPS XRa, XRb, XRc
+ * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
+ * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
+ * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
+ * D16ASUM XRa, XRb, XRc, XRd, eptn2
+ * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
+ * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
+ * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
+ * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
+ * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
+ * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
+ * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
+ * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
+ * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
+ * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
+ * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
+ * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
+ * Q8SLT XRa, XRb, XRc
+ * Q8SLTU XRa, XRb, XRc
+ * Q8MOVZ XRa, XRb, XRc Shift instructions
+ * Q8MOVN XRa, XRb, XRc ------------------
+ *
+ * D32SLL XRa, XRb, XRc, XRd, sft4
+ * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
+ * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
+ * D32SARL XRa, XRb, XRc, sft4
+ * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
+ * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
+ * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
+ * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
+ * Q16SLL XRa, XRb, XRc, XRd, sft4
+ * Q16SLR XRa, XRb, XRc, XRd, sft4
+ * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
+ * ------------------------- Q16SLLV XRa, XRb, Rb
+ * Q16SLRV XRa, XRb, Rb
+ * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
+ * S32ALN XRa, XRb, XRc, Rb
+ * S32ALNI XRa, XRb, XRc, s3
+ * S32LUI XRa, s8, optn3 Move instructions
+ * S32EXTR XRa, XRb, Rb, bits5 -----------------
+ * S32EXTRV XRa, XRb, Rs, Rt
+ * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
+ * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
+ *
+ *
+ * The opcode organization of MXU instructions
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
+ * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
+ * other bits up to the instruction level is as follows:
+ *
+ * bits
+ * 05..00
+ *
+ * ┌─ 000000 ─ OPC_MXU_S32MADD
+ * ├─ 000001 ─ OPC_MXU_S32MADDU
+ * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
+ * │
+ * │ 20..18
+ * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
+ * │ ├─ 001 ─ OPC_MXU_S32MIN
+ * │ ├─ 010 ─ OPC_MXU_D16MAX
+ * │ ├─ 011 ─ OPC_MXU_D16MIN
+ * │ ├─ 100 ─ OPC_MXU_Q8MAX
+ * │ ├─ 101 ─ OPC_MXU_Q8MIN
+ * │ ├─ 110 ─ OPC_MXU_Q8SLT
+ * │ └─ 111 ─ OPC_MXU_Q8SLTU
+ * ├─ 000100 ─ OPC_MXU_S32MSUB
+ * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
+ * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
+ * │ ├─ 001 ─ OPC_MXU_D16SLT
+ * │ ├─ 010 ─ OPC_MXU_D16AVG
+ * │ ├─ 011 ─ OPC_MXU_D16AVGR
+ * │ ├─ 100 ─ OPC_MXU_Q8AVG
+ * │ ├─ 101 ─ OPC_MXU_Q8AVGR
+ * │ └─ 111 ─ OPC_MXU_Q8ADD
+ * │
+ * │ 20..18
+ * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
+ * │ ├─ 010 ─ OPC_MXU_D16CPS
+ * │ ├─ 100 ─ OPC_MXU_Q8ABD
+ * │ └─ 110 ─ OPC_MXU_Q16SAT
+ * ├─ 001000 ─ OPC_MXU_D16MUL
+ * │ 25..24
+ * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
+ * │ └─ 01 ─ OPC_MXU_D16MULE
+ * ├─ 001010 ─ OPC_MXU_D16MAC
+ * ├─ 001011 ─ OPC_MXU_D16MACF
+ * ├─ 001100 ─ OPC_MXU_D16MADL
+ * ├─ 001101 ─ OPC_MXU_S16MAD
+ * ├─ 001110 ─ OPC_MXU_Q16ADD
+ * ├─ 001111 ─ OPC_MXU_D16MACE 23
+ * │ ┌─ 0 ─ OPC_MXU_S32LDD
+ * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
+ * │
+ * │ 23
+ * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
+ * │ └─ 1 ─ OPC_MXU_S32STDR
+ * │
+ * │ 13..10
+ * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
+ * │ └─ 0001 ─ OPC_MXU_S32LDDVR
+ * │
+ * │ 13..10
+ * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
+ * │ └─ 0001 ─ OPC_MXU_S32STDVR
+ * │
+ * │ 23
+ * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
+ * │ └─ 1 ─ OPC_MXU_S32LDIR
+ * │
+ * │ 23
+ * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
+ * │ └─ 1 ─ OPC_MXU_S32SDIR
+ * │
+ * │ 13..10
+ * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
+ * │ └─ 0001 ─ OPC_MXU_S32LDIVR
+ * │
+ * │ 13..10
+ * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
+ * │ └─ 0001 ─ OPC_MXU_S32SDIVR
+ * ├─ 011000 ─ OPC_MXU_D32ADD
+ * │ 23..22
+ * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
+ * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
+ * │ └─ 10 ─ OPC_MXU_D32ASUM
+ * ├─ 011010 ─ <not assigned>
+ * │ 23..22
+ * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
+ * │ ├─ 01 ─ OPC_MXU_Q16ACCM
+ * │ └─ 10 ─ OPC_MXU_Q16ASUM
+ * │
+ * │ 23..22
+ * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
+ * │ ├─ 01 ─ OPC_MXU_D8SUM
+ * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
+ * ├─ 011110 ─ <not assigned>
+ * ├─ 011111 ─ <not assigned>
+ * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
+ * ├─ 100001 ─ <not assigned> (overlaps with CLO)
+ * ├─ 100010 ─ OPC_MXU_S8LDD
+ * ├─ 100011 ─ OPC_MXU_S8STD 15..14
+ * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
+ * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
+ * │ ├─ 00 ─ OPC_MXU_S32EXTR
+ * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
+ * │
+ * │ 20..18
+ * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
+ * │ ├─ 001 ─ OPC_MXU_S32ALN
+ * │ ├─ 010 ─ OPC_MXU_S32ALNI
+ * │ ├─ 011 ─ OPC_MXU_S32LUI
+ * │ ├─ 100 ─ OPC_MXU_S32NOR
+ * │ ├─ 101 ─ OPC_MXU_S32AND
+ * │ ├─ 110 ─ OPC_MXU_S32OR
+ * │ └─ 111 ─ OPC_MXU_S32XOR
+ * │
+ * │ 7..5
+ * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
+ * │ ├─ 001 ─ OPC_MXU_LXH
+ * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
+ * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
+ * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
+ * ├─ 101100 ─ OPC_MXU_S16LDI
+ * ├─ 101101 ─ OPC_MXU_S16SDI
+ * ├─ 101110 ─ OPC_MXU_S32M2I
+ * ├─ 101111 ─ OPC_MXU_S32I2M
+ * ├─ 110000 ─ OPC_MXU_D32SLL
+ * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
+ * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
+ * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
+ * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
+ * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
+ * │ ├─ 100 ─ OPC_MXU_Q16SLRV
+ * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
+ * │
+ * ├─ 110111 ─ OPC_MXU_Q16SAR
+ * │ 23..22
+ * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
+ * │ └─ 01 ─ OPC_MXU_Q8MULSU
+ * │
+ * │ 20..18
+ * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
+ * │ ├─ 001 ─ OPC_MXU_Q8MOVN
+ * │ ├─ 010 ─ OPC_MXU_D16MOVZ
+ * │ ├─ 011 ─ OPC_MXU_D16MOVN
+ * │ ├─ 100 ─ OPC_MXU_S32MOVZ
+ * │ └─ 101 ─ OPC_MXU_S32MOVN
+ * │
+ * │ 23..22
+ * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
+ * │ └─ 10 ─ OPC_MXU_Q8MACSU
+ * ├─ 111011 ─ OPC_MXU_Q16SCOP
+ * ├─ 111100 ─ OPC_MXU_Q8MADL
+ * ├─ 111101 ─ OPC_MXU_S32SFL
+ * ├─ 111110 ─ OPC_MXU_Q8SAD
+ * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
+ *
+ *
+ * Compiled after:
+ *
+ * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
+ * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
+ */
+
+enum {
+ OPC_MXU__POOL00 = 0x03,
+ OPC_MXU_D16MUL = 0x08,
+ OPC_MXU_D16MAC = 0x0A,
+ OPC_MXU__POOL04 = 0x10,
+ OPC_MXU_S8LDD = 0x22,
+ OPC_MXU__POOL16 = 0x27,
+ OPC_MXU_S32M2I = 0x2E,
+ OPC_MXU_S32I2M = 0x2F,
+ OPC_MXU__POOL19 = 0x38,
+};
+
+
+/*
+ * MXU pool 00
+ */
+enum {
+ OPC_MXU_S32MAX = 0x00,
+ OPC_MXU_S32MIN = 0x01,
+ OPC_MXU_D16MAX = 0x02,
+ OPC_MXU_D16MIN = 0x03,
+ OPC_MXU_Q8MAX = 0x04,
+ OPC_MXU_Q8MIN = 0x05,
+};
+
+/*
+ * MXU pool 04
+ */
+enum {
+ OPC_MXU_S32LDD = 0x00,
+ OPC_MXU_S32LDDR = 0x01,
+};
+
+/*
+ * MXU pool 16
+ */
+enum {
+ OPC_MXU_S32ALNI = 0x02,
+ OPC_MXU_S32NOR = 0x04,
+ OPC_MXU_S32AND = 0x05,
+ OPC_MXU_S32OR = 0x06,
+ OPC_MXU_S32XOR = 0x07,
+};
+
+/*
+ * MXU pool 19
+ */
+enum {
+ OPC_MXU_Q8MUL = 0x00,
+ OPC_MXU_Q8MULSU = 0x01,
+};
+
+/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
+#define MXU_APTN1_A 0
+#define MXU_APTN1_S 1
+
+/* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
+#define MXU_APTN2_AA 0
+#define MXU_APTN2_AS 1
+#define MXU_APTN2_SA 2
+#define MXU_APTN2_SS 3
+
+/* MXU execute add/subtract 2-bit pattern 'eptn2' */
+#define MXU_EPTN2_AA 0
+#define MXU_EPTN2_AS 1
+#define MXU_EPTN2_SA 2
+#define MXU_EPTN2_SS 3
+
+/* MXU operand getting pattern 'optn2' */
+#define MXU_OPTN2_PTN0 0
+#define MXU_OPTN2_PTN1 1
+#define MXU_OPTN2_PTN2 2
+#define MXU_OPTN2_PTN3 3
+/* alternative naming scheme for 'optn2' */
+#define MXU_OPTN2_WW 0
+#define MXU_OPTN2_LW 1
+#define MXU_OPTN2_HW 2
+#define MXU_OPTN2_XW 3
+
+/* MXU operand getting pattern 'optn3' */
+#define MXU_OPTN3_PTN0 0
+#define MXU_OPTN3_PTN1 1
+#define MXU_OPTN3_PTN2 2
+#define MXU_OPTN3_PTN3 3
+#define MXU_OPTN3_PTN4 4
+#define MXU_OPTN3_PTN5 5
+#define MXU_OPTN3_PTN6 6
+#define MXU_OPTN3_PTN7 7
+
+/* MXU registers */
+static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
+static TCGv mxu_CR;
+
+static const char * const mxuregnames[] = {
+ "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
+ "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
+};
+
+void mxu_translate_init(void)
+{
+ for (unsigned i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
+ mxu_gpr[i] = tcg_global_mem_new(cpu_env,
+ offsetof(CPUMIPSState, active_tc.mxu_gpr[i]),
+ mxuregnames[i]);
+ }
+
+ mxu_CR = tcg_global_mem_new(cpu_env,
+ offsetof(CPUMIPSState, active_tc.mxu_cr),
+ mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
+}
+
+/* MXU General purpose registers moves. */
+static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
+{
+ if (reg == 0) {
+ tcg_gen_movi_tl(t, 0);
+ } else if (reg <= 15) {
+ tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
+ }
+}
+
+static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
+{
+ if (reg > 0 && reg <= 15) {
+ tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
+ }
+}
+
+/* MXU control register moves. */
+static inline void gen_load_mxu_cr(TCGv t)
+{
+ tcg_gen_mov_tl(t, mxu_CR);
+}
+
+static inline void gen_store_mxu_cr(TCGv t)
+{
+ /* TODO: Add handling of RW rules for MXU_CR. */
+ tcg_gen_mov_tl(mxu_CR, t);
+}
+
+/*
+ * S32I2M XRa, rb - Register move from GRF to XRF
+ */
+static void gen_mxu_s32i2m(DisasContext *ctx)
+{
+ TCGv t0;
+ uint32_t XRa, Rb;
+
+ t0 = tcg_temp_new();
+
+ XRa = extract32(ctx->opcode, 6, 5);
+ Rb = extract32(ctx->opcode, 16, 5);
+
+ gen_load_gpr(t0, Rb);
+ if (XRa <= 15) {
+ gen_store_mxu_gpr(t0, XRa);
+ } else if (XRa == 16) {
+ gen_store_mxu_cr(t0);
+ }
+
+ tcg_temp_free(t0);
+}
+
+/*
+ * S32M2I XRa, rb - Register move from XRF to GRF
+ */
+static void gen_mxu_s32m2i(DisasContext *ctx)
+{
+ TCGv t0;
+ uint32_t XRa, Rb;
+
+ t0 = tcg_temp_new();
+
+ XRa = extract32(ctx->opcode, 6, 5);
+ Rb = extract32(ctx->opcode, 16, 5);
+
+ if (XRa <= 15) {
+ gen_load_mxu_gpr(t0, XRa);
+ } else if (XRa == 16) {
+ gen_load_mxu_cr(t0);
+ }
+
+ gen_store_gpr(t0, Rb);
+
+ tcg_temp_free(t0);
+}
+
+/*
+ * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
+ */
+static void gen_mxu_s8ldd(DisasContext *ctx)
+{
+ TCGv t0, t1;
+ uint32_t XRa, Rb, s8, optn3;
+
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+
+ XRa = extract32(ctx->opcode, 6, 4);
+ s8 = extract32(ctx->opcode, 10, 8);
+ optn3 = extract32(ctx->opcode, 18, 3);
+ Rb = extract32(ctx->opcode, 21, 5);
+
+ gen_load_gpr(t0, Rb);
+ tcg_gen_addi_tl(t0, t0, (int8_t)s8);
+
+ switch (optn3) {
+ /* XRa[7:0] = tmp8 */
+ case MXU_OPTN3_PTN0:
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+ gen_load_mxu_gpr(t0, XRa);
+ tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
+ break;
+ /* XRa[15:8] = tmp8 */
+ case MXU_OPTN3_PTN1:
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+ gen_load_mxu_gpr(t0, XRa);
+ tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
+ break;
+ /* XRa[23:16] = tmp8 */
+ case MXU_OPTN3_PTN2:
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+ gen_load_mxu_gpr(t0, XRa);
+ tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
+ break;
+ /* XRa[31:24] = tmp8 */
+ case MXU_OPTN3_PTN3:
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+ gen_load_mxu_gpr(t0, XRa);
+ tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
+ break;
+ /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
+ case MXU_OPTN3_PTN4:
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+ tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
+ break;
+ /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
+ case MXU_OPTN3_PTN5:
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+ tcg_gen_shli_tl(t1, t1, 8);
+ tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
+ break;
+ /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
+ case MXU_OPTN3_PTN6:
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
+ tcg_gen_mov_tl(t0, t1);
+ tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
+ tcg_gen_shli_tl(t1, t1, 16);
+ tcg_gen_or_tl(t0, t0, t1);
+ break;
+ /* XRa = {tmp8, tmp8, tmp8, tmp8} */
+ case MXU_OPTN3_PTN7:
+ tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
+ tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
+ tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
+ break;
+ }
+
+ gen_store_mxu_gpr(t0, XRa);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+}
+
+/*
+ * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
+ */
+static void gen_mxu_d16mul(DisasContext *ctx)
+{
+ TCGv t0, t1, t2, t3;
+ uint32_t XRa, XRb, XRc, XRd, optn2;
+
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+ t2 = tcg_temp_new();
+ t3 = tcg_temp_new();
+
+ XRa = extract32(ctx->opcode, 6, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRd = extract32(ctx->opcode, 18, 4);
+ optn2 = extract32(ctx->opcode, 22, 2);
+
+ gen_load_mxu_gpr(t1, XRb);
+ tcg_gen_sextract_tl(t0, t1, 0, 16);
+ tcg_gen_sextract_tl(t1, t1, 16, 16);
+ gen_load_mxu_gpr(t3, XRc);
+ tcg_gen_sextract_tl(t2, t3, 0, 16);
+ tcg_gen_sextract_tl(t3, t3, 16, 16);
+
+ switch (optn2) {
+ case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
+ tcg_gen_mul_tl(t3, t1, t3);
+ tcg_gen_mul_tl(t2, t0, t2);
+ break;
+ case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
+ tcg_gen_mul_tl(t3, t0, t3);
+ tcg_gen_mul_tl(t2, t0, t2);
+ break;
+ case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
+ tcg_gen_mul_tl(t3, t1, t3);
+ tcg_gen_mul_tl(t2, t1, t2);
+ break;
+ case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
+ tcg_gen_mul_tl(t3, t0, t3);
+ tcg_gen_mul_tl(t2, t1, t2);
+ break;
+ }
+ gen_store_mxu_gpr(t3, XRa);
+ gen_store_mxu_gpr(t2, XRd);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ tcg_temp_free(t2);
+ tcg_temp_free(t3);
+}
+
+/*
+ * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
+ * and accumulate
+ */
+static void gen_mxu_d16mac(DisasContext *ctx)
+{
+ TCGv t0, t1, t2, t3;
+ uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
+
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+ t2 = tcg_temp_new();
+ t3 = tcg_temp_new();
+
+ XRa = extract32(ctx->opcode, 6, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRd = extract32(ctx->opcode, 18, 4);
+ optn2 = extract32(ctx->opcode, 22, 2);
+ aptn2 = extract32(ctx->opcode, 24, 2);
+
+ gen_load_mxu_gpr(t1, XRb);
+ tcg_gen_sextract_tl(t0, t1, 0, 16);
+ tcg_gen_sextract_tl(t1, t1, 16, 16);
+
+ gen_load_mxu_gpr(t3, XRc);
+ tcg_gen_sextract_tl(t2, t3, 0, 16);
+ tcg_gen_sextract_tl(t3, t3, 16, 16);
+
+ switch (optn2) {
+ case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
+ tcg_gen_mul_tl(t3, t1, t3);
+ tcg_gen_mul_tl(t2, t0, t2);
+ break;
+ case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
+ tcg_gen_mul_tl(t3, t0, t3);
+ tcg_gen_mul_tl(t2, t0, t2);
+ break;
+ case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
+ tcg_gen_mul_tl(t3, t1, t3);
+ tcg_gen_mul_tl(t2, t1, t2);
+ break;
+ case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
+ tcg_gen_mul_tl(t3, t0, t3);
+ tcg_gen_mul_tl(t2, t1, t2);
+ break;
+ }
+ gen_load_mxu_gpr(t0, XRa);
+ gen_load_mxu_gpr(t1, XRd);
+
+ switch (aptn2) {
+ case MXU_APTN2_AA:
+ tcg_gen_add_tl(t3, t0, t3);
+ tcg_gen_add_tl(t2, t1, t2);
+ break;
+ case MXU_APTN2_AS:
+ tcg_gen_add_tl(t3, t0, t3);
+ tcg_gen_sub_tl(t2, t1, t2);
+ break;
+ case MXU_APTN2_SA:
+ tcg_gen_sub_tl(t3, t0, t3);
+ tcg_gen_add_tl(t2, t1, t2);
+ break;
+ case MXU_APTN2_SS:
+ tcg_gen_sub_tl(t3, t0, t3);
+ tcg_gen_sub_tl(t2, t1, t2);
+ break;
+ }
+ gen_store_mxu_gpr(t3, XRa);
+ gen_store_mxu_gpr(t2, XRd);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ tcg_temp_free(t2);
+ tcg_temp_free(t3);
+}
+
+/*
+ * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
+ * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
+ */
+static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
+{
+ TCGv t0, t1, t2, t3, t4, t5, t6, t7;
+ uint32_t XRa, XRb, XRc, XRd, sel;
+
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+ t2 = tcg_temp_new();
+ t3 = tcg_temp_new();
+ t4 = tcg_temp_new();
+ t5 = tcg_temp_new();
+ t6 = tcg_temp_new();
+ t7 = tcg_temp_new();
+
+ XRa = extract32(ctx->opcode, 6, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRd = extract32(ctx->opcode, 18, 4);
+ sel = extract32(ctx->opcode, 22, 2);
+
+ gen_load_mxu_gpr(t3, XRb);
+ gen_load_mxu_gpr(t7, XRc);
+
+ if (sel == 0x2) {
+ /* Q8MULSU */
+ tcg_gen_ext8s_tl(t0, t3);
+ tcg_gen_shri_tl(t3, t3, 8);
+ tcg_gen_ext8s_tl(t1, t3);
+ tcg_gen_shri_tl(t3, t3, 8);
+ tcg_gen_ext8s_tl(t2, t3);
+ tcg_gen_shri_tl(t3, t3, 8);
+ tcg_gen_ext8s_tl(t3, t3);
+ } else {
+ /* Q8MUL */
+ tcg_gen_ext8u_tl(t0, t3);
+ tcg_gen_shri_tl(t3, t3, 8);
+ tcg_gen_ext8u_tl(t1, t3);
+ tcg_gen_shri_tl(t3, t3, 8);
+ tcg_gen_ext8u_tl(t2, t3);
+ tcg_gen_shri_tl(t3, t3, 8);
+ tcg_gen_ext8u_tl(t3, t3);
+ }
+
+ tcg_gen_ext8u_tl(t4, t7);
+ tcg_gen_shri_tl(t7, t7, 8);
+ tcg_gen_ext8u_tl(t5, t7);
+ tcg_gen_shri_tl(t7, t7, 8);
+ tcg_gen_ext8u_tl(t6, t7);
+ tcg_gen_shri_tl(t7, t7, 8);
+ tcg_gen_ext8u_tl(t7, t7);
+
+ tcg_gen_mul_tl(t0, t0, t4);
+ tcg_gen_mul_tl(t1, t1, t5);
+ tcg_gen_mul_tl(t2, t2, t6);
+ tcg_gen_mul_tl(t3, t3, t7);
+
+ tcg_gen_andi_tl(t0, t0, 0xFFFF);
+ tcg_gen_andi_tl(t1, t1, 0xFFFF);
+ tcg_gen_andi_tl(t2, t2, 0xFFFF);
+ tcg_gen_andi_tl(t3, t3, 0xFFFF);
+
+ tcg_gen_shli_tl(t1, t1, 16);
+ tcg_gen_shli_tl(t3, t3, 16);
+
+ tcg_gen_or_tl(t0, t0, t1);
+ tcg_gen_or_tl(t1, t2, t3);
+
+ gen_store_mxu_gpr(t0, XRd);
+ gen_store_mxu_gpr(t1, XRa);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ tcg_temp_free(t2);
+ tcg_temp_free(t3);
+ tcg_temp_free(t4);
+ tcg_temp_free(t5);
+ tcg_temp_free(t6);
+ tcg_temp_free(t7);
+}
+
+/*
+ * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
+ * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
+ */
+static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
+{
+ TCGv t0, t1;
+ uint32_t XRa, Rb, s12, sel;
+
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+
+ XRa = extract32(ctx->opcode, 6, 4);
+ s12 = extract32(ctx->opcode, 10, 10);
+ sel = extract32(ctx->opcode, 20, 1);
+ Rb = extract32(ctx->opcode, 21, 5);
+
+ gen_load_gpr(t0, Rb);
+
+ tcg_gen_movi_tl(t1, s12);
+ tcg_gen_shli_tl(t1, t1, 2);
+ if (s12 & 0x200) {
+ tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
+ }
+ tcg_gen_add_tl(t1, t0, t1);
+ tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
+
+ if (sel == 1) {
+ /* S32LDDR */
+ tcg_gen_bswap32_tl(t1, t1);
+ }
+ gen_store_mxu_gpr(t1, XRa);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+}
+
+
+/*
+ * MXU instruction category: logic
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * S32NOR S32AND S32OR S32XOR
+ */
+
+/*
+ * S32NOR XRa, XRb, XRc
+ * Update XRa with the result of logical bitwise 'nor' operation
+ * applied to the content of XRb and XRc.
+ */
+static void gen_mxu_S32NOR(DisasContext *ctx)
+{
+ uint32_t pad, XRc, XRb, XRa;
+
+ pad = extract32(ctx->opcode, 21, 5);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRa = extract32(ctx->opcode, 6, 4);
+
+ if (unlikely(pad != 0)) {
+ /* opcode padding incorrect -> do nothing */
+ } else if (unlikely(XRa == 0)) {
+ /* destination is zero register -> do nothing */
+ } else if (unlikely((XRb == 0) && (XRc == 0))) {
+ /* both operands zero registers -> just set destination to all 1s */
+ tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
+ } else if (unlikely(XRb == 0)) {
+ /* XRb zero register -> just set destination to the negation of XRc */
+ tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
+ } else if (unlikely(XRc == 0)) {
+ /* XRa zero register -> just set destination to the negation of XRb */
+ tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ } else if (unlikely(XRb == XRc)) {
+ /* both operands same -> just set destination to the negation of XRb */
+ tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ } else {
+ /* the most general case */
+ tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
+ }
+}
+
+/*
+ * S32AND XRa, XRb, XRc
+ * Update XRa with the result of logical bitwise 'and' operation
+ * applied to the content of XRb and XRc.
+ */
+static void gen_mxu_S32AND(DisasContext *ctx)
+{
+ uint32_t pad, XRc, XRb, XRa;
+
+ pad = extract32(ctx->opcode, 21, 5);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRa = extract32(ctx->opcode, 6, 4);
+
+ if (unlikely(pad != 0)) {
+ /* opcode padding incorrect -> do nothing */
+ } else if (unlikely(XRa == 0)) {
+ /* destination is zero register -> do nothing */
+ } else if (unlikely((XRb == 0) || (XRc == 0))) {
+ /* one of operands zero register -> just set destination to all 0s */
+ tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
+ } else if (unlikely(XRb == XRc)) {
+ /* both operands same -> just set destination to one of them */
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ } else {
+ /* the most general case */
+ tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
+ }
+}
+
+/*
+ * S32OR XRa, XRb, XRc
+ * Update XRa with the result of logical bitwise 'or' operation
+ * applied to the content of XRb and XRc.
+ */
+static void gen_mxu_S32OR(DisasContext *ctx)
+{
+ uint32_t pad, XRc, XRb, XRa;
+
+ pad = extract32(ctx->opcode, 21, 5);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRa = extract32(ctx->opcode, 6, 4);
+
+ if (unlikely(pad != 0)) {
+ /* opcode padding incorrect -> do nothing */
+ } else if (unlikely(XRa == 0)) {
+ /* destination is zero register -> do nothing */
+ } else if (unlikely((XRb == 0) && (XRc == 0))) {
+ /* both operands zero registers -> just set destination to all 0s */
+ tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
+ } else if (unlikely(XRb == 0)) {
+ /* XRb zero register -> just set destination to the content of XRc */
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
+ } else if (unlikely(XRc == 0)) {
+ /* XRc zero register -> just set destination to the content of XRb */
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ } else if (unlikely(XRb == XRc)) {
+ /* both operands same -> just set destination to one of them */
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ } else {
+ /* the most general case */
+ tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
+ }
+}
+
+/*
+ * S32XOR XRa, XRb, XRc
+ * Update XRa with the result of logical bitwise 'xor' operation
+ * applied to the content of XRb and XRc.
+ */
+static void gen_mxu_S32XOR(DisasContext *ctx)
+{
+ uint32_t pad, XRc, XRb, XRa;
+
+ pad = extract32(ctx->opcode, 21, 5);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRa = extract32(ctx->opcode, 6, 4);
+
+ if (unlikely(pad != 0)) {
+ /* opcode padding incorrect -> do nothing */
+ } else if (unlikely(XRa == 0)) {
+ /* destination is zero register -> do nothing */
+ } else if (unlikely((XRb == 0) && (XRc == 0))) {
+ /* both operands zero registers -> just set destination to all 0s */
+ tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
+ } else if (unlikely(XRb == 0)) {
+ /* XRb zero register -> just set destination to the content of XRc */
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
+ } else if (unlikely(XRc == 0)) {
+ /* XRc zero register -> just set destination to the content of XRb */
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ } else if (unlikely(XRb == XRc)) {
+ /* both operands same -> just set destination to all 0s */
+ tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
+ } else {
+ /* the most general case */
+ tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
+ }
+}
+
+
+/*
+ * MXU instruction category max/min
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * S32MAX D16MAX Q8MAX
+ * S32MIN D16MIN Q8MIN
+ */
+
+/*
+ * S32MAX XRa, XRb, XRc
+ * Update XRa with the maximum of signed 32-bit integers contained
+ * in XRb and XRc.
+ *
+ * S32MIN XRa, XRb, XRc
+ * Update XRa with the minimum of signed 32-bit integers contained
+ * in XRb and XRc.
+ */
+static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
+{
+ uint32_t pad, opc, XRc, XRb, XRa;
+
+ pad = extract32(ctx->opcode, 21, 5);
+ opc = extract32(ctx->opcode, 18, 3);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRa = extract32(ctx->opcode, 6, 4);
+
+ if (unlikely(pad != 0)) {
+ /* opcode padding incorrect -> do nothing */
+ } else if (unlikely(XRa == 0)) {
+ /* destination is zero register -> do nothing */
+ } else if (unlikely((XRb == 0) && (XRc == 0))) {
+ /* both operands zero registers -> just set destination to zero */
+ tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
+ } else if (unlikely((XRb == 0) || (XRc == 0))) {
+ /* exactly one operand is zero register - find which one is not...*/
+ uint32_t XRx = XRb ? XRb : XRc;
+ /* ...and do max/min operation with one operand 0 */
+ if (opc == OPC_MXU_S32MAX) {
+ tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
+ } else {
+ tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
+ }
+ } else if (unlikely(XRb == XRc)) {
+ /* both operands same -> just set destination to one of them */
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ } else {
+ /* the most general case */
+ if (opc == OPC_MXU_S32MAX) {
+ tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
+ mxu_gpr[XRc - 1]);
+ } else {
+ tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
+ mxu_gpr[XRc - 1]);
+ }
+ }
+}
+
+/*
+ * D16MAX
+ * Update XRa with the 16-bit-wise maximums of signed integers
+ * contained in XRb and XRc.
+ *
+ * D16MIN
+ * Update XRa with the 16-bit-wise minimums of signed integers
+ * contained in XRb and XRc.
+ */
+static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
+{
+ uint32_t pad, opc, XRc, XRb, XRa;
+
+ pad = extract32(ctx->opcode, 21, 5);
+ opc = extract32(ctx->opcode, 18, 3);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRa = extract32(ctx->opcode, 6, 4);
+
+ if (unlikely(pad != 0)) {
+ /* opcode padding incorrect -> do nothing */
+ } else if (unlikely(XRc == 0)) {
+ /* destination is zero register -> do nothing */
+ } else if (unlikely((XRb == 0) && (XRa == 0))) {
+ /* both operands zero registers -> just set destination to zero */
+ tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
+ } else if (unlikely((XRb == 0) || (XRa == 0))) {
+ /* exactly one operand is zero register - find which one is not...*/
+ uint32_t XRx = XRb ? XRb : XRc;
+ /* ...and do half-word-wise max/min with one operand 0 */
+ TCGv_i32 t0 = tcg_temp_new();
+ TCGv_i32 t1 = tcg_const_i32(0);
+
+ /* the left half-word first */
+ tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
+ if (opc == OPC_MXU_D16MAX) {
+ tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
+ } else {
+ tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
+ }
+
+ /* the right half-word */
+ tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
+ /* move half-words to the leftmost position */
+ tcg_gen_shli_i32(t0, t0, 16);
+ /* t0 will be max/min of t0 and t1 */
+ if (opc == OPC_MXU_D16MAX) {
+ tcg_gen_smax_i32(t0, t0, t1);
+ } else {
+ tcg_gen_smin_i32(t0, t0, t1);
+ }
+ /* return resulting half-words to its original position */
+ tcg_gen_shri_i32(t0, t0, 16);
+ /* finally update the destination */
+ tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
+
+ tcg_temp_free(t1);
+ tcg_temp_free(t0);
+ } else if (unlikely(XRb == XRc)) {
+ /* both operands same -> just set destination to one of them */
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ } else {
+ /* the most general case */
+ TCGv_i32 t0 = tcg_temp_new();
+ TCGv_i32 t1 = tcg_temp_new();
+
+ /* the left half-word first */
+ tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
+ tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
+ if (opc == OPC_MXU_D16MAX) {
+ tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
+ } else {
+ tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
+ }
+
+ /* the right half-word */
+ tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
+ tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
+ /* move half-words to the leftmost position */
+ tcg_gen_shli_i32(t0, t0, 16);
+ tcg_gen_shli_i32(t1, t1, 16);
+ /* t0 will be max/min of t0 and t1 */
+ if (opc == OPC_MXU_D16MAX) {
+ tcg_gen_smax_i32(t0, t0, t1);
+ } else {
+ tcg_gen_smin_i32(t0, t0, t1);
+ }
+ /* return resulting half-words to its original position */
+ tcg_gen_shri_i32(t0, t0, 16);
+ /* finally update the destination */
+ tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
+
+ tcg_temp_free(t1);
+ tcg_temp_free(t0);
+ }
+}
+
+/*
+ * Q8MAX
+ * Update XRa with the 8-bit-wise maximums of signed integers
+ * contained in XRb and XRc.
+ *
+ * Q8MIN
+ * Update XRa with the 8-bit-wise minimums of signed integers
+ * contained in XRb and XRc.
+ */
+static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
+{
+ uint32_t pad, opc, XRc, XRb, XRa;
+
+ pad = extract32(ctx->opcode, 21, 5);
+ opc = extract32(ctx->opcode, 18, 3);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRa = extract32(ctx->opcode, 6, 4);
+
+ if (unlikely(pad != 0)) {
+ /* opcode padding incorrect -> do nothing */
+ } else if (unlikely(XRa == 0)) {
+ /* destination is zero register -> do nothing */
+ } else if (unlikely((XRb == 0) && (XRc == 0))) {
+ /* both operands zero registers -> just set destination to zero */
+ tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
+ } else if (unlikely((XRb == 0) || (XRc == 0))) {
+ /* exactly one operand is zero register - make it be the first...*/
+ uint32_t XRx = XRb ? XRb : XRc;
+ /* ...and do byte-wise max/min with one operand 0 */
+ TCGv_i32 t0 = tcg_temp_new();
+ TCGv_i32 t1 = tcg_const_i32(0);
+ int32_t i;
+
+ /* the leftmost byte (byte 3) first */
+ tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
+ if (opc == OPC_MXU_Q8MAX) {
+ tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
+ } else {
+ tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
+ }
+
+ /* bytes 2, 1, 0 */
+ for (i = 2; i >= 0; i--) {
+ /* extract the byte */
+ tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
+ /* move the byte to the leftmost position */
+ tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
+ /* t0 will be max/min of t0 and t1 */
+ if (opc == OPC_MXU_Q8MAX) {
+ tcg_gen_smax_i32(t0, t0, t1);
+ } else {
+ tcg_gen_smin_i32(t0, t0, t1);
+ }
+ /* return resulting byte to its original position */
+ tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
+ /* finally update the destination */
+ tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
+ }
+
+ tcg_temp_free(t1);
+ tcg_temp_free(t0);
+ } else if (unlikely(XRb == XRc)) {
+ /* both operands same -> just set destination to one of them */
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ } else {
+ /* the most general case */
+ TCGv_i32 t0 = tcg_temp_new();
+ TCGv_i32 t1 = tcg_temp_new();
+ int32_t i;
+
+ /* the leftmost bytes (bytes 3) first */
+ tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
+ tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
+ if (opc == OPC_MXU_Q8MAX) {
+ tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
+ } else {
+ tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
+ }
+
+ /* bytes 2, 1, 0 */
+ for (i = 2; i >= 0; i--) {
+ /* extract corresponding bytes */
+ tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
+ tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
+ /* move the bytes to the leftmost position */
+ tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
+ tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
+ /* t0 will be max/min of t0 and t1 */
+ if (opc == OPC_MXU_Q8MAX) {
+ tcg_gen_smax_i32(t0, t0, t1);
+ } else {
+ tcg_gen_smin_i32(t0, t0, t1);
+ }
+ /* return resulting byte to its original position */
+ tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
+ /* finally update the destination */
+ tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
+ }
+
+ tcg_temp_free(t1);
+ tcg_temp_free(t0);
+ }
+}
+
+
+/*
+ * MXU instruction category: align
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * S32ALN S32ALNI
+ */
+
+/*
+ * S32ALNI XRc, XRb, XRa, optn3
+ * Arrange bytes from XRb and XRc according to one of five sets of
+ * rules determined by optn3, and place the result in XRa.
+ */
+static void gen_mxu_S32ALNI(DisasContext *ctx)
+{
+ uint32_t optn3, pad, XRc, XRb, XRa;
+
+ optn3 = extract32(ctx->opcode, 23, 3);
+ pad = extract32(ctx->opcode, 21, 2);
+ XRc = extract32(ctx->opcode, 14, 4);
+ XRb = extract32(ctx->opcode, 10, 4);
+ XRa = extract32(ctx->opcode, 6, 4);
+
+ if (unlikely(pad != 0)) {
+ /* opcode padding incorrect -> do nothing */
+ } else if (unlikely(XRa == 0)) {
+ /* destination is zero register -> do nothing */
+ } else if (unlikely((XRb == 0) && (XRc == 0))) {
+ /* both operands zero registers -> just set destination to all 0s */
+ tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
+ } else if (unlikely(XRb == 0)) {
+ /* XRb zero register -> just appropriatelly shift XRc into XRa */
+ switch (optn3) {
+ case MXU_OPTN3_PTN0:
+ tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
+ break;
+ case MXU_OPTN3_PTN1:
+ case MXU_OPTN3_PTN2:
+ case MXU_OPTN3_PTN3:
+ tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
+ 8 * (4 - optn3));
+ break;
+ case MXU_OPTN3_PTN4:
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
+ break;
+ }
+ } else if (unlikely(XRc == 0)) {
+ /* XRc zero register -> just appropriatelly shift XRb into XRa */
+ switch (optn3) {
+ case MXU_OPTN3_PTN0:
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ break;
+ case MXU_OPTN3_PTN1:
+ case MXU_OPTN3_PTN2:
+ case MXU_OPTN3_PTN3:
+ tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
+ break;
+ case MXU_OPTN3_PTN4:
+ tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
+ break;
+ }
+ } else if (unlikely(XRb == XRc)) {
+ /* both operands same -> just rotation or moving from any of them */
+ switch (optn3) {
+ case MXU_OPTN3_PTN0:
+ case MXU_OPTN3_PTN4:
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ break;
+ case MXU_OPTN3_PTN1:
+ case MXU_OPTN3_PTN2:
+ case MXU_OPTN3_PTN3:
+ tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
+ break;
+ }
+ } else {
+ /* the most general case */
+ switch (optn3) {
+ case MXU_OPTN3_PTN0:
+ {
+ /* */
+ /* XRb XRc */
+ /* +---------------+ */
+ /* | A B C D | E F G H */
+ /* +-------+-------+ */
+ /* | */
+ /* XRa */
+ /* */
+
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
+ }
+ break;
+ case MXU_OPTN3_PTN1:
+ {
+ /* */
+ /* XRb XRc */
+ /* +-------------------+ */
+ /* A | B C D E | F G H */
+ /* +---------+---------+ */
+ /* | */
+ /* XRa */
+ /* */
+
+ TCGv_i32 t0 = tcg_temp_new();
+ TCGv_i32 t1 = tcg_temp_new();
+
+ tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
+ tcg_gen_shli_i32(t0, t0, 8);
+
+ tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
+ tcg_gen_shri_i32(t1, t1, 24);
+
+ tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
+
+ tcg_temp_free(t1);
+ tcg_temp_free(t0);
+ }
+ break;
+ case MXU_OPTN3_PTN2:
+ {
+ /* */
+ /* XRb XRc */
+ /* +-------------------+ */
+ /* A B | C D E F | G H */
+ /* +---------+---------+ */
+ /* | */
+ /* XRa */
+ /* */
+
+ TCGv_i32 t0 = tcg_temp_new();
+ TCGv_i32 t1 = tcg_temp_new();
+
+ tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
+ tcg_gen_shli_i32(t0, t0, 16);
+
+ tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
+ tcg_gen_shri_i32(t1, t1, 16);
+
+ tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
+
+ tcg_temp_free(t1);
+ tcg_temp_free(t0);
+ }
+ break;
+ case MXU_OPTN3_PTN3:
+ {
+ /* */
+ /* XRb XRc */
+ /* +-------------------+ */
+ /* A B C | D E F G | H */
+ /* +---------+---------+ */
+ /* | */
+ /* XRa */
+ /* */
+
+ TCGv_i32 t0 = tcg_temp_new();
+ TCGv_i32 t1 = tcg_temp_new();
+
+ tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
+ tcg_gen_shli_i32(t0, t0, 24);
+
+ tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
+ tcg_gen_shri_i32(t1, t1, 8);
+
+ tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
+
+ tcg_temp_free(t1);
+ tcg_temp_free(t0);
+ }
+ break;
+ case MXU_OPTN3_PTN4:
+ {
+ /* */
+ /* XRb XRc */
+ /* +---------------+ */
+ /* A B C D | E F G H | */
+ /* +-------+-------+ */
+ /* | */
+ /* XRa */
+ /* */
+
+ tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
+ }
+ break;
+ }
+ }
+}
+
+
+/*
+ * Decoding engine for MXU
+ * =======================
+ */
+
+static void decode_opc_mxu__pool00(DisasContext *ctx)
+{
+ uint32_t opcode = extract32(ctx->opcode, 18, 3);
+
+ switch (opcode) {
+ case OPC_MXU_S32MAX:
+ case OPC_MXU_S32MIN:
+ gen_mxu_S32MAX_S32MIN(ctx);
+ break;
+ case OPC_MXU_D16MAX:
+ case OPC_MXU_D16MIN:
+ gen_mxu_D16MAX_D16MIN(ctx);
+ break;
+ case OPC_MXU_Q8MAX:
+ case OPC_MXU_Q8MIN:
+ gen_mxu_Q8MAX_Q8MIN(ctx);
+ break;
+ default:
+ MIPS_INVAL("decode_opc_mxu");
+ gen_reserved_instruction(ctx);
+ break;
+ }
+}
+
+static void decode_opc_mxu__pool04(DisasContext *ctx)
+{
+ uint32_t opcode = extract32(ctx->opcode, 20, 1);
+
+ switch (opcode) {
+ case OPC_MXU_S32LDD:
+ case OPC_MXU_S32LDDR:
+ gen_mxu_s32ldd_s32lddr(ctx);
+ break;
+ default:
+ MIPS_INVAL("decode_opc_mxu");
+ gen_reserved_instruction(ctx);
+ break;
+ }
+}
+
+static void decode_opc_mxu__pool16(DisasContext *ctx)
+{
+ uint32_t opcode = extract32(ctx->opcode, 18, 3);
+
+ switch (opcode) {
+ case OPC_MXU_S32ALNI:
+ gen_mxu_S32ALNI(ctx);
+ break;
+ case OPC_MXU_S32NOR:
+ gen_mxu_S32NOR(ctx);
+ break;
+ case OPC_MXU_S32AND:
+ gen_mxu_S32AND(ctx);
+ break;
+ case OPC_MXU_S32OR:
+ gen_mxu_S32OR(ctx);
+ break;
+ case OPC_MXU_S32XOR:
+ gen_mxu_S32XOR(ctx);
+ break;
+ default:
+ MIPS_INVAL("decode_opc_mxu");
+ gen_reserved_instruction(ctx);
+ break;
+ }
+}
+
+static void decode_opc_mxu__pool19(DisasContext *ctx)
+{
+ uint32_t opcode = extract32(ctx->opcode, 22, 2);
+
+ switch (opcode) {
+ case OPC_MXU_Q8MUL:
+ case OPC_MXU_Q8MULSU:
+ gen_mxu_q8mul_q8mulsu(ctx);
+ break;
+ default:
+ MIPS_INVAL("decode_opc_mxu");
+ gen_reserved_instruction(ctx);
+ break;
+ }
+}
+
+bool decode_ase_mxu(DisasContext *ctx, uint32_t insn)
+{
+ uint32_t opcode = extract32(insn, 0, 6);
+
+ if (opcode == OPC_MXU_S32M2I) {
+ gen_mxu_s32m2i(ctx);
+ return true;
+ }
+
+ if (opcode == OPC_MXU_S32I2M) {
+ gen_mxu_s32i2m(ctx);
+ return true;
+ }
+
+ {
+ TCGv t_mxu_cr = tcg_temp_new();
+ TCGLabel *l_exit = gen_new_label();
+
+ gen_load_mxu_cr(t_mxu_cr);
+ tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
+
+ switch (opcode) {
+ case OPC_MXU__POOL00:
+ decode_opc_mxu__pool00(ctx);
+ break;
+ case OPC_MXU_D16MUL:
+ gen_mxu_d16mul(ctx);
+ break;
+ case OPC_MXU_D16MAC:
+ gen_mxu_d16mac(ctx);
+ break;
+ case OPC_MXU__POOL04:
+ decode_opc_mxu__pool04(ctx);
+ break;
+ case OPC_MXU_S8LDD:
+ gen_mxu_s8ldd(ctx);
+ break;
+ case OPC_MXU__POOL16:
+ decode_opc_mxu__pool16(ctx);
+ break;
+ case OPC_MXU__POOL19:
+ decode_opc_mxu__pool19(ctx);
+ break;
+ default:
+ MIPS_INVAL("decode_opc_mxu");
+ gen_reserved_instruction(ctx);
+ }
+
+ gen_set_label(l_exit);
+ tcg_temp_free(t_mxu_cr);
+ }
+
+ return true;
+}
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 0b6d82d228..c518bf3963 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -1130,779 +1130,6 @@ enum {
};
/*
- *
- * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
- * ============================================
- *
- *
- * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
- * instructions set. It is designed to fit the needs of signal, graphical and
- * video processing applications. MXU instruction set is used in Xburst family
- * of microprocessors by Ingenic.
- *
- * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
- * the control register.
- *
- *
- * The notation used in MXU assembler mnemonics
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * Register operands:
- *
- * XRa, XRb, XRc, XRd - MXU registers
- * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
- *
- * Non-register operands:
- *
- * aptn1 - 1-bit accumulate add/subtract pattern
- * aptn2 - 2-bit accumulate add/subtract pattern
- * eptn2 - 2-bit execute add/subtract pattern
- * optn2 - 2-bit operand pattern
- * optn3 - 3-bit operand pattern
- * sft4 - 4-bit shift amount
- * strd2 - 2-bit stride amount
- *
- * Prefixes:
- *
- * Level of parallelism: Operand size:
- * S - single operation at a time 32 - word
- * D - two operations in parallel 16 - half word
- * Q - four operations in parallel 8 - byte
- *
- * Operations:
- *
- * ADD - Add or subtract
- * ADDC - Add with carry-in
- * ACC - Accumulate
- * ASUM - Sum together then accumulate (add or subtract)
- * ASUMC - Sum together then accumulate (add or subtract) with carry-in
- * AVG - Average between 2 operands
- * ABD - Absolute difference
- * ALN - Align data
- * AND - Logical bitwise 'and' operation
- * CPS - Copy sign
- * EXTR - Extract bits
- * I2M - Move from GPR register to MXU register
- * LDD - Load data from memory to XRF
- * LDI - Load data from memory to XRF (and increase the address base)
- * LUI - Load unsigned immediate
- * MUL - Multiply
- * MULU - Unsigned multiply
- * MADD - 64-bit operand add 32x32 product
- * MSUB - 64-bit operand subtract 32x32 product
- * MAC - Multiply and accumulate (add or subtract)
- * MAD - Multiply and add or subtract
- * MAX - Maximum between 2 operands
- * MIN - Minimum between 2 operands
- * M2I - Move from MXU register to GPR register
- * MOVZ - Move if zero
- * MOVN - Move if non-zero
- * NOR - Logical bitwise 'nor' operation
- * OR - Logical bitwise 'or' operation
- * STD - Store data from XRF to memory
- * SDI - Store data from XRF to memory (and increase the address base)
- * SLT - Set of less than comparison
- * SAD - Sum of absolute differences
- * SLL - Logical shift left
- * SLR - Logical shift right
- * SAR - Arithmetic shift right
- * SAT - Saturation
- * SFL - Shuffle
- * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
- * XOR - Logical bitwise 'exclusive or' operation
- *
- * Suffixes:
- *
- * E - Expand results
- * F - Fixed point multiplication
- * L - Low part result
- * R - Doing rounding
- * V - Variable instead of immediate
- * W - Combine above L and V
- *
- *
- * The list of MXU instructions grouped by functionality
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * Load/Store instructions Multiplication instructions
- * ----------------------- ---------------------------
- *
- * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
- * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
- * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
- * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
- * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
- * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
- * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
- * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
- * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
- * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
- * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
- * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
- * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
- * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
- * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
- * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
- * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
- * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
- * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
- * S16SDI XRa, Rb, s10, eptn2
- * S8LDD XRa, Rb, s8, eptn3
- * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
- * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
- * S8SDI XRa, Rb, s8, eptn3
- * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
- * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
- * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
- * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
- * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
- * S32CPS XRa, XRb, XRc
- * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
- * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
- * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
- * D16ASUM XRa, XRb, XRc, XRd, eptn2
- * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
- * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
- * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
- * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
- * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
- * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
- * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
- * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
- * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
- * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
- * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
- * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
- * Q8SLT XRa, XRb, XRc
- * Q8SLTU XRa, XRb, XRc
- * Q8MOVZ XRa, XRb, XRc Shift instructions
- * Q8MOVN XRa, XRb, XRc ------------------
- *
- * D32SLL XRa, XRb, XRc, XRd, sft4
- * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
- * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
- * D32SARL XRa, XRb, XRc, sft4
- * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
- * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
- * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
- * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
- * Q16SLL XRa, XRb, XRc, XRd, sft4
- * Q16SLR XRa, XRb, XRc, XRd, sft4
- * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
- * ------------------------- Q16SLLV XRa, XRb, Rb
- * Q16SLRV XRa, XRb, Rb
- * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
- * S32ALN XRa, XRb, XRc, Rb
- * S32ALNI XRa, XRb, XRc, s3
- * S32LUI XRa, s8, optn3 Move instructions
- * S32EXTR XRa, XRb, Rb, bits5 -----------------
- * S32EXTRV XRa, XRb, Rs, Rt
- * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
- * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
- *
- *
- * The opcode organization of MXU instructions
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
- * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
- * other bits up to the instruction level is as follows:
- *
- * bits
- * 05..00
- *
- * ┌─ 000000 ─ OPC_MXU_S32MADD
- * ├─ 000001 ─ OPC_MXU_S32MADDU
- * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
- * │
- * │ 20..18
- * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
- * │ ├─ 001 ─ OPC_MXU_S32MIN
- * │ ├─ 010 ─ OPC_MXU_D16MAX
- * │ ├─ 011 ─ OPC_MXU_D16MIN
- * │ ├─ 100 ─ OPC_MXU_Q8MAX
- * │ ├─ 101 ─ OPC_MXU_Q8MIN
- * │ ├─ 110 ─ OPC_MXU_Q8SLT
- * │ └─ 111 ─ OPC_MXU_Q8SLTU
- * ├─ 000100 ─ OPC_MXU_S32MSUB
- * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
- * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
- * │ ├─ 001 ─ OPC_MXU_D16SLT
- * │ ├─ 010 ─ OPC_MXU_D16AVG
- * │ ├─ 011 ─ OPC_MXU_D16AVGR
- * │ ├─ 100 ─ OPC_MXU_Q8AVG
- * │ ├─ 101 ─ OPC_MXU_Q8AVGR
- * │ └─ 111 ─ OPC_MXU_Q8ADD
- * │
- * │ 20..18
- * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
- * │ ├─ 010 ─ OPC_MXU_D16CPS
- * │ ├─ 100 ─ OPC_MXU_Q8ABD
- * │ └─ 110 ─ OPC_MXU_Q16SAT
- * ├─ 001000 ─ OPC_MXU_D16MUL
- * │ 25..24
- * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
- * │ └─ 01 ─ OPC_MXU_D16MULE
- * ├─ 001010 ─ OPC_MXU_D16MAC
- * ├─ 001011 ─ OPC_MXU_D16MACF
- * ├─ 001100 ─ OPC_MXU_D16MADL
- * ├─ 001101 ─ OPC_MXU_S16MAD
- * ├─ 001110 ─ OPC_MXU_Q16ADD
- * ├─ 001111 ─ OPC_MXU_D16MACE 23
- * │ ┌─ 0 ─ OPC_MXU_S32LDD
- * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
- * │
- * │ 23
- * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
- * │ └─ 1 ─ OPC_MXU_S32STDR
- * │
- * │ 13..10
- * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
- * │ └─ 0001 ─ OPC_MXU_S32LDDVR
- * │
- * │ 13..10
- * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
- * │ └─ 0001 ─ OPC_MXU_S32STDVR
- * │
- * │ 23
- * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
- * │ └─ 1 ─ OPC_MXU_S32LDIR
- * │
- * │ 23
- * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
- * │ └─ 1 ─ OPC_MXU_S32SDIR
- * │
- * │ 13..10
- * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
- * │ └─ 0001 ─ OPC_MXU_S32LDIVR
- * │
- * │ 13..10
- * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
- * │ └─ 0001 ─ OPC_MXU_S32SDIVR
- * ├─ 011000 ─ OPC_MXU_D32ADD
- * │ 23..22
- * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
- * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
- * │ └─ 10 ─ OPC_MXU_D32ASUM
- * ├─ 011010 ─ <not assigned>
- * │ 23..22
- * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
- * │ ├─ 01 ─ OPC_MXU_Q16ACCM
- * │ └─ 10 ─ OPC_MXU_Q16ASUM
- * │
- * │ 23..22
- * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
- * │ ├─ 01 ─ OPC_MXU_D8SUM
- * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
- * ├─ 011110 ─ <not assigned>
- * ├─ 011111 ─ <not assigned>
- * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
- * ├─ 100001 ─ <not assigned> (overlaps with CLO)
- * ├─ 100010 ─ OPC_MXU_S8LDD
- * ├─ 100011 ─ OPC_MXU_S8STD 15..14
- * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
- * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
- * │ ├─ 00 ─ OPC_MXU_S32EXTR
- * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
- * │
- * │ 20..18
- * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
- * │ ├─ 001 ─ OPC_MXU_S32ALN
- * │ ├─ 010 ─ OPC_MXU_S32ALNI
- * │ ├─ 011 ─ OPC_MXU_S32LUI
- * │ ├─ 100 ─ OPC_MXU_S32NOR
- * │ ├─ 101 ─ OPC_MXU_S32AND
- * │ ├─ 110 ─ OPC_MXU_S32OR
- * │ └─ 111 ─ OPC_MXU_S32XOR
- * │
- * │ 7..5
- * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
- * │ ├─ 001 ─ OPC_MXU_LXH
- * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
- * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
- * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
- * ├─ 101100 ─ OPC_MXU_S16LDI
- * ├─ 101101 ─ OPC_MXU_S16SDI
- * ├─ 101110 ─ OPC_MXU_S32M2I
- * ├─ 101111 ─ OPC_MXU_S32I2M
- * ├─ 110000 ─ OPC_MXU_D32SLL
- * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
- * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
- * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
- * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
- * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
- * │ ├─ 100 ─ OPC_MXU_Q16SLRV
- * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
- * │
- * ├─ 110111 ─ OPC_MXU_Q16SAR
- * │ 23..22
- * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
- * │ └─ 01 ─ OPC_MXU_Q8MULSU
- * │
- * │ 20..18
- * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
- * │ ├─ 001 ─ OPC_MXU_Q8MOVN
- * │ ├─ 010 ─ OPC_MXU_D16MOVZ
- * │ ├─ 011 ─ OPC_MXU_D16MOVN
- * │ ├─ 100 ─ OPC_MXU_S32MOVZ
- * │ └─ 101 ─ OPC_MXU_S32MOVN
- * │
- * │ 23..22
- * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
- * │ └─ 10 ─ OPC_MXU_Q8MACSU
- * ├─ 111011 ─ OPC_MXU_Q16SCOP
- * ├─ 111100 ─ OPC_MXU_Q8MADL
- * ├─ 111101 ─ OPC_MXU_S32SFL
- * ├─ 111110 ─ OPC_MXU_Q8SAD
- * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
- *
- *
- * Compiled after:
- *
- * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
- * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
- */
-
-enum {
- OPC_MXU_S32MADD = 0x00,
- OPC_MXU_S32MADDU = 0x01,
- OPC__MXU_MUL = 0x02,
- OPC_MXU__POOL00 = 0x03,
- OPC_MXU_S32MSUB = 0x04,
- OPC_MXU_S32MSUBU = 0x05,
- OPC_MXU__POOL01 = 0x06,
- OPC_MXU__POOL02 = 0x07,
- OPC_MXU_D16MUL = 0x08,
- OPC_MXU__POOL03 = 0x09,
- OPC_MXU_D16MAC = 0x0A,
- OPC_MXU_D16MACF = 0x0B,
- OPC_MXU_D16MADL = 0x0C,
- OPC_MXU_S16MAD = 0x0D,
- OPC_MXU_Q16ADD = 0x0E,
- OPC_MXU_D16MACE = 0x0F,
- OPC_MXU__POOL04 = 0x10,
- OPC_MXU__POOL05 = 0x11,
- OPC_MXU__POOL06 = 0x12,
- OPC_MXU__POOL07 = 0x13,
- OPC_MXU__POOL08 = 0x14,
- OPC_MXU__POOL09 = 0x15,
- OPC_MXU__POOL10 = 0x16,
- OPC_MXU__POOL11 = 0x17,
- OPC_MXU_D32ADD = 0x18,
- OPC_MXU__POOL12 = 0x19,
- /* not assigned 0x1A */
- OPC_MXU__POOL13 = 0x1B,
- OPC_MXU__POOL14 = 0x1C,
- OPC_MXU_Q8ACCE = 0x1D,
- /* not assigned 0x1E */
- /* not assigned 0x1F */
- /* not assigned 0x20 */
- /* not assigned 0x21 */
- OPC_MXU_S8LDD = 0x22,
- OPC_MXU_S8STD = 0x23,
- OPC_MXU_S8LDI = 0x24,
- OPC_MXU_S8SDI = 0x25,
- OPC_MXU__POOL15 = 0x26,
- OPC_MXU__POOL16 = 0x27,
- OPC_MXU__POOL17 = 0x28,
- /* not assigned 0x29 */
- OPC_MXU_S16LDD = 0x2A,
- OPC_MXU_S16STD = 0x2B,
- OPC_MXU_S16LDI = 0x2C,
- OPC_MXU_S16SDI = 0x2D,
- OPC_MXU_S32M2I = 0x2E,
- OPC_MXU_S32I2M = 0x2F,
- OPC_MXU_D32SLL = 0x30,
- OPC_MXU_D32SLR = 0x31,
- OPC_MXU_D32SARL = 0x32,
- OPC_MXU_D32SAR = 0x33,
- OPC_MXU_Q16SLL = 0x34,
- OPC_MXU_Q16SLR = 0x35,
- OPC_MXU__POOL18 = 0x36,
- OPC_MXU_Q16SAR = 0x37,
- OPC_MXU__POOL19 = 0x38,
- OPC_MXU__POOL20 = 0x39,
- OPC_MXU__POOL21 = 0x3A,
- OPC_MXU_Q16SCOP = 0x3B,
- OPC_MXU_Q8MADL = 0x3C,
- OPC_MXU_S32SFL = 0x3D,
- OPC_MXU_Q8SAD = 0x3E,
- /* not assigned 0x3F */
-};
-
-
-/*
- * MXU pool 00
- */
-enum {
- OPC_MXU_S32MAX = 0x00,
- OPC_MXU_S32MIN = 0x01,
- OPC_MXU_D16MAX = 0x02,
- OPC_MXU_D16MIN = 0x03,
- OPC_MXU_Q8MAX = 0x04,
- OPC_MXU_Q8MIN = 0x05,
- OPC_MXU_Q8SLT = 0x06,
- OPC_MXU_Q8SLTU = 0x07,
-};
-
-/*
- * MXU pool 01
- */
-enum {
- OPC_MXU_S32SLT = 0x00,
- OPC_MXU_D16SLT = 0x01,
- OPC_MXU_D16AVG = 0x02,
- OPC_MXU_D16AVGR = 0x03,
- OPC_MXU_Q8AVG = 0x04,
- OPC_MXU_Q8AVGR = 0x05,
- OPC_MXU_Q8ADD = 0x07,
-};
-
-/*
- * MXU pool 02
- */
-enum {
- OPC_MXU_S32CPS = 0x00,
- OPC_MXU_D16CPS = 0x02,
- OPC_MXU_Q8ABD = 0x04,
- OPC_MXU_Q16SAT = 0x06,
-};
-
-/*
- * MXU pool 03
- */
-enum {
- OPC_MXU_D16MULF = 0x00,
- OPC_MXU_D16MULE = 0x01,
-};
-
-/*
- * MXU pool 04
- */
-enum {
- OPC_MXU_S32LDD = 0x00,
- OPC_MXU_S32LDDR = 0x01,
-};
-
-/*
- * MXU pool 05
- */
-enum {
- OPC_MXU_S32STD = 0x00,
- OPC_MXU_S32STDR = 0x01,
-};
-
-/*
- * MXU pool 06
- */
-enum {
- OPC_MXU_S32LDDV = 0x00,
- OPC_MXU_S32LDDVR = 0x01,
-};
-
-/*
- * MXU pool 07
- */
-enum {
- OPC_MXU_S32STDV = 0x00,
- OPC_MXU_S32STDVR = 0x01,
-};
-
-/*
- * MXU pool 08
- */
-enum {
- OPC_MXU_S32LDI = 0x00,
- OPC_MXU_S32LDIR = 0x01,
-};
-
-/*
- * MXU pool 09
- */
-enum {
- OPC_MXU_S32SDI = 0x00,
- OPC_MXU_S32SDIR = 0x01,
-};
-
-/*
- * MXU pool 10
- */
-enum {
- OPC_MXU_S32LDIV = 0x00,
- OPC_MXU_S32LDIVR = 0x01,
-};
-
-/*
- * MXU pool 11
- */
-enum {
- OPC_MXU_S32SDIV = 0x00,
- OPC_MXU_S32SDIVR = 0x01,
-};
-
-/*
- * MXU pool 12
- */
-enum {
- OPC_MXU_D32ACC = 0x00,
- OPC_MXU_D32ACCM = 0x01,
- OPC_MXU_D32ASUM = 0x02,
-};
-
-/*
- * MXU pool 13
- */
-enum {
- OPC_MXU_Q16ACC = 0x00,
- OPC_MXU_Q16ACCM = 0x01,
- OPC_MXU_Q16ASUM = 0x02,
-};
-
-/*
- * MXU pool 14
- */
-enum {
- OPC_MXU_Q8ADDE = 0x00,
- OPC_MXU_D8SUM = 0x01,
- OPC_MXU_D8SUMC = 0x02,
-};
-
-/*
- * MXU pool 15
- */
-enum {
- OPC_MXU_S32MUL = 0x00,
- OPC_MXU_S32MULU = 0x01,
- OPC_MXU_S32EXTR = 0x02,
- OPC_MXU_S32EXTRV = 0x03,
-};
-
-/*
- * MXU pool 16
- */
-enum {
- OPC_MXU_D32SARW = 0x00,
- OPC_MXU_S32ALN = 0x01,
- OPC_MXU_S32ALNI = 0x02,
- OPC_MXU_S32LUI = 0x03,
- OPC_MXU_S32NOR = 0x04,
- OPC_MXU_S32AND = 0x05,
- OPC_MXU_S32OR = 0x06,
- OPC_MXU_S32XOR = 0x07,
-};
-
-/*
- * MXU pool 17
- */
-enum {
- OPC_MXU_LXB = 0x00,
- OPC_MXU_LXH = 0x01,
- OPC_MXU_LXW = 0x03,
- OPC_MXU_LXBU = 0x04,
- OPC_MXU_LXHU = 0x05,
-};
-
-/*
- * MXU pool 18
- */
-enum {
- OPC_MXU_D32SLLV = 0x00,
- OPC_MXU_D32SLRV = 0x01,
- OPC_MXU_D32SARV = 0x03,
- OPC_MXU_Q16SLLV = 0x04,
- OPC_MXU_Q16SLRV = 0x05,
- OPC_MXU_Q16SARV = 0x07,
-};
-
-/*
- * MXU pool 19
- */
-enum {
- OPC_MXU_Q8MUL = 0x00,
- OPC_MXU_Q8MULSU = 0x01,
-};
-
-/*
- * MXU pool 20
- */
-enum {
- OPC_MXU_Q8MOVZ = 0x00,
- OPC_MXU_Q8MOVN = 0x01,
- OPC_MXU_D16MOVZ = 0x02,
- OPC_MXU_D16MOVN = 0x03,
- OPC_MXU_S32MOVZ = 0x04,
- OPC_MXU_S32MOVN = 0x05,
-};
-
-/*
- * MXU pool 21
- */
-enum {
- OPC_MXU_Q8MAC = 0x00,
- OPC_MXU_Q8MACSU = 0x01,
-};
-
-/*
- * Overview of the TX79-specific instruction set
- * =============================================
- *
- * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
- * are only used by the specific quadword (128-bit) LQ/SQ load/store
- * instructions and certain multimedia instructions (MMIs). These MMIs
- * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
- * or sixteen 8-bit paths.
- *
- * Reference:
- *
- * The Toshiba TX System RISC TX79 Core Architecture manual,
- * https://wiki.qemu.org/File:C790.pdf
- *
- * Three-Operand Multiply and Multiply-Add (4 instructions)
- * --------------------------------------------------------
- * MADD [rd,] rs, rt Multiply/Add
- * MADDU [rd,] rs, rt Multiply/Add Unsigned
- * MULT [rd,] rs, rt Multiply (3-operand)
- * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
- *
- * Multiply Instructions for Pipeline 1 (10 instructions)
- * ------------------------------------------------------
- * MULT1 [rd,] rs, rt Multiply Pipeline 1
- * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
- * DIV1 rs, rt Divide Pipeline 1
- * DIVU1 rs, rt Divide Unsigned Pipeline 1
- * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
- * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
- * MFHI1 rd Move From HI1 Register
- * MFLO1 rd Move From LO1 Register
- * MTHI1 rs Move To HI1 Register
- * MTLO1 rs Move To LO1 Register
- *
- * Arithmetic (19 instructions)
- * ----------------------------
- * PADDB rd, rs, rt Parallel Add Byte
- * PSUBB rd, rs, rt Parallel Subtract Byte
- * PADDH rd, rs, rt Parallel Add Halfword
- * PSUBH rd, rs, rt Parallel Subtract Halfword
- * PADDW rd, rs, rt Parallel Add Word
- * PSUBW rd, rs, rt Parallel Subtract Word
- * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
- * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
- * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
- * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
- * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
- * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
- * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
- * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
- * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
- * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
- * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
- * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
- * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
- *
- * Min/Max (4 instructions)
- * ------------------------
- * PMAXH rd, rs, rt Parallel Maximum Halfword
- * PMINH rd, rs, rt Parallel Minimum Halfword
- * PMAXW rd, rs, rt Parallel Maximum Word
- * PMINW rd, rs, rt Parallel Minimum Word
- *
- * Absolute (2 instructions)
- * -------------------------
- * PABSH rd, rt Parallel Absolute Halfword
- * PABSW rd, rt Parallel Absolute Word
- *
- * Logical (4 instructions)
- * ------------------------
- * PAND rd, rs, rt Parallel AND
- * POR rd, rs, rt Parallel OR
- * PXOR rd, rs, rt Parallel XOR
- * PNOR rd, rs, rt Parallel NOR
- *
- * Shift (9 instructions)
- * ----------------------
- * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
- * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
- * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
- * PSLLW rd, rt, sa Parallel Shift Left Logical Word
- * PSRLW rd, rt, sa Parallel Shift Right Logical Word
- * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
- * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
- * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
- * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
- *
- * Compare (6 instructions)
- * ------------------------
- * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
- * PCEQB rd, rs, rt Parallel Compare for Equal Byte
- * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
- * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
- * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
- * PCEQW rd, rs, rt Parallel Compare for Equal Word
- *
- * LZC (1 instruction)
- * -------------------
- * PLZCW rd, rs Parallel Leading Zero or One Count Word
- *
- * Quadword Load and Store (2 instructions)
- * ----------------------------------------
- * LQ rt, offset(base) Load Quadword
- * SQ rt, offset(base) Store Quadword
- *
- * Multiply and Divide (19 instructions)
- * -------------------------------------
- * PMULTW rd, rs, rt Parallel Multiply Word
- * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
- * PDIVW rs, rt Parallel Divide Word
- * PDIVUW rs, rt Parallel Divide Unsigned Word
- * PMADDW rd, rs, rt Parallel Multiply-Add Word
- * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
- * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
- * PMULTH rd, rs, rt Parallel Multiply Halfword
- * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
- * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
- * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
- * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
- * PDIVBW rs, rt Parallel Divide Broadcast Word
- * PMFHI rd Parallel Move From HI Register
- * PMFLO rd Parallel Move From LO Register
- * PMTHI rs Parallel Move To HI Register
- * PMTLO rs Parallel Move To LO Register
- * PMFHL rd Parallel Move From HI/LO Register
- * PMTHL rs Parallel Move To HI/LO Register
- *
- * Pack/Extend (11 instructions)
- * -----------------------------
- * PPAC5 rd, rt Parallel Pack to 5 bits
- * PPACB rd, rs, rt Parallel Pack to Byte
- * PPACH rd, rs, rt Parallel Pack to Halfword
- * PPACW rd, rs, rt Parallel Pack to Word
- * PEXT5 rd, rt Parallel Extend Upper from 5 bits
- * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
- * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
- * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
- * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
- * PEXTUW rd, rs, rt Parallel Extend Upper from Word
- * PEXTLW rd, rs, rt Parallel Extend Lower from Word
- *
- * Others (16 instructions)
- * ------------------------
- * PCPYH rd, rt Parallel Copy Halfword
- * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
- * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
- * PREVH rd, rt Parallel Reverse Halfword
- * PINTH rd, rs, rt Parallel Interleave Halfword
- * PINTEH rd, rs, rt Parallel Interleave Even Halfword
- * PEXEH rd, rt Parallel Exchange Even Halfword
- * PEXCH rd, rt Parallel Exchange Center Halfword
- * PEXEW rd, rt Parallel Exchange Even Word
- * PEXCW rd, rt Parallel Exchange Center Word
- * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
- * MFSA rd Move from Shift Amount Register
- * MTSA rs Move to Shift Amount Register
- * MTSAB rs, immediate Move Byte Count to Shift Amount Register
- * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
- * PROT3W rd, rt Parallel Rotate 3 Words
- *
* MMI (MultiMedia Instruction) encodings
* ======================================
*
@@ -1970,211 +1197,12 @@ enum {
enum {
MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
- MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
- MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
- MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
- MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
- MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
- MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
- MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
- MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
- MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
- MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
- MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
- MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
- MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
- MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
- MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
- MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
- MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
-};
-
-/*
- * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
- *
- * 31 26 10 6 5 0
- * +--------+----------------------+--------+--------+
- * | MMI | |function| MMI0 |
- * +--------+----------------------+--------+--------+
- *
- * function bits 7..6
- * bits | 0 | 1 | 2 | 3
- * 10..8 | 00 | 01 | 10 | 11
- * -------+-------+-------+-------+-------
- * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
- * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
- * 2 010 | PADDB | PSUBB | PCGTB | *
- * 3 011 | * | * | * | *
- * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
- * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
- * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
- * 7 111 | * | * | PEXT5 | PPAC5
- */
-
-#define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
-enum {
- MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
- MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
-};
-
-/*
- * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
- *
- * 31 26 10 6 5 0
- * +--------+----------------------+--------+--------+
- * | MMI | |function| MMI1 |
- * +--------+----------------------+--------+--------+
- *
- * function bits 7..6
- * bits | 0 | 1 | 2 | 3
- * 10..8 | 00 | 01 | 10 | 11
- * -------+-------+-------+-------+-------
- * 0 000 | * | PABSW | PCEQW | PMINW
- * 1 001 | PADSBH| PABSH | PCEQH | PMINH
- * 2 010 | * | * | PCEQB | *
- * 3 011 | * | * | * | *
- * 4 100 | PADDUW| PSUBUW| PEXTUW| *
- * 5 101 | PADDUH| PSUBUH| PEXTUH| *
- * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
- * 7 111 | * | * | * | *
- */
-
-#define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
-enum {
- MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
- MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
-};
-
-/*
- * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
- *
- * 31 26 10 6 5 0
- * +--------+----------------------+--------+--------+
- * | MMI | |function| MMI2 |
- * +--------+----------------------+--------+--------+
- *
- * function bits 7..6
- * bits | 0 | 1 | 2 | 3
- * 10..8 | 00 | 01 | 10 | 11
- * -------+-------+-------+-------+-------
- * 0 000 | PMADDW| * | PSLLVW| PSRLVW
- * 1 001 | PMSUBW| * | * | *
- * 2 010 | PMFHI | PMFLO | PINTH | *
- * 3 011 | PMULTW| PDIVW | PCPYLD| *
- * 4 100 | PMADDH| PHMADH| PAND | PXOR
- * 5 101 | PMSUBH| PHMSBH| * | *
- * 6 110 | * | * | PEXEH | PREVH
- * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
- */
-
-#define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
-enum {
- MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
- MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
-};
-
-/*
- * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
- *
- * 31 26 10 6 5 0
- * +--------+----------------------+--------+--------+
- * | MMI | |function| MMI3 |
- * +--------+----------------------+--------+--------+
- *
- * function bits 7..6
- * bits | 0 | 1 | 2 | 3
- * 10..8 | 00 | 01 | 10 | 11
- * -------+-------+-------+-------+-------
- * 0 000 |PMADDUW| * | * | PSRAVW
- * 1 001 | * | * | * | *
- * 2 010 | PMTHI | PMTLO | PINTEH| *
- * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
- * 4 100 | * | * | POR | PNOR
- * 5 101 | * | * | * | *
- * 6 110 | * | * | PEXCH | PCPYH
- * 7 111 | * | * | PEXCW | *
- */
-
-#define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
-enum {
- MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
- MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
- MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
- MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
- MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
- MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
- MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
- MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
- MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
- MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
- MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
- MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
- MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
};
/* global register indices */
@@ -2192,12 +1220,6 @@ static TCGv_i32 hflags;
TCGv_i32 fpu_fcr0, fpu_fcr31;
TCGv_i64 fpu_f64[32];
-#if !defined(TARGET_MIPS64)
-/* MXU registers */
-static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
-static TCGv mxu_CR;
-#endif
-
#include "exec/gen-icount.h"
#define gen_helper_0e0i(name, arg) do { \
@@ -2267,13 +1289,6 @@ static const char * const fregnames[] = {
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
};
-#if !defined(TARGET_MIPS64)
-static const char * const mxuregnames[] = {
- "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
- "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
-};
-#endif
-
/* General purpose registers moves. */
void gen_load_gpr(TCGv t, int reg)
{
@@ -2357,38 +1372,6 @@ static inline void gen_store_srsgpr(int from, int to)
}
}
-#if !defined(TARGET_MIPS64)
-/* MXU General purpose registers moves. */
-static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
-{
- if (reg == 0) {
- tcg_gen_movi_tl(t, 0);
- } else if (reg <= 15) {
- tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
- }
-}
-
-static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
-{
- if (reg > 0 && reg <= 15) {
- tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
- }
-}
-
-/* MXU control register moves. */
-static inline void gen_load_mxu_cr(TCGv t)
-{
- tcg_gen_mov_tl(t, mxu_CR);
-}
-
-static inline void gen_store_mxu_cr(TCGv t)
-{
- /* TODO: Add handling of RW rules for MXU_CR. */
- tcg_gen_mov_tl(mxu_CR, t);
-}
-#endif
-
-
/* Tests */
static inline void gen_save_pc(target_ulong pc)
{
@@ -4122,31 +3105,6 @@ static void gen_shift(DisasContext *ctx, uint32_t opc,
tcg_temp_free(t1);
}
-#if defined(TARGET_MIPS64)
-/* Copy GPR to and from TX79 HI1/LO1 register. */
-static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
-{
- switch (opc) {
- case MMI_OPC_MFHI1:
- gen_store_gpr(cpu_HI[1], reg);
- break;
- case MMI_OPC_MFLO1:
- gen_store_gpr(cpu_LO[1], reg);
- break;
- case MMI_OPC_MTHI1:
- gen_load_gpr(cpu_HI[1], reg);
- break;
- case MMI_OPC_MTLO1:
- gen_load_gpr(cpu_LO[1], reg);
- break;
- default:
- MIPS_INVAL("mfthilo1 TX79");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-#endif
-
/* Arithmetic on HI/LO registers */
static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
{
@@ -11118,11 +10076,7 @@ static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
tcg_gen_brcondi_i32(cond, t0, 0, l1);
tcg_temp_free_i32(t0);
- if (rs == 0) {
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- } else {
- tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
- }
+ gen_load_gpr(cpu_gpr[rd], rs);
gen_set_label(l1);
}
@@ -13040,7 +11994,7 @@ static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
}
}
-static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
+void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
{
TCGv t0;
@@ -15452,24 +14406,15 @@ static void gen_pool16c_insn(DisasContext *ctx)
static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
int enc_rs)
{
- int rd, rs, re, rt;
+ int rd, re;
static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
+
rd = rd_enc[enc_dest];
re = re_enc[enc_dest];
- rs = rs_rt_enc[enc_rs];
- rt = rs_rt_enc[enc_rt];
- if (rs) {
- tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
- } else {
- tcg_gen_movi_tl(cpu_gpr[rd], 0);
- }
- if (rt) {
- tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
- } else {
- tcg_gen_movi_tl(cpu_gpr[re], 0);
- }
+ gen_load_gpr(cpu_gpr[rd], rs_rt_enc[enc_rs]);
+ gen_load_gpr(cpu_gpr[re], rs_rt_enc[enc_rt]);
}
static void gen_pool16c_r6_insn(DisasContext *ctx)
@@ -24742,2400 +23687,6 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
}
-#if defined(TARGET_MIPS64)
-
-/*
- *
- * MMI (MultiMedia Interface) ASE instructions
- * ===========================================
- */
-
-/*
- * MMI instructions category: data communication
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
- * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
- * PCPYUD PEXEH PEXTLW PPACW
- * PEXEW PEXTUB
- * PEXTUH
- * PEXTUW
- */
-
-/*
- * PCPYH rd, rt
- *
- * Parallel Copy Halfword
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+---------+---------+---------+-----------+
- * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
- * +-----------+---------+---------+---------+---------+-----------+
- */
-static void gen_mmi_pcpyh(DisasContext *ctx)
-{
- uint32_t pd, rt, rd;
- uint32_t opcode;
-
- opcode = ctx->opcode;
-
- pd = extract32(opcode, 21, 5);
- rt = extract32(opcode, 16, 5);
- rd = extract32(opcode, 11, 5);
-
- if (unlikely(pd != 0)) {
- gen_reserved_instruction(ctx);
- } else if (rd == 0) {
- /* nop */
- } else if (rt == 0) {
- tcg_gen_movi_i64(cpu_gpr[rd], 0);
- tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
- } else {
- TCGv_i64 t0 = tcg_temp_new();
- TCGv_i64 t1 = tcg_temp_new();
- uint64_t mask = (1ULL << 16) - 1;
-
- tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
- tcg_gen_movi_i64(t1, 0);
- tcg_gen_or_i64(t1, t0, t1);
- tcg_gen_shli_i64(t0, t0, 16);
- tcg_gen_or_i64(t1, t0, t1);
- tcg_gen_shli_i64(t0, t0, 16);
- tcg_gen_or_i64(t1, t0, t1);
- tcg_gen_shli_i64(t0, t0, 16);
- tcg_gen_or_i64(t1, t0, t1);
-
- tcg_gen_mov_i64(cpu_gpr[rd], t1);
-
- tcg_gen_andi_i64(t0, cpu_gpr_hi[rt], mask);
- tcg_gen_movi_i64(t1, 0);
- tcg_gen_or_i64(t1, t0, t1);
- tcg_gen_shli_i64(t0, t0, 16);
- tcg_gen_or_i64(t1, t0, t1);
- tcg_gen_shli_i64(t0, t0, 16);
- tcg_gen_or_i64(t1, t0, t1);
- tcg_gen_shli_i64(t0, t0, 16);
- tcg_gen_or_i64(t1, t0, t1);
-
- tcg_gen_mov_i64(cpu_gpr_hi[rd], t1);
-
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- }
-}
-
-/*
- * PCPYLD rd, rs, rt
- *
- * Parallel Copy Lower Doubleword
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+---------+---------+---------+-----------+
- * | MMI | rs | rt | rd | PCPYLD | MMI2 |
- * +-----------+---------+---------+---------+---------+-----------+
- */
-static void gen_mmi_pcpyld(DisasContext *ctx)
-{
- uint32_t rs, rt, rd;
- uint32_t opcode;
-
- opcode = ctx->opcode;
-
- rs = extract32(opcode, 21, 5);
- rt = extract32(opcode, 16, 5);
- rd = extract32(opcode, 11, 5);
-
- if (rd == 0) {
- /* nop */
- } else {
- if (rs == 0) {
- tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
- } else {
- tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr[rs]);
- }
- if (rt == 0) {
- tcg_gen_movi_i64(cpu_gpr[rd], 0);
- } else {
- if (rd != rt) {
- tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
- }
- }
- }
-}
-
-/*
- * PCPYUD rd, rs, rt
- *
- * Parallel Copy Upper Doubleword
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+---------+---------+---------+-----------+
- * | MMI | rs | rt | rd | PCPYUD | MMI3 |
- * +-----------+---------+---------+---------+---------+-----------+
- */
-static void gen_mmi_pcpyud(DisasContext *ctx)
-{
- uint32_t rs, rt, rd;
- uint32_t opcode;
-
- opcode = ctx->opcode;
-
- rs = extract32(opcode, 21, 5);
- rt = extract32(opcode, 16, 5);
- rd = extract32(opcode, 11, 5);
-
- if (rd == 0) {
- /* nop */
- } else {
- if (rs == 0) {
- tcg_gen_movi_i64(cpu_gpr[rd], 0);
- } else {
- tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr_hi[rs]);
- }
- if (rt == 0) {
- tcg_gen_movi_i64(cpu_gpr_hi[rd], 0);
- } else {
- if (rd != rt) {
- tcg_gen_mov_i64(cpu_gpr_hi[rd], cpu_gpr_hi[rt]);
- }
- }
- }
-}
-
-#endif
-
-
-#if !defined(TARGET_MIPS64)
-
-/* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
-#define MXU_APTN1_A 0
-#define MXU_APTN1_S 1
-
-/* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
-#define MXU_APTN2_AA 0
-#define MXU_APTN2_AS 1
-#define MXU_APTN2_SA 2
-#define MXU_APTN2_SS 3
-
-/* MXU execute add/subtract 2-bit pattern 'eptn2' */
-#define MXU_EPTN2_AA 0
-#define MXU_EPTN2_AS 1
-#define MXU_EPTN2_SA 2
-#define MXU_EPTN2_SS 3
-
-/* MXU operand getting pattern 'optn2' */
-#define MXU_OPTN2_PTN0 0
-#define MXU_OPTN2_PTN1 1
-#define MXU_OPTN2_PTN2 2
-#define MXU_OPTN2_PTN3 3
-/* alternative naming scheme for 'optn2' */
-#define MXU_OPTN2_WW 0
-#define MXU_OPTN2_LW 1
-#define MXU_OPTN2_HW 2
-#define MXU_OPTN2_XW 3
-
-/* MXU operand getting pattern 'optn3' */
-#define MXU_OPTN3_PTN0 0
-#define MXU_OPTN3_PTN1 1
-#define MXU_OPTN3_PTN2 2
-#define MXU_OPTN3_PTN3 3
-#define MXU_OPTN3_PTN4 4
-#define MXU_OPTN3_PTN5 5
-#define MXU_OPTN3_PTN6 6
-#define MXU_OPTN3_PTN7 7
-
-
-/*
- * S32I2M XRa, rb - Register move from GRF to XRF
- */
-static void gen_mxu_s32i2m(DisasContext *ctx)
-{
- TCGv t0;
- uint32_t XRa, Rb;
-
- t0 = tcg_temp_new();
-
- XRa = extract32(ctx->opcode, 6, 5);
- Rb = extract32(ctx->opcode, 16, 5);
-
- gen_load_gpr(t0, Rb);
- if (XRa <= 15) {
- gen_store_mxu_gpr(t0, XRa);
- } else if (XRa == 16) {
- gen_store_mxu_cr(t0);
- }
-
- tcg_temp_free(t0);
-}
-
-/*
- * S32M2I XRa, rb - Register move from XRF to GRF
- */
-static void gen_mxu_s32m2i(DisasContext *ctx)
-{
- TCGv t0;
- uint32_t XRa, Rb;
-
- t0 = tcg_temp_new();
-
- XRa = extract32(ctx->opcode, 6, 5);
- Rb = extract32(ctx->opcode, 16, 5);
-
- if (XRa <= 15) {
- gen_load_mxu_gpr(t0, XRa);
- } else if (XRa == 16) {
- gen_load_mxu_cr(t0);
- }
-
- gen_store_gpr(t0, Rb);
-
- tcg_temp_free(t0);
-}
-
-/*
- * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
- */
-static void gen_mxu_s8ldd(DisasContext *ctx)
-{
- TCGv t0, t1;
- uint32_t XRa, Rb, s8, optn3;
-
- t0 = tcg_temp_new();
- t1 = tcg_temp_new();
-
- XRa = extract32(ctx->opcode, 6, 4);
- s8 = extract32(ctx->opcode, 10, 8);
- optn3 = extract32(ctx->opcode, 18, 3);
- Rb = extract32(ctx->opcode, 21, 5);
-
- gen_load_gpr(t0, Rb);
- tcg_gen_addi_tl(t0, t0, (int8_t)s8);
-
- switch (optn3) {
- /* XRa[7:0] = tmp8 */
- case MXU_OPTN3_PTN0:
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
- gen_load_mxu_gpr(t0, XRa);
- tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
- break;
- /* XRa[15:8] = tmp8 */
- case MXU_OPTN3_PTN1:
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
- gen_load_mxu_gpr(t0, XRa);
- tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
- break;
- /* XRa[23:16] = tmp8 */
- case MXU_OPTN3_PTN2:
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
- gen_load_mxu_gpr(t0, XRa);
- tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
- break;
- /* XRa[31:24] = tmp8 */
- case MXU_OPTN3_PTN3:
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
- gen_load_mxu_gpr(t0, XRa);
- tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
- break;
- /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
- case MXU_OPTN3_PTN4:
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
- tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
- break;
- /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
- case MXU_OPTN3_PTN5:
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
- tcg_gen_shli_tl(t1, t1, 8);
- tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
- break;
- /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
- case MXU_OPTN3_PTN6:
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
- tcg_gen_mov_tl(t0, t1);
- tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
- tcg_gen_shli_tl(t1, t1, 16);
- tcg_gen_or_tl(t0, t0, t1);
- break;
- /* XRa = {tmp8, tmp8, tmp8, tmp8} */
- case MXU_OPTN3_PTN7:
- tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
- tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
- tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
- break;
- }
-
- gen_store_mxu_gpr(t0, XRa);
-
- tcg_temp_free(t0);
- tcg_temp_free(t1);
-}
-
-/*
- * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
- */
-static void gen_mxu_d16mul(DisasContext *ctx)
-{
- TCGv t0, t1, t2, t3;
- uint32_t XRa, XRb, XRc, XRd, optn2;
-
- t0 = tcg_temp_new();
- t1 = tcg_temp_new();
- t2 = tcg_temp_new();
- t3 = tcg_temp_new();
-
- XRa = extract32(ctx->opcode, 6, 4);
- XRb = extract32(ctx->opcode, 10, 4);
- XRc = extract32(ctx->opcode, 14, 4);
- XRd = extract32(ctx->opcode, 18, 4);
- optn2 = extract32(ctx->opcode, 22, 2);
-
- gen_load_mxu_gpr(t1, XRb);
- tcg_gen_sextract_tl(t0, t1, 0, 16);
- tcg_gen_sextract_tl(t1, t1, 16, 16);
- gen_load_mxu_gpr(t3, XRc);
- tcg_gen_sextract_tl(t2, t3, 0, 16);
- tcg_gen_sextract_tl(t3, t3, 16, 16);
-
- switch (optn2) {
- case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
- tcg_gen_mul_tl(t3, t1, t3);
- tcg_gen_mul_tl(t2, t0, t2);
- break;
- case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
- tcg_gen_mul_tl(t3, t0, t3);
- tcg_gen_mul_tl(t2, t0, t2);
- break;
- case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
- tcg_gen_mul_tl(t3, t1, t3);
- tcg_gen_mul_tl(t2, t1, t2);
- break;
- case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
- tcg_gen_mul_tl(t3, t0, t3);
- tcg_gen_mul_tl(t2, t1, t2);
- break;
- }
- gen_store_mxu_gpr(t3, XRa);
- gen_store_mxu_gpr(t2, XRd);
-
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- tcg_temp_free(t2);
- tcg_temp_free(t3);
-}
-
-/*
- * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
- * and accumulate
- */
-static void gen_mxu_d16mac(DisasContext *ctx)
-{
- TCGv t0, t1, t2, t3;
- uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
-
- t0 = tcg_temp_new();
- t1 = tcg_temp_new();
- t2 = tcg_temp_new();
- t3 = tcg_temp_new();
-
- XRa = extract32(ctx->opcode, 6, 4);
- XRb = extract32(ctx->opcode, 10, 4);
- XRc = extract32(ctx->opcode, 14, 4);
- XRd = extract32(ctx->opcode, 18, 4);
- optn2 = extract32(ctx->opcode, 22, 2);
- aptn2 = extract32(ctx->opcode, 24, 2);
-
- gen_load_mxu_gpr(t1, XRb);
- tcg_gen_sextract_tl(t0, t1, 0, 16);
- tcg_gen_sextract_tl(t1, t1, 16, 16);
-
- gen_load_mxu_gpr(t3, XRc);
- tcg_gen_sextract_tl(t2, t3, 0, 16);
- tcg_gen_sextract_tl(t3, t3, 16, 16);
-
- switch (optn2) {
- case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
- tcg_gen_mul_tl(t3, t1, t3);
- tcg_gen_mul_tl(t2, t0, t2);
- break;
- case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
- tcg_gen_mul_tl(t3, t0, t3);
- tcg_gen_mul_tl(t2, t0, t2);
- break;
- case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
- tcg_gen_mul_tl(t3, t1, t3);
- tcg_gen_mul_tl(t2, t1, t2);
- break;
- case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
- tcg_gen_mul_tl(t3, t0, t3);
- tcg_gen_mul_tl(t2, t1, t2);
- break;
- }
- gen_load_mxu_gpr(t0, XRa);
- gen_load_mxu_gpr(t1, XRd);
-
- switch (aptn2) {
- case MXU_APTN2_AA:
- tcg_gen_add_tl(t3, t0, t3);
- tcg_gen_add_tl(t2, t1, t2);
- break;
- case MXU_APTN2_AS:
- tcg_gen_add_tl(t3, t0, t3);
- tcg_gen_sub_tl(t2, t1, t2);
- break;
- case MXU_APTN2_SA:
- tcg_gen_sub_tl(t3, t0, t3);
- tcg_gen_add_tl(t2, t1, t2);
- break;
- case MXU_APTN2_SS:
- tcg_gen_sub_tl(t3, t0, t3);
- tcg_gen_sub_tl(t2, t1, t2);
- break;
- }
- gen_store_mxu_gpr(t3, XRa);
- gen_store_mxu_gpr(t2, XRd);
-
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- tcg_temp_free(t2);
- tcg_temp_free(t3);
-}
-
-/*
- * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
- * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
- */
-static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
-{
- TCGv t0, t1, t2, t3, t4, t5, t6, t7;
- uint32_t XRa, XRb, XRc, XRd, sel;
-
- t0 = tcg_temp_new();
- t1 = tcg_temp_new();
- t2 = tcg_temp_new();
- t3 = tcg_temp_new();
- t4 = tcg_temp_new();
- t5 = tcg_temp_new();
- t6 = tcg_temp_new();
- t7 = tcg_temp_new();
-
- XRa = extract32(ctx->opcode, 6, 4);
- XRb = extract32(ctx->opcode, 10, 4);
- XRc = extract32(ctx->opcode, 14, 4);
- XRd = extract32(ctx->opcode, 18, 4);
- sel = extract32(ctx->opcode, 22, 2);
-
- gen_load_mxu_gpr(t3, XRb);
- gen_load_mxu_gpr(t7, XRc);
-
- if (sel == 0x2) {
- /* Q8MULSU */
- tcg_gen_ext8s_tl(t0, t3);
- tcg_gen_shri_tl(t3, t3, 8);
- tcg_gen_ext8s_tl(t1, t3);
- tcg_gen_shri_tl(t3, t3, 8);
- tcg_gen_ext8s_tl(t2, t3);
- tcg_gen_shri_tl(t3, t3, 8);
- tcg_gen_ext8s_tl(t3, t3);
- } else {
- /* Q8MUL */
- tcg_gen_ext8u_tl(t0, t3);
- tcg_gen_shri_tl(t3, t3, 8);
- tcg_gen_ext8u_tl(t1, t3);
- tcg_gen_shri_tl(t3, t3, 8);
- tcg_gen_ext8u_tl(t2, t3);
- tcg_gen_shri_tl(t3, t3, 8);
- tcg_gen_ext8u_tl(t3, t3);
- }
-
- tcg_gen_ext8u_tl(t4, t7);
- tcg_gen_shri_tl(t7, t7, 8);
- tcg_gen_ext8u_tl(t5, t7);
- tcg_gen_shri_tl(t7, t7, 8);
- tcg_gen_ext8u_tl(t6, t7);
- tcg_gen_shri_tl(t7, t7, 8);
- tcg_gen_ext8u_tl(t7, t7);
-
- tcg_gen_mul_tl(t0, t0, t4);
- tcg_gen_mul_tl(t1, t1, t5);
- tcg_gen_mul_tl(t2, t2, t6);
- tcg_gen_mul_tl(t3, t3, t7);
-
- tcg_gen_andi_tl(t0, t0, 0xFFFF);
- tcg_gen_andi_tl(t1, t1, 0xFFFF);
- tcg_gen_andi_tl(t2, t2, 0xFFFF);
- tcg_gen_andi_tl(t3, t3, 0xFFFF);
-
- tcg_gen_shli_tl(t1, t1, 16);
- tcg_gen_shli_tl(t3, t3, 16);
-
- tcg_gen_or_tl(t0, t0, t1);
- tcg_gen_or_tl(t1, t2, t3);
-
- gen_store_mxu_gpr(t0, XRd);
- gen_store_mxu_gpr(t1, XRa);
-
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- tcg_temp_free(t2);
- tcg_temp_free(t3);
- tcg_temp_free(t4);
- tcg_temp_free(t5);
- tcg_temp_free(t6);
- tcg_temp_free(t7);
-}
-
-/*
- * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
- * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
- */
-static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
-{
- TCGv t0, t1;
- uint32_t XRa, Rb, s12, sel;
-
- t0 = tcg_temp_new();
- t1 = tcg_temp_new();
-
- XRa = extract32(ctx->opcode, 6, 4);
- s12 = extract32(ctx->opcode, 10, 10);
- sel = extract32(ctx->opcode, 20, 1);
- Rb = extract32(ctx->opcode, 21, 5);
-
- gen_load_gpr(t0, Rb);
-
- tcg_gen_movi_tl(t1, s12);
- tcg_gen_shli_tl(t1, t1, 2);
- if (s12 & 0x200) {
- tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
- }
- tcg_gen_add_tl(t1, t0, t1);
- tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
-
- if (sel == 1) {
- /* S32LDDR */
- tcg_gen_bswap32_tl(t1, t1);
- }
- gen_store_mxu_gpr(t1, XRa);
-
- tcg_temp_free(t0);
- tcg_temp_free(t1);
-}
-
-
-/*
- * MXU instruction category: logic
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * S32NOR S32AND S32OR S32XOR
- */
-
-/*
- * S32NOR XRa, XRb, XRc
- * Update XRa with the result of logical bitwise 'nor' operation
- * applied to the content of XRb and XRc.
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- */
-static void gen_mxu_S32NOR(DisasContext *ctx)
-{
- uint32_t pad, XRc, XRb, XRa;
-
- pad = extract32(ctx->opcode, 21, 5);
- XRc = extract32(ctx->opcode, 14, 4);
- XRb = extract32(ctx->opcode, 10, 4);
- XRa = extract32(ctx->opcode, 6, 4);
-
- if (unlikely(pad != 0)) {
- /* opcode padding incorrect -> do nothing */
- } else if (unlikely(XRa == 0)) {
- /* destination is zero register -> do nothing */
- } else if (unlikely((XRb == 0) && (XRc == 0))) {
- /* both operands zero registers -> just set destination to all 1s */
- tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
- } else if (unlikely(XRb == 0)) {
- /* XRb zero register -> just set destination to the negation of XRc */
- tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
- } else if (unlikely(XRc == 0)) {
- /* XRa zero register -> just set destination to the negation of XRb */
- tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
- } else if (unlikely(XRb == XRc)) {
- /* both operands same -> just set destination to the negation of XRb */
- tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
- } else {
- /* the most general case */
- tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
- }
-}
-
-/*
- * S32AND XRa, XRb, XRc
- * Update XRa with the result of logical bitwise 'and' operation
- * applied to the content of XRb and XRc.
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- */
-static void gen_mxu_S32AND(DisasContext *ctx)
-{
- uint32_t pad, XRc, XRb, XRa;
-
- pad = extract32(ctx->opcode, 21, 5);
- XRc = extract32(ctx->opcode, 14, 4);
- XRb = extract32(ctx->opcode, 10, 4);
- XRa = extract32(ctx->opcode, 6, 4);
-
- if (unlikely(pad != 0)) {
- /* opcode padding incorrect -> do nothing */
- } else if (unlikely(XRa == 0)) {
- /* destination is zero register -> do nothing */
- } else if (unlikely((XRb == 0) || (XRc == 0))) {
- /* one of operands zero register -> just set destination to all 0s */
- tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
- } else if (unlikely(XRb == XRc)) {
- /* both operands same -> just set destination to one of them */
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
- } else {
- /* the most general case */
- tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
- }
-}
-
-/*
- * S32OR XRa, XRb, XRc
- * Update XRa with the result of logical bitwise 'or' operation
- * applied to the content of XRb and XRc.
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- */
-static void gen_mxu_S32OR(DisasContext *ctx)
-{
- uint32_t pad, XRc, XRb, XRa;
-
- pad = extract32(ctx->opcode, 21, 5);
- XRc = extract32(ctx->opcode, 14, 4);
- XRb = extract32(ctx->opcode, 10, 4);
- XRa = extract32(ctx->opcode, 6, 4);
-
- if (unlikely(pad != 0)) {
- /* opcode padding incorrect -> do nothing */
- } else if (unlikely(XRa == 0)) {
- /* destination is zero register -> do nothing */
- } else if (unlikely((XRb == 0) && (XRc == 0))) {
- /* both operands zero registers -> just set destination to all 0s */
- tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
- } else if (unlikely(XRb == 0)) {
- /* XRb zero register -> just set destination to the content of XRc */
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
- } else if (unlikely(XRc == 0)) {
- /* XRc zero register -> just set destination to the content of XRb */
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
- } else if (unlikely(XRb == XRc)) {
- /* both operands same -> just set destination to one of them */
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
- } else {
- /* the most general case */
- tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
- }
-}
-
-/*
- * S32XOR XRa, XRb, XRc
- * Update XRa with the result of logical bitwise 'xor' operation
- * applied to the content of XRb and XRc.
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- */
-static void gen_mxu_S32XOR(DisasContext *ctx)
-{
- uint32_t pad, XRc, XRb, XRa;
-
- pad = extract32(ctx->opcode, 21, 5);
- XRc = extract32(ctx->opcode, 14, 4);
- XRb = extract32(ctx->opcode, 10, 4);
- XRa = extract32(ctx->opcode, 6, 4);
-
- if (unlikely(pad != 0)) {
- /* opcode padding incorrect -> do nothing */
- } else if (unlikely(XRa == 0)) {
- /* destination is zero register -> do nothing */
- } else if (unlikely((XRb == 0) && (XRc == 0))) {
- /* both operands zero registers -> just set destination to all 0s */
- tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
- } else if (unlikely(XRb == 0)) {
- /* XRb zero register -> just set destination to the content of XRc */
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
- } else if (unlikely(XRc == 0)) {
- /* XRc zero register -> just set destination to the content of XRb */
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
- } else if (unlikely(XRb == XRc)) {
- /* both operands same -> just set destination to all 0s */
- tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
- } else {
- /* the most general case */
- tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
- }
-}
-
-
-/*
- * MXU instruction category max/min
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * S32MAX D16MAX Q8MAX
- * S32MIN D16MIN Q8MIN
- */
-
-/*
- * S32MAX XRa, XRb, XRc
- * Update XRa with the maximum of signed 32-bit integers contained
- * in XRb and XRc.
- *
- * S32MIN XRa, XRb, XRc
- * Update XRa with the minimum of signed 32-bit integers contained
- * in XRb and XRc.
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- */
-static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
-{
- uint32_t pad, opc, XRc, XRb, XRa;
-
- pad = extract32(ctx->opcode, 21, 5);
- opc = extract32(ctx->opcode, 18, 3);
- XRc = extract32(ctx->opcode, 14, 4);
- XRb = extract32(ctx->opcode, 10, 4);
- XRa = extract32(ctx->opcode, 6, 4);
-
- if (unlikely(pad != 0)) {
- /* opcode padding incorrect -> do nothing */
- } else if (unlikely(XRa == 0)) {
- /* destination is zero register -> do nothing */
- } else if (unlikely((XRb == 0) && (XRc == 0))) {
- /* both operands zero registers -> just set destination to zero */
- tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
- } else if (unlikely((XRb == 0) || (XRc == 0))) {
- /* exactly one operand is zero register - find which one is not...*/
- uint32_t XRx = XRb ? XRb : XRc;
- /* ...and do max/min operation with one operand 0 */
- if (opc == OPC_MXU_S32MAX) {
- tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
- } else {
- tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
- }
- } else if (unlikely(XRb == XRc)) {
- /* both operands same -> just set destination to one of them */
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
- } else {
- /* the most general case */
- if (opc == OPC_MXU_S32MAX) {
- tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
- mxu_gpr[XRc - 1]);
- } else {
- tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
- mxu_gpr[XRc - 1]);
- }
- }
-}
-
-/*
- * D16MAX
- * Update XRa with the 16-bit-wise maximums of signed integers
- * contained in XRb and XRc.
- *
- * D16MIN
- * Update XRa with the 16-bit-wise minimums of signed integers
- * contained in XRb and XRc.
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- */
-static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
-{
- uint32_t pad, opc, XRc, XRb, XRa;
-
- pad = extract32(ctx->opcode, 21, 5);
- opc = extract32(ctx->opcode, 18, 3);
- XRc = extract32(ctx->opcode, 14, 4);
- XRb = extract32(ctx->opcode, 10, 4);
- XRa = extract32(ctx->opcode, 6, 4);
-
- if (unlikely(pad != 0)) {
- /* opcode padding incorrect -> do nothing */
- } else if (unlikely(XRc == 0)) {
- /* destination is zero register -> do nothing */
- } else if (unlikely((XRb == 0) && (XRa == 0))) {
- /* both operands zero registers -> just set destination to zero */
- tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
- } else if (unlikely((XRb == 0) || (XRa == 0))) {
- /* exactly one operand is zero register - find which one is not...*/
- uint32_t XRx = XRb ? XRb : XRc;
- /* ...and do half-word-wise max/min with one operand 0 */
- TCGv_i32 t0 = tcg_temp_new();
- TCGv_i32 t1 = tcg_const_i32(0);
-
- /* the left half-word first */
- tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
- if (opc == OPC_MXU_D16MAX) {
- tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
- } else {
- tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
- }
-
- /* the right half-word */
- tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
- /* move half-words to the leftmost position */
- tcg_gen_shli_i32(t0, t0, 16);
- /* t0 will be max/min of t0 and t1 */
- if (opc == OPC_MXU_D16MAX) {
- tcg_gen_smax_i32(t0, t0, t1);
- } else {
- tcg_gen_smin_i32(t0, t0, t1);
- }
- /* return resulting half-words to its original position */
- tcg_gen_shri_i32(t0, t0, 16);
- /* finally update the destination */
- tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
-
- tcg_temp_free(t1);
- tcg_temp_free(t0);
- } else if (unlikely(XRb == XRc)) {
- /* both operands same -> just set destination to one of them */
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
- } else {
- /* the most general case */
- TCGv_i32 t0 = tcg_temp_new();
- TCGv_i32 t1 = tcg_temp_new();
-
- /* the left half-word first */
- tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
- tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
- if (opc == OPC_MXU_D16MAX) {
- tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
- } else {
- tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
- }
-
- /* the right half-word */
- tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
- tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
- /* move half-words to the leftmost position */
- tcg_gen_shli_i32(t0, t0, 16);
- tcg_gen_shli_i32(t1, t1, 16);
- /* t0 will be max/min of t0 and t1 */
- if (opc == OPC_MXU_D16MAX) {
- tcg_gen_smax_i32(t0, t0, t1);
- } else {
- tcg_gen_smin_i32(t0, t0, t1);
- }
- /* return resulting half-words to its original position */
- tcg_gen_shri_i32(t0, t0, 16);
- /* finally update the destination */
- tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
-
- tcg_temp_free(t1);
- tcg_temp_free(t0);
- }
-}
-
-/*
- * Q8MAX
- * Update XRa with the 8-bit-wise maximums of signed integers
- * contained in XRb and XRc.
- *
- * Q8MIN
- * Update XRa with the 8-bit-wise minimums of signed integers
- * contained in XRb and XRc.
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- */
-static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
-{
- uint32_t pad, opc, XRc, XRb, XRa;
-
- pad = extract32(ctx->opcode, 21, 5);
- opc = extract32(ctx->opcode, 18, 3);
- XRc = extract32(ctx->opcode, 14, 4);
- XRb = extract32(ctx->opcode, 10, 4);
- XRa = extract32(ctx->opcode, 6, 4);
-
- if (unlikely(pad != 0)) {
- /* opcode padding incorrect -> do nothing */
- } else if (unlikely(XRa == 0)) {
- /* destination is zero register -> do nothing */
- } else if (unlikely((XRb == 0) && (XRc == 0))) {
- /* both operands zero registers -> just set destination to zero */
- tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
- } else if (unlikely((XRb == 0) || (XRc == 0))) {
- /* exactly one operand is zero register - make it be the first...*/
- uint32_t XRx = XRb ? XRb : XRc;
- /* ...and do byte-wise max/min with one operand 0 */
- TCGv_i32 t0 = tcg_temp_new();
- TCGv_i32 t1 = tcg_const_i32(0);
- int32_t i;
-
- /* the leftmost byte (byte 3) first */
- tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
- if (opc == OPC_MXU_Q8MAX) {
- tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
- } else {
- tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
- }
-
- /* bytes 2, 1, 0 */
- for (i = 2; i >= 0; i--) {
- /* extract the byte */
- tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
- /* move the byte to the leftmost position */
- tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
- /* t0 will be max/min of t0 and t1 */
- if (opc == OPC_MXU_Q8MAX) {
- tcg_gen_smax_i32(t0, t0, t1);
- } else {
- tcg_gen_smin_i32(t0, t0, t1);
- }
- /* return resulting byte to its original position */
- tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
- /* finally update the destination */
- tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
- }
-
- tcg_temp_free(t1);
- tcg_temp_free(t0);
- } else if (unlikely(XRb == XRc)) {
- /* both operands same -> just set destination to one of them */
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
- } else {
- /* the most general case */
- TCGv_i32 t0 = tcg_temp_new();
- TCGv_i32 t1 = tcg_temp_new();
- int32_t i;
-
- /* the leftmost bytes (bytes 3) first */
- tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
- tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
- if (opc == OPC_MXU_Q8MAX) {
- tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
- } else {
- tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
- }
-
- /* bytes 2, 1, 0 */
- for (i = 2; i >= 0; i--) {
- /* extract corresponding bytes */
- tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
- tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
- /* move the bytes to the leftmost position */
- tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
- tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
- /* t0 will be max/min of t0 and t1 */
- if (opc == OPC_MXU_Q8MAX) {
- tcg_gen_smax_i32(t0, t0, t1);
- } else {
- tcg_gen_smin_i32(t0, t0, t1);
- }
- /* return resulting byte to its original position */
- tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
- /* finally update the destination */
- tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
- }
-
- tcg_temp_free(t1);
- tcg_temp_free(t0);
- }
-}
-
-
-/*
- * MXU instruction category: align
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * S32ALN S32ALNI
- */
-
-/*
- * S32ALNI XRc, XRb, XRa, optn3
- * Arrange bytes from XRb and XRc according to one of five sets of
- * rules determined by optn3, and place the result in XRa.
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+-----+---+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
- * +-----------+-----+---+-----+-------+-------+-------+-----------+
- *
- */
-static void gen_mxu_S32ALNI(DisasContext *ctx)
-{
- uint32_t optn3, pad, XRc, XRb, XRa;
-
- optn3 = extract32(ctx->opcode, 23, 3);
- pad = extract32(ctx->opcode, 21, 2);
- XRc = extract32(ctx->opcode, 14, 4);
- XRb = extract32(ctx->opcode, 10, 4);
- XRa = extract32(ctx->opcode, 6, 4);
-
- if (unlikely(pad != 0)) {
- /* opcode padding incorrect -> do nothing */
- } else if (unlikely(XRa == 0)) {
- /* destination is zero register -> do nothing */
- } else if (unlikely((XRb == 0) && (XRc == 0))) {
- /* both operands zero registers -> just set destination to all 0s */
- tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
- } else if (unlikely(XRb == 0)) {
- /* XRb zero register -> just appropriatelly shift XRc into XRa */
- switch (optn3) {
- case MXU_OPTN3_PTN0:
- tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
- break;
- case MXU_OPTN3_PTN1:
- case MXU_OPTN3_PTN2:
- case MXU_OPTN3_PTN3:
- tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
- 8 * (4 - optn3));
- break;
- case MXU_OPTN3_PTN4:
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
- break;
- }
- } else if (unlikely(XRc == 0)) {
- /* XRc zero register -> just appropriatelly shift XRb into XRa */
- switch (optn3) {
- case MXU_OPTN3_PTN0:
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
- break;
- case MXU_OPTN3_PTN1:
- case MXU_OPTN3_PTN2:
- case MXU_OPTN3_PTN3:
- tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
- break;
- case MXU_OPTN3_PTN4:
- tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
- break;
- }
- } else if (unlikely(XRb == XRc)) {
- /* both operands same -> just rotation or moving from any of them */
- switch (optn3) {
- case MXU_OPTN3_PTN0:
- case MXU_OPTN3_PTN4:
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
- break;
- case MXU_OPTN3_PTN1:
- case MXU_OPTN3_PTN2:
- case MXU_OPTN3_PTN3:
- tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
- break;
- }
- } else {
- /* the most general case */
- switch (optn3) {
- case MXU_OPTN3_PTN0:
- {
- /* */
- /* XRb XRc */
- /* +---------------+ */
- /* | A B C D | E F G H */
- /* +-------+-------+ */
- /* | */
- /* XRa */
- /* */
-
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
- }
- break;
- case MXU_OPTN3_PTN1:
- {
- /* */
- /* XRb XRc */
- /* +-------------------+ */
- /* A | B C D E | F G H */
- /* +---------+---------+ */
- /* | */
- /* XRa */
- /* */
-
- TCGv_i32 t0 = tcg_temp_new();
- TCGv_i32 t1 = tcg_temp_new();
-
- tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
- tcg_gen_shli_i32(t0, t0, 8);
-
- tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
- tcg_gen_shri_i32(t1, t1, 24);
-
- tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
-
- tcg_temp_free(t1);
- tcg_temp_free(t0);
- }
- break;
- case MXU_OPTN3_PTN2:
- {
- /* */
- /* XRb XRc */
- /* +-------------------+ */
- /* A B | C D E F | G H */
- /* +---------+---------+ */
- /* | */
- /* XRa */
- /* */
-
- TCGv_i32 t0 = tcg_temp_new();
- TCGv_i32 t1 = tcg_temp_new();
-
- tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
- tcg_gen_shli_i32(t0, t0, 16);
-
- tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
- tcg_gen_shri_i32(t1, t1, 16);
-
- tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
-
- tcg_temp_free(t1);
- tcg_temp_free(t0);
- }
- break;
- case MXU_OPTN3_PTN3:
- {
- /* */
- /* XRb XRc */
- /* +-------------------+ */
- /* A B C | D E F G | H */
- /* +---------+---------+ */
- /* | */
- /* XRa */
- /* */
-
- TCGv_i32 t0 = tcg_temp_new();
- TCGv_i32 t1 = tcg_temp_new();
-
- tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
- tcg_gen_shli_i32(t0, t0, 24);
-
- tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
- tcg_gen_shri_i32(t1, t1, 8);
-
- tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
-
- tcg_temp_free(t1);
- tcg_temp_free(t0);
- }
- break;
- case MXU_OPTN3_PTN4:
- {
- /* */
- /* XRb XRc */
- /* +---------------+ */
- /* A B C D | E F G H | */
- /* +-------+-------+ */
- /* | */
- /* XRa */
- /* */
-
- tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
- }
- break;
- }
- }
-}
-
-
-/*
- * Decoding engine for MXU
- * =======================
- */
-
-/*
- *
- * Decode MXU pool00
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 18, 3);
-
- switch (opcode) {
- case OPC_MXU_S32MAX:
- case OPC_MXU_S32MIN:
- gen_mxu_S32MAX_S32MIN(ctx);
- break;
- case OPC_MXU_D16MAX:
- case OPC_MXU_D16MIN:
- gen_mxu_D16MAX_D16MIN(ctx);
- break;
- case OPC_MXU_Q8MAX:
- case OPC_MXU_Q8MIN:
- gen_mxu_Q8MAX_Q8MIN(ctx);
- break;
- case OPC_MXU_Q8SLT:
- /* TODO: Implement emulation of Q8SLT instruction. */
- MIPS_INVAL("OPC_MXU_Q8SLT");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q8SLTU:
- /* TODO: Implement emulation of Q8SLTU instruction. */
- MIPS_INVAL("OPC_MXU_Q8SLTU");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool01
- *
- * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- *
- * Q8ADD:
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---+-----+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
- * +-----------+---+-----+-----+-------+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 18, 3);
-
- switch (opcode) {
- case OPC_MXU_S32SLT:
- /* TODO: Implement emulation of S32SLT instruction. */
- MIPS_INVAL("OPC_MXU_S32SLT");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D16SLT:
- /* TODO: Implement emulation of D16SLT instruction. */
- MIPS_INVAL("OPC_MXU_D16SLT");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D16AVG:
- /* TODO: Implement emulation of D16AVG instruction. */
- MIPS_INVAL("OPC_MXU_D16AVG");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D16AVGR:
- /* TODO: Implement emulation of D16AVGR instruction. */
- MIPS_INVAL("OPC_MXU_D16AVGR");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q8AVG:
- /* TODO: Implement emulation of Q8AVG instruction. */
- MIPS_INVAL("OPC_MXU_Q8AVG");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q8AVGR:
- /* TODO: Implement emulation of Q8AVGR instruction. */
- MIPS_INVAL("OPC_MXU_Q8AVGR");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q8ADD:
- /* TODO: Implement emulation of Q8ADD instruction. */
- MIPS_INVAL("OPC_MXU_Q8ADD");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool02
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 18, 3);
-
- switch (opcode) {
- case OPC_MXU_S32CPS:
- /* TODO: Implement emulation of S32CPS instruction. */
- MIPS_INVAL("OPC_MXU_S32CPS");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D16CPS:
- /* TODO: Implement emulation of D16CPS instruction. */
- MIPS_INVAL("OPC_MXU_D16CPS");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q8ABD:
- /* TODO: Implement emulation of Q8ABD instruction. */
- MIPS_INVAL("OPC_MXU_Q8ABD");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q16SAT:
- /* TODO: Implement emulation of Q16SAT instruction. */
- MIPS_INVAL("OPC_MXU_Q16SAT");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool03
- *
- * D16MULF:
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- *
- * D16MULE:
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 24, 2);
-
- switch (opcode) {
- case OPC_MXU_D16MULF:
- /* TODO: Implement emulation of D16MULF instruction. */
- MIPS_INVAL("OPC_MXU_D16MULF");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D16MULE:
- /* TODO: Implement emulation of D16MULE instruction. */
- MIPS_INVAL("OPC_MXU_D16MULE");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool04
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-+-------------------+-------+-----------+
- * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
- * +-----------+---------+-+-------------------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 20, 1);
-
- switch (opcode) {
- case OPC_MXU_S32LDD:
- case OPC_MXU_S32LDDR:
- gen_mxu_s32ldd_s32lddr(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool05
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-+-------------------+-------+-----------+
- * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
- * +-----------+---------+-+-------------------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 20, 1);
-
- switch (opcode) {
- case OPC_MXU_S32STD:
- /* TODO: Implement emulation of S32STD instruction. */
- MIPS_INVAL("OPC_MXU_S32STD");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32STDR:
- /* TODO: Implement emulation of S32STDR instruction. */
- MIPS_INVAL("OPC_MXU_S32STDR");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool06
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+---------+---+-------+-------+-----------+
- * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
- * +-----------+---------+---------+---+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 10, 4);
-
- switch (opcode) {
- case OPC_MXU_S32LDDV:
- /* TODO: Implement emulation of S32LDDV instruction. */
- MIPS_INVAL("OPC_MXU_S32LDDV");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32LDDVR:
- /* TODO: Implement emulation of S32LDDVR instruction. */
- MIPS_INVAL("OPC_MXU_S32LDDVR");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool07
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+---------+---+-------+-------+-----------+
- * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
- * +-----------+---------+---------+---+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 10, 4);
-
- switch (opcode) {
- case OPC_MXU_S32STDV:
- /* TODO: Implement emulation of S32TDV instruction. */
- MIPS_INVAL("OPC_MXU_S32TDV");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32STDVR:
- /* TODO: Implement emulation of S32TDVR instruction. */
- MIPS_INVAL("OPC_MXU_S32TDVR");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool08
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-+-------------------+-------+-----------+
- * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
- * +-----------+---------+-+-------------------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 20, 1);
-
- switch (opcode) {
- case OPC_MXU_S32LDI:
- /* TODO: Implement emulation of S32LDI instruction. */
- MIPS_INVAL("OPC_MXU_S32LDI");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32LDIR:
- /* TODO: Implement emulation of S32LDIR instruction. */
- MIPS_INVAL("OPC_MXU_S32LDIR");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool09
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-+-------------------+-------+-----------+
- * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
- * +-----------+---------+-+-------------------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 5, 0);
-
- switch (opcode) {
- case OPC_MXU_S32SDI:
- /* TODO: Implement emulation of S32SDI instruction. */
- MIPS_INVAL("OPC_MXU_S32SDI");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32SDIR:
- /* TODO: Implement emulation of S32SDIR instruction. */
- MIPS_INVAL("OPC_MXU_S32SDIR");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool10
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+---------+---+-------+-------+-----------+
- * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
- * +-----------+---------+---------+---+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 5, 0);
-
- switch (opcode) {
- case OPC_MXU_S32LDIV:
- /* TODO: Implement emulation of S32LDIV instruction. */
- MIPS_INVAL("OPC_MXU_S32LDIV");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32LDIVR:
- /* TODO: Implement emulation of S32LDIVR instruction. */
- MIPS_INVAL("OPC_MXU_S32LDIVR");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool11
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+---------+---+-------+-------+-----------+
- * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
- * +-----------+---------+---------+---+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 10, 4);
-
- switch (opcode) {
- case OPC_MXU_S32SDIV:
- /* TODO: Implement emulation of S32SDIV instruction. */
- MIPS_INVAL("OPC_MXU_S32SDIV");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32SDIVR:
- /* TODO: Implement emulation of S32SDIVR instruction. */
- MIPS_INVAL("OPC_MXU_S32SDIVR");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool12
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 22, 2);
-
- switch (opcode) {
- case OPC_MXU_D32ACC:
- /* TODO: Implement emulation of D32ACC instruction. */
- MIPS_INVAL("OPC_MXU_D32ACC");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D32ACCM:
- /* TODO: Implement emulation of D32ACCM instruction. */
- MIPS_INVAL("OPC_MXU_D32ACCM");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D32ASUM:
- /* TODO: Implement emulation of D32ASUM instruction. */
- MIPS_INVAL("OPC_MXU_D32ASUM");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool13
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 22, 2);
-
- switch (opcode) {
- case OPC_MXU_Q16ACC:
- /* TODO: Implement emulation of Q16ACC instruction. */
- MIPS_INVAL("OPC_MXU_Q16ACC");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q16ACCM:
- /* TODO: Implement emulation of Q16ACCM instruction. */
- MIPS_INVAL("OPC_MXU_Q16ACCM");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q16ASUM:
- /* TODO: Implement emulation of Q16ASUM instruction. */
- MIPS_INVAL("OPC_MXU_Q16ASUM");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool14
- *
- * Q8ADDE, Q8ACCE:
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- *
- * D8SUM, D8SUMC:
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 22, 2);
-
- switch (opcode) {
- case OPC_MXU_Q8ADDE:
- /* TODO: Implement emulation of Q8ADDE instruction. */
- MIPS_INVAL("OPC_MXU_Q8ADDE");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D8SUM:
- /* TODO: Implement emulation of D8SUM instruction. */
- MIPS_INVAL("OPC_MXU_D8SUM");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D8SUMC:
- /* TODO: Implement emulation of D8SUMC instruction. */
- MIPS_INVAL("OPC_MXU_D8SUMC");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool15
- *
- * S32MUL, S32MULU, S32EXTRV:
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+---------+---+-------+-------+-----------+
- * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
- * +-----------+---------+---------+---+-------+-------+-----------+
- *
- * S32EXTR:
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+---------+---+-------+-------+-----------+
- * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
- * +-----------+---------+---------+---+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 14, 2);
-
- switch (opcode) {
- case OPC_MXU_S32MUL:
- /* TODO: Implement emulation of S32MUL instruction. */
- MIPS_INVAL("OPC_MXU_S32MUL");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32MULU:
- /* TODO: Implement emulation of S32MULU instruction. */
- MIPS_INVAL("OPC_MXU_S32MULU");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32EXTR:
- /* TODO: Implement emulation of S32EXTR instruction. */
- MIPS_INVAL("OPC_MXU_S32EXTR");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32EXTRV:
- /* TODO: Implement emulation of S32EXTRV instruction. */
- MIPS_INVAL("OPC_MXU_S32EXTRV");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool16
- *
- * D32SARW:
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- *
- * S32ALN:
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- *
- * S32ALNI:
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+-----+---+-----+-------+-------+-------+-----------+
- * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
- * +-----------+-----+---+-----+-------+-------+-------+-----------+
- *
- * S32LUI:
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+-----+---+-----+-------+---------------+-----------+
- * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
- * +-----------+-----+---+-----+-------+---------------+-----------+
- *
- * S32NOR, S32AND, S32OR, S32XOR:
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 18, 3);
-
- switch (opcode) {
- case OPC_MXU_D32SARW:
- /* TODO: Implement emulation of D32SARW instruction. */
- MIPS_INVAL("OPC_MXU_D32SARW");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32ALN:
- /* TODO: Implement emulation of S32ALN instruction. */
- MIPS_INVAL("OPC_MXU_S32ALN");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32ALNI:
- gen_mxu_S32ALNI(ctx);
- break;
- case OPC_MXU_S32LUI:
- /* TODO: Implement emulation of S32LUI instruction. */
- MIPS_INVAL("OPC_MXU_S32LUI");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32NOR:
- gen_mxu_S32NOR(ctx);
- break;
- case OPC_MXU_S32AND:
- gen_mxu_S32AND(ctx);
- break;
- case OPC_MXU_S32OR:
- gen_mxu_S32OR(ctx);
- break;
- case OPC_MXU_S32XOR:
- gen_mxu_S32XOR(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool17
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+---------+---+---------+-----+-----------+
- * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
- * +-----------+---------+---------+---+---------+-----+-----------+
- *
- */
-static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 6, 2);
-
- switch (opcode) {
- case OPC_MXU_LXW:
- /* TODO: Implement emulation of LXW instruction. */
- MIPS_INVAL("OPC_MXU_LXW");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_LXH:
- /* TODO: Implement emulation of LXH instruction. */
- MIPS_INVAL("OPC_MXU_LXH");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_LXHU:
- /* TODO: Implement emulation of LXHU instruction. */
- MIPS_INVAL("OPC_MXU_LXHU");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_LXB:
- /* TODO: Implement emulation of LXB instruction. */
- MIPS_INVAL("OPC_MXU_LXB");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_LXBU:
- /* TODO: Implement emulation of LXBU instruction. */
- MIPS_INVAL("OPC_MXU_LXBU");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-/*
- *
- * Decode MXU pool18
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 18, 3);
-
- switch (opcode) {
- case OPC_MXU_D32SLLV:
- /* TODO: Implement emulation of D32SLLV instruction. */
- MIPS_INVAL("OPC_MXU_D32SLLV");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D32SLRV:
- /* TODO: Implement emulation of D32SLRV instruction. */
- MIPS_INVAL("OPC_MXU_D32SLRV");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D32SARV:
- /* TODO: Implement emulation of D32SARV instruction. */
- MIPS_INVAL("OPC_MXU_D32SARV");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q16SLLV:
- /* TODO: Implement emulation of Q16SLLV instruction. */
- MIPS_INVAL("OPC_MXU_Q16SLLV");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q16SLRV:
- /* TODO: Implement emulation of Q16SLRV instruction. */
- MIPS_INVAL("OPC_MXU_Q16SLRV");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q16SARV:
- /* TODO: Implement emulation of Q16SARV instruction. */
- MIPS_INVAL("OPC_MXU_Q16SARV");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool19
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 22, 2);
-
- switch (opcode) {
- case OPC_MXU_Q8MUL:
- case OPC_MXU_Q8MULSU:
- gen_mxu_q8mul_q8mulsu(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool20
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------+-----+-------+-------+-------+-----------+
- * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
- * +-----------+---------+-----+-------+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 18, 3);
-
- switch (opcode) {
- case OPC_MXU_Q8MOVZ:
- /* TODO: Implement emulation of Q8MOVZ instruction. */
- MIPS_INVAL("OPC_MXU_Q8MOVZ");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q8MOVN:
- /* TODO: Implement emulation of Q8MOVN instruction. */
- MIPS_INVAL("OPC_MXU_Q8MOVN");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D16MOVZ:
- /* TODO: Implement emulation of D16MOVZ instruction. */
- MIPS_INVAL("OPC_MXU_D16MOVZ");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D16MOVN:
- /* TODO: Implement emulation of D16MOVN instruction. */
- MIPS_INVAL("OPC_MXU_D16MOVN");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32MOVZ:
- /* TODO: Implement emulation of S32MOVZ instruction. */
- MIPS_INVAL("OPC_MXU_S32MOVZ");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32MOVN:
- /* TODO: Implement emulation of S32MOVN instruction. */
- MIPS_INVAL("OPC_MXU_S32MOVN");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-/*
- *
- * Decode MXU pool21
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
- * +-----------+---+---+-------+-------+-------+-------+-----------+
- *
- */
-static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opcode = extract32(ctx->opcode, 22, 2);
-
- switch (opcode) {
- case OPC_MXU_Q8MAC:
- /* TODO: Implement emulation of Q8MAC instruction. */
- MIPS_INVAL("OPC_MXU_Q8MAC");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q8MACSU:
- /* TODO: Implement emulation of Q8MACSU instruction. */
- MIPS_INVAL("OPC_MXU_Q8MACSU");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-
-/*
- * Main MXU decoding function
- *
- * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
- * +-----------+---------------------------------------+-----------+
- * | SPECIAL2 | |x x x x x x|
- * +-----------+---------------------------------------+-----------+
- *
- */
-static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
-{
- /*
- * TODO: Investigate necessity of including handling of
- * CLZ, CLO, SDBB in this function, as they belong to
- * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
- */
- uint32_t opcode = extract32(ctx->opcode, 0, 6);
-
- if (opcode == OPC__MXU_MUL) {
- uint32_t rs, rt, rd, op1;
-
- rs = extract32(ctx->opcode, 21, 5);
- rt = extract32(ctx->opcode, 16, 5);
- rd = extract32(ctx->opcode, 11, 5);
- op1 = MASK_SPECIAL2(ctx->opcode);
-
- gen_arith(ctx, op1, rd, rs, rt);
-
- return;
- }
-
- if (opcode == OPC_MXU_S32M2I) {
- gen_mxu_s32m2i(ctx);
- return;
- }
-
- if (opcode == OPC_MXU_S32I2M) {
- gen_mxu_s32i2m(ctx);
- return;
- }
-
- {
- TCGv t_mxu_cr = tcg_temp_new();
- TCGLabel *l_exit = gen_new_label();
-
- gen_load_mxu_cr(t_mxu_cr);
- tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
- tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
-
- switch (opcode) {
- case OPC_MXU_S32MADD:
- /* TODO: Implement emulation of S32MADD instruction. */
- MIPS_INVAL("OPC_MXU_S32MADD");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32MADDU:
- /* TODO: Implement emulation of S32MADDU instruction. */
- MIPS_INVAL("OPC_MXU_S32MADDU");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU__POOL00:
- decode_opc_mxu__pool00(env, ctx);
- break;
- case OPC_MXU_S32MSUB:
- /* TODO: Implement emulation of S32MSUB instruction. */
- MIPS_INVAL("OPC_MXU_S32MSUB");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32MSUBU:
- /* TODO: Implement emulation of S32MSUBU instruction. */
- MIPS_INVAL("OPC_MXU_S32MSUBU");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU__POOL01:
- decode_opc_mxu__pool01(env, ctx);
- break;
- case OPC_MXU__POOL02:
- decode_opc_mxu__pool02(env, ctx);
- break;
- case OPC_MXU_D16MUL:
- gen_mxu_d16mul(ctx);
- break;
- case OPC_MXU__POOL03:
- decode_opc_mxu__pool03(env, ctx);
- break;
- case OPC_MXU_D16MAC:
- gen_mxu_d16mac(ctx);
- break;
- case OPC_MXU_D16MACF:
- /* TODO: Implement emulation of D16MACF instruction. */
- MIPS_INVAL("OPC_MXU_D16MACF");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D16MADL:
- /* TODO: Implement emulation of D16MADL instruction. */
- MIPS_INVAL("OPC_MXU_D16MADL");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S16MAD:
- /* TODO: Implement emulation of S16MAD instruction. */
- MIPS_INVAL("OPC_MXU_S16MAD");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q16ADD:
- /* TODO: Implement emulation of Q16ADD instruction. */
- MIPS_INVAL("OPC_MXU_Q16ADD");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D16MACE:
- /* TODO: Implement emulation of D16MACE instruction. */
- MIPS_INVAL("OPC_MXU_D16MACE");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU__POOL04:
- decode_opc_mxu__pool04(env, ctx);
- break;
- case OPC_MXU__POOL05:
- decode_opc_mxu__pool05(env, ctx);
- break;
- case OPC_MXU__POOL06:
- decode_opc_mxu__pool06(env, ctx);
- break;
- case OPC_MXU__POOL07:
- decode_opc_mxu__pool07(env, ctx);
- break;
- case OPC_MXU__POOL08:
- decode_opc_mxu__pool08(env, ctx);
- break;
- case OPC_MXU__POOL09:
- decode_opc_mxu__pool09(env, ctx);
- break;
- case OPC_MXU__POOL10:
- decode_opc_mxu__pool10(env, ctx);
- break;
- case OPC_MXU__POOL11:
- decode_opc_mxu__pool11(env, ctx);
- break;
- case OPC_MXU_D32ADD:
- /* TODO: Implement emulation of D32ADD instruction. */
- MIPS_INVAL("OPC_MXU_D32ADD");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU__POOL12:
- decode_opc_mxu__pool12(env, ctx);
- break;
- case OPC_MXU__POOL13:
- decode_opc_mxu__pool13(env, ctx);
- break;
- case OPC_MXU__POOL14:
- decode_opc_mxu__pool14(env, ctx);
- break;
- case OPC_MXU_Q8ACCE:
- /* TODO: Implement emulation of Q8ACCE instruction. */
- MIPS_INVAL("OPC_MXU_Q8ACCE");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S8LDD:
- gen_mxu_s8ldd(ctx);
- break;
- case OPC_MXU_S8STD:
- /* TODO: Implement emulation of S8STD instruction. */
- MIPS_INVAL("OPC_MXU_S8STD");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S8LDI:
- /* TODO: Implement emulation of S8LDI instruction. */
- MIPS_INVAL("OPC_MXU_S8LDI");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S8SDI:
- /* TODO: Implement emulation of S8SDI instruction. */
- MIPS_INVAL("OPC_MXU_S8SDI");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU__POOL15:
- decode_opc_mxu__pool15(env, ctx);
- break;
- case OPC_MXU__POOL16:
- decode_opc_mxu__pool16(env, ctx);
- break;
- case OPC_MXU__POOL17:
- decode_opc_mxu__pool17(env, ctx);
- break;
- case OPC_MXU_S16LDD:
- /* TODO: Implement emulation of S16LDD instruction. */
- MIPS_INVAL("OPC_MXU_S16LDD");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S16STD:
- /* TODO: Implement emulation of S16STD instruction. */
- MIPS_INVAL("OPC_MXU_S16STD");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S16LDI:
- /* TODO: Implement emulation of S16LDI instruction. */
- MIPS_INVAL("OPC_MXU_S16LDI");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S16SDI:
- /* TODO: Implement emulation of S16SDI instruction. */
- MIPS_INVAL("OPC_MXU_S16SDI");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D32SLL:
- /* TODO: Implement emulation of D32SLL instruction. */
- MIPS_INVAL("OPC_MXU_D32SLL");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D32SLR:
- /* TODO: Implement emulation of D32SLR instruction. */
- MIPS_INVAL("OPC_MXU_D32SLR");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D32SARL:
- /* TODO: Implement emulation of D32SARL instruction. */
- MIPS_INVAL("OPC_MXU_D32SARL");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_D32SAR:
- /* TODO: Implement emulation of D32SAR instruction. */
- MIPS_INVAL("OPC_MXU_D32SAR");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q16SLL:
- /* TODO: Implement emulation of Q16SLL instruction. */
- MIPS_INVAL("OPC_MXU_Q16SLL");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q16SLR:
- /* TODO: Implement emulation of Q16SLR instruction. */
- MIPS_INVAL("OPC_MXU_Q16SLR");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU__POOL18:
- decode_opc_mxu__pool18(env, ctx);
- break;
- case OPC_MXU_Q16SAR:
- /* TODO: Implement emulation of Q16SAR instruction. */
- MIPS_INVAL("OPC_MXU_Q16SAR");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU__POOL19:
- decode_opc_mxu__pool19(env, ctx);
- break;
- case OPC_MXU__POOL20:
- decode_opc_mxu__pool20(env, ctx);
- break;
- case OPC_MXU__POOL21:
- decode_opc_mxu__pool21(env, ctx);
- break;
- case OPC_MXU_Q16SCOP:
- /* TODO: Implement emulation of Q16SCOP instruction. */
- MIPS_INVAL("OPC_MXU_Q16SCOP");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q8MADL:
- /* TODO: Implement emulation of Q8MADL instruction. */
- MIPS_INVAL("OPC_MXU_Q8MADL");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_S32SFL:
- /* TODO: Implement emulation of S32SFL instruction. */
- MIPS_INVAL("OPC_MXU_S32SFL");
- gen_reserved_instruction(ctx);
- break;
- case OPC_MXU_Q8SAD:
- /* TODO: Implement emulation of Q8SAD instruction. */
- MIPS_INVAL("OPC_MXU_Q8SAD");
- gen_reserved_instruction(ctx);
- break;
- default:
- MIPS_INVAL("decode_opc_mxu");
- gen_reserved_instruction(ctx);
- }
-
- gen_set_label(l_exit);
- tcg_temp_free(t_mxu_cr);
- }
-}
-
-#endif /* !defined(TARGET_MIPS64) */
-
-
static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
{
int rs, rt, rd;
@@ -27851,146 +24402,6 @@ static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
#if defined(TARGET_MIPS64)
-static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opc = MASK_MMI0(ctx->opcode);
-
- switch (opc) {
- case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
- case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
- case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
- case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
- case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
- case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
- case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
- case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
- case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
- case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
- case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
- case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
- case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
- case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
- case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
- case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
- case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
- case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
- case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
- case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
- case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
- case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
- case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
- case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
- case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
- gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI0 */
- break;
- default:
- MIPS_INVAL("TX79 MMI class MMI0");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opc = MASK_MMI1(ctx->opcode);
-
- switch (opc) {
- case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
- case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
- case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
- case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
- case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
- case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
- case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
- case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
- case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
- case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
- case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
- case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
- case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
- case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
- case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
- case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
- case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
- case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
- gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI1 */
- break;
- default:
- MIPS_INVAL("TX79 MMI class MMI1");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opc = MASK_MMI2(ctx->opcode);
-
- switch (opc) {
- case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
- case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
- case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
- case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
- case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
- case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
- case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
- case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
- case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
- case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
- case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
- case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
- case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
- case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
- case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
- case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
- case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
- case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
- case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
- case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
- case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
- gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI2 */
- break;
- case MMI_OPC_2_PCPYLD:
- gen_mmi_pcpyld(ctx);
- break;
- default:
- MIPS_INVAL("TX79 MMI class MMI2");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
-static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
-{
- uint32_t opc = MASK_MMI3(ctx->opcode);
-
- switch (opc) {
- case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
- case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
- case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
- case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
- case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
- case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
- case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
- case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
- case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
- case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
- case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
- gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI3 */
- break;
- case MMI_OPC_3_PCPYH:
- gen_mmi_pcpyh(ctx);
- break;
- case MMI_OPC_3_PCPYUD:
- gen_mmi_pcpyud(ctx);
- break;
- default:
- MIPS_INVAL("TX79 MMI class MMI3");
- gen_reserved_instruction(ctx);
- break;
- }
-}
-
static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
{
uint32_t opc = MASK_MMI(ctx->opcode);
@@ -27999,18 +24410,6 @@ static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
int rd = extract32(ctx->opcode, 11, 5);
switch (opc) {
- case MMI_OPC_CLASS_MMI0:
- decode_mmi0(env, ctx);
- break;
- case MMI_OPC_CLASS_MMI1:
- decode_mmi1(env, ctx);
- break;
- case MMI_OPC_CLASS_MMI2:
- decode_mmi2(env, ctx);
- break;
- case MMI_OPC_CLASS_MMI3:
- decode_mmi3(env, ctx);
- break;
case MMI_OPC_MULT1:
case MMI_OPC_MULTU1:
case MMI_OPC_MADD:
@@ -28023,25 +24422,6 @@ static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
case MMI_OPC_DIVU1:
gen_div1_tx79(ctx, opc, rs, rt);
break;
- case MMI_OPC_MTLO1:
- case MMI_OPC_MTHI1:
- gen_HILO1_tx79(ctx, opc, rs);
- break;
- case MMI_OPC_MFLO1:
- case MMI_OPC_MFHI1:
- gen_HILO1_tx79(ctx, opc, rd);
- break;
- case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
- case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
- case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
- case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
- case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
- case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
- case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
- case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
- case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
- gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI */
- break;
default:
MIPS_INVAL("TX79 MMI class");
gen_reserved_instruction(ctx);
@@ -28276,13 +24656,18 @@ static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
#if defined(TARGET_MIPS64)
if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
decode_mmi(env, ctx);
-#else
- if (ctx->insn_flags & ASE_MXU) {
- decode_opc_mxu(env, ctx);
+ break;
+ }
#endif
- } else {
- decode_opc_special2_legacy(env, ctx);
+ if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
+ if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) {
+ gen_arith(ctx, OPC_MUL, rd, rs, rt);
+ } else {
+ decode_ase_mxu(ctx, ctx->opcode);
+ }
+ break;
}
+ decode_opc_special2_legacy(env, ctx);
break;
case OPC_SPECIAL3:
#if defined(TARGET_MIPS64)
@@ -28997,6 +25382,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
return;
}
+ if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
+ return;
+ }
if (decode_opc_legacy(env, ctx)) {
return;
@@ -29340,18 +25728,9 @@ void mips_tcg_init(void)
cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
"llval");
-#if !defined(TARGET_MIPS64)
- for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
- mxu_gpr[i] = tcg_global_mem_new(cpu_env,
- offsetof(CPUMIPSState,
- active_tc.mxu_gpr[i]),
- mxuregnames[i]);
+ if (TARGET_LONG_BITS == 32) {
+ mxu_translate_init();
}
-
- mxu_CR = tcg_global_mem_new(cpu_env,
- offsetof(CPUMIPSState, active_tc.mxu_cr),
- mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
-#endif /* !TARGET_MIPS64 */
}
void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
diff --git a/target/mips/translate.h b/target/mips/translate.h
index 468e29d757..2b3c7a69ec 100644
--- a/target/mips/translate.h
+++ b/target/mips/translate.h
@@ -148,6 +148,8 @@ void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1);
bool gen_lsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
bool gen_dlsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
+void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel);
+
extern TCGv cpu_gpr[32], cpu_PC;
#if defined(TARGET_MIPS64)
extern TCGv_i64 cpu_gpr_hi[32];
@@ -178,8 +180,16 @@ extern TCGv bcond;
/* MSA */
void msa_translate_init(void);
+/* MXU */
+void mxu_translate_init(void);
+bool decode_ase_mxu(DisasContext *ctx, uint32_t insn);
+
/* decodetree generated */
bool decode_isa_rel6(DisasContext *ctx, uint32_t insn);
bool decode_ase_msa(DisasContext *ctx, uint32_t insn);
+bool decode_ext_txx9(DisasContext *ctx, uint32_t insn);
+#if defined(TARGET_MIPS64)
+bool decode_ext_tx79(DisasContext *ctx, uint32_t insn);
+#endif
#endif
diff --git a/target/mips/tx79.decode b/target/mips/tx79.decode
new file mode 100644
index 0000000000..0f748b53a6
--- /dev/null
+++ b/target/mips/tx79.decode
@@ -0,0 +1,39 @@
+# Toshiba C790's instruction set
+#
+# Copyright (C) 2021 Philippe Mathieu-Daudé
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# Toshiba Appendix B C790-Specific Instruction Set Details
+
+###########################################################################
+# Named attribute sets. These are used to make nice(er) names
+# when creating helpers common to those for the individual
+# instruction patterns.
+
+&rtype rs rt rd sa
+
+###########################################################################
+# Named instruction formats. These are generally used to
+# reduce the amount of duplication between instruction patterns.
+
+@rs_rt_rd ...... rs:5 rt:5 rd:5 ..... ...... &rtype sa=0
+@rt_rd ...... ..... rt:5 rd:5 ..... ...... &rtype rs=0 sa=0
+@rs ...... rs:5 ..... .......... ...... &rtype rt=0 rd=0 sa=0
+@rd ...... .......... rd:5 ..... ...... &rtype rs=0 rt=0 sa=0
+
+###########################################################################
+
+MFHI1 011100 0000000000 ..... 00000 010000 @rd
+MTHI1 011100 ..... 0000000000 00000 010001 @rs
+MFLO1 011100 0000000000 ..... 00000 010010 @rd
+MTLO1 011100 ..... 0000000000 00000 010011 @rs
+
+# MMI2
+
+PCPYLD 011100 ..... ..... ..... 01110 001001 @rs_rt_rd
+
+# MMI3
+
+PCPYUD 011100 ..... ..... ..... 01110 101001 @rs_rt_rd
+PCPYH 011100 00000 ..... ..... 11011 101001 @rt_rd
diff --git a/target/mips/tx79_translate.c b/target/mips/tx79_translate.c
new file mode 100644
index 0000000000..ad83774b97
--- /dev/null
+++ b/target/mips/tx79_translate.c
@@ -0,0 +1,303 @@
+/*
+ * Toshiba TX79-specific instructions translation routines
+ *
+ * Copyright (c) 2018 Fredrik Noring
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "tcg/tcg-op.h"
+#include "exec/helper-gen.h"
+#include "translate.h"
+
+/* Include the auto-generated decoder. */
+#include "decode-tx79.c.inc"
+
+/*
+ * Overview of the TX79-specific instruction set
+ * =============================================
+ *
+ * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
+ * are only used by the specific quadword (128-bit) LQ/SQ load/store
+ * instructions and certain multimedia instructions (MMIs). These MMIs
+ * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
+ * or sixteen 8-bit paths.
+ *
+ * Reference:
+ *
+ * The Toshiba TX System RISC TX79 Core Architecture manual,
+ * https://wiki.qemu.org/File:C790.pdf
+ */
+
+bool decode_ext_tx79(DisasContext *ctx, uint32_t insn)
+{
+ if (TARGET_LONG_BITS == 64 && decode_tx79(ctx, insn)) {
+ return true;
+ }
+ return false;
+}
+
+/*
+ * Three-Operand Multiply and Multiply-Add (4 instructions)
+ * --------------------------------------------------------
+ * MADD [rd,] rs, rt Multiply/Add
+ * MADDU [rd,] rs, rt Multiply/Add Unsigned
+ * MULT [rd,] rs, rt Multiply (3-operand)
+ * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
+ */
+
+/*
+ * Multiply Instructions for Pipeline 1 (10 instructions)
+ * ------------------------------------------------------
+ * MULT1 [rd,] rs, rt Multiply Pipeline 1
+ * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
+ * DIV1 rs, rt Divide Pipeline 1
+ * DIVU1 rs, rt Divide Unsigned Pipeline 1
+ * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
+ * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
+ * MFHI1 rd Move From HI1 Register
+ * MFLO1 rd Move From LO1 Register
+ * MTHI1 rs Move To HI1 Register
+ * MTLO1 rs Move To LO1 Register
+ */
+
+static bool trans_MFHI1(DisasContext *ctx, arg_rtype *a)
+{
+ gen_store_gpr(cpu_HI[1], a->rd);
+
+ return true;
+}
+
+static bool trans_MFLO1(DisasContext *ctx, arg_rtype *a)
+{
+ gen_store_gpr(cpu_LO[1], a->rd);
+
+ return true;
+}
+
+static bool trans_MTHI1(DisasContext *ctx, arg_rtype *a)
+{
+ gen_load_gpr(cpu_HI[1], a->rs);
+
+ return true;
+}
+
+static bool trans_MTLO1(DisasContext *ctx, arg_rtype *a)
+{
+ gen_load_gpr(cpu_LO[1], a->rs);
+
+ return true;
+}
+
+/*
+ * Arithmetic (19 instructions)
+ * ----------------------------
+ * PADDB rd, rs, rt Parallel Add Byte
+ * PSUBB rd, rs, rt Parallel Subtract Byte
+ * PADDH rd, rs, rt Parallel Add Halfword
+ * PSUBH rd, rs, rt Parallel Subtract Halfword
+ * PADDW rd, rs, rt Parallel Add Word
+ * PSUBW rd, rs, rt Parallel Subtract Word
+ * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
+ * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
+ * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
+ * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
+ * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
+ * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
+ * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
+ * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
+ * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
+ * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
+ * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
+ * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
+ * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
+ */
+
+/*
+ * Min/Max (4 instructions)
+ * ------------------------
+ * PMAXH rd, rs, rt Parallel Maximum Halfword
+ * PMINH rd, rs, rt Parallel Minimum Halfword
+ * PMAXW rd, rs, rt Parallel Maximum Word
+ * PMINW rd, rs, rt Parallel Minimum Word
+ */
+
+/*
+ * Absolute (2 instructions)
+ * -------------------------
+ * PABSH rd, rt Parallel Absolute Halfword
+ * PABSW rd, rt Parallel Absolute Word
+ */
+
+/*
+ * Logical (4 instructions)
+ * ------------------------
+ * PAND rd, rs, rt Parallel AND
+ * POR rd, rs, rt Parallel OR
+ * PXOR rd, rs, rt Parallel XOR
+ * PNOR rd, rs, rt Parallel NOR
+ */
+
+/*
+ * Shift (9 instructions)
+ * ----------------------
+ * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
+ * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
+ * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
+ * PSLLW rd, rt, sa Parallel Shift Left Logical Word
+ * PSRLW rd, rt, sa Parallel Shift Right Logical Word
+ * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
+ * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
+ * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
+ * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
+ */
+
+/*
+ * Compare (6 instructions)
+ * ------------------------
+ * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
+ * PCEQB rd, rs, rt Parallel Compare for Equal Byte
+ * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
+ * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
+ * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
+ * PCEQW rd, rs, rt Parallel Compare for Equal Word
+ */
+
+/*
+ * LZC (1 instruction)
+ * -------------------
+ * PLZCW rd, rs Parallel Leading Zero or One Count Word
+ */
+
+/*
+ * Quadword Load and Store (2 instructions)
+ * ----------------------------------------
+ * LQ rt, offset(base) Load Quadword
+ * SQ rt, offset(base) Store Quadword
+ */
+
+/*
+ * Multiply and Divide (19 instructions)
+ * -------------------------------------
+ * PMULTW rd, rs, rt Parallel Multiply Word
+ * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
+ * PDIVW rs, rt Parallel Divide Word
+ * PDIVUW rs, rt Parallel Divide Unsigned Word
+ * PMADDW rd, rs, rt Parallel Multiply-Add Word
+ * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
+ * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
+ * PMULTH rd, rs, rt Parallel Multiply Halfword
+ * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
+ * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
+ * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
+ * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
+ * PDIVBW rs, rt Parallel Divide Broadcast Word
+ * PMFHI rd Parallel Move From HI Register
+ * PMFLO rd Parallel Move From LO Register
+ * PMTHI rs Parallel Move To HI Register
+ * PMTLO rs Parallel Move To LO Register
+ * PMFHL rd Parallel Move From HI/LO Register
+ * PMTHL rs Parallel Move To HI/LO Register
+ */
+
+/*
+ * Pack/Extend (11 instructions)
+ * -----------------------------
+ * PPAC5 rd, rt Parallel Pack to 5 bits
+ * PPACB rd, rs, rt Parallel Pack to Byte
+ * PPACH rd, rs, rt Parallel Pack to Halfword
+ * PPACW rd, rs, rt Parallel Pack to Word
+ * PEXT5 rd, rt Parallel Extend Upper from 5 bits
+ * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
+ * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
+ * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
+ * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
+ * PEXTUW rd, rs, rt Parallel Extend Upper from Word
+ * PEXTLW rd, rs, rt Parallel Extend Lower from Word
+ */
+
+/*
+ * Others (16 instructions)
+ * ------------------------
+ * PCPYH rd, rt Parallel Copy Halfword
+ * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
+ * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
+ * PREVH rd, rt Parallel Reverse Halfword
+ * PINTH rd, rs, rt Parallel Interleave Halfword
+ * PINTEH rd, rs, rt Parallel Interleave Even Halfword
+ * PEXEH rd, rt Parallel Exchange Even Halfword
+ * PEXCH rd, rt Parallel Exchange Center Halfword
+ * PEXEW rd, rt Parallel Exchange Even Word
+ * PEXCW rd, rt Parallel Exchange Center Word
+ * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
+ * MFSA rd Move from Shift Amount Register
+ * MTSA rs Move to Shift Amount Register
+ * MTSAB rs, immediate Move Byte Count to Shift Amount Register
+ * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
+ * PROT3W rd, rt Parallel Rotate 3 Words
+ */
+
+/* Parallel Copy Halfword */
+static bool trans_PCPYH(DisasContext *s, arg_rtype *a)
+{
+ if (a->rd == 0) {
+ /* nop */
+ return true;
+ }
+
+ if (a->rt == 0) {
+ tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
+ tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
+ return true;
+ }
+
+ tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rt], cpu_gpr[a->rt], 16, 16);
+ tcg_gen_deposit_i64(cpu_gpr[a->rd], cpu_gpr[a->rd], cpu_gpr[a->rd], 32, 32);
+ tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt], cpu_gpr_hi[a->rt], 16, 16);
+ tcg_gen_deposit_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rd], 32, 32);
+
+ return true;
+}
+
+/* Parallel Copy Lower Doubleword */
+static bool trans_PCPYLD(DisasContext *s, arg_rtype *a)
+{
+ if (a->rd == 0) {
+ /* nop */
+ return true;
+ }
+
+ if (a->rs == 0) {
+ tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
+ } else {
+ tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr[a->rs]);
+ }
+
+ if (a->rt == 0) {
+ tcg_gen_movi_i64(cpu_gpr[a->rd], 0);
+ } else if (a->rd != a->rt) {
+ tcg_gen_mov_i64(cpu_gpr[a->rd], cpu_gpr[a->rt]);
+ }
+
+ return true;
+}
+
+/* Parallel Copy Upper Doubleword */
+static bool trans_PCPYUD(DisasContext *s, arg_rtype *a)
+{
+ if (a->rd == 0) {
+ /* nop */
+ return true;
+ }
+
+ gen_load_gpr_hi(cpu_gpr[a->rd], a->rs);
+
+ if (a->rt == 0) {
+ tcg_gen_movi_i64(cpu_gpr_hi[a->rd], 0);
+ } else if (a->rd != a->rt) {
+ tcg_gen_mov_i64(cpu_gpr_hi[a->rd], cpu_gpr_hi[a->rt]);
+ }
+
+ return true;
+}
diff --git a/target/mips/txx9_translate.c b/target/mips/txx9_translate.c
new file mode 100644
index 0000000000..8a2c0b766b
--- /dev/null
+++ b/target/mips/txx9_translate.c
@@ -0,0 +1,20 @@
+/*
+ * Toshiba TXx9 instructions translation routines
+ *
+ * Copyright (c) 2021 Philippe Mathieu-Daudé
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "translate.h"
+
+bool decode_ext_txx9(DisasContext *ctx, uint32_t insn)
+{
+#if defined(TARGET_MIPS64)
+ if (decode_ext_tx79(ctx, insn)) {
+ return true;
+ }
+#endif
+ return false;
+}