From patchwork Sun Oct 4 11:16:35 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chen Gang X-Patchwork-Id: 526101 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 65DB71402B4 for ; Sun, 4 Oct 2015 22:17:16 +1100 (AEDT) Received: from localhost ([::1]:42092 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZihI2-0006bi-CN for incoming@patchwork.ozlabs.org; Sun, 04 Oct 2015 07:17:14 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58812) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZihHW-000646-32 for qemu-devel@nongnu.org; Sun, 04 Oct 2015 07:16:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZihHR-0004kt-0C for qemu-devel@nongnu.org; Sun, 04 Oct 2015 07:16:42 -0400 Received: from col004-omc2s3.hotmail.com ([65.55.34.77]:52187) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZihHQ-0004kd-FQ for qemu-devel@nongnu.org; Sun, 04 Oct 2015 07:16:36 -0400 Received: from COL130-W40 ([65.55.34.72]) by COL004-OMC2S3.hotmail.com over TLS secured channel with Microsoft SMTPSVC(7.5.7601.23008); Sun, 4 Oct 2015 04:16:35 -0700 X-TMN: [xIV1WdNFINjhRa5AM5GKkAjWN4nDDMJr] X-Originating-Email: [xili_gchen_5257@hotmail.com] Message-ID: From: Chen Gang To: "rth@twiddle.net" , Peter Maydell , Chris Metcalf Date: Sun, 4 Oct 2015 19:16:35 +0800 Importance: Normal MIME-Version: 1.0 X-OriginalArrivalTime: 04 Oct 2015 11:16:35.0801 (UTC) FILETIME=[21B82490:01D0FE96] X-detected-operating-system: by eggs.gnu.org: Windows 7 or 8 [fuzzy] X-Received-From: 65.55.34.77 Cc: qemu-devel Subject: [Qemu-devel] [PATCH] target-tilegx: Implement floating point temporarily X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From 4d12af14f361fb5e3a893fc68a599be9ea17d1dc Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sun, 4 Oct 2015 18:00:53 +0800 Subject: [PATCH] target-tilegx: Implement floating point temporarily It is a temporary implementation, but it can pass gcc testsuite. Signed-off-by: Chen Gang ---  target-tilegx/Makefile.objs |   2 +-  target-tilegx/cpu.h         |   5 +-  target-tilegx/fpu.h         | 149 +++++++++++++++++++++++++  target-tilegx/fpu_helper.c  | 259 ++++++++++++++++++++++++++++++++++++++++++++  target-tilegx/helper.h      |   9 ++  target-tilegx/translate.c   |  70 +++++++++---  6 files changed, 479 insertions(+), 15 deletions(-)  create mode 100644 target-tilegx/fpu.h  create mode 100644 target-tilegx/fpu_helper.c --  1.9.3 diff --git a/target-tilegx/Makefile.objs b/target-tilegx/Makefile.objs index 0db778f..1573c36 100644 --- a/target-tilegx/Makefile.objs +++ b/target-tilegx/Makefile.objs @@ -1 +1 @@ -obj-y += cpu.o translate.o helper.o simd_helper.o +obj-y += cpu.o translate.o helper.o simd_helper.o fpu_helper.o diff --git a/target-tilegx/cpu.h b/target-tilegx/cpu.h index 6c0fd53..b752ef3 100644 --- a/target-tilegx/cpu.h +++ b/target-tilegx/cpu.h @@ -27,7 +27,7 @@  #define CPUArchState struct CPUTLGState    #include "exec/cpu-defs.h" - +#include "fpu.h"    /* TILE-Gx common register alias */  #define TILEGX_R_RE    0   /*  0 register, for function/syscall return value */ @@ -77,6 +77,7 @@ typedef enum {      TILEGX_EXCP_OPCODE_FETCHAND4 = 0x10c,      TILEGX_EXCP_OPCODE_FETCHOR = 0x10d,      TILEGX_EXCP_OPCODE_FETCHOR4 = 0x10e, +    TILEGX_EXCP_OPCODE_INVALID_VALUE = 0x10f,      TILEGX_EXCP_REG_IDN_ACCESS = 0x181,      TILEGX_EXCP_REG_UDN_ACCESS = 0x182,      TILEGX_EXCP_UNALIGNMENT = 0x201, @@ -88,6 +89,8 @@ typedef struct CPUTLGState {      uint64_t spregs[TILEGX_SPR_COUNT]; /* Special used registers by outside */      uint64_t pc;                       /* Current pc */   +    FPUTLGState fpu;                   /* fpu context */ +  #if defined(CONFIG_USER_ONLY)      uint64_t excaddr;                  /* exception address */      uint64_t atomic_srca;              /* Arguments to atomic "exceptions" */ diff --git a/target-tilegx/fpu.h b/target-tilegx/fpu.h new file mode 100644 index 0000000..41076bd --- /dev/null +++ b/target-tilegx/fpu.h @@ -0,0 +1,149 @@ +/* + *  TILE-Gx virtual FPU header + * + *  Copyright (c) 2015 Chen Gang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef FPU_TILEGX_H +#define FPU_TILEGX_H + +/* + * Single floaing point instructions decription. + * + *  - fsingle_add1, fsingle_sub1, and fsingle_pack1/2 can be used individually. + * + *  - when fsingle_pack1/2 is used individually, it is for type cast. + * + *  - the old 4Kth result is alrealy useless for caller. + * + * fsingle_add1        ; make context and calc result from rsrca and rsrcb. + *                     ; save result in roundup array, and add index to context. + *                     ; move context to rdst. + * + * fsingle_sub1        ; make context and calc result from rsrca and rsrcb. + *                     ; save result in roundup array, and add index to context. + *                     ; move context to rdst. + * + * fsingle_addsub2     ; skipped. + * + * fsingle_mul1        ; make context and calc result from rsrca and srcb. + *                     ; save result in roundup array, and add index to context. + *                     ; move context to rdst. + * + * fsingle_mul2        ; move rsrca to rdst. + * + * fsingle_pack1       ; skipped. + * + * fsingle_pack2       ; get context from rsrca (rsrca is context). + *                     ; if context for add/sub/mul + *                     ;     get result from roundup array based on index. + *                     ;     move result to rdst. + *                     ; else + *                     ;     get (u)int32_t interger from context, + *                     ;     (u)int32_to_float32. + */ + +/* + * Double floating point instructions' description. + * + *  - fdouble_add_flags, fdouble_sub_flags, and fdouble_pack1/2 can be used + *    individually. + * + *  - when fdouble_pack1/2 is used individually, it is for type cast. + * + *  - the old 4Kth result is alrealy useless for caller. + * + * fdouble_unpack_max: ; skipped. + * + * fdouble_unpack_min: ; skipped. + * + * fdouble_add_flags:  ; make context and calc result from rsrca and rsrcb. + *                     ; save result in roundup array, and add index to context. + *                     ; move context to rdst. + * + * fdouble_sub_flags:  ; make context and calc result from rsrca and rsrcb. + *                     ; save result in roundup array, and add index to context. + *                     ; move context to rdst. + * + * fdouble_addsub:     ; skipped. + * + * fdouble_mul_flags:  ; make context and calc result from rsrca and rsrcb. + *                     ; save result in roundup array, and add index to context. + *                     ; move context to rdst. + * + * fdouble_pack1:      ; get context from rsrcb. + *                     ; if context for add/sub/mul + *                     ;     get result from roundup array based on index. + *                     ;     move result to rdst. + *                     ; else + *                     ;     get (u)int32_t interger from rsrca + *                     ;     (u)int32_to_float64. + * + * fdouble_pack2:      ; skipped. + */ + +#define TILEGX_F_COUNT 0x1000  /* Maximized results count for fdouble */ + +#define TILEGX_F_DUINT 0x21b00 /* exp is for uint32_t to double */ +#define TILEGX_F_DINT  0xa1b00 /* exp is for int32_t to double */ +#define TILEGX_F_SUINT 0x9e    /* exp is for uint32_t to single */ +#define TILEGX_F_SINT  0x29e   /* exp is for int32_t to single */ + +#define TILEGX_F_TCAST 0       /* Result type is for typecast, MUST BE 0 */ +#define TILEGX_F_TCALC 1       /* Result type is for add/sub/mul */ + +#pragma pack(push, 1) +typedef struct TileGXFPCtx { + +    /* According to float(uns)sisf2 and float(uns)sidf2 in gcc tilegx.md */ +    uint64_t exp : 21;         /* Exponent, for TILEGX_F_(D/S)(U)INT */ + +    /* Context type, defined and used by callee */ +    uint64_t type : 4;         /* For TILEGX_F_T(CAST/CALC) */ + +    /* Come from TILE-Gx ISA document, Table 7-2 for floating point */ +    uint64_t unordered : 1;    /* The two are unordered */ +    uint64_t lt : 1;           /* 1st is less than 2nd */ +    uint64_t le : 1;           /* 1st is less than or equal to 2nd */ +    uint64_t gt : 1;           /* 1st is greater than 2nd */ +    uint64_t ge : 1;           /* 1st is greater than or equal to 2nd */ +    uint64_t eq : 1;           /* The two operands are equal */ +    uint64_t neq : 1;          /* The two operands are not equal */ + +    /* Result data according to the context type */ +    uint64_t data : 32;        /* The explanation is below */ +#if 0 +    /* This is the explanation for 'data' above */ +    union { +        uint32_t idx;          /* Index for the add/sub/mul result */ +        uint32_t aint;         /* Absolute input integer for fsingle typecast */ +        /* +         * There is no input integer for fdouble typecast in context, it is in +         * rsrca parameter of fdouble_pack1 instruction. +         */ +    }; +#endif +} TileGXFPCtx; +#pragma pack(pop) + +typedef struct FPUTLGState { +    float_status fp_status;         /* floating point status */ +    int pos32;                      /* Current position for fsingle result */ +    int pos64;                      /* Current position for fdouble result */ +    float32 val32s[TILEGX_F_COUNT]; /* results roudup array for fsingle */ +    float64 val64s[TILEGX_F_COUNT]; /* results roudup array for fdouble */ +} FPUTLGState; + +#endif /* FPU_TILEGX_H */ diff --git a/target-tilegx/fpu_helper.c b/target-tilegx/fpu_helper.c new file mode 100644 index 0000000..daae570 --- /dev/null +++ b/target-tilegx/fpu_helper.c @@ -0,0 +1,259 @@ +/* + * QEMU TILE-Gx helpers + * + *  Copyright (c) 2015 Chen Gang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * + */ + +#include "cpu.h" +#include "qemu-common.h" +#include "exec/helper-proto.h" +#include "fpu/softfloat.h" + +#define SIGNBIT32 0x80000000 +#define FP_STATUS (fpu->fp_status) + +static void fdouble_ana(FPUTLGState *fpu, +                        float64 fsrc, float64 fsrcb, TileGXFPCtx *ctx) +{ +    if (float64_eq(fsrc, fsrcb, &FP_STATUS)) { +        ctx->eq = 1; +    } else { +        ctx->neq = 1; +    } + +    if (float64_lt(fsrc, fsrcb, &FP_STATUS)) { +        ctx->lt = 1; +    } +    if (float64_le(fsrc, fsrcb, &FP_STATUS)) { +        ctx->le = 1; +    } + +    if (float64_lt(fsrcb, fsrc, &FP_STATUS)) { +        ctx->gt = 1; +    } +    if (float64_le(fsrcb, fsrc, &FP_STATUS)) { +        ctx->ge = 1; +    } + +    if (float64_unordered(fsrc, fsrcb, &FP_STATUS)) { +        ctx->unordered = 1; +    } +} + +static float64 t_to_float64(uint64_t a) +{ +    CPU_DoubleU r; +    r.ll = a; +    return r.d; +} + +static uint64_t float64_to_t(float64 fa) +{ +    CPU_DoubleU r; +    r.d = fa; +    return r.ll; +} + +static uint64_t ctx_to_uint64(TileGXFPCtx a) +{ +    union { +        TileGXFPCtx a; +        uint64_t v; +    } t; +    t.a = a; +    return t.v; +} + +static TileGXFPCtx uint64_to_ctx(uint64 v) +{ +    union { +        TileGXFPCtx a; +        uint64_t v; +    } t; +    t.v = v; +    return t.a; +} + +static uint64_t fdouble_calc(FPUTLGState *fpu, +                             float64 fsrc, float64 fsrcb, +                             float64 (*calc)(float64, float64, float_status *)) +{ +    TileGXFPCtx ctx = {0}; + +    ctx.type = TILEGX_F_TCALC; +    ctx.data = fpu->pos64; +    fpu->val64s[fpu->pos64++] = calc(fsrc, fsrcb, &FP_STATUS); +    if (fpu->pos64>= TILEGX_F_COUNT) { +        fpu->pos64 = 0; +    } +    fdouble_ana(fpu, fsrc, fsrcb, &ctx); + +    return ctx_to_uint64(ctx); +} + +uint64_t helper_fdouble_add_flags(CPUTLGState *env, +                                  uint64_t rsrc, uint64_t rsrcb) +{ +    return fdouble_calc(&env->fpu, t_to_float64(rsrc), t_to_float64(rsrcb), +                        float64_add); +} + +uint64_t helper_fdouble_sub_flags(CPUTLGState *env, +                                  uint64_t rsrc, uint64_t rsrcb) +{ +    return fdouble_calc(&env->fpu, t_to_float64(rsrc), t_to_float64(rsrcb), +                        float64_sub); +} + +uint64_t helper_fdouble_mul_flags(CPUTLGState *env, +                                  uint64_t rsrc, uint64_t rsrcb) +{ +    return fdouble_calc(&env->fpu, t_to_float64(rsrc), t_to_float64(rsrcb), +                        float64_mul); +} + +uint64_t helper_fdouble_pack1(CPUTLGState *env, +                              uint64_t rsrc, uint64_t rsrcb) +{ +    FPUTLGState *fpu = &env->fpu; +    TileGXFPCtx ctx = uint64_to_ctx(rsrcb); + +    if (ctx.type == TILEGX_F_TCALC) { +        if (ctx.data>= TILEGX_F_COUNT) { +            helper_exception(env, TILEGX_EXCP_OPCODE_INVALID_VALUE); +        } +        return float64_to_t(fpu->val64s[ctx.data]); +    } + +    switch (ctx.exp) { +    case 0x21b00: +        return float64_to_t(uint32_to_float64(rsrc>> 4, &FP_STATUS)); +    case 0x121b00: +        return float64_to_t(int32_to_float64((rsrc>> 4) | SIGNBIT32, +                                             &FP_STATUS)); +    default: +        fprintf(stderr, "\nUIMP: in helper_fdouble_pack2().\n"); +        helper_exception(env, TILEGX_EXCP_OPCODE_UNIMPLEMENTED); +        return 0; +    } +} + +static void fsingle_ana(FPUTLGState *fpu, +                        float32 fsrc, float32 fsrcb, TileGXFPCtx *ctx) +{ +    if (float32_eq(fsrc, fsrcb, &FP_STATUS)) { +        ctx->eq = 1; +    } else { +        ctx->neq = 1; +    } + +    if (float32_lt(fsrc, fsrcb, &FP_STATUS)) { +        ctx->lt = 1; +    } +    if (float32_le(fsrc, fsrcb, &FP_STATUS)) { +        ctx->le = 1; +    } + +    if (float32_lt(fsrcb, fsrc, &FP_STATUS)) { +        ctx->gt = 1; +    } +    if (float32_le(fsrcb, fsrc, &FP_STATUS)) { +        ctx->ge = 1; +    } + +    if (float32_unordered(fsrc, fsrcb, &FP_STATUS)) { +        ctx->unordered = 1; +    } +} + +static uint64_t fsingle_calc(FPUTLGState *fpu, +                             float32 fsrc, float32 fsrcb, +                             float32 (*calc)(float32, float32, float_status *)) +{ +    TileGXFPCtx ctx = {0}; + +    ctx.type = TILEGX_F_TCALC; +    ctx.data = fpu->pos32; +    fpu->val32s[fpu->pos32++] = calc(fsrc, fsrcb, &FP_STATUS); +    if (fpu->pos32>= TILEGX_F_COUNT) { +        fpu->pos32 = 0; +    } +    fsingle_ana(fpu, fsrc, fsrcb, &ctx); + +    return ctx_to_uint64(ctx); +} + +uint64_t helper_fsingle_add1(CPUTLGState *env, uint64_t rsrc, uint64_t rsrcb) +{ +    FPUTLGState *fpu = &env->fpu; +    return fsingle_calc(fpu, int64_to_float32(rsrc, &FP_STATUS), +                        int64_to_float32(rsrcb, &FP_STATUS), +                        float32_add); +} + +uint64_t helper_fsingle_sub1(CPUTLGState *env, uint64_t rsrc, uint64_t rsrcb) +{ +    FPUTLGState *fpu = &env->fpu; +    return fsingle_calc(fpu, int64_to_float32(rsrc, &FP_STATUS), +                        int64_to_float32(rsrcb, &FP_STATUS), +                        float32_sub); +} + +uint64_t helper_fsingle_mul1(CPUTLGState *env, uint64_t rsrc, uint64_t rsrcb) +{ +    FPUTLGState *fpu = &env->fpu; +#if 0 +    { +        float32 v; +        fprintf(stderr, "\ncall helper_fsingle_mul1(), %lx, %lx\n", rsrc, rsrcb); +        v = float32_mul(int64_to_float32(rsrc, &FP_STATUS), +                        int64_to_float32(rsrcb, &FP_STATUS), +                        &FP_STATUS); +        fprintf(stderr, "result: %lx.\n", float32_to_int64(v, &FP_STATUS)); +    } +#endif +    return fsingle_calc(fpu, int64_to_float32(rsrc, &FP_STATUS), +                        int64_to_float32(rsrcb, &FP_STATUS), +                        float32_mul); +} + +uint64_t helper_fsingle_pack2(CPUTLGState *env, uint64_t rsrc) +{ +    FPUTLGState *fpu = &env->fpu; +    TileGXFPCtx ctx = uint64_to_ctx(rsrc); + +    if (ctx.type == TILEGX_F_TCALC) { +        if (ctx.data>= TILEGX_F_COUNT) { +            helper_exception(env, TILEGX_EXCP_OPCODE_INVALID_VALUE); +        } +        return float32_to_int32(fpu->val32s[ctx.data], &FP_STATUS); +    } + +    switch (ctx.exp) { +    case 0x9e: +        return float32_to_int64(uint32_to_float32(ctx.data, &FP_STATUS), +                                &FP_STATUS); +    case 0x49e: +        return float32_to_int64(int32_to_float32(ctx.data | SIGNBIT32, +                                                 &FP_STATUS), +                                 &FP_STATUS); +    default: +        fprintf(stderr, "\nUIMP: in helper_fsingle_pack2().\n"); +        helper_exception(env, TILEGX_EXCP_OPCODE_UNIMPLEMENTED); +        return 0; +    } +} diff --git a/target-tilegx/helper.h b/target-tilegx/helper.h index 9281d0f..9f4fc8a 100644 --- a/target-tilegx/helper.h +++ b/target-tilegx/helper.h @@ -24,3 +24,12 @@ DEF_HELPER_FLAGS_2(v1shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64)  DEF_HELPER_FLAGS_2(v2shl, TCG_CALL_NO_RWG_SE, i64, i64, i64)  DEF_HELPER_FLAGS_2(v2shru, TCG_CALL_NO_RWG_SE, i64, i64, i64)  DEF_HELPER_FLAGS_2(v2shrs, TCG_CALL_NO_RWG_SE, i64, i64, i64) + +DEF_HELPER_3(fsingle_add1, i64, env, i64, i64) +DEF_HELPER_3(fsingle_sub1, i64, env, i64, i64) +DEF_HELPER_3(fsingle_mul1, i64, env, i64, i64) +DEF_HELPER_2(fsingle_pack2, i64, env, i64) +DEF_HELPER_3(fdouble_add_flags, i64, env, i64, i64) +DEF_HELPER_3(fdouble_sub_flags, i64, env, i64, i64) +DEF_HELPER_3(fdouble_mul_flags, i64, env, i64, i64) +DEF_HELPER_3(fdouble_pack1, i64, env, i64, i64) diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c index 2913902..c65e980 100644 --- a/target-tilegx/translate.c +++ b/target-tilegx/translate.c @@ -616,6 +616,11 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,          qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", mnemonic,                        reg_names[dest], reg_names[srca]);          return ret; + +    case OE_RR_X0(FSINGLE_PACK1): +    case OE_RR_Y0(FSINGLE_PACK1): +        mnemonic = "fsingle_pack1"; +        goto done2;      }        tdest = dest_gr(dc, dest); @@ -632,9 +637,6 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,          gen_helper_cnttz(tdest, tsrca);          mnemonic = "cnttz";          break; -    case OE_RR_X0(FSINGLE_PACK1): -    case OE_RR_Y0(FSINGLE_PACK1): -        return TILEGX_EXCP_OPCODE_UNIMPLEMENTED;      case OE_RR_X1(LD1S):          memop = MO_SB;          mnemonic = "ld1s"; /* prefetch_l1_fault */ @@ -736,6 +738,7 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,          return TILEGX_EXCP_OPCODE_UNKNOWN;      }   +done2:      qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s", mnemonic,                    reg_names[dest], reg_names[srca]);      return ret; @@ -744,13 +747,33 @@ static TileExcp gen_rr_opcode(DisasContext *dc, unsigned opext,  static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,                                 unsigned dest, unsigned srca, unsigned srcb)  { -    TCGv tdest = dest_gr(dc, dest); -    TCGv tsrca = load_gr(dc, srca); -    TCGv tsrcb = load_gr(dc, srcb); +    TCGv tdest, tsrca, tsrcb;      TCGv t0;      const char *mnemonic;        switch (opext) { +    case OE_RRR(FSINGLE_ADDSUB2, 0, X0): +        mnemonic = "fsingle_addsub2"; +        goto done2; +    case OE_RRR(FDOUBLE_ADDSUB, 0, X0): +        mnemonic = "fdouble_addsub"; +        goto done2; +    case OE_RRR(FDOUBLE_PACK2, 0, X0): +        mnemonic = "fdouble_pack2"; +        goto done2; +    case OE_RRR(FDOUBLE_UNPACK_MAX, 0, X0): +        mnemonic = "fdouble_unpack_max"; +        goto done2; +    case OE_RRR(FDOUBLE_UNPACK_MIN, 0, X0): +        mnemonic = "fdouble_unpack_min"; +        goto done2; +    } + +    tdest = dest_gr(dc, dest); +    tsrca = load_gr(dc, srca); +    tsrcb = load_gr(dc, srcb); + +    switch (opext) {      case OE_RRR(ADDXSC, 0, X0):      case OE_RRR(ADDXSC, 0, X1):          gen_saturate_op(tdest, tsrca, tsrcb, tcg_gen_add_tl); @@ -907,15 +930,22 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,                          TILEGX_EXCP_OPCODE_EXCH);          mnemonic = "exch";          break; -    case OE_RRR(FDOUBLE_ADDSUB, 0, X0):      case OE_RRR(FDOUBLE_ADD_FLAGS, 0, X0): +        gen_helper_fdouble_add_flags(tdest, cpu_env, tsrca, tsrcb); +        mnemonic = "fdouble_add_flags"; +        break;      case OE_RRR(FDOUBLE_MUL_FLAGS, 0, X0): +        gen_helper_fdouble_mul_flags(tdest, cpu_env, tsrca, tsrcb); +        mnemonic = "fdouble_mul_flags"; +        break;      case OE_RRR(FDOUBLE_PACK1, 0, X0): -    case OE_RRR(FDOUBLE_PACK2, 0, X0): +        gen_helper_fdouble_pack1(tdest, cpu_env, tsrca, tsrcb); +        mnemonic = "fdouble_pack1"; +        break;      case OE_RRR(FDOUBLE_SUB_FLAGS, 0, X0): -    case OE_RRR(FDOUBLE_UNPACK_MAX, 0, X0): -    case OE_RRR(FDOUBLE_UNPACK_MIN, 0, X0): -        return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +        gen_helper_fdouble_sub_flags(tdest, cpu_env, tsrca, tsrcb); +        mnemonic = "fdouble_sub_flags"; +        break;      case OE_RRR(FETCHADD4, 0, X1):          gen_atomic_excp(dc, dest, tdest, tsrca, tsrcb,                          TILEGX_EXCP_OPCODE_FETCHADD4); @@ -957,12 +987,25 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,          mnemonic = "fetchor";          break;      case OE_RRR(FSINGLE_ADD1, 0, X0): -    case OE_RRR(FSINGLE_ADDSUB2, 0, X0): +        gen_helper_fsingle_add1(tdest, cpu_env, tsrca, tsrcb); +        mnemonic = "fsingle_add1"; +        break;      case OE_RRR(FSINGLE_MUL1, 0, X0): +        gen_helper_fsingle_mul1(tdest, cpu_env, tsrca, tsrcb); +        mnemonic = "fsingle_mul1"; +        break;      case OE_RRR(FSINGLE_MUL2, 0, X0): +        tcg_gen_mov_i64(tdest, tsrca); +        mnemonic = "fsingle_mul2"; +        break;      case OE_RRR(FSINGLE_PACK2, 0, X0): +        gen_helper_fsingle_pack2(tdest, cpu_env, tsrca); +        mnemonic = "fsingle_pack2"; +        break;      case OE_RRR(FSINGLE_SUB1, 0, X0): -        return TILEGX_EXCP_OPCODE_UNIMPLEMENTED; +        gen_helper_fsingle_sub1(tdest, cpu_env, tsrca, tsrcb); +        mnemonic = "fsingle_sub1"; +        break;      case OE_RRR(MNZ, 0, X0):      case OE_RRR(MNZ, 0, X1):      case OE_RRR(MNZ, 4, Y0): @@ -1466,6 +1509,7 @@ static TileExcp gen_rrr_opcode(DisasContext *dc, unsigned opext,          return TILEGX_EXCP_OPCODE_UNKNOWN;      }   +done2:      qemu_log_mask(CPU_LOG_TB_IN_ASM, "%s %s, %s, %s", mnemonic,                    reg_names[dest], reg_names[srca], reg_names[srcb]);      return TILEGX_EXCP_NONE;