diff options
Diffstat (limited to 'sim/v850/v850.igen')
-rw-r--r-- | sim/v850/v850.igen | 2079 |
1 files changed, 2069 insertions, 10 deletions
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); +} + |