diff options
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/v850-tdep.c | 139 | ||||
-rw-r--r-- | sim/common/ChangeLog | 7 | ||||
-rw-r--r-- | sim/common/sim-trace.c | 13 | ||||
-rw-r--r-- | sim/common/sim-trace.h | 17 | ||||
-rw-r--r-- | sim/v850/ChangeLog | 55 | ||||
-rw-r--r-- | sim/v850/sim-main.h | 298 | ||||
-rw-r--r-- | sim/v850/simops.c | 716 | ||||
-rw-r--r-- | sim/v850/simops.h | 47 | ||||
-rw-r--r-- | sim/v850/v850-dc | 29 | ||||
-rw-r--r-- | sim/v850/v850.igen | 2079 |
11 files changed, 3380 insertions, 29 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e7be9a8..a334a06 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2012-03-28 Rathish C <rathish.c@kpitcummins.com> + + * v850-tdep.c: Add the enum values for mpu and fpu registers. + (v850_register_name): Add the mpu and fpu register names. + (v850e_register_name): Add the mpu and fpu register names. + (v850e2_register_name): New function. + (v850_gdbarch_init): Add case for bfd_mach_v850e2 and + bfd_mach_v850e2v3. + 2012-03-28 Joel Brobecker <brobecker@adacore.com> * NEWS: Add entry for Ada varobj support. diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c index e21b9c5..fd9bda3 100644 --- a/gdb/v850-tdep.c +++ b/gdb/v850-tdep.c @@ -101,7 +101,97 @@ enum E_R62_REGNUM, E_R63_REGNUM, E_R64_REGNUM, E_PC_REGNUM = E_R64_REGNUM, - E_R65_REGNUM, + E_R65_REGNUM, E_NUM_OF_V850_REGS = E_R65_REGNUM, E_NUM_OF_V850E_REGS = E_R65_REGNUM, + + /* mpu0 system registers */ + E_R66_REGNUM, + E_R67_REGNUM, + E_R68_REGNUM, + E_R69_REGNUM, + E_R70_REGNUM, + E_R71_REGNUM, + E_R72_REGNUM, + E_R73_REGNUM, + E_R74_REGNUM, + E_R75_REGNUM, + E_R76_REGNUM, + E_R77_REGNUM, + E_R78_REGNUM, + E_R79_REGNUM, + E_R80_REGNUM, + E_R81_REGNUM, + E_R82_REGNUM, + E_R83_REGNUM, + E_R84_REGNUM, + E_R85_REGNUM, + E_R86_REGNUM, + E_R87_REGNUM, + E_R88_REGNUM, + E_R89_REGNUM, + E_R90_REGNUM, + E_R91_REGNUM, + E_R92_REGNUM, + E_R93_REGNUM, + + /* mpu1 system registers */ + + E_R94_REGNUM, + E_R95_REGNUM, + E_R96_REGNUM, + E_R97_REGNUM, + E_R98_REGNUM, + E_R99_REGNUM, + E_R100_REGNUM, + E_R101_REGNUM, + E_R102_REGNUM, + E_R103_REGNUM, + E_R104_REGNUM, + E_R105_REGNUM, + E_R106_REGNUM, + E_R107_REGNUM, + E_R108_REGNUM, + E_R109_REGNUM, + E_R110_REGNUM, + E_R111_REGNUM, + E_R112_REGNUM, + E_R113_REGNUM, + E_R114_REGNUM, + E_R115_REGNUM, + E_R116_REGNUM, + E_R117_REGNUM, + E_R118_REGNUM, + E_R119_REGNUM, + E_R120_REGNUM, + E_R121_REGNUM, + + /* fpu system registers */ + E_R122_REGNUM, + E_R123_REGNUM, + E_R124_REGNUM, + E_R125_REGNUM, + E_R126_REGNUM, + E_R127_REGNUM, + E_R128_REGNUM, E_FPSR_REGNUM = E_R128_REGNUM, + E_R129_REGNUM, E_FPEPC_REGNUM = E_R129_REGNUM, + E_R130_REGNUM, E_FPST_REGNUM = E_R130_REGNUM, + E_R131_REGNUM, E_FPCC_REGNUM = E_R131_REGNUM, + E_R132_REGNUM, E_FPCFG_REGNUM = E_R132_REGNUM, + E_R133_REGNUM, + E_R134_REGNUM, + E_R135_REGNUM, + E_R136_REGNUM, + E_R137_REGNUM, + E_R138_REGNUM, + E_R139_REGNUM, + E_R140_REGNUM, + E_R141_REGNUM, + E_R142_REGNUM, + E_R143_REGNUM, + E_R144_REGNUM, + E_R145_REGNUM, + E_R146_REGNUM, + E_R147_REGNUM, + E_R148_REGNUM, E_NUM_REGS }; @@ -152,7 +242,7 @@ v850_register_name (struct gdbarch *gdbarch, int regnum) "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31", "pc", "fp" }; - if (regnum < 0 || regnum >= E_NUM_REGS) + if (regnum < 0 || regnum > E_NUM_OF_V850_REGS) return NULL; return v850_reg_names[regnum]; } @@ -172,11 +262,50 @@ v850e_register_name (struct gdbarch *gdbarch, int regnum) "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31", "pc", "fp" }; - if (regnum < 0 || regnum >= E_NUM_REGS) + if (regnum < 0 || regnum > E_NUM_OF_V850E_REGS) return NULL; return v850e_reg_names[regnum]; } +static const char * +v850e2_register_name (struct gdbarch *gdbarch, int regnum) +{ + static const char *v850e2_reg_names[] = + { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", + + "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "sr6", "sr7", + "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15", + "ctpc", "ctpsw", "dbpc", "dbpsw", "ctbp", "sr21", "sr22", "sr23", + "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31", + "pc", "fp" + + /* mpu0 system registers */ + "vip", "sr33", "sr34", "sr35", "vmecr", "vmtid", "vmadr", "sr39", + "vpecr", "vptid", "vpadr", "sr43", "vdecr", "vdtid", "sr46", "sr47", + "sr48", "sr49", "sr50", "sr51", "sr52", "sr53", "sr54", "sr55", + "sr56", "sr57", "sr58", "sr59", + + /* mpu1 system registers */ + "mpm", "mpc", "tid", "ppa", "ppm", "ppc", "dcc", "dcv0", + "dcv1", "sr69", "spal", "spau", "ipa0l", "ipa0u", "ipa1l", "ipa1u", + "iap2l", "ipa2u", "ipa3l", "ipa3u", "dpa0l", "dpa0u", "dpa1l", "dpa1u", + "dpa2l", "dpa2u", "dpa3l", "dpa3u", + + /* fpu system registers */ + "sr88", "sr89", "sr90", "sr91", "sr92", "sr93", "fpsr", "fpepc", + "fpst", "fpcc", "fpcfg", "sr99", "sr100", "sr101", "sr102", "sr103", + "sr104", "sr105", "sr106", "sr107", "sr108", "sr109", "sr110", "sr111", + "sr112", "sr113", "sr114", "sr115" + }; + if (regnum < 0 || regnum >= E_NUM_REGS) + return NULL; + return v850e2_reg_names[regnum]; +} + /* Returns the default type for register N. */ static struct type * @@ -999,6 +1128,10 @@ v850_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) case bfd_mach_v850e1: set_gdbarch_register_name (gdbarch, v850e_register_name); break; + case bfd_mach_v850e2: + case bfd_mach_v850e2v3: + set_gdbarch_register_name (gdbarch, v850e2_register_name); + break; } set_gdbarch_num_regs (gdbarch, E_NUM_REGS); diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index 462fb61..8b906af 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,3 +1,10 @@ +2012-03-28 Rathish C <rathish.c@kpitcummins.com> + + * sim-trace.c: Update the function prototype of save_data_size. + Move the enum data_fmt from here... + * sim-trace.h: ...to here. + Add function prototype of save_data. + 2012-03-25 Mike Frysinger <vapier@gentoo.org> * sim-core.h (sim_core_trans_addr): Add prototype. diff --git a/sim/common/sim-trace.c b/sim/common/sim-trace.c index fc20d00..6b5d067 100644 --- a/sim/common/sim-trace.c +++ b/sim/common/sim-trace.c @@ -497,17 +497,6 @@ trace_uninstall (SIM_DESC sd) } } -typedef enum { - trace_fmt_invalid, - trace_fmt_word, - trace_fmt_fp, - trace_fmt_fpu, - trace_fmt_string, - trace_fmt_bool, - trace_fmt_addr, - trace_fmt_instruction_incomplete, -} data_fmt; - /* compute the nr of trace data units consumed by data */ static int save_data_size (TRACE_DATA *data, @@ -519,7 +508,7 @@ save_data_size (TRACE_DATA *data, /* Archive DATA into the trace buffer */ -static void +void save_data (SIM_DESC sd, TRACE_DATA *data, data_fmt fmt, diff --git a/sim/common/sim-trace.h b/sim/common/sim-trace.h index e824fc3..1ba6019 100644 --- a/sim/common/sim-trace.h +++ b/sim/common/sim-trace.h @@ -249,9 +249,26 @@ extern void trace_generic PARAMS ((SIM_DESC sd, ...)) __attribute__((format (printf, 4, 5))); +typedef enum { + trace_fmt_invalid, + trace_fmt_word, + trace_fmt_fp, + trace_fmt_fpu, + trace_fmt_string, + trace_fmt_bool, + trace_fmt_addr, + trace_fmt_instruction_incomplete, +} data_fmt; + /* Trace a varying number of word sized inputs/outputs. trace_result* must be called to close the trace operation. */ +extern void save_data PARAMS ((SIM_DESC sd, + TRACE_DATA *data, + data_fmt fmt, + long size, + const void *buf)); + extern void trace_input0 PARAMS ((SIM_DESC sd, sim_cpu *cpu, int trace_idx)); diff --git a/sim/v850/ChangeLog b/sim/v850/ChangeLog index 1f1a97b..e1430ee 100644 --- a/sim/v850/ChangeLog +++ b/sim/v850/ChangeLog @@ -1,3 +1,58 @@ +2012-03-28 Rathish C <rathish.c@kpitcummins.com> + + * sim-main.h (struct _v850_regs): Add new fields mpu0_sregs, + mpu1_sregs, and fpu_sregs. + (MPU0_SR, MPU1_SR, FPU_SR): New macros for accessing new fields + in _v850_regs struct. + (SP_REGNO): Define. + (SP): Redefine using SP_REGNO. + (PSW_REGNO, EIIC, FEIC, DBIC, DIR, EIWR, FEWR, DBWR, BSEL, PSW_NPV) + (PSW_DMP, PSW_IMP, ECR_EICC, ECR_FECC, FPSR, FPSR_REGNO, FPEPC) + (FPST, FPST_REGNO, FPCC, FPCFG, FPCFG_REGNO, FPSR_DEM, FPSR_SEM) + (FPSR_RM, FPSR_RN, FPSR_FS, FPSR_PR, FPSR_XC, FPSR_XCE, FPSR_XCV) + (FPSR_XCZ, FPSR_XCO, FPSR_XCU, FPSR_XCI, FPSR_XE, FPSR_XEV) + (FPSR_XEZ, FPSR_XEO, FPSR_XEU, FPSR_XEI, FPSR_XP, FPSR_XPV) + (FPSR_XPZ, FPSR_XPO, FPSR_XPU, FPSR_XPI, FPST_PR, FPST_XCE) + (FPST_XCV, FPST_XCZ, FPST_XCO, FPST_XCU, FPST_XCI, FPST_XPV) + (FPST_XPZ, FPST_XPO, FPST_XPU, FPST_XPI, FPCFG_RM, FPCFG_XEV) + (FPCFG_XEZ, FPCFG_XEO, FPCFG_XEU, FPCFG_XEI, GET_FPCC, CLEAR_FPCC) + (SET_FPCC, TEST_FPCC, FPSR_GET_ROUND, MPM, MPC, MPC_REGNO, TID) + (PPA, PPM, PPC, DCC, DCV0, DCV1, SPAL, SPAU, IPA0L, IPA0U, IPA1L) + (IPA1U, IPA2L, IPA2U, IPA3L, IPA3U, DPA0L, DPA0U, DPA1L, DPA1U) + (DPA2L, DPA2U, DPA3L, DPA3U, PPC_PPE, SPAL_SPE, SPAL_SPS, VIP) + (VMECR, VMTID, VMADR, VPECR, VPTID, VPADR, VDECR, VDTID, MPM_AUE) + (MPM_MPE, VMECR_VMX, VMECR_VMR, VMECR_VMW, VMECR_VMS, VMECR_VMRMW) + (VMECR_VMMS, IPA2ADDR, IPA_IPE, IPA_IPX, IPA_IPR, IPE0, IPE1, IPE2) + (IPE3, IPX0, IPX1, IPX2, IPX3, IPR0, IPR1, IPR2, IPR3, DPA2ADDR) + (DPA_DPE, DPA_DPR, DPA_DPW, DPE0, DPE1, DPE2, DPE3, DPR0, DPR1) + (DPR2, DPR3, DPW0, DPW1, DPW2, DPW3, DCC_DCE0, DCC_DCE1, PPA2ADDR) + (PPC_PPC, PPC_PPE, PPC_PPM): New macros. + (FPU_COMPARE): New enum. + (TRACE_FP_INPUT_FPU1, TRACE_FP_INPUT_FPU2, TRACE_FP_INPUT_FPU3) + (TRACE_FP_INPUT_BOOL1_FPU2, TRACE_FP_INPUT_WORD2) + (TRACE_FP_RESULT_WORD1, TRACE_FP_RESULT_WORD2): New macros. + * simops.c (Add32): Update prototype. + (update_fpsr): New function. + (SignalException): New function. + (SignalExceptionFPE): New function. + (check_invalid_snan): New function. + (v850_float_compare): New function. + (v850_div): New function. + (v850_divu): New function. + (v850_sar): New function. + (v850_shl): New function. + (v850_shr): New function. + (v850_satadd): New function. + (v850_satsub): New function. + (load_data_mem): New function. + (store_data_mem): New function. + (mpu_load_mem_test): New function. + (mpu_store_mem_test): New function. + * simops.h: Add function prototype for above mentioned functions. + (check_cvt_fi, check_cvt_if, check_cvt_ff): Define. + * v850-dc: Add entry for v850e2 and v850e2v3. + * v850.igen: Add support for v850e2 and v850e2v3. + 2012-03-24 Mike Frysinger <vapier@gentoo.org> * aclocal.m4, config.in, configure: Regenerate. diff --git a/sim/v850/sim-main.h b/sim/v850/sim-main.h index e9f7aad..c52da77 100644 --- a/sim/v850/sim-main.h +++ b/sim/v850/sim-main.h @@ -15,6 +15,7 @@ #include "sim-basics.h" #include "sim-signal.h" +#include "sim-fpu.h" typedef address_word sim_cia; @@ -39,7 +40,10 @@ typedef struct _v850_regs { reg_t regs[32]; /* general-purpose registers */ reg_t sregs[32]; /* system registers, including psw */ reg_t pc; - int dummy_mem; /* where invalid accesses go */ + int dummy_mem; /* where invalid accesses go */ + reg_t mpu0_sregs[28]; /* mpu0 system registers */ + reg_t mpu1_sregs[28]; /* mpu1 system registers */ + reg_t fpu_sregs[28]; /* fpu system registers */ } v850_regs; struct _sim_cpu @@ -122,11 +126,15 @@ nia = PC /* new */ #define GR ((CPU)->reg.regs) #define SR ((CPU)->reg.sregs) +#define MPU0_SR ((STATE_CPU (sd, 0))->reg.mpu0_sregs) +#define MPU1_SR ((STATE_CPU (sd, 0))->reg.mpu1_sregs) +#define FPU_SR ((STATE_CPU (sd, 0))->reg.fpu_sregs) /* old */ #define State (STATE_CPU (simulator, 0)->reg) #define PC (State.pc) -#define SP (State.regs[3]) +#define SP_REGNO 3 +#define SP (State.regs[SP_REGNO]) #define EP (State.regs[30]) #define EIPC (State.sregs[0]) @@ -135,11 +143,20 @@ nia = PC #define FEPSW (State.sregs[3]) #define ECR (State.sregs[4]) #define PSW (State.sregs[5]) +#define PSW_REGNO 5 +#define EIIC (State.sregs[13]) +#define FEIC (State.sregs[14]) +#define DBIC (SR[15]) #define CTPC (SR[16]) #define CTPSW (SR[17]) #define DBPC (State.sregs[18]) #define DBPSW (State.sregs[19]) #define CTBP (State.sregs[20]) +#define DIR (SR[21]) +#define EIWR (SR[28]) +#define FEWR (SR[29]) +#define DBWR (SR[30]) +#define BSEL (SR[31]) #define PSW_US BIT32 (8) #define PSW_NP 0x80 @@ -151,6 +168,210 @@ nia = PC #define PSW_S 0x2 #define PSW_Z 0x1 +#define PSW_NPV (1<<18) +#define PSW_DMP (1<<17) +#define PSW_IMP (1<<16) + +#define ECR_EICC 0x0000ffff +#define ECR_FECC 0xffff0000 + +/* FPU */ + +#define FPSR (FPU_SR[6]) +#define FPSR_REGNO 6 +#define FPEPC (FPU_SR[7]) +#define FPST (FPU_SR[8]) +#define FPST_REGNO 8 +#define FPCC (FPU_SR[9]) +#define FPCFG (FPU_SR[10]) +#define FPCFG_REGNO 10 + +#define FPSR_DEM 0x00200000 +#define FPSR_SEM 0x00100000 +#define FPSR_RM 0x000c0000 +#define FPSR_RN 0x00000000 +#define FPSR_FS 0x00020000 +#define FPSR_PR 0x00010000 + +#define FPSR_XC 0x0000fc00 +#define FPSR_XCE 0x00008000 +#define FPSR_XCV 0x00004000 +#define FPSR_XCZ 0x00002000 +#define FPSR_XCO 0x00001000 +#define FPSR_XCU 0x00000800 +#define FPSR_XCI 0x00000400 + +#define FPSR_XE 0x000003e0 +#define FPSR_XEV 0x00000200 +#define FPSR_XEZ 0x00000100 +#define FPSR_XEO 0x00000080 +#define FPSR_XEU 0x00000040 +#define FPSR_XEI 0x00000020 + +#define FPSR_XP 0x0000001f +#define FPSR_XPV 0x00000010 +#define FPSR_XPZ 0x00000008 +#define FPSR_XPO 0x00000004 +#define FPSR_XPU 0x00000002 +#define FPSR_XPI 0x00000001 + +#define FPST_PR 0x00008000 +#define FPST_XCE 0x00002000 +#define FPST_XCV 0x00001000 +#define FPST_XCZ 0x00000800 +#define FPST_XCO 0x00000400 +#define FPST_XCU 0x00000200 +#define FPST_XCI 0x00000100 + +#define FPST_XPV 0x00000010 +#define FPST_XPZ 0x00000008 +#define FPST_XPO 0x00000004 +#define FPST_XPU 0x00000002 +#define FPST_XPI 0x00000001 + +#define FPCFG_RM 0x00000180 +#define FPCFG_XEV 0x00000010 +#define FPCFG_XEZ 0x00000008 +#define FPCFG_XEO 0x00000004 +#define FPCFG_XEU 0x00000002 +#define FPCFG_XEI 0x00000001 + +#define GET_FPCC()\ + ((FPSR >> 24) &0xf) + +#define CLEAR_FPCC(bbb)\ + (FPSR &= ~(1 << (bbb+24))) + +#define SET_FPCC(bbb)\ + (FPSR |= 1 << (bbb+24)) + +#define TEST_FPCC(bbb)\ + ((FPSR & (1 << (bbb+24))) != 0) + +#define FPSR_GET_ROUND() \ + (((FPSR & FPSR_RM) == FPSR_RN) ? sim_fpu_round_near \ + : ((FPSR & FPSR_RM) == 0x00040000) ? sim_fpu_round_up \ + : ((FPSR & FPSR_RM) == 0x00080000) ? sim_fpu_round_down \ + : sim_fpu_round_zero) + + +enum FPU_COMPARE { + FPU_CMP_F = 0, + FPU_CMP_UN, + FPU_CMP_EQ, + FPU_CMP_UEQ, + FPU_CMP_OLT, + FPU_CMP_ULT, + FPU_CMP_OLE, + FPU_CMP_ULE, + FPU_CMP_SF, + FPU_CMP_NGLE, + FPU_CMP_SEQ, + FPU_CMP_NGL, + FPU_CMP_LT, + FPU_CMP_NGE, + FPU_CMP_LE, + FPU_CMP_NGT +}; + + +/* MPU */ +#define MPM (MPU1_SR[0]) +#define MPC (MPU1_SR[1]) +#define MPC_REGNO 1 +#define TID (MPU1_SR[2]) +#define PPA (MPU1_SR[3]) +#define PPM (MPU1_SR[4]) +#define PPC (MPU1_SR[5]) +#define DCC (MPU1_SR[6]) +#define DCV0 (MPU1_SR[7]) +#define DCV1 (MPU1_SR[8]) +#define SPAL (MPU1_SR[10]) +#define SPAU (MPU1_SR[11]) +#define IPA0L (MPU1_SR[12]) +#define IPA0U (MPU1_SR[13]) +#define IPA1L (MPU1_SR[14]) +#define IPA1U (MPU1_SR[15]) +#define IPA2L (MPU1_SR[16]) +#define IPA2U (MPU1_SR[17]) +#define IPA3L (MPU1_SR[18]) +#define IPA3U (MPU1_SR[19]) +#define DPA0L (MPU1_SR[20]) +#define DPA0U (MPU1_SR[21]) +#define DPA1L (MPU1_SR[22]) +#define DPA1U (MPU1_SR[23]) +#define DPA2L (MPU1_SR[24]) +#define DPA2U (MPU1_SR[25]) +#define DPA3L (MPU1_SR[26]) +#define DPA3U (MPU1_SR[27]) + +#define PPC_PPE 0x1 +#define SPAL_SPE 0x1 +#define SPAL_SPS 0x10 + +#define VIP (MPU0_SR[0]) +#define VMECR (MPU0_SR[4]) +#define VMTID (MPU0_SR[5]) +#define VMADR (MPU0_SR[6]) +#define VPECR (MPU0_SR[8]) +#define VPTID (MPU0_SR[9]) +#define VPADR (MPU0_SR[10]) +#define VDECR (MPU0_SR[12]) +#define VDTID (MPU0_SR[13]) + +#define MPM_AUE 0x2 +#define MPM_MPE 0x1 + +#define VMECR_VMX 0x2 +#define VMECR_VMR 0x4 +#define VMECR_VMW 0x8 +#define VMECR_VMS 0x10 +#define VMECR_VMRMW 0x20 +#define VMECR_VMMS 0x40 + +#define IPA2ADDR(IPA) ((IPA) & 0x1fffff80) +#define IPA_IPE 0x1 +#define IPA_IPX 0x2 +#define IPA_IPR 0x4 +#define IPE0 (IPA0L & IPA_IPE) +#define IPE1 (IPA1L & IPA_IPE) +#define IPE2 (IPA2L & IPA_IPE) +#define IPE3 (IPA3L & IPA_IPE) +#define IPX0 (IPA0L & IPA_IPX) +#define IPX1 (IPA1L & IPA_IPX) +#define IPX2 (IPA2L & IPA_IPX) +#define IPX3 (IPA3L & IPA_IPX) +#define IPR0 (IPA0L & IPA_IPR) +#define IPR1 (IPA1L & IPA_IPR) +#define IPR2 (IPA2L & IPA_IPR) +#define IPR3 (IPA3L & IPA_IPR) + +#define DPA2ADDR(DPA) ((DPA) & 0x1fffff80) +#define DPA_DPE 0x1 +#define DPA_DPR 0x4 +#define DPA_DPW 0x8 +#define DPE0 (DPA0L & DPA_DPE) +#define DPE1 (DPA1L & DPA_DPE) +#define DPE2 (DPA2L & DPA_DPE) +#define DPE3 (DPA3L & DPA_DPE) +#define DPR0 (DPA0L & DPA_DPR) +#define DPR1 (DPA1L & DPA_DPR) +#define DPR2 (DPA2L & DPA_DPR) +#define DPR3 (DPA3L & DPA_DPR) +#define DPW0 (DPA0L & DPA_DPW) +#define DPW1 (DPA1L & DPA_DPW) +#define DPW2 (DPA2L & DPA_DPW) +#define DPW3 (DPA3L & DPA_DPW) + +#define DCC_DCE0 0x1 +#define DCC_DCE1 0x10000 + +#define PPA2ADDR(PPA) ((PPA) & 0x1fffff80) +#define PPC_PPC 0xfffffffe +#define PPC_PPE 0x1 +#define PPC_PPM 0x0000fff8 + + #define SEXT3(x) ((((x)&0x7)^(~0x3))+0x4) /* sign-extend a 4-bit number */ @@ -344,6 +565,79 @@ do { \ } \ } while (0) +#define TRACE_FP_INPUT_FPU1(V0) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + { \ + unsigned64 f0; \ + sim_fpu_to64 (&f0, (V0)); \ + trace_input_fp1 (SD, CPU, TRACE_FPU_IDX, f0); \ + } \ +} while (0) + +#define TRACE_FP_INPUT_FPU2(V0, V1) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + { \ + unsigned64 f0, f1; \ + sim_fpu_to64 (&f0, (V0)); \ + sim_fpu_to64 (&f1, (V1)); \ + trace_input_fp2 (SD, CPU, TRACE_FPU_IDX, f0, f1); \ + } \ +} while (0) + +#define TRACE_FP_INPUT_FPU3(V0, V1, V2) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + { \ + unsigned64 f0, f1, f2; \ + sim_fpu_to64 (&f0, (V0)); \ + sim_fpu_to64 (&f1, (V1)); \ + sim_fpu_to64 (&f2, (V2)); \ + trace_input_fp3 (SD, CPU, TRACE_FPU_IDX, f0, f1, f2); \ + } \ +} while (0) + +#define TRACE_FP_INPUT_BOOL1_FPU2(V0, V1, V2) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + { \ + int d0 = (V0); \ + unsigned64 f1, f2; \ + TRACE_DATA *data = CPU_TRACE_DATA (CPU); \ + TRACE_IDX (data) = TRACE_FPU_IDX; \ + sim_fpu_to64 (&f1, (V1)); \ + sim_fpu_to64 (&f2, (V2)); \ + save_data (SD, data, trace_fmt_bool, sizeof (d0), &d0); \ + save_data (SD, data, trace_fmt_fp, sizeof (fp_word), &f1); \ + save_data (SD, data, trace_fmt_fp, sizeof (fp_word), &f2); \ + } \ +} while (0) + +#define TRACE_FP_INPUT_WORD2(V0, V1) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + trace_input_word2 (SD, CPU, TRACE_FPU_IDX, (V0), (V1)); \ +} while (0) + +#define TRACE_FP_RESULT_FPU1(R0) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + { \ + unsigned64 f0; \ + sim_fpu_to64 (&f0, (R0)); \ + trace_result_fp1 (SD, CPU, TRACE_FPU_IDX, f0); \ + } \ +} while (0) + +#define TRACE_FP_RESULT_WORD1(R0) TRACE_FP_RESULT_WORD(R0) + +#define TRACE_FP_RESULT_WORD2(R0, R1) \ +do { \ + if (TRACE_FPU_P (CPU)) \ + trace_result_word2 (SD, CPU, TRACE_FPU_IDX, (R0), (R1)); \ +} while (0) + #else #define trace_input(NAME, IN1, IN2) #define trace_output(RESULT) diff --git a/sim/v850/simops.c b/sim/v850/simops.c index a14b0b2..f7fc67d 100644 --- a/sim/v850/simops.c +++ b/sim/v850/simops.c @@ -320,7 +320,7 @@ condition_met (unsigned code) return 1; } -static unsigned long +unsigned long Add32 (unsigned long a1, unsigned long a2, int * carry) { unsigned long result = (a1 + a2); @@ -2839,3 +2839,717 @@ OP_307E0 (void) return 4; } +/* V850E2R FPU functions */ +/* + sim_fpu_status_invalid_snan = 1, -V--- (sim spec.) + sim_fpu_status_invalid_qnan = 2, ----- (sim spec.) + sim_fpu_status_invalid_isi = 4, (inf - inf) -V--- + sim_fpu_status_invalid_idi = 8, (inf / inf) -V--- + sim_fpu_status_invalid_zdz = 16, (0 / 0) -V--- + sim_fpu_status_invalid_imz = 32, (inf * 0) -V--- + sim_fpu_status_invalid_cvi = 64, convert to integer -V--- + sim_fpu_status_invalid_div0 = 128, (X / 0) --Z-- + sim_fpu_status_invalid_cmp = 256, compare ----- (sim spec.) + sim_fpu_status_invalid_sqrt = 512, -V--- + sim_fpu_status_rounded = 1024, I---- + sim_fpu_status_inexact = 2048, I---- (sim spec.) + sim_fpu_status_overflow = 4096, I--O- + sim_fpu_status_underflow = 8192, I---U + sim_fpu_status_denorm = 16384, ----U (sim spec.) +*/ + +void update_fpsr (SIM_DESC sd, sim_fpu_status status, unsigned int mask, unsigned int double_op_p) +{ + unsigned int fpsr = FPSR & mask; + + unsigned int flags = 0; + + if (fpsr & FPSR_XEI + && ((status & (sim_fpu_status_rounded + | sim_fpu_status_overflow + | sim_fpu_status_inexact)) + || (status & sim_fpu_status_underflow + && (fpsr & (FPSR_XEU | FPSR_XEI)) == 0 + && fpsr & FPSR_FS))) + { + flags |= FPSR_XCI | FPSR_XPI; + } + + if (fpsr & FPSR_XEV + && (status & (sim_fpu_status_invalid_isi + | sim_fpu_status_invalid_imz + | sim_fpu_status_invalid_zdz + | sim_fpu_status_invalid_idi + | sim_fpu_status_invalid_cvi + | sim_fpu_status_invalid_sqrt + | sim_fpu_status_invalid_snan))) + { + flags |= FPSR_XCV | FPSR_XPV; + } + + if (fpsr & FPSR_XEZ + && (status & sim_fpu_status_invalid_div0)) + { + flags |= FPSR_XCV | FPSR_XPV; + } + + if (fpsr & FPSR_XEO + && (status & sim_fpu_status_overflow)) + { + flags |= FPSR_XCO | FPSR_XPO; + } + + if (((fpsr & FPSR_XEU) || (fpsr & FPSR_FS) == 0) + && (status & (sim_fpu_status_underflow + | sim_fpu_status_denorm))) + { + flags |= FPSR_XCU | FPSR_XPU; + } + + if (flags) + { + FPSR &= ~FPSR_XC; + FPSR |= flags; + + SignalExceptionFPE(sd, double_op_p); + } +} + +/* + exception +*/ + +void SignalException(SIM_DESC sd) +{ + if (MPM & MPM_AUE) + { + PSW = PSW & ~(PSW_NPV | PSW_DMP | PSW_IMP); + } +} + +void SignalExceptionFPE(SIM_DESC sd, unsigned int double_op_p) +{ + if (((PSW & (PSW_NP|PSW_ID)) == 0) + || !(FPSR & (double_op_p ? FPSR_DEM : FPSR_SEM))) + { + EIPC = PC; + EIPSW = PSW; + EIIC = (FPSR & (double_op_p ? FPSR_DEM : FPSR_SEM)) + ? 0x71 : 0x72; + PSW |= (PSW_EP | PSW_ID); + PC = 0x70; + + SignalException(sd); + } +} + + +void check_invalid_snan(SIM_DESC sd, sim_fpu_status status, unsigned int double_op_p) +{ + if ((FPSR & FPSR_XEI) + && (status & sim_fpu_status_invalid_snan)) + { + FPSR &= ~FPSR_XC; + FPSR |= FPSR_XCV; + FPSR |= FPSR_XPV; + SignalExceptionFPE(sd, double_op_p); + } +} + +int v850_float_compare(SIM_DESC sd, int cmp, sim_fpu wop1, sim_fpu wop2, int double_op_p) +{ + int result = -1; + + if (sim_fpu_is_nan(&wop1) || sim_fpu_is_nan(&wop2)) + { + if (cmp & 0x8) + { + if (FPSR & FPSR_XEV) + { + FPSR |= FPSR_XCV | FPSR_XPV; + SignalExceptionFPE(sd, double_op_p); + } + } + + switch (cmp) + { + case FPU_CMP_F: + result = 0; + break; + case FPU_CMP_UN: + result = 1; + break; + case FPU_CMP_EQ: + result = 0; + break; + case FPU_CMP_UEQ: + result = 1; + break; + case FPU_CMP_OLT: + result = 0; + break; + case FPU_CMP_ULT: + result = 1; + break; + case FPU_CMP_OLE: + result = 0; + break; + case FPU_CMP_ULE: + result = 1; + break; + case FPU_CMP_SF: + result = 0; + break; + case FPU_CMP_NGLE: + result = 1; + break; + case FPU_CMP_SEQ: + result = 0; + break; + case FPU_CMP_NGL: + result = 1; + break; + case FPU_CMP_LT: + result = 0; + break; + case FPU_CMP_NGE: + result = 1; + break; + case FPU_CMP_LE: + result = 0; + break; + case FPU_CMP_NGT: + result = 1; + break; + default: + abort(); + } + } + else if (sim_fpu_is_infinity(&wop1) && sim_fpu_is_infinity(&wop2) + && sim_fpu_sign(&wop1) == sim_fpu_sign(&wop2)) + { + switch (cmp) + { + case FPU_CMP_F: + result = 0; + break; + case FPU_CMP_UN: + result = 0; + break; + case FPU_CMP_EQ: + result = 1; + break; + case FPU_CMP_UEQ: + result = 1; + break; + case FPU_CMP_OLT: + result = 0; + break; + case FPU_CMP_ULT: + result = 0; + break; + case FPU_CMP_OLE: + result = 1; + break; + case FPU_CMP_ULE: + result = 1; + break; + case FPU_CMP_SF: + result = 0; + break; + case FPU_CMP_NGLE: + result = 0; + break; + case FPU_CMP_SEQ: + result = 1; + break; + case FPU_CMP_NGL: + result = 1; + break; + case FPU_CMP_LT: + result = 0; + break; + case FPU_CMP_NGE: + result = 0; + break; + case FPU_CMP_LE: + result = 1; + break; + case FPU_CMP_NGT: + result = 1; + break; + default: + abort(); + } + } + else + { + int gt = 0,lt = 0,eq = 0, status; + + status = sim_fpu_cmp( &wop1, &wop2 ); + + switch (status) { + case SIM_FPU_IS_SNAN: + case SIM_FPU_IS_QNAN: + abort(); + break; + + case SIM_FPU_IS_NINF: + lt = 1; + break; + case SIM_FPU_IS_PINF: + gt = 1; + break; + case SIM_FPU_IS_NNUMBER: + lt = 1; + break; + case SIM_FPU_IS_PNUMBER: + gt = 1; + break; + case SIM_FPU_IS_NDENORM: + lt = 1; + break; + case SIM_FPU_IS_PDENORM: + gt = 1; + break; + case SIM_FPU_IS_NZERO: + case SIM_FPU_IS_PZERO: + eq = 1; + break; + } + + switch (cmp) + { + case FPU_CMP_F: + result = 0; + break; + case FPU_CMP_UN: + result = 0; + break; + case FPU_CMP_EQ: + result = eq; + break; + case FPU_CMP_UEQ: + result = eq; + break; + case FPU_CMP_OLT: + result = lt; + break; + case FPU_CMP_ULT: + result = lt; + break; + case FPU_CMP_OLE: + result = lt || eq; + break; + case FPU_CMP_ULE: + result = lt || eq; + break; + case FPU_CMP_SF: + result = 0; + break; + case FPU_CMP_NGLE: + result = 0; + break; + case FPU_CMP_SEQ: + result = eq; + break; + case FPU_CMP_NGL: + result = eq; + break; + case FPU_CMP_LT: + result = lt; + break; + case FPU_CMP_NGE: + result = lt; + break; + case FPU_CMP_LE: + result = lt || eq; + break; + case FPU_CMP_NGT: + result = lt || eq; + break; + } + } + + ASSERT(result != -1); + return result; +} + +void v850_div(SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p, unsigned int *op3p) +{ + signed long int quotient; + signed long int remainder; + signed long int divide_by; + signed long int divide_this; + bfd_boolean overflow = FALSE; + + /* Compute the result. */ + divide_by = op0; + divide_this = op1; + + if (divide_by == 0 || (divide_by == -1 && divide_this == (1 << 31))) + { + overflow = TRUE; + divide_by = 1; + } + + quotient = divide_this / divide_by; + remainder = divide_this % divide_by; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient < 0) PSW |= PSW_S; + + *op2p = quotient; + *op3p = remainder; +} + +void v850_divu(SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p, unsigned int *op3p) +{ + unsigned long int quotient; + unsigned long int remainder; + unsigned long int divide_by; + unsigned long int divide_this; + bfd_boolean overflow = FALSE; + + /* Compute the result. */ + + divide_by = op0; + divide_this = op1; + + if (divide_by == 0) + { + overflow = TRUE; + divide_by = 1; + } + + quotient = divide_this / divide_by; + remainder = divide_this % divide_by; + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV); + + if (overflow) PSW |= PSW_OV; + if (quotient == 0) PSW |= PSW_Z; + if (quotient & 0x80000000) PSW |= PSW_S; + + *op2p = quotient; + *op3p = remainder; +} + + +void v850_sar(SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p) +{ + unsigned int result, z, s, cy; + + op0 &= 0x1f; + result = (signed)op1 >> op0; + + /* Compute the condition codes. */ + z = (result == 0); + s = (result & 0x80000000); + cy = (op1 & (1 << (op0 - 1))); + + /* Store the result and condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0)); + + *op2p = result; +} + +void v850_shl(SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p) +{ + unsigned int result, z, s, cy; + + op0 &= 0x1f; + result = op1 << op0; + + /* Compute the condition codes. */ + z = (result == 0); + s = (result & 0x80000000); + cy = (op1 & (1 << (32 - op0))); + + /* Store the result and condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0)); + + *op2p = result; +} + +void v850_shr(SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p) +{ + unsigned int result, z, s, cy; + + op0 &= 0x1f; + result = op1 >> op0; + + /* Compute the condition codes. */ + z = (result == 0); + s = (result & 0x80000000); + cy = (op1 & (1 << (op0 - 1))); + + /* Store the result and condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_OV | PSW_CY); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0)); + + *op2p = result; +} + +void v850_satadd(SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p) +{ + unsigned int result, z, s, cy, ov, sat; + + result = op0 + op1; + + /* Compute the condition codes. */ + z = (result == 0); + s = (result & 0x80000000); + cy = (result < op0 || result < op1); + ov = ((op0 & 0x80000000) == (op1 & 0x80000000) + && (op0 & 0x80000000) != (result & 0x80000000)); + sat = ov; + + /* Store the result and condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0) + | (sat ? PSW_SAT : 0)); + + /* Handle saturated results. */ + if (sat && s) + { + result = 0x7fffffff; + PSW &= ~PSW_S; + } + else if (sat) + { + result = 0x80000000; + PSW |= PSW_S; + } + + *op2p = result; +} + +void v850_satsub(SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p) +{ + unsigned int result, z, s, cy, ov, sat; + + /* Compute the result. */ + result = op1 - op0; + + /* Compute the condition codes. */ + z = (result == 0); + s = (result & 0x80000000); + cy = (op1 < op0); + ov = ((op1 & 0x80000000) != (op0 & 0x80000000) + && (op1 & 0x80000000) != (result & 0x80000000)); + sat = ov; + + /* Store the result and condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0) + | (sat ? PSW_SAT : 0)); + + /* Handle saturated results. */ + if (sat && s) + { + result = 0x7fffffff; + PSW &= ~PSW_S; + } + else if (sat) + { + result = 0x80000000; + PSW |= PSW_S; + } + + *op2p = result; +} + +unsigned32 +load_data_mem(sd, addr, len) + SIM_DESC sd; + SIM_ADDR addr; + int len; +{ + uint32 data; + + switch (len) + { + case 1: + data = sim_core_read_unaligned_1 (STATE_CPU (sd, 0), + PC, read_map, addr); + break; + case 2: + data = sim_core_read_unaligned_2 (STATE_CPU (sd, 0), + PC, read_map, addr); + break; + case 4: + data = sim_core_read_unaligned_4 (STATE_CPU (sd, 0), + PC, read_map, addr); + break; + default: + abort (); + } + return data; +} + +void +store_data_mem(sd, addr, len, data) + SIM_DESC sd; + SIM_ADDR addr; + int len; + unsigned32 data; +{ + switch (len) + { + case 1: + store_mem(addr, 1, data); + break; + case 2: + store_mem(addr, 2, data); + break; + case 4: + store_mem(addr, 4, data); + break; + default: + abort (); + } +} + +int mpu_load_mem_test(SIM_DESC sd, unsigned int addr, int size, int base_reg) +{ + int result = 1; + + if (PSW & PSW_DMP) + { + if (IPE0 && addr >= IPA2ADDR(IPA0L) && addr <= IPA2ADDR(IPA0L) && IPR0) + { + /* text area */ + } + else if (IPE1 && addr >= IPA2ADDR(IPA1L) && addr <= IPA2ADDR(IPA1L) && IPR1) + { + /* text area */ + } + else if (IPE2 && addr >= IPA2ADDR(IPA2L) && addr <= IPA2ADDR(IPA2L) && IPR2) + { + /* text area */ + } + else if (IPE3 && addr >= IPA2ADDR(IPA3L) && addr <= IPA2ADDR(IPA3L) && IPR3) + { + /* text area */ + } + else if (addr >= PPA2ADDR(PPA & ~PPM) && addr <= DPA2ADDR(PPA | PPM)) + { + /* preifarallel area */ + } + else if (addr >= PPA2ADDR(SPAL) && addr <= DPA2ADDR(SPAU)) + { + /* stack area */ + } + else if (DPE0 && addr >= DPA2ADDR(DPA0L) && addr <= DPA2ADDR(DPA0L) && DPR0 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else if (DPE1 && addr >= DPA2ADDR(DPA1L) && addr <= DPA2ADDR(DPA1L) && DPR1 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else if (DPE2 && addr >= DPA2ADDR(DPA2L) && addr <= DPA2ADDR(DPA2L) && DPR2 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else if (DPE3 && addr >= DPA2ADDR(DPA3L) && addr <= DPA2ADDR(DPA3L) && DPR3 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else + { + VMECR &= ~(VMECR_VMW | VMECR_VMX); + VMECR |= VMECR_VMR; + VMADR = addr; + VMTID = TID; + FEIC = 0x431; + + PC = 0x30; + + SignalException(sd); + result = 0; + } + } + + return result; +} + +int mpu_store_mem_test(SIM_DESC sd, unsigned int addr, int size, int base_reg) +{ + int result = 1; + + if (PSW & PSW_DMP) + { + if (addr >= PPA2ADDR(PPA & ~PPM) && addr <= DPA2ADDR(PPA | PPM)) + { + /* preifarallel area */ + } + else if (addr >= PPA2ADDR(SPAL) && addr <= DPA2ADDR(SPAU)) + { + /* stack area */ + } + else if (DPE0 && addr >= DPA2ADDR(DPA0L) && addr <= DPA2ADDR(DPA0L) && DPW0 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else if (DPE1 && addr >= DPA2ADDR(DPA1L) && addr <= DPA2ADDR(DPA1L) && DPW1 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else if (DPE2 && addr >= DPA2ADDR(DPA2L) && addr <= DPA2ADDR(DPA2L) && DPW2 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else if (DPE3 && addr >= DPA2ADDR(DPA3L) && addr <= DPA2ADDR(DPA3L) && DPW3 + && ((SPAL & SPAL_SPS) ? base_reg == SP_REGNO : 1)) + { + /* data area */ + } + else + { + if (addr >= PPA2ADDR(PPA & ~PPM) && addr <= DPA2ADDR(PPA | PPM)) + { + FEIC = 0x432; + VPTID = TID; + VPADR = PC; +#ifdef NOT_YET + VIP_PP; + VPECR; +#endif + } + else + { + FEIC = 0x431; + VMTID = TID; + VMADR = VMECR; + VMECR &= ~(VMECR_VMW | VMECR_VMX); + VMECR |= VMECR_VMR; + PC = 0x30; + } + result = 0; + } + } + + return result; +} + diff --git a/sim/v850/simops.h b/sim/v850/simops.h index 750fb70..f18da2f 100644 --- a/sim/v850/simops.h +++ b/sim/v850/simops.h @@ -75,4 +75,51 @@ int OP_22007E0 (void); int OP_307F0 (void); int OP_107F0 (void); int OP_307E0 (void); + +int v850_float_compare(SIM_DESC sd, int cmp, sim_fpu wop1, sim_fpu wop2, int double_op_p); + +/* MEMORY ACCESS */ +unsigned32 load_data_mem(SIM_DESC sd, SIM_ADDR addr, int len); +void store_data_mem(SIM_DESC sd, SIM_ADDR addr, int len, unsigned32 data); + +unsigned long Add32 (unsigned long a1, unsigned long a2, int * carry); + +/* FPU */ + +/* + FPU: update FPSR flags + invalid, inexact, overflow, underflow + */ + +extern void check_invalid_snan (SIM_DESC sd, sim_fpu_status, unsigned int); + +#define check_cvt_fi(sd, status, double_op_p) \ + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI, double_op_p) + +#define check_cvt_if(sd, status, double_op_p) \ + update_fpsr (sd, status, FPSR_XEI, double_op_p) + +#define check_cvt_ff(sd, status, double_op_p) \ + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, double_op_p) + +extern void update_fpsr (SIM_DESC sd, sim_fpu_status, unsigned int, unsigned int); + + +/* + Exception + */ +void SignalException (SIM_DESC sd); +void SignalExceptionFPE (SIM_DESC sd, unsigned int double_op_p); + +int mpu_load_mem_test (SIM_DESC sd, unsigned int addr, int len, int base_reg); +int mpu_store_mem_test (SIM_DESC sd, unsigned int addr, int len, int base_reg); + +void v850_sar (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p); +void v850_shl (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p); +void v850_shr (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p); +void v850_satadd (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p); +void v850_satsub (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p); +void v850_div (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p, unsigned int *op3p); +void v850_divu (SIM_DESC sd, unsigned int op0, unsigned int op1, unsigned int *op2p, unsigned int *op3p); + #endif diff --git a/sim/v850/v850-dc b/sim/v850/v850-dc index 29fa127..ffaa406 100644 --- a/sim/v850/v850-dc +++ b/sim/v850/v850-dc @@ -12,7 +12,9 @@ switch,combine : 4 : 0 : : : : 1 : V,VII : switch,combine : 4 : 0 : : : : 1 : V,XIII : v850e switch,combine : 4 : 0 : : : : 1 : V,XIII : v850e1 - + switch,combine : 4 : 0 : : : : 1 : V,XIII : v850e2 + switch,combine : 4 : 0 : : : : 1 : V,XIII : v850e2v3 + switch,combine : 10 : 5 : : : : 0 : F_I : v850e2v3 # for opcode 63, 127, 1087 et.al. @@ -27,3 +29,28 @@ # for opcode 66 - divh/break switch,combine : 4 : 0 : : : : 0 : I : + +# for ilgop, macu + switch,combine : 10 : 9 : : : : 1 : X,XI : v850e2 + switch,combine : 10 : 9 : : : : 1 : X,XI : v850e2v3 + +#for cmovf.s, setf + switch,combine : 10 : 10 : : : : 1 :F_I,IX : v850e2v3 + +# for cmovf.s trfsr + switch,combine : 15 : 11 : : : : 1 :F_I : v850e2v3 + +# for trncf.sw, cvtf.sw + switch,combine : 0 : 0 : : : : 0 :F_I : v850e2v3 + switch,combine : 3 : 3 : : : : 0 :F_I : v850e2v3 + +# for rsqrtf.s, sqrtf.s + switch,combine : 1 : 1 : : : : 0 :F_I : v850e2v3 + +# for maddf.s, trap + switch,combine : 8 : 8 : : : : 1 :F_I,X : v850e2v3 + switch,combine : 10 : 10 : : : : 1 :F_I,X : v850e2v3 + +# for jr32 jarl32 + switch,combine : 4 : 0 : : : : 0 :VI : v850e2 + switch,combine : 4 : 0 : : : : 0 :VI : v850e2v3 diff --git a/sim/v850/v850.igen b/sim/v850/v850.igen index c0382bc..9645d28 100644 --- a/sim/v850/v850.igen +++ b/sim/v850/v850.igen @@ -6,6 +6,7 @@ :option:::format-names:XI,XII,XIII :option:::format-names:XIV,XV :option:::format-names:Z +:option:::format-names:F_I :model:::v850:v850: @@ -14,12 +15,22 @@ :model:::v850e:v850e: :option:::multi-sim:true :model:::v850e1:v850e1: +:option:::multi-sim:true +:model:::v850e2:v850e2: +:option:::multi-sim:true +:model:::v850e2v3:v850e2v3: // Cache macros :cache:::unsigned:reg1:RRRRR:(RRRRR) :cache:::unsigned:reg2:rrrrr:(rrrrr) :cache:::unsigned:reg3:wwwww:(wwwww) +:cache:::unsigned:reg4:W,WWWW:((W << 4) + WWWW) + +:cache:::unsigned:reg1e:RRRR:(RRRR << 1) +:cache:::unsigned:reg2e:rrrr:(rrrr << 1) +:cache:::unsigned:reg3e:wwww:(wwww << 1) +:cache:::unsigned:reg4e:mmmm:(mmmm << 1) :cache:::unsigned:disp4:dddd:(dddd) :cache:::unsigned:disp5:dddd:(dddd << 1) @@ -29,7 +40,10 @@ :cache:::unsigned:disp9:ddddd,ddd:SEXT32 ((ddddd << 4) + (ddd << 1), 9 - 1) :cache:::unsigned:disp16:dddddddddddddddd:EXTEND16 (dddddddddddddddd) :cache:::unsigned:disp16:ddddddddddddddd: EXTEND16 (ddddddddddddddd << 1) +:cache:::unsigned:disp17:d,ddddddddddddddd:SEXT32 (((d <<16) + (ddddddddddddddd << 1)), 17 - 1) :cache:::unsigned:disp22:dddddd,ddddddddddddddd: SEXT32 ((dddddd << 16) + (ddddddddddddddd << 1), 22 - 1) +:cache:::unsigned:disp23:ddddddd,dddddddddddddddd: SEXT32 ((ddddddd) + (dddddddddddddddd << 7), 23 - 1) +:cache:::unsigned:disp23:dddddd,dddddddddddddddd: SEXT32 ((dddddd << 1) + (dddddddddddddddd << 7), 23 - 1) :cache:::unsigned:imm5:iiiii:SEXT32 (iiiii, 4) :cache:::unsigned:imm6:iiiiii:iiiiii @@ -46,6 +60,7 @@ :cache:::unsigned:list18:LLLL,LLLLLLLLLLLL:((LLLL << 12) + LLLLLLLLLLLL) :cache:::unsigned:bit3:bbb:bbb +:cache:::unsigned:bit4:bbbb:bbbb // What do we do with an illegal instruction? @@ -58,8 +73,7 @@ -// Add - +// ADD rrrrr,001110,RRRRR:I:::add "add r<reg1>, r<reg2>" { @@ -83,6 +97,20 @@ rrrrr,110000,RRRRR + iiiiiiiiiiiiiiii:VI:::addi +// ADF +rrrrr,111111,RRRRR + wwwww,011101,cccc!13,0:XI:::adf +*v850e2 +*v850e2v3 +"adf %s<cccc>, r<reg1>, r<reg2>, r<reg3>" +{ + int cond = condition_met (cccc); + TRACE_ALU_INPUT3 (cond, GR[reg1], GR[reg2]); + GR[reg3] = GR[reg1] + GR[reg2] + (cond ? 1 : 0); + TRACE_ALU_RESULT1 (GR[reg3]); +} + + + // AND rrrrr,001010,RRRRR:I:::and "and r<reg1>, r<reg2>" @@ -153,12 +181,27 @@ ddddd,1011,ddd,cccc:III:::Bcond } } +00000111111,d,cccc + ddddddddddddddd,1:VII:::Bcond +"breakpoint":((disp17 == 0) && (cccc == 0x05)) +"b%s<cccc> <disp17>" +*v850e2v3 +{ + int cond; + cond = condition_met (cccc); + if (cond) + nia = cia + disp17; + TRACE_BRANCH_INPUT1 (cond); + TRACE_BRANCH_RESULT (nia); +} + // BSH rrrrr,11111100000 + wwwww,01101000010:XII:::bsh *v850e *v850e1 +*v850e2 +*v850e2v3 "bsh r<reg2>, r<reg3>" { unsigned32 value; @@ -178,10 +221,14 @@ rrrrr,11111100000 + wwwww,01101000010:XII:::bsh TRACE_ALU_RESULT (GR[reg3]); } + + // BSW rrrrr,11111100000 + wwwww,01101000000:XII:::bsw *v850e *v850e1 +*v850e2 +*v850e2v3 "bsw r<reg2>, r<reg3>" { #define WORDHASNULLBYTE(x) (((x) - 0x01010101) & ~(x)&0x80808080) @@ -204,10 +251,14 @@ rrrrr,11111100000 + wwwww,01101000000:XII:::bsw TRACE_ALU_RESULT (GR[reg3]); } + + // CALLT 0000001000,iiiiii:II:::callt *v850e *v850e1 +*v850e2 +*v850e2v3 "callt <imm6>" { unsigned32 adr; @@ -221,6 +272,55 @@ rrrrr,11111100000 + wwwww,01101000000:XII:::bsw } + +// CAXI +rrrrr,111111,RRRRR + wwwww,00011101110:IX:::caxi +*v850e2 +*v850e2v3 +"caxi [reg1], reg2, reg3" +{ + unsigned int z,s,cy,ov; + unsigned32 addr; + unsigned32 token,result; + + addr = GR[reg1]; + + if (mpu_load_mem_test(sd, addr, 4, reg1) + && mpu_store_mem_test(sd, addr, 4, reg1)) + { + token = load_data_mem (sd, addr, 4); + + TRACE_ALU_INPUT2 (token, GR[reg2]); + + result = GR[reg2] - token; + + z = (result == 0); + s = (result & 0x80000000); + cy = (GR[reg2] < token); + ov = ((GR[reg2] & 0x80000000) != (token & 0x80000000) + && (GR[reg2] & 0x80000000) != (result & 0x80000000)); + + if (result == 0) + { + store_data_mem (sd, addr, 4, GR[reg3]); + GR[reg3] = token; + } + else + { + store_data_mem (sd, addr, 4, token); + GR[reg3] = token; + } + + /* Set condition codes. */ + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0) + | (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)); + + TRACE_ALU_RESULT1 (GR[reg3]); + } +} + + // CLR1 10,bbb,111110,RRRRR + dddddddddddddddd:VIII:::clr1 "clr1 <bit3>, <disp16>[r<reg1>]" @@ -231,16 +331,21 @@ rrrrr,11111100000 + wwwww,01101000000:XII:::bsw rrrrr,111111,RRRRR + 0000000011100100:IX:::clr1 *v850e *v850e1 +*v850e2 +*v850e2v3 "clr1 r<reg2>, [r<reg1>]" { COMPAT_2 (OP_E407E0 ()); } + // CTRET 0000011111100000 + 0000000101000100:X:::ctret *v850e *v850e1 +*v850e2 +*v850e2v3 "ctret" { nia = (CTPC & ~1); @@ -248,10 +353,14 @@ rrrrr,111111,RRRRR + 0000000011100100:IX:::clr1 TRACE_BRANCH1 (PSW); } + + // CMOV rrrrr,111111,RRRRR + wwwww,011001,cccc,0:XI:::cmov *v850e *v850e1 +*v850e2 +*v850e2v3 "cmov %s<cccc>, r<reg1>, r<reg2>, r<reg3>" { int cond = condition_met (cccc); @@ -263,6 +372,8 @@ rrrrr,111111,RRRRR + wwwww,011001,cccc,0:XI:::cmov rrrrr,111111,iiiii + wwwww,011000,cccc,0:XII:::cmov *v850e *v850e1 +*v850e2 +*v850e2v3 "cmov %s<cccc>, <imm5>, r<reg2>, r<reg3>" { int cond = condition_met (cccc); @@ -271,6 +382,8 @@ rrrrr,111111,iiiii + wwwww,011000,cccc,0:XII:::cmov TRACE_ALU_RESULT (GR[reg3]); } + + // CMP rrrrr,001111,RRRRR:I:::cmp "cmp r<reg1>, r<reg2>" @@ -301,6 +414,8 @@ rrrrr,010011,iiiii:II:::cmp 0000011001,iiiii,L + LLLLLLLLLLL,RRRRR:XIII:::dispose *v850e *v850e1 +*v850e2 +*v850e2v3 "dispose <imm5>, <list12>":RRRRR == 0 "dispose <imm5>, <list12>, [reg1]" { @@ -329,10 +444,13 @@ rrrrr,010011,iiiii:II:::cmp } + // DIV rrrrr,111111,RRRRR + wwwww,01011000000:XI:::div *v850e *v850e1 +*v850e2 +*v850e2v3 "div r<reg1>, r<reg2>, r<reg3>" { COMPAT_2 (OP_2C007E0 ()); @@ -390,6 +508,8 @@ rrrrr!0,000010,RRRRR!0:I:::divh rrrrr,111111,RRRRR + wwwww,01010000000:XI:::divh *v850e *v850e1 +*v850e2 +*v850e2v3 "divh r<reg1>, r<reg2>, r<reg3>" { COMPAT_2 (OP_28007E0 ()); @@ -400,6 +520,8 @@ rrrrr,111111,RRRRR + wwwww,01010000000:XI:::divh rrrrr,111111,RRRRR + wwwww,01010000010:XI:::divhu *v850e *v850e1 +*v850e2 +*v850e2v3 "divhu r<reg1>, r<reg2>, r<reg3>" { COMPAT_2 (OP_28207E0 ()); @@ -410,12 +532,60 @@ rrrrr,111111,RRRRR + wwwww,01010000010:XI:::divhu rrrrr,111111,RRRRR + wwwww,01011000010:XI:::divu *v850e *v850e1 +*v850e2 +*v850e2v3 "divu r<reg1>, r<reg2>, r<reg3>" { COMPAT_2 (OP_2C207E0 ()); } +// DIVQ +rrrrr,111111,RRRRR + wwwww,01011111100:XI:::divq +*v850e2 +*v850e2v3 +"divq r<reg1>, r<reg2>, r<reg3>" +{ + unsigned int quotient; + unsigned int remainder; + unsigned int divide_by; + unsigned int divide_this; + + TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]); + + divide_by = GR[reg1]; + divide_this = GR[reg2]; + v850_div (sd, divide_by, divide_this, "ient, &remainder); + GR[reg2] = quotient; + GR[reg3] = remainder; + + TRACE_ALU_RESULT2 (GR[reg2], GR[reg3]); +} + + +// DIVQU +rrrrr,111111,RRRRR + wwwww,01011111110:XI:::divqu +*v850e2 +*v850e2v3 +"divq r<reg1>, r<reg2>, r<reg3>" +{ + unsigned int quotient; + unsigned int remainder; + unsigned int divide_by; + unsigned int divide_this; + + TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]); + + divide_by = GR[reg1]; + divide_this = GR[reg2]; + v850_divu (sd, divide_by, divide_this, "ient, &remainder); + GR[reg2] = quotient; + GR[reg3] = remainder; + + TRACE_ALU_RESULT2 (GR[reg2], GR[reg3]); +} + + // EI 1000011111100000 + 0000000101100000:X:::ei "ei" @@ -425,6 +595,76 @@ rrrrr,111111,RRRRR + wwwww,01011000010:XI:::divu +// EIRET +0000011111100000 + 0000000101001000:X:::eiret +"eiret" +*v850e2 +*v850e2v3 +{ + TRACE_ALU_INPUT1 (MPM & MPM_AUE); + + nia = EIPC; /* next PC */ + if (MPM & MPM_AUE) + { + PSW = EIPSW; + } + else + { + PSW = (PSW & (PSW_NPV | PSW_DMP | PSW_IMP)) + | (EIPSW & ~(PSW_NPV | PSW_DMP | PSW_IMP)); + } + + TRACE_ALU_RESULT1 (PSW); + TRACE_BRANCH_RESULT (nia); +} + + + +// FERET +0000011111100000 + 0000000101001010:X:::feret +"feret" +*v850e2 +*v850e2v3 +{ + TRACE_ALU_INPUT1 (MPM & MPM_AUE); + + nia = FEPC; /* next PC */ + if (MPM & MPM_AUE) + { + PSW = FEPSW; + } + else + { + PSW = (PSW & (PSW_NPV | PSW_DMP | PSW_IMP)) + | (FEPSW & ~(PSW_NPV | PSW_DMP | PSW_IMP)); + } + + TRACE_ALU_RESULT1 (PSW); + TRACE_BRANCH_RESULT (nia); +} + + +// FETRAP +0,bbbb!0,00001000000:I:::fetrap +"fetrap" +*v850e2 +*v850e2v3 +{ + TRACE_ALU_INPUT0 (); + + FEPC = PC + 2; + FEPSW = PSW; + ECR &= ~ECR_FECC; + ECR |= (0x30 + bit4) << 16; + FEIC = 0x30 + bit4; + PSW |= PSW_EP | PSW_ID | PSW_NP; + nia = 0x30; /* next PC */ + + TRACE_ALU_RESULT1 (PSW); + TRACE_BRANCH_RESULT (nia); +} + + // HALT 0000011111100000 + 0000000100100000:X:::halt "halt" @@ -434,10 +674,33 @@ rrrrr,111111,RRRRR + wwwww,01011000010:XI:::divu +// HSH +rrrrr,11111100000 + wwwww,01101000110:XII:::hsh +*v850e2 +*v850e2v3 +"hsh r<reg2>, r<reg3>" +{ + unsigned32 value; + TRACE_ALU_INPUT1 (GR[reg2]); + + value = 0xffff & GR[reg2]; + GR[reg3] = GR[reg2]; + + PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV); + + if (value == 0) { PSW |= PSW_Z; PSW |= PSW_CY; } + if (value & 0x80000000) PSW |= PSW_S; + + TRACE_ALU_RESULT1 (GR[reg3]); +} + + // HSW rrrrr,11111100000 + wwwww,01101000100:XII:::hsw *v850e *v850e1 +*v850e2 +*v850e2v3 "hsw r<reg2>, r<reg3>" { unsigned32 value; @@ -469,6 +732,16 @@ rrrrr!0,11110,dddddd + ddddddddddddddd,0:V:::jarl TRACE_BRANCH1 (GR[reg2]); } +00000010111,RRRRR!0 + iiiiiiiiiiiiiiii + IIIIIIIIIIIIIIII:VI:::jarl32 +*v850e2 +*v850e2v3 +"jarl <imm32>, r<reg1>" +{ + GR[reg1] = nia; + nia = (cia + imm32) & ~1; + + TRACE_BRANCH_RESULT (nia); +} // JMP @@ -479,6 +752,15 @@ rrrrr!0,11110,dddddd + ddddddddddddddd,0:V:::jarl TRACE_BRANCH0 (); } +00000110111,RRRRR + iiiiiiiiiiiiiiii + IIIIIIIIIIIIIIII:VI:::jmp32 +*v850e2 +*v850e2v3 +"jmp <imm32>[r<reg1>]" +{ + nia = (GR[reg1] + imm32) & ~1; + + TRACE_BRANCH_RESULT (nia); +} // JR @@ -490,6 +772,17 @@ rrrrr!0,11110,dddddd + ddddddddddddddd,0:V:::jarl } +// JR32 +00000010111,00000 + iiiiiiiiiiiiiiii + IIIIIIIIIIIIIIII:VI:::jr32 +*v850e2 +*v850e2v3 +"jr <imm32>" +{ + nia = (cia + imm32) & ~1; + + TRACE_BRANCH_RESULT (nia); +} + // LD rrrrr,111000,RRRRR + dddddddddddddddd:VII:::ld.b @@ -498,47 +791,368 @@ rrrrr,111000,RRRRR + dddddddddddddddd:VII:::ld.b COMPAT_2 (OP_700 ()); } +00000111100,RRRRR+wwwww,ddddddd,0101+dddddddddddddddd:XIV:::ld.b +"ld.b <disp23>[r<reg1>], r<reg3>" +*v850e2v3 +{ + unsigned32 addr = GR[reg1] + disp23; + unsigned32 result = EXTEND8 (load_data_mem (sd, addr, 1)); + GR[reg3] = result; + TRACE_LD (addr, result); +} + rrrrr,111001,RRRRR + ddddddddddddddd,0:VII:::ld.h "ld.h <disp16>[r<reg1>], r<reg2>" { COMPAT_2 (OP_720 ()); } +00000111100,RRRRR+wwwww,dddddd,00111+dddddddddddddddd:XIV:::ld.h +*v850e2v3 +"ld.h <disp23>[r<reg1>], r<reg3>" +{ + unsigned32 addr = GR[reg1] + disp23; + unsigned32 result = EXTEND16 (load_data_mem (sd, addr, 2)); + GR[reg3] = result; + TRACE_LD (addr, result); +} + rrrrr,111001,RRRRR + ddddddddddddddd,1:VII:::ld.w "ld.w <disp16>[r<reg1>], r<reg2>" { COMPAT_2 (OP_10720 ()); } +00000111100,RRRRR+wwwww,dddddd,01001+dddddddddddddddd:XIV:::ld.w +*v850e2v3 +"ld.w <disp23>[r<reg1>], r<reg3>" +{ + unsigned32 addr = GR[reg1] + disp23; + unsigned32 result = load_data_mem (sd, addr, 4); + GR[reg3] = result; + TRACE_LD (addr, result); +} + rrrrr!0,11110,b,RRRRR + ddddddddddddddd,1:VII:::ld.bu *v850e *v850e1 +*v850e2 +*v850e2v3 "ld.bu <disp16>[r<reg1>], r<reg2>" { COMPAT_2 (OP_10780 ()); } +00000111101,RRRRR+wwwww,ddddddd,0101+dddddddddddddddd:XIV:::ld.bu +*v850e2v3 +"ld.bu <disp23>[r<reg1>], r<reg3>" +{ + unsigned32 addr = GR[reg1] + disp23; + unsigned32 result = load_data_mem (sd, addr, 1); + GR[reg3] = result; + TRACE_LD (addr, result); +} + rrrrr!0,111111,RRRRR + ddddddddddddddd,1:VII:::ld.hu *v850e *v850e1 +*v850e2 +*v850e2v3 "ld.hu <disp16>[r<reg1>], r<reg2>" { COMPAT_2 (OP_107E0 ()); } +00000111101,RRRRR+wwwww,dddddd,00111+dddddddddddddddd:XIV:::ld.hu +*v850e2v3 +"ld.hu <disp23>[r<reg1>], r<reg3>" +{ + unsigned32 addr = GR[reg1] + disp23; + unsigned32 result = load_data_mem (sd, addr, 2); + GR[reg3] = result; + TRACE_LD (addr, result); +} + + // LDSR regID,111111,RRRRR + 0000000000100000:IX:::ldsr "ldsr r<reg1>, s<regID>" { + uint32 sreg = GR[reg1]; TRACE_ALU_INPUT1 (GR[reg1]); - if (&PSW == &SR[regID]) - PSW = (GR[reg1] & (CPU)->psw_mask); + if ((idecode_issue == idecode_v850e2_issue + || idecode_issue == idecode_v850e2v3_issue) + && regID < 28) + { + int protect_p = (PSW & PSW_NPV) ? 1 : 0; + + + switch (BSEL & 0xffff) + { + case 0x0000: + if ((PSW & PSW_NPV) + && ((regID >= 8 && regID <= 12) + || (regID >= 22 && regID <= 27) + || regID == PSW_REGNO)) + { + protect_p = 0; + } + break; + case 0x1000: /* MPU0 */ + break; + case 0x1001: /* MPU1 */ + break; + case 0x2000: /* FPU */ + if ((PSW & PSW_NPV) + && ((/* regID >= 0 && */ regID <= 5) + || regID == 8 + || regID == 9 + || regID == 10 + || (regID >= 11 && regID <= 26))) + { + protect_p = 0; + } + break; + case 0xff00: + if ((PSW & PSW_NPV) + && (regID == 6 + || regID == 7 + || regID == 8 + || regID == 9 + || regID == 10 + || (regID >= 11 && regID <= 15) + || regID == 18 + || regID == 19 + || (regID >= 21 && regID <= 27))) + { + protect_p = 0; + } + break; + case 0xffff: + if ((PSW & PSW_NPV) + && (regID == 6 + || regID == 7 + || regID == 8 + || regID == 9 + || regID == 10 + || regID == 11 + || regID == 12 + || regID == 15 + || regID == 18 + || regID == 19 + || (regID >= 21 && regID <= 27))) + { + protect_p = 0; + } + break; + } + + if (!protect_p) + { + switch (BSEL & 0xffff) + { + case 0x0000: + case 0xff00: /* user0 bank */ + case 0xffff: /* user1 bank */ + if(regID == PSW_REGNO) + { + SR[regID] = sreg & ((PSW & PSW_NPV) ? 0xf : ~0); + } + else + { + SR[regID] = sreg; + } + break; + case 0x1000: + MPU0_SR[regID] = sreg; + break; + case 0x1001: + if (regID == MPC_REGNO) + { + PPC &= ~PPC_PPE; + SPAL &= ~SPAL_SPE; + IPA0L &= ~IPA_IPE; + IPA1L &= ~IPA_IPE; + IPA2L &= ~IPA_IPE; + IPA3L &= ~IPA_IPE; + DPA0L &= ~DPA_DPE; + DPA1L &= ~DPA_DPE; + DCC &= ~(DCC_DCE0 | DCC_DCE1); + } + else + { + MPU1_SR[regID] = sreg; + } + break; + case 0x2000: /* FPU */ + if (regID == FPST_REGNO) + { + unsigned int val = FPSR & ~(FPSR_PR | FPSR_XC | FPSR_XP); + + val |= ((sreg & FPST_PR) ? FPSR_PR : 0) + | ((sreg & FPST_XCE) ? FPSR_XCE : 0) + | ((sreg & FPST_XCV) ? FPSR_XCV : 0) + | ((sreg & FPST_XCZ) ? FPSR_XCZ : 0) + | ((sreg & FPST_XCO) ? FPSR_XCO : 0) + | ((sreg & FPST_XCU) ? FPSR_XCU : 0) + | ((sreg & FPST_XCI) ? FPSR_XCI : 0) + | ((sreg & FPST_XPV) ? FPSR_XPV : 0) + | ((sreg & FPST_XPZ) ? FPSR_XPZ : 0) + | ((sreg & FPST_XPO) ? FPSR_XPO : 0) + | ((sreg & FPST_XPU) ? FPSR_XPU : 0) + | ((sreg & FPST_XPI) ? FPSR_XPI : 0); + FPSR = val; + } + else if (regID == FPCFG_REGNO) + { + unsigned int val = FPSR & ~(FPSR_RM | FPSR_XE); + + val |= (((sreg & FPCFG_RM) >> 7) << 18) + | ((sreg & FPCFG_XEV) ? FPSR_XEV : 0) + | ((sreg & FPCFG_XEZ) ? FPSR_XEZ : 0) + | ((sreg & FPCFG_XEO) ? FPSR_XEO : 0) + | ((sreg & FPCFG_XEU) ? FPSR_XEU : 0) + | ((sreg & FPCFG_XEI) ? FPSR_XEI : 0); + FPSR = val; + } + + FPU_SR[regID] = sreg; + break; + } + } + } else - SR[regID] = GR[reg1]; + { + SR[regID] = sreg; + } + + TRACE_ALU_RESULT (sreg); +} + + + +// MAC +rrrrr,111111,RRRRR + wwww,0011110,mmmm,0:XI:::mac +*v850e2 +*v850e2v3 +"mac r<reg1>, r<reg2>, r<reg3e>, r<reg4e>" +{ + unsigned long op0; + unsigned long op1; + unsigned long op2; + unsigned long op2hi; + unsigned long lo; + unsigned long mid1; + unsigned long mid2; + unsigned long hi; + unsigned long RdLo; + unsigned long RdHi; + int carry; + bfd_boolean sign; + + op0 = GR[reg1]; + op1 = GR[reg2]; + op2 = GR[reg3e]; + op2hi = GR[reg3e+1]; + + TRACE_ALU_INPUT4 (op0, op1, op2, op2hi); + + sign = (op0 ^ op1) & 0x80000000; + + if (((signed long) op0) < 0) + op0 = - op0; + + if (((signed long) op1) < 0) + op1 = - op1; + + /* We can split the 32x32 into four 16x16 operations. This ensures + that we do not lose precision on 32bit only hosts: */ + lo = ( (op0 & 0xFFFF) * (op1 & 0xFFFF)); + mid1 = ( (op0 & 0xFFFF) * ((op1 >> 16) & 0xFFFF)); + mid2 = (((op0 >> 16) & 0xFFFF) * (op1 & 0xFFFF)); + hi = (((op0 >> 16) & 0xFFFF) * ((op1 >> 16) & 0xFFFF)); - TRACE_ALU_RESULT (SR[regID]); + /* We now need to add all of these results together, taking care + to propogate the carries from the additions: */ + RdLo = Add32 (lo, (mid1 << 16), & carry); + RdHi = carry; + RdLo = Add32 (RdLo, (mid2 << 16), & carry); + RdHi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi); + + if (sign) + { + RdLo = ~ RdLo; + RdHi = ~ RdHi; + if (RdLo == 0xFFFFFFFF) + { + RdLo = 0; + RdHi += 1; + } + else + RdLo += 1; + } + + RdLo = Add32 (RdLo, op2, & carry); + RdHi += carry + op2hi; + + /* Store the result and condition codes. */ + GR[reg4e] = RdLo; + GR[reg4e + 1 ] = RdHi; + + TRACE_ALU_RESULT2 (RdLo, RdHi); +} + + + +// MACU +rrrrr,111111,RRRRR + wwww,0011111,mmmm,0:XI:::macu +*v850e2 +*v850e2v3 +"macu r<reg1>, r<reg2>, r<reg3e>, r<reg4e>" +{ + unsigned long op0; + unsigned long op1; + unsigned long op2; + unsigned long op2hi; + unsigned long lo; + unsigned long mid1; + unsigned long mid2; + unsigned long hi; + unsigned long RdLo; + unsigned long RdHi; + int carry; + + op0 = GR[reg1]; + op1 = GR[reg2]; + op2 = GR[reg3e]; + op2hi = GR[reg3e + 1]; + + TRACE_ALU_INPUT4 (op0, op1, op2, op2hi); + + /* We can split the 32x32 into four 16x16 operations. This ensures + that we do not lose precision on 32bit only hosts: */ + lo = ( (op0 & 0xFFFF) * (op1 & 0xFFFF)); + mid1 = ( (op0 & 0xFFFF) * ((op1 >> 16) & 0xFFFF)); + mid2 = (((op0 >> 16) & 0xFFFF) * (op1 & 0xFFFF)); + hi = (((op0 >> 16) & 0xFFFF) * ((op1 >> 16) & 0xFFFF)); + + /* We now need to add all of these results together, taking care + to propogate the carries from the additions: */ + RdLo = Add32 (lo, (mid1 << 16), & carry); + RdHi = carry; + RdLo = Add32 (RdLo, (mid2 << 16), & carry); + RdHi += (carry + ((mid1 >> 16) & 0xFFFF) + ((mid2 >> 16) & 0xFFFF) + hi); + + RdLo = Add32 (RdLo, op2, & carry); + RdHi += carry + op2hi; + + /* Store the result and condition codes. */ + GR[reg4e] = RdLo; + GR[reg4e+1] = RdHi; + + TRACE_ALU_RESULT2 (RdLo, RdHi); } @@ -552,7 +1166,6 @@ rrrrr!0,000000,RRRRR:I:::mov TRACE_ALU_RESULT (GR[reg2]); } - rrrrr!0,010000,iiiii:II:::mov "mov <imm5>, r<reg2>" { @@ -562,6 +1175,8 @@ rrrrr!0,010000,iiiii:II:::mov 00000110001,RRRRR + iiiiiiiiiiiiiiii + IIIIIIIIIIIIIIII:VI:::mov *v850e *v850e1 +*v850e2 +*v850e2v3 "mov <imm32>, r<reg1>" { SAVE_2; @@ -596,6 +1211,8 @@ rrrrr!0,110010,RRRRR + iiiiiiiiiiiiiiii:VI:::movhi rrrrr,111111,RRRRR + wwwww,01000100000:XI:::mul *v850e *v850e1 +*v850e2 +*v850e2v3 "mul r<reg1>, r<reg2>, r<reg3>" { COMPAT_2 (OP_22007E0 ()); @@ -604,6 +1221,8 @@ rrrrr,111111,RRRRR + wwwww,01000100000:XI:::mul rrrrr,111111,iiiii + wwwww,01001,IIII,00:XII:::mul *v850e *v850e1 +*v850e2 +*v850e2v3 "mul <imm9>, r<reg2>, r<reg3>" { COMPAT_2 (OP_24007E0 ()); @@ -638,6 +1257,8 @@ rrrrr!0,110111,RRRRR + iiiiiiiiiiiiiiii:VI:::mulhi rrrrr,111111,RRRRR + wwwww,01000100010:XI:::mulu *v850e *v850e1 +*v850e2 +*v850e2v3 "mulu r<reg1>, r<reg2>, r<reg3>" { COMPAT_2 (OP_22207E0 ()); @@ -646,6 +1267,8 @@ rrrrr,111111,RRRRR + wwwww,01000100010:XI:::mulu rrrrr,111111,iiiii + wwwww,01001,IIII,10:XII:::mulu *v850e *v850e1 +*v850e2 +*v850e2v3 "mulu <imm9>, r<reg2>, r<reg3>" { COMPAT_2 (OP_24207E0 ()); @@ -681,6 +1304,8 @@ rrrrr,000001,RRRRR:I:::not rrrrr,111111,RRRRR + 0000000011100010:IX:::not1 *v850e *v850e1 +*v850e2 +*v850e2v3 "not1 r<reg2>, r<reg1>" { COMPAT_2 (OP_E207E0 ()); @@ -710,6 +1335,8 @@ rrrrr,110100,RRRRR + iiiiiiiiiiiiiiii:VI:::ori 0000011110,iiiii,L + LLLLLLLLLLL,00001:XIII:::prepare *v850e *v850e1 +*v850e2 +*v850e2v3 "prepare <list12>, <imm5>" { int i; @@ -735,6 +1362,8 @@ rrrrr,110100,RRRRR + iiiiiiiiiiiiiiii:VI:::ori 0000011110,iiiii,L + LLLLLLLLLLL,00011:XIII:::prepare00 *v850e *v850e1 +*v850e2 +*v850e2v3 "prepare <list12>, <imm5>, sp" { COMPAT_2 (OP_30780 ()); @@ -743,6 +1372,8 @@ rrrrr,110100,RRRRR + iiiiiiiiiiiiiiii:VI:::ori 0000011110,iiiii,L + LLLLLLLLLLL,01011 + iiiiiiiiiiiiiiii:XIII:::prepare01 *v850e *v850e1 +*v850e2 +*v850e2v3 "prepare <list12>, <imm5>, <uimm16>" { COMPAT_2 (OP_B0780 ()); @@ -751,6 +1382,8 @@ rrrrr,110100,RRRRR + iiiiiiiiiiiiiiii:VI:::ori 0000011110,iiiii,L + LLLLLLLLLLL,10011 + iiiiiiiiiiiiiiii:XIII:::prepare10 *v850e *v850e1 +*v850e2 +*v850e2v3 "prepare <list12>, <imm5>, <uimm16>" { COMPAT_2 (OP_130780 ()); @@ -759,6 +1392,8 @@ rrrrr,110100,RRRRR + iiiiiiiiiiiiiiii:VI:::ori 0000011110,iiiii,L + LLLLLLLLLLL,11011 + iiiiiiiiiiiiiiii + dddddddddddddddd:XIII:::prepare11 *v850e *v850e1 +*v850e2 +*v850e2v3 "prepare <list12>, <imm5>, <uimm32>" { COMPAT_2 (OP_1B0780 ()); @@ -803,12 +1438,23 @@ rrrrr,010101,iiiii:II:::sar COMPAT_1 (OP_2A0 ()); } +rrrrr,111111,RRRRR + wwwww,00010100010:XI:::sar +*v850e2 +*v850e2v3 +"sar r<reg1>, r<reg2>, r<reg3>" +{ + TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]); + v850_sar(sd, GR[reg1], GR[reg2], &GR[reg3]); + TRACE_ALU_RESULT1 (GR[reg3]); +} // SASF rrrrr,1111110,cccc + 0000001000000000:IX:::sasf *v850e *v850e1 +*v850e2 +*v850e2v3 "sasf %s<cccc>, r<reg2>" { COMPAT_2 (OP_20007E0 ()); @@ -816,7 +1462,6 @@ rrrrr,1111110,cccc + 0000001000000000:IX:::sasf - // SATADD rrrrr!0,000110,RRRRR:I:::satadd "satadd r<reg1>, r<reg2>" @@ -830,6 +1475,16 @@ rrrrr!0,010001,iiiii:II:::satadd COMPAT_1 (OP_220 ()); } +rrrrr,111111,RRRRR + wwwww,01110111010:XI:::satadd +*v850e2 +*v850e2v3 +"satadd r<reg1>, r<reg2>, r<reg3>" +{ + TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]); + v850_satadd (sd, GR[reg1], GR[reg2], &GR[reg3]); + TRACE_ALU_RESULT1 (GR[reg3]); +} + // SATSUB @@ -839,6 +1494,16 @@ rrrrr!0,000101,RRRRR:I:::satsub COMPAT_1 (OP_A0 ()); } +rrrrr,111111,RRRRR + wwwww,01110011010:XI:::satsub +*v850e2 +*v850e2v3 +"satsub r<reg1>, r<reg2>, r<reg3>" +{ + TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]); + v850_satsub (sd, GR[reg1], GR[reg2], &GR[reg3]); + TRACE_ALU_RESULT1 (GR[reg3]); +} + // SATSUBI @@ -859,6 +1524,234 @@ rrrrr!0,000100,RRRRR:I:::satsubr +//SBF +rrrrr,111111,RRRRR + wwwww,011100,cccc!13,0:XI:::sbf +*v850e2 +*v850e2v3 +"sbf %s<cccc>, r<reg1>, r<reg2>, r<reg3>" +{ + int cond = condition_met (cccc); + TRACE_ALU_INPUT3 (cond, GR[reg1], GR[reg2]); + GR[reg3] = GR[reg2] - GR[reg1] - (cond ? 1 : 0); + TRACE_ALU_RESULT1 (GR[reg3]); +} + + + +// SCH0L +rrrrr,11111100000 + wwwww,01101100100:IX:::sch0l +*v850e2 +*v850e2v3 +"sch0l r<reg2>, r<reg3>" +{ + unsigned int pos, op0; + + TRACE_ALU_INPUT1 (GR[reg2]); + + op0 = GR[reg2]; + + if (op0 == 0xffffffff) + { + PSW &= ~PSW_CY; + PSW &= ~PSW_OV; + PSW &= ~PSW_S; + PSW |= PSW_Z; + pos = 0; + } + else if (op0 == 0xfffffffe) + { + PSW |= PSW_CY; + PSW &= ~PSW_OV; + PSW &= ~PSW_S; + PSW &= ~PSW_Z; + pos = 32; + } + else + { + pos = 1; + while (op0 & 0x80000000) + { + op0 <<= 1; + pos++; + } + PSW &= ~PSW_CY; + PSW &= ~PSW_OV; + PSW &= ~PSW_S; + PSW &= ~PSW_Z; + } + + GR[reg3] = pos; + + TRACE_ALU_RESULT1 (GR[reg3]); +} + + + +// SCH0R +rrrrr,11111100000 + wwwww,01101100000:IX:::sch0r +*v850e2 +*v850e2v3 +"sch0r r<reg2>, r<reg3>" +{ + unsigned int pos, op0; + + TRACE_ALU_INPUT1 (GR[reg2]); + + op0 = GR[reg2]; + + if (op0 == 0xffffffff) + { + PSW &= ~PSW_CY; + PSW &= ~PSW_OV; + PSW &= ~PSW_S; + PSW |= PSW_Z; + pos = 0; + } + else if (op0 == 0x7fffffff) + { + PSW |= PSW_CY; + PSW &= ~PSW_OV; + PSW &= ~PSW_S; + PSW &= ~PSW_Z; + pos = 32; + } + else + { + pos = 1; + while (op0 & 0x00000001) + { + op0 >>= 1; + pos++; + } + PSW &= ~PSW_CY; + PSW &= ~PSW_OV; + PSW &= ~PSW_S; + PSW &= ~PSW_Z; + } + + GR[reg3] = pos; + + TRACE_ALU_RESULT1 (GR[reg3]); +} + +// SCH1L +rrrrr,11111100000 + wwwww,01101100110:IX:::sch1l +*v850e2 +*v850e2v3 +"sch1l r<reg2>, r<reg3>" +{ + unsigned int pos, op0; + + TRACE_ALU_INPUT1 (GR[reg2]); + + op0 = GR[reg2]; + + if (op0 == 0x00000000) + { + PSW &= ~PSW_CY; + PSW &= ~PSW_OV; + PSW &= ~PSW_S; + PSW |= PSW_Z; + pos = 0; + } + else if (op0 == 0x00000001) + { + PSW |= PSW_CY; + PSW &= ~PSW_OV; + PSW &= ~PSW_S; + PSW &= ~PSW_Z; + pos = 32; + } + else + { + pos = 1; + while (!(op0 & 0x80000000)) + { + op0 <<= 1; + pos++; + } + PSW &= ~PSW_CY; + PSW &= ~PSW_OV; + PSW &= ~PSW_S; + PSW &= ~PSW_Z; + } + + GR[reg3] = pos; + + TRACE_ALU_RESULT1 (GR[reg3]); +} + +// SCH1R +rrrrr,11111100000 + wwwww,01101100010:IX:::sch1r +*v850e2 +*v850e2v3 +"sch1r r<reg2>, r<reg3>" +{ + unsigned int pos, op0; + + TRACE_ALU_INPUT1 (GR[reg2]); + + op0 = GR[reg2]; + + if (op0 == 0x00000000) + { + PSW &= ~PSW_CY; + PSW &= ~PSW_OV; + PSW &= ~PSW_S; + PSW |= PSW_Z; + pos = 0; + } + else if (op0 == 0x80000000) + { + PSW |= PSW_CY; + PSW &= ~PSW_OV; + PSW &= ~PSW_S; + PSW &= ~PSW_Z; + pos = 32; + } + else + { + pos = 1; + while (!(op0 & 0x00000001)) + { + op0 >>= 1; + pos++; + } + PSW &= ~PSW_CY; + PSW &= ~PSW_OV; + PSW &= ~PSW_S; + PSW &= ~PSW_Z; + } + + GR[reg3] = pos; + + TRACE_ALU_RESULT1 (GR[reg3]); +} + +//SHL +rrrrr,111111,RRRRR + wwwww,00011000010:XI:::shl +*v850e2 +*v850e2v3 +"shl r<reg1>, r<reg2>, r<reg3>" +{ + TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]); + v850_shl(sd, GR[reg1], GR[reg2], &GR[reg3]); + TRACE_ALU_RESULT1 (GR[reg3]); +} + +//SHR +rrrrr,111111,RRRRR + wwwww,00010000010:XI:::shr +*v850e2 +*v850e2v3 +"shr r<reg1>, r<reg2>, r<reg3>" +{ + TRACE_ALU_INPUT2 (GR[reg1], GR[reg2]); + v850_shr(sd, GR[reg1], GR[reg2], &GR[reg3]); + TRACE_ALU_RESULT1 (GR[reg3]); +} + + + // SETF rrrrr,1111110,cccc + 0000000000000000:IX:::setf "setf %s<cccc>, r<reg2>" @@ -878,6 +1771,8 @@ rrrrr,1111110,cccc + 0000000000000000:IX:::setf rrrrr,111111,RRRRR + 0000000011100000:IX:::set1 *v850e *v850e1 +*v850e2 +*v850e2v3 "set1 r<reg2>, [r<reg1>]" { COMPAT_2 (OP_E007E0 ()); @@ -966,6 +1861,8 @@ rrrrr,1010,dddddd,0:IV:::sld.w rrrrr!0,0000110,dddd:IV:::sld.bu *v850e *v850e1 +*v850e2 +*v850e2v3 "sld.b <disp4>[ep], r<reg2>":(PSW & PSW_US) "sld.bu <disp4>[ep], r<reg2>" { @@ -987,6 +1884,8 @@ rrrrr!0,0000110,dddd:IV:::sld.bu rrrrr!0,0000111,dddd:IV:::sld.hu *v850e *v850e1 +*v850e2 +*v850e2v3 "sld.h <disp5>[ep], r<reg2>":(PSW & PSW_US) "sld.hu <disp5>[ep], r<reg2>" { @@ -1005,6 +1904,8 @@ rrrrr!0,0000111,dddd:IV:::sld.hu } } + + // SST rrrrr,0111,ddddddd:IV:::sst.b "sst.b r<reg2>, <disp7>[ep]" @@ -1031,24 +1932,108 @@ rrrrr,111010,RRRRR + dddddddddddddddd:VII:::st.b COMPAT_2 (OP_740 ()); } +00000111100,RRRRR + wwwww,ddddddd,1101 + dddddddddddddddd:XIV:::st.b +*v850e2v3 +"st.b r<reg3>, <disp23>[r<reg1>]" +{ + unsigned32 addr = GR[reg1] + disp23; + store_data_mem (sd, addr, 1, GR[reg3]); + TRACE_ST (addr, GR[reg3]); +} + rrrrr,111011,RRRRR + ddddddddddddddd,0:VII:::st.h "st.h r<reg2>, <disp16>[r<reg1>]" { COMPAT_2 (OP_760 ()); } +00000111101,RRRRR+wwwww,dddddd,01101+dddddddddddddddd:XIV:::st.h +*v850e2v3 +"st.h r<reg3>, <disp23>[r<reg1>]" +{ + unsigned32 addr = GR[reg1] + disp23; + store_data_mem (sd, addr, 2, GR[reg3]); + TRACE_ST (addr, GR[reg3]); +} + rrrrr,111011,RRRRR + ddddddddddddddd,1:VII:::st.w "st.w r<reg2>, <disp16>[r<reg1>]" { COMPAT_2 (OP_10760 ()); } +00000111100,RRRRR+wwwww,dddddd,01111+dddddddddddddddd:XIV:::st.w +*v850e2v3 +"st.w r<reg3>, <disp23>[r<reg1>]" +{ + unsigned32 addr = GR[reg1] + disp23; + store_data_mem (sd, addr, 4, GR[reg3]); + TRACE_ST (addr, GR[reg3]); +} + + // STSR rrrrr,111111,regID + 0000000001000000:IX:::stsr "stsr s<regID>, r<reg2>" { - TRACE_ALU_INPUT1 (SR[regID]); - GR[reg2] = SR[regID]; + uint32 sreg = 0; + + if ((idecode_issue == idecode_v850e2_issue + || idecode_issue == idecode_v850e2v3_issue) + && regID < 28) + { + switch (BSEL & 0xffff) + { + case 0x0000: + case 0xff00: /* USER 0 */ + case 0xffff: /* USER 1 */ + sreg = SR[regID]; + break; + case 0x1000: + sreg = MPU0_SR[regID]; + break; + case 0x1001: + sreg = MPU1_SR[regID]; + break; + case 0x2000: + if (regID == FPST_REGNO) + { + sreg = ((FPSR & FPSR_PR) ? FPST_PR : 0) + | ((FPSR & FPSR_XCE) ? FPST_XCE : 0) + | ((FPSR & FPSR_XCV) ? FPST_XCV : 0) + | ((FPSR & FPSR_XCZ) ? FPST_XCZ : 0) + | ((FPSR & FPSR_XCO) ? FPST_XCO : 0) + | ((FPSR & FPSR_XCU) ? FPST_XCU : 0) + | ((FPSR & FPSR_XCI) ? FPST_XCI : 0) + | ((FPSR & FPSR_XPV) ? FPST_XPV : 0) + | ((FPSR & FPSR_XPZ) ? FPST_XPZ : 0) + | ((FPSR & FPSR_XPO) ? FPST_XPO : 0) + | ((FPSR & FPSR_XPU) ? FPST_XPU : 0) + | ((FPSR & FPSR_XPI) ? FPST_XPI : 0); + } + else if (regID == FPCFG_REGNO) + { + sreg = (((FPSR & FPSR_RM) >> 18) << 7) + | ((FPSR & FPSR_XEV) ? FPCFG_XEV : 0) + | ((FPSR & FPSR_XEZ) ? FPCFG_XEZ : 0) + | ((FPSR & FPSR_XEO) ? FPCFG_XEO : 0) + | ((FPSR & FPSR_XEU) ? FPCFG_XEU : 0) + | ((FPSR & FPSR_XEI) ? FPCFG_XEI : 0); + } + else + { + sreg = FPU_SR[regID]; + } + break; + } + } + else + { + sreg = SR[regID]; + } + + TRACE_ALU_INPUT1 (sreg); + GR[reg2] = sreg; TRACE_ALU_RESULT (GR[reg2]); } @@ -1070,6 +2055,8 @@ rrrrr,001100,RRRRR:I:::subr 00000000010,RRRRR:I:::switch *v850e *v850e1 +*v850e2 +*v850e2v3 "switch r<reg1>" { unsigned long adr; @@ -1084,6 +2071,8 @@ rrrrr,001100,RRRRR:I:::subr 00000000101,RRRRR:I:::sxb *v850e *v850e1 +*v850e2 +*v850e2v3 "sxb r<reg1>" { TRACE_ALU_INPUT1 (GR[reg1]); @@ -1095,6 +2084,8 @@ rrrrr,001100,RRRRR:I:::subr 00000000111,RRRRR:I:::sxh *v850e *v850e1 +*v850e2 +*v850e2v3 "sxh r<reg1>" { TRACE_ALU_INPUT1 (GR[reg1]); @@ -1126,6 +2117,8 @@ rrrrr,001011,RRRRR:I:::tst rrrrr,111111,RRRRR + 0000000011100110:IX:::tst1 *v850e *v850e1 +*v850e2 +*v850e2v3 "tst1 r<reg2>, [r<reg1>]" { COMPAT_2 (OP_E607E0 ()); @@ -1149,6 +2142,8 @@ rrrrr,110101,RRRRR + iiiiiiiiiiiiiiii:VI:::xori 00000000100,RRRRR:I:::zxb *v850e *v850e1 +*v850e2 +*v850e2v3 "zxb r<reg1>" { TRACE_ALU_INPUT1 (GR[reg1]); @@ -1160,6 +2155,8 @@ rrrrr,110101,RRRRR + iiiiiiiiiiiiiiii:VI:::xori 00000000110,RRRRR:I:::zxh *v850e *v850e1 +*v850e2 +*v850e2v3 "zxh r<reg1>" { TRACE_ALU_INPUT1 (GR[reg1]); @@ -1178,6 +2175,8 @@ rrrrr,110101,RRRRR + iiiiiiiiiiiiiiii:VI:::xori 11111,000010,00000:I:::dbtrap *v850e1 +*v850e2 +*v850e2v3 "dbtrap" { DBPC = cia + 2; @@ -1197,9 +2196,1069 @@ rrrrr,110101,RRRRR + iiiiiiiiiiiiiiii:VI:::xori // Return from debug trap: 0x146007e0 0000011111100000 + 0000000101000110:X:::dbret *v850e1 +*v850e2 +*v850e2v3 "dbret" { nia = DBPC; PSW = DBPSW; TRACE_BRANCH1 (PSW); } + + +// +// FLOAT +// + +// Map condition code to a string +:%s::::FFFF:int FFFF +{ + switch (FFFF) + { + case 0: return "f"; + case 1: return "un"; + case 2: return "eq"; + case 3: return "ueq"; + case 4: return "olt"; + case 5: return "ult"; + case 6: return "ole"; + case 7: return "ule"; + case 8: return "sf"; + case 9: return "ngle"; + case 10: return "seq"; + case 11: return "ngl"; + case 12: return "lt"; + case 13: return "nge"; + case 14: return "le"; + case 15: return "ngt"; + } + return "(null)"; +} + +// ABSF.D +rrrr,011111100000 + wwww,010001011000:F_I:::absf_d +*v850e2v3 +"absf.d r<reg2e>, r<reg3e>" +{ + sim_fpu ans, wop; + sim_fpu_status status; + + sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_abs (&ans, &wop); + check_invalid_snan(sd, status, 1); + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans); + + TRACE_FP_RESULT_FPU1 (&ans); +} + +// ABSF.S +rrrrr,11111100000 + wwwww,10001001000:F_I:::absf_s +*v850e2v3 +"absf.s r<reg2>, r<reg3>" +{ + sim_fpu ans, wop; + sim_fpu_status status; + + sim_fpu_32to (&wop, GR[reg2]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_abs (&ans, &wop); + check_invalid_snan(sd, status, 0); + + sim_fpu_to32 (&GR[reg3], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// ADDF.D +rrrr,0111111,RRRR,0 + wwww,010001110000:F_I:::addf_d +*v850e2v3 +"addf.d r<reg1e>, r<reg2e>, r<reg3e>" +{ + sim_fpu ans, wop1, wop2; + sim_fpu_status status; + + sim_fpu_232to (&wop1, GR[reg1e+1], GR[reg1e]); + sim_fpu_232to (&wop2, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + status = sim_fpu_add (&ans, &wop1, &wop2); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 1); + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// ADDF.S +rrrrr,111111,RRRRR + wwwww,10001100000:F_I:::addf_s +*v850e2v3 +"addf.s r<reg1>, r<reg2>, r<reg3>" +{ + sim_fpu ans, wop1, wop2; + sim_fpu_status status; + + sim_fpu_32to (&wop1, GR[reg1]); + sim_fpu_32to (&wop2, GR[reg2]); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + status = sim_fpu_add (&ans, &wop1, &wop2); + status |= sim_fpu_round_32 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0); + + sim_fpu_to32 (&GR[reg3], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// CMOVF.D +rrrr,0111111,RRRR,0 + wwww!0,01000001,bbb,0:F_I:::cmovf_d +*v850e2v3 +"cmovf.d <bbb>, r<reg1e>, r<reg2e>, r<reg3e>" +{ + unsigned int ophi,oplow; + sim_fpu ans, wop1, wop2; + + sim_fpu_232to (&wop1, GR[reg1e+1], GR[reg1e]); + sim_fpu_232to (&wop2, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_BOOL1_FPU2 (TEST_FPCC(bbb), &wop1, &wop2); + + if (TEST_FPCC(bbb)) + { + ophi = GR[reg1e+1]; + oplow = GR[reg1e]; + ans = wop1; + } + else + { + ophi = GR[reg2e+1]; + oplow = GR[reg2e]; + ans = wop2; + } + + GR[reg3e+1] = ophi; + GR[reg3e] = oplow; + TRACE_FP_RESULT_FPU1 (&ans);; +} + +// CMOVF.S +rrrrr,111111,RRRRR + wwwww!0,1000000,bbb,0:F_I:::cmovf_s +*v850e2v3 +"cmovf.d <bbb>, r<reg1>, r<reg2>, r<reg3>" +{ + unsigned int op; + sim_fpu ans, wop1, wop2; + + sim_fpu_32to (&wop1, GR[reg1]); + sim_fpu_32to (&wop2, GR[reg2]); + TRACE_FP_INPUT_BOOL1_FPU2 (TEST_FPCC(bbb), &wop1, &wop2); + + if (TEST_FPCC(bbb)) + { + op = GR[reg1]; + ans = wop1; + } + else + { + op = GR[reg2]; + ans = wop2; + } + + GR[reg3] = op; + TRACE_FP_RESULT_FPU1 (&ans); +} + +// CMPF.D +rrrr,0111111,RRRR,0 + 0,FFFF,1000011,bbb,0:F_I:::cmpf_d +*v850e2v3 +"cmpf.d %s<FFFF>, r<reg1e>, r<reg2e>":(bbb == 0) +"cmpf.d %s<FFFF>, r<reg1e>, r<reg2e>, <bbb>" +{ + int result; + sim_fpu wop1; + sim_fpu wop2; + + sim_fpu_232to (&wop1, GR[reg1e+1], GR[reg1e]); + sim_fpu_232to (&wop2, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + result = v850_float_compare(sd, FFFF, wop1, wop2, 1); + + if (result) + SET_FPCC(bbb); + else + CLEAR_FPCC(bbb); + + TRACE_FP_RESULT_BOOL (result); +} + +// CMPF.S +rrrrr,111111,RRRRR + 0,FFFF,1000010,bbb,0:F_I:::cmpf_s +*v850e2v3 +"cmpf.s %s<FFFF>, r<reg1>, r<reg2>":(bbb == 0) +"cmpf.s %s<FFFF>, r<reg1>, r<reg2>, <bbb>" +{ + int result; + sim_fpu wop1; + sim_fpu wop2; + + sim_fpu_32to( &wop1, GR[reg1] ); + sim_fpu_32to( &wop2, GR[reg2] ); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + result = v850_float_compare(sd, FFFF, wop1, wop2, 0); + + if (result) + SET_FPCC(bbb); + else + CLEAR_FPCC(bbb); + + TRACE_FP_RESULT_BOOL (result); +} + +// CVTF.DL +rrrr,011111100100 + wwww,010001010100:F_I:::cvtf_dl +*v850e2v3 +"cvtf.dl r<reg2e>, r<reg3e>" +{ + unsigned64 ans; + sim_fpu wop; + sim_fpu_status status; + + sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_round_64 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero); + status |= sim_fpu_to64i (&ans, &wop, FPSR_GET_ROUND()); + + check_cvt_fi(sd, status, 1); + + GR[reg3e] = ans; + GR[reg3e+1] = ans>>32L; + TRACE_FP_RESULT_WORD2 (GR[reg3e], GR[reg3e+1]); +} + +// CVTF.DS +rrrr,011111100011 + wwwww,10001010010:F_I:::cvtf_ds +*v850e2v3 +"cvtf.ds r<reg2e>, r<reg3>" +{ + sim_fpu wop; + sim_fpu_status status; + + sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_round_32 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + check_cvt_fi(sd, status, 0); + + sim_fpu_to32 (&GR[reg3], &wop); + TRACE_FP_RESULT_FPU1 (&wop); +} + +// CVTF.DW +rrrr,011111100100 + wwwww,10001010000:F_I:::cvtf_dw +*v850e2v3 +"cvtf.dw r<reg2e>, r<reg3>" +{ + uint32 ans; + sim_fpu wop; + sim_fpu_status status; + + sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_round_32 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero); + status |= sim_fpu_to32i (&ans, &wop, FPSR_GET_ROUND()); + + check_cvt_fi(sd, status, 1); + + GR[reg3] = ans; + TRACE_FP_RESULT_WORD1 (ans); +} + +// CVTF.LD +rrrr,011111100001 + wwww,010001010010:F_I:::cvtf_ld +*v850e2v3 +"cvtf.ld r<reg2e>, r<reg3e>" +{ + signed64 op; + sim_fpu wop; + sim_fpu_status status; + + op = ((signed64)GR[reg2e+1] << 32L) | GR[reg2e]; + TRACE_FP_INPUT_WORD2 (GR[reg2e], GR[reg2e+1]); + + sim_fpu_i64to (&wop, op, FPSR_GET_ROUND()); + status = sim_fpu_round_64 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero); + + check_cvt_if(sd, status, 1); + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &wop); + TRACE_FP_RESULT_FPU1 (&wop); +} + +// CVTF.LS +rrrr,011111100001 + wwwww,10001000010:F_I:::cvtf_ls +*v850e2v3 +"cvtf.ls r<reg2e>, r<reg3>" +{ + signed64 op; + sim_fpu wop; + sim_fpu_status status; + + op = ((signed64)GR[reg2e+1] << 32L) | GR[reg2e]; + TRACE_FP_INPUT_WORD2 (GR[reg2e], GR[reg2e+1]); + + sim_fpu_i64to (&wop, op, FPSR_GET_ROUND()); + status = sim_fpu_round_32 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero); + + check_cvt_if(sd, status, 0); + + sim_fpu_to32 (&GR[reg3], &wop); + TRACE_FP_RESULT_FPU1 (&wop); +} + +// CVTF.SD +rrrrr,11111100010 + wwww,010001010010:F_I:::cvtf_sd +*v850e2v3 +"cvtf.sd r<reg2>, r<reg3e>" +{ + sim_fpu wop; + sim_fpu_status status; + + sim_fpu_32to (&wop, GR[reg2]); + TRACE_FP_INPUT_FPU1 (&wop); + status = sim_fpu_round_64 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + check_cvt_ff(sd, status, 1); + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &wop); + TRACE_FP_RESULT_FPU1 (&wop); +} + +// CVTF.SL +rrrrr,11111100100 + wwww,010001000100:F_I:::cvtf_sl +*v850e2v3 +"cvtf.sl r<reg2>, r<reg3e>" +{ + signed64 ans; + sim_fpu wop; + sim_fpu_status status; + + sim_fpu_32to (&wop, GR[reg2]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_round_64 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero); + status |= sim_fpu_to64i (&ans, &wop, FPSR_GET_ROUND()); + + check_cvt_fi(sd, status, 0); + + GR[reg3e] = ans; + GR[reg3e+1] = ans >> 32L; + TRACE_FP_RESULT_WORD2 (GR[reg3e], GR[reg3e+1]); +} + +// CVTF.SW +rrrrr,11111100100 + wwwww,10001000000:F_I:::cvtf_sw +*v850e2v3 +"cvtf.sw r<reg2>, r<reg3>" +{ + uint32 ans; + sim_fpu wop; + sim_fpu_status status; + + sim_fpu_32to (&wop, GR[reg2]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_round_32 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero); + status |= sim_fpu_to32i (&ans, &wop, sim_fpu_round_zero); + + check_cvt_fi(sd, status, 0); + + GR[reg3] = ans; + TRACE_FP_RESULT_WORD1 (ans); +} + +// CVTF.WD +rrrrr,11111100000 + wwww,010001010010:F_I:::cvtf_wd +*v850e2v3 +"cvtf.wd r<reg2>, r<reg3e>" +{ + sim_fpu wop; + sim_fpu_status status; + + TRACE_FP_INPUT_WORD1 (GR[reg2]); + sim_fpu_i32to (&wop, GR[reg2], FPSR_GET_ROUND()); + status = sim_fpu_round_64 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero); + + check_cvt_if(sd, status, 1); + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &wop); + TRACE_FP_RESULT_FPU1 (&wop); +} + +// CVTF.WS +rrrrr,11111100000 + wwwww,10001000010:F_I:::cvtf_ws +*v850e2v3 +"cvtf.ws r<reg2>, r<reg3>" +{ + sim_fpu wop; + sim_fpu_status status; + + TRACE_FP_INPUT_WORD1 (GR[reg2]); + sim_fpu_i32to (&wop, GR[reg2], FPSR_GET_ROUND()); + status = sim_fpu_round_32 (&wop, FPSR_GET_ROUND(), sim_fpu_denorm_zero); + + check_cvt_if(sd, status, 0); + + sim_fpu_to32 (&GR[reg3], &wop); + TRACE_FP_RESULT_FPU1 (&wop); +} + +// DIVF.D +rrrr,0111111,RRRR,0 + wwww,010001111110:F_I:::divf_d +*v850e2v3 +"divf.d r<reg1e>, r<reg2e>, r<reg3e>" +{ + sim_fpu ans, wop1, wop2; + sim_fpu_status status; + + sim_fpu_232to (&wop1, GR[reg1e+1], GR[reg1e]); + sim_fpu_232to (&wop2, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + status = sim_fpu_div (&ans, &wop2, &wop1); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEZ | FPSR_XEI | FPSR_XEO | FPSR_XEU, 1); + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// DIVF.S +rrrrr,111111,RRRRR + wwwww,10001101110:F_I:::divf_s +*v850e2v3 +"divf.s r<reg1>, r<reg2>, r<reg3>" +{ + sim_fpu ans, wop1, wop2; + sim_fpu_status status; + + sim_fpu_32to (&wop1, GR[reg1]); + sim_fpu_32to (&wop2, GR[reg2]); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + status = sim_fpu_div (&ans, &wop2, &wop1); + status |= sim_fpu_round_32 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEZ | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0); + + sim_fpu_to32 (&GR[reg3], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// MADDF.S +rrrrr,111111,RRRRR + wwwww,101,W,00,WWWW,0:F_I:::maddf_s +*v850e2v3 +"maddf.s r<reg1>, r<reg2>, r<reg3>, r<reg4>" +{ + sim_fpu ans, wop1, wop2, wop3; + sim_fpu_status status; + + sim_fpu_32to (&wop1, GR[reg1]); + sim_fpu_32to (&wop2, GR[reg2]); + sim_fpu_32to (&wop3, GR[reg3]); + TRACE_FP_INPUT_FPU3 (&wop1, &wop2, &wop3); + + status = sim_fpu_mul (&ans, &wop1, &wop2); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + wop1 = ans; + status |= sim_fpu_add (&ans, &wop1, &wop3); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0); + + sim_fpu_to32 (&GR[reg4], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// MAXF.D +rrrr,0111111,RRRR,0 + wwww,010001111000:F_I:::maxf_d +*v850e2v3 +"maxf.d r<reg1e>, r<reg2e>, r<reg3e>" +{ + sim_fpu ans, wop1, wop2; + + sim_fpu_232to (&wop1, GR[reg1e+1], GR[reg1e]); + sim_fpu_232to (&wop2, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + if (sim_fpu_is_nan(&wop1) || sim_fpu_is_nan(&wop2)) + { + if (FPSR & FPSR_XEV) + { + SignalExceptionFPE(sd, 1); + } + else + { + ans = sim_fpu_qnan; + } + } + else if (FPSR & FPSR_FS + && ((sim_fpu_is_zero (&wop1) || sim_fpu_is_denorm (&wop1)) + && (sim_fpu_is_zero (&wop2) || sim_fpu_is_denorm (&wop2)))) + { + ans = sim_fpu_zero; + } + else + { + sim_fpu_max (&ans, &wop1, &wop2); + } + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// MAXF.S +rrrrr,111111,RRRRR + wwwww,10001101000:F_I:::maxf_s +*v850e2v3 +"maxf.s r<reg1>, r<reg2>, r<reg3>" +{ + sim_fpu ans, wop1, wop2; + + sim_fpu_32to (&wop1, GR[reg1]); + sim_fpu_32to (&wop2, GR[reg2]); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + if (sim_fpu_is_nan(&wop1) || sim_fpu_is_nan(&wop2)) + { + if (FPSR & FPSR_XEV) + { + SignalExceptionFPE(sd, 0); + } + else + { + ans = sim_fpu_qnan; + } + } + else if ((FPSR & FPSR_FS) + && ((sim_fpu_is_zero (&wop1) || sim_fpu_is_denorm (&wop1)) + && (sim_fpu_is_zero (&wop2)|| sim_fpu_is_denorm (&wop2)))) + { + ans = sim_fpu_zero; + } + else + { + sim_fpu_max (&ans, &wop1, &wop2); + } + + sim_fpu_to32 (&GR[reg3], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// MINF.D +rrrr,0111111,RRRR,0 + wwww,010001111010:F_I:::minf_d +*v850e2v3 +"minf.d r<reg1e>, r<reg2e>, r<reg3e>" +{ + sim_fpu ans, wop1, wop2; + + sim_fpu_232to (&wop1, GR[reg1e+1], GR[reg1e]); + sim_fpu_232to (&wop2, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + if (sim_fpu_is_nan(&wop1) || sim_fpu_is_nan(&wop2)) + { + if (FPSR & FPSR_XEV) + { + SignalExceptionFPE(sd, 1); + } + else + { + ans = sim_fpu_qnan; + } + } + else if (FPSR & FPSR_FS + && ((sim_fpu_is_zero (&wop1) || sim_fpu_is_denorm (&wop1)) + && (sim_fpu_is_zero (&wop2) || sim_fpu_is_denorm (&wop2)))) + { + ans = sim_fpu_zero; + } + else + { + sim_fpu_min (&ans, &wop1, &wop2); + } + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// MINF.S +rrrrr,111111,RRRRR + wwwww,10001101010:F_I:::minf_s +*v850e2v3 +"minf.s r<reg1>, r<reg2>, r<reg3>" +{ + sim_fpu ans, wop1, wop2; + + sim_fpu_32to (&wop1, GR[reg1]); + sim_fpu_32to (&wop2, GR[reg2]); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + if (sim_fpu_is_nan(&wop1) || sim_fpu_is_nan(&wop2)) + { + if (FPSR & FPSR_XEV) + { + SignalExceptionFPE(sd, 0); + } + else + { + ans = sim_fpu_qnan; + } + } + else if (FPSR & FPSR_FS + && ((sim_fpu_is_zero (&wop1) || sim_fpu_is_denorm (&wop1)) + && (sim_fpu_is_zero (&wop2) || sim_fpu_is_denorm (&wop2)))) + { + ans = sim_fpu_zero; + } + else + { + sim_fpu_min (&ans, &wop1, &wop2); + } + + sim_fpu_to32 (&GR[reg3], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// MSUBF.S +rrrrr,111111,RRRRR + wwwww,101,W,01,WWWW,0:F_I:::msubf_s +*v850e2v3 +"msubf.s r<reg1>, r<reg2>, r<reg3>, r<reg4>" +{ + sim_fpu ans, wop1, wop2, wop3; + sim_fpu_status status; + + sim_fpu_32to (&wop1, GR[reg1]); + sim_fpu_32to (&wop2, GR[reg2]); + sim_fpu_32to (&wop3, GR[reg3]); + TRACE_FP_INPUT_FPU3 (&wop1, &wop2, &wop3); + + status = sim_fpu_mul (&ans, &wop1, &wop2); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + wop1 = ans; + status |= sim_fpu_sub (&ans, &wop1, &wop3); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0); + + sim_fpu_to32 (&GR[reg4], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// MULF.D +rrrr,0111111,RRRR,0 + wwww,010001110100:F_I:::mulf_d +*v850e2v3 +"mulf.d r<reg1e>, r<reg2e>, r<reg3e>" +{ + sim_fpu ans, wop1, wop2; + sim_fpu_status status; + + sim_fpu_232to (&wop1, GR[reg1e+1], GR[reg1e]); + sim_fpu_232to (&wop2, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + status = sim_fpu_mul (&ans, &wop1, &wop2); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 1); + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// MULF.S +rrrrr,111111,RRRRR + wwwww,10001100100:F_I:::mulf_s +*v850e2v3 +"mulf.s r<reg1>, r<reg2>, r<reg3>" +{ + sim_fpu ans, wop1, wop2; + sim_fpu_status status; + + sim_fpu_32to (&wop1, GR[reg1]); + sim_fpu_32to (&wop2, GR[reg2]); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + status = sim_fpu_mul (&ans, &wop1, &wop2); + status |= sim_fpu_round_32 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0); + + sim_fpu_to32 (&GR[reg3], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// NEGF.D +rrrr,011111100001 + wwww,010001011000:F_I:::negf_d +*v850e2v3 +"negf.d r<reg2e>, r<reg3e>" +{ + sim_fpu ans, wop; + sim_fpu_status status; + + sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_neg (&ans, &wop); + + check_invalid_snan(sd, status, 1); + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// NEGF.S +rrrrr,11111100001 + wwwww,10001001000:F_I:::negf_s +*v850e2v3 +"negf.s r<reg2>, r<reg3>" +{ + sim_fpu ans, wop; + sim_fpu_status status; + + sim_fpu_32to (&wop, GR[reg2]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_neg (&ans, &wop); + + check_invalid_snan(sd, status, 0); + + sim_fpu_to32 (&GR[reg3], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// NMADDF.S +rrrrr,111111,RRRRR + wwwww,101,W,10,WWWW,0:F_I:::nmaddf_s +*v850e2v3 +"nmaddf.s r<reg1>, r<reg2>, r<reg3>, r<reg4>" +{ + sim_fpu ans, wop1, wop2, wop3; + sim_fpu_status status; + + sim_fpu_32to (&wop1, GR[reg1]); + sim_fpu_32to (&wop2, GR[reg2]); + sim_fpu_32to (&wop3, GR[reg3]); + TRACE_FP_INPUT_FPU3 (&wop1, &wop2, &wop3); + + status = sim_fpu_mul (&ans, &wop1, &wop2); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + wop1 = ans; + status |= sim_fpu_add (&ans, &wop1, &wop3); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + wop1 = ans; + status |= sim_fpu_neg (&ans, &wop1); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0); + + sim_fpu_to32 (&GR[reg4], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// NMSUBF.S +rrrrr,111111,RRRRR + wwwww,101,W,11,WWWW,0:F_I:::nmsubf_s +*v850e2v3 +"nmsubf.s r<reg1>, r<reg2>, r<reg3>, r<reg4>" +{ + sim_fpu ans, wop1, wop2, wop3; + sim_fpu_status status; + + sim_fpu_32to (&wop1, GR[reg1]); + sim_fpu_32to (&wop2, GR[reg2]); + sim_fpu_32to (&wop3, GR[reg3]); + TRACE_FP_INPUT_FPU3 (&wop1, &wop2, &wop3); + + status = sim_fpu_mul (&ans, &wop1, &wop2); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + wop1 = ans; + status |= sim_fpu_sub (&ans, &wop1, &wop3); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + wop1 = ans; + status |= sim_fpu_neg (&ans, &wop1); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0); + + sim_fpu_to32 (&GR[reg4], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// RECIPF.D +rrrr,011111100001 + wwww,010001011110:F_I:::recipf.d +*v850e2v3 +"recipf.d r<reg2e>, r<reg3e>" +{ + sim_fpu ans, wop; + sim_fpu_status status; + + sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_div (&ans, &sim_fpu_one, &wop); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEZ | FPSR_XEI | FPSR_XEO | FPSR_XEU, 1); + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// RECIPF.S +rrrrr,11111100001 + wwwww,10001001110:F_I:::recipf.s +*v850e2v3 +"recipf.s r<reg2>, r<reg3>" +{ + sim_fpu ans, wop; + sim_fpu_status status; + + sim_fpu_32to (&wop, GR[reg2]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_div (&ans, &sim_fpu_one, &wop); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEZ | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0); + + sim_fpu_to32 (&GR[reg3], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// RSQRTF.D +rrrr,011111100010 + wwww,010001011110:F_I:::rsqrtf.d +*v850e2v3 +"rsqrtf.d r<reg2e>, r<reg3e>" +{ + sim_fpu ans, wop; + sim_fpu_status status; + + sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_sqrt (&ans, &wop); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + wop = ans; + status = sim_fpu_div (&ans, &sim_fpu_one, &wop); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEZ | FPSR_XEI | FPSR_XEO | FPSR_XEU, 1); + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// RSQRTF.S +rrrrr,11111100010 + wwwww,10001001110:F_I:::rsqrtf.s +*v850e2v3 +"rsqrtf.s r<reg2>, r<reg3>" +{ + sim_fpu ans, wop; + sim_fpu_status status; + + sim_fpu_32to (&wop, GR[reg2]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_sqrt (&ans, &wop); + status |= sim_fpu_round_32 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + wop = ans; + status = sim_fpu_div (&ans, &sim_fpu_one, &wop); + status |= sim_fpu_round_32 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEZ | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0); + + sim_fpu_to32 (&GR[reg3], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// SQRTF.D +rrrr,011111100000 + wwww,010001011110:F_I:::sqrtf.d +*v850e2v3 +"sqrtf.d r<reg2e>, r<reg3e>" +{ + sim_fpu ans, wop; + sim_fpu_status status; + + sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_sqrt (&ans, &wop); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI, 1); + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// SQRTF.S +rrrrr,11111100000 + wwwww,10001001110:F_I:::sqrtf.s +*v850e2v3 +"sqrtf.s r<reg2>, r<reg3>" +{ + sim_fpu ans, wop; + sim_fpu_status status; + + sim_fpu_32to (&wop, GR[reg2]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_sqrt (&ans, &wop); + status |= sim_fpu_round_32 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI, 0); + + sim_fpu_to32 (&GR[reg3], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// SUBF.D +rrrr,0111111,RRRR,0 + wwww,010001110010:F_I:::subf.d +*v850e2v3 +"subf.d r<reg1e>, r<reg2e>, r<reg3e>" +{ + sim_fpu ans, wop1, wop2; + sim_fpu_status status; + + sim_fpu_232to (&wop1, GR[reg1e+1], GR[reg1e]); + sim_fpu_232to (&wop2, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + status = sim_fpu_sub (&ans, &wop2, &wop1); + status |= sim_fpu_round_64 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 1); + + sim_fpu_to232 (&GR[reg3e+1], &GR[reg3e], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// SUBF.S +rrrrr,111111,RRRRR + wwwww,10001100010:F_I:::subf.s +*v850e2v3 +"subf.s r<reg1>, r<reg2>, r<reg3>" +{ + sim_fpu ans, wop1, wop2; + sim_fpu_status status; + + sim_fpu_32to (&wop1, GR[reg1]); + sim_fpu_32to (&wop2, GR[reg2]); + TRACE_FP_INPUT_FPU2 (&wop1, &wop2); + + status = sim_fpu_sub (&ans, &wop2, &wop1); + status |= sim_fpu_round_32 (&ans, FPSR_GET_ROUND(), sim_fpu_denorm_underflow_inexact); + + update_fpsr (sd, status, FPSR_XEV | FPSR_XEI | FPSR_XEO | FPSR_XEU, 0); + + sim_fpu_to32 (&GR[reg3], &ans); + TRACE_FP_RESULT_FPU1 (&ans); +} + +// TRFSR +0000011111100000 + 000001000000,bbb,0:F_I:::trfsr +*v850e2v3 +"trfsr":(bbb == 0) +"trfsr <bbb>" +{ + TRACE_ALU_INPUT1 (GET_FPCC()); + + if (TEST_FPCC (bbb)) + PSW |= PSW_Z; + else + PSW &= ~PSW_Z; + + TRACE_ALU_RESULT1 (PSW); +} + +// TRNCF.DL +rrrr,011111100001 + wwww,010001010100:F_I:::trncf_dl +*v850e2v3 +"trncf.dl r<reg2e>, r<reg3e>" +{ + signed64 ans; + sim_fpu wop; + sim_fpu_status status; + + sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_round_64 (&wop, sim_fpu_round_zero, sim_fpu_denorm_zero); + status |= sim_fpu_to64i (&ans, &wop, sim_fpu_round_zero); + + check_cvt_fi(sd, status, 1); + + GR[reg3e] = ans; + GR[reg3e+1] = ans>>32L; + TRACE_FP_RESULT_WORD2 (GR[reg3e], GR[reg3e+1]); +} + +// TRNCF.DW +rrrr,011111100001 + wwwww,10001010000:F_I:::trncf_dw +*v850e2v3 +"trncf.dw r<reg2e>, r<reg3>" +{ + uint32 ans; + sim_fpu wop; + sim_fpu_status status; + + sim_fpu_232to (&wop, GR[reg2e+1], GR[reg2e]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_round_32 (&wop, sim_fpu_round_zero, sim_fpu_denorm_zero); + status |= sim_fpu_to32i (&ans, &wop, sim_fpu_round_zero); + + check_cvt_fi(sd, status, 1); + + GR[reg3] = ans; + TRACE_FP_RESULT_WORD1 (ans); +} + +// TRNCF.SL +rrrrr,11111100001 + wwww,010001000100:F_I:::trncf_sl +*v850e2v3 +"trncf.sl r<reg2>, r<reg3e>" +{ + signed64 ans; + sim_fpu wop; + sim_fpu_status status; + + sim_fpu_32to (&wop, GR[reg2]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_round_64 (&wop, sim_fpu_round_zero, sim_fpu_denorm_zero); + status |= sim_fpu_to64i (&ans, &wop, sim_fpu_round_zero); + + GR[reg3e] = ans; + GR[reg3e+1] = ans >> 32L; + TRACE_FP_RESULT_WORD2 (GR[reg3e], GR[reg3e+1]); +} + +// TRNCF.SW +rrrrr,11111100001 + wwwww,10001000000:F_I:::trncf_sw +*v850e2v3 +"trncf.sw r<reg2>, r<reg3>" +{ + uint32 ans; + sim_fpu wop; + sim_fpu_status status; + + sim_fpu_32to (&wop, GR[reg2]); + TRACE_FP_INPUT_FPU1 (&wop); + + status = sim_fpu_round_32 (&wop, sim_fpu_round_zero, sim_fpu_denorm_zero); + status |= sim_fpu_to32i (&ans, &wop, sim_fpu_round_zero); + + check_cvt_fi(sd, status, 0); + + GR[reg3] = ans; + TRACE_FP_RESULT_WORD1 (ans); +} + |