aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-12-22 13:15:52 +0000
committerPeter Maydell <peter.maydell@linaro.org>2014-12-22 13:15:52 +0000
commit7db96d6cf877d4bb8132462ec7dd19055ff968eb (patch)
tree0321904ded033d9d754d4b3c2c45d05ad924ed77
parentc95f3901b4ead79f3fe2c641fda7d2c70fc84c72 (diff)
parent9655b9328a566116c198c52792775a0641d56915 (diff)
Merge remote-tracking branch 'remotes/bkoppelmann/tags/pull-tricore-20141221' into staging
TriCore RR, RR1 insn added and several bug fixes # gpg: Signature made Sun 21 Dec 2014 18:39:11 GMT using RSA key ID 6B69CA14 # gpg: Good signature from "Bastian Koppelmann <kbastian@mail.uni-paderborn.de>" * remotes/bkoppelmann/tags/pull-tricore-20141221: target-tricore: Add instructions of RR1 opcode format, that have 0xb3 as first opcode target-tricore: Fix MFCR/MTCR insn and B format offset. target-tricore: Add missing 1.6 insn of BOL opcode format target-tricore: Add instructions of RR opcode format, that have 0x4b as the first opcode target-tricore: Add instructions of RR opcode format, that have 0x1 as the first opcode target-tricore: Add instructions of RR opcode format, that have 0xf as the first opcode target-tricore: Add instructions of RR opcode format, that have 0xb as the first opcode target-tricore: Change SSOV/SUOV makro name to SSOV32/SUOV32 target-tricore: Fix mask handling JNZ.T being 7 bit long target-tricore: pretty-print register dump and show more status registers target-tricore: add missing 64-bit MOV in RLC format target-tricore: typo in BOL format target-tricore: fix offset masking in BOL format Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--target-tricore/helper.h59
-rw-r--r--target-tricore/op_helper.c1086
-rw-r--r--target-tricore/translate.c1034
-rw-r--r--target-tricore/tricore-opcodes.h19
4 files changed, 2104 insertions, 94 deletions
diff --git a/target-tricore/helper.h b/target-tricore/helper.h
index 6c07bd7f2..068dc7b42 100644
--- a/target-tricore/helper.h
+++ b/target-tricore/helper.h
@@ -18,8 +18,12 @@
/* Arithmetic */
DEF_HELPER_3(add_ssov, i32, env, i32, i32)
DEF_HELPER_3(add_suov, i32, env, i32, i32)
+DEF_HELPER_3(add_h_ssov, i32, env, i32, i32)
+DEF_HELPER_3(add_h_suov, i32, env, i32, i32)
DEF_HELPER_3(sub_ssov, i32, env, i32, i32)
DEF_HELPER_3(sub_suov, i32, env, i32, i32)
+DEF_HELPER_3(sub_h_ssov, i32, env, i32, i32)
+DEF_HELPER_3(sub_h_suov, i32, env, i32, i32)
DEF_HELPER_3(mul_ssov, i32, env, i32, i32)
DEF_HELPER_3(mul_suov, i32, env, i32, i32)
DEF_HELPER_3(sha_ssov, i32, env, i32, i32)
@@ -32,6 +36,61 @@ DEF_HELPER_4(msub32_ssov, i32, env, i32, i32, i32)
DEF_HELPER_4(msub32_suov, i32, env, i32, i32, i32)
DEF_HELPER_4(msub64_ssov, i64, env, i32, i64, i32)
DEF_HELPER_4(msub64_suov, i64, env, i32, i64, i32)
+DEF_HELPER_3(absdif_h_ssov, i32, env, i32, i32)
+DEF_HELPER_2(abs_ssov, i32, env, i32)
+DEF_HELPER_2(abs_h_ssov, i32, env, i32)
+/* hword/byte arithmetic */
+DEF_HELPER_2(abs_b, i32, env, i32)
+DEF_HELPER_2(abs_h, i32, env, i32)
+DEF_HELPER_3(absdif_b, i32, env, i32, i32)
+DEF_HELPER_3(absdif_h, i32, env, i32, i32)
+DEF_HELPER_3(add_b, i32, env, i32, i32)
+DEF_HELPER_3(add_h, i32, env, i32, i32)
+DEF_HELPER_3(sub_b, i32, env, i32, i32)
+DEF_HELPER_3(sub_h, i32, env, i32, i32)
+DEF_HELPER_FLAGS_2(eq_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(eq_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(eqany_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(eqany_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(lt_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(lt_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(lt_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(lt_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(max_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(max_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(max_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(max_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(min_b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(min_bu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(min_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(min_hu, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+/* count leading ... */
+DEF_HELPER_FLAGS_1(clo, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(clo_h, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(clz, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(clz_h, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(cls, TCG_CALL_NO_RWG_SE, i32, i32)
+DEF_HELPER_FLAGS_1(cls_h, TCG_CALL_NO_RWG_SE, i32, i32)
+/* sh */
+DEF_HELPER_FLAGS_2(sh, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(sh_h, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_3(sha, i32, env, i32, i32)
+DEF_HELPER_2(sha_h, i32, i32, i32)
+/* merge/split/parity */
+DEF_HELPER_FLAGS_2(bmerge, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_1(bsplit, TCG_CALL_NO_RWG_SE, i64, i32)
+DEF_HELPER_FLAGS_1(parity, TCG_CALL_NO_RWG_SE, i32, i32)
+/* float */
+DEF_HELPER_1(unpack, i64, i32)
+/* dvinit */
+DEF_HELPER_3(dvinit_b_13, i64, env, i32, i32)
+DEF_HELPER_3(dvinit_b_131, i64, env, i32, i32)
+DEF_HELPER_3(dvinit_h_13, i64, env, i32, i32)
+DEF_HELPER_3(dvinit_h_131, i64, env, i32, i32)
+/* mulh */
+DEF_HELPER_FLAGS_5(mul_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_5(mulm_h, TCG_CALL_NO_RWG_SE, i64, i32, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_5(mulr_h, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32, i32, i32)
/* CSA */
DEF_HELPER_2(call, void, env, i32)
DEF_HELPER_1(ret, void, env)
diff --git a/target-tricore/op_helper.c b/target-tricore/op_helper.c
index 4da76ff23..13e27291c 100644
--- a/target-tricore/op_helper.c
+++ b/target-tricore/op_helper.c
@@ -56,118 +56,211 @@ uint32_t helper_circ_update(uint32_t reg, uint32_t off)
return reg - index + new_index;
}
-#define SSOV(env, ret, arg, len) do { \
- int64_t max_pos = INT##len ##_MAX; \
- int64_t max_neg = INT##len ##_MIN; \
- if (arg > max_pos) { \
- env->PSW_USB_V = (1 << 31); \
- env->PSW_USB_SV = (1 << 31); \
- ret = (target_ulong)max_pos; \
- } else { \
- if (arg < max_neg) { \
- env->PSW_USB_V = (1 << 31); \
- env->PSW_USB_SV = (1 << 31); \
- ret = (target_ulong)max_neg; \
- } else { \
- env->PSW_USB_V = 0; \
- ret = (target_ulong)arg; \
- } \
- } \
- env->PSW_USB_AV = arg ^ arg * 2u; \
- env->PSW_USB_SAV |= env->PSW_USB_AV; \
-} while (0)
-
-#define SUOV(env, ret, arg, len) do { \
- int64_t max_pos = UINT##len ##_MAX; \
- if (arg > max_pos) { \
- env->PSW_USB_V = (1 << 31); \
- env->PSW_USB_SV = (1 << 31); \
- ret = (target_ulong)max_pos; \
- } else { \
- if (arg < 0) { \
- env->PSW_USB_V = (1 << 31); \
- env->PSW_USB_SV = (1 << 31); \
- ret = 0; \
- } else { \
- env->PSW_USB_V = 0; \
- ret = (target_ulong)arg; \
- } \
- } \
- env->PSW_USB_AV = arg ^ arg * 2u; \
- env->PSW_USB_SAV |= env->PSW_USB_AV; \
-} while (0)
+static uint32_t ssov32(CPUTriCoreState *env, int64_t arg)
+{
+ uint32_t ret;
+ int64_t max_pos = INT32_MAX;
+ int64_t max_neg = INT32_MIN;
+ if (arg > max_pos) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ ret = (target_ulong)max_pos;
+ } else {
+ if (arg < max_neg) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ ret = (target_ulong)max_neg;
+ } else {
+ env->PSW_USB_V = 0;
+ ret = (target_ulong)arg;
+ }
+ }
+ env->PSW_USB_AV = arg ^ arg * 2u;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+ return ret;
+}
+
+static uint32_t suov32(CPUTriCoreState *env, int64_t arg)
+{
+ uint32_t ret;
+ int64_t max_pos = UINT32_MAX;
+ if (arg > max_pos) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ ret = (target_ulong)max_pos;
+ } else {
+ if (arg < 0) {
+ env->PSW_USB_V = (1 << 31);
+ env->PSW_USB_SV = (1 << 31);
+ ret = 0;
+ } else {
+ env->PSW_USB_V = 0;
+ ret = (target_ulong)arg;
+ }
+ }
+ env->PSW_USB_AV = arg ^ arg * 2u;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+ return ret;
+}
+static uint32_t ssov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1)
+{
+ int32_t max_pos = INT16_MAX;
+ int32_t max_neg = INT16_MIN;
+ int32_t av0, av1;
+
+ env->PSW_USB_V = 0;
+ av0 = hw0 ^ hw0 * 2u;
+ if (hw0 > max_pos) {
+ env->PSW_USB_V = (1 << 31);
+ hw0 = max_pos;
+ } else if (hw0 < max_neg) {
+ env->PSW_USB_V = (1 << 31);
+ hw0 = max_neg;
+ }
+
+ av1 = hw1 ^ hw1 * 2u;
+ if (hw1 > max_pos) {
+ env->PSW_USB_V = (1 << 31);
+ hw1 = max_pos;
+ } else if (hw1 < max_neg) {
+ env->PSW_USB_V = (1 << 31);
+ hw1 = max_neg;
+ }
+
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = (av0 | av1) << 16;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+ return (hw0 & 0xffff) | (hw1 << 16);
+}
+
+static uint32_t suov16(CPUTriCoreState *env, int32_t hw0, int32_t hw1)
+{
+ int32_t max_pos = UINT16_MAX;
+ int32_t av0, av1;
+
+ env->PSW_USB_V = 0;
+ av0 = hw0 ^ hw0 * 2u;
+ if (hw0 > max_pos) {
+ env->PSW_USB_V = (1 << 31);
+ hw0 = max_pos;
+ } else if (hw0 < 0) {
+ env->PSW_USB_V = (1 << 31);
+ hw0 = 0;
+ }
+
+ av1 = hw1 ^ hw1 * 2u;
+ if (hw1 > max_pos) {
+ env->PSW_USB_V = (1 << 31);
+ hw1 = max_pos;
+ } else if (hw1 < 0) {
+ env->PSW_USB_V = (1 << 31);
+ hw1 = 0;
+ }
+
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = (av0 | av1) << 16;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+ return (hw0 & 0xffff) | (hw1 << 16);
+}
target_ulong helper_add_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t result = t1 + t2;
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
+}
+
+target_ulong helper_add_h_ssov(CPUTriCoreState *env, target_ulong r1,
+ target_ulong r2)
+{
+ int32_t ret_hw0, ret_hw1;
+
+ ret_hw0 = sextract32(r1, 0, 16) + sextract32(r2, 0, 16);
+ ret_hw1 = sextract32(r1, 16, 16) + sextract32(r2, 16, 16);
+ return ssov16(env, ret_hw0, ret_hw1);
}
target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = extract64(r1, 0, 32);
int64_t t2 = extract64(r2, 0, 32);
int64_t result = t1 + t2;
- SUOV(env, ret, result, 32);
- return ret;
+ return suov32(env, result);
+}
+
+target_ulong helper_add_h_suov(CPUTriCoreState *env, target_ulong r1,
+ target_ulong r2)
+{
+ int32_t ret_hw0, ret_hw1;
+
+ ret_hw0 = extract32(r1, 0, 16) + extract32(r2, 0, 16);
+ ret_hw1 = extract32(r1, 16, 16) + extract32(r2, 16, 16);
+ return suov16(env, ret_hw0, ret_hw1);
}
target_ulong helper_sub_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t result = t1 - t2;
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
+}
+
+target_ulong helper_sub_h_ssov(CPUTriCoreState *env, target_ulong r1,
+ target_ulong r2)
+{
+ int32_t ret_hw0, ret_hw1;
+
+ ret_hw0 = sextract32(r1, 0, 16) - sextract32(r2, 0, 16);
+ ret_hw1 = sextract32(r1, 16, 16) - sextract32(r2, 16, 16);
+ return ssov16(env, ret_hw0, ret_hw1);
}
target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = extract64(r1, 0, 32);
int64_t t2 = extract64(r2, 0, 32);
int64_t result = t1 - t2;
- SUOV(env, ret, result, 32);
- return ret;
+ return suov32(env, result);
+}
+
+target_ulong helper_sub_h_suov(CPUTriCoreState *env, target_ulong r1,
+ target_ulong r2)
+{
+ int32_t ret_hw0, ret_hw1;
+
+ ret_hw0 = extract32(r1, 0, 16) - extract32(r2, 0, 16);
+ ret_hw1 = extract32(r1, 16, 16) - extract32(r2, 16, 16);
+ return suov16(env, ret_hw0, ret_hw1);
}
target_ulong helper_mul_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t result = t1 * t2;
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
}
target_ulong helper_mul_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = extract64(r1, 0, 32);
int64_t t2 = extract64(r2, 0, 32);
int64_t result = t1 * t2;
- SUOV(env, ret, result, 32);
- return ret;
+ return suov32(env, result);
}
target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int32_t t2 = sextract64(r2, 0, 6);
int64_t result;
@@ -178,14 +271,32 @@ target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1,
} else {
result = t1 >> -t2;
}
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
+}
+
+uint32_t helper_abs_ssov(CPUTriCoreState *env, target_ulong r1)
+{
+ target_ulong result;
+ result = ((int32_t)r1 >= 0) ? r1 : (0 - r1);
+ return ssov32(env, result);
+}
+
+uint32_t helper_abs_h_ssov(CPUTriCoreState *env, target_ulong r1)
+{
+ int32_t ret_h0, ret_h1;
+
+ ret_h0 = sextract32(r1, 0, 16);
+ ret_h0 = (ret_h0 >= 0) ? ret_h0 : (0 - ret_h0);
+
+ ret_h1 = sextract32(r1, 16, 16);
+ ret_h1 = (ret_h1 >= 0) ? ret_h1 : (0 - ret_h1);
+
+ return ssov16(env, ret_h0, ret_h1);
}
target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t result;
@@ -195,36 +306,56 @@ target_ulong helper_absdif_ssov(CPUTriCoreState *env, target_ulong r1,
} else {
result = t2 - t1;
}
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
+}
+
+uint32_t helper_absdif_h_ssov(CPUTriCoreState *env, target_ulong r1,
+ target_ulong r2)
+{
+ int32_t t1, t2;
+ int32_t ret_h0, ret_h1;
+
+ t1 = sextract32(r1, 0, 16);
+ t2 = sextract32(r2, 0, 16);
+ if (t1 > t2) {
+ ret_h0 = t1 - t2;
+ } else {
+ ret_h0 = t2 - t1;
+ }
+
+ t1 = sextract32(r1, 16, 16);
+ t2 = sextract32(r2, 16, 16);
+ if (t1 > t2) {
+ ret_h1 = t1 - t2;
+ } else {
+ ret_h1 = t2 - t1;
+ }
+
+ return ssov16(env, ret_h0, ret_h1);
}
target_ulong helper_madd32_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2, target_ulong r3)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t t3 = sextract64(r3, 0, 32);
int64_t result;
result = t2 + (t1 * t3);
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
}
target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2, target_ulong r3)
{
- target_ulong ret;
uint64_t t1 = extract64(r1, 0, 32);
uint64_t t2 = extract64(r2, 0, 32);
uint64_t t3 = extract64(r3, 0, 32);
int64_t result;
result = t2 + (t1 * t3);
- SUOV(env, ret, result, 32);
- return ret;
+ return suov32(env, result);
}
uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1,
@@ -286,29 +417,25 @@ uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong helper_msub32_ssov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2, target_ulong r3)
{
- target_ulong ret;
int64_t t1 = sextract64(r1, 0, 32);
int64_t t2 = sextract64(r2, 0, 32);
int64_t t3 = sextract64(r3, 0, 32);
int64_t result;
result = t2 - (t1 * t3);
- SSOV(env, ret, result, 32);
- return ret;
+ return ssov32(env, result);
}
target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1,
target_ulong r2, target_ulong r3)
{
- target_ulong ret;
int64_t t1 = extract64(r1, 0, 32);
int64_t t2 = extract64(r2, 0, 32);
int64_t t3 = extract64(r3, 0, 32);
int64_t result;
result = t2 - (t1 * t3);
- SUOV(env, ret, result, 32);
- return ret;
+ return suov32(env, result);
}
uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1,
@@ -366,6 +493,813 @@ uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1,
return ret;
}
+uint32_t helper_abs_b(CPUTriCoreState *env, target_ulong arg)
+{
+ int32_t b, i;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ int32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ b = sextract32(arg, i * 8, 8);
+ b = (b >= 0) ? b : (0 - b);
+ ovf |= (b > 0x7F) || (b < -0x80);
+ avf |= b ^ b * 2u;
+ ret |= (b & 0xff) << (i * 8);
+ }
+
+ env->PSW_USB_V = ovf << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 24;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_abs_h(CPUTriCoreState *env, target_ulong arg)
+{
+ int32_t h, i;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ int32_t ret = 0;
+
+ for (i = 0; i < 2; i++) {
+ h = sextract32(arg, i * 16, 16);
+ h = (h >= 0) ? h : (0 - h);
+ ovf |= (h > 0x7FFF) || (h < -0x8000);
+ avf |= h ^ h * 2u;
+ ret |= (h & 0xffff) << (i * 16);
+ }
+
+ env->PSW_USB_V = ovf << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 16;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_absdif_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t b, i;
+ int32_t extr_r2;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ int32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ extr_r2 = sextract32(r2, i * 8, 8);
+ b = sextract32(r1, i * 8, 8);
+ b = (b > extr_r2) ? (b - extr_r2) : (extr_r2 - b);
+ ovf |= (b > 0x7F) || (b < -0x80);
+ avf |= b ^ b * 2u;
+ ret |= (b & 0xff) << (i * 8);
+ }
+
+ env->PSW_USB_V = ovf << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 24;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+ return ret;
+}
+
+uint32_t helper_absdif_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t h, i;
+ int32_t extr_r2;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ int32_t ret = 0;
+
+ for (i = 0; i < 2; i++) {
+ extr_r2 = sextract32(r2, i * 16, 16);
+ h = sextract32(r1, i * 16, 16);
+ h = (h > extr_r2) ? (h - extr_r2) : (extr_r2 - h);
+ ovf |= (h > 0x7FFF) || (h < -0x8000);
+ avf |= h ^ h * 2u;
+ ret |= (h & 0xffff) << (i * 16);
+ }
+
+ env->PSW_USB_V = ovf << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 16;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_add_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t b, i;
+ int32_t extr_r1, extr_r2;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ uint32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ extr_r1 = sextract32(r1, i * 8, 8);
+ extr_r2 = sextract32(r2, i * 8, 8);
+
+ b = extr_r1 + extr_r2;
+ ovf |= ((b > 0x7f) || (b < -0x80));
+ avf |= b ^ b * 2u;
+ ret |= ((b & 0xff) << (i*8));
+ }
+
+ env->PSW_USB_V = (ovf << 31);
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 24;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_add_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t h, i;
+ int32_t extr_r1, extr_r2;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ int32_t ret = 0;
+
+ for (i = 0; i < 2; i++) {
+ extr_r1 = sextract32(r1, i * 16, 16);
+ extr_r2 = sextract32(r2, i * 16, 16);
+ h = extr_r1 + extr_r2;
+ ovf |= ((h > 0x7fff) || (h < -0x8000));
+ avf |= h ^ h * 2u;
+ ret |= (h & 0xffff) << (i * 16);
+ }
+
+ env->PSW_USB_V = (ovf << 31);
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = (avf << 16);
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_sub_b(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t b, i;
+ int32_t extr_r1, extr_r2;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ uint32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ extr_r1 = sextract32(r1, i * 8, 8);
+ extr_r2 = sextract32(r2, i * 8, 8);
+
+ b = extr_r1 - extr_r2;
+ ovf |= ((b > 0x7f) || (b < -0x80));
+ avf |= b ^ b * 2u;
+ ret |= ((b & 0xff) << (i*8));
+ }
+
+ env->PSW_USB_V = (ovf << 31);
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 24;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_sub_h(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t h, i;
+ int32_t extr_r1, extr_r2;
+ int32_t ovf = 0;
+ int32_t avf = 0;
+ int32_t ret = 0;
+
+ for (i = 0; i < 2; i++) {
+ extr_r1 = sextract32(r1, i * 16, 16);
+ extr_r2 = sextract32(r2, i * 16, 16);
+ h = extr_r1 - extr_r2;
+ ovf |= ((h > 0x7fff) || (h < -0x8000));
+ avf |= h ^ h * 2u;
+ ret |= (h & 0xffff) << (i * 16);
+ }
+
+ env->PSW_USB_V = (ovf << 31);
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = avf << 16;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_eq_b(target_ulong r1, target_ulong r2)
+{
+ int32_t ret;
+ int32_t i, msk;
+
+ ret = 0;
+ msk = 0xff;
+ for (i = 0; i < 4; i++) {
+ if ((r1 & msk) == (r2 & msk)) {
+ ret |= msk;
+ }
+ msk = msk << 8;
+ }
+
+ return ret;
+}
+
+uint32_t helper_eq_h(target_ulong r1, target_ulong r2)
+{
+ int32_t ret = 0;
+
+ if ((r1 & 0xffff) == (r2 & 0xffff)) {
+ ret = 0xffff;
+ }
+
+ if ((r1 & 0xffff0000) == (r2 & 0xffff0000)) {
+ ret |= 0xffff0000;
+ }
+
+ return ret;
+}
+
+uint32_t helper_eqany_b(target_ulong r1, target_ulong r2)
+{
+ int32_t i;
+ uint32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ ret |= (sextract32(r1, i * 8, 8) == sextract32(r2, i * 8, 8));
+ }
+
+ return ret;
+}
+
+uint32_t helper_eqany_h(target_ulong r1, target_ulong r2)
+{
+ uint32_t ret;
+
+ ret = (sextract32(r1, 0, 16) == sextract32(r2, 0, 16));
+ ret |= (sextract32(r1, 16, 16) == sextract32(r2, 16, 16));
+
+ return ret;
+}
+
+uint32_t helper_lt_b(target_ulong r1, target_ulong r2)
+{
+ int32_t i;
+ uint32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ if (sextract32(r1, i * 8, 8) < sextract32(r2, i * 8, 8)) {
+ ret |= (0xff << (i * 8));
+ }
+ }
+
+ return ret;
+}
+
+uint32_t helper_lt_bu(target_ulong r1, target_ulong r2)
+{
+ int32_t i;
+ uint32_t ret = 0;
+
+ for (i = 0; i < 4; i++) {
+ if (extract32(r1, i * 8, 8) < extract32(r2, i * 8, 8)) {
+ ret |= (0xff << (i * 8));
+ }
+ }
+
+ return ret;
+}
+
+uint32_t helper_lt_h(target_ulong r1, target_ulong r2)
+{
+ uint32_t ret = 0;
+
+ if (sextract32(r1, 0, 16) < sextract32(r2, 0, 16)) {
+ ret |= 0xffff;
+ }
+
+ if (sextract32(r1, 16, 16) < sextract32(r2, 16, 16)) {
+ ret |= 0xffff0000;
+ }
+
+ return ret;
+}
+
+uint32_t helper_lt_hu(target_ulong r1, target_ulong r2)
+{
+ uint32_t ret = 0;
+
+ if (extract32(r1, 0, 16) < extract32(r2, 0, 16)) {
+ ret |= 0xffff;
+ }
+
+ if (extract32(r1, 16, 16) < extract32(r2, 16, 16)) {
+ ret |= 0xffff0000;
+ }
+
+ return ret;
+}
+
+#define EXTREMA_H_B(name, op) \
+uint32_t helper_##name ##_b(target_ulong r1, target_ulong r2) \
+{ \
+ int32_t i, extr_r1, extr_r2; \
+ uint32_t ret = 0; \
+ \
+ for (i = 0; i < 4; i++) { \
+ extr_r1 = sextract32(r1, i * 8, 8); \
+ extr_r2 = sextract32(r2, i * 8, 8); \
+ extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
+ ret |= (extr_r1 & 0xff) << (i * 8); \
+ } \
+ return ret; \
+} \
+ \
+uint32_t helper_##name ##_bu(target_ulong r1, target_ulong r2)\
+{ \
+ int32_t i; \
+ uint32_t extr_r1, extr_r2; \
+ uint32_t ret = 0; \
+ \
+ for (i = 0; i < 4; i++) { \
+ extr_r1 = extract32(r1, i * 8, 8); \
+ extr_r2 = extract32(r2, i * 8, 8); \
+ extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
+ ret |= (extr_r1 & 0xff) << (i * 8); \
+ } \
+ return ret; \
+} \
+ \
+uint32_t helper_##name ##_h(target_ulong r1, target_ulong r2) \
+{ \
+ int32_t extr_r1, extr_r2; \
+ uint32_t ret = 0; \
+ \
+ extr_r1 = sextract32(r1, 0, 16); \
+ extr_r2 = sextract32(r2, 0, 16); \
+ ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
+ ret = ret & 0xffff; \
+ \
+ extr_r1 = sextract32(r1, 16, 16); \
+ extr_r2 = sextract32(r2, 16, 16); \
+ extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
+ ret |= extr_r1 << 16; \
+ \
+ return ret; \
+} \
+ \
+uint32_t helper_##name ##_hu(target_ulong r1, target_ulong r2)\
+{ \
+ uint32_t extr_r1, extr_r2; \
+ uint32_t ret = 0; \
+ \
+ extr_r1 = extract32(r1, 0, 16); \
+ extr_r2 = extract32(r2, 0, 16); \
+ ret = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
+ ret = ret & 0xffff; \
+ \
+ extr_r1 = extract32(r1, 16, 16); \
+ extr_r2 = extract32(r2, 16, 16); \
+ extr_r1 = (extr_r1 op extr_r2) ? extr_r1 : extr_r2; \
+ ret |= extr_r1 << (16); \
+ \
+ return ret; \
+} \
+
+EXTREMA_H_B(max, >)
+EXTREMA_H_B(min, <)
+
+#undef EXTREMA_H_B
+
+uint32_t helper_clo(target_ulong r1)
+{
+ return clo32(r1);
+}
+
+uint32_t helper_clo_h(target_ulong r1)
+{
+ uint32_t ret_hw0 = extract32(r1, 0, 16);
+ uint32_t ret_hw1 = extract32(r1, 16, 16);
+
+ ret_hw0 = clo32(ret_hw0 << 16);
+ ret_hw1 = clo32(ret_hw1 << 16);
+
+ if (ret_hw0 > 16) {
+ ret_hw0 = 16;
+ }
+ if (ret_hw1 > 16) {
+ ret_hw1 = 16;
+ }
+
+ return ret_hw0 | (ret_hw1 << 16);
+}
+
+uint32_t helper_clz(target_ulong r1)
+{
+ return clz32(r1);
+}
+
+uint32_t helper_clz_h(target_ulong r1)
+{
+ uint32_t ret_hw0 = extract32(r1, 0, 16);
+ uint32_t ret_hw1 = extract32(r1, 16, 16);
+
+ ret_hw0 = clz32(ret_hw0 << 16);
+ ret_hw1 = clz32(ret_hw1 << 16);
+
+ if (ret_hw0 > 16) {
+ ret_hw0 = 16;
+ }
+ if (ret_hw1 > 16) {
+ ret_hw1 = 16;
+ }
+
+ return ret_hw0 | (ret_hw1 << 16);
+}
+
+uint32_t helper_cls(target_ulong r1)
+{
+ return clrsb32(r1);
+}
+
+uint32_t helper_cls_h(target_ulong r1)
+{
+ uint32_t ret_hw0 = extract32(r1, 0, 16);
+ uint32_t ret_hw1 = extract32(r1, 16, 16);
+
+ ret_hw0 = clrsb32(ret_hw0 << 16);
+ ret_hw1 = clrsb32(ret_hw1 << 16);
+
+ if (ret_hw0 > 15) {
+ ret_hw0 = 15;
+ }
+ if (ret_hw1 > 15) {
+ ret_hw1 = 15;
+ }
+
+ return ret_hw0 | (ret_hw1 << 16);
+}
+
+uint32_t helper_sh(target_ulong r1, target_ulong r2)
+{
+ int32_t shift_count = sextract32(r2, 0, 6);
+
+ if (shift_count == -32) {
+ return 0;
+ } else if (shift_count < 0) {
+ return r1 >> -shift_count;
+ } else {
+ return r1 << shift_count;
+ }
+}
+
+uint32_t helper_sh_h(target_ulong r1, target_ulong r2)
+{
+ int32_t ret_hw0, ret_hw1;
+ int32_t shift_count;
+
+ shift_count = sextract32(r2, 0, 5);
+
+ if (shift_count == -16) {
+ return 0;
+ } else if (shift_count < 0) {
+ ret_hw0 = extract32(r1, 0, 16) >> -shift_count;
+ ret_hw1 = extract32(r1, 16, 16) >> -shift_count;
+ return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
+ } else {
+ ret_hw0 = extract32(r1, 0, 16) << shift_count;
+ ret_hw1 = extract32(r1, 16, 16) << shift_count;
+ return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
+ }
+}
+
+uint32_t helper_sha(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
+{
+ int32_t shift_count;
+ int64_t result, t1;
+ uint32_t ret;
+
+ shift_count = sextract32(r2, 0, 6);
+ t1 = sextract32(r1, 0, 32);
+
+ if (shift_count == 0) {
+ env->PSW_USB_C = env->PSW_USB_V = 0;
+ ret = r1;
+ } else if (shift_count == -32) {
+ env->PSW_USB_C = r1;
+ env->PSW_USB_V = 0;
+ ret = t1 >> 31;
+ } else if (shift_count > 0) {
+ result = t1 << shift_count;
+ /* calc carry */
+ env->PSW_USB_C = ((result & 0xffffffff00000000) != 0);
+ /* calc v */
+ env->PSW_USB_V = (((result > 0x7fffffffLL) ||
+ (result < -0x80000000LL)) << 31);
+ /* calc sv */
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ ret = (uint32_t)result;
+ } else {
+ env->PSW_USB_V = 0;
+ env->PSW_USB_C = (r1 & ((1 << -shift_count) - 1));
+ ret = t1 >> -shift_count;
+ }
+
+ env->PSW_USB_AV = ret ^ ret * 2u;
+ env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+ return ret;
+}
+
+uint32_t helper_sha_h(target_ulong r1, target_ulong r2)
+{
+ int32_t shift_count;
+ int32_t ret_hw0, ret_hw1;
+
+ shift_count = sextract32(r2, 0, 5);
+
+ if (shift_count == 0) {
+ return r1;
+ } else if (shift_count < 0) {
+ ret_hw0 = sextract32(r1, 0, 16) >> -shift_count;
+ ret_hw1 = sextract32(r1, 16, 16) >> -shift_count;
+ return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
+ } else {
+ ret_hw0 = sextract32(r1, 0, 16) << shift_count;
+ ret_hw1 = sextract32(r1, 16, 16) << shift_count;
+ return (ret_hw0 & 0xffff) | (ret_hw1 << 16);
+ }
+}
+
+uint32_t helper_bmerge(target_ulong r1, target_ulong r2)
+{
+ uint32_t i, ret;
+
+ ret = 0;
+ for (i = 0; i < 16; i++) {
+ ret |= (r1 & 1) << (2 * i + 1);
+ ret |= (r2 & 1) << (2 * i);
+ r1 = r1 >> 1;
+ r2 = r2 >> 1;
+ }
+ return ret;
+}
+
+uint64_t helper_bsplit(uint32_t r1)
+{
+ int32_t i;
+ uint64_t ret;
+
+ ret = 0;
+ for (i = 0; i < 32; i = i + 2) {
+ /* even */
+ ret |= (r1 & 1) << (i/2);
+ r1 = r1 >> 1;
+ /* odd */
+ ret |= (uint64_t)(r1 & 1) << (i/2 + 32);
+ r1 = r1 >> 1;
+ }
+ return ret;
+}
+
+uint32_t helper_parity(target_ulong r1)
+{
+ uint32_t ret;
+ uint32_t nOnes, i;
+
+ ret = 0;
+ nOnes = 0;
+ for (i = 0; i < 8; i++) {
+ ret ^= (r1 & 1);
+ r1 = r1 >> 1;
+ }
+ /* second byte */
+ nOnes = 0;
+ for (i = 0; i < 8; i++) {
+ nOnes ^= (r1 & 1);
+ r1 = r1 >> 1;
+ }
+ ret |= nOnes << 8;
+ /* third byte */
+ nOnes = 0;
+ for (i = 0; i < 8; i++) {
+ nOnes ^= (r1 & 1);
+ r1 = r1 >> 1;
+ }
+ ret |= nOnes << 16;
+ /* fourth byte */
+ nOnes = 0;
+ for (i = 0; i < 8; i++) {
+ nOnes ^= (r1 & 1);
+ r1 = r1 >> 1;
+ }
+ ret |= nOnes << 24;
+
+ return ret;
+}
+
+uint64_t helper_unpack(target_ulong arg1)
+{
+ int32_t fp_exp = extract32(arg1, 23, 8);
+ int32_t fp_frac = extract32(arg1, 0, 23);
+ uint64_t ret;
+ int32_t int_exp, int_mant;
+
+ if (fp_exp == 255) {
+ int_exp = 255;
+ int_mant = (fp_frac << 7);
+ } else if ((fp_exp == 0) && (fp_frac == 0)) {
+ int_exp = -127;
+ int_mant = 0;
+ } else if ((fp_exp == 0) && (fp_frac != 0)) {
+ int_exp = -126;
+ int_mant = (fp_frac << 7);
+ } else {
+ int_exp = fp_exp - 127;
+ int_mant = (fp_frac << 7);
+ int_mant |= (1 << 30);
+ }
+ ret = int_exp;
+ ret = ret << 32;
+ ret |= int_mant;
+
+ return ret;
+}
+
+uint64_t helper_dvinit_b_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
+{
+ uint64_t ret;
+ int32_t abs_sig_dividend, abs_base_dividend, abs_divisor;
+ int32_t quotient_sign;
+
+ ret = sextract32(r1, 0, 32);
+ ret = ret << 24;
+ quotient_sign = 0;
+ if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
+ ret |= 0xffffff;
+ quotient_sign = 1;
+ }
+
+ abs_sig_dividend = abs(r1) >> 7;
+ abs_base_dividend = abs(r1) & 0x7f;
+ abs_divisor = abs(r1);
+ /* calc overflow */
+ env->PSW_USB_V = 0;
+ if ((quotient_sign) && (abs_divisor)) {
+ env->PSW_USB_V = (((abs_sig_dividend == abs_divisor) &&
+ (abs_base_dividend >= abs_divisor)) ||
+ (abs_sig_dividend > abs_divisor));
+ } else {
+ env->PSW_USB_V = (abs_sig_dividend >= abs_divisor);
+ }
+ env->PSW_USB_V = env->PSW_USB_V << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = 0;
+
+ return ret;
+}
+
+uint64_t helper_dvinit_b_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
+{
+ uint64_t ret = sextract32(r1, 0, 32);
+
+ ret = ret << 24;
+ if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
+ ret |= 0xffffff;
+ }
+ /* calc overflow */
+ env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffffff80)));
+ env->PSW_USB_V = env->PSW_USB_V << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = 0;
+
+ return ret;
+}
+
+uint64_t helper_dvinit_h_13(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
+{
+ uint64_t ret;
+ int32_t abs_sig_dividend, abs_base_dividend, abs_divisor;
+ int32_t quotient_sign;
+
+ ret = sextract32(r1, 0, 32);
+ ret = ret << 16;
+ quotient_sign = 0;
+ if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
+ ret |= 0xffff;
+ quotient_sign = 1;
+ }
+
+ abs_sig_dividend = abs(r1) >> 7;
+ abs_base_dividend = abs(r1) & 0x7f;
+ abs_divisor = abs(r1);
+ /* calc overflow */
+ env->PSW_USB_V = 0;
+ if ((quotient_sign) && (abs_divisor)) {
+ env->PSW_USB_V = (((abs_sig_dividend == abs_divisor) &&
+ (abs_base_dividend >= abs_divisor)) ||
+ (abs_sig_dividend > abs_divisor));
+ } else {
+ env->PSW_USB_V = (abs_sig_dividend >= abs_divisor);
+ }
+ env->PSW_USB_V = env->PSW_USB_V << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = 0;
+
+ return ret;
+}
+
+uint64_t helper_dvinit_h_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
+{
+ uint64_t ret = sextract32(r1, 0, 32);
+
+ ret = ret << 16;
+ if (!((r1 & 0x80000000) == (r2 & 0x80000000))) {
+ ret |= 0xffff;
+ }
+ /* calc overflow */
+ env->PSW_USB_V = ((r2 == 0) || ((r2 == 0xffffffff) && (r1 == 0xffff8000)));
+ env->PSW_USB_V = env->PSW_USB_V << 31;
+ env->PSW_USB_SV |= env->PSW_USB_V;
+ env->PSW_USB_AV = 0;
+
+ return ret;
+}
+
+uint64_t helper_mul_h(uint32_t arg00, uint32_t arg01,
+ uint32_t arg10, uint32_t arg11, uint32_t n)
+{
+ uint64_t ret;
+ uint32_t result0, result1;
+
+ int32_t sc1 = ((arg00 & 0xffff) == 0x8000) &&
+ ((arg10 & 0xffff) == 0x8000) && (n == 1);
+ int32_t sc0 = ((arg01 & 0xffff) == 0x8000) &&
+ ((arg11 & 0xffff) == 0x8000) && (n == 1);
+ if (sc1) {
+ result1 = 0x7fffffff;
+ } else {
+ result1 = (((uint32_t)(arg00 * arg10)) << n);
+ }
+ if (sc0) {
+ result0 = 0x7fffffff;
+ } else {
+ result0 = (((uint32_t)(arg01 * arg11)) << n);
+ }
+ ret = (((uint64_t)result1 << 32)) | result0;
+ return ret;
+}
+
+uint64_t helper_mulm_h(uint32_t arg00, uint32_t arg01,
+ uint32_t arg10, uint32_t arg11, uint32_t n)
+{
+ uint64_t ret;
+ int64_t result0, result1;
+
+ int32_t sc1 = ((arg00 & 0xffff) == 0x8000) &&
+ ((arg10 & 0xffff) == 0x8000) && (n == 1);
+ int32_t sc0 = ((arg01 & 0xffff) == 0x8000) &&
+ ((arg11 & 0xffff) == 0x8000) && (n == 1);
+
+ if (sc1) {
+ result1 = 0x7fffffff;
+ } else {
+ result1 = (((int32_t)arg00 * (int32_t)arg10) << n);
+ }
+ if (sc0) {
+ result0 = 0x7fffffff;
+ } else {
+ result0 = (((int32_t)arg01 * (int32_t)arg11) << n);
+ }
+ ret = (result1 + result0);
+ ret = ret << 16;
+ return ret;
+}
+uint32_t helper_mulr_h(uint32_t arg00, uint32_t arg01,
+ uint32_t arg10, uint32_t arg11, uint32_t n)
+{
+ uint32_t result0, result1;
+
+ int32_t sc1 = ((arg00 & 0xffff) == 0x8000) &&
+ ((arg10 & 0xffff) == 0x8000) && (n == 1);
+ int32_t sc0 = ((arg01 & 0xffff) == 0x8000) &&
+ ((arg11 & 0xffff) == 0x8000) && (n == 1);
+
+ if (sc1) {
+ result1 = 0x7fffffff;
+ } else {
+ result1 = ((arg00 * arg10) << n) + 0x8000;
+ }
+ if (sc0) {
+ result0 = 0x7fffffff;
+ } else {
+ result0 = ((arg01 * arg11) << n) + 0x8000;
+ }
+ return (result1 & 0xffff0000) | (result0 >> 16);
+}
+
/* context save area (CSA) related helpers */
static int cdc_increment(target_ulong *psw)
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 65abf453f..dbcf87e38 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -85,22 +85,31 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f,
{
TriCoreCPU *cpu = TRICORE_CPU(cs);
CPUTriCoreState *env = &cpu->env;
+ uint32_t psw;
int i;
- cpu_fprintf(f, "PC=%08x\n", env->PC);
+ psw = psw_read(env);
+
+ cpu_fprintf(f, "PC: " TARGET_FMT_lx, env->PC);
+ cpu_fprintf(f, " PSW: " TARGET_FMT_lx, psw);
+ cpu_fprintf(f, " ICR: " TARGET_FMT_lx, env->ICR);
+ cpu_fprintf(f, "\nPCXI: " TARGET_FMT_lx, env->PCXI);
+ cpu_fprintf(f, " FCX: " TARGET_FMT_lx, env->FCX);
+ cpu_fprintf(f, " LCX: " TARGET_FMT_lx, env->LCX);
+
for (i = 0; i < 16; ++i) {
if ((i & 3) == 0) {
- cpu_fprintf(f, "GPR A%02d:", i);
+ cpu_fprintf(f, "\nGPR A%02d:", i);
}
- cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_a[i], env->gpr_a[i]);
+ cpu_fprintf(f, " " TARGET_FMT_lx, env->gpr_a[i]);
}
for (i = 0; i < 16; ++i) {
if ((i & 3) == 0) {
- cpu_fprintf(f, "GPR D%02d:", i);
+ cpu_fprintf(f, "\nGPR D%02d:", i);
}
- cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames_d[i], env->gpr_d[i]);
+ cpu_fprintf(f, " " TARGET_FMT_lx, env->gpr_d[i]);
}
-
+ cpu_fprintf(f, "\n");
}
/*
@@ -115,6 +124,64 @@ void tricore_cpu_dump_state(CPUState *cs, FILE *f,
tcg_temp_free_i32(helper_tmp); \
} while (0)
+#define GEN_HELPER_LL(name, ret, arg0, arg1, n) do { \
+ TCGv arg00 = tcg_temp_new(); \
+ TCGv arg01 = tcg_temp_new(); \
+ TCGv arg11 = tcg_temp_new(); \
+ tcg_gen_sari_tl(arg00, arg0, 16); \
+ tcg_gen_ext16s_tl(arg01, arg0); \
+ tcg_gen_ext16s_tl(arg11, arg1); \
+ gen_helper_##name(ret, arg00, arg01, arg11, arg11, n); \
+ tcg_temp_free(arg00); \
+ tcg_temp_free(arg01); \
+ tcg_temp_free(arg11); \
+} while (0)
+
+#define GEN_HELPER_LU(name, ret, arg0, arg1, n) do { \
+ TCGv arg00 = tcg_temp_new(); \
+ TCGv arg01 = tcg_temp_new(); \
+ TCGv arg10 = tcg_temp_new(); \
+ TCGv arg11 = tcg_temp_new(); \
+ tcg_gen_sari_tl(arg00, arg0, 16); \
+ tcg_gen_ext16s_tl(arg01, arg0); \
+ tcg_gen_sari_tl(arg11, arg1, 16); \
+ tcg_gen_ext16s_tl(arg10, arg1); \
+ gen_helper_##name(ret, arg00, arg01, arg10, arg11, n); \
+ tcg_temp_free(arg00); \
+ tcg_temp_free(arg01); \
+ tcg_temp_free(arg10); \
+ tcg_temp_free(arg11); \
+} while (0)
+
+#define GEN_HELPER_UL(name, ret, arg0, arg1, n) do { \
+ TCGv arg00 = tcg_temp_new(); \
+ TCGv arg01 = tcg_temp_new(); \
+ TCGv arg10 = tcg_temp_new(); \
+ TCGv arg11 = tcg_temp_new(); \
+ tcg_gen_sari_tl(arg00, arg0, 16); \
+ tcg_gen_ext16s_tl(arg01, arg0); \
+ tcg_gen_sari_tl(arg10, arg1, 16); \
+ tcg_gen_ext16s_tl(arg11, arg1); \
+ gen_helper_##name(ret, arg00, arg01, arg10, arg11, n); \
+ tcg_temp_free(arg00); \
+ tcg_temp_free(arg01); \
+ tcg_temp_free(arg10); \
+ tcg_temp_free(arg11); \
+} while (0)
+
+#define GEN_HELPER_UU(name, ret, arg0, arg1, n) do { \
+ TCGv arg00 = tcg_temp_new(); \
+ TCGv arg01 = tcg_temp_new(); \
+ TCGv arg11 = tcg_temp_new(); \
+ tcg_gen_sari_tl(arg01, arg0, 16); \
+ tcg_gen_ext16s_tl(arg00, arg0); \
+ tcg_gen_sari_tl(arg11, arg1, 16); \
+ gen_helper_##name(ret, arg00, arg01, arg11, arg11, n); \
+ tcg_temp_free(arg00); \
+ tcg_temp_free(arg01); \
+ tcg_temp_free(arg11); \
+} while (0)
+
#define EA_ABS_FORMAT(con) (((con & 0x3C000) << 14) + (con & 0x3FFF))
#define EA_B_ABSOLUT(con) (((offset & 0xf00000) << 8) | \
((offset & 0x0fffff) << 1))
@@ -719,6 +786,62 @@ static inline void gen_sub_d(TCGv ret, TCGv r1, TCGv r2)
tcg_temp_free(result);
}
+static inline void gen_sub_CC(TCGv ret, TCGv r1, TCGv r2)
+{
+ TCGv result = tcg_temp_new();
+ TCGv temp = tcg_temp_new();
+
+ tcg_gen_sub_tl(result, r1, r2);
+ /* calc C bit */
+ tcg_gen_setcond_tl(TCG_COND_GEU, cpu_PSW_C, r1, r2);
+ /* calc V bit */
+ tcg_gen_xor_tl(cpu_PSW_V, result, r1);
+ tcg_gen_xor_tl(temp, r1, r2);
+ tcg_gen_and_tl(cpu_PSW_V, cpu_PSW_V, temp);
+ /* calc SV bit */
+ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+ /* Calc AV bit */
+ tcg_gen_add_tl(cpu_PSW_AV, result, result);
+ tcg_gen_xor_tl(cpu_PSW_AV, result, cpu_PSW_AV);
+ /* calc SAV bit */
+ tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+ /* write back result */
+ tcg_gen_mov_tl(ret, result);
+
+ tcg_temp_free(result);
+ tcg_temp_free(temp);
+}
+
+static inline void gen_subc_CC(TCGv ret, TCGv r1, TCGv r2)
+{
+ TCGv temp = tcg_temp_new();
+ tcg_gen_not_tl(temp, r2);
+ gen_addc_CC(ret, r1, temp);
+ tcg_temp_free(temp);
+}
+
+static inline void gen_abs(TCGv ret, TCGv r1)
+{
+ TCGv temp = tcg_temp_new();
+ TCGv t0 = tcg_const_i32(0);
+
+ tcg_gen_neg_tl(temp, r1);
+ tcg_gen_movcond_tl(TCG_COND_GE, ret, r1, t0, r1, temp);
+ /* overflow can only happen, if r1 = 0x80000000 */
+ tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, r1, 0x80000000);
+ tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+ /* calc SV bit */
+ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+ /* Calc AV bit */
+ tcg_gen_add_tl(cpu_PSW_AV, ret, ret);
+ tcg_gen_xor_tl(cpu_PSW_AV, ret, cpu_PSW_AV);
+ /* calc SAV bit */
+ tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+
+ tcg_temp_free(temp);
+ tcg_temp_free(t0);
+}
+
static inline void gen_absdif(TCGv ret, TCGv r1, TCGv r2)
{
TCGv temp = tcg_temp_new_i32();
@@ -1208,6 +1331,13 @@ gen_accumulating_condi(int cond, TCGv ret, TCGv r1, int32_t con,
tcg_temp_free(temp);
}
+/* ret = (r1 cond r2) ? 0xFFFFFFFF ? 0x00000000;*/
+static inline void gen_cond_w(TCGCond cond, TCGv ret, TCGv r1, TCGv r2)
+{
+ tcg_gen_setcond_tl(cond, ret, r1, r2);
+ tcg_gen_neg_tl(ret, ret);
+}
+
static inline void gen_eqany_bi(TCGv ret, TCGv r1, int32_t con)
{
TCGv b0 = tcg_temp_new();
@@ -1284,6 +1414,86 @@ static inline void gen_insert(TCGv ret, TCGv r1, TCGv r2, TCGv width, TCGv pos)
tcg_temp_free(temp2);
}
+static inline void gen_bsplit(TCGv rl, TCGv rh, TCGv r1)
+{
+ TCGv_i64 temp = tcg_temp_new_i64();
+
+ gen_helper_bsplit(temp, r1);
+ tcg_gen_extr_i64_i32(rl, rh, temp);
+
+ tcg_temp_free_i64(temp);
+}
+
+static inline void gen_unpack(TCGv rl, TCGv rh, TCGv r1)
+{
+ TCGv_i64 temp = tcg_temp_new_i64();
+
+ gen_helper_unpack(temp, r1);
+ tcg_gen_extr_i64_i32(rl, rh, temp);
+
+ tcg_temp_free_i64(temp);
+}
+
+static inline void
+gen_dvinit_b(CPUTriCoreState *env, TCGv rl, TCGv rh, TCGv r1, TCGv r2)
+{
+ TCGv_i64 ret = tcg_temp_new_i64();
+
+ if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+ gen_helper_dvinit_b_13(ret, cpu_env, r1, r2);
+ } else {
+ gen_helper_dvinit_b_131(ret, cpu_env, r1, r2);
+ }
+ tcg_gen_extr_i64_i32(rl, rh, ret);
+
+ tcg_temp_free_i64(ret);
+}
+
+static inline void
+gen_dvinit_h(CPUTriCoreState *env, TCGv rl, TCGv rh, TCGv r1, TCGv r2)
+{
+ TCGv_i64 ret = tcg_temp_new_i64();
+
+ if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+ gen_helper_dvinit_h_13(ret, cpu_env, r1, r2);
+ } else {
+ gen_helper_dvinit_h_131(ret, cpu_env, r1, r2);
+ }
+ tcg_gen_extr_i64_i32(rl, rh, ret);
+
+ tcg_temp_free_i64(ret);
+}
+
+static void gen_calc_usb_mul_h(TCGv arg_low, TCGv arg_high)
+{
+ TCGv temp = tcg_temp_new();
+ /* calc AV bit */
+ tcg_gen_add_tl(temp, arg_low, arg_low);
+ tcg_gen_xor_tl(temp, temp, arg_low);
+ tcg_gen_add_tl(cpu_PSW_AV, arg_high, arg_high);
+ tcg_gen_xor_tl(cpu_PSW_AV, cpu_PSW_AV, arg_high);
+ tcg_gen_or_tl(cpu_PSW_AV, cpu_PSW_AV, temp);
+ /* calc SAV bit */
+ tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+ tcg_gen_movi_tl(cpu_PSW_V, 0);
+ tcg_temp_free(temp);
+}
+
+static void gen_calc_usb_mulr_h(TCGv arg)
+{
+ TCGv temp = tcg_temp_new();
+ /* calc AV bit */
+ tcg_gen_add_tl(temp, arg, arg);
+ tcg_gen_xor_tl(temp, temp, arg);
+ tcg_gen_shli_tl(cpu_PSW_AV, temp, 16);
+ tcg_gen_or_tl(cpu_PSW_AV, cpu_PSW_AV, temp);
+ /* calc SAV bit */
+ tcg_gen_or_tl(cpu_PSW_SAV, cpu_PSW_SAV, cpu_PSW_AV);
+ /* clear V bit */
+ tcg_gen_movi_tl(cpu_PSW_V, 0);
+ tcg_temp_free(temp);
+}
+
/* helpers for generating program flow micro-ops */
static inline void gen_save_pc(target_ulong pc)
@@ -3203,7 +3413,7 @@ static void decode_bol_opc(CPUTriCoreState *env, DisasContext *ctx, int32_t op1)
tcg_gen_qemu_ld_tl(cpu_gpr_a[r1], temp, ctx->mem_idx, MO_LEUL);
tcg_temp_free(temp);
break;
- case OPC1_32_BOL_LD_W_LONFOFF:
+ case OPC1_32_BOL_LD_W_LONGOFF:
temp = tcg_temp_new();
tcg_gen_addi_tl(temp, cpu_gpr_a[r2], address);
tcg_gen_qemu_ld_tl(cpu_gpr_d[r1], temp, ctx->mem_idx, MO_LEUL);
@@ -3222,8 +3432,49 @@ static void decode_bol_opc(CPUTriCoreState *env, DisasContext *ctx, int32_t op1)
case OPC1_32_BOL_ST_W_LONGOFF:
gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUL);
break;
+ case OPC1_32_BOL_LD_B_LONGOFF:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB);
+ } else {
+ /* raise illegal opcode trap */
+ }
+ break;
+ case OPC1_32_BOL_LD_BU_LONGOFF:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_UB);
+ } else {
+ /* raise illegal opcode trap */
+ }
+ break;
+ case OPC1_32_BOL_LD_H_LONGOFF:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW);
+ } else {
+ /* raise illegal opcode trap */
+ }
+ break;
+ case OPC1_32_BOL_LD_HU_LONGOFF:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LEUW);
+ } else {
+ /* raise illegal opcode trap */
+ }
+ break;
+ case OPC1_32_BOL_ST_B_LONGOFF:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ gen_offset_st(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_SB);
+ } else {
+ /* raise illegal opcode trap */
+ }
+ break;
+ case OPC1_32_BOL_ST_H_LONGOFF:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ gen_offset_ld(ctx, cpu_gpr_d[r1], cpu_gpr_a[r2], address, MO_LESW);
+ } else {
+ /* raise illegal opcode trap */
+ }
+ break;
}
-
}
/* RC format */
@@ -3776,11 +4027,23 @@ static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx,
tcg_gen_addi_tl(cpu_gpr_a[r2], cpu_gpr_a[r1], const16 << 16);
break;
case OPC1_32_RLC_MFCR:
+ const16 = MASK_OP_RLC_CONST16(ctx->opcode);
gen_mfcr(env, cpu_gpr_d[r2], const16);
break;
case OPC1_32_RLC_MOV:
tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
break;
+ case OPC1_32_RLC_MOV_64:
+ if (tricore_feature(env, TRICORE_FEATURE_16)) {
+ if ((r2 & 0x1) != 0) {
+ /* TODO: raise OPD trap */
+ }
+ tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
+ tcg_gen_movi_tl(cpu_gpr_d[r2+1], const16 >> 15);
+ } else {
+ /* TODO: raise illegal opcode trap */
+ }
+ break;
case OPC1_32_RLC_MOV_U:
const16 = MASK_OP_RLC_CONST16(ctx->opcode);
tcg_gen_movi_tl(cpu_gpr_d[r2], const16);
@@ -3792,11 +4055,729 @@ static void decode_rlc_opc(CPUTriCoreState *env, DisasContext *ctx,
tcg_gen_movi_tl(cpu_gpr_a[r2], const16 << 16);
break;
case OPC1_32_RLC_MTCR:
- gen_mtcr(env, ctx, cpu_gpr_d[r2], const16);
+ const16 = MASK_OP_RLC_CONST16(ctx->opcode);
+ gen_mtcr(env, ctx, cpu_gpr_d[r1], const16);
break;
}
}
+/* RR format */
+static void decode_rr_accumulator(CPUTriCoreState *env, DisasContext *ctx)
+{
+ uint32_t op2;
+ int r3, r2, r1;
+
+ r3 = MASK_OP_RR_D(ctx->opcode);
+ r2 = MASK_OP_RR_S2(ctx->opcode);
+ r1 = MASK_OP_RR_S1(ctx->opcode);
+ op2 = MASK_OP_RR_OP2(ctx->opcode);
+
+ switch (op2) {
+ case OPC2_32_RR_ABS:
+ gen_abs(cpu_gpr_d[r3], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABS_B:
+ gen_helper_abs_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABS_H:
+ gen_helper_abs_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSDIF:
+ gen_absdif(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSDIF_B:
+ gen_helper_absdif_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSDIF_H:
+ gen_helper_absdif_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSDIFS:
+ gen_helper_absdif_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSDIFS_H:
+ gen_helper_absdif_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSS:
+ gen_helper_abs_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ABSS_H:
+ gen_helper_abs_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADD:
+ gen_add_d(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADD_B:
+ gen_helper_add_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADD_H:
+ gen_helper_add_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADDC:
+ gen_addc_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADDS:
+ gen_adds(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADDS_H:
+ gen_helper_add_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADDS_HU:
+ gen_helper_add_h_suov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADDS_U:
+ gen_helper_add_suov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ADDX:
+ gen_add_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_AND_EQ:
+ gen_accumulating_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_and_tl);
+ break;
+ case OPC2_32_RR_AND_GE:
+ gen_accumulating_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_and_tl);
+ break;
+ case OPC2_32_RR_AND_GE_U:
+ gen_accumulating_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_and_tl);
+ break;
+ case OPC2_32_RR_AND_LT:
+ gen_accumulating_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_and_tl);
+ break;
+ case OPC2_32_RR_AND_LT_U:
+ gen_accumulating_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_and_tl);
+ break;
+ case OPC2_32_RR_AND_NE:
+ gen_accumulating_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_and_tl);
+ break;
+ case OPC2_32_RR_EQ:
+ tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_EQ_B:
+ gen_helper_eq_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_EQ_H:
+ gen_helper_eq_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_EQ_W:
+ gen_cond_w(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_EQANY_B:
+ gen_helper_eqany_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_EQANY_H:
+ gen_helper_eqany_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_GE:
+ tcg_gen_setcond_tl(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_GE_U:
+ tcg_gen_setcond_tl(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT:
+ tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_U:
+ tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_B:
+ gen_helper_lt_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_BU:
+ gen_helper_lt_bu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_H:
+ gen_helper_lt_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_HU:
+ gen_helper_lt_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_W:
+ gen_cond_w(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_LT_WU:
+ gen_cond_w(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MAX:
+ tcg_gen_movcond_tl(TCG_COND_GT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MAX_U:
+ tcg_gen_movcond_tl(TCG_COND_GTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MAX_B:
+ gen_helper_max_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MAX_BU:
+ gen_helper_max_bu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MAX_H:
+ gen_helper_max_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MAX_HU:
+ gen_helper_max_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MIN:
+ tcg_gen_movcond_tl(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MIN_U:
+ tcg_gen_movcond_tl(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MIN_B:
+ gen_helper_min_b(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MIN_BU:
+ gen_helper_min_bu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MIN_H:
+ gen_helper_min_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MIN_HU:
+ gen_helper_min_hu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MOV:
+ tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_NE:
+ tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_OR_EQ:
+ gen_accumulating_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_or_tl);
+ break;
+ case OPC2_32_RR_OR_GE:
+ gen_accumulating_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_or_tl);
+ break;
+ case OPC2_32_RR_OR_GE_U:
+ gen_accumulating_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_or_tl);
+ break;
+ case OPC2_32_RR_OR_LT:
+ gen_accumulating_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_or_tl);
+ break;
+ case OPC2_32_RR_OR_LT_U:
+ gen_accumulating_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_or_tl);
+ break;
+ case OPC2_32_RR_OR_NE:
+ gen_accumulating_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_or_tl);
+ break;
+ case OPC2_32_RR_SAT_B:
+ gen_saturate(cpu_gpr_d[r3], cpu_gpr_d[r1], 0x7f, -0x80);
+ break;
+ case OPC2_32_RR_SAT_BU:
+ gen_saturate_u(cpu_gpr_d[r3], cpu_gpr_d[r1], 0xff);
+ break;
+ case OPC2_32_RR_SAT_H:
+ gen_saturate(cpu_gpr_d[r3], cpu_gpr_d[r1], 0x7fff, -0x8000);
+ break;
+ case OPC2_32_RR_SAT_HU:
+ gen_saturate_u(cpu_gpr_d[r3], cpu_gpr_d[r1], 0xffff);
+ break;
+ case OPC2_32_RR_SH_EQ:
+ gen_sh_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH_GE:
+ gen_sh_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH_GE_U:
+ gen_sh_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH_LT:
+ gen_sh_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH_LT_U:
+ gen_sh_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH_NE:
+ gen_sh_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUB:
+ gen_sub_d(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUB_B:
+ gen_helper_sub_b(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUB_H:
+ gen_helper_sub_h(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUBC:
+ gen_subc_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUBS:
+ gen_subs(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUBS_U:
+ gen_subsu(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUBS_H:
+ gen_helper_sub_h_ssov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUBS_HU:
+ gen_helper_sub_h_suov(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SUBX:
+ gen_sub_CC(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_XOR_EQ:
+ gen_accumulating_cond(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_xor_tl);
+ break;
+ case OPC2_32_RR_XOR_GE:
+ gen_accumulating_cond(TCG_COND_GE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_xor_tl);
+ break;
+ case OPC2_32_RR_XOR_GE_U:
+ gen_accumulating_cond(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_xor_tl);
+ break;
+ case OPC2_32_RR_XOR_LT:
+ gen_accumulating_cond(TCG_COND_LT, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_xor_tl);
+ break;
+ case OPC2_32_RR_XOR_LT_U:
+ gen_accumulating_cond(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_xor_tl);
+ break;
+ case OPC2_32_RR_XOR_NE:
+ gen_accumulating_cond(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_d[r1],
+ cpu_gpr_d[r2], &tcg_gen_xor_tl);
+ break;
+ }
+}
+
+static void decode_rr_logical_shift(CPUTriCoreState *env, DisasContext *ctx)
+{
+ uint32_t op2;
+ int r3, r2, r1;
+ TCGv temp;
+
+ r3 = MASK_OP_RR_D(ctx->opcode);
+ r2 = MASK_OP_RR_S2(ctx->opcode);
+ r1 = MASK_OP_RR_S1(ctx->opcode);
+
+ temp = tcg_temp_new();
+ op2 = MASK_OP_RR_OP2(ctx->opcode);
+
+ switch (op2) {
+ case OPC2_32_RR_AND:
+ tcg_gen_and_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ANDN:
+ tcg_gen_andc_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_CLO:
+ gen_helper_clo(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_CLO_H:
+ gen_helper_clo_h(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_CLS:
+ gen_helper_cls(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_CLS_H:
+ gen_helper_cls_h(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_CLZ:
+ gen_helper_clz(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_CLZ_H:
+ gen_helper_clz_h(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_NAND:
+ tcg_gen_nand_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_NOR:
+ tcg_gen_nor_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_OR:
+ tcg_gen_or_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_ORN:
+ tcg_gen_orc_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH:
+ gen_helper_sh(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SH_H:
+ gen_helper_sh_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SHA:
+ gen_helper_sha(cpu_gpr_d[r3], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SHA_H:
+ gen_helper_sha_h(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_SHAS:
+ gen_shas(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_XNOR:
+ tcg_gen_eqv_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_XOR:
+ tcg_gen_xor_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ }
+ tcg_temp_free(temp);
+}
+
+static void decode_rr_address(CPUTriCoreState *env, DisasContext *ctx)
+{
+ uint32_t op2, n;
+ int r1, r2, r3;
+ TCGv temp;
+
+ op2 = MASK_OP_RR_OP2(ctx->opcode);
+ r3 = MASK_OP_RR_D(ctx->opcode);
+ r2 = MASK_OP_RR_S2(ctx->opcode);
+ r1 = MASK_OP_RR_S1(ctx->opcode);
+ n = MASK_OP_RR_N(ctx->opcode);
+
+ switch (op2) {
+ case OPC2_32_RR_ADD_A:
+ tcg_gen_add_tl(cpu_gpr_a[r3], cpu_gpr_a[r1], cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_ADDSC_A:
+ temp = tcg_temp_new();
+ tcg_gen_shli_tl(temp, cpu_gpr_d[r1], n);
+ tcg_gen_add_tl(cpu_gpr_a[r3], cpu_gpr_a[r2], temp);
+ tcg_temp_free(temp);
+ break;
+ case OPC2_32_RR_ADDSC_AT:
+ temp = tcg_temp_new();
+ tcg_gen_sari_tl(temp, cpu_gpr_d[r1], 3);
+ tcg_gen_add_tl(temp, cpu_gpr_a[r2], temp);
+ tcg_gen_andi_tl(cpu_gpr_a[r3], temp, 0xFFFFFFFC);
+ tcg_temp_free(temp);
+ break;
+ case OPC2_32_RR_EQ_A:
+ tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_a[r1],
+ cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_EQZ:
+ tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr_d[r3], cpu_gpr_a[r1], 0);
+ break;
+ case OPC2_32_RR_GE_A:
+ tcg_gen_setcond_tl(TCG_COND_GEU, cpu_gpr_d[r3], cpu_gpr_a[r1],
+ cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_LT_A:
+ tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr_d[r3], cpu_gpr_a[r1],
+ cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_MOV_A:
+ tcg_gen_mov_tl(cpu_gpr_a[r3], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_MOV_AA:
+ tcg_gen_mov_tl(cpu_gpr_a[r3], cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_MOV_D:
+ tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_NE_A:
+ tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_a[r1],
+ cpu_gpr_a[r2]);
+ break;
+ case OPC2_32_RR_NEZ_A:
+ tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr_d[r3], cpu_gpr_a[r1], 0);
+ break;
+ case OPC2_32_RR_SUB_A:
+ tcg_gen_sub_tl(cpu_gpr_a[r3], cpu_gpr_a[r1], cpu_gpr_a[r2]);
+ break;
+ }
+}
+
+static void decode_rr_idirect(CPUTriCoreState *env, DisasContext *ctx)
+{
+ uint32_t op2;
+ int r1;
+
+ op2 = MASK_OP_RR_OP2(ctx->opcode);
+ r1 = MASK_OP_RR_S1(ctx->opcode);
+
+ switch (op2) {
+ case OPC2_32_RR_JI:
+ tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
+ break;
+ case OPC2_32_RR_JLI:
+ tcg_gen_movi_tl(cpu_gpr_a[11], ctx->next_pc);
+ tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
+ break;
+ case OPC2_32_RR_CALLI:
+ gen_helper_1arg(call, ctx->next_pc);
+ tcg_gen_andi_tl(cpu_PC, cpu_gpr_a[r1], ~0x1);
+ break;
+ }
+ tcg_gen_exit_tb(0);
+ ctx->bstate = BS_BRANCH;
+}
+
+static void decode_rr_divide(CPUTriCoreState *env, DisasContext *ctx)
+{
+ uint32_t op2;
+ int r1, r2, r3;
+
+ TCGv temp, temp2;
+
+ op2 = MASK_OP_RR_OP2(ctx->opcode);
+ r3 = MASK_OP_RR_D(ctx->opcode);
+ r2 = MASK_OP_RR_S2(ctx->opcode);
+ r1 = MASK_OP_RR_S1(ctx->opcode);
+
+ switch (op2) {
+ case OPC2_32_RR_BMERGE:
+ gen_helper_bmerge(cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_BSPLIT:
+ gen_bsplit(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_DVINIT_B:
+ gen_dvinit_b(env, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_DVINIT_BU:
+ temp = tcg_temp_new();
+ temp2 = tcg_temp_new();
+ /* reset av */
+ tcg_gen_movi_tl(cpu_PSW_AV, 0);
+ if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+ /* overflow = (abs(D[r3+1]) >= abs(D[r2])) */
+ tcg_gen_neg_tl(temp, cpu_gpr_d[r3+1]);
+ /* use cpu_PSW_AV to compare against 0 */
+ tcg_gen_movcond_tl(TCG_COND_LT, temp, cpu_gpr_d[r3+1], cpu_PSW_AV,
+ temp, cpu_gpr_d[r3+1]);
+ tcg_gen_neg_tl(temp2, cpu_gpr_d[r2]);
+ tcg_gen_movcond_tl(TCG_COND_LT, temp2, cpu_gpr_d[r2], cpu_PSW_AV,
+ temp2, cpu_gpr_d[r2]);
+ tcg_gen_setcond_tl(TCG_COND_GE, cpu_PSW_V, temp, temp2);
+ } else {
+ /* overflow = (D[b] == 0) */
+ tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r2], 0);
+ }
+ tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+ /* sv */
+ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+ /* write result */
+ tcg_gen_shri_tl(temp, cpu_gpr_d[r1], 8);
+ tcg_gen_shli_tl(cpu_gpr_d[r3], cpu_gpr_d[r1], 24);
+ tcg_gen_mov_tl(cpu_gpr_d[r3+1], temp);
+
+ tcg_temp_free(temp);
+ tcg_temp_free(temp2);
+ break;
+ case OPC2_32_RR_DVINIT_H:
+ gen_dvinit_h(env, cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1],
+ cpu_gpr_d[r2]);
+ break;
+ case OPC2_32_RR_DVINIT_HU:
+ temp = tcg_temp_new();
+ temp2 = tcg_temp_new();
+ /* reset av */
+ tcg_gen_movi_tl(cpu_PSW_AV, 0);
+ if (!tricore_feature(env, TRICORE_FEATURE_131)) {
+ /* overflow = (abs(D[r3+1]) >= abs(D[r2])) */
+ tcg_gen_neg_tl(temp, cpu_gpr_d[r3+1]);
+ /* use cpu_PSW_AV to compare against 0 */
+ tcg_gen_movcond_tl(TCG_COND_LT, temp, cpu_gpr_d[r3+1], cpu_PSW_AV,
+ temp, cpu_gpr_d[r3+1]);
+ tcg_gen_neg_tl(temp2, cpu_gpr_d[r2]);
+ tcg_gen_movcond_tl(TCG_COND_LT, temp2, cpu_gpr_d[r2], cpu_PSW_AV,
+ temp2, cpu_gpr_d[r2]);
+ tcg_gen_setcond_tl(TCG_COND_GE, cpu_PSW_V, temp, temp2);
+ } else {
+ /* overflow = (D[b] == 0) */
+ tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r2], 0);
+ }
+ tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+ /* sv */
+ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+ /* write result */
+ tcg_gen_mov_tl(temp, cpu_gpr_d[r1]);
+ tcg_gen_shri_tl(cpu_gpr_d[r3+1], temp, 16);
+ tcg_gen_shli_tl(cpu_gpr_d[r3], temp, 16);
+ tcg_temp_free(temp);
+ tcg_temp_free(temp2);
+ break;
+ case OPC2_32_RR_DVINIT:
+ temp = tcg_temp_new();
+ temp2 = tcg_temp_new();
+ /* overflow = ((D[b] == 0) ||
+ ((D[b] == 0xFFFFFFFF) && (D[a] == 0x80000000))) */
+ tcg_gen_setcondi_tl(TCG_COND_EQ, temp, cpu_gpr_d[r2], 0xffffffff);
+ tcg_gen_setcondi_tl(TCG_COND_EQ, temp2, cpu_gpr_d[r1], 0x80000000);
+ tcg_gen_and_tl(temp, temp, temp2);
+ tcg_gen_setcondi_tl(TCG_COND_EQ, temp2, cpu_gpr_d[r2], 0);
+ tcg_gen_or_tl(cpu_PSW_V, temp, temp2);
+ tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+ /* sv */
+ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+ /* reset av */
+ tcg_gen_movi_tl(cpu_PSW_AV, 0);
+ /* write result */
+ tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ /* sign extend to high reg */
+ tcg_gen_sari_tl(cpu_gpr_d[r3+1], cpu_gpr_d[r1], 31);
+ tcg_temp_free(temp);
+ tcg_temp_free(temp2);
+ break;
+ case OPC2_32_RR_DVINIT_U:
+ /* overflow = (D[b] == 0) */
+ tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_PSW_V, cpu_gpr_d[r2], 0);
+ tcg_gen_shli_tl(cpu_PSW_V, cpu_PSW_V, 31);
+ /* sv */
+ tcg_gen_or_tl(cpu_PSW_SV, cpu_PSW_SV, cpu_PSW_V);
+ /* reset av */
+ tcg_gen_movi_tl(cpu_PSW_AV, 0);
+ /* write result */
+ tcg_gen_mov_tl(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ /* zero extend to high reg*/
+ tcg_gen_movi_tl(cpu_gpr_d[r3+1], 0);
+ break;
+ case OPC2_32_RR_PARITY:
+ gen_helper_parity(cpu_gpr_d[r3], cpu_gpr_d[r1]);
+ break;
+ case OPC2_32_RR_UNPACK:
+ gen_unpack(cpu_gpr_d[r3], cpu_gpr_d[r3+1], cpu_gpr_d[r1]);
+ break;
+ }
+}
+
+/* RR1 Format */
+static void decode_rr1_mul(CPUTriCoreState *env, DisasContext *ctx)
+{
+ uint32_t op2;
+
+ int r1, r2, r3;
+ TCGv n;
+ TCGv_i64 temp64;
+
+ r1 = MASK_OP_RR1_S1(ctx->opcode);
+ r2 = MASK_OP_RR1_S2(ctx->opcode);
+ r3 = MASK_OP_RR1_D(ctx->opcode);
+ n = tcg_const_i32(MASK_OP_RR1_N(ctx->opcode));
+ op2 = MASK_OP_RR1_OP2(ctx->opcode);
+
+ switch (op2) {
+ case OPC2_32_RR1_MUL_H_32_LL:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_LL(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MUL_H_32_LU:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_LU(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MUL_H_32_UL:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_UL(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MUL_H_32_UU:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_UU(mul_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ gen_calc_usb_mul_h(cpu_gpr_d[r3], cpu_gpr_d[r3+1]);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MULM_H_64_LL:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_LL(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ /* reset V bit */
+ tcg_gen_movi_tl(cpu_PSW_V, 0);
+ /* reset AV bit */
+ tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MULM_H_64_LU:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_LU(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ /* reset V bit */
+ tcg_gen_movi_tl(cpu_PSW_V, 0);
+ /* reset AV bit */
+ tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MULM_H_64_UL:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_UL(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ /* reset V bit */
+ tcg_gen_movi_tl(cpu_PSW_V, 0);
+ /* reset AV bit */
+ tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V);
+ tcg_temp_free_i64(temp64);
+ break;
+ case OPC2_32_RR1_MULM_H_64_UU:
+ temp64 = tcg_temp_new_i64();
+ GEN_HELPER_UU(mulm_h, temp64, cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ tcg_gen_extr_i64_i32(cpu_gpr_d[r3], cpu_gpr_d[r3+1], temp64);
+ /* reset V bit */
+ tcg_gen_movi_tl(cpu_PSW_V, 0);
+ /* reset AV bit */
+ tcg_gen_mov_tl(cpu_PSW_AV, cpu_PSW_V);
+ tcg_temp_free_i64(temp64);
+
+ break;
+ case OPC2_32_RR1_MULR_H_16_LL:
+ GEN_HELPER_LL(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ gen_calc_usb_mulr_h(cpu_gpr_d[r3]);
+ break;
+ case OPC2_32_RR1_MULR_H_16_LU:
+ GEN_HELPER_LU(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ gen_calc_usb_mulr_h(cpu_gpr_d[r3]);
+ break;
+ case OPC2_32_RR1_MULR_H_16_UL:
+ GEN_HELPER_UL(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ gen_calc_usb_mulr_h(cpu_gpr_d[r3]);
+ break;
+ case OPC2_32_RR1_MULR_H_16_UU:
+ GEN_HELPER_UU(mulr_h, cpu_gpr_d[r3], cpu_gpr_d[r1], cpu_gpr_d[r2], n);
+ gen_calc_usb_mulr_h(cpu_gpr_d[r3]);
+ break;
+ }
+ tcg_temp_free(n);
+}
+
static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
{
int op1;
@@ -3808,8 +4789,8 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
op1 = MASK_OP_MAJOR(ctx->opcode);
- /* handle JNZ.T opcode only being 6 bit long */
- if (unlikely((op1 & 0x3f) == OPCM_32_BRN_JTT)) {
+ /* handle JNZ.T opcode only being 7 bit long */
+ if (unlikely((op1 & 0x7f) == OPCM_32_BRN_JTT)) {
op1 = OPCM_32_BRN_JTT;
}
@@ -3884,7 +4865,7 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
case OPC1_32_B_JA:
case OPC1_32_B_JL:
case OPC1_32_B_JLA:
- address = MASK_OP_B_DISP24(ctx->opcode);
+ address = MASK_OP_B_DISP24_SEXT(ctx->opcode);
gen_compute_branch(ctx, op1, 0, 0, 0, address);
break;
/* Bit-format */
@@ -3930,10 +4911,16 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
break;
/* BOL-format */
case OPC1_32_BOL_LD_A_LONGOFF:
- case OPC1_32_BOL_LD_W_LONFOFF:
+ case OPC1_32_BOL_LD_W_LONGOFF:
case OPC1_32_BOL_LEA_LONGOFF:
case OPC1_32_BOL_ST_W_LONGOFF:
case OPC1_32_BOL_ST_A_LONGOFF:
+ case OPC1_32_BOL_LD_B_LONGOFF:
+ case OPC1_32_BOL_LD_BU_LONGOFF:
+ case OPC1_32_BOL_LD_H_LONGOFF:
+ case OPC1_32_BOL_LD_HU_LONGOFF:
+ case OPC1_32_BOL_ST_B_LONGOFF:
+ case OPC1_32_BOL_ST_H_LONGOFF:
decode_bol_opc(env, ctx, op1);
break;
/* BRC Format */
@@ -4021,12 +5008,33 @@ static void decode_32Bit_opc(CPUTriCoreState *env, DisasContext *ctx)
case OPC1_32_RLC_ADDIH_A:
case OPC1_32_RLC_MFCR:
case OPC1_32_RLC_MOV:
+ case OPC1_32_RLC_MOV_64:
case OPC1_32_RLC_MOV_U:
case OPC1_32_RLC_MOV_H:
case OPC1_32_RLC_MOVH_A:
case OPC1_32_RLC_MTCR:
decode_rlc_opc(env, ctx, op1);
break;
+/* RR Format */
+ case OPCM_32_RR_ACCUMULATOR:
+ decode_rr_accumulator(env, ctx);
+ break;
+ case OPCM_32_RR_LOGICAL_SHIFT:
+ decode_rr_logical_shift(env, ctx);
+ break;
+ case OPCM_32_RR_ADRESS:
+ decode_rr_address(env, ctx);
+ break;
+ case OPCM_32_RR_IDIRECT:
+ decode_rr_idirect(env, ctx);
+ break;
+ case OPCM_32_RR_DIVIDE:
+ decode_rr_divide(env, ctx);
+ break;
+/* RR1 Format */
+ case OPCM_32_RR1_MUL:
+ decode_rr1_mul(env, ctx);
+ break;
}
}
diff --git a/target-tricore/tricore-opcodes.h b/target-tricore/tricore-opcodes.h
index 0a9122cfb..919063e42 100644
--- a/target-tricore/tricore-opcodes.h
+++ b/target-tricore/tricore-opcodes.h
@@ -94,6 +94,8 @@
/* B Format */
#define MASK_OP_B_DISP24(op) (MASK_BITS_SHIFT(op, 16, 31) + \
(MASK_BITS_SHIFT(op, 8, 15) << 16))
+#define MASK_OP_B_DISP24_SEXT(op) (MASK_BITS_SHIFT(op, 16, 31) + \
+ (MASK_BITS_SHIFT_SEXT(op, 8, 15) << 16))
/* BIT Format */
#define MASK_OP_BIT_D(op) MASK_BITS_SHIFT(op, 28, 31)
#define MASK_OP_BIT_POS2(op) MASK_BITS_SHIFT(op, 23, 27)
@@ -114,7 +116,7 @@
/* BOL Format */
#define MASK_OP_BOL_OFF16(op) ((MASK_BITS_SHIFT(op, 16, 21) + \
(MASK_BITS_SHIFT(op, 28, 31) << 6)) + \
- (MASK_BITS_SHIFT(op, 22, 27) >> 10))
+ (MASK_BITS_SHIFT(op, 22, 27) << 10))
#define MASK_OP_BOL_OFF16_SEXT(op) ((MASK_BITS_SHIFT(op, 16, 21) + \
(MASK_BITS_SHIFT(op, 28, 31) << 6)) + \
(MASK_BITS_SHIFT_SEXT(op, 22, 27) << 10))
@@ -447,10 +449,16 @@ enum {
OPCM_32_BO_ADDRMODE_LDMST_BITREVERSE_CIRCULAR = 0x69,
/* BOL Format */
OPC1_32_BOL_LD_A_LONGOFF = 0x99,
- OPC1_32_BOL_LD_W_LONFOFF = 0x19,
+ OPC1_32_BOL_LD_W_LONGOFF = 0x19,
OPC1_32_BOL_LEA_LONGOFF = 0xd9,
OPC1_32_BOL_ST_W_LONGOFF = 0x59,
OPC1_32_BOL_ST_A_LONGOFF = 0xb5, /* 1.6 only */
+ OPC1_32_BOL_LD_B_LONGOFF = 0x79, /* 1.6 only */
+ OPC1_32_BOL_LD_BU_LONGOFF = 0x39, /* 1.6 only */
+ OPC1_32_BOL_LD_H_LONGOFF = 0xc9, /* 1.6 only */
+ OPC1_32_BOL_LD_HU_LONGOFF = 0xb9, /* 1.6 only */
+ OPC1_32_BOL_ST_B_LONGOFF = 0xe9, /* 1.6 only */
+ OPC1_32_BOL_ST_H_LONGOFF = 0xf9, /* 1.6 only */
/* BRC Format */
OPCM_32_BRC_EQ_NEQ = 0xdf,
OPCM_32_BRC_GE = 0xff,
@@ -487,6 +495,7 @@ enum {
OPC1_32_RLC_ADDIH_A = 0x11,
OPC1_32_RLC_MFCR = 0x4d,
OPC1_32_RLC_MOV = 0x3b,
+ OPC1_32_RLC_MOV_64 = 0xfb, /* 1.6 only */
OPC1_32_RLC_MOV_U = 0xbb,
OPC1_32_RLC_MOV_H = 0x7b,
OPC1_32_RLC_MOVH_A = 0x91,
@@ -495,7 +504,7 @@ enum {
OPCM_32_RR_LOGICAL_SHIFT = 0x0f,
OPCM_32_RR_ACCUMULATOR = 0x0b,
OPCM_32_RR_ADRESS = 0x01,
- OPCM_32_RR_FLOAT = 0x4b,
+ OPCM_32_RR_DIVIDE = 0x4b,
OPCM_32_RR_IDIRECT = 0x2d,
/* RR1 Format */
OPCM_32_RR1_MUL = 0xb3,
@@ -1033,8 +1042,8 @@ enum {
OPC2_32_RR_MAX_BU = 0x5b,
OPC2_32_RR_MAX_H = 0x7a,
OPC2_32_RR_MAX_HU = 0x7b,
- OPC2_32_RR_MIN = 0x19,
- OPC2_32_RR_MIN_U = 0x18,
+ OPC2_32_RR_MIN = 0x18,
+ OPC2_32_RR_MIN_U = 0x19,
OPC2_32_RR_MIN_B = 0x58,
OPC2_32_RR_MIN_BU = 0x59,
OPC2_32_RR_MIN_H = 0x78,