Commit 7baef630 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/bkoppelmann/tags/pull-tricore-20150127' into staging



tricore bugfixes and RR1, RR2, RRPW and RRR insn

# gpg: Signature made Tue 27 Jan 2015 12:02:06 GMT using RSA key ID 6B69CA14
# gpg: Good signature from "Bastian Koppelmann <kbastian@mail.uni-paderborn.de>"

* remotes/bkoppelmann/tags/pull-tricore-20150127:
  target-tricore: Add instructions of RRR opcode format
  target-tricore: Add instructions of RRPW opcode format
  target-tricore: Add instructions of RR2 opcode format
  target-tricore: Add instructions of RR1 opcode format, that have 0x93 as first opcode
  target-tricore: split up suov32 into suov32_pos and suov32_neg
  target-tricore: Fix bugs found by coverity
  target-tricore: calculate av bits before saturation
  target-tricore: Several translator and cpu model fixes
  target-tricore: Add missing ULL suffix on 64 bit constant

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 1ac0206b 09532255
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -118,7 +118,7 @@ static void tc1796_initfn(Object *obj)
{
    TriCoreCPU *cpu = TRICORE_CPU(obj);

    set_feature(&cpu->env, TRICORE_FEATURE_13);
    set_feature(&cpu->env, TRICORE_FEATURE_131);
}

static void aurix_initfn(Object *obj)
+1 −0
Original line number Diff line number Diff line
@@ -238,6 +238,7 @@ struct CPUTriCoreState {
#define MASK_LCX_LCXS 0x000f0000
#define MASK_LCX_LCX0 0x0000ffff

#define TRICORE_HFLAG_KUU     0x3
#define TRICORE_HFLAG_UM0     0x00002 /* user mode-0 flag          */
#define TRICORE_HFLAG_UM1     0x00001 /* user mode-1 flag          */
#define TRICORE_HFLAG_SM      0x00000 /* kernel mode flag          */
+8 −0
Original line number Diff line number Diff line
@@ -60,10 +60,14 @@ 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(ixmax, TCG_CALL_NO_RWG_SE, i64, i64, i32)
DEF_HELPER_FLAGS_2(ixmax_u, TCG_CALL_NO_RWG_SE, i64, i64, 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)
DEF_HELPER_FLAGS_2(ixmin, TCG_CALL_NO_RWG_SE, i64, i64, i32)
DEF_HELPER_FLAGS_2(ixmin_u, TCG_CALL_NO_RWG_SE, i64, i64, 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)
@@ -81,12 +85,16 @@ 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_FLAGS_4(pack, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32, i32)
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)
DEF_HELPER_FLAGS_2(dvadj, TCG_CALL_NO_RWG_SE, i64, i64, i32)
DEF_HELPER_FLAGS_2(dvstep, TCG_CALL_NO_RWG_SE, i64, i64, i32)
DEF_HELPER_FLAGS_2(dvstep_u, TCG_CALL_NO_RWG_SE, i64, i64, 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)
+204 −28
Original line number Diff line number Diff line
@@ -80,15 +80,27 @@ static uint32_t ssov32(CPUTriCoreState *env, int64_t arg)
    return ret;
}

static uint32_t suov32(CPUTriCoreState *env, int64_t arg)
static uint32_t suov32_pos(CPUTriCoreState *env, uint64_t arg)
{
    uint32_t ret;
    int64_t max_pos = UINT32_MAX;
    uint64_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 {
        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_neg(CPUTriCoreState *env, int64_t arg)
{
    uint32_t ret;

    if (arg < 0) {
        env->PSW_USB_V = (1 << 31);
        env->PSW_USB_SV = (1 << 31);
@@ -97,7 +109,6 @@ static uint32_t suov32(CPUTriCoreState *env, int64_t arg)
        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;
@@ -189,7 +200,7 @@ target_ulong helper_add_suov(CPUTriCoreState *env, target_ulong r1,
    int64_t t1 = extract64(r1, 0, 32);
    int64_t t2 = extract64(r2, 0, 32);
    int64_t result = t1 + t2;
    return suov32(env, result);
    return suov32_pos(env, result);
}

target_ulong helper_add_h_suov(CPUTriCoreState *env, target_ulong r1,
@@ -227,7 +238,7 @@ target_ulong helper_sub_suov(CPUTriCoreState *env, target_ulong r1,
    int64_t t1 = extract64(r1, 0, 32);
    int64_t t2 = extract64(r2, 0, 32);
    int64_t result = t1 - t2;
    return suov32(env, result);
    return suov32_neg(env, result);
}

target_ulong helper_sub_h_suov(CPUTriCoreState *env, target_ulong r1,
@@ -255,7 +266,8 @@ target_ulong helper_mul_suov(CPUTriCoreState *env, target_ulong r1,
    int64_t t1 = extract64(r1, 0, 32);
    int64_t t2 = extract64(r2, 0, 32);
    int64_t result = t1 * t2;
    return suov32(env, result);

    return suov32_pos(env, result);
}

target_ulong helper_sha_ssov(CPUTriCoreState *env, target_ulong r1,
@@ -355,7 +367,7 @@ target_ulong helper_madd32_suov(CPUTriCoreState *env, target_ulong r1,
    int64_t result;

    result = t2 + (t1 * t3);
    return suov32(env, result);
    return suov32_pos(env, result);
}

uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1,
@@ -370,6 +382,10 @@ uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1,
    ret = mul + r2;
    ovf = (ret ^ mul) & ~(mul ^ r2);

    t1 = ret >> 32;
    env->PSW_USB_AV = t1 ^ t1 * 2u;
    env->PSW_USB_SAV |= env->PSW_USB_AV;

    if ((int64_t)ovf < 0) {
        env->PSW_USB_V = (1 << 31);
        env->PSW_USB_SV = (1 << 31);
@@ -383,9 +399,6 @@ uint64_t helper_madd64_ssov(CPUTriCoreState *env, target_ulong r1,
    } else {
        env->PSW_USB_V = 0;
    }
    t1 = ret >> 32;
    env->PSW_USB_AV = t1 ^ t1 * 2u;
    env->PSW_USB_SAV |= env->PSW_USB_AV;

    return ret;
}
@@ -400,6 +413,10 @@ uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1,
    mul = t1 * t3;
    ret = mul + r2;

    t1 = ret >> 32;
    env->PSW_USB_AV = t1 ^ t1 * 2u;
    env->PSW_USB_SAV |= env->PSW_USB_AV;

    if (ret < r2) {
        env->PSW_USB_V = (1 << 31);
        env->PSW_USB_SV = (1 << 31);
@@ -408,9 +425,6 @@ uint64_t helper_madd64_suov(CPUTriCoreState *env, target_ulong r1,
    } else {
        env->PSW_USB_V = 0;
    }
    t1 = ret >> 32;
    env->PSW_USB_AV = t1 ^ t1 * 2u;
    env->PSW_USB_SAV |= env->PSW_USB_AV;
    return ret;
}

@@ -435,7 +449,7 @@ target_ulong helper_msub32_suov(CPUTriCoreState *env, target_ulong r1,
    int64_t result;

    result = t2 - (t1 * t3);
    return suov32(env, result);
    return suov32_neg(env, result);
}

uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1,
@@ -450,6 +464,10 @@ uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1,
    ret = r2 - mul;
    ovf = (ret ^ r2) & (mul ^ r2);

    t1 = ret >> 32;
    env->PSW_USB_AV = t1 ^ t1 * 2u;
    env->PSW_USB_SAV |= env->PSW_USB_AV;

    if ((int64_t)ovf < 0) {
        env->PSW_USB_V = (1 << 31);
        env->PSW_USB_SV = (1 << 31);
@@ -463,9 +481,6 @@ uint64_t helper_msub64_ssov(CPUTriCoreState *env, target_ulong r1,
    } else {
        env->PSW_USB_V = 0;
    }
    t1 = ret >> 32;
    env->PSW_USB_AV = t1 ^ t1 * 2u;
    env->PSW_USB_SAV |= env->PSW_USB_AV;
    return ret;
}

@@ -479,6 +494,10 @@ uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1,
    mul = t1 * t3;
    ret = r2 - mul;

    t1 = ret >> 32;
    env->PSW_USB_AV = t1 ^ t1 * 2u;
    env->PSW_USB_SAV |= env->PSW_USB_AV;

    if (ret > r2) {
        env->PSW_USB_V = (1 << 31);
        env->PSW_USB_SV = (1 << 31);
@@ -487,9 +506,6 @@ uint64_t helper_msub64_suov(CPUTriCoreState *env, target_ulong r1,
    } else {
        env->PSW_USB_V = 0;
    }
    t1 = ret >> 32;
    env->PSW_USB_AV = t1 ^ t1 * 2u;
    env->PSW_USB_SAV |= env->PSW_USB_AV;
    return ret;
}

@@ -867,6 +883,50 @@ uint32_t helper_##name ##_hu(target_ulong r1, target_ulong r2)\
                                                              \
    return ret;                                               \
}                                                             \
                                                              \
uint64_t helper_ix##name(uint64_t r1, uint32_t r2)            \
{                                                             \
    int64_t r2l, r2h, r1hl;                                   \
    uint64_t ret = 0;                                         \
                                                              \
    ret = ((r1 + 2) & 0xffff);                                \
    r2l = sextract64(r2, 0, 16);                              \
    r2h = sextract64(r2, 16, 16);                             \
    r1hl = sextract64(r1, 32, 16);                            \
                                                              \
    if ((r2l op ## = r2h) && (r2l op r1hl)) {                 \
        ret |= (r2l & 0xffff) << 32;                          \
        ret |= extract64(r1, 0, 16) << 16;                    \
    } else if ((r2h op r2l) && (r2h op r1hl)) {               \
        ret |= extract64(r2, 16, 16) << 32;                   \
        ret |= extract64(r1 + 1, 0, 16) << 16;                \
    } else {                                                  \
        ret |= r1 & 0xffffffff0000ull;                        \
    }                                                         \
    return ret;                                               \
}                                                             \
                                                              \
uint64_t helper_ix##name ##_u(uint64_t r1, uint32_t r2)       \
{                                                             \
    int64_t r2l, r2h, r1hl;                                   \
    uint64_t ret = 0;                                         \
                                                              \
    ret = ((r1 + 2) & 0xffff);                                \
    r2l = extract64(r2, 0, 16);                               \
    r2h = extract64(r2, 16, 16);                              \
    r1hl = extract64(r1, 32, 16);                             \
                                                              \
    if ((r2l op ## = r2h) && (r2l op r1hl)) {                 \
        ret |= (r2l & 0xffff) << 32;                          \
        ret |= extract64(r1, 0, 16) << 16;                    \
    } else if ((r2h op r2l) && (r2h op r1hl)) {               \
        ret |= extract64(r2, 16, 16) << 32;                   \
        ret |= extract64(r1 + 1, 0, 16) << 16;                \
    } else {                                                  \
        ret |= r1 & 0xffffffff0000ull;                        \
    }                                                         \
    return ret;                                               \
}

EXTREMA_H_B(max, >)
EXTREMA_H_B(min, <)
@@ -994,7 +1054,7 @@ uint32_t helper_sha(CPUTriCoreState *env, target_ulong r1, target_ulong r2)
    } else if (shift_count > 0) {
        result = t1 << shift_count;
        /* calc carry */
        env->PSW_USB_C = ((result & 0xffffffff00000000) != 0);
        env->PSW_USB_C = ((result & 0xffffffff00000000ULL) != 0);
        /* calc v */
        env->PSW_USB_V = (((result > 0x7fffffffLL) ||
                           (result < -0x80000000LL)) << 31);
@@ -1100,6 +1160,48 @@ uint32_t helper_parity(target_ulong r1)
    return ret;
}

uint32_t helper_pack(uint32_t carry, uint32_t r1_low, uint32_t r1_high,
                     target_ulong r2)
{
    uint32_t ret;
    int32_t fp_exp, fp_frac, temp_exp, fp_exp_frac;
    int32_t int_exp  = r1_high;
    int32_t int_mant = r1_low;
    uint32_t flag_rnd = (int_mant & (1 << 7)) && (
                        (int_mant & (1 << 8)) ||
                        (int_mant & 0x7f)     ||
                        (carry != 0));
    if (((int_mant & (1<<31)) == 0) && (int_exp == 255)) {
        fp_exp = 255;
        fp_frac = extract32(int_mant, 8, 23);
    } else if ((int_mant & (1<<31)) && (int_exp >= 127)) {
        fp_exp  = 255;
        fp_frac = 0;
    } else if ((int_mant & (1<<31)) && (int_exp <= -128)) {
        fp_exp  = 0;
        fp_frac = 0;
    } else if (int_mant == 0) {
        fp_exp  = 0;
        fp_frac = 0;
    } else {
        if (((int_mant & (1 << 31)) == 0)) {
            temp_exp = 0;
        } else {
            temp_exp = int_exp + 128;
        }
        fp_exp_frac = (((temp_exp & 0xff) << 23) |
                      extract32(int_mant, 8, 23))
                      + flag_rnd;
        fp_exp  = extract32(fp_exp_frac, 23, 8);
        fp_frac = extract32(fp_exp_frac, 0, 23);
    }
    ret = r2 & (1 << 31);
    ret = ret + (fp_exp << 23);
    ret = ret + (fp_frac & 0x7fffff);

    return ret;
}

uint64_t helper_unpack(target_ulong arg1)
{
    int32_t fp_exp  = extract32(arg1, 23, 8);
@@ -1228,6 +1330,80 @@ uint64_t helper_dvinit_h_131(CPUTriCoreState *env, uint32_t r1, uint32_t r2)
    return ret;
}

uint64_t helper_dvadj(uint64_t r1, uint32_t r2)
{
    int32_t x_sign = (r1 >> 63);
    int32_t q_sign = x_sign ^ (r2 >> 31);
    int32_t eq_pos = x_sign & ((r1 >> 32) == r2);
    int32_t eq_neg = x_sign & ((r1 >> 32) == -r2);
    uint32_t quotient;
    uint64_t ret, remainder;

    if ((q_sign & ~eq_neg) | eq_pos) {
        quotient = (r1 + 1) & 0xffffffff;
    } else {
        quotient = r1 & 0xffffffff;
    }

    if (eq_pos | eq_neg) {
        remainder = 0;
    } else {
        remainder = (r1 & 0xffffffff00000000ull);
    }
    ret = remainder|quotient;
    return ret;
}

uint64_t helper_dvstep(uint64_t r1, uint32_t r2)
{
    int32_t dividend_sign = extract64(r1, 63, 1);
    int32_t divisor_sign = extract32(r2, 31, 1);
    int32_t quotient_sign = (dividend_sign != divisor_sign);
    int32_t addend, dividend_quotient, remainder;
    int32_t i, temp;

    if (quotient_sign) {
        addend = r2;
    } else {
        addend = -r2;
    }
    dividend_quotient = (int32_t)r1;
    remainder = (int32_t)(r1 >> 32);

    for (i = 0; i < 8; i++) {
        remainder = (remainder << 1) | extract32(dividend_quotient, 31, 1);
        dividend_quotient <<= 1;
        temp = remainder + addend;
        if ((temp < 0) == dividend_sign) {
            remainder = temp;
        }
        if (((temp < 0) == dividend_sign)) {
            dividend_quotient = dividend_quotient | !quotient_sign;
        } else {
            dividend_quotient = dividend_quotient | quotient_sign;
        }
    }
    return ((uint64_t)remainder << 32) | (uint32_t)dividend_quotient;
}

uint64_t helper_dvstep_u(uint64_t r1, uint32_t r2)
{
    int32_t dividend_quotient = extract64(r1, 0, 32);
    int64_t remainder = extract64(r1, 32, 32);
    int32_t i;
    int64_t temp;
    for (i = 0; i < 8; i++) {
        remainder = (remainder << 1) | extract32(dividend_quotient, 31, 1);
        dividend_quotient <<= 1;
        temp = (remainder & 0xffffffff) - r2;
        if (temp >= 0) {
            remainder = temp;
        }
        dividend_quotient = dividend_quotient | !(temp < 0);
    }
    return ((uint64_t)remainder << 32) | (uint32_t)dividend_quotient;
}

uint64_t helper_mul_h(uint32_t arg00, uint32_t arg01,
                      uint32_t arg10, uint32_t arg11, uint32_t n)
{
+444 −4

File changed.

Preview size limit exceeded, changes collapsed.

Loading