From patchwork Fri Dec 25 14:19:52 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 10132 Received: (qmail 9012 invoked by alias); 25 Dec 2015 14:20:03 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 8997 invoked by uid 89); 25 Dec 2015 14:20:02 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.8 required=5.0 tests=AWL, BAYES_50, RCVD_IN_DNSWL_LOW, SPF_SOFTFAIL autolearn=no version=3.3.2 spammy=356, Normal, 2.6.1, 0xffffffff X-HELO: mail2.asahi-net.or.jp Received: from mail2.asahi-net.or.jp (HELO mail2.asahi-net.or.jp) (202.224.39.198) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 25 Dec 2015 14:19:58 +0000 Received: from sa76r4 (y081184.ppp.asahi-net.or.jp [118.243.81.184]) by mail2.asahi-net.or.jp (Postfix) with ESMTP id 8A53561A6; Fri, 25 Dec 2015 23:19:55 +0900 (JST) Received: from localhost (localhost [127.0.0.1]) by sa76r4 (Postfix) with ESMTP id 8D21F1076A; Fri, 25 Dec 2015 23:19:55 +0900 (JST) Received: from sa76r4 ([127.0.0.1]) by localhost (sa76r4.localdomain [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id HzycJRNVVIDm; Fri, 25 Dec 2015 23:19:55 +0900 (JST) Received: by sa76r4 (Postfix, from userid 1000) id 6FEA110A5B; Fri, 25 Dec 2015 23:19:55 +0900 (JST) From: Yoshinori Sato To: gdb-patches@sourceware.org Cc: Yoshinori Sato Subject: [PATCH][RX] v2 instructions support Date: Fri, 25 Dec 2015 23:19:52 +0900 Message-Id: <1451053193-27204-1-git-send-email-ysato@users.sourceforge.jp> X-IsSubscribed: yes include/gdb/ChangeLog * sim-rx.h: Add v2 enhanced registers. sim/rx/ChangeLog * Makefile.in: Add libm. * cpu.h(acc_t): extend to 96bit. (regs_type): Add v2 registers. (extb): New define. (li): Likewise. (acc0): Rename from acc64. (acc1): New define. (acchi,accmi,acclo): Remove. (get_acc): New function. (put_acc): Likewise. (get_reg64): Remove. (put_reg64): Likewise. * fpu.c(FP_Type): Add unique prefix. (fp_explode): Likewise. (fp_implode): Likewise. (double_to_fp): Likewise. (check_exceptions): Likewise. (rxfp_ftoi): Likewise. (check_exceptions): FP_ExceptionCases to const. (ex_add_tab): Likewise. (ex_sub_tab): Likewise. (ex_mul_tab): Likewise. (ex_div_tab): Likewise. (ex_cmp_tab): Likewise. (rx_sqrt_tab): New. (rxfp_fsqrt): New. (rxfp_ftou): New. (rxfp_utof): New. * fpu.h: Add new function prototype. * gdb-if.c(reg_size): New registers support. (sim_fetch_register): Likewise. (sim_store_register): Likewise. * reg.c(reg_names): Add new registers. * rx.c(id_names): Add new instructions. (FLOAT_OP): 3operands support. (MULADD): New. (MULSUB): New. (MULACC): New. (RAC): New. (RXO_emaca): New. (RXO_emsba): New. (RXO_emula): New. (RXO_fsqrt): New. (RXO_ftou): New. (RXO_machi): Use MULADD. (RXO_maclo): Likewise. (RXO_maclh): New. (RXO_movli): New. (RXO_movco): New. (RXO_msbhi): New. (RXO_msblo): New. (RXO_msblh): New. (RXO_mulhi): Use MULACC. (RXO_mullo): Likewise. (RXO_mullh): New. (RXO_mvfachi): New acc support. (RXO_mvfaclo): Likewise. (RXO_mvfacmi): Likewise. (RXO_mvfacgu): New. (RXO_mvtachi): New acc support. (RXO_mvtaclo): New acc support. (RXO_mvtacgu): New. (RXO_racw): Use RAC. (RXO_rdacw): New. (RXO_racl): New. (RXO_rdacl): New. (RXO_rte): Add li clear. (RXO_utof): New. --- include/gdb/sim-rx.h | 4 +- sim/rx/Makefile.in | 1 + sim/rx/cpu.h | 24 +++-- sim/rx/fpu.c | 256 +++++++++++++++++++++++++++++++++++++++-------- sim/rx/fpu.h | 3 + sim/rx/gdb-if.c | 70 +++++++++++-- sim/rx/reg.c | 97 ++++++++---------- sim/rx/rx.c | 278 +++++++++++++++++++++++++++++++++++++++++++-------- 8 files changed, 574 insertions(+), 159 deletions(-) diff --git a/include/gdb/sim-rx.h b/include/gdb/sim-rx.h index 40e18c1..b55c902 100644 --- a/include/gdb/sim-rx.h +++ b/include/gdb/sim-rx.h @@ -49,7 +49,9 @@ enum sim_rx_regnum sim_rx_bpc_regnum, sim_rx_fintv_regnum, sim_rx_fpsw_regnum, - sim_rx_acc_regnum, + sim_rx_acc0_regnum, + sim_rx_extb_regnum, + sim_rx_acc1_regnum, sim_rx_num_regs }; diff --git a/sim/rx/Makefile.in b/sim/rx/Makefile.in index 64d9f3c..73475fe 100644 --- a/sim/rx/Makefile.in +++ b/sim/rx/Makefile.in @@ -40,6 +40,7 @@ SIM_OBJS = \ $(ENDLIST) LIBS = $B/bfd/libbfd.a $B/libiberty/libiberty.a +SIM_EXTRA_LIBS = -lm ## COMMON_POST_CONFIG_FRAG diff --git a/sim/rx/cpu.h b/sim/rx/cpu.h index 9a82e5e..45e6612 100644 --- a/sim/rx/cpu.h +++ b/sim/rx/cpu.h @@ -35,6 +35,12 @@ extern int rx_big_endian; typedef struct { + SI hi; + DI lo; +} acc_t; + +typedef struct +{ SI r[16]; SI r_psw; @@ -51,8 +57,8 @@ typedef struct SI r_isp; SI r_fintv; SI r_intb; - SI r__reserved_cr_13; - SI r__reserved_cr_14; + SI r_extb; + SI r_li; SI r__reserved_cr_15; SI r__reserved_cr_16; @@ -75,7 +81,7 @@ typedef struct SI r_temp; - DI r_acc; + acc_t r_acc[2]; #ifdef CYCLE_ACCURATE /* If set, RTS/RTSD take 2 fewer cycles. */ @@ -105,12 +111,12 @@ typedef struct #define isp 26 #define fintv 27 #define intb 28 +#define extb 29 +#define li 30 #define r_temp_idx 48 -#define acc64 49 -#define acchi 50 -#define accmi 51 -#define acclo 52 +#define acc0 49 +#define acc1 50 extern regs_type regs; @@ -170,9 +176,9 @@ void init_regs (void); void stack_heap_stats (void); void set_pointer_width (int bytes); unsigned int get_reg (int id); -unsigned long long get_reg64 (int id); +void get_acc (int id, acc_t *valuel); void put_reg (int id, unsigned int value); -void put_reg64 (int id, unsigned long long value); +void put_acc (int id, acc_t *value); void set_flags (int mask, int newbits); void set_oszc (long long value, int bytes, int c); diff --git a/sim/rx/fpu.c b/sim/rx/fpu.c index 9e4a103..97cde4c 100644 --- a/sim/rx/fpu.c +++ b/sim/rx/fpu.c @@ -21,6 +21,7 @@ along with this program. If not, see . */ #include "config.h" #include #include +#include #include "cpu.h" #include "fpu.h" @@ -77,14 +78,14 @@ fp_raise (int mask) /* We classify all numbers as one of these. They correspond to the rows/colums in the exception tables. */ typedef enum { - FP_NORMAL, - FP_PZERO, - FP_NZERO, - FP_PINFINITY, - FP_NINFINITY, - FP_DENORMAL, - FP_QNAN, - FP_SNAN + RX_FP_NORMAL, + RX_FP_PZERO, + RX_FP_NZERO, + RX_FP_PINFINITY, + RX_FP_NINFINITY, + RX_FP_DENORMAL, + RX_FP_QNAN, + RX_FP_SNAN } FP_Type; #if defined DEBUG0 @@ -127,24 +128,24 @@ fp_explode (fp_t f, FP_Parts *p) if (regs.r_fpsw & FPSWBITS_DN) mant = 0; if (mant) - p->type = FP_DENORMAL; + p->type = RX_FP_DENORMAL; else { p->mant = 0; - p->type = sign ? FP_NZERO : FP_PZERO; + p->type = sign ? RX_FP_NZERO : RX_FP_PZERO; } } else if (p->exp == EXP_INF) { if (mant == 0) - p->type = sign ? FP_NINFINITY : FP_PINFINITY; + p->type = sign ? RX_FP_NINFINITY : RX_FP_PINFINITY; else if (mant & 0x00400000UL) - p->type = FP_QNAN; + p->type = RX_FP_QNAN; else - p->type = FP_SNAN; + p->type = RX_FP_SNAN; } else - p->type = FP_NORMAL; + p->type = RX_FP_NORMAL; } static fp_t @@ -155,7 +156,7 @@ fp_implode (FP_Parts *p) exp = p->exp + EXP_BIAS; mant = p->mant; /*printf("implode: exp %d mant 0x%x\n", exp, mant);*/ - if (p->type == FP_NORMAL) + if (p->type == RX_FP_NORMAL) { while (mant && exp > 0 @@ -303,7 +304,7 @@ double_to_fp (double d, FP_Parts *p) p->exp = exp; p->mant = u.ll >> (52-23) & 0x007fffffUL; p->mant |= 0x00800000UL; - p->type = FP_NORMAL; + p->type = RX_FP_NORMAL; if (u.ll & 0x1fffffffULL) { @@ -356,19 +357,19 @@ static const char *ex_names[] = { FALSE, the caller should do the "normal" operation. */ int check_exceptions (FP_Parts *a, FP_Parts *b, fp_t *c, - FP_ExceptionCases ex_tab[5][5], + const FP_ExceptionCases ex_tab[5][5], FP_ExceptionCases *case_ret) { FP_ExceptionCases fpec; - if (a->type == FP_SNAN - || b->type == FP_SNAN) + if (a->type == RX_FP_SNAN + || b->type == RX_FP_SNAN) fpec = eIn; - else if (a->type == FP_QNAN - || b->type == FP_QNAN) + else if (a->type == RX_FP_QNAN + || b->type == RX_FP_QNAN) fpec = eQN; - else if (a->type == FP_DENORMAL - || b->type == FP_DENORMAL) + else if (a->type == RX_FP_DENORMAL + || b->type == RX_FP_DENORMAL) fpec = eUn; else fpec = ex_tab[(int)(a->type)][(int)(b->type)]; @@ -415,14 +416,14 @@ check_exceptions (FP_Parts *a, FP_Parts *b, fp_t *c, return 1; case eQN: /* Quiet NANs */ - if (a->type == FP_QNAN) + if (a->type == RX_FP_QNAN) *c = a->orig_value; else *c = b->orig_value; return 1; case eSN: /* Signalling NANs */ - if (a->type == FP_SNAN) + if (a->type == RX_FP_SNAN) *c = a->orig_value; else *c = b->orig_value; @@ -431,9 +432,9 @@ check_exceptions (FP_Parts *a, FP_Parts *b, fp_t *c, case eIn: /* Invalid. */ FP_RAISE (V); - if (a->type == FP_SNAN) + if (a->type == RX_FP_SNAN) *c = a->orig_value | 0x00400000; - else if (a->type == FP_SNAN) + else if (a->type == RX_FP_SNAN) *c = b->orig_value | 0x00400000; else *c = 0x7fc00000; @@ -461,7 +462,7 @@ check_exceptions (FP_Parts *a, FP_Parts *b, fp_t *c, handled. The DN=0 case is first, followed by the DN=1 case, with each table using the following layout: */ -static FP_ExceptionCases ex_add_tab[5][5] = { +static const FP_ExceptionCases ex_add_tab[5][5] = { /* N +0 -0 +In -In */ { eNR, eNR, eNR, ePI, eNI }, /* Normal */ { eNR, ePZ, eRZ, ePI, eNI }, /* +0 */ @@ -483,14 +484,14 @@ rxfp_add (fp_t fa, fp_t fb) da = fp_to_double (&a); db = fp_to_double (&b); - tprintf("%g + %g = %g\n", da, db, da+db); + tprintf ("%g + %g = %g\n", da, db, da+db); double_to_fp (da+db, &c); rv = fp_implode (&c); return rv; } -static FP_ExceptionCases ex_sub_tab[5][5] = { +static const FP_ExceptionCases ex_sub_tab[5][5] = { /* N +0 -0 +In -In */ { eNR, eNR, eNR, eNI, ePI }, /* Normal */ { eNR, eRZ, ePZ, eNI, ePI }, /* +0 */ @@ -520,7 +521,7 @@ rxfp_sub (fp_t fa, fp_t fb) return rv; } -static FP_ExceptionCases ex_mul_tab[5][5] = { +static const FP_ExceptionCases ex_mul_tab[5][5] = { /* N +0 -0 +In -In */ { eNR, eNR, eNR, eSI, eSI }, /* Normal */ { eNR, ePZ, eNZ, eIn, eIn }, /* +0 */ @@ -550,7 +551,7 @@ rxfp_mul (fp_t fa, fp_t fb) return rv; } -static FP_ExceptionCases ex_div_tab[5][5] = { +static const FP_ExceptionCases ex_div_tab[5][5] = { /* N +0 -0 +In -In */ { eNR, eDZ, eDZ, eSZ, eSZ }, /* Normal */ { eSZ, eIn, eIn, ePZ, eNZ }, /* +0 */ @@ -580,7 +581,7 @@ rxfp_div (fp_t fa, fp_t fb) return rv; } -static FP_ExceptionCases ex_cmp_tab[5][5] = { +static const FP_ExceptionCases ex_cmp_tab[5][5] = { /* N +0 -0 +In -In */ { eNR, eNR, eNR, eLT, eGT }, /* Normal */ { eNR, eEQ, eEQ, eLT, eGT }, /* +0 */ @@ -654,22 +655,22 @@ rxfp_ftoi (fp_t fa, int round_mode) switch (a.type) { - case FP_NORMAL: + case RX_FP_NORMAL: break; - case FP_PZERO: - case FP_NZERO: + case RX_FP_PZERO: + case RX_FP_NZERO: return 0; - case FP_PINFINITY: + case RX_FP_PINFINITY: FP_RAISE (V); return 0x7fffffffL; - case FP_NINFINITY: + case RX_FP_NINFINITY: FP_RAISE (V); return 0x80000000L; - case FP_DENORMAL: + case RX_FP_DENORMAL: FP_RAISE (E); return 0; - case FP_QNAN: - case FP_SNAN: + case RX_FP_QNAN: + case RX_FP_SNAN: FP_RAISE (V); return sign ? 0x80000000U : 0x7fffffff; } @@ -790,3 +791,172 @@ rxfp_itof (long fa, int round_mode) return rv; } +static const FP_ExceptionCases ex_sqrt_tab[5][5] = { + /* N +0 -0 +In -In */ + { eNR, eDZ, eDZ, eSZ, eSZ }, /* Normal */ + { eSZ, eIn, eIn, ePZ, eNZ }, /* +0 */ + { eSZ, eIn, eIn, eNZ, ePZ }, /* -0 */ + { eSI, ePI, eNI, eIn, eIn }, /* +Inf */ + { eSI, eNI, ePI, eIn, eIn }, /* -Inf */ +}; + +fp_t +rxfp_fsqrt (fp_t fa) +{ + FP_Parts a, b, c; + fp_t rv; + double da; + + fp_explode (fa, &a); + fp_explode (fa, &b); + CHECK_EXCEPTIONS (a, b, rv, ex_sqrt_tab); + + da = fp_to_double (&a); + tprintf("sqrt(%g) = %g\n", da, sqrt(da)); + + double_to_fp (sqrt(da), &c); + rv = fp_implode (&c); + + return rv; +} + +unsigned long +rxfp_ftou (fp_t fa, int round_mode) +{ + FP_Parts a; + fp_t rv; + int sign; + int whole_bits, frac_bits; + + fp_explode (fa, &a); + sign = fa & 0x80000000UL; + + switch (a.type) + { + case RX_FP_NORMAL: + break; + case RX_FP_PZERO: + case RX_FP_NZERO: + return 0; + case RX_FP_PINFINITY: + FP_RAISE (V); + return 0xffffffffL; + case RX_FP_NINFINITY: + FP_RAISE (V); + return 0x00000000L; + case RX_FP_DENORMAL: + FP_RAISE (E); + return 0; + case RX_FP_QNAN: + case RX_FP_SNAN: + FP_RAISE (V); + return sign ? 0x00000000 : 0xffffffff; + } + + if (sign) + return 0; + if (a.exp >= 32) + { + FP_RAISE (V); + return 0xffffffff; + } + + a.exp -= 23; + + if (a.exp <= -25) + { + /* Less than 0.49999. */ + frac_bits = a.mant; + whole_bits = 0; + } + else if (a.exp < 0) + { + frac_bits = a.mant << (33 + a.exp); + whole_bits = a.mant >> (-a.exp); + } + else + { + frac_bits = 0; + whole_bits = a.mant << a.exp; + } + + if (frac_bits) + { + switch (round_mode & 3) + { + case FPRM_NEAREST: + if (frac_bits & 0x80000000UL) + whole_bits ++; + break; + case FPRM_ZERO: + case FPRM_NINF: + break; + case FPRM_PINF: + if (!sign) + whole_bits ++; + break; + } + } + + rv = whole_bits; + + return rv; +} + +fp_t +rxfp_utof (unsigned long fa, int round_mode) +{ + fp_t rv; + int sign = 0; + unsigned int frac_bits; + volatile unsigned int whole_bits; + FP_Parts a; + + if (fa == 0) + return PLUS_ZERO; + + a.sign = 1; + + whole_bits = fa; + a.exp = 31; + + while (! (whole_bits & 0x80000000UL)) + { + a.exp --; + whole_bits <<= 1; + } + frac_bits = whole_bits & 0xff; + whole_bits = whole_bits >> 8; + + if (frac_bits) + { + /* We must round. */ + switch (round_mode & 3) + { + case FPRM_NEAREST: + if (frac_bits & 0x80) + whole_bits ++; + break; + case FPRM_ZERO: + break; + case FPRM_PINF: + if (!sign) + whole_bits ++; + break; + case FPRM_NINF: + if (sign) + whole_bits ++; + break; + } + } + + a.mant = whole_bits; + if (whole_bits & 0xff000000UL) + { + a.mant >>= 1; + a.exp ++; + } + + rv = fp_implode (&a); + return rv; +} diff --git a/sim/rx/fpu.h b/sim/rx/fpu.h index a20c2a0..dcddf11 100644 --- a/sim/rx/fpu.h +++ b/sim/rx/fpu.h @@ -27,3 +27,6 @@ extern fp_t rxfp_div (fp_t fa, fp_t fb); extern void rxfp_cmp (fp_t fa, fp_t fb); extern long rxfp_ftoi (fp_t fa, int round_mode); extern fp_t rxfp_itof (long fa, int round_mode); +extern fp_t rxfp_fsqrt (fp_t fa); +extern unsigned long rxfp_ftou (fp_t fa, int round_mode); +extern fp_t rxfp_utof (unsigned long fa, int round_mode); diff --git a/sim/rx/gdb-if.c b/sim/rx/gdb-if.c index 762c3d2..ebf54ee 100644 --- a/sim/rx/gdb-if.c +++ b/sim/rx/gdb-if.c @@ -387,6 +387,9 @@ reg_size (enum sim_rx_regnum regno) case sim_rx_intb_regnum: size = sizeof (regs.r_intb); break; + case sim_rx_extb_regnum: + size = sizeof (regs.r_extb); + break; case sim_rx_pc_regnum: size = sizeof (regs.r_pc); break; @@ -405,8 +408,9 @@ reg_size (enum sim_rx_regnum regno) case sim_rx_fpsw_regnum: size = sizeof (regs.r_fpsw); break; - case sim_rx_acc_regnum: - size = sizeof (regs.r_acc); + case sim_rx_acc0_regnum: + case sim_rx_acc1_regnum: + size = 8; break; default: size = 0; @@ -490,6 +494,9 @@ sim_fetch_register (SIM_DESC sd, int regno, unsigned char *buf, int length) case sim_rx_intb_regnum: val = get_reg (intb); break; + case sim_rx_extb_regnum: + val = get_reg (extb); + break; case sim_rx_pc_regnum: val = get_reg (pc); break; @@ -508,9 +515,26 @@ sim_fetch_register (SIM_DESC sd, int regno, unsigned char *buf, int length) case sim_rx_fpsw_regnum: val = get_reg (fpsw); break; - case sim_rx_acc_regnum: - val = ((DI) get_reg (acchi) << 32) | get_reg (acclo); - break; + case sim_rx_acc0_regnum: + { + acc_t acc; + get_acc (0, &acc); + if (rx_big_endian) + put_be (buf, 8, acc.lo); + else + put_le (buf, 8, acc.lo); + return 8; + } + case sim_rx_acc1_regnum: + { + acc_t acc; + get_acc (1, &acc); + if (rx_big_endian) + put_be (buf, 8, acc.lo); + else + put_le (buf, 8, acc.lo); + return 8; + } default: fprintf (stderr, "rx minisim: unrecognized register number: %d\n", regno); @@ -623,10 +647,38 @@ sim_store_register (SIM_DESC sd, int regno, unsigned char *buf, int length) case sim_rx_fpsw_regnum: put_reg (fpsw, val); break; - case sim_rx_acc_regnum: - put_reg (acclo, val & 0xffffffff); - put_reg (acchi, (val >> 32) & 0xffffffff); - break; + case sim_rx_acc0_regnum: + { + acc_t acc; + if (rx_big_endian) + { + acc.hi = get_be (buf, 8); + acc.lo = get_be (buf + 8, 8); + } + else + { + acc.lo = get_le (buf, 8); + acc.hi = get_le (buf + 8, 8); + } + put_acc (0, &acc); + break; + } + case sim_rx_acc1_regnum: + { + acc_t acc; + if (rx_big_endian) + { + acc.hi = get_be (buf, 8); + acc.lo = get_be (buf + 8, 8); + } + else + { + acc.lo = get_le (buf, 8); + acc.hi = get_le (buf + 8, 8); + } + put_acc (1, &acc); + break; + } default: fprintf (stderr, "rx minisim: unrecognized register number: %d\n", regno); diff --git a/sim/rx/reg.c b/sim/rx/reg.c index 6effe4b..d354b7d 100644 --- a/sim/rx/reg.c +++ b/sim/rx/reg.c @@ -45,15 +45,15 @@ unsigned int heapbottom = 0; unsigned int heaptop = 0; char *reg_names[] = { - /* general registers */ + /* general registers */ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - /* control register */ + /* control registers */ "psw", "pc", "usp", "fpsw", "RES", "RES", "RES", "RES", - "bpsw", "bpc", "isp", "fintv", "intb", "RES", "RES", "RES", + "bpsw", "bpc", "isp", "fintv", "intb", "extb", "li", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", - "temp", "acc", "acchi", "accmi", "acclo" + "temp", "acc0", "acc1", }; unsigned int b2mask[] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff }; @@ -69,6 +69,9 @@ init_regs (void) memset (®s, 0, sizeof (regs)); memset (&oldregs, 0, sizeof (oldregs)); + regs.r_extb = 0xffffff80; + oldregs.r_extb = 0xffffff80; + #ifdef CYCLE_ACCURATE regs.rt = -1; oldregs.rt = -1; @@ -102,16 +105,14 @@ get_reg_i (int id) return regs.r_fintv; case intb: return regs.r_intb; + case extb: + return regs.r_extb; + case li: + return regs.r_li; case pc: return regs.r_pc; case r_temp_idx: return regs.r_temp; - case acchi: - return (SI)(regs.r_acc >> 32); - case accmi: - return (SI)(regs.r_acc >> 16); - case acclo: - return (SI)regs.r_acc; } abort(); } @@ -125,25 +126,14 @@ get_reg (int id) return rv; } -static unsigned long long -get_reg64_i (int id) -{ - switch (id) - { - case acc64: - return regs.r_acc; - default: - abort (); - } -} - -unsigned long long -get_reg64 (int id) +void +get_acc (int id, acc_t *acc) { - unsigned long long rv = get_reg64_i (id); - if (trace > ((id != pc && id != sp) ? 0 : 1)) - printf ("get_reg (%s) = %016llx\n", reg_names[id], rv); - return rv; + if (id >= 2) + abort (); + *acc = regs.r_acc[id]; + if (trace > 0) + printf ("get_reg (%s) = %08x%016lx\n", reg_names[acc0 + id], acc->hi, acc->lo); } static int highest_sp = 0, lowest_sp = 0xffffff; @@ -203,18 +193,14 @@ put_reg (int id, unsigned int v) case intb: regs.r_intb = v; break; - case pc: - regs.r_pc = v; + case extb: + regs.r_extb = v; break; - - case acchi: - regs.r_acc = (regs.r_acc & 0xffffffffULL) | ((DI)v << 32); + case li: + regs.r_li = v; break; - case accmi: - regs.r_acc = (regs.r_acc & ~0xffffffff0000ULL) | ((DI)v << 16); - break; - case acclo: - regs.r_acc = (regs.r_acc & ~0xffffffffULL) | ((DI)v); + case pc: + regs.r_pc = v; break; case 0: /* Stack pointer is "in" R0. */ @@ -261,19 +247,15 @@ put_reg (int id, unsigned int v) } void -put_reg64 (int id, unsigned long long v) +put_acc (int id, acc_t *acc) { - if (trace > ((id != pc) ? 0 : 1)) - printf ("put_reg (%s) = %016llx\n", reg_names[id], v); - switch (id) - { - case acc64: - regs.r_acc = v; - break; - default: - abort (); - } + if (id >= 2) + abort (); + if (trace > 0) + printf ("put_reg (%s) = %08x%016lx\n", reg_names[acc0 + id], acc->hi, acc->lo); + + regs.r_acc[id] = *acc; } int @@ -545,14 +527,19 @@ trace_register_changes (void) oldregs.r_fpsw = regs.r_fpsw; } - if (oldregs.r_acc != regs.r_acc) + for (i = 0; i < 2; i++) { - if (tag) { printf (tag); tag = 0; } - printf(" acc %016llx:", oldregs.r_acc); - printf("%016llx", regs.r_acc); - oldregs.r_acc = regs.r_acc; + if (oldregs.r_acc[i].hi != regs.r_acc[i].hi || + oldregs.r_acc[i].lo != regs.r_acc[i].lo) + { + if (tag) { printf (tag); tag = 0; } + printf (" acc%d %08x%016lx:", i, oldregs.r_acc[i].hi, + oldregs.r_acc[i].lo); + printf ("%08x%016lx", regs.r_acc[i].hi, + oldregs.r_acc[i].lo); + oldregs.r_acc[i] = regs.r_acc[i]; + } } - if (tag == 0) printf ("\033[0m\n"); } diff --git a/sim/rx/rx.c b/sim/rx/rx.c index e48f6c8..8c87626 100644 --- a/sim/rx/rx.c +++ b/sim/rx/rx.c @@ -137,6 +137,25 @@ static const char * id_names[] = { "RXO_wait", "RXO_sccnd", /* d = cond(s) ? 1 : 0 */ + + "RXO_fsqrt", + "RXO_ftou", + "RXO_utof", + "RXO_movco", + "RXO_movli", + "RXO_emaca", + "RXO_emsba", + "RXO_emula", + "RXO_maclh", + "RXO_msbhi", + "RXO_msblh", + "RXO_msblo", + "RXO_mullh", + "RXO_mvfacgu", + "RXO_mvtacgu", + "RXO_racl", + "RXO_rdacl", + "RXO_rdacw", }; static const char * optype_names[] = { @@ -806,8 +825,8 @@ fop_fsub (fp_t s1, fp_t s2, fp_t *d) int do_store; \ fp_t fa, fb, fc; \ FPCLEAR(); \ - fb = GS (); \ - fa = GD (); \ + fb = US2 (); \ + fa = US1 (); \ do_store = fop_##func (fa, fb, &fc); \ tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \ FPCHECK(); \ @@ -929,6 +948,72 @@ op_is_memory (const RX_Opcode_Decoded *rd, int i) #define DO_RETURN(x) { longjmp (decode_jmp_buf, x); } +#define MULADD(val, s) \ +{ \ + get_acc (opcode->op[0].reg - 32, &acc); \ + sll = val; \ + sll <<= s; \ + if (sll > 0 && (unsigned long long)acc.lo > \ + (unsigned long long)(acc.lo + sll)) \ + acc.hi++; \ + else if (sll < 0 && (unsigned long long)(acc.lo + sll) > \ + (unsigned long long)acc.lo) \ + acc.hi--; \ + acc.lo += sll; \ + put_acc (opcode->op[0].reg - 32, &acc); \ + E1; \ + break; \ +} + +#define MULSUB(val, s) \ +{ \ + get_acc (opcode->op[0].reg - 32, &acc); \ + sll = val; \ + sll <<= s; \ + if (sll > 0 && (unsigned long long)(sll - acc.lo) > \ + (unsigned long long)acc.lo) \ + acc.hi--; \ + else if (sll < 0 && (unsigned long long)acc.lo > \ + (unsigned long long)(sll - acc.lo)) \ + acc.hi++; \ + acc.hi = (signed char)acc.hi; \ + acc.lo -= sll; \ + put_acc (opcode->op[0].reg - 32, &acc); \ + E1; \ + break; \ +} + +#define MULACC(val, s) \ +{ \ + sll = val; \ + sll <<= s; \ + acc.lo = sll; \ + acc.hi = (sll < 0)? -1 : 0; \ + put_acc (opcode->op[0].reg - 32, &acc); \ + E1; \ + break; \ +} + +#define RAC(add, pl, ml) \ +{ \ + get_acc (opcode->op[0].reg - 32, &acc); \ + ll = acc.lo << GS (); \ + ll += add; \ + if ((signed long long)ll > \ + (signed long long)0x00007fff00000000ULL) \ + ll = 0x00007fff00000000ULL; \ + else if ((signed long long)ll < \ + (signed long long)0xffff800000000000ULL) \ + ll = 0xffff800000000000ULL; \ + else \ + ll &= 0xffffffff00000000ULL; \ + acc.hi = ((signed long long)ll < 0) ? -1 : 0; \ + acc.lo = ll; \ + put_acc (opcode->op[0].reg - 32, &acc); \ + E1; \ + break; \ +} + int decode_opcode () { @@ -940,6 +1025,7 @@ decode_opcode () unsigned long opcode_pc; RX_Data rx_data; const RX_Opcode_Decoded *opcode; + acc_t acc; #ifdef CYCLE_STATS unsigned long long prev_cycle_count; #endif @@ -1216,6 +1302,12 @@ decode_opcode () } break; + case RXO_emaca: + MULADD((long long)GS2 () * (long long)GS (), 0) + + case RXO_emsba: + MULSUB((long long)GS2 () * (long long)GS (), 0) + case RXO_emul: ma = GD (); mb = GS (); @@ -1226,6 +1318,18 @@ decode_opcode () E2; break; + case RXO_emula: + ma = GS2 (); + mb = GS (); + acc.lo = (long long)ma * (long long)mb; + if (acc.lo < 0) + acc.hi = -1; + else + acc.hi = 0; + put_acc (opcode->op[0].reg - 32, &acc); + E (3); + break; + case RXO_emulu: uma = GD (); umb = GS (); @@ -1264,12 +1368,24 @@ decode_opcode () PRIVILEDGED (); regs.r_psw = regs.r_bpsw; regs.r_pc = regs.r_bpc; + regs.r_li = 0; #ifdef CYCLE_ACCURATE regs.fast_return = 0; cycles(3); #endif break; + case RXO_fsqrt: + ma = GS (); + FPCLEAR (); + mb = rxfp_fsqrt (ma); + FPCHECK (); + PD (mb); + tprintf ("(int) %g = %d\n", int2float(ma), mb); + set_sz (mb, 4); + E (16); + break; + case RXO_fsub: FLOAT_OP (fsub); E (4); @@ -1286,6 +1402,17 @@ decode_opcode () E (2); break; + case RXO_ftou: + ma = GS (); + FPCLEAR (); + mb = rxfp_ftou (ma, FPRM_ZERO); + FPCHECK (); + PD (mb); + tprintf ("(int) %g = %d\n", int2float(ma), mb); + set_sz (mb, 4); + E (2); + break; + case RXO_int: v = GS (); if (v == 255) @@ -1352,18 +1479,16 @@ decode_opcode () break; case RXO_machi: - ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16); - ll <<= 16; - put_reg64 (acc64, ll + regs.r_acc); - E1; - break; + MULADD((long long)(signed short)(GS() >> 16) * + (long long)(signed short)(GS2 () >> 16), 16) + + case RXO_maclh: + MULADD((long long)(signed short)(GS()) * + (long long)(signed short)(GS2 () >> 16), 16) case RXO_maclo: - ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ()); - ll <<= 16; - put_reg64 (acc64, ll + regs.r_acc); - E1; - break; + MULADD((long long)(signed short)(GS()) * + (long long)(signed short)(GS2 ()), 16) case RXO_max: mb = GS(); @@ -1457,6 +1582,36 @@ decode_opcode () cycles (1); break; + case RXO_movli: + PD (mem_get_si (GS ())); + regs.r_li = 1; + E1; + break; + + case RXO_movco: + if (regs.r_li == 1) + { + mem_put_si (GD (), GS ()); + PS (0); + } + else + PS (1); + regs.r_li = 0; + E1; + break; + + case RXO_msbhi: + MULSUB((long long)(signed short)(GS() >> 16) * + (long long)(signed short)(GS2 () >> 16), 16) + + case RXO_msblh: + MULSUB((long long)(signed short)(GS()) * + (long long)(signed short)(GS2 () >> 16), 16) + + case RXO_msblo: + MULSUB((long long)(signed short)(GS()) * + (long long)(signed short)(GS2 ()), 16) + case RXO_mul: v = US2 (); ll = (unsigned long long) US1() * (unsigned long long) v; @@ -1465,43 +1620,67 @@ decode_opcode () break; case RXO_mulhi: - v = GS2 (); - ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v >> 16); - ll <<= 16; - put_reg64 (acc64, ll); - E1; - break; + MULACC((long long)(signed short)(GS() >> 16) * + (long long)(signed short)(GS2 () >> 16), 16) + case RXO_mullh: + MULACC((long long)(signed short)(GS()) * + (long long)(signed short)(GS2 () >> 16), 16) case RXO_mullo: - v = GS2 (); - ll = (long long)(signed short)(GS()) * (long long)(signed short)(v); - ll <<= 16; - put_reg64 (acc64, ll); - E1; - break; + MULACC((long long)(signed short)(GS()) * + (long long)(signed short)(GS2 ()), 16) case RXO_mvfachi: - PD (get_reg (acchi)); + get_acc (opcode->op[1].reg - 32, &acc); + PD ((acc.lo << GS2 ()) >> 32); E1; break; case RXO_mvfaclo: - PD (get_reg (acclo)); + get_acc (opcode->op[1].reg - 32, &acc); + PD (acc.lo << GS2 ()); E1; break; case RXO_mvfacmi: - PD (get_reg (accmi)); + get_acc (opcode->op[1].reg - 32, &acc); + PD ((acc.lo << GS2 ()) >> 16); + E1; + break; + + case RXO_mvfacgu: + get_acc (opcode->op[1].reg - 32, &acc); + uma = (signed char)acc.hi; + umb = GS2 (); + if (umb) + { + uma <<= umb; + uma |= ((acc.lo >> (64 - umb)) & 3); + } + PD (uma); E1; break; case RXO_mvtachi: - put_reg (acchi, GS ()); + get_acc (opcode->op[0].reg - 32, &acc); + acc.lo &= ((1ULL << 32) - 1); + acc.lo |= (unsigned long long) GS () << 32ULL; + put_acc (opcode->op[0].reg - 32, &acc); E1; break; case RXO_mvtaclo: - put_reg (acclo, GS ()); + get_acc (opcode->op[0].reg - 32, &acc); + acc.lo &= ~((1ULL << 32ULL) - 1); + acc.lo |= (unsigned long) GS (); + put_acc (opcode->op[0].reg - 32, &acc); + E1; + break; + + case RXO_mvtacgu: + get_acc (opcode->op[0].reg - 32, &acc); + acc.hi = GS (); + put_acc (opcode->op[0].reg - 32, &acc); E1; break; @@ -1560,22 +1739,22 @@ decode_opcode () break; case RXO_racw: - ll = get_reg64 (acc64) << GS (); - ll += 0x80000000ULL; - if ((signed long long)ll > (signed long long)0x00007fff00000000ULL) - ll = 0x00007fff00000000ULL; - else if ((signed long long)ll < (signed long long)0xffff800000000000ULL) - ll = 0xffff800000000000ULL; - else - ll &= 0xffffffff00000000ULL; - put_reg64 (acc64, ll); - E1; - break; + RAC(0x80000000ULL, 0x00007fff00000000ULL, 0xffff800000000000ULL) + + case RXO_rdacw: + RAC(0, 0x00007fff00000000ULL, 0xffffffff80000000ULL) + + case RXO_racl: + RAC(0x80000000ULL, 0x7fffffff00000000ULL, 0xffffffff80000000ULL) + + case RXO_rdacl: + RAC(0, 0x7fffffff00000000ULL, 0xffff800000000000ULL) case RXO_rte: PRIVILEDGED (); regs.r_pc = poppc (); regs.r_psw = poppc (); + regs.r_li = 0; if (FLAG_PM) regs.r_psw |= FLAGBIT_U; #ifdef CYCLE_ACCURATE @@ -2130,6 +2309,21 @@ decode_opcode () set_zc (0, ((int)uma - (int)umb) >= 0); break; + case RXO_utof: + ma = GS (); + FPCLEAR (); + mb = rxfp_utof (ma, regs.r_fpsw); + FPCHECK (); + tprintf ("(float) %d = %x\n", ma, mb); + PD (mb); + if (mb) + set_flags (FLAGBIT_Z, 0); + else + set_flags (FLAGBIT_Z, FLAGBIT_Z); + set_flags (FLAGBIT_S, 0); + E (2); + break; + case RXO_wait: PRIVILEDGED (); regs.r_psw |= FLAGBIT_I;