[PATCH][RX] v2 instructions support

Yoshinori Sato
2015-12-27T08:51:41Z

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 | 252 ++++++++++++++++++++++++++++++++++++++--------
sim/rx/fpu.h | 3 +
sim/rx/gdb-if.c | 70 +++++++++++--
sim/rx/reg.c | 117 ++++++++++------------
sim/rx/rx.c | 276 +++++++++++++++++++++++++++++++++++++++++++--------
8 files changed, 583 insertions(+), 164 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..3a47acb 100644
--- a/sim/rx/fpu.c
+++ b/sim/rx/fpu.c
@@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
+#include <math.h>

#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 */
@@ -490,7 +491,7 @@ rxfp_add (fp_t fa, fp_t fb)
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;
}
@@ -684,7 +685,7 @@ rxfp_ftoi (fp_t fa, int round_mode)

if (a.exp <= -25)
{
- /* Less than 0.49999 */
+ /* Less than 0.49999. */
frac_bits = a.mant;
whole_bits = 0;
}
@@ -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..7971fa2 100644
--- a/sim/rx/reg.c
+++ b/sim/rx/reg.c
@@ -28,6 +28,8 @@
#include "bfd.h"
#include "trace.h"

+#define tprintf if (trace) printf
+
int verbose = 0;
int trace = 0;
int enable_counting = 0;
@@ -45,15 +47,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 +71,9 @@ init_regs (void)
memset (&regs, 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 +107,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 +128,13 @@ 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];
+ tprintf ("get_reg (%s) = %08x%016lx\n", reg_names[acc0 + id], acc->hi, acc->lo);
}

static int highest_sp = 0, lowest_sp = 0xffffff;
@@ -203,18 +194,14 @@ put_reg (int id, unsigned int v)
case intb:
regs.r_intb = v;
break;
- case pc:
- regs.r_pc = v;
- break;
-
- case acchi:
- regs.r_acc = (regs.r_acc & 0xffffffffULL) | ((DI)v << 32);
+ case extb:
+ regs.r_extb = v;
break;
- case accmi:
- regs.r_acc = (regs.r_acc & ~0xffffffff0000ULL) | ((DI)v << 16);
+ case li:
+ regs.r_li = v;
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 +248,14 @@ 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 ();
+ tprintf ("put_reg (%s) = %08x%016lx\n", reg_names[acc0 + id], acc->hi, acc->lo);
+
+ regs.r_acc[id] = *acc;
}

int
@@ -506,14 +488,18 @@ fpsw2str(int rpsw)
return buf;
}

-#define TRC(f,n) \
- if (oldregs.f != regs.f) \
- { \
- if (tag) { printf (tag); tag = 0; } \
- printf(" %s %08x:%08x", n, \
- (unsigned int)oldregs.f, \
- (unsigned int)regs.f); \
- oldregs.f = regs.f; \
+#define TRC(f,n) \
+ if (oldregs.f != regs.f) \
+ { \
+ if (tag) \
+ { \
+ printf (tag); \
+ tag = 0; \
+ } \
+ printf (" %s %08x:%08x", n, \
+ (unsigned int)oldregs.f, \
+ (unsigned int)regs.f); \
+ oldregs.f = regs.f; \
}

void
@@ -545,14 +531,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..a3cf635 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);
@@ -1281,7 +1397,18 @@ decode_opcode ()
mb = rxfp_ftoi (ma, FPRM_ZERO);
FPCHECK ();
PD (mb);
- tprintf("(int) %g = %d\n", int2float(ma), mb);
+ tprintf ("(int) %g = %d\n", int2float (ma), mb);
+ set_sz (mb, 4);
+ 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;
@@ -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;
--
2.6.1