diff options
author | Kevin Buettner <kevinb@redhat.com> | 2012-03-29 00:57:19 +0000 |
---|---|---|
committer | Kevin Buettner <kevinb@redhat.com> | 2012-03-29 00:57:19 +0000 |
commit | 2aaed97917d92e80a00b7fb9d160e2d13f1ae720 (patch) | |
tree | a05d69cab5edb7a5c0738eecda4460b372386f5c /sim/v850/simops.c | |
parent | 1c1b6f059a33df3da4f61b21f22c341658f06c27 (diff) | |
download | gdb-2aaed97917d92e80a00b7fb9d160e2d13f1ae720.zip gdb-2aaed97917d92e80a00b7fb9d160e2d13f1ae720.tar.gz gdb-2aaed97917d92e80a00b7fb9d160e2d13f1ae720.tar.bz2 |
Commit gdb and sim support for v850e2 and v850e2v3 on behalf of
Rathish C <Rathish.C@kpitcummins.com>.
Diffstat (limited to 'sim/v850/simops.c')
-rw-r--r-- | sim/v850/simops.c | 716 |
1 files changed, 715 insertions, 1 deletions
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; +} + |