diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/arm/kvm.c | 4 | ||||
-rw-r--r-- | target/arm/kvm_arm.h | 6 | ||||
-rw-r--r-- | target/arm/sve_helper.c | 107 | ||||
-rw-r--r-- | target/arm/translate-sve.c | 26 | ||||
-rw-r--r-- | target/mips/meson.build | 18 | ||||
-rw-r--r-- | target/mips/mxu_translate.c | 1609 | ||||
-rw-r--r-- | target/mips/translate.c | 3663 | ||||
-rw-r--r-- | target/mips/translate.h | 10 | ||||
-rw-r--r-- | target/mips/tx79.decode | 39 | ||||
-rw-r--r-- | target/mips/tx79_translate.c | 303 | ||||
-rw-r--r-- | target/mips/txx9_translate.c | 20 |
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; +} |