From patchwork Mon Dec 21 17:34:56 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 10098 X-Patchwork-Delegate: vapier@gentoo.org Received: (qmail 123371 invoked by alias); 21 Dec 2015 17:35:38 -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 123362 invoked by uid 89); 21 Dec 2015 17:35:37 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.9 required=5.0 tests=AWL, BAYES_50, RCVD_IN_DNSWL_LOW, SPF_SOFTFAIL autolearn=no version=3.3.2 spammy=171, 356, enhanced, r14 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; Mon, 21 Dec 2015 17:35:35 +0000 Received: from sa76r4 (y081184.ppp.asahi-net.or.jp [118.243.81.184]) by mail2.asahi-net.or.jp (Postfix) with ESMTP id 59E1061C0; Tue, 22 Dec 2015 02:35:32 +0900 (JST) Received: from localhost (localhost [127.0.0.1]) by sa76r4 (Postfix) with ESMTP id 0B22AFDFE; Tue, 22 Dec 2015 02:35:32 +0900 (JST) Received: from sa76r4 ([127.0.0.1]) by localhost (sa76r4.localdomain [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id grffkefR9xng; Tue, 22 Dec 2015 02:35:31 +0900 (JST) Received: by sa76r4 (Postfix, from userid 1000) id E386D103F5; Tue, 22 Dec 2015 02:35:31 +0900 (JST) From: Yoshinori Sato To: gdb-patches@sourceware.org Cc: Yoshinori Sato Subject: [PATCH][RX] v2 instructions support Date: Tue, 22 Dec 2015 02:34:56 +0900 Message-Id: <1450719297-15073-1-git-send-email-ysato@users.sourceforge.jp> X-IsSubscribed: yes ChangeLog 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(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. --- include/gdb/sim-rx.h | 4 +- sim/rx/Makefile.in | 1 + sim/rx/cpu.h | 24 +++-- sim/rx/fpu.c | 171 ++++++++++++++++++++++++++++++++++ sim/rx/fpu.h | 3 + sim/rx/gdb-if.c | 78 ++++++++++++++-- sim/rx/reg.c | 93 ++++++++---------- sim/rx/rx.c | 259 +++++++++++++++++++++++++++++++++++++++++++-------- 8 files changed, 521 insertions(+), 112 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..d5a7665 100644 --- a/sim/rx/fpu.c +++ b/sim/rx/fpu.c @@ -790,3 +790,174 @@ rxfp_itof (long fa, int round_mode) return rv; } +double sqrt(double x); + +static 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 FP_NORMAL: + break; + case FP_PZERO: + case FP_NZERO: + return 0; + case FP_PINFINITY: + FP_RAISE (V); + return 0xffffffffL; + case FP_NINFINITY: + FP_RAISE (V); + return 0x00000000L; + case FP_DENORMAL: + FP_RAISE (E); + return 0; + case FP_QNAN: + case 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..7037c64 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,34 @@ 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 +655,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..0d78d9d 100644 --- a/sim/rx/reg.c +++ b/sim/rx/reg.c @@ -50,10 +50,10 @@ char *reg_names[] = { "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", /* control register */ "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..07654fa 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,66 @@ 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 +1019,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 +1296,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 +1312,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 +1362,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 +1396,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 +1473,13 @@ 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 +1573,33 @@ 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 +1608,64 @@ 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 +1724,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 +2294,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;