Re: [Qemu-devel] [PATCH v3 4/4] target-tricore: Add instructions of RCR opcode format

2014-11-20 Thread Richard Henderson
On 11/20/2014 02:28 PM, Bastian Koppelmann wrote:
> +uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1,
> +uint64_t r2, target_ulong r3)
> +{
> +uint64_t ret_low, ret_high;
> +uint64_t r2_high;
> +int64_t t1 = sextract64(r1, 0, 32);
> +int64_t t3 = sextract64(r3, 0, 32);
> +
> +ret_low = t1 * t3;
> +ret_high = ((int64_t)ret_low >> 63);
> +r2_high = ((int64_t)r2 >> 63);
> +add128(&ret_low, &ret_high, r2, r2_high);
> +
> +/* check for saturate */
> +t1 = (int64_t)ret_low >> 63;
> +if (t1 != ret_high) {

Instead of 128-bit addition, just use the "normal" overflow detection:

  mul = t1 * t3;
  ret = mul + r2;
  ovf = (ret ^ mul) & ~(mul ^ r2);
  if ((int64_t)ovf < 0)


> +uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1,
> +uint64_t r2, target_ulong r3)
> +{
> +uint64_t ret_low, ret_high;
> +uint64_t t1 = extract64(r1, 0, 32);
> +uint64_t t3 = extract64(r3, 0, 32);
> +
> +ret_low = t1 * t3;
> +ret_high = 0;
> +add128(&ret_low, &ret_high, r2, 0);
> +
> +if (ret_high != 0) {

I'm sure this is similar, though easier since its unsigned:

  mul = t1 * t3;
  ret = mul + r2;
  if (ret < r2)

> +env->PSW_USB_V = (1 << 31);
> +env->PSW_USB_SV = (1 << 31);
> +ret_low = UINT64_MAX;
> +} else if ((ret_high & (1LL << 63)) != 0) {

I'm not sure what this is about though, since your "ret_high != 0" shadows it,
so it'll never be executed.  Cut and paste from ssov, or is the addition
actually signed?

> +uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1,
> +uint64_t r2, target_ulong r3)
...
> +uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1,
> +uint64_t r2, target_ulong r3)

Likewise, of course.

Otherwise, it looks good.


r~



[Qemu-devel] [PATCH v3 4/4] target-tricore: Add instructions of RCR opcode format

2014-11-20 Thread Bastian Koppelmann
Add instructions of RCR opcode format.
Add helper for madd32/64_ssov and madd32/64_suov.
Add helper for msub32/64_ssov and msub32/64_suov.
Add microcode generator function madd/msub for 32bit and 64bit, which calculate 
a mul and a add/sub.
OPC2_32_RCR_MSUB_U_32 -> OPC2_32_RCR_MSUB_U_32.

Signed-off-by: Bastian Koppelmann 
---
v2 -> v3:
- madd/msub and maddu/msubu now use 64 bit arithmetic instead of 128 bit.
- helper madd64_ssov/suov and msub64_ssov/suov now use 64 bit arithmetic 
for the mul.
- cleaned up double setting of PSW_USB_V/SV in helper_msub64_suov.

 target-tricore/helper.h  |   8 +
 target-tricore/op_helper.c   | 191 
 target-tricore/translate.c   | 479 +++
 target-tricore/tricore-opcodes.h |   3 +-
 4 files changed, 680 insertions(+), 1 deletion(-)

diff --git a/target-tricore/helper.h b/target-tricore/helper.h
index 2eb33ea..6c07bd7 100644
--- a/target-tricore/helper.h
+++ b/target-tricore/helper.h
@@ -24,6 +24,14 @@ 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)
 DEF_HELPER_3(absdif_ssov, i32, env, i32, i32)
+DEF_HELPER_4(madd32_ssov, i32, env, i32, i32, i32)
+DEF_HELPER_4(madd32_suov, i32, env, i32, i32, i32)
+DEF_HELPER_4(madd64_ssov, i64, env, i32, i64, i32)
+DEF_HELPER_4(madd64_suov, i64, env, i32, i64, i32)
+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)
 /* 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 0b6b471..434839f 100644
--- a/target-tricore/op_helper.c
+++ b/target-tricore/op_helper.c
@@ -56,6 +56,16 @@ uint32_t helper_circ_update(uint32_t reg, uint32_t off)
 return reg - index + new_index;
 }

+static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
+{
+*plow += a;
+/* carry test */
+if (*plow < a) {
+(*phigh)++;
+}
+*phigh += b;
+}
+
 #define SSOV(env, ret, arg, len) do {   \
 int64_t max_pos = INT##len ##_MAX;  \
 int64_t max_neg = INT##len ##_MIN;  \
@@ -198,6 +208,187 @@ target_ulong helper_absdif_ssov(CPUTriCoreState *env, 
target_ulong r1,
 SSOV(env, ret, result, 32);
 return ret;
 }
+
+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;
+}
+
+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;
+}
+
+uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1,
+uint64_t r2, target_ulong r3)
+{
+uint64_t ret_low, ret_high;
+uint64_t r2_high;
+int64_t t1 = sextract64(r1, 0, 32);
+int64_t t3 = sextract64(r3, 0, 32);
+
+ret_low = t1 * t3;
+ret_high = ((int64_t)ret_low >> 63);
+r2_high = ((int64_t)r2 >> 63);
+add128(&ret_low, &ret_high, r2, r2_high);
+
+/* check for saturate */
+t1 = (int64_t)ret_low >> 63;
+if (t1 != ret_high) {
+env->PSW_USB_V = (1 << 31);
+env->PSW_USB_SV = (1 << 31);
+if (t1 == 0x0) {
+ret_low = INT64_MIN;
+} else {
+ret_low = INT64_MAX;
+}
+} else {
+env->PSW_USB_V = 0;
+}
+t1 = ret_low >> 32;
+env->PSW_USB_AV = t1 ^ t1 * 2u;
+env->PSW_USB_SAV |= env->PSW_USB_AV;
+
+return ret_low;
+}
+
+uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1,
+uint64_t r2, target_ulong r3)
+{
+uint64_t ret_low, ret_high;
+uint64_t t1 = extract64(r1, 0, 32);
+uint64_t t3 = extract64(r3, 0, 32);
+
+ret_low = t1 * t3;
+ret_high = 0;
+add128(&ret_low, &ret_high, r2, 0);
+
+if (ret_high != 0) {
+env->PSW_USB_V = (1 << 31);
+env->PSW_USB_SV = (1 << 31);
+ret_low = UINT64_MAX;
+} else if ((ret_high & (1LL << 63)) != 0) {
+ret_low = 0;
+env->PSW_USB_V = (1 << 31);
+env->PSW_USB_SV = (1 << 31);
+} else {
+env->PSW_USB_V = 0;
+}
+t1 = ret_low >> 32;
+env->PSW_USB_AV = t1 ^ t1 * 2u;
+env->PSW_USB_SAV |= env->PSW_USB_AV;
+return ret_low;
+}
+
+target_ulong helper_msub32_ssov(CPUTriC