Commit 54f00775 authored by Aurelien Jarno's avatar Aurelien Jarno Committed by Alexander Graf
Browse files

target-s390x: implement TRANSLATE AND TEST instruction



It is part of the basic zArchitecture instructions. Allow it to be call
from EXECUTE.

Reviewed-by: default avatarRichard Henderson <rth@twiddle.net>
Signed-off-by: default avatarAurelien Jarno <aurelien@aurel32.net>
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent ed0bcece
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ DEF_HELPER_FLAGS_3(sqxb, TCG_CALL_NO_WG, i64, env, i64, i64)
DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32)
DEF_HELPER_FLAGS_4(unpk, TCG_CALL_NO_WG, void, env, i32, i64, i64)
DEF_HELPER_FLAGS_4(tr, TCG_CALL_NO_WG, void, env, i32, i64, i64)
DEF_HELPER_4(trt, i32, env, i32, i64, i64)
DEF_HELPER_4(cksm, i64, env, i64, i64, i64)
DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64)
DEF_HELPER_FLAGS_2(sfpc, TCG_CALL_NO_RWG, void, env, i64)
+2 −0
Original line number Diff line number Diff line
@@ -759,6 +759,8 @@

/* TRANSLATE */
    C(0xdc00, TR,      SS_a,  Z,   la1, a2, 0, 0, tr, 0)
/* TRANSLATE AND TEST */
    C(0xdd00, TRT,     SS_a,  Z,   la1, a2, 0, 0, trt, 0)

/* UNPACK */
    /* Really format SS_b, but we pack both lengths into one argument
+24 −0
Original line number Diff line number Diff line
@@ -509,6 +509,9 @@ uint32_t HELPER(ex)(CPUS390XState *env, uint32_t cc, uint64_t v1,
        case 0xc00:
            helper_tr(env, l, get_address(env, 0, b1, d1),
                      get_address(env, 0, b2, d2));
        case 0xd00:
            cc = helper_trt(env, l, get_address(env, 0, b1, d1),
                            get_address(env, 0, b2, d2));
            break;
        default:
            goto abort;
@@ -801,6 +804,27 @@ void HELPER(tr)(CPUS390XState *env, uint32_t len, uint64_t array,
    }
}

uint32_t HELPER(trt)(CPUS390XState *env, uint32_t len, uint64_t array,
                     uint64_t trans)
{
    uint32_t cc = 0;
    int i;

    for (i = 0; i <= len; i++) {
        uint8_t byte = cpu_ldub_data(env, array + i);
        uint8_t sbyte = cpu_ldub_data(env, trans + byte);

        if (sbyte != 0) {
            env->regs[1] = array + i;
            env->regs[2] = (env->regs[2] & ~0xff) | sbyte;
            cc = (i == len) ? 2 : 1;
            break;
        }
    }

    return cc;
}

#if !defined(CONFIG_USER_ONLY)
void HELPER(lctlg)(CPUS390XState *env, uint32_t r1, uint64_t a2, uint32_t r3)
{
+10 −0
Original line number Diff line number Diff line
@@ -3787,6 +3787,16 @@ static ExitStatus op_tr(DisasContext *s, DisasOps *o)
    return NO_EXIT;
}

static ExitStatus op_trt(DisasContext *s, DisasOps *o)
{
    TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));
    potential_page_fault(s);
    gen_helper_trt(cc_op, cpu_env, l, o->addr1, o->in2);
    tcg_temp_free_i32(l);
    set_cc_static(s);
    return NO_EXIT;
}

static ExitStatus op_unpk(DisasContext *s, DisasOps *o)
{
    TCGv_i32 l = tcg_const_i32(get_field(s->fields, l1));