Commit b1e2af57 authored by Richard Henderson's avatar Richard Henderson
Browse files

target/hppa: Convert fp multiply-add

parent 1cd012a5
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -153,3 +153,15 @@ lda 000011 ..... ..... .. . 1 -- 0110 ...... @ldim5 size=2
lda             000011 ..... ..... .. . 0 -- 0110      ......   @ldstx size=2
sta             000011 ..... ..... .. . 1 -- 1110      ......   @stim5 size=2
stby            000011 b:5 r:5 sp:2 a:1 1 -- 1100 m:1   .....   disp=%im5_0

####
# Floating-point Multiply Add
####

&mpyadd         rm1 rm2 ta ra tm
@mpyadd         ...... rm1:5 rm2:5 ta:5 ra:5 . tm:5     &mpyadd

fmpyadd_f       000110 ..... ..... ..... ..... 0 .....  @mpyadd
fmpyadd_d       000110 ..... ..... ..... ..... 1 .....  @mpyadd
fmpysub_f       100110 ..... ..... ..... ..... 0 .....  @mpyadd
fmpysub_d       100110 ..... ..... ..... ..... 1 .....  @mpyadd
+40 −29
Original line number Diff line number Diff line
@@ -4255,37 +4255,54 @@ static inline int fmpyadd_s_reg(unsigned r)
    return (r & 16) * 2 + 16 + (r & 15);
}

static bool trans_fmpyadd(DisasContext *ctx, uint32_t insn, bool is_sub)
static bool do_fmpyadd_s(DisasContext *ctx, arg_mpyadd *a, bool is_sub)
{
    unsigned tm = extract32(insn, 0, 5);
    unsigned f = extract32(insn, 5, 1);
    unsigned ra = extract32(insn, 6, 5);
    unsigned ta = extract32(insn, 11, 5);
    unsigned rm2 = extract32(insn, 16, 5);
    unsigned rm1 = extract32(insn, 21, 5);
    int tm = fmpyadd_s_reg(a->tm);
    int ra = fmpyadd_s_reg(a->ra);
    int ta = fmpyadd_s_reg(a->ta);
    int rm2 = fmpyadd_s_reg(a->rm2);
    int rm1 = fmpyadd_s_reg(a->rm1);

    nullify_over(ctx);

    /* Independent multiply & add/sub, with undefined behaviour
       if outputs overlap inputs.  */
    if (f == 0) {
        tm = fmpyadd_s_reg(tm);
        ra = fmpyadd_s_reg(ra);
        ta = fmpyadd_s_reg(ta);
        rm2 = fmpyadd_s_reg(rm2);
        rm1 = fmpyadd_s_reg(rm1);
    do_fop_weww(ctx, tm, rm1, rm2, gen_helper_fmpy_s);
    do_fop_weww(ctx, ta, ta, ra,
                is_sub ? gen_helper_fsub_s : gen_helper_fadd_s);
    } else {
        do_fop_dedd(ctx, tm, rm1, rm2, gen_helper_fmpy_d);
        do_fop_dedd(ctx, ta, ta, ra,
                    is_sub ? gen_helper_fsub_d : gen_helper_fadd_d);

    return nullify_end(ctx);
}

static bool trans_fmpyadd_f(DisasContext *ctx, arg_mpyadd *a)
{
    return do_fmpyadd_s(ctx, a, false);
}

static bool trans_fmpysub_f(DisasContext *ctx, arg_mpyadd *a)
{
    return do_fmpyadd_s(ctx, a, true);
}

static bool do_fmpyadd_d(DisasContext *ctx, arg_mpyadd *a, bool is_sub)
{
    nullify_over(ctx);

    do_fop_dedd(ctx, a->tm, a->rm1, a->rm2, gen_helper_fmpy_d);
    do_fop_dedd(ctx, a->ta, a->ta, a->ra,
                is_sub ? gen_helper_fsub_d : gen_helper_fadd_d);

    return nullify_end(ctx);
}

static bool trans_fmpyadd_d(DisasContext *ctx, arg_mpyadd *a)
{
    return do_fmpyadd_d(ctx, a, false);
}

static bool trans_fmpysub_d(DisasContext *ctx, arg_mpyadd *a)
{
    return do_fmpyadd_d(ctx, a, true);
}

static bool trans_fmpyfadd_s(DisasContext *ctx, uint32_t insn,
                             const DisasInsn *di)
{
@@ -4376,9 +4393,6 @@ static void translate_one(DisasContext *ctx, uint32_t insn)

    opc = extract32(insn, 26, 6);
    switch (opc) {
    case 0x06:
        trans_fmpyadd(ctx, insn, false);
        return;
    case 0x08:
        trans_ldil(ctx, insn);
        return;
@@ -4456,9 +4470,6 @@ static void translate_one(DisasContext *ctx, uint32_t insn)
    case 0x25:
        trans_subi(ctx, insn);
        return;
    case 0x26:
        trans_fmpyadd(ctx, insn, true);
        return;
    case 0x27:
        trans_cmpb(ctx, insn, true, false, true);
        return;