trunk/src/emu/cpu/nec/necinstr.c
| r28738 | r28739 | |
| 1 | | #define OP(num,func_name) void nec_common_device::func_name() |
| 2 | | |
| 3 | | OP( 0x00, i_add_br8 ) { DEF_br8; ADDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 4 | | OP( 0x01, i_add_wr16 ) { DEF_wr16; ADDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 5 | | OP( 0x02, i_add_r8b ) { DEF_r8b; ADDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 6 | | OP( 0x03, i_add_r16w ) { DEF_r16w; ADDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 7 | | OP( 0x04, i_add_ald8 ) { DEF_ald8; ADDB; Breg(AL)=dst; CLKS(4,4,2); } |
| 8 | | OP( 0x05, i_add_axd16) { DEF_axd16; ADDW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 9 | | OP( 0x06, i_push_es ) { PUSH(Sreg(DS1)); CLKS(12,8,3); } |
| 10 | | OP( 0x07, i_pop_es ) { POP(Sreg(DS1)); CLKS(12,8,5); } |
| 11 | | |
| 12 | | OP( 0x08, i_or_br8 ) { DEF_br8; ORB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 13 | | OP( 0x09, i_or_wr16 ) { DEF_wr16; ORW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 14 | | OP( 0x0a, i_or_r8b ) { DEF_r8b; ORB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 15 | | OP( 0x0b, i_or_r16w ) { DEF_r16w; ORW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 16 | | OP( 0x0c, i_or_ald8 ) { DEF_ald8; ORB; Breg(AL)=dst; CLKS(4,4,2); } |
| 17 | | OP( 0x0d, i_or_axd16 ) { DEF_axd16; ORW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 18 | | OP( 0x0e, i_push_cs ) { PUSH(Sreg(PS)); CLKS(12,8,3); } |
| 19 | | OP( 0x0f, i_pre_nec ) { UINT32 ModRM, tmp, tmp2; |
| 20 | | switch (FETCH()) { |
| 21 | | case 0x10 : BITOP_BYTE; CLKS(3,3,4); tmp2 = Breg(CL) & 0x7; m_ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; m_CarryVal=m_OverVal=0; break; /* Test */ |
| 22 | | case 0x11 : BITOP_WORD; CLKS(3,3,4); tmp2 = Breg(CL) & 0xf; m_ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; m_CarryVal=m_OverVal=0; break; /* Test */ |
| 23 | | case 0x12 : BITOP_BYTE; CLKS(5,5,4); tmp2 = Breg(CL) & 0x7; tmp &= ~(1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Clr */ |
| 24 | | case 0x13 : BITOP_WORD; CLKS(5,5,4); tmp2 = Breg(CL) & 0xf; tmp &= ~(1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Clr */ |
| 25 | | case 0x14 : BITOP_BYTE; CLKS(4,4,4); tmp2 = Breg(CL) & 0x7; tmp |= (1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Set */ |
| 26 | | case 0x15 : BITOP_WORD; CLKS(4,4,4); tmp2 = Breg(CL) & 0xf; tmp |= (1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Set */ |
| 27 | | case 0x16 : BITOP_BYTE; CLKS(4,4,4); tmp2 = Breg(CL) & 0x7; BIT_NOT; PutbackRMByte(ModRM,tmp); break; /* Not */ |
| 28 | | case 0x17 : BITOP_WORD; CLKS(4,4,4); tmp2 = Breg(CL) & 0xf; BIT_NOT; PutbackRMWord(ModRM,tmp); break; /* Not */ |
| 29 | | |
| 30 | | case 0x18 : BITOP_BYTE; CLKS(4,4,4); tmp2 = (FETCH()) & 0x7; m_ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; m_CarryVal=m_OverVal=0; break; /* Test */ |
| 31 | | case 0x19 : BITOP_WORD; CLKS(4,4,4); tmp2 = (FETCH()) & 0xf; m_ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; m_CarryVal=m_OverVal=0; break; /* Test */ |
| 32 | | case 0x1a : BITOP_BYTE; CLKS(6,6,4); tmp2 = (FETCH()) & 0x7; tmp &= ~(1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Clr */ |
| 33 | | case 0x1b : BITOP_WORD; CLKS(6,6,4); tmp2 = (FETCH()) & 0xf; tmp &= ~(1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Clr */ |
| 34 | | case 0x1c : BITOP_BYTE; CLKS(5,5,4); tmp2 = (FETCH()) & 0x7; tmp |= (1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Set */ |
| 35 | | case 0x1d : BITOP_WORD; CLKS(5,5,4); tmp2 = (FETCH()) & 0xf; tmp |= (1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Set */ |
| 36 | | case 0x1e : BITOP_BYTE; CLKS(5,5,4); tmp2 = (FETCH()) & 0x7; BIT_NOT; PutbackRMByte(ModRM,tmp); break; /* Not */ |
| 37 | | case 0x1f : BITOP_WORD; CLKS(5,5,4); tmp2 = (FETCH()) & 0xf; BIT_NOT; PutbackRMWord(ModRM,tmp); break; /* Not */ |
| 38 | | |
| 39 | | case 0x20 : ADD4S; CLKS(7,7,2); break; |
| 40 | | case 0x22 : SUB4S; CLKS(7,7,2); break; |
| 41 | | case 0x26 : CMP4S; CLKS(7,7,2); break; |
| 42 | | case 0x28 : ModRM = FETCH(); tmp = GetRMByte(ModRM); tmp <<= 4; tmp |= Breg(AL) & 0xf; Breg(AL) = (Breg(AL) & 0xf0) | ((tmp>>8)&0xf); tmp &= 0xff; PutbackRMByte(ModRM,tmp); CLKM(13,13,9,28,28,15); break; |
| 43 | | case 0x2a : ModRM = FETCH(); tmp = GetRMByte(ModRM); tmp2 = (Breg(AL) & 0xf)<<4; Breg(AL) = (Breg(AL) & 0xf0) | (tmp&0xf); tmp = tmp2 | (tmp>>4); PutbackRMByte(ModRM,tmp); CLKM(17,17,13,32,32,19); break; |
| 44 | | case 0x31 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield INS\n",PC()); break; |
| 45 | | case 0x33 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield EXT\n",PC()); break; |
| 46 | | case 0xe0 : ModRM = FETCH(); ModRM=0; logerror("%06x: V33 unimplemented BRKXA (break to expansion address)\n",PC()); break; |
| 47 | | case 0xf0 : ModRM = FETCH(); ModRM=0; logerror("%06x: V33 unimplemented RETXA (return from expansion address)\n",PC()); break; |
| 48 | | case 0xff : ModRM = FETCH(); ModRM=0; logerror("%06x: unimplemented BRKEM (break to 8080 emulation mode)\n",PC()); break; |
| 49 | | default: logerror("%06x: Unknown V20 instruction\n",PC()); break; |
| 50 | | } |
| 51 | | } |
| 52 | | |
| 53 | | OP( 0x10, i_adc_br8 ) { DEF_br8; src+=CF; ADDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 54 | | OP( 0x11, i_adc_wr16 ) { DEF_wr16; src+=CF; ADDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 55 | | OP( 0x12, i_adc_r8b ) { DEF_r8b; src+=CF; ADDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 56 | | OP( 0x13, i_adc_r16w ) { DEF_r16w; src+=CF; ADDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 57 | | OP( 0x14, i_adc_ald8 ) { DEF_ald8; src+=CF; ADDB; Breg(AL)=dst; CLKS(4,4,2); } |
| 58 | | OP( 0x15, i_adc_axd16) { DEF_axd16; src+=CF; ADDW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 59 | | OP( 0x16, i_push_ss ) { PUSH(Sreg(SS)); CLKS(12,8,3); } |
| 60 | | OP( 0x17, i_pop_ss ) { POP(Sreg(SS)); CLKS(12,8,5); m_no_interrupt=1; } |
| 61 | | |
| 62 | | OP( 0x18, i_sbb_br8 ) { DEF_br8; src+=CF; SUBB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 63 | | OP( 0x19, i_sbb_wr16 ) { DEF_wr16; src+=CF; SUBW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 64 | | OP( 0x1a, i_sbb_r8b ) { DEF_r8b; src+=CF; SUBB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 65 | | OP( 0x1b, i_sbb_r16w ) { DEF_r16w; src+=CF; SUBW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 66 | | OP( 0x1c, i_sbb_ald8 ) { DEF_ald8; src+=CF; SUBB; Breg(AL)=dst; CLKS(4,4,2); } |
| 67 | | OP( 0x1d, i_sbb_axd16) { DEF_axd16; src+=CF; SUBW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 68 | | OP( 0x1e, i_push_ds ) { PUSH(Sreg(DS0)); CLKS(12,8,3); } |
| 69 | | OP( 0x1f, i_pop_ds ) { POP(Sreg(DS0)); CLKS(12,8,5); } |
| 70 | | |
| 71 | | OP( 0x20, i_and_br8 ) { DEF_br8; ANDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 72 | | OP( 0x21, i_and_wr16 ) { DEF_wr16; ANDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 73 | | OP( 0x22, i_and_r8b ) { DEF_r8b; ANDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 74 | | OP( 0x23, i_and_r16w ) { DEF_r16w; ANDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 75 | | OP( 0x24, i_and_ald8 ) { DEF_ald8; ANDB; Breg(AL)=dst; CLKS(4,4,2); } |
| 76 | | OP( 0x25, i_and_axd16) { DEF_axd16; ANDW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 77 | | OP( 0x26, i_es ) { m_seg_prefix=TRUE; m_prefix_base=Sreg(DS1)<<4; CLK(2); (this->*s_nec_instruction[fetchop()])(); m_seg_prefix=FALSE; } |
| 78 | | OP( 0x27, i_daa ) { ADJ4(6,0x60); CLKS(3,3,2); } |
| 79 | | |
| 80 | | OP( 0x28, i_sub_br8 ) { DEF_br8; SUBB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 81 | | OP( 0x29, i_sub_wr16 ) { DEF_wr16; SUBW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 82 | | OP( 0x2a, i_sub_r8b ) { DEF_r8b; SUBB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 83 | | OP( 0x2b, i_sub_r16w ) { DEF_r16w; SUBW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 84 | | OP( 0x2c, i_sub_ald8 ) { DEF_ald8; SUBB; Breg(AL)=dst; CLKS(4,4,2); } |
| 85 | | OP( 0x2d, i_sub_axd16) { DEF_axd16; SUBW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 86 | | OP( 0x2e, i_cs ) { m_seg_prefix=TRUE; m_prefix_base=Sreg(PS)<<4; CLK(2); (this->*s_nec_instruction[fetchop()])(); m_seg_prefix=FALSE; } |
| 87 | | OP( 0x2f, i_das ) { ADJ4(-6,-0x60); CLKS(3,3,2); } |
| 88 | | |
| 89 | | OP( 0x30, i_xor_br8 ) { DEF_br8; XORB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 90 | | OP( 0x31, i_xor_wr16 ) { DEF_wr16; XORW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 91 | | OP( 0x32, i_xor_r8b ) { DEF_r8b; XORB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 92 | | OP( 0x33, i_xor_r16w ) { DEF_r16w; XORW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 93 | | OP( 0x34, i_xor_ald8 ) { DEF_ald8; XORB; Breg(AL)=dst; CLKS(4,4,2); } |
| 94 | | OP( 0x35, i_xor_axd16) { DEF_axd16; XORW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 95 | | OP( 0x36, i_ss ) { m_seg_prefix=TRUE; m_prefix_base=Sreg(SS)<<4; CLK(2); (this->*s_nec_instruction[fetchop()])(); m_seg_prefix=FALSE; } |
| 96 | | OP( 0x37, i_aaa ) { ADJB(6, (Breg(AL) > 0xf9) ? 2 : 1); CLKS(7,7,4); } |
| 97 | | |
| 98 | | OP( 0x38, i_cmp_br8 ) { DEF_br8; SUBB; CLKM(2,2,2,11,11,6); } |
| 99 | | OP( 0x39, i_cmp_wr16 ) { DEF_wr16; SUBW; CLKR(15,15,8,15,11,6,2,m_EA);} |
| 100 | | OP( 0x3a, i_cmp_r8b ) { DEF_r8b; SUBB; CLKM(2,2,2,11,11,6); } |
| 101 | | OP( 0x3b, i_cmp_r16w ) { DEF_r16w; SUBW; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 102 | | OP( 0x3c, i_cmp_ald8 ) { DEF_ald8; SUBB; CLKS(4,4,2); } |
| 103 | | OP( 0x3d, i_cmp_axd16) { DEF_axd16; SUBW; CLKS(4,4,2); } |
| 104 | | OP( 0x3e, i_ds ) { m_seg_prefix=TRUE; m_prefix_base=Sreg(DS0)<<4; CLK(2); (this->*s_nec_instruction[fetchop()])(); m_seg_prefix=FALSE; } |
| 105 | | OP( 0x3f, i_aas ) { ADJB(-6, (Breg(AL) < 6) ? -2 : -1); CLKS(7,7,4); } |
| 106 | | |
| 107 | | OP( 0x40, i_inc_ax ) { IncWordReg(AW); CLK(2); } |
| 108 | | OP( 0x41, i_inc_cx ) { IncWordReg(CW); CLK(2); } |
| 109 | | OP( 0x42, i_inc_dx ) { IncWordReg(DW); CLK(2); } |
| 110 | | OP( 0x43, i_inc_bx ) { IncWordReg(BW); CLK(2); } |
| 111 | | OP( 0x44, i_inc_sp ) { IncWordReg(SP); CLK(2); } |
| 112 | | OP( 0x45, i_inc_bp ) { IncWordReg(BP); CLK(2); } |
| 113 | | OP( 0x46, i_inc_si ) { IncWordReg(IX); CLK(2); } |
| 114 | | OP( 0x47, i_inc_di ) { IncWordReg(IY); CLK(2); } |
| 115 | | |
| 116 | | OP( 0x48, i_dec_ax ) { DecWordReg(AW); CLK(2); } |
| 117 | | OP( 0x49, i_dec_cx ) { DecWordReg(CW); CLK(2); } |
| 118 | | OP( 0x4a, i_dec_dx ) { DecWordReg(DW); CLK(2); } |
| 119 | | OP( 0x4b, i_dec_bx ) { DecWordReg(BW); CLK(2); } |
| 120 | | OP( 0x4c, i_dec_sp ) { DecWordReg(SP); CLK(2); } |
| 121 | | OP( 0x4d, i_dec_bp ) { DecWordReg(BP); CLK(2); } |
| 122 | | OP( 0x4e, i_dec_si ) { DecWordReg(IX); CLK(2); } |
| 123 | | OP( 0x4f, i_dec_di ) { DecWordReg(IY); CLK(2); } |
| 124 | | |
| 125 | | OP( 0x50, i_push_ax ) { PUSH(Wreg(AW)); CLKS(12,8,3); } |
| 126 | | OP( 0x51, i_push_cx ) { PUSH(Wreg(CW)); CLKS(12,8,3); } |
| 127 | | OP( 0x52, i_push_dx ) { PUSH(Wreg(DW)); CLKS(12,8,3); } |
| 128 | | OP( 0x53, i_push_bx ) { PUSH(Wreg(BW)); CLKS(12,8,3); } |
| 129 | | OP( 0x54, i_push_sp ) { PUSH(Wreg(SP)); CLKS(12,8,3); } |
| 130 | | OP( 0x55, i_push_bp ) { PUSH(Wreg(BP)); CLKS(12,8,3); } |
| 131 | | OP( 0x56, i_push_si ) { PUSH(Wreg(IX)); CLKS(12,8,3); } |
| 132 | | OP( 0x57, i_push_di ) { PUSH(Wreg(IY)); CLKS(12,8,3); } |
| 133 | | |
| 134 | | OP( 0x58, i_pop_ax ) { POP(Wreg(AW)); CLKS(12,8,5); } |
| 135 | | OP( 0x59, i_pop_cx ) { POP(Wreg(CW)); CLKS(12,8,5); } |
| 136 | | OP( 0x5a, i_pop_dx ) { POP(Wreg(DW)); CLKS(12,8,5); } |
| 137 | | OP( 0x5b, i_pop_bx ) { POP(Wreg(BW)); CLKS(12,8,5); } |
| 138 | | OP( 0x5c, i_pop_sp ) { POP(Wreg(SP)); CLKS(12,8,5); } |
| 139 | | OP( 0x5d, i_pop_bp ) { POP(Wreg(BP)); CLKS(12,8,5); } |
| 140 | | OP( 0x5e, i_pop_si ) { POP(Wreg(IX)); CLKS(12,8,5); } |
| 141 | | OP( 0x5f, i_pop_di ) { POP(Wreg(IY)); CLKS(12,8,5); } |
| 142 | | |
| 143 | | OP( 0x60, i_pusha ) { |
| 144 | | unsigned tmp=Wreg(SP); |
| 145 | | PUSH(Wreg(AW)); |
| 146 | | PUSH(Wreg(CW)); |
| 147 | | PUSH(Wreg(DW)); |
| 148 | | PUSH(Wreg(BW)); |
| 149 | | PUSH(tmp); |
| 150 | | PUSH(Wreg(BP)); |
| 151 | | PUSH(Wreg(IX)); |
| 152 | | PUSH(Wreg(IY)); |
| 153 | | CLKS(67,35,20); |
| 154 | | } |
| 155 | | static unsigned nec_popa_tmp; |
| 156 | | OP( 0x61, i_popa ) { |
| 157 | | POP(Wreg(IY)); |
| 158 | | POP(Wreg(IX)); |
| 159 | | POP(Wreg(BP)); |
| 160 | | POP(nec_popa_tmp); |
| 161 | | POP(Wreg(BW)); |
| 162 | | POP(Wreg(DW)); |
| 163 | | POP(Wreg(CW)); |
| 164 | | POP(Wreg(AW)); |
| 165 | | CLKS(75,43,22); |
| 166 | | } |
| 167 | | OP( 0x62, i_chkind ) { |
| 168 | | UINT32 low,high,tmp; |
| 169 | | GetModRM; |
| 170 | | low = GetRMWord(ModRM); |
| 171 | | high= GetnextRMWord; |
| 172 | | tmp= RegWord(ModRM); |
| 173 | | if (tmp<low || tmp>high) { |
| 174 | | nec_interrupt(NEC_CHKIND_VECTOR, BRK); |
| 175 | | } |
| 176 | | m_icount-=20; |
| 177 | | logerror("%06x: bound %04x high %04x low %04x tmp\n",PC(),high,low,tmp); |
| 178 | | } |
| 179 | | OP( 0x64, i_repnc ) { UINT32 next = fetchop(); UINT16 c = Wreg(CW); |
| 180 | | switch(next) { /* Segments */ |
| 181 | | case 0x26: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS1)<<4; next = fetchop(); CLK(2); break; |
| 182 | | case 0x2e: m_seg_prefix=TRUE; m_prefix_base=Sreg(PS)<<4; next = fetchop(); CLK(2); break; |
| 183 | | case 0x36: m_seg_prefix=TRUE; m_prefix_base=Sreg(SS)<<4; next = fetchop(); CLK(2); break; |
| 184 | | case 0x3e: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS0)<<4; next = fetchop(); CLK(2); break; |
| 185 | | } |
| 186 | | |
| 187 | | switch(next) { |
| 188 | | case 0x6c: CLK(2); if (c) do { i_insb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 189 | | case 0x6d: CLK(2); if (c) do { i_insw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 190 | | case 0x6e: CLK(2); if (c) do { i_outsb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 191 | | case 0x6f: CLK(2); if (c) do { i_outsw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 192 | | case 0xa4: CLK(2); if (c) do { i_movsb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 193 | | case 0xa5: CLK(2); if (c) do { i_movsw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 194 | | case 0xa6: CLK(2); if (c) do { i_cmpsb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 195 | | case 0xa7: CLK(2); if (c) do { i_cmpsw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 196 | | case 0xaa: CLK(2); if (c) do { i_stosb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 197 | | case 0xab: CLK(2); if (c) do { i_stosw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 198 | | case 0xac: CLK(2); if (c) do { i_lodsb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 199 | | case 0xad: CLK(2); if (c) do { i_lodsw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 200 | | case 0xae: CLK(2); if (c) do { i_scasb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 201 | | case 0xaf: CLK(2); if (c) do { i_scasw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 202 | | default: logerror("%06x: REPNC invalid\n",PC()); (this->*s_nec_instruction[next])(); |
| 203 | | } |
| 204 | | m_seg_prefix=FALSE; |
| 205 | | } |
| 206 | | |
| 207 | | OP( 0x65, i_repc ) { UINT32 next = fetchop(); UINT16 c = Wreg(CW); |
| 208 | | switch(next) { /* Segments */ |
| 209 | | case 0x26: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS1)<<4; next = fetchop(); CLK(2); break; |
| 210 | | case 0x2e: m_seg_prefix=TRUE; m_prefix_base=Sreg(PS)<<4; next = fetchop(); CLK(2); break; |
| 211 | | case 0x36: m_seg_prefix=TRUE; m_prefix_base=Sreg(SS)<<4; next = fetchop(); CLK(2); break; |
| 212 | | case 0x3e: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS0)<<4; next = fetchop(); CLK(2); break; |
| 213 | | } |
| 214 | | |
| 215 | | switch(next) { |
| 216 | | case 0x6c: CLK(2); if (c) do { i_insb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 217 | | case 0x6d: CLK(2); if (c) do { i_insw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 218 | | case 0x6e: CLK(2); if (c) do { i_outsb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 219 | | case 0x6f: CLK(2); if (c) do { i_outsw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 220 | | case 0xa4: CLK(2); if (c) do { i_movsb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 221 | | case 0xa5: CLK(2); if (c) do { i_movsw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 222 | | case 0xa6: CLK(2); if (c) do { i_cmpsb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 223 | | case 0xa7: CLK(2); if (c) do { i_cmpsw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 224 | | case 0xaa: CLK(2); if (c) do { i_stosb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 225 | | case 0xab: CLK(2); if (c) do { i_stosw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 226 | | case 0xac: CLK(2); if (c) do { i_lodsb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 227 | | case 0xad: CLK(2); if (c) do { i_lodsw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 228 | | case 0xae: CLK(2); if (c) do { i_scasb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 229 | | case 0xaf: CLK(2); if (c) do { i_scasw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 230 | | default: logerror("%06x: REPC invalid\n",PC()); (this->*s_nec_instruction[next])(); |
| 231 | | } |
| 232 | | m_seg_prefix=FALSE; |
| 233 | | } |
| 234 | | |
| 235 | | OP( 0x68, i_push_d16 ) { UINT32 tmp; tmp = FETCHWORD(); PUSH(tmp); CLKW(12,12,5,12,8,5,Wreg(SP)); } |
| 236 | | OP( 0x69, i_imul_d16 ) { UINT32 tmp; DEF_r16w; tmp = FETCHWORD(); dst = (INT32)((INT16)src)*(INT32)((INT16)tmp); m_CarryVal = m_OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; m_icount-=(ModRM >=0xc0 )?38:47;} |
| 237 | | OP( 0x6a, i_push_d8 ) { UINT32 tmp = (WORD)((INT16)((INT8)FETCH())); PUSH(tmp); CLKW(11,11,5,11,7,3,Wreg(SP)); } |
| 238 | | OP( 0x6b, i_imul_d8 ) { UINT32 src2; DEF_r16w; src2= (WORD)((INT16)((INT8)FETCH())); dst = (INT32)((INT16)src)*(INT32)((INT16)src2); m_CarryVal = m_OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; m_icount-=(ModRM >=0xc0 )?31:39; } |
| 239 | | OP( 0x6c, i_insb ) { PutMemB(DS1,Wreg(IY),read_port_byte(Wreg(DW))); Wreg(IY)+= -2 * m_DF + 1; CLK(8); } |
| 240 | | OP( 0x6d, i_insw ) { PutMemW(DS1,Wreg(IY),read_port_word(Wreg(DW))); Wreg(IY)+= -4 * m_DF + 2; CLKS(18,10,8); } |
| 241 | | OP( 0x6e, i_outsb ) { write_port_byte(Wreg(DW),GetMemB(DS0,Wreg(IX))); Wreg(IX)+= -2 * m_DF + 1; CLK(8); } |
| 242 | | OP( 0x6f, i_outsw ) { write_port_word(Wreg(DW),GetMemW(DS0,Wreg(IX))); Wreg(IX)+= -4 * m_DF + 2; CLKS(18,10,8); } |
| 243 | | |
| 244 | | OP( 0x70, i_jo ) { JMP( OF); CLKS(4,4,3); } |
| 245 | | OP( 0x71, i_jno ) { JMP(!OF); CLKS(4,4,3); } |
| 246 | | OP( 0x72, i_jc ) { JMP( CF); CLKS(4,4,3); } |
| 247 | | OP( 0x73, i_jnc ) { JMP(!CF); CLKS(4,4,3); } |
| 248 | | OP( 0x74, i_jz ) { JMP( ZF); CLKS(4,4,3); } |
| 249 | | OP( 0x75, i_jnz ) { JMP(!ZF); CLKS(4,4,3); } |
| 250 | | OP( 0x76, i_jce ) { JMP(CF || ZF); CLKS(4,4,3); } |
| 251 | | OP( 0x77, i_jnce ) { JMP(!(CF || ZF)); CLKS(4,4,3); } |
| 252 | | OP( 0x78, i_js ) { JMP( SF); CLKS(4,4,3); } |
| 253 | | OP( 0x79, i_jns ) { JMP(!SF); CLKS(4,4,3); } |
| 254 | | OP( 0x7a, i_jp ) { JMP( PF); CLKS(4,4,3); } |
| 255 | | OP( 0x7b, i_jnp ) { JMP(!PF); CLKS(4,4,3); } |
| 256 | | OP( 0x7c, i_jl ) { JMP((SF!=OF)&&(!ZF)); CLKS(4,4,3); } |
| 257 | | OP( 0x7d, i_jnl ) { JMP((ZF)||(SF==OF)); CLKS(4,4,3); } |
| 258 | | OP( 0x7e, i_jle ) { JMP((ZF)||(SF!=OF)); CLKS(4,4,3); } |
| 259 | | OP( 0x7f, i_jnle ) { JMP((SF==OF)&&(!ZF)); CLKS(4,4,3); } |
| 260 | | |
| 261 | | OP( 0x80, i_80pre ) { UINT32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = FETCH(); |
| 262 | | if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKS(13,13,6) else CLKS(18,18,7) |
| 263 | | switch (ModRM & 0x38) { |
| 264 | | case 0x00: ADDB; PutbackRMByte(ModRM,dst); break; |
| 265 | | case 0x08: ORB; PutbackRMByte(ModRM,dst); break; |
| 266 | | case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break; |
| 267 | | case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break; |
| 268 | | case 0x20: ANDB; PutbackRMByte(ModRM,dst); break; |
| 269 | | case 0x28: SUBB; PutbackRMByte(ModRM,dst); break; |
| 270 | | case 0x30: XORB; PutbackRMByte(ModRM,dst); break; |
| 271 | | case 0x38: SUBB; break; /* CMP */ |
| 272 | | } |
| 273 | | } |
| 274 | | |
| 275 | | OP( 0x81, i_81pre ) { UINT32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = FETCH(); src+= (FETCH() << 8); |
| 276 | | if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKW(17,17,8,17,13,6,m_EA) else CLKW(26,26,11,26,18,7,m_EA) |
| 277 | | switch (ModRM & 0x38) { |
| 278 | | case 0x00: ADDW; PutbackRMWord(ModRM,dst); break; |
| 279 | | case 0x08: ORW; PutbackRMWord(ModRM,dst); break; |
| 280 | | case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break; |
| 281 | | case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break; |
| 282 | | case 0x20: ANDW; PutbackRMWord(ModRM,dst); break; |
| 283 | | case 0x28: SUBW; PutbackRMWord(ModRM,dst); break; |
| 284 | | case 0x30: XORW; PutbackRMWord(ModRM,dst); break; |
| 285 | | case 0x38: SUBW; break; /* CMP */ |
| 286 | | } |
| 287 | | } |
| 288 | | |
| 289 | | OP( 0x82, i_82pre ) { UINT32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = (BYTE)((INT8)FETCH()); |
| 290 | | if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKS(13,13,6) else CLKS(18,18,7) |
| 291 | | switch (ModRM & 0x38) { |
| 292 | | case 0x00: ADDB; PutbackRMByte(ModRM,dst); break; |
| 293 | | case 0x08: ORB; PutbackRMByte(ModRM,dst); break; |
| 294 | | case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break; |
| 295 | | case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break; |
| 296 | | case 0x20: ANDB; PutbackRMByte(ModRM,dst); break; |
| 297 | | case 0x28: SUBB; PutbackRMByte(ModRM,dst); break; |
| 298 | | case 0x30: XORB; PutbackRMByte(ModRM,dst); break; |
| 299 | | case 0x38: SUBB; break; /* CMP */ |
| 300 | | } |
| 301 | | } |
| 302 | | |
| 303 | | OP( 0x83, i_83pre ) { UINT32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = (WORD)((INT16)((INT8)FETCH())); |
| 304 | | if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKW(17,17,8,17,13,6,m_EA) else CLKW(26,26,11,26,18,7,m_EA) |
| 305 | | switch (ModRM & 0x38) { |
| 306 | | case 0x00: ADDW; PutbackRMWord(ModRM,dst); break; |
| 307 | | case 0x08: ORW; PutbackRMWord(ModRM,dst); break; |
| 308 | | case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break; |
| 309 | | case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break; |
| 310 | | case 0x20: ANDW; PutbackRMWord(ModRM,dst); break; |
| 311 | | case 0x28: SUBW; PutbackRMWord(ModRM,dst); break; |
| 312 | | case 0x30: XORW; PutbackRMWord(ModRM,dst); break; |
| 313 | | case 0x38: SUBW; break; /* CMP */ |
| 314 | | } |
| 315 | | } |
| 316 | | |
| 317 | | OP( 0x84, i_test_br8 ) { DEF_br8; ANDB; CLKM(2,2,2,10,10,6); } |
| 318 | | OP( 0x85, i_test_wr16 ) { DEF_wr16; ANDW; CLKR(14,14,8,14,10,6,2,m_EA); } |
| 319 | | OP( 0x86, i_xchg_br8 ) { DEF_br8; RegByte(ModRM)=dst; PutbackRMByte(ModRM,src); CLKM(3,3,3,16,18,8); } |
| 320 | | OP( 0x87, i_xchg_wr16 ) { DEF_wr16; RegWord(ModRM)=dst; PutbackRMWord(ModRM,src); CLKR(24,24,12,24,16,8,3,m_EA); } |
| 321 | | |
| 322 | | OP( 0x88, i_mov_br8 ) { UINT8 src; GetModRM; src = RegByte(ModRM); PutRMByte(ModRM,src); CLKM(2,2,2,9,9,3); } |
| 323 | | OP( 0x89, i_mov_wr16 ) { UINT16 src; GetModRM; src = RegWord(ModRM); PutRMWord(ModRM,src); CLKR(13,13,5,13,9,3,2,m_EA); } |
| 324 | | OP( 0x8a, i_mov_r8b ) { UINT8 src; GetModRM; src = GetRMByte(ModRM); RegByte(ModRM)=src; CLKM(2,2,2,11,11,5); } |
| 325 | | OP( 0x8b, i_mov_r16w ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); RegWord(ModRM)=src; CLKR(15,15,7,15,11,5,2,m_EA); } |
| 326 | | OP( 0x8c, i_mov_wsreg ) { GetModRM; |
| 327 | | switch (ModRM & 0x38) { |
| 328 | | case 0x00: PutRMWord(ModRM,Sreg(DS1)); CLKR(14,14,5,14,10,3,2,m_EA); break; |
| 329 | | case 0x08: PutRMWord(ModRM,Sreg(PS)); CLKR(14,14,5,14,10,3,2,m_EA); break; |
| 330 | | case 0x10: PutRMWord(ModRM,Sreg(SS)); CLKR(14,14,5,14,10,3,2,m_EA); break; |
| 331 | | case 0x18: PutRMWord(ModRM,Sreg(DS0)); CLKR(14,14,5,14,10,3,2,m_EA); break; |
| 332 | | default: logerror("%06x: MOV Sreg - Invalid register\n",PC()); |
| 333 | | } |
| 334 | | } |
| 335 | | OP( 0x8d, i_lea ) { UINT16 ModRM = FETCH(); (void)(this->*s_GetEA[ModRM])(); RegWord(ModRM)=m_EO; CLKS(4,4,2); } |
| 336 | | OP( 0x8e, i_mov_sregw ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); CLKR(15,15,7,15,11,5,2,m_EA); |
| 337 | | switch (ModRM & 0x38) { |
| 338 | | case 0x00: Sreg(DS1) = src; break; /* mov es,ew */ |
| 339 | | case 0x08: Sreg(PS) = src; break; /* mov cs,ew */ |
| 340 | | case 0x10: Sreg(SS) = src; break; /* mov ss,ew */ |
| 341 | | case 0x18: Sreg(DS0) = src; break; /* mov ds,ew */ |
| 342 | | default: logerror("%06x: MOV Sreg - Invalid register\n",PC()); |
| 343 | | } |
| 344 | | m_no_interrupt=1; |
| 345 | | } |
| 346 | | OP( 0x8f, i_popw ) { UINT16 tmp; GetModRM; POP(tmp); PutRMWord(ModRM,tmp); m_icount-=21; } |
| 347 | | OP( 0x90, i_nop ) { CLK(3); /* { if (m_MF == 0) printf("90 -> %06x: \n",PC()); } */ } |
| 348 | | OP( 0x91, i_xchg_axcx ) { XchgAWReg(CW); CLK(3); } |
| 349 | | OP( 0x92, i_xchg_axdx ) { XchgAWReg(DW); CLK(3); } |
| 350 | | OP( 0x93, i_xchg_axbx ) { XchgAWReg(BW); CLK(3); } |
| 351 | | OP( 0x94, i_xchg_axsp ) { XchgAWReg(SP); CLK(3); } |
| 352 | | OP( 0x95, i_xchg_axbp ) { XchgAWReg(BP); CLK(3); } |
| 353 | | OP( 0x96, i_xchg_axsi ) { XchgAWReg(IX); CLK(3); } |
| 354 | | OP( 0x97, i_xchg_axdi ) { XchgAWReg(IY); CLK(3); } |
| 355 | | |
| 356 | | OP( 0x98, i_cbw ) { Breg(AH) = (Breg(AL) & 0x80) ? 0xff : 0; CLK(2); } |
| 357 | | OP( 0x99, i_cwd ) { Wreg(DW) = (Breg(AH) & 0x80) ? 0xffff : 0; CLK(4); } |
| 358 | | OP( 0x9a, i_call_far ) { UINT32 tmp, tmp2; tmp = FETCHWORD(); tmp2 = FETCHWORD(); PUSH(Sreg(PS)); PUSH(m_ip); m_ip = (WORD)tmp; Sreg(PS) = (WORD)tmp2; CHANGE_PC; CLKW(29,29,13,29,21,9,Wreg(SP)); } |
| 359 | | OP( 0x9b, i_wait ) { if (!m_poll_state) m_ip--; CLK(5); } |
| 360 | | OP( 0x9c, i_pushf ) { UINT16 tmp = CompressFlags(); PUSH( tmp ); CLKS(12,8,3); } |
| 361 | | OP( 0x9d, i_popf ) { UINT32 tmp; POP(tmp); ExpandFlags(tmp); CLKS(12,8,5); if (m_TF) nec_trap(); } |
| 362 | | OP( 0x9e, i_sahf ) { UINT32 tmp = (CompressFlags() & 0xff00) | (Breg(AH) & 0xd5); ExpandFlags(tmp); CLKS(3,3,2); } |
| 363 | | OP( 0x9f, i_lahf ) { Breg(AH) = CompressFlags() & 0xff; CLKS(3,3,2); } |
| 364 | | |
| 365 | | OP( 0xa0, i_mov_aldisp ) { UINT32 addr; addr = FETCHWORD(); Breg(AL) = GetMemB(DS0, addr); CLKS(10,10,5); } |
| 366 | | OP( 0xa1, i_mov_axdisp ) { UINT32 addr; addr = FETCHWORD(); Wreg(AW) = GetMemW(DS0, addr); CLKW(14,14,7,14,10,5,addr); } |
| 367 | | OP( 0xa2, i_mov_dispal ) { UINT32 addr; addr = FETCHWORD(); PutMemB(DS0, addr, Breg(AL)); CLKS(9,9,3); } |
| 368 | | OP( 0xa3, i_mov_dispax ) { UINT32 addr; addr = FETCHWORD(); PutMemW(DS0, addr, Wreg(AW)); CLKW(13,13,5,13,9,3,addr); } |
| 369 | | OP( 0xa4, i_movsb ) { UINT32 tmp = GetMemB(DS0,Wreg(IX)); PutMemB(DS1,Wreg(IY), tmp); Wreg(IY) += -2 * m_DF + 1; Wreg(IX) += -2 * m_DF + 1; CLKS(8,8,6); } |
| 370 | | OP( 0xa5, i_movsw ) { UINT32 tmp = GetMemW(DS0,Wreg(IX)); PutMemW(DS1,Wreg(IY), tmp); Wreg(IY) += -4 * m_DF + 2; Wreg(IX) += -4 * m_DF + 2; CLKS(16,16,10); } |
| 371 | | OP( 0xa6, i_cmpsb ) { UINT32 src = GetMemB(DS1, Wreg(IY)); UINT32 dst = GetMemB(DS0, Wreg(IX)); SUBB; Wreg(IY) += -2 * m_DF + 1; Wreg(IX) += -2 * m_DF + 1; CLKS(14,14,14); } |
| 372 | | OP( 0xa7, i_cmpsw ) { UINT32 src = GetMemW(DS1, Wreg(IY)); UINT32 dst = GetMemW(DS0, Wreg(IX)); SUBW; Wreg(IY) += -4 * m_DF + 2; Wreg(IX) += -4 * m_DF + 2; CLKS(14,14,14); } |
| 373 | | |
| 374 | | OP( 0xa8, i_test_ald8 ) { DEF_ald8; ANDB; CLKS(4,4,2); } |
| 375 | | OP( 0xa9, i_test_axd16 ) { DEF_axd16; ANDW; CLKS(4,4,2); } |
| 376 | | OP( 0xaa, i_stosb ) { PutMemB(DS1,Wreg(IY),Breg(AL)); Wreg(IY) += -2 * m_DF + 1; CLKS(4,4,3); } |
| 377 | | OP( 0xab, i_stosw ) { PutMemW(DS1,Wreg(IY),Wreg(AW)); Wreg(IY) += -4 * m_DF + 2; CLKW(8,8,5,8,4,3,Wreg(IY)); } |
| 378 | | OP( 0xac, i_lodsb ) { Breg(AL) = GetMemB(DS0,Wreg(IX)); Wreg(IX) += -2 * m_DF + 1; CLKS(4,4,3); } |
| 379 | | OP( 0xad, i_lodsw ) { Wreg(AW) = GetMemW(DS0,Wreg(IX)); Wreg(IX) += -4 * m_DF + 2; CLKW(8,8,5,8,4,3,Wreg(IX)); } |
| 380 | | OP( 0xae, i_scasb ) { UINT32 src = GetMemB(DS1, Wreg(IY)); UINT32 dst = Breg(AL); SUBB; Wreg(IY) += -2 * m_DF + 1; CLKS(4,4,3); } |
| 381 | | OP( 0xaf, i_scasw ) { UINT32 src = GetMemW(DS1, Wreg(IY)); UINT32 dst = Wreg(AW); SUBW; Wreg(IY) += -4 * m_DF + 2; CLKW(8,8,5,8,4,3,Wreg(IY)); } |
| 382 | | |
| 383 | | OP( 0xb0, i_mov_ald8 ) { Breg(AL) = FETCH(); CLKS(4,4,2); } |
| 384 | | OP( 0xb1, i_mov_cld8 ) { Breg(CL) = FETCH(); CLKS(4,4,2); } |
| 385 | | OP( 0xb2, i_mov_dld8 ) { Breg(DL) = FETCH(); CLKS(4,4,2); } |
| 386 | | OP( 0xb3, i_mov_bld8 ) { Breg(BL) = FETCH(); CLKS(4,4,2); } |
| 387 | | OP( 0xb4, i_mov_ahd8 ) { Breg(AH) = FETCH(); CLKS(4,4,2); } |
| 388 | | OP( 0xb5, i_mov_chd8 ) { Breg(CH) = FETCH(); CLKS(4,4,2); } |
| 389 | | OP( 0xb6, i_mov_dhd8 ) { Breg(DH) = FETCH(); CLKS(4,4,2); } |
| 390 | | OP( 0xb7, i_mov_bhd8 ) { Breg(BH) = FETCH(); CLKS(4,4,2); } |
| 391 | | |
| 392 | | OP( 0xb8, i_mov_axd16 ) { Breg(AL) = FETCH(); Breg(AH) = FETCH(); CLKS(4,4,2); } |
| 393 | | OP( 0xb9, i_mov_cxd16 ) { Breg(CL) = FETCH(); Breg(CH) = FETCH(); CLKS(4,4,2); } |
| 394 | | OP( 0xba, i_mov_dxd16 ) { Breg(DL) = FETCH(); Breg(DH) = FETCH(); CLKS(4,4,2); } |
| 395 | | OP( 0xbb, i_mov_bxd16 ) { Breg(BL) = FETCH(); Breg(BH) = FETCH(); CLKS(4,4,2); } |
| 396 | | OP( 0xbc, i_mov_spd16 ) { Wreg(SP) = FETCHWORD(); CLKS(4,4,2); } |
| 397 | | OP( 0xbd, i_mov_bpd16 ) { Wreg(BP) = FETCHWORD(); CLKS(4,4,2); } |
| 398 | | OP( 0xbe, i_mov_sid16 ) { Wreg(IX) = FETCHWORD(); CLKS(4,4,2); } |
| 399 | | OP( 0xbf, i_mov_did16 ) { Wreg(IY) = FETCHWORD(); CLKS(4,4,2); } |
| 400 | | |
| 401 | | OP( 0xc0, i_rotshft_bd8 ) { |
| 402 | | UINT32 src, dst; UINT8 c; |
| 403 | | GetModRM; src = (unsigned)GetRMByte(ModRM); dst=src; |
| 404 | | c=FETCH(); |
| 405 | | CLKM(7,7,2,19,19,6); |
| 406 | | if (c) switch (ModRM & 0x38) { |
| 407 | | case 0x00: do { ROL_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 408 | | case 0x08: do { ROR_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 409 | | case 0x10: do { ROLC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 410 | | case 0x18: do { RORC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 411 | | case 0x20: SHL_BYTE(c); break; |
| 412 | | case 0x28: SHR_BYTE(c); break; |
| 413 | | case 0x30: logerror("%06x: Undefined opcode 0xc0 0x30 (SHLA)\n",PC()); break; |
| 414 | | case 0x38: SHRA_BYTE(c); break; |
| 415 | | } |
| 416 | | } |
| 417 | | |
| 418 | | OP( 0xc1, i_rotshft_wd8 ) { |
| 419 | | UINT32 src, dst; UINT8 c; |
| 420 | | GetModRM; src = (unsigned)GetRMWord(ModRM); dst=src; |
| 421 | | c=FETCH(); |
| 422 | | CLKM(7,7,2,27,19,6); |
| 423 | | if (c) switch (ModRM & 0x38) { |
| 424 | | case 0x00: do { ROL_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 425 | | case 0x08: do { ROR_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 426 | | case 0x10: do { ROLC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 427 | | case 0x18: do { RORC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 428 | | case 0x20: SHL_WORD(c); break; |
| 429 | | case 0x28: SHR_WORD(c); break; |
| 430 | | case 0x30: logerror("%06x: Undefined opcode 0xc1 0x30 (SHLA)\n",PC()); break; |
| 431 | | case 0x38: SHRA_WORD(c); break; |
| 432 | | } |
| 433 | | } |
| 434 | | |
| 435 | | OP( 0xc2, i_ret_d16 ) { UINT32 count = FETCH(); count += FETCH() << 8; POP(m_ip); Wreg(SP)+=count; CHANGE_PC; CLKS(24,24,10); } |
| 436 | | OP( 0xc3, i_ret ) { POP(m_ip); CHANGE_PC; CLKS(19,19,10); } |
| 437 | | OP( 0xc4, i_les_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; Sreg(DS1) = GetnextRMWord; CLKW(26,26,14,26,18,10,m_EA); } |
| 438 | | OP( 0xc5, i_lds_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; Sreg(DS0) = GetnextRMWord; CLKW(26,26,14,26,18,10,m_EA); } |
| 439 | | OP( 0xc6, i_mov_bd8 ) { GetModRM; PutImmRMByte(ModRM); m_icount-=(ModRM >=0xc0 )?4:11; } |
| 440 | | OP( 0xc7, i_mov_wd16 ) { GetModRM; PutImmRMWord(ModRM); m_icount-=(ModRM >=0xc0 )?4:15; } |
| 441 | | |
| 442 | | OP( 0xc8, i_enter ) { |
| 443 | | UINT32 nb = FETCH(); |
| 444 | | UINT32 i,level; |
| 445 | | |
| 446 | | m_icount-=23; |
| 447 | | nb += FETCH() << 8; |
| 448 | | level = FETCH(); |
| 449 | | PUSH(Wreg(BP)); |
| 450 | | Wreg(BP)=Wreg(SP); |
| 451 | | Wreg(SP) -= nb; |
| 452 | | for (i=1;i<level;i++) { |
| 453 | | PUSH(GetMemW(SS,Wreg(BP)-i*2)); |
| 454 | | m_icount-=16; |
| 455 | | } |
| 456 | | if (level) PUSH(Wreg(BP)); |
| 457 | | } |
| 458 | | OP( 0xc9, i_leave ) { |
| 459 | | Wreg(SP)=Wreg(BP); |
| 460 | | POP(Wreg(BP)); |
| 461 | | m_icount-=8; |
| 462 | | } |
| 463 | | OP( 0xca, i_retf_d16 ) { UINT32 count = FETCH(); count += FETCH() << 8; POP(m_ip); POP(Sreg(PS)); Wreg(SP)+=count; CHANGE_PC; CLKS(32,32,16); } |
| 464 | | OP( 0xcb, i_retf ) { POP(m_ip); POP(Sreg(PS)); CHANGE_PC; CLKS(29,29,16); } |
| 465 | | OP( 0xcc, i_int3 ) { nec_interrupt(3, BRK); CLKS(50,50,24); } |
| 466 | | OP( 0xcd, i_int ) { nec_interrupt(FETCH(), BRK); CLKS(50,50,24); } |
| 467 | | OP( 0xce, i_into ) { if (OF) { nec_interrupt(NEC_BRKV_VECTOR, BRK); CLKS(52,52,26); } else CLK(3); } |
| 468 | | OP( 0xcf, i_iret ) { POP(m_ip); POP(Sreg(PS)); i_popf(); CHANGE_PC; CLKS(39,39,19); } |
| 469 | | |
| 470 | | OP( 0xd0, i_rotshft_b ) { |
| 471 | | UINT32 src, dst; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src; |
| 472 | | CLKM(6,6,2,16,16,7); |
| 473 | | switch (ModRM & 0x38) { |
| 474 | | case 0x00: ROL_BYTE; PutbackRMByte(ModRM,(BYTE)dst); m_OverVal = (src^dst)&0x80; break; |
| 475 | | case 0x08: ROR_BYTE; PutbackRMByte(ModRM,(BYTE)dst); m_OverVal = (src^dst)&0x80; break; |
| 476 | | case 0x10: ROLC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); m_OverVal = (src^dst)&0x80; break; |
| 477 | | case 0x18: RORC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); m_OverVal = (src^dst)&0x80; break; |
| 478 | | case 0x20: SHL_BYTE(1); m_OverVal = (src^dst)&0x80; break; |
| 479 | | case 0x28: SHR_BYTE(1); m_OverVal = (src^dst)&0x80; break; |
| 480 | | case 0x30: logerror("%06x: Undefined opcode 0xd0 0x30 (SHLA)\n",PC()); break; |
| 481 | | case 0x38: SHRA_BYTE(1); m_OverVal = 0; break; |
| 482 | | } |
| 483 | | } |
| 484 | | |
| 485 | | OP( 0xd1, i_rotshft_w ) { |
| 486 | | UINT32 src, dst; GetModRM; src = (UINT32)GetRMWord(ModRM); dst=src; |
| 487 | | CLKM(6,6,2,24,16,7); |
| 488 | | switch (ModRM & 0x38) { |
| 489 | | case 0x00: ROL_WORD; PutbackRMWord(ModRM,(WORD)dst); m_OverVal = (src^dst)&0x8000; break; |
| 490 | | case 0x08: ROR_WORD; PutbackRMWord(ModRM,(WORD)dst); m_OverVal = (src^dst)&0x8000; break; |
| 491 | | case 0x10: ROLC_WORD; PutbackRMWord(ModRM,(WORD)dst); m_OverVal = (src^dst)&0x8000; break; |
| 492 | | case 0x18: RORC_WORD; PutbackRMWord(ModRM,(WORD)dst); m_OverVal = (src^dst)&0x8000; break; |
| 493 | | case 0x20: SHL_WORD(1); m_OverVal = (src^dst)&0x8000; break; |
| 494 | | case 0x28: SHR_WORD(1); m_OverVal = (src^dst)&0x8000; break; |
| 495 | | case 0x30: logerror("%06x: Undefined opcode 0xd1 0x30 (SHLA)\n",PC()); break; |
| 496 | | case 0x38: SHRA_WORD(1); m_OverVal = 0; break; |
| 497 | | } |
| 498 | | } |
| 499 | | |
| 500 | | OP( 0xd2, i_rotshft_bcl ) { |
| 501 | | UINT32 src, dst; UINT8 c; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src; |
| 502 | | c=Breg(CL); |
| 503 | | CLKM(7,7,2,19,19,6); |
| 504 | | if (c) switch (ModRM & 0x38) { |
| 505 | | case 0x00: do { ROL_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 506 | | case 0x08: do { ROR_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 507 | | case 0x10: do { ROLC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 508 | | case 0x18: do { RORC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 509 | | case 0x20: SHL_BYTE(c); break; |
| 510 | | case 0x28: SHR_BYTE(c); break; |
| 511 | | case 0x30: logerror("%06x: Undefined opcode 0xd2 0x30 (SHLA)\n",PC()); break; |
| 512 | | case 0x38: SHRA_BYTE(c); break; |
| 513 | | } |
| 514 | | } |
| 515 | | |
| 516 | | OP( 0xd3, i_rotshft_wcl ) { |
| 517 | | UINT32 src, dst; UINT8 c; GetModRM; src = (UINT32)GetRMWord(ModRM); dst=src; |
| 518 | | c=Breg(CL); |
| 519 | | CLKM(7,7,2,27,19,6); |
| 520 | | if (c) switch (ModRM & 0x38) { |
| 521 | | case 0x00: do { ROL_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 522 | | case 0x08: do { ROR_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 523 | | case 0x10: do { ROLC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 524 | | case 0x18: do { RORC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 525 | | case 0x20: SHL_WORD(c); break; |
| 526 | | case 0x28: SHR_WORD(c); break; |
| 527 | | case 0x30: logerror("%06x: Undefined opcode 0xd3 0x30 (SHLA)\n",PC()); break; |
| 528 | | case 0x38: SHRA_WORD(c); break; |
| 529 | | } |
| 530 | | } |
| 531 | | |
| 532 | | OP( 0xd4, i_aam ) { FETCH(); Breg(AH) = Breg(AL) / 10; Breg(AL) %= 10; SetSZPF_Word(Wreg(AW)); CLKS(15,15,12); } |
| 533 | | OP( 0xd5, i_aad ) { FETCH(); Breg(AL) = Breg(AH) * 10 + Breg(AL); Breg(AH) = 0; SetSZPF_Byte(Breg(AL)); CLKS(7,7,8); } |
| 534 | | OP( 0xd6, i_setalc ) { Breg(AL) = (CF)?0xff:0x00; m_icount-=3; logerror("%06x: Undefined opcode (SETALC)\n",PC()); } |
| 535 | | OP( 0xd7, i_trans ) { UINT32 dest = (Wreg(BW)+Breg(AL))&0xffff; Breg(AL) = GetMemB(DS0, dest); CLKS(9,9,5); } |
| 536 | | OP( 0xd8, i_fpo ) { GetModRM; m_icount-=2; logerror("%06x: Unimplemented floating point control %04x\n",PC(),ModRM); } |
| 537 | | |
| 538 | | OP( 0xe0, i_loopne ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if (!ZF && Wreg(CW)) { m_ip = (WORD)(m_ip+disp); /*CHANGE_PC;*/ CLKS(14,14,6); } else CLKS(5,5,3); } |
| 539 | | OP( 0xe1, i_loope ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if ( ZF && Wreg(CW)) { m_ip = (WORD)(m_ip+disp); /*CHANGE_PC;*/ CLKS(14,14,6); } else CLKS(5,5,3); } |
| 540 | | OP( 0xe2, i_loop ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if (Wreg(CW)) { m_ip = (WORD)(m_ip+disp); /*CHANGE_PC;*/ CLKS(13,13,6); } else CLKS(5,5,3); } |
| 541 | | OP( 0xe3, i_jcxz ) { INT8 disp = (INT8)FETCH(); if (Wreg(CW) == 0) { m_ip = (WORD)(m_ip+disp); /*CHANGE_PC;*/ CLKS(13,13,6); } else CLKS(5,5,3); } |
| 542 | | OP( 0xe4, i_inal ) { UINT8 port = FETCH(); Breg(AL) = read_port_byte(port); CLKS(9,9,5); } |
| 543 | | OP( 0xe5, i_inax ) { UINT8 port = FETCH(); Wreg(AW) = read_port_word(port); CLKW(13,13,7,13,9,5,port); } |
| 544 | | OP( 0xe6, i_outal ) { UINT8 port = FETCH(); write_port_byte(port, Breg(AL)); CLKS(8,8,3); } |
| 545 | | OP( 0xe7, i_outax ) { UINT8 port = FETCH(); write_port_word(port, Wreg(AW)); CLKW(12,12,5,12,8,3,port); } |
| 546 | | |
| 547 | | OP( 0xe8, i_call_d16 ) { UINT32 tmp; tmp = FETCHWORD(); PUSH(m_ip); m_ip = (WORD)(m_ip+(INT16)tmp); CHANGE_PC; m_icount-=24; } |
| 548 | | OP( 0xe9, i_jmp_d16 ) { UINT32 tmp; tmp = FETCHWORD(); m_ip = (WORD)(m_ip+(INT16)tmp); CHANGE_PC; m_icount-=15; } |
| 549 | | OP( 0xea, i_jmp_far ) { UINT32 tmp,tmp1; tmp = FETCHWORD(); tmp1 = FETCHWORD(); Sreg(PS) = (WORD)tmp1; m_ip = (WORD)tmp; CHANGE_PC; m_icount-=27; } |
| 550 | | OP( 0xeb, i_jmp_d8 ) { int tmp = (int)((INT8)FETCH()); m_icount-=12; m_ip = (WORD)(m_ip+tmp); } |
| 551 | | OP( 0xec, i_inaldx ) { Breg(AL) = read_port_byte(Wreg(DW)); CLKS(8,8,5);} |
| 552 | | OP( 0xed, i_inaxdx ) { Wreg(AW) = read_port_word(Wreg(DW)); CLKW(12,12,7,12,8,5,Wreg(DW)); } |
| 553 | | OP( 0xee, i_outdxal ) { write_port_byte(Wreg(DW), Breg(AL)); CLKS(8,8,3); } |
| 554 | | OP( 0xef, i_outdxax ) { write_port_word(Wreg(DW), Wreg(AW)); CLKW(12,12,5,12,8,3,Wreg(DW)); } |
| 555 | | |
| 556 | | OP( 0xf0, i_lock ) { logerror("%06x: Warning - BUSLOCK\n",PC()); m_no_interrupt=1; CLK(2); } |
| 557 | | OP( 0xf2, i_repne ) { UINT32 next = fetchop(); UINT16 c = Wreg(CW); |
| 558 | | switch(next) { /* Segments */ |
| 559 | | case 0x26: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS1)<<4; next = fetchop(); CLK(2); break; |
| 560 | | case 0x2e: m_seg_prefix=TRUE; m_prefix_base=Sreg(PS)<<4; next = fetchop(); CLK(2); break; |
| 561 | | case 0x36: m_seg_prefix=TRUE; m_prefix_base=Sreg(SS)<<4; next = fetchop(); CLK(2); break; |
| 562 | | case 0x3e: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS0)<<4; next = fetchop(); CLK(2); break; |
| 563 | | } |
| 564 | | |
| 565 | | switch(next) { |
| 566 | | case 0x6c: CLK(2); if (c) do { i_insb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 567 | | case 0x6d: CLK(2); if (c) do { i_insw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 568 | | case 0x6e: CLK(2); if (c) do { i_outsb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 569 | | case 0x6f: CLK(2); if (c) do { i_outsw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 570 | | case 0xa4: CLK(2); if (c) do { i_movsb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 571 | | case 0xa5: CLK(2); if (c) do { i_movsw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 572 | | case 0xa6: CLK(2); if (c) do { i_cmpsb(); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; |
| 573 | | case 0xa7: CLK(2); if (c) do { i_cmpsw(); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; |
| 574 | | case 0xaa: CLK(2); if (c) do { i_stosb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 575 | | case 0xab: CLK(2); if (c) do { i_stosw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 576 | | case 0xac: CLK(2); if (c) do { i_lodsb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 577 | | case 0xad: CLK(2); if (c) do { i_lodsw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 578 | | case 0xae: CLK(2); if (c) do { i_scasb(); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; |
| 579 | | case 0xaf: CLK(2); if (c) do { i_scasw(); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; |
| 580 | | default: logerror("%06x: REPNE invalid\n",PC()); (this->*s_nec_instruction[next])(); |
| 581 | | } |
| 582 | | m_seg_prefix=FALSE; |
| 583 | | } |
| 584 | | OP( 0xf3, i_repe ) { UINT32 next = fetchop(); UINT16 c = Wreg(CW); |
| 585 | | switch(next) { /* Segments */ |
| 586 | | case 0x26: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS1)<<4; next = fetchop(); CLK(2); break; |
| 587 | | case 0x2e: m_seg_prefix=TRUE; m_prefix_base=Sreg(PS)<<4; next = fetchop(); CLK(2); break; |
| 588 | | case 0x36: m_seg_prefix=TRUE; m_prefix_base=Sreg(SS)<<4; next = fetchop(); CLK(2); break; |
| 589 | | case 0x3e: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS0)<<4; next = fetchop(); CLK(2); break; |
| 590 | | } |
| 591 | | |
| 592 | | switch(next) { |
| 593 | | case 0x6c: CLK(2); if (c) do { i_insb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 594 | | case 0x6d: CLK(2); if (c) do { i_insw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 595 | | case 0x6e: CLK(2); if (c) do { i_outsb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 596 | | case 0x6f: CLK(2); if (c) do { i_outsw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 597 | | case 0xa4: CLK(2); if (c) do { i_movsb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 598 | | case 0xa5: CLK(2); if (c) do { i_movsw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 599 | | case 0xa6: CLK(2); if (c) do { i_cmpsb(); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; |
| 600 | | case 0xa7: CLK(2); if (c) do { i_cmpsw(); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; |
| 601 | | case 0xaa: CLK(2); if (c) do { i_stosb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 602 | | case 0xab: CLK(2); if (c) do { i_stosw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 603 | | case 0xac: CLK(2); if (c) do { i_lodsb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 604 | | case 0xad: CLK(2); if (c) do { i_lodsw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 605 | | case 0xae: CLK(2); if (c) do { i_scasb(); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; |
| 606 | | case 0xaf: CLK(2); if (c) do { i_scasw(); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; |
| 607 | | default: logerror("%06x: REPE invalid\n",PC()); (this->*s_nec_instruction[next])(); |
| 608 | | } |
| 609 | | m_seg_prefix=FALSE; |
| 610 | | } |
| 611 | | OP( 0xf4, i_hlt ) { logerror("%06x: HALT\n",PC()); m_halted=1; m_icount=0; } |
| 612 | | OP( 0xf5, i_cmc ) { m_CarryVal = !CF; CLK(2); } |
| 613 | | OP( 0xf6, i_f6pre ) { UINT32 tmp; UINT32 uresult,uresult2; INT32 result,result2; |
| 614 | | GetModRM; tmp = GetRMByte(ModRM); |
| 615 | | switch (ModRM & 0x38) { |
| 616 | | case 0x00: tmp &= FETCH(); m_CarryVal = m_OverVal = 0; SetSZPF_Byte(tmp); m_icount-=(ModRM >=0xc0 )?4:11; break; /* TEST */ |
| 617 | | case 0x08: logerror("%06x: Undefined opcode 0xf6 0x08\n",PC()); break; |
| 618 | | case 0x10: PutbackRMByte(ModRM,~tmp); m_icount-=(ModRM >=0xc0 )?2:16; break; /* NOT */ |
| 619 | | case 0x18: m_CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Byte(tmp); PutbackRMByte(ModRM,tmp&0xff); m_icount-=(ModRM >=0xc0 )?2:16; break; /* NEG */ |
| 620 | | case 0x20: uresult = Breg(AL)*tmp; Wreg(AW)=(WORD)uresult; m_CarryVal=m_OverVal=(Breg(AH)!=0); m_icount-=(ModRM >=0xc0 )?30:36; break; /* MULU */ |
| 621 | | case 0x28: result = (INT16)((INT8)Breg(AL))*(INT16)((INT8)tmp); Wreg(AW)=(WORD)result; m_CarryVal=m_OverVal=(Breg(AH)!=0); m_icount-=(ModRM >=0xc0 )?30:36; break; /* MUL */ |
| 622 | | case 0x30: if (tmp) { DIVUB; } else nec_interrupt(NEC_DIVIDE_VECTOR, BRK); m_icount-=(ModRM >=0xc0 )?43:53; break; |
| 623 | | case 0x38: if (tmp) { DIVB; } else nec_interrupt(NEC_DIVIDE_VECTOR, BRK); m_icount-=(ModRM >=0xc0 )?43:53; break; |
| 624 | | } |
| 625 | | } |
| 626 | | |
| 627 | | OP( 0xf7, i_f7pre ) { UINT32 tmp,tmp2; UINT32 uresult,uresult2; INT32 result,result2; |
| 628 | | GetModRM; tmp = GetRMWord(ModRM); |
| 629 | | switch (ModRM & 0x38) { |
| 630 | | case 0x00: tmp2 = FETCHWORD(); tmp &= tmp2; m_CarryVal = m_OverVal = 0; SetSZPF_Word(tmp); m_icount-=(ModRM >=0xc0 )?4:11; break; /* TEST */ |
| 631 | | case 0x08: logerror("%06x: Undefined opcode 0xf7 0x08\n",PC()); break; |
| 632 | | case 0x10: PutbackRMWord(ModRM,~tmp); m_icount-=(ModRM >=0xc0 )?2:16; break; /* NOT */ |
| 633 | | case 0x18: m_CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Word(tmp); PutbackRMWord(ModRM,tmp&0xffff); m_icount-=(ModRM >=0xc0 )?2:16; break; /* NEG */ |
| 634 | | case 0x20: uresult = Wreg(AW)*tmp; Wreg(AW)=uresult&0xffff; Wreg(DW)=((UINT32)uresult)>>16; m_CarryVal=m_OverVal=(Wreg(DW)!=0); m_icount-=(ModRM >=0xc0 )?30:36; break; /* MULU */ |
| 635 | | case 0x28: result = (INT32)((INT16)Wreg(AW))*(INT32)((INT16)tmp); Wreg(AW)=result&0xffff; Wreg(DW)=result>>16; m_CarryVal=m_OverVal=(Wreg(DW)!=0); m_icount-=(ModRM >=0xc0 )?30:36; break; /* MUL */ |
| 636 | | case 0x30: if (tmp) { DIVUW; } else nec_interrupt(NEC_DIVIDE_VECTOR, BRK); m_icount-=(ModRM >=0xc0 )?43:53; break; |
| 637 | | case 0x38: if (tmp) { DIVW; } else nec_interrupt(NEC_DIVIDE_VECTOR, BRK); m_icount-=(ModRM >=0xc0 )?43:53; break; |
| 638 | | } |
| 639 | | } |
| 640 | | |
| 641 | | OP( 0xf8, i_clc ) { m_CarryVal = 0; CLK(2); } |
| 642 | | OP( 0xf9, i_stc ) { m_CarryVal = 1; CLK(2); } |
| 643 | | OP( 0xfa, i_di ) { SetIF(0); CLK(2); } |
| 644 | | OP( 0xfb, i_ei ) { SetIF(1); CLK(2); } |
| 645 | | OP( 0xfc, i_cld ) { SetDF(0); CLK(2); } |
| 646 | | OP( 0xfd, i_std ) { SetDF(1); CLK(2); } |
| 647 | | OP( 0xfe, i_fepre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMByte(ModRM); |
| 648 | | switch(ModRM & 0x38) { |
| 649 | | case 0x00: tmp1 = tmp+1; m_OverVal = (tmp==0x7f); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(2,2,2,16,16,7); break; /* INC */ |
| 650 | | case 0x08: tmp1 = tmp-1; m_OverVal = (tmp==0x80); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(2,2,2,16,16,7); break; /* DEC */ |
| 651 | | default: logerror("%06x: FE Pre with unimplemented mod\n",PC()); |
| 652 | | } |
| 653 | | } |
| 654 | | OP( 0xff, i_ffpre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMWord(ModRM); |
| 655 | | switch(ModRM & 0x38) { |
| 656 | | case 0x00: tmp1 = tmp+1; m_OverVal = (tmp==0x7fff); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(2,2,2,24,16,7); break; /* INC */ |
| 657 | | case 0x08: tmp1 = tmp-1; m_OverVal = (tmp==0x8000); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(2,2,2,24,16,7); break; /* DEC */ |
| 658 | | case 0x10: PUSH(m_ip); m_ip = (WORD)tmp; CHANGE_PC; m_icount-=(ModRM >=0xc0 )?16:20; break; /* CALL */ |
| 659 | | case 0x18: tmp1 = Sreg(PS); Sreg(PS) = GetnextRMWord; PUSH(tmp1); PUSH(m_ip); m_ip = tmp; CHANGE_PC; m_icount-=(ModRM >=0xc0 )?16:26; break; /* CALL FAR */ |
| 660 | | case 0x20: m_ip = tmp; CHANGE_PC; m_icount-=13; break; /* JMP */ |
| 661 | | case 0x28: m_ip = tmp; Sreg(PS) = GetnextRMWord; CHANGE_PC; m_icount-=15; break; /* JMP FAR */ |
| 662 | | case 0x30: PUSH(tmp); m_icount-=4; break; |
| 663 | | default: logerror("%06x: FF Pre with unimplemented mod\n",PC()); |
| 664 | | } |
| 665 | | } |
| 666 | | |
| 667 | | void nec_common_device::i_invalid() |
| 668 | | { |
| 669 | | m_icount-=10; |
| 670 | | logerror("%06x: Invalid Opcode\n",PC()); |
| 671 | | } |
trunk/src/emu/cpu/nec/necinstr.inc
| r0 | r28739 | |
| 1 | #define OP(num,func_name) void nec_common_device::func_name() |
| 2 | |
| 3 | OP( 0x00, i_add_br8 ) { DEF_br8; ADDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 4 | OP( 0x01, i_add_wr16 ) { DEF_wr16; ADDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 5 | OP( 0x02, i_add_r8b ) { DEF_r8b; ADDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 6 | OP( 0x03, i_add_r16w ) { DEF_r16w; ADDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 7 | OP( 0x04, i_add_ald8 ) { DEF_ald8; ADDB; Breg(AL)=dst; CLKS(4,4,2); } |
| 8 | OP( 0x05, i_add_axd16) { DEF_axd16; ADDW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 9 | OP( 0x06, i_push_es ) { PUSH(Sreg(DS1)); CLKS(12,8,3); } |
| 10 | OP( 0x07, i_pop_es ) { POP(Sreg(DS1)); CLKS(12,8,5); } |
| 11 | |
| 12 | OP( 0x08, i_or_br8 ) { DEF_br8; ORB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 13 | OP( 0x09, i_or_wr16 ) { DEF_wr16; ORW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 14 | OP( 0x0a, i_or_r8b ) { DEF_r8b; ORB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 15 | OP( 0x0b, i_or_r16w ) { DEF_r16w; ORW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 16 | OP( 0x0c, i_or_ald8 ) { DEF_ald8; ORB; Breg(AL)=dst; CLKS(4,4,2); } |
| 17 | OP( 0x0d, i_or_axd16 ) { DEF_axd16; ORW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 18 | OP( 0x0e, i_push_cs ) { PUSH(Sreg(PS)); CLKS(12,8,3); } |
| 19 | OP( 0x0f, i_pre_nec ) { UINT32 ModRM, tmp, tmp2; |
| 20 | switch (FETCH()) { |
| 21 | case 0x10 : BITOP_BYTE; CLKS(3,3,4); tmp2 = Breg(CL) & 0x7; m_ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; m_CarryVal=m_OverVal=0; break; /* Test */ |
| 22 | case 0x11 : BITOP_WORD; CLKS(3,3,4); tmp2 = Breg(CL) & 0xf; m_ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; m_CarryVal=m_OverVal=0; break; /* Test */ |
| 23 | case 0x12 : BITOP_BYTE; CLKS(5,5,4); tmp2 = Breg(CL) & 0x7; tmp &= ~(1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Clr */ |
| 24 | case 0x13 : BITOP_WORD; CLKS(5,5,4); tmp2 = Breg(CL) & 0xf; tmp &= ~(1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Clr */ |
| 25 | case 0x14 : BITOP_BYTE; CLKS(4,4,4); tmp2 = Breg(CL) & 0x7; tmp |= (1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Set */ |
| 26 | case 0x15 : BITOP_WORD; CLKS(4,4,4); tmp2 = Breg(CL) & 0xf; tmp |= (1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Set */ |
| 27 | case 0x16 : BITOP_BYTE; CLKS(4,4,4); tmp2 = Breg(CL) & 0x7; BIT_NOT; PutbackRMByte(ModRM,tmp); break; /* Not */ |
| 28 | case 0x17 : BITOP_WORD; CLKS(4,4,4); tmp2 = Breg(CL) & 0xf; BIT_NOT; PutbackRMWord(ModRM,tmp); break; /* Not */ |
| 29 | |
| 30 | case 0x18 : BITOP_BYTE; CLKS(4,4,4); tmp2 = (FETCH()) & 0x7; m_ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; m_CarryVal=m_OverVal=0; break; /* Test */ |
| 31 | case 0x19 : BITOP_WORD; CLKS(4,4,4); tmp2 = (FETCH()) & 0xf; m_ZeroVal = (tmp & (1<<tmp2)) ? 1 : 0; m_CarryVal=m_OverVal=0; break; /* Test */ |
| 32 | case 0x1a : BITOP_BYTE; CLKS(6,6,4); tmp2 = (FETCH()) & 0x7; tmp &= ~(1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Clr */ |
| 33 | case 0x1b : BITOP_WORD; CLKS(6,6,4); tmp2 = (FETCH()) & 0xf; tmp &= ~(1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Clr */ |
| 34 | case 0x1c : BITOP_BYTE; CLKS(5,5,4); tmp2 = (FETCH()) & 0x7; tmp |= (1<<tmp2); PutbackRMByte(ModRM,tmp); break; /* Set */ |
| 35 | case 0x1d : BITOP_WORD; CLKS(5,5,4); tmp2 = (FETCH()) & 0xf; tmp |= (1<<tmp2); PutbackRMWord(ModRM,tmp); break; /* Set */ |
| 36 | case 0x1e : BITOP_BYTE; CLKS(5,5,4); tmp2 = (FETCH()) & 0x7; BIT_NOT; PutbackRMByte(ModRM,tmp); break; /* Not */ |
| 37 | case 0x1f : BITOP_WORD; CLKS(5,5,4); tmp2 = (FETCH()) & 0xf; BIT_NOT; PutbackRMWord(ModRM,tmp); break; /* Not */ |
| 38 | |
| 39 | case 0x20 : ADD4S; CLKS(7,7,2); break; |
| 40 | case 0x22 : SUB4S; CLKS(7,7,2); break; |
| 41 | case 0x26 : CMP4S; CLKS(7,7,2); break; |
| 42 | case 0x28 : ModRM = FETCH(); tmp = GetRMByte(ModRM); tmp <<= 4; tmp |= Breg(AL) & 0xf; Breg(AL) = (Breg(AL) & 0xf0) | ((tmp>>8)&0xf); tmp &= 0xff; PutbackRMByte(ModRM,tmp); CLKM(13,13,9,28,28,15); break; |
| 43 | case 0x2a : ModRM = FETCH(); tmp = GetRMByte(ModRM); tmp2 = (Breg(AL) & 0xf)<<4; Breg(AL) = (Breg(AL) & 0xf0) | (tmp&0xf); tmp = tmp2 | (tmp>>4); PutbackRMByte(ModRM,tmp); CLKM(17,17,13,32,32,19); break; |
| 44 | case 0x31 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield INS\n",PC()); break; |
| 45 | case 0x33 : ModRM = FETCH(); ModRM=0; logerror("%06x: Unimplemented bitfield EXT\n",PC()); break; |
| 46 | case 0xe0 : ModRM = FETCH(); ModRM=0; logerror("%06x: V33 unimplemented BRKXA (break to expansion address)\n",PC()); break; |
| 47 | case 0xf0 : ModRM = FETCH(); ModRM=0; logerror("%06x: V33 unimplemented RETXA (return from expansion address)\n",PC()); break; |
| 48 | case 0xff : ModRM = FETCH(); ModRM=0; logerror("%06x: unimplemented BRKEM (break to 8080 emulation mode)\n",PC()); break; |
| 49 | default: logerror("%06x: Unknown V20 instruction\n",PC()); break; |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | OP( 0x10, i_adc_br8 ) { DEF_br8; src+=CF; ADDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 54 | OP( 0x11, i_adc_wr16 ) { DEF_wr16; src+=CF; ADDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 55 | OP( 0x12, i_adc_r8b ) { DEF_r8b; src+=CF; ADDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 56 | OP( 0x13, i_adc_r16w ) { DEF_r16w; src+=CF; ADDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 57 | OP( 0x14, i_adc_ald8 ) { DEF_ald8; src+=CF; ADDB; Breg(AL)=dst; CLKS(4,4,2); } |
| 58 | OP( 0x15, i_adc_axd16) { DEF_axd16; src+=CF; ADDW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 59 | OP( 0x16, i_push_ss ) { PUSH(Sreg(SS)); CLKS(12,8,3); } |
| 60 | OP( 0x17, i_pop_ss ) { POP(Sreg(SS)); CLKS(12,8,5); m_no_interrupt=1; } |
| 61 | |
| 62 | OP( 0x18, i_sbb_br8 ) { DEF_br8; src+=CF; SUBB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 63 | OP( 0x19, i_sbb_wr16 ) { DEF_wr16; src+=CF; SUBW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 64 | OP( 0x1a, i_sbb_r8b ) { DEF_r8b; src+=CF; SUBB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 65 | OP( 0x1b, i_sbb_r16w ) { DEF_r16w; src+=CF; SUBW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 66 | OP( 0x1c, i_sbb_ald8 ) { DEF_ald8; src+=CF; SUBB; Breg(AL)=dst; CLKS(4,4,2); } |
| 67 | OP( 0x1d, i_sbb_axd16) { DEF_axd16; src+=CF; SUBW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 68 | OP( 0x1e, i_push_ds ) { PUSH(Sreg(DS0)); CLKS(12,8,3); } |
| 69 | OP( 0x1f, i_pop_ds ) { POP(Sreg(DS0)); CLKS(12,8,5); } |
| 70 | |
| 71 | OP( 0x20, i_and_br8 ) { DEF_br8; ANDB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 72 | OP( 0x21, i_and_wr16 ) { DEF_wr16; ANDW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 73 | OP( 0x22, i_and_r8b ) { DEF_r8b; ANDB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 74 | OP( 0x23, i_and_r16w ) { DEF_r16w; ANDW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 75 | OP( 0x24, i_and_ald8 ) { DEF_ald8; ANDB; Breg(AL)=dst; CLKS(4,4,2); } |
| 76 | OP( 0x25, i_and_axd16) { DEF_axd16; ANDW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 77 | OP( 0x26, i_es ) { m_seg_prefix=TRUE; m_prefix_base=Sreg(DS1)<<4; CLK(2); (this->*s_nec_instruction[fetchop()])(); m_seg_prefix=FALSE; } |
| 78 | OP( 0x27, i_daa ) { ADJ4(6,0x60); CLKS(3,3,2); } |
| 79 | |
| 80 | OP( 0x28, i_sub_br8 ) { DEF_br8; SUBB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 81 | OP( 0x29, i_sub_wr16 ) { DEF_wr16; SUBW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 82 | OP( 0x2a, i_sub_r8b ) { DEF_r8b; SUBB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 83 | OP( 0x2b, i_sub_r16w ) { DEF_r16w; SUBW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 84 | OP( 0x2c, i_sub_ald8 ) { DEF_ald8; SUBB; Breg(AL)=dst; CLKS(4,4,2); } |
| 85 | OP( 0x2d, i_sub_axd16) { DEF_axd16; SUBW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 86 | OP( 0x2e, i_cs ) { m_seg_prefix=TRUE; m_prefix_base=Sreg(PS)<<4; CLK(2); (this->*s_nec_instruction[fetchop()])(); m_seg_prefix=FALSE; } |
| 87 | OP( 0x2f, i_das ) { ADJ4(-6,-0x60); CLKS(3,3,2); } |
| 88 | |
| 89 | OP( 0x30, i_xor_br8 ) { DEF_br8; XORB; PutbackRMByte(ModRM,dst); CLKM(2,2,2,16,16,7); } |
| 90 | OP( 0x31, i_xor_wr16 ) { DEF_wr16; XORW; PutbackRMWord(ModRM,dst); CLKR(24,24,11,24,16,7,2,m_EA);} |
| 91 | OP( 0x32, i_xor_r8b ) { DEF_r8b; XORB; RegByte(ModRM)=dst; CLKM(2,2,2,11,11,6); } |
| 92 | OP( 0x33, i_xor_r16w ) { DEF_r16w; XORW; RegWord(ModRM)=dst; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 93 | OP( 0x34, i_xor_ald8 ) { DEF_ald8; XORB; Breg(AL)=dst; CLKS(4,4,2); } |
| 94 | OP( 0x35, i_xor_axd16) { DEF_axd16; XORW; Wreg(AW)=dst; CLKS(4,4,2); } |
| 95 | OP( 0x36, i_ss ) { m_seg_prefix=TRUE; m_prefix_base=Sreg(SS)<<4; CLK(2); (this->*s_nec_instruction[fetchop()])(); m_seg_prefix=FALSE; } |
| 96 | OP( 0x37, i_aaa ) { ADJB(6, (Breg(AL) > 0xf9) ? 2 : 1); CLKS(7,7,4); } |
| 97 | |
| 98 | OP( 0x38, i_cmp_br8 ) { DEF_br8; SUBB; CLKM(2,2,2,11,11,6); } |
| 99 | OP( 0x39, i_cmp_wr16 ) { DEF_wr16; SUBW; CLKR(15,15,8,15,11,6,2,m_EA);} |
| 100 | OP( 0x3a, i_cmp_r8b ) { DEF_r8b; SUBB; CLKM(2,2,2,11,11,6); } |
| 101 | OP( 0x3b, i_cmp_r16w ) { DEF_r16w; SUBW; CLKR(15,15,8,15,11,6,2,m_EA); } |
| 102 | OP( 0x3c, i_cmp_ald8 ) { DEF_ald8; SUBB; CLKS(4,4,2); } |
| 103 | OP( 0x3d, i_cmp_axd16) { DEF_axd16; SUBW; CLKS(4,4,2); } |
| 104 | OP( 0x3e, i_ds ) { m_seg_prefix=TRUE; m_prefix_base=Sreg(DS0)<<4; CLK(2); (this->*s_nec_instruction[fetchop()])(); m_seg_prefix=FALSE; } |
| 105 | OP( 0x3f, i_aas ) { ADJB(-6, (Breg(AL) < 6) ? -2 : -1); CLKS(7,7,4); } |
| 106 | |
| 107 | OP( 0x40, i_inc_ax ) { IncWordReg(AW); CLK(2); } |
| 108 | OP( 0x41, i_inc_cx ) { IncWordReg(CW); CLK(2); } |
| 109 | OP( 0x42, i_inc_dx ) { IncWordReg(DW); CLK(2); } |
| 110 | OP( 0x43, i_inc_bx ) { IncWordReg(BW); CLK(2); } |
| 111 | OP( 0x44, i_inc_sp ) { IncWordReg(SP); CLK(2); } |
| 112 | OP( 0x45, i_inc_bp ) { IncWordReg(BP); CLK(2); } |
| 113 | OP( 0x46, i_inc_si ) { IncWordReg(IX); CLK(2); } |
| 114 | OP( 0x47, i_inc_di ) { IncWordReg(IY); CLK(2); } |
| 115 | |
| 116 | OP( 0x48, i_dec_ax ) { DecWordReg(AW); CLK(2); } |
| 117 | OP( 0x49, i_dec_cx ) { DecWordReg(CW); CLK(2); } |
| 118 | OP( 0x4a, i_dec_dx ) { DecWordReg(DW); CLK(2); } |
| 119 | OP( 0x4b, i_dec_bx ) { DecWordReg(BW); CLK(2); } |
| 120 | OP( 0x4c, i_dec_sp ) { DecWordReg(SP); CLK(2); } |
| 121 | OP( 0x4d, i_dec_bp ) { DecWordReg(BP); CLK(2); } |
| 122 | OP( 0x4e, i_dec_si ) { DecWordReg(IX); CLK(2); } |
| 123 | OP( 0x4f, i_dec_di ) { DecWordReg(IY); CLK(2); } |
| 124 | |
| 125 | OP( 0x50, i_push_ax ) { PUSH(Wreg(AW)); CLKS(12,8,3); } |
| 126 | OP( 0x51, i_push_cx ) { PUSH(Wreg(CW)); CLKS(12,8,3); } |
| 127 | OP( 0x52, i_push_dx ) { PUSH(Wreg(DW)); CLKS(12,8,3); } |
| 128 | OP( 0x53, i_push_bx ) { PUSH(Wreg(BW)); CLKS(12,8,3); } |
| 129 | OP( 0x54, i_push_sp ) { PUSH(Wreg(SP)); CLKS(12,8,3); } |
| 130 | OP( 0x55, i_push_bp ) { PUSH(Wreg(BP)); CLKS(12,8,3); } |
| 131 | OP( 0x56, i_push_si ) { PUSH(Wreg(IX)); CLKS(12,8,3); } |
| 132 | OP( 0x57, i_push_di ) { PUSH(Wreg(IY)); CLKS(12,8,3); } |
| 133 | |
| 134 | OP( 0x58, i_pop_ax ) { POP(Wreg(AW)); CLKS(12,8,5); } |
| 135 | OP( 0x59, i_pop_cx ) { POP(Wreg(CW)); CLKS(12,8,5); } |
| 136 | OP( 0x5a, i_pop_dx ) { POP(Wreg(DW)); CLKS(12,8,5); } |
| 137 | OP( 0x5b, i_pop_bx ) { POP(Wreg(BW)); CLKS(12,8,5); } |
| 138 | OP( 0x5c, i_pop_sp ) { POP(Wreg(SP)); CLKS(12,8,5); } |
| 139 | OP( 0x5d, i_pop_bp ) { POP(Wreg(BP)); CLKS(12,8,5); } |
| 140 | OP( 0x5e, i_pop_si ) { POP(Wreg(IX)); CLKS(12,8,5); } |
| 141 | OP( 0x5f, i_pop_di ) { POP(Wreg(IY)); CLKS(12,8,5); } |
| 142 | |
| 143 | OP( 0x60, i_pusha ) { |
| 144 | unsigned tmp=Wreg(SP); |
| 145 | PUSH(Wreg(AW)); |
| 146 | PUSH(Wreg(CW)); |
| 147 | PUSH(Wreg(DW)); |
| 148 | PUSH(Wreg(BW)); |
| 149 | PUSH(tmp); |
| 150 | PUSH(Wreg(BP)); |
| 151 | PUSH(Wreg(IX)); |
| 152 | PUSH(Wreg(IY)); |
| 153 | CLKS(67,35,20); |
| 154 | } |
| 155 | static unsigned nec_popa_tmp; |
| 156 | OP( 0x61, i_popa ) { |
| 157 | POP(Wreg(IY)); |
| 158 | POP(Wreg(IX)); |
| 159 | POP(Wreg(BP)); |
| 160 | POP(nec_popa_tmp); |
| 161 | POP(Wreg(BW)); |
| 162 | POP(Wreg(DW)); |
| 163 | POP(Wreg(CW)); |
| 164 | POP(Wreg(AW)); |
| 165 | CLKS(75,43,22); |
| 166 | } |
| 167 | OP( 0x62, i_chkind ) { |
| 168 | UINT32 low,high,tmp; |
| 169 | GetModRM; |
| 170 | low = GetRMWord(ModRM); |
| 171 | high= GetnextRMWord; |
| 172 | tmp= RegWord(ModRM); |
| 173 | if (tmp<low || tmp>high) { |
| 174 | nec_interrupt(NEC_CHKIND_VECTOR, BRK); |
| 175 | } |
| 176 | m_icount-=20; |
| 177 | logerror("%06x: bound %04x high %04x low %04x tmp\n",PC(),high,low,tmp); |
| 178 | } |
| 179 | OP( 0x64, i_repnc ) { UINT32 next = fetchop(); UINT16 c = Wreg(CW); |
| 180 | switch(next) { /* Segments */ |
| 181 | case 0x26: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS1)<<4; next = fetchop(); CLK(2); break; |
| 182 | case 0x2e: m_seg_prefix=TRUE; m_prefix_base=Sreg(PS)<<4; next = fetchop(); CLK(2); break; |
| 183 | case 0x36: m_seg_prefix=TRUE; m_prefix_base=Sreg(SS)<<4; next = fetchop(); CLK(2); break; |
| 184 | case 0x3e: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS0)<<4; next = fetchop(); CLK(2); break; |
| 185 | } |
| 186 | |
| 187 | switch(next) { |
| 188 | case 0x6c: CLK(2); if (c) do { i_insb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 189 | case 0x6d: CLK(2); if (c) do { i_insw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 190 | case 0x6e: CLK(2); if (c) do { i_outsb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 191 | case 0x6f: CLK(2); if (c) do { i_outsw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 192 | case 0xa4: CLK(2); if (c) do { i_movsb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 193 | case 0xa5: CLK(2); if (c) do { i_movsw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 194 | case 0xa6: CLK(2); if (c) do { i_cmpsb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 195 | case 0xa7: CLK(2); if (c) do { i_cmpsw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 196 | case 0xaa: CLK(2); if (c) do { i_stosb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 197 | case 0xab: CLK(2); if (c) do { i_stosw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 198 | case 0xac: CLK(2); if (c) do { i_lodsb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 199 | case 0xad: CLK(2); if (c) do { i_lodsw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 200 | case 0xae: CLK(2); if (c) do { i_scasb(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 201 | case 0xaf: CLK(2); if (c) do { i_scasw(); c--; } while (c>0 && !CF); Wreg(CW)=c; break; |
| 202 | default: logerror("%06x: REPNC invalid\n",PC()); (this->*s_nec_instruction[next])(); |
| 203 | } |
| 204 | m_seg_prefix=FALSE; |
| 205 | } |
| 206 | |
| 207 | OP( 0x65, i_repc ) { UINT32 next = fetchop(); UINT16 c = Wreg(CW); |
| 208 | switch(next) { /* Segments */ |
| 209 | case 0x26: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS1)<<4; next = fetchop(); CLK(2); break; |
| 210 | case 0x2e: m_seg_prefix=TRUE; m_prefix_base=Sreg(PS)<<4; next = fetchop(); CLK(2); break; |
| 211 | case 0x36: m_seg_prefix=TRUE; m_prefix_base=Sreg(SS)<<4; next = fetchop(); CLK(2); break; |
| 212 | case 0x3e: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS0)<<4; next = fetchop(); CLK(2); break; |
| 213 | } |
| 214 | |
| 215 | switch(next) { |
| 216 | case 0x6c: CLK(2); if (c) do { i_insb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 217 | case 0x6d: CLK(2); if (c) do { i_insw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 218 | case 0x6e: CLK(2); if (c) do { i_outsb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 219 | case 0x6f: CLK(2); if (c) do { i_outsw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 220 | case 0xa4: CLK(2); if (c) do { i_movsb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 221 | case 0xa5: CLK(2); if (c) do { i_movsw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 222 | case 0xa6: CLK(2); if (c) do { i_cmpsb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 223 | case 0xa7: CLK(2); if (c) do { i_cmpsw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 224 | case 0xaa: CLK(2); if (c) do { i_stosb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 225 | case 0xab: CLK(2); if (c) do { i_stosw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 226 | case 0xac: CLK(2); if (c) do { i_lodsb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 227 | case 0xad: CLK(2); if (c) do { i_lodsw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 228 | case 0xae: CLK(2); if (c) do { i_scasb(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 229 | case 0xaf: CLK(2); if (c) do { i_scasw(); c--; } while (c>0 && CF); Wreg(CW)=c; break; |
| 230 | default: logerror("%06x: REPC invalid\n",PC()); (this->*s_nec_instruction[next])(); |
| 231 | } |
| 232 | m_seg_prefix=FALSE; |
| 233 | } |
| 234 | |
| 235 | OP( 0x68, i_push_d16 ) { UINT32 tmp; tmp = FETCHWORD(); PUSH(tmp); CLKW(12,12,5,12,8,5,Wreg(SP)); } |
| 236 | OP( 0x69, i_imul_d16 ) { UINT32 tmp; DEF_r16w; tmp = FETCHWORD(); dst = (INT32)((INT16)src)*(INT32)((INT16)tmp); m_CarryVal = m_OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; m_icount-=(ModRM >=0xc0 )?38:47;} |
| 237 | OP( 0x6a, i_push_d8 ) { UINT32 tmp = (WORD)((INT16)((INT8)FETCH())); PUSH(tmp); CLKW(11,11,5,11,7,3,Wreg(SP)); } |
| 238 | OP( 0x6b, i_imul_d8 ) { UINT32 src2; DEF_r16w; src2= (WORD)((INT16)((INT8)FETCH())); dst = (INT32)((INT16)src)*(INT32)((INT16)src2); m_CarryVal = m_OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1); RegWord(ModRM)=(WORD)dst; m_icount-=(ModRM >=0xc0 )?31:39; } |
| 239 | OP( 0x6c, i_insb ) { PutMemB(DS1,Wreg(IY),read_port_byte(Wreg(DW))); Wreg(IY)+= -2 * m_DF + 1; CLK(8); } |
| 240 | OP( 0x6d, i_insw ) { PutMemW(DS1,Wreg(IY),read_port_word(Wreg(DW))); Wreg(IY)+= -4 * m_DF + 2; CLKS(18,10,8); } |
| 241 | OP( 0x6e, i_outsb ) { write_port_byte(Wreg(DW),GetMemB(DS0,Wreg(IX))); Wreg(IX)+= -2 * m_DF + 1; CLK(8); } |
| 242 | OP( 0x6f, i_outsw ) { write_port_word(Wreg(DW),GetMemW(DS0,Wreg(IX))); Wreg(IX)+= -4 * m_DF + 2; CLKS(18,10,8); } |
| 243 | |
| 244 | OP( 0x70, i_jo ) { JMP( OF); CLKS(4,4,3); } |
| 245 | OP( 0x71, i_jno ) { JMP(!OF); CLKS(4,4,3); } |
| 246 | OP( 0x72, i_jc ) { JMP( CF); CLKS(4,4,3); } |
| 247 | OP( 0x73, i_jnc ) { JMP(!CF); CLKS(4,4,3); } |
| 248 | OP( 0x74, i_jz ) { JMP( ZF); CLKS(4,4,3); } |
| 249 | OP( 0x75, i_jnz ) { JMP(!ZF); CLKS(4,4,3); } |
| 250 | OP( 0x76, i_jce ) { JMP(CF || ZF); CLKS(4,4,3); } |
| 251 | OP( 0x77, i_jnce ) { JMP(!(CF || ZF)); CLKS(4,4,3); } |
| 252 | OP( 0x78, i_js ) { JMP( SF); CLKS(4,4,3); } |
| 253 | OP( 0x79, i_jns ) { JMP(!SF); CLKS(4,4,3); } |
| 254 | OP( 0x7a, i_jp ) { JMP( PF); CLKS(4,4,3); } |
| 255 | OP( 0x7b, i_jnp ) { JMP(!PF); CLKS(4,4,3); } |
| 256 | OP( 0x7c, i_jl ) { JMP((SF!=OF)&&(!ZF)); CLKS(4,4,3); } |
| 257 | OP( 0x7d, i_jnl ) { JMP((ZF)||(SF==OF)); CLKS(4,4,3); } |
| 258 | OP( 0x7e, i_jle ) { JMP((ZF)||(SF!=OF)); CLKS(4,4,3); } |
| 259 | OP( 0x7f, i_jnle ) { JMP((SF==OF)&&(!ZF)); CLKS(4,4,3); } |
| 260 | |
| 261 | OP( 0x80, i_80pre ) { UINT32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = FETCH(); |
| 262 | if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKS(13,13,6) else CLKS(18,18,7) |
| 263 | switch (ModRM & 0x38) { |
| 264 | case 0x00: ADDB; PutbackRMByte(ModRM,dst); break; |
| 265 | case 0x08: ORB; PutbackRMByte(ModRM,dst); break; |
| 266 | case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break; |
| 267 | case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break; |
| 268 | case 0x20: ANDB; PutbackRMByte(ModRM,dst); break; |
| 269 | case 0x28: SUBB; PutbackRMByte(ModRM,dst); break; |
| 270 | case 0x30: XORB; PutbackRMByte(ModRM,dst); break; |
| 271 | case 0x38: SUBB; break; /* CMP */ |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | OP( 0x81, i_81pre ) { UINT32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = FETCH(); src+= (FETCH() << 8); |
| 276 | if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKW(17,17,8,17,13,6,m_EA) else CLKW(26,26,11,26,18,7,m_EA) |
| 277 | switch (ModRM & 0x38) { |
| 278 | case 0x00: ADDW; PutbackRMWord(ModRM,dst); break; |
| 279 | case 0x08: ORW; PutbackRMWord(ModRM,dst); break; |
| 280 | case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break; |
| 281 | case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break; |
| 282 | case 0x20: ANDW; PutbackRMWord(ModRM,dst); break; |
| 283 | case 0x28: SUBW; PutbackRMWord(ModRM,dst); break; |
| 284 | case 0x30: XORW; PutbackRMWord(ModRM,dst); break; |
| 285 | case 0x38: SUBW; break; /* CMP */ |
| 286 | } |
| 287 | } |
| 288 | |
| 289 | OP( 0x82, i_82pre ) { UINT32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = (BYTE)((INT8)FETCH()); |
| 290 | if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKS(13,13,6) else CLKS(18,18,7) |
| 291 | switch (ModRM & 0x38) { |
| 292 | case 0x00: ADDB; PutbackRMByte(ModRM,dst); break; |
| 293 | case 0x08: ORB; PutbackRMByte(ModRM,dst); break; |
| 294 | case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break; |
| 295 | case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break; |
| 296 | case 0x20: ANDB; PutbackRMByte(ModRM,dst); break; |
| 297 | case 0x28: SUBB; PutbackRMByte(ModRM,dst); break; |
| 298 | case 0x30: XORB; PutbackRMByte(ModRM,dst); break; |
| 299 | case 0x38: SUBB; break; /* CMP */ |
| 300 | } |
| 301 | } |
| 302 | |
| 303 | OP( 0x83, i_83pre ) { UINT32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = (WORD)((INT16)((INT8)FETCH())); |
| 304 | if (ModRM >=0xc0 ) CLKS(4,4,2) else if ((ModRM & 0x38)==0x38) CLKW(17,17,8,17,13,6,m_EA) else CLKW(26,26,11,26,18,7,m_EA) |
| 305 | switch (ModRM & 0x38) { |
| 306 | case 0x00: ADDW; PutbackRMWord(ModRM,dst); break; |
| 307 | case 0x08: ORW; PutbackRMWord(ModRM,dst); break; |
| 308 | case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break; |
| 309 | case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break; |
| 310 | case 0x20: ANDW; PutbackRMWord(ModRM,dst); break; |
| 311 | case 0x28: SUBW; PutbackRMWord(ModRM,dst); break; |
| 312 | case 0x30: XORW; PutbackRMWord(ModRM,dst); break; |
| 313 | case 0x38: SUBW; break; /* CMP */ |
| 314 | } |
| 315 | } |
| 316 | |
| 317 | OP( 0x84, i_test_br8 ) { DEF_br8; ANDB; CLKM(2,2,2,10,10,6); } |
| 318 | OP( 0x85, i_test_wr16 ) { DEF_wr16; ANDW; CLKR(14,14,8,14,10,6,2,m_EA); } |
| 319 | OP( 0x86, i_xchg_br8 ) { DEF_br8; RegByte(ModRM)=dst; PutbackRMByte(ModRM,src); CLKM(3,3,3,16,18,8); } |
| 320 | OP( 0x87, i_xchg_wr16 ) { DEF_wr16; RegWord(ModRM)=dst; PutbackRMWord(ModRM,src); CLKR(24,24,12,24,16,8,3,m_EA); } |
| 321 | |
| 322 | OP( 0x88, i_mov_br8 ) { UINT8 src; GetModRM; src = RegByte(ModRM); PutRMByte(ModRM,src); CLKM(2,2,2,9,9,3); } |
| 323 | OP( 0x89, i_mov_wr16 ) { UINT16 src; GetModRM; src = RegWord(ModRM); PutRMWord(ModRM,src); CLKR(13,13,5,13,9,3,2,m_EA); } |
| 324 | OP( 0x8a, i_mov_r8b ) { UINT8 src; GetModRM; src = GetRMByte(ModRM); RegByte(ModRM)=src; CLKM(2,2,2,11,11,5); } |
| 325 | OP( 0x8b, i_mov_r16w ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); RegWord(ModRM)=src; CLKR(15,15,7,15,11,5,2,m_EA); } |
| 326 | OP( 0x8c, i_mov_wsreg ) { GetModRM; |
| 327 | switch (ModRM & 0x38) { |
| 328 | case 0x00: PutRMWord(ModRM,Sreg(DS1)); CLKR(14,14,5,14,10,3,2,m_EA); break; |
| 329 | case 0x08: PutRMWord(ModRM,Sreg(PS)); CLKR(14,14,5,14,10,3,2,m_EA); break; |
| 330 | case 0x10: PutRMWord(ModRM,Sreg(SS)); CLKR(14,14,5,14,10,3,2,m_EA); break; |
| 331 | case 0x18: PutRMWord(ModRM,Sreg(DS0)); CLKR(14,14,5,14,10,3,2,m_EA); break; |
| 332 | default: logerror("%06x: MOV Sreg - Invalid register\n",PC()); |
| 333 | } |
| 334 | } |
| 335 | OP( 0x8d, i_lea ) { UINT16 ModRM = FETCH(); (void)(this->*s_GetEA[ModRM])(); RegWord(ModRM)=m_EO; CLKS(4,4,2); } |
| 336 | OP( 0x8e, i_mov_sregw ) { UINT16 src; GetModRM; src = GetRMWord(ModRM); CLKR(15,15,7,15,11,5,2,m_EA); |
| 337 | switch (ModRM & 0x38) { |
| 338 | case 0x00: Sreg(DS1) = src; break; /* mov es,ew */ |
| 339 | case 0x08: Sreg(PS) = src; break; /* mov cs,ew */ |
| 340 | case 0x10: Sreg(SS) = src; break; /* mov ss,ew */ |
| 341 | case 0x18: Sreg(DS0) = src; break; /* mov ds,ew */ |
| 342 | default: logerror("%06x: MOV Sreg - Invalid register\n",PC()); |
| 343 | } |
| 344 | m_no_interrupt=1; |
| 345 | } |
| 346 | OP( 0x8f, i_popw ) { UINT16 tmp; GetModRM; POP(tmp); PutRMWord(ModRM,tmp); m_icount-=21; } |
| 347 | OP( 0x90, i_nop ) { CLK(3); /* { if (m_MF == 0) printf("90 -> %06x: \n",PC()); } */ } |
| 348 | OP( 0x91, i_xchg_axcx ) { XchgAWReg(CW); CLK(3); } |
| 349 | OP( 0x92, i_xchg_axdx ) { XchgAWReg(DW); CLK(3); } |
| 350 | OP( 0x93, i_xchg_axbx ) { XchgAWReg(BW); CLK(3); } |
| 351 | OP( 0x94, i_xchg_axsp ) { XchgAWReg(SP); CLK(3); } |
| 352 | OP( 0x95, i_xchg_axbp ) { XchgAWReg(BP); CLK(3); } |
| 353 | OP( 0x96, i_xchg_axsi ) { XchgAWReg(IX); CLK(3); } |
| 354 | OP( 0x97, i_xchg_axdi ) { XchgAWReg(IY); CLK(3); } |
| 355 | |
| 356 | OP( 0x98, i_cbw ) { Breg(AH) = (Breg(AL) & 0x80) ? 0xff : 0; CLK(2); } |
| 357 | OP( 0x99, i_cwd ) { Wreg(DW) = (Breg(AH) & 0x80) ? 0xffff : 0; CLK(4); } |
| 358 | OP( 0x9a, i_call_far ) { UINT32 tmp, tmp2; tmp = FETCHWORD(); tmp2 = FETCHWORD(); PUSH(Sreg(PS)); PUSH(m_ip); m_ip = (WORD)tmp; Sreg(PS) = (WORD)tmp2; CHANGE_PC; CLKW(29,29,13,29,21,9,Wreg(SP)); } |
| 359 | OP( 0x9b, i_wait ) { if (!m_poll_state) m_ip--; CLK(5); } |
| 360 | OP( 0x9c, i_pushf ) { UINT16 tmp = CompressFlags(); PUSH( tmp ); CLKS(12,8,3); } |
| 361 | OP( 0x9d, i_popf ) { UINT32 tmp; POP(tmp); ExpandFlags(tmp); CLKS(12,8,5); if (m_TF) nec_trap(); } |
| 362 | OP( 0x9e, i_sahf ) { UINT32 tmp = (CompressFlags() & 0xff00) | (Breg(AH) & 0xd5); ExpandFlags(tmp); CLKS(3,3,2); } |
| 363 | OP( 0x9f, i_lahf ) { Breg(AH) = CompressFlags() & 0xff; CLKS(3,3,2); } |
| 364 | |
| 365 | OP( 0xa0, i_mov_aldisp ) { UINT32 addr; addr = FETCHWORD(); Breg(AL) = GetMemB(DS0, addr); CLKS(10,10,5); } |
| 366 | OP( 0xa1, i_mov_axdisp ) { UINT32 addr; addr = FETCHWORD(); Wreg(AW) = GetMemW(DS0, addr); CLKW(14,14,7,14,10,5,addr); } |
| 367 | OP( 0xa2, i_mov_dispal ) { UINT32 addr; addr = FETCHWORD(); PutMemB(DS0, addr, Breg(AL)); CLKS(9,9,3); } |
| 368 | OP( 0xa3, i_mov_dispax ) { UINT32 addr; addr = FETCHWORD(); PutMemW(DS0, addr, Wreg(AW)); CLKW(13,13,5,13,9,3,addr); } |
| 369 | OP( 0xa4, i_movsb ) { UINT32 tmp = GetMemB(DS0,Wreg(IX)); PutMemB(DS1,Wreg(IY), tmp); Wreg(IY) += -2 * m_DF + 1; Wreg(IX) += -2 * m_DF + 1; CLKS(8,8,6); } |
| 370 | OP( 0xa5, i_movsw ) { UINT32 tmp = GetMemW(DS0,Wreg(IX)); PutMemW(DS1,Wreg(IY), tmp); Wreg(IY) += -4 * m_DF + 2; Wreg(IX) += -4 * m_DF + 2; CLKS(16,16,10); } |
| 371 | OP( 0xa6, i_cmpsb ) { UINT32 src = GetMemB(DS1, Wreg(IY)); UINT32 dst = GetMemB(DS0, Wreg(IX)); SUBB; Wreg(IY) += -2 * m_DF + 1; Wreg(IX) += -2 * m_DF + 1; CLKS(14,14,14); } |
| 372 | OP( 0xa7, i_cmpsw ) { UINT32 src = GetMemW(DS1, Wreg(IY)); UINT32 dst = GetMemW(DS0, Wreg(IX)); SUBW; Wreg(IY) += -4 * m_DF + 2; Wreg(IX) += -4 * m_DF + 2; CLKS(14,14,14); } |
| 373 | |
| 374 | OP( 0xa8, i_test_ald8 ) { DEF_ald8; ANDB; CLKS(4,4,2); } |
| 375 | OP( 0xa9, i_test_axd16 ) { DEF_axd16; ANDW; CLKS(4,4,2); } |
| 376 | OP( 0xaa, i_stosb ) { PutMemB(DS1,Wreg(IY),Breg(AL)); Wreg(IY) += -2 * m_DF + 1; CLKS(4,4,3); } |
| 377 | OP( 0xab, i_stosw ) { PutMemW(DS1,Wreg(IY),Wreg(AW)); Wreg(IY) += -4 * m_DF + 2; CLKW(8,8,5,8,4,3,Wreg(IY)); } |
| 378 | OP( 0xac, i_lodsb ) { Breg(AL) = GetMemB(DS0,Wreg(IX)); Wreg(IX) += -2 * m_DF + 1; CLKS(4,4,3); } |
| 379 | OP( 0xad, i_lodsw ) { Wreg(AW) = GetMemW(DS0,Wreg(IX)); Wreg(IX) += -4 * m_DF + 2; CLKW(8,8,5,8,4,3,Wreg(IX)); } |
| 380 | OP( 0xae, i_scasb ) { UINT32 src = GetMemB(DS1, Wreg(IY)); UINT32 dst = Breg(AL); SUBB; Wreg(IY) += -2 * m_DF + 1; CLKS(4,4,3); } |
| 381 | OP( 0xaf, i_scasw ) { UINT32 src = GetMemW(DS1, Wreg(IY)); UINT32 dst = Wreg(AW); SUBW; Wreg(IY) += -4 * m_DF + 2; CLKW(8,8,5,8,4,3,Wreg(IY)); } |
| 382 | |
| 383 | OP( 0xb0, i_mov_ald8 ) { Breg(AL) = FETCH(); CLKS(4,4,2); } |
| 384 | OP( 0xb1, i_mov_cld8 ) { Breg(CL) = FETCH(); CLKS(4,4,2); } |
| 385 | OP( 0xb2, i_mov_dld8 ) { Breg(DL) = FETCH(); CLKS(4,4,2); } |
| 386 | OP( 0xb3, i_mov_bld8 ) { Breg(BL) = FETCH(); CLKS(4,4,2); } |
| 387 | OP( 0xb4, i_mov_ahd8 ) { Breg(AH) = FETCH(); CLKS(4,4,2); } |
| 388 | OP( 0xb5, i_mov_chd8 ) { Breg(CH) = FETCH(); CLKS(4,4,2); } |
| 389 | OP( 0xb6, i_mov_dhd8 ) { Breg(DH) = FETCH(); CLKS(4,4,2); } |
| 390 | OP( 0xb7, i_mov_bhd8 ) { Breg(BH) = FETCH(); CLKS(4,4,2); } |
| 391 | |
| 392 | OP( 0xb8, i_mov_axd16 ) { Breg(AL) = FETCH(); Breg(AH) = FETCH(); CLKS(4,4,2); } |
| 393 | OP( 0xb9, i_mov_cxd16 ) { Breg(CL) = FETCH(); Breg(CH) = FETCH(); CLKS(4,4,2); } |
| 394 | OP( 0xba, i_mov_dxd16 ) { Breg(DL) = FETCH(); Breg(DH) = FETCH(); CLKS(4,4,2); } |
| 395 | OP( 0xbb, i_mov_bxd16 ) { Breg(BL) = FETCH(); Breg(BH) = FETCH(); CLKS(4,4,2); } |
| 396 | OP( 0xbc, i_mov_spd16 ) { Wreg(SP) = FETCHWORD(); CLKS(4,4,2); } |
| 397 | OP( 0xbd, i_mov_bpd16 ) { Wreg(BP) = FETCHWORD(); CLKS(4,4,2); } |
| 398 | OP( 0xbe, i_mov_sid16 ) { Wreg(IX) = FETCHWORD(); CLKS(4,4,2); } |
| 399 | OP( 0xbf, i_mov_did16 ) { Wreg(IY) = FETCHWORD(); CLKS(4,4,2); } |
| 400 | |
| 401 | OP( 0xc0, i_rotshft_bd8 ) { |
| 402 | UINT32 src, dst; UINT8 c; |
| 403 | GetModRM; src = (unsigned)GetRMByte(ModRM); dst=src; |
| 404 | c=FETCH(); |
| 405 | CLKM(7,7,2,19,19,6); |
| 406 | if (c) switch (ModRM & 0x38) { |
| 407 | case 0x00: do { ROL_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 408 | case 0x08: do { ROR_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 409 | case 0x10: do { ROLC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 410 | case 0x18: do { RORC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 411 | case 0x20: SHL_BYTE(c); break; |
| 412 | case 0x28: SHR_BYTE(c); break; |
| 413 | case 0x30: logerror("%06x: Undefined opcode 0xc0 0x30 (SHLA)\n",PC()); break; |
| 414 | case 0x38: SHRA_BYTE(c); break; |
| 415 | } |
| 416 | } |
| 417 | |
| 418 | OP( 0xc1, i_rotshft_wd8 ) { |
| 419 | UINT32 src, dst; UINT8 c; |
| 420 | GetModRM; src = (unsigned)GetRMWord(ModRM); dst=src; |
| 421 | c=FETCH(); |
| 422 | CLKM(7,7,2,27,19,6); |
| 423 | if (c) switch (ModRM & 0x38) { |
| 424 | case 0x00: do { ROL_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 425 | case 0x08: do { ROR_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 426 | case 0x10: do { ROLC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 427 | case 0x18: do { RORC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 428 | case 0x20: SHL_WORD(c); break; |
| 429 | case 0x28: SHR_WORD(c); break; |
| 430 | case 0x30: logerror("%06x: Undefined opcode 0xc1 0x30 (SHLA)\n",PC()); break; |
| 431 | case 0x38: SHRA_WORD(c); break; |
| 432 | } |
| 433 | } |
| 434 | |
| 435 | OP( 0xc2, i_ret_d16 ) { UINT32 count = FETCH(); count += FETCH() << 8; POP(m_ip); Wreg(SP)+=count; CHANGE_PC; CLKS(24,24,10); } |
| 436 | OP( 0xc3, i_ret ) { POP(m_ip); CHANGE_PC; CLKS(19,19,10); } |
| 437 | OP( 0xc4, i_les_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; Sreg(DS1) = GetnextRMWord; CLKW(26,26,14,26,18,10,m_EA); } |
| 438 | OP( 0xc5, i_lds_dw ) { GetModRM; WORD tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; Sreg(DS0) = GetnextRMWord; CLKW(26,26,14,26,18,10,m_EA); } |
| 439 | OP( 0xc6, i_mov_bd8 ) { GetModRM; PutImmRMByte(ModRM); m_icount-=(ModRM >=0xc0 )?4:11; } |
| 440 | OP( 0xc7, i_mov_wd16 ) { GetModRM; PutImmRMWord(ModRM); m_icount-=(ModRM >=0xc0 )?4:15; } |
| 441 | |
| 442 | OP( 0xc8, i_enter ) { |
| 443 | UINT32 nb = FETCH(); |
| 444 | UINT32 i,level; |
| 445 | |
| 446 | m_icount-=23; |
| 447 | nb += FETCH() << 8; |
| 448 | level = FETCH(); |
| 449 | PUSH(Wreg(BP)); |
| 450 | Wreg(BP)=Wreg(SP); |
| 451 | Wreg(SP) -= nb; |
| 452 | for (i=1;i<level;i++) { |
| 453 | PUSH(GetMemW(SS,Wreg(BP)-i*2)); |
| 454 | m_icount-=16; |
| 455 | } |
| 456 | if (level) PUSH(Wreg(BP)); |
| 457 | } |
| 458 | OP( 0xc9, i_leave ) { |
| 459 | Wreg(SP)=Wreg(BP); |
| 460 | POP(Wreg(BP)); |
| 461 | m_icount-=8; |
| 462 | } |
| 463 | OP( 0xca, i_retf_d16 ) { UINT32 count = FETCH(); count += FETCH() << 8; POP(m_ip); POP(Sreg(PS)); Wreg(SP)+=count; CHANGE_PC; CLKS(32,32,16); } |
| 464 | OP( 0xcb, i_retf ) { POP(m_ip); POP(Sreg(PS)); CHANGE_PC; CLKS(29,29,16); } |
| 465 | OP( 0xcc, i_int3 ) { nec_interrupt(3, BRK); CLKS(50,50,24); } |
| 466 | OP( 0xcd, i_int ) { nec_interrupt(FETCH(), BRK); CLKS(50,50,24); } |
| 467 | OP( 0xce, i_into ) { if (OF) { nec_interrupt(NEC_BRKV_VECTOR, BRK); CLKS(52,52,26); } else CLK(3); } |
| 468 | OP( 0xcf, i_iret ) { POP(m_ip); POP(Sreg(PS)); i_popf(); CHANGE_PC; CLKS(39,39,19); } |
| 469 | |
| 470 | OP( 0xd0, i_rotshft_b ) { |
| 471 | UINT32 src, dst; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src; |
| 472 | CLKM(6,6,2,16,16,7); |
| 473 | switch (ModRM & 0x38) { |
| 474 | case 0x00: ROL_BYTE; PutbackRMByte(ModRM,(BYTE)dst); m_OverVal = (src^dst)&0x80; break; |
| 475 | case 0x08: ROR_BYTE; PutbackRMByte(ModRM,(BYTE)dst); m_OverVal = (src^dst)&0x80; break; |
| 476 | case 0x10: ROLC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); m_OverVal = (src^dst)&0x80; break; |
| 477 | case 0x18: RORC_BYTE; PutbackRMByte(ModRM,(BYTE)dst); m_OverVal = (src^dst)&0x80; break; |
| 478 | case 0x20: SHL_BYTE(1); m_OverVal = (src^dst)&0x80; break; |
| 479 | case 0x28: SHR_BYTE(1); m_OverVal = (src^dst)&0x80; break; |
| 480 | case 0x30: logerror("%06x: Undefined opcode 0xd0 0x30 (SHLA)\n",PC()); break; |
| 481 | case 0x38: SHRA_BYTE(1); m_OverVal = 0; break; |
| 482 | } |
| 483 | } |
| 484 | |
| 485 | OP( 0xd1, i_rotshft_w ) { |
| 486 | UINT32 src, dst; GetModRM; src = (UINT32)GetRMWord(ModRM); dst=src; |
| 487 | CLKM(6,6,2,24,16,7); |
| 488 | switch (ModRM & 0x38) { |
| 489 | case 0x00: ROL_WORD; PutbackRMWord(ModRM,(WORD)dst); m_OverVal = (src^dst)&0x8000; break; |
| 490 | case 0x08: ROR_WORD; PutbackRMWord(ModRM,(WORD)dst); m_OverVal = (src^dst)&0x8000; break; |
| 491 | case 0x10: ROLC_WORD; PutbackRMWord(ModRM,(WORD)dst); m_OverVal = (src^dst)&0x8000; break; |
| 492 | case 0x18: RORC_WORD; PutbackRMWord(ModRM,(WORD)dst); m_OverVal = (src^dst)&0x8000; break; |
| 493 | case 0x20: SHL_WORD(1); m_OverVal = (src^dst)&0x8000; break; |
| 494 | case 0x28: SHR_WORD(1); m_OverVal = (src^dst)&0x8000; break; |
| 495 | case 0x30: logerror("%06x: Undefined opcode 0xd1 0x30 (SHLA)\n",PC()); break; |
| 496 | case 0x38: SHRA_WORD(1); m_OverVal = 0; break; |
| 497 | } |
| 498 | } |
| 499 | |
| 500 | OP( 0xd2, i_rotshft_bcl ) { |
| 501 | UINT32 src, dst; UINT8 c; GetModRM; src = (UINT32)GetRMByte(ModRM); dst=src; |
| 502 | c=Breg(CL); |
| 503 | CLKM(7,7,2,19,19,6); |
| 504 | if (c) switch (ModRM & 0x38) { |
| 505 | case 0x00: do { ROL_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 506 | case 0x08: do { ROR_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 507 | case 0x10: do { ROLC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 508 | case 0x18: do { RORC_BYTE; c--; CLK(1); } while (c>0); PutbackRMByte(ModRM,(BYTE)dst); break; |
| 509 | case 0x20: SHL_BYTE(c); break; |
| 510 | case 0x28: SHR_BYTE(c); break; |
| 511 | case 0x30: logerror("%06x: Undefined opcode 0xd2 0x30 (SHLA)\n",PC()); break; |
| 512 | case 0x38: SHRA_BYTE(c); break; |
| 513 | } |
| 514 | } |
| 515 | |
| 516 | OP( 0xd3, i_rotshft_wcl ) { |
| 517 | UINT32 src, dst; UINT8 c; GetModRM; src = (UINT32)GetRMWord(ModRM); dst=src; |
| 518 | c=Breg(CL); |
| 519 | CLKM(7,7,2,27,19,6); |
| 520 | if (c) switch (ModRM & 0x38) { |
| 521 | case 0x00: do { ROL_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 522 | case 0x08: do { ROR_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 523 | case 0x10: do { ROLC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 524 | case 0x18: do { RORC_WORD; c--; CLK(1); } while (c>0); PutbackRMWord(ModRM,(WORD)dst); break; |
| 525 | case 0x20: SHL_WORD(c); break; |
| 526 | case 0x28: SHR_WORD(c); break; |
| 527 | case 0x30: logerror("%06x: Undefined opcode 0xd3 0x30 (SHLA)\n",PC()); break; |
| 528 | case 0x38: SHRA_WORD(c); break; |
| 529 | } |
| 530 | } |
| 531 | |
| 532 | OP( 0xd4, i_aam ) { FETCH(); Breg(AH) = Breg(AL) / 10; Breg(AL) %= 10; SetSZPF_Word(Wreg(AW)); CLKS(15,15,12); } |
| 533 | OP( 0xd5, i_aad ) { FETCH(); Breg(AL) = Breg(AH) * 10 + Breg(AL); Breg(AH) = 0; SetSZPF_Byte(Breg(AL)); CLKS(7,7,8); } |
| 534 | OP( 0xd6, i_setalc ) { Breg(AL) = (CF)?0xff:0x00; m_icount-=3; logerror("%06x: Undefined opcode (SETALC)\n",PC()); } |
| 535 | OP( 0xd7, i_trans ) { UINT32 dest = (Wreg(BW)+Breg(AL))&0xffff; Breg(AL) = GetMemB(DS0, dest); CLKS(9,9,5); } |
| 536 | OP( 0xd8, i_fpo ) { GetModRM; m_icount-=2; logerror("%06x: Unimplemented floating point control %04x\n",PC(),ModRM); } |
| 537 | |
| 538 | OP( 0xe0, i_loopne ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if (!ZF && Wreg(CW)) { m_ip = (WORD)(m_ip+disp); /*CHANGE_PC;*/ CLKS(14,14,6); } else CLKS(5,5,3); } |
| 539 | OP( 0xe1, i_loope ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if ( ZF && Wreg(CW)) { m_ip = (WORD)(m_ip+disp); /*CHANGE_PC;*/ CLKS(14,14,6); } else CLKS(5,5,3); } |
| 540 | OP( 0xe2, i_loop ) { INT8 disp = (INT8)FETCH(); Wreg(CW)--; if (Wreg(CW)) { m_ip = (WORD)(m_ip+disp); /*CHANGE_PC;*/ CLKS(13,13,6); } else CLKS(5,5,3); } |
| 541 | OP( 0xe3, i_jcxz ) { INT8 disp = (INT8)FETCH(); if (Wreg(CW) == 0) { m_ip = (WORD)(m_ip+disp); /*CHANGE_PC;*/ CLKS(13,13,6); } else CLKS(5,5,3); } |
| 542 | OP( 0xe4, i_inal ) { UINT8 port = FETCH(); Breg(AL) = read_port_byte(port); CLKS(9,9,5); } |
| 543 | OP( 0xe5, i_inax ) { UINT8 port = FETCH(); Wreg(AW) = read_port_word(port); CLKW(13,13,7,13,9,5,port); } |
| 544 | OP( 0xe6, i_outal ) { UINT8 port = FETCH(); write_port_byte(port, Breg(AL)); CLKS(8,8,3); } |
| 545 | OP( 0xe7, i_outax ) { UINT8 port = FETCH(); write_port_word(port, Wreg(AW)); CLKW(12,12,5,12,8,3,port); } |
| 546 | |
| 547 | OP( 0xe8, i_call_d16 ) { UINT32 tmp; tmp = FETCHWORD(); PUSH(m_ip); m_ip = (WORD)(m_ip+(INT16)tmp); CHANGE_PC; m_icount-=24; } |
| 548 | OP( 0xe9, i_jmp_d16 ) { UINT32 tmp; tmp = FETCHWORD(); m_ip = (WORD)(m_ip+(INT16)tmp); CHANGE_PC; m_icount-=15; } |
| 549 | OP( 0xea, i_jmp_far ) { UINT32 tmp,tmp1; tmp = FETCHWORD(); tmp1 = FETCHWORD(); Sreg(PS) = (WORD)tmp1; m_ip = (WORD)tmp; CHANGE_PC; m_icount-=27; } |
| 550 | OP( 0xeb, i_jmp_d8 ) { int tmp = (int)((INT8)FETCH()); m_icount-=12; m_ip = (WORD)(m_ip+tmp); } |
| 551 | OP( 0xec, i_inaldx ) { Breg(AL) = read_port_byte(Wreg(DW)); CLKS(8,8,5);} |
| 552 | OP( 0xed, i_inaxdx ) { Wreg(AW) = read_port_word(Wreg(DW)); CLKW(12,12,7,12,8,5,Wreg(DW)); } |
| 553 | OP( 0xee, i_outdxal ) { write_port_byte(Wreg(DW), Breg(AL)); CLKS(8,8,3); } |
| 554 | OP( 0xef, i_outdxax ) { write_port_word(Wreg(DW), Wreg(AW)); CLKW(12,12,5,12,8,3,Wreg(DW)); } |
| 555 | |
| 556 | OP( 0xf0, i_lock ) { logerror("%06x: Warning - BUSLOCK\n",PC()); m_no_interrupt=1; CLK(2); } |
| 557 | OP( 0xf2, i_repne ) { UINT32 next = fetchop(); UINT16 c = Wreg(CW); |
| 558 | switch(next) { /* Segments */ |
| 559 | case 0x26: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS1)<<4; next = fetchop(); CLK(2); break; |
| 560 | case 0x2e: m_seg_prefix=TRUE; m_prefix_base=Sreg(PS)<<4; next = fetchop(); CLK(2); break; |
| 561 | case 0x36: m_seg_prefix=TRUE; m_prefix_base=Sreg(SS)<<4; next = fetchop(); CLK(2); break; |
| 562 | case 0x3e: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS0)<<4; next = fetchop(); CLK(2); break; |
| 563 | } |
| 564 | |
| 565 | switch(next) { |
| 566 | case 0x6c: CLK(2); if (c) do { i_insb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 567 | case 0x6d: CLK(2); if (c) do { i_insw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 568 | case 0x6e: CLK(2); if (c) do { i_outsb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 569 | case 0x6f: CLK(2); if (c) do { i_outsw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 570 | case 0xa4: CLK(2); if (c) do { i_movsb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 571 | case 0xa5: CLK(2); if (c) do { i_movsw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 572 | case 0xa6: CLK(2); if (c) do { i_cmpsb(); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; |
| 573 | case 0xa7: CLK(2); if (c) do { i_cmpsw(); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; |
| 574 | case 0xaa: CLK(2); if (c) do { i_stosb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 575 | case 0xab: CLK(2); if (c) do { i_stosw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 576 | case 0xac: CLK(2); if (c) do { i_lodsb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 577 | case 0xad: CLK(2); if (c) do { i_lodsw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 578 | case 0xae: CLK(2); if (c) do { i_scasb(); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; |
| 579 | case 0xaf: CLK(2); if (c) do { i_scasw(); c--; } while (c>0 && ZF==0); Wreg(CW)=c; break; |
| 580 | default: logerror("%06x: REPNE invalid\n",PC()); (this->*s_nec_instruction[next])(); |
| 581 | } |
| 582 | m_seg_prefix=FALSE; |
| 583 | } |
| 584 | OP( 0xf3, i_repe ) { UINT32 next = fetchop(); UINT16 c = Wreg(CW); |
| 585 | switch(next) { /* Segments */ |
| 586 | case 0x26: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS1)<<4; next = fetchop(); CLK(2); break; |
| 587 | case 0x2e: m_seg_prefix=TRUE; m_prefix_base=Sreg(PS)<<4; next = fetchop(); CLK(2); break; |
| 588 | case 0x36: m_seg_prefix=TRUE; m_prefix_base=Sreg(SS)<<4; next = fetchop(); CLK(2); break; |
| 589 | case 0x3e: m_seg_prefix=TRUE; m_prefix_base=Sreg(DS0)<<4; next = fetchop(); CLK(2); break; |
| 590 | } |
| 591 | |
| 592 | switch(next) { |
| 593 | case 0x6c: CLK(2); if (c) do { i_insb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 594 | case 0x6d: CLK(2); if (c) do { i_insw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 595 | case 0x6e: CLK(2); if (c) do { i_outsb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 596 | case 0x6f: CLK(2); if (c) do { i_outsw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 597 | case 0xa4: CLK(2); if (c) do { i_movsb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 598 | case 0xa5: CLK(2); if (c) do { i_movsw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 599 | case 0xa6: CLK(2); if (c) do { i_cmpsb(); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; |
| 600 | case 0xa7: CLK(2); if (c) do { i_cmpsw(); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; |
| 601 | case 0xaa: CLK(2); if (c) do { i_stosb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 602 | case 0xab: CLK(2); if (c) do { i_stosw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 603 | case 0xac: CLK(2); if (c) do { i_lodsb(); c--; } while (c>0); Wreg(CW)=c; break; |
| 604 | case 0xad: CLK(2); if (c) do { i_lodsw(); c--; } while (c>0); Wreg(CW)=c; break; |
| 605 | case 0xae: CLK(2); if (c) do { i_scasb(); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; |
| 606 | case 0xaf: CLK(2); if (c) do { i_scasw(); c--; } while (c>0 && ZF==1); Wreg(CW)=c; break; |
| 607 | default: logerror("%06x: REPE invalid\n",PC()); (this->*s_nec_instruction[next])(); |
| 608 | } |
| 609 | m_seg_prefix=FALSE; |
| 610 | } |
| 611 | OP( 0xf4, i_hlt ) { logerror("%06x: HALT\n",PC()); m_halted=1; m_icount=0; } |
| 612 | OP( 0xf5, i_cmc ) { m_CarryVal = !CF; CLK(2); } |
| 613 | OP( 0xf6, i_f6pre ) { UINT32 tmp; UINT32 uresult,uresult2; INT32 result,result2; |
| 614 | GetModRM; tmp = GetRMByte(ModRM); |
| 615 | switch (ModRM & 0x38) { |
| 616 | case 0x00: tmp &= FETCH(); m_CarryVal = m_OverVal = 0; SetSZPF_Byte(tmp); m_icount-=(ModRM >=0xc0 )?4:11; break; /* TEST */ |
| 617 | case 0x08: logerror("%06x: Undefined opcode 0xf6 0x08\n",PC()); break; |
| 618 | case 0x10: PutbackRMByte(ModRM,~tmp); m_icount-=(ModRM >=0xc0 )?2:16; break; /* NOT */ |
| 619 | case 0x18: m_CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Byte(tmp); PutbackRMByte(ModRM,tmp&0xff); m_icount-=(ModRM >=0xc0 )?2:16; break; /* NEG */ |
| 620 | case 0x20: uresult = Breg(AL)*tmp; Wreg(AW)=(WORD)uresult; m_CarryVal=m_OverVal=(Breg(AH)!=0); m_icount-=(ModRM >=0xc0 )?30:36; break; /* MULU */ |
| 621 | case 0x28: result = (INT16)((INT8)Breg(AL))*(INT16)((INT8)tmp); Wreg(AW)=(WORD)result; m_CarryVal=m_OverVal=(Breg(AH)!=0); m_icount-=(ModRM >=0xc0 )?30:36; break; /* MUL */ |
| 622 | case 0x30: if (tmp) { DIVUB; } else nec_interrupt(NEC_DIVIDE_VECTOR, BRK); m_icount-=(ModRM >=0xc0 )?43:53; break; |
| 623 | case 0x38: if (tmp) { DIVB; } else nec_interrupt(NEC_DIVIDE_VECTOR, BRK); m_icount-=(ModRM >=0xc0 )?43:53; break; |
| 624 | } |
| 625 | } |
| 626 | |
| 627 | OP( 0xf7, i_f7pre ) { UINT32 tmp,tmp2; UINT32 uresult,uresult2; INT32 result,result2; |
| 628 | GetModRM; tmp = GetRMWord(ModRM); |
| 629 | switch (ModRM & 0x38) { |
| 630 | case 0x00: tmp2 = FETCHWORD(); tmp &= tmp2; m_CarryVal = m_OverVal = 0; SetSZPF_Word(tmp); m_icount-=(ModRM >=0xc0 )?4:11; break; /* TEST */ |
| 631 | case 0x08: logerror("%06x: Undefined opcode 0xf7 0x08\n",PC()); break; |
| 632 | case 0x10: PutbackRMWord(ModRM,~tmp); m_icount-=(ModRM >=0xc0 )?2:16; break; /* NOT */ |
| 633 | case 0x18: m_CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Word(tmp); PutbackRMWord(ModRM,tmp&0xffff); m_icount-=(ModRM >=0xc0 )?2:16; break; /* NEG */ |
| 634 | case 0x20: uresult = Wreg(AW)*tmp; Wreg(AW)=uresult&0xffff; Wreg(DW)=((UINT32)uresult)>>16; m_CarryVal=m_OverVal=(Wreg(DW)!=0); m_icount-=(ModRM >=0xc0 )?30:36; break; /* MULU */ |
| 635 | case 0x28: result = (INT32)((INT16)Wreg(AW))*(INT32)((INT16)tmp); Wreg(AW)=result&0xffff; Wreg(DW)=result>>16; m_CarryVal=m_OverVal=(Wreg(DW)!=0); m_icount-=(ModRM >=0xc0 )?30:36; break; /* MUL */ |
| 636 | case 0x30: if (tmp) { DIVUW; } else nec_interrupt(NEC_DIVIDE_VECTOR, BRK); m_icount-=(ModRM >=0xc0 )?43:53; break; |
| 637 | case 0x38: if (tmp) { DIVW; } else nec_interrupt(NEC_DIVIDE_VECTOR, BRK); m_icount-=(ModRM >=0xc0 )?43:53; break; |
| 638 | } |
| 639 | } |
| 640 | |
| 641 | OP( 0xf8, i_clc ) { m_CarryVal = 0; CLK(2); } |
| 642 | OP( 0xf9, i_stc ) { m_CarryVal = 1; CLK(2); } |
| 643 | OP( 0xfa, i_di ) { SetIF(0); CLK(2); } |
| 644 | OP( 0xfb, i_ei ) { SetIF(1); CLK(2); } |
| 645 | OP( 0xfc, i_cld ) { SetDF(0); CLK(2); } |
| 646 | OP( 0xfd, i_std ) { SetDF(1); CLK(2); } |
| 647 | OP( 0xfe, i_fepre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMByte(ModRM); |
| 648 | switch(ModRM & 0x38) { |
| 649 | case 0x00: tmp1 = tmp+1; m_OverVal = (tmp==0x7f); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(2,2,2,16,16,7); break; /* INC */ |
| 650 | case 0x08: tmp1 = tmp-1; m_OverVal = (tmp==0x80); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(BYTE)tmp1); CLKM(2,2,2,16,16,7); break; /* DEC */ |
| 651 | default: logerror("%06x: FE Pre with unimplemented mod\n",PC()); |
| 652 | } |
| 653 | } |
| 654 | OP( 0xff, i_ffpre ) { UINT32 tmp, tmp1; GetModRM; tmp=GetRMWord(ModRM); |
| 655 | switch(ModRM & 0x38) { |
| 656 | case 0x00: tmp1 = tmp+1; m_OverVal = (tmp==0x7fff); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(2,2,2,24,16,7); break; /* INC */ |
| 657 | case 0x08: tmp1 = tmp-1; m_OverVal = (tmp==0x8000); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(WORD)tmp1); CLKM(2,2,2,24,16,7); break; /* DEC */ |
| 658 | case 0x10: PUSH(m_ip); m_ip = (WORD)tmp; CHANGE_PC; m_icount-=(ModRM >=0xc0 )?16:20; break; /* CALL */ |
| 659 | case 0x18: tmp1 = Sreg(PS); Sreg(PS) = GetnextRMWord; PUSH(tmp1); PUSH(m_ip); m_ip = tmp; CHANGE_PC; m_icount-=(ModRM >=0xc0 )?16:26; break; /* CALL FAR */ |
| 660 | case 0x20: m_ip = tmp; CHANGE_PC; m_icount-=13; break; /* JMP */ |
| 661 | case 0x28: m_ip = tmp; Sreg(PS) = GetnextRMWord; CHANGE_PC; m_icount-=15; break; /* JMP FAR */ |
| 662 | case 0x30: PUSH(tmp); m_icount-=4; break; |
| 663 | default: logerror("%06x: FF Pre with unimplemented mod\n",PC()); |
| 664 | } |
| 665 | } |
| 666 | |
| 667 | void nec_common_device::i_invalid() |
| 668 | { |
| 669 | m_icount-=10; |
| 670 | logerror("%06x: Invalid Opcode\n",PC()); |
| 671 | } |
trunk/src/emu/cpu/dsp32/dsp32ops.c
| r28738 | r28739 | |
| 1 | | // license:BSD-3-Clause |
| 2 | | // copyright-holders:Aaron Giles |
| 3 | | /*************************************************************************** |
| 4 | | |
| 5 | | dsp32ops.c |
| 6 | | Core implementation for the portable DSP32 emulator. |
| 7 | | |
| 8 | | ****************************************************************************/ |
| 9 | | |
| 10 | | |
| 11 | | |
| 12 | | //************************************************************************** |
| 13 | | // COMPILE-TIME OPTIONS |
| 14 | | //************************************************************************** |
| 15 | | |
| 16 | | // these defined latencies are a pain to implement, but are necessary |
| 17 | | #define EMULATE_MEMORY_LATENCY (1) |
| 18 | | #define EMULATE_MULTIPLIER_LATENCY (1) |
| 19 | | #define EMULATE_AFLAGS_LATENCY (1) |
| 20 | | |
| 21 | | // these optimizations should have some effect, but they don't really, so |
| 22 | | // leave them off |
| 23 | | #define IGNORE_DAU_UV_FLAGS (0) |
| 24 | | #define ASSUME_WRITEABLE (0) |
| 25 | | #define ASSUME_UNCONDITIONAL_CAU (0) |
| 26 | | |
| 27 | | |
| 28 | | |
| 29 | | //************************************************************************** |
| 30 | | // MACROS |
| 31 | | //************************************************************************** |
| 32 | | |
| 33 | | #define SET_V_16(a,b,r) m_vflags = (((a) ^ (b) ^ (r) ^ ((r) >> 1)) << 8) |
| 34 | | #define SET_NZC_16(r) m_nzcflags = ((r) << 8) |
| 35 | | #define SET_NZCV_16(a,b,r) SET_NZC_16(r); SET_V_16(a,b,r) |
| 36 | | #define SET_NZ00_16(r) m_nzcflags = (((r) << 8) & 0xffffff); m_vflags = 0 |
| 37 | | |
| 38 | | #define SET_V_24(a,b,r) m_vflags = ((a) ^ (b) ^ (r) ^ ((r) >> 1)) |
| 39 | | #define SET_NZC_24(r) m_nzcflags = (r) |
| 40 | | #define SET_NZCV_24(a,b,r) SET_NZC_24(r); SET_V_24(a,b,r) |
| 41 | | #define SET_NZ00_24(r) m_nzcflags = ((r) & 0xffffff); m_vflags = 0 |
| 42 | | |
| 43 | | #define TRUNCATE24(a) ((a) & 0xffffff) |
| 44 | | #define EXTEND16_TO_24(a) TRUNCATE24((INT32)(INT16)(a)) |
| 45 | | #define REG16(a) ((UINT16)m_r[a]) |
| 46 | | #define REG24(a) (m_r[a]) |
| 47 | | |
| 48 | | #define WRITEABLE_REGS (0x6f3efffe) |
| 49 | | #if ASSUME_WRITEABLE |
| 50 | | #define IS_WRITEABLE(r) (1) |
| 51 | | #else |
| 52 | | #define IS_WRITEABLE(r) (WRITEABLE_REGS & (1 << (r))) |
| 53 | | #endif |
| 54 | | |
| 55 | | #if ASSUME_UNCONDITIONAL_CAU |
| 56 | | #define CONDITION_IS_TRUE() (1) |
| 57 | | #else |
| 58 | | #define CONDITION_IS_TRUE() (!(op & 0x400) || (condition((op >> 12) & 15))) |
| 59 | | #endif |
| 60 | | |
| 61 | | #if EMULATE_MEMORY_LATENCY |
| 62 | | #define WWORD_DEFERRED(a,v) do { int bufidx = m_mbuf_index & 3; m_mbufaddr[bufidx] = -(a); m_mbufdata[bufidx] = (v); } while (0) |
| 63 | | #define WLONG_DEFERRED(a,v) do { int bufidx = m_mbuf_index & 3; m_mbufaddr[bufidx] = (a); m_mbufdata[bufidx] = (v); } while (0) |
| 64 | | #define PROCESS_DEFERRED_MEMORY() \ |
| 65 | | if (m_mbufaddr[++m_mbuf_index & 3] != 1) \ |
| 66 | | { \ |
| 67 | | int bufidx = m_mbuf_index & 3; \ |
| 68 | | if (m_mbufaddr[bufidx] >= 0) \ |
| 69 | | WLONG(m_mbufaddr[bufidx], m_mbufdata[bufidx]); \ |
| 70 | | else \ |
| 71 | | WWORD(-m_mbufaddr[bufidx], m_mbufdata[bufidx]); \ |
| 72 | | m_mbufaddr[bufidx] = 1; \ |
| 73 | | } |
| 74 | | #else |
| 75 | | #define WWORD_DEFERRED(a,v) WWORD(a,v) |
| 76 | | #define WLONG_DEFERRED(a,v) WLONG(a,v) |
| 77 | | #define PROCESS_DEFERRED_MEMORY() |
| 78 | | #endif |
| 79 | | |
| 80 | | #if EMULATE_MULTIPLIER_LATENCY |
| 81 | | #define DEFERRED_MULTIPLIER(x) dau_get_amult(x) |
| 82 | | #else |
| 83 | | #define DEFERRED_MULTIPLIER(x) m_a[x] |
| 84 | | #endif |
| 85 | | |
| 86 | | #if EMULATE_AFLAGS_LATENCY |
| 87 | | #define DEFERRED_NZFLAGS() dau_get_anzflags() |
| 88 | | #define DEFERRED_VUFLAGS() dau_get_avuflags() |
| 89 | | #else |
| 90 | | #define DEFERRED_NZFLAGS() m_NZflags |
| 91 | | #define DEFERRED_VUFLAGS() m_VUflags |
| 92 | | #endif |
| 93 | | |
| 94 | | |
| 95 | | |
| 96 | | //************************************************************************** |
| 97 | | // TYPEDEFS |
| 98 | | //************************************************************************** |
| 99 | | |
| 100 | | union int_double |
| 101 | | { |
| 102 | | double d; |
| 103 | | UINT32 i[2]; |
| 104 | | }; |
| 105 | | |
| 106 | | |
| 107 | | |
| 108 | | //************************************************************************** |
| 109 | | // IMPLEMENTATION |
| 110 | | //************************************************************************** |
| 111 | | |
| 112 | | void dsp32c_device::illegal(UINT32 op) |
| 113 | | { |
| 114 | | } |
| 115 | | |
| 116 | | |
| 117 | | void dsp32c_device::unimplemented(UINT32 op) |
| 118 | | { |
| 119 | | fatalerror("Unimplemented op @ %06X: %08X (dis=%02X, tbl=%03X)\n", PC - 4, op, op >> 25, op >> 21); |
| 120 | | } |
| 121 | | |
| 122 | | |
| 123 | | inline void dsp32c_device::execute_one() |
| 124 | | { |
| 125 | | UINT32 op; |
| 126 | | |
| 127 | | PROCESS_DEFERRED_MEMORY(); |
| 128 | | debugger_instruction_hook(this, PC); |
| 129 | | op = ROPCODE(PC); |
| 130 | | m_icount -= 4; // 4 clocks per cycle |
| 131 | | PC += 4; |
| 132 | | if (op) |
| 133 | | (this->*s_dsp32ops[op >> 21])(op); |
| 134 | | } |
| 135 | | |
| 136 | | |
| 137 | | |
| 138 | | //************************************************************************** |
| 139 | | // CAU HELPERS |
| 140 | | //************************************************************************** |
| 141 | | |
| 142 | | UINT32 dsp32c_device::cau_read_pi_special(UINT8 i) |
| 143 | | { |
| 144 | | switch (i) |
| 145 | | { |
| 146 | | case 4: return m_ibuf; |
| 147 | | case 5: return m_obuf; |
| 148 | | case 6: update_pcr(m_pcr & ~PCR_PDFs); update_pins(); return m_pdr; |
| 149 | | case 14: return m_piop; |
| 150 | | case 20: return m_pdr2; |
| 151 | | case 22: update_pcr(m_pcr & ~PCR_PIFs); update_pins(); return m_pir; |
| 152 | | case 30: return m_pcw; |
| 153 | | default: fprintf(stderr, "Unimplemented CAU PI read = %X\n", i); |
| 154 | | } |
| 155 | | return 0; |
| 156 | | } |
| 157 | | |
| 158 | | |
| 159 | | void dsp32c_device::cau_write_pi_special(UINT8 i, UINT32 val) |
| 160 | | { |
| 161 | | switch (i) |
| 162 | | { |
| 163 | | case 4: m_ibuf = val; break; |
| 164 | | case 5: m_obuf = val; break; |
| 165 | | case 6: m_pdr = val; update_pcr(m_pcr | PCR_PDFs); update_pins(); break; |
| 166 | | case 14: m_piop = val; break; |
| 167 | | case 20: m_pdr2 = val; break; |
| 168 | | case 22: m_pir = val; update_pcr(m_pcr | PCR_PIFs); update_pins(); break; |
| 169 | | case 30: m_pcw = val; break; |
| 170 | | default: fprintf(stderr, "Unimplemented CAU PI write = %X\n", i); |
| 171 | | } |
| 172 | | } |
| 173 | | |
| 174 | | |
| 175 | | inline UINT8 dsp32c_device::cau_read_pi_1byte(int pi) |
| 176 | | { |
| 177 | | int p = (pi >> 5) & 0x1f; |
| 178 | | int i = (pi >> 0) & 0x1f; |
| 179 | | if (p) |
| 180 | | { |
| 181 | | UINT32 result = RBYTE(m_r[p]); |
| 182 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i]); |
| 183 | | return result; |
| 184 | | } |
| 185 | | else |
| 186 | | return cau_read_pi_special(i); |
| 187 | | } |
| 188 | | |
| 189 | | |
| 190 | | inline UINT16 dsp32c_device::cau_read_pi_2byte(int pi) |
| 191 | | { |
| 192 | | int p = (pi >> 5) & 0x1f; |
| 193 | | int i = (pi >> 0) & 0x1f; |
| 194 | | if (p) |
| 195 | | { |
| 196 | | UINT32 result = RWORD(m_r[p]); |
| 197 | | if (i < 22 || i > 23) |
| 198 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i]); |
| 199 | | else |
| 200 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i] * 2); |
| 201 | | return result; |
| 202 | | } |
| 203 | | else |
| 204 | | return cau_read_pi_special(i); |
| 205 | | } |
| 206 | | |
| 207 | | |
| 208 | | inline UINT32 dsp32c_device::cau_read_pi_4byte(int pi) |
| 209 | | { |
| 210 | | int p = (pi >> 5) & 0x1f; |
| 211 | | int i = (pi >> 0) & 0x1f; |
| 212 | | if (p) |
| 213 | | { |
| 214 | | UINT32 result = RLONG(m_r[p]); |
| 215 | | if (i < 22 || i > 23) |
| 216 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i]); |
| 217 | | else |
| 218 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i] * 4); |
| 219 | | return result; |
| 220 | | } |
| 221 | | else |
| 222 | | return cau_read_pi_special(i); |
| 223 | | } |
| 224 | | |
| 225 | | |
| 226 | | inline void dsp32c_device::cau_write_pi_1byte(int pi, UINT8 val) |
| 227 | | { |
| 228 | | int p = (pi >> 5) & 0x1f; |
| 229 | | int i = (pi >> 0) & 0x1f; |
| 230 | | if (p) |
| 231 | | { |
| 232 | | WBYTE(m_r[p], val); |
| 233 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i]); |
| 234 | | } |
| 235 | | else |
| 236 | | cau_write_pi_special(i, val); |
| 237 | | } |
| 238 | | |
| 239 | | |
| 240 | | inline void dsp32c_device::cau_write_pi_2byte(int pi, UINT16 val) |
| 241 | | { |
| 242 | | int p = (pi >> 5) & 0x1f; |
| 243 | | int i = (pi >> 0) & 0x1f; |
| 244 | | if (p) |
| 245 | | { |
| 246 | | WWORD(m_r[p], val); |
| 247 | | if (i < 22 || i > 23) |
| 248 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i]); |
| 249 | | else |
| 250 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i] * 2); |
| 251 | | } |
| 252 | | else |
| 253 | | cau_write_pi_special(i, val); |
| 254 | | } |
| 255 | | |
| 256 | | |
| 257 | | inline void dsp32c_device::cau_write_pi_4byte(int pi, UINT32 val) |
| 258 | | { |
| 259 | | int p = (pi >> 5) & 0x1f; |
| 260 | | int i = (pi >> 0) & 0x1f; |
| 261 | | if (p) |
| 262 | | { |
| 263 | | WLONG(m_r[p], (INT32)(val << 8) >> 8); |
| 264 | | if (i < 22 || i > 23) |
| 265 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i]); |
| 266 | | else |
| 267 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i] * 4); |
| 268 | | } |
| 269 | | else |
| 270 | | cau_write_pi_special(i, val); |
| 271 | | } |
| 272 | | |
| 273 | | |
| 274 | | |
| 275 | | //************************************************************************** |
| 276 | | // DAU HELPERS |
| 277 | | //************************************************************************** |
| 278 | | |
| 279 | | inline double dsp32c_device::dau_get_amult(int aidx) |
| 280 | | { |
| 281 | | int bufidx = (m_abuf_index - 1) & 3; |
| 282 | | double val = m_a[aidx]; |
| 283 | | while (m_icount >= m_abufcycle[bufidx] - 2 * 4) |
| 284 | | { |
| 285 | | if (m_abufreg[bufidx] == aidx) |
| 286 | | val = m_abuf[bufidx]; |
| 287 | | bufidx = (bufidx - 1) & 3; |
| 288 | | } |
| 289 | | return val; |
| 290 | | } |
| 291 | | |
| 292 | | |
| 293 | | inline double dsp32c_device::dau_get_anzflags() |
| 294 | | { |
| 295 | | int bufidx = (m_abuf_index - 1) & 3; |
| 296 | | double nzflags = m_NZflags; |
| 297 | | while (m_icount >= m_abufcycle[bufidx] - 3 * 4) |
| 298 | | { |
| 299 | | nzflags = m_abufNZflags[bufidx]; |
| 300 | | bufidx = (bufidx - 1) & 3; |
| 301 | | } |
| 302 | | return nzflags; |
| 303 | | } |
| 304 | | |
| 305 | | |
| 306 | | inline UINT8 dsp32c_device::dau_get_avuflags() |
| 307 | | { |
| 308 | | #if (!IGNORE_DAU_UV_FLAGS) |
| 309 | | int bufidx = (m_abuf_index - 1) & 3; |
| 310 | | UINT8 vuflags = m_VUflags; |
| 311 | | while (m_icount >= m_abufcycle[bufidx] - 3 * 4) |
| 312 | | { |
| 313 | | vuflags = m_abufVUflags[bufidx]; |
| 314 | | bufidx = (bufidx - 1) & 3; |
| 315 | | } |
| 316 | | return vuflags; |
| 317 | | #else |
| 318 | | return 0; |
| 319 | | #endif |
| 320 | | } |
| 321 | | |
| 322 | | |
| 323 | | inline void dsp32c_device::remember_last_dau(int aidx) |
| 324 | | { |
| 325 | | #if (EMULATE_MULTIPLIER_LATENCY || EMULATE_AFLAGS_LATENCY) |
| 326 | | int bufidx = m_abuf_index++ & 3; |
| 327 | | m_abuf[bufidx] = m_a[aidx]; |
| 328 | | m_abufreg[bufidx] = aidx; |
| 329 | | m_abufNZflags[bufidx] = m_NZflags; |
| 330 | | #if (!IGNORE_DAU_UV_FLAGS) |
| 331 | | m_abufVUflags[bufidx] = m_VUflags; |
| 332 | | #endif |
| 333 | | m_abufcycle[bufidx] = m_icount; |
| 334 | | #endif |
| 335 | | } |
| 336 | | |
| 337 | | |
| 338 | | inline void dsp32c_device::dau_set_val_noflags(int aidx, double res) |
| 339 | | { |
| 340 | | remember_last_dau(aidx); |
| 341 | | m_a[aidx] = res; |
| 342 | | } |
| 343 | | |
| 344 | | |
| 345 | | inline void dsp32c_device::dau_set_val_flags(int aidx, double res) |
| 346 | | { |
| 347 | | remember_last_dau(aidx); |
| 348 | | #if (!IGNORE_DAU_UV_FLAGS) |
| 349 | | { |
| 350 | | double absres = (res < 0) ? -res : res; |
| 351 | | m_VUflags = 0; |
| 352 | | if (absres < 5.87747e-39) |
| 353 | | { |
| 354 | | if (absres != 0) |
| 355 | | m_VUflags = UFLAGBIT; |
| 356 | | res = 0.0; |
| 357 | | } |
| 358 | | else if (absres > 3.40282e38) |
| 359 | | { |
| 360 | | m_VUflags = VFLAGBIT; |
| 361 | | // debugger_break(Machine); |
| 362 | | // fprintf(stderr, "Result = %g\n", absres); |
| 363 | | res = (res < 0) ? -3.40282e38 : 3.40282e38; |
| 364 | | } |
| 365 | | } |
| 366 | | #endif |
| 367 | | m_NZflags = res; |
| 368 | | m_a[aidx] = res; |
| 369 | | } |
| 370 | | |
| 371 | | |
| 372 | | inline double dsp32c_device::dsp_to_double(UINT32 val) |
| 373 | | { |
| 374 | | int_double id; |
| 375 | | |
| 376 | | if (val == 0) |
| 377 | | return 0; |
| 378 | | else if ((INT32)val > 0) |
| 379 | | { |
| 380 | | int exponent = ((val & 0xff) - 128 + 1023) << 20; |
| 381 | | id.i[BYTE_XOR_BE(0)] = exponent + (val >> 11); |
| 382 | | id.i[BYTE_XOR_BE(1)] = (val << 21) & 0xe0000000; |
| 383 | | } |
| 384 | | else |
| 385 | | { |
| 386 | | int exponent = ((val & 0xff) - 128 + 1023) << 20; |
| 387 | | val = -(val & 0xffffff00); |
| 388 | | id.i[BYTE_XOR_BE(0)] = 0x80000000 + exponent + ((val >> 11) & 0x001fffff); |
| 389 | | id.i[BYTE_XOR_BE(1)] = (val << 21) & 0xe0000000; |
| 390 | | } |
| 391 | | return id.d; |
| 392 | | } |
| 393 | | |
| 394 | | |
| 395 | | inline UINT32 dsp32c_device::double_to_dsp(double val) |
| 396 | | { |
| 397 | | int mantissa, exponent; |
| 398 | | int_double id; |
| 399 | | id.d = val; |
| 400 | | mantissa = ((id.i[BYTE_XOR_BE(0)] & 0x000fffff) << 11) | ((id.i[BYTE_XOR_BE(1)] & 0xe0000000) >> 21); |
| 401 | | exponent = ((id.i[BYTE_XOR_BE(0)] & 0x7ff00000) >> 20) - 1023 + 128; |
| 402 | | if (exponent < 0) |
| 403 | | return 0x00000000; |
| 404 | | else if (exponent > 255) |
| 405 | | { |
| 406 | | // debugger_break(Machine); |
| 407 | | // fprintf(stderr, "Exponent = %d\n", exponent); |
| 408 | | return ((INT32)id.i[BYTE_XOR_BE(0)] >= 0) ? 0x7fffffff : 0x800000ff; |
| 409 | | } |
| 410 | | else if ((INT32)id.i[BYTE_XOR_BE(0)] >= 0) |
| 411 | | return exponent | mantissa; |
| 412 | | else |
| 413 | | { |
| 414 | | mantissa = -mantissa; |
| 415 | | if (mantissa == 0) { mantissa = 0x80000000; exponent--; } |
| 416 | | return 0x80000000 | exponent | (mantissa & 0xffffff00); |
| 417 | | } |
| 418 | | } |
| 419 | | |
| 420 | | |
| 421 | | double dsp32c_device::dau_read_pi_special(int i) |
| 422 | | { |
| 423 | | fatalerror("Unimplemented dau_read_pi_special(%d)\n", i); |
| 424 | | return 0; |
| 425 | | } |
| 426 | | |
| 427 | | |
| 428 | | void dsp32c_device::dau_write_pi_special(int i, double val) |
| 429 | | { |
| 430 | | fatalerror("Unimplemented dau_write_pi_special(%d)\n", i); |
| 431 | | } |
| 432 | | |
| 433 | | |
| 434 | | inline double dsp32c_device::dau_read_pi_double_1st(int pi, int multiplier) |
| 435 | | { |
| 436 | | int p = (pi >> 3) & 15; |
| 437 | | int i = (pi >> 0) & 7; |
| 438 | | |
| 439 | | m_lastp = p; |
| 440 | | if (p) |
| 441 | | { |
| 442 | | UINT32 result = RLONG(m_r[p]); |
| 443 | | if (i < 6) |
| 444 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 445 | | else |
| 446 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4); |
| 447 | | return dsp_to_double(result); |
| 448 | | } |
| 449 | | else if (i < 4) |
| 450 | | return multiplier ? DEFERRED_MULTIPLIER(i) : m_a[i]; |
| 451 | | else |
| 452 | | return dau_read_pi_special(i); |
| 453 | | } |
| 454 | | |
| 455 | | |
| 456 | | inline double dsp32c_device::dau_read_pi_double_2nd(int pi, int multiplier, double xval) |
| 457 | | { |
| 458 | | int p = (pi >> 3) & 15; |
| 459 | | int i = (pi >> 0) & 7; |
| 460 | | |
| 461 | | if (p == 15) p = m_lastp; // P=15 means Z inherits from Y, Y inherits from X |
| 462 | | m_lastp = p; |
| 463 | | if (p) |
| 464 | | { |
| 465 | | UINT32 result; |
| 466 | | result = RLONG(m_r[p]); |
| 467 | | if (i < 6) |
| 468 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 469 | | else |
| 470 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4); |
| 471 | | return dsp_to_double(result); |
| 472 | | } |
| 473 | | else if (i < 4) |
| 474 | | return multiplier ? DEFERRED_MULTIPLIER(i) : m_a[i]; |
| 475 | | else |
| 476 | | return dau_read_pi_special(i); |
| 477 | | } |
| 478 | | |
| 479 | | |
| 480 | | inline UINT32 dsp32c_device::dau_read_pi_4bytes(int pi) |
| 481 | | { |
| 482 | | int p = (pi >> 3) & 15; |
| 483 | | int i = (pi >> 0) & 7; |
| 484 | | |
| 485 | | m_lastp = p; |
| 486 | | if (p) |
| 487 | | { |
| 488 | | UINT32 result = RLONG(m_r[p]); |
| 489 | | if (i < 6) |
| 490 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 491 | | else |
| 492 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4); |
| 493 | | return result; |
| 494 | | } |
| 495 | | else if (i < 4) |
| 496 | | return double_to_dsp(m_a[i]); |
| 497 | | else |
| 498 | | return dau_read_pi_special(i); |
| 499 | | } |
| 500 | | |
| 501 | | |
| 502 | | inline UINT16 dsp32c_device::dau_read_pi_2bytes(int pi) |
| 503 | | { |
| 504 | | int p = (pi >> 3) & 15; |
| 505 | | int i = (pi >> 0) & 7; |
| 506 | | |
| 507 | | m_lastp = p; |
| 508 | | if (p) |
| 509 | | { |
| 510 | | UINT32 result = RWORD(m_r[p]); |
| 511 | | if (i < 6) |
| 512 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 513 | | else |
| 514 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 2); |
| 515 | | return result; |
| 516 | | } |
| 517 | | else if (i < 4) |
| 518 | | return double_to_dsp(m_a[i]); |
| 519 | | else |
| 520 | | return dau_read_pi_special(i); |
| 521 | | } |
| 522 | | |
| 523 | | |
| 524 | | inline void dsp32c_device::dau_write_pi_double(int pi, double val) |
| 525 | | { |
| 526 | | int p = (pi >> 3) & 15; |
| 527 | | int i = (pi >> 0) & 7; |
| 528 | | |
| 529 | | if (p == 15) p = m_lastp; // P=15 means Z inherits from Y, Y inherits from X |
| 530 | | if (p) |
| 531 | | { |
| 532 | | WLONG_DEFERRED(m_r[p], double_to_dsp(val)); |
| 533 | | if (i < 6) |
| 534 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 535 | | else |
| 536 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4); |
| 537 | | } |
| 538 | | else if (i < 4) |
| 539 | | dau_set_val_noflags(i, val); |
| 540 | | else |
| 541 | | dau_write_pi_special(i, val); |
| 542 | | } |
| 543 | | |
| 544 | | |
| 545 | | inline void dsp32c_device::dau_write_pi_4bytes(int pi, UINT32 val) |
| 546 | | { |
| 547 | | int p = (pi >> 3) & 15; |
| 548 | | int i = (pi >> 0) & 7; |
| 549 | | |
| 550 | | if (p == 15) p = m_lastp; // P=15 means Z inherits from Y, Y inherits from X |
| 551 | | if (p) |
| 552 | | { |
| 553 | | m_lastp = p; |
| 554 | | WLONG_DEFERRED(m_r[p], val); |
| 555 | | if (i < 6) |
| 556 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 557 | | else |
| 558 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4); |
| 559 | | } |
| 560 | | else if (i < 4) |
| 561 | | dau_set_val_noflags(i, dsp_to_double(val)); |
| 562 | | else |
| 563 | | dau_write_pi_special(i, val); |
| 564 | | } |
| 565 | | |
| 566 | | |
| 567 | | inline void dsp32c_device::dau_write_pi_2bytes(int pi, UINT16 val) |
| 568 | | { |
| 569 | | int p = (pi >> 3) & 15; |
| 570 | | int i = (pi >> 0) & 7; |
| 571 | | |
| 572 | | if (p == 15) p = m_lastp; // P=15 means Z inherits from Y, Y inherits from X |
| 573 | | if (p) |
| 574 | | { |
| 575 | | m_lastp = p; |
| 576 | | WWORD_DEFERRED(m_r[p], val); |
| 577 | | if (i < 6) |
| 578 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 579 | | else |
| 580 | | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 2); |
| 581 | | } |
| 582 | | else if (i < 4) |
| 583 | | dau_set_val_noflags(i, dsp_to_double(val << 16)); |
| 584 | | else |
| 585 | | dau_write_pi_special(i, val); |
| 586 | | } |
| 587 | | |
| 588 | | |
| 589 | | |
| 590 | | //************************************************************************** |
| 591 | | // COMMON CONDITION ROUTINE |
| 592 | | //************************************************************************** |
| 593 | | |
| 594 | | #if (!ASSUME_UNCONDITIONAL_CAU) |
| 595 | | int dsp32c_device::condition(int cond) |
| 596 | | { |
| 597 | | switch (cond) |
| 598 | | { |
| 599 | | case 0: |
| 600 | | return 0; |
| 601 | | case 1: |
| 602 | | return 1; |
| 603 | | case 2: |
| 604 | | return !nFLAG; |
| 605 | | case 3: |
| 606 | | return nFLAG; |
| 607 | | case 4: |
| 608 | | return !zFLAG; |
| 609 | | case 5: |
| 610 | | return zFLAG; |
| 611 | | case 6: |
| 612 | | return !vFLAG; |
| 613 | | case 7: |
| 614 | | return vFLAG; |
| 615 | | case 8: |
| 616 | | return !cFLAG; |
| 617 | | case 9: |
| 618 | | return cFLAG; |
| 619 | | case 10: |
| 620 | | return !(nFLAG ^ cFLAG); |
| 621 | | case 11: |
| 622 | | return (nFLAG ^ cFLAG); |
| 623 | | case 12: |
| 624 | | return !(zFLAG | (nFLAG ^ vFLAG)); |
| 625 | | case 13: |
| 626 | | return (zFLAG | (nFLAG ^ vFLAG)); |
| 627 | | case 14: |
| 628 | | return !(cFLAG | zFLAG); |
| 629 | | case 15: |
| 630 | | return (cFLAG | zFLAG); |
| 631 | | |
| 632 | | case 16: |
| 633 | | return !(DEFERRED_VUFLAGS() & UFLAGBIT); |
| 634 | | case 17: |
| 635 | | return (DEFERRED_VUFLAGS() & UFLAGBIT); |
| 636 | | case 18: |
| 637 | | return !(DEFERRED_NZFLAGS() < 0); |
| 638 | | case 19: |
| 639 | | return (DEFERRED_NZFLAGS() < 0); |
| 640 | | case 20: |
| 641 | | return !(DEFERRED_NZFLAGS() == 0); |
| 642 | | case 21: |
| 643 | | return (DEFERRED_NZFLAGS() == 0); |
| 644 | | case 22: |
| 645 | | return !(DEFERRED_VUFLAGS() & VFLAGBIT); |
| 646 | | case 23: |
| 647 | | return (DEFERRED_VUFLAGS() & VFLAGBIT); |
| 648 | | case 24: |
| 649 | | return !(DEFERRED_NZFLAGS() <= 0); |
| 650 | | case 25: |
| 651 | | return (DEFERRED_NZFLAGS() <= 0); |
| 652 | | |
| 653 | | case 32: // !ibf |
| 654 | | case 33: // ibf |
| 655 | | case 34: // !obe |
| 656 | | case 35: // obe |
| 657 | | case 36: // !pdf |
| 658 | | case 37: // pdf |
| 659 | | case 38: // !pif |
| 660 | | case 39: // pif |
| 661 | | case 40: // !sy |
| 662 | | case 41: // sy |
| 663 | | case 42: // !fb |
| 664 | | case 43: // fb |
| 665 | | case 44: // !ireq1 |
| 666 | | case 45: // ireq1 |
| 667 | | case 46: // !ireq2 |
| 668 | | case 47: // ireq2 |
| 669 | | default: |
| 670 | | fatalerror("Unimplemented condition: %X\n", cond); |
| 671 | | } |
| 672 | | } |
| 673 | | #endif |
| 674 | | |
| 675 | | |
| 676 | | |
| 677 | | //************************************************************************** |
| 678 | | // CAU BRANCH INSTRUCTION IMPLEMENTATION |
| 679 | | //************************************************************************** |
| 680 | | |
| 681 | | void dsp32c_device::nop(UINT32 op) |
| 682 | | { |
| 683 | | if (op == 0) |
| 684 | | return; |
| 685 | | execute_one(); |
| 686 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 687 | | } |
| 688 | | |
| 689 | | |
| 690 | | void dsp32c_device::goto_t(UINT32 op) |
| 691 | | { |
| 692 | | execute_one(); |
| 693 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 694 | | } |
| 695 | | |
| 696 | | |
| 697 | | void dsp32c_device::goto_pl(UINT32 op) |
| 698 | | { |
| 699 | | if (!nFLAG) |
| 700 | | { |
| 701 | | execute_one(); |
| 702 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 703 | | } |
| 704 | | } |
| 705 | | |
| 706 | | |
| 707 | | void dsp32c_device::goto_mi(UINT32 op) |
| 708 | | { |
| 709 | | if (nFLAG) |
| 710 | | { |
| 711 | | execute_one(); |
| 712 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 713 | | } |
| 714 | | } |
| 715 | | |
| 716 | | |
| 717 | | void dsp32c_device::goto_ne(UINT32 op) |
| 718 | | { |
| 719 | | if (!zFLAG) |
| 720 | | { |
| 721 | | execute_one(); |
| 722 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 723 | | } |
| 724 | | } |
| 725 | | |
| 726 | | |
| 727 | | void dsp32c_device::goto_eq(UINT32 op) |
| 728 | | { |
| 729 | | if (zFLAG) |
| 730 | | { |
| 731 | | execute_one(); |
| 732 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 733 | | } |
| 734 | | } |
| 735 | | |
| 736 | | |
| 737 | | void dsp32c_device::goto_vc(UINT32 op) |
| 738 | | { |
| 739 | | if (!vFLAG) |
| 740 | | { |
| 741 | | execute_one(); |
| 742 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 743 | | } |
| 744 | | } |
| 745 | | |
| 746 | | |
| 747 | | void dsp32c_device::goto_vs(UINT32 op) |
| 748 | | { |
| 749 | | if (vFLAG) |
| 750 | | { |
| 751 | | execute_one(); |
| 752 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 753 | | } |
| 754 | | } |
| 755 | | |
| 756 | | |
| 757 | | void dsp32c_device::goto_cc(UINT32 op) |
| 758 | | { |
| 759 | | if (!cFLAG) |
| 760 | | { |
| 761 | | execute_one(); |
| 762 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 763 | | } |
| 764 | | } |
| 765 | | |
| 766 | | |
| 767 | | void dsp32c_device::goto_cs(UINT32 op) |
| 768 | | { |
| 769 | | if (cFLAG) |
| 770 | | { |
| 771 | | execute_one(); |
| 772 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 773 | | } |
| 774 | | } |
| 775 | | |
| 776 | | |
| 777 | | void dsp32c_device::goto_ge(UINT32 op) |
| 778 | | { |
| 779 | | if (!(nFLAG ^ vFLAG)) |
| 780 | | { |
| 781 | | execute_one(); |
| 782 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 783 | | } |
| 784 | | } |
| 785 | | |
| 786 | | |
| 787 | | void dsp32c_device::goto_lt(UINT32 op) |
| 788 | | { |
| 789 | | if (nFLAG ^ vFLAG) |
| 790 | | { |
| 791 | | execute_one(); |
| 792 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 793 | | } |
| 794 | | } |
| 795 | | |
| 796 | | |
| 797 | | void dsp32c_device::goto_gt(UINT32 op) |
| 798 | | { |
| 799 | | if (!(zFLAG | (nFLAG ^ vFLAG))) |
| 800 | | { |
| 801 | | execute_one(); |
| 802 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 803 | | } |
| 804 | | } |
| 805 | | |
| 806 | | |
| 807 | | void dsp32c_device::goto_le(UINT32 op) |
| 808 | | { |
| 809 | | if (zFLAG | (nFLAG ^ vFLAG)) |
| 810 | | { |
| 811 | | execute_one(); |
| 812 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 813 | | } |
| 814 | | } |
| 815 | | |
| 816 | | |
| 817 | | void dsp32c_device::goto_hi(UINT32 op) |
| 818 | | { |
| 819 | | if (!cFLAG && !zFLAG) |
| 820 | | { |
| 821 | | execute_one(); |
| 822 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 823 | | } |
| 824 | | } |
| 825 | | |
| 826 | | |
| 827 | | void dsp32c_device::goto_ls(UINT32 op) |
| 828 | | { |
| 829 | | if (cFLAG || zFLAG) |
| 830 | | { |
| 831 | | execute_one(); |
| 832 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 833 | | } |
| 834 | | } |
| 835 | | |
| 836 | | |
| 837 | | void dsp32c_device::goto_auc(UINT32 op) |
| 838 | | { |
| 839 | | if (!(DEFERRED_VUFLAGS() & UFLAGBIT)) |
| 840 | | { |
| 841 | | execute_one(); |
| 842 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 843 | | } |
| 844 | | } |
| 845 | | |
| 846 | | |
| 847 | | void dsp32c_device::goto_aus(UINT32 op) |
| 848 | | { |
| 849 | | if (DEFERRED_VUFLAGS() & UFLAGBIT) |
| 850 | | { |
| 851 | | execute_one(); |
| 852 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 853 | | } |
| 854 | | } |
| 855 | | |
| 856 | | |
| 857 | | void dsp32c_device::goto_age(UINT32 op) |
| 858 | | { |
| 859 | | if (DEFERRED_NZFLAGS() >= 0) |
| 860 | | { |
| 861 | | execute_one(); |
| 862 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 863 | | } |
| 864 | | } |
| 865 | | |
| 866 | | |
| 867 | | void dsp32c_device::goto_alt(UINT32 op) |
| 868 | | { |
| 869 | | if (DEFERRED_NZFLAGS() < 0) |
| 870 | | { |
| 871 | | execute_one(); |
| 872 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 873 | | } |
| 874 | | } |
| 875 | | |
| 876 | | |
| 877 | | void dsp32c_device::goto_ane(UINT32 op) |
| 878 | | { |
| 879 | | if (DEFERRED_NZFLAGS() != 0) |
| 880 | | { |
| 881 | | execute_one(); |
| 882 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 883 | | } |
| 884 | | } |
| 885 | | |
| 886 | | |
| 887 | | void dsp32c_device::goto_aeq(UINT32 op) |
| 888 | | { |
| 889 | | if (DEFERRED_NZFLAGS() == 0) |
| 890 | | { |
| 891 | | execute_one(); |
| 892 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 893 | | } |
| 894 | | } |
| 895 | | |
| 896 | | |
| 897 | | void dsp32c_device::goto_avc(UINT32 op) |
| 898 | | { |
| 899 | | if (!(DEFERRED_VUFLAGS() & VFLAGBIT)) |
| 900 | | { |
| 901 | | execute_one(); |
| 902 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 903 | | } |
| 904 | | } |
| 905 | | |
| 906 | | |
| 907 | | void dsp32c_device::goto_avs(UINT32 op) |
| 908 | | { |
| 909 | | if (DEFERRED_VUFLAGS() & VFLAGBIT) |
| 910 | | { |
| 911 | | execute_one(); |
| 912 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 913 | | } |
| 914 | | } |
| 915 | | |
| 916 | | |
| 917 | | void dsp32c_device::goto_agt(UINT32 op) |
| 918 | | { |
| 919 | | if (DEFERRED_NZFLAGS() > 0) |
| 920 | | { |
| 921 | | execute_one(); |
| 922 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 923 | | } |
| 924 | | } |
| 925 | | |
| 926 | | |
| 927 | | void dsp32c_device::goto_ale(UINT32 op) |
| 928 | | { |
| 929 | | if (DEFERRED_NZFLAGS() <= 0) |
| 930 | | { |
| 931 | | execute_one(); |
| 932 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 933 | | } |
| 934 | | } |
| 935 | | |
| 936 | | |
| 937 | | void dsp32c_device::goto_ibe(UINT32 op) |
| 938 | | { |
| 939 | | unimplemented(op); |
| 940 | | } |
| 941 | | |
| 942 | | |
| 943 | | void dsp32c_device::goto_ibf(UINT32 op) |
| 944 | | { |
| 945 | | unimplemented(op); |
| 946 | | } |
| 947 | | |
| 948 | | |
| 949 | | void dsp32c_device::goto_obf(UINT32 op) |
| 950 | | { |
| 951 | | unimplemented(op); |
| 952 | | } |
| 953 | | |
| 954 | | |
| 955 | | void dsp32c_device::goto_obe(UINT32 op) |
| 956 | | { |
| 957 | | unimplemented(op); |
| 958 | | } |
| 959 | | |
| 960 | | |
| 961 | | void dsp32c_device::goto_pde(UINT32 op) |
| 962 | | { |
| 963 | | if (!(m_pcr & PCR_PDFs)) |
| 964 | | { |
| 965 | | execute_one(); |
| 966 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 967 | | } |
| 968 | | } |
| 969 | | |
| 970 | | |
| 971 | | void dsp32c_device::goto_pdf(UINT32 op) |
| 972 | | { |
| 973 | | if (m_pcr & PCR_PDFs) |
| 974 | | { |
| 975 | | execute_one(); |
| 976 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 977 | | } |
| 978 | | } |
| 979 | | |
| 980 | | |
| 981 | | void dsp32c_device::goto_pie(UINT32 op) |
| 982 | | { |
| 983 | | if (!(m_pcr & PCR_PIFs)) |
| 984 | | { |
| 985 | | execute_one(); |
| 986 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 987 | | } |
| 988 | | } |
| 989 | | |
| 990 | | |
| 991 | | void dsp32c_device::goto_pif(UINT32 op) |
| 992 | | { |
| 993 | | if (m_pcr & PCR_PIFs) |
| 994 | | { |
| 995 | | execute_one(); |
| 996 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 997 | | } |
| 998 | | } |
| 999 | | |
| 1000 | | |
| 1001 | | void dsp32c_device::goto_syc(UINT32 op) |
| 1002 | | { |
| 1003 | | unimplemented(op); |
| 1004 | | } |
| 1005 | | |
| 1006 | | |
| 1007 | | void dsp32c_device::goto_sys(UINT32 op) |
| 1008 | | { |
| 1009 | | unimplemented(op); |
| 1010 | | } |
| 1011 | | |
| 1012 | | |
| 1013 | | void dsp32c_device::goto_fbc(UINT32 op) |
| 1014 | | { |
| 1015 | | unimplemented(op); |
| 1016 | | } |
| 1017 | | |
| 1018 | | |
| 1019 | | void dsp32c_device::goto_fbs(UINT32 op) |
| 1020 | | { |
| 1021 | | unimplemented(op); |
| 1022 | | } |
| 1023 | | |
| 1024 | | |
| 1025 | | void dsp32c_device::goto_irq1lo(UINT32 op) |
| 1026 | | { |
| 1027 | | unimplemented(op); |
| 1028 | | } |
| 1029 | | |
| 1030 | | |
| 1031 | | void dsp32c_device::goto_irq1hi(UINT32 op) |
| 1032 | | { |
| 1033 | | unimplemented(op); |
| 1034 | | } |
| 1035 | | |
| 1036 | | |
| 1037 | | void dsp32c_device::goto_irq2lo(UINT32 op) |
| 1038 | | { |
| 1039 | | unimplemented(op); |
| 1040 | | } |
| 1041 | | |
| 1042 | | |
| 1043 | | void dsp32c_device::goto_irq2hi(UINT32 op) |
| 1044 | | { |
| 1045 | | unimplemented(op); |
| 1046 | | } |
| 1047 | | |
| 1048 | | |
| 1049 | | void dsp32c_device::dec_goto(UINT32 op) |
| 1050 | | { |
| 1051 | | int hr = (op >> 21) & 0x1f; |
| 1052 | | int old = (INT16)m_r[hr]; |
| 1053 | | m_r[hr] = EXTEND16_TO_24(m_r[hr] - 1); |
| 1054 | | if (old >= 0) |
| 1055 | | { |
| 1056 | | execute_one(); |
| 1057 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 1058 | | } |
| 1059 | | } |
| 1060 | | |
| 1061 | | |
| 1062 | | void dsp32c_device::call(UINT32 op) |
| 1063 | | { |
| 1064 | | int mr = (op >> 21) & 0x1f; |
| 1065 | | if (IS_WRITEABLE(mr)) |
| 1066 | | m_r[mr] = PC + 4; |
| 1067 | | execute_one(); |
| 1068 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 1069 | | } |
| 1070 | | |
| 1071 | | |
| 1072 | | void dsp32c_device::goto24(UINT32 op) |
| 1073 | | { |
| 1074 | | execute_one(); |
| 1075 | | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (op & 0xffff) + ((op >> 5) & 0xff0000)); |
| 1076 | | } |
| 1077 | | |
| 1078 | | |
| 1079 | | void dsp32c_device::call24(UINT32 op) |
| 1080 | | { |
| 1081 | | int mr = (op >> 16) & 0x1f; |
| 1082 | | if (IS_WRITEABLE(mr)) |
| 1083 | | m_r[mr] = PC + 4; |
| 1084 | | execute_one(); |
| 1085 | | PC = (op & 0xffff) + ((op >> 5) & 0xff0000); |
| 1086 | | } |
| 1087 | | |
| 1088 | | |
| 1089 | | void dsp32c_device::do_i(UINT32 op) |
| 1090 | | { |
| 1091 | | unimplemented(op); |
| 1092 | | } |
| 1093 | | |
| 1094 | | |
| 1095 | | void dsp32c_device::do_r(UINT32 op) |
| 1096 | | { |
| 1097 | | unimplemented(op); |
| 1098 | | } |
| 1099 | | |
| 1100 | | |
| 1101 | | |
| 1102 | | //************************************************************************** |
| 1103 | | // CAU 16-BIT ARITHMETIC IMPLEMENTATION |
| 1104 | | //************************************************************************** |
| 1105 | | |
| 1106 | | void dsp32c_device::add_si(UINT32 op) |
| 1107 | | { |
| 1108 | | int dr = (op >> 21) & 0x1f; |
| 1109 | | int hrval = REG16((op >> 16) & 0x1f); |
| 1110 | | int res = hrval + (UINT16)op; |
| 1111 | | if (IS_WRITEABLE(dr)) |
| 1112 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1113 | | SET_NZCV_16(hrval, op, res); |
| 1114 | | } |
| 1115 | | |
| 1116 | | |
| 1117 | | void dsp32c_device::add_ss(UINT32 op) |
| 1118 | | { |
| 1119 | | if (CONDITION_IS_TRUE()) |
| 1120 | | { |
| 1121 | | int dr = (op >> 16) & 0x1f; |
| 1122 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1123 | | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1124 | | int res = s2rval + s1rval; |
| 1125 | | if (IS_WRITEABLE(dr)) |
| 1126 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1127 | | SET_NZCV_16(s1rval, s2rval, res); |
| 1128 | | } |
| 1129 | | } |
| 1130 | | |
| 1131 | | |
| 1132 | | void dsp32c_device::mul2_s(UINT32 op) |
| 1133 | | { |
| 1134 | | if (CONDITION_IS_TRUE()) |
| 1135 | | { |
| 1136 | | int dr = (op >> 16) & 0x1f; |
| 1137 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1138 | | int res = s1rval * 2; |
| 1139 | | if (IS_WRITEABLE(dr)) |
| 1140 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1141 | | SET_NZCV_16(s1rval, 0, res); |
| 1142 | | } |
| 1143 | | } |
| 1144 | | |
| 1145 | | |
| 1146 | | void dsp32c_device::subr_ss(UINT32 op) |
| 1147 | | { |
| 1148 | | if (CONDITION_IS_TRUE()) |
| 1149 | | { |
| 1150 | | int dr = (op >> 16) & 0x1f; |
| 1151 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1152 | | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1153 | | int res = s1rval - s2rval; |
| 1154 | | if (IS_WRITEABLE(dr)) |
| 1155 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1156 | | SET_NZCV_16(s1rval, s2rval, res); |
| 1157 | | } |
| 1158 | | } |
| 1159 | | |
| 1160 | | |
| 1161 | | void dsp32c_device::addr_ss(UINT32 op) |
| 1162 | | { |
| 1163 | | unimplemented(op); |
| 1164 | | } |
| 1165 | | |
| 1166 | | |
| 1167 | | void dsp32c_device::sub_ss(UINT32 op) |
| 1168 | | { |
| 1169 | | if (CONDITION_IS_TRUE()) |
| 1170 | | { |
| 1171 | | int dr = (op >> 16) & 0x1f; |
| 1172 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1173 | | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1174 | | int res = s2rval - s1rval; |
| 1175 | | if (IS_WRITEABLE(dr)) |
| 1176 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1177 | | SET_NZCV_16(s1rval, s2rval, res); |
| 1178 | | } |
| 1179 | | } |
| 1180 | | |
| 1181 | | |
| 1182 | | void dsp32c_device::neg_s(UINT32 op) |
| 1183 | | { |
| 1184 | | if (CONDITION_IS_TRUE()) |
| 1185 | | { |
| 1186 | | int dr = (op >> 16) & 0x1f; |
| 1187 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1188 | | int res = -s1rval; |
| 1189 | | if (IS_WRITEABLE(dr)) |
| 1190 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1191 | | SET_NZCV_16(s1rval, 0, res); |
| 1192 | | } |
| 1193 | | } |
| 1194 | | |
| 1195 | | |
| 1196 | | void dsp32c_device::andc_ss(UINT32 op) |
| 1197 | | { |
| 1198 | | if (CONDITION_IS_TRUE()) |
| 1199 | | { |
| 1200 | | int dr = (op >> 16) & 0x1f; |
| 1201 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1202 | | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1203 | | int res = s2rval & ~s1rval; |
| 1204 | | if (IS_WRITEABLE(dr)) |
| 1205 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1206 | | SET_NZ00_16(res); |
| 1207 | | } |
| 1208 | | } |
| 1209 | | |
| 1210 | | |
| 1211 | | void dsp32c_device::cmp_ss(UINT32 op) |
| 1212 | | { |
| 1213 | | if (CONDITION_IS_TRUE()) |
| 1214 | | { |
| 1215 | | int drval = REG16((op >> 16) & 0x1f); |
| 1216 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1217 | | int res = drval - s1rval; |
| 1218 | | SET_NZCV_16(drval, s1rval, res); |
| 1219 | | } |
| 1220 | | } |
| 1221 | | |
| 1222 | | |
| 1223 | | void dsp32c_device::xor_ss(UINT32 op) |
| 1224 | | { |
| 1225 | | if (CONDITION_IS_TRUE()) |
| 1226 | | { |
| 1227 | | int dr = (op >> 16) & 0x1f; |
| 1228 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1229 | | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1230 | | int res = s2rval ^ s1rval; |
| 1231 | | if (IS_WRITEABLE(dr)) |
| 1232 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1233 | | SET_NZ00_16(res); |
| 1234 | | } |
| 1235 | | } |
| 1236 | | |
| 1237 | | |
| 1238 | | void dsp32c_device::rcr_s(UINT32 op) |
| 1239 | | { |
| 1240 | | if (CONDITION_IS_TRUE()) |
| 1241 | | { |
| 1242 | | int dr = (op >> 16) & 0x1f; |
| 1243 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1244 | | int res = ((m_nzcflags >> 9) & 0x8000) | (s1rval >> 1); |
| 1245 | | if (IS_WRITEABLE(dr)) |
| 1246 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1247 | | m_nzcflags = ((res & 0xffff) << 8) | ((s1rval & 1) << 24); |
| 1248 | | m_vflags = 0; |
| 1249 | | } |
| 1250 | | } |
| 1251 | | |
| 1252 | | |
| 1253 | | void dsp32c_device::or_ss(UINT32 op) |
| 1254 | | { |
| 1255 | | if (CONDITION_IS_TRUE()) |
| 1256 | | { |
| 1257 | | int dr = (op >> 16) & 0x1f; |
| 1258 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1259 | | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1260 | | int res = s2rval | s1rval; |
| 1261 | | if (IS_WRITEABLE(dr)) |
| 1262 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1263 | | SET_NZ00_16(res); |
| 1264 | | } |
| 1265 | | } |
| 1266 | | |
| 1267 | | |
| 1268 | | void dsp32c_device::rcl_s(UINT32 op) |
| 1269 | | { |
| 1270 | | if (CONDITION_IS_TRUE()) |
| 1271 | | { |
| 1272 | | int dr = (op >> 16) & 0x1f; |
| 1273 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1274 | | int res = ((m_nzcflags >> 24) & 0x0001) | (s1rval << 1); |
| 1275 | | if (IS_WRITEABLE(dr)) |
| 1276 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1277 | | m_nzcflags = ((res & 0xffff) << 8) | ((s1rval & 0x8000) << 9); |
| 1278 | | m_vflags = 0; |
| 1279 | | } |
| 1280 | | } |
| 1281 | | |
| 1282 | | |
| 1283 | | void dsp32c_device::shr_s(UINT32 op) |
| 1284 | | { |
| 1285 | | if (CONDITION_IS_TRUE()) |
| 1286 | | { |
| 1287 | | int dr = (op >> 16) & 0x1f; |
| 1288 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1289 | | int res = s1rval >> 1; |
| 1290 | | if (IS_WRITEABLE(dr)) |
| 1291 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1292 | | m_nzcflags = ((res & 0xffff) << 8) | ((s1rval & 1) << 24); |
| 1293 | | m_vflags = 0; |
| 1294 | | } |
| 1295 | | } |
| 1296 | | |
| 1297 | | |
| 1298 | | void dsp32c_device::div2_s(UINT32 op) |
| 1299 | | { |
| 1300 | | if (CONDITION_IS_TRUE()) |
| 1301 | | { |
| 1302 | | int dr = (op >> 16) & 0x1f; |
| 1303 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1304 | | int res = (s1rval & 0x8000) | (s1rval >> 1); |
| 1305 | | if (IS_WRITEABLE(dr)) |
| 1306 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1307 | | m_nzcflags = ((res & 0xffff) << 8) | ((s1rval & 1) << 24); |
| 1308 | | m_vflags = 0; |
| 1309 | | } |
| 1310 | | } |
| 1311 | | |
| 1312 | | |
| 1313 | | void dsp32c_device::and_ss(UINT32 op) |
| 1314 | | { |
| 1315 | | if (CONDITION_IS_TRUE()) |
| 1316 | | { |
| 1317 | | int dr = (op >> 16) & 0x1f; |
| 1318 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1319 | | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1320 | | int res = s2rval & s1rval; |
| 1321 | | if (IS_WRITEABLE(dr)) |
| 1322 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1323 | | SET_NZ00_16(res); |
| 1324 | | } |
| 1325 | | } |
| 1326 | | |
| 1327 | | |
| 1328 | | void dsp32c_device::test_ss(UINT32 op) |
| 1329 | | { |
| 1330 | | if (CONDITION_IS_TRUE()) |
| 1331 | | { |
| 1332 | | int drval = REG16((op >> 16) & 0x1f); |
| 1333 | | int s1rval = REG16((op >> 5) & 0x1f); |
| 1334 | | int res = drval & s1rval; |
| 1335 | | SET_NZ00_16(res); |
| 1336 | | } |
| 1337 | | } |
| 1338 | | |
| 1339 | | |
| 1340 | | void dsp32c_device::add_di(UINT32 op) |
| 1341 | | { |
| 1342 | | int dr = (op >> 16) & 0x1f; |
| 1343 | | int drval = REG16(dr); |
| 1344 | | int res = drval + (UINT16)op; |
| 1345 | | if (IS_WRITEABLE(dr)) |
| 1346 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1347 | | SET_NZCV_16(drval, op, res); |
| 1348 | | } |
| 1349 | | |
| 1350 | | |
| 1351 | | void dsp32c_device::subr_di(UINT32 op) |
| 1352 | | { |
| 1353 | | int dr = (op >> 16) & 0x1f; |
| 1354 | | int drval = REG16(dr); |
| 1355 | | int res = (UINT16)op - drval; |
| 1356 | | if (IS_WRITEABLE(dr)) |
| 1357 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1358 | | SET_NZCV_16(drval, op, res); |
| 1359 | | } |
| 1360 | | |
| 1361 | | |
| 1362 | | void dsp32c_device::addr_di(UINT32 op) |
| 1363 | | { |
| 1364 | | unimplemented(op); |
| 1365 | | } |
| 1366 | | |
| 1367 | | |
| 1368 | | void dsp32c_device::sub_di(UINT32 op) |
| 1369 | | { |
| 1370 | | int dr = (op >> 16) & 0x1f; |
| 1371 | | int drval = REG16(dr); |
| 1372 | | int res = drval - (UINT16)op; |
| 1373 | | if (IS_WRITEABLE(dr)) |
| 1374 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1375 | | SET_NZCV_16(drval, op, res); |
| 1376 | | } |
| 1377 | | |
| 1378 | | |
| 1379 | | void dsp32c_device::andc_di(UINT32 op) |
| 1380 | | { |
| 1381 | | int dr = (op >> 16) & 0x1f; |
| 1382 | | int drval = REG16(dr); |
| 1383 | | int res = drval & ~(UINT16)op; |
| 1384 | | if (IS_WRITEABLE(dr)) |
| 1385 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1386 | | SET_NZ00_16(res); |
| 1387 | | } |
| 1388 | | |
| 1389 | | |
| 1390 | | void dsp32c_device::cmp_di(UINT32 op) |
| 1391 | | { |
| 1392 | | int drval = REG16((op >> 16) & 0x1f); |
| 1393 | | int res = drval - (UINT16)op; |
| 1394 | | SET_NZCV_16(drval, op, res); |
| 1395 | | } |
| 1396 | | |
| 1397 | | |
| 1398 | | void dsp32c_device::xor_di(UINT32 op) |
| 1399 | | { |
| 1400 | | int dr = (op >> 16) & 0x1f; |
| 1401 | | int drval = REG16(dr); |
| 1402 | | int res = drval ^ (UINT16)op; |
| 1403 | | if (IS_WRITEABLE(dr)) |
| 1404 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1405 | | SET_NZ00_16(res); |
| 1406 | | } |
| 1407 | | |
| 1408 | | |
| 1409 | | void dsp32c_device::or_di(UINT32 op) |
| 1410 | | { |
| 1411 | | int dr = (op >> 16) & 0x1f; |
| 1412 | | int drval = REG16(dr); |
| 1413 | | int res = drval | (UINT16)op; |
| 1414 | | if (IS_WRITEABLE(dr)) |
| 1415 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1416 | | SET_NZ00_16(res); |
| 1417 | | } |
| 1418 | | |
| 1419 | | |
| 1420 | | void dsp32c_device::and_di(UINT32 op) |
| 1421 | | { |
| 1422 | | int dr = (op >> 16) & 0x1f; |
| 1423 | | int drval = REG16(dr); |
| 1424 | | int res = drval & (UINT16)op; |
| 1425 | | if (IS_WRITEABLE(dr)) |
| 1426 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1427 | | SET_NZ00_16(res); |
| 1428 | | } |
| 1429 | | |
| 1430 | | |
| 1431 | | void dsp32c_device::test_di(UINT32 op) |
| 1432 | | { |
| 1433 | | int drval = REG16((op >> 16) & 0x1f); |
| 1434 | | int res = drval & (UINT16)op; |
| 1435 | | SET_NZ00_16(res); |
| 1436 | | } |
| 1437 | | |
| 1438 | | |
| 1439 | | |
| 1440 | | //************************************************************************** |
| 1441 | | // CAU 24-BIT ARITHMETIC IMPLEMENTATION |
| 1442 | | //************************************************************************** |
| 1443 | | |
| 1444 | | void dsp32c_device::adde_si(UINT32 op) |
| 1445 | | { |
| 1446 | | int dr = (op >> 21) & 0x1f; |
| 1447 | | int hrval = REG24((op >> 16) & 0x1f); |
| 1448 | | int res = hrval + EXTEND16_TO_24(op); |
| 1449 | | if (IS_WRITEABLE(dr)) |
| 1450 | | m_r[dr] = TRUNCATE24(res); |
| 1451 | | SET_NZCV_24(hrval, op << 8, res); |
| 1452 | | } |
| 1453 | | |
| 1454 | | |
| 1455 | | void dsp32c_device::adde_ss(UINT32 op) |
| 1456 | | { |
| 1457 | | if (CONDITION_IS_TRUE()) |
| 1458 | | { |
| 1459 | | int dr = (op >> 16) & 0x1f; |
| 1460 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1461 | | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1462 | | int res = s2rval + s1rval; |
| 1463 | | if (IS_WRITEABLE(dr)) |
| 1464 | | m_r[dr] = TRUNCATE24(res); |
| 1465 | | SET_NZCV_24(s1rval, s2rval, res); |
| 1466 | | } |
| 1467 | | } |
| 1468 | | |
| 1469 | | |
| 1470 | | void dsp32c_device::mul2e_s(UINT32 op) |
| 1471 | | { |
| 1472 | | if (CONDITION_IS_TRUE()) |
| 1473 | | { |
| 1474 | | int dr = (op >> 16) & 0x1f; |
| 1475 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1476 | | int res = s1rval * 2; |
| 1477 | | if (IS_WRITEABLE(dr)) |
| 1478 | | m_r[dr] = TRUNCATE24(res); |
| 1479 | | SET_NZCV_24(s1rval, 0, res); |
| 1480 | | } |
| 1481 | | } |
| 1482 | | |
| 1483 | | |
| 1484 | | void dsp32c_device::subre_ss(UINT32 op) |
| 1485 | | { |
| 1486 | | if (CONDITION_IS_TRUE()) |
| 1487 | | { |
| 1488 | | int dr = (op >> 16) & 0x1f; |
| 1489 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1490 | | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1491 | | int res = s1rval - s2rval; |
| 1492 | | if (IS_WRITEABLE(dr)) |
| 1493 | | m_r[dr] = TRUNCATE24(res); |
| 1494 | | SET_NZCV_24(s1rval, s2rval, res); |
| 1495 | | } |
| 1496 | | } |
| 1497 | | |
| 1498 | | |
| 1499 | | void dsp32c_device::addre_ss(UINT32 op) |
| 1500 | | { |
| 1501 | | unimplemented(op); |
| 1502 | | } |
| 1503 | | |
| 1504 | | |
| 1505 | | void dsp32c_device::sube_ss(UINT32 op) |
| 1506 | | { |
| 1507 | | if (CONDITION_IS_TRUE()) |
| 1508 | | { |
| 1509 | | int dr = (op >> 16) & 0x1f; |
| 1510 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1511 | | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1512 | | int res = s2rval - s1rval; |
| 1513 | | if (IS_WRITEABLE(dr)) |
| 1514 | | m_r[dr] = TRUNCATE24(res); |
| 1515 | | SET_NZCV_24(s1rval, s2rval, res); |
| 1516 | | } |
| 1517 | | } |
| 1518 | | |
| 1519 | | |
| 1520 | | void dsp32c_device::nege_s(UINT32 op) |
| 1521 | | { |
| 1522 | | if (CONDITION_IS_TRUE()) |
| 1523 | | { |
| 1524 | | int dr = (op >> 16) & 0x1f; |
| 1525 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1526 | | int res = -s1rval; |
| 1527 | | if (IS_WRITEABLE(dr)) |
| 1528 | | m_r[dr] = TRUNCATE24(res); |
| 1529 | | SET_NZCV_24(s1rval, 0, res); |
| 1530 | | } |
| 1531 | | } |
| 1532 | | |
| 1533 | | |
| 1534 | | void dsp32c_device::andce_ss(UINT32 op) |
| 1535 | | { |
| 1536 | | if (CONDITION_IS_TRUE()) |
| 1537 | | { |
| 1538 | | int dr = (op >> 16) & 0x1f; |
| 1539 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1540 | | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1541 | | int res = s2rval & ~s1rval; |
| 1542 | | if (IS_WRITEABLE(dr)) |
| 1543 | | m_r[dr] = res; |
| 1544 | | SET_NZ00_24(res); |
| 1545 | | } |
| 1546 | | } |
| 1547 | | |
| 1548 | | |
| 1549 | | void dsp32c_device::cmpe_ss(UINT32 op) |
| 1550 | | { |
| 1551 | | if (CONDITION_IS_TRUE()) |
| 1552 | | { |
| 1553 | | int drval = REG24((op >> 16) & 0x1f); |
| 1554 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1555 | | int res = drval - s1rval; |
| 1556 | | SET_NZCV_24(drval, s1rval, res); |
| 1557 | | } |
| 1558 | | } |
| 1559 | | |
| 1560 | | |
| 1561 | | void dsp32c_device::xore_ss(UINT32 op) |
| 1562 | | { |
| 1563 | | if (CONDITION_IS_TRUE()) |
| 1564 | | { |
| 1565 | | int dr = (op >> 16) & 0x1f; |
| 1566 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1567 | | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1568 | | int res = s2rval ^ s1rval; |
| 1569 | | if (IS_WRITEABLE(dr)) |
| 1570 | | m_r[dr] = res; |
| 1571 | | SET_NZ00_24(res); |
| 1572 | | } |
| 1573 | | } |
| 1574 | | |
| 1575 | | |
| 1576 | | void dsp32c_device::rcre_s(UINT32 op) |
| 1577 | | { |
| 1578 | | if (CONDITION_IS_TRUE()) |
| 1579 | | { |
| 1580 | | int dr = (op >> 16) & 0x1f; |
| 1581 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1582 | | int res = ((m_nzcflags >> 1) & 0x800000) | (s1rval >> 1); |
| 1583 | | if (IS_WRITEABLE(dr)) |
| 1584 | | m_r[dr] = TRUNCATE24(res); |
| 1585 | | m_nzcflags = res | ((s1rval & 1) << 24); |
| 1586 | | m_vflags = 0; |
| 1587 | | } |
| 1588 | | } |
| 1589 | | |
| 1590 | | |
| 1591 | | void dsp32c_device::ore_ss(UINT32 op) |
| 1592 | | { |
| 1593 | | if (CONDITION_IS_TRUE()) |
| 1594 | | { |
| 1595 | | int dr = (op >> 16) & 0x1f; |
| 1596 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1597 | | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1598 | | int res = s2rval | s1rval; |
| 1599 | | if (IS_WRITEABLE(dr)) |
| 1600 | | m_r[dr] = res; |
| 1601 | | SET_NZ00_24(res); |
| 1602 | | } |
| 1603 | | } |
| 1604 | | |
| 1605 | | |
| 1606 | | void dsp32c_device::rcle_s(UINT32 op) |
| 1607 | | { |
| 1608 | | if (CONDITION_IS_TRUE()) |
| 1609 | | { |
| 1610 | | int dr = (op >> 16) & 0x1f; |
| 1611 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1612 | | int res = ((m_nzcflags >> 24) & 0x000001) | (s1rval << 1); |
| 1613 | | if (IS_WRITEABLE(dr)) |
| 1614 | | m_r[dr] = TRUNCATE24(res); |
| 1615 | | m_nzcflags = res | ((s1rval & 0x800000) << 1); |
| 1616 | | m_vflags = 0; |
| 1617 | | } |
| 1618 | | } |
| 1619 | | |
| 1620 | | |
| 1621 | | void dsp32c_device::shre_s(UINT32 op) |
| 1622 | | { |
| 1623 | | if (CONDITION_IS_TRUE()) |
| 1624 | | { |
| 1625 | | int dr = (op >> 16) & 0x1f; |
| 1626 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1627 | | int res = s1rval >> 1; |
| 1628 | | if (IS_WRITEABLE(dr)) |
| 1629 | | m_r[dr] = res; |
| 1630 | | m_nzcflags = res | ((s1rval & 1) << 24); |
| 1631 | | m_vflags = 0; |
| 1632 | | } |
| 1633 | | } |
| 1634 | | |
| 1635 | | |
| 1636 | | void dsp32c_device::div2e_s(UINT32 op) |
| 1637 | | { |
| 1638 | | if (CONDITION_IS_TRUE()) |
| 1639 | | { |
| 1640 | | int dr = (op >> 16) & 0x1f; |
| 1641 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1642 | | int res = (s1rval & 0x800000) | (s1rval >> 1); |
| 1643 | | if (IS_WRITEABLE(dr)) |
| 1644 | | m_r[dr] = TRUNCATE24(res); |
| 1645 | | m_nzcflags = res | ((s1rval & 1) << 24); |
| 1646 | | m_vflags = 0; |
| 1647 | | } |
| 1648 | | } |
| 1649 | | |
| 1650 | | |
| 1651 | | void dsp32c_device::ande_ss(UINT32 op) |
| 1652 | | { |
| 1653 | | if (CONDITION_IS_TRUE()) |
| 1654 | | { |
| 1655 | | int dr = (op >> 16) & 0x1f; |
| 1656 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1657 | | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1658 | | int res = s2rval & s1rval; |
| 1659 | | if (IS_WRITEABLE(dr)) |
| 1660 | | m_r[dr] = res; |
| 1661 | | SET_NZ00_24(res); |
| 1662 | | } |
| 1663 | | } |
| 1664 | | |
| 1665 | | |
| 1666 | | void dsp32c_device::teste_ss(UINT32 op) |
| 1667 | | { |
| 1668 | | if (CONDITION_IS_TRUE()) |
| 1669 | | { |
| 1670 | | int drval = REG24((op >> 16) & 0x1f); |
| 1671 | | int s1rval = REG24((op >> 5) & 0x1f); |
| 1672 | | int res = drval & s1rval; |
| 1673 | | SET_NZ00_24(res); |
| 1674 | | } |
| 1675 | | } |
| 1676 | | |
| 1677 | | |
| 1678 | | void dsp32c_device::adde_di(UINT32 op) |
| 1679 | | { |
| 1680 | | int dr = (op >> 16) & 0x1f; |
| 1681 | | int drval = REG24(dr); |
| 1682 | | int res = drval + EXTEND16_TO_24(op); |
| 1683 | | if (IS_WRITEABLE(dr)) |
| 1684 | | m_r[dr] = TRUNCATE24(res); |
| 1685 | | SET_NZCV_24(drval, op << 8, res); |
| 1686 | | } |
| 1687 | | |
| 1688 | | |
| 1689 | | void dsp32c_device::subre_di(UINT32 op) |
| 1690 | | { |
| 1691 | | int dr = (op >> 16) & 0x1f; |
| 1692 | | int drval = REG24(dr); |
| 1693 | | int res = EXTEND16_TO_24(op) - drval; |
| 1694 | | if (IS_WRITEABLE(dr)) |
| 1695 | | m_r[dr] = TRUNCATE24(res); |
| 1696 | | SET_NZCV_24(drval, op << 8, res); |
| 1697 | | } |
| 1698 | | |
| 1699 | | |
| 1700 | | void dsp32c_device::addre_di(UINT32 op) |
| 1701 | | { |
| 1702 | | unimplemented(op); |
| 1703 | | } |
| 1704 | | |
| 1705 | | |
| 1706 | | void dsp32c_device::sube_di(UINT32 op) |
| 1707 | | { |
| 1708 | | int dr = (op >> 16) & 0x1f; |
| 1709 | | int drval = REG24(dr); |
| 1710 | | int res = drval - EXTEND16_TO_24(op); |
| 1711 | | if (IS_WRITEABLE(dr)) |
| 1712 | | m_r[dr] = TRUNCATE24(res); |
| 1713 | | SET_NZCV_24(drval, op << 8, res); |
| 1714 | | } |
| 1715 | | |
| 1716 | | |
| 1717 | | void dsp32c_device::andce_di(UINT32 op) |
| 1718 | | { |
| 1719 | | int dr = (op >> 16) & 0x1f; |
| 1720 | | int drval = REG24(dr); |
| 1721 | | int res = drval & ~EXTEND16_TO_24(op); |
| 1722 | | if (IS_WRITEABLE(dr)) |
| 1723 | | m_r[dr] = res; |
| 1724 | | SET_NZ00_24(res); |
| 1725 | | } |
| 1726 | | |
| 1727 | | |
| 1728 | | void dsp32c_device::cmpe_di(UINT32 op) |
| 1729 | | { |
| 1730 | | int drval = REG24((op >> 16) & 0x1f); |
| 1731 | | int res = drval - EXTEND16_TO_24(op); |
| 1732 | | SET_NZCV_24(drval, op << 8, res); |
| 1733 | | } |
| 1734 | | |
| 1735 | | |
| 1736 | | void dsp32c_device::xore_di(UINT32 op) |
| 1737 | | { |
| 1738 | | int dr = (op >> 16) & 0x1f; |
| 1739 | | int drval = REG24(dr); |
| 1740 | | int res = drval ^ EXTEND16_TO_24(op); |
| 1741 | | if (IS_WRITEABLE(dr)) |
| 1742 | | m_r[dr] = res; |
| 1743 | | SET_NZ00_24(res); |
| 1744 | | } |
| 1745 | | |
| 1746 | | |
| 1747 | | void dsp32c_device::ore_di(UINT32 op) |
| 1748 | | { |
| 1749 | | int dr = (op >> 16) & 0x1f; |
| 1750 | | int drval = REG24(dr); |
| 1751 | | int res = drval | EXTEND16_TO_24(op); |
| 1752 | | if (IS_WRITEABLE(dr)) |
| 1753 | | m_r[dr] = res; |
| 1754 | | SET_NZ00_24(res); |
| 1755 | | } |
| 1756 | | |
| 1757 | | |
| 1758 | | void dsp32c_device::ande_di(UINT32 op) |
| 1759 | | { |
| 1760 | | int dr = (op >> 16) & 0x1f; |
| 1761 | | int drval = REG24(dr); |
| 1762 | | int res = drval & EXTEND16_TO_24(op); |
| 1763 | | if (IS_WRITEABLE(dr)) |
| 1764 | | m_r[dr] = res; |
| 1765 | | SET_NZ00_24(res); |
| 1766 | | } |
| 1767 | | |
| 1768 | | |
| 1769 | | void dsp32c_device::teste_di(UINT32 op) |
| 1770 | | { |
| 1771 | | int drval = REG24((op >> 16) & 0x1f); |
| 1772 | | int res = drval & EXTEND16_TO_24(op); |
| 1773 | | SET_NZ00_24(res); |
| 1774 | | } |
| 1775 | | |
| 1776 | | |
| 1777 | | |
| 1778 | | //************************************************************************** |
| 1779 | | // CAU LOAD/STORE IMPLEMENTATION |
| 1780 | | //************************************************************************** |
| 1781 | | |
| 1782 | | void dsp32c_device::load_hi(UINT32 op) |
| 1783 | | { |
| 1784 | | int dr = (op >> 16) & 0x1f; |
| 1785 | | UINT32 res = RBYTE(EXTEND16_TO_24(op)); |
| 1786 | | if (IS_WRITEABLE(dr)) |
| 1787 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1788 | | m_nzcflags = res << 8; |
| 1789 | | m_vflags = 0; |
| 1790 | | } |
| 1791 | | |
| 1792 | | |
| 1793 | | void dsp32c_device::load_li(UINT32 op) |
| 1794 | | { |
| 1795 | | int dr = (op >> 16) & 0x1f; |
| 1796 | | UINT32 res = RBYTE(EXTEND16_TO_24(op)); |
| 1797 | | if (IS_WRITEABLE(dr)) |
| 1798 | | m_r[dr] = res; |
| 1799 | | m_nzcflags = res << 8; |
| 1800 | | m_vflags = 0; |
| 1801 | | } |
| 1802 | | |
| 1803 | | |
| 1804 | | void dsp32c_device::load_i(UINT32 op) |
| 1805 | | { |
| 1806 | | UINT32 res = RWORD(EXTEND16_TO_24(op)); |
| 1807 | | int dr = (op >> 16) & 0x1f; |
| 1808 | | if (IS_WRITEABLE(dr)) |
| 1809 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1810 | | m_nzcflags = res << 8; |
| 1811 | | m_vflags = 0; |
| 1812 | | } |
| 1813 | | |
| 1814 | | |
| 1815 | | void dsp32c_device::load_ei(UINT32 op) |
| 1816 | | { |
| 1817 | | UINT32 res = TRUNCATE24(RLONG(EXTEND16_TO_24(op))); |
| 1818 | | int dr = (op >> 16) & 0x1f; |
| 1819 | | if (IS_WRITEABLE(dr)) |
| 1820 | | m_r[dr] = res; |
| 1821 | | m_nzcflags = res; |
| 1822 | | m_vflags = 0; |
| 1823 | | } |
| 1824 | | |
| 1825 | | |
| 1826 | | void dsp32c_device::store_hi(UINT32 op) |
| 1827 | | { |
| 1828 | | WBYTE(EXTEND16_TO_24(op), m_r[(op >> 16) & 0x1f] >> 8); |
| 1829 | | } |
| 1830 | | |
| 1831 | | |
| 1832 | | void dsp32c_device::store_li(UINT32 op) |
| 1833 | | { |
| 1834 | | WBYTE(EXTEND16_TO_24(op), m_r[(op >> 16) & 0x1f]); |
| 1835 | | } |
| 1836 | | |
| 1837 | | |
| 1838 | | void dsp32c_device::store_i(UINT32 op) |
| 1839 | | { |
| 1840 | | WWORD(EXTEND16_TO_24(op), REG16((op >> 16) & 0x1f)); |
| 1841 | | } |
| 1842 | | |
| 1843 | | |
| 1844 | | void dsp32c_device::store_ei(UINT32 op) |
| 1845 | | { |
| 1846 | | WLONG(EXTEND16_TO_24(op), (INT32)(REG24((op >> 16) & 0x1f) << 8) >> 8); |
| 1847 | | } |
| 1848 | | |
| 1849 | | |
| 1850 | | void dsp32c_device::load_hr(UINT32 op) |
| 1851 | | { |
| 1852 | | if (!(op & 0x400)) |
| 1853 | | { |
| 1854 | | int dr = (op >> 16) & 0x1f; |
| 1855 | | UINT32 res = cau_read_pi_1byte(op) << 8; |
| 1856 | | if (IS_WRITEABLE(dr)) |
| 1857 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1858 | | m_nzcflags = res << 8; |
| 1859 | | m_vflags = 0; |
| 1860 | | } |
| 1861 | | else |
| 1862 | | unimplemented(op); |
| 1863 | | } |
| 1864 | | |
| 1865 | | |
| 1866 | | void dsp32c_device::load_lr(UINT32 op) |
| 1867 | | { |
| 1868 | | if (!(op & 0x400)) |
| 1869 | | { |
| 1870 | | int dr = (op >> 16) & 0x1f; |
| 1871 | | UINT32 res = cau_read_pi_1byte(op); |
| 1872 | | if (IS_WRITEABLE(dr)) |
| 1873 | | m_r[dr] = res; |
| 1874 | | m_nzcflags = res << 8; |
| 1875 | | m_vflags = 0; |
| 1876 | | } |
| 1877 | | else |
| 1878 | | unimplemented(op); |
| 1879 | | } |
| 1880 | | |
| 1881 | | |
| 1882 | | void dsp32c_device::load_r(UINT32 op) |
| 1883 | | { |
| 1884 | | if (!(op & 0x400)) |
| 1885 | | { |
| 1886 | | UINT32 res = cau_read_pi_2byte(op); |
| 1887 | | int dr = (op >> 16) & 0x1f; |
| 1888 | | if (IS_WRITEABLE(dr)) |
| 1889 | | m_r[dr] = EXTEND16_TO_24(res); |
| 1890 | | m_nzcflags = res << 8; |
| 1891 | | m_vflags = 0; |
| 1892 | | } |
| 1893 | | else |
| 1894 | | unimplemented(op); |
| 1895 | | } |
| 1896 | | |
| 1897 | | |
| 1898 | | void dsp32c_device::load_er(UINT32 op) |
| 1899 | | { |
| 1900 | | if (!(op & 0x400)) |
| 1901 | | { |
| 1902 | | UINT32 res = TRUNCATE24(cau_read_pi_4byte(op)); |
| 1903 | | int dr = (op >> 16) & 0x1f; |
| 1904 | | if (IS_WRITEABLE(dr)) |
| 1905 | | m_r[dr] = res; |
| 1906 | | m_nzcflags = res; |
| 1907 | | m_vflags = 0; |
| 1908 | | } |
| 1909 | | else |
| 1910 | | unimplemented(op); |
| 1911 | | } |
| 1912 | | |
| 1913 | | |
| 1914 | | void dsp32c_device::store_hr(UINT32 op) |
| 1915 | | { |
| 1916 | | if (!(op & 0x400)) |
| 1917 | | cau_write_pi_1byte(op, m_r[(op >> 16) & 0x1f] >> 8); |
| 1918 | | else |
| 1919 | | unimplemented(op); |
| 1920 | | } |
| 1921 | | |
| 1922 | | |
| 1923 | | void dsp32c_device::store_lr(UINT32 op) |
| 1924 | | { |
| 1925 | | if (!(op & 0x400)) |
| 1926 | | cau_write_pi_1byte(op, m_r[(op >> 16) & 0x1f]); |
| 1927 | | else |
| 1928 | | unimplemented(op); |
| 1929 | | } |
| 1930 | | |
| 1931 | | |
| 1932 | | void dsp32c_device::store_r(UINT32 op) |
| 1933 | | { |
| 1934 | | if (!(op & 0x400)) |
| 1935 | | cau_write_pi_2byte(op, REG16((op >> 16) & 0x1f)); |
| 1936 | | else |
| 1937 | | unimplemented(op); |
| 1938 | | } |
| 1939 | | |
| 1940 | | |
| 1941 | | void dsp32c_device::store_er(UINT32 op) |
| 1942 | | { |
| 1943 | | if (!(op & 0x400)) |
| 1944 | | cau_write_pi_4byte(op, REG24((op >> 16) & 0x1f)); |
| 1945 | | else |
| 1946 | | unimplemented(op); |
| 1947 | | } |
| 1948 | | |
| 1949 | | |
| 1950 | | void dsp32c_device::load24(UINT32 op) |
| 1951 | | { |
| 1952 | | int dr = (op >> 16) & 0x1f; |
| 1953 | | UINT32 res = (op & 0xffff) + ((op >> 5) & 0xff0000); |
| 1954 | | if (IS_WRITEABLE(dr)) |
| 1955 | | m_r[dr] = res; |
| 1956 | | } |
| 1957 | | |
| 1958 | | |
| 1959 | | |
| 1960 | | //************************************************************************** |
| 1961 | | // DAU FORM 1 IMPLEMENTATION |
| 1962 | | //************************************************************************** |
| 1963 | | |
| 1964 | | void dsp32c_device::d1_aMpp(UINT32 op) |
| 1965 | | { |
| 1966 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 1967 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 1968 | | double res = yval + DEFERRED_MULTIPLIER((op >> 26) & 7) * xval; |
| 1969 | | int zpi = (op >> 0) & 0x7f; |
| 1970 | | if (zpi != 7) |
| 1971 | | dau_write_pi_double(zpi, res); |
| 1972 | | dau_set_val_flags((op >> 21) & 3, res); |
| 1973 | | } |
| 1974 | | |
| 1975 | | |
| 1976 | | void dsp32c_device::d1_aMpm(UINT32 op) |
| 1977 | | { |
| 1978 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 1979 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 1980 | | double res = yval - DEFERRED_MULTIPLIER((op >> 26) & 7) * xval; |
| 1981 | | int zpi = (op >> 0) & 0x7f; |
| 1982 | | if (zpi != 7) |
| 1983 | | dau_write_pi_double(zpi, res); |
| 1984 | | dau_set_val_flags((op >> 21) & 3, res); |
| 1985 | | } |
| 1986 | | |
| 1987 | | |
| 1988 | | void dsp32c_device::d1_aMmp(UINT32 op) |
| 1989 | | { |
| 1990 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 1991 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 1992 | | double res = -yval + DEFERRED_MULTIPLIER((op >> 26) & 7) * xval; |
| 1993 | | int zpi = (op >> 0) & 0x7f; |
| 1994 | | if (zpi != 7) |
| 1995 | | dau_write_pi_double(zpi, res); |
| 1996 | | dau_set_val_flags((op >> 21) & 3, res); |
| 1997 | | } |
| 1998 | | |
| 1999 | | |
| 2000 | | void dsp32c_device::d1_aMmm(UINT32 op) |
| 2001 | | { |
| 2002 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2003 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2004 | | double res = -yval - DEFERRED_MULTIPLIER((op >> 26) & 7) * xval; |
| 2005 | | int zpi = (op >> 0) & 0x7f; |
| 2006 | | if (zpi != 7) |
| 2007 | | dau_write_pi_double(zpi, res); |
| 2008 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2009 | | } |
| 2010 | | |
| 2011 | | |
| 2012 | | void dsp32c_device::d1_0px(UINT32 op) |
| 2013 | | { |
| 2014 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2015 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2016 | | double res = yval; |
| 2017 | | int zpi = (op >> 0) & 0x7f; |
| 2018 | | if (zpi != 7) |
| 2019 | | dau_write_pi_double(zpi, res); |
| 2020 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2021 | | (void)xval; |
| 2022 | | } |
| 2023 | | |
| 2024 | | |
| 2025 | | void dsp32c_device::d1_0mx(UINT32 op) |
| 2026 | | { |
| 2027 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2028 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2029 | | double res = -yval; |
| 2030 | | int zpi = (op >> 0) & 0x7f; |
| 2031 | | if (zpi != 7) |
| 2032 | | dau_write_pi_double(zpi, res); |
| 2033 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2034 | | (void)xval; |
| 2035 | | } |
| 2036 | | |
| 2037 | | |
| 2038 | | void dsp32c_device::d1_1pp(UINT32 op) |
| 2039 | | { |
| 2040 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2041 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2042 | | double res = yval + xval; |
| 2043 | | int zpi = (op >> 0) & 0x7f; |
| 2044 | | if (zpi != 7) |
| 2045 | | dau_write_pi_double(zpi, res); |
| 2046 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2047 | | } |
| 2048 | | |
| 2049 | | |
| 2050 | | void dsp32c_device::d1_1pm(UINT32 op) |
| 2051 | | { |
| 2052 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2053 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2054 | | double res = yval - xval; |
| 2055 | | int zpi = (op >> 0) & 0x7f; |
| 2056 | | if (zpi != 7) |
| 2057 | | dau_write_pi_double(zpi, res); |
| 2058 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2059 | | } |
| 2060 | | |
| 2061 | | |
| 2062 | | void dsp32c_device::d1_1mp(UINT32 op) |
| 2063 | | { |
| 2064 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2065 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2066 | | double res = -yval + xval; |
| 2067 | | int zpi = (op >> 0) & 0x7f; |
| 2068 | | if (zpi != 7) |
| 2069 | | dau_write_pi_double(zpi, res); |
| 2070 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2071 | | } |
| 2072 | | |
| 2073 | | |
| 2074 | | void dsp32c_device::d1_1mm(UINT32 op) |
| 2075 | | { |
| 2076 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2077 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2078 | | double res = -yval - xval; |
| 2079 | | int zpi = (op >> 0) & 0x7f; |
| 2080 | | if (zpi != 7) |
| 2081 | | dau_write_pi_double(zpi, res); |
| 2082 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2083 | | } |
| 2084 | | |
| 2085 | | |
| 2086 | | void dsp32c_device::d1_aMppr(UINT32 op) |
| 2087 | | { |
| 2088 | | unimplemented(op); |
| 2089 | | } |
| 2090 | | |
| 2091 | | |
| 2092 | | void dsp32c_device::d1_aMpmr(UINT32 op) |
| 2093 | | { |
| 2094 | | unimplemented(op); |
| 2095 | | } |
| 2096 | | |
| 2097 | | |
| 2098 | | void dsp32c_device::d1_aMmpr(UINT32 op) |
| 2099 | | { |
| 2100 | | unimplemented(op); |
| 2101 | | } |
| 2102 | | |
| 2103 | | |
| 2104 | | void dsp32c_device::d1_aMmmr(UINT32 op) |
| 2105 | | { |
| 2106 | | unimplemented(op); |
| 2107 | | } |
| 2108 | | |
| 2109 | | |
| 2110 | | |
| 2111 | | //************************************************************************** |
| 2112 | | // DAU FORM 2 IMPLEMENTATION |
| 2113 | | //************************************************************************** |
| 2114 | | |
| 2115 | | void dsp32c_device::d2_aMpp(UINT32 op) |
| 2116 | | { |
| 2117 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2118 | | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2119 | | double res = m_a[(op >> 26) & 7] + yval * xval; |
| 2120 | | int zpi = (op >> 0) & 0x7f; |
| 2121 | | if (zpi != 7) |
| 2122 | | dau_write_pi_double(zpi, yval); |
| 2123 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2124 | | } |
| 2125 | | |
| 2126 | | |
| 2127 | | void dsp32c_device::d2_aMpm(UINT32 op) |
| 2128 | | { |
| 2129 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2130 | | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2131 | | double res = m_a[(op >> 26) & 7] - yval * xval; |
| 2132 | | int zpi = (op >> 0) & 0x7f; |
| 2133 | | if (zpi != 7) |
| 2134 | | dau_write_pi_double(zpi, yval); |
| 2135 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2136 | | } |
| 2137 | | |
| 2138 | | |
| 2139 | | void dsp32c_device::d2_aMmp(UINT32 op) |
| 2140 | | { |
| 2141 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2142 | | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2143 | | double res = -m_a[(op >> 26) & 7] + yval * xval; |
| 2144 | | int zpi = (op >> 0) & 0x7f; |
| 2145 | | if (zpi != 7) |
| 2146 | | dau_write_pi_double(zpi, yval); |
| 2147 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2148 | | } |
| 2149 | | |
| 2150 | | |
| 2151 | | void dsp32c_device::d2_aMmm(UINT32 op) |
| 2152 | | { |
| 2153 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2154 | | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2155 | | double res = -m_a[(op >> 26) & 7] - yval * xval; |
| 2156 | | int zpi = (op >> 0) & 0x7f; |
| 2157 | | if (zpi != 7) |
| 2158 | | dau_write_pi_double(zpi, yval); |
| 2159 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2160 | | } |
| 2161 | | |
| 2162 | | |
| 2163 | | void dsp32c_device::d2_aMppr(UINT32 op) |
| 2164 | | { |
| 2165 | | unimplemented(op); |
| 2166 | | } |
| 2167 | | |
| 2168 | | |
| 2169 | | void dsp32c_device::d2_aMpmr(UINT32 op) |
| 2170 | | { |
| 2171 | | unimplemented(op); |
| 2172 | | } |
| 2173 | | |
| 2174 | | |
| 2175 | | void dsp32c_device::d2_aMmpr(UINT32 op) |
| 2176 | | { |
| 2177 | | unimplemented(op); |
| 2178 | | } |
| 2179 | | |
| 2180 | | |
| 2181 | | void dsp32c_device::d2_aMmmr(UINT32 op) |
| 2182 | | { |
| 2183 | | unimplemented(op); |
| 2184 | | } |
| 2185 | | |
| 2186 | | |
| 2187 | | |
| 2188 | | //************************************************************************** |
| 2189 | | // DAU FORM 3 IMPLEMENTATION |
| 2190 | | //************************************************************************** |
| 2191 | | |
| 2192 | | void dsp32c_device::d3_aMpp(UINT32 op) |
| 2193 | | { |
| 2194 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2195 | | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2196 | | double res = m_a[(op >> 26) & 7] + yval * xval; |
| 2197 | | int zpi = (op >> 0) & 0x7f; |
| 2198 | | if (zpi != 7) |
| 2199 | | dau_write_pi_double(zpi, res); |
| 2200 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2201 | | } |
| 2202 | | |
| 2203 | | |
| 2204 | | void dsp32c_device::d3_aMpm(UINT32 op) |
| 2205 | | { |
| 2206 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2207 | | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2208 | | double res = m_a[(op >> 26) & 7] - yval * xval; |
| 2209 | | int zpi = (op >> 0) & 0x7f; |
| 2210 | | if (zpi != 7) |
| 2211 | | dau_write_pi_double(zpi, res); |
| 2212 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2213 | | } |
| 2214 | | |
| 2215 | | |
| 2216 | | void dsp32c_device::d3_aMmp(UINT32 op) |
| 2217 | | { |
| 2218 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2219 | | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2220 | | double res = -m_a[(op >> 26) & 7] + yval * xval; |
| 2221 | | int zpi = (op >> 0) & 0x7f; |
| 2222 | | if (zpi != 7) |
| 2223 | | dau_write_pi_double(zpi, res); |
| 2224 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2225 | | } |
| 2226 | | |
| 2227 | | |
| 2228 | | void dsp32c_device::d3_aMmm(UINT32 op) |
| 2229 | | { |
| 2230 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2231 | | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2232 | | double res = -m_a[(op >> 26) & 7] - yval * xval; |
| 2233 | | int zpi = (op >> 0) & 0x7f; |
| 2234 | | if (zpi != 7) |
| 2235 | | dau_write_pi_double(zpi, res); |
| 2236 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2237 | | } |
| 2238 | | |
| 2239 | | |
| 2240 | | void dsp32c_device::d3_aMppr(UINT32 op) |
| 2241 | | { |
| 2242 | | unimplemented(op); |
| 2243 | | } |
| 2244 | | |
| 2245 | | |
| 2246 | | void dsp32c_device::d3_aMpmr(UINT32 op) |
| 2247 | | { |
| 2248 | | unimplemented(op); |
| 2249 | | } |
| 2250 | | |
| 2251 | | |
| 2252 | | void dsp32c_device::d3_aMmpr(UINT32 op) |
| 2253 | | { |
| 2254 | | unimplemented(op); |
| 2255 | | } |
| 2256 | | |
| 2257 | | |
| 2258 | | void dsp32c_device::d3_aMmmr(UINT32 op) |
| 2259 | | { |
| 2260 | | unimplemented(op); |
| 2261 | | } |
| 2262 | | |
| 2263 | | |
| 2264 | | |
| 2265 | | //************************************************************************** |
| 2266 | | // DAU FORM 4 IMPLEMENTATION |
| 2267 | | //************************************************************************** |
| 2268 | | |
| 2269 | | void dsp32c_device::d4_pp(UINT32 op) |
| 2270 | | { |
| 2271 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2272 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2273 | | double res = yval + xval; |
| 2274 | | int zpi = (op >> 0) & 0x7f; |
| 2275 | | if (zpi != 7) |
| 2276 | | dau_write_pi_double(zpi, yval); |
| 2277 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2278 | | } |
| 2279 | | |
| 2280 | | |
| 2281 | | void dsp32c_device::d4_pm(UINT32 op) |
| 2282 | | { |
| 2283 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2284 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2285 | | double res = yval - xval; |
| 2286 | | int zpi = (op >> 0) & 0x7f; |
| 2287 | | if (zpi != 7) |
| 2288 | | dau_write_pi_double(zpi, yval); |
| 2289 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2290 | | } |
| 2291 | | |
| 2292 | | |
| 2293 | | void dsp32c_device::d4_mp(UINT32 op) |
| 2294 | | { |
| 2295 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2296 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2297 | | double res = -yval + xval; |
| 2298 | | int zpi = (op >> 0) & 0x7f; |
| 2299 | | if (zpi != 7) |
| 2300 | | dau_write_pi_double(zpi, yval); |
| 2301 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2302 | | } |
| 2303 | | |
| 2304 | | |
| 2305 | | void dsp32c_device::d4_mm(UINT32 op) |
| 2306 | | { |
| 2307 | | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2308 | | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2309 | | double res = -yval - xval; |
| 2310 | | int zpi = (op >> 0) & 0x7f; |
| 2311 | | if (zpi != 7) |
| 2312 | | dau_write_pi_double(zpi, yval); |
| 2313 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2314 | | } |
| 2315 | | |
| 2316 | | |
| 2317 | | void dsp32c_device::d4_ppr(UINT32 op) |
| 2318 | | { |
| 2319 | | unimplemented(op); |
| 2320 | | } |
| 2321 | | |
| 2322 | | |
| 2323 | | void dsp32c_device::d4_pmr(UINT32 op) |
| 2324 | | { |
| 2325 | | unimplemented(op); |
| 2326 | | } |
| 2327 | | |
| 2328 | | |
| 2329 | | void dsp32c_device::d4_mpr(UINT32 op) |
| 2330 | | { |
| 2331 | | unimplemented(op); |
| 2332 | | } |
| 2333 | | |
| 2334 | | |
| 2335 | | void dsp32c_device::d4_mmr(UINT32 op) |
| 2336 | | { |
| 2337 | | unimplemented(op); |
| 2338 | | } |
| 2339 | | |
| 2340 | | |
| 2341 | | |
| 2342 | | //************************************************************************** |
| 2343 | | // DAU FORM 5 IMPLEMENTATION |
| 2344 | | //************************************************************************** |
| 2345 | | |
| 2346 | | void dsp32c_device::d5_ic(UINT32 op) |
| 2347 | | { |
| 2348 | | unimplemented(op); |
| 2349 | | } |
| 2350 | | |
| 2351 | | |
| 2352 | | void dsp32c_device::d5_oc(UINT32 op) |
| 2353 | | { |
| 2354 | | unimplemented(op); |
| 2355 | | } |
| 2356 | | |
| 2357 | | |
| 2358 | | void dsp32c_device::d5_float(UINT32 op) |
| 2359 | | { |
| 2360 | | double res = (double)(INT16)dau_read_pi_2bytes(op >> 7); |
| 2361 | | int zpi = (op >> 0) & 0x7f; |
| 2362 | | if (zpi != 7) |
| 2363 | | dau_write_pi_double(zpi, res); |
| 2364 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2365 | | } |
| 2366 | | |
| 2367 | | |
| 2368 | | void dsp32c_device::d5_int(UINT32 op) |
| 2369 | | { |
| 2370 | | double val = dau_read_pi_double_1st(op >> 7, 0); |
| 2371 | | int zpi = (op >> 0) & 0x7f; |
| 2372 | | INT16 res; |
| 2373 | | if (!(DAUC & 0x10)) val = floor(val + 0.5); |
| 2374 | | else val = ceil(val - 0.5); |
| 2375 | | res = (INT16)val; |
| 2376 | | if (zpi != 7) |
| 2377 | | dau_write_pi_2bytes(zpi, res); |
| 2378 | | dau_set_val_noflags((op >> 21) & 3, dsp_to_double(res << 16)); |
| 2379 | | } |
| 2380 | | |
| 2381 | | |
| 2382 | | void dsp32c_device::d5_round(UINT32 op) |
| 2383 | | { |
| 2384 | | double res = (double)(float)dau_read_pi_double_1st(op >> 7, 0); |
| 2385 | | int zpi = (op >> 0) & 0x7f; |
| 2386 | | if (zpi != 7) |
| 2387 | | dau_write_pi_double(zpi, res); |
| 2388 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2389 | | } |
| 2390 | | |
| 2391 | | |
| 2392 | | void dsp32c_device::d5_ifalt(UINT32 op) |
| 2393 | | { |
| 2394 | | int ar = (op >> 21) & 3; |
| 2395 | | double res = m_a[ar]; |
| 2396 | | int zpi = (op >> 0) & 0x7f; |
| 2397 | | if (NFLAG) |
| 2398 | | res = dau_read_pi_double_1st(op >> 7, 0); |
| 2399 | | if (zpi != 7) |
| 2400 | | dau_write_pi_double(zpi, res); |
| 2401 | | dau_set_val_noflags(ar, res); |
| 2402 | | } |
| 2403 | | |
| 2404 | | |
| 2405 | | void dsp32c_device::d5_ifaeq(UINT32 op) |
| 2406 | | { |
| 2407 | | int ar = (op >> 21) & 3; |
| 2408 | | double res = m_a[ar]; |
| 2409 | | int zpi = (op >> 0) & 0x7f; |
| 2410 | | if (ZFLAG) |
| 2411 | | res = dau_read_pi_double_1st(op >> 7, 0); |
| 2412 | | if (zpi != 7) |
| 2413 | | dau_write_pi_double(zpi, res); |
| 2414 | | dau_set_val_noflags(ar, res); |
| 2415 | | } |
| 2416 | | |
| 2417 | | |
| 2418 | | void dsp32c_device::d5_ifagt(UINT32 op) |
| 2419 | | { |
| 2420 | | int ar = (op >> 21) & 3; |
| 2421 | | double res = m_a[ar]; |
| 2422 | | int zpi = (op >> 0) & 0x7f; |
| 2423 | | if (!NFLAG && !ZFLAG) |
| 2424 | | res = dau_read_pi_double_1st(op >> 7, 0); |
| 2425 | | if (zpi != 7) |
| 2426 | | dau_write_pi_double(zpi, res); |
| 2427 | | dau_set_val_noflags(ar, res); |
| 2428 | | } |
| 2429 | | |
| 2430 | | |
| 2431 | | void dsp32c_device::d5_float24(UINT32 op) |
| 2432 | | { |
| 2433 | | double res = (double)((INT32)(dau_read_pi_4bytes(op >> 7) << 8) >> 8); |
| 2434 | | int zpi = (op >> 0) & 0x7f; |
| 2435 | | if (zpi != 7) |
| 2436 | | dau_write_pi_double(zpi, res); |
| 2437 | | dau_set_val_flags((op >> 21) & 3, res); |
| 2438 | | } |
| 2439 | | |
| 2440 | | |
| 2441 | | void dsp32c_device::d5_int24(UINT32 op) |
| 2442 | | { |
| 2443 | | double val = dau_read_pi_double_1st(op >> 7, 0); |
| 2444 | | int zpi = (op >> 0) & 0x7f; |
| 2445 | | INT32 res; |
| 2446 | | if (!(DAUC & 0x10)) val = floor(val + 0.5); |
| 2447 | | else val = ceil(val - 0.5); |
| 2448 | | res = (INT32)val; |
| 2449 | | if (res > 0x7fffff) res = 0x7fffff; |
| 2450 | | else if (res < -0x800000) res = -0x800000; |
| 2451 | | if (zpi != 7) |
| 2452 | | dau_write_pi_4bytes(zpi, (INT32)(res << 8) >> 8); |
| 2453 | | dau_set_val_noflags((op >> 21) & 3, dsp_to_double(res << 8)); |
| 2454 | | } |
| 2455 | | |
| 2456 | | |
| 2457 | | void dsp32c_device::d5_ieee(UINT32 op) |
| 2458 | | { |
| 2459 | | unimplemented(op); |
| 2460 | | } |
| 2461 | | |
| 2462 | | |
| 2463 | | void dsp32c_device::d5_dsp(UINT32 op) |
| 2464 | | { |
| 2465 | | unimplemented(op); |
| 2466 | | } |
| 2467 | | |
| 2468 | | |
| 2469 | | void dsp32c_device::d5_seed(UINT32 op) |
| 2470 | | { |
| 2471 | | UINT32 val = dau_read_pi_4bytes(op >> 7); |
| 2472 | | INT32 res = val ^ 0x7fffffff; |
| 2473 | | int zpi = (op >> 0) & 0x7f; |
| 2474 | | if (zpi != 7) |
| 2475 | | dau_write_pi_4bytes(zpi, res); |
| 2476 | | dau_set_val_flags((op >> 21) & 3, dsp_to_double((INT32)res)); |
| 2477 | | } |
| 2478 | | |
| 2479 | | |
| 2480 | | |
| 2481 | | //************************************************************************** |
| 2482 | | // FUNCTION TABLE |
| 2483 | | //************************************************************************** |
| 2484 | | |
| 2485 | | void (dsp32c_device::*const dsp32c_device::s_dsp32ops[])(UINT32 op) = |
| 2486 | | { |
| 2487 | | &dsp32c_device::nop, &dsp32c_device::goto_t, &dsp32c_device::goto_pl, &dsp32c_device::goto_mi, &dsp32c_device::goto_ne, &dsp32c_device::goto_eq, &dsp32c_device::goto_vc, &dsp32c_device::goto_vs, // 00 |
| 2488 | | &dsp32c_device::goto_cc, &dsp32c_device::goto_cs, &dsp32c_device::goto_ge, &dsp32c_device::goto_lt, &dsp32c_device::goto_gt, &dsp32c_device::goto_le, &dsp32c_device::goto_hi, &dsp32c_device::goto_ls, |
| 2489 | | &dsp32c_device::goto_auc, &dsp32c_device::goto_aus, &dsp32c_device::goto_age, &dsp32c_device::goto_alt, &dsp32c_device::goto_ane, &dsp32c_device::goto_aeq, &dsp32c_device::goto_avc, &dsp32c_device::goto_avs, // 01 |
| 2490 | | &dsp32c_device::goto_agt, &dsp32c_device::goto_ale, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2491 | | &dsp32c_device::goto_ibe, &dsp32c_device::goto_ibf, &dsp32c_device::goto_obf, &dsp32c_device::goto_obe, &dsp32c_device::goto_pde, &dsp32c_device::goto_pdf, &dsp32c_device::goto_pie, &dsp32c_device::goto_pif, // 02 |
| 2492 | | &dsp32c_device::goto_syc, &dsp32c_device::goto_sys, &dsp32c_device::goto_fbc, &dsp32c_device::goto_fbs, &dsp32c_device::goto_irq1lo,&dsp32c_device::goto_irq1hi,&dsp32c_device::goto_irq2lo,&dsp32c_device::goto_irq2hi, |
| 2493 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 03 |
| 2494 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2495 | | |
| 2496 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 04 |
| 2497 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2498 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 05 |
| 2499 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2500 | | &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, // 06 |
| 2501 | | &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, |
| 2502 | | &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, // 07 |
| 2503 | | &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, |
| 2504 | | |
| 2505 | | &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, // 08 |
| 2506 | | &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, |
| 2507 | | &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, // 09 |
| 2508 | | &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, |
| 2509 | | &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, // 0a |
| 2510 | | &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, |
| 2511 | | &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, // 0b |
| 2512 | | &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, |
| 2513 | | |
| 2514 | | &dsp32c_device::add_ss, &dsp32c_device::mul2_s, &dsp32c_device::subr_ss, &dsp32c_device::addr_ss, &dsp32c_device::sub_ss, &dsp32c_device::neg_s, &dsp32c_device::andc_ss, &dsp32c_device::cmp_ss, // 0c |
| 2515 | | &dsp32c_device::xor_ss, &dsp32c_device::rcr_s, &dsp32c_device::or_ss, &dsp32c_device::rcl_s, &dsp32c_device::shr_s, &dsp32c_device::div2_s, &dsp32c_device::and_ss, &dsp32c_device::test_ss, |
| 2516 | | &dsp32c_device::add_di, &dsp32c_device::illegal, &dsp32c_device::subr_di, &dsp32c_device::addr_di, &dsp32c_device::sub_di, &dsp32c_device::illegal, &dsp32c_device::andc_di, &dsp32c_device::cmp_di, // 0d |
| 2517 | | &dsp32c_device::xor_di, &dsp32c_device::illegal, &dsp32c_device::or_di, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::and_di, &dsp32c_device::test_di, |
| 2518 | | &dsp32c_device::load_hi, &dsp32c_device::load_hi, &dsp32c_device::load_li, &dsp32c_device::load_li, &dsp32c_device::load_i, &dsp32c_device::load_i, &dsp32c_device::load_ei, &dsp32c_device::load_ei, // 0e |
| 2519 | | &dsp32c_device::store_hi, &dsp32c_device::store_hi, &dsp32c_device::store_li, &dsp32c_device::store_li, &dsp32c_device::store_i, &dsp32c_device::store_i, &dsp32c_device::store_ei, &dsp32c_device::store_ei, |
| 2520 | | &dsp32c_device::load_hr, &dsp32c_device::load_hr, &dsp32c_device::load_lr, &dsp32c_device::load_lr, &dsp32c_device::load_r, &dsp32c_device::load_r, &dsp32c_device::load_er, &dsp32c_device::load_er, // 0f |
| 2521 | | &dsp32c_device::store_hr, &dsp32c_device::store_hr, &dsp32c_device::store_lr, &dsp32c_device::store_lr, &dsp32c_device::store_r, &dsp32c_device::store_r, &dsp32c_device::store_er, &dsp32c_device::store_er, |
| 2522 | | |
| 2523 | | &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, // 10 |
| 2524 | | &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, |
| 2525 | | &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 11 |
| 2526 | | &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, |
| 2527 | | &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, // 12 |
| 2528 | | &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, |
| 2529 | | &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 13 |
| 2530 | | &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, |
| 2531 | | |
| 2532 | | &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, // 14 |
| 2533 | | &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, |
| 2534 | | &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 15 |
| 2535 | | &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, |
| 2536 | | &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, // 16 |
| 2537 | | &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, |
| 2538 | | &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 17 |
| 2539 | | &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, |
| 2540 | | |
| 2541 | | &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, // 18 |
| 2542 | | &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, |
| 2543 | | &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 19 |
| 2544 | | &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, |
| 2545 | | &dsp32c_device::d1_1pp, &dsp32c_device::d1_1pp, &dsp32c_device::d1_1pp, &dsp32c_device::d1_1pp, &dsp32c_device::d1_1pm, &dsp32c_device::d1_1pm, &dsp32c_device::d1_1pm, &dsp32c_device::d1_1pm, // 1a |
| 2546 | | &dsp32c_device::d1_1mp, &dsp32c_device::d1_1mp, &dsp32c_device::d1_1mp, &dsp32c_device::d1_1mp, &dsp32c_device::d1_1mm, &dsp32c_device::d1_1mm, &dsp32c_device::d1_1mm, &dsp32c_device::d1_1mm, |
| 2547 | | &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 1b |
| 2548 | | &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, |
| 2549 | | |
| 2550 | | &dsp32c_device::d4_pp, &dsp32c_device::d4_pp, &dsp32c_device::d4_pp, &dsp32c_device::d4_pp, &dsp32c_device::d4_pm, &dsp32c_device::d4_pm, &dsp32c_device::d4_pm, &dsp32c_device::d4_pm, // 1c |
| 2551 | | &dsp32c_device::d4_mp, &dsp32c_device::d4_mp, &dsp32c_device::d4_mp, &dsp32c_device::d4_mp, &dsp32c_device::d4_mm, &dsp32c_device::d4_mm, &dsp32c_device::d4_mm, &dsp32c_device::d4_mm, |
| 2552 | | &dsp32c_device::d4_ppr, &dsp32c_device::d4_ppr, &dsp32c_device::d4_ppr, &dsp32c_device::d4_ppr, &dsp32c_device::d4_pmr, &dsp32c_device::d4_pmr, &dsp32c_device::d4_pmr, &dsp32c_device::d4_pmr, // 1d |
| 2553 | | &dsp32c_device::d4_mpr, &dsp32c_device::d4_mpr, &dsp32c_device::d4_mpr, &dsp32c_device::d4_mpr, &dsp32c_device::d4_mmr, &dsp32c_device::d4_mmr, &dsp32c_device::d4_mmr, &dsp32c_device::d4_mmr, |
| 2554 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 1e |
| 2555 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2556 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 1f |
| 2557 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2558 | | |
| 2559 | | &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 20 |
| 2560 | | &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, |
| 2561 | | &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 21 |
| 2562 | | &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, |
| 2563 | | &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 22 |
| 2564 | | &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, |
| 2565 | | &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 23 |
| 2566 | | &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, |
| 2567 | | |
| 2568 | | &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 24 |
| 2569 | | &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, |
| 2570 | | &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 25 |
| 2571 | | &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, |
| 2572 | | &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 26 |
| 2573 | | &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, |
| 2574 | | &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 27 |
| 2575 | | &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, |
| 2576 | | |
| 2577 | | &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 28 |
| 2578 | | &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, |
| 2579 | | &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 29 |
| 2580 | | &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, |
| 2581 | | &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 2a |
| 2582 | | &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, |
| 2583 | | &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 2b |
| 2584 | | &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, |
| 2585 | | |
| 2586 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 2c |
| 2587 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2588 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 2d |
| 2589 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2590 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 2e |
| 2591 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2592 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 2f |
| 2593 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2594 | | |
| 2595 | | &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 30 |
| 2596 | | &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, |
| 2597 | | &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 31 |
| 2598 | | &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, |
| 2599 | | &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 32 |
| 2600 | | &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, |
| 2601 | | &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 33 |
| 2602 | | &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, |
| 2603 | | |
| 2604 | | &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 34 |
| 2605 | | &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, |
| 2606 | | &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 35 |
| 2607 | | &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, |
| 2608 | | &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 36 |
| 2609 | | &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, |
| 2610 | | &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 37 |
| 2611 | | &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, |
| 2612 | | |
| 2613 | | &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 38 |
| 2614 | | &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, |
| 2615 | | &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 39 |
| 2616 | | &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, |
| 2617 | | &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 3a |
| 2618 | | &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, |
| 2619 | | &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 3b |
| 2620 | | &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, |
| 2621 | | |
| 2622 | | &dsp32c_device::d5_ic, &dsp32c_device::d5_ic, &dsp32c_device::d5_ic, &dsp32c_device::d5_ic, &dsp32c_device::d5_oc, &dsp32c_device::d5_oc, &dsp32c_device::d5_oc, &dsp32c_device::d5_oc, // 3c |
| 2623 | | &dsp32c_device::d5_float, &dsp32c_device::d5_float, &dsp32c_device::d5_float, &dsp32c_device::d5_float, &dsp32c_device::d5_int, &dsp32c_device::d5_int, &dsp32c_device::d5_int, &dsp32c_device::d5_int, |
| 2624 | | &dsp32c_device::d5_round, &dsp32c_device::d5_round, &dsp32c_device::d5_round, &dsp32c_device::d5_round, &dsp32c_device::d5_ifalt, &dsp32c_device::d5_ifalt, &dsp32c_device::d5_ifalt, &dsp32c_device::d5_ifalt, // 3d |
| 2625 | | &dsp32c_device::d5_ifaeq, &dsp32c_device::d5_ifaeq, &dsp32c_device::d5_ifaeq, &dsp32c_device::d5_ifaeq, &dsp32c_device::d5_ifagt, &dsp32c_device::d5_ifagt, &dsp32c_device::d5_ifagt, &dsp32c_device::d5_ifagt, |
| 2626 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 3e |
| 2627 | | &dsp32c_device::d5_float24, &dsp32c_device::d5_float24, &dsp32c_device::d5_float24, &dsp32c_device::d5_float24, &dsp32c_device::d5_int24, &dsp32c_device::d5_int24, &dsp32c_device::d5_int24, &dsp32c_device::d5_int24, |
| 2628 | | &dsp32c_device::d5_ieee, &dsp32c_device::d5_ieee, &dsp32c_device::d5_ieee, &dsp32c_device::d5_ieee, &dsp32c_device::d5_dsp, &dsp32c_device::d5_dsp, &dsp32c_device::d5_dsp, &dsp32c_device::d5_dsp, // 3f |
| 2629 | | &dsp32c_device::d5_seed, &dsp32c_device::d5_seed, &dsp32c_device::d5_seed, &dsp32c_device::d5_seed, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2630 | | |
| 2631 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 40 |
| 2632 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2633 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 41 |
| 2634 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2635 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 42 |
| 2636 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2637 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 43 |
| 2638 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2639 | | |
| 2640 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 44 |
| 2641 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2642 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 45 |
| 2643 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2644 | | &dsp32c_device::do_i, &dsp32c_device::do_r, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 46 |
| 2645 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2646 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 47 |
| 2647 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2648 | | |
| 2649 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 48 |
| 2650 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2651 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 49 |
| 2652 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2653 | | &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, // 4a |
| 2654 | | &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, |
| 2655 | | &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, // 4b |
| 2656 | | &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, |
| 2657 | | |
| 2658 | | &dsp32c_device::adde_ss, &dsp32c_device::mul2e_s, &dsp32c_device::subre_ss, &dsp32c_device::addre_ss, &dsp32c_device::sube_ss, &dsp32c_device::nege_s, &dsp32c_device::andce_ss, &dsp32c_device::cmpe_ss, // 4c |
| 2659 | | &dsp32c_device::xore_ss, &dsp32c_device::rcre_s, &dsp32c_device::ore_ss, &dsp32c_device::rcle_s, &dsp32c_device::shre_s, &dsp32c_device::div2e_s, &dsp32c_device::ande_ss, &dsp32c_device::teste_ss, |
| 2660 | | &dsp32c_device::adde_di, &dsp32c_device::illegal, &dsp32c_device::subre_di, &dsp32c_device::addre_di, &dsp32c_device::sube_di, &dsp32c_device::illegal, &dsp32c_device::andce_di, &dsp32c_device::cmpe_di, // 4d |
| 2661 | | &dsp32c_device::xore_di, &dsp32c_device::illegal, &dsp32c_device::ore_di, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::ande_di, &dsp32c_device::teste_di, |
| 2662 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 4e |
| 2663 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2664 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 4f |
| 2665 | | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2666 | | |
| 2667 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 50 |
| 2668 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2669 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 51 |
| 2670 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2671 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 52 |
| 2672 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2673 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 53 |
| 2674 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2675 | | |
| 2676 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 54 |
| 2677 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2678 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 55 |
| 2679 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2680 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 56 |
| 2681 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2682 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 57 |
| 2683 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2684 | | |
| 2685 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 58 |
| 2686 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2687 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 59 |
| 2688 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2689 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5a |
| 2690 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2691 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5b |
| 2692 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2693 | | |
| 2694 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5c |
| 2695 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2696 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5d |
| 2697 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2698 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5e |
| 2699 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2700 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5f |
| 2701 | | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2702 | | |
| 2703 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 60 |
| 2704 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2705 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 61 |
| 2706 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2707 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 62 |
| 2708 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2709 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 63 |
| 2710 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2711 | | |
| 2712 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 64 |
| 2713 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2714 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 65 |
| 2715 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2716 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 66 |
| 2717 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2718 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 67 |
| 2719 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2720 | | |
| 2721 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 68 |
| 2722 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2723 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 69 |
| 2724 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2725 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6a |
| 2726 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2727 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6b |
| 2728 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2729 | | |
| 2730 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6c |
| 2731 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2732 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6d |
| 2733 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2734 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6e |
| 2735 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2736 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6f |
| 2737 | | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2738 | | |
| 2739 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 70 |
| 2740 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2741 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 71 |
| 2742 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2743 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 72 |
| 2744 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2745 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 73 |
| 2746 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2747 | | |
| 2748 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 74 |
| 2749 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2750 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 75 |
| 2751 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2752 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 76 |
| 2753 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2754 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 77 |
| 2755 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2756 | | |
| 2757 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 78 |
| 2758 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2759 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 79 |
| 2760 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2761 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7a |
| 2762 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2763 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7b |
| 2764 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2765 | | |
| 2766 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7c |
| 2767 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2768 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7d |
| 2769 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2770 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7e |
| 2771 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2772 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7f |
| 2773 | | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24 |
| 2774 | | }; |
| 2775 | | |
| 2776 | | |
| 2777 | | /* |
| 2778 | | |
| 2779 | | Most common OPs in Race Drivin': |
| 2780 | | |
| 2781 | | 301681217 - op 0 - nop |
| 2782 | | 164890391 - op 4A1 - adde_si |
| 2783 | | 99210113 - op 661 - load24 |
| 2784 | | 86010010 - op F7 - load_er |
| 2785 | | 61148739 - op 4D4 - sube_di |
| 2786 | | 52693763 - op 180 - d1_0px |
| 2787 | | 41525754 - op FF - store_er |
| 2788 | | 35033321 - op 380 - d3_aMpp |
| 2789 | | 31621151 - op 4C0 - adde_ss |
| 2790 | | 28076244 - op 660 - load24 |
| 2791 | | 19190505 - op 4C1 - mul2e_s |
| 2792 | | 13270852 - op F5 - load_r |
| 2793 | | 12535169 - op 1A4 - d1_1pm |
| 2794 | | 12265141 - op 4C4 - sube_ss |
| 2795 | | 10748211 - op 4CD - div2e_s |
| 2796 | | 10493660 - op FD - store_r |
| 2797 | | 9721263 - op 189 |
| 2798 | | 9415685 - op 3C8 |
| 2799 | | 9294148 - op 3D5 |
| 2800 | | 8887846 - op 1A1 |
| 2801 | | 8788648 - op 381 |
| 2802 | | 8185239 - op 300 |
| 2803 | | 7241256 - op 383 |
| 2804 | | 6877349 - op 4A3 |
| 2805 | | 6832295 - op 181 |
| 2806 | | 6601270 - op 3E8 |
| 2807 | | 6562483 - op 4A4 |
| 2808 | | 6553514 - op 3C9 |
| 2809 | | 6270430 - op 280 |
| 2810 | | 6041485 - op 1A0 |
| 2811 | | 5299529 - op 304 |
| 2812 | | 5110926 - op 382 |
| 2813 | | 4922253 - op 363 |
| 2814 | | 4603670 - op 4D7 |
| 2815 | | 4164327 - op 4AE |
| 2816 | | 3980085 - op 3EC |
| 2817 | | 3599198 - op 3CC |
| 2818 | | 3543878 - op 3D0 |
| 2819 | | 3489158 - op 4 |
| 2820 | | 3463235 - op 321 |
| 2821 | | 3335995 - op 3F9 |
| 2822 | | 3001546 - op 4CE |
| 2823 | | 2882940 - op 129 |
| 2824 | | 2882940 - op 1A5 |
| 2825 | | 2882940 - op 342 |
| 2826 | | 2841981 - op 360 |
| 2827 | | 2663417 - op FB |
| 2828 | | 2059640 - op 3ED |
| 2829 | | 1867166 - op 1A8 |
| 2830 | | 1830789 - op 305 |
| 2831 | | 1753312 - op 301 |
| 2832 | | 1726866 - op 5 |
| 2833 | | 1594991 - op 12 |
| 2834 | | 1571286 - op 19 |
| 2835 | | 1507644 - op A2 |
| 2836 | | 1418846 - op 3CD |
| 2837 | | 1273134 - op F3 |
| 2838 | | 1177914 - op 4C7 |
| 2839 | | 1175720 - op 188 |
| 2840 | | 1091848 - op 3E9 |
| 2841 | | 1088206 - op 6FF |
| 2842 | | 1088204 - op 4CA |
| 2843 | | 1012639 - op 101 |
| 2844 | | 939617 - op 4C5 |
| 2845 | | |
| 2846 | | */ |
trunk/src/emu/cpu/dsp32/dsp32ops.inc
| r0 | r28739 | |
| 1 | // license:BSD-3-Clause |
| 2 | // copyright-holders:Aaron Giles |
| 3 | /*************************************************************************** |
| 4 | |
| 5 | dsp32ops.inc |
| 6 | Core implementation for the portable DSP32 emulator. |
| 7 | |
| 8 | ****************************************************************************/ |
| 9 | |
| 10 | |
| 11 | |
| 12 | //************************************************************************** |
| 13 | // COMPILE-TIME OPTIONS |
| 14 | //************************************************************************** |
| 15 | |
| 16 | // these defined latencies are a pain to implement, but are necessary |
| 17 | #define EMULATE_MEMORY_LATENCY (1) |
| 18 | #define EMULATE_MULTIPLIER_LATENCY (1) |
| 19 | #define EMULATE_AFLAGS_LATENCY (1) |
| 20 | |
| 21 | // these optimizations should have some effect, but they don't really, so |
| 22 | // leave them off |
| 23 | #define IGNORE_DAU_UV_FLAGS (0) |
| 24 | #define ASSUME_WRITEABLE (0) |
| 25 | #define ASSUME_UNCONDITIONAL_CAU (0) |
| 26 | |
| 27 | |
| 28 | |
| 29 | //************************************************************************** |
| 30 | // MACROS |
| 31 | //************************************************************************** |
| 32 | |
| 33 | #define SET_V_16(a,b,r) m_vflags = (((a) ^ (b) ^ (r) ^ ((r) >> 1)) << 8) |
| 34 | #define SET_NZC_16(r) m_nzcflags = ((r) << 8) |
| 35 | #define SET_NZCV_16(a,b,r) SET_NZC_16(r); SET_V_16(a,b,r) |
| 36 | #define SET_NZ00_16(r) m_nzcflags = (((r) << 8) & 0xffffff); m_vflags = 0 |
| 37 | |
| 38 | #define SET_V_24(a,b,r) m_vflags = ((a) ^ (b) ^ (r) ^ ((r) >> 1)) |
| 39 | #define SET_NZC_24(r) m_nzcflags = (r) |
| 40 | #define SET_NZCV_24(a,b,r) SET_NZC_24(r); SET_V_24(a,b,r) |
| 41 | #define SET_NZ00_24(r) m_nzcflags = ((r) & 0xffffff); m_vflags = 0 |
| 42 | |
| 43 | #define TRUNCATE24(a) ((a) & 0xffffff) |
| 44 | #define EXTEND16_TO_24(a) TRUNCATE24((INT32)(INT16)(a)) |
| 45 | #define REG16(a) ((UINT16)m_r[a]) |
| 46 | #define REG24(a) (m_r[a]) |
| 47 | |
| 48 | #define WRITEABLE_REGS (0x6f3efffe) |
| 49 | #if ASSUME_WRITEABLE |
| 50 | #define IS_WRITEABLE(r) (1) |
| 51 | #else |
| 52 | #define IS_WRITEABLE(r) (WRITEABLE_REGS & (1 << (r))) |
| 53 | #endif |
| 54 | |
| 55 | #if ASSUME_UNCONDITIONAL_CAU |
| 56 | #define CONDITION_IS_TRUE() (1) |
| 57 | #else |
| 58 | #define CONDITION_IS_TRUE() (!(op & 0x400) || (condition((op >> 12) & 15))) |
| 59 | #endif |
| 60 | |
| 61 | #if EMULATE_MEMORY_LATENCY |
| 62 | #define WWORD_DEFERRED(a,v) do { int bufidx = m_mbuf_index & 3; m_mbufaddr[bufidx] = -(a); m_mbufdata[bufidx] = (v); } while (0) |
| 63 | #define WLONG_DEFERRED(a,v) do { int bufidx = m_mbuf_index & 3; m_mbufaddr[bufidx] = (a); m_mbufdata[bufidx] = (v); } while (0) |
| 64 | #define PROCESS_DEFERRED_MEMORY() \ |
| 65 | if (m_mbufaddr[++m_mbuf_index & 3] != 1) \ |
| 66 | { \ |
| 67 | int bufidx = m_mbuf_index & 3; \ |
| 68 | if (m_mbufaddr[bufidx] >= 0) \ |
| 69 | WLONG(m_mbufaddr[bufidx], m_mbufdata[bufidx]); \ |
| 70 | else \ |
| 71 | WWORD(-m_mbufaddr[bufidx], m_mbufdata[bufidx]); \ |
| 72 | m_mbufaddr[bufidx] = 1; \ |
| 73 | } |
| 74 | #else |
| 75 | #define WWORD_DEFERRED(a,v) WWORD(a,v) |
| 76 | #define WLONG_DEFERRED(a,v) WLONG(a,v) |
| 77 | #define PROCESS_DEFERRED_MEMORY() |
| 78 | #endif |
| 79 | |
| 80 | #if EMULATE_MULTIPLIER_LATENCY |
| 81 | #define DEFERRED_MULTIPLIER(x) dau_get_amult(x) |
| 82 | #else |
| 83 | #define DEFERRED_MULTIPLIER(x) m_a[x] |
| 84 | #endif |
| 85 | |
| 86 | #if EMULATE_AFLAGS_LATENCY |
| 87 | #define DEFERRED_NZFLAGS() dau_get_anzflags() |
| 88 | #define DEFERRED_VUFLAGS() dau_get_avuflags() |
| 89 | #else |
| 90 | #define DEFERRED_NZFLAGS() m_NZflags |
| 91 | #define DEFERRED_VUFLAGS() m_VUflags |
| 92 | #endif |
| 93 | |
| 94 | |
| 95 | |
| 96 | //************************************************************************** |
| 97 | // TYPEDEFS |
| 98 | //************************************************************************** |
| 99 | |
| 100 | union int_double |
| 101 | { |
| 102 | double d; |
| 103 | UINT32 i[2]; |
| 104 | }; |
| 105 | |
| 106 | |
| 107 | |
| 108 | //************************************************************************** |
| 109 | // IMPLEMENTATION |
| 110 | //************************************************************************** |
| 111 | |
| 112 | void dsp32c_device::illegal(UINT32 op) |
| 113 | { |
| 114 | } |
| 115 | |
| 116 | |
| 117 | void dsp32c_device::unimplemented(UINT32 op) |
| 118 | { |
| 119 | fatalerror("Unimplemented op @ %06X: %08X (dis=%02X, tbl=%03X)\n", PC - 4, op, op >> 25, op >> 21); |
| 120 | } |
| 121 | |
| 122 | |
| 123 | inline void dsp32c_device::execute_one() |
| 124 | { |
| 125 | UINT32 op; |
| 126 | |
| 127 | PROCESS_DEFERRED_MEMORY(); |
| 128 | debugger_instruction_hook(this, PC); |
| 129 | op = ROPCODE(PC); |
| 130 | m_icount -= 4; // 4 clocks per cycle |
| 131 | PC += 4; |
| 132 | if (op) |
| 133 | (this->*s_dsp32ops[op >> 21])(op); |
| 134 | } |
| 135 | |
| 136 | |
| 137 | |
| 138 | //************************************************************************** |
| 139 | // CAU HELPERS |
| 140 | //************************************************************************** |
| 141 | |
| 142 | UINT32 dsp32c_device::cau_read_pi_special(UINT8 i) |
| 143 | { |
| 144 | switch (i) |
| 145 | { |
| 146 | case 4: return m_ibuf; |
| 147 | case 5: return m_obuf; |
| 148 | case 6: update_pcr(m_pcr & ~PCR_PDFs); update_pins(); return m_pdr; |
| 149 | case 14: return m_piop; |
| 150 | case 20: return m_pdr2; |
| 151 | case 22: update_pcr(m_pcr & ~PCR_PIFs); update_pins(); return m_pir; |
| 152 | case 30: return m_pcw; |
| 153 | default: fprintf(stderr, "Unimplemented CAU PI read = %X\n", i); |
| 154 | } |
| 155 | return 0; |
| 156 | } |
| 157 | |
| 158 | |
| 159 | void dsp32c_device::cau_write_pi_special(UINT8 i, UINT32 val) |
| 160 | { |
| 161 | switch (i) |
| 162 | { |
| 163 | case 4: m_ibuf = val; break; |
| 164 | case 5: m_obuf = val; break; |
| 165 | case 6: m_pdr = val; update_pcr(m_pcr | PCR_PDFs); update_pins(); break; |
| 166 | case 14: m_piop = val; break; |
| 167 | case 20: m_pdr2 = val; break; |
| 168 | case 22: m_pir = val; update_pcr(m_pcr | PCR_PIFs); update_pins(); break; |
| 169 | case 30: m_pcw = val; break; |
| 170 | default: fprintf(stderr, "Unimplemented CAU PI write = %X\n", i); |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | |
| 175 | inline UINT8 dsp32c_device::cau_read_pi_1byte(int pi) |
| 176 | { |
| 177 | int p = (pi >> 5) & 0x1f; |
| 178 | int i = (pi >> 0) & 0x1f; |
| 179 | if (p) |
| 180 | { |
| 181 | UINT32 result = RBYTE(m_r[p]); |
| 182 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i]); |
| 183 | return result; |
| 184 | } |
| 185 | else |
| 186 | return cau_read_pi_special(i); |
| 187 | } |
| 188 | |
| 189 | |
| 190 | inline UINT16 dsp32c_device::cau_read_pi_2byte(int pi) |
| 191 | { |
| 192 | int p = (pi >> 5) & 0x1f; |
| 193 | int i = (pi >> 0) & 0x1f; |
| 194 | if (p) |
| 195 | { |
| 196 | UINT32 result = RWORD(m_r[p]); |
| 197 | if (i < 22 || i > 23) |
| 198 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i]); |
| 199 | else |
| 200 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i] * 2); |
| 201 | return result; |
| 202 | } |
| 203 | else |
| 204 | return cau_read_pi_special(i); |
| 205 | } |
| 206 | |
| 207 | |
| 208 | inline UINT32 dsp32c_device::cau_read_pi_4byte(int pi) |
| 209 | { |
| 210 | int p = (pi >> 5) & 0x1f; |
| 211 | int i = (pi >> 0) & 0x1f; |
| 212 | if (p) |
| 213 | { |
| 214 | UINT32 result = RLONG(m_r[p]); |
| 215 | if (i < 22 || i > 23) |
| 216 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i]); |
| 217 | else |
| 218 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i] * 4); |
| 219 | return result; |
| 220 | } |
| 221 | else |
| 222 | return cau_read_pi_special(i); |
| 223 | } |
| 224 | |
| 225 | |
| 226 | inline void dsp32c_device::cau_write_pi_1byte(int pi, UINT8 val) |
| 227 | { |
| 228 | int p = (pi >> 5) & 0x1f; |
| 229 | int i = (pi >> 0) & 0x1f; |
| 230 | if (p) |
| 231 | { |
| 232 | WBYTE(m_r[p], val); |
| 233 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i]); |
| 234 | } |
| 235 | else |
| 236 | cau_write_pi_special(i, val); |
| 237 | } |
| 238 | |
| 239 | |
| 240 | inline void dsp32c_device::cau_write_pi_2byte(int pi, UINT16 val) |
| 241 | { |
| 242 | int p = (pi >> 5) & 0x1f; |
| 243 | int i = (pi >> 0) & 0x1f; |
| 244 | if (p) |
| 245 | { |
| 246 | WWORD(m_r[p], val); |
| 247 | if (i < 22 || i > 23) |
| 248 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i]); |
| 249 | else |
| 250 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i] * 2); |
| 251 | } |
| 252 | else |
| 253 | cau_write_pi_special(i, val); |
| 254 | } |
| 255 | |
| 256 | |
| 257 | inline void dsp32c_device::cau_write_pi_4byte(int pi, UINT32 val) |
| 258 | { |
| 259 | int p = (pi >> 5) & 0x1f; |
| 260 | int i = (pi >> 0) & 0x1f; |
| 261 | if (p) |
| 262 | { |
| 263 | WLONG(m_r[p], (INT32)(val << 8) >> 8); |
| 264 | if (i < 22 || i > 23) |
| 265 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i]); |
| 266 | else |
| 267 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i] * 4); |
| 268 | } |
| 269 | else |
| 270 | cau_write_pi_special(i, val); |
| 271 | } |
| 272 | |
| 273 | |
| 274 | |
| 275 | //************************************************************************** |
| 276 | // DAU HELPERS |
| 277 | //************************************************************************** |
| 278 | |
| 279 | inline double dsp32c_device::dau_get_amult(int aidx) |
| 280 | { |
| 281 | int bufidx = (m_abuf_index - 1) & 3; |
| 282 | double val = m_a[aidx]; |
| 283 | while (m_icount >= m_abufcycle[bufidx] - 2 * 4) |
| 284 | { |
| 285 | if (m_abufreg[bufidx] == aidx) |
| 286 | val = m_abuf[bufidx]; |
| 287 | bufidx = (bufidx - 1) & 3; |
| 288 | } |
| 289 | return val; |
| 290 | } |
| 291 | |
| 292 | |
| 293 | inline double dsp32c_device::dau_get_anzflags() |
| 294 | { |
| 295 | int bufidx = (m_abuf_index - 1) & 3; |
| 296 | double nzflags = m_NZflags; |
| 297 | while (m_icount >= m_abufcycle[bufidx] - 3 * 4) |
| 298 | { |
| 299 | nzflags = m_abufNZflags[bufidx]; |
| 300 | bufidx = (bufidx - 1) & 3; |
| 301 | } |
| 302 | return nzflags; |
| 303 | } |
| 304 | |
| 305 | |
| 306 | inline UINT8 dsp32c_device::dau_get_avuflags() |
| 307 | { |
| 308 | #if (!IGNORE_DAU_UV_FLAGS) |
| 309 | int bufidx = (m_abuf_index - 1) & 3; |
| 310 | UINT8 vuflags = m_VUflags; |
| 311 | while (m_icount >= m_abufcycle[bufidx] - 3 * 4) |
| 312 | { |
| 313 | vuflags = m_abufVUflags[bufidx]; |
| 314 | bufidx = (bufidx - 1) & 3; |
| 315 | } |
| 316 | return vuflags; |
| 317 | #else |
| 318 | return 0; |
| 319 | #endif |
| 320 | } |
| 321 | |
| 322 | |
| 323 | inline void dsp32c_device::remember_last_dau(int aidx) |
| 324 | { |
| 325 | #if (EMULATE_MULTIPLIER_LATENCY || EMULATE_AFLAGS_LATENCY) |
| 326 | int bufidx = m_abuf_index++ & 3; |
| 327 | m_abuf[bufidx] = m_a[aidx]; |
| 328 | m_abufreg[bufidx] = aidx; |
| 329 | m_abufNZflags[bufidx] = m_NZflags; |
| 330 | #if (!IGNORE_DAU_UV_FLAGS) |
| 331 | m_abufVUflags[bufidx] = m_VUflags; |
| 332 | #endif |
| 333 | m_abufcycle[bufidx] = m_icount; |
| 334 | #endif |
| 335 | } |
| 336 | |
| 337 | |
| 338 | inline void dsp32c_device::dau_set_val_noflags(int aidx, double res) |
| 339 | { |
| 340 | remember_last_dau(aidx); |
| 341 | m_a[aidx] = res; |
| 342 | } |
| 343 | |
| 344 | |
| 345 | inline void dsp32c_device::dau_set_val_flags(int aidx, double res) |
| 346 | { |
| 347 | remember_last_dau(aidx); |
| 348 | #if (!IGNORE_DAU_UV_FLAGS) |
| 349 | { |
| 350 | double absres = (res < 0) ? -res : res; |
| 351 | m_VUflags = 0; |
| 352 | if (absres < 5.87747e-39) |
| 353 | { |
| 354 | if (absres != 0) |
| 355 | m_VUflags = UFLAGBIT; |
| 356 | res = 0.0; |
| 357 | } |
| 358 | else if (absres > 3.40282e38) |
| 359 | { |
| 360 | m_VUflags = VFLAGBIT; |
| 361 | // debugger_break(Machine); |
| 362 | // fprintf(stderr, "Result = %g\n", absres); |
| 363 | res = (res < 0) ? -3.40282e38 : 3.40282e38; |
| 364 | } |
| 365 | } |
| 366 | #endif |
| 367 | m_NZflags = res; |
| 368 | m_a[aidx] = res; |
| 369 | } |
| 370 | |
| 371 | |
| 372 | inline double dsp32c_device::dsp_to_double(UINT32 val) |
| 373 | { |
| 374 | int_double id; |
| 375 | |
| 376 | if (val == 0) |
| 377 | return 0; |
| 378 | else if ((INT32)val > 0) |
| 379 | { |
| 380 | int exponent = ((val & 0xff) - 128 + 1023) << 20; |
| 381 | id.i[BYTE_XOR_BE(0)] = exponent + (val >> 11); |
| 382 | id.i[BYTE_XOR_BE(1)] = (val << 21) & 0xe0000000; |
| 383 | } |
| 384 | else |
| 385 | { |
| 386 | int exponent = ((val & 0xff) - 128 + 1023) << 20; |
| 387 | val = -(val & 0xffffff00); |
| 388 | id.i[BYTE_XOR_BE(0)] = 0x80000000 + exponent + ((val >> 11) & 0x001fffff); |
| 389 | id.i[BYTE_XOR_BE(1)] = (val << 21) & 0xe0000000; |
| 390 | } |
| 391 | return id.d; |
| 392 | } |
| 393 | |
| 394 | |
| 395 | inline UINT32 dsp32c_device::double_to_dsp(double val) |
| 396 | { |
| 397 | int mantissa, exponent; |
| 398 | int_double id; |
| 399 | id.d = val; |
| 400 | mantissa = ((id.i[BYTE_XOR_BE(0)] & 0x000fffff) << 11) | ((id.i[BYTE_XOR_BE(1)] & 0xe0000000) >> 21); |
| 401 | exponent = ((id.i[BYTE_XOR_BE(0)] & 0x7ff00000) >> 20) - 1023 + 128; |
| 402 | if (exponent < 0) |
| 403 | return 0x00000000; |
| 404 | else if (exponent > 255) |
| 405 | { |
| 406 | // debugger_break(Machine); |
| 407 | // fprintf(stderr, "Exponent = %d\n", exponent); |
| 408 | return ((INT32)id.i[BYTE_XOR_BE(0)] >= 0) ? 0x7fffffff : 0x800000ff; |
| 409 | } |
| 410 | else if ((INT32)id.i[BYTE_XOR_BE(0)] >= 0) |
| 411 | return exponent | mantissa; |
| 412 | else |
| 413 | { |
| 414 | mantissa = -mantissa; |
| 415 | if (mantissa == 0) { mantissa = 0x80000000; exponent--; } |
| 416 | return 0x80000000 | exponent | (mantissa & 0xffffff00); |
| 417 | } |
| 418 | } |
| 419 | |
| 420 | |
| 421 | double dsp32c_device::dau_read_pi_special(int i) |
| 422 | { |
| 423 | fatalerror("Unimplemented dau_read_pi_special(%d)\n", i); |
| 424 | return 0; |
| 425 | } |
| 426 | |
| 427 | |
| 428 | void dsp32c_device::dau_write_pi_special(int i, double val) |
| 429 | { |
| 430 | fatalerror("Unimplemented dau_write_pi_special(%d)\n", i); |
| 431 | } |
| 432 | |
| 433 | |
| 434 | inline double dsp32c_device::dau_read_pi_double_1st(int pi, int multiplier) |
| 435 | { |
| 436 | int p = (pi >> 3) & 15; |
| 437 | int i = (pi >> 0) & 7; |
| 438 | |
| 439 | m_lastp = p; |
| 440 | if (p) |
| 441 | { |
| 442 | UINT32 result = RLONG(m_r[p]); |
| 443 | if (i < 6) |
| 444 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 445 | else |
| 446 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4); |
| 447 | return dsp_to_double(result); |
| 448 | } |
| 449 | else if (i < 4) |
| 450 | return multiplier ? DEFERRED_MULTIPLIER(i) : m_a[i]; |
| 451 | else |
| 452 | return dau_read_pi_special(i); |
| 453 | } |
| 454 | |
| 455 | |
| 456 | inline double dsp32c_device::dau_read_pi_double_2nd(int pi, int multiplier, double xval) |
| 457 | { |
| 458 | int p = (pi >> 3) & 15; |
| 459 | int i = (pi >> 0) & 7; |
| 460 | |
| 461 | if (p == 15) p = m_lastp; // P=15 means Z inherits from Y, Y inherits from X |
| 462 | m_lastp = p; |
| 463 | if (p) |
| 464 | { |
| 465 | UINT32 result; |
| 466 | result = RLONG(m_r[p]); |
| 467 | if (i < 6) |
| 468 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 469 | else |
| 470 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4); |
| 471 | return dsp_to_double(result); |
| 472 | } |
| 473 | else if (i < 4) |
| 474 | return multiplier ? DEFERRED_MULTIPLIER(i) : m_a[i]; |
| 475 | else |
| 476 | return dau_read_pi_special(i); |
| 477 | } |
| 478 | |
| 479 | |
| 480 | inline UINT32 dsp32c_device::dau_read_pi_4bytes(int pi) |
| 481 | { |
| 482 | int p = (pi >> 3) & 15; |
| 483 | int i = (pi >> 0) & 7; |
| 484 | |
| 485 | m_lastp = p; |
| 486 | if (p) |
| 487 | { |
| 488 | UINT32 result = RLONG(m_r[p]); |
| 489 | if (i < 6) |
| 490 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 491 | else |
| 492 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4); |
| 493 | return result; |
| 494 | } |
| 495 | else if (i < 4) |
| 496 | return double_to_dsp(m_a[i]); |
| 497 | else |
| 498 | return dau_read_pi_special(i); |
| 499 | } |
| 500 | |
| 501 | |
| 502 | inline UINT16 dsp32c_device::dau_read_pi_2bytes(int pi) |
| 503 | { |
| 504 | int p = (pi >> 3) & 15; |
| 505 | int i = (pi >> 0) & 7; |
| 506 | |
| 507 | m_lastp = p; |
| 508 | if (p) |
| 509 | { |
| 510 | UINT32 result = RWORD(m_r[p]); |
| 511 | if (i < 6) |
| 512 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 513 | else |
| 514 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 2); |
| 515 | return result; |
| 516 | } |
| 517 | else if (i < 4) |
| 518 | return double_to_dsp(m_a[i]); |
| 519 | else |
| 520 | return dau_read_pi_special(i); |
| 521 | } |
| 522 | |
| 523 | |
| 524 | inline void dsp32c_device::dau_write_pi_double(int pi, double val) |
| 525 | { |
| 526 | int p = (pi >> 3) & 15; |
| 527 | int i = (pi >> 0) & 7; |
| 528 | |
| 529 | if (p == 15) p = m_lastp; // P=15 means Z inherits from Y, Y inherits from X |
| 530 | if (p) |
| 531 | { |
| 532 | WLONG_DEFERRED(m_r[p], double_to_dsp(val)); |
| 533 | if (i < 6) |
| 534 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 535 | else |
| 536 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4); |
| 537 | } |
| 538 | else if (i < 4) |
| 539 | dau_set_val_noflags(i, val); |
| 540 | else |
| 541 | dau_write_pi_special(i, val); |
| 542 | } |
| 543 | |
| 544 | |
| 545 | inline void dsp32c_device::dau_write_pi_4bytes(int pi, UINT32 val) |
| 546 | { |
| 547 | int p = (pi >> 3) & 15; |
| 548 | int i = (pi >> 0) & 7; |
| 549 | |
| 550 | if (p == 15) p = m_lastp; // P=15 means Z inherits from Y, Y inherits from X |
| 551 | if (p) |
| 552 | { |
| 553 | m_lastp = p; |
| 554 | WLONG_DEFERRED(m_r[p], val); |
| 555 | if (i < 6) |
| 556 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 557 | else |
| 558 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 4); |
| 559 | } |
| 560 | else if (i < 4) |
| 561 | dau_set_val_noflags(i, dsp_to_double(val)); |
| 562 | else |
| 563 | dau_write_pi_special(i, val); |
| 564 | } |
| 565 | |
| 566 | |
| 567 | inline void dsp32c_device::dau_write_pi_2bytes(int pi, UINT16 val) |
| 568 | { |
| 569 | int p = (pi >> 3) & 15; |
| 570 | int i = (pi >> 0) & 7; |
| 571 | |
| 572 | if (p == 15) p = m_lastp; // P=15 means Z inherits from Y, Y inherits from X |
| 573 | if (p) |
| 574 | { |
| 575 | m_lastp = p; |
| 576 | WWORD_DEFERRED(m_r[p], val); |
| 577 | if (i < 6) |
| 578 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16]); |
| 579 | else |
| 580 | m_r[p] = TRUNCATE24(m_r[p] + m_r[i+16] * 2); |
| 581 | } |
| 582 | else if (i < 4) |
| 583 | dau_set_val_noflags(i, dsp_to_double(val << 16)); |
| 584 | else |
| 585 | dau_write_pi_special(i, val); |
| 586 | } |
| 587 | |
| 588 | |
| 589 | |
| 590 | //************************************************************************** |
| 591 | // COMMON CONDITION ROUTINE |
| 592 | //************************************************************************** |
| 593 | |
| 594 | #if (!ASSUME_UNCONDITIONAL_CAU) |
| 595 | int dsp32c_device::condition(int cond) |
| 596 | { |
| 597 | switch (cond) |
| 598 | { |
| 599 | case 0: |
| 600 | return 0; |
| 601 | case 1: |
| 602 | return 1; |
| 603 | case 2: |
| 604 | return !nFLAG; |
| 605 | case 3: |
| 606 | return nFLAG; |
| 607 | case 4: |
| 608 | return !zFLAG; |
| 609 | case 5: |
| 610 | return zFLAG; |
| 611 | case 6: |
| 612 | return !vFLAG; |
| 613 | case 7: |
| 614 | return vFLAG; |
| 615 | case 8: |
| 616 | return !cFLAG; |
| 617 | case 9: |
| 618 | return cFLAG; |
| 619 | case 10: |
| 620 | return !(nFLAG ^ cFLAG); |
| 621 | case 11: |
| 622 | return (nFLAG ^ cFLAG); |
| 623 | case 12: |
| 624 | return !(zFLAG | (nFLAG ^ vFLAG)); |
| 625 | case 13: |
| 626 | return (zFLAG | (nFLAG ^ vFLAG)); |
| 627 | case 14: |
| 628 | return !(cFLAG | zFLAG); |
| 629 | case 15: |
| 630 | return (cFLAG | zFLAG); |
| 631 | |
| 632 | case 16: |
| 633 | return !(DEFERRED_VUFLAGS() & UFLAGBIT); |
| 634 | case 17: |
| 635 | return (DEFERRED_VUFLAGS() & UFLAGBIT); |
| 636 | case 18: |
| 637 | return !(DEFERRED_NZFLAGS() < 0); |
| 638 | case 19: |
| 639 | return (DEFERRED_NZFLAGS() < 0); |
| 640 | case 20: |
| 641 | return !(DEFERRED_NZFLAGS() == 0); |
| 642 | case 21: |
| 643 | return (DEFERRED_NZFLAGS() == 0); |
| 644 | case 22: |
| 645 | return !(DEFERRED_VUFLAGS() & VFLAGBIT); |
| 646 | case 23: |
| 647 | return (DEFERRED_VUFLAGS() & VFLAGBIT); |
| 648 | case 24: |
| 649 | return !(DEFERRED_NZFLAGS() <= 0); |
| 650 | case 25: |
| 651 | return (DEFERRED_NZFLAGS() <= 0); |
| 652 | |
| 653 | case 32: // !ibf |
| 654 | case 33: // ibf |
| 655 | case 34: // !obe |
| 656 | case 35: // obe |
| 657 | case 36: // !pdf |
| 658 | case 37: // pdf |
| 659 | case 38: // !pif |
| 660 | case 39: // pif |
| 661 | case 40: // !sy |
| 662 | case 41: // sy |
| 663 | case 42: // !fb |
| 664 | case 43: // fb |
| 665 | case 44: // !ireq1 |
| 666 | case 45: // ireq1 |
| 667 | case 46: // !ireq2 |
| 668 | case 47: // ireq2 |
| 669 | default: |
| 670 | fatalerror("Unimplemented condition: %X\n", cond); |
| 671 | } |
| 672 | } |
| 673 | #endif |
| 674 | |
| 675 | |
| 676 | |
| 677 | //************************************************************************** |
| 678 | // CAU BRANCH INSTRUCTION IMPLEMENTATION |
| 679 | //************************************************************************** |
| 680 | |
| 681 | void dsp32c_device::nop(UINT32 op) |
| 682 | { |
| 683 | if (op == 0) |
| 684 | return; |
| 685 | execute_one(); |
| 686 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 687 | } |
| 688 | |
| 689 | |
| 690 | void dsp32c_device::goto_t(UINT32 op) |
| 691 | { |
| 692 | execute_one(); |
| 693 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 694 | } |
| 695 | |
| 696 | |
| 697 | void dsp32c_device::goto_pl(UINT32 op) |
| 698 | { |
| 699 | if (!nFLAG) |
| 700 | { |
| 701 | execute_one(); |
| 702 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 703 | } |
| 704 | } |
| 705 | |
| 706 | |
| 707 | void dsp32c_device::goto_mi(UINT32 op) |
| 708 | { |
| 709 | if (nFLAG) |
| 710 | { |
| 711 | execute_one(); |
| 712 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 713 | } |
| 714 | } |
| 715 | |
| 716 | |
| 717 | void dsp32c_device::goto_ne(UINT32 op) |
| 718 | { |
| 719 | if (!zFLAG) |
| 720 | { |
| 721 | execute_one(); |
| 722 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 723 | } |
| 724 | } |
| 725 | |
| 726 | |
| 727 | void dsp32c_device::goto_eq(UINT32 op) |
| 728 | { |
| 729 | if (zFLAG) |
| 730 | { |
| 731 | execute_one(); |
| 732 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 733 | } |
| 734 | } |
| 735 | |
| 736 | |
| 737 | void dsp32c_device::goto_vc(UINT32 op) |
| 738 | { |
| 739 | if (!vFLAG) |
| 740 | { |
| 741 | execute_one(); |
| 742 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 743 | } |
| 744 | } |
| 745 | |
| 746 | |
| 747 | void dsp32c_device::goto_vs(UINT32 op) |
| 748 | { |
| 749 | if (vFLAG) |
| 750 | { |
| 751 | execute_one(); |
| 752 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 753 | } |
| 754 | } |
| 755 | |
| 756 | |
| 757 | void dsp32c_device::goto_cc(UINT32 op) |
| 758 | { |
| 759 | if (!cFLAG) |
| 760 | { |
| 761 | execute_one(); |
| 762 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 763 | } |
| 764 | } |
| 765 | |
| 766 | |
| 767 | void dsp32c_device::goto_cs(UINT32 op) |
| 768 | { |
| 769 | if (cFLAG) |
| 770 | { |
| 771 | execute_one(); |
| 772 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 773 | } |
| 774 | } |
| 775 | |
| 776 | |
| 777 | void dsp32c_device::goto_ge(UINT32 op) |
| 778 | { |
| 779 | if (!(nFLAG ^ vFLAG)) |
| 780 | { |
| 781 | execute_one(); |
| 782 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 783 | } |
| 784 | } |
| 785 | |
| 786 | |
| 787 | void dsp32c_device::goto_lt(UINT32 op) |
| 788 | { |
| 789 | if (nFLAG ^ vFLAG) |
| 790 | { |
| 791 | execute_one(); |
| 792 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 793 | } |
| 794 | } |
| 795 | |
| 796 | |
| 797 | void dsp32c_device::goto_gt(UINT32 op) |
| 798 | { |
| 799 | if (!(zFLAG | (nFLAG ^ vFLAG))) |
| 800 | { |
| 801 | execute_one(); |
| 802 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 803 | } |
| 804 | } |
| 805 | |
| 806 | |
| 807 | void dsp32c_device::goto_le(UINT32 op) |
| 808 | { |
| 809 | if (zFLAG | (nFLAG ^ vFLAG)) |
| 810 | { |
| 811 | execute_one(); |
| 812 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 813 | } |
| 814 | } |
| 815 | |
| 816 | |
| 817 | void dsp32c_device::goto_hi(UINT32 op) |
| 818 | { |
| 819 | if (!cFLAG && !zFLAG) |
| 820 | { |
| 821 | execute_one(); |
| 822 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 823 | } |
| 824 | } |
| 825 | |
| 826 | |
| 827 | void dsp32c_device::goto_ls(UINT32 op) |
| 828 | { |
| 829 | if (cFLAG || zFLAG) |
| 830 | { |
| 831 | execute_one(); |
| 832 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 833 | } |
| 834 | } |
| 835 | |
| 836 | |
| 837 | void dsp32c_device::goto_auc(UINT32 op) |
| 838 | { |
| 839 | if (!(DEFERRED_VUFLAGS() & UFLAGBIT)) |
| 840 | { |
| 841 | execute_one(); |
| 842 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 843 | } |
| 844 | } |
| 845 | |
| 846 | |
| 847 | void dsp32c_device::goto_aus(UINT32 op) |
| 848 | { |
| 849 | if (DEFERRED_VUFLAGS() & UFLAGBIT) |
| 850 | { |
| 851 | execute_one(); |
| 852 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 853 | } |
| 854 | } |
| 855 | |
| 856 | |
| 857 | void dsp32c_device::goto_age(UINT32 op) |
| 858 | { |
| 859 | if (DEFERRED_NZFLAGS() >= 0) |
| 860 | { |
| 861 | execute_one(); |
| 862 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 863 | } |
| 864 | } |
| 865 | |
| 866 | |
| 867 | void dsp32c_device::goto_alt(UINT32 op) |
| 868 | { |
| 869 | if (DEFERRED_NZFLAGS() < 0) |
| 870 | { |
| 871 | execute_one(); |
| 872 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 873 | } |
| 874 | } |
| 875 | |
| 876 | |
| 877 | void dsp32c_device::goto_ane(UINT32 op) |
| 878 | { |
| 879 | if (DEFERRED_NZFLAGS() != 0) |
| 880 | { |
| 881 | execute_one(); |
| 882 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 883 | } |
| 884 | } |
| 885 | |
| 886 | |
| 887 | void dsp32c_device::goto_aeq(UINT32 op) |
| 888 | { |
| 889 | if (DEFERRED_NZFLAGS() == 0) |
| 890 | { |
| 891 | execute_one(); |
| 892 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 893 | } |
| 894 | } |
| 895 | |
| 896 | |
| 897 | void dsp32c_device::goto_avc(UINT32 op) |
| 898 | { |
| 899 | if (!(DEFERRED_VUFLAGS() & VFLAGBIT)) |
| 900 | { |
| 901 | execute_one(); |
| 902 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 903 | } |
| 904 | } |
| 905 | |
| 906 | |
| 907 | void dsp32c_device::goto_avs(UINT32 op) |
| 908 | { |
| 909 | if (DEFERRED_VUFLAGS() & VFLAGBIT) |
| 910 | { |
| 911 | execute_one(); |
| 912 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 913 | } |
| 914 | } |
| 915 | |
| 916 | |
| 917 | void dsp32c_device::goto_agt(UINT32 op) |
| 918 | { |
| 919 | if (DEFERRED_NZFLAGS() > 0) |
| 920 | { |
| 921 | execute_one(); |
| 922 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 923 | } |
| 924 | } |
| 925 | |
| 926 | |
| 927 | void dsp32c_device::goto_ale(UINT32 op) |
| 928 | { |
| 929 | if (DEFERRED_NZFLAGS() <= 0) |
| 930 | { |
| 931 | execute_one(); |
| 932 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 933 | } |
| 934 | } |
| 935 | |
| 936 | |
| 937 | void dsp32c_device::goto_ibe(UINT32 op) |
| 938 | { |
| 939 | unimplemented(op); |
| 940 | } |
| 941 | |
| 942 | |
| 943 | void dsp32c_device::goto_ibf(UINT32 op) |
| 944 | { |
| 945 | unimplemented(op); |
| 946 | } |
| 947 | |
| 948 | |
| 949 | void dsp32c_device::goto_obf(UINT32 op) |
| 950 | { |
| 951 | unimplemented(op); |
| 952 | } |
| 953 | |
| 954 | |
| 955 | void dsp32c_device::goto_obe(UINT32 op) |
| 956 | { |
| 957 | unimplemented(op); |
| 958 | } |
| 959 | |
| 960 | |
| 961 | void dsp32c_device::goto_pde(UINT32 op) |
| 962 | { |
| 963 | if (!(m_pcr & PCR_PDFs)) |
| 964 | { |
| 965 | execute_one(); |
| 966 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 967 | } |
| 968 | } |
| 969 | |
| 970 | |
| 971 | void dsp32c_device::goto_pdf(UINT32 op) |
| 972 | { |
| 973 | if (m_pcr & PCR_PDFs) |
| 974 | { |
| 975 | execute_one(); |
| 976 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 977 | } |
| 978 | } |
| 979 | |
| 980 | |
| 981 | void dsp32c_device::goto_pie(UINT32 op) |
| 982 | { |
| 983 | if (!(m_pcr & PCR_PIFs)) |
| 984 | { |
| 985 | execute_one(); |
| 986 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 987 | } |
| 988 | } |
| 989 | |
| 990 | |
| 991 | void dsp32c_device::goto_pif(UINT32 op) |
| 992 | { |
| 993 | if (m_pcr & PCR_PIFs) |
| 994 | { |
| 995 | execute_one(); |
| 996 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 997 | } |
| 998 | } |
| 999 | |
| 1000 | |
| 1001 | void dsp32c_device::goto_syc(UINT32 op) |
| 1002 | { |
| 1003 | unimplemented(op); |
| 1004 | } |
| 1005 | |
| 1006 | |
| 1007 | void dsp32c_device::goto_sys(UINT32 op) |
| 1008 | { |
| 1009 | unimplemented(op); |
| 1010 | } |
| 1011 | |
| 1012 | |
| 1013 | void dsp32c_device::goto_fbc(UINT32 op) |
| 1014 | { |
| 1015 | unimplemented(op); |
| 1016 | } |
| 1017 | |
| 1018 | |
| 1019 | void dsp32c_device::goto_fbs(UINT32 op) |
| 1020 | { |
| 1021 | unimplemented(op); |
| 1022 | } |
| 1023 | |
| 1024 | |
| 1025 | void dsp32c_device::goto_irq1lo(UINT32 op) |
| 1026 | { |
| 1027 | unimplemented(op); |
| 1028 | } |
| 1029 | |
| 1030 | |
| 1031 | void dsp32c_device::goto_irq1hi(UINT32 op) |
| 1032 | { |
| 1033 | unimplemented(op); |
| 1034 | } |
| 1035 | |
| 1036 | |
| 1037 | void dsp32c_device::goto_irq2lo(UINT32 op) |
| 1038 | { |
| 1039 | unimplemented(op); |
| 1040 | } |
| 1041 | |
| 1042 | |
| 1043 | void dsp32c_device::goto_irq2hi(UINT32 op) |
| 1044 | { |
| 1045 | unimplemented(op); |
| 1046 | } |
| 1047 | |
| 1048 | |
| 1049 | void dsp32c_device::dec_goto(UINT32 op) |
| 1050 | { |
| 1051 | int hr = (op >> 21) & 0x1f; |
| 1052 | int old = (INT16)m_r[hr]; |
| 1053 | m_r[hr] = EXTEND16_TO_24(m_r[hr] - 1); |
| 1054 | if (old >= 0) |
| 1055 | { |
| 1056 | execute_one(); |
| 1057 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 1058 | } |
| 1059 | } |
| 1060 | |
| 1061 | |
| 1062 | void dsp32c_device::call(UINT32 op) |
| 1063 | { |
| 1064 | int mr = (op >> 21) & 0x1f; |
| 1065 | if (IS_WRITEABLE(mr)) |
| 1066 | m_r[mr] = PC + 4; |
| 1067 | execute_one(); |
| 1068 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (INT16)op); |
| 1069 | } |
| 1070 | |
| 1071 | |
| 1072 | void dsp32c_device::goto24(UINT32 op) |
| 1073 | { |
| 1074 | execute_one(); |
| 1075 | PC = TRUNCATE24(REG24((op >> 16) & 0x1f) + (op & 0xffff) + ((op >> 5) & 0xff0000)); |
| 1076 | } |
| 1077 | |
| 1078 | |
| 1079 | void dsp32c_device::call24(UINT32 op) |
| 1080 | { |
| 1081 | int mr = (op >> 16) & 0x1f; |
| 1082 | if (IS_WRITEABLE(mr)) |
| 1083 | m_r[mr] = PC + 4; |
| 1084 | execute_one(); |
| 1085 | PC = (op & 0xffff) + ((op >> 5) & 0xff0000); |
| 1086 | } |
| 1087 | |
| 1088 | |
| 1089 | void dsp32c_device::do_i(UINT32 op) |
| 1090 | { |
| 1091 | unimplemented(op); |
| 1092 | } |
| 1093 | |
| 1094 | |
| 1095 | void dsp32c_device::do_r(UINT32 op) |
| 1096 | { |
| 1097 | unimplemented(op); |
| 1098 | } |
| 1099 | |
| 1100 | |
| 1101 | |
| 1102 | //************************************************************************** |
| 1103 | // CAU 16-BIT ARITHMETIC IMPLEMENTATION |
| 1104 | //************************************************************************** |
| 1105 | |
| 1106 | void dsp32c_device::add_si(UINT32 op) |
| 1107 | { |
| 1108 | int dr = (op >> 21) & 0x1f; |
| 1109 | int hrval = REG16((op >> 16) & 0x1f); |
| 1110 | int res = hrval + (UINT16)op; |
| 1111 | if (IS_WRITEABLE(dr)) |
| 1112 | m_r[dr] = EXTEND16_TO_24(res); |
| 1113 | SET_NZCV_16(hrval, op, res); |
| 1114 | } |
| 1115 | |
| 1116 | |
| 1117 | void dsp32c_device::add_ss(UINT32 op) |
| 1118 | { |
| 1119 | if (CONDITION_IS_TRUE()) |
| 1120 | { |
| 1121 | int dr = (op >> 16) & 0x1f; |
| 1122 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1123 | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1124 | int res = s2rval + s1rval; |
| 1125 | if (IS_WRITEABLE(dr)) |
| 1126 | m_r[dr] = EXTEND16_TO_24(res); |
| 1127 | SET_NZCV_16(s1rval, s2rval, res); |
| 1128 | } |
| 1129 | } |
| 1130 | |
| 1131 | |
| 1132 | void dsp32c_device::mul2_s(UINT32 op) |
| 1133 | { |
| 1134 | if (CONDITION_IS_TRUE()) |
| 1135 | { |
| 1136 | int dr = (op >> 16) & 0x1f; |
| 1137 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1138 | int res = s1rval * 2; |
| 1139 | if (IS_WRITEABLE(dr)) |
| 1140 | m_r[dr] = EXTEND16_TO_24(res); |
| 1141 | SET_NZCV_16(s1rval, 0, res); |
| 1142 | } |
| 1143 | } |
| 1144 | |
| 1145 | |
| 1146 | void dsp32c_device::subr_ss(UINT32 op) |
| 1147 | { |
| 1148 | if (CONDITION_IS_TRUE()) |
| 1149 | { |
| 1150 | int dr = (op >> 16) & 0x1f; |
| 1151 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1152 | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1153 | int res = s1rval - s2rval; |
| 1154 | if (IS_WRITEABLE(dr)) |
| 1155 | m_r[dr] = EXTEND16_TO_24(res); |
| 1156 | SET_NZCV_16(s1rval, s2rval, res); |
| 1157 | } |
| 1158 | } |
| 1159 | |
| 1160 | |
| 1161 | void dsp32c_device::addr_ss(UINT32 op) |
| 1162 | { |
| 1163 | unimplemented(op); |
| 1164 | } |
| 1165 | |
| 1166 | |
| 1167 | void dsp32c_device::sub_ss(UINT32 op) |
| 1168 | { |
| 1169 | if (CONDITION_IS_TRUE()) |
| 1170 | { |
| 1171 | int dr = (op >> 16) & 0x1f; |
| 1172 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1173 | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1174 | int res = s2rval - s1rval; |
| 1175 | if (IS_WRITEABLE(dr)) |
| 1176 | m_r[dr] = EXTEND16_TO_24(res); |
| 1177 | SET_NZCV_16(s1rval, s2rval, res); |
| 1178 | } |
| 1179 | } |
| 1180 | |
| 1181 | |
| 1182 | void dsp32c_device::neg_s(UINT32 op) |
| 1183 | { |
| 1184 | if (CONDITION_IS_TRUE()) |
| 1185 | { |
| 1186 | int dr = (op >> 16) & 0x1f; |
| 1187 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1188 | int res = -s1rval; |
| 1189 | if (IS_WRITEABLE(dr)) |
| 1190 | m_r[dr] = EXTEND16_TO_24(res); |
| 1191 | SET_NZCV_16(s1rval, 0, res); |
| 1192 | } |
| 1193 | } |
| 1194 | |
| 1195 | |
| 1196 | void dsp32c_device::andc_ss(UINT32 op) |
| 1197 | { |
| 1198 | if (CONDITION_IS_TRUE()) |
| 1199 | { |
| 1200 | int dr = (op >> 16) & 0x1f; |
| 1201 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1202 | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1203 | int res = s2rval & ~s1rval; |
| 1204 | if (IS_WRITEABLE(dr)) |
| 1205 | m_r[dr] = EXTEND16_TO_24(res); |
| 1206 | SET_NZ00_16(res); |
| 1207 | } |
| 1208 | } |
| 1209 | |
| 1210 | |
| 1211 | void dsp32c_device::cmp_ss(UINT32 op) |
| 1212 | { |
| 1213 | if (CONDITION_IS_TRUE()) |
| 1214 | { |
| 1215 | int drval = REG16((op >> 16) & 0x1f); |
| 1216 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1217 | int res = drval - s1rval; |
| 1218 | SET_NZCV_16(drval, s1rval, res); |
| 1219 | } |
| 1220 | } |
| 1221 | |
| 1222 | |
| 1223 | void dsp32c_device::xor_ss(UINT32 op) |
| 1224 | { |
| 1225 | if (CONDITION_IS_TRUE()) |
| 1226 | { |
| 1227 | int dr = (op >> 16) & 0x1f; |
| 1228 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1229 | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1230 | int res = s2rval ^ s1rval; |
| 1231 | if (IS_WRITEABLE(dr)) |
| 1232 | m_r[dr] = EXTEND16_TO_24(res); |
| 1233 | SET_NZ00_16(res); |
| 1234 | } |
| 1235 | } |
| 1236 | |
| 1237 | |
| 1238 | void dsp32c_device::rcr_s(UINT32 op) |
| 1239 | { |
| 1240 | if (CONDITION_IS_TRUE()) |
| 1241 | { |
| 1242 | int dr = (op >> 16) & 0x1f; |
| 1243 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1244 | int res = ((m_nzcflags >> 9) & 0x8000) | (s1rval >> 1); |
| 1245 | if (IS_WRITEABLE(dr)) |
| 1246 | m_r[dr] = EXTEND16_TO_24(res); |
| 1247 | m_nzcflags = ((res & 0xffff) << 8) | ((s1rval & 1) << 24); |
| 1248 | m_vflags = 0; |
| 1249 | } |
| 1250 | } |
| 1251 | |
| 1252 | |
| 1253 | void dsp32c_device::or_ss(UINT32 op) |
| 1254 | { |
| 1255 | if (CONDITION_IS_TRUE()) |
| 1256 | { |
| 1257 | int dr = (op >> 16) & 0x1f; |
| 1258 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1259 | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1260 | int res = s2rval | s1rval; |
| 1261 | if (IS_WRITEABLE(dr)) |
| 1262 | m_r[dr] = EXTEND16_TO_24(res); |
| 1263 | SET_NZ00_16(res); |
| 1264 | } |
| 1265 | } |
| 1266 | |
| 1267 | |
| 1268 | void dsp32c_device::rcl_s(UINT32 op) |
| 1269 | { |
| 1270 | if (CONDITION_IS_TRUE()) |
| 1271 | { |
| 1272 | int dr = (op >> 16) & 0x1f; |
| 1273 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1274 | int res = ((m_nzcflags >> 24) & 0x0001) | (s1rval << 1); |
| 1275 | if (IS_WRITEABLE(dr)) |
| 1276 | m_r[dr] = EXTEND16_TO_24(res); |
| 1277 | m_nzcflags = ((res & 0xffff) << 8) | ((s1rval & 0x8000) << 9); |
| 1278 | m_vflags = 0; |
| 1279 | } |
| 1280 | } |
| 1281 | |
| 1282 | |
| 1283 | void dsp32c_device::shr_s(UINT32 op) |
| 1284 | { |
| 1285 | if (CONDITION_IS_TRUE()) |
| 1286 | { |
| 1287 | int dr = (op >> 16) & 0x1f; |
| 1288 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1289 | int res = s1rval >> 1; |
| 1290 | if (IS_WRITEABLE(dr)) |
| 1291 | m_r[dr] = EXTEND16_TO_24(res); |
| 1292 | m_nzcflags = ((res & 0xffff) << 8) | ((s1rval & 1) << 24); |
| 1293 | m_vflags = 0; |
| 1294 | } |
| 1295 | } |
| 1296 | |
| 1297 | |
| 1298 | void dsp32c_device::div2_s(UINT32 op) |
| 1299 | { |
| 1300 | if (CONDITION_IS_TRUE()) |
| 1301 | { |
| 1302 | int dr = (op >> 16) & 0x1f; |
| 1303 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1304 | int res = (s1rval & 0x8000) | (s1rval >> 1); |
| 1305 | if (IS_WRITEABLE(dr)) |
| 1306 | m_r[dr] = EXTEND16_TO_24(res); |
| 1307 | m_nzcflags = ((res & 0xffff) << 8) | ((s1rval & 1) << 24); |
| 1308 | m_vflags = 0; |
| 1309 | } |
| 1310 | } |
| 1311 | |
| 1312 | |
| 1313 | void dsp32c_device::and_ss(UINT32 op) |
| 1314 | { |
| 1315 | if (CONDITION_IS_TRUE()) |
| 1316 | { |
| 1317 | int dr = (op >> 16) & 0x1f; |
| 1318 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1319 | int s2rval = (op & 0x800) ? REG16((op >> 0) & 0x1f) : REG16(dr); |
| 1320 | int res = s2rval & s1rval; |
| 1321 | if (IS_WRITEABLE(dr)) |
| 1322 | m_r[dr] = EXTEND16_TO_24(res); |
| 1323 | SET_NZ00_16(res); |
| 1324 | } |
| 1325 | } |
| 1326 | |
| 1327 | |
| 1328 | void dsp32c_device::test_ss(UINT32 op) |
| 1329 | { |
| 1330 | if (CONDITION_IS_TRUE()) |
| 1331 | { |
| 1332 | int drval = REG16((op >> 16) & 0x1f); |
| 1333 | int s1rval = REG16((op >> 5) & 0x1f); |
| 1334 | int res = drval & s1rval; |
| 1335 | SET_NZ00_16(res); |
| 1336 | } |
| 1337 | } |
| 1338 | |
| 1339 | |
| 1340 | void dsp32c_device::add_di(UINT32 op) |
| 1341 | { |
| 1342 | int dr = (op >> 16) & 0x1f; |
| 1343 | int drval = REG16(dr); |
| 1344 | int res = drval + (UINT16)op; |
| 1345 | if (IS_WRITEABLE(dr)) |
| 1346 | m_r[dr] = EXTEND16_TO_24(res); |
| 1347 | SET_NZCV_16(drval, op, res); |
| 1348 | } |
| 1349 | |
| 1350 | |
| 1351 | void dsp32c_device::subr_di(UINT32 op) |
| 1352 | { |
| 1353 | int dr = (op >> 16) & 0x1f; |
| 1354 | int drval = REG16(dr); |
| 1355 | int res = (UINT16)op - drval; |
| 1356 | if (IS_WRITEABLE(dr)) |
| 1357 | m_r[dr] = EXTEND16_TO_24(res); |
| 1358 | SET_NZCV_16(drval, op, res); |
| 1359 | } |
| 1360 | |
| 1361 | |
| 1362 | void dsp32c_device::addr_di(UINT32 op) |
| 1363 | { |
| 1364 | unimplemented(op); |
| 1365 | } |
| 1366 | |
| 1367 | |
| 1368 | void dsp32c_device::sub_di(UINT32 op) |
| 1369 | { |
| 1370 | int dr = (op >> 16) & 0x1f; |
| 1371 | int drval = REG16(dr); |
| 1372 | int res = drval - (UINT16)op; |
| 1373 | if (IS_WRITEABLE(dr)) |
| 1374 | m_r[dr] = EXTEND16_TO_24(res); |
| 1375 | SET_NZCV_16(drval, op, res); |
| 1376 | } |
| 1377 | |
| 1378 | |
| 1379 | void dsp32c_device::andc_di(UINT32 op) |
| 1380 | { |
| 1381 | int dr = (op >> 16) & 0x1f; |
| 1382 | int drval = REG16(dr); |
| 1383 | int res = drval & ~(UINT16)op; |
| 1384 | if (IS_WRITEABLE(dr)) |
| 1385 | m_r[dr] = EXTEND16_TO_24(res); |
| 1386 | SET_NZ00_16(res); |
| 1387 | } |
| 1388 | |
| 1389 | |
| 1390 | void dsp32c_device::cmp_di(UINT32 op) |
| 1391 | { |
| 1392 | int drval = REG16((op >> 16) & 0x1f); |
| 1393 | int res = drval - (UINT16)op; |
| 1394 | SET_NZCV_16(drval, op, res); |
| 1395 | } |
| 1396 | |
| 1397 | |
| 1398 | void dsp32c_device::xor_di(UINT32 op) |
| 1399 | { |
| 1400 | int dr = (op >> 16) & 0x1f; |
| 1401 | int drval = REG16(dr); |
| 1402 | int res = drval ^ (UINT16)op; |
| 1403 | if (IS_WRITEABLE(dr)) |
| 1404 | m_r[dr] = EXTEND16_TO_24(res); |
| 1405 | SET_NZ00_16(res); |
| 1406 | } |
| 1407 | |
| 1408 | |
| 1409 | void dsp32c_device::or_di(UINT32 op) |
| 1410 | { |
| 1411 | int dr = (op >> 16) & 0x1f; |
| 1412 | int drval = REG16(dr); |
| 1413 | int res = drval | (UINT16)op; |
| 1414 | if (IS_WRITEABLE(dr)) |
| 1415 | m_r[dr] = EXTEND16_TO_24(res); |
| 1416 | SET_NZ00_16(res); |
| 1417 | } |
| 1418 | |
| 1419 | |
| 1420 | void dsp32c_device::and_di(UINT32 op) |
| 1421 | { |
| 1422 | int dr = (op >> 16) & 0x1f; |
| 1423 | int drval = REG16(dr); |
| 1424 | int res = drval & (UINT16)op; |
| 1425 | if (IS_WRITEABLE(dr)) |
| 1426 | m_r[dr] = EXTEND16_TO_24(res); |
| 1427 | SET_NZ00_16(res); |
| 1428 | } |
| 1429 | |
| 1430 | |
| 1431 | void dsp32c_device::test_di(UINT32 op) |
| 1432 | { |
| 1433 | int drval = REG16((op >> 16) & 0x1f); |
| 1434 | int res = drval & (UINT16)op; |
| 1435 | SET_NZ00_16(res); |
| 1436 | } |
| 1437 | |
| 1438 | |
| 1439 | |
| 1440 | //************************************************************************** |
| 1441 | // CAU 24-BIT ARITHMETIC IMPLEMENTATION |
| 1442 | //************************************************************************** |
| 1443 | |
| 1444 | void dsp32c_device::adde_si(UINT32 op) |
| 1445 | { |
| 1446 | int dr = (op >> 21) & 0x1f; |
| 1447 | int hrval = REG24((op >> 16) & 0x1f); |
| 1448 | int res = hrval + EXTEND16_TO_24(op); |
| 1449 | if (IS_WRITEABLE(dr)) |
| 1450 | m_r[dr] = TRUNCATE24(res); |
| 1451 | SET_NZCV_24(hrval, op << 8, res); |
| 1452 | } |
| 1453 | |
| 1454 | |
| 1455 | void dsp32c_device::adde_ss(UINT32 op) |
| 1456 | { |
| 1457 | if (CONDITION_IS_TRUE()) |
| 1458 | { |
| 1459 | int dr = (op >> 16) & 0x1f; |
| 1460 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1461 | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1462 | int res = s2rval + s1rval; |
| 1463 | if (IS_WRITEABLE(dr)) |
| 1464 | m_r[dr] = TRUNCATE24(res); |
| 1465 | SET_NZCV_24(s1rval, s2rval, res); |
| 1466 | } |
| 1467 | } |
| 1468 | |
| 1469 | |
| 1470 | void dsp32c_device::mul2e_s(UINT32 op) |
| 1471 | { |
| 1472 | if (CONDITION_IS_TRUE()) |
| 1473 | { |
| 1474 | int dr = (op >> 16) & 0x1f; |
| 1475 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1476 | int res = s1rval * 2; |
| 1477 | if (IS_WRITEABLE(dr)) |
| 1478 | m_r[dr] = TRUNCATE24(res); |
| 1479 | SET_NZCV_24(s1rval, 0, res); |
| 1480 | } |
| 1481 | } |
| 1482 | |
| 1483 | |
| 1484 | void dsp32c_device::subre_ss(UINT32 op) |
| 1485 | { |
| 1486 | if (CONDITION_IS_TRUE()) |
| 1487 | { |
| 1488 | int dr = (op >> 16) & 0x1f; |
| 1489 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1490 | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1491 | int res = s1rval - s2rval; |
| 1492 | if (IS_WRITEABLE(dr)) |
| 1493 | m_r[dr] = TRUNCATE24(res); |
| 1494 | SET_NZCV_24(s1rval, s2rval, res); |
| 1495 | } |
| 1496 | } |
| 1497 | |
| 1498 | |
| 1499 | void dsp32c_device::addre_ss(UINT32 op) |
| 1500 | { |
| 1501 | unimplemented(op); |
| 1502 | } |
| 1503 | |
| 1504 | |
| 1505 | void dsp32c_device::sube_ss(UINT32 op) |
| 1506 | { |
| 1507 | if (CONDITION_IS_TRUE()) |
| 1508 | { |
| 1509 | int dr = (op >> 16) & 0x1f; |
| 1510 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1511 | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1512 | int res = s2rval - s1rval; |
| 1513 | if (IS_WRITEABLE(dr)) |
| 1514 | m_r[dr] = TRUNCATE24(res); |
| 1515 | SET_NZCV_24(s1rval, s2rval, res); |
| 1516 | } |
| 1517 | } |
| 1518 | |
| 1519 | |
| 1520 | void dsp32c_device::nege_s(UINT32 op) |
| 1521 | { |
| 1522 | if (CONDITION_IS_TRUE()) |
| 1523 | { |
| 1524 | int dr = (op >> 16) & 0x1f; |
| 1525 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1526 | int res = -s1rval; |
| 1527 | if (IS_WRITEABLE(dr)) |
| 1528 | m_r[dr] = TRUNCATE24(res); |
| 1529 | SET_NZCV_24(s1rval, 0, res); |
| 1530 | } |
| 1531 | } |
| 1532 | |
| 1533 | |
| 1534 | void dsp32c_device::andce_ss(UINT32 op) |
| 1535 | { |
| 1536 | if (CONDITION_IS_TRUE()) |
| 1537 | { |
| 1538 | int dr = (op >> 16) & 0x1f; |
| 1539 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1540 | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1541 | int res = s2rval & ~s1rval; |
| 1542 | if (IS_WRITEABLE(dr)) |
| 1543 | m_r[dr] = res; |
| 1544 | SET_NZ00_24(res); |
| 1545 | } |
| 1546 | } |
| 1547 | |
| 1548 | |
| 1549 | void dsp32c_device::cmpe_ss(UINT32 op) |
| 1550 | { |
| 1551 | if (CONDITION_IS_TRUE()) |
| 1552 | { |
| 1553 | int drval = REG24((op >> 16) & 0x1f); |
| 1554 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1555 | int res = drval - s1rval; |
| 1556 | SET_NZCV_24(drval, s1rval, res); |
| 1557 | } |
| 1558 | } |
| 1559 | |
| 1560 | |
| 1561 | void dsp32c_device::xore_ss(UINT32 op) |
| 1562 | { |
| 1563 | if (CONDITION_IS_TRUE()) |
| 1564 | { |
| 1565 | int dr = (op >> 16) & 0x1f; |
| 1566 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1567 | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1568 | int res = s2rval ^ s1rval; |
| 1569 | if (IS_WRITEABLE(dr)) |
| 1570 | m_r[dr] = res; |
| 1571 | SET_NZ00_24(res); |
| 1572 | } |
| 1573 | } |
| 1574 | |
| 1575 | |
| 1576 | void dsp32c_device::rcre_s(UINT32 op) |
| 1577 | { |
| 1578 | if (CONDITION_IS_TRUE()) |
| 1579 | { |
| 1580 | int dr = (op >> 16) & 0x1f; |
| 1581 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1582 | int res = ((m_nzcflags >> 1) & 0x800000) | (s1rval >> 1); |
| 1583 | if (IS_WRITEABLE(dr)) |
| 1584 | m_r[dr] = TRUNCATE24(res); |
| 1585 | m_nzcflags = res | ((s1rval & 1) << 24); |
| 1586 | m_vflags = 0; |
| 1587 | } |
| 1588 | } |
| 1589 | |
| 1590 | |
| 1591 | void dsp32c_device::ore_ss(UINT32 op) |
| 1592 | { |
| 1593 | if (CONDITION_IS_TRUE()) |
| 1594 | { |
| 1595 | int dr = (op >> 16) & 0x1f; |
| 1596 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1597 | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1598 | int res = s2rval | s1rval; |
| 1599 | if (IS_WRITEABLE(dr)) |
| 1600 | m_r[dr] = res; |
| 1601 | SET_NZ00_24(res); |
| 1602 | } |
| 1603 | } |
| 1604 | |
| 1605 | |
| 1606 | void dsp32c_device::rcle_s(UINT32 op) |
| 1607 | { |
| 1608 | if (CONDITION_IS_TRUE()) |
| 1609 | { |
| 1610 | int dr = (op >> 16) & 0x1f; |
| 1611 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1612 | int res = ((m_nzcflags >> 24) & 0x000001) | (s1rval << 1); |
| 1613 | if (IS_WRITEABLE(dr)) |
| 1614 | m_r[dr] = TRUNCATE24(res); |
| 1615 | m_nzcflags = res | ((s1rval & 0x800000) << 1); |
| 1616 | m_vflags = 0; |
| 1617 | } |
| 1618 | } |
| 1619 | |
| 1620 | |
| 1621 | void dsp32c_device::shre_s(UINT32 op) |
| 1622 | { |
| 1623 | if (CONDITION_IS_TRUE()) |
| 1624 | { |
| 1625 | int dr = (op >> 16) & 0x1f; |
| 1626 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1627 | int res = s1rval >> 1; |
| 1628 | if (IS_WRITEABLE(dr)) |
| 1629 | m_r[dr] = res; |
| 1630 | m_nzcflags = res | ((s1rval & 1) << 24); |
| 1631 | m_vflags = 0; |
| 1632 | } |
| 1633 | } |
| 1634 | |
| 1635 | |
| 1636 | void dsp32c_device::div2e_s(UINT32 op) |
| 1637 | { |
| 1638 | if (CONDITION_IS_TRUE()) |
| 1639 | { |
| 1640 | int dr = (op >> 16) & 0x1f; |
| 1641 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1642 | int res = (s1rval & 0x800000) | (s1rval >> 1); |
| 1643 | if (IS_WRITEABLE(dr)) |
| 1644 | m_r[dr] = TRUNCATE24(res); |
| 1645 | m_nzcflags = res | ((s1rval & 1) << 24); |
| 1646 | m_vflags = 0; |
| 1647 | } |
| 1648 | } |
| 1649 | |
| 1650 | |
| 1651 | void dsp32c_device::ande_ss(UINT32 op) |
| 1652 | { |
| 1653 | if (CONDITION_IS_TRUE()) |
| 1654 | { |
| 1655 | int dr = (op >> 16) & 0x1f; |
| 1656 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1657 | int s2rval = (op & 0x800) ? REG24((op >> 0) & 0x1f) : REG24(dr); |
| 1658 | int res = s2rval & s1rval; |
| 1659 | if (IS_WRITEABLE(dr)) |
| 1660 | m_r[dr] = res; |
| 1661 | SET_NZ00_24(res); |
| 1662 | } |
| 1663 | } |
| 1664 | |
| 1665 | |
| 1666 | void dsp32c_device::teste_ss(UINT32 op) |
| 1667 | { |
| 1668 | if (CONDITION_IS_TRUE()) |
| 1669 | { |
| 1670 | int drval = REG24((op >> 16) & 0x1f); |
| 1671 | int s1rval = REG24((op >> 5) & 0x1f); |
| 1672 | int res = drval & s1rval; |
| 1673 | SET_NZ00_24(res); |
| 1674 | } |
| 1675 | } |
| 1676 | |
| 1677 | |
| 1678 | void dsp32c_device::adde_di(UINT32 op) |
| 1679 | { |
| 1680 | int dr = (op >> 16) & 0x1f; |
| 1681 | int drval = REG24(dr); |
| 1682 | int res = drval + EXTEND16_TO_24(op); |
| 1683 | if (IS_WRITEABLE(dr)) |
| 1684 | m_r[dr] = TRUNCATE24(res); |
| 1685 | SET_NZCV_24(drval, op << 8, res); |
| 1686 | } |
| 1687 | |
| 1688 | |
| 1689 | void dsp32c_device::subre_di(UINT32 op) |
| 1690 | { |
| 1691 | int dr = (op >> 16) & 0x1f; |
| 1692 | int drval = REG24(dr); |
| 1693 | int res = EXTEND16_TO_24(op) - drval; |
| 1694 | if (IS_WRITEABLE(dr)) |
| 1695 | m_r[dr] = TRUNCATE24(res); |
| 1696 | SET_NZCV_24(drval, op << 8, res); |
| 1697 | } |
| 1698 | |
| 1699 | |
| 1700 | void dsp32c_device::addre_di(UINT32 op) |
| 1701 | { |
| 1702 | unimplemented(op); |
| 1703 | } |
| 1704 | |
| 1705 | |
| 1706 | void dsp32c_device::sube_di(UINT32 op) |
| 1707 | { |
| 1708 | int dr = (op >> 16) & 0x1f; |
| 1709 | int drval = REG24(dr); |
| 1710 | int res = drval - EXTEND16_TO_24(op); |
| 1711 | if (IS_WRITEABLE(dr)) |
| 1712 | m_r[dr] = TRUNCATE24(res); |
| 1713 | SET_NZCV_24(drval, op << 8, res); |
| 1714 | } |
| 1715 | |
| 1716 | |
| 1717 | void dsp32c_device::andce_di(UINT32 op) |
| 1718 | { |
| 1719 | int dr = (op >> 16) & 0x1f; |
| 1720 | int drval = REG24(dr); |
| 1721 | int res = drval & ~EXTEND16_TO_24(op); |
| 1722 | if (IS_WRITEABLE(dr)) |
| 1723 | m_r[dr] = res; |
| 1724 | SET_NZ00_24(res); |
| 1725 | } |
| 1726 | |
| 1727 | |
| 1728 | void dsp32c_device::cmpe_di(UINT32 op) |
| 1729 | { |
| 1730 | int drval = REG24((op >> 16) & 0x1f); |
| 1731 | int res = drval - EXTEND16_TO_24(op); |
| 1732 | SET_NZCV_24(drval, op << 8, res); |
| 1733 | } |
| 1734 | |
| 1735 | |
| 1736 | void dsp32c_device::xore_di(UINT32 op) |
| 1737 | { |
| 1738 | int dr = (op >> 16) & 0x1f; |
| 1739 | int drval = REG24(dr); |
| 1740 | int res = drval ^ EXTEND16_TO_24(op); |
| 1741 | if (IS_WRITEABLE(dr)) |
| 1742 | m_r[dr] = res; |
| 1743 | SET_NZ00_24(res); |
| 1744 | } |
| 1745 | |
| 1746 | |
| 1747 | void dsp32c_device::ore_di(UINT32 op) |
| 1748 | { |
| 1749 | int dr = (op >> 16) & 0x1f; |
| 1750 | int drval = REG24(dr); |
| 1751 | int res = drval | EXTEND16_TO_24(op); |
| 1752 | if (IS_WRITEABLE(dr)) |
| 1753 | m_r[dr] = res; |
| 1754 | SET_NZ00_24(res); |
| 1755 | } |
| 1756 | |
| 1757 | |
| 1758 | void dsp32c_device::ande_di(UINT32 op) |
| 1759 | { |
| 1760 | int dr = (op >> 16) & 0x1f; |
| 1761 | int drval = REG24(dr); |
| 1762 | int res = drval & EXTEND16_TO_24(op); |
| 1763 | if (IS_WRITEABLE(dr)) |
| 1764 | m_r[dr] = res; |
| 1765 | SET_NZ00_24(res); |
| 1766 | } |
| 1767 | |
| 1768 | |
| 1769 | void dsp32c_device::teste_di(UINT32 op) |
| 1770 | { |
| 1771 | int drval = REG24((op >> 16) & 0x1f); |
| 1772 | int res = drval & EXTEND16_TO_24(op); |
| 1773 | SET_NZ00_24(res); |
| 1774 | } |
| 1775 | |
| 1776 | |
| 1777 | |
| 1778 | //************************************************************************** |
| 1779 | // CAU LOAD/STORE IMPLEMENTATION |
| 1780 | //************************************************************************** |
| 1781 | |
| 1782 | void dsp32c_device::load_hi(UINT32 op) |
| 1783 | { |
| 1784 | int dr = (op >> 16) & 0x1f; |
| 1785 | UINT32 res = RBYTE(EXTEND16_TO_24(op)); |
| 1786 | if (IS_WRITEABLE(dr)) |
| 1787 | m_r[dr] = EXTEND16_TO_24(res); |
| 1788 | m_nzcflags = res << 8; |
| 1789 | m_vflags = 0; |
| 1790 | } |
| 1791 | |
| 1792 | |
| 1793 | void dsp32c_device::load_li(UINT32 op) |
| 1794 | { |
| 1795 | int dr = (op >> 16) & 0x1f; |
| 1796 | UINT32 res = RBYTE(EXTEND16_TO_24(op)); |
| 1797 | if (IS_WRITEABLE(dr)) |
| 1798 | m_r[dr] = res; |
| 1799 | m_nzcflags = res << 8; |
| 1800 | m_vflags = 0; |
| 1801 | } |
| 1802 | |
| 1803 | |
| 1804 | void dsp32c_device::load_i(UINT32 op) |
| 1805 | { |
| 1806 | UINT32 res = RWORD(EXTEND16_TO_24(op)); |
| 1807 | int dr = (op >> 16) & 0x1f; |
| 1808 | if (IS_WRITEABLE(dr)) |
| 1809 | m_r[dr] = EXTEND16_TO_24(res); |
| 1810 | m_nzcflags = res << 8; |
| 1811 | m_vflags = 0; |
| 1812 | } |
| 1813 | |
| 1814 | |
| 1815 | void dsp32c_device::load_ei(UINT32 op) |
| 1816 | { |
| 1817 | UINT32 res = TRUNCATE24(RLONG(EXTEND16_TO_24(op))); |
| 1818 | int dr = (op >> 16) & 0x1f; |
| 1819 | if (IS_WRITEABLE(dr)) |
| 1820 | m_r[dr] = res; |
| 1821 | m_nzcflags = res; |
| 1822 | m_vflags = 0; |
| 1823 | } |
| 1824 | |
| 1825 | |
| 1826 | void dsp32c_device::store_hi(UINT32 op) |
| 1827 | { |
| 1828 | WBYTE(EXTEND16_TO_24(op), m_r[(op >> 16) & 0x1f] >> 8); |
| 1829 | } |
| 1830 | |
| 1831 | |
| 1832 | void dsp32c_device::store_li(UINT32 op) |
| 1833 | { |
| 1834 | WBYTE(EXTEND16_TO_24(op), m_r[(op >> 16) & 0x1f]); |
| 1835 | } |
| 1836 | |
| 1837 | |
| 1838 | void dsp32c_device::store_i(UINT32 op) |
| 1839 | { |
| 1840 | WWORD(EXTEND16_TO_24(op), REG16((op >> 16) & 0x1f)); |
| 1841 | } |
| 1842 | |
| 1843 | |
| 1844 | void dsp32c_device::store_ei(UINT32 op) |
| 1845 | { |
| 1846 | WLONG(EXTEND16_TO_24(op), (INT32)(REG24((op >> 16) & 0x1f) << 8) >> 8); |
| 1847 | } |
| 1848 | |
| 1849 | |
| 1850 | void dsp32c_device::load_hr(UINT32 op) |
| 1851 | { |
| 1852 | if (!(op & 0x400)) |
| 1853 | { |
| 1854 | int dr = (op >> 16) & 0x1f; |
| 1855 | UINT32 res = cau_read_pi_1byte(op) << 8; |
| 1856 | if (IS_WRITEABLE(dr)) |
| 1857 | m_r[dr] = EXTEND16_TO_24(res); |
| 1858 | m_nzcflags = res << 8; |
| 1859 | m_vflags = 0; |
| 1860 | } |
| 1861 | else |
| 1862 | unimplemented(op); |
| 1863 | } |
| 1864 | |
| 1865 | |
| 1866 | void dsp32c_device::load_lr(UINT32 op) |
| 1867 | { |
| 1868 | if (!(op & 0x400)) |
| 1869 | { |
| 1870 | int dr = (op >> 16) & 0x1f; |
| 1871 | UINT32 res = cau_read_pi_1byte(op); |
| 1872 | if (IS_WRITEABLE(dr)) |
| 1873 | m_r[dr] = res; |
| 1874 | m_nzcflags = res << 8; |
| 1875 | m_vflags = 0; |
| 1876 | } |
| 1877 | else |
| 1878 | unimplemented(op); |
| 1879 | } |
| 1880 | |
| 1881 | |
| 1882 | void dsp32c_device::load_r(UINT32 op) |
| 1883 | { |
| 1884 | if (!(op & 0x400)) |
| 1885 | { |
| 1886 | UINT32 res = cau_read_pi_2byte(op); |
| 1887 | int dr = (op >> 16) & 0x1f; |
| 1888 | if (IS_WRITEABLE(dr)) |
| 1889 | m_r[dr] = EXTEND16_TO_24(res); |
| 1890 | m_nzcflags = res << 8; |
| 1891 | m_vflags = 0; |
| 1892 | } |
| 1893 | else |
| 1894 | unimplemented(op); |
| 1895 | } |
| 1896 | |
| 1897 | |
| 1898 | void dsp32c_device::load_er(UINT32 op) |
| 1899 | { |
| 1900 | if (!(op & 0x400)) |
| 1901 | { |
| 1902 | UINT32 res = TRUNCATE24(cau_read_pi_4byte(op)); |
| 1903 | int dr = (op >> 16) & 0x1f; |
| 1904 | if (IS_WRITEABLE(dr)) |
| 1905 | m_r[dr] = res; |
| 1906 | m_nzcflags = res; |
| 1907 | m_vflags = 0; |
| 1908 | } |
| 1909 | else |
| 1910 | unimplemented(op); |
| 1911 | } |
| 1912 | |
| 1913 | |
| 1914 | void dsp32c_device::store_hr(UINT32 op) |
| 1915 | { |
| 1916 | if (!(op & 0x400)) |
| 1917 | cau_write_pi_1byte(op, m_r[(op >> 16) & 0x1f] >> 8); |
| 1918 | else |
| 1919 | unimplemented(op); |
| 1920 | } |
| 1921 | |
| 1922 | |
| 1923 | void dsp32c_device::store_lr(UINT32 op) |
| 1924 | { |
| 1925 | if (!(op & 0x400)) |
| 1926 | cau_write_pi_1byte(op, m_r[(op >> 16) & 0x1f]); |
| 1927 | else |
| 1928 | unimplemented(op); |
| 1929 | } |
| 1930 | |
| 1931 | |
| 1932 | void dsp32c_device::store_r(UINT32 op) |
| 1933 | { |
| 1934 | if (!(op & 0x400)) |
| 1935 | cau_write_pi_2byte(op, REG16((op >> 16) & 0x1f)); |
| 1936 | else |
| 1937 | unimplemented(op); |
| 1938 | } |
| 1939 | |
| 1940 | |
| 1941 | void dsp32c_device::store_er(UINT32 op) |
| 1942 | { |
| 1943 | if (!(op & 0x400)) |
| 1944 | cau_write_pi_4byte(op, REG24((op >> 16) & 0x1f)); |
| 1945 | else |
| 1946 | unimplemented(op); |
| 1947 | } |
| 1948 | |
| 1949 | |
| 1950 | void dsp32c_device::load24(UINT32 op) |
| 1951 | { |
| 1952 | int dr = (op >> 16) & 0x1f; |
| 1953 | UINT32 res = (op & 0xffff) + ((op >> 5) & 0xff0000); |
| 1954 | if (IS_WRITEABLE(dr)) |
| 1955 | m_r[dr] = res; |
| 1956 | } |
| 1957 | |
| 1958 | |
| 1959 | |
| 1960 | //************************************************************************** |
| 1961 | // DAU FORM 1 IMPLEMENTATION |
| 1962 | //************************************************************************** |
| 1963 | |
| 1964 | void dsp32c_device::d1_aMpp(UINT32 op) |
| 1965 | { |
| 1966 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 1967 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 1968 | double res = yval + DEFERRED_MULTIPLIER((op >> 26) & 7) * xval; |
| 1969 | int zpi = (op >> 0) & 0x7f; |
| 1970 | if (zpi != 7) |
| 1971 | dau_write_pi_double(zpi, res); |
| 1972 | dau_set_val_flags((op >> 21) & 3, res); |
| 1973 | } |
| 1974 | |
| 1975 | |
| 1976 | void dsp32c_device::d1_aMpm(UINT32 op) |
| 1977 | { |
| 1978 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 1979 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 1980 | double res = yval - DEFERRED_MULTIPLIER((op >> 26) & 7) * xval; |
| 1981 | int zpi = (op >> 0) & 0x7f; |
| 1982 | if (zpi != 7) |
| 1983 | dau_write_pi_double(zpi, res); |
| 1984 | dau_set_val_flags((op >> 21) & 3, res); |
| 1985 | } |
| 1986 | |
| 1987 | |
| 1988 | void dsp32c_device::d1_aMmp(UINT32 op) |
| 1989 | { |
| 1990 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 1991 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 1992 | double res = -yval + DEFERRED_MULTIPLIER((op >> 26) & 7) * xval; |
| 1993 | int zpi = (op >> 0) & 0x7f; |
| 1994 | if (zpi != 7) |
| 1995 | dau_write_pi_double(zpi, res); |
| 1996 | dau_set_val_flags((op >> 21) & 3, res); |
| 1997 | } |
| 1998 | |
| 1999 | |
| 2000 | void dsp32c_device::d1_aMmm(UINT32 op) |
| 2001 | { |
| 2002 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2003 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2004 | double res = -yval - DEFERRED_MULTIPLIER((op >> 26) & 7) * xval; |
| 2005 | int zpi = (op >> 0) & 0x7f; |
| 2006 | if (zpi != 7) |
| 2007 | dau_write_pi_double(zpi, res); |
| 2008 | dau_set_val_flags((op >> 21) & 3, res); |
| 2009 | } |
| 2010 | |
| 2011 | |
| 2012 | void dsp32c_device::d1_0px(UINT32 op) |
| 2013 | { |
| 2014 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2015 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2016 | double res = yval; |
| 2017 | int zpi = (op >> 0) & 0x7f; |
| 2018 | if (zpi != 7) |
| 2019 | dau_write_pi_double(zpi, res); |
| 2020 | dau_set_val_flags((op >> 21) & 3, res); |
| 2021 | (void)xval; |
| 2022 | } |
| 2023 | |
| 2024 | |
| 2025 | void dsp32c_device::d1_0mx(UINT32 op) |
| 2026 | { |
| 2027 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2028 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2029 | double res = -yval; |
| 2030 | int zpi = (op >> 0) & 0x7f; |
| 2031 | if (zpi != 7) |
| 2032 | dau_write_pi_double(zpi, res); |
| 2033 | dau_set_val_flags((op >> 21) & 3, res); |
| 2034 | (void)xval; |
| 2035 | } |
| 2036 | |
| 2037 | |
| 2038 | void dsp32c_device::d1_1pp(UINT32 op) |
| 2039 | { |
| 2040 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2041 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2042 | double res = yval + xval; |
| 2043 | int zpi = (op >> 0) & 0x7f; |
| 2044 | if (zpi != 7) |
| 2045 | dau_write_pi_double(zpi, res); |
| 2046 | dau_set_val_flags((op >> 21) & 3, res); |
| 2047 | } |
| 2048 | |
| 2049 | |
| 2050 | void dsp32c_device::d1_1pm(UINT32 op) |
| 2051 | { |
| 2052 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2053 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2054 | double res = yval - xval; |
| 2055 | int zpi = (op >> 0) & 0x7f; |
| 2056 | if (zpi != 7) |
| 2057 | dau_write_pi_double(zpi, res); |
| 2058 | dau_set_val_flags((op >> 21) & 3, res); |
| 2059 | } |
| 2060 | |
| 2061 | |
| 2062 | void dsp32c_device::d1_1mp(UINT32 op) |
| 2063 | { |
| 2064 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2065 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2066 | double res = -yval + xval; |
| 2067 | int zpi = (op >> 0) & 0x7f; |
| 2068 | if (zpi != 7) |
| 2069 | dau_write_pi_double(zpi, res); |
| 2070 | dau_set_val_flags((op >> 21) & 3, res); |
| 2071 | } |
| 2072 | |
| 2073 | |
| 2074 | void dsp32c_device::d1_1mm(UINT32 op) |
| 2075 | { |
| 2076 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2077 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2078 | double res = -yval - xval; |
| 2079 | int zpi = (op >> 0) & 0x7f; |
| 2080 | if (zpi != 7) |
| 2081 | dau_write_pi_double(zpi, res); |
| 2082 | dau_set_val_flags((op >> 21) & 3, res); |
| 2083 | } |
| 2084 | |
| 2085 | |
| 2086 | void dsp32c_device::d1_aMppr(UINT32 op) |
| 2087 | { |
| 2088 | unimplemented(op); |
| 2089 | } |
| 2090 | |
| 2091 | |
| 2092 | void dsp32c_device::d1_aMpmr(UINT32 op) |
| 2093 | { |
| 2094 | unimplemented(op); |
| 2095 | } |
| 2096 | |
| 2097 | |
| 2098 | void dsp32c_device::d1_aMmpr(UINT32 op) |
| 2099 | { |
| 2100 | unimplemented(op); |
| 2101 | } |
| 2102 | |
| 2103 | |
| 2104 | void dsp32c_device::d1_aMmmr(UINT32 op) |
| 2105 | { |
| 2106 | unimplemented(op); |
| 2107 | } |
| 2108 | |
| 2109 | |
| 2110 | |
| 2111 | //************************************************************************** |
| 2112 | // DAU FORM 2 IMPLEMENTATION |
| 2113 | //************************************************************************** |
| 2114 | |
| 2115 | void dsp32c_device::d2_aMpp(UINT32 op) |
| 2116 | { |
| 2117 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2118 | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2119 | double res = m_a[(op >> 26) & 7] + yval * xval; |
| 2120 | int zpi = (op >> 0) & 0x7f; |
| 2121 | if (zpi != 7) |
| 2122 | dau_write_pi_double(zpi, yval); |
| 2123 | dau_set_val_flags((op >> 21) & 3, res); |
| 2124 | } |
| 2125 | |
| 2126 | |
| 2127 | void dsp32c_device::d2_aMpm(UINT32 op) |
| 2128 | { |
| 2129 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2130 | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2131 | double res = m_a[(op >> 26) & 7] - yval * xval; |
| 2132 | int zpi = (op >> 0) & 0x7f; |
| 2133 | if (zpi != 7) |
| 2134 | dau_write_pi_double(zpi, yval); |
| 2135 | dau_set_val_flags((op >> 21) & 3, res); |
| 2136 | } |
| 2137 | |
| 2138 | |
| 2139 | void dsp32c_device::d2_aMmp(UINT32 op) |
| 2140 | { |
| 2141 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2142 | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2143 | double res = -m_a[(op >> 26) & 7] + yval * xval; |
| 2144 | int zpi = (op >> 0) & 0x7f; |
| 2145 | if (zpi != 7) |
| 2146 | dau_write_pi_double(zpi, yval); |
| 2147 | dau_set_val_flags((op >> 21) & 3, res); |
| 2148 | } |
| 2149 | |
| 2150 | |
| 2151 | void dsp32c_device::d2_aMmm(UINT32 op) |
| 2152 | { |
| 2153 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2154 | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2155 | double res = -m_a[(op >> 26) & 7] - yval * xval; |
| 2156 | int zpi = (op >> 0) & 0x7f; |
| 2157 | if (zpi != 7) |
| 2158 | dau_write_pi_double(zpi, yval); |
| 2159 | dau_set_val_flags((op >> 21) & 3, res); |
| 2160 | } |
| 2161 | |
| 2162 | |
| 2163 | void dsp32c_device::d2_aMppr(UINT32 op) |
| 2164 | { |
| 2165 | unimplemented(op); |
| 2166 | } |
| 2167 | |
| 2168 | |
| 2169 | void dsp32c_device::d2_aMpmr(UINT32 op) |
| 2170 | { |
| 2171 | unimplemented(op); |
| 2172 | } |
| 2173 | |
| 2174 | |
| 2175 | void dsp32c_device::d2_aMmpr(UINT32 op) |
| 2176 | { |
| 2177 | unimplemented(op); |
| 2178 | } |
| 2179 | |
| 2180 | |
| 2181 | void dsp32c_device::d2_aMmmr(UINT32 op) |
| 2182 | { |
| 2183 | unimplemented(op); |
| 2184 | } |
| 2185 | |
| 2186 | |
| 2187 | |
| 2188 | //************************************************************************** |
| 2189 | // DAU FORM 3 IMPLEMENTATION |
| 2190 | //************************************************************************** |
| 2191 | |
| 2192 | void dsp32c_device::d3_aMpp(UINT32 op) |
| 2193 | { |
| 2194 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2195 | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2196 | double res = m_a[(op >> 26) & 7] + yval * xval; |
| 2197 | int zpi = (op >> 0) & 0x7f; |
| 2198 | if (zpi != 7) |
| 2199 | dau_write_pi_double(zpi, res); |
| 2200 | dau_set_val_flags((op >> 21) & 3, res); |
| 2201 | } |
| 2202 | |
| 2203 | |
| 2204 | void dsp32c_device::d3_aMpm(UINT32 op) |
| 2205 | { |
| 2206 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2207 | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2208 | double res = m_a[(op >> 26) & 7] - yval * xval; |
| 2209 | int zpi = (op >> 0) & 0x7f; |
| 2210 | if (zpi != 7) |
| 2211 | dau_write_pi_double(zpi, res); |
| 2212 | dau_set_val_flags((op >> 21) & 3, res); |
| 2213 | } |
| 2214 | |
| 2215 | |
| 2216 | void dsp32c_device::d3_aMmp(UINT32 op) |
| 2217 | { |
| 2218 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2219 | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2220 | double res = -m_a[(op >> 26) & 7] + yval * xval; |
| 2221 | int zpi = (op >> 0) & 0x7f; |
| 2222 | if (zpi != 7) |
| 2223 | dau_write_pi_double(zpi, res); |
| 2224 | dau_set_val_flags((op >> 21) & 3, res); |
| 2225 | } |
| 2226 | |
| 2227 | |
| 2228 | void dsp32c_device::d3_aMmm(UINT32 op) |
| 2229 | { |
| 2230 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2231 | double yval = dau_read_pi_double_2nd(op >> 7, 1, xval); |
| 2232 | double res = -m_a[(op >> 26) & 7] - yval * xval; |
| 2233 | int zpi = (op >> 0) & 0x7f; |
| 2234 | if (zpi != 7) |
| 2235 | dau_write_pi_double(zpi, res); |
| 2236 | dau_set_val_flags((op >> 21) & 3, res); |
| 2237 | } |
| 2238 | |
| 2239 | |
| 2240 | void dsp32c_device::d3_aMppr(UINT32 op) |
| 2241 | { |
| 2242 | unimplemented(op); |
| 2243 | } |
| 2244 | |
| 2245 | |
| 2246 | void dsp32c_device::d3_aMpmr(UINT32 op) |
| 2247 | { |
| 2248 | unimplemented(op); |
| 2249 | } |
| 2250 | |
| 2251 | |
| 2252 | void dsp32c_device::d3_aMmpr(UINT32 op) |
| 2253 | { |
| 2254 | unimplemented(op); |
| 2255 | } |
| 2256 | |
| 2257 | |
| 2258 | void dsp32c_device::d3_aMmmr(UINT32 op) |
| 2259 | { |
| 2260 | unimplemented(op); |
| 2261 | } |
| 2262 | |
| 2263 | |
| 2264 | |
| 2265 | //************************************************************************** |
| 2266 | // DAU FORM 4 IMPLEMENTATION |
| 2267 | //************************************************************************** |
| 2268 | |
| 2269 | void dsp32c_device::d4_pp(UINT32 op) |
| 2270 | { |
| 2271 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2272 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2273 | double res = yval + xval; |
| 2274 | int zpi = (op >> 0) & 0x7f; |
| 2275 | if (zpi != 7) |
| 2276 | dau_write_pi_double(zpi, yval); |
| 2277 | dau_set_val_flags((op >> 21) & 3, res); |
| 2278 | } |
| 2279 | |
| 2280 | |
| 2281 | void dsp32c_device::d4_pm(UINT32 op) |
| 2282 | { |
| 2283 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2284 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2285 | double res = yval - xval; |
| 2286 | int zpi = (op >> 0) & 0x7f; |
| 2287 | if (zpi != 7) |
| 2288 | dau_write_pi_double(zpi, yval); |
| 2289 | dau_set_val_flags((op >> 21) & 3, res); |
| 2290 | } |
| 2291 | |
| 2292 | |
| 2293 | void dsp32c_device::d4_mp(UINT32 op) |
| 2294 | { |
| 2295 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2296 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2297 | double res = -yval + xval; |
| 2298 | int zpi = (op >> 0) & 0x7f; |
| 2299 | if (zpi != 7) |
| 2300 | dau_write_pi_double(zpi, yval); |
| 2301 | dau_set_val_flags((op >> 21) & 3, res); |
| 2302 | } |
| 2303 | |
| 2304 | |
| 2305 | void dsp32c_device::d4_mm(UINT32 op) |
| 2306 | { |
| 2307 | double xval = dau_read_pi_double_1st(op >> 14, 1); |
| 2308 | double yval = dau_read_pi_double_2nd(op >> 7, 0, xval); |
| 2309 | double res = -yval - xval; |
| 2310 | int zpi = (op >> 0) & 0x7f; |
| 2311 | if (zpi != 7) |
| 2312 | dau_write_pi_double(zpi, yval); |
| 2313 | dau_set_val_flags((op >> 21) & 3, res); |
| 2314 | } |
| 2315 | |
| 2316 | |
| 2317 | void dsp32c_device::d4_ppr(UINT32 op) |
| 2318 | { |
| 2319 | unimplemented(op); |
| 2320 | } |
| 2321 | |
| 2322 | |
| 2323 | void dsp32c_device::d4_pmr(UINT32 op) |
| 2324 | { |
| 2325 | unimplemented(op); |
| 2326 | } |
| 2327 | |
| 2328 | |
| 2329 | void dsp32c_device::d4_mpr(UINT32 op) |
| 2330 | { |
| 2331 | unimplemented(op); |
| 2332 | } |
| 2333 | |
| 2334 | |
| 2335 | void dsp32c_device::d4_mmr(UINT32 op) |
| 2336 | { |
| 2337 | unimplemented(op); |
| 2338 | } |
| 2339 | |
| 2340 | |
| 2341 | |
| 2342 | //************************************************************************** |
| 2343 | // DAU FORM 5 IMPLEMENTATION |
| 2344 | //************************************************************************** |
| 2345 | |
| 2346 | void dsp32c_device::d5_ic(UINT32 op) |
| 2347 | { |
| 2348 | unimplemented(op); |
| 2349 | } |
| 2350 | |
| 2351 | |
| 2352 | void dsp32c_device::d5_oc(UINT32 op) |
| 2353 | { |
| 2354 | unimplemented(op); |
| 2355 | } |
| 2356 | |
| 2357 | |
| 2358 | void dsp32c_device::d5_float(UINT32 op) |
| 2359 | { |
| 2360 | double res = (double)(INT16)dau_read_pi_2bytes(op >> 7); |
| 2361 | int zpi = (op >> 0) & 0x7f; |
| 2362 | if (zpi != 7) |
| 2363 | dau_write_pi_double(zpi, res); |
| 2364 | dau_set_val_flags((op >> 21) & 3, res); |
| 2365 | } |
| 2366 | |
| 2367 | |
| 2368 | void dsp32c_device::d5_int(UINT32 op) |
| 2369 | { |
| 2370 | double val = dau_read_pi_double_1st(op >> 7, 0); |
| 2371 | int zpi = (op >> 0) & 0x7f; |
| 2372 | INT16 res; |
| 2373 | if (!(DAUC & 0x10)) val = floor(val + 0.5); |
| 2374 | else val = ceil(val - 0.5); |
| 2375 | res = (INT16)val; |
| 2376 | if (zpi != 7) |
| 2377 | dau_write_pi_2bytes(zpi, res); |
| 2378 | dau_set_val_noflags((op >> 21) & 3, dsp_to_double(res << 16)); |
| 2379 | } |
| 2380 | |
| 2381 | |
| 2382 | void dsp32c_device::d5_round(UINT32 op) |
| 2383 | { |
| 2384 | double res = (double)(float)dau_read_pi_double_1st(op >> 7, 0); |
| 2385 | int zpi = (op >> 0) & 0x7f; |
| 2386 | if (zpi != 7) |
| 2387 | dau_write_pi_double(zpi, res); |
| 2388 | dau_set_val_flags((op >> 21) & 3, res); |
| 2389 | } |
| 2390 | |
| 2391 | |
| 2392 | void dsp32c_device::d5_ifalt(UINT32 op) |
| 2393 | { |
| 2394 | int ar = (op >> 21) & 3; |
| 2395 | double res = m_a[ar]; |
| 2396 | int zpi = (op >> 0) & 0x7f; |
| 2397 | if (NFLAG) |
| 2398 | res = dau_read_pi_double_1st(op >> 7, 0); |
| 2399 | if (zpi != 7) |
| 2400 | dau_write_pi_double(zpi, res); |
| 2401 | dau_set_val_noflags(ar, res); |
| 2402 | } |
| 2403 | |
| 2404 | |
| 2405 | void dsp32c_device::d5_ifaeq(UINT32 op) |
| 2406 | { |
| 2407 | int ar = (op >> 21) & 3; |
| 2408 | double res = m_a[ar]; |
| 2409 | int zpi = (op >> 0) & 0x7f; |
| 2410 | if (ZFLAG) |
| 2411 | res = dau_read_pi_double_1st(op >> 7, 0); |
| 2412 | if (zpi != 7) |
| 2413 | dau_write_pi_double(zpi, res); |
| 2414 | dau_set_val_noflags(ar, res); |
| 2415 | } |
| 2416 | |
| 2417 | |
| 2418 | void dsp32c_device::d5_ifagt(UINT32 op) |
| 2419 | { |
| 2420 | int ar = (op >> 21) & 3; |
| 2421 | double res = m_a[ar]; |
| 2422 | int zpi = (op >> 0) & 0x7f; |
| 2423 | if (!NFLAG && !ZFLAG) |
| 2424 | res = dau_read_pi_double_1st(op >> 7, 0); |
| 2425 | if (zpi != 7) |
| 2426 | dau_write_pi_double(zpi, res); |
| 2427 | dau_set_val_noflags(ar, res); |
| 2428 | } |
| 2429 | |
| 2430 | |
| 2431 | void dsp32c_device::d5_float24(UINT32 op) |
| 2432 | { |
| 2433 | double res = (double)((INT32)(dau_read_pi_4bytes(op >> 7) << 8) >> 8); |
| 2434 | int zpi = (op >> 0) & 0x7f; |
| 2435 | if (zpi != 7) |
| 2436 | dau_write_pi_double(zpi, res); |
| 2437 | dau_set_val_flags((op >> 21) & 3, res); |
| 2438 | } |
| 2439 | |
| 2440 | |
| 2441 | void dsp32c_device::d5_int24(UINT32 op) |
| 2442 | { |
| 2443 | double val = dau_read_pi_double_1st(op >> 7, 0); |
| 2444 | int zpi = (op >> 0) & 0x7f; |
| 2445 | INT32 res; |
| 2446 | if (!(DAUC & 0x10)) val = floor(val + 0.5); |
| 2447 | else val = ceil(val - 0.5); |
| 2448 | res = (INT32)val; |
| 2449 | if (res > 0x7fffff) res = 0x7fffff; |
| 2450 | else if (res < -0x800000) res = -0x800000; |
| 2451 | if (zpi != 7) |
| 2452 | dau_write_pi_4bytes(zpi, (INT32)(res << 8) >> 8); |
| 2453 | dau_set_val_noflags((op >> 21) & 3, dsp_to_double(res << 8)); |
| 2454 | } |
| 2455 | |
| 2456 | |
| 2457 | void dsp32c_device::d5_ieee(UINT32 op) |
| 2458 | { |
| 2459 | unimplemented(op); |
| 2460 | } |
| 2461 | |
| 2462 | |
| 2463 | void dsp32c_device::d5_dsp(UINT32 op) |
| 2464 | { |
| 2465 | unimplemented(op); |
| 2466 | } |
| 2467 | |
| 2468 | |
| 2469 | void dsp32c_device::d5_seed(UINT32 op) |
| 2470 | { |
| 2471 | UINT32 val = dau_read_pi_4bytes(op >> 7); |
| 2472 | INT32 res = val ^ 0x7fffffff; |
| 2473 | int zpi = (op >> 0) & 0x7f; |
| 2474 | if (zpi != 7) |
| 2475 | dau_write_pi_4bytes(zpi, res); |
| 2476 | dau_set_val_flags((op >> 21) & 3, dsp_to_double((INT32)res)); |
| 2477 | } |
| 2478 | |
| 2479 | |
| 2480 | |
| 2481 | //************************************************************************** |
| 2482 | // FUNCTION TABLE |
| 2483 | //************************************************************************** |
| 2484 | |
| 2485 | void (dsp32c_device::*const dsp32c_device::s_dsp32ops[])(UINT32 op) = |
| 2486 | { |
| 2487 | &dsp32c_device::nop, &dsp32c_device::goto_t, &dsp32c_device::goto_pl, &dsp32c_device::goto_mi, &dsp32c_device::goto_ne, &dsp32c_device::goto_eq, &dsp32c_device::goto_vc, &dsp32c_device::goto_vs, // 00 |
| 2488 | &dsp32c_device::goto_cc, &dsp32c_device::goto_cs, &dsp32c_device::goto_ge, &dsp32c_device::goto_lt, &dsp32c_device::goto_gt, &dsp32c_device::goto_le, &dsp32c_device::goto_hi, &dsp32c_device::goto_ls, |
| 2489 | &dsp32c_device::goto_auc, &dsp32c_device::goto_aus, &dsp32c_device::goto_age, &dsp32c_device::goto_alt, &dsp32c_device::goto_ane, &dsp32c_device::goto_aeq, &dsp32c_device::goto_avc, &dsp32c_device::goto_avs, // 01 |
| 2490 | &dsp32c_device::goto_agt, &dsp32c_device::goto_ale, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2491 | &dsp32c_device::goto_ibe, &dsp32c_device::goto_ibf, &dsp32c_device::goto_obf, &dsp32c_device::goto_obe, &dsp32c_device::goto_pde, &dsp32c_device::goto_pdf, &dsp32c_device::goto_pie, &dsp32c_device::goto_pif, // 02 |
| 2492 | &dsp32c_device::goto_syc, &dsp32c_device::goto_sys, &dsp32c_device::goto_fbc, &dsp32c_device::goto_fbs, &dsp32c_device::goto_irq1lo,&dsp32c_device::goto_irq1hi,&dsp32c_device::goto_irq2lo,&dsp32c_device::goto_irq2hi, |
| 2493 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 03 |
| 2494 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2495 | |
| 2496 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 04 |
| 2497 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2498 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 05 |
| 2499 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2500 | &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, // 06 |
| 2501 | &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, |
| 2502 | &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, // 07 |
| 2503 | &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, &dsp32c_device::dec_goto, |
| 2504 | |
| 2505 | &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, // 08 |
| 2506 | &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, |
| 2507 | &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, // 09 |
| 2508 | &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, &dsp32c_device::call, |
| 2509 | &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, // 0a |
| 2510 | &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, |
| 2511 | &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, // 0b |
| 2512 | &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, &dsp32c_device::add_si, |
| 2513 | |
| 2514 | &dsp32c_device::add_ss, &dsp32c_device::mul2_s, &dsp32c_device::subr_ss, &dsp32c_device::addr_ss, &dsp32c_device::sub_ss, &dsp32c_device::neg_s, &dsp32c_device::andc_ss, &dsp32c_device::cmp_ss, // 0c |
| 2515 | &dsp32c_device::xor_ss, &dsp32c_device::rcr_s, &dsp32c_device::or_ss, &dsp32c_device::rcl_s, &dsp32c_device::shr_s, &dsp32c_device::div2_s, &dsp32c_device::and_ss, &dsp32c_device::test_ss, |
| 2516 | &dsp32c_device::add_di, &dsp32c_device::illegal, &dsp32c_device::subr_di, &dsp32c_device::addr_di, &dsp32c_device::sub_di, &dsp32c_device::illegal, &dsp32c_device::andc_di, &dsp32c_device::cmp_di, // 0d |
| 2517 | &dsp32c_device::xor_di, &dsp32c_device::illegal, &dsp32c_device::or_di, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::and_di, &dsp32c_device::test_di, |
| 2518 | &dsp32c_device::load_hi, &dsp32c_device::load_hi, &dsp32c_device::load_li, &dsp32c_device::load_li, &dsp32c_device::load_i, &dsp32c_device::load_i, &dsp32c_device::load_ei, &dsp32c_device::load_ei, // 0e |
| 2519 | &dsp32c_device::store_hi, &dsp32c_device::store_hi, &dsp32c_device::store_li, &dsp32c_device::store_li, &dsp32c_device::store_i, &dsp32c_device::store_i, &dsp32c_device::store_ei, &dsp32c_device::store_ei, |
| 2520 | &dsp32c_device::load_hr, &dsp32c_device::load_hr, &dsp32c_device::load_lr, &dsp32c_device::load_lr, &dsp32c_device::load_r, &dsp32c_device::load_r, &dsp32c_device::load_er, &dsp32c_device::load_er, // 0f |
| 2521 | &dsp32c_device::store_hr, &dsp32c_device::store_hr, &dsp32c_device::store_lr, &dsp32c_device::store_lr, &dsp32c_device::store_r, &dsp32c_device::store_r, &dsp32c_device::store_er, &dsp32c_device::store_er, |
| 2522 | |
| 2523 | &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, // 10 |
| 2524 | &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, |
| 2525 | &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 11 |
| 2526 | &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, |
| 2527 | &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, // 12 |
| 2528 | &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, |
| 2529 | &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 13 |
| 2530 | &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, |
| 2531 | |
| 2532 | &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, // 14 |
| 2533 | &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, |
| 2534 | &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 15 |
| 2535 | &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, |
| 2536 | &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpp, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, &dsp32c_device::d1_aMpm, // 16 |
| 2537 | &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmp, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, &dsp32c_device::d1_aMmm, |
| 2538 | &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 17 |
| 2539 | &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, |
| 2540 | |
| 2541 | &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, &dsp32c_device::d1_0px, // 18 |
| 2542 | &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, &dsp32c_device::d1_0mx, |
| 2543 | &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 19 |
| 2544 | &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, |
| 2545 | &dsp32c_device::d1_1pp, &dsp32c_device::d1_1pp, &dsp32c_device::d1_1pp, &dsp32c_device::d1_1pp, &dsp32c_device::d1_1pm, &dsp32c_device::d1_1pm, &dsp32c_device::d1_1pm, &dsp32c_device::d1_1pm, // 1a |
| 2546 | &dsp32c_device::d1_1mp, &dsp32c_device::d1_1mp, &dsp32c_device::d1_1mp, &dsp32c_device::d1_1mp, &dsp32c_device::d1_1mm, &dsp32c_device::d1_1mm, &dsp32c_device::d1_1mm, &dsp32c_device::d1_1mm, |
| 2547 | &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMppr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, &dsp32c_device::d1_aMpmr, // 1b |
| 2548 | &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmpr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, &dsp32c_device::d1_aMmmr, |
| 2549 | |
| 2550 | &dsp32c_device::d4_pp, &dsp32c_device::d4_pp, &dsp32c_device::d4_pp, &dsp32c_device::d4_pp, &dsp32c_device::d4_pm, &dsp32c_device::d4_pm, &dsp32c_device::d4_pm, &dsp32c_device::d4_pm, // 1c |
| 2551 | &dsp32c_device::d4_mp, &dsp32c_device::d4_mp, &dsp32c_device::d4_mp, &dsp32c_device::d4_mp, &dsp32c_device::d4_mm, &dsp32c_device::d4_mm, &dsp32c_device::d4_mm, &dsp32c_device::d4_mm, |
| 2552 | &dsp32c_device::d4_ppr, &dsp32c_device::d4_ppr, &dsp32c_device::d4_ppr, &dsp32c_device::d4_ppr, &dsp32c_device::d4_pmr, &dsp32c_device::d4_pmr, &dsp32c_device::d4_pmr, &dsp32c_device::d4_pmr, // 1d |
| 2553 | &dsp32c_device::d4_mpr, &dsp32c_device::d4_mpr, &dsp32c_device::d4_mpr, &dsp32c_device::d4_mpr, &dsp32c_device::d4_mmr, &dsp32c_device::d4_mmr, &dsp32c_device::d4_mmr, &dsp32c_device::d4_mmr, |
| 2554 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 1e |
| 2555 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2556 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 1f |
| 2557 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2558 | |
| 2559 | &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 20 |
| 2560 | &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, |
| 2561 | &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 21 |
| 2562 | &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, |
| 2563 | &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 22 |
| 2564 | &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, |
| 2565 | &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 23 |
| 2566 | &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, |
| 2567 | |
| 2568 | &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 24 |
| 2569 | &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, |
| 2570 | &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 25 |
| 2571 | &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, |
| 2572 | &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 26 |
| 2573 | &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, |
| 2574 | &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 27 |
| 2575 | &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, |
| 2576 | |
| 2577 | &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 28 |
| 2578 | &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, |
| 2579 | &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 29 |
| 2580 | &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, |
| 2581 | &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpp, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, &dsp32c_device::d2_aMpm, // 2a |
| 2582 | &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmp, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, &dsp32c_device::d2_aMmm, |
| 2583 | &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMppr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, &dsp32c_device::d2_aMpmr, // 2b |
| 2584 | &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmpr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, &dsp32c_device::d2_aMmmr, |
| 2585 | |
| 2586 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 2c |
| 2587 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2588 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 2d |
| 2589 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2590 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 2e |
| 2591 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2592 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 2f |
| 2593 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2594 | |
| 2595 | &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 30 |
| 2596 | &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, |
| 2597 | &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 31 |
| 2598 | &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, |
| 2599 | &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 32 |
| 2600 | &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, |
| 2601 | &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 33 |
| 2602 | &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, |
| 2603 | |
| 2604 | &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 34 |
| 2605 | &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, |
| 2606 | &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 35 |
| 2607 | &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, |
| 2608 | &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 36 |
| 2609 | &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, |
| 2610 | &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 37 |
| 2611 | &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, |
| 2612 | |
| 2613 | &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 38 |
| 2614 | &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, |
| 2615 | &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 39 |
| 2616 | &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, |
| 2617 | &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpp, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, &dsp32c_device::d3_aMpm, // 3a |
| 2618 | &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmp, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, &dsp32c_device::d3_aMmm, |
| 2619 | &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMppr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, &dsp32c_device::d3_aMpmr, // 3b |
| 2620 | &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmpr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, &dsp32c_device::d3_aMmmr, |
| 2621 | |
| 2622 | &dsp32c_device::d5_ic, &dsp32c_device::d5_ic, &dsp32c_device::d5_ic, &dsp32c_device::d5_ic, &dsp32c_device::d5_oc, &dsp32c_device::d5_oc, &dsp32c_device::d5_oc, &dsp32c_device::d5_oc, // 3c |
| 2623 | &dsp32c_device::d5_float, &dsp32c_device::d5_float, &dsp32c_device::d5_float, &dsp32c_device::d5_float, &dsp32c_device::d5_int, &dsp32c_device::d5_int, &dsp32c_device::d5_int, &dsp32c_device::d5_int, |
| 2624 | &dsp32c_device::d5_round, &dsp32c_device::d5_round, &dsp32c_device::d5_round, &dsp32c_device::d5_round, &dsp32c_device::d5_ifalt, &dsp32c_device::d5_ifalt, &dsp32c_device::d5_ifalt, &dsp32c_device::d5_ifalt, // 3d |
| 2625 | &dsp32c_device::d5_ifaeq, &dsp32c_device::d5_ifaeq, &dsp32c_device::d5_ifaeq, &dsp32c_device::d5_ifaeq, &dsp32c_device::d5_ifagt, &dsp32c_device::d5_ifagt, &dsp32c_device::d5_ifagt, &dsp32c_device::d5_ifagt, |
| 2626 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 3e |
| 2627 | &dsp32c_device::d5_float24, &dsp32c_device::d5_float24, &dsp32c_device::d5_float24, &dsp32c_device::d5_float24, &dsp32c_device::d5_int24, &dsp32c_device::d5_int24, &dsp32c_device::d5_int24, &dsp32c_device::d5_int24, |
| 2628 | &dsp32c_device::d5_ieee, &dsp32c_device::d5_ieee, &dsp32c_device::d5_ieee, &dsp32c_device::d5_ieee, &dsp32c_device::d5_dsp, &dsp32c_device::d5_dsp, &dsp32c_device::d5_dsp, &dsp32c_device::d5_dsp, // 3f |
| 2629 | &dsp32c_device::d5_seed, &dsp32c_device::d5_seed, &dsp32c_device::d5_seed, &dsp32c_device::d5_seed, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2630 | |
| 2631 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 40 |
| 2632 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2633 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 41 |
| 2634 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2635 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 42 |
| 2636 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2637 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 43 |
| 2638 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2639 | |
| 2640 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 44 |
| 2641 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2642 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 45 |
| 2643 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2644 | &dsp32c_device::do_i, &dsp32c_device::do_r, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 46 |
| 2645 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2646 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 47 |
| 2647 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2648 | |
| 2649 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 48 |
| 2650 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2651 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 49 |
| 2652 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2653 | &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, // 4a |
| 2654 | &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, |
| 2655 | &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, // 4b |
| 2656 | &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, &dsp32c_device::adde_si, |
| 2657 | |
| 2658 | &dsp32c_device::adde_ss, &dsp32c_device::mul2e_s, &dsp32c_device::subre_ss, &dsp32c_device::addre_ss, &dsp32c_device::sube_ss, &dsp32c_device::nege_s, &dsp32c_device::andce_ss, &dsp32c_device::cmpe_ss, // 4c |
| 2659 | &dsp32c_device::xore_ss, &dsp32c_device::rcre_s, &dsp32c_device::ore_ss, &dsp32c_device::rcle_s, &dsp32c_device::shre_s, &dsp32c_device::div2e_s, &dsp32c_device::ande_ss, &dsp32c_device::teste_ss, |
| 2660 | &dsp32c_device::adde_di, &dsp32c_device::illegal, &dsp32c_device::subre_di, &dsp32c_device::addre_di, &dsp32c_device::sube_di, &dsp32c_device::illegal, &dsp32c_device::andce_di, &dsp32c_device::cmpe_di, // 4d |
| 2661 | &dsp32c_device::xore_di, &dsp32c_device::illegal, &dsp32c_device::ore_di, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::ande_di, &dsp32c_device::teste_di, |
| 2662 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 4e |
| 2663 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2664 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, // 4f |
| 2665 | &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, &dsp32c_device::illegal, |
| 2666 | |
| 2667 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 50 |
| 2668 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2669 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 51 |
| 2670 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2671 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 52 |
| 2672 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2673 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 53 |
| 2674 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2675 | |
| 2676 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 54 |
| 2677 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2678 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 55 |
| 2679 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2680 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 56 |
| 2681 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2682 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 57 |
| 2683 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2684 | |
| 2685 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 58 |
| 2686 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2687 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 59 |
| 2688 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2689 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5a |
| 2690 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2691 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5b |
| 2692 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2693 | |
| 2694 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5c |
| 2695 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2696 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5d |
| 2697 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2698 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5e |
| 2699 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2700 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, // 5f |
| 2701 | &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, &dsp32c_device::goto24, |
| 2702 | |
| 2703 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 60 |
| 2704 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2705 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 61 |
| 2706 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2707 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 62 |
| 2708 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2709 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 63 |
| 2710 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2711 | |
| 2712 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 64 |
| 2713 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2714 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 65 |
| 2715 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2716 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 66 |
| 2717 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2718 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 67 |
| 2719 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2720 | |
| 2721 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 68 |
| 2722 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2723 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 69 |
| 2724 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2725 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6a |
| 2726 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2727 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6b |
| 2728 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2729 | |
| 2730 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6c |
| 2731 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2732 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6d |
| 2733 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2734 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6e |
| 2735 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2736 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, // 6f |
| 2737 | &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, &dsp32c_device::load24, |
| 2738 | |
| 2739 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 70 |
| 2740 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2741 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 71 |
| 2742 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2743 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 72 |
| 2744 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2745 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 73 |
| 2746 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2747 | |
| 2748 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 74 |
| 2749 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2750 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 75 |
| 2751 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2752 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 76 |
| 2753 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2754 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 77 |
| 2755 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2756 | |
| 2757 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 78 |
| 2758 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2759 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 79 |
| 2760 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2761 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7a |
| 2762 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2763 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7b |
| 2764 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2765 | |
| 2766 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7c |
| 2767 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2768 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7d |
| 2769 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2770 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7e |
| 2771 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, |
| 2772 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, // 7f |
| 2773 | &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24, &dsp32c_device::call24 |
| 2774 | }; |
| 2775 | |
| 2776 | |
| 2777 | /* |
| 2778 | |
| 2779 | Most common OPs in Race Drivin': |
| 2780 | |
| 2781 | 301681217 - op 0 - nop |
| 2782 | 164890391 - op 4A1 - adde_si |
| 2783 | 99210113 - op 661 - load24 |
| 2784 | 86010010 - op F7 - load_er |
| 2785 | 61148739 - op 4D4 - sube_di |
| 2786 | 52693763 - op 180 - d1_0px |
| 2787 | 41525754 - op FF - store_er |
| 2788 | 35033321 - op 380 - d3_aMpp |
| 2789 | 31621151 - op 4C0 - adde_ss |
| 2790 | 28076244 - op 660 - load24 |
| 2791 | 19190505 - op 4C1 - mul2e_s |
| 2792 | 13270852 - op F5 - load_r |
| 2793 | 12535169 - op 1A4 - d1_1pm |
| 2794 | 12265141 - op 4C4 - sube_ss |
| 2795 | 10748211 - op 4CD - div2e_s |
| 2796 | 10493660 - op FD - store_r |
| 2797 | 9721263 - op 189 |
| 2798 | 9415685 - op 3C8 |
| 2799 | 9294148 - op 3D5 |
| 2800 | 8887846 - op 1A1 |
| 2801 | 8788648 - op 381 |
| 2802 | 8185239 - op 300 |
| 2803 | 7241256 - op 383 |
| 2804 | 6877349 - op 4A3 |
| 2805 | 6832295 - op 181 |
| 2806 | 6601270 - op 3E8 |
| 2807 | 6562483 - op 4A4 |
| 2808 | 6553514 - op 3C9 |
| 2809 | 6270430 - op 280 |
| 2810 | 6041485 - op 1A0 |
| 2811 | 5299529 - op 304 |
| 2812 | 5110926 - op 382 |
| 2813 | 4922253 - op 363 |
| 2814 | 4603670 - op 4D7 |
| 2815 | 4164327 - op 4AE |
| 2816 | 3980085 - op 3EC |
| 2817 | 3599198 - op 3CC |
| 2818 | 3543878 - op 3D0 |
| 2819 | 3489158 - op 4 |
| 2820 | 3463235 - op 321 |
| 2821 | 3335995 - op 3F9 |
| 2822 | 3001546 - op 4CE |
| 2823 | 2882940 - op 129 |
| 2824 | 2882940 - op 1A5 |
| 2825 | 2882940 - op 342 |
| 2826 | 2841981 - op 360 |
| 2827 | 2663417 - op FB |
| 2828 | 2059640 - op 3ED |
| 2829 | 1867166 - op 1A8 |
| 2830 | 1830789 - op 305 |
| 2831 | 1753312 - op 301 |
| 2832 | 1726866 - op 5 |
| 2833 | 1594991 - op 12 |
| 2834 | 1571286 - op 19 |
| 2835 | 1507644 - op A2 |
| 2836 | 1418846 - op 3CD |
| 2837 | 1273134 - op F3 |
| 2838 | 1177914 - op 4C7 |
| 2839 | 1175720 - op 188 |
| 2840 | 1091848 - op 3E9 |
| 2841 | 1088206 - op 6FF |
| 2842 | 1088204 - op 4CA |
| 2843 | 1012639 - op 101 |
| 2844 | 939617 - op 4C5 |
| 2845 | |
| 2846 | */ |
trunk/src/emu/cpu/i860/i860dec.c
| r28738 | r28739 | |
| 1 | | /*************************************************************************** |
| 2 | | |
| 3 | | i860dec.c |
| 4 | | |
| 5 | | Execution engine for the Intel i860 emulator. |
| 6 | | |
| 7 | | Copyright (C) 1995-present Jason Eckhardt (jle@rice.edu) |
| 8 | | Released for general non-commercial use under the MAME license |
| 9 | | with the additional requirement that you are free to use and |
| 10 | | redistribute this code in modified or unmodified form, provided |
| 11 | | you list me in the credits. |
| 12 | | Visit http://mamedev.org for licensing and usage restrictions. |
| 13 | | |
| 14 | | ***************************************************************************/ |
| 15 | | |
| 16 | | /* |
| 17 | | * References: |
| 18 | | * `i860 Microprocessor Programmer's Reference Manual', Intel, 1990. |
| 19 | | * |
| 20 | | * This code was originally written by Jason Eckhardt as part of an |
| 21 | | * emulator for some i860-based Unix workstations (early 1990's) such |
| 22 | | * as the Stardent Vistra 800 series and the OkiStation/i860 7300 series. |
| 23 | | * The code you are reading now is the i860 CPU portion only, which has |
| 24 | | * been adapted to (and simplified for) MAME. |
| 25 | | * MAME-specific notes: |
| 26 | | * - i860XR emulation only (i860XP unnecessary for MAME). |
| 27 | | * - No emulation of data and instruction caches (unnecessary for MAME version). |
| 28 | | * - No emulation of DIM mode or CS8 mode (unnecessary for MAME version). |
| 29 | | * - No BL/IL/locked sequences (unnecessary for MAME). |
| 30 | | * - Emulate only the i860's LSB-first mode (BE = 0). |
| 31 | | * Generic notes: |
| 32 | | * - There is some amount of code duplication (e.g., see the |
| 33 | | * various insn_* routines for the branches and FP routines) that |
| 34 | | * could be eliminated. |
| 35 | | * - The host's floating point types are used to emulate the i860's |
| 36 | | * floating point. Should probably be made machine independent by |
| 37 | | * using an IEEE FP emulation library. On the other hand, most machines |
| 38 | | * today also use IEEE FP. |
| 39 | | * |
| 40 | | */ |
| 41 | | #include "i860.h" |
| 42 | | #include <math.h> |
| 43 | | |
| 44 | | |
| 45 | | #undef HOST_MSB |
| 46 | | |
| 47 | | #undef TRACE_RDWR_MEM |
| 48 | | #undef TRACE_ADDR_TRANSLATION |
| 49 | | #undef TRACE_PAGE_FAULT |
| 50 | | #define TRACE_UNDEFINED_I860 |
| 51 | | #undef TRACE_EXT_INT |
| 52 | | #define TRACE_UNALIGNED_MEM |
| 53 | | |
| 54 | | |
| 55 | | /* Defines for pending_trap. */ |
| 56 | | enum { |
| 57 | | TRAP_NORMAL = 0x01, |
| 58 | | TRAP_IN_DELAY_SLOT = 0x02, |
| 59 | | TRAP_WAS_EXTERNAL = 0x04 |
| 60 | | }; |
| 61 | | |
| 62 | | |
| 63 | | /* TODO: THESE WILL BE REPLACED BY MAME FUNCTIONS |
| 64 | | #define BYTE_REV32(t) \ |
| 65 | | do { \ |
| 66 | | (t) = ((UINT32)(t) >> 16) | ((UINT32)(t) << 16); \ |
| 67 | | (t) = (((UINT32)(t) >> 8) & 0x00ff00ff) | (((UINT32)(t) << 8) & 0xff00ff00); \ |
| 68 | | } while (0); |
| 69 | | |
| 70 | | #define BYTE_REV16(t) \ |
| 71 | | do { \ |
| 72 | | (t) = (((UINT16)(t) >> 8) & 0x00ff) | (((UINT16)(t) << 8) & 0xff00); \ |
| 73 | | } while (0); |
| 74 | | #endif |
| 75 | | */ |
| 76 | | |
| 77 | | |
| 78 | | /* Get/set general register value -- watch for r0 on writes. */ |
| 79 | | #define get_iregval(gr) (m_iregs[(gr)]) |
| 80 | | #define set_iregval(gr, val) (m_iregs[(gr)] = ((gr) == 0 ? 0 : (val))) |
| 81 | | |
| 82 | | float i860_cpu_device::get_fregval_s (int fr) |
| 83 | | { |
| 84 | | float f; |
| 85 | | UINT32 x; |
| 86 | | UINT8 *tp; |
| 87 | | fr = 31 - fr; |
| 88 | | tp = (UINT8 *)(&m_frg[fr * 4]); |
| 89 | | x = ((UINT32)tp[0] << 24) | ((UINT32)tp[1] << 16) | |
| 90 | | ((UINT32)tp[2] << 8) | ((UINT32)tp[3]); |
| 91 | | f = *(float *)(&x); |
| 92 | | return f; |
| 93 | | } |
| 94 | | |
| 95 | | double i860_cpu_device::get_fregval_d (int fr) |
| 96 | | { |
| 97 | | double d; |
| 98 | | UINT64 x; |
| 99 | | UINT8 *tp; |
| 100 | | fr = 31 - (fr + 1); |
| 101 | | tp = (UINT8 *)(&m_frg[fr * 4]); |
| 102 | | x = ((UINT64)tp[0] << 56) | ((UINT64)tp[1] << 48) | |
| 103 | | ((UINT64)tp[2] << 40) | ((UINT64)tp[3] << 32) | |
| 104 | | ((UINT64)tp[4] << 24) | ((UINT64)tp[5] << 16) | |
| 105 | | ((UINT64)tp[6] << 8) | ((UINT64)tp[7]); |
| 106 | | d = *(double *)(&x); |
| 107 | | return d; |
| 108 | | } |
| 109 | | |
| 110 | | void i860_cpu_device::set_fregval_s (int fr, float s) |
| 111 | | { |
| 112 | | UINT8 *f = (UINT8 *)&s; |
| 113 | | UINT8 *tp; |
| 114 | | int newfr = 31 - fr; |
| 115 | | float jj = s; |
| 116 | | tp = (UINT8 *)(&m_frg[newfr * 4]); |
| 117 | | |
| 118 | | f = (UINT8 *)(&jj); |
| 119 | | if (fr == 0 || fr == 1) |
| 120 | | { |
| 121 | | tp[0] = 0; tp[1] = 0; tp[2] = 0; tp[3] = 0; |
| 122 | | } |
| 123 | | else |
| 124 | | { |
| 125 | | #ifndef HOST_MSB |
| 126 | | tp[0] = f[3]; tp[1] = f[2]; tp[2] = f[1]; tp[3] = f[0]; |
| 127 | | #else |
| 128 | | tp[0] = f[0]; tp[1] = f[1]; tp[2] = f[2]; tp[3] = f[3]; |
| 129 | | #endif |
| 130 | | } |
| 131 | | } |
| 132 | | |
| 133 | | void i860_cpu_device::set_fregval_d (int fr, double d) |
| 134 | | { |
| 135 | | UINT8 *f = (UINT8 *)&d; |
| 136 | | UINT8 *tp; |
| 137 | | int newfr = 31 - (fr + 1); |
| 138 | | double jj = d; |
| 139 | | tp = (UINT8 *)(&m_frg[newfr * 4]); |
| 140 | | |
| 141 | | f = (UINT8 *)(&jj); |
| 142 | | |
| 143 | | if (fr == 0) |
| 144 | | { |
| 145 | | tp[0] = 0; tp[1] = 0; tp[2] = 0; tp[3] = 0; |
| 146 | | tp[4] = 0; tp[5] = 0; tp[6] = 0; tp[7] = 0; |
| 147 | | } |
| 148 | | else |
| 149 | | { |
| 150 | | #ifndef HOST_MSB |
| 151 | | tp[0] = f[7]; tp[1] = f[6]; tp[2] = f[5]; tp[3] = f[4]; |
| 152 | | tp[4] = f[3]; tp[5] = f[2]; tp[6] = f[1]; tp[7] = f[0]; |
| 153 | | #else |
| 154 | | tp[0] = f[0]; tp[1] = f[1]; tp[2] = f[2]; tp[3] = f[3]; |
| 155 | | tp[4] = f[4]; tp[5] = f[5]; tp[6] = f[6]; tp[7] = f[7]; |
| 156 | | #endif |
| 157 | | } |
| 158 | | } |
| 159 | | |
| 160 | | |
| 161 | | /* Macros for accessing register fields in instruction word. */ |
| 162 | | #define get_isrc1(bits) (((bits) >> 11) & 0x1f) |
| 163 | | #define get_isrc2(bits) (((bits) >> 21) & 0x1f) |
| 164 | | #define get_idest(bits) (((bits) >> 16) & 0x1f) |
| 165 | | #define get_fsrc1(bits) (((bits) >> 11) & 0x1f) |
| 166 | | #define get_fsrc2(bits) (((bits) >> 21) & 0x1f) |
| 167 | | #define get_fdest(bits) (((bits) >> 16) & 0x1f) |
| 168 | | #define get_creg(bits) (((bits) >> 21) & 0x7) |
| 169 | | |
| 170 | | /* Macros for accessing immediate fields. */ |
| 171 | | /* 16-bit immediate. */ |
| 172 | | #define get_imm16(insn) ((insn) & 0xffff) |
| 173 | | |
| 174 | | /* A mask for all the trap bits of the PSR (FT, DAT, IAT, IN, IT, or |
| 175 | | bits [12..8]). */ |
| 176 | | #define PSR_ALL_TRAP_BITS_MASK 0x00001f00 |
| 177 | | |
| 178 | | /* A mask for PSR bits which can only be changed from supervisor level. */ |
| 179 | | #define PSR_SUPERVISOR_ONLY_MASK 0x0000fff3 |
| 180 | | |
| 181 | | |
| 182 | | /* PSR: BR flag (PSR[0]): set/get. */ |
| 183 | | #define GET_PSR_BR() ((m_cregs[CR_PSR] >> 0) & 1) |
| 184 | | #define SET_PSR_BR(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 0)) | (((val) & 1) << 0)) |
| 185 | | |
| 186 | | /* PSR: BW flag (PSR[1]): set/get. */ |
| 187 | | #define GET_PSR_BW() ((m_cregs[CR_PSR] >> 1) & 1) |
| 188 | | #define SET_PSR_BW(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 1)) | (((val) & 1) << 1)) |
| 189 | | |
| 190 | | /* PSR: Shift count (PSR[21..17]): set/get. */ |
| 191 | | #define GET_PSR_SC() ((m_cregs[CR_PSR] >> 17) & 0x1f) |
| 192 | | #define SET_PSR_SC(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~0x003e0000) | (((val) & 0x1f) << 17)) |
| 193 | | |
| 194 | | /* PSR: CC flag (PSR[2]): set/get. */ |
| 195 | | #define GET_PSR_CC() ((m_cregs[CR_PSR] >> 2) & 1) |
| 196 | | #define SET_PSR_CC(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 2)) | (((val) & 1) << 2)) |
| 197 | | |
| 198 | | /* PSR: IT flag (PSR[8]): set/get. */ |
| 199 | | #define GET_PSR_IT() ((m_cregs[CR_PSR] >> 8) & 1) |
| 200 | | #define SET_PSR_IT(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 8)) | (((val) & 1) << 8)) |
| 201 | | |
| 202 | | /* PSR: IN flag (PSR[9]): set/get. */ |
| 203 | | #define GET_PSR_IN() ((m_cregs[CR_PSR] >> 9) & 1) |
| 204 | | #define SET_PSR_IN(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 9)) | (((val) & 1) << 9)) |
| 205 | | |
| 206 | | /* PSR: IAT flag (PSR[10]): set/get. */ |
| 207 | | #define GET_PSR_IAT() ((m_cregs[CR_PSR] >> 10) & 1) |
| 208 | | #define SET_PSR_IAT(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 10)) | (((val) & 1) << 10)) |
| 209 | | |
| 210 | | /* PSR: DAT flag (PSR[11]): set/get. */ |
| 211 | | #define GET_PSR_DAT() ((m_cregs[CR_PSR] >> 11) & 1) |
| 212 | | #define SET_PSR_DAT(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 11)) | (((val) & 1) << 11)) |
| 213 | | |
| 214 | | /* PSR: FT flag (PSR[12]): set/get. */ |
| 215 | | #define GET_PSR_FT() ((m_cregs[CR_PSR] >> 12) & 1) |
| 216 | | #define SET_PSR_FT(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 12)) | (((val) & 1) << 12)) |
| 217 | | |
| 218 | | /* PSR: DS flag (PSR[13]): set/get. */ |
| 219 | | #define GET_PSR_DS() ((m_cregs[CR_PSR] >> 13) & 1) |
| 220 | | #define SET_PSR_DS(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 13)) | (((val) & 1) << 13)) |
| 221 | | |
| 222 | | /* PSR: DIM flag (PSR[14]): set/get. */ |
| 223 | | #define GET_PSR_DIM() ((m_cregs[CR_PSR] >> 14) & 1) |
| 224 | | #define SET_PSR_DIM(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 14)) | (((val) & 1) << 14)) |
| 225 | | |
| 226 | | /* PSR: LCC (PSR[3]): set/get. */ |
| 227 | | #define GET_PSR_LCC() ((m_cregs[CR_PSR] >> 3) & 1) |
| 228 | | #define SET_PSR_LCC(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 3)) | (((val) & 1) << 3)) |
| 229 | | |
| 230 | | /* PSR: IM (PSR[4]): set/get. */ |
| 231 | | #define GET_PSR_IM() ((m_cregs[CR_PSR] >> 4) & 1) |
| 232 | | #define SET_PSR_IM(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 4)) | (((val) & 1) << 4)) |
| 233 | | |
| 234 | | /* PSR: PIM (PSR[5]): set/get. */ |
| 235 | | #define GET_PSR_PIM() ((m_cregs[CR_PSR] >> 5) & 1) |
| 236 | | #define SET_PSR_PIM(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 5)) | (((val) & 1) << 5)) |
| 237 | | |
| 238 | | /* PSR: U (PSR[6]): set/get. */ |
| 239 | | #define GET_PSR_U() ((m_cregs[CR_PSR] >> 6) & 1) |
| 240 | | #define SET_PSR_U(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 6)) | (((val) & 1) << 6)) |
| 241 | | |
| 242 | | /* PSR: PU (PSR[7]): set/get. */ |
| 243 | | #define GET_PSR_PU() ((m_cregs[CR_PSR] >> 7) & 1) |
| 244 | | #define SET_PSR_PU(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 7)) | (((val) & 1) << 7)) |
| 245 | | |
| 246 | | /* PSR: Pixel size (PSR[23..22]): set/get. */ |
| 247 | | #define GET_PSR_PS() ((m_cregs[CR_PSR] >> 22) & 0x3) |
| 248 | | #define SET_PSR_PS(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~0x00c00000) | (((val) & 0x3) << 22)) |
| 249 | | |
| 250 | | /* PSR: Pixel mask (PSR[31..24]): set/get. */ |
| 251 | | #define GET_PSR_PM() ((m_cregs[CR_PSR] >> 24) & 0xff) |
| 252 | | #define SET_PSR_PM(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~0xff000000) | (((val) & 0xff) << 24)) |
| 253 | | |
| 254 | | /* EPSR: WP bit (EPSR[14]): set/get. */ |
| 255 | | #define GET_EPSR_WP() ((m_cregs[CR_EPSR] >> 14) & 1) |
| 256 | | #define SET_EPSR_WP(val) (m_cregs[CR_EPSR] = (m_cregs[CR_EPSR] & ~(1 << 14)) | (((val) & 1) << 14)) |
| 257 | | |
| 258 | | /* EPSR: INT bit (EPSR[17]): set/get. */ |
| 259 | | #define GET_EPSR_INT() ((m_cregs[CR_EPSR] >> 17) & 1) |
| 260 | | #define SET_EPSR_INT(val) (m_cregs[CR_EPSR] = (m_cregs[CR_EPSR] & ~(1 << 17)) | (((val) & 1) << 17)) |
| 261 | | |
| 262 | | |
| 263 | | /* EPSR: OF flag (EPSR[24]): set/get. */ |
| 264 | | #define GET_EPSR_OF() ((m_cregs[CR_EPSR] >> 24) & 1) |
| 265 | | #define SET_EPSR_OF(val) (m_cregs[CR_EPSR] = (m_cregs[CR_EPSR] & ~(1 << 24)) | (((val) & 1) << 24)) |
| 266 | | |
| 267 | | /* EPSR: BE flag (EPSR[23]): set/get. */ |
| 268 | | #define GET_EPSR_BE() ((m_cregs[CR_EPSR] >> 23) & 1) |
| 269 | | #define SET_EPSR_BE(val) (m_cregs[CR_EPSR] = (m_cregs[CR_EPSR] & ~(1 << 23)) | (((val) & 1) << 23)) |
| 270 | | |
| 271 | | /* DIRBASE: ATE bit (DIRBASE[0]): get. */ |
| 272 | | #define GET_DIRBASE_ATE() (m_cregs[CR_DIRBASE] & 1) |
| 273 | | |
| 274 | | /* DIRBASE: CS8 bit (DIRBASE[7]): get. */ |
| 275 | | #define GET_DIRBASE_CS8() ((m_cregs[CR_DIRBASE] >> 7) & 1) |
| 276 | | |
| 277 | | /* FSR: FTE bit (FSR[5]): set/get. */ |
| 278 | | #define GET_FSR_FTE() ((m_cregs[CR_FSR] >> 5) & 1) |
| 279 | | #define SET_FSR_FTE(val) (m_cregs[CR_FSR] = (m_cregs[CR_FSR] & ~(1 << 5)) | (((val) & 1) << 5)) |
| 280 | | |
| 281 | | /* FSR: SE bit (FSR[8]): set/get. */ |
| 282 | | #define GET_FSR_SE() ((m_cregs[CR_FSR] >> 8) & 1) |
| 283 | | #define SET_FSR_SE(val) (m_cregs[CR_FSR] = (m_cregs[CR_FSR] & ~(1 << 8)) | (((val) & 1) << 8)) |
| 284 | | |
| 285 | | |
| 286 | | int i860_cpu_device::has_delay_slot(UINT32 insn) |
| 287 | | { |
| 288 | | int opc = (insn >> 26) & 0x3f; |
| 289 | | if (opc == 0x10 || opc == 0x1a || opc == 0x1b || opc == 0x1d || |
| 290 | | opc == 0x1f || opc == 0x2d || (opc == 0x13 && (insn & 3) == 2)) |
| 291 | | return 1; |
| 292 | | return 0; |
| 293 | | } |
| 294 | | |
| 295 | | /* This is the external interface for asserting/deasserting pins on |
| 296 | | the i860. */ |
| 297 | | void i860_cpu_device::i860_set_pin (int pin, int val) |
| 298 | | { |
| 299 | | if (pin == DEC_PIN_BUS_HOLD) |
| 300 | | m_pin_bus_hold = val; |
| 301 | | else if (pin == DEC_PIN_RESET) |
| 302 | | m_pin_reset = val; |
| 303 | | else |
| 304 | | assert (0); |
| 305 | | } |
| 306 | | |
| 307 | | |
| 308 | | /* This is the external interface for indicating an external interrupt |
| 309 | | to the i860. */ |
| 310 | | void i860_cpu_device::i860_gen_interrupt() |
| 311 | | { |
| 312 | | /* If interrupts are enabled, then set PSR.IN and prepare for trap. |
| 313 | | Otherwise, the external interrupt is ignored. We also set |
| 314 | | bit EPSR.INT (which tracks the INT pin). */ |
| 315 | | if (GET_PSR_IM ()) |
| 316 | | { |
| 317 | | SET_PSR_IN (1); |
| 318 | | SET_EPSR_INT (1); |
| 319 | | m_pending_trap = TRAP_WAS_EXTERNAL; |
| 320 | | } |
| 321 | | |
| 322 | | #ifdef TRACE_EXT_INT |
| 323 | | fprintf (stderr, "i860_gen_interrupt: External interrupt received "); |
| 324 | | if (GET_PSR_IM ()) |
| 325 | | fprintf (stderr, "[PSR.IN set, preparing to trap]\n"); |
| 326 | | else |
| 327 | | fprintf (stderr, "[ignored (interrupts disabled)]\n"); |
| 328 | | #endif |
| 329 | | } |
| 330 | | |
| 331 | | |
| 332 | | /* Fetch instructions from instruction cache. |
| 333 | | Note: The instruction cache is not implemented for MAME version, |
| 334 | | this just fetches and returns 1 instruction from memory. */ |
| 335 | | UINT32 i860_cpu_device::ifetch (UINT32 pc) |
| 336 | | { |
| 337 | | UINT32 phys_pc = 0; |
| 338 | | UINT32 w1 = 0; |
| 339 | | |
| 340 | | /* If virtual mode, get translation. */ |
| 341 | | if (GET_DIRBASE_ATE ()) |
| 342 | | { |
| 343 | | phys_pc = get_address_translation (pc, 0 /* is_dataref */, 0 /* is_write */); |
| 344 | | m_exiting_ifetch = 0; |
| 345 | | if (m_pending_trap && (GET_PSR_DAT () || GET_PSR_IAT ())) |
| 346 | | { |
| 347 | | m_exiting_ifetch = 1; |
| 348 | | return 0xffeeffee; |
| 349 | | } |
| 350 | | } |
| 351 | | else |
| 352 | | phys_pc = pc; |
| 353 | | |
| 354 | | /* Since i860 instructions are always stored LSB first (regardless of |
| 355 | | the BE bit), we need to adjust the instruction below on MSB hosts. */ |
| 356 | | w1 = m_program->read_dword(phys_pc); |
| 357 | | #ifdef HOST_MSB |
| 358 | | BYTE_REV32 (w1); |
| 359 | | #endif /* HOST_MSB. */ |
| 360 | | return w1; |
| 361 | | } |
| 362 | | |
| 363 | | |
| 364 | | /* Given a virtual address, perform the i860 address translation and |
| 365 | | return the corresponding physical address. |
| 366 | | vaddr: virtual address |
| 367 | | is_dataref: 1 = load/store, 0 = instruction fetch. |
| 368 | | is_write: 1 = writing to vaddr, 0 = reading from vaddr |
| 369 | | The last two arguments are only used to determine what types |
| 370 | | of traps should be taken. |
| 371 | | |
| 372 | | Page tables must always be in memory (not cached). So the routine |
| 373 | | here only accesses memory. */ |
| 374 | | UINT32 i860_cpu_device::get_address_translation (UINT32 vaddr, int is_dataref, int is_write) |
| 375 | | { |
| 376 | | UINT32 vdir = (vaddr >> 22) & 0x3ff; |
| 377 | | UINT32 vpage = (vaddr >> 12) & 0x3ff; |
| 378 | | UINT32 voffset = vaddr & 0xfff; |
| 379 | | UINT32 dtb = (m_cregs[CR_DIRBASE]) & 0xfffff000; |
| 380 | | UINT32 pg_dir_entry_a = 0; |
| 381 | | UINT32 pg_dir_entry = 0; |
| 382 | | UINT32 pg_tbl_entry_a = 0; |
| 383 | | UINT32 pg_tbl_entry = 0; |
| 384 | | UINT32 pfa1 = 0; |
| 385 | | UINT32 pfa2 = 0; |
| 386 | | UINT32 ret = 0; |
| 387 | | UINT32 ttpde = 0; |
| 388 | | UINT32 ttpte = 0; |
| 389 | | |
| 390 | | assert (GET_DIRBASE_ATE ()); |
| 391 | | |
| 392 | | /* Get page directory entry at DTB:DIR:00. */ |
| 393 | | pg_dir_entry_a = dtb | (vdir << 2); |
| 394 | | pg_dir_entry = m_program->read_dword(pg_dir_entry_a); |
| 395 | | #ifdef HOST_MSB |
| 396 | | BYTE_REV32 (pg_dir_entry); |
| 397 | | #endif |
| 398 | | |
| 399 | | /* Check for non-present PDE. */ |
| 400 | | if (!(pg_dir_entry & 1)) |
| 401 | | { |
| 402 | | /* PDE is not present, generate DAT or IAT. */ |
| 403 | | if (is_dataref) |
| 404 | | SET_PSR_DAT (1); |
| 405 | | else |
| 406 | | SET_PSR_IAT (1); |
| 407 | | m_pending_trap = 1; |
| 408 | | |
| 409 | | /* Dummy return. */ |
| 410 | | return 0; |
| 411 | | } |
| 412 | | |
| 413 | | /* PDE Check for write protection violations. */ |
| 414 | | if (is_write && is_dataref |
| 415 | | && !(pg_dir_entry & 2) /* W = 0. */ |
| 416 | | && (GET_PSR_U () || GET_EPSR_WP ())) /* PSR_U = 1 or EPSR_WP = 1. */ |
| 417 | | { |
| 418 | | SET_PSR_DAT (1); |
| 419 | | m_pending_trap = 1; |
| 420 | | /* Dummy return. */ |
| 421 | | return 0; |
| 422 | | } |
| 423 | | |
| 424 | | /* PDE Check for user-mode access to supervisor pages. */ |
| 425 | | if (GET_PSR_U () |
| 426 | | && !(pg_dir_entry & 4)) /* U = 0. */ |
| 427 | | { |
| 428 | | if (is_dataref) |
| 429 | | SET_PSR_DAT (1); |
| 430 | | else |
| 431 | | SET_PSR_IAT (1); |
| 432 | | m_pending_trap = 1; |
| 433 | | /* Dummy return. */ |
| 434 | | return 0; |
| 435 | | } |
| 436 | | |
| 437 | | /* FIXME: How exactly to handle A check/update?. */ |
| 438 | | |
| 439 | | /* Get page table entry at PFA1:PAGE:00. */ |
| 440 | | pfa1 = pg_dir_entry & 0xfffff000; |
| 441 | | pg_tbl_entry_a = pfa1 | (vpage << 2); |
| 442 | | pg_tbl_entry = m_program->read_dword(pg_tbl_entry_a); |
| 443 | | #ifdef HOST_MSB |
| 444 | | BYTE_REV32 (pg_tbl_entry); |
| 445 | | #endif |
| 446 | | |
| 447 | | /* Check for non-present PTE. */ |
| 448 | | if (!(pg_tbl_entry & 1)) |
| 449 | | { |
| 450 | | /* PTE is not present, generate DAT or IAT. */ |
| 451 | | if (is_dataref) |
| 452 | | SET_PSR_DAT (1); |
| 453 | | else |
| 454 | | SET_PSR_IAT (1); |
| 455 | | m_pending_trap = 1; |
| 456 | | |
| 457 | | /* Dummy return. */ |
| 458 | | return 0; |
| 459 | | } |
| 460 | | |
| 461 | | /* PTE Check for write protection violations. */ |
| 462 | | if (is_write && is_dataref |
| 463 | | && !(pg_tbl_entry & 2) /* W = 0. */ |
| 464 | | && (GET_PSR_U () || GET_EPSR_WP ())) /* PSR_U = 1 or EPSR_WP = 1. */ |
| 465 | | { |
| 466 | | SET_PSR_DAT (1); |
| 467 | | m_pending_trap = 1; |
| 468 | | /* Dummy return. */ |
| 469 | | return 0; |
| 470 | | } |
| 471 | | |
| 472 | | /* PTE Check for user-mode access to supervisor pages. */ |
| 473 | | if (GET_PSR_U () |
| 474 | | && !(pg_tbl_entry & 4)) /* U = 0. */ |
| 475 | | { |
| 476 | | if (is_dataref) |
| 477 | | SET_PSR_DAT (1); |
| 478 | | else |
| 479 | | SET_PSR_IAT (1); |
| 480 | | m_pending_trap = 1; |
| 481 | | /* Dummy return. */ |
| 482 | | return 0; |
| 483 | | } |
| 484 | | |
| 485 | | /* Update A bit and check D bit. */ |
| 486 | | ttpde = pg_dir_entry | 0x20; |
| 487 | | ttpte = pg_tbl_entry | 0x20; |
| 488 | | #ifdef HOST_MSB |
| 489 | | BYTE_REV32 (ttpde); |
| 490 | | BYTE_REV32 (ttpte); |
| 491 | | #endif |
| 492 | | m_program->write_dword(pg_dir_entry_a, ttpde); |
| 493 | | m_program->write_dword(pg_tbl_entry_a, ttpte); |
| 494 | | |
| 495 | | if (is_write && is_dataref && (pg_tbl_entry & 0x40) == 0) |
| 496 | | { |
| 497 | | /* fprintf(stderr, "DAT trap on write without dirty bit v0x%08x/p0x%08x\n", |
| 498 | | vaddr, (pg_tbl_entry & ~0xfff)|voffset); */ |
| 499 | | SET_PSR_DAT (1); |
| 500 | | m_pending_trap = 1; |
| 501 | | /* Dummy return. */ |
| 502 | | return 0; |
| 503 | | } |
| 504 | | |
| 505 | | pfa2 = (pg_tbl_entry & 0xfffff000); |
| 506 | | ret = pfa2 | voffset; |
| 507 | | |
| 508 | | #ifdef TRACE_ADDR_TRANSLATION |
| 509 | | fprintf (stderr, "get_address_translation: virt(0x%08x) -> phys(0x%08x)\n", |
| 510 | | vaddr, ret); |
| 511 | | #endif |
| 512 | | |
| 513 | | return ret; |
| 514 | | } |
| 515 | | |
| 516 | | |
| 517 | | /* Read memory emulation. |
| 518 | | addr = address to read. |
| 519 | | size = size of read in bytes. */ |
| 520 | | UINT32 i860_cpu_device::readmemi_emu (UINT32 addr, int size) |
| 521 | | { |
| 522 | | #ifdef TRACE_RDWR_MEM |
| 523 | | fprintf (stderr, "readmemi_emu: (ATE=%d) addr = 0x%08x, size = %d\n", |
| 524 | | GET_DIRBASE_ATE (), addr, size); |
| 525 | | #endif |
| 526 | | |
| 527 | | /* If virtual mode, do translation. */ |
| 528 | | if (GET_DIRBASE_ATE ()) |
| 529 | | { |
| 530 | | UINT32 phys = get_address_translation (addr, 1 /* is_dataref */, 0 /* is_write */); |
| 531 | | if (m_pending_trap && (GET_PSR_IAT () || GET_PSR_DAT ())) |
| 532 | | { |
| 533 | | #ifdef TRACE_PAGE_FAULT |
| 534 | | fprintf (stderr, "0x%08x: ## Page fault (readmemi_emu).\n", |
| 535 | | m_pc); |
| 536 | | #endif |
| 537 | | m_exiting_readmem = 1; |
| 538 | | return 0; |
| 539 | | } |
| 540 | | addr = phys; |
| 541 | | } |
| 542 | | |
| 543 | | /* First check for match to db register (before read). */ |
| 544 | | if (((addr & ~(size - 1)) == m_cregs[CR_DB]) && GET_PSR_BR ()) |
| 545 | | { |
| 546 | | SET_PSR_DAT (1); |
| 547 | | m_pending_trap = 1; |
| 548 | | return 0; |
| 549 | | } |
| 550 | | |
| 551 | | /* Now do the actual read. */ |
| 552 | | if (size == 1) |
| 553 | | { |
| 554 | | UINT32 ret = m_program->read_byte(addr); |
| 555 | | return ret & 0xff; |
| 556 | | } |
| 557 | | else if (size == 2) |
| 558 | | { |
| 559 | | UINT32 ret = m_program->read_word(addr); |
| 560 | | #ifdef HOST_MSB |
| 561 | | BYTE_REV16 (ret); |
| 562 | | #endif |
| 563 | | return ret & 0xffff; |
| 564 | | } |
| 565 | | else if (size == 4) |
| 566 | | { |
| 567 | | UINT32 ret = m_program->read_dword(addr); |
| 568 | | #ifdef HOST_MSB |
| 569 | | BYTE_REV32 (ret); |
| 570 | | #endif |
| 571 | | return ret; |
| 572 | | } |
| 573 | | else |
| 574 | | assert (0); |
| 575 | | |
| 576 | | return 0; |
| 577 | | } |
| 578 | | |
| 579 | | |
| 580 | | /* Write memory emulation. |
| 581 | | addr = address to write. |
| 582 | | size = size of write in bytes. |
| 583 | | data = data to write. */ |
| 584 | | void i860_cpu_device::writememi_emu (UINT32 addr, int size, UINT32 data) |
| 585 | | { |
| 586 | | #ifdef TRACE_RDWR_MEM |
| 587 | | fprintf (stderr, "writememi_emu: (ATE=%d) addr = 0x%08x, size = %d, data = 0x%08x\n", |
| 588 | | GET_DIRBASE_ATE (), addr, size, data); |
| 589 | | #endif |
| 590 | | |
| 591 | | /* If virtual mode, do translation. */ |
| 592 | | if (GET_DIRBASE_ATE ()) |
| 593 | | { |
| 594 | | UINT32 phys = get_address_translation (addr, 1 /* is_dataref */, 1 /* is_write */); |
| 595 | | if (m_pending_trap && (GET_PSR_IAT () || GET_PSR_DAT ())) |
| 596 | | { |
| 597 | | #ifdef TRACE_PAGE_FAULT |
| 598 | | fprintf (stderr, "0x%08x: ## Page fault (writememi_emu).\n", |
| 599 | | m_pc); |
| 600 | | #endif |
| 601 | | m_exiting_readmem = 2; |
| 602 | | return; |
| 603 | | } |
| 604 | | addr = phys; |
| 605 | | } |
| 606 | | |
| 607 | | /* First check for match to db register (before write). */ |
| 608 | | if (((addr & ~(size - 1)) == m_cregs[CR_DB]) && GET_PSR_BW ()) |
| 609 | | { |
| 610 | | SET_PSR_DAT (1); |
| 611 | | m_pending_trap = 1; |
| 612 | | return; |
| 613 | | } |
| 614 | | |
| 615 | | /* Now do the actual write. */ |
| 616 | | if (size == 1) |
| 617 | | m_program->write_byte(addr, data); |
| 618 | | else if (size == 2) |
| 619 | | { |
| 620 | | #ifdef HOST_MSB |
| 621 | | BYTE_REV16 (data); |
| 622 | | #endif |
| 623 | | m_program->write_word(addr, data); |
| 624 | | } |
| 625 | | else if (size == 4) |
| 626 | | { |
| 627 | | #ifdef HOST_MSB |
| 628 | | BYTE_REV32 (data); |
| 629 | | #endif |
| 630 | | m_program->write_dword(addr, data); |
| 631 | | } |
| 632 | | else |
| 633 | | assert (0); |
| 634 | | } |
| 635 | | |
| 636 | | |
| 637 | | /* Floating-point read mem routine. |
| 638 | | addr = address to read. |
| 639 | | size = size of read in bytes. |
| 640 | | dest = memory to put read data. */ |
| 641 | | void i860_cpu_device::fp_readmem_emu (UINT32 addr, int size, UINT8 *dest) |
| 642 | | { |
| 643 | | #ifdef TRACE_RDWR_MEM |
| 644 | | fprintf (stderr, "fp_readmem_emu: (ATE=%d) addr = 0x%08x, size = %d\n", |
| 645 | | GET_DIRBASE_ATE (), addr, size); |
| 646 | | #endif |
| 647 | | |
| 648 | | assert (size == 4 || size == 8 || size == 16); |
| 649 | | |
| 650 | | /* If virtual mode, do translation. */ |
| 651 | | if (GET_DIRBASE_ATE ()) |
| 652 | | { |
| 653 | | UINT32 phys = get_address_translation (addr, 1 /* is_dataref */, 0 /* is_write */); |
| 654 | | if (m_pending_trap && (GET_PSR_IAT () || GET_PSR_DAT ())) |
| 655 | | { |
| 656 | | #ifdef TRACE_PAGE_FAULT |
| 657 | | fprintf (stderr, "0x%08x: ## Page fault (fp_readmem_emu).\n", |
| 658 | | m_pc); |
| 659 | | #endif |
| 660 | | m_exiting_readmem = 3; |
| 661 | | return; |
| 662 | | } |
| 663 | | addr = phys; |
| 664 | | } |
| 665 | | |
| 666 | | /* First check for match to db register (before read). */ |
| 667 | | if (((addr & ~(size - 1)) == m_cregs[CR_DB]) && GET_PSR_BR ()) |
| 668 | | { |
| 669 | | SET_PSR_DAT (1); |
| 670 | | m_pending_trap = 1; |
| 671 | | return; |
| 672 | | } |
| 673 | | |
| 674 | | if (size == 4) |
| 675 | | { |
| 676 | | dest[0] = m_program->read_byte(addr+3); |
| 677 | | dest[1] = m_program->read_byte(addr+2); |
| 678 | | dest[2] = m_program->read_byte(addr+1); |
| 679 | | dest[3] = m_program->read_byte(addr+0); |
| 680 | | } |
| 681 | | else if (size == 8) |
| 682 | | { |
| 683 | | dest[0] = m_program->read_byte(addr+7); |
| 684 | | dest[1] = m_program->read_byte(addr+6); |
| 685 | | dest[2] = m_program->read_byte(addr+5); |
| 686 | | dest[3] = m_program->read_byte(addr+4); |
| 687 | | dest[4] = m_program->read_byte(addr+3); |
| 688 | | dest[5] = m_program->read_byte(addr+2); |
| 689 | | dest[6] = m_program->read_byte(addr+1); |
| 690 | | dest[7] = m_program->read_byte(addr+0); |
| 691 | | } |
| 692 | | else if (size == 16) |
| 693 | | { |
| 694 | | int i; |
| 695 | | for (i = 0; i < 16; i++) |
| 696 | | { |
| 697 | | dest[i] = m_program->read_byte(addr+15-i); |
| 698 | | } |
| 699 | | } |
| 700 | | } |
| 701 | | |
| 702 | | |
| 703 | | /* Floating-point write mem routine. |
| 704 | | addr = address to read. |
| 705 | | size = size of read in bytes. |
| 706 | | data = pointer to the data. |
| 707 | | wmask = bit mask of bytes to write (only for pst.d). */ |
| 708 | | void i860_cpu_device::fp_writemem_emu (UINT32 addr, int size, UINT8 *data, UINT32 wmask) |
| 709 | | { |
| 710 | | #ifdef TRACE_RDWR_MEM |
| 711 | | fprintf (stderr, "fp_writemem_emu: (ATE=%d) addr = 0x%08x, size = %d\n", |
| 712 | | GET_DIRBASE_ATE (), addr, size); |
| 713 | | #endif |
| 714 | | |
| 715 | | assert (size == 4 || size == 8 || size == 16); |
| 716 | | |
| 717 | | /* If virtual mode, do translation. */ |
| 718 | | if (GET_DIRBASE_ATE ()) |
| 719 | | { |
| 720 | | UINT32 phys = get_address_translation (addr, 1 /* is_dataref */, 1 /* is_write */); |
| 721 | | if (m_pending_trap && GET_PSR_DAT ()) |
| 722 | | { |
| 723 | | #ifdef TRACE_PAGE_FAULT |
| 724 | | fprintf (stderr, "0x%08x: ## Page fault (fp_writememi_emu).\n", |
| 725 | | m_pc); |
| 726 | | #endif |
| 727 | | m_exiting_readmem = 4; |
| 728 | | return; |
| 729 | | } |
| 730 | | addr = phys; |
| 731 | | } |
| 732 | | |
| 733 | | /* First check for match to db register (before read). */ |
| 734 | | if (((addr & ~(size - 1)) == m_cregs[CR_DB]) && GET_PSR_BW ()) |
| 735 | | { |
| 736 | | SET_PSR_DAT (1); |
| 737 | | m_pending_trap = 1; |
| 738 | | return; |
| 739 | | } |
| 740 | | |
| 741 | | if (size == 4) |
| 742 | | { |
| 743 | | #if 1 |
| 744 | | m_program->write_byte(addr+3, data[0]); |
| 745 | | m_program->write_byte(addr+2, data[1]); |
| 746 | | m_program->write_byte(addr+1, data[2]); |
| 747 | | m_program->write_byte(addr+0, data[3]); |
| 748 | | #else |
| 749 | | UINT32 ddd = (data[3]) | (data[2] << 8) | (data[1] << 16) |(data[0] << 24); |
| 750 | | m_program->write_dword(addr+0, ddd); |
| 751 | | #endif |
| 752 | | } |
| 753 | | else if (size == 8) |
| 754 | | { |
| 755 | | /* Special: watch for wmask != 0xff, which means we're doing pst.d. */ |
| 756 | | if (wmask == 0xff) |
| 757 | | { |
| 758 | | m_program->write_byte(addr+7, data[0]); |
| 759 | | m_program->write_byte(addr+6, data[1]); |
| 760 | | m_program->write_byte(addr+5, data[2]); |
| 761 | | m_program->write_byte(addr+4, data[3]); |
| 762 | | m_program->write_byte(addr+3, data[4]); |
| 763 | | m_program->write_byte(addr+2, data[5]); |
| 764 | | m_program->write_byte(addr+1, data[6]); |
| 765 | | m_program->write_byte(addr+0, data[7]); |
| 766 | | } |
| 767 | | else |
| 768 | | { |
| 769 | | if (wmask & 0x80) m_program->write_byte(addr+7, data[0]); |
| 770 | | if (wmask & 0x40) m_program->write_byte(addr+6, data[1]); |
| 771 | | if (wmask & 0x20) m_program->write_byte(addr+5, data[2]); |
| 772 | | if (wmask & 0x10) m_program->write_byte(addr+4, data[3]); |
| 773 | | if (wmask & 0x08) m_program->write_byte(addr+3, data[4]); |
| 774 | | if (wmask & 0x04) m_program->write_byte(addr+2, data[5]); |
| 775 | | if (wmask & 0x02) m_program->write_byte(addr+1, data[6]); |
| 776 | | if (wmask & 0x01) m_program->write_byte(addr+0, data[7]); |
| 777 | | } |
| 778 | | } |
| 779 | | else if (size == 16) |
| 780 | | { |
| 781 | | int i; |
| 782 | | for (i = 0; i < 16; i++) |
| 783 | | { |
| 784 | | m_program->write_byte(addr+15-i, data[i]); |
| 785 | | } |
| 786 | | } |
| 787 | | |
| 788 | | } |
| 789 | | |
| 790 | | |
| 791 | | #if 0 |
| 792 | | /* Do a pipeline dump. |
| 793 | | type: 0 (all), 1 (add), 2 (mul), 3 (load), 4 (graphics). */ |
| 794 | | void i860_cpu_device::dump_pipe (int type) |
| 795 | | { |
| 796 | | int i = 0; |
| 797 | | |
| 798 | | fprintf (stderr, "pipeline state:\n"); |
| 799 | | /* Dump the adder pipeline, if requested. */ |
| 800 | | if (type == 0 || type == 1) |
| 801 | | { |
| 802 | | fprintf (stderr, " A: "); |
| 803 | | for (i = 0; i < 3; i++) |
| 804 | | { |
| 805 | | if (m_A[i].stat.arp) |
| 806 | | fprintf (stderr, "[%dd] 0x%016llx ", i + 1, |
| 807 | | *(UINT64 *)(&m_A[i].val.d)); |
| 808 | | else |
| 809 | | fprintf (stderr, "[%ds] 0x%08x ", i + 1, |
| 810 | | *(UINT32 *)(&m_A[i].val.s)); |
| 811 | | } |
| 812 | | fprintf (stderr, "\n"); |
| 813 | | } |
| 814 | | |
| 815 | | |
| 816 | | /* Dump the multiplier pipeline, if requested. */ |
| 817 | | if (type == 0 || type == 2) |
| 818 | | { |
| 819 | | fprintf (stderr, " M: "); |
| 820 | | for (i = 0; i < 3; i++) |
| 821 | | { |
| 822 | | if (m_M[i].stat.mrp) |
| 823 | | fprintf (stderr, "[%dd] 0x%016llx ", i + 1, |
| 824 | | *(UINT64 *)(&m_M[i].val.d)); |
| 825 | | else |
| 826 | | fprintf (stderr, "[%ds] 0x%08x ", i + 1, |
| 827 | | *(UINT32 *)(&m_M[i].val.s)); |
| 828 | | } |
| 829 | | fprintf (stderr, "\n"); |
| 830 | | } |
| 831 | | |
| 832 | | /* Dump the load pipeline, if requested. */ |
| 833 | | if (type == 0 || type == 3) |
| 834 | | { |
| 835 | | fprintf (stderr, " L: "); |
| 836 | | for (i = 0; i < 3; i++) |
| 837 | | { |
| 838 | | if (m_L[i].stat.lrp) |
| 839 | | fprintf (stderr, "[%dd] 0x%016llx ", i + 1, |
| 840 | | *(UINT64 *)(&m_L[i].val.d)); |
| 841 | | else |
| 842 | | fprintf (stderr, "[%ds] 0x%08x ", i + 1, |
| 843 | | *(UINT32 *)(&m_L[i].val.s)); |
| 844 | | } |
| 845 | | fprintf (stderr, "\n"); |
| 846 | | } |
| 847 | | |
| 848 | | /* Dump the graphics pipeline, if requested. */ |
| 849 | | if (type == 0 || type == 4) |
| 850 | | { |
| 851 | | fprintf (stderr, " I: "); |
| 852 | | if (m_G.stat.irp) |
| 853 | | fprintf (stderr, "[1d] 0x%016llx\n", |
| 854 | | *(UINT64 *)(&m_G.val.d)); |
| 855 | | else |
| 856 | | fprintf (stderr, "[1s] 0x%08x\n", |
| 857 | | *(UINT32 *)(&m_G.val.s)); |
| 858 | | } |
| 859 | | } |
| 860 | | |
| 861 | | |
| 862 | | /* Do a register/state dump. */ |
| 863 | | void i860_cpu_device::dump_state (i860s *cpustate) |
| 864 | | { |
| 865 | | int rn; |
| 866 | | |
| 867 | | /* GR's first, 4 per line. */ |
| 868 | | for (rn = 0; rn < 32; rn++) |
| 869 | | { |
| 870 | | if ((rn % 4) == 0) |
| 871 | | fprintf (stderr, "\n"); |
| 872 | | fprintf (stderr, "%%r%-3d: 0x%08x ", rn, get_iregval (rn)); |
| 873 | | } |
| 874 | | fprintf (stderr, "\n"); |
| 875 | | |
| 876 | | /* FR's (as 32-bits), 4 per line. */ |
| 877 | | for (rn = 0; rn < 32; rn++) |
| 878 | | { |
| 879 | | float ff = get_fregval_s (rn); |
| 880 | | if ((rn % 4) == 0) |
| 881 | | fprintf (stderr, "\n"); |
| 882 | | fprintf (stderr, "%%f%-3d: 0x%08x ", rn, *(UINT32 *)&ff); |
| 883 | | } |
| 884 | | fprintf (stderr, "\n"); |
| 885 | | |
| 886 | | fprintf (stderr, " psr: CC = %d, LCC = %d, SC = %d, IM = %d, U = %d\n", |
| 887 | | GET_PSR_CC (), GET_PSR_LCC (), GET_PSR_SC (), GET_PSR_IM (), |
| 888 | | GET_PSR_U ()); |
| 889 | | fprintf (stderr, " IT/FT/IAT/DAT/IN = %d/%d/%d/%d/%d\n", |
| 890 | | GET_PSR_IT (), GET_PSR_FT (), GET_PSR_IAT (), |
| 891 | | GET_PSR_DAT (), GET_PSR_IN ()); |
| 892 | | fprintf (stderr, "epsr: INT = %d, OF = %d, BE = %d\n", |
| 893 | | GET_EPSR_INT (), GET_EPSR_OF (), GET_EPSR_BE ()); |
| 894 | | fprintf (stderr, " fir: 0x%08x dirbase: 0x%08x fsr: 0x%08x\n", |
| 895 | | m_cregs[CR_FIR], m_cregs[CR_DIRBASE], |
| 896 | | m_cregs[CR_FSR]); |
| 897 | | fprintf (stderr, " pc: 0x%08x\n", m_pc); |
| 898 | | } |
| 899 | | #endif |
| 900 | | |
| 901 | | /* Sign extend N-bit number. */ |
| 902 | | INLINE INT32 sign_ext (UINT32 x, int n) |
| 903 | | { |
| 904 | | INT32 t; |
| 905 | | t = x >> (n - 1); |
| 906 | | t = ((-t) << n) | x; |
| 907 | | return t; |
| 908 | | } |
| 909 | | |
| 910 | | |
| 911 | | void i860_cpu_device::unrecog_opcode (UINT32 pc, UINT32 insn) |
| 912 | | { |
| 913 | | fprintf (stderr, "0x%08x: 0x%08x (unrecognized opcode)\n", pc, insn); |
| 914 | | } |
| 915 | | |
| 916 | | |
| 917 | | /* Execute "ld.c csrc2,idest" instruction. */ |
| 918 | | void i860_cpu_device::insn_ld_ctrl (UINT32 insn) |
| 919 | | { |
| 920 | | UINT32 csrc2 = get_creg (insn); |
| 921 | | UINT32 idest = get_idest (insn); |
| 922 | | |
| 923 | | #ifdef TRACE_UNDEFINED_I860 |
| 924 | | if (csrc2 > 5) |
| 925 | | { |
| 926 | | /* Control register not between 0..5. Undefined i860XR behavior. */ |
| 927 | | fprintf (stderr, "WARNING: insn_ld_from_ctrl (pc=0x%08x): bad creg in ld.c (ignored)\n", m_pc); |
| 928 | | return; |
| 929 | | } |
| 930 | | #endif |
| 931 | | |
| 932 | | /* If this is a load of the fir, then there are two cases: |
| 933 | | 1. First load of fir after a trap = usual value. |
| 934 | | 2. Not first load of fir after a trap = address of the ld.c insn. */ |
| 935 | | if (csrc2 == CR_FIR) |
| 936 | | { |
| 937 | | if (m_fir_gets_trap_addr) |
| 938 | | set_iregval (idest, m_cregs[csrc2]); |
| 939 | | else |
| 940 | | { |
| 941 | | m_cregs[csrc2] = m_pc; |
| 942 | | set_iregval (idest, m_cregs[csrc2]); |
| 943 | | } |
| 944 | | m_fir_gets_trap_addr = 0; |
| 945 | | } |
| 946 | | else |
| 947 | | set_iregval (idest, m_cregs[csrc2]); |
| 948 | | } |
| 949 | | |
| 950 | | |
| 951 | | /* Execute "st.c isrc1,csrc2" instruction. */ |
| 952 | | void i860_cpu_device::insn_st_ctrl (UINT32 insn) |
| 953 | | { |
| 954 | | UINT32 csrc2 = get_creg (insn); |
| 955 | | UINT32 isrc1 = get_isrc1 (insn); |
| 956 | | |
| 957 | | #ifdef TRACE_UNDEFINED_I860 |
| 958 | | if (csrc2 > 5) |
| 959 | | { |
| 960 | | /* Control register not between 0..5. Undefined i860XR behavior. */ |
| 961 | | fprintf (stderr, "WARNING: insn_st_to_ctrl (pc=0x%08x): bad creg in st.c (ignored)\n", m_pc); |
| 962 | | return; |
| 963 | | } |
| 964 | | #endif |
| 965 | | |
| 966 | | /* Look for ITI bit turned on (but it never actually is written -- |
| 967 | | it always appears to be 0). */ |
| 968 | | if (csrc2 == CR_DIRBASE && (get_iregval (isrc1) & 0x20)) |
| 969 | | { |
| 970 | | /* NOTE: The actual icache and TLB flush are unimplemented for |
| 971 | | the MAME version. */ |
| 972 | | |
| 973 | | /* Make sure ITI isn't actually written. */ |
| 974 | | set_iregval (isrc1, (get_iregval (isrc1) & ~0x20)); |
| 975 | | } |
| 976 | | |
| 977 | | if (csrc2 == CR_DIRBASE && (get_iregval (isrc1) & 1) |
| 978 | | && GET_DIRBASE_ATE () == 0) |
| 979 | | { |
| 980 | | fprintf (stderr, "0x%08x: ** ATE going high!\n", m_pc); |
| 981 | | } |
| 982 | | |
| 983 | | /* Update the register -- unless it is fir which cannot be updated. */ |
| 984 | | if (csrc2 == CR_EPSR) |
| 985 | | { |
| 986 | | UINT32 enew = 0, tmp = 0; |
| 987 | | /* Make sure unchangeable EPSR bits stay unchanged (DCS, stepping, |
| 988 | | and type). Also, some bits are only writeable in supervisor |
| 989 | | mode. */ |
| 990 | | if (GET_PSR_U ()) |
| 991 | | { |
| 992 | | enew = get_iregval (isrc1) & ~(0x003e1fff | 0x00c06000); |
| 993 | | tmp = m_cregs[CR_EPSR] & (0x003e1fff | 0x00c06000); |
| 994 | | } |
| 995 | | else |
| 996 | | { |
| 997 | | enew = get_iregval (isrc1) & ~0x003e1fff; |
| 998 | | tmp = m_cregs[CR_EPSR] & 0x003e1fff; |
| 999 | | } |
| 1000 | | m_cregs[CR_EPSR] = enew | tmp; |
| 1001 | | } |
| 1002 | | else if (csrc2 == CR_PSR) |
| 1003 | | { |
| 1004 | | /* Some PSR bits are only writeable in supervisor mode. */ |
| 1005 | | if (GET_PSR_U ()) |
| 1006 | | { |
| 1007 | | UINT32 enew = get_iregval (isrc1) & ~PSR_SUPERVISOR_ONLY_MASK; |
| 1008 | | UINT32 tmp = m_cregs[CR_PSR] & PSR_SUPERVISOR_ONLY_MASK; |
| 1009 | | m_cregs[CR_PSR] = enew | tmp; |
| 1010 | | } |
| 1011 | | else |
| 1012 | | m_cregs[CR_PSR] = get_iregval (isrc1); |
| 1013 | | } |
| 1014 | | else if (csrc2 == CR_FSR) |
| 1015 | | { |
| 1016 | | /* I believe that only 21..17, 8..5, and 3..0 should be updated. */ |
| 1017 | | UINT32 enew = get_iregval (isrc1) & 0x003e01ef; |
| 1018 | | UINT32 tmp = m_cregs[CR_FSR] & ~0x003e01ef; |
| 1019 | | m_cregs[CR_FSR] = enew | tmp; |
| 1020 | | } |
| 1021 | | else if (csrc2 != CR_FIR) |
| 1022 | | m_cregs[csrc2] = get_iregval (isrc1); |
| 1023 | | } |
| 1024 | | |
| 1025 | | |
| 1026 | | /* Execute "ld.{s,b,l} isrc1(isrc2),idest" or |
| 1027 | | "ld.{s,b,l} #const(isrc2),idest". */ |
| 1028 | | void i860_cpu_device::insn_ldx (UINT32 insn) |
| 1029 | | { |
| 1030 | | UINT32 isrc1 = get_isrc1 (insn); |
| 1031 | | INT32 immsrc1 = sign_ext (get_imm16 (insn), 16); |
| 1032 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1033 | | UINT32 idest = get_idest (insn); |
| 1034 | | UINT32 eff = 0; |
| 1035 | | /* Operand size, in bytes. */ |
| 1036 | | int sizes[4] = { 1, 1, 2, 4}; |
| 1037 | | int size = 0; |
| 1038 | | int form_disp_reg = 0; |
| 1039 | | |
| 1040 | | /* Bits 28 and 0 determine the operand size. */ |
| 1041 | | size = sizes[((insn >> 27) & 2) | (insn & 1)]; |
| 1042 | | |
| 1043 | | /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */ |
| 1044 | | form_disp_reg = (insn & 0x04000000); |
| 1045 | | |
| 1046 | | /* Get effective address depending on disp+reg or reg+reg form. */ |
| 1047 | | if (form_disp_reg) |
| 1048 | | { |
| 1049 | | /* Chop off lower bits of displacement. */ |
| 1050 | | immsrc1 &= ~(size - 1); |
| 1051 | | eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2))); |
| 1052 | | } |
| 1053 | | else |
| 1054 | | eff = get_iregval (isrc1) + get_iregval (isrc2); |
| 1055 | | |
| 1056 | | #ifdef TRACE_UNALIGNED_MEM |
| 1057 | | if (eff & (size - 1)) |
| 1058 | | { |
| 1059 | | fprintf (stderr, "0x%08x: Unaligned access detected (0x%08x).\n", |
| 1060 | | m_pc, eff); |
| 1061 | | SET_PSR_DAT (1); |
| 1062 | | m_pending_trap = 1; |
| 1063 | | return; |
| 1064 | | } |
| 1065 | | #endif |
| 1066 | | |
| 1067 | | /* The i860 sign-extends 8- or 16-bit integer loads. |
| 1068 | | |
| 1069 | | Below, the readmemi_emu() needs to happen outside of the |
| 1070 | | set_iregval macro (otherwise the readmem won't occur if r0 |
| 1071 | | is the target register). */ |
| 1072 | | if (size < 4) |
| 1073 | | { |
| 1074 | | UINT32 readval = sign_ext (readmemi_emu (eff, size), size * 8); |
| 1075 | | /* Do not update register on page fault. */ |
| 1076 | | if (m_exiting_readmem) |
| 1077 | | { |
| 1078 | | return; |
| 1079 | | } |
| 1080 | | set_iregval (idest, readval); |
| 1081 | | } |
| 1082 | | else |
| 1083 | | { |
| 1084 | | UINT32 readval = readmemi_emu (eff, size); |
| 1085 | | /* Do not update register on page fault. */ |
| 1086 | | if (m_exiting_readmem) |
| 1087 | | { |
| 1088 | | return; |
| 1089 | | } |
| 1090 | | set_iregval (idest, readval); |
| 1091 | | } |
| 1092 | | } |
| 1093 | | |
| 1094 | | |
| 1095 | | /* Execute "st.x isrc1ni,#const(isrc2)" instruction (there is no |
| 1096 | | (reg + reg form). Store uses the split immediate, not the normal |
| 1097 | | 16-bit immediate as in ld.x. */ |
| 1098 | | void i860_cpu_device::insn_stx (UINT32 insn) |
| 1099 | | { |
| 1100 | | INT32 immsrc = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); |
| 1101 | | UINT32 isrc1 = get_isrc1 (insn); |
| 1102 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1103 | | UINT32 eff = 0; |
| 1104 | | /* Operand size, in bytes. */ |
| 1105 | | int sizes[4] = { 1, 1, 2, 4}; |
| 1106 | | int size = 0; |
| 1107 | | |
| 1108 | | /* Bits 28 and 0 determine the operand size. */ |
| 1109 | | size = sizes[((insn >> 27) & 2) | (insn & 1)]; |
| 1110 | | |
| 1111 | | /* FIXME: Do any necessary traps. */ |
| 1112 | | |
| 1113 | | /* Get effective address. Chop off lower bits of displacement. */ |
| 1114 | | immsrc &= ~(size - 1); |
| 1115 | | eff = (UINT32)(immsrc + (INT32)get_iregval (isrc2)); |
| 1116 | | |
| 1117 | | /* Write data (value of reg isrc1) to memory at eff. */ |
| 1118 | | writememi_emu (eff, size, get_iregval (isrc1)); |
| 1119 | | if (m_exiting_readmem) |
| 1120 | | return; |
| 1121 | | } |
| 1122 | | |
| 1123 | | |
| 1124 | | /* Execute "fst.y fdest,isrc1(isrc2)", "fst.y fdest,isrc1(isrc2)++", |
| 1125 | | "fst.y fdest,#const(isrc2)" or "fst.y fdest,#const(isrc2)++" |
| 1126 | | instruction. */ |
| 1127 | | void i860_cpu_device::insn_fsty (UINT32 insn) |
| 1128 | | { |
| 1129 | | UINT32 isrc1 = get_isrc1 (insn); |
| 1130 | | INT32 immsrc1 = sign_ext (get_imm16 (insn), 16); |
| 1131 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1132 | | UINT32 fdest = get_fdest (insn); |
| 1133 | | UINT32 eff = 0; |
| 1134 | | /* Operand size, in bytes. */ |
| 1135 | | int sizes[4] = { 8, 4, 16, 4}; |
| 1136 | | int size = 0; |
| 1137 | | int form_disp_reg = 0; |
| 1138 | | int auto_inc = (insn & 1); |
| 1139 | | |
| 1140 | | /* Bits 2 and 1 determine the operand size. */ |
| 1141 | | size = sizes[((insn >> 1) & 3)]; |
| 1142 | | |
| 1143 | | /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */ |
| 1144 | | form_disp_reg = (insn & 0x04000000); |
| 1145 | | |
| 1146 | | /* FIXME: Check for undefined behavior, non-even or non-quad |
| 1147 | | register operands for fst.d and fst.q respectively. */ |
| 1148 | | |
| 1149 | | /* Get effective address depending on disp+reg or reg+reg form. */ |
| 1150 | | if (form_disp_reg) |
| 1151 | | { |
| 1152 | | /* Chop off lower bits of displacement. */ |
| 1153 | | immsrc1 &= ~(size - 1); |
| 1154 | | eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2))); |
| 1155 | | } |
| 1156 | | else |
| 1157 | | eff = get_iregval (isrc1) + get_iregval (isrc2); |
| 1158 | | |
| 1159 | | #ifdef TRACE_UNALIGNED_MEM |
| 1160 | | if (eff & (size - 1)) |
| 1161 | | { |
| 1162 | | fprintf (stderr, "0x%08x: Unaligned access detected (0x%08x).\n", |
| 1163 | | m_pc, eff); |
| 1164 | | SET_PSR_DAT (1); |
| 1165 | | m_pending_trap = 1; |
| 1166 | | return; |
| 1167 | | } |
| 1168 | | #endif |
| 1169 | | |
| 1170 | | /* Do (post) auto-increment. */ |
| 1171 | | if (auto_inc) |
| 1172 | | { |
| 1173 | | set_iregval (isrc2, eff); |
| 1174 | | #ifdef TRACE_UNDEFINED_I860 |
| 1175 | | /* When auto-inc, isrc1 and isrc2 regs can't be the same. */ |
| 1176 | | if (isrc1 == isrc2) |
| 1177 | | { |
| 1178 | | /* Undefined i860XR behavior. */ |
| 1179 | | fprintf (stderr, "WARNING: insn_fsty (pc=0x%08x): isrc1 = isrc2 in fst with auto-inc (ignored)\n", m_pc); |
| 1180 | | return; |
| 1181 | | } |
| 1182 | | #endif |
| 1183 | | } |
| 1184 | | |
| 1185 | | /* Write data (value of freg fdest) to memory at eff. */ |
| 1186 | | if (size == 4) |
| 1187 | | fp_writemem_emu (eff, size, (UINT8 *)(&m_frg[4 * (31 - fdest)]), 0xff); |
| 1188 | | else if (size == 8) |
| 1189 | | fp_writemem_emu (eff, size, (UINT8 *)(&m_frg[4 * (31 - (fdest + 1))]), 0xff); |
| 1190 | | else |
| 1191 | | fp_writemem_emu (eff, size, (UINT8 *)(&m_frg[4 * (31 - (fdest + 3))]), 0xff); |
| 1192 | | |
| 1193 | | } |
| 1194 | | |
| 1195 | | |
| 1196 | | /* Execute "fld.y isrc1(isrc2),fdest", "fld.y isrc1(isrc2)++,idest", |
| 1197 | | "fld.y #const(isrc2),fdest" or "fld.y #const(isrc2)++,idest". |
| 1198 | | Where y = {l,d,q}. Note, there is no pfld.q, though. */ |
| 1199 | | void i860_cpu_device::insn_fldy (UINT32 insn) |
| 1200 | | { |
| 1201 | | UINT32 isrc1 = get_isrc1 (insn); |
| 1202 | | INT32 immsrc1 = sign_ext (get_imm16 (insn), 16); |
| 1203 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1204 | | UINT32 fdest = get_fdest (insn); |
| 1205 | | UINT32 eff = 0; |
| 1206 | | /* Operand size, in bytes. */ |
| 1207 | | int sizes[4] = { 8, 4, 16, 4}; |
| 1208 | | int size = 0; |
| 1209 | | int form_disp_reg = 0; |
| 1210 | | int auto_inc = (insn & 1); |
| 1211 | | int piped = (insn & 0x40000000); |
| 1212 | | |
| 1213 | | /* Bits 2 and 1 determine the operand size. */ |
| 1214 | | size = sizes[((insn >> 1) & 3)]; |
| 1215 | | |
| 1216 | | /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */ |
| 1217 | | form_disp_reg = (insn & 0x04000000); |
| 1218 | | |
| 1219 | | /* There is no pipelined load quad. */ |
| 1220 | | if (piped && size == 16) |
| 1221 | | { |
| 1222 | | unrecog_opcode (m_pc, insn); |
| 1223 | | return; |
| 1224 | | } |
| 1225 | | |
| 1226 | | /* FIXME: Check for undefined behavior, non-even or non-quad |
| 1227 | | register operands for fld.d and fld.q respectively. */ |
| 1228 | | |
| 1229 | | /* Get effective address depending on disp+reg or reg+reg form. */ |
| 1230 | | if (form_disp_reg) |
| 1231 | | { |
| 1232 | | /* Chop off lower bits of displacement. */ |
| 1233 | | immsrc1 &= ~(size - 1); |
| 1234 | | eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2))); |
| 1235 | | } |
| 1236 | | else |
| 1237 | | eff = get_iregval (isrc1) + get_iregval (isrc2); |
| 1238 | | |
| 1239 | | /* Do (post) auto-increment. */ |
| 1240 | | if (auto_inc) |
| 1241 | | { |
| 1242 | | set_iregval (isrc2, eff); |
| 1243 | | #ifdef TRACE_UNDEFINED_I860 |
| 1244 | | /* When auto-inc, isrc1 and isrc2 regs can't be the same. */ |
| 1245 | | if (isrc1 == isrc2) |
| 1246 | | { |
| 1247 | | /* Undefined i860XR behavior. */ |
| 1248 | | fprintf (stderr, "WARNING: insn_fldy (pc=0x%08x): isrc1 = isrc2 in fst with auto-inc (ignored)\n", m_pc); |
| 1249 | | return; |
| 1250 | | } |
| 1251 | | #endif |
| 1252 | | } |
| 1253 | | |
| 1254 | | #ifdef TRACE_UNALIGNED_MEM |
| 1255 | | if (eff & (size - 1)) |
| 1256 | | { |
| 1257 | | fprintf (stderr, "0x%08x: Unaligned access detected (0x%08x).\n", |
| 1258 | | m_pc, eff); |
| 1259 | | SET_PSR_DAT (1); |
| 1260 | | m_pending_trap = 1; |
| 1261 | | return; |
| 1262 | | } |
| 1263 | | #endif |
| 1264 | | |
| 1265 | | /* Update the load pipe if necessary. */ |
| 1266 | | /* FIXME: Copy result-status bits to fsr from last stage. */ |
| 1267 | | if (!piped) |
| 1268 | | { |
| 1269 | | /* Scalar version writes the current result to fdest. */ |
| 1270 | | /* Read data at 'eff' into freg 'fdest' (reads to f0 or f1 are |
| 1271 | | thrown away). */ |
| 1272 | | if (fdest > 1) |
| 1273 | | { |
| 1274 | | if (size == 4) |
| 1275 | | fp_readmem_emu (eff, size, (UINT8 *)&(m_frg[4 * (31 - fdest)])); |
| 1276 | | else if (size == 8) |
| 1277 | | fp_readmem_emu (eff, size, (UINT8 *)&(m_frg[4 * (31 - (fdest + 1))])); |
| 1278 | | else if (size == 16) |
| 1279 | | fp_readmem_emu (eff, size, (UINT8 *)&(m_frg[4 * (31 - (fdest + 3))])); |
| 1280 | | } |
| 1281 | | } |
| 1282 | | else |
| 1283 | | { |
| 1284 | | /* Read the data into a temp space first. This way we can test |
| 1285 | | for any traps before updating the pipeline. The pipeline must |
| 1286 | | stay unaffected after a trap so that the instruction can be |
| 1287 | | properly restarted. */ |
| 1288 | | UINT8 bebuf[8]; |
| 1289 | | fp_readmem_emu (eff, size, bebuf); |
| 1290 | | if (m_pending_trap && m_exiting_readmem) |
| 1291 | | goto ab_op; |
| 1292 | | |
| 1293 | | /* Pipelined version writes fdest with the result from the last |
| 1294 | | stage of the pipeline, with precision specified by the LRP |
| 1295 | | bit of the stage's result-status bits. */ |
| 1296 | | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 1297 | | /* Copy 3rd stage LRP to FSR. */ |
| 1298 | | if (m_L[1 /* 2 */].stat.lrp) |
| 1299 | | m_cregs[CR_FSR] |= 0x04000000; |
| 1300 | | else |
| 1301 | | m_cregs[CR_FSR] &= ~0x04000000; |
| 1302 | | #endif |
| 1303 | | if (m_L[2].stat.lrp) /* 3rd (last) stage. */ |
| 1304 | | set_fregval_d (fdest, m_L[2].val.d); |
| 1305 | | else |
| 1306 | | set_fregval_s (fdest, m_L[2].val.s); |
| 1307 | | |
| 1308 | | /* Now advance pipeline and write loaded data to first stage. */ |
| 1309 | | m_L[2] = m_L[1]; |
| 1310 | | m_L[1] = m_L[0]; |
| 1311 | | if (size == 8) |
| 1312 | | { |
| 1313 | | UINT8 *t = (UINT8 *)&(m_L[0].val.d); |
| 1314 | | #ifndef HOST_MSB |
| 1315 | | t[7] = bebuf[0]; t[6] = bebuf[1]; t[5] = bebuf[2]; t[4] = bebuf[3]; |
| 1316 | | t[3] = bebuf[4]; t[2] = bebuf[5]; t[1] = bebuf[6]; t[0] = bebuf[7]; |
| 1317 | | #else |
| 1318 | | t[0] = bebuf[0]; t[1] = bebuf[1]; t[2] = bebuf[2]; t[3] = bebuf[3]; |
| 1319 | | t[4] = bebuf[4]; t[5] = bebuf[5]; t[6] = bebuf[6]; t[7] = bebuf[7]; |
| 1320 | | #endif |
| 1321 | | m_L[0].stat.lrp = 1; |
| 1322 | | } |
| 1323 | | else |
| 1324 | | { |
| 1325 | | UINT8 *t = (UINT8 *)&(m_L[0].val.s); |
| 1326 | | #ifndef HOST_MSB |
| 1327 | | t[3] = bebuf[0]; t[2] = bebuf[1]; t[1] = bebuf[2]; t[0] = bebuf[3]; |
| 1328 | | #else |
| 1329 | | t[0] = bebuf[0]; t[1] = bebuf[1]; t[2] = bebuf[2]; t[3] = bebuf[3]; |
| 1330 | | #endif |
| 1331 | | m_L[0].stat.lrp = 0; |
| 1332 | | } |
| 1333 | | } |
| 1334 | | |
| 1335 | | ab_op:; |
| 1336 | | } |
| 1337 | | |
| 1338 | | |
| 1339 | | /* Execute "pst.d fdest,#const(isrc2)" or "fst.d fdest,#const(isrc2)++" |
| 1340 | | instruction. */ |
| 1341 | | void i860_cpu_device::insn_pstd (UINT32 insn) |
| 1342 | | { |
| 1343 | | INT32 immsrc1 = sign_ext (get_imm16 (insn), 16); |
| 1344 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1345 | | UINT32 fdest = get_fdest (insn); |
| 1346 | | UINT32 eff = 0; |
| 1347 | | int auto_inc = (insn & 1); |
| 1348 | | UINT8 *bebuf = 0; |
| 1349 | | int pm = GET_PSR_PM (); |
| 1350 | | int i; |
| 1351 | | UINT32 wmask; |
| 1352 | | int orig_pm = pm; |
| 1353 | | |
| 1354 | | /* Get the pixel size, where: |
| 1355 | | PS: 0 = 8 bits, 1 = 16 bits, 2 = 32-bits. */ |
| 1356 | | int ps = GET_PSR_PS (); |
| 1357 | | |
| 1358 | | #ifdef TRACE_UNDEFINED_I860 |
| 1359 | | if (!(ps == 0 || ps == 1 || ps == 2)) |
| 1360 | | fprintf (stderr, "insn_pstd: Undefined i860XR behavior, invalid value %d for pixel size.\n", ps); |
| 1361 | | #endif |
| 1362 | | |
| 1363 | | #ifdef TRACE_UNDEFINED_I860 |
| 1364 | | /* Bits 2 and 1 determine the operand size, which must always be |
| 1365 | | zero (indicating a 64-bit operand). */ |
| 1366 | | if (insn & 0x6) |
| 1367 | | { |
| 1368 | | /* Undefined i860XR behavior. */ |
| 1369 | | fprintf (stderr, "WARNING: insn_pstd (pc=0x%08x): bad operand size specifier\n", m_pc); |
| 1370 | | } |
| 1371 | | #endif |
| 1372 | | |
| 1373 | | /* FIXME: Check for undefined behavior, non-even register operands. */ |
| 1374 | | |
| 1375 | | /* Get effective address. Chop off lower bits of displacement. */ |
| 1376 | | immsrc1 &= ~(8 - 1); |
| 1377 | | eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2))); |
| 1378 | | |
| 1379 | | #ifdef TRACE_UNALIGNED_MEM |
| 1380 | | if (eff & (8 - 1)) |
| 1381 | | { |
| 1382 | | fprintf (stderr, "0x%08x: Unaligned access detected (0x%08x).\n", |
| 1383 | | m_pc, eff); |
| 1384 | | SET_PSR_DAT (1); |
| 1385 | | m_pending_trap = 1; |
| 1386 | | return; |
| 1387 | | } |
| 1388 | | #endif |
| 1389 | | |
| 1390 | | /* Do (post) auto-increment. */ |
| 1391 | | if (auto_inc) |
| 1392 | | set_iregval (isrc2, eff); |
| 1393 | | |
| 1394 | | /* Update the the pixel mask depending on the pixel size. Shift PM |
| 1395 | | right by 8/2^ps bits. */ |
| 1396 | | if (ps == 0) |
| 1397 | | pm = (pm >> 8) & 0x00; |
| 1398 | | else if (ps == 1) |
| 1399 | | pm = (pm >> 4) & 0x0f; |
| 1400 | | else if (ps == 2) |
| 1401 | | pm = (pm >> 2) & 0x3f; |
| 1402 | | SET_PSR_PM (pm); |
| 1403 | | |
| 1404 | | /* Write data (value of freg fdest) to memory at eff-- but only those |
| 1405 | | bytes that are enabled by the bits in PSR.PM. Bit 0 of PM selects |
| 1406 | | the pixel at the lowest address. */ |
| 1407 | | wmask = 0; |
| 1408 | | for (i = 0; i < 8; ) |
| 1409 | | { |
| 1410 | | if (ps == 0) |
| 1411 | | { |
| 1412 | | if (orig_pm & 0x80) |
| 1413 | | wmask |= 1 << (7-i); |
| 1414 | | i += 1; |
| 1415 | | } |
| 1416 | | else if (ps == 1) |
| 1417 | | { |
| 1418 | | if (orig_pm & 0x08) |
| 1419 | | wmask |= 0x3 << (6-i); |
| 1420 | | i += 2; |
| 1421 | | } |
| 1422 | | else if (ps == 2) |
| 1423 | | { |
| 1424 | | if (orig_pm & 0x02) |
| 1425 | | wmask |= 0xf << (4-i); |
| 1426 | | i += 4; |
| 1427 | | } |
| 1428 | | else |
| 1429 | | { |
| 1430 | | wmask = 0xff; |
| 1431 | | break; |
| 1432 | | } |
| 1433 | | orig_pm <<= 1; |
| 1434 | | } |
| 1435 | | bebuf = (UINT8 *)(&m_frg[4 * (31 - (fdest + 1))]); |
| 1436 | | fp_writemem_emu (eff, 8, bebuf, wmask); |
| 1437 | | } |
| 1438 | | |
| 1439 | | |
| 1440 | | /* Execute "ixfr isrc1ni,fdest" instruction. */ |
| 1441 | | void i860_cpu_device::insn_ixfr (UINT32 insn) |
| 1442 | | { |
| 1443 | | UINT32 isrc1 = get_isrc1 (insn); |
| 1444 | | UINT32 fdest = get_fdest (insn); |
| 1445 | | UINT32 iv = 0; |
| 1446 | | |
| 1447 | | /* This is a bit-pattern transfer, not a conversion. */ |
| 1448 | | iv = get_iregval (isrc1); |
| 1449 | | set_fregval_s (fdest, *(float *)&iv); |
| 1450 | | } |
| 1451 | | |
| 1452 | | |
| 1453 | | /* Execute "addu isrc1,isrc2,idest". */ |
| 1454 | | void i860_cpu_device::insn_addu (UINT32 insn) |
| 1455 | | { |
| 1456 | | UINT32 src1val; |
| 1457 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1458 | | UINT32 idest = get_idest (insn); |
| 1459 | | UINT32 tmp_dest_val = 0; |
| 1460 | | UINT64 tmp = 0; |
| 1461 | | |
| 1462 | | src1val = get_iregval (get_isrc1 (insn)); |
| 1463 | | |
| 1464 | | /* We don't update the actual idest register now because below we |
| 1465 | | need to test the original src1 and src2 if either happens to |
| 1466 | | be the destination register. */ |
| 1467 | | tmp_dest_val = src1val + get_iregval (isrc2); |
| 1468 | | |
| 1469 | | /* Set OF and CC flags. |
| 1470 | | For unsigned: |
| 1471 | | OF = bit 31 carry |
| 1472 | | CC = bit 31 carry. |
| 1473 | | */ |
| 1474 | | tmp = (UINT64)src1val + (UINT64)(get_iregval (isrc2)); |
| 1475 | | if ((tmp >> 32) & 1) |
| 1476 | | { |
| 1477 | | SET_PSR_CC (1); |
| 1478 | | SET_EPSR_OF (1); |
| 1479 | | } |
| 1480 | | else |
| 1481 | | { |
| 1482 | | SET_PSR_CC (0); |
| 1483 | | SET_EPSR_OF (0); |
| 1484 | | } |
| 1485 | | |
| 1486 | | /* Now update the destination register. */ |
| 1487 | | set_iregval (idest, tmp_dest_val); |
| 1488 | | } |
| 1489 | | |
| 1490 | | |
| 1491 | | /* Execute "addu #const,isrc2,idest". */ |
| 1492 | | void i860_cpu_device::insn_addu_imm (UINT32 insn) |
| 1493 | | { |
| 1494 | | UINT32 src1val; |
| 1495 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1496 | | UINT32 idest = get_idest (insn); |
| 1497 | | UINT32 tmp_dest_val = 0; |
| 1498 | | UINT64 tmp = 0; |
| 1499 | | |
| 1500 | | src1val = sign_ext (get_imm16 (insn), 16); |
| 1501 | | |
| 1502 | | /* We don't update the actual idest register now because below we |
| 1503 | | need to test the original src1 and src2 if either happens to |
| 1504 | | be the destination register. */ |
| 1505 | | tmp_dest_val = src1val + get_iregval (isrc2); |
| 1506 | | |
| 1507 | | /* Set OF and CC flags. |
| 1508 | | For unsigned: |
| 1509 | | OF = bit 31 carry |
| 1510 | | CC = bit 31 carry. |
| 1511 | | */ |
| 1512 | | tmp = (UINT64)src1val + (UINT64)(get_iregval (isrc2)); |
| 1513 | | if ((tmp >> 32) & 1) |
| 1514 | | { |
| 1515 | | SET_PSR_CC (1); |
| 1516 | | SET_EPSR_OF (1); |
| 1517 | | } |
| 1518 | | else |
| 1519 | | { |
| 1520 | | SET_PSR_CC (0); |
| 1521 | | SET_EPSR_OF (0); |
| 1522 | | } |
| 1523 | | |
| 1524 | | /* Now update the destination register. */ |
| 1525 | | set_iregval (idest, tmp_dest_val); |
| 1526 | | } |
| 1527 | | |
| 1528 | | |
| 1529 | | /* Execute "adds isrc1,isrc2,idest". */ |
| 1530 | | void i860_cpu_device::insn_adds (UINT32 insn) |
| 1531 | | { |
| 1532 | | UINT32 src1val; |
| 1533 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1534 | | UINT32 idest = get_idest (insn); |
| 1535 | | UINT32 tmp_dest_val = 0; |
| 1536 | | int sa, sb, sres; |
| 1537 | | |
| 1538 | | src1val = get_iregval (get_isrc1 (insn)); |
| 1539 | | |
| 1540 | | /* We don't update the actual idest register now because below we |
| 1541 | | need to test the original src1 and src2 if either happens to |
| 1542 | | be the destination register. */ |
| 1543 | | tmp_dest_val = src1val + get_iregval (isrc2); |
| 1544 | | |
| 1545 | | /* Set OF and CC flags. |
| 1546 | | For signed: |
| 1547 | | OF = standard signed overflow. |
| 1548 | | CC set if isrc2 < -isrc1 |
| 1549 | | CC clear if isrc2 >= -isrc1 |
| 1550 | | */ |
| 1551 | | sa = src1val & 0x80000000; |
| 1552 | | sb = get_iregval (isrc2) & 0x80000000; |
| 1553 | | sres = tmp_dest_val & 0x80000000; |
| 1554 | | if (sa != sb && sa != sres) |
| 1555 | | SET_EPSR_OF (1); |
| 1556 | | else |
| 1557 | | SET_EPSR_OF (0); |
| 1558 | | |
| 1559 | | if ((INT32)get_iregval (isrc2) < -(INT32)(src1val)) |
| 1560 | | SET_PSR_CC (1); |
| 1561 | | else |
| 1562 | | SET_PSR_CC (0); |
| 1563 | | |
| 1564 | | /* Now update the destination register. */ |
| 1565 | | set_iregval (idest, tmp_dest_val); |
| 1566 | | } |
| 1567 | | |
| 1568 | | |
| 1569 | | /* Execute "adds #const,isrc2,idest". */ |
| 1570 | | void i860_cpu_device::insn_adds_imm (UINT32 insn) |
| 1571 | | { |
| 1572 | | UINT32 src1val; |
| 1573 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1574 | | UINT32 idest = get_idest (insn); |
| 1575 | | UINT32 tmp_dest_val = 0; |
| 1576 | | int sa, sb, sres; |
| 1577 | | |
| 1578 | | src1val = sign_ext (get_imm16 (insn), 16); |
| 1579 | | |
| 1580 | | /* We don't update the actual idest register now because below we |
| 1581 | | need to test the original src1 and src2 if either happens to |
| 1582 | | be the destination register. */ |
| 1583 | | tmp_dest_val = src1val + get_iregval (isrc2); |
| 1584 | | |
| 1585 | | /* Set OF and CC flags. |
| 1586 | | For signed: |
| 1587 | | OF = standard signed overflow. |
| 1588 | | CC set if isrc2 < -isrc1 |
| 1589 | | CC clear if isrc2 >= -isrc1 |
| 1590 | | */ |
| 1591 | | sa = src1val & 0x80000000; |
| 1592 | | sb = get_iregval (isrc2) & 0x80000000; |
| 1593 | | sres = tmp_dest_val & 0x80000000; |
| 1594 | | if (sa != sb && sa != sres) |
| 1595 | | SET_EPSR_OF (1); |
| 1596 | | else |
| 1597 | | SET_EPSR_OF (0); |
| 1598 | | |
| 1599 | | if ((INT32)get_iregval (isrc2) < -(INT32)(src1val)) |
| 1600 | | SET_PSR_CC (1); |
| 1601 | | else |
| 1602 | | SET_PSR_CC (0); |
| 1603 | | |
| 1604 | | /* Now update the destination register. */ |
| 1605 | | set_iregval (idest, tmp_dest_val); |
| 1606 | | } |
| 1607 | | |
| 1608 | | |
| 1609 | | /* Execute "subu isrc1,isrc2,idest". */ |
| 1610 | | void i860_cpu_device::insn_subu (UINT32 insn) |
| 1611 | | { |
| 1612 | | UINT32 src1val; |
| 1613 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1614 | | UINT32 idest = get_idest (insn); |
| 1615 | | UINT32 tmp_dest_val = 0; |
| 1616 | | |
| 1617 | | src1val = get_iregval (get_isrc1 (insn)); |
| 1618 | | |
| 1619 | | /* We don't update the actual idest register now because below we |
| 1620 | | need to test the original src1 and src2 if either happens to |
| 1621 | | be the destination register. */ |
| 1622 | | tmp_dest_val = src1val - get_iregval (isrc2); |
| 1623 | | |
| 1624 | | /* Set OF and CC flags. |
| 1625 | | For unsigned: |
| 1626 | | OF = NOT(bit 31 carry) |
| 1627 | | CC = bit 31 carry. |
| 1628 | | (i.e. CC set if isrc2 <= isrc1 |
| 1629 | | CC clear if isrc2 > isrc1 |
| 1630 | | */ |
| 1631 | | if ((UINT32)get_iregval (isrc2) <= (UINT32)src1val) |
| 1632 | | { |
| 1633 | | SET_PSR_CC (1); |
| 1634 | | SET_EPSR_OF (0); |
| 1635 | | } |
| 1636 | | else |
| 1637 | | { |
| 1638 | | SET_PSR_CC (0); |
| 1639 | | SET_EPSR_OF (1); |
| 1640 | | } |
| 1641 | | |
| 1642 | | /* Now update the destination register. */ |
| 1643 | | set_iregval (idest, tmp_dest_val); |
| 1644 | | } |
| 1645 | | |
| 1646 | | |
| 1647 | | /* Execute "subu #const,isrc2,idest". */ |
| 1648 | | void i860_cpu_device::insn_subu_imm (UINT32 insn) |
| 1649 | | { |
| 1650 | | UINT32 src1val; |
| 1651 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1652 | | UINT32 idest = get_idest (insn); |
| 1653 | | UINT32 tmp_dest_val = 0; |
| 1654 | | |
| 1655 | | src1val = sign_ext (get_imm16 (insn), 16); |
| 1656 | | |
| 1657 | | /* We don't update the actual idest register now because below we |
| 1658 | | need to test the original src1 and src2 if either happens to |
| 1659 | | be the destination register. */ |
| 1660 | | tmp_dest_val = src1val - get_iregval (isrc2); |
| 1661 | | |
| 1662 | | /* Set OF and CC flags. |
| 1663 | | For unsigned: |
| 1664 | | OF = NOT(bit 31 carry) |
| 1665 | | CC = bit 31 carry. |
| 1666 | | (i.e. CC set if isrc2 <= isrc1 |
| 1667 | | CC clear if isrc2 > isrc1 |
| 1668 | | */ |
| 1669 | | if ((UINT32)get_iregval (isrc2) <= (UINT32)src1val) |
| 1670 | | { |
| 1671 | | SET_PSR_CC (1); |
| 1672 | | SET_EPSR_OF (0); |
| 1673 | | } |
| 1674 | | else |
| 1675 | | { |
| 1676 | | SET_PSR_CC (0); |
| 1677 | | SET_EPSR_OF (1); |
| 1678 | | } |
| 1679 | | |
| 1680 | | /* Now update the destination register. */ |
| 1681 | | set_iregval (idest, tmp_dest_val); |
| 1682 | | } |
| 1683 | | |
| 1684 | | |
| 1685 | | /* Execute "subs isrc1,isrc2,idest". */ |
| 1686 | | void i860_cpu_device::insn_subs (UINT32 insn) |
| 1687 | | { |
| 1688 | | UINT32 src1val; |
| 1689 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1690 | | UINT32 idest = get_idest (insn); |
| 1691 | | UINT32 tmp_dest_val = 0; |
| 1692 | | int sa, sb, sres; |
| 1693 | | |
| 1694 | | src1val = get_iregval (get_isrc1 (insn)); |
| 1695 | | |
| 1696 | | /* We don't update the actual idest register now because below we |
| 1697 | | need to test the original src1 and src2 if either happens to |
| 1698 | | be the destination register. */ |
| 1699 | | tmp_dest_val = src1val - get_iregval (isrc2); |
| 1700 | | |
| 1701 | | /* Set OF and CC flags. |
| 1702 | | For signed: |
| 1703 | | OF = standard signed overflow. |
| 1704 | | CC set if isrc2 > isrc1 |
| 1705 | | CC clear if isrc2 <= isrc1 |
| 1706 | | */ |
| 1707 | | sa = src1val & 0x80000000; |
| 1708 | | sb = get_iregval (isrc2) & 0x80000000; |
| 1709 | | sres = tmp_dest_val & 0x80000000; |
| 1710 | | if (sa != sb && sa != sres) |
| 1711 | | SET_EPSR_OF (1); |
| 1712 | | else |
| 1713 | | SET_EPSR_OF (0); |
| 1714 | | |
| 1715 | | if ((INT32)get_iregval (isrc2) > (INT32)(src1val)) |
| 1716 | | SET_PSR_CC (1); |
| 1717 | | else |
| 1718 | | SET_PSR_CC (0); |
| 1719 | | |
| 1720 | | /* Now update the destination register. */ |
| 1721 | | set_iregval (idest, tmp_dest_val); |
| 1722 | | } |
| 1723 | | |
| 1724 | | |
| 1725 | | /* Execute "subs #const,isrc2,idest". */ |
| 1726 | | void i860_cpu_device::insn_subs_imm (UINT32 insn) |
| 1727 | | { |
| 1728 | | UINT32 src1val; |
| 1729 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1730 | | UINT32 idest = get_idest (insn); |
| 1731 | | UINT32 tmp_dest_val = 0; |
| 1732 | | int sa, sb, sres; |
| 1733 | | |
| 1734 | | src1val = sign_ext (get_imm16 (insn), 16); |
| 1735 | | |
| 1736 | | /* We don't update the actual idest register now because below we |
| 1737 | | need to test the original src1 and src2 if either happens to |
| 1738 | | be the destination register. */ |
| 1739 | | tmp_dest_val = src1val - get_iregval (isrc2); |
| 1740 | | |
| 1741 | | /* Set OF and CC flags. |
| 1742 | | For signed: |
| 1743 | | OF = standard signed overflow. |
| 1744 | | CC set if isrc2 > isrc1 |
| 1745 | | CC clear if isrc2 <= isrc1 |
| 1746 | | */ |
| 1747 | | sa = src1val & 0x80000000; |
| 1748 | | sb = get_iregval (isrc2) & 0x80000000; |
| 1749 | | sres = tmp_dest_val & 0x80000000; |
| 1750 | | if (sa != sb && sa != sres) |
| 1751 | | SET_EPSR_OF (1); |
| 1752 | | else |
| 1753 | | SET_EPSR_OF (0); |
| 1754 | | |
| 1755 | | if ((INT32)get_iregval (isrc2) > (INT32)(src1val)) |
| 1756 | | SET_PSR_CC (1); |
| 1757 | | else |
| 1758 | | SET_PSR_CC (0); |
| 1759 | | |
| 1760 | | /* Now update the destination register. */ |
| 1761 | | set_iregval (idest, tmp_dest_val); |
| 1762 | | } |
| 1763 | | |
| 1764 | | |
| 1765 | | /* Execute "shl isrc1,isrc2,idest". */ |
| 1766 | | void i860_cpu_device::insn_shl (UINT32 insn) |
| 1767 | | { |
| 1768 | | UINT32 src1val = 0; |
| 1769 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1770 | | UINT32 idest = get_idest (insn); |
| 1771 | | |
| 1772 | | src1val = get_iregval (get_isrc1 (insn)); |
| 1773 | | set_iregval (idest, get_iregval (isrc2) << src1val); |
| 1774 | | } |
| 1775 | | |
| 1776 | | |
| 1777 | | /* Execute "shl #const,isrc2,idest". */ |
| 1778 | | void i860_cpu_device::insn_shl_imm (UINT32 insn) |
| 1779 | | { |
| 1780 | | UINT32 src1val = 0; |
| 1781 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1782 | | UINT32 idest = get_idest (insn); |
| 1783 | | |
| 1784 | | src1val = sign_ext (get_imm16 (insn), 16); |
| 1785 | | set_iregval (idest, get_iregval (isrc2) << src1val); |
| 1786 | | } |
| 1787 | | |
| 1788 | | |
| 1789 | | /* Execute "shr isrc1,isrc2,idest". */ |
| 1790 | | void i860_cpu_device::insn_shr (UINT32 insn) |
| 1791 | | { |
| 1792 | | UINT32 src1val = 0; |
| 1793 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1794 | | UINT32 idest = get_idest (insn); |
| 1795 | | |
| 1796 | | src1val = get_iregval (get_isrc1 (insn)); |
| 1797 | | |
| 1798 | | /* The iregs array is UINT32, so this is a logical shift. */ |
| 1799 | | set_iregval (idest, get_iregval (isrc2) >> src1val); |
| 1800 | | |
| 1801 | | /* shr also sets the SC in psr (shift count). */ |
| 1802 | | SET_PSR_SC (src1val); |
| 1803 | | } |
| 1804 | | |
| 1805 | | |
| 1806 | | /* Execute "shr #const,isrc2,idest". */ |
| 1807 | | void i860_cpu_device::insn_shr_imm (UINT32 insn) |
| 1808 | | { |
| 1809 | | UINT32 src1val = 0; |
| 1810 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1811 | | UINT32 idest = get_idest (insn); |
| 1812 | | |
| 1813 | | src1val = sign_ext (get_imm16 (insn), 16); |
| 1814 | | |
| 1815 | | /* The iregs array is UINT32, so this is a logical shift. */ |
| 1816 | | set_iregval (idest, get_iregval (isrc2) >> src1val); |
| 1817 | | |
| 1818 | | /* shr also sets the SC in psr (shift count). */ |
| 1819 | | SET_PSR_SC (src1val); |
| 1820 | | } |
| 1821 | | |
| 1822 | | |
| 1823 | | /* Execute "shra isrc1,isrc2,idest". */ |
| 1824 | | void i860_cpu_device::insn_shra (UINT32 insn) |
| 1825 | | { |
| 1826 | | UINT32 src1val = 0; |
| 1827 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1828 | | UINT32 idest = get_idest (insn); |
| 1829 | | |
| 1830 | | src1val = get_iregval (get_isrc1 (insn)); |
| 1831 | | |
| 1832 | | /* The iregs array is UINT32, so cast isrc2 to get arithmetic shift. */ |
| 1833 | | set_iregval (idest, (INT32)get_iregval (isrc2) >> src1val); |
| 1834 | | } |
| 1835 | | |
| 1836 | | |
| 1837 | | /* Execute "shra #const,isrc2,idest". */ |
| 1838 | | void i860_cpu_device::insn_shra_imm (UINT32 insn) |
| 1839 | | { |
| 1840 | | UINT32 src1val = 0; |
| 1841 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1842 | | UINT32 idest = get_idest (insn); |
| 1843 | | |
| 1844 | | src1val = sign_ext (get_imm16 (insn), 16); |
| 1845 | | |
| 1846 | | /* The iregs array is UINT32, so cast isrc2 to get arithmetic shift. */ |
| 1847 | | set_iregval (idest, (INT32)get_iregval (isrc2) >> src1val); |
| 1848 | | } |
| 1849 | | |
| 1850 | | |
| 1851 | | /* Execute "shrd isrc1ni,isrc2,idest" instruction. */ |
| 1852 | | void i860_cpu_device::insn_shrd (UINT32 insn) |
| 1853 | | { |
| 1854 | | UINT32 isrc1 = get_isrc1 (insn); |
| 1855 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1856 | | UINT32 idest = get_idest (insn); |
| 1857 | | UINT32 sc = GET_PSR_SC (); |
| 1858 | | UINT32 tmp; |
| 1859 | | |
| 1860 | | /* Do the operation: |
| 1861 | | idest = low_32(isrc1ni:isrc2 >> sc). */ |
| 1862 | | if (sc == 0) |
| 1863 | | tmp = get_iregval (isrc2); |
| 1864 | | else |
| 1865 | | { |
| 1866 | | tmp = get_iregval (isrc1) << (32 - sc); |
| 1867 | | tmp |= (get_iregval (isrc2) >> sc); |
| 1868 | | } |
| 1869 | | set_iregval (idest, tmp); |
| 1870 | | } |
| 1871 | | |
| 1872 | | |
| 1873 | | /* Execute "and isrc1,isrc2,idest". */ |
| 1874 | | void i860_cpu_device::insn_and (UINT32 insn) |
| 1875 | | { |
| 1876 | | UINT32 isrc1 = get_isrc1 (insn); |
| 1877 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1878 | | UINT32 idest = get_idest (insn); |
| 1879 | | UINT32 res = 0; |
| 1880 | | |
| 1881 | | /* Do the operation. */ |
| 1882 | | res = get_iregval (isrc1) & get_iregval (isrc2); |
| 1883 | | |
| 1884 | | /* Set flags. */ |
| 1885 | | if (res == 0) |
| 1886 | | SET_PSR_CC (1); |
| 1887 | | else |
| 1888 | | SET_PSR_CC (0); |
| 1889 | | |
| 1890 | | set_iregval (idest, res); |
| 1891 | | } |
| 1892 | | |
| 1893 | | |
| 1894 | | /* Execute "and #const,isrc2,idest". */ |
| 1895 | | void i860_cpu_device::insn_and_imm (UINT32 insn) |
| 1896 | | { |
| 1897 | | UINT32 src1val = 0; |
| 1898 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1899 | | UINT32 idest = get_idest (insn); |
| 1900 | | UINT32 res = 0; |
| 1901 | | |
| 1902 | | /* Do the operation. */ |
| 1903 | | src1val = get_imm16 (insn); |
| 1904 | | res = src1val & get_iregval (isrc2); |
| 1905 | | |
| 1906 | | /* Set flags. */ |
| 1907 | | if (res == 0) |
| 1908 | | SET_PSR_CC (1); |
| 1909 | | else |
| 1910 | | SET_PSR_CC (0); |
| 1911 | | |
| 1912 | | set_iregval (idest, res); |
| 1913 | | } |
| 1914 | | |
| 1915 | | |
| 1916 | | /* Execute "andh #const,isrc2,idest". */ |
| 1917 | | void i860_cpu_device::insn_andh_imm (UINT32 insn) |
| 1918 | | { |
| 1919 | | UINT32 src1val = 0; |
| 1920 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1921 | | UINT32 idest = get_idest (insn); |
| 1922 | | UINT32 res = 0; |
| 1923 | | |
| 1924 | | /* Do the operation. */ |
| 1925 | | src1val = get_imm16 (insn); |
| 1926 | | res = (src1val << 16) & get_iregval (isrc2); |
| 1927 | | |
| 1928 | | /* Set flags. */ |
| 1929 | | if (res == 0) |
| 1930 | | SET_PSR_CC (1); |
| 1931 | | else |
| 1932 | | SET_PSR_CC (0); |
| 1933 | | |
| 1934 | | set_iregval (idest, res); |
| 1935 | | } |
| 1936 | | |
| 1937 | | |
| 1938 | | /* Execute "andnot isrc1,isrc2,idest". */ |
| 1939 | | void i860_cpu_device::insn_andnot (UINT32 insn) |
| 1940 | | { |
| 1941 | | UINT32 isrc1 = get_isrc1 (insn); |
| 1942 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1943 | | UINT32 idest = get_idest (insn); |
| 1944 | | UINT32 res = 0; |
| 1945 | | |
| 1946 | | /* Do the operation. */ |
| 1947 | | res = (~get_iregval (isrc1)) & get_iregval (isrc2); |
| 1948 | | |
| 1949 | | /* Set flags. */ |
| 1950 | | if (res == 0) |
| 1951 | | SET_PSR_CC (1); |
| 1952 | | else |
| 1953 | | SET_PSR_CC (0); |
| 1954 | | |
| 1955 | | set_iregval (idest, res); |
| 1956 | | } |
| 1957 | | |
| 1958 | | |
| 1959 | | /* Execute "andnot #const,isrc2,idest". */ |
| 1960 | | void i860_cpu_device::insn_andnot_imm (UINT32 insn) |
| 1961 | | { |
| 1962 | | UINT32 src1val = 0; |
| 1963 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1964 | | UINT32 idest = get_idest (insn); |
| 1965 | | UINT32 res = 0; |
| 1966 | | |
| 1967 | | /* Do the operation. */ |
| 1968 | | src1val = get_imm16 (insn); |
| 1969 | | res = (~src1val) & get_iregval (isrc2); |
| 1970 | | |
| 1971 | | /* Set flags. */ |
| 1972 | | if (res == 0) |
| 1973 | | SET_PSR_CC (1); |
| 1974 | | else |
| 1975 | | SET_PSR_CC (0); |
| 1976 | | |
| 1977 | | set_iregval (idest, res); |
| 1978 | | } |
| 1979 | | |
| 1980 | | |
| 1981 | | /* Execute "andnoth #const,isrc2,idest". */ |
| 1982 | | void i860_cpu_device::insn_andnoth_imm (UINT32 insn) |
| 1983 | | { |
| 1984 | | UINT32 src1val = 0; |
| 1985 | | UINT32 isrc2 = get_isrc2 (insn); |
| 1986 | | UINT32 idest = get_idest (insn); |
| 1987 | | UINT32 res = 0; |
| 1988 | | |
| 1989 | | /* Do the operation. */ |
| 1990 | | src1val = get_imm16 (insn); |
| 1991 | | res = (~(src1val << 16)) & get_iregval (isrc2); |
| 1992 | | |
| 1993 | | /* Set flags. */ |
| 1994 | | if (res == 0) |
| 1995 | | SET_PSR_CC (1); |
| 1996 | | else |
| 1997 | | SET_PSR_CC (0); |
| 1998 | | |
| 1999 | | set_iregval (idest, res); |
| 2000 | | } |
| 2001 | | |
| 2002 | | |
| 2003 | | /* Execute "or isrc1,isrc2,idest". */ |
| 2004 | | void i860_cpu_device::insn_or (UINT32 insn) |
| 2005 | | { |
| 2006 | | UINT32 isrc1 = get_isrc1 (insn); |
| 2007 | | UINT32 isrc2 = get_isrc2 (insn); |
| 2008 | | UINT32 idest = get_idest (insn); |
| 2009 | | UINT32 res = 0; |
| 2010 | | |
| 2011 | | /* Do the operation. */ |
| 2012 | | res = get_iregval (isrc1) | get_iregval (isrc2); |
| 2013 | | |
| 2014 | | /* Set flags. */ |
| 2015 | | if (res == 0) |
| 2016 | | SET_PSR_CC (1); |
| 2017 | | else |
| 2018 | | SET_PSR_CC (0); |
| 2019 | | |
| 2020 | | set_iregval (idest, res); |
| 2021 | | } |
| 2022 | | |
| 2023 | | |
| 2024 | | /* Execute "or #const,isrc2,idest". */ |
| 2025 | | void i860_cpu_device::insn_or_imm (UINT32 insn) |
| 2026 | | { |
| 2027 | | UINT32 src1val = 0; |
| 2028 | | UINT32 isrc2 = get_isrc2 (insn); |
| 2029 | | UINT32 idest = get_idest (insn); |
| 2030 | | UINT32 res = 0; |
| 2031 | | |
| 2032 | | /* Do the operation. */ |
| 2033 | | src1val = get_imm16 (insn); |
| 2034 | | res = src1val | get_iregval (isrc2); |
| 2035 | | |
| 2036 | | /* Set flags. */ |
| 2037 | | if (res == 0) |
| 2038 | | SET_PSR_CC (1); |
| 2039 | | else |
| 2040 | | SET_PSR_CC (0); |
| 2041 | | |
| 2042 | | set_iregval (idest, res); |
| 2043 | | } |
| 2044 | | |
| 2045 | | |
| 2046 | | /* Execute "orh #const,isrc2,idest". */ |
| 2047 | | void i860_cpu_device::insn_orh_imm (UINT32 insn) |
| 2048 | | { |
| 2049 | | UINT32 src1val = 0; |
| 2050 | | UINT32 isrc2 = get_isrc2 (insn); |
| 2051 | | UINT32 idest = get_idest (insn); |
| 2052 | | UINT32 res = 0; |
| 2053 | | |
| 2054 | | /* Do the operation. */ |
| 2055 | | src1val = get_imm16 (insn); |
| 2056 | | res = (src1val << 16) | get_iregval (isrc2); |
| 2057 | | |
| 2058 | | /* Set flags. */ |
| 2059 | | if (res == 0) |
| 2060 | | SET_PSR_CC (1); |
| 2061 | | else |
| 2062 | | SET_PSR_CC (0); |
| 2063 | | |
| 2064 | | set_iregval (idest, res); |
| 2065 | | } |
| 2066 | | |
| 2067 | | |
| 2068 | | /* Execute "xor isrc1,isrc2,idest". */ |
| 2069 | | void i860_cpu_device::insn_xor (UINT32 insn) |
| 2070 | | { |
| 2071 | | UINT32 isrc1 = get_isrc1 (insn); |
| 2072 | | UINT32 isrc2 = get_isrc2 (insn); |
| 2073 | | UINT32 idest = get_idest (insn); |
| 2074 | | UINT32 res = 0; |
| 2075 | | |
| 2076 | | /* Do the operation. */ |
| 2077 | | res = get_iregval (isrc1) ^ get_iregval (isrc2); |
| 2078 | | |
| 2079 | | /* Set flags. */ |
| 2080 | | if (res == 0) |
| 2081 | | SET_PSR_CC (1); |
| 2082 | | else |
| 2083 | | SET_PSR_CC (0); |
| 2084 | | |
| 2085 | | set_iregval (idest, res); |
| 2086 | | } |
| 2087 | | |
| 2088 | | |
| 2089 | | /* Execute "xor #const,isrc2,idest". */ |
| 2090 | | void i860_cpu_device::insn_xor_imm (UINT32 insn) |
| 2091 | | { |
| 2092 | | UINT32 src1val = 0; |
| 2093 | | UINT32 isrc2 = get_isrc2 (insn); |
| 2094 | | UINT32 idest = get_idest (insn); |
| 2095 | | UINT32 res = 0; |
| 2096 | | |
| 2097 | | /* Do the operation. */ |
| 2098 | | src1val = get_imm16 (insn); |
| 2099 | | res = src1val ^ get_iregval (isrc2); |
| 2100 | | |
| 2101 | | /* Set flags. */ |
| 2102 | | if (res == 0) |
| 2103 | | SET_PSR_CC (1); |
| 2104 | | else |
| 2105 | | SET_PSR_CC (0); |
| 2106 | | |
| 2107 | | set_iregval (idest, res); |
| 2108 | | } |
| 2109 | | |
| 2110 | | |
| 2111 | | /* Execute "xorh #const,isrc2,idest". */ |
| 2112 | | void i860_cpu_device::insn_xorh_imm (UINT32 insn) |
| 2113 | | { |
| 2114 | | UINT32 src1val = 0; |
| 2115 | | UINT32 isrc2 = get_isrc2 (insn); |
| 2116 | | UINT32 idest = get_idest (insn); |
| 2117 | | UINT32 res = 0; |
| 2118 | | |
| 2119 | | /* Do the operation. */ |
| 2120 | | src1val = get_imm16 (insn); |
| 2121 | | res = (src1val << 16) ^ get_iregval (isrc2); |
| 2122 | | |
| 2123 | | /* Set flags. */ |
| 2124 | | if (res == 0) |
| 2125 | | SET_PSR_CC (1); |
| 2126 | | else |
| 2127 | | SET_PSR_CC (0); |
| 2128 | | |
| 2129 | | set_iregval (idest, res); |
| 2130 | | } |
| 2131 | | |
| 2132 | | |
| 2133 | | /* Execute "trap isrc1ni,isrc2,idest" instruction. */ |
| 2134 | | void i860_cpu_device::insn_trap (UINT32 insn) |
| 2135 | | { |
| 2136 | | SET_PSR_IT (1); |
| 2137 | | m_pending_trap = 1; |
| 2138 | | } |
| 2139 | | |
| 2140 | | |
| 2141 | | /* Execute "intovr" instruction. */ |
| 2142 | | void i860_cpu_device::insn_intovr (UINT32 insn) |
| 2143 | | { |
| 2144 | | if (GET_EPSR_OF ()) |
| 2145 | | { |
| 2146 | | SET_PSR_IT (1); |
| 2147 | | m_pending_trap = 1; |
| 2148 | | } |
| 2149 | | } |
| 2150 | | |
| 2151 | | |
| 2152 | | /* Execute "bte isrc1,isrc2,sbroff". */ |
| 2153 | | void i860_cpu_device::insn_bte (UINT32 insn) |
| 2154 | | { |
| 2155 | | UINT32 src1val = 0; |
| 2156 | | UINT32 isrc2 = get_isrc2 (insn); |
| 2157 | | UINT32 target_addr = 0; |
| 2158 | | INT32 sbroff = 0; |
| 2159 | | int res = 0; |
| 2160 | | |
| 2161 | | src1val = get_iregval (get_isrc1 (insn)); |
| 2162 | | |
| 2163 | | /* Compute the target address from the sbroff field. */ |
| 2164 | | sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); |
| 2165 | | target_addr = (INT32)m_pc + 4 + (sbroff << 2); |
| 2166 | | |
| 2167 | | /* Determine comparison result. */ |
| 2168 | | res = (src1val == get_iregval (isrc2)); |
| 2169 | | |
| 2170 | | /* Branch routines always update the PC. */ |
| 2171 | | if (res) |
| 2172 | | m_pc = target_addr; |
| 2173 | | else |
| 2174 | | m_pc += 4; |
| 2175 | | |
| 2176 | | m_pc_updated = 1; |
| 2177 | | } |
| 2178 | | |
| 2179 | | |
| 2180 | | /* Execute "bte #const5,isrc2,sbroff". */ |
| 2181 | | void i860_cpu_device::insn_bte_imm (UINT32 insn) |
| 2182 | | { |
| 2183 | | UINT32 src1val = 0; |
| 2184 | | UINT32 isrc2 = get_isrc2 (insn); |
| 2185 | | UINT32 target_addr = 0; |
| 2186 | | INT32 sbroff = 0; |
| 2187 | | int res = 0; |
| 2188 | | |
| 2189 | | src1val = (insn >> 11) & 0x1f; /* 5-bit field, zero-extended. */ |
| 2190 | | |
| 2191 | | /* Compute the target address from the sbroff field. */ |
| 2192 | | sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); |
| 2193 | | target_addr = (INT32)m_pc + 4 + (sbroff << 2); |
| 2194 | | |
| 2195 | | /* Determine comparison result. */ |
| 2196 | | res = (src1val == get_iregval (isrc2)); |
| 2197 | | |
| 2198 | | /* Branch routines always update the PC. */ |
| 2199 | | if (res) |
| 2200 | | m_pc = target_addr; |
| 2201 | | else |
| 2202 | | m_pc += 4; |
| 2203 | | |
| 2204 | | m_pc_updated = 1; |
| 2205 | | } |
| 2206 | | |
| 2207 | | |
| 2208 | | /* Execute "btne isrc1,isrc2,sbroff". */ |
| 2209 | | void i860_cpu_device::insn_btne (UINT32 insn) |
| 2210 | | { |
| 2211 | | UINT32 src1val = 0; |
| 2212 | | UINT32 isrc2 = get_isrc2 (insn); |
| 2213 | | UINT32 target_addr = 0; |
| 2214 | | INT32 sbroff = 0; |
| 2215 | | int res = 0; |
| 2216 | | |
| 2217 | | src1val = get_iregval (get_isrc1 (insn)); |
| 2218 | | |
| 2219 | | /* Compute the target address from the sbroff field. */ |
| 2220 | | sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); |
| 2221 | | target_addr = (INT32)m_pc + 4 + (sbroff << 2); |
| 2222 | | |
| 2223 | | /* Determine comparison result. */ |
| 2224 | | res = (src1val != get_iregval (isrc2)); |
| 2225 | | |
| 2226 | | /* Branch routines always update the PC. */ |
| 2227 | | if (res) |
| 2228 | | m_pc = target_addr; |
| 2229 | | else |
| 2230 | | m_pc += 4; |
| 2231 | | |
| 2232 | | m_pc_updated = 1; |
| 2233 | | } |
| 2234 | | |
| 2235 | | |
| 2236 | | /* Execute "btne #const5,isrc2,sbroff". */ |
| 2237 | | void i860_cpu_device::insn_btne_imm (UINT32 insn) |
| 2238 | | { |
| 2239 | | UINT32 src1val = 0; |
| 2240 | | UINT32 isrc2 = get_isrc2 (insn); |
| 2241 | | UINT32 target_addr = 0; |
| 2242 | | INT32 sbroff = 0; |
| 2243 | | int res = 0; |
| 2244 | | |
| 2245 | | src1val = (insn >> 11) & 0x1f; /* 5-bit field, zero-extended. */ |
| 2246 | | |
| 2247 | | /* Compute the target address from the sbroff field. */ |
| 2248 | | sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); |
| 2249 | | target_addr = (INT32)m_pc + 4 + (sbroff << 2); |
| 2250 | | |
| 2251 | | /* Determine comparison result. */ |
| 2252 | | res = (src1val != get_iregval (isrc2)); |
| 2253 | | |
| 2254 | | /* Branch routines always update the PC. */ |
| 2255 | | if (res) |
| 2256 | | m_pc = target_addr; |
| 2257 | | else |
| 2258 | | m_pc += 4; |
| 2259 | | |
| 2260 | | m_pc_updated = 1; |
| 2261 | | } |
| 2262 | | |
| 2263 | | |
| 2264 | | /* Execute "bc lbroff" instruction. */ |
| 2265 | | void i860_cpu_device::insn_bc (UINT32 insn) |
| 2266 | | { |
| 2267 | | UINT32 target_addr = 0; |
| 2268 | | INT32 lbroff = 0; |
| 2269 | | int res = 0; |
| 2270 | | |
| 2271 | | /* Compute the target address from the lbroff field. */ |
| 2272 | | lbroff = sign_ext ((insn & 0x03ffffff), 26); |
| 2273 | | target_addr = (INT32)m_pc + 4 + (lbroff << 2); |
| 2274 | | |
| 2275 | | /* Determine comparison result. */ |
| 2276 | | res = (GET_PSR_CC () == 1); |
| 2277 | | |
| 2278 | | /* Branch routines always update the PC. */ |
| 2279 | | if (res) |
| 2280 | | m_pc = target_addr; |
| 2281 | | else |
| 2282 | | m_pc += 4; |
| 2283 | | |
| 2284 | | m_pc_updated = 1; |
| 2285 | | } |
| 2286 | | |
| 2287 | | |
| 2288 | | /* Execute "bnc lbroff" instruction. */ |
| 2289 | | void i860_cpu_device::insn_bnc (UINT32 insn) |
| 2290 | | { |
| 2291 | | UINT32 target_addr = 0; |
| 2292 | | INT32 lbroff = 0; |
| 2293 | | int res = 0; |
| 2294 | | |
| 2295 | | /* Compute the target address from the lbroff field. */ |
| 2296 | | lbroff = sign_ext ((insn & 0x03ffffff), 26); |
| 2297 | | target_addr = (INT32)m_pc + 4 + (lbroff << 2); |
| 2298 | | |
| 2299 | | /* Determine comparison result. */ |
| 2300 | | res = (GET_PSR_CC () == 0); |
| 2301 | | |
| 2302 | | /* Branch routines always update the PC, since pc_updated is set |
| 2303 | | in the decode routine. */ |
| 2304 | | if (res) |
| 2305 | | m_pc = target_addr; |
| 2306 | | else |
| 2307 | | m_pc += 4; |
| 2308 | | |
| 2309 | | m_pc_updated = 1; |
| 2310 | | } |
| 2311 | | |
| 2312 | | |
| 2313 | | /* Execute "bc.t lbroff" instruction. */ |
| 2314 | | void i860_cpu_device::insn_bct (UINT32 insn) |
| 2315 | | { |
| 2316 | | UINT32 target_addr = 0; |
| 2317 | | INT32 lbroff = 0; |
| 2318 | | int res = 0; |
| 2319 | | UINT32 orig_pc = m_pc; |
| 2320 | | |
| 2321 | | /* Compute the target address from the lbroff field. */ |
| 2322 | | lbroff = sign_ext ((insn & 0x03ffffff), 26); |
| 2323 | | target_addr = (INT32)m_pc + 4 + (lbroff << 2); |
| 2324 | | |
| 2325 | | /* Determine comparison result. */ |
| 2326 | | res = (GET_PSR_CC () == 1); |
| 2327 | | |
| 2328 | | /* Careful. Unlike bla, the delay slot instruction is only executed |
| 2329 | | if the branch is taken. */ |
| 2330 | | if (res) |
| 2331 | | { |
| 2332 | | /* Execute delay slot instruction. */ |
| 2333 | | m_pc += 4; |
| 2334 | | decode_exec (ifetch (orig_pc + 4), 0); |
| 2335 | | m_pc = orig_pc; |
| 2336 | | if (m_pending_trap) |
| 2337 | | { |
| 2338 | | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2339 | | goto ab_op; |
| 2340 | | } |
| 2341 | | } |
| 2342 | | |
| 2343 | | /* Since this branch is delayed, we must jump 2 instructions if |
| 2344 | | if isn't taken. */ |
| 2345 | | if (res) |
| 2346 | | m_pc = target_addr; |
| 2347 | | else |
| 2348 | | m_pc += 8; |
| 2349 | | |
| 2350 | | m_pc_updated = 1; |
| 2351 | | |
| 2352 | | ab_op: |
| 2353 | | ; |
| 2354 | | } |
| 2355 | | |
| 2356 | | |
| 2357 | | /* Execute "bnc.t lbroff" instruction. */ |
| 2358 | | void i860_cpu_device::insn_bnct (UINT32 insn) |
| 2359 | | { |
| 2360 | | UINT32 target_addr = 0; |
| 2361 | | INT32 lbroff = 0; |
| 2362 | | int res = 0; |
| 2363 | | UINT32 orig_pc = m_pc; |
| 2364 | | |
| 2365 | | /* Compute the target address from the lbroff field. */ |
| 2366 | | lbroff = sign_ext ((insn & 0x03ffffff), 26); |
| 2367 | | target_addr = (INT32)m_pc + 4 + (lbroff << 2); |
| 2368 | | |
| 2369 | | /* Determine comparison result. */ |
| 2370 | | res = (GET_PSR_CC () == 0); |
| 2371 | | |
| 2372 | | /* Careful. Unlike bla, the delay slot instruction is only executed |
| 2373 | | if the branch is taken. */ |
| 2374 | | if (res) |
| 2375 | | { |
| 2376 | | /* Execute delay slot instruction. */ |
| 2377 | | m_pc += 4; |
| 2378 | | decode_exec (ifetch (orig_pc + 4), 0); |
| 2379 | | m_pc = orig_pc; |
| 2380 | | if (m_pending_trap) |
| 2381 | | { |
| 2382 | | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2383 | | goto ab_op; |
| 2384 | | } |
| 2385 | | } |
| 2386 | | |
| 2387 | | /* Since this branch is delayed, we must jump 2 instructions if |
| 2388 | | if isn't taken. */ |
| 2389 | | if (res) |
| 2390 | | m_pc = target_addr; |
| 2391 | | else |
| 2392 | | m_pc += 8; |
| 2393 | | |
| 2394 | | m_pc_updated = 1; |
| 2395 | | |
| 2396 | | ab_op: |
| 2397 | | ; |
| 2398 | | } |
| 2399 | | |
| 2400 | | |
| 2401 | | /* Execute "call lbroff" instruction. */ |
| 2402 | | void i860_cpu_device::insn_call (UINT32 insn) |
| 2403 | | { |
| 2404 | | UINT32 target_addr = 0; |
| 2405 | | INT32 lbroff = 0; |
| 2406 | | UINT32 orig_pc = m_pc; |
| 2407 | | |
| 2408 | | /* Compute the target address from the lbroff field. */ |
| 2409 | | lbroff = sign_ext ((insn & 0x03ffffff), 26); |
| 2410 | | target_addr = (INT32)m_pc + 4 + (lbroff << 2); |
| 2411 | | |
| 2412 | | /* Execute the delay slot instruction. */ |
| 2413 | | m_pc += 4; |
| 2414 | | decode_exec (ifetch (orig_pc + 4), 0); |
| 2415 | | m_pc = orig_pc; |
| 2416 | | if (m_pending_trap) |
| 2417 | | { |
| 2418 | | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2419 | | goto ab_op; |
| 2420 | | } |
| 2421 | | |
| 2422 | | /* Sets the return pointer (r1). */ |
| 2423 | | set_iregval (1, orig_pc + 8); |
| 2424 | | |
| 2425 | | /* New target. */ |
| 2426 | | m_pc = target_addr; |
| 2427 | | m_pc_updated = 1; |
| 2428 | | |
| 2429 | | ab_op:; |
| 2430 | | } |
| 2431 | | |
| 2432 | | |
| 2433 | | /* Execute "br lbroff". */ |
| 2434 | | void i860_cpu_device::insn_br (UINT32 insn) |
| 2435 | | { |
| 2436 | | UINT32 target_addr = 0; |
| 2437 | | INT32 lbroff = 0; |
| 2438 | | UINT32 orig_pc = m_pc; |
| 2439 | | |
| 2440 | | /* Compute the target address from the lbroff field. */ |
| 2441 | | lbroff = sign_ext ((insn & 0x03ffffff), 26); |
| 2442 | | target_addr = (INT32)m_pc + 4 + (lbroff << 2); |
| 2443 | | |
| 2444 | | /* Execute the delay slot instruction. */ |
| 2445 | | m_pc += 4; |
| 2446 | | decode_exec (ifetch (orig_pc + 4), 0); |
| 2447 | | m_pc = orig_pc; |
| 2448 | | if (m_pending_trap) |
| 2449 | | { |
| 2450 | | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2451 | | goto ab_op; |
| 2452 | | } |
| 2453 | | |
| 2454 | | /* New target. */ |
| 2455 | | m_pc = target_addr; |
| 2456 | | m_pc_updated = 1; |
| 2457 | | |
| 2458 | | ab_op:; |
| 2459 | | } |
| 2460 | | |
| 2461 | | |
| 2462 | | /* Execute "bri isrc1ni" instruction. |
| 2463 | | Note: I didn't merge this code with calli because bri must do |
| 2464 | | a lot of flag manipulation if any trap bits are set. */ |
| 2465 | | void i860_cpu_device::insn_bri (UINT32 insn) |
| 2466 | | { |
| 2467 | | UINT32 isrc1 = get_isrc1 (insn); |
| 2468 | | UINT32 orig_pc = m_pc; |
| 2469 | | UINT32 orig_psr = m_cregs[CR_PSR]; |
| 2470 | | UINT32 orig_src1_val = get_iregval (isrc1); |
| 2471 | | |
| 2472 | | #if 1 /* TURBO. */ |
| 2473 | | m_cregs[CR_PSR] &= ~PSR_ALL_TRAP_BITS_MASK; |
| 2474 | | #endif |
| 2475 | | |
| 2476 | | /* Execute the delay slot instruction. */ |
| 2477 | | m_pc += 4; |
| 2478 | | decode_exec (ifetch (orig_pc + 4), 0); |
| 2479 | | m_pc = orig_pc; |
| 2480 | | |
| 2481 | | /* Delay slot insn caused a trap, abort operation. */ |
| 2482 | | if (m_pending_trap) |
| 2483 | | { |
| 2484 | | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2485 | | goto ab_op; |
| 2486 | | } |
| 2487 | | |
| 2488 | | /* If any trap bits are set, we need to do the return from |
| 2489 | | trap work. Note, we must use the PSR value that existed |
| 2490 | | before the delay slot instruction was executed since the |
| 2491 | | delay slot instruction might itself cause a trap bit to |
| 2492 | | be set. */ |
| 2493 | | if (orig_psr & PSR_ALL_TRAP_BITS_MASK) |
| 2494 | | { |
| 2495 | | /* Restore U and IM from their previous copies. */ |
| 2496 | | SET_PSR_U (GET_PSR_PU ()); |
| 2497 | | SET_PSR_IM (GET_PSR_PIM ()); |
| 2498 | | |
| 2499 | | m_fir_gets_trap_addr = 0; |
| 2500 | | } |
| 2501 | | |
| 2502 | | /* Update PC. */ |
| 2503 | | m_pc = orig_src1_val; |
| 2504 | | |
| 2505 | | m_pc_updated = 1; |
| 2506 | | ab_op:; |
| 2507 | | } |
| 2508 | | |
| 2509 | | /* Execute "calli isrc1ni" instruction. */ |
| 2510 | | void i860_cpu_device::insn_calli (UINT32 insn) |
| 2511 | | { |
| 2512 | | UINT32 isrc1 = get_isrc1 (insn); |
| 2513 | | UINT32 orig_pc = m_pc; |
| 2514 | | UINT32 orig_src1_val = get_iregval (isrc1); |
| 2515 | | |
| 2516 | | #ifdef TRACE_UNDEFINED_I860 |
| 2517 | | /* Check for undefined behavior. */ |
| 2518 | | if (isrc1 == 1) |
| 2519 | | { |
| 2520 | | /* Src1 must not be r1. */ |
| 2521 | | fprintf (stderr, "WARNING: insn_calli (pc=0x%08x): isrc1 = r1 on a calli\n", m_pc); |
| 2522 | | } |
| 2523 | | #endif |
| 2524 | | |
| 2525 | | /* Set return pointer before executing delay slot instruction. */ |
| 2526 | | set_iregval (1, m_pc + 8); |
| 2527 | | |
| 2528 | | /* Execute the delay slot instruction. */ |
| 2529 | | m_pc += 4; |
| 2530 | | decode_exec (ifetch (orig_pc + 4), 0); |
| 2531 | | m_pc = orig_pc; |
| 2532 | | if (m_pending_trap) |
| 2533 | | { |
| 2534 | | set_iregval (1, orig_src1_val); |
| 2535 | | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2536 | | goto ab_op; |
| 2537 | | } |
| 2538 | | |
| 2539 | | /* Set new PC. */ |
| 2540 | | m_pc = orig_src1_val; |
| 2541 | | m_pc_updated = 1; |
| 2542 | | |
| 2543 | | ab_op:; |
| 2544 | | } |
| 2545 | | |
| 2546 | | |
| 2547 | | /* Execute "bla isrc1ni,isrc2,sbroff" instruction. */ |
| 2548 | | void i860_cpu_device::insn_bla (UINT32 insn) |
| 2549 | | { |
| 2550 | | UINT32 isrc1 = get_isrc1 (insn); |
| 2551 | | UINT32 isrc2 = get_isrc2 (insn); |
| 2552 | | UINT32 target_addr = 0; |
| 2553 | | INT32 sbroff = 0; |
| 2554 | | int lcc_tmp = 0; |
| 2555 | | UINT32 orig_pc = m_pc; |
| 2556 | | UINT32 orig_isrc2val = get_iregval (isrc2); |
| 2557 | | |
| 2558 | | #ifdef TRACE_UNDEFINED_I860 |
| 2559 | | /* Check for undefined behavior. */ |
| 2560 | | if (isrc1 == isrc2) |
| 2561 | | { |
| 2562 | | /* Src1 and src2 the same is undefined i860XR behavior. */ |
| 2563 | | fprintf (stderr, "WARNING: insn_bla (pc=0x%08x): isrc1 and isrc2 are the same (ignored)\n", m_pc); |
| 2564 | | return; |
| 2565 | | } |
| 2566 | | #endif |
| 2567 | | |
| 2568 | | /* Compute the target address from the sbroff field. */ |
| 2569 | | sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); |
| 2570 | | target_addr = (INT32)m_pc + 4 + (sbroff << 2); |
| 2571 | | |
| 2572 | | /* Determine comparison result based on opcode. */ |
| 2573 | | lcc_tmp = ((INT32)get_iregval (isrc2) >= -(INT32)get_iregval (isrc1)); |
| 2574 | | |
| 2575 | | set_iregval (isrc2, get_iregval (isrc1) + orig_isrc2val); |
| 2576 | | |
| 2577 | | /* Execute the delay slot instruction. */ |
| 2578 | | m_pc += 4; |
| 2579 | | decode_exec (ifetch (orig_pc + 4), 0); |
| 2580 | | m_pc = orig_pc; |
| 2581 | | if (m_pending_trap) |
| 2582 | | { |
| 2583 | | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2584 | | goto ab_op; |
| 2585 | | } |
| 2586 | | |
| 2587 | | if (GET_PSR_LCC ()) |
| 2588 | | m_pc = target_addr; |
| 2589 | | else |
| 2590 | | { |
| 2591 | | /* Since this branch is delayed, we must jump 2 instructions if |
| 2592 | | if isn't taken. */ |
| 2593 | | m_pc += 8; |
| 2594 | | } |
| 2595 | | SET_PSR_LCC (lcc_tmp); |
| 2596 | | |
| 2597 | | m_pc_updated = 1; |
| 2598 | | ab_op:; |
| 2599 | | } |
| 2600 | | |
| 2601 | | |
| 2602 | | /* Execute "flush #const(isrc2)" or "flush #const(isrc2)++" instruction. */ |
| 2603 | | void i860_cpu_device::insn_flush (UINT32 insn) |
| 2604 | | { |
| 2605 | | UINT32 src1val = sign_ext (get_imm16 (insn), 16); |
| 2606 | | UINT32 isrc2 = get_isrc2 (insn); |
| 2607 | | int auto_inc = (insn & 1); |
| 2608 | | UINT32 eff = 0; |
| 2609 | | |
| 2610 | | /* Technically, idest should be encoded as r0 because idest |
| 2611 | | is undefined after the instruction. We don't currently |
| 2612 | | check for this. |
| 2613 | | |
| 2614 | | Flush D$ block at address #const+isrc2. Block is undefined |
| 2615 | | after. The effective address must be 16-byte aligned. |
| 2616 | | |
| 2617 | | FIXME: Need to examine RB and RC and do this right. |
| 2618 | | */ |
| 2619 | | |
| 2620 | | /* Chop off lower bits of displacement to 16-byte alignment. */ |
| 2621 | | src1val &= ~(16-1); |
| 2622 | | eff = src1val + get_iregval (isrc2); |
| 2623 | | if (auto_inc) |
| 2624 | | set_iregval (isrc2, eff); |
| 2625 | | |
| 2626 | | /* In user mode, the flush is ignored. */ |
| 2627 | | if (GET_PSR_U () == 0) |
| 2628 | | { |
| 2629 | | /* If line is dirty, write it to memory and invalidate. |
| 2630 | | NOTE: The actual dirty write is unimplemented in the MAME version |
| 2631 | | as we don't emulate the dcache. */ |
| 2632 | | } |
| 2633 | | } |
| 2634 | | |
| 2635 | | |
| 2636 | | /* Execute "[p]fmul.{ss,sd,dd} fsrc1,fsrc2,fdest" instruction or |
| 2637 | | pfmul3.dd fsrc1,fsrc2,fdest. |
| 2638 | | |
| 2639 | | The pfmul3.dd differs from pfmul.dd in that it treats the pipeline |
| 2640 | | as 3 stages, even though it is a double precision multiply. */ |
| 2641 | | void i860_cpu_device::insn_fmul (UINT32 insn) |
| 2642 | | { |
| 2643 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 2644 | | UINT32 fsrc2 = get_fsrc2 (insn); |
| 2645 | | UINT32 fdest = get_fdest (insn); |
| 2646 | | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 2647 | | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 2648 | | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 2649 | | double dbl_tmp_dest = 0.0; |
| 2650 | | float sgl_tmp_dest = 0.0; |
| 2651 | | double dbl_last_stage_contents = 0.0; |
| 2652 | | float sgl_last_stage_contents = 0.0; |
| 2653 | | int is_pfmul3 = insn & 0x4; |
| 2654 | | int num_stages = (src_prec && !is_pfmul3) ? 2 : 3; |
| 2655 | | |
| 2656 | | /* Only .dd is valid for pfmul. */ |
| 2657 | | if (is_pfmul3 && (insn & 0x180) != 0x180) |
| 2658 | | { |
| 2659 | | unrecog_opcode (m_pc, insn); |
| 2660 | | return; |
| 2661 | | } |
| 2662 | | |
| 2663 | | /* Check for invalid .ds combination. */ |
| 2664 | | if ((insn & 0x180) == 0x100) |
| 2665 | | { |
| 2666 | | unrecog_opcode (m_pc, insn); |
| 2667 | | return; |
| 2668 | | } |
| 2669 | | |
| 2670 | | /* For pipelined version, retrieve the contents of the last stage |
| 2671 | | of the pipeline, whose precision is specified by the MRP bit |
| 2672 | | of the stage's result-status bits. Note for pfmul, the number |
| 2673 | | of stages is determined by the source precision of the current |
| 2674 | | operation. */ |
| 2675 | | if (piped) |
| 2676 | | { |
| 2677 | | if (m_M[num_stages - 1].stat.mrp) |
| 2678 | | dbl_last_stage_contents = m_M[num_stages - 1].val.d; |
| 2679 | | else |
| 2680 | | sgl_last_stage_contents = m_M[num_stages - 1].val.s; |
| 2681 | | } |
| 2682 | | |
| 2683 | | /* Do the operation, being careful about source and result |
| 2684 | | precision. */ |
| 2685 | | if (src_prec) |
| 2686 | | { |
| 2687 | | double v1 = get_fregval_d (fsrc1); |
| 2688 | | double v2 = get_fregval_d (fsrc2); |
| 2689 | | |
| 2690 | | /* For pipelined mul, if fsrc2 is the same as fdest, then the last |
| 2691 | | stage is bypassed to fsrc2 (rather than using the value in fsrc2). |
| 2692 | | This bypass is not available for fsrc1, and is undefined behavior. */ |
| 2693 | | if (0 && piped && fdest != 0 && fsrc1 == fdest) |
| 2694 | | v1 = dbl_last_stage_contents; |
| 2695 | | if (piped && fdest != 0 && fsrc2 == fdest) |
| 2696 | | v2 = dbl_last_stage_contents; |
| 2697 | | |
| 2698 | | if (res_prec) |
| 2699 | | dbl_tmp_dest = v1 * v2; |
| 2700 | | else |
| 2701 | | sgl_tmp_dest = (float)(v1 * v2); |
| 2702 | | } |
| 2703 | | else |
| 2704 | | { |
| 2705 | | float v1 = get_fregval_s (fsrc1); |
| 2706 | | float v2 = get_fregval_s (fsrc2); |
| 2707 | | |
| 2708 | | /* For pipelined mul, if fsrc2 is the same as fdest, then the last |
| 2709 | | stage is bypassed to fsrc2 (rather than using the value in fsrc2). |
| 2710 | | This bypass is not available for fsrc1, and is undefined behavior. */ |
| 2711 | | if (0 && piped && fdest != 0 && fsrc1 == fdest) |
| 2712 | | v1 = sgl_last_stage_contents; |
| 2713 | | if (piped && fdest != 0 && fsrc2 == fdest) |
| 2714 | | v2 = sgl_last_stage_contents; |
| 2715 | | |
| 2716 | | if (res_prec) |
| 2717 | | dbl_tmp_dest = (double)(v1 * v2); |
| 2718 | | else |
| 2719 | | sgl_tmp_dest = v1 * v2; |
| 2720 | | } |
| 2721 | | |
| 2722 | | /* FIXME: Set result-status bits besides MRP. And copy to fsr from |
| 2723 | | last stage. */ |
| 2724 | | /* FIXME: Scalar version flows through all stages. */ |
| 2725 | | /* FIXME: Mixed precision (only weird for pfmul). */ |
| 2726 | | if (!piped) |
| 2727 | | { |
| 2728 | | /* Scalar version writes the current calculation to the fdest |
| 2729 | | register, with precision specified by the R bit. */ |
| 2730 | | if (res_prec) |
| 2731 | | set_fregval_d (fdest, dbl_tmp_dest); |
| 2732 | | else |
| 2733 | | set_fregval_s (fdest, sgl_tmp_dest); |
| 2734 | | } |
| 2735 | | else |
| 2736 | | { |
| 2737 | | /* Pipelined version writes fdest with the result from the last |
| 2738 | | stage of the pipeline. */ |
| 2739 | | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 2740 | | /* Copy 3rd stage MRP to FSR. */ |
| 2741 | | if (m_M[num_stages - 2 /* 1 */].stat.mrp) |
| 2742 | | m_cregs[CR_FSR] |= 0x10000000; |
| 2743 | | else |
| 2744 | | m_cregs[CR_FSR] &= ~0x10000000; |
| 2745 | | #endif |
| 2746 | | |
| 2747 | | if (m_M[num_stages - 1].stat.mrp) |
| 2748 | | set_fregval_d (fdest, dbl_last_stage_contents); |
| 2749 | | else |
| 2750 | | set_fregval_s (fdest, sgl_last_stage_contents); |
| 2751 | | |
| 2752 | | /* Now advance pipeline and write current calculation to |
| 2753 | | first stage. */ |
| 2754 | | if (num_stages == 3) |
| 2755 | | { |
| 2756 | | m_M[2] = m_M[1]; |
| 2757 | | m_M[1] = m_M[0]; |
| 2758 | | } |
| 2759 | | else |
| 2760 | | m_M[1] = m_M[0]; |
| 2761 | | |
| 2762 | | if (res_prec) |
| 2763 | | { |
| 2764 | | m_M[0].val.d = dbl_tmp_dest; |
| 2765 | | m_M[0].stat.mrp = 1; |
| 2766 | | } |
| 2767 | | else |
| 2768 | | { |
| 2769 | | m_M[0].val.s = sgl_tmp_dest; |
| 2770 | | m_M[0].stat.mrp = 0; |
| 2771 | | } |
| 2772 | | } |
| 2773 | | } |
| 2774 | | |
| 2775 | | |
| 2776 | | /* Execute "fmlow.dd fsrc1,fsrc2,fdest" instruction. */ |
| 2777 | | void i860_cpu_device::insn_fmlow (UINT32 insn) |
| 2778 | | { |
| 2779 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 2780 | | UINT32 fsrc2 = get_fsrc2 (insn); |
| 2781 | | UINT32 fdest = get_fdest (insn); |
| 2782 | | |
| 2783 | | double v1 = get_fregval_d (fsrc1); |
| 2784 | | double v2 = get_fregval_d (fsrc2); |
| 2785 | | INT64 i1 = *(UINT64 *)&v1; |
| 2786 | | INT64 i2 = *(UINT64 *)&v2; |
| 2787 | | INT64 tmp = 0; |
| 2788 | | |
| 2789 | | /* Only .dd is valid for fmlow. */ |
| 2790 | | if ((insn & 0x180) != 0x180) |
| 2791 | | { |
| 2792 | | unrecog_opcode (m_pc, insn); |
| 2793 | | return; |
| 2794 | | } |
| 2795 | | |
| 2796 | | /* The lower 32-bits are obvious. What exactly goes in the upper |
| 2797 | | bits? |
| 2798 | | Technically, the upper-most 10 bits are undefined, but i'd like |
| 2799 | | to be undefined in the same way as the real i860 if possible. */ |
| 2800 | | |
| 2801 | | /* Keep lower 53 bits of multiply. */ |
| 2802 | | tmp = i1 * i2; |
| 2803 | | tmp &= 0x001fffffffffffffULL; |
| 2804 | | tmp |= (i1 & 0x8000000000000000LL) ^ (i2 & 0x8000000000000000LL); |
| 2805 | | set_fregval_d (fdest, *(double *)&tmp); |
| 2806 | | } |
| 2807 | | |
| 2808 | | |
| 2809 | | /* Execute [p]fadd.{ss,sd,dd} fsrc1,fsrc2,fdest (.ds disallowed above). */ |
| 2810 | | void i860_cpu_device::insn_fadd_sub (UINT32 insn) |
| 2811 | | { |
| 2812 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 2813 | | UINT32 fsrc2 = get_fsrc2 (insn); |
| 2814 | | UINT32 fdest = get_fdest (insn); |
| 2815 | | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 2816 | | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 2817 | | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 2818 | | int is_sub = insn & 1; /* 1 = sub, 0 = add. */ |
| 2819 | | double dbl_tmp_dest = 0.0; |
| 2820 | | float sgl_tmp_dest = 0.0; |
| 2821 | | double dbl_last_stage_contents = 0.0; |
| 2822 | | float sgl_last_stage_contents = 0.0; |
| 2823 | | |
| 2824 | | /* Check for invalid .ds combination. */ |
| 2825 | | if ((insn & 0x180) == 0x100) |
| 2826 | | { |
| 2827 | | unrecog_opcode (m_pc, insn); |
| 2828 | | return; |
| 2829 | | } |
| 2830 | | |
| 2831 | | /* For pipelined version, retrieve the contents of the last stage |
| 2832 | | of the pipeline, whose precision is specified by the ARP bit |
| 2833 | | of the stage's result-status bits. There are always three stages |
| 2834 | | for pfadd/pfsub. */ |
| 2835 | | if (piped) |
| 2836 | | { |
| 2837 | | if (m_A[2].stat.arp) |
| 2838 | | dbl_last_stage_contents = m_A[2].val.d; |
| 2839 | | else |
| 2840 | | sgl_last_stage_contents = m_A[2].val.s; |
| 2841 | | } |
| 2842 | | |
| 2843 | | /* Do the operation, being careful about source and result |
| 2844 | | precision. */ |
| 2845 | | if (src_prec) |
| 2846 | | { |
| 2847 | | double v1 = get_fregval_d (fsrc1); |
| 2848 | | double v2 = get_fregval_d (fsrc2); |
| 2849 | | |
| 2850 | | /* For pipelined add/sub, if fsrc1 is the same as fdest, then the last |
| 2851 | | stage is bypassed to fsrc1 (rather than using the value in fsrc1). |
| 2852 | | Likewise for fsrc2. */ |
| 2853 | | if (piped && fdest != 0 && fsrc1 == fdest) |
| 2854 | | v1 = dbl_last_stage_contents; |
| 2855 | | if (piped && fdest != 0 && fsrc2 == fdest) |
| 2856 | | v2 = dbl_last_stage_contents; |
| 2857 | | |
| 2858 | | if (res_prec) |
| 2859 | | dbl_tmp_dest = is_sub ? v1 - v2 : v1 + v2; |
| 2860 | | else |
| 2861 | | sgl_tmp_dest = is_sub ? (float)(v1 - v2) : (float)(v1 + v2); |
| 2862 | | } |
| 2863 | | else |
| 2864 | | { |
| 2865 | | float v1 = get_fregval_s (fsrc1); |
| 2866 | | float v2 = get_fregval_s (fsrc2); |
| 2867 | | |
| 2868 | | /* For pipelined add/sub, if fsrc1 is the same as fdest, then the last |
| 2869 | | stage is bypassed to fsrc1 (rather than using the value in fsrc1). |
| 2870 | | Likewise for fsrc2. */ |
| 2871 | | if (piped && fdest != 0 && fsrc1 == fdest) |
| 2872 | | v1 = sgl_last_stage_contents; |
| 2873 | | if (piped && fdest != 0 && fsrc2 == fdest) |
| 2874 | | v2 = sgl_last_stage_contents; |
| 2875 | | |
| 2876 | | if (res_prec) |
| 2877 | | dbl_tmp_dest = is_sub ? (double)(v1 - v2) : (double)(v1 + v2); |
| 2878 | | else |
| 2879 | | sgl_tmp_dest = is_sub ? v1 - v2 : v1 + v2; |
| 2880 | | } |
| 2881 | | |
| 2882 | | /* FIXME: Set result-status bits besides ARP. And copy to fsr from |
| 2883 | | last stage. */ |
| 2884 | | /* FIXME: Scalar version flows through all stages. */ |
| 2885 | | if (!piped) |
| 2886 | | { |
| 2887 | | /* Scalar version writes the current calculation to the fdest |
| 2888 | | register, with precision specified by the R bit. */ |
| 2889 | | if (res_prec) |
| 2890 | | set_fregval_d (fdest, dbl_tmp_dest); |
| 2891 | | else |
| 2892 | | set_fregval_s (fdest, sgl_tmp_dest); |
| 2893 | | } |
| 2894 | | else |
| 2895 | | { |
| 2896 | | /* Pipelined version writes fdest with the result from the last |
| 2897 | | stage of the pipeline, with precision specified by the ARP |
| 2898 | | bit of the stage's result-status bits. */ |
| 2899 | | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 2900 | | /* Copy 3rd stage ARP to FSR. */ |
| 2901 | | if (m_A[1 /* 2 */].stat.arp) |
| 2902 | | m_cregs[CR_FSR] |= 0x20000000; |
| 2903 | | else |
| 2904 | | m_cregs[CR_FSR] &= ~0x20000000; |
| 2905 | | #endif |
| 2906 | | if (m_A[2].stat.arp) /* 3rd (last) stage. */ |
| 2907 | | set_fregval_d (fdest, dbl_last_stage_contents); |
| 2908 | | else |
| 2909 | | set_fregval_s (fdest, sgl_last_stage_contents); |
| 2910 | | |
| 2911 | | /* Now advance pipeline and write current calculation to |
| 2912 | | first stage. */ |
| 2913 | | m_A[2] = m_A[1]; |
| 2914 | | m_A[1] = m_A[0]; |
| 2915 | | if (res_prec) |
| 2916 | | { |
| 2917 | | m_A[0].val.d = dbl_tmp_dest; |
| 2918 | | m_A[0].stat.arp = 1; |
| 2919 | | } |
| 2920 | | else |
| 2921 | | { |
| 2922 | | m_A[0].val.s = sgl_tmp_dest; |
| 2923 | | m_A[0].stat.arp = 0; |
| 2924 | | } |
| 2925 | | } |
| 2926 | | } |
| 2927 | | |
| 2928 | | |
| 2929 | | /* Operand types for PFAM/PFMAM routine below. */ |
| 2930 | | enum { |
| 2931 | | OP_SRC1 = 0, |
| 2932 | | OP_SRC2 = 1, |
| 2933 | | OP_KI = 2, |
| 2934 | | OP_KR = 4, |
| 2935 | | OP_T = 8, |
| 2936 | | OP_MPIPE = 16, |
| 2937 | | OP_APIPE = 32, |
| 2938 | | FLAGM = 64 /* Indicates PFMAM uses M rather than A pipe result. */ |
| 2939 | | }; |
| 2940 | | |
| 2941 | | /* A table to map DPC value to source operands. |
| 2942 | | |
| 2943 | | The PFAM and PFMAM tables are nearly identical, and the only differences |
| 2944 | | are that every time PFAM uses the A pipe, PFMAM uses the M pipe instead. |
| 2945 | | So we only represent the PFAM table and use a special flag on any entry |
| 2946 | | where the PFMAM table would use the M pipe rather than the A pipe. |
| 2947 | | Also, entry 16 is not valid for PFMAM. */ |
| 2948 | | static const struct |
| 2949 | | { |
| 2950 | | int M_unit_op1; |
| 2951 | | int M_unit_op2; |
| 2952 | | int A_unit_op1; |
| 2953 | | int A_unit_op2; |
| 2954 | | int T_loaded; |
| 2955 | | int K_loaded; |
| 2956 | | } src_opers[] = { |
| 2957 | | /* 0000 */ { OP_KR, OP_SRC2, OP_SRC1, OP_MPIPE, 0, 0}, |
| 2958 | | /* 0001 */ { OP_KR, OP_SRC2, OP_T, OP_MPIPE, 0, 1}, |
| 2959 | | /* 0010 */ { OP_KR, OP_SRC2, OP_SRC1, OP_APIPE|FLAGM, 1, 0}, |
| 2960 | | /* 0011 */ { OP_KR, OP_SRC2, OP_T, OP_APIPE|FLAGM, 1, 1}, |
| 2961 | | /* 0100 */ { OP_KI, OP_SRC2, OP_SRC1, OP_MPIPE, 0, 0}, |
| 2962 | | /* 0101 */ { OP_KI, OP_SRC2, OP_T, OP_MPIPE, 0, 1}, |
| 2963 | | /* 0110 */ { OP_KI, OP_SRC2, OP_SRC1, OP_APIPE|FLAGM, 1, 0}, |
| 2964 | | /* 0111 */ { OP_KI, OP_SRC2, OP_T, OP_APIPE|FLAGM, 1, 1}, |
| 2965 | | /* 1000 */ { OP_KR, OP_APIPE|FLAGM, OP_SRC1, OP_SRC2, 1, 0}, |
| 2966 | | /* 1001 */ { OP_SRC1, OP_SRC2, OP_APIPE|FLAGM, OP_MPIPE, 0, 0}, |
| 2967 | | /* 1010 */ { OP_KR, OP_APIPE|FLAGM, OP_SRC1, OP_SRC2, 0, 0}, |
| 2968 | | /* 1011 */ { OP_SRC1, OP_SRC2, OP_T, OP_APIPE|FLAGM, 1, 0}, |
| 2969 | | /* 1100 */ { OP_KI, OP_APIPE|FLAGM, OP_SRC1, OP_SRC2, 1, 0}, |
| 2970 | | /* 1101 */ { OP_SRC1, OP_SRC2, OP_T, OP_MPIPE, 0, 0}, |
| 2971 | | /* 1110 */ { OP_KI, OP_APIPE|FLAGM, OP_SRC1, OP_SRC2, 0, 0}, |
| 2972 | | /* 1111 */ { OP_SRC1, OP_SRC2, OP_T, OP_APIPE|FLAGM, 0, 0} |
| 2973 | | }; |
| 2974 | | |
| 2975 | | float i860_cpu_device::get_fval_from_optype_s (UINT32 insn, int optype) |
| 2976 | | { |
| 2977 | | float retval = 0.0; |
| 2978 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 2979 | | UINT32 fsrc2 = get_fsrc2 (insn); |
| 2980 | | |
| 2981 | | optype &= ~FLAGM; |
| 2982 | | switch (optype) |
| 2983 | | { |
| 2984 | | case OP_SRC1: |
| 2985 | | retval = get_fregval_s (fsrc1); |
| 2986 | | break; |
| 2987 | | case OP_SRC2: |
| 2988 | | retval = get_fregval_s (fsrc2); |
| 2989 | | break; |
| 2990 | | case OP_KI: |
| 2991 | | retval = m_KI.s; |
| 2992 | | break; |
| 2993 | | case OP_KR: |
| 2994 | | retval = m_KR.s; |
| 2995 | | break; |
| 2996 | | case OP_T: |
| 2997 | | retval = m_T.s; |
| 2998 | | break; |
| 2999 | | case OP_MPIPE: |
| 3000 | | /* Last stage is 3rd stage for single precision input. */ |
| 3001 | | retval = m_M[2].val.s; |
| 3002 | | break; |
| 3003 | | case OP_APIPE: |
| 3004 | | retval = m_A[2].val.s; |
| 3005 | | break; |
| 3006 | | default: |
| 3007 | | assert (0); |
| 3008 | | } |
| 3009 | | |
| 3010 | | return retval; |
| 3011 | | } |
| 3012 | | |
| 3013 | | |
| 3014 | | double i860_cpu_device::get_fval_from_optype_d (UINT32 insn, int optype) |
| 3015 | | { |
| 3016 | | double retval = 0.0; |
| 3017 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3018 | | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3019 | | |
| 3020 | | optype &= ~FLAGM; |
| 3021 | | switch (optype) |
| 3022 | | { |
| 3023 | | case OP_SRC1: |
| 3024 | | retval = get_fregval_d (fsrc1); |
| 3025 | | break; |
| 3026 | | case OP_SRC2: |
| 3027 | | retval = get_fregval_d (fsrc2); |
| 3028 | | break; |
| 3029 | | case OP_KI: |
| 3030 | | retval = m_KI.d; |
| 3031 | | break; |
| 3032 | | case OP_KR: |
| 3033 | | retval = m_KR.d; |
| 3034 | | break; |
| 3035 | | case OP_T: |
| 3036 | | retval = m_T.d; |
| 3037 | | break; |
| 3038 | | case OP_MPIPE: |
| 3039 | | /* Last stage is 2nd stage for double precision input. */ |
| 3040 | | retval = m_M[1].val.d; |
| 3041 | | break; |
| 3042 | | case OP_APIPE: |
| 3043 | | retval = m_A[2].val.d; |
| 3044 | | break; |
| 3045 | | default: |
| 3046 | | assert (0); |
| 3047 | | } |
| 3048 | | |
| 3049 | | return retval; |
| 3050 | | } |
| 3051 | | |
| 3052 | | |
| 3053 | | /* Execute pf[m]{a,s}m.{ss,sd,dd} fsrc1,fsrc2,fdest (FP dual ops). |
| 3054 | | |
| 3055 | | Since these are always pipelined, the P bit is used to distinguish |
| 3056 | | family pfam (P=1) from family pfmam (P=0), and the lower 4 bits |
| 3057 | | of the extended opcode is the DPC. |
| 3058 | | |
| 3059 | | Note also that the S and R bits are slightly different than normal |
| 3060 | | floating point operations. The S bit denotes the precision of the |
| 3061 | | multiplication source, while the R bit denotes the precision of |
| 3062 | | the addition source as well as precision of all results. */ |
| 3063 | | void i860_cpu_device::insn_dualop (UINT32 insn) |
| 3064 | | { |
| 3065 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3066 | | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3067 | | UINT32 fdest = get_fdest (insn); |
| 3068 | | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3069 | | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 3070 | | int is_pfam = insn & 0x400; /* 1 = pfam, 0 = pfmam. */ |
| 3071 | | int is_sub = insn & 0x10; /* 1 = pf[m]sm, 0 = pf[m]am. */ |
| 3072 | | double dbl_tmp_dest_mul = 0.0; |
| 3073 | | float sgl_tmp_dest_mul = 0.0; |
| 3074 | | double dbl_tmp_dest_add = 0.0; |
| 3075 | | float sgl_tmp_dest_add = 0.0; |
| 3076 | | double dbl_last_Mstage_contents = 0.0; |
| 3077 | | float sgl_last_Mstage_contents = 0.0; |
| 3078 | | double dbl_last_Astage_contents = 0.0; |
| 3079 | | float sgl_last_Astage_contents = 0.0; |
| 3080 | | int num_mul_stages = src_prec ? 2 : 3; |
| 3081 | | |
| 3082 | | int dpc = insn & 0xf; |
| 3083 | | int M_unit_op1 = src_opers[dpc].M_unit_op1; |
| 3084 | | int M_unit_op2 = src_opers[dpc].M_unit_op2; |
| 3085 | | int A_unit_op1 = src_opers[dpc].A_unit_op1; |
| 3086 | | int A_unit_op2 = src_opers[dpc].A_unit_op2; |
| 3087 | | int T_loaded = src_opers[dpc].T_loaded; |
| 3088 | | int K_loaded = src_opers[dpc].K_loaded; |
| 3089 | | |
| 3090 | | /* Check for invalid .ds combination. */ |
| 3091 | | if ((insn & 0x180) == 0x100) |
| 3092 | | { |
| 3093 | | unrecog_opcode (m_pc, insn); |
| 3094 | | return; |
| 3095 | | } |
| 3096 | | |
| 3097 | | if (is_pfam == 0) |
| 3098 | | { |
| 3099 | | /* Check for invalid DPC combination 16 for PFMAM. */ |
| 3100 | | if (dpc == 16) |
| 3101 | | { |
| 3102 | | unrecog_opcode (m_pc, insn); |
| 3103 | | return; |
| 3104 | | } |
| 3105 | | |
| 3106 | | /* PFMAM table adjustments (M_unit_op1 is never a pipe stage, |
| 3107 | | so no adjustment made for it). */ |
| 3108 | | M_unit_op2 = (M_unit_op2 & FLAGM) ? OP_MPIPE : M_unit_op2; |
| 3109 | | A_unit_op1 = (A_unit_op1 & FLAGM) ? OP_MPIPE : A_unit_op1; |
| 3110 | | A_unit_op2 = (A_unit_op2 & FLAGM) ? OP_MPIPE : A_unit_op2; |
| 3111 | | } |
| 3112 | | |
| 3113 | | /* FIXME: Check for fsrc1/fdest overlap for some mul DPC combinations. */ |
| 3114 | | |
| 3115 | | /* Retrieve the contents of the last stage of the multiplier pipeline, |
| 3116 | | whose precision is specified by the MRP bit of the stage's result- |
| 3117 | | status bits. Note for multiply, the number of stages is determined |
| 3118 | | by the source precision of the current operation. */ |
| 3119 | | if (m_M[num_mul_stages - 1].stat.mrp) |
| 3120 | | dbl_last_Mstage_contents = m_M[num_mul_stages - 1].val.d; |
| 3121 | | else |
| 3122 | | sgl_last_Mstage_contents = m_M[num_mul_stages - 1].val.s; |
| 3123 | | |
| 3124 | | /* Similarly, retrieve the last stage of the adder pipe. */ |
| 3125 | | if (m_A[2].stat.arp) |
| 3126 | | dbl_last_Astage_contents = m_A[2].val.d; |
| 3127 | | else |
| 3128 | | sgl_last_Astage_contents = m_A[2].val.s; |
| 3129 | | |
| 3130 | | /* Do the mul operation, being careful about source and result |
| 3131 | | precision. */ |
| 3132 | | if (src_prec) |
| 3133 | | { |
| 3134 | | double v1 = get_fval_from_optype_d (insn, M_unit_op1); |
| 3135 | | double v2 = get_fval_from_optype_d (insn, M_unit_op2); |
| 3136 | | |
| 3137 | | /* For mul, if fsrc2 is the same as fdest, then the last stage |
| 3138 | | is bypassed to fsrc2 (rather than using the value in fsrc2). |
| 3139 | | This bypass is not available for fsrc1, and is undefined behavior. */ |
| 3140 | | if (0 && M_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest) |
| 3141 | | v1 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents; |
| 3142 | | if (M_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest) |
| 3143 | | v2 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents; |
| 3144 | | |
| 3145 | | if (res_prec) |
| 3146 | | dbl_tmp_dest_mul = v1 * v2; |
| 3147 | | else |
| 3148 | | sgl_tmp_dest_mul = (float)(v1 * v2); |
| 3149 | | } |
| 3150 | | else |
| 3151 | | { |
| 3152 | | float v1 = get_fval_from_optype_s (insn, M_unit_op1); |
| 3153 | | float v2 = get_fval_from_optype_s (insn, M_unit_op2); |
| 3154 | | |
| 3155 | | /* For mul, if fsrc2 is the same as fdest, then the last stage |
| 3156 | | is bypassed to fsrc2 (rather than using the value in fsrc2). |
| 3157 | | This bypass is not available for fsrc1, and is undefined behavior. */ |
| 3158 | | if (0 && M_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest) |
| 3159 | | v1 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents; |
| 3160 | | if (M_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest) |
| 3161 | | v2 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents; |
| 3162 | | |
| 3163 | | if (res_prec) |
| 3164 | | dbl_tmp_dest_mul = (double)(v1 * v2); |
| 3165 | | else |
| 3166 | | sgl_tmp_dest_mul = v1 * v2; |
| 3167 | | } |
| 3168 | | |
| 3169 | | /* Do the add operation, being careful about source and result |
| 3170 | | precision. Remember, the R bit indicates source and result precision |
| 3171 | | here. */ |
| 3172 | | if (res_prec) |
| 3173 | | { |
| 3174 | | double v1 = get_fval_from_optype_d (insn, A_unit_op1); |
| 3175 | | double v2 = get_fval_from_optype_d (insn, A_unit_op2); |
| 3176 | | |
| 3177 | | /* For add/sub, if fsrc1 is the same as fdest, then the last stage |
| 3178 | | is bypassed to fsrc1 (rather than using the value in fsrc1). |
| 3179 | | Likewise for fsrc2. */ |
| 3180 | | if (A_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest) |
| 3181 | | v1 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents; |
| 3182 | | if (A_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest) |
| 3183 | | v2 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents; |
| 3184 | | |
| 3185 | | if (res_prec) |
| 3186 | | dbl_tmp_dest_add = is_sub ? v1 - v2 : v1 + v2; |
| 3187 | | else |
| 3188 | | sgl_tmp_dest_add = is_sub ? (float)(v1 - v2) : (float)(v1 + v2); |
| 3189 | | } |
| 3190 | | else |
| 3191 | | { |
| 3192 | | float v1 = get_fval_from_optype_s (insn, A_unit_op1); |
| 3193 | | float v2 = get_fval_from_optype_s (insn, A_unit_op2); |
| 3194 | | |
| 3195 | | /* For add/sub, if fsrc1 is the same as fdest, then the last stage |
| 3196 | | is bypassed to fsrc1 (rather than using the value in fsrc1). |
| 3197 | | Likewise for fsrc2. */ |
| 3198 | | if (A_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest) |
| 3199 | | v1 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents; |
| 3200 | | if (A_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest) |
| 3201 | | v2 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents; |
| 3202 | | |
| 3203 | | if (res_prec) |
| 3204 | | dbl_tmp_dest_add = is_sub ? (double)(v1 - v2) : (double)(v1 + v2); |
| 3205 | | else |
| 3206 | | sgl_tmp_dest_add = is_sub ? v1 - v2 : v1 + v2; |
| 3207 | | } |
| 3208 | | |
| 3209 | | /* If necessary, load T. */ |
| 3210 | | if (T_loaded) |
| 3211 | | { |
| 3212 | | /* T is loaded from the result of the last stage of the multiplier. */ |
| 3213 | | if (m_M[num_mul_stages - 1].stat.mrp) |
| 3214 | | m_T.d = dbl_last_Mstage_contents; |
| 3215 | | else |
| 3216 | | m_T.s = sgl_last_Mstage_contents; |
| 3217 | | } |
| 3218 | | |
| 3219 | | /* If necessary, load KR or KI. */ |
| 3220 | | if (K_loaded) |
| 3221 | | { |
| 3222 | | /* KI or KR is loaded from the first register input. */ |
| 3223 | | if (M_unit_op1 == OP_KI) |
| 3224 | | { |
| 3225 | | if (src_prec) |
| 3226 | | m_KI.d = get_fregval_d (fsrc1); |
| 3227 | | else |
| 3228 | | m_KI.s = get_fregval_s (fsrc1); |
| 3229 | | } |
| 3230 | | else if (M_unit_op1 == OP_KR) |
| 3231 | | { |
| 3232 | | if (src_prec) |
| 3233 | | m_KR.d = get_fregval_d (fsrc1); |
| 3234 | | else |
| 3235 | | m_KR.s = get_fregval_s (fsrc1); |
| 3236 | | } |
| 3237 | | else |
| 3238 | | assert (0); |
| 3239 | | } |
| 3240 | | |
| 3241 | | /* Now update fdest (either from adder pipe or multiplier pipe, |
| 3242 | | depending on whether the instruction is pfam or pfmam). */ |
| 3243 | | if (is_pfam) |
| 3244 | | { |
| 3245 | | /* Update fdest with the result from the last stage of the |
| 3246 | | adder pipeline, with precision specified by the ARP |
| 3247 | | bit of the stage's result-status bits. */ |
| 3248 | | if (m_A[2].stat.arp) |
| 3249 | | set_fregval_d (fdest, dbl_last_Astage_contents); |
| 3250 | | else |
| 3251 | | set_fregval_s (fdest, sgl_last_Astage_contents); |
| 3252 | | } |
| 3253 | | else |
| 3254 | | { |
| 3255 | | /* Update fdest with the result from the last stage of the |
| 3256 | | multiplier pipeline, with precision specified by the MRP |
| 3257 | | bit of the stage's result-status bits. */ |
| 3258 | | if (m_M[num_mul_stages - 1].stat.mrp) |
| 3259 | | set_fregval_d (fdest, dbl_last_Mstage_contents); |
| 3260 | | else |
| 3261 | | set_fregval_s (fdest, sgl_last_Mstage_contents); |
| 3262 | | } |
| 3263 | | |
| 3264 | | /* FIXME: Set result-status bits besides MRP. And copy to fsr from |
| 3265 | | last stage. */ |
| 3266 | | /* FIXME: Mixed precision (only weird for pfmul). */ |
| 3267 | | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 3268 | | /* Copy 3rd stage MRP to FSR. */ |
| 3269 | | if (m_M[num_mul_stages - 2 /* 1 */].stat.mrp) |
| 3270 | | m_cregs[CR_FSR] |= 0x10000000; |
| 3271 | | else |
| 3272 | | m_cregs[CR_FSR] &= ~0x10000000; |
| 3273 | | #endif |
| 3274 | | |
| 3275 | | /* Now advance multiplier pipeline and write current calculation to |
| 3276 | | first stage. */ |
| 3277 | | if (num_mul_stages == 3) |
| 3278 | | { |
| 3279 | | m_M[2] = m_M[1]; |
| 3280 | | m_M[1] = m_M[0]; |
| 3281 | | } |
| 3282 | | else |
| 3283 | | m_M[1] = m_M[0]; |
| 3284 | | |
| 3285 | | if (res_prec) |
| 3286 | | { |
| 3287 | | m_M[0].val.d = dbl_tmp_dest_mul; |
| 3288 | | m_M[0].stat.mrp = 1; |
| 3289 | | } |
| 3290 | | else |
| 3291 | | { |
| 3292 | | m_M[0].val.s = sgl_tmp_dest_mul; |
| 3293 | | m_M[0].stat.mrp = 0; |
| 3294 | | } |
| 3295 | | |
| 3296 | | /* FIXME: Set result-status bits besides ARP. And copy to fsr from |
| 3297 | | last stage. */ |
| 3298 | | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 3299 | | /* Copy 3rd stage ARP to FSR. */ |
| 3300 | | if (m_A[1 /* 2 */].stat.arp) |
| 3301 | | m_cregs[CR_FSR] |= 0x20000000; |
| 3302 | | else |
| 3303 | | m_cregs[CR_FSR] &= ~0x20000000; |
| 3304 | | #endif |
| 3305 | | |
| 3306 | | /* Now advance adder pipeline and write current calculation to |
| 3307 | | first stage. */ |
| 3308 | | m_A[2] = m_A[1]; |
| 3309 | | m_A[1] = m_A[0]; |
| 3310 | | if (res_prec) |
| 3311 | | { |
| 3312 | | m_A[0].val.d = dbl_tmp_dest_add; |
| 3313 | | m_A[0].stat.arp = 1; |
| 3314 | | } |
| 3315 | | else |
| 3316 | | { |
| 3317 | | m_A[0].val.s = sgl_tmp_dest_add; |
| 3318 | | m_A[0].stat.arp = 0; |
| 3319 | | } |
| 3320 | | } |
| 3321 | | |
| 3322 | | |
| 3323 | | /* Execute frcp.{ss,sd,dd} fsrc2,fdest (.ds disallowed above). */ |
| 3324 | | void i860_cpu_device::insn_frcp (UINT32 insn) |
| 3325 | | { |
| 3326 | | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3327 | | UINT32 fdest = get_fdest (insn); |
| 3328 | | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3329 | | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 3330 | | |
| 3331 | | /* Do the operation, being careful about source and result |
| 3332 | | precision. */ |
| 3333 | | if (src_prec) |
| 3334 | | { |
| 3335 | | double v = get_fregval_d (fsrc2); |
| 3336 | | double res; |
| 3337 | | if (v == (double)0.0) |
| 3338 | | { |
| 3339 | | /* Generate source-exception trap if fsrc2 is 0. */ |
| 3340 | | if (0 /* && GET_FSR_FTE () */) |
| 3341 | | { |
| 3342 | | SET_PSR_FT (1); |
| 3343 | | SET_FSR_SE (1); |
| 3344 | | m_pending_trap = GET_FSR_FTE (); |
| 3345 | | } |
| 3346 | | /* Set fdest to INF or some other exceptional value here? */ |
| 3347 | | } |
| 3348 | | else |
| 3349 | | { |
| 3350 | | /* Real i860 isn't a precise as a real divide, but this should |
| 3351 | | be okay. */ |
| 3352 | | SET_FSR_SE (0); |
| 3353 | | *((UINT64 *)&v) &= 0xfffff00000000000ULL; |
| 3354 | | res = (double)1.0/v; |
| 3355 | | *((UINT64 *)&res) &= 0xfffff00000000000ULL; |
| 3356 | | if (res_prec) |
| 3357 | | set_fregval_d (fdest, res); |
| 3358 | | else |
| 3359 | | set_fregval_s (fdest, (float)res); |
| 3360 | | } |
| 3361 | | } |
| 3362 | | else |
| 3363 | | { |
| 3364 | | float v = get_fregval_s (fsrc2); |
| 3365 | | float res; |
| 3366 | | if (v == 0.0) |
| 3367 | | { |
| 3368 | | /* Generate source-exception trap if fsrc2 is 0. */ |
| 3369 | | if (0 /* GET_FSR_FTE () */) |
| 3370 | | { |
| 3371 | | SET_PSR_FT (1); |
| 3372 | | SET_FSR_SE (1); |
| 3373 | | m_pending_trap = GET_FSR_FTE (); |
| 3374 | | } |
| 3375 | | /* Set fdest to INF or some other exceptional value here? */ |
| 3376 | | } |
| 3377 | | else |
| 3378 | | { |
| 3379 | | /* Real i860 isn't a precise as a real divide, but this should |
| 3380 | | be okay. */ |
| 3381 | | SET_FSR_SE (0); |
| 3382 | | *((UINT32 *)&v) &= 0xffff8000; |
| 3383 | | res = (float)1.0/v; |
| 3384 | | *((UINT32 *)&res) &= 0xffff8000; |
| 3385 | | if (res_prec) |
| 3386 | | set_fregval_d (fdest, (double)res); |
| 3387 | | else |
| 3388 | | set_fregval_s (fdest, res); |
| 3389 | | } |
| 3390 | | } |
| 3391 | | } |
| 3392 | | |
| 3393 | | |
| 3394 | | /* Execute frsqr.{ss,sd,dd} fsrc2,fdest (.ds disallowed above). */ |
| 3395 | | void i860_cpu_device::insn_frsqr (UINT32 insn) |
| 3396 | | { |
| 3397 | | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3398 | | UINT32 fdest = get_fdest (insn); |
| 3399 | | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3400 | | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 3401 | | |
| 3402 | | /* Check for invalid .ds combination. */ |
| 3403 | | if ((insn & 0x180) == 0x100) |
| 3404 | | { |
| 3405 | | unrecog_opcode (m_pc, insn); |
| 3406 | | return; |
| 3407 | | } |
| 3408 | | |
| 3409 | | /* Check for invalid .ds combination. */ |
| 3410 | | if ((insn & 0x180) == 0x100) |
| 3411 | | { |
| 3412 | | unrecog_opcode (m_pc, insn); |
| 3413 | | return; |
| 3414 | | } |
| 3415 | | |
| 3416 | | /* Do the operation, being careful about source and result |
| 3417 | | precision. */ |
| 3418 | | if (src_prec) |
| 3419 | | { |
| 3420 | | double v = get_fregval_d (fsrc2); |
| 3421 | | double res; |
| 3422 | | if (v == 0.0 || v < 0.0) |
| 3423 | | { |
| 3424 | | /* Generate source-exception trap if fsrc2 is 0 or negative. */ |
| 3425 | | if (0 /* GET_FSR_FTE () */) |
| 3426 | | { |
| 3427 | | SET_PSR_FT (1); |
| 3428 | | SET_FSR_SE (1); |
| 3429 | | m_pending_trap = GET_FSR_FTE (); |
| 3430 | | } |
| 3431 | | /* Set fdest to INF or some other exceptional value here? */ |
| 3432 | | } |
| 3433 | | else |
| 3434 | | { |
| 3435 | | SET_FSR_SE (0); |
| 3436 | | *((UINT64 *)&v) &= 0xfffff00000000000ULL; |
| 3437 | | res = (double)1.0/sqrt (v); |
| 3438 | | *((UINT64 *)&res) &= 0xfffff00000000000ULL; |
| 3439 | | if (res_prec) |
| 3440 | | set_fregval_d (fdest, res); |
| 3441 | | else |
| 3442 | | set_fregval_s (fdest, (float)res); |
| 3443 | | } |
| 3444 | | } |
| 3445 | | else |
| 3446 | | { |
| 3447 | | float v = get_fregval_s (fsrc2); |
| 3448 | | float res; |
| 3449 | | if (v == 0.0 || v < 0.0) |
| 3450 | | { |
| 3451 | | /* Generate source-exception trap if fsrc2 is 0 or negative. */ |
| 3452 | | if (0 /* GET_FSR_FTE () */) |
| 3453 | | { |
| 3454 | | SET_PSR_FT (1); |
| 3455 | | SET_FSR_SE (1); |
| 3456 | | m_pending_trap = GET_FSR_FTE (); |
| 3457 | | } |
| 3458 | | /* Set fdest to INF or some other exceptional value here? */ |
| 3459 | | } |
| 3460 | | else |
| 3461 | | { |
| 3462 | | SET_FSR_SE (0); |
| 3463 | | *((UINT32 *)&v) &= 0xffff8000; |
| 3464 | | res = (float)1.0/sqrt (v); |
| 3465 | | *((UINT32 *)&res) &= 0xffff8000; |
| 3466 | | if (res_prec) |
| 3467 | | set_fregval_d (fdest, (double)res); |
| 3468 | | else |
| 3469 | | set_fregval_s (fdest, res); |
| 3470 | | } |
| 3471 | | } |
| 3472 | | } |
| 3473 | | |
| 3474 | | |
| 3475 | | /* Execute fxfr fsrc1,idest. */ |
| 3476 | | void i860_cpu_device::insn_fxfr (UINT32 insn) |
| 3477 | | { |
| 3478 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3479 | | UINT32 idest = get_idest (insn); |
| 3480 | | float fv = 0; |
| 3481 | | |
| 3482 | | /* This is a bit-pattern transfer, not a conversion. */ |
| 3483 | | fv = get_fregval_s (fsrc1); |
| 3484 | | set_iregval (idest, *(UINT32 *)&fv); |
| 3485 | | } |
| 3486 | | |
| 3487 | | |
| 3488 | | /* Execute [p]ftrunc.{ss,sd,dd} fsrc1,idest. */ |
| 3489 | | /* FIXME: Is .ss really a valid combination? On the one hand, |
| 3490 | | the programmer's reference (1990) lists ftrunc.p where .p |
| 3491 | | is any of {ss,sd,dd}. On the other hand, a paragraph on the |
| 3492 | | same page states that [p]ftrunc must specify double-precision |
| 3493 | | results. Inconsistent. |
| 3494 | | Update: The vendor SVR4 assembler does not accept .ss combination, |
| 3495 | | so the latter sentence above appears to be the correct way. */ |
| 3496 | | void i860_cpu_device::insn_ftrunc (UINT32 insn) |
| 3497 | | { |
| 3498 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3499 | | UINT32 fdest = get_fdest (insn); |
| 3500 | | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3501 | | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 3502 | | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 3503 | | |
| 3504 | | /* Check for invalid .ds or .ss combinations. */ |
| 3505 | | if ((insn & 0x080) == 0) |
| 3506 | | { |
| 3507 | | unrecog_opcode (m_pc, insn); |
| 3508 | | return; |
| 3509 | | } |
| 3510 | | |
| 3511 | | /* Do the operation, being careful about source and result |
| 3512 | | precision. Operation: fdest = integer part of fsrc1 in |
| 3513 | | lower 32-bits. */ |
| 3514 | | if (src_prec) |
| 3515 | | { |
| 3516 | | double v1 = get_fregval_d (fsrc1); |
| 3517 | | INT32 iv = (INT32)v1; |
| 3518 | | /* We always write a single, since the lower 32-bits of fdest |
| 3519 | | get the result (and the even numbered reg is the lower). */ |
| 3520 | | set_fregval_s (fdest, *(float *)&iv); |
| 3521 | | } |
| 3522 | | else |
| 3523 | | { |
| 3524 | | float v1 = get_fregval_s (fsrc1); |
| 3525 | | INT32 iv = (INT32)v1; |
| 3526 | | /* We always write a single, since the lower 32-bits of fdest |
| 3527 | | get the result (and the even numbered reg is the lower). */ |
| 3528 | | set_fregval_s (fdest, *(float *)&iv); |
| 3529 | | } |
| 3530 | | |
| 3531 | | /* FIXME: Handle updating of pipestages for pftrunc. */ |
| 3532 | | /* Includes looking at ARP (add result precision.) */ |
| 3533 | | if (piped) |
| 3534 | | { |
| 3535 | | fprintf (stderr, "insn_ftrunc: FIXME: pipelined not functional yet.\n"); |
| 3536 | | if (res_prec) |
| 3537 | | set_fregval_d (fdest, 0.0); |
| 3538 | | else |
| 3539 | | set_fregval_s (fdest, 0.0); |
| 3540 | | } |
| 3541 | | } |
| 3542 | | |
| 3543 | | |
| 3544 | | /* Execute [p]famov.{ss,sd,ds,dd} fsrc1,fdest. */ |
| 3545 | | void i860_cpu_device::insn_famov (UINT32 insn) |
| 3546 | | { |
| 3547 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3548 | | UINT32 fdest = get_fdest (insn); |
| 3549 | | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3550 | | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 3551 | | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 3552 | | double dbl_tmp_dest = 0.0; |
| 3553 | | double sgl_tmp_dest = 0.0; |
| 3554 | | |
| 3555 | | /* Do the operation, being careful about source and result |
| 3556 | | precision. */ |
| 3557 | | if (src_prec) |
| 3558 | | { |
| 3559 | | double v1 = get_fregval_d (fsrc1); |
| 3560 | | if (res_prec) |
| 3561 | | dbl_tmp_dest = v1; |
| 3562 | | else |
| 3563 | | sgl_tmp_dest = (float)v1; |
| 3564 | | } |
| 3565 | | else |
| 3566 | | { |
| 3567 | | float v1 = get_fregval_s (fsrc1); |
| 3568 | | if (res_prec) |
| 3569 | | dbl_tmp_dest = (double)v1; |
| 3570 | | else |
| 3571 | | sgl_tmp_dest = v1; |
| 3572 | | } |
| 3573 | | |
| 3574 | | /* FIXME: Set result-status bits besides ARP. And copy to fsr from |
| 3575 | | last stage. */ |
| 3576 | | /* FIXME: Scalar version flows through all stages. */ |
| 3577 | | if (!piped) |
| 3578 | | { |
| 3579 | | /* Scalar version writes the current calculation to the fdest |
| 3580 | | register, with precision specified by the R bit. */ |
| 3581 | | if (res_prec) |
| 3582 | | set_fregval_d (fdest, dbl_tmp_dest); |
| 3583 | | else |
| 3584 | | set_fregval_s (fdest, sgl_tmp_dest); |
| 3585 | | } |
| 3586 | | else |
| 3587 | | { |
| 3588 | | /* Pipelined version writes fdest with the result from the last |
| 3589 | | stage of the pipeline, with precision specified by the ARP |
| 3590 | | bit of the stage's result-status bits. */ |
| 3591 | | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 3592 | | /* Copy 3rd stage ARP to FSR. */ |
| 3593 | | if (m_A[1 /* 2 */].stat.arp) |
| 3594 | | m_cregs[CR_FSR] |= 0x20000000; |
| 3595 | | else |
| 3596 | | m_cregs[CR_FSR] &= ~0x20000000; |
| 3597 | | #endif |
| 3598 | | if (m_A[2].stat.arp) /* 3rd (last) stage. */ |
| 3599 | | set_fregval_d (fdest, m_A[2].val.d); |
| 3600 | | else |
| 3601 | | set_fregval_s (fdest, m_A[2].val.s); |
| 3602 | | |
| 3603 | | /* Now advance pipeline and write current calculation to |
| 3604 | | first stage. */ |
| 3605 | | m_A[2] = m_A[1]; |
| 3606 | | m_A[1] = m_A[0]; |
| 3607 | | if (res_prec) |
| 3608 | | { |
| 3609 | | m_A[0].val.d = dbl_tmp_dest; |
| 3610 | | m_A[0].stat.arp = 1; |
| 3611 | | } |
| 3612 | | else |
| 3613 | | { |
| 3614 | | m_A[0].val.s = sgl_tmp_dest; |
| 3615 | | m_A[0].stat.arp = 0; |
| 3616 | | } |
| 3617 | | } |
| 3618 | | } |
| 3619 | | |
| 3620 | | |
| 3621 | | /* Execute [p]fiadd/sub.{ss,dd} fsrc1,fsrc2,fdest. */ |
| 3622 | | void i860_cpu_device::insn_fiadd_sub (UINT32 insn) |
| 3623 | | { |
| 3624 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3625 | | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3626 | | UINT32 fdest = get_fdest (insn); |
| 3627 | | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3628 | | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 3629 | | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 3630 | | int is_sub = insn & 0x4; /* 1 = sub, 0 = add. */ |
| 3631 | | double dbl_tmp_dest = 0.0; |
| 3632 | | float sgl_tmp_dest = 0.0; |
| 3633 | | |
| 3634 | | /* Check for invalid .ds and .sd combinations. */ |
| 3635 | | if ((insn & 0x180) == 0x100 |
| 3636 | | || (insn & 0x180) == 0x080) |
| 3637 | | { |
| 3638 | | unrecog_opcode (m_pc, insn); |
| 3639 | | return; |
| 3640 | | } |
| 3641 | | |
| 3642 | | /* Do the operation, being careful about source and result |
| 3643 | | precision. */ |
| 3644 | | if (src_prec) |
| 3645 | | { |
| 3646 | | double v1 = get_fregval_d (fsrc1); |
| 3647 | | double v2 = get_fregval_d (fsrc2); |
| 3648 | | UINT64 iv1 = *(UINT64 *)&v1; |
| 3649 | | UINT64 iv2 = *(UINT64 *)&v2; |
| 3650 | | UINT64 r; |
| 3651 | | if (is_sub) |
| 3652 | | r = iv1 - iv2; |
| 3653 | | else |
| 3654 | | r = iv1 + iv2; |
| 3655 | | if (res_prec) |
| 3656 | | dbl_tmp_dest = *(double *)&r; |
| 3657 | | else |
| 3658 | | assert (0); /* .ds not allowed. */ |
| 3659 | | } |
| 3660 | | else |
| 3661 | | { |
| 3662 | | float v1 = get_fregval_s (fsrc1); |
| 3663 | | float v2 = get_fregval_s (fsrc2); |
| 3664 | | UINT64 iv1 = (UINT64)(*(UINT32 *)&v1); |
| 3665 | | UINT64 iv2 = (UINT64)(*(UINT32 *)&v2); |
| 3666 | | UINT32 r; |
| 3667 | | if (is_sub) |
| 3668 | | r = (UINT32)(iv1 - iv2); |
| 3669 | | else |
| 3670 | | r = (UINT32)(iv1 + iv2); |
| 3671 | | if (res_prec) |
| 3672 | | assert (0); /* .sd not allowed. */ |
| 3673 | | else |
| 3674 | | sgl_tmp_dest = *(float *)&r; |
| 3675 | | } |
| 3676 | | |
| 3677 | | /* FIXME: Copy result-status bit IRP to fsr from last stage. */ |
| 3678 | | /* FIXME: Scalar version flows through all stages. */ |
| 3679 | | if (!piped) |
| 3680 | | { |
| 3681 | | /* Scalar version writes the current calculation to the fdest |
| 3682 | | register, with precision specified by the R bit. */ |
| 3683 | | if (res_prec) |
| 3684 | | set_fregval_d (fdest, dbl_tmp_dest); |
| 3685 | | else |
| 3686 | | set_fregval_s (fdest, sgl_tmp_dest); |
| 3687 | | } |
| 3688 | | else |
| 3689 | | { |
| 3690 | | /* Pipelined version writes fdest with the result from the last |
| 3691 | | stage of the pipeline, with precision specified by the IRP |
| 3692 | | bit of the stage's result-status bits. */ |
| 3693 | | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 3694 | | /* Copy stage IRP to FSR. */ |
| 3695 | | if (res_prec) |
| 3696 | | m_cregs[CR_FSR] |= 0x08000000; |
| 3697 | | else |
| 3698 | | m_cregs[CR_FSR] &= ~0x08000000; |
| 3699 | | #endif |
| 3700 | | if (m_G.stat.irp) /* 1st (and last) stage. */ |
| 3701 | | set_fregval_d (fdest, m_G.val.d); |
| 3702 | | else |
| 3703 | | set_fregval_s (fdest, m_G.val.s); |
| 3704 | | |
| 3705 | | /* Now write current calculation to first and only stage. */ |
| 3706 | | if (res_prec) |
| 3707 | | { |
| 3708 | | m_G.val.d = dbl_tmp_dest; |
| 3709 | | m_G.stat.irp = 1; |
| 3710 | | } |
| 3711 | | else |
| 3712 | | { |
| 3713 | | m_G.val.s = sgl_tmp_dest; |
| 3714 | | m_G.stat.irp = 0; |
| 3715 | | } |
| 3716 | | } |
| 3717 | | } |
| 3718 | | |
| 3719 | | |
| 3720 | | /* Execute pf{gt,le,eq}.{ss,dd} fsrc1,fsrc2,fdest. |
| 3721 | | Opcode pfgt has R bit cleared; pfle has R bit set. */ |
| 3722 | | void i860_cpu_device::insn_fcmp (UINT32 insn) |
| 3723 | | { |
| 3724 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3725 | | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3726 | | UINT32 fdest = get_fdest (insn); |
| 3727 | | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3728 | | double dbl_tmp_dest = 0.0; |
| 3729 | | double sgl_tmp_dest = 0.0; |
| 3730 | | /* int is_eq = insn & 1; */ |
| 3731 | | int is_gt = ((insn & 0x81) == 0x00); |
| 3732 | | int is_le = ((insn & 0x81) == 0x80); |
| 3733 | | |
| 3734 | | /* Do the operation. Source and result precision must be the same. |
| 3735 | | pfgt: CC set if fsrc1 > fsrc2, else cleared. |
| 3736 | | pfle: CC cleared if fsrc1 <= fsrc2, else set. |
| 3737 | | pfeq: CC set if fsrc1 = fsrc2, else cleared. |
| 3738 | | |
| 3739 | | Note that the compares write an undefined (but non-exceptional) |
| 3740 | | result into the first stage of the adder pipeline. We'll model |
| 3741 | | this by just pushing in dbl_ or sgl_tmp_dest which equal 0.0. */ |
| 3742 | | if (src_prec) |
| 3743 | | { |
| 3744 | | double v1 = get_fregval_d (fsrc1); |
| 3745 | | double v2 = get_fregval_d (fsrc2); |
| 3746 | | if (is_gt) /* gt. */ |
| 3747 | | SET_PSR_CC (v1 > v2 ? 1 : 0); |
| 3748 | | else if (is_le) /* le. */ |
| 3749 | | SET_PSR_CC (v1 <= v2 ? 0 : 1); |
| 3750 | | else /* eq. */ |
| 3751 | | SET_PSR_CC (v1 == v2 ? 1 : 0); |
| 3752 | | } |
| 3753 | | else |
| 3754 | | { |
| 3755 | | float v1 = get_fregval_s (fsrc1); |
| 3756 | | float v2 = get_fregval_s (fsrc2); |
| 3757 | | if (is_gt) /* gt. */ |
| 3758 | | SET_PSR_CC (v1 > v2 ? 1 : 0); |
| 3759 | | else if (is_le) /* le. */ |
| 3760 | | SET_PSR_CC (v1 <= v2 ? 0 : 1); |
| 3761 | | else /* eq. */ |
| 3762 | | SET_PSR_CC (v1 == v2 ? 1 : 0); |
| 3763 | | } |
| 3764 | | |
| 3765 | | /* FIXME: Set result-status bits besides ARP. And copy to fsr from |
| 3766 | | last stage. */ |
| 3767 | | /* These write fdest with the result from the last |
| 3768 | | stage of the pipeline, with precision specified by the ARP |
| 3769 | | bit of the stage's result-status bits. */ |
| 3770 | | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 3771 | | /* Copy 3rd stage ARP to FSR. */ |
| 3772 | | if (m_A[1 /* 2 */].stat.arp) |
| 3773 | | m_cregs[CR_FSR] |= 0x20000000; |
| 3774 | | else |
| 3775 | | m_cregs[CR_FSR] &= ~0x20000000; |
| 3776 | | #endif |
| 3777 | | if (m_A[2].stat.arp) /* 3rd (last) stage. */ |
| 3778 | | set_fregval_d (fdest, m_A[2].val.d); |
| 3779 | | else |
| 3780 | | set_fregval_s (fdest, m_A[2].val.s); |
| 3781 | | |
| 3782 | | /* Now advance pipeline and write current calculation to |
| 3783 | | first stage. */ |
| 3784 | | m_A[2] = m_A[1]; |
| 3785 | | m_A[1] = m_A[0]; |
| 3786 | | if (src_prec) |
| 3787 | | { |
| 3788 | | m_A[0].val.d = dbl_tmp_dest; |
| 3789 | | m_A[0].stat.arp = 1; |
| 3790 | | } |
| 3791 | | else |
| 3792 | | { |
| 3793 | | m_A[0].val.s = sgl_tmp_dest; |
| 3794 | | m_A[0].stat.arp = 0; |
| 3795 | | } |
| 3796 | | } |
| 3797 | | |
| 3798 | | |
| 3799 | | /* Execute [p]fzchk{l,s} fsrc1,fsrc2,fdest. |
| 3800 | | The fzchk instructions have S and R bits set. */ |
| 3801 | | void i860_cpu_device::insn_fzchk (UINT32 insn) |
| 3802 | | { |
| 3803 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3804 | | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3805 | | UINT32 fdest = get_fdest (insn); |
| 3806 | | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 3807 | | int is_fzchks = insn & 8; /* 1 = fzchks, 0 = fzchkl. */ |
| 3808 | | double dbl_tmp_dest = 0.0; |
| 3809 | | int i; |
| 3810 | | double v1 = get_fregval_d (fsrc1); |
| 3811 | | double v2 = get_fregval_d (fsrc2); |
| 3812 | | UINT64 iv1 = *(UINT64 *)&v1; |
| 3813 | | UINT64 iv2 = *(UINT64 *)&v2; |
| 3814 | | UINT64 r = 0; |
| 3815 | | char pm = GET_PSR_PM (); |
| 3816 | | |
| 3817 | | /* Check for S and R bits set. */ |
| 3818 | | if ((insn & 0x180) != 0x180) |
| 3819 | | { |
| 3820 | | unrecog_opcode (m_pc, insn); |
| 3821 | | return; |
| 3822 | | } |
| 3823 | | |
| 3824 | | /* Do the operation. The fzchks version operates in parallel on |
| 3825 | | four 16-bit pixels, while the fzchkl operates on two 32-bit |
| 3826 | | pixels (pixels are unsigned ordinals in this context). */ |
| 3827 | | if (is_fzchks) |
| 3828 | | { |
| 3829 | | pm = (pm >> 4) & 0x0f; |
| 3830 | | for (i = 3; i >= 0; i--) |
| 3831 | | { |
| 3832 | | UINT16 ps1 = (iv1 >> (i * 16)) & 0xffff; |
| 3833 | | UINT16 ps2 = (iv2 >> (i * 16)) & 0xffff; |
| 3834 | | if (ps2 <= ps1) |
| 3835 | | { |
| 3836 | | r |= ((UINT64)ps2 << (i * 16)); |
| 3837 | | pm |= (1 << (7 - (3 - i))); |
| 3838 | | } |
| 3839 | | else |
| 3840 | | { |
| 3841 | | r |= ((UINT64)ps1 << (i * 16)); |
| 3842 | | pm &= ~(1 << (7 - (3 - i))); |
| 3843 | | } |
| 3844 | | } |
| 3845 | | } |
| 3846 | | else |
| 3847 | | { |
| 3848 | | pm = (pm >> 2) & 0x3f; |
| 3849 | | for (i = 1; i >= 0; i--) |
| 3850 | | { |
| 3851 | | UINT32 ps1 = (iv1 >> (i * 32)) & 0xffffffff; |
| 3852 | | UINT32 ps2 = (iv2 >> (i * 32)) & 0xffffffff; |
| 3853 | | if (ps2 <= ps1) |
| 3854 | | { |
| 3855 | | r |= ((UINT64)ps2 << (i * 32)); |
| 3856 | | pm |= (1 << (7 - (1 - i))); |
| 3857 | | } |
| 3858 | | else |
| 3859 | | { |
| 3860 | | r |= ((UINT64)ps1 << (i * 32)); |
| 3861 | | pm &= ~(1 << (7 - (1 - i))); |
| 3862 | | } |
| 3863 | | } |
| 3864 | | } |
| 3865 | | |
| 3866 | | dbl_tmp_dest = *(double *)&r; |
| 3867 | | SET_PSR_PM (pm); |
| 3868 | | m_merge = 0; |
| 3869 | | |
| 3870 | | /* FIXME: Copy result-status bit IRP to fsr from last stage. */ |
| 3871 | | /* FIXME: Scalar version flows through all stages. */ |
| 3872 | | if (!piped) |
| 3873 | | { |
| 3874 | | /* Scalar version writes the current calculation to the fdest |
| 3875 | | register, always with double precision. */ |
| 3876 | | set_fregval_d (fdest, dbl_tmp_dest); |
| 3877 | | } |
| 3878 | | else |
| 3879 | | { |
| 3880 | | /* Pipelined version writes fdest with the result from the last |
| 3881 | | stage of the pipeline, with precision specified by the IRP |
| 3882 | | bit of the stage's result-status bits. */ |
| 3883 | | if (m_G.stat.irp) /* 1st (and last) stage. */ |
| 3884 | | set_fregval_d (fdest, m_G.val.d); |
| 3885 | | else |
| 3886 | | set_fregval_s (fdest, m_G.val.s); |
| 3887 | | |
| 3888 | | /* Now write current calculation to first and only stage. */ |
| 3889 | | m_G.val.d = dbl_tmp_dest; |
| 3890 | | m_G.stat.irp = 1; |
| 3891 | | } |
| 3892 | | } |
| 3893 | | |
| 3894 | | |
| 3895 | | /* Execute [p]form.dd fsrc1,fdest. |
| 3896 | | The form.dd instructions have S and R bits set. */ |
| 3897 | | void i860_cpu_device::insn_form (UINT32 insn) |
| 3898 | | { |
| 3899 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3900 | | UINT32 fdest = get_fdest (insn); |
| 3901 | | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 3902 | | double dbl_tmp_dest = 0.0; |
| 3903 | | double v1 = get_fregval_d (fsrc1); |
| 3904 | | UINT64 iv1 = *(UINT64 *)&v1; |
| 3905 | | |
| 3906 | | /* Check for S and R bits set. */ |
| 3907 | | if ((insn & 0x180) != 0x180) |
| 3908 | | { |
| 3909 | | unrecog_opcode (m_pc, insn); |
| 3910 | | return; |
| 3911 | | } |
| 3912 | | |
| 3913 | | iv1 |= m_merge; |
| 3914 | | dbl_tmp_dest = *(double *)&iv1; |
| 3915 | | m_merge = 0; |
| 3916 | | |
| 3917 | | /* FIXME: Copy result-status bit IRP to fsr from last stage. */ |
| 3918 | | /* FIXME: Scalar version flows through all stages. */ |
| 3919 | | if (!piped) |
| 3920 | | { |
| 3921 | | /* Scalar version writes the current calculation to the fdest |
| 3922 | | register, always with double precision. */ |
| 3923 | | set_fregval_d (fdest, dbl_tmp_dest); |
| 3924 | | } |
| 3925 | | else |
| 3926 | | { |
| 3927 | | /* Pipelined version writes fdest with the result from the last |
| 3928 | | stage of the pipeline, with precision specified by the IRP |
| 3929 | | bit of the stage's result-status bits. */ |
| 3930 | | if (m_G.stat.irp) /* 1st (and last) stage. */ |
| 3931 | | set_fregval_d (fdest, m_G.val.d); |
| 3932 | | else |
| 3933 | | set_fregval_s (fdest, m_G.val.s); |
| 3934 | | |
| 3935 | | /* Now write current calculation to first and only stage. */ |
| 3936 | | m_G.val.d = dbl_tmp_dest; |
| 3937 | | m_G.stat.irp = 1; |
| 3938 | | } |
| 3939 | | } |
| 3940 | | |
| 3941 | | |
| 3942 | | /* Execute [p]faddp fsrc1,fsrc2,fdest. */ |
| 3943 | | void i860_cpu_device::insn_faddp (UINT32 insn) |
| 3944 | | { |
| 3945 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3946 | | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3947 | | UINT32 fdest = get_fdest (insn); |
| 3948 | | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 3949 | | double dbl_tmp_dest = 0.0; |
| 3950 | | double v1 = get_fregval_d (fsrc1); |
| 3951 | | double v2 = get_fregval_d (fsrc2); |
| 3952 | | UINT64 iv1 = *(UINT64 *)&v1; |
| 3953 | | UINT64 iv2 = *(UINT64 *)&v2; |
| 3954 | | UINT64 r = 0; |
| 3955 | | int ps = GET_PSR_PS (); |
| 3956 | | |
| 3957 | | r = iv1 + iv2; |
| 3958 | | dbl_tmp_dest = *(double *)&r; |
| 3959 | | |
| 3960 | | /* Update the merge register depending on the pixel size. |
| 3961 | | PS: 0 = 8 bits, 1 = 16 bits, 2 = 32-bits. */ |
| 3962 | | if (ps == 0) |
| 3963 | | { |
| 3964 | | m_merge = ((m_merge >> 8) & ~0xff00ff00ff00ff00ULL); |
| 3965 | | m_merge |= (r & 0xff00ff00ff00ff00ULL); |
| 3966 | | } |
| 3967 | | else if (ps == 1) |
| 3968 | | { |
| 3969 | | m_merge = ((m_merge >> 6) & ~0xfc00fc00fc00fc00ULL); |
| 3970 | | m_merge |= (r & 0xfc00fc00fc00fc00ULL); |
| 3971 | | } |
| 3972 | | else if (ps == 2) |
| 3973 | | { |
| 3974 | | m_merge = ((m_merge >> 8) & ~0xff000000ff000000ULL); |
| 3975 | | m_merge |= (r & 0xff000000ff000000ULL); |
| 3976 | | } |
| 3977 | | #ifdef TRACE_UNDEFINED_I860 |
| 3978 | | else |
| 3979 | | fprintf (stderr, "insn_faddp: Undefined i860XR behavior, invalid value %d for pixel size.\n", ps); |
| 3980 | | #endif |
| 3981 | | |
| 3982 | | /* FIXME: Copy result-status bit IRP to fsr from last stage. */ |
| 3983 | | /* FIXME: Scalar version flows through all stages. */ |
| 3984 | | if (!piped) |
| 3985 | | { |
| 3986 | | /* Scalar version writes the current calculation to the fdest |
| 3987 | | register, always with double precision. */ |
| 3988 | | set_fregval_d (fdest, dbl_tmp_dest); |
| 3989 | | } |
| 3990 | | else |
| 3991 | | { |
| 3992 | | /* Pipelined version writes fdest with the result from the last |
| 3993 | | stage of the pipeline, with precision specified by the IRP |
| 3994 | | bit of the stage's result-status bits. */ |
| 3995 | | if (m_G.stat.irp) /* 1st (and last) stage. */ |
| 3996 | | set_fregval_d (fdest, m_G.val.d); |
| 3997 | | else |
| 3998 | | set_fregval_s (fdest, m_G.val.s); |
| 3999 | | |
| 4000 | | /* Now write current calculation to first and only stage. */ |
| 4001 | | m_G.val.d = dbl_tmp_dest; |
| 4002 | | m_G.stat.irp = 1; |
| 4003 | | } |
| 4004 | | } |
| 4005 | | |
| 4006 | | |
| 4007 | | /* Execute [p]faddz fsrc1,fsrc2,fdest. */ |
| 4008 | | void i860_cpu_device::insn_faddz (UINT32 insn) |
| 4009 | | { |
| 4010 | | UINT32 fsrc1 = get_fsrc1 (insn); |
| 4011 | | UINT32 fsrc2 = get_fsrc2 (insn); |
| 4012 | | UINT32 fdest = get_fdest (insn); |
| 4013 | | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 4014 | | double dbl_tmp_dest = 0.0; |
| 4015 | | double v1 = get_fregval_d (fsrc1); |
| 4016 | | double v2 = get_fregval_d (fsrc2); |
| 4017 | | UINT64 iv1 = *(UINT64 *)&v1; |
| 4018 | | UINT64 iv2 = *(UINT64 *)&v2; |
| 4019 | | UINT64 r = 0; |
| 4020 | | |
| 4021 | | r = iv1 + iv2; |
| 4022 | | dbl_tmp_dest = *(double *)&r; |
| 4023 | | |
| 4024 | | /* Update the merge register depending on the pixel size. */ |
| 4025 | | m_merge = ((m_merge >> 16) & ~0xffff0000ffff0000ULL); |
| 4026 | | m_merge |= (r & 0xffff0000ffff0000ULL); |
| 4027 | | |
| 4028 | | /* FIXME: Copy result-status bit IRP to fsr from last stage. */ |
| 4029 | | /* FIXME: Scalar version flows through all stages. */ |
| 4030 | | if (!piped) |
| 4031 | | { |
| 4032 | | /* Scalar version writes the current calculation to the fdest |
| 4033 | | register, always with double precision. */ |
| 4034 | | set_fregval_d (fdest, dbl_tmp_dest); |
| 4035 | | } |
| 4036 | | else |
| 4037 | | { |
| 4038 | | /* Pipelined version writes fdest with the result from the last |
| 4039 | | stage of the pipeline, with precision specified by the IRP |
| 4040 | | bit of the stage's result-status bits. */ |
| 4041 | | if (m_G.stat.irp) /* 1st (and last) stage. */ |
| 4042 | | set_fregval_d (fdest, m_G.val.d); |
| 4043 | | else |
| 4044 | | set_fregval_s (fdest, m_G.val.s); |
| 4045 | | |
| 4046 | | /* Now write current calculation to first and only stage. */ |
| 4047 | | m_G.val.d = dbl_tmp_dest; |
| 4048 | | m_G.stat.irp = 1; |
| 4049 | | } |
| 4050 | | } |
| 4051 | | |
| 4052 | | |
| 4053 | | /* Flags for the decode table. */ |
| 4054 | | enum { |
| 4055 | | DEC_MORE = 1, /* More decoding necessary. */ |
| 4056 | | DEC_DECODED = 2 /* Fully decoded, go. */ |
| 4057 | | }; |
| 4058 | | |
| 4059 | | |
| 4060 | | /* First-level decode table (i.e., for the 6 primary opcode bits). */ |
| 4061 | | const i860_cpu_device::decode_tbl_t i860_cpu_device::decode_tbl[64] = { |
| 4062 | | /* A slight bit of decoding for loads and stores is done in the |
| 4063 | | execution routines (operand size and addressing mode), which |
| 4064 | | is why their respective entries are identical. */ |
| 4065 | | { &i860_cpu_device::insn_ldx, DEC_DECODED}, /* ld.b isrc1(isrc2),idest. */ |
| 4066 | | { &i860_cpu_device::insn_ldx, DEC_DECODED}, /* ld.b #const(isrc2),idest. */ |
| 4067 | | { &i860_cpu_device::insn_ixfr, DEC_DECODED}, /* ixfr isrc1ni,fdest. */ |
| 4068 | | { &i860_cpu_device::insn_stx, DEC_DECODED}, /* st.b isrc1ni,#const(isrc2). */ |
| 4069 | | { &i860_cpu_device::insn_ldx, DEC_DECODED}, /* ld.{s,l} isrc1(isrc2),idest. */ |
| 4070 | | { &i860_cpu_device::insn_ldx, DEC_DECODED}, /* ld.{s,l} #const(isrc2),idest. */ |
| 4071 | | { 0, 0}, |
| 4072 | | { &i860_cpu_device::insn_stx, DEC_DECODED}, /* st.{s,l} isrc1ni,#const(isrc2),idest.*/ |
| 4073 | | { &i860_cpu_device::insn_fldy, DEC_DECODED}, /* fld.{l,d,q} isrc1(isrc2)[++],fdest. */ |
| 4074 | | { &i860_cpu_device::insn_fldy, DEC_DECODED}, /* fld.{l,d,q} #const(isrc2)[++],fdest. */ |
| 4075 | | { &i860_cpu_device::insn_fsty, DEC_DECODED}, /* fst.{l,d,q} fdest,isrc1(isrc2)[++] */ |
| 4076 | | { &i860_cpu_device::insn_fsty, DEC_DECODED}, /* fst.{l,d,q} fdest,#const(isrc2)[++] */ |
| 4077 | | { &i860_cpu_device::insn_ld_ctrl, DEC_DECODED}, /* ld.c csrc2,idest. */ |
| 4078 | | { &i860_cpu_device::insn_flush, DEC_DECODED}, /* flush #const(isrc2) (or autoinc). */ |
| 4079 | | { &i860_cpu_device::insn_st_ctrl, DEC_DECODED}, /* st.c isrc1,csrc2. */ |
| 4080 | | { &i860_cpu_device::insn_pstd, DEC_DECODED}, /* pst.d fdest,#const(isrc2)[++]. */ |
| 4081 | | { &i860_cpu_device::insn_bri, DEC_DECODED}, /* bri isrc1ni. */ |
| 4082 | | { &i860_cpu_device::insn_trap, DEC_DECODED}, /* trap isrc1ni,isrc2,idest. */ |
| 4083 | | { 0, DEC_MORE}, /* FP ESCAPE FORMAT, more decode. */ |
| 4084 | | { 0, DEC_MORE}, /* CORE ESCAPE FORMAT, more decode. */ |
| 4085 | | { &i860_cpu_device::insn_btne, DEC_DECODED}, /* btne isrc1,isrc2,sbroff. */ |
| 4086 | | { &i860_cpu_device::insn_btne_imm, DEC_DECODED}, /* btne #const,isrc2,sbroff. */ |
| 4087 | | { &i860_cpu_device::insn_bte, DEC_DECODED}, /* bte isrc1,isrc2,sbroff. */ |
| 4088 | | { &i860_cpu_device::insn_bte_imm, DEC_DECODED}, /* bte #const5,isrc2,idest. */ |
| 4089 | | { &i860_cpu_device::insn_fldy, DEC_DECODED}, /* pfld.{l,d,q} isrc1(isrc2)[++],fdest.*/ |
| 4090 | | { &i860_cpu_device::insn_fldy, DEC_DECODED}, /* pfld.{l,d,q} #const(isrc2)[++],fdest.*/ |
| 4091 | | { &i860_cpu_device::insn_br, DEC_DECODED}, /* br lbroff. */ |
| 4092 | | { &i860_cpu_device::insn_call, DEC_DECODED}, /* call lbroff . */ |
| 4093 | | { &i860_cpu_device::insn_bc, DEC_DECODED}, /* bc lbroff. */ |
| 4094 | | { &i860_cpu_device::insn_bct, DEC_DECODED}, /* bc.t lbroff. */ |
| 4095 | | { &i860_cpu_device::insn_bnc, DEC_DECODED}, /* bnc lbroff. */ |
| 4096 | | { &i860_cpu_device::insn_bnct, DEC_DECODED}, /* bnc.t lbroff. */ |
| 4097 | | { &i860_cpu_device::insn_addu, DEC_DECODED}, /* addu isrc1,isrc2,idest. */ |
| 4098 | | { &i860_cpu_device::insn_addu_imm, DEC_DECODED}, /* addu #const,isrc2,idest. */ |
| 4099 | | { &i860_cpu_device::insn_subu, DEC_DECODED}, /* subu isrc1,isrc2,idest. */ |
| 4100 | | { &i860_cpu_device::insn_subu_imm, DEC_DECODED}, /* subu #const,isrc2,idest. */ |
| 4101 | | { &i860_cpu_device::insn_adds, DEC_DECODED}, /* adds isrc1,isrc2,idest. */ |
| 4102 | | { &i860_cpu_device::insn_adds_imm, DEC_DECODED}, /* adds #const,isrc2,idest. */ |
| 4103 | | { &i860_cpu_device::insn_subs, DEC_DECODED}, /* subs isrc1,isrc2,idest. */ |
| 4104 | | { &i860_cpu_device::insn_subs_imm, DEC_DECODED}, /* subs #const,isrc2,idest. */ |
| 4105 | | { &i860_cpu_device::insn_shl, DEC_DECODED}, /* shl isrc1,isrc2,idest. */ |
| 4106 | | { &i860_cpu_device::insn_shl_imm, DEC_DECODED}, /* shl #const,isrc2,idest. */ |
| 4107 | | { &i860_cpu_device::insn_shr, DEC_DECODED}, /* shr isrc1,isrc2,idest. */ |
| 4108 | | { &i860_cpu_device::insn_shr_imm, DEC_DECODED}, /* shr #const,isrc2,idest. */ |
| 4109 | | { &i860_cpu_device::insn_shrd, DEC_DECODED}, /* shrd isrc1ni,isrc2,idest. */ |
| 4110 | | { &i860_cpu_device::insn_bla, DEC_DECODED}, /* bla isrc1ni,isrc2,sbroff. */ |
| 4111 | | { &i860_cpu_device::insn_shra, DEC_DECODED}, /* shra isrc1,isrc2,idest. */ |
| 4112 | | { &i860_cpu_device::insn_shra_imm, DEC_DECODED}, /* shra #const,isrc2,idest. */ |
| 4113 | | { &i860_cpu_device::insn_and, DEC_DECODED}, /* and isrc1,isrc2,idest. */ |
| 4114 | | { &i860_cpu_device::insn_and_imm, DEC_DECODED}, /* and #const,isrc2,idest. */ |
| 4115 | | { 0, 0}, |
| 4116 | | { &i860_cpu_device::insn_andh_imm, DEC_DECODED}, /* andh #const,isrc2,idest. */ |
| 4117 | | { &i860_cpu_device::insn_andnot, DEC_DECODED}, /* andnot isrc1,isrc2,idest. */ |
| 4118 | | { &i860_cpu_device::insn_andnot_imm, DEC_DECODED}, /* andnot #const,isrc2,idest. */ |
| 4119 | | { 0, 0}, |
| 4120 | | { &i860_cpu_device::insn_andnoth_imm, DEC_DECODED}, /* andnoth #const,isrc2,idest. */ |
| 4121 | | { &i860_cpu_device::insn_or, DEC_DECODED}, /* or isrc1,isrc2,idest. */ |
| 4122 | | { &i860_cpu_device::insn_or_imm, DEC_DECODED}, /* or #const,isrc2,idest. */ |
| 4123 | | { 0, 0}, |
| 4124 | | { &i860_cpu_device::insn_orh_imm, DEC_DECODED}, /* orh #const,isrc2,idest. */ |
| 4125 | | { &i860_cpu_device::insn_xor, DEC_DECODED}, /* xor isrc1,isrc2,idest. */ |
| 4126 | | { &i860_cpu_device::insn_xor_imm, DEC_DECODED}, /* xor #const,isrc2,idest. */ |
| 4127 | | { 0, 0}, |
| 4128 | | { &i860_cpu_device::insn_xorh_imm, DEC_DECODED}, /* xorh #const,isrc2,idest. */ |
| 4129 | | }; |
| 4130 | | |
| 4131 | | |
| 4132 | | /* Second-level decode table (i.e., for the 3 core escape opcode bits). */ |
| 4133 | | const i860_cpu_device::decode_tbl_t i860_cpu_device::core_esc_decode_tbl[8] = { |
| 4134 | | { 0, 0}, |
| 4135 | | { 0, 0}, /* lock (FIXME: unimplemented). */ |
| 4136 | | { &i860_cpu_device::insn_calli, DEC_DECODED}, /* calli isrc1ni. */ |
| 4137 | | { 0, 0}, |
| 4138 | | { &i860_cpu_device::insn_intovr, DEC_DECODED}, /* intovr. */ |
| 4139 | | { 0, 0}, |
| 4140 | | { 0, 0}, |
| 4141 | | { 0, 0}, /* unlock (FIXME: unimplemented). */ |
| 4142 | | }; |
| 4143 | | |
| 4144 | | |
| 4145 | | /* Second-level decode table (i.e., for the 7 FP extended opcode bits). */ |
| 4146 | | const i860_cpu_device::decode_tbl_t i860_cpu_device::fp_decode_tbl[128] = { |
| 4147 | | /* Floating point instructions. The least significant 7 bits are |
| 4148 | | the (extended) opcode and bits 10:7 are P,D,S,R respectively |
| 4149 | | ([p]ipelined, [d]ual, [s]ource prec., [r]esult prec.). |
| 4150 | | For some operations, I defer decoding the P,S,R bits to the |
| 4151 | | emulation routine for them. */ |
| 4152 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x00 pf[m]am */ |
| 4153 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x01 pf[m]am */ |
| 4154 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x02 pf[m]am */ |
| 4155 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x03 pf[m]am */ |
| 4156 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x04 pf[m]am */ |
| 4157 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x05 pf[m]am */ |
| 4158 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x06 pf[m]am */ |
| 4159 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x07 pf[m]am */ |
| 4160 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x08 pf[m]am */ |
| 4161 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x09 pf[m]am */ |
| 4162 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x0A pf[m]am */ |
| 4163 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x0B pf[m]am */ |
| 4164 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x0C pf[m]am */ |
| 4165 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x0D pf[m]am */ |
| 4166 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x0E pf[m]am */ |
| 4167 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x0F pf[m]am */ |
| 4168 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x10 pf[m]sm */ |
| 4169 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x11 pf[m]sm */ |
| 4170 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x12 pf[m]sm */ |
| 4171 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x13 pf[m]sm */ |
| 4172 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x14 pf[m]sm */ |
| 4173 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x15 pf[m]sm */ |
| 4174 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x16 pf[m]sm */ |
| 4175 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x17 pf[m]sm */ |
| 4176 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x18 pf[m]sm */ |
| 4177 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x19 pf[m]sm */ |
| 4178 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x1A pf[m]sm */ |
| 4179 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x1B pf[m]sm */ |
| 4180 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x1C pf[m]sm */ |
| 4181 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x1D pf[m]sm */ |
| 4182 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x1E pf[m]sm */ |
| 4183 | | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x1F pf[m]sm */ |
| 4184 | | { &i860_cpu_device::insn_fmul, DEC_DECODED}, /* 0x20 [p]fmul */ |
| 4185 | | { &i860_cpu_device::insn_fmlow, DEC_DECODED}, /* 0x21 fmlow.dd */ |
| 4186 | | { &i860_cpu_device::insn_frcp, DEC_DECODED}, /* 0x22 frcp.{ss,sd,dd} */ |
| 4187 | | { &i860_cpu_device::insn_frsqr, DEC_DECODED}, /* 0x23 frsqr.{ss,sd,dd} */ |
| 4188 | | { &i860_cpu_device::insn_fmul, DEC_DECODED}, /* 0x24 pfmul3.dd */ |
| 4189 | | { 0, 0}, /* 0x25 */ |
| 4190 | | { 0, 0}, /* 0x26 */ |
| 4191 | | { 0, 0}, /* 0x27 */ |
| 4192 | | { 0, 0}, /* 0x28 */ |
| 4193 | | { 0, 0}, /* 0x29 */ |
| 4194 | | { 0, 0}, /* 0x2A */ |
| 4195 | | { 0, 0}, /* 0x2B */ |
| 4196 | | { 0, 0}, /* 0x2C */ |
| 4197 | | { 0, 0}, /* 0x2D */ |
| 4198 | | { 0, 0}, /* 0x2E */ |
| 4199 | | { 0, 0}, /* 0x2F */ |
| 4200 | | { &i860_cpu_device::insn_fadd_sub, DEC_DECODED}, /* 0x30, [p]fadd.{ss,sd,dd} */ |
| 4201 | | { &i860_cpu_device::insn_fadd_sub, DEC_DECODED}, /* 0x31, [p]fsub.{ss,sd,dd} */ |
| 4202 | | { 0, 0}, /* 0x32, [p]fix.{ss,sd,dd} FIXME: nyi. */ |
| 4203 | | { &i860_cpu_device::insn_famov, DEC_DECODED}, /* 0x33, [p]famov.{ss,sd,ds,dd} */ |
| 4204 | | { &i860_cpu_device::insn_fcmp, DEC_DECODED}, /* 0x34, pf{gt,le}.{ss,dd} */ |
| 4205 | | { &i860_cpu_device::insn_fcmp, DEC_DECODED}, /* 0x35, pfeq.{ss,dd} */ |
| 4206 | | { 0, 0}, /* 0x36 */ |
| 4207 | | { 0, 0}, /* 0x37 */ |
| 4208 | | { 0, 0}, /* 0x38 */ |
| 4209 | | { 0, 0}, /* 0x39 */ |
| 4210 | | { &i860_cpu_device::insn_ftrunc, DEC_DECODED}, /* 0x3A, [p]ftrunc.{ss,sd,dd} */ |
| 4211 | | { 0, 0}, /* 0x3B */ |
| 4212 | | { 0, 0}, /* 0x3C */ |
| 4213 | | { 0, 0}, /* 0x3D */ |
| 4214 | | { 0, 0}, /* 0x3E */ |
| 4215 | | { 0, 0}, /* 0x3F */ |
| 4216 | | { &i860_cpu_device::insn_fxfr, DEC_DECODED}, /* 0x40, fxfr */ |
| 4217 | | { 0, 0}, /* 0x41 */ |
| 4218 | | { 0, 0}, /* 0x42 */ |
| 4219 | | { 0, 0}, /* 0x43 */ |
| 4220 | | { 0, 0}, /* 0x44 */ |
| 4221 | | { 0, 0}, /* 0x45 */ |
| 4222 | | { 0, 0}, /* 0x46 */ |
| 4223 | | { 0, 0}, /* 0x47 */ |
| 4224 | | { 0, 0}, /* 0x48 */ |
| 4225 | | { &i860_cpu_device::insn_fiadd_sub, DEC_DECODED}, /* 0x49, [p]fiadd.{ss,dd} */ |
| 4226 | | { 0, 0}, /* 0x4A */ |
| 4227 | | { 0, 0}, /* 0x4B */ |
| 4228 | | { 0, 0}, /* 0x4C */ |
| 4229 | | { &i860_cpu_device::insn_fiadd_sub, DEC_DECODED}, /* 0x4D, [p]fisub.{ss,dd} */ |
| 4230 | | { 0, 0}, /* 0x4E */ |
| 4231 | | { 0, 0}, /* 0x4F */ |
| 4232 | | { &i860_cpu_device::insn_faddp, DEC_DECODED}, /* 0x50, [p]faddp */ |
| 4233 | | { &i860_cpu_device::insn_faddz, DEC_DECODED}, /* 0x51, [p]faddz */ |
| 4234 | | { 0, 0}, /* 0x52 */ |
| 4235 | | { 0, 0}, /* 0x53 */ |
| 4236 | | { 0, 0}, /* 0x54 */ |
| 4237 | | { 0, 0}, /* 0x55 */ |
| 4238 | | { 0, 0}, /* 0x56 */ |
| 4239 | | { &i860_cpu_device::insn_fzchk, DEC_DECODED}, /* 0x57, [p]fzchkl */ |
| 4240 | | { 0, 0}, /* 0x58 */ |
| 4241 | | { 0, 0}, /* 0x59 */ |
| 4242 | | { &i860_cpu_device::insn_form, DEC_DECODED}, /* 0x5A, [p]form.dd */ |
| 4243 | | { 0, 0}, /* 0x5B */ |
| 4244 | | { 0, 0}, /* 0x5C */ |
| 4245 | | { 0, 0}, /* 0x5D */ |
| 4246 | | { 0, 0}, /* 0x5E */ |
| 4247 | | { &i860_cpu_device::insn_fzchk, DEC_DECODED}, /* 0x5F, [p]fzchks */ |
| 4248 | | { 0, 0}, /* 0x60 */ |
| 4249 | | { 0, 0}, /* 0x61 */ |
| 4250 | | { 0, 0}, /* 0x62 */ |
| 4251 | | { 0, 0}, /* 0x63 */ |
| 4252 | | { 0, 0}, /* 0x64 */ |
| 4253 | | { 0, 0}, /* 0x65 */ |
| 4254 | | { 0, 0}, /* 0x66 */ |
| 4255 | | { 0, 0}, /* 0x67 */ |
| 4256 | | { 0, 0}, /* 0x68 */ |
| 4257 | | { 0, 0}, /* 0x69 */ |
| 4258 | | { 0, 0}, /* 0x6A */ |
| 4259 | | { 0, 0}, /* 0x6B */ |
| 4260 | | { 0, 0}, /* 0x6C */ |
| 4261 | | { 0, 0}, /* 0x6D */ |
| 4262 | | { 0, 0}, /* 0x6E */ |
| 4263 | | { 0, 0}, /* 0x6F */ |
| 4264 | | { 0, 0}, /* 0x70 */ |
| 4265 | | { 0, 0}, /* 0x71 */ |
| 4266 | | { 0, 0}, /* 0x72 */ |
| 4267 | | { 0, 0}, /* 0x73 */ |
| 4268 | | { 0, 0}, /* 0x74 */ |
| 4269 | | { 0, 0}, /* 0x75 */ |
| 4270 | | { 0, 0}, /* 0x76 */ |
| 4271 | | { 0, 0}, /* 0x77 */ |
| 4272 | | { 0, 0}, /* 0x78 */ |
| 4273 | | { 0, 0}, /* 0x79 */ |
| 4274 | | { 0, 0}, /* 0x7A */ |
| 4275 | | { 0, 0}, /* 0x7B */ |
| 4276 | | { 0, 0}, /* 0x7C */ |
| 4277 | | { 0, 0}, /* 0x7D */ |
| 4278 | | { 0, 0}, /* 0x7E */ |
| 4279 | | { 0, 0}, /* 0x7F */ |
| 4280 | | }; |
| 4281 | | |
| 4282 | | |
| 4283 | | /* |
| 4284 | | * Main decoder driver. |
| 4285 | | * insn = instruction at the current PC to execute. |
| 4286 | | * non_shadow = This insn is not in the shadow of a delayed branch). |
| 4287 | | */ |
| 4288 | | void i860_cpu_device::decode_exec (UINT32 insn, UINT32 non_shadow) |
| 4289 | | { |
| 4290 | | int upper_6bits = (insn >> 26) & 0x3f; |
| 4291 | | char flags = 0; |
| 4292 | | int unrecognized = 1; |
| 4293 | | |
| 4294 | | if (m_exiting_ifetch) |
| 4295 | | return; |
| 4296 | | |
| 4297 | | if ((upper_6bits == 0x12 || upper_6bits == 0x2c) && insn & 0x0200) |
| 4298 | | logerror("D-bit seen.\n"); |
| 4299 | | if (GET_EPSR_BE ()) |
| 4300 | | logerror("BE-bit high.\n"); |
| 4301 | | if (GET_DIRBASE_CS8 ()) |
| 4302 | | logerror("CS8-bit high.\n"); |
| 4303 | | |
| 4304 | | flags = decode_tbl[upper_6bits].flags; |
| 4305 | | if (flags & DEC_DECODED) |
| 4306 | | { |
| 4307 | | (this->*decode_tbl[upper_6bits].insn_exec)(insn); |
| 4308 | | unrecognized = 0; |
| 4309 | | } |
| 4310 | | else if (flags & DEC_MORE) |
| 4311 | | { |
| 4312 | | if (upper_6bits == 0x12) |
| 4313 | | { |
| 4314 | | /* FP instruction format handled here. */ |
| 4315 | | char fp_flags = fp_decode_tbl[insn & 0x7f].flags; |
| 4316 | | if (fp_flags & DEC_DECODED) |
| 4317 | | { |
| 4318 | | (this->*fp_decode_tbl[insn & 0x7f].insn_exec)(insn); |
| 4319 | | unrecognized = 0; |
| 4320 | | } |
| 4321 | | } |
| 4322 | | else if (upper_6bits == 0x13) |
| 4323 | | { |
| 4324 | | /* Core escape instruction format handled here. */ |
| 4325 | | char esc_flags = core_esc_decode_tbl[insn & 0x3].flags; |
| 4326 | | if (esc_flags & DEC_DECODED) |
| 4327 | | { |
| 4328 | | (this->*core_esc_decode_tbl[insn & 0x3].insn_exec)(insn); |
| 4329 | | unrecognized = 0; |
| 4330 | | } |
| 4331 | | } |
| 4332 | | } |
| 4333 | | |
| 4334 | | if (unrecognized) |
| 4335 | | unrecog_opcode (m_pc, insn); |
| 4336 | | |
| 4337 | | /* For now, just treat every instruction as taking the same number of |
| 4338 | | clocks-- a major oversimplification. */ |
| 4339 | | m_icount -= 9; |
| 4340 | | } |
| 4341 | | |
| 4342 | | |
| 4343 | | /* Set-up all the default power-on/reset values. */ |
| 4344 | | void i860_cpu_device::reset_i860 () |
| 4345 | | { |
| 4346 | | int i; |
| 4347 | | /* On power-up/reset, i860 has values: |
| 4348 | | PC = 0xffffff00. |
| 4349 | | Integer registers: r0 = 0, others = undefined. |
| 4350 | | FP registers: f0:f1 = 0, others undefined. |
| 4351 | | psr: U = IM = BR = BW = 0; others = undefined. |
| 4352 | | epsr: IL = WP = PBM = BE = 0; processor type, stepping, and |
| 4353 | | DCS are proper and read-only; others = undefined. |
| 4354 | | db: undefined. |
| 4355 | | dirbase: DPS, BL, ATE = 0 |
| 4356 | | fir, fsr, KR, KI, MERGE: undefined. (what about T?) |
| 4357 | | |
| 4358 | | I$: flushed. |
| 4359 | | D$: undefined (all modified bits = 0). |
| 4360 | | TLB: flushed. |
| 4361 | | |
| 4362 | | Note that any undefined values are set to 0x55aa55aa patterns to |
| 4363 | | try to detect defective i860 software. */ |
| 4364 | | |
| 4365 | | /* PC is at trap address after reset. */ |
| 4366 | | m_pc = 0xffffff00; |
| 4367 | | |
| 4368 | | /* Set grs and frs to undefined/nonsense values, except r0. */ |
| 4369 | | for (i = 0; i < 32; i++) |
| 4370 | | { |
| 4371 | | set_iregval (i, 0x55aa55aa); |
| 4372 | | set_fregval_s (i, 0.0); |
| 4373 | | } |
| 4374 | | set_iregval (0, 0); |
| 4375 | | set_fregval_s (0, 0.0); |
| 4376 | | set_fregval_s (1, 0.0); |
| 4377 | | |
| 4378 | | /* Set whole psr to 0. This sets the proper bits to 0 as specified |
| 4379 | | above, and zeroes the undefined bits. */ |
| 4380 | | m_cregs[CR_PSR] = 0; |
| 4381 | | |
| 4382 | | /* Set most of the epsr bits to 0 (as specified above), leaving |
| 4383 | | undefined as zero as well. Then properly set processor type, |
| 4384 | | step, and DCS. Type = EPSR[7..0], step = EPSR[12..8], |
| 4385 | | DCS = EPSR[21..18] (2^[12+dcs] = cache size). |
| 4386 | | We'll pretend to be stepping D0, since it has the fewest bugs |
| 4387 | | (and I don't want to emulate the many defects in the earlier |
| 4388 | | steppings). |
| 4389 | | Proc type: 1 = XR, 2 = XP (XR has 8KB data cache -> DCS = 1). |
| 4390 | | Steppings (XR): 3,4,5,6,7 = (B2, C0, B3, C1, D0 respectively). |
| 4391 | | Steppings (XP): 0, 2, 3, 4 = (A0, B0, B1, B2) (any others?). */ |
| 4392 | | m_cregs[CR_EPSR] = 0x00040701; |
| 4393 | | |
| 4394 | | /* Set DPS, BL, ATE = 0 and the undefined parts also to 0. */ |
| 4395 | | m_cregs[CR_DIRBASE] = 0x00000000; |
| 4396 | | |
| 4397 | | /* Set fir, fsr, KR, KI, MERGE, T to undefined. */ |
| 4398 | | m_cregs[CR_FIR] = 0xaa55aa55; |
| 4399 | | m_cregs[CR_FSR] = /* 0xaa55aa55; */ 0; |
| 4400 | | m_KR.d = 0.0; |
| 4401 | | m_KI.d = 0.0; |
| 4402 | | m_T.d = 0.0; |
| 4403 | | m_merge = 0xaa55aa55; |
| 4404 | | |
| 4405 | | m_fir_gets_trap_addr = 0; |
| 4406 | | } |
| 4407 | | |
| 4408 | | |
| 4409 | | |
| 4410 | | |
| 4411 | | /*=================================================================*/ |
| 4412 | | /* MAME execution hook for i860 emulator. */ |
| 4413 | | /*=================================================================*/ |
| 4414 | | |
| 4415 | | void i860_cpu_device::execute_run() |
| 4416 | | { |
| 4417 | | /* Check if the data bus is held by another device, and bail if so. |
| 4418 | | Also check for reset. */ |
| 4419 | | if (m_pin_reset) |
| 4420 | | reset_i860 (); |
| 4421 | | if (m_pin_bus_hold) |
| 4422 | | { |
| 4423 | | m_icount = 0; |
| 4424 | | return; |
| 4425 | | } |
| 4426 | | |
| 4427 | | m_exiting_readmem = 0; |
| 4428 | | m_exiting_ifetch = 0; |
| 4429 | | |
| 4430 | | /* Decode and execute loop. */ |
| 4431 | | while (m_icount > 0) |
| 4432 | | { |
| 4433 | | UINT32 savepc = m_pc; |
| 4434 | | m_pc_updated = 0; |
| 4435 | | m_pending_trap = 0; |
| 4436 | | |
| 4437 | | #if 1 /* Delete me soon, for debugging VC inter-processor synch. */ |
| 4438 | | if (m_pc == 0xfffc0370 || |
| 4439 | | m_pc == 0xfffc03a4) |
| 4440 | | { |
| 4441 | | fprintf(stderr, "(%s) 0x%08x: snag 0x20000000\n", tag(), m_pc); |
| 4442 | | m_single_stepping = 0; |
| 4443 | | } |
| 4444 | | else if (m_pc == 0xfffc0384 || |
| 4445 | | m_pc == 0xfffc03b8) |
| 4446 | | { |
| 4447 | | fprintf(stderr, "(%s) 0x%08x: passed 0x20000000\n", tag(), m_pc); |
| 4448 | | m_single_stepping = 0; |
| 4449 | | } |
| 4450 | | #endif |
| 4451 | | |
| 4452 | | savepc = m_pc; |
| 4453 | | debugger_instruction_hook(this, m_pc); |
| 4454 | | decode_exec (ifetch (m_pc), 1); |
| 4455 | | |
| 4456 | | m_exiting_ifetch = 0; |
| 4457 | | m_exiting_readmem = 0; |
| 4458 | | |
| 4459 | | if (m_pending_trap) |
| 4460 | | { |
| 4461 | | /* If we need to trap, change PC to trap address. |
| 4462 | | Also set supervisor mode, copy U and IM to their |
| 4463 | | previous versions, clear IM. */ |
| 4464 | | if ((m_pending_trap & TRAP_WAS_EXTERNAL) || (GET_EPSR_INT () && GET_PSR_IN ())) |
| 4465 | | { |
| 4466 | | if (!m_pc_updated) |
| 4467 | | m_cregs[CR_FIR] = savepc + 4; |
| 4468 | | else |
| 4469 | | m_cregs[CR_FIR] = m_pc; |
| 4470 | | } |
| 4471 | | else if (m_pending_trap & TRAP_IN_DELAY_SLOT) |
| 4472 | | { |
| 4473 | | m_cregs[CR_FIR] = savepc + 4; |
| 4474 | | } |
| 4475 | | else |
| 4476 | | m_cregs[CR_FIR] = savepc; |
| 4477 | | |
| 4478 | | m_fir_gets_trap_addr = 1; |
| 4479 | | SET_PSR_PU (GET_PSR_U ()); |
| 4480 | | SET_PSR_PIM (GET_PSR_IM ()); |
| 4481 | | SET_PSR_U (0); |
| 4482 | | SET_PSR_IM (0); |
| 4483 | | SET_PSR_DIM (0); |
| 4484 | | SET_PSR_DS (0); |
| 4485 | | m_pc = 0xffffff00; |
| 4486 | | m_pending_trap = 0; |
| 4487 | | } |
| 4488 | | else if (!m_pc_updated) |
| 4489 | | { |
| 4490 | | /* If the PC wasn't updated by a control flow instruction, just |
| 4491 | | bump to next sequential instruction. */ |
| 4492 | | m_pc += 4; |
| 4493 | | } |
| 4494 | | |
| 4495 | | /*if (m_single_stepping) |
| 4496 | | debugger (cpustate); */ |
| 4497 | | } |
| 4498 | | } |
| 4499 | | /*=================================================================*/ |
| 4500 | | |
| 4501 | | |
| 4502 | | |
| 4503 | | |
| 4504 | | #if 0 |
| 4505 | | /*=================================================================*/ |
| 4506 | | /* Internal debugger-related stuff. */ |
| 4507 | | |
| 4508 | | extern unsigned disasm_i860 (char *buf, unsigned int pc, unsigned int insn); |
| 4509 | | |
| 4510 | | |
| 4511 | | /* Disassemble `len' instructions starting at `addr'. */ |
| 4512 | | void i860_cpu_device::disasm (UINT32 addr, int len) |
| 4513 | | { |
| 4514 | | UINT32 insn; |
| 4515 | | int j; |
| 4516 | | for (j = 0; j < len; j++) |
| 4517 | | { |
| 4518 | | char buf[256]; |
| 4519 | | UINT32 phys_addr = addr; |
| 4520 | | if (GET_DIRBASE_ATE ()) |
| 4521 | | phys_addr = get_address_translation (addr, 1 /* is_dataref */, 0 /* is_write */); |
| 4522 | | |
| 4523 | | /* Note that we print the incoming (possibly virtual) address as the |
| 4524 | | PC rather than the translated address. */ |
| 4525 | | fprintf (stderr, " (%s) 0x%08x: ", m_device->tag(), addr); |
| 4526 | | insn = m_program->read_dword(phys_addr); |
| 4527 | | #ifdef HOST_MSB |
| 4528 | | BYTE_REV32 (insn); |
| 4529 | | #endif /* HOST_MSB. */ |
| 4530 | | disasm_i860 (buf, addr, insn); fprintf (stderr, "%s", buf); |
| 4531 | | fprintf (stderr, "\n"); |
| 4532 | | addr += 4; |
| 4533 | | #if 1 |
| 4534 | | if (m_single_stepping == 1 && has_delay_slot (insn)) |
| 4535 | | len += 1; |
| 4536 | | #endif |
| 4537 | | } |
| 4538 | | } |
| 4539 | | |
| 4540 | | |
| 4541 | | /* Dump `len' bytes starting at `addr'. */ |
| 4542 | | void i860_cpu_device::dbg_db (UINT32 addr, int len) |
| 4543 | | { |
| 4544 | | UINT8 b[16]; |
| 4545 | | int i; |
| 4546 | | /* This will always dump a multiple of 16 bytes, even if 'len' isn't. */ |
| 4547 | | while (len > 0) |
| 4548 | | { |
| 4549 | | /* Note that we print the incoming (possibly virtual) address |
| 4550 | | rather than the translated address. */ |
| 4551 | | fprintf (stderr, "0x%08x: ", addr); |
| 4552 | | for (i = 0; i < 16; i++) |
| 4553 | | { |
| 4554 | | UINT32 phys_addr = addr; |
| 4555 | | if (GET_DIRBASE_ATE ()) |
| 4556 | | phys_addr = get_address_translation (addr, 1 /* is_dataref */, 0 /* is_write */); |
| 4557 | | |
| 4558 | | b[i] = m_program->read_byte(phys_addr); |
| 4559 | | fprintf (stderr, "%02x ", b[i]); |
| 4560 | | addr++; |
| 4561 | | } |
| 4562 | | fprintf (stderr, "| "); |
| 4563 | | for (i = 0; i < 16; i++) |
| 4564 | | { |
| 4565 | | if (isprint (b[i])) |
| 4566 | | fprintf (stderr, "%c", b[i]); |
| 4567 | | else |
| 4568 | | fprintf (stderr, "."); |
| 4569 | | } |
| 4570 | | fprintf (stderr, "\n"); |
| 4571 | | len -= 16; |
| 4572 | | } |
| 4573 | | } |
| 4574 | | |
| 4575 | | |
| 4576 | | /* A simple internal debugger. */ |
| 4577 | | void debugger (i860s *cpustate) |
| 4578 | | { |
| 4579 | | char buf[256]; |
| 4580 | | UINT32 curr_disasm = m_pc; |
| 4581 | | UINT32 curr_dumpdb = 0; |
| 4582 | | int c = 0; |
| 4583 | | |
| 4584 | | if (m_single_stepping > 1 && m_single_stepping != m_pc) |
| 4585 | | return; |
| 4586 | | |
| 4587 | | buf[0] = 0; |
| 4588 | | |
| 4589 | | /* Always disassemble the upcoming instruction when single-stepping. */ |
| 4590 | | if (m_single_stepping) |
| 4591 | | { |
| 4592 | | disasm (m_pc, 1); |
| 4593 | | if (has_delay_slot (2)) |
| 4594 | | disasm (m_pc + 4, 1); |
| 4595 | | } |
| 4596 | | else |
| 4597 | | fprintf (stderr, "\nEmulator: internal debugger started (? for help).\n"); |
| 4598 | | |
| 4599 | | fflush (stdin); |
| 4600 | | |
| 4601 | | m_single_stepping = 0; |
| 4602 | | while (!m_single_stepping) |
| 4603 | | { |
| 4604 | | fprintf (stderr, "- "); |
| 4605 | | #if 0 /* Doesn't work on MacOSX BSD flavor. */ |
| 4606 | | fscanf (stdin, "%s", buf); |
| 4607 | | #else |
| 4608 | | while (1) |
| 4609 | | { |
| 4610 | | char it = 0; |
| 4611 | | if (read(STDIN_FILENO, &it, 1) == 1) |
| 4612 | | { |
| 4613 | | if (it == '\n') |
| 4614 | | { |
| 4615 | | buf[c] = 0; |
| 4616 | | c = 0; |
| 4617 | | break; |
| 4618 | | } |
| 4619 | | buf[c++] = it; |
| 4620 | | } |
| 4621 | | } |
| 4622 | | #endif |
| 4623 | | if (buf[0] == 'g') |
| 4624 | | { |
| 4625 | | if (buf[1] == '0') |
| 4626 | | sscanf (buf + 1, "%x", &m_single_stepping); |
| 4627 | | else |
| 4628 | | break; |
| 4629 | | buf[1] = 0; |
| 4630 | | fprintf (stderr, "go until pc = 0x%08x.\n", |
| 4631 | | m_single_stepping); |
| 4632 | | m_single_stepping = 0; /* HACK */ |
| 4633 | | } |
| 4634 | | else if (buf[0] == 'r') |
| 4635 | | dump_state (cpustate); |
| 4636 | | else if (buf[0] == 'u') |
| 4637 | | { |
| 4638 | | if (buf[1] == '0') |
| 4639 | | sscanf (buf + 1, "%x", &curr_disasm); |
| 4640 | | disasm (curr_disasm, 10); |
| 4641 | | curr_disasm += 10 * 4; |
| 4642 | | buf[1] = 0; |
| 4643 | | } |
| 4644 | | else if (buf[0] == 'p') |
| 4645 | | { |
| 4646 | | if (buf[1] >= '0' && buf[1] <= '4') |
| 4647 | | dump_pipe (buf[1] - 0x30); |
| 4648 | | buf[1] = 0; |
| 4649 | | } |
| 4650 | | else if (buf[0] == 's') |
| 4651 | | m_single_stepping = 1; |
| 4652 | | else if (buf[0] == 'l') |
| 4653 | | ; //m_pc = elf_load(buf + 1); |
| 4654 | | else if (buf[0] == 'd' && buf[1] == 'b') |
| 4655 | | { |
| 4656 | | if (buf[2] == '0') |
| 4657 | | sscanf (buf + 2, "%x", &curr_dumpdb); |
| 4658 | | dbg_db (curr_dumpdb, 32); |
| 4659 | | curr_dumpdb += 32; |
| 4660 | | } |
| 4661 | | else if (buf[0] == 'x' && buf[1] == '0') |
| 4662 | | { |
| 4663 | | UINT32 v; |
| 4664 | | sscanf (buf + 1, "%x", &v); |
| 4665 | | if (GET_DIRBASE_ATE ()) |
| 4666 | | fprintf (stderr, "vma 0x%08x ==> phys 0x%08x\n", v, |
| 4667 | | get_address_translation (v, 1, 0)); |
| 4668 | | else |
| 4669 | | fprintf (stderr, "not in virtual address mode.\n"); |
| 4670 | | } |
| 4671 | | else if (buf[0] == 'B') |
| 4672 | | { |
| 4673 | | ;//m_pc = elf_load("bins/bsd"); |
| 4674 | | break; |
| 4675 | | } |
| 4676 | | else if (buf[0] == '?') |
| 4677 | | { |
| 4678 | | fprintf (stderr, " db: dump bytes (db[0xaddress])\n r: dump registers\n s: single-step\n g: go back to emulator (g[0xaddress])\n u: disassemble (u[0xaddress])\n p: dump pipelines (p{0-4} for all, add, mul, load, graphics)\n l: load an ELF binary (lpath)\n x: give virt->phys translation (x{0xaddress})\n"); |
| 4679 | | } |
| 4680 | | else |
| 4681 | | fprintf (stderr, "Bad command '%s'.\n", buf); |
| 4682 | | } |
| 4683 | | |
| 4684 | | /* Less noise when single-stepping. */ |
| 4685 | | if (m_single_stepping != 1) |
| 4686 | | fprintf (stderr, "Debugger done, continuing emulation.\n"); |
| 4687 | | } |
| 4688 | | |
| 4689 | | #endif |
trunk/src/emu/cpu/i860/i860dec.inc
| r0 | r28739 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | i860dec.inc |
| 4 | |
| 5 | Execution engine for the Intel i860 emulator. |
| 6 | |
| 7 | Copyright (C) 1995-present Jason Eckhardt (jle@rice.edu) |
| 8 | Released for general non-commercial use under the MAME license |
| 9 | with the additional requirement that you are free to use and |
| 10 | redistribute this code in modified or unmodified form, provided |
| 11 | you list me in the credits. |
| 12 | Visit http://mamedev.org for licensing and usage restrictions. |
| 13 | |
| 14 | ***************************************************************************/ |
| 15 | |
| 16 | /* |
| 17 | * References: |
| 18 | * `i860 Microprocessor Programmer's Reference Manual', Intel, 1990. |
| 19 | * |
| 20 | * This code was originally written by Jason Eckhardt as part of an |
| 21 | * emulator for some i860-based Unix workstations (early 1990's) such |
| 22 | * as the Stardent Vistra 800 series and the OkiStation/i860 7300 series. |
| 23 | * The code you are reading now is the i860 CPU portion only, which has |
| 24 | * been adapted to (and simplified for) MAME. |
| 25 | * MAME-specific notes: |
| 26 | * - i860XR emulation only (i860XP unnecessary for MAME). |
| 27 | * - No emulation of data and instruction caches (unnecessary for MAME version). |
| 28 | * - No emulation of DIM mode or CS8 mode (unnecessary for MAME version). |
| 29 | * - No BL/IL/locked sequences (unnecessary for MAME). |
| 30 | * - Emulate only the i860's LSB-first mode (BE = 0). |
| 31 | * Generic notes: |
| 32 | * - There is some amount of code duplication (e.g., see the |
| 33 | * various insn_* routines for the branches and FP routines) that |
| 34 | * could be eliminated. |
| 35 | * - The host's floating point types are used to emulate the i860's |
| 36 | * floating point. Should probably be made machine independent by |
| 37 | * using an IEEE FP emulation library. On the other hand, most machines |
| 38 | * today also use IEEE FP. |
| 39 | * |
| 40 | */ |
| 41 | #include "i860.h" |
| 42 | #include <math.h> |
| 43 | |
| 44 | |
| 45 | #undef HOST_MSB |
| 46 | |
| 47 | #undef TRACE_RDWR_MEM |
| 48 | #undef TRACE_ADDR_TRANSLATION |
| 49 | #undef TRACE_PAGE_FAULT |
| 50 | #define TRACE_UNDEFINED_I860 |
| 51 | #undef TRACE_EXT_INT |
| 52 | #define TRACE_UNALIGNED_MEM |
| 53 | |
| 54 | |
| 55 | /* Defines for pending_trap. */ |
| 56 | enum { |
| 57 | TRAP_NORMAL = 0x01, |
| 58 | TRAP_IN_DELAY_SLOT = 0x02, |
| 59 | TRAP_WAS_EXTERNAL = 0x04 |
| 60 | }; |
| 61 | |
| 62 | |
| 63 | /* TODO: THESE WILL BE REPLACED BY MAME FUNCTIONS |
| 64 | #define BYTE_REV32(t) \ |
| 65 | do { \ |
| 66 | (t) = ((UINT32)(t) >> 16) | ((UINT32)(t) << 16); \ |
| 67 | (t) = (((UINT32)(t) >> 8) & 0x00ff00ff) | (((UINT32)(t) << 8) & 0xff00ff00); \ |
| 68 | } while (0); |
| 69 | |
| 70 | #define BYTE_REV16(t) \ |
| 71 | do { \ |
| 72 | (t) = (((UINT16)(t) >> 8) & 0x00ff) | (((UINT16)(t) << 8) & 0xff00); \ |
| 73 | } while (0); |
| 74 | #endif |
| 75 | */ |
| 76 | |
| 77 | |
| 78 | /* Get/set general register value -- watch for r0 on writes. */ |
| 79 | #define get_iregval(gr) (m_iregs[(gr)]) |
| 80 | #define set_iregval(gr, val) (m_iregs[(gr)] = ((gr) == 0 ? 0 : (val))) |
| 81 | |
| 82 | float i860_cpu_device::get_fregval_s (int fr) |
| 83 | { |
| 84 | float f; |
| 85 | UINT32 x; |
| 86 | UINT8 *tp; |
| 87 | fr = 31 - fr; |
| 88 | tp = (UINT8 *)(&m_frg[fr * 4]); |
| 89 | x = ((UINT32)tp[0] << 24) | ((UINT32)tp[1] << 16) | |
| 90 | ((UINT32)tp[2] << 8) | ((UINT32)tp[3]); |
| 91 | f = *(float *)(&x); |
| 92 | return f; |
| 93 | } |
| 94 | |
| 95 | double i860_cpu_device::get_fregval_d (int fr) |
| 96 | { |
| 97 | double d; |
| 98 | UINT64 x; |
| 99 | UINT8 *tp; |
| 100 | fr = 31 - (fr + 1); |
| 101 | tp = (UINT8 *)(&m_frg[fr * 4]); |
| 102 | x = ((UINT64)tp[0] << 56) | ((UINT64)tp[1] << 48) | |
| 103 | ((UINT64)tp[2] << 40) | ((UINT64)tp[3] << 32) | |
| 104 | ((UINT64)tp[4] << 24) | ((UINT64)tp[5] << 16) | |
| 105 | ((UINT64)tp[6] << 8) | ((UINT64)tp[7]); |
| 106 | d = *(double *)(&x); |
| 107 | return d; |
| 108 | } |
| 109 | |
| 110 | void i860_cpu_device::set_fregval_s (int fr, float s) |
| 111 | { |
| 112 | UINT8 *f = (UINT8 *)&s; |
| 113 | UINT8 *tp; |
| 114 | int newfr = 31 - fr; |
| 115 | float jj = s; |
| 116 | tp = (UINT8 *)(&m_frg[newfr * 4]); |
| 117 | |
| 118 | f = (UINT8 *)(&jj); |
| 119 | if (fr == 0 || fr == 1) |
| 120 | { |
| 121 | tp[0] = 0; tp[1] = 0; tp[2] = 0; tp[3] = 0; |
| 122 | } |
| 123 | else |
| 124 | { |
| 125 | #ifndef HOST_MSB |
| 126 | tp[0] = f[3]; tp[1] = f[2]; tp[2] = f[1]; tp[3] = f[0]; |
| 127 | #else |
| 128 | tp[0] = f[0]; tp[1] = f[1]; tp[2] = f[2]; tp[3] = f[3]; |
| 129 | #endif |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | void i860_cpu_device::set_fregval_d (int fr, double d) |
| 134 | { |
| 135 | UINT8 *f = (UINT8 *)&d; |
| 136 | UINT8 *tp; |
| 137 | int newfr = 31 - (fr + 1); |
| 138 | double jj = d; |
| 139 | tp = (UINT8 *)(&m_frg[newfr * 4]); |
| 140 | |
| 141 | f = (UINT8 *)(&jj); |
| 142 | |
| 143 | if (fr == 0) |
| 144 | { |
| 145 | tp[0] = 0; tp[1] = 0; tp[2] = 0; tp[3] = 0; |
| 146 | tp[4] = 0; tp[5] = 0; tp[6] = 0; tp[7] = 0; |
| 147 | } |
| 148 | else |
| 149 | { |
| 150 | #ifndef HOST_MSB |
| 151 | tp[0] = f[7]; tp[1] = f[6]; tp[2] = f[5]; tp[3] = f[4]; |
| 152 | tp[4] = f[3]; tp[5] = f[2]; tp[6] = f[1]; tp[7] = f[0]; |
| 153 | #else |
| 154 | tp[0] = f[0]; tp[1] = f[1]; tp[2] = f[2]; tp[3] = f[3]; |
| 155 | tp[4] = f[4]; tp[5] = f[5]; tp[6] = f[6]; tp[7] = f[7]; |
| 156 | #endif |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | |
| 161 | /* Macros for accessing register fields in instruction word. */ |
| 162 | #define get_isrc1(bits) (((bits) >> 11) & 0x1f) |
| 163 | #define get_isrc2(bits) (((bits) >> 21) & 0x1f) |
| 164 | #define get_idest(bits) (((bits) >> 16) & 0x1f) |
| 165 | #define get_fsrc1(bits) (((bits) >> 11) & 0x1f) |
| 166 | #define get_fsrc2(bits) (((bits) >> 21) & 0x1f) |
| 167 | #define get_fdest(bits) (((bits) >> 16) & 0x1f) |
| 168 | #define get_creg(bits) (((bits) >> 21) & 0x7) |
| 169 | |
| 170 | /* Macros for accessing immediate fields. */ |
| 171 | /* 16-bit immediate. */ |
| 172 | #define get_imm16(insn) ((insn) & 0xffff) |
| 173 | |
| 174 | /* A mask for all the trap bits of the PSR (FT, DAT, IAT, IN, IT, or |
| 175 | bits [12..8]). */ |
| 176 | #define PSR_ALL_TRAP_BITS_MASK 0x00001f00 |
| 177 | |
| 178 | /* A mask for PSR bits which can only be changed from supervisor level. */ |
| 179 | #define PSR_SUPERVISOR_ONLY_MASK 0x0000fff3 |
| 180 | |
| 181 | |
| 182 | /* PSR: BR flag (PSR[0]): set/get. */ |
| 183 | #define GET_PSR_BR() ((m_cregs[CR_PSR] >> 0) & 1) |
| 184 | #define SET_PSR_BR(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 0)) | (((val) & 1) << 0)) |
| 185 | |
| 186 | /* PSR: BW flag (PSR[1]): set/get. */ |
| 187 | #define GET_PSR_BW() ((m_cregs[CR_PSR] >> 1) & 1) |
| 188 | #define SET_PSR_BW(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 1)) | (((val) & 1) << 1)) |
| 189 | |
| 190 | /* PSR: Shift count (PSR[21..17]): set/get. */ |
| 191 | #define GET_PSR_SC() ((m_cregs[CR_PSR] >> 17) & 0x1f) |
| 192 | #define SET_PSR_SC(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~0x003e0000) | (((val) & 0x1f) << 17)) |
| 193 | |
| 194 | /* PSR: CC flag (PSR[2]): set/get. */ |
| 195 | #define GET_PSR_CC() ((m_cregs[CR_PSR] >> 2) & 1) |
| 196 | #define SET_PSR_CC(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 2)) | (((val) & 1) << 2)) |
| 197 | |
| 198 | /* PSR: IT flag (PSR[8]): set/get. */ |
| 199 | #define GET_PSR_IT() ((m_cregs[CR_PSR] >> 8) & 1) |
| 200 | #define SET_PSR_IT(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 8)) | (((val) & 1) << 8)) |
| 201 | |
| 202 | /* PSR: IN flag (PSR[9]): set/get. */ |
| 203 | #define GET_PSR_IN() ((m_cregs[CR_PSR] >> 9) & 1) |
| 204 | #define SET_PSR_IN(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 9)) | (((val) & 1) << 9)) |
| 205 | |
| 206 | /* PSR: IAT flag (PSR[10]): set/get. */ |
| 207 | #define GET_PSR_IAT() ((m_cregs[CR_PSR] >> 10) & 1) |
| 208 | #define SET_PSR_IAT(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 10)) | (((val) & 1) << 10)) |
| 209 | |
| 210 | /* PSR: DAT flag (PSR[11]): set/get. */ |
| 211 | #define GET_PSR_DAT() ((m_cregs[CR_PSR] >> 11) & 1) |
| 212 | #define SET_PSR_DAT(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 11)) | (((val) & 1) << 11)) |
| 213 | |
| 214 | /* PSR: FT flag (PSR[12]): set/get. */ |
| 215 | #define GET_PSR_FT() ((m_cregs[CR_PSR] >> 12) & 1) |
| 216 | #define SET_PSR_FT(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 12)) | (((val) & 1) << 12)) |
| 217 | |
| 218 | /* PSR: DS flag (PSR[13]): set/get. */ |
| 219 | #define GET_PSR_DS() ((m_cregs[CR_PSR] >> 13) & 1) |
| 220 | #define SET_PSR_DS(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 13)) | (((val) & 1) << 13)) |
| 221 | |
| 222 | /* PSR: DIM flag (PSR[14]): set/get. */ |
| 223 | #define GET_PSR_DIM() ((m_cregs[CR_PSR] >> 14) & 1) |
| 224 | #define SET_PSR_DIM(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 14)) | (((val) & 1) << 14)) |
| 225 | |
| 226 | /* PSR: LCC (PSR[3]): set/get. */ |
| 227 | #define GET_PSR_LCC() ((m_cregs[CR_PSR] >> 3) & 1) |
| 228 | #define SET_PSR_LCC(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 3)) | (((val) & 1) << 3)) |
| 229 | |
| 230 | /* PSR: IM (PSR[4]): set/get. */ |
| 231 | #define GET_PSR_IM() ((m_cregs[CR_PSR] >> 4) & 1) |
| 232 | #define SET_PSR_IM(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 4)) | (((val) & 1) << 4)) |
| 233 | |
| 234 | /* PSR: PIM (PSR[5]): set/get. */ |
| 235 | #define GET_PSR_PIM() ((m_cregs[CR_PSR] >> 5) & 1) |
| 236 | #define SET_PSR_PIM(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 5)) | (((val) & 1) << 5)) |
| 237 | |
| 238 | /* PSR: U (PSR[6]): set/get. */ |
| 239 | #define GET_PSR_U() ((m_cregs[CR_PSR] >> 6) & 1) |
| 240 | #define SET_PSR_U(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 6)) | (((val) & 1) << 6)) |
| 241 | |
| 242 | /* PSR: PU (PSR[7]): set/get. */ |
| 243 | #define GET_PSR_PU() ((m_cregs[CR_PSR] >> 7) & 1) |
| 244 | #define SET_PSR_PU(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 7)) | (((val) & 1) << 7)) |
| 245 | |
| 246 | /* PSR: Pixel size (PSR[23..22]): set/get. */ |
| 247 | #define GET_PSR_PS() ((m_cregs[CR_PSR] >> 22) & 0x3) |
| 248 | #define SET_PSR_PS(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~0x00c00000) | (((val) & 0x3) << 22)) |
| 249 | |
| 250 | /* PSR: Pixel mask (PSR[31..24]): set/get. */ |
| 251 | #define GET_PSR_PM() ((m_cregs[CR_PSR] >> 24) & 0xff) |
| 252 | #define SET_PSR_PM(val) (m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~0xff000000) | (((val) & 0xff) << 24)) |
| 253 | |
| 254 | /* EPSR: WP bit (EPSR[14]): set/get. */ |
| 255 | #define GET_EPSR_WP() ((m_cregs[CR_EPSR] >> 14) & 1) |
| 256 | #define SET_EPSR_WP(val) (m_cregs[CR_EPSR] = (m_cregs[CR_EPSR] & ~(1 << 14)) | (((val) & 1) << 14)) |
| 257 | |
| 258 | /* EPSR: INT bit (EPSR[17]): set/get. */ |
| 259 | #define GET_EPSR_INT() ((m_cregs[CR_EPSR] >> 17) & 1) |
| 260 | #define SET_EPSR_INT(val) (m_cregs[CR_EPSR] = (m_cregs[CR_EPSR] & ~(1 << 17)) | (((val) & 1) << 17)) |
| 261 | |
| 262 | |
| 263 | /* EPSR: OF flag (EPSR[24]): set/get. */ |
| 264 | #define GET_EPSR_OF() ((m_cregs[CR_EPSR] >> 24) & 1) |
| 265 | #define SET_EPSR_OF(val) (m_cregs[CR_EPSR] = (m_cregs[CR_EPSR] & ~(1 << 24)) | (((val) & 1) << 24)) |
| 266 | |
| 267 | /* EPSR: BE flag (EPSR[23]): set/get. */ |
| 268 | #define GET_EPSR_BE() ((m_cregs[CR_EPSR] >> 23) & 1) |
| 269 | #define SET_EPSR_BE(val) (m_cregs[CR_EPSR] = (m_cregs[CR_EPSR] & ~(1 << 23)) | (((val) & 1) << 23)) |
| 270 | |
| 271 | /* DIRBASE: ATE bit (DIRBASE[0]): get. */ |
| 272 | #define GET_DIRBASE_ATE() (m_cregs[CR_DIRBASE] & 1) |
| 273 | |
| 274 | /* DIRBASE: CS8 bit (DIRBASE[7]): get. */ |
| 275 | #define GET_DIRBASE_CS8() ((m_cregs[CR_DIRBASE] >> 7) & 1) |
| 276 | |
| 277 | /* FSR: FTE bit (FSR[5]): set/get. */ |
| 278 | #define GET_FSR_FTE() ((m_cregs[CR_FSR] >> 5) & 1) |
| 279 | #define SET_FSR_FTE(val) (m_cregs[CR_FSR] = (m_cregs[CR_FSR] & ~(1 << 5)) | (((val) & 1) << 5)) |
| 280 | |
| 281 | /* FSR: SE bit (FSR[8]): set/get. */ |
| 282 | #define GET_FSR_SE() ((m_cregs[CR_FSR] >> 8) & 1) |
| 283 | #define SET_FSR_SE(val) (m_cregs[CR_FSR] = (m_cregs[CR_FSR] & ~(1 << 8)) | (((val) & 1) << 8)) |
| 284 | |
| 285 | |
| 286 | int i860_cpu_device::has_delay_slot(UINT32 insn) |
| 287 | { |
| 288 | int opc = (insn >> 26) & 0x3f; |
| 289 | if (opc == 0x10 || opc == 0x1a || opc == 0x1b || opc == 0x1d || |
| 290 | opc == 0x1f || opc == 0x2d || (opc == 0x13 && (insn & 3) == 2)) |
| 291 | return 1; |
| 292 | return 0; |
| 293 | } |
| 294 | |
| 295 | /* This is the external interface for asserting/deasserting pins on |
| 296 | the i860. */ |
| 297 | void i860_cpu_device::i860_set_pin (int pin, int val) |
| 298 | { |
| 299 | if (pin == DEC_PIN_BUS_HOLD) |
| 300 | m_pin_bus_hold = val; |
| 301 | else if (pin == DEC_PIN_RESET) |
| 302 | m_pin_reset = val; |
| 303 | else |
| 304 | assert (0); |
| 305 | } |
| 306 | |
| 307 | |
| 308 | /* This is the external interface for indicating an external interrupt |
| 309 | to the i860. */ |
| 310 | void i860_cpu_device::i860_gen_interrupt() |
| 311 | { |
| 312 | /* If interrupts are enabled, then set PSR.IN and prepare for trap. |
| 313 | Otherwise, the external interrupt is ignored. We also set |
| 314 | bit EPSR.INT (which tracks the INT pin). */ |
| 315 | if (GET_PSR_IM ()) |
| 316 | { |
| 317 | SET_PSR_IN (1); |
| 318 | SET_EPSR_INT (1); |
| 319 | m_pending_trap = TRAP_WAS_EXTERNAL; |
| 320 | } |
| 321 | |
| 322 | #ifdef TRACE_EXT_INT |
| 323 | fprintf (stderr, "i860_gen_interrupt: External interrupt received "); |
| 324 | if (GET_PSR_IM ()) |
| 325 | fprintf (stderr, "[PSR.IN set, preparing to trap]\n"); |
| 326 | else |
| 327 | fprintf (stderr, "[ignored (interrupts disabled)]\n"); |
| 328 | #endif |
| 329 | } |
| 330 | |
| 331 | |
| 332 | /* Fetch instructions from instruction cache. |
| 333 | Note: The instruction cache is not implemented for MAME version, |
| 334 | this just fetches and returns 1 instruction from memory. */ |
| 335 | UINT32 i860_cpu_device::ifetch (UINT32 pc) |
| 336 | { |
| 337 | UINT32 phys_pc = 0; |
| 338 | UINT32 w1 = 0; |
| 339 | |
| 340 | /* If virtual mode, get translation. */ |
| 341 | if (GET_DIRBASE_ATE ()) |
| 342 | { |
| 343 | phys_pc = get_address_translation (pc, 0 /* is_dataref */, 0 /* is_write */); |
| 344 | m_exiting_ifetch = 0; |
| 345 | if (m_pending_trap && (GET_PSR_DAT () || GET_PSR_IAT ())) |
| 346 | { |
| 347 | m_exiting_ifetch = 1; |
| 348 | return 0xffeeffee; |
| 349 | } |
| 350 | } |
| 351 | else |
| 352 | phys_pc = pc; |
| 353 | |
| 354 | /* Since i860 instructions are always stored LSB first (regardless of |
| 355 | the BE bit), we need to adjust the instruction below on MSB hosts. */ |
| 356 | w1 = m_program->read_dword(phys_pc); |
| 357 | #ifdef HOST_MSB |
| 358 | BYTE_REV32 (w1); |
| 359 | #endif /* HOST_MSB. */ |
| 360 | return w1; |
| 361 | } |
| 362 | |
| 363 | |
| 364 | /* Given a virtual address, perform the i860 address translation and |
| 365 | return the corresponding physical address. |
| 366 | vaddr: virtual address |
| 367 | is_dataref: 1 = load/store, 0 = instruction fetch. |
| 368 | is_write: 1 = writing to vaddr, 0 = reading from vaddr |
| 369 | The last two arguments are only used to determine what types |
| 370 | of traps should be taken. |
| 371 | |
| 372 | Page tables must always be in memory (not cached). So the routine |
| 373 | here only accesses memory. */ |
| 374 | UINT32 i860_cpu_device::get_address_translation (UINT32 vaddr, int is_dataref, int is_write) |
| 375 | { |
| 376 | UINT32 vdir = (vaddr >> 22) & 0x3ff; |
| 377 | UINT32 vpage = (vaddr >> 12) & 0x3ff; |
| 378 | UINT32 voffset = vaddr & 0xfff; |
| 379 | UINT32 dtb = (m_cregs[CR_DIRBASE]) & 0xfffff000; |
| 380 | UINT32 pg_dir_entry_a = 0; |
| 381 | UINT32 pg_dir_entry = 0; |
| 382 | UINT32 pg_tbl_entry_a = 0; |
| 383 | UINT32 pg_tbl_entry = 0; |
| 384 | UINT32 pfa1 = 0; |
| 385 | UINT32 pfa2 = 0; |
| 386 | UINT32 ret = 0; |
| 387 | UINT32 ttpde = 0; |
| 388 | UINT32 ttpte = 0; |
| 389 | |
| 390 | assert (GET_DIRBASE_ATE ()); |
| 391 | |
| 392 | /* Get page directory entry at DTB:DIR:00. */ |
| 393 | pg_dir_entry_a = dtb | (vdir << 2); |
| 394 | pg_dir_entry = m_program->read_dword(pg_dir_entry_a); |
| 395 | #ifdef HOST_MSB |
| 396 | BYTE_REV32 (pg_dir_entry); |
| 397 | #endif |
| 398 | |
| 399 | /* Check for non-present PDE. */ |
| 400 | if (!(pg_dir_entry & 1)) |
| 401 | { |
| 402 | /* PDE is not present, generate DAT or IAT. */ |
| 403 | if (is_dataref) |
| 404 | SET_PSR_DAT (1); |
| 405 | else |
| 406 | SET_PSR_IAT (1); |
| 407 | m_pending_trap = 1; |
| 408 | |
| 409 | /* Dummy return. */ |
| 410 | return 0; |
| 411 | } |
| 412 | |
| 413 | /* PDE Check for write protection violations. */ |
| 414 | if (is_write && is_dataref |
| 415 | && !(pg_dir_entry & 2) /* W = 0. */ |
| 416 | && (GET_PSR_U () || GET_EPSR_WP ())) /* PSR_U = 1 or EPSR_WP = 1. */ |
| 417 | { |
| 418 | SET_PSR_DAT (1); |
| 419 | m_pending_trap = 1; |
| 420 | /* Dummy return. */ |
| 421 | return 0; |
| 422 | } |
| 423 | |
| 424 | /* PDE Check for user-mode access to supervisor pages. */ |
| 425 | if (GET_PSR_U () |
| 426 | && !(pg_dir_entry & 4)) /* U = 0. */ |
| 427 | { |
| 428 | if (is_dataref) |
| 429 | SET_PSR_DAT (1); |
| 430 | else |
| 431 | SET_PSR_IAT (1); |
| 432 | m_pending_trap = 1; |
| 433 | /* Dummy return. */ |
| 434 | return 0; |
| 435 | } |
| 436 | |
| 437 | /* FIXME: How exactly to handle A check/update?. */ |
| 438 | |
| 439 | /* Get page table entry at PFA1:PAGE:00. */ |
| 440 | pfa1 = pg_dir_entry & 0xfffff000; |
| 441 | pg_tbl_entry_a = pfa1 | (vpage << 2); |
| 442 | pg_tbl_entry = m_program->read_dword(pg_tbl_entry_a); |
| 443 | #ifdef HOST_MSB |
| 444 | BYTE_REV32 (pg_tbl_entry); |
| 445 | #endif |
| 446 | |
| 447 | /* Check for non-present PTE. */ |
| 448 | if (!(pg_tbl_entry & 1)) |
| 449 | { |
| 450 | /* PTE is not present, generate DAT or IAT. */ |
| 451 | if (is_dataref) |
| 452 | SET_PSR_DAT (1); |
| 453 | else |
| 454 | SET_PSR_IAT (1); |
| 455 | m_pending_trap = 1; |
| 456 | |
| 457 | /* Dummy return. */ |
| 458 | return 0; |
| 459 | } |
| 460 | |
| 461 | /* PTE Check for write protection violations. */ |
| 462 | if (is_write && is_dataref |
| 463 | && !(pg_tbl_entry & 2) /* W = 0. */ |
| 464 | && (GET_PSR_U () || GET_EPSR_WP ())) /* PSR_U = 1 or EPSR_WP = 1. */ |
| 465 | { |
| 466 | SET_PSR_DAT (1); |
| 467 | m_pending_trap = 1; |
| 468 | /* Dummy return. */ |
| 469 | return 0; |
| 470 | } |
| 471 | |
| 472 | /* PTE Check for user-mode access to supervisor pages. */ |
| 473 | if (GET_PSR_U () |
| 474 | && !(pg_tbl_entry & 4)) /* U = 0. */ |
| 475 | { |
| 476 | if (is_dataref) |
| 477 | SET_PSR_DAT (1); |
| 478 | else |
| 479 | SET_PSR_IAT (1); |
| 480 | m_pending_trap = 1; |
| 481 | /* Dummy return. */ |
| 482 | return 0; |
| 483 | } |
| 484 | |
| 485 | /* Update A bit and check D bit. */ |
| 486 | ttpde = pg_dir_entry | 0x20; |
| 487 | ttpte = pg_tbl_entry | 0x20; |
| 488 | #ifdef HOST_MSB |
| 489 | BYTE_REV32 (ttpde); |
| 490 | BYTE_REV32 (ttpte); |
| 491 | #endif |
| 492 | m_program->write_dword(pg_dir_entry_a, ttpde); |
| 493 | m_program->write_dword(pg_tbl_entry_a, ttpte); |
| 494 | |
| 495 | if (is_write && is_dataref && (pg_tbl_entry & 0x40) == 0) |
| 496 | { |
| 497 | /* fprintf(stderr, "DAT trap on write without dirty bit v0x%08x/p0x%08x\n", |
| 498 | vaddr, (pg_tbl_entry & ~0xfff)|voffset); */ |
| 499 | SET_PSR_DAT (1); |
| 500 | m_pending_trap = 1; |
| 501 | /* Dummy return. */ |
| 502 | return 0; |
| 503 | } |
| 504 | |
| 505 | pfa2 = (pg_tbl_entry & 0xfffff000); |
| 506 | ret = pfa2 | voffset; |
| 507 | |
| 508 | #ifdef TRACE_ADDR_TRANSLATION |
| 509 | fprintf (stderr, "get_address_translation: virt(0x%08x) -> phys(0x%08x)\n", |
| 510 | vaddr, ret); |
| 511 | #endif |
| 512 | |
| 513 | return ret; |
| 514 | } |
| 515 | |
| 516 | |
| 517 | /* Read memory emulation. |
| 518 | addr = address to read. |
| 519 | size = size of read in bytes. */ |
| 520 | UINT32 i860_cpu_device::readmemi_emu (UINT32 addr, int size) |
| 521 | { |
| 522 | #ifdef TRACE_RDWR_MEM |
| 523 | fprintf (stderr, "readmemi_emu: (ATE=%d) addr = 0x%08x, size = %d\n", |
| 524 | GET_DIRBASE_ATE (), addr, size); |
| 525 | #endif |
| 526 | |
| 527 | /* If virtual mode, do translation. */ |
| 528 | if (GET_DIRBASE_ATE ()) |
| 529 | { |
| 530 | UINT32 phys = get_address_translation (addr, 1 /* is_dataref */, 0 /* is_write */); |
| 531 | if (m_pending_trap && (GET_PSR_IAT () || GET_PSR_DAT ())) |
| 532 | { |
| 533 | #ifdef TRACE_PAGE_FAULT |
| 534 | fprintf (stderr, "0x%08x: ## Page fault (readmemi_emu).\n", |
| 535 | m_pc); |
| 536 | #endif |
| 537 | m_exiting_readmem = 1; |
| 538 | return 0; |
| 539 | } |
| 540 | addr = phys; |
| 541 | } |
| 542 | |
| 543 | /* First check for match to db register (before read). */ |
| 544 | if (((addr & ~(size - 1)) == m_cregs[CR_DB]) && GET_PSR_BR ()) |
| 545 | { |
| 546 | SET_PSR_DAT (1); |
| 547 | m_pending_trap = 1; |
| 548 | return 0; |
| 549 | } |
| 550 | |
| 551 | /* Now do the actual read. */ |
| 552 | if (size == 1) |
| 553 | { |
| 554 | UINT32 ret = m_program->read_byte(addr); |
| 555 | return ret & 0xff; |
| 556 | } |
| 557 | else if (size == 2) |
| 558 | { |
| 559 | UINT32 ret = m_program->read_word(addr); |
| 560 | #ifdef HOST_MSB |
| 561 | BYTE_REV16 (ret); |
| 562 | #endif |
| 563 | return ret & 0xffff; |
| 564 | } |
| 565 | else if (size == 4) |
| 566 | { |
| 567 | UINT32 ret = m_program->read_dword(addr); |
| 568 | #ifdef HOST_MSB |
| 569 | BYTE_REV32 (ret); |
| 570 | #endif |
| 571 | return ret; |
| 572 | } |
| 573 | else |
| 574 | assert (0); |
| 575 | |
| 576 | return 0; |
| 577 | } |
| 578 | |
| 579 | |
| 580 | /* Write memory emulation. |
| 581 | addr = address to write. |
| 582 | size = size of write in bytes. |
| 583 | data = data to write. */ |
| 584 | void i860_cpu_device::writememi_emu (UINT32 addr, int size, UINT32 data) |
| 585 | { |
| 586 | #ifdef TRACE_RDWR_MEM |
| 587 | fprintf (stderr, "writememi_emu: (ATE=%d) addr = 0x%08x, size = %d, data = 0x%08x\n", |
| 588 | GET_DIRBASE_ATE (), addr, size, data); |
| 589 | #endif |
| 590 | |
| 591 | /* If virtual mode, do translation. */ |
| 592 | if (GET_DIRBASE_ATE ()) |
| 593 | { |
| 594 | UINT32 phys = get_address_translation (addr, 1 /* is_dataref */, 1 /* is_write */); |
| 595 | if (m_pending_trap && (GET_PSR_IAT () || GET_PSR_DAT ())) |
| 596 | { |
| 597 | #ifdef TRACE_PAGE_FAULT |
| 598 | fprintf (stderr, "0x%08x: ## Page fault (writememi_emu).\n", |
| 599 | m_pc); |
| 600 | #endif |
| 601 | m_exiting_readmem = 2; |
| 602 | return; |
| 603 | } |
| 604 | addr = phys; |
| 605 | } |
| 606 | |
| 607 | /* First check for match to db register (before write). */ |
| 608 | if (((addr & ~(size - 1)) == m_cregs[CR_DB]) && GET_PSR_BW ()) |
| 609 | { |
| 610 | SET_PSR_DAT (1); |
| 611 | m_pending_trap = 1; |
| 612 | return; |
| 613 | } |
| 614 | |
| 615 | /* Now do the actual write. */ |
| 616 | if (size == 1) |
| 617 | m_program->write_byte(addr, data); |
| 618 | else if (size == 2) |
| 619 | { |
| 620 | #ifdef HOST_MSB |
| 621 | BYTE_REV16 (data); |
| 622 | #endif |
| 623 | m_program->write_word(addr, data); |
| 624 | } |
| 625 | else if (size == 4) |
| 626 | { |
| 627 | #ifdef HOST_MSB |
| 628 | BYTE_REV32 (data); |
| 629 | #endif |
| 630 | m_program->write_dword(addr, data); |
| 631 | } |
| 632 | else |
| 633 | assert (0); |
| 634 | } |
| 635 | |
| 636 | |
| 637 | /* Floating-point read mem routine. |
| 638 | addr = address to read. |
| 639 | size = size of read in bytes. |
| 640 | dest = memory to put read data. */ |
| 641 | void i860_cpu_device::fp_readmem_emu (UINT32 addr, int size, UINT8 *dest) |
| 642 | { |
| 643 | #ifdef TRACE_RDWR_MEM |
| 644 | fprintf (stderr, "fp_readmem_emu: (ATE=%d) addr = 0x%08x, size = %d\n", |
| 645 | GET_DIRBASE_ATE (), addr, size); |
| 646 | #endif |
| 647 | |
| 648 | assert (size == 4 || size == 8 || size == 16); |
| 649 | |
| 650 | /* If virtual mode, do translation. */ |
| 651 | if (GET_DIRBASE_ATE ()) |
| 652 | { |
| 653 | UINT32 phys = get_address_translation (addr, 1 /* is_dataref */, 0 /* is_write */); |
| 654 | if (m_pending_trap && (GET_PSR_IAT () || GET_PSR_DAT ())) |
| 655 | { |
| 656 | #ifdef TRACE_PAGE_FAULT |
| 657 | fprintf (stderr, "0x%08x: ## Page fault (fp_readmem_emu).\n", |
| 658 | m_pc); |
| 659 | #endif |
| 660 | m_exiting_readmem = 3; |
| 661 | return; |
| 662 | } |
| 663 | addr = phys; |
| 664 | } |
| 665 | |
| 666 | /* First check for match to db register (before read). */ |
| 667 | if (((addr & ~(size - 1)) == m_cregs[CR_DB]) && GET_PSR_BR ()) |
| 668 | { |
| 669 | SET_PSR_DAT (1); |
| 670 | m_pending_trap = 1; |
| 671 | return; |
| 672 | } |
| 673 | |
| 674 | if (size == 4) |
| 675 | { |
| 676 | dest[0] = m_program->read_byte(addr+3); |
| 677 | dest[1] = m_program->read_byte(addr+2); |
| 678 | dest[2] = m_program->read_byte(addr+1); |
| 679 | dest[3] = m_program->read_byte(addr+0); |
| 680 | } |
| 681 | else if (size == 8) |
| 682 | { |
| 683 | dest[0] = m_program->read_byte(addr+7); |
| 684 | dest[1] = m_program->read_byte(addr+6); |
| 685 | dest[2] = m_program->read_byte(addr+5); |
| 686 | dest[3] = m_program->read_byte(addr+4); |
| 687 | dest[4] = m_program->read_byte(addr+3); |
| 688 | dest[5] = m_program->read_byte(addr+2); |
| 689 | dest[6] = m_program->read_byte(addr+1); |
| 690 | dest[7] = m_program->read_byte(addr+0); |
| 691 | } |
| 692 | else if (size == 16) |
| 693 | { |
| 694 | int i; |
| 695 | for (i = 0; i < 16; i++) |
| 696 | { |
| 697 | dest[i] = m_program->read_byte(addr+15-i); |
| 698 | } |
| 699 | } |
| 700 | } |
| 701 | |
| 702 | |
| 703 | /* Floating-point write mem routine. |
| 704 | addr = address to read. |
| 705 | size = size of read in bytes. |
| 706 | data = pointer to the data. |
| 707 | wmask = bit mask of bytes to write (only for pst.d). */ |
| 708 | void i860_cpu_device::fp_writemem_emu (UINT32 addr, int size, UINT8 *data, UINT32 wmask) |
| 709 | { |
| 710 | #ifdef TRACE_RDWR_MEM |
| 711 | fprintf (stderr, "fp_writemem_emu: (ATE=%d) addr = 0x%08x, size = %d\n", |
| 712 | GET_DIRBASE_ATE (), addr, size); |
| 713 | #endif |
| 714 | |
| 715 | assert (size == 4 || size == 8 || size == 16); |
| 716 | |
| 717 | /* If virtual mode, do translation. */ |
| 718 | if (GET_DIRBASE_ATE ()) |
| 719 | { |
| 720 | UINT32 phys = get_address_translation (addr, 1 /* is_dataref */, 1 /* is_write */); |
| 721 | if (m_pending_trap && GET_PSR_DAT ()) |
| 722 | { |
| 723 | #ifdef TRACE_PAGE_FAULT |
| 724 | fprintf (stderr, "0x%08x: ## Page fault (fp_writememi_emu).\n", |
| 725 | m_pc); |
| 726 | #endif |
| 727 | m_exiting_readmem = 4; |
| 728 | return; |
| 729 | } |
| 730 | addr = phys; |
| 731 | } |
| 732 | |
| 733 | /* First check for match to db register (before read). */ |
| 734 | if (((addr & ~(size - 1)) == m_cregs[CR_DB]) && GET_PSR_BW ()) |
| 735 | { |
| 736 | SET_PSR_DAT (1); |
| 737 | m_pending_trap = 1; |
| 738 | return; |
| 739 | } |
| 740 | |
| 741 | if (size == 4) |
| 742 | { |
| 743 | #if 1 |
| 744 | m_program->write_byte(addr+3, data[0]); |
| 745 | m_program->write_byte(addr+2, data[1]); |
| 746 | m_program->write_byte(addr+1, data[2]); |
| 747 | m_program->write_byte(addr+0, data[3]); |
| 748 | #else |
| 749 | UINT32 ddd = (data[3]) | (data[2] << 8) | (data[1] << 16) |(data[0] << 24); |
| 750 | m_program->write_dword(addr+0, ddd); |
| 751 | #endif |
| 752 | } |
| 753 | else if (size == 8) |
| 754 | { |
| 755 | /* Special: watch for wmask != 0xff, which means we're doing pst.d. */ |
| 756 | if (wmask == 0xff) |
| 757 | { |
| 758 | m_program->write_byte(addr+7, data[0]); |
| 759 | m_program->write_byte(addr+6, data[1]); |
| 760 | m_program->write_byte(addr+5, data[2]); |
| 761 | m_program->write_byte(addr+4, data[3]); |
| 762 | m_program->write_byte(addr+3, data[4]); |
| 763 | m_program->write_byte(addr+2, data[5]); |
| 764 | m_program->write_byte(addr+1, data[6]); |
| 765 | m_program->write_byte(addr+0, data[7]); |
| 766 | } |
| 767 | else |
| 768 | { |
| 769 | if (wmask & 0x80) m_program->write_byte(addr+7, data[0]); |
| 770 | if (wmask & 0x40) m_program->write_byte(addr+6, data[1]); |
| 771 | if (wmask & 0x20) m_program->write_byte(addr+5, data[2]); |
| 772 | if (wmask & 0x10) m_program->write_byte(addr+4, data[3]); |
| 773 | if (wmask & 0x08) m_program->write_byte(addr+3, data[4]); |
| 774 | if (wmask & 0x04) m_program->write_byte(addr+2, data[5]); |
| 775 | if (wmask & 0x02) m_program->write_byte(addr+1, data[6]); |
| 776 | if (wmask & 0x01) m_program->write_byte(addr+0, data[7]); |
| 777 | } |
| 778 | } |
| 779 | else if (size == 16) |
| 780 | { |
| 781 | int i; |
| 782 | for (i = 0; i < 16; i++) |
| 783 | { |
| 784 | m_program->write_byte(addr+15-i, data[i]); |
| 785 | } |
| 786 | } |
| 787 | |
| 788 | } |
| 789 | |
| 790 | |
| 791 | #if 0 |
| 792 | /* Do a pipeline dump. |
| 793 | type: 0 (all), 1 (add), 2 (mul), 3 (load), 4 (graphics). */ |
| 794 | void i860_cpu_device::dump_pipe (int type) |
| 795 | { |
| 796 | int i = 0; |
| 797 | |
| 798 | fprintf (stderr, "pipeline state:\n"); |
| 799 | /* Dump the adder pipeline, if requested. */ |
| 800 | if (type == 0 || type == 1) |
| 801 | { |
| 802 | fprintf (stderr, " A: "); |
| 803 | for (i = 0; i < 3; i++) |
| 804 | { |
| 805 | if (m_A[i].stat.arp) |
| 806 | fprintf (stderr, "[%dd] 0x%016llx ", i + 1, |
| 807 | *(UINT64 *)(&m_A[i].val.d)); |
| 808 | else |
| 809 | fprintf (stderr, "[%ds] 0x%08x ", i + 1, |
| 810 | *(UINT32 *)(&m_A[i].val.s)); |
| 811 | } |
| 812 | fprintf (stderr, "\n"); |
| 813 | } |
| 814 | |
| 815 | |
| 816 | /* Dump the multiplier pipeline, if requested. */ |
| 817 | if (type == 0 || type == 2) |
| 818 | { |
| 819 | fprintf (stderr, " M: "); |
| 820 | for (i = 0; i < 3; i++) |
| 821 | { |
| 822 | if (m_M[i].stat.mrp) |
| 823 | fprintf (stderr, "[%dd] 0x%016llx ", i + 1, |
| 824 | *(UINT64 *)(&m_M[i].val.d)); |
| 825 | else |
| 826 | fprintf (stderr, "[%ds] 0x%08x ", i + 1, |
| 827 | *(UINT32 *)(&m_M[i].val.s)); |
| 828 | } |
| 829 | fprintf (stderr, "\n"); |
| 830 | } |
| 831 | |
| 832 | /* Dump the load pipeline, if requested. */ |
| 833 | if (type == 0 || type == 3) |
| 834 | { |
| 835 | fprintf (stderr, " L: "); |
| 836 | for (i = 0; i < 3; i++) |
| 837 | { |
| 838 | if (m_L[i].stat.lrp) |
| 839 | fprintf (stderr, "[%dd] 0x%016llx ", i + 1, |
| 840 | *(UINT64 *)(&m_L[i].val.d)); |
| 841 | else |
| 842 | fprintf (stderr, "[%ds] 0x%08x ", i + 1, |
| 843 | *(UINT32 *)(&m_L[i].val.s)); |
| 844 | } |
| 845 | fprintf (stderr, "\n"); |
| 846 | } |
| 847 | |
| 848 | /* Dump the graphics pipeline, if requested. */ |
| 849 | if (type == 0 || type == 4) |
| 850 | { |
| 851 | fprintf (stderr, " I: "); |
| 852 | if (m_G.stat.irp) |
| 853 | fprintf (stderr, "[1d] 0x%016llx\n", |
| 854 | *(UINT64 *)(&m_G.val.d)); |
| 855 | else |
| 856 | fprintf (stderr, "[1s] 0x%08x\n", |
| 857 | *(UINT32 *)(&m_G.val.s)); |
| 858 | } |
| 859 | } |
| 860 | |
| 861 | |
| 862 | /* Do a register/state dump. */ |
| 863 | void i860_cpu_device::dump_state (i860s *cpustate) |
| 864 | { |
| 865 | int rn; |
| 866 | |
| 867 | /* GR's first, 4 per line. */ |
| 868 | for (rn = 0; rn < 32; rn++) |
| 869 | { |
| 870 | if ((rn % 4) == 0) |
| 871 | fprintf (stderr, "\n"); |
| 872 | fprintf (stderr, "%%r%-3d: 0x%08x ", rn, get_iregval (rn)); |
| 873 | } |
| 874 | fprintf (stderr, "\n"); |
| 875 | |
| 876 | /* FR's (as 32-bits), 4 per line. */ |
| 877 | for (rn = 0; rn < 32; rn++) |
| 878 | { |
| 879 | float ff = get_fregval_s (rn); |
| 880 | if ((rn % 4) == 0) |
| 881 | fprintf (stderr, "\n"); |
| 882 | fprintf (stderr, "%%f%-3d: 0x%08x ", rn, *(UINT32 *)&ff); |
| 883 | } |
| 884 | fprintf (stderr, "\n"); |
| 885 | |
| 886 | fprintf (stderr, " psr: CC = %d, LCC = %d, SC = %d, IM = %d, U = %d\n", |
| 887 | GET_PSR_CC (), GET_PSR_LCC (), GET_PSR_SC (), GET_PSR_IM (), |
| 888 | GET_PSR_U ()); |
| 889 | fprintf (stderr, " IT/FT/IAT/DAT/IN = %d/%d/%d/%d/%d\n", |
| 890 | GET_PSR_IT (), GET_PSR_FT (), GET_PSR_IAT (), |
| 891 | GET_PSR_DAT (), GET_PSR_IN ()); |
| 892 | fprintf (stderr, "epsr: INT = %d, OF = %d, BE = %d\n", |
| 893 | GET_EPSR_INT (), GET_EPSR_OF (), GET_EPSR_BE ()); |
| 894 | fprintf (stderr, " fir: 0x%08x dirbase: 0x%08x fsr: 0x%08x\n", |
| 895 | m_cregs[CR_FIR], m_cregs[CR_DIRBASE], |
| 896 | m_cregs[CR_FSR]); |
| 897 | fprintf (stderr, " pc: 0x%08x\n", m_pc); |
| 898 | } |
| 899 | #endif |
| 900 | |
| 901 | /* Sign extend N-bit number. */ |
| 902 | INLINE INT32 sign_ext (UINT32 x, int n) |
| 903 | { |
| 904 | INT32 t; |
| 905 | t = x >> (n - 1); |
| 906 | t = ((-t) << n) | x; |
| 907 | return t; |
| 908 | } |
| 909 | |
| 910 | |
| 911 | void i860_cpu_device::unrecog_opcode (UINT32 pc, UINT32 insn) |
| 912 | { |
| 913 | fprintf (stderr, "0x%08x: 0x%08x (unrecognized opcode)\n", pc, insn); |
| 914 | } |
| 915 | |
| 916 | |
| 917 | /* Execute "ld.c csrc2,idest" instruction. */ |
| 918 | void i860_cpu_device::insn_ld_ctrl (UINT32 insn) |
| 919 | { |
| 920 | UINT32 csrc2 = get_creg (insn); |
| 921 | UINT32 idest = get_idest (insn); |
| 922 | |
| 923 | #ifdef TRACE_UNDEFINED_I860 |
| 924 | if (csrc2 > 5) |
| 925 | { |
| 926 | /* Control register not between 0..5. Undefined i860XR behavior. */ |
| 927 | fprintf (stderr, "WARNING: insn_ld_from_ctrl (pc=0x%08x): bad creg in ld.c (ignored)\n", m_pc); |
| 928 | return; |
| 929 | } |
| 930 | #endif |
| 931 | |
| 932 | /* If this is a load of the fir, then there are two cases: |
| 933 | 1. First load of fir after a trap = usual value. |
| 934 | 2. Not first load of fir after a trap = address of the ld.c insn. */ |
| 935 | if (csrc2 == CR_FIR) |
| 936 | { |
| 937 | if (m_fir_gets_trap_addr) |
| 938 | set_iregval (idest, m_cregs[csrc2]); |
| 939 | else |
| 940 | { |
| 941 | m_cregs[csrc2] = m_pc; |
| 942 | set_iregval (idest, m_cregs[csrc2]); |
| 943 | } |
| 944 | m_fir_gets_trap_addr = 0; |
| 945 | } |
| 946 | else |
| 947 | set_iregval (idest, m_cregs[csrc2]); |
| 948 | } |
| 949 | |
| 950 | |
| 951 | /* Execute "st.c isrc1,csrc2" instruction. */ |
| 952 | void i860_cpu_device::insn_st_ctrl (UINT32 insn) |
| 953 | { |
| 954 | UINT32 csrc2 = get_creg (insn); |
| 955 | UINT32 isrc1 = get_isrc1 (insn); |
| 956 | |
| 957 | #ifdef TRACE_UNDEFINED_I860 |
| 958 | if (csrc2 > 5) |
| 959 | { |
| 960 | /* Control register not between 0..5. Undefined i860XR behavior. */ |
| 961 | fprintf (stderr, "WARNING: insn_st_to_ctrl (pc=0x%08x): bad creg in st.c (ignored)\n", m_pc); |
| 962 | return; |
| 963 | } |
| 964 | #endif |
| 965 | |
| 966 | /* Look for ITI bit turned on (but it never actually is written -- |
| 967 | it always appears to be 0). */ |
| 968 | if (csrc2 == CR_DIRBASE && (get_iregval (isrc1) & 0x20)) |
| 969 | { |
| 970 | /* NOTE: The actual icache and TLB flush are unimplemented for |
| 971 | the MAME version. */ |
| 972 | |
| 973 | /* Make sure ITI isn't actually written. */ |
| 974 | set_iregval (isrc1, (get_iregval (isrc1) & ~0x20)); |
| 975 | } |
| 976 | |
| 977 | if (csrc2 == CR_DIRBASE && (get_iregval (isrc1) & 1) |
| 978 | && GET_DIRBASE_ATE () == 0) |
| 979 | { |
| 980 | fprintf (stderr, "0x%08x: ** ATE going high!\n", m_pc); |
| 981 | } |
| 982 | |
| 983 | /* Update the register -- unless it is fir which cannot be updated. */ |
| 984 | if (csrc2 == CR_EPSR) |
| 985 | { |
| 986 | UINT32 enew = 0, tmp = 0; |
| 987 | /* Make sure unchangeable EPSR bits stay unchanged (DCS, stepping, |
| 988 | and type). Also, some bits are only writeable in supervisor |
| 989 | mode. */ |
| 990 | if (GET_PSR_U ()) |
| 991 | { |
| 992 | enew = get_iregval (isrc1) & ~(0x003e1fff | 0x00c06000); |
| 993 | tmp = m_cregs[CR_EPSR] & (0x003e1fff | 0x00c06000); |
| 994 | } |
| 995 | else |
| 996 | { |
| 997 | enew = get_iregval (isrc1) & ~0x003e1fff; |
| 998 | tmp = m_cregs[CR_EPSR] & 0x003e1fff; |
| 999 | } |
| 1000 | m_cregs[CR_EPSR] = enew | tmp; |
| 1001 | } |
| 1002 | else if (csrc2 == CR_PSR) |
| 1003 | { |
| 1004 | /* Some PSR bits are only writeable in supervisor mode. */ |
| 1005 | if (GET_PSR_U ()) |
| 1006 | { |
| 1007 | UINT32 enew = get_iregval (isrc1) & ~PSR_SUPERVISOR_ONLY_MASK; |
| 1008 | UINT32 tmp = m_cregs[CR_PSR] & PSR_SUPERVISOR_ONLY_MASK; |
| 1009 | m_cregs[CR_PSR] = enew | tmp; |
| 1010 | } |
| 1011 | else |
| 1012 | m_cregs[CR_PSR] = get_iregval (isrc1); |
| 1013 | } |
| 1014 | else if (csrc2 == CR_FSR) |
| 1015 | { |
| 1016 | /* I believe that only 21..17, 8..5, and 3..0 should be updated. */ |
| 1017 | UINT32 enew = get_iregval (isrc1) & 0x003e01ef; |
| 1018 | UINT32 tmp = m_cregs[CR_FSR] & ~0x003e01ef; |
| 1019 | m_cregs[CR_FSR] = enew | tmp; |
| 1020 | } |
| 1021 | else if (csrc2 != CR_FIR) |
| 1022 | m_cregs[csrc2] = get_iregval (isrc1); |
| 1023 | } |
| 1024 | |
| 1025 | |
| 1026 | /* Execute "ld.{s,b,l} isrc1(isrc2),idest" or |
| 1027 | "ld.{s,b,l} #const(isrc2),idest". */ |
| 1028 | void i860_cpu_device::insn_ldx (UINT32 insn) |
| 1029 | { |
| 1030 | UINT32 isrc1 = get_isrc1 (insn); |
| 1031 | INT32 immsrc1 = sign_ext (get_imm16 (insn), 16); |
| 1032 | UINT32 isrc2 = get_isrc2 (insn); |
| 1033 | UINT32 idest = get_idest (insn); |
| 1034 | UINT32 eff = 0; |
| 1035 | /* Operand size, in bytes. */ |
| 1036 | int sizes[4] = { 1, 1, 2, 4}; |
| 1037 | int size = 0; |
| 1038 | int form_disp_reg = 0; |
| 1039 | |
| 1040 | /* Bits 28 and 0 determine the operand size. */ |
| 1041 | size = sizes[((insn >> 27) & 2) | (insn & 1)]; |
| 1042 | |
| 1043 | /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */ |
| 1044 | form_disp_reg = (insn & 0x04000000); |
| 1045 | |
| 1046 | /* Get effective address depending on disp+reg or reg+reg form. */ |
| 1047 | if (form_disp_reg) |
| 1048 | { |
| 1049 | /* Chop off lower bits of displacement. */ |
| 1050 | immsrc1 &= ~(size - 1); |
| 1051 | eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2))); |
| 1052 | } |
| 1053 | else |
| 1054 | eff = get_iregval (isrc1) + get_iregval (isrc2); |
| 1055 | |
| 1056 | #ifdef TRACE_UNALIGNED_MEM |
| 1057 | if (eff & (size - 1)) |
| 1058 | { |
| 1059 | fprintf (stderr, "0x%08x: Unaligned access detected (0x%08x).\n", |
| 1060 | m_pc, eff); |
| 1061 | SET_PSR_DAT (1); |
| 1062 | m_pending_trap = 1; |
| 1063 | return; |
| 1064 | } |
| 1065 | #endif |
| 1066 | |
| 1067 | /* The i860 sign-extends 8- or 16-bit integer loads. |
| 1068 | |
| 1069 | Below, the readmemi_emu() needs to happen outside of the |
| 1070 | set_iregval macro (otherwise the readmem won't occur if r0 |
| 1071 | is the target register). */ |
| 1072 | if (size < 4) |
| 1073 | { |
| 1074 | UINT32 readval = sign_ext (readmemi_emu (eff, size), size * 8); |
| 1075 | /* Do not update register on page fault. */ |
| 1076 | if (m_exiting_readmem) |
| 1077 | { |
| 1078 | return; |
| 1079 | } |
| 1080 | set_iregval (idest, readval); |
| 1081 | } |
| 1082 | else |
| 1083 | { |
| 1084 | UINT32 readval = readmemi_emu (eff, size); |
| 1085 | /* Do not update register on page fault. */ |
| 1086 | if (m_exiting_readmem) |
| 1087 | { |
| 1088 | return; |
| 1089 | } |
| 1090 | set_iregval (idest, readval); |
| 1091 | } |
| 1092 | } |
| 1093 | |
| 1094 | |
| 1095 | /* Execute "st.x isrc1ni,#const(isrc2)" instruction (there is no |
| 1096 | (reg + reg form). Store uses the split immediate, not the normal |
| 1097 | 16-bit immediate as in ld.x. */ |
| 1098 | void i860_cpu_device::insn_stx (UINT32 insn) |
| 1099 | { |
| 1100 | INT32 immsrc = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); |
| 1101 | UINT32 isrc1 = get_isrc1 (insn); |
| 1102 | UINT32 isrc2 = get_isrc2 (insn); |
| 1103 | UINT32 eff = 0; |
| 1104 | /* Operand size, in bytes. */ |
| 1105 | int sizes[4] = { 1, 1, 2, 4}; |
| 1106 | int size = 0; |
| 1107 | |
| 1108 | /* Bits 28 and 0 determine the operand size. */ |
| 1109 | size = sizes[((insn >> 27) & 2) | (insn & 1)]; |
| 1110 | |
| 1111 | /* FIXME: Do any necessary traps. */ |
| 1112 | |
| 1113 | /* Get effective address. Chop off lower bits of displacement. */ |
| 1114 | immsrc &= ~(size - 1); |
| 1115 | eff = (UINT32)(immsrc + (INT32)get_iregval (isrc2)); |
| 1116 | |
| 1117 | /* Write data (value of reg isrc1) to memory at eff. */ |
| 1118 | writememi_emu (eff, size, get_iregval (isrc1)); |
| 1119 | if (m_exiting_readmem) |
| 1120 | return; |
| 1121 | } |
| 1122 | |
| 1123 | |
| 1124 | /* Execute "fst.y fdest,isrc1(isrc2)", "fst.y fdest,isrc1(isrc2)++", |
| 1125 | "fst.y fdest,#const(isrc2)" or "fst.y fdest,#const(isrc2)++" |
| 1126 | instruction. */ |
| 1127 | void i860_cpu_device::insn_fsty (UINT32 insn) |
| 1128 | { |
| 1129 | UINT32 isrc1 = get_isrc1 (insn); |
| 1130 | INT32 immsrc1 = sign_ext (get_imm16 (insn), 16); |
| 1131 | UINT32 isrc2 = get_isrc2 (insn); |
| 1132 | UINT32 fdest = get_fdest (insn); |
| 1133 | UINT32 eff = 0; |
| 1134 | /* Operand size, in bytes. */ |
| 1135 | int sizes[4] = { 8, 4, 16, 4}; |
| 1136 | int size = 0; |
| 1137 | int form_disp_reg = 0; |
| 1138 | int auto_inc = (insn & 1); |
| 1139 | |
| 1140 | /* Bits 2 and 1 determine the operand size. */ |
| 1141 | size = sizes[((insn >> 1) & 3)]; |
| 1142 | |
| 1143 | /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */ |
| 1144 | form_disp_reg = (insn & 0x04000000); |
| 1145 | |
| 1146 | /* FIXME: Check for undefined behavior, non-even or non-quad |
| 1147 | register operands for fst.d and fst.q respectively. */ |
| 1148 | |
| 1149 | /* Get effective address depending on disp+reg or reg+reg form. */ |
| 1150 | if (form_disp_reg) |
| 1151 | { |
| 1152 | /* Chop off lower bits of displacement. */ |
| 1153 | immsrc1 &= ~(size - 1); |
| 1154 | eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2))); |
| 1155 | } |
| 1156 | else |
| 1157 | eff = get_iregval (isrc1) + get_iregval (isrc2); |
| 1158 | |
| 1159 | #ifdef TRACE_UNALIGNED_MEM |
| 1160 | if (eff & (size - 1)) |
| 1161 | { |
| 1162 | fprintf (stderr, "0x%08x: Unaligned access detected (0x%08x).\n", |
| 1163 | m_pc, eff); |
| 1164 | SET_PSR_DAT (1); |
| 1165 | m_pending_trap = 1; |
| 1166 | return; |
| 1167 | } |
| 1168 | #endif |
| 1169 | |
| 1170 | /* Do (post) auto-increment. */ |
| 1171 | if (auto_inc) |
| 1172 | { |
| 1173 | set_iregval (isrc2, eff); |
| 1174 | #ifdef TRACE_UNDEFINED_I860 |
| 1175 | /* When auto-inc, isrc1 and isrc2 regs can't be the same. */ |
| 1176 | if (isrc1 == isrc2) |
| 1177 | { |
| 1178 | /* Undefined i860XR behavior. */ |
| 1179 | fprintf (stderr, "WARNING: insn_fsty (pc=0x%08x): isrc1 = isrc2 in fst with auto-inc (ignored)\n", m_pc); |
| 1180 | return; |
| 1181 | } |
| 1182 | #endif |
| 1183 | } |
| 1184 | |
| 1185 | /* Write data (value of freg fdest) to memory at eff. */ |
| 1186 | if (size == 4) |
| 1187 | fp_writemem_emu (eff, size, (UINT8 *)(&m_frg[4 * (31 - fdest)]), 0xff); |
| 1188 | else if (size == 8) |
| 1189 | fp_writemem_emu (eff, size, (UINT8 *)(&m_frg[4 * (31 - (fdest + 1))]), 0xff); |
| 1190 | else |
| 1191 | fp_writemem_emu (eff, size, (UINT8 *)(&m_frg[4 * (31 - (fdest + 3))]), 0xff); |
| 1192 | |
| 1193 | } |
| 1194 | |
| 1195 | |
| 1196 | /* Execute "fld.y isrc1(isrc2),fdest", "fld.y isrc1(isrc2)++,idest", |
| 1197 | "fld.y #const(isrc2),fdest" or "fld.y #const(isrc2)++,idest". |
| 1198 | Where y = {l,d,q}. Note, there is no pfld.q, though. */ |
| 1199 | void i860_cpu_device::insn_fldy (UINT32 insn) |
| 1200 | { |
| 1201 | UINT32 isrc1 = get_isrc1 (insn); |
| 1202 | INT32 immsrc1 = sign_ext (get_imm16 (insn), 16); |
| 1203 | UINT32 isrc2 = get_isrc2 (insn); |
| 1204 | UINT32 fdest = get_fdest (insn); |
| 1205 | UINT32 eff = 0; |
| 1206 | /* Operand size, in bytes. */ |
| 1207 | int sizes[4] = { 8, 4, 16, 4}; |
| 1208 | int size = 0; |
| 1209 | int form_disp_reg = 0; |
| 1210 | int auto_inc = (insn & 1); |
| 1211 | int piped = (insn & 0x40000000); |
| 1212 | |
| 1213 | /* Bits 2 and 1 determine the operand size. */ |
| 1214 | size = sizes[((insn >> 1) & 3)]; |
| 1215 | |
| 1216 | /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */ |
| 1217 | form_disp_reg = (insn & 0x04000000); |
| 1218 | |
| 1219 | /* There is no pipelined load quad. */ |
| 1220 | if (piped && size == 16) |
| 1221 | { |
| 1222 | unrecog_opcode (m_pc, insn); |
| 1223 | return; |
| 1224 | } |
| 1225 | |
| 1226 | /* FIXME: Check for undefined behavior, non-even or non-quad |
| 1227 | register operands for fld.d and fld.q respectively. */ |
| 1228 | |
| 1229 | /* Get effective address depending on disp+reg or reg+reg form. */ |
| 1230 | if (form_disp_reg) |
| 1231 | { |
| 1232 | /* Chop off lower bits of displacement. */ |
| 1233 | immsrc1 &= ~(size - 1); |
| 1234 | eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2))); |
| 1235 | } |
| 1236 | else |
| 1237 | eff = get_iregval (isrc1) + get_iregval (isrc2); |
| 1238 | |
| 1239 | /* Do (post) auto-increment. */ |
| 1240 | if (auto_inc) |
| 1241 | { |
| 1242 | set_iregval (isrc2, eff); |
| 1243 | #ifdef TRACE_UNDEFINED_I860 |
| 1244 | /* When auto-inc, isrc1 and isrc2 regs can't be the same. */ |
| 1245 | if (isrc1 == isrc2) |
| 1246 | { |
| 1247 | /* Undefined i860XR behavior. */ |
| 1248 | fprintf (stderr, "WARNING: insn_fldy (pc=0x%08x): isrc1 = isrc2 in fst with auto-inc (ignored)\n", m_pc); |
| 1249 | return; |
| 1250 | } |
| 1251 | #endif |
| 1252 | } |
| 1253 | |
| 1254 | #ifdef TRACE_UNALIGNED_MEM |
| 1255 | if (eff & (size - 1)) |
| 1256 | { |
| 1257 | fprintf (stderr, "0x%08x: Unaligned access detected (0x%08x).\n", |
| 1258 | m_pc, eff); |
| 1259 | SET_PSR_DAT (1); |
| 1260 | m_pending_trap = 1; |
| 1261 | return; |
| 1262 | } |
| 1263 | #endif |
| 1264 | |
| 1265 | /* Update the load pipe if necessary. */ |
| 1266 | /* FIXME: Copy result-status bits to fsr from last stage. */ |
| 1267 | if (!piped) |
| 1268 | { |
| 1269 | /* Scalar version writes the current result to fdest. */ |
| 1270 | /* Read data at 'eff' into freg 'fdest' (reads to f0 or f1 are |
| 1271 | thrown away). */ |
| 1272 | if (fdest > 1) |
| 1273 | { |
| 1274 | if (size == 4) |
| 1275 | fp_readmem_emu (eff, size, (UINT8 *)&(m_frg[4 * (31 - fdest)])); |
| 1276 | else if (size == 8) |
| 1277 | fp_readmem_emu (eff, size, (UINT8 *)&(m_frg[4 * (31 - (fdest + 1))])); |
| 1278 | else if (size == 16) |
| 1279 | fp_readmem_emu (eff, size, (UINT8 *)&(m_frg[4 * (31 - (fdest + 3))])); |
| 1280 | } |
| 1281 | } |
| 1282 | else |
| 1283 | { |
| 1284 | /* Read the data into a temp space first. This way we can test |
| 1285 | for any traps before updating the pipeline. The pipeline must |
| 1286 | stay unaffected after a trap so that the instruction can be |
| 1287 | properly restarted. */ |
| 1288 | UINT8 bebuf[8]; |
| 1289 | fp_readmem_emu (eff, size, bebuf); |
| 1290 | if (m_pending_trap && m_exiting_readmem) |
| 1291 | goto ab_op; |
| 1292 | |
| 1293 | /* Pipelined version writes fdest with the result from the last |
| 1294 | stage of the pipeline, with precision specified by the LRP |
| 1295 | bit of the stage's result-status bits. */ |
| 1296 | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 1297 | /* Copy 3rd stage LRP to FSR. */ |
| 1298 | if (m_L[1 /* 2 */].stat.lrp) |
| 1299 | m_cregs[CR_FSR] |= 0x04000000; |
| 1300 | else |
| 1301 | m_cregs[CR_FSR] &= ~0x04000000; |
| 1302 | #endif |
| 1303 | if (m_L[2].stat.lrp) /* 3rd (last) stage. */ |
| 1304 | set_fregval_d (fdest, m_L[2].val.d); |
| 1305 | else |
| 1306 | set_fregval_s (fdest, m_L[2].val.s); |
| 1307 | |
| 1308 | /* Now advance pipeline and write loaded data to first stage. */ |
| 1309 | m_L[2] = m_L[1]; |
| 1310 | m_L[1] = m_L[0]; |
| 1311 | if (size == 8) |
| 1312 | { |
| 1313 | UINT8 *t = (UINT8 *)&(m_L[0].val.d); |
| 1314 | #ifndef HOST_MSB |
| 1315 | t[7] = bebuf[0]; t[6] = bebuf[1]; t[5] = bebuf[2]; t[4] = bebuf[3]; |
| 1316 | t[3] = bebuf[4]; t[2] = bebuf[5]; t[1] = bebuf[6]; t[0] = bebuf[7]; |
| 1317 | #else |
| 1318 | t[0] = bebuf[0]; t[1] = bebuf[1]; t[2] = bebuf[2]; t[3] = bebuf[3]; |
| 1319 | t[4] = bebuf[4]; t[5] = bebuf[5]; t[6] = bebuf[6]; t[7] = bebuf[7]; |
| 1320 | #endif |
| 1321 | m_L[0].stat.lrp = 1; |
| 1322 | } |
| 1323 | else |
| 1324 | { |
| 1325 | UINT8 *t = (UINT8 *)&(m_L[0].val.s); |
| 1326 | #ifndef HOST_MSB |
| 1327 | t[3] = bebuf[0]; t[2] = bebuf[1]; t[1] = bebuf[2]; t[0] = bebuf[3]; |
| 1328 | #else |
| 1329 | t[0] = bebuf[0]; t[1] = bebuf[1]; t[2] = bebuf[2]; t[3] = bebuf[3]; |
| 1330 | #endif |
| 1331 | m_L[0].stat.lrp = 0; |
| 1332 | } |
| 1333 | } |
| 1334 | |
| 1335 | ab_op:; |
| 1336 | } |
| 1337 | |
| 1338 | |
| 1339 | /* Execute "pst.d fdest,#const(isrc2)" or "fst.d fdest,#const(isrc2)++" |
| 1340 | instruction. */ |
| 1341 | void i860_cpu_device::insn_pstd (UINT32 insn) |
| 1342 | { |
| 1343 | INT32 immsrc1 = sign_ext (get_imm16 (insn), 16); |
| 1344 | UINT32 isrc2 = get_isrc2 (insn); |
| 1345 | UINT32 fdest = get_fdest (insn); |
| 1346 | UINT32 eff = 0; |
| 1347 | int auto_inc = (insn & 1); |
| 1348 | UINT8 *bebuf = 0; |
| 1349 | int pm = GET_PSR_PM (); |
| 1350 | int i; |
| 1351 | UINT32 wmask; |
| 1352 | int orig_pm = pm; |
| 1353 | |
| 1354 | /* Get the pixel size, where: |
| 1355 | PS: 0 = 8 bits, 1 = 16 bits, 2 = 32-bits. */ |
| 1356 | int ps = GET_PSR_PS (); |
| 1357 | |
| 1358 | #ifdef TRACE_UNDEFINED_I860 |
| 1359 | if (!(ps == 0 || ps == 1 || ps == 2)) |
| 1360 | fprintf (stderr, "insn_pstd: Undefined i860XR behavior, invalid value %d for pixel size.\n", ps); |
| 1361 | #endif |
| 1362 | |
| 1363 | #ifdef TRACE_UNDEFINED_I860 |
| 1364 | /* Bits 2 and 1 determine the operand size, which must always be |
| 1365 | zero (indicating a 64-bit operand). */ |
| 1366 | if (insn & 0x6) |
| 1367 | { |
| 1368 | /* Undefined i860XR behavior. */ |
| 1369 | fprintf (stderr, "WARNING: insn_pstd (pc=0x%08x): bad operand size specifier\n", m_pc); |
| 1370 | } |
| 1371 | #endif |
| 1372 | |
| 1373 | /* FIXME: Check for undefined behavior, non-even register operands. */ |
| 1374 | |
| 1375 | /* Get effective address. Chop off lower bits of displacement. */ |
| 1376 | immsrc1 &= ~(8 - 1); |
| 1377 | eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2))); |
| 1378 | |
| 1379 | #ifdef TRACE_UNALIGNED_MEM |
| 1380 | if (eff & (8 - 1)) |
| 1381 | { |
| 1382 | fprintf (stderr, "0x%08x: Unaligned access detected (0x%08x).\n", |
| 1383 | m_pc, eff); |
| 1384 | SET_PSR_DAT (1); |
| 1385 | m_pending_trap = 1; |
| 1386 | return; |
| 1387 | } |
| 1388 | #endif |
| 1389 | |
| 1390 | /* Do (post) auto-increment. */ |
| 1391 | if (auto_inc) |
| 1392 | set_iregval (isrc2, eff); |
| 1393 | |
| 1394 | /* Update the the pixel mask depending on the pixel size. Shift PM |
| 1395 | right by 8/2^ps bits. */ |
| 1396 | if (ps == 0) |
| 1397 | pm = (pm >> 8) & 0x00; |
| 1398 | else if (ps == 1) |
| 1399 | pm = (pm >> 4) & 0x0f; |
| 1400 | else if (ps == 2) |
| 1401 | pm = (pm >> 2) & 0x3f; |
| 1402 | SET_PSR_PM (pm); |
| 1403 | |
| 1404 | /* Write data (value of freg fdest) to memory at eff-- but only those |
| 1405 | bytes that are enabled by the bits in PSR.PM. Bit 0 of PM selects |
| 1406 | the pixel at the lowest address. */ |
| 1407 | wmask = 0; |
| 1408 | for (i = 0; i < 8; ) |
| 1409 | { |
| 1410 | if (ps == 0) |
| 1411 | { |
| 1412 | if (orig_pm & 0x80) |
| 1413 | wmask |= 1 << (7-i); |
| 1414 | i += 1; |
| 1415 | } |
| 1416 | else if (ps == 1) |
| 1417 | { |
| 1418 | if (orig_pm & 0x08) |
| 1419 | wmask |= 0x3 << (6-i); |
| 1420 | i += 2; |
| 1421 | } |
| 1422 | else if (ps == 2) |
| 1423 | { |
| 1424 | if (orig_pm & 0x02) |
| 1425 | wmask |= 0xf << (4-i); |
| 1426 | i += 4; |
| 1427 | } |
| 1428 | else |
| 1429 | { |
| 1430 | wmask = 0xff; |
| 1431 | break; |
| 1432 | } |
| 1433 | orig_pm <<= 1; |
| 1434 | } |
| 1435 | bebuf = (UINT8 *)(&m_frg[4 * (31 - (fdest + 1))]); |
| 1436 | fp_writemem_emu (eff, 8, bebuf, wmask); |
| 1437 | } |
| 1438 | |
| 1439 | |
| 1440 | /* Execute "ixfr isrc1ni,fdest" instruction. */ |
| 1441 | void i860_cpu_device::insn_ixfr (UINT32 insn) |
| 1442 | { |
| 1443 | UINT32 isrc1 = get_isrc1 (insn); |
| 1444 | UINT32 fdest = get_fdest (insn); |
| 1445 | UINT32 iv = 0; |
| 1446 | |
| 1447 | /* This is a bit-pattern transfer, not a conversion. */ |
| 1448 | iv = get_iregval (isrc1); |
| 1449 | set_fregval_s (fdest, *(float *)&iv); |
| 1450 | } |
| 1451 | |
| 1452 | |
| 1453 | /* Execute "addu isrc1,isrc2,idest". */ |
| 1454 | void i860_cpu_device::insn_addu (UINT32 insn) |
| 1455 | { |
| 1456 | UINT32 src1val; |
| 1457 | UINT32 isrc2 = get_isrc2 (insn); |
| 1458 | UINT32 idest = get_idest (insn); |
| 1459 | UINT32 tmp_dest_val = 0; |
| 1460 | UINT64 tmp = 0; |
| 1461 | |
| 1462 | src1val = get_iregval (get_isrc1 (insn)); |
| 1463 | |
| 1464 | /* We don't update the actual idest register now because below we |
| 1465 | need to test the original src1 and src2 if either happens to |
| 1466 | be the destination register. */ |
| 1467 | tmp_dest_val = src1val + get_iregval (isrc2); |
| 1468 | |
| 1469 | /* Set OF and CC flags. |
| 1470 | For unsigned: |
| 1471 | OF = bit 31 carry |
| 1472 | CC = bit 31 carry. |
| 1473 | */ |
| 1474 | tmp = (UINT64)src1val + (UINT64)(get_iregval (isrc2)); |
| 1475 | if ((tmp >> 32) & 1) |
| 1476 | { |
| 1477 | SET_PSR_CC (1); |
| 1478 | SET_EPSR_OF (1); |
| 1479 | } |
| 1480 | else |
| 1481 | { |
| 1482 | SET_PSR_CC (0); |
| 1483 | SET_EPSR_OF (0); |
| 1484 | } |
| 1485 | |
| 1486 | /* Now update the destination register. */ |
| 1487 | set_iregval (idest, tmp_dest_val); |
| 1488 | } |
| 1489 | |
| 1490 | |
| 1491 | /* Execute "addu #const,isrc2,idest". */ |
| 1492 | void i860_cpu_device::insn_addu_imm (UINT32 insn) |
| 1493 | { |
| 1494 | UINT32 src1val; |
| 1495 | UINT32 isrc2 = get_isrc2 (insn); |
| 1496 | UINT32 idest = get_idest (insn); |
| 1497 | UINT32 tmp_dest_val = 0; |
| 1498 | UINT64 tmp = 0; |
| 1499 | |
| 1500 | src1val = sign_ext (get_imm16 (insn), 16); |
| 1501 | |
| 1502 | /* We don't update the actual idest register now because below we |
| 1503 | need to test the original src1 and src2 if either happens to |
| 1504 | be the destination register. */ |
| 1505 | tmp_dest_val = src1val + get_iregval (isrc2); |
| 1506 | |
| 1507 | /* Set OF and CC flags. |
| 1508 | For unsigned: |
| 1509 | OF = bit 31 carry |
| 1510 | CC = bit 31 carry. |
| 1511 | */ |
| 1512 | tmp = (UINT64)src1val + (UINT64)(get_iregval (isrc2)); |
| 1513 | if ((tmp >> 32) & 1) |
| 1514 | { |
| 1515 | SET_PSR_CC (1); |
| 1516 | SET_EPSR_OF (1); |
| 1517 | } |
| 1518 | else |
| 1519 | { |
| 1520 | SET_PSR_CC (0); |
| 1521 | SET_EPSR_OF (0); |
| 1522 | } |
| 1523 | |
| 1524 | /* Now update the destination register. */ |
| 1525 | set_iregval (idest, tmp_dest_val); |
| 1526 | } |
| 1527 | |
| 1528 | |
| 1529 | /* Execute "adds isrc1,isrc2,idest". */ |
| 1530 | void i860_cpu_device::insn_adds (UINT32 insn) |
| 1531 | { |
| 1532 | UINT32 src1val; |
| 1533 | UINT32 isrc2 = get_isrc2 (insn); |
| 1534 | UINT32 idest = get_idest (insn); |
| 1535 | UINT32 tmp_dest_val = 0; |
| 1536 | int sa, sb, sres; |
| 1537 | |
| 1538 | src1val = get_iregval (get_isrc1 (insn)); |
| 1539 | |
| 1540 | /* We don't update the actual idest register now because below we |
| 1541 | need to test the original src1 and src2 if either happens to |
| 1542 | be the destination register. */ |
| 1543 | tmp_dest_val = src1val + get_iregval (isrc2); |
| 1544 | |
| 1545 | /* Set OF and CC flags. |
| 1546 | For signed: |
| 1547 | OF = standard signed overflow. |
| 1548 | CC set if isrc2 < -isrc1 |
| 1549 | CC clear if isrc2 >= -isrc1 |
| 1550 | */ |
| 1551 | sa = src1val & 0x80000000; |
| 1552 | sb = get_iregval (isrc2) & 0x80000000; |
| 1553 | sres = tmp_dest_val & 0x80000000; |
| 1554 | if (sa != sb && sa != sres) |
| 1555 | SET_EPSR_OF (1); |
| 1556 | else |
| 1557 | SET_EPSR_OF (0); |
| 1558 | |
| 1559 | if ((INT32)get_iregval (isrc2) < -(INT32)(src1val)) |
| 1560 | SET_PSR_CC (1); |
| 1561 | else |
| 1562 | SET_PSR_CC (0); |
| 1563 | |
| 1564 | /* Now update the destination register. */ |
| 1565 | set_iregval (idest, tmp_dest_val); |
| 1566 | } |
| 1567 | |
| 1568 | |
| 1569 | /* Execute "adds #const,isrc2,idest". */ |
| 1570 | void i860_cpu_device::insn_adds_imm (UINT32 insn) |
| 1571 | { |
| 1572 | UINT32 src1val; |
| 1573 | UINT32 isrc2 = get_isrc2 (insn); |
| 1574 | UINT32 idest = get_idest (insn); |
| 1575 | UINT32 tmp_dest_val = 0; |
| 1576 | int sa, sb, sres; |
| 1577 | |
| 1578 | src1val = sign_ext (get_imm16 (insn), 16); |
| 1579 | |
| 1580 | /* We don't update the actual idest register now because below we |
| 1581 | need to test the original src1 and src2 if either happens to |
| 1582 | be the destination register. */ |
| 1583 | tmp_dest_val = src1val + get_iregval (isrc2); |
| 1584 | |
| 1585 | /* Set OF and CC flags. |
| 1586 | For signed: |
| 1587 | OF = standard signed overflow. |
| 1588 | CC set if isrc2 < -isrc1 |
| 1589 | CC clear if isrc2 >= -isrc1 |
| 1590 | */ |
| 1591 | sa = src1val & 0x80000000; |
| 1592 | sb = get_iregval (isrc2) & 0x80000000; |
| 1593 | sres = tmp_dest_val & 0x80000000; |
| 1594 | if (sa != sb && sa != sres) |
| 1595 | SET_EPSR_OF (1); |
| 1596 | else |
| 1597 | SET_EPSR_OF (0); |
| 1598 | |
| 1599 | if ((INT32)get_iregval (isrc2) < -(INT32)(src1val)) |
| 1600 | SET_PSR_CC (1); |
| 1601 | else |
| 1602 | SET_PSR_CC (0); |
| 1603 | |
| 1604 | /* Now update the destination register. */ |
| 1605 | set_iregval (idest, tmp_dest_val); |
| 1606 | } |
| 1607 | |
| 1608 | |
| 1609 | /* Execute "subu isrc1,isrc2,idest". */ |
| 1610 | void i860_cpu_device::insn_subu (UINT32 insn) |
| 1611 | { |
| 1612 | UINT32 src1val; |
| 1613 | UINT32 isrc2 = get_isrc2 (insn); |
| 1614 | UINT32 idest = get_idest (insn); |
| 1615 | UINT32 tmp_dest_val = 0; |
| 1616 | |
| 1617 | src1val = get_iregval (get_isrc1 (insn)); |
| 1618 | |
| 1619 | /* We don't update the actual idest register now because below we |
| 1620 | need to test the original src1 and src2 if either happens to |
| 1621 | be the destination register. */ |
| 1622 | tmp_dest_val = src1val - get_iregval (isrc2); |
| 1623 | |
| 1624 | /* Set OF and CC flags. |
| 1625 | For unsigned: |
| 1626 | OF = NOT(bit 31 carry) |
| 1627 | CC = bit 31 carry. |
| 1628 | (i.e. CC set if isrc2 <= isrc1 |
| 1629 | CC clear if isrc2 > isrc1 |
| 1630 | */ |
| 1631 | if ((UINT32)get_iregval (isrc2) <= (UINT32)src1val) |
| 1632 | { |
| 1633 | SET_PSR_CC (1); |
| 1634 | SET_EPSR_OF (0); |
| 1635 | } |
| 1636 | else |
| 1637 | { |
| 1638 | SET_PSR_CC (0); |
| 1639 | SET_EPSR_OF (1); |
| 1640 | } |
| 1641 | |
| 1642 | /* Now update the destination register. */ |
| 1643 | set_iregval (idest, tmp_dest_val); |
| 1644 | } |
| 1645 | |
| 1646 | |
| 1647 | /* Execute "subu #const,isrc2,idest". */ |
| 1648 | void i860_cpu_device::insn_subu_imm (UINT32 insn) |
| 1649 | { |
| 1650 | UINT32 src1val; |
| 1651 | UINT32 isrc2 = get_isrc2 (insn); |
| 1652 | UINT32 idest = get_idest (insn); |
| 1653 | UINT32 tmp_dest_val = 0; |
| 1654 | |
| 1655 | src1val = sign_ext (get_imm16 (insn), 16); |
| 1656 | |
| 1657 | /* We don't update the actual idest register now because below we |
| 1658 | need to test the original src1 and src2 if either happens to |
| 1659 | be the destination register. */ |
| 1660 | tmp_dest_val = src1val - get_iregval (isrc2); |
| 1661 | |
| 1662 | /* Set OF and CC flags. |
| 1663 | For unsigned: |
| 1664 | OF = NOT(bit 31 carry) |
| 1665 | CC = bit 31 carry. |
| 1666 | (i.e. CC set if isrc2 <= isrc1 |
| 1667 | CC clear if isrc2 > isrc1 |
| 1668 | */ |
| 1669 | if ((UINT32)get_iregval (isrc2) <= (UINT32)src1val) |
| 1670 | { |
| 1671 | SET_PSR_CC (1); |
| 1672 | SET_EPSR_OF (0); |
| 1673 | } |
| 1674 | else |
| 1675 | { |
| 1676 | SET_PSR_CC (0); |
| 1677 | SET_EPSR_OF (1); |
| 1678 | } |
| 1679 | |
| 1680 | /* Now update the destination register. */ |
| 1681 | set_iregval (idest, tmp_dest_val); |
| 1682 | } |
| 1683 | |
| 1684 | |
| 1685 | /* Execute "subs isrc1,isrc2,idest". */ |
| 1686 | void i860_cpu_device::insn_subs (UINT32 insn) |
| 1687 | { |
| 1688 | UINT32 src1val; |
| 1689 | UINT32 isrc2 = get_isrc2 (insn); |
| 1690 | UINT32 idest = get_idest (insn); |
| 1691 | UINT32 tmp_dest_val = 0; |
| 1692 | int sa, sb, sres; |
| 1693 | |
| 1694 | src1val = get_iregval (get_isrc1 (insn)); |
| 1695 | |
| 1696 | /* We don't update the actual idest register now because below we |
| 1697 | need to test the original src1 and src2 if either happens to |
| 1698 | be the destination register. */ |
| 1699 | tmp_dest_val = src1val - get_iregval (isrc2); |
| 1700 | |
| 1701 | /* Set OF and CC flags. |
| 1702 | For signed: |
| 1703 | OF = standard signed overflow. |
| 1704 | CC set if isrc2 > isrc1 |
| 1705 | CC clear if isrc2 <= isrc1 |
| 1706 | */ |
| 1707 | sa = src1val & 0x80000000; |
| 1708 | sb = get_iregval (isrc2) & 0x80000000; |
| 1709 | sres = tmp_dest_val & 0x80000000; |
| 1710 | if (sa != sb && sa != sres) |
| 1711 | SET_EPSR_OF (1); |
| 1712 | else |
| 1713 | SET_EPSR_OF (0); |
| 1714 | |
| 1715 | if ((INT32)get_iregval (isrc2) > (INT32)(src1val)) |
| 1716 | SET_PSR_CC (1); |
| 1717 | else |
| 1718 | SET_PSR_CC (0); |
| 1719 | |
| 1720 | /* Now update the destination register. */ |
| 1721 | set_iregval (idest, tmp_dest_val); |
| 1722 | } |
| 1723 | |
| 1724 | |
| 1725 | /* Execute "subs #const,isrc2,idest". */ |
| 1726 | void i860_cpu_device::insn_subs_imm (UINT32 insn) |
| 1727 | { |
| 1728 | UINT32 src1val; |
| 1729 | UINT32 isrc2 = get_isrc2 (insn); |
| 1730 | UINT32 idest = get_idest (insn); |
| 1731 | UINT32 tmp_dest_val = 0; |
| 1732 | int sa, sb, sres; |
| 1733 | |
| 1734 | src1val = sign_ext (get_imm16 (insn), 16); |
| 1735 | |
| 1736 | /* We don't update the actual idest register now because below we |
| 1737 | need to test the original src1 and src2 if either happens to |
| 1738 | be the destination register. */ |
| 1739 | tmp_dest_val = src1val - get_iregval (isrc2); |
| 1740 | |
| 1741 | /* Set OF and CC flags. |
| 1742 | For signed: |
| 1743 | OF = standard signed overflow. |
| 1744 | CC set if isrc2 > isrc1 |
| 1745 | CC clear if isrc2 <= isrc1 |
| 1746 | */ |
| 1747 | sa = src1val & 0x80000000; |
| 1748 | sb = get_iregval (isrc2) & 0x80000000; |
| 1749 | sres = tmp_dest_val & 0x80000000; |
| 1750 | if (sa != sb && sa != sres) |
| 1751 | SET_EPSR_OF (1); |
| 1752 | else |
| 1753 | SET_EPSR_OF (0); |
| 1754 | |
| 1755 | if ((INT32)get_iregval (isrc2) > (INT32)(src1val)) |
| 1756 | SET_PSR_CC (1); |
| 1757 | else |
| 1758 | SET_PSR_CC (0); |
| 1759 | |
| 1760 | /* Now update the destination register. */ |
| 1761 | set_iregval (idest, tmp_dest_val); |
| 1762 | } |
| 1763 | |
| 1764 | |
| 1765 | /* Execute "shl isrc1,isrc2,idest". */ |
| 1766 | void i860_cpu_device::insn_shl (UINT32 insn) |
| 1767 | { |
| 1768 | UINT32 src1val = 0; |
| 1769 | UINT32 isrc2 = get_isrc2 (insn); |
| 1770 | UINT32 idest = get_idest (insn); |
| 1771 | |
| 1772 | src1val = get_iregval (get_isrc1 (insn)); |
| 1773 | set_iregval (idest, get_iregval (isrc2) << src1val); |
| 1774 | } |
| 1775 | |
| 1776 | |
| 1777 | /* Execute "shl #const,isrc2,idest". */ |
| 1778 | void i860_cpu_device::insn_shl_imm (UINT32 insn) |
| 1779 | { |
| 1780 | UINT32 src1val = 0; |
| 1781 | UINT32 isrc2 = get_isrc2 (insn); |
| 1782 | UINT32 idest = get_idest (insn); |
| 1783 | |
| 1784 | src1val = sign_ext (get_imm16 (insn), 16); |
| 1785 | set_iregval (idest, get_iregval (isrc2) << src1val); |
| 1786 | } |
| 1787 | |
| 1788 | |
| 1789 | /* Execute "shr isrc1,isrc2,idest". */ |
| 1790 | void i860_cpu_device::insn_shr (UINT32 insn) |
| 1791 | { |
| 1792 | UINT32 src1val = 0; |
| 1793 | UINT32 isrc2 = get_isrc2 (insn); |
| 1794 | UINT32 idest = get_idest (insn); |
| 1795 | |
| 1796 | src1val = get_iregval (get_isrc1 (insn)); |
| 1797 | |
| 1798 | /* The iregs array is UINT32, so this is a logical shift. */ |
| 1799 | set_iregval (idest, get_iregval (isrc2) >> src1val); |
| 1800 | |
| 1801 | /* shr also sets the SC in psr (shift count). */ |
| 1802 | SET_PSR_SC (src1val); |
| 1803 | } |
| 1804 | |
| 1805 | |
| 1806 | /* Execute "shr #const,isrc2,idest". */ |
| 1807 | void i860_cpu_device::insn_shr_imm (UINT32 insn) |
| 1808 | { |
| 1809 | UINT32 src1val = 0; |
| 1810 | UINT32 isrc2 = get_isrc2 (insn); |
| 1811 | UINT32 idest = get_idest (insn); |
| 1812 | |
| 1813 | src1val = sign_ext (get_imm16 (insn), 16); |
| 1814 | |
| 1815 | /* The iregs array is UINT32, so this is a logical shift. */ |
| 1816 | set_iregval (idest, get_iregval (isrc2) >> src1val); |
| 1817 | |
| 1818 | /* shr also sets the SC in psr (shift count). */ |
| 1819 | SET_PSR_SC (src1val); |
| 1820 | } |
| 1821 | |
| 1822 | |
| 1823 | /* Execute "shra isrc1,isrc2,idest". */ |
| 1824 | void i860_cpu_device::insn_shra (UINT32 insn) |
| 1825 | { |
| 1826 | UINT32 src1val = 0; |
| 1827 | UINT32 isrc2 = get_isrc2 (insn); |
| 1828 | UINT32 idest = get_idest (insn); |
| 1829 | |
| 1830 | src1val = get_iregval (get_isrc1 (insn)); |
| 1831 | |
| 1832 | /* The iregs array is UINT32, so cast isrc2 to get arithmetic shift. */ |
| 1833 | set_iregval (idest, (INT32)get_iregval (isrc2) >> src1val); |
| 1834 | } |
| 1835 | |
| 1836 | |
| 1837 | /* Execute "shra #const,isrc2,idest". */ |
| 1838 | void i860_cpu_device::insn_shra_imm (UINT32 insn) |
| 1839 | { |
| 1840 | UINT32 src1val = 0; |
| 1841 | UINT32 isrc2 = get_isrc2 (insn); |
| 1842 | UINT32 idest = get_idest (insn); |
| 1843 | |
| 1844 | src1val = sign_ext (get_imm16 (insn), 16); |
| 1845 | |
| 1846 | /* The iregs array is UINT32, so cast isrc2 to get arithmetic shift. */ |
| 1847 | set_iregval (idest, (INT32)get_iregval (isrc2) >> src1val); |
| 1848 | } |
| 1849 | |
| 1850 | |
| 1851 | /* Execute "shrd isrc1ni,isrc2,idest" instruction. */ |
| 1852 | void i860_cpu_device::insn_shrd (UINT32 insn) |
| 1853 | { |
| 1854 | UINT32 isrc1 = get_isrc1 (insn); |
| 1855 | UINT32 isrc2 = get_isrc2 (insn); |
| 1856 | UINT32 idest = get_idest (insn); |
| 1857 | UINT32 sc = GET_PSR_SC (); |
| 1858 | UINT32 tmp; |
| 1859 | |
| 1860 | /* Do the operation: |
| 1861 | idest = low_32(isrc1ni:isrc2 >> sc). */ |
| 1862 | if (sc == 0) |
| 1863 | tmp = get_iregval (isrc2); |
| 1864 | else |
| 1865 | { |
| 1866 | tmp = get_iregval (isrc1) << (32 - sc); |
| 1867 | tmp |= (get_iregval (isrc2) >> sc); |
| 1868 | } |
| 1869 | set_iregval (idest, tmp); |
| 1870 | } |
| 1871 | |
| 1872 | |
| 1873 | /* Execute "and isrc1,isrc2,idest". */ |
| 1874 | void i860_cpu_device::insn_and (UINT32 insn) |
| 1875 | { |
| 1876 | UINT32 isrc1 = get_isrc1 (insn); |
| 1877 | UINT32 isrc2 = get_isrc2 (insn); |
| 1878 | UINT32 idest = get_idest (insn); |
| 1879 | UINT32 res = 0; |
| 1880 | |
| 1881 | /* Do the operation. */ |
| 1882 | res = get_iregval (isrc1) & get_iregval (isrc2); |
| 1883 | |
| 1884 | /* Set flags. */ |
| 1885 | if (res == 0) |
| 1886 | SET_PSR_CC (1); |
| 1887 | else |
| 1888 | SET_PSR_CC (0); |
| 1889 | |
| 1890 | set_iregval (idest, res); |
| 1891 | } |
| 1892 | |
| 1893 | |
| 1894 | /* Execute "and #const,isrc2,idest". */ |
| 1895 | void i860_cpu_device::insn_and_imm (UINT32 insn) |
| 1896 | { |
| 1897 | UINT32 src1val = 0; |
| 1898 | UINT32 isrc2 = get_isrc2 (insn); |
| 1899 | UINT32 idest = get_idest (insn); |
| 1900 | UINT32 res = 0; |
| 1901 | |
| 1902 | /* Do the operation. */ |
| 1903 | src1val = get_imm16 (insn); |
| 1904 | res = src1val & get_iregval (isrc2); |
| 1905 | |
| 1906 | /* Set flags. */ |
| 1907 | if (res == 0) |
| 1908 | SET_PSR_CC (1); |
| 1909 | else |
| 1910 | SET_PSR_CC (0); |
| 1911 | |
| 1912 | set_iregval (idest, res); |
| 1913 | } |
| 1914 | |
| 1915 | |
| 1916 | /* Execute "andh #const,isrc2,idest". */ |
| 1917 | void i860_cpu_device::insn_andh_imm (UINT32 insn) |
| 1918 | { |
| 1919 | UINT32 src1val = 0; |
| 1920 | UINT32 isrc2 = get_isrc2 (insn); |
| 1921 | UINT32 idest = get_idest (insn); |
| 1922 | UINT32 res = 0; |
| 1923 | |
| 1924 | /* Do the operation. */ |
| 1925 | src1val = get_imm16 (insn); |
| 1926 | res = (src1val << 16) & get_iregval (isrc2); |
| 1927 | |
| 1928 | /* Set flags. */ |
| 1929 | if (res == 0) |
| 1930 | SET_PSR_CC (1); |
| 1931 | else |
| 1932 | SET_PSR_CC (0); |
| 1933 | |
| 1934 | set_iregval (idest, res); |
| 1935 | } |
| 1936 | |
| 1937 | |
| 1938 | /* Execute "andnot isrc1,isrc2,idest". */ |
| 1939 | void i860_cpu_device::insn_andnot (UINT32 insn) |
| 1940 | { |
| 1941 | UINT32 isrc1 = get_isrc1 (insn); |
| 1942 | UINT32 isrc2 = get_isrc2 (insn); |
| 1943 | UINT32 idest = get_idest (insn); |
| 1944 | UINT32 res = 0; |
| 1945 | |
| 1946 | /* Do the operation. */ |
| 1947 | res = (~get_iregval (isrc1)) & get_iregval (isrc2); |
| 1948 | |
| 1949 | /* Set flags. */ |
| 1950 | if (res == 0) |
| 1951 | SET_PSR_CC (1); |
| 1952 | else |
| 1953 | SET_PSR_CC (0); |
| 1954 | |
| 1955 | set_iregval (idest, res); |
| 1956 | } |
| 1957 | |
| 1958 | |
| 1959 | /* Execute "andnot #const,isrc2,idest". */ |
| 1960 | void i860_cpu_device::insn_andnot_imm (UINT32 insn) |
| 1961 | { |
| 1962 | UINT32 src1val = 0; |
| 1963 | UINT32 isrc2 = get_isrc2 (insn); |
| 1964 | UINT32 idest = get_idest (insn); |
| 1965 | UINT32 res = 0; |
| 1966 | |
| 1967 | /* Do the operation. */ |
| 1968 | src1val = get_imm16 (insn); |
| 1969 | res = (~src1val) & get_iregval (isrc2); |
| 1970 | |
| 1971 | /* Set flags. */ |
| 1972 | if (res == 0) |
| 1973 | SET_PSR_CC (1); |
| 1974 | else |
| 1975 | SET_PSR_CC (0); |
| 1976 | |
| 1977 | set_iregval (idest, res); |
| 1978 | } |
| 1979 | |
| 1980 | |
| 1981 | /* Execute "andnoth #const,isrc2,idest". */ |
| 1982 | void i860_cpu_device::insn_andnoth_imm (UINT32 insn) |
| 1983 | { |
| 1984 | UINT32 src1val = 0; |
| 1985 | UINT32 isrc2 = get_isrc2 (insn); |
| 1986 | UINT32 idest = get_idest (insn); |
| 1987 | UINT32 res = 0; |
| 1988 | |
| 1989 | /* Do the operation. */ |
| 1990 | src1val = get_imm16 (insn); |
| 1991 | res = (~(src1val << 16)) & get_iregval (isrc2); |
| 1992 | |
| 1993 | /* Set flags. */ |
| 1994 | if (res == 0) |
| 1995 | SET_PSR_CC (1); |
| 1996 | else |
| 1997 | SET_PSR_CC (0); |
| 1998 | |
| 1999 | set_iregval (idest, res); |
| 2000 | } |
| 2001 | |
| 2002 | |
| 2003 | /* Execute "or isrc1,isrc2,idest". */ |
| 2004 | void i860_cpu_device::insn_or (UINT32 insn) |
| 2005 | { |
| 2006 | UINT32 isrc1 = get_isrc1 (insn); |
| 2007 | UINT32 isrc2 = get_isrc2 (insn); |
| 2008 | UINT32 idest = get_idest (insn); |
| 2009 | UINT32 res = 0; |
| 2010 | |
| 2011 | /* Do the operation. */ |
| 2012 | res = get_iregval (isrc1) | get_iregval (isrc2); |
| 2013 | |
| 2014 | /* Set flags. */ |
| 2015 | if (res == 0) |
| 2016 | SET_PSR_CC (1); |
| 2017 | else |
| 2018 | SET_PSR_CC (0); |
| 2019 | |
| 2020 | set_iregval (idest, res); |
| 2021 | } |
| 2022 | |
| 2023 | |
| 2024 | /* Execute "or #const,isrc2,idest". */ |
| 2025 | void i860_cpu_device::insn_or_imm (UINT32 insn) |
| 2026 | { |
| 2027 | UINT32 src1val = 0; |
| 2028 | UINT32 isrc2 = get_isrc2 (insn); |
| 2029 | UINT32 idest = get_idest (insn); |
| 2030 | UINT32 res = 0; |
| 2031 | |
| 2032 | /* Do the operation. */ |
| 2033 | src1val = get_imm16 (insn); |
| 2034 | res = src1val | get_iregval (isrc2); |
| 2035 | |
| 2036 | /* Set flags. */ |
| 2037 | if (res == 0) |
| 2038 | SET_PSR_CC (1); |
| 2039 | else |
| 2040 | SET_PSR_CC (0); |
| 2041 | |
| 2042 | set_iregval (idest, res); |
| 2043 | } |
| 2044 | |
| 2045 | |
| 2046 | /* Execute "orh #const,isrc2,idest". */ |
| 2047 | void i860_cpu_device::insn_orh_imm (UINT32 insn) |
| 2048 | { |
| 2049 | UINT32 src1val = 0; |
| 2050 | UINT32 isrc2 = get_isrc2 (insn); |
| 2051 | UINT32 idest = get_idest (insn); |
| 2052 | UINT32 res = 0; |
| 2053 | |
| 2054 | /* Do the operation. */ |
| 2055 | src1val = get_imm16 (insn); |
| 2056 | res = (src1val << 16) | get_iregval (isrc2); |
| 2057 | |
| 2058 | /* Set flags. */ |
| 2059 | if (res == 0) |
| 2060 | SET_PSR_CC (1); |
| 2061 | else |
| 2062 | SET_PSR_CC (0); |
| 2063 | |
| 2064 | set_iregval (idest, res); |
| 2065 | } |
| 2066 | |
| 2067 | |
| 2068 | /* Execute "xor isrc1,isrc2,idest". */ |
| 2069 | void i860_cpu_device::insn_xor (UINT32 insn) |
| 2070 | { |
| 2071 | UINT32 isrc1 = get_isrc1 (insn); |
| 2072 | UINT32 isrc2 = get_isrc2 (insn); |
| 2073 | UINT32 idest = get_idest (insn); |
| 2074 | UINT32 res = 0; |
| 2075 | |
| 2076 | /* Do the operation. */ |
| 2077 | res = get_iregval (isrc1) ^ get_iregval (isrc2); |
| 2078 | |
| 2079 | /* Set flags. */ |
| 2080 | if (res == 0) |
| 2081 | SET_PSR_CC (1); |
| 2082 | else |
| 2083 | SET_PSR_CC (0); |
| 2084 | |
| 2085 | set_iregval (idest, res); |
| 2086 | } |
| 2087 | |
| 2088 | |
| 2089 | /* Execute "xor #const,isrc2,idest". */ |
| 2090 | void i860_cpu_device::insn_xor_imm (UINT32 insn) |
| 2091 | { |
| 2092 | UINT32 src1val = 0; |
| 2093 | UINT32 isrc2 = get_isrc2 (insn); |
| 2094 | UINT32 idest = get_idest (insn); |
| 2095 | UINT32 res = 0; |
| 2096 | |
| 2097 | /* Do the operation. */ |
| 2098 | src1val = get_imm16 (insn); |
| 2099 | res = src1val ^ get_iregval (isrc2); |
| 2100 | |
| 2101 | /* Set flags. */ |
| 2102 | if (res == 0) |
| 2103 | SET_PSR_CC (1); |
| 2104 | else |
| 2105 | SET_PSR_CC (0); |
| 2106 | |
| 2107 | set_iregval (idest, res); |
| 2108 | } |
| 2109 | |
| 2110 | |
| 2111 | /* Execute "xorh #const,isrc2,idest". */ |
| 2112 | void i860_cpu_device::insn_xorh_imm (UINT32 insn) |
| 2113 | { |
| 2114 | UINT32 src1val = 0; |
| 2115 | UINT32 isrc2 = get_isrc2 (insn); |
| 2116 | UINT32 idest = get_idest (insn); |
| 2117 | UINT32 res = 0; |
| 2118 | |
| 2119 | /* Do the operation. */ |
| 2120 | src1val = get_imm16 (insn); |
| 2121 | res = (src1val << 16) ^ get_iregval (isrc2); |
| 2122 | |
| 2123 | /* Set flags. */ |
| 2124 | if (res == 0) |
| 2125 | SET_PSR_CC (1); |
| 2126 | else |
| 2127 | SET_PSR_CC (0); |
| 2128 | |
| 2129 | set_iregval (idest, res); |
| 2130 | } |
| 2131 | |
| 2132 | |
| 2133 | /* Execute "trap isrc1ni,isrc2,idest" instruction. */ |
| 2134 | void i860_cpu_device::insn_trap (UINT32 insn) |
| 2135 | { |
| 2136 | SET_PSR_IT (1); |
| 2137 | m_pending_trap = 1; |
| 2138 | } |
| 2139 | |
| 2140 | |
| 2141 | /* Execute "intovr" instruction. */ |
| 2142 | void i860_cpu_device::insn_intovr (UINT32 insn) |
| 2143 | { |
| 2144 | if (GET_EPSR_OF ()) |
| 2145 | { |
| 2146 | SET_PSR_IT (1); |
| 2147 | m_pending_trap = 1; |
| 2148 | } |
| 2149 | } |
| 2150 | |
| 2151 | |
| 2152 | /* Execute "bte isrc1,isrc2,sbroff". */ |
| 2153 | void i860_cpu_device::insn_bte (UINT32 insn) |
| 2154 | { |
| 2155 | UINT32 src1val = 0; |
| 2156 | UINT32 isrc2 = get_isrc2 (insn); |
| 2157 | UINT32 target_addr = 0; |
| 2158 | INT32 sbroff = 0; |
| 2159 | int res = 0; |
| 2160 | |
| 2161 | src1val = get_iregval (get_isrc1 (insn)); |
| 2162 | |
| 2163 | /* Compute the target address from the sbroff field. */ |
| 2164 | sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); |
| 2165 | target_addr = (INT32)m_pc + 4 + (sbroff << 2); |
| 2166 | |
| 2167 | /* Determine comparison result. */ |
| 2168 | res = (src1val == get_iregval (isrc2)); |
| 2169 | |
| 2170 | /* Branch routines always update the PC. */ |
| 2171 | if (res) |
| 2172 | m_pc = target_addr; |
| 2173 | else |
| 2174 | m_pc += 4; |
| 2175 | |
| 2176 | m_pc_updated = 1; |
| 2177 | } |
| 2178 | |
| 2179 | |
| 2180 | /* Execute "bte #const5,isrc2,sbroff". */ |
| 2181 | void i860_cpu_device::insn_bte_imm (UINT32 insn) |
| 2182 | { |
| 2183 | UINT32 src1val = 0; |
| 2184 | UINT32 isrc2 = get_isrc2 (insn); |
| 2185 | UINT32 target_addr = 0; |
| 2186 | INT32 sbroff = 0; |
| 2187 | int res = 0; |
| 2188 | |
| 2189 | src1val = (insn >> 11) & 0x1f; /* 5-bit field, zero-extended. */ |
| 2190 | |
| 2191 | /* Compute the target address from the sbroff field. */ |
| 2192 | sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); |
| 2193 | target_addr = (INT32)m_pc + 4 + (sbroff << 2); |
| 2194 | |
| 2195 | /* Determine comparison result. */ |
| 2196 | res = (src1val == get_iregval (isrc2)); |
| 2197 | |
| 2198 | /* Branch routines always update the PC. */ |
| 2199 | if (res) |
| 2200 | m_pc = target_addr; |
| 2201 | else |
| 2202 | m_pc += 4; |
| 2203 | |
| 2204 | m_pc_updated = 1; |
| 2205 | } |
| 2206 | |
| 2207 | |
| 2208 | /* Execute "btne isrc1,isrc2,sbroff". */ |
| 2209 | void i860_cpu_device::insn_btne (UINT32 insn) |
| 2210 | { |
| 2211 | UINT32 src1val = 0; |
| 2212 | UINT32 isrc2 = get_isrc2 (insn); |
| 2213 | UINT32 target_addr = 0; |
| 2214 | INT32 sbroff = 0; |
| 2215 | int res = 0; |
| 2216 | |
| 2217 | src1val = get_iregval (get_isrc1 (insn)); |
| 2218 | |
| 2219 | /* Compute the target address from the sbroff field. */ |
| 2220 | sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); |
| 2221 | target_addr = (INT32)m_pc + 4 + (sbroff << 2); |
| 2222 | |
| 2223 | /* Determine comparison result. */ |
| 2224 | res = (src1val != get_iregval (isrc2)); |
| 2225 | |
| 2226 | /* Branch routines always update the PC. */ |
| 2227 | if (res) |
| 2228 | m_pc = target_addr; |
| 2229 | else |
| 2230 | m_pc += 4; |
| 2231 | |
| 2232 | m_pc_updated = 1; |
| 2233 | } |
| 2234 | |
| 2235 | |
| 2236 | /* Execute "btne #const5,isrc2,sbroff". */ |
| 2237 | void i860_cpu_device::insn_btne_imm (UINT32 insn) |
| 2238 | { |
| 2239 | UINT32 src1val = 0; |
| 2240 | UINT32 isrc2 = get_isrc2 (insn); |
| 2241 | UINT32 target_addr = 0; |
| 2242 | INT32 sbroff = 0; |
| 2243 | int res = 0; |
| 2244 | |
| 2245 | src1val = (insn >> 11) & 0x1f; /* 5-bit field, zero-extended. */ |
| 2246 | |
| 2247 | /* Compute the target address from the sbroff field. */ |
| 2248 | sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); |
| 2249 | target_addr = (INT32)m_pc + 4 + (sbroff << 2); |
| 2250 | |
| 2251 | /* Determine comparison result. */ |
| 2252 | res = (src1val != get_iregval (isrc2)); |
| 2253 | |
| 2254 | /* Branch routines always update the PC. */ |
| 2255 | if (res) |
| 2256 | m_pc = target_addr; |
| 2257 | else |
| 2258 | m_pc += 4; |
| 2259 | |
| 2260 | m_pc_updated = 1; |
| 2261 | } |
| 2262 | |
| 2263 | |
| 2264 | /* Execute "bc lbroff" instruction. */ |
| 2265 | void i860_cpu_device::insn_bc (UINT32 insn) |
| 2266 | { |
| 2267 | UINT32 target_addr = 0; |
| 2268 | INT32 lbroff = 0; |
| 2269 | int res = 0; |
| 2270 | |
| 2271 | /* Compute the target address from the lbroff field. */ |
| 2272 | lbroff = sign_ext ((insn & 0x03ffffff), 26); |
| 2273 | target_addr = (INT32)m_pc + 4 + (lbroff << 2); |
| 2274 | |
| 2275 | /* Determine comparison result. */ |
| 2276 | res = (GET_PSR_CC () == 1); |
| 2277 | |
| 2278 | /* Branch routines always update the PC. */ |
| 2279 | if (res) |
| 2280 | m_pc = target_addr; |
| 2281 | else |
| 2282 | m_pc += 4; |
| 2283 | |
| 2284 | m_pc_updated = 1; |
| 2285 | } |
| 2286 | |
| 2287 | |
| 2288 | /* Execute "bnc lbroff" instruction. */ |
| 2289 | void i860_cpu_device::insn_bnc (UINT32 insn) |
| 2290 | { |
| 2291 | UINT32 target_addr = 0; |
| 2292 | INT32 lbroff = 0; |
| 2293 | int res = 0; |
| 2294 | |
| 2295 | /* Compute the target address from the lbroff field. */ |
| 2296 | lbroff = sign_ext ((insn & 0x03ffffff), 26); |
| 2297 | target_addr = (INT32)m_pc + 4 + (lbroff << 2); |
| 2298 | |
| 2299 | /* Determine comparison result. */ |
| 2300 | res = (GET_PSR_CC () == 0); |
| 2301 | |
| 2302 | /* Branch routines always update the PC, since pc_updated is set |
| 2303 | in the decode routine. */ |
| 2304 | if (res) |
| 2305 | m_pc = target_addr; |
| 2306 | else |
| 2307 | m_pc += 4; |
| 2308 | |
| 2309 | m_pc_updated = 1; |
| 2310 | } |
| 2311 | |
| 2312 | |
| 2313 | /* Execute "bc.t lbroff" instruction. */ |
| 2314 | void i860_cpu_device::insn_bct (UINT32 insn) |
| 2315 | { |
| 2316 | UINT32 target_addr = 0; |
| 2317 | INT32 lbroff = 0; |
| 2318 | int res = 0; |
| 2319 | UINT32 orig_pc = m_pc; |
| 2320 | |
| 2321 | /* Compute the target address from the lbroff field. */ |
| 2322 | lbroff = sign_ext ((insn & 0x03ffffff), 26); |
| 2323 | target_addr = (INT32)m_pc + 4 + (lbroff << 2); |
| 2324 | |
| 2325 | /* Determine comparison result. */ |
| 2326 | res = (GET_PSR_CC () == 1); |
| 2327 | |
| 2328 | /* Careful. Unlike bla, the delay slot instruction is only executed |
| 2329 | if the branch is taken. */ |
| 2330 | if (res) |
| 2331 | { |
| 2332 | /* Execute delay slot instruction. */ |
| 2333 | m_pc += 4; |
| 2334 | decode_exec (ifetch (orig_pc + 4), 0); |
| 2335 | m_pc = orig_pc; |
| 2336 | if (m_pending_trap) |
| 2337 | { |
| 2338 | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2339 | goto ab_op; |
| 2340 | } |
| 2341 | } |
| 2342 | |
| 2343 | /* Since this branch is delayed, we must jump 2 instructions if |
| 2344 | if isn't taken. */ |
| 2345 | if (res) |
| 2346 | m_pc = target_addr; |
| 2347 | else |
| 2348 | m_pc += 8; |
| 2349 | |
| 2350 | m_pc_updated = 1; |
| 2351 | |
| 2352 | ab_op: |
| 2353 | ; |
| 2354 | } |
| 2355 | |
| 2356 | |
| 2357 | /* Execute "bnc.t lbroff" instruction. */ |
| 2358 | void i860_cpu_device::insn_bnct (UINT32 insn) |
| 2359 | { |
| 2360 | UINT32 target_addr = 0; |
| 2361 | INT32 lbroff = 0; |
| 2362 | int res = 0; |
| 2363 | UINT32 orig_pc = m_pc; |
| 2364 | |
| 2365 | /* Compute the target address from the lbroff field. */ |
| 2366 | lbroff = sign_ext ((insn & 0x03ffffff), 26); |
| 2367 | target_addr = (INT32)m_pc + 4 + (lbroff << 2); |
| 2368 | |
| 2369 | /* Determine comparison result. */ |
| 2370 | res = (GET_PSR_CC () == 0); |
| 2371 | |
| 2372 | /* Careful. Unlike bla, the delay slot instruction is only executed |
| 2373 | if the branch is taken. */ |
| 2374 | if (res) |
| 2375 | { |
| 2376 | /* Execute delay slot instruction. */ |
| 2377 | m_pc += 4; |
| 2378 | decode_exec (ifetch (orig_pc + 4), 0); |
| 2379 | m_pc = orig_pc; |
| 2380 | if (m_pending_trap) |
| 2381 | { |
| 2382 | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2383 | goto ab_op; |
| 2384 | } |
| 2385 | } |
| 2386 | |
| 2387 | /* Since this branch is delayed, we must jump 2 instructions if |
| 2388 | if isn't taken. */ |
| 2389 | if (res) |
| 2390 | m_pc = target_addr; |
| 2391 | else |
| 2392 | m_pc += 8; |
| 2393 | |
| 2394 | m_pc_updated = 1; |
| 2395 | |
| 2396 | ab_op: |
| 2397 | ; |
| 2398 | } |
| 2399 | |
| 2400 | |
| 2401 | /* Execute "call lbroff" instruction. */ |
| 2402 | void i860_cpu_device::insn_call (UINT32 insn) |
| 2403 | { |
| 2404 | UINT32 target_addr = 0; |
| 2405 | INT32 lbroff = 0; |
| 2406 | UINT32 orig_pc = m_pc; |
| 2407 | |
| 2408 | /* Compute the target address from the lbroff field. */ |
| 2409 | lbroff = sign_ext ((insn & 0x03ffffff), 26); |
| 2410 | target_addr = (INT32)m_pc + 4 + (lbroff << 2); |
| 2411 | |
| 2412 | /* Execute the delay slot instruction. */ |
| 2413 | m_pc += 4; |
| 2414 | decode_exec (ifetch (orig_pc + 4), 0); |
| 2415 | m_pc = orig_pc; |
| 2416 | if (m_pending_trap) |
| 2417 | { |
| 2418 | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2419 | goto ab_op; |
| 2420 | } |
| 2421 | |
| 2422 | /* Sets the return pointer (r1). */ |
| 2423 | set_iregval (1, orig_pc + 8); |
| 2424 | |
| 2425 | /* New target. */ |
| 2426 | m_pc = target_addr; |
| 2427 | m_pc_updated = 1; |
| 2428 | |
| 2429 | ab_op:; |
| 2430 | } |
| 2431 | |
| 2432 | |
| 2433 | /* Execute "br lbroff". */ |
| 2434 | void i860_cpu_device::insn_br (UINT32 insn) |
| 2435 | { |
| 2436 | UINT32 target_addr = 0; |
| 2437 | INT32 lbroff = 0; |
| 2438 | UINT32 orig_pc = m_pc; |
| 2439 | |
| 2440 | /* Compute the target address from the lbroff field. */ |
| 2441 | lbroff = sign_ext ((insn & 0x03ffffff), 26); |
| 2442 | target_addr = (INT32)m_pc + 4 + (lbroff << 2); |
| 2443 | |
| 2444 | /* Execute the delay slot instruction. */ |
| 2445 | m_pc += 4; |
| 2446 | decode_exec (ifetch (orig_pc + 4), 0); |
| 2447 | m_pc = orig_pc; |
| 2448 | if (m_pending_trap) |
| 2449 | { |
| 2450 | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2451 | goto ab_op; |
| 2452 | } |
| 2453 | |
| 2454 | /* New target. */ |
| 2455 | m_pc = target_addr; |
| 2456 | m_pc_updated = 1; |
| 2457 | |
| 2458 | ab_op:; |
| 2459 | } |
| 2460 | |
| 2461 | |
| 2462 | /* Execute "bri isrc1ni" instruction. |
| 2463 | Note: I didn't merge this code with calli because bri must do |
| 2464 | a lot of flag manipulation if any trap bits are set. */ |
| 2465 | void i860_cpu_device::insn_bri (UINT32 insn) |
| 2466 | { |
| 2467 | UINT32 isrc1 = get_isrc1 (insn); |
| 2468 | UINT32 orig_pc = m_pc; |
| 2469 | UINT32 orig_psr = m_cregs[CR_PSR]; |
| 2470 | UINT32 orig_src1_val = get_iregval (isrc1); |
| 2471 | |
| 2472 | #if 1 /* TURBO. */ |
| 2473 | m_cregs[CR_PSR] &= ~PSR_ALL_TRAP_BITS_MASK; |
| 2474 | #endif |
| 2475 | |
| 2476 | /* Execute the delay slot instruction. */ |
| 2477 | m_pc += 4; |
| 2478 | decode_exec (ifetch (orig_pc + 4), 0); |
| 2479 | m_pc = orig_pc; |
| 2480 | |
| 2481 | /* Delay slot insn caused a trap, abort operation. */ |
| 2482 | if (m_pending_trap) |
| 2483 | { |
| 2484 | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2485 | goto ab_op; |
| 2486 | } |
| 2487 | |
| 2488 | /* If any trap bits are set, we need to do the return from |
| 2489 | trap work. Note, we must use the PSR value that existed |
| 2490 | before the delay slot instruction was executed since the |
| 2491 | delay slot instruction might itself cause a trap bit to |
| 2492 | be set. */ |
| 2493 | if (orig_psr & PSR_ALL_TRAP_BITS_MASK) |
| 2494 | { |
| 2495 | /* Restore U and IM from their previous copies. */ |
| 2496 | SET_PSR_U (GET_PSR_PU ()); |
| 2497 | SET_PSR_IM (GET_PSR_PIM ()); |
| 2498 | |
| 2499 | m_fir_gets_trap_addr = 0; |
| 2500 | } |
| 2501 | |
| 2502 | /* Update PC. */ |
| 2503 | m_pc = orig_src1_val; |
| 2504 | |
| 2505 | m_pc_updated = 1; |
| 2506 | ab_op:; |
| 2507 | } |
| 2508 | |
| 2509 | /* Execute "calli isrc1ni" instruction. */ |
| 2510 | void i860_cpu_device::insn_calli (UINT32 insn) |
| 2511 | { |
| 2512 | UINT32 isrc1 = get_isrc1 (insn); |
| 2513 | UINT32 orig_pc = m_pc; |
| 2514 | UINT32 orig_src1_val = get_iregval (isrc1); |
| 2515 | |
| 2516 | #ifdef TRACE_UNDEFINED_I860 |
| 2517 | /* Check for undefined behavior. */ |
| 2518 | if (isrc1 == 1) |
| 2519 | { |
| 2520 | /* Src1 must not be r1. */ |
| 2521 | fprintf (stderr, "WARNING: insn_calli (pc=0x%08x): isrc1 = r1 on a calli\n", m_pc); |
| 2522 | } |
| 2523 | #endif |
| 2524 | |
| 2525 | /* Set return pointer before executing delay slot instruction. */ |
| 2526 | set_iregval (1, m_pc + 8); |
| 2527 | |
| 2528 | /* Execute the delay slot instruction. */ |
| 2529 | m_pc += 4; |
| 2530 | decode_exec (ifetch (orig_pc + 4), 0); |
| 2531 | m_pc = orig_pc; |
| 2532 | if (m_pending_trap) |
| 2533 | { |
| 2534 | set_iregval (1, orig_src1_val); |
| 2535 | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2536 | goto ab_op; |
| 2537 | } |
| 2538 | |
| 2539 | /* Set new PC. */ |
| 2540 | m_pc = orig_src1_val; |
| 2541 | m_pc_updated = 1; |
| 2542 | |
| 2543 | ab_op:; |
| 2544 | } |
| 2545 | |
| 2546 | |
| 2547 | /* Execute "bla isrc1ni,isrc2,sbroff" instruction. */ |
| 2548 | void i860_cpu_device::insn_bla (UINT32 insn) |
| 2549 | { |
| 2550 | UINT32 isrc1 = get_isrc1 (insn); |
| 2551 | UINT32 isrc2 = get_isrc2 (insn); |
| 2552 | UINT32 target_addr = 0; |
| 2553 | INT32 sbroff = 0; |
| 2554 | int lcc_tmp = 0; |
| 2555 | UINT32 orig_pc = m_pc; |
| 2556 | UINT32 orig_isrc2val = get_iregval (isrc2); |
| 2557 | |
| 2558 | #ifdef TRACE_UNDEFINED_I860 |
| 2559 | /* Check for undefined behavior. */ |
| 2560 | if (isrc1 == isrc2) |
| 2561 | { |
| 2562 | /* Src1 and src2 the same is undefined i860XR behavior. */ |
| 2563 | fprintf (stderr, "WARNING: insn_bla (pc=0x%08x): isrc1 and isrc2 are the same (ignored)\n", m_pc); |
| 2564 | return; |
| 2565 | } |
| 2566 | #endif |
| 2567 | |
| 2568 | /* Compute the target address from the sbroff field. */ |
| 2569 | sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); |
| 2570 | target_addr = (INT32)m_pc + 4 + (sbroff << 2); |
| 2571 | |
| 2572 | /* Determine comparison result based on opcode. */ |
| 2573 | lcc_tmp = ((INT32)get_iregval (isrc2) >= -(INT32)get_iregval (isrc1)); |
| 2574 | |
| 2575 | set_iregval (isrc2, get_iregval (isrc1) + orig_isrc2val); |
| 2576 | |
| 2577 | /* Execute the delay slot instruction. */ |
| 2578 | m_pc += 4; |
| 2579 | decode_exec (ifetch (orig_pc + 4), 0); |
| 2580 | m_pc = orig_pc; |
| 2581 | if (m_pending_trap) |
| 2582 | { |
| 2583 | m_pending_trap |= TRAP_IN_DELAY_SLOT; |
| 2584 | goto ab_op; |
| 2585 | } |
| 2586 | |
| 2587 | if (GET_PSR_LCC ()) |
| 2588 | m_pc = target_addr; |
| 2589 | else |
| 2590 | { |
| 2591 | /* Since this branch is delayed, we must jump 2 instructions if |
| 2592 | if isn't taken. */ |
| 2593 | m_pc += 8; |
| 2594 | } |
| 2595 | SET_PSR_LCC (lcc_tmp); |
| 2596 | |
| 2597 | m_pc_updated = 1; |
| 2598 | ab_op:; |
| 2599 | } |
| 2600 | |
| 2601 | |
| 2602 | /* Execute "flush #const(isrc2)" or "flush #const(isrc2)++" instruction. */ |
| 2603 | void i860_cpu_device::insn_flush (UINT32 insn) |
| 2604 | { |
| 2605 | UINT32 src1val = sign_ext (get_imm16 (insn), 16); |
| 2606 | UINT32 isrc2 = get_isrc2 (insn); |
| 2607 | int auto_inc = (insn & 1); |
| 2608 | UINT32 eff = 0; |
| 2609 | |
| 2610 | /* Technically, idest should be encoded as r0 because idest |
| 2611 | is undefined after the instruction. We don't currently |
| 2612 | check for this. |
| 2613 | |
| 2614 | Flush D$ block at address #const+isrc2. Block is undefined |
| 2615 | after. The effective address must be 16-byte aligned. |
| 2616 | |
| 2617 | FIXME: Need to examine RB and RC and do this right. |
| 2618 | */ |
| 2619 | |
| 2620 | /* Chop off lower bits of displacement to 16-byte alignment. */ |
| 2621 | src1val &= ~(16-1); |
| 2622 | eff = src1val + get_iregval (isrc2); |
| 2623 | if (auto_inc) |
| 2624 | set_iregval (isrc2, eff); |
| 2625 | |
| 2626 | /* In user mode, the flush is ignored. */ |
| 2627 | if (GET_PSR_U () == 0) |
| 2628 | { |
| 2629 | /* If line is dirty, write it to memory and invalidate. |
| 2630 | NOTE: The actual dirty write is unimplemented in the MAME version |
| 2631 | as we don't emulate the dcache. */ |
| 2632 | } |
| 2633 | } |
| 2634 | |
| 2635 | |
| 2636 | /* Execute "[p]fmul.{ss,sd,dd} fsrc1,fsrc2,fdest" instruction or |
| 2637 | pfmul3.dd fsrc1,fsrc2,fdest. |
| 2638 | |
| 2639 | The pfmul3.dd differs from pfmul.dd in that it treats the pipeline |
| 2640 | as 3 stages, even though it is a double precision multiply. */ |
| 2641 | void i860_cpu_device::insn_fmul (UINT32 insn) |
| 2642 | { |
| 2643 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 2644 | UINT32 fsrc2 = get_fsrc2 (insn); |
| 2645 | UINT32 fdest = get_fdest (insn); |
| 2646 | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 2647 | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 2648 | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 2649 | double dbl_tmp_dest = 0.0; |
| 2650 | float sgl_tmp_dest = 0.0; |
| 2651 | double dbl_last_stage_contents = 0.0; |
| 2652 | float sgl_last_stage_contents = 0.0; |
| 2653 | int is_pfmul3 = insn & 0x4; |
| 2654 | int num_stages = (src_prec && !is_pfmul3) ? 2 : 3; |
| 2655 | |
| 2656 | /* Only .dd is valid for pfmul. */ |
| 2657 | if (is_pfmul3 && (insn & 0x180) != 0x180) |
| 2658 | { |
| 2659 | unrecog_opcode (m_pc, insn); |
| 2660 | return; |
| 2661 | } |
| 2662 | |
| 2663 | /* Check for invalid .ds combination. */ |
| 2664 | if ((insn & 0x180) == 0x100) |
| 2665 | { |
| 2666 | unrecog_opcode (m_pc, insn); |
| 2667 | return; |
| 2668 | } |
| 2669 | |
| 2670 | /* For pipelined version, retrieve the contents of the last stage |
| 2671 | of the pipeline, whose precision is specified by the MRP bit |
| 2672 | of the stage's result-status bits. Note for pfmul, the number |
| 2673 | of stages is determined by the source precision of the current |
| 2674 | operation. */ |
| 2675 | if (piped) |
| 2676 | { |
| 2677 | if (m_M[num_stages - 1].stat.mrp) |
| 2678 | dbl_last_stage_contents = m_M[num_stages - 1].val.d; |
| 2679 | else |
| 2680 | sgl_last_stage_contents = m_M[num_stages - 1].val.s; |
| 2681 | } |
| 2682 | |
| 2683 | /* Do the operation, being careful about source and result |
| 2684 | precision. */ |
| 2685 | if (src_prec) |
| 2686 | { |
| 2687 | double v1 = get_fregval_d (fsrc1); |
| 2688 | double v2 = get_fregval_d (fsrc2); |
| 2689 | |
| 2690 | /* For pipelined mul, if fsrc2 is the same as fdest, then the last |
| 2691 | stage is bypassed to fsrc2 (rather than using the value in fsrc2). |
| 2692 | This bypass is not available for fsrc1, and is undefined behavior. */ |
| 2693 | if (0 && piped && fdest != 0 && fsrc1 == fdest) |
| 2694 | v1 = dbl_last_stage_contents; |
| 2695 | if (piped && fdest != 0 && fsrc2 == fdest) |
| 2696 | v2 = dbl_last_stage_contents; |
| 2697 | |
| 2698 | if (res_prec) |
| 2699 | dbl_tmp_dest = v1 * v2; |
| 2700 | else |
| 2701 | sgl_tmp_dest = (float)(v1 * v2); |
| 2702 | } |
| 2703 | else |
| 2704 | { |
| 2705 | float v1 = get_fregval_s (fsrc1); |
| 2706 | float v2 = get_fregval_s (fsrc2); |
| 2707 | |
| 2708 | /* For pipelined mul, if fsrc2 is the same as fdest, then the last |
| 2709 | stage is bypassed to fsrc2 (rather than using the value in fsrc2). |
| 2710 | This bypass is not available for fsrc1, and is undefined behavior. */ |
| 2711 | if (0 && piped && fdest != 0 && fsrc1 == fdest) |
| 2712 | v1 = sgl_last_stage_contents; |
| 2713 | if (piped && fdest != 0 && fsrc2 == fdest) |
| 2714 | v2 = sgl_last_stage_contents; |
| 2715 | |
| 2716 | if (res_prec) |
| 2717 | dbl_tmp_dest = (double)(v1 * v2); |
| 2718 | else |
| 2719 | sgl_tmp_dest = v1 * v2; |
| 2720 | } |
| 2721 | |
| 2722 | /* FIXME: Set result-status bits besides MRP. And copy to fsr from |
| 2723 | last stage. */ |
| 2724 | /* FIXME: Scalar version flows through all stages. */ |
| 2725 | /* FIXME: Mixed precision (only weird for pfmul). */ |
| 2726 | if (!piped) |
| 2727 | { |
| 2728 | /* Scalar version writes the current calculation to the fdest |
| 2729 | register, with precision specified by the R bit. */ |
| 2730 | if (res_prec) |
| 2731 | set_fregval_d (fdest, dbl_tmp_dest); |
| 2732 | else |
| 2733 | set_fregval_s (fdest, sgl_tmp_dest); |
| 2734 | } |
| 2735 | else |
| 2736 | { |
| 2737 | /* Pipelined version writes fdest with the result from the last |
| 2738 | stage of the pipeline. */ |
| 2739 | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 2740 | /* Copy 3rd stage MRP to FSR. */ |
| 2741 | if (m_M[num_stages - 2 /* 1 */].stat.mrp) |
| 2742 | m_cregs[CR_FSR] |= 0x10000000; |
| 2743 | else |
| 2744 | m_cregs[CR_FSR] &= ~0x10000000; |
| 2745 | #endif |
| 2746 | |
| 2747 | if (m_M[num_stages - 1].stat.mrp) |
| 2748 | set_fregval_d (fdest, dbl_last_stage_contents); |
| 2749 | else |
| 2750 | set_fregval_s (fdest, sgl_last_stage_contents); |
| 2751 | |
| 2752 | /* Now advance pipeline and write current calculation to |
| 2753 | first stage. */ |
| 2754 | if (num_stages == 3) |
| 2755 | { |
| 2756 | m_M[2] = m_M[1]; |
| 2757 | m_M[1] = m_M[0]; |
| 2758 | } |
| 2759 | else |
| 2760 | m_M[1] = m_M[0]; |
| 2761 | |
| 2762 | if (res_prec) |
| 2763 | { |
| 2764 | m_M[0].val.d = dbl_tmp_dest; |
| 2765 | m_M[0].stat.mrp = 1; |
| 2766 | } |
| 2767 | else |
| 2768 | { |
| 2769 | m_M[0].val.s = sgl_tmp_dest; |
| 2770 | m_M[0].stat.mrp = 0; |
| 2771 | } |
| 2772 | } |
| 2773 | } |
| 2774 | |
| 2775 | |
| 2776 | /* Execute "fmlow.dd fsrc1,fsrc2,fdest" instruction. */ |
| 2777 | void i860_cpu_device::insn_fmlow (UINT32 insn) |
| 2778 | { |
| 2779 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 2780 | UINT32 fsrc2 = get_fsrc2 (insn); |
| 2781 | UINT32 fdest = get_fdest (insn); |
| 2782 | |
| 2783 | double v1 = get_fregval_d (fsrc1); |
| 2784 | double v2 = get_fregval_d (fsrc2); |
| 2785 | INT64 i1 = *(UINT64 *)&v1; |
| 2786 | INT64 i2 = *(UINT64 *)&v2; |
| 2787 | INT64 tmp = 0; |
| 2788 | |
| 2789 | /* Only .dd is valid for fmlow. */ |
| 2790 | if ((insn & 0x180) != 0x180) |
| 2791 | { |
| 2792 | unrecog_opcode (m_pc, insn); |
| 2793 | return; |
| 2794 | } |
| 2795 | |
| 2796 | /* The lower 32-bits are obvious. What exactly goes in the upper |
| 2797 | bits? |
| 2798 | Technically, the upper-most 10 bits are undefined, but i'd like |
| 2799 | to be undefined in the same way as the real i860 if possible. */ |
| 2800 | |
| 2801 | /* Keep lower 53 bits of multiply. */ |
| 2802 | tmp = i1 * i2; |
| 2803 | tmp &= 0x001fffffffffffffULL; |
| 2804 | tmp |= (i1 & 0x8000000000000000LL) ^ (i2 & 0x8000000000000000LL); |
| 2805 | set_fregval_d (fdest, *(double *)&tmp); |
| 2806 | } |
| 2807 | |
| 2808 | |
| 2809 | /* Execute [p]fadd.{ss,sd,dd} fsrc1,fsrc2,fdest (.ds disallowed above). */ |
| 2810 | void i860_cpu_device::insn_fadd_sub (UINT32 insn) |
| 2811 | { |
| 2812 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 2813 | UINT32 fsrc2 = get_fsrc2 (insn); |
| 2814 | UINT32 fdest = get_fdest (insn); |
| 2815 | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 2816 | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 2817 | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 2818 | int is_sub = insn & 1; /* 1 = sub, 0 = add. */ |
| 2819 | double dbl_tmp_dest = 0.0; |
| 2820 | float sgl_tmp_dest = 0.0; |
| 2821 | double dbl_last_stage_contents = 0.0; |
| 2822 | float sgl_last_stage_contents = 0.0; |
| 2823 | |
| 2824 | /* Check for invalid .ds combination. */ |
| 2825 | if ((insn & 0x180) == 0x100) |
| 2826 | { |
| 2827 | unrecog_opcode (m_pc, insn); |
| 2828 | return; |
| 2829 | } |
| 2830 | |
| 2831 | /* For pipelined version, retrieve the contents of the last stage |
| 2832 | of the pipeline, whose precision is specified by the ARP bit |
| 2833 | of the stage's result-status bits. There are always three stages |
| 2834 | for pfadd/pfsub. */ |
| 2835 | if (piped) |
| 2836 | { |
| 2837 | if (m_A[2].stat.arp) |
| 2838 | dbl_last_stage_contents = m_A[2].val.d; |
| 2839 | else |
| 2840 | sgl_last_stage_contents = m_A[2].val.s; |
| 2841 | } |
| 2842 | |
| 2843 | /* Do the operation, being careful about source and result |
| 2844 | precision. */ |
| 2845 | if (src_prec) |
| 2846 | { |
| 2847 | double v1 = get_fregval_d (fsrc1); |
| 2848 | double v2 = get_fregval_d (fsrc2); |
| 2849 | |
| 2850 | /* For pipelined add/sub, if fsrc1 is the same as fdest, then the last |
| 2851 | stage is bypassed to fsrc1 (rather than using the value in fsrc1). |
| 2852 | Likewise for fsrc2. */ |
| 2853 | if (piped && fdest != 0 && fsrc1 == fdest) |
| 2854 | v1 = dbl_last_stage_contents; |
| 2855 | if (piped && fdest != 0 && fsrc2 == fdest) |
| 2856 | v2 = dbl_last_stage_contents; |
| 2857 | |
| 2858 | if (res_prec) |
| 2859 | dbl_tmp_dest = is_sub ? v1 - v2 : v1 + v2; |
| 2860 | else |
| 2861 | sgl_tmp_dest = is_sub ? (float)(v1 - v2) : (float)(v1 + v2); |
| 2862 | } |
| 2863 | else |
| 2864 | { |
| 2865 | float v1 = get_fregval_s (fsrc1); |
| 2866 | float v2 = get_fregval_s (fsrc2); |
| 2867 | |
| 2868 | /* For pipelined add/sub, if fsrc1 is the same as fdest, then the last |
| 2869 | stage is bypassed to fsrc1 (rather than using the value in fsrc1). |
| 2870 | Likewise for fsrc2. */ |
| 2871 | if (piped && fdest != 0 && fsrc1 == fdest) |
| 2872 | v1 = sgl_last_stage_contents; |
| 2873 | if (piped && fdest != 0 && fsrc2 == fdest) |
| 2874 | v2 = sgl_last_stage_contents; |
| 2875 | |
| 2876 | if (res_prec) |
| 2877 | dbl_tmp_dest = is_sub ? (double)(v1 - v2) : (double)(v1 + v2); |
| 2878 | else |
| 2879 | sgl_tmp_dest = is_sub ? v1 - v2 : v1 + v2; |
| 2880 | } |
| 2881 | |
| 2882 | /* FIXME: Set result-status bits besides ARP. And copy to fsr from |
| 2883 | last stage. */ |
| 2884 | /* FIXME: Scalar version flows through all stages. */ |
| 2885 | if (!piped) |
| 2886 | { |
| 2887 | /* Scalar version writes the current calculation to the fdest |
| 2888 | register, with precision specified by the R bit. */ |
| 2889 | if (res_prec) |
| 2890 | set_fregval_d (fdest, dbl_tmp_dest); |
| 2891 | else |
| 2892 | set_fregval_s (fdest, sgl_tmp_dest); |
| 2893 | } |
| 2894 | else |
| 2895 | { |
| 2896 | /* Pipelined version writes fdest with the result from the last |
| 2897 | stage of the pipeline, with precision specified by the ARP |
| 2898 | bit of the stage's result-status bits. */ |
| 2899 | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 2900 | /* Copy 3rd stage ARP to FSR. */ |
| 2901 | if (m_A[1 /* 2 */].stat.arp) |
| 2902 | m_cregs[CR_FSR] |= 0x20000000; |
| 2903 | else |
| 2904 | m_cregs[CR_FSR] &= ~0x20000000; |
| 2905 | #endif |
| 2906 | if (m_A[2].stat.arp) /* 3rd (last) stage. */ |
| 2907 | set_fregval_d (fdest, dbl_last_stage_contents); |
| 2908 | else |
| 2909 | set_fregval_s (fdest, sgl_last_stage_contents); |
| 2910 | |
| 2911 | /* Now advance pipeline and write current calculation to |
| 2912 | first stage. */ |
| 2913 | m_A[2] = m_A[1]; |
| 2914 | m_A[1] = m_A[0]; |
| 2915 | if (res_prec) |
| 2916 | { |
| 2917 | m_A[0].val.d = dbl_tmp_dest; |
| 2918 | m_A[0].stat.arp = 1; |
| 2919 | } |
| 2920 | else |
| 2921 | { |
| 2922 | m_A[0].val.s = sgl_tmp_dest; |
| 2923 | m_A[0].stat.arp = 0; |
| 2924 | } |
| 2925 | } |
| 2926 | } |
| 2927 | |
| 2928 | |
| 2929 | /* Operand types for PFAM/PFMAM routine below. */ |
| 2930 | enum { |
| 2931 | OP_SRC1 = 0, |
| 2932 | OP_SRC2 = 1, |
| 2933 | OP_KI = 2, |
| 2934 | OP_KR = 4, |
| 2935 | OP_T = 8, |
| 2936 | OP_MPIPE = 16, |
| 2937 | OP_APIPE = 32, |
| 2938 | FLAGM = 64 /* Indicates PFMAM uses M rather than A pipe result. */ |
| 2939 | }; |
| 2940 | |
| 2941 | /* A table to map DPC value to source operands. |
| 2942 | |
| 2943 | The PFAM and PFMAM tables are nearly identical, and the only differences |
| 2944 | are that every time PFAM uses the A pipe, PFMAM uses the M pipe instead. |
| 2945 | So we only represent the PFAM table and use a special flag on any entry |
| 2946 | where the PFMAM table would use the M pipe rather than the A pipe. |
| 2947 | Also, entry 16 is not valid for PFMAM. */ |
| 2948 | static const struct |
| 2949 | { |
| 2950 | int M_unit_op1; |
| 2951 | int M_unit_op2; |
| 2952 | int A_unit_op1; |
| 2953 | int A_unit_op2; |
| 2954 | int T_loaded; |
| 2955 | int K_loaded; |
| 2956 | } src_opers[] = { |
| 2957 | /* 0000 */ { OP_KR, OP_SRC2, OP_SRC1, OP_MPIPE, 0, 0}, |
| 2958 | /* 0001 */ { OP_KR, OP_SRC2, OP_T, OP_MPIPE, 0, 1}, |
| 2959 | /* 0010 */ { OP_KR, OP_SRC2, OP_SRC1, OP_APIPE|FLAGM, 1, 0}, |
| 2960 | /* 0011 */ { OP_KR, OP_SRC2, OP_T, OP_APIPE|FLAGM, 1, 1}, |
| 2961 | /* 0100 */ { OP_KI, OP_SRC2, OP_SRC1, OP_MPIPE, 0, 0}, |
| 2962 | /* 0101 */ { OP_KI, OP_SRC2, OP_T, OP_MPIPE, 0, 1}, |
| 2963 | /* 0110 */ { OP_KI, OP_SRC2, OP_SRC1, OP_APIPE|FLAGM, 1, 0}, |
| 2964 | /* 0111 */ { OP_KI, OP_SRC2, OP_T, OP_APIPE|FLAGM, 1, 1}, |
| 2965 | /* 1000 */ { OP_KR, OP_APIPE|FLAGM, OP_SRC1, OP_SRC2, 1, 0}, |
| 2966 | /* 1001 */ { OP_SRC1, OP_SRC2, OP_APIPE|FLAGM, OP_MPIPE, 0, 0}, |
| 2967 | /* 1010 */ { OP_KR, OP_APIPE|FLAGM, OP_SRC1, OP_SRC2, 0, 0}, |
| 2968 | /* 1011 */ { OP_SRC1, OP_SRC2, OP_T, OP_APIPE|FLAGM, 1, 0}, |
| 2969 | /* 1100 */ { OP_KI, OP_APIPE|FLAGM, OP_SRC1, OP_SRC2, 1, 0}, |
| 2970 | /* 1101 */ { OP_SRC1, OP_SRC2, OP_T, OP_MPIPE, 0, 0}, |
| 2971 | /* 1110 */ { OP_KI, OP_APIPE|FLAGM, OP_SRC1, OP_SRC2, 0, 0}, |
| 2972 | /* 1111 */ { OP_SRC1, OP_SRC2, OP_T, OP_APIPE|FLAGM, 0, 0} |
| 2973 | }; |
| 2974 | |
| 2975 | float i860_cpu_device::get_fval_from_optype_s (UINT32 insn, int optype) |
| 2976 | { |
| 2977 | float retval = 0.0; |
| 2978 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 2979 | UINT32 fsrc2 = get_fsrc2 (insn); |
| 2980 | |
| 2981 | optype &= ~FLAGM; |
| 2982 | switch (optype) |
| 2983 | { |
| 2984 | case OP_SRC1: |
| 2985 | retval = get_fregval_s (fsrc1); |
| 2986 | break; |
| 2987 | case OP_SRC2: |
| 2988 | retval = get_fregval_s (fsrc2); |
| 2989 | break; |
| 2990 | case OP_KI: |
| 2991 | retval = m_KI.s; |
| 2992 | break; |
| 2993 | case OP_KR: |
| 2994 | retval = m_KR.s; |
| 2995 | break; |
| 2996 | case OP_T: |
| 2997 | retval = m_T.s; |
| 2998 | break; |
| 2999 | case OP_MPIPE: |
| 3000 | /* Last stage is 3rd stage for single precision input. */ |
| 3001 | retval = m_M[2].val.s; |
| 3002 | break; |
| 3003 | case OP_APIPE: |
| 3004 | retval = m_A[2].val.s; |
| 3005 | break; |
| 3006 | default: |
| 3007 | assert (0); |
| 3008 | } |
| 3009 | |
| 3010 | return retval; |
| 3011 | } |
| 3012 | |
| 3013 | |
| 3014 | double i860_cpu_device::get_fval_from_optype_d (UINT32 insn, int optype) |
| 3015 | { |
| 3016 | double retval = 0.0; |
| 3017 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3018 | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3019 | |
| 3020 | optype &= ~FLAGM; |
| 3021 | switch (optype) |
| 3022 | { |
| 3023 | case OP_SRC1: |
| 3024 | retval = get_fregval_d (fsrc1); |
| 3025 | break; |
| 3026 | case OP_SRC2: |
| 3027 | retval = get_fregval_d (fsrc2); |
| 3028 | break; |
| 3029 | case OP_KI: |
| 3030 | retval = m_KI.d; |
| 3031 | break; |
| 3032 | case OP_KR: |
| 3033 | retval = m_KR.d; |
| 3034 | break; |
| 3035 | case OP_T: |
| 3036 | retval = m_T.d; |
| 3037 | break; |
| 3038 | case OP_MPIPE: |
| 3039 | /* Last stage is 2nd stage for double precision input. */ |
| 3040 | retval = m_M[1].val.d; |
| 3041 | break; |
| 3042 | case OP_APIPE: |
| 3043 | retval = m_A[2].val.d; |
| 3044 | break; |
| 3045 | default: |
| 3046 | assert (0); |
| 3047 | } |
| 3048 | |
| 3049 | return retval; |
| 3050 | } |
| 3051 | |
| 3052 | |
| 3053 | /* Execute pf[m]{a,s}m.{ss,sd,dd} fsrc1,fsrc2,fdest (FP dual ops). |
| 3054 | |
| 3055 | Since these are always pipelined, the P bit is used to distinguish |
| 3056 | family pfam (P=1) from family pfmam (P=0), and the lower 4 bits |
| 3057 | of the extended opcode is the DPC. |
| 3058 | |
| 3059 | Note also that the S and R bits are slightly different than normal |
| 3060 | floating point operations. The S bit denotes the precision of the |
| 3061 | multiplication source, while the R bit denotes the precision of |
| 3062 | the addition source as well as precision of all results. */ |
| 3063 | void i860_cpu_device::insn_dualop (UINT32 insn) |
| 3064 | { |
| 3065 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3066 | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3067 | UINT32 fdest = get_fdest (insn); |
| 3068 | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3069 | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 3070 | int is_pfam = insn & 0x400; /* 1 = pfam, 0 = pfmam. */ |
| 3071 | int is_sub = insn & 0x10; /* 1 = pf[m]sm, 0 = pf[m]am. */ |
| 3072 | double dbl_tmp_dest_mul = 0.0; |
| 3073 | float sgl_tmp_dest_mul = 0.0; |
| 3074 | double dbl_tmp_dest_add = 0.0; |
| 3075 | float sgl_tmp_dest_add = 0.0; |
| 3076 | double dbl_last_Mstage_contents = 0.0; |
| 3077 | float sgl_last_Mstage_contents = 0.0; |
| 3078 | double dbl_last_Astage_contents = 0.0; |
| 3079 | float sgl_last_Astage_contents = 0.0; |
| 3080 | int num_mul_stages = src_prec ? 2 : 3; |
| 3081 | |
| 3082 | int dpc = insn & 0xf; |
| 3083 | int M_unit_op1 = src_opers[dpc].M_unit_op1; |
| 3084 | int M_unit_op2 = src_opers[dpc].M_unit_op2; |
| 3085 | int A_unit_op1 = src_opers[dpc].A_unit_op1; |
| 3086 | int A_unit_op2 = src_opers[dpc].A_unit_op2; |
| 3087 | int T_loaded = src_opers[dpc].T_loaded; |
| 3088 | int K_loaded = src_opers[dpc].K_loaded; |
| 3089 | |
| 3090 | /* Check for invalid .ds combination. */ |
| 3091 | if ((insn & 0x180) == 0x100) |
| 3092 | { |
| 3093 | unrecog_opcode (m_pc, insn); |
| 3094 | return; |
| 3095 | } |
| 3096 | |
| 3097 | if (is_pfam == 0) |
| 3098 | { |
| 3099 | /* Check for invalid DPC combination 16 for PFMAM. */ |
| 3100 | if (dpc == 16) |
| 3101 | { |
| 3102 | unrecog_opcode (m_pc, insn); |
| 3103 | return; |
| 3104 | } |
| 3105 | |
| 3106 | /* PFMAM table adjustments (M_unit_op1 is never a pipe stage, |
| 3107 | so no adjustment made for it). */ |
| 3108 | M_unit_op2 = (M_unit_op2 & FLAGM) ? OP_MPIPE : M_unit_op2; |
| 3109 | A_unit_op1 = (A_unit_op1 & FLAGM) ? OP_MPIPE : A_unit_op1; |
| 3110 | A_unit_op2 = (A_unit_op2 & FLAGM) ? OP_MPIPE : A_unit_op2; |
| 3111 | } |
| 3112 | |
| 3113 | /* FIXME: Check for fsrc1/fdest overlap for some mul DPC combinations. */ |
| 3114 | |
| 3115 | /* Retrieve the contents of the last stage of the multiplier pipeline, |
| 3116 | whose precision is specified by the MRP bit of the stage's result- |
| 3117 | status bits. Note for multiply, the number of stages is determined |
| 3118 | by the source precision of the current operation. */ |
| 3119 | if (m_M[num_mul_stages - 1].stat.mrp) |
| 3120 | dbl_last_Mstage_contents = m_M[num_mul_stages - 1].val.d; |
| 3121 | else |
| 3122 | sgl_last_Mstage_contents = m_M[num_mul_stages - 1].val.s; |
| 3123 | |
| 3124 | /* Similarly, retrieve the last stage of the adder pipe. */ |
| 3125 | if (m_A[2].stat.arp) |
| 3126 | dbl_last_Astage_contents = m_A[2].val.d; |
| 3127 | else |
| 3128 | sgl_last_Astage_contents = m_A[2].val.s; |
| 3129 | |
| 3130 | /* Do the mul operation, being careful about source and result |
| 3131 | precision. */ |
| 3132 | if (src_prec) |
| 3133 | { |
| 3134 | double v1 = get_fval_from_optype_d (insn, M_unit_op1); |
| 3135 | double v2 = get_fval_from_optype_d (insn, M_unit_op2); |
| 3136 | |
| 3137 | /* For mul, if fsrc2 is the same as fdest, then the last stage |
| 3138 | is bypassed to fsrc2 (rather than using the value in fsrc2). |
| 3139 | This bypass is not available for fsrc1, and is undefined behavior. */ |
| 3140 | if (0 && M_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest) |
| 3141 | v1 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents; |
| 3142 | if (M_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest) |
| 3143 | v2 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents; |
| 3144 | |
| 3145 | if (res_prec) |
| 3146 | dbl_tmp_dest_mul = v1 * v2; |
| 3147 | else |
| 3148 | sgl_tmp_dest_mul = (float)(v1 * v2); |
| 3149 | } |
| 3150 | else |
| 3151 | { |
| 3152 | float v1 = get_fval_from_optype_s (insn, M_unit_op1); |
| 3153 | float v2 = get_fval_from_optype_s (insn, M_unit_op2); |
| 3154 | |
| 3155 | /* For mul, if fsrc2 is the same as fdest, then the last stage |
| 3156 | is bypassed to fsrc2 (rather than using the value in fsrc2). |
| 3157 | This bypass is not available for fsrc1, and is undefined behavior. */ |
| 3158 | if (0 && M_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest) |
| 3159 | v1 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents; |
| 3160 | if (M_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest) |
| 3161 | v2 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents; |
| 3162 | |
| 3163 | if (res_prec) |
| 3164 | dbl_tmp_dest_mul = (double)(v1 * v2); |
| 3165 | else |
| 3166 | sgl_tmp_dest_mul = v1 * v2; |
| 3167 | } |
| 3168 | |
| 3169 | /* Do the add operation, being careful about source and result |
| 3170 | precision. Remember, the R bit indicates source and result precision |
| 3171 | here. */ |
| 3172 | if (res_prec) |
| 3173 | { |
| 3174 | double v1 = get_fval_from_optype_d (insn, A_unit_op1); |
| 3175 | double v2 = get_fval_from_optype_d (insn, A_unit_op2); |
| 3176 | |
| 3177 | /* For add/sub, if fsrc1 is the same as fdest, then the last stage |
| 3178 | is bypassed to fsrc1 (rather than using the value in fsrc1). |
| 3179 | Likewise for fsrc2. */ |
| 3180 | if (A_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest) |
| 3181 | v1 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents; |
| 3182 | if (A_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest) |
| 3183 | v2 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents; |
| 3184 | |
| 3185 | if (res_prec) |
| 3186 | dbl_tmp_dest_add = is_sub ? v1 - v2 : v1 + v2; |
| 3187 | else |
| 3188 | sgl_tmp_dest_add = is_sub ? (float)(v1 - v2) : (float)(v1 + v2); |
| 3189 | } |
| 3190 | else |
| 3191 | { |
| 3192 | float v1 = get_fval_from_optype_s (insn, A_unit_op1); |
| 3193 | float v2 = get_fval_from_optype_s (insn, A_unit_op2); |
| 3194 | |
| 3195 | /* For add/sub, if fsrc1 is the same as fdest, then the last stage |
| 3196 | is bypassed to fsrc1 (rather than using the value in fsrc1). |
| 3197 | Likewise for fsrc2. */ |
| 3198 | if (A_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest) |
| 3199 | v1 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents; |
| 3200 | if (A_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest) |
| 3201 | v2 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents; |
| 3202 | |
| 3203 | if (res_prec) |
| 3204 | dbl_tmp_dest_add = is_sub ? (double)(v1 - v2) : (double)(v1 + v2); |
| 3205 | else |
| 3206 | sgl_tmp_dest_add = is_sub ? v1 - v2 : v1 + v2; |
| 3207 | } |
| 3208 | |
| 3209 | /* If necessary, load T. */ |
| 3210 | if (T_loaded) |
| 3211 | { |
| 3212 | /* T is loaded from the result of the last stage of the multiplier. */ |
| 3213 | if (m_M[num_mul_stages - 1].stat.mrp) |
| 3214 | m_T.d = dbl_last_Mstage_contents; |
| 3215 | else |
| 3216 | m_T.s = sgl_last_Mstage_contents; |
| 3217 | } |
| 3218 | |
| 3219 | /* If necessary, load KR or KI. */ |
| 3220 | if (K_loaded) |
| 3221 | { |
| 3222 | /* KI or KR is loaded from the first register input. */ |
| 3223 | if (M_unit_op1 == OP_KI) |
| 3224 | { |
| 3225 | if (src_prec) |
| 3226 | m_KI.d = get_fregval_d (fsrc1); |
| 3227 | else |
| 3228 | m_KI.s = get_fregval_s (fsrc1); |
| 3229 | } |
| 3230 | else if (M_unit_op1 == OP_KR) |
| 3231 | { |
| 3232 | if (src_prec) |
| 3233 | m_KR.d = get_fregval_d (fsrc1); |
| 3234 | else |
| 3235 | m_KR.s = get_fregval_s (fsrc1); |
| 3236 | } |
| 3237 | else |
| 3238 | assert (0); |
| 3239 | } |
| 3240 | |
| 3241 | /* Now update fdest (either from adder pipe or multiplier pipe, |
| 3242 | depending on whether the instruction is pfam or pfmam). */ |
| 3243 | if (is_pfam) |
| 3244 | { |
| 3245 | /* Update fdest with the result from the last stage of the |
| 3246 | adder pipeline, with precision specified by the ARP |
| 3247 | bit of the stage's result-status bits. */ |
| 3248 | if (m_A[2].stat.arp) |
| 3249 | set_fregval_d (fdest, dbl_last_Astage_contents); |
| 3250 | else |
| 3251 | set_fregval_s (fdest, sgl_last_Astage_contents); |
| 3252 | } |
| 3253 | else |
| 3254 | { |
| 3255 | /* Update fdest with the result from the last stage of the |
| 3256 | multiplier pipeline, with precision specified by the MRP |
| 3257 | bit of the stage's result-status bits. */ |
| 3258 | if (m_M[num_mul_stages - 1].stat.mrp) |
| 3259 | set_fregval_d (fdest, dbl_last_Mstage_contents); |
| 3260 | else |
| 3261 | set_fregval_s (fdest, sgl_last_Mstage_contents); |
| 3262 | } |
| 3263 | |
| 3264 | /* FIXME: Set result-status bits besides MRP. And copy to fsr from |
| 3265 | last stage. */ |
| 3266 | /* FIXME: Mixed precision (only weird for pfmul). */ |
| 3267 | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 3268 | /* Copy 3rd stage MRP to FSR. */ |
| 3269 | if (m_M[num_mul_stages - 2 /* 1 */].stat.mrp) |
| 3270 | m_cregs[CR_FSR] |= 0x10000000; |
| 3271 | else |
| 3272 | m_cregs[CR_FSR] &= ~0x10000000; |
| 3273 | #endif |
| 3274 | |
| 3275 | /* Now advance multiplier pipeline and write current calculation to |
| 3276 | first stage. */ |
| 3277 | if (num_mul_stages == 3) |
| 3278 | { |
| 3279 | m_M[2] = m_M[1]; |
| 3280 | m_M[1] = m_M[0]; |
| 3281 | } |
| 3282 | else |
| 3283 | m_M[1] = m_M[0]; |
| 3284 | |
| 3285 | if (res_prec) |
| 3286 | { |
| 3287 | m_M[0].val.d = dbl_tmp_dest_mul; |
| 3288 | m_M[0].stat.mrp = 1; |
| 3289 | } |
| 3290 | else |
| 3291 | { |
| 3292 | m_M[0].val.s = sgl_tmp_dest_mul; |
| 3293 | m_M[0].stat.mrp = 0; |
| 3294 | } |
| 3295 | |
| 3296 | /* FIXME: Set result-status bits besides ARP. And copy to fsr from |
| 3297 | last stage. */ |
| 3298 | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 3299 | /* Copy 3rd stage ARP to FSR. */ |
| 3300 | if (m_A[1 /* 2 */].stat.arp) |
| 3301 | m_cregs[CR_FSR] |= 0x20000000; |
| 3302 | else |
| 3303 | m_cregs[CR_FSR] &= ~0x20000000; |
| 3304 | #endif |
| 3305 | |
| 3306 | /* Now advance adder pipeline and write current calculation to |
| 3307 | first stage. */ |
| 3308 | m_A[2] = m_A[1]; |
| 3309 | m_A[1] = m_A[0]; |
| 3310 | if (res_prec) |
| 3311 | { |
| 3312 | m_A[0].val.d = dbl_tmp_dest_add; |
| 3313 | m_A[0].stat.arp = 1; |
| 3314 | } |
| 3315 | else |
| 3316 | { |
| 3317 | m_A[0].val.s = sgl_tmp_dest_add; |
| 3318 | m_A[0].stat.arp = 0; |
| 3319 | } |
| 3320 | } |
| 3321 | |
| 3322 | |
| 3323 | /* Execute frcp.{ss,sd,dd} fsrc2,fdest (.ds disallowed above). */ |
| 3324 | void i860_cpu_device::insn_frcp (UINT32 insn) |
| 3325 | { |
| 3326 | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3327 | UINT32 fdest = get_fdest (insn); |
| 3328 | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3329 | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 3330 | |
| 3331 | /* Do the operation, being careful about source and result |
| 3332 | precision. */ |
| 3333 | if (src_prec) |
| 3334 | { |
| 3335 | double v = get_fregval_d (fsrc2); |
| 3336 | double res; |
| 3337 | if (v == (double)0.0) |
| 3338 | { |
| 3339 | /* Generate source-exception trap if fsrc2 is 0. */ |
| 3340 | if (0 /* && GET_FSR_FTE () */) |
| 3341 | { |
| 3342 | SET_PSR_FT (1); |
| 3343 | SET_FSR_SE (1); |
| 3344 | m_pending_trap = GET_FSR_FTE (); |
| 3345 | } |
| 3346 | /* Set fdest to INF or some other exceptional value here? */ |
| 3347 | } |
| 3348 | else |
| 3349 | { |
| 3350 | /* Real i860 isn't a precise as a real divide, but this should |
| 3351 | be okay. */ |
| 3352 | SET_FSR_SE (0); |
| 3353 | *((UINT64 *)&v) &= 0xfffff00000000000ULL; |
| 3354 | res = (double)1.0/v; |
| 3355 | *((UINT64 *)&res) &= 0xfffff00000000000ULL; |
| 3356 | if (res_prec) |
| 3357 | set_fregval_d (fdest, res); |
| 3358 | else |
| 3359 | set_fregval_s (fdest, (float)res); |
| 3360 | } |
| 3361 | } |
| 3362 | else |
| 3363 | { |
| 3364 | float v = get_fregval_s (fsrc2); |
| 3365 | float res; |
| 3366 | if (v == 0.0) |
| 3367 | { |
| 3368 | /* Generate source-exception trap if fsrc2 is 0. */ |
| 3369 | if (0 /* GET_FSR_FTE () */) |
| 3370 | { |
| 3371 | SET_PSR_FT (1); |
| 3372 | SET_FSR_SE (1); |
| 3373 | m_pending_trap = GET_FSR_FTE (); |
| 3374 | } |
| 3375 | /* Set fdest to INF or some other exceptional value here? */ |
| 3376 | } |
| 3377 | else |
| 3378 | { |
| 3379 | /* Real i860 isn't a precise as a real divide, but this should |
| 3380 | be okay. */ |
| 3381 | SET_FSR_SE (0); |
| 3382 | *((UINT32 *)&v) &= 0xffff8000; |
| 3383 | res = (float)1.0/v; |
| 3384 | *((UINT32 *)&res) &= 0xffff8000; |
| 3385 | if (res_prec) |
| 3386 | set_fregval_d (fdest, (double)res); |
| 3387 | else |
| 3388 | set_fregval_s (fdest, res); |
| 3389 | } |
| 3390 | } |
| 3391 | } |
| 3392 | |
| 3393 | |
| 3394 | /* Execute frsqr.{ss,sd,dd} fsrc2,fdest (.ds disallowed above). */ |
| 3395 | void i860_cpu_device::insn_frsqr (UINT32 insn) |
| 3396 | { |
| 3397 | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3398 | UINT32 fdest = get_fdest (insn); |
| 3399 | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3400 | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 3401 | |
| 3402 | /* Check for invalid .ds combination. */ |
| 3403 | if ((insn & 0x180) == 0x100) |
| 3404 | { |
| 3405 | unrecog_opcode (m_pc, insn); |
| 3406 | return; |
| 3407 | } |
| 3408 | |
| 3409 | /* Check for invalid .ds combination. */ |
| 3410 | if ((insn & 0x180) == 0x100) |
| 3411 | { |
| 3412 | unrecog_opcode (m_pc, insn); |
| 3413 | return; |
| 3414 | } |
| 3415 | |
| 3416 | /* Do the operation, being careful about source and result |
| 3417 | precision. */ |
| 3418 | if (src_prec) |
| 3419 | { |
| 3420 | double v = get_fregval_d (fsrc2); |
| 3421 | double res; |
| 3422 | if (v == 0.0 || v < 0.0) |
| 3423 | { |
| 3424 | /* Generate source-exception trap if fsrc2 is 0 or negative. */ |
| 3425 | if (0 /* GET_FSR_FTE () */) |
| 3426 | { |
| 3427 | SET_PSR_FT (1); |
| 3428 | SET_FSR_SE (1); |
| 3429 | m_pending_trap = GET_FSR_FTE (); |
| 3430 | } |
| 3431 | /* Set fdest to INF or some other exceptional value here? */ |
| 3432 | } |
| 3433 | else |
| 3434 | { |
| 3435 | SET_FSR_SE (0); |
| 3436 | *((UINT64 *)&v) &= 0xfffff00000000000ULL; |
| 3437 | res = (double)1.0/sqrt (v); |
| 3438 | *((UINT64 *)&res) &= 0xfffff00000000000ULL; |
| 3439 | if (res_prec) |
| 3440 | set_fregval_d (fdest, res); |
| 3441 | else |
| 3442 | set_fregval_s (fdest, (float)res); |
| 3443 | } |
| 3444 | } |
| 3445 | else |
| 3446 | { |
| 3447 | float v = get_fregval_s (fsrc2); |
| 3448 | float res; |
| 3449 | if (v == 0.0 || v < 0.0) |
| 3450 | { |
| 3451 | /* Generate source-exception trap if fsrc2 is 0 or negative. */ |
| 3452 | if (0 /* GET_FSR_FTE () */) |
| 3453 | { |
| 3454 | SET_PSR_FT (1); |
| 3455 | SET_FSR_SE (1); |
| 3456 | m_pending_trap = GET_FSR_FTE (); |
| 3457 | } |
| 3458 | /* Set fdest to INF or some other exceptional value here? */ |
| 3459 | } |
| 3460 | else |
| 3461 | { |
| 3462 | SET_FSR_SE (0); |
| 3463 | *((UINT32 *)&v) &= 0xffff8000; |
| 3464 | res = (float)1.0/sqrt (v); |
| 3465 | *((UINT32 *)&res) &= 0xffff8000; |
| 3466 | if (res_prec) |
| 3467 | set_fregval_d (fdest, (double)res); |
| 3468 | else |
| 3469 | set_fregval_s (fdest, res); |
| 3470 | } |
| 3471 | } |
| 3472 | } |
| 3473 | |
| 3474 | |
| 3475 | /* Execute fxfr fsrc1,idest. */ |
| 3476 | void i860_cpu_device::insn_fxfr (UINT32 insn) |
| 3477 | { |
| 3478 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3479 | UINT32 idest = get_idest (insn); |
| 3480 | float fv = 0; |
| 3481 | |
| 3482 | /* This is a bit-pattern transfer, not a conversion. */ |
| 3483 | fv = get_fregval_s (fsrc1); |
| 3484 | set_iregval (idest, *(UINT32 *)&fv); |
| 3485 | } |
| 3486 | |
| 3487 | |
| 3488 | /* Execute [p]ftrunc.{ss,sd,dd} fsrc1,idest. */ |
| 3489 | /* FIXME: Is .ss really a valid combination? On the one hand, |
| 3490 | the programmer's reference (1990) lists ftrunc.p where .p |
| 3491 | is any of {ss,sd,dd}. On the other hand, a paragraph on the |
| 3492 | same page states that [p]ftrunc must specify double-precision |
| 3493 | results. Inconsistent. |
| 3494 | Update: The vendor SVR4 assembler does not accept .ss combination, |
| 3495 | so the latter sentence above appears to be the correct way. */ |
| 3496 | void i860_cpu_device::insn_ftrunc (UINT32 insn) |
| 3497 | { |
| 3498 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3499 | UINT32 fdest = get_fdest (insn); |
| 3500 | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3501 | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 3502 | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 3503 | |
| 3504 | /* Check for invalid .ds or .ss combinations. */ |
| 3505 | if ((insn & 0x080) == 0) |
| 3506 | { |
| 3507 | unrecog_opcode (m_pc, insn); |
| 3508 | return; |
| 3509 | } |
| 3510 | |
| 3511 | /* Do the operation, being careful about source and result |
| 3512 | precision. Operation: fdest = integer part of fsrc1 in |
| 3513 | lower 32-bits. */ |
| 3514 | if (src_prec) |
| 3515 | { |
| 3516 | double v1 = get_fregval_d (fsrc1); |
| 3517 | INT32 iv = (INT32)v1; |
| 3518 | /* We always write a single, since the lower 32-bits of fdest |
| 3519 | get the result (and the even numbered reg is the lower). */ |
| 3520 | set_fregval_s (fdest, *(float *)&iv); |
| 3521 | } |
| 3522 | else |
| 3523 | { |
| 3524 | float v1 = get_fregval_s (fsrc1); |
| 3525 | INT32 iv = (INT32)v1; |
| 3526 | /* We always write a single, since the lower 32-bits of fdest |
| 3527 | get the result (and the even numbered reg is the lower). */ |
| 3528 | set_fregval_s (fdest, *(float *)&iv); |
| 3529 | } |
| 3530 | |
| 3531 | /* FIXME: Handle updating of pipestages for pftrunc. */ |
| 3532 | /* Includes looking at ARP (add result precision.) */ |
| 3533 | if (piped) |
| 3534 | { |
| 3535 | fprintf (stderr, "insn_ftrunc: FIXME: pipelined not functional yet.\n"); |
| 3536 | if (res_prec) |
| 3537 | set_fregval_d (fdest, 0.0); |
| 3538 | else |
| 3539 | set_fregval_s (fdest, 0.0); |
| 3540 | } |
| 3541 | } |
| 3542 | |
| 3543 | |
| 3544 | /* Execute [p]famov.{ss,sd,ds,dd} fsrc1,fdest. */ |
| 3545 | void i860_cpu_device::insn_famov (UINT32 insn) |
| 3546 | { |
| 3547 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3548 | UINT32 fdest = get_fdest (insn); |
| 3549 | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3550 | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 3551 | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 3552 | double dbl_tmp_dest = 0.0; |
| 3553 | double sgl_tmp_dest = 0.0; |
| 3554 | |
| 3555 | /* Do the operation, being careful about source and result |
| 3556 | precision. */ |
| 3557 | if (src_prec) |
| 3558 | { |
| 3559 | double v1 = get_fregval_d (fsrc1); |
| 3560 | if (res_prec) |
| 3561 | dbl_tmp_dest = v1; |
| 3562 | else |
| 3563 | sgl_tmp_dest = (float)v1; |
| 3564 | } |
| 3565 | else |
| 3566 | { |
| 3567 | float v1 = get_fregval_s (fsrc1); |
| 3568 | if (res_prec) |
| 3569 | dbl_tmp_dest = (double)v1; |
| 3570 | else |
| 3571 | sgl_tmp_dest = v1; |
| 3572 | } |
| 3573 | |
| 3574 | /* FIXME: Set result-status bits besides ARP. And copy to fsr from |
| 3575 | last stage. */ |
| 3576 | /* FIXME: Scalar version flows through all stages. */ |
| 3577 | if (!piped) |
| 3578 | { |
| 3579 | /* Scalar version writes the current calculation to the fdest |
| 3580 | register, with precision specified by the R bit. */ |
| 3581 | if (res_prec) |
| 3582 | set_fregval_d (fdest, dbl_tmp_dest); |
| 3583 | else |
| 3584 | set_fregval_s (fdest, sgl_tmp_dest); |
| 3585 | } |
| 3586 | else |
| 3587 | { |
| 3588 | /* Pipelined version writes fdest with the result from the last |
| 3589 | stage of the pipeline, with precision specified by the ARP |
| 3590 | bit of the stage's result-status bits. */ |
| 3591 | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 3592 | /* Copy 3rd stage ARP to FSR. */ |
| 3593 | if (m_A[1 /* 2 */].stat.arp) |
| 3594 | m_cregs[CR_FSR] |= 0x20000000; |
| 3595 | else |
| 3596 | m_cregs[CR_FSR] &= ~0x20000000; |
| 3597 | #endif |
| 3598 | if (m_A[2].stat.arp) /* 3rd (last) stage. */ |
| 3599 | set_fregval_d (fdest, m_A[2].val.d); |
| 3600 | else |
| 3601 | set_fregval_s (fdest, m_A[2].val.s); |
| 3602 | |
| 3603 | /* Now advance pipeline and write current calculation to |
| 3604 | first stage. */ |
| 3605 | m_A[2] = m_A[1]; |
| 3606 | m_A[1] = m_A[0]; |
| 3607 | if (res_prec) |
| 3608 | { |
| 3609 | m_A[0].val.d = dbl_tmp_dest; |
| 3610 | m_A[0].stat.arp = 1; |
| 3611 | } |
| 3612 | else |
| 3613 | { |
| 3614 | m_A[0].val.s = sgl_tmp_dest; |
| 3615 | m_A[0].stat.arp = 0; |
| 3616 | } |
| 3617 | } |
| 3618 | } |
| 3619 | |
| 3620 | |
| 3621 | /* Execute [p]fiadd/sub.{ss,dd} fsrc1,fsrc2,fdest. */ |
| 3622 | void i860_cpu_device::insn_fiadd_sub (UINT32 insn) |
| 3623 | { |
| 3624 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3625 | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3626 | UINT32 fdest = get_fdest (insn); |
| 3627 | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3628 | int res_prec = insn & 0x080; /* 1 = double, 0 = single. */ |
| 3629 | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 3630 | int is_sub = insn & 0x4; /* 1 = sub, 0 = add. */ |
| 3631 | double dbl_tmp_dest = 0.0; |
| 3632 | float sgl_tmp_dest = 0.0; |
| 3633 | |
| 3634 | /* Check for invalid .ds and .sd combinations. */ |
| 3635 | if ((insn & 0x180) == 0x100 |
| 3636 | || (insn & 0x180) == 0x080) |
| 3637 | { |
| 3638 | unrecog_opcode (m_pc, insn); |
| 3639 | return; |
| 3640 | } |
| 3641 | |
| 3642 | /* Do the operation, being careful about source and result |
| 3643 | precision. */ |
| 3644 | if (src_prec) |
| 3645 | { |
| 3646 | double v1 = get_fregval_d (fsrc1); |
| 3647 | double v2 = get_fregval_d (fsrc2); |
| 3648 | UINT64 iv1 = *(UINT64 *)&v1; |
| 3649 | UINT64 iv2 = *(UINT64 *)&v2; |
| 3650 | UINT64 r; |
| 3651 | if (is_sub) |
| 3652 | r = iv1 - iv2; |
| 3653 | else |
| 3654 | r = iv1 + iv2; |
| 3655 | if (res_prec) |
| 3656 | dbl_tmp_dest = *(double *)&r; |
| 3657 | else |
| 3658 | assert (0); /* .ds not allowed. */ |
| 3659 | } |
| 3660 | else |
| 3661 | { |
| 3662 | float v1 = get_fregval_s (fsrc1); |
| 3663 | float v2 = get_fregval_s (fsrc2); |
| 3664 | UINT64 iv1 = (UINT64)(*(UINT32 *)&v1); |
| 3665 | UINT64 iv2 = (UINT64)(*(UINT32 *)&v2); |
| 3666 | UINT32 r; |
| 3667 | if (is_sub) |
| 3668 | r = (UINT32)(iv1 - iv2); |
| 3669 | else |
| 3670 | r = (UINT32)(iv1 + iv2); |
| 3671 | if (res_prec) |
| 3672 | assert (0); /* .sd not allowed. */ |
| 3673 | else |
| 3674 | sgl_tmp_dest = *(float *)&r; |
| 3675 | } |
| 3676 | |
| 3677 | /* FIXME: Copy result-status bit IRP to fsr from last stage. */ |
| 3678 | /* FIXME: Scalar version flows through all stages. */ |
| 3679 | if (!piped) |
| 3680 | { |
| 3681 | /* Scalar version writes the current calculation to the fdest |
| 3682 | register, with precision specified by the R bit. */ |
| 3683 | if (res_prec) |
| 3684 | set_fregval_d (fdest, dbl_tmp_dest); |
| 3685 | else |
| 3686 | set_fregval_s (fdest, sgl_tmp_dest); |
| 3687 | } |
| 3688 | else |
| 3689 | { |
| 3690 | /* Pipelined version writes fdest with the result from the last |
| 3691 | stage of the pipeline, with precision specified by the IRP |
| 3692 | bit of the stage's result-status bits. */ |
| 3693 | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 3694 | /* Copy stage IRP to FSR. */ |
| 3695 | if (res_prec) |
| 3696 | m_cregs[CR_FSR] |= 0x08000000; |
| 3697 | else |
| 3698 | m_cregs[CR_FSR] &= ~0x08000000; |
| 3699 | #endif |
| 3700 | if (m_G.stat.irp) /* 1st (and last) stage. */ |
| 3701 | set_fregval_d (fdest, m_G.val.d); |
| 3702 | else |
| 3703 | set_fregval_s (fdest, m_G.val.s); |
| 3704 | |
| 3705 | /* Now write current calculation to first and only stage. */ |
| 3706 | if (res_prec) |
| 3707 | { |
| 3708 | m_G.val.d = dbl_tmp_dest; |
| 3709 | m_G.stat.irp = 1; |
| 3710 | } |
| 3711 | else |
| 3712 | { |
| 3713 | m_G.val.s = sgl_tmp_dest; |
| 3714 | m_G.stat.irp = 0; |
| 3715 | } |
| 3716 | } |
| 3717 | } |
| 3718 | |
| 3719 | |
| 3720 | /* Execute pf{gt,le,eq}.{ss,dd} fsrc1,fsrc2,fdest. |
| 3721 | Opcode pfgt has R bit cleared; pfle has R bit set. */ |
| 3722 | void i860_cpu_device::insn_fcmp (UINT32 insn) |
| 3723 | { |
| 3724 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3725 | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3726 | UINT32 fdest = get_fdest (insn); |
| 3727 | int src_prec = insn & 0x100; /* 1 = double, 0 = single. */ |
| 3728 | double dbl_tmp_dest = 0.0; |
| 3729 | double sgl_tmp_dest = 0.0; |
| 3730 | /* int is_eq = insn & 1; */ |
| 3731 | int is_gt = ((insn & 0x81) == 0x00); |
| 3732 | int is_le = ((insn & 0x81) == 0x80); |
| 3733 | |
| 3734 | /* Do the operation. Source and result precision must be the same. |
| 3735 | pfgt: CC set if fsrc1 > fsrc2, else cleared. |
| 3736 | pfle: CC cleared if fsrc1 <= fsrc2, else set. |
| 3737 | pfeq: CC set if fsrc1 = fsrc2, else cleared. |
| 3738 | |
| 3739 | Note that the compares write an undefined (but non-exceptional) |
| 3740 | result into the first stage of the adder pipeline. We'll model |
| 3741 | this by just pushing in dbl_ or sgl_tmp_dest which equal 0.0. */ |
| 3742 | if (src_prec) |
| 3743 | { |
| 3744 | double v1 = get_fregval_d (fsrc1); |
| 3745 | double v2 = get_fregval_d (fsrc2); |
| 3746 | if (is_gt) /* gt. */ |
| 3747 | SET_PSR_CC (v1 > v2 ? 1 : 0); |
| 3748 | else if (is_le) /* le. */ |
| 3749 | SET_PSR_CC (v1 <= v2 ? 0 : 1); |
| 3750 | else /* eq. */ |
| 3751 | SET_PSR_CC (v1 == v2 ? 1 : 0); |
| 3752 | } |
| 3753 | else |
| 3754 | { |
| 3755 | float v1 = get_fregval_s (fsrc1); |
| 3756 | float v2 = get_fregval_s (fsrc2); |
| 3757 | if (is_gt) /* gt. */ |
| 3758 | SET_PSR_CC (v1 > v2 ? 1 : 0); |
| 3759 | else if (is_le) /* le. */ |
| 3760 | SET_PSR_CC (v1 <= v2 ? 0 : 1); |
| 3761 | else /* eq. */ |
| 3762 | SET_PSR_CC (v1 == v2 ? 1 : 0); |
| 3763 | } |
| 3764 | |
| 3765 | /* FIXME: Set result-status bits besides ARP. And copy to fsr from |
| 3766 | last stage. */ |
| 3767 | /* These write fdest with the result from the last |
| 3768 | stage of the pipeline, with precision specified by the ARP |
| 3769 | bit of the stage's result-status bits. */ |
| 3770 | #if 1 /* FIXME: WIP on FSR update. This may not be correct. */ |
| 3771 | /* Copy 3rd stage ARP to FSR. */ |
| 3772 | if (m_A[1 /* 2 */].stat.arp) |
| 3773 | m_cregs[CR_FSR] |= 0x20000000; |
| 3774 | else |
| 3775 | m_cregs[CR_FSR] &= ~0x20000000; |
| 3776 | #endif |
| 3777 | if (m_A[2].stat.arp) /* 3rd (last) stage. */ |
| 3778 | set_fregval_d (fdest, m_A[2].val.d); |
| 3779 | else |
| 3780 | set_fregval_s (fdest, m_A[2].val.s); |
| 3781 | |
| 3782 | /* Now advance pipeline and write current calculation to |
| 3783 | first stage. */ |
| 3784 | m_A[2] = m_A[1]; |
| 3785 | m_A[1] = m_A[0]; |
| 3786 | if (src_prec) |
| 3787 | { |
| 3788 | m_A[0].val.d = dbl_tmp_dest; |
| 3789 | m_A[0].stat.arp = 1; |
| 3790 | } |
| 3791 | else |
| 3792 | { |
| 3793 | m_A[0].val.s = sgl_tmp_dest; |
| 3794 | m_A[0].stat.arp = 0; |
| 3795 | } |
| 3796 | } |
| 3797 | |
| 3798 | |
| 3799 | /* Execute [p]fzchk{l,s} fsrc1,fsrc2,fdest. |
| 3800 | The fzchk instructions have S and R bits set. */ |
| 3801 | void i860_cpu_device::insn_fzchk (UINT32 insn) |
| 3802 | { |
| 3803 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3804 | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3805 | UINT32 fdest = get_fdest (insn); |
| 3806 | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 3807 | int is_fzchks = insn & 8; /* 1 = fzchks, 0 = fzchkl. */ |
| 3808 | double dbl_tmp_dest = 0.0; |
| 3809 | int i; |
| 3810 | double v1 = get_fregval_d (fsrc1); |
| 3811 | double v2 = get_fregval_d (fsrc2); |
| 3812 | UINT64 iv1 = *(UINT64 *)&v1; |
| 3813 | UINT64 iv2 = *(UINT64 *)&v2; |
| 3814 | UINT64 r = 0; |
| 3815 | char pm = GET_PSR_PM (); |
| 3816 | |
| 3817 | /* Check for S and R bits set. */ |
| 3818 | if ((insn & 0x180) != 0x180) |
| 3819 | { |
| 3820 | unrecog_opcode (m_pc, insn); |
| 3821 | return; |
| 3822 | } |
| 3823 | |
| 3824 | /* Do the operation. The fzchks version operates in parallel on |
| 3825 | four 16-bit pixels, while the fzchkl operates on two 32-bit |
| 3826 | pixels (pixels are unsigned ordinals in this context). */ |
| 3827 | if (is_fzchks) |
| 3828 | { |
| 3829 | pm = (pm >> 4) & 0x0f; |
| 3830 | for (i = 3; i >= 0; i--) |
| 3831 | { |
| 3832 | UINT16 ps1 = (iv1 >> (i * 16)) & 0xffff; |
| 3833 | UINT16 ps2 = (iv2 >> (i * 16)) & 0xffff; |
| 3834 | if (ps2 <= ps1) |
| 3835 | { |
| 3836 | r |= ((UINT64)ps2 << (i * 16)); |
| 3837 | pm |= (1 << (7 - (3 - i))); |
| 3838 | } |
| 3839 | else |
| 3840 | { |
| 3841 | r |= ((UINT64)ps1 << (i * 16)); |
| 3842 | pm &= ~(1 << (7 - (3 - i))); |
| 3843 | } |
| 3844 | } |
| 3845 | } |
| 3846 | else |
| 3847 | { |
| 3848 | pm = (pm >> 2) & 0x3f; |
| 3849 | for (i = 1; i >= 0; i--) |
| 3850 | { |
| 3851 | UINT32 ps1 = (iv1 >> (i * 32)) & 0xffffffff; |
| 3852 | UINT32 ps2 = (iv2 >> (i * 32)) & 0xffffffff; |
| 3853 | if (ps2 <= ps1) |
| 3854 | { |
| 3855 | r |= ((UINT64)ps2 << (i * 32)); |
| 3856 | pm |= (1 << (7 - (1 - i))); |
| 3857 | } |
| 3858 | else |
| 3859 | { |
| 3860 | r |= ((UINT64)ps1 << (i * 32)); |
| 3861 | pm &= ~(1 << (7 - (1 - i))); |
| 3862 | } |
| 3863 | } |
| 3864 | } |
| 3865 | |
| 3866 | dbl_tmp_dest = *(double *)&r; |
| 3867 | SET_PSR_PM (pm); |
| 3868 | m_merge = 0; |
| 3869 | |
| 3870 | /* FIXME: Copy result-status bit IRP to fsr from last stage. */ |
| 3871 | /* FIXME: Scalar version flows through all stages. */ |
| 3872 | if (!piped) |
| 3873 | { |
| 3874 | /* Scalar version writes the current calculation to the fdest |
| 3875 | register, always with double precision. */ |
| 3876 | set_fregval_d (fdest, dbl_tmp_dest); |
| 3877 | } |
| 3878 | else |
| 3879 | { |
| 3880 | /* Pipelined version writes fdest with the result from the last |
| 3881 | stage of the pipeline, with precision specified by the IRP |
| 3882 | bit of the stage's result-status bits. */ |
| 3883 | if (m_G.stat.irp) /* 1st (and last) stage. */ |
| 3884 | set_fregval_d (fdest, m_G.val.d); |
| 3885 | else |
| 3886 | set_fregval_s (fdest, m_G.val.s); |
| 3887 | |
| 3888 | /* Now write current calculation to first and only stage. */ |
| 3889 | m_G.val.d = dbl_tmp_dest; |
| 3890 | m_G.stat.irp = 1; |
| 3891 | } |
| 3892 | } |
| 3893 | |
| 3894 | |
| 3895 | /* Execute [p]form.dd fsrc1,fdest. |
| 3896 | The form.dd instructions have S and R bits set. */ |
| 3897 | void i860_cpu_device::insn_form (UINT32 insn) |
| 3898 | { |
| 3899 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3900 | UINT32 fdest = get_fdest (insn); |
| 3901 | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 3902 | double dbl_tmp_dest = 0.0; |
| 3903 | double v1 = get_fregval_d (fsrc1); |
| 3904 | UINT64 iv1 = *(UINT64 *)&v1; |
| 3905 | |
| 3906 | /* Check for S and R bits set. */ |
| 3907 | if ((insn & 0x180) != 0x180) |
| 3908 | { |
| 3909 | unrecog_opcode (m_pc, insn); |
| 3910 | return; |
| 3911 | } |
| 3912 | |
| 3913 | iv1 |= m_merge; |
| 3914 | dbl_tmp_dest = *(double *)&iv1; |
| 3915 | m_merge = 0; |
| 3916 | |
| 3917 | /* FIXME: Copy result-status bit IRP to fsr from last stage. */ |
| 3918 | /* FIXME: Scalar version flows through all stages. */ |
| 3919 | if (!piped) |
| 3920 | { |
| 3921 | /* Scalar version writes the current calculation to the fdest |
| 3922 | register, always with double precision. */ |
| 3923 | set_fregval_d (fdest, dbl_tmp_dest); |
| 3924 | } |
| 3925 | else |
| 3926 | { |
| 3927 | /* Pipelined version writes fdest with the result from the last |
| 3928 | stage of the pipeline, with precision specified by the IRP |
| 3929 | bit of the stage's result-status bits. */ |
| 3930 | if (m_G.stat.irp) /* 1st (and last) stage. */ |
| 3931 | set_fregval_d (fdest, m_G.val.d); |
| 3932 | else |
| 3933 | set_fregval_s (fdest, m_G.val.s); |
| 3934 | |
| 3935 | /* Now write current calculation to first and only stage. */ |
| 3936 | m_G.val.d = dbl_tmp_dest; |
| 3937 | m_G.stat.irp = 1; |
| 3938 | } |
| 3939 | } |
| 3940 | |
| 3941 | |
| 3942 | /* Execute [p]faddp fsrc1,fsrc2,fdest. */ |
| 3943 | void i860_cpu_device::insn_faddp (UINT32 insn) |
| 3944 | { |
| 3945 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 3946 | UINT32 fsrc2 = get_fsrc2 (insn); |
| 3947 | UINT32 fdest = get_fdest (insn); |
| 3948 | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 3949 | double dbl_tmp_dest = 0.0; |
| 3950 | double v1 = get_fregval_d (fsrc1); |
| 3951 | double v2 = get_fregval_d (fsrc2); |
| 3952 | UINT64 iv1 = *(UINT64 *)&v1; |
| 3953 | UINT64 iv2 = *(UINT64 *)&v2; |
| 3954 | UINT64 r = 0; |
| 3955 | int ps = GET_PSR_PS (); |
| 3956 | |
| 3957 | r = iv1 + iv2; |
| 3958 | dbl_tmp_dest = *(double *)&r; |
| 3959 | |
| 3960 | /* Update the merge register depending on the pixel size. |
| 3961 | PS: 0 = 8 bits, 1 = 16 bits, 2 = 32-bits. */ |
| 3962 | if (ps == 0) |
| 3963 | { |
| 3964 | m_merge = ((m_merge >> 8) & ~0xff00ff00ff00ff00ULL); |
| 3965 | m_merge |= (r & 0xff00ff00ff00ff00ULL); |
| 3966 | } |
| 3967 | else if (ps == 1) |
| 3968 | { |
| 3969 | m_merge = ((m_merge >> 6) & ~0xfc00fc00fc00fc00ULL); |
| 3970 | m_merge |= (r & 0xfc00fc00fc00fc00ULL); |
| 3971 | } |
| 3972 | else if (ps == 2) |
| 3973 | { |
| 3974 | m_merge = ((m_merge >> 8) & ~0xff000000ff000000ULL); |
| 3975 | m_merge |= (r & 0xff000000ff000000ULL); |
| 3976 | } |
| 3977 | #ifdef TRACE_UNDEFINED_I860 |
| 3978 | else |
| 3979 | fprintf (stderr, "insn_faddp: Undefined i860XR behavior, invalid value %d for pixel size.\n", ps); |
| 3980 | #endif |
| 3981 | |
| 3982 | /* FIXME: Copy result-status bit IRP to fsr from last stage. */ |
| 3983 | /* FIXME: Scalar version flows through all stages. */ |
| 3984 | if (!piped) |
| 3985 | { |
| 3986 | /* Scalar version writes the current calculation to the fdest |
| 3987 | register, always with double precision. */ |
| 3988 | set_fregval_d (fdest, dbl_tmp_dest); |
| 3989 | } |
| 3990 | else |
| 3991 | { |
| 3992 | /* Pipelined version writes fdest with the result from the last |
| 3993 | stage of the pipeline, with precision specified by the IRP |
| 3994 | bit of the stage's result-status bits. */ |
| 3995 | if (m_G.stat.irp) /* 1st (and last) stage. */ |
| 3996 | set_fregval_d (fdest, m_G.val.d); |
| 3997 | else |
| 3998 | set_fregval_s (fdest, m_G.val.s); |
| 3999 | |
| 4000 | /* Now write current calculation to first and only stage. */ |
| 4001 | m_G.val.d = dbl_tmp_dest; |
| 4002 | m_G.stat.irp = 1; |
| 4003 | } |
| 4004 | } |
| 4005 | |
| 4006 | |
| 4007 | /* Execute [p]faddz fsrc1,fsrc2,fdest. */ |
| 4008 | void i860_cpu_device::insn_faddz (UINT32 insn) |
| 4009 | { |
| 4010 | UINT32 fsrc1 = get_fsrc1 (insn); |
| 4011 | UINT32 fsrc2 = get_fsrc2 (insn); |
| 4012 | UINT32 fdest = get_fdest (insn); |
| 4013 | int piped = insn & 0x400; /* 1 = pipelined, 0 = scalar. */ |
| 4014 | double dbl_tmp_dest = 0.0; |
| 4015 | double v1 = get_fregval_d (fsrc1); |
| 4016 | double v2 = get_fregval_d (fsrc2); |
| 4017 | UINT64 iv1 = *(UINT64 *)&v1; |
| 4018 | UINT64 iv2 = *(UINT64 *)&v2; |
| 4019 | UINT64 r = 0; |
| 4020 | |
| 4021 | r = iv1 + iv2; |
| 4022 | dbl_tmp_dest = *(double *)&r; |
| 4023 | |
| 4024 | /* Update the merge register depending on the pixel size. */ |
| 4025 | m_merge = ((m_merge >> 16) & ~0xffff0000ffff0000ULL); |
| 4026 | m_merge |= (r & 0xffff0000ffff0000ULL); |
| 4027 | |
| 4028 | /* FIXME: Copy result-status bit IRP to fsr from last stage. */ |
| 4029 | /* FIXME: Scalar version flows through all stages. */ |
| 4030 | if (!piped) |
| 4031 | { |
| 4032 | /* Scalar version writes the current calculation to the fdest |
| 4033 | register, always with double precision. */ |
| 4034 | set_fregval_d (fdest, dbl_tmp_dest); |
| 4035 | } |
| 4036 | else |
| 4037 | { |
| 4038 | /* Pipelined version writes fdest with the result from the last |
| 4039 | stage of the pipeline, with precision specified by the IRP |
| 4040 | bit of the stage's result-status bits. */ |
| 4041 | if (m_G.stat.irp) /* 1st (and last) stage. */ |
| 4042 | set_fregval_d (fdest, m_G.val.d); |
| 4043 | else |
| 4044 | set_fregval_s (fdest, m_G.val.s); |
| 4045 | |
| 4046 | /* Now write current calculation to first and only stage. */ |
| 4047 | m_G.val.d = dbl_tmp_dest; |
| 4048 | m_G.stat.irp = 1; |
| 4049 | } |
| 4050 | } |
| 4051 | |
| 4052 | |
| 4053 | /* Flags for the decode table. */ |
| 4054 | enum { |
| 4055 | DEC_MORE = 1, /* More decoding necessary. */ |
| 4056 | DEC_DECODED = 2 /* Fully decoded, go. */ |
| 4057 | }; |
| 4058 | |
| 4059 | |
| 4060 | /* First-level decode table (i.e., for the 6 primary opcode bits). */ |
| 4061 | const i860_cpu_device::decode_tbl_t i860_cpu_device::decode_tbl[64] = { |
| 4062 | /* A slight bit of decoding for loads and stores is done in the |
| 4063 | execution routines (operand size and addressing mode), which |
| 4064 | is why their respective entries are identical. */ |
| 4065 | { &i860_cpu_device::insn_ldx, DEC_DECODED}, /* ld.b isrc1(isrc2),idest. */ |
| 4066 | { &i860_cpu_device::insn_ldx, DEC_DECODED}, /* ld.b #const(isrc2),idest. */ |
| 4067 | { &i860_cpu_device::insn_ixfr, DEC_DECODED}, /* ixfr isrc1ni,fdest. */ |
| 4068 | { &i860_cpu_device::insn_stx, DEC_DECODED}, /* st.b isrc1ni,#const(isrc2). */ |
| 4069 | { &i860_cpu_device::insn_ldx, DEC_DECODED}, /* ld.{s,l} isrc1(isrc2),idest. */ |
| 4070 | { &i860_cpu_device::insn_ldx, DEC_DECODED}, /* ld.{s,l} #const(isrc2),idest. */ |
| 4071 | { 0, 0}, |
| 4072 | { &i860_cpu_device::insn_stx, DEC_DECODED}, /* st.{s,l} isrc1ni,#const(isrc2),idest.*/ |
| 4073 | { &i860_cpu_device::insn_fldy, DEC_DECODED}, /* fld.{l,d,q} isrc1(isrc2)[++],fdest. */ |
| 4074 | { &i860_cpu_device::insn_fldy, DEC_DECODED}, /* fld.{l,d,q} #const(isrc2)[++],fdest. */ |
| 4075 | { &i860_cpu_device::insn_fsty, DEC_DECODED}, /* fst.{l,d,q} fdest,isrc1(isrc2)[++] */ |
| 4076 | { &i860_cpu_device::insn_fsty, DEC_DECODED}, /* fst.{l,d,q} fdest,#const(isrc2)[++] */ |
| 4077 | { &i860_cpu_device::insn_ld_ctrl, DEC_DECODED}, /* ld.c csrc2,idest. */ |
| 4078 | { &i860_cpu_device::insn_flush, DEC_DECODED}, /* flush #const(isrc2) (or autoinc). */ |
| 4079 | { &i860_cpu_device::insn_st_ctrl, DEC_DECODED}, /* st.c isrc1,csrc2. */ |
| 4080 | { &i860_cpu_device::insn_pstd, DEC_DECODED}, /* pst.d fdest,#const(isrc2)[++]. */ |
| 4081 | { &i860_cpu_device::insn_bri, DEC_DECODED}, /* bri isrc1ni. */ |
| 4082 | { &i860_cpu_device::insn_trap, DEC_DECODED}, /* trap isrc1ni,isrc2,idest. */ |
| 4083 | { 0, DEC_MORE}, /* FP ESCAPE FORMAT, more decode. */ |
| 4084 | { 0, DEC_MORE}, /* CORE ESCAPE FORMAT, more decode. */ |
| 4085 | { &i860_cpu_device::insn_btne, DEC_DECODED}, /* btne isrc1,isrc2,sbroff. */ |
| 4086 | { &i860_cpu_device::insn_btne_imm, DEC_DECODED}, /* btne #const,isrc2,sbroff. */ |
| 4087 | { &i860_cpu_device::insn_bte, DEC_DECODED}, /* bte isrc1,isrc2,sbroff. */ |
| 4088 | { &i860_cpu_device::insn_bte_imm, DEC_DECODED}, /* bte #const5,isrc2,idest. */ |
| 4089 | { &i860_cpu_device::insn_fldy, DEC_DECODED}, /* pfld.{l,d,q} isrc1(isrc2)[++],fdest.*/ |
| 4090 | { &i860_cpu_device::insn_fldy, DEC_DECODED}, /* pfld.{l,d,q} #const(isrc2)[++],fdest.*/ |
| 4091 | { &i860_cpu_device::insn_br, DEC_DECODED}, /* br lbroff. */ |
| 4092 | { &i860_cpu_device::insn_call, DEC_DECODED}, /* call lbroff . */ |
| 4093 | { &i860_cpu_device::insn_bc, DEC_DECODED}, /* bc lbroff. */ |
| 4094 | { &i860_cpu_device::insn_bct, DEC_DECODED}, /* bc.t lbroff. */ |
| 4095 | { &i860_cpu_device::insn_bnc, DEC_DECODED}, /* bnc lbroff. */ |
| 4096 | { &i860_cpu_device::insn_bnct, DEC_DECODED}, /* bnc.t lbroff. */ |
| 4097 | { &i860_cpu_device::insn_addu, DEC_DECODED}, /* addu isrc1,isrc2,idest. */ |
| 4098 | { &i860_cpu_device::insn_addu_imm, DEC_DECODED}, /* addu #const,isrc2,idest. */ |
| 4099 | { &i860_cpu_device::insn_subu, DEC_DECODED}, /* subu isrc1,isrc2,idest. */ |
| 4100 | { &i860_cpu_device::insn_subu_imm, DEC_DECODED}, /* subu #const,isrc2,idest. */ |
| 4101 | { &i860_cpu_device::insn_adds, DEC_DECODED}, /* adds isrc1,isrc2,idest. */ |
| 4102 | { &i860_cpu_device::insn_adds_imm, DEC_DECODED}, /* adds #const,isrc2,idest. */ |
| 4103 | { &i860_cpu_device::insn_subs, DEC_DECODED}, /* subs isrc1,isrc2,idest. */ |
| 4104 | { &i860_cpu_device::insn_subs_imm, DEC_DECODED}, /* subs #const,isrc2,idest. */ |
| 4105 | { &i860_cpu_device::insn_shl, DEC_DECODED}, /* shl isrc1,isrc2,idest. */ |
| 4106 | { &i860_cpu_device::insn_shl_imm, DEC_DECODED}, /* shl #const,isrc2,idest. */ |
| 4107 | { &i860_cpu_device::insn_shr, DEC_DECODED}, /* shr isrc1,isrc2,idest. */ |
| 4108 | { &i860_cpu_device::insn_shr_imm, DEC_DECODED}, /* shr #const,isrc2,idest. */ |
| 4109 | { &i860_cpu_device::insn_shrd, DEC_DECODED}, /* shrd isrc1ni,isrc2,idest. */ |
| 4110 | { &i860_cpu_device::insn_bla, DEC_DECODED}, /* bla isrc1ni,isrc2,sbroff. */ |
| 4111 | { &i860_cpu_device::insn_shra, DEC_DECODED}, /* shra isrc1,isrc2,idest. */ |
| 4112 | { &i860_cpu_device::insn_shra_imm, DEC_DECODED}, /* shra #const,isrc2,idest. */ |
| 4113 | { &i860_cpu_device::insn_and, DEC_DECODED}, /* and isrc1,isrc2,idest. */ |
| 4114 | { &i860_cpu_device::insn_and_imm, DEC_DECODED}, /* and #const,isrc2,idest. */ |
| 4115 | { 0, 0}, |
| 4116 | { &i860_cpu_device::insn_andh_imm, DEC_DECODED}, /* andh #const,isrc2,idest. */ |
| 4117 | { &i860_cpu_device::insn_andnot, DEC_DECODED}, /* andnot isrc1,isrc2,idest. */ |
| 4118 | { &i860_cpu_device::insn_andnot_imm, DEC_DECODED}, /* andnot #const,isrc2,idest. */ |
| 4119 | { 0, 0}, |
| 4120 | { &i860_cpu_device::insn_andnoth_imm, DEC_DECODED}, /* andnoth #const,isrc2,idest. */ |
| 4121 | { &i860_cpu_device::insn_or, DEC_DECODED}, /* or isrc1,isrc2,idest. */ |
| 4122 | { &i860_cpu_device::insn_or_imm, DEC_DECODED}, /* or #const,isrc2,idest. */ |
| 4123 | { 0, 0}, |
| 4124 | { &i860_cpu_device::insn_orh_imm, DEC_DECODED}, /* orh #const,isrc2,idest. */ |
| 4125 | { &i860_cpu_device::insn_xor, DEC_DECODED}, /* xor isrc1,isrc2,idest. */ |
| 4126 | { &i860_cpu_device::insn_xor_imm, DEC_DECODED}, /* xor #const,isrc2,idest. */ |
| 4127 | { 0, 0}, |
| 4128 | { &i860_cpu_device::insn_xorh_imm, DEC_DECODED}, /* xorh #const,isrc2,idest. */ |
| 4129 | }; |
| 4130 | |
| 4131 | |
| 4132 | /* Second-level decode table (i.e., for the 3 core escape opcode bits). */ |
| 4133 | const i860_cpu_device::decode_tbl_t i860_cpu_device::core_esc_decode_tbl[8] = { |
| 4134 | { 0, 0}, |
| 4135 | { 0, 0}, /* lock (FIXME: unimplemented). */ |
| 4136 | { &i860_cpu_device::insn_calli, DEC_DECODED}, /* calli isrc1ni. */ |
| 4137 | { 0, 0}, |
| 4138 | { &i860_cpu_device::insn_intovr, DEC_DECODED}, /* intovr. */ |
| 4139 | { 0, 0}, |
| 4140 | { 0, 0}, |
| 4141 | { 0, 0}, /* unlock (FIXME: unimplemented). */ |
| 4142 | }; |
| 4143 | |
| 4144 | |
| 4145 | /* Second-level decode table (i.e., for the 7 FP extended opcode bits). */ |
| 4146 | const i860_cpu_device::decode_tbl_t i860_cpu_device::fp_decode_tbl[128] = { |
| 4147 | /* Floating point instructions. The least significant 7 bits are |
| 4148 | the (extended) opcode and bits 10:7 are P,D,S,R respectively |
| 4149 | ([p]ipelined, [d]ual, [s]ource prec., [r]esult prec.). |
| 4150 | For some operations, I defer decoding the P,S,R bits to the |
| 4151 | emulation routine for them. */ |
| 4152 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x00 pf[m]am */ |
| 4153 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x01 pf[m]am */ |
| 4154 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x02 pf[m]am */ |
| 4155 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x03 pf[m]am */ |
| 4156 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x04 pf[m]am */ |
| 4157 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x05 pf[m]am */ |
| 4158 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x06 pf[m]am */ |
| 4159 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x07 pf[m]am */ |
| 4160 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x08 pf[m]am */ |
| 4161 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x09 pf[m]am */ |
| 4162 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x0A pf[m]am */ |
| 4163 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x0B pf[m]am */ |
| 4164 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x0C pf[m]am */ |
| 4165 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x0D pf[m]am */ |
| 4166 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x0E pf[m]am */ |
| 4167 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x0F pf[m]am */ |
| 4168 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x10 pf[m]sm */ |
| 4169 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x11 pf[m]sm */ |
| 4170 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x12 pf[m]sm */ |
| 4171 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x13 pf[m]sm */ |
| 4172 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x14 pf[m]sm */ |
| 4173 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x15 pf[m]sm */ |
| 4174 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x16 pf[m]sm */ |
| 4175 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x17 pf[m]sm */ |
| 4176 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x18 pf[m]sm */ |
| 4177 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x19 pf[m]sm */ |
| 4178 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x1A pf[m]sm */ |
| 4179 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x1B pf[m]sm */ |
| 4180 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x1C pf[m]sm */ |
| 4181 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x1D pf[m]sm */ |
| 4182 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x1E pf[m]sm */ |
| 4183 | { &i860_cpu_device::insn_dualop, DEC_DECODED}, /* 0x1F pf[m]sm */ |
| 4184 | { &i860_cpu_device::insn_fmul, DEC_DECODED}, /* 0x20 [p]fmul */ |
| 4185 | { &i860_cpu_device::insn_fmlow, DEC_DECODED}, /* 0x21 fmlow.dd */ |
| 4186 | { &i860_cpu_device::insn_frcp, DEC_DECODED}, /* 0x22 frcp.{ss,sd,dd} */ |
| 4187 | { &i860_cpu_device::insn_frsqr, DEC_DECODED}, /* 0x23 frsqr.{ss,sd,dd} */ |
| 4188 | { &i860_cpu_device::insn_fmul, DEC_DECODED}, /* 0x24 pfmul3.dd */ |
| 4189 | { 0, 0}, /* 0x25 */ |
| 4190 | { 0, 0}, /* 0x26 */ |
| 4191 | { 0, 0}, /* 0x27 */ |
| 4192 | { 0, 0}, /* 0x28 */ |
| 4193 | { 0, 0}, /* 0x29 */ |
| 4194 | { 0, 0}, /* 0x2A */ |
| 4195 | { 0, 0}, /* 0x2B */ |
| 4196 | { 0, 0}, /* 0x2C */ |
| 4197 | { 0, 0}, /* 0x2D */ |
| 4198 | { 0, 0}, /* 0x2E */ |
| 4199 | { 0, 0}, /* 0x2F */ |
| 4200 | { &i860_cpu_device::insn_fadd_sub, DEC_DECODED}, /* 0x30, [p]fadd.{ss,sd,dd} */ |
| 4201 | { &i860_cpu_device::insn_fadd_sub, DEC_DECODED}, /* 0x31, [p]fsub.{ss,sd,dd} */ |
| 4202 | { 0, 0}, /* 0x32, [p]fix.{ss,sd,dd} FIXME: nyi. */ |
| 4203 | { &i860_cpu_device::insn_famov, DEC_DECODED}, /* 0x33, [p]famov.{ss,sd,ds,dd} */ |
| 4204 | { &i860_cpu_device::insn_fcmp, DEC_DECODED}, /* 0x34, pf{gt,le}.{ss,dd} */ |
| 4205 | { &i860_cpu_device::insn_fcmp, DEC_DECODED}, /* 0x35, pfeq.{ss,dd} */ |
| 4206 | { 0, 0}, /* 0x36 */ |
| 4207 | { 0, 0}, /* 0x37 */ |
| 4208 | { 0, 0}, /* 0x38 */ |
| 4209 | { 0, 0}, /* 0x39 */ |
| 4210 | { &i860_cpu_device::insn_ftrunc, DEC_DECODED}, /* 0x3A, [p]ftrunc.{ss,sd,dd} */ |
| 4211 | { 0, 0}, /* 0x3B */ |
| 4212 | { 0, 0}, /* 0x3C */ |
| 4213 | { 0, 0}, /* 0x3D */ |
| 4214 | { 0, 0}, /* 0x3E */ |
| 4215 | { 0, 0}, /* 0x3F */ |
| 4216 | { &i860_cpu_device::insn_fxfr, DEC_DECODED}, /* 0x40, fxfr */ |
| 4217 | { 0, 0}, /* 0x41 */ |
| 4218 | { 0, 0}, /* 0x42 */ |
| 4219 | { 0, 0}, /* 0x43 */ |
| 4220 | { 0, 0}, /* 0x44 */ |
| 4221 | { 0, 0}, /* 0x45 */ |
| 4222 | { 0, 0}, /* 0x46 */ |
| 4223 | { 0, 0}, /* 0x47 */ |
| 4224 | { 0, 0}, /* 0x48 */ |
| 4225 | { &i860_cpu_device::insn_fiadd_sub, DEC_DECODED}, /* 0x49, [p]fiadd.{ss,dd} */ |
| 4226 | { 0, 0}, /* 0x4A */ |
| 4227 | { 0, 0}, /* 0x4B */ |
| 4228 | { 0, 0}, /* 0x4C */ |
| 4229 | { &i860_cpu_device::insn_fiadd_sub, DEC_DECODED}, /* 0x4D, [p]fisub.{ss,dd} */ |
| 4230 | { 0, 0}, /* 0x4E */ |
| 4231 | { 0, 0}, /* 0x4F */ |
| 4232 | { &i860_cpu_device::insn_faddp, DEC_DECODED}, /* 0x50, [p]faddp */ |
| 4233 | { &i860_cpu_device::insn_faddz, DEC_DECODED}, /* 0x51, [p]faddz */ |
| 4234 | { 0, 0}, /* 0x52 */ |
| 4235 | { 0, 0}, /* 0x53 */ |
| 4236 | { 0, 0}, /* 0x54 */ |
| 4237 | { 0, 0}, /* 0x55 */ |
| 4238 | { 0, 0}, /* 0x56 */ |
| 4239 | { &i860_cpu_device::insn_fzchk, DEC_DECODED}, /* 0x57, [p]fzchkl */ |
| 4240 | { 0, 0}, /* 0x58 */ |
| 4241 | { 0, 0}, /* 0x59 */ |
| 4242 | { &i860_cpu_device::insn_form, DEC_DECODED}, /* 0x5A, [p]form.dd */ |
| 4243 | { 0, 0}, /* 0x5B */ |
| 4244 | { 0, 0}, /* 0x5C */ |
| 4245 | { 0, 0}, /* 0x5D */ |
| 4246 | { 0, 0}, /* 0x5E */ |
| 4247 | { &i860_cpu_device::insn_fzchk, DEC_DECODED}, /* 0x5F, [p]fzchks */ |
| 4248 | { 0, 0}, /* 0x60 */ |
| 4249 | { 0, 0}, /* 0x61 */ |
| 4250 | { 0, 0}, /* 0x62 */ |
| 4251 | { 0, 0}, /* 0x63 */ |
| 4252 | { 0, 0}, /* 0x64 */ |
| 4253 | { 0, 0}, /* 0x65 */ |
| 4254 | { 0, 0}, /* 0x66 */ |
| 4255 | { 0, 0}, /* 0x67 */ |
| 4256 | { 0, 0}, /* 0x68 */ |
| 4257 | { 0, 0}, /* 0x69 */ |
| 4258 | { 0, 0}, /* 0x6A */ |
| 4259 | { 0, 0}, /* 0x6B */ |
| 4260 | { 0, 0}, /* 0x6C */ |
| 4261 | { 0, 0}, /* 0x6D */ |
| 4262 | { 0, 0}, /* 0x6E */ |
| 4263 | { 0, 0}, /* 0x6F */ |
| 4264 | { 0, 0}, /* 0x70 */ |
| 4265 | { 0, 0}, /* 0x71 */ |
| 4266 | { 0, 0}, /* 0x72 */ |
| 4267 | { 0, 0}, /* 0x73 */ |
| 4268 | { 0, 0}, /* 0x74 */ |
| 4269 | { 0, 0}, /* 0x75 */ |
| 4270 | { 0, 0}, /* 0x76 */ |
| 4271 | { 0, 0}, /* 0x77 */ |
| 4272 | { 0, 0}, /* 0x78 */ |
| 4273 | { 0, 0}, /* 0x79 */ |
| 4274 | { 0, 0}, /* 0x7A */ |
| 4275 | { 0, 0}, /* 0x7B */ |
| 4276 | { 0, 0}, /* 0x7C */ |
| 4277 | { 0, 0}, /* 0x7D */ |
| 4278 | { 0, 0}, /* 0x7E */ |
| 4279 | { 0, 0}, /* 0x7F */ |
| 4280 | }; |
| 4281 | |
| 4282 | |
| 4283 | /* |
| 4284 | * Main decoder driver. |
| 4285 | * insn = instruction at the current PC to execute. |
| 4286 | * non_shadow = This insn is not in the shadow of a delayed branch). |
| 4287 | */ |
| 4288 | void i860_cpu_device::decode_exec (UINT32 insn, UINT32 non_shadow) |
| 4289 | { |
| 4290 | int upper_6bits = (insn >> 26) & 0x3f; |
| 4291 | char flags = 0; |
| 4292 | int unrecognized = 1; |
| 4293 | |
| 4294 | if (m_exiting_ifetch) |
| 4295 | return; |
| 4296 | |
| 4297 | if ((upper_6bits == 0x12 || upper_6bits == 0x2c) && insn & 0x0200) |
| 4298 | logerror("D-bit seen.\n"); |
| 4299 | if (GET_EPSR_BE ()) |
| 4300 | logerror("BE-bit high.\n"); |
| 4301 | if (GET_DIRBASE_CS8 ()) |
| 4302 | logerror("CS8-bit high.\n"); |
| 4303 | |
| 4304 | flags = decode_tbl[upper_6bits].flags; |
| 4305 | if (flags & DEC_DECODED) |
| 4306 | { |
| 4307 | (this->*decode_tbl[upper_6bits].insn_exec)(insn); |
| 4308 | unrecognized = 0; |
| 4309 | } |
| 4310 | else if (flags & DEC_MORE) |
| 4311 | { |
| 4312 | if (upper_6bits == 0x12) |
| 4313 | { |
| 4314 | /* FP instruction format handled here. */ |
| 4315 | char fp_flags = fp_decode_tbl[insn & 0x7f].flags; |
| 4316 | if (fp_flags & DEC_DECODED) |
| 4317 | { |
| 4318 | (this->*fp_decode_tbl[insn & 0x7f].insn_exec)(insn); |
| 4319 | unrecognized = 0; |
| 4320 | } |
| 4321 | } |
| 4322 | else if (upper_6bits == 0x13) |
| 4323 | { |
| 4324 | /* Core escape instruction format handled here. */ |
| 4325 | char esc_flags = core_esc_decode_tbl[insn & 0x3].flags; |
| 4326 | if (esc_flags & DEC_DECODED) |
| 4327 | { |
| 4328 | (this->*core_esc_decode_tbl[insn & 0x3].insn_exec)(insn); |
| 4329 | unrecognized = 0; |
| 4330 | } |
| 4331 | } |
| 4332 | } |
| 4333 | |
| 4334 | if (unrecognized) |
| 4335 | unrecog_opcode (m_pc, insn); |
| 4336 | |
| 4337 | /* For now, just treat every instruction as taking the same number of |
| 4338 | clocks-- a major oversimplification. */ |
| 4339 | m_icount -= 9; |
| 4340 | } |
| 4341 | |
| 4342 | |
| 4343 | /* Set-up all the default power-on/reset values. */ |
| 4344 | void i860_cpu_device::reset_i860 () |
| 4345 | { |
| 4346 | int i; |
| 4347 | /* On power-up/reset, i860 has values: |
| 4348 | PC = 0xffffff00. |
| 4349 | Integer registers: r0 = 0, others = undefined. |
| 4350 | FP registers: f0:f1 = 0, others undefined. |
| 4351 | psr: U = IM = BR = BW = 0; others = undefined. |
| 4352 | epsr: IL = WP = PBM = BE = 0; processor type, stepping, and |
| 4353 | DCS are proper and read-only; others = undefined. |
| 4354 | db: undefined. |
| 4355 | dirbase: DPS, BL, ATE = 0 |
| 4356 | fir, fsr, KR, KI, MERGE: undefined. (what about T?) |
| 4357 | |
| 4358 | I$: flushed. |
| 4359 | D$: undefined (all modified bits = 0). |
| 4360 | TLB: flushed. |
| 4361 | |
| 4362 | Note that any undefined values are set to 0x55aa55aa patterns to |
| 4363 | try to detect defective i860 software. */ |
| 4364 | |
| 4365 | /* PC is at trap address after reset. */ |
| 4366 | m_pc = 0xffffff00; |
| 4367 | |
| 4368 | /* Set grs and frs to undefined/nonsense values, except r0. */ |
| 4369 | for (i = 0; i < 32; i++) |
| 4370 | { |
| 4371 | set_iregval (i, 0x55aa55aa); |
| 4372 | set_fregval_s (i, 0.0); |
| 4373 | } |
| 4374 | set_iregval (0, 0); |
| 4375 | set_fregval_s (0, 0.0); |
| 4376 | set_fregval_s (1, 0.0); |
| 4377 | |
| 4378 | /* Set whole psr to 0. This sets the proper bits to 0 as specified |
| 4379 | above, and zeroes the undefined bits. */ |
| 4380 | m_cregs[CR_PSR] = 0; |
| 4381 | |
| 4382 | /* Set most of the epsr bits to 0 (as specified above), leaving |
| 4383 | undefined as zero as well. Then properly set processor type, |
| 4384 | step, and DCS. Type = EPSR[7..0], step = EPSR[12..8], |
| 4385 | DCS = EPSR[21..18] (2^[12+dcs] = cache size). |
| 4386 | We'll pretend to be stepping D0, since it has the fewest bugs |
| 4387 | (and I don't want to emulate the many defects in the earlier |
| 4388 | steppings). |
| 4389 | Proc type: 1 = XR, 2 = XP (XR has 8KB data cache -> DCS = 1). |
| 4390 | Steppings (XR): 3,4,5,6,7 = (B2, C0, B3, C1, D0 respectively). |
| 4391 | Steppings (XP): 0, 2, 3, 4 = (A0, B0, B1, B2) (any others?). */ |
| 4392 | m_cregs[CR_EPSR] = 0x00040701; |
| 4393 | |
| 4394 | /* Set DPS, BL, ATE = 0 and the undefined parts also to 0. */ |
| 4395 | m_cregs[CR_DIRBASE] = 0x00000000; |
| 4396 | |
| 4397 | /* Set fir, fsr, KR, KI, MERGE, T to undefined. */ |
| 4398 | m_cregs[CR_FIR] = 0xaa55aa55; |
| 4399 | m_cregs[CR_FSR] = /* 0xaa55aa55; */ 0; |
| 4400 | m_KR.d = 0.0; |
| 4401 | m_KI.d = 0.0; |
| 4402 | m_T.d = 0.0; |
| 4403 | m_merge = 0xaa55aa55; |
| 4404 | |
| 4405 | m_fir_gets_trap_addr = 0; |
| 4406 | } |
| 4407 | |
| 4408 | |
| 4409 | |
| 4410 | |
| 4411 | /*=================================================================*/ |
| 4412 | /* MAME execution hook for i860 emulator. */ |
| 4413 | /*=================================================================*/ |
| 4414 | |
| 4415 | void i860_cpu_device::execute_run() |
| 4416 | { |
| 4417 | /* Check if the data bus is held by another device, and bail if so. |
| 4418 | Also check for reset. */ |
| 4419 | if (m_pin_reset) |
| 4420 | reset_i860 (); |
| 4421 | if (m_pin_bus_hold) |
| 4422 | { |
| 4423 | m_icount = 0; |
| 4424 | return; |
| 4425 | } |
| 4426 | |
| 4427 | m_exiting_readmem = 0; |
| 4428 | m_exiting_ifetch = 0; |
| 4429 | |
| 4430 | /* Decode and execute loop. */ |
| 4431 | while (m_icount > 0) |
| 4432 | { |
| 4433 | UINT32 savepc = m_pc; |
| 4434 | m_pc_updated = 0; |
| 4435 | m_pending_trap = 0; |
| 4436 | |
| 4437 | #if 1 /* Delete me soon, for debugging VC inter-processor synch. */ |
| 4438 | if (m_pc == 0xfffc0370 || |
| 4439 | m_pc == 0xfffc03a4) |
| 4440 | { |
| 4441 | fprintf(stderr, "(%s) 0x%08x: snag 0x20000000\n", tag(), m_pc); |
| 4442 | m_single_stepping = 0; |
| 4443 | } |
| 4444 | else if (m_pc == 0xfffc0384 || |
| 4445 | m_pc == 0xfffc03b8) |
| 4446 | { |
| 4447 | fprintf(stderr, "(%s) 0x%08x: passed 0x20000000\n", tag(), m_pc); |
| 4448 | m_single_stepping = 0; |
| 4449 | } |
| 4450 | #endif |
| 4451 | |
| 4452 | savepc = m_pc; |
| 4453 | debugger_instruction_hook(this, m_pc); |
| 4454 | decode_exec (ifetch (m_pc), 1); |
| 4455 | |
| 4456 | m_exiting_ifetch = 0; |
| 4457 | m_exiting_readmem = 0; |
| 4458 | |
| 4459 | if (m_pending_trap) |
| 4460 | { |
| 4461 | /* If we need to trap, change PC to trap address. |
| 4462 | Also set supervisor mode, copy U and IM to their |
| 4463 | previous versions, clear IM. */ |
| 4464 | if ((m_pending_trap & TRAP_WAS_EXTERNAL) || (GET_EPSR_INT () && GET_PSR_IN ())) |
| 4465 | { |
| 4466 | if (!m_pc_updated) |
| 4467 | m_cregs[CR_FIR] = savepc + 4; |
| 4468 | else |
| 4469 | m_cregs[CR_FIR] = m_pc; |
| 4470 | } |
| 4471 | else if (m_pending_trap & TRAP_IN_DELAY_SLOT) |
| 4472 | { |
| 4473 | m_cregs[CR_FIR] = savepc + 4; |
| 4474 | } |
| 4475 | else |
| 4476 | m_cregs[CR_FIR] = savepc; |
| 4477 | |
| 4478 | m_fir_gets_trap_addr = 1; |
| 4479 | SET_PSR_PU (GET_PSR_U ()); |
| 4480 | SET_PSR_PIM (GET_PSR_IM ()); |
| 4481 | SET_PSR_U (0); |
| 4482 | SET_PSR_IM (0); |
| 4483 | SET_PSR_DIM (0); |
| 4484 | SET_PSR_DS (0); |
| 4485 | m_pc = 0xffffff00; |
| 4486 | m_pending_trap = 0; |
| 4487 | } |
| 4488 | else if (!m_pc_updated) |
| 4489 | { |
| 4490 | /* If the PC wasn't updated by a control flow instruction, just |
| 4491 | bump to next sequential instruction. */ |
| 4492 | m_pc += 4; |
| 4493 | } |
| 4494 | |
| 4495 | /*if (m_single_stepping) |
| 4496 | debugger (cpustate); */ |
| 4497 | } |
| 4498 | } |
| 4499 | /*=================================================================*/ |
| 4500 | |
| 4501 | |
| 4502 | |
| 4503 | |
| 4504 | #if 0 |
| 4505 | /*=================================================================*/ |
| 4506 | /* Internal debugger-related stuff. */ |
| 4507 | |
| 4508 | extern unsigned disasm_i860 (char *buf, unsigned int pc, unsigned int insn); |
| 4509 | |
| 4510 | |
| 4511 | /* Disassemble `len' instructions starting at `addr'. */ |
| 4512 | void i860_cpu_device::disasm (UINT32 addr, int len) |
| 4513 | { |
| 4514 | UINT32 insn; |
| 4515 | int j; |
| 4516 | for (j = 0; j < len; j++) |
| 4517 | { |
| 4518 | char buf[256]; |
| 4519 | UINT32 phys_addr = addr; |
| 4520 | if (GET_DIRBASE_ATE ()) |
| 4521 | phys_addr = get_address_translation (addr, 1 /* is_dataref */, 0 /* is_write */); |
| 4522 | |
| 4523 | /* Note that we print the incoming (possibly virtual) address as the |
| 4524 | PC rather than the translated address. */ |
| 4525 | fprintf (stderr, " (%s) 0x%08x: ", m_device->tag(), addr); |
| 4526 | insn = m_program->read_dword(phys_addr); |
| 4527 | #ifdef HOST_MSB |
| 4528 | BYTE_REV32 (insn); |
| 4529 | #endif /* HOST_MSB. */ |
| 4530 | disasm_i860 (buf, addr, insn); fprintf (stderr, "%s", buf); |
| 4531 | fprintf (stderr, "\n"); |
| 4532 | addr += 4; |
| 4533 | #if 1 |
| 4534 | if (m_single_stepping == 1 && has_delay_slot (insn)) |
| 4535 | len += 1; |
| 4536 | #endif |
| 4537 | } |
| 4538 | } |
| 4539 | |
| 4540 | |
| 4541 | /* Dump `len' bytes starting at `addr'. */ |
| 4542 | void i860_cpu_device::dbg_db (UINT32 addr, int len) |
| 4543 | { |
| 4544 | UINT8 b[16]; |
| 4545 | int i; |
| 4546 | /* This will always dump a multiple of 16 bytes, even if 'len' isn't. */ |
| 4547 | while (len > 0) |
| 4548 | { |
| 4549 | /* Note that we print the incoming (possibly virtual) address |
| 4550 | rather than the translated address. */ |
| 4551 | fprintf (stderr, "0x%08x: ", addr); |
| 4552 | for (i = 0; i < 16; i++) |
| 4553 | { |
| 4554 | UINT32 phys_addr = addr; |
| 4555 | if (GET_DIRBASE_ATE ()) |
| 4556 | phys_addr = get_address_translation (addr, 1 /* is_dataref */, 0 /* is_write */); |
| 4557 | |
| 4558 | b[i] = m_program->read_byte(phys_addr); |
| 4559 | fprintf (stderr, "%02x ", b[i]); |
| 4560 | addr++; |
| 4561 | } |
| 4562 | fprintf (stderr, "| "); |
| 4563 | for (i = 0; i < 16; i++) |
| 4564 | { |
| 4565 | if (isprint (b[i])) |
| 4566 | fprintf (stderr, "%c", b[i]); |
| 4567 | else |
| 4568 | fprintf (stderr, "."); |
| 4569 | } |
| 4570 | fprintf (stderr, "\n"); |
| 4571 | len -= 16; |
| 4572 | } |
| 4573 | } |
| 4574 | |
| 4575 | |
| 4576 | /* A simple internal debugger. */ |
| 4577 | void debugger (i860s *cpustate) |
| 4578 | { |
| 4579 | char buf[256]; |
| 4580 | UINT32 curr_disasm = m_pc; |
| 4581 | UINT32 curr_dumpdb = 0; |
| 4582 | int c = 0; |
| 4583 | |
| 4584 | if (m_single_stepping > 1 && m_single_stepping != m_pc) |
| 4585 | return; |
| 4586 | |
| 4587 | buf[0] = 0; |
| 4588 | |
| 4589 | /* Always disassemble the upcoming instruction when single-stepping. */ |
| 4590 | if (m_single_stepping) |
| 4591 | { |
| 4592 | disasm (m_pc, 1); |
| 4593 | if (has_delay_slot (2)) |
| 4594 | disasm (m_pc + 4, 1); |
| 4595 | } |
| 4596 | else |
| 4597 | fprintf (stderr, "\nEmulator: internal debugger started (? for help).\n"); |
| 4598 | |
| 4599 | fflush (stdin); |
| 4600 | |
| 4601 | m_single_stepping = 0; |
| 4602 | while (!m_single_stepping) |
| 4603 | { |
| 4604 | fprintf (stderr, "- "); |
| 4605 | #if 0 /* Doesn't work on MacOSX BSD flavor. */ |
| 4606 | fscanf (stdin, "%s", buf); |
| 4607 | #else |
| 4608 | while (1) |
| 4609 | { |
| 4610 | char it = 0; |
| 4611 | if (read(STDIN_FILENO, &it, 1) == 1) |
| 4612 | { |
| 4613 | if (it == '\n') |
| 4614 | { |
| 4615 | buf[c] = 0; |
| 4616 | c = 0; |
| 4617 | break; |
| 4618 | } |
| 4619 | buf[c++] = it; |
| 4620 | } |
| 4621 | } |
| 4622 | #endif |
| 4623 | if (buf[0] == 'g') |
| 4624 | { |
| 4625 | if (buf[1] == '0') |
| 4626 | sscanf (buf + 1, "%x", &m_single_stepping); |
| 4627 | else |
| 4628 | break; |
| 4629 | buf[1] = 0; |
| 4630 | fprintf (stderr, "go until pc = 0x%08x.\n", |
| 4631 | m_single_stepping); |
| 4632 | m_single_stepping = 0; /* HACK */ |
| 4633 | } |
| 4634 | else if (buf[0] == 'r') |
| 4635 | dump_state (cpustate); |
| 4636 | else if (buf[0] == 'u') |
| 4637 | { |
| 4638 | if (buf[1] == '0') |
| 4639 | sscanf (buf + 1, "%x", &curr_disasm); |
| 4640 | disasm (curr_disasm, 10); |
| 4641 | curr_disasm += 10 * 4; |
| 4642 | buf[1] = 0; |
| 4643 | } |
| 4644 | else if (buf[0] == 'p') |
| 4645 | { |
| 4646 | if (buf[1] >= '0' && buf[1] <= '4') |
| 4647 | dump_pipe (buf[1] - 0x30); |
| 4648 | buf[1] = 0; |
| 4649 | } |
| 4650 | else if (buf[0] == 's') |
| 4651 | m_single_stepping = 1; |
| 4652 | else if (buf[0] == 'l') |
| 4653 | ; //m_pc = elf_load(buf + 1); |
| 4654 | else if (buf[0] == 'd' && buf[1] == 'b') |
| 4655 | { |
| 4656 | if (buf[2] == '0') |
| 4657 | sscanf (buf + 2, "%x", &curr_dumpdb); |
| 4658 | dbg_db (curr_dumpdb, 32); |
| 4659 | curr_dumpdb += 32; |
| 4660 | } |
| 4661 | else if (buf[0] == 'x' && buf[1] == '0') |
| 4662 | { |
| 4663 | UINT32 v; |
| 4664 | sscanf (buf + 1, "%x", &v); |
| 4665 | if (GET_DIRBASE_ATE ()) |
| 4666 | fprintf (stderr, "vma 0x%08x ==> phys 0x%08x\n", v, |
| 4667 | get_address_translation (v, 1, 0)); |
| 4668 | else |
| 4669 | fprintf (stderr, "not in virtual address mode.\n"); |
| 4670 | } |
| 4671 | else if (buf[0] == 'B') |
| 4672 | { |
| 4673 | ;//m_pc = elf_load("bins/bsd"); |
| 4674 | break; |
| 4675 | } |
| 4676 | else if (buf[0] == '?') |
| 4677 | { |
| 4678 | fprintf (stderr, " db: dump bytes (db[0xaddress])\n r: dump registers\n s: single-step\n g: go back to emulator (g[0xaddress])\n u: disassemble (u[0xaddress])\n p: dump pipelines (p{0-4} for all, add, mul, load, graphics)\n l: load an ELF binary (lpath)\n x: give virt->phys translation (x{0xaddress})\n"); |
| 4679 | } |
| 4680 | else |
| 4681 | fprintf (stderr, "Bad command '%s'.\n", buf); |
| 4682 | } |
| 4683 | |
| 4684 | /* Less noise when single-stepping. */ |
| 4685 | if (m_single_stepping != 1) |
| 4686 | fprintf (stderr, "Debugger done, continuing emulation.\n"); |
| 4687 | } |
| 4688 | |
| 4689 | #endif |
trunk/src/emu/cpu/i386/i386ops.c
| r28738 | r28739 | |
| 1 | | UINT8 i386_device::i386_shift_rotate8(UINT8 modrm, UINT32 value, UINT8 shift) |
| 2 | | { |
| 3 | | UINT32 src = value & 0xff; |
| 4 | | UINT8 dst = value; |
| 5 | | |
| 6 | | if( shift == 0 ) { |
| 7 | | CYCLES_RM(modrm, 3, 7); |
| 8 | | } else if( shift == 1 ) { |
| 9 | | switch( (modrm >> 3) & 0x7 ) |
| 10 | | { |
| 11 | | case 0: /* ROL rm8, 1 */ |
| 12 | | m_CF = (src & 0x80) ? 1 : 0; |
| 13 | | dst = (src << 1) + m_CF; |
| 14 | | m_OF = ((src ^ dst) & 0x80) ? 1 : 0; |
| 15 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 16 | | break; |
| 17 | | case 1: /* ROR rm8, 1 */ |
| 18 | | m_CF = (src & 0x1) ? 1 : 0; |
| 19 | | dst = (m_CF << 7) | (src >> 1); |
| 20 | | m_OF = ((src ^ dst) & 0x80) ? 1 : 0; |
| 21 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 22 | | break; |
| 23 | | case 2: /* RCL rm8, 1 */ |
| 24 | | dst = (src << 1) + m_CF; |
| 25 | | m_CF = (src & 0x80) ? 1 : 0; |
| 26 | | m_OF = ((src ^ dst) & 0x80) ? 1 : 0; |
| 27 | | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 28 | | break; |
| 29 | | case 3: /* RCR rm8, 1 */ |
| 30 | | dst = (m_CF << 7) | (src >> 1); |
| 31 | | m_CF = src & 0x1; |
| 32 | | m_OF = ((src ^ dst) & 0x80) ? 1 : 0; |
| 33 | | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 34 | | break; |
| 35 | | case 4: /* SHL/SAL rm8, 1 */ |
| 36 | | case 6: |
| 37 | | dst = src << 1; |
| 38 | | m_CF = (src & 0x80) ? 1 : 0; |
| 39 | | m_OF = (((m_CF << 7) ^ dst) & 0x80) ? 1 : 0; |
| 40 | | SetSZPF8(dst); |
| 41 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 42 | | break; |
| 43 | | case 5: /* SHR rm8, 1 */ |
| 44 | | dst = src >> 1; |
| 45 | | m_CF = src & 0x1; |
| 46 | | m_OF = (dst & 0x80) ? 1 : 0; |
| 47 | | SetSZPF8(dst); |
| 48 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 49 | | break; |
| 50 | | case 7: /* SAR rm8, 1 */ |
| 51 | | dst = (INT8)(src) >> 1; |
| 52 | | m_CF = src & 0x1; |
| 53 | | m_OF = 0; |
| 54 | | SetSZPF8(dst); |
| 55 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 56 | | break; |
| 57 | | } |
| 58 | | |
| 59 | | } else { |
| 60 | | switch( (modrm >> 3) & 0x7 ) |
| 61 | | { |
| 62 | | case 0: /* ROL rm8, i8 */ |
| 63 | | if(!(shift & 7)) |
| 64 | | { |
| 65 | | if(shift & 0x18) |
| 66 | | { |
| 67 | | m_CF = src & 1; |
| 68 | | m_OF = (src & 1) ^ ((src >> 7) & 1); |
| 69 | | } |
| 70 | | break; |
| 71 | | } |
| 72 | | shift &= 7; |
| 73 | | dst = ((src & ((UINT8)0xff >> shift)) << shift) | |
| 74 | | ((src & ((UINT8)0xff << (8-shift))) >> (8-shift)); |
| 75 | | m_CF = dst & 0x1; |
| 76 | | m_OF = (dst & 1) ^ (dst >> 7); |
| 77 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 78 | | break; |
| 79 | | case 1: /* ROR rm8, i8 */ |
| 80 | | if(!(shift & 7)) |
| 81 | | { |
| 82 | | if(shift & 0x18) |
| 83 | | { |
| 84 | | m_CF = (src >> 7) & 1; |
| 85 | | m_OF = ((src >> 7) & 1) ^ ((src >> 6) & 1); |
| 86 | | } |
| 87 | | break; |
| 88 | | } |
| 89 | | shift &= 7; |
| 90 | | dst = ((src & ((UINT8)0xff << shift)) >> shift) | |
| 91 | | ((src & ((UINT8)0xff >> (8-shift))) << (8-shift)); |
| 92 | | m_CF = (dst >> 7) & 1; |
| 93 | | m_OF = ((dst >> 7) ^ (dst >> 6)) & 1; |
| 94 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 95 | | break; |
| 96 | | case 2: /* RCL rm8, i8 */ |
| 97 | | shift %= 9; |
| 98 | | dst = ((src & ((UINT8)0xff >> shift)) << shift) | |
| 99 | | ((src & ((UINT8)0xff << (9-shift))) >> (9-shift)) | |
| 100 | | (m_CF << (shift-1)); |
| 101 | | if(shift) m_CF = (src >> (8-shift)) & 0x1; |
| 102 | | m_OF = m_CF ^ ((dst >> 7) & 1); |
| 103 | | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 104 | | break; |
| 105 | | case 3: /* RCR rm8, i8 */ |
| 106 | | shift %= 9; |
| 107 | | dst = ((src & ((UINT8)0xff << shift)) >> shift) | |
| 108 | | ((src & ((UINT8)0xff >> (8-shift))) << (9-shift)) | |
| 109 | | (m_CF << (8-shift)); |
| 110 | | if(shift) m_CF = (src >> (shift-1)) & 0x1; |
| 111 | | m_OF = ((dst >> 7) ^ (dst >> 6)) & 1; |
| 112 | | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 113 | | break; |
| 114 | | case 4: /* SHL/SAL rm8, i8 */ |
| 115 | | case 6: |
| 116 | | shift &= 31; |
| 117 | | dst = src << shift; |
| 118 | | m_CF = (shift <= 8) && ((src >> (8 - shift)) & 1); |
| 119 | | SetSZPF8(dst); |
| 120 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 121 | | break; |
| 122 | | case 5: /* SHR rm8, i8 */ |
| 123 | | shift &= 31; |
| 124 | | dst = src >> shift; |
| 125 | | m_CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 126 | | SetSZPF8(dst); |
| 127 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 128 | | break; |
| 129 | | case 7: /* SAR rm8, i8 */ |
| 130 | | shift &= 31; |
| 131 | | dst = (INT8)src >> shift; |
| 132 | | m_CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 133 | | SetSZPF8(dst); |
| 134 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 135 | | break; |
| 136 | | } |
| 137 | | } |
| 138 | | |
| 139 | | return dst; |
| 140 | | } |
| 141 | | |
| 142 | | |
| 143 | | |
| 144 | | void i386_device::i386_adc_rm8_r8() // Opcode 0x10 |
| 145 | | { |
| 146 | | UINT8 src, dst; |
| 147 | | UINT8 modrm = FETCH(); |
| 148 | | if( modrm >= 0xc0 ) { |
| 149 | | src = LOAD_REG8(modrm); |
| 150 | | dst = LOAD_RM8(modrm); |
| 151 | | dst = ADC8(dst, src, m_CF); |
| 152 | | STORE_RM8(modrm, dst); |
| 153 | | CYCLES(CYCLES_ALU_REG_REG); |
| 154 | | } else { |
| 155 | | UINT32 ea = GetEA(modrm,1); |
| 156 | | src = LOAD_REG8(modrm); |
| 157 | | dst = READ8(ea); |
| 158 | | dst = ADC8(dst, src, m_CF); |
| 159 | | WRITE8(ea, dst); |
| 160 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 161 | | } |
| 162 | | } |
| 163 | | |
| 164 | | void i386_device::i386_adc_r8_rm8() // Opcode 0x12 |
| 165 | | { |
| 166 | | UINT8 src, dst; |
| 167 | | UINT8 modrm = FETCH(); |
| 168 | | if( modrm >= 0xc0 ) { |
| 169 | | src = LOAD_RM8(modrm); |
| 170 | | dst = LOAD_REG8(modrm); |
| 171 | | dst = ADC8(dst, src, m_CF); |
| 172 | | STORE_REG8(modrm, dst); |
| 173 | | CYCLES(CYCLES_ALU_REG_REG); |
| 174 | | } else { |
| 175 | | UINT32 ea = GetEA(modrm,0); |
| 176 | | src = READ8(ea); |
| 177 | | dst = LOAD_REG8(modrm); |
| 178 | | dst = ADC8(dst, src, m_CF); |
| 179 | | STORE_REG8(modrm, dst); |
| 180 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 181 | | } |
| 182 | | } |
| 183 | | |
| 184 | | void i386_device::i386_adc_al_i8() // Opcode 0x14 |
| 185 | | { |
| 186 | | UINT8 src, dst; |
| 187 | | src = FETCH(); |
| 188 | | dst = REG8(AL); |
| 189 | | dst = ADC8(dst, src, m_CF); |
| 190 | | REG8(AL) = dst; |
| 191 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 192 | | } |
| 193 | | |
| 194 | | void i386_device::i386_add_rm8_r8() // Opcode 0x00 |
| 195 | | { |
| 196 | | UINT8 src, dst; |
| 197 | | UINT8 modrm = FETCH(); |
| 198 | | if( modrm >= 0xc0 ) { |
| 199 | | src = LOAD_REG8(modrm); |
| 200 | | dst = LOAD_RM8(modrm); |
| 201 | | dst = ADD8(dst, src); |
| 202 | | STORE_RM8(modrm, dst); |
| 203 | | CYCLES(CYCLES_ALU_REG_REG); |
| 204 | | } else { |
| 205 | | UINT32 ea = GetEA(modrm,1); |
| 206 | | src = LOAD_REG8(modrm); |
| 207 | | dst = READ8(ea); |
| 208 | | dst = ADD8(dst, src); |
| 209 | | WRITE8(ea, dst); |
| 210 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 211 | | } |
| 212 | | } |
| 213 | | |
| 214 | | void i386_device::i386_add_r8_rm8() // Opcode 0x02 |
| 215 | | { |
| 216 | | UINT8 src, dst; |
| 217 | | UINT8 modrm = FETCH(); |
| 218 | | if( modrm >= 0xc0 ) { |
| 219 | | src = LOAD_RM8(modrm); |
| 220 | | dst = LOAD_REG8(modrm); |
| 221 | | dst = ADD8(dst, src); |
| 222 | | STORE_REG8(modrm, dst); |
| 223 | | CYCLES(CYCLES_ALU_REG_REG); |
| 224 | | } else { |
| 225 | | UINT32 ea = GetEA(modrm,0); |
| 226 | | src = READ8(ea); |
| 227 | | dst = LOAD_REG8(modrm); |
| 228 | | dst = ADD8(dst, src); |
| 229 | | STORE_REG8(modrm, dst); |
| 230 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 231 | | } |
| 232 | | } |
| 233 | | |
| 234 | | void i386_device::i386_add_al_i8() // Opcode 0x04 |
| 235 | | { |
| 236 | | UINT8 src, dst; |
| 237 | | src = FETCH(); |
| 238 | | dst = REG8(AL); |
| 239 | | dst = ADD8(dst, src); |
| 240 | | REG8(AL) = dst; |
| 241 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 242 | | } |
| 243 | | |
| 244 | | void i386_device::i386_and_rm8_r8() // Opcode 0x20 |
| 245 | | { |
| 246 | | UINT8 src, dst; |
| 247 | | UINT8 modrm = FETCH(); |
| 248 | | if( modrm >= 0xc0 ) { |
| 249 | | src = LOAD_REG8(modrm); |
| 250 | | dst = LOAD_RM8(modrm); |
| 251 | | dst = AND8(dst, src); |
| 252 | | STORE_RM8(modrm, dst); |
| 253 | | CYCLES(CYCLES_ALU_REG_REG); |
| 254 | | } else { |
| 255 | | UINT32 ea = GetEA(modrm,1); |
| 256 | | src = LOAD_REG8(modrm); |
| 257 | | dst = READ8(ea); |
| 258 | | dst = AND8(dst, src); |
| 259 | | WRITE8(ea, dst); |
| 260 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 261 | | } |
| 262 | | } |
| 263 | | |
| 264 | | void i386_device::i386_and_r8_rm8() // Opcode 0x22 |
| 265 | | { |
| 266 | | UINT8 src, dst; |
| 267 | | UINT8 modrm = FETCH(); |
| 268 | | if( modrm >= 0xc0 ) { |
| 269 | | src = LOAD_RM8(modrm); |
| 270 | | dst = LOAD_REG8(modrm); |
| 271 | | dst = AND8(dst, src); |
| 272 | | STORE_REG8(modrm, dst); |
| 273 | | CYCLES(CYCLES_ALU_REG_REG); |
| 274 | | } else { |
| 275 | | UINT32 ea = GetEA(modrm,0); |
| 276 | | src = READ8(ea); |
| 277 | | dst = LOAD_REG8(modrm); |
| 278 | | dst = AND8(dst, src); |
| 279 | | STORE_REG8(modrm, dst); |
| 280 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 281 | | } |
| 282 | | } |
| 283 | | |
| 284 | | void i386_device::i386_and_al_i8() // Opcode 0x24 |
| 285 | | { |
| 286 | | UINT8 src, dst; |
| 287 | | src = FETCH(); |
| 288 | | dst = REG8(AL); |
| 289 | | dst = AND8(dst, src); |
| 290 | | REG8(AL) = dst; |
| 291 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 292 | | } |
| 293 | | |
| 294 | | void i386_device::i386_clc() // Opcode 0xf8 |
| 295 | | { |
| 296 | | m_CF = 0; |
| 297 | | CYCLES(CYCLES_CLC); |
| 298 | | } |
| 299 | | |
| 300 | | void i386_device::i386_cld() // Opcode 0xfc |
| 301 | | { |
| 302 | | m_DF = 0; |
| 303 | | CYCLES(CYCLES_CLD); |
| 304 | | } |
| 305 | | |
| 306 | | void i386_device::i386_cli() // Opcode 0xfa |
| 307 | | { |
| 308 | | if(PROTECTED_MODE) |
| 309 | | { |
| 310 | | UINT8 IOPL = m_IOP1 | (m_IOP2 << 1); |
| 311 | | if(m_CPL > IOPL) |
| 312 | | FAULT(FAULT_GP,0); |
| 313 | | } |
| 314 | | m_IF = 0; |
| 315 | | CYCLES(CYCLES_CLI); |
| 316 | | } |
| 317 | | |
| 318 | | void i386_device::i386_cmc() // Opcode 0xf5 |
| 319 | | { |
| 320 | | m_CF ^= 1; |
| 321 | | CYCLES(CYCLES_CMC); |
| 322 | | } |
| 323 | | |
| 324 | | void i386_device::i386_cmp_rm8_r8() // Opcode 0x38 |
| 325 | | { |
| 326 | | UINT8 src, dst; |
| 327 | | UINT8 modrm = FETCH(); |
| 328 | | if( modrm >= 0xc0 ) { |
| 329 | | src = LOAD_REG8(modrm); |
| 330 | | dst = LOAD_RM8(modrm); |
| 331 | | SUB8(dst, src); |
| 332 | | CYCLES(CYCLES_CMP_REG_REG); |
| 333 | | } else { |
| 334 | | UINT32 ea = GetEA(modrm,0); |
| 335 | | src = LOAD_REG8(modrm); |
| 336 | | dst = READ8(ea); |
| 337 | | SUB8(dst, src); |
| 338 | | CYCLES(CYCLES_CMP_REG_MEM); |
| 339 | | } |
| 340 | | } |
| 341 | | |
| 342 | | void i386_device::i386_cmp_r8_rm8() // Opcode 0x3a |
| 343 | | { |
| 344 | | UINT8 src, dst; |
| 345 | | UINT8 modrm = FETCH(); |
| 346 | | if( modrm >= 0xc0 ) { |
| 347 | | src = LOAD_RM8(modrm); |
| 348 | | dst = LOAD_REG8(modrm); |
| 349 | | SUB8(dst, src); |
| 350 | | CYCLES(CYCLES_CMP_REG_REG); |
| 351 | | } else { |
| 352 | | UINT32 ea = GetEA(modrm,0); |
| 353 | | src = READ8(ea); |
| 354 | | dst = LOAD_REG8(modrm); |
| 355 | | SUB8(dst, src); |
| 356 | | CYCLES(CYCLES_CMP_MEM_REG); |
| 357 | | } |
| 358 | | } |
| 359 | | |
| 360 | | void i386_device::i386_cmp_al_i8() // Opcode 0x3c |
| 361 | | { |
| 362 | | UINT8 src, dst; |
| 363 | | src = FETCH(); |
| 364 | | dst = REG8(AL); |
| 365 | | SUB8(dst, src); |
| 366 | | CYCLES(CYCLES_CMP_IMM_ACC); |
| 367 | | } |
| 368 | | |
| 369 | | void i386_device::i386_cmpsb() // Opcode 0xa6 |
| 370 | | { |
| 371 | | UINT32 eas, ead; |
| 372 | | UINT8 src, dst; |
| 373 | | if( m_segment_prefix ) { |
| 374 | | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 375 | | } else { |
| 376 | | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 377 | | } |
| 378 | | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 ); |
| 379 | | src = READ8(eas); |
| 380 | | dst = READ8(ead); |
| 381 | | SUB8(src, dst); |
| 382 | | BUMP_SI(1); |
| 383 | | BUMP_DI(1); |
| 384 | | CYCLES(CYCLES_CMPS); |
| 385 | | } |
| 386 | | |
| 387 | | void i386_device::i386_in_al_i8() // Opcode 0xe4 |
| 388 | | { |
| 389 | | UINT16 port = FETCH(); |
| 390 | | UINT8 data = READPORT8(port); |
| 391 | | REG8(AL) = data; |
| 392 | | CYCLES(CYCLES_IN_VAR); |
| 393 | | } |
| 394 | | |
| 395 | | void i386_device::i386_in_al_dx() // Opcode 0xec |
| 396 | | { |
| 397 | | UINT16 port = REG16(DX); |
| 398 | | UINT8 data = READPORT8(port); |
| 399 | | REG8(AL) = data; |
| 400 | | CYCLES(CYCLES_IN); |
| 401 | | } |
| 402 | | |
| 403 | | void i386_device::i386_ja_rel8() // Opcode 0x77 |
| 404 | | { |
| 405 | | INT8 disp = FETCH(); |
| 406 | | if( m_CF == 0 && m_ZF == 0 ) { |
| 407 | | NEAR_BRANCH(disp); |
| 408 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 409 | | } else { |
| 410 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 411 | | } |
| 412 | | } |
| 413 | | |
| 414 | | void i386_device::i386_jbe_rel8() // Opcode 0x76 |
| 415 | | { |
| 416 | | INT8 disp = FETCH(); |
| 417 | | if( m_CF != 0 || m_ZF != 0 ) { |
| 418 | | NEAR_BRANCH(disp); |
| 419 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 420 | | } else { |
| 421 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 422 | | } |
| 423 | | } |
| 424 | | |
| 425 | | void i386_device::i386_jc_rel8() // Opcode 0x72 |
| 426 | | { |
| 427 | | INT8 disp = FETCH(); |
| 428 | | if( m_CF != 0 ) { |
| 429 | | NEAR_BRANCH(disp); |
| 430 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 431 | | } else { |
| 432 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 433 | | } |
| 434 | | } |
| 435 | | |
| 436 | | void i386_device::i386_jg_rel8() // Opcode 0x7f |
| 437 | | { |
| 438 | | INT8 disp = FETCH(); |
| 439 | | if( m_ZF == 0 && (m_SF == m_OF) ) { |
| 440 | | NEAR_BRANCH(disp); |
| 441 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 442 | | } else { |
| 443 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 444 | | } |
| 445 | | } |
| 446 | | |
| 447 | | void i386_device::i386_jge_rel8() // Opcode 0x7d |
| 448 | | { |
| 449 | | INT8 disp = FETCH(); |
| 450 | | if(m_SF == m_OF) { |
| 451 | | NEAR_BRANCH(disp); |
| 452 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 453 | | } else { |
| 454 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 455 | | } |
| 456 | | } |
| 457 | | |
| 458 | | void i386_device::i386_jl_rel8() // Opcode 0x7c |
| 459 | | { |
| 460 | | INT8 disp = FETCH(); |
| 461 | | if( (m_SF != m_OF) ) { |
| 462 | | NEAR_BRANCH(disp); |
| 463 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 464 | | } else { |
| 465 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 466 | | } |
| 467 | | } |
| 468 | | |
| 469 | | void i386_device::i386_jle_rel8() // Opcode 0x7e |
| 470 | | { |
| 471 | | INT8 disp = FETCH(); |
| 472 | | if( m_ZF != 0 || (m_SF != m_OF) ) { |
| 473 | | NEAR_BRANCH(disp); |
| 474 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 475 | | } else { |
| 476 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 477 | | } |
| 478 | | } |
| 479 | | |
| 480 | | void i386_device::i386_jnc_rel8() // Opcode 0x73 |
| 481 | | { |
| 482 | | INT8 disp = FETCH(); |
| 483 | | if( m_CF == 0 ) { |
| 484 | | NEAR_BRANCH(disp); |
| 485 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 486 | | } else { |
| 487 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 488 | | } |
| 489 | | } |
| 490 | | |
| 491 | | void i386_device::i386_jno_rel8() // Opcode 0x71 |
| 492 | | { |
| 493 | | INT8 disp = FETCH(); |
| 494 | | if( m_OF == 0 ) { |
| 495 | | NEAR_BRANCH(disp); |
| 496 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 497 | | } else { |
| 498 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 499 | | } |
| 500 | | } |
| 501 | | |
| 502 | | void i386_device::i386_jnp_rel8() // Opcode 0x7b |
| 503 | | { |
| 504 | | INT8 disp = FETCH(); |
| 505 | | if( m_PF == 0 ) { |
| 506 | | NEAR_BRANCH(disp); |
| 507 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 508 | | } else { |
| 509 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 510 | | } |
| 511 | | } |
| 512 | | |
| 513 | | void i386_device::i386_jns_rel8() // Opcode 0x79 |
| 514 | | { |
| 515 | | INT8 disp = FETCH(); |
| 516 | | if( m_SF == 0 ) { |
| 517 | | NEAR_BRANCH(disp); |
| 518 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 519 | | } else { |
| 520 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 521 | | } |
| 522 | | } |
| 523 | | |
| 524 | | void i386_device::i386_jnz_rel8() // Opcode 0x75 |
| 525 | | { |
| 526 | | INT8 disp = FETCH(); |
| 527 | | if( m_ZF == 0 ) { |
| 528 | | NEAR_BRANCH(disp); |
| 529 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 530 | | } else { |
| 531 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 532 | | } |
| 533 | | } |
| 534 | | |
| 535 | | void i386_device::i386_jo_rel8() // Opcode 0x70 |
| 536 | | { |
| 537 | | INT8 disp = FETCH(); |
| 538 | | if( m_OF != 0 ) { |
| 539 | | NEAR_BRANCH(disp); |
| 540 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 541 | | } else { |
| 542 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 543 | | } |
| 544 | | } |
| 545 | | |
| 546 | | void i386_device::i386_jp_rel8() // Opcode 0x7a |
| 547 | | { |
| 548 | | INT8 disp = FETCH(); |
| 549 | | if( m_PF != 0 ) { |
| 550 | | NEAR_BRANCH(disp); |
| 551 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 552 | | } else { |
| 553 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 554 | | } |
| 555 | | } |
| 556 | | |
| 557 | | void i386_device::i386_js_rel8() // Opcode 0x78 |
| 558 | | { |
| 559 | | INT8 disp = FETCH(); |
| 560 | | if( m_SF != 0 ) { |
| 561 | | NEAR_BRANCH(disp); |
| 562 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 563 | | } else { |
| 564 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 565 | | } |
| 566 | | } |
| 567 | | |
| 568 | | void i386_device::i386_jz_rel8() // Opcode 0x74 |
| 569 | | { |
| 570 | | INT8 disp = FETCH(); |
| 571 | | if( m_ZF != 0 ) { |
| 572 | | NEAR_BRANCH(disp); |
| 573 | | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 574 | | } else { |
| 575 | | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 576 | | } |
| 577 | | } |
| 578 | | |
| 579 | | void i386_device::i386_jmp_rel8() // Opcode 0xeb |
| 580 | | { |
| 581 | | INT8 disp = FETCH(); |
| 582 | | NEAR_BRANCH(disp); |
| 583 | | CYCLES(CYCLES_JMP_SHORT); /* TODO: Timing = 7 + m */ |
| 584 | | } |
| 585 | | |
| 586 | | void i386_device::i386_lahf() // Opcode 0x9f |
| 587 | | { |
| 588 | | REG8(AH) = get_flags() & 0xd7; |
| 589 | | CYCLES(CYCLES_LAHF); |
| 590 | | } |
| 591 | | |
| 592 | | void i386_device::i386_lodsb() // Opcode 0xac |
| 593 | | { |
| 594 | | UINT32 eas; |
| 595 | | if( m_segment_prefix ) { |
| 596 | | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 597 | | } else { |
| 598 | | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 599 | | } |
| 600 | | REG8(AL) = READ8(eas); |
| 601 | | BUMP_SI(1); |
| 602 | | CYCLES(CYCLES_LODS); |
| 603 | | } |
| 604 | | |
| 605 | | void i386_device::i386_mov_rm8_r8() // Opcode 0x88 |
| 606 | | { |
| 607 | | UINT8 src; |
| 608 | | UINT8 modrm = FETCH(); |
| 609 | | if( modrm >= 0xc0 ) { |
| 610 | | src = LOAD_REG8(modrm); |
| 611 | | STORE_RM8(modrm, src); |
| 612 | | CYCLES(CYCLES_MOV_REG_REG); |
| 613 | | } else { |
| 614 | | UINT32 ea = GetEA(modrm,1); |
| 615 | | src = LOAD_REG8(modrm); |
| 616 | | WRITE8(ea, src); |
| 617 | | CYCLES(CYCLES_MOV_REG_MEM); |
| 618 | | } |
| 619 | | } |
| 620 | | |
| 621 | | void i386_device::i386_mov_r8_rm8() // Opcode 0x8a |
| 622 | | { |
| 623 | | UINT8 src; |
| 624 | | UINT8 modrm = FETCH(); |
| 625 | | if( modrm >= 0xc0 ) { |
| 626 | | src = LOAD_RM8(modrm); |
| 627 | | STORE_REG8(modrm, src); |
| 628 | | CYCLES(CYCLES_MOV_REG_REG); |
| 629 | | } else { |
| 630 | | UINT32 ea = GetEA(modrm,0); |
| 631 | | src = READ8(ea); |
| 632 | | STORE_REG8(modrm, src); |
| 633 | | CYCLES(CYCLES_MOV_MEM_REG); |
| 634 | | } |
| 635 | | } |
| 636 | | |
| 637 | | void i386_device::i386_mov_rm8_i8() // Opcode 0xc6 |
| 638 | | { |
| 639 | | UINT8 modrm = FETCH(); |
| 640 | | if( modrm >= 0xc0 ) { |
| 641 | | UINT8 value = FETCH(); |
| 642 | | STORE_RM8(modrm, value); |
| 643 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 644 | | } else { |
| 645 | | UINT32 ea = GetEA(modrm,1); |
| 646 | | UINT8 value = FETCH(); |
| 647 | | WRITE8(ea, value); |
| 648 | | CYCLES(CYCLES_MOV_IMM_MEM); |
| 649 | | } |
| 650 | | } |
| 651 | | |
| 652 | | void i386_device::i386_mov_r32_cr() // Opcode 0x0f 20 |
| 653 | | { |
| 654 | | if(PROTECTED_MODE && m_CPL) |
| 655 | | FAULT(FAULT_GP, 0); |
| 656 | | UINT8 modrm = FETCH(); |
| 657 | | UINT8 cr = (modrm >> 3) & 0x7; |
| 658 | | |
| 659 | | STORE_RM32(modrm, m_cr[cr]); |
| 660 | | CYCLES(CYCLES_MOV_CR_REG); |
| 661 | | } |
| 662 | | |
| 663 | | void i386_device::i386_mov_r32_dr() // Opcode 0x0f 21 |
| 664 | | { |
| 665 | | if(PROTECTED_MODE && m_CPL) |
| 666 | | FAULT(FAULT_GP, 0); |
| 667 | | UINT8 modrm = FETCH(); |
| 668 | | UINT8 dr = (modrm >> 3) & 0x7; |
| 669 | | |
| 670 | | STORE_RM32(modrm, m_dr[dr]); |
| 671 | | switch(dr) |
| 672 | | { |
| 673 | | case 0: |
| 674 | | case 1: |
| 675 | | case 2: |
| 676 | | case 3: |
| 677 | | CYCLES(CYCLES_MOV_REG_DR0_3); |
| 678 | | break; |
| 679 | | case 6: |
| 680 | | case 7: |
| 681 | | CYCLES(CYCLES_MOV_REG_DR6_7); |
| 682 | | break; |
| 683 | | } |
| 684 | | } |
| 685 | | |
| 686 | | void i386_device::i386_mov_cr_r32() // Opcode 0x0f 22 |
| 687 | | { |
| 688 | | if(PROTECTED_MODE && m_CPL) |
| 689 | | FAULT(FAULT_GP, 0); |
| 690 | | UINT8 modrm = FETCH(); |
| 691 | | UINT8 cr = (modrm >> 3) & 0x7; |
| 692 | | UINT32 data = LOAD_RM32(modrm); |
| 693 | | switch(cr) |
| 694 | | { |
| 695 | | case 0: |
| 696 | | data &= 0xfffeffff; // wp not supported on 386 |
| 697 | | CYCLES(CYCLES_MOV_REG_CR0); |
| 698 | | break; |
| 699 | | case 2: CYCLES(CYCLES_MOV_REG_CR2); break; |
| 700 | | case 3: |
| 701 | | CYCLES(CYCLES_MOV_REG_CR3); |
| 702 | | vtlb_flush_dynamic(m_vtlb); |
| 703 | | break; |
| 704 | | case 4: CYCLES(1); break; // TODO |
| 705 | | default: |
| 706 | | logerror("i386: mov_cr_r32 CR%d!\n", cr); |
| 707 | | return; |
| 708 | | } |
| 709 | | m_cr[cr] = data; |
| 710 | | } |
| 711 | | |
| 712 | | void i386_device::i386_mov_dr_r32() // Opcode 0x0f 23 |
| 713 | | { |
| 714 | | if(PROTECTED_MODE && m_CPL) |
| 715 | | FAULT(FAULT_GP, 0); |
| 716 | | UINT8 modrm = FETCH(); |
| 717 | | UINT8 dr = (modrm >> 3) & 0x7; |
| 718 | | |
| 719 | | m_dr[dr] = LOAD_RM32(modrm); |
| 720 | | switch(dr) |
| 721 | | { |
| 722 | | case 0: |
| 723 | | case 1: |
| 724 | | case 2: |
| 725 | | case 3: |
| 726 | | CYCLES(CYCLES_MOV_DR0_3_REG); |
| 727 | | break; |
| 728 | | case 6: |
| 729 | | case 7: |
| 730 | | CYCLES(CYCLES_MOV_DR6_7_REG); |
| 731 | | break; |
| 732 | | default: |
| 733 | | logerror("i386: mov_dr_r32 DR%d!\n", dr); |
| 734 | | return; |
| 735 | | } |
| 736 | | } |
| 737 | | |
| 738 | | void i386_device::i386_mov_al_m8() // Opcode 0xa0 |
| 739 | | { |
| 740 | | UINT32 offset, ea; |
| 741 | | if( m_address_size ) { |
| 742 | | offset = FETCH32(); |
| 743 | | } else { |
| 744 | | offset = FETCH16(); |
| 745 | | } |
| 746 | | /* TODO: Not sure if this is correct... */ |
| 747 | | if( m_segment_prefix ) { |
| 748 | | ea = i386_translate(m_segment_override, offset, 0 ); |
| 749 | | } else { |
| 750 | | ea = i386_translate(DS, offset, 0 ); |
| 751 | | } |
| 752 | | REG8(AL) = READ8(ea); |
| 753 | | CYCLES(CYCLES_MOV_IMM_MEM); |
| 754 | | } |
| 755 | | |
| 756 | | void i386_device::i386_mov_m8_al() // Opcode 0xa2 |
| 757 | | { |
| 758 | | UINT32 offset, ea; |
| 759 | | if( m_address_size ) { |
| 760 | | offset = FETCH32(); |
| 761 | | } else { |
| 762 | | offset = FETCH16(); |
| 763 | | } |
| 764 | | /* TODO: Not sure if this is correct... */ |
| 765 | | if( m_segment_prefix ) { |
| 766 | | ea = i386_translate(m_segment_override, offset, 1 ); |
| 767 | | } else { |
| 768 | | ea = i386_translate(DS, offset, 1 ); |
| 769 | | } |
| 770 | | WRITE8(ea, REG8(AL) ); |
| 771 | | CYCLES(CYCLES_MOV_MEM_ACC); |
| 772 | | } |
| 773 | | |
| 774 | | void i386_device::i386_mov_rm16_sreg() // Opcode 0x8c |
| 775 | | { |
| 776 | | UINT8 modrm = FETCH(); |
| 777 | | int s = (modrm >> 3) & 0x7; |
| 778 | | |
| 779 | | if( modrm >= 0xc0 ) { |
| 780 | | if(m_operand_size) |
| 781 | | STORE_RM32(modrm, m_sreg[s].selector); |
| 782 | | else |
| 783 | | STORE_RM16(modrm, m_sreg[s].selector); |
| 784 | | CYCLES(CYCLES_MOV_SREG_REG); |
| 785 | | } else { |
| 786 | | UINT32 ea = GetEA(modrm,1); |
| 787 | | WRITE16(ea, m_sreg[s].selector); |
| 788 | | CYCLES(CYCLES_MOV_SREG_MEM); |
| 789 | | } |
| 790 | | } |
| 791 | | |
| 792 | | void i386_device::i386_mov_sreg_rm16() // Opcode 0x8e |
| 793 | | { |
| 794 | | UINT16 selector; |
| 795 | | UINT8 modrm = FETCH(); |
| 796 | | bool fault; |
| 797 | | int s = (modrm >> 3) & 0x7; |
| 798 | | |
| 799 | | if( modrm >= 0xc0 ) { |
| 800 | | selector = LOAD_RM16(modrm); |
| 801 | | CYCLES(CYCLES_MOV_REG_SREG); |
| 802 | | } else { |
| 803 | | UINT32 ea = GetEA(modrm,0); |
| 804 | | selector = READ16(ea); |
| 805 | | CYCLES(CYCLES_MOV_MEM_SREG); |
| 806 | | } |
| 807 | | |
| 808 | | i386_sreg_load(selector,s,&fault); |
| 809 | | if((s == SS) && !fault) |
| 810 | | { |
| 811 | | if(m_IF != 0) // if external interrupts are enabled |
| 812 | | { |
| 813 | | m_IF = 0; // reset IF for the next instruction |
| 814 | | m_delayed_interrupt_enable = 1; |
| 815 | | } |
| 816 | | } |
| 817 | | } |
| 818 | | |
| 819 | | void i386_device::i386_mov_al_i8() // Opcode 0xb0 |
| 820 | | { |
| 821 | | REG8(AL) = FETCH(); |
| 822 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 823 | | } |
| 824 | | |
| 825 | | void i386_device::i386_mov_cl_i8() // Opcode 0xb1 |
| 826 | | { |
| 827 | | REG8(CL) = FETCH(); |
| 828 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 829 | | } |
| 830 | | |
| 831 | | void i386_device::i386_mov_dl_i8() // Opcode 0xb2 |
| 832 | | { |
| 833 | | REG8(DL) = FETCH(); |
| 834 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 835 | | } |
| 836 | | |
| 837 | | void i386_device::i386_mov_bl_i8() // Opcode 0xb3 |
| 838 | | { |
| 839 | | REG8(BL) = FETCH(); |
| 840 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 841 | | } |
| 842 | | |
| 843 | | void i386_device::i386_mov_ah_i8() // Opcode 0xb4 |
| 844 | | { |
| 845 | | REG8(AH) = FETCH(); |
| 846 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 847 | | } |
| 848 | | |
| 849 | | void i386_device::i386_mov_ch_i8() // Opcode 0xb5 |
| 850 | | { |
| 851 | | REG8(CH) = FETCH(); |
| 852 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 853 | | } |
| 854 | | |
| 855 | | void i386_device::i386_mov_dh_i8() // Opcode 0xb6 |
| 856 | | { |
| 857 | | REG8(DH) = FETCH(); |
| 858 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 859 | | } |
| 860 | | |
| 861 | | void i386_device::i386_mov_bh_i8() // Opcode 0xb7 |
| 862 | | { |
| 863 | | REG8(BH) = FETCH(); |
| 864 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 865 | | } |
| 866 | | |
| 867 | | void i386_device::i386_movsb() // Opcode 0xa4 |
| 868 | | { |
| 869 | | UINT32 eas, ead; |
| 870 | | UINT8 v; |
| 871 | | if( m_segment_prefix ) { |
| 872 | | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 873 | | } else { |
| 874 | | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 875 | | } |
| 876 | | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 877 | | v = READ8(eas); |
| 878 | | WRITE8(ead, v); |
| 879 | | BUMP_SI(1); |
| 880 | | BUMP_DI(1); |
| 881 | | CYCLES(CYCLES_MOVS); |
| 882 | | } |
| 883 | | |
| 884 | | void i386_device::i386_or_rm8_r8() // Opcode 0x08 |
| 885 | | { |
| 886 | | UINT8 src, dst; |
| 887 | | UINT8 modrm = FETCH(); |
| 888 | | if( modrm >= 0xc0 ) { |
| 889 | | src = LOAD_REG8(modrm); |
| 890 | | dst = LOAD_RM8(modrm); |
| 891 | | dst = OR8(dst, src); |
| 892 | | STORE_RM8(modrm, dst); |
| 893 | | CYCLES(CYCLES_ALU_REG_REG); |
| 894 | | } else { |
| 895 | | UINT32 ea = GetEA(modrm,1); |
| 896 | | src = LOAD_REG8(modrm); |
| 897 | | dst = READ8(ea); |
| 898 | | dst = OR8(dst, src); |
| 899 | | WRITE8(ea, dst); |
| 900 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 901 | | } |
| 902 | | } |
| 903 | | |
| 904 | | void i386_device::i386_or_r8_rm8() // Opcode 0x0a |
| 905 | | { |
| 906 | | UINT8 src, dst; |
| 907 | | UINT8 modrm = FETCH(); |
| 908 | | if( modrm >= 0xc0 ) { |
| 909 | | src = LOAD_RM8(modrm); |
| 910 | | dst = LOAD_REG8(modrm); |
| 911 | | dst = OR8(dst, src); |
| 912 | | STORE_REG8(modrm, dst); |
| 913 | | CYCLES(CYCLES_ALU_REG_REG); |
| 914 | | } else { |
| 915 | | UINT32 ea = GetEA(modrm,0); |
| 916 | | src = READ8(ea); |
| 917 | | dst = LOAD_REG8(modrm); |
| 918 | | dst = OR8(dst, src); |
| 919 | | STORE_REG8(modrm, dst); |
| 920 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 921 | | } |
| 922 | | } |
| 923 | | |
| 924 | | void i386_device::i386_or_al_i8() // Opcode 0x0c |
| 925 | | { |
| 926 | | UINT8 src, dst; |
| 927 | | src = FETCH(); |
| 928 | | dst = REG8(AL); |
| 929 | | dst = OR8(dst, src); |
| 930 | | REG8(EAX) = dst; |
| 931 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 932 | | } |
| 933 | | |
| 934 | | void i386_device::i386_out_al_i8() // Opcode 0xe6 |
| 935 | | { |
| 936 | | UINT16 port = FETCH(); |
| 937 | | UINT8 data = REG8(AL); |
| 938 | | WRITEPORT8(port, data); |
| 939 | | CYCLES(CYCLES_OUT_VAR); |
| 940 | | } |
| 941 | | |
| 942 | | void i386_device::i386_out_al_dx() // Opcode 0xee |
| 943 | | { |
| 944 | | UINT16 port = REG16(DX); |
| 945 | | UINT8 data = REG8(AL); |
| 946 | | WRITEPORT8(port, data); |
| 947 | | CYCLES(CYCLES_OUT); |
| 948 | | } |
| 949 | | |
| 950 | | |
| 951 | | void i386_device::i386_arpl() // Opcode 0x63 |
| 952 | | { |
| 953 | | UINT16 src, dst; |
| 954 | | UINT8 modrm = FETCH(); |
| 955 | | UINT8 flag = 0; |
| 956 | | |
| 957 | | if(PROTECTED_MODE && !V8086_MODE) |
| 958 | | { |
| 959 | | if( modrm >= 0xc0 ) { |
| 960 | | src = LOAD_REG16(modrm); |
| 961 | | dst = LOAD_RM16(modrm); |
| 962 | | if( (dst&0x3) < (src&0x3) ) { |
| 963 | | dst = (dst&0xfffc) | (src&0x3); |
| 964 | | flag = 1; |
| 965 | | STORE_RM16(modrm, dst); |
| 966 | | } |
| 967 | | } else { |
| 968 | | UINT32 ea = GetEA(modrm,1); |
| 969 | | src = LOAD_REG16(modrm); |
| 970 | | dst = READ16(ea); |
| 971 | | if( (dst&0x3) < (src&0x3) ) { |
| 972 | | dst = (dst&0xfffc) | (src&0x3); |
| 973 | | flag = 1; |
| 974 | | WRITE16(ea, dst); |
| 975 | | } |
| 976 | | } |
| 977 | | SetZF(flag); |
| 978 | | } |
| 979 | | else |
| 980 | | i386_trap(6, 0, 0); // invalid opcode in real mode or v8086 mode |
| 981 | | } |
| 982 | | |
| 983 | | void i386_device::i386_push_i8() // Opcode 0x6a |
| 984 | | { |
| 985 | | UINT8 value = FETCH(); |
| 986 | | PUSH8(value); |
| 987 | | CYCLES(CYCLES_PUSH_IMM); |
| 988 | | } |
| 989 | | |
| 990 | | void i386_device::i386_ins_generic(int size) |
| 991 | | { |
| 992 | | UINT32 ead; |
| 993 | | UINT8 vb; |
| 994 | | UINT16 vw; |
| 995 | | UINT32 vd; |
| 996 | | |
| 997 | | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 998 | | |
| 999 | | switch(size) { |
| 1000 | | case 1: |
| 1001 | | vb = READPORT8(REG16(DX)); |
| 1002 | | WRITE8(ead, vb); |
| 1003 | | break; |
| 1004 | | case 2: |
| 1005 | | vw = READPORT16(REG16(DX)); |
| 1006 | | WRITE16(ead, vw); |
| 1007 | | break; |
| 1008 | | case 4: |
| 1009 | | vd = READPORT32(REG16(DX)); |
| 1010 | | WRITE32(ead, vd); |
| 1011 | | break; |
| 1012 | | } |
| 1013 | | |
| 1014 | | if(m_address_size) |
| 1015 | | REG32(EDI) += ((m_DF) ? -1 : 1) * size; |
| 1016 | | else |
| 1017 | | REG16(DI) += ((m_DF) ? -1 : 1) * size; |
| 1018 | | CYCLES(CYCLES_INS); // TODO: Confirm this value |
| 1019 | | } |
| 1020 | | |
| 1021 | | void i386_device::i386_insb() // Opcode 0x6c |
| 1022 | | { |
| 1023 | | i386_ins_generic(1); |
| 1024 | | } |
| 1025 | | |
| 1026 | | void i386_device::i386_insw() // Opcode 0x6d |
| 1027 | | { |
| 1028 | | i386_ins_generic(2); |
| 1029 | | } |
| 1030 | | |
| 1031 | | void i386_device::i386_insd() // Opcode 0x6d |
| 1032 | | { |
| 1033 | | i386_ins_generic(4); |
| 1034 | | } |
| 1035 | | |
| 1036 | | void i386_device::i386_outs_generic(int size) |
| 1037 | | { |
| 1038 | | UINT32 eas; |
| 1039 | | UINT8 vb; |
| 1040 | | UINT16 vw; |
| 1041 | | UINT32 vd; |
| 1042 | | |
| 1043 | | if( m_segment_prefix ) { |
| 1044 | | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1045 | | } else { |
| 1046 | | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1047 | | } |
| 1048 | | |
| 1049 | | switch(size) { |
| 1050 | | case 1: |
| 1051 | | vb = READ8(eas); |
| 1052 | | WRITEPORT8(REG16(DX), vb); |
| 1053 | | break; |
| 1054 | | case 2: |
| 1055 | | vw = READ16(eas); |
| 1056 | | WRITEPORT16(REG16(DX), vw); |
| 1057 | | break; |
| 1058 | | case 4: |
| 1059 | | vd = READ32(eas); |
| 1060 | | WRITEPORT32(REG16(DX), vd); |
| 1061 | | break; |
| 1062 | | } |
| 1063 | | |
| 1064 | | if(m_address_size) |
| 1065 | | REG32(ESI) += ((m_DF) ? -1 : 1) * size; |
| 1066 | | else |
| 1067 | | REG16(SI) += ((m_DF) ? -1 : 1) * size; |
| 1068 | | CYCLES(CYCLES_OUTS); // TODO: Confirm this value |
| 1069 | | } |
| 1070 | | |
| 1071 | | void i386_device::i386_outsb() // Opcode 0x6e |
| 1072 | | { |
| 1073 | | i386_outs_generic(1); |
| 1074 | | } |
| 1075 | | |
| 1076 | | void i386_device::i386_outsw() // Opcode 0x6f |
| 1077 | | { |
| 1078 | | i386_outs_generic(2); |
| 1079 | | } |
| 1080 | | |
| 1081 | | void i386_device::i386_outsd() // Opcode 0x6f |
| 1082 | | { |
| 1083 | | i386_outs_generic(4); |
| 1084 | | } |
| 1085 | | |
| 1086 | | void i386_device::i386_repeat(int invert_flag) |
| 1087 | | { |
| 1088 | | UINT32 repeated_eip = m_eip; |
| 1089 | | UINT32 repeated_pc = m_pc; |
| 1090 | | UINT8 opcode; // = FETCH(); |
| 1091 | | // UINT32 eas, ead; |
| 1092 | | UINT32 count; |
| 1093 | | INT32 cycle_base = 0, cycle_adjustment = 0; |
| 1094 | | UINT8 prefix_flag=1; |
| 1095 | | UINT8 *flag = NULL; |
| 1096 | | |
| 1097 | | |
| 1098 | | do { |
| 1099 | | repeated_eip = m_eip; |
| 1100 | | repeated_pc = m_pc; |
| 1101 | | opcode = FETCH(); |
| 1102 | | switch(opcode) { |
| 1103 | | case 0x0f: |
| 1104 | | if (invert_flag == 0) |
| 1105 | | i386_decode_three_bytef3(); // sse f3 0f |
| 1106 | | else |
| 1107 | | i386_decode_three_bytef2(); // sse f2 0f |
| 1108 | | return; |
| 1109 | | case 0x26: |
| 1110 | | m_segment_override=ES; |
| 1111 | | m_segment_prefix=1; |
| 1112 | | break; |
| 1113 | | case 0x2e: |
| 1114 | | m_segment_override=CS; |
| 1115 | | m_segment_prefix=1; |
| 1116 | | break; |
| 1117 | | case 0x36: |
| 1118 | | m_segment_override=SS; |
| 1119 | | m_segment_prefix=1; |
| 1120 | | break; |
| 1121 | | case 0x3e: |
| 1122 | | m_segment_override=DS; |
| 1123 | | m_segment_prefix=1; |
| 1124 | | break; |
| 1125 | | case 0x64: |
| 1126 | | m_segment_override=FS; |
| 1127 | | m_segment_prefix=1; |
| 1128 | | break; |
| 1129 | | case 0x65: |
| 1130 | | m_segment_override=GS; |
| 1131 | | m_segment_prefix=1; |
| 1132 | | break; |
| 1133 | | case 0x66: |
| 1134 | | m_operand_size ^= 1; |
| 1135 | | break; |
| 1136 | | case 0x67: |
| 1137 | | m_address_size ^= 1; |
| 1138 | | break; |
| 1139 | | default: |
| 1140 | | prefix_flag=0; |
| 1141 | | } |
| 1142 | | } while (prefix_flag); |
| 1143 | | |
| 1144 | | |
| 1145 | | if( m_segment_prefix ) { |
| 1146 | | // FIXME: the following does not work if both address override and segment override are used |
| 1147 | | i386_translate(m_segment_override, m_sreg[m_segment_prefix].d ? REG32(ESI) : REG16(SI), -1 ); |
| 1148 | | } else { |
| 1149 | | //eas = |
| 1150 | | i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), -1 ); |
| 1151 | | } |
| 1152 | | i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), -1 ); |
| 1153 | | |
| 1154 | | switch(opcode) |
| 1155 | | { |
| 1156 | | case 0x6c: |
| 1157 | | case 0x6d: |
| 1158 | | /* INSB, INSW, INSD */ |
| 1159 | | // TODO: cycle count |
| 1160 | | cycle_base = 8; |
| 1161 | | cycle_adjustment = -4; |
| 1162 | | flag = NULL; |
| 1163 | | break; |
| 1164 | | |
| 1165 | | case 0x6e: |
| 1166 | | case 0x6f: |
| 1167 | | /* OUTSB, OUTSW, OUTSD */ |
| 1168 | | // TODO: cycle count |
| 1169 | | cycle_base = 8; |
| 1170 | | cycle_adjustment = -4; |
| 1171 | | flag = NULL; |
| 1172 | | break; |
| 1173 | | |
| 1174 | | case 0xa4: |
| 1175 | | case 0xa5: |
| 1176 | | /* MOVSB, MOVSW, MOVSD */ |
| 1177 | | cycle_base = 8; |
| 1178 | | cycle_adjustment = -4; |
| 1179 | | flag = NULL; |
| 1180 | | break; |
| 1181 | | |
| 1182 | | case 0xa6: |
| 1183 | | case 0xa7: |
| 1184 | | /* CMPSB, CMPSW, CMPSD */ |
| 1185 | | cycle_base = 5; |
| 1186 | | cycle_adjustment = -1; |
| 1187 | | flag = &m_ZF; |
| 1188 | | break; |
| 1189 | | |
| 1190 | | case 0xac: |
| 1191 | | case 0xad: |
| 1192 | | /* LODSB, LODSW, LODSD */ |
| 1193 | | cycle_base = 5; |
| 1194 | | cycle_adjustment = 1; |
| 1195 | | flag = NULL; |
| 1196 | | break; |
| 1197 | | |
| 1198 | | case 0xaa: |
| 1199 | | case 0xab: |
| 1200 | | /* STOSB, STOSW, STOSD */ |
| 1201 | | cycle_base = 5; |
| 1202 | | cycle_adjustment = 0; |
| 1203 | | flag = NULL; |
| 1204 | | break; |
| 1205 | | |
| 1206 | | case 0xae: |
| 1207 | | case 0xaf: |
| 1208 | | /* SCASB, SCASW, SCASD */ |
| 1209 | | cycle_base = 5; |
| 1210 | | cycle_adjustment = 0; |
| 1211 | | flag = &m_ZF; |
| 1212 | | break; |
| 1213 | | |
| 1214 | | case 0x90: |
| 1215 | | CYCLES(CYCLES_NOP); |
| 1216 | | return; |
| 1217 | | |
| 1218 | | case 0xc2: // sigh |
| 1219 | | case 0xc3: |
| 1220 | | m_pc--; |
| 1221 | | return; |
| 1222 | | |
| 1223 | | default: |
| 1224 | | fatalerror("i386: Invalid REP/opcode %02X combination\n",opcode); |
| 1225 | | break; |
| 1226 | | } |
| 1227 | | |
| 1228 | | if( m_address_size ) { |
| 1229 | | if( REG32(ECX) == 0 ) |
| 1230 | | return; |
| 1231 | | } else { |
| 1232 | | if( REG16(CX) == 0 ) |
| 1233 | | return; |
| 1234 | | } |
| 1235 | | |
| 1236 | | /* now actually perform the repeat */ |
| 1237 | | CYCLES_NUM(cycle_base); |
| 1238 | | do |
| 1239 | | { |
| 1240 | | m_eip = repeated_eip; |
| 1241 | | m_pc = repeated_pc; |
| 1242 | | try |
| 1243 | | { |
| 1244 | | i386_decode_opcode(); |
| 1245 | | } |
| 1246 | | catch (UINT64 e) |
| 1247 | | { |
| 1248 | | m_eip = m_prev_eip; |
| 1249 | | throw e; |
| 1250 | | } |
| 1251 | | |
| 1252 | | CYCLES_NUM(cycle_adjustment); |
| 1253 | | |
| 1254 | | if (m_address_size) |
| 1255 | | count = --REG32(ECX); |
| 1256 | | else |
| 1257 | | count = --REG16(CX); |
| 1258 | | if (m_cycles <= 0) |
| 1259 | | goto outofcycles; |
| 1260 | | } |
| 1261 | | while( count && (!flag || (invert_flag ? !*flag : *flag)) ); |
| 1262 | | return; |
| 1263 | | |
| 1264 | | outofcycles: |
| 1265 | | /* if we run out of cycles to execute, and we are still in the repeat, we need |
| 1266 | | * to exit this instruction in such a way to go right back into it when we have |
| 1267 | | * time to execute cycles */ |
| 1268 | | if(flag && (invert_flag ? *flag : !*flag)) |
| 1269 | | return; |
| 1270 | | m_eip = m_prev_eip; |
| 1271 | | CHANGE_PC(m_eip); |
| 1272 | | CYCLES_NUM(-cycle_base); |
| 1273 | | } |
| 1274 | | |
| 1275 | | void i386_device::i386_rep() // Opcode 0xf3 |
| 1276 | | { |
| 1277 | | i386_repeat(0); |
| 1278 | | } |
| 1279 | | |
| 1280 | | void i386_device::i386_repne() // Opcode 0xf2 |
| 1281 | | { |
| 1282 | | i386_repeat(1); |
| 1283 | | } |
| 1284 | | |
| 1285 | | void i386_device::i386_sahf() // Opcode 0x9e |
| 1286 | | { |
| 1287 | | set_flags((get_flags() & 0xffffff00) | (REG8(AH) & 0xd7) ); |
| 1288 | | CYCLES(CYCLES_SAHF); |
| 1289 | | } |
| 1290 | | |
| 1291 | | void i386_device::i386_sbb_rm8_r8() // Opcode 0x18 |
| 1292 | | { |
| 1293 | | UINT8 src, dst; |
| 1294 | | UINT8 modrm = FETCH(); |
| 1295 | | if( modrm >= 0xc0 ) { |
| 1296 | | src = LOAD_REG8(modrm); |
| 1297 | | dst = LOAD_RM8(modrm); |
| 1298 | | dst = SBB8(dst, src, m_CF); |
| 1299 | | STORE_RM8(modrm, dst); |
| 1300 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1301 | | } else { |
| 1302 | | UINT32 ea = GetEA(modrm,1); |
| 1303 | | src = LOAD_REG8(modrm); |
| 1304 | | dst = READ8(ea); |
| 1305 | | dst = SBB8(dst, src, m_CF); |
| 1306 | | WRITE8(ea, dst); |
| 1307 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1308 | | } |
| 1309 | | } |
| 1310 | | |
| 1311 | | void i386_device::i386_sbb_r8_rm8() // Opcode 0x1a |
| 1312 | | { |
| 1313 | | UINT8 src, dst; |
| 1314 | | UINT8 modrm = FETCH(); |
| 1315 | | if( modrm >= 0xc0 ) { |
| 1316 | | src = LOAD_RM8(modrm); |
| 1317 | | dst = LOAD_REG8(modrm); |
| 1318 | | dst = SBB8(dst, src, m_CF); |
| 1319 | | STORE_REG8(modrm, dst); |
| 1320 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1321 | | } else { |
| 1322 | | UINT32 ea = GetEA(modrm,0); |
| 1323 | | src = READ8(ea); |
| 1324 | | dst = LOAD_REG8(modrm); |
| 1325 | | dst = SBB8(dst, src, m_CF); |
| 1326 | | STORE_REG8(modrm, dst); |
| 1327 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 1328 | | } |
| 1329 | | } |
| 1330 | | |
| 1331 | | void i386_device::i386_sbb_al_i8() // Opcode 0x1c |
| 1332 | | { |
| 1333 | | UINT8 src, dst; |
| 1334 | | src = FETCH(); |
| 1335 | | dst = REG8(AL); |
| 1336 | | dst = SBB8(dst, src, m_CF); |
| 1337 | | REG8(EAX) = dst; |
| 1338 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1339 | | } |
| 1340 | | |
| 1341 | | void i386_device::i386_scasb() // Opcode 0xae |
| 1342 | | { |
| 1343 | | UINT32 eas; |
| 1344 | | UINT8 src, dst; |
| 1345 | | eas = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 ); |
| 1346 | | src = READ8(eas); |
| 1347 | | dst = REG8(AL); |
| 1348 | | SUB8(dst, src); |
| 1349 | | BUMP_DI(1); |
| 1350 | | CYCLES(CYCLES_SCAS); |
| 1351 | | } |
| 1352 | | |
| 1353 | | void i386_device::i386_setalc() // Opcode 0xd6 (undocumented) |
| 1354 | | { |
| 1355 | | if( m_CF ) { |
| 1356 | | REG8(AL) = 0xff; |
| 1357 | | } else { |
| 1358 | | REG8(AL) = 0; |
| 1359 | | } |
| 1360 | | CYCLES(3); |
| 1361 | | } |
| 1362 | | |
| 1363 | | void i386_device::i386_seta_rm8() // Opcode 0x0f 97 |
| 1364 | | { |
| 1365 | | UINT8 modrm = FETCH(); |
| 1366 | | UINT8 value = 0; |
| 1367 | | if( m_CF == 0 && m_ZF == 0 ) { |
| 1368 | | value = 1; |
| 1369 | | } |
| 1370 | | if( modrm >= 0xc0 ) { |
| 1371 | | STORE_RM8(modrm, value); |
| 1372 | | CYCLES(CYCLES_SETCC_REG); |
| 1373 | | } else { |
| 1374 | | UINT32 ea = GetEA(modrm,1); |
| 1375 | | WRITE8(ea, value); |
| 1376 | | CYCLES(CYCLES_SETCC_MEM); |
| 1377 | | } |
| 1378 | | } |
| 1379 | | |
| 1380 | | void i386_device::i386_setbe_rm8() // Opcode 0x0f 96 |
| 1381 | | { |
| 1382 | | UINT8 modrm = FETCH(); |
| 1383 | | UINT8 value = 0; |
| 1384 | | if( m_CF != 0 || m_ZF != 0 ) { |
| 1385 | | value = 1; |
| 1386 | | } |
| 1387 | | if( modrm >= 0xc0 ) { |
| 1388 | | STORE_RM8(modrm, value); |
| 1389 | | CYCLES(CYCLES_SETCC_REG); |
| 1390 | | } else { |
| 1391 | | UINT32 ea = GetEA(modrm,1); |
| 1392 | | WRITE8(ea, value); |
| 1393 | | CYCLES(CYCLES_SETCC_MEM); |
| 1394 | | } |
| 1395 | | } |
| 1396 | | |
| 1397 | | void i386_device::i386_setc_rm8() // Opcode 0x0f 92 |
| 1398 | | { |
| 1399 | | UINT8 modrm = FETCH(); |
| 1400 | | UINT8 value = 0; |
| 1401 | | if( m_CF != 0 ) { |
| 1402 | | value = 1; |
| 1403 | | } |
| 1404 | | if( modrm >= 0xc0 ) { |
| 1405 | | STORE_RM8(modrm, value); |
| 1406 | | CYCLES(CYCLES_SETCC_REG); |
| 1407 | | } else { |
| 1408 | | UINT32 ea = GetEA(modrm,1); |
| 1409 | | WRITE8(ea, value); |
| 1410 | | CYCLES(CYCLES_SETCC_MEM); |
| 1411 | | } |
| 1412 | | } |
| 1413 | | |
| 1414 | | void i386_device::i386_setg_rm8() // Opcode 0x0f 9f |
| 1415 | | { |
| 1416 | | UINT8 modrm = FETCH(); |
| 1417 | | UINT8 value = 0; |
| 1418 | | if( m_ZF == 0 && (m_SF == m_OF) ) { |
| 1419 | | value = 1; |
| 1420 | | } |
| 1421 | | if( modrm >= 0xc0 ) { |
| 1422 | | STORE_RM8(modrm, value); |
| 1423 | | CYCLES(CYCLES_SETCC_REG); |
| 1424 | | } else { |
| 1425 | | UINT32 ea = GetEA(modrm,1); |
| 1426 | | WRITE8(ea, value); |
| 1427 | | CYCLES(CYCLES_SETCC_MEM); |
| 1428 | | } |
| 1429 | | } |
| 1430 | | |
| 1431 | | void i386_device::i386_setge_rm8() // Opcode 0x0f 9d |
| 1432 | | { |
| 1433 | | UINT8 modrm = FETCH(); |
| 1434 | | UINT8 value = 0; |
| 1435 | | if(m_SF == m_OF) { |
| 1436 | | value = 1; |
| 1437 | | } |
| 1438 | | if( modrm >= 0xc0 ) { |
| 1439 | | STORE_RM8(modrm, value); |
| 1440 | | CYCLES(CYCLES_SETCC_REG); |
| 1441 | | } else { |
| 1442 | | UINT32 ea = GetEA(modrm,1); |
| 1443 | | WRITE8(ea, value); |
| 1444 | | CYCLES(CYCLES_SETCC_MEM); |
| 1445 | | } |
| 1446 | | } |
| 1447 | | |
| 1448 | | void i386_device::i386_setl_rm8() // Opcode 0x0f 9c |
| 1449 | | { |
| 1450 | | UINT8 modrm = FETCH(); |
| 1451 | | UINT8 value = 0; |
| 1452 | | if( m_SF != m_OF ) { |
| 1453 | | value = 1; |
| 1454 | | } |
| 1455 | | if( modrm >= 0xc0 ) { |
| 1456 | | STORE_RM8(modrm, value); |
| 1457 | | CYCLES(CYCLES_SETCC_REG); |
| 1458 | | } else { |
| 1459 | | UINT32 ea = GetEA(modrm,1); |
| 1460 | | WRITE8(ea, value); |
| 1461 | | CYCLES(CYCLES_SETCC_MEM); |
| 1462 | | } |
| 1463 | | } |
| 1464 | | |
| 1465 | | void i386_device::i386_setle_rm8() // Opcode 0x0f 9e |
| 1466 | | { |
| 1467 | | UINT8 modrm = FETCH(); |
| 1468 | | UINT8 value = 0; |
| 1469 | | if( m_ZF != 0 || (m_SF != m_OF) ) { |
| 1470 | | value = 1; |
| 1471 | | } |
| 1472 | | if( modrm >= 0xc0 ) { |
| 1473 | | STORE_RM8(modrm, value); |
| 1474 | | CYCLES(CYCLES_SETCC_REG); |
| 1475 | | } else { |
| 1476 | | UINT32 ea = GetEA(modrm,1); |
| 1477 | | WRITE8(ea, value); |
| 1478 | | CYCLES(CYCLES_SETCC_MEM); |
| 1479 | | } |
| 1480 | | } |
| 1481 | | |
| 1482 | | void i386_device::i386_setnc_rm8() // Opcode 0x0f 93 |
| 1483 | | { |
| 1484 | | UINT8 modrm = FETCH(); |
| 1485 | | UINT8 value = 0; |
| 1486 | | if( m_CF == 0 ) { |
| 1487 | | value = 1; |
| 1488 | | } |
| 1489 | | if( modrm >= 0xc0 ) { |
| 1490 | | STORE_RM8(modrm, value); |
| 1491 | | CYCLES(CYCLES_SETCC_REG); |
| 1492 | | } else { |
| 1493 | | UINT32 ea = GetEA(modrm,1); |
| 1494 | | WRITE8(ea, value); |
| 1495 | | CYCLES(CYCLES_SETCC_MEM); |
| 1496 | | } |
| 1497 | | } |
| 1498 | | |
| 1499 | | void i386_device::i386_setno_rm8() // Opcode 0x0f 91 |
| 1500 | | { |
| 1501 | | UINT8 modrm = FETCH(); |
| 1502 | | UINT8 value = 0; |
| 1503 | | if( m_OF == 0 ) { |
| 1504 | | value = 1; |
| 1505 | | } |
| 1506 | | if( modrm >= 0xc0 ) { |
| 1507 | | STORE_RM8(modrm, value); |
| 1508 | | CYCLES(CYCLES_SETCC_REG); |
| 1509 | | } else { |
| 1510 | | UINT32 ea = GetEA(modrm,1); |
| 1511 | | WRITE8(ea, value); |
| 1512 | | CYCLES(CYCLES_SETCC_MEM); |
| 1513 | | } |
| 1514 | | } |
| 1515 | | |
| 1516 | | void i386_device::i386_setnp_rm8() // Opcode 0x0f 9b |
| 1517 | | { |
| 1518 | | UINT8 modrm = FETCH(); |
| 1519 | | UINT8 value = 0; |
| 1520 | | if( m_PF == 0 ) { |
| 1521 | | value = 1; |
| 1522 | | } |
| 1523 | | if( modrm >= 0xc0 ) { |
| 1524 | | STORE_RM8(modrm, value); |
| 1525 | | CYCLES(CYCLES_SETCC_REG); |
| 1526 | | } else { |
| 1527 | | UINT32 ea = GetEA(modrm,1); |
| 1528 | | WRITE8(ea, value); |
| 1529 | | CYCLES(CYCLES_SETCC_MEM); |
| 1530 | | } |
| 1531 | | } |
| 1532 | | |
| 1533 | | void i386_device::i386_setns_rm8() // Opcode 0x0f 99 |
| 1534 | | { |
| 1535 | | UINT8 modrm = FETCH(); |
| 1536 | | UINT8 value = 0; |
| 1537 | | if( m_SF == 0 ) { |
| 1538 | | value = 1; |
| 1539 | | } |
| 1540 | | if( modrm >= 0xc0 ) { |
| 1541 | | STORE_RM8(modrm, value); |
| 1542 | | CYCLES(CYCLES_SETCC_REG); |
| 1543 | | } else { |
| 1544 | | UINT32 ea = GetEA(modrm,1); |
| 1545 | | WRITE8(ea, value); |
| 1546 | | CYCLES(CYCLES_SETCC_MEM); |
| 1547 | | } |
| 1548 | | } |
| 1549 | | |
| 1550 | | void i386_device::i386_setnz_rm8() // Opcode 0x0f 95 |
| 1551 | | { |
| 1552 | | UINT8 modrm = FETCH(); |
| 1553 | | UINT8 value = 0; |
| 1554 | | if( m_ZF == 0 ) { |
| 1555 | | value = 1; |
| 1556 | | } |
| 1557 | | if( modrm >= 0xc0 ) { |
| 1558 | | STORE_RM8(modrm, value); |
| 1559 | | CYCLES(CYCLES_SETCC_REG); |
| 1560 | | } else { |
| 1561 | | UINT32 ea = GetEA(modrm,1); |
| 1562 | | WRITE8(ea, value); |
| 1563 | | CYCLES(CYCLES_SETCC_MEM); |
| 1564 | | } |
| 1565 | | } |
| 1566 | | |
| 1567 | | void i386_device::i386_seto_rm8() // Opcode 0x0f 90 |
| 1568 | | { |
| 1569 | | UINT8 modrm = FETCH(); |
| 1570 | | UINT8 value = 0; |
| 1571 | | if( m_OF != 0 ) { |
| 1572 | | value = 1; |
| 1573 | | } |
| 1574 | | if( modrm >= 0xc0 ) { |
| 1575 | | STORE_RM8(modrm, value); |
| 1576 | | CYCLES(CYCLES_SETCC_REG); |
| 1577 | | } else { |
| 1578 | | UINT32 ea = GetEA(modrm,1); |
| 1579 | | WRITE8(ea, value); |
| 1580 | | CYCLES(CYCLES_SETCC_MEM); |
| 1581 | | } |
| 1582 | | } |
| 1583 | | |
| 1584 | | void i386_device::i386_setp_rm8() // Opcode 0x0f 9a |
| 1585 | | { |
| 1586 | | UINT8 modrm = FETCH(); |
| 1587 | | UINT8 value = 0; |
| 1588 | | if( m_PF != 0 ) { |
| 1589 | | value = 1; |
| 1590 | | } |
| 1591 | | if( modrm >= 0xc0 ) { |
| 1592 | | STORE_RM8(modrm, value); |
| 1593 | | CYCLES(CYCLES_SETCC_REG); |
| 1594 | | } else { |
| 1595 | | UINT32 ea = GetEA(modrm,1); |
| 1596 | | WRITE8(ea, value); |
| 1597 | | CYCLES(CYCLES_SETCC_MEM); |
| 1598 | | } |
| 1599 | | } |
| 1600 | | |
| 1601 | | void i386_device::i386_sets_rm8() // Opcode 0x0f 98 |
| 1602 | | { |
| 1603 | | UINT8 modrm = FETCH(); |
| 1604 | | UINT8 value = 0; |
| 1605 | | if( m_SF != 0 ) { |
| 1606 | | value = 1; |
| 1607 | | } |
| 1608 | | if( modrm >= 0xc0 ) { |
| 1609 | | STORE_RM8(modrm, value); |
| 1610 | | CYCLES(CYCLES_SETCC_REG); |
| 1611 | | } else { |
| 1612 | | UINT32 ea = GetEA(modrm,1); |
| 1613 | | WRITE8(ea, value); |
| 1614 | | CYCLES(CYCLES_SETCC_MEM); |
| 1615 | | } |
| 1616 | | } |
| 1617 | | |
| 1618 | | void i386_device::i386_setz_rm8() // Opcode 0x0f 94 |
| 1619 | | { |
| 1620 | | UINT8 modrm = FETCH(); |
| 1621 | | UINT8 value = 0; |
| 1622 | | if( m_ZF != 0 ) { |
| 1623 | | value = 1; |
| 1624 | | } |
| 1625 | | if( modrm >= 0xc0 ) { |
| 1626 | | STORE_RM8(modrm, value); |
| 1627 | | CYCLES(CYCLES_SETCC_REG); |
| 1628 | | } else { |
| 1629 | | UINT32 ea = GetEA(modrm,1); |
| 1630 | | WRITE8(ea, value); |
| 1631 | | CYCLES(CYCLES_SETCC_MEM); |
| 1632 | | } |
| 1633 | | } |
| 1634 | | |
| 1635 | | void i386_device::i386_stc() // Opcode 0xf9 |
| 1636 | | { |
| 1637 | | m_CF = 1; |
| 1638 | | CYCLES(CYCLES_STC); |
| 1639 | | } |
| 1640 | | |
| 1641 | | void i386_device::i386_std() // Opcode 0xfd |
| 1642 | | { |
| 1643 | | m_DF = 1; |
| 1644 | | CYCLES(CYCLES_STD); |
| 1645 | | } |
| 1646 | | |
| 1647 | | void i386_device::i386_sti() // Opcode 0xfb |
| 1648 | | { |
| 1649 | | if(PROTECTED_MODE) |
| 1650 | | { |
| 1651 | | UINT8 IOPL = m_IOP1 | (m_IOP2 << 1); |
| 1652 | | if(m_CPL > IOPL) |
| 1653 | | FAULT(FAULT_GP,0); |
| 1654 | | } |
| 1655 | | m_delayed_interrupt_enable = 1; // IF is set after the next instruction. |
| 1656 | | CYCLES(CYCLES_STI); |
| 1657 | | } |
| 1658 | | |
| 1659 | | void i386_device::i386_stosb() // Opcode 0xaa |
| 1660 | | { |
| 1661 | | UINT32 ead; |
| 1662 | | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 1663 | | WRITE8(ead, REG8(AL)); |
| 1664 | | BUMP_DI(1); |
| 1665 | | CYCLES(CYCLES_STOS); |
| 1666 | | } |
| 1667 | | |
| 1668 | | void i386_device::i386_sub_rm8_r8() // Opcode 0x28 |
| 1669 | | { |
| 1670 | | UINT8 src, dst; |
| 1671 | | UINT8 modrm = FETCH(); |
| 1672 | | if( modrm >= 0xc0 ) { |
| 1673 | | src = LOAD_REG8(modrm); |
| 1674 | | dst = LOAD_RM8(modrm); |
| 1675 | | dst = SUB8(dst, src); |
| 1676 | | STORE_RM8(modrm, dst); |
| 1677 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1678 | | } else { |
| 1679 | | UINT32 ea = GetEA(modrm,1); |
| 1680 | | src = LOAD_REG8(modrm); |
| 1681 | | dst = READ8(ea); |
| 1682 | | dst = SUB8(dst, src); |
| 1683 | | WRITE8(ea, dst); |
| 1684 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1685 | | } |
| 1686 | | } |
| 1687 | | |
| 1688 | | void i386_device::i386_sub_r8_rm8() // Opcode 0x2a |
| 1689 | | { |
| 1690 | | UINT8 src, dst; |
| 1691 | | UINT8 modrm = FETCH(); |
| 1692 | | if( modrm >= 0xc0 ) { |
| 1693 | | src = LOAD_RM8(modrm); |
| 1694 | | dst = LOAD_REG8(modrm); |
| 1695 | | dst = SUB8(dst, src); |
| 1696 | | STORE_REG8(modrm, dst); |
| 1697 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1698 | | } else { |
| 1699 | | UINT32 ea = GetEA(modrm,0); |
| 1700 | | src = READ8(ea); |
| 1701 | | dst = LOAD_REG8(modrm); |
| 1702 | | dst = SUB8(dst, src); |
| 1703 | | STORE_REG8(modrm, dst); |
| 1704 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 1705 | | } |
| 1706 | | } |
| 1707 | | |
| 1708 | | void i386_device::i386_sub_al_i8() // Opcode 0x2c |
| 1709 | | { |
| 1710 | | UINT8 src, dst; |
| 1711 | | src = FETCH(); |
| 1712 | | dst = REG8(EAX); |
| 1713 | | dst = SUB8(dst, src); |
| 1714 | | REG8(EAX) = dst; |
| 1715 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1716 | | } |
| 1717 | | |
| 1718 | | void i386_device::i386_test_al_i8() // Opcode 0xa8 |
| 1719 | | { |
| 1720 | | UINT8 src = FETCH(); |
| 1721 | | UINT8 dst = REG8(AL); |
| 1722 | | dst = src & dst; |
| 1723 | | SetSZPF8(dst); |
| 1724 | | m_CF = 0; |
| 1725 | | m_OF = 0; |
| 1726 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1727 | | } |
| 1728 | | |
| 1729 | | void i386_device::i386_test_rm8_r8() // Opcode 0x84 |
| 1730 | | { |
| 1731 | | UINT8 src, dst; |
| 1732 | | UINT8 modrm = FETCH(); |
| 1733 | | if( modrm >= 0xc0 ) { |
| 1734 | | src = LOAD_REG8(modrm); |
| 1735 | | dst = LOAD_RM8(modrm); |
| 1736 | | dst = src & dst; |
| 1737 | | SetSZPF8(dst); |
| 1738 | | m_CF = 0; |
| 1739 | | m_OF = 0; |
| 1740 | | CYCLES(CYCLES_TEST_REG_REG); |
| 1741 | | } else { |
| 1742 | | UINT32 ea = GetEA(modrm,0); |
| 1743 | | src = LOAD_REG8(modrm); |
| 1744 | | dst = READ8(ea); |
| 1745 | | dst = src & dst; |
| 1746 | | SetSZPF8(dst); |
| 1747 | | m_CF = 0; |
| 1748 | | m_OF = 0; |
| 1749 | | CYCLES(CYCLES_TEST_REG_MEM); |
| 1750 | | } |
| 1751 | | } |
| 1752 | | |
| 1753 | | void i386_device::i386_xchg_r8_rm8() // Opcode 0x86 |
| 1754 | | { |
| 1755 | | UINT8 modrm = FETCH(); |
| 1756 | | if( modrm >= 0xc0 ) { |
| 1757 | | UINT8 src = LOAD_RM8(modrm); |
| 1758 | | UINT8 dst = LOAD_REG8(modrm); |
| 1759 | | STORE_REG8(modrm, src); |
| 1760 | | STORE_RM8(modrm, dst); |
| 1761 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 1762 | | } else { |
| 1763 | | UINT32 ea = GetEA(modrm,1); |
| 1764 | | UINT8 src = READ8(ea); |
| 1765 | | UINT8 dst = LOAD_REG8(modrm); |
| 1766 | | WRITE8(ea, dst); |
| 1767 | | STORE_REG8(modrm, src); |
| 1768 | | CYCLES(CYCLES_XCHG_REG_MEM); |
| 1769 | | } |
| 1770 | | } |
| 1771 | | |
| 1772 | | void i386_device::i386_xor_rm8_r8() // Opcode 0x30 |
| 1773 | | { |
| 1774 | | UINT8 src, dst; |
| 1775 | | UINT8 modrm = FETCH(); |
| 1776 | | if( modrm >= 0xc0 ) { |
| 1777 | | src = LOAD_REG8(modrm); |
| 1778 | | dst = LOAD_RM8(modrm); |
| 1779 | | dst = XOR8(dst, src); |
| 1780 | | STORE_RM8(modrm, dst); |
| 1781 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1782 | | } else { |
| 1783 | | UINT32 ea = GetEA(modrm,1); |
| 1784 | | src = LOAD_REG8(modrm); |
| 1785 | | dst = READ8(ea); |
| 1786 | | dst = XOR8(dst, src); |
| 1787 | | WRITE8(ea, dst); |
| 1788 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1789 | | } |
| 1790 | | } |
| 1791 | | |
| 1792 | | void i386_device::i386_xor_r8_rm8() // Opcode 0x32 |
| 1793 | | { |
| 1794 | | UINT32 src, dst; |
| 1795 | | UINT8 modrm = FETCH(); |
| 1796 | | if( modrm >= 0xc0 ) { |
| 1797 | | src = LOAD_RM8(modrm); |
| 1798 | | dst = LOAD_REG8(modrm); |
| 1799 | | dst = XOR8(dst, src); |
| 1800 | | STORE_REG8(modrm, dst); |
| 1801 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1802 | | } else { |
| 1803 | | UINT32 ea = GetEA(modrm,0); |
| 1804 | | src = READ8(ea); |
| 1805 | | dst = LOAD_REG8(modrm); |
| 1806 | | dst = XOR8(dst, src); |
| 1807 | | STORE_REG8(modrm, dst); |
| 1808 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 1809 | | } |
| 1810 | | } |
| 1811 | | |
| 1812 | | void i386_device::i386_xor_al_i8() // Opcode 0x34 |
| 1813 | | { |
| 1814 | | UINT8 src, dst; |
| 1815 | | src = FETCH(); |
| 1816 | | dst = REG8(AL); |
| 1817 | | dst = XOR8(dst, src); |
| 1818 | | REG8(AL) = dst; |
| 1819 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1820 | | } |
| 1821 | | |
| 1822 | | |
| 1823 | | |
| 1824 | | void i386_device::i386_group80_8() // Opcode 0x80 |
| 1825 | | { |
| 1826 | | UINT32 ea; |
| 1827 | | UINT8 src, dst; |
| 1828 | | UINT8 modrm = FETCH(); |
| 1829 | | |
| 1830 | | switch( (modrm >> 3) & 0x7 ) |
| 1831 | | { |
| 1832 | | case 0: // ADD Rm8, i8 |
| 1833 | | if( modrm >= 0xc0 ) { |
| 1834 | | dst = LOAD_RM8(modrm); |
| 1835 | | src = FETCH(); |
| 1836 | | dst = ADD8(dst, src); |
| 1837 | | STORE_RM8(modrm, dst); |
| 1838 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1839 | | } else { |
| 1840 | | ea = GetEA(modrm,0); |
| 1841 | | dst = READ8(ea); |
| 1842 | | src = FETCH(); |
| 1843 | | dst = ADD8(dst, src); |
| 1844 | | WRITE8(ea, dst); |
| 1845 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1846 | | } |
| 1847 | | break; |
| 1848 | | case 1: // OR Rm8, i8 |
| 1849 | | if( modrm >= 0xc0 ) { |
| 1850 | | dst = LOAD_RM8(modrm); |
| 1851 | | src = FETCH(); |
| 1852 | | dst = OR8(dst, src); |
| 1853 | | STORE_RM8(modrm, dst); |
| 1854 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1855 | | } else { |
| 1856 | | ea = GetEA(modrm,1); |
| 1857 | | dst = READ8(ea); |
| 1858 | | src = FETCH(); |
| 1859 | | dst = OR8(dst, src); |
| 1860 | | WRITE8(ea, dst); |
| 1861 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1862 | | } |
| 1863 | | break; |
| 1864 | | case 2: // ADC Rm8, i8 |
| 1865 | | if( modrm >= 0xc0 ) { |
| 1866 | | dst = LOAD_RM8(modrm); |
| 1867 | | src = FETCH(); |
| 1868 | | dst = ADC8(dst, src, m_CF); |
| 1869 | | STORE_RM8(modrm, dst); |
| 1870 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1871 | | } else { |
| 1872 | | ea = GetEA(modrm,1); |
| 1873 | | dst = READ8(ea); |
| 1874 | | src = FETCH(); |
| 1875 | | dst = ADC8(dst, src, m_CF); |
| 1876 | | WRITE8(ea, dst); |
| 1877 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1878 | | } |
| 1879 | | break; |
| 1880 | | case 3: // SBB Rm8, i8 |
| 1881 | | if( modrm >= 0xc0 ) { |
| 1882 | | dst = LOAD_RM8(modrm); |
| 1883 | | src = FETCH(); |
| 1884 | | dst = SBB8(dst, src, m_CF); |
| 1885 | | STORE_RM8(modrm, dst); |
| 1886 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1887 | | } else { |
| 1888 | | ea = GetEA(modrm,1); |
| 1889 | | dst = READ8(ea); |
| 1890 | | src = FETCH(); |
| 1891 | | dst = SBB8(dst, src, m_CF); |
| 1892 | | WRITE8(ea, dst); |
| 1893 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1894 | | } |
| 1895 | | break; |
| 1896 | | case 4: // AND Rm8, i8 |
| 1897 | | if( modrm >= 0xc0 ) { |
| 1898 | | dst = LOAD_RM8(modrm); |
| 1899 | | src = FETCH(); |
| 1900 | | dst = AND8(dst, src); |
| 1901 | | STORE_RM8(modrm, dst); |
| 1902 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1903 | | } else { |
| 1904 | | ea = GetEA(modrm,1); |
| 1905 | | dst = READ8(ea); |
| 1906 | | src = FETCH(); |
| 1907 | | dst = AND8(dst, src); |
| 1908 | | WRITE8(ea, dst); |
| 1909 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1910 | | } |
| 1911 | | break; |
| 1912 | | case 5: // SUB Rm8, i8 |
| 1913 | | if( modrm >= 0xc0 ) { |
| 1914 | | dst = LOAD_RM8(modrm); |
| 1915 | | src = FETCH(); |
| 1916 | | dst = SUB8(dst, src); |
| 1917 | | STORE_RM8(modrm, dst); |
| 1918 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1919 | | } else { |
| 1920 | | ea = GetEA(modrm,1); |
| 1921 | | dst = READ8(ea); |
| 1922 | | src = FETCH(); |
| 1923 | | dst = SUB8(dst, src); |
| 1924 | | WRITE8(ea, dst); |
| 1925 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1926 | | } |
| 1927 | | break; |
| 1928 | | case 6: // XOR Rm8, i8 |
| 1929 | | if( modrm >= 0xc0 ) { |
| 1930 | | dst = LOAD_RM8(modrm); |
| 1931 | | src = FETCH(); |
| 1932 | | dst = XOR8(dst, src); |
| 1933 | | STORE_RM8(modrm, dst); |
| 1934 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1935 | | } else { |
| 1936 | | ea = GetEA(modrm,1); |
| 1937 | | dst = READ8(ea); |
| 1938 | | src = FETCH(); |
| 1939 | | dst = XOR8(dst, src); |
| 1940 | | WRITE8(ea, dst); |
| 1941 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1942 | | } |
| 1943 | | break; |
| 1944 | | case 7: // CMP Rm8, i8 |
| 1945 | | if( modrm >= 0xc0 ) { |
| 1946 | | dst = LOAD_RM8(modrm); |
| 1947 | | src = FETCH(); |
| 1948 | | SUB8(dst, src); |
| 1949 | | CYCLES(CYCLES_CMP_REG_REG); |
| 1950 | | } else { |
| 1951 | | ea = GetEA(modrm,0); |
| 1952 | | dst = READ8(ea); |
| 1953 | | src = FETCH(); |
| 1954 | | SUB8(dst, src); |
| 1955 | | CYCLES(CYCLES_CMP_REG_MEM); |
| 1956 | | } |
| 1957 | | break; |
| 1958 | | } |
| 1959 | | } |
| 1960 | | |
| 1961 | | void i386_device::i386_groupC0_8() // Opcode 0xc0 |
| 1962 | | { |
| 1963 | | UINT8 dst; |
| 1964 | | UINT8 modrm = FETCH(); |
| 1965 | | UINT8 shift; |
| 1966 | | |
| 1967 | | if( modrm >= 0xc0 ) { |
| 1968 | | dst = LOAD_RM8(modrm); |
| 1969 | | shift = FETCH() & 0x1f; |
| 1970 | | dst = i386_shift_rotate8(modrm, dst, shift); |
| 1971 | | STORE_RM8(modrm, dst); |
| 1972 | | } else { |
| 1973 | | UINT32 ea = GetEA(modrm,1); |
| 1974 | | dst = READ8(ea); |
| 1975 | | shift = FETCH() & 0x1f; |
| 1976 | | dst = i386_shift_rotate8(modrm, dst, shift); |
| 1977 | | WRITE8(ea, dst); |
| 1978 | | } |
| 1979 | | } |
| 1980 | | |
| 1981 | | void i386_device::i386_groupD0_8() // Opcode 0xd0 |
| 1982 | | { |
| 1983 | | UINT8 dst; |
| 1984 | | UINT8 modrm = FETCH(); |
| 1985 | | |
| 1986 | | if( modrm >= 0xc0 ) { |
| 1987 | | dst = LOAD_RM8(modrm); |
| 1988 | | dst = i386_shift_rotate8(modrm, dst, 1); |
| 1989 | | STORE_RM8(modrm, dst); |
| 1990 | | } else { |
| 1991 | | UINT32 ea = GetEA(modrm,1); |
| 1992 | | dst = READ8(ea); |
| 1993 | | dst = i386_shift_rotate8(modrm, dst, 1); |
| 1994 | | WRITE8(ea, dst); |
| 1995 | | } |
| 1996 | | } |
| 1997 | | |
| 1998 | | void i386_device::i386_groupD2_8() // Opcode 0xd2 |
| 1999 | | { |
| 2000 | | UINT8 dst; |
| 2001 | | UINT8 modrm = FETCH(); |
| 2002 | | |
| 2003 | | if( modrm >= 0xc0 ) { |
| 2004 | | dst = LOAD_RM8(modrm); |
| 2005 | | dst = i386_shift_rotate8(modrm, dst, REG8(CL)); |
| 2006 | | STORE_RM8(modrm, dst); |
| 2007 | | } else { |
| 2008 | | UINT32 ea = GetEA(modrm,1); |
| 2009 | | dst = READ8(ea); |
| 2010 | | dst = i386_shift_rotate8(modrm, dst, REG8(CL)); |
| 2011 | | WRITE8(ea, dst); |
| 2012 | | } |
| 2013 | | } |
| 2014 | | |
| 2015 | | void i386_device::i386_groupF6_8() // Opcode 0xf6 |
| 2016 | | { |
| 2017 | | UINT8 modrm = FETCH(); |
| 2018 | | |
| 2019 | | switch( (modrm >> 3) & 0x7 ) |
| 2020 | | { |
| 2021 | | case 0: /* TEST Rm8, i8 */ |
| 2022 | | if( modrm >= 0xc0 ) { |
| 2023 | | UINT8 dst = LOAD_RM8(modrm); |
| 2024 | | UINT8 src = FETCH(); |
| 2025 | | dst &= src; |
| 2026 | | m_CF = m_OF = m_AF = 0; |
| 2027 | | SetSZPF8(dst); |
| 2028 | | CYCLES(CYCLES_TEST_IMM_REG); |
| 2029 | | } else { |
| 2030 | | UINT32 ea = GetEA(modrm,0); |
| 2031 | | UINT8 dst = READ8(ea); |
| 2032 | | UINT8 src = FETCH(); |
| 2033 | | dst &= src; |
| 2034 | | m_CF = m_OF = m_AF = 0; |
| 2035 | | SetSZPF8(dst); |
| 2036 | | CYCLES(CYCLES_TEST_IMM_MEM); |
| 2037 | | } |
| 2038 | | break; |
| 2039 | | case 2: /* NOT Rm8 */ |
| 2040 | | if( modrm >= 0xc0 ) { |
| 2041 | | UINT8 dst = LOAD_RM8(modrm); |
| 2042 | | dst = ~dst; |
| 2043 | | STORE_RM8(modrm, dst); |
| 2044 | | CYCLES(CYCLES_NOT_REG); |
| 2045 | | } else { |
| 2046 | | UINT32 ea = GetEA(modrm,1); |
| 2047 | | UINT8 dst = READ8(ea); |
| 2048 | | dst = ~dst; |
| 2049 | | WRITE8(ea, dst); |
| 2050 | | CYCLES(CYCLES_NOT_MEM); |
| 2051 | | } |
| 2052 | | break; |
| 2053 | | case 3: /* NEG Rm8 */ |
| 2054 | | if( modrm >= 0xc0 ) { |
| 2055 | | UINT8 dst = LOAD_RM8(modrm); |
| 2056 | | dst = SUB8(0, dst ); |
| 2057 | | STORE_RM8(modrm, dst); |
| 2058 | | CYCLES(CYCLES_NEG_REG); |
| 2059 | | } else { |
| 2060 | | UINT32 ea = GetEA(modrm,1); |
| 2061 | | UINT8 dst = READ8(ea); |
| 2062 | | dst = SUB8(0, dst ); |
| 2063 | | WRITE8(ea, dst); |
| 2064 | | CYCLES(CYCLES_NEG_MEM); |
| 2065 | | } |
| 2066 | | break; |
| 2067 | | case 4: /* MUL AL, Rm8 */ |
| 2068 | | { |
| 2069 | | UINT16 result; |
| 2070 | | UINT8 src, dst; |
| 2071 | | if( modrm >= 0xc0 ) { |
| 2072 | | src = LOAD_RM8(modrm); |
| 2073 | | CYCLES(CYCLES_MUL8_ACC_REG); /* TODO: Correct multiply timing */ |
| 2074 | | } else { |
| 2075 | | UINT32 ea = GetEA(modrm,0); |
| 2076 | | src = READ8(ea); |
| 2077 | | CYCLES(CYCLES_MUL8_ACC_MEM); /* TODO: Correct multiply timing */ |
| 2078 | | } |
| 2079 | | |
| 2080 | | dst = REG8(AL); |
| 2081 | | result = (UINT16)src * (UINT16)dst; |
| 2082 | | REG16(AX) = (UINT16)result; |
| 2083 | | |
| 2084 | | m_CF = m_OF = (REG16(AX) > 0xff); |
| 2085 | | } |
| 2086 | | break; |
| 2087 | | case 5: /* IMUL AL, Rm8 */ |
| 2088 | | { |
| 2089 | | INT16 result; |
| 2090 | | INT16 src, dst; |
| 2091 | | if( modrm >= 0xc0 ) { |
| 2092 | | src = (INT16)(INT8)LOAD_RM8(modrm); |
| 2093 | | CYCLES(CYCLES_IMUL8_ACC_REG); /* TODO: Correct multiply timing */ |
| 2094 | | } else { |
| 2095 | | UINT32 ea = GetEA(modrm,0); |
| 2096 | | src = (INT16)(INT8)READ8(ea); |
| 2097 | | CYCLES(CYCLES_IMUL8_ACC_MEM); /* TODO: Correct multiply timing */ |
| 2098 | | } |
| 2099 | | |
| 2100 | | dst = (INT16)(INT8)REG8(AL); |
| 2101 | | result = src * dst; |
| 2102 | | |
| 2103 | | REG16(AX) = (UINT16)result; |
| 2104 | | |
| 2105 | | m_CF = m_OF = !(result == (INT16)(INT8)result); |
| 2106 | | } |
| 2107 | | break; |
| 2108 | | case 6: /* DIV AL, Rm8 */ |
| 2109 | | { |
| 2110 | | UINT16 quotient, remainder, result; |
| 2111 | | UINT8 src; |
| 2112 | | if( modrm >= 0xc0 ) { |
| 2113 | | src = LOAD_RM8(modrm); |
| 2114 | | CYCLES(CYCLES_DIV8_ACC_REG); |
| 2115 | | } else { |
| 2116 | | UINT32 ea = GetEA(modrm,0); |
| 2117 | | src = READ8(ea); |
| 2118 | | CYCLES(CYCLES_DIV8_ACC_MEM); |
| 2119 | | } |
| 2120 | | |
| 2121 | | quotient = (UINT16)REG16(AX); |
| 2122 | | if( src ) { |
| 2123 | | remainder = quotient % (UINT16)src; |
| 2124 | | result = quotient / (UINT16)src; |
| 2125 | | if( result > 0xff ) { |
| 2126 | | /* TODO: Divide error */ |
| 2127 | | } else { |
| 2128 | | REG8(AH) = (UINT8)remainder & 0xff; |
| 2129 | | REG8(AL) = (UINT8)result & 0xff; |
| 2130 | | |
| 2131 | | // this flag is actually undefined, enable on non-cyrix |
| 2132 | | if (m_cpuid_id0 != 0x69727943) |
| 2133 | | m_CF = 1; |
| 2134 | | } |
| 2135 | | } else { |
| 2136 | | i386_trap(0, 0, 0); |
| 2137 | | } |
| 2138 | | } |
| 2139 | | break; |
| 2140 | | case 7: /* IDIV AL, Rm8 */ |
| 2141 | | { |
| 2142 | | INT16 quotient, remainder, result; |
| 2143 | | UINT8 src; |
| 2144 | | if( modrm >= 0xc0 ) { |
| 2145 | | src = LOAD_RM8(modrm); |
| 2146 | | CYCLES(CYCLES_IDIV8_ACC_REG); |
| 2147 | | } else { |
| 2148 | | UINT32 ea = GetEA(modrm,0); |
| 2149 | | src = READ8(ea); |
| 2150 | | CYCLES(CYCLES_IDIV8_ACC_MEM); |
| 2151 | | } |
| 2152 | | |
| 2153 | | quotient = (INT16)REG16(AX); |
| 2154 | | if( src ) { |
| 2155 | | remainder = quotient % (INT16)(INT8)src; |
| 2156 | | result = quotient / (INT16)(INT8)src; |
| 2157 | | if( result > 0xff ) { |
| 2158 | | /* TODO: Divide error */ |
| 2159 | | } else { |
| 2160 | | REG8(AH) = (UINT8)remainder & 0xff; |
| 2161 | | REG8(AL) = (UINT8)result & 0xff; |
| 2162 | | |
| 2163 | | // this flag is actually undefined, enable on non-cyrix |
| 2164 | | if (m_cpuid_id0 != 0x69727943) |
| 2165 | | m_CF = 1; |
| 2166 | | } |
| 2167 | | } else { |
| 2168 | | i386_trap(0, 0, 0); |
| 2169 | | } |
| 2170 | | } |
| 2171 | | break; |
| 2172 | | } |
| 2173 | | } |
| 2174 | | |
| 2175 | | void i386_device::i386_groupFE_8() // Opcode 0xfe |
| 2176 | | { |
| 2177 | | UINT8 modrm = FETCH(); |
| 2178 | | |
| 2179 | | switch( (modrm >> 3) & 0x7 ) |
| 2180 | | { |
| 2181 | | case 0: /* INC Rm8 */ |
| 2182 | | if( modrm >= 0xc0 ) { |
| 2183 | | UINT8 dst = LOAD_RM8(modrm); |
| 2184 | | dst = INC8(dst); |
| 2185 | | STORE_RM8(modrm, dst); |
| 2186 | | CYCLES(CYCLES_INC_REG); |
| 2187 | | } else { |
| 2188 | | UINT32 ea = GetEA(modrm,1); |
| 2189 | | UINT8 dst = READ8(ea); |
| 2190 | | dst = INC8(dst); |
| 2191 | | WRITE8(ea, dst); |
| 2192 | | CYCLES(CYCLES_INC_MEM); |
| 2193 | | } |
| 2194 | | break; |
| 2195 | | case 1: /* DEC Rm8 */ |
| 2196 | | if( modrm >= 0xc0 ) { |
| 2197 | | UINT8 dst = LOAD_RM8(modrm); |
| 2198 | | dst = DEC8(dst); |
| 2199 | | STORE_RM8(modrm, dst); |
| 2200 | | CYCLES(CYCLES_DEC_REG); |
| 2201 | | } else { |
| 2202 | | UINT32 ea = GetEA(modrm,1); |
| 2203 | | UINT8 dst = READ8(ea); |
| 2204 | | dst = DEC8(dst); |
| 2205 | | WRITE8(ea, dst); |
| 2206 | | CYCLES(CYCLES_DEC_MEM); |
| 2207 | | } |
| 2208 | | break; |
| 2209 | | case 6: /* PUSH Rm8*/ |
| 2210 | | { |
| 2211 | | UINT8 value; |
| 2212 | | if( modrm >= 0xc0 ) { |
| 2213 | | value = LOAD_RM8(modrm); |
| 2214 | | } else { |
| 2215 | | UINT32 ea = GetEA(modrm,0); |
| 2216 | | value = READ8(ea); |
| 2217 | | } |
| 2218 | | if( m_operand_size ) { |
| 2219 | | PUSH32(value); |
| 2220 | | } else { |
| 2221 | | PUSH16(value); |
| 2222 | | } |
| 2223 | | CYCLES(CYCLES_PUSH_RM); |
| 2224 | | } |
| 2225 | | break; |
| 2226 | | default: |
| 2227 | | report_invalid_modrm("groupFE_8", modrm); |
| 2228 | | break; |
| 2229 | | } |
| 2230 | | } |
| 2231 | | |
| 2232 | | |
| 2233 | | |
| 2234 | | void i386_device::i386_segment_CS() // Opcode 0x2e |
| 2235 | | { |
| 2236 | | m_segment_prefix = 1; |
| 2237 | | m_segment_override = CS; |
| 2238 | | |
| 2239 | | i386_decode_opcode(); |
| 2240 | | } |
| 2241 | | |
| 2242 | | void i386_device::i386_segment_DS() // Opcode 0x3e |
| 2243 | | { |
| 2244 | | m_segment_prefix = 1; |
| 2245 | | m_segment_override = DS; |
| 2246 | | CYCLES(0); // TODO: Specify cycle count |
| 2247 | | i386_decode_opcode(); |
| 2248 | | } |
| 2249 | | |
| 2250 | | void i386_device::i386_segment_ES() // Opcode 0x26 |
| 2251 | | { |
| 2252 | | m_segment_prefix = 1; |
| 2253 | | m_segment_override = ES; |
| 2254 | | CYCLES(0); // TODO: Specify cycle count |
| 2255 | | i386_decode_opcode(); |
| 2256 | | } |
| 2257 | | |
| 2258 | | void i386_device::i386_segment_FS() // Opcode 0x64 |
| 2259 | | { |
| 2260 | | m_segment_prefix = 1; |
| 2261 | | m_segment_override = FS; |
| 2262 | | CYCLES(1); // TODO: Specify cycle count |
| 2263 | | i386_decode_opcode(); |
| 2264 | | } |
| 2265 | | |
| 2266 | | void i386_device::i386_segment_GS() // Opcode 0x65 |
| 2267 | | { |
| 2268 | | m_segment_prefix = 1; |
| 2269 | | m_segment_override = GS; |
| 2270 | | CYCLES(1); // TODO: Specify cycle count |
| 2271 | | i386_decode_opcode(); |
| 2272 | | } |
| 2273 | | |
| 2274 | | void i386_device::i386_segment_SS() // Opcode 0x36 |
| 2275 | | { |
| 2276 | | m_segment_prefix = 1; |
| 2277 | | m_segment_override = SS; |
| 2278 | | CYCLES(0); // TODO: Specify cycle count |
| 2279 | | i386_decode_opcode(); |
| 2280 | | } |
| 2281 | | |
| 2282 | | void i386_device::i386_operand_size() // Opcode prefix 0x66 |
| 2283 | | { |
| 2284 | | if(m_operand_prefix == 0) |
| 2285 | | { |
| 2286 | | m_operand_size ^= 1; |
| 2287 | | m_operand_prefix = 1; |
| 2288 | | } |
| 2289 | | m_opcode = FETCH(); |
| 2290 | | if (m_opcode == 0x0f) |
| 2291 | | i386_decode_three_byte66(); |
| 2292 | | else |
| 2293 | | { |
| 2294 | | if( m_operand_size ) |
| 2295 | | (this->*m_opcode_table1_32[m_opcode])(); |
| 2296 | | else |
| 2297 | | (this->*m_opcode_table1_16[m_opcode])(); |
| 2298 | | } |
| 2299 | | } |
| 2300 | | |
| 2301 | | void i386_device::i386_address_size() // Opcode 0x67 |
| 2302 | | { |
| 2303 | | if(m_address_prefix == 0) |
| 2304 | | { |
| 2305 | | m_address_size ^= 1; |
| 2306 | | m_address_prefix = 1; |
| 2307 | | } |
| 2308 | | i386_decode_opcode(); |
| 2309 | | } |
| 2310 | | |
| 2311 | | void i386_device::i386_nop() // Opcode 0x90 |
| 2312 | | { |
| 2313 | | CYCLES(CYCLES_NOP); |
| 2314 | | } |
| 2315 | | |
| 2316 | | void i386_device::i386_int3() // Opcode 0xcc |
| 2317 | | { |
| 2318 | | CYCLES(CYCLES_INT3); |
| 2319 | | m_ext = 0; // not an external interrupt |
| 2320 | | i386_trap(3, 1, 0); |
| 2321 | | m_ext = 1; |
| 2322 | | } |
| 2323 | | |
| 2324 | | void i386_device::i386_int() // Opcode 0xcd |
| 2325 | | { |
| 2326 | | int interrupt = FETCH(); |
| 2327 | | CYCLES(CYCLES_INT); |
| 2328 | | m_ext = 0; // not an external interrupt |
| 2329 | | i386_trap(interrupt, 1, 0); |
| 2330 | | m_ext = 1; |
| 2331 | | } |
| 2332 | | |
| 2333 | | void i386_device::i386_into() // Opcode 0xce |
| 2334 | | { |
| 2335 | | if( m_OF ) { |
| 2336 | | m_ext = 0; |
| 2337 | | i386_trap(4, 1, 0); |
| 2338 | | m_ext = 1; |
| 2339 | | CYCLES(CYCLES_INTO_OF1); |
| 2340 | | } |
| 2341 | | else |
| 2342 | | { |
| 2343 | | CYCLES(CYCLES_INTO_OF0); |
| 2344 | | } |
| 2345 | | } |
| 2346 | | |
| 2347 | | static UINT32 i386_escape_ea; // hack around GCC 4.6 error because we need the side effects of GetEA() |
| 2348 | | void i386_device::i386_escape() // Opcodes 0xd8 - 0xdf |
| 2349 | | { |
| 2350 | | UINT8 modrm = FETCH(); |
| 2351 | | if(modrm < 0xc0) |
| 2352 | | { |
| 2353 | | i386_escape_ea = GetEA(modrm,0); |
| 2354 | | } |
| 2355 | | CYCLES(3); // TODO: confirm this |
| 2356 | | (void) LOAD_RM8(modrm); |
| 2357 | | } |
| 2358 | | |
| 2359 | | void i386_device::i386_hlt() // Opcode 0xf4 |
| 2360 | | { |
| 2361 | | if(PROTECTED_MODE && m_CPL != 0) |
| 2362 | | FAULT(FAULT_GP,0); |
| 2363 | | m_halted = 1; |
| 2364 | | CYCLES(CYCLES_HLT); |
| 2365 | | if (m_cycles > 0) |
| 2366 | | m_cycles = 0; |
| 2367 | | } |
| 2368 | | |
| 2369 | | void i386_device::i386_decimal_adjust(int direction) |
| 2370 | | { |
| 2371 | | UINT8 tmpAL = REG8(AL); |
| 2372 | | UINT8 tmpCF = m_CF; |
| 2373 | | |
| 2374 | | if (m_AF || ((REG8(AL) & 0xf) > 9)) |
| 2375 | | { |
| 2376 | | UINT16 t= (UINT16)REG8(AL) + (direction * 0x06); |
| 2377 | | REG8(AL) = (UINT8)t&0xff; |
| 2378 | | m_AF = 1; |
| 2379 | | if (t & 0x100) |
| 2380 | | m_CF = 1; |
| 2381 | | if (direction > 0) |
| 2382 | | tmpAL = REG8(AL); |
| 2383 | | } |
| 2384 | | |
| 2385 | | if (tmpCF || (tmpAL > 0x99)) |
| 2386 | | { |
| 2387 | | REG8(AL) += (direction * 0x60); |
| 2388 | | m_CF = 1; |
| 2389 | | } |
| 2390 | | |
| 2391 | | SetSZPF8(REG8(AL)); |
| 2392 | | } |
| 2393 | | |
| 2394 | | void i386_device::i386_daa() // Opcode 0x27 |
| 2395 | | { |
| 2396 | | i386_decimal_adjust(+1); |
| 2397 | | CYCLES(CYCLES_DAA); |
| 2398 | | } |
| 2399 | | |
| 2400 | | void i386_device::i386_das() // Opcode 0x2f |
| 2401 | | { |
| 2402 | | i386_decimal_adjust(-1); |
| 2403 | | CYCLES(CYCLES_DAS); |
| 2404 | | } |
| 2405 | | |
| 2406 | | void i386_device::i386_aaa() // Opcode 0x37 |
| 2407 | | { |
| 2408 | | if( ( (REG8(AL) & 0x0f) > 9) || (m_AF != 0) ) { |
| 2409 | | REG16(AX) = REG16(AX) + 6; |
| 2410 | | REG8(AH) = REG8(AH) + 1; |
| 2411 | | m_AF = 1; |
| 2412 | | m_CF = 1; |
| 2413 | | } else { |
| 2414 | | m_AF = 0; |
| 2415 | | m_CF = 0; |
| 2416 | | } |
| 2417 | | REG8(AL) = REG8(AL) & 0x0f; |
| 2418 | | CYCLES(CYCLES_AAA); |
| 2419 | | } |
| 2420 | | |
| 2421 | | void i386_device::i386_aas() // Opcode 0x3f |
| 2422 | | { |
| 2423 | | if (m_AF || ((REG8(AL) & 0xf) > 9)) |
| 2424 | | { |
| 2425 | | REG16(AX) -= 6; |
| 2426 | | REG8(AH) -= 1; |
| 2427 | | m_AF = 1; |
| 2428 | | m_CF = 1; |
| 2429 | | } |
| 2430 | | else |
| 2431 | | { |
| 2432 | | m_AF = 0; |
| 2433 | | m_CF = 0; |
| 2434 | | } |
| 2435 | | REG8(AL) &= 0x0f; |
| 2436 | | CYCLES(CYCLES_AAS); |
| 2437 | | } |
| 2438 | | |
| 2439 | | void i386_device::i386_aad() // Opcode 0xd5 |
| 2440 | | { |
| 2441 | | UINT8 tempAL = REG8(AL); |
| 2442 | | UINT8 tempAH = REG8(AH); |
| 2443 | | UINT8 i = FETCH(); |
| 2444 | | |
| 2445 | | REG8(AL) = (tempAL + (tempAH * i)) & 0xff; |
| 2446 | | REG8(AH) = 0; |
| 2447 | | SetSZPF8( REG8(AL) ); |
| 2448 | | CYCLES(CYCLES_AAD); |
| 2449 | | } |
| 2450 | | |
| 2451 | | void i386_device::i386_aam() // Opcode 0xd4 |
| 2452 | | { |
| 2453 | | UINT8 tempAL = REG8(AL); |
| 2454 | | UINT8 i = FETCH(); |
| 2455 | | |
| 2456 | | if(!i) |
| 2457 | | { |
| 2458 | | i386_trap(0, 0, 0); |
| 2459 | | return; |
| 2460 | | } |
| 2461 | | REG8(AH) = tempAL / i; |
| 2462 | | REG8(AL) = tempAL % i; |
| 2463 | | SetSZPF8( REG8(AL) ); |
| 2464 | | CYCLES(CYCLES_AAM); |
| 2465 | | } |
| 2466 | | |
| 2467 | | void i386_device::i386_clts() // Opcode 0x0f 0x06 |
| 2468 | | { |
| 2469 | | // Privileged instruction, CPL must be zero. Can be used in real or v86 mode. |
| 2470 | | if(PROTECTED_MODE && m_CPL != 0) |
| 2471 | | FAULT(FAULT_GP,0) |
| 2472 | | m_cr[0] &= ~0x08; /* clear TS bit */ |
| 2473 | | CYCLES(CYCLES_CLTS); |
| 2474 | | } |
| 2475 | | |
| 2476 | | void i386_device::i386_wait() // Opcode 0x9B |
| 2477 | | { |
| 2478 | | // TODO |
| 2479 | | } |
| 2480 | | |
| 2481 | | void i386_device::i386_lock() // Opcode 0xf0 |
| 2482 | | { |
| 2483 | | // lock doesn't depend on iopl on 386 |
| 2484 | | // TODO: lock causes UD on unlockable opcodes |
| 2485 | | CYCLES(CYCLES_LOCK); // TODO: Determine correct cycle count |
| 2486 | | i386_decode_opcode(); |
| 2487 | | } |
| 2488 | | |
| 2489 | | void i386_device::i386_mov_r32_tr() // Opcode 0x0f 24 |
| 2490 | | { |
| 2491 | | FETCH(); |
| 2492 | | CYCLES(1); // TODO: correct cycle count |
| 2493 | | } |
| 2494 | | |
| 2495 | | void i386_device::i386_mov_tr_r32() // Opcode 0x0f 26 |
| 2496 | | { |
| 2497 | | FETCH(); |
| 2498 | | CYCLES(1); // TODO: correct cycle count |
| 2499 | | } |
| 2500 | | |
| 2501 | | void i386_device::i386_loadall() // Opcode 0x0f 0x07 (0x0f 0x05 on 80286), undocumented |
| 2502 | | { |
| 2503 | | fatalerror("i386: LOADALL unimplemented at %08X\n", m_pc - 1); |
| 2504 | | } |
| 2505 | | |
| 2506 | | void i386_device::i386_invalid() |
| 2507 | | { |
| 2508 | | report_invalid_opcode(); |
| 2509 | | i386_trap(6, 0, 0); |
| 2510 | | } |
| 2511 | | |
| 2512 | | void i386_device::i386_xlat() // Opcode 0xd7 |
| 2513 | | { |
| 2514 | | UINT32 ea; |
| 2515 | | if( m_segment_prefix ) { |
| 2516 | | if(!m_address_size) |
| 2517 | | { |
| 2518 | | ea = i386_translate(m_segment_override, REG16(BX) + REG8(AL), 0 ); |
| 2519 | | } |
| 2520 | | else |
| 2521 | | { |
| 2522 | | ea = i386_translate(m_segment_override, REG32(EBX) + REG8(AL), 0 ); |
| 2523 | | } |
| 2524 | | } else { |
| 2525 | | if(!m_address_size) |
| 2526 | | { |
| 2527 | | ea = i386_translate(DS, REG16(BX) + REG8(AL), 0 ); |
| 2528 | | } |
| 2529 | | else |
| 2530 | | { |
| 2531 | | ea = i386_translate(DS, REG32(EBX) + REG8(AL), 0 ); |
| 2532 | | } |
| 2533 | | } |
| 2534 | | REG8(AL) = READ8(ea); |
| 2535 | | CYCLES(CYCLES_XLAT); |
| 2536 | | } |
trunk/src/emu/cpu/i386/i386op32.c
| r28738 | r28739 | |
| 1 | | UINT32 i386_device::i386_shift_rotate32(UINT8 modrm, UINT32 value, UINT8 shift) |
| 2 | | { |
| 3 | | UINT32 dst, src; |
| 4 | | dst = value; |
| 5 | | src = value; |
| 6 | | |
| 7 | | if( shift == 0 ) { |
| 8 | | CYCLES_RM(modrm, 3, 7); |
| 9 | | } else if( shift == 1 ) { |
| 10 | | switch( (modrm >> 3) & 0x7 ) |
| 11 | | { |
| 12 | | case 0: /* ROL rm32, 1 */ |
| 13 | | m_CF = (src & 0x80000000) ? 1 : 0; |
| 14 | | dst = (src << 1) + m_CF; |
| 15 | | m_OF = ((src ^ dst) & 0x80000000) ? 1 : 0; |
| 16 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 17 | | break; |
| 18 | | case 1: /* ROR rm32, 1 */ |
| 19 | | m_CF = (src & 0x1) ? 1 : 0; |
| 20 | | dst = (m_CF << 31) | (src >> 1); |
| 21 | | m_OF = ((src ^ dst) & 0x80000000) ? 1 : 0; |
| 22 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 23 | | break; |
| 24 | | case 2: /* RCL rm32, 1 */ |
| 25 | | dst = (src << 1) + m_CF; |
| 26 | | m_CF = (src & 0x80000000) ? 1 : 0; |
| 27 | | m_OF = ((src ^ dst) & 0x80000000) ? 1 : 0; |
| 28 | | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 29 | | break; |
| 30 | | case 3: /* RCR rm32, 1 */ |
| 31 | | dst = (m_CF << 31) | (src >> 1); |
| 32 | | m_CF = src & 0x1; |
| 33 | | m_OF = ((src ^ dst) & 0x80000000) ? 1 : 0; |
| 34 | | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 35 | | break; |
| 36 | | case 4: /* SHL/SAL rm32, 1 */ |
| 37 | | case 6: |
| 38 | | dst = src << 1; |
| 39 | | m_CF = (src & 0x80000000) ? 1 : 0; |
| 40 | | m_OF = (((m_CF << 31) ^ dst) & 0x80000000) ? 1 : 0; |
| 41 | | SetSZPF32(dst); |
| 42 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 43 | | break; |
| 44 | | case 5: /* SHR rm32, 1 */ |
| 45 | | dst = src >> 1; |
| 46 | | m_CF = src & 0x1; |
| 47 | | m_OF = (src & 0x80000000) ? 1 : 0; |
| 48 | | SetSZPF32(dst); |
| 49 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 50 | | break; |
| 51 | | case 7: /* SAR rm32, 1 */ |
| 52 | | dst = (INT32)(src) >> 1; |
| 53 | | m_CF = src & 0x1; |
| 54 | | m_OF = 0; |
| 55 | | SetSZPF32(dst); |
| 56 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 57 | | break; |
| 58 | | } |
| 59 | | |
| 60 | | } else { |
| 61 | | shift &= 31; |
| 62 | | switch( (modrm >> 3) & 0x7 ) |
| 63 | | { |
| 64 | | case 0: /* ROL rm32, i8 */ |
| 65 | | dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) | |
| 66 | | ((src & ((UINT32)0xffffffff << (32-shift))) >> (32-shift)); |
| 67 | | m_CF = dst & 0x1; |
| 68 | | m_OF = (dst & 1) ^ (dst >> 31); |
| 69 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 70 | | break; |
| 71 | | case 1: /* ROR rm32, i8 */ |
| 72 | | dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) | |
| 73 | | ((src & ((UINT32)0xffffffff >> (32-shift))) << (32-shift)); |
| 74 | | m_CF = (dst >> 31) & 0x1; |
| 75 | | m_OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 76 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 77 | | break; |
| 78 | | case 2: /* RCL rm32, i8 */ |
| 79 | | dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) | |
| 80 | | ((src & ((UINT32)0xffffffff << (33-shift))) >> (33-shift)) | |
| 81 | | (m_CF << (shift-1)); |
| 82 | | m_CF = (src >> (32-shift)) & 0x1; |
| 83 | | m_OF = m_CF ^ ((dst >> 31) & 1); |
| 84 | | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 85 | | break; |
| 86 | | case 3: /* RCR rm32, i8 */ |
| 87 | | dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) | |
| 88 | | ((src & ((UINT32)0xffffffff >> (32-shift))) << (33-shift)) | |
| 89 | | (m_CF << (32-shift)); |
| 90 | | m_CF = (src >> (shift-1)) & 0x1; |
| 91 | | m_OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 92 | | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 93 | | break; |
| 94 | | case 4: /* SHL/SAL rm32, i8 */ |
| 95 | | case 6: |
| 96 | | dst = src << shift; |
| 97 | | m_CF = (src & (1 << (32-shift))) ? 1 : 0; |
| 98 | | SetSZPF32(dst); |
| 99 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 100 | | break; |
| 101 | | case 5: /* SHR rm32, i8 */ |
| 102 | | dst = src >> shift; |
| 103 | | m_CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 104 | | SetSZPF32(dst); |
| 105 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 106 | | break; |
| 107 | | case 7: /* SAR rm32, i8 */ |
| 108 | | dst = (INT32)src >> shift; |
| 109 | | m_CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 110 | | SetSZPF32(dst); |
| 111 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 112 | | break; |
| 113 | | } |
| 114 | | |
| 115 | | } |
| 116 | | return dst; |
| 117 | | } |
| 118 | | |
| 119 | | |
| 120 | | |
| 121 | | void i386_device::i386_adc_rm32_r32() // Opcode 0x11 |
| 122 | | { |
| 123 | | UINT32 src, dst; |
| 124 | | UINT8 modrm = FETCH(); |
| 125 | | if( modrm >= 0xc0 ) { |
| 126 | | src = LOAD_REG32(modrm); |
| 127 | | dst = LOAD_RM32(modrm); |
| 128 | | dst = ADC32(dst, src, m_CF); |
| 129 | | STORE_RM32(modrm, dst); |
| 130 | | CYCLES(CYCLES_ALU_REG_REG); |
| 131 | | } else { |
| 132 | | UINT32 ea = GetEA(modrm,1); |
| 133 | | src = LOAD_REG32(modrm); |
| 134 | | dst = READ32(ea); |
| 135 | | dst = ADC32(dst, src, m_CF); |
| 136 | | WRITE32(ea, dst); |
| 137 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 138 | | } |
| 139 | | } |
| 140 | | |
| 141 | | void i386_device::i386_adc_r32_rm32() // Opcode 0x13 |
| 142 | | { |
| 143 | | UINT32 src, dst; |
| 144 | | UINT8 modrm = FETCH(); |
| 145 | | if( modrm >= 0xc0 ) { |
| 146 | | src = LOAD_RM32(modrm); |
| 147 | | dst = LOAD_REG32(modrm); |
| 148 | | dst = ADC32(dst, src, m_CF); |
| 149 | | STORE_REG32(modrm, dst); |
| 150 | | CYCLES(CYCLES_ALU_REG_REG); |
| 151 | | } else { |
| 152 | | UINT32 ea = GetEA(modrm,0); |
| 153 | | src = READ32(ea); |
| 154 | | dst = LOAD_REG32(modrm); |
| 155 | | dst = ADC32(dst, src, m_CF); |
| 156 | | STORE_REG32(modrm, dst); |
| 157 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 158 | | } |
| 159 | | } |
| 160 | | |
| 161 | | void i386_device::i386_adc_eax_i32() // Opcode 0x15 |
| 162 | | { |
| 163 | | UINT32 src, dst; |
| 164 | | src = FETCH32(); |
| 165 | | dst = REG32(EAX); |
| 166 | | dst = ADC32(dst, src, m_CF); |
| 167 | | REG32(EAX) = dst; |
| 168 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 169 | | } |
| 170 | | |
| 171 | | void i386_device::i386_add_rm32_r32() // Opcode 0x01 |
| 172 | | { |
| 173 | | UINT32 src, dst; |
| 174 | | UINT8 modrm = FETCH(); |
| 175 | | if( modrm >= 0xc0 ) { |
| 176 | | src = LOAD_REG32(modrm); |
| 177 | | dst = LOAD_RM32(modrm); |
| 178 | | dst = ADD32(dst, src); |
| 179 | | STORE_RM32(modrm, dst); |
| 180 | | CYCLES(CYCLES_ALU_REG_REG); |
| 181 | | } else { |
| 182 | | UINT32 ea = GetEA(modrm,1); |
| 183 | | src = LOAD_REG32(modrm); |
| 184 | | dst = READ32(ea); |
| 185 | | dst = ADD32(dst, src); |
| 186 | | WRITE32(ea, dst); |
| 187 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 188 | | } |
| 189 | | } |
| 190 | | |
| 191 | | void i386_device::i386_add_r32_rm32() // Opcode 0x03 |
| 192 | | { |
| 193 | | UINT32 src, dst; |
| 194 | | UINT8 modrm = FETCH(); |
| 195 | | if( modrm >= 0xc0 ) { |
| 196 | | src = LOAD_RM32(modrm); |
| 197 | | dst = LOAD_REG32(modrm); |
| 198 | | dst = ADD32(dst, src); |
| 199 | | STORE_REG32(modrm, dst); |
| 200 | | CYCLES(CYCLES_ALU_REG_REG); |
| 201 | | } else { |
| 202 | | UINT32 ea = GetEA(modrm,0); |
| 203 | | src = READ32(ea); |
| 204 | | dst = LOAD_REG32(modrm); |
| 205 | | dst = ADD32(dst, src); |
| 206 | | STORE_REG32(modrm, dst); |
| 207 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 208 | | } |
| 209 | | } |
| 210 | | |
| 211 | | void i386_device::i386_add_eax_i32() // Opcode 0x05 |
| 212 | | { |
| 213 | | UINT32 src, dst; |
| 214 | | src = FETCH32(); |
| 215 | | dst = REG32(EAX); |
| 216 | | dst = ADD32(dst, src); |
| 217 | | REG32(EAX) = dst; |
| 218 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 219 | | } |
| 220 | | |
| 221 | | void i386_device::i386_and_rm32_r32() // Opcode 0x21 |
| 222 | | { |
| 223 | | UINT32 src, dst; |
| 224 | | UINT8 modrm = FETCH(); |
| 225 | | if( modrm >= 0xc0 ) { |
| 226 | | src = LOAD_REG32(modrm); |
| 227 | | dst = LOAD_RM32(modrm); |
| 228 | | dst = AND32(dst, src); |
| 229 | | STORE_RM32(modrm, dst); |
| 230 | | CYCLES(CYCLES_ALU_REG_REG); |
| 231 | | } else { |
| 232 | | UINT32 ea = GetEA(modrm,1); |
| 233 | | src = LOAD_REG32(modrm); |
| 234 | | dst = READ32(ea); |
| 235 | | dst = AND32(dst, src); |
| 236 | | WRITE32(ea, dst); |
| 237 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 238 | | } |
| 239 | | } |
| 240 | | |
| 241 | | void i386_device::i386_and_r32_rm32() // Opcode 0x23 |
| 242 | | { |
| 243 | | UINT32 src, dst; |
| 244 | | UINT8 modrm = FETCH(); |
| 245 | | if( modrm >= 0xc0 ) { |
| 246 | | src = LOAD_RM32(modrm); |
| 247 | | dst = LOAD_REG32(modrm); |
| 248 | | dst = AND32(dst, src); |
| 249 | | STORE_REG32(modrm, dst); |
| 250 | | CYCLES(CYCLES_ALU_REG_REG); |
| 251 | | } else { |
| 252 | | UINT32 ea = GetEA(modrm,0); |
| 253 | | src = READ32(ea); |
| 254 | | dst = LOAD_REG32(modrm); |
| 255 | | dst = AND32(dst, src); |
| 256 | | STORE_REG32(modrm, dst); |
| 257 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 258 | | } |
| 259 | | } |
| 260 | | |
| 261 | | void i386_device::i386_and_eax_i32() // Opcode 0x25 |
| 262 | | { |
| 263 | | UINT32 src, dst; |
| 264 | | src = FETCH32(); |
| 265 | | dst = REG32(EAX); |
| 266 | | dst = AND32(dst, src); |
| 267 | | REG32(EAX) = dst; |
| 268 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 269 | | } |
| 270 | | |
| 271 | | void i386_device::i386_bsf_r32_rm32() // Opcode 0x0f bc |
| 272 | | { |
| 273 | | UINT32 src, dst, temp; |
| 274 | | UINT8 modrm = FETCH(); |
| 275 | | |
| 276 | | if( modrm >= 0xc0 ) { |
| 277 | | src = LOAD_RM32(modrm); |
| 278 | | } else { |
| 279 | | UINT32 ea = GetEA(modrm,0); |
| 280 | | src = READ32(ea); |
| 281 | | } |
| 282 | | |
| 283 | | dst = 0; |
| 284 | | |
| 285 | | if( src == 0 ) { |
| 286 | | m_ZF = 1; |
| 287 | | } else { |
| 288 | | m_ZF = 0; |
| 289 | | temp = 0; |
| 290 | | while( (src & (1 << temp)) == 0 ) { |
| 291 | | temp++; |
| 292 | | dst = temp; |
| 293 | | CYCLES(CYCLES_BSF); |
| 294 | | } |
| 295 | | STORE_REG32(modrm, dst); |
| 296 | | } |
| 297 | | CYCLES(CYCLES_BSF_BASE); |
| 298 | | } |
| 299 | | |
| 300 | | void i386_device::i386_bsr_r32_rm32() // Opcode 0x0f bd |
| 301 | | { |
| 302 | | UINT32 src, dst, temp; |
| 303 | | UINT8 modrm = FETCH(); |
| 304 | | |
| 305 | | if( modrm >= 0xc0 ) { |
| 306 | | src = LOAD_RM32(modrm); |
| 307 | | } else { |
| 308 | | UINT32 ea = GetEA(modrm,0); |
| 309 | | src = READ32(ea); |
| 310 | | } |
| 311 | | |
| 312 | | dst = 0; |
| 313 | | |
| 314 | | if( src == 0 ) { |
| 315 | | m_ZF = 1; |
| 316 | | } else { |
| 317 | | m_ZF = 0; |
| 318 | | dst = temp = 31; |
| 319 | | while( (src & (1 << temp)) == 0 ) { |
| 320 | | temp--; |
| 321 | | dst = temp; |
| 322 | | CYCLES(CYCLES_BSR); |
| 323 | | } |
| 324 | | STORE_REG32(modrm, dst); |
| 325 | | } |
| 326 | | CYCLES(CYCLES_BSR_BASE); |
| 327 | | } |
| 328 | | |
| 329 | | void i386_device::i386_bt_rm32_r32() // Opcode 0x0f a3 |
| 330 | | { |
| 331 | | UINT8 modrm = FETCH(); |
| 332 | | if( modrm >= 0xc0 ) { |
| 333 | | UINT32 dst = LOAD_RM32(modrm); |
| 334 | | UINT32 bit = LOAD_REG32(modrm); |
| 335 | | |
| 336 | | if( dst & (1 << bit) ) |
| 337 | | m_CF = 1; |
| 338 | | else |
| 339 | | m_CF = 0; |
| 340 | | |
| 341 | | CYCLES(CYCLES_BT_REG_REG); |
| 342 | | } else { |
| 343 | | UINT8 segment; |
| 344 | | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 345 | | UINT32 bit = LOAD_REG32(modrm); |
| 346 | | ea += 4*(bit/32); |
| 347 | | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),0); |
| 348 | | bit %= 32; |
| 349 | | UINT32 dst = READ32(ea); |
| 350 | | |
| 351 | | if( dst & (1 << bit) ) |
| 352 | | m_CF = 1; |
| 353 | | else |
| 354 | | m_CF = 0; |
| 355 | | |
| 356 | | CYCLES(CYCLES_BT_REG_MEM); |
| 357 | | } |
| 358 | | } |
| 359 | | |
| 360 | | void i386_device::i386_btc_rm32_r32() // Opcode 0x0f bb |
| 361 | | { |
| 362 | | UINT8 modrm = FETCH(); |
| 363 | | if( modrm >= 0xc0 ) { |
| 364 | | UINT32 dst = LOAD_RM32(modrm); |
| 365 | | UINT32 bit = LOAD_REG32(modrm); |
| 366 | | |
| 367 | | if( dst & (1 << bit) ) |
| 368 | | m_CF = 1; |
| 369 | | else |
| 370 | | m_CF = 0; |
| 371 | | dst ^= (1 << bit); |
| 372 | | |
| 373 | | STORE_RM32(modrm, dst); |
| 374 | | CYCLES(CYCLES_BTC_REG_REG); |
| 375 | | } else { |
| 376 | | UINT8 segment; |
| 377 | | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 378 | | UINT32 bit = LOAD_REG32(modrm); |
| 379 | | ea += 4*(bit/32); |
| 380 | | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1); |
| 381 | | bit %= 32; |
| 382 | | UINT32 dst = READ32(ea); |
| 383 | | |
| 384 | | if( dst & (1 << bit) ) |
| 385 | | m_CF = 1; |
| 386 | | else |
| 387 | | m_CF = 0; |
| 388 | | dst ^= (1 << bit); |
| 389 | | |
| 390 | | WRITE32(ea, dst); |
| 391 | | CYCLES(CYCLES_BTC_REG_MEM); |
| 392 | | } |
| 393 | | } |
| 394 | | |
| 395 | | void i386_device::i386_btr_rm32_r32() // Opcode 0x0f b3 |
| 396 | | { |
| 397 | | UINT8 modrm = FETCH(); |
| 398 | | if( modrm >= 0xc0 ) { |
| 399 | | UINT32 dst = LOAD_RM32(modrm); |
| 400 | | UINT32 bit = LOAD_REG32(modrm); |
| 401 | | |
| 402 | | if( dst & (1 << bit) ) |
| 403 | | m_CF = 1; |
| 404 | | else |
| 405 | | m_CF = 0; |
| 406 | | dst &= ~(1 << bit); |
| 407 | | |
| 408 | | STORE_RM32(modrm, dst); |
| 409 | | CYCLES(CYCLES_BTR_REG_REG); |
| 410 | | } else { |
| 411 | | UINT8 segment; |
| 412 | | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 413 | | UINT32 bit = LOAD_REG32(modrm); |
| 414 | | ea += 4*(bit/32); |
| 415 | | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1); |
| 416 | | bit %= 32; |
| 417 | | UINT32 dst = READ32(ea); |
| 418 | | |
| 419 | | if( dst & (1 << bit) ) |
| 420 | | m_CF = 1; |
| 421 | | else |
| 422 | | m_CF = 0; |
| 423 | | dst &= ~(1 << bit); |
| 424 | | |
| 425 | | WRITE32(ea, dst); |
| 426 | | CYCLES(CYCLES_BTR_REG_MEM); |
| 427 | | } |
| 428 | | } |
| 429 | | |
| 430 | | void i386_device::i386_bts_rm32_r32() // Opcode 0x0f ab |
| 431 | | { |
| 432 | | UINT8 modrm = FETCH(); |
| 433 | | if( modrm >= 0xc0 ) { |
| 434 | | UINT32 dst = LOAD_RM32(modrm); |
| 435 | | UINT32 bit = LOAD_REG32(modrm); |
| 436 | | |
| 437 | | if( dst & (1 << bit) ) |
| 438 | | m_CF = 1; |
| 439 | | else |
| 440 | | m_CF = 0; |
| 441 | | dst |= (1 << bit); |
| 442 | | |
| 443 | | STORE_RM32(modrm, dst); |
| 444 | | CYCLES(CYCLES_BTS_REG_REG); |
| 445 | | } else { |
| 446 | | UINT8 segment; |
| 447 | | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 448 | | UINT32 bit = LOAD_REG32(modrm); |
| 449 | | ea += 4*(bit/32); |
| 450 | | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1); |
| 451 | | bit %= 32; |
| 452 | | UINT32 dst = READ32(ea); |
| 453 | | |
| 454 | | if( dst & (1 << bit) ) |
| 455 | | m_CF = 1; |
| 456 | | else |
| 457 | | m_CF = 0; |
| 458 | | dst |= (1 << bit); |
| 459 | | |
| 460 | | WRITE32(ea, dst); |
| 461 | | CYCLES(CYCLES_BTS_REG_MEM); |
| 462 | | } |
| 463 | | } |
| 464 | | |
| 465 | | void i386_device::i386_call_abs32() // Opcode 0x9a |
| 466 | | { |
| 467 | | UINT32 offset = FETCH32(); |
| 468 | | UINT16 ptr = FETCH16(); |
| 469 | | |
| 470 | | if(PROTECTED_MODE && !V8086_MODE) |
| 471 | | { |
| 472 | | i386_protected_mode_call(ptr,offset,0,1); |
| 473 | | } |
| 474 | | else |
| 475 | | { |
| 476 | | PUSH32(m_sreg[CS].selector ); |
| 477 | | PUSH32(m_eip ); |
| 478 | | m_sreg[CS].selector = ptr; |
| 479 | | m_performed_intersegment_jump = 1; |
| 480 | | m_eip = offset; |
| 481 | | i386_load_segment_descriptor(CS); |
| 482 | | } |
| 483 | | CYCLES(CYCLES_CALL_INTERSEG); |
| 484 | | CHANGE_PC(m_eip); |
| 485 | | } |
| 486 | | |
| 487 | | void i386_device::i386_call_rel32() // Opcode 0xe8 |
| 488 | | { |
| 489 | | INT32 disp = FETCH32(); |
| 490 | | PUSH32(m_eip ); |
| 491 | | m_eip += disp; |
| 492 | | CHANGE_PC(m_eip); |
| 493 | | CYCLES(CYCLES_CALL); /* TODO: Timing = 7 + m */ |
| 494 | | } |
| 495 | | |
| 496 | | void i386_device::i386_cdq() // Opcode 0x99 |
| 497 | | { |
| 498 | | if( REG32(EAX) & 0x80000000 ) { |
| 499 | | REG32(EDX) = 0xffffffff; |
| 500 | | } else { |
| 501 | | REG32(EDX) = 0x00000000; |
| 502 | | } |
| 503 | | CYCLES(CYCLES_CWD); |
| 504 | | } |
| 505 | | |
| 506 | | void i386_device::i386_cmp_rm32_r32() // Opcode 0x39 |
| 507 | | { |
| 508 | | UINT32 src, dst; |
| 509 | | UINT8 modrm = FETCH(); |
| 510 | | if( modrm >= 0xc0 ) { |
| 511 | | src = LOAD_REG32(modrm); |
| 512 | | dst = LOAD_RM32(modrm); |
| 513 | | SUB32(dst, src); |
| 514 | | CYCLES(CYCLES_CMP_REG_REG); |
| 515 | | } else { |
| 516 | | UINT32 ea = GetEA(modrm,0); |
| 517 | | src = LOAD_REG32(modrm); |
| 518 | | dst = READ32(ea); |
| 519 | | SUB32(dst, src); |
| 520 | | CYCLES(CYCLES_CMP_REG_MEM); |
| 521 | | } |
| 522 | | } |
| 523 | | |
| 524 | | void i386_device::i386_cmp_r32_rm32() // Opcode 0x3b |
| 525 | | { |
| 526 | | UINT32 src, dst; |
| 527 | | UINT8 modrm = FETCH(); |
| 528 | | if( modrm >= 0xc0 ) { |
| 529 | | src = LOAD_RM32(modrm); |
| 530 | | dst = LOAD_REG32(modrm); |
| 531 | | SUB32(dst, src); |
| 532 | | CYCLES(CYCLES_CMP_REG_REG); |
| 533 | | } else { |
| 534 | | UINT32 ea = GetEA(modrm,0); |
| 535 | | src = READ32(ea); |
| 536 | | dst = LOAD_REG32(modrm); |
| 537 | | SUB32(dst, src); |
| 538 | | CYCLES(CYCLES_CMP_MEM_REG); |
| 539 | | } |
| 540 | | } |
| 541 | | |
| 542 | | void i386_device::i386_cmp_eax_i32() // Opcode 0x3d |
| 543 | | { |
| 544 | | UINT32 src, dst; |
| 545 | | src = FETCH32(); |
| 546 | | dst = REG32(EAX); |
| 547 | | SUB32(dst, src); |
| 548 | | CYCLES(CYCLES_CMP_IMM_ACC); |
| 549 | | } |
| 550 | | |
| 551 | | void i386_device::i386_cmpsd() // Opcode 0xa7 |
| 552 | | { |
| 553 | | UINT32 eas, ead, src, dst; |
| 554 | | if( m_segment_prefix ) { |
| 555 | | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 556 | | } else { |
| 557 | | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 558 | | } |
| 559 | | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 ); |
| 560 | | src = READ32(eas); |
| 561 | | dst = READ32(ead); |
| 562 | | SUB32(src,dst); |
| 563 | | BUMP_SI(4); |
| 564 | | BUMP_DI(4); |
| 565 | | CYCLES(CYCLES_CMPS); |
| 566 | | } |
| 567 | | |
| 568 | | void i386_device::i386_cwde() // Opcode 0x98 |
| 569 | | { |
| 570 | | REG32(EAX) = (INT32)((INT16)REG16(AX)); |
| 571 | | CYCLES(CYCLES_CBW); |
| 572 | | } |
| 573 | | |
| 574 | | void i386_device::i386_dec_eax() // Opcode 0x48 |
| 575 | | { |
| 576 | | REG32(EAX) = DEC32(REG32(EAX) ); |
| 577 | | CYCLES(CYCLES_DEC_REG); |
| 578 | | } |
| 579 | | |
| 580 | | void i386_device::i386_dec_ecx() // Opcode 0x49 |
| 581 | | { |
| 582 | | REG32(ECX) = DEC32(REG32(ECX) ); |
| 583 | | CYCLES(CYCLES_DEC_REG); |
| 584 | | } |
| 585 | | |
| 586 | | void i386_device::i386_dec_edx() // Opcode 0x4a |
| 587 | | { |
| 588 | | REG32(EDX) = DEC32(REG32(EDX) ); |
| 589 | | CYCLES(CYCLES_DEC_REG); |
| 590 | | } |
| 591 | | |
| 592 | | void i386_device::i386_dec_ebx() // Opcode 0x4b |
| 593 | | { |
| 594 | | REG32(EBX) = DEC32(REG32(EBX) ); |
| 595 | | CYCLES(CYCLES_DEC_REG); |
| 596 | | } |
| 597 | | |
| 598 | | void i386_device::i386_dec_esp() // Opcode 0x4c |
| 599 | | { |
| 600 | | REG32(ESP) = DEC32(REG32(ESP) ); |
| 601 | | CYCLES(CYCLES_DEC_REG); |
| 602 | | } |
| 603 | | |
| 604 | | void i386_device::i386_dec_ebp() // Opcode 0x4d |
| 605 | | { |
| 606 | | REG32(EBP) = DEC32(REG32(EBP) ); |
| 607 | | CYCLES(CYCLES_DEC_REG); |
| 608 | | } |
| 609 | | |
| 610 | | void i386_device::i386_dec_esi() // Opcode 0x4e |
| 611 | | { |
| 612 | | REG32(ESI) = DEC32(REG32(ESI) ); |
| 613 | | CYCLES(CYCLES_DEC_REG); |
| 614 | | } |
| 615 | | |
| 616 | | void i386_device::i386_dec_edi() // Opcode 0x4f |
| 617 | | { |
| 618 | | REG32(EDI) = DEC32(REG32(EDI) ); |
| 619 | | CYCLES(CYCLES_DEC_REG); |
| 620 | | } |
| 621 | | |
| 622 | | void i386_device::i386_imul_r32_rm32() // Opcode 0x0f af |
| 623 | | { |
| 624 | | UINT8 modrm = FETCH(); |
| 625 | | INT64 result; |
| 626 | | INT64 src, dst; |
| 627 | | if( modrm >= 0xc0 ) { |
| 628 | | src = (INT64)(INT32)LOAD_RM32(modrm); |
| 629 | | CYCLES(CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */ |
| 630 | | } else { |
| 631 | | UINT32 ea = GetEA(modrm,0); |
| 632 | | src = (INT64)(INT32)READ32(ea); |
| 633 | | CYCLES(CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */ |
| 634 | | } |
| 635 | | |
| 636 | | dst = (INT64)(INT32)LOAD_REG32(modrm); |
| 637 | | result = src * dst; |
| 638 | | |
| 639 | | STORE_REG32(modrm, (UINT32)result); |
| 640 | | |
| 641 | | m_CF = m_OF = !(result == (INT64)(INT32)result); |
| 642 | | } |
| 643 | | |
| 644 | | void i386_device::i386_imul_r32_rm32_i32() // Opcode 0x69 |
| 645 | | { |
| 646 | | UINT8 modrm = FETCH(); |
| 647 | | INT64 result; |
| 648 | | INT64 src, dst; |
| 649 | | if( modrm >= 0xc0 ) { |
| 650 | | dst = (INT64)(INT32)LOAD_RM32(modrm); |
| 651 | | CYCLES(CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */ |
| 652 | | } else { |
| 653 | | UINT32 ea = GetEA(modrm,0); |
| 654 | | dst = (INT64)(INT32)READ32(ea); |
| 655 | | CYCLES(CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */ |
| 656 | | } |
| 657 | | |
| 658 | | src = (INT64)(INT32)FETCH32(); |
| 659 | | result = src * dst; |
| 660 | | |
| 661 | | STORE_REG32(modrm, (UINT32)result); |
| 662 | | |
| 663 | | m_CF = m_OF = !(result == (INT64)(INT32)result); |
| 664 | | } |
| 665 | | |
| 666 | | void i386_device::i386_imul_r32_rm32_i8() // Opcode 0x6b |
| 667 | | { |
| 668 | | UINT8 modrm = FETCH(); |
| 669 | | INT64 result; |
| 670 | | INT64 src, dst; |
| 671 | | if( modrm >= 0xc0 ) { |
| 672 | | dst = (INT64)(INT32)LOAD_RM32(modrm); |
| 673 | | CYCLES(CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */ |
| 674 | | } else { |
| 675 | | UINT32 ea = GetEA(modrm,0); |
| 676 | | dst = (INT64)(INT32)READ32(ea); |
| 677 | | CYCLES(CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */ |
| 678 | | } |
| 679 | | |
| 680 | | src = (INT64)(INT8)FETCH(); |
| 681 | | result = src * dst; |
| 682 | | |
| 683 | | STORE_REG32(modrm, (UINT32)result); |
| 684 | | |
| 685 | | m_CF = m_OF = !(result == (INT64)(INT32)result); |
| 686 | | } |
| 687 | | |
| 688 | | void i386_device::i386_in_eax_i8() // Opcode 0xe5 |
| 689 | | { |
| 690 | | UINT16 port = FETCH(); |
| 691 | | UINT32 data = READPORT32(port); |
| 692 | | REG32(EAX) = data; |
| 693 | | CYCLES(CYCLES_IN_VAR); |
| 694 | | } |
| 695 | | |
| 696 | | void i386_device::i386_in_eax_dx() // Opcode 0xed |
| 697 | | { |
| 698 | | UINT16 port = REG16(DX); |
| 699 | | UINT32 data = READPORT32(port); |
| 700 | | REG32(EAX) = data; |
| 701 | | CYCLES(CYCLES_IN); |
| 702 | | } |
| 703 | | |
| 704 | | void i386_device::i386_inc_eax() // Opcode 0x40 |
| 705 | | { |
| 706 | | REG32(EAX) = INC32(REG32(EAX) ); |
| 707 | | CYCLES(CYCLES_INC_REG); |
| 708 | | } |
| 709 | | |
| 710 | | void i386_device::i386_inc_ecx() // Opcode 0x41 |
| 711 | | { |
| 712 | | REG32(ECX) = INC32(REG32(ECX) ); |
| 713 | | CYCLES(CYCLES_INC_REG); |
| 714 | | } |
| 715 | | |
| 716 | | void i386_device::i386_inc_edx() // Opcode 0x42 |
| 717 | | { |
| 718 | | REG32(EDX) = INC32(REG32(EDX) ); |
| 719 | | CYCLES(CYCLES_INC_REG); |
| 720 | | } |
| 721 | | |
| 722 | | void i386_device::i386_inc_ebx() // Opcode 0x43 |
| 723 | | { |
| 724 | | REG32(EBX) = INC32(REG32(EBX) ); |
| 725 | | CYCLES(CYCLES_INC_REG); |
| 726 | | } |
| 727 | | |
| 728 | | void i386_device::i386_inc_esp() // Opcode 0x44 |
| 729 | | { |
| 730 | | REG32(ESP) = INC32(REG32(ESP) ); |
| 731 | | CYCLES(CYCLES_INC_REG); |
| 732 | | } |
| 733 | | |
| 734 | | void i386_device::i386_inc_ebp() // Opcode 0x45 |
| 735 | | { |
| 736 | | REG32(EBP) = INC32(REG32(EBP) ); |
| 737 | | CYCLES(CYCLES_INC_REG); |
| 738 | | } |
| 739 | | |
| 740 | | void i386_device::i386_inc_esi() // Opcode 0x46 |
| 741 | | { |
| 742 | | REG32(ESI) = INC32(REG32(ESI) ); |
| 743 | | CYCLES(CYCLES_INC_REG); |
| 744 | | } |
| 745 | | |
| 746 | | void i386_device::i386_inc_edi() // Opcode 0x47 |
| 747 | | { |
| 748 | | REG32(EDI) = INC32(REG32(EDI) ); |
| 749 | | CYCLES(CYCLES_INC_REG); |
| 750 | | } |
| 751 | | |
| 752 | | void i386_device::i386_iret32() // Opcode 0xcf |
| 753 | | { |
| 754 | | if( PROTECTED_MODE ) |
| 755 | | { |
| 756 | | i386_protected_mode_iret(1); |
| 757 | | } |
| 758 | | else |
| 759 | | { |
| 760 | | /* TODO: #SS(0) exception */ |
| 761 | | /* TODO: #GP(0) exception */ |
| 762 | | m_eip = POP32(); |
| 763 | | m_sreg[CS].selector = POP32() & 0xffff; |
| 764 | | set_flags(POP32() ); |
| 765 | | i386_load_segment_descriptor(CS); |
| 766 | | CHANGE_PC(m_eip); |
| 767 | | } |
| 768 | | CYCLES(CYCLES_IRET); |
| 769 | | } |
| 770 | | |
| 771 | | void i386_device::i386_ja_rel32() // Opcode 0x0f 87 |
| 772 | | { |
| 773 | | INT32 disp = FETCH32(); |
| 774 | | if( m_CF == 0 && m_ZF == 0 ) { |
| 775 | | m_eip += disp; |
| 776 | | CHANGE_PC(m_eip); |
| 777 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 778 | | } else { |
| 779 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 780 | | } |
| 781 | | } |
| 782 | | |
| 783 | | void i386_device::i386_jbe_rel32() // Opcode 0x0f 86 |
| 784 | | { |
| 785 | | INT32 disp = FETCH32(); |
| 786 | | if( m_CF != 0 || m_ZF != 0 ) { |
| 787 | | m_eip += disp; |
| 788 | | CHANGE_PC(m_eip); |
| 789 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 790 | | } else { |
| 791 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 792 | | } |
| 793 | | } |
| 794 | | |
| 795 | | void i386_device::i386_jc_rel32() // Opcode 0x0f 82 |
| 796 | | { |
| 797 | | INT32 disp = FETCH32(); |
| 798 | | if( m_CF != 0 ) { |
| 799 | | m_eip += disp; |
| 800 | | CHANGE_PC(m_eip); |
| 801 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 802 | | } else { |
| 803 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 804 | | } |
| 805 | | } |
| 806 | | |
| 807 | | void i386_device::i386_jg_rel32() // Opcode 0x0f 8f |
| 808 | | { |
| 809 | | INT32 disp = FETCH32(); |
| 810 | | if( m_ZF == 0 && (m_SF == m_OF) ) { |
| 811 | | m_eip += disp; |
| 812 | | CHANGE_PC(m_eip); |
| 813 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 814 | | } else { |
| 815 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 816 | | } |
| 817 | | } |
| 818 | | |
| 819 | | void i386_device::i386_jge_rel32() // Opcode 0x0f 8d |
| 820 | | { |
| 821 | | INT32 disp = FETCH32(); |
| 822 | | if(m_SF == m_OF) { |
| 823 | | m_eip += disp; |
| 824 | | CHANGE_PC(m_eip); |
| 825 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 826 | | } else { |
| 827 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 828 | | } |
| 829 | | } |
| 830 | | |
| 831 | | void i386_device::i386_jl_rel32() // Opcode 0x0f 8c |
| 832 | | { |
| 833 | | INT32 disp = FETCH32(); |
| 834 | | if( (m_SF != m_OF) ) { |
| 835 | | m_eip += disp; |
| 836 | | CHANGE_PC(m_eip); |
| 837 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 838 | | } else { |
| 839 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 840 | | } |
| 841 | | } |
| 842 | | |
| 843 | | void i386_device::i386_jle_rel32() // Opcode 0x0f 8e |
| 844 | | { |
| 845 | | INT32 disp = FETCH32(); |
| 846 | | if( m_ZF != 0 || (m_SF != m_OF) ) { |
| 847 | | m_eip += disp; |
| 848 | | CHANGE_PC(m_eip); |
| 849 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 850 | | } else { |
| 851 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 852 | | } |
| 853 | | } |
| 854 | | |
| 855 | | void i386_device::i386_jnc_rel32() // Opcode 0x0f 83 |
| 856 | | { |
| 857 | | INT32 disp = FETCH32(); |
| 858 | | if( m_CF == 0 ) { |
| 859 | | m_eip += disp; |
| 860 | | CHANGE_PC(m_eip); |
| 861 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 862 | | } else { |
| 863 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 864 | | } |
| 865 | | } |
| 866 | | |
| 867 | | void i386_device::i386_jno_rel32() // Opcode 0x0f 81 |
| 868 | | { |
| 869 | | INT32 disp = FETCH32(); |
| 870 | | if( m_OF == 0 ) { |
| 871 | | m_eip += disp; |
| 872 | | CHANGE_PC(m_eip); |
| 873 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 874 | | } else { |
| 875 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 876 | | } |
| 877 | | } |
| 878 | | |
| 879 | | void i386_device::i386_jnp_rel32() // Opcode 0x0f 8b |
| 880 | | { |
| 881 | | INT32 disp = FETCH32(); |
| 882 | | if( m_PF == 0 ) { |
| 883 | | m_eip += disp; |
| 884 | | CHANGE_PC(m_eip); |
| 885 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 886 | | } else { |
| 887 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 888 | | } |
| 889 | | } |
| 890 | | |
| 891 | | void i386_device::i386_jns_rel32() // Opcode 0x0f 89 |
| 892 | | { |
| 893 | | INT32 disp = FETCH32(); |
| 894 | | if( m_SF == 0 ) { |
| 895 | | m_eip += disp; |
| 896 | | CHANGE_PC(m_eip); |
| 897 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 898 | | } else { |
| 899 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 900 | | } |
| 901 | | } |
| 902 | | |
| 903 | | void i386_device::i386_jnz_rel32() // Opcode 0x0f 85 |
| 904 | | { |
| 905 | | INT32 disp = FETCH32(); |
| 906 | | if( m_ZF == 0 ) { |
| 907 | | m_eip += disp; |
| 908 | | CHANGE_PC(m_eip); |
| 909 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 910 | | } else { |
| 911 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 912 | | } |
| 913 | | } |
| 914 | | |
| 915 | | void i386_device::i386_jo_rel32() // Opcode 0x0f 80 |
| 916 | | { |
| 917 | | INT32 disp = FETCH32(); |
| 918 | | if( m_OF != 0 ) { |
| 919 | | m_eip += disp; |
| 920 | | CHANGE_PC(m_eip); |
| 921 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 922 | | } else { |
| 923 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 924 | | } |
| 925 | | } |
| 926 | | |
| 927 | | void i386_device::i386_jp_rel32() // Opcode 0x0f 8a |
| 928 | | { |
| 929 | | INT32 disp = FETCH32(); |
| 930 | | if( m_PF != 0 ) { |
| 931 | | m_eip += disp; |
| 932 | | CHANGE_PC(m_eip); |
| 933 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 934 | | } else { |
| 935 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 936 | | } |
| 937 | | } |
| 938 | | |
| 939 | | void i386_device::i386_js_rel32() // Opcode 0x0f 88 |
| 940 | | { |
| 941 | | INT32 disp = FETCH32(); |
| 942 | | if( m_SF != 0 ) { |
| 943 | | m_eip += disp; |
| 944 | | CHANGE_PC(m_eip); |
| 945 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 946 | | } else { |
| 947 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 948 | | } |
| 949 | | } |
| 950 | | |
| 951 | | void i386_device::i386_jz_rel32() // Opcode 0x0f 84 |
| 952 | | { |
| 953 | | INT32 disp = FETCH32(); |
| 954 | | if( m_ZF != 0 ) { |
| 955 | | m_eip += disp; |
| 956 | | CHANGE_PC(m_eip); |
| 957 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 958 | | } else { |
| 959 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 960 | | } |
| 961 | | } |
| 962 | | |
| 963 | | void i386_device::i386_jcxz32() // Opcode 0xe3 |
| 964 | | { |
| 965 | | INT8 disp = FETCH(); |
| 966 | | int val = (m_address_size)?(REG32(ECX) == 0):(REG16(CX) == 0); |
| 967 | | if( val ) { |
| 968 | | m_eip += disp; |
| 969 | | CHANGE_PC(m_eip); |
| 970 | | CYCLES(CYCLES_JCXZ); /* TODO: Timing = 9 + m */ |
| 971 | | } else { |
| 972 | | CYCLES(CYCLES_JCXZ_NOBRANCH); |
| 973 | | } |
| 974 | | } |
| 975 | | |
| 976 | | void i386_device::i386_jmp_rel32() // Opcode 0xe9 |
| 977 | | { |
| 978 | | UINT32 disp = FETCH32(); |
| 979 | | /* TODO: Segment limit */ |
| 980 | | m_eip += disp; |
| 981 | | CHANGE_PC(m_eip); |
| 982 | | CYCLES(CYCLES_JMP); /* TODO: Timing = 7 + m */ |
| 983 | | } |
| 984 | | |
| 985 | | void i386_device::i386_jmp_abs32() // Opcode 0xea |
| 986 | | { |
| 987 | | UINT32 address = FETCH32(); |
| 988 | | UINT16 segment = FETCH16(); |
| 989 | | |
| 990 | | if( PROTECTED_MODE && !V8086_MODE) |
| 991 | | { |
| 992 | | i386_protected_mode_jump(segment,address,0,1); |
| 993 | | } |
| 994 | | else |
| 995 | | { |
| 996 | | m_eip = address; |
| 997 | | m_sreg[CS].selector = segment; |
| 998 | | m_performed_intersegment_jump = 1; |
| 999 | | i386_load_segment_descriptor(CS); |
| 1000 | | CHANGE_PC(m_eip); |
| 1001 | | } |
| 1002 | | CYCLES(CYCLES_JMP_INTERSEG); |
| 1003 | | } |
| 1004 | | |
| 1005 | | void i386_device::i386_lea32() // Opcode 0x8d |
| 1006 | | { |
| 1007 | | UINT8 modrm = FETCH(); |
| 1008 | | UINT32 ea = GetNonTranslatedEA(modrm,NULL); |
| 1009 | | if (!m_address_size) |
| 1010 | | { |
| 1011 | | ea &= 0xffff; |
| 1012 | | } |
| 1013 | | STORE_REG32(modrm, ea); |
| 1014 | | CYCLES(CYCLES_LEA); |
| 1015 | | } |
| 1016 | | |
| 1017 | | void i386_device::i386_enter32() // Opcode 0xc8 |
| 1018 | | { |
| 1019 | | UINT16 framesize = FETCH16(); |
| 1020 | | UINT8 level = FETCH() % 32; |
| 1021 | | UINT8 x; |
| 1022 | | UINT32 frameptr; |
| 1023 | | PUSH32(REG32(EBP)); |
| 1024 | | if(!STACK_32BIT) |
| 1025 | | frameptr = REG16(SP); |
| 1026 | | else |
| 1027 | | frameptr = REG32(ESP); |
| 1028 | | |
| 1029 | | if(level > 0) |
| 1030 | | { |
| 1031 | | for(x=1;x<level-1;x++) |
| 1032 | | { |
| 1033 | | REG32(EBP) -= 4; |
| 1034 | | PUSH32(READ32(REG32(EBP))); |
| 1035 | | } |
| 1036 | | PUSH32(frameptr); |
| 1037 | | } |
| 1038 | | REG32(EBP) = frameptr; |
| 1039 | | if(!STACK_32BIT) |
| 1040 | | REG16(SP) -= framesize; |
| 1041 | | else |
| 1042 | | REG32(ESP) -= framesize; |
| 1043 | | CYCLES(CYCLES_ENTER); |
| 1044 | | } |
| 1045 | | |
| 1046 | | void i386_device::i386_leave32() // Opcode 0xc9 |
| 1047 | | { |
| 1048 | | if(!STACK_32BIT) |
| 1049 | | REG16(SP) = REG16(BP); |
| 1050 | | else |
| 1051 | | REG32(ESP) = REG32(EBP); |
| 1052 | | REG32(EBP) = POP32(); |
| 1053 | | CYCLES(CYCLES_LEAVE); |
| 1054 | | } |
| 1055 | | |
| 1056 | | void i386_device::i386_lodsd() // Opcode 0xad |
| 1057 | | { |
| 1058 | | UINT32 eas; |
| 1059 | | if( m_segment_prefix ) { |
| 1060 | | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1061 | | } else { |
| 1062 | | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1063 | | } |
| 1064 | | REG32(EAX) = READ32(eas); |
| 1065 | | BUMP_SI(4); |
| 1066 | | CYCLES(CYCLES_LODS); |
| 1067 | | } |
| 1068 | | |
| 1069 | | void i386_device::i386_loop32() // Opcode 0xe2 |
| 1070 | | { |
| 1071 | | INT8 disp = FETCH(); |
| 1072 | | INT32 reg = (m_address_size)?--REG32(ECX):--REG16(CX); |
| 1073 | | if( reg != 0 ) { |
| 1074 | | m_eip += disp; |
| 1075 | | CHANGE_PC(m_eip); |
| 1076 | | } |
| 1077 | | CYCLES(CYCLES_LOOP); /* TODO: Timing = 11 + m */ |
| 1078 | | } |
| 1079 | | |
| 1080 | | void i386_device::i386_loopne32() // Opcode 0xe0 |
| 1081 | | { |
| 1082 | | INT8 disp = FETCH(); |
| 1083 | | INT32 reg = (m_address_size)?--REG32(ECX):--REG16(CX); |
| 1084 | | if( reg != 0 && m_ZF == 0 ) { |
| 1085 | | m_eip += disp; |
| 1086 | | CHANGE_PC(m_eip); |
| 1087 | | } |
| 1088 | | CYCLES(CYCLES_LOOPNZ); /* TODO: Timing = 11 + m */ |
| 1089 | | } |
| 1090 | | |
| 1091 | | void i386_device::i386_loopz32() // Opcode 0xe1 |
| 1092 | | { |
| 1093 | | INT8 disp = FETCH(); |
| 1094 | | INT32 reg = (m_address_size)?--REG32(ECX):--REG16(CX); |
| 1095 | | if( reg != 0 && m_ZF != 0 ) { |
| 1096 | | m_eip += disp; |
| 1097 | | CHANGE_PC(m_eip); |
| 1098 | | } |
| 1099 | | CYCLES(CYCLES_LOOPZ); /* TODO: Timing = 11 + m */ |
| 1100 | | } |
| 1101 | | |
| 1102 | | void i386_device::i386_mov_rm32_r32() // Opcode 0x89 |
| 1103 | | { |
| 1104 | | UINT32 src; |
| 1105 | | UINT8 modrm = FETCH(); |
| 1106 | | if( modrm >= 0xc0 ) { |
| 1107 | | src = LOAD_REG32(modrm); |
| 1108 | | STORE_RM32(modrm, src); |
| 1109 | | CYCLES(CYCLES_MOV_REG_REG); |
| 1110 | | } else { |
| 1111 | | UINT32 ea = GetEA(modrm,1); |
| 1112 | | src = LOAD_REG32(modrm); |
| 1113 | | WRITE32(ea, src); |
| 1114 | | CYCLES(CYCLES_MOV_REG_MEM); |
| 1115 | | } |
| 1116 | | } |
| 1117 | | |
| 1118 | | void i386_device::i386_mov_r32_rm32() // Opcode 0x8b |
| 1119 | | { |
| 1120 | | UINT32 src; |
| 1121 | | UINT8 modrm = FETCH(); |
| 1122 | | if( modrm >= 0xc0 ) { |
| 1123 | | src = LOAD_RM32(modrm); |
| 1124 | | STORE_REG32(modrm, src); |
| 1125 | | CYCLES(CYCLES_MOV_REG_REG); |
| 1126 | | } else { |
| 1127 | | UINT32 ea = GetEA(modrm,0); |
| 1128 | | src = READ32(ea); |
| 1129 | | STORE_REG32(modrm, src); |
| 1130 | | CYCLES(CYCLES_MOV_MEM_REG); |
| 1131 | | } |
| 1132 | | } |
| 1133 | | |
| 1134 | | void i386_device::i386_mov_rm32_i32() // Opcode 0xc7 |
| 1135 | | { |
| 1136 | | UINT8 modrm = FETCH(); |
| 1137 | | if( modrm >= 0xc0 ) { |
| 1138 | | UINT32 value = FETCH32(); |
| 1139 | | STORE_RM32(modrm, value); |
| 1140 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1141 | | } else { |
| 1142 | | UINT32 ea = GetEA(modrm,1); |
| 1143 | | UINT32 value = FETCH32(); |
| 1144 | | WRITE32(ea, value); |
| 1145 | | CYCLES(CYCLES_MOV_IMM_MEM); |
| 1146 | | } |
| 1147 | | } |
| 1148 | | |
| 1149 | | void i386_device::i386_mov_eax_m32() // Opcode 0xa1 |
| 1150 | | { |
| 1151 | | UINT32 offset, ea; |
| 1152 | | if( m_address_size ) { |
| 1153 | | offset = FETCH32(); |
| 1154 | | } else { |
| 1155 | | offset = FETCH16(); |
| 1156 | | } |
| 1157 | | if( m_segment_prefix ) { |
| 1158 | | ea = i386_translate(m_segment_override, offset, 0 ); |
| 1159 | | } else { |
| 1160 | | ea = i386_translate(DS, offset, 0 ); |
| 1161 | | } |
| 1162 | | REG32(EAX) = READ32(ea); |
| 1163 | | CYCLES(CYCLES_MOV_MEM_ACC); |
| 1164 | | } |
| 1165 | | |
| 1166 | | void i386_device::i386_mov_m32_eax() // Opcode 0xa3 |
| 1167 | | { |
| 1168 | | UINT32 offset, ea; |
| 1169 | | if( m_address_size ) { |
| 1170 | | offset = FETCH32(); |
| 1171 | | } else { |
| 1172 | | offset = FETCH16(); |
| 1173 | | } |
| 1174 | | if( m_segment_prefix ) { |
| 1175 | | ea = i386_translate(m_segment_override, offset, 1 ); |
| 1176 | | } else { |
| 1177 | | ea = i386_translate(DS, offset, 1 ); |
| 1178 | | } |
| 1179 | | WRITE32(ea, REG32(EAX) ); |
| 1180 | | CYCLES(CYCLES_MOV_ACC_MEM); |
| 1181 | | } |
| 1182 | | |
| 1183 | | void i386_device::i386_mov_eax_i32() // Opcode 0xb8 |
| 1184 | | { |
| 1185 | | REG32(EAX) = FETCH32(); |
| 1186 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1187 | | } |
| 1188 | | |
| 1189 | | void i386_device::i386_mov_ecx_i32() // Opcode 0xb9 |
| 1190 | | { |
| 1191 | | REG32(ECX) = FETCH32(); |
| 1192 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1193 | | } |
| 1194 | | |
| 1195 | | void i386_device::i386_mov_edx_i32() // Opcode 0xba |
| 1196 | | { |
| 1197 | | REG32(EDX) = FETCH32(); |
| 1198 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1199 | | } |
| 1200 | | |
| 1201 | | void i386_device::i386_mov_ebx_i32() // Opcode 0xbb |
| 1202 | | { |
| 1203 | | REG32(EBX) = FETCH32(); |
| 1204 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1205 | | } |
| 1206 | | |
| 1207 | | void i386_device::i386_mov_esp_i32() // Opcode 0xbc |
| 1208 | | { |
| 1209 | | REG32(ESP) = FETCH32(); |
| 1210 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1211 | | } |
| 1212 | | |
| 1213 | | void i386_device::i386_mov_ebp_i32() // Opcode 0xbd |
| 1214 | | { |
| 1215 | | REG32(EBP) = FETCH32(); |
| 1216 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1217 | | } |
| 1218 | | |
| 1219 | | void i386_device::i386_mov_esi_i32() // Opcode 0xbe |
| 1220 | | { |
| 1221 | | REG32(ESI) = FETCH32(); |
| 1222 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1223 | | } |
| 1224 | | |
| 1225 | | void i386_device::i386_mov_edi_i32() // Opcode 0xbf |
| 1226 | | { |
| 1227 | | REG32(EDI) = FETCH32(); |
| 1228 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1229 | | } |
| 1230 | | |
| 1231 | | void i386_device::i386_movsd() // Opcode 0xa5 |
| 1232 | | { |
| 1233 | | UINT32 eas, ead, v; |
| 1234 | | if( m_segment_prefix ) { |
| 1235 | | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1236 | | } else { |
| 1237 | | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1238 | | } |
| 1239 | | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 1240 | | v = READ32(eas); |
| 1241 | | WRITE32(ead, v); |
| 1242 | | BUMP_SI(4); |
| 1243 | | BUMP_DI(4); |
| 1244 | | CYCLES(CYCLES_MOVS); |
| 1245 | | } |
| 1246 | | |
| 1247 | | void i386_device::i386_movsx_r32_rm8() // Opcode 0x0f be |
| 1248 | | { |
| 1249 | | UINT8 modrm = FETCH(); |
| 1250 | | if( modrm >= 0xc0 ) { |
| 1251 | | INT32 src = (INT8)LOAD_RM8(modrm); |
| 1252 | | STORE_REG32(modrm, src); |
| 1253 | | CYCLES(CYCLES_MOVSX_REG_REG); |
| 1254 | | } else { |
| 1255 | | UINT32 ea = GetEA(modrm,0); |
| 1256 | | INT32 src = (INT8)READ8(ea); |
| 1257 | | STORE_REG32(modrm, src); |
| 1258 | | CYCLES(CYCLES_MOVSX_MEM_REG); |
| 1259 | | } |
| 1260 | | } |
| 1261 | | |
| 1262 | | void i386_device::i386_movsx_r32_rm16() // Opcode 0x0f bf |
| 1263 | | { |
| 1264 | | UINT8 modrm = FETCH(); |
| 1265 | | if( modrm >= 0xc0 ) { |
| 1266 | | INT32 src = (INT16)LOAD_RM16(modrm); |
| 1267 | | STORE_REG32(modrm, src); |
| 1268 | | CYCLES(CYCLES_MOVSX_REG_REG); |
| 1269 | | } else { |
| 1270 | | UINT32 ea = GetEA(modrm,0); |
| 1271 | | INT32 src = (INT16)READ16(ea); |
| 1272 | | STORE_REG32(modrm, src); |
| 1273 | | CYCLES(CYCLES_MOVSX_MEM_REG); |
| 1274 | | } |
| 1275 | | } |
| 1276 | | |
| 1277 | | void i386_device::i386_movzx_r32_rm8() // Opcode 0x0f b6 |
| 1278 | | { |
| 1279 | | UINT8 modrm = FETCH(); |
| 1280 | | if( modrm >= 0xc0 ) { |
| 1281 | | UINT32 src = (UINT8)LOAD_RM8(modrm); |
| 1282 | | STORE_REG32(modrm, src); |
| 1283 | | CYCLES(CYCLES_MOVZX_REG_REG); |
| 1284 | | } else { |
| 1285 | | UINT32 ea = GetEA(modrm,0); |
| 1286 | | UINT32 src = (UINT8)READ8(ea); |
| 1287 | | STORE_REG32(modrm, src); |
| 1288 | | CYCLES(CYCLES_MOVZX_MEM_REG); |
| 1289 | | } |
| 1290 | | } |
| 1291 | | |
| 1292 | | void i386_device::i386_movzx_r32_rm16() // Opcode 0x0f b7 |
| 1293 | | { |
| 1294 | | UINT8 modrm = FETCH(); |
| 1295 | | if( modrm >= 0xc0 ) { |
| 1296 | | UINT32 src = (UINT16)LOAD_RM16(modrm); |
| 1297 | | STORE_REG32(modrm, src); |
| 1298 | | CYCLES(CYCLES_MOVZX_REG_REG); |
| 1299 | | } else { |
| 1300 | | UINT32 ea = GetEA(modrm,0); |
| 1301 | | UINT32 src = (UINT16)READ16(ea); |
| 1302 | | STORE_REG32(modrm, src); |
| 1303 | | CYCLES(CYCLES_MOVZX_MEM_REG); |
| 1304 | | } |
| 1305 | | } |
| 1306 | | |
| 1307 | | void i386_device::i386_or_rm32_r32() // Opcode 0x09 |
| 1308 | | { |
| 1309 | | UINT32 src, dst; |
| 1310 | | UINT8 modrm = FETCH(); |
| 1311 | | if( modrm >= 0xc0 ) { |
| 1312 | | src = LOAD_REG32(modrm); |
| 1313 | | dst = LOAD_RM32(modrm); |
| 1314 | | dst = OR32(dst, src); |
| 1315 | | STORE_RM32(modrm, dst); |
| 1316 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1317 | | } else { |
| 1318 | | UINT32 ea = GetEA(modrm,1); |
| 1319 | | src = LOAD_REG32(modrm); |
| 1320 | | dst = READ32(ea); |
| 1321 | | dst = OR32(dst, src); |
| 1322 | | WRITE32(ea, dst); |
| 1323 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1324 | | } |
| 1325 | | } |
| 1326 | | |
| 1327 | | void i386_device::i386_or_r32_rm32() // Opcode 0x0b |
| 1328 | | { |
| 1329 | | UINT32 src, dst; |
| 1330 | | UINT8 modrm = FETCH(); |
| 1331 | | if( modrm >= 0xc0 ) { |
| 1332 | | src = LOAD_RM32(modrm); |
| 1333 | | dst = LOAD_REG32(modrm); |
| 1334 | | dst = OR32(dst, src); |
| 1335 | | STORE_REG32(modrm, dst); |
| 1336 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1337 | | } else { |
| 1338 | | UINT32 ea = GetEA(modrm,0); |
| 1339 | | src = READ32(ea); |
| 1340 | | dst = LOAD_REG32(modrm); |
| 1341 | | dst = OR32(dst, src); |
| 1342 | | STORE_REG32(modrm, dst); |
| 1343 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 1344 | | } |
| 1345 | | } |
| 1346 | | |
| 1347 | | void i386_device::i386_or_eax_i32() // Opcode 0x0d |
| 1348 | | { |
| 1349 | | UINT32 src, dst; |
| 1350 | | src = FETCH32(); |
| 1351 | | dst = REG32(EAX); |
| 1352 | | dst = OR32(dst, src); |
| 1353 | | REG32(EAX) = dst; |
| 1354 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1355 | | } |
| 1356 | | |
| 1357 | | void i386_device::i386_out_eax_i8() // Opcode 0xe7 |
| 1358 | | { |
| 1359 | | UINT16 port = FETCH(); |
| 1360 | | UINT32 data = REG32(EAX); |
| 1361 | | WRITEPORT32(port, data); |
| 1362 | | CYCLES(CYCLES_OUT_VAR); |
| 1363 | | } |
| 1364 | | |
| 1365 | | void i386_device::i386_out_eax_dx() // Opcode 0xef |
| 1366 | | { |
| 1367 | | UINT16 port = REG16(DX); |
| 1368 | | UINT32 data = REG32(EAX); |
| 1369 | | WRITEPORT32(port, data); |
| 1370 | | CYCLES(CYCLES_OUT); |
| 1371 | | } |
| 1372 | | |
| 1373 | | void i386_device::i386_pop_eax() // Opcode 0x58 |
| 1374 | | { |
| 1375 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1376 | | if(i386_limit_check(SS,offset+3) == 0) |
| 1377 | | REG32(EAX) = POP32(); |
| 1378 | | else |
| 1379 | | FAULT(FAULT_SS,0) |
| 1380 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1381 | | } |
| 1382 | | |
| 1383 | | void i386_device::i386_pop_ecx() // Opcode 0x59 |
| 1384 | | { |
| 1385 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1386 | | if(i386_limit_check(SS,offset+3) == 0) |
| 1387 | | REG32(ECX) = POP32(); |
| 1388 | | else |
| 1389 | | FAULT(FAULT_SS,0) |
| 1390 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1391 | | } |
| 1392 | | |
| 1393 | | void i386_device::i386_pop_edx() // Opcode 0x5a |
| 1394 | | { |
| 1395 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1396 | | if(i386_limit_check(SS,offset+3) == 0) |
| 1397 | | REG32(EDX) = POP32(); |
| 1398 | | else |
| 1399 | | FAULT(FAULT_SS,0) |
| 1400 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1401 | | } |
| 1402 | | |
| 1403 | | void i386_device::i386_pop_ebx() // Opcode 0x5b |
| 1404 | | { |
| 1405 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1406 | | if(i386_limit_check(SS,offset+3) == 0) |
| 1407 | | REG32(EBX) = POP32(); |
| 1408 | | else |
| 1409 | | FAULT(FAULT_SS,0) |
| 1410 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1411 | | } |
| 1412 | | |
| 1413 | | void i386_device::i386_pop_esp() // Opcode 0x5c |
| 1414 | | { |
| 1415 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1416 | | if(i386_limit_check(SS,offset+3) == 0) |
| 1417 | | REG32(ESP) = POP32(); |
| 1418 | | else |
| 1419 | | FAULT(FAULT_SS,0) |
| 1420 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1421 | | } |
| 1422 | | |
| 1423 | | void i386_device::i386_pop_ebp() // Opcode 0x5d |
| 1424 | | { |
| 1425 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1426 | | if(i386_limit_check(SS,offset+3) == 0) |
| 1427 | | REG32(EBP) = POP32(); |
| 1428 | | else |
| 1429 | | FAULT(FAULT_SS,0) |
| 1430 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1431 | | } |
| 1432 | | |
| 1433 | | void i386_device::i386_pop_esi() // Opcode 0x5e |
| 1434 | | { |
| 1435 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1436 | | if(i386_limit_check(SS,offset+3) == 0) |
| 1437 | | REG32(ESI) = POP32(); |
| 1438 | | else |
| 1439 | | FAULT(FAULT_SS,0) |
| 1440 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1441 | | } |
| 1442 | | |
| 1443 | | void i386_device::i386_pop_edi() // Opcode 0x5f |
| 1444 | | { |
| 1445 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1446 | | if(i386_limit_check(SS,offset+3) == 0) |
| 1447 | | REG32(EDI) = POP32(); |
| 1448 | | else |
| 1449 | | FAULT(FAULT_SS,0) |
| 1450 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1451 | | } |
| 1452 | | |
| 1453 | | bool i386_device::i386_pop_seg32(int segment) |
| 1454 | | { |
| 1455 | | UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1456 | | UINT32 value; |
| 1457 | | bool fault; |
| 1458 | | if(i386_limit_check(SS,offset+3) == 0) |
| 1459 | | { |
| 1460 | | ea = i386_translate(SS, offset, 0); |
| 1461 | | value = READ32(ea); |
| 1462 | | i386_sreg_load(value, segment, &fault); |
| 1463 | | if(fault) return false; |
| 1464 | | if(STACK_32BIT) |
| 1465 | | REG32(ESP) = offset + 4; |
| 1466 | | else |
| 1467 | | REG16(SP) = offset + 4; |
| 1468 | | } |
| 1469 | | else |
| 1470 | | { |
| 1471 | | m_ext = 1; |
| 1472 | | i386_trap_with_error(FAULT_SS,0,0,0); |
| 1473 | | return false; |
| 1474 | | } |
| 1475 | | CYCLES(CYCLES_POP_SREG); |
| 1476 | | return true; |
| 1477 | | } |
| 1478 | | |
| 1479 | | void i386_device::i386_pop_ds32() // Opcode 0x1f |
| 1480 | | { |
| 1481 | | i386_pop_seg32(DS); |
| 1482 | | } |
| 1483 | | |
| 1484 | | void i386_device::i386_pop_es32() // Opcode 0x07 |
| 1485 | | { |
| 1486 | | i386_pop_seg32(ES); |
| 1487 | | } |
| 1488 | | |
| 1489 | | void i386_device::i386_pop_fs32() // Opcode 0x0f a1 |
| 1490 | | { |
| 1491 | | i386_pop_seg32(FS); |
| 1492 | | } |
| 1493 | | |
| 1494 | | void i386_device::i386_pop_gs32() // Opcode 0x0f a9 |
| 1495 | | { |
| 1496 | | i386_pop_seg32(GS); |
| 1497 | | } |
| 1498 | | |
| 1499 | | void i386_device::i386_pop_ss32() // Opcode 0x17 |
| 1500 | | { |
| 1501 | | if(!i386_pop_seg32(SS)) return; |
| 1502 | | if(m_IF != 0) // if external interrupts are enabled |
| 1503 | | { |
| 1504 | | m_IF = 0; // reset IF for the next instruction |
| 1505 | | m_delayed_interrupt_enable = 1; |
| 1506 | | } |
| 1507 | | } |
| 1508 | | |
| 1509 | | void i386_device::i386_pop_rm32() // Opcode 0x8f |
| 1510 | | { |
| 1511 | | UINT8 modrm = FETCH(); |
| 1512 | | UINT32 value; |
| 1513 | | UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1514 | | if(i386_limit_check(SS,offset+3) == 0) |
| 1515 | | { |
| 1516 | | // be careful here, if the write references the esp register |
| 1517 | | // it expects the post-pop value but esp must be wound back |
| 1518 | | // if the write faults |
| 1519 | | UINT32 temp_sp = REG32(ESP); |
| 1520 | | value = POP32(); |
| 1521 | | |
| 1522 | | if( modrm >= 0xc0 ) { |
| 1523 | | STORE_RM32(modrm, value); |
| 1524 | | } else { |
| 1525 | | ea = GetEA(modrm,1); |
| 1526 | | try |
| 1527 | | { |
| 1528 | | WRITE32(ea, value); |
| 1529 | | } |
| 1530 | | catch(UINT64 e) |
| 1531 | | { |
| 1532 | | REG32(ESP) = temp_sp; |
| 1533 | | throw e; |
| 1534 | | } |
| 1535 | | } |
| 1536 | | } |
| 1537 | | else |
| 1538 | | FAULT(FAULT_SS,0) |
| 1539 | | CYCLES(CYCLES_POP_RM); |
| 1540 | | } |
| 1541 | | |
| 1542 | | void i386_device::i386_popad() // Opcode 0x61 |
| 1543 | | { |
| 1544 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1545 | | if(i386_limit_check(SS,offset+31) == 0) |
| 1546 | | { |
| 1547 | | REG32(EDI) = POP32(); |
| 1548 | | REG32(ESI) = POP32(); |
| 1549 | | REG32(EBP) = POP32(); |
| 1550 | | REG32(ESP) += 4; |
| 1551 | | REG32(EBX) = POP32(); |
| 1552 | | REG32(EDX) = POP32(); |
| 1553 | | REG32(ECX) = POP32(); |
| 1554 | | REG32(EAX) = POP32(); |
| 1555 | | } |
| 1556 | | else |
| 1557 | | FAULT(FAULT_SS,0) |
| 1558 | | CYCLES(CYCLES_POPA); |
| 1559 | | } |
| 1560 | | |
| 1561 | | void i386_device::i386_popfd() // Opcode 0x9d |
| 1562 | | { |
| 1563 | | UINT32 value; |
| 1564 | | UINT32 current = get_flags(); |
| 1565 | | UINT8 IOPL = (current >> 12) & 0x03; |
| 1566 | | UINT32 mask = 0x00257fd5; // VM, VIP and VIF cannot be set by POPF/POPFD |
| 1567 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1568 | | |
| 1569 | | // IOPL can only change if CPL is 0 |
| 1570 | | if(m_CPL != 0) |
| 1571 | | mask &= ~0x00003000; |
| 1572 | | |
| 1573 | | // IF can only change if CPL is at least as privileged as IOPL |
| 1574 | | if(m_CPL > IOPL) |
| 1575 | | mask &= ~0x00000200; |
| 1576 | | |
| 1577 | | if(V8086_MODE) |
| 1578 | | { |
| 1579 | | if(IOPL < 3) |
| 1580 | | { |
| 1581 | | logerror("POPFD(%08x): IOPL < 3 while in V86 mode.\n",m_pc); |
| 1582 | | FAULT(FAULT_GP,0) // #GP(0) |
| 1583 | | } |
| 1584 | | mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode |
| 1585 | | } |
| 1586 | | |
| 1587 | | if(i386_limit_check(SS,offset+3) == 0) |
| 1588 | | { |
| 1589 | | value = POP32(); |
| 1590 | | value &= ~0x00010000; // RF will always return zero |
| 1591 | | set_flags((current & ~mask) | (value & mask)); // mask out reserved bits |
| 1592 | | } |
| 1593 | | else |
| 1594 | | FAULT(FAULT_SS,0) |
| 1595 | | CYCLES(CYCLES_POPF); |
| 1596 | | } |
| 1597 | | |
| 1598 | | void i386_device::i386_push_eax() // Opcode 0x50 |
| 1599 | | { |
| 1600 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1601 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1602 | | PUSH32(REG32(EAX) ); |
| 1603 | | else |
| 1604 | | FAULT(FAULT_SS,0) |
| 1605 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1606 | | } |
| 1607 | | |
| 1608 | | void i386_device::i386_push_ecx() // Opcode 0x51 |
| 1609 | | { |
| 1610 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1611 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1612 | | PUSH32(REG32(ECX) ); |
| 1613 | | else |
| 1614 | | FAULT(FAULT_SS,0) |
| 1615 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1616 | | } |
| 1617 | | |
| 1618 | | void i386_device::i386_push_edx() // Opcode 0x52 |
| 1619 | | { |
| 1620 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1621 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1622 | | PUSH32(REG32(EDX) ); |
| 1623 | | else |
| 1624 | | FAULT(FAULT_SS,0) |
| 1625 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1626 | | } |
| 1627 | | |
| 1628 | | void i386_device::i386_push_ebx() // Opcode 0x53 |
| 1629 | | { |
| 1630 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1631 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1632 | | PUSH32(REG32(EBX) ); |
| 1633 | | else |
| 1634 | | FAULT(FAULT_SS,0) |
| 1635 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1636 | | } |
| 1637 | | |
| 1638 | | void i386_device::i386_push_esp() // Opcode 0x54 |
| 1639 | | { |
| 1640 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1641 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1642 | | PUSH32(REG32(ESP) ); |
| 1643 | | else |
| 1644 | | FAULT(FAULT_SS,0) |
| 1645 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1646 | | } |
| 1647 | | |
| 1648 | | void i386_device::i386_push_ebp() // Opcode 0x55 |
| 1649 | | { |
| 1650 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1651 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1652 | | PUSH32(REG32(EBP) ); |
| 1653 | | else |
| 1654 | | FAULT(FAULT_SS,0) |
| 1655 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1656 | | } |
| 1657 | | |
| 1658 | | void i386_device::i386_push_esi() // Opcode 0x56 |
| 1659 | | { |
| 1660 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1661 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1662 | | PUSH32(REG32(ESI) ); |
| 1663 | | else |
| 1664 | | FAULT(FAULT_SS,0) |
| 1665 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1666 | | } |
| 1667 | | |
| 1668 | | void i386_device::i386_push_edi() // Opcode 0x57 |
| 1669 | | { |
| 1670 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1671 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1672 | | PUSH32(REG32(EDI) ); |
| 1673 | | else |
| 1674 | | FAULT(FAULT_SS,0) |
| 1675 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1676 | | } |
| 1677 | | |
| 1678 | | void i386_device::i386_push_cs32() // Opcode 0x0e |
| 1679 | | { |
| 1680 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1681 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1682 | | PUSH32(m_sreg[CS].selector ); |
| 1683 | | else |
| 1684 | | FAULT(FAULT_SS,0) |
| 1685 | | CYCLES(CYCLES_PUSH_SREG); |
| 1686 | | } |
| 1687 | | |
| 1688 | | void i386_device::i386_push_ds32() // Opcode 0x1e |
| 1689 | | { |
| 1690 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1691 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1692 | | PUSH32(m_sreg[DS].selector ); |
| 1693 | | else |
| 1694 | | FAULT(FAULT_SS,0) |
| 1695 | | CYCLES(CYCLES_PUSH_SREG); |
| 1696 | | } |
| 1697 | | |
| 1698 | | void i386_device::i386_push_es32() // Opcode 0x06 |
| 1699 | | { |
| 1700 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1701 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1702 | | PUSH32(m_sreg[ES].selector ); |
| 1703 | | else |
| 1704 | | FAULT(FAULT_SS,0) |
| 1705 | | CYCLES(CYCLES_PUSH_SREG); |
| 1706 | | } |
| 1707 | | |
| 1708 | | void i386_device::i386_push_fs32() // Opcode 0x0f a0 |
| 1709 | | { |
| 1710 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1711 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1712 | | PUSH32(m_sreg[FS].selector ); |
| 1713 | | else |
| 1714 | | FAULT(FAULT_SS,0) |
| 1715 | | CYCLES(CYCLES_PUSH_SREG); |
| 1716 | | } |
| 1717 | | |
| 1718 | | void i386_device::i386_push_gs32() // Opcode 0x0f a8 |
| 1719 | | { |
| 1720 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1721 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1722 | | PUSH32(m_sreg[GS].selector ); |
| 1723 | | else |
| 1724 | | FAULT(FAULT_SS,0) |
| 1725 | | CYCLES(CYCLES_PUSH_SREG); |
| 1726 | | } |
| 1727 | | |
| 1728 | | void i386_device::i386_push_ss32() // Opcode 0x16 |
| 1729 | | { |
| 1730 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1731 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1732 | | PUSH32(m_sreg[SS].selector ); |
| 1733 | | else |
| 1734 | | FAULT(FAULT_SS,0) |
| 1735 | | CYCLES(CYCLES_PUSH_SREG); |
| 1736 | | } |
| 1737 | | |
| 1738 | | void i386_device::i386_push_i32() // Opcode 0x68 |
| 1739 | | { |
| 1740 | | UINT32 value = FETCH32(); |
| 1741 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1742 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1743 | | PUSH32(value); |
| 1744 | | else |
| 1745 | | FAULT(FAULT_SS,0) |
| 1746 | | CYCLES(CYCLES_PUSH_IMM); |
| 1747 | | } |
| 1748 | | |
| 1749 | | void i386_device::i386_pushad() // Opcode 0x60 |
| 1750 | | { |
| 1751 | | UINT32 temp = REG32(ESP); |
| 1752 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1753 | | if(i386_limit_check(SS,offset-32) == 0) |
| 1754 | | { |
| 1755 | | PUSH32(REG32(EAX) ); |
| 1756 | | PUSH32(REG32(ECX) ); |
| 1757 | | PUSH32(REG32(EDX) ); |
| 1758 | | PUSH32(REG32(EBX) ); |
| 1759 | | PUSH32(temp ); |
| 1760 | | PUSH32(REG32(EBP) ); |
| 1761 | | PUSH32(REG32(ESI) ); |
| 1762 | | PUSH32(REG32(EDI) ); |
| 1763 | | } |
| 1764 | | else |
| 1765 | | FAULT(FAULT_SS,0) |
| 1766 | | CYCLES(CYCLES_PUSHA); |
| 1767 | | } |
| 1768 | | |
| 1769 | | void i386_device::i386_pushfd() // Opcode 0x9c |
| 1770 | | { |
| 1771 | | if(!m_IOP1 && !m_IOP2 && V8086_MODE) |
| 1772 | | FAULT(FAULT_GP,0) |
| 1773 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1774 | | if(i386_limit_check(SS,offset-4) == 0) |
| 1775 | | PUSH32(get_flags() & 0x00fcffff ); |
| 1776 | | else |
| 1777 | | FAULT(FAULT_SS,0) |
| 1778 | | CYCLES(CYCLES_PUSHF); |
| 1779 | | } |
| 1780 | | |
| 1781 | | void i386_device::i386_ret_near32_i16() // Opcode 0xc2 |
| 1782 | | { |
| 1783 | | INT16 disp = FETCH16(); |
| 1784 | | m_eip = POP32(); |
| 1785 | | REG32(ESP) += disp; |
| 1786 | | CHANGE_PC(m_eip); |
| 1787 | | CYCLES(CYCLES_RET_IMM); /* TODO: Timing = 10 + m */ |
| 1788 | | } |
| 1789 | | |
| 1790 | | void i386_device::i386_ret_near32() // Opcode 0xc3 |
| 1791 | | { |
| 1792 | | m_eip = POP32(); |
| 1793 | | CHANGE_PC(m_eip); |
| 1794 | | CYCLES(CYCLES_RET); /* TODO: Timing = 10 + m */ |
| 1795 | | } |
| 1796 | | |
| 1797 | | void i386_device::i386_sbb_rm32_r32() // Opcode 0x19 |
| 1798 | | { |
| 1799 | | UINT32 src, dst; |
| 1800 | | UINT8 modrm = FETCH(); |
| 1801 | | if( modrm >= 0xc0 ) { |
| 1802 | | src = LOAD_REG32(modrm); |
| 1803 | | dst = LOAD_RM32(modrm); |
| 1804 | | dst = SBB32(dst, src, m_CF); |
| 1805 | | STORE_RM32(modrm, dst); |
| 1806 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1807 | | } else { |
| 1808 | | UINT32 ea = GetEA(modrm,1); |
| 1809 | | src = LOAD_REG32(modrm); |
| 1810 | | dst = READ32(ea); |
| 1811 | | dst = SBB32(dst, src, m_CF); |
| 1812 | | WRITE32(ea, dst); |
| 1813 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1814 | | } |
| 1815 | | } |
| 1816 | | |
| 1817 | | void i386_device::i386_sbb_r32_rm32() // Opcode 0x1b |
| 1818 | | { |
| 1819 | | UINT32 src, dst; |
| 1820 | | UINT8 modrm = FETCH(); |
| 1821 | | if( modrm >= 0xc0 ) { |
| 1822 | | src = LOAD_RM32(modrm); |
| 1823 | | dst = LOAD_REG32(modrm); |
| 1824 | | dst = SBB32(dst, src, m_CF); |
| 1825 | | STORE_REG32(modrm, dst); |
| 1826 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1827 | | } else { |
| 1828 | | UINT32 ea = GetEA(modrm,0); |
| 1829 | | src = READ32(ea); |
| 1830 | | dst = LOAD_REG32(modrm); |
| 1831 | | dst = SBB32(dst, src, m_CF); |
| 1832 | | STORE_REG32(modrm, dst); |
| 1833 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 1834 | | } |
| 1835 | | } |
| 1836 | | |
| 1837 | | void i386_device::i386_sbb_eax_i32() // Opcode 0x1d |
| 1838 | | { |
| 1839 | | UINT32 src, dst; |
| 1840 | | src = FETCH32(); |
| 1841 | | dst = REG32(EAX); |
| 1842 | | dst = SBB32(dst, src, m_CF); |
| 1843 | | REG32(EAX) = dst; |
| 1844 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1845 | | } |
| 1846 | | |
| 1847 | | void i386_device::i386_scasd() // Opcode 0xaf |
| 1848 | | { |
| 1849 | | UINT32 eas, src, dst; |
| 1850 | | eas = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 ); |
| 1851 | | src = READ32(eas); |
| 1852 | | dst = REG32(EAX); |
| 1853 | | SUB32(dst, src); |
| 1854 | | BUMP_DI(4); |
| 1855 | | CYCLES(CYCLES_SCAS); |
| 1856 | | } |
| 1857 | | |
| 1858 | | void i386_device::i386_shld32_i8() // Opcode 0x0f a4 |
| 1859 | | { |
| 1860 | | UINT8 modrm = FETCH(); |
| 1861 | | if( modrm >= 0xc0 ) { |
| 1862 | | UINT32 dst = LOAD_RM32(modrm); |
| 1863 | | UINT32 upper = LOAD_REG32(modrm); |
| 1864 | | UINT8 shift = FETCH(); |
| 1865 | | shift &= 31; |
| 1866 | | if( shift == 0 ) { |
| 1867 | | } else { |
| 1868 | | m_CF = (dst & (1 << (32-shift))) ? 1 : 0; |
| 1869 | | dst = (dst << shift) | (upper >> (32-shift)); |
| 1870 | | m_OF = m_CF ^ (dst >> 31); |
| 1871 | | SetSZPF32(dst); |
| 1872 | | } |
| 1873 | | STORE_RM32(modrm, dst); |
| 1874 | | CYCLES(CYCLES_SHLD_REG); |
| 1875 | | } else { |
| 1876 | | UINT32 ea = GetEA(modrm,1); |
| 1877 | | UINT32 dst = READ32(ea); |
| 1878 | | UINT32 upper = LOAD_REG32(modrm); |
| 1879 | | UINT8 shift = FETCH(); |
| 1880 | | shift &= 31; |
| 1881 | | if( shift == 0 ) { |
| 1882 | | } else { |
| 1883 | | m_CF = (dst & (1 << (32-shift))) ? 1 : 0; |
| 1884 | | dst = (dst << shift) | (upper >> (32-shift)); |
| 1885 | | m_OF = m_CF ^ (dst >> 31); |
| 1886 | | SetSZPF32(dst); |
| 1887 | | } |
| 1888 | | WRITE32(ea, dst); |
| 1889 | | CYCLES(CYCLES_SHLD_MEM); |
| 1890 | | } |
| 1891 | | } |
| 1892 | | |
| 1893 | | void i386_device::i386_shld32_cl() // Opcode 0x0f a5 |
| 1894 | | { |
| 1895 | | UINT8 modrm = FETCH(); |
| 1896 | | if( modrm >= 0xc0 ) { |
| 1897 | | UINT32 dst = LOAD_RM32(modrm); |
| 1898 | | UINT32 upper = LOAD_REG32(modrm); |
| 1899 | | UINT8 shift = REG8(CL); |
| 1900 | | shift &= 31; |
| 1901 | | if( shift == 0 ) { |
| 1902 | | } else { |
| 1903 | | m_CF = (dst & (1 << (32-shift))) ? 1 : 0; |
| 1904 | | dst = (dst << shift) | (upper >> (32-shift)); |
| 1905 | | m_OF = m_CF ^ (dst >> 31); |
| 1906 | | SetSZPF32(dst); |
| 1907 | | } |
| 1908 | | STORE_RM32(modrm, dst); |
| 1909 | | CYCLES(CYCLES_SHLD_REG); |
| 1910 | | } else { |
| 1911 | | UINT32 ea = GetEA(modrm,1); |
| 1912 | | UINT32 dst = READ32(ea); |
| 1913 | | UINT32 upper = LOAD_REG32(modrm); |
| 1914 | | UINT8 shift = REG8(CL); |
| 1915 | | shift &= 31; |
| 1916 | | if( shift == 0 ) { |
| 1917 | | } else { |
| 1918 | | m_CF = (dst & (1 << (32-shift))) ? 1 : 0; |
| 1919 | | dst = (dst << shift) | (upper >> (32-shift)); |
| 1920 | | m_OF = m_CF ^ (dst >> 31); |
| 1921 | | SetSZPF32(dst); |
| 1922 | | } |
| 1923 | | WRITE32(ea, dst); |
| 1924 | | CYCLES(CYCLES_SHLD_MEM); |
| 1925 | | } |
| 1926 | | } |
| 1927 | | |
| 1928 | | void i386_device::i386_shrd32_i8() // Opcode 0x0f ac |
| 1929 | | { |
| 1930 | | UINT8 modrm = FETCH(); |
| 1931 | | if( modrm >= 0xc0 ) { |
| 1932 | | UINT32 dst = LOAD_RM32(modrm); |
| 1933 | | UINT32 upper = LOAD_REG32(modrm); |
| 1934 | | UINT8 shift = FETCH(); |
| 1935 | | shift &= 31; |
| 1936 | | if( shift == 0 ) { |
| 1937 | | } else { |
| 1938 | | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 1939 | | dst = (dst >> shift) | (upper << (32-shift)); |
| 1940 | | m_OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 1941 | | SetSZPF32(dst); |
| 1942 | | } |
| 1943 | | STORE_RM32(modrm, dst); |
| 1944 | | CYCLES(CYCLES_SHRD_REG); |
| 1945 | | } else { |
| 1946 | | UINT32 ea = GetEA(modrm,1); |
| 1947 | | UINT32 dst = READ32(ea); |
| 1948 | | UINT32 upper = LOAD_REG32(modrm); |
| 1949 | | UINT8 shift = FETCH(); |
| 1950 | | shift &= 31; |
| 1951 | | if( shift == 0 ) { |
| 1952 | | } else { |
| 1953 | | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 1954 | | dst = (dst >> shift) | (upper << (32-shift)); |
| 1955 | | m_OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 1956 | | SetSZPF32(dst); |
| 1957 | | } |
| 1958 | | WRITE32(ea, dst); |
| 1959 | | CYCLES(CYCLES_SHRD_MEM); |
| 1960 | | } |
| 1961 | | } |
| 1962 | | |
| 1963 | | void i386_device::i386_shrd32_cl() // Opcode 0x0f ad |
| 1964 | | { |
| 1965 | | UINT8 modrm = FETCH(); |
| 1966 | | if( modrm >= 0xc0 ) { |
| 1967 | | UINT32 dst = LOAD_RM32(modrm); |
| 1968 | | UINT32 upper = LOAD_REG32(modrm); |
| 1969 | | UINT8 shift = REG8(CL); |
| 1970 | | shift &= 31; |
| 1971 | | if( shift == 0 ) { |
| 1972 | | } else { |
| 1973 | | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 1974 | | dst = (dst >> shift) | (upper << (32-shift)); |
| 1975 | | m_OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 1976 | | SetSZPF32(dst); |
| 1977 | | } |
| 1978 | | STORE_RM32(modrm, dst); |
| 1979 | | CYCLES(CYCLES_SHRD_REG); |
| 1980 | | } else { |
| 1981 | | UINT32 ea = GetEA(modrm,1); |
| 1982 | | UINT32 dst = READ32(ea); |
| 1983 | | UINT32 upper = LOAD_REG32(modrm); |
| 1984 | | UINT8 shift = REG8(CL); |
| 1985 | | shift &= 31; |
| 1986 | | if( shift == 0 ) { |
| 1987 | | } else { |
| 1988 | | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 1989 | | dst = (dst >> shift) | (upper << (32-shift)); |
| 1990 | | m_OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 1991 | | SetSZPF32(dst); |
| 1992 | | } |
| 1993 | | WRITE32(ea, dst); |
| 1994 | | CYCLES(CYCLES_SHRD_MEM); |
| 1995 | | } |
| 1996 | | } |
| 1997 | | |
| 1998 | | void i386_device::i386_stosd() // Opcode 0xab |
| 1999 | | { |
| 2000 | | UINT32 eas = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 2001 | | WRITE32(eas, REG32(EAX)); |
| 2002 | | BUMP_DI(4); |
| 2003 | | CYCLES(CYCLES_STOS); |
| 2004 | | } |
| 2005 | | |
| 2006 | | void i386_device::i386_sub_rm32_r32() // Opcode 0x29 |
| 2007 | | { |
| 2008 | | UINT32 src, dst; |
| 2009 | | UINT8 modrm = FETCH(); |
| 2010 | | if( modrm >= 0xc0 ) { |
| 2011 | | src = LOAD_REG32(modrm); |
| 2012 | | dst = LOAD_RM32(modrm); |
| 2013 | | dst = SUB32(dst, src); |
| 2014 | | STORE_RM32(modrm, dst); |
| 2015 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2016 | | } else { |
| 2017 | | UINT32 ea = GetEA(modrm,1); |
| 2018 | | src = LOAD_REG32(modrm); |
| 2019 | | dst = READ32(ea); |
| 2020 | | dst = SUB32(dst, src); |
| 2021 | | WRITE32(ea, dst); |
| 2022 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2023 | | } |
| 2024 | | } |
| 2025 | | |
| 2026 | | void i386_device::i386_sub_r32_rm32() // Opcode 0x2b |
| 2027 | | { |
| 2028 | | UINT32 src, dst; |
| 2029 | | UINT8 modrm = FETCH(); |
| 2030 | | if( modrm >= 0xc0 ) { |
| 2031 | | src = LOAD_RM32(modrm); |
| 2032 | | dst = LOAD_REG32(modrm); |
| 2033 | | dst = SUB32(dst, src); |
| 2034 | | STORE_REG32(modrm, dst); |
| 2035 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2036 | | } else { |
| 2037 | | UINT32 ea = GetEA(modrm,1); |
| 2038 | | src = READ32(ea); |
| 2039 | | dst = LOAD_REG32(modrm); |
| 2040 | | dst = SUB32(dst, src); |
| 2041 | | STORE_REG32(modrm, dst); |
| 2042 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 2043 | | } |
| 2044 | | } |
| 2045 | | |
| 2046 | | void i386_device::i386_sub_eax_i32() // Opcode 0x2d |
| 2047 | | { |
| 2048 | | UINT32 src, dst; |
| 2049 | | src = FETCH32(); |
| 2050 | | dst = REG32(EAX); |
| 2051 | | dst = SUB32(dst, src); |
| 2052 | | REG32(EAX) = dst; |
| 2053 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 2054 | | } |
| 2055 | | |
| 2056 | | void i386_device::i386_test_eax_i32() // Opcode 0xa9 |
| 2057 | | { |
| 2058 | | UINT32 src = FETCH32(); |
| 2059 | | UINT32 dst = REG32(EAX); |
| 2060 | | dst = src & dst; |
| 2061 | | SetSZPF32(dst); |
| 2062 | | m_CF = 0; |
| 2063 | | m_OF = 0; |
| 2064 | | CYCLES(CYCLES_TEST_IMM_ACC); |
| 2065 | | } |
| 2066 | | |
| 2067 | | void i386_device::i386_test_rm32_r32() // Opcode 0x85 |
| 2068 | | { |
| 2069 | | UINT32 src, dst; |
| 2070 | | UINT8 modrm = FETCH(); |
| 2071 | | if( modrm >= 0xc0 ) { |
| 2072 | | src = LOAD_REG32(modrm); |
| 2073 | | dst = LOAD_RM32(modrm); |
| 2074 | | dst = src & dst; |
| 2075 | | SetSZPF32(dst); |
| 2076 | | m_CF = 0; |
| 2077 | | m_OF = 0; |
| 2078 | | CYCLES(CYCLES_TEST_REG_REG); |
| 2079 | | } else { |
| 2080 | | UINT32 ea = GetEA(modrm,0); |
| 2081 | | src = LOAD_REG32(modrm); |
| 2082 | | dst = READ32(ea); |
| 2083 | | dst = src & dst; |
| 2084 | | SetSZPF32(dst); |
| 2085 | | m_CF = 0; |
| 2086 | | m_OF = 0; |
| 2087 | | CYCLES(CYCLES_TEST_REG_MEM); |
| 2088 | | } |
| 2089 | | } |
| 2090 | | |
| 2091 | | void i386_device::i386_xchg_eax_ecx() // Opcode 0x91 |
| 2092 | | { |
| 2093 | | UINT32 temp; |
| 2094 | | temp = REG32(EAX); |
| 2095 | | REG32(EAX) = REG32(ECX); |
| 2096 | | REG32(ECX) = temp; |
| 2097 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2098 | | } |
| 2099 | | |
| 2100 | | void i386_device::i386_xchg_eax_edx() // Opcode 0x92 |
| 2101 | | { |
| 2102 | | UINT32 temp; |
| 2103 | | temp = REG32(EAX); |
| 2104 | | REG32(EAX) = REG32(EDX); |
| 2105 | | REG32(EDX) = temp; |
| 2106 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2107 | | } |
| 2108 | | |
| 2109 | | void i386_device::i386_xchg_eax_ebx() // Opcode 0x93 |
| 2110 | | { |
| 2111 | | UINT32 temp; |
| 2112 | | temp = REG32(EAX); |
| 2113 | | REG32(EAX) = REG32(EBX); |
| 2114 | | REG32(EBX) = temp; |
| 2115 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2116 | | } |
| 2117 | | |
| 2118 | | void i386_device::i386_xchg_eax_esp() // Opcode 0x94 |
| 2119 | | { |
| 2120 | | UINT32 temp; |
| 2121 | | temp = REG32(EAX); |
| 2122 | | REG32(EAX) = REG32(ESP); |
| 2123 | | REG32(ESP) = temp; |
| 2124 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2125 | | } |
| 2126 | | |
| 2127 | | void i386_device::i386_xchg_eax_ebp() // Opcode 0x95 |
| 2128 | | { |
| 2129 | | UINT32 temp; |
| 2130 | | temp = REG32(EAX); |
| 2131 | | REG32(EAX) = REG32(EBP); |
| 2132 | | REG32(EBP) = temp; |
| 2133 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2134 | | } |
| 2135 | | |
| 2136 | | void i386_device::i386_xchg_eax_esi() // Opcode 0x96 |
| 2137 | | { |
| 2138 | | UINT32 temp; |
| 2139 | | temp = REG32(EAX); |
| 2140 | | REG32(EAX) = REG32(ESI); |
| 2141 | | REG32(ESI) = temp; |
| 2142 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2143 | | } |
| 2144 | | |
| 2145 | | void i386_device::i386_xchg_eax_edi() // Opcode 0x97 |
| 2146 | | { |
| 2147 | | UINT32 temp; |
| 2148 | | temp = REG32(EAX); |
| 2149 | | REG32(EAX) = REG32(EDI); |
| 2150 | | REG32(EDI) = temp; |
| 2151 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2152 | | } |
| 2153 | | |
| 2154 | | void i386_device::i386_xchg_r32_rm32() // Opcode 0x87 |
| 2155 | | { |
| 2156 | | UINT8 modrm = FETCH(); |
| 2157 | | if( modrm >= 0xc0 ) { |
| 2158 | | UINT32 src = LOAD_RM32(modrm); |
| 2159 | | UINT32 dst = LOAD_REG32(modrm); |
| 2160 | | STORE_REG32(modrm, src); |
| 2161 | | STORE_RM32(modrm, dst); |
| 2162 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2163 | | } else { |
| 2164 | | UINT32 ea = GetEA(modrm,1); |
| 2165 | | UINT32 src = READ32(ea); |
| 2166 | | UINT32 dst = LOAD_REG32(modrm); |
| 2167 | | WRITE32(ea, dst); |
| 2168 | | STORE_REG32(modrm, src); |
| 2169 | | CYCLES(CYCLES_XCHG_REG_MEM); |
| 2170 | | } |
| 2171 | | } |
| 2172 | | |
| 2173 | | void i386_device::i386_xor_rm32_r32() // Opcode 0x31 |
| 2174 | | { |
| 2175 | | UINT32 src, dst; |
| 2176 | | UINT8 modrm = FETCH(); |
| 2177 | | if( modrm >= 0xc0 ) { |
| 2178 | | src = LOAD_REG32(modrm); |
| 2179 | | dst = LOAD_RM32(modrm); |
| 2180 | | dst = XOR32(dst, src); |
| 2181 | | STORE_RM32(modrm, dst); |
| 2182 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2183 | | } else { |
| 2184 | | UINT32 ea = GetEA(modrm,1); |
| 2185 | | src = LOAD_REG32(modrm); |
| 2186 | | dst = READ32(ea); |
| 2187 | | dst = XOR32(dst, src); |
| 2188 | | WRITE32(ea, dst); |
| 2189 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2190 | | } |
| 2191 | | } |
| 2192 | | |
| 2193 | | void i386_device::i386_xor_r32_rm32() // Opcode 0x33 |
| 2194 | | { |
| 2195 | | UINT32 src, dst; |
| 2196 | | UINT8 modrm = FETCH(); |
| 2197 | | if( modrm >= 0xc0 ) { |
| 2198 | | src = LOAD_RM32(modrm); |
| 2199 | | dst = LOAD_REG32(modrm); |
| 2200 | | dst = XOR32(dst, src); |
| 2201 | | STORE_REG32(modrm, dst); |
| 2202 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2203 | | } else { |
| 2204 | | UINT32 ea = GetEA(modrm,0); |
| 2205 | | src = READ32(ea); |
| 2206 | | dst = LOAD_REG32(modrm); |
| 2207 | | dst = XOR32(dst, src); |
| 2208 | | STORE_REG32(modrm, dst); |
| 2209 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 2210 | | } |
| 2211 | | } |
| 2212 | | |
| 2213 | | void i386_device::i386_xor_eax_i32() // Opcode 0x35 |
| 2214 | | { |
| 2215 | | UINT32 src, dst; |
| 2216 | | src = FETCH32(); |
| 2217 | | dst = REG32(EAX); |
| 2218 | | dst = XOR32(dst, src); |
| 2219 | | REG32(EAX) = dst; |
| 2220 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 2221 | | } |
| 2222 | | |
| 2223 | | |
| 2224 | | |
| 2225 | | void i386_device::i386_group81_32() // Opcode 0x81 |
| 2226 | | { |
| 2227 | | UINT32 ea; |
| 2228 | | UINT32 src, dst; |
| 2229 | | UINT8 modrm = FETCH(); |
| 2230 | | |
| 2231 | | switch( (modrm >> 3) & 0x7 ) |
| 2232 | | { |
| 2233 | | case 0: // ADD Rm32, i32 |
| 2234 | | if( modrm >= 0xc0 ) { |
| 2235 | | dst = LOAD_RM32(modrm); |
| 2236 | | src = FETCH32(); |
| 2237 | | dst = ADD32(dst, src); |
| 2238 | | STORE_RM32(modrm, dst); |
| 2239 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2240 | | } else { |
| 2241 | | ea = GetEA(modrm,1); |
| 2242 | | dst = READ32(ea); |
| 2243 | | src = FETCH32(); |
| 2244 | | dst = ADD32(dst, src); |
| 2245 | | WRITE32(ea, dst); |
| 2246 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2247 | | } |
| 2248 | | break; |
| 2249 | | case 1: // OR Rm32, i32 |
| 2250 | | if( modrm >= 0xc0 ) { |
| 2251 | | dst = LOAD_RM32(modrm); |
| 2252 | | src = FETCH32(); |
| 2253 | | dst = OR32(dst, src); |
| 2254 | | STORE_RM32(modrm, dst); |
| 2255 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2256 | | } else { |
| 2257 | | ea = GetEA(modrm,1); |
| 2258 | | dst = READ32(ea); |
| 2259 | | src = FETCH32(); |
| 2260 | | dst = OR32(dst, src); |
| 2261 | | WRITE32(ea, dst); |
| 2262 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2263 | | } |
| 2264 | | break; |
| 2265 | | case 2: // ADC Rm32, i32 |
| 2266 | | if( modrm >= 0xc0 ) { |
| 2267 | | dst = LOAD_RM32(modrm); |
| 2268 | | src = FETCH32(); |
| 2269 | | dst = ADC32(dst, src, m_CF); |
| 2270 | | STORE_RM32(modrm, dst); |
| 2271 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2272 | | } else { |
| 2273 | | ea = GetEA(modrm,1); |
| 2274 | | dst = READ32(ea); |
| 2275 | | src = FETCH32(); |
| 2276 | | dst = ADC32(dst, src, m_CF); |
| 2277 | | WRITE32(ea, dst); |
| 2278 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2279 | | } |
| 2280 | | break; |
| 2281 | | case 3: // SBB Rm32, i32 |
| 2282 | | if( modrm >= 0xc0 ) { |
| 2283 | | dst = LOAD_RM32(modrm); |
| 2284 | | src = FETCH32(); |
| 2285 | | dst = SBB32(dst, src, m_CF); |
| 2286 | | STORE_RM32(modrm, dst); |
| 2287 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2288 | | } else { |
| 2289 | | ea = GetEA(modrm,1); |
| 2290 | | dst = READ32(ea); |
| 2291 | | src = FETCH32(); |
| 2292 | | dst = SBB32(dst, src, m_CF); |
| 2293 | | WRITE32(ea, dst); |
| 2294 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2295 | | } |
| 2296 | | break; |
| 2297 | | case 4: // AND Rm32, i32 |
| 2298 | | if( modrm >= 0xc0 ) { |
| 2299 | | dst = LOAD_RM32(modrm); |
| 2300 | | src = FETCH32(); |
| 2301 | | dst = AND32(dst, src); |
| 2302 | | STORE_RM32(modrm, dst); |
| 2303 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2304 | | } else { |
| 2305 | | ea = GetEA(modrm,1); |
| 2306 | | dst = READ32(ea); |
| 2307 | | src = FETCH32(); |
| 2308 | | dst = AND32(dst, src); |
| 2309 | | WRITE32(ea, dst); |
| 2310 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2311 | | } |
| 2312 | | break; |
| 2313 | | case 5: // SUB Rm32, i32 |
| 2314 | | if( modrm >= 0xc0 ) { |
| 2315 | | dst = LOAD_RM32(modrm); |
| 2316 | | src = FETCH32(); |
| 2317 | | dst = SUB32(dst, src); |
| 2318 | | STORE_RM32(modrm, dst); |
| 2319 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2320 | | } else { |
| 2321 | | ea = GetEA(modrm,1); |
| 2322 | | dst = READ32(ea); |
| 2323 | | src = FETCH32(); |
| 2324 | | dst = SUB32(dst, src); |
| 2325 | | WRITE32(ea, dst); |
| 2326 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2327 | | } |
| 2328 | | break; |
| 2329 | | case 6: // XOR Rm32, i32 |
| 2330 | | if( modrm >= 0xc0 ) { |
| 2331 | | dst = LOAD_RM32(modrm); |
| 2332 | | src = FETCH32(); |
| 2333 | | dst = XOR32(dst, src); |
| 2334 | | STORE_RM32(modrm, dst); |
| 2335 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2336 | | } else { |
| 2337 | | ea = GetEA(modrm,1); |
| 2338 | | dst = READ32(ea); |
| 2339 | | src = FETCH32(); |
| 2340 | | dst = XOR32(dst, src); |
| 2341 | | WRITE32(ea, dst); |
| 2342 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2343 | | } |
| 2344 | | break; |
| 2345 | | case 7: // CMP Rm32, i32 |
| 2346 | | if( modrm >= 0xc0 ) { |
| 2347 | | dst = LOAD_RM32(modrm); |
| 2348 | | src = FETCH32(); |
| 2349 | | SUB32(dst, src); |
| 2350 | | CYCLES(CYCLES_CMP_REG_REG); |
| 2351 | | } else { |
| 2352 | | ea = GetEA(modrm,0); |
| 2353 | | dst = READ32(ea); |
| 2354 | | src = FETCH32(); |
| 2355 | | SUB32(dst, src); |
| 2356 | | CYCLES(CYCLES_CMP_REG_MEM); |
| 2357 | | } |
| 2358 | | break; |
| 2359 | | } |
| 2360 | | } |
| 2361 | | |
| 2362 | | void i386_device::i386_group83_32() // Opcode 0x83 |
| 2363 | | { |
| 2364 | | UINT32 ea; |
| 2365 | | UINT32 src, dst; |
| 2366 | | UINT8 modrm = FETCH(); |
| 2367 | | |
| 2368 | | switch( (modrm >> 3) & 0x7 ) |
| 2369 | | { |
| 2370 | | case 0: // ADD Rm32, i32 |
| 2371 | | if( modrm >= 0xc0 ) { |
| 2372 | | dst = LOAD_RM32(modrm); |
| 2373 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2374 | | dst = ADD32(dst, src); |
| 2375 | | STORE_RM32(modrm, dst); |
| 2376 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2377 | | } else { |
| 2378 | | ea = GetEA(modrm,1); |
| 2379 | | dst = READ32(ea); |
| 2380 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2381 | | dst = ADD32(dst, src); |
| 2382 | | WRITE32(ea, dst); |
| 2383 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2384 | | } |
| 2385 | | break; |
| 2386 | | case 1: // OR Rm32, i32 |
| 2387 | | if( modrm >= 0xc0 ) { |
| 2388 | | dst = LOAD_RM32(modrm); |
| 2389 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2390 | | dst = OR32(dst, src); |
| 2391 | | STORE_RM32(modrm, dst); |
| 2392 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2393 | | } else { |
| 2394 | | ea = GetEA(modrm,1); |
| 2395 | | dst = READ32(ea); |
| 2396 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2397 | | dst = OR32(dst, src); |
| 2398 | | WRITE32(ea, dst); |
| 2399 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2400 | | } |
| 2401 | | break; |
| 2402 | | case 2: // ADC Rm32, i32 |
| 2403 | | if( modrm >= 0xc0 ) { |
| 2404 | | dst = LOAD_RM32(modrm); |
| 2405 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2406 | | dst = ADC32(dst, src, m_CF); |
| 2407 | | STORE_RM32(modrm, dst); |
| 2408 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2409 | | } else { |
| 2410 | | ea = GetEA(modrm,1); |
| 2411 | | dst = READ32(ea); |
| 2412 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2413 | | dst = ADC32(dst, src, m_CF); |
| 2414 | | WRITE32(ea, dst); |
| 2415 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2416 | | } |
| 2417 | | break; |
| 2418 | | case 3: // SBB Rm32, i32 |
| 2419 | | if( modrm >= 0xc0 ) { |
| 2420 | | dst = LOAD_RM32(modrm); |
| 2421 | | src = ((UINT32)(INT32)(INT8)FETCH()); |
| 2422 | | dst = SBB32(dst, src, m_CF); |
| 2423 | | STORE_RM32(modrm, dst); |
| 2424 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2425 | | } else { |
| 2426 | | ea = GetEA(modrm,1); |
| 2427 | | dst = READ32(ea); |
| 2428 | | src = ((UINT32)(INT32)(INT8)FETCH()); |
| 2429 | | dst = SBB32(dst, src, m_CF); |
| 2430 | | WRITE32(ea, dst); |
| 2431 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2432 | | } |
| 2433 | | break; |
| 2434 | | case 4: // AND Rm32, i32 |
| 2435 | | if( modrm >= 0xc0 ) { |
| 2436 | | dst = LOAD_RM32(modrm); |
| 2437 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2438 | | dst = AND32(dst, src); |
| 2439 | | STORE_RM32(modrm, dst); |
| 2440 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2441 | | } else { |
| 2442 | | ea = GetEA(modrm,1); |
| 2443 | | dst = READ32(ea); |
| 2444 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2445 | | dst = AND32(dst, src); |
| 2446 | | WRITE32(ea, dst); |
| 2447 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2448 | | } |
| 2449 | | break; |
| 2450 | | case 5: // SUB Rm32, i32 |
| 2451 | | if( modrm >= 0xc0 ) { |
| 2452 | | dst = LOAD_RM32(modrm); |
| 2453 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2454 | | dst = SUB32(dst, src); |
| 2455 | | STORE_RM32(modrm, dst); |
| 2456 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2457 | | } else { |
| 2458 | | ea = GetEA(modrm,1); |
| 2459 | | dst = READ32(ea); |
| 2460 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2461 | | dst = SUB32(dst, src); |
| 2462 | | WRITE32(ea, dst); |
| 2463 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2464 | | } |
| 2465 | | break; |
| 2466 | | case 6: // XOR Rm32, i32 |
| 2467 | | if( modrm >= 0xc0 ) { |
| 2468 | | dst = LOAD_RM32(modrm); |
| 2469 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2470 | | dst = XOR32(dst, src); |
| 2471 | | STORE_RM32(modrm, dst); |
| 2472 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2473 | | } else { |
| 2474 | | ea = GetEA(modrm,1); |
| 2475 | | dst = READ32(ea); |
| 2476 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2477 | | dst = XOR32(dst, src); |
| 2478 | | WRITE32(ea, dst); |
| 2479 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2480 | | } |
| 2481 | | break; |
| 2482 | | case 7: // CMP Rm32, i32 |
| 2483 | | if( modrm >= 0xc0 ) { |
| 2484 | | dst = LOAD_RM32(modrm); |
| 2485 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2486 | | SUB32(dst, src); |
| 2487 | | CYCLES(CYCLES_CMP_REG_REG); |
| 2488 | | } else { |
| 2489 | | ea = GetEA(modrm,0); |
| 2490 | | dst = READ32(ea); |
| 2491 | | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2492 | | SUB32(dst, src); |
| 2493 | | CYCLES(CYCLES_CMP_REG_MEM); |
| 2494 | | } |
| 2495 | | break; |
| 2496 | | } |
| 2497 | | } |
| 2498 | | |
| 2499 | | void i386_device::i386_groupC1_32() // Opcode 0xc1 |
| 2500 | | { |
| 2501 | | UINT32 dst; |
| 2502 | | UINT8 modrm = FETCH(); |
| 2503 | | UINT8 shift; |
| 2504 | | |
| 2505 | | if( modrm >= 0xc0 ) { |
| 2506 | | dst = LOAD_RM32(modrm); |
| 2507 | | shift = FETCH() & 0x1f; |
| 2508 | | dst = i386_shift_rotate32(modrm, dst, shift); |
| 2509 | | STORE_RM32(modrm, dst); |
| 2510 | | } else { |
| 2511 | | UINT32 ea = GetEA(modrm,1); |
| 2512 | | dst = READ32(ea); |
| 2513 | | shift = FETCH() & 0x1f; |
| 2514 | | dst = i386_shift_rotate32(modrm, dst, shift); |
| 2515 | | WRITE32(ea, dst); |
| 2516 | | } |
| 2517 | | } |
| 2518 | | |
| 2519 | | void i386_device::i386_groupD1_32() // Opcode 0xd1 |
| 2520 | | { |
| 2521 | | UINT32 dst; |
| 2522 | | UINT8 modrm = FETCH(); |
| 2523 | | |
| 2524 | | if( modrm >= 0xc0 ) { |
| 2525 | | dst = LOAD_RM32(modrm); |
| 2526 | | dst = i386_shift_rotate32(modrm, dst, 1); |
| 2527 | | STORE_RM32(modrm, dst); |
| 2528 | | } else { |
| 2529 | | UINT32 ea = GetEA(modrm,1); |
| 2530 | | dst = READ32(ea); |
| 2531 | | dst = i386_shift_rotate32(modrm, dst, 1); |
| 2532 | | WRITE32(ea, dst); |
| 2533 | | } |
| 2534 | | } |
| 2535 | | |
| 2536 | | void i386_device::i386_groupD3_32() // Opcode 0xd3 |
| 2537 | | { |
| 2538 | | UINT32 dst; |
| 2539 | | UINT8 modrm = FETCH(); |
| 2540 | | |
| 2541 | | if( modrm >= 0xc0 ) { |
| 2542 | | dst = LOAD_RM32(modrm); |
| 2543 | | dst = i386_shift_rotate32(modrm, dst, REG8(CL)); |
| 2544 | | STORE_RM32(modrm, dst); |
| 2545 | | } else { |
| 2546 | | UINT32 ea = GetEA(modrm,1); |
| 2547 | | dst = READ32(ea); |
| 2548 | | dst = i386_shift_rotate32(modrm, dst, REG8(CL)); |
| 2549 | | WRITE32(ea, dst); |
| 2550 | | } |
| 2551 | | } |
| 2552 | | |
| 2553 | | void i386_device::i386_groupF7_32() // Opcode 0xf7 |
| 2554 | | { |
| 2555 | | UINT8 modrm = FETCH(); |
| 2556 | | |
| 2557 | | switch( (modrm >> 3) & 0x7 ) |
| 2558 | | { |
| 2559 | | case 0: /* TEST Rm32, i32 */ |
| 2560 | | if( modrm >= 0xc0 ) { |
| 2561 | | UINT32 dst = LOAD_RM32(modrm); |
| 2562 | | UINT32 src = FETCH32(); |
| 2563 | | dst &= src; |
| 2564 | | m_CF = m_OF = m_AF = 0; |
| 2565 | | SetSZPF32(dst); |
| 2566 | | CYCLES(CYCLES_TEST_IMM_REG); |
| 2567 | | } else { |
| 2568 | | UINT32 ea = GetEA(modrm,0); |
| 2569 | | UINT32 dst = READ32(ea); |
| 2570 | | UINT32 src = FETCH32(); |
| 2571 | | dst &= src; |
| 2572 | | m_CF = m_OF = m_AF = 0; |
| 2573 | | SetSZPF32(dst); |
| 2574 | | CYCLES(CYCLES_TEST_IMM_MEM); |
| 2575 | | } |
| 2576 | | break; |
| 2577 | | case 2: /* NOT Rm32 */ |
| 2578 | | if( modrm >= 0xc0 ) { |
| 2579 | | UINT32 dst = LOAD_RM32(modrm); |
| 2580 | | dst = ~dst; |
| 2581 | | STORE_RM32(modrm, dst); |
| 2582 | | CYCLES(CYCLES_NOT_REG); |
| 2583 | | } else { |
| 2584 | | UINT32 ea = GetEA(modrm,1); |
| 2585 | | UINT32 dst = READ32(ea); |
| 2586 | | dst = ~dst; |
| 2587 | | WRITE32(ea, dst); |
| 2588 | | CYCLES(CYCLES_NOT_MEM); |
| 2589 | | } |
| 2590 | | break; |
| 2591 | | case 3: /* NEG Rm32 */ |
| 2592 | | if( modrm >= 0xc0 ) { |
| 2593 | | UINT32 dst = LOAD_RM32(modrm); |
| 2594 | | dst = SUB32(0, dst ); |
| 2595 | | STORE_RM32(modrm, dst); |
| 2596 | | CYCLES(CYCLES_NEG_REG); |
| 2597 | | } else { |
| 2598 | | UINT32 ea = GetEA(modrm,1); |
| 2599 | | UINT32 dst = READ32(ea); |
| 2600 | | dst = SUB32(0, dst ); |
| 2601 | | WRITE32(ea, dst); |
| 2602 | | CYCLES(CYCLES_NEG_MEM); |
| 2603 | | } |
| 2604 | | break; |
| 2605 | | case 4: /* MUL EAX, Rm32 */ |
| 2606 | | { |
| 2607 | | UINT64 result; |
| 2608 | | UINT32 src, dst; |
| 2609 | | if( modrm >= 0xc0 ) { |
| 2610 | | src = LOAD_RM32(modrm); |
| 2611 | | CYCLES(CYCLES_MUL32_ACC_REG); /* TODO: Correct multiply timing */ |
| 2612 | | } else { |
| 2613 | | UINT32 ea = GetEA(modrm,0); |
| 2614 | | src = READ32(ea); |
| 2615 | | CYCLES(CYCLES_MUL32_ACC_MEM); /* TODO: Correct multiply timing */ |
| 2616 | | } |
| 2617 | | |
| 2618 | | dst = REG32(EAX); |
| 2619 | | result = (UINT64)src * (UINT64)dst; |
| 2620 | | REG32(EDX) = (UINT32)(result >> 32); |
| 2621 | | REG32(EAX) = (UINT32)result; |
| 2622 | | |
| 2623 | | m_CF = m_OF = (REG32(EDX) != 0); |
| 2624 | | } |
| 2625 | | break; |
| 2626 | | case 5: /* IMUL EAX, Rm32 */ |
| 2627 | | { |
| 2628 | | INT64 result; |
| 2629 | | INT64 src, dst; |
| 2630 | | if( modrm >= 0xc0 ) { |
| 2631 | | src = (INT64)(INT32)LOAD_RM32(modrm); |
| 2632 | | CYCLES(CYCLES_IMUL32_ACC_REG); /* TODO: Correct multiply timing */ |
| 2633 | | } else { |
| 2634 | | UINT32 ea = GetEA(modrm,0); |
| 2635 | | src = (INT64)(INT32)READ32(ea); |
| 2636 | | CYCLES(CYCLES_IMUL32_ACC_MEM); /* TODO: Correct multiply timing */ |
| 2637 | | } |
| 2638 | | |
| 2639 | | dst = (INT64)(INT32)REG32(EAX); |
| 2640 | | result = src * dst; |
| 2641 | | |
| 2642 | | REG32(EDX) = (UINT32)(result >> 32); |
| 2643 | | REG32(EAX) = (UINT32)result; |
| 2644 | | |
| 2645 | | m_CF = m_OF = !(result == (INT64)(INT32)result); |
| 2646 | | } |
| 2647 | | break; |
| 2648 | | case 6: /* DIV EAX, Rm32 */ |
| 2649 | | { |
| 2650 | | UINT64 quotient, remainder, result; |
| 2651 | | UINT32 src; |
| 2652 | | if( modrm >= 0xc0 ) { |
| 2653 | | src = LOAD_RM32(modrm); |
| 2654 | | CYCLES(CYCLES_DIV32_ACC_REG); |
| 2655 | | } else { |
| 2656 | | UINT32 ea = GetEA(modrm,0); |
| 2657 | | src = READ32(ea); |
| 2658 | | CYCLES(CYCLES_DIV32_ACC_MEM); |
| 2659 | | } |
| 2660 | | |
| 2661 | | quotient = ((UINT64)(REG32(EDX)) << 32) | (UINT64)(REG32(EAX)); |
| 2662 | | if( src ) { |
| 2663 | | remainder = quotient % (UINT64)src; |
| 2664 | | result = quotient / (UINT64)src; |
| 2665 | | if( result > 0xffffffff ) { |
| 2666 | | /* TODO: Divide error */ |
| 2667 | | } else { |
| 2668 | | REG32(EDX) = (UINT32)remainder; |
| 2669 | | REG32(EAX) = (UINT32)result; |
| 2670 | | } |
| 2671 | | } else { |
| 2672 | | i386_trap(0, 0, 0); |
| 2673 | | } |
| 2674 | | } |
| 2675 | | break; |
| 2676 | | case 7: /* IDIV EAX, Rm32 */ |
| 2677 | | { |
| 2678 | | INT64 quotient, remainder, result; |
| 2679 | | UINT32 src; |
| 2680 | | if( modrm >= 0xc0 ) { |
| 2681 | | src = LOAD_RM32(modrm); |
| 2682 | | CYCLES(CYCLES_IDIV32_ACC_REG); |
| 2683 | | } else { |
| 2684 | | UINT32 ea = GetEA(modrm,0); |
| 2685 | | src = READ32(ea); |
| 2686 | | CYCLES(CYCLES_IDIV32_ACC_MEM); |
| 2687 | | } |
| 2688 | | |
| 2689 | | quotient = (((INT64)REG32(EDX)) << 32) | ((UINT64)REG32(EAX)); |
| 2690 | | if( src ) { |
| 2691 | | remainder = quotient % (INT64)(INT32)src; |
| 2692 | | result = quotient / (INT64)(INT32)src; |
| 2693 | | if( result > 0xffffffff ) { |
| 2694 | | /* TODO: Divide error */ |
| 2695 | | } else { |
| 2696 | | REG32(EDX) = (UINT32)remainder; |
| 2697 | | REG32(EAX) = (UINT32)result; |
| 2698 | | } |
| 2699 | | } else { |
| 2700 | | i386_trap(0, 0, 0); |
| 2701 | | } |
| 2702 | | } |
| 2703 | | break; |
| 2704 | | } |
| 2705 | | } |
| 2706 | | |
| 2707 | | void i386_device::i386_groupFF_32() // Opcode 0xff |
| 2708 | | { |
| 2709 | | UINT8 modrm = FETCH(); |
| 2710 | | |
| 2711 | | switch( (modrm >> 3) & 0x7 ) |
| 2712 | | { |
| 2713 | | case 0: /* INC Rm32 */ |
| 2714 | | if( modrm >= 0xc0 ) { |
| 2715 | | UINT32 dst = LOAD_RM32(modrm); |
| 2716 | | dst = INC32(dst); |
| 2717 | | STORE_RM32(modrm, dst); |
| 2718 | | CYCLES(CYCLES_INC_REG); |
| 2719 | | } else { |
| 2720 | | UINT32 ea = GetEA(modrm,1); |
| 2721 | | UINT32 dst = READ32(ea); |
| 2722 | | dst = INC32(dst); |
| 2723 | | WRITE32(ea, dst); |
| 2724 | | CYCLES(CYCLES_INC_MEM); |
| 2725 | | } |
| 2726 | | break; |
| 2727 | | case 1: /* DEC Rm32 */ |
| 2728 | | if( modrm >= 0xc0 ) { |
| 2729 | | UINT32 dst = LOAD_RM32(modrm); |
| 2730 | | dst = DEC32(dst); |
| 2731 | | STORE_RM32(modrm, dst); |
| 2732 | | CYCLES(CYCLES_DEC_REG); |
| 2733 | | } else { |
| 2734 | | UINT32 ea = GetEA(modrm,1); |
| 2735 | | UINT32 dst = READ32(ea); |
| 2736 | | dst = DEC32(dst); |
| 2737 | | WRITE32(ea, dst); |
| 2738 | | CYCLES(CYCLES_DEC_MEM); |
| 2739 | | } |
| 2740 | | break; |
| 2741 | | case 2: /* CALL Rm32 */ |
| 2742 | | { |
| 2743 | | UINT32 address; |
| 2744 | | if( modrm >= 0xc0 ) { |
| 2745 | | address = LOAD_RM32(modrm); |
| 2746 | | CYCLES(CYCLES_CALL_REG); /* TODO: Timing = 7 + m */ |
| 2747 | | } else { |
| 2748 | | UINT32 ea = GetEA(modrm,0); |
| 2749 | | address = READ32(ea); |
| 2750 | | CYCLES(CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */ |
| 2751 | | } |
| 2752 | | PUSH32(m_eip ); |
| 2753 | | m_eip = address; |
| 2754 | | CHANGE_PC(m_eip); |
| 2755 | | } |
| 2756 | | break; |
| 2757 | | case 3: /* CALL FAR Rm32 */ |
| 2758 | | { |
| 2759 | | UINT16 selector; |
| 2760 | | UINT32 address; |
| 2761 | | |
| 2762 | | if( modrm >= 0xc0 ) |
| 2763 | | { |
| 2764 | | report_invalid_modrm("groupFF_32", modrm); |
| 2765 | | } |
| 2766 | | else |
| 2767 | | { |
| 2768 | | UINT32 ea = GetEA(modrm,0); |
| 2769 | | address = READ32(ea + 0); |
| 2770 | | selector = READ16(ea + 4); |
| 2771 | | CYCLES(CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */ |
| 2772 | | if(PROTECTED_MODE && !V8086_MODE) |
| 2773 | | { |
| 2774 | | i386_protected_mode_call(selector,address,1,1); |
| 2775 | | } |
| 2776 | | else |
| 2777 | | { |
| 2778 | | PUSH32(m_sreg[CS].selector ); |
| 2779 | | PUSH32(m_eip ); |
| 2780 | | m_sreg[CS].selector = selector; |
| 2781 | | m_performed_intersegment_jump = 1; |
| 2782 | | i386_load_segment_descriptor(CS ); |
| 2783 | | m_eip = address; |
| 2784 | | CHANGE_PC(m_eip); |
| 2785 | | } |
| 2786 | | } |
| 2787 | | } |
| 2788 | | break; |
| 2789 | | case 4: /* JMP Rm32 */ |
| 2790 | | { |
| 2791 | | UINT32 address; |
| 2792 | | if( modrm >= 0xc0 ) { |
| 2793 | | address = LOAD_RM32(modrm); |
| 2794 | | CYCLES(CYCLES_JMP_REG); /* TODO: Timing = 7 + m */ |
| 2795 | | } else { |
| 2796 | | UINT32 ea = GetEA(modrm,0); |
| 2797 | | address = READ32(ea); |
| 2798 | | CYCLES(CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */ |
| 2799 | | } |
| 2800 | | m_eip = address; |
| 2801 | | CHANGE_PC(m_eip); |
| 2802 | | } |
| 2803 | | break; |
| 2804 | | case 5: /* JMP FAR Rm32 */ |
| 2805 | | { |
| 2806 | | UINT16 selector; |
| 2807 | | UINT32 address; |
| 2808 | | |
| 2809 | | if( modrm >= 0xc0 ) |
| 2810 | | { |
| 2811 | | report_invalid_modrm("groupFF_32", modrm); |
| 2812 | | } |
| 2813 | | else |
| 2814 | | { |
| 2815 | | UINT32 ea = GetEA(modrm,0); |
| 2816 | | address = READ32(ea + 0); |
| 2817 | | selector = READ16(ea + 4); |
| 2818 | | CYCLES(CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */ |
| 2819 | | if(PROTECTED_MODE && !V8086_MODE) |
| 2820 | | { |
| 2821 | | i386_protected_mode_jump(selector,address,1,1); |
| 2822 | | } |
| 2823 | | else |
| 2824 | | { |
| 2825 | | m_sreg[CS].selector = selector; |
| 2826 | | m_performed_intersegment_jump = 1; |
| 2827 | | i386_load_segment_descriptor(CS ); |
| 2828 | | m_eip = address; |
| 2829 | | CHANGE_PC(m_eip); |
| 2830 | | } |
| 2831 | | } |
| 2832 | | } |
| 2833 | | break; |
| 2834 | | case 6: /* PUSH Rm32 */ |
| 2835 | | { |
| 2836 | | UINT32 value; |
| 2837 | | if( modrm >= 0xc0 ) { |
| 2838 | | value = LOAD_RM32(modrm); |
| 2839 | | } else { |
| 2840 | | UINT32 ea = GetEA(modrm,0); |
| 2841 | | value = READ32(ea); |
| 2842 | | } |
| 2843 | | PUSH32(value); |
| 2844 | | CYCLES(CYCLES_PUSH_RM); |
| 2845 | | } |
| 2846 | | break; |
| 2847 | | default: |
| 2848 | | report_invalid_modrm("groupFF_32", modrm); |
| 2849 | | break; |
| 2850 | | } |
| 2851 | | } |
| 2852 | | |
| 2853 | | void i386_device::i386_group0F00_32() // Opcode 0x0f 00 |
| 2854 | | { |
| 2855 | | UINT32 address, ea; |
| 2856 | | UINT8 modrm = FETCH(); |
| 2857 | | I386_SREG seg; |
| 2858 | | UINT8 result; |
| 2859 | | |
| 2860 | | switch( (modrm >> 3) & 0x7 ) |
| 2861 | | { |
| 2862 | | case 0: /* SLDT */ |
| 2863 | | if ( PROTECTED_MODE && !V8086_MODE ) |
| 2864 | | { |
| 2865 | | if( modrm >= 0xc0 ) { |
| 2866 | | STORE_RM32(modrm, m_ldtr.segment); |
| 2867 | | CYCLES(CYCLES_SLDT_REG); |
| 2868 | | } else { |
| 2869 | | ea = GetEA(modrm,1); |
| 2870 | | WRITE16(ea, m_ldtr.segment); |
| 2871 | | CYCLES(CYCLES_SLDT_MEM); |
| 2872 | | } |
| 2873 | | } |
| 2874 | | else |
| 2875 | | { |
| 2876 | | i386_trap(6, 0, 0); |
| 2877 | | } |
| 2878 | | break; |
| 2879 | | case 1: /* STR */ |
| 2880 | | if ( PROTECTED_MODE && !V8086_MODE ) |
| 2881 | | { |
| 2882 | | if( modrm >= 0xc0 ) { |
| 2883 | | STORE_RM32(modrm, m_task.segment); |
| 2884 | | CYCLES(CYCLES_STR_REG); |
| 2885 | | } else { |
| 2886 | | ea = GetEA(modrm,1); |
| 2887 | | WRITE16(ea, m_task.segment); |
| 2888 | | CYCLES(CYCLES_STR_MEM); |
| 2889 | | } |
| 2890 | | } |
| 2891 | | else |
| 2892 | | { |
| 2893 | | i386_trap(6, 0, 0); |
| 2894 | | } |
| 2895 | | break; |
| 2896 | | case 2: /* LLDT */ |
| 2897 | | if ( PROTECTED_MODE && !V8086_MODE ) |
| 2898 | | { |
| 2899 | | if(m_CPL) |
| 2900 | | FAULT(FAULT_GP,0) |
| 2901 | | if( modrm >= 0xc0 ) { |
| 2902 | | address = LOAD_RM32(modrm); |
| 2903 | | m_ldtr.segment = address; |
| 2904 | | CYCLES(CYCLES_LLDT_REG); |
| 2905 | | } else { |
| 2906 | | ea = GetEA(modrm,0); |
| 2907 | | m_ldtr.segment = READ32(ea); |
| 2908 | | CYCLES(CYCLES_LLDT_MEM); |
| 2909 | | } |
| 2910 | | memset(&seg, 0, sizeof(seg)); |
| 2911 | | seg.selector = m_ldtr.segment; |
| 2912 | | i386_load_protected_mode_segment(&seg,NULL); |
| 2913 | | m_ldtr.limit = seg.limit; |
| 2914 | | m_ldtr.base = seg.base; |
| 2915 | | m_ldtr.flags = seg.flags; |
| 2916 | | } |
| 2917 | | else |
| 2918 | | { |
| 2919 | | i386_trap(6, 0, 0); |
| 2920 | | } |
| 2921 | | break; |
| 2922 | | |
| 2923 | | case 3: /* LTR */ |
| 2924 | | if ( PROTECTED_MODE && !V8086_MODE ) |
| 2925 | | { |
| 2926 | | if(m_CPL) |
| 2927 | | FAULT(FAULT_GP,0) |
| 2928 | | if( modrm >= 0xc0 ) { |
| 2929 | | address = LOAD_RM32(modrm); |
| 2930 | | m_task.segment = address; |
| 2931 | | CYCLES(CYCLES_LTR_REG); |
| 2932 | | } else { |
| 2933 | | ea = GetEA(modrm,0); |
| 2934 | | m_task.segment = READ32(ea); |
| 2935 | | CYCLES(CYCLES_LTR_MEM); |
| 2936 | | } |
| 2937 | | memset(&seg, 0, sizeof(seg)); |
| 2938 | | seg.selector = m_task.segment; |
| 2939 | | i386_load_protected_mode_segment(&seg,NULL); |
| 2940 | | m_task.limit = seg.limit; |
| 2941 | | m_task.base = seg.base; |
| 2942 | | m_task.flags = seg.flags; |
| 2943 | | } |
| 2944 | | else |
| 2945 | | { |
| 2946 | | i386_trap(6, 0, 0); |
| 2947 | | } |
| 2948 | | break; |
| 2949 | | |
| 2950 | | case 4: /* VERR */ |
| 2951 | | if ( PROTECTED_MODE && !V8086_MODE ) |
| 2952 | | { |
| 2953 | | if( modrm >= 0xc0 ) { |
| 2954 | | address = LOAD_RM32(modrm); |
| 2955 | | CYCLES(CYCLES_VERR_REG); |
| 2956 | | } else { |
| 2957 | | ea = GetEA(modrm,0); |
| 2958 | | address = READ32(ea); |
| 2959 | | CYCLES(CYCLES_VERR_MEM); |
| 2960 | | } |
| 2961 | | memset(&seg, 0, sizeof(seg)); |
| 2962 | | seg.selector = address; |
| 2963 | | result = i386_load_protected_mode_segment(&seg,NULL); |
| 2964 | | // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) |
| 2965 | | if(!(seg.flags & 0x10)) |
| 2966 | | result = 0; |
| 2967 | | // check that the segment is readable |
| 2968 | | if(seg.flags & 0x10) // is code or data segment |
| 2969 | | { |
| 2970 | | if(seg.flags & 0x08) // is code segment, so check if it's readable |
| 2971 | | { |
| 2972 | | if(!(seg.flags & 0x02)) |
| 2973 | | { |
| 2974 | | result = 0; |
| 2975 | | } |
| 2976 | | else |
| 2977 | | { // check if conforming, these are always readable, regardless of privilege |
| 2978 | | if(!(seg.flags & 0x04)) |
| 2979 | | { |
| 2980 | | // if not conforming, then we must check privilege levels (TODO: current privilege level check) |
| 2981 | | if(((seg.flags >> 5) & 0x03) < (address & 0x03)) |
| 2982 | | result = 0; |
| 2983 | | } |
| 2984 | | } |
| 2985 | | } |
| 2986 | | } |
| 2987 | | // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO) |
| 2988 | | SetZF(result); |
| 2989 | | } |
| 2990 | | else |
| 2991 | | { |
| 2992 | | i386_trap(6, 0, 0); |
| 2993 | | logerror("i386: VERR: Exception - Running in real mode or virtual 8086 mode.\n"); |
| 2994 | | } |
| 2995 | | break; |
| 2996 | | |
| 2997 | | case 5: /* VERW */ |
| 2998 | | if ( PROTECTED_MODE && !V8086_MODE ) |
| 2999 | | { |
| 3000 | | if( modrm >= 0xc0 ) { |
| 3001 | | address = LOAD_RM16(modrm); |
| 3002 | | CYCLES(CYCLES_VERW_REG); |
| 3003 | | } else { |
| 3004 | | ea = GetEA(modrm,0); |
| 3005 | | address = READ16(ea); |
| 3006 | | CYCLES(CYCLES_VERW_MEM); |
| 3007 | | } |
| 3008 | | memset(&seg, 0, sizeof(seg)); |
| 3009 | | seg.selector = address; |
| 3010 | | result = i386_load_protected_mode_segment(&seg,NULL); |
| 3011 | | // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) |
| 3012 | | if(!(seg.flags & 0x10)) |
| 3013 | | result = 0; |
| 3014 | | // check that the segment is writable |
| 3015 | | if(seg.flags & 0x10) // is code or data segment |
| 3016 | | { |
| 3017 | | if(seg.flags & 0x08) // is code segment (and thus, not writable) |
| 3018 | | { |
| 3019 | | result = 0; |
| 3020 | | } |
| 3021 | | else |
| 3022 | | { // is data segment |
| 3023 | | if(!(seg.flags & 0x02)) |
| 3024 | | result = 0; |
| 3025 | | } |
| 3026 | | } |
| 3027 | | // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO) |
| 3028 | | if(((seg.flags >> 5) & 0x03) < (address & 0x03)) |
| 3029 | | result = 0; |
| 3030 | | SetZF(result); |
| 3031 | | } |
| 3032 | | else |
| 3033 | | { |
| 3034 | | i386_trap(6, 0, 0); |
| 3035 | | logerror("i386: VERW: Exception - Running in real mode or virtual 8086 mode.\n"); |
| 3036 | | } |
| 3037 | | break; |
| 3038 | | |
| 3039 | | default: |
| 3040 | | report_invalid_modrm("group0F00_32", modrm); |
| 3041 | | break; |
| 3042 | | } |
| 3043 | | } |
| 3044 | | |
| 3045 | | void i386_device::i386_group0F01_32() // Opcode 0x0f 01 |
| 3046 | | { |
| 3047 | | UINT8 modrm = FETCH(); |
| 3048 | | UINT32 address, ea; |
| 3049 | | |
| 3050 | | switch( (modrm >> 3) & 0x7 ) |
| 3051 | | { |
| 3052 | | case 0: /* SGDT */ |
| 3053 | | { |
| 3054 | | if( modrm >= 0xc0 ) { |
| 3055 | | address = LOAD_RM32(modrm); |
| 3056 | | ea = i386_translate(CS, address, 1 ); |
| 3057 | | } else { |
| 3058 | | ea = GetEA(modrm,1); |
| 3059 | | } |
| 3060 | | WRITE16(ea, m_gdtr.limit); |
| 3061 | | WRITE32(ea + 2, m_gdtr.base); |
| 3062 | | CYCLES(CYCLES_SGDT); |
| 3063 | | break; |
| 3064 | | } |
| 3065 | | case 1: /* SIDT */ |
| 3066 | | { |
| 3067 | | if (modrm >= 0xc0) |
| 3068 | | { |
| 3069 | | address = LOAD_RM32(modrm); |
| 3070 | | ea = i386_translate(CS, address, 1 ); |
| 3071 | | } |
| 3072 | | else |
| 3073 | | { |
| 3074 | | ea = GetEA(modrm,1); |
| 3075 | | } |
| 3076 | | WRITE16(ea, m_idtr.limit); |
| 3077 | | WRITE32(ea + 2, m_idtr.base); |
| 3078 | | CYCLES(CYCLES_SIDT); |
| 3079 | | break; |
| 3080 | | } |
| 3081 | | case 2: /* LGDT */ |
| 3082 | | { |
| 3083 | | if(PROTECTED_MODE && m_CPL) |
| 3084 | | FAULT(FAULT_GP,0) |
| 3085 | | if( modrm >= 0xc0 ) { |
| 3086 | | address = LOAD_RM32(modrm); |
| 3087 | | ea = i386_translate(CS, address, 0 ); |
| 3088 | | } else { |
| 3089 | | ea = GetEA(modrm,0); |
| 3090 | | } |
| 3091 | | m_gdtr.limit = READ16(ea); |
| 3092 | | m_gdtr.base = READ32(ea + 2); |
| 3093 | | CYCLES(CYCLES_LGDT); |
| 3094 | | break; |
| 3095 | | } |
| 3096 | | case 3: /* LIDT */ |
| 3097 | | { |
| 3098 | | if(PROTECTED_MODE && m_CPL) |
| 3099 | | FAULT(FAULT_GP,0) |
| 3100 | | if( modrm >= 0xc0 ) { |
| 3101 | | address = LOAD_RM32(modrm); |
| 3102 | | ea = i386_translate(CS, address, 0 ); |
| 3103 | | } else { |
| 3104 | | ea = GetEA(modrm,0); |
| 3105 | | } |
| 3106 | | m_idtr.limit = READ16(ea); |
| 3107 | | m_idtr.base = READ32(ea + 2); |
| 3108 | | CYCLES(CYCLES_LIDT); |
| 3109 | | break; |
| 3110 | | } |
| 3111 | | case 4: /* SMSW */ |
| 3112 | | { |
| 3113 | | if( modrm >= 0xc0 ) { |
| 3114 | | // smsw stores all of cr0 into register |
| 3115 | | STORE_RM32(modrm, m_cr[0]); |
| 3116 | | CYCLES(CYCLES_SMSW_REG); |
| 3117 | | } else { |
| 3118 | | /* always 16-bit memory operand */ |
| 3119 | | ea = GetEA(modrm,1); |
| 3120 | | WRITE16(ea, m_cr[0]); |
| 3121 | | CYCLES(CYCLES_SMSW_MEM); |
| 3122 | | } |
| 3123 | | break; |
| 3124 | | } |
| 3125 | | case 6: /* LMSW */ |
| 3126 | | { |
| 3127 | | if(PROTECTED_MODE && m_CPL) |
| 3128 | | FAULT(FAULT_GP,0) |
| 3129 | | UINT16 b; |
| 3130 | | if( modrm >= 0xc0 ) { |
| 3131 | | b = LOAD_RM16(modrm); |
| 3132 | | CYCLES(CYCLES_LMSW_REG); |
| 3133 | | } else { |
| 3134 | | ea = GetEA(modrm,0); |
| 3135 | | CYCLES(CYCLES_LMSW_MEM); |
| 3136 | | b = READ16(ea); |
| 3137 | | } |
| 3138 | | if(PROTECTED_MODE) |
| 3139 | | b |= 0x0001; // cannot return to real mode using this instruction. |
| 3140 | | m_cr[0] &= ~0x0000000f; |
| 3141 | | m_cr[0] |= b & 0x0000000f; |
| 3142 | | break; |
| 3143 | | } |
| 3144 | | default: |
| 3145 | | report_invalid_modrm("group0F01_32", modrm); |
| 3146 | | break; |
| 3147 | | } |
| 3148 | | } |
| 3149 | | |
| 3150 | | void i386_device::i386_group0FBA_32() // Opcode 0x0f ba |
| 3151 | | { |
| 3152 | | UINT8 modrm = FETCH(); |
| 3153 | | |
| 3154 | | switch( (modrm >> 3) & 0x7 ) |
| 3155 | | { |
| 3156 | | case 4: /* BT Rm32, i8 */ |
| 3157 | | if( modrm >= 0xc0 ) { |
| 3158 | | UINT32 dst = LOAD_RM32(modrm); |
| 3159 | | UINT8 bit = FETCH(); |
| 3160 | | |
| 3161 | | if( dst & (1 << bit) ) |
| 3162 | | m_CF = 1; |
| 3163 | | else |
| 3164 | | m_CF = 0; |
| 3165 | | |
| 3166 | | CYCLES(CYCLES_BT_IMM_REG); |
| 3167 | | } else { |
| 3168 | | UINT32 ea = GetEA(modrm,0); |
| 3169 | | UINT32 dst = READ32(ea); |
| 3170 | | UINT8 bit = FETCH(); |
| 3171 | | |
| 3172 | | if( dst & (1 << bit) ) |
| 3173 | | m_CF = 1; |
| 3174 | | else |
| 3175 | | m_CF = 0; |
| 3176 | | |
| 3177 | | CYCLES(CYCLES_BT_IMM_MEM); |
| 3178 | | } |
| 3179 | | break; |
| 3180 | | case 5: /* BTS Rm32, i8 */ |
| 3181 | | if( modrm >= 0xc0 ) { |
| 3182 | | UINT32 dst = LOAD_RM32(modrm); |
| 3183 | | UINT8 bit = FETCH(); |
| 3184 | | |
| 3185 | | if( dst & (1 << bit) ) |
| 3186 | | m_CF = 1; |
| 3187 | | else |
| 3188 | | m_CF = 0; |
| 3189 | | dst |= (1 << bit); |
| 3190 | | |
| 3191 | | STORE_RM32(modrm, dst); |
| 3192 | | CYCLES(CYCLES_BTS_IMM_REG); |
| 3193 | | } else { |
| 3194 | | UINT32 ea = GetEA(modrm,1); |
| 3195 | | UINT32 dst = READ32(ea); |
| 3196 | | UINT8 bit = FETCH(); |
| 3197 | | |
| 3198 | | if( dst & (1 << bit) ) |
| 3199 | | m_CF = 1; |
| 3200 | | else |
| 3201 | | m_CF = 0; |
| 3202 | | dst |= (1 << bit); |
| 3203 | | |
| 3204 | | WRITE32(ea, dst); |
| 3205 | | CYCLES(CYCLES_BTS_IMM_MEM); |
| 3206 | | } |
| 3207 | | break; |
| 3208 | | case 6: /* BTR Rm32, i8 */ |
| 3209 | | if( modrm >= 0xc0 ) { |
| 3210 | | UINT32 dst = LOAD_RM32(modrm); |
| 3211 | | UINT8 bit = FETCH(); |
| 3212 | | |
| 3213 | | if( dst & (1 << bit) ) |
| 3214 | | m_CF = 1; |
| 3215 | | else |
| 3216 | | m_CF = 0; |
| 3217 | | dst &= ~(1 << bit); |
| 3218 | | |
| 3219 | | STORE_RM32(modrm, dst); |
| 3220 | | CYCLES(CYCLES_BTR_IMM_REG); |
| 3221 | | } else { |
| 3222 | | UINT32 ea = GetEA(modrm,1); |
| 3223 | | UINT32 dst = READ32(ea); |
| 3224 | | UINT8 bit = FETCH(); |
| 3225 | | |
| 3226 | | if( dst & (1 << bit) ) |
| 3227 | | m_CF = 1; |
| 3228 | | else |
| 3229 | | m_CF = 0; |
| 3230 | | dst &= ~(1 << bit); |
| 3231 | | |
| 3232 | | WRITE32(ea, dst); |
| 3233 | | CYCLES(CYCLES_BTR_IMM_MEM); |
| 3234 | | } |
| 3235 | | break; |
| 3236 | | case 7: /* BTC Rm32, i8 */ |
| 3237 | | if( modrm >= 0xc0 ) { |
| 3238 | | UINT32 dst = LOAD_RM32(modrm); |
| 3239 | | UINT8 bit = FETCH(); |
| 3240 | | |
| 3241 | | if( dst & (1 << bit) ) |
| 3242 | | m_CF = 1; |
| 3243 | | else |
| 3244 | | m_CF = 0; |
| 3245 | | dst ^= (1 << bit); |
| 3246 | | |
| 3247 | | STORE_RM32(modrm, dst); |
| 3248 | | CYCLES(CYCLES_BTC_IMM_REG); |
| 3249 | | } else { |
| 3250 | | UINT32 ea = GetEA(modrm,1); |
| 3251 | | UINT32 dst = READ32(ea); |
| 3252 | | UINT8 bit = FETCH(); |
| 3253 | | |
| 3254 | | if( dst & (1 << bit) ) |
| 3255 | | m_CF = 1; |
| 3256 | | else |
| 3257 | | m_CF = 0; |
| 3258 | | dst ^= (1 << bit); |
| 3259 | | |
| 3260 | | WRITE32(ea, dst); |
| 3261 | | CYCLES(CYCLES_BTC_IMM_MEM); |
| 3262 | | } |
| 3263 | | break; |
| 3264 | | default: |
| 3265 | | report_invalid_modrm("group0FBA_32", modrm); |
| 3266 | | break; |
| 3267 | | } |
| 3268 | | } |
| 3269 | | |
| 3270 | | void i386_device::i386_lar_r32_rm32() // Opcode 0x0f 0x02 |
| 3271 | | { |
| 3272 | | UINT8 modrm = FETCH(); |
| 3273 | | I386_SREG seg; |
| 3274 | | UINT8 type; |
| 3275 | | |
| 3276 | | if(PROTECTED_MODE && !V8086_MODE) |
| 3277 | | { |
| 3278 | | memset(&seg,0,sizeof(seg)); |
| 3279 | | if(modrm >= 0xc0) |
| 3280 | | { |
| 3281 | | seg.selector = LOAD_RM32(modrm); |
| 3282 | | CYCLES(CYCLES_LAR_REG); |
| 3283 | | } |
| 3284 | | else |
| 3285 | | { |
| 3286 | | UINT32 ea = GetEA(modrm,0); |
| 3287 | | seg.selector = READ32(ea); |
| 3288 | | CYCLES(CYCLES_LAR_MEM); |
| 3289 | | } |
| 3290 | | if(seg.selector == 0) |
| 3291 | | { |
| 3292 | | SetZF(0); // not a valid segment |
| 3293 | | } |
| 3294 | | else |
| 3295 | | { |
| 3296 | | UINT64 desc; |
| 3297 | | if(!i386_load_protected_mode_segment(&seg,&desc)) |
| 3298 | | { |
| 3299 | | SetZF(0); |
| 3300 | | return; |
| 3301 | | } |
| 3302 | | UINT8 DPL = (seg.flags >> 5) & 3; |
| 3303 | | if(((DPL < m_CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c)) |
| 3304 | | { |
| 3305 | | SetZF(0); |
| 3306 | | return; |
| 3307 | | } |
| 3308 | | if(!(seg.flags & 0x10)) // special segment |
| 3309 | | { |
| 3310 | | // check for invalid segment types |
| 3311 | | type = seg.flags & 0x000f; |
| 3312 | | if(type == 0x00 || type == 0x08 || type == 0x0a || type == 0x0d) |
| 3313 | | { |
| 3314 | | SetZF(0); // invalid segment type |
| 3315 | | } |
| 3316 | | else |
| 3317 | | { |
| 3318 | | STORE_REG32(modrm,(desc>>32) & 0x00ffff00); |
| 3319 | | SetZF(1); |
| 3320 | | } |
| 3321 | | } |
| 3322 | | else |
| 3323 | | { |
| 3324 | | STORE_REG32(modrm,(desc>>32) & 0x00ffff00); |
| 3325 | | SetZF(1); |
| 3326 | | } |
| 3327 | | } |
| 3328 | | } |
| 3329 | | else |
| 3330 | | { |
| 3331 | | // illegal opcode |
| 3332 | | i386_trap(6,0, 0); |
| 3333 | | logerror("i386: LAR: Exception - running in real mode or virtual 8086 mode.\n"); |
| 3334 | | } |
| 3335 | | } |
| 3336 | | |
| 3337 | | void i386_device::i386_lsl_r32_rm32() // Opcode 0x0f 0x03 |
| 3338 | | { |
| 3339 | | UINT8 modrm = FETCH(); |
| 3340 | | UINT32 limit; |
| 3341 | | I386_SREG seg; |
| 3342 | | |
| 3343 | | if(PROTECTED_MODE && !V8086_MODE) |
| 3344 | | { |
| 3345 | | memset(&seg, 0, sizeof(seg)); |
| 3346 | | if(modrm >= 0xc0) |
| 3347 | | { |
| 3348 | | seg.selector = LOAD_RM32(modrm); |
| 3349 | | } |
| 3350 | | else |
| 3351 | | { |
| 3352 | | UINT32 ea = GetEA(modrm,0); |
| 3353 | | seg.selector = READ32(ea); |
| 3354 | | } |
| 3355 | | if(seg.selector == 0) |
| 3356 | | { |
| 3357 | | SetZF(0); // not a valid segment |
| 3358 | | } |
| 3359 | | else |
| 3360 | | { |
| 3361 | | UINT8 type; |
| 3362 | | if(!i386_load_protected_mode_segment(&seg,NULL)) |
| 3363 | | { |
| 3364 | | SetZF(0); |
| 3365 | | return; |
| 3366 | | } |
| 3367 | | UINT8 DPL = (seg.flags >> 5) & 3; |
| 3368 | | if(((DPL < m_CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c)) |
| 3369 | | { |
| 3370 | | SetZF(0); |
| 3371 | | return; |
| 3372 | | } |
| 3373 | | type = seg.flags & 0x1f; |
| 3374 | | switch(type) |
| 3375 | | { |
| 3376 | | case 0: |
| 3377 | | case 4: |
| 3378 | | case 5: |
| 3379 | | case 6: |
| 3380 | | case 7: |
| 3381 | | case 8: |
| 3382 | | case 10: |
| 3383 | | case 12: |
| 3384 | | case 13: |
| 3385 | | case 14: |
| 3386 | | case 15: |
| 3387 | | SetZF(0); |
| 3388 | | return; |
| 3389 | | default: |
| 3390 | | limit = seg.limit; |
| 3391 | | STORE_REG32(modrm,limit); |
| 3392 | | SetZF(1); |
| 3393 | | } |
| 3394 | | } |
| 3395 | | } |
| 3396 | | else |
| 3397 | | i386_trap(6, 0, 0); |
| 3398 | | } |
| 3399 | | |
| 3400 | | void i386_device::i386_bound_r32_m32_m32() // Opcode 0x62 |
| 3401 | | { |
| 3402 | | UINT8 modrm; |
| 3403 | | INT32 val, low, high; |
| 3404 | | |
| 3405 | | modrm = FETCH(); |
| 3406 | | |
| 3407 | | if (modrm >= 0xc0) |
| 3408 | | { |
| 3409 | | low = high = LOAD_RM32(modrm); |
| 3410 | | } |
| 3411 | | else |
| 3412 | | { |
| 3413 | | UINT32 ea = GetEA(modrm,0); |
| 3414 | | low = READ32(ea + 0); |
| 3415 | | high = READ32(ea + 4); |
| 3416 | | } |
| 3417 | | val = LOAD_REG32(modrm); |
| 3418 | | |
| 3419 | | if ((val < low) || (val > high)) |
| 3420 | | { |
| 3421 | | CYCLES(CYCLES_BOUND_OUT_RANGE); |
| 3422 | | i386_trap(5, 0, 0); |
| 3423 | | } |
| 3424 | | else |
| 3425 | | { |
| 3426 | | CYCLES(CYCLES_BOUND_IN_RANGE); |
| 3427 | | } |
| 3428 | | } |
| 3429 | | |
| 3430 | | void i386_device::i386_retf32() // Opcode 0xcb |
| 3431 | | { |
| 3432 | | if(PROTECTED_MODE && !V8086_MODE) |
| 3433 | | { |
| 3434 | | i386_protected_mode_retf(0,1); |
| 3435 | | } |
| 3436 | | else |
| 3437 | | { |
| 3438 | | m_eip = POP32(); |
| 3439 | | m_sreg[CS].selector = POP32(); |
| 3440 | | i386_load_segment_descriptor(CS ); |
| 3441 | | CHANGE_PC(m_eip); |
| 3442 | | } |
| 3443 | | |
| 3444 | | CYCLES(CYCLES_RET_INTERSEG); |
| 3445 | | } |
| 3446 | | |
| 3447 | | void i386_device::i386_retf_i32() // Opcode 0xca |
| 3448 | | { |
| 3449 | | UINT16 count = FETCH16(); |
| 3450 | | |
| 3451 | | if(PROTECTED_MODE && !V8086_MODE) |
| 3452 | | { |
| 3453 | | i386_protected_mode_retf(count,1); |
| 3454 | | } |
| 3455 | | else |
| 3456 | | { |
| 3457 | | m_eip = POP32(); |
| 3458 | | m_sreg[CS].selector = POP32(); |
| 3459 | | i386_load_segment_descriptor(CS ); |
| 3460 | | CHANGE_PC(m_eip); |
| 3461 | | REG32(ESP) += count; |
| 3462 | | } |
| 3463 | | |
| 3464 | | CYCLES(CYCLES_RET_IMM_INTERSEG); |
| 3465 | | } |
| 3466 | | |
| 3467 | | void i386_device::i386_load_far_pointer32(int s) |
| 3468 | | { |
| 3469 | | UINT8 modrm = FETCH(); |
| 3470 | | UINT16 selector; |
| 3471 | | |
| 3472 | | if( modrm >= 0xc0 ) { |
| 3473 | | report_invalid_modrm("load_far_pointer32", modrm); |
| 3474 | | } else { |
| 3475 | | UINT32 ea = GetEA(modrm,0); |
| 3476 | | STORE_REG32(modrm, READ32(ea + 0)); |
| 3477 | | selector = READ16(ea + 4); |
| 3478 | | i386_sreg_load(selector,s,NULL); |
| 3479 | | } |
| 3480 | | } |
| 3481 | | |
| 3482 | | void i386_device::i386_lds32() // Opcode 0xc5 |
| 3483 | | { |
| 3484 | | i386_load_far_pointer32(DS); |
| 3485 | | CYCLES(CYCLES_LDS); |
| 3486 | | } |
| 3487 | | |
| 3488 | | void i386_device::i386_lss32() // Opcode 0x0f 0xb2 |
| 3489 | | { |
| 3490 | | i386_load_far_pointer32(SS); |
| 3491 | | CYCLES(CYCLES_LSS); |
| 3492 | | } |
| 3493 | | |
| 3494 | | void i386_device::i386_les32() // Opcode 0xc4 |
| 3495 | | { |
| 3496 | | i386_load_far_pointer32(ES); |
| 3497 | | CYCLES(CYCLES_LES); |
| 3498 | | } |
| 3499 | | |
| 3500 | | void i386_device::i386_lfs32() // Opcode 0x0f 0xb4 |
| 3501 | | { |
| 3502 | | i386_load_far_pointer32(FS); |
| 3503 | | CYCLES(CYCLES_LFS); |
| 3504 | | } |
| 3505 | | |
| 3506 | | void i386_device::i386_lgs32() // Opcode 0x0f 0xb5 |
| 3507 | | { |
| 3508 | | i386_load_far_pointer32(GS); |
| 3509 | | CYCLES(CYCLES_LGS); |
| 3510 | | } |
trunk/src/emu/cpu/i386/i386op16.c
| r28738 | r28739 | |
| 1 | | UINT16 i386_device::i386_shift_rotate16(UINT8 modrm, UINT32 value, UINT8 shift) |
| 2 | | { |
| 3 | | UINT32 src = value & 0xffff; |
| 4 | | UINT16 dst = value; |
| 5 | | |
| 6 | | if( shift == 0 ) { |
| 7 | | CYCLES_RM(modrm, 3, 7); |
| 8 | | } else if( shift == 1 ) { |
| 9 | | switch( (modrm >> 3) & 0x7 ) |
| 10 | | { |
| 11 | | case 0: /* ROL rm16, 1 */ |
| 12 | | m_CF = (src & 0x8000) ? 1 : 0; |
| 13 | | dst = (src << 1) + m_CF; |
| 14 | | m_OF = ((src ^ dst) & 0x8000) ? 1 : 0; |
| 15 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 16 | | break; |
| 17 | | case 1: /* ROR rm16, 1 */ |
| 18 | | m_CF = (src & 0x1) ? 1 : 0; |
| 19 | | dst = (m_CF << 15) | (src >> 1); |
| 20 | | m_OF = ((src ^ dst) & 0x8000) ? 1 : 0; |
| 21 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 22 | | break; |
| 23 | | case 2: /* RCL rm16, 1 */ |
| 24 | | dst = (src << 1) + m_CF; |
| 25 | | m_CF = (src & 0x8000) ? 1 : 0; |
| 26 | | m_OF = ((src ^ dst) & 0x8000) ? 1 : 0; |
| 27 | | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 28 | | break; |
| 29 | | case 3: /* RCR rm16, 1 */ |
| 30 | | dst = (m_CF << 15) | (src >> 1); |
| 31 | | m_CF = src & 0x1; |
| 32 | | m_OF = ((src ^ dst) & 0x8000) ? 1 : 0; |
| 33 | | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 34 | | break; |
| 35 | | case 4: /* SHL/SAL rm16, 1 */ |
| 36 | | case 6: |
| 37 | | dst = src << 1; |
| 38 | | m_CF = (src & 0x8000) ? 1 : 0; |
| 39 | | m_OF = (((m_CF << 15) ^ dst) & 0x8000) ? 1 : 0; |
| 40 | | SetSZPF16(dst); |
| 41 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 42 | | break; |
| 43 | | case 5: /* SHR rm16, 1 */ |
| 44 | | dst = src >> 1; |
| 45 | | m_CF = src & 0x1; |
| 46 | | m_OF = (dst & 0x8000) ? 1 : 0; |
| 47 | | SetSZPF16(dst); |
| 48 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 49 | | break; |
| 50 | | case 7: /* SAR rm16, 1 */ |
| 51 | | dst = (INT16)(src) >> 1; |
| 52 | | m_CF = src & 0x1; |
| 53 | | m_OF = 0; |
| 54 | | SetSZPF16(dst); |
| 55 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 56 | | break; |
| 57 | | } |
| 58 | | } else { |
| 59 | | switch( (modrm >> 3) & 0x7 ) |
| 60 | | { |
| 61 | | case 0: /* ROL rm16, i8 */ |
| 62 | | if(!(shift & 15)) |
| 63 | | { |
| 64 | | if(shift & 16) |
| 65 | | { |
| 66 | | m_CF = src & 1; |
| 67 | | m_OF = (src & 1) ^ ((src >> 15) & 1); |
| 68 | | } |
| 69 | | break; |
| 70 | | } |
| 71 | | shift &= 15; |
| 72 | | dst = ((src & ((UINT16)0xffff >> shift)) << shift) | |
| 73 | | ((src & ((UINT16)0xffff << (16-shift))) >> (16-shift)); |
| 74 | | m_CF = dst & 0x1; |
| 75 | | m_OF = (dst & 1) ^ (dst >> 15); |
| 76 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 77 | | break; |
| 78 | | case 1: /* ROR rm16, i8 */ |
| 79 | | if(!(shift & 15)) |
| 80 | | { |
| 81 | | if(shift & 16) |
| 82 | | { |
| 83 | | m_CF = (src >> 15) & 1; |
| 84 | | m_OF = ((src >> 15) & 1) ^ ((src >> 14) & 1); |
| 85 | | } |
| 86 | | break; |
| 87 | | } |
| 88 | | shift &= 15; |
| 89 | | dst = ((src & ((UINT16)0xffff << shift)) >> shift) | |
| 90 | | ((src & ((UINT16)0xffff >> (16-shift))) << (16-shift)); |
| 91 | | m_CF = (dst >> 15) & 1; |
| 92 | | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 93 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 94 | | break; |
| 95 | | case 2: /* RCL rm16, i8 */ |
| 96 | | shift %= 17; |
| 97 | | dst = ((src & ((UINT16)0xffff >> shift)) << shift) | |
| 98 | | ((src & ((UINT16)0xffff << (17-shift))) >> (17-shift)) | |
| 99 | | (m_CF << (shift-1)); |
| 100 | | if(shift) m_CF = (src >> (16-shift)) & 0x1; |
| 101 | | m_OF = m_CF ^ ((dst >> 15) & 1); |
| 102 | | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 103 | | break; |
| 104 | | case 3: /* RCR rm16, i8 */ |
| 105 | | shift %= 17; |
| 106 | | dst = ((src & ((UINT16)0xffff << shift)) >> shift) | |
| 107 | | ((src & ((UINT16)0xffff >> (16-shift))) << (17-shift)) | |
| 108 | | (m_CF << (16-shift)); |
| 109 | | if(shift) m_CF = (src >> (shift-1)) & 0x1; |
| 110 | | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 111 | | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 112 | | break; |
| 113 | | case 4: /* SHL/SAL rm16, i8 */ |
| 114 | | case 6: |
| 115 | | shift &= 31; |
| 116 | | dst = src << shift; |
| 117 | | m_CF = (shift <= 16) && (src & (1 << (16-shift))); |
| 118 | | SetSZPF16(dst); |
| 119 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 120 | | break; |
| 121 | | case 5: /* SHR rm16, i8 */ |
| 122 | | shift &= 31; |
| 123 | | dst = src >> shift; |
| 124 | | m_CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 125 | | SetSZPF16(dst); |
| 126 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 127 | | break; |
| 128 | | case 7: /* SAR rm16, i8 */ |
| 129 | | shift &= 31; |
| 130 | | dst = (INT16)src >> shift; |
| 131 | | m_CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 132 | | SetSZPF16(dst); |
| 133 | | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 134 | | break; |
| 135 | | } |
| 136 | | |
| 137 | | } |
| 138 | | return dst; |
| 139 | | } |
| 140 | | |
| 141 | | |
| 142 | | |
| 143 | | void i386_device::i386_adc_rm16_r16() // Opcode 0x11 |
| 144 | | { |
| 145 | | UINT16 src, dst; |
| 146 | | UINT8 modrm = FETCH(); |
| 147 | | if( modrm >= 0xc0 ) { |
| 148 | | src = LOAD_REG16(modrm); |
| 149 | | dst = LOAD_RM16(modrm); |
| 150 | | dst = ADC16(dst, src, m_CF); |
| 151 | | STORE_RM16(modrm, dst); |
| 152 | | CYCLES(CYCLES_ALU_REG_REG); |
| 153 | | } else { |
| 154 | | UINT32 ea = GetEA(modrm,1); |
| 155 | | src = LOAD_REG16(modrm); |
| 156 | | dst = READ16(ea); |
| 157 | | dst = ADC16(dst, src, m_CF); |
| 158 | | WRITE16(ea, dst); |
| 159 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 160 | | } |
| 161 | | } |
| 162 | | |
| 163 | | void i386_device::i386_adc_r16_rm16() // Opcode 0x13 |
| 164 | | { |
| 165 | | UINT16 src, dst; |
| 166 | | UINT8 modrm = FETCH(); |
| 167 | | if( modrm >= 0xc0 ) { |
| 168 | | src = LOAD_RM16(modrm); |
| 169 | | dst = LOAD_REG16(modrm); |
| 170 | | dst = ADC16(dst, src, m_CF); |
| 171 | | STORE_REG16(modrm, dst); |
| 172 | | CYCLES(CYCLES_ALU_REG_REG); |
| 173 | | } else { |
| 174 | | UINT32 ea = GetEA(modrm,0); |
| 175 | | src = READ16(ea); |
| 176 | | dst = LOAD_REG16(modrm); |
| 177 | | dst = ADC16(dst, src, m_CF); |
| 178 | | STORE_REG16(modrm, dst); |
| 179 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 180 | | } |
| 181 | | } |
| 182 | | |
| 183 | | void i386_device::i386_adc_ax_i16() // Opcode 0x15 |
| 184 | | { |
| 185 | | UINT16 src, dst; |
| 186 | | src = FETCH16(); |
| 187 | | dst = REG16(AX); |
| 188 | | dst = ADC16(dst, src, m_CF); |
| 189 | | REG16(AX) = dst; |
| 190 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 191 | | } |
| 192 | | |
| 193 | | void i386_device::i386_add_rm16_r16() // Opcode 0x01 |
| 194 | | { |
| 195 | | UINT16 src, dst; |
| 196 | | UINT8 modrm = FETCH(); |
| 197 | | if( modrm >= 0xc0 ) { |
| 198 | | src = LOAD_REG16(modrm); |
| 199 | | dst = LOAD_RM16(modrm); |
| 200 | | dst = ADD16(dst, src); |
| 201 | | STORE_RM16(modrm, dst); |
| 202 | | CYCLES(CYCLES_ALU_REG_REG); |
| 203 | | } else { |
| 204 | | UINT32 ea = GetEA(modrm,1); |
| 205 | | src = LOAD_REG16(modrm); |
| 206 | | dst = READ16(ea); |
| 207 | | dst = ADD16(dst, src); |
| 208 | | WRITE16(ea, dst); |
| 209 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 210 | | } |
| 211 | | } |
| 212 | | |
| 213 | | void i386_device::i386_add_r16_rm16() // Opcode 0x03 |
| 214 | | { |
| 215 | | UINT16 src, dst; |
| 216 | | UINT8 modrm = FETCH(); |
| 217 | | if( modrm >= 0xc0 ) { |
| 218 | | src = LOAD_RM16(modrm); |
| 219 | | dst = LOAD_REG16(modrm); |
| 220 | | dst = ADD16(dst, src); |
| 221 | | STORE_REG16(modrm, dst); |
| 222 | | CYCLES(CYCLES_ALU_REG_REG); |
| 223 | | } else { |
| 224 | | UINT32 ea = GetEA(modrm,0); |
| 225 | | src = READ16(ea); |
| 226 | | dst = LOAD_REG16(modrm); |
| 227 | | dst = ADD16(dst, src); |
| 228 | | STORE_REG16(modrm, dst); |
| 229 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 230 | | } |
| 231 | | } |
| 232 | | |
| 233 | | void i386_device::i386_add_ax_i16() // Opcode 0x05 |
| 234 | | { |
| 235 | | UINT16 src, dst; |
| 236 | | src = FETCH16(); |
| 237 | | dst = REG16(AX); |
| 238 | | dst = ADD16(dst, src); |
| 239 | | REG16(AX) = dst; |
| 240 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 241 | | } |
| 242 | | |
| 243 | | void i386_device::i386_and_rm16_r16() // Opcode 0x21 |
| 244 | | { |
| 245 | | UINT16 src, dst; |
| 246 | | UINT8 modrm = FETCH(); |
| 247 | | if( modrm >= 0xc0 ) { |
| 248 | | src = LOAD_REG16(modrm); |
| 249 | | dst = LOAD_RM16(modrm); |
| 250 | | dst = AND16(dst, src); |
| 251 | | STORE_RM16(modrm, dst); |
| 252 | | CYCLES(CYCLES_ALU_REG_REG); |
| 253 | | } else { |
| 254 | | UINT32 ea = GetEA(modrm,1); |
| 255 | | src = LOAD_REG16(modrm); |
| 256 | | dst = READ16(ea); |
| 257 | | dst = AND16(dst, src); |
| 258 | | WRITE16(ea, dst); |
| 259 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 260 | | } |
| 261 | | } |
| 262 | | |
| 263 | | void i386_device::i386_and_r16_rm16() // Opcode 0x23 |
| 264 | | { |
| 265 | | UINT16 src, dst; |
| 266 | | UINT8 modrm = FETCH(); |
| 267 | | if( modrm >= 0xc0 ) { |
| 268 | | src = LOAD_RM16(modrm); |
| 269 | | dst = LOAD_REG16(modrm); |
| 270 | | dst = AND16(dst, src); |
| 271 | | STORE_REG16(modrm, dst); |
| 272 | | CYCLES(CYCLES_ALU_REG_REG); |
| 273 | | } else { |
| 274 | | UINT32 ea = GetEA(modrm,0); |
| 275 | | src = READ16(ea); |
| 276 | | dst = LOAD_REG16(modrm); |
| 277 | | dst = AND16(dst, src); |
| 278 | | STORE_REG16(modrm, dst); |
| 279 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 280 | | } |
| 281 | | } |
| 282 | | |
| 283 | | void i386_device::i386_and_ax_i16() // Opcode 0x25 |
| 284 | | { |
| 285 | | UINT16 src, dst; |
| 286 | | src = FETCH16(); |
| 287 | | dst = REG16(AX); |
| 288 | | dst = AND16(dst, src); |
| 289 | | REG16(AX) = dst; |
| 290 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 291 | | } |
| 292 | | |
| 293 | | void i386_device::i386_bsf_r16_rm16() // Opcode 0x0f bc |
| 294 | | { |
| 295 | | UINT16 src, dst, temp; |
| 296 | | UINT8 modrm = FETCH(); |
| 297 | | |
| 298 | | if( modrm >= 0xc0 ) { |
| 299 | | src = LOAD_RM16(modrm); |
| 300 | | } else { |
| 301 | | UINT32 ea = GetEA(modrm,0); |
| 302 | | src = READ16(ea); |
| 303 | | } |
| 304 | | |
| 305 | | dst = 0; |
| 306 | | |
| 307 | | if( src == 0 ) { |
| 308 | | m_ZF = 1; |
| 309 | | } else { |
| 310 | | m_ZF = 0; |
| 311 | | temp = 0; |
| 312 | | while( (src & (1 << temp)) == 0 ) { |
| 313 | | temp++; |
| 314 | | dst = temp; |
| 315 | | CYCLES(CYCLES_BSF); |
| 316 | | } |
| 317 | | STORE_REG16(modrm, dst); |
| 318 | | } |
| 319 | | CYCLES(CYCLES_BSF_BASE); |
| 320 | | } |
| 321 | | |
| 322 | | void i386_device::i386_bsr_r16_rm16() // Opcode 0x0f bd |
| 323 | | { |
| 324 | | UINT16 src, dst, temp; |
| 325 | | UINT8 modrm = FETCH(); |
| 326 | | |
| 327 | | if( modrm >= 0xc0 ) { |
| 328 | | src = LOAD_RM16(modrm); |
| 329 | | } else { |
| 330 | | UINT32 ea = GetEA(modrm,0); |
| 331 | | src = READ16(ea); |
| 332 | | } |
| 333 | | |
| 334 | | dst = 0; |
| 335 | | |
| 336 | | if( src == 0 ) { |
| 337 | | m_ZF = 1; |
| 338 | | } else { |
| 339 | | m_ZF = 0; |
| 340 | | dst = temp = 15; |
| 341 | | while( (src & (1 << temp)) == 0 ) { |
| 342 | | temp--; |
| 343 | | dst = temp; |
| 344 | | CYCLES(CYCLES_BSR); |
| 345 | | } |
| 346 | | STORE_REG16(modrm, dst); |
| 347 | | } |
| 348 | | CYCLES(CYCLES_BSR_BASE); |
| 349 | | } |
| 350 | | |
| 351 | | |
| 352 | | void i386_device::i386_bt_rm16_r16() // Opcode 0x0f a3 |
| 353 | | { |
| 354 | | UINT8 modrm = FETCH(); |
| 355 | | if( modrm >= 0xc0 ) { |
| 356 | | UINT16 dst = LOAD_RM16(modrm); |
| 357 | | UINT16 bit = LOAD_REG16(modrm); |
| 358 | | |
| 359 | | if( dst & (1 << (bit & 0xf)) ) |
| 360 | | m_CF = 1; |
| 361 | | else |
| 362 | | m_CF = 0; |
| 363 | | |
| 364 | | CYCLES(CYCLES_BT_REG_REG); |
| 365 | | } else { |
| 366 | | UINT8 segment; |
| 367 | | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 368 | | UINT16 bit = LOAD_REG16(modrm); |
| 369 | | ea += 2*(bit/16); |
| 370 | | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),0); |
| 371 | | bit %= 16; |
| 372 | | UINT16 dst = READ16(ea); |
| 373 | | |
| 374 | | if( dst & (1 << bit) ) |
| 375 | | m_CF = 1; |
| 376 | | else |
| 377 | | m_CF = 0; |
| 378 | | |
| 379 | | CYCLES(CYCLES_BT_REG_MEM); |
| 380 | | } |
| 381 | | } |
| 382 | | |
| 383 | | void i386_device::i386_btc_rm16_r16() // Opcode 0x0f bb |
| 384 | | { |
| 385 | | UINT8 modrm = FETCH(); |
| 386 | | if( modrm >= 0xc0 ) { |
| 387 | | UINT16 dst = LOAD_RM16(modrm); |
| 388 | | UINT16 bit = LOAD_REG16(modrm); |
| 389 | | |
| 390 | | if( dst & (1 << (bit & 0xf)) ) |
| 391 | | m_CF = 1; |
| 392 | | else |
| 393 | | m_CF = 0; |
| 394 | | dst ^= (1 << (bit & 0xf)); |
| 395 | | |
| 396 | | STORE_RM16(modrm, dst); |
| 397 | | CYCLES(CYCLES_BTC_REG_REG); |
| 398 | | } else { |
| 399 | | UINT8 segment; |
| 400 | | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 401 | | UINT16 bit = LOAD_REG16(modrm); |
| 402 | | ea += 2*(bit/16); |
| 403 | | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1); |
| 404 | | bit %= 16; |
| 405 | | UINT16 dst = READ16(ea); |
| 406 | | |
| 407 | | if( dst & (1 << bit) ) |
| 408 | | m_CF = 1; |
| 409 | | else |
| 410 | | m_CF = 0; |
| 411 | | dst ^= (1 << bit); |
| 412 | | |
| 413 | | WRITE16(ea, dst); |
| 414 | | CYCLES(CYCLES_BTC_REG_MEM); |
| 415 | | } |
| 416 | | } |
| 417 | | |
| 418 | | void i386_device::i386_btr_rm16_r16() // Opcode 0x0f b3 |
| 419 | | { |
| 420 | | UINT8 modrm = FETCH(); |
| 421 | | if( modrm >= 0xc0 ) { |
| 422 | | UINT16 dst = LOAD_RM16(modrm); |
| 423 | | UINT16 bit = LOAD_REG16(modrm); |
| 424 | | |
| 425 | | if( dst & (1 << (bit & 0xf)) ) |
| 426 | | m_CF = 1; |
| 427 | | else |
| 428 | | m_CF = 0; |
| 429 | | dst &= ~(1 << (bit & 0xf)); |
| 430 | | |
| 431 | | STORE_RM16(modrm, dst); |
| 432 | | CYCLES(CYCLES_BTR_REG_REG); |
| 433 | | } else { |
| 434 | | UINT8 segment; |
| 435 | | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 436 | | UINT16 bit = LOAD_REG16(modrm); |
| 437 | | ea += 2*(bit/16); |
| 438 | | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1); |
| 439 | | bit %= 16; |
| 440 | | UINT16 dst = READ16(ea); |
| 441 | | |
| 442 | | if( dst & (1 << bit) ) |
| 443 | | m_CF = 1; |
| 444 | | else |
| 445 | | m_CF = 0; |
| 446 | | dst &= ~(1 << bit); |
| 447 | | |
| 448 | | WRITE16(ea, dst); |
| 449 | | CYCLES(CYCLES_BTR_REG_MEM); |
| 450 | | } |
| 451 | | } |
| 452 | | |
| 453 | | void i386_device::i386_bts_rm16_r16() // Opcode 0x0f ab |
| 454 | | { |
| 455 | | UINT8 modrm = FETCH(); |
| 456 | | if( modrm >= 0xc0 ) { |
| 457 | | UINT16 dst = LOAD_RM16(modrm); |
| 458 | | UINT16 bit = LOAD_REG16(modrm); |
| 459 | | |
| 460 | | if( dst & (1 << (bit & 0xf)) ) |
| 461 | | m_CF = 1; |
| 462 | | else |
| 463 | | m_CF = 0; |
| 464 | | dst |= (1 << (bit & 0xf)); |
| 465 | | |
| 466 | | STORE_RM16(modrm, dst); |
| 467 | | CYCLES(CYCLES_BTS_REG_REG); |
| 468 | | } else { |
| 469 | | UINT8 segment; |
| 470 | | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 471 | | UINT16 bit = LOAD_REG16(modrm); |
| 472 | | ea += 2*(bit/16); |
| 473 | | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1); |
| 474 | | bit %= 16; |
| 475 | | UINT16 dst = READ16(ea); |
| 476 | | |
| 477 | | if( dst & (1 << bit) ) |
| 478 | | m_CF = 1; |
| 479 | | else |
| 480 | | m_CF = 0; |
| 481 | | dst |= (1 << bit); |
| 482 | | |
| 483 | | WRITE16(ea, dst); |
| 484 | | CYCLES(CYCLES_BTS_REG_MEM); |
| 485 | | } |
| 486 | | } |
| 487 | | |
| 488 | | void i386_device::i386_call_abs16() // Opcode 0x9a |
| 489 | | { |
| 490 | | UINT16 offset = FETCH16(); |
| 491 | | UINT16 ptr = FETCH16(); |
| 492 | | |
| 493 | | if( PROTECTED_MODE && !V8086_MODE) |
| 494 | | { |
| 495 | | i386_protected_mode_call(ptr,offset,0,0); |
| 496 | | } |
| 497 | | else |
| 498 | | { |
| 499 | | PUSH16(m_sreg[CS].selector ); |
| 500 | | PUSH16(m_eip ); |
| 501 | | m_sreg[CS].selector = ptr; |
| 502 | | m_performed_intersegment_jump = 1; |
| 503 | | m_eip = offset; |
| 504 | | i386_load_segment_descriptor(CS); |
| 505 | | } |
| 506 | | CYCLES(CYCLES_CALL_INTERSEG); /* TODO: Timing = 17 + m */ |
| 507 | | CHANGE_PC(m_eip); |
| 508 | | } |
| 509 | | |
| 510 | | void i386_device::i386_call_rel16() // Opcode 0xe8 |
| 511 | | { |
| 512 | | INT16 disp = FETCH16(); |
| 513 | | |
| 514 | | PUSH16(m_eip ); |
| 515 | | if (m_sreg[CS].d) |
| 516 | | { |
| 517 | | m_eip += disp; |
| 518 | | } |
| 519 | | else |
| 520 | | { |
| 521 | | m_eip = (m_eip + disp) & 0xffff; |
| 522 | | } |
| 523 | | CHANGE_PC(m_eip); |
| 524 | | CYCLES(CYCLES_CALL); /* TODO: Timing = 7 + m */ |
| 525 | | } |
| 526 | | |
| 527 | | void i386_device::i386_cbw() // Opcode 0x98 |
| 528 | | { |
| 529 | | REG16(AX) = (INT16)((INT8)REG8(AL)); |
| 530 | | CYCLES(CYCLES_CBW); |
| 531 | | } |
| 532 | | |
| 533 | | void i386_device::i386_cmp_rm16_r16() // Opcode 0x39 |
| 534 | | { |
| 535 | | UINT16 src, dst; |
| 536 | | UINT8 modrm = FETCH(); |
| 537 | | if( modrm >= 0xc0 ) { |
| 538 | | src = LOAD_REG16(modrm); |
| 539 | | dst = LOAD_RM16(modrm); |
| 540 | | SUB16(dst, src); |
| 541 | | CYCLES(CYCLES_CMP_REG_REG); |
| 542 | | } else { |
| 543 | | UINT32 ea = GetEA(modrm,0); |
| 544 | | src = LOAD_REG16(modrm); |
| 545 | | dst = READ16(ea); |
| 546 | | SUB16(dst, src); |
| 547 | | CYCLES(CYCLES_CMP_REG_MEM); |
| 548 | | } |
| 549 | | } |
| 550 | | |
| 551 | | void i386_device::i386_cmp_r16_rm16() // Opcode 0x3b |
| 552 | | { |
| 553 | | UINT16 src, dst; |
| 554 | | UINT8 modrm = FETCH(); |
| 555 | | if( modrm >= 0xc0 ) { |
| 556 | | src = LOAD_RM16(modrm); |
| 557 | | dst = LOAD_REG16(modrm); |
| 558 | | SUB16(dst, src); |
| 559 | | CYCLES(CYCLES_CMP_REG_REG); |
| 560 | | } else { |
| 561 | | UINT32 ea = GetEA(modrm,0); |
| 562 | | src = READ16(ea); |
| 563 | | dst = LOAD_REG16(modrm); |
| 564 | | SUB16(dst, src); |
| 565 | | CYCLES(CYCLES_CMP_MEM_REG); |
| 566 | | } |
| 567 | | } |
| 568 | | |
| 569 | | void i386_device::i386_cmp_ax_i16() // Opcode 0x3d |
| 570 | | { |
| 571 | | UINT16 src, dst; |
| 572 | | src = FETCH16(); |
| 573 | | dst = REG16(AX); |
| 574 | | SUB16(dst, src); |
| 575 | | CYCLES(CYCLES_CMP_IMM_ACC); |
| 576 | | } |
| 577 | | |
| 578 | | void i386_device::i386_cmpsw() // Opcode 0xa7 |
| 579 | | { |
| 580 | | UINT32 eas, ead; |
| 581 | | UINT16 src, dst; |
| 582 | | if( m_segment_prefix ) { |
| 583 | | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 584 | | } else { |
| 585 | | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 586 | | } |
| 587 | | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 ); |
| 588 | | src = READ16(eas); |
| 589 | | dst = READ16(ead); |
| 590 | | SUB16(src,dst); |
| 591 | | BUMP_SI(2); |
| 592 | | BUMP_DI(2); |
| 593 | | CYCLES(CYCLES_CMPS); |
| 594 | | } |
| 595 | | |
| 596 | | void i386_device::i386_cwd() // Opcode 0x99 |
| 597 | | { |
| 598 | | if( REG16(AX) & 0x8000 ) { |
| 599 | | REG16(DX) = 0xffff; |
| 600 | | } else { |
| 601 | | REG16(DX) = 0x0000; |
| 602 | | } |
| 603 | | CYCLES(CYCLES_CWD); |
| 604 | | } |
| 605 | | |
| 606 | | void i386_device::i386_dec_ax() // Opcode 0x48 |
| 607 | | { |
| 608 | | REG16(AX) = DEC16(REG16(AX) ); |
| 609 | | CYCLES(CYCLES_DEC_REG); |
| 610 | | } |
| 611 | | |
| 612 | | void i386_device::i386_dec_cx() // Opcode 0x49 |
| 613 | | { |
| 614 | | REG16(CX) = DEC16(REG16(CX) ); |
| 615 | | CYCLES(CYCLES_DEC_REG); |
| 616 | | } |
| 617 | | |
| 618 | | void i386_device::i386_dec_dx() // Opcode 0x4a |
| 619 | | { |
| 620 | | REG16(DX) = DEC16(REG16(DX) ); |
| 621 | | CYCLES(CYCLES_DEC_REG); |
| 622 | | } |
| 623 | | |
| 624 | | void i386_device::i386_dec_bx() // Opcode 0x4b |
| 625 | | { |
| 626 | | REG16(BX) = DEC16(REG16(BX) ); |
| 627 | | CYCLES(CYCLES_DEC_REG); |
| 628 | | } |
| 629 | | |
| 630 | | void i386_device::i386_dec_sp() // Opcode 0x4c |
| 631 | | { |
| 632 | | REG16(SP) = DEC16(REG16(SP) ); |
| 633 | | CYCLES(CYCLES_DEC_REG); |
| 634 | | } |
| 635 | | |
| 636 | | void i386_device::i386_dec_bp() // Opcode 0x4d |
| 637 | | { |
| 638 | | REG16(BP) = DEC16(REG16(BP) ); |
| 639 | | CYCLES(CYCLES_DEC_REG); |
| 640 | | } |
| 641 | | |
| 642 | | void i386_device::i386_dec_si() // Opcode 0x4e |
| 643 | | { |
| 644 | | REG16(SI) = DEC16(REG16(SI) ); |
| 645 | | CYCLES(CYCLES_DEC_REG); |
| 646 | | } |
| 647 | | |
| 648 | | void i386_device::i386_dec_di() // Opcode 0x4f |
| 649 | | { |
| 650 | | REG16(DI) = DEC16(REG16(DI) ); |
| 651 | | CYCLES(CYCLES_DEC_REG); |
| 652 | | } |
| 653 | | |
| 654 | | void i386_device::i386_imul_r16_rm16() // Opcode 0x0f af |
| 655 | | { |
| 656 | | UINT8 modrm = FETCH(); |
| 657 | | INT32 result; |
| 658 | | INT32 src, dst; |
| 659 | | if( modrm >= 0xc0 ) { |
| 660 | | src = (INT32)(INT16)LOAD_RM16(modrm); |
| 661 | | CYCLES(CYCLES_IMUL16_REG_REG); /* TODO: Correct multiply timing */ |
| 662 | | } else { |
| 663 | | UINT32 ea = GetEA(modrm,0); |
| 664 | | src = (INT32)(INT16)READ16(ea); |
| 665 | | CYCLES(CYCLES_IMUL16_REG_MEM); /* TODO: Correct multiply timing */ |
| 666 | | } |
| 667 | | |
| 668 | | dst = (INT32)(INT16)LOAD_REG16(modrm); |
| 669 | | result = src * dst; |
| 670 | | |
| 671 | | STORE_REG16(modrm, (UINT16)result); |
| 672 | | |
| 673 | | m_CF = m_OF = !(result == (INT32)(INT16)result); |
| 674 | | } |
| 675 | | |
| 676 | | void i386_device::i386_imul_r16_rm16_i16() // Opcode 0x69 |
| 677 | | { |
| 678 | | UINT8 modrm = FETCH(); |
| 679 | | INT32 result; |
| 680 | | INT32 src, dst; |
| 681 | | if( modrm >= 0xc0 ) { |
| 682 | | dst = (INT32)(INT16)LOAD_RM16(modrm); |
| 683 | | CYCLES(CYCLES_IMUL16_REG_IMM_REG); /* TODO: Correct multiply timing */ |
| 684 | | } else { |
| 685 | | UINT32 ea = GetEA(modrm,0); |
| 686 | | dst = (INT32)(INT16)READ16(ea); |
| 687 | | CYCLES(CYCLES_IMUL16_MEM_IMM_REG); /* TODO: Correct multiply timing */ |
| 688 | | } |
| 689 | | |
| 690 | | src = (INT32)(INT16)FETCH16(); |
| 691 | | result = src * dst; |
| 692 | | |
| 693 | | STORE_REG16(modrm, (UINT16)result); |
| 694 | | |
| 695 | | m_CF = m_OF = !(result == (INT32)(INT16)result); |
| 696 | | } |
| 697 | | |
| 698 | | void i386_device::i386_imul_r16_rm16_i8() // Opcode 0x6b |
| 699 | | { |
| 700 | | UINT8 modrm = FETCH(); |
| 701 | | INT32 result; |
| 702 | | INT32 src, dst; |
| 703 | | if( modrm >= 0xc0 ) { |
| 704 | | dst = (INT32)(INT16)LOAD_RM16(modrm); |
| 705 | | CYCLES(CYCLES_IMUL16_REG_IMM_REG); /* TODO: Correct multiply timing */ |
| 706 | | } else { |
| 707 | | UINT32 ea = GetEA(modrm,0); |
| 708 | | dst = (INT32)(INT16)READ16(ea); |
| 709 | | CYCLES(CYCLES_IMUL16_MEM_IMM_REG); /* TODO: Correct multiply timing */ |
| 710 | | } |
| 711 | | |
| 712 | | src = (INT32)(INT8)FETCH(); |
| 713 | | result = src * dst; |
| 714 | | |
| 715 | | STORE_REG16(modrm, (UINT16)result); |
| 716 | | |
| 717 | | m_CF = m_OF = !(result == (INT32)(INT16)result); |
| 718 | | } |
| 719 | | |
| 720 | | void i386_device::i386_in_ax_i8() // Opcode 0xe5 |
| 721 | | { |
| 722 | | UINT16 port = FETCH(); |
| 723 | | UINT16 data = READPORT16(port); |
| 724 | | REG16(AX) = data; |
| 725 | | CYCLES(CYCLES_IN_VAR); |
| 726 | | } |
| 727 | | |
| 728 | | void i386_device::i386_in_ax_dx() // Opcode 0xed |
| 729 | | { |
| 730 | | UINT16 port = REG16(DX); |
| 731 | | UINT16 data = READPORT16(port); |
| 732 | | REG16(AX) = data; |
| 733 | | CYCLES(CYCLES_IN); |
| 734 | | } |
| 735 | | |
| 736 | | void i386_device::i386_inc_ax() // Opcode 0x40 |
| 737 | | { |
| 738 | | REG16(AX) = INC16(REG16(AX) ); |
| 739 | | CYCLES(CYCLES_INC_REG); |
| 740 | | } |
| 741 | | |
| 742 | | void i386_device::i386_inc_cx() // Opcode 0x41 |
| 743 | | { |
| 744 | | REG16(CX) = INC16(REG16(CX) ); |
| 745 | | CYCLES(CYCLES_INC_REG); |
| 746 | | } |
| 747 | | |
| 748 | | void i386_device::i386_inc_dx() // Opcode 0x42 |
| 749 | | { |
| 750 | | REG16(DX) = INC16(REG16(DX) ); |
| 751 | | CYCLES(CYCLES_INC_REG); |
| 752 | | } |
| 753 | | |
| 754 | | void i386_device::i386_inc_bx() // Opcode 0x43 |
| 755 | | { |
| 756 | | REG16(BX) = INC16(REG16(BX) ); |
| 757 | | CYCLES(CYCLES_INC_REG); |
| 758 | | } |
| 759 | | |
| 760 | | void i386_device::i386_inc_sp() // Opcode 0x44 |
| 761 | | { |
| 762 | | REG16(SP) = INC16(REG16(SP) ); |
| 763 | | CYCLES(CYCLES_INC_REG); |
| 764 | | } |
| 765 | | |
| 766 | | void i386_device::i386_inc_bp() // Opcode 0x45 |
| 767 | | { |
| 768 | | REG16(BP) = INC16(REG16(BP) ); |
| 769 | | CYCLES(CYCLES_INC_REG); |
| 770 | | } |
| 771 | | |
| 772 | | void i386_device::i386_inc_si() // Opcode 0x46 |
| 773 | | { |
| 774 | | REG16(SI) = INC16(REG16(SI) ); |
| 775 | | CYCLES(CYCLES_INC_REG); |
| 776 | | } |
| 777 | | |
| 778 | | void i386_device::i386_inc_di() // Opcode 0x47 |
| 779 | | { |
| 780 | | REG16(DI) = INC16(REG16(DI) ); |
| 781 | | CYCLES(CYCLES_INC_REG); |
| 782 | | } |
| 783 | | |
| 784 | | void i386_device::i386_iret16() // Opcode 0xcf |
| 785 | | { |
| 786 | | if( PROTECTED_MODE ) |
| 787 | | { |
| 788 | | i386_protected_mode_iret(0); |
| 789 | | } |
| 790 | | else |
| 791 | | { |
| 792 | | /* TODO: #SS(0) exception */ |
| 793 | | /* TODO: #GP(0) exception */ |
| 794 | | m_eip = POP16(); |
| 795 | | m_sreg[CS].selector = POP16(); |
| 796 | | set_flags(POP16() ); |
| 797 | | i386_load_segment_descriptor(CS); |
| 798 | | CHANGE_PC(m_eip); |
| 799 | | } |
| 800 | | CYCLES(CYCLES_IRET); |
| 801 | | } |
| 802 | | |
| 803 | | void i386_device::i386_ja_rel16() // Opcode 0x0f 87 |
| 804 | | { |
| 805 | | INT16 disp = FETCH16(); |
| 806 | | if( m_CF == 0 && m_ZF == 0 ) { |
| 807 | | if (m_sreg[CS].d) |
| 808 | | { |
| 809 | | m_eip += disp; |
| 810 | | } |
| 811 | | else |
| 812 | | { |
| 813 | | m_eip = (m_eip + disp) & 0xffff; |
| 814 | | } |
| 815 | | CHANGE_PC(m_eip); |
| 816 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 817 | | } else { |
| 818 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 819 | | } |
| 820 | | } |
| 821 | | |
| 822 | | void i386_device::i386_jbe_rel16() // Opcode 0x0f 86 |
| 823 | | { |
| 824 | | INT16 disp = FETCH16(); |
| 825 | | if( m_CF != 0 || m_ZF != 0 ) { |
| 826 | | if (m_sreg[CS].d) |
| 827 | | { |
| 828 | | m_eip += disp; |
| 829 | | } |
| 830 | | else |
| 831 | | { |
| 832 | | m_eip = (m_eip + disp) & 0xffff; |
| 833 | | } |
| 834 | | CHANGE_PC(m_eip); |
| 835 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 836 | | } else { |
| 837 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 838 | | } |
| 839 | | } |
| 840 | | |
| 841 | | void i386_device::i386_jc_rel16() // Opcode 0x0f 82 |
| 842 | | { |
| 843 | | INT16 disp = FETCH16(); |
| 844 | | if( m_CF != 0 ) { |
| 845 | | if (m_sreg[CS].d) |
| 846 | | { |
| 847 | | m_eip += disp; |
| 848 | | } |
| 849 | | else |
| 850 | | { |
| 851 | | m_eip = (m_eip + disp) & 0xffff; |
| 852 | | } |
| 853 | | CHANGE_PC(m_eip); |
| 854 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 855 | | } else { |
| 856 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 857 | | } |
| 858 | | } |
| 859 | | |
| 860 | | void i386_device::i386_jg_rel16() // Opcode 0x0f 8f |
| 861 | | { |
| 862 | | INT16 disp = FETCH16(); |
| 863 | | if( m_ZF == 0 && (m_SF == m_OF) ) { |
| 864 | | if (m_sreg[CS].d) |
| 865 | | { |
| 866 | | m_eip += disp; |
| 867 | | } |
| 868 | | else |
| 869 | | { |
| 870 | | m_eip = (m_eip + disp) & 0xffff; |
| 871 | | } |
| 872 | | CHANGE_PC(m_eip); |
| 873 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 874 | | } else { |
| 875 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 876 | | } |
| 877 | | } |
| 878 | | |
| 879 | | void i386_device::i386_jge_rel16() // Opcode 0x0f 8d |
| 880 | | { |
| 881 | | INT16 disp = FETCH16(); |
| 882 | | if(m_SF == m_OF) { |
| 883 | | if (m_sreg[CS].d) |
| 884 | | { |
| 885 | | m_eip += disp; |
| 886 | | } |
| 887 | | else |
| 888 | | { |
| 889 | | m_eip = (m_eip + disp) & 0xffff; |
| 890 | | } |
| 891 | | CHANGE_PC(m_eip); |
| 892 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 893 | | } else { |
| 894 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 895 | | } |
| 896 | | } |
| 897 | | |
| 898 | | void i386_device::i386_jl_rel16() // Opcode 0x0f 8c |
| 899 | | { |
| 900 | | INT16 disp = FETCH16(); |
| 901 | | if( (m_SF != m_OF) ) { |
| 902 | | if (m_sreg[CS].d) |
| 903 | | { |
| 904 | | m_eip += disp; |
| 905 | | } |
| 906 | | else |
| 907 | | { |
| 908 | | m_eip = (m_eip + disp) & 0xffff; |
| 909 | | } |
| 910 | | CHANGE_PC(m_eip); |
| 911 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 912 | | } else { |
| 913 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 914 | | } |
| 915 | | } |
| 916 | | |
| 917 | | void i386_device::i386_jle_rel16() // Opcode 0x0f 8e |
| 918 | | { |
| 919 | | INT16 disp = FETCH16(); |
| 920 | | if( m_ZF != 0 || (m_SF != m_OF) ) { |
| 921 | | if (m_sreg[CS].d) |
| 922 | | { |
| 923 | | m_eip += disp; |
| 924 | | } |
| 925 | | else |
| 926 | | { |
| 927 | | m_eip = (m_eip + disp) & 0xffff; |
| 928 | | } |
| 929 | | CHANGE_PC(m_eip); |
| 930 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 931 | | } else { |
| 932 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 933 | | } |
| 934 | | } |
| 935 | | |
| 936 | | void i386_device::i386_jnc_rel16() // Opcode 0x0f 83 |
| 937 | | { |
| 938 | | INT16 disp = FETCH16(); |
| 939 | | if( m_CF == 0 ) { |
| 940 | | if (m_sreg[CS].d) |
| 941 | | { |
| 942 | | m_eip += disp; |
| 943 | | } |
| 944 | | else |
| 945 | | { |
| 946 | | m_eip = (m_eip + disp) & 0xffff; |
| 947 | | } |
| 948 | | CHANGE_PC(m_eip); |
| 949 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 950 | | } else { |
| 951 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 952 | | } |
| 953 | | } |
| 954 | | |
| 955 | | void i386_device::i386_jno_rel16() // Opcode 0x0f 81 |
| 956 | | { |
| 957 | | INT16 disp = FETCH16(); |
| 958 | | if( m_OF == 0 ) { |
| 959 | | if (m_sreg[CS].d) |
| 960 | | { |
| 961 | | m_eip += disp; |
| 962 | | } |
| 963 | | else |
| 964 | | { |
| 965 | | m_eip = (m_eip + disp) & 0xffff; |
| 966 | | } |
| 967 | | CHANGE_PC(m_eip); |
| 968 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 969 | | } else { |
| 970 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 971 | | } |
| 972 | | } |
| 973 | | |
| 974 | | void i386_device::i386_jnp_rel16() // Opcode 0x0f 8b |
| 975 | | { |
| 976 | | INT16 disp = FETCH16(); |
| 977 | | if( m_PF == 0 ) { |
| 978 | | if (m_sreg[CS].d) |
| 979 | | { |
| 980 | | m_eip += disp; |
| 981 | | } |
| 982 | | else |
| 983 | | { |
| 984 | | m_eip = (m_eip + disp) & 0xffff; |
| 985 | | } |
| 986 | | CHANGE_PC(m_eip); |
| 987 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 988 | | } else { |
| 989 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 990 | | } |
| 991 | | } |
| 992 | | |
| 993 | | void i386_device::i386_jns_rel16() // Opcode 0x0f 89 |
| 994 | | { |
| 995 | | INT16 disp = FETCH16(); |
| 996 | | if( m_SF == 0 ) { |
| 997 | | if (m_sreg[CS].d) |
| 998 | | { |
| 999 | | m_eip += disp; |
| 1000 | | } |
| 1001 | | else |
| 1002 | | { |
| 1003 | | m_eip = (m_eip + disp) & 0xffff; |
| 1004 | | } |
| 1005 | | CHANGE_PC(m_eip); |
| 1006 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 1007 | | } else { |
| 1008 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 1009 | | } |
| 1010 | | } |
| 1011 | | |
| 1012 | | void i386_device::i386_jnz_rel16() // Opcode 0x0f 85 |
| 1013 | | { |
| 1014 | | INT16 disp = FETCH16(); |
| 1015 | | if( m_ZF == 0 ) { |
| 1016 | | if (m_sreg[CS].d) |
| 1017 | | { |
| 1018 | | m_eip += disp; |
| 1019 | | } |
| 1020 | | else |
| 1021 | | { |
| 1022 | | m_eip = (m_eip + disp) & 0xffff; |
| 1023 | | } |
| 1024 | | CHANGE_PC(m_eip); |
| 1025 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 1026 | | } else { |
| 1027 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 1028 | | } |
| 1029 | | } |
| 1030 | | |
| 1031 | | void i386_device::i386_jo_rel16() // Opcode 0x0f 80 |
| 1032 | | { |
| 1033 | | INT16 disp = FETCH16(); |
| 1034 | | if( m_OF != 0 ) { |
| 1035 | | if (m_sreg[CS].d) |
| 1036 | | { |
| 1037 | | m_eip += disp; |
| 1038 | | } |
| 1039 | | else |
| 1040 | | { |
| 1041 | | m_eip = (m_eip + disp) & 0xffff; |
| 1042 | | } |
| 1043 | | CHANGE_PC(m_eip); |
| 1044 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 1045 | | } else { |
| 1046 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 1047 | | } |
| 1048 | | } |
| 1049 | | |
| 1050 | | void i386_device::i386_jp_rel16() // Opcode 0x0f 8a |
| 1051 | | { |
| 1052 | | INT16 disp = FETCH16(); |
| 1053 | | if( m_PF != 0 ) { |
| 1054 | | if (m_sreg[CS].d) |
| 1055 | | { |
| 1056 | | m_eip += disp; |
| 1057 | | } |
| 1058 | | else |
| 1059 | | { |
| 1060 | | m_eip = (m_eip + disp) & 0xffff; |
| 1061 | | } |
| 1062 | | CHANGE_PC(m_eip); |
| 1063 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 1064 | | } else { |
| 1065 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 1066 | | } |
| 1067 | | } |
| 1068 | | |
| 1069 | | void i386_device::i386_js_rel16() // Opcode 0x0f 88 |
| 1070 | | { |
| 1071 | | INT16 disp = FETCH16(); |
| 1072 | | if( m_SF != 0 ) { |
| 1073 | | if (m_sreg[CS].d) |
| 1074 | | { |
| 1075 | | m_eip += disp; |
| 1076 | | } |
| 1077 | | else |
| 1078 | | { |
| 1079 | | m_eip = (m_eip + disp) & 0xffff; |
| 1080 | | } |
| 1081 | | CHANGE_PC(m_eip); |
| 1082 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 1083 | | } else { |
| 1084 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 1085 | | } |
| 1086 | | } |
| 1087 | | |
| 1088 | | void i386_device::i386_jz_rel16() // Opcode 0x0f 84 |
| 1089 | | { |
| 1090 | | INT16 disp = FETCH16(); |
| 1091 | | if( m_ZF != 0 ) { |
| 1092 | | if (m_sreg[CS].d) |
| 1093 | | { |
| 1094 | | m_eip += disp; |
| 1095 | | } |
| 1096 | | else |
| 1097 | | { |
| 1098 | | m_eip = (m_eip + disp) & 0xffff; |
| 1099 | | } |
| 1100 | | CHANGE_PC(m_eip); |
| 1101 | | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 1102 | | } else { |
| 1103 | | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 1104 | | } |
| 1105 | | } |
| 1106 | | |
| 1107 | | void i386_device::i386_jcxz16() // Opcode 0xe3 |
| 1108 | | { |
| 1109 | | INT8 disp = FETCH(); |
| 1110 | | int val = (m_address_size)?(REG32(ECX) == 0):(REG16(CX) == 0); |
| 1111 | | if( val ) { |
| 1112 | | if (m_sreg[CS].d) |
| 1113 | | { |
| 1114 | | m_eip += disp; |
| 1115 | | } |
| 1116 | | else |
| 1117 | | { |
| 1118 | | m_eip = (m_eip + disp) & 0xffff; |
| 1119 | | } |
| 1120 | | CHANGE_PC(m_eip); |
| 1121 | | CYCLES(CYCLES_JCXZ); /* TODO: Timing = 9 + m */ |
| 1122 | | } else { |
| 1123 | | CYCLES(CYCLES_JCXZ_NOBRANCH); |
| 1124 | | } |
| 1125 | | } |
| 1126 | | |
| 1127 | | void i386_device::i386_jmp_rel16() // Opcode 0xe9 |
| 1128 | | { |
| 1129 | | INT16 disp = FETCH16(); |
| 1130 | | |
| 1131 | | if (m_sreg[CS].d) |
| 1132 | | { |
| 1133 | | m_eip += disp; |
| 1134 | | } |
| 1135 | | else |
| 1136 | | { |
| 1137 | | m_eip = (m_eip + disp) & 0xffff; |
| 1138 | | } |
| 1139 | | CHANGE_PC(m_eip); |
| 1140 | | CYCLES(CYCLES_JMP); /* TODO: Timing = 7 + m */ |
| 1141 | | } |
| 1142 | | |
| 1143 | | void i386_device::i386_jmp_abs16() // Opcode 0xea |
| 1144 | | { |
| 1145 | | UINT16 address = FETCH16(); |
| 1146 | | UINT16 segment = FETCH16(); |
| 1147 | | |
| 1148 | | if( PROTECTED_MODE && !V8086_MODE) |
| 1149 | | { |
| 1150 | | i386_protected_mode_jump(segment,address,0,0); |
| 1151 | | } |
| 1152 | | else |
| 1153 | | { |
| 1154 | | m_eip = address; |
| 1155 | | m_sreg[CS].selector = segment; |
| 1156 | | m_performed_intersegment_jump = 1; |
| 1157 | | i386_load_segment_descriptor(CS); |
| 1158 | | CHANGE_PC(m_eip); |
| 1159 | | } |
| 1160 | | CYCLES(CYCLES_JMP_INTERSEG); |
| 1161 | | } |
| 1162 | | |
| 1163 | | void i386_device::i386_lea16() // Opcode 0x8d |
| 1164 | | { |
| 1165 | | UINT8 modrm = FETCH(); |
| 1166 | | UINT32 ea = GetNonTranslatedEA(modrm,NULL); |
| 1167 | | STORE_REG16(modrm, ea); |
| 1168 | | CYCLES(CYCLES_LEA); |
| 1169 | | } |
| 1170 | | |
| 1171 | | void i386_device::i386_enter16() // Opcode 0xc8 |
| 1172 | | { |
| 1173 | | UINT16 framesize = FETCH16(); |
| 1174 | | UINT8 level = FETCH() % 32; |
| 1175 | | UINT8 x; |
| 1176 | | UINT16 frameptr; |
| 1177 | | PUSH16(REG16(BP)); |
| 1178 | | |
| 1179 | | if(!STACK_32BIT) |
| 1180 | | frameptr = REG16(SP); |
| 1181 | | else |
| 1182 | | frameptr = REG32(ESP); |
| 1183 | | |
| 1184 | | if(level > 0) |
| 1185 | | { |
| 1186 | | for(x=1;x<level-1;x++) |
| 1187 | | { |
| 1188 | | REG16(BP) -= 2; |
| 1189 | | PUSH16(READ16(REG16(BP))); |
| 1190 | | } |
| 1191 | | PUSH16(frameptr); |
| 1192 | | } |
| 1193 | | REG16(BP) = frameptr; |
| 1194 | | if(!STACK_32BIT) |
| 1195 | | REG16(SP) -= framesize; |
| 1196 | | else |
| 1197 | | REG32(ESP) -= framesize; |
| 1198 | | CYCLES(CYCLES_ENTER); |
| 1199 | | } |
| 1200 | | |
| 1201 | | void i386_device::i386_leave16() // Opcode 0xc9 |
| 1202 | | { |
| 1203 | | if(!STACK_32BIT) |
| 1204 | | REG16(SP) = REG16(BP); |
| 1205 | | else |
| 1206 | | REG32(ESP) = REG32(EBP); |
| 1207 | | REG16(BP) = POP16(); |
| 1208 | | CYCLES(CYCLES_LEAVE); |
| 1209 | | } |
| 1210 | | |
| 1211 | | void i386_device::i386_lodsw() // Opcode 0xad |
| 1212 | | { |
| 1213 | | UINT32 eas; |
| 1214 | | if( m_segment_prefix ) { |
| 1215 | | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1216 | | } else { |
| 1217 | | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1218 | | } |
| 1219 | | REG16(AX) = READ16(eas); |
| 1220 | | BUMP_SI(2); |
| 1221 | | CYCLES(CYCLES_LODS); |
| 1222 | | } |
| 1223 | | |
| 1224 | | void i386_device::i386_loop16() // Opcode 0xe2 |
| 1225 | | { |
| 1226 | | INT8 disp = FETCH(); |
| 1227 | | INT32 val = (m_address_size)?(--REG32(ECX)):(--REG16(CX)); |
| 1228 | | if( val != 0 ) { |
| 1229 | | if (m_sreg[CS].d) |
| 1230 | | { |
| 1231 | | m_eip += disp; |
| 1232 | | } |
| 1233 | | else |
| 1234 | | { |
| 1235 | | m_eip = (m_eip + disp) & 0xffff; |
| 1236 | | } |
| 1237 | | CHANGE_PC(m_eip); |
| 1238 | | } |
| 1239 | | CYCLES(CYCLES_LOOP); /* TODO: Timing = 11 + m */ |
| 1240 | | } |
| 1241 | | |
| 1242 | | void i386_device::i386_loopne16() // Opcode 0xe0 |
| 1243 | | { |
| 1244 | | INT8 disp = FETCH(); |
| 1245 | | INT32 val = (m_address_size)?(--REG32(ECX)):(--REG16(CX)); |
| 1246 | | if( val != 0 && m_ZF == 0 ) { |
| 1247 | | if (m_sreg[CS].d) |
| 1248 | | { |
| 1249 | | m_eip += disp; |
| 1250 | | } |
| 1251 | | else |
| 1252 | | { |
| 1253 | | m_eip = (m_eip + disp) & 0xffff; |
| 1254 | | } |
| 1255 | | CHANGE_PC(m_eip); |
| 1256 | | } |
| 1257 | | CYCLES(CYCLES_LOOPNZ); /* TODO: Timing = 11 + m */ |
| 1258 | | } |
| 1259 | | |
| 1260 | | void i386_device::i386_loopz16() // Opcode 0xe1 |
| 1261 | | { |
| 1262 | | INT8 disp = FETCH(); |
| 1263 | | INT32 val = (m_address_size)?(--REG32(ECX)):(--REG16(CX)); |
| 1264 | | if( val != 0 && m_ZF != 0 ) { |
| 1265 | | if (m_sreg[CS].d) |
| 1266 | | { |
| 1267 | | m_eip += disp; |
| 1268 | | } |
| 1269 | | else |
| 1270 | | { |
| 1271 | | m_eip = (m_eip + disp) & 0xffff; |
| 1272 | | } |
| 1273 | | CHANGE_PC(m_eip); |
| 1274 | | } |
| 1275 | | CYCLES(CYCLES_LOOPZ); /* TODO: Timing = 11 + m */ |
| 1276 | | } |
| 1277 | | |
| 1278 | | void i386_device::i386_mov_rm16_r16() // Opcode 0x89 |
| 1279 | | { |
| 1280 | | UINT16 src; |
| 1281 | | UINT8 modrm = FETCH(); |
| 1282 | | if( modrm >= 0xc0 ) { |
| 1283 | | src = LOAD_REG16(modrm); |
| 1284 | | STORE_RM16(modrm, src); |
| 1285 | | CYCLES(CYCLES_MOV_REG_REG); |
| 1286 | | } else { |
| 1287 | | UINT32 ea = GetEA(modrm,1); |
| 1288 | | src = LOAD_REG16(modrm); |
| 1289 | | WRITE16(ea, src); |
| 1290 | | CYCLES(CYCLES_MOV_REG_MEM); |
| 1291 | | } |
| 1292 | | } |
| 1293 | | |
| 1294 | | void i386_device::i386_mov_r16_rm16() // Opcode 0x8b |
| 1295 | | { |
| 1296 | | UINT16 src; |
| 1297 | | UINT8 modrm = FETCH(); |
| 1298 | | if( modrm >= 0xc0 ) { |
| 1299 | | src = LOAD_RM16(modrm); |
| 1300 | | STORE_REG16(modrm, src); |
| 1301 | | CYCLES(CYCLES_MOV_REG_REG); |
| 1302 | | } else { |
| 1303 | | UINT32 ea = GetEA(modrm,0); |
| 1304 | | src = READ16(ea); |
| 1305 | | STORE_REG16(modrm, src); |
| 1306 | | CYCLES(CYCLES_MOV_MEM_REG); |
| 1307 | | } |
| 1308 | | } |
| 1309 | | |
| 1310 | | void i386_device::i386_mov_rm16_i16() // Opcode 0xc7 |
| 1311 | | { |
| 1312 | | UINT8 modrm = FETCH(); |
| 1313 | | if( modrm >= 0xc0 ) { |
| 1314 | | UINT16 value = FETCH16(); |
| 1315 | | STORE_RM16(modrm, value); |
| 1316 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1317 | | } else { |
| 1318 | | UINT32 ea = GetEA(modrm,1); |
| 1319 | | UINT16 value = FETCH16(); |
| 1320 | | WRITE16(ea, value); |
| 1321 | | CYCLES(CYCLES_MOV_IMM_MEM); |
| 1322 | | } |
| 1323 | | } |
| 1324 | | |
| 1325 | | void i386_device::i386_mov_ax_m16() // Opcode 0xa1 |
| 1326 | | { |
| 1327 | | UINT32 offset, ea; |
| 1328 | | if( m_address_size ) { |
| 1329 | | offset = FETCH32(); |
| 1330 | | } else { |
| 1331 | | offset = FETCH16(); |
| 1332 | | } |
| 1333 | | /* TODO: Not sure if this is correct... */ |
| 1334 | | if( m_segment_prefix ) { |
| 1335 | | ea = i386_translate(m_segment_override, offset, 0 ); |
| 1336 | | } else { |
| 1337 | | ea = i386_translate(DS, offset, 0 ); |
| 1338 | | } |
| 1339 | | REG16(AX) = READ16(ea); |
| 1340 | | CYCLES(CYCLES_MOV_MEM_ACC); |
| 1341 | | } |
| 1342 | | |
| 1343 | | void i386_device::i386_mov_m16_ax() // Opcode 0xa3 |
| 1344 | | { |
| 1345 | | UINT32 offset, ea; |
| 1346 | | if( m_address_size ) { |
| 1347 | | offset = FETCH32(); |
| 1348 | | } else { |
| 1349 | | offset = FETCH16(); |
| 1350 | | } |
| 1351 | | /* TODO: Not sure if this is correct... */ |
| 1352 | | if( m_segment_prefix ) { |
| 1353 | | ea = i386_translate(m_segment_override, offset, 1 ); |
| 1354 | | } else { |
| 1355 | | ea = i386_translate(DS, offset, 1 ); |
| 1356 | | } |
| 1357 | | WRITE16(ea, REG16(AX) ); |
| 1358 | | CYCLES(CYCLES_MOV_ACC_MEM); |
| 1359 | | } |
| 1360 | | |
| 1361 | | void i386_device::i386_mov_ax_i16() // Opcode 0xb8 |
| 1362 | | { |
| 1363 | | REG16(AX) = FETCH16(); |
| 1364 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1365 | | } |
| 1366 | | |
| 1367 | | void i386_device::i386_mov_cx_i16() // Opcode 0xb9 |
| 1368 | | { |
| 1369 | | REG16(CX) = FETCH16(); |
| 1370 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1371 | | } |
| 1372 | | |
| 1373 | | void i386_device::i386_mov_dx_i16() // Opcode 0xba |
| 1374 | | { |
| 1375 | | REG16(DX) = FETCH16(); |
| 1376 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1377 | | } |
| 1378 | | |
| 1379 | | void i386_device::i386_mov_bx_i16() // Opcode 0xbb |
| 1380 | | { |
| 1381 | | REG16(BX) = FETCH16(); |
| 1382 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1383 | | } |
| 1384 | | |
| 1385 | | void i386_device::i386_mov_sp_i16() // Opcode 0xbc |
| 1386 | | { |
| 1387 | | REG16(SP) = FETCH16(); |
| 1388 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1389 | | } |
| 1390 | | |
| 1391 | | void i386_device::i386_mov_bp_i16() // Opcode 0xbd |
| 1392 | | { |
| 1393 | | REG16(BP) = FETCH16(); |
| 1394 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1395 | | } |
| 1396 | | |
| 1397 | | void i386_device::i386_mov_si_i16() // Opcode 0xbe |
| 1398 | | { |
| 1399 | | REG16(SI) = FETCH16(); |
| 1400 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1401 | | } |
| 1402 | | |
| 1403 | | void i386_device::i386_mov_di_i16() // Opcode 0xbf |
| 1404 | | { |
| 1405 | | REG16(DI) = FETCH16(); |
| 1406 | | CYCLES(CYCLES_MOV_IMM_REG); |
| 1407 | | } |
| 1408 | | |
| 1409 | | void i386_device::i386_movsw() // Opcode 0xa5 |
| 1410 | | { |
| 1411 | | UINT32 eas, ead; |
| 1412 | | UINT16 v; |
| 1413 | | if( m_segment_prefix ) { |
| 1414 | | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1415 | | } else { |
| 1416 | | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1417 | | } |
| 1418 | | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 1419 | | v = READ16(eas); |
| 1420 | | WRITE16(ead, v); |
| 1421 | | BUMP_SI(2); |
| 1422 | | BUMP_DI(2); |
| 1423 | | CYCLES(CYCLES_MOVS); |
| 1424 | | } |
| 1425 | | |
| 1426 | | void i386_device::i386_movsx_r16_rm8() // Opcode 0x0f be |
| 1427 | | { |
| 1428 | | UINT8 modrm = FETCH(); |
| 1429 | | if( modrm >= 0xc0 ) { |
| 1430 | | INT16 src = (INT8)LOAD_RM8(modrm); |
| 1431 | | STORE_REG16(modrm, src); |
| 1432 | | CYCLES(CYCLES_MOVSX_REG_REG); |
| 1433 | | } else { |
| 1434 | | UINT32 ea = GetEA(modrm,0); |
| 1435 | | INT16 src = (INT8)READ8(ea); |
| 1436 | | STORE_REG16(modrm, src); |
| 1437 | | CYCLES(CYCLES_MOVSX_MEM_REG); |
| 1438 | | } |
| 1439 | | } |
| 1440 | | |
| 1441 | | void i386_device::i386_movzx_r16_rm8() // Opcode 0x0f b6 |
| 1442 | | { |
| 1443 | | UINT8 modrm = FETCH(); |
| 1444 | | if( modrm >= 0xc0 ) { |
| 1445 | | UINT16 src = (UINT8)LOAD_RM8(modrm); |
| 1446 | | STORE_REG16(modrm, src); |
| 1447 | | CYCLES(CYCLES_MOVZX_REG_REG); |
| 1448 | | } else { |
| 1449 | | UINT32 ea = GetEA(modrm,0); |
| 1450 | | UINT16 src = (UINT8)READ8(ea); |
| 1451 | | STORE_REG16(modrm, src); |
| 1452 | | CYCLES(CYCLES_MOVZX_MEM_REG); |
| 1453 | | } |
| 1454 | | } |
| 1455 | | |
| 1456 | | void i386_device::i386_or_rm16_r16() // Opcode 0x09 |
| 1457 | | { |
| 1458 | | UINT16 src, dst; |
| 1459 | | UINT8 modrm = FETCH(); |
| 1460 | | if( modrm >= 0xc0 ) { |
| 1461 | | src = LOAD_REG16(modrm); |
| 1462 | | dst = LOAD_RM16(modrm); |
| 1463 | | dst = OR16(dst, src); |
| 1464 | | STORE_RM16(modrm, dst); |
| 1465 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1466 | | } else { |
| 1467 | | UINT32 ea = GetEA(modrm,1); |
| 1468 | | src = LOAD_REG16(modrm); |
| 1469 | | dst = READ16(ea); |
| 1470 | | dst = OR16(dst, src); |
| 1471 | | WRITE16(ea, dst); |
| 1472 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1473 | | } |
| 1474 | | } |
| 1475 | | |
| 1476 | | void i386_device::i386_or_r16_rm16() // Opcode 0x0b |
| 1477 | | { |
| 1478 | | UINT16 src, dst; |
| 1479 | | UINT8 modrm = FETCH(); |
| 1480 | | if( modrm >= 0xc0 ) { |
| 1481 | | src = LOAD_RM16(modrm); |
| 1482 | | dst = LOAD_REG16(modrm); |
| 1483 | | dst = OR16(dst, src); |
| 1484 | | STORE_REG16(modrm, dst); |
| 1485 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1486 | | } else { |
| 1487 | | UINT32 ea = GetEA(modrm,0); |
| 1488 | | src = READ16(ea); |
| 1489 | | dst = LOAD_REG16(modrm); |
| 1490 | | dst = OR16(dst, src); |
| 1491 | | STORE_REG16(modrm, dst); |
| 1492 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 1493 | | } |
| 1494 | | } |
| 1495 | | |
| 1496 | | void i386_device::i386_or_ax_i16() // Opcode 0x0d |
| 1497 | | { |
| 1498 | | UINT16 src, dst; |
| 1499 | | src = FETCH16(); |
| 1500 | | dst = REG16(AX); |
| 1501 | | dst = OR16(dst, src); |
| 1502 | | REG16(AX) = dst; |
| 1503 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1504 | | } |
| 1505 | | |
| 1506 | | void i386_device::i386_out_ax_i8() // Opcode 0xe7 |
| 1507 | | { |
| 1508 | | UINT16 port = FETCH(); |
| 1509 | | UINT16 data = REG16(AX); |
| 1510 | | WRITEPORT16(port, data); |
| 1511 | | CYCLES(CYCLES_OUT_VAR); |
| 1512 | | } |
| 1513 | | |
| 1514 | | void i386_device::i386_out_ax_dx() // Opcode 0xef |
| 1515 | | { |
| 1516 | | UINT16 port = REG16(DX); |
| 1517 | | UINT16 data = REG16(AX); |
| 1518 | | WRITEPORT16(port, data); |
| 1519 | | CYCLES(CYCLES_OUT); |
| 1520 | | } |
| 1521 | | |
| 1522 | | void i386_device::i386_pop_ax() // Opcode 0x58 |
| 1523 | | { |
| 1524 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1525 | | if(i386_limit_check(SS,offset+1) == 0) |
| 1526 | | REG16(AX) = POP16(); |
| 1527 | | else |
| 1528 | | FAULT(FAULT_SS,0) |
| 1529 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1530 | | } |
| 1531 | | |
| 1532 | | void i386_device::i386_pop_cx() // Opcode 0x59 |
| 1533 | | { |
| 1534 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1535 | | if(i386_limit_check(SS,offset+1) == 0) |
| 1536 | | REG16(CX) = POP16(); |
| 1537 | | else |
| 1538 | | FAULT(FAULT_SS,0) |
| 1539 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1540 | | } |
| 1541 | | |
| 1542 | | void i386_device::i386_pop_dx() // Opcode 0x5a |
| 1543 | | { |
| 1544 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1545 | | if(i386_limit_check(SS,offset+1) == 0) |
| 1546 | | REG16(DX) = POP16(); |
| 1547 | | else |
| 1548 | | FAULT(FAULT_SS,0) |
| 1549 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1550 | | } |
| 1551 | | |
| 1552 | | void i386_device::i386_pop_bx() // Opcode 0x5b |
| 1553 | | { |
| 1554 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1555 | | if(i386_limit_check(SS,offset+1) == 0) |
| 1556 | | REG16(BX) = POP16(); |
| 1557 | | else |
| 1558 | | FAULT(FAULT_SS,0) |
| 1559 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1560 | | } |
| 1561 | | |
| 1562 | | void i386_device::i386_pop_sp() // Opcode 0x5c |
| 1563 | | { |
| 1564 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1565 | | if(i386_limit_check(SS,offset+1) == 0) |
| 1566 | | REG16(SP) = POP16(); |
| 1567 | | else |
| 1568 | | FAULT(FAULT_SS,0) |
| 1569 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1570 | | } |
| 1571 | | |
| 1572 | | void i386_device::i386_pop_bp() // Opcode 0x5d |
| 1573 | | { |
| 1574 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1575 | | if(i386_limit_check(SS,offset+1) == 0) |
| 1576 | | REG16(BP) = POP16(); |
| 1577 | | else |
| 1578 | | FAULT(FAULT_SS,0) |
| 1579 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1580 | | } |
| 1581 | | |
| 1582 | | void i386_device::i386_pop_si() // Opcode 0x5e |
| 1583 | | { |
| 1584 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1585 | | if(i386_limit_check(SS,offset+1) == 0) |
| 1586 | | REG16(SI) = POP16(); |
| 1587 | | else |
| 1588 | | FAULT(FAULT_SS,0) |
| 1589 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1590 | | } |
| 1591 | | |
| 1592 | | void i386_device::i386_pop_di() // Opcode 0x5f |
| 1593 | | { |
| 1594 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1595 | | if(i386_limit_check(SS,offset+1) == 0) |
| 1596 | | REG16(DI) = POP16(); |
| 1597 | | else |
| 1598 | | FAULT(FAULT_SS,0) |
| 1599 | | CYCLES(CYCLES_POP_REG_SHORT); |
| 1600 | | } |
| 1601 | | |
| 1602 | | bool i386_device::i386_pop_seg16(int segment) |
| 1603 | | { |
| 1604 | | UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1605 | | UINT16 value; |
| 1606 | | bool fault; |
| 1607 | | if(i386_limit_check(SS,offset+1) == 0) |
| 1608 | | { |
| 1609 | | ea = i386_translate(SS, offset, 0); |
| 1610 | | value = READ16(ea); |
| 1611 | | i386_sreg_load(value, segment, &fault); |
| 1612 | | if(fault) return false; |
| 1613 | | if(STACK_32BIT) |
| 1614 | | REG32(ESP) = offset + 2; |
| 1615 | | else |
| 1616 | | REG16(SP) = offset + 2; |
| 1617 | | } |
| 1618 | | else |
| 1619 | | { |
| 1620 | | m_ext = 1; |
| 1621 | | i386_trap_with_error(FAULT_SS,0,0,0); |
| 1622 | | return false; |
| 1623 | | } |
| 1624 | | CYCLES(CYCLES_POP_SREG); |
| 1625 | | return true; |
| 1626 | | } |
| 1627 | | |
| 1628 | | void i386_device::i386_pop_ds16() // Opcode 0x1f |
| 1629 | | { |
| 1630 | | i386_pop_seg16(DS); |
| 1631 | | } |
| 1632 | | |
| 1633 | | void i386_device::i386_pop_es16() // Opcode 0x07 |
| 1634 | | { |
| 1635 | | i386_pop_seg16(ES); |
| 1636 | | } |
| 1637 | | |
| 1638 | | void i386_device::i386_pop_fs16() // Opcode 0x0f a1 |
| 1639 | | { |
| 1640 | | i386_pop_seg16(FS); |
| 1641 | | } |
| 1642 | | |
| 1643 | | void i386_device::i386_pop_gs16() // Opcode 0x0f a9 |
| 1644 | | { |
| 1645 | | i386_pop_seg16(GS); |
| 1646 | | } |
| 1647 | | |
| 1648 | | void i386_device::i386_pop_ss16() // Opcode 0x17 |
| 1649 | | { |
| 1650 | | if(!i386_pop_seg16(SS)) return; |
| 1651 | | if(m_IF != 0) // if external interrupts are enabled |
| 1652 | | { |
| 1653 | | m_IF = 0; // reset IF for the next instruction |
| 1654 | | m_delayed_interrupt_enable = 1; |
| 1655 | | } |
| 1656 | | } |
| 1657 | | |
| 1658 | | void i386_device::i386_pop_rm16() // Opcode 0x8f |
| 1659 | | { |
| 1660 | | UINT8 modrm = FETCH(); |
| 1661 | | UINT16 value; |
| 1662 | | UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1663 | | |
| 1664 | | if(i386_limit_check(SS,offset+1) == 0) |
| 1665 | | { |
| 1666 | | UINT32 temp_sp = REG32(ESP); |
| 1667 | | value = POP16(); |
| 1668 | | |
| 1669 | | if( modrm >= 0xc0 ) { |
| 1670 | | STORE_RM16(modrm, value); |
| 1671 | | } else { |
| 1672 | | ea = GetEA(modrm,1); |
| 1673 | | try |
| 1674 | | { |
| 1675 | | WRITE16(ea, value); |
| 1676 | | } |
| 1677 | | catch(UINT64 e) |
| 1678 | | { |
| 1679 | | REG32(ESP) = temp_sp; |
| 1680 | | throw e; |
| 1681 | | } |
| 1682 | | } |
| 1683 | | } |
| 1684 | | else |
| 1685 | | FAULT(FAULT_SS,0) |
| 1686 | | CYCLES(CYCLES_POP_RM); |
| 1687 | | } |
| 1688 | | |
| 1689 | | void i386_device::i386_popa() // Opcode 0x61 |
| 1690 | | { |
| 1691 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1692 | | |
| 1693 | | if(i386_limit_check(SS,offset+15) == 0) |
| 1694 | | { |
| 1695 | | REG16(DI) = POP16(); |
| 1696 | | REG16(SI) = POP16(); |
| 1697 | | REG16(BP) = POP16(); |
| 1698 | | REG16(SP) += 2; |
| 1699 | | REG16(BX) = POP16(); |
| 1700 | | REG16(DX) = POP16(); |
| 1701 | | REG16(CX) = POP16(); |
| 1702 | | REG16(AX) = POP16(); |
| 1703 | | } |
| 1704 | | else |
| 1705 | | FAULT(FAULT_SS,0) |
| 1706 | | CYCLES(CYCLES_POPA); |
| 1707 | | } |
| 1708 | | |
| 1709 | | void i386_device::i386_popf() // Opcode 0x9d |
| 1710 | | { |
| 1711 | | UINT32 value; |
| 1712 | | UINT32 current = get_flags(); |
| 1713 | | UINT8 IOPL = (current >> 12) & 0x03; |
| 1714 | | UINT32 mask = 0x7fd5; |
| 1715 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1716 | | |
| 1717 | | // IOPL can only change if CPL is 0 |
| 1718 | | if(m_CPL != 0) |
| 1719 | | mask &= ~0x00003000; |
| 1720 | | |
| 1721 | | // IF can only change if CPL is at least as privileged as IOPL |
| 1722 | | if(m_CPL > IOPL) |
| 1723 | | mask &= ~0x00000200; |
| 1724 | | |
| 1725 | | if(V8086_MODE) |
| 1726 | | { |
| 1727 | | if(IOPL < 3) |
| 1728 | | { |
| 1729 | | logerror("POPFD(%08x): IOPL < 3 while in V86 mode.\n",m_pc); |
| 1730 | | FAULT(FAULT_GP,0) // #GP(0) |
| 1731 | | } |
| 1732 | | mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode |
| 1733 | | } |
| 1734 | | |
| 1735 | | if(i386_limit_check(SS,offset+1) == 0) |
| 1736 | | { |
| 1737 | | value = POP16(); |
| 1738 | | set_flags((current & ~mask) | (value & mask)); // mask out reserved bits |
| 1739 | | } |
| 1740 | | else |
| 1741 | | FAULT(FAULT_SS,0) |
| 1742 | | CYCLES(CYCLES_POPF); |
| 1743 | | } |
| 1744 | | |
| 1745 | | void i386_device::i386_push_ax() // Opcode 0x50 |
| 1746 | | { |
| 1747 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1748 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1749 | | PUSH16(REG16(AX) ); |
| 1750 | | else |
| 1751 | | FAULT(FAULT_SS,0) |
| 1752 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1753 | | } |
| 1754 | | |
| 1755 | | void i386_device::i386_push_cx() // Opcode 0x51 |
| 1756 | | { |
| 1757 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1758 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1759 | | PUSH16(REG16(CX) ); |
| 1760 | | else |
| 1761 | | FAULT(FAULT_SS,0) |
| 1762 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1763 | | } |
| 1764 | | |
| 1765 | | void i386_device::i386_push_dx() // Opcode 0x52 |
| 1766 | | { |
| 1767 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1768 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1769 | | PUSH16(REG16(DX) ); |
| 1770 | | else |
| 1771 | | FAULT(FAULT_SS,0) |
| 1772 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1773 | | } |
| 1774 | | |
| 1775 | | void i386_device::i386_push_bx() // Opcode 0x53 |
| 1776 | | { |
| 1777 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1778 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1779 | | PUSH16(REG16(BX) ); |
| 1780 | | else |
| 1781 | | FAULT(FAULT_SS,0) |
| 1782 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1783 | | } |
| 1784 | | |
| 1785 | | void i386_device::i386_push_sp() // Opcode 0x54 |
| 1786 | | { |
| 1787 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1788 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1789 | | PUSH16(REG16(SP) ); |
| 1790 | | else |
| 1791 | | FAULT(FAULT_SS,0) |
| 1792 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1793 | | } |
| 1794 | | |
| 1795 | | void i386_device::i386_push_bp() // Opcode 0x55 |
| 1796 | | { |
| 1797 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1798 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1799 | | PUSH16(REG16(BP) ); |
| 1800 | | else |
| 1801 | | FAULT(FAULT_SS,0) |
| 1802 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1803 | | } |
| 1804 | | |
| 1805 | | void i386_device::i386_push_si() // Opcode 0x56 |
| 1806 | | { |
| 1807 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1808 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1809 | | PUSH16(REG16(SI) ); |
| 1810 | | else |
| 1811 | | FAULT(FAULT_SS,0) |
| 1812 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1813 | | } |
| 1814 | | |
| 1815 | | void i386_device::i386_push_di() // Opcode 0x57 |
| 1816 | | { |
| 1817 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1818 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1819 | | PUSH16(REG16(DI) ); |
| 1820 | | else |
| 1821 | | FAULT(FAULT_SS,0) |
| 1822 | | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1823 | | } |
| 1824 | | |
| 1825 | | void i386_device::i386_push_cs16() // Opcode 0x0e |
| 1826 | | { |
| 1827 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1828 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1829 | | PUSH16(m_sreg[CS].selector ); |
| 1830 | | else |
| 1831 | | FAULT(FAULT_SS,0) |
| 1832 | | CYCLES(CYCLES_PUSH_SREG); |
| 1833 | | } |
| 1834 | | |
| 1835 | | void i386_device::i386_push_ds16() // Opcode 0x1e |
| 1836 | | { |
| 1837 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1838 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1839 | | PUSH16(m_sreg[DS].selector ); |
| 1840 | | else |
| 1841 | | FAULT(FAULT_SS,0) |
| 1842 | | CYCLES(CYCLES_PUSH_SREG); |
| 1843 | | } |
| 1844 | | |
| 1845 | | void i386_device::i386_push_es16() // Opcode 0x06 |
| 1846 | | { |
| 1847 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1848 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1849 | | PUSH16(m_sreg[ES].selector ); |
| 1850 | | else |
| 1851 | | FAULT(FAULT_SS,0) |
| 1852 | | CYCLES(CYCLES_PUSH_SREG); |
| 1853 | | } |
| 1854 | | |
| 1855 | | void i386_device::i386_push_fs16() // Opcode 0x0f a0 |
| 1856 | | { |
| 1857 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1858 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1859 | | PUSH16(m_sreg[FS].selector ); |
| 1860 | | else |
| 1861 | | FAULT(FAULT_SS,0) |
| 1862 | | CYCLES(CYCLES_PUSH_SREG); |
| 1863 | | } |
| 1864 | | |
| 1865 | | void i386_device::i386_push_gs16() // Opcode 0x0f a8 |
| 1866 | | { |
| 1867 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1868 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1869 | | PUSH16(m_sreg[GS].selector ); |
| 1870 | | else |
| 1871 | | FAULT(FAULT_SS,0) |
| 1872 | | CYCLES(CYCLES_PUSH_SREG); |
| 1873 | | } |
| 1874 | | |
| 1875 | | void i386_device::i386_push_ss16() // Opcode 0x16 |
| 1876 | | { |
| 1877 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1878 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1879 | | PUSH16(m_sreg[SS].selector ); |
| 1880 | | else |
| 1881 | | FAULT(FAULT_SS,0) |
| 1882 | | CYCLES(CYCLES_PUSH_SREG); |
| 1883 | | } |
| 1884 | | |
| 1885 | | void i386_device::i386_push_i16() // Opcode 0x68 |
| 1886 | | { |
| 1887 | | UINT16 value = FETCH16(); |
| 1888 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1889 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1890 | | PUSH16(value); |
| 1891 | | else |
| 1892 | | FAULT(FAULT_SS,0) |
| 1893 | | CYCLES(CYCLES_PUSH_IMM); |
| 1894 | | } |
| 1895 | | |
| 1896 | | void i386_device::i386_pusha() // Opcode 0x60 |
| 1897 | | { |
| 1898 | | UINT16 temp = REG16(SP); |
| 1899 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1900 | | if(i386_limit_check(SS,offset-16) == 0) |
| 1901 | | { |
| 1902 | | PUSH16(REG16(AX) ); |
| 1903 | | PUSH16(REG16(CX) ); |
| 1904 | | PUSH16(REG16(DX) ); |
| 1905 | | PUSH16(REG16(BX) ); |
| 1906 | | PUSH16(temp ); |
| 1907 | | PUSH16(REG16(BP) ); |
| 1908 | | PUSH16(REG16(SI) ); |
| 1909 | | PUSH16(REG16(DI) ); |
| 1910 | | } |
| 1911 | | else |
| 1912 | | FAULT(FAULT_SS,0) |
| 1913 | | CYCLES(CYCLES_PUSHA); |
| 1914 | | } |
| 1915 | | |
| 1916 | | void i386_device::i386_pushf() // Opcode 0x9c |
| 1917 | | { |
| 1918 | | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1919 | | if(i386_limit_check(SS,offset-2) == 0) |
| 1920 | | PUSH16(get_flags() & 0xffff ); |
| 1921 | | else |
| 1922 | | FAULT(FAULT_SS,0) |
| 1923 | | CYCLES(CYCLES_PUSHF); |
| 1924 | | } |
| 1925 | | |
| 1926 | | void i386_device::i386_ret_near16_i16() // Opcode 0xc2 |
| 1927 | | { |
| 1928 | | INT16 disp = FETCH16(); |
| 1929 | | m_eip = POP16(); |
| 1930 | | REG16(SP) += disp; |
| 1931 | | CHANGE_PC(m_eip); |
| 1932 | | CYCLES(CYCLES_RET_IMM); /* TODO: Timing = 10 + m */ |
| 1933 | | } |
| 1934 | | |
| 1935 | | void i386_device::i386_ret_near16() // Opcode 0xc3 |
| 1936 | | { |
| 1937 | | m_eip = POP16(); |
| 1938 | | CHANGE_PC(m_eip); |
| 1939 | | CYCLES(CYCLES_RET); /* TODO: Timing = 10 + m */ |
| 1940 | | } |
| 1941 | | |
| 1942 | | void i386_device::i386_sbb_rm16_r16() // Opcode 0x19 |
| 1943 | | { |
| 1944 | | UINT16 src, dst; |
| 1945 | | UINT8 modrm = FETCH(); |
| 1946 | | if( modrm >= 0xc0 ) { |
| 1947 | | src = LOAD_REG16(modrm); |
| 1948 | | dst = LOAD_RM16(modrm); |
| 1949 | | dst = SBB16(dst, src, m_CF); |
| 1950 | | STORE_RM16(modrm, dst); |
| 1951 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1952 | | } else { |
| 1953 | | UINT32 ea = GetEA(modrm,1); |
| 1954 | | src = LOAD_REG16(modrm); |
| 1955 | | dst = READ16(ea); |
| 1956 | | dst = SBB16(dst, src, m_CF); |
| 1957 | | WRITE16(ea, dst); |
| 1958 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 1959 | | } |
| 1960 | | } |
| 1961 | | |
| 1962 | | void i386_device::i386_sbb_r16_rm16() // Opcode 0x1b |
| 1963 | | { |
| 1964 | | UINT16 src, dst; |
| 1965 | | UINT8 modrm = FETCH(); |
| 1966 | | if( modrm >= 0xc0 ) { |
| 1967 | | src = LOAD_RM16(modrm); |
| 1968 | | dst = LOAD_REG16(modrm); |
| 1969 | | dst = SBB16(dst, src, m_CF); |
| 1970 | | STORE_REG16(modrm, dst); |
| 1971 | | CYCLES(CYCLES_ALU_REG_REG); |
| 1972 | | } else { |
| 1973 | | UINT32 ea = GetEA(modrm,0); |
| 1974 | | src = READ16(ea); |
| 1975 | | dst = LOAD_REG16(modrm); |
| 1976 | | dst = SBB16(dst, src, m_CF); |
| 1977 | | STORE_REG16(modrm, dst); |
| 1978 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 1979 | | } |
| 1980 | | } |
| 1981 | | |
| 1982 | | void i386_device::i386_sbb_ax_i16() // Opcode 0x1d |
| 1983 | | { |
| 1984 | | UINT16 src, dst; |
| 1985 | | src = FETCH16(); |
| 1986 | | dst = REG16(AX); |
| 1987 | | dst = SBB16(dst, src, m_CF); |
| 1988 | | REG16(AX) = dst; |
| 1989 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1990 | | } |
| 1991 | | |
| 1992 | | void i386_device::i386_scasw() // Opcode 0xaf |
| 1993 | | { |
| 1994 | | UINT32 eas; |
| 1995 | | UINT16 src, dst; |
| 1996 | | eas = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 ); |
| 1997 | | src = READ16(eas); |
| 1998 | | dst = REG16(AX); |
| 1999 | | SUB16(dst, src); |
| 2000 | | BUMP_DI(2); |
| 2001 | | CYCLES(CYCLES_SCAS); |
| 2002 | | } |
| 2003 | | |
| 2004 | | void i386_device::i386_shld16_i8() // Opcode 0x0f a4 |
| 2005 | | { |
| 2006 | | UINT8 modrm = FETCH(); |
| 2007 | | if( modrm >= 0xc0 ) { |
| 2008 | | UINT16 dst = LOAD_RM16(modrm); |
| 2009 | | UINT16 upper = LOAD_REG16(modrm); |
| 2010 | | UINT8 shift = FETCH(); |
| 2011 | | shift &= 31; |
| 2012 | | if( shift == 0 ) { |
| 2013 | | } else if( shift > 15 ) { |
| 2014 | | m_CF = (upper & (1 << (16-shift))) ? 1 : 0; |
| 2015 | | // ppro and above should be (dst >> (32-shift)) |
| 2016 | | dst = (upper << (shift-16)) | (upper >> (32-shift)); |
| 2017 | | m_OF = m_CF ^ (dst >> 15); |
| 2018 | | SetSZPF16(dst); |
| 2019 | | } else { |
| 2020 | | m_CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2021 | | dst = (dst << shift) | (upper >> (16-shift)); |
| 2022 | | m_OF = m_CF ^ (dst >> 15); |
| 2023 | | SetSZPF16(dst); |
| 2024 | | } |
| 2025 | | STORE_RM16(modrm, dst); |
| 2026 | | CYCLES(CYCLES_SHLD_REG); |
| 2027 | | } else { |
| 2028 | | UINT32 ea = GetEA(modrm,1); |
| 2029 | | UINT16 dst = READ16(ea); |
| 2030 | | UINT16 upper = LOAD_REG16(modrm); |
| 2031 | | UINT8 shift = FETCH(); |
| 2032 | | shift &= 31; |
| 2033 | | if( shift == 0 ) { |
| 2034 | | } else if( shift > 15 ) { |
| 2035 | | m_CF = (upper & (1 << (16-shift))) ? 1 : 0; |
| 2036 | | dst = (upper << (shift-16)) | (upper >> (32-shift)); |
| 2037 | | m_OF = m_CF ^ (dst >> 15); |
| 2038 | | SetSZPF16(dst); |
| 2039 | | } else { |
| 2040 | | m_CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2041 | | dst = (dst << shift) | (upper >> (16-shift)); |
| 2042 | | m_OF = m_CF ^ (dst >> 15); |
| 2043 | | SetSZPF16(dst); |
| 2044 | | } |
| 2045 | | WRITE16(ea, dst); |
| 2046 | | CYCLES(CYCLES_SHLD_MEM); |
| 2047 | | } |
| 2048 | | } |
| 2049 | | |
| 2050 | | void i386_device::i386_shld16_cl() // Opcode 0x0f a5 |
| 2051 | | { |
| 2052 | | UINT8 modrm = FETCH(); |
| 2053 | | if( modrm >= 0xc0 ) { |
| 2054 | | UINT16 dst = LOAD_RM16(modrm); |
| 2055 | | UINT16 upper = LOAD_REG16(modrm); |
| 2056 | | UINT8 shift = REG8(CL); |
| 2057 | | shift &= 31; |
| 2058 | | if( shift == 0 ) { |
| 2059 | | } else if( shift > 15 ) { |
| 2060 | | m_CF = (upper & (1 << (16-shift))) ? 1 : 0; |
| 2061 | | dst = (upper << (shift-16)) | (upper >> (32-shift)); |
| 2062 | | m_OF = m_CF ^ (dst >> 15); |
| 2063 | | SetSZPF16(dst); |
| 2064 | | } else { |
| 2065 | | m_CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2066 | | dst = (dst << shift) | (upper >> (16-shift)); |
| 2067 | | m_OF = m_CF ^ (dst >> 15); |
| 2068 | | SetSZPF16(dst); |
| 2069 | | } |
| 2070 | | STORE_RM16(modrm, dst); |
| 2071 | | CYCLES(CYCLES_SHLD_REG); |
| 2072 | | } else { |
| 2073 | | UINT32 ea = GetEA(modrm,1); |
| 2074 | | UINT16 dst = READ16(ea); |
| 2075 | | UINT16 upper = LOAD_REG16(modrm); |
| 2076 | | UINT8 shift = REG8(CL); |
| 2077 | | shift &= 31; |
| 2078 | | if( shift == 0 ) { |
| 2079 | | } else if( shift > 15 ) { |
| 2080 | | m_CF = (upper & (1 << (16-shift))) ? 1 : 0; |
| 2081 | | dst = (upper << (shift-16)) | (upper >> (32-shift)); |
| 2082 | | m_OF = m_CF ^ (dst >> 15); |
| 2083 | | SetSZPF16(dst); |
| 2084 | | } else { |
| 2085 | | m_CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2086 | | dst = (dst << shift) | (upper >> (16-shift)); |
| 2087 | | m_OF = m_CF ^ (dst >> 15); |
| 2088 | | SetSZPF16(dst); |
| 2089 | | } |
| 2090 | | WRITE16(ea, dst); |
| 2091 | | CYCLES(CYCLES_SHLD_MEM); |
| 2092 | | } |
| 2093 | | } |
| 2094 | | |
| 2095 | | void i386_device::i386_shrd16_i8() // Opcode 0x0f ac |
| 2096 | | { |
| 2097 | | UINT8 modrm = FETCH(); |
| 2098 | | if( modrm >= 0xc0 ) { |
| 2099 | | UINT16 dst = LOAD_RM16(modrm); |
| 2100 | | UINT16 upper = LOAD_REG16(modrm); |
| 2101 | | UINT8 shift = FETCH(); |
| 2102 | | shift &= 31; |
| 2103 | | if( shift == 0) { |
| 2104 | | } else if( shift > 15 ) { |
| 2105 | | m_CF = (upper & (1 << (shift-1))) ? 1 : 0; |
| 2106 | | dst = (upper >> (shift-16)) | (upper << (32-shift)); |
| 2107 | | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2108 | | SetSZPF16(dst); |
| 2109 | | } else { |
| 2110 | | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 2111 | | dst = (dst >> shift) | (upper << (16-shift)); |
| 2112 | | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2113 | | SetSZPF16(dst); |
| 2114 | | } |
| 2115 | | STORE_RM16(modrm, dst); |
| 2116 | | CYCLES(CYCLES_SHRD_REG); |
| 2117 | | } else { |
| 2118 | | UINT32 ea = GetEA(modrm,1); |
| 2119 | | UINT16 dst = READ16(ea); |
| 2120 | | UINT16 upper = LOAD_REG16(modrm); |
| 2121 | | UINT8 shift = FETCH(); |
| 2122 | | shift &= 31; |
| 2123 | | if( shift == 0) { |
| 2124 | | } else if( shift > 15 ) { |
| 2125 | | m_CF = (upper & (1 << (shift-1))) ? 1 : 0; |
| 2126 | | dst = (upper >> (shift-16)) | (upper << (32-shift)); |
| 2127 | | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2128 | | SetSZPF16(dst); |
| 2129 | | } else { |
| 2130 | | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 2131 | | dst = (dst >> shift) | (upper << (16-shift)); |
| 2132 | | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2133 | | SetSZPF16(dst); |
| 2134 | | } |
| 2135 | | WRITE16(ea, dst); |
| 2136 | | CYCLES(CYCLES_SHRD_MEM); |
| 2137 | | } |
| 2138 | | } |
| 2139 | | |
| 2140 | | void i386_device::i386_shrd16_cl() // Opcode 0x0f ad |
| 2141 | | { |
| 2142 | | UINT8 modrm = FETCH(); |
| 2143 | | if( modrm >= 0xc0 ) { |
| 2144 | | UINT16 dst = LOAD_RM16(modrm); |
| 2145 | | UINT16 upper = LOAD_REG16(modrm); |
| 2146 | | UINT8 shift = REG8(CL); |
| 2147 | | shift &= 31; |
| 2148 | | if( shift == 0) { |
| 2149 | | } else if( shift > 15 ) { |
| 2150 | | m_CF = (upper & (1 << (shift-1))) ? 1 : 0; |
| 2151 | | dst = (upper >> (shift-16)) | (upper << (32-shift)); |
| 2152 | | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2153 | | SetSZPF16(dst); |
| 2154 | | } else { |
| 2155 | | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 2156 | | dst = (dst >> shift) | (upper << (16-shift)); |
| 2157 | | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2158 | | SetSZPF16(dst); |
| 2159 | | } |
| 2160 | | STORE_RM16(modrm, dst); |
| 2161 | | CYCLES(CYCLES_SHRD_REG); |
| 2162 | | } else { |
| 2163 | | UINT32 ea = GetEA(modrm,1); |
| 2164 | | UINT16 dst = READ16(ea); |
| 2165 | | UINT16 upper = LOAD_REG16(modrm); |
| 2166 | | UINT8 shift = REG8(CL); |
| 2167 | | shift &= 31; |
| 2168 | | if( shift == 0) { |
| 2169 | | } else if( shift > 15 ) { |
| 2170 | | m_CF = (upper & (1 << (shift-1))) ? 1 : 0; |
| 2171 | | dst = (upper >> (shift-16)) | (upper << (32-shift)); |
| 2172 | | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2173 | | SetSZPF16(dst); |
| 2174 | | } else { |
| 2175 | | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 2176 | | dst = (dst >> shift) | (upper << (16-shift)); |
| 2177 | | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2178 | | SetSZPF16(dst); |
| 2179 | | } |
| 2180 | | WRITE16(ea, dst); |
| 2181 | | CYCLES(CYCLES_SHRD_MEM); |
| 2182 | | } |
| 2183 | | } |
| 2184 | | |
| 2185 | | void i386_device::i386_stosw() // Opcode 0xab |
| 2186 | | { |
| 2187 | | UINT32 ead; |
| 2188 | | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 2189 | | WRITE16(ead, REG16(AX)); |
| 2190 | | BUMP_DI(2); |
| 2191 | | CYCLES(CYCLES_STOS); |
| 2192 | | } |
| 2193 | | |
| 2194 | | void i386_device::i386_sub_rm16_r16() // Opcode 0x29 |
| 2195 | | { |
| 2196 | | UINT16 src, dst; |
| 2197 | | UINT8 modrm = FETCH(); |
| 2198 | | if( modrm >= 0xc0 ) { |
| 2199 | | src = LOAD_REG16(modrm); |
| 2200 | | dst = LOAD_RM16(modrm); |
| 2201 | | dst = SUB16(dst, src); |
| 2202 | | STORE_RM16(modrm, dst); |
| 2203 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2204 | | } else { |
| 2205 | | UINT32 ea = GetEA(modrm,1); |
| 2206 | | src = LOAD_REG16(modrm); |
| 2207 | | dst = READ16(ea); |
| 2208 | | dst = SUB16(dst, src); |
| 2209 | | WRITE16(ea, dst); |
| 2210 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2211 | | } |
| 2212 | | } |
| 2213 | | |
| 2214 | | void i386_device::i386_sub_r16_rm16() // Opcode 0x2b |
| 2215 | | { |
| 2216 | | UINT16 src, dst; |
| 2217 | | UINT8 modrm = FETCH(); |
| 2218 | | if( modrm >= 0xc0 ) { |
| 2219 | | src = LOAD_RM16(modrm); |
| 2220 | | dst = LOAD_REG16(modrm); |
| 2221 | | dst = SUB16(dst, src); |
| 2222 | | STORE_REG16(modrm, dst); |
| 2223 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2224 | | } else { |
| 2225 | | UINT32 ea = GetEA(modrm,0); |
| 2226 | | src = READ16(ea); |
| 2227 | | dst = LOAD_REG16(modrm); |
| 2228 | | dst = SUB16(dst, src); |
| 2229 | | STORE_REG16(modrm, dst); |
| 2230 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 2231 | | } |
| 2232 | | } |
| 2233 | | |
| 2234 | | void i386_device::i386_sub_ax_i16() // Opcode 0x2d |
| 2235 | | { |
| 2236 | | UINT16 src, dst; |
| 2237 | | src = FETCH16(); |
| 2238 | | dst = REG16(AX); |
| 2239 | | dst = SUB16(dst, src); |
| 2240 | | REG16(AX) = dst; |
| 2241 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 2242 | | } |
| 2243 | | |
| 2244 | | void i386_device::i386_test_ax_i16() // Opcode 0xa9 |
| 2245 | | { |
| 2246 | | UINT16 src = FETCH16(); |
| 2247 | | UINT16 dst = REG16(AX); |
| 2248 | | dst = src & dst; |
| 2249 | | SetSZPF16(dst); |
| 2250 | | m_CF = 0; |
| 2251 | | m_OF = 0; |
| 2252 | | CYCLES(CYCLES_TEST_IMM_ACC); |
| 2253 | | } |
| 2254 | | |
| 2255 | | void i386_device::i386_test_rm16_r16() // Opcode 0x85 |
| 2256 | | { |
| 2257 | | UINT16 src, dst; |
| 2258 | | UINT8 modrm = FETCH(); |
| 2259 | | if( modrm >= 0xc0 ) { |
| 2260 | | src = LOAD_REG16(modrm); |
| 2261 | | dst = LOAD_RM16(modrm); |
| 2262 | | dst = src & dst; |
| 2263 | | SetSZPF16(dst); |
| 2264 | | m_CF = 0; |
| 2265 | | m_OF = 0; |
| 2266 | | CYCLES(CYCLES_TEST_REG_REG); |
| 2267 | | } else { |
| 2268 | | UINT32 ea = GetEA(modrm,0); |
| 2269 | | src = LOAD_REG16(modrm); |
| 2270 | | dst = READ16(ea); |
| 2271 | | dst = src & dst; |
| 2272 | | SetSZPF16(dst); |
| 2273 | | m_CF = 0; |
| 2274 | | m_OF = 0; |
| 2275 | | CYCLES(CYCLES_TEST_REG_MEM); |
| 2276 | | } |
| 2277 | | } |
| 2278 | | |
| 2279 | | void i386_device::i386_xchg_ax_cx() // Opcode 0x91 |
| 2280 | | { |
| 2281 | | UINT16 temp; |
| 2282 | | temp = REG16(AX); |
| 2283 | | REG16(AX) = REG16(CX); |
| 2284 | | REG16(CX) = temp; |
| 2285 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2286 | | } |
| 2287 | | |
| 2288 | | void i386_device::i386_xchg_ax_dx() // Opcode 0x92 |
| 2289 | | { |
| 2290 | | UINT16 temp; |
| 2291 | | temp = REG16(AX); |
| 2292 | | REG16(AX) = REG16(DX); |
| 2293 | | REG16(DX) = temp; |
| 2294 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2295 | | } |
| 2296 | | |
| 2297 | | void i386_device::i386_xchg_ax_bx() // Opcode 0x93 |
| 2298 | | { |
| 2299 | | UINT16 temp; |
| 2300 | | temp = REG16(AX); |
| 2301 | | REG16(AX) = REG16(BX); |
| 2302 | | REG16(BX) = temp; |
| 2303 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2304 | | } |
| 2305 | | |
| 2306 | | void i386_device::i386_xchg_ax_sp() // Opcode 0x94 |
| 2307 | | { |
| 2308 | | UINT16 temp; |
| 2309 | | temp = REG16(AX); |
| 2310 | | REG16(AX) = REG16(SP); |
| 2311 | | REG16(SP) = temp; |
| 2312 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2313 | | } |
| 2314 | | |
| 2315 | | void i386_device::i386_xchg_ax_bp() // Opcode 0x95 |
| 2316 | | { |
| 2317 | | UINT16 temp; |
| 2318 | | temp = REG16(AX); |
| 2319 | | REG16(AX) = REG16(BP); |
| 2320 | | REG16(BP) = temp; |
| 2321 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2322 | | } |
| 2323 | | |
| 2324 | | void i386_device::i386_xchg_ax_si() // Opcode 0x96 |
| 2325 | | { |
| 2326 | | UINT16 temp; |
| 2327 | | temp = REG16(AX); |
| 2328 | | REG16(AX) = REG16(SI); |
| 2329 | | REG16(SI) = temp; |
| 2330 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2331 | | } |
| 2332 | | |
| 2333 | | void i386_device::i386_xchg_ax_di() // Opcode 0x97 |
| 2334 | | { |
| 2335 | | UINT16 temp; |
| 2336 | | temp = REG16(AX); |
| 2337 | | REG16(AX) = REG16(DI); |
| 2338 | | REG16(DI) = temp; |
| 2339 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2340 | | } |
| 2341 | | |
| 2342 | | void i386_device::i386_xchg_r16_rm16() // Opcode 0x87 |
| 2343 | | { |
| 2344 | | UINT8 modrm = FETCH(); |
| 2345 | | if( modrm >= 0xc0 ) { |
| 2346 | | UINT16 src = LOAD_RM16(modrm); |
| 2347 | | UINT16 dst = LOAD_REG16(modrm); |
| 2348 | | STORE_REG16(modrm, src); |
| 2349 | | STORE_RM16(modrm, dst); |
| 2350 | | CYCLES(CYCLES_XCHG_REG_REG); |
| 2351 | | } else { |
| 2352 | | UINT32 ea = GetEA(modrm,1); |
| 2353 | | UINT16 src = READ16(ea); |
| 2354 | | UINT16 dst = LOAD_REG16(modrm); |
| 2355 | | STORE_REG16(modrm, src); |
| 2356 | | WRITE16(ea, dst); |
| 2357 | | CYCLES(CYCLES_XCHG_REG_MEM); |
| 2358 | | } |
| 2359 | | } |
| 2360 | | |
| 2361 | | void i386_device::i386_xor_rm16_r16() // Opcode 0x31 |
| 2362 | | { |
| 2363 | | UINT16 src, dst; |
| 2364 | | UINT8 modrm = FETCH(); |
| 2365 | | if( modrm >= 0xc0 ) { |
| 2366 | | src = LOAD_REG16(modrm); |
| 2367 | | dst = LOAD_RM16(modrm); |
| 2368 | | dst = XOR16(dst, src); |
| 2369 | | STORE_RM16(modrm, dst); |
| 2370 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2371 | | } else { |
| 2372 | | UINT32 ea = GetEA(modrm,1); |
| 2373 | | src = LOAD_REG16(modrm); |
| 2374 | | dst = READ16(ea); |
| 2375 | | dst = XOR16(dst, src); |
| 2376 | | WRITE16(ea, dst); |
| 2377 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2378 | | } |
| 2379 | | } |
| 2380 | | |
| 2381 | | void i386_device::i386_xor_r16_rm16() // Opcode 0x33 |
| 2382 | | { |
| 2383 | | UINT16 src, dst; |
| 2384 | | UINT8 modrm = FETCH(); |
| 2385 | | if( modrm >= 0xc0 ) { |
| 2386 | | src = LOAD_RM16(modrm); |
| 2387 | | dst = LOAD_REG16(modrm); |
| 2388 | | dst = XOR16(dst, src); |
| 2389 | | STORE_REG16(modrm, dst); |
| 2390 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2391 | | } else { |
| 2392 | | UINT32 ea = GetEA(modrm,0); |
| 2393 | | src = READ16(ea); |
| 2394 | | dst = LOAD_REG16(modrm); |
| 2395 | | dst = XOR16(dst, src); |
| 2396 | | STORE_REG16(modrm, dst); |
| 2397 | | CYCLES(CYCLES_ALU_MEM_REG); |
| 2398 | | } |
| 2399 | | } |
| 2400 | | |
| 2401 | | void i386_device::i386_xor_ax_i16() // Opcode 0x35 |
| 2402 | | { |
| 2403 | | UINT16 src, dst; |
| 2404 | | src = FETCH16(); |
| 2405 | | dst = REG16(AX); |
| 2406 | | dst = XOR16(dst, src); |
| 2407 | | REG16(AX) = dst; |
| 2408 | | CYCLES(CYCLES_ALU_IMM_ACC); |
| 2409 | | } |
| 2410 | | |
| 2411 | | |
| 2412 | | |
| 2413 | | void i386_device::i386_group81_16() // Opcode 0x81 |
| 2414 | | { |
| 2415 | | UINT32 ea; |
| 2416 | | UINT16 src, dst; |
| 2417 | | UINT8 modrm = FETCH(); |
| 2418 | | |
| 2419 | | switch( (modrm >> 3) & 0x7 ) |
| 2420 | | { |
| 2421 | | case 0: // ADD Rm16, i16 |
| 2422 | | if( modrm >= 0xc0 ) { |
| 2423 | | dst = LOAD_RM16(modrm); |
| 2424 | | src = FETCH16(); |
| 2425 | | dst = ADD16(dst, src); |
| 2426 | | STORE_RM16(modrm, dst); |
| 2427 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2428 | | } else { |
| 2429 | | ea = GetEA(modrm,1); |
| 2430 | | dst = READ16(ea); |
| 2431 | | src = FETCH16(); |
| 2432 | | dst = ADD16(dst, src); |
| 2433 | | WRITE16(ea, dst); |
| 2434 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2435 | | } |
| 2436 | | break; |
| 2437 | | case 1: // OR Rm16, i16 |
| 2438 | | if( modrm >= 0xc0 ) { |
| 2439 | | dst = LOAD_RM16(modrm); |
| 2440 | | src = FETCH16(); |
| 2441 | | dst = OR16(dst, src); |
| 2442 | | STORE_RM16(modrm, dst); |
| 2443 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2444 | | } else { |
| 2445 | | ea = GetEA(modrm,1); |
| 2446 | | dst = READ16(ea); |
| 2447 | | src = FETCH16(); |
| 2448 | | dst = OR16(dst, src); |
| 2449 | | WRITE16(ea, dst); |
| 2450 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2451 | | } |
| 2452 | | break; |
| 2453 | | case 2: // ADC Rm16, i16 |
| 2454 | | if( modrm >= 0xc0 ) { |
| 2455 | | dst = LOAD_RM16(modrm); |
| 2456 | | src = FETCH16(); |
| 2457 | | dst = ADC16(dst, src, m_CF); |
| 2458 | | STORE_RM16(modrm, dst); |
| 2459 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2460 | | } else { |
| 2461 | | ea = GetEA(modrm,1); |
| 2462 | | dst = READ16(ea); |
| 2463 | | src = FETCH16(); |
| 2464 | | dst = ADC16(dst, src, m_CF); |
| 2465 | | WRITE16(ea, dst); |
| 2466 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2467 | | } |
| 2468 | | break; |
| 2469 | | case 3: // SBB Rm16, i16 |
| 2470 | | if( modrm >= 0xc0 ) { |
| 2471 | | dst = LOAD_RM16(modrm); |
| 2472 | | src = FETCH16(); |
| 2473 | | dst = SBB16(dst, src, m_CF); |
| 2474 | | STORE_RM16(modrm, dst); |
| 2475 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2476 | | } else { |
| 2477 | | ea = GetEA(modrm,1); |
| 2478 | | dst = READ16(ea); |
| 2479 | | src = FETCH16(); |
| 2480 | | dst = SBB16(dst, src, m_CF); |
| 2481 | | WRITE16(ea, dst); |
| 2482 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2483 | | } |
| 2484 | | break; |
| 2485 | | case 4: // AND Rm16, i16 |
| 2486 | | if( modrm >= 0xc0 ) { |
| 2487 | | dst = LOAD_RM16(modrm); |
| 2488 | | src = FETCH16(); |
| 2489 | | dst = AND16(dst, src); |
| 2490 | | STORE_RM16(modrm, dst); |
| 2491 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2492 | | } else { |
| 2493 | | ea = GetEA(modrm,1); |
| 2494 | | dst = READ16(ea); |
| 2495 | | src = FETCH16(); |
| 2496 | | dst = AND16(dst, src); |
| 2497 | | WRITE16(ea, dst); |
| 2498 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2499 | | } |
| 2500 | | break; |
| 2501 | | case 5: // SUB Rm16, i16 |
| 2502 | | if( modrm >= 0xc0 ) { |
| 2503 | | dst = LOAD_RM16(modrm); |
| 2504 | | src = FETCH16(); |
| 2505 | | dst = SUB16(dst, src); |
| 2506 | | STORE_RM16(modrm, dst); |
| 2507 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2508 | | } else { |
| 2509 | | ea = GetEA(modrm,1); |
| 2510 | | dst = READ16(ea); |
| 2511 | | src = FETCH16(); |
| 2512 | | dst = SUB16(dst, src); |
| 2513 | | WRITE16(ea, dst); |
| 2514 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2515 | | } |
| 2516 | | break; |
| 2517 | | case 6: // XOR Rm16, i16 |
| 2518 | | if( modrm >= 0xc0 ) { |
| 2519 | | dst = LOAD_RM16(modrm); |
| 2520 | | src = FETCH16(); |
| 2521 | | dst = XOR16(dst, src); |
| 2522 | | STORE_RM16(modrm, dst); |
| 2523 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2524 | | } else { |
| 2525 | | ea = GetEA(modrm,1); |
| 2526 | | dst = READ16(ea); |
| 2527 | | src = FETCH16(); |
| 2528 | | dst = XOR16(dst, src); |
| 2529 | | WRITE16(ea, dst); |
| 2530 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2531 | | } |
| 2532 | | break; |
| 2533 | | case 7: // CMP Rm16, i16 |
| 2534 | | if( modrm >= 0xc0 ) { |
| 2535 | | dst = LOAD_RM16(modrm); |
| 2536 | | src = FETCH16(); |
| 2537 | | SUB16(dst, src); |
| 2538 | | CYCLES(CYCLES_CMP_REG_REG); |
| 2539 | | } else { |
| 2540 | | ea = GetEA(modrm,0); |
| 2541 | | dst = READ16(ea); |
| 2542 | | src = FETCH16(); |
| 2543 | | SUB16(dst, src); |
| 2544 | | CYCLES(CYCLES_CMP_REG_MEM); |
| 2545 | | } |
| 2546 | | break; |
| 2547 | | } |
| 2548 | | } |
| 2549 | | |
| 2550 | | void i386_device::i386_group83_16() // Opcode 0x83 |
| 2551 | | { |
| 2552 | | UINT32 ea; |
| 2553 | | UINT16 src, dst; |
| 2554 | | UINT8 modrm = FETCH(); |
| 2555 | | |
| 2556 | | switch( (modrm >> 3) & 0x7 ) |
| 2557 | | { |
| 2558 | | case 0: // ADD Rm16, i16 |
| 2559 | | if( modrm >= 0xc0 ) { |
| 2560 | | dst = LOAD_RM16(modrm); |
| 2561 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2562 | | dst = ADD16(dst, src); |
| 2563 | | STORE_RM16(modrm, dst); |
| 2564 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2565 | | } else { |
| 2566 | | ea = GetEA(modrm,1); |
| 2567 | | dst = READ16(ea); |
| 2568 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2569 | | dst = ADD16(dst, src); |
| 2570 | | WRITE16(ea, dst); |
| 2571 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2572 | | } |
| 2573 | | break; |
| 2574 | | case 1: // OR Rm16, i16 |
| 2575 | | if( modrm >= 0xc0 ) { |
| 2576 | | dst = LOAD_RM16(modrm); |
| 2577 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2578 | | dst = OR16(dst, src); |
| 2579 | | STORE_RM16(modrm, dst); |
| 2580 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2581 | | } else { |
| 2582 | | ea = GetEA(modrm,1); |
| 2583 | | dst = READ16(ea); |
| 2584 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2585 | | dst = OR16(dst, src); |
| 2586 | | WRITE16(ea, dst); |
| 2587 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2588 | | } |
| 2589 | | break; |
| 2590 | | case 2: // ADC Rm16, i16 |
| 2591 | | if( modrm >= 0xc0 ) { |
| 2592 | | dst = LOAD_RM16(modrm); |
| 2593 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2594 | | dst = ADC16(dst, src, m_CF); |
| 2595 | | STORE_RM16(modrm, dst); |
| 2596 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2597 | | } else { |
| 2598 | | ea = GetEA(modrm,1); |
| 2599 | | dst = READ16(ea); |
| 2600 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2601 | | dst = ADC16(dst, src, m_CF); |
| 2602 | | WRITE16(ea, dst); |
| 2603 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2604 | | } |
| 2605 | | break; |
| 2606 | | case 3: // SBB Rm16, i16 |
| 2607 | | if( modrm >= 0xc0 ) { |
| 2608 | | dst = LOAD_RM16(modrm); |
| 2609 | | src = ((UINT16)(INT16)(INT8)FETCH()); |
| 2610 | | dst = SBB16(dst, src, m_CF); |
| 2611 | | STORE_RM16(modrm, dst); |
| 2612 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2613 | | } else { |
| 2614 | | ea = GetEA(modrm,1); |
| 2615 | | dst = READ16(ea); |
| 2616 | | src = ((UINT16)(INT16)(INT8)FETCH()); |
| 2617 | | dst = SBB16(dst, src, m_CF); |
| 2618 | | WRITE16(ea, dst); |
| 2619 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2620 | | } |
| 2621 | | break; |
| 2622 | | case 4: // AND Rm16, i16 |
| 2623 | | if( modrm >= 0xc0 ) { |
| 2624 | | dst = LOAD_RM16(modrm); |
| 2625 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2626 | | dst = AND16(dst, src); |
| 2627 | | STORE_RM16(modrm, dst); |
| 2628 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2629 | | } else { |
| 2630 | | ea = GetEA(modrm,1); |
| 2631 | | dst = READ16(ea); |
| 2632 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2633 | | dst = AND16(dst, src); |
| 2634 | | WRITE16(ea, dst); |
| 2635 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2636 | | } |
| 2637 | | break; |
| 2638 | | case 5: // SUB Rm16, i16 |
| 2639 | | if( modrm >= 0xc0 ) { |
| 2640 | | dst = LOAD_RM16(modrm); |
| 2641 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2642 | | dst = SUB16(dst, src); |
| 2643 | | STORE_RM16(modrm, dst); |
| 2644 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2645 | | } else { |
| 2646 | | ea = GetEA(modrm,1); |
| 2647 | | dst = READ16(ea); |
| 2648 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2649 | | dst = SUB16(dst, src); |
| 2650 | | WRITE16(ea, dst); |
| 2651 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2652 | | } |
| 2653 | | break; |
| 2654 | | case 6: // XOR Rm16, i16 |
| 2655 | | if( modrm >= 0xc0 ) { |
| 2656 | | dst = LOAD_RM16(modrm); |
| 2657 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2658 | | dst = XOR16(dst, src); |
| 2659 | | STORE_RM16(modrm, dst); |
| 2660 | | CYCLES(CYCLES_ALU_REG_REG); |
| 2661 | | } else { |
| 2662 | | ea = GetEA(modrm,1); |
| 2663 | | dst = READ16(ea); |
| 2664 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2665 | | dst = XOR16(dst, src); |
| 2666 | | WRITE16(ea, dst); |
| 2667 | | CYCLES(CYCLES_ALU_REG_MEM); |
| 2668 | | } |
| 2669 | | break; |
| 2670 | | case 7: // CMP Rm16, i16 |
| 2671 | | if( modrm >= 0xc0 ) { |
| 2672 | | dst = LOAD_RM16(modrm); |
| 2673 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2674 | | SUB16(dst, src); |
| 2675 | | CYCLES(CYCLES_CMP_REG_REG); |
| 2676 | | } else { |
| 2677 | | ea = GetEA(modrm,0); |
| 2678 | | dst = READ16(ea); |
| 2679 | | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2680 | | SUB16(dst, src); |
| 2681 | | CYCLES(CYCLES_CMP_REG_MEM); |
| 2682 | | } |
| 2683 | | break; |
| 2684 | | } |
| 2685 | | } |
| 2686 | | |
| 2687 | | void i386_device::i386_groupC1_16() // Opcode 0xc1 |
| 2688 | | { |
| 2689 | | UINT16 dst; |
| 2690 | | UINT8 modrm = FETCH(); |
| 2691 | | UINT8 shift; |
| 2692 | | |
| 2693 | | if( modrm >= 0xc0 ) { |
| 2694 | | dst = LOAD_RM16(modrm); |
| 2695 | | shift = FETCH() & 0x1f; |
| 2696 | | dst = i386_shift_rotate16(modrm, dst, shift); |
| 2697 | | STORE_RM16(modrm, dst); |
| 2698 | | } else { |
| 2699 | | UINT32 ea = GetEA(modrm,1); |
| 2700 | | dst = READ16(ea); |
| 2701 | | shift = FETCH() & 0x1f; |
| 2702 | | dst = i386_shift_rotate16(modrm, dst, shift); |
| 2703 | | WRITE16(ea, dst); |
| 2704 | | } |
| 2705 | | } |
| 2706 | | |
| 2707 | | void i386_device::i386_groupD1_16() // Opcode 0xd1 |
| 2708 | | { |
| 2709 | | UINT16 dst; |
| 2710 | | UINT8 modrm = FETCH(); |
| 2711 | | |
| 2712 | | if( modrm >= 0xc0 ) { |
| 2713 | | dst = LOAD_RM16(modrm); |
| 2714 | | dst = i386_shift_rotate16(modrm, dst, 1); |
| 2715 | | STORE_RM16(modrm, dst); |
| 2716 | | } else { |
| 2717 | | UINT32 ea = GetEA(modrm,1); |
| 2718 | | dst = READ16(ea); |
| 2719 | | dst = i386_shift_rotate16(modrm, dst, 1); |
| 2720 | | WRITE16(ea, dst); |
| 2721 | | } |
| 2722 | | } |
| 2723 | | |
| 2724 | | void i386_device::i386_groupD3_16() // Opcode 0xd3 |
| 2725 | | { |
| 2726 | | UINT16 dst; |
| 2727 | | UINT8 modrm = FETCH(); |
| 2728 | | |
| 2729 | | if( modrm >= 0xc0 ) { |
| 2730 | | dst = LOAD_RM16(modrm); |
| 2731 | | dst = i386_shift_rotate16(modrm, dst, REG8(CL)); |
| 2732 | | STORE_RM16(modrm, dst); |
| 2733 | | } else { |
| 2734 | | UINT32 ea = GetEA(modrm,1); |
| 2735 | | dst = READ16(ea); |
| 2736 | | dst = i386_shift_rotate16(modrm, dst, REG8(CL)); |
| 2737 | | WRITE16(ea, dst); |
| 2738 | | } |
| 2739 | | } |
| 2740 | | |
| 2741 | | void i386_device::i386_groupF7_16() // Opcode 0xf7 |
| 2742 | | { |
| 2743 | | UINT8 modrm = FETCH(); |
| 2744 | | |
| 2745 | | switch( (modrm >> 3) & 0x7 ) |
| 2746 | | { |
| 2747 | | case 0: /* TEST Rm16, i16 */ |
| 2748 | | if( modrm >= 0xc0 ) { |
| 2749 | | UINT16 dst = LOAD_RM16(modrm); |
| 2750 | | UINT16 src = FETCH16(); |
| 2751 | | dst &= src; |
| 2752 | | m_CF = m_OF = m_AF = 0; |
| 2753 | | SetSZPF16(dst); |
| 2754 | | CYCLES(CYCLES_TEST_IMM_REG); |
| 2755 | | } else { |
| 2756 | | UINT32 ea = GetEA(modrm,0); |
| 2757 | | UINT16 dst = READ16(ea); |
| 2758 | | UINT16 src = FETCH16(); |
| 2759 | | dst &= src; |
| 2760 | | m_CF = m_OF = m_AF = 0; |
| 2761 | | SetSZPF16(dst); |
| 2762 | | CYCLES(CYCLES_TEST_IMM_MEM); |
| 2763 | | } |
| 2764 | | break; |
| 2765 | | case 2: /* NOT Rm16 */ |
| 2766 | | if( modrm >= 0xc0 ) { |
| 2767 | | UINT16 dst = LOAD_RM16(modrm); |
| 2768 | | dst = ~dst; |
| 2769 | | STORE_RM16(modrm, dst); |
| 2770 | | CYCLES(CYCLES_NOT_REG); |
| 2771 | | } else { |
| 2772 | | UINT32 ea = GetEA(modrm,1); |
| 2773 | | UINT16 dst = READ16(ea); |
| 2774 | | dst = ~dst; |
| 2775 | | WRITE16(ea, dst); |
| 2776 | | CYCLES(CYCLES_NOT_MEM); |
| 2777 | | } |
| 2778 | | break; |
| 2779 | | case 3: /* NEG Rm16 */ |
| 2780 | | if( modrm >= 0xc0 ) { |
| 2781 | | UINT16 dst = LOAD_RM16(modrm); |
| 2782 | | dst = SUB16(0, dst ); |
| 2783 | | STORE_RM16(modrm, dst); |
| 2784 | | CYCLES(CYCLES_NEG_REG); |
| 2785 | | } else { |
| 2786 | | UINT32 ea = GetEA(modrm,1); |
| 2787 | | UINT16 dst = READ16(ea); |
| 2788 | | dst = SUB16(0, dst ); |
| 2789 | | WRITE16(ea, dst); |
| 2790 | | CYCLES(CYCLES_NEG_MEM); |
| 2791 | | } |
| 2792 | | break; |
| 2793 | | case 4: /* MUL AX, Rm16 */ |
| 2794 | | { |
| 2795 | | UINT32 result; |
| 2796 | | UINT16 src, dst; |
| 2797 | | if( modrm >= 0xc0 ) { |
| 2798 | | src = LOAD_RM16(modrm); |
| 2799 | | CYCLES(CYCLES_MUL16_ACC_REG); /* TODO: Correct multiply timing */ |
| 2800 | | } else { |
| 2801 | | UINT32 ea = GetEA(modrm,0); |
| 2802 | | src = READ16(ea); |
| 2803 | | CYCLES(CYCLES_MUL16_ACC_MEM); /* TODO: Correct multiply timing */ |
| 2804 | | } |
| 2805 | | |
| 2806 | | dst = REG16(AX); |
| 2807 | | result = (UINT32)src * (UINT32)dst; |
| 2808 | | REG16(DX) = (UINT16)(result >> 16); |
| 2809 | | REG16(AX) = (UINT16)result; |
| 2810 | | |
| 2811 | | m_CF = m_OF = (REG16(DX) != 0); |
| 2812 | | } |
| 2813 | | break; |
| 2814 | | case 5: /* IMUL AX, Rm16 */ |
| 2815 | | { |
| 2816 | | INT32 result; |
| 2817 | | INT32 src, dst; |
| 2818 | | if( modrm >= 0xc0 ) { |
| 2819 | | src = (INT32)(INT16)LOAD_RM16(modrm); |
| 2820 | | CYCLES(CYCLES_IMUL16_ACC_REG); /* TODO: Correct multiply timing */ |
| 2821 | | } else { |
| 2822 | | UINT32 ea = GetEA(modrm,0); |
| 2823 | | src = (INT32)(INT16)READ16(ea); |
| 2824 | | CYCLES(CYCLES_IMUL16_ACC_MEM); /* TODO: Correct multiply timing */ |
| 2825 | | } |
| 2826 | | |
| 2827 | | dst = (INT32)(INT16)REG16(AX); |
| 2828 | | result = src * dst; |
| 2829 | | |
| 2830 | | REG16(DX) = (UINT16)(result >> 16); |
| 2831 | | REG16(AX) = (UINT16)result; |
| 2832 | | |
| 2833 | | m_CF = m_OF = !(result == (INT32)(INT16)result); |
| 2834 | | } |
| 2835 | | break; |
| 2836 | | case 6: /* DIV AX, Rm16 */ |
| 2837 | | { |
| 2838 | | UINT32 quotient, remainder, result; |
| 2839 | | UINT16 src; |
| 2840 | | if( modrm >= 0xc0 ) { |
| 2841 | | src = LOAD_RM16(modrm); |
| 2842 | | CYCLES(CYCLES_DIV16_ACC_REG); |
| 2843 | | } else { |
| 2844 | | UINT32 ea = GetEA(modrm,0); |
| 2845 | | src = READ16(ea); |
| 2846 | | CYCLES(CYCLES_DIV16_ACC_MEM); |
| 2847 | | } |
| 2848 | | |
| 2849 | | quotient = ((UINT32)(REG16(DX)) << 16) | (UINT32)(REG16(AX)); |
| 2850 | | if( src ) { |
| 2851 | | remainder = quotient % (UINT32)src; |
| 2852 | | result = quotient / (UINT32)src; |
| 2853 | | if( result > 0xffff ) { |
| 2854 | | /* TODO: Divide error */ |
| 2855 | | } else { |
| 2856 | | REG16(DX) = (UINT16)remainder; |
| 2857 | | REG16(AX) = (UINT16)result; |
| 2858 | | |
| 2859 | | // this flag is actually undefined, enable on non-cyrix |
| 2860 | | if (m_cpuid_id0 != 0x69727943) |
| 2861 | | m_CF = 1; |
| 2862 | | } |
| 2863 | | } else { |
| 2864 | | i386_trap(0, 0, 0); |
| 2865 | | } |
| 2866 | | } |
| 2867 | | break; |
| 2868 | | case 7: /* IDIV AX, Rm16 */ |
| 2869 | | { |
| 2870 | | INT32 quotient, remainder, result; |
| 2871 | | UINT16 src; |
| 2872 | | if( modrm >= 0xc0 ) { |
| 2873 | | src = LOAD_RM16(modrm); |
| 2874 | | CYCLES(CYCLES_IDIV16_ACC_REG); |
| 2875 | | } else { |
| 2876 | | UINT32 ea = GetEA(modrm,0); |
| 2877 | | src = READ16(ea); |
| 2878 | | CYCLES(CYCLES_IDIV16_ACC_MEM); |
| 2879 | | } |
| 2880 | | |
| 2881 | | quotient = (((INT32)REG16(DX)) << 16) | ((UINT32)REG16(AX)); |
| 2882 | | if( src ) { |
| 2883 | | remainder = quotient % (INT32)(INT16)src; |
| 2884 | | result = quotient / (INT32)(INT16)src; |
| 2885 | | if( result > 0xffff ) { |
| 2886 | | /* TODO: Divide error */ |
| 2887 | | } else { |
| 2888 | | REG16(DX) = (UINT16)remainder; |
| 2889 | | REG16(AX) = (UINT16)result; |
| 2890 | | |
| 2891 | | // this flag is actually undefined, enable on non-cyrix |
| 2892 | | if (m_cpuid_id0 != 0x69727943) |
| 2893 | | m_CF = 1; |
| 2894 | | } |
| 2895 | | } else { |
| 2896 | | i386_trap(0, 0, 0); |
| 2897 | | } |
| 2898 | | } |
| 2899 | | break; |
| 2900 | | } |
| 2901 | | } |
| 2902 | | |
| 2903 | | void i386_device::i386_groupFF_16() // Opcode 0xff |
| 2904 | | { |
| 2905 | | UINT8 modrm = FETCH(); |
| 2906 | | |
| 2907 | | switch( (modrm >> 3) & 0x7 ) |
| 2908 | | { |
| 2909 | | case 0: /* INC Rm16 */ |
| 2910 | | if( modrm >= 0xc0 ) { |
| 2911 | | UINT16 dst = LOAD_RM16(modrm); |
| 2912 | | dst = INC16(dst); |
| 2913 | | STORE_RM16(modrm, dst); |
| 2914 | | CYCLES(CYCLES_INC_REG); |
| 2915 | | } else { |
| 2916 | | UINT32 ea = GetEA(modrm,1); |
| 2917 | | UINT16 dst = READ16(ea); |
| 2918 | | dst = INC16(dst); |
| 2919 | | WRITE16(ea, dst); |
| 2920 | | CYCLES(CYCLES_INC_MEM); |
| 2921 | | } |
| 2922 | | break; |
| 2923 | | case 1: /* DEC Rm16 */ |
| 2924 | | if( modrm >= 0xc0 ) { |
| 2925 | | UINT16 dst = LOAD_RM16(modrm); |
| 2926 | | dst = DEC16(dst); |
| 2927 | | STORE_RM16(modrm, dst); |
| 2928 | | CYCLES(CYCLES_DEC_REG); |
| 2929 | | } else { |
| 2930 | | UINT32 ea = GetEA(modrm,1); |
| 2931 | | UINT16 dst = READ16(ea); |
| 2932 | | dst = DEC16(dst); |
| 2933 | | WRITE16(ea, dst); |
| 2934 | | CYCLES(CYCLES_DEC_MEM); |
| 2935 | | } |
| 2936 | | break; |
| 2937 | | case 2: /* CALL Rm16 */ |
| 2938 | | { |
| 2939 | | UINT16 address; |
| 2940 | | if( modrm >= 0xc0 ) { |
| 2941 | | address = LOAD_RM16(modrm); |
| 2942 | | CYCLES(CYCLES_CALL_REG); /* TODO: Timing = 7 + m */ |
| 2943 | | } else { |
| 2944 | | UINT32 ea = GetEA(modrm,0); |
| 2945 | | address = READ16(ea); |
| 2946 | | CYCLES(CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */ |
| 2947 | | } |
| 2948 | | PUSH16(m_eip ); |
| 2949 | | m_eip = address; |
| 2950 | | CHANGE_PC(m_eip); |
| 2951 | | } |
| 2952 | | break; |
| 2953 | | case 3: /* CALL FAR Rm16 */ |
| 2954 | | { |
| 2955 | | UINT16 address, selector; |
| 2956 | | if( modrm >= 0xc0 ) |
| 2957 | | { |
| 2958 | | report_invalid_modrm("groupFF_16", modrm); |
| 2959 | | } |
| 2960 | | else |
| 2961 | | { |
| 2962 | | UINT32 ea = GetEA(modrm,0); |
| 2963 | | address = READ16(ea + 0); |
| 2964 | | selector = READ16(ea + 2); |
| 2965 | | CYCLES(CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */ |
| 2966 | | |
| 2967 | | if(PROTECTED_MODE && !V8086_MODE) |
| 2968 | | { |
| 2969 | | i386_protected_mode_call(selector,address,1,0); |
| 2970 | | } |
| 2971 | | else |
| 2972 | | { |
| 2973 | | PUSH16(m_sreg[CS].selector ); |
| 2974 | | PUSH16(m_eip ); |
| 2975 | | m_sreg[CS].selector = selector; |
| 2976 | | m_performed_intersegment_jump = 1; |
| 2977 | | i386_load_segment_descriptor(CS ); |
| 2978 | | m_eip = address; |
| 2979 | | CHANGE_PC(m_eip); |
| 2980 | | } |
| 2981 | | } |
| 2982 | | } |
| 2983 | | break; |
| 2984 | | case 4: /* JMP Rm16 */ |
| 2985 | | { |
| 2986 | | UINT16 address; |
| 2987 | | if( modrm >= 0xc0 ) { |
| 2988 | | address = LOAD_RM16(modrm); |
| 2989 | | CYCLES(CYCLES_JMP_REG); /* TODO: Timing = 7 + m */ |
| 2990 | | } else { |
| 2991 | | UINT32 ea = GetEA(modrm,0); |
| 2992 | | address = READ16(ea); |
| 2993 | | CYCLES(CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */ |
| 2994 | | } |
| 2995 | | m_eip = address; |
| 2996 | | CHANGE_PC(m_eip); |
| 2997 | | } |
| 2998 | | break; |
| 2999 | | case 5: /* JMP FAR Rm16 */ |
| 3000 | | { |
| 3001 | | UINT16 address, selector; |
| 3002 | | |
| 3003 | | if( modrm >= 0xc0 ) |
| 3004 | | { |
| 3005 | | report_invalid_modrm("groupFF_16", modrm); |
| 3006 | | } |
| 3007 | | else |
| 3008 | | { |
| 3009 | | UINT32 ea = GetEA(modrm,0); |
| 3010 | | address = READ16(ea + 0); |
| 3011 | | selector = READ16(ea + 2); |
| 3012 | | CYCLES(CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */ |
| 3013 | | if(PROTECTED_MODE && !V8086_MODE) |
| 3014 | | { |
| 3015 | | i386_protected_mode_jump(selector,address,1,0); |
| 3016 | | } |
| 3017 | | else |
| 3018 | | { |
| 3019 | | m_sreg[CS].selector = selector; |
| 3020 | | m_performed_intersegment_jump = 1; |
| 3021 | | i386_load_segment_descriptor(CS ); |
| 3022 | | m_eip = address; |
| 3023 | | CHANGE_PC(m_eip); |
| 3024 | | } |
| 3025 | | } |
| 3026 | | } |
| 3027 | | break; |
| 3028 | | case 6: /* PUSH Rm16 */ |
| 3029 | | { |
| 3030 | | UINT16 value; |
| 3031 | | if( modrm >= 0xc0 ) { |
| 3032 | | value = LOAD_RM16(modrm); |
| 3033 | | } else { |
| 3034 | | UINT32 ea = GetEA(modrm,0); |
| 3035 | | value = READ16(ea); |
| 3036 | | } |
| 3037 | | PUSH16(value); |
| 3038 | | CYCLES(CYCLES_PUSH_RM); |
| 3039 | | } |
| 3040 | | break; |
| 3041 | | default: |
| 3042 | | report_invalid_modrm("groupFF_16", modrm); |
| 3043 | | break; |
| 3044 | | } |
| 3045 | | } |
| 3046 | | |
| 3047 | | void i386_device::i386_group0F00_16() // Opcode 0x0f 00 |
| 3048 | | { |
| 3049 | | UINT32 address, ea; |
| 3050 | | UINT8 modrm = FETCH(); |
| 3051 | | I386_SREG seg; |
| 3052 | | UINT8 result; |
| 3053 | | |
| 3054 | | switch( (modrm >> 3) & 0x7 ) |
| 3055 | | { |
| 3056 | | case 0: /* SLDT */ |
| 3057 | | if ( PROTECTED_MODE && !V8086_MODE ) |
| 3058 | | { |
| 3059 | | if( modrm >= 0xc0 ) { |
| 3060 | | STORE_RM16(modrm, m_ldtr.segment); |
| 3061 | | CYCLES(CYCLES_SLDT_REG); |
| 3062 | | } else { |
| 3063 | | ea = GetEA(modrm,1); |
| 3064 | | WRITE16(ea, m_ldtr.segment); |
| 3065 | | CYCLES(CYCLES_SLDT_MEM); |
| 3066 | | } |
| 3067 | | } |
| 3068 | | else |
| 3069 | | { |
| 3070 | | i386_trap(6, 0, 0); |
| 3071 | | } |
| 3072 | | break; |
| 3073 | | case 1: /* STR */ |
| 3074 | | if ( PROTECTED_MODE && !V8086_MODE ) |
| 3075 | | { |
| 3076 | | if( modrm >= 0xc0 ) { |
| 3077 | | STORE_RM16(modrm, m_task.segment); |
| 3078 | | CYCLES(CYCLES_STR_REG); |
| 3079 | | } else { |
| 3080 | | ea = GetEA(modrm,1); |
| 3081 | | WRITE16(ea, m_task.segment); |
| 3082 | | CYCLES(CYCLES_STR_MEM); |
| 3083 | | } |
| 3084 | | } |
| 3085 | | else |
| 3086 | | { |
| 3087 | | i386_trap(6, 0, 0); |
| 3088 | | } |
| 3089 | | break; |
| 3090 | | case 2: /* LLDT */ |
| 3091 | | if ( PROTECTED_MODE && !V8086_MODE ) |
| 3092 | | { |
| 3093 | | if(m_CPL) |
| 3094 | | FAULT(FAULT_GP,0) |
| 3095 | | if( modrm >= 0xc0 ) { |
| 3096 | | address = LOAD_RM16(modrm); |
| 3097 | | m_ldtr.segment = address; |
| 3098 | | CYCLES(CYCLES_LLDT_REG); |
| 3099 | | } else { |
| 3100 | | ea = GetEA(modrm,0); |
| 3101 | | m_ldtr.segment = READ16(ea); |
| 3102 | | CYCLES(CYCLES_LLDT_MEM); |
| 3103 | | } |
| 3104 | | memset(&seg, 0, sizeof(seg)); |
| 3105 | | seg.selector = m_ldtr.segment; |
| 3106 | | i386_load_protected_mode_segment(&seg,NULL); |
| 3107 | | m_ldtr.limit = seg.limit; |
| 3108 | | m_ldtr.base = seg.base; |
| 3109 | | m_ldtr.flags = seg.flags; |
| 3110 | | } |
| 3111 | | else |
| 3112 | | { |
| 3113 | | i386_trap(6, 0, 0); |
| 3114 | | } |
| 3115 | | break; |
| 3116 | | |
| 3117 | | case 3: /* LTR */ |
| 3118 | | if ( PROTECTED_MODE && !V8086_MODE ) |
| 3119 | | { |
| 3120 | | if(m_CPL) |
| 3121 | | FAULT(FAULT_GP,0) |
| 3122 | | if( modrm >= 0xc0 ) { |
| 3123 | | address = LOAD_RM16(modrm); |
| 3124 | | m_task.segment = address; |
| 3125 | | CYCLES(CYCLES_LTR_REG); |
| 3126 | | } else { |
| 3127 | | ea = GetEA(modrm,0); |
| 3128 | | m_task.segment = READ16(ea); |
| 3129 | | CYCLES(CYCLES_LTR_MEM); |
| 3130 | | } |
| 3131 | | memset(&seg, 0, sizeof(seg)); |
| 3132 | | seg.selector = m_task.segment; |
| 3133 | | i386_load_protected_mode_segment(&seg,NULL); |
| 3134 | | m_task.limit = seg.limit; |
| 3135 | | m_task.base = seg.base; |
| 3136 | | m_task.flags = seg.flags; |
| 3137 | | } |
| 3138 | | else |
| 3139 | | { |
| 3140 | | i386_trap(6, 0, 0); |
| 3141 | | } |
| 3142 | | break; |
| 3143 | | |
| 3144 | | case 4: /* VERR */ |
| 3145 | | if ( PROTECTED_MODE && !V8086_MODE ) |
| 3146 | | { |
| 3147 | | result = 1; |
| 3148 | | if( modrm >= 0xc0 ) { |
| 3149 | | address = LOAD_RM16(modrm); |
| 3150 | | CYCLES(CYCLES_VERR_REG); |
| 3151 | | } else { |
| 3152 | | ea = GetEA(modrm,0); |
| 3153 | | address = READ16(ea); |
| 3154 | | CYCLES(CYCLES_VERR_MEM); |
| 3155 | | } |
| 3156 | | memset(&seg, 0, sizeof(seg)); |
| 3157 | | seg.selector = address; |
| 3158 | | result = i386_load_protected_mode_segment(&seg,NULL); |
| 3159 | | // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) |
| 3160 | | if(!(seg.flags & 0x10)) |
| 3161 | | result = 0; |
| 3162 | | // check that the segment is readable |
| 3163 | | if(seg.flags & 0x10) // is code or data segment |
| 3164 | | { |
| 3165 | | if(seg.flags & 0x08) // is code segment, so check if it's readable |
| 3166 | | { |
| 3167 | | if(!(seg.flags & 0x02)) |
| 3168 | | { |
| 3169 | | result = 0; |
| 3170 | | } |
| 3171 | | else |
| 3172 | | { // check if conforming, these are always readable, regardless of privilege |
| 3173 | | if(!(seg.flags & 0x04)) |
| 3174 | | { |
| 3175 | | // if not conforming, then we must check privilege levels (TODO: current privilege level check) |
| 3176 | | if(((seg.flags >> 5) & 0x03) < (address & 0x03)) |
| 3177 | | result = 0; |
| 3178 | | } |
| 3179 | | } |
| 3180 | | } |
| 3181 | | } |
| 3182 | | // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO) |
| 3183 | | SetZF(result); |
| 3184 | | } |
| 3185 | | else |
| 3186 | | { |
| 3187 | | i386_trap(6, 0, 0); |
| 3188 | | logerror("i386: VERR: Exception - Running in real mode or virtual 8086 mode.\n"); |
| 3189 | | } |
| 3190 | | break; |
| 3191 | | |
| 3192 | | case 5: /* VERW */ |
| 3193 | | if ( PROTECTED_MODE && !V8086_MODE ) |
| 3194 | | { |
| 3195 | | result = 1; |
| 3196 | | if( modrm >= 0xc0 ) { |
| 3197 | | address = LOAD_RM16(modrm); |
| 3198 | | CYCLES(CYCLES_VERW_REG); |
| 3199 | | } else { |
| 3200 | | ea = GetEA(modrm,0); |
| 3201 | | address = READ16(ea); |
| 3202 | | CYCLES(CYCLES_VERW_MEM); |
| 3203 | | } |
| 3204 | | memset(&seg, 0, sizeof(seg)); |
| 3205 | | seg.selector = address; |
| 3206 | | result = i386_load_protected_mode_segment(&seg,NULL); |
| 3207 | | // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) |
| 3208 | | if(!(seg.flags & 0x10)) |
| 3209 | | result = 0; |
| 3210 | | // check that the segment is writable |
| 3211 | | if(seg.flags & 0x10) // is code or data segment |
| 3212 | | { |
| 3213 | | if(seg.flags & 0x08) // is code segment (and thus, not writable) |
| 3214 | | { |
| 3215 | | result = 0; |
| 3216 | | } |
| 3217 | | else |
| 3218 | | { // is data segment |
| 3219 | | if(!(seg.flags & 0x02)) |
| 3220 | | result = 0; |
| 3221 | | } |
| 3222 | | } |
| 3223 | | // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO) |
| 3224 | | if(((seg.flags >> 5) & 0x03) < (address & 0x03)) |
| 3225 | | result = 0; |
| 3226 | | SetZF(result); |
| 3227 | | } |
| 3228 | | else |
| 3229 | | { |
| 3230 | | i386_trap(6, 0, 0); |
| 3231 | | logerror("i386: VERW: Exception - Running in real mode or virtual 8086 mode.\n"); |
| 3232 | | } |
| 3233 | | break; |
| 3234 | | |
| 3235 | | default: |
| 3236 | | report_invalid_modrm("group0F00_16", modrm); |
| 3237 | | break; |
| 3238 | | } |
| 3239 | | } |
| 3240 | | |
| 3241 | | void i386_device::i386_group0F01_16() // Opcode 0x0f 01 |
| 3242 | | { |
| 3243 | | UINT8 modrm = FETCH(); |
| 3244 | | UINT16 address; |
| 3245 | | UINT32 ea; |
| 3246 | | |
| 3247 | | switch( (modrm >> 3) & 0x7 ) |
| 3248 | | { |
| 3249 | | case 0: /* SGDT */ |
| 3250 | | { |
| 3251 | | if( modrm >= 0xc0 ) { |
| 3252 | | address = LOAD_RM16(modrm); |
| 3253 | | ea = i386_translate(CS, address, 1 ); |
| 3254 | | } else { |
| 3255 | | ea = GetEA(modrm,1); |
| 3256 | | } |
| 3257 | | WRITE16(ea, m_gdtr.limit); |
| 3258 | | WRITE32(ea + 2, m_gdtr.base & 0xffffff); |
| 3259 | | CYCLES(CYCLES_SGDT); |
| 3260 | | break; |
| 3261 | | } |
| 3262 | | case 1: /* SIDT */ |
| 3263 | | { |
| 3264 | | if (modrm >= 0xc0) |
| 3265 | | { |
| 3266 | | address = LOAD_RM16(modrm); |
| 3267 | | ea = i386_translate(CS, address, 1 ); |
| 3268 | | } |
| 3269 | | else |
| 3270 | | { |
| 3271 | | ea = GetEA(modrm,1); |
| 3272 | | } |
| 3273 | | WRITE16(ea, m_idtr.limit); |
| 3274 | | WRITE32(ea + 2, m_idtr.base & 0xffffff); |
| 3275 | | CYCLES(CYCLES_SIDT); |
| 3276 | | break; |
| 3277 | | } |
| 3278 | | case 2: /* LGDT */ |
| 3279 | | { |
| 3280 | | if(PROTECTED_MODE && m_CPL) |
| 3281 | | FAULT(FAULT_GP,0) |
| 3282 | | if( modrm >= 0xc0 ) { |
| 3283 | | address = LOAD_RM16(modrm); |
| 3284 | | ea = i386_translate(CS, address, 0 ); |
| 3285 | | } else { |
| 3286 | | ea = GetEA(modrm,0); |
| 3287 | | } |
| 3288 | | m_gdtr.limit = READ16(ea); |
| 3289 | | m_gdtr.base = READ32(ea + 2) & 0xffffff; |
| 3290 | | CYCLES(CYCLES_LGDT); |
| 3291 | | break; |
| 3292 | | } |
| 3293 | | case 3: /* LIDT */ |
| 3294 | | { |
| 3295 | | if(PROTECTED_MODE && m_CPL) |
| 3296 | | FAULT(FAULT_GP,0) |
| 3297 | | if( modrm >= 0xc0 ) { |
| 3298 | | address = LOAD_RM16(modrm); |
| 3299 | | ea = i386_translate(CS, address, 0 ); |
| 3300 | | } else { |
| 3301 | | ea = GetEA(modrm,0); |
| 3302 | | } |
| 3303 | | m_idtr.limit = READ16(ea); |
| 3304 | | m_idtr.base = READ32(ea + 2) & 0xffffff; |
| 3305 | | CYCLES(CYCLES_LIDT); |
| 3306 | | break; |
| 3307 | | } |
| 3308 | | case 4: /* SMSW */ |
| 3309 | | { |
| 3310 | | if( modrm >= 0xc0 ) { |
| 3311 | | STORE_RM16(modrm, m_cr[0]); |
| 3312 | | CYCLES(CYCLES_SMSW_REG); |
| 3313 | | } else { |
| 3314 | | ea = GetEA(modrm,1); |
| 3315 | | WRITE16(ea, m_cr[0]); |
| 3316 | | CYCLES(CYCLES_SMSW_MEM); |
| 3317 | | } |
| 3318 | | break; |
| 3319 | | } |
| 3320 | | case 6: /* LMSW */ |
| 3321 | | { |
| 3322 | | if(PROTECTED_MODE && m_CPL) |
| 3323 | | FAULT(FAULT_GP,0) |
| 3324 | | UINT16 b; |
| 3325 | | if( modrm >= 0xc0 ) { |
| 3326 | | b = LOAD_RM16(modrm); |
| 3327 | | CYCLES(CYCLES_LMSW_REG); |
| 3328 | | } else { |
| 3329 | | ea = GetEA(modrm,0); |
| 3330 | | CYCLES(CYCLES_LMSW_MEM); |
| 3331 | | b = READ16(ea); |
| 3332 | | } |
| 3333 | | if(PROTECTED_MODE) |
| 3334 | | b |= 0x0001; // cannot return to real mode using this instruction. |
| 3335 | | m_cr[0] &= ~0x0000000f; |
| 3336 | | m_cr[0] |= b & 0x0000000f; |
| 3337 | | break; |
| 3338 | | } |
| 3339 | | default: |
| 3340 | | report_invalid_modrm("group0F01_16", modrm); |
| 3341 | | break; |
| 3342 | | } |
| 3343 | | } |
| 3344 | | |
| 3345 | | void i386_device::i386_group0FBA_16() // Opcode 0x0f ba |
| 3346 | | { |
| 3347 | | UINT8 modrm = FETCH(); |
| 3348 | | |
| 3349 | | switch( (modrm >> 3) & 0x7 ) |
| 3350 | | { |
| 3351 | | case 4: /* BT Rm16, i8 */ |
| 3352 | | if( modrm >= 0xc0 ) { |
| 3353 | | UINT16 dst = LOAD_RM16(modrm); |
| 3354 | | UINT8 bit = FETCH(); |
| 3355 | | |
| 3356 | | if( dst & (1 << bit) ) |
| 3357 | | m_CF = 1; |
| 3358 | | else |
| 3359 | | m_CF = 0; |
| 3360 | | |
| 3361 | | CYCLES(CYCLES_BT_IMM_REG); |
| 3362 | | } else { |
| 3363 | | UINT32 ea = GetEA(modrm,0); |
| 3364 | | UINT16 dst = READ16(ea); |
| 3365 | | UINT8 bit = FETCH(); |
| 3366 | | |
| 3367 | | if( dst & (1 << bit) ) |
| 3368 | | m_CF = 1; |
| 3369 | | else |
| 3370 | | m_CF = 0; |
| 3371 | | |
| 3372 | | CYCLES(CYCLES_BT_IMM_MEM); |
| 3373 | | } |
| 3374 | | break; |
| 3375 | | case 5: /* BTS Rm16, i8 */ |
| 3376 | | if( modrm >= 0xc0 ) { |
| 3377 | | UINT16 dst = LOAD_RM16(modrm); |
| 3378 | | UINT8 bit = FETCH(); |
| 3379 | | |
| 3380 | | if( dst & (1 << bit) ) |
| 3381 | | m_CF = 1; |
| 3382 | | else |
| 3383 | | m_CF = 0; |
| 3384 | | dst |= (1 << bit); |
| 3385 | | |
| 3386 | | STORE_RM16(modrm, dst); |
| 3387 | | CYCLES(CYCLES_BTS_IMM_REG); |
| 3388 | | } else { |
| 3389 | | UINT32 ea = GetEA(modrm,1); |
| 3390 | | UINT16 dst = READ16(ea); |
| 3391 | | UINT8 bit = FETCH(); |
| 3392 | | |
| 3393 | | if( dst & (1 << bit) ) |
| 3394 | | m_CF = 1; |
| 3395 | | else |
| 3396 | | m_CF = 0; |
| 3397 | | dst |= (1 << bit); |
| 3398 | | |
| 3399 | | WRITE16(ea, dst); |
| 3400 | | CYCLES(CYCLES_BTS_IMM_MEM); |
| 3401 | | } |
| 3402 | | break; |
| 3403 | | case 6: /* BTR Rm16, i8 */ |
| 3404 | | if( modrm >= 0xc0 ) { |
| 3405 | | UINT16 dst = LOAD_RM16(modrm); |
| 3406 | | UINT8 bit = FETCH(); |
| 3407 | | |
| 3408 | | if( dst & (1 << bit) ) |
| 3409 | | m_CF = 1; |
| 3410 | | else |
| 3411 | | m_CF = 0; |
| 3412 | | dst &= ~(1 << bit); |
| 3413 | | |
| 3414 | | STORE_RM16(modrm, dst); |
| 3415 | | CYCLES(CYCLES_BTR_IMM_REG); |
| 3416 | | } else { |
| 3417 | | UINT32 ea = GetEA(modrm,1); |
| 3418 | | UINT16 dst = READ16(ea); |
| 3419 | | UINT8 bit = FETCH(); |
| 3420 | | |
| 3421 | | if( dst & (1 << bit) ) |
| 3422 | | m_CF = 1; |
| 3423 | | else |
| 3424 | | m_CF = 0; |
| 3425 | | dst &= ~(1 << bit); |
| 3426 | | |
| 3427 | | WRITE16(ea, dst); |
| 3428 | | CYCLES(CYCLES_BTR_IMM_MEM); |
| 3429 | | } |
| 3430 | | break; |
| 3431 | | case 7: /* BTC Rm16, i8 */ |
| 3432 | | if( modrm >= 0xc0 ) { |
| 3433 | | UINT16 dst = LOAD_RM16(modrm); |
| 3434 | | UINT8 bit = FETCH(); |
| 3435 | | |
| 3436 | | if( dst & (1 << bit) ) |
| 3437 | | m_CF = 1; |
| 3438 | | else |
| 3439 | | m_CF = 0; |
| 3440 | | dst ^= (1 << bit); |
| 3441 | | |
| 3442 | | STORE_RM16(modrm, dst); |
| 3443 | | CYCLES(CYCLES_BTC_IMM_REG); |
| 3444 | | } else { |
| 3445 | | UINT32 ea = GetEA(modrm,1); |
| 3446 | | UINT16 dst = READ16(ea); |
| 3447 | | UINT8 bit = FETCH(); |
| 3448 | | |
| 3449 | | if( dst & (1 << bit) ) |
| 3450 | | m_CF = 1; |
| 3451 | | else |
| 3452 | | m_CF = 0; |
| 3453 | | dst ^= (1 << bit); |
| 3454 | | |
| 3455 | | WRITE16(ea, dst); |
| 3456 | | CYCLES(CYCLES_BTC_IMM_MEM); |
| 3457 | | } |
| 3458 | | break; |
| 3459 | | default: |
| 3460 | | report_invalid_modrm("group0FBA_16", modrm); |
| 3461 | | break; |
| 3462 | | } |
| 3463 | | } |
| 3464 | | |
| 3465 | | void i386_device::i386_lar_r16_rm16() // Opcode 0x0f 0x02 |
| 3466 | | { |
| 3467 | | UINT8 modrm = FETCH(); |
| 3468 | | I386_SREG seg; |
| 3469 | | UINT8 type; |
| 3470 | | |
| 3471 | | if(PROTECTED_MODE && !V8086_MODE) |
| 3472 | | { |
| 3473 | | memset(&seg,0,sizeof(seg)); |
| 3474 | | if(modrm >= 0xc0) |
| 3475 | | { |
| 3476 | | seg.selector = LOAD_RM16(modrm); |
| 3477 | | CYCLES(CYCLES_LAR_REG); |
| 3478 | | } |
| 3479 | | else |
| 3480 | | { |
| 3481 | | UINT32 ea = GetEA(modrm,0); |
| 3482 | | seg.selector = READ16(ea); |
| 3483 | | CYCLES(CYCLES_LAR_MEM); |
| 3484 | | } |
| 3485 | | if(seg.selector == 0) |
| 3486 | | { |
| 3487 | | SetZF(0); // not a valid segment |
| 3488 | | // logerror("i386 (%08x): LAR: Selector %04x is invalid type.\n",m_pc,seg.selector); |
| 3489 | | } |
| 3490 | | else |
| 3491 | | { |
| 3492 | | if(!i386_load_protected_mode_segment(&seg,NULL)) |
| 3493 | | { |
| 3494 | | SetZF(0); |
| 3495 | | return; |
| 3496 | | } |
| 3497 | | UINT8 DPL = (seg.flags >> 5) & 3; |
| 3498 | | if(((DPL < m_CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c)) |
| 3499 | | { |
| 3500 | | SetZF(0); |
| 3501 | | return; |
| 3502 | | } |
| 3503 | | if(!(seg.flags & 0x10)) // special segment |
| 3504 | | { |
| 3505 | | // check for invalid segment types |
| 3506 | | type = seg.flags & 0x000f; |
| 3507 | | if(type == 0x00 || type == 0x08 || type == 0x0a || type == 0x0d) |
| 3508 | | { |
| 3509 | | SetZF(0); // invalid segment type |
| 3510 | | } |
| 3511 | | else |
| 3512 | | { |
| 3513 | | STORE_REG16(modrm,(seg.flags << 8) & 0xff00); |
| 3514 | | SetZF(1); |
| 3515 | | } |
| 3516 | | } |
| 3517 | | else |
| 3518 | | { // data or code segment (both are valid for LAR) |
| 3519 | | STORE_REG16(modrm,(seg.flags << 8) & 0xff00); |
| 3520 | | SetZF(1); |
| 3521 | | } |
| 3522 | | } |
| 3523 | | } |
| 3524 | | else |
| 3525 | | { |
| 3526 | | // illegal opcode |
| 3527 | | i386_trap(6,0, 0); |
| 3528 | | logerror("i386: LAR: Exception - running in real mode or virtual 8086 mode.\n"); |
| 3529 | | } |
| 3530 | | } |
| 3531 | | |
| 3532 | | void i386_device::i386_lsl_r16_rm16() // Opcode 0x0f 0x03 |
| 3533 | | { |
| 3534 | | UINT8 modrm = FETCH(); |
| 3535 | | UINT32 limit; |
| 3536 | | I386_SREG seg; |
| 3537 | | |
| 3538 | | if(PROTECTED_MODE && !V8086_MODE) |
| 3539 | | { |
| 3540 | | memset(&seg, 0, sizeof(seg)); |
| 3541 | | if(modrm >= 0xc0) |
| 3542 | | { |
| 3543 | | seg.selector = LOAD_RM16(modrm); |
| 3544 | | } |
| 3545 | | else |
| 3546 | | { |
| 3547 | | UINT32 ea = GetEA(modrm,0); |
| 3548 | | seg.selector = READ16(ea); |
| 3549 | | } |
| 3550 | | if(seg.selector == 0) |
| 3551 | | { |
| 3552 | | SetZF(0); // not a valid segment |
| 3553 | | } |
| 3554 | | else |
| 3555 | | { |
| 3556 | | UINT8 type; |
| 3557 | | if(!i386_load_protected_mode_segment(&seg,NULL)) |
| 3558 | | { |
| 3559 | | SetZF(0); |
| 3560 | | return; |
| 3561 | | } |
| 3562 | | UINT8 DPL = (seg.flags >> 5) & 3; |
| 3563 | | if(((DPL < m_CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c)) |
| 3564 | | { |
| 3565 | | SetZF(0); |
| 3566 | | return; |
| 3567 | | } |
| 3568 | | type = seg.flags & 0x1f; |
| 3569 | | switch(type) |
| 3570 | | { |
| 3571 | | case 0: |
| 3572 | | case 4: |
| 3573 | | case 5: |
| 3574 | | case 6: |
| 3575 | | case 7: |
| 3576 | | case 8: |
| 3577 | | case 10: |
| 3578 | | case 12: |
| 3579 | | case 13: |
| 3580 | | case 14: |
| 3581 | | case 15: |
| 3582 | | SetZF(0); |
| 3583 | | return; |
| 3584 | | default: |
| 3585 | | limit = seg.limit; |
| 3586 | | STORE_REG16(modrm,limit & 0x0000ffff); |
| 3587 | | SetZF(1); |
| 3588 | | } |
| 3589 | | } |
| 3590 | | } |
| 3591 | | else |
| 3592 | | i386_trap(6, 0, 0); |
| 3593 | | } |
| 3594 | | |
| 3595 | | void i386_device::i386_bound_r16_m16_m16() // Opcode 0x62 |
| 3596 | | { |
| 3597 | | UINT8 modrm; |
| 3598 | | INT16 val, low, high; |
| 3599 | | |
| 3600 | | modrm = FETCH(); |
| 3601 | | |
| 3602 | | if (modrm >= 0xc0) |
| 3603 | | { |
| 3604 | | low = high = LOAD_RM16(modrm); |
| 3605 | | } |
| 3606 | | else |
| 3607 | | { |
| 3608 | | UINT32 ea = GetEA(modrm,0); |
| 3609 | | low = READ16(ea + 0); |
| 3610 | | high = READ16(ea + 2); |
| 3611 | | } |
| 3612 | | val = LOAD_REG16(modrm); |
| 3613 | | |
| 3614 | | if ((val < low) || (val > high)) |
| 3615 | | { |
| 3616 | | CYCLES(CYCLES_BOUND_OUT_RANGE); |
| 3617 | | i386_trap(5, 0, 0); |
| 3618 | | } |
| 3619 | | else |
| 3620 | | { |
| 3621 | | CYCLES(CYCLES_BOUND_IN_RANGE); |
| 3622 | | } |
| 3623 | | } |
| 3624 | | |
| 3625 | | void i386_device::i386_retf16() // Opcode 0xcb |
| 3626 | | { |
| 3627 | | if(PROTECTED_MODE && !V8086_MODE) |
| 3628 | | { |
| 3629 | | i386_protected_mode_retf(0,0); |
| 3630 | | } |
| 3631 | | else |
| 3632 | | { |
| 3633 | | m_eip = POP16(); |
| 3634 | | m_sreg[CS].selector = POP16(); |
| 3635 | | i386_load_segment_descriptor(CS ); |
| 3636 | | CHANGE_PC(m_eip); |
| 3637 | | } |
| 3638 | | |
| 3639 | | CYCLES(CYCLES_RET_INTERSEG); |
| 3640 | | } |
| 3641 | | |
| 3642 | | void i386_device::i386_retf_i16() // Opcode 0xca |
| 3643 | | { |
| 3644 | | UINT16 count = FETCH16(); |
| 3645 | | |
| 3646 | | if(PROTECTED_MODE && !V8086_MODE) |
| 3647 | | { |
| 3648 | | i386_protected_mode_retf(count,0); |
| 3649 | | } |
| 3650 | | else |
| 3651 | | { |
| 3652 | | m_eip = POP16(); |
| 3653 | | m_sreg[CS].selector = POP16(); |
| 3654 | | i386_load_segment_descriptor(CS ); |
| 3655 | | CHANGE_PC(m_eip); |
| 3656 | | REG16(SP) += count; |
| 3657 | | } |
| 3658 | | |
| 3659 | | CYCLES(CYCLES_RET_IMM_INTERSEG); |
| 3660 | | } |
| 3661 | | |
| 3662 | | bool i386_device::i386_load_far_pointer16(int s) |
| 3663 | | { |
| 3664 | | UINT8 modrm = FETCH(); |
| 3665 | | UINT16 selector; |
| 3666 | | |
| 3667 | | if( modrm >= 0xc0 ) { |
| 3668 | | //logerror("i386: load_far_pointer16 NYI\n"); // don't log, NT will use this a lot |
| 3669 | | i386_trap(6, 0, 0); |
| 3670 | | return false; |
| 3671 | | } else { |
| 3672 | | UINT32 ea = GetEA(modrm,0); |
| 3673 | | STORE_REG16(modrm, READ16(ea + 0)); |
| 3674 | | selector = READ16(ea + 2); |
| 3675 | | i386_sreg_load(selector,s,NULL); |
| 3676 | | } |
| 3677 | | return true; |
| 3678 | | } |
| 3679 | | |
| 3680 | | void i386_device::i386_lds16() // Opcode 0xc5 |
| 3681 | | { |
| 3682 | | if(i386_load_far_pointer16(DS)) |
| 3683 | | CYCLES(CYCLES_LDS); |
| 3684 | | } |
| 3685 | | |
| 3686 | | void i386_device::i386_lss16() // Opcode 0x0f 0xb2 |
| 3687 | | { |
| 3688 | | if(i386_load_far_pointer16(SS)) |
| 3689 | | CYCLES(CYCLES_LSS); |
| 3690 | | } |
| 3691 | | |
| 3692 | | void i386_device::i386_les16() // Opcode 0xc4 |
| 3693 | | { |
| 3694 | | if(i386_load_far_pointer16(ES)) |
| 3695 | | CYCLES(CYCLES_LES); |
| 3696 | | } |
| 3697 | | |
| 3698 | | void i386_device::i386_lfs16() // Opcode 0x0f 0xb4 |
| 3699 | | { |
| 3700 | | if(i386_load_far_pointer16(FS)) |
| 3701 | | CYCLES(CYCLES_LFS); |
| 3702 | | } |
| 3703 | | |
| 3704 | | void i386_device::i386_lgs16() // Opcode 0x0f 0xb5 |
| 3705 | | { |
| 3706 | | if(i386_load_far_pointer16(GS)) |
| 3707 | | CYCLES(CYCLES_LGS); |
| 3708 | | } |
trunk/src/emu/cpu/i386/pentops.c
| r28738 | r28739 | |
| 1 | | // Pentium+ specific opcodes |
| 2 | | |
| 3 | | extern flag float32_is_nan( float32 a ); // since its not defined in softfloat.h |
| 4 | | |
| 5 | | void i386_device::MMXPROLOG() |
| 6 | | { |
| 7 | | //m_x87_sw &= ~(X87_SW_TOP_MASK << X87_SW_TOP_SHIFT); // top = 0 |
| 8 | | m_x87_tw = 0; // tag word = 0 |
| 9 | | } |
| 10 | | |
| 11 | | void i386_device::READMMX(UINT32 ea,MMX_REG &r) |
| 12 | | { |
| 13 | | r.q=READ64(ea); |
| 14 | | } |
| 15 | | |
| 16 | | void i386_device::WRITEMMX(UINT32 ea,MMX_REG &r) |
| 17 | | { |
| 18 | | WRITE64(ea, r.q); |
| 19 | | } |
| 20 | | |
| 21 | | void i386_device::READXMM(UINT32 ea,XMM_REG &r) |
| 22 | | { |
| 23 | | r.q[0]=READ64(ea); |
| 24 | | r.q[1]=READ64(ea+8); |
| 25 | | } |
| 26 | | |
| 27 | | void i386_device::WRITEXMM(UINT32 ea,i386_device::XMM_REG &r) |
| 28 | | { |
| 29 | | WRITE64(ea, r.q[0]); |
| 30 | | WRITE64(ea+8, r.q[1]); |
| 31 | | } |
| 32 | | |
| 33 | | void i386_device::READXMM_LO64(UINT32 ea,i386_device::XMM_REG &r) |
| 34 | | { |
| 35 | | r.q[0]=READ64(ea); |
| 36 | | } |
| 37 | | |
| 38 | | void i386_device::WRITEXMM_LO64(UINT32 ea,i386_device::XMM_REG &r) |
| 39 | | { |
| 40 | | WRITE64(ea, r.q[0]); |
| 41 | | } |
| 42 | | |
| 43 | | void i386_device::READXMM_HI64(UINT32 ea,i386_device::XMM_REG &r) |
| 44 | | { |
| 45 | | r.q[1]=READ64(ea); |
| 46 | | } |
| 47 | | |
| 48 | | void i386_device::WRITEXMM_HI64(UINT32 ea,i386_device::XMM_REG &r) |
| 49 | | { |
| 50 | | WRITE64(ea, r.q[1]); |
| 51 | | } |
| 52 | | |
| 53 | | void i386_device::pentium_rdmsr() // Opcode 0x0f 32 |
| 54 | | { |
| 55 | | UINT64 data; |
| 56 | | UINT8 valid_msr = 0; |
| 57 | | |
| 58 | | data = MSR_READ(REG32(ECX),&valid_msr); |
| 59 | | REG32(EDX) = data >> 32; |
| 60 | | REG32(EAX) = data & 0xffffffff; |
| 61 | | |
| 62 | | if(m_CPL != 0 || valid_msr == 0) // if current privilege level isn't 0 or the register isn't recognized ... |
| 63 | | FAULT(FAULT_GP,0) // ... throw a general exception fault |
| 64 | | |
| 65 | | CYCLES(CYCLES_RDMSR); |
| 66 | | } |
| 67 | | |
| 68 | | void i386_device::pentium_wrmsr() // Opcode 0x0f 30 |
| 69 | | { |
| 70 | | UINT64 data; |
| 71 | | UINT8 valid_msr = 0; |
| 72 | | |
| 73 | | data = (UINT64)REG32(EAX); |
| 74 | | data |= (UINT64)(REG32(EDX)) << 32; |
| 75 | | |
| 76 | | MSR_WRITE(REG32(ECX),data,&valid_msr); |
| 77 | | |
| 78 | | if(m_CPL != 0 || valid_msr == 0) // if current privilege level isn't 0 or the register isn't recognized |
| 79 | | FAULT(FAULT_GP,0) // ... throw a general exception fault |
| 80 | | |
| 81 | | CYCLES(1); // TODO: correct cycle count (~30-45) |
| 82 | | } |
| 83 | | |
| 84 | | void i386_device::pentium_rdtsc() // Opcode 0x0f 31 |
| 85 | | { |
| 86 | | UINT64 ts = m_tsc + (m_base_cycles - m_cycles); |
| 87 | | REG32(EAX) = (UINT32)(ts); |
| 88 | | REG32(EDX) = (UINT32)(ts >> 32); |
| 89 | | |
| 90 | | CYCLES(CYCLES_RDTSC); |
| 91 | | } |
| 92 | | |
| 93 | | void i386_device::pentium_ud2() // Opcode 0x0f 0b |
| 94 | | { |
| 95 | | i386_trap(6, 0, 0); |
| 96 | | } |
| 97 | | |
| 98 | | void i386_device::pentium_rsm() |
| 99 | | { |
| 100 | | UINT32 smram_state = m_smbase + 0xfe00; |
| 101 | | if(!m_smm) |
| 102 | | { |
| 103 | | logerror("i386: Invalid RSM outside SMM at %08X\n", m_pc - 1); |
| 104 | | i386_trap(6, 0, 0); |
| 105 | | return; |
| 106 | | } |
| 107 | | |
| 108 | | // load state, no sanity checks anywhere |
| 109 | | m_smbase = READ32(smram_state+SMRAM_SMBASE); |
| 110 | | m_cr[4] = READ32(smram_state+SMRAM_IP5_CR4); |
| 111 | | m_sreg[ES].limit = READ32(smram_state+SMRAM_IP5_ESLIM); |
| 112 | | m_sreg[ES].base = READ32(smram_state+SMRAM_IP5_ESBASE); |
| 113 | | m_sreg[ES].flags = READ32(smram_state+SMRAM_IP5_ESACC); |
| 114 | | m_sreg[CS].limit = READ32(smram_state+SMRAM_IP5_CSLIM); |
| 115 | | m_sreg[CS].base = READ32(smram_state+SMRAM_IP5_CSBASE); |
| 116 | | m_sreg[CS].flags = READ32(smram_state+SMRAM_IP5_CSACC); |
| 117 | | m_sreg[SS].limit = READ32(smram_state+SMRAM_IP5_SSLIM); |
| 118 | | m_sreg[SS].base = READ32(smram_state+SMRAM_IP5_SSBASE); |
| 119 | | m_sreg[SS].flags = READ32(smram_state+SMRAM_IP5_SSACC); |
| 120 | | m_sreg[DS].limit = READ32(smram_state+SMRAM_IP5_DSLIM); |
| 121 | | m_sreg[DS].base = READ32(smram_state+SMRAM_IP5_DSBASE); |
| 122 | | m_sreg[DS].flags = READ32(smram_state+SMRAM_IP5_DSACC); |
| 123 | | m_sreg[FS].limit = READ32(smram_state+SMRAM_IP5_FSLIM); |
| 124 | | m_sreg[FS].base = READ32(smram_state+SMRAM_IP5_FSBASE); |
| 125 | | m_sreg[FS].flags = READ32(smram_state+SMRAM_IP5_FSACC); |
| 126 | | m_sreg[GS].limit = READ32(smram_state+SMRAM_IP5_GSLIM); |
| 127 | | m_sreg[GS].base = READ32(smram_state+SMRAM_IP5_GSBASE); |
| 128 | | m_sreg[GS].flags = READ32(smram_state+SMRAM_IP5_GSACC); |
| 129 | | m_ldtr.flags = READ32(smram_state+SMRAM_IP5_LDTACC); |
| 130 | | m_ldtr.limit = READ32(smram_state+SMRAM_IP5_LDTLIM); |
| 131 | | m_ldtr.base = READ32(smram_state+SMRAM_IP5_LDTBASE); |
| 132 | | m_gdtr.limit = READ32(smram_state+SMRAM_IP5_GDTLIM); |
| 133 | | m_gdtr.base = READ32(smram_state+SMRAM_IP5_GDTBASE); |
| 134 | | m_idtr.limit = READ32(smram_state+SMRAM_IP5_IDTLIM); |
| 135 | | m_idtr.base = READ32(smram_state+SMRAM_IP5_IDTBASE); |
| 136 | | m_task.limit = READ32(smram_state+SMRAM_IP5_TRLIM); |
| 137 | | m_task.base = READ32(smram_state+SMRAM_IP5_TRBASE); |
| 138 | | m_task.flags = READ32(smram_state+SMRAM_IP5_TRACC); |
| 139 | | |
| 140 | | m_sreg[ES].selector = READ32(smram_state+SMRAM_ES); |
| 141 | | m_sreg[CS].selector = READ32(smram_state+SMRAM_CS); |
| 142 | | m_sreg[SS].selector = READ32(smram_state+SMRAM_SS); |
| 143 | | m_sreg[DS].selector = READ32(smram_state+SMRAM_DS); |
| 144 | | m_sreg[FS].selector = READ32(smram_state+SMRAM_FS); |
| 145 | | m_sreg[GS].selector = READ32(smram_state+SMRAM_GS); |
| 146 | | m_ldtr.segment = READ32(smram_state+SMRAM_LDTR); |
| 147 | | m_task.segment = READ32(smram_state+SMRAM_TR); |
| 148 | | |
| 149 | | m_dr[7] = READ32(smram_state+SMRAM_DR7); |
| 150 | | m_dr[6] = READ32(smram_state+SMRAM_DR6); |
| 151 | | REG32(EAX) = READ32(smram_state+SMRAM_EAX); |
| 152 | | REG32(ECX) = READ32(smram_state+SMRAM_ECX); |
| 153 | | REG32(EDX) = READ32(smram_state+SMRAM_EDX); |
| 154 | | REG32(EBX) = READ32(smram_state+SMRAM_EBX); |
| 155 | | REG32(ESP) = READ32(smram_state+SMRAM_ESP); |
| 156 | | REG32(EBP) = READ32(smram_state+SMRAM_EBP); |
| 157 | | REG32(ESI) = READ32(smram_state+SMRAM_ESI); |
| 158 | | REG32(EDI) = READ32(smram_state+SMRAM_EDI); |
| 159 | | m_eip = READ32(smram_state+SMRAM_EIP); |
| 160 | | m_eflags = READ32(smram_state+SMRAM_EAX); |
| 161 | | m_cr[3] = READ32(smram_state+SMRAM_CR3); |
| 162 | | m_cr[0] = READ32(smram_state+SMRAM_CR0); |
| 163 | | |
| 164 | | m_CPL = (m_sreg[SS].flags >> 13) & 3; // cpl == dpl of ss |
| 165 | | |
| 166 | | for(int i = 0; i < GS; i++) |
| 167 | | { |
| 168 | | if(PROTECTED_MODE && !V8086_MODE) |
| 169 | | { |
| 170 | | m_sreg[i].valid = m_sreg[i].selector ? true : false; |
| 171 | | m_sreg[i].d = (m_sreg[i].flags & 0x4000) ? 1 : 0; |
| 172 | | } |
| 173 | | else |
| 174 | | m_sreg[i].valid = true; |
| 175 | | } |
| 176 | | |
| 177 | | if(!m_smiact.isnull()) |
| 178 | | m_smiact(false); |
| 179 | | m_smm = false; |
| 180 | | |
| 181 | | CHANGE_PC(m_eip); |
| 182 | | m_nmi_masked = false; |
| 183 | | if(m_smi_latched) |
| 184 | | { |
| 185 | | pentium_smi(); |
| 186 | | return; |
| 187 | | } |
| 188 | | if(m_nmi_latched) |
| 189 | | { |
| 190 | | m_nmi_latched = false; |
| 191 | | i386_trap(2, 1, 0); |
| 192 | | } |
| 193 | | } |
| 194 | | |
| 195 | | void i386_device::pentium_prefetch_m8() // Opcode 0x0f 18 |
| 196 | | { |
| 197 | | UINT8 modrm = FETCH(); |
| 198 | | UINT32 ea = GetEA(modrm,0); |
| 199 | | CYCLES(1+(ea & 1)); // TODO: correct cycle count |
| 200 | | } |
| 201 | | |
| 202 | | void i386_device::pentium_cmovo_r16_rm16() // Opcode 0x0f 40 |
| 203 | | { |
| 204 | | UINT16 src; |
| 205 | | UINT8 modrm = FETCH(); |
| 206 | | |
| 207 | | if( modrm >= 0xc0 ) |
| 208 | | { |
| 209 | | if (m_OF == 1) |
| 210 | | { |
| 211 | | src = LOAD_RM16(modrm); |
| 212 | | STORE_REG16(modrm, src); |
| 213 | | } |
| 214 | | CYCLES(1); // TODO: correct cycle count |
| 215 | | } |
| 216 | | else |
| 217 | | { |
| 218 | | UINT32 ea = GetEA(modrm,0); |
| 219 | | if (m_OF == 1) |
| 220 | | { |
| 221 | | src = READ16(ea); |
| 222 | | STORE_REG16(modrm, src); |
| 223 | | } |
| 224 | | CYCLES(1); // TODO: correct cycle count |
| 225 | | } |
| 226 | | } |
| 227 | | |
| 228 | | void i386_device::pentium_cmovo_r32_rm32() // Opcode 0x0f 40 |
| 229 | | { |
| 230 | | UINT32 src; |
| 231 | | UINT8 modrm = FETCH(); |
| 232 | | |
| 233 | | if( modrm >= 0xc0 ) |
| 234 | | { |
| 235 | | if (m_OF == 1) |
| 236 | | { |
| 237 | | src = LOAD_RM32(modrm); |
| 238 | | STORE_REG32(modrm, src); |
| 239 | | } |
| 240 | | CYCLES(1); // TODO: correct cycle count |
| 241 | | } |
| 242 | | else |
| 243 | | { |
| 244 | | UINT32 ea = GetEA(modrm,0); |
| 245 | | if (m_OF == 1) |
| 246 | | { |
| 247 | | src = READ32(ea); |
| 248 | | STORE_REG32(modrm, src); |
| 249 | | } |
| 250 | | CYCLES(1); // TODO: correct cycle count |
| 251 | | } |
| 252 | | } |
| 253 | | |
| 254 | | void i386_device::pentium_cmovno_r16_rm16() // Opcode 0x0f 41 |
| 255 | | { |
| 256 | | UINT16 src; |
| 257 | | UINT8 modrm = FETCH(); |
| 258 | | |
| 259 | | if( modrm >= 0xc0 ) |
| 260 | | { |
| 261 | | if (m_OF == 0) |
| 262 | | { |
| 263 | | src = LOAD_RM16(modrm); |
| 264 | | STORE_REG16(modrm, src); |
| 265 | | } |
| 266 | | CYCLES(1); // TODO: correct cycle count |
| 267 | | } |
| 268 | | else |
| 269 | | { |
| 270 | | UINT32 ea = GetEA(modrm,0); |
| 271 | | if (m_OF == 0) |
| 272 | | { |
| 273 | | src = READ16(ea); |
| 274 | | STORE_REG16(modrm, src); |
| 275 | | } |
| 276 | | CYCLES(1); // TODO: correct cycle count |
| 277 | | } |
| 278 | | } |
| 279 | | |
| 280 | | void i386_device::pentium_cmovno_r32_rm32() // Opcode 0x0f 41 |
| 281 | | { |
| 282 | | UINT32 src; |
| 283 | | UINT8 modrm = FETCH(); |
| 284 | | |
| 285 | | if( modrm >= 0xc0 ) |
| 286 | | { |
| 287 | | if (m_OF == 0) |
| 288 | | { |
| 289 | | src = LOAD_RM32(modrm); |
| 290 | | STORE_REG32(modrm, src); |
| 291 | | } |
| 292 | | CYCLES(1); // TODO: correct cycle count |
| 293 | | } |
| 294 | | else |
| 295 | | { |
| 296 | | UINT32 ea = GetEA(modrm,0); |
| 297 | | if (m_OF == 0) |
| 298 | | { |
| 299 | | src = READ32(ea); |
| 300 | | STORE_REG32(modrm, src); |
| 301 | | } |
| 302 | | CYCLES(1); // TODO: correct cycle count |
| 303 | | } |
| 304 | | } |
| 305 | | |
| 306 | | void i386_device::pentium_cmovb_r16_rm16() // Opcode 0x0f 42 |
| 307 | | { |
| 308 | | UINT16 src; |
| 309 | | UINT8 modrm = FETCH(); |
| 310 | | |
| 311 | | if( modrm >= 0xc0 ) |
| 312 | | { |
| 313 | | if (m_CF == 1) |
| 314 | | { |
| 315 | | src = LOAD_RM16(modrm); |
| 316 | | STORE_REG16(modrm, src); |
| 317 | | } |
| 318 | | CYCLES(1); // TODO: correct cycle count |
| 319 | | } |
| 320 | | else |
| 321 | | { |
| 322 | | UINT32 ea = GetEA(modrm,0); |
| 323 | | if (m_CF == 1) |
| 324 | | { |
| 325 | | src = READ16(ea); |
| 326 | | STORE_REG16(modrm, src); |
| 327 | | } |
| 328 | | CYCLES(1); // TODO: correct cycle count |
| 329 | | } |
| 330 | | } |
| 331 | | |
| 332 | | void i386_device::pentium_cmovb_r32_rm32() // Opcode 0x0f 42 |
| 333 | | { |
| 334 | | UINT32 src; |
| 335 | | UINT8 modrm = FETCH(); |
| 336 | | |
| 337 | | if( modrm >= 0xc0 ) |
| 338 | | { |
| 339 | | if (m_CF == 1) |
| 340 | | { |
| 341 | | src = LOAD_RM32(modrm); |
| 342 | | STORE_REG32(modrm, src); |
| 343 | | } |
| 344 | | CYCLES(1); // TODO: correct cycle count |
| 345 | | } |
| 346 | | else |
| 347 | | { |
| 348 | | UINT32 ea = GetEA(modrm,0); |
| 349 | | if (m_CF == 1) |
| 350 | | { |
| 351 | | src = READ32(ea); |
| 352 | | STORE_REG32(modrm, src); |
| 353 | | } |
| 354 | | CYCLES(1); // TODO: correct cycle count |
| 355 | | } |
| 356 | | } |
| 357 | | |
| 358 | | void i386_device::pentium_cmovae_r16_rm16() // Opcode 0x0f 43 |
| 359 | | { |
| 360 | | UINT16 src; |
| 361 | | UINT8 modrm = FETCH(); |
| 362 | | |
| 363 | | if( modrm >= 0xc0 ) |
| 364 | | { |
| 365 | | if (m_CF == 0) |
| 366 | | { |
| 367 | | src = LOAD_RM16(modrm); |
| 368 | | STORE_REG16(modrm, src); |
| 369 | | } |
| 370 | | CYCLES(1); // TODO: correct cycle count |
| 371 | | } |
| 372 | | else |
| 373 | | { |
| 374 | | UINT32 ea = GetEA(modrm,0); |
| 375 | | if (m_CF == 0) |
| 376 | | { |
| 377 | | src = READ16(ea); |
| 378 | | STORE_REG16(modrm, src); |
| 379 | | } |
| 380 | | CYCLES(1); // TODO: correct cycle count |
| 381 | | } |
| 382 | | } |
| 383 | | |
| 384 | | void i386_device::pentium_cmovae_r32_rm32() // Opcode 0x0f 43 |
| 385 | | { |
| 386 | | UINT32 src; |
| 387 | | UINT8 modrm = FETCH(); |
| 388 | | |
| 389 | | if( modrm >= 0xc0 ) |
| 390 | | { |
| 391 | | if (m_CF == 0) |
| 392 | | { |
| 393 | | src = LOAD_RM32(modrm); |
| 394 | | STORE_REG32(modrm, src); |
| 395 | | } |
| 396 | | CYCLES(1); // TODO: correct cycle count |
| 397 | | } |
| 398 | | else |
| 399 | | { |
| 400 | | UINT32 ea = GetEA(modrm,0); |
| 401 | | if (m_CF == 0) |
| 402 | | { |
| 403 | | src = READ32(ea); |
| 404 | | STORE_REG32(modrm, src); |
| 405 | | } |
| 406 | | CYCLES(1); // TODO: correct cycle count |
| 407 | | } |
| 408 | | } |
| 409 | | |
| 410 | | void i386_device::pentium_cmove_r16_rm16() // Opcode 0x0f 44 |
| 411 | | { |
| 412 | | UINT16 src; |
| 413 | | UINT8 modrm = FETCH(); |
| 414 | | |
| 415 | | if( modrm >= 0xc0 ) |
| 416 | | { |
| 417 | | if (m_ZF == 1) |
| 418 | | { |
| 419 | | src = LOAD_RM16(modrm); |
| 420 | | STORE_REG16(modrm, src); |
| 421 | | } |
| 422 | | CYCLES(1); // TODO: correct cycle count |
| 423 | | } |
| 424 | | else |
| 425 | | { |
| 426 | | UINT32 ea = GetEA(modrm,0); |
| 427 | | if (m_ZF == 1) |
| 428 | | { |
| 429 | | src = READ16(ea); |
| 430 | | STORE_REG16(modrm, src); |
| 431 | | } |
| 432 | | CYCLES(1); // TODO: correct cycle count |
| 433 | | } |
| 434 | | } |
| 435 | | |
| 436 | | void i386_device::pentium_cmove_r32_rm32() // Opcode 0x0f 44 |
| 437 | | { |
| 438 | | UINT32 src; |
| 439 | | UINT8 modrm = FETCH(); |
| 440 | | |
| 441 | | if( modrm >= 0xc0 ) |
| 442 | | { |
| 443 | | if (m_ZF == 1) |
| 444 | | { |
| 445 | | src = LOAD_RM32(modrm); |
| 446 | | STORE_REG32(modrm, src); |
| 447 | | } |
| 448 | | CYCLES(1); // TODO: correct cycle count |
| 449 | | } |
| 450 | | else |
| 451 | | { |
| 452 | | UINT32 ea = GetEA(modrm,0); |
| 453 | | if (m_ZF == 1) |
| 454 | | { |
| 455 | | src = READ32(ea); |
| 456 | | STORE_REG32(modrm, src); |
| 457 | | } |
| 458 | | CYCLES(1); // TODO: correct cycle count |
| 459 | | } |
| 460 | | } |
| 461 | | |
| 462 | | void i386_device::pentium_cmovne_r16_rm16() // Opcode 0x0f 45 |
| 463 | | { |
| 464 | | UINT16 src; |
| 465 | | UINT8 modrm = FETCH(); |
| 466 | | |
| 467 | | if( modrm >= 0xc0 ) |
| 468 | | { |
| 469 | | if (m_ZF == 0) |
| 470 | | { |
| 471 | | src = LOAD_RM16(modrm); |
| 472 | | STORE_REG16(modrm, src); |
| 473 | | } |
| 474 | | CYCLES(1); // TODO: correct cycle count |
| 475 | | } |
| 476 | | else |
| 477 | | { |
| 478 | | UINT32 ea = GetEA(modrm,0); |
| 479 | | if (m_ZF == 0) |
| 480 | | { |
| 481 | | src = READ16(ea); |
| 482 | | STORE_REG16(modrm, src); |
| 483 | | } |
| 484 | | CYCLES(1); // TODO: correct cycle count |
| 485 | | } |
| 486 | | } |
| 487 | | |
| 488 | | void i386_device::pentium_cmovne_r32_rm32() // Opcode 0x0f 45 |
| 489 | | { |
| 490 | | UINT32 src; |
| 491 | | UINT8 modrm = FETCH(); |
| 492 | | |
| 493 | | if( modrm >= 0xc0 ) |
| 494 | | { |
| 495 | | if (m_ZF == 0) |
| 496 | | { |
| 497 | | src = LOAD_RM32(modrm); |
| 498 | | STORE_REG32(modrm, src); |
| 499 | | } |
| 500 | | CYCLES(1); // TODO: correct cycle count |
| 501 | | } |
| 502 | | else |
| 503 | | { |
| 504 | | UINT32 ea = GetEA(modrm,0); |
| 505 | | if (m_ZF == 0) |
| 506 | | { |
| 507 | | src = READ32(ea); |
| 508 | | STORE_REG32(modrm, src); |
| 509 | | } |
| 510 | | CYCLES(1); // TODO: correct cycle count |
| 511 | | } |
| 512 | | } |
| 513 | | |
| 514 | | void i386_device::pentium_cmovbe_r16_rm16() // Opcode 0x0f 46 |
| 515 | | { |
| 516 | | UINT16 src; |
| 517 | | UINT8 modrm = FETCH(); |
| 518 | | |
| 519 | | if( modrm >= 0xc0 ) |
| 520 | | { |
| 521 | | if ((m_CF == 1) || (m_ZF == 1)) |
| 522 | | { |
| 523 | | src = LOAD_RM16(modrm); |
| 524 | | STORE_REG16(modrm, src); |
| 525 | | } |
| 526 | | CYCLES(1); // TODO: correct cycle count |
| 527 | | } |
| 528 | | else |
| 529 | | { |
| 530 | | UINT32 ea = GetEA(modrm,0); |
| 531 | | if ((m_CF == 1) || (m_ZF == 1)) |
| 532 | | { |
| 533 | | src = READ16(ea); |
| 534 | | STORE_REG16(modrm, src); |
| 535 | | } |
| 536 | | CYCLES(1); // TODO: correct cycle count |
| 537 | | } |
| 538 | | } |
| 539 | | |
| 540 | | void i386_device::pentium_cmovbe_r32_rm32() // Opcode 0x0f 46 |
| 541 | | { |
| 542 | | UINT32 src; |
| 543 | | UINT8 modrm = FETCH(); |
| 544 | | |
| 545 | | if( modrm >= 0xc0 ) |
| 546 | | { |
| 547 | | if ((m_CF == 1) || (m_ZF == 1)) |
| 548 | | { |
| 549 | | src = LOAD_RM32(modrm); |
| 550 | | STORE_REG32(modrm, src); |
| 551 | | } |
| 552 | | CYCLES(1); // TODO: correct cycle count |
| 553 | | } |
| 554 | | else |
| 555 | | { |
| 556 | | UINT32 ea = GetEA(modrm,0); |
| 557 | | if ((m_CF == 1) || (m_ZF == 1)) |
| 558 | | { |
| 559 | | src = READ32(ea); |
| 560 | | STORE_REG32(modrm, src); |
| 561 | | } |
| 562 | | CYCLES(1); // TODO: correct cycle count |
| 563 | | } |
| 564 | | } |
| 565 | | |
| 566 | | void i386_device::pentium_cmova_r16_rm16() // Opcode 0x0f 47 |
| 567 | | { |
| 568 | | UINT16 src; |
| 569 | | UINT8 modrm = FETCH(); |
| 570 | | |
| 571 | | if( modrm >= 0xc0 ) |
| 572 | | { |
| 573 | | if ((m_CF == 0) && (m_ZF == 0)) |
| 574 | | { |
| 575 | | src = LOAD_RM16(modrm); |
| 576 | | STORE_REG16(modrm, src); |
| 577 | | } |
| 578 | | CYCLES(1); // TODO: correct cycle count |
| 579 | | } |
| 580 | | else |
| 581 | | { |
| 582 | | UINT32 ea = GetEA(modrm,0); |
| 583 | | if ((m_CF == 0) && (m_ZF == 0)) |
| 584 | | { |
| 585 | | src = READ16(ea); |
| 586 | | STORE_REG16(modrm, src); |
| 587 | | } |
| 588 | | CYCLES(1); // TODO: correct cycle count |
| 589 | | } |
| 590 | | } |
| 591 | | |
| 592 | | void i386_device::pentium_cmova_r32_rm32() // Opcode 0x0f 47 |
| 593 | | { |
| 594 | | UINT32 src; |
| 595 | | UINT8 modrm = FETCH(); |
| 596 | | |
| 597 | | if( modrm >= 0xc0 ) |
| 598 | | { |
| 599 | | if ((m_CF == 0) && (m_ZF == 0)) |
| 600 | | { |
| 601 | | src = LOAD_RM32(modrm); |
| 602 | | STORE_REG32(modrm, src); |
| 603 | | } |
| 604 | | CYCLES(1); // TODO: correct cycle count |
| 605 | | } |
| 606 | | else |
| 607 | | { |
| 608 | | UINT32 ea = GetEA(modrm,0); |
| 609 | | if ((m_CF == 0) && (m_ZF == 0)) |
| 610 | | { |
| 611 | | src = READ32(ea); |
| 612 | | STORE_REG32(modrm, src); |
| 613 | | } |
| 614 | | CYCLES(1); // TODO: correct cycle count |
| 615 | | } |
| 616 | | } |
| 617 | | |
| 618 | | void i386_device::pentium_cmovs_r16_rm16() // Opcode 0x0f 48 |
| 619 | | { |
| 620 | | UINT16 src; |
| 621 | | UINT8 modrm = FETCH(); |
| 622 | | |
| 623 | | if( modrm >= 0xc0 ) |
| 624 | | { |
| 625 | | if (m_SF == 1) |
| 626 | | { |
| 627 | | src = LOAD_RM16(modrm); |
| 628 | | STORE_REG16(modrm, src); |
| 629 | | } |
| 630 | | CYCLES(1); // TODO: correct cycle count |
| 631 | | } |
| 632 | | else |
| 633 | | { |
| 634 | | UINT32 ea = GetEA(modrm,0); |
| 635 | | if (m_SF == 1) |
| 636 | | { |
| 637 | | src = READ16(ea); |
| 638 | | STORE_REG16(modrm, src); |
| 639 | | } |
| 640 | | CYCLES(1); // TODO: correct cycle count |
| 641 | | } |
| 642 | | } |
| 643 | | |
| 644 | | void i386_device::pentium_cmovs_r32_rm32() // Opcode 0x0f 48 |
| 645 | | { |
| 646 | | UINT32 src; |
| 647 | | UINT8 modrm = FETCH(); |
| 648 | | |
| 649 | | if( modrm >= 0xc0 ) |
| 650 | | { |
| 651 | | if (m_SF == 1) |
| 652 | | { |
| 653 | | src = LOAD_RM32(modrm); |
| 654 | | STORE_REG32(modrm, src); |
| 655 | | } |
| 656 | | CYCLES(1); // TODO: correct cycle count |
| 657 | | } |
| 658 | | else |
| 659 | | { |
| 660 | | UINT32 ea = GetEA(modrm,0); |
| 661 | | if (m_SF == 1) |
| 662 | | { |
| 663 | | src = READ32(ea); |
| 664 | | STORE_REG32(modrm, src); |
| 665 | | } |
| 666 | | CYCLES(1); // TODO: correct cycle count |
| 667 | | } |
| 668 | | } |
| 669 | | |
| 670 | | void i386_device::pentium_cmovns_r16_rm16() // Opcode 0x0f 49 |
| 671 | | { |
| 672 | | UINT16 src; |
| 673 | | UINT8 modrm = FETCH(); |
| 674 | | |
| 675 | | if( modrm >= 0xc0 ) |
| 676 | | { |
| 677 | | if (m_SF == 0) |
| 678 | | { |
| 679 | | src = LOAD_RM16(modrm); |
| 680 | | STORE_REG16(modrm, src); |
| 681 | | } |
| 682 | | CYCLES(1); // TODO: correct cycle count |
| 683 | | } |
| 684 | | else |
| 685 | | { |
| 686 | | UINT32 ea = GetEA(modrm,0); |
| 687 | | if (m_SF == 0) |
| 688 | | { |
| 689 | | src = READ16(ea); |
| 690 | | STORE_REG16(modrm, src); |
| 691 | | } |
| 692 | | CYCLES(1); // TODO: correct cycle count |
| 693 | | } |
| 694 | | } |
| 695 | | |
| 696 | | void i386_device::pentium_cmovns_r32_rm32() // Opcode 0x0f 49 |
| 697 | | { |
| 698 | | UINT32 src; |
| 699 | | UINT8 modrm = FETCH(); |
| 700 | | |
| 701 | | if( modrm >= 0xc0 ) |
| 702 | | { |
| 703 | | if (m_SF == 0) |
| 704 | | { |
| 705 | | src = LOAD_RM32(modrm); |
| 706 | | STORE_REG32(modrm, src); |
| 707 | | } |
| 708 | | CYCLES(1); // TODO: correct cycle count |
| 709 | | } |
| 710 | | else |
| 711 | | { |
| 712 | | UINT32 ea = GetEA(modrm,0); |
| 713 | | if (m_SF == 0) |
| 714 | | { |
| 715 | | src = READ32(ea); |
| 716 | | STORE_REG32(modrm, src); |
| 717 | | } |
| 718 | | CYCLES(1); // TODO: correct cycle count |
| 719 | | } |
| 720 | | } |
| 721 | | |
| 722 | | void i386_device::pentium_cmovp_r16_rm16() // Opcode 0x0f 4a |
| 723 | | { |
| 724 | | UINT16 src; |
| 725 | | UINT8 modrm = FETCH(); |
| 726 | | |
| 727 | | if( modrm >= 0xc0 ) |
| 728 | | { |
| 729 | | if (m_PF == 1) |
| 730 | | { |
| 731 | | src = LOAD_RM16(modrm); |
| 732 | | STORE_REG16(modrm, src); |
| 733 | | } |
| 734 | | CYCLES(1); // TODO: correct cycle count |
| 735 | | } |
| 736 | | else |
| 737 | | { |
| 738 | | UINT32 ea = GetEA(modrm,0); |
| 739 | | if (m_PF == 1) |
| 740 | | { |
| 741 | | src = READ16(ea); |
| 742 | | STORE_REG16(modrm, src); |
| 743 | | } |
| 744 | | CYCLES(1); // TODO: correct cycle count |
| 745 | | } |
| 746 | | } |
| 747 | | |
| 748 | | void i386_device::pentium_cmovp_r32_rm32() // Opcode 0x0f 4a |
| 749 | | { |
| 750 | | UINT32 src; |
| 751 | | UINT8 modrm = FETCH(); |
| 752 | | |
| 753 | | if( modrm >= 0xc0 ) |
| 754 | | { |
| 755 | | if (m_PF == 1) |
| 756 | | { |
| 757 | | src = LOAD_RM32(modrm); |
| 758 | | STORE_REG32(modrm, src); |
| 759 | | } |
| 760 | | CYCLES(1); // TODO: correct cycle count |
| 761 | | } |
| 762 | | else |
| 763 | | { |
| 764 | | UINT32 ea = GetEA(modrm,0); |
| 765 | | if (m_PF == 1) |
| 766 | | { |
| 767 | | src = READ32(ea); |
| 768 | | STORE_REG32(modrm, src); |
| 769 | | } |
| 770 | | CYCLES(1); // TODO: correct cycle count |
| 771 | | } |
| 772 | | } |
| 773 | | |
| 774 | | void i386_device::pentium_cmovnp_r16_rm16() // Opcode 0x0f 4b |
| 775 | | { |
| 776 | | UINT16 src; |
| 777 | | UINT8 modrm = FETCH(); |
| 778 | | |
| 779 | | if( modrm >= 0xc0 ) |
| 780 | | { |
| 781 | | if (m_PF == 0) |
| 782 | | { |
| 783 | | src = LOAD_RM16(modrm); |
| 784 | | STORE_REG16(modrm, src); |
| 785 | | } |
| 786 | | CYCLES(1); // TODO: correct cycle count |
| 787 | | } |
| 788 | | else |
| 789 | | { |
| 790 | | UINT32 ea = GetEA(modrm,0); |
| 791 | | if (m_PF == 0) |
| 792 | | { |
| 793 | | src = READ16(ea); |
| 794 | | STORE_REG16(modrm, src); |
| 795 | | } |
| 796 | | CYCLES(1); // TODO: correct cycle count |
| 797 | | } |
| 798 | | } |
| 799 | | |
| 800 | | void i386_device::pentium_cmovnp_r32_rm32() // Opcode 0x0f 4b |
| 801 | | { |
| 802 | | UINT32 src; |
| 803 | | UINT8 modrm = FETCH(); |
| 804 | | |
| 805 | | if( modrm >= 0xc0 ) |
| 806 | | { |
| 807 | | if (m_PF == 0) |
| 808 | | { |
| 809 | | src = LOAD_RM32(modrm); |
| 810 | | STORE_REG32(modrm, src); |
| 811 | | } |
| 812 | | CYCLES(1); // TODO: correct cycle count |
| 813 | | } |
| 814 | | else |
| 815 | | { |
| 816 | | UINT32 ea = GetEA(modrm,0); |
| 817 | | if (m_PF == 0) |
| 818 | | { |
| 819 | | src = READ32(ea); |
| 820 | | STORE_REG32(modrm, src); |
| 821 | | } |
| 822 | | CYCLES(1); // TODO: correct cycle count |
| 823 | | } |
| 824 | | } |
| 825 | | |
| 826 | | void i386_device::pentium_cmovl_r16_rm16() // Opcode 0x0f 4c |
| 827 | | { |
| 828 | | UINT16 src; |
| 829 | | UINT8 modrm = FETCH(); |
| 830 | | |
| 831 | | if( modrm >= 0xc0 ) |
| 832 | | { |
| 833 | | if (m_SF != m_OF) |
| 834 | | { |
| 835 | | src = LOAD_RM16(modrm); |
| 836 | | STORE_REG16(modrm, src); |
| 837 | | } |
| 838 | | CYCLES(1); // TODO: correct cycle count |
| 839 | | } |
| 840 | | else |
| 841 | | { |
| 842 | | UINT32 ea = GetEA(modrm,0); |
| 843 | | if (m_SF != m_OF) |
| 844 | | { |
| 845 | | src = READ16(ea); |
| 846 | | STORE_REG16(modrm, src); |
| 847 | | } |
| 848 | | CYCLES(1); // TODO: correct cycle count |
| 849 | | } |
| 850 | | } |
| 851 | | |
| 852 | | void i386_device::pentium_cmovl_r32_rm32() // Opcode 0x0f 4c |
| 853 | | { |
| 854 | | UINT32 src; |
| 855 | | UINT8 modrm = FETCH(); |
| 856 | | |
| 857 | | if( modrm >= 0xc0 ) |
| 858 | | { |
| 859 | | if (m_SF != m_OF) |
| 860 | | { |
| 861 | | src = LOAD_RM32(modrm); |
| 862 | | STORE_REG32(modrm, src); |
| 863 | | } |
| 864 | | CYCLES(1); // TODO: correct cycle count |
| 865 | | } |
| 866 | | else |
| 867 | | { |
| 868 | | UINT32 ea = GetEA(modrm,0); |
| 869 | | if (m_SF != m_OF) |
| 870 | | { |
| 871 | | src = READ32(ea); |
| 872 | | STORE_REG32(modrm, src); |
| 873 | | } |
| 874 | | CYCLES(1); // TODO: correct cycle count |
| 875 | | } |
| 876 | | } |
| 877 | | |
| 878 | | void i386_device::pentium_cmovge_r16_rm16() // Opcode 0x0f 4d |
| 879 | | { |
| 880 | | UINT16 src; |
| 881 | | UINT8 modrm = FETCH(); |
| 882 | | |
| 883 | | if( modrm >= 0xc0 ) |
| 884 | | { |
| 885 | | if (m_SF == m_OF) |
| 886 | | { |
| 887 | | src = LOAD_RM16(modrm); |
| 888 | | STORE_REG16(modrm, src); |
| 889 | | } |
| 890 | | CYCLES(1); // TODO: correct cycle count |
| 891 | | } |
| 892 | | else |
| 893 | | { |
| 894 | | UINT32 ea = GetEA(modrm,0); |
| 895 | | if (m_SF == m_OF) |
| 896 | | { |
| 897 | | src = READ16(ea); |
| 898 | | STORE_REG16(modrm, src); |
| 899 | | } |
| 900 | | CYCLES(1); // TODO: correct cycle count |
| 901 | | } |
| 902 | | } |
| 903 | | |
| 904 | | void i386_device::pentium_cmovge_r32_rm32() // Opcode 0x0f 4d |
| 905 | | { |
| 906 | | UINT32 src; |
| 907 | | UINT8 modrm = FETCH(); |
| 908 | | |
| 909 | | if( modrm >= 0xc0 ) |
| 910 | | { |
| 911 | | if (m_SF == m_OF) |
| 912 | | { |
| 913 | | src = LOAD_RM32(modrm); |
| 914 | | STORE_REG32(modrm, src); |
| 915 | | } |
| 916 | | CYCLES(1); // TODO: correct cycle count |
| 917 | | } |
| 918 | | else |
| 919 | | { |
| 920 | | UINT32 ea = GetEA(modrm,0); |
| 921 | | if (m_SF == m_OF) |
| 922 | | { |
| 923 | | src = READ32(ea); |
| 924 | | STORE_REG32(modrm, src); |
| 925 | | } |
| 926 | | CYCLES(1); // TODO: correct cycle count |
| 927 | | } |
| 928 | | } |
| 929 | | |
| 930 | | void i386_device::pentium_cmovle_r16_rm16() // Opcode 0x0f 4e |
| 931 | | { |
| 932 | | UINT16 src; |
| 933 | | UINT8 modrm = FETCH(); |
| 934 | | |
| 935 | | if( modrm >= 0xc0 ) |
| 936 | | { |
| 937 | | if ((m_ZF == 1) || (m_SF != m_OF)) |
| 938 | | { |
| 939 | | src = LOAD_RM16(modrm); |
| 940 | | STORE_REG16(modrm, src); |
| 941 | | } |
| 942 | | CYCLES(1); // TODO: correct cycle count |
| 943 | | } |
| 944 | | else |
| 945 | | { |
| 946 | | UINT32 ea = GetEA(modrm,0); |
| 947 | | if ((m_ZF == 1) || (m_SF != m_OF)) |
| 948 | | { |
| 949 | | src = READ16(ea); |
| 950 | | STORE_REG16(modrm, src); |
| 951 | | } |
| 952 | | CYCLES(1); // TODO: correct cycle count |
| 953 | | } |
| 954 | | } |
| 955 | | |
| 956 | | void i386_device::pentium_cmovle_r32_rm32() // Opcode 0x0f 4e |
| 957 | | { |
| 958 | | UINT32 src; |
| 959 | | UINT8 modrm = FETCH(); |
| 960 | | |
| 961 | | if( modrm >= 0xc0 ) |
| 962 | | { |
| 963 | | if ((m_ZF == 1) || (m_SF != m_OF)) |
| 964 | | { |
| 965 | | src = LOAD_RM32(modrm); |
| 966 | | STORE_REG32(modrm, src); |
| 967 | | } |
| 968 | | CYCLES(1); // TODO: correct cycle count |
| 969 | | } |
| 970 | | else |
| 971 | | { |
| 972 | | UINT32 ea = GetEA(modrm,0); |
| 973 | | if ((m_ZF == 1) || (m_SF != m_OF)) |
| 974 | | { |
| 975 | | src = READ32(ea); |
| 976 | | STORE_REG32(modrm, src); |
| 977 | | } |
| 978 | | CYCLES(1); // TODO: correct cycle count |
| 979 | | } |
| 980 | | } |
| 981 | | |
| 982 | | void i386_device::pentium_cmovg_r16_rm16() // Opcode 0x0f 4f |
| 983 | | { |
| 984 | | UINT16 src; |
| 985 | | UINT8 modrm = FETCH(); |
| 986 | | |
| 987 | | if( modrm >= 0xc0 ) |
| 988 | | { |
| 989 | | if ((m_ZF == 0) && (m_SF == m_OF)) |
| 990 | | { |
| 991 | | src = LOAD_RM16(modrm); |
| 992 | | STORE_REG16(modrm, src); |
| 993 | | } |
| 994 | | CYCLES(1); // TODO: correct cycle count |
| 995 | | } |
| 996 | | else |
| 997 | | { |
| 998 | | UINT32 ea = GetEA(modrm,0); |
| 999 | | if ((m_ZF == 0) && (m_SF == m_OF)) |
| 1000 | | { |
| 1001 | | src = READ16(ea); |
| 1002 | | STORE_REG16(modrm, src); |
| 1003 | | } |
| 1004 | | CYCLES(1); // TODO: correct cycle count |
| 1005 | | } |
| 1006 | | } |
| 1007 | | |
| 1008 | | void i386_device::pentium_cmovg_r32_rm32() // Opcode 0x0f 4f |
| 1009 | | { |
| 1010 | | UINT32 src; |
| 1011 | | UINT8 modrm = FETCH(); |
| 1012 | | |
| 1013 | | if( modrm >= 0xc0 ) |
| 1014 | | { |
| 1015 | | if ((m_ZF == 0) && (m_SF == m_OF)) |
| 1016 | | { |
| 1017 | | src = LOAD_RM32(modrm); |
| 1018 | | STORE_REG32(modrm, src); |
| 1019 | | } |
| 1020 | | CYCLES(1); // TODO: correct cycle count |
| 1021 | | } |
| 1022 | | else |
| 1023 | | { |
| 1024 | | UINT32 ea = GetEA(modrm,0); |
| 1025 | | if ((m_ZF == 0) && (m_SF == m_OF)) |
| 1026 | | { |
| 1027 | | src = READ32(ea); |
| 1028 | | STORE_REG32(modrm, src); |
| 1029 | | } |
| 1030 | | CYCLES(1); // TODO: correct cycle count |
| 1031 | | } |
| 1032 | | } |
| 1033 | | |
| 1034 | | void i386_device::pentium_movnti_m16_r16() // Opcode 0f c3 |
| 1035 | | { |
| 1036 | | UINT8 modrm = FETCH(); |
| 1037 | | if( modrm >= 0xc0 ) { |
| 1038 | | // unsupported by cpu |
| 1039 | | CYCLES(1); // TODO: correct cycle count |
| 1040 | | } else { |
| 1041 | | // since cache is not implemented |
| 1042 | | UINT32 ea = GetEA(modrm, 0); |
| 1043 | | WRITE16(ea,LOAD_RM16(modrm)); |
| 1044 | | CYCLES(1); // TODO: correct cycle count |
| 1045 | | } |
| 1046 | | } |
| 1047 | | |
| 1048 | | void i386_device::pentium_movnti_m32_r32() // Opcode 0f c3 |
| 1049 | | { |
| 1050 | | UINT8 modrm = FETCH(); |
| 1051 | | if( modrm >= 0xc0 ) { |
| 1052 | | // unsupported by cpu |
| 1053 | | CYCLES(1); // TODO: correct cycle count |
| 1054 | | } else { |
| 1055 | | // since cache is not implemented |
| 1056 | | UINT32 ea = GetEA(modrm, 0); |
| 1057 | | WRITE32(ea,LOAD_RM32(modrm)); |
| 1058 | | CYCLES(1); // TODO: correct cycle count |
| 1059 | | } |
| 1060 | | } |
| 1061 | | |
| 1062 | | void i386_device::i386_cyrix_unknown() // Opcode 0x0f 74 |
| 1063 | | { |
| 1064 | | logerror("Unemulated 0x0f 0x74 opcode called\n"); |
| 1065 | | |
| 1066 | | CYCLES(1); |
| 1067 | | } |
| 1068 | | |
| 1069 | | void i386_device::pentium_cmpxchg8b_m64() // Opcode 0x0f c7 |
| 1070 | | { |
| 1071 | | UINT8 modm = FETCH(); |
| 1072 | | if( modm >= 0xc0 ) { |
| 1073 | | report_invalid_modrm("cmpxchg8b_m64", modm); |
| 1074 | | } else { |
| 1075 | | UINT32 ea = GetEA(modm, 0); |
| 1076 | | UINT64 value = READ64(ea); |
| 1077 | | UINT64 edx_eax = (((UINT64) REG32(EDX)) << 32) | REG32(EAX); |
| 1078 | | UINT64 ecx_ebx = (((UINT64) REG32(ECX)) << 32) | REG32(EBX); |
| 1079 | | |
| 1080 | | if( value == edx_eax ) { |
| 1081 | | WRITE64(ea, ecx_ebx); |
| 1082 | | m_ZF = 1; |
| 1083 | | CYCLES(CYCLES_CMPXCHG_REG_MEM_T); |
| 1084 | | } else { |
| 1085 | | REG32(EDX) = (UINT32) (value >> 32); |
| 1086 | | REG32(EAX) = (UINT32) (value >> 0); |
| 1087 | | m_ZF = 0; |
| 1088 | | CYCLES(CYCLES_CMPXCHG_REG_MEM_F); |
| 1089 | | } |
| 1090 | | } |
| 1091 | | } |
| 1092 | | |
| 1093 | | void i386_device::pentium_movntq_m64_r64() // Opcode 0f e7 |
| 1094 | | { |
| 1095 | | //MMXPROLOG(); // TODO: check if needed |
| 1096 | | UINT8 modrm = FETCH(); |
| 1097 | | if( modrm >= 0xc0 ) { |
| 1098 | | CYCLES(1); // unsupported |
| 1099 | | } else { |
| 1100 | | // since cache is not implemented |
| 1101 | | UINT32 ea = GetEA(modrm, 0); |
| 1102 | | WRITEMMX(ea, MMX((modrm >> 3) & 0x7)); |
| 1103 | | CYCLES(1); // TODO: correct cycle count |
| 1104 | | } |
| 1105 | | } |
| 1106 | | |
| 1107 | | void i386_device::pentium_maskmovq_r64_r64() // Opcode 0f f7 |
| 1108 | | { |
| 1109 | | int s,m,n; |
| 1110 | | UINT8 modm = FETCH(); |
| 1111 | | UINT32 ea = GetEA(7, 0); // ds:di/edi/rdi register |
| 1112 | | MMXPROLOG(); |
| 1113 | | s=(modm >> 3) & 7; |
| 1114 | | m=modm & 7; |
| 1115 | | for (n=0;n <= 7;n++) |
| 1116 | | if (MMX(m).b[n] & 127) |
| 1117 | | WRITE8(ea+n, MMX(s).b[n]); |
| 1118 | | } |
| 1119 | | |
| 1120 | | void i386_device::pentium_popcnt_r16_rm16() // Opcode f3 0f b8 |
| 1121 | | { |
| 1122 | | UINT16 src; |
| 1123 | | UINT8 modrm = FETCH(); |
| 1124 | | int n,count; |
| 1125 | | |
| 1126 | | if( modrm >= 0xc0 ) { |
| 1127 | | src = LOAD_RM16(modrm); |
| 1128 | | } else { |
| 1129 | | UINT32 ea = GetEA(modrm,0); |
| 1130 | | src = READ16(ea); |
| 1131 | | } |
| 1132 | | count=0; |
| 1133 | | for (n=0;n < 16;n++) { |
| 1134 | | count=count+(src & 1); |
| 1135 | | src=src >> 1; |
| 1136 | | } |
| 1137 | | STORE_REG16(modrm, count); |
| 1138 | | CYCLES(1); // TODO: correct cycle count |
| 1139 | | } |
| 1140 | | |
| 1141 | | void i386_device::pentium_popcnt_r32_rm32() // Opcode f3 0f b8 |
| 1142 | | { |
| 1143 | | UINT32 src; |
| 1144 | | UINT8 modrm = FETCH(); |
| 1145 | | int n,count; |
| 1146 | | |
| 1147 | | if( modrm >= 0xc0 ) { |
| 1148 | | src = LOAD_RM32(modrm); |
| 1149 | | } else { |
| 1150 | | UINT32 ea = GetEA(modrm,0); |
| 1151 | | src = READ32(ea); |
| 1152 | | } |
| 1153 | | count=0; |
| 1154 | | for (n=0;n < 32;n++) { |
| 1155 | | count=count+(src & 1); |
| 1156 | | src=src >> 1; |
| 1157 | | } |
| 1158 | | STORE_REG32(modrm, count); |
| 1159 | | CYCLES(1); // TODO: correct cycle count |
| 1160 | | } |
| 1161 | | |
| 1162 | | void i386_device::pentium_tzcnt_r16_rm16() |
| 1163 | | { |
| 1164 | | // for CPUs that don't support TZCNT, fall back to BSF |
| 1165 | | i386_bsf_r16_rm16(); |
| 1166 | | // TODO: actually implement TZCNT |
| 1167 | | } |
| 1168 | | |
| 1169 | | void i386_device::pentium_tzcnt_r32_rm32() |
| 1170 | | { |
| 1171 | | // for CPUs that don't support TZCNT, fall back to BSF |
| 1172 | | i386_bsf_r32_rm32(); |
| 1173 | | // TODO: actually implement TZCNT |
| 1174 | | } |
| 1175 | | |
| 1176 | | INLINE INT8 SaturatedSignedWordToSignedByte(INT16 word) |
| 1177 | | { |
| 1178 | | if (word > 127) |
| 1179 | | return 127; |
| 1180 | | if (word < -128) |
| 1181 | | return -128; |
| 1182 | | return (INT8)word; |
| 1183 | | } |
| 1184 | | |
| 1185 | | INLINE UINT8 SaturatedSignedWordToUnsignedByte(INT16 word) |
| 1186 | | { |
| 1187 | | if (word > 255) |
| 1188 | | return 255; |
| 1189 | | if (word < 0) |
| 1190 | | return 0; |
| 1191 | | return (UINT8)word; |
| 1192 | | } |
| 1193 | | |
| 1194 | | INLINE INT16 SaturatedSignedDwordToSignedWord(INT32 dword) |
| 1195 | | { |
| 1196 | | if (dword > 32767) |
| 1197 | | return 32767; |
| 1198 | | if (dword < -32768) |
| 1199 | | return -32768; |
| 1200 | | return (INT16)dword; |
| 1201 | | } |
| 1202 | | |
| 1203 | | void i386_device::mmx_group_0f71() // Opcode 0f 71 |
| 1204 | | { |
| 1205 | | UINT8 modm = FETCH(); |
| 1206 | | UINT8 imm8 = FETCH(); |
| 1207 | | MMXPROLOG(); |
| 1208 | | if( modm >= 0xc0 ) { |
| 1209 | | switch ( (modm & 0x38) >> 3 ) |
| 1210 | | { |
| 1211 | | case 2: // psrlw |
| 1212 | | MMX(modm & 7).w[0]=MMX(modm & 7).w[0] >> imm8; |
| 1213 | | MMX(modm & 7).w[1]=MMX(modm & 7).w[1] >> imm8; |
| 1214 | | MMX(modm & 7).w[2]=MMX(modm & 7).w[2] >> imm8; |
| 1215 | | MMX(modm & 7).w[3]=MMX(modm & 7).w[3] >> imm8; |
| 1216 | | break; |
| 1217 | | case 4: // psraw |
| 1218 | | MMX(modm & 7).s[0]=MMX(modm & 7).s[0] >> imm8; |
| 1219 | | MMX(modm & 7).s[1]=MMX(modm & 7).s[1] >> imm8; |
| 1220 | | MMX(modm & 7).s[2]=MMX(modm & 7).s[2] >> imm8; |
| 1221 | | MMX(modm & 7).s[3]=MMX(modm & 7).s[3] >> imm8; |
| 1222 | | break; |
| 1223 | | case 6: // psllw |
| 1224 | | MMX(modm & 7).w[0]=MMX(modm & 7).w[0] << imm8; |
| 1225 | | MMX(modm & 7).w[1]=MMX(modm & 7).w[1] << imm8; |
| 1226 | | MMX(modm & 7).w[2]=MMX(modm & 7).w[2] << imm8; |
| 1227 | | MMX(modm & 7).w[3]=MMX(modm & 7).w[3] << imm8; |
| 1228 | | break; |
| 1229 | | default: |
| 1230 | | report_invalid_modrm("mmx_group0f71", modm); |
| 1231 | | } |
| 1232 | | } |
| 1233 | | } |
| 1234 | | |
| 1235 | | void i386_device::mmx_group_0f72() // Opcode 0f 72 |
| 1236 | | { |
| 1237 | | UINT8 modm = FETCH(); |
| 1238 | | UINT8 imm8 = FETCH(); |
| 1239 | | MMXPROLOG(); |
| 1240 | | if( modm >= 0xc0 ) { |
| 1241 | | switch ( (modm & 0x38) >> 3 ) |
| 1242 | | { |
| 1243 | | case 2: // psrld |
| 1244 | | MMX(modm & 7).d[0]=MMX(modm & 7).d[0] >> imm8; |
| 1245 | | MMX(modm & 7).d[1]=MMX(modm & 7).d[1] >> imm8; |
| 1246 | | break; |
| 1247 | | case 4: // psrad |
| 1248 | | MMX(modm & 7).i[0]=MMX(modm & 7).i[0] >> imm8; |
| 1249 | | MMX(modm & 7).i[1]=MMX(modm & 7).i[1] >> imm8; |
| 1250 | | break; |
| 1251 | | case 6: // pslld |
| 1252 | | MMX(modm & 7).d[0]=MMX(modm & 7).d[0] << imm8; |
| 1253 | | MMX(modm & 7).d[1]=MMX(modm & 7).d[1] << imm8; |
| 1254 | | break; |
| 1255 | | default: |
| 1256 | | report_invalid_modrm("mmx_group0f72", modm); |
| 1257 | | } |
| 1258 | | } |
| 1259 | | } |
| 1260 | | |
| 1261 | | void i386_device::mmx_group_0f73() // Opcode 0f 73 |
| 1262 | | { |
| 1263 | | UINT8 modm = FETCH(); |
| 1264 | | UINT8 imm8 = FETCH(); |
| 1265 | | MMXPROLOG(); |
| 1266 | | if( modm >= 0xc0 ) { |
| 1267 | | switch ( (modm & 0x38) >> 3 ) |
| 1268 | | { |
| 1269 | | case 2: // psrlq |
| 1270 | | MMX(modm & 7).q=MMX(modm & 7).q >> imm8; |
| 1271 | | break; |
| 1272 | | case 6: // psllq |
| 1273 | | MMX(modm & 7).q=MMX(modm & 7).q << imm8; |
| 1274 | | break; |
| 1275 | | default: |
| 1276 | | report_invalid_modrm("mmx_group0f73", modm); |
| 1277 | | } |
| 1278 | | } |
| 1279 | | } |
| 1280 | | |
| 1281 | | void i386_device::mmx_psrlw_r64_rm64() // Opcode 0f d1 |
| 1282 | | { |
| 1283 | | MMXPROLOG(); |
| 1284 | | UINT8 modrm = FETCH(); |
| 1285 | | if( modrm >= 0xc0 ) { |
| 1286 | | int count=(int)MMX(modrm & 7).q; |
| 1287 | | MMX((modrm >> 3) & 0x7).w[0]=MMX((modrm >> 3) & 0x7).w[0] >> count; |
| 1288 | | MMX((modrm >> 3) & 0x7).w[1]=MMX((modrm >> 3) & 0x7).w[1] >> count; |
| 1289 | | MMX((modrm >> 3) & 0x7).w[2]=MMX((modrm >> 3) & 0x7).w[2] >> count; |
| 1290 | | MMX((modrm >> 3) & 0x7).w[3]=MMX((modrm >> 3) & 0x7).w[3] >> count; |
| 1291 | | } else { |
| 1292 | | MMX_REG src; |
| 1293 | | UINT32 ea = GetEA(modrm, 0); |
| 1294 | | READMMX(ea, src); |
| 1295 | | int count=(int)src.q; |
| 1296 | | MMX((modrm >> 3) & 0x7).w[0]=MMX((modrm >> 3) & 0x7).w[0] >> count; |
| 1297 | | MMX((modrm >> 3) & 0x7).w[1]=MMX((modrm >> 3) & 0x7).w[1] >> count; |
| 1298 | | MMX((modrm >> 3) & 0x7).w[2]=MMX((modrm >> 3) & 0x7).w[2] >> count; |
| 1299 | | MMX((modrm >> 3) & 0x7).w[3]=MMX((modrm >> 3) & 0x7).w[3] >> count; |
| 1300 | | } |
| 1301 | | CYCLES(1); // TODO: correct cycle count |
| 1302 | | } |
| 1303 | | |
| 1304 | | void i386_device::mmx_psrld_r64_rm64() // Opcode 0f d2 |
| 1305 | | { |
| 1306 | | MMXPROLOG(); |
| 1307 | | UINT8 modrm = FETCH(); |
| 1308 | | if( modrm >= 0xc0 ) { |
| 1309 | | int count=(int)MMX(modrm & 7).q; |
| 1310 | | MMX((modrm >> 3) & 0x7).d[0]=MMX((modrm >> 3) & 0x7).d[0] >> count; |
| 1311 | | MMX((modrm >> 3) & 0x7).d[1]=MMX((modrm >> 3) & 0x7).d[1] >> count; |
| 1312 | | } else { |
| 1313 | | MMX_REG src; |
| 1314 | | UINT32 ea = GetEA(modrm, 0); |
| 1315 | | READMMX(ea, src); |
| 1316 | | int count=(int)src.q; |
| 1317 | | MMX((modrm >> 3) & 0x7).d[0]=MMX((modrm >> 3) & 0x7).d[0] >> count; |
| 1318 | | MMX((modrm >> 3) & 0x7).d[1]=MMX((modrm >> 3) & 0x7).d[1] >> count; |
| 1319 | | } |
| 1320 | | CYCLES(1); // TODO: correct cycle count |
| 1321 | | } |
| 1322 | | |
| 1323 | | void i386_device::mmx_psrlq_r64_rm64() // Opcode 0f d3 |
| 1324 | | { |
| 1325 | | MMXPROLOG(); |
| 1326 | | UINT8 modrm = FETCH(); |
| 1327 | | if( modrm >= 0xc0 ) { |
| 1328 | | int count=(int)MMX(modrm & 7).q; |
| 1329 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q >> count; |
| 1330 | | } else { |
| 1331 | | MMX_REG src; |
| 1332 | | UINT32 ea = GetEA(modrm, 0); |
| 1333 | | READMMX(ea, src); |
| 1334 | | int count=(int)src.q; |
| 1335 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q >> count; |
| 1336 | | } |
| 1337 | | CYCLES(1); // TODO: correct cycle count |
| 1338 | | } |
| 1339 | | |
| 1340 | | void i386_device::mmx_paddq_r64_rm64() // Opcode 0f d4 |
| 1341 | | { |
| 1342 | | MMXPROLOG(); |
| 1343 | | UINT8 modrm = FETCH(); |
| 1344 | | if( modrm >= 0xc0 ) { |
| 1345 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q+MMX(modrm & 7).q; |
| 1346 | | } else { |
| 1347 | | MMX_REG src; |
| 1348 | | UINT32 ea = GetEA(modrm, 0); |
| 1349 | | READMMX(ea, src); |
| 1350 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q+src.q; |
| 1351 | | } |
| 1352 | | CYCLES(1); // TODO: correct cycle count |
| 1353 | | } |
| 1354 | | |
| 1355 | | void i386_device::mmx_pmullw_r64_rm64() // Opcode 0f d5 |
| 1356 | | { |
| 1357 | | MMXPROLOG(); |
| 1358 | | UINT8 modrm = FETCH(); |
| 1359 | | if( modrm >= 0xc0 ) { |
| 1360 | | MMX((modrm >> 3) & 0x7).w[0]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)MMX(modrm & 7).s[0]) & 0xffff; |
| 1361 | | MMX((modrm >> 3) & 0x7).w[1]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)MMX(modrm & 7).s[1]) & 0xffff; |
| 1362 | | MMX((modrm >> 3) & 0x7).w[2]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)MMX(modrm & 7).s[2]) & 0xffff; |
| 1363 | | MMX((modrm >> 3) & 0x7).w[3]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)MMX(modrm & 7).s[3]) & 0xffff; |
| 1364 | | } else { |
| 1365 | | MMX_REG src; |
| 1366 | | UINT32 ea = GetEA(modrm, 0); |
| 1367 | | READMMX(ea, src); |
| 1368 | | MMX((modrm >> 3) & 0x7).w[0]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)src.s[0]) & 0xffff; |
| 1369 | | MMX((modrm >> 3) & 0x7).w[1]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)src.s[1]) & 0xffff; |
| 1370 | | MMX((modrm >> 3) & 0x7).w[2]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)src.s[2]) & 0xffff; |
| 1371 | | MMX((modrm >> 3) & 0x7).w[3]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)src.s[3]) & 0xffff; |
| 1372 | | } |
| 1373 | | CYCLES(1); // TODO: correct cycle count |
| 1374 | | } |
| 1375 | | |
| 1376 | | void i386_device::mmx_psubusb_r64_rm64() // Opcode 0f d8 |
| 1377 | | { |
| 1378 | | int n; |
| 1379 | | MMXPROLOG(); |
| 1380 | | UINT8 modrm = FETCH(); |
| 1381 | | if( modrm >= 0xc0 ) { |
| 1382 | | for (n=0;n < 8;n++) |
| 1383 | | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] < MMX(modrm & 7).b[n] ? 0 : MMX((modrm >> 3) & 0x7).b[n]-MMX(modrm & 7).b[n]; |
| 1384 | | } else { |
| 1385 | | MMX_REG src; |
| 1386 | | UINT32 ea = GetEA(modrm, 0); |
| 1387 | | READMMX(ea, src); |
| 1388 | | for (n=0;n < 8;n++) |
| 1389 | | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] < src.b[n] ? 0 : MMX((modrm >> 3) & 0x7).b[n]-src.b[n]; |
| 1390 | | } |
| 1391 | | CYCLES(1); // TODO: correct cycle count |
| 1392 | | } |
| 1393 | | |
| 1394 | | void i386_device::mmx_psubusw_r64_rm64() // Opcode 0f d9 |
| 1395 | | { |
| 1396 | | int n; |
| 1397 | | MMXPROLOG(); |
| 1398 | | UINT8 modrm = FETCH(); |
| 1399 | | if( modrm >= 0xc0 ) { |
| 1400 | | for (n=0;n < 4;n++) |
| 1401 | | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] < MMX(modrm & 7).w[n] ? 0 : MMX((modrm >> 3) & 0x7).w[n]-MMX(modrm & 7).w[n]; |
| 1402 | | } else { |
| 1403 | | MMX_REG src; |
| 1404 | | UINT32 ea = GetEA(modrm, 0); |
| 1405 | | READMMX(ea, src); |
| 1406 | | for (n=0;n < 4;n++) |
| 1407 | | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] < src.w[n] ? 0 : MMX((modrm >> 3) & 0x7).w[n]-src.w[n]; |
| 1408 | | } |
| 1409 | | CYCLES(1); // TODO: correct cycle count |
| 1410 | | } |
| 1411 | | |
| 1412 | | void i386_device::mmx_pand_r64_rm64() // Opcode 0f db |
| 1413 | | { |
| 1414 | | MMXPROLOG(); |
| 1415 | | UINT8 modrm = FETCH(); |
| 1416 | | if( modrm >= 0xc0 ) { |
| 1417 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q & MMX(modrm & 7).q; |
| 1418 | | } else { |
| 1419 | | MMX_REG src; |
| 1420 | | UINT32 ea = GetEA(modrm, 0); |
| 1421 | | READMMX(ea, src); |
| 1422 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q & src.q; |
| 1423 | | } |
| 1424 | | CYCLES(1); // TODO: correct cycle count |
| 1425 | | } |
| 1426 | | |
| 1427 | | void i386_device::mmx_paddusb_r64_rm64() // Opcode 0f dc |
| 1428 | | { |
| 1429 | | int n; |
| 1430 | | MMXPROLOG(); |
| 1431 | | UINT8 modrm = FETCH(); |
| 1432 | | if( modrm >= 0xc0 ) { |
| 1433 | | for (n=0;n < 8;n++) |
| 1434 | | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] > (0xff-MMX(modrm & 7).b[n]) ? 0xff : MMX((modrm >> 3) & 0x7).b[n]+MMX(modrm & 7).b[n]; |
| 1435 | | } else { |
| 1436 | | MMX_REG src; |
| 1437 | | UINT32 ea = GetEA(modrm, 0); |
| 1438 | | READMMX(ea, src); |
| 1439 | | for (n=0;n < 8;n++) |
| 1440 | | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] > (0xff-src.b[n]) ? 0xff : MMX((modrm >> 3) & 0x7).b[n]+src.b[n]; |
| 1441 | | } |
| 1442 | | CYCLES(1); // TODO: correct cycle count |
| 1443 | | } |
| 1444 | | |
| 1445 | | void i386_device::mmx_paddusw_r64_rm64() // Opcode 0f dd |
| 1446 | | { |
| 1447 | | int n; |
| 1448 | | MMXPROLOG(); |
| 1449 | | UINT8 modrm = FETCH(); |
| 1450 | | if( modrm >= 0xc0 ) { |
| 1451 | | for (n=0;n < 4;n++) |
| 1452 | | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] > (0xffff-MMX(modrm & 7).w[n]) ? 0xffff : MMX((modrm >> 3) & 0x7).w[n]+MMX(modrm & 7).w[n]; |
| 1453 | | } else { |
| 1454 | | MMX_REG src; |
| 1455 | | UINT32 ea = GetEA(modrm, 0); |
| 1456 | | READMMX(ea, src); |
| 1457 | | for (n=0;n < 4;n++) |
| 1458 | | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] > (0xffff-src.w[n]) ? 0xffff : MMX((modrm >> 3) & 0x7).w[n]+src.w[n]; |
| 1459 | | } |
| 1460 | | CYCLES(1); // TODO: correct cycle count |
| 1461 | | } |
| 1462 | | |
| 1463 | | void i386_device::mmx_pandn_r64_rm64() // Opcode 0f df |
| 1464 | | { |
| 1465 | | MMXPROLOG(); |
| 1466 | | UINT8 modrm = FETCH(); |
| 1467 | | if( modrm >= 0xc0 ) { |
| 1468 | | MMX((modrm >> 3) & 0x7).q=(~MMX((modrm >> 3) & 0x7).q) & MMX(modrm & 7).q; |
| 1469 | | } else { |
| 1470 | | MMX_REG src; |
| 1471 | | UINT32 ea = GetEA(modrm, 0); |
| 1472 | | READMMX(ea, src); |
| 1473 | | MMX((modrm >> 3) & 0x7).q=(~MMX((modrm >> 3) & 0x7).q) & src.q; |
| 1474 | | } |
| 1475 | | CYCLES(1); // TODO: correct cycle count |
| 1476 | | } |
| 1477 | | |
| 1478 | | void i386_device::mmx_psraw_r64_rm64() // Opcode 0f e1 |
| 1479 | | { |
| 1480 | | MMXPROLOG(); |
| 1481 | | UINT8 modrm = FETCH(); |
| 1482 | | if( modrm >= 0xc0 ) { |
| 1483 | | int count=(int)MMX(modrm & 7).q; |
| 1484 | | MMX((modrm >> 3) & 0x7).s[0]=MMX((modrm >> 3) & 0x7).s[0] >> count; |
| 1485 | | MMX((modrm >> 3) & 0x7).s[1]=MMX((modrm >> 3) & 0x7).s[1] >> count; |
| 1486 | | MMX((modrm >> 3) & 0x7).s[2]=MMX((modrm >> 3) & 0x7).s[2] >> count; |
| 1487 | | MMX((modrm >> 3) & 0x7).s[3]=MMX((modrm >> 3) & 0x7).s[3] >> count; |
| 1488 | | } else { |
| 1489 | | MMX_REG src; |
| 1490 | | UINT32 ea = GetEA(modrm, 0); |
| 1491 | | READMMX(ea, src); |
| 1492 | | int count=(int)src.q; |
| 1493 | | MMX((modrm >> 3) & 0x7).s[0]=MMX((modrm >> 3) & 0x7).s[0] >> count; |
| 1494 | | MMX((modrm >> 3) & 0x7).s[1]=MMX((modrm >> 3) & 0x7).s[1] >> count; |
| 1495 | | MMX((modrm >> 3) & 0x7).s[2]=MMX((modrm >> 3) & 0x7).s[2] >> count; |
| 1496 | | MMX((modrm >> 3) & 0x7).s[3]=MMX((modrm >> 3) & 0x7).s[3] >> count; |
| 1497 | | } |
| 1498 | | CYCLES(1); // TODO: correct cycle count |
| 1499 | | } |
| 1500 | | |
| 1501 | | void i386_device::mmx_psrad_r64_rm64() // Opcode 0f e2 |
| 1502 | | { |
| 1503 | | MMXPROLOG(); |
| 1504 | | UINT8 modrm = FETCH(); |
| 1505 | | if( modrm >= 0xc0 ) { |
| 1506 | | int count=(int)MMX(modrm & 7).q; |
| 1507 | | MMX((modrm >> 3) & 0x7).i[0]=MMX((modrm >> 3) & 0x7).i[0] >> count; |
| 1508 | | MMX((modrm >> 3) & 0x7).i[1]=MMX((modrm >> 3) & 0x7).i[1] >> count; |
| 1509 | | } else { |
| 1510 | | MMX_REG src; |
| 1511 | | UINT32 ea = GetEA(modrm, 0); |
| 1512 | | READMMX(ea, src); |
| 1513 | | int count=(int)src.q; |
| 1514 | | MMX((modrm >> 3) & 0x7).i[0]=MMX((modrm >> 3) & 0x7).i[0] >> count; |
| 1515 | | MMX((modrm >> 3) & 0x7).i[1]=MMX((modrm >> 3) & 0x7).i[1] >> count; |
| 1516 | | } |
| 1517 | | CYCLES(1); // TODO: correct cycle count |
| 1518 | | } |
| 1519 | | |
| 1520 | | void i386_device::mmx_pmulhw_r64_rm64() // Opcode 0f e5 |
| 1521 | | { |
| 1522 | | MMXPROLOG(); |
| 1523 | | UINT8 modrm = FETCH(); |
| 1524 | | if( modrm >= 0xc0 ) { |
| 1525 | | MMX((modrm >> 3) & 0x7).w[0]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)MMX(modrm & 7).s[0]) >> 16; |
| 1526 | | MMX((modrm >> 3) & 0x7).w[1]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)MMX(modrm & 7).s[1]) >> 16; |
| 1527 | | MMX((modrm >> 3) & 0x7).w[2]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)MMX(modrm & 7).s[2]) >> 16; |
| 1528 | | MMX((modrm >> 3) & 0x7).w[3]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)MMX(modrm & 7).s[3]) >> 16; |
| 1529 | | } else { |
| 1530 | | MMX_REG src; |
| 1531 | | UINT32 ea = GetEA(modrm, 0); |
| 1532 | | READMMX(ea, src); |
| 1533 | | MMX((modrm >> 3) & 0x7).w[0]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)src.s[0]) >> 16; |
| 1534 | | MMX((modrm >> 3) & 0x7).w[1]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)src.s[1]) >> 16; |
| 1535 | | MMX((modrm >> 3) & 0x7).w[2]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)src.s[2]) >> 16; |
| 1536 | | MMX((modrm >> 3) & 0x7).w[3]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)src.s[3]) >> 16; |
| 1537 | | } |
| 1538 | | CYCLES(1); // TODO: correct cycle count |
| 1539 | | } |
| 1540 | | |
| 1541 | | void i386_device::mmx_psubsb_r64_rm64() // Opcode 0f e8 |
| 1542 | | { |
| 1543 | | int n; |
| 1544 | | MMXPROLOG(); |
| 1545 | | UINT8 modrm = FETCH(); |
| 1546 | | if( modrm >= 0xc0 ) { |
| 1547 | | for (n=0;n < 8;n++) |
| 1548 | | MMX((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)MMX((modrm >> 3) & 0x7).c[n] - (INT16)MMX(modrm & 7).c[n]); |
| 1549 | | } else { |
| 1550 | | MMX_REG s; |
| 1551 | | UINT32 ea = GetEA(modrm, 0); |
| 1552 | | READMMX(ea, s); |
| 1553 | | for (n=0;n < 8;n++) |
| 1554 | | MMX((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)MMX((modrm >> 3) & 0x7).c[n] - (INT16)s.c[n]); |
| 1555 | | } |
| 1556 | | CYCLES(1); // TODO: correct cycle count |
| 1557 | | } |
| 1558 | | |
| 1559 | | void i386_device::mmx_psubsw_r64_rm64() // Opcode 0f e9 |
| 1560 | | { |
| 1561 | | int n; |
| 1562 | | MMXPROLOG(); |
| 1563 | | UINT8 modrm = FETCH(); |
| 1564 | | if( modrm >= 0xc0 ) { |
| 1565 | | for (n=0;n < 4;n++) |
| 1566 | | MMX((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)MMX((modrm >> 3) & 0x7).s[n] - (INT32)MMX(modrm & 7).s[n]); |
| 1567 | | } else { |
| 1568 | | MMX_REG s; |
| 1569 | | UINT32 ea = GetEA(modrm, 0); |
| 1570 | | READMMX(ea, s); |
| 1571 | | for (n=0;n < 4;n++) |
| 1572 | | MMX((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)MMX((modrm >> 3) & 0x7).s[n] - (INT32)s.s[n]); |
| 1573 | | } |
| 1574 | | CYCLES(1); // TODO: correct cycle count |
| 1575 | | } |
| 1576 | | |
| 1577 | | void i386_device::mmx_por_r64_rm64() // Opcode 0f eb |
| 1578 | | { |
| 1579 | | MMXPROLOG(); |
| 1580 | | UINT8 modrm = FETCH(); |
| 1581 | | if( modrm >= 0xc0 ) { |
| 1582 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q | MMX(modrm & 7).q; |
| 1583 | | } else { |
| 1584 | | MMX_REG s; |
| 1585 | | UINT32 ea = GetEA(modrm, 0); |
| 1586 | | READMMX(ea, s); |
| 1587 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q | s.q; |
| 1588 | | } |
| 1589 | | CYCLES(1); // TODO: correct cycle count |
| 1590 | | } |
| 1591 | | |
| 1592 | | void i386_device::mmx_paddsb_r64_rm64() // Opcode 0f ec |
| 1593 | | { |
| 1594 | | int n; |
| 1595 | | MMXPROLOG(); |
| 1596 | | UINT8 modrm = FETCH(); |
| 1597 | | if( modrm >= 0xc0 ) { |
| 1598 | | for (n=0;n < 8;n++) |
| 1599 | | MMX((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)MMX((modrm >> 3) & 0x7).c[n] + (INT16)MMX(modrm & 7).c[n]); |
| 1600 | | } else { |
| 1601 | | MMX_REG s; |
| 1602 | | UINT32 ea = GetEA(modrm, 0); |
| 1603 | | READMMX(ea, s); |
| 1604 | | for (n=0;n < 8;n++) |
| 1605 | | MMX((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)MMX((modrm >> 3) & 0x7).c[n] + (INT16)s.c[n]); |
| 1606 | | } |
| 1607 | | CYCLES(1); // TODO: correct cycle count |
| 1608 | | } |
| 1609 | | |
| 1610 | | void i386_device::mmx_paddsw_r64_rm64() // Opcode 0f ed |
| 1611 | | { |
| 1612 | | int n; |
| 1613 | | MMXPROLOG(); |
| 1614 | | UINT8 modrm = FETCH(); |
| 1615 | | if( modrm >= 0xc0 ) { |
| 1616 | | for (n=0;n < 4;n++) |
| 1617 | | MMX((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)MMX((modrm >> 3) & 0x7).s[n] + (INT32)MMX(modrm & 7).s[n]); |
| 1618 | | } else { |
| 1619 | | MMX_REG s; |
| 1620 | | UINT32 ea = GetEA(modrm, 0); |
| 1621 | | READMMX(ea, s); |
| 1622 | | for (n=0;n < 4;n++) |
| 1623 | | MMX((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)MMX((modrm >> 3) & 0x7).s[n] + (INT32)s.s[n]); |
| 1624 | | } |
| 1625 | | CYCLES(1); // TODO: correct cycle count |
| 1626 | | } |
| 1627 | | |
| 1628 | | void i386_device::mmx_pxor_r64_rm64() // Opcode 0f ef |
| 1629 | | { |
| 1630 | | MMXPROLOG(); |
| 1631 | | UINT8 modrm = FETCH(); |
| 1632 | | if( modrm >= 0xc0 ) { |
| 1633 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q ^ MMX(modrm & 7).q; |
| 1634 | | } else { |
| 1635 | | MMX_REG s; |
| 1636 | | UINT32 ea = GetEA(modrm, 0); |
| 1637 | | READMMX(ea, s); |
| 1638 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q ^ s.q; |
| 1639 | | } |
| 1640 | | CYCLES(1); // TODO: correct cycle count |
| 1641 | | } |
| 1642 | | |
| 1643 | | void i386_device::mmx_psllw_r64_rm64() // Opcode 0f f1 |
| 1644 | | { |
| 1645 | | MMXPROLOG(); |
| 1646 | | UINT8 modrm = FETCH(); |
| 1647 | | if( modrm >= 0xc0 ) { |
| 1648 | | int count=(int)MMX(modrm & 7).q; |
| 1649 | | MMX((modrm >> 3) & 0x7).w[0]=MMX((modrm >> 3) & 0x7).w[0] << count; |
| 1650 | | MMX((modrm >> 3) & 0x7).w[1]=MMX((modrm >> 3) & 0x7).w[1] << count; |
| 1651 | | MMX((modrm >> 3) & 0x7).w[2]=MMX((modrm >> 3) & 0x7).w[2] << count; |
| 1652 | | MMX((modrm >> 3) & 0x7).w[3]=MMX((modrm >> 3) & 0x7).w[3] << count; |
| 1653 | | } else { |
| 1654 | | MMX_REG s; |
| 1655 | | UINT32 ea = GetEA(modrm, 0); |
| 1656 | | READMMX(ea, s); |
| 1657 | | int count=(int)s.q; |
| 1658 | | MMX((modrm >> 3) & 0x7).w[0]=MMX((modrm >> 3) & 0x7).w[0] << count; |
| 1659 | | MMX((modrm >> 3) & 0x7).w[1]=MMX((modrm >> 3) & 0x7).w[1] << count; |
| 1660 | | MMX((modrm >> 3) & 0x7).w[2]=MMX((modrm >> 3) & 0x7).w[2] << count; |
| 1661 | | MMX((modrm >> 3) & 0x7).w[3]=MMX((modrm >> 3) & 0x7).w[3] << count; |
| 1662 | | } |
| 1663 | | CYCLES(1); // TODO: correct cycle count |
| 1664 | | } |
| 1665 | | |
| 1666 | | void i386_device::mmx_pslld_r64_rm64() // Opcode 0f f2 |
| 1667 | | { |
| 1668 | | MMXPROLOG(); |
| 1669 | | UINT8 modrm = FETCH(); |
| 1670 | | if( modrm >= 0xc0 ) { |
| 1671 | | int count=(int)MMX(modrm & 7).q; |
| 1672 | | MMX((modrm >> 3) & 0x7).d[0]=MMX((modrm >> 3) & 0x7).d[0] << count; |
| 1673 | | MMX((modrm >> 3) & 0x7).d[1]=MMX((modrm >> 3) & 0x7).d[1] << count; |
| 1674 | | } else { |
| 1675 | | MMX_REG s; |
| 1676 | | UINT32 ea = GetEA(modrm, 0); |
| 1677 | | READMMX(ea, s); |
| 1678 | | int count=(int)s.q; |
| 1679 | | MMX((modrm >> 3) & 0x7).d[0]=MMX((modrm >> 3) & 0x7).d[0] << count; |
| 1680 | | MMX((modrm >> 3) & 0x7).d[1]=MMX((modrm >> 3) & 0x7).d[1] << count; |
| 1681 | | } |
| 1682 | | CYCLES(1); // TODO: correct cycle count |
| 1683 | | } |
| 1684 | | |
| 1685 | | void i386_device::mmx_psllq_r64_rm64() // Opcode 0f f3 |
| 1686 | | { |
| 1687 | | MMXPROLOG(); |
| 1688 | | UINT8 modrm = FETCH(); |
| 1689 | | if( modrm >= 0xc0 ) { |
| 1690 | | int count=(int)MMX(modrm & 7).q; |
| 1691 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q << count; |
| 1692 | | } else { |
| 1693 | | MMX_REG s; |
| 1694 | | UINT32 ea = GetEA(modrm, 0); |
| 1695 | | READMMX(ea, s); |
| 1696 | | int count=(int)s.q; |
| 1697 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q << count; |
| 1698 | | } |
| 1699 | | CYCLES(1); // TODO: correct cycle count |
| 1700 | | } |
| 1701 | | |
| 1702 | | void i386_device::mmx_pmaddwd_r64_rm64() // Opcode 0f f5 |
| 1703 | | { |
| 1704 | | MMXPROLOG(); |
| 1705 | | UINT8 modrm = FETCH(); |
| 1706 | | if( modrm >= 0xc0 ) { |
| 1707 | | MMX((modrm >> 3) & 0x7).i[0]=(INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)MMX(modrm & 7).s[0]+ |
| 1708 | | (INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)MMX(modrm & 7).s[1]; |
| 1709 | | MMX((modrm >> 3) & 0x7).i[1]=(INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)MMX(modrm & 7).s[2]+ |
| 1710 | | (INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)MMX(modrm & 7).s[3]; |
| 1711 | | } else { |
| 1712 | | MMX_REG s; |
| 1713 | | UINT32 ea = GetEA(modrm, 0); |
| 1714 | | READMMX(ea, s); |
| 1715 | | MMX((modrm >> 3) & 0x7).i[0]=(INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)s.s[0]+ |
| 1716 | | (INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)s.s[1]; |
| 1717 | | MMX((modrm >> 3) & 0x7).i[1]=(INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)s.s[2]+ |
| 1718 | | (INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)s.s[3]; |
| 1719 | | } |
| 1720 | | CYCLES(1); // TODO: correct cycle count |
| 1721 | | } |
| 1722 | | |
| 1723 | | void i386_device::mmx_psubb_r64_rm64() // Opcode 0f f8 |
| 1724 | | { |
| 1725 | | int n; |
| 1726 | | MMXPROLOG(); |
| 1727 | | UINT8 modrm = FETCH(); |
| 1728 | | if( modrm >= 0xc0 ) { |
| 1729 | | for (n=0;n < 8;n++) |
| 1730 | | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] - MMX(modrm & 7).b[n]; |
| 1731 | | } else { |
| 1732 | | MMX_REG s; |
| 1733 | | UINT32 ea = GetEA(modrm, 0); |
| 1734 | | READMMX(ea, s); |
| 1735 | | for (n=0;n < 8;n++) |
| 1736 | | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] - s.b[n]; |
| 1737 | | } |
| 1738 | | CYCLES(1); // TODO: correct cycle count |
| 1739 | | } |
| 1740 | | |
| 1741 | | void i386_device::mmx_psubw_r64_rm64() // Opcode 0f f9 |
| 1742 | | { |
| 1743 | | int n; |
| 1744 | | MMXPROLOG(); |
| 1745 | | UINT8 modrm = FETCH(); |
| 1746 | | if( modrm >= 0xc0 ) { |
| 1747 | | for (n=0;n < 4;n++) |
| 1748 | | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] - MMX(modrm & 7).w[n]; |
| 1749 | | } else { |
| 1750 | | MMX_REG s; |
| 1751 | | UINT32 ea = GetEA(modrm, 0); |
| 1752 | | READMMX(ea, s); |
| 1753 | | for (n=0;n < 4;n++) |
| 1754 | | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] - s.w[n]; |
| 1755 | | } |
| 1756 | | CYCLES(1); // TODO: correct cycle count |
| 1757 | | } |
| 1758 | | |
| 1759 | | void i386_device::mmx_psubd_r64_rm64() // Opcode 0f fa |
| 1760 | | { |
| 1761 | | int n; |
| 1762 | | MMXPROLOG(); |
| 1763 | | UINT8 modrm = FETCH(); |
| 1764 | | if( modrm >= 0xc0 ) { |
| 1765 | | for (n=0;n < 2;n++) |
| 1766 | | MMX((modrm >> 3) & 0x7).d[n]=MMX((modrm >> 3) & 0x7).d[n] - MMX(modrm & 7).d[n]; |
| 1767 | | } else { |
| 1768 | | MMX_REG s; |
| 1769 | | UINT32 ea = GetEA(modrm, 0); |
| 1770 | | READMMX(ea, s); |
| 1771 | | for (n=0;n < 2;n++) |
| 1772 | | MMX((modrm >> 3) & 0x7).d[n]=MMX((modrm >> 3) & 0x7).d[n] - s.d[n]; |
| 1773 | | } |
| 1774 | | CYCLES(1); // TODO: correct cycle count |
| 1775 | | } |
| 1776 | | |
| 1777 | | void i386_device::mmx_paddb_r64_rm64() // Opcode 0f fc |
| 1778 | | { |
| 1779 | | int n; |
| 1780 | | MMXPROLOG(); |
| 1781 | | UINT8 modrm = FETCH(); |
| 1782 | | if( modrm >= 0xc0 ) { |
| 1783 | | for (n=0;n < 8;n++) |
| 1784 | | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] + MMX(modrm & 7).b[n]; |
| 1785 | | } else { |
| 1786 | | MMX_REG s; |
| 1787 | | UINT32 ea = GetEA(modrm, 0); |
| 1788 | | READMMX(ea, s); |
| 1789 | | for (n=0;n < 8;n++) |
| 1790 | | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] + s.b[n]; |
| 1791 | | } |
| 1792 | | CYCLES(1); // TODO: correct cycle count |
| 1793 | | } |
| 1794 | | |
| 1795 | | void i386_device::mmx_paddw_r64_rm64() // Opcode 0f fd |
| 1796 | | { |
| 1797 | | int n; |
| 1798 | | MMXPROLOG(); |
| 1799 | | UINT8 modrm = FETCH(); |
| 1800 | | if( modrm >= 0xc0 ) { |
| 1801 | | for (n=0;n < 4;n++) |
| 1802 | | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] + MMX(modrm & 7).w[n]; |
| 1803 | | } else { |
| 1804 | | MMX_REG s; |
| 1805 | | UINT32 ea = GetEA(modrm, 0); |
| 1806 | | READMMX(ea, s); |
| 1807 | | for (n=0;n < 4;n++) |
| 1808 | | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] + s.w[n]; |
| 1809 | | } |
| 1810 | | CYCLES(1); // TODO: correct cycle count |
| 1811 | | } |
| 1812 | | |
| 1813 | | void i386_device::mmx_paddd_r64_rm64() // Opcode 0f fe |
| 1814 | | { |
| 1815 | | int n; |
| 1816 | | MMXPROLOG(); |
| 1817 | | UINT8 modrm = FETCH(); |
| 1818 | | if( modrm >= 0xc0 ) { |
| 1819 | | for (n=0;n < 2;n++) |
| 1820 | | MMX((modrm >> 3) & 0x7).d[n]=MMX((modrm >> 3) & 0x7).d[n] + MMX(modrm & 7).d[n]; |
| 1821 | | } else { |
| 1822 | | MMX_REG s; |
| 1823 | | UINT32 ea = GetEA(modrm, 0); |
| 1824 | | READMMX(ea, s); |
| 1825 | | for (n=0;n < 2;n++) |
| 1826 | | MMX((modrm >> 3) & 0x7).d[n]=MMX((modrm >> 3) & 0x7).d[n] + s.d[n]; |
| 1827 | | } |
| 1828 | | CYCLES(1); // TODO: correct cycle count |
| 1829 | | } |
| 1830 | | |
| 1831 | | void i386_device::mmx_emms() // Opcode 0f 77 |
| 1832 | | { |
| 1833 | | m_x87_tw = 0xffff; // tag word = 0xffff |
| 1834 | | // TODO |
| 1835 | | CYCLES(1); // TODO: correct cycle count |
| 1836 | | } |
| 1837 | | |
| 1838 | | void i386_device::mmx_movd_r64_rm32() // Opcode 0f 6e |
| 1839 | | { |
| 1840 | | MMXPROLOG(); |
| 1841 | | UINT8 modrm = FETCH(); |
| 1842 | | if( modrm >= 0xc0 ) { |
| 1843 | | MMX((modrm >> 3) & 0x7).d[0]=LOAD_RM32(modrm); |
| 1844 | | } else { |
| 1845 | | UINT32 ea = GetEA(modrm, 0); |
| 1846 | | MMX((modrm >> 3) & 0x7).d[0]=READ32(ea); |
| 1847 | | } |
| 1848 | | MMX((modrm >> 3) & 0x7).d[1]=0; |
| 1849 | | CYCLES(1); // TODO: correct cycle count |
| 1850 | | } |
| 1851 | | |
| 1852 | | void i386_device::mmx_movq_r64_rm64() // Opcode 0f 6f |
| 1853 | | { |
| 1854 | | MMXPROLOG(); |
| 1855 | | UINT8 modrm = FETCH(); |
| 1856 | | if( modrm >= 0xc0 ) { |
| 1857 | | MMX((modrm >> 3) & 0x7).l=MMX(modrm & 0x7).l; |
| 1858 | | } else { |
| 1859 | | UINT32 ea = GetEA(modrm, 0); |
| 1860 | | READMMX(ea, MMX((modrm >> 3) & 0x7)); |
| 1861 | | } |
| 1862 | | CYCLES(1); // TODO: correct cycle count |
| 1863 | | } |
| 1864 | | |
| 1865 | | void i386_device::mmx_movd_rm32_r64() // Opcode 0f 7e |
| 1866 | | { |
| 1867 | | MMXPROLOG(); |
| 1868 | | UINT8 modrm = FETCH(); |
| 1869 | | if( modrm >= 0xc0 ) { |
| 1870 | | STORE_RM32(modrm, MMX((modrm >> 3) & 0x7).d[0]); |
| 1871 | | } else { |
| 1872 | | UINT32 ea = GetEA(modrm, 0); |
| 1873 | | WRITE32(ea, MMX((modrm >> 3) & 0x7).d[0]); |
| 1874 | | } |
| 1875 | | CYCLES(1); // TODO: correct cycle count |
| 1876 | | } |
| 1877 | | |
| 1878 | | void i386_device::mmx_movq_rm64_r64() // Opcode 0f 7f |
| 1879 | | { |
| 1880 | | MMXPROLOG(); |
| 1881 | | UINT8 modrm = FETCH(); |
| 1882 | | if( modrm >= 0xc0 ) { |
| 1883 | | MMX(modrm & 0x7)=MMX((modrm >> 3) & 0x7); |
| 1884 | | } else { |
| 1885 | | UINT32 ea = GetEA(modrm, 0); |
| 1886 | | WRITEMMX(ea, MMX((modrm >> 3) & 0x7)); |
| 1887 | | } |
| 1888 | | CYCLES(1); // TODO: correct cycle count |
| 1889 | | } |
| 1890 | | |
| 1891 | | void i386_device::mmx_pcmpeqb_r64_rm64() // Opcode 0f 74 |
| 1892 | | { |
| 1893 | | int c; |
| 1894 | | MMXPROLOG(); |
| 1895 | | UINT8 modrm = FETCH(); |
| 1896 | | if( modrm >= 0xc0 ) { |
| 1897 | | int s,d; |
| 1898 | | s=modrm & 0x7; |
| 1899 | | d=(modrm >> 3) & 0x7; |
| 1900 | | for (c=0;c <= 7;c++) |
| 1901 | | MMX(d).b[c]=(MMX(d).b[c] == MMX(s).b[c]) ? 0xff : 0; |
| 1902 | | } else { |
| 1903 | | MMX_REG s; |
| 1904 | | int d=(modrm >> 3) & 0x7; |
| 1905 | | UINT32 ea = GetEA(modrm, 0); |
| 1906 | | READMMX(ea, s); |
| 1907 | | for (c=0;c <= 7;c++) |
| 1908 | | MMX(d).b[c]=(MMX(d).b[c] == s.b[c]) ? 0xff : 0; |
| 1909 | | } |
| 1910 | | CYCLES(1); // TODO: correct cycle count |
| 1911 | | } |
| 1912 | | |
| 1913 | | void i386_device::mmx_pcmpeqw_r64_rm64() // Opcode 0f 75 |
| 1914 | | { |
| 1915 | | MMXPROLOG(); |
| 1916 | | UINT8 modrm = FETCH(); |
| 1917 | | if( modrm >= 0xc0 ) { |
| 1918 | | int s,d; |
| 1919 | | s=modrm & 0x7; |
| 1920 | | d=(modrm >> 3) & 0x7; |
| 1921 | | MMX(d).w[0]=(MMX(d).w[0] == MMX(s).w[0]) ? 0xffff : 0; |
| 1922 | | MMX(d).w[1]=(MMX(d).w[1] == MMX(s).w[1]) ? 0xffff : 0; |
| 1923 | | MMX(d).w[2]=(MMX(d).w[2] == MMX(s).w[2]) ? 0xffff : 0; |
| 1924 | | MMX(d).w[3]=(MMX(d).w[3] == MMX(s).w[3]) ? 0xffff : 0; |
| 1925 | | } else { |
| 1926 | | MMX_REG s; |
| 1927 | | int d=(modrm >> 3) & 0x7; |
| 1928 | | UINT32 ea = GetEA(modrm, 0); |
| 1929 | | READMMX(ea, s); |
| 1930 | | MMX(d).w[0]=(MMX(d).w[0] == s.w[0]) ? 0xffff : 0; |
| 1931 | | MMX(d).w[1]=(MMX(d).w[1] == s.w[1]) ? 0xffff : 0; |
| 1932 | | MMX(d).w[2]=(MMX(d).w[2] == s.w[2]) ? 0xffff : 0; |
| 1933 | | MMX(d).w[3]=(MMX(d).w[3] == s.w[3]) ? 0xffff : 0; |
| 1934 | | } |
| 1935 | | CYCLES(1); // TODO: correct cycle count |
| 1936 | | } |
| 1937 | | |
| 1938 | | void i386_device::mmx_pcmpeqd_r64_rm64() // Opcode 0f 76 |
| 1939 | | { |
| 1940 | | MMXPROLOG(); |
| 1941 | | UINT8 modrm = FETCH(); |
| 1942 | | if( modrm >= 0xc0 ) { |
| 1943 | | int s,d; |
| 1944 | | s=modrm & 0x7; |
| 1945 | | d=(modrm >> 3) & 0x7; |
| 1946 | | MMX(d).d[0]=(MMX(d).d[0] == MMX(s).d[0]) ? 0xffffffff : 0; |
| 1947 | | MMX(d).d[1]=(MMX(d).d[1] == MMX(s).d[1]) ? 0xffffffff : 0; |
| 1948 | | } else { |
| 1949 | | MMX_REG s; |
| 1950 | | int d=(modrm >> 3) & 0x7; |
| 1951 | | UINT32 ea = GetEA(modrm, 0); |
| 1952 | | READMMX(ea, s); |
| 1953 | | MMX(d).d[0]=(MMX(d).d[0] == s.d[0]) ? 0xffffffff : 0; |
| 1954 | | MMX(d).d[1]=(MMX(d).d[1] == s.d[1]) ? 0xffffffff : 0; |
| 1955 | | } |
| 1956 | | CYCLES(1); // TODO: correct cycle count |
| 1957 | | } |
| 1958 | | |
| 1959 | | void i386_device::mmx_pshufw_r64_rm64_i8() // Opcode 0f 70 |
| 1960 | | { |
| 1961 | | MMXPROLOG(); |
| 1962 | | UINT8 modrm = FETCH(); |
| 1963 | | if( modrm >= 0xc0 ) { |
| 1964 | | MMX_REG t; |
| 1965 | | int s,d; |
| 1966 | | UINT8 imm8 = FETCH(); |
| 1967 | | s=modrm & 0x7; |
| 1968 | | d=(modrm >> 3) & 0x7; |
| 1969 | | t.q=MMX(s).q; |
| 1970 | | MMX(d).w[0]=t.w[imm8 & 3]; |
| 1971 | | MMX(d).w[1]=t.w[(imm8 >> 2) & 3]; |
| 1972 | | MMX(d).w[2]=t.w[(imm8 >> 4) & 3]; |
| 1973 | | MMX(d).w[3]=t.w[(imm8 >> 6) & 3]; |
| 1974 | | } else { |
| 1975 | | MMX_REG s; |
| 1976 | | int d=(modrm >> 3) & 0x7; |
| 1977 | | UINT32 ea = GetEA(modrm, 0); |
| 1978 | | UINT8 imm8 = FETCH(); |
| 1979 | | READMMX(ea, s); |
| 1980 | | MMX(d).w[0]=s.w[imm8 & 3]; |
| 1981 | | MMX(d).w[1]=s.w[(imm8 >> 2) & 3]; |
| 1982 | | MMX(d).w[2]=s.w[(imm8 >> 4) & 3]; |
| 1983 | | MMX(d).w[3]=s.w[(imm8 >> 6) & 3]; |
| 1984 | | } |
| 1985 | | CYCLES(1); // TODO: correct cycle count |
| 1986 | | } |
| 1987 | | |
| 1988 | | void i386_device::mmx_punpcklbw_r64_r64m32() // Opcode 0f 60 |
| 1989 | | { |
| 1990 | | MMXPROLOG(); |
| 1991 | | UINT8 modrm = FETCH(); |
| 1992 | | if( modrm >= 0xc0 ) { |
| 1993 | | UINT32 t; |
| 1994 | | int s,d; |
| 1995 | | s=modrm & 0x7; |
| 1996 | | d=(modrm >> 3) & 0x7; |
| 1997 | | t=MMX(d).d[0]; |
| 1998 | | MMX(d).b[0]=t & 0xff; |
| 1999 | | MMX(d).b[1]=MMX(s).b[0]; |
| 2000 | | MMX(d).b[2]=(t >> 8) & 0xff; |
| 2001 | | MMX(d).b[3]=MMX(s).b[1]; |
| 2002 | | MMX(d).b[4]=(t >> 16) & 0xff; |
| 2003 | | MMX(d).b[5]=MMX(s).b[2]; |
| 2004 | | MMX(d).b[6]=(t >> 24) & 0xff; |
| 2005 | | MMX(d).b[7]=MMX(s).b[3]; |
| 2006 | | } else { |
| 2007 | | UINT32 s,t; |
| 2008 | | int d=(modrm >> 3) & 0x7; |
| 2009 | | UINT32 ea = GetEA(modrm, 0); |
| 2010 | | s = READ32(ea); |
| 2011 | | t=MMX(d).d[0]; |
| 2012 | | MMX(d).b[0]=t & 0xff; |
| 2013 | | MMX(d).b[1]=s & 0xff; |
| 2014 | | MMX(d).b[2]=(t >> 8) & 0xff; |
| 2015 | | MMX(d).b[3]=(s >> 8) & 0xff; |
| 2016 | | MMX(d).b[4]=(t >> 16) & 0xff; |
| 2017 | | MMX(d).b[5]=(s >> 16) & 0xff; |
| 2018 | | MMX(d).b[6]=(t >> 24) & 0xff; |
| 2019 | | MMX(d).b[7]=(s >> 24) & 0xff; |
| 2020 | | } |
| 2021 | | CYCLES(1); // TODO: correct cycle count |
| 2022 | | } |
| 2023 | | |
| 2024 | | void i386_device::mmx_punpcklwd_r64_r64m32() // Opcode 0f 61 |
| 2025 | | { |
| 2026 | | MMXPROLOG(); |
| 2027 | | UINT8 modrm = FETCH(); |
| 2028 | | if( modrm >= 0xc0 ) { |
| 2029 | | UINT16 t; |
| 2030 | | int s,d; |
| 2031 | | s=modrm & 0x7; |
| 2032 | | d=(modrm >> 3) & 0x7; |
| 2033 | | t=MMX(d).w[1]; |
| 2034 | | MMX(d).w[0]=MMX(d).w[0]; |
| 2035 | | MMX(d).w[1]=MMX(s).w[0]; |
| 2036 | | MMX(d).w[2]=t; |
| 2037 | | MMX(d).w[3]=MMX(s).w[1]; |
| 2038 | | } else { |
| 2039 | | UINT32 s; |
| 2040 | | UINT16 t; |
| 2041 | | int d=(modrm >> 3) & 0x7; |
| 2042 | | UINT32 ea = GetEA(modrm, 0); |
| 2043 | | s = READ32(ea); |
| 2044 | | t=MMX(d).w[1]; |
| 2045 | | MMX(d).w[0]=MMX(d).w[0]; |
| 2046 | | MMX(d).w[1]=s & 0xffff; |
| 2047 | | MMX(d).w[2]=t; |
| 2048 | | MMX(d).w[3]=(s >> 16) & 0xffff; |
| 2049 | | } |
| 2050 | | CYCLES(1); // TODO: correct cycle count |
| 2051 | | } |
| 2052 | | |
| 2053 | | void i386_device::mmx_punpckldq_r64_r64m32() // Opcode 0f 62 |
| 2054 | | { |
| 2055 | | MMXPROLOG(); |
| 2056 | | UINT8 modrm = FETCH(); |
| 2057 | | if( modrm >= 0xc0 ) { |
| 2058 | | int s,d; |
| 2059 | | s=modrm & 0x7; |
| 2060 | | d=(modrm >> 3) & 0x7; |
| 2061 | | MMX(d).d[0]=MMX(d).d[0]; |
| 2062 | | MMX(d).d[1]=MMX(s).d[0]; |
| 2063 | | } else { |
| 2064 | | UINT32 s; |
| 2065 | | int d=(modrm >> 3) & 0x7; |
| 2066 | | UINT32 ea = GetEA(modrm, 0); |
| 2067 | | s = READ32(ea); |
| 2068 | | MMX(d).d[0]=MMX(d).d[0]; |
| 2069 | | MMX(d).d[1]=s; |
| 2070 | | } |
| 2071 | | CYCLES(1); // TODO: correct cycle count |
| 2072 | | } |
| 2073 | | |
| 2074 | | void i386_device::mmx_packsswb_r64_rm64() // Opcode 0f 63 |
| 2075 | | { |
| 2076 | | MMXPROLOG(); |
| 2077 | | UINT8 modrm = FETCH(); |
| 2078 | | if( modrm >= 0xc0 ) { |
| 2079 | | int s,d; |
| 2080 | | s=modrm & 0x7; |
| 2081 | | d=(modrm >> 3) & 0x7; |
| 2082 | | MMX(d).c[0]=SaturatedSignedWordToSignedByte(MMX(d).s[0]); |
| 2083 | | MMX(d).c[1]=SaturatedSignedWordToSignedByte(MMX(d).s[1]); |
| 2084 | | MMX(d).c[2]=SaturatedSignedWordToSignedByte(MMX(d).s[2]); |
| 2085 | | MMX(d).c[3]=SaturatedSignedWordToSignedByte(MMX(d).s[3]); |
| 2086 | | MMX(d).c[4]=SaturatedSignedWordToSignedByte(MMX(s).s[0]); |
| 2087 | | MMX(d).c[5]=SaturatedSignedWordToSignedByte(MMX(s).s[1]); |
| 2088 | | MMX(d).c[6]=SaturatedSignedWordToSignedByte(MMX(s).s[2]); |
| 2089 | | MMX(d).c[7]=SaturatedSignedWordToSignedByte(MMX(s).s[3]); |
| 2090 | | } else { |
| 2091 | | MMX_REG s; |
| 2092 | | int d=(modrm >> 3) & 0x7; |
| 2093 | | UINT32 ea = GetEA(modrm, 0); |
| 2094 | | READMMX(ea, s); |
| 2095 | | MMX(d).c[0]=SaturatedSignedWordToSignedByte(MMX(d).s[0]); |
| 2096 | | MMX(d).c[1]=SaturatedSignedWordToSignedByte(MMX(d).s[1]); |
| 2097 | | MMX(d).c[2]=SaturatedSignedWordToSignedByte(MMX(d).s[2]); |
| 2098 | | MMX(d).c[3]=SaturatedSignedWordToSignedByte(MMX(d).s[3]); |
| 2099 | | MMX(d).c[4]=SaturatedSignedWordToSignedByte(s.s[0]); |
| 2100 | | MMX(d).c[5]=SaturatedSignedWordToSignedByte(s.s[1]); |
| 2101 | | MMX(d).c[6]=SaturatedSignedWordToSignedByte(s.s[2]); |
| 2102 | | MMX(d).c[7]=SaturatedSignedWordToSignedByte(s.s[3]); |
| 2103 | | } |
| 2104 | | CYCLES(1); // TODO: correct cycle count |
| 2105 | | } |
| 2106 | | |
| 2107 | | void i386_device::mmx_pcmpgtb_r64_rm64() // Opcode 0f 64 |
| 2108 | | { |
| 2109 | | int c; |
| 2110 | | MMXPROLOG(); |
| 2111 | | UINT8 modrm = FETCH(); |
| 2112 | | if( modrm >= 0xc0 ) { |
| 2113 | | int s,d; |
| 2114 | | s=modrm & 0x7; |
| 2115 | | d=(modrm >> 3) & 0x7; |
| 2116 | | for (c=0;c <= 7;c++) |
| 2117 | | MMX(d).b[c]=(MMX(d).c[c] > MMX(s).c[c]) ? 0xff : 0; |
| 2118 | | } else { |
| 2119 | | MMX_REG s; |
| 2120 | | int d=(modrm >> 3) & 0x7; |
| 2121 | | UINT32 ea = GetEA(modrm, 0); |
| 2122 | | READMMX(ea, s); |
| 2123 | | for (c=0;c <= 7;c++) |
| 2124 | | MMX(d).b[c]=(MMX(d).c[c] > s.c[c]) ? 0xff : 0; |
| 2125 | | } |
| 2126 | | CYCLES(1); // TODO: correct cycle count |
| 2127 | | } |
| 2128 | | |
| 2129 | | void i386_device::mmx_pcmpgtw_r64_rm64() // Opcode 0f 65 |
| 2130 | | { |
| 2131 | | int c; |
| 2132 | | MMXPROLOG(); |
| 2133 | | UINT8 modrm = FETCH(); |
| 2134 | | if( modrm >= 0xc0 ) { |
| 2135 | | int s,d; |
| 2136 | | s=modrm & 0x7; |
| 2137 | | d=(modrm >> 3) & 0x7; |
| 2138 | | for (c=0;c <= 3;c++) |
| 2139 | | MMX(d).w[c]=(MMX(d).s[c] > MMX(s).s[c]) ? 0xffff : 0; |
| 2140 | | } else { |
| 2141 | | MMX_REG s; |
| 2142 | | int d=(modrm >> 3) & 0x7; |
| 2143 | | UINT32 ea = GetEA(modrm, 0); |
| 2144 | | READMMX(ea, s); |
| 2145 | | for (c=0;c <= 3;c++) |
| 2146 | | MMX(d).w[c]=(MMX(d).s[c] > s.s[c]) ? 0xffff : 0; |
| 2147 | | } |
| 2148 | | CYCLES(1); // TODO: correct cycle count |
| 2149 | | } |
| 2150 | | |
| 2151 | | void i386_device::mmx_pcmpgtd_r64_rm64() // Opcode 0f 66 |
| 2152 | | { |
| 2153 | | int c; |
| 2154 | | MMXPROLOG(); |
| 2155 | | UINT8 modrm = FETCH(); |
| 2156 | | if( modrm >= 0xc0 ) { |
| 2157 | | int s,d; |
| 2158 | | s=modrm & 0x7; |
| 2159 | | d=(modrm >> 3) & 0x7; |
| 2160 | | for (c=0;c <= 1;c++) |
| 2161 | | MMX(d).d[c]=(MMX(d).i[c] > MMX(s).i[c]) ? 0xffffffff : 0; |
| 2162 | | } else { |
| 2163 | | MMX_REG s; |
| 2164 | | int d=(modrm >> 3) & 0x7; |
| 2165 | | UINT32 ea = GetEA(modrm, 0); |
| 2166 | | READMMX(ea, s); |
| 2167 | | for (c=0;c <= 1;c++) |
| 2168 | | MMX(d).d[c]=(MMX(d).i[c] > s.i[c]) ? 0xffffffff : 0; |
| 2169 | | } |
| 2170 | | CYCLES(1); // TODO: correct cycle count |
| 2171 | | } |
| 2172 | | |
| 2173 | | void i386_device::mmx_packuswb_r64_rm64() // Opcode 0f 67 |
| 2174 | | { |
| 2175 | | MMXPROLOG(); |
| 2176 | | UINT8 modrm = FETCH(); |
| 2177 | | if( modrm >= 0xc0 ) { |
| 2178 | | int s,d; |
| 2179 | | s=modrm & 0x7; |
| 2180 | | d=(modrm >> 3) & 0x7; |
| 2181 | | MMX(d).b[0]=SaturatedSignedWordToUnsignedByte(MMX(d).s[0]); |
| 2182 | | MMX(d).b[1]=SaturatedSignedWordToUnsignedByte(MMX(d).s[1]); |
| 2183 | | MMX(d).b[2]=SaturatedSignedWordToUnsignedByte(MMX(d).s[2]); |
| 2184 | | MMX(d).b[3]=SaturatedSignedWordToUnsignedByte(MMX(d).s[3]); |
| 2185 | | MMX(d).b[4]=SaturatedSignedWordToUnsignedByte(MMX(s).s[0]); |
| 2186 | | MMX(d).b[5]=SaturatedSignedWordToUnsignedByte(MMX(s).s[1]); |
| 2187 | | MMX(d).b[6]=SaturatedSignedWordToUnsignedByte(MMX(s).s[2]); |
| 2188 | | MMX(d).b[7]=SaturatedSignedWordToUnsignedByte(MMX(s).s[3]); |
| 2189 | | } else { |
| 2190 | | MMX_REG s; |
| 2191 | | int d=(modrm >> 3) & 0x7; |
| 2192 | | UINT32 ea = GetEA(modrm, 0); |
| 2193 | | READMMX(ea, s); |
| 2194 | | MMX(d).b[0]=SaturatedSignedWordToUnsignedByte(MMX(d).s[0]); |
| 2195 | | MMX(d).b[1]=SaturatedSignedWordToUnsignedByte(MMX(d).s[1]); |
| 2196 | | MMX(d).b[2]=SaturatedSignedWordToUnsignedByte(MMX(d).s[2]); |
| 2197 | | MMX(d).b[3]=SaturatedSignedWordToUnsignedByte(MMX(d).s[3]); |
| 2198 | | MMX(d).b[4]=SaturatedSignedWordToUnsignedByte(s.s[0]); |
| 2199 | | MMX(d).b[5]=SaturatedSignedWordToUnsignedByte(s.s[1]); |
| 2200 | | MMX(d).b[6]=SaturatedSignedWordToUnsignedByte(s.s[2]); |
| 2201 | | MMX(d).b[7]=SaturatedSignedWordToUnsignedByte(s.s[3]); |
| 2202 | | } |
| 2203 | | CYCLES(1); // TODO: correct cycle count |
| 2204 | | } |
| 2205 | | |
| 2206 | | void i386_device::mmx_punpckhbw_r64_rm64() // Opcode 0f 68 |
| 2207 | | { |
| 2208 | | MMXPROLOG(); |
| 2209 | | UINT8 modrm = FETCH(); |
| 2210 | | if( modrm >= 0xc0 ) { |
| 2211 | | int s,d; |
| 2212 | | s=modrm & 0x7; |
| 2213 | | d=(modrm >> 3) & 0x7; |
| 2214 | | MMX(d).b[0]=MMX(d).b[4]; |
| 2215 | | MMX(d).b[1]=MMX(s).b[4]; |
| 2216 | | MMX(d).b[2]=MMX(d).b[5]; |
| 2217 | | MMX(d).b[3]=MMX(s).b[5]; |
| 2218 | | MMX(d).b[4]=MMX(d).b[6]; |
| 2219 | | MMX(d).b[5]=MMX(s).b[6]; |
| 2220 | | MMX(d).b[6]=MMX(d).b[7]; |
| 2221 | | MMX(d).b[7]=MMX(s).b[7]; |
| 2222 | | } else { |
| 2223 | | MMX_REG s; |
| 2224 | | int d=(modrm >> 3) & 0x7; |
| 2225 | | UINT32 ea = GetEA(modrm, 0); |
| 2226 | | READMMX(ea, s); |
| 2227 | | MMX(d).b[0]=MMX(d).b[4]; |
| 2228 | | MMX(d).b[1]=s.b[4]; |
| 2229 | | MMX(d).b[2]=MMX(d).b[5]; |
| 2230 | | MMX(d).b[3]=s.b[5]; |
| 2231 | | MMX(d).b[4]=MMX(d).b[6]; |
| 2232 | | MMX(d).b[5]=s.b[6]; |
| 2233 | | MMX(d).b[6]=MMX(d).b[7]; |
| 2234 | | MMX(d).b[7]=s.b[7]; |
| 2235 | | } |
| 2236 | | CYCLES(1); // TODO: correct cycle count |
| 2237 | | } |
| 2238 | | |
| 2239 | | void i386_device::mmx_punpckhwd_r64_rm64() // Opcode 0f 69 |
| 2240 | | { |
| 2241 | | MMXPROLOG(); |
| 2242 | | UINT8 modrm = FETCH(); |
| 2243 | | if( modrm >= 0xc0 ) { |
| 2244 | | int s,d; |
| 2245 | | s=modrm & 0x7; |
| 2246 | | d=(modrm >> 3) & 0x7; |
| 2247 | | MMX(d).w[0]=MMX(d).w[2]; |
| 2248 | | MMX(d).w[1]=MMX(s).w[2]; |
| 2249 | | MMX(d).w[2]=MMX(d).w[3]; |
| 2250 | | MMX(d).w[3]=MMX(s).w[3]; |
| 2251 | | } else { |
| 2252 | | MMX_REG s; |
| 2253 | | int d=(modrm >> 3) & 0x7; |
| 2254 | | UINT32 ea = GetEA(modrm, 0); |
| 2255 | | READMMX(ea, s); |
| 2256 | | MMX(d).w[0]=MMX(d).w[2]; |
| 2257 | | MMX(d).w[1]=s.w[2]; |
| 2258 | | MMX(d).w[2]=MMX(d).w[3]; |
| 2259 | | MMX(d).w[3]=s.w[3]; |
| 2260 | | } |
| 2261 | | CYCLES(1); // TODO: correct cycle count |
| 2262 | | } |
| 2263 | | |
| 2264 | | void i386_device::mmx_punpckhdq_r64_rm64() // Opcode 0f 6a |
| 2265 | | { |
| 2266 | | MMXPROLOG(); |
| 2267 | | UINT8 modrm = FETCH(); |
| 2268 | | if( modrm >= 0xc0 ) { |
| 2269 | | int s,d; |
| 2270 | | s=modrm & 0x7; |
| 2271 | | d=(modrm >> 3) & 0x7; |
| 2272 | | MMX(d).d[0]=MMX(d).d[1]; |
| 2273 | | MMX(d).d[1]=MMX(s).d[1]; |
| 2274 | | } else { |
| 2275 | | MMX_REG s; |
| 2276 | | int d=(modrm >> 3) & 0x7; |
| 2277 | | UINT32 ea = GetEA(modrm, 0); |
| 2278 | | READMMX(ea, s); |
| 2279 | | MMX(d).d[0]=MMX(d).d[1]; |
| 2280 | | MMX(d).d[1]=s.d[1]; |
| 2281 | | } |
| 2282 | | CYCLES(1); // TODO: correct cycle count |
| 2283 | | } |
| 2284 | | |
| 2285 | | void i386_device::mmx_packssdw_r64_rm64() // Opcode 0f 6b |
| 2286 | | { |
| 2287 | | MMXPROLOG(); |
| 2288 | | UINT8 modrm = FETCH(); |
| 2289 | | if( modrm >= 0xc0 ) { |
| 2290 | | int s,d; |
| 2291 | | s=modrm & 0x7; |
| 2292 | | d=(modrm >> 3) & 0x7; |
| 2293 | | MMX(d).s[0]=SaturatedSignedDwordToSignedWord(MMX(d).i[0]); |
| 2294 | | MMX(d).s[1]=SaturatedSignedDwordToSignedWord(MMX(d).i[1]); |
| 2295 | | MMX(d).s[2]=SaturatedSignedDwordToSignedWord(MMX(s).i[0]); |
| 2296 | | MMX(d).s[3]=SaturatedSignedDwordToSignedWord(MMX(s).i[1]); |
| 2297 | | } else { |
| 2298 | | MMX_REG s; |
| 2299 | | int d=(modrm >> 3) & 0x7; |
| 2300 | | UINT32 ea = GetEA(modrm, 0); |
| 2301 | | READMMX(ea, s); |
| 2302 | | MMX(d).s[0]=SaturatedSignedDwordToSignedWord(MMX(d).i[0]); |
| 2303 | | MMX(d).s[1]=SaturatedSignedDwordToSignedWord(MMX(d).i[1]); |
| 2304 | | MMX(d).s[2]=SaturatedSignedDwordToSignedWord(s.i[0]); |
| 2305 | | MMX(d).s[3]=SaturatedSignedDwordToSignedWord(s.i[1]); |
| 2306 | | } |
| 2307 | | CYCLES(1); // TODO: correct cycle count |
| 2308 | | } |
| 2309 | | |
| 2310 | | void i386_device::sse_sse_group0fae() // Opcode 0f ae |
| 2311 | | { |
| 2312 | | UINT8 modm = FETCH(); |
| 2313 | | if( modm == 0xf8 ) { |
| 2314 | | logerror("Unemulated SFENCE opcode called\n"); |
| 2315 | | CYCLES(1); // sfence instruction |
| 2316 | | } else if( modm == 0xf0 ) { |
| 2317 | | CYCLES(1); // mfence instruction |
| 2318 | | } else if( modm == 0xe8 ) { |
| 2319 | | CYCLES(1); // lfence instruction |
| 2320 | | } else if( modm < 0xc0 ) { |
| 2321 | | UINT32 ea; |
| 2322 | | switch ( (modm & 0x38) >> 3 ) |
| 2323 | | { |
| 2324 | | case 2: // ldmxcsr m32 |
| 2325 | | ea = GetEA(modm, 0); |
| 2326 | | m_mxcsr = READ32(ea); |
| 2327 | | break; |
| 2328 | | case 3: // stmxcsr m32 |
| 2329 | | ea = GetEA(modm, 0); |
| 2330 | | WRITE32(ea, m_mxcsr); |
| 2331 | | break; |
| 2332 | | case 7: // clflush m8 |
| 2333 | | GetNonTranslatedEA(modm, NULL); |
| 2334 | | break; |
| 2335 | | default: |
| 2336 | | report_invalid_modrm("sse_group0fae", modm); |
| 2337 | | } |
| 2338 | | } else { |
| 2339 | | report_invalid_modrm("sse_group0fae", modm); |
| 2340 | | } |
| 2341 | | } |
| 2342 | | |
| 2343 | | void i386_device::sse_cvttps2dq_r128_rm128() // Opcode f3 0f 5b |
| 2344 | | { |
| 2345 | | UINT8 modrm = FETCH(); |
| 2346 | | if( modrm >= 0xc0 ) { |
| 2347 | | XMM((modrm >> 3) & 0x7).i[0]=(INT32)XMM(modrm & 0x7).f[0]; |
| 2348 | | XMM((modrm >> 3) & 0x7).i[1]=(INT32)XMM(modrm & 0x7).f[1]; |
| 2349 | | XMM((modrm >> 3) & 0x7).i[2]=(INT32)XMM(modrm & 0x7).f[2]; |
| 2350 | | XMM((modrm >> 3) & 0x7).i[3]=(INT32)XMM(modrm & 0x7).f[3]; |
| 2351 | | } else { |
| 2352 | | XMM_REG src; |
| 2353 | | UINT32 ea = GetEA(modrm, 0); |
| 2354 | | READXMM(ea, src); |
| 2355 | | XMM((modrm >> 3) & 0x7).i[0]=(INT32)src.f[0]; |
| 2356 | | XMM((modrm >> 3) & 0x7).i[1]=(INT32)src.f[1]; |
| 2357 | | XMM((modrm >> 3) & 0x7).i[2]=(INT32)src.f[2]; |
| 2358 | | XMM((modrm >> 3) & 0x7).i[3]=(INT32)src.f[3]; |
| 2359 | | } |
| 2360 | | CYCLES(1); // TODO: correct cycle count |
| 2361 | | } |
| 2362 | | |
| 2363 | | void i386_device::sse_cvtss2sd_r128_r128m32() // Opcode f3 0f 5a |
| 2364 | | { |
| 2365 | | UINT8 modrm = FETCH(); |
| 2366 | | if( modrm >= 0xc0 ) { |
| 2367 | | XMM((modrm >> 3) & 0x7).f64[0] = XMM(modrm & 0x7).f[0]; |
| 2368 | | } else { |
| 2369 | | XMM_REG s; |
| 2370 | | UINT32 ea = GetEA(modrm, 0); |
| 2371 | | s.d[0] = READ32(ea); |
| 2372 | | XMM((modrm >> 3) & 0x7).f64[0] = s.f[0]; |
| 2373 | | } |
| 2374 | | CYCLES(1); // TODO: correct cycle count |
| 2375 | | } |
| 2376 | | |
| 2377 | | void i386_device::sse_cvttss2si_r32_r128m32() // Opcode f3 0f 2c |
| 2378 | | { |
| 2379 | | INT32 src; |
| 2380 | | UINT8 modrm = FETCH(); // get mordm byte |
| 2381 | | if( modrm >= 0xc0 ) { // if bits 7-6 are 11 the source is a xmm register (low doubleword) |
| 2382 | | src = (INT32)XMM(modrm & 0x7).f[0^NATIVE_ENDIAN_VALUE_LE_BE(0,1)]; |
| 2383 | | } else { // otherwise is a memory address |
| 2384 | | XMM_REG t; |
| 2385 | | UINT32 ea = GetEA(modrm, 0); |
| 2386 | | t.d[0] = READ32(ea); |
| 2387 | | src = (INT32)t.f[0]; |
| 2388 | | } |
| 2389 | | STORE_REG32(modrm, (UINT32)src); |
| 2390 | | CYCLES(1); // TODO: correct cycle count |
| 2391 | | } |
| 2392 | | |
| 2393 | | void i386_device::sse_cvtss2si_r32_r128m32() // Opcode f3 0f 2d |
| 2394 | | { |
| 2395 | | INT32 src; |
| 2396 | | UINT8 modrm = FETCH(); |
| 2397 | | if( modrm >= 0xc0 ) { |
| 2398 | | src = (INT32)XMM(modrm & 0x7).f[0]; |
| 2399 | | } else { |
| 2400 | | XMM_REG t; |
| 2401 | | UINT32 ea = GetEA(modrm, 0); |
| 2402 | | t.d[0] = READ32(ea); |
| 2403 | | src = (INT32)t.f[0]; |
| 2404 | | } |
| 2405 | | STORE_REG32(modrm, (UINT32)src); |
| 2406 | | CYCLES(1); // TODO: correct cycle count |
| 2407 | | } |
| 2408 | | |
| 2409 | | void i386_device::sse_cvtsi2ss_r128_rm32() // Opcode f3 0f 2a |
| 2410 | | { |
| 2411 | | UINT8 modrm = FETCH(); |
| 2412 | | if( modrm >= 0xc0 ) { |
| 2413 | | XMM((modrm >> 3) & 0x7).f[0] = (INT32)LOAD_RM32(modrm); |
| 2414 | | } else { |
| 2415 | | UINT32 ea = GetEA(modrm, 0); |
| 2416 | | XMM((modrm >> 3) & 0x7).f[0] = (INT32)READ32(ea); |
| 2417 | | } |
| 2418 | | CYCLES(1); // TODO: correct cycle count |
| 2419 | | } |
| 2420 | | |
| 2421 | | void i386_device::sse_cvtpi2ps_r128_rm64() // Opcode 0f 2a |
| 2422 | | { |
| 2423 | | UINT8 modrm = FETCH(); |
| 2424 | | MMXPROLOG(); |
| 2425 | | if( modrm >= 0xc0 ) { |
| 2426 | | XMM((modrm >> 3) & 0x7).f[0] = MMX(modrm & 0x7).i[0]; |
| 2427 | | XMM((modrm >> 3) & 0x7).f[1] = MMX(modrm & 0x7).i[1]; |
| 2428 | | } else { |
| 2429 | | MMX_REG r; |
| 2430 | | UINT32 ea = GetEA(modrm, 0); |
| 2431 | | READMMX(ea, r); |
| 2432 | | XMM((modrm >> 3) & 0x7).f[0] = r.i[0]; |
| 2433 | | XMM((modrm >> 3) & 0x7).f[1] = r.i[1]; |
| 2434 | | } |
| 2435 | | CYCLES(1); // TODO: correct cycle count |
| 2436 | | } |
| 2437 | | |
| 2438 | | void i386_device::sse_cvttps2pi_r64_r128m64() // Opcode 0f 2c |
| 2439 | | { |
| 2440 | | UINT8 modrm = FETCH(); |
| 2441 | | MMXPROLOG(); |
| 2442 | | if( modrm >= 0xc0 ) { |
| 2443 | | MMX((modrm >> 3) & 0x7).i[0] = XMM(modrm & 0x7).f[0]; |
| 2444 | | MMX((modrm >> 3) & 0x7).i[1] = XMM(modrm & 0x7).f[1]; |
| 2445 | | } else { |
| 2446 | | XMM_REG r; |
| 2447 | | UINT32 ea = GetEA(modrm, 0); |
| 2448 | | READXMM(ea, r); |
| 2449 | | XMM((modrm >> 3) & 0x7).i[0] = r.f[0]; |
| 2450 | | XMM((modrm >> 3) & 0x7).i[1] = r.f[1]; |
| 2451 | | } |
| 2452 | | CYCLES(1); // TODO: correct cycle count |
| 2453 | | } |
| 2454 | | |
| 2455 | | void i386_device::sse_cvtps2pi_r64_r128m64() // Opcode 0f 2d |
| 2456 | | { |
| 2457 | | UINT8 modrm = FETCH(); |
| 2458 | | MMXPROLOG(); |
| 2459 | | if( modrm >= 0xc0 ) { |
| 2460 | | MMX((modrm >> 3) & 0x7).i[0] = XMM(modrm & 0x7).f[0]; |
| 2461 | | MMX((modrm >> 3) & 0x7).i[1] = XMM(modrm & 0x7).f[1]; |
| 2462 | | } else { |
| 2463 | | XMM_REG r; |
| 2464 | | UINT32 ea = GetEA(modrm, 0); |
| 2465 | | READXMM(ea, r); |
| 2466 | | XMM((modrm >> 3) & 0x7).i[0] = r.f[0]; |
| 2467 | | XMM((modrm >> 3) & 0x7).i[1] = r.f[1]; |
| 2468 | | } |
| 2469 | | CYCLES(1); // TODO: correct cycle count |
| 2470 | | } |
| 2471 | | |
| 2472 | | void i386_device::sse_cvtps2pd_r128_r128m64() // Opcode 0f 5a |
| 2473 | | { |
| 2474 | | UINT8 modrm = FETCH(); |
| 2475 | | if( modrm >= 0xc0 ) { |
| 2476 | | XMM((modrm >> 3) & 0x7).f64[0] = (double)XMM(modrm & 0x7).f[0]; |
| 2477 | | XMM((modrm >> 3) & 0x7).f64[1] = (double)XMM(modrm & 0x7).f[1]; |
| 2478 | | } else { |
| 2479 | | MMX_REG r; |
| 2480 | | UINT32 ea = GetEA(modrm, 0); |
| 2481 | | READMMX(ea, r); |
| 2482 | | XMM((modrm >> 3) & 0x7).f64[0] = (double)r.f[0]; |
| 2483 | | XMM((modrm >> 3) & 0x7).f64[1] = (double)r.f[1]; |
| 2484 | | } |
| 2485 | | CYCLES(1); // TODO: correct cycle count |
| 2486 | | } |
| 2487 | | |
| 2488 | | void i386_device::sse_cvtdq2ps_r128_rm128() // Opcode 0f 5b |
| 2489 | | { |
| 2490 | | UINT8 modrm = FETCH(); |
| 2491 | | if( modrm >= 0xc0 ) { |
| 2492 | | XMM((modrm >> 3) & 0x7).f[0] = (float)XMM(modrm & 0x7).i[0]; |
| 2493 | | XMM((modrm >> 3) & 0x7).f[1] = (float)XMM(modrm & 0x7).i[1]; |
| 2494 | | XMM((modrm >> 3) & 0x7).f[2] = (float)XMM(modrm & 0x7).i[2]; |
| 2495 | | XMM((modrm >> 3) & 0x7).f[3] = (float)XMM(modrm & 0x7).i[3]; |
| 2496 | | } else { |
| 2497 | | XMM_REG r; |
| 2498 | | UINT32 ea = GetEA(modrm, 0); |
| 2499 | | READXMM(ea, r); |
| 2500 | | XMM((modrm >> 3) & 0x7).f[0] = (float)r.i[0]; |
| 2501 | | XMM((modrm >> 3) & 0x7).f[1] = (float)r.i[1]; |
| 2502 | | XMM((modrm >> 3) & 0x7).f[2] = (float)r.i[2]; |
| 2503 | | XMM((modrm >> 3) & 0x7).f[3] = (float)r.i[3]; |
| 2504 | | } |
| 2505 | | CYCLES(1); // TODO: correct cycle count |
| 2506 | | } |
| 2507 | | |
| 2508 | | void i386_device::sse_cvtdq2pd_r128_r128m64() // Opcode f3 0f e6 |
| 2509 | | { |
| 2510 | | UINT8 modrm = FETCH(); |
| 2511 | | if( modrm >= 0xc0 ) { |
| 2512 | | XMM((modrm >> 3) & 0x7).f64[0] = (double)XMM(modrm & 0x7).i[0]; |
| 2513 | | XMM((modrm >> 3) & 0x7).f64[1] = (double)XMM(modrm & 0x7).i[1]; |
| 2514 | | } else { |
| 2515 | | MMX_REG s; |
| 2516 | | UINT32 ea = GetEA(modrm, 0); |
| 2517 | | READMMX(ea, s); |
| 2518 | | XMM((modrm >> 3) & 0x7).f64[0] = (double)s.i[0]; |
| 2519 | | XMM((modrm >> 3) & 0x7).f64[1] = (double)s.i[1]; |
| 2520 | | } |
| 2521 | | CYCLES(1); // TODO: correct cycle count |
| 2522 | | } |
| 2523 | | |
| 2524 | | void i386_device::sse_movss_r128_rm128() // Opcode f3 0f 10 |
| 2525 | | { |
| 2526 | | UINT8 modrm = FETCH(); |
| 2527 | | if( modrm >= 0xc0 ) { |
| 2528 | | XMM((modrm >> 3) & 0x7).d[0] = XMM(modrm & 0x7).d[0]; |
| 2529 | | } else { |
| 2530 | | UINT32 ea = GetEA(modrm, 0); |
| 2531 | | XMM((modrm >> 3) & 0x7).d[0] = READ32(ea); |
| 2532 | | } |
| 2533 | | CYCLES(1); // TODO: correct cycle count |
| 2534 | | } |
| 2535 | | |
| 2536 | | void i386_device::sse_movss_rm128_r128() // Opcode f3 0f 11 |
| 2537 | | { |
| 2538 | | UINT8 modrm = FETCH(); |
| 2539 | | if( modrm >= 0xc0 ) { |
| 2540 | | XMM(modrm & 0x7).d[0] = XMM((modrm >> 3) & 0x7).d[0]; |
| 2541 | | } else { |
| 2542 | | UINT32 ea = GetEA(modrm, 0); |
| 2543 | | WRITE32(ea, XMM((modrm >> 3) & 0x7).d[0]); |
| 2544 | | } |
| 2545 | | CYCLES(1); // TODO: correct cycle count |
| 2546 | | } |
| 2547 | | |
| 2548 | | void i386_device::sse_movsldup_r128_rm128() // Opcode f3 0f 12 |
| 2549 | | { |
| 2550 | | UINT8 modrm = FETCH(); |
| 2551 | | if( modrm >= 0xc0 ) { |
| 2552 | | XMM((modrm >> 3) & 0x7).d[0] = XMM(modrm & 0x7).d[0]; |
| 2553 | | XMM((modrm >> 3) & 0x7).d[1] = XMM(modrm & 0x7).d[0]; |
| 2554 | | XMM((modrm >> 3) & 0x7).d[2] = XMM(modrm & 0x7).d[2]; |
| 2555 | | XMM((modrm >> 3) & 0x7).d[3] = XMM(modrm & 0x7).d[2]; |
| 2556 | | } else { |
| 2557 | | XMM_REG src; |
| 2558 | | UINT32 ea = GetEA(modrm, 0); |
| 2559 | | READXMM(ea, src); |
| 2560 | | XMM((modrm >> 3) & 0x7).d[0] = src.d[0]; |
| 2561 | | XMM((modrm >> 3) & 0x7).d[1] = src.d[0]; |
| 2562 | | XMM((modrm >> 3) & 0x7).d[2] = src.d[2]; |
| 2563 | | XMM((modrm >> 3) & 0x7).d[3] = src.d[2]; |
| 2564 | | } |
| 2565 | | CYCLES(1); // TODO: correct cycle count |
| 2566 | | } |
| 2567 | | |
| 2568 | | void i386_device::sse_movshdup_r128_rm128() // Opcode f3 0f 16 |
| 2569 | | { |
| 2570 | | UINT8 modrm = FETCH(); |
| 2571 | | if( modrm >= 0xc0 ) { |
| 2572 | | XMM((modrm >> 3) & 0x7).d[0] = XMM(modrm & 0x7).d[1]; |
| 2573 | | XMM((modrm >> 3) & 0x7).d[1] = XMM(modrm & 0x7).d[1]; |
| 2574 | | XMM((modrm >> 3) & 0x7).d[2] = XMM(modrm & 0x7).d[3]; |
| 2575 | | XMM((modrm >> 3) & 0x7).d[3] = XMM(modrm & 0x7).d[3]; |
| 2576 | | } else { |
| 2577 | | XMM_REG src; |
| 2578 | | UINT32 ea = GetEA(modrm, 0); |
| 2579 | | READXMM(ea, src); |
| 2580 | | XMM((modrm >> 3) & 0x7).d[0] = src.d[1]; |
| 2581 | | XMM((modrm >> 3) & 0x7).d[1] = src.d[1]; |
| 2582 | | XMM((modrm >> 3) & 0x7).d[2] = src.d[3]; |
| 2583 | | XMM((modrm >> 3) & 0x7).d[3] = src.d[3]; |
| 2584 | | } |
| 2585 | | CYCLES(1); // TODO: correct cycle count |
| 2586 | | } |
| 2587 | | |
| 2588 | | void i386_device::sse_movaps_r128_rm128() // Opcode 0f 28 |
| 2589 | | { |
| 2590 | | UINT8 modrm = FETCH(); |
| 2591 | | if( modrm >= 0xc0 ) { |
| 2592 | | XMM((modrm >> 3) & 0x7) = XMM(modrm & 0x7); |
| 2593 | | } else { |
| 2594 | | UINT32 ea = GetEA(modrm, 0); |
| 2595 | | READXMM(ea, XMM((modrm >> 3) & 0x7)); |
| 2596 | | } |
| 2597 | | CYCLES(1); // TODO: correct cycle count |
| 2598 | | } |
| 2599 | | |
| 2600 | | void i386_device::sse_movaps_rm128_r128() // Opcode 0f 29 |
| 2601 | | { |
| 2602 | | UINT8 modrm = FETCH(); |
| 2603 | | if( modrm >= 0xc0 ) { |
| 2604 | | XMM(modrm & 0x7) = XMM((modrm >> 3) & 0x7); |
| 2605 | | } else { |
| 2606 | | UINT32 ea = GetEA(modrm, 0); |
| 2607 | | WRITEXMM(ea, XMM((modrm >> 3) & 0x7)); |
| 2608 | | } |
| 2609 | | CYCLES(1); // TODO: correct cycle count |
| 2610 | | } |
| 2611 | | |
| 2612 | | void i386_device::sse_movups_r128_rm128() // Opcode 0f 10 |
| 2613 | | { |
| 2614 | | UINT8 modrm = FETCH(); |
| 2615 | | if( modrm >= 0xc0 ) { |
| 2616 | | XMM((modrm >> 3) & 0x7) = XMM(modrm & 0x7); |
| 2617 | | } else { |
| 2618 | | UINT32 ea = GetEA(modrm, 0); |
| 2619 | | READXMM(ea, XMM((modrm >> 3) & 0x7)); // address does not need to be 16-byte aligned |
| 2620 | | } |
| 2621 | | CYCLES(1); // TODO: correct cycle count |
| 2622 | | } |
| 2623 | | |
| 2624 | | void i386_device::sse_movups_rm128_r128() // Opcode 0f 11 |
| 2625 | | { |
| 2626 | | UINT8 modrm = FETCH(); |
| 2627 | | if( modrm >= 0xc0 ) { |
| 2628 | | XMM(modrm & 0x7) = XMM((modrm >> 3) & 0x7); |
| 2629 | | } else { |
| 2630 | | UINT32 ea = GetEA(modrm, 0); |
| 2631 | | WRITEXMM(ea, XMM((modrm >> 3) & 0x7)); // address does not need to be 16-byte aligned |
| 2632 | | } |
| 2633 | | CYCLES(1); // TODO: correct cycle count |
| 2634 | | } |
| 2635 | | |
| 2636 | | void i386_device::sse_movlps_r128_m64() // Opcode 0f 12 |
| 2637 | | { |
| 2638 | | UINT8 modrm = FETCH(); |
| 2639 | | if( modrm >= 0xc0 ) { |
| 2640 | | // unsupported by cpu |
| 2641 | | CYCLES(1); // TODO: correct cycle count |
| 2642 | | } else { |
| 2643 | | UINT32 ea = GetEA(modrm, 0); |
| 2644 | | READXMM_LO64(ea, XMM((modrm >> 3) & 0x7)); |
| 2645 | | CYCLES(1); // TODO: correct cycle count |
| 2646 | | } |
| 2647 | | } |
| 2648 | | |
| 2649 | | void i386_device::sse_movlps_m64_r128() // Opcode 0f 13 |
| 2650 | | { |
| 2651 | | UINT8 modrm = FETCH(); |
| 2652 | | if( modrm >= 0xc0 ) { |
| 2653 | | // unsupported by cpu |
| 2654 | | CYCLES(1); // TODO: correct cycle count |
| 2655 | | } else { |
| 2656 | | UINT32 ea = GetEA(modrm, 0); |
| 2657 | | WRITEXMM_LO64(ea, XMM((modrm >> 3) & 0x7)); |
| 2658 | | CYCLES(1); // TODO: correct cycle count |
| 2659 | | } |
| 2660 | | } |
| 2661 | | |
| 2662 | | void i386_device::sse_movhps_r128_m64() // Opcode 0f 16 |
| 2663 | | { |
| 2664 | | UINT8 modrm = FETCH(); |
| 2665 | | if( modrm >= 0xc0 ) { |
| 2666 | | // unsupported by cpu |
| 2667 | | CYCLES(1); // TODO: correct cycle count |
| 2668 | | } else { |
| 2669 | | UINT32 ea = GetEA(modrm, 0); |
| 2670 | | READXMM_HI64(ea, XMM((modrm >> 3) & 0x7)); |
| 2671 | | CYCLES(1); // TODO: correct cycle count |
| 2672 | | } |
| 2673 | | } |
| 2674 | | |
| 2675 | | void i386_device::sse_movhps_m64_r128() // Opcode 0f 17 |
| 2676 | | { |
| 2677 | | UINT8 modrm = FETCH(); |
| 2678 | | if( modrm >= 0xc0 ) { |
| 2679 | | // unsupported by cpu |
| 2680 | | CYCLES(1); // TODO: correct cycle count |
| 2681 | | } else { |
| 2682 | | UINT32 ea = GetEA(modrm, 0); |
| 2683 | | WRITEXMM_HI64(ea, XMM((modrm >> 3) & 0x7)); |
| 2684 | | CYCLES(1); // TODO: correct cycle count |
| 2685 | | } |
| 2686 | | } |
| 2687 | | |
| 2688 | | void i386_device::sse_movntps_m128_r128() // Opcode 0f 2b |
| 2689 | | { |
| 2690 | | UINT8 modrm = FETCH(); |
| 2691 | | if( modrm >= 0xc0 ) { |
| 2692 | | // unsupported by cpu |
| 2693 | | CYCLES(1); // TODO: correct cycle count |
| 2694 | | } else { |
| 2695 | | // since cache is not implemented |
| 2696 | | UINT32 ea = GetEA(modrm, 0); |
| 2697 | | WRITEXMM(ea, XMM((modrm >> 3) & 0x7)); |
| 2698 | | CYCLES(1); // TODO: correct cycle count |
| 2699 | | } |
| 2700 | | } |
| 2701 | | |
| 2702 | | void i386_device::sse_movmskps_r16_r128() // Opcode 0f 50 |
| 2703 | | { |
| 2704 | | UINT8 modrm = FETCH(); |
| 2705 | | if( modrm >= 0xc0 ) { |
| 2706 | | int b; |
| 2707 | | b=(XMM(modrm & 0x7).d[0] >> 31) & 1; |
| 2708 | | b=b | ((XMM(modrm & 0x7).d[1] >> 30) & 2); |
| 2709 | | b=b | ((XMM(modrm & 0x7).d[2] >> 29) & 4); |
| 2710 | | b=b | ((XMM(modrm & 0x7).d[3] >> 28) & 8); |
| 2711 | | STORE_REG16(modrm, b); |
| 2712 | | } |
| 2713 | | CYCLES(1); // TODO: correct cycle count |
| 2714 | | } |
| 2715 | | |
| 2716 | | void i386_device::sse_movmskps_r32_r128() // Opcode 0f 50 |
| 2717 | | { |
| 2718 | | UINT8 modrm = FETCH(); |
| 2719 | | if( modrm >= 0xc0 ) { |
| 2720 | | int b; |
| 2721 | | b=(XMM(modrm & 0x7).d[0] >> 31) & 1; |
| 2722 | | b=b | ((XMM(modrm & 0x7).d[1] >> 30) & 2); |
| 2723 | | b=b | ((XMM(modrm & 0x7).d[2] >> 29) & 4); |
| 2724 | | b=b | ((XMM(modrm & 0x7).d[3] >> 28) & 8); |
| 2725 | | STORE_REG32(modrm, b); |
| 2726 | | } |
| 2727 | | CYCLES(1); // TODO: correct cycle count |
| 2728 | | } |
| 2729 | | |
| 2730 | | void i386_device::sse_movq2dq_r128_r64() // Opcode f3 0f d6 |
| 2731 | | { |
| 2732 | | MMXPROLOG(); |
| 2733 | | UINT8 modrm = FETCH(); |
| 2734 | | if( modrm >= 0xc0 ) { |
| 2735 | | XMM((modrm >> 3) & 0x7).q[0] = MMX(modrm & 7).q; |
| 2736 | | XMM((modrm >> 3) & 0x7).q[1] = 0; |
| 2737 | | } |
| 2738 | | CYCLES(1); // TODO: correct cycle count |
| 2739 | | } |
| 2740 | | |
| 2741 | | void i386_device::sse_movdqu_r128_rm128() // Opcode f3 0f 6f |
| 2742 | | { |
| 2743 | | MMXPROLOG(); |
| 2744 | | UINT8 modrm = FETCH(); |
| 2745 | | if( modrm >= 0xc0 ) { |
| 2746 | | XMM((modrm >> 3) & 0x7).q[0] = XMM(modrm & 0x7).q[0]; |
| 2747 | | XMM((modrm >> 3) & 0x7).q[1] = XMM(modrm & 0x7).q[1]; |
| 2748 | | } else { |
| 2749 | | UINT32 ea = GetEA(modrm, 0); |
| 2750 | | READXMM(ea, XMM((modrm >> 3) & 0x7)); |
| 2751 | | } |
| 2752 | | CYCLES(1); // TODO: correct cycle count |
| 2753 | | } |
| 2754 | | |
| 2755 | | void i386_device::sse_movdqu_rm128_r128() // Opcode f3 0f 7f |
| 2756 | | { |
| 2757 | | MMXPROLOG(); |
| 2758 | | UINT8 modrm = FETCH(); |
| 2759 | | if( modrm >= 0xc0 ) { |
| 2760 | | XMM(modrm & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0]; |
| 2761 | | XMM(modrm & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1]; |
| 2762 | | } else { |
| 2763 | | UINT32 ea = GetEA(modrm, 0); |
| 2764 | | WRITEXMM(ea, XMM((modrm >> 3) & 0x7)); |
| 2765 | | } |
| 2766 | | CYCLES(1); // TODO: correct cycle count |
| 2767 | | } |
| 2768 | | |
| 2769 | | void i386_device::sse_movq_r128_r128m64() // Opcode f3 0f 7e |
| 2770 | | { |
| 2771 | | MMXPROLOG(); |
| 2772 | | UINT8 modrm = FETCH(); |
| 2773 | | if( modrm >= 0xc0 ) { |
| 2774 | | XMM((modrm >> 3) & 0x7).q[0] = XMM(modrm & 0x7).q[0]; |
| 2775 | | XMM((modrm >> 3) & 0x7).q[1] = 0; |
| 2776 | | } else { |
| 2777 | | UINT32 ea = GetEA(modrm, 0); |
| 2778 | | XMM((modrm >> 3) & 0x7).q[0] = READ64(ea); |
| 2779 | | XMM((modrm >> 3) & 0x7).q[1] = 0; |
| 2780 | | } |
| 2781 | | CYCLES(1); // TODO: correct cycle count |
| 2782 | | } |
| 2783 | | |
| 2784 | | void i386_device::sse_pmovmskb_r16_r64() // Opcode 0f d7 |
| 2785 | | { |
| 2786 | | //MMXPROLOG(); |
| 2787 | | UINT8 modrm = FETCH(); |
| 2788 | | if( modrm >= 0xc0 ) { |
| 2789 | | int b; |
| 2790 | | b=(MMX(modrm & 0x7).b[0] >> 7) & 1; |
| 2791 | | b=b | ((MMX(modrm & 0x7).b[1] >> 6) & 2); |
| 2792 | | b=b | ((MMX(modrm & 0x7).b[2] >> 5) & 4); |
| 2793 | | b=b | ((MMX(modrm & 0x7).b[3] >> 4) & 8); |
| 2794 | | b=b | ((MMX(modrm & 0x7).b[4] >> 3) & 16); |
| 2795 | | b=b | ((MMX(modrm & 0x7).b[5] >> 2) & 32); |
| 2796 | | b=b | ((MMX(modrm & 0x7).b[6] >> 1) & 64); |
| 2797 | | b=b | ((MMX(modrm & 0x7).b[7] >> 0) & 128); |
| 2798 | | STORE_REG16(modrm, b); |
| 2799 | | } |
| 2800 | | CYCLES(1); // TODO: correct cycle count |
| 2801 | | } |
| 2802 | | |
| 2803 | | void i386_device::sse_pmovmskb_r32_r64() // Opcode 0f d7 |
| 2804 | | { |
| 2805 | | //MMXPROLOG(); |
| 2806 | | UINT8 modrm = FETCH(); |
| 2807 | | if( modrm >= 0xc0 ) { |
| 2808 | | int b; |
| 2809 | | b=(MMX(modrm & 0x7).b[0] >> 7) & 1; |
| 2810 | | b=b | ((MMX(modrm & 0x7).b[1] >> 6) & 2); |
| 2811 | | b=b | ((MMX(modrm & 0x7).b[2] >> 5) & 4); |
| 2812 | | b=b | ((MMX(modrm & 0x7).b[3] >> 4) & 8); |
| 2813 | | b=b | ((MMX(modrm & 0x7).b[4] >> 3) & 16); |
| 2814 | | b=b | ((MMX(modrm & 0x7).b[5] >> 2) & 32); |
| 2815 | | b=b | ((MMX(modrm & 0x7).b[6] >> 1) & 64); |
| 2816 | | b=b | ((MMX(modrm & 0x7).b[7] >> 0) & 128); |
| 2817 | | STORE_REG32(modrm, b); |
| 2818 | | } |
| 2819 | | CYCLES(1); // TODO: correct cycle count |
| 2820 | | } |
| 2821 | | |
| 2822 | | void i386_device::sse_xorps() // Opcode 0f 57 |
| 2823 | | { |
| 2824 | | UINT8 modrm = FETCH(); |
| 2825 | | if( modrm >= 0xc0 ) { |
| 2826 | | XMM((modrm >> 3) & 0x7).d[0] = XMM((modrm >> 3) & 0x7).d[0] ^ XMM(modrm & 0x7).d[0]; |
| 2827 | | XMM((modrm >> 3) & 0x7).d[1] = XMM((modrm >> 3) & 0x7).d[1] ^ XMM(modrm & 0x7).d[1]; |
| 2828 | | XMM((modrm >> 3) & 0x7).d[2] = XMM((modrm >> 3) & 0x7).d[2] ^ XMM(modrm & 0x7).d[2]; |
| 2829 | | XMM((modrm >> 3) & 0x7).d[3] = XMM((modrm >> 3) & 0x7).d[3] ^ XMM(modrm & 0x7).d[3]; |
| 2830 | | } else { |
| 2831 | | XMM_REG src; |
| 2832 | | UINT32 ea = GetEA(modrm, 0); |
| 2833 | | READXMM(ea, src); |
| 2834 | | XMM((modrm >> 3) & 0x7).d[0] = XMM((modrm >> 3) & 0x7).d[0] ^ src.d[0]; |
| 2835 | | XMM((modrm >> 3) & 0x7).d[1] = XMM((modrm >> 3) & 0x7).d[1] ^ src.d[1]; |
| 2836 | | XMM((modrm >> 3) & 0x7).d[2] = XMM((modrm >> 3) & 0x7).d[2] ^ src.d[2]; |
| 2837 | | XMM((modrm >> 3) & 0x7).d[3] = XMM((modrm >> 3) & 0x7).d[3] ^ src.d[3]; |
| 2838 | | } |
| 2839 | | CYCLES(1); // TODO: correct cycle count |
| 2840 | | } |
| 2841 | | |
| 2842 | | void i386_device::sse_addps() // Opcode 0f 58 |
| 2843 | | { |
| 2844 | | UINT8 modrm = FETCH(); |
| 2845 | | if( modrm >= 0xc0 ) { |
| 2846 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + XMM(modrm & 0x7).f[0]; |
| 2847 | | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] + XMM(modrm & 0x7).f[1]; |
| 2848 | | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] + XMM(modrm & 0x7).f[2]; |
| 2849 | | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] + XMM(modrm & 0x7).f[3]; |
| 2850 | | } else { |
| 2851 | | XMM_REG src; |
| 2852 | | UINT32 ea = GetEA(modrm, 0); |
| 2853 | | READXMM(ea, src); |
| 2854 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + src.f[0]; |
| 2855 | | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] + src.f[1]; |
| 2856 | | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] + src.f[2]; |
| 2857 | | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] + src.f[3]; |
| 2858 | | } |
| 2859 | | CYCLES(1); // TODO: correct cycle count |
| 2860 | | } |
| 2861 | | |
| 2862 | | void i386_device::sse_sqrtps_r128_rm128() // Opcode 0f 51 |
| 2863 | | { |
| 2864 | | UINT8 modrm = FETCH(); |
| 2865 | | if( modrm >= 0xc0 ) { |
| 2866 | | XMM((modrm >> 3) & 0x7).f[0] = sqrt(XMM(modrm & 0x7).f[0]); |
| 2867 | | XMM((modrm >> 3) & 0x7).f[1] = sqrt(XMM(modrm & 0x7).f[1]); |
| 2868 | | XMM((modrm >> 3) & 0x7).f[2] = sqrt(XMM(modrm & 0x7).f[2]); |
| 2869 | | XMM((modrm >> 3) & 0x7).f[3] = sqrt(XMM(modrm & 0x7).f[3]); |
| 2870 | | } else { |
| 2871 | | XMM_REG src; |
| 2872 | | UINT32 ea = GetEA(modrm, 0); |
| 2873 | | READXMM(ea, src); |
| 2874 | | XMM((modrm >> 3) & 0x7).f[0] = sqrt(src.f[0]); |
| 2875 | | XMM((modrm >> 3) & 0x7).f[1] = sqrt(src.f[1]); |
| 2876 | | XMM((modrm >> 3) & 0x7).f[2] = sqrt(src.f[2]); |
| 2877 | | XMM((modrm >> 3) & 0x7).f[3] = sqrt(src.f[3]); |
| 2878 | | } |
| 2879 | | CYCLES(1); // TODO: correct cycle count |
| 2880 | | } |
| 2881 | | |
| 2882 | | void i386_device::sse_rsqrtps_r128_rm128() // Opcode 0f 52 |
| 2883 | | { |
| 2884 | | UINT8 modrm = FETCH(); |
| 2885 | | if( modrm >= 0xc0 ) { |
| 2886 | | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / sqrt(XMM(modrm & 0x7).f[0]); |
| 2887 | | XMM((modrm >> 3) & 0x7).f[1] = 1.0 / sqrt(XMM(modrm & 0x7).f[1]); |
| 2888 | | XMM((modrm >> 3) & 0x7).f[2] = 1.0 / sqrt(XMM(modrm & 0x7).f[2]); |
| 2889 | | XMM((modrm >> 3) & 0x7).f[3] = 1.0 / sqrt(XMM(modrm & 0x7).f[3]); |
| 2890 | | } else { |
| 2891 | | XMM_REG src; |
| 2892 | | UINT32 ea = GetEA(modrm, 0); |
| 2893 | | READXMM(ea, src); |
| 2894 | | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / sqrt(src.f[0]); |
| 2895 | | XMM((modrm >> 3) & 0x7).f[1] = 1.0 / sqrt(src.f[1]); |
| 2896 | | XMM((modrm >> 3) & 0x7).f[2] = 1.0 / sqrt(src.f[2]); |
| 2897 | | XMM((modrm >> 3) & 0x7).f[3] = 1.0 / sqrt(src.f[3]); |
| 2898 | | } |
| 2899 | | CYCLES(1); // TODO: correct cycle count |
| 2900 | | } |
| 2901 | | |
| 2902 | | void i386_device::sse_rcpps_r128_rm128() // Opcode 0f 53 |
| 2903 | | { |
| 2904 | | UINT8 modrm = FETCH(); |
| 2905 | | if( modrm >= 0xc0 ) { |
| 2906 | | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / XMM(modrm & 0x7).f[0]; |
| 2907 | | XMM((modrm >> 3) & 0x7).f[1] = 1.0 / XMM(modrm & 0x7).f[1]; |
| 2908 | | XMM((modrm >> 3) & 0x7).f[2] = 1.0 / XMM(modrm & 0x7).f[2]; |
| 2909 | | XMM((modrm >> 3) & 0x7).f[3] = 1.0 / XMM(modrm & 0x7).f[3]; |
| 2910 | | } else { |
| 2911 | | XMM_REG src; |
| 2912 | | UINT32 ea = GetEA(modrm, 0); |
| 2913 | | READXMM(ea, src); |
| 2914 | | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / src.f[0]; |
| 2915 | | XMM((modrm >> 3) & 0x7).f[1] = 1.0 / src.f[1]; |
| 2916 | | XMM((modrm >> 3) & 0x7).f[2] = 1.0 / src.f[2]; |
| 2917 | | XMM((modrm >> 3) & 0x7).f[3] = 1.0 / src.f[3]; |
| 2918 | | } |
| 2919 | | CYCLES(1); // TODO: correct cycle count |
| 2920 | | } |
| 2921 | | |
| 2922 | | void i386_device::sse_andps_r128_rm128() // Opcode 0f 54 |
| 2923 | | { |
| 2924 | | UINT8 modrm = FETCH(); |
| 2925 | | if( modrm >= 0xc0 ) { |
| 2926 | | XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] & XMM(modrm & 0x7).q[0]; |
| 2927 | | XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] & XMM(modrm & 0x7).q[1]; |
| 2928 | | } else { |
| 2929 | | XMM_REG src; |
| 2930 | | UINT32 ea = GetEA(modrm, 0); |
| 2931 | | READXMM(ea, src); |
| 2932 | | XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] & src.q[0]; |
| 2933 | | XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] & src.q[1]; |
| 2934 | | } |
| 2935 | | CYCLES(1); // TODO: correct cycle count |
| 2936 | | } |
| 2937 | | |
| 2938 | | void i386_device::sse_andnps_r128_rm128() // Opcode 0f 55 |
| 2939 | | { |
| 2940 | | UINT8 modrm = FETCH(); |
| 2941 | | if( modrm >= 0xc0 ) { |
| 2942 | | XMM((modrm >> 3) & 0x7).q[0] = ~(XMM((modrm >> 3) & 0x7).q[0]) & XMM(modrm & 0x7).q[0]; |
| 2943 | | XMM((modrm >> 3) & 0x7).q[1] = ~(XMM((modrm >> 3) & 0x7).q[1]) & XMM(modrm & 0x7).q[1]; |
| 2944 | | } else { |
| 2945 | | XMM_REG src; |
| 2946 | | UINT32 ea = GetEA(modrm, 0); |
| 2947 | | READXMM(ea, src); |
| 2948 | | XMM((modrm >> 3) & 0x7).q[0] = ~(XMM((modrm >> 3) & 0x7).q[0]) & src.q[0]; |
| 2949 | | XMM((modrm >> 3) & 0x7).q[1] = ~(XMM((modrm >> 3) & 0x7).q[1]) & src.q[1]; |
| 2950 | | } |
| 2951 | | CYCLES(1); // TODO: correct cycle count |
| 2952 | | } |
| 2953 | | |
| 2954 | | void i386_device::sse_orps_r128_rm128() // Opcode 0f 56 |
| 2955 | | { |
| 2956 | | UINT8 modrm = FETCH(); |
| 2957 | | if( modrm >= 0xc0 ) { |
| 2958 | | XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] | XMM(modrm & 0x7).q[0]; |
| 2959 | | XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] | XMM(modrm & 0x7).q[1]; |
| 2960 | | } else { |
| 2961 | | XMM_REG src; |
| 2962 | | UINT32 ea = GetEA(modrm, 0); |
| 2963 | | READXMM(ea, src); |
| 2964 | | XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] | src.q[0]; |
| 2965 | | XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] | src.q[1]; |
| 2966 | | } |
| 2967 | | CYCLES(1); // TODO: correct cycle count |
| 2968 | | } |
| 2969 | | |
| 2970 | | void i386_device::sse_mulps() // Opcode 0f 59 ???? |
| 2971 | | { |
| 2972 | | UINT8 modrm = FETCH(); |
| 2973 | | if( modrm >= 0xc0 ) { |
| 2974 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * XMM(modrm & 0x7).f[0]; |
| 2975 | | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] * XMM(modrm & 0x7).f[1]; |
| 2976 | | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] * XMM(modrm & 0x7).f[2]; |
| 2977 | | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] * XMM(modrm & 0x7).f[3]; |
| 2978 | | } else { |
| 2979 | | XMM_REG src; |
| 2980 | | UINT32 ea = GetEA(modrm, 0); |
| 2981 | | READXMM(ea, src); |
| 2982 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * src.f[0]; |
| 2983 | | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] * src.f[1]; |
| 2984 | | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] * src.f[2]; |
| 2985 | | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] * src.f[3]; |
| 2986 | | } |
| 2987 | | CYCLES(1); // TODO: correct cycle count |
| 2988 | | } |
| 2989 | | |
| 2990 | | void i386_device::sse_subps() // Opcode 0f 5c |
| 2991 | | { |
| 2992 | | UINT8 modrm = FETCH(); |
| 2993 | | if( modrm >= 0xc0 ) { |
| 2994 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] - XMM(modrm & 0x7).f[0]; |
| 2995 | | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] - XMM(modrm & 0x7).f[1]; |
| 2996 | | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] - XMM(modrm & 0x7).f[2]; |
| 2997 | | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] - XMM(modrm & 0x7).f[3]; |
| 2998 | | } else { |
| 2999 | | XMM_REG src; |
| 3000 | | UINT32 ea = GetEA(modrm, 0); |
| 3001 | | READXMM(ea, src); |
| 3002 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] - src.f[0]; |
| 3003 | | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] - src.f[1]; |
| 3004 | | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] - src.f[2]; |
| 3005 | | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] - src.f[3]; |
| 3006 | | } |
| 3007 | | CYCLES(1); // TODO: correct cycle count |
| 3008 | | } |
| 3009 | | |
| 3010 | | INLINE float sse_min_single(float src1, float src2) |
| 3011 | | { |
| 3012 | | /*if ((src1 == 0) && (src2 == 0)) |
| 3013 | | return src2; |
| 3014 | | if (src1 = SNaN) |
| 3015 | | return src2; |
| 3016 | | if (src2 = SNaN) |
| 3017 | | return src2;*/ |
| 3018 | | if (src1 < src2) |
| 3019 | | return src1; |
| 3020 | | return src2; |
| 3021 | | } |
| 3022 | | |
| 3023 | | void i386_device::sse_minps() // Opcode 0f 5d |
| 3024 | | { |
| 3025 | | UINT8 modrm = FETCH(); |
| 3026 | | if( modrm >= 0xc0 ) { |
| 3027 | | XMM((modrm >> 3) & 0x7).f[0] = sse_min_single(XMM((modrm >> 3) & 0x7).f[0], XMM(modrm & 0x7).f[0]); |
| 3028 | | XMM((modrm >> 3) & 0x7).f[1] = sse_min_single(XMM((modrm >> 3) & 0x7).f[1], XMM(modrm & 0x7).f[1]); |
| 3029 | | XMM((modrm >> 3) & 0x7).f[2] = sse_min_single(XMM((modrm >> 3) & 0x7).f[2], XMM(modrm & 0x7).f[2]); |
| 3030 | | XMM((modrm >> 3) & 0x7).f[3] = sse_min_single(XMM((modrm >> 3) & 0x7).f[3], XMM(modrm & 0x7).f[3]); |
| 3031 | | } else { |
| 3032 | | XMM_REG src; |
| 3033 | | UINT32 ea = GetEA(modrm, 0); |
| 3034 | | READXMM(ea, src); |
| 3035 | | XMM((modrm >> 3) & 0x7).f[0] = sse_min_single(XMM((modrm >> 3) & 0x7).f[0], src.f[0]); |
| 3036 | | XMM((modrm >> 3) & 0x7).f[1] = sse_min_single(XMM((modrm >> 3) & 0x7).f[1], src.f[1]); |
| 3037 | | XMM((modrm >> 3) & 0x7).f[2] = sse_min_single(XMM((modrm >> 3) & 0x7).f[2], src.f[2]); |
| 3038 | | XMM((modrm >> 3) & 0x7).f[3] = sse_min_single(XMM((modrm >> 3) & 0x7).f[3], src.f[3]); |
| 3039 | | } |
| 3040 | | CYCLES(1); // TODO: correct cycle count |
| 3041 | | } |
| 3042 | | |
| 3043 | | void i386_device::sse_divps() // Opcode 0f 5e |
| 3044 | | { |
| 3045 | | UINT8 modrm = FETCH(); |
| 3046 | | if( modrm >= 0xc0 ) { |
| 3047 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] / XMM(modrm & 0x7).f[0]; |
| 3048 | | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] / XMM(modrm & 0x7).f[1]; |
| 3049 | | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] / XMM(modrm & 0x7).f[2]; |
| 3050 | | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] / XMM(modrm & 0x7).f[3]; |
| 3051 | | } else { |
| 3052 | | XMM_REG src; |
| 3053 | | UINT32 ea = GetEA(modrm, 0); |
| 3054 | | READXMM(ea, src); |
| 3055 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] / src.f[0]; |
| 3056 | | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] / src.f[1]; |
| 3057 | | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] / src.f[2]; |
| 3058 | | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] / src.f[3]; |
| 3059 | | } |
| 3060 | | CYCLES(1); // TODO: correct cycle count |
| 3061 | | } |
| 3062 | | |
| 3063 | | INLINE float sse_max_single(float src1, float src2) |
| 3064 | | { |
| 3065 | | /*if ((src1 == 0) && (src2 == 0)) |
| 3066 | | return src2; |
| 3067 | | if (src1 = SNaN) |
| 3068 | | return src2; |
| 3069 | | if (src2 = SNaN) |
| 3070 | | return src2;*/ |
| 3071 | | if (src1 > src2) |
| 3072 | | return src1; |
| 3073 | | return src2; |
| 3074 | | } |
| 3075 | | |
| 3076 | | void i386_device::sse_maxps() // Opcode 0f 5f |
| 3077 | | { |
| 3078 | | UINT8 modrm = FETCH(); |
| 3079 | | if( modrm >= 0xc0 ) { |
| 3080 | | XMM((modrm >> 3) & 0x7).f[0] = sse_max_single(XMM((modrm >> 3) & 0x7).f[0], XMM(modrm & 0x7).f[0]); |
| 3081 | | XMM((modrm >> 3) & 0x7).f[1] = sse_max_single(XMM((modrm >> 3) & 0x7).f[1], XMM(modrm & 0x7).f[1]); |
| 3082 | | XMM((modrm >> 3) & 0x7).f[2] = sse_max_single(XMM((modrm >> 3) & 0x7).f[2], XMM(modrm & 0x7).f[2]); |
| 3083 | | XMM((modrm >> 3) & 0x7).f[3] = sse_max_single(XMM((modrm >> 3) & 0x7).f[3], XMM(modrm & 0x7).f[3]); |
| 3084 | | } else { |
| 3085 | | XMM_REG src; |
| 3086 | | UINT32 ea = GetEA(modrm, 0); |
| 3087 | | READXMM(ea, src); |
| 3088 | | XMM((modrm >> 3) & 0x7).f[0] = sse_max_single(XMM((modrm >> 3) & 0x7).f[0], src.f[0]); |
| 3089 | | XMM((modrm >> 3) & 0x7).f[1] = sse_max_single(XMM((modrm >> 3) & 0x7).f[1], src.f[1]); |
| 3090 | | XMM((modrm >> 3) & 0x7).f[2] = sse_max_single(XMM((modrm >> 3) & 0x7).f[2], src.f[2]); |
| 3091 | | XMM((modrm >> 3) & 0x7).f[3] = sse_max_single(XMM((modrm >> 3) & 0x7).f[3], src.f[3]); |
| 3092 | | } |
| 3093 | | CYCLES(1); // TODO: correct cycle count |
| 3094 | | } |
| 3095 | | |
| 3096 | | void i386_device::sse_maxss_r128_r128m32() // Opcode f3 0f 5f |
| 3097 | | { |
| 3098 | | UINT8 modrm = FETCH(); |
| 3099 | | if( modrm >= 0xc0 ) { |
| 3100 | | XMM((modrm >> 3) & 0x7).f[0] = sse_max_single(XMM((modrm >> 3) & 0x7).f[0], XMM(modrm & 0x7).f[0]); |
| 3101 | | } else { |
| 3102 | | XMM_REG src; |
| 3103 | | UINT32 ea = GetEA(modrm, 0); |
| 3104 | | src.d[0]=READ32(ea); |
| 3105 | | XMM((modrm >> 3) & 0x7).f[0] = sse_max_single(XMM((modrm >> 3) & 0x7).f[0], src.f[0]); |
| 3106 | | } |
| 3107 | | CYCLES(1); // TODO: correct cycle count |
| 3108 | | } |
| 3109 | | |
| 3110 | | void i386_device::sse_addss() // Opcode f3 0f 58 |
| 3111 | | { |
| 3112 | | UINT8 modrm = FETCH(); |
| 3113 | | if( modrm >= 0xc0 ) { |
| 3114 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + XMM(modrm & 0x7).f[0]; |
| 3115 | | } else { |
| 3116 | | XMM_REG src; |
| 3117 | | UINT32 ea = GetEA(modrm, 0); |
| 3118 | | READXMM(ea, src); |
| 3119 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + src.f[0]; |
| 3120 | | } |
| 3121 | | CYCLES(1); // TODO: correct cycle count |
| 3122 | | } |
| 3123 | | |
| 3124 | | void i386_device::sse_subss() // Opcode f3 0f 5c |
| 3125 | | { |
| 3126 | | UINT8 modrm = FETCH(); |
| 3127 | | if( modrm >= 0xc0 ) { |
| 3128 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] - XMM(modrm & 0x7).f[0]; |
| 3129 | | } else { |
| 3130 | | XMM_REG src; |
| 3131 | | UINT32 ea = GetEA(modrm, 0); |
| 3132 | | READXMM(ea, src); |
| 3133 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] - src.f[0]; |
| 3134 | | } |
| 3135 | | CYCLES(1); // TODO: correct cycle count |
| 3136 | | } |
| 3137 | | |
| 3138 | | void i386_device::sse_mulss() // Opcode f3 0f 5e |
| 3139 | | { |
| 3140 | | UINT8 modrm = FETCH(); |
| 3141 | | if( modrm >= 0xc0 ) { |
| 3142 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * XMM(modrm & 0x7).f[0]; |
| 3143 | | } else { |
| 3144 | | XMM_REG src; |
| 3145 | | UINT32 ea = GetEA(modrm, 0); |
| 3146 | | READXMM(ea, src); |
| 3147 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * src.f[0]; |
| 3148 | | } |
| 3149 | | CYCLES(1); // TODO: correct cycle count |
| 3150 | | } |
| 3151 | | |
| 3152 | | void i386_device::sse_divss() // Opcode 0f 59 |
| 3153 | | { |
| 3154 | | UINT8 modrm = FETCH(); |
| 3155 | | if( modrm >= 0xc0 ) { |
| 3156 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] / XMM(modrm & 0x7).f[0]; |
| 3157 | | } else { |
| 3158 | | XMM_REG src; |
| 3159 | | UINT32 ea = GetEA(modrm, 0); |
| 3160 | | READXMM(ea, src); |
| 3161 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] / src.f[0]; |
| 3162 | | } |
| 3163 | | CYCLES(1); // TODO: correct cycle count |
| 3164 | | } |
| 3165 | | |
| 3166 | | void i386_device::sse_rcpss_r128_r128m32() // Opcode f3 0f 53 |
| 3167 | | { |
| 3168 | | UINT8 modrm = FETCH(); |
| 3169 | | if( modrm >= 0xc0 ) { |
| 3170 | | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / XMM(modrm & 0x7).f[0]; |
| 3171 | | } else { |
| 3172 | | XMM_REG s; |
| 3173 | | UINT32 ea = GetEA(modrm, 0); |
| 3174 | | s.d[0]=READ32(ea); |
| 3175 | | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / s.f[0]; |
| 3176 | | } |
| 3177 | | CYCLES(1); // TODO: correct cycle count |
| 3178 | | } |
| 3179 | | |
| 3180 | | void i386_device::sse_sqrtss_r128_r128m32() // Opcode f3 0f 51 |
| 3181 | | { |
| 3182 | | UINT8 modrm = FETCH(); |
| 3183 | | if( modrm >= 0xc0 ) { |
| 3184 | | XMM((modrm >> 3) & 0x7).f[0] = sqrt(XMM(modrm & 0x7).f[0]); |
| 3185 | | } else { |
| 3186 | | XMM_REG s; |
| 3187 | | UINT32 ea = GetEA(modrm, 0); |
| 3188 | | s.d[0]=READ32(ea); |
| 3189 | | XMM((modrm >> 3) & 0x7).f[0] = sqrt(s.f[0]); |
| 3190 | | } |
| 3191 | | CYCLES(1); // TODO: correct cycle count |
| 3192 | | } |
| 3193 | | |
| 3194 | | void i386_device::sse_rsqrtss_r128_r128m32() // Opcode f3 0f 52 |
| 3195 | | { |
| 3196 | | UINT8 modrm = FETCH(); |
| 3197 | | if( modrm >= 0xc0 ) { |
| 3198 | | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / sqrt(XMM(modrm & 0x7).f[0]); |
| 3199 | | } else { |
| 3200 | | XMM_REG s; |
| 3201 | | UINT32 ea = GetEA(modrm, 0); |
| 3202 | | s.d[0]=READ32(ea); |
| 3203 | | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / sqrt(s.f[0]); |
| 3204 | | } |
| 3205 | | CYCLES(1); // TODO: correct cycle count |
| 3206 | | } |
| 3207 | | |
| 3208 | | void i386_device::sse_minss_r128_r128m32() // Opcode f3 0f 5d |
| 3209 | | { |
| 3210 | | UINT8 modrm = FETCH(); |
| 3211 | | if( modrm >= 0xc0 ) { |
| 3212 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] < XMM(modrm & 0x7).f[0] ? XMM((modrm >> 3) & 0x7).f[0] : XMM(modrm & 0x7).f[0]; |
| 3213 | | } else { |
| 3214 | | XMM_REG s; |
| 3215 | | UINT32 ea = GetEA(modrm, 0); |
| 3216 | | s.d[0] = READ32(ea); |
| 3217 | | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] < s.f[0] ? XMM((modrm >> 3) & 0x7).f[0] : s.f[0]; |
| 3218 | | } |
| 3219 | | CYCLES(1); // TODO: correct cycle count |
| 3220 | | } |
| 3221 | | |
| 3222 | | void i386_device::sse_comiss_r128_r128m32() // Opcode 0f 2f |
| 3223 | | { |
| 3224 | | float32 a,b; |
| 3225 | | UINT8 modrm = FETCH(); |
| 3226 | | if( modrm >= 0xc0 ) { |
| 3227 | | a = XMM((modrm >> 3) & 0x7).d[0]; |
| 3228 | | b = XMM(modrm & 0x7).d[0]; |
| 3229 | | } else { |
| 3230 | | XMM_REG src; |
| 3231 | | UINT32 ea = GetEA(modrm, 0); |
| 3232 | | READXMM(ea, src); |
| 3233 | | a = XMM((modrm >> 3) & 0x7).d[0]; |
| 3234 | | b = src.d[0]; |
| 3235 | | } |
| 3236 | | m_OF=0; |
| 3237 | | m_SF=0; |
| 3238 | | m_AF=0; |
| 3239 | | if (float32_is_nan(a) || float32_is_nan(b)) |
| 3240 | | { |
| 3241 | | m_ZF = 1; |
| 3242 | | m_PF = 1; |
| 3243 | | m_CF = 1; |
| 3244 | | } |
| 3245 | | else |
| 3246 | | { |
| 3247 | | m_ZF = 0; |
| 3248 | | m_PF = 0; |
| 3249 | | m_CF = 0; |
| 3250 | | if (float32_eq(a, b)) |
| 3251 | | m_ZF = 1; |
| 3252 | | if (float32_lt(a, b)) |
| 3253 | | m_CF = 1; |
| 3254 | | } |
| 3255 | | // should generate exception when at least one of the operands is either QNaN or SNaN |
| 3256 | | CYCLES(1); // TODO: correct cycle count |
| 3257 | | } |
| 3258 | | |
| 3259 | | void i386_device::sse_ucomiss_r128_r128m32() // Opcode 0f 2e |
| 3260 | | { |
| 3261 | | float32 a,b; |
| 3262 | | UINT8 modrm = FETCH(); |
| 3263 | | if( modrm >= 0xc0 ) { |
| 3264 | | a = XMM((modrm >> 3) & 0x7).d[0]; |
| 3265 | | b = XMM(modrm & 0x7).d[0]; |
| 3266 | | } else { |
| 3267 | | XMM_REG src; |
| 3268 | | UINT32 ea = GetEA(modrm, 0); |
| 3269 | | READXMM(ea, src); |
| 3270 | | a = XMM((modrm >> 3) & 0x7).d[0]; |
| 3271 | | b = src.d[0]; |
| 3272 | | } |
| 3273 | | m_OF=0; |
| 3274 | | m_SF=0; |
| 3275 | | m_AF=0; |
| 3276 | | if (float32_is_nan(a) || float32_is_nan(b)) |
| 3277 | | { |
| 3278 | | m_ZF = 1; |
| 3279 | | m_PF = 1; |
| 3280 | | m_CF = 1; |
| 3281 | | } |
| 3282 | | else |
| 3283 | | { |
| 3284 | | m_ZF = 0; |
| 3285 | | m_PF = 0; |
| 3286 | | m_CF = 0; |
| 3287 | | if (float32_eq(a, b)) |
| 3288 | | m_ZF = 1; |
| 3289 | | if (float32_lt(a, b)) |
| 3290 | | m_CF = 1; |
| 3291 | | } |
| 3292 | | // should generate exception when at least one of the operands is SNaN |
| 3293 | | CYCLES(1); // TODO: correct cycle count |
| 3294 | | } |
| 3295 | | |
| 3296 | | void i386_device::sse_shufps() // Opcode 0f 67 |
| 3297 | | { |
| 3298 | | UINT8 modrm = FETCH(); |
| 3299 | | UINT8 sel = FETCH(); |
| 3300 | | int m1,m2,m3,m4; |
| 3301 | | int s,d; |
| 3302 | | m1=sel & 3; |
| 3303 | | m2=(sel >> 2) & 3; |
| 3304 | | m3=(sel >> 4) & 3; |
| 3305 | | m4=(sel >> 6) & 3; |
| 3306 | | s=modrm & 0x7; |
| 3307 | | d=(modrm >> 3) & 0x7; |
| 3308 | | if( modrm >= 0xc0 ) { |
| 3309 | | UINT32 t; |
| 3310 | | t=XMM(d).d[m1]; |
| 3311 | | XMM(d).d[1]=XMM(d).d[m2]; |
| 3312 | | XMM(d).d[0]=t; |
| 3313 | | XMM(d).d[2]=XMM(s).d[m3]; |
| 3314 | | XMM(d).d[3]=XMM(s).d[m4]; |
| 3315 | | } else { |
| 3316 | | UINT32 t; |
| 3317 | | XMM_REG src; |
| 3318 | | UINT32 ea = GetEA(modrm, 0); |
| 3319 | | READXMM(ea, src); |
| 3320 | | t=XMM(d).d[m1]; |
| 3321 | | XMM(d).d[1]=XMM(d).d[m2]; |
| 3322 | | XMM(d).d[0]=t; |
| 3323 | | XMM(d).d[2]=src.d[m3]; |
| 3324 | | XMM(d).d[3]=src.d[m4]; |
| 3325 | | } |
| 3326 | | CYCLES(1); // TODO: correct cycle count |
| 3327 | | } |
| 3328 | | |
| 3329 | | void i386_device::sse_unpcklps_r128_rm128() // Opcode 0f 14 |
| 3330 | | { |
| 3331 | | UINT8 modrm = FETCH(); |
| 3332 | | int s,d; |
| 3333 | | s=modrm & 0x7; |
| 3334 | | d=(modrm >> 3) & 0x7; |
| 3335 | | if( modrm >= 0xc0 ) { |
| 3336 | | XMM(d).d[3]=XMM(s).d[1]; |
| 3337 | | XMM(d).d[2]=XMM(d).d[1]; |
| 3338 | | XMM(d).d[1]=XMM(s).d[0]; |
| 3339 | | //XMM(d).d[0]=XMM(d).d[0]; |
| 3340 | | } else { |
| 3341 | | XMM_REG src; |
| 3342 | | UINT32 ea = GetEA(modrm, 0); |
| 3343 | | READXMM(ea, src); |
| 3344 | | XMM(d).d[3]=src.d[1]; |
| 3345 | | XMM(d).d[2]=XMM(d).d[1]; |
| 3346 | | XMM(d).d[1]=src.d[0]; |
| 3347 | | } |
| 3348 | | CYCLES(1); // TODO: correct cycle count |
| 3349 | | } |
| 3350 | | |
| 3351 | | void i386_device::sse_unpckhps_r128_rm128() // Opcode 0f 15 |
| 3352 | | { |
| 3353 | | UINT8 modrm = FETCH(); |
| 3354 | | int s,d; |
| 3355 | | s=modrm & 0x7; |
| 3356 | | d=(modrm >> 3) & 0x7; |
| 3357 | | if( modrm >= 0xc0 ) { |
| 3358 | | XMM(d).d[0]=XMM(d).d[2]; |
| 3359 | | XMM(d).d[1]=XMM(s).d[2]; |
| 3360 | | XMM(d).d[2]=XMM(d).d[3]; |
| 3361 | | XMM(d).d[3]=XMM(s).d[3]; |
| 3362 | | } else { |
| 3363 | | XMM_REG src; |
| 3364 | | UINT32 ea = GetEA(modrm, 0); |
| 3365 | | READXMM(ea, src); |
| 3366 | | XMM(d).d[0]=XMM(d).d[2]; |
| 3367 | | XMM(d).d[1]=src.d[2]; |
| 3368 | | XMM(d).d[2]=XMM(d).d[3]; |
| 3369 | | XMM(d).d[3]=src.d[3]; |
| 3370 | | } |
| 3371 | | CYCLES(1); // TODO: correct cycle count |
| 3372 | | } |
| 3373 | | |
| 3374 | | INLINE bool sse_issingleordered(float op1, float op2) |
| 3375 | | { |
| 3376 | | // TODO: true when at least one of the two source operands being compared is a NaN |
| 3377 | | return (op1 != op1) || (op1 != op2); |
| 3378 | | } |
| 3379 | | |
| 3380 | | INLINE bool sse_issingleunordered(float op1, float op2) |
| 3381 | | { |
| 3382 | | // TODO: true when neither source operand is a NaN |
| 3383 | | return !((op1 != op1) || (op1 != op2)); |
| 3384 | | } |
| 3385 | | |
| 3386 | | void i386_device::sse_predicate_compare_single(UINT8 imm8, XMM_REG d, XMM_REG s) |
| 3387 | | { |
| 3388 | | switch (imm8 & 7) |
| 3389 | | { |
| 3390 | | case 0: |
| 3391 | | s.d[0]=s.f[0] == s.f[0] ? 0xffffffff : 0; |
| 3392 | | d.d[1]=d.f[1] == s.f[1] ? 0xffffffff : 0; |
| 3393 | | d.d[2]=d.f[2] == s.f[2] ? 0xffffffff : 0; |
| 3394 | | d.d[3]=d.f[3] == s.f[3] ? 0xffffffff : 0; |
| 3395 | | break; |
| 3396 | | case 1: |
| 3397 | | d.d[0]=d.f[0] < s.f[0] ? 0xffffffff : 0; |
| 3398 | | d.d[1]=d.f[1] < s.f[1] ? 0xffffffff : 0; |
| 3399 | | d.d[2]=d.f[2] < s.f[2] ? 0xffffffff : 0; |
| 3400 | | d.d[3]=d.f[3] < s.f[3] ? 0xffffffff : 0; |
| 3401 | | break; |
| 3402 | | case 2: |
| 3403 | | d.d[0]=d.f[0] <= s.f[0] ? 0xffffffff : 0; |
| 3404 | | d.d[1]=d.f[1] <= s.f[1] ? 0xffffffff : 0; |
| 3405 | | d.d[2]=d.f[2] <= s.f[2] ? 0xffffffff : 0; |
| 3406 | | d.d[3]=d.f[3] <= s.f[3] ? 0xffffffff : 0; |
| 3407 | | break; |
| 3408 | | case 3: |
| 3409 | | d.d[0]=sse_issingleunordered(d.f[0], s.f[0]) ? 0xffffffff : 0; |
| 3410 | | d.d[1]=sse_issingleunordered(d.f[1], s.f[1]) ? 0xffffffff : 0; |
| 3411 | | d.d[2]=sse_issingleunordered(d.f[2], s.f[2]) ? 0xffffffff : 0; |
| 3412 | | d.d[3]=sse_issingleunordered(d.f[3], s.f[3]) ? 0xffffffff : 0; |
| 3413 | | break; |
| 3414 | | case 4: |
| 3415 | | d.d[0]=d.f[0] != s.f[0] ? 0xffffffff : 0; |
| 3416 | | d.d[1]=d.f[1] != s.f[1] ? 0xffffffff : 0; |
| 3417 | | d.d[2]=d.f[2] != s.f[2] ? 0xffffffff : 0; |
| 3418 | | d.d[3]=d.f[3] != s.f[3] ? 0xffffffff : 0; |
| 3419 | | break; |
| 3420 | | case 5: |
| 3421 | | d.d[0]=d.f[0] < s.f[0] ? 0 : 0xffffffff; |
| 3422 | | d.d[1]=d.f[1] < s.f[1] ? 0 : 0xffffffff; |
| 3423 | | d.d[2]=d.f[2] < s.f[2] ? 0 : 0xffffffff; |
| 3424 | | d.d[3]=d.f[3] < s.f[3] ? 0 : 0xffffffff; |
| 3425 | | break; |
| 3426 | | case 6: |
| 3427 | | d.d[0]=d.f[0] <= s.f[0] ? 0 : 0xffffffff; |
| 3428 | | d.d[1]=d.f[1] <= s.f[1] ? 0 : 0xffffffff; |
| 3429 | | d.d[2]=d.f[2] <= s.f[2] ? 0 : 0xffffffff; |
| 3430 | | d.d[3]=d.f[3] <= s.f[3] ? 0 : 0xffffffff; |
| 3431 | | break; |
| 3432 | | case 7: |
| 3433 | | d.d[0]=sse_issingleordered(d.f[0], s.f[0]) ? 0xffffffff : 0; |
| 3434 | | d.d[1]=sse_issingleordered(d.f[1], s.f[1]) ? 0xffffffff : 0; |
| 3435 | | d.d[2]=sse_issingleordered(d.f[2], s.f[2]) ? 0xffffffff : 0; |
| 3436 | | d.d[3]=sse_issingleordered(d.f[3], s.f[3]) ? 0xffffffff : 0; |
| 3437 | | break; |
| 3438 | | } |
| 3439 | | } |
| 3440 | | |
| 3441 | | void i386_device::sse_predicate_compare_single_scalar(UINT8 imm8, XMM_REG d, XMM_REG s) |
| 3442 | | { |
| 3443 | | switch (imm8 & 7) |
| 3444 | | { |
| 3445 | | case 0: |
| 3446 | | s.d[0]=s.f[0] == s.f[0] ? 0xffffffff : 0; |
| 3447 | | break; |
| 3448 | | case 1: |
| 3449 | | d.d[0]=d.f[0] < s.f[0] ? 0xffffffff : 0; |
| 3450 | | break; |
| 3451 | | case 2: |
| 3452 | | d.d[0]=d.f[0] <= s.f[0] ? 0xffffffff : 0; |
| 3453 | | break; |
| 3454 | | case 3: |
| 3455 | | d.d[0]=sse_issingleunordered(d.f[0], s.f[0]) ? 0xffffffff : 0; |
| 3456 | | break; |
| 3457 | | case 4: |
| 3458 | | d.d[0]=d.f[0] != s.f[0] ? 0xffffffff : 0; |
| 3459 | | break; |
| 3460 | | case 5: |
| 3461 | | d.d[0]=d.f[0] < s.f[0] ? 0 : 0xffffffff; |
| 3462 | | break; |
| 3463 | | case 6: |
| 3464 | | d.d[0]=d.f[0] <= s.f[0] ? 0 : 0xffffffff; |
| 3465 | | break; |
| 3466 | | case 7: |
| 3467 | | d.d[0]=sse_issingleordered(d.f[0], s.f[0]) ? 0xffffffff : 0; |
| 3468 | | break; |
| 3469 | | } |
| 3470 | | } |
| 3471 | | |
| 3472 | | void i386_device::sse_cmpps_r128_rm128_i8() // Opcode 0f c2 |
| 3473 | | { |
| 3474 | | UINT8 modrm = FETCH(); |
| 3475 | | if( modrm >= 0xc0 ) { |
| 3476 | | int s,d; |
| 3477 | | UINT8 imm8 = FETCH(); |
| 3478 | | s=modrm & 0x7; |
| 3479 | | d=(modrm >> 3) & 0x7; |
| 3480 | | sse_predicate_compare_single(imm8, XMM(d), XMM(s)); |
| 3481 | | } else { |
| 3482 | | int d; |
| 3483 | | XMM_REG s; |
| 3484 | | UINT32 ea = GetEA(modrm, 0); |
| 3485 | | UINT8 imm8 = FETCH(); |
| 3486 | | READXMM(ea, s); |
| 3487 | | d=(modrm >> 3) & 0x7; |
| 3488 | | sse_predicate_compare_single(imm8, XMM(d), s); |
| 3489 | | } |
| 3490 | | CYCLES(1); // TODO: correct cycle count |
| 3491 | | } |
| 3492 | | |
| 3493 | | void i386_device::sse_cmpss_r128_r128m32_i8() // Opcode f3 0f c2 |
| 3494 | | { |
| 3495 | | UINT8 modrm = FETCH(); |
| 3496 | | if( modrm >= 0xc0 ) { |
| 3497 | | int s,d; |
| 3498 | | UINT8 imm8 = FETCH(); |
| 3499 | | s=modrm & 0x7; |
| 3500 | | d=(modrm >> 3) & 0x7; |
| 3501 | | sse_predicate_compare_single_scalar(imm8, XMM(d), XMM(s)); |
| 3502 | | } else { |
| 3503 | | int d; |
| 3504 | | XMM_REG s; |
| 3505 | | UINT32 ea = GetEA(modrm, 0); |
| 3506 | | UINT8 imm8 = FETCH(); |
| 3507 | | s.d[0]=READ32(ea); |
| 3508 | | d=(modrm >> 3) & 0x7; |
| 3509 | | sse_predicate_compare_single_scalar(imm8, XMM(d), s); |
| 3510 | | } |
| 3511 | | CYCLES(1); // TODO: correct cycle count |
| 3512 | | } |
| 3513 | | |
| 3514 | | void i386_device::sse_pinsrw_r64_r16m16_i8() // Opcode 0f c4 |
| 3515 | | { |
| 3516 | | MMXPROLOG(); |
| 3517 | | UINT8 modrm = FETCH(); |
| 3518 | | if( modrm >= 0xc0 ) { |
| 3519 | | UINT8 imm8 = FETCH(); |
| 3520 | | UINT16 v = LOAD_RM16(modrm); |
| 3521 | | MMX((modrm >> 3) & 0x7).w[imm8 & 3] = v; |
| 3522 | | } else { |
| 3523 | | UINT32 ea = GetEA(modrm, 0); |
| 3524 | | UINT8 imm8 = FETCH(); |
| 3525 | | UINT16 v = READ16(ea); |
| 3526 | | MMX((modrm >> 3) & 0x7).w[imm8 & 3] = v; |
| 3527 | | } |
| 3528 | | CYCLES(1); // TODO: correct cycle count |
| 3529 | | } |
| 3530 | | |
| 3531 | | void i386_device::sse_pinsrw_r64_r32m16_i8() // Opcode 0f c4 |
| 3532 | | { |
| 3533 | | MMXPROLOG(); |
| 3534 | | UINT8 modrm = FETCH(); |
| 3535 | | if( modrm >= 0xc0 ) { |
| 3536 | | UINT8 imm8 = FETCH(); |
| 3537 | | UINT16 v = (UINT16)LOAD_RM32(modrm); |
| 3538 | | MMX((modrm >> 3) & 0x7).w[imm8 & 3] = v; |
| 3539 | | } else { |
| 3540 | | UINT32 ea = GetEA(modrm, 0); |
| 3541 | | UINT8 imm8 = FETCH(); |
| 3542 | | UINT16 v = READ16(ea); |
| 3543 | | MMX((modrm >> 3) & 0x7).w[imm8 & 3] = v; |
| 3544 | | } |
| 3545 | | CYCLES(1); // TODO: correct cycle count |
| 3546 | | } |
| 3547 | | |
| 3548 | | void i386_device::sse_pextrw_r16_r64_i8() // Opcode 0f c5 |
| 3549 | | { |
| 3550 | | //MMXPROLOG(); |
| 3551 | | UINT8 modrm = FETCH(); |
| 3552 | | if( modrm >= 0xc0 ) { |
| 3553 | | UINT8 imm8 = FETCH(); |
| 3554 | | STORE_REG16(modrm, MMX(modrm & 0x7).w[imm8 & 3]); |
| 3555 | | } else { |
| 3556 | | //UINT8 imm8 = FETCH(); |
| 3557 | | report_invalid_modrm("pextrw_r16_r64_i8", modrm); |
| 3558 | | } |
| 3559 | | CYCLES(1); // TODO: correct cycle count |
| 3560 | | } |
| 3561 | | |
| 3562 | | void i386_device::sse_pextrw_r32_r64_i8() // Opcode 0f c5 |
| 3563 | | { |
| 3564 | | //MMXPROLOG(); |
| 3565 | | UINT8 modrm = FETCH(); |
| 3566 | | if( modrm >= 0xc0 ) { |
| 3567 | | UINT8 imm8 = FETCH(); |
| 3568 | | STORE_REG32(modrm, MMX(modrm & 0x7).w[imm8 & 3]); |
| 3569 | | } else { |
| 3570 | | //UINT8 imm8 = FETCH(); |
| 3571 | | report_invalid_modrm("pextrw_r32_r64_i8", modrm); |
| 3572 | | } |
| 3573 | | CYCLES(1); // TODO: correct cycle count |
| 3574 | | } |
| 3575 | | |
| 3576 | | void i386_device::sse_pminub_r64_rm64() // Opcode 0f da |
| 3577 | | { |
| 3578 | | int n; |
| 3579 | | MMXPROLOG(); |
| 3580 | | UINT8 modrm = FETCH(); |
| 3581 | | if( modrm >= 0xc0 ) { |
| 3582 | | for (n=0;n < 8;n++) |
| 3583 | | MMX((modrm >> 3) & 0x7).b[n] = MMX((modrm >> 3) & 0x7).b[n] < MMX(modrm & 0x7).b[n] ? MMX((modrm >> 3) & 0x7).b[n] : MMX(modrm & 0x7).b[n]; |
| 3584 | | } else { |
| 3585 | | MMX_REG s; |
| 3586 | | UINT32 ea = GetEA(modrm, 0); |
| 3587 | | READMMX(ea, s); |
| 3588 | | for (n=0;n < 8;n++) |
| 3589 | | MMX((modrm >> 3) & 0x7).b[n] = MMX((modrm >> 3) & 0x7).b[n] < s.b[n] ? MMX((modrm >> 3) & 0x7).b[n] : s.b[n]; |
| 3590 | | } |
| 3591 | | CYCLES(1); // TODO: correct cycle count |
| 3592 | | } |
| 3593 | | |
| 3594 | | void i386_device::sse_pmaxub_r64_rm64() // Opcode 0f de |
| 3595 | | { |
| 3596 | | int n; |
| 3597 | | MMXPROLOG(); |
| 3598 | | UINT8 modrm = FETCH(); |
| 3599 | | if( modrm >= 0xc0 ) { |
| 3600 | | for (n=0;n < 8;n++) |
| 3601 | | MMX((modrm >> 3) & 0x7).b[n] = MMX((modrm >> 3) & 0x7).b[n] > MMX(modrm & 0x7).b[n] ? MMX((modrm >> 3) & 0x7).b[n] : MMX(modrm & 0x7).b[n]; |
| 3602 | | } else { |
| 3603 | | MMX_REG s; |
| 3604 | | UINT32 ea = GetEA(modrm, 0); |
| 3605 | | READMMX(ea, s); |
| 3606 | | for (n=0;n < 8;n++) |
| 3607 | | MMX((modrm >> 3) & 0x7).b[n] = MMX((modrm >> 3) & 0x7).b[n] > s.b[n] ? MMX((modrm >> 3) & 0x7).b[n] : s.b[n]; |
| 3608 | | } |
| 3609 | | CYCLES(1); // TODO: correct cycle count |
| 3610 | | } |
| 3611 | | |
| 3612 | | void i386_device::sse_pavgb_r64_rm64() // Opcode 0f e0 |
| 3613 | | { |
| 3614 | | int n; |
| 3615 | | MMXPROLOG(); |
| 3616 | | UINT8 modrm = FETCH(); |
| 3617 | | if( modrm >= 0xc0 ) { |
| 3618 | | for (n=0;n < 8;n++) |
| 3619 | | MMX((modrm >> 3) & 0x7).b[n] = ((UINT16)MMX((modrm >> 3) & 0x7).b[n] + (UINT16)MMX(modrm & 0x7).b[n] + 1) >> 1; |
| 3620 | | } else { |
| 3621 | | MMX_REG s; |
| 3622 | | UINT32 ea = GetEA(modrm, 0); |
| 3623 | | READMMX(ea, s); |
| 3624 | | for (n=0;n < 8;n++) |
| 3625 | | MMX((modrm >> 3) & 0x7).b[n] = ((UINT16)MMX((modrm >> 3) & 0x7).b[n] + (UINT16)s.b[n] + 1) >> 1; |
| 3626 | | } |
| 3627 | | CYCLES(1); // TODO: correct cycle count |
| 3628 | | } |
| 3629 | | |
| 3630 | | void i386_device::sse_pavgw_r64_rm64() // Opcode 0f e3 |
| 3631 | | { |
| 3632 | | int n; |
| 3633 | | MMXPROLOG(); |
| 3634 | | UINT8 modrm = FETCH(); |
| 3635 | | if( modrm >= 0xc0 ) { |
| 3636 | | for (n=0;n < 4;n++) |
| 3637 | | MMX((modrm >> 3) & 0x7).w[n] = ((UINT32)MMX((modrm >> 3) & 0x7).w[n] + (UINT32)MMX(modrm & 0x7).w[n] + 1) >> 1; |
| 3638 | | } else { |
| 3639 | | MMX_REG s; |
| 3640 | | UINT32 ea = GetEA(modrm, 0); |
| 3641 | | READMMX(ea, s); |
| 3642 | | for (n=0;n < 4;n++) |
| 3643 | | MMX((modrm >> 3) & 0x7).w[n] = ((UINT32)MMX((modrm >> 3) & 0x7).w[n] + (UINT32)s.w[n] + 1) >> 1; |
| 3644 | | } |
| 3645 | | CYCLES(1); // TODO: correct cycle count |
| 3646 | | } |
| 3647 | | |
| 3648 | | void i386_device::sse_pmulhuw_r64_rm64() // Opcode 0f e4 |
| 3649 | | { |
| 3650 | | MMXPROLOG(); |
| 3651 | | UINT8 modrm = FETCH(); |
| 3652 | | if( modrm >= 0xc0 ) { |
| 3653 | | MMX((modrm >> 3) & 0x7).w[0]=((UINT32)MMX((modrm >> 3) & 0x7).w[0]*(UINT32)MMX(modrm & 7).w[0]) >> 16; |
| 3654 | | MMX((modrm >> 3) & 0x7).w[1]=((UINT32)MMX((modrm >> 3) & 0x7).w[1]*(UINT32)MMX(modrm & 7).w[1]) >> 16; |
| 3655 | | MMX((modrm >> 3) & 0x7).w[2]=((UINT32)MMX((modrm >> 3) & 0x7).w[2]*(UINT32)MMX(modrm & 7).w[2]) >> 16; |
| 3656 | | MMX((modrm >> 3) & 0x7).w[3]=((UINT32)MMX((modrm >> 3) & 0x7).w[3]*(UINT32)MMX(modrm & 7).w[3]) >> 16; |
| 3657 | | } else { |
| 3658 | | MMX_REG s; |
| 3659 | | UINT32 ea = GetEA(modrm, 0); |
| 3660 | | READMMX(ea, s); |
| 3661 | | MMX((modrm >> 3) & 0x7).w[0]=((UINT32)MMX((modrm >> 3) & 0x7).w[0]*(UINT32)s.w[0]) >> 16; |
| 3662 | | MMX((modrm >> 3) & 0x7).w[1]=((UINT32)MMX((modrm >> 3) & 0x7).w[1]*(UINT32)s.w[1]) >> 16; |
| 3663 | | MMX((modrm >> 3) & 0x7).w[2]=((UINT32)MMX((modrm >> 3) & 0x7).w[2]*(UINT32)s.w[2]) >> 16; |
| 3664 | | MMX((modrm >> 3) & 0x7).w[3]=((UINT32)MMX((modrm >> 3) & 0x7).w[3]*(UINT32)s.w[3]) >> 16; |
| 3665 | | } |
| 3666 | | CYCLES(1); // TODO: correct cycle count |
| 3667 | | } |
| 3668 | | |
| 3669 | | void i386_device::sse_pminsw_r64_rm64() // Opcode 0f ea |
| 3670 | | { |
| 3671 | | int n; |
| 3672 | | MMXPROLOG(); |
| 3673 | | UINT8 modrm = FETCH(); |
| 3674 | | if( modrm >= 0xc0 ) { |
| 3675 | | for (n=0;n < 4;n++) |
| 3676 | | MMX((modrm >> 3) & 0x7).s[n] = MMX((modrm >> 3) & 0x7).s[n] < MMX(modrm & 0x7).s[n] ? MMX((modrm >> 3) & 0x7).s[n] : MMX(modrm & 0x7).s[n]; |
| 3677 | | } else { |
| 3678 | | MMX_REG s; |
| 3679 | | UINT32 ea = GetEA(modrm, 0); |
| 3680 | | READMMX(ea, s); |
| 3681 | | for (n=0;n < 4;n++) |
| 3682 | | MMX((modrm >> 3) & 0x7).s[n] = MMX((modrm >> 3) & 0x7).s[n] < s.s[n] ? MMX((modrm >> 3) & 0x7).s[n] : s.s[n]; |
| 3683 | | } |
| 3684 | | CYCLES(1); // TODO: correct cycle count |
| 3685 | | } |
| 3686 | | |
| 3687 | | void i386_device::sse_pmaxsw_r64_rm64() // Opcode 0f ee |
| 3688 | | { |
| 3689 | | int n; |
| 3690 | | MMXPROLOG(); |
| 3691 | | UINT8 modrm = FETCH(); |
| 3692 | | if( modrm >= 0xc0 ) { |
| 3693 | | for (n=0;n < 4;n++) |
| 3694 | | MMX((modrm >> 3) & 0x7).s[n] = MMX((modrm >> 3) & 0x7).s[n] > MMX(modrm & 0x7).s[n] ? MMX((modrm >> 3) & 0x7).s[n] : MMX(modrm & 0x7).s[n]; |
| 3695 | | } else { |
| 3696 | | MMX_REG s; |
| 3697 | | UINT32 ea = GetEA(modrm, 0); |
| 3698 | | READMMX(ea, s); |
| 3699 | | for (n=0;n < 4;n++) |
| 3700 | | MMX((modrm >> 3) & 0x7).s[n] = MMX((modrm >> 3) & 0x7).s[n] > s.s[n] ? MMX((modrm >> 3) & 0x7).s[n] : s.s[n]; |
| 3701 | | } |
| 3702 | | CYCLES(1); // TODO: correct cycle count |
| 3703 | | } |
| 3704 | | |
| 3705 | | void i386_device::sse_pmuludq_r64_rm64() // Opcode 0f f4 |
| 3706 | | { |
| 3707 | | MMXPROLOG(); |
| 3708 | | UINT8 modrm = FETCH(); |
| 3709 | | if( modrm >= 0xc0 ) { |
| 3710 | | MMX((modrm >> 3) & 0x7).q = (UINT64)MMX((modrm >> 3) & 0x7).d[0] * (UINT64)MMX(modrm & 0x7).d[0]; |
| 3711 | | } else { |
| 3712 | | MMX_REG s; |
| 3713 | | UINT32 ea = GetEA(modrm, 0); |
| 3714 | | READMMX(ea, s); |
| 3715 | | MMX((modrm >> 3) & 0x7).q = (UINT64)MMX((modrm >> 3) & 0x7).d[0] * (UINT64)s.d[0]; |
| 3716 | | } |
| 3717 | | CYCLES(1); // TODO: correct cycle count |
| 3718 | | } |
| 3719 | | |
| 3720 | | void i386_device::sse_psadbw_r64_rm64() // Opcode 0f f6 |
| 3721 | | { |
| 3722 | | int n; |
| 3723 | | INT32 temp; |
| 3724 | | MMXPROLOG(); |
| 3725 | | UINT8 modrm = FETCH(); |
| 3726 | | if( modrm >= 0xc0 ) { |
| 3727 | | temp=0; |
| 3728 | | for (n=0;n < 8;n++) |
| 3729 | | temp += abs((INT32)MMX((modrm >> 3) & 0x7).b[n] - (INT32)MMX(modrm & 0x7).b[n]); |
| 3730 | | MMX((modrm >> 3) & 0x7).l=(UINT64)temp & 0xffff; |
| 3731 | | } else { |
| 3732 | | MMX_REG s; |
| 3733 | | UINT32 ea = GetEA(modrm, 0); |
| 3734 | | READMMX(ea, s); |
| 3735 | | temp=0; |
| 3736 | | for (n=0;n < 8;n++) |
| 3737 | | temp += abs((INT32)MMX((modrm >> 3) & 0x7).b[n] - (INT32)s.b[n]); |
| 3738 | | MMX((modrm >> 3) & 0x7).l=(UINT64)temp & 0xffff; |
| 3739 | | } |
| 3740 | | CYCLES(1); // TODO: correct cycle count |
| 3741 | | } |
| 3742 | | |
| 3743 | | void i386_device::sse_psubq_r64_rm64() // Opcode 0f fb |
| 3744 | | { |
| 3745 | | MMXPROLOG(); |
| 3746 | | UINT8 modrm = FETCH(); |
| 3747 | | if( modrm >= 0xc0 ) { |
| 3748 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q - MMX(modrm & 7).q; |
| 3749 | | } else { |
| 3750 | | MMX_REG s; |
| 3751 | | UINT32 ea = GetEA(modrm, 0); |
| 3752 | | READMMX(ea, s); |
| 3753 | | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q - s.q; |
| 3754 | | } |
| 3755 | | CYCLES(1); // TODO: correct cycle count |
| 3756 | | } |
| 3757 | | |
| 3758 | | void i386_device::sse_pshufhw_r128_rm128_i8() // Opcode f3 0f 70 |
| 3759 | | { |
| 3760 | | UINT8 modrm = FETCH(); |
| 3761 | | if( modrm >= 0xc0 ) { |
| 3762 | | XMM_REG t; |
| 3763 | | int s,d; |
| 3764 | | UINT8 imm8 = FETCH(); |
| 3765 | | s=modrm & 0x7; |
| 3766 | | d=(modrm >> 3) & 0x7; |
| 3767 | | t.q[0]=XMM(s).q[1]; |
| 3768 | | XMM(d).q[0]=XMM(s).q[0]; |
| 3769 | | XMM(d).w[4]=t.w[imm8 & 3]; |
| 3770 | | XMM(d).w[5]=t.w[(imm8 >> 2) & 3]; |
| 3771 | | XMM(d).w[6]=t.w[(imm8 >> 4) & 3]; |
| 3772 | | XMM(d).w[7]=t.w[(imm8 >> 6) & 3]; |
| 3773 | | } else { |
| 3774 | | XMM_REG s; |
| 3775 | | int d=(modrm >> 3) & 0x7; |
| 3776 | | UINT32 ea = GetEA(modrm, 0); |
| 3777 | | UINT8 imm8 = FETCH(); |
| 3778 | | READXMM(ea, s); |
| 3779 | | XMM(d).q[0]=s.q[0]; |
| 3780 | | XMM(d).w[4]=s.w[4 + (imm8 & 3)]; |
| 3781 | | XMM(d).w[5]=s.w[4 + ((imm8 >> 2) & 3)]; |
| 3782 | | XMM(d).w[6]=s.w[4 + ((imm8 >> 4) & 3)]; |
| 3783 | | XMM(d).w[7]=s.w[4 + ((imm8 >> 6) & 3)]; |
| 3784 | | } |
| 3785 | | CYCLES(1); // TODO: correct cycle count |
| 3786 | | } |
trunk/src/emu/cpu/i386/x87ops.c
| r28738 | r28739 | |
| 1 | | /*************************************************************************** |
| 2 | | |
| 3 | | x87 FPU emulation |
| 4 | | |
| 5 | | TODO: |
| 6 | | - 80-bit precision for F2XM1, FYL2X, FPATAN |
| 7 | | - Figure out why SoftFloat trig extensions produce bad values |
| 8 | | - Cycle counts for all processors (currently using 486 counts) |
| 9 | | - Precision-dependent cycle counts for divide instructions |
| 10 | | - Last instruction, operand pointers etc. |
| 11 | | - Fix FLDENV, FSTENV, FSAVE, FRSTOR and FPREM |
| 12 | | - Status word C2 updates to reflect round up/down |
| 13 | | - Handling of invalid and denormal numbers |
| 14 | | - Remove redundant operand checks |
| 15 | | - Exceptions |
| 16 | | |
| 17 | | ***************************************************************************/ |
| 18 | | |
| 19 | | #include <math.h> |
| 20 | | |
| 21 | | |
| 22 | | /************************************* |
| 23 | | * |
| 24 | | * Defines |
| 25 | | * |
| 26 | | *************************************/ |
| 27 | | |
| 28 | | #define X87_SW_IE 0x0001 |
| 29 | | #define X87_SW_DE 0x0002 |
| 30 | | #define X87_SW_ZE 0x0004 |
| 31 | | #define X87_SW_OE 0x0008 |
| 32 | | #define X87_SW_UE 0x0010 |
| 33 | | #define X87_SW_PE 0x0020 |
| 34 | | #define X87_SW_SF 0x0040 |
| 35 | | #define X87_SW_ES 0x0080 |
| 36 | | #define X87_SW_C0 0x0100 |
| 37 | | #define X87_SW_C1 0x0200 |
| 38 | | #define X87_SW_C2 0x0400 |
| 39 | | #define X87_SW_TOP_SHIFT 11 |
| 40 | | #define X87_SW_TOP_MASK 7 |
| 41 | | #define X87_SW_C3 0x4000 |
| 42 | | #define X87_SW_BUSY 0x8000 |
| 43 | | |
| 44 | | #define X87_CW_IM 0x0001 |
| 45 | | #define X87_CW_DM 0x0002 |
| 46 | | #define X87_CW_ZM 0x0004 |
| 47 | | #define X87_CW_OM 0x0008 |
| 48 | | #define X87_CW_UM 0x0010 |
| 49 | | #define X87_CW_PM 0x0020 |
| 50 | | #define X87_CW_PC_SHIFT 8 |
| 51 | | #define X87_CW_PC_MASK 3 |
| 52 | | #define X87_CW_PC_SINGLE 0 |
| 53 | | #define X87_CW_PC_DOUBLE 2 |
| 54 | | #define X87_CW_PC_EXTEND 3 |
| 55 | | #define X87_CW_RC_SHIFT 10 |
| 56 | | #define X87_CW_RC_MASK 3 |
| 57 | | #define X87_CW_RC_NEAREST 0 |
| 58 | | #define X87_CW_RC_DOWN 1 |
| 59 | | #define X87_CW_RC_UP 2 |
| 60 | | #define X87_CW_RC_ZERO 3 |
| 61 | | |
| 62 | | #define X87_TW_MASK 3 |
| 63 | | #define X87_TW_VALID 0 |
| 64 | | #define X87_TW_ZERO 1 |
| 65 | | #define X87_TW_SPECIAL 2 |
| 66 | | #define X87_TW_EMPTY 3 |
| 67 | | |
| 68 | | |
| 69 | | /************************************* |
| 70 | | * |
| 71 | | * Macros |
| 72 | | * |
| 73 | | *************************************/ |
| 74 | | |
| 75 | | #define ST_TO_PHYS(x) (((m_x87_sw >> X87_SW_TOP_SHIFT) + (x)) & X87_SW_TOP_MASK) |
| 76 | | #define ST(x) (m_x87_reg[ST_TO_PHYS(x)]) |
| 77 | | #define X87_TW_FIELD_SHIFT(x) ((x) << 1) |
| 78 | | #define X87_TAG(x) ((m_x87_tw >> X87_TW_FIELD_SHIFT(x)) & X87_TW_MASK) |
| 79 | | #define X87_RC ((m_x87_cw >> X87_CW_RC_SHIFT) & X87_CW_RC_MASK) |
| 80 | | #define X87_IS_ST_EMPTY(x) (X87_TAG(ST_TO_PHYS(x)) == X87_TW_EMPTY) |
| 81 | | #define X87_SW_C3_0 X87_SW_C0 |
| 82 | | |
| 83 | | #define UNIMPLEMENTED fatalerror("Unimplemented x87 op: %s (PC:%x)\n", __FUNCTION__, m_pc) |
| 84 | | |
| 85 | | |
| 86 | | /************************************* |
| 87 | | * |
| 88 | | * Constants |
| 89 | | * |
| 90 | | *************************************/ |
| 91 | | |
| 92 | | static const floatx80 fx80_zero = { 0x0000, U64(0x0000000000000000) }; |
| 93 | | static const floatx80 fx80_one = { 0x3fff, U64(0x8000000000000000) }; |
| 94 | | |
| 95 | | static const floatx80 fx80_ninf = { 0xffff, U64(0x8000000000000000) }; |
| 96 | | static const floatx80 fx80_inan = { 0xffff, U64(0xc000000000000000) }; |
| 97 | | |
| 98 | | /* Maps x87 round modes to SoftFloat round modes */ |
| 99 | | static const int x87_to_sf_rc[4] = |
| 100 | | { |
| 101 | | float_round_nearest_even, |
| 102 | | float_round_down, |
| 103 | | float_round_up, |
| 104 | | float_round_to_zero, |
| 105 | | }; |
| 106 | | |
| 107 | | |
| 108 | | /************************************* |
| 109 | | * |
| 110 | | * SoftFloat helpers |
| 111 | | * |
| 112 | | *************************************/ |
| 113 | | |
| 114 | | extern flag floatx80_is_nan( floatx80 a ); |
| 115 | | |
| 116 | | INLINE int floatx80_is_zero(floatx80 fx) |
| 117 | | { |
| 118 | | return (((fx.high & 0x7fff) == 0) && ((fx.low << 1) == 0)); |
| 119 | | } |
| 120 | | |
| 121 | | INLINE int floatx80_is_inf(floatx80 fx) |
| 122 | | { |
| 123 | | return (((fx.high & 0x7fff) == 0x7fff) && ((fx.low << 1) == 0)); |
| 124 | | } |
| 125 | | |
| 126 | | INLINE int floatx80_is_denormal(floatx80 fx) |
| 127 | | { |
| 128 | | return (((fx.high & 0x7fff) == 0) && |
| 129 | | ((fx.low & U64(0x8000000000000000)) == 0) && |
| 130 | | ((fx.low << 1) != 0)); |
| 131 | | } |
| 132 | | |
| 133 | | INLINE floatx80 floatx80_abs(floatx80 fx) |
| 134 | | { |
| 135 | | fx.high &= 0x7fff; |
| 136 | | return fx; |
| 137 | | } |
| 138 | | |
| 139 | | INLINE double fx80_to_double(floatx80 fx) |
| 140 | | { |
| 141 | | UINT64 d = floatx80_to_float64(fx); |
| 142 | | return *(double*)&d; |
| 143 | | } |
| 144 | | |
| 145 | | INLINE floatx80 double_to_fx80(double in) |
| 146 | | { |
| 147 | | return float64_to_floatx80(*(UINT64*)&in); |
| 148 | | } |
| 149 | | |
| 150 | | floatx80 i386_device::READ80(UINT32 ea) |
| 151 | | { |
| 152 | | floatx80 t; |
| 153 | | |
| 154 | | t.low = READ64(ea); |
| 155 | | t.high = READ16(ea + 8); |
| 156 | | |
| 157 | | return t; |
| 158 | | } |
| 159 | | |
| 160 | | void i386_device::WRITE80(UINT32 ea, floatx80 t) |
| 161 | | { |
| 162 | | WRITE64(ea, t.low); |
| 163 | | WRITE16(ea + 8, t.high); |
| 164 | | } |
| 165 | | |
| 166 | | |
| 167 | | /************************************* |
| 168 | | * |
| 169 | | * x87 stack handling |
| 170 | | * |
| 171 | | *************************************/ |
| 172 | | |
| 173 | | void i386_device::x87_set_stack_top(int top) |
| 174 | | { |
| 175 | | m_x87_sw &= ~(X87_SW_TOP_MASK << X87_SW_TOP_SHIFT); |
| 176 | | m_x87_sw |= (top << X87_SW_TOP_SHIFT); |
| 177 | | } |
| 178 | | |
| 179 | | void i386_device::x87_set_tag(int reg, int tag) |
| 180 | | { |
| 181 | | int shift = X87_TW_FIELD_SHIFT(reg); |
| 182 | | |
| 183 | | m_x87_tw &= ~(X87_TW_MASK << shift); |
| 184 | | m_x87_tw |= (tag << shift); |
| 185 | | } |
| 186 | | |
| 187 | | void i386_device::x87_write_stack(int i, floatx80 value, int update_tag) |
| 188 | | { |
| 189 | | ST(i) = value; |
| 190 | | |
| 191 | | if (update_tag) |
| 192 | | { |
| 193 | | int tag; |
| 194 | | |
| 195 | | if (floatx80_is_zero(value)) |
| 196 | | { |
| 197 | | tag = X87_TW_ZERO; |
| 198 | | } |
| 199 | | else if (floatx80_is_inf(value) || floatx80_is_nan(value)) |
| 200 | | { |
| 201 | | tag = X87_TW_SPECIAL; |
| 202 | | } |
| 203 | | else |
| 204 | | { |
| 205 | | tag = X87_TW_VALID; |
| 206 | | } |
| 207 | | |
| 208 | | x87_set_tag(ST_TO_PHYS(i), tag); |
| 209 | | } |
| 210 | | } |
| 211 | | |
| 212 | | void i386_device::x87_set_stack_underflow() |
| 213 | | { |
| 214 | | m_x87_sw |= X87_SW_C1 | X87_SW_IE | X87_SW_SF; |
| 215 | | } |
| 216 | | |
| 217 | | void i386_device::x87_set_stack_overflow() |
| 218 | | { |
| 219 | | m_x87_sw &= ~X87_SW_C1; |
| 220 | | m_x87_sw |= X87_SW_IE | X87_SW_SF; |
| 221 | | } |
| 222 | | |
| 223 | | int i386_device::x87_inc_stack() |
| 224 | | { |
| 225 | | int ret = 1; |
| 226 | | |
| 227 | | // Check for stack underflow |
| 228 | | if (X87_IS_ST_EMPTY(0)) |
| 229 | | { |
| 230 | | ret = 0; |
| 231 | | x87_set_stack_underflow(); |
| 232 | | |
| 233 | | // Don't update the stack if the exception is unmasked |
| 234 | | if (~m_x87_cw & X87_CW_IM) |
| 235 | | return ret; |
| 236 | | } |
| 237 | | |
| 238 | | x87_set_tag(ST_TO_PHYS(0), X87_TW_EMPTY); |
| 239 | | x87_set_stack_top(ST_TO_PHYS(1)); |
| 240 | | return ret; |
| 241 | | } |
| 242 | | |
| 243 | | int i386_device::x87_dec_stack() |
| 244 | | { |
| 245 | | int ret = 1; |
| 246 | | |
| 247 | | // Check for stack overflow |
| 248 | | if (!X87_IS_ST_EMPTY(7)) |
| 249 | | { |
| 250 | | ret = 0; |
| 251 | | x87_set_stack_overflow(); |
| 252 | | |
| 253 | | // Don't update the stack if the exception is unmasked |
| 254 | | if (~m_x87_cw & X87_CW_IM) |
| 255 | | return ret; |
| 256 | | } |
| 257 | | |
| 258 | | x87_set_stack_top(ST_TO_PHYS(7)); |
| 259 | | return ret; |
| 260 | | } |
| 261 | | |
| 262 | | |
| 263 | | /************************************* |
| 264 | | * |
| 265 | | * Exception handling |
| 266 | | * |
| 267 | | *************************************/ |
| 268 | | |
| 269 | | int i386_device::x87_check_exceptions() |
| 270 | | { |
| 271 | | /* Update the exceptions from SoftFloat */ |
| 272 | | if (float_exception_flags & float_flag_invalid) |
| 273 | | { |
| 274 | | m_x87_sw |= X87_SW_IE; |
| 275 | | float_exception_flags &= ~float_flag_invalid; |
| 276 | | } |
| 277 | | if (float_exception_flags & float_flag_overflow) |
| 278 | | { |
| 279 | | m_x87_sw |= X87_SW_OE; |
| 280 | | float_exception_flags &= ~float_flag_overflow; |
| 281 | | } |
| 282 | | if (float_exception_flags & float_flag_underflow) |
| 283 | | { |
| 284 | | m_x87_sw |= X87_SW_UE; |
| 285 | | float_exception_flags &= ~float_flag_underflow; |
| 286 | | } |
| 287 | | if (float_exception_flags & float_flag_inexact) |
| 288 | | { |
| 289 | | m_x87_sw |= X87_SW_PE; |
| 290 | | float_exception_flags &= ~float_flag_inexact; |
| 291 | | } |
| 292 | | |
| 293 | | if ((m_x87_sw & ~m_x87_cw) & 0x3f) |
| 294 | | { |
| 295 | | // m_device->execute().set_input_line(INPUT_LINE_FERR, RAISE_LINE); |
| 296 | | logerror("Unmasked x87 exception (CW:%.4x, SW:%.4x)\n", m_x87_cw, m_x87_sw); |
| 297 | | if (m_cr[0] & 0x20) // FIXME: 486 and up only |
| 298 | | { |
| 299 | | m_ext = 1; |
| 300 | | i386_trap(FAULT_MF, 0, 0); |
| 301 | | } |
| 302 | | return 0; |
| 303 | | } |
| 304 | | |
| 305 | | return 1; |
| 306 | | } |
| 307 | | |
| 308 | | void i386_device::x87_write_cw(UINT16 cw) |
| 309 | | { |
| 310 | | m_x87_cw = cw; |
| 311 | | |
| 312 | | /* Update the SoftFloat rounding mode */ |
| 313 | | float_rounding_mode = x87_to_sf_rc[(m_x87_cw >> X87_CW_RC_SHIFT) & X87_CW_RC_MASK]; |
| 314 | | } |
| 315 | | |
| 316 | | void i386_device::x87_reset() |
| 317 | | { |
| 318 | | x87_write_cw(0x0037f); |
| 319 | | |
| 320 | | m_x87_sw = 0; |
| 321 | | m_x87_tw = 0xffff; |
| 322 | | |
| 323 | | // TODO: FEA=0, FDS=0, FIP=0 FOP=0 FCS=0 |
| 324 | | m_x87_data_ptr = 0; |
| 325 | | m_x87_inst_ptr = 0; |
| 326 | | m_x87_opcode = 0; |
| 327 | | } |
| 328 | | |
| 329 | | |
| 330 | | /************************************* |
| 331 | | * |
| 332 | | * Core arithmetic |
| 333 | | * |
| 334 | | *************************************/ |
| 335 | | |
| 336 | | floatx80 i386_device::x87_add(floatx80 a, floatx80 b) |
| 337 | | { |
| 338 | | floatx80 result = { 0 }; |
| 339 | | |
| 340 | | switch ((m_x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK) |
| 341 | | { |
| 342 | | case X87_CW_PC_SINGLE: |
| 343 | | { |
| 344 | | float32 a32 = floatx80_to_float32(a); |
| 345 | | float32 b32 = floatx80_to_float32(b); |
| 346 | | result = float32_to_floatx80(float32_add(a32, b32)); |
| 347 | | break; |
| 348 | | } |
| 349 | | case X87_CW_PC_DOUBLE: |
| 350 | | { |
| 351 | | float64 a64 = floatx80_to_float64(a); |
| 352 | | float64 b64 = floatx80_to_float64(b); |
| 353 | | result = float64_to_floatx80(float64_add(a64, b64)); |
| 354 | | break; |
| 355 | | } |
| 356 | | case X87_CW_PC_EXTEND: |
| 357 | | { |
| 358 | | result = floatx80_add(a, b); |
| 359 | | break; |
| 360 | | } |
| 361 | | } |
| 362 | | |
| 363 | | return result; |
| 364 | | } |
| 365 | | |
| 366 | | floatx80 i386_device::x87_sub(floatx80 a, floatx80 b) |
| 367 | | { |
| 368 | | floatx80 result = { 0 }; |
| 369 | | |
| 370 | | switch ((m_x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK) |
| 371 | | { |
| 372 | | case X87_CW_PC_SINGLE: |
| 373 | | { |
| 374 | | float32 a32 = floatx80_to_float32(a); |
| 375 | | float32 b32 = floatx80_to_float32(b); |
| 376 | | result = float32_to_floatx80(float32_sub(a32, b32)); |
| 377 | | break; |
| 378 | | } |
| 379 | | case X87_CW_PC_DOUBLE: |
| 380 | | { |
| 381 | | float64 a64 = floatx80_to_float64(a); |
| 382 | | float64 b64 = floatx80_to_float64(b); |
| 383 | | result = float64_to_floatx80(float64_sub(a64, b64)); |
| 384 | | break; |
| 385 | | } |
| 386 | | case X87_CW_PC_EXTEND: |
| 387 | | { |
| 388 | | result = floatx80_sub(a, b); |
| 389 | | break; |
| 390 | | } |
| 391 | | } |
| 392 | | |
| 393 | | return result; |
| 394 | | } |
| 395 | | |
| 396 | | floatx80 i386_device::x87_mul(floatx80 a, floatx80 b) |
| 397 | | { |
| 398 | | floatx80 val = { 0 }; |
| 399 | | |
| 400 | | switch ((m_x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK) |
| 401 | | { |
| 402 | | case X87_CW_PC_SINGLE: |
| 403 | | { |
| 404 | | float32 a32 = floatx80_to_float32(a); |
| 405 | | float32 b32 = floatx80_to_float32(b); |
| 406 | | val = float32_to_floatx80(float32_mul(a32, b32)); |
| 407 | | break; |
| 408 | | } |
| 409 | | case X87_CW_PC_DOUBLE: |
| 410 | | { |
| 411 | | float64 a64 = floatx80_to_float64(a); |
| 412 | | float64 b64 = floatx80_to_float64(b); |
| 413 | | val = float64_to_floatx80(float64_mul(a64, b64)); |
| 414 | | break; |
| 415 | | } |
| 416 | | case X87_CW_PC_EXTEND: |
| 417 | | { |
| 418 | | val = floatx80_mul(a, b); |
| 419 | | break; |
| 420 | | } |
| 421 | | } |
| 422 | | |
| 423 | | return val; |
| 424 | | } |
| 425 | | |
| 426 | | |
| 427 | | floatx80 i386_device::x87_div(floatx80 a, floatx80 b) |
| 428 | | { |
| 429 | | floatx80 val = { 0 }; |
| 430 | | |
| 431 | | switch ((m_x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK) |
| 432 | | { |
| 433 | | case X87_CW_PC_SINGLE: |
| 434 | | { |
| 435 | | float32 a32 = floatx80_to_float32(a); |
| 436 | | float32 b32 = floatx80_to_float32(b); |
| 437 | | val = float32_to_floatx80(float32_div(a32, b32)); |
| 438 | | break; |
| 439 | | } |
| 440 | | case X87_CW_PC_DOUBLE: |
| 441 | | { |
| 442 | | float64 a64 = floatx80_to_float64(a); |
| 443 | | float64 b64 = floatx80_to_float64(b); |
| 444 | | val = float64_to_floatx80(float64_div(a64, b64)); |
| 445 | | break; |
| 446 | | } |
| 447 | | case X87_CW_PC_EXTEND: |
| 448 | | { |
| 449 | | val = floatx80_div(a, b); |
| 450 | | break; |
| 451 | | } |
| 452 | | } |
| 453 | | return val; |
| 454 | | } |
| 455 | | |
| 456 | | |
| 457 | | /************************************* |
| 458 | | * |
| 459 | | * Instructions |
| 460 | | * |
| 461 | | *************************************/ |
| 462 | | |
| 463 | | /************************************* |
| 464 | | * |
| 465 | | * Add |
| 466 | | * |
| 467 | | *************************************/ |
| 468 | | |
| 469 | | void i386_device::x87_fadd_m32real(UINT8 modrm) |
| 470 | | { |
| 471 | | floatx80 result; |
| 472 | | |
| 473 | | UINT32 ea = GetEA(modrm, 0); |
| 474 | | if (X87_IS_ST_EMPTY(0)) |
| 475 | | { |
| 476 | | x87_set_stack_underflow(); |
| 477 | | result = fx80_inan; |
| 478 | | } |
| 479 | | else |
| 480 | | { |
| 481 | | UINT32 m32real = READ32(ea); |
| 482 | | |
| 483 | | floatx80 a = ST(0); |
| 484 | | floatx80 b = float32_to_floatx80(m32real); |
| 485 | | |
| 486 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 487 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 488 | | { |
| 489 | | m_x87_sw |= X87_SW_IE; |
| 490 | | result = fx80_inan; |
| 491 | | } |
| 492 | | else |
| 493 | | { |
| 494 | | result = x87_add(a, b); |
| 495 | | } |
| 496 | | } |
| 497 | | |
| 498 | | if (x87_check_exceptions()) |
| 499 | | x87_write_stack(0, result, TRUE); |
| 500 | | |
| 501 | | CYCLES(8); |
| 502 | | } |
| 503 | | |
| 504 | | void i386_device::x87_fadd_m64real(UINT8 modrm) |
| 505 | | { |
| 506 | | floatx80 result; |
| 507 | | |
| 508 | | UINT32 ea = GetEA(modrm, 0); |
| 509 | | if (X87_IS_ST_EMPTY(0)) |
| 510 | | { |
| 511 | | x87_set_stack_underflow(); |
| 512 | | result = fx80_inan; |
| 513 | | } |
| 514 | | else |
| 515 | | { |
| 516 | | UINT64 m64real = READ64(ea); |
| 517 | | |
| 518 | | floatx80 a = ST(0); |
| 519 | | floatx80 b = float64_to_floatx80(m64real); |
| 520 | | |
| 521 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 522 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 523 | | { |
| 524 | | m_x87_sw |= X87_SW_IE; |
| 525 | | result = fx80_inan; |
| 526 | | } |
| 527 | | else |
| 528 | | { |
| 529 | | result = x87_add(a, b); |
| 530 | | } |
| 531 | | } |
| 532 | | |
| 533 | | if (x87_check_exceptions()) |
| 534 | | x87_write_stack(0, result, TRUE); |
| 535 | | |
| 536 | | CYCLES(8); |
| 537 | | } |
| 538 | | |
| 539 | | void i386_device::x87_fadd_st_sti(UINT8 modrm) |
| 540 | | { |
| 541 | | floatx80 result; |
| 542 | | int i = modrm & 7; |
| 543 | | |
| 544 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 545 | | { |
| 546 | | x87_set_stack_underflow(); |
| 547 | | result = fx80_inan; |
| 548 | | } |
| 549 | | else |
| 550 | | { |
| 551 | | floatx80 a = ST(0); |
| 552 | | floatx80 b = ST(i); |
| 553 | | |
| 554 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 555 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 556 | | { |
| 557 | | m_x87_sw |= X87_SW_IE; |
| 558 | | result = fx80_inan; |
| 559 | | } |
| 560 | | else |
| 561 | | { |
| 562 | | result = x87_add(a, b); |
| 563 | | } |
| 564 | | } |
| 565 | | |
| 566 | | if (x87_check_exceptions()) |
| 567 | | x87_write_stack(0, result, TRUE); |
| 568 | | |
| 569 | | CYCLES(8); |
| 570 | | } |
| 571 | | |
| 572 | | void i386_device::x87_fadd_sti_st(UINT8 modrm) |
| 573 | | { |
| 574 | | floatx80 result; |
| 575 | | int i = modrm & 7; |
| 576 | | |
| 577 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 578 | | { |
| 579 | | x87_set_stack_underflow(); |
| 580 | | result = fx80_inan; |
| 581 | | } |
| 582 | | else |
| 583 | | { |
| 584 | | floatx80 a = ST(0); |
| 585 | | floatx80 b = ST(i); |
| 586 | | |
| 587 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 588 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 589 | | { |
| 590 | | m_x87_sw |= X87_SW_IE; |
| 591 | | result = fx80_inan; |
| 592 | | } |
| 593 | | else |
| 594 | | { |
| 595 | | result = x87_add(a, b); |
| 596 | | } |
| 597 | | } |
| 598 | | |
| 599 | | if (x87_check_exceptions()) |
| 600 | | x87_write_stack(i, result, TRUE); |
| 601 | | |
| 602 | | CYCLES(8); |
| 603 | | } |
| 604 | | |
| 605 | | void i386_device::x87_faddp(UINT8 modrm) |
| 606 | | { |
| 607 | | floatx80 result; |
| 608 | | int i = modrm & 7; |
| 609 | | |
| 610 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 611 | | { |
| 612 | | x87_set_stack_underflow(); |
| 613 | | result = fx80_inan; |
| 614 | | } |
| 615 | | else |
| 616 | | { |
| 617 | | floatx80 a = ST(0); |
| 618 | | floatx80 b = ST(i); |
| 619 | | |
| 620 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 621 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 622 | | { |
| 623 | | m_x87_sw |= X87_SW_IE; |
| 624 | | result = fx80_inan; |
| 625 | | } |
| 626 | | else |
| 627 | | { |
| 628 | | result = x87_add(a, b); |
| 629 | | } |
| 630 | | } |
| 631 | | |
| 632 | | if (x87_check_exceptions()) |
| 633 | | { |
| 634 | | x87_write_stack(i, result, TRUE); |
| 635 | | x87_inc_stack(); |
| 636 | | } |
| 637 | | |
| 638 | | CYCLES(8); |
| 639 | | } |
| 640 | | |
| 641 | | void i386_device::x87_fiadd_m32int(UINT8 modrm) |
| 642 | | { |
| 643 | | floatx80 result; |
| 644 | | |
| 645 | | UINT32 ea = GetEA(modrm, 0); |
| 646 | | if (X87_IS_ST_EMPTY(0)) |
| 647 | | { |
| 648 | | x87_set_stack_underflow(); |
| 649 | | result = fx80_inan; |
| 650 | | } |
| 651 | | else |
| 652 | | { |
| 653 | | INT32 m32int = READ32(ea); |
| 654 | | |
| 655 | | floatx80 a = ST(0); |
| 656 | | floatx80 b = int32_to_floatx80(m32int); |
| 657 | | |
| 658 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 659 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 660 | | { |
| 661 | | m_x87_sw |= X87_SW_IE; |
| 662 | | result = fx80_inan; |
| 663 | | } |
| 664 | | else |
| 665 | | { |
| 666 | | result = x87_add(a, b); |
| 667 | | } |
| 668 | | } |
| 669 | | |
| 670 | | if (x87_check_exceptions()) |
| 671 | | x87_write_stack(0, result, TRUE); |
| 672 | | |
| 673 | | CYCLES(19); |
| 674 | | } |
| 675 | | |
| 676 | | void i386_device::x87_fiadd_m16int(UINT8 modrm) |
| 677 | | { |
| 678 | | floatx80 result; |
| 679 | | |
| 680 | | UINT32 ea = GetEA(modrm, 0); |
| 681 | | if (X87_IS_ST_EMPTY(0)) |
| 682 | | { |
| 683 | | x87_set_stack_underflow(); |
| 684 | | result = fx80_inan; |
| 685 | | } |
| 686 | | else |
| 687 | | { |
| 688 | | INT16 m16int = READ16(ea); |
| 689 | | |
| 690 | | floatx80 a = ST(0); |
| 691 | | floatx80 b = int32_to_floatx80(m16int); |
| 692 | | |
| 693 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 694 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 695 | | { |
| 696 | | m_x87_sw |= X87_SW_IE; |
| 697 | | result = fx80_inan; |
| 698 | | } |
| 699 | | else |
| 700 | | { |
| 701 | | result = x87_add(a, b); |
| 702 | | } |
| 703 | | } |
| 704 | | |
| 705 | | if (x87_check_exceptions()) |
| 706 | | x87_write_stack(0, result, TRUE); |
| 707 | | |
| 708 | | CYCLES(20); |
| 709 | | } |
| 710 | | |
| 711 | | |
| 712 | | /************************************* |
| 713 | | * |
| 714 | | * Subtract |
| 715 | | * |
| 716 | | *************************************/ |
| 717 | | |
| 718 | | void i386_device::x87_fsub_m32real(UINT8 modrm) |
| 719 | | { |
| 720 | | floatx80 result; |
| 721 | | |
| 722 | | UINT32 ea = GetEA(modrm, 0); |
| 723 | | if (X87_IS_ST_EMPTY(0)) |
| 724 | | { |
| 725 | | x87_set_stack_underflow(); |
| 726 | | result = fx80_inan; |
| 727 | | } |
| 728 | | else |
| 729 | | { |
| 730 | | UINT32 m32real = READ32(ea); |
| 731 | | |
| 732 | | floatx80 a = ST(0); |
| 733 | | floatx80 b = float32_to_floatx80(m32real); |
| 734 | | |
| 735 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 736 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 737 | | { |
| 738 | | m_x87_sw |= X87_SW_IE; |
| 739 | | result = fx80_inan; |
| 740 | | } |
| 741 | | else |
| 742 | | { |
| 743 | | result = x87_sub(a, b); |
| 744 | | } |
| 745 | | } |
| 746 | | |
| 747 | | if (x87_check_exceptions()) |
| 748 | | x87_write_stack(0, result, TRUE); |
| 749 | | |
| 750 | | CYCLES(8); |
| 751 | | } |
| 752 | | |
| 753 | | void i386_device::x87_fsub_m64real(UINT8 modrm) |
| 754 | | { |
| 755 | | floatx80 result; |
| 756 | | |
| 757 | | UINT32 ea = GetEA(modrm, 0); |
| 758 | | if (X87_IS_ST_EMPTY(0)) |
| 759 | | { |
| 760 | | x87_set_stack_underflow(); |
| 761 | | result = fx80_inan; |
| 762 | | } |
| 763 | | else |
| 764 | | { |
| 765 | | UINT64 m64real = READ64(ea); |
| 766 | | |
| 767 | | floatx80 a = ST(0); |
| 768 | | floatx80 b = float64_to_floatx80(m64real); |
| 769 | | |
| 770 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 771 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 772 | | { |
| 773 | | m_x87_sw |= X87_SW_IE; |
| 774 | | result = fx80_inan; |
| 775 | | } |
| 776 | | else |
| 777 | | { |
| 778 | | result = x87_sub(a, b); |
| 779 | | } |
| 780 | | } |
| 781 | | |
| 782 | | if (x87_check_exceptions()) |
| 783 | | x87_write_stack(0, result, TRUE); |
| 784 | | |
| 785 | | CYCLES(8); |
| 786 | | } |
| 787 | | |
| 788 | | void i386_device::x87_fsub_st_sti(UINT8 modrm) |
| 789 | | { |
| 790 | | floatx80 result; |
| 791 | | int i = modrm & 7; |
| 792 | | |
| 793 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 794 | | { |
| 795 | | x87_set_stack_underflow(); |
| 796 | | result = fx80_inan; |
| 797 | | } |
| 798 | | else |
| 799 | | { |
| 800 | | floatx80 a = ST(0); |
| 801 | | floatx80 b = ST(i); |
| 802 | | |
| 803 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 804 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 805 | | { |
| 806 | | m_x87_sw |= X87_SW_IE; |
| 807 | | result = fx80_inan; |
| 808 | | } |
| 809 | | else |
| 810 | | { |
| 811 | | result = x87_sub(a, b); |
| 812 | | } |
| 813 | | } |
| 814 | | |
| 815 | | if (x87_check_exceptions()) |
| 816 | | x87_write_stack(0, result, TRUE); |
| 817 | | |
| 818 | | CYCLES(8); |
| 819 | | } |
| 820 | | |
| 821 | | void i386_device::x87_fsub_sti_st(UINT8 modrm) |
| 822 | | { |
| 823 | | floatx80 result; |
| 824 | | int i = modrm & 7; |
| 825 | | |
| 826 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 827 | | { |
| 828 | | x87_set_stack_underflow(); |
| 829 | | result = fx80_inan; |
| 830 | | } |
| 831 | | else |
| 832 | | { |
| 833 | | floatx80 a = ST(i); |
| 834 | | floatx80 b = ST(0); |
| 835 | | |
| 836 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 837 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 838 | | { |
| 839 | | m_x87_sw |= X87_SW_IE; |
| 840 | | result = fx80_inan; |
| 841 | | } |
| 842 | | else |
| 843 | | { |
| 844 | | result = x87_sub(a, b); |
| 845 | | } |
| 846 | | } |
| 847 | | |
| 848 | | if (x87_check_exceptions()) |
| 849 | | x87_write_stack(i, result, TRUE); |
| 850 | | |
| 851 | | CYCLES(8); |
| 852 | | } |
| 853 | | |
| 854 | | void i386_device::x87_fsubp(UINT8 modrm) |
| 855 | | { |
| 856 | | floatx80 result; |
| 857 | | int i = modrm & 7; |
| 858 | | |
| 859 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 860 | | { |
| 861 | | x87_set_stack_underflow(); |
| 862 | | result = fx80_inan; |
| 863 | | } |
| 864 | | else |
| 865 | | { |
| 866 | | floatx80 a = ST(i); |
| 867 | | floatx80 b = ST(0); |
| 868 | | |
| 869 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 870 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 871 | | { |
| 872 | | m_x87_sw |= X87_SW_IE; |
| 873 | | result = fx80_inan; |
| 874 | | } |
| 875 | | else |
| 876 | | { |
| 877 | | result = x87_sub(a, b); |
| 878 | | } |
| 879 | | } |
| 880 | | |
| 881 | | if (x87_check_exceptions()) |
| 882 | | { |
| 883 | | x87_write_stack(i, result, TRUE); |
| 884 | | x87_inc_stack(); |
| 885 | | } |
| 886 | | |
| 887 | | CYCLES(8); |
| 888 | | } |
| 889 | | |
| 890 | | void i386_device::x87_fisub_m32int(UINT8 modrm) |
| 891 | | { |
| 892 | | floatx80 result; |
| 893 | | |
| 894 | | UINT32 ea = GetEA(modrm, 0); |
| 895 | | if (X87_IS_ST_EMPTY(0)) |
| 896 | | { |
| 897 | | x87_set_stack_underflow(); |
| 898 | | result = fx80_inan; |
| 899 | | } |
| 900 | | else |
| 901 | | { |
| 902 | | INT32 m32int = READ32(ea); |
| 903 | | |
| 904 | | floatx80 a = ST(0); |
| 905 | | floatx80 b = int32_to_floatx80(m32int); |
| 906 | | |
| 907 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 908 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 909 | | { |
| 910 | | m_x87_sw |= X87_SW_IE; |
| 911 | | result = fx80_inan; |
| 912 | | } |
| 913 | | else |
| 914 | | { |
| 915 | | result = x87_sub(a, b); |
| 916 | | } |
| 917 | | } |
| 918 | | |
| 919 | | if (x87_check_exceptions()) |
| 920 | | x87_write_stack(0, result, TRUE); |
| 921 | | |
| 922 | | CYCLES(19); |
| 923 | | } |
| 924 | | |
| 925 | | void i386_device::x87_fisub_m16int(UINT8 modrm) |
| 926 | | { |
| 927 | | floatx80 result; |
| 928 | | |
| 929 | | UINT32 ea = GetEA(modrm, 0); |
| 930 | | if (X87_IS_ST_EMPTY(0)) |
| 931 | | { |
| 932 | | x87_set_stack_underflow(); |
| 933 | | result = fx80_inan; |
| 934 | | } |
| 935 | | else |
| 936 | | { |
| 937 | | INT16 m16int = READ16(ea); |
| 938 | | |
| 939 | | floatx80 a = ST(0); |
| 940 | | floatx80 b = int32_to_floatx80(m16int); |
| 941 | | |
| 942 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 943 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 944 | | { |
| 945 | | m_x87_sw |= X87_SW_IE; |
| 946 | | result = fx80_inan; |
| 947 | | } |
| 948 | | else |
| 949 | | { |
| 950 | | result = x87_sub(a, b); |
| 951 | | } |
| 952 | | } |
| 953 | | |
| 954 | | if (x87_check_exceptions()) |
| 955 | | x87_write_stack(0, result, TRUE); |
| 956 | | |
| 957 | | CYCLES(20); |
| 958 | | } |
| 959 | | |
| 960 | | |
| 961 | | /************************************* |
| 962 | | * |
| 963 | | * Reverse Subtract |
| 964 | | * |
| 965 | | *************************************/ |
| 966 | | |
| 967 | | void i386_device::x87_fsubr_m32real(UINT8 modrm) |
| 968 | | { |
| 969 | | floatx80 result; |
| 970 | | |
| 971 | | UINT32 ea = GetEA(modrm, 0); |
| 972 | | if (X87_IS_ST_EMPTY(0)) |
| 973 | | { |
| 974 | | x87_set_stack_underflow(); |
| 975 | | result = fx80_inan; |
| 976 | | } |
| 977 | | else |
| 978 | | { |
| 979 | | UINT32 m32real = READ32(ea); |
| 980 | | |
| 981 | | floatx80 a = float32_to_floatx80(m32real); |
| 982 | | floatx80 b = ST(0); |
| 983 | | |
| 984 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 985 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 986 | | { |
| 987 | | m_x87_sw |= X87_SW_IE; |
| 988 | | result = fx80_inan; |
| 989 | | } |
| 990 | | else |
| 991 | | { |
| 992 | | result = x87_sub(a, b); |
| 993 | | } |
| 994 | | } |
| 995 | | |
| 996 | | if (x87_check_exceptions()) |
| 997 | | x87_write_stack(0, result, TRUE); |
| 998 | | |
| 999 | | CYCLES(8); |
| 1000 | | } |
| 1001 | | |
| 1002 | | void i386_device::x87_fsubr_m64real(UINT8 modrm) |
| 1003 | | { |
| 1004 | | floatx80 result; |
| 1005 | | |
| 1006 | | UINT32 ea = GetEA(modrm, 0); |
| 1007 | | if (X87_IS_ST_EMPTY(0)) |
| 1008 | | { |
| 1009 | | x87_set_stack_underflow(); |
| 1010 | | result = fx80_inan; |
| 1011 | | } |
| 1012 | | else |
| 1013 | | { |
| 1014 | | UINT64 m64real = READ64(ea); |
| 1015 | | |
| 1016 | | floatx80 a = float64_to_floatx80(m64real); |
| 1017 | | floatx80 b = ST(0); |
| 1018 | | |
| 1019 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1020 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 1021 | | { |
| 1022 | | m_x87_sw |= X87_SW_IE; |
| 1023 | | result = fx80_inan; |
| 1024 | | } |
| 1025 | | else |
| 1026 | | { |
| 1027 | | result = x87_sub(a, b); |
| 1028 | | } |
| 1029 | | } |
| 1030 | | |
| 1031 | | if (x87_check_exceptions()) |
| 1032 | | x87_write_stack(0, result, TRUE); |
| 1033 | | |
| 1034 | | CYCLES(8); |
| 1035 | | } |
| 1036 | | |
| 1037 | | void i386_device::x87_fsubr_st_sti(UINT8 modrm) |
| 1038 | | { |
| 1039 | | floatx80 result; |
| 1040 | | int i = modrm & 7; |
| 1041 | | |
| 1042 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1043 | | { |
| 1044 | | x87_set_stack_underflow(); |
| 1045 | | result = fx80_inan; |
| 1046 | | } |
| 1047 | | else |
| 1048 | | { |
| 1049 | | floatx80 a = ST(i); |
| 1050 | | floatx80 b = ST(0); |
| 1051 | | |
| 1052 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1053 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 1054 | | { |
| 1055 | | m_x87_sw |= X87_SW_IE; |
| 1056 | | result = fx80_inan; |
| 1057 | | } |
| 1058 | | else |
| 1059 | | { |
| 1060 | | result = x87_sub(a, b); |
| 1061 | | } |
| 1062 | | } |
| 1063 | | |
| 1064 | | if (x87_check_exceptions()) |
| 1065 | | x87_write_stack(0, result, TRUE); |
| 1066 | | |
| 1067 | | CYCLES(8); |
| 1068 | | } |
| 1069 | | |
| 1070 | | void i386_device::x87_fsubr_sti_st(UINT8 modrm) |
| 1071 | | { |
| 1072 | | floatx80 result; |
| 1073 | | int i = modrm & 7; |
| 1074 | | |
| 1075 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1076 | | { |
| 1077 | | x87_set_stack_underflow(); |
| 1078 | | result = fx80_inan; |
| 1079 | | } |
| 1080 | | else |
| 1081 | | { |
| 1082 | | floatx80 a = ST(0); |
| 1083 | | floatx80 b = ST(i); |
| 1084 | | |
| 1085 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1086 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 1087 | | { |
| 1088 | | m_x87_sw |= X87_SW_IE; |
| 1089 | | result = fx80_inan; |
| 1090 | | } |
| 1091 | | else |
| 1092 | | { |
| 1093 | | result = x87_sub(a, b); |
| 1094 | | } |
| 1095 | | } |
| 1096 | | |
| 1097 | | if (x87_check_exceptions()) |
| 1098 | | x87_write_stack(i, result, TRUE); |
| 1099 | | |
| 1100 | | CYCLES(8); |
| 1101 | | } |
| 1102 | | |
| 1103 | | void i386_device::x87_fsubrp(UINT8 modrm) |
| 1104 | | { |
| 1105 | | floatx80 result; |
| 1106 | | int i = modrm & 7; |
| 1107 | | |
| 1108 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1109 | | { |
| 1110 | | x87_set_stack_underflow(); |
| 1111 | | result = fx80_inan; |
| 1112 | | } |
| 1113 | | else |
| 1114 | | { |
| 1115 | | floatx80 a = ST(0); |
| 1116 | | floatx80 b = ST(i); |
| 1117 | | |
| 1118 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1119 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 1120 | | { |
| 1121 | | m_x87_sw |= X87_SW_IE; |
| 1122 | | result = fx80_inan; |
| 1123 | | } |
| 1124 | | else |
| 1125 | | { |
| 1126 | | result = x87_sub(a, b); |
| 1127 | | } |
| 1128 | | } |
| 1129 | | |
| 1130 | | if (x87_check_exceptions()) |
| 1131 | | { |
| 1132 | | x87_write_stack(i, result, TRUE); |
| 1133 | | x87_inc_stack(); |
| 1134 | | } |
| 1135 | | |
| 1136 | | CYCLES(8); |
| 1137 | | } |
| 1138 | | |
| 1139 | | void i386_device::x87_fisubr_m32int(UINT8 modrm) |
| 1140 | | { |
| 1141 | | floatx80 result; |
| 1142 | | |
| 1143 | | UINT32 ea = GetEA(modrm, 0); |
| 1144 | | if (X87_IS_ST_EMPTY(0)) |
| 1145 | | { |
| 1146 | | x87_set_stack_underflow(); |
| 1147 | | result = fx80_inan; |
| 1148 | | } |
| 1149 | | else |
| 1150 | | { |
| 1151 | | INT32 m32int = READ32(ea); |
| 1152 | | |
| 1153 | | floatx80 a = int32_to_floatx80(m32int); |
| 1154 | | floatx80 b = ST(0); |
| 1155 | | |
| 1156 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1157 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 1158 | | { |
| 1159 | | m_x87_sw |= X87_SW_IE; |
| 1160 | | result = fx80_inan; |
| 1161 | | } |
| 1162 | | else |
| 1163 | | { |
| 1164 | | result = x87_sub(a, b); |
| 1165 | | } |
| 1166 | | } |
| 1167 | | |
| 1168 | | if (x87_check_exceptions()) |
| 1169 | | x87_write_stack(0, result, TRUE); |
| 1170 | | |
| 1171 | | CYCLES(19); |
| 1172 | | } |
| 1173 | | |
| 1174 | | void i386_device::x87_fisubr_m16int(UINT8 modrm) |
| 1175 | | { |
| 1176 | | floatx80 result; |
| 1177 | | |
| 1178 | | UINT32 ea = GetEA(modrm, 0); |
| 1179 | | if (X87_IS_ST_EMPTY(0)) |
| 1180 | | { |
| 1181 | | x87_set_stack_underflow(); |
| 1182 | | result = fx80_inan; |
| 1183 | | } |
| 1184 | | else |
| 1185 | | { |
| 1186 | | INT16 m16int = READ16(ea); |
| 1187 | | |
| 1188 | | floatx80 a = int32_to_floatx80(m16int); |
| 1189 | | floatx80 b = ST(0); |
| 1190 | | |
| 1191 | | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1192 | | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 1193 | | { |
| 1194 | | m_x87_sw |= X87_SW_IE; |
| 1195 | | result = fx80_inan; |
| 1196 | | } |
| 1197 | | else |
| 1198 | | { |
| 1199 | | result = x87_sub(a, b); |
| 1200 | | } |
| 1201 | | } |
| 1202 | | |
| 1203 | | if (x87_check_exceptions()) |
| 1204 | | x87_write_stack(0, result, TRUE); |
| 1205 | | |
| 1206 | | CYCLES(20); |
| 1207 | | } |
| 1208 | | |
| 1209 | | |
| 1210 | | /************************************* |
| 1211 | | * |
| 1212 | | * Divide |
| 1213 | | * |
| 1214 | | *************************************/ |
| 1215 | | |
| 1216 | | void i386_device::x87_fdiv_m32real(UINT8 modrm) |
| 1217 | | { |
| 1218 | | floatx80 result; |
| 1219 | | |
| 1220 | | UINT32 ea = GetEA(modrm, 0); |
| 1221 | | if (X87_IS_ST_EMPTY(0)) |
| 1222 | | { |
| 1223 | | x87_set_stack_underflow(); |
| 1224 | | result = fx80_inan; |
| 1225 | | } |
| 1226 | | else |
| 1227 | | { |
| 1228 | | UINT32 m32real = READ32(ea); |
| 1229 | | |
| 1230 | | floatx80 a = ST(0); |
| 1231 | | floatx80 b = float32_to_floatx80(m32real); |
| 1232 | | |
| 1233 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1234 | | { |
| 1235 | | m_x87_sw |= X87_SW_IE; |
| 1236 | | result = fx80_inan; |
| 1237 | | } |
| 1238 | | else |
| 1239 | | { |
| 1240 | | result = x87_div(a, b); |
| 1241 | | } |
| 1242 | | } |
| 1243 | | |
| 1244 | | if (x87_check_exceptions()) |
| 1245 | | x87_write_stack(0, result, TRUE); |
| 1246 | | |
| 1247 | | // 73, 62, 35 |
| 1248 | | CYCLES(73); |
| 1249 | | } |
| 1250 | | |
| 1251 | | void i386_device::x87_fdiv_m64real(UINT8 modrm) |
| 1252 | | { |
| 1253 | | floatx80 result; |
| 1254 | | |
| 1255 | | UINT32 ea = GetEA(modrm, 0); |
| 1256 | | if (X87_IS_ST_EMPTY(0)) |
| 1257 | | { |
| 1258 | | x87_set_stack_underflow(); |
| 1259 | | result = fx80_inan; |
| 1260 | | } |
| 1261 | | else |
| 1262 | | { |
| 1263 | | UINT64 m64real = READ64(ea); |
| 1264 | | |
| 1265 | | floatx80 a = ST(0); |
| 1266 | | floatx80 b = float64_to_floatx80(m64real); |
| 1267 | | |
| 1268 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1269 | | { |
| 1270 | | m_x87_sw |= X87_SW_IE; |
| 1271 | | result = fx80_inan; |
| 1272 | | } |
| 1273 | | else |
| 1274 | | { |
| 1275 | | result = x87_div(a, b); |
| 1276 | | } |
| 1277 | | } |
| 1278 | | |
| 1279 | | if (x87_check_exceptions()) |
| 1280 | | x87_write_stack(0, result, TRUE); |
| 1281 | | |
| 1282 | | // 73, 62, 35 |
| 1283 | | CYCLES(73); |
| 1284 | | } |
| 1285 | | |
| 1286 | | void i386_device::x87_fdiv_st_sti(UINT8 modrm) |
| 1287 | | { |
| 1288 | | int i = modrm & 7; |
| 1289 | | floatx80 result; |
| 1290 | | |
| 1291 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1292 | | { |
| 1293 | | x87_set_stack_underflow(); |
| 1294 | | result = fx80_inan; |
| 1295 | | } |
| 1296 | | else |
| 1297 | | { |
| 1298 | | floatx80 a = ST(0); |
| 1299 | | floatx80 b = ST(i); |
| 1300 | | |
| 1301 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1302 | | { |
| 1303 | | m_x87_sw |= X87_SW_IE; |
| 1304 | | result = fx80_inan; |
| 1305 | | } |
| 1306 | | else |
| 1307 | | { |
| 1308 | | result = x87_div(a, b); |
| 1309 | | } |
| 1310 | | } |
| 1311 | | |
| 1312 | | if (x87_check_exceptions()) |
| 1313 | | { |
| 1314 | | x87_write_stack(0, result, TRUE); |
| 1315 | | } |
| 1316 | | |
| 1317 | | // 73, 62, 35 |
| 1318 | | CYCLES(73); |
| 1319 | | } |
| 1320 | | |
| 1321 | | void i386_device::x87_fdiv_sti_st(UINT8 modrm) |
| 1322 | | { |
| 1323 | | int i = modrm & 7; |
| 1324 | | floatx80 result; |
| 1325 | | |
| 1326 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1327 | | { |
| 1328 | | x87_set_stack_underflow(); |
| 1329 | | result = fx80_inan; |
| 1330 | | } |
| 1331 | | else |
| 1332 | | { |
| 1333 | | floatx80 a = ST(i); |
| 1334 | | floatx80 b = ST(0); |
| 1335 | | |
| 1336 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1337 | | { |
| 1338 | | m_x87_sw |= X87_SW_IE; |
| 1339 | | result = fx80_inan; |
| 1340 | | } |
| 1341 | | else |
| 1342 | | { |
| 1343 | | result = x87_div(a, b); |
| 1344 | | } |
| 1345 | | } |
| 1346 | | |
| 1347 | | if (x87_check_exceptions()) |
| 1348 | | { |
| 1349 | | x87_write_stack(i, result, TRUE); |
| 1350 | | } |
| 1351 | | |
| 1352 | | // 73, 62, 35 |
| 1353 | | CYCLES(73); |
| 1354 | | } |
| 1355 | | |
| 1356 | | void i386_device::x87_fdivp(UINT8 modrm) |
| 1357 | | { |
| 1358 | | int i = modrm & 7; |
| 1359 | | floatx80 result; |
| 1360 | | |
| 1361 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1362 | | { |
| 1363 | | x87_set_stack_underflow(); |
| 1364 | | result = fx80_inan; |
| 1365 | | } |
| 1366 | | else |
| 1367 | | { |
| 1368 | | floatx80 a = ST(i); |
| 1369 | | floatx80 b = ST(0); |
| 1370 | | |
| 1371 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1372 | | { |
| 1373 | | m_x87_sw |= X87_SW_IE; |
| 1374 | | result = fx80_inan; |
| 1375 | | } |
| 1376 | | else |
| 1377 | | { |
| 1378 | | result = x87_div(a, b); |
| 1379 | | } |
| 1380 | | } |
| 1381 | | |
| 1382 | | if (x87_check_exceptions()) |
| 1383 | | { |
| 1384 | | x87_write_stack(i, result, TRUE); |
| 1385 | | x87_inc_stack(); |
| 1386 | | } |
| 1387 | | |
| 1388 | | // 73, 62, 35 |
| 1389 | | CYCLES(73); |
| 1390 | | } |
| 1391 | | |
| 1392 | | void i386_device::x87_fidiv_m32int(UINT8 modrm) |
| 1393 | | { |
| 1394 | | floatx80 result; |
| 1395 | | |
| 1396 | | UINT32 ea = GetEA(modrm, 0); |
| 1397 | | if (X87_IS_ST_EMPTY(0)) |
| 1398 | | { |
| 1399 | | x87_set_stack_underflow(); |
| 1400 | | result = fx80_inan; |
| 1401 | | } |
| 1402 | | else |
| 1403 | | { |
| 1404 | | INT32 m32int = READ32(ea); |
| 1405 | | |
| 1406 | | floatx80 a = ST(0); |
| 1407 | | floatx80 b = int32_to_floatx80(m32int); |
| 1408 | | |
| 1409 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1410 | | { |
| 1411 | | m_x87_sw |= X87_SW_IE; |
| 1412 | | result = fx80_inan; |
| 1413 | | } |
| 1414 | | else |
| 1415 | | { |
| 1416 | | result = x87_div(a, b); |
| 1417 | | } |
| 1418 | | } |
| 1419 | | |
| 1420 | | if (x87_check_exceptions()) |
| 1421 | | x87_write_stack(0, result, TRUE); |
| 1422 | | |
| 1423 | | // 73, 62, 35 |
| 1424 | | CYCLES(73); |
| 1425 | | } |
| 1426 | | |
| 1427 | | void i386_device::x87_fidiv_m16int(UINT8 modrm) |
| 1428 | | { |
| 1429 | | floatx80 result; |
| 1430 | | |
| 1431 | | UINT32 ea = GetEA(modrm, 0); |
| 1432 | | if (X87_IS_ST_EMPTY(0)) |
| 1433 | | { |
| 1434 | | x87_set_stack_underflow(); |
| 1435 | | result = fx80_inan; |
| 1436 | | } |
| 1437 | | else |
| 1438 | | { |
| 1439 | | INT16 m16int = READ32(ea); |
| 1440 | | |
| 1441 | | floatx80 a = ST(0); |
| 1442 | | floatx80 b = int32_to_floatx80(m16int); |
| 1443 | | |
| 1444 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1445 | | { |
| 1446 | | m_x87_sw |= X87_SW_IE; |
| 1447 | | result = fx80_inan; |
| 1448 | | } |
| 1449 | | else |
| 1450 | | { |
| 1451 | | result = x87_div(a, b); |
| 1452 | | } |
| 1453 | | } |
| 1454 | | |
| 1455 | | if (x87_check_exceptions()) |
| 1456 | | x87_write_stack(0, result, TRUE); |
| 1457 | | |
| 1458 | | // 73, 62, 35 |
| 1459 | | CYCLES(73); |
| 1460 | | } |
| 1461 | | |
| 1462 | | |
| 1463 | | /************************************* |
| 1464 | | * |
| 1465 | | * Reverse Divide |
| 1466 | | * |
| 1467 | | *************************************/ |
| 1468 | | |
| 1469 | | void i386_device::x87_fdivr_m32real(UINT8 modrm) |
| 1470 | | { |
| 1471 | | floatx80 result; |
| 1472 | | |
| 1473 | | UINT32 ea = GetEA(modrm, 0); |
| 1474 | | if (X87_IS_ST_EMPTY(0)) |
| 1475 | | { |
| 1476 | | x87_set_stack_underflow(); |
| 1477 | | result = fx80_inan; |
| 1478 | | } |
| 1479 | | else |
| 1480 | | { |
| 1481 | | UINT32 m32real = READ32(ea); |
| 1482 | | |
| 1483 | | floatx80 a = float32_to_floatx80(m32real); |
| 1484 | | floatx80 b = ST(0); |
| 1485 | | |
| 1486 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1487 | | { |
| 1488 | | m_x87_sw |= X87_SW_IE; |
| 1489 | | result = fx80_inan; |
| 1490 | | } |
| 1491 | | else |
| 1492 | | { |
| 1493 | | result = x87_div(a, b); |
| 1494 | | } |
| 1495 | | } |
| 1496 | | |
| 1497 | | if (x87_check_exceptions()) |
| 1498 | | x87_write_stack(0, result, TRUE); |
| 1499 | | |
| 1500 | | // 73, 62, 35 |
| 1501 | | CYCLES(73); |
| 1502 | | } |
| 1503 | | |
| 1504 | | void i386_device::x87_fdivr_m64real(UINT8 modrm) |
| 1505 | | { |
| 1506 | | floatx80 result; |
| 1507 | | |
| 1508 | | UINT32 ea = GetEA(modrm, 0); |
| 1509 | | if (X87_IS_ST_EMPTY(0)) |
| 1510 | | { |
| 1511 | | x87_set_stack_underflow(); |
| 1512 | | result = fx80_inan; |
| 1513 | | } |
| 1514 | | else |
| 1515 | | { |
| 1516 | | UINT64 m64real = READ64(ea); |
| 1517 | | |
| 1518 | | floatx80 a = float64_to_floatx80(m64real); |
| 1519 | | floatx80 b = ST(0); |
| 1520 | | |
| 1521 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1522 | | { |
| 1523 | | m_x87_sw |= X87_SW_IE; |
| 1524 | | result = fx80_inan; |
| 1525 | | } |
| 1526 | | else |
| 1527 | | { |
| 1528 | | result = x87_div(a, b); |
| 1529 | | } |
| 1530 | | } |
| 1531 | | |
| 1532 | | if (x87_check_exceptions()) |
| 1533 | | x87_write_stack(0, result, TRUE); |
| 1534 | | |
| 1535 | | // 73, 62, 35 |
| 1536 | | CYCLES(73); |
| 1537 | | } |
| 1538 | | |
| 1539 | | void i386_device::x87_fdivr_st_sti(UINT8 modrm) |
| 1540 | | { |
| 1541 | | int i = modrm & 7; |
| 1542 | | floatx80 result; |
| 1543 | | |
| 1544 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1545 | | { |
| 1546 | | x87_set_stack_underflow(); |
| 1547 | | result = fx80_inan; |
| 1548 | | } |
| 1549 | | else |
| 1550 | | { |
| 1551 | | floatx80 a = ST(i); |
| 1552 | | floatx80 b = ST(0); |
| 1553 | | |
| 1554 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1555 | | { |
| 1556 | | m_x87_sw |= X87_SW_IE; |
| 1557 | | result = fx80_inan; |
| 1558 | | } |
| 1559 | | else |
| 1560 | | { |
| 1561 | | result = x87_div(a, b); |
| 1562 | | } |
| 1563 | | } |
| 1564 | | |
| 1565 | | if (x87_check_exceptions()) |
| 1566 | | { |
| 1567 | | x87_write_stack(0, result, TRUE); |
| 1568 | | } |
| 1569 | | |
| 1570 | | // 73, 62, 35 |
| 1571 | | CYCLES(73); |
| 1572 | | } |
| 1573 | | |
| 1574 | | void i386_device::x87_fdivr_sti_st(UINT8 modrm) |
| 1575 | | { |
| 1576 | | int i = modrm & 7; |
| 1577 | | floatx80 result; |
| 1578 | | |
| 1579 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1580 | | { |
| 1581 | | x87_set_stack_underflow(); |
| 1582 | | result = fx80_inan; |
| 1583 | | } |
| 1584 | | else |
| 1585 | | { |
| 1586 | | floatx80 a = ST(0); |
| 1587 | | floatx80 b = ST(i); |
| 1588 | | |
| 1589 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1590 | | { |
| 1591 | | m_x87_sw |= X87_SW_IE; |
| 1592 | | result = fx80_inan; |
| 1593 | | } |
| 1594 | | else |
| 1595 | | { |
| 1596 | | result = x87_div(a, b); |
| 1597 | | } |
| 1598 | | } |
| 1599 | | |
| 1600 | | if (x87_check_exceptions()) |
| 1601 | | { |
| 1602 | | x87_write_stack(i, result, TRUE); |
| 1603 | | } |
| 1604 | | |
| 1605 | | // 73, 62, 35 |
| 1606 | | CYCLES(73); |
| 1607 | | } |
| 1608 | | |
| 1609 | | void i386_device::x87_fdivrp(UINT8 modrm) |
| 1610 | | { |
| 1611 | | int i = modrm & 7; |
| 1612 | | floatx80 result; |
| 1613 | | |
| 1614 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1615 | | { |
| 1616 | | x87_set_stack_underflow(); |
| 1617 | | result = fx80_inan; |
| 1618 | | } |
| 1619 | | else |
| 1620 | | { |
| 1621 | | floatx80 a = ST(0); |
| 1622 | | floatx80 b = ST(i); |
| 1623 | | |
| 1624 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1625 | | { |
| 1626 | | m_x87_sw |= X87_SW_IE; |
| 1627 | | result = fx80_inan; |
| 1628 | | } |
| 1629 | | else |
| 1630 | | { |
| 1631 | | result = x87_div(a, b); |
| 1632 | | } |
| 1633 | | } |
| 1634 | | |
| 1635 | | if (x87_check_exceptions()) |
| 1636 | | { |
| 1637 | | x87_write_stack(i, result, TRUE); |
| 1638 | | x87_inc_stack(); |
| 1639 | | } |
| 1640 | | |
| 1641 | | // 73, 62, 35 |
| 1642 | | CYCLES(73); |
| 1643 | | } |
| 1644 | | |
| 1645 | | |
| 1646 | | void i386_device::x87_fidivr_m32int(UINT8 modrm) |
| 1647 | | { |
| 1648 | | floatx80 result; |
| 1649 | | |
| 1650 | | UINT32 ea = GetEA(modrm, 0); |
| 1651 | | if (X87_IS_ST_EMPTY(0)) |
| 1652 | | { |
| 1653 | | x87_set_stack_underflow(); |
| 1654 | | result = fx80_inan; |
| 1655 | | } |
| 1656 | | else |
| 1657 | | { |
| 1658 | | INT32 m32int = READ32(ea); |
| 1659 | | |
| 1660 | | floatx80 a = int32_to_floatx80(m32int); |
| 1661 | | floatx80 b = ST(0); |
| 1662 | | |
| 1663 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1664 | | { |
| 1665 | | m_x87_sw |= X87_SW_IE; |
| 1666 | | result = fx80_inan; |
| 1667 | | } |
| 1668 | | else |
| 1669 | | { |
| 1670 | | result = x87_div(a, b); |
| 1671 | | } |
| 1672 | | } |
| 1673 | | |
| 1674 | | if (x87_check_exceptions()) |
| 1675 | | x87_write_stack(0, result, TRUE); |
| 1676 | | |
| 1677 | | // 73, 62, 35 |
| 1678 | | CYCLES(73); |
| 1679 | | } |
| 1680 | | |
| 1681 | | void i386_device::x87_fidivr_m16int(UINT8 modrm) |
| 1682 | | { |
| 1683 | | floatx80 result; |
| 1684 | | |
| 1685 | | UINT32 ea = GetEA(modrm, 0); |
| 1686 | | if (X87_IS_ST_EMPTY(0)) |
| 1687 | | { |
| 1688 | | x87_set_stack_underflow(); |
| 1689 | | result = fx80_inan; |
| 1690 | | } |
| 1691 | | else |
| 1692 | | { |
| 1693 | | INT16 m16int = READ32(ea); |
| 1694 | | |
| 1695 | | floatx80 a = int32_to_floatx80(m16int); |
| 1696 | | floatx80 b = ST(0); |
| 1697 | | |
| 1698 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1699 | | { |
| 1700 | | m_x87_sw |= X87_SW_IE; |
| 1701 | | result = fx80_inan; |
| 1702 | | } |
| 1703 | | else |
| 1704 | | { |
| 1705 | | result = x87_div(a, b); |
| 1706 | | } |
| 1707 | | } |
| 1708 | | |
| 1709 | | if (x87_check_exceptions()) |
| 1710 | | x87_write_stack(0, result, TRUE); |
| 1711 | | |
| 1712 | | // 73, 62, 35 |
| 1713 | | CYCLES(73); |
| 1714 | | } |
| 1715 | | |
| 1716 | | |
| 1717 | | /************************************* |
| 1718 | | * |
| 1719 | | * Multiply |
| 1720 | | * |
| 1721 | | *************************************/ |
| 1722 | | |
| 1723 | | void i386_device::x87_fmul_m32real(UINT8 modrm) |
| 1724 | | { |
| 1725 | | floatx80 result; |
| 1726 | | |
| 1727 | | UINT32 ea = GetEA(modrm, 0); |
| 1728 | | if (X87_IS_ST_EMPTY(0)) |
| 1729 | | { |
| 1730 | | x87_set_stack_underflow(); |
| 1731 | | result = fx80_inan; |
| 1732 | | } |
| 1733 | | else |
| 1734 | | { |
| 1735 | | UINT32 m32real = READ32(ea); |
| 1736 | | |
| 1737 | | floatx80 a = ST(0); |
| 1738 | | floatx80 b = float32_to_floatx80(m32real); |
| 1739 | | |
| 1740 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1741 | | { |
| 1742 | | m_x87_sw |= X87_SW_IE; |
| 1743 | | result = fx80_inan; |
| 1744 | | } |
| 1745 | | else |
| 1746 | | { |
| 1747 | | result = x87_mul(a, b); |
| 1748 | | } |
| 1749 | | } |
| 1750 | | |
| 1751 | | if (x87_check_exceptions()) |
| 1752 | | x87_write_stack(0, result, TRUE); |
| 1753 | | |
| 1754 | | CYCLES(11); |
| 1755 | | } |
| 1756 | | |
| 1757 | | void i386_device::x87_fmul_m64real(UINT8 modrm) |
| 1758 | | { |
| 1759 | | floatx80 result; |
| 1760 | | |
| 1761 | | UINT32 ea = GetEA(modrm, 0); |
| 1762 | | if (X87_IS_ST_EMPTY(0)) |
| 1763 | | { |
| 1764 | | x87_set_stack_underflow(); |
| 1765 | | result = fx80_inan; |
| 1766 | | } |
| 1767 | | else |
| 1768 | | { |
| 1769 | | UINT64 m64real = READ64(ea); |
| 1770 | | |
| 1771 | | floatx80 a = ST(0); |
| 1772 | | floatx80 b = float64_to_floatx80(m64real); |
| 1773 | | |
| 1774 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1775 | | { |
| 1776 | | m_x87_sw |= X87_SW_IE; |
| 1777 | | result = fx80_inan; |
| 1778 | | } |
| 1779 | | else |
| 1780 | | { |
| 1781 | | result = x87_mul(a, b); |
| 1782 | | } |
| 1783 | | } |
| 1784 | | |
| 1785 | | if (x87_check_exceptions()) |
| 1786 | | x87_write_stack(0, result, TRUE); |
| 1787 | | |
| 1788 | | CYCLES(14); |
| 1789 | | } |
| 1790 | | |
| 1791 | | void i386_device::x87_fmul_st_sti(UINT8 modrm) |
| 1792 | | { |
| 1793 | | floatx80 result; |
| 1794 | | int i = modrm & 7; |
| 1795 | | |
| 1796 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1797 | | { |
| 1798 | | x87_set_stack_underflow(); |
| 1799 | | result = fx80_inan; |
| 1800 | | } |
| 1801 | | else |
| 1802 | | { |
| 1803 | | floatx80 a = ST(0); |
| 1804 | | floatx80 b = ST(i); |
| 1805 | | |
| 1806 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1807 | | { |
| 1808 | | m_x87_sw |= X87_SW_IE; |
| 1809 | | result = fx80_inan; |
| 1810 | | } |
| 1811 | | else |
| 1812 | | { |
| 1813 | | result = x87_mul(a, b); |
| 1814 | | } |
| 1815 | | } |
| 1816 | | |
| 1817 | | if (x87_check_exceptions()) |
| 1818 | | x87_write_stack(0, result, TRUE); |
| 1819 | | |
| 1820 | | CYCLES(16); |
| 1821 | | } |
| 1822 | | |
| 1823 | | void i386_device::x87_fmul_sti_st(UINT8 modrm) |
| 1824 | | { |
| 1825 | | floatx80 result; |
| 1826 | | int i = modrm & 7; |
| 1827 | | |
| 1828 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1829 | | { |
| 1830 | | x87_set_stack_underflow(); |
| 1831 | | result = fx80_inan; |
| 1832 | | } |
| 1833 | | else |
| 1834 | | { |
| 1835 | | floatx80 a = ST(0); |
| 1836 | | floatx80 b = ST(i); |
| 1837 | | |
| 1838 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1839 | | { |
| 1840 | | m_x87_sw |= X87_SW_IE; |
| 1841 | | result = fx80_inan; |
| 1842 | | } |
| 1843 | | else |
| 1844 | | { |
| 1845 | | result = x87_mul(a, b); |
| 1846 | | } |
| 1847 | | } |
| 1848 | | |
| 1849 | | if (x87_check_exceptions()) |
| 1850 | | x87_write_stack(i, result, TRUE); |
| 1851 | | |
| 1852 | | CYCLES(16); |
| 1853 | | } |
| 1854 | | |
| 1855 | | void i386_device::x87_fmulp(UINT8 modrm) |
| 1856 | | { |
| 1857 | | floatx80 result; |
| 1858 | | int i = modrm & 7; |
| 1859 | | |
| 1860 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1861 | | { |
| 1862 | | x87_set_stack_underflow(); |
| 1863 | | result = fx80_inan; |
| 1864 | | } |
| 1865 | | else |
| 1866 | | { |
| 1867 | | floatx80 a = ST(0); |
| 1868 | | floatx80 b = ST(i); |
| 1869 | | |
| 1870 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1871 | | { |
| 1872 | | m_x87_sw |= X87_SW_IE; |
| 1873 | | result = fx80_inan; |
| 1874 | | } |
| 1875 | | else |
| 1876 | | { |
| 1877 | | result = x87_mul(a, b); |
| 1878 | | } |
| 1879 | | } |
| 1880 | | |
| 1881 | | if (x87_check_exceptions()) |
| 1882 | | { |
| 1883 | | x87_write_stack(i, result, TRUE); |
| 1884 | | x87_inc_stack(); |
| 1885 | | } |
| 1886 | | |
| 1887 | | CYCLES(16); |
| 1888 | | } |
| 1889 | | |
| 1890 | | void i386_device::x87_fimul_m32int(UINT8 modrm) |
| 1891 | | { |
| 1892 | | floatx80 result; |
| 1893 | | |
| 1894 | | UINT32 ea = GetEA(modrm, 0); |
| 1895 | | if (X87_IS_ST_EMPTY(0)) |
| 1896 | | { |
| 1897 | | x87_set_stack_underflow(); |
| 1898 | | result = fx80_inan; |
| 1899 | | } |
| 1900 | | else |
| 1901 | | { |
| 1902 | | INT32 m32int = READ32(ea); |
| 1903 | | |
| 1904 | | floatx80 a = ST(0); |
| 1905 | | floatx80 b = int32_to_floatx80(m32int); |
| 1906 | | |
| 1907 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1908 | | { |
| 1909 | | m_x87_sw |= X87_SW_IE; |
| 1910 | | result = fx80_inan; |
| 1911 | | } |
| 1912 | | else |
| 1913 | | { |
| 1914 | | result = x87_mul(a, b); |
| 1915 | | } |
| 1916 | | } |
| 1917 | | |
| 1918 | | if (x87_check_exceptions()) |
| 1919 | | x87_write_stack(0, result, TRUE); |
| 1920 | | |
| 1921 | | CYCLES(22); |
| 1922 | | } |
| 1923 | | |
| 1924 | | void i386_device::x87_fimul_m16int(UINT8 modrm) |
| 1925 | | { |
| 1926 | | floatx80 result; |
| 1927 | | |
| 1928 | | UINT32 ea = GetEA(modrm, 0); |
| 1929 | | if (X87_IS_ST_EMPTY(0)) |
| 1930 | | { |
| 1931 | | x87_set_stack_underflow(); |
| 1932 | | result = fx80_inan; |
| 1933 | | } |
| 1934 | | else |
| 1935 | | { |
| 1936 | | INT16 m16int = READ16(ea); |
| 1937 | | |
| 1938 | | floatx80 a = ST(0); |
| 1939 | | floatx80 b = int32_to_floatx80(m16int); |
| 1940 | | |
| 1941 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1942 | | { |
| 1943 | | m_x87_sw |= X87_SW_IE; |
| 1944 | | result = fx80_inan; |
| 1945 | | } |
| 1946 | | else |
| 1947 | | { |
| 1948 | | result = x87_mul(a, b); |
| 1949 | | } |
| 1950 | | } |
| 1951 | | |
| 1952 | | if (x87_check_exceptions()) |
| 1953 | | x87_write_stack(0, result, TRUE); |
| 1954 | | |
| 1955 | | CYCLES(22); |
| 1956 | | } |
| 1957 | | |
| 1958 | | |
| 1959 | | /************************************* |
| 1960 | | * |
| 1961 | | * Miscellaneous arithmetic |
| 1962 | | * |
| 1963 | | *************************************/ |
| 1964 | | |
| 1965 | | void i386_device::x87_fprem(UINT8 modrm) |
| 1966 | | { |
| 1967 | | floatx80 result; |
| 1968 | | |
| 1969 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 1970 | | { |
| 1971 | | x87_set_stack_underflow(); |
| 1972 | | result = fx80_inan; |
| 1973 | | } |
| 1974 | | else |
| 1975 | | { |
| 1976 | | floatx80 a = ST(0); |
| 1977 | | floatx80 b = ST(1); |
| 1978 | | |
| 1979 | | m_x87_sw &= ~X87_SW_C0; |
| 1980 | | |
| 1981 | | // TODO: Implement Cx bits |
| 1982 | | result = floatx80_rem(a, b); |
| 1983 | | } |
| 1984 | | |
| 1985 | | if (x87_check_exceptions()) |
| 1986 | | x87_write_stack(0, result, TRUE); |
| 1987 | | |
| 1988 | | CYCLES(84); |
| 1989 | | } |
| 1990 | | |
| 1991 | | void i386_device::x87_fprem1(UINT8 modrm) |
| 1992 | | { |
| 1993 | | floatx80 result; |
| 1994 | | |
| 1995 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 1996 | | { |
| 1997 | | x87_set_stack_underflow(); |
| 1998 | | result = fx80_inan; |
| 1999 | | } |
| 2000 | | else |
| 2001 | | { |
| 2002 | | floatx80 a = ST(0); |
| 2003 | | floatx80 b = ST(1); |
| 2004 | | |
| 2005 | | m_x87_sw &= ~X87_SW_C0; |
| 2006 | | |
| 2007 | | // TODO: Implement Cx bits |
| 2008 | | result = floatx80_rem(a, b); |
| 2009 | | } |
| 2010 | | |
| 2011 | | if (x87_check_exceptions()) |
| 2012 | | x87_write_stack(0, result, TRUE); |
| 2013 | | |
| 2014 | | CYCLES(94); |
| 2015 | | } |
| 2016 | | |
| 2017 | | void i386_device::x87_fsqrt(UINT8 modrm) |
| 2018 | | { |
| 2019 | | floatx80 result; |
| 2020 | | |
| 2021 | | if (X87_IS_ST_EMPTY(0)) |
| 2022 | | { |
| 2023 | | x87_set_stack_underflow(); |
| 2024 | | result = fx80_inan; |
| 2025 | | } |
| 2026 | | else |
| 2027 | | { |
| 2028 | | floatx80 value = ST(0); |
| 2029 | | |
| 2030 | | if ((!floatx80_is_zero(value) && (value.high & 0x8000)) || |
| 2031 | | floatx80_is_denormal(value)) |
| 2032 | | { |
| 2033 | | m_x87_sw |= X87_SW_IE; |
| 2034 | | result = fx80_inan; |
| 2035 | | } |
| 2036 | | else |
| 2037 | | { |
| 2038 | | result = floatx80_sqrt(value); |
| 2039 | | } |
| 2040 | | } |
| 2041 | | |
| 2042 | | if (x87_check_exceptions()) |
| 2043 | | x87_write_stack(0, result, TRUE); |
| 2044 | | |
| 2045 | | CYCLES(8); |
| 2046 | | } |
| 2047 | | |
| 2048 | | /************************************* |
| 2049 | | * |
| 2050 | | * Trigonometric |
| 2051 | | * |
| 2052 | | *************************************/ |
| 2053 | | |
| 2054 | | void i386_device::x87_f2xm1(UINT8 modrm) |
| 2055 | | { |
| 2056 | | floatx80 result; |
| 2057 | | |
| 2058 | | if (X87_IS_ST_EMPTY(0)) |
| 2059 | | { |
| 2060 | | x87_set_stack_underflow(); |
| 2061 | | result = fx80_inan; |
| 2062 | | } |
| 2063 | | else |
| 2064 | | { |
| 2065 | | // TODO: Inaccurate |
| 2066 | | double x = fx80_to_double(ST(0)); |
| 2067 | | double res = pow(2.0, x) - 1; |
| 2068 | | result = double_to_fx80(res); |
| 2069 | | } |
| 2070 | | |
| 2071 | | if (x87_check_exceptions()) |
| 2072 | | { |
| 2073 | | x87_write_stack(0, result, TRUE); |
| 2074 | | } |
| 2075 | | |
| 2076 | | CYCLES(242); |
| 2077 | | } |
| 2078 | | |
| 2079 | | void i386_device::x87_fyl2x(UINT8 modrm) |
| 2080 | | { |
| 2081 | | floatx80 result; |
| 2082 | | |
| 2083 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 2084 | | { |
| 2085 | | x87_set_stack_underflow(); |
| 2086 | | result = fx80_inan; |
| 2087 | | } |
| 2088 | | else |
| 2089 | | { |
| 2090 | | floatx80 x = ST(0); |
| 2091 | | floatx80 y = ST(1); |
| 2092 | | |
| 2093 | | if (x.high & 0x8000) |
| 2094 | | { |
| 2095 | | m_x87_sw |= X87_SW_IE; |
| 2096 | | result = fx80_inan; |
| 2097 | | } |
| 2098 | | else |
| 2099 | | { |
| 2100 | | // TODO: Inaccurate |
| 2101 | | double d64 = fx80_to_double(x); |
| 2102 | | double l2x = log(d64)/log(2.0); |
| 2103 | | result = floatx80_mul(double_to_fx80(l2x), y); |
| 2104 | | } |
| 2105 | | } |
| 2106 | | |
| 2107 | | if (x87_check_exceptions()) |
| 2108 | | { |
| 2109 | | x87_write_stack(1, result, TRUE); |
| 2110 | | x87_inc_stack(); |
| 2111 | | } |
| 2112 | | |
| 2113 | | CYCLES(250); |
| 2114 | | } |
| 2115 | | |
| 2116 | | void i386_device::x87_fyl2xp1(UINT8 modrm) |
| 2117 | | { |
| 2118 | | floatx80 result; |
| 2119 | | |
| 2120 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 2121 | | { |
| 2122 | | x87_set_stack_underflow(); |
| 2123 | | result = fx80_inan; |
| 2124 | | } |
| 2125 | | else |
| 2126 | | { |
| 2127 | | floatx80 x = ST(0); |
| 2128 | | floatx80 y = ST(1); |
| 2129 | | |
| 2130 | | // TODO: Inaccurate |
| 2131 | | double d64 = fx80_to_double(x); |
| 2132 | | double l2x1 = log(d64 + 1.0)/log(2.0); |
| 2133 | | result = floatx80_mul(double_to_fx80(l2x1), y); |
| 2134 | | } |
| 2135 | | |
| 2136 | | if (x87_check_exceptions()) |
| 2137 | | { |
| 2138 | | x87_write_stack(1, result, TRUE); |
| 2139 | | x87_inc_stack(); |
| 2140 | | } |
| 2141 | | |
| 2142 | | CYCLES(313); |
| 2143 | | } |
| 2144 | | |
| 2145 | | void i386_device::x87_fptan(UINT8 modrm) |
| 2146 | | { |
| 2147 | | floatx80 result1, result2; |
| 2148 | | |
| 2149 | | if (X87_IS_ST_EMPTY(0)) |
| 2150 | | { |
| 2151 | | x87_set_stack_underflow(); |
| 2152 | | result1 = fx80_inan; |
| 2153 | | result2 = fx80_inan; |
| 2154 | | } |
| 2155 | | else if (!X87_IS_ST_EMPTY(7)) |
| 2156 | | { |
| 2157 | | x87_set_stack_overflow(); |
| 2158 | | result1 = fx80_inan; |
| 2159 | | result2 = fx80_inan; |
| 2160 | | } |
| 2161 | | else |
| 2162 | | { |
| 2163 | | result1 = ST(0); |
| 2164 | | result2 = fx80_one; |
| 2165 | | |
| 2166 | | #if 0 // TODO: Function produces bad values |
| 2167 | | if (floatx80_ftan(result1) != -1) |
| 2168 | | m_x87_sw &= ~X87_SW_C2; |
| 2169 | | else |
| 2170 | | m_x87_sw |= X87_SW_C2; |
| 2171 | | #else |
| 2172 | | double x = fx80_to_double(result1); |
| 2173 | | x = tan(x); |
| 2174 | | result1 = double_to_fx80(x); |
| 2175 | | |
| 2176 | | m_x87_sw &= ~X87_SW_C2; |
| 2177 | | #endif |
| 2178 | | } |
| 2179 | | |
| 2180 | | if (x87_check_exceptions()) |
| 2181 | | { |
| 2182 | | x87_write_stack(0, result1, TRUE); |
| 2183 | | x87_dec_stack(); |
| 2184 | | x87_write_stack(0, result2, TRUE); |
| 2185 | | } |
| 2186 | | |
| 2187 | | CYCLES(244); |
| 2188 | | } |
| 2189 | | |
| 2190 | | void i386_device::x87_fpatan(UINT8 modrm) |
| 2191 | | { |
| 2192 | | floatx80 result; |
| 2193 | | |
| 2194 | | if (X87_IS_ST_EMPTY(0)) |
| 2195 | | { |
| 2196 | | x87_set_stack_underflow(); |
| 2197 | | result = fx80_inan; |
| 2198 | | } |
| 2199 | | else |
| 2200 | | { |
| 2201 | | // TODO: Inaccurate |
| 2202 | | double val = atan(fx80_to_double(ST(1)) / fx80_to_double(ST(0))); |
| 2203 | | result = double_to_fx80(val); |
| 2204 | | } |
| 2205 | | |
| 2206 | | if (x87_check_exceptions()) |
| 2207 | | { |
| 2208 | | x87_write_stack(1, result, TRUE); |
| 2209 | | x87_inc_stack(); |
| 2210 | | } |
| 2211 | | |
| 2212 | | CYCLES(289); |
| 2213 | | } |
| 2214 | | |
| 2215 | | void i386_device::x87_fsin(UINT8 modrm) |
| 2216 | | { |
| 2217 | | floatx80 result; |
| 2218 | | |
| 2219 | | if (X87_IS_ST_EMPTY(0)) |
| 2220 | | { |
| 2221 | | x87_set_stack_underflow(); |
| 2222 | | result = fx80_inan; |
| 2223 | | } |
| 2224 | | else |
| 2225 | | { |
| 2226 | | result = ST(0); |
| 2227 | | |
| 2228 | | #if 0 // TODO: Function produces bad values |
| 2229 | | if (floatx80_fsin(result) != -1) |
| 2230 | | m_x87_sw &= ~X87_SW_C2; |
| 2231 | | else |
| 2232 | | m_x87_sw |= X87_SW_C2; |
| 2233 | | #else |
| 2234 | | double x = fx80_to_double(result); |
| 2235 | | x = sin(x); |
| 2236 | | result = double_to_fx80(x); |
| 2237 | | |
| 2238 | | m_x87_sw &= ~X87_SW_C2; |
| 2239 | | #endif |
| 2240 | | } |
| 2241 | | |
| 2242 | | if (x87_check_exceptions()) |
| 2243 | | x87_write_stack(0, result, TRUE); |
| 2244 | | |
| 2245 | | CYCLES(241); |
| 2246 | | } |
| 2247 | | |
| 2248 | | void i386_device::x87_fcos(UINT8 modrm) |
| 2249 | | { |
| 2250 | | floatx80 result; |
| 2251 | | |
| 2252 | | if (X87_IS_ST_EMPTY(0)) |
| 2253 | | { |
| 2254 | | x87_set_stack_underflow(); |
| 2255 | | result = fx80_inan; |
| 2256 | | } |
| 2257 | | else |
| 2258 | | { |
| 2259 | | result = ST(0); |
| 2260 | | |
| 2261 | | #if 0 // TODO: Function produces bad values |
| 2262 | | if (floatx80_fcos(result) != -1) |
| 2263 | | m_x87_sw &= ~X87_SW_C2; |
| 2264 | | else |
| 2265 | | m_x87_sw |= X87_SW_C2; |
| 2266 | | #else |
| 2267 | | double x = fx80_to_double(result); |
| 2268 | | x = cos(x); |
| 2269 | | result = double_to_fx80(x); |
| 2270 | | |
| 2271 | | m_x87_sw &= ~X87_SW_C2; |
| 2272 | | #endif |
| 2273 | | } |
| 2274 | | |
| 2275 | | if (x87_check_exceptions()) |
| 2276 | | x87_write_stack(0, result, TRUE); |
| 2277 | | |
| 2278 | | CYCLES(241); |
| 2279 | | } |
| 2280 | | |
| 2281 | | void i386_device::x87_fsincos(UINT8 modrm) |
| 2282 | | { |
| 2283 | | floatx80 s_result, c_result; |
| 2284 | | |
| 2285 | | if (X87_IS_ST_EMPTY(0)) |
| 2286 | | { |
| 2287 | | x87_set_stack_underflow(); |
| 2288 | | s_result = c_result = fx80_inan; |
| 2289 | | } |
| 2290 | | else if (!X87_IS_ST_EMPTY(7)) |
| 2291 | | { |
| 2292 | | x87_set_stack_overflow(); |
| 2293 | | s_result = c_result = fx80_inan; |
| 2294 | | } |
| 2295 | | else |
| 2296 | | { |
| 2297 | | extern int sf_fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a); |
| 2298 | | |
| 2299 | | s_result = c_result = ST(0); |
| 2300 | | |
| 2301 | | #if 0 // TODO: Function produces bad values |
| 2302 | | if (sf_fsincos(s_result, &s_result, &c_result) != -1) |
| 2303 | | m_x87_sw &= ~X87_SW_C2; |
| 2304 | | else |
| 2305 | | m_x87_sw |= X87_SW_C2; |
| 2306 | | #else |
| 2307 | | double s = fx80_to_double(s_result); |
| 2308 | | double c = fx80_to_double(c_result); |
| 2309 | | s = sin(s); |
| 2310 | | c = cos(c); |
| 2311 | | |
| 2312 | | s_result = double_to_fx80(s); |
| 2313 | | c_result = double_to_fx80(c); |
| 2314 | | |
| 2315 | | m_x87_sw &= ~X87_SW_C2; |
| 2316 | | #endif |
| 2317 | | } |
| 2318 | | |
| 2319 | | if (x87_check_exceptions()) |
| 2320 | | { |
| 2321 | | x87_write_stack(0, s_result, TRUE); |
| 2322 | | x87_dec_stack(); |
| 2323 | | x87_write_stack(0, c_result, TRUE); |
| 2324 | | } |
| 2325 | | |
| 2326 | | CYCLES(291); |
| 2327 | | } |
| 2328 | | |
| 2329 | | |
| 2330 | | /************************************* |
| 2331 | | * |
| 2332 | | * Load data |
| 2333 | | * |
| 2334 | | *************************************/ |
| 2335 | | |
| 2336 | | void i386_device::x87_fld_m32real(UINT8 modrm) |
| 2337 | | { |
| 2338 | | floatx80 value; |
| 2339 | | |
| 2340 | | UINT32 ea = GetEA(modrm, 0); |
| 2341 | | if (x87_dec_stack()) |
| 2342 | | { |
| 2343 | | UINT32 m32real = READ32(ea); |
| 2344 | | |
| 2345 | | value = float32_to_floatx80(m32real); |
| 2346 | | |
| 2347 | | m_x87_sw &= ~X87_SW_C1; |
| 2348 | | |
| 2349 | | if (floatx80_is_signaling_nan(value) || floatx80_is_denormal(value)) |
| 2350 | | { |
| 2351 | | m_x87_sw |= X87_SW_IE; |
| 2352 | | value = fx80_inan; |
| 2353 | | } |
| 2354 | | } |
| 2355 | | else |
| 2356 | | { |
| 2357 | | value = fx80_inan; |
| 2358 | | } |
| 2359 | | |
| 2360 | | if (x87_check_exceptions()) |
| 2361 | | x87_write_stack(0, value, TRUE); |
| 2362 | | |
| 2363 | | CYCLES(3); |
| 2364 | | } |
| 2365 | | |
| 2366 | | void i386_device::x87_fld_m64real(UINT8 modrm) |
| 2367 | | { |
| 2368 | | floatx80 value; |
| 2369 | | |
| 2370 | | UINT32 ea = GetEA(modrm, 0); |
| 2371 | | if (x87_dec_stack()) |
| 2372 | | { |
| 2373 | | UINT64 m64real = READ64(ea); |
| 2374 | | |
| 2375 | | value = float64_to_floatx80(m64real); |
| 2376 | | |
| 2377 | | m_x87_sw &= ~X87_SW_C1; |
| 2378 | | |
| 2379 | | if (floatx80_is_signaling_nan(value) || floatx80_is_denormal(value)) |
| 2380 | | { |
| 2381 | | m_x87_sw |= X87_SW_IE; |
| 2382 | | value = fx80_inan; |
| 2383 | | } |
| 2384 | | } |
| 2385 | | else |
| 2386 | | { |
| 2387 | | value = fx80_inan; |
| 2388 | | } |
| 2389 | | |
| 2390 | | if (x87_check_exceptions()) |
| 2391 | | x87_write_stack(0, value, TRUE); |
| 2392 | | |
| 2393 | | CYCLES(3); |
| 2394 | | } |
| 2395 | | |
| 2396 | | void i386_device::x87_fld_m80real(UINT8 modrm) |
| 2397 | | { |
| 2398 | | floatx80 value; |
| 2399 | | |
| 2400 | | UINT32 ea = GetEA(modrm, 0); |
| 2401 | | if (x87_dec_stack()) |
| 2402 | | { |
| 2403 | | m_x87_sw &= ~X87_SW_C1; |
| 2404 | | value = READ80(ea); |
| 2405 | | } |
| 2406 | | else |
| 2407 | | { |
| 2408 | | value = fx80_inan; |
| 2409 | | } |
| 2410 | | |
| 2411 | | if (x87_check_exceptions()) |
| 2412 | | x87_write_stack(0, value, TRUE); |
| 2413 | | |
| 2414 | | CYCLES(6); |
| 2415 | | } |
| 2416 | | |
| 2417 | | void i386_device::x87_fld_sti(UINT8 modrm) |
| 2418 | | { |
| 2419 | | floatx80 value; |
| 2420 | | |
| 2421 | | if (x87_dec_stack()) |
| 2422 | | { |
| 2423 | | m_x87_sw &= ~X87_SW_C1; |
| 2424 | | value = ST((modrm + 1) & 7); |
| 2425 | | } |
| 2426 | | else |
| 2427 | | { |
| 2428 | | value = fx80_inan; |
| 2429 | | } |
| 2430 | | |
| 2431 | | if (x87_check_exceptions()) |
| 2432 | | x87_write_stack(0, value, TRUE); |
| 2433 | | |
| 2434 | | CYCLES(4); |
| 2435 | | } |
| 2436 | | |
| 2437 | | void i386_device::x87_fild_m16int(UINT8 modrm) |
| 2438 | | { |
| 2439 | | floatx80 value; |
| 2440 | | |
| 2441 | | UINT32 ea = GetEA(modrm, 0); |
| 2442 | | if (!x87_dec_stack()) |
| 2443 | | { |
| 2444 | | value = fx80_inan; |
| 2445 | | } |
| 2446 | | else |
| 2447 | | { |
| 2448 | | m_x87_sw &= ~X87_SW_C1; |
| 2449 | | |
| 2450 | | INT16 m16int = READ16(ea); |
| 2451 | | value = int32_to_floatx80(m16int); |
| 2452 | | } |
| 2453 | | |
| 2454 | | if (x87_check_exceptions()) |
| 2455 | | x87_write_stack(0, value, TRUE); |
| 2456 | | |
| 2457 | | CYCLES(13); |
| 2458 | | } |
| 2459 | | |
| 2460 | | void i386_device::x87_fild_m32int(UINT8 modrm) |
| 2461 | | { |
| 2462 | | floatx80 value; |
| 2463 | | |
| 2464 | | UINT32 ea = GetEA(modrm, 0); |
| 2465 | | if (!x87_dec_stack()) |
| 2466 | | { |
| 2467 | | value = fx80_inan; |
| 2468 | | } |
| 2469 | | else |
| 2470 | | { |
| 2471 | | m_x87_sw &= ~X87_SW_C1; |
| 2472 | | |
| 2473 | | INT32 m32int = READ32(ea); |
| 2474 | | value = int32_to_floatx80(m32int); |
| 2475 | | } |
| 2476 | | |
| 2477 | | if (x87_check_exceptions()) |
| 2478 | | x87_write_stack(0, value, TRUE); |
| 2479 | | |
| 2480 | | CYCLES(9); |
| 2481 | | } |
| 2482 | | |
| 2483 | | void i386_device::x87_fild_m64int(UINT8 modrm) |
| 2484 | | { |
| 2485 | | floatx80 value; |
| 2486 | | |
| 2487 | | UINT32 ea = GetEA(modrm, 0); |
| 2488 | | if (!x87_dec_stack()) |
| 2489 | | { |
| 2490 | | value = fx80_inan; |
| 2491 | | } |
| 2492 | | else |
| 2493 | | { |
| 2494 | | m_x87_sw &= ~X87_SW_C1; |
| 2495 | | |
| 2496 | | INT64 m64int = READ64(ea); |
| 2497 | | value = int64_to_floatx80(m64int); |
| 2498 | | } |
| 2499 | | |
| 2500 | | if (x87_check_exceptions()) |
| 2501 | | x87_write_stack(0, value, TRUE); |
| 2502 | | |
| 2503 | | CYCLES(10); |
| 2504 | | } |
| 2505 | | |
| 2506 | | void i386_device::x87_fbld(UINT8 modrm) |
| 2507 | | { |
| 2508 | | floatx80 value; |
| 2509 | | |
| 2510 | | UINT32 ea = GetEA(modrm, 0); |
| 2511 | | if (!x87_dec_stack()) |
| 2512 | | { |
| 2513 | | value = fx80_inan; |
| 2514 | | } |
| 2515 | | else |
| 2516 | | { |
| 2517 | | m_x87_sw &= ~X87_SW_C1; |
| 2518 | | |
| 2519 | | UINT64 m64val = 0; |
| 2520 | | UINT16 sign; |
| 2521 | | |
| 2522 | | value = READ80(ea); |
| 2523 | | |
| 2524 | | sign = value.high & 0x8000; |
| 2525 | | m64val += ((value.high >> 4) & 0xf) * 10; |
| 2526 | | m64val += ((value.high >> 0) & 0xf); |
| 2527 | | |
| 2528 | | for (int i = 60; i >= 0; i -= 4) |
| 2529 | | { |
| 2530 | | m64val *= 10; |
| 2531 | | m64val += (value.low >> i) & 0xf; |
| 2532 | | } |
| 2533 | | |
| 2534 | | value = int64_to_floatx80(m64val); |
| 2535 | | value.high |= sign; |
| 2536 | | } |
| 2537 | | |
| 2538 | | if (x87_check_exceptions()) |
| 2539 | | x87_write_stack(0, value, TRUE); |
| 2540 | | |
| 2541 | | CYCLES(75); |
| 2542 | | } |
| 2543 | | |
| 2544 | | |
| 2545 | | /************************************* |
| 2546 | | * |
| 2547 | | * Store data |
| 2548 | | * |
| 2549 | | *************************************/ |
| 2550 | | |
| 2551 | | void i386_device::x87_fst_m32real(UINT8 modrm) |
| 2552 | | { |
| 2553 | | floatx80 value; |
| 2554 | | |
| 2555 | | UINT32 ea = GetEA(modrm, 1); |
| 2556 | | if (X87_IS_ST_EMPTY(0)) |
| 2557 | | { |
| 2558 | | x87_set_stack_underflow(); |
| 2559 | | value = fx80_inan; |
| 2560 | | } |
| 2561 | | else |
| 2562 | | { |
| 2563 | | m_x87_sw &= ~X87_SW_C1; |
| 2564 | | value = ST(0); |
| 2565 | | } |
| 2566 | | |
| 2567 | | if (x87_check_exceptions()) |
| 2568 | | { |
| 2569 | | UINT32 m32real = floatx80_to_float32(value); |
| 2570 | | WRITE32(ea, m32real); |
| 2571 | | } |
| 2572 | | |
| 2573 | | CYCLES(7); |
| 2574 | | } |
| 2575 | | |
| 2576 | | void i386_device::x87_fst_m64real(UINT8 modrm) |
| 2577 | | { |
| 2578 | | floatx80 value; |
| 2579 | | |
| 2580 | | UINT32 ea = GetEA(modrm, 1); |
| 2581 | | if (X87_IS_ST_EMPTY(0)) |
| 2582 | | { |
| 2583 | | x87_set_stack_underflow(); |
| 2584 | | value = fx80_inan; |
| 2585 | | } |
| 2586 | | else |
| 2587 | | { |
| 2588 | | m_x87_sw &= ~X87_SW_C1; |
| 2589 | | value = ST(0); |
| 2590 | | } |
| 2591 | | |
| 2592 | | if (x87_check_exceptions()) |
| 2593 | | { |
| 2594 | | UINT64 m64real = floatx80_to_float64(value); |
| 2595 | | WRITE64(ea, m64real); |
| 2596 | | } |
| 2597 | | |
| 2598 | | CYCLES(8); |
| 2599 | | } |
| 2600 | | |
| 2601 | | void i386_device::x87_fst_sti(UINT8 modrm) |
| 2602 | | { |
| 2603 | | int i = modrm & 7; |
| 2604 | | floatx80 value; |
| 2605 | | |
| 2606 | | if (X87_IS_ST_EMPTY(0)) |
| 2607 | | { |
| 2608 | | x87_set_stack_underflow(); |
| 2609 | | value = fx80_inan; |
| 2610 | | } |
| 2611 | | else |
| 2612 | | { |
| 2613 | | m_x87_sw &= ~X87_SW_C1; |
| 2614 | | value = ST(0); |
| 2615 | | } |
| 2616 | | |
| 2617 | | if (x87_check_exceptions()) |
| 2618 | | x87_write_stack(i, value, TRUE); |
| 2619 | | |
| 2620 | | CYCLES(3); |
| 2621 | | } |
| 2622 | | |
| 2623 | | void i386_device::x87_fstp_m32real(UINT8 modrm) |
| 2624 | | { |
| 2625 | | floatx80 value; |
| 2626 | | |
| 2627 | | UINT32 ea = GetEA(modrm, 1); |
| 2628 | | if (X87_IS_ST_EMPTY(0)) |
| 2629 | | { |
| 2630 | | x87_set_stack_underflow(); |
| 2631 | | value = fx80_inan; |
| 2632 | | } |
| 2633 | | else |
| 2634 | | { |
| 2635 | | m_x87_sw &= ~X87_SW_C1; |
| 2636 | | value = ST(0); |
| 2637 | | } |
| 2638 | | |
| 2639 | | if (x87_check_exceptions()) |
| 2640 | | { |
| 2641 | | UINT32 m32real = floatx80_to_float32(value); |
| 2642 | | WRITE32(ea, m32real); |
| 2643 | | x87_inc_stack(); |
| 2644 | | } |
| 2645 | | |
| 2646 | | CYCLES(7); |
| 2647 | | } |
| 2648 | | |
| 2649 | | void i386_device::x87_fstp_m64real(UINT8 modrm) |
| 2650 | | { |
| 2651 | | floatx80 value; |
| 2652 | | |
| 2653 | | if (X87_IS_ST_EMPTY(0)) |
| 2654 | | { |
| 2655 | | x87_set_stack_underflow(); |
| 2656 | | value = fx80_inan; |
| 2657 | | } |
| 2658 | | else |
| 2659 | | { |
| 2660 | | m_x87_sw &= ~X87_SW_C1; |
| 2661 | | value = ST(0); |
| 2662 | | } |
| 2663 | | |
| 2664 | | |
| 2665 | | UINT32 ea = GetEA(modrm, 1); |
| 2666 | | if (x87_check_exceptions()) |
| 2667 | | { |
| 2668 | | UINT64 m64real = floatx80_to_float64(value); |
| 2669 | | WRITE64(ea, m64real); |
| 2670 | | x87_inc_stack(); |
| 2671 | | } |
| 2672 | | |
| 2673 | | CYCLES(8); |
| 2674 | | } |
| 2675 | | |
| 2676 | | void i386_device::x87_fstp_m80real(UINT8 modrm) |
| 2677 | | { |
| 2678 | | floatx80 value; |
| 2679 | | |
| 2680 | | if (X87_IS_ST_EMPTY(0)) |
| 2681 | | { |
| 2682 | | x87_set_stack_underflow(); |
| 2683 | | value = fx80_inan; |
| 2684 | | } |
| 2685 | | else |
| 2686 | | { |
| 2687 | | m_x87_sw &= ~X87_SW_C1; |
| 2688 | | value = ST(0); |
| 2689 | | } |
| 2690 | | |
| 2691 | | UINT32 ea = GetEA(modrm, 1); |
| 2692 | | if (x87_check_exceptions()) |
| 2693 | | { |
| 2694 | | WRITE80(ea, value); |
| 2695 | | x87_inc_stack(); |
| 2696 | | } |
| 2697 | | |
| 2698 | | CYCLES(6); |
| 2699 | | } |
| 2700 | | |
| 2701 | | void i386_device::x87_fstp_sti(UINT8 modrm) |
| 2702 | | { |
| 2703 | | int i = modrm & 7; |
| 2704 | | floatx80 value; |
| 2705 | | |
| 2706 | | if (X87_IS_ST_EMPTY(0)) |
| 2707 | | { |
| 2708 | | x87_set_stack_underflow(); |
| 2709 | | value = fx80_inan; |
| 2710 | | } |
| 2711 | | else |
| 2712 | | { |
| 2713 | | m_x87_sw &= ~X87_SW_C1; |
| 2714 | | value = ST(0); |
| 2715 | | } |
| 2716 | | |
| 2717 | | if (x87_check_exceptions()) |
| 2718 | | { |
| 2719 | | x87_write_stack(i, value, TRUE); |
| 2720 | | x87_inc_stack(); |
| 2721 | | } |
| 2722 | | |
| 2723 | | CYCLES(3); |
| 2724 | | } |
| 2725 | | |
| 2726 | | void i386_device::x87_fist_m16int(UINT8 modrm) |
| 2727 | | { |
| 2728 | | INT16 m16int; |
| 2729 | | |
| 2730 | | if (X87_IS_ST_EMPTY(0)) |
| 2731 | | { |
| 2732 | | x87_set_stack_underflow(); |
| 2733 | | m16int = -32768; |
| 2734 | | } |
| 2735 | | else |
| 2736 | | { |
| 2737 | | floatx80 fx80 = floatx80_round_to_int(ST(0)); |
| 2738 | | |
| 2739 | | floatx80 lowerLim = int32_to_floatx80(-32768); |
| 2740 | | floatx80 upperLim = int32_to_floatx80(32767); |
| 2741 | | |
| 2742 | | m_x87_sw &= ~X87_SW_C1; |
| 2743 | | |
| 2744 | | if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) |
| 2745 | | m16int = floatx80_to_int32(fx80); |
| 2746 | | else |
| 2747 | | m16int = -32768; |
| 2748 | | } |
| 2749 | | |
| 2750 | | UINT32 ea = GetEA(modrm, 1); |
| 2751 | | if (x87_check_exceptions()) |
| 2752 | | { |
| 2753 | | WRITE16(ea, m16int); |
| 2754 | | } |
| 2755 | | |
| 2756 | | CYCLES(29); |
| 2757 | | } |
| 2758 | | |
| 2759 | | void i386_device::x87_fist_m32int(UINT8 modrm) |
| 2760 | | { |
| 2761 | | INT32 m32int; |
| 2762 | | |
| 2763 | | if (X87_IS_ST_EMPTY(0)) |
| 2764 | | { |
| 2765 | | x87_set_stack_underflow(); |
| 2766 | | m32int = 0x80000000; |
| 2767 | | } |
| 2768 | | else |
| 2769 | | { |
| 2770 | | floatx80 fx80 = floatx80_round_to_int(ST(0)); |
| 2771 | | |
| 2772 | | floatx80 lowerLim = int32_to_floatx80(0x80000000); |
| 2773 | | floatx80 upperLim = int32_to_floatx80(0x7fffffff); |
| 2774 | | |
| 2775 | | m_x87_sw &= ~X87_SW_C1; |
| 2776 | | |
| 2777 | | if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) |
| 2778 | | m32int = floatx80_to_int32(fx80); |
| 2779 | | else |
| 2780 | | m32int = 0x80000000; |
| 2781 | | } |
| 2782 | | |
| 2783 | | UINT32 ea = GetEA(modrm, 1); |
| 2784 | | if (x87_check_exceptions()) |
| 2785 | | { |
| 2786 | | WRITE32(ea, m32int); |
| 2787 | | } |
| 2788 | | |
| 2789 | | CYCLES(28); |
| 2790 | | } |
| 2791 | | |
| 2792 | | void i386_device::x87_fistp_m16int(UINT8 modrm) |
| 2793 | | { |
| 2794 | | INT16 m16int; |
| 2795 | | |
| 2796 | | if (X87_IS_ST_EMPTY(0)) |
| 2797 | | { |
| 2798 | | x87_set_stack_underflow(); |
| 2799 | | m16int = (UINT16)0x8000; |
| 2800 | | } |
| 2801 | | else |
| 2802 | | { |
| 2803 | | floatx80 fx80 = floatx80_round_to_int(ST(0)); |
| 2804 | | |
| 2805 | | floatx80 lowerLim = int32_to_floatx80(-32768); |
| 2806 | | floatx80 upperLim = int32_to_floatx80(32767); |
| 2807 | | |
| 2808 | | m_x87_sw &= ~X87_SW_C1; |
| 2809 | | |
| 2810 | | if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) |
| 2811 | | m16int = floatx80_to_int32(fx80); |
| 2812 | | else |
| 2813 | | m16int = (UINT16)0x8000; |
| 2814 | | } |
| 2815 | | |
| 2816 | | UINT32 ea = GetEA(modrm, 1); |
| 2817 | | if (x87_check_exceptions()) |
| 2818 | | { |
| 2819 | | WRITE16(ea, m16int); |
| 2820 | | x87_inc_stack(); |
| 2821 | | } |
| 2822 | | |
| 2823 | | CYCLES(29); |
| 2824 | | } |
| 2825 | | |
| 2826 | | void i386_device::x87_fistp_m32int(UINT8 modrm) |
| 2827 | | { |
| 2828 | | INT32 m32int; |
| 2829 | | |
| 2830 | | if (X87_IS_ST_EMPTY(0)) |
| 2831 | | { |
| 2832 | | x87_set_stack_underflow(); |
| 2833 | | m32int = 0x80000000; |
| 2834 | | } |
| 2835 | | else |
| 2836 | | { |
| 2837 | | floatx80 fx80 = floatx80_round_to_int(ST(0)); |
| 2838 | | |
| 2839 | | floatx80 lowerLim = int32_to_floatx80(0x80000000); |
| 2840 | | floatx80 upperLim = int32_to_floatx80(0x7fffffff); |
| 2841 | | |
| 2842 | | m_x87_sw &= ~X87_SW_C1; |
| 2843 | | |
| 2844 | | if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) |
| 2845 | | m32int = floatx80_to_int32(fx80); |
| 2846 | | else |
| 2847 | | m32int = 0x80000000; |
| 2848 | | } |
| 2849 | | |
| 2850 | | UINT32 ea = GetEA(modrm, 1); |
| 2851 | | if (x87_check_exceptions()) |
| 2852 | | { |
| 2853 | | WRITE32(ea, m32int); |
| 2854 | | x87_inc_stack(); |
| 2855 | | } |
| 2856 | | |
| 2857 | | CYCLES(29); |
| 2858 | | } |
| 2859 | | |
| 2860 | | void i386_device::x87_fistp_m64int(UINT8 modrm) |
| 2861 | | { |
| 2862 | | INT64 m64int; |
| 2863 | | |
| 2864 | | if (X87_IS_ST_EMPTY(0)) |
| 2865 | | { |
| 2866 | | x87_set_stack_underflow(); |
| 2867 | | m64int = U64(0x8000000000000000); |
| 2868 | | } |
| 2869 | | else |
| 2870 | | { |
| 2871 | | floatx80 fx80 = floatx80_round_to_int(ST(0)); |
| 2872 | | |
| 2873 | | floatx80 lowerLim = int64_to_floatx80(U64(0x8000000000000000)); |
| 2874 | | floatx80 upperLim = int64_to_floatx80(U64(0x7fffffffffffffff)); |
| 2875 | | |
| 2876 | | m_x87_sw &= ~X87_SW_C1; |
| 2877 | | |
| 2878 | | if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) |
| 2879 | | m64int = floatx80_to_int64(fx80); |
| 2880 | | else |
| 2881 | | m64int = U64(0x8000000000000000); |
| 2882 | | } |
| 2883 | | |
| 2884 | | UINT32 ea = GetEA(modrm, 1); |
| 2885 | | if (x87_check_exceptions()) |
| 2886 | | { |
| 2887 | | WRITE64(ea, m64int); |
| 2888 | | x87_inc_stack(); |
| 2889 | | } |
| 2890 | | |
| 2891 | | CYCLES(29); |
| 2892 | | } |
| 2893 | | |
| 2894 | | void i386_device::x87_fbstp(UINT8 modrm) |
| 2895 | | { |
| 2896 | | floatx80 result; |
| 2897 | | |
| 2898 | | if (X87_IS_ST_EMPTY(0)) |
| 2899 | | { |
| 2900 | | x87_set_stack_underflow(); |
| 2901 | | result = fx80_inan; |
| 2902 | | } |
| 2903 | | else |
| 2904 | | { |
| 2905 | | UINT64 u64 = floatx80_to_int64(floatx80_abs(ST(0))); |
| 2906 | | result.low = 0; |
| 2907 | | |
| 2908 | | for (int i = 0; i < 64; i += 4) |
| 2909 | | { |
| 2910 | | result.low += (u64 % 10) << i; |
| 2911 | | u64 /= 10; |
| 2912 | | } |
| 2913 | | |
| 2914 | | result.high = (u64 % 10); |
| 2915 | | result.high += ((u64 / 10) % 10) << 4; |
| 2916 | | result.high |= ST(0).high & 0x8000; |
| 2917 | | } |
| 2918 | | |
| 2919 | | UINT32 ea = GetEA(modrm, 1); |
| 2920 | | if (x87_check_exceptions()) |
| 2921 | | { |
| 2922 | | WRITE80(ea, result); |
| 2923 | | x87_inc_stack(); |
| 2924 | | } |
| 2925 | | |
| 2926 | | CYCLES(175); |
| 2927 | | } |
| 2928 | | |
| 2929 | | |
| 2930 | | /************************************* |
| 2931 | | * |
| 2932 | | * Constant load |
| 2933 | | * |
| 2934 | | *************************************/ |
| 2935 | | |
| 2936 | | void i386_device::x87_fld1(UINT8 modrm) |
| 2937 | | { |
| 2938 | | floatx80 value; |
| 2939 | | int tag; |
| 2940 | | |
| 2941 | | if (x87_dec_stack()) |
| 2942 | | { |
| 2943 | | m_x87_sw &= ~X87_SW_C1; |
| 2944 | | value = fx80_one; |
| 2945 | | tag = X87_TW_VALID; |
| 2946 | | } |
| 2947 | | else |
| 2948 | | { |
| 2949 | | value = fx80_inan; |
| 2950 | | tag = X87_TW_SPECIAL; |
| 2951 | | } |
| 2952 | | |
| 2953 | | if (x87_check_exceptions()) |
| 2954 | | { |
| 2955 | | x87_set_tag(ST_TO_PHYS(0), tag); |
| 2956 | | x87_write_stack(0, value, FALSE); |
| 2957 | | } |
| 2958 | | |
| 2959 | | CYCLES(4); |
| 2960 | | } |
| 2961 | | |
| 2962 | | void i386_device::x87_fldl2t(UINT8 modrm) |
| 2963 | | { |
| 2964 | | floatx80 value; |
| 2965 | | int tag; |
| 2966 | | |
| 2967 | | if (x87_dec_stack()) |
| 2968 | | { |
| 2969 | | tag = X87_TW_VALID; |
| 2970 | | value.high = 0x4000; |
| 2971 | | |
| 2972 | | if (X87_RC == X87_CW_RC_UP) |
| 2973 | | value.low = U64(0xd49a784bcd1b8aff); |
| 2974 | | else |
| 2975 | | value.low = U64(0xd49a784bcd1b8afe); |
| 2976 | | |
| 2977 | | m_x87_sw &= ~X87_SW_C1; |
| 2978 | | } |
| 2979 | | else |
| 2980 | | { |
| 2981 | | value = fx80_inan; |
| 2982 | | tag = X87_TW_SPECIAL; |
| 2983 | | } |
| 2984 | | |
| 2985 | | if (x87_check_exceptions()) |
| 2986 | | { |
| 2987 | | x87_set_tag(ST_TO_PHYS(0), tag); |
| 2988 | | x87_write_stack(0, value, FALSE); |
| 2989 | | } |
| 2990 | | |
| 2991 | | CYCLES(8); |
| 2992 | | } |
| 2993 | | |
| 2994 | | void i386_device::x87_fldl2e(UINT8 modrm) |
| 2995 | | { |
| 2996 | | floatx80 value; |
| 2997 | | int tag; |
| 2998 | | |
| 2999 | | if (x87_dec_stack()) |
| 3000 | | { |
| 3001 | | int rc = X87_RC; |
| 3002 | | tag = X87_TW_VALID; |
| 3003 | | value.high = 0x3fff; |
| 3004 | | |
| 3005 | | if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST) |
| 3006 | | value.low = U64(0xb8aa3b295c17f0bc); |
| 3007 | | else |
| 3008 | | value.low = U64(0xb8aa3b295c17f0bb); |
| 3009 | | |
| 3010 | | m_x87_sw &= ~X87_SW_C1; |
| 3011 | | } |
| 3012 | | else |
| 3013 | | { |
| 3014 | | value = fx80_inan; |
| 3015 | | tag = X87_TW_SPECIAL; |
| 3016 | | } |
| 3017 | | |
| 3018 | | if (x87_check_exceptions()) |
| 3019 | | { |
| 3020 | | x87_set_tag(ST_TO_PHYS(0), tag); |
| 3021 | | x87_write_stack(0, value, FALSE); |
| 3022 | | } |
| 3023 | | |
| 3024 | | CYCLES(8); |
| 3025 | | } |
| 3026 | | |
| 3027 | | void i386_device::x87_fldpi(UINT8 modrm) |
| 3028 | | { |
| 3029 | | floatx80 value; |
| 3030 | | int tag; |
| 3031 | | |
| 3032 | | if (x87_dec_stack()) |
| 3033 | | { |
| 3034 | | int rc = X87_RC; |
| 3035 | | tag = X87_TW_VALID; |
| 3036 | | value.high = 0x4000; |
| 3037 | | |
| 3038 | | if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST) |
| 3039 | | value.low = U64(0xc90fdaa22168c235); |
| 3040 | | else |
| 3041 | | value.low = U64(0xc90fdaa22168c234); |
| 3042 | | |
| 3043 | | m_x87_sw &= ~X87_SW_C1; |
| 3044 | | } |
| 3045 | | else |
| 3046 | | { |
| 3047 | | value = fx80_inan; |
| 3048 | | tag = X87_TW_SPECIAL; |
| 3049 | | } |
| 3050 | | |
| 3051 | | if (x87_check_exceptions()) |
| 3052 | | { |
| 3053 | | x87_set_tag(ST_TO_PHYS(0), tag); |
| 3054 | | x87_write_stack(0, value, FALSE); |
| 3055 | | } |
| 3056 | | |
| 3057 | | CYCLES(8); |
| 3058 | | } |
| 3059 | | |
| 3060 | | void i386_device::x87_fldlg2(UINT8 modrm) |
| 3061 | | { |
| 3062 | | floatx80 value; |
| 3063 | | int tag; |
| 3064 | | |
| 3065 | | if (x87_dec_stack()) |
| 3066 | | { |
| 3067 | | int rc = X87_RC; |
| 3068 | | tag = X87_TW_VALID; |
| 3069 | | value.high = 0x3ffd; |
| 3070 | | |
| 3071 | | if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST) |
| 3072 | | value.low = U64(0x9a209a84fbcff799); |
| 3073 | | else |
| 3074 | | value.low = U64(0x9a209a84fbcff798); |
| 3075 | | |
| 3076 | | m_x87_sw &= ~X87_SW_C1; |
| 3077 | | } |
| 3078 | | else |
| 3079 | | { |
| 3080 | | value = fx80_inan; |
| 3081 | | tag = X87_TW_SPECIAL; |
| 3082 | | } |
| 3083 | | |
| 3084 | | if (x87_check_exceptions()) |
| 3085 | | { |
| 3086 | | x87_set_tag(ST_TO_PHYS(0), tag); |
| 3087 | | x87_write_stack(0, value, FALSE); |
| 3088 | | } |
| 3089 | | |
| 3090 | | CYCLES(8); |
| 3091 | | } |
| 3092 | | |
| 3093 | | void i386_device::x87_fldln2(UINT8 modrm) |
| 3094 | | { |
| 3095 | | floatx80 value; |
| 3096 | | int tag; |
| 3097 | | |
| 3098 | | if (x87_dec_stack()) |
| 3099 | | { |
| 3100 | | int rc = X87_RC; |
| 3101 | | tag = X87_TW_VALID; |
| 3102 | | value.high = 0x3ffe; |
| 3103 | | |
| 3104 | | if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST) |
| 3105 | | value.low = U64(0xb17217f7d1cf79ac); |
| 3106 | | else |
| 3107 | | value.low = U64(0xb17217f7d1cf79ab); |
| 3108 | | |
| 3109 | | m_x87_sw &= ~X87_SW_C1; |
| 3110 | | } |
| 3111 | | else |
| 3112 | | { |
| 3113 | | value = fx80_inan; |
| 3114 | | tag = X87_TW_SPECIAL; |
| 3115 | | } |
| 3116 | | |
| 3117 | | if (x87_check_exceptions()) |
| 3118 | | { |
| 3119 | | x87_set_tag(ST_TO_PHYS(0), tag); |
| 3120 | | x87_write_stack(0, value, FALSE); |
| 3121 | | } |
| 3122 | | |
| 3123 | | CYCLES(8); |
| 3124 | | } |
| 3125 | | |
| 3126 | | void i386_device::x87_fldz(UINT8 modrm) |
| 3127 | | { |
| 3128 | | floatx80 value; |
| 3129 | | int tag; |
| 3130 | | |
| 3131 | | if (x87_dec_stack()) |
| 3132 | | { |
| 3133 | | value = fx80_zero; |
| 3134 | | tag = X87_TW_ZERO; |
| 3135 | | m_x87_sw &= ~X87_SW_C1; |
| 3136 | | } |
| 3137 | | else |
| 3138 | | { |
| 3139 | | value = fx80_inan; |
| 3140 | | tag = X87_TW_SPECIAL; |
| 3141 | | } |
| 3142 | | |
| 3143 | | if (x87_check_exceptions()) |
| 3144 | | { |
| 3145 | | x87_set_tag(ST_TO_PHYS(0), tag); |
| 3146 | | x87_write_stack(0, value, FALSE); |
| 3147 | | } |
| 3148 | | |
| 3149 | | CYCLES(4); |
| 3150 | | } |
| 3151 | | |
| 3152 | | |
| 3153 | | /************************************* |
| 3154 | | * |
| 3155 | | * Miscellaneous |
| 3156 | | * |
| 3157 | | *************************************/ |
| 3158 | | |
| 3159 | | void i386_device::x87_fnop(UINT8 modrm) |
| 3160 | | { |
| 3161 | | CYCLES(3); |
| 3162 | | } |
| 3163 | | |
| 3164 | | void i386_device::x87_fchs(UINT8 modrm) |
| 3165 | | { |
| 3166 | | floatx80 value; |
| 3167 | | |
| 3168 | | if (X87_IS_ST_EMPTY(0)) |
| 3169 | | { |
| 3170 | | x87_set_stack_underflow(); |
| 3171 | | value = fx80_inan; |
| 3172 | | } |
| 3173 | | else |
| 3174 | | { |
| 3175 | | m_x87_sw &= ~X87_SW_C1; |
| 3176 | | |
| 3177 | | value = ST(0); |
| 3178 | | value.high ^= 0x8000; |
| 3179 | | } |
| 3180 | | |
| 3181 | | if (x87_check_exceptions()) |
| 3182 | | x87_write_stack(0, value, FALSE); |
| 3183 | | |
| 3184 | | CYCLES(6); |
| 3185 | | } |
| 3186 | | |
| 3187 | | void i386_device::x87_fabs(UINT8 modrm) |
| 3188 | | { |
| 3189 | | floatx80 value; |
| 3190 | | |
| 3191 | | if (X87_IS_ST_EMPTY(0)) |
| 3192 | | { |
| 3193 | | x87_set_stack_underflow(); |
| 3194 | | value = fx80_inan; |
| 3195 | | } |
| 3196 | | else |
| 3197 | | { |
| 3198 | | m_x87_sw &= ~X87_SW_C1; |
| 3199 | | |
| 3200 | | value = ST(0); |
| 3201 | | value.high &= 0x7fff; |
| 3202 | | } |
| 3203 | | |
| 3204 | | if (x87_check_exceptions()) |
| 3205 | | x87_write_stack(0, value, FALSE); |
| 3206 | | |
| 3207 | | CYCLES(6); |
| 3208 | | } |
| 3209 | | |
| 3210 | | void i386_device::x87_fscale(UINT8 modrm) |
| 3211 | | { |
| 3212 | | floatx80 value; |
| 3213 | | |
| 3214 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 3215 | | { |
| 3216 | | x87_set_stack_underflow(); |
| 3217 | | value = fx80_inan; |
| 3218 | | } |
| 3219 | | else |
| 3220 | | { |
| 3221 | | m_x87_sw &= ~X87_SW_C1; |
| 3222 | | value = ST(0); |
| 3223 | | |
| 3224 | | // Set the rounding mode to truncate |
| 3225 | | UINT16 old_cw = m_x87_cw; |
| 3226 | | UINT16 new_cw = (old_cw & ~(X87_CW_RC_MASK << X87_CW_RC_SHIFT)) | (X87_CW_RC_ZERO << X87_CW_RC_SHIFT); |
| 3227 | | x87_write_cw(new_cw); |
| 3228 | | |
| 3229 | | // Interpret ST(1) as an integer |
| 3230 | | UINT32 st1 = floatx80_to_int32(floatx80_round_to_int(ST(1))); |
| 3231 | | |
| 3232 | | // Restore the rounding mode |
| 3233 | | x87_write_cw(old_cw); |
| 3234 | | |
| 3235 | | // Get the unbiased exponent of ST(0) |
| 3236 | | INT16 exp = (ST(0).high & 0x7fff) - 0x3fff; |
| 3237 | | |
| 3238 | | // Calculate the new exponent |
| 3239 | | exp = (exp + st1 + 0x3fff) & 0x7fff; |
| 3240 | | |
| 3241 | | // Write it back |
| 3242 | | value.high = (value.high & ~0x7fff) + exp; |
| 3243 | | } |
| 3244 | | |
| 3245 | | if (x87_check_exceptions()) |
| 3246 | | x87_write_stack(0, value, FALSE); |
| 3247 | | |
| 3248 | | CYCLES(31); |
| 3249 | | } |
| 3250 | | |
| 3251 | | void i386_device::x87_frndint(UINT8 modrm) |
| 3252 | | { |
| 3253 | | floatx80 value; |
| 3254 | | |
| 3255 | | if (X87_IS_ST_EMPTY(0)) |
| 3256 | | { |
| 3257 | | x87_set_stack_underflow(); |
| 3258 | | value = fx80_inan; |
| 3259 | | } |
| 3260 | | else |
| 3261 | | { |
| 3262 | | m_x87_sw &= ~X87_SW_C1; |
| 3263 | | |
| 3264 | | value = floatx80_round_to_int(ST(0)); |
| 3265 | | } |
| 3266 | | |
| 3267 | | if (x87_check_exceptions()) |
| 3268 | | x87_write_stack(0, value, TRUE); |
| 3269 | | |
| 3270 | | CYCLES(21); |
| 3271 | | } |
| 3272 | | |
| 3273 | | void i386_device::x87_fxtract(UINT8 modrm) |
| 3274 | | { |
| 3275 | | floatx80 sig80, exp80; |
| 3276 | | |
| 3277 | | if (X87_IS_ST_EMPTY(0)) |
| 3278 | | { |
| 3279 | | x87_set_stack_underflow(); |
| 3280 | | sig80 = exp80 = fx80_inan; |
| 3281 | | } |
| 3282 | | else if (!X87_IS_ST_EMPTY(7)) |
| 3283 | | { |
| 3284 | | x87_set_stack_overflow(); |
| 3285 | | sig80 = exp80 = fx80_inan; |
| 3286 | | } |
| 3287 | | else |
| 3288 | | { |
| 3289 | | floatx80 value = ST(0); |
| 3290 | | |
| 3291 | | if (floatx80_eq(value, fx80_zero)) |
| 3292 | | { |
| 3293 | | m_x87_sw |= X87_SW_ZE; |
| 3294 | | |
| 3295 | | exp80 = fx80_ninf; |
| 3296 | | sig80 = fx80_zero; |
| 3297 | | } |
| 3298 | | else |
| 3299 | | { |
| 3300 | | // Extract the unbiased exponent |
| 3301 | | exp80 = int32_to_floatx80((value.high & 0x7fff) - 0x3fff); |
| 3302 | | |
| 3303 | | // For the significand, replicate the original value and set its true exponent to 0. |
| 3304 | | sig80 = value; |
| 3305 | | sig80.high &= ~0x7fff; |
| 3306 | | sig80.high |= 0x3fff; |
| 3307 | | } |
| 3308 | | } |
| 3309 | | |
| 3310 | | if (x87_check_exceptions()) |
| 3311 | | { |
| 3312 | | x87_write_stack(0, exp80, TRUE); |
| 3313 | | x87_dec_stack(); |
| 3314 | | x87_write_stack(0, sig80, TRUE); |
| 3315 | | } |
| 3316 | | |
| 3317 | | CYCLES(21); |
| 3318 | | } |
| 3319 | | |
| 3320 | | /************************************* |
| 3321 | | * |
| 3322 | | * Comparison |
| 3323 | | * |
| 3324 | | *************************************/ |
| 3325 | | |
| 3326 | | void i386_device::x87_ftst(UINT8 modrm) |
| 3327 | | { |
| 3328 | | if (X87_IS_ST_EMPTY(0)) |
| 3329 | | { |
| 3330 | | x87_set_stack_underflow(); |
| 3331 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3332 | | } |
| 3333 | | else |
| 3334 | | { |
| 3335 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3336 | | |
| 3337 | | if (floatx80_is_nan(ST(0))) |
| 3338 | | { |
| 3339 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3340 | | m_x87_sw |= X87_SW_IE; |
| 3341 | | } |
| 3342 | | else |
| 3343 | | { |
| 3344 | | if (floatx80_eq(ST(0), fx80_zero)) |
| 3345 | | m_x87_sw |= X87_SW_C3; |
| 3346 | | |
| 3347 | | if (floatx80_lt(ST(0), fx80_zero)) |
| 3348 | | m_x87_sw |= X87_SW_C0; |
| 3349 | | } |
| 3350 | | } |
| 3351 | | |
| 3352 | | x87_check_exceptions(); |
| 3353 | | |
| 3354 | | CYCLES(4); |
| 3355 | | } |
| 3356 | | |
| 3357 | | void i386_device::x87_fxam(UINT8 modrm) |
| 3358 | | { |
| 3359 | | floatx80 value = ST(0); |
| 3360 | | |
| 3361 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3362 | | |
| 3363 | | // TODO: Unsupported and denormal values |
| 3364 | | if (X87_IS_ST_EMPTY(0)) |
| 3365 | | { |
| 3366 | | m_x87_sw |= X87_SW_C3 | X87_SW_C0; |
| 3367 | | } |
| 3368 | | else if (floatx80_is_zero(value)) |
| 3369 | | { |
| 3370 | | m_x87_sw |= X87_SW_C3; |
| 3371 | | } |
| 3372 | | if (floatx80_is_nan(value)) |
| 3373 | | { |
| 3374 | | m_x87_sw |= X87_SW_C0; |
| 3375 | | } |
| 3376 | | else if (floatx80_is_inf(value)) |
| 3377 | | { |
| 3378 | | m_x87_sw |= X87_SW_C2 | X87_SW_C0; |
| 3379 | | } |
| 3380 | | else |
| 3381 | | { |
| 3382 | | m_x87_sw |= X87_SW_C2; |
| 3383 | | } |
| 3384 | | |
| 3385 | | if (value.high & 0x8000) |
| 3386 | | m_x87_sw |= X87_SW_C1; |
| 3387 | | |
| 3388 | | CYCLES(8); |
| 3389 | | } |
| 3390 | | |
| 3391 | | void i386_device::x87_ficom_m16int(UINT8 modrm) |
| 3392 | | { |
| 3393 | | UINT32 ea = GetEA(modrm, 0); |
| 3394 | | if (X87_IS_ST_EMPTY(0)) |
| 3395 | | { |
| 3396 | | x87_set_stack_underflow(); |
| 3397 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3398 | | } |
| 3399 | | else |
| 3400 | | { |
| 3401 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3402 | | |
| 3403 | | INT16 m16int = READ16(ea); |
| 3404 | | |
| 3405 | | floatx80 a = ST(0); |
| 3406 | | floatx80 b = int32_to_floatx80(m16int); |
| 3407 | | |
| 3408 | | if (floatx80_is_nan(a)) |
| 3409 | | { |
| 3410 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3411 | | m_x87_sw |= X87_SW_IE; |
| 3412 | | } |
| 3413 | | else |
| 3414 | | { |
| 3415 | | if (floatx80_eq(a, b)) |
| 3416 | | m_x87_sw |= X87_SW_C3; |
| 3417 | | |
| 3418 | | if (floatx80_lt(a, b)) |
| 3419 | | m_x87_sw |= X87_SW_C0; |
| 3420 | | } |
| 3421 | | } |
| 3422 | | |
| 3423 | | x87_check_exceptions(); |
| 3424 | | |
| 3425 | | CYCLES(16); |
| 3426 | | } |
| 3427 | | |
| 3428 | | void i386_device::x87_ficom_m32int(UINT8 modrm) |
| 3429 | | { |
| 3430 | | UINT32 ea = GetEA(modrm, 0); |
| 3431 | | if (X87_IS_ST_EMPTY(0)) |
| 3432 | | { |
| 3433 | | x87_set_stack_underflow(); |
| 3434 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3435 | | } |
| 3436 | | else |
| 3437 | | { |
| 3438 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3439 | | |
| 3440 | | INT32 m32int = READ32(ea); |
| 3441 | | |
| 3442 | | floatx80 a = ST(0); |
| 3443 | | floatx80 b = int32_to_floatx80(m32int); |
| 3444 | | |
| 3445 | | if (floatx80_is_nan(a)) |
| 3446 | | { |
| 3447 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3448 | | m_x87_sw |= X87_SW_IE; |
| 3449 | | } |
| 3450 | | else |
| 3451 | | { |
| 3452 | | if (floatx80_eq(a, b)) |
| 3453 | | m_x87_sw |= X87_SW_C3; |
| 3454 | | |
| 3455 | | if (floatx80_lt(a, b)) |
| 3456 | | m_x87_sw |= X87_SW_C0; |
| 3457 | | } |
| 3458 | | } |
| 3459 | | |
| 3460 | | x87_check_exceptions(); |
| 3461 | | |
| 3462 | | CYCLES(15); |
| 3463 | | } |
| 3464 | | |
| 3465 | | void i386_device::x87_ficomp_m16int(UINT8 modrm) |
| 3466 | | { |
| 3467 | | UINT32 ea = GetEA(modrm, 0); |
| 3468 | | if (X87_IS_ST_EMPTY(0)) |
| 3469 | | { |
| 3470 | | x87_set_stack_underflow(); |
| 3471 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3472 | | } |
| 3473 | | else |
| 3474 | | { |
| 3475 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3476 | | |
| 3477 | | INT16 m16int = READ16(ea); |
| 3478 | | |
| 3479 | | floatx80 a = ST(0); |
| 3480 | | floatx80 b = int32_to_floatx80(m16int); |
| 3481 | | |
| 3482 | | if (floatx80_is_nan(a)) |
| 3483 | | { |
| 3484 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3485 | | m_x87_sw |= X87_SW_IE; |
| 3486 | | } |
| 3487 | | else |
| 3488 | | { |
| 3489 | | if (floatx80_eq(a, b)) |
| 3490 | | m_x87_sw |= X87_SW_C3; |
| 3491 | | |
| 3492 | | if (floatx80_lt(a, b)) |
| 3493 | | m_x87_sw |= X87_SW_C0; |
| 3494 | | } |
| 3495 | | } |
| 3496 | | |
| 3497 | | if (x87_check_exceptions()) |
| 3498 | | x87_inc_stack(); |
| 3499 | | |
| 3500 | | CYCLES(16); |
| 3501 | | } |
| 3502 | | |
| 3503 | | void i386_device::x87_ficomp_m32int(UINT8 modrm) |
| 3504 | | { |
| 3505 | | UINT32 ea = GetEA(modrm, 0); |
| 3506 | | if (X87_IS_ST_EMPTY(0)) |
| 3507 | | { |
| 3508 | | x87_set_stack_underflow(); |
| 3509 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3510 | | } |
| 3511 | | else |
| 3512 | | { |
| 3513 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3514 | | |
| 3515 | | INT32 m32int = READ32(ea); |
| 3516 | | |
| 3517 | | floatx80 a = ST(0); |
| 3518 | | floatx80 b = int32_to_floatx80(m32int); |
| 3519 | | |
| 3520 | | if (floatx80_is_nan(a)) |
| 3521 | | { |
| 3522 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3523 | | m_x87_sw |= X87_SW_IE; |
| 3524 | | } |
| 3525 | | else |
| 3526 | | { |
| 3527 | | if (floatx80_eq(a, b)) |
| 3528 | | m_x87_sw |= X87_SW_C3; |
| 3529 | | |
| 3530 | | if (floatx80_lt(a, b)) |
| 3531 | | m_x87_sw |= X87_SW_C0; |
| 3532 | | } |
| 3533 | | } |
| 3534 | | |
| 3535 | | if (x87_check_exceptions()) |
| 3536 | | x87_inc_stack(); |
| 3537 | | |
| 3538 | | CYCLES(15); |
| 3539 | | } |
| 3540 | | |
| 3541 | | |
| 3542 | | void i386_device::x87_fcom_m32real(UINT8 modrm) |
| 3543 | | { |
| 3544 | | UINT32 ea = GetEA(modrm, 0); |
| 3545 | | if (X87_IS_ST_EMPTY(0)) |
| 3546 | | { |
| 3547 | | x87_set_stack_underflow(); |
| 3548 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3549 | | } |
| 3550 | | else |
| 3551 | | { |
| 3552 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3553 | | |
| 3554 | | UINT32 m32real = READ32(ea); |
| 3555 | | |
| 3556 | | floatx80 a = ST(0); |
| 3557 | | floatx80 b = float32_to_floatx80(m32real); |
| 3558 | | |
| 3559 | | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3560 | | { |
| 3561 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3562 | | m_x87_sw |= X87_SW_IE; |
| 3563 | | } |
| 3564 | | else |
| 3565 | | { |
| 3566 | | if (floatx80_eq(a, b)) |
| 3567 | | m_x87_sw |= X87_SW_C3; |
| 3568 | | |
| 3569 | | if (floatx80_lt(a, b)) |
| 3570 | | m_x87_sw |= X87_SW_C0; |
| 3571 | | } |
| 3572 | | } |
| 3573 | | |
| 3574 | | x87_check_exceptions(); |
| 3575 | | |
| 3576 | | CYCLES(4); |
| 3577 | | } |
| 3578 | | |
| 3579 | | void i386_device::x87_fcom_m64real(UINT8 modrm) |
| 3580 | | { |
| 3581 | | UINT32 ea = GetEA(modrm, 0); |
| 3582 | | if (X87_IS_ST_EMPTY(0)) |
| 3583 | | { |
| 3584 | | x87_set_stack_underflow(); |
| 3585 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3586 | | } |
| 3587 | | else |
| 3588 | | { |
| 3589 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3590 | | |
| 3591 | | UINT64 m64real = READ64(ea); |
| 3592 | | |
| 3593 | | floatx80 a = ST(0); |
| 3594 | | floatx80 b = float64_to_floatx80(m64real); |
| 3595 | | |
| 3596 | | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3597 | | { |
| 3598 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3599 | | m_x87_sw |= X87_SW_IE; |
| 3600 | | } |
| 3601 | | else |
| 3602 | | { |
| 3603 | | if (floatx80_eq(a, b)) |
| 3604 | | m_x87_sw |= X87_SW_C3; |
| 3605 | | |
| 3606 | | if (floatx80_lt(a, b)) |
| 3607 | | m_x87_sw |= X87_SW_C0; |
| 3608 | | } |
| 3609 | | } |
| 3610 | | |
| 3611 | | x87_check_exceptions(); |
| 3612 | | |
| 3613 | | CYCLES(4); |
| 3614 | | } |
| 3615 | | |
| 3616 | | void i386_device::x87_fcom_sti(UINT8 modrm) |
| 3617 | | { |
| 3618 | | int i = modrm & 7; |
| 3619 | | |
| 3620 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 3621 | | { |
| 3622 | | x87_set_stack_underflow(); |
| 3623 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3624 | | } |
| 3625 | | else |
| 3626 | | { |
| 3627 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3628 | | |
| 3629 | | floatx80 a = ST(0); |
| 3630 | | floatx80 b = ST(i); |
| 3631 | | |
| 3632 | | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3633 | | { |
| 3634 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3635 | | m_x87_sw |= X87_SW_IE; |
| 3636 | | } |
| 3637 | | else |
| 3638 | | { |
| 3639 | | if (floatx80_eq(a, b)) |
| 3640 | | m_x87_sw |= X87_SW_C3; |
| 3641 | | |
| 3642 | | if (floatx80_lt(a, b)) |
| 3643 | | m_x87_sw |= X87_SW_C0; |
| 3644 | | } |
| 3645 | | } |
| 3646 | | |
| 3647 | | x87_check_exceptions(); |
| 3648 | | |
| 3649 | | CYCLES(4); |
| 3650 | | } |
| 3651 | | |
| 3652 | | void i386_device::x87_fcomp_m32real(UINT8 modrm) |
| 3653 | | { |
| 3654 | | UINT32 ea = GetEA(modrm, 0); |
| 3655 | | if (X87_IS_ST_EMPTY(0)) |
| 3656 | | { |
| 3657 | | x87_set_stack_underflow(); |
| 3658 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3659 | | } |
| 3660 | | else |
| 3661 | | { |
| 3662 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3663 | | |
| 3664 | | UINT32 m32real = READ32(ea); |
| 3665 | | |
| 3666 | | floatx80 a = ST(0); |
| 3667 | | floatx80 b = float32_to_floatx80(m32real); |
| 3668 | | |
| 3669 | | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3670 | | { |
| 3671 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3672 | | m_x87_sw |= X87_SW_IE; |
| 3673 | | } |
| 3674 | | else |
| 3675 | | { |
| 3676 | | if (floatx80_eq(a, b)) |
| 3677 | | m_x87_sw |= X87_SW_C3; |
| 3678 | | |
| 3679 | | if (floatx80_lt(a, b)) |
| 3680 | | m_x87_sw |= X87_SW_C0; |
| 3681 | | } |
| 3682 | | } |
| 3683 | | |
| 3684 | | if (x87_check_exceptions()) |
| 3685 | | x87_inc_stack(); |
| 3686 | | |
| 3687 | | CYCLES(4); |
| 3688 | | } |
| 3689 | | |
| 3690 | | void i386_device::x87_fcomp_m64real(UINT8 modrm) |
| 3691 | | { |
| 3692 | | UINT32 ea = GetEA(modrm, 0); |
| 3693 | | if (X87_IS_ST_EMPTY(0)) |
| 3694 | | { |
| 3695 | | x87_set_stack_underflow(); |
| 3696 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3697 | | } |
| 3698 | | else |
| 3699 | | { |
| 3700 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3701 | | |
| 3702 | | UINT64 m64real = READ64(ea); |
| 3703 | | |
| 3704 | | floatx80 a = ST(0); |
| 3705 | | floatx80 b = float64_to_floatx80(m64real); |
| 3706 | | |
| 3707 | | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3708 | | { |
| 3709 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3710 | | m_x87_sw |= X87_SW_IE; |
| 3711 | | } |
| 3712 | | else |
| 3713 | | { |
| 3714 | | if (floatx80_eq(a, b)) |
| 3715 | | m_x87_sw |= X87_SW_C3; |
| 3716 | | |
| 3717 | | if (floatx80_lt(a, b)) |
| 3718 | | m_x87_sw |= X87_SW_C0; |
| 3719 | | } |
| 3720 | | } |
| 3721 | | |
| 3722 | | if (x87_check_exceptions()) |
| 3723 | | x87_inc_stack(); |
| 3724 | | |
| 3725 | | CYCLES(4); |
| 3726 | | } |
| 3727 | | |
| 3728 | | void i386_device::x87_fcomp_sti(UINT8 modrm) |
| 3729 | | { |
| 3730 | | int i = modrm & 7; |
| 3731 | | |
| 3732 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 3733 | | { |
| 3734 | | x87_set_stack_underflow(); |
| 3735 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3736 | | } |
| 3737 | | else |
| 3738 | | { |
| 3739 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3740 | | |
| 3741 | | floatx80 a = ST(0); |
| 3742 | | floatx80 b = ST(i); |
| 3743 | | |
| 3744 | | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3745 | | { |
| 3746 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3747 | | m_x87_sw |= X87_SW_IE; |
| 3748 | | } |
| 3749 | | else |
| 3750 | | { |
| 3751 | | if (floatx80_eq(a, b)) |
| 3752 | | m_x87_sw |= X87_SW_C3; |
| 3753 | | |
| 3754 | | if (floatx80_lt(a, b)) |
| 3755 | | m_x87_sw |= X87_SW_C0; |
| 3756 | | } |
| 3757 | | } |
| 3758 | | |
| 3759 | | if (x87_check_exceptions()) |
| 3760 | | x87_inc_stack(); |
| 3761 | | |
| 3762 | | CYCLES(4); |
| 3763 | | } |
| 3764 | | |
| 3765 | | void i386_device::x87_fcomip_sti(UINT8 modrm) |
| 3766 | | { |
| 3767 | | int i = modrm & 7; |
| 3768 | | |
| 3769 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 3770 | | { |
| 3771 | | x87_set_stack_underflow(); |
| 3772 | | m_ZF = 1; |
| 3773 | | m_PF = 1; |
| 3774 | | m_CF = 1; |
| 3775 | | } |
| 3776 | | else |
| 3777 | | { |
| 3778 | | m_x87_sw &= ~X87_SW_C1; |
| 3779 | | |
| 3780 | | floatx80 a = ST(0); |
| 3781 | | floatx80 b = ST(i); |
| 3782 | | |
| 3783 | | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3784 | | { |
| 3785 | | m_ZF = 1; |
| 3786 | | m_PF = 1; |
| 3787 | | m_CF = 1; |
| 3788 | | m_x87_sw |= X87_SW_IE; |
| 3789 | | } |
| 3790 | | else |
| 3791 | | { |
| 3792 | | m_ZF = 0; |
| 3793 | | m_PF = 0; |
| 3794 | | m_CF = 0; |
| 3795 | | |
| 3796 | | if (floatx80_eq(a, b)) |
| 3797 | | m_ZF = 1; |
| 3798 | | |
| 3799 | | if (floatx80_lt(a, b)) |
| 3800 | | m_CF = 1; |
| 3801 | | } |
| 3802 | | } |
| 3803 | | |
| 3804 | | if (x87_check_exceptions()) |
| 3805 | | x87_inc_stack(); |
| 3806 | | |
| 3807 | | CYCLES(4); // TODO: correct cycle count |
| 3808 | | } |
| 3809 | | |
| 3810 | | void i386_device::x87_fcompp(UINT8 modrm) |
| 3811 | | { |
| 3812 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 3813 | | { |
| 3814 | | x87_set_stack_underflow(); |
| 3815 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3816 | | } |
| 3817 | | else |
| 3818 | | { |
| 3819 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3820 | | |
| 3821 | | floatx80 a = ST(0); |
| 3822 | | floatx80 b = ST(1); |
| 3823 | | |
| 3824 | | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3825 | | { |
| 3826 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3827 | | m_x87_sw |= X87_SW_IE; |
| 3828 | | } |
| 3829 | | else |
| 3830 | | { |
| 3831 | | if (floatx80_eq(a, b)) |
| 3832 | | m_x87_sw |= X87_SW_C3; |
| 3833 | | |
| 3834 | | if (floatx80_lt(a, b)) |
| 3835 | | m_x87_sw |= X87_SW_C0; |
| 3836 | | } |
| 3837 | | } |
| 3838 | | |
| 3839 | | if (x87_check_exceptions()) |
| 3840 | | { |
| 3841 | | x87_inc_stack(); |
| 3842 | | x87_inc_stack(); |
| 3843 | | } |
| 3844 | | |
| 3845 | | CYCLES(5); |
| 3846 | | } |
| 3847 | | |
| 3848 | | |
| 3849 | | /************************************* |
| 3850 | | * |
| 3851 | | * Unordererd comparison |
| 3852 | | * |
| 3853 | | *************************************/ |
| 3854 | | |
| 3855 | | void i386_device::x87_fucom_sti(UINT8 modrm) |
| 3856 | | { |
| 3857 | | int i = modrm & 7; |
| 3858 | | |
| 3859 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 3860 | | { |
| 3861 | | x87_set_stack_underflow(); |
| 3862 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3863 | | } |
| 3864 | | else |
| 3865 | | { |
| 3866 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3867 | | |
| 3868 | | floatx80 a = ST(0); |
| 3869 | | floatx80 b = ST(i); |
| 3870 | | |
| 3871 | | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3872 | | { |
| 3873 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3874 | | |
| 3875 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 3876 | | m_x87_sw |= X87_SW_IE; |
| 3877 | | } |
| 3878 | | else |
| 3879 | | { |
| 3880 | | if (floatx80_eq(a, b)) |
| 3881 | | m_x87_sw |= X87_SW_C3; |
| 3882 | | |
| 3883 | | if (floatx80_lt(a, b)) |
| 3884 | | m_x87_sw |= X87_SW_C0; |
| 3885 | | } |
| 3886 | | } |
| 3887 | | |
| 3888 | | x87_check_exceptions(); |
| 3889 | | |
| 3890 | | CYCLES(4); |
| 3891 | | } |
| 3892 | | |
| 3893 | | void i386_device::x87_fucomp_sti(UINT8 modrm) |
| 3894 | | { |
| 3895 | | int i = modrm & 7; |
| 3896 | | |
| 3897 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 3898 | | { |
| 3899 | | x87_set_stack_underflow(); |
| 3900 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3901 | | } |
| 3902 | | else |
| 3903 | | { |
| 3904 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3905 | | |
| 3906 | | floatx80 a = ST(0); |
| 3907 | | floatx80 b = ST(i); |
| 3908 | | |
| 3909 | | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3910 | | { |
| 3911 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3912 | | |
| 3913 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 3914 | | m_x87_sw |= X87_SW_IE; |
| 3915 | | } |
| 3916 | | else |
| 3917 | | { |
| 3918 | | if (floatx80_eq(a, b)) |
| 3919 | | m_x87_sw |= X87_SW_C3; |
| 3920 | | |
| 3921 | | if (floatx80_lt(a, b)) |
| 3922 | | m_x87_sw |= X87_SW_C0; |
| 3923 | | } |
| 3924 | | } |
| 3925 | | |
| 3926 | | if (x87_check_exceptions()) |
| 3927 | | x87_inc_stack(); |
| 3928 | | |
| 3929 | | CYCLES(4); |
| 3930 | | } |
| 3931 | | |
| 3932 | | void i386_device::x87_fucompp(UINT8 modrm) |
| 3933 | | { |
| 3934 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 3935 | | { |
| 3936 | | x87_set_stack_underflow(); |
| 3937 | | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3938 | | } |
| 3939 | | else |
| 3940 | | { |
| 3941 | | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3942 | | |
| 3943 | | floatx80 a = ST(0); |
| 3944 | | floatx80 b = ST(1); |
| 3945 | | |
| 3946 | | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3947 | | { |
| 3948 | | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3949 | | |
| 3950 | | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 3951 | | m_x87_sw |= X87_SW_IE; |
| 3952 | | } |
| 3953 | | else |
| 3954 | | { |
| 3955 | | if (floatx80_eq(a, b)) |
| 3956 | | m_x87_sw |= X87_SW_C3; |
| 3957 | | |
| 3958 | | if (floatx80_lt(a, b)) |
| 3959 | | m_x87_sw |= X87_SW_C0; |
| 3960 | | } |
| 3961 | | } |
| 3962 | | |
| 3963 | | if (x87_check_exceptions()) |
| 3964 | | { |
| 3965 | | x87_inc_stack(); |
| 3966 | | x87_inc_stack(); |
| 3967 | | } |
| 3968 | | |
| 3969 | | CYCLES(4); |
| 3970 | | } |
| 3971 | | |
| 3972 | | |
| 3973 | | /************************************* |
| 3974 | | * |
| 3975 | | * Control |
| 3976 | | * |
| 3977 | | *************************************/ |
| 3978 | | |
| 3979 | | void i386_device::x87_fdecstp(UINT8 modrm) |
| 3980 | | { |
| 3981 | | m_x87_sw &= ~X87_SW_C1; |
| 3982 | | |
| 3983 | | x87_dec_stack(); |
| 3984 | | x87_check_exceptions(); |
| 3985 | | |
| 3986 | | CYCLES(3); |
| 3987 | | } |
| 3988 | | |
| 3989 | | void i386_device::x87_fincstp(UINT8 modrm) |
| 3990 | | { |
| 3991 | | m_x87_sw &= ~X87_SW_C1; |
| 3992 | | |
| 3993 | | x87_inc_stack(); |
| 3994 | | x87_check_exceptions(); |
| 3995 | | |
| 3996 | | CYCLES(3); |
| 3997 | | } |
| 3998 | | |
| 3999 | | void i386_device::x87_fclex(UINT8 modrm) |
| 4000 | | { |
| 4001 | | m_x87_sw &= ~0x80ff; |
| 4002 | | |
| 4003 | | CYCLES(7); |
| 4004 | | } |
| 4005 | | |
| 4006 | | void i386_device::x87_ffree(UINT8 modrm) |
| 4007 | | { |
| 4008 | | x87_set_tag(ST_TO_PHYS(modrm & 7), X87_TW_EMPTY); |
| 4009 | | |
| 4010 | | CYCLES(3); |
| 4011 | | } |
| 4012 | | |
| 4013 | | void i386_device::x87_finit(UINT8 modrm) |
| 4014 | | { |
| 4015 | | x87_reset(); |
| 4016 | | |
| 4017 | | CYCLES(17); |
| 4018 | | } |
| 4019 | | |
| 4020 | | void i386_device::x87_fldcw(UINT8 modrm) |
| 4021 | | { |
| 4022 | | UINT32 ea = GetEA(modrm, 0); |
| 4023 | | UINT16 cw = READ16(ea); |
| 4024 | | |
| 4025 | | x87_write_cw(cw); |
| 4026 | | |
| 4027 | | x87_check_exceptions(); |
| 4028 | | |
| 4029 | | CYCLES(4); |
| 4030 | | } |
| 4031 | | |
| 4032 | | void i386_device::x87_fstcw(UINT8 modrm) |
| 4033 | | { |
| 4034 | | UINT32 ea = GetEA(modrm, 1); |
| 4035 | | WRITE16(ea, m_x87_cw); |
| 4036 | | |
| 4037 | | CYCLES(3); |
| 4038 | | } |
| 4039 | | |
| 4040 | | void i386_device::x87_fldenv(UINT8 modrm) |
| 4041 | | { |
| 4042 | | // TODO: Pointers and selectors |
| 4043 | | UINT32 ea = GetEA(modrm, 0); |
| 4044 | | |
| 4045 | | if (m_operand_size) |
| 4046 | | { |
| 4047 | | // 32-bit real/protected mode |
| 4048 | | x87_write_cw(READ16(ea)); |
| 4049 | | m_x87_sw = READ16(ea + 4); |
| 4050 | | m_x87_tw = READ16(ea + 8); |
| 4051 | | } |
| 4052 | | else |
| 4053 | | { |
| 4054 | | // 16-bit real/protected mode |
| 4055 | | x87_write_cw(READ16(ea)); |
| 4056 | | m_x87_sw = READ16(ea + 2); |
| 4057 | | m_x87_tw = READ16(ea + 4); |
| 4058 | | } |
| 4059 | | |
| 4060 | | x87_check_exceptions(); |
| 4061 | | |
| 4062 | | CYCLES((m_cr[0] & 1) ? 34 : 44); |
| 4063 | | } |
| 4064 | | |
| 4065 | | void i386_device::x87_fstenv(UINT8 modrm) |
| 4066 | | { |
| 4067 | | UINT32 ea = GetEA(modrm, 1); |
| 4068 | | |
| 4069 | | // TODO: Pointers and selectors |
| 4070 | | switch((m_cr[0] & 1)|(m_operand_size & 1)<<1) |
| 4071 | | { |
| 4072 | | case 0: // 16-bit real mode |
| 4073 | | WRITE16(ea + 0, m_x87_cw); |
| 4074 | | WRITE16(ea + 2, m_x87_sw); |
| 4075 | | WRITE16(ea + 4, m_x87_tw); |
| 4076 | | // WRITE16(ea + 6, m_fpu_inst_ptr & 0xffff); |
| 4077 | | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4078 | | // WRITE16(ea + 10, m_fpu_data_ptr & 0xffff); |
| 4079 | | // WRITE16(ea + 12, (m_fpu_inst_ptr & 0x0f0000) >> 4); |
| 4080 | | break; |
| 4081 | | case 1: // 16-bit protected mode |
| 4082 | | WRITE16(ea + 0, m_x87_cw); |
| 4083 | | WRITE16(ea + 2, m_x87_sw); |
| 4084 | | WRITE16(ea + 4, m_x87_tw); |
| 4085 | | // WRITE16(ea + 6, m_fpu_inst_ptr & 0xffff); |
| 4086 | | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4087 | | // WRITE16(ea + 10, m_fpu_data_ptr & 0xffff); |
| 4088 | | // WRITE16(ea + 12, (m_fpu_inst_ptr & 0x0f0000) >> 4); |
| 4089 | | break; |
| 4090 | | case 2: // 32-bit real mode |
| 4091 | | WRITE16(ea + 0, m_x87_cw); |
| 4092 | | WRITE16(ea + 4, m_x87_sw); |
| 4093 | | WRITE16(ea + 8, m_x87_tw); |
| 4094 | | // WRITE16(ea + 12, m_fpu_inst_ptr & 0xffff); |
| 4095 | | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4096 | | // WRITE16(ea + 20, m_fpu_data_ptr & 0xffff); |
| 4097 | | // WRITE16(ea + 12, ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4098 | | // WRITE32(ea + 24, (m_fpu_data_ptr >> 16) << 12); |
| 4099 | | break; |
| 4100 | | case 3: // 32-bit protected mode |
| 4101 | | WRITE16(ea + 0, m_x87_cw); |
| 4102 | | WRITE16(ea + 4, m_x87_sw); |
| 4103 | | WRITE16(ea + 8, m_x87_tw); |
| 4104 | | // WRITE32(ea + 12, m_fpu_inst_ptr); |
| 4105 | | // WRITE32(ea + 16, m_fpu_opcode); |
| 4106 | | // WRITE32(ea + 20, m_fpu_data_ptr); |
| 4107 | | // WRITE32(ea + 24, m_fpu_inst_ptr); |
| 4108 | | break; |
| 4109 | | } |
| 4110 | | |
| 4111 | | CYCLES((m_cr[0] & 1) ? 56 : 67); |
| 4112 | | } |
| 4113 | | |
| 4114 | | void i386_device::x87_fsave(UINT8 modrm) |
| 4115 | | { |
| 4116 | | UINT32 ea = GetEA(modrm, 1); |
| 4117 | | |
| 4118 | | // TODO: Pointers and selectors |
| 4119 | | switch((m_cr[0] & 1)|(m_operand_size & 1)<<1) |
| 4120 | | { |
| 4121 | | case 0: // 16-bit real mode |
| 4122 | | WRITE16(ea + 0, m_x87_cw); |
| 4123 | | WRITE16(ea + 2, m_x87_sw); |
| 4124 | | WRITE16(ea + 4, m_x87_tw); |
| 4125 | | // WRITE16(ea + 6, m_fpu_inst_ptr & 0xffff); |
| 4126 | | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4127 | | // WRITE16(ea + 10, m_fpu_data_ptr & 0xffff); |
| 4128 | | // WRITE16(ea + 12, (m_fpu_inst_ptr & 0x0f0000) >> 4); |
| 4129 | | ea += 14; |
| 4130 | | break; |
| 4131 | | case 1: // 16-bit protected mode |
| 4132 | | WRITE16(ea + 0, m_x87_cw); |
| 4133 | | WRITE16(ea + 2, m_x87_sw); |
| 4134 | | WRITE16(ea + 4, m_x87_tw); |
| 4135 | | // WRITE16(ea + 6, m_fpu_inst_ptr & 0xffff); |
| 4136 | | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4137 | | // WRITE16(ea + 10, m_fpu_data_ptr & 0xffff); |
| 4138 | | // WRITE16(ea + 12, (m_fpu_inst_ptr & 0x0f0000) >> 4); |
| 4139 | | ea += 14; |
| 4140 | | break; |
| 4141 | | case 2: // 32-bit real mode |
| 4142 | | WRITE16(ea + 0, m_x87_cw); |
| 4143 | | WRITE16(ea + 4, m_x87_sw); |
| 4144 | | WRITE16(ea + 8, m_x87_tw); |
| 4145 | | // WRITE16(ea + 12, m_fpu_inst_ptr & 0xffff); |
| 4146 | | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4147 | | // WRITE16(ea + 20, m_fpu_data_ptr & 0xffff); |
| 4148 | | // WRITE16(ea + 12, ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4149 | | // WRITE32(ea + 24, (m_fpu_data_ptr >> 16) << 12); |
| 4150 | | ea += 28; |
| 4151 | | break; |
| 4152 | | case 3: // 32-bit protected mode |
| 4153 | | WRITE16(ea + 0, m_x87_cw); |
| 4154 | | WRITE16(ea + 4, m_x87_sw); |
| 4155 | | WRITE16(ea + 8, m_x87_tw); |
| 4156 | | // WRITE32(ea + 12, m_fpu_inst_ptr); |
| 4157 | | // WRITE32(ea + 16, m_fpu_opcode); |
| 4158 | | // WRITE32(ea + 20, m_fpu_data_ptr); |
| 4159 | | // WRITE32(ea + 24, m_fpu_inst_ptr); |
| 4160 | | ea += 28; |
| 4161 | | break; |
| 4162 | | } |
| 4163 | | |
| 4164 | | for (int i = 0; i < 8; ++i) |
| 4165 | | x87_write_stack(i, READ80(ea + i*10), FALSE); |
| 4166 | | |
| 4167 | | CYCLES((m_cr[0] & 1) ? 56 : 67); |
| 4168 | | } |
| 4169 | | |
| 4170 | | void i386_device::x87_frstor(UINT8 modrm) |
| 4171 | | { |
| 4172 | | UINT32 ea = GetEA(modrm, 0); |
| 4173 | | |
| 4174 | | // TODO: Pointers and selectors |
| 4175 | | switch((m_cr[0] & 1)|(m_operand_size & 1)<<1) |
| 4176 | | { |
| 4177 | | case 0: // 16-bit real mode |
| 4178 | | x87_write_cw(READ16(ea)); |
| 4179 | | m_x87_sw = READ16(ea + 2); |
| 4180 | | m_x87_tw = READ16(ea + 4); |
| 4181 | | // WRITE16(ea + 6, m_fpu_inst_ptr & 0xffff); |
| 4182 | | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4183 | | // WRITE16(ea + 10, m_fpu_data_ptr & 0xffff); |
| 4184 | | // WRITE16(ea + 12, (m_fpu_inst_ptr & 0x0f0000) >> 4); |
| 4185 | | ea += 14; |
| 4186 | | break; |
| 4187 | | case 1: // 16-bit protected mode |
| 4188 | | x87_write_cw(READ16(ea)); |
| 4189 | | m_x87_sw = READ16(ea + 2); |
| 4190 | | m_x87_tw = READ16(ea + 4); |
| 4191 | | // WRITE16(ea + 6, m_fpu_inst_ptr & 0xffff); |
| 4192 | | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4193 | | // WRITE16(ea + 10, m_fpu_data_ptr & 0xffff); |
| 4194 | | // WRITE16(ea + 12, (m_fpu_inst_ptr & 0x0f0000) >> 4); |
| 4195 | | ea += 14; |
| 4196 | | break; |
| 4197 | | case 2: // 32-bit real mode |
| 4198 | | x87_write_cw(READ16(ea)); |
| 4199 | | m_x87_sw = READ16(ea + 4); |
| 4200 | | m_x87_tw = READ16(ea + 8); |
| 4201 | | // WRITE16(ea + 12, m_fpu_inst_ptr & 0xffff); |
| 4202 | | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4203 | | // WRITE16(ea + 20, m_fpu_data_ptr & 0xffff); |
| 4204 | | // WRITE16(ea + 12, ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4205 | | // WRITE32(ea + 24, (m_fpu_data_ptr >> 16) << 12); |
| 4206 | | ea += 28; |
| 4207 | | break; |
| 4208 | | case 3: // 32-bit protected mode |
| 4209 | | x87_write_cw(READ16(ea)); |
| 4210 | | m_x87_sw = READ16(ea + 4); |
| 4211 | | m_x87_tw = READ16(ea + 8); |
| 4212 | | // WRITE32(ea + 12, m_fpu_inst_ptr); |
| 4213 | | // WRITE32(ea + 16, m_fpu_opcode); |
| 4214 | | // WRITE32(ea + 20, m_fpu_data_ptr); |
| 4215 | | // WRITE32(ea + 24, m_fpu_inst_ptr); |
| 4216 | | ea += 28; |
| 4217 | | break; |
| 4218 | | } |
| 4219 | | |
| 4220 | | for (int i = 0; i < 8; ++i) |
| 4221 | | WRITE80(ea + i*10, ST(i)); |
| 4222 | | |
| 4223 | | CYCLES((m_cr[0] & 1) ? 34 : 44); |
| 4224 | | } |
| 4225 | | |
| 4226 | | void i386_device::x87_fxch(UINT8 modrm) |
| 4227 | | { |
| 4228 | | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 4229 | | x87_set_stack_underflow(); |
| 4230 | | |
| 4231 | | if (x87_check_exceptions()) |
| 4232 | | { |
| 4233 | | floatx80 tmp = ST(0); |
| 4234 | | ST(0) = ST(1); |
| 4235 | | ST(1) = tmp; |
| 4236 | | |
| 4237 | | // Swap the tags |
| 4238 | | int tag0 = X87_TAG(ST_TO_PHYS(0)); |
| 4239 | | x87_set_tag(ST_TO_PHYS(0), X87_TAG(ST_TO_PHYS(1))); |
| 4240 | | x87_set_tag(ST_TO_PHYS(1), tag0); |
| 4241 | | } |
| 4242 | | |
| 4243 | | CYCLES(4); |
| 4244 | | } |
| 4245 | | |
| 4246 | | void i386_device::x87_fxch_sti(UINT8 modrm) |
| 4247 | | { |
| 4248 | | int i = modrm & 7; |
| 4249 | | |
| 4250 | | if (X87_IS_ST_EMPTY(0)) |
| 4251 | | { |
| 4252 | | ST(0) = fx80_inan; |
| 4253 | | x87_set_tag(ST_TO_PHYS(0), X87_TW_SPECIAL); |
| 4254 | | x87_set_stack_underflow(); |
| 4255 | | } |
| 4256 | | if (X87_IS_ST_EMPTY(i)) |
| 4257 | | { |
| 4258 | | ST(i) = fx80_inan; |
| 4259 | | x87_set_tag(ST_TO_PHYS(i), X87_TW_SPECIAL); |
| 4260 | | x87_set_stack_underflow(); |
| 4261 | | } |
| 4262 | | |
| 4263 | | if (x87_check_exceptions()) |
| 4264 | | { |
| 4265 | | floatx80 tmp = ST(0); |
| 4266 | | ST(0) = ST(i); |
| 4267 | | ST(i) = tmp; |
| 4268 | | |
| 4269 | | // Swap the tags |
| 4270 | | int tag0 = X87_TAG(ST_TO_PHYS(0)); |
| 4271 | | x87_set_tag(ST_TO_PHYS(0), X87_TAG(ST_TO_PHYS(i))); |
| 4272 | | x87_set_tag(ST_TO_PHYS(i), tag0); |
| 4273 | | } |
| 4274 | | |
| 4275 | | CYCLES(4); |
| 4276 | | } |
| 4277 | | |
| 4278 | | void i386_device::x87_fstsw_ax(UINT8 modrm) |
| 4279 | | { |
| 4280 | | REG16(AX) = m_x87_sw; |
| 4281 | | |
| 4282 | | CYCLES(3); |
| 4283 | | } |
| 4284 | | |
| 4285 | | void i386_device::x87_fstsw_m2byte(UINT8 modrm) |
| 4286 | | { |
| 4287 | | UINT32 ea = GetEA(modrm, 1); |
| 4288 | | |
| 4289 | | WRITE16(ea, m_x87_sw); |
| 4290 | | |
| 4291 | | CYCLES(3); |
| 4292 | | } |
| 4293 | | |
| 4294 | | void i386_device::x87_invalid(UINT8 modrm) |
| 4295 | | { |
| 4296 | | // TODO |
| 4297 | | fatalerror("x87 invalid instruction (PC:%.4x)\n", m_pc); |
| 4298 | | } |
| 4299 | | |
| 4300 | | |
| 4301 | | |
| 4302 | | /************************************* |
| 4303 | | * |
| 4304 | | * Instruction dispatch |
| 4305 | | * |
| 4306 | | *************************************/ |
| 4307 | | |
| 4308 | | void i386_device::i386_x87_group_d8() |
| 4309 | | { |
| 4310 | | UINT8 modrm = FETCH(); |
| 4311 | | (this->*m_opcode_table_x87_d8[modrm])(modrm); |
| 4312 | | } |
| 4313 | | |
| 4314 | | void i386_device::i386_x87_group_d9() |
| 4315 | | { |
| 4316 | | UINT8 modrm = FETCH(); |
| 4317 | | (this->*m_opcode_table_x87_d9[modrm])(modrm); |
| 4318 | | } |
| 4319 | | |
| 4320 | | void i386_device::i386_x87_group_da() |
| 4321 | | { |
| 4322 | | UINT8 modrm = FETCH(); |
| 4323 | | (this->*m_opcode_table_x87_da[modrm])(modrm); |
| 4324 | | } |
| 4325 | | |
| 4326 | | void i386_device::i386_x87_group_db() |
| 4327 | | { |
| 4328 | | UINT8 modrm = FETCH(); |
| 4329 | | (this->*m_opcode_table_x87_db[modrm])(modrm); |
| 4330 | | } |
| 4331 | | |
| 4332 | | void i386_device::i386_x87_group_dc() |
| 4333 | | { |
| 4334 | | UINT8 modrm = FETCH(); |
| 4335 | | (this->*m_opcode_table_x87_dc[modrm])(modrm); |
| 4336 | | } |
| 4337 | | |
| 4338 | | void i386_device::i386_x87_group_dd() |
| 4339 | | { |
| 4340 | | UINT8 modrm = FETCH(); |
| 4341 | | (this->*m_opcode_table_x87_dd[modrm])(modrm); |
| 4342 | | } |
| 4343 | | |
| 4344 | | void i386_device::i386_x87_group_de() |
| 4345 | | { |
| 4346 | | UINT8 modrm = FETCH(); |
| 4347 | | (this->*m_opcode_table_x87_de[modrm])(modrm); |
| 4348 | | } |
| 4349 | | |
| 4350 | | void i386_device::i386_x87_group_df() |
| 4351 | | { |
| 4352 | | UINT8 modrm = FETCH(); |
| 4353 | | (this->*m_opcode_table_x87_df[modrm])(modrm); |
| 4354 | | } |
| 4355 | | |
| 4356 | | |
| 4357 | | /************************************* |
| 4358 | | * |
| 4359 | | * Opcode table building |
| 4360 | | * |
| 4361 | | *************************************/ |
| 4362 | | |
| 4363 | | void i386_device::build_x87_opcode_table_d8() |
| 4364 | | { |
| 4365 | | int modrm = 0; |
| 4366 | | |
| 4367 | | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4368 | | { |
| 4369 | | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4370 | | |
| 4371 | | if (modrm < 0xc0) |
| 4372 | | { |
| 4373 | | switch ((modrm >> 3) & 0x7) |
| 4374 | | { |
| 4375 | | case 0x00: ptr = &i386_device::x87_fadd_m32real; break; |
| 4376 | | case 0x01: ptr = &i386_device::x87_fmul_m32real; break; |
| 4377 | | case 0x02: ptr = &i386_device::x87_fcom_m32real; break; |
| 4378 | | case 0x03: ptr = &i386_device::x87_fcomp_m32real; break; |
| 4379 | | case 0x04: ptr = &i386_device::x87_fsub_m32real; break; |
| 4380 | | case 0x05: ptr = &i386_device::x87_fsubr_m32real; break; |
| 4381 | | case 0x06: ptr = &i386_device::x87_fdiv_m32real; break; |
| 4382 | | case 0x07: ptr = &i386_device::x87_fdivr_m32real; break; |
| 4383 | | } |
| 4384 | | } |
| 4385 | | else |
| 4386 | | { |
| 4387 | | switch (modrm) |
| 4388 | | { |
| 4389 | | case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &i386_device::x87_fadd_st_sti; break; |
| 4390 | | case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &i386_device::x87_fmul_st_sti; break; |
| 4391 | | case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: ptr = &i386_device::x87_fcom_sti; break; |
| 4392 | | case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: ptr = &i386_device::x87_fcomp_sti; break; |
| 4393 | | case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = &i386_device::x87_fsub_st_sti; break; |
| 4394 | | case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &i386_device::x87_fsubr_st_sti; break; |
| 4395 | | case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = &i386_device::x87_fdiv_st_sti; break; |
| 4396 | | case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: ptr = &i386_device::x87_fdivr_st_sti; break; |
| 4397 | | } |
| 4398 | | } |
| 4399 | | |
| 4400 | | m_opcode_table_x87_d8[modrm] = ptr; |
| 4401 | | } |
| 4402 | | } |
| 4403 | | |
| 4404 | | |
| 4405 | | void i386_device::build_x87_opcode_table_d9() |
| 4406 | | { |
| 4407 | | int modrm = 0; |
| 4408 | | |
| 4409 | | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4410 | | { |
| 4411 | | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4412 | | |
| 4413 | | if (modrm < 0xc0) |
| 4414 | | { |
| 4415 | | switch ((modrm >> 3) & 0x7) |
| 4416 | | { |
| 4417 | | case 0x00: ptr = &i386_device::x87_fld_m32real; break; |
| 4418 | | case 0x02: ptr = &i386_device::x87_fst_m32real; break; |
| 4419 | | case 0x03: ptr = &i386_device::x87_fstp_m32real; break; |
| 4420 | | case 0x04: ptr = &i386_device::x87_fldenv; break; |
| 4421 | | case 0x05: ptr = &i386_device::x87_fldcw; break; |
| 4422 | | case 0x06: ptr = &i386_device::x87_fstenv; break; |
| 4423 | | case 0x07: ptr = &i386_device::x87_fstcw; break; |
| 4424 | | } |
| 4425 | | } |
| 4426 | | else |
| 4427 | | { |
| 4428 | | switch (modrm) |
| 4429 | | { |
| 4430 | | case 0xc0: |
| 4431 | | case 0xc1: |
| 4432 | | case 0xc2: |
| 4433 | | case 0xc3: |
| 4434 | | case 0xc4: |
| 4435 | | case 0xc5: |
| 4436 | | case 0xc6: |
| 4437 | | case 0xc7: ptr = &i386_device::x87_fld_sti; break; |
| 4438 | | |
| 4439 | | case 0xc8: |
| 4440 | | case 0xc9: |
| 4441 | | case 0xca: |
| 4442 | | case 0xcb: |
| 4443 | | case 0xcc: |
| 4444 | | case 0xcd: |
| 4445 | | case 0xce: |
| 4446 | | case 0xcf: ptr = &i386_device::x87_fxch_sti; break; |
| 4447 | | |
| 4448 | | case 0xd0: ptr = &i386_device::x87_fnop; break; |
| 4449 | | case 0xe0: ptr = &i386_device::x87_fchs; break; |
| 4450 | | case 0xe1: ptr = &i386_device::x87_fabs; break; |
| 4451 | | case 0xe4: ptr = &i386_device::x87_ftst; break; |
| 4452 | | case 0xe5: ptr = &i386_device::x87_fxam; break; |
| 4453 | | case 0xe8: ptr = &i386_device::x87_fld1; break; |
| 4454 | | case 0xe9: ptr = &i386_device::x87_fldl2t; break; |
| 4455 | | case 0xea: ptr = &i386_device::x87_fldl2e; break; |
| 4456 | | case 0xeb: ptr = &i386_device::x87_fldpi; break; |
| 4457 | | case 0xec: ptr = &i386_device::x87_fldlg2; break; |
| 4458 | | case 0xed: ptr = &i386_device::x87_fldln2; break; |
| 4459 | | case 0xee: ptr = &i386_device::x87_fldz; break; |
| 4460 | | case 0xf0: ptr = &i386_device::x87_f2xm1; break; |
| 4461 | | case 0xf1: ptr = &i386_device::x87_fyl2x; break; |
| 4462 | | case 0xf2: ptr = &i386_device::x87_fptan; break; |
| 4463 | | case 0xf3: ptr = &i386_device::x87_fpatan; break; |
| 4464 | | case 0xf4: ptr = &i386_device::x87_fxtract; break; |
| 4465 | | case 0xf5: ptr = &i386_device::x87_fprem1; break; |
| 4466 | | case 0xf6: ptr = &i386_device::x87_fdecstp; break; |
| 4467 | | case 0xf7: ptr = &i386_device::x87_fincstp; break; |
| 4468 | | case 0xf8: ptr = &i386_device::x87_fprem; break; |
| 4469 | | case 0xf9: ptr = &i386_device::x87_fyl2xp1; break; |
| 4470 | | case 0xfa: ptr = &i386_device::x87_fsqrt; break; |
| 4471 | | case 0xfb: ptr = &i386_device::x87_fsincos; break; |
| 4472 | | case 0xfc: ptr = &i386_device::x87_frndint; break; |
| 4473 | | case 0xfd: ptr = &i386_device::x87_fscale; break; |
| 4474 | | case 0xfe: ptr = &i386_device::x87_fsin; break; |
| 4475 | | case 0xff: ptr = &i386_device::x87_fcos; break; |
| 4476 | | } |
| 4477 | | } |
| 4478 | | |
| 4479 | | m_opcode_table_x87_d9[modrm] = ptr; |
| 4480 | | } |
| 4481 | | } |
| 4482 | | |
| 4483 | | void i386_device::build_x87_opcode_table_da() |
| 4484 | | { |
| 4485 | | int modrm = 0; |
| 4486 | | |
| 4487 | | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4488 | | { |
| 4489 | | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4490 | | |
| 4491 | | if (modrm < 0xc0) |
| 4492 | | { |
| 4493 | | switch ((modrm >> 3) & 0x7) |
| 4494 | | { |
| 4495 | | case 0x00: ptr = &i386_device::x87_fiadd_m32int; break; |
| 4496 | | case 0x01: ptr = &i386_device::x87_fimul_m32int; break; |
| 4497 | | case 0x02: ptr = &i386_device::x87_ficom_m32int; break; |
| 4498 | | case 0x03: ptr = &i386_device::x87_ficomp_m32int; break; |
| 4499 | | case 0x04: ptr = &i386_device::x87_fisub_m32int; break; |
| 4500 | | case 0x05: ptr = &i386_device::x87_fisubr_m32int; break; |
| 4501 | | case 0x06: ptr = &i386_device::x87_fidiv_m32int; break; |
| 4502 | | case 0x07: ptr = &i386_device::x87_fidivr_m32int; break; |
| 4503 | | } |
| 4504 | | } |
| 4505 | | else |
| 4506 | | { |
| 4507 | | switch (modrm) |
| 4508 | | { |
| 4509 | | case 0xe9: ptr = &i386_device::x87_fucompp; break; |
| 4510 | | } |
| 4511 | | } |
| 4512 | | |
| 4513 | | m_opcode_table_x87_da[modrm] = ptr; |
| 4514 | | } |
| 4515 | | } |
| 4516 | | |
| 4517 | | |
| 4518 | | void i386_device::build_x87_opcode_table_db() |
| 4519 | | { |
| 4520 | | int modrm = 0; |
| 4521 | | |
| 4522 | | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4523 | | { |
| 4524 | | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4525 | | |
| 4526 | | if (modrm < 0xc0) |
| 4527 | | { |
| 4528 | | switch ((modrm >> 3) & 0x7) |
| 4529 | | { |
| 4530 | | case 0x00: ptr = &i386_device::x87_fild_m32int; break; |
| 4531 | | case 0x02: ptr = &i386_device::x87_fist_m32int; break; |
| 4532 | | case 0x03: ptr = &i386_device::x87_fistp_m32int; break; |
| 4533 | | case 0x05: ptr = &i386_device::x87_fld_m80real; break; |
| 4534 | | case 0x07: ptr = &i386_device::x87_fstp_m80real; break; |
| 4535 | | } |
| 4536 | | } |
| 4537 | | else |
| 4538 | | { |
| 4539 | | switch (modrm) |
| 4540 | | { |
| 4541 | | case 0xe0: ptr = &i386_device::x87_fnop; break; /* FENI */ |
| 4542 | | case 0xe1: ptr = &i386_device::x87_fnop; break; /* FDISI */ |
| 4543 | | case 0xe2: ptr = &i386_device::x87_fclex; break; |
| 4544 | | case 0xe3: ptr = &i386_device::x87_finit; break; |
| 4545 | | case 0xe4: ptr = &i386_device::x87_fnop; break; /* FSETPM */ |
| 4546 | | } |
| 4547 | | } |
| 4548 | | |
| 4549 | | m_opcode_table_x87_db[modrm] = ptr; |
| 4550 | | } |
| 4551 | | } |
| 4552 | | |
| 4553 | | |
| 4554 | | void i386_device::build_x87_opcode_table_dc() |
| 4555 | | { |
| 4556 | | int modrm = 0; |
| 4557 | | |
| 4558 | | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4559 | | { |
| 4560 | | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4561 | | |
| 4562 | | if (modrm < 0xc0) |
| 4563 | | { |
| 4564 | | switch ((modrm >> 3) & 0x7) |
| 4565 | | { |
| 4566 | | case 0x00: ptr = &i386_device::x87_fadd_m64real; break; |
| 4567 | | case 0x01: ptr = &i386_device::x87_fmul_m64real; break; |
| 4568 | | case 0x02: ptr = &i386_device::x87_fcom_m64real; break; |
| 4569 | | case 0x03: ptr = &i386_device::x87_fcomp_m64real; break; |
| 4570 | | case 0x04: ptr = &i386_device::x87_fsub_m64real; break; |
| 4571 | | case 0x05: ptr = &i386_device::x87_fsubr_m64real; break; |
| 4572 | | case 0x06: ptr = &i386_device::x87_fdiv_m64real; break; |
| 4573 | | case 0x07: ptr = &i386_device::x87_fdivr_m64real; break; |
| 4574 | | } |
| 4575 | | } |
| 4576 | | else |
| 4577 | | { |
| 4578 | | switch (modrm) |
| 4579 | | { |
| 4580 | | case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &i386_device::x87_fadd_sti_st; break; |
| 4581 | | case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &i386_device::x87_fmul_sti_st; break; |
| 4582 | | case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = &i386_device::x87_fsubr_sti_st; break; |
| 4583 | | case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &i386_device::x87_fsub_sti_st; break; |
| 4584 | | case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = &i386_device::x87_fdivr_sti_st; break; |
| 4585 | | case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: ptr = &i386_device::x87_fdiv_sti_st; break; |
| 4586 | | } |
| 4587 | | } |
| 4588 | | |
| 4589 | | m_opcode_table_x87_dc[modrm] = ptr; |
| 4590 | | } |
| 4591 | | } |
| 4592 | | |
| 4593 | | |
| 4594 | | void i386_device::build_x87_opcode_table_dd() |
| 4595 | | { |
| 4596 | | int modrm = 0; |
| 4597 | | |
| 4598 | | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4599 | | { |
| 4600 | | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4601 | | |
| 4602 | | if (modrm < 0xc0) |
| 4603 | | { |
| 4604 | | switch ((modrm >> 3) & 0x7) |
| 4605 | | { |
| 4606 | | case 0x00: ptr = &i386_device::x87_fld_m64real; break; |
| 4607 | | case 0x02: ptr = &i386_device::x87_fst_m64real; break; |
| 4608 | | case 0x03: ptr = &i386_device::x87_fstp_m64real; break; |
| 4609 | | case 0x04: ptr = &i386_device::x87_frstor; break; |
| 4610 | | case 0x06: ptr = &i386_device::x87_fsave; break; |
| 4611 | | case 0x07: ptr = &i386_device::x87_fstsw_m2byte; break; |
| 4612 | | } |
| 4613 | | } |
| 4614 | | else |
| 4615 | | { |
| 4616 | | switch (modrm) |
| 4617 | | { |
| 4618 | | case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &i386_device::x87_ffree; break; |
| 4619 | | case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &i386_device::x87_fxch_sti; break; |
| 4620 | | case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: ptr = &i386_device::x87_fst_sti; break; |
| 4621 | | case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: ptr = &i386_device::x87_fstp_sti; break; |
| 4622 | | case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = &i386_device::x87_fucom_sti; break; |
| 4623 | | case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &i386_device::x87_fucomp_sti; break; |
| 4624 | | } |
| 4625 | | } |
| 4626 | | |
| 4627 | | m_opcode_table_x87_dd[modrm] = ptr; |
| 4628 | | } |
| 4629 | | } |
| 4630 | | |
| 4631 | | |
| 4632 | | void i386_device::build_x87_opcode_table_de() |
| 4633 | | { |
| 4634 | | int modrm = 0; |
| 4635 | | |
| 4636 | | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4637 | | { |
| 4638 | | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4639 | | |
| 4640 | | if (modrm < 0xc0) |
| 4641 | | { |
| 4642 | | switch ((modrm >> 3) & 0x7) |
| 4643 | | { |
| 4644 | | case 0x00: ptr = &i386_device::x87_fiadd_m16int; break; |
| 4645 | | case 0x01: ptr = &i386_device::x87_fimul_m16int; break; |
| 4646 | | case 0x02: ptr = &i386_device::x87_ficom_m16int; break; |
| 4647 | | case 0x03: ptr = &i386_device::x87_ficomp_m16int; break; |
| 4648 | | case 0x04: ptr = &i386_device::x87_fisub_m16int; break; |
| 4649 | | case 0x05: ptr = &i386_device::x87_fisubr_m16int; break; |
| 4650 | | case 0x06: ptr = &i386_device::x87_fidiv_m16int; break; |
| 4651 | | case 0x07: ptr = &i386_device::x87_fidivr_m16int; break; |
| 4652 | | } |
| 4653 | | } |
| 4654 | | else |
| 4655 | | { |
| 4656 | | switch (modrm) |
| 4657 | | { |
| 4658 | | case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &i386_device::x87_faddp; break; |
| 4659 | | case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &i386_device::x87_fmulp; break; |
| 4660 | | case 0xd9: ptr = &i386_device::x87_fcompp; break; |
| 4661 | | case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = &i386_device::x87_fsubrp; break; |
| 4662 | | case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &i386_device::x87_fsubp; break; |
| 4663 | | case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = &i386_device::x87_fdivrp; break; |
| 4664 | | case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: ptr = &i386_device::x87_fdivp; break; |
| 4665 | | } |
| 4666 | | } |
| 4667 | | |
| 4668 | | m_opcode_table_x87_de[modrm] = ptr; |
| 4669 | | } |
| 4670 | | } |
| 4671 | | |
| 4672 | | |
| 4673 | | void i386_device::build_x87_opcode_table_df() |
| 4674 | | { |
| 4675 | | int modrm = 0; |
| 4676 | | |
| 4677 | | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4678 | | { |
| 4679 | | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4680 | | |
| 4681 | | if (modrm < 0xc0) |
| 4682 | | { |
| 4683 | | switch ((modrm >> 3) & 0x7) |
| 4684 | | { |
| 4685 | | case 0x00: ptr = &i386_device::x87_fild_m16int; break; |
| 4686 | | case 0x02: ptr = &i386_device::x87_fist_m16int; break; |
| 4687 | | case 0x03: ptr = &i386_device::x87_fistp_m16int; break; |
| 4688 | | case 0x04: ptr = &i386_device::x87_fbld; break; |
| 4689 | | case 0x05: ptr = &i386_device::x87_fild_m64int; break; |
| 4690 | | case 0x06: ptr = &i386_device::x87_fbstp; break; |
| 4691 | | case 0x07: ptr = &i386_device::x87_fistp_m64int; break; |
| 4692 | | } |
| 4693 | | } |
| 4694 | | else |
| 4695 | | { |
| 4696 | | switch (modrm) |
| 4697 | | { |
| 4698 | | case 0xe0: ptr = &i386_device::x87_fstsw_ax; break; |
| 4699 | | case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = &i386_device::x87_fcomip_sti; break; |
| 4700 | | } |
| 4701 | | } |
| 4702 | | |
| 4703 | | m_opcode_table_x87_df[modrm] = ptr; |
| 4704 | | } |
| 4705 | | } |
| 4706 | | |
| 4707 | | void i386_device::build_x87_opcode_table() |
| 4708 | | { |
| 4709 | | build_x87_opcode_table_d8(); |
| 4710 | | build_x87_opcode_table_d9(); |
| 4711 | | build_x87_opcode_table_da(); |
| 4712 | | build_x87_opcode_table_db(); |
| 4713 | | build_x87_opcode_table_dc(); |
| 4714 | | build_x87_opcode_table_dd(); |
| 4715 | | build_x87_opcode_table_de(); |
| 4716 | | build_x87_opcode_table_df(); |
| 4717 | | } |
trunk/src/emu/cpu/i386/pentops.inc
| r0 | r28739 | |
| 1 | // Pentium+ specific opcodes |
| 2 | |
| 3 | extern flag float32_is_nan( float32 a ); // since its not defined in softfloat.h |
| 4 | |
| 5 | void i386_device::MMXPROLOG() |
| 6 | { |
| 7 | //m_x87_sw &= ~(X87_SW_TOP_MASK << X87_SW_TOP_SHIFT); // top = 0 |
| 8 | m_x87_tw = 0; // tag word = 0 |
| 9 | } |
| 10 | |
| 11 | void i386_device::READMMX(UINT32 ea,MMX_REG &r) |
| 12 | { |
| 13 | r.q=READ64(ea); |
| 14 | } |
| 15 | |
| 16 | void i386_device::WRITEMMX(UINT32 ea,MMX_REG &r) |
| 17 | { |
| 18 | WRITE64(ea, r.q); |
| 19 | } |
| 20 | |
| 21 | void i386_device::READXMM(UINT32 ea,XMM_REG &r) |
| 22 | { |
| 23 | r.q[0]=READ64(ea); |
| 24 | r.q[1]=READ64(ea+8); |
| 25 | } |
| 26 | |
| 27 | void i386_device::WRITEXMM(UINT32 ea,i386_device::XMM_REG &r) |
| 28 | { |
| 29 | WRITE64(ea, r.q[0]); |
| 30 | WRITE64(ea+8, r.q[1]); |
| 31 | } |
| 32 | |
| 33 | void i386_device::READXMM_LO64(UINT32 ea,i386_device::XMM_REG &r) |
| 34 | { |
| 35 | r.q[0]=READ64(ea); |
| 36 | } |
| 37 | |
| 38 | void i386_device::WRITEXMM_LO64(UINT32 ea,i386_device::XMM_REG &r) |
| 39 | { |
| 40 | WRITE64(ea, r.q[0]); |
| 41 | } |
| 42 | |
| 43 | void i386_device::READXMM_HI64(UINT32 ea,i386_device::XMM_REG &r) |
| 44 | { |
| 45 | r.q[1]=READ64(ea); |
| 46 | } |
| 47 | |
| 48 | void i386_device::WRITEXMM_HI64(UINT32 ea,i386_device::XMM_REG &r) |
| 49 | { |
| 50 | WRITE64(ea, r.q[1]); |
| 51 | } |
| 52 | |
| 53 | void i386_device::pentium_rdmsr() // Opcode 0x0f 32 |
| 54 | { |
| 55 | UINT64 data; |
| 56 | UINT8 valid_msr = 0; |
| 57 | |
| 58 | data = MSR_READ(REG32(ECX),&valid_msr); |
| 59 | REG32(EDX) = data >> 32; |
| 60 | REG32(EAX) = data & 0xffffffff; |
| 61 | |
| 62 | if(m_CPL != 0 || valid_msr == 0) // if current privilege level isn't 0 or the register isn't recognized ... |
| 63 | FAULT(FAULT_GP,0) // ... throw a general exception fault |
| 64 | |
| 65 | CYCLES(CYCLES_RDMSR); |
| 66 | } |
| 67 | |
| 68 | void i386_device::pentium_wrmsr() // Opcode 0x0f 30 |
| 69 | { |
| 70 | UINT64 data; |
| 71 | UINT8 valid_msr = 0; |
| 72 | |
| 73 | data = (UINT64)REG32(EAX); |
| 74 | data |= (UINT64)(REG32(EDX)) << 32; |
| 75 | |
| 76 | MSR_WRITE(REG32(ECX),data,&valid_msr); |
| 77 | |
| 78 | if(m_CPL != 0 || valid_msr == 0) // if current privilege level isn't 0 or the register isn't recognized |
| 79 | FAULT(FAULT_GP,0) // ... throw a general exception fault |
| 80 | |
| 81 | CYCLES(1); // TODO: correct cycle count (~30-45) |
| 82 | } |
| 83 | |
| 84 | void i386_device::pentium_rdtsc() // Opcode 0x0f 31 |
| 85 | { |
| 86 | UINT64 ts = m_tsc + (m_base_cycles - m_cycles); |
| 87 | REG32(EAX) = (UINT32)(ts); |
| 88 | REG32(EDX) = (UINT32)(ts >> 32); |
| 89 | |
| 90 | CYCLES(CYCLES_RDTSC); |
| 91 | } |
| 92 | |
| 93 | void i386_device::pentium_ud2() // Opcode 0x0f 0b |
| 94 | { |
| 95 | i386_trap(6, 0, 0); |
| 96 | } |
| 97 | |
| 98 | void i386_device::pentium_rsm() |
| 99 | { |
| 100 | UINT32 smram_state = m_smbase + 0xfe00; |
| 101 | if(!m_smm) |
| 102 | { |
| 103 | logerror("i386: Invalid RSM outside SMM at %08X\n", m_pc - 1); |
| 104 | i386_trap(6, 0, 0); |
| 105 | return; |
| 106 | } |
| 107 | |
| 108 | // load state, no sanity checks anywhere |
| 109 | m_smbase = READ32(smram_state+SMRAM_SMBASE); |
| 110 | m_cr[4] = READ32(smram_state+SMRAM_IP5_CR4); |
| 111 | m_sreg[ES].limit = READ32(smram_state+SMRAM_IP5_ESLIM); |
| 112 | m_sreg[ES].base = READ32(smram_state+SMRAM_IP5_ESBASE); |
| 113 | m_sreg[ES].flags = READ32(smram_state+SMRAM_IP5_ESACC); |
| 114 | m_sreg[CS].limit = READ32(smram_state+SMRAM_IP5_CSLIM); |
| 115 | m_sreg[CS].base = READ32(smram_state+SMRAM_IP5_CSBASE); |
| 116 | m_sreg[CS].flags = READ32(smram_state+SMRAM_IP5_CSACC); |
| 117 | m_sreg[SS].limit = READ32(smram_state+SMRAM_IP5_SSLIM); |
| 118 | m_sreg[SS].base = READ32(smram_state+SMRAM_IP5_SSBASE); |
| 119 | m_sreg[SS].flags = READ32(smram_state+SMRAM_IP5_SSACC); |
| 120 | m_sreg[DS].limit = READ32(smram_state+SMRAM_IP5_DSLIM); |
| 121 | m_sreg[DS].base = READ32(smram_state+SMRAM_IP5_DSBASE); |
| 122 | m_sreg[DS].flags = READ32(smram_state+SMRAM_IP5_DSACC); |
| 123 | m_sreg[FS].limit = READ32(smram_state+SMRAM_IP5_FSLIM); |
| 124 | m_sreg[FS].base = READ32(smram_state+SMRAM_IP5_FSBASE); |
| 125 | m_sreg[FS].flags = READ32(smram_state+SMRAM_IP5_FSACC); |
| 126 | m_sreg[GS].limit = READ32(smram_state+SMRAM_IP5_GSLIM); |
| 127 | m_sreg[GS].base = READ32(smram_state+SMRAM_IP5_GSBASE); |
| 128 | m_sreg[GS].flags = READ32(smram_state+SMRAM_IP5_GSACC); |
| 129 | m_ldtr.flags = READ32(smram_state+SMRAM_IP5_LDTACC); |
| 130 | m_ldtr.limit = READ32(smram_state+SMRAM_IP5_LDTLIM); |
| 131 | m_ldtr.base = READ32(smram_state+SMRAM_IP5_LDTBASE); |
| 132 | m_gdtr.limit = READ32(smram_state+SMRAM_IP5_GDTLIM); |
| 133 | m_gdtr.base = READ32(smram_state+SMRAM_IP5_GDTBASE); |
| 134 | m_idtr.limit = READ32(smram_state+SMRAM_IP5_IDTLIM); |
| 135 | m_idtr.base = READ32(smram_state+SMRAM_IP5_IDTBASE); |
| 136 | m_task.limit = READ32(smram_state+SMRAM_IP5_TRLIM); |
| 137 | m_task.base = READ32(smram_state+SMRAM_IP5_TRBASE); |
| 138 | m_task.flags = READ32(smram_state+SMRAM_IP5_TRACC); |
| 139 | |
| 140 | m_sreg[ES].selector = READ32(smram_state+SMRAM_ES); |
| 141 | m_sreg[CS].selector = READ32(smram_state+SMRAM_CS); |
| 142 | m_sreg[SS].selector = READ32(smram_state+SMRAM_SS); |
| 143 | m_sreg[DS].selector = READ32(smram_state+SMRAM_DS); |
| 144 | m_sreg[FS].selector = READ32(smram_state+SMRAM_FS); |
| 145 | m_sreg[GS].selector = READ32(smram_state+SMRAM_GS); |
| 146 | m_ldtr.segment = READ32(smram_state+SMRAM_LDTR); |
| 147 | m_task.segment = READ32(smram_state+SMRAM_TR); |
| 148 | |
| 149 | m_dr[7] = READ32(smram_state+SMRAM_DR7); |
| 150 | m_dr[6] = READ32(smram_state+SMRAM_DR6); |
| 151 | REG32(EAX) = READ32(smram_state+SMRAM_EAX); |
| 152 | REG32(ECX) = READ32(smram_state+SMRAM_ECX); |
| 153 | REG32(EDX) = READ32(smram_state+SMRAM_EDX); |
| 154 | REG32(EBX) = READ32(smram_state+SMRAM_EBX); |
| 155 | REG32(ESP) = READ32(smram_state+SMRAM_ESP); |
| 156 | REG32(EBP) = READ32(smram_state+SMRAM_EBP); |
| 157 | REG32(ESI) = READ32(smram_state+SMRAM_ESI); |
| 158 | REG32(EDI) = READ32(smram_state+SMRAM_EDI); |
| 159 | m_eip = READ32(smram_state+SMRAM_EIP); |
| 160 | m_eflags = READ32(smram_state+SMRAM_EAX); |
| 161 | m_cr[3] = READ32(smram_state+SMRAM_CR3); |
| 162 | m_cr[0] = READ32(smram_state+SMRAM_CR0); |
| 163 | |
| 164 | m_CPL = (m_sreg[SS].flags >> 13) & 3; // cpl == dpl of ss |
| 165 | |
| 166 | for(int i = 0; i < GS; i++) |
| 167 | { |
| 168 | if(PROTECTED_MODE && !V8086_MODE) |
| 169 | { |
| 170 | m_sreg[i].valid = m_sreg[i].selector ? true : false; |
| 171 | m_sreg[i].d = (m_sreg[i].flags & 0x4000) ? 1 : 0; |
| 172 | } |
| 173 | else |
| 174 | m_sreg[i].valid = true; |
| 175 | } |
| 176 | |
| 177 | if(!m_smiact.isnull()) |
| 178 | m_smiact(false); |
| 179 | m_smm = false; |
| 180 | |
| 181 | CHANGE_PC(m_eip); |
| 182 | m_nmi_masked = false; |
| 183 | if(m_smi_latched) |
| 184 | { |
| 185 | pentium_smi(); |
| 186 | return; |
| 187 | } |
| 188 | if(m_nmi_latched) |
| 189 | { |
| 190 | m_nmi_latched = false; |
| 191 | i386_trap(2, 1, 0); |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | void i386_device::pentium_prefetch_m8() // Opcode 0x0f 18 |
| 196 | { |
| 197 | UINT8 modrm = FETCH(); |
| 198 | UINT32 ea = GetEA(modrm,0); |
| 199 | CYCLES(1+(ea & 1)); // TODO: correct cycle count |
| 200 | } |
| 201 | |
| 202 | void i386_device::pentium_cmovo_r16_rm16() // Opcode 0x0f 40 |
| 203 | { |
| 204 | UINT16 src; |
| 205 | UINT8 modrm = FETCH(); |
| 206 | |
| 207 | if( modrm >= 0xc0 ) |
| 208 | { |
| 209 | if (m_OF == 1) |
| 210 | { |
| 211 | src = LOAD_RM16(modrm); |
| 212 | STORE_REG16(modrm, src); |
| 213 | } |
| 214 | CYCLES(1); // TODO: correct cycle count |
| 215 | } |
| 216 | else |
| 217 | { |
| 218 | UINT32 ea = GetEA(modrm,0); |
| 219 | if (m_OF == 1) |
| 220 | { |
| 221 | src = READ16(ea); |
| 222 | STORE_REG16(modrm, src); |
| 223 | } |
| 224 | CYCLES(1); // TODO: correct cycle count |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | void i386_device::pentium_cmovo_r32_rm32() // Opcode 0x0f 40 |
| 229 | { |
| 230 | UINT32 src; |
| 231 | UINT8 modrm = FETCH(); |
| 232 | |
| 233 | if( modrm >= 0xc0 ) |
| 234 | { |
| 235 | if (m_OF == 1) |
| 236 | { |
| 237 | src = LOAD_RM32(modrm); |
| 238 | STORE_REG32(modrm, src); |
| 239 | } |
| 240 | CYCLES(1); // TODO: correct cycle count |
| 241 | } |
| 242 | else |
| 243 | { |
| 244 | UINT32 ea = GetEA(modrm,0); |
| 245 | if (m_OF == 1) |
| 246 | { |
| 247 | src = READ32(ea); |
| 248 | STORE_REG32(modrm, src); |
| 249 | } |
| 250 | CYCLES(1); // TODO: correct cycle count |
| 251 | } |
| 252 | } |
| 253 | |
| 254 | void i386_device::pentium_cmovno_r16_rm16() // Opcode 0x0f 41 |
| 255 | { |
| 256 | UINT16 src; |
| 257 | UINT8 modrm = FETCH(); |
| 258 | |
| 259 | if( modrm >= 0xc0 ) |
| 260 | { |
| 261 | if (m_OF == 0) |
| 262 | { |
| 263 | src = LOAD_RM16(modrm); |
| 264 | STORE_REG16(modrm, src); |
| 265 | } |
| 266 | CYCLES(1); // TODO: correct cycle count |
| 267 | } |
| 268 | else |
| 269 | { |
| 270 | UINT32 ea = GetEA(modrm,0); |
| 271 | if (m_OF == 0) |
| 272 | { |
| 273 | src = READ16(ea); |
| 274 | STORE_REG16(modrm, src); |
| 275 | } |
| 276 | CYCLES(1); // TODO: correct cycle count |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | void i386_device::pentium_cmovno_r32_rm32() // Opcode 0x0f 41 |
| 281 | { |
| 282 | UINT32 src; |
| 283 | UINT8 modrm = FETCH(); |
| 284 | |
| 285 | if( modrm >= 0xc0 ) |
| 286 | { |
| 287 | if (m_OF == 0) |
| 288 | { |
| 289 | src = LOAD_RM32(modrm); |
| 290 | STORE_REG32(modrm, src); |
| 291 | } |
| 292 | CYCLES(1); // TODO: correct cycle count |
| 293 | } |
| 294 | else |
| 295 | { |
| 296 | UINT32 ea = GetEA(modrm,0); |
| 297 | if (m_OF == 0) |
| 298 | { |
| 299 | src = READ32(ea); |
| 300 | STORE_REG32(modrm, src); |
| 301 | } |
| 302 | CYCLES(1); // TODO: correct cycle count |
| 303 | } |
| 304 | } |
| 305 | |
| 306 | void i386_device::pentium_cmovb_r16_rm16() // Opcode 0x0f 42 |
| 307 | { |
| 308 | UINT16 src; |
| 309 | UINT8 modrm = FETCH(); |
| 310 | |
| 311 | if( modrm >= 0xc0 ) |
| 312 | { |
| 313 | if (m_CF == 1) |
| 314 | { |
| 315 | src = LOAD_RM16(modrm); |
| 316 | STORE_REG16(modrm, src); |
| 317 | } |
| 318 | CYCLES(1); // TODO: correct cycle count |
| 319 | } |
| 320 | else |
| 321 | { |
| 322 | UINT32 ea = GetEA(modrm,0); |
| 323 | if (m_CF == 1) |
| 324 | { |
| 325 | src = READ16(ea); |
| 326 | STORE_REG16(modrm, src); |
| 327 | } |
| 328 | CYCLES(1); // TODO: correct cycle count |
| 329 | } |
| 330 | } |
| 331 | |
| 332 | void i386_device::pentium_cmovb_r32_rm32() // Opcode 0x0f 42 |
| 333 | { |
| 334 | UINT32 src; |
| 335 | UINT8 modrm = FETCH(); |
| 336 | |
| 337 | if( modrm >= 0xc0 ) |
| 338 | { |
| 339 | if (m_CF == 1) |
| 340 | { |
| 341 | src = LOAD_RM32(modrm); |
| 342 | STORE_REG32(modrm, src); |
| 343 | } |
| 344 | CYCLES(1); // TODO: correct cycle count |
| 345 | } |
| 346 | else |
| 347 | { |
| 348 | UINT32 ea = GetEA(modrm,0); |
| 349 | if (m_CF == 1) |
| 350 | { |
| 351 | src = READ32(ea); |
| 352 | STORE_REG32(modrm, src); |
| 353 | } |
| 354 | CYCLES(1); // TODO: correct cycle count |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | void i386_device::pentium_cmovae_r16_rm16() // Opcode 0x0f 43 |
| 359 | { |
| 360 | UINT16 src; |
| 361 | UINT8 modrm = FETCH(); |
| 362 | |
| 363 | if( modrm >= 0xc0 ) |
| 364 | { |
| 365 | if (m_CF == 0) |
| 366 | { |
| 367 | src = LOAD_RM16(modrm); |
| 368 | STORE_REG16(modrm, src); |
| 369 | } |
| 370 | CYCLES(1); // TODO: correct cycle count |
| 371 | } |
| 372 | else |
| 373 | { |
| 374 | UINT32 ea = GetEA(modrm,0); |
| 375 | if (m_CF == 0) |
| 376 | { |
| 377 | src = READ16(ea); |
| 378 | STORE_REG16(modrm, src); |
| 379 | } |
| 380 | CYCLES(1); // TODO: correct cycle count |
| 381 | } |
| 382 | } |
| 383 | |
| 384 | void i386_device::pentium_cmovae_r32_rm32() // Opcode 0x0f 43 |
| 385 | { |
| 386 | UINT32 src; |
| 387 | UINT8 modrm = FETCH(); |
| 388 | |
| 389 | if( modrm >= 0xc0 ) |
| 390 | { |
| 391 | if (m_CF == 0) |
| 392 | { |
| 393 | src = LOAD_RM32(modrm); |
| 394 | STORE_REG32(modrm, src); |
| 395 | } |
| 396 | CYCLES(1); // TODO: correct cycle count |
| 397 | } |
| 398 | else |
| 399 | { |
| 400 | UINT32 ea = GetEA(modrm,0); |
| 401 | if (m_CF == 0) |
| 402 | { |
| 403 | src = READ32(ea); |
| 404 | STORE_REG32(modrm, src); |
| 405 | } |
| 406 | CYCLES(1); // TODO: correct cycle count |
| 407 | } |
| 408 | } |
| 409 | |
| 410 | void i386_device::pentium_cmove_r16_rm16() // Opcode 0x0f 44 |
| 411 | { |
| 412 | UINT16 src; |
| 413 | UINT8 modrm = FETCH(); |
| 414 | |
| 415 | if( modrm >= 0xc0 ) |
| 416 | { |
| 417 | if (m_ZF == 1) |
| 418 | { |
| 419 | src = LOAD_RM16(modrm); |
| 420 | STORE_REG16(modrm, src); |
| 421 | } |
| 422 | CYCLES(1); // TODO: correct cycle count |
| 423 | } |
| 424 | else |
| 425 | { |
| 426 | UINT32 ea = GetEA(modrm,0); |
| 427 | if (m_ZF == 1) |
| 428 | { |
| 429 | src = READ16(ea); |
| 430 | STORE_REG16(modrm, src); |
| 431 | } |
| 432 | CYCLES(1); // TODO: correct cycle count |
| 433 | } |
| 434 | } |
| 435 | |
| 436 | void i386_device::pentium_cmove_r32_rm32() // Opcode 0x0f 44 |
| 437 | { |
| 438 | UINT32 src; |
| 439 | UINT8 modrm = FETCH(); |
| 440 | |
| 441 | if( modrm >= 0xc0 ) |
| 442 | { |
| 443 | if (m_ZF == 1) |
| 444 | { |
| 445 | src = LOAD_RM32(modrm); |
| 446 | STORE_REG32(modrm, src); |
| 447 | } |
| 448 | CYCLES(1); // TODO: correct cycle count |
| 449 | } |
| 450 | else |
| 451 | { |
| 452 | UINT32 ea = GetEA(modrm,0); |
| 453 | if (m_ZF == 1) |
| 454 | { |
| 455 | src = READ32(ea); |
| 456 | STORE_REG32(modrm, src); |
| 457 | } |
| 458 | CYCLES(1); // TODO: correct cycle count |
| 459 | } |
| 460 | } |
| 461 | |
| 462 | void i386_device::pentium_cmovne_r16_rm16() // Opcode 0x0f 45 |
| 463 | { |
| 464 | UINT16 src; |
| 465 | UINT8 modrm = FETCH(); |
| 466 | |
| 467 | if( modrm >= 0xc0 ) |
| 468 | { |
| 469 | if (m_ZF == 0) |
| 470 | { |
| 471 | src = LOAD_RM16(modrm); |
| 472 | STORE_REG16(modrm, src); |
| 473 | } |
| 474 | CYCLES(1); // TODO: correct cycle count |
| 475 | } |
| 476 | else |
| 477 | { |
| 478 | UINT32 ea = GetEA(modrm,0); |
| 479 | if (m_ZF == 0) |
| 480 | { |
| 481 | src = READ16(ea); |
| 482 | STORE_REG16(modrm, src); |
| 483 | } |
| 484 | CYCLES(1); // TODO: correct cycle count |
| 485 | } |
| 486 | } |
| 487 | |
| 488 | void i386_device::pentium_cmovne_r32_rm32() // Opcode 0x0f 45 |
| 489 | { |
| 490 | UINT32 src; |
| 491 | UINT8 modrm = FETCH(); |
| 492 | |
| 493 | if( modrm >= 0xc0 ) |
| 494 | { |
| 495 | if (m_ZF == 0) |
| 496 | { |
| 497 | src = LOAD_RM32(modrm); |
| 498 | STORE_REG32(modrm, src); |
| 499 | } |
| 500 | CYCLES(1); // TODO: correct cycle count |
| 501 | } |
| 502 | else |
| 503 | { |
| 504 | UINT32 ea = GetEA(modrm,0); |
| 505 | if (m_ZF == 0) |
| 506 | { |
| 507 | src = READ32(ea); |
| 508 | STORE_REG32(modrm, src); |
| 509 | } |
| 510 | CYCLES(1); // TODO: correct cycle count |
| 511 | } |
| 512 | } |
| 513 | |
| 514 | void i386_device::pentium_cmovbe_r16_rm16() // Opcode 0x0f 46 |
| 515 | { |
| 516 | UINT16 src; |
| 517 | UINT8 modrm = FETCH(); |
| 518 | |
| 519 | if( modrm >= 0xc0 ) |
| 520 | { |
| 521 | if ((m_CF == 1) || (m_ZF == 1)) |
| 522 | { |
| 523 | src = LOAD_RM16(modrm); |
| 524 | STORE_REG16(modrm, src); |
| 525 | } |
| 526 | CYCLES(1); // TODO: correct cycle count |
| 527 | } |
| 528 | else |
| 529 | { |
| 530 | UINT32 ea = GetEA(modrm,0); |
| 531 | if ((m_CF == 1) || (m_ZF == 1)) |
| 532 | { |
| 533 | src = READ16(ea); |
| 534 | STORE_REG16(modrm, src); |
| 535 | } |
| 536 | CYCLES(1); // TODO: correct cycle count |
| 537 | } |
| 538 | } |
| 539 | |
| 540 | void i386_device::pentium_cmovbe_r32_rm32() // Opcode 0x0f 46 |
| 541 | { |
| 542 | UINT32 src; |
| 543 | UINT8 modrm = FETCH(); |
| 544 | |
| 545 | if( modrm >= 0xc0 ) |
| 546 | { |
| 547 | if ((m_CF == 1) || (m_ZF == 1)) |
| 548 | { |
| 549 | src = LOAD_RM32(modrm); |
| 550 | STORE_REG32(modrm, src); |
| 551 | } |
| 552 | CYCLES(1); // TODO: correct cycle count |
| 553 | } |
| 554 | else |
| 555 | { |
| 556 | UINT32 ea = GetEA(modrm,0); |
| 557 | if ((m_CF == 1) || (m_ZF == 1)) |
| 558 | { |
| 559 | src = READ32(ea); |
| 560 | STORE_REG32(modrm, src); |
| 561 | } |
| 562 | CYCLES(1); // TODO: correct cycle count |
| 563 | } |
| 564 | } |
| 565 | |
| 566 | void i386_device::pentium_cmova_r16_rm16() // Opcode 0x0f 47 |
| 567 | { |
| 568 | UINT16 src; |
| 569 | UINT8 modrm = FETCH(); |
| 570 | |
| 571 | if( modrm >= 0xc0 ) |
| 572 | { |
| 573 | if ((m_CF == 0) && (m_ZF == 0)) |
| 574 | { |
| 575 | src = LOAD_RM16(modrm); |
| 576 | STORE_REG16(modrm, src); |
| 577 | } |
| 578 | CYCLES(1); // TODO: correct cycle count |
| 579 | } |
| 580 | else |
| 581 | { |
| 582 | UINT32 ea = GetEA(modrm,0); |
| 583 | if ((m_CF == 0) && (m_ZF == 0)) |
| 584 | { |
| 585 | src = READ16(ea); |
| 586 | STORE_REG16(modrm, src); |
| 587 | } |
| 588 | CYCLES(1); // TODO: correct cycle count |
| 589 | } |
| 590 | } |
| 591 | |
| 592 | void i386_device::pentium_cmova_r32_rm32() // Opcode 0x0f 47 |
| 593 | { |
| 594 | UINT32 src; |
| 595 | UINT8 modrm = FETCH(); |
| 596 | |
| 597 | if( modrm >= 0xc0 ) |
| 598 | { |
| 599 | if ((m_CF == 0) && (m_ZF == 0)) |
| 600 | { |
| 601 | src = LOAD_RM32(modrm); |
| 602 | STORE_REG32(modrm, src); |
| 603 | } |
| 604 | CYCLES(1); // TODO: correct cycle count |
| 605 | } |
| 606 | else |
| 607 | { |
| 608 | UINT32 ea = GetEA(modrm,0); |
| 609 | if ((m_CF == 0) && (m_ZF == 0)) |
| 610 | { |
| 611 | src = READ32(ea); |
| 612 | STORE_REG32(modrm, src); |
| 613 | } |
| 614 | CYCLES(1); // TODO: correct cycle count |
| 615 | } |
| 616 | } |
| 617 | |
| 618 | void i386_device::pentium_cmovs_r16_rm16() // Opcode 0x0f 48 |
| 619 | { |
| 620 | UINT16 src; |
| 621 | UINT8 modrm = FETCH(); |
| 622 | |
| 623 | if( modrm >= 0xc0 ) |
| 624 | { |
| 625 | if (m_SF == 1) |
| 626 | { |
| 627 | src = LOAD_RM16(modrm); |
| 628 | STORE_REG16(modrm, src); |
| 629 | } |
| 630 | CYCLES(1); // TODO: correct cycle count |
| 631 | } |
| 632 | else |
| 633 | { |
| 634 | UINT32 ea = GetEA(modrm,0); |
| 635 | if (m_SF == 1) |
| 636 | { |
| 637 | src = READ16(ea); |
| 638 | STORE_REG16(modrm, src); |
| 639 | } |
| 640 | CYCLES(1); // TODO: correct cycle count |
| 641 | } |
| 642 | } |
| 643 | |
| 644 | void i386_device::pentium_cmovs_r32_rm32() // Opcode 0x0f 48 |
| 645 | { |
| 646 | UINT32 src; |
| 647 | UINT8 modrm = FETCH(); |
| 648 | |
| 649 | if( modrm >= 0xc0 ) |
| 650 | { |
| 651 | if (m_SF == 1) |
| 652 | { |
| 653 | src = LOAD_RM32(modrm); |
| 654 | STORE_REG32(modrm, src); |
| 655 | } |
| 656 | CYCLES(1); // TODO: correct cycle count |
| 657 | } |
| 658 | else |
| 659 | { |
| 660 | UINT32 ea = GetEA(modrm,0); |
| 661 | if (m_SF == 1) |
| 662 | { |
| 663 | src = READ32(ea); |
| 664 | STORE_REG32(modrm, src); |
| 665 | } |
| 666 | CYCLES(1); // TODO: correct cycle count |
| 667 | } |
| 668 | } |
| 669 | |
| 670 | void i386_device::pentium_cmovns_r16_rm16() // Opcode 0x0f 49 |
| 671 | { |
| 672 | UINT16 src; |
| 673 | UINT8 modrm = FETCH(); |
| 674 | |
| 675 | if( modrm >= 0xc0 ) |
| 676 | { |
| 677 | if (m_SF == 0) |
| 678 | { |
| 679 | src = LOAD_RM16(modrm); |
| 680 | STORE_REG16(modrm, src); |
| 681 | } |
| 682 | CYCLES(1); // TODO: correct cycle count |
| 683 | } |
| 684 | else |
| 685 | { |
| 686 | UINT32 ea = GetEA(modrm,0); |
| 687 | if (m_SF == 0) |
| 688 | { |
| 689 | src = READ16(ea); |
| 690 | STORE_REG16(modrm, src); |
| 691 | } |
| 692 | CYCLES(1); // TODO: correct cycle count |
| 693 | } |
| 694 | } |
| 695 | |
| 696 | void i386_device::pentium_cmovns_r32_rm32() // Opcode 0x0f 49 |
| 697 | { |
| 698 | UINT32 src; |
| 699 | UINT8 modrm = FETCH(); |
| 700 | |
| 701 | if( modrm >= 0xc0 ) |
| 702 | { |
| 703 | if (m_SF == 0) |
| 704 | { |
| 705 | src = LOAD_RM32(modrm); |
| 706 | STORE_REG32(modrm, src); |
| 707 | } |
| 708 | CYCLES(1); // TODO: correct cycle count |
| 709 | } |
| 710 | else |
| 711 | { |
| 712 | UINT32 ea = GetEA(modrm,0); |
| 713 | if (m_SF == 0) |
| 714 | { |
| 715 | src = READ32(ea); |
| 716 | STORE_REG32(modrm, src); |
| 717 | } |
| 718 | CYCLES(1); // TODO: correct cycle count |
| 719 | } |
| 720 | } |
| 721 | |
| 722 | void i386_device::pentium_cmovp_r16_rm16() // Opcode 0x0f 4a |
| 723 | { |
| 724 | UINT16 src; |
| 725 | UINT8 modrm = FETCH(); |
| 726 | |
| 727 | if( modrm >= 0xc0 ) |
| 728 | { |
| 729 | if (m_PF == 1) |
| 730 | { |
| 731 | src = LOAD_RM16(modrm); |
| 732 | STORE_REG16(modrm, src); |
| 733 | } |
| 734 | CYCLES(1); // TODO: correct cycle count |
| 735 | } |
| 736 | else |
| 737 | { |
| 738 | UINT32 ea = GetEA(modrm,0); |
| 739 | if (m_PF == 1) |
| 740 | { |
| 741 | src = READ16(ea); |
| 742 | STORE_REG16(modrm, src); |
| 743 | } |
| 744 | CYCLES(1); // TODO: correct cycle count |
| 745 | } |
| 746 | } |
| 747 | |
| 748 | void i386_device::pentium_cmovp_r32_rm32() // Opcode 0x0f 4a |
| 749 | { |
| 750 | UINT32 src; |
| 751 | UINT8 modrm = FETCH(); |
| 752 | |
| 753 | if( modrm >= 0xc0 ) |
| 754 | { |
| 755 | if (m_PF == 1) |
| 756 | { |
| 757 | src = LOAD_RM32(modrm); |
| 758 | STORE_REG32(modrm, src); |
| 759 | } |
| 760 | CYCLES(1); // TODO: correct cycle count |
| 761 | } |
| 762 | else |
| 763 | { |
| 764 | UINT32 ea = GetEA(modrm,0); |
| 765 | if (m_PF == 1) |
| 766 | { |
| 767 | src = READ32(ea); |
| 768 | STORE_REG32(modrm, src); |
| 769 | } |
| 770 | CYCLES(1); // TODO: correct cycle count |
| 771 | } |
| 772 | } |
| 773 | |
| 774 | void i386_device::pentium_cmovnp_r16_rm16() // Opcode 0x0f 4b |
| 775 | { |
| 776 | UINT16 src; |
| 777 | UINT8 modrm = FETCH(); |
| 778 | |
| 779 | if( modrm >= 0xc0 ) |
| 780 | { |
| 781 | if (m_PF == 0) |
| 782 | { |
| 783 | src = LOAD_RM16(modrm); |
| 784 | STORE_REG16(modrm, src); |
| 785 | } |
| 786 | CYCLES(1); // TODO: correct cycle count |
| 787 | } |
| 788 | else |
| 789 | { |
| 790 | UINT32 ea = GetEA(modrm,0); |
| 791 | if (m_PF == 0) |
| 792 | { |
| 793 | src = READ16(ea); |
| 794 | STORE_REG16(modrm, src); |
| 795 | } |
| 796 | CYCLES(1); // TODO: correct cycle count |
| 797 | } |
| 798 | } |
| 799 | |
| 800 | void i386_device::pentium_cmovnp_r32_rm32() // Opcode 0x0f 4b |
| 801 | { |
| 802 | UINT32 src; |
| 803 | UINT8 modrm = FETCH(); |
| 804 | |
| 805 | if( modrm >= 0xc0 ) |
| 806 | { |
| 807 | if (m_PF == 0) |
| 808 | { |
| 809 | src = LOAD_RM32(modrm); |
| 810 | STORE_REG32(modrm, src); |
| 811 | } |
| 812 | CYCLES(1); // TODO: correct cycle count |
| 813 | } |
| 814 | else |
| 815 | { |
| 816 | UINT32 ea = GetEA(modrm,0); |
| 817 | if (m_PF == 0) |
| 818 | { |
| 819 | src = READ32(ea); |
| 820 | STORE_REG32(modrm, src); |
| 821 | } |
| 822 | CYCLES(1); // TODO: correct cycle count |
| 823 | } |
| 824 | } |
| 825 | |
| 826 | void i386_device::pentium_cmovl_r16_rm16() // Opcode 0x0f 4c |
| 827 | { |
| 828 | UINT16 src; |
| 829 | UINT8 modrm = FETCH(); |
| 830 | |
| 831 | if( modrm >= 0xc0 ) |
| 832 | { |
| 833 | if (m_SF != m_OF) |
| 834 | { |
| 835 | src = LOAD_RM16(modrm); |
| 836 | STORE_REG16(modrm, src); |
| 837 | } |
| 838 | CYCLES(1); // TODO: correct cycle count |
| 839 | } |
| 840 | else |
| 841 | { |
| 842 | UINT32 ea = GetEA(modrm,0); |
| 843 | if (m_SF != m_OF) |
| 844 | { |
| 845 | src = READ16(ea); |
| 846 | STORE_REG16(modrm, src); |
| 847 | } |
| 848 | CYCLES(1); // TODO: correct cycle count |
| 849 | } |
| 850 | } |
| 851 | |
| 852 | void i386_device::pentium_cmovl_r32_rm32() // Opcode 0x0f 4c |
| 853 | { |
| 854 | UINT32 src; |
| 855 | UINT8 modrm = FETCH(); |
| 856 | |
| 857 | if( modrm >= 0xc0 ) |
| 858 | { |
| 859 | if (m_SF != m_OF) |
| 860 | { |
| 861 | src = LOAD_RM32(modrm); |
| 862 | STORE_REG32(modrm, src); |
| 863 | } |
| 864 | CYCLES(1); // TODO: correct cycle count |
| 865 | } |
| 866 | else |
| 867 | { |
| 868 | UINT32 ea = GetEA(modrm,0); |
| 869 | if (m_SF != m_OF) |
| 870 | { |
| 871 | src = READ32(ea); |
| 872 | STORE_REG32(modrm, src); |
| 873 | } |
| 874 | CYCLES(1); // TODO: correct cycle count |
| 875 | } |
| 876 | } |
| 877 | |
| 878 | void i386_device::pentium_cmovge_r16_rm16() // Opcode 0x0f 4d |
| 879 | { |
| 880 | UINT16 src; |
| 881 | UINT8 modrm = FETCH(); |
| 882 | |
| 883 | if( modrm >= 0xc0 ) |
| 884 | { |
| 885 | if (m_SF == m_OF) |
| 886 | { |
| 887 | src = LOAD_RM16(modrm); |
| 888 | STORE_REG16(modrm, src); |
| 889 | } |
| 890 | CYCLES(1); // TODO: correct cycle count |
| 891 | } |
| 892 | else |
| 893 | { |
| 894 | UINT32 ea = GetEA(modrm,0); |
| 895 | if (m_SF == m_OF) |
| 896 | { |
| 897 | src = READ16(ea); |
| 898 | STORE_REG16(modrm, src); |
| 899 | } |
| 900 | CYCLES(1); // TODO: correct cycle count |
| 901 | } |
| 902 | } |
| 903 | |
| 904 | void i386_device::pentium_cmovge_r32_rm32() // Opcode 0x0f 4d |
| 905 | { |
| 906 | UINT32 src; |
| 907 | UINT8 modrm = FETCH(); |
| 908 | |
| 909 | if( modrm >= 0xc0 ) |
| 910 | { |
| 911 | if (m_SF == m_OF) |
| 912 | { |
| 913 | src = LOAD_RM32(modrm); |
| 914 | STORE_REG32(modrm, src); |
| 915 | } |
| 916 | CYCLES(1); // TODO: correct cycle count |
| 917 | } |
| 918 | else |
| 919 | { |
| 920 | UINT32 ea = GetEA(modrm,0); |
| 921 | if (m_SF == m_OF) |
| 922 | { |
| 923 | src = READ32(ea); |
| 924 | STORE_REG32(modrm, src); |
| 925 | } |
| 926 | CYCLES(1); // TODO: correct cycle count |
| 927 | } |
| 928 | } |
| 929 | |
| 930 | void i386_device::pentium_cmovle_r16_rm16() // Opcode 0x0f 4e |
| 931 | { |
| 932 | UINT16 src; |
| 933 | UINT8 modrm = FETCH(); |
| 934 | |
| 935 | if( modrm >= 0xc0 ) |
| 936 | { |
| 937 | if ((m_ZF == 1) || (m_SF != m_OF)) |
| 938 | { |
| 939 | src = LOAD_RM16(modrm); |
| 940 | STORE_REG16(modrm, src); |
| 941 | } |
| 942 | CYCLES(1); // TODO: correct cycle count |
| 943 | } |
| 944 | else |
| 945 | { |
| 946 | UINT32 ea = GetEA(modrm,0); |
| 947 | if ((m_ZF == 1) || (m_SF != m_OF)) |
| 948 | { |
| 949 | src = READ16(ea); |
| 950 | STORE_REG16(modrm, src); |
| 951 | } |
| 952 | CYCLES(1); // TODO: correct cycle count |
| 953 | } |
| 954 | } |
| 955 | |
| 956 | void i386_device::pentium_cmovle_r32_rm32() // Opcode 0x0f 4e |
| 957 | { |
| 958 | UINT32 src; |
| 959 | UINT8 modrm = FETCH(); |
| 960 | |
| 961 | if( modrm >= 0xc0 ) |
| 962 | { |
| 963 | if ((m_ZF == 1) || (m_SF != m_OF)) |
| 964 | { |
| 965 | src = LOAD_RM32(modrm); |
| 966 | STORE_REG32(modrm, src); |
| 967 | } |
| 968 | CYCLES(1); // TODO: correct cycle count |
| 969 | } |
| 970 | else |
| 971 | { |
| 972 | UINT32 ea = GetEA(modrm,0); |
| 973 | if ((m_ZF == 1) || (m_SF != m_OF)) |
| 974 | { |
| 975 | src = READ32(ea); |
| 976 | STORE_REG32(modrm, src); |
| 977 | } |
| 978 | CYCLES(1); // TODO: correct cycle count |
| 979 | } |
| 980 | } |
| 981 | |
| 982 | void i386_device::pentium_cmovg_r16_rm16() // Opcode 0x0f 4f |
| 983 | { |
| 984 | UINT16 src; |
| 985 | UINT8 modrm = FETCH(); |
| 986 | |
| 987 | if( modrm >= 0xc0 ) |
| 988 | { |
| 989 | if ((m_ZF == 0) && (m_SF == m_OF)) |
| 990 | { |
| 991 | src = LOAD_RM16(modrm); |
| 992 | STORE_REG16(modrm, src); |
| 993 | } |
| 994 | CYCLES(1); // TODO: correct cycle count |
| 995 | } |
| 996 | else |
| 997 | { |
| 998 | UINT32 ea = GetEA(modrm,0); |
| 999 | if ((m_ZF == 0) && (m_SF == m_OF)) |
| 1000 | { |
| 1001 | src = READ16(ea); |
| 1002 | STORE_REG16(modrm, src); |
| 1003 | } |
| 1004 | CYCLES(1); // TODO: correct cycle count |
| 1005 | } |
| 1006 | } |
| 1007 | |
| 1008 | void i386_device::pentium_cmovg_r32_rm32() // Opcode 0x0f 4f |
| 1009 | { |
| 1010 | UINT32 src; |
| 1011 | UINT8 modrm = FETCH(); |
| 1012 | |
| 1013 | if( modrm >= 0xc0 ) |
| 1014 | { |
| 1015 | if ((m_ZF == 0) && (m_SF == m_OF)) |
| 1016 | { |
| 1017 | src = LOAD_RM32(modrm); |
| 1018 | STORE_REG32(modrm, src); |
| 1019 | } |
| 1020 | CYCLES(1); // TODO: correct cycle count |
| 1021 | } |
| 1022 | else |
| 1023 | { |
| 1024 | UINT32 ea = GetEA(modrm,0); |
| 1025 | if ((m_ZF == 0) && (m_SF == m_OF)) |
| 1026 | { |
| 1027 | src = READ32(ea); |
| 1028 | STORE_REG32(modrm, src); |
| 1029 | } |
| 1030 | CYCLES(1); // TODO: correct cycle count |
| 1031 | } |
| 1032 | } |
| 1033 | |
| 1034 | void i386_device::pentium_movnti_m16_r16() // Opcode 0f c3 |
| 1035 | { |
| 1036 | UINT8 modrm = FETCH(); |
| 1037 | if( modrm >= 0xc0 ) { |
| 1038 | // unsupported by cpu |
| 1039 | CYCLES(1); // TODO: correct cycle count |
| 1040 | } else { |
| 1041 | // since cache is not implemented |
| 1042 | UINT32 ea = GetEA(modrm, 0); |
| 1043 | WRITE16(ea,LOAD_RM16(modrm)); |
| 1044 | CYCLES(1); // TODO: correct cycle count |
| 1045 | } |
| 1046 | } |
| 1047 | |
| 1048 | void i386_device::pentium_movnti_m32_r32() // Opcode 0f c3 |
| 1049 | { |
| 1050 | UINT8 modrm = FETCH(); |
| 1051 | if( modrm >= 0xc0 ) { |
| 1052 | // unsupported by cpu |
| 1053 | CYCLES(1); // TODO: correct cycle count |
| 1054 | } else { |
| 1055 | // since cache is not implemented |
| 1056 | UINT32 ea = GetEA(modrm, 0); |
| 1057 | WRITE32(ea,LOAD_RM32(modrm)); |
| 1058 | CYCLES(1); // TODO: correct cycle count |
| 1059 | } |
| 1060 | } |
| 1061 | |
| 1062 | void i386_device::i386_cyrix_unknown() // Opcode 0x0f 74 |
| 1063 | { |
| 1064 | logerror("Unemulated 0x0f 0x74 opcode called\n"); |
| 1065 | |
| 1066 | CYCLES(1); |
| 1067 | } |
| 1068 | |
| 1069 | void i386_device::pentium_cmpxchg8b_m64() // Opcode 0x0f c7 |
| 1070 | { |
| 1071 | UINT8 modm = FETCH(); |
| 1072 | if( modm >= 0xc0 ) { |
| 1073 | report_invalid_modrm("cmpxchg8b_m64", modm); |
| 1074 | } else { |
| 1075 | UINT32 ea = GetEA(modm, 0); |
| 1076 | UINT64 value = READ64(ea); |
| 1077 | UINT64 edx_eax = (((UINT64) REG32(EDX)) << 32) | REG32(EAX); |
| 1078 | UINT64 ecx_ebx = (((UINT64) REG32(ECX)) << 32) | REG32(EBX); |
| 1079 | |
| 1080 | if( value == edx_eax ) { |
| 1081 | WRITE64(ea, ecx_ebx); |
| 1082 | m_ZF = 1; |
| 1083 | CYCLES(CYCLES_CMPXCHG_REG_MEM_T); |
| 1084 | } else { |
| 1085 | REG32(EDX) = (UINT32) (value >> 32); |
| 1086 | REG32(EAX) = (UINT32) (value >> 0); |
| 1087 | m_ZF = 0; |
| 1088 | CYCLES(CYCLES_CMPXCHG_REG_MEM_F); |
| 1089 | } |
| 1090 | } |
| 1091 | } |
| 1092 | |
| 1093 | void i386_device::pentium_movntq_m64_r64() // Opcode 0f e7 |
| 1094 | { |
| 1095 | //MMXPROLOG(); // TODO: check if needed |
| 1096 | UINT8 modrm = FETCH(); |
| 1097 | if( modrm >= 0xc0 ) { |
| 1098 | CYCLES(1); // unsupported |
| 1099 | } else { |
| 1100 | // since cache is not implemented |
| 1101 | UINT32 ea = GetEA(modrm, 0); |
| 1102 | WRITEMMX(ea, MMX((modrm >> 3) & 0x7)); |
| 1103 | CYCLES(1); // TODO: correct cycle count |
| 1104 | } |
| 1105 | } |
| 1106 | |
| 1107 | void i386_device::pentium_maskmovq_r64_r64() // Opcode 0f f7 |
| 1108 | { |
| 1109 | int s,m,n; |
| 1110 | UINT8 modm = FETCH(); |
| 1111 | UINT32 ea = GetEA(7, 0); // ds:di/edi/rdi register |
| 1112 | MMXPROLOG(); |
| 1113 | s=(modm >> 3) & 7; |
| 1114 | m=modm & 7; |
| 1115 | for (n=0;n <= 7;n++) |
| 1116 | if (MMX(m).b[n] & 127) |
| 1117 | WRITE8(ea+n, MMX(s).b[n]); |
| 1118 | } |
| 1119 | |
| 1120 | void i386_device::pentium_popcnt_r16_rm16() // Opcode f3 0f b8 |
| 1121 | { |
| 1122 | UINT16 src; |
| 1123 | UINT8 modrm = FETCH(); |
| 1124 | int n,count; |
| 1125 | |
| 1126 | if( modrm >= 0xc0 ) { |
| 1127 | src = LOAD_RM16(modrm); |
| 1128 | } else { |
| 1129 | UINT32 ea = GetEA(modrm,0); |
| 1130 | src = READ16(ea); |
| 1131 | } |
| 1132 | count=0; |
| 1133 | for (n=0;n < 16;n++) { |
| 1134 | count=count+(src & 1); |
| 1135 | src=src >> 1; |
| 1136 | } |
| 1137 | STORE_REG16(modrm, count); |
| 1138 | CYCLES(1); // TODO: correct cycle count |
| 1139 | } |
| 1140 | |
| 1141 | void i386_device::pentium_popcnt_r32_rm32() // Opcode f3 0f b8 |
| 1142 | { |
| 1143 | UINT32 src; |
| 1144 | UINT8 modrm = FETCH(); |
| 1145 | int n,count; |
| 1146 | |
| 1147 | if( modrm >= 0xc0 ) { |
| 1148 | src = LOAD_RM32(modrm); |
| 1149 | } else { |
| 1150 | UINT32 ea = GetEA(modrm,0); |
| 1151 | src = READ32(ea); |
| 1152 | } |
| 1153 | count=0; |
| 1154 | for (n=0;n < 32;n++) { |
| 1155 | count=count+(src & 1); |
| 1156 | src=src >> 1; |
| 1157 | } |
| 1158 | STORE_REG32(modrm, count); |
| 1159 | CYCLES(1); // TODO: correct cycle count |
| 1160 | } |
| 1161 | |
| 1162 | void i386_device::pentium_tzcnt_r16_rm16() |
| 1163 | { |
| 1164 | // for CPUs that don't support TZCNT, fall back to BSF |
| 1165 | i386_bsf_r16_rm16(); |
| 1166 | // TODO: actually implement TZCNT |
| 1167 | } |
| 1168 | |
| 1169 | void i386_device::pentium_tzcnt_r32_rm32() |
| 1170 | { |
| 1171 | // for CPUs that don't support TZCNT, fall back to BSF |
| 1172 | i386_bsf_r32_rm32(); |
| 1173 | // TODO: actually implement TZCNT |
| 1174 | } |
| 1175 | |
| 1176 | INLINE INT8 SaturatedSignedWordToSignedByte(INT16 word) |
| 1177 | { |
| 1178 | if (word > 127) |
| 1179 | return 127; |
| 1180 | if (word < -128) |
| 1181 | return -128; |
| 1182 | return (INT8)word; |
| 1183 | } |
| 1184 | |
| 1185 | INLINE UINT8 SaturatedSignedWordToUnsignedByte(INT16 word) |
| 1186 | { |
| 1187 | if (word > 255) |
| 1188 | return 255; |
| 1189 | if (word < 0) |
| 1190 | return 0; |
| 1191 | return (UINT8)word; |
| 1192 | } |
| 1193 | |
| 1194 | INLINE INT16 SaturatedSignedDwordToSignedWord(INT32 dword) |
| 1195 | { |
| 1196 | if (dword > 32767) |
| 1197 | return 32767; |
| 1198 | if (dword < -32768) |
| 1199 | return -32768; |
| 1200 | return (INT16)dword; |
| 1201 | } |
| 1202 | |
| 1203 | void i386_device::mmx_group_0f71() // Opcode 0f 71 |
| 1204 | { |
| 1205 | UINT8 modm = FETCH(); |
| 1206 | UINT8 imm8 = FETCH(); |
| 1207 | MMXPROLOG(); |
| 1208 | if( modm >= 0xc0 ) { |
| 1209 | switch ( (modm & 0x38) >> 3 ) |
| 1210 | { |
| 1211 | case 2: // psrlw |
| 1212 | MMX(modm & 7).w[0]=MMX(modm & 7).w[0] >> imm8; |
| 1213 | MMX(modm & 7).w[1]=MMX(modm & 7).w[1] >> imm8; |
| 1214 | MMX(modm & 7).w[2]=MMX(modm & 7).w[2] >> imm8; |
| 1215 | MMX(modm & 7).w[3]=MMX(modm & 7).w[3] >> imm8; |
| 1216 | break; |
| 1217 | case 4: // psraw |
| 1218 | MMX(modm & 7).s[0]=MMX(modm & 7).s[0] >> imm8; |
| 1219 | MMX(modm & 7).s[1]=MMX(modm & 7).s[1] >> imm8; |
| 1220 | MMX(modm & 7).s[2]=MMX(modm & 7).s[2] >> imm8; |
| 1221 | MMX(modm & 7).s[3]=MMX(modm & 7).s[3] >> imm8; |
| 1222 | break; |
| 1223 | case 6: // psllw |
| 1224 | MMX(modm & 7).w[0]=MMX(modm & 7).w[0] << imm8; |
| 1225 | MMX(modm & 7).w[1]=MMX(modm & 7).w[1] << imm8; |
| 1226 | MMX(modm & 7).w[2]=MMX(modm & 7).w[2] << imm8; |
| 1227 | MMX(modm & 7).w[3]=MMX(modm & 7).w[3] << imm8; |
| 1228 | break; |
| 1229 | default: |
| 1230 | report_invalid_modrm("mmx_group0f71", modm); |
| 1231 | } |
| 1232 | } |
| 1233 | } |
| 1234 | |
| 1235 | void i386_device::mmx_group_0f72() // Opcode 0f 72 |
| 1236 | { |
| 1237 | UINT8 modm = FETCH(); |
| 1238 | UINT8 imm8 = FETCH(); |
| 1239 | MMXPROLOG(); |
| 1240 | if( modm >= 0xc0 ) { |
| 1241 | switch ( (modm & 0x38) >> 3 ) |
| 1242 | { |
| 1243 | case 2: // psrld |
| 1244 | MMX(modm & 7).d[0]=MMX(modm & 7).d[0] >> imm8; |
| 1245 | MMX(modm & 7).d[1]=MMX(modm & 7).d[1] >> imm8; |
| 1246 | break; |
| 1247 | case 4: // psrad |
| 1248 | MMX(modm & 7).i[0]=MMX(modm & 7).i[0] >> imm8; |
| 1249 | MMX(modm & 7).i[1]=MMX(modm & 7).i[1] >> imm8; |
| 1250 | break; |
| 1251 | case 6: // pslld |
| 1252 | MMX(modm & 7).d[0]=MMX(modm & 7).d[0] << imm8; |
| 1253 | MMX(modm & 7).d[1]=MMX(modm & 7).d[1] << imm8; |
| 1254 | break; |
| 1255 | default: |
| 1256 | report_invalid_modrm("mmx_group0f72", modm); |
| 1257 | } |
| 1258 | } |
| 1259 | } |
| 1260 | |
| 1261 | void i386_device::mmx_group_0f73() // Opcode 0f 73 |
| 1262 | { |
| 1263 | UINT8 modm = FETCH(); |
| 1264 | UINT8 imm8 = FETCH(); |
| 1265 | MMXPROLOG(); |
| 1266 | if( modm >= 0xc0 ) { |
| 1267 | switch ( (modm & 0x38) >> 3 ) |
| 1268 | { |
| 1269 | case 2: // psrlq |
| 1270 | MMX(modm & 7).q=MMX(modm & 7).q >> imm8; |
| 1271 | break; |
| 1272 | case 6: // psllq |
| 1273 | MMX(modm & 7).q=MMX(modm & 7).q << imm8; |
| 1274 | break; |
| 1275 | default: |
| 1276 | report_invalid_modrm("mmx_group0f73", modm); |
| 1277 | } |
| 1278 | } |
| 1279 | } |
| 1280 | |
| 1281 | void i386_device::mmx_psrlw_r64_rm64() // Opcode 0f d1 |
| 1282 | { |
| 1283 | MMXPROLOG(); |
| 1284 | UINT8 modrm = FETCH(); |
| 1285 | if( modrm >= 0xc0 ) { |
| 1286 | int count=(int)MMX(modrm & 7).q; |
| 1287 | MMX((modrm >> 3) & 0x7).w[0]=MMX((modrm >> 3) & 0x7).w[0] >> count; |
| 1288 | MMX((modrm >> 3) & 0x7).w[1]=MMX((modrm >> 3) & 0x7).w[1] >> count; |
| 1289 | MMX((modrm >> 3) & 0x7).w[2]=MMX((modrm >> 3) & 0x7).w[2] >> count; |
| 1290 | MMX((modrm >> 3) & 0x7).w[3]=MMX((modrm >> 3) & 0x7).w[3] >> count; |
| 1291 | } else { |
| 1292 | MMX_REG src; |
| 1293 | UINT32 ea = GetEA(modrm, 0); |
| 1294 | READMMX(ea, src); |
| 1295 | int count=(int)src.q; |
| 1296 | MMX((modrm >> 3) & 0x7).w[0]=MMX((modrm >> 3) & 0x7).w[0] >> count; |
| 1297 | MMX((modrm >> 3) & 0x7).w[1]=MMX((modrm >> 3) & 0x7).w[1] >> count; |
| 1298 | MMX((modrm >> 3) & 0x7).w[2]=MMX((modrm >> 3) & 0x7).w[2] >> count; |
| 1299 | MMX((modrm >> 3) & 0x7).w[3]=MMX((modrm >> 3) & 0x7).w[3] >> count; |
| 1300 | } |
| 1301 | CYCLES(1); // TODO: correct cycle count |
| 1302 | } |
| 1303 | |
| 1304 | void i386_device::mmx_psrld_r64_rm64() // Opcode 0f d2 |
| 1305 | { |
| 1306 | MMXPROLOG(); |
| 1307 | UINT8 modrm = FETCH(); |
| 1308 | if( modrm >= 0xc0 ) { |
| 1309 | int count=(int)MMX(modrm & 7).q; |
| 1310 | MMX((modrm >> 3) & 0x7).d[0]=MMX((modrm >> 3) & 0x7).d[0] >> count; |
| 1311 | MMX((modrm >> 3) & 0x7).d[1]=MMX((modrm >> 3) & 0x7).d[1] >> count; |
| 1312 | } else { |
| 1313 | MMX_REG src; |
| 1314 | UINT32 ea = GetEA(modrm, 0); |
| 1315 | READMMX(ea, src); |
| 1316 | int count=(int)src.q; |
| 1317 | MMX((modrm >> 3) & 0x7).d[0]=MMX((modrm >> 3) & 0x7).d[0] >> count; |
| 1318 | MMX((modrm >> 3) & 0x7).d[1]=MMX((modrm >> 3) & 0x7).d[1] >> count; |
| 1319 | } |
| 1320 | CYCLES(1); // TODO: correct cycle count |
| 1321 | } |
| 1322 | |
| 1323 | void i386_device::mmx_psrlq_r64_rm64() // Opcode 0f d3 |
| 1324 | { |
| 1325 | MMXPROLOG(); |
| 1326 | UINT8 modrm = FETCH(); |
| 1327 | if( modrm >= 0xc0 ) { |
| 1328 | int count=(int)MMX(modrm & 7).q; |
| 1329 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q >> count; |
| 1330 | } else { |
| 1331 | MMX_REG src; |
| 1332 | UINT32 ea = GetEA(modrm, 0); |
| 1333 | READMMX(ea, src); |
| 1334 | int count=(int)src.q; |
| 1335 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q >> count; |
| 1336 | } |
| 1337 | CYCLES(1); // TODO: correct cycle count |
| 1338 | } |
| 1339 | |
| 1340 | void i386_device::mmx_paddq_r64_rm64() // Opcode 0f d4 |
| 1341 | { |
| 1342 | MMXPROLOG(); |
| 1343 | UINT8 modrm = FETCH(); |
| 1344 | if( modrm >= 0xc0 ) { |
| 1345 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q+MMX(modrm & 7).q; |
| 1346 | } else { |
| 1347 | MMX_REG src; |
| 1348 | UINT32 ea = GetEA(modrm, 0); |
| 1349 | READMMX(ea, src); |
| 1350 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q+src.q; |
| 1351 | } |
| 1352 | CYCLES(1); // TODO: correct cycle count |
| 1353 | } |
| 1354 | |
| 1355 | void i386_device::mmx_pmullw_r64_rm64() // Opcode 0f d5 |
| 1356 | { |
| 1357 | MMXPROLOG(); |
| 1358 | UINT8 modrm = FETCH(); |
| 1359 | if( modrm >= 0xc0 ) { |
| 1360 | MMX((modrm >> 3) & 0x7).w[0]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)MMX(modrm & 7).s[0]) & 0xffff; |
| 1361 | MMX((modrm >> 3) & 0x7).w[1]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)MMX(modrm & 7).s[1]) & 0xffff; |
| 1362 | MMX((modrm >> 3) & 0x7).w[2]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)MMX(modrm & 7).s[2]) & 0xffff; |
| 1363 | MMX((modrm >> 3) & 0x7).w[3]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)MMX(modrm & 7).s[3]) & 0xffff; |
| 1364 | } else { |
| 1365 | MMX_REG src; |
| 1366 | UINT32 ea = GetEA(modrm, 0); |
| 1367 | READMMX(ea, src); |
| 1368 | MMX((modrm >> 3) & 0x7).w[0]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)src.s[0]) & 0xffff; |
| 1369 | MMX((modrm >> 3) & 0x7).w[1]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)src.s[1]) & 0xffff; |
| 1370 | MMX((modrm >> 3) & 0x7).w[2]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)src.s[2]) & 0xffff; |
| 1371 | MMX((modrm >> 3) & 0x7).w[3]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)src.s[3]) & 0xffff; |
| 1372 | } |
| 1373 | CYCLES(1); // TODO: correct cycle count |
| 1374 | } |
| 1375 | |
| 1376 | void i386_device::mmx_psubusb_r64_rm64() // Opcode 0f d8 |
| 1377 | { |
| 1378 | int n; |
| 1379 | MMXPROLOG(); |
| 1380 | UINT8 modrm = FETCH(); |
| 1381 | if( modrm >= 0xc0 ) { |
| 1382 | for (n=0;n < 8;n++) |
| 1383 | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] < MMX(modrm & 7).b[n] ? 0 : MMX((modrm >> 3) & 0x7).b[n]-MMX(modrm & 7).b[n]; |
| 1384 | } else { |
| 1385 | MMX_REG src; |
| 1386 | UINT32 ea = GetEA(modrm, 0); |
| 1387 | READMMX(ea, src); |
| 1388 | for (n=0;n < 8;n++) |
| 1389 | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] < src.b[n] ? 0 : MMX((modrm >> 3) & 0x7).b[n]-src.b[n]; |
| 1390 | } |
| 1391 | CYCLES(1); // TODO: correct cycle count |
| 1392 | } |
| 1393 | |
| 1394 | void i386_device::mmx_psubusw_r64_rm64() // Opcode 0f d9 |
| 1395 | { |
| 1396 | int n; |
| 1397 | MMXPROLOG(); |
| 1398 | UINT8 modrm = FETCH(); |
| 1399 | if( modrm >= 0xc0 ) { |
| 1400 | for (n=0;n < 4;n++) |
| 1401 | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] < MMX(modrm & 7).w[n] ? 0 : MMX((modrm >> 3) & 0x7).w[n]-MMX(modrm & 7).w[n]; |
| 1402 | } else { |
| 1403 | MMX_REG src; |
| 1404 | UINT32 ea = GetEA(modrm, 0); |
| 1405 | READMMX(ea, src); |
| 1406 | for (n=0;n < 4;n++) |
| 1407 | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] < src.w[n] ? 0 : MMX((modrm >> 3) & 0x7).w[n]-src.w[n]; |
| 1408 | } |
| 1409 | CYCLES(1); // TODO: correct cycle count |
| 1410 | } |
| 1411 | |
| 1412 | void i386_device::mmx_pand_r64_rm64() // Opcode 0f db |
| 1413 | { |
| 1414 | MMXPROLOG(); |
| 1415 | UINT8 modrm = FETCH(); |
| 1416 | if( modrm >= 0xc0 ) { |
| 1417 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q & MMX(modrm & 7).q; |
| 1418 | } else { |
| 1419 | MMX_REG src; |
| 1420 | UINT32 ea = GetEA(modrm, 0); |
| 1421 | READMMX(ea, src); |
| 1422 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q & src.q; |
| 1423 | } |
| 1424 | CYCLES(1); // TODO: correct cycle count |
| 1425 | } |
| 1426 | |
| 1427 | void i386_device::mmx_paddusb_r64_rm64() // Opcode 0f dc |
| 1428 | { |
| 1429 | int n; |
| 1430 | MMXPROLOG(); |
| 1431 | UINT8 modrm = FETCH(); |
| 1432 | if( modrm >= 0xc0 ) { |
| 1433 | for (n=0;n < 8;n++) |
| 1434 | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] > (0xff-MMX(modrm & 7).b[n]) ? 0xff : MMX((modrm >> 3) & 0x7).b[n]+MMX(modrm & 7).b[n]; |
| 1435 | } else { |
| 1436 | MMX_REG src; |
| 1437 | UINT32 ea = GetEA(modrm, 0); |
| 1438 | READMMX(ea, src); |
| 1439 | for (n=0;n < 8;n++) |
| 1440 | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] > (0xff-src.b[n]) ? 0xff : MMX((modrm >> 3) & 0x7).b[n]+src.b[n]; |
| 1441 | } |
| 1442 | CYCLES(1); // TODO: correct cycle count |
| 1443 | } |
| 1444 | |
| 1445 | void i386_device::mmx_paddusw_r64_rm64() // Opcode 0f dd |
| 1446 | { |
| 1447 | int n; |
| 1448 | MMXPROLOG(); |
| 1449 | UINT8 modrm = FETCH(); |
| 1450 | if( modrm >= 0xc0 ) { |
| 1451 | for (n=0;n < 4;n++) |
| 1452 | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] > (0xffff-MMX(modrm & 7).w[n]) ? 0xffff : MMX((modrm >> 3) & 0x7).w[n]+MMX(modrm & 7).w[n]; |
| 1453 | } else { |
| 1454 | MMX_REG src; |
| 1455 | UINT32 ea = GetEA(modrm, 0); |
| 1456 | READMMX(ea, src); |
| 1457 | for (n=0;n < 4;n++) |
| 1458 | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] > (0xffff-src.w[n]) ? 0xffff : MMX((modrm >> 3) & 0x7).w[n]+src.w[n]; |
| 1459 | } |
| 1460 | CYCLES(1); // TODO: correct cycle count |
| 1461 | } |
| 1462 | |
| 1463 | void i386_device::mmx_pandn_r64_rm64() // Opcode 0f df |
| 1464 | { |
| 1465 | MMXPROLOG(); |
| 1466 | UINT8 modrm = FETCH(); |
| 1467 | if( modrm >= 0xc0 ) { |
| 1468 | MMX((modrm >> 3) & 0x7).q=(~MMX((modrm >> 3) & 0x7).q) & MMX(modrm & 7).q; |
| 1469 | } else { |
| 1470 | MMX_REG src; |
| 1471 | UINT32 ea = GetEA(modrm, 0); |
| 1472 | READMMX(ea, src); |
| 1473 | MMX((modrm >> 3) & 0x7).q=(~MMX((modrm >> 3) & 0x7).q) & src.q; |
| 1474 | } |
| 1475 | CYCLES(1); // TODO: correct cycle count |
| 1476 | } |
| 1477 | |
| 1478 | void i386_device::mmx_psraw_r64_rm64() // Opcode 0f e1 |
| 1479 | { |
| 1480 | MMXPROLOG(); |
| 1481 | UINT8 modrm = FETCH(); |
| 1482 | if( modrm >= 0xc0 ) { |
| 1483 | int count=(int)MMX(modrm & 7).q; |
| 1484 | MMX((modrm >> 3) & 0x7).s[0]=MMX((modrm >> 3) & 0x7).s[0] >> count; |
| 1485 | MMX((modrm >> 3) & 0x7).s[1]=MMX((modrm >> 3) & 0x7).s[1] >> count; |
| 1486 | MMX((modrm >> 3) & 0x7).s[2]=MMX((modrm >> 3) & 0x7).s[2] >> count; |
| 1487 | MMX((modrm >> 3) & 0x7).s[3]=MMX((modrm >> 3) & 0x7).s[3] >> count; |
| 1488 | } else { |
| 1489 | MMX_REG src; |
| 1490 | UINT32 ea = GetEA(modrm, 0); |
| 1491 | READMMX(ea, src); |
| 1492 | int count=(int)src.q; |
| 1493 | MMX((modrm >> 3) & 0x7).s[0]=MMX((modrm >> 3) & 0x7).s[0] >> count; |
| 1494 | MMX((modrm >> 3) & 0x7).s[1]=MMX((modrm >> 3) & 0x7).s[1] >> count; |
| 1495 | MMX((modrm >> 3) & 0x7).s[2]=MMX((modrm >> 3) & 0x7).s[2] >> count; |
| 1496 | MMX((modrm >> 3) & 0x7).s[3]=MMX((modrm >> 3) & 0x7).s[3] >> count; |
| 1497 | } |
| 1498 | CYCLES(1); // TODO: correct cycle count |
| 1499 | } |
| 1500 | |
| 1501 | void i386_device::mmx_psrad_r64_rm64() // Opcode 0f e2 |
| 1502 | { |
| 1503 | MMXPROLOG(); |
| 1504 | UINT8 modrm = FETCH(); |
| 1505 | if( modrm >= 0xc0 ) { |
| 1506 | int count=(int)MMX(modrm & 7).q; |
| 1507 | MMX((modrm >> 3) & 0x7).i[0]=MMX((modrm >> 3) & 0x7).i[0] >> count; |
| 1508 | MMX((modrm >> 3) & 0x7).i[1]=MMX((modrm >> 3) & 0x7).i[1] >> count; |
| 1509 | } else { |
| 1510 | MMX_REG src; |
| 1511 | UINT32 ea = GetEA(modrm, 0); |
| 1512 | READMMX(ea, src); |
| 1513 | int count=(int)src.q; |
| 1514 | MMX((modrm >> 3) & 0x7).i[0]=MMX((modrm >> 3) & 0x7).i[0] >> count; |
| 1515 | MMX((modrm >> 3) & 0x7).i[1]=MMX((modrm >> 3) & 0x7).i[1] >> count; |
| 1516 | } |
| 1517 | CYCLES(1); // TODO: correct cycle count |
| 1518 | } |
| 1519 | |
| 1520 | void i386_device::mmx_pmulhw_r64_rm64() // Opcode 0f e5 |
| 1521 | { |
| 1522 | MMXPROLOG(); |
| 1523 | UINT8 modrm = FETCH(); |
| 1524 | if( modrm >= 0xc0 ) { |
| 1525 | MMX((modrm >> 3) & 0x7).w[0]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)MMX(modrm & 7).s[0]) >> 16; |
| 1526 | MMX((modrm >> 3) & 0x7).w[1]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)MMX(modrm & 7).s[1]) >> 16; |
| 1527 | MMX((modrm >> 3) & 0x7).w[2]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)MMX(modrm & 7).s[2]) >> 16; |
| 1528 | MMX((modrm >> 3) & 0x7).w[3]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)MMX(modrm & 7).s[3]) >> 16; |
| 1529 | } else { |
| 1530 | MMX_REG src; |
| 1531 | UINT32 ea = GetEA(modrm, 0); |
| 1532 | READMMX(ea, src); |
| 1533 | MMX((modrm >> 3) & 0x7).w[0]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)src.s[0]) >> 16; |
| 1534 | MMX((modrm >> 3) & 0x7).w[1]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)src.s[1]) >> 16; |
| 1535 | MMX((modrm >> 3) & 0x7).w[2]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)src.s[2]) >> 16; |
| 1536 | MMX((modrm >> 3) & 0x7).w[3]=(UINT32)((INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)src.s[3]) >> 16; |
| 1537 | } |
| 1538 | CYCLES(1); // TODO: correct cycle count |
| 1539 | } |
| 1540 | |
| 1541 | void i386_device::mmx_psubsb_r64_rm64() // Opcode 0f e8 |
| 1542 | { |
| 1543 | int n; |
| 1544 | MMXPROLOG(); |
| 1545 | UINT8 modrm = FETCH(); |
| 1546 | if( modrm >= 0xc0 ) { |
| 1547 | for (n=0;n < 8;n++) |
| 1548 | MMX((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)MMX((modrm >> 3) & 0x7).c[n] - (INT16)MMX(modrm & 7).c[n]); |
| 1549 | } else { |
| 1550 | MMX_REG s; |
| 1551 | UINT32 ea = GetEA(modrm, 0); |
| 1552 | READMMX(ea, s); |
| 1553 | for (n=0;n < 8;n++) |
| 1554 | MMX((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)MMX((modrm >> 3) & 0x7).c[n] - (INT16)s.c[n]); |
| 1555 | } |
| 1556 | CYCLES(1); // TODO: correct cycle count |
| 1557 | } |
| 1558 | |
| 1559 | void i386_device::mmx_psubsw_r64_rm64() // Opcode 0f e9 |
| 1560 | { |
| 1561 | int n; |
| 1562 | MMXPROLOG(); |
| 1563 | UINT8 modrm = FETCH(); |
| 1564 | if( modrm >= 0xc0 ) { |
| 1565 | for (n=0;n < 4;n++) |
| 1566 | MMX((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)MMX((modrm >> 3) & 0x7).s[n] - (INT32)MMX(modrm & 7).s[n]); |
| 1567 | } else { |
| 1568 | MMX_REG s; |
| 1569 | UINT32 ea = GetEA(modrm, 0); |
| 1570 | READMMX(ea, s); |
| 1571 | for (n=0;n < 4;n++) |
| 1572 | MMX((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)MMX((modrm >> 3) & 0x7).s[n] - (INT32)s.s[n]); |
| 1573 | } |
| 1574 | CYCLES(1); // TODO: correct cycle count |
| 1575 | } |
| 1576 | |
| 1577 | void i386_device::mmx_por_r64_rm64() // Opcode 0f eb |
| 1578 | { |
| 1579 | MMXPROLOG(); |
| 1580 | UINT8 modrm = FETCH(); |
| 1581 | if( modrm >= 0xc0 ) { |
| 1582 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q | MMX(modrm & 7).q; |
| 1583 | } else { |
| 1584 | MMX_REG s; |
| 1585 | UINT32 ea = GetEA(modrm, 0); |
| 1586 | READMMX(ea, s); |
| 1587 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q | s.q; |
| 1588 | } |
| 1589 | CYCLES(1); // TODO: correct cycle count |
| 1590 | } |
| 1591 | |
| 1592 | void i386_device::mmx_paddsb_r64_rm64() // Opcode 0f ec |
| 1593 | { |
| 1594 | int n; |
| 1595 | MMXPROLOG(); |
| 1596 | UINT8 modrm = FETCH(); |
| 1597 | if( modrm >= 0xc0 ) { |
| 1598 | for (n=0;n < 8;n++) |
| 1599 | MMX((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)MMX((modrm >> 3) & 0x7).c[n] + (INT16)MMX(modrm & 7).c[n]); |
| 1600 | } else { |
| 1601 | MMX_REG s; |
| 1602 | UINT32 ea = GetEA(modrm, 0); |
| 1603 | READMMX(ea, s); |
| 1604 | for (n=0;n < 8;n++) |
| 1605 | MMX((modrm >> 3) & 0x7).c[n]=SaturatedSignedWordToSignedByte((INT16)MMX((modrm >> 3) & 0x7).c[n] + (INT16)s.c[n]); |
| 1606 | } |
| 1607 | CYCLES(1); // TODO: correct cycle count |
| 1608 | } |
| 1609 | |
| 1610 | void i386_device::mmx_paddsw_r64_rm64() // Opcode 0f ed |
| 1611 | { |
| 1612 | int n; |
| 1613 | MMXPROLOG(); |
| 1614 | UINT8 modrm = FETCH(); |
| 1615 | if( modrm >= 0xc0 ) { |
| 1616 | for (n=0;n < 4;n++) |
| 1617 | MMX((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)MMX((modrm >> 3) & 0x7).s[n] + (INT32)MMX(modrm & 7).s[n]); |
| 1618 | } else { |
| 1619 | MMX_REG s; |
| 1620 | UINT32 ea = GetEA(modrm, 0); |
| 1621 | READMMX(ea, s); |
| 1622 | for (n=0;n < 4;n++) |
| 1623 | MMX((modrm >> 3) & 0x7).s[n]=SaturatedSignedDwordToSignedWord((INT32)MMX((modrm >> 3) & 0x7).s[n] + (INT32)s.s[n]); |
| 1624 | } |
| 1625 | CYCLES(1); // TODO: correct cycle count |
| 1626 | } |
| 1627 | |
| 1628 | void i386_device::mmx_pxor_r64_rm64() // Opcode 0f ef |
| 1629 | { |
| 1630 | MMXPROLOG(); |
| 1631 | UINT8 modrm = FETCH(); |
| 1632 | if( modrm >= 0xc0 ) { |
| 1633 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q ^ MMX(modrm & 7).q; |
| 1634 | } else { |
| 1635 | MMX_REG s; |
| 1636 | UINT32 ea = GetEA(modrm, 0); |
| 1637 | READMMX(ea, s); |
| 1638 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q ^ s.q; |
| 1639 | } |
| 1640 | CYCLES(1); // TODO: correct cycle count |
| 1641 | } |
| 1642 | |
| 1643 | void i386_device::mmx_psllw_r64_rm64() // Opcode 0f f1 |
| 1644 | { |
| 1645 | MMXPROLOG(); |
| 1646 | UINT8 modrm = FETCH(); |
| 1647 | if( modrm >= 0xc0 ) { |
| 1648 | int count=(int)MMX(modrm & 7).q; |
| 1649 | MMX((modrm >> 3) & 0x7).w[0]=MMX((modrm >> 3) & 0x7).w[0] << count; |
| 1650 | MMX((modrm >> 3) & 0x7).w[1]=MMX((modrm >> 3) & 0x7).w[1] << count; |
| 1651 | MMX((modrm >> 3) & 0x7).w[2]=MMX((modrm >> 3) & 0x7).w[2] << count; |
| 1652 | MMX((modrm >> 3) & 0x7).w[3]=MMX((modrm >> 3) & 0x7).w[3] << count; |
| 1653 | } else { |
| 1654 | MMX_REG s; |
| 1655 | UINT32 ea = GetEA(modrm, 0); |
| 1656 | READMMX(ea, s); |
| 1657 | int count=(int)s.q; |
| 1658 | MMX((modrm >> 3) & 0x7).w[0]=MMX((modrm >> 3) & 0x7).w[0] << count; |
| 1659 | MMX((modrm >> 3) & 0x7).w[1]=MMX((modrm >> 3) & 0x7).w[1] << count; |
| 1660 | MMX((modrm >> 3) & 0x7).w[2]=MMX((modrm >> 3) & 0x7).w[2] << count; |
| 1661 | MMX((modrm >> 3) & 0x7).w[3]=MMX((modrm >> 3) & 0x7).w[3] << count; |
| 1662 | } |
| 1663 | CYCLES(1); // TODO: correct cycle count |
| 1664 | } |
| 1665 | |
| 1666 | void i386_device::mmx_pslld_r64_rm64() // Opcode 0f f2 |
| 1667 | { |
| 1668 | MMXPROLOG(); |
| 1669 | UINT8 modrm = FETCH(); |
| 1670 | if( modrm >= 0xc0 ) { |
| 1671 | int count=(int)MMX(modrm & 7).q; |
| 1672 | MMX((modrm >> 3) & 0x7).d[0]=MMX((modrm >> 3) & 0x7).d[0] << count; |
| 1673 | MMX((modrm >> 3) & 0x7).d[1]=MMX((modrm >> 3) & 0x7).d[1] << count; |
| 1674 | } else { |
| 1675 | MMX_REG s; |
| 1676 | UINT32 ea = GetEA(modrm, 0); |
| 1677 | READMMX(ea, s); |
| 1678 | int count=(int)s.q; |
| 1679 | MMX((modrm >> 3) & 0x7).d[0]=MMX((modrm >> 3) & 0x7).d[0] << count; |
| 1680 | MMX((modrm >> 3) & 0x7).d[1]=MMX((modrm >> 3) & 0x7).d[1] << count; |
| 1681 | } |
| 1682 | CYCLES(1); // TODO: correct cycle count |
| 1683 | } |
| 1684 | |
| 1685 | void i386_device::mmx_psllq_r64_rm64() // Opcode 0f f3 |
| 1686 | { |
| 1687 | MMXPROLOG(); |
| 1688 | UINT8 modrm = FETCH(); |
| 1689 | if( modrm >= 0xc0 ) { |
| 1690 | int count=(int)MMX(modrm & 7).q; |
| 1691 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q << count; |
| 1692 | } else { |
| 1693 | MMX_REG s; |
| 1694 | UINT32 ea = GetEA(modrm, 0); |
| 1695 | READMMX(ea, s); |
| 1696 | int count=(int)s.q; |
| 1697 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q << count; |
| 1698 | } |
| 1699 | CYCLES(1); // TODO: correct cycle count |
| 1700 | } |
| 1701 | |
| 1702 | void i386_device::mmx_pmaddwd_r64_rm64() // Opcode 0f f5 |
| 1703 | { |
| 1704 | MMXPROLOG(); |
| 1705 | UINT8 modrm = FETCH(); |
| 1706 | if( modrm >= 0xc0 ) { |
| 1707 | MMX((modrm >> 3) & 0x7).i[0]=(INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)MMX(modrm & 7).s[0]+ |
| 1708 | (INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)MMX(modrm & 7).s[1]; |
| 1709 | MMX((modrm >> 3) & 0x7).i[1]=(INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)MMX(modrm & 7).s[2]+ |
| 1710 | (INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)MMX(modrm & 7).s[3]; |
| 1711 | } else { |
| 1712 | MMX_REG s; |
| 1713 | UINT32 ea = GetEA(modrm, 0); |
| 1714 | READMMX(ea, s); |
| 1715 | MMX((modrm >> 3) & 0x7).i[0]=(INT32)MMX((modrm >> 3) & 0x7).s[0]*(INT32)s.s[0]+ |
| 1716 | (INT32)MMX((modrm >> 3) & 0x7).s[1]*(INT32)s.s[1]; |
| 1717 | MMX((modrm >> 3) & 0x7).i[1]=(INT32)MMX((modrm >> 3) & 0x7).s[2]*(INT32)s.s[2]+ |
| 1718 | (INT32)MMX((modrm >> 3) & 0x7).s[3]*(INT32)s.s[3]; |
| 1719 | } |
| 1720 | CYCLES(1); // TODO: correct cycle count |
| 1721 | } |
| 1722 | |
| 1723 | void i386_device::mmx_psubb_r64_rm64() // Opcode 0f f8 |
| 1724 | { |
| 1725 | int n; |
| 1726 | MMXPROLOG(); |
| 1727 | UINT8 modrm = FETCH(); |
| 1728 | if( modrm >= 0xc0 ) { |
| 1729 | for (n=0;n < 8;n++) |
| 1730 | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] - MMX(modrm & 7).b[n]; |
| 1731 | } else { |
| 1732 | MMX_REG s; |
| 1733 | UINT32 ea = GetEA(modrm, 0); |
| 1734 | READMMX(ea, s); |
| 1735 | for (n=0;n < 8;n++) |
| 1736 | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] - s.b[n]; |
| 1737 | } |
| 1738 | CYCLES(1); // TODO: correct cycle count |
| 1739 | } |
| 1740 | |
| 1741 | void i386_device::mmx_psubw_r64_rm64() // Opcode 0f f9 |
| 1742 | { |
| 1743 | int n; |
| 1744 | MMXPROLOG(); |
| 1745 | UINT8 modrm = FETCH(); |
| 1746 | if( modrm >= 0xc0 ) { |
| 1747 | for (n=0;n < 4;n++) |
| 1748 | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] - MMX(modrm & 7).w[n]; |
| 1749 | } else { |
| 1750 | MMX_REG s; |
| 1751 | UINT32 ea = GetEA(modrm, 0); |
| 1752 | READMMX(ea, s); |
| 1753 | for (n=0;n < 4;n++) |
| 1754 | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] - s.w[n]; |
| 1755 | } |
| 1756 | CYCLES(1); // TODO: correct cycle count |
| 1757 | } |
| 1758 | |
| 1759 | void i386_device::mmx_psubd_r64_rm64() // Opcode 0f fa |
| 1760 | { |
| 1761 | int n; |
| 1762 | MMXPROLOG(); |
| 1763 | UINT8 modrm = FETCH(); |
| 1764 | if( modrm >= 0xc0 ) { |
| 1765 | for (n=0;n < 2;n++) |
| 1766 | MMX((modrm >> 3) & 0x7).d[n]=MMX((modrm >> 3) & 0x7).d[n] - MMX(modrm & 7).d[n]; |
| 1767 | } else { |
| 1768 | MMX_REG s; |
| 1769 | UINT32 ea = GetEA(modrm, 0); |
| 1770 | READMMX(ea, s); |
| 1771 | for (n=0;n < 2;n++) |
| 1772 | MMX((modrm >> 3) & 0x7).d[n]=MMX((modrm >> 3) & 0x7).d[n] - s.d[n]; |
| 1773 | } |
| 1774 | CYCLES(1); // TODO: correct cycle count |
| 1775 | } |
| 1776 | |
| 1777 | void i386_device::mmx_paddb_r64_rm64() // Opcode 0f fc |
| 1778 | { |
| 1779 | int n; |
| 1780 | MMXPROLOG(); |
| 1781 | UINT8 modrm = FETCH(); |
| 1782 | if( modrm >= 0xc0 ) { |
| 1783 | for (n=0;n < 8;n++) |
| 1784 | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] + MMX(modrm & 7).b[n]; |
| 1785 | } else { |
| 1786 | MMX_REG s; |
| 1787 | UINT32 ea = GetEA(modrm, 0); |
| 1788 | READMMX(ea, s); |
| 1789 | for (n=0;n < 8;n++) |
| 1790 | MMX((modrm >> 3) & 0x7).b[n]=MMX((modrm >> 3) & 0x7).b[n] + s.b[n]; |
| 1791 | } |
| 1792 | CYCLES(1); // TODO: correct cycle count |
| 1793 | } |
| 1794 | |
| 1795 | void i386_device::mmx_paddw_r64_rm64() // Opcode 0f fd |
| 1796 | { |
| 1797 | int n; |
| 1798 | MMXPROLOG(); |
| 1799 | UINT8 modrm = FETCH(); |
| 1800 | if( modrm >= 0xc0 ) { |
| 1801 | for (n=0;n < 4;n++) |
| 1802 | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] + MMX(modrm & 7).w[n]; |
| 1803 | } else { |
| 1804 | MMX_REG s; |
| 1805 | UINT32 ea = GetEA(modrm, 0); |
| 1806 | READMMX(ea, s); |
| 1807 | for (n=0;n < 4;n++) |
| 1808 | MMX((modrm >> 3) & 0x7).w[n]=MMX((modrm >> 3) & 0x7).w[n] + s.w[n]; |
| 1809 | } |
| 1810 | CYCLES(1); // TODO: correct cycle count |
| 1811 | } |
| 1812 | |
| 1813 | void i386_device::mmx_paddd_r64_rm64() // Opcode 0f fe |
| 1814 | { |
| 1815 | int n; |
| 1816 | MMXPROLOG(); |
| 1817 | UINT8 modrm = FETCH(); |
| 1818 | if( modrm >= 0xc0 ) { |
| 1819 | for (n=0;n < 2;n++) |
| 1820 | MMX((modrm >> 3) & 0x7).d[n]=MMX((modrm >> 3) & 0x7).d[n] + MMX(modrm & 7).d[n]; |
| 1821 | } else { |
| 1822 | MMX_REG s; |
| 1823 | UINT32 ea = GetEA(modrm, 0); |
| 1824 | READMMX(ea, s); |
| 1825 | for (n=0;n < 2;n++) |
| 1826 | MMX((modrm >> 3) & 0x7).d[n]=MMX((modrm >> 3) & 0x7).d[n] + s.d[n]; |
| 1827 | } |
| 1828 | CYCLES(1); // TODO: correct cycle count |
| 1829 | } |
| 1830 | |
| 1831 | void i386_device::mmx_emms() // Opcode 0f 77 |
| 1832 | { |
| 1833 | m_x87_tw = 0xffff; // tag word = 0xffff |
| 1834 | // TODO |
| 1835 | CYCLES(1); // TODO: correct cycle count |
| 1836 | } |
| 1837 | |
| 1838 | void i386_device::mmx_movd_r64_rm32() // Opcode 0f 6e |
| 1839 | { |
| 1840 | MMXPROLOG(); |
| 1841 | UINT8 modrm = FETCH(); |
| 1842 | if( modrm >= 0xc0 ) { |
| 1843 | MMX((modrm >> 3) & 0x7).d[0]=LOAD_RM32(modrm); |
| 1844 | } else { |
| 1845 | UINT32 ea = GetEA(modrm, 0); |
| 1846 | MMX((modrm >> 3) & 0x7).d[0]=READ32(ea); |
| 1847 | } |
| 1848 | MMX((modrm >> 3) & 0x7).d[1]=0; |
| 1849 | CYCLES(1); // TODO: correct cycle count |
| 1850 | } |
| 1851 | |
| 1852 | void i386_device::mmx_movq_r64_rm64() // Opcode 0f 6f |
| 1853 | { |
| 1854 | MMXPROLOG(); |
| 1855 | UINT8 modrm = FETCH(); |
| 1856 | if( modrm >= 0xc0 ) { |
| 1857 | MMX((modrm >> 3) & 0x7).l=MMX(modrm & 0x7).l; |
| 1858 | } else { |
| 1859 | UINT32 ea = GetEA(modrm, 0); |
| 1860 | READMMX(ea, MMX((modrm >> 3) & 0x7)); |
| 1861 | } |
| 1862 | CYCLES(1); // TODO: correct cycle count |
| 1863 | } |
| 1864 | |
| 1865 | void i386_device::mmx_movd_rm32_r64() // Opcode 0f 7e |
| 1866 | { |
| 1867 | MMXPROLOG(); |
| 1868 | UINT8 modrm = FETCH(); |
| 1869 | if( modrm >= 0xc0 ) { |
| 1870 | STORE_RM32(modrm, MMX((modrm >> 3) & 0x7).d[0]); |
| 1871 | } else { |
| 1872 | UINT32 ea = GetEA(modrm, 0); |
| 1873 | WRITE32(ea, MMX((modrm >> 3) & 0x7).d[0]); |
| 1874 | } |
| 1875 | CYCLES(1); // TODO: correct cycle count |
| 1876 | } |
| 1877 | |
| 1878 | void i386_device::mmx_movq_rm64_r64() // Opcode 0f 7f |
| 1879 | { |
| 1880 | MMXPROLOG(); |
| 1881 | UINT8 modrm = FETCH(); |
| 1882 | if( modrm >= 0xc0 ) { |
| 1883 | MMX(modrm & 0x7)=MMX((modrm >> 3) & 0x7); |
| 1884 | } else { |
| 1885 | UINT32 ea = GetEA(modrm, 0); |
| 1886 | WRITEMMX(ea, MMX((modrm >> 3) & 0x7)); |
| 1887 | } |
| 1888 | CYCLES(1); // TODO: correct cycle count |
| 1889 | } |
| 1890 | |
| 1891 | void i386_device::mmx_pcmpeqb_r64_rm64() // Opcode 0f 74 |
| 1892 | { |
| 1893 | int c; |
| 1894 | MMXPROLOG(); |
| 1895 | UINT8 modrm = FETCH(); |
| 1896 | if( modrm >= 0xc0 ) { |
| 1897 | int s,d; |
| 1898 | s=modrm & 0x7; |
| 1899 | d=(modrm >> 3) & 0x7; |
| 1900 | for (c=0;c <= 7;c++) |
| 1901 | MMX(d).b[c]=(MMX(d).b[c] == MMX(s).b[c]) ? 0xff : 0; |
| 1902 | } else { |
| 1903 | MMX_REG s; |
| 1904 | int d=(modrm >> 3) & 0x7; |
| 1905 | UINT32 ea = GetEA(modrm, 0); |
| 1906 | READMMX(ea, s); |
| 1907 | for (c=0;c <= 7;c++) |
| 1908 | MMX(d).b[c]=(MMX(d).b[c] == s.b[c]) ? 0xff : 0; |
| 1909 | } |
| 1910 | CYCLES(1); // TODO: correct cycle count |
| 1911 | } |
| 1912 | |
| 1913 | void i386_device::mmx_pcmpeqw_r64_rm64() // Opcode 0f 75 |
| 1914 | { |
| 1915 | MMXPROLOG(); |
| 1916 | UINT8 modrm = FETCH(); |
| 1917 | if( modrm >= 0xc0 ) { |
| 1918 | int s,d; |
| 1919 | s=modrm & 0x7; |
| 1920 | d=(modrm >> 3) & 0x7; |
| 1921 | MMX(d).w[0]=(MMX(d).w[0] == MMX(s).w[0]) ? 0xffff : 0; |
| 1922 | MMX(d).w[1]=(MMX(d).w[1] == MMX(s).w[1]) ? 0xffff : 0; |
| 1923 | MMX(d).w[2]=(MMX(d).w[2] == MMX(s).w[2]) ? 0xffff : 0; |
| 1924 | MMX(d).w[3]=(MMX(d).w[3] == MMX(s).w[3]) ? 0xffff : 0; |
| 1925 | } else { |
| 1926 | MMX_REG s; |
| 1927 | int d=(modrm >> 3) & 0x7; |
| 1928 | UINT32 ea = GetEA(modrm, 0); |
| 1929 | READMMX(ea, s); |
| 1930 | MMX(d).w[0]=(MMX(d).w[0] == s.w[0]) ? 0xffff : 0; |
| 1931 | MMX(d).w[1]=(MMX(d).w[1] == s.w[1]) ? 0xffff : 0; |
| 1932 | MMX(d).w[2]=(MMX(d).w[2] == s.w[2]) ? 0xffff : 0; |
| 1933 | MMX(d).w[3]=(MMX(d).w[3] == s.w[3]) ? 0xffff : 0; |
| 1934 | } |
| 1935 | CYCLES(1); // TODO: correct cycle count |
| 1936 | } |
| 1937 | |
| 1938 | void i386_device::mmx_pcmpeqd_r64_rm64() // Opcode 0f 76 |
| 1939 | { |
| 1940 | MMXPROLOG(); |
| 1941 | UINT8 modrm = FETCH(); |
| 1942 | if( modrm >= 0xc0 ) { |
| 1943 | int s,d; |
| 1944 | s=modrm & 0x7; |
| 1945 | d=(modrm >> 3) & 0x7; |
| 1946 | MMX(d).d[0]=(MMX(d).d[0] == MMX(s).d[0]) ? 0xffffffff : 0; |
| 1947 | MMX(d).d[1]=(MMX(d).d[1] == MMX(s).d[1]) ? 0xffffffff : 0; |
| 1948 | } else { |
| 1949 | MMX_REG s; |
| 1950 | int d=(modrm >> 3) & 0x7; |
| 1951 | UINT32 ea = GetEA(modrm, 0); |
| 1952 | READMMX(ea, s); |
| 1953 | MMX(d).d[0]=(MMX(d).d[0] == s.d[0]) ? 0xffffffff : 0; |
| 1954 | MMX(d).d[1]=(MMX(d).d[1] == s.d[1]) ? 0xffffffff : 0; |
| 1955 | } |
| 1956 | CYCLES(1); // TODO: correct cycle count |
| 1957 | } |
| 1958 | |
| 1959 | void i386_device::mmx_pshufw_r64_rm64_i8() // Opcode 0f 70 |
| 1960 | { |
| 1961 | MMXPROLOG(); |
| 1962 | UINT8 modrm = FETCH(); |
| 1963 | if( modrm >= 0xc0 ) { |
| 1964 | MMX_REG t; |
| 1965 | int s,d; |
| 1966 | UINT8 imm8 = FETCH(); |
| 1967 | s=modrm & 0x7; |
| 1968 | d=(modrm >> 3) & 0x7; |
| 1969 | t.q=MMX(s).q; |
| 1970 | MMX(d).w[0]=t.w[imm8 & 3]; |
| 1971 | MMX(d).w[1]=t.w[(imm8 >> 2) & 3]; |
| 1972 | MMX(d).w[2]=t.w[(imm8 >> 4) & 3]; |
| 1973 | MMX(d).w[3]=t.w[(imm8 >> 6) & 3]; |
| 1974 | } else { |
| 1975 | MMX_REG s; |
| 1976 | int d=(modrm >> 3) & 0x7; |
| 1977 | UINT32 ea = GetEA(modrm, 0); |
| 1978 | UINT8 imm8 = FETCH(); |
| 1979 | READMMX(ea, s); |
| 1980 | MMX(d).w[0]=s.w[imm8 & 3]; |
| 1981 | MMX(d).w[1]=s.w[(imm8 >> 2) & 3]; |
| 1982 | MMX(d).w[2]=s.w[(imm8 >> 4) & 3]; |
| 1983 | MMX(d).w[3]=s.w[(imm8 >> 6) & 3]; |
| 1984 | } |
| 1985 | CYCLES(1); // TODO: correct cycle count |
| 1986 | } |
| 1987 | |
| 1988 | void i386_device::mmx_punpcklbw_r64_r64m32() // Opcode 0f 60 |
| 1989 | { |
| 1990 | MMXPROLOG(); |
| 1991 | UINT8 modrm = FETCH(); |
| 1992 | if( modrm >= 0xc0 ) { |
| 1993 | UINT32 t; |
| 1994 | int s,d; |
| 1995 | s=modrm & 0x7; |
| 1996 | d=(modrm >> 3) & 0x7; |
| 1997 | t=MMX(d).d[0]; |
| 1998 | MMX(d).b[0]=t & 0xff; |
| 1999 | MMX(d).b[1]=MMX(s).b[0]; |
| 2000 | MMX(d).b[2]=(t >> 8) & 0xff; |
| 2001 | MMX(d).b[3]=MMX(s).b[1]; |
| 2002 | MMX(d).b[4]=(t >> 16) & 0xff; |
| 2003 | MMX(d).b[5]=MMX(s).b[2]; |
| 2004 | MMX(d).b[6]=(t >> 24) & 0xff; |
| 2005 | MMX(d).b[7]=MMX(s).b[3]; |
| 2006 | } else { |
| 2007 | UINT32 s,t; |
| 2008 | int d=(modrm >> 3) & 0x7; |
| 2009 | UINT32 ea = GetEA(modrm, 0); |
| 2010 | s = READ32(ea); |
| 2011 | t=MMX(d).d[0]; |
| 2012 | MMX(d).b[0]=t & 0xff; |
| 2013 | MMX(d).b[1]=s & 0xff; |
| 2014 | MMX(d).b[2]=(t >> 8) & 0xff; |
| 2015 | MMX(d).b[3]=(s >> 8) & 0xff; |
| 2016 | MMX(d).b[4]=(t >> 16) & 0xff; |
| 2017 | MMX(d).b[5]=(s >> 16) & 0xff; |
| 2018 | MMX(d).b[6]=(t >> 24) & 0xff; |
| 2019 | MMX(d).b[7]=(s >> 24) & 0xff; |
| 2020 | } |
| 2021 | CYCLES(1); // TODO: correct cycle count |
| 2022 | } |
| 2023 | |
| 2024 | void i386_device::mmx_punpcklwd_r64_r64m32() // Opcode 0f 61 |
| 2025 | { |
| 2026 | MMXPROLOG(); |
| 2027 | UINT8 modrm = FETCH(); |
| 2028 | if( modrm >= 0xc0 ) { |
| 2029 | UINT16 t; |
| 2030 | int s,d; |
| 2031 | s=modrm & 0x7; |
| 2032 | d=(modrm >> 3) & 0x7; |
| 2033 | t=MMX(d).w[1]; |
| 2034 | MMX(d).w[0]=MMX(d).w[0]; |
| 2035 | MMX(d).w[1]=MMX(s).w[0]; |
| 2036 | MMX(d).w[2]=t; |
| 2037 | MMX(d).w[3]=MMX(s).w[1]; |
| 2038 | } else { |
| 2039 | UINT32 s; |
| 2040 | UINT16 t; |
| 2041 | int d=(modrm >> 3) & 0x7; |
| 2042 | UINT32 ea = GetEA(modrm, 0); |
| 2043 | s = READ32(ea); |
| 2044 | t=MMX(d).w[1]; |
| 2045 | MMX(d).w[0]=MMX(d).w[0]; |
| 2046 | MMX(d).w[1]=s & 0xffff; |
| 2047 | MMX(d).w[2]=t; |
| 2048 | MMX(d).w[3]=(s >> 16) & 0xffff; |
| 2049 | } |
| 2050 | CYCLES(1); // TODO: correct cycle count |
| 2051 | } |
| 2052 | |
| 2053 | void i386_device::mmx_punpckldq_r64_r64m32() // Opcode 0f 62 |
| 2054 | { |
| 2055 | MMXPROLOG(); |
| 2056 | UINT8 modrm = FETCH(); |
| 2057 | if( modrm >= 0xc0 ) { |
| 2058 | int s,d; |
| 2059 | s=modrm & 0x7; |
| 2060 | d=(modrm >> 3) & 0x7; |
| 2061 | MMX(d).d[0]=MMX(d).d[0]; |
| 2062 | MMX(d).d[1]=MMX(s).d[0]; |
| 2063 | } else { |
| 2064 | UINT32 s; |
| 2065 | int d=(modrm >> 3) & 0x7; |
| 2066 | UINT32 ea = GetEA(modrm, 0); |
| 2067 | s = READ32(ea); |
| 2068 | MMX(d).d[0]=MMX(d).d[0]; |
| 2069 | MMX(d).d[1]=s; |
| 2070 | } |
| 2071 | CYCLES(1); // TODO: correct cycle count |
| 2072 | } |
| 2073 | |
| 2074 | void i386_device::mmx_packsswb_r64_rm64() // Opcode 0f 63 |
| 2075 | { |
| 2076 | MMXPROLOG(); |
| 2077 | UINT8 modrm = FETCH(); |
| 2078 | if( modrm >= 0xc0 ) { |
| 2079 | int s,d; |
| 2080 | s=modrm & 0x7; |
| 2081 | d=(modrm >> 3) & 0x7; |
| 2082 | MMX(d).c[0]=SaturatedSignedWordToSignedByte(MMX(d).s[0]); |
| 2083 | MMX(d).c[1]=SaturatedSignedWordToSignedByte(MMX(d).s[1]); |
| 2084 | MMX(d).c[2]=SaturatedSignedWordToSignedByte(MMX(d).s[2]); |
| 2085 | MMX(d).c[3]=SaturatedSignedWordToSignedByte(MMX(d).s[3]); |
| 2086 | MMX(d).c[4]=SaturatedSignedWordToSignedByte(MMX(s).s[0]); |
| 2087 | MMX(d).c[5]=SaturatedSignedWordToSignedByte(MMX(s).s[1]); |
| 2088 | MMX(d).c[6]=SaturatedSignedWordToSignedByte(MMX(s).s[2]); |
| 2089 | MMX(d).c[7]=SaturatedSignedWordToSignedByte(MMX(s).s[3]); |
| 2090 | } else { |
| 2091 | MMX_REG s; |
| 2092 | int d=(modrm >> 3) & 0x7; |
| 2093 | UINT32 ea = GetEA(modrm, 0); |
| 2094 | READMMX(ea, s); |
| 2095 | MMX(d).c[0]=SaturatedSignedWordToSignedByte(MMX(d).s[0]); |
| 2096 | MMX(d).c[1]=SaturatedSignedWordToSignedByte(MMX(d).s[1]); |
| 2097 | MMX(d).c[2]=SaturatedSignedWordToSignedByte(MMX(d).s[2]); |
| 2098 | MMX(d).c[3]=SaturatedSignedWordToSignedByte(MMX(d).s[3]); |
| 2099 | MMX(d).c[4]=SaturatedSignedWordToSignedByte(s.s[0]); |
| 2100 | MMX(d).c[5]=SaturatedSignedWordToSignedByte(s.s[1]); |
| 2101 | MMX(d).c[6]=SaturatedSignedWordToSignedByte(s.s[2]); |
| 2102 | MMX(d).c[7]=SaturatedSignedWordToSignedByte(s.s[3]); |
| 2103 | } |
| 2104 | CYCLES(1); // TODO: correct cycle count |
| 2105 | } |
| 2106 | |
| 2107 | void i386_device::mmx_pcmpgtb_r64_rm64() // Opcode 0f 64 |
| 2108 | { |
| 2109 | int c; |
| 2110 | MMXPROLOG(); |
| 2111 | UINT8 modrm = FETCH(); |
| 2112 | if( modrm >= 0xc0 ) { |
| 2113 | int s,d; |
| 2114 | s=modrm & 0x7; |
| 2115 | d=(modrm >> 3) & 0x7; |
| 2116 | for (c=0;c <= 7;c++) |
| 2117 | MMX(d).b[c]=(MMX(d).c[c] > MMX(s).c[c]) ? 0xff : 0; |
| 2118 | } else { |
| 2119 | MMX_REG s; |
| 2120 | int d=(modrm >> 3) & 0x7; |
| 2121 | UINT32 ea = GetEA(modrm, 0); |
| 2122 | READMMX(ea, s); |
| 2123 | for (c=0;c <= 7;c++) |
| 2124 | MMX(d).b[c]=(MMX(d).c[c] > s.c[c]) ? 0xff : 0; |
| 2125 | } |
| 2126 | CYCLES(1); // TODO: correct cycle count |
| 2127 | } |
| 2128 | |
| 2129 | void i386_device::mmx_pcmpgtw_r64_rm64() // Opcode 0f 65 |
| 2130 | { |
| 2131 | int c; |
| 2132 | MMXPROLOG(); |
| 2133 | UINT8 modrm = FETCH(); |
| 2134 | if( modrm >= 0xc0 ) { |
| 2135 | int s,d; |
| 2136 | s=modrm & 0x7; |
| 2137 | d=(modrm >> 3) & 0x7; |
| 2138 | for (c=0;c <= 3;c++) |
| 2139 | MMX(d).w[c]=(MMX(d).s[c] > MMX(s).s[c]) ? 0xffff : 0; |
| 2140 | } else { |
| 2141 | MMX_REG s; |
| 2142 | int d=(modrm >> 3) & 0x7; |
| 2143 | UINT32 ea = GetEA(modrm, 0); |
| 2144 | READMMX(ea, s); |
| 2145 | for (c=0;c <= 3;c++) |
| 2146 | MMX(d).w[c]=(MMX(d).s[c] > s.s[c]) ? 0xffff : 0; |
| 2147 | } |
| 2148 | CYCLES(1); // TODO: correct cycle count |
| 2149 | } |
| 2150 | |
| 2151 | void i386_device::mmx_pcmpgtd_r64_rm64() // Opcode 0f 66 |
| 2152 | { |
| 2153 | int c; |
| 2154 | MMXPROLOG(); |
| 2155 | UINT8 modrm = FETCH(); |
| 2156 | if( modrm >= 0xc0 ) { |
| 2157 | int s,d; |
| 2158 | s=modrm & 0x7; |
| 2159 | d=(modrm >> 3) & 0x7; |
| 2160 | for (c=0;c <= 1;c++) |
| 2161 | MMX(d).d[c]=(MMX(d).i[c] > MMX(s).i[c]) ? 0xffffffff : 0; |
| 2162 | } else { |
| 2163 | MMX_REG s; |
| 2164 | int d=(modrm >> 3) & 0x7; |
| 2165 | UINT32 ea = GetEA(modrm, 0); |
| 2166 | READMMX(ea, s); |
| 2167 | for (c=0;c <= 1;c++) |
| 2168 | MMX(d).d[c]=(MMX(d).i[c] > s.i[c]) ? 0xffffffff : 0; |
| 2169 | } |
| 2170 | CYCLES(1); // TODO: correct cycle count |
| 2171 | } |
| 2172 | |
| 2173 | void i386_device::mmx_packuswb_r64_rm64() // Opcode 0f 67 |
| 2174 | { |
| 2175 | MMXPROLOG(); |
| 2176 | UINT8 modrm = FETCH(); |
| 2177 | if( modrm >= 0xc0 ) { |
| 2178 | int s,d; |
| 2179 | s=modrm & 0x7; |
| 2180 | d=(modrm >> 3) & 0x7; |
| 2181 | MMX(d).b[0]=SaturatedSignedWordToUnsignedByte(MMX(d).s[0]); |
| 2182 | MMX(d).b[1]=SaturatedSignedWordToUnsignedByte(MMX(d).s[1]); |
| 2183 | MMX(d).b[2]=SaturatedSignedWordToUnsignedByte(MMX(d).s[2]); |
| 2184 | MMX(d).b[3]=SaturatedSignedWordToUnsignedByte(MMX(d).s[3]); |
| 2185 | MMX(d).b[4]=SaturatedSignedWordToUnsignedByte(MMX(s).s[0]); |
| 2186 | MMX(d).b[5]=SaturatedSignedWordToUnsignedByte(MMX(s).s[1]); |
| 2187 | MMX(d).b[6]=SaturatedSignedWordToUnsignedByte(MMX(s).s[2]); |
| 2188 | MMX(d).b[7]=SaturatedSignedWordToUnsignedByte(MMX(s).s[3]); |
| 2189 | } else { |
| 2190 | MMX_REG s; |
| 2191 | int d=(modrm >> 3) & 0x7; |
| 2192 | UINT32 ea = GetEA(modrm, 0); |
| 2193 | READMMX(ea, s); |
| 2194 | MMX(d).b[0]=SaturatedSignedWordToUnsignedByte(MMX(d).s[0]); |
| 2195 | MMX(d).b[1]=SaturatedSignedWordToUnsignedByte(MMX(d).s[1]); |
| 2196 | MMX(d).b[2]=SaturatedSignedWordToUnsignedByte(MMX(d).s[2]); |
| 2197 | MMX(d).b[3]=SaturatedSignedWordToUnsignedByte(MMX(d).s[3]); |
| 2198 | MMX(d).b[4]=SaturatedSignedWordToUnsignedByte(s.s[0]); |
| 2199 | MMX(d).b[5]=SaturatedSignedWordToUnsignedByte(s.s[1]); |
| 2200 | MMX(d).b[6]=SaturatedSignedWordToUnsignedByte(s.s[2]); |
| 2201 | MMX(d).b[7]=SaturatedSignedWordToUnsignedByte(s.s[3]); |
| 2202 | } |
| 2203 | CYCLES(1); // TODO: correct cycle count |
| 2204 | } |
| 2205 | |
| 2206 | void i386_device::mmx_punpckhbw_r64_rm64() // Opcode 0f 68 |
| 2207 | { |
| 2208 | MMXPROLOG(); |
| 2209 | UINT8 modrm = FETCH(); |
| 2210 | if( modrm >= 0xc0 ) { |
| 2211 | int s,d; |
| 2212 | s=modrm & 0x7; |
| 2213 | d=(modrm >> 3) & 0x7; |
| 2214 | MMX(d).b[0]=MMX(d).b[4]; |
| 2215 | MMX(d).b[1]=MMX(s).b[4]; |
| 2216 | MMX(d).b[2]=MMX(d).b[5]; |
| 2217 | MMX(d).b[3]=MMX(s).b[5]; |
| 2218 | MMX(d).b[4]=MMX(d).b[6]; |
| 2219 | MMX(d).b[5]=MMX(s).b[6]; |
| 2220 | MMX(d).b[6]=MMX(d).b[7]; |
| 2221 | MMX(d).b[7]=MMX(s).b[7]; |
| 2222 | } else { |
| 2223 | MMX_REG s; |
| 2224 | int d=(modrm >> 3) & 0x7; |
| 2225 | UINT32 ea = GetEA(modrm, 0); |
| 2226 | READMMX(ea, s); |
| 2227 | MMX(d).b[0]=MMX(d).b[4]; |
| 2228 | MMX(d).b[1]=s.b[4]; |
| 2229 | MMX(d).b[2]=MMX(d).b[5]; |
| 2230 | MMX(d).b[3]=s.b[5]; |
| 2231 | MMX(d).b[4]=MMX(d).b[6]; |
| 2232 | MMX(d).b[5]=s.b[6]; |
| 2233 | MMX(d).b[6]=MMX(d).b[7]; |
| 2234 | MMX(d).b[7]=s.b[7]; |
| 2235 | } |
| 2236 | CYCLES(1); // TODO: correct cycle count |
| 2237 | } |
| 2238 | |
| 2239 | void i386_device::mmx_punpckhwd_r64_rm64() // Opcode 0f 69 |
| 2240 | { |
| 2241 | MMXPROLOG(); |
| 2242 | UINT8 modrm = FETCH(); |
| 2243 | if( modrm >= 0xc0 ) { |
| 2244 | int s,d; |
| 2245 | s=modrm & 0x7; |
| 2246 | d=(modrm >> 3) & 0x7; |
| 2247 | MMX(d).w[0]=MMX(d).w[2]; |
| 2248 | MMX(d).w[1]=MMX(s).w[2]; |
| 2249 | MMX(d).w[2]=MMX(d).w[3]; |
| 2250 | MMX(d).w[3]=MMX(s).w[3]; |
| 2251 | } else { |
| 2252 | MMX_REG s; |
| 2253 | int d=(modrm >> 3) & 0x7; |
| 2254 | UINT32 ea = GetEA(modrm, 0); |
| 2255 | READMMX(ea, s); |
| 2256 | MMX(d).w[0]=MMX(d).w[2]; |
| 2257 | MMX(d).w[1]=s.w[2]; |
| 2258 | MMX(d).w[2]=MMX(d).w[3]; |
| 2259 | MMX(d).w[3]=s.w[3]; |
| 2260 | } |
| 2261 | CYCLES(1); // TODO: correct cycle count |
| 2262 | } |
| 2263 | |
| 2264 | void i386_device::mmx_punpckhdq_r64_rm64() // Opcode 0f 6a |
| 2265 | { |
| 2266 | MMXPROLOG(); |
| 2267 | UINT8 modrm = FETCH(); |
| 2268 | if( modrm >= 0xc0 ) { |
| 2269 | int s,d; |
| 2270 | s=modrm & 0x7; |
| 2271 | d=(modrm >> 3) & 0x7; |
| 2272 | MMX(d).d[0]=MMX(d).d[1]; |
| 2273 | MMX(d).d[1]=MMX(s).d[1]; |
| 2274 | } else { |
| 2275 | MMX_REG s; |
| 2276 | int d=(modrm >> 3) & 0x7; |
| 2277 | UINT32 ea = GetEA(modrm, 0); |
| 2278 | READMMX(ea, s); |
| 2279 | MMX(d).d[0]=MMX(d).d[1]; |
| 2280 | MMX(d).d[1]=s.d[1]; |
| 2281 | } |
| 2282 | CYCLES(1); // TODO: correct cycle count |
| 2283 | } |
| 2284 | |
| 2285 | void i386_device::mmx_packssdw_r64_rm64() // Opcode 0f 6b |
| 2286 | { |
| 2287 | MMXPROLOG(); |
| 2288 | UINT8 modrm = FETCH(); |
| 2289 | if( modrm >= 0xc0 ) { |
| 2290 | int s,d; |
| 2291 | s=modrm & 0x7; |
| 2292 | d=(modrm >> 3) & 0x7; |
| 2293 | MMX(d).s[0]=SaturatedSignedDwordToSignedWord(MMX(d).i[0]); |
| 2294 | MMX(d).s[1]=SaturatedSignedDwordToSignedWord(MMX(d).i[1]); |
| 2295 | MMX(d).s[2]=SaturatedSignedDwordToSignedWord(MMX(s).i[0]); |
| 2296 | MMX(d).s[3]=SaturatedSignedDwordToSignedWord(MMX(s).i[1]); |
| 2297 | } else { |
| 2298 | MMX_REG s; |
| 2299 | int d=(modrm >> 3) & 0x7; |
| 2300 | UINT32 ea = GetEA(modrm, 0); |
| 2301 | READMMX(ea, s); |
| 2302 | MMX(d).s[0]=SaturatedSignedDwordToSignedWord(MMX(d).i[0]); |
| 2303 | MMX(d).s[1]=SaturatedSignedDwordToSignedWord(MMX(d).i[1]); |
| 2304 | MMX(d).s[2]=SaturatedSignedDwordToSignedWord(s.i[0]); |
| 2305 | MMX(d).s[3]=SaturatedSignedDwordToSignedWord(s.i[1]); |
| 2306 | } |
| 2307 | CYCLES(1); // TODO: correct cycle count |
| 2308 | } |
| 2309 | |
| 2310 | void i386_device::sse_sse_group0fae() // Opcode 0f ae |
| 2311 | { |
| 2312 | UINT8 modm = FETCH(); |
| 2313 | if( modm == 0xf8 ) { |
| 2314 | logerror("Unemulated SFENCE opcode called\n"); |
| 2315 | CYCLES(1); // sfence instruction |
| 2316 | } else if( modm == 0xf0 ) { |
| 2317 | CYCLES(1); // mfence instruction |
| 2318 | } else if( modm == 0xe8 ) { |
| 2319 | CYCLES(1); // lfence instruction |
| 2320 | } else if( modm < 0xc0 ) { |
| 2321 | UINT32 ea; |
| 2322 | switch ( (modm & 0x38) >> 3 ) |
| 2323 | { |
| 2324 | case 2: // ldmxcsr m32 |
| 2325 | ea = GetEA(modm, 0); |
| 2326 | m_mxcsr = READ32(ea); |
| 2327 | break; |
| 2328 | case 3: // stmxcsr m32 |
| 2329 | ea = GetEA(modm, 0); |
| 2330 | WRITE32(ea, m_mxcsr); |
| 2331 | break; |
| 2332 | case 7: // clflush m8 |
| 2333 | GetNonTranslatedEA(modm, NULL); |
| 2334 | break; |
| 2335 | default: |
| 2336 | report_invalid_modrm("sse_group0fae", modm); |
| 2337 | } |
| 2338 | } else { |
| 2339 | report_invalid_modrm("sse_group0fae", modm); |
| 2340 | } |
| 2341 | } |
| 2342 | |
| 2343 | void i386_device::sse_cvttps2dq_r128_rm128() // Opcode f3 0f 5b |
| 2344 | { |
| 2345 | UINT8 modrm = FETCH(); |
| 2346 | if( modrm >= 0xc0 ) { |
| 2347 | XMM((modrm >> 3) & 0x7).i[0]=(INT32)XMM(modrm & 0x7).f[0]; |
| 2348 | XMM((modrm >> 3) & 0x7).i[1]=(INT32)XMM(modrm & 0x7).f[1]; |
| 2349 | XMM((modrm >> 3) & 0x7).i[2]=(INT32)XMM(modrm & 0x7).f[2]; |
| 2350 | XMM((modrm >> 3) & 0x7).i[3]=(INT32)XMM(modrm & 0x7).f[3]; |
| 2351 | } else { |
| 2352 | XMM_REG src; |
| 2353 | UINT32 ea = GetEA(modrm, 0); |
| 2354 | READXMM(ea, src); |
| 2355 | XMM((modrm >> 3) & 0x7).i[0]=(INT32)src.f[0]; |
| 2356 | XMM((modrm >> 3) & 0x7).i[1]=(INT32)src.f[1]; |
| 2357 | XMM((modrm >> 3) & 0x7).i[2]=(INT32)src.f[2]; |
| 2358 | XMM((modrm >> 3) & 0x7).i[3]=(INT32)src.f[3]; |
| 2359 | } |
| 2360 | CYCLES(1); // TODO: correct cycle count |
| 2361 | } |
| 2362 | |
| 2363 | void i386_device::sse_cvtss2sd_r128_r128m32() // Opcode f3 0f 5a |
| 2364 | { |
| 2365 | UINT8 modrm = FETCH(); |
| 2366 | if( modrm >= 0xc0 ) { |
| 2367 | XMM((modrm >> 3) & 0x7).f64[0] = XMM(modrm & 0x7).f[0]; |
| 2368 | } else { |
| 2369 | XMM_REG s; |
| 2370 | UINT32 ea = GetEA(modrm, 0); |
| 2371 | s.d[0] = READ32(ea); |
| 2372 | XMM((modrm >> 3) & 0x7).f64[0] = s.f[0]; |
| 2373 | } |
| 2374 | CYCLES(1); // TODO: correct cycle count |
| 2375 | } |
| 2376 | |
| 2377 | void i386_device::sse_cvttss2si_r32_r128m32() // Opcode f3 0f 2c |
| 2378 | { |
| 2379 | INT32 src; |
| 2380 | UINT8 modrm = FETCH(); // get mordm byte |
| 2381 | if( modrm >= 0xc0 ) { // if bits 7-6 are 11 the source is a xmm register (low doubleword) |
| 2382 | src = (INT32)XMM(modrm & 0x7).f[0^NATIVE_ENDIAN_VALUE_LE_BE(0,1)]; |
| 2383 | } else { // otherwise is a memory address |
| 2384 | XMM_REG t; |
| 2385 | UINT32 ea = GetEA(modrm, 0); |
| 2386 | t.d[0] = READ32(ea); |
| 2387 | src = (INT32)t.f[0]; |
| 2388 | } |
| 2389 | STORE_REG32(modrm, (UINT32)src); |
| 2390 | CYCLES(1); // TODO: correct cycle count |
| 2391 | } |
| 2392 | |
| 2393 | void i386_device::sse_cvtss2si_r32_r128m32() // Opcode f3 0f 2d |
| 2394 | { |
| 2395 | INT32 src; |
| 2396 | UINT8 modrm = FETCH(); |
| 2397 | if( modrm >= 0xc0 ) { |
| 2398 | src = (INT32)XMM(modrm & 0x7).f[0]; |
| 2399 | } else { |
| 2400 | XMM_REG t; |
| 2401 | UINT32 ea = GetEA(modrm, 0); |
| 2402 | t.d[0] = READ32(ea); |
| 2403 | src = (INT32)t.f[0]; |
| 2404 | } |
| 2405 | STORE_REG32(modrm, (UINT32)src); |
| 2406 | CYCLES(1); // TODO: correct cycle count |
| 2407 | } |
| 2408 | |
| 2409 | void i386_device::sse_cvtsi2ss_r128_rm32() // Opcode f3 0f 2a |
| 2410 | { |
| 2411 | UINT8 modrm = FETCH(); |
| 2412 | if( modrm >= 0xc0 ) { |
| 2413 | XMM((modrm >> 3) & 0x7).f[0] = (INT32)LOAD_RM32(modrm); |
| 2414 | } else { |
| 2415 | UINT32 ea = GetEA(modrm, 0); |
| 2416 | XMM((modrm >> 3) & 0x7).f[0] = (INT32)READ32(ea); |
| 2417 | } |
| 2418 | CYCLES(1); // TODO: correct cycle count |
| 2419 | } |
| 2420 | |
| 2421 | void i386_device::sse_cvtpi2ps_r128_rm64() // Opcode 0f 2a |
| 2422 | { |
| 2423 | UINT8 modrm = FETCH(); |
| 2424 | MMXPROLOG(); |
| 2425 | if( modrm >= 0xc0 ) { |
| 2426 | XMM((modrm >> 3) & 0x7).f[0] = MMX(modrm & 0x7).i[0]; |
| 2427 | XMM((modrm >> 3) & 0x7).f[1] = MMX(modrm & 0x7).i[1]; |
| 2428 | } else { |
| 2429 | MMX_REG r; |
| 2430 | UINT32 ea = GetEA(modrm, 0); |
| 2431 | READMMX(ea, r); |
| 2432 | XMM((modrm >> 3) & 0x7).f[0] = r.i[0]; |
| 2433 | XMM((modrm >> 3) & 0x7).f[1] = r.i[1]; |
| 2434 | } |
| 2435 | CYCLES(1); // TODO: correct cycle count |
| 2436 | } |
| 2437 | |
| 2438 | void i386_device::sse_cvttps2pi_r64_r128m64() // Opcode 0f 2c |
| 2439 | { |
| 2440 | UINT8 modrm = FETCH(); |
| 2441 | MMXPROLOG(); |
| 2442 | if( modrm >= 0xc0 ) { |
| 2443 | MMX((modrm >> 3) & 0x7).i[0] = XMM(modrm & 0x7).f[0]; |
| 2444 | MMX((modrm >> 3) & 0x7).i[1] = XMM(modrm & 0x7).f[1]; |
| 2445 | } else { |
| 2446 | XMM_REG r; |
| 2447 | UINT32 ea = GetEA(modrm, 0); |
| 2448 | READXMM(ea, r); |
| 2449 | XMM((modrm >> 3) & 0x7).i[0] = r.f[0]; |
| 2450 | XMM((modrm >> 3) & 0x7).i[1] = r.f[1]; |
| 2451 | } |
| 2452 | CYCLES(1); // TODO: correct cycle count |
| 2453 | } |
| 2454 | |
| 2455 | void i386_device::sse_cvtps2pi_r64_r128m64() // Opcode 0f 2d |
| 2456 | { |
| 2457 | UINT8 modrm = FETCH(); |
| 2458 | MMXPROLOG(); |
| 2459 | if( modrm >= 0xc0 ) { |
| 2460 | MMX((modrm >> 3) & 0x7).i[0] = XMM(modrm & 0x7).f[0]; |
| 2461 | MMX((modrm >> 3) & 0x7).i[1] = XMM(modrm & 0x7).f[1]; |
| 2462 | } else { |
| 2463 | XMM_REG r; |
| 2464 | UINT32 ea = GetEA(modrm, 0); |
| 2465 | READXMM(ea, r); |
| 2466 | XMM((modrm >> 3) & 0x7).i[0] = r.f[0]; |
| 2467 | XMM((modrm >> 3) & 0x7).i[1] = r.f[1]; |
| 2468 | } |
| 2469 | CYCLES(1); // TODO: correct cycle count |
| 2470 | } |
| 2471 | |
| 2472 | void i386_device::sse_cvtps2pd_r128_r128m64() // Opcode 0f 5a |
| 2473 | { |
| 2474 | UINT8 modrm = FETCH(); |
| 2475 | if( modrm >= 0xc0 ) { |
| 2476 | XMM((modrm >> 3) & 0x7).f64[0] = (double)XMM(modrm & 0x7).f[0]; |
| 2477 | XMM((modrm >> 3) & 0x7).f64[1] = (double)XMM(modrm & 0x7).f[1]; |
| 2478 | } else { |
| 2479 | MMX_REG r; |
| 2480 | UINT32 ea = GetEA(modrm, 0); |
| 2481 | READMMX(ea, r); |
| 2482 | XMM((modrm >> 3) & 0x7).f64[0] = (double)r.f[0]; |
| 2483 | XMM((modrm >> 3) & 0x7).f64[1] = (double)r.f[1]; |
| 2484 | } |
| 2485 | CYCLES(1); // TODO: correct cycle count |
| 2486 | } |
| 2487 | |
| 2488 | void i386_device::sse_cvtdq2ps_r128_rm128() // Opcode 0f 5b |
| 2489 | { |
| 2490 | UINT8 modrm = FETCH(); |
| 2491 | if( modrm >= 0xc0 ) { |
| 2492 | XMM((modrm >> 3) & 0x7).f[0] = (float)XMM(modrm & 0x7).i[0]; |
| 2493 | XMM((modrm >> 3) & 0x7).f[1] = (float)XMM(modrm & 0x7).i[1]; |
| 2494 | XMM((modrm >> 3) & 0x7).f[2] = (float)XMM(modrm & 0x7).i[2]; |
| 2495 | XMM((modrm >> 3) & 0x7).f[3] = (float)XMM(modrm & 0x7).i[3]; |
| 2496 | } else { |
| 2497 | XMM_REG r; |
| 2498 | UINT32 ea = GetEA(modrm, 0); |
| 2499 | READXMM(ea, r); |
| 2500 | XMM((modrm >> 3) & 0x7).f[0] = (float)r.i[0]; |
| 2501 | XMM((modrm >> 3) & 0x7).f[1] = (float)r.i[1]; |
| 2502 | XMM((modrm >> 3) & 0x7).f[2] = (float)r.i[2]; |
| 2503 | XMM((modrm >> 3) & 0x7).f[3] = (float)r.i[3]; |
| 2504 | } |
| 2505 | CYCLES(1); // TODO: correct cycle count |
| 2506 | } |
| 2507 | |
| 2508 | void i386_device::sse_cvtdq2pd_r128_r128m64() // Opcode f3 0f e6 |
| 2509 | { |
| 2510 | UINT8 modrm = FETCH(); |
| 2511 | if( modrm >= 0xc0 ) { |
| 2512 | XMM((modrm >> 3) & 0x7).f64[0] = (double)XMM(modrm & 0x7).i[0]; |
| 2513 | XMM((modrm >> 3) & 0x7).f64[1] = (double)XMM(modrm & 0x7).i[1]; |
| 2514 | } else { |
| 2515 | MMX_REG s; |
| 2516 | UINT32 ea = GetEA(modrm, 0); |
| 2517 | READMMX(ea, s); |
| 2518 | XMM((modrm >> 3) & 0x7).f64[0] = (double)s.i[0]; |
| 2519 | XMM((modrm >> 3) & 0x7).f64[1] = (double)s.i[1]; |
| 2520 | } |
| 2521 | CYCLES(1); // TODO: correct cycle count |
| 2522 | } |
| 2523 | |
| 2524 | void i386_device::sse_movss_r128_rm128() // Opcode f3 0f 10 |
| 2525 | { |
| 2526 | UINT8 modrm = FETCH(); |
| 2527 | if( modrm >= 0xc0 ) { |
| 2528 | XMM((modrm >> 3) & 0x7).d[0] = XMM(modrm & 0x7).d[0]; |
| 2529 | } else { |
| 2530 | UINT32 ea = GetEA(modrm, 0); |
| 2531 | XMM((modrm >> 3) & 0x7).d[0] = READ32(ea); |
| 2532 | } |
| 2533 | CYCLES(1); // TODO: correct cycle count |
| 2534 | } |
| 2535 | |
| 2536 | void i386_device::sse_movss_rm128_r128() // Opcode f3 0f 11 |
| 2537 | { |
| 2538 | UINT8 modrm = FETCH(); |
| 2539 | if( modrm >= 0xc0 ) { |
| 2540 | XMM(modrm & 0x7).d[0] = XMM((modrm >> 3) & 0x7).d[0]; |
| 2541 | } else { |
| 2542 | UINT32 ea = GetEA(modrm, 0); |
| 2543 | WRITE32(ea, XMM((modrm >> 3) & 0x7).d[0]); |
| 2544 | } |
| 2545 | CYCLES(1); // TODO: correct cycle count |
| 2546 | } |
| 2547 | |
| 2548 | void i386_device::sse_movsldup_r128_rm128() // Opcode f3 0f 12 |
| 2549 | { |
| 2550 | UINT8 modrm = FETCH(); |
| 2551 | if( modrm >= 0xc0 ) { |
| 2552 | XMM((modrm >> 3) & 0x7).d[0] = XMM(modrm & 0x7).d[0]; |
| 2553 | XMM((modrm >> 3) & 0x7).d[1] = XMM(modrm & 0x7).d[0]; |
| 2554 | XMM((modrm >> 3) & 0x7).d[2] = XMM(modrm & 0x7).d[2]; |
| 2555 | XMM((modrm >> 3) & 0x7).d[3] = XMM(modrm & 0x7).d[2]; |
| 2556 | } else { |
| 2557 | XMM_REG src; |
| 2558 | UINT32 ea = GetEA(modrm, 0); |
| 2559 | READXMM(ea, src); |
| 2560 | XMM((modrm >> 3) & 0x7).d[0] = src.d[0]; |
| 2561 | XMM((modrm >> 3) & 0x7).d[1] = src.d[0]; |
| 2562 | XMM((modrm >> 3) & 0x7).d[2] = src.d[2]; |
| 2563 | XMM((modrm >> 3) & 0x7).d[3] = src.d[2]; |
| 2564 | } |
| 2565 | CYCLES(1); // TODO: correct cycle count |
| 2566 | } |
| 2567 | |
| 2568 | void i386_device::sse_movshdup_r128_rm128() // Opcode f3 0f 16 |
| 2569 | { |
| 2570 | UINT8 modrm = FETCH(); |
| 2571 | if( modrm >= 0xc0 ) { |
| 2572 | XMM((modrm >> 3) & 0x7).d[0] = XMM(modrm & 0x7).d[1]; |
| 2573 | XMM((modrm >> 3) & 0x7).d[1] = XMM(modrm & 0x7).d[1]; |
| 2574 | XMM((modrm >> 3) & 0x7).d[2] = XMM(modrm & 0x7).d[3]; |
| 2575 | XMM((modrm >> 3) & 0x7).d[3] = XMM(modrm & 0x7).d[3]; |
| 2576 | } else { |
| 2577 | XMM_REG src; |
| 2578 | UINT32 ea = GetEA(modrm, 0); |
| 2579 | READXMM(ea, src); |
| 2580 | XMM((modrm >> 3) & 0x7).d[0] = src.d[1]; |
| 2581 | XMM((modrm >> 3) & 0x7).d[1] = src.d[1]; |
| 2582 | XMM((modrm >> 3) & 0x7).d[2] = src.d[3]; |
| 2583 | XMM((modrm >> 3) & 0x7).d[3] = src.d[3]; |
| 2584 | } |
| 2585 | CYCLES(1); // TODO: correct cycle count |
| 2586 | } |
| 2587 | |
| 2588 | void i386_device::sse_movaps_r128_rm128() // Opcode 0f 28 |
| 2589 | { |
| 2590 | UINT8 modrm = FETCH(); |
| 2591 | if( modrm >= 0xc0 ) { |
| 2592 | XMM((modrm >> 3) & 0x7) = XMM(modrm & 0x7); |
| 2593 | } else { |
| 2594 | UINT32 ea = GetEA(modrm, 0); |
| 2595 | READXMM(ea, XMM((modrm >> 3) & 0x7)); |
| 2596 | } |
| 2597 | CYCLES(1); // TODO: correct cycle count |
| 2598 | } |
| 2599 | |
| 2600 | void i386_device::sse_movaps_rm128_r128() // Opcode 0f 29 |
| 2601 | { |
| 2602 | UINT8 modrm = FETCH(); |
| 2603 | if( modrm >= 0xc0 ) { |
| 2604 | XMM(modrm & 0x7) = XMM((modrm >> 3) & 0x7); |
| 2605 | } else { |
| 2606 | UINT32 ea = GetEA(modrm, 0); |
| 2607 | WRITEXMM(ea, XMM((modrm >> 3) & 0x7)); |
| 2608 | } |
| 2609 | CYCLES(1); // TODO: correct cycle count |
| 2610 | } |
| 2611 | |
| 2612 | void i386_device::sse_movups_r128_rm128() // Opcode 0f 10 |
| 2613 | { |
| 2614 | UINT8 modrm = FETCH(); |
| 2615 | if( modrm >= 0xc0 ) { |
| 2616 | XMM((modrm >> 3) & 0x7) = XMM(modrm & 0x7); |
| 2617 | } else { |
| 2618 | UINT32 ea = GetEA(modrm, 0); |
| 2619 | READXMM(ea, XMM((modrm >> 3) & 0x7)); // address does not need to be 16-byte aligned |
| 2620 | } |
| 2621 | CYCLES(1); // TODO: correct cycle count |
| 2622 | } |
| 2623 | |
| 2624 | void i386_device::sse_movups_rm128_r128() // Opcode 0f 11 |
| 2625 | { |
| 2626 | UINT8 modrm = FETCH(); |
| 2627 | if( modrm >= 0xc0 ) { |
| 2628 | XMM(modrm & 0x7) = XMM((modrm >> 3) & 0x7); |
| 2629 | } else { |
| 2630 | UINT32 ea = GetEA(modrm, 0); |
| 2631 | WRITEXMM(ea, XMM((modrm >> 3) & 0x7)); // address does not need to be 16-byte aligned |
| 2632 | } |
| 2633 | CYCLES(1); // TODO: correct cycle count |
| 2634 | } |
| 2635 | |
| 2636 | void i386_device::sse_movlps_r128_m64() // Opcode 0f 12 |
| 2637 | { |
| 2638 | UINT8 modrm = FETCH(); |
| 2639 | if( modrm >= 0xc0 ) { |
| 2640 | // unsupported by cpu |
| 2641 | CYCLES(1); // TODO: correct cycle count |
| 2642 | } else { |
| 2643 | UINT32 ea = GetEA(modrm, 0); |
| 2644 | READXMM_LO64(ea, XMM((modrm >> 3) & 0x7)); |
| 2645 | CYCLES(1); // TODO: correct cycle count |
| 2646 | } |
| 2647 | } |
| 2648 | |
| 2649 | void i386_device::sse_movlps_m64_r128() // Opcode 0f 13 |
| 2650 | { |
| 2651 | UINT8 modrm = FETCH(); |
| 2652 | if( modrm >= 0xc0 ) { |
| 2653 | // unsupported by cpu |
| 2654 | CYCLES(1); // TODO: correct cycle count |
| 2655 | } else { |
| 2656 | UINT32 ea = GetEA(modrm, 0); |
| 2657 | WRITEXMM_LO64(ea, XMM((modrm >> 3) & 0x7)); |
| 2658 | CYCLES(1); // TODO: correct cycle count |
| 2659 | } |
| 2660 | } |
| 2661 | |
| 2662 | void i386_device::sse_movhps_r128_m64() // Opcode 0f 16 |
| 2663 | { |
| 2664 | UINT8 modrm = FETCH(); |
| 2665 | if( modrm >= 0xc0 ) { |
| 2666 | // unsupported by cpu |
| 2667 | CYCLES(1); // TODO: correct cycle count |
| 2668 | } else { |
| 2669 | UINT32 ea = GetEA(modrm, 0); |
| 2670 | READXMM_HI64(ea, XMM((modrm >> 3) & 0x7)); |
| 2671 | CYCLES(1); // TODO: correct cycle count |
| 2672 | } |
| 2673 | } |
| 2674 | |
| 2675 | void i386_device::sse_movhps_m64_r128() // Opcode 0f 17 |
| 2676 | { |
| 2677 | UINT8 modrm = FETCH(); |
| 2678 | if( modrm >= 0xc0 ) { |
| 2679 | // unsupported by cpu |
| 2680 | CYCLES(1); // TODO: correct cycle count |
| 2681 | } else { |
| 2682 | UINT32 ea = GetEA(modrm, 0); |
| 2683 | WRITEXMM_HI64(ea, XMM((modrm >> 3) & 0x7)); |
| 2684 | CYCLES(1); // TODO: correct cycle count |
| 2685 | } |
| 2686 | } |
| 2687 | |
| 2688 | void i386_device::sse_movntps_m128_r128() // Opcode 0f 2b |
| 2689 | { |
| 2690 | UINT8 modrm = FETCH(); |
| 2691 | if( modrm >= 0xc0 ) { |
| 2692 | // unsupported by cpu |
| 2693 | CYCLES(1); // TODO: correct cycle count |
| 2694 | } else { |
| 2695 | // since cache is not implemented |
| 2696 | UINT32 ea = GetEA(modrm, 0); |
| 2697 | WRITEXMM(ea, XMM((modrm >> 3) & 0x7)); |
| 2698 | CYCLES(1); // TODO: correct cycle count |
| 2699 | } |
| 2700 | } |
| 2701 | |
| 2702 | void i386_device::sse_movmskps_r16_r128() // Opcode 0f 50 |
| 2703 | { |
| 2704 | UINT8 modrm = FETCH(); |
| 2705 | if( modrm >= 0xc0 ) { |
| 2706 | int b; |
| 2707 | b=(XMM(modrm & 0x7).d[0] >> 31) & 1; |
| 2708 | b=b | ((XMM(modrm & 0x7).d[1] >> 30) & 2); |
| 2709 | b=b | ((XMM(modrm & 0x7).d[2] >> 29) & 4); |
| 2710 | b=b | ((XMM(modrm & 0x7).d[3] >> 28) & 8); |
| 2711 | STORE_REG16(modrm, b); |
| 2712 | } |
| 2713 | CYCLES(1); // TODO: correct cycle count |
| 2714 | } |
| 2715 | |
| 2716 | void i386_device::sse_movmskps_r32_r128() // Opcode 0f 50 |
| 2717 | { |
| 2718 | UINT8 modrm = FETCH(); |
| 2719 | if( modrm >= 0xc0 ) { |
| 2720 | int b; |
| 2721 | b=(XMM(modrm & 0x7).d[0] >> 31) & 1; |
| 2722 | b=b | ((XMM(modrm & 0x7).d[1] >> 30) & 2); |
| 2723 | b=b | ((XMM(modrm & 0x7).d[2] >> 29) & 4); |
| 2724 | b=b | ((XMM(modrm & 0x7).d[3] >> 28) & 8); |
| 2725 | STORE_REG32(modrm, b); |
| 2726 | } |
| 2727 | CYCLES(1); // TODO: correct cycle count |
| 2728 | } |
| 2729 | |
| 2730 | void i386_device::sse_movq2dq_r128_r64() // Opcode f3 0f d6 |
| 2731 | { |
| 2732 | MMXPROLOG(); |
| 2733 | UINT8 modrm = FETCH(); |
| 2734 | if( modrm >= 0xc0 ) { |
| 2735 | XMM((modrm >> 3) & 0x7).q[0] = MMX(modrm & 7).q; |
| 2736 | XMM((modrm >> 3) & 0x7).q[1] = 0; |
| 2737 | } |
| 2738 | CYCLES(1); // TODO: correct cycle count |
| 2739 | } |
| 2740 | |
| 2741 | void i386_device::sse_movdqu_r128_rm128() // Opcode f3 0f 6f |
| 2742 | { |
| 2743 | MMXPROLOG(); |
| 2744 | UINT8 modrm = FETCH(); |
| 2745 | if( modrm >= 0xc0 ) { |
| 2746 | XMM((modrm >> 3) & 0x7).q[0] = XMM(modrm & 0x7).q[0]; |
| 2747 | XMM((modrm >> 3) & 0x7).q[1] = XMM(modrm & 0x7).q[1]; |
| 2748 | } else { |
| 2749 | UINT32 ea = GetEA(modrm, 0); |
| 2750 | READXMM(ea, XMM((modrm >> 3) & 0x7)); |
| 2751 | } |
| 2752 | CYCLES(1); // TODO: correct cycle count |
| 2753 | } |
| 2754 | |
| 2755 | void i386_device::sse_movdqu_rm128_r128() // Opcode f3 0f 7f |
| 2756 | { |
| 2757 | MMXPROLOG(); |
| 2758 | UINT8 modrm = FETCH(); |
| 2759 | if( modrm >= 0xc0 ) { |
| 2760 | XMM(modrm & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0]; |
| 2761 | XMM(modrm & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1]; |
| 2762 | } else { |
| 2763 | UINT32 ea = GetEA(modrm, 0); |
| 2764 | WRITEXMM(ea, XMM((modrm >> 3) & 0x7)); |
| 2765 | } |
| 2766 | CYCLES(1); // TODO: correct cycle count |
| 2767 | } |
| 2768 | |
| 2769 | void i386_device::sse_movq_r128_r128m64() // Opcode f3 0f 7e |
| 2770 | { |
| 2771 | MMXPROLOG(); |
| 2772 | UINT8 modrm = FETCH(); |
| 2773 | if( modrm >= 0xc0 ) { |
| 2774 | XMM((modrm >> 3) & 0x7).q[0] = XMM(modrm & 0x7).q[0]; |
| 2775 | XMM((modrm >> 3) & 0x7).q[1] = 0; |
| 2776 | } else { |
| 2777 | UINT32 ea = GetEA(modrm, 0); |
| 2778 | XMM((modrm >> 3) & 0x7).q[0] = READ64(ea); |
| 2779 | XMM((modrm >> 3) & 0x7).q[1] = 0; |
| 2780 | } |
| 2781 | CYCLES(1); // TODO: correct cycle count |
| 2782 | } |
| 2783 | |
| 2784 | void i386_device::sse_pmovmskb_r16_r64() // Opcode 0f d7 |
| 2785 | { |
| 2786 | //MMXPROLOG(); |
| 2787 | UINT8 modrm = FETCH(); |
| 2788 | if( modrm >= 0xc0 ) { |
| 2789 | int b; |
| 2790 | b=(MMX(modrm & 0x7).b[0] >> 7) & 1; |
| 2791 | b=b | ((MMX(modrm & 0x7).b[1] >> 6) & 2); |
| 2792 | b=b | ((MMX(modrm & 0x7).b[2] >> 5) & 4); |
| 2793 | b=b | ((MMX(modrm & 0x7).b[3] >> 4) & 8); |
| 2794 | b=b | ((MMX(modrm & 0x7).b[4] >> 3) & 16); |
| 2795 | b=b | ((MMX(modrm & 0x7).b[5] >> 2) & 32); |
| 2796 | b=b | ((MMX(modrm & 0x7).b[6] >> 1) & 64); |
| 2797 | b=b | ((MMX(modrm & 0x7).b[7] >> 0) & 128); |
| 2798 | STORE_REG16(modrm, b); |
| 2799 | } |
| 2800 | CYCLES(1); // TODO: correct cycle count |
| 2801 | } |
| 2802 | |
| 2803 | void i386_device::sse_pmovmskb_r32_r64() // Opcode 0f d7 |
| 2804 | { |
| 2805 | //MMXPROLOG(); |
| 2806 | UINT8 modrm = FETCH(); |
| 2807 | if( modrm >= 0xc0 ) { |
| 2808 | int b; |
| 2809 | b=(MMX(modrm & 0x7).b[0] >> 7) & 1; |
| 2810 | b=b | ((MMX(modrm & 0x7).b[1] >> 6) & 2); |
| 2811 | b=b | ((MMX(modrm & 0x7).b[2] >> 5) & 4); |
| 2812 | b=b | ((MMX(modrm & 0x7).b[3] >> 4) & 8); |
| 2813 | b=b | ((MMX(modrm & 0x7).b[4] >> 3) & 16); |
| 2814 | b=b | ((MMX(modrm & 0x7).b[5] >> 2) & 32); |
| 2815 | b=b | ((MMX(modrm & 0x7).b[6] >> 1) & 64); |
| 2816 | b=b | ((MMX(modrm & 0x7).b[7] >> 0) & 128); |
| 2817 | STORE_REG32(modrm, b); |
| 2818 | } |
| 2819 | CYCLES(1); // TODO: correct cycle count |
| 2820 | } |
| 2821 | |
| 2822 | void i386_device::sse_xorps() // Opcode 0f 57 |
| 2823 | { |
| 2824 | UINT8 modrm = FETCH(); |
| 2825 | if( modrm >= 0xc0 ) { |
| 2826 | XMM((modrm >> 3) & 0x7).d[0] = XMM((modrm >> 3) & 0x7).d[0] ^ XMM(modrm & 0x7).d[0]; |
| 2827 | XMM((modrm >> 3) & 0x7).d[1] = XMM((modrm >> 3) & 0x7).d[1] ^ XMM(modrm & 0x7).d[1]; |
| 2828 | XMM((modrm >> 3) & 0x7).d[2] = XMM((modrm >> 3) & 0x7).d[2] ^ XMM(modrm & 0x7).d[2]; |
| 2829 | XMM((modrm >> 3) & 0x7).d[3] = XMM((modrm >> 3) & 0x7).d[3] ^ XMM(modrm & 0x7).d[3]; |
| 2830 | } else { |
| 2831 | XMM_REG src; |
| 2832 | UINT32 ea = GetEA(modrm, 0); |
| 2833 | READXMM(ea, src); |
| 2834 | XMM((modrm >> 3) & 0x7).d[0] = XMM((modrm >> 3) & 0x7).d[0] ^ src.d[0]; |
| 2835 | XMM((modrm >> 3) & 0x7).d[1] = XMM((modrm >> 3) & 0x7).d[1] ^ src.d[1]; |
| 2836 | XMM((modrm >> 3) & 0x7).d[2] = XMM((modrm >> 3) & 0x7).d[2] ^ src.d[2]; |
| 2837 | XMM((modrm >> 3) & 0x7).d[3] = XMM((modrm >> 3) & 0x7).d[3] ^ src.d[3]; |
| 2838 | } |
| 2839 | CYCLES(1); // TODO: correct cycle count |
| 2840 | } |
| 2841 | |
| 2842 | void i386_device::sse_addps() // Opcode 0f 58 |
| 2843 | { |
| 2844 | UINT8 modrm = FETCH(); |
| 2845 | if( modrm >= 0xc0 ) { |
| 2846 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + XMM(modrm & 0x7).f[0]; |
| 2847 | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] + XMM(modrm & 0x7).f[1]; |
| 2848 | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] + XMM(modrm & 0x7).f[2]; |
| 2849 | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] + XMM(modrm & 0x7).f[3]; |
| 2850 | } else { |
| 2851 | XMM_REG src; |
| 2852 | UINT32 ea = GetEA(modrm, 0); |
| 2853 | READXMM(ea, src); |
| 2854 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + src.f[0]; |
| 2855 | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] + src.f[1]; |
| 2856 | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] + src.f[2]; |
| 2857 | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] + src.f[3]; |
| 2858 | } |
| 2859 | CYCLES(1); // TODO: correct cycle count |
| 2860 | } |
| 2861 | |
| 2862 | void i386_device::sse_sqrtps_r128_rm128() // Opcode 0f 51 |
| 2863 | { |
| 2864 | UINT8 modrm = FETCH(); |
| 2865 | if( modrm >= 0xc0 ) { |
| 2866 | XMM((modrm >> 3) & 0x7).f[0] = sqrt(XMM(modrm & 0x7).f[0]); |
| 2867 | XMM((modrm >> 3) & 0x7).f[1] = sqrt(XMM(modrm & 0x7).f[1]); |
| 2868 | XMM((modrm >> 3) & 0x7).f[2] = sqrt(XMM(modrm & 0x7).f[2]); |
| 2869 | XMM((modrm >> 3) & 0x7).f[3] = sqrt(XMM(modrm & 0x7).f[3]); |
| 2870 | } else { |
| 2871 | XMM_REG src; |
| 2872 | UINT32 ea = GetEA(modrm, 0); |
| 2873 | READXMM(ea, src); |
| 2874 | XMM((modrm >> 3) & 0x7).f[0] = sqrt(src.f[0]); |
| 2875 | XMM((modrm >> 3) & 0x7).f[1] = sqrt(src.f[1]); |
| 2876 | XMM((modrm >> 3) & 0x7).f[2] = sqrt(src.f[2]); |
| 2877 | XMM((modrm >> 3) & 0x7).f[3] = sqrt(src.f[3]); |
| 2878 | } |
| 2879 | CYCLES(1); // TODO: correct cycle count |
| 2880 | } |
| 2881 | |
| 2882 | void i386_device::sse_rsqrtps_r128_rm128() // Opcode 0f 52 |
| 2883 | { |
| 2884 | UINT8 modrm = FETCH(); |
| 2885 | if( modrm >= 0xc0 ) { |
| 2886 | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / sqrt(XMM(modrm & 0x7).f[0]); |
| 2887 | XMM((modrm >> 3) & 0x7).f[1] = 1.0 / sqrt(XMM(modrm & 0x7).f[1]); |
| 2888 | XMM((modrm >> 3) & 0x7).f[2] = 1.0 / sqrt(XMM(modrm & 0x7).f[2]); |
| 2889 | XMM((modrm >> 3) & 0x7).f[3] = 1.0 / sqrt(XMM(modrm & 0x7).f[3]); |
| 2890 | } else { |
| 2891 | XMM_REG src; |
| 2892 | UINT32 ea = GetEA(modrm, 0); |
| 2893 | READXMM(ea, src); |
| 2894 | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / sqrt(src.f[0]); |
| 2895 | XMM((modrm >> 3) & 0x7).f[1] = 1.0 / sqrt(src.f[1]); |
| 2896 | XMM((modrm >> 3) & 0x7).f[2] = 1.0 / sqrt(src.f[2]); |
| 2897 | XMM((modrm >> 3) & 0x7).f[3] = 1.0 / sqrt(src.f[3]); |
| 2898 | } |
| 2899 | CYCLES(1); // TODO: correct cycle count |
| 2900 | } |
| 2901 | |
| 2902 | void i386_device::sse_rcpps_r128_rm128() // Opcode 0f 53 |
| 2903 | { |
| 2904 | UINT8 modrm = FETCH(); |
| 2905 | if( modrm >= 0xc0 ) { |
| 2906 | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / XMM(modrm & 0x7).f[0]; |
| 2907 | XMM((modrm >> 3) & 0x7).f[1] = 1.0 / XMM(modrm & 0x7).f[1]; |
| 2908 | XMM((modrm >> 3) & 0x7).f[2] = 1.0 / XMM(modrm & 0x7).f[2]; |
| 2909 | XMM((modrm >> 3) & 0x7).f[3] = 1.0 / XMM(modrm & 0x7).f[3]; |
| 2910 | } else { |
| 2911 | XMM_REG src; |
| 2912 | UINT32 ea = GetEA(modrm, 0); |
| 2913 | READXMM(ea, src); |
| 2914 | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / src.f[0]; |
| 2915 | XMM((modrm >> 3) & 0x7).f[1] = 1.0 / src.f[1]; |
| 2916 | XMM((modrm >> 3) & 0x7).f[2] = 1.0 / src.f[2]; |
| 2917 | XMM((modrm >> 3) & 0x7).f[3] = 1.0 / src.f[3]; |
| 2918 | } |
| 2919 | CYCLES(1); // TODO: correct cycle count |
| 2920 | } |
| 2921 | |
| 2922 | void i386_device::sse_andps_r128_rm128() // Opcode 0f 54 |
| 2923 | { |
| 2924 | UINT8 modrm = FETCH(); |
| 2925 | if( modrm >= 0xc0 ) { |
| 2926 | XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] & XMM(modrm & 0x7).q[0]; |
| 2927 | XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] & XMM(modrm & 0x7).q[1]; |
| 2928 | } else { |
| 2929 | XMM_REG src; |
| 2930 | UINT32 ea = GetEA(modrm, 0); |
| 2931 | READXMM(ea, src); |
| 2932 | XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] & src.q[0]; |
| 2933 | XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] & src.q[1]; |
| 2934 | } |
| 2935 | CYCLES(1); // TODO: correct cycle count |
| 2936 | } |
| 2937 | |
| 2938 | void i386_device::sse_andnps_r128_rm128() // Opcode 0f 55 |
| 2939 | { |
| 2940 | UINT8 modrm = FETCH(); |
| 2941 | if( modrm >= 0xc0 ) { |
| 2942 | XMM((modrm >> 3) & 0x7).q[0] = ~(XMM((modrm >> 3) & 0x7).q[0]) & XMM(modrm & 0x7).q[0]; |
| 2943 | XMM((modrm >> 3) & 0x7).q[1] = ~(XMM((modrm >> 3) & 0x7).q[1]) & XMM(modrm & 0x7).q[1]; |
| 2944 | } else { |
| 2945 | XMM_REG src; |
| 2946 | UINT32 ea = GetEA(modrm, 0); |
| 2947 | READXMM(ea, src); |
| 2948 | XMM((modrm >> 3) & 0x7).q[0] = ~(XMM((modrm >> 3) & 0x7).q[0]) & src.q[0]; |
| 2949 | XMM((modrm >> 3) & 0x7).q[1] = ~(XMM((modrm >> 3) & 0x7).q[1]) & src.q[1]; |
| 2950 | } |
| 2951 | CYCLES(1); // TODO: correct cycle count |
| 2952 | } |
| 2953 | |
| 2954 | void i386_device::sse_orps_r128_rm128() // Opcode 0f 56 |
| 2955 | { |
| 2956 | UINT8 modrm = FETCH(); |
| 2957 | if( modrm >= 0xc0 ) { |
| 2958 | XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] | XMM(modrm & 0x7).q[0]; |
| 2959 | XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] | XMM(modrm & 0x7).q[1]; |
| 2960 | } else { |
| 2961 | XMM_REG src; |
| 2962 | UINT32 ea = GetEA(modrm, 0); |
| 2963 | READXMM(ea, src); |
| 2964 | XMM((modrm >> 3) & 0x7).q[0] = XMM((modrm >> 3) & 0x7).q[0] | src.q[0]; |
| 2965 | XMM((modrm >> 3) & 0x7).q[1] = XMM((modrm >> 3) & 0x7).q[1] | src.q[1]; |
| 2966 | } |
| 2967 | CYCLES(1); // TODO: correct cycle count |
| 2968 | } |
| 2969 | |
| 2970 | void i386_device::sse_mulps() // Opcode 0f 59 ???? |
| 2971 | { |
| 2972 | UINT8 modrm = FETCH(); |
| 2973 | if( modrm >= 0xc0 ) { |
| 2974 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * XMM(modrm & 0x7).f[0]; |
| 2975 | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] * XMM(modrm & 0x7).f[1]; |
| 2976 | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] * XMM(modrm & 0x7).f[2]; |
| 2977 | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] * XMM(modrm & 0x7).f[3]; |
| 2978 | } else { |
| 2979 | XMM_REG src; |
| 2980 | UINT32 ea = GetEA(modrm, 0); |
| 2981 | READXMM(ea, src); |
| 2982 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * src.f[0]; |
| 2983 | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] * src.f[1]; |
| 2984 | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] * src.f[2]; |
| 2985 | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] * src.f[3]; |
| 2986 | } |
| 2987 | CYCLES(1); // TODO: correct cycle count |
| 2988 | } |
| 2989 | |
| 2990 | void i386_device::sse_subps() // Opcode 0f 5c |
| 2991 | { |
| 2992 | UINT8 modrm = FETCH(); |
| 2993 | if( modrm >= 0xc0 ) { |
| 2994 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] - XMM(modrm & 0x7).f[0]; |
| 2995 | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] - XMM(modrm & 0x7).f[1]; |
| 2996 | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] - XMM(modrm & 0x7).f[2]; |
| 2997 | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] - XMM(modrm & 0x7).f[3]; |
| 2998 | } else { |
| 2999 | XMM_REG src; |
| 3000 | UINT32 ea = GetEA(modrm, 0); |
| 3001 | READXMM(ea, src); |
| 3002 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] - src.f[0]; |
| 3003 | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] - src.f[1]; |
| 3004 | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] - src.f[2]; |
| 3005 | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] - src.f[3]; |
| 3006 | } |
| 3007 | CYCLES(1); // TODO: correct cycle count |
| 3008 | } |
| 3009 | |
| 3010 | INLINE float sse_min_single(float src1, float src2) |
| 3011 | { |
| 3012 | /*if ((src1 == 0) && (src2 == 0)) |
| 3013 | return src2; |
| 3014 | if (src1 = SNaN) |
| 3015 | return src2; |
| 3016 | if (src2 = SNaN) |
| 3017 | return src2;*/ |
| 3018 | if (src1 < src2) |
| 3019 | return src1; |
| 3020 | return src2; |
| 3021 | } |
| 3022 | |
| 3023 | void i386_device::sse_minps() // Opcode 0f 5d |
| 3024 | { |
| 3025 | UINT8 modrm = FETCH(); |
| 3026 | if( modrm >= 0xc0 ) { |
| 3027 | XMM((modrm >> 3) & 0x7).f[0] = sse_min_single(XMM((modrm >> 3) & 0x7).f[0], XMM(modrm & 0x7).f[0]); |
| 3028 | XMM((modrm >> 3) & 0x7).f[1] = sse_min_single(XMM((modrm >> 3) & 0x7).f[1], XMM(modrm & 0x7).f[1]); |
| 3029 | XMM((modrm >> 3) & 0x7).f[2] = sse_min_single(XMM((modrm >> 3) & 0x7).f[2], XMM(modrm & 0x7).f[2]); |
| 3030 | XMM((modrm >> 3) & 0x7).f[3] = sse_min_single(XMM((modrm >> 3) & 0x7).f[3], XMM(modrm & 0x7).f[3]); |
| 3031 | } else { |
| 3032 | XMM_REG src; |
| 3033 | UINT32 ea = GetEA(modrm, 0); |
| 3034 | READXMM(ea, src); |
| 3035 | XMM((modrm >> 3) & 0x7).f[0] = sse_min_single(XMM((modrm >> 3) & 0x7).f[0], src.f[0]); |
| 3036 | XMM((modrm >> 3) & 0x7).f[1] = sse_min_single(XMM((modrm >> 3) & 0x7).f[1], src.f[1]); |
| 3037 | XMM((modrm >> 3) & 0x7).f[2] = sse_min_single(XMM((modrm >> 3) & 0x7).f[2], src.f[2]); |
| 3038 | XMM((modrm >> 3) & 0x7).f[3] = sse_min_single(XMM((modrm >> 3) & 0x7).f[3], src.f[3]); |
| 3039 | } |
| 3040 | CYCLES(1); // TODO: correct cycle count |
| 3041 | } |
| 3042 | |
| 3043 | void i386_device::sse_divps() // Opcode 0f 5e |
| 3044 | { |
| 3045 | UINT8 modrm = FETCH(); |
| 3046 | if( modrm >= 0xc0 ) { |
| 3047 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] / XMM(modrm & 0x7).f[0]; |
| 3048 | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] / XMM(modrm & 0x7).f[1]; |
| 3049 | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] / XMM(modrm & 0x7).f[2]; |
| 3050 | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] / XMM(modrm & 0x7).f[3]; |
| 3051 | } else { |
| 3052 | XMM_REG src; |
| 3053 | UINT32 ea = GetEA(modrm, 0); |
| 3054 | READXMM(ea, src); |
| 3055 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] / src.f[0]; |
| 3056 | XMM((modrm >> 3) & 0x7).f[1] = XMM((modrm >> 3) & 0x7).f[1] / src.f[1]; |
| 3057 | XMM((modrm >> 3) & 0x7).f[2] = XMM((modrm >> 3) & 0x7).f[2] / src.f[2]; |
| 3058 | XMM((modrm >> 3) & 0x7).f[3] = XMM((modrm >> 3) & 0x7).f[3] / src.f[3]; |
| 3059 | } |
| 3060 | CYCLES(1); // TODO: correct cycle count |
| 3061 | } |
| 3062 | |
| 3063 | INLINE float sse_max_single(float src1, float src2) |
| 3064 | { |
| 3065 | /*if ((src1 == 0) && (src2 == 0)) |
| 3066 | return src2; |
| 3067 | if (src1 = SNaN) |
| 3068 | return src2; |
| 3069 | if (src2 = SNaN) |
| 3070 | return src2;*/ |
| 3071 | if (src1 > src2) |
| 3072 | return src1; |
| 3073 | return src2; |
| 3074 | } |
| 3075 | |
| 3076 | void i386_device::sse_maxps() // Opcode 0f 5f |
| 3077 | { |
| 3078 | UINT8 modrm = FETCH(); |
| 3079 | if( modrm >= 0xc0 ) { |
| 3080 | XMM((modrm >> 3) & 0x7).f[0] = sse_max_single(XMM((modrm >> 3) & 0x7).f[0], XMM(modrm & 0x7).f[0]); |
| 3081 | XMM((modrm >> 3) & 0x7).f[1] = sse_max_single(XMM((modrm >> 3) & 0x7).f[1], XMM(modrm & 0x7).f[1]); |
| 3082 | XMM((modrm >> 3) & 0x7).f[2] = sse_max_single(XMM((modrm >> 3) & 0x7).f[2], XMM(modrm & 0x7).f[2]); |
| 3083 | XMM((modrm >> 3) & 0x7).f[3] = sse_max_single(XMM((modrm >> 3) & 0x7).f[3], XMM(modrm & 0x7).f[3]); |
| 3084 | } else { |
| 3085 | XMM_REG src; |
| 3086 | UINT32 ea = GetEA(modrm, 0); |
| 3087 | READXMM(ea, src); |
| 3088 | XMM((modrm >> 3) & 0x7).f[0] = sse_max_single(XMM((modrm >> 3) & 0x7).f[0], src.f[0]); |
| 3089 | XMM((modrm >> 3) & 0x7).f[1] = sse_max_single(XMM((modrm >> 3) & 0x7).f[1], src.f[1]); |
| 3090 | XMM((modrm >> 3) & 0x7).f[2] = sse_max_single(XMM((modrm >> 3) & 0x7).f[2], src.f[2]); |
| 3091 | XMM((modrm >> 3) & 0x7).f[3] = sse_max_single(XMM((modrm >> 3) & 0x7).f[3], src.f[3]); |
| 3092 | } |
| 3093 | CYCLES(1); // TODO: correct cycle count |
| 3094 | } |
| 3095 | |
| 3096 | void i386_device::sse_maxss_r128_r128m32() // Opcode f3 0f 5f |
| 3097 | { |
| 3098 | UINT8 modrm = FETCH(); |
| 3099 | if( modrm >= 0xc0 ) { |
| 3100 | XMM((modrm >> 3) & 0x7).f[0] = sse_max_single(XMM((modrm >> 3) & 0x7).f[0], XMM(modrm & 0x7).f[0]); |
| 3101 | } else { |
| 3102 | XMM_REG src; |
| 3103 | UINT32 ea = GetEA(modrm, 0); |
| 3104 | src.d[0]=READ32(ea); |
| 3105 | XMM((modrm >> 3) & 0x7).f[0] = sse_max_single(XMM((modrm >> 3) & 0x7).f[0], src.f[0]); |
| 3106 | } |
| 3107 | CYCLES(1); // TODO: correct cycle count |
| 3108 | } |
| 3109 | |
| 3110 | void i386_device::sse_addss() // Opcode f3 0f 58 |
| 3111 | { |
| 3112 | UINT8 modrm = FETCH(); |
| 3113 | if( modrm >= 0xc0 ) { |
| 3114 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + XMM(modrm & 0x7).f[0]; |
| 3115 | } else { |
| 3116 | XMM_REG src; |
| 3117 | UINT32 ea = GetEA(modrm, 0); |
| 3118 | READXMM(ea, src); |
| 3119 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] + src.f[0]; |
| 3120 | } |
| 3121 | CYCLES(1); // TODO: correct cycle count |
| 3122 | } |
| 3123 | |
| 3124 | void i386_device::sse_subss() // Opcode f3 0f 5c |
| 3125 | { |
| 3126 | UINT8 modrm = FETCH(); |
| 3127 | if( modrm >= 0xc0 ) { |
| 3128 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] - XMM(modrm & 0x7).f[0]; |
| 3129 | } else { |
| 3130 | XMM_REG src; |
| 3131 | UINT32 ea = GetEA(modrm, 0); |
| 3132 | READXMM(ea, src); |
| 3133 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] - src.f[0]; |
| 3134 | } |
| 3135 | CYCLES(1); // TODO: correct cycle count |
| 3136 | } |
| 3137 | |
| 3138 | void i386_device::sse_mulss() // Opcode f3 0f 5e |
| 3139 | { |
| 3140 | UINT8 modrm = FETCH(); |
| 3141 | if( modrm >= 0xc0 ) { |
| 3142 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * XMM(modrm & 0x7).f[0]; |
| 3143 | } else { |
| 3144 | XMM_REG src; |
| 3145 | UINT32 ea = GetEA(modrm, 0); |
| 3146 | READXMM(ea, src); |
| 3147 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] * src.f[0]; |
| 3148 | } |
| 3149 | CYCLES(1); // TODO: correct cycle count |
| 3150 | } |
| 3151 | |
| 3152 | void i386_device::sse_divss() // Opcode 0f 59 |
| 3153 | { |
| 3154 | UINT8 modrm = FETCH(); |
| 3155 | if( modrm >= 0xc0 ) { |
| 3156 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] / XMM(modrm & 0x7).f[0]; |
| 3157 | } else { |
| 3158 | XMM_REG src; |
| 3159 | UINT32 ea = GetEA(modrm, 0); |
| 3160 | READXMM(ea, src); |
| 3161 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] / src.f[0]; |
| 3162 | } |
| 3163 | CYCLES(1); // TODO: correct cycle count |
| 3164 | } |
| 3165 | |
| 3166 | void i386_device::sse_rcpss_r128_r128m32() // Opcode f3 0f 53 |
| 3167 | { |
| 3168 | UINT8 modrm = FETCH(); |
| 3169 | if( modrm >= 0xc0 ) { |
| 3170 | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / XMM(modrm & 0x7).f[0]; |
| 3171 | } else { |
| 3172 | XMM_REG s; |
| 3173 | UINT32 ea = GetEA(modrm, 0); |
| 3174 | s.d[0]=READ32(ea); |
| 3175 | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / s.f[0]; |
| 3176 | } |
| 3177 | CYCLES(1); // TODO: correct cycle count |
| 3178 | } |
| 3179 | |
| 3180 | void i386_device::sse_sqrtss_r128_r128m32() // Opcode f3 0f 51 |
| 3181 | { |
| 3182 | UINT8 modrm = FETCH(); |
| 3183 | if( modrm >= 0xc0 ) { |
| 3184 | XMM((modrm >> 3) & 0x7).f[0] = sqrt(XMM(modrm & 0x7).f[0]); |
| 3185 | } else { |
| 3186 | XMM_REG s; |
| 3187 | UINT32 ea = GetEA(modrm, 0); |
| 3188 | s.d[0]=READ32(ea); |
| 3189 | XMM((modrm >> 3) & 0x7).f[0] = sqrt(s.f[0]); |
| 3190 | } |
| 3191 | CYCLES(1); // TODO: correct cycle count |
| 3192 | } |
| 3193 | |
| 3194 | void i386_device::sse_rsqrtss_r128_r128m32() // Opcode f3 0f 52 |
| 3195 | { |
| 3196 | UINT8 modrm = FETCH(); |
| 3197 | if( modrm >= 0xc0 ) { |
| 3198 | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / sqrt(XMM(modrm & 0x7).f[0]); |
| 3199 | } else { |
| 3200 | XMM_REG s; |
| 3201 | UINT32 ea = GetEA(modrm, 0); |
| 3202 | s.d[0]=READ32(ea); |
| 3203 | XMM((modrm >> 3) & 0x7).f[0] = 1.0 / sqrt(s.f[0]); |
| 3204 | } |
| 3205 | CYCLES(1); // TODO: correct cycle count |
| 3206 | } |
| 3207 | |
| 3208 | void i386_device::sse_minss_r128_r128m32() // Opcode f3 0f 5d |
| 3209 | { |
| 3210 | UINT8 modrm = FETCH(); |
| 3211 | if( modrm >= 0xc0 ) { |
| 3212 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] < XMM(modrm & 0x7).f[0] ? XMM((modrm >> 3) & 0x7).f[0] : XMM(modrm & 0x7).f[0]; |
| 3213 | } else { |
| 3214 | XMM_REG s; |
| 3215 | UINT32 ea = GetEA(modrm, 0); |
| 3216 | s.d[0] = READ32(ea); |
| 3217 | XMM((modrm >> 3) & 0x7).f[0] = XMM((modrm >> 3) & 0x7).f[0] < s.f[0] ? XMM((modrm >> 3) & 0x7).f[0] : s.f[0]; |
| 3218 | } |
| 3219 | CYCLES(1); // TODO: correct cycle count |
| 3220 | } |
| 3221 | |
| 3222 | void i386_device::sse_comiss_r128_r128m32() // Opcode 0f 2f |
| 3223 | { |
| 3224 | float32 a,b; |
| 3225 | UINT8 modrm = FETCH(); |
| 3226 | if( modrm >= 0xc0 ) { |
| 3227 | a = XMM((modrm >> 3) & 0x7).d[0]; |
| 3228 | b = XMM(modrm & 0x7).d[0]; |
| 3229 | } else { |
| 3230 | XMM_REG src; |
| 3231 | UINT32 ea = GetEA(modrm, 0); |
| 3232 | READXMM(ea, src); |
| 3233 | a = XMM((modrm >> 3) & 0x7).d[0]; |
| 3234 | b = src.d[0]; |
| 3235 | } |
| 3236 | m_OF=0; |
| 3237 | m_SF=0; |
| 3238 | m_AF=0; |
| 3239 | if (float32_is_nan(a) || float32_is_nan(b)) |
| 3240 | { |
| 3241 | m_ZF = 1; |
| 3242 | m_PF = 1; |
| 3243 | m_CF = 1; |
| 3244 | } |
| 3245 | else |
| 3246 | { |
| 3247 | m_ZF = 0; |
| 3248 | m_PF = 0; |
| 3249 | m_CF = 0; |
| 3250 | if (float32_eq(a, b)) |
| 3251 | m_ZF = 1; |
| 3252 | if (float32_lt(a, b)) |
| 3253 | m_CF = 1; |
| 3254 | } |
| 3255 | // should generate exception when at least one of the operands is either QNaN or SNaN |
| 3256 | CYCLES(1); // TODO: correct cycle count |
| 3257 | } |
| 3258 | |
| 3259 | void i386_device::sse_ucomiss_r128_r128m32() // Opcode 0f 2e |
| 3260 | { |
| 3261 | float32 a,b; |
| 3262 | UINT8 modrm = FETCH(); |
| 3263 | if( modrm >= 0xc0 ) { |
| 3264 | a = XMM((modrm >> 3) & 0x7).d[0]; |
| 3265 | b = XMM(modrm & 0x7).d[0]; |
| 3266 | } else { |
| 3267 | XMM_REG src; |
| 3268 | UINT32 ea = GetEA(modrm, 0); |
| 3269 | READXMM(ea, src); |
| 3270 | a = XMM((modrm >> 3) & 0x7).d[0]; |
| 3271 | b = src.d[0]; |
| 3272 | } |
| 3273 | m_OF=0; |
| 3274 | m_SF=0; |
| 3275 | m_AF=0; |
| 3276 | if (float32_is_nan(a) || float32_is_nan(b)) |
| 3277 | { |
| 3278 | m_ZF = 1; |
| 3279 | m_PF = 1; |
| 3280 | m_CF = 1; |
| 3281 | } |
| 3282 | else |
| 3283 | { |
| 3284 | m_ZF = 0; |
| 3285 | m_PF = 0; |
| 3286 | m_CF = 0; |
| 3287 | if (float32_eq(a, b)) |
| 3288 | m_ZF = 1; |
| 3289 | if (float32_lt(a, b)) |
| 3290 | m_CF = 1; |
| 3291 | } |
| 3292 | // should generate exception when at least one of the operands is SNaN |
| 3293 | CYCLES(1); // TODO: correct cycle count |
| 3294 | } |
| 3295 | |
| 3296 | void i386_device::sse_shufps() // Opcode 0f 67 |
| 3297 | { |
| 3298 | UINT8 modrm = FETCH(); |
| 3299 | UINT8 sel = FETCH(); |
| 3300 | int m1,m2,m3,m4; |
| 3301 | int s,d; |
| 3302 | m1=sel & 3; |
| 3303 | m2=(sel >> 2) & 3; |
| 3304 | m3=(sel >> 4) & 3; |
| 3305 | m4=(sel >> 6) & 3; |
| 3306 | s=modrm & 0x7; |
| 3307 | d=(modrm >> 3) & 0x7; |
| 3308 | if( modrm >= 0xc0 ) { |
| 3309 | UINT32 t; |
| 3310 | t=XMM(d).d[m1]; |
| 3311 | XMM(d).d[1]=XMM(d).d[m2]; |
| 3312 | XMM(d).d[0]=t; |
| 3313 | XMM(d).d[2]=XMM(s).d[m3]; |
| 3314 | XMM(d).d[3]=XMM(s).d[m4]; |
| 3315 | } else { |
| 3316 | UINT32 t; |
| 3317 | XMM_REG src; |
| 3318 | UINT32 ea = GetEA(modrm, 0); |
| 3319 | READXMM(ea, src); |
| 3320 | t=XMM(d).d[m1]; |
| 3321 | XMM(d).d[1]=XMM(d).d[m2]; |
| 3322 | XMM(d).d[0]=t; |
| 3323 | XMM(d).d[2]=src.d[m3]; |
| 3324 | XMM(d).d[3]=src.d[m4]; |
| 3325 | } |
| 3326 | CYCLES(1); // TODO: correct cycle count |
| 3327 | } |
| 3328 | |
| 3329 | void i386_device::sse_unpcklps_r128_rm128() // Opcode 0f 14 |
| 3330 | { |
| 3331 | UINT8 modrm = FETCH(); |
| 3332 | int s,d; |
| 3333 | s=modrm & 0x7; |
| 3334 | d=(modrm >> 3) & 0x7; |
| 3335 | if( modrm >= 0xc0 ) { |
| 3336 | XMM(d).d[3]=XMM(s).d[1]; |
| 3337 | XMM(d).d[2]=XMM(d).d[1]; |
| 3338 | XMM(d).d[1]=XMM(s).d[0]; |
| 3339 | //XMM(d).d[0]=XMM(d).d[0]; |
| 3340 | } else { |
| 3341 | XMM_REG src; |
| 3342 | UINT32 ea = GetEA(modrm, 0); |
| 3343 | READXMM(ea, src); |
| 3344 | XMM(d).d[3]=src.d[1]; |
| 3345 | XMM(d).d[2]=XMM(d).d[1]; |
| 3346 | XMM(d).d[1]=src.d[0]; |
| 3347 | } |
| 3348 | CYCLES(1); // TODO: correct cycle count |
| 3349 | } |
| 3350 | |
| 3351 | void i386_device::sse_unpckhps_r128_rm128() // Opcode 0f 15 |
| 3352 | { |
| 3353 | UINT8 modrm = FETCH(); |
| 3354 | int s,d; |
| 3355 | s=modrm & 0x7; |
| 3356 | d=(modrm >> 3) & 0x7; |
| 3357 | if( modrm >= 0xc0 ) { |
| 3358 | XMM(d).d[0]=XMM(d).d[2]; |
| 3359 | XMM(d).d[1]=XMM(s).d[2]; |
| 3360 | XMM(d).d[2]=XMM(d).d[3]; |
| 3361 | XMM(d).d[3]=XMM(s).d[3]; |
| 3362 | } else { |
| 3363 | XMM_REG src; |
| 3364 | UINT32 ea = GetEA(modrm, 0); |
| 3365 | READXMM(ea, src); |
| 3366 | XMM(d).d[0]=XMM(d).d[2]; |
| 3367 | XMM(d).d[1]=src.d[2]; |
| 3368 | XMM(d).d[2]=XMM(d).d[3]; |
| 3369 | XMM(d).d[3]=src.d[3]; |
| 3370 | } |
| 3371 | CYCLES(1); // TODO: correct cycle count |
| 3372 | } |
| 3373 | |
| 3374 | INLINE bool sse_issingleordered(float op1, float op2) |
| 3375 | { |
| 3376 | // TODO: true when at least one of the two source operands being compared is a NaN |
| 3377 | return (op1 != op1) || (op1 != op2); |
| 3378 | } |
| 3379 | |
| 3380 | INLINE bool sse_issingleunordered(float op1, float op2) |
| 3381 | { |
| 3382 | // TODO: true when neither source operand is a NaN |
| 3383 | return !((op1 != op1) || (op1 != op2)); |
| 3384 | } |
| 3385 | |
| 3386 | void i386_device::sse_predicate_compare_single(UINT8 imm8, XMM_REG d, XMM_REG s) |
| 3387 | { |
| 3388 | switch (imm8 & 7) |
| 3389 | { |
| 3390 | case 0: |
| 3391 | s.d[0]=s.f[0] == s.f[0] ? 0xffffffff : 0; |
| 3392 | d.d[1]=d.f[1] == s.f[1] ? 0xffffffff : 0; |
| 3393 | d.d[2]=d.f[2] == s.f[2] ? 0xffffffff : 0; |
| 3394 | d.d[3]=d.f[3] == s.f[3] ? 0xffffffff : 0; |
| 3395 | break; |
| 3396 | case 1: |
| 3397 | d.d[0]=d.f[0] < s.f[0] ? 0xffffffff : 0; |
| 3398 | d.d[1]=d.f[1] < s.f[1] ? 0xffffffff : 0; |
| 3399 | d.d[2]=d.f[2] < s.f[2] ? 0xffffffff : 0; |
| 3400 | d.d[3]=d.f[3] < s.f[3] ? 0xffffffff : 0; |
| 3401 | break; |
| 3402 | case 2: |
| 3403 | d.d[0]=d.f[0] <= s.f[0] ? 0xffffffff : 0; |
| 3404 | d.d[1]=d.f[1] <= s.f[1] ? 0xffffffff : 0; |
| 3405 | d.d[2]=d.f[2] <= s.f[2] ? 0xffffffff : 0; |
| 3406 | d.d[3]=d.f[3] <= s.f[3] ? 0xffffffff : 0; |
| 3407 | break; |
| 3408 | case 3: |
| 3409 | d.d[0]=sse_issingleunordered(d.f[0], s.f[0]) ? 0xffffffff : 0; |
| 3410 | d.d[1]=sse_issingleunordered(d.f[1], s.f[1]) ? 0xffffffff : 0; |
| 3411 | d.d[2]=sse_issingleunordered(d.f[2], s.f[2]) ? 0xffffffff : 0; |
| 3412 | d.d[3]=sse_issingleunordered(d.f[3], s.f[3]) ? 0xffffffff : 0; |
| 3413 | break; |
| 3414 | case 4: |
| 3415 | d.d[0]=d.f[0] != s.f[0] ? 0xffffffff : 0; |
| 3416 | d.d[1]=d.f[1] != s.f[1] ? 0xffffffff : 0; |
| 3417 | d.d[2]=d.f[2] != s.f[2] ? 0xffffffff : 0; |
| 3418 | d.d[3]=d.f[3] != s.f[3] ? 0xffffffff : 0; |
| 3419 | break; |
| 3420 | case 5: |
| 3421 | d.d[0]=d.f[0] < s.f[0] ? 0 : 0xffffffff; |
| 3422 | d.d[1]=d.f[1] < s.f[1] ? 0 : 0xffffffff; |
| 3423 | d.d[2]=d.f[2] < s.f[2] ? 0 : 0xffffffff; |
| 3424 | d.d[3]=d.f[3] < s.f[3] ? 0 : 0xffffffff; |
| 3425 | break; |
| 3426 | case 6: |
| 3427 | d.d[0]=d.f[0] <= s.f[0] ? 0 : 0xffffffff; |
| 3428 | d.d[1]=d.f[1] <= s.f[1] ? 0 : 0xffffffff; |
| 3429 | d.d[2]=d.f[2] <= s.f[2] ? 0 : 0xffffffff; |
| 3430 | d.d[3]=d.f[3] <= s.f[3] ? 0 : 0xffffffff; |
| 3431 | break; |
| 3432 | case 7: |
| 3433 | d.d[0]=sse_issingleordered(d.f[0], s.f[0]) ? 0xffffffff : 0; |
| 3434 | d.d[1]=sse_issingleordered(d.f[1], s.f[1]) ? 0xffffffff : 0; |
| 3435 | d.d[2]=sse_issingleordered(d.f[2], s.f[2]) ? 0xffffffff : 0; |
| 3436 | d.d[3]=sse_issingleordered(d.f[3], s.f[3]) ? 0xffffffff : 0; |
| 3437 | break; |
| 3438 | } |
| 3439 | } |
| 3440 | |
| 3441 | void i386_device::sse_predicate_compare_single_scalar(UINT8 imm8, XMM_REG d, XMM_REG s) |
| 3442 | { |
| 3443 | switch (imm8 & 7) |
| 3444 | { |
| 3445 | case 0: |
| 3446 | s.d[0]=s.f[0] == s.f[0] ? 0xffffffff : 0; |
| 3447 | break; |
| 3448 | case 1: |
| 3449 | d.d[0]=d.f[0] < s.f[0] ? 0xffffffff : 0; |
| 3450 | break; |
| 3451 | case 2: |
| 3452 | d.d[0]=d.f[0] <= s.f[0] ? 0xffffffff : 0; |
| 3453 | break; |
| 3454 | case 3: |
| 3455 | d.d[0]=sse_issingleunordered(d.f[0], s.f[0]) ? 0xffffffff : 0; |
| 3456 | break; |
| 3457 | case 4: |
| 3458 | d.d[0]=d.f[0] != s.f[0] ? 0xffffffff : 0; |
| 3459 | break; |
| 3460 | case 5: |
| 3461 | d.d[0]=d.f[0] < s.f[0] ? 0 : 0xffffffff; |
| 3462 | break; |
| 3463 | case 6: |
| 3464 | d.d[0]=d.f[0] <= s.f[0] ? 0 : 0xffffffff; |
| 3465 | break; |
| 3466 | case 7: |
| 3467 | d.d[0]=sse_issingleordered(d.f[0], s.f[0]) ? 0xffffffff : 0; |
| 3468 | break; |
| 3469 | } |
| 3470 | } |
| 3471 | |
| 3472 | void i386_device::sse_cmpps_r128_rm128_i8() // Opcode 0f c2 |
| 3473 | { |
| 3474 | UINT8 modrm = FETCH(); |
| 3475 | if( modrm >= 0xc0 ) { |
| 3476 | int s,d; |
| 3477 | UINT8 imm8 = FETCH(); |
| 3478 | s=modrm & 0x7; |
| 3479 | d=(modrm >> 3) & 0x7; |
| 3480 | sse_predicate_compare_single(imm8, XMM(d), XMM(s)); |
| 3481 | } else { |
| 3482 | int d; |
| 3483 | XMM_REG s; |
| 3484 | UINT32 ea = GetEA(modrm, 0); |
| 3485 | UINT8 imm8 = FETCH(); |
| 3486 | READXMM(ea, s); |
| 3487 | d=(modrm >> 3) & 0x7; |
| 3488 | sse_predicate_compare_single(imm8, XMM(d), s); |
| 3489 | } |
| 3490 | CYCLES(1); // TODO: correct cycle count |
| 3491 | } |
| 3492 | |
| 3493 | void i386_device::sse_cmpss_r128_r128m32_i8() // Opcode f3 0f c2 |
| 3494 | { |
| 3495 | UINT8 modrm = FETCH(); |
| 3496 | if( modrm >= 0xc0 ) { |
| 3497 | int s,d; |
| 3498 | UINT8 imm8 = FETCH(); |
| 3499 | s=modrm & 0x7; |
| 3500 | d=(modrm >> 3) & 0x7; |
| 3501 | sse_predicate_compare_single_scalar(imm8, XMM(d), XMM(s)); |
| 3502 | } else { |
| 3503 | int d; |
| 3504 | XMM_REG s; |
| 3505 | UINT32 ea = GetEA(modrm, 0); |
| 3506 | UINT8 imm8 = FETCH(); |
| 3507 | s.d[0]=READ32(ea); |
| 3508 | d=(modrm >> 3) & 0x7; |
| 3509 | sse_predicate_compare_single_scalar(imm8, XMM(d), s); |
| 3510 | } |
| 3511 | CYCLES(1); // TODO: correct cycle count |
| 3512 | } |
| 3513 | |
| 3514 | void i386_device::sse_pinsrw_r64_r16m16_i8() // Opcode 0f c4 |
| 3515 | { |
| 3516 | MMXPROLOG(); |
| 3517 | UINT8 modrm = FETCH(); |
| 3518 | if( modrm >= 0xc0 ) { |
| 3519 | UINT8 imm8 = FETCH(); |
| 3520 | UINT16 v = LOAD_RM16(modrm); |
| 3521 | MMX((modrm >> 3) & 0x7).w[imm8 & 3] = v; |
| 3522 | } else { |
| 3523 | UINT32 ea = GetEA(modrm, 0); |
| 3524 | UINT8 imm8 = FETCH(); |
| 3525 | UINT16 v = READ16(ea); |
| 3526 | MMX((modrm >> 3) & 0x7).w[imm8 & 3] = v; |
| 3527 | } |
| 3528 | CYCLES(1); // TODO: correct cycle count |
| 3529 | } |
| 3530 | |
| 3531 | void i386_device::sse_pinsrw_r64_r32m16_i8() // Opcode 0f c4 |
| 3532 | { |
| 3533 | MMXPROLOG(); |
| 3534 | UINT8 modrm = FETCH(); |
| 3535 | if( modrm >= 0xc0 ) { |
| 3536 | UINT8 imm8 = FETCH(); |
| 3537 | UINT16 v = (UINT16)LOAD_RM32(modrm); |
| 3538 | MMX((modrm >> 3) & 0x7).w[imm8 & 3] = v; |
| 3539 | } else { |
| 3540 | UINT32 ea = GetEA(modrm, 0); |
| 3541 | UINT8 imm8 = FETCH(); |
| 3542 | UINT16 v = READ16(ea); |
| 3543 | MMX((modrm >> 3) & 0x7).w[imm8 & 3] = v; |
| 3544 | } |
| 3545 | CYCLES(1); // TODO: correct cycle count |
| 3546 | } |
| 3547 | |
| 3548 | void i386_device::sse_pextrw_r16_r64_i8() // Opcode 0f c5 |
| 3549 | { |
| 3550 | //MMXPROLOG(); |
| 3551 | UINT8 modrm = FETCH(); |
| 3552 | if( modrm >= 0xc0 ) { |
| 3553 | UINT8 imm8 = FETCH(); |
| 3554 | STORE_REG16(modrm, MMX(modrm & 0x7).w[imm8 & 3]); |
| 3555 | } else { |
| 3556 | //UINT8 imm8 = FETCH(); |
| 3557 | report_invalid_modrm("pextrw_r16_r64_i8", modrm); |
| 3558 | } |
| 3559 | CYCLES(1); // TODO: correct cycle count |
| 3560 | } |
| 3561 | |
| 3562 | void i386_device::sse_pextrw_r32_r64_i8() // Opcode 0f c5 |
| 3563 | { |
| 3564 | //MMXPROLOG(); |
| 3565 | UINT8 modrm = FETCH(); |
| 3566 | if( modrm >= 0xc0 ) { |
| 3567 | UINT8 imm8 = FETCH(); |
| 3568 | STORE_REG32(modrm, MMX(modrm & 0x7).w[imm8 & 3]); |
| 3569 | } else { |
| 3570 | //UINT8 imm8 = FETCH(); |
| 3571 | report_invalid_modrm("pextrw_r32_r64_i8", modrm); |
| 3572 | } |
| 3573 | CYCLES(1); // TODO: correct cycle count |
| 3574 | } |
| 3575 | |
| 3576 | void i386_device::sse_pminub_r64_rm64() // Opcode 0f da |
| 3577 | { |
| 3578 | int n; |
| 3579 | MMXPROLOG(); |
| 3580 | UINT8 modrm = FETCH(); |
| 3581 | if( modrm >= 0xc0 ) { |
| 3582 | for (n=0;n < 8;n++) |
| 3583 | MMX((modrm >> 3) & 0x7).b[n] = MMX((modrm >> 3) & 0x7).b[n] < MMX(modrm & 0x7).b[n] ? MMX((modrm >> 3) & 0x7).b[n] : MMX(modrm & 0x7).b[n]; |
| 3584 | } else { |
| 3585 | MMX_REG s; |
| 3586 | UINT32 ea = GetEA(modrm, 0); |
| 3587 | READMMX(ea, s); |
| 3588 | for (n=0;n < 8;n++) |
| 3589 | MMX((modrm >> 3) & 0x7).b[n] = MMX((modrm >> 3) & 0x7).b[n] < s.b[n] ? MMX((modrm >> 3) & 0x7).b[n] : s.b[n]; |
| 3590 | } |
| 3591 | CYCLES(1); // TODO: correct cycle count |
| 3592 | } |
| 3593 | |
| 3594 | void i386_device::sse_pmaxub_r64_rm64() // Opcode 0f de |
| 3595 | { |
| 3596 | int n; |
| 3597 | MMXPROLOG(); |
| 3598 | UINT8 modrm = FETCH(); |
| 3599 | if( modrm >= 0xc0 ) { |
| 3600 | for (n=0;n < 8;n++) |
| 3601 | MMX((modrm >> 3) & 0x7).b[n] = MMX((modrm >> 3) & 0x7).b[n] > MMX(modrm & 0x7).b[n] ? MMX((modrm >> 3) & 0x7).b[n] : MMX(modrm & 0x7).b[n]; |
| 3602 | } else { |
| 3603 | MMX_REG s; |
| 3604 | UINT32 ea = GetEA(modrm, 0); |
| 3605 | READMMX(ea, s); |
| 3606 | for (n=0;n < 8;n++) |
| 3607 | MMX((modrm >> 3) & 0x7).b[n] = MMX((modrm >> 3) & 0x7).b[n] > s.b[n] ? MMX((modrm >> 3) & 0x7).b[n] : s.b[n]; |
| 3608 | } |
| 3609 | CYCLES(1); // TODO: correct cycle count |
| 3610 | } |
| 3611 | |
| 3612 | void i386_device::sse_pavgb_r64_rm64() // Opcode 0f e0 |
| 3613 | { |
| 3614 | int n; |
| 3615 | MMXPROLOG(); |
| 3616 | UINT8 modrm = FETCH(); |
| 3617 | if( modrm >= 0xc0 ) { |
| 3618 | for (n=0;n < 8;n++) |
| 3619 | MMX((modrm >> 3) & 0x7).b[n] = ((UINT16)MMX((modrm >> 3) & 0x7).b[n] + (UINT16)MMX(modrm & 0x7).b[n] + 1) >> 1; |
| 3620 | } else { |
| 3621 | MMX_REG s; |
| 3622 | UINT32 ea = GetEA(modrm, 0); |
| 3623 | READMMX(ea, s); |
| 3624 | for (n=0;n < 8;n++) |
| 3625 | MMX((modrm >> 3) & 0x7).b[n] = ((UINT16)MMX((modrm >> 3) & 0x7).b[n] + (UINT16)s.b[n] + 1) >> 1; |
| 3626 | } |
| 3627 | CYCLES(1); // TODO: correct cycle count |
| 3628 | } |
| 3629 | |
| 3630 | void i386_device::sse_pavgw_r64_rm64() // Opcode 0f e3 |
| 3631 | { |
| 3632 | int n; |
| 3633 | MMXPROLOG(); |
| 3634 | UINT8 modrm = FETCH(); |
| 3635 | if( modrm >= 0xc0 ) { |
| 3636 | for (n=0;n < 4;n++) |
| 3637 | MMX((modrm >> 3) & 0x7).w[n] = ((UINT32)MMX((modrm >> 3) & 0x7).w[n] + (UINT32)MMX(modrm & 0x7).w[n] + 1) >> 1; |
| 3638 | } else { |
| 3639 | MMX_REG s; |
| 3640 | UINT32 ea = GetEA(modrm, 0); |
| 3641 | READMMX(ea, s); |
| 3642 | for (n=0;n < 4;n++) |
| 3643 | MMX((modrm >> 3) & 0x7).w[n] = ((UINT32)MMX((modrm >> 3) & 0x7).w[n] + (UINT32)s.w[n] + 1) >> 1; |
| 3644 | } |
| 3645 | CYCLES(1); // TODO: correct cycle count |
| 3646 | } |
| 3647 | |
| 3648 | void i386_device::sse_pmulhuw_r64_rm64() // Opcode 0f e4 |
| 3649 | { |
| 3650 | MMXPROLOG(); |
| 3651 | UINT8 modrm = FETCH(); |
| 3652 | if( modrm >= 0xc0 ) { |
| 3653 | MMX((modrm >> 3) & 0x7).w[0]=((UINT32)MMX((modrm >> 3) & 0x7).w[0]*(UINT32)MMX(modrm & 7).w[0]) >> 16; |
| 3654 | MMX((modrm >> 3) & 0x7).w[1]=((UINT32)MMX((modrm >> 3) & 0x7).w[1]*(UINT32)MMX(modrm & 7).w[1]) >> 16; |
| 3655 | MMX((modrm >> 3) & 0x7).w[2]=((UINT32)MMX((modrm >> 3) & 0x7).w[2]*(UINT32)MMX(modrm & 7).w[2]) >> 16; |
| 3656 | MMX((modrm >> 3) & 0x7).w[3]=((UINT32)MMX((modrm >> 3) & 0x7).w[3]*(UINT32)MMX(modrm & 7).w[3]) >> 16; |
| 3657 | } else { |
| 3658 | MMX_REG s; |
| 3659 | UINT32 ea = GetEA(modrm, 0); |
| 3660 | READMMX(ea, s); |
| 3661 | MMX((modrm >> 3) & 0x7).w[0]=((UINT32)MMX((modrm >> 3) & 0x7).w[0]*(UINT32)s.w[0]) >> 16; |
| 3662 | MMX((modrm >> 3) & 0x7).w[1]=((UINT32)MMX((modrm >> 3) & 0x7).w[1]*(UINT32)s.w[1]) >> 16; |
| 3663 | MMX((modrm >> 3) & 0x7).w[2]=((UINT32)MMX((modrm >> 3) & 0x7).w[2]*(UINT32)s.w[2]) >> 16; |
| 3664 | MMX((modrm >> 3) & 0x7).w[3]=((UINT32)MMX((modrm >> 3) & 0x7).w[3]*(UINT32)s.w[3]) >> 16; |
| 3665 | } |
| 3666 | CYCLES(1); // TODO: correct cycle count |
| 3667 | } |
| 3668 | |
| 3669 | void i386_device::sse_pminsw_r64_rm64() // Opcode 0f ea |
| 3670 | { |
| 3671 | int n; |
| 3672 | MMXPROLOG(); |
| 3673 | UINT8 modrm = FETCH(); |
| 3674 | if( modrm >= 0xc0 ) { |
| 3675 | for (n=0;n < 4;n++) |
| 3676 | MMX((modrm >> 3) & 0x7).s[n] = MMX((modrm >> 3) & 0x7).s[n] < MMX(modrm & 0x7).s[n] ? MMX((modrm >> 3) & 0x7).s[n] : MMX(modrm & 0x7).s[n]; |
| 3677 | } else { |
| 3678 | MMX_REG s; |
| 3679 | UINT32 ea = GetEA(modrm, 0); |
| 3680 | READMMX(ea, s); |
| 3681 | for (n=0;n < 4;n++) |
| 3682 | MMX((modrm >> 3) & 0x7).s[n] = MMX((modrm >> 3) & 0x7).s[n] < s.s[n] ? MMX((modrm >> 3) & 0x7).s[n] : s.s[n]; |
| 3683 | } |
| 3684 | CYCLES(1); // TODO: correct cycle count |
| 3685 | } |
| 3686 | |
| 3687 | void i386_device::sse_pmaxsw_r64_rm64() // Opcode 0f ee |
| 3688 | { |
| 3689 | int n; |
| 3690 | MMXPROLOG(); |
| 3691 | UINT8 modrm = FETCH(); |
| 3692 | if( modrm >= 0xc0 ) { |
| 3693 | for (n=0;n < 4;n++) |
| 3694 | MMX((modrm >> 3) & 0x7).s[n] = MMX((modrm >> 3) & 0x7).s[n] > MMX(modrm & 0x7).s[n] ? MMX((modrm >> 3) & 0x7).s[n] : MMX(modrm & 0x7).s[n]; |
| 3695 | } else { |
| 3696 | MMX_REG s; |
| 3697 | UINT32 ea = GetEA(modrm, 0); |
| 3698 | READMMX(ea, s); |
| 3699 | for (n=0;n < 4;n++) |
| 3700 | MMX((modrm >> 3) & 0x7).s[n] = MMX((modrm >> 3) & 0x7).s[n] > s.s[n] ? MMX((modrm >> 3) & 0x7).s[n] : s.s[n]; |
| 3701 | } |
| 3702 | CYCLES(1); // TODO: correct cycle count |
| 3703 | } |
| 3704 | |
| 3705 | void i386_device::sse_pmuludq_r64_rm64() // Opcode 0f f4 |
| 3706 | { |
| 3707 | MMXPROLOG(); |
| 3708 | UINT8 modrm = FETCH(); |
| 3709 | if( modrm >= 0xc0 ) { |
| 3710 | MMX((modrm >> 3) & 0x7).q = (UINT64)MMX((modrm >> 3) & 0x7).d[0] * (UINT64)MMX(modrm & 0x7).d[0]; |
| 3711 | } else { |
| 3712 | MMX_REG s; |
| 3713 | UINT32 ea = GetEA(modrm, 0); |
| 3714 | READMMX(ea, s); |
| 3715 | MMX((modrm >> 3) & 0x7).q = (UINT64)MMX((modrm >> 3) & 0x7).d[0] * (UINT64)s.d[0]; |
| 3716 | } |
| 3717 | CYCLES(1); // TODO: correct cycle count |
| 3718 | } |
| 3719 | |
| 3720 | void i386_device::sse_psadbw_r64_rm64() // Opcode 0f f6 |
| 3721 | { |
| 3722 | int n; |
| 3723 | INT32 temp; |
| 3724 | MMXPROLOG(); |
| 3725 | UINT8 modrm = FETCH(); |
| 3726 | if( modrm >= 0xc0 ) { |
| 3727 | temp=0; |
| 3728 | for (n=0;n < 8;n++) |
| 3729 | temp += abs((INT32)MMX((modrm >> 3) & 0x7).b[n] - (INT32)MMX(modrm & 0x7).b[n]); |
| 3730 | MMX((modrm >> 3) & 0x7).l=(UINT64)temp & 0xffff; |
| 3731 | } else { |
| 3732 | MMX_REG s; |
| 3733 | UINT32 ea = GetEA(modrm, 0); |
| 3734 | READMMX(ea, s); |
| 3735 | temp=0; |
| 3736 | for (n=0;n < 8;n++) |
| 3737 | temp += abs((INT32)MMX((modrm >> 3) & 0x7).b[n] - (INT32)s.b[n]); |
| 3738 | MMX((modrm >> 3) & 0x7).l=(UINT64)temp & 0xffff; |
| 3739 | } |
| 3740 | CYCLES(1); // TODO: correct cycle count |
| 3741 | } |
| 3742 | |
| 3743 | void i386_device::sse_psubq_r64_rm64() // Opcode 0f fb |
| 3744 | { |
| 3745 | MMXPROLOG(); |
| 3746 | UINT8 modrm = FETCH(); |
| 3747 | if( modrm >= 0xc0 ) { |
| 3748 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q - MMX(modrm & 7).q; |
| 3749 | } else { |
| 3750 | MMX_REG s; |
| 3751 | UINT32 ea = GetEA(modrm, 0); |
| 3752 | READMMX(ea, s); |
| 3753 | MMX((modrm >> 3) & 0x7).q=MMX((modrm >> 3) & 0x7).q - s.q; |
| 3754 | } |
| 3755 | CYCLES(1); // TODO: correct cycle count |
| 3756 | } |
| 3757 | |
| 3758 | void i386_device::sse_pshufhw_r128_rm128_i8() // Opcode f3 0f 70 |
| 3759 | { |
| 3760 | UINT8 modrm = FETCH(); |
| 3761 | if( modrm >= 0xc0 ) { |
| 3762 | XMM_REG t; |
| 3763 | int s,d; |
| 3764 | UINT8 imm8 = FETCH(); |
| 3765 | s=modrm & 0x7; |
| 3766 | d=(modrm >> 3) & 0x7; |
| 3767 | t.q[0]=XMM(s).q[1]; |
| 3768 | XMM(d).q[0]=XMM(s).q[0]; |
| 3769 | XMM(d).w[4]=t.w[imm8 & 3]; |
| 3770 | XMM(d).w[5]=t.w[(imm8 >> 2) & 3]; |
| 3771 | XMM(d).w[6]=t.w[(imm8 >> 4) & 3]; |
| 3772 | XMM(d).w[7]=t.w[(imm8 >> 6) & 3]; |
| 3773 | } else { |
| 3774 | XMM_REG s; |
| 3775 | int d=(modrm >> 3) & 0x7; |
| 3776 | UINT32 ea = GetEA(modrm, 0); |
| 3777 | UINT8 imm8 = FETCH(); |
| 3778 | READXMM(ea, s); |
| 3779 | XMM(d).q[0]=s.q[0]; |
| 3780 | XMM(d).w[4]=s.w[4 + (imm8 & 3)]; |
| 3781 | XMM(d).w[5]=s.w[4 + ((imm8 >> 2) & 3)]; |
| 3782 | XMM(d).w[6]=s.w[4 + ((imm8 >> 4) & 3)]; |
| 3783 | XMM(d).w[7]=s.w[4 + ((imm8 >> 6) & 3)]; |
| 3784 | } |
| 3785 | CYCLES(1); // TODO: correct cycle count |
| 3786 | } |
trunk/src/emu/cpu/i386/x87ops.inc
| r0 | r28739 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | x87 FPU emulation |
| 4 | |
| 5 | TODO: |
| 6 | - 80-bit precision for F2XM1, FYL2X, FPATAN |
| 7 | - Figure out why SoftFloat trig extensions produce bad values |
| 8 | - Cycle counts for all processors (currently using 486 counts) |
| 9 | - Precision-dependent cycle counts for divide instructions |
| 10 | - Last instruction, operand pointers etc. |
| 11 | - Fix FLDENV, FSTENV, FSAVE, FRSTOR and FPREM |
| 12 | - Status word C2 updates to reflect round up/down |
| 13 | - Handling of invalid and denormal numbers |
| 14 | - Remove redundant operand checks |
| 15 | - Exceptions |
| 16 | |
| 17 | ***************************************************************************/ |
| 18 | |
| 19 | #include <math.h> |
| 20 | |
| 21 | |
| 22 | /************************************* |
| 23 | * |
| 24 | * Defines |
| 25 | * |
| 26 | *************************************/ |
| 27 | |
| 28 | #define X87_SW_IE 0x0001 |
| 29 | #define X87_SW_DE 0x0002 |
| 30 | #define X87_SW_ZE 0x0004 |
| 31 | #define X87_SW_OE 0x0008 |
| 32 | #define X87_SW_UE 0x0010 |
| 33 | #define X87_SW_PE 0x0020 |
| 34 | #define X87_SW_SF 0x0040 |
| 35 | #define X87_SW_ES 0x0080 |
| 36 | #define X87_SW_C0 0x0100 |
| 37 | #define X87_SW_C1 0x0200 |
| 38 | #define X87_SW_C2 0x0400 |
| 39 | #define X87_SW_TOP_SHIFT 11 |
| 40 | #define X87_SW_TOP_MASK 7 |
| 41 | #define X87_SW_C3 0x4000 |
| 42 | #define X87_SW_BUSY 0x8000 |
| 43 | |
| 44 | #define X87_CW_IM 0x0001 |
| 45 | #define X87_CW_DM 0x0002 |
| 46 | #define X87_CW_ZM 0x0004 |
| 47 | #define X87_CW_OM 0x0008 |
| 48 | #define X87_CW_UM 0x0010 |
| 49 | #define X87_CW_PM 0x0020 |
| 50 | #define X87_CW_PC_SHIFT 8 |
| 51 | #define X87_CW_PC_MASK 3 |
| 52 | #define X87_CW_PC_SINGLE 0 |
| 53 | #define X87_CW_PC_DOUBLE 2 |
| 54 | #define X87_CW_PC_EXTEND 3 |
| 55 | #define X87_CW_RC_SHIFT 10 |
| 56 | #define X87_CW_RC_MASK 3 |
| 57 | #define X87_CW_RC_NEAREST 0 |
| 58 | #define X87_CW_RC_DOWN 1 |
| 59 | #define X87_CW_RC_UP 2 |
| 60 | #define X87_CW_RC_ZERO 3 |
| 61 | |
| 62 | #define X87_TW_MASK 3 |
| 63 | #define X87_TW_VALID 0 |
| 64 | #define X87_TW_ZERO 1 |
| 65 | #define X87_TW_SPECIAL 2 |
| 66 | #define X87_TW_EMPTY 3 |
| 67 | |
| 68 | |
| 69 | /************************************* |
| 70 | * |
| 71 | * Macros |
| 72 | * |
| 73 | *************************************/ |
| 74 | |
| 75 | #define ST_TO_PHYS(x) (((m_x87_sw >> X87_SW_TOP_SHIFT) + (x)) & X87_SW_TOP_MASK) |
| 76 | #define ST(x) (m_x87_reg[ST_TO_PHYS(x)]) |
| 77 | #define X87_TW_FIELD_SHIFT(x) ((x) << 1) |
| 78 | #define X87_TAG(x) ((m_x87_tw >> X87_TW_FIELD_SHIFT(x)) & X87_TW_MASK) |
| 79 | #define X87_RC ((m_x87_cw >> X87_CW_RC_SHIFT) & X87_CW_RC_MASK) |
| 80 | #define X87_IS_ST_EMPTY(x) (X87_TAG(ST_TO_PHYS(x)) == X87_TW_EMPTY) |
| 81 | #define X87_SW_C3_0 X87_SW_C0 |
| 82 | |
| 83 | #define UNIMPLEMENTED fatalerror("Unimplemented x87 op: %s (PC:%x)\n", __FUNCTION__, m_pc) |
| 84 | |
| 85 | |
| 86 | /************************************* |
| 87 | * |
| 88 | * Constants |
| 89 | * |
| 90 | *************************************/ |
| 91 | |
| 92 | static const floatx80 fx80_zero = { 0x0000, U64(0x0000000000000000) }; |
| 93 | static const floatx80 fx80_one = { 0x3fff, U64(0x8000000000000000) }; |
| 94 | |
| 95 | static const floatx80 fx80_ninf = { 0xffff, U64(0x8000000000000000) }; |
| 96 | static const floatx80 fx80_inan = { 0xffff, U64(0xc000000000000000) }; |
| 97 | |
| 98 | /* Maps x87 round modes to SoftFloat round modes */ |
| 99 | static const int x87_to_sf_rc[4] = |
| 100 | { |
| 101 | float_round_nearest_even, |
| 102 | float_round_down, |
| 103 | float_round_up, |
| 104 | float_round_to_zero, |
| 105 | }; |
| 106 | |
| 107 | |
| 108 | /************************************* |
| 109 | * |
| 110 | * SoftFloat helpers |
| 111 | * |
| 112 | *************************************/ |
| 113 | |
| 114 | extern flag floatx80_is_nan( floatx80 a ); |
| 115 | |
| 116 | INLINE int floatx80_is_zero(floatx80 fx) |
| 117 | { |
| 118 | return (((fx.high & 0x7fff) == 0) && ((fx.low << 1) == 0)); |
| 119 | } |
| 120 | |
| 121 | INLINE int floatx80_is_inf(floatx80 fx) |
| 122 | { |
| 123 | return (((fx.high & 0x7fff) == 0x7fff) && ((fx.low << 1) == 0)); |
| 124 | } |
| 125 | |
| 126 | INLINE int floatx80_is_denormal(floatx80 fx) |
| 127 | { |
| 128 | return (((fx.high & 0x7fff) == 0) && |
| 129 | ((fx.low & U64(0x8000000000000000)) == 0) && |
| 130 | ((fx.low << 1) != 0)); |
| 131 | } |
| 132 | |
| 133 | INLINE floatx80 floatx80_abs(floatx80 fx) |
| 134 | { |
| 135 | fx.high &= 0x7fff; |
| 136 | return fx; |
| 137 | } |
| 138 | |
| 139 | INLINE double fx80_to_double(floatx80 fx) |
| 140 | { |
| 141 | UINT64 d = floatx80_to_float64(fx); |
| 142 | return *(double*)&d; |
| 143 | } |
| 144 | |
| 145 | INLINE floatx80 double_to_fx80(double in) |
| 146 | { |
| 147 | return float64_to_floatx80(*(UINT64*)&in); |
| 148 | } |
| 149 | |
| 150 | floatx80 i386_device::READ80(UINT32 ea) |
| 151 | { |
| 152 | floatx80 t; |
| 153 | |
| 154 | t.low = READ64(ea); |
| 155 | t.high = READ16(ea + 8); |
| 156 | |
| 157 | return t; |
| 158 | } |
| 159 | |
| 160 | void i386_device::WRITE80(UINT32 ea, floatx80 t) |
| 161 | { |
| 162 | WRITE64(ea, t.low); |
| 163 | WRITE16(ea + 8, t.high); |
| 164 | } |
| 165 | |
| 166 | |
| 167 | /************************************* |
| 168 | * |
| 169 | * x87 stack handling |
| 170 | * |
| 171 | *************************************/ |
| 172 | |
| 173 | void i386_device::x87_set_stack_top(int top) |
| 174 | { |
| 175 | m_x87_sw &= ~(X87_SW_TOP_MASK << X87_SW_TOP_SHIFT); |
| 176 | m_x87_sw |= (top << X87_SW_TOP_SHIFT); |
| 177 | } |
| 178 | |
| 179 | void i386_device::x87_set_tag(int reg, int tag) |
| 180 | { |
| 181 | int shift = X87_TW_FIELD_SHIFT(reg); |
| 182 | |
| 183 | m_x87_tw &= ~(X87_TW_MASK << shift); |
| 184 | m_x87_tw |= (tag << shift); |
| 185 | } |
| 186 | |
| 187 | void i386_device::x87_write_stack(int i, floatx80 value, int update_tag) |
| 188 | { |
| 189 | ST(i) = value; |
| 190 | |
| 191 | if (update_tag) |
| 192 | { |
| 193 | int tag; |
| 194 | |
| 195 | if (floatx80_is_zero(value)) |
| 196 | { |
| 197 | tag = X87_TW_ZERO; |
| 198 | } |
| 199 | else if (floatx80_is_inf(value) || floatx80_is_nan(value)) |
| 200 | { |
| 201 | tag = X87_TW_SPECIAL; |
| 202 | } |
| 203 | else |
| 204 | { |
| 205 | tag = X87_TW_VALID; |
| 206 | } |
| 207 | |
| 208 | x87_set_tag(ST_TO_PHYS(i), tag); |
| 209 | } |
| 210 | } |
| 211 | |
| 212 | void i386_device::x87_set_stack_underflow() |
| 213 | { |
| 214 | m_x87_sw |= X87_SW_C1 | X87_SW_IE | X87_SW_SF; |
| 215 | } |
| 216 | |
| 217 | void i386_device::x87_set_stack_overflow() |
| 218 | { |
| 219 | m_x87_sw &= ~X87_SW_C1; |
| 220 | m_x87_sw |= X87_SW_IE | X87_SW_SF; |
| 221 | } |
| 222 | |
| 223 | int i386_device::x87_inc_stack() |
| 224 | { |
| 225 | int ret = 1; |
| 226 | |
| 227 | // Check for stack underflow |
| 228 | if (X87_IS_ST_EMPTY(0)) |
| 229 | { |
| 230 | ret = 0; |
| 231 | x87_set_stack_underflow(); |
| 232 | |
| 233 | // Don't update the stack if the exception is unmasked |
| 234 | if (~m_x87_cw & X87_CW_IM) |
| 235 | return ret; |
| 236 | } |
| 237 | |
| 238 | x87_set_tag(ST_TO_PHYS(0), X87_TW_EMPTY); |
| 239 | x87_set_stack_top(ST_TO_PHYS(1)); |
| 240 | return ret; |
| 241 | } |
| 242 | |
| 243 | int i386_device::x87_dec_stack() |
| 244 | { |
| 245 | int ret = 1; |
| 246 | |
| 247 | // Check for stack overflow |
| 248 | if (!X87_IS_ST_EMPTY(7)) |
| 249 | { |
| 250 | ret = 0; |
| 251 | x87_set_stack_overflow(); |
| 252 | |
| 253 | // Don't update the stack if the exception is unmasked |
| 254 | if (~m_x87_cw & X87_CW_IM) |
| 255 | return ret; |
| 256 | } |
| 257 | |
| 258 | x87_set_stack_top(ST_TO_PHYS(7)); |
| 259 | return ret; |
| 260 | } |
| 261 | |
| 262 | |
| 263 | /************************************* |
| 264 | * |
| 265 | * Exception handling |
| 266 | * |
| 267 | *************************************/ |
| 268 | |
| 269 | int i386_device::x87_check_exceptions() |
| 270 | { |
| 271 | /* Update the exceptions from SoftFloat */ |
| 272 | if (float_exception_flags & float_flag_invalid) |
| 273 | { |
| 274 | m_x87_sw |= X87_SW_IE; |
| 275 | float_exception_flags &= ~float_flag_invalid; |
| 276 | } |
| 277 | if (float_exception_flags & float_flag_overflow) |
| 278 | { |
| 279 | m_x87_sw |= X87_SW_OE; |
| 280 | float_exception_flags &= ~float_flag_overflow; |
| 281 | } |
| 282 | if (float_exception_flags & float_flag_underflow) |
| 283 | { |
| 284 | m_x87_sw |= X87_SW_UE; |
| 285 | float_exception_flags &= ~float_flag_underflow; |
| 286 | } |
| 287 | if (float_exception_flags & float_flag_inexact) |
| 288 | { |
| 289 | m_x87_sw |= X87_SW_PE; |
| 290 | float_exception_flags &= ~float_flag_inexact; |
| 291 | } |
| 292 | |
| 293 | if ((m_x87_sw & ~m_x87_cw) & 0x3f) |
| 294 | { |
| 295 | // m_device->execute().set_input_line(INPUT_LINE_FERR, RAISE_LINE); |
| 296 | logerror("Unmasked x87 exception (CW:%.4x, SW:%.4x)\n", m_x87_cw, m_x87_sw); |
| 297 | if (m_cr[0] & 0x20) // FIXME: 486 and up only |
| 298 | { |
| 299 | m_ext = 1; |
| 300 | i386_trap(FAULT_MF, 0, 0); |
| 301 | } |
| 302 | return 0; |
| 303 | } |
| 304 | |
| 305 | return 1; |
| 306 | } |
| 307 | |
| 308 | void i386_device::x87_write_cw(UINT16 cw) |
| 309 | { |
| 310 | m_x87_cw = cw; |
| 311 | |
| 312 | /* Update the SoftFloat rounding mode */ |
| 313 | float_rounding_mode = x87_to_sf_rc[(m_x87_cw >> X87_CW_RC_SHIFT) & X87_CW_RC_MASK]; |
| 314 | } |
| 315 | |
| 316 | void i386_device::x87_reset() |
| 317 | { |
| 318 | x87_write_cw(0x0037f); |
| 319 | |
| 320 | m_x87_sw = 0; |
| 321 | m_x87_tw = 0xffff; |
| 322 | |
| 323 | // TODO: FEA=0, FDS=0, FIP=0 FOP=0 FCS=0 |
| 324 | m_x87_data_ptr = 0; |
| 325 | m_x87_inst_ptr = 0; |
| 326 | m_x87_opcode = 0; |
| 327 | } |
| 328 | |
| 329 | |
| 330 | /************************************* |
| 331 | * |
| 332 | * Core arithmetic |
| 333 | * |
| 334 | *************************************/ |
| 335 | |
| 336 | floatx80 i386_device::x87_add(floatx80 a, floatx80 b) |
| 337 | { |
| 338 | floatx80 result = { 0 }; |
| 339 | |
| 340 | switch ((m_x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK) |
| 341 | { |
| 342 | case X87_CW_PC_SINGLE: |
| 343 | { |
| 344 | float32 a32 = floatx80_to_float32(a); |
| 345 | float32 b32 = floatx80_to_float32(b); |
| 346 | result = float32_to_floatx80(float32_add(a32, b32)); |
| 347 | break; |
| 348 | } |
| 349 | case X87_CW_PC_DOUBLE: |
| 350 | { |
| 351 | float64 a64 = floatx80_to_float64(a); |
| 352 | float64 b64 = floatx80_to_float64(b); |
| 353 | result = float64_to_floatx80(float64_add(a64, b64)); |
| 354 | break; |
| 355 | } |
| 356 | case X87_CW_PC_EXTEND: |
| 357 | { |
| 358 | result = floatx80_add(a, b); |
| 359 | break; |
| 360 | } |
| 361 | } |
| 362 | |
| 363 | return result; |
| 364 | } |
| 365 | |
| 366 | floatx80 i386_device::x87_sub(floatx80 a, floatx80 b) |
| 367 | { |
| 368 | floatx80 result = { 0 }; |
| 369 | |
| 370 | switch ((m_x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK) |
| 371 | { |
| 372 | case X87_CW_PC_SINGLE: |
| 373 | { |
| 374 | float32 a32 = floatx80_to_float32(a); |
| 375 | float32 b32 = floatx80_to_float32(b); |
| 376 | result = float32_to_floatx80(float32_sub(a32, b32)); |
| 377 | break; |
| 378 | } |
| 379 | case X87_CW_PC_DOUBLE: |
| 380 | { |
| 381 | float64 a64 = floatx80_to_float64(a); |
| 382 | float64 b64 = floatx80_to_float64(b); |
| 383 | result = float64_to_floatx80(float64_sub(a64, b64)); |
| 384 | break; |
| 385 | } |
| 386 | case X87_CW_PC_EXTEND: |
| 387 | { |
| 388 | result = floatx80_sub(a, b); |
| 389 | break; |
| 390 | } |
| 391 | } |
| 392 | |
| 393 | return result; |
| 394 | } |
| 395 | |
| 396 | floatx80 i386_device::x87_mul(floatx80 a, floatx80 b) |
| 397 | { |
| 398 | floatx80 val = { 0 }; |
| 399 | |
| 400 | switch ((m_x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK) |
| 401 | { |
| 402 | case X87_CW_PC_SINGLE: |
| 403 | { |
| 404 | float32 a32 = floatx80_to_float32(a); |
| 405 | float32 b32 = floatx80_to_float32(b); |
| 406 | val = float32_to_floatx80(float32_mul(a32, b32)); |
| 407 | break; |
| 408 | } |
| 409 | case X87_CW_PC_DOUBLE: |
| 410 | { |
| 411 | float64 a64 = floatx80_to_float64(a); |
| 412 | float64 b64 = floatx80_to_float64(b); |
| 413 | val = float64_to_floatx80(float64_mul(a64, b64)); |
| 414 | break; |
| 415 | } |
| 416 | case X87_CW_PC_EXTEND: |
| 417 | { |
| 418 | val = floatx80_mul(a, b); |
| 419 | break; |
| 420 | } |
| 421 | } |
| 422 | |
| 423 | return val; |
| 424 | } |
| 425 | |
| 426 | |
| 427 | floatx80 i386_device::x87_div(floatx80 a, floatx80 b) |
| 428 | { |
| 429 | floatx80 val = { 0 }; |
| 430 | |
| 431 | switch ((m_x87_cw >> X87_CW_PC_SHIFT) & X87_CW_PC_MASK) |
| 432 | { |
| 433 | case X87_CW_PC_SINGLE: |
| 434 | { |
| 435 | float32 a32 = floatx80_to_float32(a); |
| 436 | float32 b32 = floatx80_to_float32(b); |
| 437 | val = float32_to_floatx80(float32_div(a32, b32)); |
| 438 | break; |
| 439 | } |
| 440 | case X87_CW_PC_DOUBLE: |
| 441 | { |
| 442 | float64 a64 = floatx80_to_float64(a); |
| 443 | float64 b64 = floatx80_to_float64(b); |
| 444 | val = float64_to_floatx80(float64_div(a64, b64)); |
| 445 | break; |
| 446 | } |
| 447 | case X87_CW_PC_EXTEND: |
| 448 | { |
| 449 | val = floatx80_div(a, b); |
| 450 | break; |
| 451 | } |
| 452 | } |
| 453 | return val; |
| 454 | } |
| 455 | |
| 456 | |
| 457 | /************************************* |
| 458 | * |
| 459 | * Instructions |
| 460 | * |
| 461 | *************************************/ |
| 462 | |
| 463 | /************************************* |
| 464 | * |
| 465 | * Add |
| 466 | * |
| 467 | *************************************/ |
| 468 | |
| 469 | void i386_device::x87_fadd_m32real(UINT8 modrm) |
| 470 | { |
| 471 | floatx80 result; |
| 472 | |
| 473 | UINT32 ea = GetEA(modrm, 0); |
| 474 | if (X87_IS_ST_EMPTY(0)) |
| 475 | { |
| 476 | x87_set_stack_underflow(); |
| 477 | result = fx80_inan; |
| 478 | } |
| 479 | else |
| 480 | { |
| 481 | UINT32 m32real = READ32(ea); |
| 482 | |
| 483 | floatx80 a = ST(0); |
| 484 | floatx80 b = float32_to_floatx80(m32real); |
| 485 | |
| 486 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 487 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 488 | { |
| 489 | m_x87_sw |= X87_SW_IE; |
| 490 | result = fx80_inan; |
| 491 | } |
| 492 | else |
| 493 | { |
| 494 | result = x87_add(a, b); |
| 495 | } |
| 496 | } |
| 497 | |
| 498 | if (x87_check_exceptions()) |
| 499 | x87_write_stack(0, result, TRUE); |
| 500 | |
| 501 | CYCLES(8); |
| 502 | } |
| 503 | |
| 504 | void i386_device::x87_fadd_m64real(UINT8 modrm) |
| 505 | { |
| 506 | floatx80 result; |
| 507 | |
| 508 | UINT32 ea = GetEA(modrm, 0); |
| 509 | if (X87_IS_ST_EMPTY(0)) |
| 510 | { |
| 511 | x87_set_stack_underflow(); |
| 512 | result = fx80_inan; |
| 513 | } |
| 514 | else |
| 515 | { |
| 516 | UINT64 m64real = READ64(ea); |
| 517 | |
| 518 | floatx80 a = ST(0); |
| 519 | floatx80 b = float64_to_floatx80(m64real); |
| 520 | |
| 521 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 522 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 523 | { |
| 524 | m_x87_sw |= X87_SW_IE; |
| 525 | result = fx80_inan; |
| 526 | } |
| 527 | else |
| 528 | { |
| 529 | result = x87_add(a, b); |
| 530 | } |
| 531 | } |
| 532 | |
| 533 | if (x87_check_exceptions()) |
| 534 | x87_write_stack(0, result, TRUE); |
| 535 | |
| 536 | CYCLES(8); |
| 537 | } |
| 538 | |
| 539 | void i386_device::x87_fadd_st_sti(UINT8 modrm) |
| 540 | { |
| 541 | floatx80 result; |
| 542 | int i = modrm & 7; |
| 543 | |
| 544 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 545 | { |
| 546 | x87_set_stack_underflow(); |
| 547 | result = fx80_inan; |
| 548 | } |
| 549 | else |
| 550 | { |
| 551 | floatx80 a = ST(0); |
| 552 | floatx80 b = ST(i); |
| 553 | |
| 554 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 555 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 556 | { |
| 557 | m_x87_sw |= X87_SW_IE; |
| 558 | result = fx80_inan; |
| 559 | } |
| 560 | else |
| 561 | { |
| 562 | result = x87_add(a, b); |
| 563 | } |
| 564 | } |
| 565 | |
| 566 | if (x87_check_exceptions()) |
| 567 | x87_write_stack(0, result, TRUE); |
| 568 | |
| 569 | CYCLES(8); |
| 570 | } |
| 571 | |
| 572 | void i386_device::x87_fadd_sti_st(UINT8 modrm) |
| 573 | { |
| 574 | floatx80 result; |
| 575 | int i = modrm & 7; |
| 576 | |
| 577 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 578 | { |
| 579 | x87_set_stack_underflow(); |
| 580 | result = fx80_inan; |
| 581 | } |
| 582 | else |
| 583 | { |
| 584 | floatx80 a = ST(0); |
| 585 | floatx80 b = ST(i); |
| 586 | |
| 587 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 588 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 589 | { |
| 590 | m_x87_sw |= X87_SW_IE; |
| 591 | result = fx80_inan; |
| 592 | } |
| 593 | else |
| 594 | { |
| 595 | result = x87_add(a, b); |
| 596 | } |
| 597 | } |
| 598 | |
| 599 | if (x87_check_exceptions()) |
| 600 | x87_write_stack(i, result, TRUE); |
| 601 | |
| 602 | CYCLES(8); |
| 603 | } |
| 604 | |
| 605 | void i386_device::x87_faddp(UINT8 modrm) |
| 606 | { |
| 607 | floatx80 result; |
| 608 | int i = modrm & 7; |
| 609 | |
| 610 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 611 | { |
| 612 | x87_set_stack_underflow(); |
| 613 | result = fx80_inan; |
| 614 | } |
| 615 | else |
| 616 | { |
| 617 | floatx80 a = ST(0); |
| 618 | floatx80 b = ST(i); |
| 619 | |
| 620 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 621 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 622 | { |
| 623 | m_x87_sw |= X87_SW_IE; |
| 624 | result = fx80_inan; |
| 625 | } |
| 626 | else |
| 627 | { |
| 628 | result = x87_add(a, b); |
| 629 | } |
| 630 | } |
| 631 | |
| 632 | if (x87_check_exceptions()) |
| 633 | { |
| 634 | x87_write_stack(i, result, TRUE); |
| 635 | x87_inc_stack(); |
| 636 | } |
| 637 | |
| 638 | CYCLES(8); |
| 639 | } |
| 640 | |
| 641 | void i386_device::x87_fiadd_m32int(UINT8 modrm) |
| 642 | { |
| 643 | floatx80 result; |
| 644 | |
| 645 | UINT32 ea = GetEA(modrm, 0); |
| 646 | if (X87_IS_ST_EMPTY(0)) |
| 647 | { |
| 648 | x87_set_stack_underflow(); |
| 649 | result = fx80_inan; |
| 650 | } |
| 651 | else |
| 652 | { |
| 653 | INT32 m32int = READ32(ea); |
| 654 | |
| 655 | floatx80 a = ST(0); |
| 656 | floatx80 b = int32_to_floatx80(m32int); |
| 657 | |
| 658 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 659 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 660 | { |
| 661 | m_x87_sw |= X87_SW_IE; |
| 662 | result = fx80_inan; |
| 663 | } |
| 664 | else |
| 665 | { |
| 666 | result = x87_add(a, b); |
| 667 | } |
| 668 | } |
| 669 | |
| 670 | if (x87_check_exceptions()) |
| 671 | x87_write_stack(0, result, TRUE); |
| 672 | |
| 673 | CYCLES(19); |
| 674 | } |
| 675 | |
| 676 | void i386_device::x87_fiadd_m16int(UINT8 modrm) |
| 677 | { |
| 678 | floatx80 result; |
| 679 | |
| 680 | UINT32 ea = GetEA(modrm, 0); |
| 681 | if (X87_IS_ST_EMPTY(0)) |
| 682 | { |
| 683 | x87_set_stack_underflow(); |
| 684 | result = fx80_inan; |
| 685 | } |
| 686 | else |
| 687 | { |
| 688 | INT16 m16int = READ16(ea); |
| 689 | |
| 690 | floatx80 a = ST(0); |
| 691 | floatx80 b = int32_to_floatx80(m16int); |
| 692 | |
| 693 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 694 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 695 | { |
| 696 | m_x87_sw |= X87_SW_IE; |
| 697 | result = fx80_inan; |
| 698 | } |
| 699 | else |
| 700 | { |
| 701 | result = x87_add(a, b); |
| 702 | } |
| 703 | } |
| 704 | |
| 705 | if (x87_check_exceptions()) |
| 706 | x87_write_stack(0, result, TRUE); |
| 707 | |
| 708 | CYCLES(20); |
| 709 | } |
| 710 | |
| 711 | |
| 712 | /************************************* |
| 713 | * |
| 714 | * Subtract |
| 715 | * |
| 716 | *************************************/ |
| 717 | |
| 718 | void i386_device::x87_fsub_m32real(UINT8 modrm) |
| 719 | { |
| 720 | floatx80 result; |
| 721 | |
| 722 | UINT32 ea = GetEA(modrm, 0); |
| 723 | if (X87_IS_ST_EMPTY(0)) |
| 724 | { |
| 725 | x87_set_stack_underflow(); |
| 726 | result = fx80_inan; |
| 727 | } |
| 728 | else |
| 729 | { |
| 730 | UINT32 m32real = READ32(ea); |
| 731 | |
| 732 | floatx80 a = ST(0); |
| 733 | floatx80 b = float32_to_floatx80(m32real); |
| 734 | |
| 735 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 736 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 737 | { |
| 738 | m_x87_sw |= X87_SW_IE; |
| 739 | result = fx80_inan; |
| 740 | } |
| 741 | else |
| 742 | { |
| 743 | result = x87_sub(a, b); |
| 744 | } |
| 745 | } |
| 746 | |
| 747 | if (x87_check_exceptions()) |
| 748 | x87_write_stack(0, result, TRUE); |
| 749 | |
| 750 | CYCLES(8); |
| 751 | } |
| 752 | |
| 753 | void i386_device::x87_fsub_m64real(UINT8 modrm) |
| 754 | { |
| 755 | floatx80 result; |
| 756 | |
| 757 | UINT32 ea = GetEA(modrm, 0); |
| 758 | if (X87_IS_ST_EMPTY(0)) |
| 759 | { |
| 760 | x87_set_stack_underflow(); |
| 761 | result = fx80_inan; |
| 762 | } |
| 763 | else |
| 764 | { |
| 765 | UINT64 m64real = READ64(ea); |
| 766 | |
| 767 | floatx80 a = ST(0); |
| 768 | floatx80 b = float64_to_floatx80(m64real); |
| 769 | |
| 770 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 771 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 772 | { |
| 773 | m_x87_sw |= X87_SW_IE; |
| 774 | result = fx80_inan; |
| 775 | } |
| 776 | else |
| 777 | { |
| 778 | result = x87_sub(a, b); |
| 779 | } |
| 780 | } |
| 781 | |
| 782 | if (x87_check_exceptions()) |
| 783 | x87_write_stack(0, result, TRUE); |
| 784 | |
| 785 | CYCLES(8); |
| 786 | } |
| 787 | |
| 788 | void i386_device::x87_fsub_st_sti(UINT8 modrm) |
| 789 | { |
| 790 | floatx80 result; |
| 791 | int i = modrm & 7; |
| 792 | |
| 793 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 794 | { |
| 795 | x87_set_stack_underflow(); |
| 796 | result = fx80_inan; |
| 797 | } |
| 798 | else |
| 799 | { |
| 800 | floatx80 a = ST(0); |
| 801 | floatx80 b = ST(i); |
| 802 | |
| 803 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 804 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 805 | { |
| 806 | m_x87_sw |= X87_SW_IE; |
| 807 | result = fx80_inan; |
| 808 | } |
| 809 | else |
| 810 | { |
| 811 | result = x87_sub(a, b); |
| 812 | } |
| 813 | } |
| 814 | |
| 815 | if (x87_check_exceptions()) |
| 816 | x87_write_stack(0, result, TRUE); |
| 817 | |
| 818 | CYCLES(8); |
| 819 | } |
| 820 | |
| 821 | void i386_device::x87_fsub_sti_st(UINT8 modrm) |
| 822 | { |
| 823 | floatx80 result; |
| 824 | int i = modrm & 7; |
| 825 | |
| 826 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 827 | { |
| 828 | x87_set_stack_underflow(); |
| 829 | result = fx80_inan; |
| 830 | } |
| 831 | else |
| 832 | { |
| 833 | floatx80 a = ST(i); |
| 834 | floatx80 b = ST(0); |
| 835 | |
| 836 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 837 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 838 | { |
| 839 | m_x87_sw |= X87_SW_IE; |
| 840 | result = fx80_inan; |
| 841 | } |
| 842 | else |
| 843 | { |
| 844 | result = x87_sub(a, b); |
| 845 | } |
| 846 | } |
| 847 | |
| 848 | if (x87_check_exceptions()) |
| 849 | x87_write_stack(i, result, TRUE); |
| 850 | |
| 851 | CYCLES(8); |
| 852 | } |
| 853 | |
| 854 | void i386_device::x87_fsubp(UINT8 modrm) |
| 855 | { |
| 856 | floatx80 result; |
| 857 | int i = modrm & 7; |
| 858 | |
| 859 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 860 | { |
| 861 | x87_set_stack_underflow(); |
| 862 | result = fx80_inan; |
| 863 | } |
| 864 | else |
| 865 | { |
| 866 | floatx80 a = ST(i); |
| 867 | floatx80 b = ST(0); |
| 868 | |
| 869 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 870 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 871 | { |
| 872 | m_x87_sw |= X87_SW_IE; |
| 873 | result = fx80_inan; |
| 874 | } |
| 875 | else |
| 876 | { |
| 877 | result = x87_sub(a, b); |
| 878 | } |
| 879 | } |
| 880 | |
| 881 | if (x87_check_exceptions()) |
| 882 | { |
| 883 | x87_write_stack(i, result, TRUE); |
| 884 | x87_inc_stack(); |
| 885 | } |
| 886 | |
| 887 | CYCLES(8); |
| 888 | } |
| 889 | |
| 890 | void i386_device::x87_fisub_m32int(UINT8 modrm) |
| 891 | { |
| 892 | floatx80 result; |
| 893 | |
| 894 | UINT32 ea = GetEA(modrm, 0); |
| 895 | if (X87_IS_ST_EMPTY(0)) |
| 896 | { |
| 897 | x87_set_stack_underflow(); |
| 898 | result = fx80_inan; |
| 899 | } |
| 900 | else |
| 901 | { |
| 902 | INT32 m32int = READ32(ea); |
| 903 | |
| 904 | floatx80 a = ST(0); |
| 905 | floatx80 b = int32_to_floatx80(m32int); |
| 906 | |
| 907 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 908 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 909 | { |
| 910 | m_x87_sw |= X87_SW_IE; |
| 911 | result = fx80_inan; |
| 912 | } |
| 913 | else |
| 914 | { |
| 915 | result = x87_sub(a, b); |
| 916 | } |
| 917 | } |
| 918 | |
| 919 | if (x87_check_exceptions()) |
| 920 | x87_write_stack(0, result, TRUE); |
| 921 | |
| 922 | CYCLES(19); |
| 923 | } |
| 924 | |
| 925 | void i386_device::x87_fisub_m16int(UINT8 modrm) |
| 926 | { |
| 927 | floatx80 result; |
| 928 | |
| 929 | UINT32 ea = GetEA(modrm, 0); |
| 930 | if (X87_IS_ST_EMPTY(0)) |
| 931 | { |
| 932 | x87_set_stack_underflow(); |
| 933 | result = fx80_inan; |
| 934 | } |
| 935 | else |
| 936 | { |
| 937 | INT16 m16int = READ16(ea); |
| 938 | |
| 939 | floatx80 a = ST(0); |
| 940 | floatx80 b = int32_to_floatx80(m16int); |
| 941 | |
| 942 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 943 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 944 | { |
| 945 | m_x87_sw |= X87_SW_IE; |
| 946 | result = fx80_inan; |
| 947 | } |
| 948 | else |
| 949 | { |
| 950 | result = x87_sub(a, b); |
| 951 | } |
| 952 | } |
| 953 | |
| 954 | if (x87_check_exceptions()) |
| 955 | x87_write_stack(0, result, TRUE); |
| 956 | |
| 957 | CYCLES(20); |
| 958 | } |
| 959 | |
| 960 | |
| 961 | /************************************* |
| 962 | * |
| 963 | * Reverse Subtract |
| 964 | * |
| 965 | *************************************/ |
| 966 | |
| 967 | void i386_device::x87_fsubr_m32real(UINT8 modrm) |
| 968 | { |
| 969 | floatx80 result; |
| 970 | |
| 971 | UINT32 ea = GetEA(modrm, 0); |
| 972 | if (X87_IS_ST_EMPTY(0)) |
| 973 | { |
| 974 | x87_set_stack_underflow(); |
| 975 | result = fx80_inan; |
| 976 | } |
| 977 | else |
| 978 | { |
| 979 | UINT32 m32real = READ32(ea); |
| 980 | |
| 981 | floatx80 a = float32_to_floatx80(m32real); |
| 982 | floatx80 b = ST(0); |
| 983 | |
| 984 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 985 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 986 | { |
| 987 | m_x87_sw |= X87_SW_IE; |
| 988 | result = fx80_inan; |
| 989 | } |
| 990 | else |
| 991 | { |
| 992 | result = x87_sub(a, b); |
| 993 | } |
| 994 | } |
| 995 | |
| 996 | if (x87_check_exceptions()) |
| 997 | x87_write_stack(0, result, TRUE); |
| 998 | |
| 999 | CYCLES(8); |
| 1000 | } |
| 1001 | |
| 1002 | void i386_device::x87_fsubr_m64real(UINT8 modrm) |
| 1003 | { |
| 1004 | floatx80 result; |
| 1005 | |
| 1006 | UINT32 ea = GetEA(modrm, 0); |
| 1007 | if (X87_IS_ST_EMPTY(0)) |
| 1008 | { |
| 1009 | x87_set_stack_underflow(); |
| 1010 | result = fx80_inan; |
| 1011 | } |
| 1012 | else |
| 1013 | { |
| 1014 | UINT64 m64real = READ64(ea); |
| 1015 | |
| 1016 | floatx80 a = float64_to_floatx80(m64real); |
| 1017 | floatx80 b = ST(0); |
| 1018 | |
| 1019 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1020 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 1021 | { |
| 1022 | m_x87_sw |= X87_SW_IE; |
| 1023 | result = fx80_inan; |
| 1024 | } |
| 1025 | else |
| 1026 | { |
| 1027 | result = x87_sub(a, b); |
| 1028 | } |
| 1029 | } |
| 1030 | |
| 1031 | if (x87_check_exceptions()) |
| 1032 | x87_write_stack(0, result, TRUE); |
| 1033 | |
| 1034 | CYCLES(8); |
| 1035 | } |
| 1036 | |
| 1037 | void i386_device::x87_fsubr_st_sti(UINT8 modrm) |
| 1038 | { |
| 1039 | floatx80 result; |
| 1040 | int i = modrm & 7; |
| 1041 | |
| 1042 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1043 | { |
| 1044 | x87_set_stack_underflow(); |
| 1045 | result = fx80_inan; |
| 1046 | } |
| 1047 | else |
| 1048 | { |
| 1049 | floatx80 a = ST(i); |
| 1050 | floatx80 b = ST(0); |
| 1051 | |
| 1052 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1053 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 1054 | { |
| 1055 | m_x87_sw |= X87_SW_IE; |
| 1056 | result = fx80_inan; |
| 1057 | } |
| 1058 | else |
| 1059 | { |
| 1060 | result = x87_sub(a, b); |
| 1061 | } |
| 1062 | } |
| 1063 | |
| 1064 | if (x87_check_exceptions()) |
| 1065 | x87_write_stack(0, result, TRUE); |
| 1066 | |
| 1067 | CYCLES(8); |
| 1068 | } |
| 1069 | |
| 1070 | void i386_device::x87_fsubr_sti_st(UINT8 modrm) |
| 1071 | { |
| 1072 | floatx80 result; |
| 1073 | int i = modrm & 7; |
| 1074 | |
| 1075 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1076 | { |
| 1077 | x87_set_stack_underflow(); |
| 1078 | result = fx80_inan; |
| 1079 | } |
| 1080 | else |
| 1081 | { |
| 1082 | floatx80 a = ST(0); |
| 1083 | floatx80 b = ST(i); |
| 1084 | |
| 1085 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1086 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 1087 | { |
| 1088 | m_x87_sw |= X87_SW_IE; |
| 1089 | result = fx80_inan; |
| 1090 | } |
| 1091 | else |
| 1092 | { |
| 1093 | result = x87_sub(a, b); |
| 1094 | } |
| 1095 | } |
| 1096 | |
| 1097 | if (x87_check_exceptions()) |
| 1098 | x87_write_stack(i, result, TRUE); |
| 1099 | |
| 1100 | CYCLES(8); |
| 1101 | } |
| 1102 | |
| 1103 | void i386_device::x87_fsubrp(UINT8 modrm) |
| 1104 | { |
| 1105 | floatx80 result; |
| 1106 | int i = modrm & 7; |
| 1107 | |
| 1108 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1109 | { |
| 1110 | x87_set_stack_underflow(); |
| 1111 | result = fx80_inan; |
| 1112 | } |
| 1113 | else |
| 1114 | { |
| 1115 | floatx80 a = ST(0); |
| 1116 | floatx80 b = ST(i); |
| 1117 | |
| 1118 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1119 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 1120 | { |
| 1121 | m_x87_sw |= X87_SW_IE; |
| 1122 | result = fx80_inan; |
| 1123 | } |
| 1124 | else |
| 1125 | { |
| 1126 | result = x87_sub(a, b); |
| 1127 | } |
| 1128 | } |
| 1129 | |
| 1130 | if (x87_check_exceptions()) |
| 1131 | { |
| 1132 | x87_write_stack(i, result, TRUE); |
| 1133 | x87_inc_stack(); |
| 1134 | } |
| 1135 | |
| 1136 | CYCLES(8); |
| 1137 | } |
| 1138 | |
| 1139 | void i386_device::x87_fisubr_m32int(UINT8 modrm) |
| 1140 | { |
| 1141 | floatx80 result; |
| 1142 | |
| 1143 | UINT32 ea = GetEA(modrm, 0); |
| 1144 | if (X87_IS_ST_EMPTY(0)) |
| 1145 | { |
| 1146 | x87_set_stack_underflow(); |
| 1147 | result = fx80_inan; |
| 1148 | } |
| 1149 | else |
| 1150 | { |
| 1151 | INT32 m32int = READ32(ea); |
| 1152 | |
| 1153 | floatx80 a = int32_to_floatx80(m32int); |
| 1154 | floatx80 b = ST(0); |
| 1155 | |
| 1156 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1157 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 1158 | { |
| 1159 | m_x87_sw |= X87_SW_IE; |
| 1160 | result = fx80_inan; |
| 1161 | } |
| 1162 | else |
| 1163 | { |
| 1164 | result = x87_sub(a, b); |
| 1165 | } |
| 1166 | } |
| 1167 | |
| 1168 | if (x87_check_exceptions()) |
| 1169 | x87_write_stack(0, result, TRUE); |
| 1170 | |
| 1171 | CYCLES(19); |
| 1172 | } |
| 1173 | |
| 1174 | void i386_device::x87_fisubr_m16int(UINT8 modrm) |
| 1175 | { |
| 1176 | floatx80 result; |
| 1177 | |
| 1178 | UINT32 ea = GetEA(modrm, 0); |
| 1179 | if (X87_IS_ST_EMPTY(0)) |
| 1180 | { |
| 1181 | x87_set_stack_underflow(); |
| 1182 | result = fx80_inan; |
| 1183 | } |
| 1184 | else |
| 1185 | { |
| 1186 | INT16 m16int = READ16(ea); |
| 1187 | |
| 1188 | floatx80 a = int32_to_floatx80(m16int); |
| 1189 | floatx80 b = ST(0); |
| 1190 | |
| 1191 | if ((floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1192 | || (floatx80_is_inf(a) && floatx80_is_inf(b) && ((a.high ^ b.high) & 0x8000))) |
| 1193 | { |
| 1194 | m_x87_sw |= X87_SW_IE; |
| 1195 | result = fx80_inan; |
| 1196 | } |
| 1197 | else |
| 1198 | { |
| 1199 | result = x87_sub(a, b); |
| 1200 | } |
| 1201 | } |
| 1202 | |
| 1203 | if (x87_check_exceptions()) |
| 1204 | x87_write_stack(0, result, TRUE); |
| 1205 | |
| 1206 | CYCLES(20); |
| 1207 | } |
| 1208 | |
| 1209 | |
| 1210 | /************************************* |
| 1211 | * |
| 1212 | * Divide |
| 1213 | * |
| 1214 | *************************************/ |
| 1215 | |
| 1216 | void i386_device::x87_fdiv_m32real(UINT8 modrm) |
| 1217 | { |
| 1218 | floatx80 result; |
| 1219 | |
| 1220 | UINT32 ea = GetEA(modrm, 0); |
| 1221 | if (X87_IS_ST_EMPTY(0)) |
| 1222 | { |
| 1223 | x87_set_stack_underflow(); |
| 1224 | result = fx80_inan; |
| 1225 | } |
| 1226 | else |
| 1227 | { |
| 1228 | UINT32 m32real = READ32(ea); |
| 1229 | |
| 1230 | floatx80 a = ST(0); |
| 1231 | floatx80 b = float32_to_floatx80(m32real); |
| 1232 | |
| 1233 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1234 | { |
| 1235 | m_x87_sw |= X87_SW_IE; |
| 1236 | result = fx80_inan; |
| 1237 | } |
| 1238 | else |
| 1239 | { |
| 1240 | result = x87_div(a, b); |
| 1241 | } |
| 1242 | } |
| 1243 | |
| 1244 | if (x87_check_exceptions()) |
| 1245 | x87_write_stack(0, result, TRUE); |
| 1246 | |
| 1247 | // 73, 62, 35 |
| 1248 | CYCLES(73); |
| 1249 | } |
| 1250 | |
| 1251 | void i386_device::x87_fdiv_m64real(UINT8 modrm) |
| 1252 | { |
| 1253 | floatx80 result; |
| 1254 | |
| 1255 | UINT32 ea = GetEA(modrm, 0); |
| 1256 | if (X87_IS_ST_EMPTY(0)) |
| 1257 | { |
| 1258 | x87_set_stack_underflow(); |
| 1259 | result = fx80_inan; |
| 1260 | } |
| 1261 | else |
| 1262 | { |
| 1263 | UINT64 m64real = READ64(ea); |
| 1264 | |
| 1265 | floatx80 a = ST(0); |
| 1266 | floatx80 b = float64_to_floatx80(m64real); |
| 1267 | |
| 1268 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1269 | { |
| 1270 | m_x87_sw |= X87_SW_IE; |
| 1271 | result = fx80_inan; |
| 1272 | } |
| 1273 | else |
| 1274 | { |
| 1275 | result = x87_div(a, b); |
| 1276 | } |
| 1277 | } |
| 1278 | |
| 1279 | if (x87_check_exceptions()) |
| 1280 | x87_write_stack(0, result, TRUE); |
| 1281 | |
| 1282 | // 73, 62, 35 |
| 1283 | CYCLES(73); |
| 1284 | } |
| 1285 | |
| 1286 | void i386_device::x87_fdiv_st_sti(UINT8 modrm) |
| 1287 | { |
| 1288 | int i = modrm & 7; |
| 1289 | floatx80 result; |
| 1290 | |
| 1291 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1292 | { |
| 1293 | x87_set_stack_underflow(); |
| 1294 | result = fx80_inan; |
| 1295 | } |
| 1296 | else |
| 1297 | { |
| 1298 | floatx80 a = ST(0); |
| 1299 | floatx80 b = ST(i); |
| 1300 | |
| 1301 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1302 | { |
| 1303 | m_x87_sw |= X87_SW_IE; |
| 1304 | result = fx80_inan; |
| 1305 | } |
| 1306 | else |
| 1307 | { |
| 1308 | result = x87_div(a, b); |
| 1309 | } |
| 1310 | } |
| 1311 | |
| 1312 | if (x87_check_exceptions()) |
| 1313 | { |
| 1314 | x87_write_stack(0, result, TRUE); |
| 1315 | } |
| 1316 | |
| 1317 | // 73, 62, 35 |
| 1318 | CYCLES(73); |
| 1319 | } |
| 1320 | |
| 1321 | void i386_device::x87_fdiv_sti_st(UINT8 modrm) |
| 1322 | { |
| 1323 | int i = modrm & 7; |
| 1324 | floatx80 result; |
| 1325 | |
| 1326 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1327 | { |
| 1328 | x87_set_stack_underflow(); |
| 1329 | result = fx80_inan; |
| 1330 | } |
| 1331 | else |
| 1332 | { |
| 1333 | floatx80 a = ST(i); |
| 1334 | floatx80 b = ST(0); |
| 1335 | |
| 1336 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1337 | { |
| 1338 | m_x87_sw |= X87_SW_IE; |
| 1339 | result = fx80_inan; |
| 1340 | } |
| 1341 | else |
| 1342 | { |
| 1343 | result = x87_div(a, b); |
| 1344 | } |
| 1345 | } |
| 1346 | |
| 1347 | if (x87_check_exceptions()) |
| 1348 | { |
| 1349 | x87_write_stack(i, result, TRUE); |
| 1350 | } |
| 1351 | |
| 1352 | // 73, 62, 35 |
| 1353 | CYCLES(73); |
| 1354 | } |
| 1355 | |
| 1356 | void i386_device::x87_fdivp(UINT8 modrm) |
| 1357 | { |
| 1358 | int i = modrm & 7; |
| 1359 | floatx80 result; |
| 1360 | |
| 1361 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1362 | { |
| 1363 | x87_set_stack_underflow(); |
| 1364 | result = fx80_inan; |
| 1365 | } |
| 1366 | else |
| 1367 | { |
| 1368 | floatx80 a = ST(i); |
| 1369 | floatx80 b = ST(0); |
| 1370 | |
| 1371 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1372 | { |
| 1373 | m_x87_sw |= X87_SW_IE; |
| 1374 | result = fx80_inan; |
| 1375 | } |
| 1376 | else |
| 1377 | { |
| 1378 | result = x87_div(a, b); |
| 1379 | } |
| 1380 | } |
| 1381 | |
| 1382 | if (x87_check_exceptions()) |
| 1383 | { |
| 1384 | x87_write_stack(i, result, TRUE); |
| 1385 | x87_inc_stack(); |
| 1386 | } |
| 1387 | |
| 1388 | // 73, 62, 35 |
| 1389 | CYCLES(73); |
| 1390 | } |
| 1391 | |
| 1392 | void i386_device::x87_fidiv_m32int(UINT8 modrm) |
| 1393 | { |
| 1394 | floatx80 result; |
| 1395 | |
| 1396 | UINT32 ea = GetEA(modrm, 0); |
| 1397 | if (X87_IS_ST_EMPTY(0)) |
| 1398 | { |
| 1399 | x87_set_stack_underflow(); |
| 1400 | result = fx80_inan; |
| 1401 | } |
| 1402 | else |
| 1403 | { |
| 1404 | INT32 m32int = READ32(ea); |
| 1405 | |
| 1406 | floatx80 a = ST(0); |
| 1407 | floatx80 b = int32_to_floatx80(m32int); |
| 1408 | |
| 1409 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1410 | { |
| 1411 | m_x87_sw |= X87_SW_IE; |
| 1412 | result = fx80_inan; |
| 1413 | } |
| 1414 | else |
| 1415 | { |
| 1416 | result = x87_div(a, b); |
| 1417 | } |
| 1418 | } |
| 1419 | |
| 1420 | if (x87_check_exceptions()) |
| 1421 | x87_write_stack(0, result, TRUE); |
| 1422 | |
| 1423 | // 73, 62, 35 |
| 1424 | CYCLES(73); |
| 1425 | } |
| 1426 | |
| 1427 | void i386_device::x87_fidiv_m16int(UINT8 modrm) |
| 1428 | { |
| 1429 | floatx80 result; |
| 1430 | |
| 1431 | UINT32 ea = GetEA(modrm, 0); |
| 1432 | if (X87_IS_ST_EMPTY(0)) |
| 1433 | { |
| 1434 | x87_set_stack_underflow(); |
| 1435 | result = fx80_inan; |
| 1436 | } |
| 1437 | else |
| 1438 | { |
| 1439 | INT16 m16int = READ32(ea); |
| 1440 | |
| 1441 | floatx80 a = ST(0); |
| 1442 | floatx80 b = int32_to_floatx80(m16int); |
| 1443 | |
| 1444 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1445 | { |
| 1446 | m_x87_sw |= X87_SW_IE; |
| 1447 | result = fx80_inan; |
| 1448 | } |
| 1449 | else |
| 1450 | { |
| 1451 | result = x87_div(a, b); |
| 1452 | } |
| 1453 | } |
| 1454 | |
| 1455 | if (x87_check_exceptions()) |
| 1456 | x87_write_stack(0, result, TRUE); |
| 1457 | |
| 1458 | // 73, 62, 35 |
| 1459 | CYCLES(73); |
| 1460 | } |
| 1461 | |
| 1462 | |
| 1463 | /************************************* |
| 1464 | * |
| 1465 | * Reverse Divide |
| 1466 | * |
| 1467 | *************************************/ |
| 1468 | |
| 1469 | void i386_device::x87_fdivr_m32real(UINT8 modrm) |
| 1470 | { |
| 1471 | floatx80 result; |
| 1472 | |
| 1473 | UINT32 ea = GetEA(modrm, 0); |
| 1474 | if (X87_IS_ST_EMPTY(0)) |
| 1475 | { |
| 1476 | x87_set_stack_underflow(); |
| 1477 | result = fx80_inan; |
| 1478 | } |
| 1479 | else |
| 1480 | { |
| 1481 | UINT32 m32real = READ32(ea); |
| 1482 | |
| 1483 | floatx80 a = float32_to_floatx80(m32real); |
| 1484 | floatx80 b = ST(0); |
| 1485 | |
| 1486 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1487 | { |
| 1488 | m_x87_sw |= X87_SW_IE; |
| 1489 | result = fx80_inan; |
| 1490 | } |
| 1491 | else |
| 1492 | { |
| 1493 | result = x87_div(a, b); |
| 1494 | } |
| 1495 | } |
| 1496 | |
| 1497 | if (x87_check_exceptions()) |
| 1498 | x87_write_stack(0, result, TRUE); |
| 1499 | |
| 1500 | // 73, 62, 35 |
| 1501 | CYCLES(73); |
| 1502 | } |
| 1503 | |
| 1504 | void i386_device::x87_fdivr_m64real(UINT8 modrm) |
| 1505 | { |
| 1506 | floatx80 result; |
| 1507 | |
| 1508 | UINT32 ea = GetEA(modrm, 0); |
| 1509 | if (X87_IS_ST_EMPTY(0)) |
| 1510 | { |
| 1511 | x87_set_stack_underflow(); |
| 1512 | result = fx80_inan; |
| 1513 | } |
| 1514 | else |
| 1515 | { |
| 1516 | UINT64 m64real = READ64(ea); |
| 1517 | |
| 1518 | floatx80 a = float64_to_floatx80(m64real); |
| 1519 | floatx80 b = ST(0); |
| 1520 | |
| 1521 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1522 | { |
| 1523 | m_x87_sw |= X87_SW_IE; |
| 1524 | result = fx80_inan; |
| 1525 | } |
| 1526 | else |
| 1527 | { |
| 1528 | result = x87_div(a, b); |
| 1529 | } |
| 1530 | } |
| 1531 | |
| 1532 | if (x87_check_exceptions()) |
| 1533 | x87_write_stack(0, result, TRUE); |
| 1534 | |
| 1535 | // 73, 62, 35 |
| 1536 | CYCLES(73); |
| 1537 | } |
| 1538 | |
| 1539 | void i386_device::x87_fdivr_st_sti(UINT8 modrm) |
| 1540 | { |
| 1541 | int i = modrm & 7; |
| 1542 | floatx80 result; |
| 1543 | |
| 1544 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1545 | { |
| 1546 | x87_set_stack_underflow(); |
| 1547 | result = fx80_inan; |
| 1548 | } |
| 1549 | else |
| 1550 | { |
| 1551 | floatx80 a = ST(i); |
| 1552 | floatx80 b = ST(0); |
| 1553 | |
| 1554 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1555 | { |
| 1556 | m_x87_sw |= X87_SW_IE; |
| 1557 | result = fx80_inan; |
| 1558 | } |
| 1559 | else |
| 1560 | { |
| 1561 | result = x87_div(a, b); |
| 1562 | } |
| 1563 | } |
| 1564 | |
| 1565 | if (x87_check_exceptions()) |
| 1566 | { |
| 1567 | x87_write_stack(0, result, TRUE); |
| 1568 | } |
| 1569 | |
| 1570 | // 73, 62, 35 |
| 1571 | CYCLES(73); |
| 1572 | } |
| 1573 | |
| 1574 | void i386_device::x87_fdivr_sti_st(UINT8 modrm) |
| 1575 | { |
| 1576 | int i = modrm & 7; |
| 1577 | floatx80 result; |
| 1578 | |
| 1579 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1580 | { |
| 1581 | x87_set_stack_underflow(); |
| 1582 | result = fx80_inan; |
| 1583 | } |
| 1584 | else |
| 1585 | { |
| 1586 | floatx80 a = ST(0); |
| 1587 | floatx80 b = ST(i); |
| 1588 | |
| 1589 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1590 | { |
| 1591 | m_x87_sw |= X87_SW_IE; |
| 1592 | result = fx80_inan; |
| 1593 | } |
| 1594 | else |
| 1595 | { |
| 1596 | result = x87_div(a, b); |
| 1597 | } |
| 1598 | } |
| 1599 | |
| 1600 | if (x87_check_exceptions()) |
| 1601 | { |
| 1602 | x87_write_stack(i, result, TRUE); |
| 1603 | } |
| 1604 | |
| 1605 | // 73, 62, 35 |
| 1606 | CYCLES(73); |
| 1607 | } |
| 1608 | |
| 1609 | void i386_device::x87_fdivrp(UINT8 modrm) |
| 1610 | { |
| 1611 | int i = modrm & 7; |
| 1612 | floatx80 result; |
| 1613 | |
| 1614 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1615 | { |
| 1616 | x87_set_stack_underflow(); |
| 1617 | result = fx80_inan; |
| 1618 | } |
| 1619 | else |
| 1620 | { |
| 1621 | floatx80 a = ST(0); |
| 1622 | floatx80 b = ST(i); |
| 1623 | |
| 1624 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1625 | { |
| 1626 | m_x87_sw |= X87_SW_IE; |
| 1627 | result = fx80_inan; |
| 1628 | } |
| 1629 | else |
| 1630 | { |
| 1631 | result = x87_div(a, b); |
| 1632 | } |
| 1633 | } |
| 1634 | |
| 1635 | if (x87_check_exceptions()) |
| 1636 | { |
| 1637 | x87_write_stack(i, result, TRUE); |
| 1638 | x87_inc_stack(); |
| 1639 | } |
| 1640 | |
| 1641 | // 73, 62, 35 |
| 1642 | CYCLES(73); |
| 1643 | } |
| 1644 | |
| 1645 | |
| 1646 | void i386_device::x87_fidivr_m32int(UINT8 modrm) |
| 1647 | { |
| 1648 | floatx80 result; |
| 1649 | |
| 1650 | UINT32 ea = GetEA(modrm, 0); |
| 1651 | if (X87_IS_ST_EMPTY(0)) |
| 1652 | { |
| 1653 | x87_set_stack_underflow(); |
| 1654 | result = fx80_inan; |
| 1655 | } |
| 1656 | else |
| 1657 | { |
| 1658 | INT32 m32int = READ32(ea); |
| 1659 | |
| 1660 | floatx80 a = int32_to_floatx80(m32int); |
| 1661 | floatx80 b = ST(0); |
| 1662 | |
| 1663 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1664 | { |
| 1665 | m_x87_sw |= X87_SW_IE; |
| 1666 | result = fx80_inan; |
| 1667 | } |
| 1668 | else |
| 1669 | { |
| 1670 | result = x87_div(a, b); |
| 1671 | } |
| 1672 | } |
| 1673 | |
| 1674 | if (x87_check_exceptions()) |
| 1675 | x87_write_stack(0, result, TRUE); |
| 1676 | |
| 1677 | // 73, 62, 35 |
| 1678 | CYCLES(73); |
| 1679 | } |
| 1680 | |
| 1681 | void i386_device::x87_fidivr_m16int(UINT8 modrm) |
| 1682 | { |
| 1683 | floatx80 result; |
| 1684 | |
| 1685 | UINT32 ea = GetEA(modrm, 0); |
| 1686 | if (X87_IS_ST_EMPTY(0)) |
| 1687 | { |
| 1688 | x87_set_stack_underflow(); |
| 1689 | result = fx80_inan; |
| 1690 | } |
| 1691 | else |
| 1692 | { |
| 1693 | INT16 m16int = READ32(ea); |
| 1694 | |
| 1695 | floatx80 a = int32_to_floatx80(m16int); |
| 1696 | floatx80 b = ST(0); |
| 1697 | |
| 1698 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1699 | { |
| 1700 | m_x87_sw |= X87_SW_IE; |
| 1701 | result = fx80_inan; |
| 1702 | } |
| 1703 | else |
| 1704 | { |
| 1705 | result = x87_div(a, b); |
| 1706 | } |
| 1707 | } |
| 1708 | |
| 1709 | if (x87_check_exceptions()) |
| 1710 | x87_write_stack(0, result, TRUE); |
| 1711 | |
| 1712 | // 73, 62, 35 |
| 1713 | CYCLES(73); |
| 1714 | } |
| 1715 | |
| 1716 | |
| 1717 | /************************************* |
| 1718 | * |
| 1719 | * Multiply |
| 1720 | * |
| 1721 | *************************************/ |
| 1722 | |
| 1723 | void i386_device::x87_fmul_m32real(UINT8 modrm) |
| 1724 | { |
| 1725 | floatx80 result; |
| 1726 | |
| 1727 | UINT32 ea = GetEA(modrm, 0); |
| 1728 | if (X87_IS_ST_EMPTY(0)) |
| 1729 | { |
| 1730 | x87_set_stack_underflow(); |
| 1731 | result = fx80_inan; |
| 1732 | } |
| 1733 | else |
| 1734 | { |
| 1735 | UINT32 m32real = READ32(ea); |
| 1736 | |
| 1737 | floatx80 a = ST(0); |
| 1738 | floatx80 b = float32_to_floatx80(m32real); |
| 1739 | |
| 1740 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1741 | { |
| 1742 | m_x87_sw |= X87_SW_IE; |
| 1743 | result = fx80_inan; |
| 1744 | } |
| 1745 | else |
| 1746 | { |
| 1747 | result = x87_mul(a, b); |
| 1748 | } |
| 1749 | } |
| 1750 | |
| 1751 | if (x87_check_exceptions()) |
| 1752 | x87_write_stack(0, result, TRUE); |
| 1753 | |
| 1754 | CYCLES(11); |
| 1755 | } |
| 1756 | |
| 1757 | void i386_device::x87_fmul_m64real(UINT8 modrm) |
| 1758 | { |
| 1759 | floatx80 result; |
| 1760 | |
| 1761 | UINT32 ea = GetEA(modrm, 0); |
| 1762 | if (X87_IS_ST_EMPTY(0)) |
| 1763 | { |
| 1764 | x87_set_stack_underflow(); |
| 1765 | result = fx80_inan; |
| 1766 | } |
| 1767 | else |
| 1768 | { |
| 1769 | UINT64 m64real = READ64(ea); |
| 1770 | |
| 1771 | floatx80 a = ST(0); |
| 1772 | floatx80 b = float64_to_floatx80(m64real); |
| 1773 | |
| 1774 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1775 | { |
| 1776 | m_x87_sw |= X87_SW_IE; |
| 1777 | result = fx80_inan; |
| 1778 | } |
| 1779 | else |
| 1780 | { |
| 1781 | result = x87_mul(a, b); |
| 1782 | } |
| 1783 | } |
| 1784 | |
| 1785 | if (x87_check_exceptions()) |
| 1786 | x87_write_stack(0, result, TRUE); |
| 1787 | |
| 1788 | CYCLES(14); |
| 1789 | } |
| 1790 | |
| 1791 | void i386_device::x87_fmul_st_sti(UINT8 modrm) |
| 1792 | { |
| 1793 | floatx80 result; |
| 1794 | int i = modrm & 7; |
| 1795 | |
| 1796 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1797 | { |
| 1798 | x87_set_stack_underflow(); |
| 1799 | result = fx80_inan; |
| 1800 | } |
| 1801 | else |
| 1802 | { |
| 1803 | floatx80 a = ST(0); |
| 1804 | floatx80 b = ST(i); |
| 1805 | |
| 1806 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1807 | { |
| 1808 | m_x87_sw |= X87_SW_IE; |
| 1809 | result = fx80_inan; |
| 1810 | } |
| 1811 | else |
| 1812 | { |
| 1813 | result = x87_mul(a, b); |
| 1814 | } |
| 1815 | } |
| 1816 | |
| 1817 | if (x87_check_exceptions()) |
| 1818 | x87_write_stack(0, result, TRUE); |
| 1819 | |
| 1820 | CYCLES(16); |
| 1821 | } |
| 1822 | |
| 1823 | void i386_device::x87_fmul_sti_st(UINT8 modrm) |
| 1824 | { |
| 1825 | floatx80 result; |
| 1826 | int i = modrm & 7; |
| 1827 | |
| 1828 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1829 | { |
| 1830 | x87_set_stack_underflow(); |
| 1831 | result = fx80_inan; |
| 1832 | } |
| 1833 | else |
| 1834 | { |
| 1835 | floatx80 a = ST(0); |
| 1836 | floatx80 b = ST(i); |
| 1837 | |
| 1838 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1839 | { |
| 1840 | m_x87_sw |= X87_SW_IE; |
| 1841 | result = fx80_inan; |
| 1842 | } |
| 1843 | else |
| 1844 | { |
| 1845 | result = x87_mul(a, b); |
| 1846 | } |
| 1847 | } |
| 1848 | |
| 1849 | if (x87_check_exceptions()) |
| 1850 | x87_write_stack(i, result, TRUE); |
| 1851 | |
| 1852 | CYCLES(16); |
| 1853 | } |
| 1854 | |
| 1855 | void i386_device::x87_fmulp(UINT8 modrm) |
| 1856 | { |
| 1857 | floatx80 result; |
| 1858 | int i = modrm & 7; |
| 1859 | |
| 1860 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 1861 | { |
| 1862 | x87_set_stack_underflow(); |
| 1863 | result = fx80_inan; |
| 1864 | } |
| 1865 | else |
| 1866 | { |
| 1867 | floatx80 a = ST(0); |
| 1868 | floatx80 b = ST(i); |
| 1869 | |
| 1870 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1871 | { |
| 1872 | m_x87_sw |= X87_SW_IE; |
| 1873 | result = fx80_inan; |
| 1874 | } |
| 1875 | else |
| 1876 | { |
| 1877 | result = x87_mul(a, b); |
| 1878 | } |
| 1879 | } |
| 1880 | |
| 1881 | if (x87_check_exceptions()) |
| 1882 | { |
| 1883 | x87_write_stack(i, result, TRUE); |
| 1884 | x87_inc_stack(); |
| 1885 | } |
| 1886 | |
| 1887 | CYCLES(16); |
| 1888 | } |
| 1889 | |
| 1890 | void i386_device::x87_fimul_m32int(UINT8 modrm) |
| 1891 | { |
| 1892 | floatx80 result; |
| 1893 | |
| 1894 | UINT32 ea = GetEA(modrm, 0); |
| 1895 | if (X87_IS_ST_EMPTY(0)) |
| 1896 | { |
| 1897 | x87_set_stack_underflow(); |
| 1898 | result = fx80_inan; |
| 1899 | } |
| 1900 | else |
| 1901 | { |
| 1902 | INT32 m32int = READ32(ea); |
| 1903 | |
| 1904 | floatx80 a = ST(0); |
| 1905 | floatx80 b = int32_to_floatx80(m32int); |
| 1906 | |
| 1907 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1908 | { |
| 1909 | m_x87_sw |= X87_SW_IE; |
| 1910 | result = fx80_inan; |
| 1911 | } |
| 1912 | else |
| 1913 | { |
| 1914 | result = x87_mul(a, b); |
| 1915 | } |
| 1916 | } |
| 1917 | |
| 1918 | if (x87_check_exceptions()) |
| 1919 | x87_write_stack(0, result, TRUE); |
| 1920 | |
| 1921 | CYCLES(22); |
| 1922 | } |
| 1923 | |
| 1924 | void i386_device::x87_fimul_m16int(UINT8 modrm) |
| 1925 | { |
| 1926 | floatx80 result; |
| 1927 | |
| 1928 | UINT32 ea = GetEA(modrm, 0); |
| 1929 | if (X87_IS_ST_EMPTY(0)) |
| 1930 | { |
| 1931 | x87_set_stack_underflow(); |
| 1932 | result = fx80_inan; |
| 1933 | } |
| 1934 | else |
| 1935 | { |
| 1936 | INT16 m16int = READ16(ea); |
| 1937 | |
| 1938 | floatx80 a = ST(0); |
| 1939 | floatx80 b = int32_to_floatx80(m16int); |
| 1940 | |
| 1941 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 1942 | { |
| 1943 | m_x87_sw |= X87_SW_IE; |
| 1944 | result = fx80_inan; |
| 1945 | } |
| 1946 | else |
| 1947 | { |
| 1948 | result = x87_mul(a, b); |
| 1949 | } |
| 1950 | } |
| 1951 | |
| 1952 | if (x87_check_exceptions()) |
| 1953 | x87_write_stack(0, result, TRUE); |
| 1954 | |
| 1955 | CYCLES(22); |
| 1956 | } |
| 1957 | |
| 1958 | |
| 1959 | /************************************* |
| 1960 | * |
| 1961 | * Miscellaneous arithmetic |
| 1962 | * |
| 1963 | *************************************/ |
| 1964 | |
| 1965 | void i386_device::x87_fprem(UINT8 modrm) |
| 1966 | { |
| 1967 | floatx80 result; |
| 1968 | |
| 1969 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 1970 | { |
| 1971 | x87_set_stack_underflow(); |
| 1972 | result = fx80_inan; |
| 1973 | } |
| 1974 | else |
| 1975 | { |
| 1976 | floatx80 a = ST(0); |
| 1977 | floatx80 b = ST(1); |
| 1978 | |
| 1979 | m_x87_sw &= ~X87_SW_C0; |
| 1980 | |
| 1981 | // TODO: Implement Cx bits |
| 1982 | result = floatx80_rem(a, b); |
| 1983 | } |
| 1984 | |
| 1985 | if (x87_check_exceptions()) |
| 1986 | x87_write_stack(0, result, TRUE); |
| 1987 | |
| 1988 | CYCLES(84); |
| 1989 | } |
| 1990 | |
| 1991 | void i386_device::x87_fprem1(UINT8 modrm) |
| 1992 | { |
| 1993 | floatx80 result; |
| 1994 | |
| 1995 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 1996 | { |
| 1997 | x87_set_stack_underflow(); |
| 1998 | result = fx80_inan; |
| 1999 | } |
| 2000 | else |
| 2001 | { |
| 2002 | floatx80 a = ST(0); |
| 2003 | floatx80 b = ST(1); |
| 2004 | |
| 2005 | m_x87_sw &= ~X87_SW_C0; |
| 2006 | |
| 2007 | // TODO: Implement Cx bits |
| 2008 | result = floatx80_rem(a, b); |
| 2009 | } |
| 2010 | |
| 2011 | if (x87_check_exceptions()) |
| 2012 | x87_write_stack(0, result, TRUE); |
| 2013 | |
| 2014 | CYCLES(94); |
| 2015 | } |
| 2016 | |
| 2017 | void i386_device::x87_fsqrt(UINT8 modrm) |
| 2018 | { |
| 2019 | floatx80 result; |
| 2020 | |
| 2021 | if (X87_IS_ST_EMPTY(0)) |
| 2022 | { |
| 2023 | x87_set_stack_underflow(); |
| 2024 | result = fx80_inan; |
| 2025 | } |
| 2026 | else |
| 2027 | { |
| 2028 | floatx80 value = ST(0); |
| 2029 | |
| 2030 | if ((!floatx80_is_zero(value) && (value.high & 0x8000)) || |
| 2031 | floatx80_is_denormal(value)) |
| 2032 | { |
| 2033 | m_x87_sw |= X87_SW_IE; |
| 2034 | result = fx80_inan; |
| 2035 | } |
| 2036 | else |
| 2037 | { |
| 2038 | result = floatx80_sqrt(value); |
| 2039 | } |
| 2040 | } |
| 2041 | |
| 2042 | if (x87_check_exceptions()) |
| 2043 | x87_write_stack(0, result, TRUE); |
| 2044 | |
| 2045 | CYCLES(8); |
| 2046 | } |
| 2047 | |
| 2048 | /************************************* |
| 2049 | * |
| 2050 | * Trigonometric |
| 2051 | * |
| 2052 | *************************************/ |
| 2053 | |
| 2054 | void i386_device::x87_f2xm1(UINT8 modrm) |
| 2055 | { |
| 2056 | floatx80 result; |
| 2057 | |
| 2058 | if (X87_IS_ST_EMPTY(0)) |
| 2059 | { |
| 2060 | x87_set_stack_underflow(); |
| 2061 | result = fx80_inan; |
| 2062 | } |
| 2063 | else |
| 2064 | { |
| 2065 | // TODO: Inaccurate |
| 2066 | double x = fx80_to_double(ST(0)); |
| 2067 | double res = pow(2.0, x) - 1; |
| 2068 | result = double_to_fx80(res); |
| 2069 | } |
| 2070 | |
| 2071 | if (x87_check_exceptions()) |
| 2072 | { |
| 2073 | x87_write_stack(0, result, TRUE); |
| 2074 | } |
| 2075 | |
| 2076 | CYCLES(242); |
| 2077 | } |
| 2078 | |
| 2079 | void i386_device::x87_fyl2x(UINT8 modrm) |
| 2080 | { |
| 2081 | floatx80 result; |
| 2082 | |
| 2083 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 2084 | { |
| 2085 | x87_set_stack_underflow(); |
| 2086 | result = fx80_inan; |
| 2087 | } |
| 2088 | else |
| 2089 | { |
| 2090 | floatx80 x = ST(0); |
| 2091 | floatx80 y = ST(1); |
| 2092 | |
| 2093 | if (x.high & 0x8000) |
| 2094 | { |
| 2095 | m_x87_sw |= X87_SW_IE; |
| 2096 | result = fx80_inan; |
| 2097 | } |
| 2098 | else |
| 2099 | { |
| 2100 | // TODO: Inaccurate |
| 2101 | double d64 = fx80_to_double(x); |
| 2102 | double l2x = log(d64)/log(2.0); |
| 2103 | result = floatx80_mul(double_to_fx80(l2x), y); |
| 2104 | } |
| 2105 | } |
| 2106 | |
| 2107 | if (x87_check_exceptions()) |
| 2108 | { |
| 2109 | x87_write_stack(1, result, TRUE); |
| 2110 | x87_inc_stack(); |
| 2111 | } |
| 2112 | |
| 2113 | CYCLES(250); |
| 2114 | } |
| 2115 | |
| 2116 | void i386_device::x87_fyl2xp1(UINT8 modrm) |
| 2117 | { |
| 2118 | floatx80 result; |
| 2119 | |
| 2120 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 2121 | { |
| 2122 | x87_set_stack_underflow(); |
| 2123 | result = fx80_inan; |
| 2124 | } |
| 2125 | else |
| 2126 | { |
| 2127 | floatx80 x = ST(0); |
| 2128 | floatx80 y = ST(1); |
| 2129 | |
| 2130 | // TODO: Inaccurate |
| 2131 | double d64 = fx80_to_double(x); |
| 2132 | double l2x1 = log(d64 + 1.0)/log(2.0); |
| 2133 | result = floatx80_mul(double_to_fx80(l2x1), y); |
| 2134 | } |
| 2135 | |
| 2136 | if (x87_check_exceptions()) |
| 2137 | { |
| 2138 | x87_write_stack(1, result, TRUE); |
| 2139 | x87_inc_stack(); |
| 2140 | } |
| 2141 | |
| 2142 | CYCLES(313); |
| 2143 | } |
| 2144 | |
| 2145 | void i386_device::x87_fptan(UINT8 modrm) |
| 2146 | { |
| 2147 | floatx80 result1, result2; |
| 2148 | |
| 2149 | if (X87_IS_ST_EMPTY(0)) |
| 2150 | { |
| 2151 | x87_set_stack_underflow(); |
| 2152 | result1 = fx80_inan; |
| 2153 | result2 = fx80_inan; |
| 2154 | } |
| 2155 | else if (!X87_IS_ST_EMPTY(7)) |
| 2156 | { |
| 2157 | x87_set_stack_overflow(); |
| 2158 | result1 = fx80_inan; |
| 2159 | result2 = fx80_inan; |
| 2160 | } |
| 2161 | else |
| 2162 | { |
| 2163 | result1 = ST(0); |
| 2164 | result2 = fx80_one; |
| 2165 | |
| 2166 | #if 0 // TODO: Function produces bad values |
| 2167 | if (floatx80_ftan(result1) != -1) |
| 2168 | m_x87_sw &= ~X87_SW_C2; |
| 2169 | else |
| 2170 | m_x87_sw |= X87_SW_C2; |
| 2171 | #else |
| 2172 | double x = fx80_to_double(result1); |
| 2173 | x = tan(x); |
| 2174 | result1 = double_to_fx80(x); |
| 2175 | |
| 2176 | m_x87_sw &= ~X87_SW_C2; |
| 2177 | #endif |
| 2178 | } |
| 2179 | |
| 2180 | if (x87_check_exceptions()) |
| 2181 | { |
| 2182 | x87_write_stack(0, result1, TRUE); |
| 2183 | x87_dec_stack(); |
| 2184 | x87_write_stack(0, result2, TRUE); |
| 2185 | } |
| 2186 | |
| 2187 | CYCLES(244); |
| 2188 | } |
| 2189 | |
| 2190 | void i386_device::x87_fpatan(UINT8 modrm) |
| 2191 | { |
| 2192 | floatx80 result; |
| 2193 | |
| 2194 | if (X87_IS_ST_EMPTY(0)) |
| 2195 | { |
| 2196 | x87_set_stack_underflow(); |
| 2197 | result = fx80_inan; |
| 2198 | } |
| 2199 | else |
| 2200 | { |
| 2201 | // TODO: Inaccurate |
| 2202 | double val = atan(fx80_to_double(ST(1)) / fx80_to_double(ST(0))); |
| 2203 | result = double_to_fx80(val); |
| 2204 | } |
| 2205 | |
| 2206 | if (x87_check_exceptions()) |
| 2207 | { |
| 2208 | x87_write_stack(1, result, TRUE); |
| 2209 | x87_inc_stack(); |
| 2210 | } |
| 2211 | |
| 2212 | CYCLES(289); |
| 2213 | } |
| 2214 | |
| 2215 | void i386_device::x87_fsin(UINT8 modrm) |
| 2216 | { |
| 2217 | floatx80 result; |
| 2218 | |
| 2219 | if (X87_IS_ST_EMPTY(0)) |
| 2220 | { |
| 2221 | x87_set_stack_underflow(); |
| 2222 | result = fx80_inan; |
| 2223 | } |
| 2224 | else |
| 2225 | { |
| 2226 | result = ST(0); |
| 2227 | |
| 2228 | #if 0 // TODO: Function produces bad values |
| 2229 | if (floatx80_fsin(result) != -1) |
| 2230 | m_x87_sw &= ~X87_SW_C2; |
| 2231 | else |
| 2232 | m_x87_sw |= X87_SW_C2; |
| 2233 | #else |
| 2234 | double x = fx80_to_double(result); |
| 2235 | x = sin(x); |
| 2236 | result = double_to_fx80(x); |
| 2237 | |
| 2238 | m_x87_sw &= ~X87_SW_C2; |
| 2239 | #endif |
| 2240 | } |
| 2241 | |
| 2242 | if (x87_check_exceptions()) |
| 2243 | x87_write_stack(0, result, TRUE); |
| 2244 | |
| 2245 | CYCLES(241); |
| 2246 | } |
| 2247 | |
| 2248 | void i386_device::x87_fcos(UINT8 modrm) |
| 2249 | { |
| 2250 | floatx80 result; |
| 2251 | |
| 2252 | if (X87_IS_ST_EMPTY(0)) |
| 2253 | { |
| 2254 | x87_set_stack_underflow(); |
| 2255 | result = fx80_inan; |
| 2256 | } |
| 2257 | else |
| 2258 | { |
| 2259 | result = ST(0); |
| 2260 | |
| 2261 | #if 0 // TODO: Function produces bad values |
| 2262 | if (floatx80_fcos(result) != -1) |
| 2263 | m_x87_sw &= ~X87_SW_C2; |
| 2264 | else |
| 2265 | m_x87_sw |= X87_SW_C2; |
| 2266 | #else |
| 2267 | double x = fx80_to_double(result); |
| 2268 | x = cos(x); |
| 2269 | result = double_to_fx80(x); |
| 2270 | |
| 2271 | m_x87_sw &= ~X87_SW_C2; |
| 2272 | #endif |
| 2273 | } |
| 2274 | |
| 2275 | if (x87_check_exceptions()) |
| 2276 | x87_write_stack(0, result, TRUE); |
| 2277 | |
| 2278 | CYCLES(241); |
| 2279 | } |
| 2280 | |
| 2281 | void i386_device::x87_fsincos(UINT8 modrm) |
| 2282 | { |
| 2283 | floatx80 s_result, c_result; |
| 2284 | |
| 2285 | if (X87_IS_ST_EMPTY(0)) |
| 2286 | { |
| 2287 | x87_set_stack_underflow(); |
| 2288 | s_result = c_result = fx80_inan; |
| 2289 | } |
| 2290 | else if (!X87_IS_ST_EMPTY(7)) |
| 2291 | { |
| 2292 | x87_set_stack_overflow(); |
| 2293 | s_result = c_result = fx80_inan; |
| 2294 | } |
| 2295 | else |
| 2296 | { |
| 2297 | extern int sf_fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a); |
| 2298 | |
| 2299 | s_result = c_result = ST(0); |
| 2300 | |
| 2301 | #if 0 // TODO: Function produces bad values |
| 2302 | if (sf_fsincos(s_result, &s_result, &c_result) != -1) |
| 2303 | m_x87_sw &= ~X87_SW_C2; |
| 2304 | else |
| 2305 | m_x87_sw |= X87_SW_C2; |
| 2306 | #else |
| 2307 | double s = fx80_to_double(s_result); |
| 2308 | double c = fx80_to_double(c_result); |
| 2309 | s = sin(s); |
| 2310 | c = cos(c); |
| 2311 | |
| 2312 | s_result = double_to_fx80(s); |
| 2313 | c_result = double_to_fx80(c); |
| 2314 | |
| 2315 | m_x87_sw &= ~X87_SW_C2; |
| 2316 | #endif |
| 2317 | } |
| 2318 | |
| 2319 | if (x87_check_exceptions()) |
| 2320 | { |
| 2321 | x87_write_stack(0, s_result, TRUE); |
| 2322 | x87_dec_stack(); |
| 2323 | x87_write_stack(0, c_result, TRUE); |
| 2324 | } |
| 2325 | |
| 2326 | CYCLES(291); |
| 2327 | } |
| 2328 | |
| 2329 | |
| 2330 | /************************************* |
| 2331 | * |
| 2332 | * Load data |
| 2333 | * |
| 2334 | *************************************/ |
| 2335 | |
| 2336 | void i386_device::x87_fld_m32real(UINT8 modrm) |
| 2337 | { |
| 2338 | floatx80 value; |
| 2339 | |
| 2340 | UINT32 ea = GetEA(modrm, 0); |
| 2341 | if (x87_dec_stack()) |
| 2342 | { |
| 2343 | UINT32 m32real = READ32(ea); |
| 2344 | |
| 2345 | value = float32_to_floatx80(m32real); |
| 2346 | |
| 2347 | m_x87_sw &= ~X87_SW_C1; |
| 2348 | |
| 2349 | if (floatx80_is_signaling_nan(value) || floatx80_is_denormal(value)) |
| 2350 | { |
| 2351 | m_x87_sw |= X87_SW_IE; |
| 2352 | value = fx80_inan; |
| 2353 | } |
| 2354 | } |
| 2355 | else |
| 2356 | { |
| 2357 | value = fx80_inan; |
| 2358 | } |
| 2359 | |
| 2360 | if (x87_check_exceptions()) |
| 2361 | x87_write_stack(0, value, TRUE); |
| 2362 | |
| 2363 | CYCLES(3); |
| 2364 | } |
| 2365 | |
| 2366 | void i386_device::x87_fld_m64real(UINT8 modrm) |
| 2367 | { |
| 2368 | floatx80 value; |
| 2369 | |
| 2370 | UINT32 ea = GetEA(modrm, 0); |
| 2371 | if (x87_dec_stack()) |
| 2372 | { |
| 2373 | UINT64 m64real = READ64(ea); |
| 2374 | |
| 2375 | value = float64_to_floatx80(m64real); |
| 2376 | |
| 2377 | m_x87_sw &= ~X87_SW_C1; |
| 2378 | |
| 2379 | if (floatx80_is_signaling_nan(value) || floatx80_is_denormal(value)) |
| 2380 | { |
| 2381 | m_x87_sw |= X87_SW_IE; |
| 2382 | value = fx80_inan; |
| 2383 | } |
| 2384 | } |
| 2385 | else |
| 2386 | { |
| 2387 | value = fx80_inan; |
| 2388 | } |
| 2389 | |
| 2390 | if (x87_check_exceptions()) |
| 2391 | x87_write_stack(0, value, TRUE); |
| 2392 | |
| 2393 | CYCLES(3); |
| 2394 | } |
| 2395 | |
| 2396 | void i386_device::x87_fld_m80real(UINT8 modrm) |
| 2397 | { |
| 2398 | floatx80 value; |
| 2399 | |
| 2400 | UINT32 ea = GetEA(modrm, 0); |
| 2401 | if (x87_dec_stack()) |
| 2402 | { |
| 2403 | m_x87_sw &= ~X87_SW_C1; |
| 2404 | value = READ80(ea); |
| 2405 | } |
| 2406 | else |
| 2407 | { |
| 2408 | value = fx80_inan; |
| 2409 | } |
| 2410 | |
| 2411 | if (x87_check_exceptions()) |
| 2412 | x87_write_stack(0, value, TRUE); |
| 2413 | |
| 2414 | CYCLES(6); |
| 2415 | } |
| 2416 | |
| 2417 | void i386_device::x87_fld_sti(UINT8 modrm) |
| 2418 | { |
| 2419 | floatx80 value; |
| 2420 | |
| 2421 | if (x87_dec_stack()) |
| 2422 | { |
| 2423 | m_x87_sw &= ~X87_SW_C1; |
| 2424 | value = ST((modrm + 1) & 7); |
| 2425 | } |
| 2426 | else |
| 2427 | { |
| 2428 | value = fx80_inan; |
| 2429 | } |
| 2430 | |
| 2431 | if (x87_check_exceptions()) |
| 2432 | x87_write_stack(0, value, TRUE); |
| 2433 | |
| 2434 | CYCLES(4); |
| 2435 | } |
| 2436 | |
| 2437 | void i386_device::x87_fild_m16int(UINT8 modrm) |
| 2438 | { |
| 2439 | floatx80 value; |
| 2440 | |
| 2441 | UINT32 ea = GetEA(modrm, 0); |
| 2442 | if (!x87_dec_stack()) |
| 2443 | { |
| 2444 | value = fx80_inan; |
| 2445 | } |
| 2446 | else |
| 2447 | { |
| 2448 | m_x87_sw &= ~X87_SW_C1; |
| 2449 | |
| 2450 | INT16 m16int = READ16(ea); |
| 2451 | value = int32_to_floatx80(m16int); |
| 2452 | } |
| 2453 | |
| 2454 | if (x87_check_exceptions()) |
| 2455 | x87_write_stack(0, value, TRUE); |
| 2456 | |
| 2457 | CYCLES(13); |
| 2458 | } |
| 2459 | |
| 2460 | void i386_device::x87_fild_m32int(UINT8 modrm) |
| 2461 | { |
| 2462 | floatx80 value; |
| 2463 | |
| 2464 | UINT32 ea = GetEA(modrm, 0); |
| 2465 | if (!x87_dec_stack()) |
| 2466 | { |
| 2467 | value = fx80_inan; |
| 2468 | } |
| 2469 | else |
| 2470 | { |
| 2471 | m_x87_sw &= ~X87_SW_C1; |
| 2472 | |
| 2473 | INT32 m32int = READ32(ea); |
| 2474 | value = int32_to_floatx80(m32int); |
| 2475 | } |
| 2476 | |
| 2477 | if (x87_check_exceptions()) |
| 2478 | x87_write_stack(0, value, TRUE); |
| 2479 | |
| 2480 | CYCLES(9); |
| 2481 | } |
| 2482 | |
| 2483 | void i386_device::x87_fild_m64int(UINT8 modrm) |
| 2484 | { |
| 2485 | floatx80 value; |
| 2486 | |
| 2487 | UINT32 ea = GetEA(modrm, 0); |
| 2488 | if (!x87_dec_stack()) |
| 2489 | { |
| 2490 | value = fx80_inan; |
| 2491 | } |
| 2492 | else |
| 2493 | { |
| 2494 | m_x87_sw &= ~X87_SW_C1; |
| 2495 | |
| 2496 | INT64 m64int = READ64(ea); |
| 2497 | value = int64_to_floatx80(m64int); |
| 2498 | } |
| 2499 | |
| 2500 | if (x87_check_exceptions()) |
| 2501 | x87_write_stack(0, value, TRUE); |
| 2502 | |
| 2503 | CYCLES(10); |
| 2504 | } |
| 2505 | |
| 2506 | void i386_device::x87_fbld(UINT8 modrm) |
| 2507 | { |
| 2508 | floatx80 value; |
| 2509 | |
| 2510 | UINT32 ea = GetEA(modrm, 0); |
| 2511 | if (!x87_dec_stack()) |
| 2512 | { |
| 2513 | value = fx80_inan; |
| 2514 | } |
| 2515 | else |
| 2516 | { |
| 2517 | m_x87_sw &= ~X87_SW_C1; |
| 2518 | |
| 2519 | UINT64 m64val = 0; |
| 2520 | UINT16 sign; |
| 2521 | |
| 2522 | value = READ80(ea); |
| 2523 | |
| 2524 | sign = value.high & 0x8000; |
| 2525 | m64val += ((value.high >> 4) & 0xf) * 10; |
| 2526 | m64val += ((value.high >> 0) & 0xf); |
| 2527 | |
| 2528 | for (int i = 60; i >= 0; i -= 4) |
| 2529 | { |
| 2530 | m64val *= 10; |
| 2531 | m64val += (value.low >> i) & 0xf; |
| 2532 | } |
| 2533 | |
| 2534 | value = int64_to_floatx80(m64val); |
| 2535 | value.high |= sign; |
| 2536 | } |
| 2537 | |
| 2538 | if (x87_check_exceptions()) |
| 2539 | x87_write_stack(0, value, TRUE); |
| 2540 | |
| 2541 | CYCLES(75); |
| 2542 | } |
| 2543 | |
| 2544 | |
| 2545 | /************************************* |
| 2546 | * |
| 2547 | * Store data |
| 2548 | * |
| 2549 | *************************************/ |
| 2550 | |
| 2551 | void i386_device::x87_fst_m32real(UINT8 modrm) |
| 2552 | { |
| 2553 | floatx80 value; |
| 2554 | |
| 2555 | UINT32 ea = GetEA(modrm, 1); |
| 2556 | if (X87_IS_ST_EMPTY(0)) |
| 2557 | { |
| 2558 | x87_set_stack_underflow(); |
| 2559 | value = fx80_inan; |
| 2560 | } |
| 2561 | else |
| 2562 | { |
| 2563 | m_x87_sw &= ~X87_SW_C1; |
| 2564 | value = ST(0); |
| 2565 | } |
| 2566 | |
| 2567 | if (x87_check_exceptions()) |
| 2568 | { |
| 2569 | UINT32 m32real = floatx80_to_float32(value); |
| 2570 | WRITE32(ea, m32real); |
| 2571 | } |
| 2572 | |
| 2573 | CYCLES(7); |
| 2574 | } |
| 2575 | |
| 2576 | void i386_device::x87_fst_m64real(UINT8 modrm) |
| 2577 | { |
| 2578 | floatx80 value; |
| 2579 | |
| 2580 | UINT32 ea = GetEA(modrm, 1); |
| 2581 | if (X87_IS_ST_EMPTY(0)) |
| 2582 | { |
| 2583 | x87_set_stack_underflow(); |
| 2584 | value = fx80_inan; |
| 2585 | } |
| 2586 | else |
| 2587 | { |
| 2588 | m_x87_sw &= ~X87_SW_C1; |
| 2589 | value = ST(0); |
| 2590 | } |
| 2591 | |
| 2592 | if (x87_check_exceptions()) |
| 2593 | { |
| 2594 | UINT64 m64real = floatx80_to_float64(value); |
| 2595 | WRITE64(ea, m64real); |
| 2596 | } |
| 2597 | |
| 2598 | CYCLES(8); |
| 2599 | } |
| 2600 | |
| 2601 | void i386_device::x87_fst_sti(UINT8 modrm) |
| 2602 | { |
| 2603 | int i = modrm & 7; |
| 2604 | floatx80 value; |
| 2605 | |
| 2606 | if (X87_IS_ST_EMPTY(0)) |
| 2607 | { |
| 2608 | x87_set_stack_underflow(); |
| 2609 | value = fx80_inan; |
| 2610 | } |
| 2611 | else |
| 2612 | { |
| 2613 | m_x87_sw &= ~X87_SW_C1; |
| 2614 | value = ST(0); |
| 2615 | } |
| 2616 | |
| 2617 | if (x87_check_exceptions()) |
| 2618 | x87_write_stack(i, value, TRUE); |
| 2619 | |
| 2620 | CYCLES(3); |
| 2621 | } |
| 2622 | |
| 2623 | void i386_device::x87_fstp_m32real(UINT8 modrm) |
| 2624 | { |
| 2625 | floatx80 value; |
| 2626 | |
| 2627 | UINT32 ea = GetEA(modrm, 1); |
| 2628 | if (X87_IS_ST_EMPTY(0)) |
| 2629 | { |
| 2630 | x87_set_stack_underflow(); |
| 2631 | value = fx80_inan; |
| 2632 | } |
| 2633 | else |
| 2634 | { |
| 2635 | m_x87_sw &= ~X87_SW_C1; |
| 2636 | value = ST(0); |
| 2637 | } |
| 2638 | |
| 2639 | if (x87_check_exceptions()) |
| 2640 | { |
| 2641 | UINT32 m32real = floatx80_to_float32(value); |
| 2642 | WRITE32(ea, m32real); |
| 2643 | x87_inc_stack(); |
| 2644 | } |
| 2645 | |
| 2646 | CYCLES(7); |
| 2647 | } |
| 2648 | |
| 2649 | void i386_device::x87_fstp_m64real(UINT8 modrm) |
| 2650 | { |
| 2651 | floatx80 value; |
| 2652 | |
| 2653 | if (X87_IS_ST_EMPTY(0)) |
| 2654 | { |
| 2655 | x87_set_stack_underflow(); |
| 2656 | value = fx80_inan; |
| 2657 | } |
| 2658 | else |
| 2659 | { |
| 2660 | m_x87_sw &= ~X87_SW_C1; |
| 2661 | value = ST(0); |
| 2662 | } |
| 2663 | |
| 2664 | |
| 2665 | UINT32 ea = GetEA(modrm, 1); |
| 2666 | if (x87_check_exceptions()) |
| 2667 | { |
| 2668 | UINT64 m64real = floatx80_to_float64(value); |
| 2669 | WRITE64(ea, m64real); |
| 2670 | x87_inc_stack(); |
| 2671 | } |
| 2672 | |
| 2673 | CYCLES(8); |
| 2674 | } |
| 2675 | |
| 2676 | void i386_device::x87_fstp_m80real(UINT8 modrm) |
| 2677 | { |
| 2678 | floatx80 value; |
| 2679 | |
| 2680 | if (X87_IS_ST_EMPTY(0)) |
| 2681 | { |
| 2682 | x87_set_stack_underflow(); |
| 2683 | value = fx80_inan; |
| 2684 | } |
| 2685 | else |
| 2686 | { |
| 2687 | m_x87_sw &= ~X87_SW_C1; |
| 2688 | value = ST(0); |
| 2689 | } |
| 2690 | |
| 2691 | UINT32 ea = GetEA(modrm, 1); |
| 2692 | if (x87_check_exceptions()) |
| 2693 | { |
| 2694 | WRITE80(ea, value); |
| 2695 | x87_inc_stack(); |
| 2696 | } |
| 2697 | |
| 2698 | CYCLES(6); |
| 2699 | } |
| 2700 | |
| 2701 | void i386_device::x87_fstp_sti(UINT8 modrm) |
| 2702 | { |
| 2703 | int i = modrm & 7; |
| 2704 | floatx80 value; |
| 2705 | |
| 2706 | if (X87_IS_ST_EMPTY(0)) |
| 2707 | { |
| 2708 | x87_set_stack_underflow(); |
| 2709 | value = fx80_inan; |
| 2710 | } |
| 2711 | else |
| 2712 | { |
| 2713 | m_x87_sw &= ~X87_SW_C1; |
| 2714 | value = ST(0); |
| 2715 | } |
| 2716 | |
| 2717 | if (x87_check_exceptions()) |
| 2718 | { |
| 2719 | x87_write_stack(i, value, TRUE); |
| 2720 | x87_inc_stack(); |
| 2721 | } |
| 2722 | |
| 2723 | CYCLES(3); |
| 2724 | } |
| 2725 | |
| 2726 | void i386_device::x87_fist_m16int(UINT8 modrm) |
| 2727 | { |
| 2728 | INT16 m16int; |
| 2729 | |
| 2730 | if (X87_IS_ST_EMPTY(0)) |
| 2731 | { |
| 2732 | x87_set_stack_underflow(); |
| 2733 | m16int = -32768; |
| 2734 | } |
| 2735 | else |
| 2736 | { |
| 2737 | floatx80 fx80 = floatx80_round_to_int(ST(0)); |
| 2738 | |
| 2739 | floatx80 lowerLim = int32_to_floatx80(-32768); |
| 2740 | floatx80 upperLim = int32_to_floatx80(32767); |
| 2741 | |
| 2742 | m_x87_sw &= ~X87_SW_C1; |
| 2743 | |
| 2744 | if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) |
| 2745 | m16int = floatx80_to_int32(fx80); |
| 2746 | else |
| 2747 | m16int = -32768; |
| 2748 | } |
| 2749 | |
| 2750 | UINT32 ea = GetEA(modrm, 1); |
| 2751 | if (x87_check_exceptions()) |
| 2752 | { |
| 2753 | WRITE16(ea, m16int); |
| 2754 | } |
| 2755 | |
| 2756 | CYCLES(29); |
| 2757 | } |
| 2758 | |
| 2759 | void i386_device::x87_fist_m32int(UINT8 modrm) |
| 2760 | { |
| 2761 | INT32 m32int; |
| 2762 | |
| 2763 | if (X87_IS_ST_EMPTY(0)) |
| 2764 | { |
| 2765 | x87_set_stack_underflow(); |
| 2766 | m32int = 0x80000000; |
| 2767 | } |
| 2768 | else |
| 2769 | { |
| 2770 | floatx80 fx80 = floatx80_round_to_int(ST(0)); |
| 2771 | |
| 2772 | floatx80 lowerLim = int32_to_floatx80(0x80000000); |
| 2773 | floatx80 upperLim = int32_to_floatx80(0x7fffffff); |
| 2774 | |
| 2775 | m_x87_sw &= ~X87_SW_C1; |
| 2776 | |
| 2777 | if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) |
| 2778 | m32int = floatx80_to_int32(fx80); |
| 2779 | else |
| 2780 | m32int = 0x80000000; |
| 2781 | } |
| 2782 | |
| 2783 | UINT32 ea = GetEA(modrm, 1); |
| 2784 | if (x87_check_exceptions()) |
| 2785 | { |
| 2786 | WRITE32(ea, m32int); |
| 2787 | } |
| 2788 | |
| 2789 | CYCLES(28); |
| 2790 | } |
| 2791 | |
| 2792 | void i386_device::x87_fistp_m16int(UINT8 modrm) |
| 2793 | { |
| 2794 | INT16 m16int; |
| 2795 | |
| 2796 | if (X87_IS_ST_EMPTY(0)) |
| 2797 | { |
| 2798 | x87_set_stack_underflow(); |
| 2799 | m16int = (UINT16)0x8000; |
| 2800 | } |
| 2801 | else |
| 2802 | { |
| 2803 | floatx80 fx80 = floatx80_round_to_int(ST(0)); |
| 2804 | |
| 2805 | floatx80 lowerLim = int32_to_floatx80(-32768); |
| 2806 | floatx80 upperLim = int32_to_floatx80(32767); |
| 2807 | |
| 2808 | m_x87_sw &= ~X87_SW_C1; |
| 2809 | |
| 2810 | if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) |
| 2811 | m16int = floatx80_to_int32(fx80); |
| 2812 | else |
| 2813 | m16int = (UINT16)0x8000; |
| 2814 | } |
| 2815 | |
| 2816 | UINT32 ea = GetEA(modrm, 1); |
| 2817 | if (x87_check_exceptions()) |
| 2818 | { |
| 2819 | WRITE16(ea, m16int); |
| 2820 | x87_inc_stack(); |
| 2821 | } |
| 2822 | |
| 2823 | CYCLES(29); |
| 2824 | } |
| 2825 | |
| 2826 | void i386_device::x87_fistp_m32int(UINT8 modrm) |
| 2827 | { |
| 2828 | INT32 m32int; |
| 2829 | |
| 2830 | if (X87_IS_ST_EMPTY(0)) |
| 2831 | { |
| 2832 | x87_set_stack_underflow(); |
| 2833 | m32int = 0x80000000; |
| 2834 | } |
| 2835 | else |
| 2836 | { |
| 2837 | floatx80 fx80 = floatx80_round_to_int(ST(0)); |
| 2838 | |
| 2839 | floatx80 lowerLim = int32_to_floatx80(0x80000000); |
| 2840 | floatx80 upperLim = int32_to_floatx80(0x7fffffff); |
| 2841 | |
| 2842 | m_x87_sw &= ~X87_SW_C1; |
| 2843 | |
| 2844 | if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) |
| 2845 | m32int = floatx80_to_int32(fx80); |
| 2846 | else |
| 2847 | m32int = 0x80000000; |
| 2848 | } |
| 2849 | |
| 2850 | UINT32 ea = GetEA(modrm, 1); |
| 2851 | if (x87_check_exceptions()) |
| 2852 | { |
| 2853 | WRITE32(ea, m32int); |
| 2854 | x87_inc_stack(); |
| 2855 | } |
| 2856 | |
| 2857 | CYCLES(29); |
| 2858 | } |
| 2859 | |
| 2860 | void i386_device::x87_fistp_m64int(UINT8 modrm) |
| 2861 | { |
| 2862 | INT64 m64int; |
| 2863 | |
| 2864 | if (X87_IS_ST_EMPTY(0)) |
| 2865 | { |
| 2866 | x87_set_stack_underflow(); |
| 2867 | m64int = U64(0x8000000000000000); |
| 2868 | } |
| 2869 | else |
| 2870 | { |
| 2871 | floatx80 fx80 = floatx80_round_to_int(ST(0)); |
| 2872 | |
| 2873 | floatx80 lowerLim = int64_to_floatx80(U64(0x8000000000000000)); |
| 2874 | floatx80 upperLim = int64_to_floatx80(U64(0x7fffffffffffffff)); |
| 2875 | |
| 2876 | m_x87_sw &= ~X87_SW_C1; |
| 2877 | |
| 2878 | if (!floatx80_lt(fx80, lowerLim) && floatx80_le(fx80, upperLim)) |
| 2879 | m64int = floatx80_to_int64(fx80); |
| 2880 | else |
| 2881 | m64int = U64(0x8000000000000000); |
| 2882 | } |
| 2883 | |
| 2884 | UINT32 ea = GetEA(modrm, 1); |
| 2885 | if (x87_check_exceptions()) |
| 2886 | { |
| 2887 | WRITE64(ea, m64int); |
| 2888 | x87_inc_stack(); |
| 2889 | } |
| 2890 | |
| 2891 | CYCLES(29); |
| 2892 | } |
| 2893 | |
| 2894 | void i386_device::x87_fbstp(UINT8 modrm) |
| 2895 | { |
| 2896 | floatx80 result; |
| 2897 | |
| 2898 | if (X87_IS_ST_EMPTY(0)) |
| 2899 | { |
| 2900 | x87_set_stack_underflow(); |
| 2901 | result = fx80_inan; |
| 2902 | } |
| 2903 | else |
| 2904 | { |
| 2905 | UINT64 u64 = floatx80_to_int64(floatx80_abs(ST(0))); |
| 2906 | result.low = 0; |
| 2907 | |
| 2908 | for (int i = 0; i < 64; i += 4) |
| 2909 | { |
| 2910 | result.low += (u64 % 10) << i; |
| 2911 | u64 /= 10; |
| 2912 | } |
| 2913 | |
| 2914 | result.high = (u64 % 10); |
| 2915 | result.high += ((u64 / 10) % 10) << 4; |
| 2916 | result.high |= ST(0).high & 0x8000; |
| 2917 | } |
| 2918 | |
| 2919 | UINT32 ea = GetEA(modrm, 1); |
| 2920 | if (x87_check_exceptions()) |
| 2921 | { |
| 2922 | WRITE80(ea, result); |
| 2923 | x87_inc_stack(); |
| 2924 | } |
| 2925 | |
| 2926 | CYCLES(175); |
| 2927 | } |
| 2928 | |
| 2929 | |
| 2930 | /************************************* |
| 2931 | * |
| 2932 | * Constant load |
| 2933 | * |
| 2934 | *************************************/ |
| 2935 | |
| 2936 | void i386_device::x87_fld1(UINT8 modrm) |
| 2937 | { |
| 2938 | floatx80 value; |
| 2939 | int tag; |
| 2940 | |
| 2941 | if (x87_dec_stack()) |
| 2942 | { |
| 2943 | m_x87_sw &= ~X87_SW_C1; |
| 2944 | value = fx80_one; |
| 2945 | tag = X87_TW_VALID; |
| 2946 | } |
| 2947 | else |
| 2948 | { |
| 2949 | value = fx80_inan; |
| 2950 | tag = X87_TW_SPECIAL; |
| 2951 | } |
| 2952 | |
| 2953 | if (x87_check_exceptions()) |
| 2954 | { |
| 2955 | x87_set_tag(ST_TO_PHYS(0), tag); |
| 2956 | x87_write_stack(0, value, FALSE); |
| 2957 | } |
| 2958 | |
| 2959 | CYCLES(4); |
| 2960 | } |
| 2961 | |
| 2962 | void i386_device::x87_fldl2t(UINT8 modrm) |
| 2963 | { |
| 2964 | floatx80 value; |
| 2965 | int tag; |
| 2966 | |
| 2967 | if (x87_dec_stack()) |
| 2968 | { |
| 2969 | tag = X87_TW_VALID; |
| 2970 | value.high = 0x4000; |
| 2971 | |
| 2972 | if (X87_RC == X87_CW_RC_UP) |
| 2973 | value.low = U64(0xd49a784bcd1b8aff); |
| 2974 | else |
| 2975 | value.low = U64(0xd49a784bcd1b8afe); |
| 2976 | |
| 2977 | m_x87_sw &= ~X87_SW_C1; |
| 2978 | } |
| 2979 | else |
| 2980 | { |
| 2981 | value = fx80_inan; |
| 2982 | tag = X87_TW_SPECIAL; |
| 2983 | } |
| 2984 | |
| 2985 | if (x87_check_exceptions()) |
| 2986 | { |
| 2987 | x87_set_tag(ST_TO_PHYS(0), tag); |
| 2988 | x87_write_stack(0, value, FALSE); |
| 2989 | } |
| 2990 | |
| 2991 | CYCLES(8); |
| 2992 | } |
| 2993 | |
| 2994 | void i386_device::x87_fldl2e(UINT8 modrm) |
| 2995 | { |
| 2996 | floatx80 value; |
| 2997 | int tag; |
| 2998 | |
| 2999 | if (x87_dec_stack()) |
| 3000 | { |
| 3001 | int rc = X87_RC; |
| 3002 | tag = X87_TW_VALID; |
| 3003 | value.high = 0x3fff; |
| 3004 | |
| 3005 | if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST) |
| 3006 | value.low = U64(0xb8aa3b295c17f0bc); |
| 3007 | else |
| 3008 | value.low = U64(0xb8aa3b295c17f0bb); |
| 3009 | |
| 3010 | m_x87_sw &= ~X87_SW_C1; |
| 3011 | } |
| 3012 | else |
| 3013 | { |
| 3014 | value = fx80_inan; |
| 3015 | tag = X87_TW_SPECIAL; |
| 3016 | } |
| 3017 | |
| 3018 | if (x87_check_exceptions()) |
| 3019 | { |
| 3020 | x87_set_tag(ST_TO_PHYS(0), tag); |
| 3021 | x87_write_stack(0, value, FALSE); |
| 3022 | } |
| 3023 | |
| 3024 | CYCLES(8); |
| 3025 | } |
| 3026 | |
| 3027 | void i386_device::x87_fldpi(UINT8 modrm) |
| 3028 | { |
| 3029 | floatx80 value; |
| 3030 | int tag; |
| 3031 | |
| 3032 | if (x87_dec_stack()) |
| 3033 | { |
| 3034 | int rc = X87_RC; |
| 3035 | tag = X87_TW_VALID; |
| 3036 | value.high = 0x4000; |
| 3037 | |
| 3038 | if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST) |
| 3039 | value.low = U64(0xc90fdaa22168c235); |
| 3040 | else |
| 3041 | value.low = U64(0xc90fdaa22168c234); |
| 3042 | |
| 3043 | m_x87_sw &= ~X87_SW_C1; |
| 3044 | } |
| 3045 | else |
| 3046 | { |
| 3047 | value = fx80_inan; |
| 3048 | tag = X87_TW_SPECIAL; |
| 3049 | } |
| 3050 | |
| 3051 | if (x87_check_exceptions()) |
| 3052 | { |
| 3053 | x87_set_tag(ST_TO_PHYS(0), tag); |
| 3054 | x87_write_stack(0, value, FALSE); |
| 3055 | } |
| 3056 | |
| 3057 | CYCLES(8); |
| 3058 | } |
| 3059 | |
| 3060 | void i386_device::x87_fldlg2(UINT8 modrm) |
| 3061 | { |
| 3062 | floatx80 value; |
| 3063 | int tag; |
| 3064 | |
| 3065 | if (x87_dec_stack()) |
| 3066 | { |
| 3067 | int rc = X87_RC; |
| 3068 | tag = X87_TW_VALID; |
| 3069 | value.high = 0x3ffd; |
| 3070 | |
| 3071 | if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST) |
| 3072 | value.low = U64(0x9a209a84fbcff799); |
| 3073 | else |
| 3074 | value.low = U64(0x9a209a84fbcff798); |
| 3075 | |
| 3076 | m_x87_sw &= ~X87_SW_C1; |
| 3077 | } |
| 3078 | else |
| 3079 | { |
| 3080 | value = fx80_inan; |
| 3081 | tag = X87_TW_SPECIAL; |
| 3082 | } |
| 3083 | |
| 3084 | if (x87_check_exceptions()) |
| 3085 | { |
| 3086 | x87_set_tag(ST_TO_PHYS(0), tag); |
| 3087 | x87_write_stack(0, value, FALSE); |
| 3088 | } |
| 3089 | |
| 3090 | CYCLES(8); |
| 3091 | } |
| 3092 | |
| 3093 | void i386_device::x87_fldln2(UINT8 modrm) |
| 3094 | { |
| 3095 | floatx80 value; |
| 3096 | int tag; |
| 3097 | |
| 3098 | if (x87_dec_stack()) |
| 3099 | { |
| 3100 | int rc = X87_RC; |
| 3101 | tag = X87_TW_VALID; |
| 3102 | value.high = 0x3ffe; |
| 3103 | |
| 3104 | if (rc == X87_CW_RC_UP || rc == X87_CW_RC_NEAREST) |
| 3105 | value.low = U64(0xb17217f7d1cf79ac); |
| 3106 | else |
| 3107 | value.low = U64(0xb17217f7d1cf79ab); |
| 3108 | |
| 3109 | m_x87_sw &= ~X87_SW_C1; |
| 3110 | } |
| 3111 | else |
| 3112 | { |
| 3113 | value = fx80_inan; |
| 3114 | tag = X87_TW_SPECIAL; |
| 3115 | } |
| 3116 | |
| 3117 | if (x87_check_exceptions()) |
| 3118 | { |
| 3119 | x87_set_tag(ST_TO_PHYS(0), tag); |
| 3120 | x87_write_stack(0, value, FALSE); |
| 3121 | } |
| 3122 | |
| 3123 | CYCLES(8); |
| 3124 | } |
| 3125 | |
| 3126 | void i386_device::x87_fldz(UINT8 modrm) |
| 3127 | { |
| 3128 | floatx80 value; |
| 3129 | int tag; |
| 3130 | |
| 3131 | if (x87_dec_stack()) |
| 3132 | { |
| 3133 | value = fx80_zero; |
| 3134 | tag = X87_TW_ZERO; |
| 3135 | m_x87_sw &= ~X87_SW_C1; |
| 3136 | } |
| 3137 | else |
| 3138 | { |
| 3139 | value = fx80_inan; |
| 3140 | tag = X87_TW_SPECIAL; |
| 3141 | } |
| 3142 | |
| 3143 | if (x87_check_exceptions()) |
| 3144 | { |
| 3145 | x87_set_tag(ST_TO_PHYS(0), tag); |
| 3146 | x87_write_stack(0, value, FALSE); |
| 3147 | } |
| 3148 | |
| 3149 | CYCLES(4); |
| 3150 | } |
| 3151 | |
| 3152 | |
| 3153 | /************************************* |
| 3154 | * |
| 3155 | * Miscellaneous |
| 3156 | * |
| 3157 | *************************************/ |
| 3158 | |
| 3159 | void i386_device::x87_fnop(UINT8 modrm) |
| 3160 | { |
| 3161 | CYCLES(3); |
| 3162 | } |
| 3163 | |
| 3164 | void i386_device::x87_fchs(UINT8 modrm) |
| 3165 | { |
| 3166 | floatx80 value; |
| 3167 | |
| 3168 | if (X87_IS_ST_EMPTY(0)) |
| 3169 | { |
| 3170 | x87_set_stack_underflow(); |
| 3171 | value = fx80_inan; |
| 3172 | } |
| 3173 | else |
| 3174 | { |
| 3175 | m_x87_sw &= ~X87_SW_C1; |
| 3176 | |
| 3177 | value = ST(0); |
| 3178 | value.high ^= 0x8000; |
| 3179 | } |
| 3180 | |
| 3181 | if (x87_check_exceptions()) |
| 3182 | x87_write_stack(0, value, FALSE); |
| 3183 | |
| 3184 | CYCLES(6); |
| 3185 | } |
| 3186 | |
| 3187 | void i386_device::x87_fabs(UINT8 modrm) |
| 3188 | { |
| 3189 | floatx80 value; |
| 3190 | |
| 3191 | if (X87_IS_ST_EMPTY(0)) |
| 3192 | { |
| 3193 | x87_set_stack_underflow(); |
| 3194 | value = fx80_inan; |
| 3195 | } |
| 3196 | else |
| 3197 | { |
| 3198 | m_x87_sw &= ~X87_SW_C1; |
| 3199 | |
| 3200 | value = ST(0); |
| 3201 | value.high &= 0x7fff; |
| 3202 | } |
| 3203 | |
| 3204 | if (x87_check_exceptions()) |
| 3205 | x87_write_stack(0, value, FALSE); |
| 3206 | |
| 3207 | CYCLES(6); |
| 3208 | } |
| 3209 | |
| 3210 | void i386_device::x87_fscale(UINT8 modrm) |
| 3211 | { |
| 3212 | floatx80 value; |
| 3213 | |
| 3214 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 3215 | { |
| 3216 | x87_set_stack_underflow(); |
| 3217 | value = fx80_inan; |
| 3218 | } |
| 3219 | else |
| 3220 | { |
| 3221 | m_x87_sw &= ~X87_SW_C1; |
| 3222 | value = ST(0); |
| 3223 | |
| 3224 | // Set the rounding mode to truncate |
| 3225 | UINT16 old_cw = m_x87_cw; |
| 3226 | UINT16 new_cw = (old_cw & ~(X87_CW_RC_MASK << X87_CW_RC_SHIFT)) | (X87_CW_RC_ZERO << X87_CW_RC_SHIFT); |
| 3227 | x87_write_cw(new_cw); |
| 3228 | |
| 3229 | // Interpret ST(1) as an integer |
| 3230 | UINT32 st1 = floatx80_to_int32(floatx80_round_to_int(ST(1))); |
| 3231 | |
| 3232 | // Restore the rounding mode |
| 3233 | x87_write_cw(old_cw); |
| 3234 | |
| 3235 | // Get the unbiased exponent of ST(0) |
| 3236 | INT16 exp = (ST(0).high & 0x7fff) - 0x3fff; |
| 3237 | |
| 3238 | // Calculate the new exponent |
| 3239 | exp = (exp + st1 + 0x3fff) & 0x7fff; |
| 3240 | |
| 3241 | // Write it back |
| 3242 | value.high = (value.high & ~0x7fff) + exp; |
| 3243 | } |
| 3244 | |
| 3245 | if (x87_check_exceptions()) |
| 3246 | x87_write_stack(0, value, FALSE); |
| 3247 | |
| 3248 | CYCLES(31); |
| 3249 | } |
| 3250 | |
| 3251 | void i386_device::x87_frndint(UINT8 modrm) |
| 3252 | { |
| 3253 | floatx80 value; |
| 3254 | |
| 3255 | if (X87_IS_ST_EMPTY(0)) |
| 3256 | { |
| 3257 | x87_set_stack_underflow(); |
| 3258 | value = fx80_inan; |
| 3259 | } |
| 3260 | else |
| 3261 | { |
| 3262 | m_x87_sw &= ~X87_SW_C1; |
| 3263 | |
| 3264 | value = floatx80_round_to_int(ST(0)); |
| 3265 | } |
| 3266 | |
| 3267 | if (x87_check_exceptions()) |
| 3268 | x87_write_stack(0, value, TRUE); |
| 3269 | |
| 3270 | CYCLES(21); |
| 3271 | } |
| 3272 | |
| 3273 | void i386_device::x87_fxtract(UINT8 modrm) |
| 3274 | { |
| 3275 | floatx80 sig80, exp80; |
| 3276 | |
| 3277 | if (X87_IS_ST_EMPTY(0)) |
| 3278 | { |
| 3279 | x87_set_stack_underflow(); |
| 3280 | sig80 = exp80 = fx80_inan; |
| 3281 | } |
| 3282 | else if (!X87_IS_ST_EMPTY(7)) |
| 3283 | { |
| 3284 | x87_set_stack_overflow(); |
| 3285 | sig80 = exp80 = fx80_inan; |
| 3286 | } |
| 3287 | else |
| 3288 | { |
| 3289 | floatx80 value = ST(0); |
| 3290 | |
| 3291 | if (floatx80_eq(value, fx80_zero)) |
| 3292 | { |
| 3293 | m_x87_sw |= X87_SW_ZE; |
| 3294 | |
| 3295 | exp80 = fx80_ninf; |
| 3296 | sig80 = fx80_zero; |
| 3297 | } |
| 3298 | else |
| 3299 | { |
| 3300 | // Extract the unbiased exponent |
| 3301 | exp80 = int32_to_floatx80((value.high & 0x7fff) - 0x3fff); |
| 3302 | |
| 3303 | // For the significand, replicate the original value and set its true exponent to 0. |
| 3304 | sig80 = value; |
| 3305 | sig80.high &= ~0x7fff; |
| 3306 | sig80.high |= 0x3fff; |
| 3307 | } |
| 3308 | } |
| 3309 | |
| 3310 | if (x87_check_exceptions()) |
| 3311 | { |
| 3312 | x87_write_stack(0, exp80, TRUE); |
| 3313 | x87_dec_stack(); |
| 3314 | x87_write_stack(0, sig80, TRUE); |
| 3315 | } |
| 3316 | |
| 3317 | CYCLES(21); |
| 3318 | } |
| 3319 | |
| 3320 | /************************************* |
| 3321 | * |
| 3322 | * Comparison |
| 3323 | * |
| 3324 | *************************************/ |
| 3325 | |
| 3326 | void i386_device::x87_ftst(UINT8 modrm) |
| 3327 | { |
| 3328 | if (X87_IS_ST_EMPTY(0)) |
| 3329 | { |
| 3330 | x87_set_stack_underflow(); |
| 3331 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3332 | } |
| 3333 | else |
| 3334 | { |
| 3335 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3336 | |
| 3337 | if (floatx80_is_nan(ST(0))) |
| 3338 | { |
| 3339 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3340 | m_x87_sw |= X87_SW_IE; |
| 3341 | } |
| 3342 | else |
| 3343 | { |
| 3344 | if (floatx80_eq(ST(0), fx80_zero)) |
| 3345 | m_x87_sw |= X87_SW_C3; |
| 3346 | |
| 3347 | if (floatx80_lt(ST(0), fx80_zero)) |
| 3348 | m_x87_sw |= X87_SW_C0; |
| 3349 | } |
| 3350 | } |
| 3351 | |
| 3352 | x87_check_exceptions(); |
| 3353 | |
| 3354 | CYCLES(4); |
| 3355 | } |
| 3356 | |
| 3357 | void i386_device::x87_fxam(UINT8 modrm) |
| 3358 | { |
| 3359 | floatx80 value = ST(0); |
| 3360 | |
| 3361 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3362 | |
| 3363 | // TODO: Unsupported and denormal values |
| 3364 | if (X87_IS_ST_EMPTY(0)) |
| 3365 | { |
| 3366 | m_x87_sw |= X87_SW_C3 | X87_SW_C0; |
| 3367 | } |
| 3368 | else if (floatx80_is_zero(value)) |
| 3369 | { |
| 3370 | m_x87_sw |= X87_SW_C3; |
| 3371 | } |
| 3372 | if (floatx80_is_nan(value)) |
| 3373 | { |
| 3374 | m_x87_sw |= X87_SW_C0; |
| 3375 | } |
| 3376 | else if (floatx80_is_inf(value)) |
| 3377 | { |
| 3378 | m_x87_sw |= X87_SW_C2 | X87_SW_C0; |
| 3379 | } |
| 3380 | else |
| 3381 | { |
| 3382 | m_x87_sw |= X87_SW_C2; |
| 3383 | } |
| 3384 | |
| 3385 | if (value.high & 0x8000) |
| 3386 | m_x87_sw |= X87_SW_C1; |
| 3387 | |
| 3388 | CYCLES(8); |
| 3389 | } |
| 3390 | |
| 3391 | void i386_device::x87_ficom_m16int(UINT8 modrm) |
| 3392 | { |
| 3393 | UINT32 ea = GetEA(modrm, 0); |
| 3394 | if (X87_IS_ST_EMPTY(0)) |
| 3395 | { |
| 3396 | x87_set_stack_underflow(); |
| 3397 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3398 | } |
| 3399 | else |
| 3400 | { |
| 3401 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3402 | |
| 3403 | INT16 m16int = READ16(ea); |
| 3404 | |
| 3405 | floatx80 a = ST(0); |
| 3406 | floatx80 b = int32_to_floatx80(m16int); |
| 3407 | |
| 3408 | if (floatx80_is_nan(a)) |
| 3409 | { |
| 3410 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3411 | m_x87_sw |= X87_SW_IE; |
| 3412 | } |
| 3413 | else |
| 3414 | { |
| 3415 | if (floatx80_eq(a, b)) |
| 3416 | m_x87_sw |= X87_SW_C3; |
| 3417 | |
| 3418 | if (floatx80_lt(a, b)) |
| 3419 | m_x87_sw |= X87_SW_C0; |
| 3420 | } |
| 3421 | } |
| 3422 | |
| 3423 | x87_check_exceptions(); |
| 3424 | |
| 3425 | CYCLES(16); |
| 3426 | } |
| 3427 | |
| 3428 | void i386_device::x87_ficom_m32int(UINT8 modrm) |
| 3429 | { |
| 3430 | UINT32 ea = GetEA(modrm, 0); |
| 3431 | if (X87_IS_ST_EMPTY(0)) |
| 3432 | { |
| 3433 | x87_set_stack_underflow(); |
| 3434 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3435 | } |
| 3436 | else |
| 3437 | { |
| 3438 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3439 | |
| 3440 | INT32 m32int = READ32(ea); |
| 3441 | |
| 3442 | floatx80 a = ST(0); |
| 3443 | floatx80 b = int32_to_floatx80(m32int); |
| 3444 | |
| 3445 | if (floatx80_is_nan(a)) |
| 3446 | { |
| 3447 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3448 | m_x87_sw |= X87_SW_IE; |
| 3449 | } |
| 3450 | else |
| 3451 | { |
| 3452 | if (floatx80_eq(a, b)) |
| 3453 | m_x87_sw |= X87_SW_C3; |
| 3454 | |
| 3455 | if (floatx80_lt(a, b)) |
| 3456 | m_x87_sw |= X87_SW_C0; |
| 3457 | } |
| 3458 | } |
| 3459 | |
| 3460 | x87_check_exceptions(); |
| 3461 | |
| 3462 | CYCLES(15); |
| 3463 | } |
| 3464 | |
| 3465 | void i386_device::x87_ficomp_m16int(UINT8 modrm) |
| 3466 | { |
| 3467 | UINT32 ea = GetEA(modrm, 0); |
| 3468 | if (X87_IS_ST_EMPTY(0)) |
| 3469 | { |
| 3470 | x87_set_stack_underflow(); |
| 3471 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3472 | } |
| 3473 | else |
| 3474 | { |
| 3475 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3476 | |
| 3477 | INT16 m16int = READ16(ea); |
| 3478 | |
| 3479 | floatx80 a = ST(0); |
| 3480 | floatx80 b = int32_to_floatx80(m16int); |
| 3481 | |
| 3482 | if (floatx80_is_nan(a)) |
| 3483 | { |
| 3484 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3485 | m_x87_sw |= X87_SW_IE; |
| 3486 | } |
| 3487 | else |
| 3488 | { |
| 3489 | if (floatx80_eq(a, b)) |
| 3490 | m_x87_sw |= X87_SW_C3; |
| 3491 | |
| 3492 | if (floatx80_lt(a, b)) |
| 3493 | m_x87_sw |= X87_SW_C0; |
| 3494 | } |
| 3495 | } |
| 3496 | |
| 3497 | if (x87_check_exceptions()) |
| 3498 | x87_inc_stack(); |
| 3499 | |
| 3500 | CYCLES(16); |
| 3501 | } |
| 3502 | |
| 3503 | void i386_device::x87_ficomp_m32int(UINT8 modrm) |
| 3504 | { |
| 3505 | UINT32 ea = GetEA(modrm, 0); |
| 3506 | if (X87_IS_ST_EMPTY(0)) |
| 3507 | { |
| 3508 | x87_set_stack_underflow(); |
| 3509 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3510 | } |
| 3511 | else |
| 3512 | { |
| 3513 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3514 | |
| 3515 | INT32 m32int = READ32(ea); |
| 3516 | |
| 3517 | floatx80 a = ST(0); |
| 3518 | floatx80 b = int32_to_floatx80(m32int); |
| 3519 | |
| 3520 | if (floatx80_is_nan(a)) |
| 3521 | { |
| 3522 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3523 | m_x87_sw |= X87_SW_IE; |
| 3524 | } |
| 3525 | else |
| 3526 | { |
| 3527 | if (floatx80_eq(a, b)) |
| 3528 | m_x87_sw |= X87_SW_C3; |
| 3529 | |
| 3530 | if (floatx80_lt(a, b)) |
| 3531 | m_x87_sw |= X87_SW_C0; |
| 3532 | } |
| 3533 | } |
| 3534 | |
| 3535 | if (x87_check_exceptions()) |
| 3536 | x87_inc_stack(); |
| 3537 | |
| 3538 | CYCLES(15); |
| 3539 | } |
| 3540 | |
| 3541 | |
| 3542 | void i386_device::x87_fcom_m32real(UINT8 modrm) |
| 3543 | { |
| 3544 | UINT32 ea = GetEA(modrm, 0); |
| 3545 | if (X87_IS_ST_EMPTY(0)) |
| 3546 | { |
| 3547 | x87_set_stack_underflow(); |
| 3548 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3549 | } |
| 3550 | else |
| 3551 | { |
| 3552 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3553 | |
| 3554 | UINT32 m32real = READ32(ea); |
| 3555 | |
| 3556 | floatx80 a = ST(0); |
| 3557 | floatx80 b = float32_to_floatx80(m32real); |
| 3558 | |
| 3559 | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3560 | { |
| 3561 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3562 | m_x87_sw |= X87_SW_IE; |
| 3563 | } |
| 3564 | else |
| 3565 | { |
| 3566 | if (floatx80_eq(a, b)) |
| 3567 | m_x87_sw |= X87_SW_C3; |
| 3568 | |
| 3569 | if (floatx80_lt(a, b)) |
| 3570 | m_x87_sw |= X87_SW_C0; |
| 3571 | } |
| 3572 | } |
| 3573 | |
| 3574 | x87_check_exceptions(); |
| 3575 | |
| 3576 | CYCLES(4); |
| 3577 | } |
| 3578 | |
| 3579 | void i386_device::x87_fcom_m64real(UINT8 modrm) |
| 3580 | { |
| 3581 | UINT32 ea = GetEA(modrm, 0); |
| 3582 | if (X87_IS_ST_EMPTY(0)) |
| 3583 | { |
| 3584 | x87_set_stack_underflow(); |
| 3585 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3586 | } |
| 3587 | else |
| 3588 | { |
| 3589 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3590 | |
| 3591 | UINT64 m64real = READ64(ea); |
| 3592 | |
| 3593 | floatx80 a = ST(0); |
| 3594 | floatx80 b = float64_to_floatx80(m64real); |
| 3595 | |
| 3596 | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3597 | { |
| 3598 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3599 | m_x87_sw |= X87_SW_IE; |
| 3600 | } |
| 3601 | else |
| 3602 | { |
| 3603 | if (floatx80_eq(a, b)) |
| 3604 | m_x87_sw |= X87_SW_C3; |
| 3605 | |
| 3606 | if (floatx80_lt(a, b)) |
| 3607 | m_x87_sw |= X87_SW_C0; |
| 3608 | } |
| 3609 | } |
| 3610 | |
| 3611 | x87_check_exceptions(); |
| 3612 | |
| 3613 | CYCLES(4); |
| 3614 | } |
| 3615 | |
| 3616 | void i386_device::x87_fcom_sti(UINT8 modrm) |
| 3617 | { |
| 3618 | int i = modrm & 7; |
| 3619 | |
| 3620 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 3621 | { |
| 3622 | x87_set_stack_underflow(); |
| 3623 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3624 | } |
| 3625 | else |
| 3626 | { |
| 3627 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3628 | |
| 3629 | floatx80 a = ST(0); |
| 3630 | floatx80 b = ST(i); |
| 3631 | |
| 3632 | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3633 | { |
| 3634 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3635 | m_x87_sw |= X87_SW_IE; |
| 3636 | } |
| 3637 | else |
| 3638 | { |
| 3639 | if (floatx80_eq(a, b)) |
| 3640 | m_x87_sw |= X87_SW_C3; |
| 3641 | |
| 3642 | if (floatx80_lt(a, b)) |
| 3643 | m_x87_sw |= X87_SW_C0; |
| 3644 | } |
| 3645 | } |
| 3646 | |
| 3647 | x87_check_exceptions(); |
| 3648 | |
| 3649 | CYCLES(4); |
| 3650 | } |
| 3651 | |
| 3652 | void i386_device::x87_fcomp_m32real(UINT8 modrm) |
| 3653 | { |
| 3654 | UINT32 ea = GetEA(modrm, 0); |
| 3655 | if (X87_IS_ST_EMPTY(0)) |
| 3656 | { |
| 3657 | x87_set_stack_underflow(); |
| 3658 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3659 | } |
| 3660 | else |
| 3661 | { |
| 3662 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3663 | |
| 3664 | UINT32 m32real = READ32(ea); |
| 3665 | |
| 3666 | floatx80 a = ST(0); |
| 3667 | floatx80 b = float32_to_floatx80(m32real); |
| 3668 | |
| 3669 | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3670 | { |
| 3671 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3672 | m_x87_sw |= X87_SW_IE; |
| 3673 | } |
| 3674 | else |
| 3675 | { |
| 3676 | if (floatx80_eq(a, b)) |
| 3677 | m_x87_sw |= X87_SW_C3; |
| 3678 | |
| 3679 | if (floatx80_lt(a, b)) |
| 3680 | m_x87_sw |= X87_SW_C0; |
| 3681 | } |
| 3682 | } |
| 3683 | |
| 3684 | if (x87_check_exceptions()) |
| 3685 | x87_inc_stack(); |
| 3686 | |
| 3687 | CYCLES(4); |
| 3688 | } |
| 3689 | |
| 3690 | void i386_device::x87_fcomp_m64real(UINT8 modrm) |
| 3691 | { |
| 3692 | UINT32 ea = GetEA(modrm, 0); |
| 3693 | if (X87_IS_ST_EMPTY(0)) |
| 3694 | { |
| 3695 | x87_set_stack_underflow(); |
| 3696 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3697 | } |
| 3698 | else |
| 3699 | { |
| 3700 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3701 | |
| 3702 | UINT64 m64real = READ64(ea); |
| 3703 | |
| 3704 | floatx80 a = ST(0); |
| 3705 | floatx80 b = float64_to_floatx80(m64real); |
| 3706 | |
| 3707 | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3708 | { |
| 3709 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3710 | m_x87_sw |= X87_SW_IE; |
| 3711 | } |
| 3712 | else |
| 3713 | { |
| 3714 | if (floatx80_eq(a, b)) |
| 3715 | m_x87_sw |= X87_SW_C3; |
| 3716 | |
| 3717 | if (floatx80_lt(a, b)) |
| 3718 | m_x87_sw |= X87_SW_C0; |
| 3719 | } |
| 3720 | } |
| 3721 | |
| 3722 | if (x87_check_exceptions()) |
| 3723 | x87_inc_stack(); |
| 3724 | |
| 3725 | CYCLES(4); |
| 3726 | } |
| 3727 | |
| 3728 | void i386_device::x87_fcomp_sti(UINT8 modrm) |
| 3729 | { |
| 3730 | int i = modrm & 7; |
| 3731 | |
| 3732 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 3733 | { |
| 3734 | x87_set_stack_underflow(); |
| 3735 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3736 | } |
| 3737 | else |
| 3738 | { |
| 3739 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3740 | |
| 3741 | floatx80 a = ST(0); |
| 3742 | floatx80 b = ST(i); |
| 3743 | |
| 3744 | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3745 | { |
| 3746 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3747 | m_x87_sw |= X87_SW_IE; |
| 3748 | } |
| 3749 | else |
| 3750 | { |
| 3751 | if (floatx80_eq(a, b)) |
| 3752 | m_x87_sw |= X87_SW_C3; |
| 3753 | |
| 3754 | if (floatx80_lt(a, b)) |
| 3755 | m_x87_sw |= X87_SW_C0; |
| 3756 | } |
| 3757 | } |
| 3758 | |
| 3759 | if (x87_check_exceptions()) |
| 3760 | x87_inc_stack(); |
| 3761 | |
| 3762 | CYCLES(4); |
| 3763 | } |
| 3764 | |
| 3765 | void i386_device::x87_fcomip_sti(UINT8 modrm) |
| 3766 | { |
| 3767 | int i = modrm & 7; |
| 3768 | |
| 3769 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 3770 | { |
| 3771 | x87_set_stack_underflow(); |
| 3772 | m_ZF = 1; |
| 3773 | m_PF = 1; |
| 3774 | m_CF = 1; |
| 3775 | } |
| 3776 | else |
| 3777 | { |
| 3778 | m_x87_sw &= ~X87_SW_C1; |
| 3779 | |
| 3780 | floatx80 a = ST(0); |
| 3781 | floatx80 b = ST(i); |
| 3782 | |
| 3783 | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3784 | { |
| 3785 | m_ZF = 1; |
| 3786 | m_PF = 1; |
| 3787 | m_CF = 1; |
| 3788 | m_x87_sw |= X87_SW_IE; |
| 3789 | } |
| 3790 | else |
| 3791 | { |
| 3792 | m_ZF = 0; |
| 3793 | m_PF = 0; |
| 3794 | m_CF = 0; |
| 3795 | |
| 3796 | if (floatx80_eq(a, b)) |
| 3797 | m_ZF = 1; |
| 3798 | |
| 3799 | if (floatx80_lt(a, b)) |
| 3800 | m_CF = 1; |
| 3801 | } |
| 3802 | } |
| 3803 | |
| 3804 | if (x87_check_exceptions()) |
| 3805 | x87_inc_stack(); |
| 3806 | |
| 3807 | CYCLES(4); // TODO: correct cycle count |
| 3808 | } |
| 3809 | |
| 3810 | void i386_device::x87_fcompp(UINT8 modrm) |
| 3811 | { |
| 3812 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 3813 | { |
| 3814 | x87_set_stack_underflow(); |
| 3815 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3816 | } |
| 3817 | else |
| 3818 | { |
| 3819 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3820 | |
| 3821 | floatx80 a = ST(0); |
| 3822 | floatx80 b = ST(1); |
| 3823 | |
| 3824 | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3825 | { |
| 3826 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3827 | m_x87_sw |= X87_SW_IE; |
| 3828 | } |
| 3829 | else |
| 3830 | { |
| 3831 | if (floatx80_eq(a, b)) |
| 3832 | m_x87_sw |= X87_SW_C3; |
| 3833 | |
| 3834 | if (floatx80_lt(a, b)) |
| 3835 | m_x87_sw |= X87_SW_C0; |
| 3836 | } |
| 3837 | } |
| 3838 | |
| 3839 | if (x87_check_exceptions()) |
| 3840 | { |
| 3841 | x87_inc_stack(); |
| 3842 | x87_inc_stack(); |
| 3843 | } |
| 3844 | |
| 3845 | CYCLES(5); |
| 3846 | } |
| 3847 | |
| 3848 | |
| 3849 | /************************************* |
| 3850 | * |
| 3851 | * Unordererd comparison |
| 3852 | * |
| 3853 | *************************************/ |
| 3854 | |
| 3855 | void i386_device::x87_fucom_sti(UINT8 modrm) |
| 3856 | { |
| 3857 | int i = modrm & 7; |
| 3858 | |
| 3859 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 3860 | { |
| 3861 | x87_set_stack_underflow(); |
| 3862 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3863 | } |
| 3864 | else |
| 3865 | { |
| 3866 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3867 | |
| 3868 | floatx80 a = ST(0); |
| 3869 | floatx80 b = ST(i); |
| 3870 | |
| 3871 | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3872 | { |
| 3873 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3874 | |
| 3875 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 3876 | m_x87_sw |= X87_SW_IE; |
| 3877 | } |
| 3878 | else |
| 3879 | { |
| 3880 | if (floatx80_eq(a, b)) |
| 3881 | m_x87_sw |= X87_SW_C3; |
| 3882 | |
| 3883 | if (floatx80_lt(a, b)) |
| 3884 | m_x87_sw |= X87_SW_C0; |
| 3885 | } |
| 3886 | } |
| 3887 | |
| 3888 | x87_check_exceptions(); |
| 3889 | |
| 3890 | CYCLES(4); |
| 3891 | } |
| 3892 | |
| 3893 | void i386_device::x87_fucomp_sti(UINT8 modrm) |
| 3894 | { |
| 3895 | int i = modrm & 7; |
| 3896 | |
| 3897 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(i)) |
| 3898 | { |
| 3899 | x87_set_stack_underflow(); |
| 3900 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3901 | } |
| 3902 | else |
| 3903 | { |
| 3904 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3905 | |
| 3906 | floatx80 a = ST(0); |
| 3907 | floatx80 b = ST(i); |
| 3908 | |
| 3909 | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3910 | { |
| 3911 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3912 | |
| 3913 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 3914 | m_x87_sw |= X87_SW_IE; |
| 3915 | } |
| 3916 | else |
| 3917 | { |
| 3918 | if (floatx80_eq(a, b)) |
| 3919 | m_x87_sw |= X87_SW_C3; |
| 3920 | |
| 3921 | if (floatx80_lt(a, b)) |
| 3922 | m_x87_sw |= X87_SW_C0; |
| 3923 | } |
| 3924 | } |
| 3925 | |
| 3926 | if (x87_check_exceptions()) |
| 3927 | x87_inc_stack(); |
| 3928 | |
| 3929 | CYCLES(4); |
| 3930 | } |
| 3931 | |
| 3932 | void i386_device::x87_fucompp(UINT8 modrm) |
| 3933 | { |
| 3934 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 3935 | { |
| 3936 | x87_set_stack_underflow(); |
| 3937 | m_x87_sw |= X87_SW_C3 | X87_SW_C2 | X87_SW_C0; |
| 3938 | } |
| 3939 | else |
| 3940 | { |
| 3941 | m_x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3942 | |
| 3943 | floatx80 a = ST(0); |
| 3944 | floatx80 b = ST(1); |
| 3945 | |
| 3946 | if (floatx80_is_nan(a) || floatx80_is_nan(b)) |
| 3947 | { |
| 3948 | m_x87_sw |= X87_SW_C0 | X87_SW_C2 | X87_SW_C3; |
| 3949 | |
| 3950 | if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b)) |
| 3951 | m_x87_sw |= X87_SW_IE; |
| 3952 | } |
| 3953 | else |
| 3954 | { |
| 3955 | if (floatx80_eq(a, b)) |
| 3956 | m_x87_sw |= X87_SW_C3; |
| 3957 | |
| 3958 | if (floatx80_lt(a, b)) |
| 3959 | m_x87_sw |= X87_SW_C0; |
| 3960 | } |
| 3961 | } |
| 3962 | |
| 3963 | if (x87_check_exceptions()) |
| 3964 | { |
| 3965 | x87_inc_stack(); |
| 3966 | x87_inc_stack(); |
| 3967 | } |
| 3968 | |
| 3969 | CYCLES(4); |
| 3970 | } |
| 3971 | |
| 3972 | |
| 3973 | /************************************* |
| 3974 | * |
| 3975 | * Control |
| 3976 | * |
| 3977 | *************************************/ |
| 3978 | |
| 3979 | void i386_device::x87_fdecstp(UINT8 modrm) |
| 3980 | { |
| 3981 | m_x87_sw &= ~X87_SW_C1; |
| 3982 | |
| 3983 | x87_dec_stack(); |
| 3984 | x87_check_exceptions(); |
| 3985 | |
| 3986 | CYCLES(3); |
| 3987 | } |
| 3988 | |
| 3989 | void i386_device::x87_fincstp(UINT8 modrm) |
| 3990 | { |
| 3991 | m_x87_sw &= ~X87_SW_C1; |
| 3992 | |
| 3993 | x87_inc_stack(); |
| 3994 | x87_check_exceptions(); |
| 3995 | |
| 3996 | CYCLES(3); |
| 3997 | } |
| 3998 | |
| 3999 | void i386_device::x87_fclex(UINT8 modrm) |
| 4000 | { |
| 4001 | m_x87_sw &= ~0x80ff; |
| 4002 | |
| 4003 | CYCLES(7); |
| 4004 | } |
| 4005 | |
| 4006 | void i386_device::x87_ffree(UINT8 modrm) |
| 4007 | { |
| 4008 | x87_set_tag(ST_TO_PHYS(modrm & 7), X87_TW_EMPTY); |
| 4009 | |
| 4010 | CYCLES(3); |
| 4011 | } |
| 4012 | |
| 4013 | void i386_device::x87_finit(UINT8 modrm) |
| 4014 | { |
| 4015 | x87_reset(); |
| 4016 | |
| 4017 | CYCLES(17); |
| 4018 | } |
| 4019 | |
| 4020 | void i386_device::x87_fldcw(UINT8 modrm) |
| 4021 | { |
| 4022 | UINT32 ea = GetEA(modrm, 0); |
| 4023 | UINT16 cw = READ16(ea); |
| 4024 | |
| 4025 | x87_write_cw(cw); |
| 4026 | |
| 4027 | x87_check_exceptions(); |
| 4028 | |
| 4029 | CYCLES(4); |
| 4030 | } |
| 4031 | |
| 4032 | void i386_device::x87_fstcw(UINT8 modrm) |
| 4033 | { |
| 4034 | UINT32 ea = GetEA(modrm, 1); |
| 4035 | WRITE16(ea, m_x87_cw); |
| 4036 | |
| 4037 | CYCLES(3); |
| 4038 | } |
| 4039 | |
| 4040 | void i386_device::x87_fldenv(UINT8 modrm) |
| 4041 | { |
| 4042 | // TODO: Pointers and selectors |
| 4043 | UINT32 ea = GetEA(modrm, 0); |
| 4044 | |
| 4045 | if (m_operand_size) |
| 4046 | { |
| 4047 | // 32-bit real/protected mode |
| 4048 | x87_write_cw(READ16(ea)); |
| 4049 | m_x87_sw = READ16(ea + 4); |
| 4050 | m_x87_tw = READ16(ea + 8); |
| 4051 | } |
| 4052 | else |
| 4053 | { |
| 4054 | // 16-bit real/protected mode |
| 4055 | x87_write_cw(READ16(ea)); |
| 4056 | m_x87_sw = READ16(ea + 2); |
| 4057 | m_x87_tw = READ16(ea + 4); |
| 4058 | } |
| 4059 | |
| 4060 | x87_check_exceptions(); |
| 4061 | |
| 4062 | CYCLES((m_cr[0] & 1) ? 34 : 44); |
| 4063 | } |
| 4064 | |
| 4065 | void i386_device::x87_fstenv(UINT8 modrm) |
| 4066 | { |
| 4067 | UINT32 ea = GetEA(modrm, 1); |
| 4068 | |
| 4069 | // TODO: Pointers and selectors |
| 4070 | switch((m_cr[0] & 1)|(m_operand_size & 1)<<1) |
| 4071 | { |
| 4072 | case 0: // 16-bit real mode |
| 4073 | WRITE16(ea + 0, m_x87_cw); |
| 4074 | WRITE16(ea + 2, m_x87_sw); |
| 4075 | WRITE16(ea + 4, m_x87_tw); |
| 4076 | // WRITE16(ea + 6, m_fpu_inst_ptr & 0xffff); |
| 4077 | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4078 | // WRITE16(ea + 10, m_fpu_data_ptr & 0xffff); |
| 4079 | // WRITE16(ea + 12, (m_fpu_inst_ptr & 0x0f0000) >> 4); |
| 4080 | break; |
| 4081 | case 1: // 16-bit protected mode |
| 4082 | WRITE16(ea + 0, m_x87_cw); |
| 4083 | WRITE16(ea + 2, m_x87_sw); |
| 4084 | WRITE16(ea + 4, m_x87_tw); |
| 4085 | // WRITE16(ea + 6, m_fpu_inst_ptr & 0xffff); |
| 4086 | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4087 | // WRITE16(ea + 10, m_fpu_data_ptr & 0xffff); |
| 4088 | // WRITE16(ea + 12, (m_fpu_inst_ptr & 0x0f0000) >> 4); |
| 4089 | break; |
| 4090 | case 2: // 32-bit real mode |
| 4091 | WRITE16(ea + 0, m_x87_cw); |
| 4092 | WRITE16(ea + 4, m_x87_sw); |
| 4093 | WRITE16(ea + 8, m_x87_tw); |
| 4094 | // WRITE16(ea + 12, m_fpu_inst_ptr & 0xffff); |
| 4095 | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4096 | // WRITE16(ea + 20, m_fpu_data_ptr & 0xffff); |
| 4097 | // WRITE16(ea + 12, ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4098 | // WRITE32(ea + 24, (m_fpu_data_ptr >> 16) << 12); |
| 4099 | break; |
| 4100 | case 3: // 32-bit protected mode |
| 4101 | WRITE16(ea + 0, m_x87_cw); |
| 4102 | WRITE16(ea + 4, m_x87_sw); |
| 4103 | WRITE16(ea + 8, m_x87_tw); |
| 4104 | // WRITE32(ea + 12, m_fpu_inst_ptr); |
| 4105 | // WRITE32(ea + 16, m_fpu_opcode); |
| 4106 | // WRITE32(ea + 20, m_fpu_data_ptr); |
| 4107 | // WRITE32(ea + 24, m_fpu_inst_ptr); |
| 4108 | break; |
| 4109 | } |
| 4110 | |
| 4111 | CYCLES((m_cr[0] & 1) ? 56 : 67); |
| 4112 | } |
| 4113 | |
| 4114 | void i386_device::x87_fsave(UINT8 modrm) |
| 4115 | { |
| 4116 | UINT32 ea = GetEA(modrm, 1); |
| 4117 | |
| 4118 | // TODO: Pointers and selectors |
| 4119 | switch((m_cr[0] & 1)|(m_operand_size & 1)<<1) |
| 4120 | { |
| 4121 | case 0: // 16-bit real mode |
| 4122 | WRITE16(ea + 0, m_x87_cw); |
| 4123 | WRITE16(ea + 2, m_x87_sw); |
| 4124 | WRITE16(ea + 4, m_x87_tw); |
| 4125 | // WRITE16(ea + 6, m_fpu_inst_ptr & 0xffff); |
| 4126 | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4127 | // WRITE16(ea + 10, m_fpu_data_ptr & 0xffff); |
| 4128 | // WRITE16(ea + 12, (m_fpu_inst_ptr & 0x0f0000) >> 4); |
| 4129 | ea += 14; |
| 4130 | break; |
| 4131 | case 1: // 16-bit protected mode |
| 4132 | WRITE16(ea + 0, m_x87_cw); |
| 4133 | WRITE16(ea + 2, m_x87_sw); |
| 4134 | WRITE16(ea + 4, m_x87_tw); |
| 4135 | // WRITE16(ea + 6, m_fpu_inst_ptr & 0xffff); |
| 4136 | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4137 | // WRITE16(ea + 10, m_fpu_data_ptr & 0xffff); |
| 4138 | // WRITE16(ea + 12, (m_fpu_inst_ptr & 0x0f0000) >> 4); |
| 4139 | ea += 14; |
| 4140 | break; |
| 4141 | case 2: // 32-bit real mode |
| 4142 | WRITE16(ea + 0, m_x87_cw); |
| 4143 | WRITE16(ea + 4, m_x87_sw); |
| 4144 | WRITE16(ea + 8, m_x87_tw); |
| 4145 | // WRITE16(ea + 12, m_fpu_inst_ptr & 0xffff); |
| 4146 | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4147 | // WRITE16(ea + 20, m_fpu_data_ptr & 0xffff); |
| 4148 | // WRITE16(ea + 12, ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4149 | // WRITE32(ea + 24, (m_fpu_data_ptr >> 16) << 12); |
| 4150 | ea += 28; |
| 4151 | break; |
| 4152 | case 3: // 32-bit protected mode |
| 4153 | WRITE16(ea + 0, m_x87_cw); |
| 4154 | WRITE16(ea + 4, m_x87_sw); |
| 4155 | WRITE16(ea + 8, m_x87_tw); |
| 4156 | // WRITE32(ea + 12, m_fpu_inst_ptr); |
| 4157 | // WRITE32(ea + 16, m_fpu_opcode); |
| 4158 | // WRITE32(ea + 20, m_fpu_data_ptr); |
| 4159 | // WRITE32(ea + 24, m_fpu_inst_ptr); |
| 4160 | ea += 28; |
| 4161 | break; |
| 4162 | } |
| 4163 | |
| 4164 | for (int i = 0; i < 8; ++i) |
| 4165 | x87_write_stack(i, READ80(ea + i*10), FALSE); |
| 4166 | |
| 4167 | CYCLES((m_cr[0] & 1) ? 56 : 67); |
| 4168 | } |
| 4169 | |
| 4170 | void i386_device::x87_frstor(UINT8 modrm) |
| 4171 | { |
| 4172 | UINT32 ea = GetEA(modrm, 0); |
| 4173 | |
| 4174 | // TODO: Pointers and selectors |
| 4175 | switch((m_cr[0] & 1)|(m_operand_size & 1)<<1) |
| 4176 | { |
| 4177 | case 0: // 16-bit real mode |
| 4178 | x87_write_cw(READ16(ea)); |
| 4179 | m_x87_sw = READ16(ea + 2); |
| 4180 | m_x87_tw = READ16(ea + 4); |
| 4181 | // WRITE16(ea + 6, m_fpu_inst_ptr & 0xffff); |
| 4182 | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4183 | // WRITE16(ea + 10, m_fpu_data_ptr & 0xffff); |
| 4184 | // WRITE16(ea + 12, (m_fpu_inst_ptr & 0x0f0000) >> 4); |
| 4185 | ea += 14; |
| 4186 | break; |
| 4187 | case 1: // 16-bit protected mode |
| 4188 | x87_write_cw(READ16(ea)); |
| 4189 | m_x87_sw = READ16(ea + 2); |
| 4190 | m_x87_tw = READ16(ea + 4); |
| 4191 | // WRITE16(ea + 6, m_fpu_inst_ptr & 0xffff); |
| 4192 | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4193 | // WRITE16(ea + 10, m_fpu_data_ptr & 0xffff); |
| 4194 | // WRITE16(ea + 12, (m_fpu_inst_ptr & 0x0f0000) >> 4); |
| 4195 | ea += 14; |
| 4196 | break; |
| 4197 | case 2: // 32-bit real mode |
| 4198 | x87_write_cw(READ16(ea)); |
| 4199 | m_x87_sw = READ16(ea + 4); |
| 4200 | m_x87_tw = READ16(ea + 8); |
| 4201 | // WRITE16(ea + 12, m_fpu_inst_ptr & 0xffff); |
| 4202 | // WRITE16(ea + 8, (m_fpu_opcode & 0x07ff) | ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4203 | // WRITE16(ea + 20, m_fpu_data_ptr & 0xffff); |
| 4204 | // WRITE16(ea + 12, ((m_fpu_inst_ptr & 0x0f0000) >> 4)); |
| 4205 | // WRITE32(ea + 24, (m_fpu_data_ptr >> 16) << 12); |
| 4206 | ea += 28; |
| 4207 | break; |
| 4208 | case 3: // 32-bit protected mode |
| 4209 | x87_write_cw(READ16(ea)); |
| 4210 | m_x87_sw = READ16(ea + 4); |
| 4211 | m_x87_tw = READ16(ea + 8); |
| 4212 | // WRITE32(ea + 12, m_fpu_inst_ptr); |
| 4213 | // WRITE32(ea + 16, m_fpu_opcode); |
| 4214 | // WRITE32(ea + 20, m_fpu_data_ptr); |
| 4215 | // WRITE32(ea + 24, m_fpu_inst_ptr); |
| 4216 | ea += 28; |
| 4217 | break; |
| 4218 | } |
| 4219 | |
| 4220 | for (int i = 0; i < 8; ++i) |
| 4221 | WRITE80(ea + i*10, ST(i)); |
| 4222 | |
| 4223 | CYCLES((m_cr[0] & 1) ? 34 : 44); |
| 4224 | } |
| 4225 | |
| 4226 | void i386_device::x87_fxch(UINT8 modrm) |
| 4227 | { |
| 4228 | if (X87_IS_ST_EMPTY(0) || X87_IS_ST_EMPTY(1)) |
| 4229 | x87_set_stack_underflow(); |
| 4230 | |
| 4231 | if (x87_check_exceptions()) |
| 4232 | { |
| 4233 | floatx80 tmp = ST(0); |
| 4234 | ST(0) = ST(1); |
| 4235 | ST(1) = tmp; |
| 4236 | |
| 4237 | // Swap the tags |
| 4238 | int tag0 = X87_TAG(ST_TO_PHYS(0)); |
| 4239 | x87_set_tag(ST_TO_PHYS(0), X87_TAG(ST_TO_PHYS(1))); |
| 4240 | x87_set_tag(ST_TO_PHYS(1), tag0); |
| 4241 | } |
| 4242 | |
| 4243 | CYCLES(4); |
| 4244 | } |
| 4245 | |
| 4246 | void i386_device::x87_fxch_sti(UINT8 modrm) |
| 4247 | { |
| 4248 | int i = modrm & 7; |
| 4249 | |
| 4250 | if (X87_IS_ST_EMPTY(0)) |
| 4251 | { |
| 4252 | ST(0) = fx80_inan; |
| 4253 | x87_set_tag(ST_TO_PHYS(0), X87_TW_SPECIAL); |
| 4254 | x87_set_stack_underflow(); |
| 4255 | } |
| 4256 | if (X87_IS_ST_EMPTY(i)) |
| 4257 | { |
| 4258 | ST(i) = fx80_inan; |
| 4259 | x87_set_tag(ST_TO_PHYS(i), X87_TW_SPECIAL); |
| 4260 | x87_set_stack_underflow(); |
| 4261 | } |
| 4262 | |
| 4263 | if (x87_check_exceptions()) |
| 4264 | { |
| 4265 | floatx80 tmp = ST(0); |
| 4266 | ST(0) = ST(i); |
| 4267 | ST(i) = tmp; |
| 4268 | |
| 4269 | // Swap the tags |
| 4270 | int tag0 = X87_TAG(ST_TO_PHYS(0)); |
| 4271 | x87_set_tag(ST_TO_PHYS(0), X87_TAG(ST_TO_PHYS(i))); |
| 4272 | x87_set_tag(ST_TO_PHYS(i), tag0); |
| 4273 | } |
| 4274 | |
| 4275 | CYCLES(4); |
| 4276 | } |
| 4277 | |
| 4278 | void i386_device::x87_fstsw_ax(UINT8 modrm) |
| 4279 | { |
| 4280 | REG16(AX) = m_x87_sw; |
| 4281 | |
| 4282 | CYCLES(3); |
| 4283 | } |
| 4284 | |
| 4285 | void i386_device::x87_fstsw_m2byte(UINT8 modrm) |
| 4286 | { |
| 4287 | UINT32 ea = GetEA(modrm, 1); |
| 4288 | |
| 4289 | WRITE16(ea, m_x87_sw); |
| 4290 | |
| 4291 | CYCLES(3); |
| 4292 | } |
| 4293 | |
| 4294 | void i386_device::x87_invalid(UINT8 modrm) |
| 4295 | { |
| 4296 | // TODO |
| 4297 | fatalerror("x87 invalid instruction (PC:%.4x)\n", m_pc); |
| 4298 | } |
| 4299 | |
| 4300 | |
| 4301 | |
| 4302 | /************************************* |
| 4303 | * |
| 4304 | * Instruction dispatch |
| 4305 | * |
| 4306 | *************************************/ |
| 4307 | |
| 4308 | void i386_device::i386_x87_group_d8() |
| 4309 | { |
| 4310 | UINT8 modrm = FETCH(); |
| 4311 | (this->*m_opcode_table_x87_d8[modrm])(modrm); |
| 4312 | } |
| 4313 | |
| 4314 | void i386_device::i386_x87_group_d9() |
| 4315 | { |
| 4316 | UINT8 modrm = FETCH(); |
| 4317 | (this->*m_opcode_table_x87_d9[modrm])(modrm); |
| 4318 | } |
| 4319 | |
| 4320 | void i386_device::i386_x87_group_da() |
| 4321 | { |
| 4322 | UINT8 modrm = FETCH(); |
| 4323 | (this->*m_opcode_table_x87_da[modrm])(modrm); |
| 4324 | } |
| 4325 | |
| 4326 | void i386_device::i386_x87_group_db() |
| 4327 | { |
| 4328 | UINT8 modrm = FETCH(); |
| 4329 | (this->*m_opcode_table_x87_db[modrm])(modrm); |
| 4330 | } |
| 4331 | |
| 4332 | void i386_device::i386_x87_group_dc() |
| 4333 | { |
| 4334 | UINT8 modrm = FETCH(); |
| 4335 | (this->*m_opcode_table_x87_dc[modrm])(modrm); |
| 4336 | } |
| 4337 | |
| 4338 | void i386_device::i386_x87_group_dd() |
| 4339 | { |
| 4340 | UINT8 modrm = FETCH(); |
| 4341 | (this->*m_opcode_table_x87_dd[modrm])(modrm); |
| 4342 | } |
| 4343 | |
| 4344 | void i386_device::i386_x87_group_de() |
| 4345 | { |
| 4346 | UINT8 modrm = FETCH(); |
| 4347 | (this->*m_opcode_table_x87_de[modrm])(modrm); |
| 4348 | } |
| 4349 | |
| 4350 | void i386_device::i386_x87_group_df() |
| 4351 | { |
| 4352 | UINT8 modrm = FETCH(); |
| 4353 | (this->*m_opcode_table_x87_df[modrm])(modrm); |
| 4354 | } |
| 4355 | |
| 4356 | |
| 4357 | /************************************* |
| 4358 | * |
| 4359 | * Opcode table building |
| 4360 | * |
| 4361 | *************************************/ |
| 4362 | |
| 4363 | void i386_device::build_x87_opcode_table_d8() |
| 4364 | { |
| 4365 | int modrm = 0; |
| 4366 | |
| 4367 | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4368 | { |
| 4369 | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4370 | |
| 4371 | if (modrm < 0xc0) |
| 4372 | { |
| 4373 | switch ((modrm >> 3) & 0x7) |
| 4374 | { |
| 4375 | case 0x00: ptr = &i386_device::x87_fadd_m32real; break; |
| 4376 | case 0x01: ptr = &i386_device::x87_fmul_m32real; break; |
| 4377 | case 0x02: ptr = &i386_device::x87_fcom_m32real; break; |
| 4378 | case 0x03: ptr = &i386_device::x87_fcomp_m32real; break; |
| 4379 | case 0x04: ptr = &i386_device::x87_fsub_m32real; break; |
| 4380 | case 0x05: ptr = &i386_device::x87_fsubr_m32real; break; |
| 4381 | case 0x06: ptr = &i386_device::x87_fdiv_m32real; break; |
| 4382 | case 0x07: ptr = &i386_device::x87_fdivr_m32real; break; |
| 4383 | } |
| 4384 | } |
| 4385 | else |
| 4386 | { |
| 4387 | switch (modrm) |
| 4388 | { |
| 4389 | case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &i386_device::x87_fadd_st_sti; break; |
| 4390 | case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &i386_device::x87_fmul_st_sti; break; |
| 4391 | case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: ptr = &i386_device::x87_fcom_sti; break; |
| 4392 | case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: ptr = &i386_device::x87_fcomp_sti; break; |
| 4393 | case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = &i386_device::x87_fsub_st_sti; break; |
| 4394 | case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &i386_device::x87_fsubr_st_sti; break; |
| 4395 | case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = &i386_device::x87_fdiv_st_sti; break; |
| 4396 | case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: ptr = &i386_device::x87_fdivr_st_sti; break; |
| 4397 | } |
| 4398 | } |
| 4399 | |
| 4400 | m_opcode_table_x87_d8[modrm] = ptr; |
| 4401 | } |
| 4402 | } |
| 4403 | |
| 4404 | |
| 4405 | void i386_device::build_x87_opcode_table_d9() |
| 4406 | { |
| 4407 | int modrm = 0; |
| 4408 | |
| 4409 | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4410 | { |
| 4411 | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4412 | |
| 4413 | if (modrm < 0xc0) |
| 4414 | { |
| 4415 | switch ((modrm >> 3) & 0x7) |
| 4416 | { |
| 4417 | case 0x00: ptr = &i386_device::x87_fld_m32real; break; |
| 4418 | case 0x02: ptr = &i386_device::x87_fst_m32real; break; |
| 4419 | case 0x03: ptr = &i386_device::x87_fstp_m32real; break; |
| 4420 | case 0x04: ptr = &i386_device::x87_fldenv; break; |
| 4421 | case 0x05: ptr = &i386_device::x87_fldcw; break; |
| 4422 | case 0x06: ptr = &i386_device::x87_fstenv; break; |
| 4423 | case 0x07: ptr = &i386_device::x87_fstcw; break; |
| 4424 | } |
| 4425 | } |
| 4426 | else |
| 4427 | { |
| 4428 | switch (modrm) |
| 4429 | { |
| 4430 | case 0xc0: |
| 4431 | case 0xc1: |
| 4432 | case 0xc2: |
| 4433 | case 0xc3: |
| 4434 | case 0xc4: |
| 4435 | case 0xc5: |
| 4436 | case 0xc6: |
| 4437 | case 0xc7: ptr = &i386_device::x87_fld_sti; break; |
| 4438 | |
| 4439 | case 0xc8: |
| 4440 | case 0xc9: |
| 4441 | case 0xca: |
| 4442 | case 0xcb: |
| 4443 | case 0xcc: |
| 4444 | case 0xcd: |
| 4445 | case 0xce: |
| 4446 | case 0xcf: ptr = &i386_device::x87_fxch_sti; break; |
| 4447 | |
| 4448 | case 0xd0: ptr = &i386_device::x87_fnop; break; |
| 4449 | case 0xe0: ptr = &i386_device::x87_fchs; break; |
| 4450 | case 0xe1: ptr = &i386_device::x87_fabs; break; |
| 4451 | case 0xe4: ptr = &i386_device::x87_ftst; break; |
| 4452 | case 0xe5: ptr = &i386_device::x87_fxam; break; |
| 4453 | case 0xe8: ptr = &i386_device::x87_fld1; break; |
| 4454 | case 0xe9: ptr = &i386_device::x87_fldl2t; break; |
| 4455 | case 0xea: ptr = &i386_device::x87_fldl2e; break; |
| 4456 | case 0xeb: ptr = &i386_device::x87_fldpi; break; |
| 4457 | case 0xec: ptr = &i386_device::x87_fldlg2; break; |
| 4458 | case 0xed: ptr = &i386_device::x87_fldln2; break; |
| 4459 | case 0xee: ptr = &i386_device::x87_fldz; break; |
| 4460 | case 0xf0: ptr = &i386_device::x87_f2xm1; break; |
| 4461 | case 0xf1: ptr = &i386_device::x87_fyl2x; break; |
| 4462 | case 0xf2: ptr = &i386_device::x87_fptan; break; |
| 4463 | case 0xf3: ptr = &i386_device::x87_fpatan; break; |
| 4464 | case 0xf4: ptr = &i386_device::x87_fxtract; break; |
| 4465 | case 0xf5: ptr = &i386_device::x87_fprem1; break; |
| 4466 | case 0xf6: ptr = &i386_device::x87_fdecstp; break; |
| 4467 | case 0xf7: ptr = &i386_device::x87_fincstp; break; |
| 4468 | case 0xf8: ptr = &i386_device::x87_fprem; break; |
| 4469 | case 0xf9: ptr = &i386_device::x87_fyl2xp1; break; |
| 4470 | case 0xfa: ptr = &i386_device::x87_fsqrt; break; |
| 4471 | case 0xfb: ptr = &i386_device::x87_fsincos; break; |
| 4472 | case 0xfc: ptr = &i386_device::x87_frndint; break; |
| 4473 | case 0xfd: ptr = &i386_device::x87_fscale; break; |
| 4474 | case 0xfe: ptr = &i386_device::x87_fsin; break; |
| 4475 | case 0xff: ptr = &i386_device::x87_fcos; break; |
| 4476 | } |
| 4477 | } |
| 4478 | |
| 4479 | m_opcode_table_x87_d9[modrm] = ptr; |
| 4480 | } |
| 4481 | } |
| 4482 | |
| 4483 | void i386_device::build_x87_opcode_table_da() |
| 4484 | { |
| 4485 | int modrm = 0; |
| 4486 | |
| 4487 | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4488 | { |
| 4489 | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4490 | |
| 4491 | if (modrm < 0xc0) |
| 4492 | { |
| 4493 | switch ((modrm >> 3) & 0x7) |
| 4494 | { |
| 4495 | case 0x00: ptr = &i386_device::x87_fiadd_m32int; break; |
| 4496 | case 0x01: ptr = &i386_device::x87_fimul_m32int; break; |
| 4497 | case 0x02: ptr = &i386_device::x87_ficom_m32int; break; |
| 4498 | case 0x03: ptr = &i386_device::x87_ficomp_m32int; break; |
| 4499 | case 0x04: ptr = &i386_device::x87_fisub_m32int; break; |
| 4500 | case 0x05: ptr = &i386_device::x87_fisubr_m32int; break; |
| 4501 | case 0x06: ptr = &i386_device::x87_fidiv_m32int; break; |
| 4502 | case 0x07: ptr = &i386_device::x87_fidivr_m32int; break; |
| 4503 | } |
| 4504 | } |
| 4505 | else |
| 4506 | { |
| 4507 | switch (modrm) |
| 4508 | { |
| 4509 | case 0xe9: ptr = &i386_device::x87_fucompp; break; |
| 4510 | } |
| 4511 | } |
| 4512 | |
| 4513 | m_opcode_table_x87_da[modrm] = ptr; |
| 4514 | } |
| 4515 | } |
| 4516 | |
| 4517 | |
| 4518 | void i386_device::build_x87_opcode_table_db() |
| 4519 | { |
| 4520 | int modrm = 0; |
| 4521 | |
| 4522 | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4523 | { |
| 4524 | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4525 | |
| 4526 | if (modrm < 0xc0) |
| 4527 | { |
| 4528 | switch ((modrm >> 3) & 0x7) |
| 4529 | { |
| 4530 | case 0x00: ptr = &i386_device::x87_fild_m32int; break; |
| 4531 | case 0x02: ptr = &i386_device::x87_fist_m32int; break; |
| 4532 | case 0x03: ptr = &i386_device::x87_fistp_m32int; break; |
| 4533 | case 0x05: ptr = &i386_device::x87_fld_m80real; break; |
| 4534 | case 0x07: ptr = &i386_device::x87_fstp_m80real; break; |
| 4535 | } |
| 4536 | } |
| 4537 | else |
| 4538 | { |
| 4539 | switch (modrm) |
| 4540 | { |
| 4541 | case 0xe0: ptr = &i386_device::x87_fnop; break; /* FENI */ |
| 4542 | case 0xe1: ptr = &i386_device::x87_fnop; break; /* FDISI */ |
| 4543 | case 0xe2: ptr = &i386_device::x87_fclex; break; |
| 4544 | case 0xe3: ptr = &i386_device::x87_finit; break; |
| 4545 | case 0xe4: ptr = &i386_device::x87_fnop; break; /* FSETPM */ |
| 4546 | } |
| 4547 | } |
| 4548 | |
| 4549 | m_opcode_table_x87_db[modrm] = ptr; |
| 4550 | } |
| 4551 | } |
| 4552 | |
| 4553 | |
| 4554 | void i386_device::build_x87_opcode_table_dc() |
| 4555 | { |
| 4556 | int modrm = 0; |
| 4557 | |
| 4558 | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4559 | { |
| 4560 | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4561 | |
| 4562 | if (modrm < 0xc0) |
| 4563 | { |
| 4564 | switch ((modrm >> 3) & 0x7) |
| 4565 | { |
| 4566 | case 0x00: ptr = &i386_device::x87_fadd_m64real; break; |
| 4567 | case 0x01: ptr = &i386_device::x87_fmul_m64real; break; |
| 4568 | case 0x02: ptr = &i386_device::x87_fcom_m64real; break; |
| 4569 | case 0x03: ptr = &i386_device::x87_fcomp_m64real; break; |
| 4570 | case 0x04: ptr = &i386_device::x87_fsub_m64real; break; |
| 4571 | case 0x05: ptr = &i386_device::x87_fsubr_m64real; break; |
| 4572 | case 0x06: ptr = &i386_device::x87_fdiv_m64real; break; |
| 4573 | case 0x07: ptr = &i386_device::x87_fdivr_m64real; break; |
| 4574 | } |
| 4575 | } |
| 4576 | else |
| 4577 | { |
| 4578 | switch (modrm) |
| 4579 | { |
| 4580 | case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &i386_device::x87_fadd_sti_st; break; |
| 4581 | case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &i386_device::x87_fmul_sti_st; break; |
| 4582 | case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = &i386_device::x87_fsubr_sti_st; break; |
| 4583 | case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &i386_device::x87_fsub_sti_st; break; |
| 4584 | case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = &i386_device::x87_fdivr_sti_st; break; |
| 4585 | case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: ptr = &i386_device::x87_fdiv_sti_st; break; |
| 4586 | } |
| 4587 | } |
| 4588 | |
| 4589 | m_opcode_table_x87_dc[modrm] = ptr; |
| 4590 | } |
| 4591 | } |
| 4592 | |
| 4593 | |
| 4594 | void i386_device::build_x87_opcode_table_dd() |
| 4595 | { |
| 4596 | int modrm = 0; |
| 4597 | |
| 4598 | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4599 | { |
| 4600 | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4601 | |
| 4602 | if (modrm < 0xc0) |
| 4603 | { |
| 4604 | switch ((modrm >> 3) & 0x7) |
| 4605 | { |
| 4606 | case 0x00: ptr = &i386_device::x87_fld_m64real; break; |
| 4607 | case 0x02: ptr = &i386_device::x87_fst_m64real; break; |
| 4608 | case 0x03: ptr = &i386_device::x87_fstp_m64real; break; |
| 4609 | case 0x04: ptr = &i386_device::x87_frstor; break; |
| 4610 | case 0x06: ptr = &i386_device::x87_fsave; break; |
| 4611 | case 0x07: ptr = &i386_device::x87_fstsw_m2byte; break; |
| 4612 | } |
| 4613 | } |
| 4614 | else |
| 4615 | { |
| 4616 | switch (modrm) |
| 4617 | { |
| 4618 | case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &i386_device::x87_ffree; break; |
| 4619 | case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &i386_device::x87_fxch_sti; break; |
| 4620 | case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: ptr = &i386_device::x87_fst_sti; break; |
| 4621 | case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: ptr = &i386_device::x87_fstp_sti; break; |
| 4622 | case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = &i386_device::x87_fucom_sti; break; |
| 4623 | case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &i386_device::x87_fucomp_sti; break; |
| 4624 | } |
| 4625 | } |
| 4626 | |
| 4627 | m_opcode_table_x87_dd[modrm] = ptr; |
| 4628 | } |
| 4629 | } |
| 4630 | |
| 4631 | |
| 4632 | void i386_device::build_x87_opcode_table_de() |
| 4633 | { |
| 4634 | int modrm = 0; |
| 4635 | |
| 4636 | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4637 | { |
| 4638 | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4639 | |
| 4640 | if (modrm < 0xc0) |
| 4641 | { |
| 4642 | switch ((modrm >> 3) & 0x7) |
| 4643 | { |
| 4644 | case 0x00: ptr = &i386_device::x87_fiadd_m16int; break; |
| 4645 | case 0x01: ptr = &i386_device::x87_fimul_m16int; break; |
| 4646 | case 0x02: ptr = &i386_device::x87_ficom_m16int; break; |
| 4647 | case 0x03: ptr = &i386_device::x87_ficomp_m16int; break; |
| 4648 | case 0x04: ptr = &i386_device::x87_fisub_m16int; break; |
| 4649 | case 0x05: ptr = &i386_device::x87_fisubr_m16int; break; |
| 4650 | case 0x06: ptr = &i386_device::x87_fidiv_m16int; break; |
| 4651 | case 0x07: ptr = &i386_device::x87_fidivr_m16int; break; |
| 4652 | } |
| 4653 | } |
| 4654 | else |
| 4655 | { |
| 4656 | switch (modrm) |
| 4657 | { |
| 4658 | case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: ptr = &i386_device::x87_faddp; break; |
| 4659 | case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: ptr = &i386_device::x87_fmulp; break; |
| 4660 | case 0xd9: ptr = &i386_device::x87_fcompp; break; |
| 4661 | case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: ptr = &i386_device::x87_fsubrp; break; |
| 4662 | case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: ptr = &i386_device::x87_fsubp; break; |
| 4663 | case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = &i386_device::x87_fdivrp; break; |
| 4664 | case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: ptr = &i386_device::x87_fdivp; break; |
| 4665 | } |
| 4666 | } |
| 4667 | |
| 4668 | m_opcode_table_x87_de[modrm] = ptr; |
| 4669 | } |
| 4670 | } |
| 4671 | |
| 4672 | |
| 4673 | void i386_device::build_x87_opcode_table_df() |
| 4674 | { |
| 4675 | int modrm = 0; |
| 4676 | |
| 4677 | for (modrm = 0; modrm < 0x100; ++modrm) |
| 4678 | { |
| 4679 | i386_modrm_func ptr = &i386_device::x87_invalid; |
| 4680 | |
| 4681 | if (modrm < 0xc0) |
| 4682 | { |
| 4683 | switch ((modrm >> 3) & 0x7) |
| 4684 | { |
| 4685 | case 0x00: ptr = &i386_device::x87_fild_m16int; break; |
| 4686 | case 0x02: ptr = &i386_device::x87_fist_m16int; break; |
| 4687 | case 0x03: ptr = &i386_device::x87_fistp_m16int; break; |
| 4688 | case 0x04: ptr = &i386_device::x87_fbld; break; |
| 4689 | case 0x05: ptr = &i386_device::x87_fild_m64int; break; |
| 4690 | case 0x06: ptr = &i386_device::x87_fbstp; break; |
| 4691 | case 0x07: ptr = &i386_device::x87_fistp_m64int; break; |
| 4692 | } |
| 4693 | } |
| 4694 | else |
| 4695 | { |
| 4696 | switch (modrm) |
| 4697 | { |
| 4698 | case 0xe0: ptr = &i386_device::x87_fstsw_ax; break; |
| 4699 | case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: ptr = &i386_device::x87_fcomip_sti; break; |
| 4700 | } |
| 4701 | } |
| 4702 | |
| 4703 | m_opcode_table_x87_df[modrm] = ptr; |
| 4704 | } |
| 4705 | } |
| 4706 | |
| 4707 | void i386_device::build_x87_opcode_table() |
| 4708 | { |
| 4709 | build_x87_opcode_table_d8(); |
| 4710 | build_x87_opcode_table_d9(); |
| 4711 | build_x87_opcode_table_da(); |
| 4712 | build_x87_opcode_table_db(); |
| 4713 | build_x87_opcode_table_dc(); |
| 4714 | build_x87_opcode_table_dd(); |
| 4715 | build_x87_opcode_table_de(); |
| 4716 | build_x87_opcode_table_df(); |
| 4717 | } |
trunk/src/emu/cpu/i386/i386ops.inc
| r0 | r28739 | |
| 1 | UINT8 i386_device::i386_shift_rotate8(UINT8 modrm, UINT32 value, UINT8 shift) |
| 2 | { |
| 3 | UINT32 src = value & 0xff; |
| 4 | UINT8 dst = value; |
| 5 | |
| 6 | if( shift == 0 ) { |
| 7 | CYCLES_RM(modrm, 3, 7); |
| 8 | } else if( shift == 1 ) { |
| 9 | switch( (modrm >> 3) & 0x7 ) |
| 10 | { |
| 11 | case 0: /* ROL rm8, 1 */ |
| 12 | m_CF = (src & 0x80) ? 1 : 0; |
| 13 | dst = (src << 1) + m_CF; |
| 14 | m_OF = ((src ^ dst) & 0x80) ? 1 : 0; |
| 15 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 16 | break; |
| 17 | case 1: /* ROR rm8, 1 */ |
| 18 | m_CF = (src & 0x1) ? 1 : 0; |
| 19 | dst = (m_CF << 7) | (src >> 1); |
| 20 | m_OF = ((src ^ dst) & 0x80) ? 1 : 0; |
| 21 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 22 | break; |
| 23 | case 2: /* RCL rm8, 1 */ |
| 24 | dst = (src << 1) + m_CF; |
| 25 | m_CF = (src & 0x80) ? 1 : 0; |
| 26 | m_OF = ((src ^ dst) & 0x80) ? 1 : 0; |
| 27 | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 28 | break; |
| 29 | case 3: /* RCR rm8, 1 */ |
| 30 | dst = (m_CF << 7) | (src >> 1); |
| 31 | m_CF = src & 0x1; |
| 32 | m_OF = ((src ^ dst) & 0x80) ? 1 : 0; |
| 33 | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 34 | break; |
| 35 | case 4: /* SHL/SAL rm8, 1 */ |
| 36 | case 6: |
| 37 | dst = src << 1; |
| 38 | m_CF = (src & 0x80) ? 1 : 0; |
| 39 | m_OF = (((m_CF << 7) ^ dst) & 0x80) ? 1 : 0; |
| 40 | SetSZPF8(dst); |
| 41 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 42 | break; |
| 43 | case 5: /* SHR rm8, 1 */ |
| 44 | dst = src >> 1; |
| 45 | m_CF = src & 0x1; |
| 46 | m_OF = (dst & 0x80) ? 1 : 0; |
| 47 | SetSZPF8(dst); |
| 48 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 49 | break; |
| 50 | case 7: /* SAR rm8, 1 */ |
| 51 | dst = (INT8)(src) >> 1; |
| 52 | m_CF = src & 0x1; |
| 53 | m_OF = 0; |
| 54 | SetSZPF8(dst); |
| 55 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 56 | break; |
| 57 | } |
| 58 | |
| 59 | } else { |
| 60 | switch( (modrm >> 3) & 0x7 ) |
| 61 | { |
| 62 | case 0: /* ROL rm8, i8 */ |
| 63 | if(!(shift & 7)) |
| 64 | { |
| 65 | if(shift & 0x18) |
| 66 | { |
| 67 | m_CF = src & 1; |
| 68 | m_OF = (src & 1) ^ ((src >> 7) & 1); |
| 69 | } |
| 70 | break; |
| 71 | } |
| 72 | shift &= 7; |
| 73 | dst = ((src & ((UINT8)0xff >> shift)) << shift) | |
| 74 | ((src & ((UINT8)0xff << (8-shift))) >> (8-shift)); |
| 75 | m_CF = dst & 0x1; |
| 76 | m_OF = (dst & 1) ^ (dst >> 7); |
| 77 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 78 | break; |
| 79 | case 1: /* ROR rm8, i8 */ |
| 80 | if(!(shift & 7)) |
| 81 | { |
| 82 | if(shift & 0x18) |
| 83 | { |
| 84 | m_CF = (src >> 7) & 1; |
| 85 | m_OF = ((src >> 7) & 1) ^ ((src >> 6) & 1); |
| 86 | } |
| 87 | break; |
| 88 | } |
| 89 | shift &= 7; |
| 90 | dst = ((src & ((UINT8)0xff << shift)) >> shift) | |
| 91 | ((src & ((UINT8)0xff >> (8-shift))) << (8-shift)); |
| 92 | m_CF = (dst >> 7) & 1; |
| 93 | m_OF = ((dst >> 7) ^ (dst >> 6)) & 1; |
| 94 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 95 | break; |
| 96 | case 2: /* RCL rm8, i8 */ |
| 97 | shift %= 9; |
| 98 | dst = ((src & ((UINT8)0xff >> shift)) << shift) | |
| 99 | ((src & ((UINT8)0xff << (9-shift))) >> (9-shift)) | |
| 100 | (m_CF << (shift-1)); |
| 101 | if(shift) m_CF = (src >> (8-shift)) & 0x1; |
| 102 | m_OF = m_CF ^ ((dst >> 7) & 1); |
| 103 | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 104 | break; |
| 105 | case 3: /* RCR rm8, i8 */ |
| 106 | shift %= 9; |
| 107 | dst = ((src & ((UINT8)0xff << shift)) >> shift) | |
| 108 | ((src & ((UINT8)0xff >> (8-shift))) << (9-shift)) | |
| 109 | (m_CF << (8-shift)); |
| 110 | if(shift) m_CF = (src >> (shift-1)) & 0x1; |
| 111 | m_OF = ((dst >> 7) ^ (dst >> 6)) & 1; |
| 112 | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 113 | break; |
| 114 | case 4: /* SHL/SAL rm8, i8 */ |
| 115 | case 6: |
| 116 | shift &= 31; |
| 117 | dst = src << shift; |
| 118 | m_CF = (shift <= 8) && ((src >> (8 - shift)) & 1); |
| 119 | SetSZPF8(dst); |
| 120 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 121 | break; |
| 122 | case 5: /* SHR rm8, i8 */ |
| 123 | shift &= 31; |
| 124 | dst = src >> shift; |
| 125 | m_CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 126 | SetSZPF8(dst); |
| 127 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 128 | break; |
| 129 | case 7: /* SAR rm8, i8 */ |
| 130 | shift &= 31; |
| 131 | dst = (INT8)src >> shift; |
| 132 | m_CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 133 | SetSZPF8(dst); |
| 134 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 135 | break; |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | return dst; |
| 140 | } |
| 141 | |
| 142 | |
| 143 | |
| 144 | void i386_device::i386_adc_rm8_r8() // Opcode 0x10 |
| 145 | { |
| 146 | UINT8 src, dst; |
| 147 | UINT8 modrm = FETCH(); |
| 148 | if( modrm >= 0xc0 ) { |
| 149 | src = LOAD_REG8(modrm); |
| 150 | dst = LOAD_RM8(modrm); |
| 151 | dst = ADC8(dst, src, m_CF); |
| 152 | STORE_RM8(modrm, dst); |
| 153 | CYCLES(CYCLES_ALU_REG_REG); |
| 154 | } else { |
| 155 | UINT32 ea = GetEA(modrm,1); |
| 156 | src = LOAD_REG8(modrm); |
| 157 | dst = READ8(ea); |
| 158 | dst = ADC8(dst, src, m_CF); |
| 159 | WRITE8(ea, dst); |
| 160 | CYCLES(CYCLES_ALU_REG_MEM); |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | void i386_device::i386_adc_r8_rm8() // Opcode 0x12 |
| 165 | { |
| 166 | UINT8 src, dst; |
| 167 | UINT8 modrm = FETCH(); |
| 168 | if( modrm >= 0xc0 ) { |
| 169 | src = LOAD_RM8(modrm); |
| 170 | dst = LOAD_REG8(modrm); |
| 171 | dst = ADC8(dst, src, m_CF); |
| 172 | STORE_REG8(modrm, dst); |
| 173 | CYCLES(CYCLES_ALU_REG_REG); |
| 174 | } else { |
| 175 | UINT32 ea = GetEA(modrm,0); |
| 176 | src = READ8(ea); |
| 177 | dst = LOAD_REG8(modrm); |
| 178 | dst = ADC8(dst, src, m_CF); |
| 179 | STORE_REG8(modrm, dst); |
| 180 | CYCLES(CYCLES_ALU_MEM_REG); |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | void i386_device::i386_adc_al_i8() // Opcode 0x14 |
| 185 | { |
| 186 | UINT8 src, dst; |
| 187 | src = FETCH(); |
| 188 | dst = REG8(AL); |
| 189 | dst = ADC8(dst, src, m_CF); |
| 190 | REG8(AL) = dst; |
| 191 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 192 | } |
| 193 | |
| 194 | void i386_device::i386_add_rm8_r8() // Opcode 0x00 |
| 195 | { |
| 196 | UINT8 src, dst; |
| 197 | UINT8 modrm = FETCH(); |
| 198 | if( modrm >= 0xc0 ) { |
| 199 | src = LOAD_REG8(modrm); |
| 200 | dst = LOAD_RM8(modrm); |
| 201 | dst = ADD8(dst, src); |
| 202 | STORE_RM8(modrm, dst); |
| 203 | CYCLES(CYCLES_ALU_REG_REG); |
| 204 | } else { |
| 205 | UINT32 ea = GetEA(modrm,1); |
| 206 | src = LOAD_REG8(modrm); |
| 207 | dst = READ8(ea); |
| 208 | dst = ADD8(dst, src); |
| 209 | WRITE8(ea, dst); |
| 210 | CYCLES(CYCLES_ALU_REG_MEM); |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | void i386_device::i386_add_r8_rm8() // Opcode 0x02 |
| 215 | { |
| 216 | UINT8 src, dst; |
| 217 | UINT8 modrm = FETCH(); |
| 218 | if( modrm >= 0xc0 ) { |
| 219 | src = LOAD_RM8(modrm); |
| 220 | dst = LOAD_REG8(modrm); |
| 221 | dst = ADD8(dst, src); |
| 222 | STORE_REG8(modrm, dst); |
| 223 | CYCLES(CYCLES_ALU_REG_REG); |
| 224 | } else { |
| 225 | UINT32 ea = GetEA(modrm,0); |
| 226 | src = READ8(ea); |
| 227 | dst = LOAD_REG8(modrm); |
| 228 | dst = ADD8(dst, src); |
| 229 | STORE_REG8(modrm, dst); |
| 230 | CYCLES(CYCLES_ALU_MEM_REG); |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | void i386_device::i386_add_al_i8() // Opcode 0x04 |
| 235 | { |
| 236 | UINT8 src, dst; |
| 237 | src = FETCH(); |
| 238 | dst = REG8(AL); |
| 239 | dst = ADD8(dst, src); |
| 240 | REG8(AL) = dst; |
| 241 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 242 | } |
| 243 | |
| 244 | void i386_device::i386_and_rm8_r8() // Opcode 0x20 |
| 245 | { |
| 246 | UINT8 src, dst; |
| 247 | UINT8 modrm = FETCH(); |
| 248 | if( modrm >= 0xc0 ) { |
| 249 | src = LOAD_REG8(modrm); |
| 250 | dst = LOAD_RM8(modrm); |
| 251 | dst = AND8(dst, src); |
| 252 | STORE_RM8(modrm, dst); |
| 253 | CYCLES(CYCLES_ALU_REG_REG); |
| 254 | } else { |
| 255 | UINT32 ea = GetEA(modrm,1); |
| 256 | src = LOAD_REG8(modrm); |
| 257 | dst = READ8(ea); |
| 258 | dst = AND8(dst, src); |
| 259 | WRITE8(ea, dst); |
| 260 | CYCLES(CYCLES_ALU_REG_MEM); |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | void i386_device::i386_and_r8_rm8() // Opcode 0x22 |
| 265 | { |
| 266 | UINT8 src, dst; |
| 267 | UINT8 modrm = FETCH(); |
| 268 | if( modrm >= 0xc0 ) { |
| 269 | src = LOAD_RM8(modrm); |
| 270 | dst = LOAD_REG8(modrm); |
| 271 | dst = AND8(dst, src); |
| 272 | STORE_REG8(modrm, dst); |
| 273 | CYCLES(CYCLES_ALU_REG_REG); |
| 274 | } else { |
| 275 | UINT32 ea = GetEA(modrm,0); |
| 276 | src = READ8(ea); |
| 277 | dst = LOAD_REG8(modrm); |
| 278 | dst = AND8(dst, src); |
| 279 | STORE_REG8(modrm, dst); |
| 280 | CYCLES(CYCLES_ALU_MEM_REG); |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | void i386_device::i386_and_al_i8() // Opcode 0x24 |
| 285 | { |
| 286 | UINT8 src, dst; |
| 287 | src = FETCH(); |
| 288 | dst = REG8(AL); |
| 289 | dst = AND8(dst, src); |
| 290 | REG8(AL) = dst; |
| 291 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 292 | } |
| 293 | |
| 294 | void i386_device::i386_clc() // Opcode 0xf8 |
| 295 | { |
| 296 | m_CF = 0; |
| 297 | CYCLES(CYCLES_CLC); |
| 298 | } |
| 299 | |
| 300 | void i386_device::i386_cld() // Opcode 0xfc |
| 301 | { |
| 302 | m_DF = 0; |
| 303 | CYCLES(CYCLES_CLD); |
| 304 | } |
| 305 | |
| 306 | void i386_device::i386_cli() // Opcode 0xfa |
| 307 | { |
| 308 | if(PROTECTED_MODE) |
| 309 | { |
| 310 | UINT8 IOPL = m_IOP1 | (m_IOP2 << 1); |
| 311 | if(m_CPL > IOPL) |
| 312 | FAULT(FAULT_GP,0); |
| 313 | } |
| 314 | m_IF = 0; |
| 315 | CYCLES(CYCLES_CLI); |
| 316 | } |
| 317 | |
| 318 | void i386_device::i386_cmc() // Opcode 0xf5 |
| 319 | { |
| 320 | m_CF ^= 1; |
| 321 | CYCLES(CYCLES_CMC); |
| 322 | } |
| 323 | |
| 324 | void i386_device::i386_cmp_rm8_r8() // Opcode 0x38 |
| 325 | { |
| 326 | UINT8 src, dst; |
| 327 | UINT8 modrm = FETCH(); |
| 328 | if( modrm >= 0xc0 ) { |
| 329 | src = LOAD_REG8(modrm); |
| 330 | dst = LOAD_RM8(modrm); |
| 331 | SUB8(dst, src); |
| 332 | CYCLES(CYCLES_CMP_REG_REG); |
| 333 | } else { |
| 334 | UINT32 ea = GetEA(modrm,0); |
| 335 | src = LOAD_REG8(modrm); |
| 336 | dst = READ8(ea); |
| 337 | SUB8(dst, src); |
| 338 | CYCLES(CYCLES_CMP_REG_MEM); |
| 339 | } |
| 340 | } |
| 341 | |
| 342 | void i386_device::i386_cmp_r8_rm8() // Opcode 0x3a |
| 343 | { |
| 344 | UINT8 src, dst; |
| 345 | UINT8 modrm = FETCH(); |
| 346 | if( modrm >= 0xc0 ) { |
| 347 | src = LOAD_RM8(modrm); |
| 348 | dst = LOAD_REG8(modrm); |
| 349 | SUB8(dst, src); |
| 350 | CYCLES(CYCLES_CMP_REG_REG); |
| 351 | } else { |
| 352 | UINT32 ea = GetEA(modrm,0); |
| 353 | src = READ8(ea); |
| 354 | dst = LOAD_REG8(modrm); |
| 355 | SUB8(dst, src); |
| 356 | CYCLES(CYCLES_CMP_MEM_REG); |
| 357 | } |
| 358 | } |
| 359 | |
| 360 | void i386_device::i386_cmp_al_i8() // Opcode 0x3c |
| 361 | { |
| 362 | UINT8 src, dst; |
| 363 | src = FETCH(); |
| 364 | dst = REG8(AL); |
| 365 | SUB8(dst, src); |
| 366 | CYCLES(CYCLES_CMP_IMM_ACC); |
| 367 | } |
| 368 | |
| 369 | void i386_device::i386_cmpsb() // Opcode 0xa6 |
| 370 | { |
| 371 | UINT32 eas, ead; |
| 372 | UINT8 src, dst; |
| 373 | if( m_segment_prefix ) { |
| 374 | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 375 | } else { |
| 376 | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 377 | } |
| 378 | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 ); |
| 379 | src = READ8(eas); |
| 380 | dst = READ8(ead); |
| 381 | SUB8(src, dst); |
| 382 | BUMP_SI(1); |
| 383 | BUMP_DI(1); |
| 384 | CYCLES(CYCLES_CMPS); |
| 385 | } |
| 386 | |
| 387 | void i386_device::i386_in_al_i8() // Opcode 0xe4 |
| 388 | { |
| 389 | UINT16 port = FETCH(); |
| 390 | UINT8 data = READPORT8(port); |
| 391 | REG8(AL) = data; |
| 392 | CYCLES(CYCLES_IN_VAR); |
| 393 | } |
| 394 | |
| 395 | void i386_device::i386_in_al_dx() // Opcode 0xec |
| 396 | { |
| 397 | UINT16 port = REG16(DX); |
| 398 | UINT8 data = READPORT8(port); |
| 399 | REG8(AL) = data; |
| 400 | CYCLES(CYCLES_IN); |
| 401 | } |
| 402 | |
| 403 | void i386_device::i386_ja_rel8() // Opcode 0x77 |
| 404 | { |
| 405 | INT8 disp = FETCH(); |
| 406 | if( m_CF == 0 && m_ZF == 0 ) { |
| 407 | NEAR_BRANCH(disp); |
| 408 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 409 | } else { |
| 410 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 411 | } |
| 412 | } |
| 413 | |
| 414 | void i386_device::i386_jbe_rel8() // Opcode 0x76 |
| 415 | { |
| 416 | INT8 disp = FETCH(); |
| 417 | if( m_CF != 0 || m_ZF != 0 ) { |
| 418 | NEAR_BRANCH(disp); |
| 419 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 420 | } else { |
| 421 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 422 | } |
| 423 | } |
| 424 | |
| 425 | void i386_device::i386_jc_rel8() // Opcode 0x72 |
| 426 | { |
| 427 | INT8 disp = FETCH(); |
| 428 | if( m_CF != 0 ) { |
| 429 | NEAR_BRANCH(disp); |
| 430 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 431 | } else { |
| 432 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 433 | } |
| 434 | } |
| 435 | |
| 436 | void i386_device::i386_jg_rel8() // Opcode 0x7f |
| 437 | { |
| 438 | INT8 disp = FETCH(); |
| 439 | if( m_ZF == 0 && (m_SF == m_OF) ) { |
| 440 | NEAR_BRANCH(disp); |
| 441 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 442 | } else { |
| 443 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 444 | } |
| 445 | } |
| 446 | |
| 447 | void i386_device::i386_jge_rel8() // Opcode 0x7d |
| 448 | { |
| 449 | INT8 disp = FETCH(); |
| 450 | if(m_SF == m_OF) { |
| 451 | NEAR_BRANCH(disp); |
| 452 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 453 | } else { |
| 454 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 455 | } |
| 456 | } |
| 457 | |
| 458 | void i386_device::i386_jl_rel8() // Opcode 0x7c |
| 459 | { |
| 460 | INT8 disp = FETCH(); |
| 461 | if( (m_SF != m_OF) ) { |
| 462 | NEAR_BRANCH(disp); |
| 463 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 464 | } else { |
| 465 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 466 | } |
| 467 | } |
| 468 | |
| 469 | void i386_device::i386_jle_rel8() // Opcode 0x7e |
| 470 | { |
| 471 | INT8 disp = FETCH(); |
| 472 | if( m_ZF != 0 || (m_SF != m_OF) ) { |
| 473 | NEAR_BRANCH(disp); |
| 474 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 475 | } else { |
| 476 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 477 | } |
| 478 | } |
| 479 | |
| 480 | void i386_device::i386_jnc_rel8() // Opcode 0x73 |
| 481 | { |
| 482 | INT8 disp = FETCH(); |
| 483 | if( m_CF == 0 ) { |
| 484 | NEAR_BRANCH(disp); |
| 485 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 486 | } else { |
| 487 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 488 | } |
| 489 | } |
| 490 | |
| 491 | void i386_device::i386_jno_rel8() // Opcode 0x71 |
| 492 | { |
| 493 | INT8 disp = FETCH(); |
| 494 | if( m_OF == 0 ) { |
| 495 | NEAR_BRANCH(disp); |
| 496 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 497 | } else { |
| 498 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 499 | } |
| 500 | } |
| 501 | |
| 502 | void i386_device::i386_jnp_rel8() // Opcode 0x7b |
| 503 | { |
| 504 | INT8 disp = FETCH(); |
| 505 | if( m_PF == 0 ) { |
| 506 | NEAR_BRANCH(disp); |
| 507 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 508 | } else { |
| 509 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 510 | } |
| 511 | } |
| 512 | |
| 513 | void i386_device::i386_jns_rel8() // Opcode 0x79 |
| 514 | { |
| 515 | INT8 disp = FETCH(); |
| 516 | if( m_SF == 0 ) { |
| 517 | NEAR_BRANCH(disp); |
| 518 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 519 | } else { |
| 520 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 521 | } |
| 522 | } |
| 523 | |
| 524 | void i386_device::i386_jnz_rel8() // Opcode 0x75 |
| 525 | { |
| 526 | INT8 disp = FETCH(); |
| 527 | if( m_ZF == 0 ) { |
| 528 | NEAR_BRANCH(disp); |
| 529 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 530 | } else { |
| 531 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 532 | } |
| 533 | } |
| 534 | |
| 535 | void i386_device::i386_jo_rel8() // Opcode 0x70 |
| 536 | { |
| 537 | INT8 disp = FETCH(); |
| 538 | if( m_OF != 0 ) { |
| 539 | NEAR_BRANCH(disp); |
| 540 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 541 | } else { |
| 542 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 543 | } |
| 544 | } |
| 545 | |
| 546 | void i386_device::i386_jp_rel8() // Opcode 0x7a |
| 547 | { |
| 548 | INT8 disp = FETCH(); |
| 549 | if( m_PF != 0 ) { |
| 550 | NEAR_BRANCH(disp); |
| 551 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 552 | } else { |
| 553 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 554 | } |
| 555 | } |
| 556 | |
| 557 | void i386_device::i386_js_rel8() // Opcode 0x78 |
| 558 | { |
| 559 | INT8 disp = FETCH(); |
| 560 | if( m_SF != 0 ) { |
| 561 | NEAR_BRANCH(disp); |
| 562 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 563 | } else { |
| 564 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 565 | } |
| 566 | } |
| 567 | |
| 568 | void i386_device::i386_jz_rel8() // Opcode 0x74 |
| 569 | { |
| 570 | INT8 disp = FETCH(); |
| 571 | if( m_ZF != 0 ) { |
| 572 | NEAR_BRANCH(disp); |
| 573 | CYCLES(CYCLES_JCC_DISP8); /* TODO: Timing = 7 + m */ |
| 574 | } else { |
| 575 | CYCLES(CYCLES_JCC_DISP8_NOBRANCH); |
| 576 | } |
| 577 | } |
| 578 | |
| 579 | void i386_device::i386_jmp_rel8() // Opcode 0xeb |
| 580 | { |
| 581 | INT8 disp = FETCH(); |
| 582 | NEAR_BRANCH(disp); |
| 583 | CYCLES(CYCLES_JMP_SHORT); /* TODO: Timing = 7 + m */ |
| 584 | } |
| 585 | |
| 586 | void i386_device::i386_lahf() // Opcode 0x9f |
| 587 | { |
| 588 | REG8(AH) = get_flags() & 0xd7; |
| 589 | CYCLES(CYCLES_LAHF); |
| 590 | } |
| 591 | |
| 592 | void i386_device::i386_lodsb() // Opcode 0xac |
| 593 | { |
| 594 | UINT32 eas; |
| 595 | if( m_segment_prefix ) { |
| 596 | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 597 | } else { |
| 598 | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 599 | } |
| 600 | REG8(AL) = READ8(eas); |
| 601 | BUMP_SI(1); |
| 602 | CYCLES(CYCLES_LODS); |
| 603 | } |
| 604 | |
| 605 | void i386_device::i386_mov_rm8_r8() // Opcode 0x88 |
| 606 | { |
| 607 | UINT8 src; |
| 608 | UINT8 modrm = FETCH(); |
| 609 | if( modrm >= 0xc0 ) { |
| 610 | src = LOAD_REG8(modrm); |
| 611 | STORE_RM8(modrm, src); |
| 612 | CYCLES(CYCLES_MOV_REG_REG); |
| 613 | } else { |
| 614 | UINT32 ea = GetEA(modrm,1); |
| 615 | src = LOAD_REG8(modrm); |
| 616 | WRITE8(ea, src); |
| 617 | CYCLES(CYCLES_MOV_REG_MEM); |
| 618 | } |
| 619 | } |
| 620 | |
| 621 | void i386_device::i386_mov_r8_rm8() // Opcode 0x8a |
| 622 | { |
| 623 | UINT8 src; |
| 624 | UINT8 modrm = FETCH(); |
| 625 | if( modrm >= 0xc0 ) { |
| 626 | src = LOAD_RM8(modrm); |
| 627 | STORE_REG8(modrm, src); |
| 628 | CYCLES(CYCLES_MOV_REG_REG); |
| 629 | } else { |
| 630 | UINT32 ea = GetEA(modrm,0); |
| 631 | src = READ8(ea); |
| 632 | STORE_REG8(modrm, src); |
| 633 | CYCLES(CYCLES_MOV_MEM_REG); |
| 634 | } |
| 635 | } |
| 636 | |
| 637 | void i386_device::i386_mov_rm8_i8() // Opcode 0xc6 |
| 638 | { |
| 639 | UINT8 modrm = FETCH(); |
| 640 | if( modrm >= 0xc0 ) { |
| 641 | UINT8 value = FETCH(); |
| 642 | STORE_RM8(modrm, value); |
| 643 | CYCLES(CYCLES_MOV_IMM_REG); |
| 644 | } else { |
| 645 | UINT32 ea = GetEA(modrm,1); |
| 646 | UINT8 value = FETCH(); |
| 647 | WRITE8(ea, value); |
| 648 | CYCLES(CYCLES_MOV_IMM_MEM); |
| 649 | } |
| 650 | } |
| 651 | |
| 652 | void i386_device::i386_mov_r32_cr() // Opcode 0x0f 20 |
| 653 | { |
| 654 | if(PROTECTED_MODE && m_CPL) |
| 655 | FAULT(FAULT_GP, 0); |
| 656 | UINT8 modrm = FETCH(); |
| 657 | UINT8 cr = (modrm >> 3) & 0x7; |
| 658 | |
| 659 | STORE_RM32(modrm, m_cr[cr]); |
| 660 | CYCLES(CYCLES_MOV_CR_REG); |
| 661 | } |
| 662 | |
| 663 | void i386_device::i386_mov_r32_dr() // Opcode 0x0f 21 |
| 664 | { |
| 665 | if(PROTECTED_MODE && m_CPL) |
| 666 | FAULT(FAULT_GP, 0); |
| 667 | UINT8 modrm = FETCH(); |
| 668 | UINT8 dr = (modrm >> 3) & 0x7; |
| 669 | |
| 670 | STORE_RM32(modrm, m_dr[dr]); |
| 671 | switch(dr) |
| 672 | { |
| 673 | case 0: |
| 674 | case 1: |
| 675 | case 2: |
| 676 | case 3: |
| 677 | CYCLES(CYCLES_MOV_REG_DR0_3); |
| 678 | break; |
| 679 | case 6: |
| 680 | case 7: |
| 681 | CYCLES(CYCLES_MOV_REG_DR6_7); |
| 682 | break; |
| 683 | } |
| 684 | } |
| 685 | |
| 686 | void i386_device::i386_mov_cr_r32() // Opcode 0x0f 22 |
| 687 | { |
| 688 | if(PROTECTED_MODE && m_CPL) |
| 689 | FAULT(FAULT_GP, 0); |
| 690 | UINT8 modrm = FETCH(); |
| 691 | UINT8 cr = (modrm >> 3) & 0x7; |
| 692 | UINT32 data = LOAD_RM32(modrm); |
| 693 | switch(cr) |
| 694 | { |
| 695 | case 0: |
| 696 | data &= 0xfffeffff; // wp not supported on 386 |
| 697 | CYCLES(CYCLES_MOV_REG_CR0); |
| 698 | break; |
| 699 | case 2: CYCLES(CYCLES_MOV_REG_CR2); break; |
| 700 | case 3: |
| 701 | CYCLES(CYCLES_MOV_REG_CR3); |
| 702 | vtlb_flush_dynamic(m_vtlb); |
| 703 | break; |
| 704 | case 4: CYCLES(1); break; // TODO |
| 705 | default: |
| 706 | logerror("i386: mov_cr_r32 CR%d!\n", cr); |
| 707 | return; |
| 708 | } |
| 709 | m_cr[cr] = data; |
| 710 | } |
| 711 | |
| 712 | void i386_device::i386_mov_dr_r32() // Opcode 0x0f 23 |
| 713 | { |
| 714 | if(PROTECTED_MODE && m_CPL) |
| 715 | FAULT(FAULT_GP, 0); |
| 716 | UINT8 modrm = FETCH(); |
| 717 | UINT8 dr = (modrm >> 3) & 0x7; |
| 718 | |
| 719 | m_dr[dr] = LOAD_RM32(modrm); |
| 720 | switch(dr) |
| 721 | { |
| 722 | case 0: |
| 723 | case 1: |
| 724 | case 2: |
| 725 | case 3: |
| 726 | CYCLES(CYCLES_MOV_DR0_3_REG); |
| 727 | break; |
| 728 | case 6: |
| 729 | case 7: |
| 730 | CYCLES(CYCLES_MOV_DR6_7_REG); |
| 731 | break; |
| 732 | default: |
| 733 | logerror("i386: mov_dr_r32 DR%d!\n", dr); |
| 734 | return; |
| 735 | } |
| 736 | } |
| 737 | |
| 738 | void i386_device::i386_mov_al_m8() // Opcode 0xa0 |
| 739 | { |
| 740 | UINT32 offset, ea; |
| 741 | if( m_address_size ) { |
| 742 | offset = FETCH32(); |
| 743 | } else { |
| 744 | offset = FETCH16(); |
| 745 | } |
| 746 | /* TODO: Not sure if this is correct... */ |
| 747 | if( m_segment_prefix ) { |
| 748 | ea = i386_translate(m_segment_override, offset, 0 ); |
| 749 | } else { |
| 750 | ea = i386_translate(DS, offset, 0 ); |
| 751 | } |
| 752 | REG8(AL) = READ8(ea); |
| 753 | CYCLES(CYCLES_MOV_IMM_MEM); |
| 754 | } |
| 755 | |
| 756 | void i386_device::i386_mov_m8_al() // Opcode 0xa2 |
| 757 | { |
| 758 | UINT32 offset, ea; |
| 759 | if( m_address_size ) { |
| 760 | offset = FETCH32(); |
| 761 | } else { |
| 762 | offset = FETCH16(); |
| 763 | } |
| 764 | /* TODO: Not sure if this is correct... */ |
| 765 | if( m_segment_prefix ) { |
| 766 | ea = i386_translate(m_segment_override, offset, 1 ); |
| 767 | } else { |
| 768 | ea = i386_translate(DS, offset, 1 ); |
| 769 | } |
| 770 | WRITE8(ea, REG8(AL) ); |
| 771 | CYCLES(CYCLES_MOV_MEM_ACC); |
| 772 | } |
| 773 | |
| 774 | void i386_device::i386_mov_rm16_sreg() // Opcode 0x8c |
| 775 | { |
| 776 | UINT8 modrm = FETCH(); |
| 777 | int s = (modrm >> 3) & 0x7; |
| 778 | |
| 779 | if( modrm >= 0xc0 ) { |
| 780 | if(m_operand_size) |
| 781 | STORE_RM32(modrm, m_sreg[s].selector); |
| 782 | else |
| 783 | STORE_RM16(modrm, m_sreg[s].selector); |
| 784 | CYCLES(CYCLES_MOV_SREG_REG); |
| 785 | } else { |
| 786 | UINT32 ea = GetEA(modrm,1); |
| 787 | WRITE16(ea, m_sreg[s].selector); |
| 788 | CYCLES(CYCLES_MOV_SREG_MEM); |
| 789 | } |
| 790 | } |
| 791 | |
| 792 | void i386_device::i386_mov_sreg_rm16() // Opcode 0x8e |
| 793 | { |
| 794 | UINT16 selector; |
| 795 | UINT8 modrm = FETCH(); |
| 796 | bool fault; |
| 797 | int s = (modrm >> 3) & 0x7; |
| 798 | |
| 799 | if( modrm >= 0xc0 ) { |
| 800 | selector = LOAD_RM16(modrm); |
| 801 | CYCLES(CYCLES_MOV_REG_SREG); |
| 802 | } else { |
| 803 | UINT32 ea = GetEA(modrm,0); |
| 804 | selector = READ16(ea); |
| 805 | CYCLES(CYCLES_MOV_MEM_SREG); |
| 806 | } |
| 807 | |
| 808 | i386_sreg_load(selector,s,&fault); |
| 809 | if((s == SS) && !fault) |
| 810 | { |
| 811 | if(m_IF != 0) // if external interrupts are enabled |
| 812 | { |
| 813 | m_IF = 0; // reset IF for the next instruction |
| 814 | m_delayed_interrupt_enable = 1; |
| 815 | } |
| 816 | } |
| 817 | } |
| 818 | |
| 819 | void i386_device::i386_mov_al_i8() // Opcode 0xb0 |
| 820 | { |
| 821 | REG8(AL) = FETCH(); |
| 822 | CYCLES(CYCLES_MOV_IMM_REG); |
| 823 | } |
| 824 | |
| 825 | void i386_device::i386_mov_cl_i8() // Opcode 0xb1 |
| 826 | { |
| 827 | REG8(CL) = FETCH(); |
| 828 | CYCLES(CYCLES_MOV_IMM_REG); |
| 829 | } |
| 830 | |
| 831 | void i386_device::i386_mov_dl_i8() // Opcode 0xb2 |
| 832 | { |
| 833 | REG8(DL) = FETCH(); |
| 834 | CYCLES(CYCLES_MOV_IMM_REG); |
| 835 | } |
| 836 | |
| 837 | void i386_device::i386_mov_bl_i8() // Opcode 0xb3 |
| 838 | { |
| 839 | REG8(BL) = FETCH(); |
| 840 | CYCLES(CYCLES_MOV_IMM_REG); |
| 841 | } |
| 842 | |
| 843 | void i386_device::i386_mov_ah_i8() // Opcode 0xb4 |
| 844 | { |
| 845 | REG8(AH) = FETCH(); |
| 846 | CYCLES(CYCLES_MOV_IMM_REG); |
| 847 | } |
| 848 | |
| 849 | void i386_device::i386_mov_ch_i8() // Opcode 0xb5 |
| 850 | { |
| 851 | REG8(CH) = FETCH(); |
| 852 | CYCLES(CYCLES_MOV_IMM_REG); |
| 853 | } |
| 854 | |
| 855 | void i386_device::i386_mov_dh_i8() // Opcode 0xb6 |
| 856 | { |
| 857 | REG8(DH) = FETCH(); |
| 858 | CYCLES(CYCLES_MOV_IMM_REG); |
| 859 | } |
| 860 | |
| 861 | void i386_device::i386_mov_bh_i8() // Opcode 0xb7 |
| 862 | { |
| 863 | REG8(BH) = FETCH(); |
| 864 | CYCLES(CYCLES_MOV_IMM_REG); |
| 865 | } |
| 866 | |
| 867 | void i386_device::i386_movsb() // Opcode 0xa4 |
| 868 | { |
| 869 | UINT32 eas, ead; |
| 870 | UINT8 v; |
| 871 | if( m_segment_prefix ) { |
| 872 | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 873 | } else { |
| 874 | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 875 | } |
| 876 | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 877 | v = READ8(eas); |
| 878 | WRITE8(ead, v); |
| 879 | BUMP_SI(1); |
| 880 | BUMP_DI(1); |
| 881 | CYCLES(CYCLES_MOVS); |
| 882 | } |
| 883 | |
| 884 | void i386_device::i386_or_rm8_r8() // Opcode 0x08 |
| 885 | { |
| 886 | UINT8 src, dst; |
| 887 | UINT8 modrm = FETCH(); |
| 888 | if( modrm >= 0xc0 ) { |
| 889 | src = LOAD_REG8(modrm); |
| 890 | dst = LOAD_RM8(modrm); |
| 891 | dst = OR8(dst, src); |
| 892 | STORE_RM8(modrm, dst); |
| 893 | CYCLES(CYCLES_ALU_REG_REG); |
| 894 | } else { |
| 895 | UINT32 ea = GetEA(modrm,1); |
| 896 | src = LOAD_REG8(modrm); |
| 897 | dst = READ8(ea); |
| 898 | dst = OR8(dst, src); |
| 899 | WRITE8(ea, dst); |
| 900 | CYCLES(CYCLES_ALU_REG_MEM); |
| 901 | } |
| 902 | } |
| 903 | |
| 904 | void i386_device::i386_or_r8_rm8() // Opcode 0x0a |
| 905 | { |
| 906 | UINT8 src, dst; |
| 907 | UINT8 modrm = FETCH(); |
| 908 | if( modrm >= 0xc0 ) { |
| 909 | src = LOAD_RM8(modrm); |
| 910 | dst = LOAD_REG8(modrm); |
| 911 | dst = OR8(dst, src); |
| 912 | STORE_REG8(modrm, dst); |
| 913 | CYCLES(CYCLES_ALU_REG_REG); |
| 914 | } else { |
| 915 | UINT32 ea = GetEA(modrm,0); |
| 916 | src = READ8(ea); |
| 917 | dst = LOAD_REG8(modrm); |
| 918 | dst = OR8(dst, src); |
| 919 | STORE_REG8(modrm, dst); |
| 920 | CYCLES(CYCLES_ALU_MEM_REG); |
| 921 | } |
| 922 | } |
| 923 | |
| 924 | void i386_device::i386_or_al_i8() // Opcode 0x0c |
| 925 | { |
| 926 | UINT8 src, dst; |
| 927 | src = FETCH(); |
| 928 | dst = REG8(AL); |
| 929 | dst = OR8(dst, src); |
| 930 | REG8(EAX) = dst; |
| 931 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 932 | } |
| 933 | |
| 934 | void i386_device::i386_out_al_i8() // Opcode 0xe6 |
| 935 | { |
| 936 | UINT16 port = FETCH(); |
| 937 | UINT8 data = REG8(AL); |
| 938 | WRITEPORT8(port, data); |
| 939 | CYCLES(CYCLES_OUT_VAR); |
| 940 | } |
| 941 | |
| 942 | void i386_device::i386_out_al_dx() // Opcode 0xee |
| 943 | { |
| 944 | UINT16 port = REG16(DX); |
| 945 | UINT8 data = REG8(AL); |
| 946 | WRITEPORT8(port, data); |
| 947 | CYCLES(CYCLES_OUT); |
| 948 | } |
| 949 | |
| 950 | |
| 951 | void i386_device::i386_arpl() // Opcode 0x63 |
| 952 | { |
| 953 | UINT16 src, dst; |
| 954 | UINT8 modrm = FETCH(); |
| 955 | UINT8 flag = 0; |
| 956 | |
| 957 | if(PROTECTED_MODE && !V8086_MODE) |
| 958 | { |
| 959 | if( modrm >= 0xc0 ) { |
| 960 | src = LOAD_REG16(modrm); |
| 961 | dst = LOAD_RM16(modrm); |
| 962 | if( (dst&0x3) < (src&0x3) ) { |
| 963 | dst = (dst&0xfffc) | (src&0x3); |
| 964 | flag = 1; |
| 965 | STORE_RM16(modrm, dst); |
| 966 | } |
| 967 | } else { |
| 968 | UINT32 ea = GetEA(modrm,1); |
| 969 | src = LOAD_REG16(modrm); |
| 970 | dst = READ16(ea); |
| 971 | if( (dst&0x3) < (src&0x3) ) { |
| 972 | dst = (dst&0xfffc) | (src&0x3); |
| 973 | flag = 1; |
| 974 | WRITE16(ea, dst); |
| 975 | } |
| 976 | } |
| 977 | SetZF(flag); |
| 978 | } |
| 979 | else |
| 980 | i386_trap(6, 0, 0); // invalid opcode in real mode or v8086 mode |
| 981 | } |
| 982 | |
| 983 | void i386_device::i386_push_i8() // Opcode 0x6a |
| 984 | { |
| 985 | UINT8 value = FETCH(); |
| 986 | PUSH8(value); |
| 987 | CYCLES(CYCLES_PUSH_IMM); |
| 988 | } |
| 989 | |
| 990 | void i386_device::i386_ins_generic(int size) |
| 991 | { |
| 992 | UINT32 ead; |
| 993 | UINT8 vb; |
| 994 | UINT16 vw; |
| 995 | UINT32 vd; |
| 996 | |
| 997 | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 998 | |
| 999 | switch(size) { |
| 1000 | case 1: |
| 1001 | vb = READPORT8(REG16(DX)); |
| 1002 | WRITE8(ead, vb); |
| 1003 | break; |
| 1004 | case 2: |
| 1005 | vw = READPORT16(REG16(DX)); |
| 1006 | WRITE16(ead, vw); |
| 1007 | break; |
| 1008 | case 4: |
| 1009 | vd = READPORT32(REG16(DX)); |
| 1010 | WRITE32(ead, vd); |
| 1011 | break; |
| 1012 | } |
| 1013 | |
| 1014 | if(m_address_size) |
| 1015 | REG32(EDI) += ((m_DF) ? -1 : 1) * size; |
| 1016 | else |
| 1017 | REG16(DI) += ((m_DF) ? -1 : 1) * size; |
| 1018 | CYCLES(CYCLES_INS); // TODO: Confirm this value |
| 1019 | } |
| 1020 | |
| 1021 | void i386_device::i386_insb() // Opcode 0x6c |
| 1022 | { |
| 1023 | i386_ins_generic(1); |
| 1024 | } |
| 1025 | |
| 1026 | void i386_device::i386_insw() // Opcode 0x6d |
| 1027 | { |
| 1028 | i386_ins_generic(2); |
| 1029 | } |
| 1030 | |
| 1031 | void i386_device::i386_insd() // Opcode 0x6d |
| 1032 | { |
| 1033 | i386_ins_generic(4); |
| 1034 | } |
| 1035 | |
| 1036 | void i386_device::i386_outs_generic(int size) |
| 1037 | { |
| 1038 | UINT32 eas; |
| 1039 | UINT8 vb; |
| 1040 | UINT16 vw; |
| 1041 | UINT32 vd; |
| 1042 | |
| 1043 | if( m_segment_prefix ) { |
| 1044 | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1045 | } else { |
| 1046 | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1047 | } |
| 1048 | |
| 1049 | switch(size) { |
| 1050 | case 1: |
| 1051 | vb = READ8(eas); |
| 1052 | WRITEPORT8(REG16(DX), vb); |
| 1053 | break; |
| 1054 | case 2: |
| 1055 | vw = READ16(eas); |
| 1056 | WRITEPORT16(REG16(DX), vw); |
| 1057 | break; |
| 1058 | case 4: |
| 1059 | vd = READ32(eas); |
| 1060 | WRITEPORT32(REG16(DX), vd); |
| 1061 | break; |
| 1062 | } |
| 1063 | |
| 1064 | if(m_address_size) |
| 1065 | REG32(ESI) += ((m_DF) ? -1 : 1) * size; |
| 1066 | else |
| 1067 | REG16(SI) += ((m_DF) ? -1 : 1) * size; |
| 1068 | CYCLES(CYCLES_OUTS); // TODO: Confirm this value |
| 1069 | } |
| 1070 | |
| 1071 | void i386_device::i386_outsb() // Opcode 0x6e |
| 1072 | { |
| 1073 | i386_outs_generic(1); |
| 1074 | } |
| 1075 | |
| 1076 | void i386_device::i386_outsw() // Opcode 0x6f |
| 1077 | { |
| 1078 | i386_outs_generic(2); |
| 1079 | } |
| 1080 | |
| 1081 | void i386_device::i386_outsd() // Opcode 0x6f |
| 1082 | { |
| 1083 | i386_outs_generic(4); |
| 1084 | } |
| 1085 | |
| 1086 | void i386_device::i386_repeat(int invert_flag) |
| 1087 | { |
| 1088 | UINT32 repeated_eip = m_eip; |
| 1089 | UINT32 repeated_pc = m_pc; |
| 1090 | UINT8 opcode; // = FETCH(); |
| 1091 | // UINT32 eas, ead; |
| 1092 | UINT32 count; |
| 1093 | INT32 cycle_base = 0, cycle_adjustment = 0; |
| 1094 | UINT8 prefix_flag=1; |
| 1095 | UINT8 *flag = NULL; |
| 1096 | |
| 1097 | |
| 1098 | do { |
| 1099 | repeated_eip = m_eip; |
| 1100 | repeated_pc = m_pc; |
| 1101 | opcode = FETCH(); |
| 1102 | switch(opcode) { |
| 1103 | case 0x0f: |
| 1104 | if (invert_flag == 0) |
| 1105 | i386_decode_three_bytef3(); // sse f3 0f |
| 1106 | else |
| 1107 | i386_decode_three_bytef2(); // sse f2 0f |
| 1108 | return; |
| 1109 | case 0x26: |
| 1110 | m_segment_override=ES; |
| 1111 | m_segment_prefix=1; |
| 1112 | break; |
| 1113 | case 0x2e: |
| 1114 | m_segment_override=CS; |
| 1115 | m_segment_prefix=1; |
| 1116 | break; |
| 1117 | case 0x36: |
| 1118 | m_segment_override=SS; |
| 1119 | m_segment_prefix=1; |
| 1120 | break; |
| 1121 | case 0x3e: |
| 1122 | m_segment_override=DS; |
| 1123 | m_segment_prefix=1; |
| 1124 | break; |
| 1125 | case 0x64: |
| 1126 | m_segment_override=FS; |
| 1127 | m_segment_prefix=1; |
| 1128 | break; |
| 1129 | case 0x65: |
| 1130 | m_segment_override=GS; |
| 1131 | m_segment_prefix=1; |
| 1132 | break; |
| 1133 | case 0x66: |
| 1134 | m_operand_size ^= 1; |
| 1135 | break; |
| 1136 | case 0x67: |
| 1137 | m_address_size ^= 1; |
| 1138 | break; |
| 1139 | default: |
| 1140 | prefix_flag=0; |
| 1141 | } |
| 1142 | } while (prefix_flag); |
| 1143 | |
| 1144 | |
| 1145 | if( m_segment_prefix ) { |
| 1146 | // FIXME: the following does not work if both address override and segment override are used |
| 1147 | i386_translate(m_segment_override, m_sreg[m_segment_prefix].d ? REG32(ESI) : REG16(SI), -1 ); |
| 1148 | } else { |
| 1149 | //eas = |
| 1150 | i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), -1 ); |
| 1151 | } |
| 1152 | i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), -1 ); |
| 1153 | |
| 1154 | switch(opcode) |
| 1155 | { |
| 1156 | case 0x6c: |
| 1157 | case 0x6d: |
| 1158 | /* INSB, INSW, INSD */ |
| 1159 | // TODO: cycle count |
| 1160 | cycle_base = 8; |
| 1161 | cycle_adjustment = -4; |
| 1162 | flag = NULL; |
| 1163 | break; |
| 1164 | |
| 1165 | case 0x6e: |
| 1166 | case 0x6f: |
| 1167 | /* OUTSB, OUTSW, OUTSD */ |
| 1168 | // TODO: cycle count |
| 1169 | cycle_base = 8; |
| 1170 | cycle_adjustment = -4; |
| 1171 | flag = NULL; |
| 1172 | break; |
| 1173 | |
| 1174 | case 0xa4: |
| 1175 | case 0xa5: |
| 1176 | /* MOVSB, MOVSW, MOVSD */ |
| 1177 | cycle_base = 8; |
| 1178 | cycle_adjustment = -4; |
| 1179 | flag = NULL; |
| 1180 | break; |
| 1181 | |
| 1182 | case 0xa6: |
| 1183 | case 0xa7: |
| 1184 | /* CMPSB, CMPSW, CMPSD */ |
| 1185 | cycle_base = 5; |
| 1186 | cycle_adjustment = -1; |
| 1187 | flag = &m_ZF; |
| 1188 | break; |
| 1189 | |
| 1190 | case 0xac: |
| 1191 | case 0xad: |
| 1192 | /* LODSB, LODSW, LODSD */ |
| 1193 | cycle_base = 5; |
| 1194 | cycle_adjustment = 1; |
| 1195 | flag = NULL; |
| 1196 | break; |
| 1197 | |
| 1198 | case 0xaa: |
| 1199 | case 0xab: |
| 1200 | /* STOSB, STOSW, STOSD */ |
| 1201 | cycle_base = 5; |
| 1202 | cycle_adjustment = 0; |
| 1203 | flag = NULL; |
| 1204 | break; |
| 1205 | |
| 1206 | case 0xae: |
| 1207 | case 0xaf: |
| 1208 | /* SCASB, SCASW, SCASD */ |
| 1209 | cycle_base = 5; |
| 1210 | cycle_adjustment = 0; |
| 1211 | flag = &m_ZF; |
| 1212 | break; |
| 1213 | |
| 1214 | case 0x90: |
| 1215 | CYCLES(CYCLES_NOP); |
| 1216 | return; |
| 1217 | |
| 1218 | case 0xc2: // sigh |
| 1219 | case 0xc3: |
| 1220 | m_pc--; |
| 1221 | return; |
| 1222 | |
| 1223 | default: |
| 1224 | fatalerror("i386: Invalid REP/opcode %02X combination\n",opcode); |
| 1225 | break; |
| 1226 | } |
| 1227 | |
| 1228 | if( m_address_size ) { |
| 1229 | if( REG32(ECX) == 0 ) |
| 1230 | return; |
| 1231 | } else { |
| 1232 | if( REG16(CX) == 0 ) |
| 1233 | return; |
| 1234 | } |
| 1235 | |
| 1236 | /* now actually perform the repeat */ |
| 1237 | CYCLES_NUM(cycle_base); |
| 1238 | do |
| 1239 | { |
| 1240 | m_eip = repeated_eip; |
| 1241 | m_pc = repeated_pc; |
| 1242 | try |
| 1243 | { |
| 1244 | i386_decode_opcode(); |
| 1245 | } |
| 1246 | catch (UINT64 e) |
| 1247 | { |
| 1248 | m_eip = m_prev_eip; |
| 1249 | throw e; |
| 1250 | } |
| 1251 | |
| 1252 | CYCLES_NUM(cycle_adjustment); |
| 1253 | |
| 1254 | if (m_address_size) |
| 1255 | count = --REG32(ECX); |
| 1256 | else |
| 1257 | count = --REG16(CX); |
| 1258 | if (m_cycles <= 0) |
| 1259 | goto outofcycles; |
| 1260 | } |
| 1261 | while( count && (!flag || (invert_flag ? !*flag : *flag)) ); |
| 1262 | return; |
| 1263 | |
| 1264 | outofcycles: |
| 1265 | /* if we run out of cycles to execute, and we are still in the repeat, we need |
| 1266 | * to exit this instruction in such a way to go right back into it when we have |
| 1267 | * time to execute cycles */ |
| 1268 | if(flag && (invert_flag ? *flag : !*flag)) |
| 1269 | return; |
| 1270 | m_eip = m_prev_eip; |
| 1271 | CHANGE_PC(m_eip); |
| 1272 | CYCLES_NUM(-cycle_base); |
| 1273 | } |
| 1274 | |
| 1275 | void i386_device::i386_rep() // Opcode 0xf3 |
| 1276 | { |
| 1277 | i386_repeat(0); |
| 1278 | } |
| 1279 | |
| 1280 | void i386_device::i386_repne() // Opcode 0xf2 |
| 1281 | { |
| 1282 | i386_repeat(1); |
| 1283 | } |
| 1284 | |
| 1285 | void i386_device::i386_sahf() // Opcode 0x9e |
| 1286 | { |
| 1287 | set_flags((get_flags() & 0xffffff00) | (REG8(AH) & 0xd7) ); |
| 1288 | CYCLES(CYCLES_SAHF); |
| 1289 | } |
| 1290 | |
| 1291 | void i386_device::i386_sbb_rm8_r8() // Opcode 0x18 |
| 1292 | { |
| 1293 | UINT8 src, dst; |
| 1294 | UINT8 modrm = FETCH(); |
| 1295 | if( modrm >= 0xc0 ) { |
| 1296 | src = LOAD_REG8(modrm); |
| 1297 | dst = LOAD_RM8(modrm); |
| 1298 | dst = SBB8(dst, src, m_CF); |
| 1299 | STORE_RM8(modrm, dst); |
| 1300 | CYCLES(CYCLES_ALU_REG_REG); |
| 1301 | } else { |
| 1302 | UINT32 ea = GetEA(modrm,1); |
| 1303 | src = LOAD_REG8(modrm); |
| 1304 | dst = READ8(ea); |
| 1305 | dst = SBB8(dst, src, m_CF); |
| 1306 | WRITE8(ea, dst); |
| 1307 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1308 | } |
| 1309 | } |
| 1310 | |
| 1311 | void i386_device::i386_sbb_r8_rm8() // Opcode 0x1a |
| 1312 | { |
| 1313 | UINT8 src, dst; |
| 1314 | UINT8 modrm = FETCH(); |
| 1315 | if( modrm >= 0xc0 ) { |
| 1316 | src = LOAD_RM8(modrm); |
| 1317 | dst = LOAD_REG8(modrm); |
| 1318 | dst = SBB8(dst, src, m_CF); |
| 1319 | STORE_REG8(modrm, dst); |
| 1320 | CYCLES(CYCLES_ALU_REG_REG); |
| 1321 | } else { |
| 1322 | UINT32 ea = GetEA(modrm,0); |
| 1323 | src = READ8(ea); |
| 1324 | dst = LOAD_REG8(modrm); |
| 1325 | dst = SBB8(dst, src, m_CF); |
| 1326 | STORE_REG8(modrm, dst); |
| 1327 | CYCLES(CYCLES_ALU_MEM_REG); |
| 1328 | } |
| 1329 | } |
| 1330 | |
| 1331 | void i386_device::i386_sbb_al_i8() // Opcode 0x1c |
| 1332 | { |
| 1333 | UINT8 src, dst; |
| 1334 | src = FETCH(); |
| 1335 | dst = REG8(AL); |
| 1336 | dst = SBB8(dst, src, m_CF); |
| 1337 | REG8(EAX) = dst; |
| 1338 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1339 | } |
| 1340 | |
| 1341 | void i386_device::i386_scasb() // Opcode 0xae |
| 1342 | { |
| 1343 | UINT32 eas; |
| 1344 | UINT8 src, dst; |
| 1345 | eas = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 ); |
| 1346 | src = READ8(eas); |
| 1347 | dst = REG8(AL); |
| 1348 | SUB8(dst, src); |
| 1349 | BUMP_DI(1); |
| 1350 | CYCLES(CYCLES_SCAS); |
| 1351 | } |
| 1352 | |
| 1353 | void i386_device::i386_setalc() // Opcode 0xd6 (undocumented) |
| 1354 | { |
| 1355 | if( m_CF ) { |
| 1356 | REG8(AL) = 0xff; |
| 1357 | } else { |
| 1358 | REG8(AL) = 0; |
| 1359 | } |
| 1360 | CYCLES(3); |
| 1361 | } |
| 1362 | |
| 1363 | void i386_device::i386_seta_rm8() // Opcode 0x0f 97 |
| 1364 | { |
| 1365 | UINT8 modrm = FETCH(); |
| 1366 | UINT8 value = 0; |
| 1367 | if( m_CF == 0 && m_ZF == 0 ) { |
| 1368 | value = 1; |
| 1369 | } |
| 1370 | if( modrm >= 0xc0 ) { |
| 1371 | STORE_RM8(modrm, value); |
| 1372 | CYCLES(CYCLES_SETCC_REG); |
| 1373 | } else { |
| 1374 | UINT32 ea = GetEA(modrm,1); |
| 1375 | WRITE8(ea, value); |
| 1376 | CYCLES(CYCLES_SETCC_MEM); |
| 1377 | } |
| 1378 | } |
| 1379 | |
| 1380 | void i386_device::i386_setbe_rm8() // Opcode 0x0f 96 |
| 1381 | { |
| 1382 | UINT8 modrm = FETCH(); |
| 1383 | UINT8 value = 0; |
| 1384 | if( m_CF != 0 || m_ZF != 0 ) { |
| 1385 | value = 1; |
| 1386 | } |
| 1387 | if( modrm >= 0xc0 ) { |
| 1388 | STORE_RM8(modrm, value); |
| 1389 | CYCLES(CYCLES_SETCC_REG); |
| 1390 | } else { |
| 1391 | UINT32 ea = GetEA(modrm,1); |
| 1392 | WRITE8(ea, value); |
| 1393 | CYCLES(CYCLES_SETCC_MEM); |
| 1394 | } |
| 1395 | } |
| 1396 | |
| 1397 | void i386_device::i386_setc_rm8() // Opcode 0x0f 92 |
| 1398 | { |
| 1399 | UINT8 modrm = FETCH(); |
| 1400 | UINT8 value = 0; |
| 1401 | if( m_CF != 0 ) { |
| 1402 | value = 1; |
| 1403 | } |
| 1404 | if( modrm >= 0xc0 ) { |
| 1405 | STORE_RM8(modrm, value); |
| 1406 | CYCLES(CYCLES_SETCC_REG); |
| 1407 | } else { |
| 1408 | UINT32 ea = GetEA(modrm,1); |
| 1409 | WRITE8(ea, value); |
| 1410 | CYCLES(CYCLES_SETCC_MEM); |
| 1411 | } |
| 1412 | } |
| 1413 | |
| 1414 | void i386_device::i386_setg_rm8() // Opcode 0x0f 9f |
| 1415 | { |
| 1416 | UINT8 modrm = FETCH(); |
| 1417 | UINT8 value = 0; |
| 1418 | if( m_ZF == 0 && (m_SF == m_OF) ) { |
| 1419 | value = 1; |
| 1420 | } |
| 1421 | if( modrm >= 0xc0 ) { |
| 1422 | STORE_RM8(modrm, value); |
| 1423 | CYCLES(CYCLES_SETCC_REG); |
| 1424 | } else { |
| 1425 | UINT32 ea = GetEA(modrm,1); |
| 1426 | WRITE8(ea, value); |
| 1427 | CYCLES(CYCLES_SETCC_MEM); |
| 1428 | } |
| 1429 | } |
| 1430 | |
| 1431 | void i386_device::i386_setge_rm8() // Opcode 0x0f 9d |
| 1432 | { |
| 1433 | UINT8 modrm = FETCH(); |
| 1434 | UINT8 value = 0; |
| 1435 | if(m_SF == m_OF) { |
| 1436 | value = 1; |
| 1437 | } |
| 1438 | if( modrm >= 0xc0 ) { |
| 1439 | STORE_RM8(modrm, value); |
| 1440 | CYCLES(CYCLES_SETCC_REG); |
| 1441 | } else { |
| 1442 | UINT32 ea = GetEA(modrm,1); |
| 1443 | WRITE8(ea, value); |
| 1444 | CYCLES(CYCLES_SETCC_MEM); |
| 1445 | } |
| 1446 | } |
| 1447 | |
| 1448 | void i386_device::i386_setl_rm8() // Opcode 0x0f 9c |
| 1449 | { |
| 1450 | UINT8 modrm = FETCH(); |
| 1451 | UINT8 value = 0; |
| 1452 | if( m_SF != m_OF ) { |
| 1453 | value = 1; |
| 1454 | } |
| 1455 | if( modrm >= 0xc0 ) { |
| 1456 | STORE_RM8(modrm, value); |
| 1457 | CYCLES(CYCLES_SETCC_REG); |
| 1458 | } else { |
| 1459 | UINT32 ea = GetEA(modrm,1); |
| 1460 | WRITE8(ea, value); |
| 1461 | CYCLES(CYCLES_SETCC_MEM); |
| 1462 | } |
| 1463 | } |
| 1464 | |
| 1465 | void i386_device::i386_setle_rm8() // Opcode 0x0f 9e |
| 1466 | { |
| 1467 | UINT8 modrm = FETCH(); |
| 1468 | UINT8 value = 0; |
| 1469 | if( m_ZF != 0 || (m_SF != m_OF) ) { |
| 1470 | value = 1; |
| 1471 | } |
| 1472 | if( modrm >= 0xc0 ) { |
| 1473 | STORE_RM8(modrm, value); |
| 1474 | CYCLES(CYCLES_SETCC_REG); |
| 1475 | } else { |
| 1476 | UINT32 ea = GetEA(modrm,1); |
| 1477 | WRITE8(ea, value); |
| 1478 | CYCLES(CYCLES_SETCC_MEM); |
| 1479 | } |
| 1480 | } |
| 1481 | |
| 1482 | void i386_device::i386_setnc_rm8() // Opcode 0x0f 93 |
| 1483 | { |
| 1484 | UINT8 modrm = FETCH(); |
| 1485 | UINT8 value = 0; |
| 1486 | if( m_CF == 0 ) { |
| 1487 | value = 1; |
| 1488 | } |
| 1489 | if( modrm >= 0xc0 ) { |
| 1490 | STORE_RM8(modrm, value); |
| 1491 | CYCLES(CYCLES_SETCC_REG); |
| 1492 | } else { |
| 1493 | UINT32 ea = GetEA(modrm,1); |
| 1494 | WRITE8(ea, value); |
| 1495 | CYCLES(CYCLES_SETCC_MEM); |
| 1496 | } |
| 1497 | } |
| 1498 | |
| 1499 | void i386_device::i386_setno_rm8() // Opcode 0x0f 91 |
| 1500 | { |
| 1501 | UINT8 modrm = FETCH(); |
| 1502 | UINT8 value = 0; |
| 1503 | if( m_OF == 0 ) { |
| 1504 | value = 1; |
| 1505 | } |
| 1506 | if( modrm >= 0xc0 ) { |
| 1507 | STORE_RM8(modrm, value); |
| 1508 | CYCLES(CYCLES_SETCC_REG); |
| 1509 | } else { |
| 1510 | UINT32 ea = GetEA(modrm,1); |
| 1511 | WRITE8(ea, value); |
| 1512 | CYCLES(CYCLES_SETCC_MEM); |
| 1513 | } |
| 1514 | } |
| 1515 | |
| 1516 | void i386_device::i386_setnp_rm8() // Opcode 0x0f 9b |
| 1517 | { |
| 1518 | UINT8 modrm = FETCH(); |
| 1519 | UINT8 value = 0; |
| 1520 | if( m_PF == 0 ) { |
| 1521 | value = 1; |
| 1522 | } |
| 1523 | if( modrm >= 0xc0 ) { |
| 1524 | STORE_RM8(modrm, value); |
| 1525 | CYCLES(CYCLES_SETCC_REG); |
| 1526 | } else { |
| 1527 | UINT32 ea = GetEA(modrm,1); |
| 1528 | WRITE8(ea, value); |
| 1529 | CYCLES(CYCLES_SETCC_MEM); |
| 1530 | } |
| 1531 | } |
| 1532 | |
| 1533 | void i386_device::i386_setns_rm8() // Opcode 0x0f 99 |
| 1534 | { |
| 1535 | UINT8 modrm = FETCH(); |
| 1536 | UINT8 value = 0; |
| 1537 | if( m_SF == 0 ) { |
| 1538 | value = 1; |
| 1539 | } |
| 1540 | if( modrm >= 0xc0 ) { |
| 1541 | STORE_RM8(modrm, value); |
| 1542 | CYCLES(CYCLES_SETCC_REG); |
| 1543 | } else { |
| 1544 | UINT32 ea = GetEA(modrm,1); |
| 1545 | WRITE8(ea, value); |
| 1546 | CYCLES(CYCLES_SETCC_MEM); |
| 1547 | } |
| 1548 | } |
| 1549 | |
| 1550 | void i386_device::i386_setnz_rm8() // Opcode 0x0f 95 |
| 1551 | { |
| 1552 | UINT8 modrm = FETCH(); |
| 1553 | UINT8 value = 0; |
| 1554 | if( m_ZF == 0 ) { |
| 1555 | value = 1; |
| 1556 | } |
| 1557 | if( modrm >= 0xc0 ) { |
| 1558 | STORE_RM8(modrm, value); |
| 1559 | CYCLES(CYCLES_SETCC_REG); |
| 1560 | } else { |
| 1561 | UINT32 ea = GetEA(modrm,1); |
| 1562 | WRITE8(ea, value); |
| 1563 | CYCLES(CYCLES_SETCC_MEM); |
| 1564 | } |
| 1565 | } |
| 1566 | |
| 1567 | void i386_device::i386_seto_rm8() // Opcode 0x0f 90 |
| 1568 | { |
| 1569 | UINT8 modrm = FETCH(); |
| 1570 | UINT8 value = 0; |
| 1571 | if( m_OF != 0 ) { |
| 1572 | value = 1; |
| 1573 | } |
| 1574 | if( modrm >= 0xc0 ) { |
| 1575 | STORE_RM8(modrm, value); |
| 1576 | CYCLES(CYCLES_SETCC_REG); |
| 1577 | } else { |
| 1578 | UINT32 ea = GetEA(modrm,1); |
| 1579 | WRITE8(ea, value); |
| 1580 | CYCLES(CYCLES_SETCC_MEM); |
| 1581 | } |
| 1582 | } |
| 1583 | |
| 1584 | void i386_device::i386_setp_rm8() // Opcode 0x0f 9a |
| 1585 | { |
| 1586 | UINT8 modrm = FETCH(); |
| 1587 | UINT8 value = 0; |
| 1588 | if( m_PF != 0 ) { |
| 1589 | value = 1; |
| 1590 | } |
| 1591 | if( modrm >= 0xc0 ) { |
| 1592 | STORE_RM8(modrm, value); |
| 1593 | CYCLES(CYCLES_SETCC_REG); |
| 1594 | } else { |
| 1595 | UINT32 ea = GetEA(modrm,1); |
| 1596 | WRITE8(ea, value); |
| 1597 | CYCLES(CYCLES_SETCC_MEM); |
| 1598 | } |
| 1599 | } |
| 1600 | |
| 1601 | void i386_device::i386_sets_rm8() // Opcode 0x0f 98 |
| 1602 | { |
| 1603 | UINT8 modrm = FETCH(); |
| 1604 | UINT8 value = 0; |
| 1605 | if( m_SF != 0 ) { |
| 1606 | value = 1; |
| 1607 | } |
| 1608 | if( modrm >= 0xc0 ) { |
| 1609 | STORE_RM8(modrm, value); |
| 1610 | CYCLES(CYCLES_SETCC_REG); |
| 1611 | } else { |
| 1612 | UINT32 ea = GetEA(modrm,1); |
| 1613 | WRITE8(ea, value); |
| 1614 | CYCLES(CYCLES_SETCC_MEM); |
| 1615 | } |
| 1616 | } |
| 1617 | |
| 1618 | void i386_device::i386_setz_rm8() // Opcode 0x0f 94 |
| 1619 | { |
| 1620 | UINT8 modrm = FETCH(); |
| 1621 | UINT8 value = 0; |
| 1622 | if( m_ZF != 0 ) { |
| 1623 | value = 1; |
| 1624 | } |
| 1625 | if( modrm >= 0xc0 ) { |
| 1626 | STORE_RM8(modrm, value); |
| 1627 | CYCLES(CYCLES_SETCC_REG); |
| 1628 | } else { |
| 1629 | UINT32 ea = GetEA(modrm,1); |
| 1630 | WRITE8(ea, value); |
| 1631 | CYCLES(CYCLES_SETCC_MEM); |
| 1632 | } |
| 1633 | } |
| 1634 | |
| 1635 | void i386_device::i386_stc() // Opcode 0xf9 |
| 1636 | { |
| 1637 | m_CF = 1; |
| 1638 | CYCLES(CYCLES_STC); |
| 1639 | } |
| 1640 | |
| 1641 | void i386_device::i386_std() // Opcode 0xfd |
| 1642 | { |
| 1643 | m_DF = 1; |
| 1644 | CYCLES(CYCLES_STD); |
| 1645 | } |
| 1646 | |
| 1647 | void i386_device::i386_sti() // Opcode 0xfb |
| 1648 | { |
| 1649 | if(PROTECTED_MODE) |
| 1650 | { |
| 1651 | UINT8 IOPL = m_IOP1 | (m_IOP2 << 1); |
| 1652 | if(m_CPL > IOPL) |
| 1653 | FAULT(FAULT_GP,0); |
| 1654 | } |
| 1655 | m_delayed_interrupt_enable = 1; // IF is set after the next instruction. |
| 1656 | CYCLES(CYCLES_STI); |
| 1657 | } |
| 1658 | |
| 1659 | void i386_device::i386_stosb() // Opcode 0xaa |
| 1660 | { |
| 1661 | UINT32 ead; |
| 1662 | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 1663 | WRITE8(ead, REG8(AL)); |
| 1664 | BUMP_DI(1); |
| 1665 | CYCLES(CYCLES_STOS); |
| 1666 | } |
| 1667 | |
| 1668 | void i386_device::i386_sub_rm8_r8() // Opcode 0x28 |
| 1669 | { |
| 1670 | UINT8 src, dst; |
| 1671 | UINT8 modrm = FETCH(); |
| 1672 | if( modrm >= 0xc0 ) { |
| 1673 | src = LOAD_REG8(modrm); |
| 1674 | dst = LOAD_RM8(modrm); |
| 1675 | dst = SUB8(dst, src); |
| 1676 | STORE_RM8(modrm, dst); |
| 1677 | CYCLES(CYCLES_ALU_REG_REG); |
| 1678 | } else { |
| 1679 | UINT32 ea = GetEA(modrm,1); |
| 1680 | src = LOAD_REG8(modrm); |
| 1681 | dst = READ8(ea); |
| 1682 | dst = SUB8(dst, src); |
| 1683 | WRITE8(ea, dst); |
| 1684 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1685 | } |
| 1686 | } |
| 1687 | |
| 1688 | void i386_device::i386_sub_r8_rm8() // Opcode 0x2a |
| 1689 | { |
| 1690 | UINT8 src, dst; |
| 1691 | UINT8 modrm = FETCH(); |
| 1692 | if( modrm >= 0xc0 ) { |
| 1693 | src = LOAD_RM8(modrm); |
| 1694 | dst = LOAD_REG8(modrm); |
| 1695 | dst = SUB8(dst, src); |
| 1696 | STORE_REG8(modrm, dst); |
| 1697 | CYCLES(CYCLES_ALU_REG_REG); |
| 1698 | } else { |
| 1699 | UINT32 ea = GetEA(modrm,0); |
| 1700 | src = READ8(ea); |
| 1701 | dst = LOAD_REG8(modrm); |
| 1702 | dst = SUB8(dst, src); |
| 1703 | STORE_REG8(modrm, dst); |
| 1704 | CYCLES(CYCLES_ALU_MEM_REG); |
| 1705 | } |
| 1706 | } |
| 1707 | |
| 1708 | void i386_device::i386_sub_al_i8() // Opcode 0x2c |
| 1709 | { |
| 1710 | UINT8 src, dst; |
| 1711 | src = FETCH(); |
| 1712 | dst = REG8(EAX); |
| 1713 | dst = SUB8(dst, src); |
| 1714 | REG8(EAX) = dst; |
| 1715 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1716 | } |
| 1717 | |
| 1718 | void i386_device::i386_test_al_i8() // Opcode 0xa8 |
| 1719 | { |
| 1720 | UINT8 src = FETCH(); |
| 1721 | UINT8 dst = REG8(AL); |
| 1722 | dst = src & dst; |
| 1723 | SetSZPF8(dst); |
| 1724 | m_CF = 0; |
| 1725 | m_OF = 0; |
| 1726 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1727 | } |
| 1728 | |
| 1729 | void i386_device::i386_test_rm8_r8() // Opcode 0x84 |
| 1730 | { |
| 1731 | UINT8 src, dst; |
| 1732 | UINT8 modrm = FETCH(); |
| 1733 | if( modrm >= 0xc0 ) { |
| 1734 | src = LOAD_REG8(modrm); |
| 1735 | dst = LOAD_RM8(modrm); |
| 1736 | dst = src & dst; |
| 1737 | SetSZPF8(dst); |
| 1738 | m_CF = 0; |
| 1739 | m_OF = 0; |
| 1740 | CYCLES(CYCLES_TEST_REG_REG); |
| 1741 | } else { |
| 1742 | UINT32 ea = GetEA(modrm,0); |
| 1743 | src = LOAD_REG8(modrm); |
| 1744 | dst = READ8(ea); |
| 1745 | dst = src & dst; |
| 1746 | SetSZPF8(dst); |
| 1747 | m_CF = 0; |
| 1748 | m_OF = 0; |
| 1749 | CYCLES(CYCLES_TEST_REG_MEM); |
| 1750 | } |
| 1751 | } |
| 1752 | |
| 1753 | void i386_device::i386_xchg_r8_rm8() // Opcode 0x86 |
| 1754 | { |
| 1755 | UINT8 modrm = FETCH(); |
| 1756 | if( modrm >= 0xc0 ) { |
| 1757 | UINT8 src = LOAD_RM8(modrm); |
| 1758 | UINT8 dst = LOAD_REG8(modrm); |
| 1759 | STORE_REG8(modrm, src); |
| 1760 | STORE_RM8(modrm, dst); |
| 1761 | CYCLES(CYCLES_XCHG_REG_REG); |
| 1762 | } else { |
| 1763 | UINT32 ea = GetEA(modrm,1); |
| 1764 | UINT8 src = READ8(ea); |
| 1765 | UINT8 dst = LOAD_REG8(modrm); |
| 1766 | WRITE8(ea, dst); |
| 1767 | STORE_REG8(modrm, src); |
| 1768 | CYCLES(CYCLES_XCHG_REG_MEM); |
| 1769 | } |
| 1770 | } |
| 1771 | |
| 1772 | void i386_device::i386_xor_rm8_r8() // Opcode 0x30 |
| 1773 | { |
| 1774 | UINT8 src, dst; |
| 1775 | UINT8 modrm = FETCH(); |
| 1776 | if( modrm >= 0xc0 ) { |
| 1777 | src = LOAD_REG8(modrm); |
| 1778 | dst = LOAD_RM8(modrm); |
| 1779 | dst = XOR8(dst, src); |
| 1780 | STORE_RM8(modrm, dst); |
| 1781 | CYCLES(CYCLES_ALU_REG_REG); |
| 1782 | } else { |
| 1783 | UINT32 ea = GetEA(modrm,1); |
| 1784 | src = LOAD_REG8(modrm); |
| 1785 | dst = READ8(ea); |
| 1786 | dst = XOR8(dst, src); |
| 1787 | WRITE8(ea, dst); |
| 1788 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1789 | } |
| 1790 | } |
| 1791 | |
| 1792 | void i386_device::i386_xor_r8_rm8() // Opcode 0x32 |
| 1793 | { |
| 1794 | UINT32 src, dst; |
| 1795 | UINT8 modrm = FETCH(); |
| 1796 | if( modrm >= 0xc0 ) { |
| 1797 | src = LOAD_RM8(modrm); |
| 1798 | dst = LOAD_REG8(modrm); |
| 1799 | dst = XOR8(dst, src); |
| 1800 | STORE_REG8(modrm, dst); |
| 1801 | CYCLES(CYCLES_ALU_REG_REG); |
| 1802 | } else { |
| 1803 | UINT32 ea = GetEA(modrm,0); |
| 1804 | src = READ8(ea); |
| 1805 | dst = LOAD_REG8(modrm); |
| 1806 | dst = XOR8(dst, src); |
| 1807 | STORE_REG8(modrm, dst); |
| 1808 | CYCLES(CYCLES_ALU_MEM_REG); |
| 1809 | } |
| 1810 | } |
| 1811 | |
| 1812 | void i386_device::i386_xor_al_i8() // Opcode 0x34 |
| 1813 | { |
| 1814 | UINT8 src, dst; |
| 1815 | src = FETCH(); |
| 1816 | dst = REG8(AL); |
| 1817 | dst = XOR8(dst, src); |
| 1818 | REG8(AL) = dst; |
| 1819 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1820 | } |
| 1821 | |
| 1822 | |
| 1823 | |
| 1824 | void i386_device::i386_group80_8() // Opcode 0x80 |
| 1825 | { |
| 1826 | UINT32 ea; |
| 1827 | UINT8 src, dst; |
| 1828 | UINT8 modrm = FETCH(); |
| 1829 | |
| 1830 | switch( (modrm >> 3) & 0x7 ) |
| 1831 | { |
| 1832 | case 0: // ADD Rm8, i8 |
| 1833 | if( modrm >= 0xc0 ) { |
| 1834 | dst = LOAD_RM8(modrm); |
| 1835 | src = FETCH(); |
| 1836 | dst = ADD8(dst, src); |
| 1837 | STORE_RM8(modrm, dst); |
| 1838 | CYCLES(CYCLES_ALU_REG_REG); |
| 1839 | } else { |
| 1840 | ea = GetEA(modrm,0); |
| 1841 | dst = READ8(ea); |
| 1842 | src = FETCH(); |
| 1843 | dst = ADD8(dst, src); |
| 1844 | WRITE8(ea, dst); |
| 1845 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1846 | } |
| 1847 | break; |
| 1848 | case 1: // OR Rm8, i8 |
| 1849 | if( modrm >= 0xc0 ) { |
| 1850 | dst = LOAD_RM8(modrm); |
| 1851 | src = FETCH(); |
| 1852 | dst = OR8(dst, src); |
| 1853 | STORE_RM8(modrm, dst); |
| 1854 | CYCLES(CYCLES_ALU_REG_REG); |
| 1855 | } else { |
| 1856 | ea = GetEA(modrm,1); |
| 1857 | dst = READ8(ea); |
| 1858 | src = FETCH(); |
| 1859 | dst = OR8(dst, src); |
| 1860 | WRITE8(ea, dst); |
| 1861 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1862 | } |
| 1863 | break; |
| 1864 | case 2: // ADC Rm8, i8 |
| 1865 | if( modrm >= 0xc0 ) { |
| 1866 | dst = LOAD_RM8(modrm); |
| 1867 | src = FETCH(); |
| 1868 | dst = ADC8(dst, src, m_CF); |
| 1869 | STORE_RM8(modrm, dst); |
| 1870 | CYCLES(CYCLES_ALU_REG_REG); |
| 1871 | } else { |
| 1872 | ea = GetEA(modrm,1); |
| 1873 | dst = READ8(ea); |
| 1874 | src = FETCH(); |
| 1875 | dst = ADC8(dst, src, m_CF); |
| 1876 | WRITE8(ea, dst); |
| 1877 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1878 | } |
| 1879 | break; |
| 1880 | case 3: // SBB Rm8, i8 |
| 1881 | if( modrm >= 0xc0 ) { |
| 1882 | dst = LOAD_RM8(modrm); |
| 1883 | src = FETCH(); |
| 1884 | dst = SBB8(dst, src, m_CF); |
| 1885 | STORE_RM8(modrm, dst); |
| 1886 | CYCLES(CYCLES_ALU_REG_REG); |
| 1887 | } else { |
| 1888 | ea = GetEA(modrm,1); |
| 1889 | dst = READ8(ea); |
| 1890 | src = FETCH(); |
| 1891 | dst = SBB8(dst, src, m_CF); |
| 1892 | WRITE8(ea, dst); |
| 1893 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1894 | } |
| 1895 | break; |
| 1896 | case 4: // AND Rm8, i8 |
| 1897 | if( modrm >= 0xc0 ) { |
| 1898 | dst = LOAD_RM8(modrm); |
| 1899 | src = FETCH(); |
| 1900 | dst = AND8(dst, src); |
| 1901 | STORE_RM8(modrm, dst); |
| 1902 | CYCLES(CYCLES_ALU_REG_REG); |
| 1903 | } else { |
| 1904 | ea = GetEA(modrm,1); |
| 1905 | dst = READ8(ea); |
| 1906 | src = FETCH(); |
| 1907 | dst = AND8(dst, src); |
| 1908 | WRITE8(ea, dst); |
| 1909 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1910 | } |
| 1911 | break; |
| 1912 | case 5: // SUB Rm8, i8 |
| 1913 | if( modrm >= 0xc0 ) { |
| 1914 | dst = LOAD_RM8(modrm); |
| 1915 | src = FETCH(); |
| 1916 | dst = SUB8(dst, src); |
| 1917 | STORE_RM8(modrm, dst); |
| 1918 | CYCLES(CYCLES_ALU_REG_REG); |
| 1919 | } else { |
| 1920 | ea = GetEA(modrm,1); |
| 1921 | dst = READ8(ea); |
| 1922 | src = FETCH(); |
| 1923 | dst = SUB8(dst, src); |
| 1924 | WRITE8(ea, dst); |
| 1925 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1926 | } |
| 1927 | break; |
| 1928 | case 6: // XOR Rm8, i8 |
| 1929 | if( modrm >= 0xc0 ) { |
| 1930 | dst = LOAD_RM8(modrm); |
| 1931 | src = FETCH(); |
| 1932 | dst = XOR8(dst, src); |
| 1933 | STORE_RM8(modrm, dst); |
| 1934 | CYCLES(CYCLES_ALU_REG_REG); |
| 1935 | } else { |
| 1936 | ea = GetEA(modrm,1); |
| 1937 | dst = READ8(ea); |
| 1938 | src = FETCH(); |
| 1939 | dst = XOR8(dst, src); |
| 1940 | WRITE8(ea, dst); |
| 1941 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1942 | } |
| 1943 | break; |
| 1944 | case 7: // CMP Rm8, i8 |
| 1945 | if( modrm >= 0xc0 ) { |
| 1946 | dst = LOAD_RM8(modrm); |
| 1947 | src = FETCH(); |
| 1948 | SUB8(dst, src); |
| 1949 | CYCLES(CYCLES_CMP_REG_REG); |
| 1950 | } else { |
| 1951 | ea = GetEA(modrm,0); |
| 1952 | dst = READ8(ea); |
| 1953 | src = FETCH(); |
| 1954 | SUB8(dst, src); |
| 1955 | CYCLES(CYCLES_CMP_REG_MEM); |
| 1956 | } |
| 1957 | break; |
| 1958 | } |
| 1959 | } |
| 1960 | |
| 1961 | void i386_device::i386_groupC0_8() // Opcode 0xc0 |
| 1962 | { |
| 1963 | UINT8 dst; |
| 1964 | UINT8 modrm = FETCH(); |
| 1965 | UINT8 shift; |
| 1966 | |
| 1967 | if( modrm >= 0xc0 ) { |
| 1968 | dst = LOAD_RM8(modrm); |
| 1969 | shift = FETCH() & 0x1f; |
| 1970 | dst = i386_shift_rotate8(modrm, dst, shift); |
| 1971 | STORE_RM8(modrm, dst); |
| 1972 | } else { |
| 1973 | UINT32 ea = GetEA(modrm,1); |
| 1974 | dst = READ8(ea); |
| 1975 | shift = FETCH() & 0x1f; |
| 1976 | dst = i386_shift_rotate8(modrm, dst, shift); |
| 1977 | WRITE8(ea, dst); |
| 1978 | } |
| 1979 | } |
| 1980 | |
| 1981 | void i386_device::i386_groupD0_8() // Opcode 0xd0 |
| 1982 | { |
| 1983 | UINT8 dst; |
| 1984 | UINT8 modrm = FETCH(); |
| 1985 | |
| 1986 | if( modrm >= 0xc0 ) { |
| 1987 | dst = LOAD_RM8(modrm); |
| 1988 | dst = i386_shift_rotate8(modrm, dst, 1); |
| 1989 | STORE_RM8(modrm, dst); |
| 1990 | } else { |
| 1991 | UINT32 ea = GetEA(modrm,1); |
| 1992 | dst = READ8(ea); |
| 1993 | dst = i386_shift_rotate8(modrm, dst, 1); |
| 1994 | WRITE8(ea, dst); |
| 1995 | } |
| 1996 | } |
| 1997 | |
| 1998 | void i386_device::i386_groupD2_8() // Opcode 0xd2 |
| 1999 | { |
| 2000 | UINT8 dst; |
| 2001 | UINT8 modrm = FETCH(); |
| 2002 | |
| 2003 | if( modrm >= 0xc0 ) { |
| 2004 | dst = LOAD_RM8(modrm); |
| 2005 | dst = i386_shift_rotate8(modrm, dst, REG8(CL)); |
| 2006 | STORE_RM8(modrm, dst); |
| 2007 | } else { |
| 2008 | UINT32 ea = GetEA(modrm,1); |
| 2009 | dst = READ8(ea); |
| 2010 | dst = i386_shift_rotate8(modrm, dst, REG8(CL)); |
| 2011 | WRITE8(ea, dst); |
| 2012 | } |
| 2013 | } |
| 2014 | |
| 2015 | void i386_device::i386_groupF6_8() // Opcode 0xf6 |
| 2016 | { |
| 2017 | UINT8 modrm = FETCH(); |
| 2018 | |
| 2019 | switch( (modrm >> 3) & 0x7 ) |
| 2020 | { |
| 2021 | case 0: /* TEST Rm8, i8 */ |
| 2022 | if( modrm >= 0xc0 ) { |
| 2023 | UINT8 dst = LOAD_RM8(modrm); |
| 2024 | UINT8 src = FETCH(); |
| 2025 | dst &= src; |
| 2026 | m_CF = m_OF = m_AF = 0; |
| 2027 | SetSZPF8(dst); |
| 2028 | CYCLES(CYCLES_TEST_IMM_REG); |
| 2029 | } else { |
| 2030 | UINT32 ea = GetEA(modrm,0); |
| 2031 | UINT8 dst = READ8(ea); |
| 2032 | UINT8 src = FETCH(); |
| 2033 | dst &= src; |
| 2034 | m_CF = m_OF = m_AF = 0; |
| 2035 | SetSZPF8(dst); |
| 2036 | CYCLES(CYCLES_TEST_IMM_MEM); |
| 2037 | } |
| 2038 | break; |
| 2039 | case 2: /* NOT Rm8 */ |
| 2040 | if( modrm >= 0xc0 ) { |
| 2041 | UINT8 dst = LOAD_RM8(modrm); |
| 2042 | dst = ~dst; |
| 2043 | STORE_RM8(modrm, dst); |
| 2044 | CYCLES(CYCLES_NOT_REG); |
| 2045 | } else { |
| 2046 | UINT32 ea = GetEA(modrm,1); |
| 2047 | UINT8 dst = READ8(ea); |
| 2048 | dst = ~dst; |
| 2049 | WRITE8(ea, dst); |
| 2050 | CYCLES(CYCLES_NOT_MEM); |
| 2051 | } |
| 2052 | break; |
| 2053 | case 3: /* NEG Rm8 */ |
| 2054 | if( modrm >= 0xc0 ) { |
| 2055 | UINT8 dst = LOAD_RM8(modrm); |
| 2056 | dst = SUB8(0, dst ); |
| 2057 | STORE_RM8(modrm, dst); |
| 2058 | CYCLES(CYCLES_NEG_REG); |
| 2059 | } else { |
| 2060 | UINT32 ea = GetEA(modrm,1); |
| 2061 | UINT8 dst = READ8(ea); |
| 2062 | dst = SUB8(0, dst ); |
| 2063 | WRITE8(ea, dst); |
| 2064 | CYCLES(CYCLES_NEG_MEM); |
| 2065 | } |
| 2066 | break; |
| 2067 | case 4: /* MUL AL, Rm8 */ |
| 2068 | { |
| 2069 | UINT16 result; |
| 2070 | UINT8 src, dst; |
| 2071 | if( modrm >= 0xc0 ) { |
| 2072 | src = LOAD_RM8(modrm); |
| 2073 | CYCLES(CYCLES_MUL8_ACC_REG); /* TODO: Correct multiply timing */ |
| 2074 | } else { |
| 2075 | UINT32 ea = GetEA(modrm,0); |
| 2076 | src = READ8(ea); |
| 2077 | CYCLES(CYCLES_MUL8_ACC_MEM); /* TODO: Correct multiply timing */ |
| 2078 | } |
| 2079 | |
| 2080 | dst = REG8(AL); |
| 2081 | result = (UINT16)src * (UINT16)dst; |
| 2082 | REG16(AX) = (UINT16)result; |
| 2083 | |
| 2084 | m_CF = m_OF = (REG16(AX) > 0xff); |
| 2085 | } |
| 2086 | break; |
| 2087 | case 5: /* IMUL AL, Rm8 */ |
| 2088 | { |
| 2089 | INT16 result; |
| 2090 | INT16 src, dst; |
| 2091 | if( modrm >= 0xc0 ) { |
| 2092 | src = (INT16)(INT8)LOAD_RM8(modrm); |
| 2093 | CYCLES(CYCLES_IMUL8_ACC_REG); /* TODO: Correct multiply timing */ |
| 2094 | } else { |
| 2095 | UINT32 ea = GetEA(modrm,0); |
| 2096 | src = (INT16)(INT8)READ8(ea); |
| 2097 | CYCLES(CYCLES_IMUL8_ACC_MEM); /* TODO: Correct multiply timing */ |
| 2098 | } |
| 2099 | |
| 2100 | dst = (INT16)(INT8)REG8(AL); |
| 2101 | result = src * dst; |
| 2102 | |
| 2103 | REG16(AX) = (UINT16)result; |
| 2104 | |
| 2105 | m_CF = m_OF = !(result == (INT16)(INT8)result); |
| 2106 | } |
| 2107 | break; |
| 2108 | case 6: /* DIV AL, Rm8 */ |
| 2109 | { |
| 2110 | UINT16 quotient, remainder, result; |
| 2111 | UINT8 src; |
| 2112 | if( modrm >= 0xc0 ) { |
| 2113 | src = LOAD_RM8(modrm); |
| 2114 | CYCLES(CYCLES_DIV8_ACC_REG); |
| 2115 | } else { |
| 2116 | UINT32 ea = GetEA(modrm,0); |
| 2117 | src = READ8(ea); |
| 2118 | CYCLES(CYCLES_DIV8_ACC_MEM); |
| 2119 | } |
| 2120 | |
| 2121 | quotient = (UINT16)REG16(AX); |
| 2122 | if( src ) { |
| 2123 | remainder = quotient % (UINT16)src; |
| 2124 | result = quotient / (UINT16)src; |
| 2125 | if( result > 0xff ) { |
| 2126 | /* TODO: Divide error */ |
| 2127 | } else { |
| 2128 | REG8(AH) = (UINT8)remainder & 0xff; |
| 2129 | REG8(AL) = (UINT8)result & 0xff; |
| 2130 | |
| 2131 | // this flag is actually undefined, enable on non-cyrix |
| 2132 | if (m_cpuid_id0 != 0x69727943) |
| 2133 | m_CF = 1; |
| 2134 | } |
| 2135 | } else { |
| 2136 | i386_trap(0, 0, 0); |
| 2137 | } |
| 2138 | } |
| 2139 | break; |
| 2140 | case 7: /* IDIV AL, Rm8 */ |
| 2141 | { |
| 2142 | INT16 quotient, remainder, result; |
| 2143 | UINT8 src; |
| 2144 | if( modrm >= 0xc0 ) { |
| 2145 | src = LOAD_RM8(modrm); |
| 2146 | CYCLES(CYCLES_IDIV8_ACC_REG); |
| 2147 | } else { |
| 2148 | UINT32 ea = GetEA(modrm,0); |
| 2149 | src = READ8(ea); |
| 2150 | CYCLES(CYCLES_IDIV8_ACC_MEM); |
| 2151 | } |
| 2152 | |
| 2153 | quotient = (INT16)REG16(AX); |
| 2154 | if( src ) { |
| 2155 | remainder = quotient % (INT16)(INT8)src; |
| 2156 | result = quotient / (INT16)(INT8)src; |
| 2157 | if( result > 0xff ) { |
| 2158 | /* TODO: Divide error */ |
| 2159 | } else { |
| 2160 | REG8(AH) = (UINT8)remainder & 0xff; |
| 2161 | REG8(AL) = (UINT8)result & 0xff; |
| 2162 | |
| 2163 | // this flag is actually undefined, enable on non-cyrix |
| 2164 | if (m_cpuid_id0 != 0x69727943) |
| 2165 | m_CF = 1; |
| 2166 | } |
| 2167 | } else { |
| 2168 | i386_trap(0, 0, 0); |
| 2169 | } |
| 2170 | } |
| 2171 | break; |
| 2172 | } |
| 2173 | } |
| 2174 | |
| 2175 | void i386_device::i386_groupFE_8() // Opcode 0xfe |
| 2176 | { |
| 2177 | UINT8 modrm = FETCH(); |
| 2178 | |
| 2179 | switch( (modrm >> 3) & 0x7 ) |
| 2180 | { |
| 2181 | case 0: /* INC Rm8 */ |
| 2182 | if( modrm >= 0xc0 ) { |
| 2183 | UINT8 dst = LOAD_RM8(modrm); |
| 2184 | dst = INC8(dst); |
| 2185 | STORE_RM8(modrm, dst); |
| 2186 | CYCLES(CYCLES_INC_REG); |
| 2187 | } else { |
| 2188 | UINT32 ea = GetEA(modrm,1); |
| 2189 | UINT8 dst = READ8(ea); |
| 2190 | dst = INC8(dst); |
| 2191 | WRITE8(ea, dst); |
| 2192 | CYCLES(CYCLES_INC_MEM); |
| 2193 | } |
| 2194 | break; |
| 2195 | case 1: /* DEC Rm8 */ |
| 2196 | if( modrm >= 0xc0 ) { |
| 2197 | UINT8 dst = LOAD_RM8(modrm); |
| 2198 | dst = DEC8(dst); |
| 2199 | STORE_RM8(modrm, dst); |
| 2200 | CYCLES(CYCLES_DEC_REG); |
| 2201 | } else { |
| 2202 | UINT32 ea = GetEA(modrm,1); |
| 2203 | UINT8 dst = READ8(ea); |
| 2204 | dst = DEC8(dst); |
| 2205 | WRITE8(ea, dst); |
| 2206 | CYCLES(CYCLES_DEC_MEM); |
| 2207 | } |
| 2208 | break; |
| 2209 | case 6: /* PUSH Rm8*/ |
| 2210 | { |
| 2211 | UINT8 value; |
| 2212 | if( modrm >= 0xc0 ) { |
| 2213 | value = LOAD_RM8(modrm); |
| 2214 | } else { |
| 2215 | UINT32 ea = GetEA(modrm,0); |
| 2216 | value = READ8(ea); |
| 2217 | } |
| 2218 | if( m_operand_size ) { |
| 2219 | PUSH32(value); |
| 2220 | } else { |
| 2221 | PUSH16(value); |
| 2222 | } |
| 2223 | CYCLES(CYCLES_PUSH_RM); |
| 2224 | } |
| 2225 | break; |
| 2226 | default: |
| 2227 | report_invalid_modrm("groupFE_8", modrm); |
| 2228 | break; |
| 2229 | } |
| 2230 | } |
| 2231 | |
| 2232 | |
| 2233 | |
| 2234 | void i386_device::i386_segment_CS() // Opcode 0x2e |
| 2235 | { |
| 2236 | m_segment_prefix = 1; |
| 2237 | m_segment_override = CS; |
| 2238 | |
| 2239 | i386_decode_opcode(); |
| 2240 | } |
| 2241 | |
| 2242 | void i386_device::i386_segment_DS() // Opcode 0x3e |
| 2243 | { |
| 2244 | m_segment_prefix = 1; |
| 2245 | m_segment_override = DS; |
| 2246 | CYCLES(0); // TODO: Specify cycle count |
| 2247 | i386_decode_opcode(); |
| 2248 | } |
| 2249 | |
| 2250 | void i386_device::i386_segment_ES() // Opcode 0x26 |
| 2251 | { |
| 2252 | m_segment_prefix = 1; |
| 2253 | m_segment_override = ES; |
| 2254 | CYCLES(0); // TODO: Specify cycle count |
| 2255 | i386_decode_opcode(); |
| 2256 | } |
| 2257 | |
| 2258 | void i386_device::i386_segment_FS() // Opcode 0x64 |
| 2259 | { |
| 2260 | m_segment_prefix = 1; |
| 2261 | m_segment_override = FS; |
| 2262 | CYCLES(1); // TODO: Specify cycle count |
| 2263 | i386_decode_opcode(); |
| 2264 | } |
| 2265 | |
| 2266 | void i386_device::i386_segment_GS() // Opcode 0x65 |
| 2267 | { |
| 2268 | m_segment_prefix = 1; |
| 2269 | m_segment_override = GS; |
| 2270 | CYCLES(1); // TODO: Specify cycle count |
| 2271 | i386_decode_opcode(); |
| 2272 | } |
| 2273 | |
| 2274 | void i386_device::i386_segment_SS() // Opcode 0x36 |
| 2275 | { |
| 2276 | m_segment_prefix = 1; |
| 2277 | m_segment_override = SS; |
| 2278 | CYCLES(0); // TODO: Specify cycle count |
| 2279 | i386_decode_opcode(); |
| 2280 | } |
| 2281 | |
| 2282 | void i386_device::i386_operand_size() // Opcode prefix 0x66 |
| 2283 | { |
| 2284 | if(m_operand_prefix == 0) |
| 2285 | { |
| 2286 | m_operand_size ^= 1; |
| 2287 | m_operand_prefix = 1; |
| 2288 | } |
| 2289 | m_opcode = FETCH(); |
| 2290 | if (m_opcode == 0x0f) |
| 2291 | i386_decode_three_byte66(); |
| 2292 | else |
| 2293 | { |
| 2294 | if( m_operand_size ) |
| 2295 | (this->*m_opcode_table1_32[m_opcode])(); |
| 2296 | else |
| 2297 | (this->*m_opcode_table1_16[m_opcode])(); |
| 2298 | } |
| 2299 | } |
| 2300 | |
| 2301 | void i386_device::i386_address_size() // Opcode 0x67 |
| 2302 | { |
| 2303 | if(m_address_prefix == 0) |
| 2304 | { |
| 2305 | m_address_size ^= 1; |
| 2306 | m_address_prefix = 1; |
| 2307 | } |
| 2308 | i386_decode_opcode(); |
| 2309 | } |
| 2310 | |
| 2311 | void i386_device::i386_nop() // Opcode 0x90 |
| 2312 | { |
| 2313 | CYCLES(CYCLES_NOP); |
| 2314 | } |
| 2315 | |
| 2316 | void i386_device::i386_int3() // Opcode 0xcc |
| 2317 | { |
| 2318 | CYCLES(CYCLES_INT3); |
| 2319 | m_ext = 0; // not an external interrupt |
| 2320 | i386_trap(3, 1, 0); |
| 2321 | m_ext = 1; |
| 2322 | } |
| 2323 | |
| 2324 | void i386_device::i386_int() // Opcode 0xcd |
| 2325 | { |
| 2326 | int interrupt = FETCH(); |
| 2327 | CYCLES(CYCLES_INT); |
| 2328 | m_ext = 0; // not an external interrupt |
| 2329 | i386_trap(interrupt, 1, 0); |
| 2330 | m_ext = 1; |
| 2331 | } |
| 2332 | |
| 2333 | void i386_device::i386_into() // Opcode 0xce |
| 2334 | { |
| 2335 | if( m_OF ) { |
| 2336 | m_ext = 0; |
| 2337 | i386_trap(4, 1, 0); |
| 2338 | m_ext = 1; |
| 2339 | CYCLES(CYCLES_INTO_OF1); |
| 2340 | } |
| 2341 | else |
| 2342 | { |
| 2343 | CYCLES(CYCLES_INTO_OF0); |
| 2344 | } |
| 2345 | } |
| 2346 | |
| 2347 | static UINT32 i386_escape_ea; // hack around GCC 4.6 error because we need the side effects of GetEA() |
| 2348 | void i386_device::i386_escape() // Opcodes 0xd8 - 0xdf |
| 2349 | { |
| 2350 | UINT8 modrm = FETCH(); |
| 2351 | if(modrm < 0xc0) |
| 2352 | { |
| 2353 | i386_escape_ea = GetEA(modrm,0); |
| 2354 | } |
| 2355 | CYCLES(3); // TODO: confirm this |
| 2356 | (void) LOAD_RM8(modrm); |
| 2357 | } |
| 2358 | |
| 2359 | void i386_device::i386_hlt() // Opcode 0xf4 |
| 2360 | { |
| 2361 | if(PROTECTED_MODE && m_CPL != 0) |
| 2362 | FAULT(FAULT_GP,0); |
| 2363 | m_halted = 1; |
| 2364 | CYCLES(CYCLES_HLT); |
| 2365 | if (m_cycles > 0) |
| 2366 | m_cycles = 0; |
| 2367 | } |
| 2368 | |
| 2369 | void i386_device::i386_decimal_adjust(int direction) |
| 2370 | { |
| 2371 | UINT8 tmpAL = REG8(AL); |
| 2372 | UINT8 tmpCF = m_CF; |
| 2373 | |
| 2374 | if (m_AF || ((REG8(AL) & 0xf) > 9)) |
| 2375 | { |
| 2376 | UINT16 t= (UINT16)REG8(AL) + (direction * 0x06); |
| 2377 | REG8(AL) = (UINT8)t&0xff; |
| 2378 | m_AF = 1; |
| 2379 | if (t & 0x100) |
| 2380 | m_CF = 1; |
| 2381 | if (direction > 0) |
| 2382 | tmpAL = REG8(AL); |
| 2383 | } |
| 2384 | |
| 2385 | if (tmpCF || (tmpAL > 0x99)) |
| 2386 | { |
| 2387 | REG8(AL) += (direction * 0x60); |
| 2388 | m_CF = 1; |
| 2389 | } |
| 2390 | |
| 2391 | SetSZPF8(REG8(AL)); |
| 2392 | } |
| 2393 | |
| 2394 | void i386_device::i386_daa() // Opcode 0x27 |
| 2395 | { |
| 2396 | i386_decimal_adjust(+1); |
| 2397 | CYCLES(CYCLES_DAA); |
| 2398 | } |
| 2399 | |
| 2400 | void i386_device::i386_das() // Opcode 0x2f |
| 2401 | { |
| 2402 | i386_decimal_adjust(-1); |
| 2403 | CYCLES(CYCLES_DAS); |
| 2404 | } |
| 2405 | |
| 2406 | void i386_device::i386_aaa() // Opcode 0x37 |
| 2407 | { |
| 2408 | if( ( (REG8(AL) & 0x0f) > 9) || (m_AF != 0) ) { |
| 2409 | REG16(AX) = REG16(AX) + 6; |
| 2410 | REG8(AH) = REG8(AH) + 1; |
| 2411 | m_AF = 1; |
| 2412 | m_CF = 1; |
| 2413 | } else { |
| 2414 | m_AF = 0; |
| 2415 | m_CF = 0; |
| 2416 | } |
| 2417 | REG8(AL) = REG8(AL) & 0x0f; |
| 2418 | CYCLES(CYCLES_AAA); |
| 2419 | } |
| 2420 | |
| 2421 | void i386_device::i386_aas() // Opcode 0x3f |
| 2422 | { |
| 2423 | if (m_AF || ((REG8(AL) & 0xf) > 9)) |
| 2424 | { |
| 2425 | REG16(AX) -= 6; |
| 2426 | REG8(AH) -= 1; |
| 2427 | m_AF = 1; |
| 2428 | m_CF = 1; |
| 2429 | } |
| 2430 | else |
| 2431 | { |
| 2432 | m_AF = 0; |
| 2433 | m_CF = 0; |
| 2434 | } |
| 2435 | REG8(AL) &= 0x0f; |
| 2436 | CYCLES(CYCLES_AAS); |
| 2437 | } |
| 2438 | |
| 2439 | void i386_device::i386_aad() // Opcode 0xd5 |
| 2440 | { |
| 2441 | UINT8 tempAL = REG8(AL); |
| 2442 | UINT8 tempAH = REG8(AH); |
| 2443 | UINT8 i = FETCH(); |
| 2444 | |
| 2445 | REG8(AL) = (tempAL + (tempAH * i)) & 0xff; |
| 2446 | REG8(AH) = 0; |
| 2447 | SetSZPF8( REG8(AL) ); |
| 2448 | CYCLES(CYCLES_AAD); |
| 2449 | } |
| 2450 | |
| 2451 | void i386_device::i386_aam() // Opcode 0xd4 |
| 2452 | { |
| 2453 | UINT8 tempAL = REG8(AL); |
| 2454 | UINT8 i = FETCH(); |
| 2455 | |
| 2456 | if(!i) |
| 2457 | { |
| 2458 | i386_trap(0, 0, 0); |
| 2459 | return; |
| 2460 | } |
| 2461 | REG8(AH) = tempAL / i; |
| 2462 | REG8(AL) = tempAL % i; |
| 2463 | SetSZPF8( REG8(AL) ); |
| 2464 | CYCLES(CYCLES_AAM); |
| 2465 | } |
| 2466 | |
| 2467 | void i386_device::i386_clts() // Opcode 0x0f 0x06 |
| 2468 | { |
| 2469 | // Privileged instruction, CPL must be zero. Can be used in real or v86 mode. |
| 2470 | if(PROTECTED_MODE && m_CPL != 0) |
| 2471 | FAULT(FAULT_GP,0) |
| 2472 | m_cr[0] &= ~0x08; /* clear TS bit */ |
| 2473 | CYCLES(CYCLES_CLTS); |
| 2474 | } |
| 2475 | |
| 2476 | void i386_device::i386_wait() // Opcode 0x9B |
| 2477 | { |
| 2478 | // TODO |
| 2479 | } |
| 2480 | |
| 2481 | void i386_device::i386_lock() // Opcode 0xf0 |
| 2482 | { |
| 2483 | // lock doesn't depend on iopl on 386 |
| 2484 | // TODO: lock causes UD on unlockable opcodes |
| 2485 | CYCLES(CYCLES_LOCK); // TODO: Determine correct cycle count |
| 2486 | i386_decode_opcode(); |
| 2487 | } |
| 2488 | |
| 2489 | void i386_device::i386_mov_r32_tr() // Opcode 0x0f 24 |
| 2490 | { |
| 2491 | FETCH(); |
| 2492 | CYCLES(1); // TODO: correct cycle count |
| 2493 | } |
| 2494 | |
| 2495 | void i386_device::i386_mov_tr_r32() // Opcode 0x0f 26 |
| 2496 | { |
| 2497 | FETCH(); |
| 2498 | CYCLES(1); // TODO: correct cycle count |
| 2499 | } |
| 2500 | |
| 2501 | void i386_device::i386_loadall() // Opcode 0x0f 0x07 (0x0f 0x05 on 80286), undocumented |
| 2502 | { |
| 2503 | fatalerror("i386: LOADALL unimplemented at %08X\n", m_pc - 1); |
| 2504 | } |
| 2505 | |
| 2506 | void i386_device::i386_invalid() |
| 2507 | { |
| 2508 | report_invalid_opcode(); |
| 2509 | i386_trap(6, 0, 0); |
| 2510 | } |
| 2511 | |
| 2512 | void i386_device::i386_xlat() // Opcode 0xd7 |
| 2513 | { |
| 2514 | UINT32 ea; |
| 2515 | if( m_segment_prefix ) { |
| 2516 | if(!m_address_size) |
| 2517 | { |
| 2518 | ea = i386_translate(m_segment_override, REG16(BX) + REG8(AL), 0 ); |
| 2519 | } |
| 2520 | else |
| 2521 | { |
| 2522 | ea = i386_translate(m_segment_override, REG32(EBX) + REG8(AL), 0 ); |
| 2523 | } |
| 2524 | } else { |
| 2525 | if(!m_address_size) |
| 2526 | { |
| 2527 | ea = i386_translate(DS, REG16(BX) + REG8(AL), 0 ); |
| 2528 | } |
| 2529 | else |
| 2530 | { |
| 2531 | ea = i386_translate(DS, REG32(EBX) + REG8(AL), 0 ); |
| 2532 | } |
| 2533 | } |
| 2534 | REG8(AL) = READ8(ea); |
| 2535 | CYCLES(CYCLES_XLAT); |
| 2536 | } |
trunk/src/emu/cpu/i386/i386op32.inc
| r0 | r28739 | |
| 1 | UINT32 i386_device::i386_shift_rotate32(UINT8 modrm, UINT32 value, UINT8 shift) |
| 2 | { |
| 3 | UINT32 dst, src; |
| 4 | dst = value; |
| 5 | src = value; |
| 6 | |
| 7 | if( shift == 0 ) { |
| 8 | CYCLES_RM(modrm, 3, 7); |
| 9 | } else if( shift == 1 ) { |
| 10 | switch( (modrm >> 3) & 0x7 ) |
| 11 | { |
| 12 | case 0: /* ROL rm32, 1 */ |
| 13 | m_CF = (src & 0x80000000) ? 1 : 0; |
| 14 | dst = (src << 1) + m_CF; |
| 15 | m_OF = ((src ^ dst) & 0x80000000) ? 1 : 0; |
| 16 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 17 | break; |
| 18 | case 1: /* ROR rm32, 1 */ |
| 19 | m_CF = (src & 0x1) ? 1 : 0; |
| 20 | dst = (m_CF << 31) | (src >> 1); |
| 21 | m_OF = ((src ^ dst) & 0x80000000) ? 1 : 0; |
| 22 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 23 | break; |
| 24 | case 2: /* RCL rm32, 1 */ |
| 25 | dst = (src << 1) + m_CF; |
| 26 | m_CF = (src & 0x80000000) ? 1 : 0; |
| 27 | m_OF = ((src ^ dst) & 0x80000000) ? 1 : 0; |
| 28 | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 29 | break; |
| 30 | case 3: /* RCR rm32, 1 */ |
| 31 | dst = (m_CF << 31) | (src >> 1); |
| 32 | m_CF = src & 0x1; |
| 33 | m_OF = ((src ^ dst) & 0x80000000) ? 1 : 0; |
| 34 | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 35 | break; |
| 36 | case 4: /* SHL/SAL rm32, 1 */ |
| 37 | case 6: |
| 38 | dst = src << 1; |
| 39 | m_CF = (src & 0x80000000) ? 1 : 0; |
| 40 | m_OF = (((m_CF << 31) ^ dst) & 0x80000000) ? 1 : 0; |
| 41 | SetSZPF32(dst); |
| 42 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 43 | break; |
| 44 | case 5: /* SHR rm32, 1 */ |
| 45 | dst = src >> 1; |
| 46 | m_CF = src & 0x1; |
| 47 | m_OF = (src & 0x80000000) ? 1 : 0; |
| 48 | SetSZPF32(dst); |
| 49 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 50 | break; |
| 51 | case 7: /* SAR rm32, 1 */ |
| 52 | dst = (INT32)(src) >> 1; |
| 53 | m_CF = src & 0x1; |
| 54 | m_OF = 0; |
| 55 | SetSZPF32(dst); |
| 56 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 57 | break; |
| 58 | } |
| 59 | |
| 60 | } else { |
| 61 | shift &= 31; |
| 62 | switch( (modrm >> 3) & 0x7 ) |
| 63 | { |
| 64 | case 0: /* ROL rm32, i8 */ |
| 65 | dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) | |
| 66 | ((src & ((UINT32)0xffffffff << (32-shift))) >> (32-shift)); |
| 67 | m_CF = dst & 0x1; |
| 68 | m_OF = (dst & 1) ^ (dst >> 31); |
| 69 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 70 | break; |
| 71 | case 1: /* ROR rm32, i8 */ |
| 72 | dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) | |
| 73 | ((src & ((UINT32)0xffffffff >> (32-shift))) << (32-shift)); |
| 74 | m_CF = (dst >> 31) & 0x1; |
| 75 | m_OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 76 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 77 | break; |
| 78 | case 2: /* RCL rm32, i8 */ |
| 79 | dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) | |
| 80 | ((src & ((UINT32)0xffffffff << (33-shift))) >> (33-shift)) | |
| 81 | (m_CF << (shift-1)); |
| 82 | m_CF = (src >> (32-shift)) & 0x1; |
| 83 | m_OF = m_CF ^ ((dst >> 31) & 1); |
| 84 | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 85 | break; |
| 86 | case 3: /* RCR rm32, i8 */ |
| 87 | dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) | |
| 88 | ((src & ((UINT32)0xffffffff >> (32-shift))) << (33-shift)) | |
| 89 | (m_CF << (32-shift)); |
| 90 | m_CF = (src >> (shift-1)) & 0x1; |
| 91 | m_OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 92 | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 93 | break; |
| 94 | case 4: /* SHL/SAL rm32, i8 */ |
| 95 | case 6: |
| 96 | dst = src << shift; |
| 97 | m_CF = (src & (1 << (32-shift))) ? 1 : 0; |
| 98 | SetSZPF32(dst); |
| 99 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 100 | break; |
| 101 | case 5: /* SHR rm32, i8 */ |
| 102 | dst = src >> shift; |
| 103 | m_CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 104 | SetSZPF32(dst); |
| 105 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 106 | break; |
| 107 | case 7: /* SAR rm32, i8 */ |
| 108 | dst = (INT32)src >> shift; |
| 109 | m_CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 110 | SetSZPF32(dst); |
| 111 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 112 | break; |
| 113 | } |
| 114 | |
| 115 | } |
| 116 | return dst; |
| 117 | } |
| 118 | |
| 119 | |
| 120 | |
| 121 | void i386_device::i386_adc_rm32_r32() // Opcode 0x11 |
| 122 | { |
| 123 | UINT32 src, dst; |
| 124 | UINT8 modrm = FETCH(); |
| 125 | if( modrm >= 0xc0 ) { |
| 126 | src = LOAD_REG32(modrm); |
| 127 | dst = LOAD_RM32(modrm); |
| 128 | dst = ADC32(dst, src, m_CF); |
| 129 | STORE_RM32(modrm, dst); |
| 130 | CYCLES(CYCLES_ALU_REG_REG); |
| 131 | } else { |
| 132 | UINT32 ea = GetEA(modrm,1); |
| 133 | src = LOAD_REG32(modrm); |
| 134 | dst = READ32(ea); |
| 135 | dst = ADC32(dst, src, m_CF); |
| 136 | WRITE32(ea, dst); |
| 137 | CYCLES(CYCLES_ALU_REG_MEM); |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | void i386_device::i386_adc_r32_rm32() // Opcode 0x13 |
| 142 | { |
| 143 | UINT32 src, dst; |
| 144 | UINT8 modrm = FETCH(); |
| 145 | if( modrm >= 0xc0 ) { |
| 146 | src = LOAD_RM32(modrm); |
| 147 | dst = LOAD_REG32(modrm); |
| 148 | dst = ADC32(dst, src, m_CF); |
| 149 | STORE_REG32(modrm, dst); |
| 150 | CYCLES(CYCLES_ALU_REG_REG); |
| 151 | } else { |
| 152 | UINT32 ea = GetEA(modrm,0); |
| 153 | src = READ32(ea); |
| 154 | dst = LOAD_REG32(modrm); |
| 155 | dst = ADC32(dst, src, m_CF); |
| 156 | STORE_REG32(modrm, dst); |
| 157 | CYCLES(CYCLES_ALU_MEM_REG); |
| 158 | } |
| 159 | } |
| 160 | |
| 161 | void i386_device::i386_adc_eax_i32() // Opcode 0x15 |
| 162 | { |
| 163 | UINT32 src, dst; |
| 164 | src = FETCH32(); |
| 165 | dst = REG32(EAX); |
| 166 | dst = ADC32(dst, src, m_CF); |
| 167 | REG32(EAX) = dst; |
| 168 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 169 | } |
| 170 | |
| 171 | void i386_device::i386_add_rm32_r32() // Opcode 0x01 |
| 172 | { |
| 173 | UINT32 src, dst; |
| 174 | UINT8 modrm = FETCH(); |
| 175 | if( modrm >= 0xc0 ) { |
| 176 | src = LOAD_REG32(modrm); |
| 177 | dst = LOAD_RM32(modrm); |
| 178 | dst = ADD32(dst, src); |
| 179 | STORE_RM32(modrm, dst); |
| 180 | CYCLES(CYCLES_ALU_REG_REG); |
| 181 | } else { |
| 182 | UINT32 ea = GetEA(modrm,1); |
| 183 | src = LOAD_REG32(modrm); |
| 184 | dst = READ32(ea); |
| 185 | dst = ADD32(dst, src); |
| 186 | WRITE32(ea, dst); |
| 187 | CYCLES(CYCLES_ALU_REG_MEM); |
| 188 | } |
| 189 | } |
| 190 | |
| 191 | void i386_device::i386_add_r32_rm32() // Opcode 0x03 |
| 192 | { |
| 193 | UINT32 src, dst; |
| 194 | UINT8 modrm = FETCH(); |
| 195 | if( modrm >= 0xc0 ) { |
| 196 | src = LOAD_RM32(modrm); |
| 197 | dst = LOAD_REG32(modrm); |
| 198 | dst = ADD32(dst, src); |
| 199 | STORE_REG32(modrm, dst); |
| 200 | CYCLES(CYCLES_ALU_REG_REG); |
| 201 | } else { |
| 202 | UINT32 ea = GetEA(modrm,0); |
| 203 | src = READ32(ea); |
| 204 | dst = LOAD_REG32(modrm); |
| 205 | dst = ADD32(dst, src); |
| 206 | STORE_REG32(modrm, dst); |
| 207 | CYCLES(CYCLES_ALU_MEM_REG); |
| 208 | } |
| 209 | } |
| 210 | |
| 211 | void i386_device::i386_add_eax_i32() // Opcode 0x05 |
| 212 | { |
| 213 | UINT32 src, dst; |
| 214 | src = FETCH32(); |
| 215 | dst = REG32(EAX); |
| 216 | dst = ADD32(dst, src); |
| 217 | REG32(EAX) = dst; |
| 218 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 219 | } |
| 220 | |
| 221 | void i386_device::i386_and_rm32_r32() // Opcode 0x21 |
| 222 | { |
| 223 | UINT32 src, dst; |
| 224 | UINT8 modrm = FETCH(); |
| 225 | if( modrm >= 0xc0 ) { |
| 226 | src = LOAD_REG32(modrm); |
| 227 | dst = LOAD_RM32(modrm); |
| 228 | dst = AND32(dst, src); |
| 229 | STORE_RM32(modrm, dst); |
| 230 | CYCLES(CYCLES_ALU_REG_REG); |
| 231 | } else { |
| 232 | UINT32 ea = GetEA(modrm,1); |
| 233 | src = LOAD_REG32(modrm); |
| 234 | dst = READ32(ea); |
| 235 | dst = AND32(dst, src); |
| 236 | WRITE32(ea, dst); |
| 237 | CYCLES(CYCLES_ALU_REG_MEM); |
| 238 | } |
| 239 | } |
| 240 | |
| 241 | void i386_device::i386_and_r32_rm32() // Opcode 0x23 |
| 242 | { |
| 243 | UINT32 src, dst; |
| 244 | UINT8 modrm = FETCH(); |
| 245 | if( modrm >= 0xc0 ) { |
| 246 | src = LOAD_RM32(modrm); |
| 247 | dst = LOAD_REG32(modrm); |
| 248 | dst = AND32(dst, src); |
| 249 | STORE_REG32(modrm, dst); |
| 250 | CYCLES(CYCLES_ALU_REG_REG); |
| 251 | } else { |
| 252 | UINT32 ea = GetEA(modrm,0); |
| 253 | src = READ32(ea); |
| 254 | dst = LOAD_REG32(modrm); |
| 255 | dst = AND32(dst, src); |
| 256 | STORE_REG32(modrm, dst); |
| 257 | CYCLES(CYCLES_ALU_MEM_REG); |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | void i386_device::i386_and_eax_i32() // Opcode 0x25 |
| 262 | { |
| 263 | UINT32 src, dst; |
| 264 | src = FETCH32(); |
| 265 | dst = REG32(EAX); |
| 266 | dst = AND32(dst, src); |
| 267 | REG32(EAX) = dst; |
| 268 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 269 | } |
| 270 | |
| 271 | void i386_device::i386_bsf_r32_rm32() // Opcode 0x0f bc |
| 272 | { |
| 273 | UINT32 src, dst, temp; |
| 274 | UINT8 modrm = FETCH(); |
| 275 | |
| 276 | if( modrm >= 0xc0 ) { |
| 277 | src = LOAD_RM32(modrm); |
| 278 | } else { |
| 279 | UINT32 ea = GetEA(modrm,0); |
| 280 | src = READ32(ea); |
| 281 | } |
| 282 | |
| 283 | dst = 0; |
| 284 | |
| 285 | if( src == 0 ) { |
| 286 | m_ZF = 1; |
| 287 | } else { |
| 288 | m_ZF = 0; |
| 289 | temp = 0; |
| 290 | while( (src & (1 << temp)) == 0 ) { |
| 291 | temp++; |
| 292 | dst = temp; |
| 293 | CYCLES(CYCLES_BSF); |
| 294 | } |
| 295 | STORE_REG32(modrm, dst); |
| 296 | } |
| 297 | CYCLES(CYCLES_BSF_BASE); |
| 298 | } |
| 299 | |
| 300 | void i386_device::i386_bsr_r32_rm32() // Opcode 0x0f bd |
| 301 | { |
| 302 | UINT32 src, dst, temp; |
| 303 | UINT8 modrm = FETCH(); |
| 304 | |
| 305 | if( modrm >= 0xc0 ) { |
| 306 | src = LOAD_RM32(modrm); |
| 307 | } else { |
| 308 | UINT32 ea = GetEA(modrm,0); |
| 309 | src = READ32(ea); |
| 310 | } |
| 311 | |
| 312 | dst = 0; |
| 313 | |
| 314 | if( src == 0 ) { |
| 315 | m_ZF = 1; |
| 316 | } else { |
| 317 | m_ZF = 0; |
| 318 | dst = temp = 31; |
| 319 | while( (src & (1 << temp)) == 0 ) { |
| 320 | temp--; |
| 321 | dst = temp; |
| 322 | CYCLES(CYCLES_BSR); |
| 323 | } |
| 324 | STORE_REG32(modrm, dst); |
| 325 | } |
| 326 | CYCLES(CYCLES_BSR_BASE); |
| 327 | } |
| 328 | |
| 329 | void i386_device::i386_bt_rm32_r32() // Opcode 0x0f a3 |
| 330 | { |
| 331 | UINT8 modrm = FETCH(); |
| 332 | if( modrm >= 0xc0 ) { |
| 333 | UINT32 dst = LOAD_RM32(modrm); |
| 334 | UINT32 bit = LOAD_REG32(modrm); |
| 335 | |
| 336 | if( dst & (1 << bit) ) |
| 337 | m_CF = 1; |
| 338 | else |
| 339 | m_CF = 0; |
| 340 | |
| 341 | CYCLES(CYCLES_BT_REG_REG); |
| 342 | } else { |
| 343 | UINT8 segment; |
| 344 | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 345 | UINT32 bit = LOAD_REG32(modrm); |
| 346 | ea += 4*(bit/32); |
| 347 | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),0); |
| 348 | bit %= 32; |
| 349 | UINT32 dst = READ32(ea); |
| 350 | |
| 351 | if( dst & (1 << bit) ) |
| 352 | m_CF = 1; |
| 353 | else |
| 354 | m_CF = 0; |
| 355 | |
| 356 | CYCLES(CYCLES_BT_REG_MEM); |
| 357 | } |
| 358 | } |
| 359 | |
| 360 | void i386_device::i386_btc_rm32_r32() // Opcode 0x0f bb |
| 361 | { |
| 362 | UINT8 modrm = FETCH(); |
| 363 | if( modrm >= 0xc0 ) { |
| 364 | UINT32 dst = LOAD_RM32(modrm); |
| 365 | UINT32 bit = LOAD_REG32(modrm); |
| 366 | |
| 367 | if( dst & (1 << bit) ) |
| 368 | m_CF = 1; |
| 369 | else |
| 370 | m_CF = 0; |
| 371 | dst ^= (1 << bit); |
| 372 | |
| 373 | STORE_RM32(modrm, dst); |
| 374 | CYCLES(CYCLES_BTC_REG_REG); |
| 375 | } else { |
| 376 | UINT8 segment; |
| 377 | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 378 | UINT32 bit = LOAD_REG32(modrm); |
| 379 | ea += 4*(bit/32); |
| 380 | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1); |
| 381 | bit %= 32; |
| 382 | UINT32 dst = READ32(ea); |
| 383 | |
| 384 | if( dst & (1 << bit) ) |
| 385 | m_CF = 1; |
| 386 | else |
| 387 | m_CF = 0; |
| 388 | dst ^= (1 << bit); |
| 389 | |
| 390 | WRITE32(ea, dst); |
| 391 | CYCLES(CYCLES_BTC_REG_MEM); |
| 392 | } |
| 393 | } |
| 394 | |
| 395 | void i386_device::i386_btr_rm32_r32() // Opcode 0x0f b3 |
| 396 | { |
| 397 | UINT8 modrm = FETCH(); |
| 398 | if( modrm >= 0xc0 ) { |
| 399 | UINT32 dst = LOAD_RM32(modrm); |
| 400 | UINT32 bit = LOAD_REG32(modrm); |
| 401 | |
| 402 | if( dst & (1 << bit) ) |
| 403 | m_CF = 1; |
| 404 | else |
| 405 | m_CF = 0; |
| 406 | dst &= ~(1 << bit); |
| 407 | |
| 408 | STORE_RM32(modrm, dst); |
| 409 | CYCLES(CYCLES_BTR_REG_REG); |
| 410 | } else { |
| 411 | UINT8 segment; |
| 412 | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 413 | UINT32 bit = LOAD_REG32(modrm); |
| 414 | ea += 4*(bit/32); |
| 415 | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1); |
| 416 | bit %= 32; |
| 417 | UINT32 dst = READ32(ea); |
| 418 | |
| 419 | if( dst & (1 << bit) ) |
| 420 | m_CF = 1; |
| 421 | else |
| 422 | m_CF = 0; |
| 423 | dst &= ~(1 << bit); |
| 424 | |
| 425 | WRITE32(ea, dst); |
| 426 | CYCLES(CYCLES_BTR_REG_MEM); |
| 427 | } |
| 428 | } |
| 429 | |
| 430 | void i386_device::i386_bts_rm32_r32() // Opcode 0x0f ab |
| 431 | { |
| 432 | UINT8 modrm = FETCH(); |
| 433 | if( modrm >= 0xc0 ) { |
| 434 | UINT32 dst = LOAD_RM32(modrm); |
| 435 | UINT32 bit = LOAD_REG32(modrm); |
| 436 | |
| 437 | if( dst & (1 << bit) ) |
| 438 | m_CF = 1; |
| 439 | else |
| 440 | m_CF = 0; |
| 441 | dst |= (1 << bit); |
| 442 | |
| 443 | STORE_RM32(modrm, dst); |
| 444 | CYCLES(CYCLES_BTS_REG_REG); |
| 445 | } else { |
| 446 | UINT8 segment; |
| 447 | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 448 | UINT32 bit = LOAD_REG32(modrm); |
| 449 | ea += 4*(bit/32); |
| 450 | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1); |
| 451 | bit %= 32; |
| 452 | UINT32 dst = READ32(ea); |
| 453 | |
| 454 | if( dst & (1 << bit) ) |
| 455 | m_CF = 1; |
| 456 | else |
| 457 | m_CF = 0; |
| 458 | dst |= (1 << bit); |
| 459 | |
| 460 | WRITE32(ea, dst); |
| 461 | CYCLES(CYCLES_BTS_REG_MEM); |
| 462 | } |
| 463 | } |
| 464 | |
| 465 | void i386_device::i386_call_abs32() // Opcode 0x9a |
| 466 | { |
| 467 | UINT32 offset = FETCH32(); |
| 468 | UINT16 ptr = FETCH16(); |
| 469 | |
| 470 | if(PROTECTED_MODE && !V8086_MODE) |
| 471 | { |
| 472 | i386_protected_mode_call(ptr,offset,0,1); |
| 473 | } |
| 474 | else |
| 475 | { |
| 476 | PUSH32(m_sreg[CS].selector ); |
| 477 | PUSH32(m_eip ); |
| 478 | m_sreg[CS].selector = ptr; |
| 479 | m_performed_intersegment_jump = 1; |
| 480 | m_eip = offset; |
| 481 | i386_load_segment_descriptor(CS); |
| 482 | } |
| 483 | CYCLES(CYCLES_CALL_INTERSEG); |
| 484 | CHANGE_PC(m_eip); |
| 485 | } |
| 486 | |
| 487 | void i386_device::i386_call_rel32() // Opcode 0xe8 |
| 488 | { |
| 489 | INT32 disp = FETCH32(); |
| 490 | PUSH32(m_eip ); |
| 491 | m_eip += disp; |
| 492 | CHANGE_PC(m_eip); |
| 493 | CYCLES(CYCLES_CALL); /* TODO: Timing = 7 + m */ |
| 494 | } |
| 495 | |
| 496 | void i386_device::i386_cdq() // Opcode 0x99 |
| 497 | { |
| 498 | if( REG32(EAX) & 0x80000000 ) { |
| 499 | REG32(EDX) = 0xffffffff; |
| 500 | } else { |
| 501 | REG32(EDX) = 0x00000000; |
| 502 | } |
| 503 | CYCLES(CYCLES_CWD); |
| 504 | } |
| 505 | |
| 506 | void i386_device::i386_cmp_rm32_r32() // Opcode 0x39 |
| 507 | { |
| 508 | UINT32 src, dst; |
| 509 | UINT8 modrm = FETCH(); |
| 510 | if( modrm >= 0xc0 ) { |
| 511 | src = LOAD_REG32(modrm); |
| 512 | dst = LOAD_RM32(modrm); |
| 513 | SUB32(dst, src); |
| 514 | CYCLES(CYCLES_CMP_REG_REG); |
| 515 | } else { |
| 516 | UINT32 ea = GetEA(modrm,0); |
| 517 | src = LOAD_REG32(modrm); |
| 518 | dst = READ32(ea); |
| 519 | SUB32(dst, src); |
| 520 | CYCLES(CYCLES_CMP_REG_MEM); |
| 521 | } |
| 522 | } |
| 523 | |
| 524 | void i386_device::i386_cmp_r32_rm32() // Opcode 0x3b |
| 525 | { |
| 526 | UINT32 src, dst; |
| 527 | UINT8 modrm = FETCH(); |
| 528 | if( modrm >= 0xc0 ) { |
| 529 | src = LOAD_RM32(modrm); |
| 530 | dst = LOAD_REG32(modrm); |
| 531 | SUB32(dst, src); |
| 532 | CYCLES(CYCLES_CMP_REG_REG); |
| 533 | } else { |
| 534 | UINT32 ea = GetEA(modrm,0); |
| 535 | src = READ32(ea); |
| 536 | dst = LOAD_REG32(modrm); |
| 537 | SUB32(dst, src); |
| 538 | CYCLES(CYCLES_CMP_MEM_REG); |
| 539 | } |
| 540 | } |
| 541 | |
| 542 | void i386_device::i386_cmp_eax_i32() // Opcode 0x3d |
| 543 | { |
| 544 | UINT32 src, dst; |
| 545 | src = FETCH32(); |
| 546 | dst = REG32(EAX); |
| 547 | SUB32(dst, src); |
| 548 | CYCLES(CYCLES_CMP_IMM_ACC); |
| 549 | } |
| 550 | |
| 551 | void i386_device::i386_cmpsd() // Opcode 0xa7 |
| 552 | { |
| 553 | UINT32 eas, ead, src, dst; |
| 554 | if( m_segment_prefix ) { |
| 555 | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 556 | } else { |
| 557 | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 558 | } |
| 559 | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 ); |
| 560 | src = READ32(eas); |
| 561 | dst = READ32(ead); |
| 562 | SUB32(src,dst); |
| 563 | BUMP_SI(4); |
| 564 | BUMP_DI(4); |
| 565 | CYCLES(CYCLES_CMPS); |
| 566 | } |
| 567 | |
| 568 | void i386_device::i386_cwde() // Opcode 0x98 |
| 569 | { |
| 570 | REG32(EAX) = (INT32)((INT16)REG16(AX)); |
| 571 | CYCLES(CYCLES_CBW); |
| 572 | } |
| 573 | |
| 574 | void i386_device::i386_dec_eax() // Opcode 0x48 |
| 575 | { |
| 576 | REG32(EAX) = DEC32(REG32(EAX) ); |
| 577 | CYCLES(CYCLES_DEC_REG); |
| 578 | } |
| 579 | |
| 580 | void i386_device::i386_dec_ecx() // Opcode 0x49 |
| 581 | { |
| 582 | REG32(ECX) = DEC32(REG32(ECX) ); |
| 583 | CYCLES(CYCLES_DEC_REG); |
| 584 | } |
| 585 | |
| 586 | void i386_device::i386_dec_edx() // Opcode 0x4a |
| 587 | { |
| 588 | REG32(EDX) = DEC32(REG32(EDX) ); |
| 589 | CYCLES(CYCLES_DEC_REG); |
| 590 | } |
| 591 | |
| 592 | void i386_device::i386_dec_ebx() // Opcode 0x4b |
| 593 | { |
| 594 | REG32(EBX) = DEC32(REG32(EBX) ); |
| 595 | CYCLES(CYCLES_DEC_REG); |
| 596 | } |
| 597 | |
| 598 | void i386_device::i386_dec_esp() // Opcode 0x4c |
| 599 | { |
| 600 | REG32(ESP) = DEC32(REG32(ESP) ); |
| 601 | CYCLES(CYCLES_DEC_REG); |
| 602 | } |
| 603 | |
| 604 | void i386_device::i386_dec_ebp() // Opcode 0x4d |
| 605 | { |
| 606 | REG32(EBP) = DEC32(REG32(EBP) ); |
| 607 | CYCLES(CYCLES_DEC_REG); |
| 608 | } |
| 609 | |
| 610 | void i386_device::i386_dec_esi() // Opcode 0x4e |
| 611 | { |
| 612 | REG32(ESI) = DEC32(REG32(ESI) ); |
| 613 | CYCLES(CYCLES_DEC_REG); |
| 614 | } |
| 615 | |
| 616 | void i386_device::i386_dec_edi() // Opcode 0x4f |
| 617 | { |
| 618 | REG32(EDI) = DEC32(REG32(EDI) ); |
| 619 | CYCLES(CYCLES_DEC_REG); |
| 620 | } |
| 621 | |
| 622 | void i386_device::i386_imul_r32_rm32() // Opcode 0x0f af |
| 623 | { |
| 624 | UINT8 modrm = FETCH(); |
| 625 | INT64 result; |
| 626 | INT64 src, dst; |
| 627 | if( modrm >= 0xc0 ) { |
| 628 | src = (INT64)(INT32)LOAD_RM32(modrm); |
| 629 | CYCLES(CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */ |
| 630 | } else { |
| 631 | UINT32 ea = GetEA(modrm,0); |
| 632 | src = (INT64)(INT32)READ32(ea); |
| 633 | CYCLES(CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */ |
| 634 | } |
| 635 | |
| 636 | dst = (INT64)(INT32)LOAD_REG32(modrm); |
| 637 | result = src * dst; |
| 638 | |
| 639 | STORE_REG32(modrm, (UINT32)result); |
| 640 | |
| 641 | m_CF = m_OF = !(result == (INT64)(INT32)result); |
| 642 | } |
| 643 | |
| 644 | void i386_device::i386_imul_r32_rm32_i32() // Opcode 0x69 |
| 645 | { |
| 646 | UINT8 modrm = FETCH(); |
| 647 | INT64 result; |
| 648 | INT64 src, dst; |
| 649 | if( modrm >= 0xc0 ) { |
| 650 | dst = (INT64)(INT32)LOAD_RM32(modrm); |
| 651 | CYCLES(CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */ |
| 652 | } else { |
| 653 | UINT32 ea = GetEA(modrm,0); |
| 654 | dst = (INT64)(INT32)READ32(ea); |
| 655 | CYCLES(CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */ |
| 656 | } |
| 657 | |
| 658 | src = (INT64)(INT32)FETCH32(); |
| 659 | result = src * dst; |
| 660 | |
| 661 | STORE_REG32(modrm, (UINT32)result); |
| 662 | |
| 663 | m_CF = m_OF = !(result == (INT64)(INT32)result); |
| 664 | } |
| 665 | |
| 666 | void i386_device::i386_imul_r32_rm32_i8() // Opcode 0x6b |
| 667 | { |
| 668 | UINT8 modrm = FETCH(); |
| 669 | INT64 result; |
| 670 | INT64 src, dst; |
| 671 | if( modrm >= 0xc0 ) { |
| 672 | dst = (INT64)(INT32)LOAD_RM32(modrm); |
| 673 | CYCLES(CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */ |
| 674 | } else { |
| 675 | UINT32 ea = GetEA(modrm,0); |
| 676 | dst = (INT64)(INT32)READ32(ea); |
| 677 | CYCLES(CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */ |
| 678 | } |
| 679 | |
| 680 | src = (INT64)(INT8)FETCH(); |
| 681 | result = src * dst; |
| 682 | |
| 683 | STORE_REG32(modrm, (UINT32)result); |
| 684 | |
| 685 | m_CF = m_OF = !(result == (INT64)(INT32)result); |
| 686 | } |
| 687 | |
| 688 | void i386_device::i386_in_eax_i8() // Opcode 0xe5 |
| 689 | { |
| 690 | UINT16 port = FETCH(); |
| 691 | UINT32 data = READPORT32(port); |
| 692 | REG32(EAX) = data; |
| 693 | CYCLES(CYCLES_IN_VAR); |
| 694 | } |
| 695 | |
| 696 | void i386_device::i386_in_eax_dx() // Opcode 0xed |
| 697 | { |
| 698 | UINT16 port = REG16(DX); |
| 699 | UINT32 data = READPORT32(port); |
| 700 | REG32(EAX) = data; |
| 701 | CYCLES(CYCLES_IN); |
| 702 | } |
| 703 | |
| 704 | void i386_device::i386_inc_eax() // Opcode 0x40 |
| 705 | { |
| 706 | REG32(EAX) = INC32(REG32(EAX) ); |
| 707 | CYCLES(CYCLES_INC_REG); |
| 708 | } |
| 709 | |
| 710 | void i386_device::i386_inc_ecx() // Opcode 0x41 |
| 711 | { |
| 712 | REG32(ECX) = INC32(REG32(ECX) ); |
| 713 | CYCLES(CYCLES_INC_REG); |
| 714 | } |
| 715 | |
| 716 | void i386_device::i386_inc_edx() // Opcode 0x42 |
| 717 | { |
| 718 | REG32(EDX) = INC32(REG32(EDX) ); |
| 719 | CYCLES(CYCLES_INC_REG); |
| 720 | } |
| 721 | |
| 722 | void i386_device::i386_inc_ebx() // Opcode 0x43 |
| 723 | { |
| 724 | REG32(EBX) = INC32(REG32(EBX) ); |
| 725 | CYCLES(CYCLES_INC_REG); |
| 726 | } |
| 727 | |
| 728 | void i386_device::i386_inc_esp() // Opcode 0x44 |
| 729 | { |
| 730 | REG32(ESP) = INC32(REG32(ESP) ); |
| 731 | CYCLES(CYCLES_INC_REG); |
| 732 | } |
| 733 | |
| 734 | void i386_device::i386_inc_ebp() // Opcode 0x45 |
| 735 | { |
| 736 | REG32(EBP) = INC32(REG32(EBP) ); |
| 737 | CYCLES(CYCLES_INC_REG); |
| 738 | } |
| 739 | |
| 740 | void i386_device::i386_inc_esi() // Opcode 0x46 |
| 741 | { |
| 742 | REG32(ESI) = INC32(REG32(ESI) ); |
| 743 | CYCLES(CYCLES_INC_REG); |
| 744 | } |
| 745 | |
| 746 | void i386_device::i386_inc_edi() // Opcode 0x47 |
| 747 | { |
| 748 | REG32(EDI) = INC32(REG32(EDI) ); |
| 749 | CYCLES(CYCLES_INC_REG); |
| 750 | } |
| 751 | |
| 752 | void i386_device::i386_iret32() // Opcode 0xcf |
| 753 | { |
| 754 | if( PROTECTED_MODE ) |
| 755 | { |
| 756 | i386_protected_mode_iret(1); |
| 757 | } |
| 758 | else |
| 759 | { |
| 760 | /* TODO: #SS(0) exception */ |
| 761 | /* TODO: #GP(0) exception */ |
| 762 | m_eip = POP32(); |
| 763 | m_sreg[CS].selector = POP32() & 0xffff; |
| 764 | set_flags(POP32() ); |
| 765 | i386_load_segment_descriptor(CS); |
| 766 | CHANGE_PC(m_eip); |
| 767 | } |
| 768 | CYCLES(CYCLES_IRET); |
| 769 | } |
| 770 | |
| 771 | void i386_device::i386_ja_rel32() // Opcode 0x0f 87 |
| 772 | { |
| 773 | INT32 disp = FETCH32(); |
| 774 | if( m_CF == 0 && m_ZF == 0 ) { |
| 775 | m_eip += disp; |
| 776 | CHANGE_PC(m_eip); |
| 777 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 778 | } else { |
| 779 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 780 | } |
| 781 | } |
| 782 | |
| 783 | void i386_device::i386_jbe_rel32() // Opcode 0x0f 86 |
| 784 | { |
| 785 | INT32 disp = FETCH32(); |
| 786 | if( m_CF != 0 || m_ZF != 0 ) { |
| 787 | m_eip += disp; |
| 788 | CHANGE_PC(m_eip); |
| 789 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 790 | } else { |
| 791 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 792 | } |
| 793 | } |
| 794 | |
| 795 | void i386_device::i386_jc_rel32() // Opcode 0x0f 82 |
| 796 | { |
| 797 | INT32 disp = FETCH32(); |
| 798 | if( m_CF != 0 ) { |
| 799 | m_eip += disp; |
| 800 | CHANGE_PC(m_eip); |
| 801 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 802 | } else { |
| 803 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 804 | } |
| 805 | } |
| 806 | |
| 807 | void i386_device::i386_jg_rel32() // Opcode 0x0f 8f |
| 808 | { |
| 809 | INT32 disp = FETCH32(); |
| 810 | if( m_ZF == 0 && (m_SF == m_OF) ) { |
| 811 | m_eip += disp; |
| 812 | CHANGE_PC(m_eip); |
| 813 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 814 | } else { |
| 815 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 816 | } |
| 817 | } |
| 818 | |
| 819 | void i386_device::i386_jge_rel32() // Opcode 0x0f 8d |
| 820 | { |
| 821 | INT32 disp = FETCH32(); |
| 822 | if(m_SF == m_OF) { |
| 823 | m_eip += disp; |
| 824 | CHANGE_PC(m_eip); |
| 825 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 826 | } else { |
| 827 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 828 | } |
| 829 | } |
| 830 | |
| 831 | void i386_device::i386_jl_rel32() // Opcode 0x0f 8c |
| 832 | { |
| 833 | INT32 disp = FETCH32(); |
| 834 | if( (m_SF != m_OF) ) { |
| 835 | m_eip += disp; |
| 836 | CHANGE_PC(m_eip); |
| 837 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 838 | } else { |
| 839 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 840 | } |
| 841 | } |
| 842 | |
| 843 | void i386_device::i386_jle_rel32() // Opcode 0x0f 8e |
| 844 | { |
| 845 | INT32 disp = FETCH32(); |
| 846 | if( m_ZF != 0 || (m_SF != m_OF) ) { |
| 847 | m_eip += disp; |
| 848 | CHANGE_PC(m_eip); |
| 849 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 850 | } else { |
| 851 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 852 | } |
| 853 | } |
| 854 | |
| 855 | void i386_device::i386_jnc_rel32() // Opcode 0x0f 83 |
| 856 | { |
| 857 | INT32 disp = FETCH32(); |
| 858 | if( m_CF == 0 ) { |
| 859 | m_eip += disp; |
| 860 | CHANGE_PC(m_eip); |
| 861 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 862 | } else { |
| 863 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 864 | } |
| 865 | } |
| 866 | |
| 867 | void i386_device::i386_jno_rel32() // Opcode 0x0f 81 |
| 868 | { |
| 869 | INT32 disp = FETCH32(); |
| 870 | if( m_OF == 0 ) { |
| 871 | m_eip += disp; |
| 872 | CHANGE_PC(m_eip); |
| 873 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 874 | } else { |
| 875 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 876 | } |
| 877 | } |
| 878 | |
| 879 | void i386_device::i386_jnp_rel32() // Opcode 0x0f 8b |
| 880 | { |
| 881 | INT32 disp = FETCH32(); |
| 882 | if( m_PF == 0 ) { |
| 883 | m_eip += disp; |
| 884 | CHANGE_PC(m_eip); |
| 885 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 886 | } else { |
| 887 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 888 | } |
| 889 | } |
| 890 | |
| 891 | void i386_device::i386_jns_rel32() // Opcode 0x0f 89 |
| 892 | { |
| 893 | INT32 disp = FETCH32(); |
| 894 | if( m_SF == 0 ) { |
| 895 | m_eip += disp; |
| 896 | CHANGE_PC(m_eip); |
| 897 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 898 | } else { |
| 899 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 900 | } |
| 901 | } |
| 902 | |
| 903 | void i386_device::i386_jnz_rel32() // Opcode 0x0f 85 |
| 904 | { |
| 905 | INT32 disp = FETCH32(); |
| 906 | if( m_ZF == 0 ) { |
| 907 | m_eip += disp; |
| 908 | CHANGE_PC(m_eip); |
| 909 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 910 | } else { |
| 911 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 912 | } |
| 913 | } |
| 914 | |
| 915 | void i386_device::i386_jo_rel32() // Opcode 0x0f 80 |
| 916 | { |
| 917 | INT32 disp = FETCH32(); |
| 918 | if( m_OF != 0 ) { |
| 919 | m_eip += disp; |
| 920 | CHANGE_PC(m_eip); |
| 921 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 922 | } else { |
| 923 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 924 | } |
| 925 | } |
| 926 | |
| 927 | void i386_device::i386_jp_rel32() // Opcode 0x0f 8a |
| 928 | { |
| 929 | INT32 disp = FETCH32(); |
| 930 | if( m_PF != 0 ) { |
| 931 | m_eip += disp; |
| 932 | CHANGE_PC(m_eip); |
| 933 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 934 | } else { |
| 935 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 936 | } |
| 937 | } |
| 938 | |
| 939 | void i386_device::i386_js_rel32() // Opcode 0x0f 88 |
| 940 | { |
| 941 | INT32 disp = FETCH32(); |
| 942 | if( m_SF != 0 ) { |
| 943 | m_eip += disp; |
| 944 | CHANGE_PC(m_eip); |
| 945 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 946 | } else { |
| 947 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 948 | } |
| 949 | } |
| 950 | |
| 951 | void i386_device::i386_jz_rel32() // Opcode 0x0f 84 |
| 952 | { |
| 953 | INT32 disp = FETCH32(); |
| 954 | if( m_ZF != 0 ) { |
| 955 | m_eip += disp; |
| 956 | CHANGE_PC(m_eip); |
| 957 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 958 | } else { |
| 959 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 960 | } |
| 961 | } |
| 962 | |
| 963 | void i386_device::i386_jcxz32() // Opcode 0xe3 |
| 964 | { |
| 965 | INT8 disp = FETCH(); |
| 966 | int val = (m_address_size)?(REG32(ECX) == 0):(REG16(CX) == 0); |
| 967 | if( val ) { |
| 968 | m_eip += disp; |
| 969 | CHANGE_PC(m_eip); |
| 970 | CYCLES(CYCLES_JCXZ); /* TODO: Timing = 9 + m */ |
| 971 | } else { |
| 972 | CYCLES(CYCLES_JCXZ_NOBRANCH); |
| 973 | } |
| 974 | } |
| 975 | |
| 976 | void i386_device::i386_jmp_rel32() // Opcode 0xe9 |
| 977 | { |
| 978 | UINT32 disp = FETCH32(); |
| 979 | /* TODO: Segment limit */ |
| 980 | m_eip += disp; |
| 981 | CHANGE_PC(m_eip); |
| 982 | CYCLES(CYCLES_JMP); /* TODO: Timing = 7 + m */ |
| 983 | } |
| 984 | |
| 985 | void i386_device::i386_jmp_abs32() // Opcode 0xea |
| 986 | { |
| 987 | UINT32 address = FETCH32(); |
| 988 | UINT16 segment = FETCH16(); |
| 989 | |
| 990 | if( PROTECTED_MODE && !V8086_MODE) |
| 991 | { |
| 992 | i386_protected_mode_jump(segment,address,0,1); |
| 993 | } |
| 994 | else |
| 995 | { |
| 996 | m_eip = address; |
| 997 | m_sreg[CS].selector = segment; |
| 998 | m_performed_intersegment_jump = 1; |
| 999 | i386_load_segment_descriptor(CS); |
| 1000 | CHANGE_PC(m_eip); |
| 1001 | } |
| 1002 | CYCLES(CYCLES_JMP_INTERSEG); |
| 1003 | } |
| 1004 | |
| 1005 | void i386_device::i386_lea32() // Opcode 0x8d |
| 1006 | { |
| 1007 | UINT8 modrm = FETCH(); |
| 1008 | UINT32 ea = GetNonTranslatedEA(modrm,NULL); |
| 1009 | if (!m_address_size) |
| 1010 | { |
| 1011 | ea &= 0xffff; |
| 1012 | } |
| 1013 | STORE_REG32(modrm, ea); |
| 1014 | CYCLES(CYCLES_LEA); |
| 1015 | } |
| 1016 | |
| 1017 | void i386_device::i386_enter32() // Opcode 0xc8 |
| 1018 | { |
| 1019 | UINT16 framesize = FETCH16(); |
| 1020 | UINT8 level = FETCH() % 32; |
| 1021 | UINT8 x; |
| 1022 | UINT32 frameptr; |
| 1023 | PUSH32(REG32(EBP)); |
| 1024 | if(!STACK_32BIT) |
| 1025 | frameptr = REG16(SP); |
| 1026 | else |
| 1027 | frameptr = REG32(ESP); |
| 1028 | |
| 1029 | if(level > 0) |
| 1030 | { |
| 1031 | for(x=1;x<level-1;x++) |
| 1032 | { |
| 1033 | REG32(EBP) -= 4; |
| 1034 | PUSH32(READ32(REG32(EBP))); |
| 1035 | } |
| 1036 | PUSH32(frameptr); |
| 1037 | } |
| 1038 | REG32(EBP) = frameptr; |
| 1039 | if(!STACK_32BIT) |
| 1040 | REG16(SP) -= framesize; |
| 1041 | else |
| 1042 | REG32(ESP) -= framesize; |
| 1043 | CYCLES(CYCLES_ENTER); |
| 1044 | } |
| 1045 | |
| 1046 | void i386_device::i386_leave32() // Opcode 0xc9 |
| 1047 | { |
| 1048 | if(!STACK_32BIT) |
| 1049 | REG16(SP) = REG16(BP); |
| 1050 | else |
| 1051 | REG32(ESP) = REG32(EBP); |
| 1052 | REG32(EBP) = POP32(); |
| 1053 | CYCLES(CYCLES_LEAVE); |
| 1054 | } |
| 1055 | |
| 1056 | void i386_device::i386_lodsd() // Opcode 0xad |
| 1057 | { |
| 1058 | UINT32 eas; |
| 1059 | if( m_segment_prefix ) { |
| 1060 | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1061 | } else { |
| 1062 | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1063 | } |
| 1064 | REG32(EAX) = READ32(eas); |
| 1065 | BUMP_SI(4); |
| 1066 | CYCLES(CYCLES_LODS); |
| 1067 | } |
| 1068 | |
| 1069 | void i386_device::i386_loop32() // Opcode 0xe2 |
| 1070 | { |
| 1071 | INT8 disp = FETCH(); |
| 1072 | INT32 reg = (m_address_size)?--REG32(ECX):--REG16(CX); |
| 1073 | if( reg != 0 ) { |
| 1074 | m_eip += disp; |
| 1075 | CHANGE_PC(m_eip); |
| 1076 | } |
| 1077 | CYCLES(CYCLES_LOOP); /* TODO: Timing = 11 + m */ |
| 1078 | } |
| 1079 | |
| 1080 | void i386_device::i386_loopne32() // Opcode 0xe0 |
| 1081 | { |
| 1082 | INT8 disp = FETCH(); |
| 1083 | INT32 reg = (m_address_size)?--REG32(ECX):--REG16(CX); |
| 1084 | if( reg != 0 && m_ZF == 0 ) { |
| 1085 | m_eip += disp; |
| 1086 | CHANGE_PC(m_eip); |
| 1087 | } |
| 1088 | CYCLES(CYCLES_LOOPNZ); /* TODO: Timing = 11 + m */ |
| 1089 | } |
| 1090 | |
| 1091 | void i386_device::i386_loopz32() // Opcode 0xe1 |
| 1092 | { |
| 1093 | INT8 disp = FETCH(); |
| 1094 | INT32 reg = (m_address_size)?--REG32(ECX):--REG16(CX); |
| 1095 | if( reg != 0 && m_ZF != 0 ) { |
| 1096 | m_eip += disp; |
| 1097 | CHANGE_PC(m_eip); |
| 1098 | } |
| 1099 | CYCLES(CYCLES_LOOPZ); /* TODO: Timing = 11 + m */ |
| 1100 | } |
| 1101 | |
| 1102 | void i386_device::i386_mov_rm32_r32() // Opcode 0x89 |
| 1103 | { |
| 1104 | UINT32 src; |
| 1105 | UINT8 modrm = FETCH(); |
| 1106 | if( modrm >= 0xc0 ) { |
| 1107 | src = LOAD_REG32(modrm); |
| 1108 | STORE_RM32(modrm, src); |
| 1109 | CYCLES(CYCLES_MOV_REG_REG); |
| 1110 | } else { |
| 1111 | UINT32 ea = GetEA(modrm,1); |
| 1112 | src = LOAD_REG32(modrm); |
| 1113 | WRITE32(ea, src); |
| 1114 | CYCLES(CYCLES_MOV_REG_MEM); |
| 1115 | } |
| 1116 | } |
| 1117 | |
| 1118 | void i386_device::i386_mov_r32_rm32() // Opcode 0x8b |
| 1119 | { |
| 1120 | UINT32 src; |
| 1121 | UINT8 modrm = FETCH(); |
| 1122 | if( modrm >= 0xc0 ) { |
| 1123 | src = LOAD_RM32(modrm); |
| 1124 | STORE_REG32(modrm, src); |
| 1125 | CYCLES(CYCLES_MOV_REG_REG); |
| 1126 | } else { |
| 1127 | UINT32 ea = GetEA(modrm,0); |
| 1128 | src = READ32(ea); |
| 1129 | STORE_REG32(modrm, src); |
| 1130 | CYCLES(CYCLES_MOV_MEM_REG); |
| 1131 | } |
| 1132 | } |
| 1133 | |
| 1134 | void i386_device::i386_mov_rm32_i32() // Opcode 0xc7 |
| 1135 | { |
| 1136 | UINT8 modrm = FETCH(); |
| 1137 | if( modrm >= 0xc0 ) { |
| 1138 | UINT32 value = FETCH32(); |
| 1139 | STORE_RM32(modrm, value); |
| 1140 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1141 | } else { |
| 1142 | UINT32 ea = GetEA(modrm,1); |
| 1143 | UINT32 value = FETCH32(); |
| 1144 | WRITE32(ea, value); |
| 1145 | CYCLES(CYCLES_MOV_IMM_MEM); |
| 1146 | } |
| 1147 | } |
| 1148 | |
| 1149 | void i386_device::i386_mov_eax_m32() // Opcode 0xa1 |
| 1150 | { |
| 1151 | UINT32 offset, ea; |
| 1152 | if( m_address_size ) { |
| 1153 | offset = FETCH32(); |
| 1154 | } else { |
| 1155 | offset = FETCH16(); |
| 1156 | } |
| 1157 | if( m_segment_prefix ) { |
| 1158 | ea = i386_translate(m_segment_override, offset, 0 ); |
| 1159 | } else { |
| 1160 | ea = i386_translate(DS, offset, 0 ); |
| 1161 | } |
| 1162 | REG32(EAX) = READ32(ea); |
| 1163 | CYCLES(CYCLES_MOV_MEM_ACC); |
| 1164 | } |
| 1165 | |
| 1166 | void i386_device::i386_mov_m32_eax() // Opcode 0xa3 |
| 1167 | { |
| 1168 | UINT32 offset, ea; |
| 1169 | if( m_address_size ) { |
| 1170 | offset = FETCH32(); |
| 1171 | } else { |
| 1172 | offset = FETCH16(); |
| 1173 | } |
| 1174 | if( m_segment_prefix ) { |
| 1175 | ea = i386_translate(m_segment_override, offset, 1 ); |
| 1176 | } else { |
| 1177 | ea = i386_translate(DS, offset, 1 ); |
| 1178 | } |
| 1179 | WRITE32(ea, REG32(EAX) ); |
| 1180 | CYCLES(CYCLES_MOV_ACC_MEM); |
| 1181 | } |
| 1182 | |
| 1183 | void i386_device::i386_mov_eax_i32() // Opcode 0xb8 |
| 1184 | { |
| 1185 | REG32(EAX) = FETCH32(); |
| 1186 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1187 | } |
| 1188 | |
| 1189 | void i386_device::i386_mov_ecx_i32() // Opcode 0xb9 |
| 1190 | { |
| 1191 | REG32(ECX) = FETCH32(); |
| 1192 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1193 | } |
| 1194 | |
| 1195 | void i386_device::i386_mov_edx_i32() // Opcode 0xba |
| 1196 | { |
| 1197 | REG32(EDX) = FETCH32(); |
| 1198 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1199 | } |
| 1200 | |
| 1201 | void i386_device::i386_mov_ebx_i32() // Opcode 0xbb |
| 1202 | { |
| 1203 | REG32(EBX) = FETCH32(); |
| 1204 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1205 | } |
| 1206 | |
| 1207 | void i386_device::i386_mov_esp_i32() // Opcode 0xbc |
| 1208 | { |
| 1209 | REG32(ESP) = FETCH32(); |
| 1210 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1211 | } |
| 1212 | |
| 1213 | void i386_device::i386_mov_ebp_i32() // Opcode 0xbd |
| 1214 | { |
| 1215 | REG32(EBP) = FETCH32(); |
| 1216 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1217 | } |
| 1218 | |
| 1219 | void i386_device::i386_mov_esi_i32() // Opcode 0xbe |
| 1220 | { |
| 1221 | REG32(ESI) = FETCH32(); |
| 1222 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1223 | } |
| 1224 | |
| 1225 | void i386_device::i386_mov_edi_i32() // Opcode 0xbf |
| 1226 | { |
| 1227 | REG32(EDI) = FETCH32(); |
| 1228 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1229 | } |
| 1230 | |
| 1231 | void i386_device::i386_movsd() // Opcode 0xa5 |
| 1232 | { |
| 1233 | UINT32 eas, ead, v; |
| 1234 | if( m_segment_prefix ) { |
| 1235 | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1236 | } else { |
| 1237 | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1238 | } |
| 1239 | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 1240 | v = READ32(eas); |
| 1241 | WRITE32(ead, v); |
| 1242 | BUMP_SI(4); |
| 1243 | BUMP_DI(4); |
| 1244 | CYCLES(CYCLES_MOVS); |
| 1245 | } |
| 1246 | |
| 1247 | void i386_device::i386_movsx_r32_rm8() // Opcode 0x0f be |
| 1248 | { |
| 1249 | UINT8 modrm = FETCH(); |
| 1250 | if( modrm >= 0xc0 ) { |
| 1251 | INT32 src = (INT8)LOAD_RM8(modrm); |
| 1252 | STORE_REG32(modrm, src); |
| 1253 | CYCLES(CYCLES_MOVSX_REG_REG); |
| 1254 | } else { |
| 1255 | UINT32 ea = GetEA(modrm,0); |
| 1256 | INT32 src = (INT8)READ8(ea); |
| 1257 | STORE_REG32(modrm, src); |
| 1258 | CYCLES(CYCLES_MOVSX_MEM_REG); |
| 1259 | } |
| 1260 | } |
| 1261 | |
| 1262 | void i386_device::i386_movsx_r32_rm16() // Opcode 0x0f bf |
| 1263 | { |
| 1264 | UINT8 modrm = FETCH(); |
| 1265 | if( modrm >= 0xc0 ) { |
| 1266 | INT32 src = (INT16)LOAD_RM16(modrm); |
| 1267 | STORE_REG32(modrm, src); |
| 1268 | CYCLES(CYCLES_MOVSX_REG_REG); |
| 1269 | } else { |
| 1270 | UINT32 ea = GetEA(modrm,0); |
| 1271 | INT32 src = (INT16)READ16(ea); |
| 1272 | STORE_REG32(modrm, src); |
| 1273 | CYCLES(CYCLES_MOVSX_MEM_REG); |
| 1274 | } |
| 1275 | } |
| 1276 | |
| 1277 | void i386_device::i386_movzx_r32_rm8() // Opcode 0x0f b6 |
| 1278 | { |
| 1279 | UINT8 modrm = FETCH(); |
| 1280 | if( modrm >= 0xc0 ) { |
| 1281 | UINT32 src = (UINT8)LOAD_RM8(modrm); |
| 1282 | STORE_REG32(modrm, src); |
| 1283 | CYCLES(CYCLES_MOVZX_REG_REG); |
| 1284 | } else { |
| 1285 | UINT32 ea = GetEA(modrm,0); |
| 1286 | UINT32 src = (UINT8)READ8(ea); |
| 1287 | STORE_REG32(modrm, src); |
| 1288 | CYCLES(CYCLES_MOVZX_MEM_REG); |
| 1289 | } |
| 1290 | } |
| 1291 | |
| 1292 | void i386_device::i386_movzx_r32_rm16() // Opcode 0x0f b7 |
| 1293 | { |
| 1294 | UINT8 modrm = FETCH(); |
| 1295 | if( modrm >= 0xc0 ) { |
| 1296 | UINT32 src = (UINT16)LOAD_RM16(modrm); |
| 1297 | STORE_REG32(modrm, src); |
| 1298 | CYCLES(CYCLES_MOVZX_REG_REG); |
| 1299 | } else { |
| 1300 | UINT32 ea = GetEA(modrm,0); |
| 1301 | UINT32 src = (UINT16)READ16(ea); |
| 1302 | STORE_REG32(modrm, src); |
| 1303 | CYCLES(CYCLES_MOVZX_MEM_REG); |
| 1304 | } |
| 1305 | } |
| 1306 | |
| 1307 | void i386_device::i386_or_rm32_r32() // Opcode 0x09 |
| 1308 | { |
| 1309 | UINT32 src, dst; |
| 1310 | UINT8 modrm = FETCH(); |
| 1311 | if( modrm >= 0xc0 ) { |
| 1312 | src = LOAD_REG32(modrm); |
| 1313 | dst = LOAD_RM32(modrm); |
| 1314 | dst = OR32(dst, src); |
| 1315 | STORE_RM32(modrm, dst); |
| 1316 | CYCLES(CYCLES_ALU_REG_REG); |
| 1317 | } else { |
| 1318 | UINT32 ea = GetEA(modrm,1); |
| 1319 | src = LOAD_REG32(modrm); |
| 1320 | dst = READ32(ea); |
| 1321 | dst = OR32(dst, src); |
| 1322 | WRITE32(ea, dst); |
| 1323 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1324 | } |
| 1325 | } |
| 1326 | |
| 1327 | void i386_device::i386_or_r32_rm32() // Opcode 0x0b |
| 1328 | { |
| 1329 | UINT32 src, dst; |
| 1330 | UINT8 modrm = FETCH(); |
| 1331 | if( modrm >= 0xc0 ) { |
| 1332 | src = LOAD_RM32(modrm); |
| 1333 | dst = LOAD_REG32(modrm); |
| 1334 | dst = OR32(dst, src); |
| 1335 | STORE_REG32(modrm, dst); |
| 1336 | CYCLES(CYCLES_ALU_REG_REG); |
| 1337 | } else { |
| 1338 | UINT32 ea = GetEA(modrm,0); |
| 1339 | src = READ32(ea); |
| 1340 | dst = LOAD_REG32(modrm); |
| 1341 | dst = OR32(dst, src); |
| 1342 | STORE_REG32(modrm, dst); |
| 1343 | CYCLES(CYCLES_ALU_MEM_REG); |
| 1344 | } |
| 1345 | } |
| 1346 | |
| 1347 | void i386_device::i386_or_eax_i32() // Opcode 0x0d |
| 1348 | { |
| 1349 | UINT32 src, dst; |
| 1350 | src = FETCH32(); |
| 1351 | dst = REG32(EAX); |
| 1352 | dst = OR32(dst, src); |
| 1353 | REG32(EAX) = dst; |
| 1354 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1355 | } |
| 1356 | |
| 1357 | void i386_device::i386_out_eax_i8() // Opcode 0xe7 |
| 1358 | { |
| 1359 | UINT16 port = FETCH(); |
| 1360 | UINT32 data = REG32(EAX); |
| 1361 | WRITEPORT32(port, data); |
| 1362 | CYCLES(CYCLES_OUT_VAR); |
| 1363 | } |
| 1364 | |
| 1365 | void i386_device::i386_out_eax_dx() // Opcode 0xef |
| 1366 | { |
| 1367 | UINT16 port = REG16(DX); |
| 1368 | UINT32 data = REG32(EAX); |
| 1369 | WRITEPORT32(port, data); |
| 1370 | CYCLES(CYCLES_OUT); |
| 1371 | } |
| 1372 | |
| 1373 | void i386_device::i386_pop_eax() // Opcode 0x58 |
| 1374 | { |
| 1375 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1376 | if(i386_limit_check(SS,offset+3) == 0) |
| 1377 | REG32(EAX) = POP32(); |
| 1378 | else |
| 1379 | FAULT(FAULT_SS,0) |
| 1380 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1381 | } |
| 1382 | |
| 1383 | void i386_device::i386_pop_ecx() // Opcode 0x59 |
| 1384 | { |
| 1385 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1386 | if(i386_limit_check(SS,offset+3) == 0) |
| 1387 | REG32(ECX) = POP32(); |
| 1388 | else |
| 1389 | FAULT(FAULT_SS,0) |
| 1390 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1391 | } |
| 1392 | |
| 1393 | void i386_device::i386_pop_edx() // Opcode 0x5a |
| 1394 | { |
| 1395 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1396 | if(i386_limit_check(SS,offset+3) == 0) |
| 1397 | REG32(EDX) = POP32(); |
| 1398 | else |
| 1399 | FAULT(FAULT_SS,0) |
| 1400 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1401 | } |
| 1402 | |
| 1403 | void i386_device::i386_pop_ebx() // Opcode 0x5b |
| 1404 | { |
| 1405 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1406 | if(i386_limit_check(SS,offset+3) == 0) |
| 1407 | REG32(EBX) = POP32(); |
| 1408 | else |
| 1409 | FAULT(FAULT_SS,0) |
| 1410 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1411 | } |
| 1412 | |
| 1413 | void i386_device::i386_pop_esp() // Opcode 0x5c |
| 1414 | { |
| 1415 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1416 | if(i386_limit_check(SS,offset+3) == 0) |
| 1417 | REG32(ESP) = POP32(); |
| 1418 | else |
| 1419 | FAULT(FAULT_SS,0) |
| 1420 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1421 | } |
| 1422 | |
| 1423 | void i386_device::i386_pop_ebp() // Opcode 0x5d |
| 1424 | { |
| 1425 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1426 | if(i386_limit_check(SS,offset+3) == 0) |
| 1427 | REG32(EBP) = POP32(); |
| 1428 | else |
| 1429 | FAULT(FAULT_SS,0) |
| 1430 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1431 | } |
| 1432 | |
| 1433 | void i386_device::i386_pop_esi() // Opcode 0x5e |
| 1434 | { |
| 1435 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1436 | if(i386_limit_check(SS,offset+3) == 0) |
| 1437 | REG32(ESI) = POP32(); |
| 1438 | else |
| 1439 | FAULT(FAULT_SS,0) |
| 1440 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1441 | } |
| 1442 | |
| 1443 | void i386_device::i386_pop_edi() // Opcode 0x5f |
| 1444 | { |
| 1445 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1446 | if(i386_limit_check(SS,offset+3) == 0) |
| 1447 | REG32(EDI) = POP32(); |
| 1448 | else |
| 1449 | FAULT(FAULT_SS,0) |
| 1450 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1451 | } |
| 1452 | |
| 1453 | bool i386_device::i386_pop_seg32(int segment) |
| 1454 | { |
| 1455 | UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1456 | UINT32 value; |
| 1457 | bool fault; |
| 1458 | if(i386_limit_check(SS,offset+3) == 0) |
| 1459 | { |
| 1460 | ea = i386_translate(SS, offset, 0); |
| 1461 | value = READ32(ea); |
| 1462 | i386_sreg_load(value, segment, &fault); |
| 1463 | if(fault) return false; |
| 1464 | if(STACK_32BIT) |
| 1465 | REG32(ESP) = offset + 4; |
| 1466 | else |
| 1467 | REG16(SP) = offset + 4; |
| 1468 | } |
| 1469 | else |
| 1470 | { |
| 1471 | m_ext = 1; |
| 1472 | i386_trap_with_error(FAULT_SS,0,0,0); |
| 1473 | return false; |
| 1474 | } |
| 1475 | CYCLES(CYCLES_POP_SREG); |
| 1476 | return true; |
| 1477 | } |
| 1478 | |
| 1479 | void i386_device::i386_pop_ds32() // Opcode 0x1f |
| 1480 | { |
| 1481 | i386_pop_seg32(DS); |
| 1482 | } |
| 1483 | |
| 1484 | void i386_device::i386_pop_es32() // Opcode 0x07 |
| 1485 | { |
| 1486 | i386_pop_seg32(ES); |
| 1487 | } |
| 1488 | |
| 1489 | void i386_device::i386_pop_fs32() // Opcode 0x0f a1 |
| 1490 | { |
| 1491 | i386_pop_seg32(FS); |
| 1492 | } |
| 1493 | |
| 1494 | void i386_device::i386_pop_gs32() // Opcode 0x0f a9 |
| 1495 | { |
| 1496 | i386_pop_seg32(GS); |
| 1497 | } |
| 1498 | |
| 1499 | void i386_device::i386_pop_ss32() // Opcode 0x17 |
| 1500 | { |
| 1501 | if(!i386_pop_seg32(SS)) return; |
| 1502 | if(m_IF != 0) // if external interrupts are enabled |
| 1503 | { |
| 1504 | m_IF = 0; // reset IF for the next instruction |
| 1505 | m_delayed_interrupt_enable = 1; |
| 1506 | } |
| 1507 | } |
| 1508 | |
| 1509 | void i386_device::i386_pop_rm32() // Opcode 0x8f |
| 1510 | { |
| 1511 | UINT8 modrm = FETCH(); |
| 1512 | UINT32 value; |
| 1513 | UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1514 | if(i386_limit_check(SS,offset+3) == 0) |
| 1515 | { |
| 1516 | // be careful here, if the write references the esp register |
| 1517 | // it expects the post-pop value but esp must be wound back |
| 1518 | // if the write faults |
| 1519 | UINT32 temp_sp = REG32(ESP); |
| 1520 | value = POP32(); |
| 1521 | |
| 1522 | if( modrm >= 0xc0 ) { |
| 1523 | STORE_RM32(modrm, value); |
| 1524 | } else { |
| 1525 | ea = GetEA(modrm,1); |
| 1526 | try |
| 1527 | { |
| 1528 | WRITE32(ea, value); |
| 1529 | } |
| 1530 | catch(UINT64 e) |
| 1531 | { |
| 1532 | REG32(ESP) = temp_sp; |
| 1533 | throw e; |
| 1534 | } |
| 1535 | } |
| 1536 | } |
| 1537 | else |
| 1538 | FAULT(FAULT_SS,0) |
| 1539 | CYCLES(CYCLES_POP_RM); |
| 1540 | } |
| 1541 | |
| 1542 | void i386_device::i386_popad() // Opcode 0x61 |
| 1543 | { |
| 1544 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1545 | if(i386_limit_check(SS,offset+31) == 0) |
| 1546 | { |
| 1547 | REG32(EDI) = POP32(); |
| 1548 | REG32(ESI) = POP32(); |
| 1549 | REG32(EBP) = POP32(); |
| 1550 | REG32(ESP) += 4; |
| 1551 | REG32(EBX) = POP32(); |
| 1552 | REG32(EDX) = POP32(); |
| 1553 | REG32(ECX) = POP32(); |
| 1554 | REG32(EAX) = POP32(); |
| 1555 | } |
| 1556 | else |
| 1557 | FAULT(FAULT_SS,0) |
| 1558 | CYCLES(CYCLES_POPA); |
| 1559 | } |
| 1560 | |
| 1561 | void i386_device::i386_popfd() // Opcode 0x9d |
| 1562 | { |
| 1563 | UINT32 value; |
| 1564 | UINT32 current = get_flags(); |
| 1565 | UINT8 IOPL = (current >> 12) & 0x03; |
| 1566 | UINT32 mask = 0x00257fd5; // VM, VIP and VIF cannot be set by POPF/POPFD |
| 1567 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1568 | |
| 1569 | // IOPL can only change if CPL is 0 |
| 1570 | if(m_CPL != 0) |
| 1571 | mask &= ~0x00003000; |
| 1572 | |
| 1573 | // IF can only change if CPL is at least as privileged as IOPL |
| 1574 | if(m_CPL > IOPL) |
| 1575 | mask &= ~0x00000200; |
| 1576 | |
| 1577 | if(V8086_MODE) |
| 1578 | { |
| 1579 | if(IOPL < 3) |
| 1580 | { |
| 1581 | logerror("POPFD(%08x): IOPL < 3 while in V86 mode.\n",m_pc); |
| 1582 | FAULT(FAULT_GP,0) // #GP(0) |
| 1583 | } |
| 1584 | mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode |
| 1585 | } |
| 1586 | |
| 1587 | if(i386_limit_check(SS,offset+3) == 0) |
| 1588 | { |
| 1589 | value = POP32(); |
| 1590 | value &= ~0x00010000; // RF will always return zero |
| 1591 | set_flags((current & ~mask) | (value & mask)); // mask out reserved bits |
| 1592 | } |
| 1593 | else |
| 1594 | FAULT(FAULT_SS,0) |
| 1595 | CYCLES(CYCLES_POPF); |
| 1596 | } |
| 1597 | |
| 1598 | void i386_device::i386_push_eax() // Opcode 0x50 |
| 1599 | { |
| 1600 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1601 | if(i386_limit_check(SS,offset-4) == 0) |
| 1602 | PUSH32(REG32(EAX) ); |
| 1603 | else |
| 1604 | FAULT(FAULT_SS,0) |
| 1605 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1606 | } |
| 1607 | |
| 1608 | void i386_device::i386_push_ecx() // Opcode 0x51 |
| 1609 | { |
| 1610 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1611 | if(i386_limit_check(SS,offset-4) == 0) |
| 1612 | PUSH32(REG32(ECX) ); |
| 1613 | else |
| 1614 | FAULT(FAULT_SS,0) |
| 1615 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1616 | } |
| 1617 | |
| 1618 | void i386_device::i386_push_edx() // Opcode 0x52 |
| 1619 | { |
| 1620 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1621 | if(i386_limit_check(SS,offset-4) == 0) |
| 1622 | PUSH32(REG32(EDX) ); |
| 1623 | else |
| 1624 | FAULT(FAULT_SS,0) |
| 1625 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1626 | } |
| 1627 | |
| 1628 | void i386_device::i386_push_ebx() // Opcode 0x53 |
| 1629 | { |
| 1630 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1631 | if(i386_limit_check(SS,offset-4) == 0) |
| 1632 | PUSH32(REG32(EBX) ); |
| 1633 | else |
| 1634 | FAULT(FAULT_SS,0) |
| 1635 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1636 | } |
| 1637 | |
| 1638 | void i386_device::i386_push_esp() // Opcode 0x54 |
| 1639 | { |
| 1640 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1641 | if(i386_limit_check(SS,offset-4) == 0) |
| 1642 | PUSH32(REG32(ESP) ); |
| 1643 | else |
| 1644 | FAULT(FAULT_SS,0) |
| 1645 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1646 | } |
| 1647 | |
| 1648 | void i386_device::i386_push_ebp() // Opcode 0x55 |
| 1649 | { |
| 1650 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1651 | if(i386_limit_check(SS,offset-4) == 0) |
| 1652 | PUSH32(REG32(EBP) ); |
| 1653 | else |
| 1654 | FAULT(FAULT_SS,0) |
| 1655 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1656 | } |
| 1657 | |
| 1658 | void i386_device::i386_push_esi() // Opcode 0x56 |
| 1659 | { |
| 1660 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1661 | if(i386_limit_check(SS,offset-4) == 0) |
| 1662 | PUSH32(REG32(ESI) ); |
| 1663 | else |
| 1664 | FAULT(FAULT_SS,0) |
| 1665 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1666 | } |
| 1667 | |
| 1668 | void i386_device::i386_push_edi() // Opcode 0x57 |
| 1669 | { |
| 1670 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1671 | if(i386_limit_check(SS,offset-4) == 0) |
| 1672 | PUSH32(REG32(EDI) ); |
| 1673 | else |
| 1674 | FAULT(FAULT_SS,0) |
| 1675 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1676 | } |
| 1677 | |
| 1678 | void i386_device::i386_push_cs32() // Opcode 0x0e |
| 1679 | { |
| 1680 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1681 | if(i386_limit_check(SS,offset-4) == 0) |
| 1682 | PUSH32(m_sreg[CS].selector ); |
| 1683 | else |
| 1684 | FAULT(FAULT_SS,0) |
| 1685 | CYCLES(CYCLES_PUSH_SREG); |
| 1686 | } |
| 1687 | |
| 1688 | void i386_device::i386_push_ds32() // Opcode 0x1e |
| 1689 | { |
| 1690 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1691 | if(i386_limit_check(SS,offset-4) == 0) |
| 1692 | PUSH32(m_sreg[DS].selector ); |
| 1693 | else |
| 1694 | FAULT(FAULT_SS,0) |
| 1695 | CYCLES(CYCLES_PUSH_SREG); |
| 1696 | } |
| 1697 | |
| 1698 | void i386_device::i386_push_es32() // Opcode 0x06 |
| 1699 | { |
| 1700 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1701 | if(i386_limit_check(SS,offset-4) == 0) |
| 1702 | PUSH32(m_sreg[ES].selector ); |
| 1703 | else |
| 1704 | FAULT(FAULT_SS,0) |
| 1705 | CYCLES(CYCLES_PUSH_SREG); |
| 1706 | } |
| 1707 | |
| 1708 | void i386_device::i386_push_fs32() // Opcode 0x0f a0 |
| 1709 | { |
| 1710 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1711 | if(i386_limit_check(SS,offset-4) == 0) |
| 1712 | PUSH32(m_sreg[FS].selector ); |
| 1713 | else |
| 1714 | FAULT(FAULT_SS,0) |
| 1715 | CYCLES(CYCLES_PUSH_SREG); |
| 1716 | } |
| 1717 | |
| 1718 | void i386_device::i386_push_gs32() // Opcode 0x0f a8 |
| 1719 | { |
| 1720 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1721 | if(i386_limit_check(SS,offset-4) == 0) |
| 1722 | PUSH32(m_sreg[GS].selector ); |
| 1723 | else |
| 1724 | FAULT(FAULT_SS,0) |
| 1725 | CYCLES(CYCLES_PUSH_SREG); |
| 1726 | } |
| 1727 | |
| 1728 | void i386_device::i386_push_ss32() // Opcode 0x16 |
| 1729 | { |
| 1730 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1731 | if(i386_limit_check(SS,offset-4) == 0) |
| 1732 | PUSH32(m_sreg[SS].selector ); |
| 1733 | else |
| 1734 | FAULT(FAULT_SS,0) |
| 1735 | CYCLES(CYCLES_PUSH_SREG); |
| 1736 | } |
| 1737 | |
| 1738 | void i386_device::i386_push_i32() // Opcode 0x68 |
| 1739 | { |
| 1740 | UINT32 value = FETCH32(); |
| 1741 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1742 | if(i386_limit_check(SS,offset-4) == 0) |
| 1743 | PUSH32(value); |
| 1744 | else |
| 1745 | FAULT(FAULT_SS,0) |
| 1746 | CYCLES(CYCLES_PUSH_IMM); |
| 1747 | } |
| 1748 | |
| 1749 | void i386_device::i386_pushad() // Opcode 0x60 |
| 1750 | { |
| 1751 | UINT32 temp = REG32(ESP); |
| 1752 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1753 | if(i386_limit_check(SS,offset-32) == 0) |
| 1754 | { |
| 1755 | PUSH32(REG32(EAX) ); |
| 1756 | PUSH32(REG32(ECX) ); |
| 1757 | PUSH32(REG32(EDX) ); |
| 1758 | PUSH32(REG32(EBX) ); |
| 1759 | PUSH32(temp ); |
| 1760 | PUSH32(REG32(EBP) ); |
| 1761 | PUSH32(REG32(ESI) ); |
| 1762 | PUSH32(REG32(EDI) ); |
| 1763 | } |
| 1764 | else |
| 1765 | FAULT(FAULT_SS,0) |
| 1766 | CYCLES(CYCLES_PUSHA); |
| 1767 | } |
| 1768 | |
| 1769 | void i386_device::i386_pushfd() // Opcode 0x9c |
| 1770 | { |
| 1771 | if(!m_IOP1 && !m_IOP2 && V8086_MODE) |
| 1772 | FAULT(FAULT_GP,0) |
| 1773 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1774 | if(i386_limit_check(SS,offset-4) == 0) |
| 1775 | PUSH32(get_flags() & 0x00fcffff ); |
| 1776 | else |
| 1777 | FAULT(FAULT_SS,0) |
| 1778 | CYCLES(CYCLES_PUSHF); |
| 1779 | } |
| 1780 | |
| 1781 | void i386_device::i386_ret_near32_i16() // Opcode 0xc2 |
| 1782 | { |
| 1783 | INT16 disp = FETCH16(); |
| 1784 | m_eip = POP32(); |
| 1785 | REG32(ESP) += disp; |
| 1786 | CHANGE_PC(m_eip); |
| 1787 | CYCLES(CYCLES_RET_IMM); /* TODO: Timing = 10 + m */ |
| 1788 | } |
| 1789 | |
| 1790 | void i386_device::i386_ret_near32() // Opcode 0xc3 |
| 1791 | { |
| 1792 | m_eip = POP32(); |
| 1793 | CHANGE_PC(m_eip); |
| 1794 | CYCLES(CYCLES_RET); /* TODO: Timing = 10 + m */ |
| 1795 | } |
| 1796 | |
| 1797 | void i386_device::i386_sbb_rm32_r32() // Opcode 0x19 |
| 1798 | { |
| 1799 | UINT32 src, dst; |
| 1800 | UINT8 modrm = FETCH(); |
| 1801 | if( modrm >= 0xc0 ) { |
| 1802 | src = LOAD_REG32(modrm); |
| 1803 | dst = LOAD_RM32(modrm); |
| 1804 | dst = SBB32(dst, src, m_CF); |
| 1805 | STORE_RM32(modrm, dst); |
| 1806 | CYCLES(CYCLES_ALU_REG_REG); |
| 1807 | } else { |
| 1808 | UINT32 ea = GetEA(modrm,1); |
| 1809 | src = LOAD_REG32(modrm); |
| 1810 | dst = READ32(ea); |
| 1811 | dst = SBB32(dst, src, m_CF); |
| 1812 | WRITE32(ea, dst); |
| 1813 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1814 | } |
| 1815 | } |
| 1816 | |
| 1817 | void i386_device::i386_sbb_r32_rm32() // Opcode 0x1b |
| 1818 | { |
| 1819 | UINT32 src, dst; |
| 1820 | UINT8 modrm = FETCH(); |
| 1821 | if( modrm >= 0xc0 ) { |
| 1822 | src = LOAD_RM32(modrm); |
| 1823 | dst = LOAD_REG32(modrm); |
| 1824 | dst = SBB32(dst, src, m_CF); |
| 1825 | STORE_REG32(modrm, dst); |
| 1826 | CYCLES(CYCLES_ALU_REG_REG); |
| 1827 | } else { |
| 1828 | UINT32 ea = GetEA(modrm,0); |
| 1829 | src = READ32(ea); |
| 1830 | dst = LOAD_REG32(modrm); |
| 1831 | dst = SBB32(dst, src, m_CF); |
| 1832 | STORE_REG32(modrm, dst); |
| 1833 | CYCLES(CYCLES_ALU_MEM_REG); |
| 1834 | } |
| 1835 | } |
| 1836 | |
| 1837 | void i386_device::i386_sbb_eax_i32() // Opcode 0x1d |
| 1838 | { |
| 1839 | UINT32 src, dst; |
| 1840 | src = FETCH32(); |
| 1841 | dst = REG32(EAX); |
| 1842 | dst = SBB32(dst, src, m_CF); |
| 1843 | REG32(EAX) = dst; |
| 1844 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1845 | } |
| 1846 | |
| 1847 | void i386_device::i386_scasd() // Opcode 0xaf |
| 1848 | { |
| 1849 | UINT32 eas, src, dst; |
| 1850 | eas = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 ); |
| 1851 | src = READ32(eas); |
| 1852 | dst = REG32(EAX); |
| 1853 | SUB32(dst, src); |
| 1854 | BUMP_DI(4); |
| 1855 | CYCLES(CYCLES_SCAS); |
| 1856 | } |
| 1857 | |
| 1858 | void i386_device::i386_shld32_i8() // Opcode 0x0f a4 |
| 1859 | { |
| 1860 | UINT8 modrm = FETCH(); |
| 1861 | if( modrm >= 0xc0 ) { |
| 1862 | UINT32 dst = LOAD_RM32(modrm); |
| 1863 | UINT32 upper = LOAD_REG32(modrm); |
| 1864 | UINT8 shift = FETCH(); |
| 1865 | shift &= 31; |
| 1866 | if( shift == 0 ) { |
| 1867 | } else { |
| 1868 | m_CF = (dst & (1 << (32-shift))) ? 1 : 0; |
| 1869 | dst = (dst << shift) | (upper >> (32-shift)); |
| 1870 | m_OF = m_CF ^ (dst >> 31); |
| 1871 | SetSZPF32(dst); |
| 1872 | } |
| 1873 | STORE_RM32(modrm, dst); |
| 1874 | CYCLES(CYCLES_SHLD_REG); |
| 1875 | } else { |
| 1876 | UINT32 ea = GetEA(modrm,1); |
| 1877 | UINT32 dst = READ32(ea); |
| 1878 | UINT32 upper = LOAD_REG32(modrm); |
| 1879 | UINT8 shift = FETCH(); |
| 1880 | shift &= 31; |
| 1881 | if( shift == 0 ) { |
| 1882 | } else { |
| 1883 | m_CF = (dst & (1 << (32-shift))) ? 1 : 0; |
| 1884 | dst = (dst << shift) | (upper >> (32-shift)); |
| 1885 | m_OF = m_CF ^ (dst >> 31); |
| 1886 | SetSZPF32(dst); |
| 1887 | } |
| 1888 | WRITE32(ea, dst); |
| 1889 | CYCLES(CYCLES_SHLD_MEM); |
| 1890 | } |
| 1891 | } |
| 1892 | |
| 1893 | void i386_device::i386_shld32_cl() // Opcode 0x0f a5 |
| 1894 | { |
| 1895 | UINT8 modrm = FETCH(); |
| 1896 | if( modrm >= 0xc0 ) { |
| 1897 | UINT32 dst = LOAD_RM32(modrm); |
| 1898 | UINT32 upper = LOAD_REG32(modrm); |
| 1899 | UINT8 shift = REG8(CL); |
| 1900 | shift &= 31; |
| 1901 | if( shift == 0 ) { |
| 1902 | } else { |
| 1903 | m_CF = (dst & (1 << (32-shift))) ? 1 : 0; |
| 1904 | dst = (dst << shift) | (upper >> (32-shift)); |
| 1905 | m_OF = m_CF ^ (dst >> 31); |
| 1906 | SetSZPF32(dst); |
| 1907 | } |
| 1908 | STORE_RM32(modrm, dst); |
| 1909 | CYCLES(CYCLES_SHLD_REG); |
| 1910 | } else { |
| 1911 | UINT32 ea = GetEA(modrm,1); |
| 1912 | UINT32 dst = READ32(ea); |
| 1913 | UINT32 upper = LOAD_REG32(modrm); |
| 1914 | UINT8 shift = REG8(CL); |
| 1915 | shift &= 31; |
| 1916 | if( shift == 0 ) { |
| 1917 | } else { |
| 1918 | m_CF = (dst & (1 << (32-shift))) ? 1 : 0; |
| 1919 | dst = (dst << shift) | (upper >> (32-shift)); |
| 1920 | m_OF = m_CF ^ (dst >> 31); |
| 1921 | SetSZPF32(dst); |
| 1922 | } |
| 1923 | WRITE32(ea, dst); |
| 1924 | CYCLES(CYCLES_SHLD_MEM); |
| 1925 | } |
| 1926 | } |
| 1927 | |
| 1928 | void i386_device::i386_shrd32_i8() // Opcode 0x0f ac |
| 1929 | { |
| 1930 | UINT8 modrm = FETCH(); |
| 1931 | if( modrm >= 0xc0 ) { |
| 1932 | UINT32 dst = LOAD_RM32(modrm); |
| 1933 | UINT32 upper = LOAD_REG32(modrm); |
| 1934 | UINT8 shift = FETCH(); |
| 1935 | shift &= 31; |
| 1936 | if( shift == 0 ) { |
| 1937 | } else { |
| 1938 | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 1939 | dst = (dst >> shift) | (upper << (32-shift)); |
| 1940 | m_OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 1941 | SetSZPF32(dst); |
| 1942 | } |
| 1943 | STORE_RM32(modrm, dst); |
| 1944 | CYCLES(CYCLES_SHRD_REG); |
| 1945 | } else { |
| 1946 | UINT32 ea = GetEA(modrm,1); |
| 1947 | UINT32 dst = READ32(ea); |
| 1948 | UINT32 upper = LOAD_REG32(modrm); |
| 1949 | UINT8 shift = FETCH(); |
| 1950 | shift &= 31; |
| 1951 | if( shift == 0 ) { |
| 1952 | } else { |
| 1953 | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 1954 | dst = (dst >> shift) | (upper << (32-shift)); |
| 1955 | m_OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 1956 | SetSZPF32(dst); |
| 1957 | } |
| 1958 | WRITE32(ea, dst); |
| 1959 | CYCLES(CYCLES_SHRD_MEM); |
| 1960 | } |
| 1961 | } |
| 1962 | |
| 1963 | void i386_device::i386_shrd32_cl() // Opcode 0x0f ad |
| 1964 | { |
| 1965 | UINT8 modrm = FETCH(); |
| 1966 | if( modrm >= 0xc0 ) { |
| 1967 | UINT32 dst = LOAD_RM32(modrm); |
| 1968 | UINT32 upper = LOAD_REG32(modrm); |
| 1969 | UINT8 shift = REG8(CL); |
| 1970 | shift &= 31; |
| 1971 | if( shift == 0 ) { |
| 1972 | } else { |
| 1973 | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 1974 | dst = (dst >> shift) | (upper << (32-shift)); |
| 1975 | m_OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 1976 | SetSZPF32(dst); |
| 1977 | } |
| 1978 | STORE_RM32(modrm, dst); |
| 1979 | CYCLES(CYCLES_SHRD_REG); |
| 1980 | } else { |
| 1981 | UINT32 ea = GetEA(modrm,1); |
| 1982 | UINT32 dst = READ32(ea); |
| 1983 | UINT32 upper = LOAD_REG32(modrm); |
| 1984 | UINT8 shift = REG8(CL); |
| 1985 | shift &= 31; |
| 1986 | if( shift == 0 ) { |
| 1987 | } else { |
| 1988 | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 1989 | dst = (dst >> shift) | (upper << (32-shift)); |
| 1990 | m_OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 1991 | SetSZPF32(dst); |
| 1992 | } |
| 1993 | WRITE32(ea, dst); |
| 1994 | CYCLES(CYCLES_SHRD_MEM); |
| 1995 | } |
| 1996 | } |
| 1997 | |
| 1998 | void i386_device::i386_stosd() // Opcode 0xab |
| 1999 | { |
| 2000 | UINT32 eas = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 2001 | WRITE32(eas, REG32(EAX)); |
| 2002 | BUMP_DI(4); |
| 2003 | CYCLES(CYCLES_STOS); |
| 2004 | } |
| 2005 | |
| 2006 | void i386_device::i386_sub_rm32_r32() // Opcode 0x29 |
| 2007 | { |
| 2008 | UINT32 src, dst; |
| 2009 | UINT8 modrm = FETCH(); |
| 2010 | if( modrm >= 0xc0 ) { |
| 2011 | src = LOAD_REG32(modrm); |
| 2012 | dst = LOAD_RM32(modrm); |
| 2013 | dst = SUB32(dst, src); |
| 2014 | STORE_RM32(modrm, dst); |
| 2015 | CYCLES(CYCLES_ALU_REG_REG); |
| 2016 | } else { |
| 2017 | UINT32 ea = GetEA(modrm,1); |
| 2018 | src = LOAD_REG32(modrm); |
| 2019 | dst = READ32(ea); |
| 2020 | dst = SUB32(dst, src); |
| 2021 | WRITE32(ea, dst); |
| 2022 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2023 | } |
| 2024 | } |
| 2025 | |
| 2026 | void i386_device::i386_sub_r32_rm32() // Opcode 0x2b |
| 2027 | { |
| 2028 | UINT32 src, dst; |
| 2029 | UINT8 modrm = FETCH(); |
| 2030 | if( modrm >= 0xc0 ) { |
| 2031 | src = LOAD_RM32(modrm); |
| 2032 | dst = LOAD_REG32(modrm); |
| 2033 | dst = SUB32(dst, src); |
| 2034 | STORE_REG32(modrm, dst); |
| 2035 | CYCLES(CYCLES_ALU_REG_REG); |
| 2036 | } else { |
| 2037 | UINT32 ea = GetEA(modrm,1); |
| 2038 | src = READ32(ea); |
| 2039 | dst = LOAD_REG32(modrm); |
| 2040 | dst = SUB32(dst, src); |
| 2041 | STORE_REG32(modrm, dst); |
| 2042 | CYCLES(CYCLES_ALU_MEM_REG); |
| 2043 | } |
| 2044 | } |
| 2045 | |
| 2046 | void i386_device::i386_sub_eax_i32() // Opcode 0x2d |
| 2047 | { |
| 2048 | UINT32 src, dst; |
| 2049 | src = FETCH32(); |
| 2050 | dst = REG32(EAX); |
| 2051 | dst = SUB32(dst, src); |
| 2052 | REG32(EAX) = dst; |
| 2053 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 2054 | } |
| 2055 | |
| 2056 | void i386_device::i386_test_eax_i32() // Opcode 0xa9 |
| 2057 | { |
| 2058 | UINT32 src = FETCH32(); |
| 2059 | UINT32 dst = REG32(EAX); |
| 2060 | dst = src & dst; |
| 2061 | SetSZPF32(dst); |
| 2062 | m_CF = 0; |
| 2063 | m_OF = 0; |
| 2064 | CYCLES(CYCLES_TEST_IMM_ACC); |
| 2065 | } |
| 2066 | |
| 2067 | void i386_device::i386_test_rm32_r32() // Opcode 0x85 |
| 2068 | { |
| 2069 | UINT32 src, dst; |
| 2070 | UINT8 modrm = FETCH(); |
| 2071 | if( modrm >= 0xc0 ) { |
| 2072 | src = LOAD_REG32(modrm); |
| 2073 | dst = LOAD_RM32(modrm); |
| 2074 | dst = src & dst; |
| 2075 | SetSZPF32(dst); |
| 2076 | m_CF = 0; |
| 2077 | m_OF = 0; |
| 2078 | CYCLES(CYCLES_TEST_REG_REG); |
| 2079 | } else { |
| 2080 | UINT32 ea = GetEA(modrm,0); |
| 2081 | src = LOAD_REG32(modrm); |
| 2082 | dst = READ32(ea); |
| 2083 | dst = src & dst; |
| 2084 | SetSZPF32(dst); |
| 2085 | m_CF = 0; |
| 2086 | m_OF = 0; |
| 2087 | CYCLES(CYCLES_TEST_REG_MEM); |
| 2088 | } |
| 2089 | } |
| 2090 | |
| 2091 | void i386_device::i386_xchg_eax_ecx() // Opcode 0x91 |
| 2092 | { |
| 2093 | UINT32 temp; |
| 2094 | temp = REG32(EAX); |
| 2095 | REG32(EAX) = REG32(ECX); |
| 2096 | REG32(ECX) = temp; |
| 2097 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2098 | } |
| 2099 | |
| 2100 | void i386_device::i386_xchg_eax_edx() // Opcode 0x92 |
| 2101 | { |
| 2102 | UINT32 temp; |
| 2103 | temp = REG32(EAX); |
| 2104 | REG32(EAX) = REG32(EDX); |
| 2105 | REG32(EDX) = temp; |
| 2106 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2107 | } |
| 2108 | |
| 2109 | void i386_device::i386_xchg_eax_ebx() // Opcode 0x93 |
| 2110 | { |
| 2111 | UINT32 temp; |
| 2112 | temp = REG32(EAX); |
| 2113 | REG32(EAX) = REG32(EBX); |
| 2114 | REG32(EBX) = temp; |
| 2115 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2116 | } |
| 2117 | |
| 2118 | void i386_device::i386_xchg_eax_esp() // Opcode 0x94 |
| 2119 | { |
| 2120 | UINT32 temp; |
| 2121 | temp = REG32(EAX); |
| 2122 | REG32(EAX) = REG32(ESP); |
| 2123 | REG32(ESP) = temp; |
| 2124 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2125 | } |
| 2126 | |
| 2127 | void i386_device::i386_xchg_eax_ebp() // Opcode 0x95 |
| 2128 | { |
| 2129 | UINT32 temp; |
| 2130 | temp = REG32(EAX); |
| 2131 | REG32(EAX) = REG32(EBP); |
| 2132 | REG32(EBP) = temp; |
| 2133 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2134 | } |
| 2135 | |
| 2136 | void i386_device::i386_xchg_eax_esi() // Opcode 0x96 |
| 2137 | { |
| 2138 | UINT32 temp; |
| 2139 | temp = REG32(EAX); |
| 2140 | REG32(EAX) = REG32(ESI); |
| 2141 | REG32(ESI) = temp; |
| 2142 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2143 | } |
| 2144 | |
| 2145 | void i386_device::i386_xchg_eax_edi() // Opcode 0x97 |
| 2146 | { |
| 2147 | UINT32 temp; |
| 2148 | temp = REG32(EAX); |
| 2149 | REG32(EAX) = REG32(EDI); |
| 2150 | REG32(EDI) = temp; |
| 2151 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2152 | } |
| 2153 | |
| 2154 | void i386_device::i386_xchg_r32_rm32() // Opcode 0x87 |
| 2155 | { |
| 2156 | UINT8 modrm = FETCH(); |
| 2157 | if( modrm >= 0xc0 ) { |
| 2158 | UINT32 src = LOAD_RM32(modrm); |
| 2159 | UINT32 dst = LOAD_REG32(modrm); |
| 2160 | STORE_REG32(modrm, src); |
| 2161 | STORE_RM32(modrm, dst); |
| 2162 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2163 | } else { |
| 2164 | UINT32 ea = GetEA(modrm,1); |
| 2165 | UINT32 src = READ32(ea); |
| 2166 | UINT32 dst = LOAD_REG32(modrm); |
| 2167 | WRITE32(ea, dst); |
| 2168 | STORE_REG32(modrm, src); |
| 2169 | CYCLES(CYCLES_XCHG_REG_MEM); |
| 2170 | } |
| 2171 | } |
| 2172 | |
| 2173 | void i386_device::i386_xor_rm32_r32() // Opcode 0x31 |
| 2174 | { |
| 2175 | UINT32 src, dst; |
| 2176 | UINT8 modrm = FETCH(); |
| 2177 | if( modrm >= 0xc0 ) { |
| 2178 | src = LOAD_REG32(modrm); |
| 2179 | dst = LOAD_RM32(modrm); |
| 2180 | dst = XOR32(dst, src); |
| 2181 | STORE_RM32(modrm, dst); |
| 2182 | CYCLES(CYCLES_ALU_REG_REG); |
| 2183 | } else { |
| 2184 | UINT32 ea = GetEA(modrm,1); |
| 2185 | src = LOAD_REG32(modrm); |
| 2186 | dst = READ32(ea); |
| 2187 | dst = XOR32(dst, src); |
| 2188 | WRITE32(ea, dst); |
| 2189 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2190 | } |
| 2191 | } |
| 2192 | |
| 2193 | void i386_device::i386_xor_r32_rm32() // Opcode 0x33 |
| 2194 | { |
| 2195 | UINT32 src, dst; |
| 2196 | UINT8 modrm = FETCH(); |
| 2197 | if( modrm >= 0xc0 ) { |
| 2198 | src = LOAD_RM32(modrm); |
| 2199 | dst = LOAD_REG32(modrm); |
| 2200 | dst = XOR32(dst, src); |
| 2201 | STORE_REG32(modrm, dst); |
| 2202 | CYCLES(CYCLES_ALU_REG_REG); |
| 2203 | } else { |
| 2204 | UINT32 ea = GetEA(modrm,0); |
| 2205 | src = READ32(ea); |
| 2206 | dst = LOAD_REG32(modrm); |
| 2207 | dst = XOR32(dst, src); |
| 2208 | STORE_REG32(modrm, dst); |
| 2209 | CYCLES(CYCLES_ALU_MEM_REG); |
| 2210 | } |
| 2211 | } |
| 2212 | |
| 2213 | void i386_device::i386_xor_eax_i32() // Opcode 0x35 |
| 2214 | { |
| 2215 | UINT32 src, dst; |
| 2216 | src = FETCH32(); |
| 2217 | dst = REG32(EAX); |
| 2218 | dst = XOR32(dst, src); |
| 2219 | REG32(EAX) = dst; |
| 2220 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 2221 | } |
| 2222 | |
| 2223 | |
| 2224 | |
| 2225 | void i386_device::i386_group81_32() // Opcode 0x81 |
| 2226 | { |
| 2227 | UINT32 ea; |
| 2228 | UINT32 src, dst; |
| 2229 | UINT8 modrm = FETCH(); |
| 2230 | |
| 2231 | switch( (modrm >> 3) & 0x7 ) |
| 2232 | { |
| 2233 | case 0: // ADD Rm32, i32 |
| 2234 | if( modrm >= 0xc0 ) { |
| 2235 | dst = LOAD_RM32(modrm); |
| 2236 | src = FETCH32(); |
| 2237 | dst = ADD32(dst, src); |
| 2238 | STORE_RM32(modrm, dst); |
| 2239 | CYCLES(CYCLES_ALU_REG_REG); |
| 2240 | } else { |
| 2241 | ea = GetEA(modrm,1); |
| 2242 | dst = READ32(ea); |
| 2243 | src = FETCH32(); |
| 2244 | dst = ADD32(dst, src); |
| 2245 | WRITE32(ea, dst); |
| 2246 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2247 | } |
| 2248 | break; |
| 2249 | case 1: // OR Rm32, i32 |
| 2250 | if( modrm >= 0xc0 ) { |
| 2251 | dst = LOAD_RM32(modrm); |
| 2252 | src = FETCH32(); |
| 2253 | dst = OR32(dst, src); |
| 2254 | STORE_RM32(modrm, dst); |
| 2255 | CYCLES(CYCLES_ALU_REG_REG); |
| 2256 | } else { |
| 2257 | ea = GetEA(modrm,1); |
| 2258 | dst = READ32(ea); |
| 2259 | src = FETCH32(); |
| 2260 | dst = OR32(dst, src); |
| 2261 | WRITE32(ea, dst); |
| 2262 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2263 | } |
| 2264 | break; |
| 2265 | case 2: // ADC Rm32, i32 |
| 2266 | if( modrm >= 0xc0 ) { |
| 2267 | dst = LOAD_RM32(modrm); |
| 2268 | src = FETCH32(); |
| 2269 | dst = ADC32(dst, src, m_CF); |
| 2270 | STORE_RM32(modrm, dst); |
| 2271 | CYCLES(CYCLES_ALU_REG_REG); |
| 2272 | } else { |
| 2273 | ea = GetEA(modrm,1); |
| 2274 | dst = READ32(ea); |
| 2275 | src = FETCH32(); |
| 2276 | dst = ADC32(dst, src, m_CF); |
| 2277 | WRITE32(ea, dst); |
| 2278 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2279 | } |
| 2280 | break; |
| 2281 | case 3: // SBB Rm32, i32 |
| 2282 | if( modrm >= 0xc0 ) { |
| 2283 | dst = LOAD_RM32(modrm); |
| 2284 | src = FETCH32(); |
| 2285 | dst = SBB32(dst, src, m_CF); |
| 2286 | STORE_RM32(modrm, dst); |
| 2287 | CYCLES(CYCLES_ALU_REG_REG); |
| 2288 | } else { |
| 2289 | ea = GetEA(modrm,1); |
| 2290 | dst = READ32(ea); |
| 2291 | src = FETCH32(); |
| 2292 | dst = SBB32(dst, src, m_CF); |
| 2293 | WRITE32(ea, dst); |
| 2294 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2295 | } |
| 2296 | break; |
| 2297 | case 4: // AND Rm32, i32 |
| 2298 | if( modrm >= 0xc0 ) { |
| 2299 | dst = LOAD_RM32(modrm); |
| 2300 | src = FETCH32(); |
| 2301 | dst = AND32(dst, src); |
| 2302 | STORE_RM32(modrm, dst); |
| 2303 | CYCLES(CYCLES_ALU_REG_REG); |
| 2304 | } else { |
| 2305 | ea = GetEA(modrm,1); |
| 2306 | dst = READ32(ea); |
| 2307 | src = FETCH32(); |
| 2308 | dst = AND32(dst, src); |
| 2309 | WRITE32(ea, dst); |
| 2310 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2311 | } |
| 2312 | break; |
| 2313 | case 5: // SUB Rm32, i32 |
| 2314 | if( modrm >= 0xc0 ) { |
| 2315 | dst = LOAD_RM32(modrm); |
| 2316 | src = FETCH32(); |
| 2317 | dst = SUB32(dst, src); |
| 2318 | STORE_RM32(modrm, dst); |
| 2319 | CYCLES(CYCLES_ALU_REG_REG); |
| 2320 | } else { |
| 2321 | ea = GetEA(modrm,1); |
| 2322 | dst = READ32(ea); |
| 2323 | src = FETCH32(); |
| 2324 | dst = SUB32(dst, src); |
| 2325 | WRITE32(ea, dst); |
| 2326 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2327 | } |
| 2328 | break; |
| 2329 | case 6: // XOR Rm32, i32 |
| 2330 | if( modrm >= 0xc0 ) { |
| 2331 | dst = LOAD_RM32(modrm); |
| 2332 | src = FETCH32(); |
| 2333 | dst = XOR32(dst, src); |
| 2334 | STORE_RM32(modrm, dst); |
| 2335 | CYCLES(CYCLES_ALU_REG_REG); |
| 2336 | } else { |
| 2337 | ea = GetEA(modrm,1); |
| 2338 | dst = READ32(ea); |
| 2339 | src = FETCH32(); |
| 2340 | dst = XOR32(dst, src); |
| 2341 | WRITE32(ea, dst); |
| 2342 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2343 | } |
| 2344 | break; |
| 2345 | case 7: // CMP Rm32, i32 |
| 2346 | if( modrm >= 0xc0 ) { |
| 2347 | dst = LOAD_RM32(modrm); |
| 2348 | src = FETCH32(); |
| 2349 | SUB32(dst, src); |
| 2350 | CYCLES(CYCLES_CMP_REG_REG); |
| 2351 | } else { |
| 2352 | ea = GetEA(modrm,0); |
| 2353 | dst = READ32(ea); |
| 2354 | src = FETCH32(); |
| 2355 | SUB32(dst, src); |
| 2356 | CYCLES(CYCLES_CMP_REG_MEM); |
| 2357 | } |
| 2358 | break; |
| 2359 | } |
| 2360 | } |
| 2361 | |
| 2362 | void i386_device::i386_group83_32() // Opcode 0x83 |
| 2363 | { |
| 2364 | UINT32 ea; |
| 2365 | UINT32 src, dst; |
| 2366 | UINT8 modrm = FETCH(); |
| 2367 | |
| 2368 | switch( (modrm >> 3) & 0x7 ) |
| 2369 | { |
| 2370 | case 0: // ADD Rm32, i32 |
| 2371 | if( modrm >= 0xc0 ) { |
| 2372 | dst = LOAD_RM32(modrm); |
| 2373 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2374 | dst = ADD32(dst, src); |
| 2375 | STORE_RM32(modrm, dst); |
| 2376 | CYCLES(CYCLES_ALU_REG_REG); |
| 2377 | } else { |
| 2378 | ea = GetEA(modrm,1); |
| 2379 | dst = READ32(ea); |
| 2380 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2381 | dst = ADD32(dst, src); |
| 2382 | WRITE32(ea, dst); |
| 2383 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2384 | } |
| 2385 | break; |
| 2386 | case 1: // OR Rm32, i32 |
| 2387 | if( modrm >= 0xc0 ) { |
| 2388 | dst = LOAD_RM32(modrm); |
| 2389 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2390 | dst = OR32(dst, src); |
| 2391 | STORE_RM32(modrm, dst); |
| 2392 | CYCLES(CYCLES_ALU_REG_REG); |
| 2393 | } else { |
| 2394 | ea = GetEA(modrm,1); |
| 2395 | dst = READ32(ea); |
| 2396 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2397 | dst = OR32(dst, src); |
| 2398 | WRITE32(ea, dst); |
| 2399 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2400 | } |
| 2401 | break; |
| 2402 | case 2: // ADC Rm32, i32 |
| 2403 | if( modrm >= 0xc0 ) { |
| 2404 | dst = LOAD_RM32(modrm); |
| 2405 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2406 | dst = ADC32(dst, src, m_CF); |
| 2407 | STORE_RM32(modrm, dst); |
| 2408 | CYCLES(CYCLES_ALU_REG_REG); |
| 2409 | } else { |
| 2410 | ea = GetEA(modrm,1); |
| 2411 | dst = READ32(ea); |
| 2412 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2413 | dst = ADC32(dst, src, m_CF); |
| 2414 | WRITE32(ea, dst); |
| 2415 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2416 | } |
| 2417 | break; |
| 2418 | case 3: // SBB Rm32, i32 |
| 2419 | if( modrm >= 0xc0 ) { |
| 2420 | dst = LOAD_RM32(modrm); |
| 2421 | src = ((UINT32)(INT32)(INT8)FETCH()); |
| 2422 | dst = SBB32(dst, src, m_CF); |
| 2423 | STORE_RM32(modrm, dst); |
| 2424 | CYCLES(CYCLES_ALU_REG_REG); |
| 2425 | } else { |
| 2426 | ea = GetEA(modrm,1); |
| 2427 | dst = READ32(ea); |
| 2428 | src = ((UINT32)(INT32)(INT8)FETCH()); |
| 2429 | dst = SBB32(dst, src, m_CF); |
| 2430 | WRITE32(ea, dst); |
| 2431 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2432 | } |
| 2433 | break; |
| 2434 | case 4: // AND Rm32, i32 |
| 2435 | if( modrm >= 0xc0 ) { |
| 2436 | dst = LOAD_RM32(modrm); |
| 2437 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2438 | dst = AND32(dst, src); |
| 2439 | STORE_RM32(modrm, dst); |
| 2440 | CYCLES(CYCLES_ALU_REG_REG); |
| 2441 | } else { |
| 2442 | ea = GetEA(modrm,1); |
| 2443 | dst = READ32(ea); |
| 2444 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2445 | dst = AND32(dst, src); |
| 2446 | WRITE32(ea, dst); |
| 2447 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2448 | } |
| 2449 | break; |
| 2450 | case 5: // SUB Rm32, i32 |
| 2451 | if( modrm >= 0xc0 ) { |
| 2452 | dst = LOAD_RM32(modrm); |
| 2453 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2454 | dst = SUB32(dst, src); |
| 2455 | STORE_RM32(modrm, dst); |
| 2456 | CYCLES(CYCLES_ALU_REG_REG); |
| 2457 | } else { |
| 2458 | ea = GetEA(modrm,1); |
| 2459 | dst = READ32(ea); |
| 2460 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2461 | dst = SUB32(dst, src); |
| 2462 | WRITE32(ea, dst); |
| 2463 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2464 | } |
| 2465 | break; |
| 2466 | case 6: // XOR Rm32, i32 |
| 2467 | if( modrm >= 0xc0 ) { |
| 2468 | dst = LOAD_RM32(modrm); |
| 2469 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2470 | dst = XOR32(dst, src); |
| 2471 | STORE_RM32(modrm, dst); |
| 2472 | CYCLES(CYCLES_ALU_REG_REG); |
| 2473 | } else { |
| 2474 | ea = GetEA(modrm,1); |
| 2475 | dst = READ32(ea); |
| 2476 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2477 | dst = XOR32(dst, src); |
| 2478 | WRITE32(ea, dst); |
| 2479 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2480 | } |
| 2481 | break; |
| 2482 | case 7: // CMP Rm32, i32 |
| 2483 | if( modrm >= 0xc0 ) { |
| 2484 | dst = LOAD_RM32(modrm); |
| 2485 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2486 | SUB32(dst, src); |
| 2487 | CYCLES(CYCLES_CMP_REG_REG); |
| 2488 | } else { |
| 2489 | ea = GetEA(modrm,0); |
| 2490 | dst = READ32(ea); |
| 2491 | src = (UINT32)(INT32)(INT8)FETCH(); |
| 2492 | SUB32(dst, src); |
| 2493 | CYCLES(CYCLES_CMP_REG_MEM); |
| 2494 | } |
| 2495 | break; |
| 2496 | } |
| 2497 | } |
| 2498 | |
| 2499 | void i386_device::i386_groupC1_32() // Opcode 0xc1 |
| 2500 | { |
| 2501 | UINT32 dst; |
| 2502 | UINT8 modrm = FETCH(); |
| 2503 | UINT8 shift; |
| 2504 | |
| 2505 | if( modrm >= 0xc0 ) { |
| 2506 | dst = LOAD_RM32(modrm); |
| 2507 | shift = FETCH() & 0x1f; |
| 2508 | dst = i386_shift_rotate32(modrm, dst, shift); |
| 2509 | STORE_RM32(modrm, dst); |
| 2510 | } else { |
| 2511 | UINT32 ea = GetEA(modrm,1); |
| 2512 | dst = READ32(ea); |
| 2513 | shift = FETCH() & 0x1f; |
| 2514 | dst = i386_shift_rotate32(modrm, dst, shift); |
| 2515 | WRITE32(ea, dst); |
| 2516 | } |
| 2517 | } |
| 2518 | |
| 2519 | void i386_device::i386_groupD1_32() // Opcode 0xd1 |
| 2520 | { |
| 2521 | UINT32 dst; |
| 2522 | UINT8 modrm = FETCH(); |
| 2523 | |
| 2524 | if( modrm >= 0xc0 ) { |
| 2525 | dst = LOAD_RM32(modrm); |
| 2526 | dst = i386_shift_rotate32(modrm, dst, 1); |
| 2527 | STORE_RM32(modrm, dst); |
| 2528 | } else { |
| 2529 | UINT32 ea = GetEA(modrm,1); |
| 2530 | dst = READ32(ea); |
| 2531 | dst = i386_shift_rotate32(modrm, dst, 1); |
| 2532 | WRITE32(ea, dst); |
| 2533 | } |
| 2534 | } |
| 2535 | |
| 2536 | void i386_device::i386_groupD3_32() // Opcode 0xd3 |
| 2537 | { |
| 2538 | UINT32 dst; |
| 2539 | UINT8 modrm = FETCH(); |
| 2540 | |
| 2541 | if( modrm >= 0xc0 ) { |
| 2542 | dst = LOAD_RM32(modrm); |
| 2543 | dst = i386_shift_rotate32(modrm, dst, REG8(CL)); |
| 2544 | STORE_RM32(modrm, dst); |
| 2545 | } else { |
| 2546 | UINT32 ea = GetEA(modrm,1); |
| 2547 | dst = READ32(ea); |
| 2548 | dst = i386_shift_rotate32(modrm, dst, REG8(CL)); |
| 2549 | WRITE32(ea, dst); |
| 2550 | } |
| 2551 | } |
| 2552 | |
| 2553 | void i386_device::i386_groupF7_32() // Opcode 0xf7 |
| 2554 | { |
| 2555 | UINT8 modrm = FETCH(); |
| 2556 | |
| 2557 | switch( (modrm >> 3) & 0x7 ) |
| 2558 | { |
| 2559 | case 0: /* TEST Rm32, i32 */ |
| 2560 | if( modrm >= 0xc0 ) { |
| 2561 | UINT32 dst = LOAD_RM32(modrm); |
| 2562 | UINT32 src = FETCH32(); |
| 2563 | dst &= src; |
| 2564 | m_CF = m_OF = m_AF = 0; |
| 2565 | SetSZPF32(dst); |
| 2566 | CYCLES(CYCLES_TEST_IMM_REG); |
| 2567 | } else { |
| 2568 | UINT32 ea = GetEA(modrm,0); |
| 2569 | UINT32 dst = READ32(ea); |
| 2570 | UINT32 src = FETCH32(); |
| 2571 | dst &= src; |
| 2572 | m_CF = m_OF = m_AF = 0; |
| 2573 | SetSZPF32(dst); |
| 2574 | CYCLES(CYCLES_TEST_IMM_MEM); |
| 2575 | } |
| 2576 | break; |
| 2577 | case 2: /* NOT Rm32 */ |
| 2578 | if( modrm >= 0xc0 ) { |
| 2579 | UINT32 dst = LOAD_RM32(modrm); |
| 2580 | dst = ~dst; |
| 2581 | STORE_RM32(modrm, dst); |
| 2582 | CYCLES(CYCLES_NOT_REG); |
| 2583 | } else { |
| 2584 | UINT32 ea = GetEA(modrm,1); |
| 2585 | UINT32 dst = READ32(ea); |
| 2586 | dst = ~dst; |
| 2587 | WRITE32(ea, dst); |
| 2588 | CYCLES(CYCLES_NOT_MEM); |
| 2589 | } |
| 2590 | break; |
| 2591 | case 3: /* NEG Rm32 */ |
| 2592 | if( modrm >= 0xc0 ) { |
| 2593 | UINT32 dst = LOAD_RM32(modrm); |
| 2594 | dst = SUB32(0, dst ); |
| 2595 | STORE_RM32(modrm, dst); |
| 2596 | CYCLES(CYCLES_NEG_REG); |
| 2597 | } else { |
| 2598 | UINT32 ea = GetEA(modrm,1); |
| 2599 | UINT32 dst = READ32(ea); |
| 2600 | dst = SUB32(0, dst ); |
| 2601 | WRITE32(ea, dst); |
| 2602 | CYCLES(CYCLES_NEG_MEM); |
| 2603 | } |
| 2604 | break; |
| 2605 | case 4: /* MUL EAX, Rm32 */ |
| 2606 | { |
| 2607 | UINT64 result; |
| 2608 | UINT32 src, dst; |
| 2609 | if( modrm >= 0xc0 ) { |
| 2610 | src = LOAD_RM32(modrm); |
| 2611 | CYCLES(CYCLES_MUL32_ACC_REG); /* TODO: Correct multiply timing */ |
| 2612 | } else { |
| 2613 | UINT32 ea = GetEA(modrm,0); |
| 2614 | src = READ32(ea); |
| 2615 | CYCLES(CYCLES_MUL32_ACC_MEM); /* TODO: Correct multiply timing */ |
| 2616 | } |
| 2617 | |
| 2618 | dst = REG32(EAX); |
| 2619 | result = (UINT64)src * (UINT64)dst; |
| 2620 | REG32(EDX) = (UINT32)(result >> 32); |
| 2621 | REG32(EAX) = (UINT32)result; |
| 2622 | |
| 2623 | m_CF = m_OF = (REG32(EDX) != 0); |
| 2624 | } |
| 2625 | break; |
| 2626 | case 5: /* IMUL EAX, Rm32 */ |
| 2627 | { |
| 2628 | INT64 result; |
| 2629 | INT64 src, dst; |
| 2630 | if( modrm >= 0xc0 ) { |
| 2631 | src = (INT64)(INT32)LOAD_RM32(modrm); |
| 2632 | CYCLES(CYCLES_IMUL32_ACC_REG); /* TODO: Correct multiply timing */ |
| 2633 | } else { |
| 2634 | UINT32 ea = GetEA(modrm,0); |
| 2635 | src = (INT64)(INT32)READ32(ea); |
| 2636 | CYCLES(CYCLES_IMUL32_ACC_MEM); /* TODO: Correct multiply timing */ |
| 2637 | } |
| 2638 | |
| 2639 | dst = (INT64)(INT32)REG32(EAX); |
| 2640 | result = src * dst; |
| 2641 | |
| 2642 | REG32(EDX) = (UINT32)(result >> 32); |
| 2643 | REG32(EAX) = (UINT32)result; |
| 2644 | |
| 2645 | m_CF = m_OF = !(result == (INT64)(INT32)result); |
| 2646 | } |
| 2647 | break; |
| 2648 | case 6: /* DIV EAX, Rm32 */ |
| 2649 | { |
| 2650 | UINT64 quotient, remainder, result; |
| 2651 | UINT32 src; |
| 2652 | if( modrm >= 0xc0 ) { |
| 2653 | src = LOAD_RM32(modrm); |
| 2654 | CYCLES(CYCLES_DIV32_ACC_REG); |
| 2655 | } else { |
| 2656 | UINT32 ea = GetEA(modrm,0); |
| 2657 | src = READ32(ea); |
| 2658 | CYCLES(CYCLES_DIV32_ACC_MEM); |
| 2659 | } |
| 2660 | |
| 2661 | quotient = ((UINT64)(REG32(EDX)) << 32) | (UINT64)(REG32(EAX)); |
| 2662 | if( src ) { |
| 2663 | remainder = quotient % (UINT64)src; |
| 2664 | result = quotient / (UINT64)src; |
| 2665 | if( result > 0xffffffff ) { |
| 2666 | /* TODO: Divide error */ |
| 2667 | } else { |
| 2668 | REG32(EDX) = (UINT32)remainder; |
| 2669 | REG32(EAX) = (UINT32)result; |
| 2670 | } |
| 2671 | } else { |
| 2672 | i386_trap(0, 0, 0); |
| 2673 | } |
| 2674 | } |
| 2675 | break; |
| 2676 | case 7: /* IDIV EAX, Rm32 */ |
| 2677 | { |
| 2678 | INT64 quotient, remainder, result; |
| 2679 | UINT32 src; |
| 2680 | if( modrm >= 0xc0 ) { |
| 2681 | src = LOAD_RM32(modrm); |
| 2682 | CYCLES(CYCLES_IDIV32_ACC_REG); |
| 2683 | } else { |
| 2684 | UINT32 ea = GetEA(modrm,0); |
| 2685 | src = READ32(ea); |
| 2686 | CYCLES(CYCLES_IDIV32_ACC_MEM); |
| 2687 | } |
| 2688 | |
| 2689 | quotient = (((INT64)REG32(EDX)) << 32) | ((UINT64)REG32(EAX)); |
| 2690 | if( src ) { |
| 2691 | remainder = quotient % (INT64)(INT32)src; |
| 2692 | result = quotient / (INT64)(INT32)src; |
| 2693 | if( result > 0xffffffff ) { |
| 2694 | /* TODO: Divide error */ |
| 2695 | } else { |
| 2696 | REG32(EDX) = (UINT32)remainder; |
| 2697 | REG32(EAX) = (UINT32)result; |
| 2698 | } |
| 2699 | } else { |
| 2700 | i386_trap(0, 0, 0); |
| 2701 | } |
| 2702 | } |
| 2703 | break; |
| 2704 | } |
| 2705 | } |
| 2706 | |
| 2707 | void i386_device::i386_groupFF_32() // Opcode 0xff |
| 2708 | { |
| 2709 | UINT8 modrm = FETCH(); |
| 2710 | |
| 2711 | switch( (modrm >> 3) & 0x7 ) |
| 2712 | { |
| 2713 | case 0: /* INC Rm32 */ |
| 2714 | if( modrm >= 0xc0 ) { |
| 2715 | UINT32 dst = LOAD_RM32(modrm); |
| 2716 | dst = INC32(dst); |
| 2717 | STORE_RM32(modrm, dst); |
| 2718 | CYCLES(CYCLES_INC_REG); |
| 2719 | } else { |
| 2720 | UINT32 ea = GetEA(modrm,1); |
| 2721 | UINT32 dst = READ32(ea); |
| 2722 | dst = INC32(dst); |
| 2723 | WRITE32(ea, dst); |
| 2724 | CYCLES(CYCLES_INC_MEM); |
| 2725 | } |
| 2726 | break; |
| 2727 | case 1: /* DEC Rm32 */ |
| 2728 | if( modrm >= 0xc0 ) { |
| 2729 | UINT32 dst = LOAD_RM32(modrm); |
| 2730 | dst = DEC32(dst); |
| 2731 | STORE_RM32(modrm, dst); |
| 2732 | CYCLES(CYCLES_DEC_REG); |
| 2733 | } else { |
| 2734 | UINT32 ea = GetEA(modrm,1); |
| 2735 | UINT32 dst = READ32(ea); |
| 2736 | dst = DEC32(dst); |
| 2737 | WRITE32(ea, dst); |
| 2738 | CYCLES(CYCLES_DEC_MEM); |
| 2739 | } |
| 2740 | break; |
| 2741 | case 2: /* CALL Rm32 */ |
| 2742 | { |
| 2743 | UINT32 address; |
| 2744 | if( modrm >= 0xc0 ) { |
| 2745 | address = LOAD_RM32(modrm); |
| 2746 | CYCLES(CYCLES_CALL_REG); /* TODO: Timing = 7 + m */ |
| 2747 | } else { |
| 2748 | UINT32 ea = GetEA(modrm,0); |
| 2749 | address = READ32(ea); |
| 2750 | CYCLES(CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */ |
| 2751 | } |
| 2752 | PUSH32(m_eip ); |
| 2753 | m_eip = address; |
| 2754 | CHANGE_PC(m_eip); |
| 2755 | } |
| 2756 | break; |
| 2757 | case 3: /* CALL FAR Rm32 */ |
| 2758 | { |
| 2759 | UINT16 selector; |
| 2760 | UINT32 address; |
| 2761 | |
| 2762 | if( modrm >= 0xc0 ) |
| 2763 | { |
| 2764 | report_invalid_modrm("groupFF_32", modrm); |
| 2765 | } |
| 2766 | else |
| 2767 | { |
| 2768 | UINT32 ea = GetEA(modrm,0); |
| 2769 | address = READ32(ea + 0); |
| 2770 | selector = READ16(ea + 4); |
| 2771 | CYCLES(CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */ |
| 2772 | if(PROTECTED_MODE && !V8086_MODE) |
| 2773 | { |
| 2774 | i386_protected_mode_call(selector,address,1,1); |
| 2775 | } |
| 2776 | else |
| 2777 | { |
| 2778 | PUSH32(m_sreg[CS].selector ); |
| 2779 | PUSH32(m_eip ); |
| 2780 | m_sreg[CS].selector = selector; |
| 2781 | m_performed_intersegment_jump = 1; |
| 2782 | i386_load_segment_descriptor(CS ); |
| 2783 | m_eip = address; |
| 2784 | CHANGE_PC(m_eip); |
| 2785 | } |
| 2786 | } |
| 2787 | } |
| 2788 | break; |
| 2789 | case 4: /* JMP Rm32 */ |
| 2790 | { |
| 2791 | UINT32 address; |
| 2792 | if( modrm >= 0xc0 ) { |
| 2793 | address = LOAD_RM32(modrm); |
| 2794 | CYCLES(CYCLES_JMP_REG); /* TODO: Timing = 7 + m */ |
| 2795 | } else { |
| 2796 | UINT32 ea = GetEA(modrm,0); |
| 2797 | address = READ32(ea); |
| 2798 | CYCLES(CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */ |
| 2799 | } |
| 2800 | m_eip = address; |
| 2801 | CHANGE_PC(m_eip); |
| 2802 | } |
| 2803 | break; |
| 2804 | case 5: /* JMP FAR Rm32 */ |
| 2805 | { |
| 2806 | UINT16 selector; |
| 2807 | UINT32 address; |
| 2808 | |
| 2809 | if( modrm >= 0xc0 ) |
| 2810 | { |
| 2811 | report_invalid_modrm("groupFF_32", modrm); |
| 2812 | } |
| 2813 | else |
| 2814 | { |
| 2815 | UINT32 ea = GetEA(modrm,0); |
| 2816 | address = READ32(ea + 0); |
| 2817 | selector = READ16(ea + 4); |
| 2818 | CYCLES(CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */ |
| 2819 | if(PROTECTED_MODE && !V8086_MODE) |
| 2820 | { |
| 2821 | i386_protected_mode_jump(selector,address,1,1); |
| 2822 | } |
| 2823 | else |
| 2824 | { |
| 2825 | m_sreg[CS].selector = selector; |
| 2826 | m_performed_intersegment_jump = 1; |
| 2827 | i386_load_segment_descriptor(CS ); |
| 2828 | m_eip = address; |
| 2829 | CHANGE_PC(m_eip); |
| 2830 | } |
| 2831 | } |
| 2832 | } |
| 2833 | break; |
| 2834 | case 6: /* PUSH Rm32 */ |
| 2835 | { |
| 2836 | UINT32 value; |
| 2837 | if( modrm >= 0xc0 ) { |
| 2838 | value = LOAD_RM32(modrm); |
| 2839 | } else { |
| 2840 | UINT32 ea = GetEA(modrm,0); |
| 2841 | value = READ32(ea); |
| 2842 | } |
| 2843 | PUSH32(value); |
| 2844 | CYCLES(CYCLES_PUSH_RM); |
| 2845 | } |
| 2846 | break; |
| 2847 | default: |
| 2848 | report_invalid_modrm("groupFF_32", modrm); |
| 2849 | break; |
| 2850 | } |
| 2851 | } |
| 2852 | |
| 2853 | void i386_device::i386_group0F00_32() // Opcode 0x0f 00 |
| 2854 | { |
| 2855 | UINT32 address, ea; |
| 2856 | UINT8 modrm = FETCH(); |
| 2857 | I386_SREG seg; |
| 2858 | UINT8 result; |
| 2859 | |
| 2860 | switch( (modrm >> 3) & 0x7 ) |
| 2861 | { |
| 2862 | case 0: /* SLDT */ |
| 2863 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 2864 | { |
| 2865 | if( modrm >= 0xc0 ) { |
| 2866 | STORE_RM32(modrm, m_ldtr.segment); |
| 2867 | CYCLES(CYCLES_SLDT_REG); |
| 2868 | } else { |
| 2869 | ea = GetEA(modrm,1); |
| 2870 | WRITE16(ea, m_ldtr.segment); |
| 2871 | CYCLES(CYCLES_SLDT_MEM); |
| 2872 | } |
| 2873 | } |
| 2874 | else |
| 2875 | { |
| 2876 | i386_trap(6, 0, 0); |
| 2877 | } |
| 2878 | break; |
| 2879 | case 1: /* STR */ |
| 2880 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 2881 | { |
| 2882 | if( modrm >= 0xc0 ) { |
| 2883 | STORE_RM32(modrm, m_task.segment); |
| 2884 | CYCLES(CYCLES_STR_REG); |
| 2885 | } else { |
| 2886 | ea = GetEA(modrm,1); |
| 2887 | WRITE16(ea, m_task.segment); |
| 2888 | CYCLES(CYCLES_STR_MEM); |
| 2889 | } |
| 2890 | } |
| 2891 | else |
| 2892 | { |
| 2893 | i386_trap(6, 0, 0); |
| 2894 | } |
| 2895 | break; |
| 2896 | case 2: /* LLDT */ |
| 2897 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 2898 | { |
| 2899 | if(m_CPL) |
| 2900 | FAULT(FAULT_GP,0) |
| 2901 | if( modrm >= 0xc0 ) { |
| 2902 | address = LOAD_RM32(modrm); |
| 2903 | m_ldtr.segment = address; |
| 2904 | CYCLES(CYCLES_LLDT_REG); |
| 2905 | } else { |
| 2906 | ea = GetEA(modrm,0); |
| 2907 | m_ldtr.segment = READ32(ea); |
| 2908 | CYCLES(CYCLES_LLDT_MEM); |
| 2909 | } |
| 2910 | memset(&seg, 0, sizeof(seg)); |
| 2911 | seg.selector = m_ldtr.segment; |
| 2912 | i386_load_protected_mode_segment(&seg,NULL); |
| 2913 | m_ldtr.limit = seg.limit; |
| 2914 | m_ldtr.base = seg.base; |
| 2915 | m_ldtr.flags = seg.flags; |
| 2916 | } |
| 2917 | else |
| 2918 | { |
| 2919 | i386_trap(6, 0, 0); |
| 2920 | } |
| 2921 | break; |
| 2922 | |
| 2923 | case 3: /* LTR */ |
| 2924 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 2925 | { |
| 2926 | if(m_CPL) |
| 2927 | FAULT(FAULT_GP,0) |
| 2928 | if( modrm >= 0xc0 ) { |
| 2929 | address = LOAD_RM32(modrm); |
| 2930 | m_task.segment = address; |
| 2931 | CYCLES(CYCLES_LTR_REG); |
| 2932 | } else { |
| 2933 | ea = GetEA(modrm,0); |
| 2934 | m_task.segment = READ32(ea); |
| 2935 | CYCLES(CYCLES_LTR_MEM); |
| 2936 | } |
| 2937 | memset(&seg, 0, sizeof(seg)); |
| 2938 | seg.selector = m_task.segment; |
| 2939 | i386_load_protected_mode_segment(&seg,NULL); |
| 2940 | m_task.limit = seg.limit; |
| 2941 | m_task.base = seg.base; |
| 2942 | m_task.flags = seg.flags; |
| 2943 | } |
| 2944 | else |
| 2945 | { |
| 2946 | i386_trap(6, 0, 0); |
| 2947 | } |
| 2948 | break; |
| 2949 | |
| 2950 | case 4: /* VERR */ |
| 2951 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 2952 | { |
| 2953 | if( modrm >= 0xc0 ) { |
| 2954 | address = LOAD_RM32(modrm); |
| 2955 | CYCLES(CYCLES_VERR_REG); |
| 2956 | } else { |
| 2957 | ea = GetEA(modrm,0); |
| 2958 | address = READ32(ea); |
| 2959 | CYCLES(CYCLES_VERR_MEM); |
| 2960 | } |
| 2961 | memset(&seg, 0, sizeof(seg)); |
| 2962 | seg.selector = address; |
| 2963 | result = i386_load_protected_mode_segment(&seg,NULL); |
| 2964 | // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) |
| 2965 | if(!(seg.flags & 0x10)) |
| 2966 | result = 0; |
| 2967 | // check that the segment is readable |
| 2968 | if(seg.flags & 0x10) // is code or data segment |
| 2969 | { |
| 2970 | if(seg.flags & 0x08) // is code segment, so check if it's readable |
| 2971 | { |
| 2972 | if(!(seg.flags & 0x02)) |
| 2973 | { |
| 2974 | result = 0; |
| 2975 | } |
| 2976 | else |
| 2977 | { // check if conforming, these are always readable, regardless of privilege |
| 2978 | if(!(seg.flags & 0x04)) |
| 2979 | { |
| 2980 | // if not conforming, then we must check privilege levels (TODO: current privilege level check) |
| 2981 | if(((seg.flags >> 5) & 0x03) < (address & 0x03)) |
| 2982 | result = 0; |
| 2983 | } |
| 2984 | } |
| 2985 | } |
| 2986 | } |
| 2987 | // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO) |
| 2988 | SetZF(result); |
| 2989 | } |
| 2990 | else |
| 2991 | { |
| 2992 | i386_trap(6, 0, 0); |
| 2993 | logerror("i386: VERR: Exception - Running in real mode or virtual 8086 mode.\n"); |
| 2994 | } |
| 2995 | break; |
| 2996 | |
| 2997 | case 5: /* VERW */ |
| 2998 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 2999 | { |
| 3000 | if( modrm >= 0xc0 ) { |
| 3001 | address = LOAD_RM16(modrm); |
| 3002 | CYCLES(CYCLES_VERW_REG); |
| 3003 | } else { |
| 3004 | ea = GetEA(modrm,0); |
| 3005 | address = READ16(ea); |
| 3006 | CYCLES(CYCLES_VERW_MEM); |
| 3007 | } |
| 3008 | memset(&seg, 0, sizeof(seg)); |
| 3009 | seg.selector = address; |
| 3010 | result = i386_load_protected_mode_segment(&seg,NULL); |
| 3011 | // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) |
| 3012 | if(!(seg.flags & 0x10)) |
| 3013 | result = 0; |
| 3014 | // check that the segment is writable |
| 3015 | if(seg.flags & 0x10) // is code or data segment |
| 3016 | { |
| 3017 | if(seg.flags & 0x08) // is code segment (and thus, not writable) |
| 3018 | { |
| 3019 | result = 0; |
| 3020 | } |
| 3021 | else |
| 3022 | { // is data segment |
| 3023 | if(!(seg.flags & 0x02)) |
| 3024 | result = 0; |
| 3025 | } |
| 3026 | } |
| 3027 | // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO) |
| 3028 | if(((seg.flags >> 5) & 0x03) < (address & 0x03)) |
| 3029 | result = 0; |
| 3030 | SetZF(result); |
| 3031 | } |
| 3032 | else |
| 3033 | { |
| 3034 | i386_trap(6, 0, 0); |
| 3035 | logerror("i386: VERW: Exception - Running in real mode or virtual 8086 mode.\n"); |
| 3036 | } |
| 3037 | break; |
| 3038 | |
| 3039 | default: |
| 3040 | report_invalid_modrm("group0F00_32", modrm); |
| 3041 | break; |
| 3042 | } |
| 3043 | } |
| 3044 | |
| 3045 | void i386_device::i386_group0F01_32() // Opcode 0x0f 01 |
| 3046 | { |
| 3047 | UINT8 modrm = FETCH(); |
| 3048 | UINT32 address, ea; |
| 3049 | |
| 3050 | switch( (modrm >> 3) & 0x7 ) |
| 3051 | { |
| 3052 | case 0: /* SGDT */ |
| 3053 | { |
| 3054 | if( modrm >= 0xc0 ) { |
| 3055 | address = LOAD_RM32(modrm); |
| 3056 | ea = i386_translate(CS, address, 1 ); |
| 3057 | } else { |
| 3058 | ea = GetEA(modrm,1); |
| 3059 | } |
| 3060 | WRITE16(ea, m_gdtr.limit); |
| 3061 | WRITE32(ea + 2, m_gdtr.base); |
| 3062 | CYCLES(CYCLES_SGDT); |
| 3063 | break; |
| 3064 | } |
| 3065 | case 1: /* SIDT */ |
| 3066 | { |
| 3067 | if (modrm >= 0xc0) |
| 3068 | { |
| 3069 | address = LOAD_RM32(modrm); |
| 3070 | ea = i386_translate(CS, address, 1 ); |
| 3071 | } |
| 3072 | else |
| 3073 | { |
| 3074 | ea = GetEA(modrm,1); |
| 3075 | } |
| 3076 | WRITE16(ea, m_idtr.limit); |
| 3077 | WRITE32(ea + 2, m_idtr.base); |
| 3078 | CYCLES(CYCLES_SIDT); |
| 3079 | break; |
| 3080 | } |
| 3081 | case 2: /* LGDT */ |
| 3082 | { |
| 3083 | if(PROTECTED_MODE && m_CPL) |
| 3084 | FAULT(FAULT_GP,0) |
| 3085 | if( modrm >= 0xc0 ) { |
| 3086 | address = LOAD_RM32(modrm); |
| 3087 | ea = i386_translate(CS, address, 0 ); |
| 3088 | } else { |
| 3089 | ea = GetEA(modrm,0); |
| 3090 | } |
| 3091 | m_gdtr.limit = READ16(ea); |
| 3092 | m_gdtr.base = READ32(ea + 2); |
| 3093 | CYCLES(CYCLES_LGDT); |
| 3094 | break; |
| 3095 | } |
| 3096 | case 3: /* LIDT */ |
| 3097 | { |
| 3098 | if(PROTECTED_MODE && m_CPL) |
| 3099 | FAULT(FAULT_GP,0) |
| 3100 | if( modrm >= 0xc0 ) { |
| 3101 | address = LOAD_RM32(modrm); |
| 3102 | ea = i386_translate(CS, address, 0 ); |
| 3103 | } else { |
| 3104 | ea = GetEA(modrm,0); |
| 3105 | } |
| 3106 | m_idtr.limit = READ16(ea); |
| 3107 | m_idtr.base = READ32(ea + 2); |
| 3108 | CYCLES(CYCLES_LIDT); |
| 3109 | break; |
| 3110 | } |
| 3111 | case 4: /* SMSW */ |
| 3112 | { |
| 3113 | if( modrm >= 0xc0 ) { |
| 3114 | // smsw stores all of cr0 into register |
| 3115 | STORE_RM32(modrm, m_cr[0]); |
| 3116 | CYCLES(CYCLES_SMSW_REG); |
| 3117 | } else { |
| 3118 | /* always 16-bit memory operand */ |
| 3119 | ea = GetEA(modrm,1); |
| 3120 | WRITE16(ea, m_cr[0]); |
| 3121 | CYCLES(CYCLES_SMSW_MEM); |
| 3122 | } |
| 3123 | break; |
| 3124 | } |
| 3125 | case 6: /* LMSW */ |
| 3126 | { |
| 3127 | if(PROTECTED_MODE && m_CPL) |
| 3128 | FAULT(FAULT_GP,0) |
| 3129 | UINT16 b; |
| 3130 | if( modrm >= 0xc0 ) { |
| 3131 | b = LOAD_RM16(modrm); |
| 3132 | CYCLES(CYCLES_LMSW_REG); |
| 3133 | } else { |
| 3134 | ea = GetEA(modrm,0); |
| 3135 | CYCLES(CYCLES_LMSW_MEM); |
| 3136 | b = READ16(ea); |
| 3137 | } |
| 3138 | if(PROTECTED_MODE) |
| 3139 | b |= 0x0001; // cannot return to real mode using this instruction. |
| 3140 | m_cr[0] &= ~0x0000000f; |
| 3141 | m_cr[0] |= b & 0x0000000f; |
| 3142 | break; |
| 3143 | } |
| 3144 | default: |
| 3145 | report_invalid_modrm("group0F01_32", modrm); |
| 3146 | break; |
| 3147 | } |
| 3148 | } |
| 3149 | |
| 3150 | void i386_device::i386_group0FBA_32() // Opcode 0x0f ba |
| 3151 | { |
| 3152 | UINT8 modrm = FETCH(); |
| 3153 | |
| 3154 | switch( (modrm >> 3) & 0x7 ) |
| 3155 | { |
| 3156 | case 4: /* BT Rm32, i8 */ |
| 3157 | if( modrm >= 0xc0 ) { |
| 3158 | UINT32 dst = LOAD_RM32(modrm); |
| 3159 | UINT8 bit = FETCH(); |
| 3160 | |
| 3161 | if( dst & (1 << bit) ) |
| 3162 | m_CF = 1; |
| 3163 | else |
| 3164 | m_CF = 0; |
| 3165 | |
| 3166 | CYCLES(CYCLES_BT_IMM_REG); |
| 3167 | } else { |
| 3168 | UINT32 ea = GetEA(modrm,0); |
| 3169 | UINT32 dst = READ32(ea); |
| 3170 | UINT8 bit = FETCH(); |
| 3171 | |
| 3172 | if( dst & (1 << bit) ) |
| 3173 | m_CF = 1; |
| 3174 | else |
| 3175 | m_CF = 0; |
| 3176 | |
| 3177 | CYCLES(CYCLES_BT_IMM_MEM); |
| 3178 | } |
| 3179 | break; |
| 3180 | case 5: /* BTS Rm32, i8 */ |
| 3181 | if( modrm >= 0xc0 ) { |
| 3182 | UINT32 dst = LOAD_RM32(modrm); |
| 3183 | UINT8 bit = FETCH(); |
| 3184 | |
| 3185 | if( dst & (1 << bit) ) |
| 3186 | m_CF = 1; |
| 3187 | else |
| 3188 | m_CF = 0; |
| 3189 | dst |= (1 << bit); |
| 3190 | |
| 3191 | STORE_RM32(modrm, dst); |
| 3192 | CYCLES(CYCLES_BTS_IMM_REG); |
| 3193 | } else { |
| 3194 | UINT32 ea = GetEA(modrm,1); |
| 3195 | UINT32 dst = READ32(ea); |
| 3196 | UINT8 bit = FETCH(); |
| 3197 | |
| 3198 | if( dst & (1 << bit) ) |
| 3199 | m_CF = 1; |
| 3200 | else |
| 3201 | m_CF = 0; |
| 3202 | dst |= (1 << bit); |
| 3203 | |
| 3204 | WRITE32(ea, dst); |
| 3205 | CYCLES(CYCLES_BTS_IMM_MEM); |
| 3206 | } |
| 3207 | break; |
| 3208 | case 6: /* BTR Rm32, i8 */ |
| 3209 | if( modrm >= 0xc0 ) { |
| 3210 | UINT32 dst = LOAD_RM32(modrm); |
| 3211 | UINT8 bit = FETCH(); |
| 3212 | |
| 3213 | if( dst & (1 << bit) ) |
| 3214 | m_CF = 1; |
| 3215 | else |
| 3216 | m_CF = 0; |
| 3217 | dst &= ~(1 << bit); |
| 3218 | |
| 3219 | STORE_RM32(modrm, dst); |
| 3220 | CYCLES(CYCLES_BTR_IMM_REG); |
| 3221 | } else { |
| 3222 | UINT32 ea = GetEA(modrm,1); |
| 3223 | UINT32 dst = READ32(ea); |
| 3224 | UINT8 bit = FETCH(); |
| 3225 | |
| 3226 | if( dst & (1 << bit) ) |
| 3227 | m_CF = 1; |
| 3228 | else |
| 3229 | m_CF = 0; |
| 3230 | dst &= ~(1 << bit); |
| 3231 | |
| 3232 | WRITE32(ea, dst); |
| 3233 | CYCLES(CYCLES_BTR_IMM_MEM); |
| 3234 | } |
| 3235 | break; |
| 3236 | case 7: /* BTC Rm32, i8 */ |
| 3237 | if( modrm >= 0xc0 ) { |
| 3238 | UINT32 dst = LOAD_RM32(modrm); |
| 3239 | UINT8 bit = FETCH(); |
| 3240 | |
| 3241 | if( dst & (1 << bit) ) |
| 3242 | m_CF = 1; |
| 3243 | else |
| 3244 | m_CF = 0; |
| 3245 | dst ^= (1 << bit); |
| 3246 | |
| 3247 | STORE_RM32(modrm, dst); |
| 3248 | CYCLES(CYCLES_BTC_IMM_REG); |
| 3249 | } else { |
| 3250 | UINT32 ea = GetEA(modrm,1); |
| 3251 | UINT32 dst = READ32(ea); |
| 3252 | UINT8 bit = FETCH(); |
| 3253 | |
| 3254 | if( dst & (1 << bit) ) |
| 3255 | m_CF = 1; |
| 3256 | else |
| 3257 | m_CF = 0; |
| 3258 | dst ^= (1 << bit); |
| 3259 | |
| 3260 | WRITE32(ea, dst); |
| 3261 | CYCLES(CYCLES_BTC_IMM_MEM); |
| 3262 | } |
| 3263 | break; |
| 3264 | default: |
| 3265 | report_invalid_modrm("group0FBA_32", modrm); |
| 3266 | break; |
| 3267 | } |
| 3268 | } |
| 3269 | |
| 3270 | void i386_device::i386_lar_r32_rm32() // Opcode 0x0f 0x02 |
| 3271 | { |
| 3272 | UINT8 modrm = FETCH(); |
| 3273 | I386_SREG seg; |
| 3274 | UINT8 type; |
| 3275 | |
| 3276 | if(PROTECTED_MODE && !V8086_MODE) |
| 3277 | { |
| 3278 | memset(&seg,0,sizeof(seg)); |
| 3279 | if(modrm >= 0xc0) |
| 3280 | { |
| 3281 | seg.selector = LOAD_RM32(modrm); |
| 3282 | CYCLES(CYCLES_LAR_REG); |
| 3283 | } |
| 3284 | else |
| 3285 | { |
| 3286 | UINT32 ea = GetEA(modrm,0); |
| 3287 | seg.selector = READ32(ea); |
| 3288 | CYCLES(CYCLES_LAR_MEM); |
| 3289 | } |
| 3290 | if(seg.selector == 0) |
| 3291 | { |
| 3292 | SetZF(0); // not a valid segment |
| 3293 | } |
| 3294 | else |
| 3295 | { |
| 3296 | UINT64 desc; |
| 3297 | if(!i386_load_protected_mode_segment(&seg,&desc)) |
| 3298 | { |
| 3299 | SetZF(0); |
| 3300 | return; |
| 3301 | } |
| 3302 | UINT8 DPL = (seg.flags >> 5) & 3; |
| 3303 | if(((DPL < m_CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c)) |
| 3304 | { |
| 3305 | SetZF(0); |
| 3306 | return; |
| 3307 | } |
| 3308 | if(!(seg.flags & 0x10)) // special segment |
| 3309 | { |
| 3310 | // check for invalid segment types |
| 3311 | type = seg.flags & 0x000f; |
| 3312 | if(type == 0x00 || type == 0x08 || type == 0x0a || type == 0x0d) |
| 3313 | { |
| 3314 | SetZF(0); // invalid segment type |
| 3315 | } |
| 3316 | else |
| 3317 | { |
| 3318 | STORE_REG32(modrm,(desc>>32) & 0x00ffff00); |
| 3319 | SetZF(1); |
| 3320 | } |
| 3321 | } |
| 3322 | else |
| 3323 | { |
| 3324 | STORE_REG32(modrm,(desc>>32) & 0x00ffff00); |
| 3325 | SetZF(1); |
| 3326 | } |
| 3327 | } |
| 3328 | } |
| 3329 | else |
| 3330 | { |
| 3331 | // illegal opcode |
| 3332 | i386_trap(6,0, 0); |
| 3333 | logerror("i386: LAR: Exception - running in real mode or virtual 8086 mode.\n"); |
| 3334 | } |
| 3335 | } |
| 3336 | |
| 3337 | void i386_device::i386_lsl_r32_rm32() // Opcode 0x0f 0x03 |
| 3338 | { |
| 3339 | UINT8 modrm = FETCH(); |
| 3340 | UINT32 limit; |
| 3341 | I386_SREG seg; |
| 3342 | |
| 3343 | if(PROTECTED_MODE && !V8086_MODE) |
| 3344 | { |
| 3345 | memset(&seg, 0, sizeof(seg)); |
| 3346 | if(modrm >= 0xc0) |
| 3347 | { |
| 3348 | seg.selector = LOAD_RM32(modrm); |
| 3349 | } |
| 3350 | else |
| 3351 | { |
| 3352 | UINT32 ea = GetEA(modrm,0); |
| 3353 | seg.selector = READ32(ea); |
| 3354 | } |
| 3355 | if(seg.selector == 0) |
| 3356 | { |
| 3357 | SetZF(0); // not a valid segment |
| 3358 | } |
| 3359 | else |
| 3360 | { |
| 3361 | UINT8 type; |
| 3362 | if(!i386_load_protected_mode_segment(&seg,NULL)) |
| 3363 | { |
| 3364 | SetZF(0); |
| 3365 | return; |
| 3366 | } |
| 3367 | UINT8 DPL = (seg.flags >> 5) & 3; |
| 3368 | if(((DPL < m_CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c)) |
| 3369 | { |
| 3370 | SetZF(0); |
| 3371 | return; |
| 3372 | } |
| 3373 | type = seg.flags & 0x1f; |
| 3374 | switch(type) |
| 3375 | { |
| 3376 | case 0: |
| 3377 | case 4: |
| 3378 | case 5: |
| 3379 | case 6: |
| 3380 | case 7: |
| 3381 | case 8: |
| 3382 | case 10: |
| 3383 | case 12: |
| 3384 | case 13: |
| 3385 | case 14: |
| 3386 | case 15: |
| 3387 | SetZF(0); |
| 3388 | return; |
| 3389 | default: |
| 3390 | limit = seg.limit; |
| 3391 | STORE_REG32(modrm,limit); |
| 3392 | SetZF(1); |
| 3393 | } |
| 3394 | } |
| 3395 | } |
| 3396 | else |
| 3397 | i386_trap(6, 0, 0); |
| 3398 | } |
| 3399 | |
| 3400 | void i386_device::i386_bound_r32_m32_m32() // Opcode 0x62 |
| 3401 | { |
| 3402 | UINT8 modrm; |
| 3403 | INT32 val, low, high; |
| 3404 | |
| 3405 | modrm = FETCH(); |
| 3406 | |
| 3407 | if (modrm >= 0xc0) |
| 3408 | { |
| 3409 | low = high = LOAD_RM32(modrm); |
| 3410 | } |
| 3411 | else |
| 3412 | { |
| 3413 | UINT32 ea = GetEA(modrm,0); |
| 3414 | low = READ32(ea + 0); |
| 3415 | high = READ32(ea + 4); |
| 3416 | } |
| 3417 | val = LOAD_REG32(modrm); |
| 3418 | |
| 3419 | if ((val < low) || (val > high)) |
| 3420 | { |
| 3421 | CYCLES(CYCLES_BOUND_OUT_RANGE); |
| 3422 | i386_trap(5, 0, 0); |
| 3423 | } |
| 3424 | else |
| 3425 | { |
| 3426 | CYCLES(CYCLES_BOUND_IN_RANGE); |
| 3427 | } |
| 3428 | } |
| 3429 | |
| 3430 | void i386_device::i386_retf32() // Opcode 0xcb |
| 3431 | { |
| 3432 | if(PROTECTED_MODE && !V8086_MODE) |
| 3433 | { |
| 3434 | i386_protected_mode_retf(0,1); |
| 3435 | } |
| 3436 | else |
| 3437 | { |
| 3438 | m_eip = POP32(); |
| 3439 | m_sreg[CS].selector = POP32(); |
| 3440 | i386_load_segment_descriptor(CS ); |
| 3441 | CHANGE_PC(m_eip); |
| 3442 | } |
| 3443 | |
| 3444 | CYCLES(CYCLES_RET_INTERSEG); |
| 3445 | } |
| 3446 | |
| 3447 | void i386_device::i386_retf_i32() // Opcode 0xca |
| 3448 | { |
| 3449 | UINT16 count = FETCH16(); |
| 3450 | |
| 3451 | if(PROTECTED_MODE && !V8086_MODE) |
| 3452 | { |
| 3453 | i386_protected_mode_retf(count,1); |
| 3454 | } |
| 3455 | else |
| 3456 | { |
| 3457 | m_eip = POP32(); |
| 3458 | m_sreg[CS].selector = POP32(); |
| 3459 | i386_load_segment_descriptor(CS ); |
| 3460 | CHANGE_PC(m_eip); |
| 3461 | REG32(ESP) += count; |
| 3462 | } |
| 3463 | |
| 3464 | CYCLES(CYCLES_RET_IMM_INTERSEG); |
| 3465 | } |
| 3466 | |
| 3467 | void i386_device::i386_load_far_pointer32(int s) |
| 3468 | { |
| 3469 | UINT8 modrm = FETCH(); |
| 3470 | UINT16 selector; |
| 3471 | |
| 3472 | if( modrm >= 0xc0 ) { |
| 3473 | report_invalid_modrm("load_far_pointer32", modrm); |
| 3474 | } else { |
| 3475 | UINT32 ea = GetEA(modrm,0); |
| 3476 | STORE_REG32(modrm, READ32(ea + 0)); |
| 3477 | selector = READ16(ea + 4); |
| 3478 | i386_sreg_load(selector,s,NULL); |
| 3479 | } |
| 3480 | } |
| 3481 | |
| 3482 | void i386_device::i386_lds32() // Opcode 0xc5 |
| 3483 | { |
| 3484 | i386_load_far_pointer32(DS); |
| 3485 | CYCLES(CYCLES_LDS); |
| 3486 | } |
| 3487 | |
| 3488 | void i386_device::i386_lss32() // Opcode 0x0f 0xb2 |
| 3489 | { |
| 3490 | i386_load_far_pointer32(SS); |
| 3491 | CYCLES(CYCLES_LSS); |
| 3492 | } |
| 3493 | |
| 3494 | void i386_device::i386_les32() // Opcode 0xc4 |
| 3495 | { |
| 3496 | i386_load_far_pointer32(ES); |
| 3497 | CYCLES(CYCLES_LES); |
| 3498 | } |
| 3499 | |
| 3500 | void i386_device::i386_lfs32() // Opcode 0x0f 0xb4 |
| 3501 | { |
| 3502 | i386_load_far_pointer32(FS); |
| 3503 | CYCLES(CYCLES_LFS); |
| 3504 | } |
| 3505 | |
| 3506 | void i386_device::i386_lgs32() // Opcode 0x0f 0xb5 |
| 3507 | { |
| 3508 | i386_load_far_pointer32(GS); |
| 3509 | CYCLES(CYCLES_LGS); |
| 3510 | } |
trunk/src/emu/cpu/i386/i386op16.inc
| r0 | r28739 | |
| 1 | UINT16 i386_device::i386_shift_rotate16(UINT8 modrm, UINT32 value, UINT8 shift) |
| 2 | { |
| 3 | UINT32 src = value & 0xffff; |
| 4 | UINT16 dst = value; |
| 5 | |
| 6 | if( shift == 0 ) { |
| 7 | CYCLES_RM(modrm, 3, 7); |
| 8 | } else if( shift == 1 ) { |
| 9 | switch( (modrm >> 3) & 0x7 ) |
| 10 | { |
| 11 | case 0: /* ROL rm16, 1 */ |
| 12 | m_CF = (src & 0x8000) ? 1 : 0; |
| 13 | dst = (src << 1) + m_CF; |
| 14 | m_OF = ((src ^ dst) & 0x8000) ? 1 : 0; |
| 15 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 16 | break; |
| 17 | case 1: /* ROR rm16, 1 */ |
| 18 | m_CF = (src & 0x1) ? 1 : 0; |
| 19 | dst = (m_CF << 15) | (src >> 1); |
| 20 | m_OF = ((src ^ dst) & 0x8000) ? 1 : 0; |
| 21 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 22 | break; |
| 23 | case 2: /* RCL rm16, 1 */ |
| 24 | dst = (src << 1) + m_CF; |
| 25 | m_CF = (src & 0x8000) ? 1 : 0; |
| 26 | m_OF = ((src ^ dst) & 0x8000) ? 1 : 0; |
| 27 | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 28 | break; |
| 29 | case 3: /* RCR rm16, 1 */ |
| 30 | dst = (m_CF << 15) | (src >> 1); |
| 31 | m_CF = src & 0x1; |
| 32 | m_OF = ((src ^ dst) & 0x8000) ? 1 : 0; |
| 33 | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 34 | break; |
| 35 | case 4: /* SHL/SAL rm16, 1 */ |
| 36 | case 6: |
| 37 | dst = src << 1; |
| 38 | m_CF = (src & 0x8000) ? 1 : 0; |
| 39 | m_OF = (((m_CF << 15) ^ dst) & 0x8000) ? 1 : 0; |
| 40 | SetSZPF16(dst); |
| 41 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 42 | break; |
| 43 | case 5: /* SHR rm16, 1 */ |
| 44 | dst = src >> 1; |
| 45 | m_CF = src & 0x1; |
| 46 | m_OF = (dst & 0x8000) ? 1 : 0; |
| 47 | SetSZPF16(dst); |
| 48 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 49 | break; |
| 50 | case 7: /* SAR rm16, 1 */ |
| 51 | dst = (INT16)(src) >> 1; |
| 52 | m_CF = src & 0x1; |
| 53 | m_OF = 0; |
| 54 | SetSZPF16(dst); |
| 55 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 56 | break; |
| 57 | } |
| 58 | } else { |
| 59 | switch( (modrm >> 3) & 0x7 ) |
| 60 | { |
| 61 | case 0: /* ROL rm16, i8 */ |
| 62 | if(!(shift & 15)) |
| 63 | { |
| 64 | if(shift & 16) |
| 65 | { |
| 66 | m_CF = src & 1; |
| 67 | m_OF = (src & 1) ^ ((src >> 15) & 1); |
| 68 | } |
| 69 | break; |
| 70 | } |
| 71 | shift &= 15; |
| 72 | dst = ((src & ((UINT16)0xffff >> shift)) << shift) | |
| 73 | ((src & ((UINT16)0xffff << (16-shift))) >> (16-shift)); |
| 74 | m_CF = dst & 0x1; |
| 75 | m_OF = (dst & 1) ^ (dst >> 15); |
| 76 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 77 | break; |
| 78 | case 1: /* ROR rm16, i8 */ |
| 79 | if(!(shift & 15)) |
| 80 | { |
| 81 | if(shift & 16) |
| 82 | { |
| 83 | m_CF = (src >> 15) & 1; |
| 84 | m_OF = ((src >> 15) & 1) ^ ((src >> 14) & 1); |
| 85 | } |
| 86 | break; |
| 87 | } |
| 88 | shift &= 15; |
| 89 | dst = ((src & ((UINT16)0xffff << shift)) >> shift) | |
| 90 | ((src & ((UINT16)0xffff >> (16-shift))) << (16-shift)); |
| 91 | m_CF = (dst >> 15) & 1; |
| 92 | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 93 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 94 | break; |
| 95 | case 2: /* RCL rm16, i8 */ |
| 96 | shift %= 17; |
| 97 | dst = ((src & ((UINT16)0xffff >> shift)) << shift) | |
| 98 | ((src & ((UINT16)0xffff << (17-shift))) >> (17-shift)) | |
| 99 | (m_CF << (shift-1)); |
| 100 | if(shift) m_CF = (src >> (16-shift)) & 0x1; |
| 101 | m_OF = m_CF ^ ((dst >> 15) & 1); |
| 102 | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 103 | break; |
| 104 | case 3: /* RCR rm16, i8 */ |
| 105 | shift %= 17; |
| 106 | dst = ((src & ((UINT16)0xffff << shift)) >> shift) | |
| 107 | ((src & ((UINT16)0xffff >> (16-shift))) << (17-shift)) | |
| 108 | (m_CF << (16-shift)); |
| 109 | if(shift) m_CF = (src >> (shift-1)) & 0x1; |
| 110 | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 111 | CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 112 | break; |
| 113 | case 4: /* SHL/SAL rm16, i8 */ |
| 114 | case 6: |
| 115 | shift &= 31; |
| 116 | dst = src << shift; |
| 117 | m_CF = (shift <= 16) && (src & (1 << (16-shift))); |
| 118 | SetSZPF16(dst); |
| 119 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 120 | break; |
| 121 | case 5: /* SHR rm16, i8 */ |
| 122 | shift &= 31; |
| 123 | dst = src >> shift; |
| 124 | m_CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 125 | SetSZPF16(dst); |
| 126 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 127 | break; |
| 128 | case 7: /* SAR rm16, i8 */ |
| 129 | shift &= 31; |
| 130 | dst = (INT16)src >> shift; |
| 131 | m_CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 132 | SetSZPF16(dst); |
| 133 | CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 134 | break; |
| 135 | } |
| 136 | |
| 137 | } |
| 138 | return dst; |
| 139 | } |
| 140 | |
| 141 | |
| 142 | |
| 143 | void i386_device::i386_adc_rm16_r16() // Opcode 0x11 |
| 144 | { |
| 145 | UINT16 src, dst; |
| 146 | UINT8 modrm = FETCH(); |
| 147 | if( modrm >= 0xc0 ) { |
| 148 | src = LOAD_REG16(modrm); |
| 149 | dst = LOAD_RM16(modrm); |
| 150 | dst = ADC16(dst, src, m_CF); |
| 151 | STORE_RM16(modrm, dst); |
| 152 | CYCLES(CYCLES_ALU_REG_REG); |
| 153 | } else { |
| 154 | UINT32 ea = GetEA(modrm,1); |
| 155 | src = LOAD_REG16(modrm); |
| 156 | dst = READ16(ea); |
| 157 | dst = ADC16(dst, src, m_CF); |
| 158 | WRITE16(ea, dst); |
| 159 | CYCLES(CYCLES_ALU_REG_MEM); |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | void i386_device::i386_adc_r16_rm16() // Opcode 0x13 |
| 164 | { |
| 165 | UINT16 src, dst; |
| 166 | UINT8 modrm = FETCH(); |
| 167 | if( modrm >= 0xc0 ) { |
| 168 | src = LOAD_RM16(modrm); |
| 169 | dst = LOAD_REG16(modrm); |
| 170 | dst = ADC16(dst, src, m_CF); |
| 171 | STORE_REG16(modrm, dst); |
| 172 | CYCLES(CYCLES_ALU_REG_REG); |
| 173 | } else { |
| 174 | UINT32 ea = GetEA(modrm,0); |
| 175 | src = READ16(ea); |
| 176 | dst = LOAD_REG16(modrm); |
| 177 | dst = ADC16(dst, src, m_CF); |
| 178 | STORE_REG16(modrm, dst); |
| 179 | CYCLES(CYCLES_ALU_MEM_REG); |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | void i386_device::i386_adc_ax_i16() // Opcode 0x15 |
| 184 | { |
| 185 | UINT16 src, dst; |
| 186 | src = FETCH16(); |
| 187 | dst = REG16(AX); |
| 188 | dst = ADC16(dst, src, m_CF); |
| 189 | REG16(AX) = dst; |
| 190 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 191 | } |
| 192 | |
| 193 | void i386_device::i386_add_rm16_r16() // Opcode 0x01 |
| 194 | { |
| 195 | UINT16 src, dst; |
| 196 | UINT8 modrm = FETCH(); |
| 197 | if( modrm >= 0xc0 ) { |
| 198 | src = LOAD_REG16(modrm); |
| 199 | dst = LOAD_RM16(modrm); |
| 200 | dst = ADD16(dst, src); |
| 201 | STORE_RM16(modrm, dst); |
| 202 | CYCLES(CYCLES_ALU_REG_REG); |
| 203 | } else { |
| 204 | UINT32 ea = GetEA(modrm,1); |
| 205 | src = LOAD_REG16(modrm); |
| 206 | dst = READ16(ea); |
| 207 | dst = ADD16(dst, src); |
| 208 | WRITE16(ea, dst); |
| 209 | CYCLES(CYCLES_ALU_REG_MEM); |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | void i386_device::i386_add_r16_rm16() // Opcode 0x03 |
| 214 | { |
| 215 | UINT16 src, dst; |
| 216 | UINT8 modrm = FETCH(); |
| 217 | if( modrm >= 0xc0 ) { |
| 218 | src = LOAD_RM16(modrm); |
| 219 | dst = LOAD_REG16(modrm); |
| 220 | dst = ADD16(dst, src); |
| 221 | STORE_REG16(modrm, dst); |
| 222 | CYCLES(CYCLES_ALU_REG_REG); |
| 223 | } else { |
| 224 | UINT32 ea = GetEA(modrm,0); |
| 225 | src = READ16(ea); |
| 226 | dst = LOAD_REG16(modrm); |
| 227 | dst = ADD16(dst, src); |
| 228 | STORE_REG16(modrm, dst); |
| 229 | CYCLES(CYCLES_ALU_MEM_REG); |
| 230 | } |
| 231 | } |
| 232 | |
| 233 | void i386_device::i386_add_ax_i16() // Opcode 0x05 |
| 234 | { |
| 235 | UINT16 src, dst; |
| 236 | src = FETCH16(); |
| 237 | dst = REG16(AX); |
| 238 | dst = ADD16(dst, src); |
| 239 | REG16(AX) = dst; |
| 240 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 241 | } |
| 242 | |
| 243 | void i386_device::i386_and_rm16_r16() // Opcode 0x21 |
| 244 | { |
| 245 | UINT16 src, dst; |
| 246 | UINT8 modrm = FETCH(); |
| 247 | if( modrm >= 0xc0 ) { |
| 248 | src = LOAD_REG16(modrm); |
| 249 | dst = LOAD_RM16(modrm); |
| 250 | dst = AND16(dst, src); |
| 251 | STORE_RM16(modrm, dst); |
| 252 | CYCLES(CYCLES_ALU_REG_REG); |
| 253 | } else { |
| 254 | UINT32 ea = GetEA(modrm,1); |
| 255 | src = LOAD_REG16(modrm); |
| 256 | dst = READ16(ea); |
| 257 | dst = AND16(dst, src); |
| 258 | WRITE16(ea, dst); |
| 259 | CYCLES(CYCLES_ALU_REG_MEM); |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | void i386_device::i386_and_r16_rm16() // Opcode 0x23 |
| 264 | { |
| 265 | UINT16 src, dst; |
| 266 | UINT8 modrm = FETCH(); |
| 267 | if( modrm >= 0xc0 ) { |
| 268 | src = LOAD_RM16(modrm); |
| 269 | dst = LOAD_REG16(modrm); |
| 270 | dst = AND16(dst, src); |
| 271 | STORE_REG16(modrm, dst); |
| 272 | CYCLES(CYCLES_ALU_REG_REG); |
| 273 | } else { |
| 274 | UINT32 ea = GetEA(modrm,0); |
| 275 | src = READ16(ea); |
| 276 | dst = LOAD_REG16(modrm); |
| 277 | dst = AND16(dst, src); |
| 278 | STORE_REG16(modrm, dst); |
| 279 | CYCLES(CYCLES_ALU_MEM_REG); |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | void i386_device::i386_and_ax_i16() // Opcode 0x25 |
| 284 | { |
| 285 | UINT16 src, dst; |
| 286 | src = FETCH16(); |
| 287 | dst = REG16(AX); |
| 288 | dst = AND16(dst, src); |
| 289 | REG16(AX) = dst; |
| 290 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 291 | } |
| 292 | |
| 293 | void i386_device::i386_bsf_r16_rm16() // Opcode 0x0f bc |
| 294 | { |
| 295 | UINT16 src, dst, temp; |
| 296 | UINT8 modrm = FETCH(); |
| 297 | |
| 298 | if( modrm >= 0xc0 ) { |
| 299 | src = LOAD_RM16(modrm); |
| 300 | } else { |
| 301 | UINT32 ea = GetEA(modrm,0); |
| 302 | src = READ16(ea); |
| 303 | } |
| 304 | |
| 305 | dst = 0; |
| 306 | |
| 307 | if( src == 0 ) { |
| 308 | m_ZF = 1; |
| 309 | } else { |
| 310 | m_ZF = 0; |
| 311 | temp = 0; |
| 312 | while( (src & (1 << temp)) == 0 ) { |
| 313 | temp++; |
| 314 | dst = temp; |
| 315 | CYCLES(CYCLES_BSF); |
| 316 | } |
| 317 | STORE_REG16(modrm, dst); |
| 318 | } |
| 319 | CYCLES(CYCLES_BSF_BASE); |
| 320 | } |
| 321 | |
| 322 | void i386_device::i386_bsr_r16_rm16() // Opcode 0x0f bd |
| 323 | { |
| 324 | UINT16 src, dst, temp; |
| 325 | UINT8 modrm = FETCH(); |
| 326 | |
| 327 | if( modrm >= 0xc0 ) { |
| 328 | src = LOAD_RM16(modrm); |
| 329 | } else { |
| 330 | UINT32 ea = GetEA(modrm,0); |
| 331 | src = READ16(ea); |
| 332 | } |
| 333 | |
| 334 | dst = 0; |
| 335 | |
| 336 | if( src == 0 ) { |
| 337 | m_ZF = 1; |
| 338 | } else { |
| 339 | m_ZF = 0; |
| 340 | dst = temp = 15; |
| 341 | while( (src & (1 << temp)) == 0 ) { |
| 342 | temp--; |
| 343 | dst = temp; |
| 344 | CYCLES(CYCLES_BSR); |
| 345 | } |
| 346 | STORE_REG16(modrm, dst); |
| 347 | } |
| 348 | CYCLES(CYCLES_BSR_BASE); |
| 349 | } |
| 350 | |
| 351 | |
| 352 | void i386_device::i386_bt_rm16_r16() // Opcode 0x0f a3 |
| 353 | { |
| 354 | UINT8 modrm = FETCH(); |
| 355 | if( modrm >= 0xc0 ) { |
| 356 | UINT16 dst = LOAD_RM16(modrm); |
| 357 | UINT16 bit = LOAD_REG16(modrm); |
| 358 | |
| 359 | if( dst & (1 << (bit & 0xf)) ) |
| 360 | m_CF = 1; |
| 361 | else |
| 362 | m_CF = 0; |
| 363 | |
| 364 | CYCLES(CYCLES_BT_REG_REG); |
| 365 | } else { |
| 366 | UINT8 segment; |
| 367 | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 368 | UINT16 bit = LOAD_REG16(modrm); |
| 369 | ea += 2*(bit/16); |
| 370 | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),0); |
| 371 | bit %= 16; |
| 372 | UINT16 dst = READ16(ea); |
| 373 | |
| 374 | if( dst & (1 << bit) ) |
| 375 | m_CF = 1; |
| 376 | else |
| 377 | m_CF = 0; |
| 378 | |
| 379 | CYCLES(CYCLES_BT_REG_MEM); |
| 380 | } |
| 381 | } |
| 382 | |
| 383 | void i386_device::i386_btc_rm16_r16() // Opcode 0x0f bb |
| 384 | { |
| 385 | UINT8 modrm = FETCH(); |
| 386 | if( modrm >= 0xc0 ) { |
| 387 | UINT16 dst = LOAD_RM16(modrm); |
| 388 | UINT16 bit = LOAD_REG16(modrm); |
| 389 | |
| 390 | if( dst & (1 << (bit & 0xf)) ) |
| 391 | m_CF = 1; |
| 392 | else |
| 393 | m_CF = 0; |
| 394 | dst ^= (1 << (bit & 0xf)); |
| 395 | |
| 396 | STORE_RM16(modrm, dst); |
| 397 | CYCLES(CYCLES_BTC_REG_REG); |
| 398 | } else { |
| 399 | UINT8 segment; |
| 400 | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 401 | UINT16 bit = LOAD_REG16(modrm); |
| 402 | ea += 2*(bit/16); |
| 403 | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1); |
| 404 | bit %= 16; |
| 405 | UINT16 dst = READ16(ea); |
| 406 | |
| 407 | if( dst & (1 << bit) ) |
| 408 | m_CF = 1; |
| 409 | else |
| 410 | m_CF = 0; |
| 411 | dst ^= (1 << bit); |
| 412 | |
| 413 | WRITE16(ea, dst); |
| 414 | CYCLES(CYCLES_BTC_REG_MEM); |
| 415 | } |
| 416 | } |
| 417 | |
| 418 | void i386_device::i386_btr_rm16_r16() // Opcode 0x0f b3 |
| 419 | { |
| 420 | UINT8 modrm = FETCH(); |
| 421 | if( modrm >= 0xc0 ) { |
| 422 | UINT16 dst = LOAD_RM16(modrm); |
| 423 | UINT16 bit = LOAD_REG16(modrm); |
| 424 | |
| 425 | if( dst & (1 << (bit & 0xf)) ) |
| 426 | m_CF = 1; |
| 427 | else |
| 428 | m_CF = 0; |
| 429 | dst &= ~(1 << (bit & 0xf)); |
| 430 | |
| 431 | STORE_RM16(modrm, dst); |
| 432 | CYCLES(CYCLES_BTR_REG_REG); |
| 433 | } else { |
| 434 | UINT8 segment; |
| 435 | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 436 | UINT16 bit = LOAD_REG16(modrm); |
| 437 | ea += 2*(bit/16); |
| 438 | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1); |
| 439 | bit %= 16; |
| 440 | UINT16 dst = READ16(ea); |
| 441 | |
| 442 | if( dst & (1 << bit) ) |
| 443 | m_CF = 1; |
| 444 | else |
| 445 | m_CF = 0; |
| 446 | dst &= ~(1 << bit); |
| 447 | |
| 448 | WRITE16(ea, dst); |
| 449 | CYCLES(CYCLES_BTR_REG_MEM); |
| 450 | } |
| 451 | } |
| 452 | |
| 453 | void i386_device::i386_bts_rm16_r16() // Opcode 0x0f ab |
| 454 | { |
| 455 | UINT8 modrm = FETCH(); |
| 456 | if( modrm >= 0xc0 ) { |
| 457 | UINT16 dst = LOAD_RM16(modrm); |
| 458 | UINT16 bit = LOAD_REG16(modrm); |
| 459 | |
| 460 | if( dst & (1 << (bit & 0xf)) ) |
| 461 | m_CF = 1; |
| 462 | else |
| 463 | m_CF = 0; |
| 464 | dst |= (1 << (bit & 0xf)); |
| 465 | |
| 466 | STORE_RM16(modrm, dst); |
| 467 | CYCLES(CYCLES_BTS_REG_REG); |
| 468 | } else { |
| 469 | UINT8 segment; |
| 470 | UINT32 ea = GetNonTranslatedEA(modrm,&segment); |
| 471 | UINT16 bit = LOAD_REG16(modrm); |
| 472 | ea += 2*(bit/16); |
| 473 | ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1); |
| 474 | bit %= 16; |
| 475 | UINT16 dst = READ16(ea); |
| 476 | |
| 477 | if( dst & (1 << bit) ) |
| 478 | m_CF = 1; |
| 479 | else |
| 480 | m_CF = 0; |
| 481 | dst |= (1 << bit); |
| 482 | |
| 483 | WRITE16(ea, dst); |
| 484 | CYCLES(CYCLES_BTS_REG_MEM); |
| 485 | } |
| 486 | } |
| 487 | |
| 488 | void i386_device::i386_call_abs16() // Opcode 0x9a |
| 489 | { |
| 490 | UINT16 offset = FETCH16(); |
| 491 | UINT16 ptr = FETCH16(); |
| 492 | |
| 493 | if( PROTECTED_MODE && !V8086_MODE) |
| 494 | { |
| 495 | i386_protected_mode_call(ptr,offset,0,0); |
| 496 | } |
| 497 | else |
| 498 | { |
| 499 | PUSH16(m_sreg[CS].selector ); |
| 500 | PUSH16(m_eip ); |
| 501 | m_sreg[CS].selector = ptr; |
| 502 | m_performed_intersegment_jump = 1; |
| 503 | m_eip = offset; |
| 504 | i386_load_segment_descriptor(CS); |
| 505 | } |
| 506 | CYCLES(CYCLES_CALL_INTERSEG); /* TODO: Timing = 17 + m */ |
| 507 | CHANGE_PC(m_eip); |
| 508 | } |
| 509 | |
| 510 | void i386_device::i386_call_rel16() // Opcode 0xe8 |
| 511 | { |
| 512 | INT16 disp = FETCH16(); |
| 513 | |
| 514 | PUSH16(m_eip ); |
| 515 | if (m_sreg[CS].d) |
| 516 | { |
| 517 | m_eip += disp; |
| 518 | } |
| 519 | else |
| 520 | { |
| 521 | m_eip = (m_eip + disp) & 0xffff; |
| 522 | } |
| 523 | CHANGE_PC(m_eip); |
| 524 | CYCLES(CYCLES_CALL); /* TODO: Timing = 7 + m */ |
| 525 | } |
| 526 | |
| 527 | void i386_device::i386_cbw() // Opcode 0x98 |
| 528 | { |
| 529 | REG16(AX) = (INT16)((INT8)REG8(AL)); |
| 530 | CYCLES(CYCLES_CBW); |
| 531 | } |
| 532 | |
| 533 | void i386_device::i386_cmp_rm16_r16() // Opcode 0x39 |
| 534 | { |
| 535 | UINT16 src, dst; |
| 536 | UINT8 modrm = FETCH(); |
| 537 | if( modrm >= 0xc0 ) { |
| 538 | src = LOAD_REG16(modrm); |
| 539 | dst = LOAD_RM16(modrm); |
| 540 | SUB16(dst, src); |
| 541 | CYCLES(CYCLES_CMP_REG_REG); |
| 542 | } else { |
| 543 | UINT32 ea = GetEA(modrm,0); |
| 544 | src = LOAD_REG16(modrm); |
| 545 | dst = READ16(ea); |
| 546 | SUB16(dst, src); |
| 547 | CYCLES(CYCLES_CMP_REG_MEM); |
| 548 | } |
| 549 | } |
| 550 | |
| 551 | void i386_device::i386_cmp_r16_rm16() // Opcode 0x3b |
| 552 | { |
| 553 | UINT16 src, dst; |
| 554 | UINT8 modrm = FETCH(); |
| 555 | if( modrm >= 0xc0 ) { |
| 556 | src = LOAD_RM16(modrm); |
| 557 | dst = LOAD_REG16(modrm); |
| 558 | SUB16(dst, src); |
| 559 | CYCLES(CYCLES_CMP_REG_REG); |
| 560 | } else { |
| 561 | UINT32 ea = GetEA(modrm,0); |
| 562 | src = READ16(ea); |
| 563 | dst = LOAD_REG16(modrm); |
| 564 | SUB16(dst, src); |
| 565 | CYCLES(CYCLES_CMP_MEM_REG); |
| 566 | } |
| 567 | } |
| 568 | |
| 569 | void i386_device::i386_cmp_ax_i16() // Opcode 0x3d |
| 570 | { |
| 571 | UINT16 src, dst; |
| 572 | src = FETCH16(); |
| 573 | dst = REG16(AX); |
| 574 | SUB16(dst, src); |
| 575 | CYCLES(CYCLES_CMP_IMM_ACC); |
| 576 | } |
| 577 | |
| 578 | void i386_device::i386_cmpsw() // Opcode 0xa7 |
| 579 | { |
| 580 | UINT32 eas, ead; |
| 581 | UINT16 src, dst; |
| 582 | if( m_segment_prefix ) { |
| 583 | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 584 | } else { |
| 585 | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 586 | } |
| 587 | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 ); |
| 588 | src = READ16(eas); |
| 589 | dst = READ16(ead); |
| 590 | SUB16(src,dst); |
| 591 | BUMP_SI(2); |
| 592 | BUMP_DI(2); |
| 593 | CYCLES(CYCLES_CMPS); |
| 594 | } |
| 595 | |
| 596 | void i386_device::i386_cwd() // Opcode 0x99 |
| 597 | { |
| 598 | if( REG16(AX) & 0x8000 ) { |
| 599 | REG16(DX) = 0xffff; |
| 600 | } else { |
| 601 | REG16(DX) = 0x0000; |
| 602 | } |
| 603 | CYCLES(CYCLES_CWD); |
| 604 | } |
| 605 | |
| 606 | void i386_device::i386_dec_ax() // Opcode 0x48 |
| 607 | { |
| 608 | REG16(AX) = DEC16(REG16(AX) ); |
| 609 | CYCLES(CYCLES_DEC_REG); |
| 610 | } |
| 611 | |
| 612 | void i386_device::i386_dec_cx() // Opcode 0x49 |
| 613 | { |
| 614 | REG16(CX) = DEC16(REG16(CX) ); |
| 615 | CYCLES(CYCLES_DEC_REG); |
| 616 | } |
| 617 | |
| 618 | void i386_device::i386_dec_dx() // Opcode 0x4a |
| 619 | { |
| 620 | REG16(DX) = DEC16(REG16(DX) ); |
| 621 | CYCLES(CYCLES_DEC_REG); |
| 622 | } |
| 623 | |
| 624 | void i386_device::i386_dec_bx() // Opcode 0x4b |
| 625 | { |
| 626 | REG16(BX) = DEC16(REG16(BX) ); |
| 627 | CYCLES(CYCLES_DEC_REG); |
| 628 | } |
| 629 | |
| 630 | void i386_device::i386_dec_sp() // Opcode 0x4c |
| 631 | { |
| 632 | REG16(SP) = DEC16(REG16(SP) ); |
| 633 | CYCLES(CYCLES_DEC_REG); |
| 634 | } |
| 635 | |
| 636 | void i386_device::i386_dec_bp() // Opcode 0x4d |
| 637 | { |
| 638 | REG16(BP) = DEC16(REG16(BP) ); |
| 639 | CYCLES(CYCLES_DEC_REG); |
| 640 | } |
| 641 | |
| 642 | void i386_device::i386_dec_si() // Opcode 0x4e |
| 643 | { |
| 644 | REG16(SI) = DEC16(REG16(SI) ); |
| 645 | CYCLES(CYCLES_DEC_REG); |
| 646 | } |
| 647 | |
| 648 | void i386_device::i386_dec_di() // Opcode 0x4f |
| 649 | { |
| 650 | REG16(DI) = DEC16(REG16(DI) ); |
| 651 | CYCLES(CYCLES_DEC_REG); |
| 652 | } |
| 653 | |
| 654 | void i386_device::i386_imul_r16_rm16() // Opcode 0x0f af |
| 655 | { |
| 656 | UINT8 modrm = FETCH(); |
| 657 | INT32 result; |
| 658 | INT32 src, dst; |
| 659 | if( modrm >= 0xc0 ) { |
| 660 | src = (INT32)(INT16)LOAD_RM16(modrm); |
| 661 | CYCLES(CYCLES_IMUL16_REG_REG); /* TODO: Correct multiply timing */ |
| 662 | } else { |
| 663 | UINT32 ea = GetEA(modrm,0); |
| 664 | src = (INT32)(INT16)READ16(ea); |
| 665 | CYCLES(CYCLES_IMUL16_REG_MEM); /* TODO: Correct multiply timing */ |
| 666 | } |
| 667 | |
| 668 | dst = (INT32)(INT16)LOAD_REG16(modrm); |
| 669 | result = src * dst; |
| 670 | |
| 671 | STORE_REG16(modrm, (UINT16)result); |
| 672 | |
| 673 | m_CF = m_OF = !(result == (INT32)(INT16)result); |
| 674 | } |
| 675 | |
| 676 | void i386_device::i386_imul_r16_rm16_i16() // Opcode 0x69 |
| 677 | { |
| 678 | UINT8 modrm = FETCH(); |
| 679 | INT32 result; |
| 680 | INT32 src, dst; |
| 681 | if( modrm >= 0xc0 ) { |
| 682 | dst = (INT32)(INT16)LOAD_RM16(modrm); |
| 683 | CYCLES(CYCLES_IMUL16_REG_IMM_REG); /* TODO: Correct multiply timing */ |
| 684 | } else { |
| 685 | UINT32 ea = GetEA(modrm,0); |
| 686 | dst = (INT32)(INT16)READ16(ea); |
| 687 | CYCLES(CYCLES_IMUL16_MEM_IMM_REG); /* TODO: Correct multiply timing */ |
| 688 | } |
| 689 | |
| 690 | src = (INT32)(INT16)FETCH16(); |
| 691 | result = src * dst; |
| 692 | |
| 693 | STORE_REG16(modrm, (UINT16)result); |
| 694 | |
| 695 | m_CF = m_OF = !(result == (INT32)(INT16)result); |
| 696 | } |
| 697 | |
| 698 | void i386_device::i386_imul_r16_rm16_i8() // Opcode 0x6b |
| 699 | { |
| 700 | UINT8 modrm = FETCH(); |
| 701 | INT32 result; |
| 702 | INT32 src, dst; |
| 703 | if( modrm >= 0xc0 ) { |
| 704 | dst = (INT32)(INT16)LOAD_RM16(modrm); |
| 705 | CYCLES(CYCLES_IMUL16_REG_IMM_REG); /* TODO: Correct multiply timing */ |
| 706 | } else { |
| 707 | UINT32 ea = GetEA(modrm,0); |
| 708 | dst = (INT32)(INT16)READ16(ea); |
| 709 | CYCLES(CYCLES_IMUL16_MEM_IMM_REG); /* TODO: Correct multiply timing */ |
| 710 | } |
| 711 | |
| 712 | src = (INT32)(INT8)FETCH(); |
| 713 | result = src * dst; |
| 714 | |
| 715 | STORE_REG16(modrm, (UINT16)result); |
| 716 | |
| 717 | m_CF = m_OF = !(result == (INT32)(INT16)result); |
| 718 | } |
| 719 | |
| 720 | void i386_device::i386_in_ax_i8() // Opcode 0xe5 |
| 721 | { |
| 722 | UINT16 port = FETCH(); |
| 723 | UINT16 data = READPORT16(port); |
| 724 | REG16(AX) = data; |
| 725 | CYCLES(CYCLES_IN_VAR); |
| 726 | } |
| 727 | |
| 728 | void i386_device::i386_in_ax_dx() // Opcode 0xed |
| 729 | { |
| 730 | UINT16 port = REG16(DX); |
| 731 | UINT16 data = READPORT16(port); |
| 732 | REG16(AX) = data; |
| 733 | CYCLES(CYCLES_IN); |
| 734 | } |
| 735 | |
| 736 | void i386_device::i386_inc_ax() // Opcode 0x40 |
| 737 | { |
| 738 | REG16(AX) = INC16(REG16(AX) ); |
| 739 | CYCLES(CYCLES_INC_REG); |
| 740 | } |
| 741 | |
| 742 | void i386_device::i386_inc_cx() // Opcode 0x41 |
| 743 | { |
| 744 | REG16(CX) = INC16(REG16(CX) ); |
| 745 | CYCLES(CYCLES_INC_REG); |
| 746 | } |
| 747 | |
| 748 | void i386_device::i386_inc_dx() // Opcode 0x42 |
| 749 | { |
| 750 | REG16(DX) = INC16(REG16(DX) ); |
| 751 | CYCLES(CYCLES_INC_REG); |
| 752 | } |
| 753 | |
| 754 | void i386_device::i386_inc_bx() // Opcode 0x43 |
| 755 | { |
| 756 | REG16(BX) = INC16(REG16(BX) ); |
| 757 | CYCLES(CYCLES_INC_REG); |
| 758 | } |
| 759 | |
| 760 | void i386_device::i386_inc_sp() // Opcode 0x44 |
| 761 | { |
| 762 | REG16(SP) = INC16(REG16(SP) ); |
| 763 | CYCLES(CYCLES_INC_REG); |
| 764 | } |
| 765 | |
| 766 | void i386_device::i386_inc_bp() // Opcode 0x45 |
| 767 | { |
| 768 | REG16(BP) = INC16(REG16(BP) ); |
| 769 | CYCLES(CYCLES_INC_REG); |
| 770 | } |
| 771 | |
| 772 | void i386_device::i386_inc_si() // Opcode 0x46 |
| 773 | { |
| 774 | REG16(SI) = INC16(REG16(SI) ); |
| 775 | CYCLES(CYCLES_INC_REG); |
| 776 | } |
| 777 | |
| 778 | void i386_device::i386_inc_di() // Opcode 0x47 |
| 779 | { |
| 780 | REG16(DI) = INC16(REG16(DI) ); |
| 781 | CYCLES(CYCLES_INC_REG); |
| 782 | } |
| 783 | |
| 784 | void i386_device::i386_iret16() // Opcode 0xcf |
| 785 | { |
| 786 | if( PROTECTED_MODE ) |
| 787 | { |
| 788 | i386_protected_mode_iret(0); |
| 789 | } |
| 790 | else |
| 791 | { |
| 792 | /* TODO: #SS(0) exception */ |
| 793 | /* TODO: #GP(0) exception */ |
| 794 | m_eip = POP16(); |
| 795 | m_sreg[CS].selector = POP16(); |
| 796 | set_flags(POP16() ); |
| 797 | i386_load_segment_descriptor(CS); |
| 798 | CHANGE_PC(m_eip); |
| 799 | } |
| 800 | CYCLES(CYCLES_IRET); |
| 801 | } |
| 802 | |
| 803 | void i386_device::i386_ja_rel16() // Opcode 0x0f 87 |
| 804 | { |
| 805 | INT16 disp = FETCH16(); |
| 806 | if( m_CF == 0 && m_ZF == 0 ) { |
| 807 | if (m_sreg[CS].d) |
| 808 | { |
| 809 | m_eip += disp; |
| 810 | } |
| 811 | else |
| 812 | { |
| 813 | m_eip = (m_eip + disp) & 0xffff; |
| 814 | } |
| 815 | CHANGE_PC(m_eip); |
| 816 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 817 | } else { |
| 818 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 819 | } |
| 820 | } |
| 821 | |
| 822 | void i386_device::i386_jbe_rel16() // Opcode 0x0f 86 |
| 823 | { |
| 824 | INT16 disp = FETCH16(); |
| 825 | if( m_CF != 0 || m_ZF != 0 ) { |
| 826 | if (m_sreg[CS].d) |
| 827 | { |
| 828 | m_eip += disp; |
| 829 | } |
| 830 | else |
| 831 | { |
| 832 | m_eip = (m_eip + disp) & 0xffff; |
| 833 | } |
| 834 | CHANGE_PC(m_eip); |
| 835 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 836 | } else { |
| 837 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 838 | } |
| 839 | } |
| 840 | |
| 841 | void i386_device::i386_jc_rel16() // Opcode 0x0f 82 |
| 842 | { |
| 843 | INT16 disp = FETCH16(); |
| 844 | if( m_CF != 0 ) { |
| 845 | if (m_sreg[CS].d) |
| 846 | { |
| 847 | m_eip += disp; |
| 848 | } |
| 849 | else |
| 850 | { |
| 851 | m_eip = (m_eip + disp) & 0xffff; |
| 852 | } |
| 853 | CHANGE_PC(m_eip); |
| 854 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 855 | } else { |
| 856 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 857 | } |
| 858 | } |
| 859 | |
| 860 | void i386_device::i386_jg_rel16() // Opcode 0x0f 8f |
| 861 | { |
| 862 | INT16 disp = FETCH16(); |
| 863 | if( m_ZF == 0 && (m_SF == m_OF) ) { |
| 864 | if (m_sreg[CS].d) |
| 865 | { |
| 866 | m_eip += disp; |
| 867 | } |
| 868 | else |
| 869 | { |
| 870 | m_eip = (m_eip + disp) & 0xffff; |
| 871 | } |
| 872 | CHANGE_PC(m_eip); |
| 873 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 874 | } else { |
| 875 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 876 | } |
| 877 | } |
| 878 | |
| 879 | void i386_device::i386_jge_rel16() // Opcode 0x0f 8d |
| 880 | { |
| 881 | INT16 disp = FETCH16(); |
| 882 | if(m_SF == m_OF) { |
| 883 | if (m_sreg[CS].d) |
| 884 | { |
| 885 | m_eip += disp; |
| 886 | } |
| 887 | else |
| 888 | { |
| 889 | m_eip = (m_eip + disp) & 0xffff; |
| 890 | } |
| 891 | CHANGE_PC(m_eip); |
| 892 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 893 | } else { |
| 894 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 895 | } |
| 896 | } |
| 897 | |
| 898 | void i386_device::i386_jl_rel16() // Opcode 0x0f 8c |
| 899 | { |
| 900 | INT16 disp = FETCH16(); |
| 901 | if( (m_SF != m_OF) ) { |
| 902 | if (m_sreg[CS].d) |
| 903 | { |
| 904 | m_eip += disp; |
| 905 | } |
| 906 | else |
| 907 | { |
| 908 | m_eip = (m_eip + disp) & 0xffff; |
| 909 | } |
| 910 | CHANGE_PC(m_eip); |
| 911 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 912 | } else { |
| 913 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 914 | } |
| 915 | } |
| 916 | |
| 917 | void i386_device::i386_jle_rel16() // Opcode 0x0f 8e |
| 918 | { |
| 919 | INT16 disp = FETCH16(); |
| 920 | if( m_ZF != 0 || (m_SF != m_OF) ) { |
| 921 | if (m_sreg[CS].d) |
| 922 | { |
| 923 | m_eip += disp; |
| 924 | } |
| 925 | else |
| 926 | { |
| 927 | m_eip = (m_eip + disp) & 0xffff; |
| 928 | } |
| 929 | CHANGE_PC(m_eip); |
| 930 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 931 | } else { |
| 932 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 933 | } |
| 934 | } |
| 935 | |
| 936 | void i386_device::i386_jnc_rel16() // Opcode 0x0f 83 |
| 937 | { |
| 938 | INT16 disp = FETCH16(); |
| 939 | if( m_CF == 0 ) { |
| 940 | if (m_sreg[CS].d) |
| 941 | { |
| 942 | m_eip += disp; |
| 943 | } |
| 944 | else |
| 945 | { |
| 946 | m_eip = (m_eip + disp) & 0xffff; |
| 947 | } |
| 948 | CHANGE_PC(m_eip); |
| 949 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 950 | } else { |
| 951 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 952 | } |
| 953 | } |
| 954 | |
| 955 | void i386_device::i386_jno_rel16() // Opcode 0x0f 81 |
| 956 | { |
| 957 | INT16 disp = FETCH16(); |
| 958 | if( m_OF == 0 ) { |
| 959 | if (m_sreg[CS].d) |
| 960 | { |
| 961 | m_eip += disp; |
| 962 | } |
| 963 | else |
| 964 | { |
| 965 | m_eip = (m_eip + disp) & 0xffff; |
| 966 | } |
| 967 | CHANGE_PC(m_eip); |
| 968 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 969 | } else { |
| 970 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 971 | } |
| 972 | } |
| 973 | |
| 974 | void i386_device::i386_jnp_rel16() // Opcode 0x0f 8b |
| 975 | { |
| 976 | INT16 disp = FETCH16(); |
| 977 | if( m_PF == 0 ) { |
| 978 | if (m_sreg[CS].d) |
| 979 | { |
| 980 | m_eip += disp; |
| 981 | } |
| 982 | else |
| 983 | { |
| 984 | m_eip = (m_eip + disp) & 0xffff; |
| 985 | } |
| 986 | CHANGE_PC(m_eip); |
| 987 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 988 | } else { |
| 989 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 990 | } |
| 991 | } |
| 992 | |
| 993 | void i386_device::i386_jns_rel16() // Opcode 0x0f 89 |
| 994 | { |
| 995 | INT16 disp = FETCH16(); |
| 996 | if( m_SF == 0 ) { |
| 997 | if (m_sreg[CS].d) |
| 998 | { |
| 999 | m_eip += disp; |
| 1000 | } |
| 1001 | else |
| 1002 | { |
| 1003 | m_eip = (m_eip + disp) & 0xffff; |
| 1004 | } |
| 1005 | CHANGE_PC(m_eip); |
| 1006 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 1007 | } else { |
| 1008 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 1009 | } |
| 1010 | } |
| 1011 | |
| 1012 | void i386_device::i386_jnz_rel16() // Opcode 0x0f 85 |
| 1013 | { |
| 1014 | INT16 disp = FETCH16(); |
| 1015 | if( m_ZF == 0 ) { |
| 1016 | if (m_sreg[CS].d) |
| 1017 | { |
| 1018 | m_eip += disp; |
| 1019 | } |
| 1020 | else |
| 1021 | { |
| 1022 | m_eip = (m_eip + disp) & 0xffff; |
| 1023 | } |
| 1024 | CHANGE_PC(m_eip); |
| 1025 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 1026 | } else { |
| 1027 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 1028 | } |
| 1029 | } |
| 1030 | |
| 1031 | void i386_device::i386_jo_rel16() // Opcode 0x0f 80 |
| 1032 | { |
| 1033 | INT16 disp = FETCH16(); |
| 1034 | if( m_OF != 0 ) { |
| 1035 | if (m_sreg[CS].d) |
| 1036 | { |
| 1037 | m_eip += disp; |
| 1038 | } |
| 1039 | else |
| 1040 | { |
| 1041 | m_eip = (m_eip + disp) & 0xffff; |
| 1042 | } |
| 1043 | CHANGE_PC(m_eip); |
| 1044 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 1045 | } else { |
| 1046 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 1047 | } |
| 1048 | } |
| 1049 | |
| 1050 | void i386_device::i386_jp_rel16() // Opcode 0x0f 8a |
| 1051 | { |
| 1052 | INT16 disp = FETCH16(); |
| 1053 | if( m_PF != 0 ) { |
| 1054 | if (m_sreg[CS].d) |
| 1055 | { |
| 1056 | m_eip += disp; |
| 1057 | } |
| 1058 | else |
| 1059 | { |
| 1060 | m_eip = (m_eip + disp) & 0xffff; |
| 1061 | } |
| 1062 | CHANGE_PC(m_eip); |
| 1063 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 1064 | } else { |
| 1065 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 1066 | } |
| 1067 | } |
| 1068 | |
| 1069 | void i386_device::i386_js_rel16() // Opcode 0x0f 88 |
| 1070 | { |
| 1071 | INT16 disp = FETCH16(); |
| 1072 | if( m_SF != 0 ) { |
| 1073 | if (m_sreg[CS].d) |
| 1074 | { |
| 1075 | m_eip += disp; |
| 1076 | } |
| 1077 | else |
| 1078 | { |
| 1079 | m_eip = (m_eip + disp) & 0xffff; |
| 1080 | } |
| 1081 | CHANGE_PC(m_eip); |
| 1082 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 1083 | } else { |
| 1084 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 1085 | } |
| 1086 | } |
| 1087 | |
| 1088 | void i386_device::i386_jz_rel16() // Opcode 0x0f 84 |
| 1089 | { |
| 1090 | INT16 disp = FETCH16(); |
| 1091 | if( m_ZF != 0 ) { |
| 1092 | if (m_sreg[CS].d) |
| 1093 | { |
| 1094 | m_eip += disp; |
| 1095 | } |
| 1096 | else |
| 1097 | { |
| 1098 | m_eip = (m_eip + disp) & 0xffff; |
| 1099 | } |
| 1100 | CHANGE_PC(m_eip); |
| 1101 | CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */ |
| 1102 | } else { |
| 1103 | CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH); |
| 1104 | } |
| 1105 | } |
| 1106 | |
| 1107 | void i386_device::i386_jcxz16() // Opcode 0xe3 |
| 1108 | { |
| 1109 | INT8 disp = FETCH(); |
| 1110 | int val = (m_address_size)?(REG32(ECX) == 0):(REG16(CX) == 0); |
| 1111 | if( val ) { |
| 1112 | if (m_sreg[CS].d) |
| 1113 | { |
| 1114 | m_eip += disp; |
| 1115 | } |
| 1116 | else |
| 1117 | { |
| 1118 | m_eip = (m_eip + disp) & 0xffff; |
| 1119 | } |
| 1120 | CHANGE_PC(m_eip); |
| 1121 | CYCLES(CYCLES_JCXZ); /* TODO: Timing = 9 + m */ |
| 1122 | } else { |
| 1123 | CYCLES(CYCLES_JCXZ_NOBRANCH); |
| 1124 | } |
| 1125 | } |
| 1126 | |
| 1127 | void i386_device::i386_jmp_rel16() // Opcode 0xe9 |
| 1128 | { |
| 1129 | INT16 disp = FETCH16(); |
| 1130 | |
| 1131 | if (m_sreg[CS].d) |
| 1132 | { |
| 1133 | m_eip += disp; |
| 1134 | } |
| 1135 | else |
| 1136 | { |
| 1137 | m_eip = (m_eip + disp) & 0xffff; |
| 1138 | } |
| 1139 | CHANGE_PC(m_eip); |
| 1140 | CYCLES(CYCLES_JMP); /* TODO: Timing = 7 + m */ |
| 1141 | } |
| 1142 | |
| 1143 | void i386_device::i386_jmp_abs16() // Opcode 0xea |
| 1144 | { |
| 1145 | UINT16 address = FETCH16(); |
| 1146 | UINT16 segment = FETCH16(); |
| 1147 | |
| 1148 | if( PROTECTED_MODE && !V8086_MODE) |
| 1149 | { |
| 1150 | i386_protected_mode_jump(segment,address,0,0); |
| 1151 | } |
| 1152 | else |
| 1153 | { |
| 1154 | m_eip = address; |
| 1155 | m_sreg[CS].selector = segment; |
| 1156 | m_performed_intersegment_jump = 1; |
| 1157 | i386_load_segment_descriptor(CS); |
| 1158 | CHANGE_PC(m_eip); |
| 1159 | } |
| 1160 | CYCLES(CYCLES_JMP_INTERSEG); |
| 1161 | } |
| 1162 | |
| 1163 | void i386_device::i386_lea16() // Opcode 0x8d |
| 1164 | { |
| 1165 | UINT8 modrm = FETCH(); |
| 1166 | UINT32 ea = GetNonTranslatedEA(modrm,NULL); |
| 1167 | STORE_REG16(modrm, ea); |
| 1168 | CYCLES(CYCLES_LEA); |
| 1169 | } |
| 1170 | |
| 1171 | void i386_device::i386_enter16() // Opcode 0xc8 |
| 1172 | { |
| 1173 | UINT16 framesize = FETCH16(); |
| 1174 | UINT8 level = FETCH() % 32; |
| 1175 | UINT8 x; |
| 1176 | UINT16 frameptr; |
| 1177 | PUSH16(REG16(BP)); |
| 1178 | |
| 1179 | if(!STACK_32BIT) |
| 1180 | frameptr = REG16(SP); |
| 1181 | else |
| 1182 | frameptr = REG32(ESP); |
| 1183 | |
| 1184 | if(level > 0) |
| 1185 | { |
| 1186 | for(x=1;x<level-1;x++) |
| 1187 | { |
| 1188 | REG16(BP) -= 2; |
| 1189 | PUSH16(READ16(REG16(BP))); |
| 1190 | } |
| 1191 | PUSH16(frameptr); |
| 1192 | } |
| 1193 | REG16(BP) = frameptr; |
| 1194 | if(!STACK_32BIT) |
| 1195 | REG16(SP) -= framesize; |
| 1196 | else |
| 1197 | REG32(ESP) -= framesize; |
| 1198 | CYCLES(CYCLES_ENTER); |
| 1199 | } |
| 1200 | |
| 1201 | void i386_device::i386_leave16() // Opcode 0xc9 |
| 1202 | { |
| 1203 | if(!STACK_32BIT) |
| 1204 | REG16(SP) = REG16(BP); |
| 1205 | else |
| 1206 | REG32(ESP) = REG32(EBP); |
| 1207 | REG16(BP) = POP16(); |
| 1208 | CYCLES(CYCLES_LEAVE); |
| 1209 | } |
| 1210 | |
| 1211 | void i386_device::i386_lodsw() // Opcode 0xad |
| 1212 | { |
| 1213 | UINT32 eas; |
| 1214 | if( m_segment_prefix ) { |
| 1215 | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1216 | } else { |
| 1217 | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1218 | } |
| 1219 | REG16(AX) = READ16(eas); |
| 1220 | BUMP_SI(2); |
| 1221 | CYCLES(CYCLES_LODS); |
| 1222 | } |
| 1223 | |
| 1224 | void i386_device::i386_loop16() // Opcode 0xe2 |
| 1225 | { |
| 1226 | INT8 disp = FETCH(); |
| 1227 | INT32 val = (m_address_size)?(--REG32(ECX)):(--REG16(CX)); |
| 1228 | if( val != 0 ) { |
| 1229 | if (m_sreg[CS].d) |
| 1230 | { |
| 1231 | m_eip += disp; |
| 1232 | } |
| 1233 | else |
| 1234 | { |
| 1235 | m_eip = (m_eip + disp) & 0xffff; |
| 1236 | } |
| 1237 | CHANGE_PC(m_eip); |
| 1238 | } |
| 1239 | CYCLES(CYCLES_LOOP); /* TODO: Timing = 11 + m */ |
| 1240 | } |
| 1241 | |
| 1242 | void i386_device::i386_loopne16() // Opcode 0xe0 |
| 1243 | { |
| 1244 | INT8 disp = FETCH(); |
| 1245 | INT32 val = (m_address_size)?(--REG32(ECX)):(--REG16(CX)); |
| 1246 | if( val != 0 && m_ZF == 0 ) { |
| 1247 | if (m_sreg[CS].d) |
| 1248 | { |
| 1249 | m_eip += disp; |
| 1250 | } |
| 1251 | else |
| 1252 | { |
| 1253 | m_eip = (m_eip + disp) & 0xffff; |
| 1254 | } |
| 1255 | CHANGE_PC(m_eip); |
| 1256 | } |
| 1257 | CYCLES(CYCLES_LOOPNZ); /* TODO: Timing = 11 + m */ |
| 1258 | } |
| 1259 | |
| 1260 | void i386_device::i386_loopz16() // Opcode 0xe1 |
| 1261 | { |
| 1262 | INT8 disp = FETCH(); |
| 1263 | INT32 val = (m_address_size)?(--REG32(ECX)):(--REG16(CX)); |
| 1264 | if( val != 0 && m_ZF != 0 ) { |
| 1265 | if (m_sreg[CS].d) |
| 1266 | { |
| 1267 | m_eip += disp; |
| 1268 | } |
| 1269 | else |
| 1270 | { |
| 1271 | m_eip = (m_eip + disp) & 0xffff; |
| 1272 | } |
| 1273 | CHANGE_PC(m_eip); |
| 1274 | } |
| 1275 | CYCLES(CYCLES_LOOPZ); /* TODO: Timing = 11 + m */ |
| 1276 | } |
| 1277 | |
| 1278 | void i386_device::i386_mov_rm16_r16() // Opcode 0x89 |
| 1279 | { |
| 1280 | UINT16 src; |
| 1281 | UINT8 modrm = FETCH(); |
| 1282 | if( modrm >= 0xc0 ) { |
| 1283 | src = LOAD_REG16(modrm); |
| 1284 | STORE_RM16(modrm, src); |
| 1285 | CYCLES(CYCLES_MOV_REG_REG); |
| 1286 | } else { |
| 1287 | UINT32 ea = GetEA(modrm,1); |
| 1288 | src = LOAD_REG16(modrm); |
| 1289 | WRITE16(ea, src); |
| 1290 | CYCLES(CYCLES_MOV_REG_MEM); |
| 1291 | } |
| 1292 | } |
| 1293 | |
| 1294 | void i386_device::i386_mov_r16_rm16() // Opcode 0x8b |
| 1295 | { |
| 1296 | UINT16 src; |
| 1297 | UINT8 modrm = FETCH(); |
| 1298 | if( modrm >= 0xc0 ) { |
| 1299 | src = LOAD_RM16(modrm); |
| 1300 | STORE_REG16(modrm, src); |
| 1301 | CYCLES(CYCLES_MOV_REG_REG); |
| 1302 | } else { |
| 1303 | UINT32 ea = GetEA(modrm,0); |
| 1304 | src = READ16(ea); |
| 1305 | STORE_REG16(modrm, src); |
| 1306 | CYCLES(CYCLES_MOV_MEM_REG); |
| 1307 | } |
| 1308 | } |
| 1309 | |
| 1310 | void i386_device::i386_mov_rm16_i16() // Opcode 0xc7 |
| 1311 | { |
| 1312 | UINT8 modrm = FETCH(); |
| 1313 | if( modrm >= 0xc0 ) { |
| 1314 | UINT16 value = FETCH16(); |
| 1315 | STORE_RM16(modrm, value); |
| 1316 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1317 | } else { |
| 1318 | UINT32 ea = GetEA(modrm,1); |
| 1319 | UINT16 value = FETCH16(); |
| 1320 | WRITE16(ea, value); |
| 1321 | CYCLES(CYCLES_MOV_IMM_MEM); |
| 1322 | } |
| 1323 | } |
| 1324 | |
| 1325 | void i386_device::i386_mov_ax_m16() // Opcode 0xa1 |
| 1326 | { |
| 1327 | UINT32 offset, ea; |
| 1328 | if( m_address_size ) { |
| 1329 | offset = FETCH32(); |
| 1330 | } else { |
| 1331 | offset = FETCH16(); |
| 1332 | } |
| 1333 | /* TODO: Not sure if this is correct... */ |
| 1334 | if( m_segment_prefix ) { |
| 1335 | ea = i386_translate(m_segment_override, offset, 0 ); |
| 1336 | } else { |
| 1337 | ea = i386_translate(DS, offset, 0 ); |
| 1338 | } |
| 1339 | REG16(AX) = READ16(ea); |
| 1340 | CYCLES(CYCLES_MOV_MEM_ACC); |
| 1341 | } |
| 1342 | |
| 1343 | void i386_device::i386_mov_m16_ax() // Opcode 0xa3 |
| 1344 | { |
| 1345 | UINT32 offset, ea; |
| 1346 | if( m_address_size ) { |
| 1347 | offset = FETCH32(); |
| 1348 | } else { |
| 1349 | offset = FETCH16(); |
| 1350 | } |
| 1351 | /* TODO: Not sure if this is correct... */ |
| 1352 | if( m_segment_prefix ) { |
| 1353 | ea = i386_translate(m_segment_override, offset, 1 ); |
| 1354 | } else { |
| 1355 | ea = i386_translate(DS, offset, 1 ); |
| 1356 | } |
| 1357 | WRITE16(ea, REG16(AX) ); |
| 1358 | CYCLES(CYCLES_MOV_ACC_MEM); |
| 1359 | } |
| 1360 | |
| 1361 | void i386_device::i386_mov_ax_i16() // Opcode 0xb8 |
| 1362 | { |
| 1363 | REG16(AX) = FETCH16(); |
| 1364 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1365 | } |
| 1366 | |
| 1367 | void i386_device::i386_mov_cx_i16() // Opcode 0xb9 |
| 1368 | { |
| 1369 | REG16(CX) = FETCH16(); |
| 1370 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1371 | } |
| 1372 | |
| 1373 | void i386_device::i386_mov_dx_i16() // Opcode 0xba |
| 1374 | { |
| 1375 | REG16(DX) = FETCH16(); |
| 1376 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1377 | } |
| 1378 | |
| 1379 | void i386_device::i386_mov_bx_i16() // Opcode 0xbb |
| 1380 | { |
| 1381 | REG16(BX) = FETCH16(); |
| 1382 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1383 | } |
| 1384 | |
| 1385 | void i386_device::i386_mov_sp_i16() // Opcode 0xbc |
| 1386 | { |
| 1387 | REG16(SP) = FETCH16(); |
| 1388 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1389 | } |
| 1390 | |
| 1391 | void i386_device::i386_mov_bp_i16() // Opcode 0xbd |
| 1392 | { |
| 1393 | REG16(BP) = FETCH16(); |
| 1394 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1395 | } |
| 1396 | |
| 1397 | void i386_device::i386_mov_si_i16() // Opcode 0xbe |
| 1398 | { |
| 1399 | REG16(SI) = FETCH16(); |
| 1400 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1401 | } |
| 1402 | |
| 1403 | void i386_device::i386_mov_di_i16() // Opcode 0xbf |
| 1404 | { |
| 1405 | REG16(DI) = FETCH16(); |
| 1406 | CYCLES(CYCLES_MOV_IMM_REG); |
| 1407 | } |
| 1408 | |
| 1409 | void i386_device::i386_movsw() // Opcode 0xa5 |
| 1410 | { |
| 1411 | UINT32 eas, ead; |
| 1412 | UINT16 v; |
| 1413 | if( m_segment_prefix ) { |
| 1414 | eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1415 | } else { |
| 1416 | eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 ); |
| 1417 | } |
| 1418 | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 1419 | v = READ16(eas); |
| 1420 | WRITE16(ead, v); |
| 1421 | BUMP_SI(2); |
| 1422 | BUMP_DI(2); |
| 1423 | CYCLES(CYCLES_MOVS); |
| 1424 | } |
| 1425 | |
| 1426 | void i386_device::i386_movsx_r16_rm8() // Opcode 0x0f be |
| 1427 | { |
| 1428 | UINT8 modrm = FETCH(); |
| 1429 | if( modrm >= 0xc0 ) { |
| 1430 | INT16 src = (INT8)LOAD_RM8(modrm); |
| 1431 | STORE_REG16(modrm, src); |
| 1432 | CYCLES(CYCLES_MOVSX_REG_REG); |
| 1433 | } else { |
| 1434 | UINT32 ea = GetEA(modrm,0); |
| 1435 | INT16 src = (INT8)READ8(ea); |
| 1436 | STORE_REG16(modrm, src); |
| 1437 | CYCLES(CYCLES_MOVSX_MEM_REG); |
| 1438 | } |
| 1439 | } |
| 1440 | |
| 1441 | void i386_device::i386_movzx_r16_rm8() // Opcode 0x0f b6 |
| 1442 | { |
| 1443 | UINT8 modrm = FETCH(); |
| 1444 | if( modrm >= 0xc0 ) { |
| 1445 | UINT16 src = (UINT8)LOAD_RM8(modrm); |
| 1446 | STORE_REG16(modrm, src); |
| 1447 | CYCLES(CYCLES_MOVZX_REG_REG); |
| 1448 | } else { |
| 1449 | UINT32 ea = GetEA(modrm,0); |
| 1450 | UINT16 src = (UINT8)READ8(ea); |
| 1451 | STORE_REG16(modrm, src); |
| 1452 | CYCLES(CYCLES_MOVZX_MEM_REG); |
| 1453 | } |
| 1454 | } |
| 1455 | |
| 1456 | void i386_device::i386_or_rm16_r16() // Opcode 0x09 |
| 1457 | { |
| 1458 | UINT16 src, dst; |
| 1459 | UINT8 modrm = FETCH(); |
| 1460 | if( modrm >= 0xc0 ) { |
| 1461 | src = LOAD_REG16(modrm); |
| 1462 | dst = LOAD_RM16(modrm); |
| 1463 | dst = OR16(dst, src); |
| 1464 | STORE_RM16(modrm, dst); |
| 1465 | CYCLES(CYCLES_ALU_REG_REG); |
| 1466 | } else { |
| 1467 | UINT32 ea = GetEA(modrm,1); |
| 1468 | src = LOAD_REG16(modrm); |
| 1469 | dst = READ16(ea); |
| 1470 | dst = OR16(dst, src); |
| 1471 | WRITE16(ea, dst); |
| 1472 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1473 | } |
| 1474 | } |
| 1475 | |
| 1476 | void i386_device::i386_or_r16_rm16() // Opcode 0x0b |
| 1477 | { |
| 1478 | UINT16 src, dst; |
| 1479 | UINT8 modrm = FETCH(); |
| 1480 | if( modrm >= 0xc0 ) { |
| 1481 | src = LOAD_RM16(modrm); |
| 1482 | dst = LOAD_REG16(modrm); |
| 1483 | dst = OR16(dst, src); |
| 1484 | STORE_REG16(modrm, dst); |
| 1485 | CYCLES(CYCLES_ALU_REG_REG); |
| 1486 | } else { |
| 1487 | UINT32 ea = GetEA(modrm,0); |
| 1488 | src = READ16(ea); |
| 1489 | dst = LOAD_REG16(modrm); |
| 1490 | dst = OR16(dst, src); |
| 1491 | STORE_REG16(modrm, dst); |
| 1492 | CYCLES(CYCLES_ALU_MEM_REG); |
| 1493 | } |
| 1494 | } |
| 1495 | |
| 1496 | void i386_device::i386_or_ax_i16() // Opcode 0x0d |
| 1497 | { |
| 1498 | UINT16 src, dst; |
| 1499 | src = FETCH16(); |
| 1500 | dst = REG16(AX); |
| 1501 | dst = OR16(dst, src); |
| 1502 | REG16(AX) = dst; |
| 1503 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1504 | } |
| 1505 | |
| 1506 | void i386_device::i386_out_ax_i8() // Opcode 0xe7 |
| 1507 | { |
| 1508 | UINT16 port = FETCH(); |
| 1509 | UINT16 data = REG16(AX); |
| 1510 | WRITEPORT16(port, data); |
| 1511 | CYCLES(CYCLES_OUT_VAR); |
| 1512 | } |
| 1513 | |
| 1514 | void i386_device::i386_out_ax_dx() // Opcode 0xef |
| 1515 | { |
| 1516 | UINT16 port = REG16(DX); |
| 1517 | UINT16 data = REG16(AX); |
| 1518 | WRITEPORT16(port, data); |
| 1519 | CYCLES(CYCLES_OUT); |
| 1520 | } |
| 1521 | |
| 1522 | void i386_device::i386_pop_ax() // Opcode 0x58 |
| 1523 | { |
| 1524 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1525 | if(i386_limit_check(SS,offset+1) == 0) |
| 1526 | REG16(AX) = POP16(); |
| 1527 | else |
| 1528 | FAULT(FAULT_SS,0) |
| 1529 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1530 | } |
| 1531 | |
| 1532 | void i386_device::i386_pop_cx() // Opcode 0x59 |
| 1533 | { |
| 1534 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1535 | if(i386_limit_check(SS,offset+1) == 0) |
| 1536 | REG16(CX) = POP16(); |
| 1537 | else |
| 1538 | FAULT(FAULT_SS,0) |
| 1539 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1540 | } |
| 1541 | |
| 1542 | void i386_device::i386_pop_dx() // Opcode 0x5a |
| 1543 | { |
| 1544 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1545 | if(i386_limit_check(SS,offset+1) == 0) |
| 1546 | REG16(DX) = POP16(); |
| 1547 | else |
| 1548 | FAULT(FAULT_SS,0) |
| 1549 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1550 | } |
| 1551 | |
| 1552 | void i386_device::i386_pop_bx() // Opcode 0x5b |
| 1553 | { |
| 1554 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1555 | if(i386_limit_check(SS,offset+1) == 0) |
| 1556 | REG16(BX) = POP16(); |
| 1557 | else |
| 1558 | FAULT(FAULT_SS,0) |
| 1559 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1560 | } |
| 1561 | |
| 1562 | void i386_device::i386_pop_sp() // Opcode 0x5c |
| 1563 | { |
| 1564 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1565 | if(i386_limit_check(SS,offset+1) == 0) |
| 1566 | REG16(SP) = POP16(); |
| 1567 | else |
| 1568 | FAULT(FAULT_SS,0) |
| 1569 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1570 | } |
| 1571 | |
| 1572 | void i386_device::i386_pop_bp() // Opcode 0x5d |
| 1573 | { |
| 1574 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1575 | if(i386_limit_check(SS,offset+1) == 0) |
| 1576 | REG16(BP) = POP16(); |
| 1577 | else |
| 1578 | FAULT(FAULT_SS,0) |
| 1579 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1580 | } |
| 1581 | |
| 1582 | void i386_device::i386_pop_si() // Opcode 0x5e |
| 1583 | { |
| 1584 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1585 | if(i386_limit_check(SS,offset+1) == 0) |
| 1586 | REG16(SI) = POP16(); |
| 1587 | else |
| 1588 | FAULT(FAULT_SS,0) |
| 1589 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1590 | } |
| 1591 | |
| 1592 | void i386_device::i386_pop_di() // Opcode 0x5f |
| 1593 | { |
| 1594 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1595 | if(i386_limit_check(SS,offset+1) == 0) |
| 1596 | REG16(DI) = POP16(); |
| 1597 | else |
| 1598 | FAULT(FAULT_SS,0) |
| 1599 | CYCLES(CYCLES_POP_REG_SHORT); |
| 1600 | } |
| 1601 | |
| 1602 | bool i386_device::i386_pop_seg16(int segment) |
| 1603 | { |
| 1604 | UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1605 | UINT16 value; |
| 1606 | bool fault; |
| 1607 | if(i386_limit_check(SS,offset+1) == 0) |
| 1608 | { |
| 1609 | ea = i386_translate(SS, offset, 0); |
| 1610 | value = READ16(ea); |
| 1611 | i386_sreg_load(value, segment, &fault); |
| 1612 | if(fault) return false; |
| 1613 | if(STACK_32BIT) |
| 1614 | REG32(ESP) = offset + 2; |
| 1615 | else |
| 1616 | REG16(SP) = offset + 2; |
| 1617 | } |
| 1618 | else |
| 1619 | { |
| 1620 | m_ext = 1; |
| 1621 | i386_trap_with_error(FAULT_SS,0,0,0); |
| 1622 | return false; |
| 1623 | } |
| 1624 | CYCLES(CYCLES_POP_SREG); |
| 1625 | return true; |
| 1626 | } |
| 1627 | |
| 1628 | void i386_device::i386_pop_ds16() // Opcode 0x1f |
| 1629 | { |
| 1630 | i386_pop_seg16(DS); |
| 1631 | } |
| 1632 | |
| 1633 | void i386_device::i386_pop_es16() // Opcode 0x07 |
| 1634 | { |
| 1635 | i386_pop_seg16(ES); |
| 1636 | } |
| 1637 | |
| 1638 | void i386_device::i386_pop_fs16() // Opcode 0x0f a1 |
| 1639 | { |
| 1640 | i386_pop_seg16(FS); |
| 1641 | } |
| 1642 | |
| 1643 | void i386_device::i386_pop_gs16() // Opcode 0x0f a9 |
| 1644 | { |
| 1645 | i386_pop_seg16(GS); |
| 1646 | } |
| 1647 | |
| 1648 | void i386_device::i386_pop_ss16() // Opcode 0x17 |
| 1649 | { |
| 1650 | if(!i386_pop_seg16(SS)) return; |
| 1651 | if(m_IF != 0) // if external interrupts are enabled |
| 1652 | { |
| 1653 | m_IF = 0; // reset IF for the next instruction |
| 1654 | m_delayed_interrupt_enable = 1; |
| 1655 | } |
| 1656 | } |
| 1657 | |
| 1658 | void i386_device::i386_pop_rm16() // Opcode 0x8f |
| 1659 | { |
| 1660 | UINT8 modrm = FETCH(); |
| 1661 | UINT16 value; |
| 1662 | UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1663 | |
| 1664 | if(i386_limit_check(SS,offset+1) == 0) |
| 1665 | { |
| 1666 | UINT32 temp_sp = REG32(ESP); |
| 1667 | value = POP16(); |
| 1668 | |
| 1669 | if( modrm >= 0xc0 ) { |
| 1670 | STORE_RM16(modrm, value); |
| 1671 | } else { |
| 1672 | ea = GetEA(modrm,1); |
| 1673 | try |
| 1674 | { |
| 1675 | WRITE16(ea, value); |
| 1676 | } |
| 1677 | catch(UINT64 e) |
| 1678 | { |
| 1679 | REG32(ESP) = temp_sp; |
| 1680 | throw e; |
| 1681 | } |
| 1682 | } |
| 1683 | } |
| 1684 | else |
| 1685 | FAULT(FAULT_SS,0) |
| 1686 | CYCLES(CYCLES_POP_RM); |
| 1687 | } |
| 1688 | |
| 1689 | void i386_device::i386_popa() // Opcode 0x61 |
| 1690 | { |
| 1691 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1692 | |
| 1693 | if(i386_limit_check(SS,offset+15) == 0) |
| 1694 | { |
| 1695 | REG16(DI) = POP16(); |
| 1696 | REG16(SI) = POP16(); |
| 1697 | REG16(BP) = POP16(); |
| 1698 | REG16(SP) += 2; |
| 1699 | REG16(BX) = POP16(); |
| 1700 | REG16(DX) = POP16(); |
| 1701 | REG16(CX) = POP16(); |
| 1702 | REG16(AX) = POP16(); |
| 1703 | } |
| 1704 | else |
| 1705 | FAULT(FAULT_SS,0) |
| 1706 | CYCLES(CYCLES_POPA); |
| 1707 | } |
| 1708 | |
| 1709 | void i386_device::i386_popf() // Opcode 0x9d |
| 1710 | { |
| 1711 | UINT32 value; |
| 1712 | UINT32 current = get_flags(); |
| 1713 | UINT8 IOPL = (current >> 12) & 0x03; |
| 1714 | UINT32 mask = 0x7fd5; |
| 1715 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1716 | |
| 1717 | // IOPL can only change if CPL is 0 |
| 1718 | if(m_CPL != 0) |
| 1719 | mask &= ~0x00003000; |
| 1720 | |
| 1721 | // IF can only change if CPL is at least as privileged as IOPL |
| 1722 | if(m_CPL > IOPL) |
| 1723 | mask &= ~0x00000200; |
| 1724 | |
| 1725 | if(V8086_MODE) |
| 1726 | { |
| 1727 | if(IOPL < 3) |
| 1728 | { |
| 1729 | logerror("POPFD(%08x): IOPL < 3 while in V86 mode.\n",m_pc); |
| 1730 | FAULT(FAULT_GP,0) // #GP(0) |
| 1731 | } |
| 1732 | mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode |
| 1733 | } |
| 1734 | |
| 1735 | if(i386_limit_check(SS,offset+1) == 0) |
| 1736 | { |
| 1737 | value = POP16(); |
| 1738 | set_flags((current & ~mask) | (value & mask)); // mask out reserved bits |
| 1739 | } |
| 1740 | else |
| 1741 | FAULT(FAULT_SS,0) |
| 1742 | CYCLES(CYCLES_POPF); |
| 1743 | } |
| 1744 | |
| 1745 | void i386_device::i386_push_ax() // Opcode 0x50 |
| 1746 | { |
| 1747 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1748 | if(i386_limit_check(SS,offset-2) == 0) |
| 1749 | PUSH16(REG16(AX) ); |
| 1750 | else |
| 1751 | FAULT(FAULT_SS,0) |
| 1752 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1753 | } |
| 1754 | |
| 1755 | void i386_device::i386_push_cx() // Opcode 0x51 |
| 1756 | { |
| 1757 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1758 | if(i386_limit_check(SS,offset-2) == 0) |
| 1759 | PUSH16(REG16(CX) ); |
| 1760 | else |
| 1761 | FAULT(FAULT_SS,0) |
| 1762 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1763 | } |
| 1764 | |
| 1765 | void i386_device::i386_push_dx() // Opcode 0x52 |
| 1766 | { |
| 1767 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1768 | if(i386_limit_check(SS,offset-2) == 0) |
| 1769 | PUSH16(REG16(DX) ); |
| 1770 | else |
| 1771 | FAULT(FAULT_SS,0) |
| 1772 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1773 | } |
| 1774 | |
| 1775 | void i386_device::i386_push_bx() // Opcode 0x53 |
| 1776 | { |
| 1777 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1778 | if(i386_limit_check(SS,offset-2) == 0) |
| 1779 | PUSH16(REG16(BX) ); |
| 1780 | else |
| 1781 | FAULT(FAULT_SS,0) |
| 1782 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1783 | } |
| 1784 | |
| 1785 | void i386_device::i386_push_sp() // Opcode 0x54 |
| 1786 | { |
| 1787 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1788 | if(i386_limit_check(SS,offset-2) == 0) |
| 1789 | PUSH16(REG16(SP) ); |
| 1790 | else |
| 1791 | FAULT(FAULT_SS,0) |
| 1792 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1793 | } |
| 1794 | |
| 1795 | void i386_device::i386_push_bp() // Opcode 0x55 |
| 1796 | { |
| 1797 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1798 | if(i386_limit_check(SS,offset-2) == 0) |
| 1799 | PUSH16(REG16(BP) ); |
| 1800 | else |
| 1801 | FAULT(FAULT_SS,0) |
| 1802 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1803 | } |
| 1804 | |
| 1805 | void i386_device::i386_push_si() // Opcode 0x56 |
| 1806 | { |
| 1807 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1808 | if(i386_limit_check(SS,offset-2) == 0) |
| 1809 | PUSH16(REG16(SI) ); |
| 1810 | else |
| 1811 | FAULT(FAULT_SS,0) |
| 1812 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1813 | } |
| 1814 | |
| 1815 | void i386_device::i386_push_di() // Opcode 0x57 |
| 1816 | { |
| 1817 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1818 | if(i386_limit_check(SS,offset-2) == 0) |
| 1819 | PUSH16(REG16(DI) ); |
| 1820 | else |
| 1821 | FAULT(FAULT_SS,0) |
| 1822 | CYCLES(CYCLES_PUSH_REG_SHORT); |
| 1823 | } |
| 1824 | |
| 1825 | void i386_device::i386_push_cs16() // Opcode 0x0e |
| 1826 | { |
| 1827 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1828 | if(i386_limit_check(SS,offset-2) == 0) |
| 1829 | PUSH16(m_sreg[CS].selector ); |
| 1830 | else |
| 1831 | FAULT(FAULT_SS,0) |
| 1832 | CYCLES(CYCLES_PUSH_SREG); |
| 1833 | } |
| 1834 | |
| 1835 | void i386_device::i386_push_ds16() // Opcode 0x1e |
| 1836 | { |
| 1837 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1838 | if(i386_limit_check(SS,offset-2) == 0) |
| 1839 | PUSH16(m_sreg[DS].selector ); |
| 1840 | else |
| 1841 | FAULT(FAULT_SS,0) |
| 1842 | CYCLES(CYCLES_PUSH_SREG); |
| 1843 | } |
| 1844 | |
| 1845 | void i386_device::i386_push_es16() // Opcode 0x06 |
| 1846 | { |
| 1847 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1848 | if(i386_limit_check(SS,offset-2) == 0) |
| 1849 | PUSH16(m_sreg[ES].selector ); |
| 1850 | else |
| 1851 | FAULT(FAULT_SS,0) |
| 1852 | CYCLES(CYCLES_PUSH_SREG); |
| 1853 | } |
| 1854 | |
| 1855 | void i386_device::i386_push_fs16() // Opcode 0x0f a0 |
| 1856 | { |
| 1857 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1858 | if(i386_limit_check(SS,offset-2) == 0) |
| 1859 | PUSH16(m_sreg[FS].selector ); |
| 1860 | else |
| 1861 | FAULT(FAULT_SS,0) |
| 1862 | CYCLES(CYCLES_PUSH_SREG); |
| 1863 | } |
| 1864 | |
| 1865 | void i386_device::i386_push_gs16() // Opcode 0x0f a8 |
| 1866 | { |
| 1867 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1868 | if(i386_limit_check(SS,offset-2) == 0) |
| 1869 | PUSH16(m_sreg[GS].selector ); |
| 1870 | else |
| 1871 | FAULT(FAULT_SS,0) |
| 1872 | CYCLES(CYCLES_PUSH_SREG); |
| 1873 | } |
| 1874 | |
| 1875 | void i386_device::i386_push_ss16() // Opcode 0x16 |
| 1876 | { |
| 1877 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1878 | if(i386_limit_check(SS,offset-2) == 0) |
| 1879 | PUSH16(m_sreg[SS].selector ); |
| 1880 | else |
| 1881 | FAULT(FAULT_SS,0) |
| 1882 | CYCLES(CYCLES_PUSH_SREG); |
| 1883 | } |
| 1884 | |
| 1885 | void i386_device::i386_push_i16() // Opcode 0x68 |
| 1886 | { |
| 1887 | UINT16 value = FETCH16(); |
| 1888 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1889 | if(i386_limit_check(SS,offset-2) == 0) |
| 1890 | PUSH16(value); |
| 1891 | else |
| 1892 | FAULT(FAULT_SS,0) |
| 1893 | CYCLES(CYCLES_PUSH_IMM); |
| 1894 | } |
| 1895 | |
| 1896 | void i386_device::i386_pusha() // Opcode 0x60 |
| 1897 | { |
| 1898 | UINT16 temp = REG16(SP); |
| 1899 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1900 | if(i386_limit_check(SS,offset-16) == 0) |
| 1901 | { |
| 1902 | PUSH16(REG16(AX) ); |
| 1903 | PUSH16(REG16(CX) ); |
| 1904 | PUSH16(REG16(DX) ); |
| 1905 | PUSH16(REG16(BX) ); |
| 1906 | PUSH16(temp ); |
| 1907 | PUSH16(REG16(BP) ); |
| 1908 | PUSH16(REG16(SI) ); |
| 1909 | PUSH16(REG16(DI) ); |
| 1910 | } |
| 1911 | else |
| 1912 | FAULT(FAULT_SS,0) |
| 1913 | CYCLES(CYCLES_PUSHA); |
| 1914 | } |
| 1915 | |
| 1916 | void i386_device::i386_pushf() // Opcode 0x9c |
| 1917 | { |
| 1918 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| 1919 | if(i386_limit_check(SS,offset-2) == 0) |
| 1920 | PUSH16(get_flags() & 0xffff ); |
| 1921 | else |
| 1922 | FAULT(FAULT_SS,0) |
| 1923 | CYCLES(CYCLES_PUSHF); |
| 1924 | } |
| 1925 | |
| 1926 | void i386_device::i386_ret_near16_i16() // Opcode 0xc2 |
| 1927 | { |
| 1928 | INT16 disp = FETCH16(); |
| 1929 | m_eip = POP16(); |
| 1930 | REG16(SP) += disp; |
| 1931 | CHANGE_PC(m_eip); |
| 1932 | CYCLES(CYCLES_RET_IMM); /* TODO: Timing = 10 + m */ |
| 1933 | } |
| 1934 | |
| 1935 | void i386_device::i386_ret_near16() // Opcode 0xc3 |
| 1936 | { |
| 1937 | m_eip = POP16(); |
| 1938 | CHANGE_PC(m_eip); |
| 1939 | CYCLES(CYCLES_RET); /* TODO: Timing = 10 + m */ |
| 1940 | } |
| 1941 | |
| 1942 | void i386_device::i386_sbb_rm16_r16() // Opcode 0x19 |
| 1943 | { |
| 1944 | UINT16 src, dst; |
| 1945 | UINT8 modrm = FETCH(); |
| 1946 | if( modrm >= 0xc0 ) { |
| 1947 | src = LOAD_REG16(modrm); |
| 1948 | dst = LOAD_RM16(modrm); |
| 1949 | dst = SBB16(dst, src, m_CF); |
| 1950 | STORE_RM16(modrm, dst); |
| 1951 | CYCLES(CYCLES_ALU_REG_REG); |
| 1952 | } else { |
| 1953 | UINT32 ea = GetEA(modrm,1); |
| 1954 | src = LOAD_REG16(modrm); |
| 1955 | dst = READ16(ea); |
| 1956 | dst = SBB16(dst, src, m_CF); |
| 1957 | WRITE16(ea, dst); |
| 1958 | CYCLES(CYCLES_ALU_REG_MEM); |
| 1959 | } |
| 1960 | } |
| 1961 | |
| 1962 | void i386_device::i386_sbb_r16_rm16() // Opcode 0x1b |
| 1963 | { |
| 1964 | UINT16 src, dst; |
| 1965 | UINT8 modrm = FETCH(); |
| 1966 | if( modrm >= 0xc0 ) { |
| 1967 | src = LOAD_RM16(modrm); |
| 1968 | dst = LOAD_REG16(modrm); |
| 1969 | dst = SBB16(dst, src, m_CF); |
| 1970 | STORE_REG16(modrm, dst); |
| 1971 | CYCLES(CYCLES_ALU_REG_REG); |
| 1972 | } else { |
| 1973 | UINT32 ea = GetEA(modrm,0); |
| 1974 | src = READ16(ea); |
| 1975 | dst = LOAD_REG16(modrm); |
| 1976 | dst = SBB16(dst, src, m_CF); |
| 1977 | STORE_REG16(modrm, dst); |
| 1978 | CYCLES(CYCLES_ALU_MEM_REG); |
| 1979 | } |
| 1980 | } |
| 1981 | |
| 1982 | void i386_device::i386_sbb_ax_i16() // Opcode 0x1d |
| 1983 | { |
| 1984 | UINT16 src, dst; |
| 1985 | src = FETCH16(); |
| 1986 | dst = REG16(AX); |
| 1987 | dst = SBB16(dst, src, m_CF); |
| 1988 | REG16(AX) = dst; |
| 1989 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 1990 | } |
| 1991 | |
| 1992 | void i386_device::i386_scasw() // Opcode 0xaf |
| 1993 | { |
| 1994 | UINT32 eas; |
| 1995 | UINT16 src, dst; |
| 1996 | eas = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 ); |
| 1997 | src = READ16(eas); |
| 1998 | dst = REG16(AX); |
| 1999 | SUB16(dst, src); |
| 2000 | BUMP_DI(2); |
| 2001 | CYCLES(CYCLES_SCAS); |
| 2002 | } |
| 2003 | |
| 2004 | void i386_device::i386_shld16_i8() // Opcode 0x0f a4 |
| 2005 | { |
| 2006 | UINT8 modrm = FETCH(); |
| 2007 | if( modrm >= 0xc0 ) { |
| 2008 | UINT16 dst = LOAD_RM16(modrm); |
| 2009 | UINT16 upper = LOAD_REG16(modrm); |
| 2010 | UINT8 shift = FETCH(); |
| 2011 | shift &= 31; |
| 2012 | if( shift == 0 ) { |
| 2013 | } else if( shift > 15 ) { |
| 2014 | m_CF = (upper & (1 << (16-shift))) ? 1 : 0; |
| 2015 | // ppro and above should be (dst >> (32-shift)) |
| 2016 | dst = (upper << (shift-16)) | (upper >> (32-shift)); |
| 2017 | m_OF = m_CF ^ (dst >> 15); |
| 2018 | SetSZPF16(dst); |
| 2019 | } else { |
| 2020 | m_CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2021 | dst = (dst << shift) | (upper >> (16-shift)); |
| 2022 | m_OF = m_CF ^ (dst >> 15); |
| 2023 | SetSZPF16(dst); |
| 2024 | } |
| 2025 | STORE_RM16(modrm, dst); |
| 2026 | CYCLES(CYCLES_SHLD_REG); |
| 2027 | } else { |
| 2028 | UINT32 ea = GetEA(modrm,1); |
| 2029 | UINT16 dst = READ16(ea); |
| 2030 | UINT16 upper = LOAD_REG16(modrm); |
| 2031 | UINT8 shift = FETCH(); |
| 2032 | shift &= 31; |
| 2033 | if( shift == 0 ) { |
| 2034 | } else if( shift > 15 ) { |
| 2035 | m_CF = (upper & (1 << (16-shift))) ? 1 : 0; |
| 2036 | dst = (upper << (shift-16)) | (upper >> (32-shift)); |
| 2037 | m_OF = m_CF ^ (dst >> 15); |
| 2038 | SetSZPF16(dst); |
| 2039 | } else { |
| 2040 | m_CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2041 | dst = (dst << shift) | (upper >> (16-shift)); |
| 2042 | m_OF = m_CF ^ (dst >> 15); |
| 2043 | SetSZPF16(dst); |
| 2044 | } |
| 2045 | WRITE16(ea, dst); |
| 2046 | CYCLES(CYCLES_SHLD_MEM); |
| 2047 | } |
| 2048 | } |
| 2049 | |
| 2050 | void i386_device::i386_shld16_cl() // Opcode 0x0f a5 |
| 2051 | { |
| 2052 | UINT8 modrm = FETCH(); |
| 2053 | if( modrm >= 0xc0 ) { |
| 2054 | UINT16 dst = LOAD_RM16(modrm); |
| 2055 | UINT16 upper = LOAD_REG16(modrm); |
| 2056 | UINT8 shift = REG8(CL); |
| 2057 | shift &= 31; |
| 2058 | if( shift == 0 ) { |
| 2059 | } else if( shift > 15 ) { |
| 2060 | m_CF = (upper & (1 << (16-shift))) ? 1 : 0; |
| 2061 | dst = (upper << (shift-16)) | (upper >> (32-shift)); |
| 2062 | m_OF = m_CF ^ (dst >> 15); |
| 2063 | SetSZPF16(dst); |
| 2064 | } else { |
| 2065 | m_CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2066 | dst = (dst << shift) | (upper >> (16-shift)); |
| 2067 | m_OF = m_CF ^ (dst >> 15); |
| 2068 | SetSZPF16(dst); |
| 2069 | } |
| 2070 | STORE_RM16(modrm, dst); |
| 2071 | CYCLES(CYCLES_SHLD_REG); |
| 2072 | } else { |
| 2073 | UINT32 ea = GetEA(modrm,1); |
| 2074 | UINT16 dst = READ16(ea); |
| 2075 | UINT16 upper = LOAD_REG16(modrm); |
| 2076 | UINT8 shift = REG8(CL); |
| 2077 | shift &= 31; |
| 2078 | if( shift == 0 ) { |
| 2079 | } else if( shift > 15 ) { |
| 2080 | m_CF = (upper & (1 << (16-shift))) ? 1 : 0; |
| 2081 | dst = (upper << (shift-16)) | (upper >> (32-shift)); |
| 2082 | m_OF = m_CF ^ (dst >> 15); |
| 2083 | SetSZPF16(dst); |
| 2084 | } else { |
| 2085 | m_CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2086 | dst = (dst << shift) | (upper >> (16-shift)); |
| 2087 | m_OF = m_CF ^ (dst >> 15); |
| 2088 | SetSZPF16(dst); |
| 2089 | } |
| 2090 | WRITE16(ea, dst); |
| 2091 | CYCLES(CYCLES_SHLD_MEM); |
| 2092 | } |
| 2093 | } |
| 2094 | |
| 2095 | void i386_device::i386_shrd16_i8() // Opcode 0x0f ac |
| 2096 | { |
| 2097 | UINT8 modrm = FETCH(); |
| 2098 | if( modrm >= 0xc0 ) { |
| 2099 | UINT16 dst = LOAD_RM16(modrm); |
| 2100 | UINT16 upper = LOAD_REG16(modrm); |
| 2101 | UINT8 shift = FETCH(); |
| 2102 | shift &= 31; |
| 2103 | if( shift == 0) { |
| 2104 | } else if( shift > 15 ) { |
| 2105 | m_CF = (upper & (1 << (shift-1))) ? 1 : 0; |
| 2106 | dst = (upper >> (shift-16)) | (upper << (32-shift)); |
| 2107 | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2108 | SetSZPF16(dst); |
| 2109 | } else { |
| 2110 | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 2111 | dst = (dst >> shift) | (upper << (16-shift)); |
| 2112 | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2113 | SetSZPF16(dst); |
| 2114 | } |
| 2115 | STORE_RM16(modrm, dst); |
| 2116 | CYCLES(CYCLES_SHRD_REG); |
| 2117 | } else { |
| 2118 | UINT32 ea = GetEA(modrm,1); |
| 2119 | UINT16 dst = READ16(ea); |
| 2120 | UINT16 upper = LOAD_REG16(modrm); |
| 2121 | UINT8 shift = FETCH(); |
| 2122 | shift &= 31; |
| 2123 | if( shift == 0) { |
| 2124 | } else if( shift > 15 ) { |
| 2125 | m_CF = (upper & (1 << (shift-1))) ? 1 : 0; |
| 2126 | dst = (upper >> (shift-16)) | (upper << (32-shift)); |
| 2127 | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2128 | SetSZPF16(dst); |
| 2129 | } else { |
| 2130 | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 2131 | dst = (dst >> shift) | (upper << (16-shift)); |
| 2132 | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2133 | SetSZPF16(dst); |
| 2134 | } |
| 2135 | WRITE16(ea, dst); |
| 2136 | CYCLES(CYCLES_SHRD_MEM); |
| 2137 | } |
| 2138 | } |
| 2139 | |
| 2140 | void i386_device::i386_shrd16_cl() // Opcode 0x0f ad |
| 2141 | { |
| 2142 | UINT8 modrm = FETCH(); |
| 2143 | if( modrm >= 0xc0 ) { |
| 2144 | UINT16 dst = LOAD_RM16(modrm); |
| 2145 | UINT16 upper = LOAD_REG16(modrm); |
| 2146 | UINT8 shift = REG8(CL); |
| 2147 | shift &= 31; |
| 2148 | if( shift == 0) { |
| 2149 | } else if( shift > 15 ) { |
| 2150 | m_CF = (upper & (1 << (shift-1))) ? 1 : 0; |
| 2151 | dst = (upper >> (shift-16)) | (upper << (32-shift)); |
| 2152 | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2153 | SetSZPF16(dst); |
| 2154 | } else { |
| 2155 | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 2156 | dst = (dst >> shift) | (upper << (16-shift)); |
| 2157 | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2158 | SetSZPF16(dst); |
| 2159 | } |
| 2160 | STORE_RM16(modrm, dst); |
| 2161 | CYCLES(CYCLES_SHRD_REG); |
| 2162 | } else { |
| 2163 | UINT32 ea = GetEA(modrm,1); |
| 2164 | UINT16 dst = READ16(ea); |
| 2165 | UINT16 upper = LOAD_REG16(modrm); |
| 2166 | UINT8 shift = REG8(CL); |
| 2167 | shift &= 31; |
| 2168 | if( shift == 0) { |
| 2169 | } else if( shift > 15 ) { |
| 2170 | m_CF = (upper & (1 << (shift-1))) ? 1 : 0; |
| 2171 | dst = (upper >> (shift-16)) | (upper << (32-shift)); |
| 2172 | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2173 | SetSZPF16(dst); |
| 2174 | } else { |
| 2175 | m_CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 2176 | dst = (dst >> shift) | (upper << (16-shift)); |
| 2177 | m_OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2178 | SetSZPF16(dst); |
| 2179 | } |
| 2180 | WRITE16(ea, dst); |
| 2181 | CYCLES(CYCLES_SHRD_MEM); |
| 2182 | } |
| 2183 | } |
| 2184 | |
| 2185 | void i386_device::i386_stosw() // Opcode 0xab |
| 2186 | { |
| 2187 | UINT32 ead; |
| 2188 | ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 ); |
| 2189 | WRITE16(ead, REG16(AX)); |
| 2190 | BUMP_DI(2); |
| 2191 | CYCLES(CYCLES_STOS); |
| 2192 | } |
| 2193 | |
| 2194 | void i386_device::i386_sub_rm16_r16() // Opcode 0x29 |
| 2195 | { |
| 2196 | UINT16 src, dst; |
| 2197 | UINT8 modrm = FETCH(); |
| 2198 | if( modrm >= 0xc0 ) { |
| 2199 | src = LOAD_REG16(modrm); |
| 2200 | dst = LOAD_RM16(modrm); |
| 2201 | dst = SUB16(dst, src); |
| 2202 | STORE_RM16(modrm, dst); |
| 2203 | CYCLES(CYCLES_ALU_REG_REG); |
| 2204 | } else { |
| 2205 | UINT32 ea = GetEA(modrm,1); |
| 2206 | src = LOAD_REG16(modrm); |
| 2207 | dst = READ16(ea); |
| 2208 | dst = SUB16(dst, src); |
| 2209 | WRITE16(ea, dst); |
| 2210 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2211 | } |
| 2212 | } |
| 2213 | |
| 2214 | void i386_device::i386_sub_r16_rm16() // Opcode 0x2b |
| 2215 | { |
| 2216 | UINT16 src, dst; |
| 2217 | UINT8 modrm = FETCH(); |
| 2218 | if( modrm >= 0xc0 ) { |
| 2219 | src = LOAD_RM16(modrm); |
| 2220 | dst = LOAD_REG16(modrm); |
| 2221 | dst = SUB16(dst, src); |
| 2222 | STORE_REG16(modrm, dst); |
| 2223 | CYCLES(CYCLES_ALU_REG_REG); |
| 2224 | } else { |
| 2225 | UINT32 ea = GetEA(modrm,0); |
| 2226 | src = READ16(ea); |
| 2227 | dst = LOAD_REG16(modrm); |
| 2228 | dst = SUB16(dst, src); |
| 2229 | STORE_REG16(modrm, dst); |
| 2230 | CYCLES(CYCLES_ALU_MEM_REG); |
| 2231 | } |
| 2232 | } |
| 2233 | |
| 2234 | void i386_device::i386_sub_ax_i16() // Opcode 0x2d |
| 2235 | { |
| 2236 | UINT16 src, dst; |
| 2237 | src = FETCH16(); |
| 2238 | dst = REG16(AX); |
| 2239 | dst = SUB16(dst, src); |
| 2240 | REG16(AX) = dst; |
| 2241 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 2242 | } |
| 2243 | |
| 2244 | void i386_device::i386_test_ax_i16() // Opcode 0xa9 |
| 2245 | { |
| 2246 | UINT16 src = FETCH16(); |
| 2247 | UINT16 dst = REG16(AX); |
| 2248 | dst = src & dst; |
| 2249 | SetSZPF16(dst); |
| 2250 | m_CF = 0; |
| 2251 | m_OF = 0; |
| 2252 | CYCLES(CYCLES_TEST_IMM_ACC); |
| 2253 | } |
| 2254 | |
| 2255 | void i386_device::i386_test_rm16_r16() // Opcode 0x85 |
| 2256 | { |
| 2257 | UINT16 src, dst; |
| 2258 | UINT8 modrm = FETCH(); |
| 2259 | if( modrm >= 0xc0 ) { |
| 2260 | src = LOAD_REG16(modrm); |
| 2261 | dst = LOAD_RM16(modrm); |
| 2262 | dst = src & dst; |
| 2263 | SetSZPF16(dst); |
| 2264 | m_CF = 0; |
| 2265 | m_OF = 0; |
| 2266 | CYCLES(CYCLES_TEST_REG_REG); |
| 2267 | } else { |
| 2268 | UINT32 ea = GetEA(modrm,0); |
| 2269 | src = LOAD_REG16(modrm); |
| 2270 | dst = READ16(ea); |
| 2271 | dst = src & dst; |
| 2272 | SetSZPF16(dst); |
| 2273 | m_CF = 0; |
| 2274 | m_OF = 0; |
| 2275 | CYCLES(CYCLES_TEST_REG_MEM); |
| 2276 | } |
| 2277 | } |
| 2278 | |
| 2279 | void i386_device::i386_xchg_ax_cx() // Opcode 0x91 |
| 2280 | { |
| 2281 | UINT16 temp; |
| 2282 | temp = REG16(AX); |
| 2283 | REG16(AX) = REG16(CX); |
| 2284 | REG16(CX) = temp; |
| 2285 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2286 | } |
| 2287 | |
| 2288 | void i386_device::i386_xchg_ax_dx() // Opcode 0x92 |
| 2289 | { |
| 2290 | UINT16 temp; |
| 2291 | temp = REG16(AX); |
| 2292 | REG16(AX) = REG16(DX); |
| 2293 | REG16(DX) = temp; |
| 2294 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2295 | } |
| 2296 | |
| 2297 | void i386_device::i386_xchg_ax_bx() // Opcode 0x93 |
| 2298 | { |
| 2299 | UINT16 temp; |
| 2300 | temp = REG16(AX); |
| 2301 | REG16(AX) = REG16(BX); |
| 2302 | REG16(BX) = temp; |
| 2303 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2304 | } |
| 2305 | |
| 2306 | void i386_device::i386_xchg_ax_sp() // Opcode 0x94 |
| 2307 | { |
| 2308 | UINT16 temp; |
| 2309 | temp = REG16(AX); |
| 2310 | REG16(AX) = REG16(SP); |
| 2311 | REG16(SP) = temp; |
| 2312 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2313 | } |
| 2314 | |
| 2315 | void i386_device::i386_xchg_ax_bp() // Opcode 0x95 |
| 2316 | { |
| 2317 | UINT16 temp; |
| 2318 | temp = REG16(AX); |
| 2319 | REG16(AX) = REG16(BP); |
| 2320 | REG16(BP) = temp; |
| 2321 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2322 | } |
| 2323 | |
| 2324 | void i386_device::i386_xchg_ax_si() // Opcode 0x96 |
| 2325 | { |
| 2326 | UINT16 temp; |
| 2327 | temp = REG16(AX); |
| 2328 | REG16(AX) = REG16(SI); |
| 2329 | REG16(SI) = temp; |
| 2330 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2331 | } |
| 2332 | |
| 2333 | void i386_device::i386_xchg_ax_di() // Opcode 0x97 |
| 2334 | { |
| 2335 | UINT16 temp; |
| 2336 | temp = REG16(AX); |
| 2337 | REG16(AX) = REG16(DI); |
| 2338 | REG16(DI) = temp; |
| 2339 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2340 | } |
| 2341 | |
| 2342 | void i386_device::i386_xchg_r16_rm16() // Opcode 0x87 |
| 2343 | { |
| 2344 | UINT8 modrm = FETCH(); |
| 2345 | if( modrm >= 0xc0 ) { |
| 2346 | UINT16 src = LOAD_RM16(modrm); |
| 2347 | UINT16 dst = LOAD_REG16(modrm); |
| 2348 | STORE_REG16(modrm, src); |
| 2349 | STORE_RM16(modrm, dst); |
| 2350 | CYCLES(CYCLES_XCHG_REG_REG); |
| 2351 | } else { |
| 2352 | UINT32 ea = GetEA(modrm,1); |
| 2353 | UINT16 src = READ16(ea); |
| 2354 | UINT16 dst = LOAD_REG16(modrm); |
| 2355 | STORE_REG16(modrm, src); |
| 2356 | WRITE16(ea, dst); |
| 2357 | CYCLES(CYCLES_XCHG_REG_MEM); |
| 2358 | } |
| 2359 | } |
| 2360 | |
| 2361 | void i386_device::i386_xor_rm16_r16() // Opcode 0x31 |
| 2362 | { |
| 2363 | UINT16 src, dst; |
| 2364 | UINT8 modrm = FETCH(); |
| 2365 | if( modrm >= 0xc0 ) { |
| 2366 | src = LOAD_REG16(modrm); |
| 2367 | dst = LOAD_RM16(modrm); |
| 2368 | dst = XOR16(dst, src); |
| 2369 | STORE_RM16(modrm, dst); |
| 2370 | CYCLES(CYCLES_ALU_REG_REG); |
| 2371 | } else { |
| 2372 | UINT32 ea = GetEA(modrm,1); |
| 2373 | src = LOAD_REG16(modrm); |
| 2374 | dst = READ16(ea); |
| 2375 | dst = XOR16(dst, src); |
| 2376 | WRITE16(ea, dst); |
| 2377 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2378 | } |
| 2379 | } |
| 2380 | |
| 2381 | void i386_device::i386_xor_r16_rm16() // Opcode 0x33 |
| 2382 | { |
| 2383 | UINT16 src, dst; |
| 2384 | UINT8 modrm = FETCH(); |
| 2385 | if( modrm >= 0xc0 ) { |
| 2386 | src = LOAD_RM16(modrm); |
| 2387 | dst = LOAD_REG16(modrm); |
| 2388 | dst = XOR16(dst, src); |
| 2389 | STORE_REG16(modrm, dst); |
| 2390 | CYCLES(CYCLES_ALU_REG_REG); |
| 2391 | } else { |
| 2392 | UINT32 ea = GetEA(modrm,0); |
| 2393 | src = READ16(ea); |
| 2394 | dst = LOAD_REG16(modrm); |
| 2395 | dst = XOR16(dst, src); |
| 2396 | STORE_REG16(modrm, dst); |
| 2397 | CYCLES(CYCLES_ALU_MEM_REG); |
| 2398 | } |
| 2399 | } |
| 2400 | |
| 2401 | void i386_device::i386_xor_ax_i16() // Opcode 0x35 |
| 2402 | { |
| 2403 | UINT16 src, dst; |
| 2404 | src = FETCH16(); |
| 2405 | dst = REG16(AX); |
| 2406 | dst = XOR16(dst, src); |
| 2407 | REG16(AX) = dst; |
| 2408 | CYCLES(CYCLES_ALU_IMM_ACC); |
| 2409 | } |
| 2410 | |
| 2411 | |
| 2412 | |
| 2413 | void i386_device::i386_group81_16() // Opcode 0x81 |
| 2414 | { |
| 2415 | UINT32 ea; |
| 2416 | UINT16 src, dst; |
| 2417 | UINT8 modrm = FETCH(); |
| 2418 | |
| 2419 | switch( (modrm >> 3) & 0x7 ) |
| 2420 | { |
| 2421 | case 0: // ADD Rm16, i16 |
| 2422 | if( modrm >= 0xc0 ) { |
| 2423 | dst = LOAD_RM16(modrm); |
| 2424 | src = FETCH16(); |
| 2425 | dst = ADD16(dst, src); |
| 2426 | STORE_RM16(modrm, dst); |
| 2427 | CYCLES(CYCLES_ALU_REG_REG); |
| 2428 | } else { |
| 2429 | ea = GetEA(modrm,1); |
| 2430 | dst = READ16(ea); |
| 2431 | src = FETCH16(); |
| 2432 | dst = ADD16(dst, src); |
| 2433 | WRITE16(ea, dst); |
| 2434 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2435 | } |
| 2436 | break; |
| 2437 | case 1: // OR Rm16, i16 |
| 2438 | if( modrm >= 0xc0 ) { |
| 2439 | dst = LOAD_RM16(modrm); |
| 2440 | src = FETCH16(); |
| 2441 | dst = OR16(dst, src); |
| 2442 | STORE_RM16(modrm, dst); |
| 2443 | CYCLES(CYCLES_ALU_REG_REG); |
| 2444 | } else { |
| 2445 | ea = GetEA(modrm,1); |
| 2446 | dst = READ16(ea); |
| 2447 | src = FETCH16(); |
| 2448 | dst = OR16(dst, src); |
| 2449 | WRITE16(ea, dst); |
| 2450 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2451 | } |
| 2452 | break; |
| 2453 | case 2: // ADC Rm16, i16 |
| 2454 | if( modrm >= 0xc0 ) { |
| 2455 | dst = LOAD_RM16(modrm); |
| 2456 | src = FETCH16(); |
| 2457 | dst = ADC16(dst, src, m_CF); |
| 2458 | STORE_RM16(modrm, dst); |
| 2459 | CYCLES(CYCLES_ALU_REG_REG); |
| 2460 | } else { |
| 2461 | ea = GetEA(modrm,1); |
| 2462 | dst = READ16(ea); |
| 2463 | src = FETCH16(); |
| 2464 | dst = ADC16(dst, src, m_CF); |
| 2465 | WRITE16(ea, dst); |
| 2466 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2467 | } |
| 2468 | break; |
| 2469 | case 3: // SBB Rm16, i16 |
| 2470 | if( modrm >= 0xc0 ) { |
| 2471 | dst = LOAD_RM16(modrm); |
| 2472 | src = FETCH16(); |
| 2473 | dst = SBB16(dst, src, m_CF); |
| 2474 | STORE_RM16(modrm, dst); |
| 2475 | CYCLES(CYCLES_ALU_REG_REG); |
| 2476 | } else { |
| 2477 | ea = GetEA(modrm,1); |
| 2478 | dst = READ16(ea); |
| 2479 | src = FETCH16(); |
| 2480 | dst = SBB16(dst, src, m_CF); |
| 2481 | WRITE16(ea, dst); |
| 2482 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2483 | } |
| 2484 | break; |
| 2485 | case 4: // AND Rm16, i16 |
| 2486 | if( modrm >= 0xc0 ) { |
| 2487 | dst = LOAD_RM16(modrm); |
| 2488 | src = FETCH16(); |
| 2489 | dst = AND16(dst, src); |
| 2490 | STORE_RM16(modrm, dst); |
| 2491 | CYCLES(CYCLES_ALU_REG_REG); |
| 2492 | } else { |
| 2493 | ea = GetEA(modrm,1); |
| 2494 | dst = READ16(ea); |
| 2495 | src = FETCH16(); |
| 2496 | dst = AND16(dst, src); |
| 2497 | WRITE16(ea, dst); |
| 2498 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2499 | } |
| 2500 | break; |
| 2501 | case 5: // SUB Rm16, i16 |
| 2502 | if( modrm >= 0xc0 ) { |
| 2503 | dst = LOAD_RM16(modrm); |
| 2504 | src = FETCH16(); |
| 2505 | dst = SUB16(dst, src); |
| 2506 | STORE_RM16(modrm, dst); |
| 2507 | CYCLES(CYCLES_ALU_REG_REG); |
| 2508 | } else { |
| 2509 | ea = GetEA(modrm,1); |
| 2510 | dst = READ16(ea); |
| 2511 | src = FETCH16(); |
| 2512 | dst = SUB16(dst, src); |
| 2513 | WRITE16(ea, dst); |
| 2514 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2515 | } |
| 2516 | break; |
| 2517 | case 6: // XOR Rm16, i16 |
| 2518 | if( modrm >= 0xc0 ) { |
| 2519 | dst = LOAD_RM16(modrm); |
| 2520 | src = FETCH16(); |
| 2521 | dst = XOR16(dst, src); |
| 2522 | STORE_RM16(modrm, dst); |
| 2523 | CYCLES(CYCLES_ALU_REG_REG); |
| 2524 | } else { |
| 2525 | ea = GetEA(modrm,1); |
| 2526 | dst = READ16(ea); |
| 2527 | src = FETCH16(); |
| 2528 | dst = XOR16(dst, src); |
| 2529 | WRITE16(ea, dst); |
| 2530 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2531 | } |
| 2532 | break; |
| 2533 | case 7: // CMP Rm16, i16 |
| 2534 | if( modrm >= 0xc0 ) { |
| 2535 | dst = LOAD_RM16(modrm); |
| 2536 | src = FETCH16(); |
| 2537 | SUB16(dst, src); |
| 2538 | CYCLES(CYCLES_CMP_REG_REG); |
| 2539 | } else { |
| 2540 | ea = GetEA(modrm,0); |
| 2541 | dst = READ16(ea); |
| 2542 | src = FETCH16(); |
| 2543 | SUB16(dst, src); |
| 2544 | CYCLES(CYCLES_CMP_REG_MEM); |
| 2545 | } |
| 2546 | break; |
| 2547 | } |
| 2548 | } |
| 2549 | |
| 2550 | void i386_device::i386_group83_16() // Opcode 0x83 |
| 2551 | { |
| 2552 | UINT32 ea; |
| 2553 | UINT16 src, dst; |
| 2554 | UINT8 modrm = FETCH(); |
| 2555 | |
| 2556 | switch( (modrm >> 3) & 0x7 ) |
| 2557 | { |
| 2558 | case 0: // ADD Rm16, i16 |
| 2559 | if( modrm >= 0xc0 ) { |
| 2560 | dst = LOAD_RM16(modrm); |
| 2561 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2562 | dst = ADD16(dst, src); |
| 2563 | STORE_RM16(modrm, dst); |
| 2564 | CYCLES(CYCLES_ALU_REG_REG); |
| 2565 | } else { |
| 2566 | ea = GetEA(modrm,1); |
| 2567 | dst = READ16(ea); |
| 2568 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2569 | dst = ADD16(dst, src); |
| 2570 | WRITE16(ea, dst); |
| 2571 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2572 | } |
| 2573 | break; |
| 2574 | case 1: // OR Rm16, i16 |
| 2575 | if( modrm >= 0xc0 ) { |
| 2576 | dst = LOAD_RM16(modrm); |
| 2577 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2578 | dst = OR16(dst, src); |
| 2579 | STORE_RM16(modrm, dst); |
| 2580 | CYCLES(CYCLES_ALU_REG_REG); |
| 2581 | } else { |
| 2582 | ea = GetEA(modrm,1); |
| 2583 | dst = READ16(ea); |
| 2584 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2585 | dst = OR16(dst, src); |
| 2586 | WRITE16(ea, dst); |
| 2587 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2588 | } |
| 2589 | break; |
| 2590 | case 2: // ADC Rm16, i16 |
| 2591 | if( modrm >= 0xc0 ) { |
| 2592 | dst = LOAD_RM16(modrm); |
| 2593 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2594 | dst = ADC16(dst, src, m_CF); |
| 2595 | STORE_RM16(modrm, dst); |
| 2596 | CYCLES(CYCLES_ALU_REG_REG); |
| 2597 | } else { |
| 2598 | ea = GetEA(modrm,1); |
| 2599 | dst = READ16(ea); |
| 2600 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2601 | dst = ADC16(dst, src, m_CF); |
| 2602 | WRITE16(ea, dst); |
| 2603 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2604 | } |
| 2605 | break; |
| 2606 | case 3: // SBB Rm16, i16 |
| 2607 | if( modrm >= 0xc0 ) { |
| 2608 | dst = LOAD_RM16(modrm); |
| 2609 | src = ((UINT16)(INT16)(INT8)FETCH()); |
| 2610 | dst = SBB16(dst, src, m_CF); |
| 2611 | STORE_RM16(modrm, dst); |
| 2612 | CYCLES(CYCLES_ALU_REG_REG); |
| 2613 | } else { |
| 2614 | ea = GetEA(modrm,1); |
| 2615 | dst = READ16(ea); |
| 2616 | src = ((UINT16)(INT16)(INT8)FETCH()); |
| 2617 | dst = SBB16(dst, src, m_CF); |
| 2618 | WRITE16(ea, dst); |
| 2619 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2620 | } |
| 2621 | break; |
| 2622 | case 4: // AND Rm16, i16 |
| 2623 | if( modrm >= 0xc0 ) { |
| 2624 | dst = LOAD_RM16(modrm); |
| 2625 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2626 | dst = AND16(dst, src); |
| 2627 | STORE_RM16(modrm, dst); |
| 2628 | CYCLES(CYCLES_ALU_REG_REG); |
| 2629 | } else { |
| 2630 | ea = GetEA(modrm,1); |
| 2631 | dst = READ16(ea); |
| 2632 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2633 | dst = AND16(dst, src); |
| 2634 | WRITE16(ea, dst); |
| 2635 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2636 | } |
| 2637 | break; |
| 2638 | case 5: // SUB Rm16, i16 |
| 2639 | if( modrm >= 0xc0 ) { |
| 2640 | dst = LOAD_RM16(modrm); |
| 2641 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2642 | dst = SUB16(dst, src); |
| 2643 | STORE_RM16(modrm, dst); |
| 2644 | CYCLES(CYCLES_ALU_REG_REG); |
| 2645 | } else { |
| 2646 | ea = GetEA(modrm,1); |
| 2647 | dst = READ16(ea); |
| 2648 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2649 | dst = SUB16(dst, src); |
| 2650 | WRITE16(ea, dst); |
| 2651 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2652 | } |
| 2653 | break; |
| 2654 | case 6: // XOR Rm16, i16 |
| 2655 | if( modrm >= 0xc0 ) { |
| 2656 | dst = LOAD_RM16(modrm); |
| 2657 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2658 | dst = XOR16(dst, src); |
| 2659 | STORE_RM16(modrm, dst); |
| 2660 | CYCLES(CYCLES_ALU_REG_REG); |
| 2661 | } else { |
| 2662 | ea = GetEA(modrm,1); |
| 2663 | dst = READ16(ea); |
| 2664 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2665 | dst = XOR16(dst, src); |
| 2666 | WRITE16(ea, dst); |
| 2667 | CYCLES(CYCLES_ALU_REG_MEM); |
| 2668 | } |
| 2669 | break; |
| 2670 | case 7: // CMP Rm16, i16 |
| 2671 | if( modrm >= 0xc0 ) { |
| 2672 | dst = LOAD_RM16(modrm); |
| 2673 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2674 | SUB16(dst, src); |
| 2675 | CYCLES(CYCLES_CMP_REG_REG); |
| 2676 | } else { |
| 2677 | ea = GetEA(modrm,0); |
| 2678 | dst = READ16(ea); |
| 2679 | src = (UINT16)(INT16)(INT8)FETCH(); |
| 2680 | SUB16(dst, src); |
| 2681 | CYCLES(CYCLES_CMP_REG_MEM); |
| 2682 | } |
| 2683 | break; |
| 2684 | } |
| 2685 | } |
| 2686 | |
| 2687 | void i386_device::i386_groupC1_16() // Opcode 0xc1 |
| 2688 | { |
| 2689 | UINT16 dst; |
| 2690 | UINT8 modrm = FETCH(); |
| 2691 | UINT8 shift; |
| 2692 | |
| 2693 | if( modrm >= 0xc0 ) { |
| 2694 | dst = LOAD_RM16(modrm); |
| 2695 | shift = FETCH() & 0x1f; |
| 2696 | dst = i386_shift_rotate16(modrm, dst, shift); |
| 2697 | STORE_RM16(modrm, dst); |
| 2698 | } else { |
| 2699 | UINT32 ea = GetEA(modrm,1); |
| 2700 | dst = READ16(ea); |
| 2701 | shift = FETCH() & 0x1f; |
| 2702 | dst = i386_shift_rotate16(modrm, dst, shift); |
| 2703 | WRITE16(ea, dst); |
| 2704 | } |
| 2705 | } |
| 2706 | |
| 2707 | void i386_device::i386_groupD1_16() // Opcode 0xd1 |
| 2708 | { |
| 2709 | UINT16 dst; |
| 2710 | UINT8 modrm = FETCH(); |
| 2711 | |
| 2712 | if( modrm >= 0xc0 ) { |
| 2713 | dst = LOAD_RM16(modrm); |
| 2714 | dst = i386_shift_rotate16(modrm, dst, 1); |
| 2715 | STORE_RM16(modrm, dst); |
| 2716 | } else { |
| 2717 | UINT32 ea = GetEA(modrm,1); |
| 2718 | dst = READ16(ea); |
| 2719 | dst = i386_shift_rotate16(modrm, dst, 1); |
| 2720 | WRITE16(ea, dst); |
| 2721 | } |
| 2722 | } |
| 2723 | |
| 2724 | void i386_device::i386_groupD3_16() // Opcode 0xd3 |
| 2725 | { |
| 2726 | UINT16 dst; |
| 2727 | UINT8 modrm = FETCH(); |
| 2728 | |
| 2729 | if( modrm >= 0xc0 ) { |
| 2730 | dst = LOAD_RM16(modrm); |
| 2731 | dst = i386_shift_rotate16(modrm, dst, REG8(CL)); |
| 2732 | STORE_RM16(modrm, dst); |
| 2733 | } else { |
| 2734 | UINT32 ea = GetEA(modrm,1); |
| 2735 | dst = READ16(ea); |
| 2736 | dst = i386_shift_rotate16(modrm, dst, REG8(CL)); |
| 2737 | WRITE16(ea, dst); |
| 2738 | } |
| 2739 | } |
| 2740 | |
| 2741 | void i386_device::i386_groupF7_16() // Opcode 0xf7 |
| 2742 | { |
| 2743 | UINT8 modrm = FETCH(); |
| 2744 | |
| 2745 | switch( (modrm >> 3) & 0x7 ) |
| 2746 | { |
| 2747 | case 0: /* TEST Rm16, i16 */ |
| 2748 | if( modrm >= 0xc0 ) { |
| 2749 | UINT16 dst = LOAD_RM16(modrm); |
| 2750 | UINT16 src = FETCH16(); |
| 2751 | dst &= src; |
| 2752 | m_CF = m_OF = m_AF = 0; |
| 2753 | SetSZPF16(dst); |
| 2754 | CYCLES(CYCLES_TEST_IMM_REG); |
| 2755 | } else { |
| 2756 | UINT32 ea = GetEA(modrm,0); |
| 2757 | UINT16 dst = READ16(ea); |
| 2758 | UINT16 src = FETCH16(); |
| 2759 | dst &= src; |
| 2760 | m_CF = m_OF = m_AF = 0; |
| 2761 | SetSZPF16(dst); |
| 2762 | CYCLES(CYCLES_TEST_IMM_MEM); |
| 2763 | } |
| 2764 | break; |
| 2765 | case 2: /* NOT Rm16 */ |
| 2766 | if( modrm >= 0xc0 ) { |
| 2767 | UINT16 dst = LOAD_RM16(modrm); |
| 2768 | dst = ~dst; |
| 2769 | STORE_RM16(modrm, dst); |
| 2770 | CYCLES(CYCLES_NOT_REG); |
| 2771 | } else { |
| 2772 | UINT32 ea = GetEA(modrm,1); |
| 2773 | UINT16 dst = READ16(ea); |
| 2774 | dst = ~dst; |
| 2775 | WRITE16(ea, dst); |
| 2776 | CYCLES(CYCLES_NOT_MEM); |
| 2777 | } |
| 2778 | break; |
| 2779 | case 3: /* NEG Rm16 */ |
| 2780 | if( modrm >= 0xc0 ) { |
| 2781 | UINT16 dst = LOAD_RM16(modrm); |
| 2782 | dst = SUB16(0, dst ); |
| 2783 | STORE_RM16(modrm, dst); |
| 2784 | CYCLES(CYCLES_NEG_REG); |
| 2785 | } else { |
| 2786 | UINT32 ea = GetEA(modrm,1); |
| 2787 | UINT16 dst = READ16(ea); |
| 2788 | dst = SUB16(0, dst ); |
| 2789 | WRITE16(ea, dst); |
| 2790 | CYCLES(CYCLES_NEG_MEM); |
| 2791 | } |
| 2792 | break; |
| 2793 | case 4: /* MUL AX, Rm16 */ |
| 2794 | { |
| 2795 | UINT32 result; |
| 2796 | UINT16 src, dst; |
| 2797 | if( modrm >= 0xc0 ) { |
| 2798 | src = LOAD_RM16(modrm); |
| 2799 | CYCLES(CYCLES_MUL16_ACC_REG); /* TODO: Correct multiply timing */ |
| 2800 | } else { |
| 2801 | UINT32 ea = GetEA(modrm,0); |
| 2802 | src = READ16(ea); |
| 2803 | CYCLES(CYCLES_MUL16_ACC_MEM); /* TODO: Correct multiply timing */ |
| 2804 | } |
| 2805 | |
| 2806 | dst = REG16(AX); |
| 2807 | result = (UINT32)src * (UINT32)dst; |
| 2808 | REG16(DX) = (UINT16)(result >> 16); |
| 2809 | REG16(AX) = (UINT16)result; |
| 2810 | |
| 2811 | m_CF = m_OF = (REG16(DX) != 0); |
| 2812 | } |
| 2813 | break; |
| 2814 | case 5: /* IMUL AX, Rm16 */ |
| 2815 | { |
| 2816 | INT32 result; |
| 2817 | INT32 src, dst; |
| 2818 | if( modrm >= 0xc0 ) { |
| 2819 | src = (INT32)(INT16)LOAD_RM16(modrm); |
| 2820 | CYCLES(CYCLES_IMUL16_ACC_REG); /* TODO: Correct multiply timing */ |
| 2821 | } else { |
| 2822 | UINT32 ea = GetEA(modrm,0); |
| 2823 | src = (INT32)(INT16)READ16(ea); |
| 2824 | CYCLES(CYCLES_IMUL16_ACC_MEM); /* TODO: Correct multiply timing */ |
| 2825 | } |
| 2826 | |
| 2827 | dst = (INT32)(INT16)REG16(AX); |
| 2828 | result = src * dst; |
| 2829 | |
| 2830 | REG16(DX) = (UINT16)(result >> 16); |
| 2831 | REG16(AX) = (UINT16)result; |
| 2832 | |
| 2833 | m_CF = m_OF = !(result == (INT32)(INT16)result); |
| 2834 | } |
| 2835 | break; |
| 2836 | case 6: /* DIV AX, Rm16 */ |
| 2837 | { |
| 2838 | UINT32 quotient, remainder, result; |
| 2839 | UINT16 src; |
| 2840 | if( modrm >= 0xc0 ) { |
| 2841 | src = LOAD_RM16(modrm); |
| 2842 | CYCLES(CYCLES_DIV16_ACC_REG); |
| 2843 | } else { |
| 2844 | UINT32 ea = GetEA(modrm,0); |
| 2845 | src = READ16(ea); |
| 2846 | CYCLES(CYCLES_DIV16_ACC_MEM); |
| 2847 | } |
| 2848 | |
| 2849 | quotient = ((UINT32)(REG16(DX)) << 16) | (UINT32)(REG16(AX)); |
| 2850 | if( src ) { |
| 2851 | remainder = quotient % (UINT32)src; |
| 2852 | result = quotient / (UINT32)src; |
| 2853 | if( result > 0xffff ) { |
| 2854 | /* TODO: Divide error */ |
| 2855 | } else { |
| 2856 | REG16(DX) = (UINT16)remainder; |
| 2857 | REG16(AX) = (UINT16)result; |
| 2858 | |
| 2859 | // this flag is actually undefined, enable on non-cyrix |
| 2860 | if (m_cpuid_id0 != 0x69727943) |
| 2861 | m_CF = 1; |
| 2862 | } |
| 2863 | } else { |
| 2864 | i386_trap(0, 0, 0); |
| 2865 | } |
| 2866 | } |
| 2867 | break; |
| 2868 | case 7: /* IDIV AX, Rm16 */ |
| 2869 | { |
| 2870 | INT32 quotient, remainder, result; |
| 2871 | UINT16 src; |
| 2872 | if( modrm >= 0xc0 ) { |
| 2873 | src = LOAD_RM16(modrm); |
| 2874 | CYCLES(CYCLES_IDIV16_ACC_REG); |
| 2875 | } else { |
| 2876 | UINT32 ea = GetEA(modrm,0); |
| 2877 | src = READ16(ea); |
| 2878 | CYCLES(CYCLES_IDIV16_ACC_MEM); |
| 2879 | } |
| 2880 | |
| 2881 | quotient = (((INT32)REG16(DX)) << 16) | ((UINT32)REG16(AX)); |
| 2882 | if( src ) { |
| 2883 | remainder = quotient % (INT32)(INT16)src; |
| 2884 | result = quotient / (INT32)(INT16)src; |
| 2885 | if( result > 0xffff ) { |
| 2886 | /* TODO: Divide error */ |
| 2887 | } else { |
| 2888 | REG16(DX) = (UINT16)remainder; |
| 2889 | REG16(AX) = (UINT16)result; |
| 2890 | |
| 2891 | // this flag is actually undefined, enable on non-cyrix |
| 2892 | if (m_cpuid_id0 != 0x69727943) |
| 2893 | m_CF = 1; |
| 2894 | } |
| 2895 | } else { |
| 2896 | i386_trap(0, 0, 0); |
| 2897 | } |
| 2898 | } |
| 2899 | break; |
| 2900 | } |
| 2901 | } |
| 2902 | |
| 2903 | void i386_device::i386_groupFF_16() // Opcode 0xff |
| 2904 | { |
| 2905 | UINT8 modrm = FETCH(); |
| 2906 | |
| 2907 | switch( (modrm >> 3) & 0x7 ) |
| 2908 | { |
| 2909 | case 0: /* INC Rm16 */ |
| 2910 | if( modrm >= 0xc0 ) { |
| 2911 | UINT16 dst = LOAD_RM16(modrm); |
| 2912 | dst = INC16(dst); |
| 2913 | STORE_RM16(modrm, dst); |
| 2914 | CYCLES(CYCLES_INC_REG); |
| 2915 | } else { |
| 2916 | UINT32 ea = GetEA(modrm,1); |
| 2917 | UINT16 dst = READ16(ea); |
| 2918 | dst = INC16(dst); |
| 2919 | WRITE16(ea, dst); |
| 2920 | CYCLES(CYCLES_INC_MEM); |
| 2921 | } |
| 2922 | break; |
| 2923 | case 1: /* DEC Rm16 */ |
| 2924 | if( modrm >= 0xc0 ) { |
| 2925 | UINT16 dst = LOAD_RM16(modrm); |
| 2926 | dst = DEC16(dst); |
| 2927 | STORE_RM16(modrm, dst); |
| 2928 | CYCLES(CYCLES_DEC_REG); |
| 2929 | } else { |
| 2930 | UINT32 ea = GetEA(modrm,1); |
| 2931 | UINT16 dst = READ16(ea); |
| 2932 | dst = DEC16(dst); |
| 2933 | WRITE16(ea, dst); |
| 2934 | CYCLES(CYCLES_DEC_MEM); |
| 2935 | } |
| 2936 | break; |
| 2937 | case 2: /* CALL Rm16 */ |
| 2938 | { |
| 2939 | UINT16 address; |
| 2940 | if( modrm >= 0xc0 ) { |
| 2941 | address = LOAD_RM16(modrm); |
| 2942 | CYCLES(CYCLES_CALL_REG); /* TODO: Timing = 7 + m */ |
| 2943 | } else { |
| 2944 | UINT32 ea = GetEA(modrm,0); |
| 2945 | address = READ16(ea); |
| 2946 | CYCLES(CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */ |
| 2947 | } |
| 2948 | PUSH16(m_eip ); |
| 2949 | m_eip = address; |
| 2950 | CHANGE_PC(m_eip); |
| 2951 | } |
| 2952 | break; |
| 2953 | case 3: /* CALL FAR Rm16 */ |
| 2954 | { |
| 2955 | UINT16 address, selector; |
| 2956 | if( modrm >= 0xc0 ) |
| 2957 | { |
| 2958 | report_invalid_modrm("groupFF_16", modrm); |
| 2959 | } |
| 2960 | else |
| 2961 | { |
| 2962 | UINT32 ea = GetEA(modrm,0); |
| 2963 | address = READ16(ea + 0); |
| 2964 | selector = READ16(ea + 2); |
| 2965 | CYCLES(CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */ |
| 2966 | |
| 2967 | if(PROTECTED_MODE && !V8086_MODE) |
| 2968 | { |
| 2969 | i386_protected_mode_call(selector,address,1,0); |
| 2970 | } |
| 2971 | else |
| 2972 | { |
| 2973 | PUSH16(m_sreg[CS].selector ); |
| 2974 | PUSH16(m_eip ); |
| 2975 | m_sreg[CS].selector = selector; |
| 2976 | m_performed_intersegment_jump = 1; |
| 2977 | i386_load_segment_descriptor(CS ); |
| 2978 | m_eip = address; |
| 2979 | CHANGE_PC(m_eip); |
| 2980 | } |
| 2981 | } |
| 2982 | } |
| 2983 | break; |
| 2984 | case 4: /* JMP Rm16 */ |
| 2985 | { |
| 2986 | UINT16 address; |
| 2987 | if( modrm >= 0xc0 ) { |
| 2988 | address = LOAD_RM16(modrm); |
| 2989 | CYCLES(CYCLES_JMP_REG); /* TODO: Timing = 7 + m */ |
| 2990 | } else { |
| 2991 | UINT32 ea = GetEA(modrm,0); |
| 2992 | address = READ16(ea); |
| 2993 | CYCLES(CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */ |
| 2994 | } |
| 2995 | m_eip = address; |
| 2996 | CHANGE_PC(m_eip); |
| 2997 | } |
| 2998 | break; |
| 2999 | case 5: /* JMP FAR Rm16 */ |
| 3000 | { |
| 3001 | UINT16 address, selector; |
| 3002 | |
| 3003 | if( modrm >= 0xc0 ) |
| 3004 | { |
| 3005 | report_invalid_modrm("groupFF_16", modrm); |
| 3006 | } |
| 3007 | else |
| 3008 | { |
| 3009 | UINT32 ea = GetEA(modrm,0); |
| 3010 | address = READ16(ea + 0); |
| 3011 | selector = READ16(ea + 2); |
| 3012 | CYCLES(CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */ |
| 3013 | if(PROTECTED_MODE && !V8086_MODE) |
| 3014 | { |
| 3015 | i386_protected_mode_jump(selector,address,1,0); |
| 3016 | } |
| 3017 | else |
| 3018 | { |
| 3019 | m_sreg[CS].selector = selector; |
| 3020 | m_performed_intersegment_jump = 1; |
| 3021 | i386_load_segment_descriptor(CS ); |
| 3022 | m_eip = address; |
| 3023 | CHANGE_PC(m_eip); |
| 3024 | } |
| 3025 | } |
| 3026 | } |
| 3027 | break; |
| 3028 | case 6: /* PUSH Rm16 */ |
| 3029 | { |
| 3030 | UINT16 value; |
| 3031 | if( modrm >= 0xc0 ) { |
| 3032 | value = LOAD_RM16(modrm); |
| 3033 | } else { |
| 3034 | UINT32 ea = GetEA(modrm,0); |
| 3035 | value = READ16(ea); |
| 3036 | } |
| 3037 | PUSH16(value); |
| 3038 | CYCLES(CYCLES_PUSH_RM); |
| 3039 | } |
| 3040 | break; |
| 3041 | default: |
| 3042 | report_invalid_modrm("groupFF_16", modrm); |
| 3043 | break; |
| 3044 | } |
| 3045 | } |
| 3046 | |
| 3047 | void i386_device::i386_group0F00_16() // Opcode 0x0f 00 |
| 3048 | { |
| 3049 | UINT32 address, ea; |
| 3050 | UINT8 modrm = FETCH(); |
| 3051 | I386_SREG seg; |
| 3052 | UINT8 result; |
| 3053 | |
| 3054 | switch( (modrm >> 3) & 0x7 ) |
| 3055 | { |
| 3056 | case 0: /* SLDT */ |
| 3057 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 3058 | { |
| 3059 | if( modrm >= 0xc0 ) { |
| 3060 | STORE_RM16(modrm, m_ldtr.segment); |
| 3061 | CYCLES(CYCLES_SLDT_REG); |
| 3062 | } else { |
| 3063 | ea = GetEA(modrm,1); |
| 3064 | WRITE16(ea, m_ldtr.segment); |
| 3065 | CYCLES(CYCLES_SLDT_MEM); |
| 3066 | } |
| 3067 | } |
| 3068 | else |
| 3069 | { |
| 3070 | i386_trap(6, 0, 0); |
| 3071 | } |
| 3072 | break; |
| 3073 | case 1: /* STR */ |
| 3074 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 3075 | { |
| 3076 | if( modrm >= 0xc0 ) { |
| 3077 | STORE_RM16(modrm, m_task.segment); |
| 3078 | CYCLES(CYCLES_STR_REG); |
| 3079 | } else { |
| 3080 | ea = GetEA(modrm,1); |
| 3081 | WRITE16(ea, m_task.segment); |
| 3082 | CYCLES(CYCLES_STR_MEM); |
| 3083 | } |
| 3084 | } |
| 3085 | else |
| 3086 | { |
| 3087 | i386_trap(6, 0, 0); |
| 3088 | } |
| 3089 | break; |
| 3090 | case 2: /* LLDT */ |
| 3091 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 3092 | { |
| 3093 | if(m_CPL) |
| 3094 | FAULT(FAULT_GP,0) |
| 3095 | if( modrm >= 0xc0 ) { |
| 3096 | address = LOAD_RM16(modrm); |
| 3097 | m_ldtr.segment = address; |
| 3098 | CYCLES(CYCLES_LLDT_REG); |
| 3099 | } else { |
| 3100 | ea = GetEA(modrm,0); |
| 3101 | m_ldtr.segment = READ16(ea); |
| 3102 | CYCLES(CYCLES_LLDT_MEM); |
| 3103 | } |
| 3104 | memset(&seg, 0, sizeof(seg)); |
| 3105 | seg.selector = m_ldtr.segment; |
| 3106 | i386_load_protected_mode_segment(&seg,NULL); |
| 3107 | m_ldtr.limit = seg.limit; |
| 3108 | m_ldtr.base = seg.base; |
| 3109 | m_ldtr.flags = seg.flags; |
| 3110 | } |
| 3111 | else |
| 3112 | { |
| 3113 | i386_trap(6, 0, 0); |
| 3114 | } |
| 3115 | break; |
| 3116 | |
| 3117 | case 3: /* LTR */ |
| 3118 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 3119 | { |
| 3120 | if(m_CPL) |
| 3121 | FAULT(FAULT_GP,0) |
| 3122 | if( modrm >= 0xc0 ) { |
| 3123 | address = LOAD_RM16(modrm); |
| 3124 | m_task.segment = address; |
| 3125 | CYCLES(CYCLES_LTR_REG); |
| 3126 | } else { |
| 3127 | ea = GetEA(modrm,0); |
| 3128 | m_task.segment = READ16(ea); |
| 3129 | CYCLES(CYCLES_LTR_MEM); |
| 3130 | } |
| 3131 | memset(&seg, 0, sizeof(seg)); |
| 3132 | seg.selector = m_task.segment; |
| 3133 | i386_load_protected_mode_segment(&seg,NULL); |
| 3134 | m_task.limit = seg.limit; |
| 3135 | m_task.base = seg.base; |
| 3136 | m_task.flags = seg.flags; |
| 3137 | } |
| 3138 | else |
| 3139 | { |
| 3140 | i386_trap(6, 0, 0); |
| 3141 | } |
| 3142 | break; |
| 3143 | |
| 3144 | case 4: /* VERR */ |
| 3145 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 3146 | { |
| 3147 | result = 1; |
| 3148 | if( modrm >= 0xc0 ) { |
| 3149 | address = LOAD_RM16(modrm); |
| 3150 | CYCLES(CYCLES_VERR_REG); |
| 3151 | } else { |
| 3152 | ea = GetEA(modrm,0); |
| 3153 | address = READ16(ea); |
| 3154 | CYCLES(CYCLES_VERR_MEM); |
| 3155 | } |
| 3156 | memset(&seg, 0, sizeof(seg)); |
| 3157 | seg.selector = address; |
| 3158 | result = i386_load_protected_mode_segment(&seg,NULL); |
| 3159 | // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) |
| 3160 | if(!(seg.flags & 0x10)) |
| 3161 | result = 0; |
| 3162 | // check that the segment is readable |
| 3163 | if(seg.flags & 0x10) // is code or data segment |
| 3164 | { |
| 3165 | if(seg.flags & 0x08) // is code segment, so check if it's readable |
| 3166 | { |
| 3167 | if(!(seg.flags & 0x02)) |
| 3168 | { |
| 3169 | result = 0; |
| 3170 | } |
| 3171 | else |
| 3172 | { // check if conforming, these are always readable, regardless of privilege |
| 3173 | if(!(seg.flags & 0x04)) |
| 3174 | { |
| 3175 | // if not conforming, then we must check privilege levels (TODO: current privilege level check) |
| 3176 | if(((seg.flags >> 5) & 0x03) < (address & 0x03)) |
| 3177 | result = 0; |
| 3178 | } |
| 3179 | } |
| 3180 | } |
| 3181 | } |
| 3182 | // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO) |
| 3183 | SetZF(result); |
| 3184 | } |
| 3185 | else |
| 3186 | { |
| 3187 | i386_trap(6, 0, 0); |
| 3188 | logerror("i386: VERR: Exception - Running in real mode or virtual 8086 mode.\n"); |
| 3189 | } |
| 3190 | break; |
| 3191 | |
| 3192 | case 5: /* VERW */ |
| 3193 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 3194 | { |
| 3195 | result = 1; |
| 3196 | if( modrm >= 0xc0 ) { |
| 3197 | address = LOAD_RM16(modrm); |
| 3198 | CYCLES(CYCLES_VERW_REG); |
| 3199 | } else { |
| 3200 | ea = GetEA(modrm,0); |
| 3201 | address = READ16(ea); |
| 3202 | CYCLES(CYCLES_VERW_MEM); |
| 3203 | } |
| 3204 | memset(&seg, 0, sizeof(seg)); |
| 3205 | seg.selector = address; |
| 3206 | result = i386_load_protected_mode_segment(&seg,NULL); |
| 3207 | // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) |
| 3208 | if(!(seg.flags & 0x10)) |
| 3209 | result = 0; |
| 3210 | // check that the segment is writable |
| 3211 | if(seg.flags & 0x10) // is code or data segment |
| 3212 | { |
| 3213 | if(seg.flags & 0x08) // is code segment (and thus, not writable) |
| 3214 | { |
| 3215 | result = 0; |
| 3216 | } |
| 3217 | else |
| 3218 | { // is data segment |
| 3219 | if(!(seg.flags & 0x02)) |
| 3220 | result = 0; |
| 3221 | } |
| 3222 | } |
| 3223 | // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO) |
| 3224 | if(((seg.flags >> 5) & 0x03) < (address & 0x03)) |
| 3225 | result = 0; |
| 3226 | SetZF(result); |
| 3227 | } |
| 3228 | else |
| 3229 | { |
| 3230 | i386_trap(6, 0, 0); |
| 3231 | logerror("i386: VERW: Exception - Running in real mode or virtual 8086 mode.\n"); |
| 3232 | } |
| 3233 | break; |
| 3234 | |
| 3235 | default: |
| 3236 | report_invalid_modrm("group0F00_16", modrm); |
| 3237 | break; |
| 3238 | } |
| 3239 | } |
| 3240 | |
| 3241 | void i386_device::i386_group0F01_16() // Opcode 0x0f 01 |
| 3242 | { |
| 3243 | UINT8 modrm = FETCH(); |
| 3244 | UINT16 address; |
| 3245 | UINT32 ea; |
| 3246 | |
| 3247 | switch( (modrm >> 3) & 0x7 ) |
| 3248 | { |
| 3249 | case 0: /* SGDT */ |
| 3250 | { |
| 3251 | if( modrm >= 0xc0 ) { |
| 3252 | address = LOAD_RM16(modrm); |
| 3253 | ea = i386_translate(CS, address, 1 ); |
| 3254 | } else { |
| 3255 | ea = GetEA(modrm,1); |
| 3256 | } |
| 3257 | WRITE16(ea, m_gdtr.limit); |
| 3258 | WRITE32(ea + 2, m_gdtr.base & 0xffffff); |
| 3259 | CYCLES(CYCLES_SGDT); |
| 3260 | break; |
| 3261 | } |
| 3262 | case 1: /* SIDT */ |
| 3263 | { |
| 3264 | if (modrm >= 0xc0) |
| 3265 | { |
| 3266 | address = LOAD_RM16(modrm); |
| 3267 | ea = i386_translate(CS, address, 1 ); |
| 3268 | } |
| 3269 | else |
| 3270 | { |
| 3271 | ea = GetEA(modrm,1); |
| 3272 | } |
| 3273 | WRITE16(ea, m_idtr.limit); |
| 3274 | WRITE32(ea + 2, m_idtr.base & 0xffffff); |
| 3275 | CYCLES(CYCLES_SIDT); |
| 3276 | break; |
| 3277 | } |
| 3278 | case 2: /* LGDT */ |
| 3279 | { |
| 3280 | if(PROTECTED_MODE && m_CPL) |
| 3281 | FAULT(FAULT_GP,0) |
| 3282 | if( modrm >= 0xc0 ) { |
| 3283 | address = LOAD_RM16(modrm); |
| 3284 | ea = i386_translate(CS, address, 0 ); |
| 3285 | } else { |
| 3286 | ea = GetEA(modrm,0); |
| 3287 | } |
| 3288 | m_gdtr.limit = READ16(ea); |
| 3289 | m_gdtr.base = READ32(ea + 2) & 0xffffff; |
| 3290 | CYCLES(CYCLES_LGDT); |
| 3291 | break; |
| 3292 | } |
| 3293 | case 3: /* LIDT */ |
| 3294 | { |
| 3295 | if(PROTECTED_MODE && m_CPL) |
| 3296 | FAULT(FAULT_GP,0) |
| 3297 | if( modrm >= 0xc0 ) { |
| 3298 | address = LOAD_RM16(modrm); |
| 3299 | ea = i386_translate(CS, address, 0 ); |
| 3300 | } else { |
| 3301 | ea = GetEA(modrm,0); |
| 3302 | } |
| 3303 | m_idtr.limit = READ16(ea); |
| 3304 | m_idtr.base = READ32(ea + 2) & 0xffffff; |
| 3305 | CYCLES(CYCLES_LIDT); |
| 3306 | break; |
| 3307 | } |
| 3308 | case 4: /* SMSW */ |
| 3309 | { |
| 3310 | if( modrm >= 0xc0 ) { |
| 3311 | STORE_RM16(modrm, m_cr[0]); |
| 3312 | CYCLES(CYCLES_SMSW_REG); |
| 3313 | } else { |
| 3314 | ea = GetEA(modrm,1); |
| 3315 | WRITE16(ea, m_cr[0]); |
| 3316 | CYCLES(CYCLES_SMSW_MEM); |
| 3317 | } |
| 3318 | break; |
| 3319 | } |
| 3320 | case 6: /* LMSW */ |
| 3321 | { |
| 3322 | if(PROTECTED_MODE && m_CPL) |
| 3323 | FAULT(FAULT_GP,0) |
| 3324 | UINT16 b; |
| 3325 | if( modrm >= 0xc0 ) { |
| 3326 | b = LOAD_RM16(modrm); |
| 3327 | CYCLES(CYCLES_LMSW_REG); |
| 3328 | } else { |
| 3329 | ea = GetEA(modrm,0); |
| 3330 | CYCLES(CYCLES_LMSW_MEM); |
| 3331 | b = READ16(ea); |
| 3332 | } |
| 3333 | if(PROTECTED_MODE) |
| 3334 | b |= 0x0001; // cannot return to real mode using this instruction. |
| 3335 | m_cr[0] &= ~0x0000000f; |
| 3336 | m_cr[0] |= b & 0x0000000f; |
| 3337 | break; |
| 3338 | } |
| 3339 | default: |
| 3340 | report_invalid_modrm("group0F01_16", modrm); |
| 3341 | break; |
| 3342 | } |
| 3343 | } |
| 3344 | |
| 3345 | void i386_device::i386_group0FBA_16() // Opcode 0x0f ba |
| 3346 | { |
| 3347 | UINT8 modrm = FETCH(); |
| 3348 | |
| 3349 | switch( (modrm >> 3) & 0x7 ) |
| 3350 | { |
| 3351 | case 4: /* BT Rm16, i8 */ |
| 3352 | if( modrm >= 0xc0 ) { |
| 3353 | UINT16 dst = LOAD_RM16(modrm); |
| 3354 | UINT8 bit = FETCH(); |
| 3355 | |
| 3356 | if( dst & (1 << bit) ) |
| 3357 | m_CF = 1; |
| 3358 | else |
| 3359 | m_CF = 0; |
| 3360 | |
| 3361 | CYCLES(CYCLES_BT_IMM_REG); |
| 3362 | } else { |
| 3363 | UINT32 ea = GetEA(modrm,0); |
| 3364 | UINT16 dst = READ16(ea); |
| 3365 | UINT8 bit = FETCH(); |
| 3366 | |
| 3367 | if( dst & (1 << bit) ) |
| 3368 | m_CF = 1; |
| 3369 | else |
| 3370 | m_CF = 0; |
| 3371 | |
| 3372 | CYCLES(CYCLES_BT_IMM_MEM); |
| 3373 | } |
| 3374 | break; |
| 3375 | case 5: /* BTS Rm16, i8 */ |
| 3376 | if( modrm >= 0xc0 ) { |
| 3377 | UINT16 dst = LOAD_RM16(modrm); |
| 3378 | UINT8 bit = FETCH(); |
| 3379 | |
| 3380 | if( dst & (1 << bit) ) |
| 3381 | m_CF = 1; |
| 3382 | else |
| 3383 | m_CF = 0; |
| 3384 | dst |= (1 << bit); |
| 3385 | |
| 3386 | STORE_RM16(modrm, dst); |
| 3387 | CYCLES(CYCLES_BTS_IMM_REG); |
| 3388 | } else { |
| 3389 | UINT32 ea = GetEA(modrm,1); |
| 3390 | UINT16 dst = READ16(ea); |
| 3391 | UINT8 bit = FETCH(); |
| 3392 | |
| 3393 | if( dst & (1 << bit) ) |
| 3394 | m_CF = 1; |
| 3395 | else |
| 3396 | m_CF = 0; |
| 3397 | dst |= (1 << bit); |
| 3398 | |
| 3399 | WRITE16(ea, dst); |
| 3400 | CYCLES(CYCLES_BTS_IMM_MEM); |
| 3401 | } |
| 3402 | break; |
| 3403 | case 6: /* BTR Rm16, i8 */ |
| 3404 | if( modrm >= 0xc0 ) { |
| 3405 | UINT16 dst = LOAD_RM16(modrm); |
| 3406 | UINT8 bit = FETCH(); |
| 3407 | |
| 3408 | if( dst & (1 << bit) ) |
| 3409 | m_CF = 1; |
| 3410 | else |
| 3411 | m_CF = 0; |
| 3412 | dst &= ~(1 << bit); |
| 3413 | |
| 3414 | STORE_RM16(modrm, dst); |
| 3415 | CYCLES(CYCLES_BTR_IMM_REG); |
| 3416 | } else { |
| 3417 | UINT32 ea = GetEA(modrm,1); |
| 3418 | UINT16 dst = READ16(ea); |
| 3419 | UINT8 bit = FETCH(); |
| 3420 | |
| 3421 | if( dst & (1 << bit) ) |
| 3422 | m_CF = 1; |
| 3423 | else |
| 3424 | m_CF = 0; |
| 3425 | dst &= ~(1 << bit); |
| 3426 | |
| 3427 | WRITE16(ea, dst); |
| 3428 | CYCLES(CYCLES_BTR_IMM_MEM); |
| 3429 | } |
| 3430 | break; |
| 3431 | case 7: /* BTC Rm16, i8 */ |
| 3432 | if( modrm >= 0xc0 ) { |
| 3433 | UINT16 dst = LOAD_RM16(modrm); |
| 3434 | UINT8 bit = FETCH(); |
| 3435 | |
| 3436 | if( dst & (1 << bit) ) |
| 3437 | m_CF = 1; |
| 3438 | else |
| 3439 | m_CF = 0; |
| 3440 | dst ^= (1 << bit); |
| 3441 | |
| 3442 | STORE_RM16(modrm, dst); |
| 3443 | CYCLES(CYCLES_BTC_IMM_REG); |
| 3444 | } else { |
| 3445 | UINT32 ea = GetEA(modrm,1); |
| 3446 | UINT16 dst = READ16(ea); |
| 3447 | UINT8 bit = FETCH(); |
| 3448 | |
| 3449 | if( dst & (1 << bit) ) |
| 3450 | m_CF = 1; |
| 3451 | else |
| 3452 | m_CF = 0; |
| 3453 | dst ^= (1 << bit); |
| 3454 | |
| 3455 | WRITE16(ea, dst); |
| 3456 | CYCLES(CYCLES_BTC_IMM_MEM); |
| 3457 | } |
| 3458 | break; |
| 3459 | default: |
| 3460 | report_invalid_modrm("group0FBA_16", modrm); |
| 3461 | break; |
| 3462 | } |
| 3463 | } |
| 3464 | |
| 3465 | void i386_device::i386_lar_r16_rm16() // Opcode 0x0f 0x02 |
| 3466 | { |
| 3467 | UINT8 modrm = FETCH(); |
| 3468 | I386_SREG seg; |
| 3469 | UINT8 type; |
| 3470 | |
| 3471 | if(PROTECTED_MODE && !V8086_MODE) |
| 3472 | { |
| 3473 | memset(&seg,0,sizeof(seg)); |
| 3474 | if(modrm >= 0xc0) |
| 3475 | { |
| 3476 | seg.selector = LOAD_RM16(modrm); |
| 3477 | CYCLES(CYCLES_LAR_REG); |
| 3478 | } |
| 3479 | else |
| 3480 | { |
| 3481 | UINT32 ea = GetEA(modrm,0); |
| 3482 | seg.selector = READ16(ea); |
| 3483 | CYCLES(CYCLES_LAR_MEM); |
| 3484 | } |
| 3485 | if(seg.selector == 0) |
| 3486 | { |
| 3487 | SetZF(0); // not a valid segment |
| 3488 | // logerror("i386 (%08x): LAR: Selector %04x is invalid type.\n",m_pc,seg.selector); |
| 3489 | } |
| 3490 | else |
| 3491 | { |
| 3492 | if(!i386_load_protected_mode_segment(&seg,NULL)) |
| 3493 | { |
| 3494 | SetZF(0); |
| 3495 | return; |
| 3496 | } |
| 3497 | UINT8 DPL = (seg.flags >> 5) & 3; |
| 3498 | if(((DPL < m_CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c)) |
| 3499 | { |
| 3500 | SetZF(0); |
| 3501 | return; |
| 3502 | } |
| 3503 | if(!(seg.flags & 0x10)) // special segment |
| 3504 | { |
| 3505 | // check for invalid segment types |
| 3506 | type = seg.flags & 0x000f; |
| 3507 | if(type == 0x00 || type == 0x08 || type == 0x0a || type == 0x0d) |
| 3508 | { |
| 3509 | SetZF(0); // invalid segment type |
| 3510 | } |
| 3511 | else |
| 3512 | { |
| 3513 | STORE_REG16(modrm,(seg.flags << 8) & 0xff00); |
| 3514 | SetZF(1); |
| 3515 | } |
| 3516 | } |
| 3517 | else |
| 3518 | { // data or code segment (both are valid for LAR) |
| 3519 | STORE_REG16(modrm,(seg.flags << 8) & 0xff00); |
| 3520 | SetZF(1); |
| 3521 | } |
| 3522 | } |
| 3523 | } |
| 3524 | else |
| 3525 | { |
| 3526 | // illegal opcode |
| 3527 | i386_trap(6,0, 0); |
| 3528 | logerror("i386: LAR: Exception - running in real mode or virtual 8086 mode.\n"); |
| 3529 | } |
| 3530 | } |
| 3531 | |
| 3532 | void i386_device::i386_lsl_r16_rm16() // Opcode 0x0f 0x03 |
| 3533 | { |
| 3534 | UINT8 modrm = FETCH(); |
| 3535 | UINT32 limit; |
| 3536 | I386_SREG seg; |
| 3537 | |
| 3538 | if(PROTECTED_MODE && !V8086_MODE) |
| 3539 | { |
| 3540 | memset(&seg, 0, sizeof(seg)); |
| 3541 | if(modrm >= 0xc0) |
| 3542 | { |
| 3543 | seg.selector = LOAD_RM16(modrm); |
| 3544 | } |
| 3545 | else |
| 3546 | { |
| 3547 | UINT32 ea = GetEA(modrm,0); |
| 3548 | seg.selector = READ16(ea); |
| 3549 | } |
| 3550 | if(seg.selector == 0) |
| 3551 | { |
| 3552 | SetZF(0); // not a valid segment |
| 3553 | } |
| 3554 | else |
| 3555 | { |
| 3556 | UINT8 type; |
| 3557 | if(!i386_load_protected_mode_segment(&seg,NULL)) |
| 3558 | { |
| 3559 | SetZF(0); |
| 3560 | return; |
| 3561 | } |
| 3562 | UINT8 DPL = (seg.flags >> 5) & 3; |
| 3563 | if(((DPL < m_CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c)) |
| 3564 | { |
| 3565 | SetZF(0); |
| 3566 | return; |
| 3567 | } |
| 3568 | type = seg.flags & 0x1f; |
| 3569 | switch(type) |
| 3570 | { |
| 3571 | case 0: |
| 3572 | case 4: |
| 3573 | case 5: |
| 3574 | case 6: |
| 3575 | case 7: |
| 3576 | case 8: |
| 3577 | case 10: |
| 3578 | case 12: |
| 3579 | case 13: |
| 3580 | case 14: |
| 3581 | case 15: |
| 3582 | SetZF(0); |
| 3583 | return; |
| 3584 | default: |
| 3585 | limit = seg.limit; |
| 3586 | STORE_REG16(modrm,limit & 0x0000ffff); |
| 3587 | SetZF(1); |
| 3588 | } |
| 3589 | } |
| 3590 | } |
| 3591 | else |
| 3592 | i386_trap(6, 0, 0); |
| 3593 | } |
| 3594 | |
| 3595 | void i386_device::i386_bound_r16_m16_m16() // Opcode 0x62 |
| 3596 | { |
| 3597 | UINT8 modrm; |
| 3598 | INT16 val, low, high; |
| 3599 | |
| 3600 | modrm = FETCH(); |
| 3601 | |
| 3602 | if (modrm >= 0xc0) |
| 3603 | { |
| 3604 | low = high = LOAD_RM16(modrm); |
| 3605 | } |
| 3606 | else |
| 3607 | { |
| 3608 | UINT32 ea = GetEA(modrm,0); |
| 3609 | low = READ16(ea + 0); |
| 3610 | high = READ16(ea + 2); |
| 3611 | } |
| 3612 | val = LOAD_REG16(modrm); |
| 3613 | |
| 3614 | if ((val < low) || (val > high)) |
| 3615 | { |
| 3616 | CYCLES(CYCLES_BOUND_OUT_RANGE); |
| 3617 | i386_trap(5, 0, 0); |
| 3618 | } |
| 3619 | else |
| 3620 | { |
| 3621 | CYCLES(CYCLES_BOUND_IN_RANGE); |
| 3622 | } |
| 3623 | } |
| 3624 | |
| 3625 | void i386_device::i386_retf16() // Opcode 0xcb |
| 3626 | { |
| 3627 | if(PROTECTED_MODE && !V8086_MODE) |
| 3628 | { |
| 3629 | i386_protected_mode_retf(0,0); |
| 3630 | } |
| 3631 | else |
| 3632 | { |
| 3633 | m_eip = POP16(); |
| 3634 | m_sreg[CS].selector = POP16(); |
| 3635 | i386_load_segment_descriptor(CS ); |
| 3636 | CHANGE_PC(m_eip); |
| 3637 | } |
| 3638 | |
| 3639 | CYCLES(CYCLES_RET_INTERSEG); |
| 3640 | } |
| 3641 | |
| 3642 | void i386_device::i386_retf_i16() // Opcode 0xca |
| 3643 | { |
| 3644 | UINT16 count = FETCH16(); |
| 3645 | |
| 3646 | if(PROTECTED_MODE && !V8086_MODE) |
| 3647 | { |
| 3648 | i386_protected_mode_retf(count,0); |
| 3649 | } |
| 3650 | else |
| 3651 | { |
| 3652 | m_eip = POP16(); |
| 3653 | m_sreg[CS].selector = POP16(); |
| 3654 | i386_load_segment_descriptor(CS ); |
| 3655 | CHANGE_PC(m_eip); |
| 3656 | REG16(SP) += count; |
| 3657 | } |
| 3658 | |
| 3659 | CYCLES(CYCLES_RET_IMM_INTERSEG); |
| 3660 | } |
| 3661 | |
| 3662 | bool i386_device::i386_load_far_pointer16(int s) |
| 3663 | { |
| 3664 | UINT8 modrm = FETCH(); |
| 3665 | UINT16 selector; |
| 3666 | |
| 3667 | if( modrm >= 0xc0 ) { |
| 3668 | //logerror("i386: load_far_pointer16 NYI\n"); // don't log, NT will use this a lot |
| 3669 | i386_trap(6, 0, 0); |
| 3670 | return false; |
| 3671 | } else { |
| 3672 | UINT32 ea = GetEA(modrm,0); |
| 3673 | STORE_REG16(modrm, READ16(ea + 0)); |
| 3674 | selector = READ16(ea + 2); |
| 3675 | i386_sreg_load(selector,s,NULL); |
| 3676 | } |
| 3677 | return true; |
| 3678 | } |
| 3679 | |
| 3680 | void i386_device::i386_lds16() // Opcode 0xc5 |
| 3681 | { |
| 3682 | if(i386_load_far_pointer16(DS)) |
| 3683 | CYCLES(CYCLES_LDS); |
| 3684 | } |
| 3685 | |
| 3686 | void i386_device::i386_lss16() // Opcode 0x0f 0xb2 |
| 3687 | { |
| 3688 | if(i386_load_far_pointer16(SS)) |
| 3689 | CYCLES(CYCLES_LSS); |
| 3690 | } |
| 3691 | |
| 3692 | void i386_device::i386_les16() // Opcode 0xc4 |
| 3693 | { |
| 3694 | if(i386_load_far_pointer16(ES)) |
| 3695 | CYCLES(CYCLES_LES); |
| 3696 | } |
| 3697 | |
| 3698 | void i386_device::i386_lfs16() // Opcode 0x0f 0xb4 |
| 3699 | { |
| 3700 | if(i386_load_far_pointer16(FS)) |
| 3701 | CYCLES(CYCLES_LFS); |
| 3702 | } |
| 3703 | |
| 3704 | void i386_device::i386_lgs16() // Opcode 0x0f 0xb5 |
| 3705 | { |
| 3706 | if(i386_load_far_pointer16(GS)) |
| 3707 | CYCLES(CYCLES_LGS); |
| 3708 | } |
trunk/src/emu/cpu/m68000/m68kfpu.c
| r28738 | r28739 | |
| 1 | | #include <math.h> |
| 2 | | |
| 3 | | #define FPCC_N 0x08000000 |
| 4 | | #define FPCC_Z 0x04000000 |
| 5 | | #define FPCC_I 0x02000000 |
| 6 | | #define FPCC_NAN 0x01000000 |
| 7 | | |
| 8 | | #define FPES_OE 0x00002000 |
| 9 | | #define FPAE_IOP 0x00000080 |
| 10 | | |
| 11 | | #define DOUBLE_INFINITY U64(0x7ff0000000000000) |
| 12 | | #define DOUBLE_EXPONENT U64(0x7ff0000000000000) |
| 13 | | #define DOUBLE_MANTISSA U64(0x000fffffffffffff) |
| 14 | | |
| 15 | | extern flag floatx80_is_nan( floatx80 a ); |
| 16 | | |
| 17 | | // masks for packed dwords, positive k-factor |
| 18 | | static const UINT32 pkmask2[18] = |
| 19 | | { |
| 20 | | 0xffffffff, 0, 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000, |
| 21 | | 0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff, |
| 22 | | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, |
| 23 | | 0xffffffff, 0xffffffff, 0xffffffff |
| 24 | | }; |
| 25 | | |
| 26 | | static const UINT32 pkmask3[18] = |
| 27 | | { |
| 28 | | 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 29 | | 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000, |
| 30 | | 0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff, |
| 31 | | }; |
| 32 | | |
| 33 | | INLINE double fx80_to_double(floatx80 fx) |
| 34 | | { |
| 35 | | UINT64 d; |
| 36 | | double *foo; |
| 37 | | |
| 38 | | foo = (double *)&d; |
| 39 | | |
| 40 | | d = floatx80_to_float64(fx); |
| 41 | | |
| 42 | | return *foo; |
| 43 | | } |
| 44 | | |
| 45 | | INLINE floatx80 double_to_fx80(double in) |
| 46 | | { |
| 47 | | UINT64 *d; |
| 48 | | |
| 49 | | d = (UINT64 *)∈ |
| 50 | | |
| 51 | | return float64_to_floatx80(*d); |
| 52 | | } |
| 53 | | |
| 54 | | INLINE floatx80 load_extended_float80(m68000_base_device *m68k, UINT32 ea) |
| 55 | | { |
| 56 | | UINT32 d1,d2; |
| 57 | | UINT16 d3; |
| 58 | | floatx80 fp; |
| 59 | | |
| 60 | | d3 = m68ki_read_16(m68k, ea); |
| 61 | | d1 = m68ki_read_32(m68k, ea+4); |
| 62 | | d2 = m68ki_read_32(m68k, ea+8); |
| 63 | | |
| 64 | | fp.high = d3; |
| 65 | | fp.low = ((UINT64)d1<<32) | (d2 & 0xffffffff); |
| 66 | | |
| 67 | | return fp; |
| 68 | | } |
| 69 | | |
| 70 | | INLINE void store_extended_float80(m68000_base_device *m68k, UINT32 ea, floatx80 fpr) |
| 71 | | { |
| 72 | | m68ki_write_16(m68k, ea+0, fpr.high); |
| 73 | | m68ki_write_16(m68k, ea+2, 0); |
| 74 | | m68ki_write_32(m68k, ea+4, (fpr.low>>32)&0xffffffff); |
| 75 | | m68ki_write_32(m68k, ea+8, fpr.low&0xffffffff); |
| 76 | | } |
| 77 | | |
| 78 | | INLINE floatx80 load_pack_float80(m68000_base_device *m68k, UINT32 ea) |
| 79 | | { |
| 80 | | UINT32 dw1, dw2, dw3; |
| 81 | | floatx80 result; |
| 82 | | double tmp; |
| 83 | | char str[128], *ch; |
| 84 | | |
| 85 | | dw1 = m68ki_read_32(m68k, ea); |
| 86 | | dw2 = m68ki_read_32(m68k, ea+4); |
| 87 | | dw3 = m68ki_read_32(m68k, ea+8); |
| 88 | | |
| 89 | | ch = &str[0]; |
| 90 | | if (dw1 & 0x80000000) // mantissa sign |
| 91 | | { |
| 92 | | *ch++ = '-'; |
| 93 | | } |
| 94 | | *ch++ = (char)((dw1 & 0xf) + '0'); |
| 95 | | *ch++ = '.'; |
| 96 | | *ch++ = (char)(((dw2 >> 28) & 0xf) + '0'); |
| 97 | | *ch++ = (char)(((dw2 >> 24) & 0xf) + '0'); |
| 98 | | *ch++ = (char)(((dw2 >> 20) & 0xf) + '0'); |
| 99 | | *ch++ = (char)(((dw2 >> 16) & 0xf) + '0'); |
| 100 | | *ch++ = (char)(((dw2 >> 12) & 0xf) + '0'); |
| 101 | | *ch++ = (char)(((dw2 >> 8) & 0xf) + '0'); |
| 102 | | *ch++ = (char)(((dw2 >> 4) & 0xf) + '0'); |
| 103 | | *ch++ = (char)(((dw2 >> 0) & 0xf) + '0'); |
| 104 | | *ch++ = (char)(((dw3 >> 28) & 0xf) + '0'); |
| 105 | | *ch++ = (char)(((dw3 >> 24) & 0xf) + '0'); |
| 106 | | *ch++ = (char)(((dw3 >> 20) & 0xf) + '0'); |
| 107 | | *ch++ = (char)(((dw3 >> 16) & 0xf) + '0'); |
| 108 | | *ch++ = (char)(((dw3 >> 12) & 0xf) + '0'); |
| 109 | | *ch++ = (char)(((dw3 >> 8) & 0xf) + '0'); |
| 110 | | *ch++ = (char)(((dw3 >> 4) & 0xf) + '0'); |
| 111 | | *ch++ = (char)(((dw3 >> 0) & 0xf) + '0'); |
| 112 | | *ch++ = 'E'; |
| 113 | | if (dw1 & 0x40000000) // exponent sign |
| 114 | | { |
| 115 | | *ch++ = '-'; |
| 116 | | } |
| 117 | | *ch++ = (char)(((dw1 >> 24) & 0xf) + '0'); |
| 118 | | *ch++ = (char)(((dw1 >> 20) & 0xf) + '0'); |
| 119 | | *ch++ = (char)(((dw1 >> 16) & 0xf) + '0'); |
| 120 | | *ch = '\0'; |
| 121 | | |
| 122 | | sscanf(str, "%le", &tmp); |
| 123 | | |
| 124 | | result = double_to_fx80(tmp); |
| 125 | | |
| 126 | | return result; |
| 127 | | } |
| 128 | | |
| 129 | | INLINE void store_pack_float80(m68000_base_device *m68k, UINT32 ea, int k, floatx80 fpr) |
| 130 | | { |
| 131 | | UINT32 dw1, dw2, dw3; |
| 132 | | char str[128], *ch; |
| 133 | | int i, j, exp; |
| 134 | | |
| 135 | | dw1 = dw2 = dw3 = 0; |
| 136 | | ch = &str[0]; |
| 137 | | |
| 138 | | sprintf(str, "%.16e", fx80_to_double(fpr)); |
| 139 | | |
| 140 | | if (*ch == '-') |
| 141 | | { |
| 142 | | ch++; |
| 143 | | dw1 = 0x80000000; |
| 144 | | } |
| 145 | | |
| 146 | | if (*ch == '+') |
| 147 | | { |
| 148 | | ch++; |
| 149 | | } |
| 150 | | |
| 151 | | dw1 |= (*ch++ - '0'); |
| 152 | | |
| 153 | | if (*ch == '.') |
| 154 | | { |
| 155 | | ch++; |
| 156 | | } |
| 157 | | |
| 158 | | // handle negative k-factor here |
| 159 | | if ((k <= 0) && (k >= -13)) |
| 160 | | { |
| 161 | | exp = 0; |
| 162 | | for (i = 0; i < 3; i++) |
| 163 | | { |
| 164 | | if (ch[18+i] >= '0' && ch[18+i] <= '9') |
| 165 | | { |
| 166 | | exp = (exp << 4) | (ch[18+i] - '0'); |
| 167 | | } |
| 168 | | } |
| 169 | | |
| 170 | | if (ch[17] == '-') |
| 171 | | { |
| 172 | | exp = -exp; |
| 173 | | } |
| 174 | | |
| 175 | | k = -k; |
| 176 | | // last digit is (k + exponent - 1) |
| 177 | | k += (exp - 1); |
| 178 | | |
| 179 | | // round up the last significant mantissa digit |
| 180 | | if (ch[k+1] >= '5') |
| 181 | | { |
| 182 | | ch[k]++; |
| 183 | | } |
| 184 | | |
| 185 | | // zero out the rest of the mantissa digits |
| 186 | | for (j = (k+1); j < 16; j++) |
| 187 | | { |
| 188 | | ch[j] = '0'; |
| 189 | | } |
| 190 | | |
| 191 | | // now zero out K to avoid tripping the positive K detection below |
| 192 | | k = 0; |
| 193 | | } |
| 194 | | |
| 195 | | // crack 8 digits of the mantissa |
| 196 | | for (i = 0; i < 8; i++) |
| 197 | | { |
| 198 | | dw2 <<= 4; |
| 199 | | if (*ch >= '0' && *ch <= '9') |
| 200 | | { |
| 201 | | dw2 |= *ch++ - '0'; |
| 202 | | } |
| 203 | | } |
| 204 | | |
| 205 | | // next 8 digits of the mantissa |
| 206 | | for (i = 0; i < 8; i++) |
| 207 | | { |
| 208 | | dw3 <<= 4; |
| 209 | | if (*ch >= '0' && *ch <= '9') |
| 210 | | dw3 |= *ch++ - '0'; |
| 211 | | } |
| 212 | | |
| 213 | | // handle masking if k is positive |
| 214 | | if (k >= 1) |
| 215 | | { |
| 216 | | if (k <= 17) |
| 217 | | { |
| 218 | | dw2 &= pkmask2[k]; |
| 219 | | dw3 &= pkmask3[k]; |
| 220 | | } |
| 221 | | else |
| 222 | | { |
| 223 | | dw2 &= pkmask2[17]; |
| 224 | | dw3 &= pkmask3[17]; |
| 225 | | // m68k->fpcr |= (need to set OPERR bit) |
| 226 | | } |
| 227 | | } |
| 228 | | |
| 229 | | // finally, crack the exponent |
| 230 | | if (*ch == 'e' || *ch == 'E') |
| 231 | | { |
| 232 | | ch++; |
| 233 | | if (*ch == '-') |
| 234 | | { |
| 235 | | ch++; |
| 236 | | dw1 |= 0x40000000; |
| 237 | | } |
| 238 | | |
| 239 | | if (*ch == '+') |
| 240 | | { |
| 241 | | ch++; |
| 242 | | } |
| 243 | | |
| 244 | | j = 0; |
| 245 | | for (i = 0; i < 3; i++) |
| 246 | | { |
| 247 | | if (*ch >= '0' && *ch <= '9') |
| 248 | | { |
| 249 | | j = (j << 4) | (*ch++ - '0'); |
| 250 | | } |
| 251 | | } |
| 252 | | |
| 253 | | dw1 |= (j << 16); |
| 254 | | } |
| 255 | | |
| 256 | | m68ki_write_32(m68k, ea, dw1); |
| 257 | | m68ki_write_32(m68k, ea+4, dw2); |
| 258 | | m68ki_write_32(m68k, ea+8, dw3); |
| 259 | | } |
| 260 | | |
| 261 | | INLINE void SET_CONDITION_CODES(m68000_base_device *m68k, floatx80 reg) |
| 262 | | { |
| 263 | | // UINT64 *regi; |
| 264 | | |
| 265 | | // regi = (UINT64 *)® |
| 266 | | |
| 267 | | REG_FPSR(m68k) &= ~(FPCC_N|FPCC_Z|FPCC_I|FPCC_NAN); |
| 268 | | |
| 269 | | // sign flag |
| 270 | | if (reg.high & 0x8000) |
| 271 | | { |
| 272 | | REG_FPSR(m68k) |= FPCC_N; |
| 273 | | } |
| 274 | | |
| 275 | | // zero flag |
| 276 | | if (((reg.high & 0x7fff) == 0) && ((reg.low<<1) == 0)) |
| 277 | | { |
| 278 | | REG_FPSR(m68k) |= FPCC_Z; |
| 279 | | } |
| 280 | | |
| 281 | | // infinity flag |
| 282 | | if (((reg.high & 0x7fff) == 0x7fff) && ((reg.low<<1) == 0)) |
| 283 | | { |
| 284 | | REG_FPSR(m68k) |= FPCC_I; |
| 285 | | } |
| 286 | | |
| 287 | | // NaN flag |
| 288 | | if (floatx80_is_nan(reg)) |
| 289 | | { |
| 290 | | REG_FPSR(m68k) |= FPCC_NAN; |
| 291 | | } |
| 292 | | } |
| 293 | | |
| 294 | | INLINE int TEST_CONDITION(m68000_base_device *m68k, int condition) |
| 295 | | { |
| 296 | | int n = (REG_FPSR(m68k) & FPCC_N) != 0; |
| 297 | | int z = (REG_FPSR(m68k) & FPCC_Z) != 0; |
| 298 | | int nan = (REG_FPSR(m68k) & FPCC_NAN) != 0; |
| 299 | | int r = 0; |
| 300 | | switch (condition) |
| 301 | | { |
| 302 | | case 0x10: |
| 303 | | case 0x00: return 0; // False |
| 304 | | |
| 305 | | case 0x11: |
| 306 | | case 0x01: return (z); // Equal |
| 307 | | |
| 308 | | case 0x12: |
| 309 | | case 0x02: return (!(nan || z || n)); // Greater Than |
| 310 | | |
| 311 | | case 0x13: |
| 312 | | case 0x03: return (z || !(nan || n)); // Greater or Equal |
| 313 | | |
| 314 | | case 0x14: |
| 315 | | case 0x04: return (n && !(nan || z)); // Less Than |
| 316 | | |
| 317 | | case 0x15: |
| 318 | | case 0x05: return (z || (n && !nan)); // Less Than or Equal |
| 319 | | |
| 320 | | case 0x16: |
| 321 | | case 0x06: return !nan && !z; |
| 322 | | |
| 323 | | case 0x17: |
| 324 | | case 0x07: return !nan; |
| 325 | | |
| 326 | | case 0x18: |
| 327 | | case 0x08: return nan; |
| 328 | | |
| 329 | | case 0x19: |
| 330 | | case 0x09: return nan || z; |
| 331 | | |
| 332 | | case 0x1a: |
| 333 | | case 0x0a: return (nan || !(n || z)); // Not Less Than or Equal |
| 334 | | |
| 335 | | case 0x1b: |
| 336 | | case 0x0b: return (nan || z || !n); // Not Less Than |
| 337 | | |
| 338 | | case 0x1c: |
| 339 | | case 0x0c: return (nan || (n && !z)); // Not Greater or Equal Than |
| 340 | | |
| 341 | | case 0x1d: |
| 342 | | case 0x0d: return (nan || z || n); // Not Greater Than |
| 343 | | |
| 344 | | case 0x1e: |
| 345 | | case 0x0e: return (!z); // Not Equal |
| 346 | | |
| 347 | | case 0x1f: |
| 348 | | case 0x0f: return 1; // True |
| 349 | | |
| 350 | | default: fatalerror("M68kFPU: test_condition: unhandled condition %02X\n", condition); |
| 351 | | } |
| 352 | | |
| 353 | | return r; |
| 354 | | } |
| 355 | | |
| 356 | | static UINT8 READ_EA_8(m68000_base_device *m68k, int ea) |
| 357 | | { |
| 358 | | int mode = (ea >> 3) & 0x7; |
| 359 | | int reg = (ea & 0x7); |
| 360 | | |
| 361 | | switch (mode) |
| 362 | | { |
| 363 | | case 0: // Dn |
| 364 | | { |
| 365 | | return REG_D(m68k)[reg]; |
| 366 | | } |
| 367 | | case 2: // (An) |
| 368 | | { |
| 369 | | UINT32 ea = REG_A(m68k)[reg]; |
| 370 | | return m68ki_read_8(m68k, ea); |
| 371 | | } |
| 372 | | case 3: // (An)+ |
| 373 | | { |
| 374 | | UINT32 ea = EA_AY_PI_8(m68k); |
| 375 | | return m68ki_read_8(m68k, ea); |
| 376 | | } |
| 377 | | case 4: // -(An) |
| 378 | | { |
| 379 | | UINT32 ea = EA_AY_PD_8(m68k); |
| 380 | | return m68ki_read_8(m68k, ea); |
| 381 | | } |
| 382 | | case 5: // (d16, An) |
| 383 | | { |
| 384 | | UINT32 ea = EA_AY_DI_8(m68k); |
| 385 | | return m68ki_read_8(m68k, ea); |
| 386 | | } |
| 387 | | case 6: // (An) + (Xn) + d8 |
| 388 | | { |
| 389 | | UINT32 ea = EA_AY_IX_8(m68k); |
| 390 | | return m68ki_read_8(m68k, ea); |
| 391 | | } |
| 392 | | case 7: |
| 393 | | { |
| 394 | | switch (reg) |
| 395 | | { |
| 396 | | case 0: // (xxx).W |
| 397 | | { |
| 398 | | UINT32 ea = (UINT32)OPER_I_16(m68k); |
| 399 | | return m68ki_read_8(m68k, ea); |
| 400 | | } |
| 401 | | case 1: // (xxx).L |
| 402 | | { |
| 403 | | UINT32 d1 = OPER_I_16(m68k); |
| 404 | | UINT32 d2 = OPER_I_16(m68k); |
| 405 | | UINT32 ea = (d1 << 16) | d2; |
| 406 | | return m68ki_read_8(m68k, ea); |
| 407 | | } |
| 408 | | case 2: // (d16, PC) |
| 409 | | { |
| 410 | | UINT32 ea = EA_PCDI_8(m68k); |
| 411 | | return m68ki_read_8(m68k, ea); |
| 412 | | } |
| 413 | | case 3: // (PC) + (Xn) + d8 |
| 414 | | { |
| 415 | | UINT32 ea = EA_PCIX_8(m68k); |
| 416 | | return m68ki_read_8(m68k, ea); |
| 417 | | } |
| 418 | | case 4: // #<data> |
| 419 | | { |
| 420 | | return OPER_I_8(m68k); |
| 421 | | } |
| 422 | | default: fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 423 | | } |
| 424 | | break; |
| 425 | | } |
| 426 | | default: fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 427 | | } |
| 428 | | |
| 429 | | return 0; |
| 430 | | } |
| 431 | | |
| 432 | | static UINT16 READ_EA_16(m68000_base_device *m68k, int ea) |
| 433 | | { |
| 434 | | int mode = (ea >> 3) & 0x7; |
| 435 | | int reg = (ea & 0x7); |
| 436 | | |
| 437 | | switch (mode) |
| 438 | | { |
| 439 | | case 0: // Dn |
| 440 | | { |
| 441 | | return (UINT16)(REG_D(m68k)[reg]); |
| 442 | | } |
| 443 | | case 2: // (An) |
| 444 | | { |
| 445 | | UINT32 ea = REG_A(m68k)[reg]; |
| 446 | | return m68ki_read_16(m68k, ea); |
| 447 | | } |
| 448 | | case 3: // (An)+ |
| 449 | | { |
| 450 | | UINT32 ea = EA_AY_PI_16(m68k); |
| 451 | | return m68ki_read_16(m68k, ea); |
| 452 | | } |
| 453 | | case 4: // -(An) |
| 454 | | { |
| 455 | | UINT32 ea = EA_AY_PD_16(m68k); |
| 456 | | return m68ki_read_16(m68k, ea); |
| 457 | | } |
| 458 | | case 5: // (d16, An) |
| 459 | | { |
| 460 | | UINT32 ea = EA_AY_DI_16(m68k); |
| 461 | | return m68ki_read_16(m68k, ea); |
| 462 | | } |
| 463 | | case 6: // (An) + (Xn) + d8 |
| 464 | | { |
| 465 | | UINT32 ea = EA_AY_IX_16(m68k); |
| 466 | | return m68ki_read_16(m68k, ea); |
| 467 | | } |
| 468 | | case 7: |
| 469 | | { |
| 470 | | switch (reg) |
| 471 | | { |
| 472 | | case 0: // (xxx).W |
| 473 | | { |
| 474 | | UINT32 ea = (UINT32)OPER_I_16(m68k); |
| 475 | | return m68ki_read_16(m68k, ea); |
| 476 | | } |
| 477 | | case 1: // (xxx).L |
| 478 | | { |
| 479 | | UINT32 d1 = OPER_I_16(m68k); |
| 480 | | UINT32 d2 = OPER_I_16(m68k); |
| 481 | | UINT32 ea = (d1 << 16) | d2; |
| 482 | | return m68ki_read_16(m68k, ea); |
| 483 | | } |
| 484 | | case 2: // (d16, PC) |
| 485 | | { |
| 486 | | UINT32 ea = EA_PCDI_16(m68k); |
| 487 | | return m68ki_read_16(m68k, ea); |
| 488 | | } |
| 489 | | case 3: // (PC) + (Xn) + d8 |
| 490 | | { |
| 491 | | UINT32 ea = EA_PCIX_16(m68k); |
| 492 | | return m68ki_read_16(m68k, ea); |
| 493 | | } |
| 494 | | case 4: // #<data> |
| 495 | | { |
| 496 | | return OPER_I_16(m68k); |
| 497 | | } |
| 498 | | |
| 499 | | default: fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 500 | | } |
| 501 | | break; |
| 502 | | } |
| 503 | | default: fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 504 | | } |
| 505 | | |
| 506 | | return 0; |
| 507 | | } |
| 508 | | |
| 509 | | static UINT32 READ_EA_32(m68000_base_device *m68k, int ea) |
| 510 | | { |
| 511 | | int mode = (ea >> 3) & 0x7; |
| 512 | | int reg = (ea & 0x7); |
| 513 | | |
| 514 | | switch (mode) |
| 515 | | { |
| 516 | | case 0: // Dn |
| 517 | | { |
| 518 | | return REG_D(m68k)[reg]; |
| 519 | | } |
| 520 | | case 2: // (An) |
| 521 | | { |
| 522 | | UINT32 ea = REG_A(m68k)[reg]; |
| 523 | | return m68ki_read_32(m68k, ea); |
| 524 | | } |
| 525 | | case 3: // (An)+ |
| 526 | | { |
| 527 | | UINT32 ea = EA_AY_PI_32(m68k); |
| 528 | | return m68ki_read_32(m68k, ea); |
| 529 | | } |
| 530 | | case 4: // -(An) |
| 531 | | { |
| 532 | | UINT32 ea = EA_AY_PD_32(m68k); |
| 533 | | return m68ki_read_32(m68k, ea); |
| 534 | | } |
| 535 | | case 5: // (d16, An) |
| 536 | | { |
| 537 | | UINT32 ea = EA_AY_DI_32(m68k); |
| 538 | | return m68ki_read_32(m68k, ea); |
| 539 | | } |
| 540 | | case 6: // (An) + (Xn) + d8 |
| 541 | | { |
| 542 | | UINT32 ea = EA_AY_IX_32(m68k); |
| 543 | | return m68ki_read_32(m68k, ea); |
| 544 | | } |
| 545 | | case 7: |
| 546 | | { |
| 547 | | switch (reg) |
| 548 | | { |
| 549 | | case 0: // (xxx).W |
| 550 | | { |
| 551 | | UINT32 ea = (UINT32)OPER_I_16(m68k); |
| 552 | | return m68ki_read_32(m68k, ea); |
| 553 | | } |
| 554 | | case 1: // (xxx).L |
| 555 | | { |
| 556 | | UINT32 d1 = OPER_I_16(m68k); |
| 557 | | UINT32 d2 = OPER_I_16(m68k); |
| 558 | | UINT32 ea = (d1 << 16) | d2; |
| 559 | | return m68ki_read_32(m68k, ea); |
| 560 | | } |
| 561 | | case 2: // (d16, PC) |
| 562 | | { |
| 563 | | UINT32 ea = EA_PCDI_32(m68k); |
| 564 | | return m68ki_read_32(m68k, ea); |
| 565 | | } |
| 566 | | case 3: // (PC) + (Xn) + d8 |
| 567 | | { |
| 568 | | UINT32 ea = EA_PCIX_32(m68k); |
| 569 | | return m68ki_read_32(m68k, ea); |
| 570 | | } |
| 571 | | case 4: // #<data> |
| 572 | | { |
| 573 | | return OPER_I_32(m68k); |
| 574 | | } |
| 575 | | default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 576 | | } |
| 577 | | break; |
| 578 | | } |
| 579 | | default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 580 | | } |
| 581 | | return 0; |
| 582 | | } |
| 583 | | |
| 584 | | static UINT64 READ_EA_64(m68000_base_device *m68k, int ea) |
| 585 | | { |
| 586 | | int mode = (ea >> 3) & 0x7; |
| 587 | | int reg = (ea & 0x7); |
| 588 | | UINT32 h1, h2; |
| 589 | | |
| 590 | | switch (mode) |
| 591 | | { |
| 592 | | case 2: // (An) |
| 593 | | { |
| 594 | | UINT32 ea = REG_A(m68k)[reg]; |
| 595 | | h1 = m68ki_read_32(m68k, ea+0); |
| 596 | | h2 = m68ki_read_32(m68k, ea+4); |
| 597 | | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 598 | | } |
| 599 | | case 3: // (An)+ |
| 600 | | { |
| 601 | | UINT32 ea = REG_A(m68k)[reg]; |
| 602 | | REG_A(m68k)[reg] += 8; |
| 603 | | h1 = m68ki_read_32(m68k, ea+0); |
| 604 | | h2 = m68ki_read_32(m68k, ea+4); |
| 605 | | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 606 | | } |
| 607 | | case 4: // -(An) |
| 608 | | { |
| 609 | | UINT32 ea = REG_A(m68k)[reg]-8; |
| 610 | | REG_A(m68k)[reg] -= 8; |
| 611 | | h1 = m68ki_read_32(m68k, ea+0); |
| 612 | | h2 = m68ki_read_32(m68k, ea+4); |
| 613 | | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 614 | | } |
| 615 | | case 5: // (d16, An) |
| 616 | | { |
| 617 | | UINT32 ea = EA_AY_DI_32(m68k); |
| 618 | | h1 = m68ki_read_32(m68k, ea+0); |
| 619 | | h2 = m68ki_read_32(m68k, ea+4); |
| 620 | | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 621 | | } |
| 622 | | case 6: // (An) + (Xn) + d8 |
| 623 | | { |
| 624 | | UINT32 ea = EA_AY_IX_32(m68k); |
| 625 | | h1 = m68ki_read_32(m68k, ea+0); |
| 626 | | h2 = m68ki_read_32(m68k, ea+4); |
| 627 | | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 628 | | } |
| 629 | | case 7: |
| 630 | | { |
| 631 | | switch (reg) |
| 632 | | { |
| 633 | | case 1: // (xxx).L |
| 634 | | { |
| 635 | | UINT32 d1 = OPER_I_16(m68k); |
| 636 | | UINT32 d2 = OPER_I_16(m68k); |
| 637 | | UINT32 ea = (d1 << 16) | d2; |
| 638 | | return (UINT64)(m68ki_read_32(m68k, ea)) << 32 | (UINT64)(m68ki_read_32(m68k, ea+4)); |
| 639 | | } |
| 640 | | case 3: // (PC) + (Xn) + d8 |
| 641 | | { |
| 642 | | UINT32 ea = EA_PCIX_32(m68k); |
| 643 | | h1 = m68ki_read_32(m68k, ea+0); |
| 644 | | h2 = m68ki_read_32(m68k, ea+4); |
| 645 | | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 646 | | } |
| 647 | | case 4: // #<data> |
| 648 | | { |
| 649 | | h1 = OPER_I_32(m68k); |
| 650 | | h2 = OPER_I_32(m68k); |
| 651 | | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 652 | | } |
| 653 | | case 2: // (d16, PC) |
| 654 | | { |
| 655 | | UINT32 ea = EA_PCDI_32(m68k); |
| 656 | | h1 = m68ki_read_32(m68k, ea+0); |
| 657 | | h2 = m68ki_read_32(m68k, ea+4); |
| 658 | | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 659 | | } |
| 660 | | default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 661 | | } |
| 662 | | break; |
| 663 | | } |
| 664 | | default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 665 | | } |
| 666 | | |
| 667 | | return 0; |
| 668 | | } |
| 669 | | |
| 670 | | |
| 671 | | static floatx80 READ_EA_FPE(m68000_base_device *m68k, int ea) |
| 672 | | { |
| 673 | | floatx80 fpr; |
| 674 | | int mode = (ea >> 3) & 0x7; |
| 675 | | int reg = (ea & 0x7); |
| 676 | | |
| 677 | | switch (mode) |
| 678 | | { |
| 679 | | case 2: // (An) |
| 680 | | { |
| 681 | | UINT32 ea = REG_A(m68k)[reg]; |
| 682 | | fpr = load_extended_float80(m68k, ea); |
| 683 | | break; |
| 684 | | } |
| 685 | | |
| 686 | | case 3: // (An)+ |
| 687 | | { |
| 688 | | UINT32 ea = REG_A(m68k)[reg]; |
| 689 | | REG_A(m68k)[reg] += 12; |
| 690 | | fpr = load_extended_float80(m68k, ea); |
| 691 | | break; |
| 692 | | } |
| 693 | | case 4: // -(An) |
| 694 | | { |
| 695 | | UINT32 ea = REG_A(m68k)[reg]-12; |
| 696 | | REG_A(m68k)[reg] -= 12; |
| 697 | | fpr = load_extended_float80(m68k, ea); |
| 698 | | break; |
| 699 | | } |
| 700 | | case 5: // (d16, An) |
| 701 | | { |
| 702 | | // FIXME: will fail for fmovem |
| 703 | | UINT32 ea = EA_AY_DI_32(m68k); |
| 704 | | fpr = load_extended_float80(m68k, ea); |
| 705 | | break; |
| 706 | | } |
| 707 | | case 6: // (An) + (Xn) + d8 |
| 708 | | { |
| 709 | | // FIXME: will fail for fmovem |
| 710 | | UINT32 ea = EA_AY_IX_32(m68k); |
| 711 | | fpr = load_extended_float80(m68k, ea); |
| 712 | | break; |
| 713 | | } |
| 714 | | |
| 715 | | case 7: // extended modes |
| 716 | | { |
| 717 | | switch (reg) |
| 718 | | { |
| 719 | | case 2: // (d16, PC) |
| 720 | | { |
| 721 | | UINT32 ea = EA_PCDI_32(m68k); |
| 722 | | fpr = load_extended_float80(m68k, ea); |
| 723 | | } |
| 724 | | break; |
| 725 | | |
| 726 | | case 3: // (d16,PC,Dx.w) |
| 727 | | { |
| 728 | | UINT32 ea = EA_PCIX_32(m68k); |
| 729 | | fpr = load_extended_float80(m68k, ea); |
| 730 | | } |
| 731 | | break; |
| 732 | | |
| 733 | | default: |
| 734 | | fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); |
| 735 | | break; |
| 736 | | } |
| 737 | | } |
| 738 | | break; |
| 739 | | |
| 740 | | default: fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); break; |
| 741 | | } |
| 742 | | |
| 743 | | return fpr; |
| 744 | | } |
| 745 | | |
| 746 | | static floatx80 READ_EA_PACK(m68000_base_device *m68k, int ea) |
| 747 | | { |
| 748 | | floatx80 fpr; |
| 749 | | int mode = (ea >> 3) & 0x7; |
| 750 | | int reg = (ea & 0x7); |
| 751 | | |
| 752 | | switch (mode) |
| 753 | | { |
| 754 | | case 2: // (An) |
| 755 | | { |
| 756 | | UINT32 ea = REG_A(m68k)[reg]; |
| 757 | | fpr = load_pack_float80(m68k, ea); |
| 758 | | break; |
| 759 | | } |
| 760 | | |
| 761 | | case 3: // (An)+ |
| 762 | | { |
| 763 | | UINT32 ea = REG_A(m68k)[reg]; |
| 764 | | REG_A(m68k)[reg] += 12; |
| 765 | | fpr = load_pack_float80(m68k, ea); |
| 766 | | break; |
| 767 | | } |
| 768 | | |
| 769 | | case 7: // extended modes |
| 770 | | { |
| 771 | | switch (reg) |
| 772 | | { |
| 773 | | case 3: // (d16,PC,Dx.w) |
| 774 | | { |
| 775 | | UINT32 ea = EA_PCIX_32(m68k); |
| 776 | | fpr = load_pack_float80(m68k, ea); |
| 777 | | } |
| 778 | | break; |
| 779 | | |
| 780 | | default: |
| 781 | | fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); |
| 782 | | break; |
| 783 | | } |
| 784 | | } |
| 785 | | break; |
| 786 | | |
| 787 | | default: fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); break; |
| 788 | | } |
| 789 | | |
| 790 | | return fpr; |
| 791 | | } |
| 792 | | |
| 793 | | static void WRITE_EA_8(m68000_base_device *m68k, int ea, UINT8 data) |
| 794 | | { |
| 795 | | int mode = (ea >> 3) & 0x7; |
| 796 | | int reg = (ea & 0x7); |
| 797 | | |
| 798 | | switch (mode) |
| 799 | | { |
| 800 | | case 0: // Dn |
| 801 | | { |
| 802 | | REG_D(m68k)[reg] = data; |
| 803 | | break; |
| 804 | | } |
| 805 | | case 2: // (An) |
| 806 | | { |
| 807 | | UINT32 ea = REG_A(m68k)[reg]; |
| 808 | | m68ki_write_8(m68k, ea, data); |
| 809 | | break; |
| 810 | | } |
| 811 | | case 3: // (An)+ |
| 812 | | { |
| 813 | | UINT32 ea = EA_AY_PI_8(m68k); |
| 814 | | m68ki_write_8(m68k, ea, data); |
| 815 | | break; |
| 816 | | } |
| 817 | | case 4: // -(An) |
| 818 | | { |
| 819 | | UINT32 ea = EA_AY_PD_8(m68k); |
| 820 | | m68ki_write_8(m68k, ea, data); |
| 821 | | break; |
| 822 | | } |
| 823 | | case 5: // (d16, An) |
| 824 | | { |
| 825 | | UINT32 ea = EA_AY_DI_8(m68k); |
| 826 | | m68ki_write_8(m68k, ea, data); |
| 827 | | break; |
| 828 | | } |
| 829 | | case 6: // (An) + (Xn) + d8 |
| 830 | | { |
| 831 | | UINT32 ea = EA_AY_IX_8(m68k); |
| 832 | | m68ki_write_8(m68k, ea, data); |
| 833 | | break; |
| 834 | | } |
| 835 | | case 7: |
| 836 | | { |
| 837 | | switch (reg) |
| 838 | | { |
| 839 | | case 1: // (xxx).B |
| 840 | | { |
| 841 | | UINT32 d1 = OPER_I_16(m68k); |
| 842 | | UINT32 d2 = OPER_I_16(m68k); |
| 843 | | UINT32 ea = (d1 << 16) | d2; |
| 844 | | m68ki_write_8(m68k, ea, data); |
| 845 | | break; |
| 846 | | } |
| 847 | | case 2: // (d16, PC) |
| 848 | | { |
| 849 | | UINT32 ea = EA_PCDI_16(m68k); |
| 850 | | m68ki_write_8(m68k, ea, data); |
| 851 | | break; |
| 852 | | } |
| 853 | | default: fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 854 | | } |
| 855 | | break; |
| 856 | | } |
| 857 | | default: fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC(m68k)); |
| 858 | | } |
| 859 | | } |
| 860 | | |
| 861 | | static void WRITE_EA_16(m68000_base_device *m68k, int ea, UINT16 data) |
| 862 | | { |
| 863 | | int mode = (ea >> 3) & 0x7; |
| 864 | | int reg = (ea & 0x7); |
| 865 | | |
| 866 | | switch (mode) |
| 867 | | { |
| 868 | | case 0: // Dn |
| 869 | | { |
| 870 | | REG_D(m68k)[reg] = data; |
| 871 | | break; |
| 872 | | } |
| 873 | | case 2: // (An) |
| 874 | | { |
| 875 | | UINT32 ea = REG_A(m68k)[reg]; |
| 876 | | m68ki_write_16(m68k, ea, data); |
| 877 | | break; |
| 878 | | } |
| 879 | | case 3: // (An)+ |
| 880 | | { |
| 881 | | UINT32 ea = EA_AY_PI_16(m68k); |
| 882 | | m68ki_write_16(m68k, ea, data); |
| 883 | | break; |
| 884 | | } |
| 885 | | case 4: // -(An) |
| 886 | | { |
| 887 | | UINT32 ea = EA_AY_PD_16(m68k); |
| 888 | | m68ki_write_16(m68k, ea, data); |
| 889 | | break; |
| 890 | | } |
| 891 | | case 5: // (d16, An) |
| 892 | | { |
| 893 | | UINT32 ea = EA_AY_DI_16(m68k); |
| 894 | | m68ki_write_16(m68k, ea, data); |
| 895 | | break; |
| 896 | | } |
| 897 | | case 6: // (An) + (Xn) + d8 |
| 898 | | { |
| 899 | | UINT32 ea = EA_AY_IX_16(m68k); |
| 900 | | m68ki_write_16(m68k, ea, data); |
| 901 | | break; |
| 902 | | } |
| 903 | | case 7: |
| 904 | | { |
| 905 | | switch (reg) |
| 906 | | { |
| 907 | | case 1: // (xxx).W |
| 908 | | { |
| 909 | | UINT32 d1 = OPER_I_16(m68k); |
| 910 | | UINT32 d2 = OPER_I_16(m68k); |
| 911 | | UINT32 ea = (d1 << 16) | d2; |
| 912 | | m68ki_write_16(m68k, ea, data); |
| 913 | | break; |
| 914 | | } |
| 915 | | case 2: // (d16, PC) |
| 916 | | { |
| 917 | | UINT32 ea = EA_PCDI_16(m68k); |
| 918 | | m68ki_write_16(m68k, ea, data); |
| 919 | | break; |
| 920 | | } |
| 921 | | default: fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 922 | | } |
| 923 | | break; |
| 924 | | } |
| 925 | | default: fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC(m68k)); |
| 926 | | } |
| 927 | | } |
| 928 | | |
| 929 | | static void WRITE_EA_32(m68000_base_device *m68k, int ea, UINT32 data) |
| 930 | | { |
| 931 | | int mode = (ea >> 3) & 0x7; |
| 932 | | int reg = (ea & 0x7); |
| 933 | | |
| 934 | | switch (mode) |
| 935 | | { |
| 936 | | case 0: // Dn |
| 937 | | { |
| 938 | | REG_D(m68k)[reg] = data; |
| 939 | | break; |
| 940 | | } |
| 941 | | case 1: // An |
| 942 | | { |
| 943 | | REG_A(m68k)[reg] = data; |
| 944 | | break; |
| 945 | | } |
| 946 | | case 2: // (An) |
| 947 | | { |
| 948 | | UINT32 ea = REG_A(m68k)[reg]; |
| 949 | | m68ki_write_32(m68k, ea, data); |
| 950 | | break; |
| 951 | | } |
| 952 | | case 3: // (An)+ |
| 953 | | { |
| 954 | | UINT32 ea = EA_AY_PI_32(m68k); |
| 955 | | m68ki_write_32(m68k, ea, data); |
| 956 | | break; |
| 957 | | } |
| 958 | | case 4: // -(An) |
| 959 | | { |
| 960 | | UINT32 ea = EA_AY_PD_32(m68k); |
| 961 | | m68ki_write_32(m68k, ea, data); |
| 962 | | break; |
| 963 | | } |
| 964 | | case 5: // (d16, An) |
| 965 | | { |
| 966 | | UINT32 ea = EA_AY_DI_32(m68k); |
| 967 | | m68ki_write_32(m68k, ea, data); |
| 968 | | break; |
| 969 | | } |
| 970 | | case 6: // (An) + (Xn) + d8 |
| 971 | | { |
| 972 | | UINT32 ea = EA_AY_IX_32(m68k); |
| 973 | | m68ki_write_32(m68k, ea, data); |
| 974 | | break; |
| 975 | | } |
| 976 | | case 7: |
| 977 | | { |
| 978 | | switch (reg) |
| 979 | | { |
| 980 | | case 1: // (xxx).L |
| 981 | | { |
| 982 | | UINT32 d1 = OPER_I_16(m68k); |
| 983 | | UINT32 d2 = OPER_I_16(m68k); |
| 984 | | UINT32 ea = (d1 << 16) | d2; |
| 985 | | m68ki_write_32(m68k, ea, data); |
| 986 | | break; |
| 987 | | } |
| 988 | | case 2: // (d16, PC) |
| 989 | | { |
| 990 | | UINT32 ea = EA_PCDI_32(m68k); |
| 991 | | m68ki_write_32(m68k, ea, data); |
| 992 | | break; |
| 993 | | } |
| 994 | | default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 995 | | } |
| 996 | | break; |
| 997 | | } |
| 998 | | default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC(m68k)); |
| 999 | | } |
| 1000 | | } |
| 1001 | | |
| 1002 | | static void WRITE_EA_64(m68000_base_device *m68k, int ea, UINT64 data) |
| 1003 | | { |
| 1004 | | int mode = (ea >> 3) & 0x7; |
| 1005 | | int reg = (ea & 0x7); |
| 1006 | | |
| 1007 | | switch (mode) |
| 1008 | | { |
| 1009 | | case 2: // (An) |
| 1010 | | { |
| 1011 | | UINT32 ea = REG_A(m68k)[reg]; |
| 1012 | | m68ki_write_32(m68k, ea, (UINT32)(data >> 32)); |
| 1013 | | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1014 | | break; |
| 1015 | | } |
| 1016 | | case 3: // (An)+ |
| 1017 | | { |
| 1018 | | UINT32 ea = REG_A(m68k)[reg]; |
| 1019 | | REG_A(m68k)[reg] += 8; |
| 1020 | | m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); |
| 1021 | | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1022 | | break; |
| 1023 | | } |
| 1024 | | case 4: // -(An) |
| 1025 | | { |
| 1026 | | UINT32 ea; |
| 1027 | | REG_A(m68k)[reg] -= 8; |
| 1028 | | ea = REG_A(m68k)[reg]; |
| 1029 | | m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); |
| 1030 | | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1031 | | break; |
| 1032 | | } |
| 1033 | | case 5: // (d16, An) |
| 1034 | | { |
| 1035 | | UINT32 ea = EA_AY_DI_32(m68k); |
| 1036 | | m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); |
| 1037 | | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1038 | | break; |
| 1039 | | } |
| 1040 | | case 6: // (An) + (Xn) + d8 |
| 1041 | | { |
| 1042 | | UINT32 ea = EA_AY_IX_32(m68k); |
| 1043 | | m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); |
| 1044 | | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1045 | | break; |
| 1046 | | } |
| 1047 | | case 7: |
| 1048 | | { |
| 1049 | | switch (reg) |
| 1050 | | { |
| 1051 | | case 1: // (xxx).L |
| 1052 | | { |
| 1053 | | UINT32 d1 = OPER_I_16(m68k); |
| 1054 | | UINT32 d2 = OPER_I_16(m68k); |
| 1055 | | UINT32 ea = (d1 << 16) | d2; |
| 1056 | | m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); |
| 1057 | | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1058 | | break; |
| 1059 | | } |
| 1060 | | case 2: // (d16, PC) |
| 1061 | | { |
| 1062 | | UINT32 ea = EA_PCDI_32(m68k); |
| 1063 | | m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); |
| 1064 | | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1065 | | break; |
| 1066 | | } |
| 1067 | | default: fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 1068 | | } |
| 1069 | | break; |
| 1070 | | } |
| 1071 | | default: fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d, data %08X%08X at %08X\n", mode, reg, (UINT32)(data >> 32), (UINT32)(data), REG_PC(m68k)); |
| 1072 | | } |
| 1073 | | } |
| 1074 | | |
| 1075 | | static void WRITE_EA_FPE(m68000_base_device *m68k, int ea, floatx80 fpr) |
| 1076 | | { |
| 1077 | | int mode = (ea >> 3) & 0x7; |
| 1078 | | int reg = (ea & 0x7); |
| 1079 | | |
| 1080 | | switch (mode) |
| 1081 | | { |
| 1082 | | case 2: // (An) |
| 1083 | | { |
| 1084 | | UINT32 ea; |
| 1085 | | ea = REG_A(m68k)[reg]; |
| 1086 | | store_extended_float80(m68k, ea, fpr); |
| 1087 | | break; |
| 1088 | | } |
| 1089 | | |
| 1090 | | case 3: // (An)+ |
| 1091 | | { |
| 1092 | | UINT32 ea; |
| 1093 | | ea = REG_A(m68k)[reg]; |
| 1094 | | store_extended_float80(m68k, ea, fpr); |
| 1095 | | REG_A(m68k)[reg] += 12; |
| 1096 | | break; |
| 1097 | | } |
| 1098 | | |
| 1099 | | case 4: // -(An) |
| 1100 | | { |
| 1101 | | UINT32 ea; |
| 1102 | | REG_A(m68k)[reg] -= 12; |
| 1103 | | ea = REG_A(m68k)[reg]; |
| 1104 | | store_extended_float80(m68k, ea, fpr); |
| 1105 | | break; |
| 1106 | | } |
| 1107 | | |
| 1108 | | case 7: |
| 1109 | | { |
| 1110 | | switch (reg) |
| 1111 | | { |
| 1112 | | default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); |
| 1113 | | } |
| 1114 | | } |
| 1115 | | default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); |
| 1116 | | } |
| 1117 | | } |
| 1118 | | |
| 1119 | | static void WRITE_EA_PACK(m68000_base_device *m68k, int ea, int k, floatx80 fpr) |
| 1120 | | { |
| 1121 | | int mode = (ea >> 3) & 0x7; |
| 1122 | | int reg = (ea & 0x7); |
| 1123 | | |
| 1124 | | switch (mode) |
| 1125 | | { |
| 1126 | | case 2: // (An) |
| 1127 | | { |
| 1128 | | UINT32 ea; |
| 1129 | | ea = REG_A(m68k)[reg]; |
| 1130 | | store_pack_float80(m68k, ea, k, fpr); |
| 1131 | | break; |
| 1132 | | } |
| 1133 | | |
| 1134 | | case 3: // (An)+ |
| 1135 | | { |
| 1136 | | UINT32 ea; |
| 1137 | | ea = REG_A(m68k)[reg]; |
| 1138 | | store_pack_float80(m68k, ea, k, fpr); |
| 1139 | | REG_A(m68k)[reg] += 12; |
| 1140 | | break; |
| 1141 | | } |
| 1142 | | |
| 1143 | | case 4: // -(An) |
| 1144 | | { |
| 1145 | | UINT32 ea; |
| 1146 | | REG_A(m68k)[reg] -= 12; |
| 1147 | | ea = REG_A(m68k)[reg]; |
| 1148 | | store_pack_float80(m68k, ea, k, fpr); |
| 1149 | | break; |
| 1150 | | } |
| 1151 | | |
| 1152 | | case 7: |
| 1153 | | { |
| 1154 | | switch (reg) |
| 1155 | | { |
| 1156 | | default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); |
| 1157 | | } |
| 1158 | | } |
| 1159 | | default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); |
| 1160 | | } |
| 1161 | | } |
| 1162 | | |
| 1163 | | static void fpgen_rm_reg(m68000_base_device *m68k, UINT16 w2) |
| 1164 | | { |
| 1165 | | int ea = m68k->ir & 0x3f; |
| 1166 | | int rm = (w2 >> 14) & 0x1; |
| 1167 | | int src = (w2 >> 10) & 0x7; |
| 1168 | | int dst = (w2 >> 7) & 0x7; |
| 1169 | | int opmode = w2 & 0x7f; |
| 1170 | | floatx80 source; |
| 1171 | | |
| 1172 | | // fmovecr #$f, fp0 f200 5c0f |
| 1173 | | |
| 1174 | | if (rm) |
| 1175 | | { |
| 1176 | | switch (src) |
| 1177 | | { |
| 1178 | | case 0: // Long-Word Integer |
| 1179 | | { |
| 1180 | | INT32 d = READ_EA_32(m68k, ea); |
| 1181 | | source = int32_to_floatx80(d); |
| 1182 | | break; |
| 1183 | | } |
| 1184 | | case 1: // Single-precision Real |
| 1185 | | { |
| 1186 | | UINT32 d = READ_EA_32(m68k, ea); |
| 1187 | | source = float32_to_floatx80(d); |
| 1188 | | break; |
| 1189 | | } |
| 1190 | | case 2: // Extended-precision Real |
| 1191 | | { |
| 1192 | | source = READ_EA_FPE(m68k, ea); |
| 1193 | | break; |
| 1194 | | } |
| 1195 | | case 3: // Packed-decimal Real |
| 1196 | | { |
| 1197 | | source = READ_EA_PACK(m68k, ea); |
| 1198 | | break; |
| 1199 | | } |
| 1200 | | case 4: // Word Integer |
| 1201 | | { |
| 1202 | | INT16 d = READ_EA_16(m68k, ea); |
| 1203 | | source = int32_to_floatx80((INT32)d); |
| 1204 | | break; |
| 1205 | | } |
| 1206 | | case 5: // Double-precision Real |
| 1207 | | { |
| 1208 | | UINT64 d = READ_EA_64(m68k, ea); |
| 1209 | | |
| 1210 | | source = float64_to_floatx80(d); |
| 1211 | | break; |
| 1212 | | } |
| 1213 | | case 6: // Byte Integer |
| 1214 | | { |
| 1215 | | INT8 d = READ_EA_8(m68k, ea); |
| 1216 | | source = int32_to_floatx80((INT32)d); |
| 1217 | | break; |
| 1218 | | } |
| 1219 | | case 7: // FMOVECR load from constant ROM |
| 1220 | | { |
| 1221 | | switch (w2 & 0x7f) |
| 1222 | | { |
| 1223 | | case 0x0: // Pi |
| 1224 | | source.high = 0x4000; |
| 1225 | | source.low = U64(0xc90fdaa22168c235); |
| 1226 | | break; |
| 1227 | | |
| 1228 | | case 0xb: // log10(2) |
| 1229 | | source.high = 0x3ffd; |
| 1230 | | source.low = U64(0x9a209a84fbcff798); |
| 1231 | | break; |
| 1232 | | |
| 1233 | | case 0xc: // e |
| 1234 | | source.high = 0x4000; |
| 1235 | | source.low = U64(0xadf85458a2bb4a9b); |
| 1236 | | break; |
| 1237 | | |
| 1238 | | case 0xd: // log2(e) |
| 1239 | | source.high = 0x3fff; |
| 1240 | | source.low = U64(0xb8aa3b295c17f0bc); |
| 1241 | | break; |
| 1242 | | |
| 1243 | | case 0xe: // log10(e) |
| 1244 | | source.high = 0x3ffd; |
| 1245 | | source.low = U64(0xde5bd8a937287195); |
| 1246 | | break; |
| 1247 | | |
| 1248 | | case 0xf: // 0.0 |
| 1249 | | source = int32_to_floatx80((INT32)0); |
| 1250 | | break; |
| 1251 | | |
| 1252 | | case 0x30: // ln(2) |
| 1253 | | source.high = 0x3ffe; |
| 1254 | | source.low = U64(0xb17217f7d1cf79ac); |
| 1255 | | break; |
| 1256 | | |
| 1257 | | case 0x31: // ln(10) |
| 1258 | | source.high = 0x4000; |
| 1259 | | source.low = U64(0x935d8dddaaa8ac17); |
| 1260 | | break; |
| 1261 | | |
| 1262 | | case 0x32: // 1 (or 100? manuals are unclear, but 1 would make more sense) |
| 1263 | | source = int32_to_floatx80((INT32)1); |
| 1264 | | break; |
| 1265 | | |
| 1266 | | case 0x33: // 10^1 |
| 1267 | | source = int32_to_floatx80((INT32)10); |
| 1268 | | break; |
| 1269 | | |
| 1270 | | case 0x34: // 10^2 |
| 1271 | | source = int32_to_floatx80((INT32)10*10); |
| 1272 | | break; |
| 1273 | | |
| 1274 | | case 0x35: // 10^4 |
| 1275 | | source = int32_to_floatx80((INT32)1000*10); |
| 1276 | | break; |
| 1277 | | |
| 1278 | | case 0x36: // 1.0e8 |
| 1279 | | source = int32_to_floatx80((INT32)10000000*10); |
| 1280 | | break; |
| 1281 | | |
| 1282 | | case 0x37: // 1.0e16 - can't get the right precision from INT32 so go "direct" with constants from h/w |
| 1283 | | source.high = 0x4034; |
| 1284 | | source.low = U64(0x8e1bc9bf04000000); |
| 1285 | | break; |
| 1286 | | |
| 1287 | | case 0x38: // 1.0e32 |
| 1288 | | source.high = 0x4069; |
| 1289 | | source.low = U64(0x9dc5ada82b70b59e); |
| 1290 | | break; |
| 1291 | | |
| 1292 | | case 0x39: // 1.0e64 |
| 1293 | | source.high = 0x40d3; |
| 1294 | | source.low = U64(0xc2781f49ffcfa6d5); |
| 1295 | | break; |
| 1296 | | |
| 1297 | | case 0x3a: // 1.0e128 |
| 1298 | | source.high = 0x41a8; |
| 1299 | | source.low = U64(0x93ba47c980e98ce0); |
| 1300 | | break; |
| 1301 | | |
| 1302 | | case 0x3b: // 1.0e256 |
| 1303 | | source.high = 0x4351; |
| 1304 | | source.low = U64(0xaa7eebfb9df9de8e); |
| 1305 | | break; |
| 1306 | | |
| 1307 | | case 0x3c: // 1.0e512 |
| 1308 | | source.high = 0x46a3; |
| 1309 | | source.low = U64(0xe319a0aea60e91c7); |
| 1310 | | break; |
| 1311 | | |
| 1312 | | case 0x3d: // 1.0e1024 |
| 1313 | | source.high = 0x4d48; |
| 1314 | | source.low = U64(0xc976758681750c17); |
| 1315 | | break; |
| 1316 | | |
| 1317 | | case 0x3e: // 1.0e2048 |
| 1318 | | source.high = 0x5a92; |
| 1319 | | source.low = U64(0x9e8b3b5dc53d5de5); |
| 1320 | | break; |
| 1321 | | |
| 1322 | | case 0x3f: // 1.0e4096 |
| 1323 | | source.high = 0x7525; |
| 1324 | | source.low = U64(0xc46052028a20979b); |
| 1325 | | break; |
| 1326 | | |
| 1327 | | default: |
| 1328 | | fatalerror("fmove_rm_reg: unknown constant ROM offset %x at %08x\n", w2&0x7f, REG_PC(m68k)-4); |
| 1329 | | break; |
| 1330 | | } |
| 1331 | | |
| 1332 | | // handle it right here, the usual opmode bits aren't valid in the FMOVECR case |
| 1333 | | REG_FP(m68k)[dst] = source; |
| 1334 | | m68k->remaining_cycles -= 4; |
| 1335 | | return; |
| 1336 | | } |
| 1337 | | default: fatalerror("fmove_rm_reg: invalid source specifier %x at %08X\n", src, REG_PC(m68k)-4); |
| 1338 | | } |
| 1339 | | } |
| 1340 | | else |
| 1341 | | { |
| 1342 | | source = REG_FP(m68k)[src]; |
| 1343 | | } |
| 1344 | | |
| 1345 | | |
| 1346 | | |
| 1347 | | switch (opmode) |
| 1348 | | { |
| 1349 | | case 0x00: // FMOVE |
| 1350 | | { |
| 1351 | | REG_FP(m68k)[dst] = source; |
| 1352 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1353 | | m68k->remaining_cycles -= 4; |
| 1354 | | break; |
| 1355 | | } |
| 1356 | | case 0x01: // FINT |
| 1357 | | { |
| 1358 | | INT32 temp; |
| 1359 | | temp = floatx80_to_int32(source); |
| 1360 | | REG_FP(m68k)[dst] = int32_to_floatx80(temp); |
| 1361 | | break; |
| 1362 | | } |
| 1363 | | case 0x03: // FINTRZ |
| 1364 | | { |
| 1365 | | INT32 temp; |
| 1366 | | temp = floatx80_to_int32_round_to_zero(source); |
| 1367 | | REG_FP(m68k)[dst] = int32_to_floatx80(temp); |
| 1368 | | break; |
| 1369 | | } |
| 1370 | | case 0x04: // FSQRT |
| 1371 | | { |
| 1372 | | REG_FP(m68k)[dst] = floatx80_sqrt(source); |
| 1373 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1374 | | m68k->remaining_cycles -= 109; |
| 1375 | | break; |
| 1376 | | } |
| 1377 | | case 0x06: // FLOGNP1 |
| 1378 | | { |
| 1379 | | REG_FP(m68k)[dst] = floatx80_flognp1 (source); |
| 1380 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1381 | | m68k->remaining_cycles -= 594; // for MC68881 |
| 1382 | | break; |
| 1383 | | } |
| 1384 | | case 0x0e: // FSIN |
| 1385 | | { |
| 1386 | | REG_FP(m68k)[dst] = source; |
| 1387 | | floatx80_fsin(REG_FP(m68k)[dst]); |
| 1388 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1389 | | m68k->remaining_cycles -= 75; |
| 1390 | | break; |
| 1391 | | } |
| 1392 | | case 0x0f: // FTAN |
| 1393 | | { |
| 1394 | | REG_FP(m68k)[dst] = source; |
| 1395 | | floatx80_ftan(REG_FP(m68k)[dst]); |
| 1396 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1397 | | m68k->remaining_cycles -= 75; |
| 1398 | | break; |
| 1399 | | } |
| 1400 | | case 0x14: // FLOGN |
| 1401 | | { |
| 1402 | | REG_FP(m68k)[dst] = floatx80_flogn (source); |
| 1403 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1404 | | m68k->remaining_cycles -= 548; // for MC68881 |
| 1405 | | break; |
| 1406 | | } |
| 1407 | | case 0x15: // FLOG10 |
| 1408 | | { |
| 1409 | | REG_FP(m68k)[dst] = floatx80_flog10 (source); |
| 1410 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1411 | | m68k->remaining_cycles -= 604; // for MC68881 |
| 1412 | | break; |
| 1413 | | } |
| 1414 | | case 0x16: // FLOG2 |
| 1415 | | { |
| 1416 | | REG_FP(m68k)[dst] = floatx80_flog2 (source); |
| 1417 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1418 | | m68k->remaining_cycles -= 604; // for MC68881 |
| 1419 | | break; |
| 1420 | | } |
| 1421 | | case 0x18: // FABS |
| 1422 | | { |
| 1423 | | REG_FP(m68k)[dst] = source; |
| 1424 | | REG_FP(m68k)[dst].high &= 0x7fff; |
| 1425 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1426 | | m68k->remaining_cycles -= 3; |
| 1427 | | break; |
| 1428 | | } |
| 1429 | | case 0x1a: // FNEG |
| 1430 | | { |
| 1431 | | REG_FP(m68k)[dst] = source; |
| 1432 | | REG_FP(m68k)[dst].high ^= 0x8000; |
| 1433 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1434 | | m68k->remaining_cycles -= 3; |
| 1435 | | break; |
| 1436 | | } |
| 1437 | | case 0x1d: // FCOS |
| 1438 | | { |
| 1439 | | REG_FP(m68k)[dst] = source; |
| 1440 | | floatx80_fcos(REG_FP(m68k)[dst]); |
| 1441 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1442 | | m68k->remaining_cycles -= 75; |
| 1443 | | break; |
| 1444 | | } |
| 1445 | | case 0x1e: // FGETEXP |
| 1446 | | { |
| 1447 | | INT16 temp2; |
| 1448 | | |
| 1449 | | temp2 = source.high; // get the exponent |
| 1450 | | temp2 -= 0x3fff; // take off the bias |
| 1451 | | REG_FP(m68k)[dst] = double_to_fx80((double)temp2); |
| 1452 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1453 | | m68k->remaining_cycles -= 6; |
| 1454 | | break; |
| 1455 | | } |
| 1456 | | case 0x20: // FDIV |
| 1457 | | { |
| 1458 | | REG_FP(m68k)[dst] = floatx80_div(REG_FP(m68k)[dst], source); |
| 1459 | | m68k->remaining_cycles -= 43; |
| 1460 | | break; |
| 1461 | | } |
| 1462 | | case 0x22: // FADD |
| 1463 | | { |
| 1464 | | REG_FP(m68k)[dst] = floatx80_add(REG_FP(m68k)[dst], source); |
| 1465 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1466 | | m68k->remaining_cycles -= 9; |
| 1467 | | break; |
| 1468 | | } |
| 1469 | | case 0x23: // FMUL |
| 1470 | | { |
| 1471 | | REG_FP(m68k)[dst] = floatx80_mul(REG_FP(m68k)[dst], source); |
| 1472 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1473 | | m68k->remaining_cycles -= 11; |
| 1474 | | break; |
| 1475 | | } |
| 1476 | | case 0x24: // FSGLDIV |
| 1477 | | { |
| 1478 | | float32 a = floatx80_to_float32( REG_FP(m68k)[dst] ); |
| 1479 | | float32 b = floatx80_to_float32( source ); |
| 1480 | | REG_FP(m68k)[dst] = float32_to_floatx80( float32_div(a, b) ); |
| 1481 | | m68k->remaining_cycles -= 43; // // ? (value is from FDIV) |
| 1482 | | break; |
| 1483 | | } |
| 1484 | | case 0x25: // FREM |
| 1485 | | { |
| 1486 | | REG_FP(m68k)[dst] = floatx80_rem(REG_FP(m68k)[dst], source); |
| 1487 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1488 | | m68k->remaining_cycles -= 43; // guess |
| 1489 | | break; |
| 1490 | | } |
| 1491 | | case 0x26: // FSCALE |
| 1492 | | { |
| 1493 | | REG_FP(m68k)[dst] = floatx80_scale(REG_FP(m68k)[dst], source); |
| 1494 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1495 | | m68k->remaining_cycles -= 46; // (better?) guess |
| 1496 | | break; |
| 1497 | | } |
| 1498 | | case 0x27: // FSGLMUL |
| 1499 | | { |
| 1500 | | float32 a = floatx80_to_float32( REG_FP(m68k)[dst] ); |
| 1501 | | float32 b = floatx80_to_float32( source ); |
| 1502 | | REG_FP(m68k)[dst] = float32_to_floatx80( float32_mul(a, b) ); |
| 1503 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1504 | | m68k->remaining_cycles -= 11; // ? (value is from FMUL) |
| 1505 | | break; |
| 1506 | | } |
| 1507 | | case 0x28: // FSUB |
| 1508 | | { |
| 1509 | | REG_FP(m68k)[dst] = floatx80_sub(REG_FP(m68k)[dst], source); |
| 1510 | | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1511 | | m68k->remaining_cycles -= 9; |
| 1512 | | break; |
| 1513 | | } |
| 1514 | | case 0x38: // FCMP |
| 1515 | | { |
| 1516 | | floatx80 res; |
| 1517 | | res = floatx80_sub(REG_FP(m68k)[dst], source); |
| 1518 | | SET_CONDITION_CODES(m68k, res); |
| 1519 | | m68k->remaining_cycles -= 7; |
| 1520 | | break; |
| 1521 | | } |
| 1522 | | case 0x3a: // FTST |
| 1523 | | { |
| 1524 | | floatx80 res; |
| 1525 | | res = source; |
| 1526 | | SET_CONDITION_CODES(m68k, res); |
| 1527 | | m68k->remaining_cycles -= 7; |
| 1528 | | break; |
| 1529 | | } |
| 1530 | | |
| 1531 | | default: fatalerror("fpgen_rm_reg: unimplemented opmode %02X at %08X\n", opmode, REG_PPC(m68k)); |
| 1532 | | } |
| 1533 | | } |
| 1534 | | |
| 1535 | | static void fmove_reg_mem(m68000_base_device *m68k, UINT16 w2) |
| 1536 | | { |
| 1537 | | int ea = m68k->ir & 0x3f; |
| 1538 | | int src = (w2 >> 7) & 0x7; |
| 1539 | | int dst = (w2 >> 10) & 0x7; |
| 1540 | | int k = (w2 & 0x7f); |
| 1541 | | |
| 1542 | | switch (dst) |
| 1543 | | { |
| 1544 | | case 0: // Long-Word Integer |
| 1545 | | { |
| 1546 | | INT32 d = (INT32)floatx80_to_int32(REG_FP(m68k)[src]); |
| 1547 | | WRITE_EA_32(m68k, ea, d); |
| 1548 | | break; |
| 1549 | | } |
| 1550 | | case 1: // Single-precision Real |
| 1551 | | { |
| 1552 | | UINT32 d = floatx80_to_float32(REG_FP(m68k)[src]); |
| 1553 | | WRITE_EA_32(m68k, ea, d); |
| 1554 | | break; |
| 1555 | | } |
| 1556 | | case 2: // Extended-precision Real |
| 1557 | | { |
| 1558 | | WRITE_EA_FPE(m68k, ea, REG_FP(m68k)[src]); |
| 1559 | | break; |
| 1560 | | } |
| 1561 | | case 3: // Packed-decimal Real with Static K-factor |
| 1562 | | { |
| 1563 | | // sign-extend k |
| 1564 | | k = (k & 0x40) ? (k | 0xffffff80) : (k & 0x7f); |
| 1565 | | WRITE_EA_PACK(m68k, ea, k, REG_FP(m68k)[src]); |
| 1566 | | break; |
| 1567 | | } |
| 1568 | | case 4: // Word Integer |
| 1569 | | { |
| 1570 | | int32 value = floatx80_to_int32(REG_FP(m68k)[src]); |
| 1571 | | if (value > 0x7fff || value < -0x8000 ) |
| 1572 | | { |
| 1573 | | REG_FPSR(m68k) |= FPES_OE | FPAE_IOP; |
| 1574 | | } |
| 1575 | | WRITE_EA_16(m68k, ea, (INT16)value); |
| 1576 | | break; |
| 1577 | | } |
| 1578 | | case 5: // Double-precision Real |
| 1579 | | { |
| 1580 | | UINT64 d; |
| 1581 | | |
| 1582 | | d = floatx80_to_float64(REG_FP(m68k)[src]); |
| 1583 | | |
| 1584 | | WRITE_EA_64(m68k, ea, d); |
| 1585 | | break; |
| 1586 | | } |
| 1587 | | case 6: // Byte Integer |
| 1588 | | { |
| 1589 | | int32 value = floatx80_to_int32(REG_FP(m68k)[src]); |
| 1590 | | if (value > 127 || value < -128) |
| 1591 | | { |
| 1592 | | REG_FPSR(m68k) |= FPES_OE | FPAE_IOP; |
| 1593 | | } |
| 1594 | | WRITE_EA_8(m68k, ea, (INT8) value); |
| 1595 | | break; |
| 1596 | | } |
| 1597 | | case 7: // Packed-decimal Real with Dynamic K-factor |
| 1598 | | { |
| 1599 | | WRITE_EA_PACK(m68k, ea, REG_D(m68k)[k>>4], REG_FP(m68k)[src]); |
| 1600 | | break; |
| 1601 | | } |
| 1602 | | } |
| 1603 | | |
| 1604 | | m68k->remaining_cycles -= 12; |
| 1605 | | } |
| 1606 | | |
| 1607 | | static void fmove_fpcr(m68000_base_device *m68k, UINT16 w2) |
| 1608 | | { |
| 1609 | | int ea = m68k->ir & 0x3f; |
| 1610 | | int dir = (w2 >> 13) & 0x1; |
| 1611 | | int regsel = (w2 >> 10) & 0x7; |
| 1612 | | int mode = (ea >> 3) & 0x7; |
| 1613 | | |
| 1614 | | if ((mode == 5) || (mode == 6)) |
| 1615 | | { |
| 1616 | | UINT32 address = 0xffffffff; // force a bus error if this doesn't get assigned |
| 1617 | | |
| 1618 | | if (mode == 5) |
| 1619 | | { |
| 1620 | | address = EA_AY_DI_32(m68k); |
| 1621 | | } |
| 1622 | | else if (mode == 6) |
| 1623 | | { |
| 1624 | | address = EA_AY_IX_32(m68k); |
| 1625 | | } |
| 1626 | | |
| 1627 | | if (dir) // From system control reg to <ea> |
| 1628 | | { |
| 1629 | | if (regsel & 4) { m68ki_write_32(m68k, address, REG_FPCR(m68k)); address += 4; } |
| 1630 | | if (regsel & 2) { m68ki_write_32(m68k, address, REG_FPSR(m68k)); address += 4; } |
| 1631 | | if (regsel & 1) { m68ki_write_32(m68k, address, REG_FPIAR(m68k)); address += 4; } |
| 1632 | | } |
| 1633 | | else // From <ea> to system control reg |
| 1634 | | { |
| 1635 | | if (regsel & 4) { REG_FPCR(m68k) = m68ki_read_32(m68k, address); address += 4; } |
| 1636 | | if (regsel & 2) { REG_FPSR(m68k) = m68ki_read_32(m68k, address); address += 4; } |
| 1637 | | if (regsel & 1) { REG_FPIAR(m68k) = m68ki_read_32(m68k, address); address += 4; } |
| 1638 | | } |
| 1639 | | } |
| 1640 | | else |
| 1641 | | { |
| 1642 | | if (dir) // From system control reg to <ea> |
| 1643 | | { |
| 1644 | | if (regsel & 4) WRITE_EA_32(m68k, ea, REG_FPCR(m68k)); |
| 1645 | | if (regsel & 2) WRITE_EA_32(m68k, ea, REG_FPSR(m68k)); |
| 1646 | | if (regsel & 1) WRITE_EA_32(m68k, ea, REG_FPIAR(m68k)); |
| 1647 | | } |
| 1648 | | else // From <ea> to system control reg |
| 1649 | | { |
| 1650 | | if (regsel & 4) REG_FPCR(m68k) = READ_EA_32(m68k, ea); |
| 1651 | | if (regsel & 2) REG_FPSR(m68k) = READ_EA_32(m68k, ea); |
| 1652 | | if (regsel & 1) REG_FPIAR(m68k) = READ_EA_32(m68k, ea); |
| 1653 | | } |
| 1654 | | } |
| 1655 | | |
| 1656 | | #if 0 |
| 1657 | | // FIXME: (2011-12-18 ost) |
| 1658 | | // rounding_mode and rounding_precision of softfloat.c should be set according to current fpcr |
| 1659 | | // but: with this code on Apollo the following programs in /systest/fptest will fail: |
| 1660 | | // 1. Single Precision Whetstone will return wrong results never the less |
| 1661 | | // 2. Vector Test will fault with 00040004: reference to illegal address |
| 1662 | | |
| 1663 | | if ((regsel & 4) && dir == 0) |
| 1664 | | { |
| 1665 | | int rnd = (REG_FPCR(m68k) >> 4) & 3; |
| 1666 | | int prec = (REG_FPCR(m68k) >> 6) & 3; |
| 1667 | | |
| 1668 | | logerror("m68k_fpsp:fmove_fpcr fpcr=%04x prec=%d rnd=%d\n", REG_FPCR(m68k), prec, rnd); |
| 1669 | | |
| 1670 | | #ifdef FLOATX80 |
| 1671 | | switch (prec) |
| 1672 | | { |
| 1673 | | case 0: // Extend (X) |
| 1674 | | floatx80_rounding_precision = 80; |
| 1675 | | break; |
| 1676 | | case 1: // Single (S) |
| 1677 | | floatx80_rounding_precision = 32; |
| 1678 | | break; |
| 1679 | | case 2: // Double (D) |
| 1680 | | floatx80_rounding_precision = 64; |
| 1681 | | break; |
| 1682 | | case 3: // Undefined |
| 1683 | | floatx80_rounding_precision = 80; |
| 1684 | | break; |
| 1685 | | } |
| 1686 | | #endif |
| 1687 | | |
| 1688 | | switch (rnd) |
| 1689 | | { |
| 1690 | | case 0: // To Nearest (RN) |
| 1691 | | float_rounding_mode = float_round_nearest_even; |
| 1692 | | break; |
| 1693 | | case 1: // To Zero (RZ) |
| 1694 | | float_rounding_mode = float_round_to_zero; |
| 1695 | | break; |
| 1696 | | case 2: // To Minus Infinitiy (RM) |
| 1697 | | float_rounding_mode = float_round_down; |
| 1698 | | break; |
| 1699 | | case 3: // To Plus Infinitiy (RP) |
| 1700 | | float_rounding_mode = float_round_up; |
| 1701 | | break; |
| 1702 | | } |
| 1703 | | } |
| 1704 | | #endif |
| 1705 | | |
| 1706 | | m68k->remaining_cycles -= 10; |
| 1707 | | } |
| 1708 | | |
| 1709 | | static void fmovem(m68000_base_device *m68k, UINT16 w2) |
| 1710 | | { |
| 1711 | | int i; |
| 1712 | | int ea = m68k->ir & 0x3f; |
| 1713 | | int dir = (w2 >> 13) & 0x1; |
| 1714 | | int mode = (w2 >> 11) & 0x3; |
| 1715 | | int reglist = w2 & 0xff; |
| 1716 | | |
| 1717 | | UINT32 mem_addr = 0; |
| 1718 | | switch (ea >> 3) |
| 1719 | | { |
| 1720 | | case 5: // (d16, An) |
| 1721 | | mem_addr= EA_AY_DI_32(m68k); |
| 1722 | | break; |
| 1723 | | case 6: // (An) + (Xn) + d8 |
| 1724 | | mem_addr= EA_AY_IX_32(m68k); |
| 1725 | | break; |
| 1726 | | } |
| 1727 | | |
| 1728 | | if (dir) // From FP regs to mem |
| 1729 | | { |
| 1730 | | switch (mode) |
| 1731 | | { |
| 1732 | | case 1: // Dynamic register list, postincrement or control addressing mode. |
| 1733 | | // FIXME: not really tested, but seems to work |
| 1734 | | reglist = REG_D(m68k)[(reglist >> 4) & 7]; |
| 1735 | | |
| 1736 | | case 0: // Static register list, predecrement or control addressing mode |
| 1737 | | { |
| 1738 | | for (i=0; i < 8; i++) |
| 1739 | | { |
| 1740 | | if (reglist & (1 << i)) |
| 1741 | | { |
| 1742 | | switch (ea >> 3) |
| 1743 | | { |
| 1744 | | case 5: // (d16, An) |
| 1745 | | case 6: // (An) + (Xn) + d8 |
| 1746 | | store_extended_float80(m68k, mem_addr, REG_FP(m68k)[i]); |
| 1747 | | mem_addr += 12; |
| 1748 | | break; |
| 1749 | | default: |
| 1750 | | WRITE_EA_FPE(m68k, ea, REG_FP(m68k)[i]); |
| 1751 | | break; |
| 1752 | | } |
| 1753 | | |
| 1754 | | m68k->remaining_cycles -= 2; |
| 1755 | | } |
| 1756 | | } |
| 1757 | | break; |
| 1758 | | } |
| 1759 | | |
| 1760 | | case 2: // Static register list, postdecrement or control addressing mode |
| 1761 | | { |
| 1762 | | for (i=0; i < 8; i++) |
| 1763 | | { |
| 1764 | | if (reglist & (1 << i)) |
| 1765 | | { |
| 1766 | | switch (ea >> 3) |
| 1767 | | { |
| 1768 | | case 5: // (d16, An) |
| 1769 | | case 6: // (An) + (Xn) + d8 |
| 1770 | | store_extended_float80(m68k, mem_addr, REG_FP(m68k)[7-i]); |
| 1771 | | mem_addr += 12; |
| 1772 | | break; |
| 1773 | | default: |
| 1774 | | WRITE_EA_FPE(m68k, ea, REG_FP(m68k)[7-i]); |
| 1775 | | break; |
| 1776 | | } |
| 1777 | | |
| 1778 | | m68k->remaining_cycles -= 2; |
| 1779 | | } |
| 1780 | | } |
| 1781 | | break; |
| 1782 | | } |
| 1783 | | |
| 1784 | | default: fatalerror("M680x0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC(m68k)-4); |
| 1785 | | } |
| 1786 | | } |
| 1787 | | else // From mem to FP regs |
| 1788 | | { |
| 1789 | | switch (mode) |
| 1790 | | { |
| 1791 | | case 3: // Dynamic register list, predecrement addressing mode. |
| 1792 | | // FIXME: not really tested, but seems to work |
| 1793 | | reglist = REG_D(m68k)[(reglist >> 4) & 7]; |
| 1794 | | |
| 1795 | | case 2: // Static register list, postincrement or control addressing mode |
| 1796 | | { |
| 1797 | | for (i=0; i < 8; i++) |
| 1798 | | { |
| 1799 | | if (reglist & (1 << i)) |
| 1800 | | { |
| 1801 | | switch (ea >> 3) |
| 1802 | | { |
| 1803 | | case 5: // (d16, An) |
| 1804 | | case 6: // (An) + (Xn) + d8 |
| 1805 | | REG_FP(m68k)[7-i] = load_extended_float80(m68k, mem_addr); |
| 1806 | | mem_addr += 12; |
| 1807 | | break; |
| 1808 | | default: |
| 1809 | | REG_FP(m68k)[7-i] = READ_EA_FPE(m68k, ea); |
| 1810 | | break; |
| 1811 | | } |
| 1812 | | m68k->remaining_cycles -= 2; |
| 1813 | | } |
| 1814 | | } |
| 1815 | | break; |
| 1816 | | } |
| 1817 | | |
| 1818 | | default: fatalerror("M680x0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC(m68k)-4); |
| 1819 | | } |
| 1820 | | } |
| 1821 | | } |
| 1822 | | |
| 1823 | | static void fscc(m68000_base_device *m68k) |
| 1824 | | { |
| 1825 | | int ea = m68k->ir & 0x3f; |
| 1826 | | int condition = (INT16)(OPER_I_16(m68k)); |
| 1827 | | |
| 1828 | | WRITE_EA_8(m68k, ea, TEST_CONDITION(m68k, condition) ? 0xff : 0); |
| 1829 | | m68k->remaining_cycles -= 7; // ??? |
| 1830 | | } |
| 1831 | | |
| 1832 | | static void fbcc16(m68000_base_device *m68k) |
| 1833 | | { |
| 1834 | | INT32 offset; |
| 1835 | | int condition = m68k->ir & 0x3f; |
| 1836 | | |
| 1837 | | offset = (INT16)(OPER_I_16(m68k)); |
| 1838 | | |
| 1839 | | // TODO: condition and jump!!! |
| 1840 | | if (TEST_CONDITION(m68k, condition)) |
| 1841 | | { |
| 1842 | | m68ki_trace_t0(m68k); /* auto-disable (see m68kcpu.h) */ |
| 1843 | | m68ki_branch_16(m68k, offset-2); |
| 1844 | | } |
| 1845 | | |
| 1846 | | m68k->remaining_cycles -= 7; |
| 1847 | | } |
| 1848 | | |
| 1849 | | static void fbcc32(m68000_base_device *m68k) |
| 1850 | | { |
| 1851 | | INT32 offset; |
| 1852 | | int condition = m68k->ir & 0x3f; |
| 1853 | | |
| 1854 | | offset = OPER_I_32(m68k); |
| 1855 | | |
| 1856 | | // TODO: condition and jump!!! |
| 1857 | | if (TEST_CONDITION(m68k, condition)) |
| 1858 | | { |
| 1859 | | m68ki_trace_t0(m68k); /* auto-disable (see m68kcpu.h) */ |
| 1860 | | m68ki_branch_32(m68k, offset-4); |
| 1861 | | } |
| 1862 | | |
| 1863 | | m68k->remaining_cycles -= 7; |
| 1864 | | } |
| 1865 | | |
| 1866 | | |
| 1867 | | void m68040_fpu_op0(m68000_base_device *m68k) |
| 1868 | | { |
| 1869 | | m68k->fpu_just_reset = 0; |
| 1870 | | |
| 1871 | | switch ((m68k->ir >> 6) & 0x3) |
| 1872 | | { |
| 1873 | | case 0: |
| 1874 | | { |
| 1875 | | UINT16 w2 = OPER_I_16(m68k); |
| 1876 | | switch ((w2 >> 13) & 0x7) |
| 1877 | | { |
| 1878 | | case 0x0: // FPU ALU FP, FP |
| 1879 | | case 0x2: // FPU ALU ea, FP |
| 1880 | | { |
| 1881 | | fpgen_rm_reg(m68k, w2); |
| 1882 | | break; |
| 1883 | | } |
| 1884 | | |
| 1885 | | case 0x3: // FMOVE FP, ea |
| 1886 | | { |
| 1887 | | fmove_reg_mem(m68k, w2); |
| 1888 | | break; |
| 1889 | | } |
| 1890 | | |
| 1891 | | case 0x4: // FMOVEM ea, FPCR |
| 1892 | | case 0x5: // FMOVEM FPCR, ea |
| 1893 | | { |
| 1894 | | fmove_fpcr(m68k, w2); |
| 1895 | | break; |
| 1896 | | } |
| 1897 | | |
| 1898 | | case 0x6: // FMOVEM ea, list |
| 1899 | | case 0x7: // FMOVEM list, ea |
| 1900 | | { |
| 1901 | | fmovem(m68k, w2); |
| 1902 | | break; |
| 1903 | | } |
| 1904 | | |
| 1905 | | default: fatalerror("M68kFPU: unimplemented subop %d at %08X\n", (w2 >> 13) & 0x7, REG_PC(m68k)-4); |
| 1906 | | } |
| 1907 | | break; |
| 1908 | | } |
| 1909 | | |
| 1910 | | case 1: // FBcc disp16 |
| 1911 | | { |
| 1912 | | switch ((m68k->ir >> 3) & 0x7) { |
| 1913 | | case 1: // FDBcc |
| 1914 | | // TODO: |
| 1915 | | break; |
| 1916 | | default: // FScc (?) |
| 1917 | | fscc(m68k); |
| 1918 | | return; |
| 1919 | | } |
| 1920 | | fatalerror("M68kFPU: unimplemented main op %d with mode %d at %08X\n", (m68k->ir >> 6) & 0x3, (m68k->ir >> 3) & 0x7, REG_PPC(m68k)); |
| 1921 | | } |
| 1922 | | |
| 1923 | | case 2: // FBcc disp16 |
| 1924 | | { |
| 1925 | | fbcc16(m68k); |
| 1926 | | break; |
| 1927 | | } |
| 1928 | | case 3: // FBcc disp32 |
| 1929 | | { |
| 1930 | | fbcc32(m68k); |
| 1931 | | break; |
| 1932 | | } |
| 1933 | | |
| 1934 | | default: fatalerror("M68kFPU: unimplemented main op %d\n", (m68k->ir >> 6) & 0x3); |
| 1935 | | } |
| 1936 | | } |
| 1937 | | |
| 1938 | | static int perform_fsave(m68000_base_device *m68k, UINT32 addr, int inc) |
| 1939 | | { |
| 1940 | | if(m68k->cpu_type & CPU_TYPE_040) |
| 1941 | | { |
| 1942 | | if(inc) |
| 1943 | | { |
| 1944 | | m68ki_write_32(m68k, addr, 0x41000000); |
| 1945 | | return 4; |
| 1946 | | } |
| 1947 | | else |
| 1948 | | { |
| 1949 | | m68ki_write_32(m68k, addr-4, 0x41000000); |
| 1950 | | return -4; |
| 1951 | | } |
| 1952 | | } |
| 1953 | | |
| 1954 | | if (inc) |
| 1955 | | { |
| 1956 | | // 68881 IDLE, version 0x1f |
| 1957 | | m68ki_write_32(m68k, addr, 0x1f180000); |
| 1958 | | m68ki_write_32(m68k, addr+4, 0); |
| 1959 | | m68ki_write_32(m68k, addr+8, 0); |
| 1960 | | m68ki_write_32(m68k, addr+12, 0); |
| 1961 | | m68ki_write_32(m68k, addr+16, 0); |
| 1962 | | m68ki_write_32(m68k, addr+20, 0); |
| 1963 | | m68ki_write_32(m68k, addr+24, 0x70000000); |
| 1964 | | return 7*4; |
| 1965 | | } |
| 1966 | | else |
| 1967 | | { |
| 1968 | | m68ki_write_32(m68k, addr-4, 0x70000000); |
| 1969 | | m68ki_write_32(m68k, addr-8, 0); |
| 1970 | | m68ki_write_32(m68k, addr-12, 0); |
| 1971 | | m68ki_write_32(m68k, addr-16, 0); |
| 1972 | | m68ki_write_32(m68k, addr-20, 0); |
| 1973 | | m68ki_write_32(m68k, addr-24, 0); |
| 1974 | | m68ki_write_32(m68k, addr-28, 0x1f180000); |
| 1975 | | return -7*4; |
| 1976 | | } |
| 1977 | | } |
| 1978 | | |
| 1979 | | // FRESTORE on a NULL frame reboots the FPU - all registers to NaN, the 3 status regs to 0 |
| 1980 | | static void do_frestore_null(m68000_base_device *m68k) |
| 1981 | | { |
| 1982 | | int i; |
| 1983 | | |
| 1984 | | REG_FPCR(m68k) = 0; |
| 1985 | | REG_FPSR(m68k) = 0; |
| 1986 | | REG_FPIAR(m68k) = 0; |
| 1987 | | for (i = 0; i < 8; i++) |
| 1988 | | { |
| 1989 | | REG_FP(m68k)[i].high = 0x7fff; |
| 1990 | | REG_FP(m68k)[i].low = U64(0xffffffffffffffff); |
| 1991 | | } |
| 1992 | | |
| 1993 | | // Mac IIci at 408458e6 wants an FSAVE of a just-restored NULL frame to also be NULL |
| 1994 | | // The PRM says it's possible to generate a NULL frame, but not how/when/why. (need the 68881/68882 manual!) |
| 1995 | | m68k->fpu_just_reset = 1; |
| 1996 | | } |
| 1997 | | |
| 1998 | | static void m68040_do_fsave(m68000_base_device *m68k, UINT32 addr, int reg, int inc) |
| 1999 | | { |
| 2000 | | if (m68k->fpu_just_reset) |
| 2001 | | { |
| 2002 | | m68ki_write_32(m68k, addr, 0); |
| 2003 | | } |
| 2004 | | else |
| 2005 | | { |
| 2006 | | // we normally generate an IDLE frame |
| 2007 | | int delta = perform_fsave(m68k, addr, inc); |
| 2008 | | if(reg != -1) |
| 2009 | | REG_A(m68k)[reg] += delta; |
| 2010 | | } |
| 2011 | | } |
| 2012 | | |
| 2013 | | static void m68040_do_frestore(m68000_base_device *m68k, UINT32 addr, int reg) |
| 2014 | | { |
| 2015 | | bool m40 = m68k->cpu_type & CPU_TYPE_040; |
| 2016 | | UINT32 temp = m68ki_read_32(m68k, addr); |
| 2017 | | |
| 2018 | | // check for NULL frame |
| 2019 | | if (temp & 0xff000000) |
| 2020 | | { |
| 2021 | | // we don't handle non-NULL frames |
| 2022 | | m68k->fpu_just_reset = 0; |
| 2023 | | |
| 2024 | | if (reg != -1) |
| 2025 | | { |
| 2026 | | // how about an IDLE frame? |
| 2027 | | if (!m40 && ((temp & 0x00ff0000) == 0x00180000)) |
| 2028 | | { |
| 2029 | | REG_A(m68k)[reg] += 7*4; |
| 2030 | | } |
| 2031 | | else if (m40 && ((temp & 0xffff0000) == 0x41000000)) |
| 2032 | | { |
| 2033 | | REG_A(m68k)[reg] += 4; |
| 2034 | | } // check UNIMP |
| 2035 | | else if ((temp & 0x00ff0000) == 0x00380000) |
| 2036 | | { |
| 2037 | | REG_A(m68k)[reg] += 14*4; |
| 2038 | | } // check BUSY |
| 2039 | | else if ((temp & 0x00ff0000) == 0x00b40000) |
| 2040 | | { |
| 2041 | | REG_A(m68k)[reg] += 45*4; |
| 2042 | | } |
| 2043 | | } |
| 2044 | | } |
| 2045 | | else |
| 2046 | | { |
| 2047 | | do_frestore_null(m68k); |
| 2048 | | } |
| 2049 | | } |
| 2050 | | |
| 2051 | | void m68040_fpu_op1(m68000_base_device *m68k) |
| 2052 | | { |
| 2053 | | int ea = m68k->ir & 0x3f; |
| 2054 | | int mode = (ea >> 3) & 0x7; |
| 2055 | | int reg = (ea & 0x7); |
| 2056 | | UINT32 addr; |
| 2057 | | |
| 2058 | | switch ((m68k->ir >> 6) & 0x3) |
| 2059 | | { |
| 2060 | | case 0: // FSAVE <ea> |
| 2061 | | { |
| 2062 | | switch (mode) |
| 2063 | | { |
| 2064 | | case 2: // (An) |
| 2065 | | addr = REG_A(m68k)[reg]; |
| 2066 | | m68040_do_fsave(m68k, addr, -1, 1); |
| 2067 | | break; |
| 2068 | | |
| 2069 | | case 3: // (An)+ |
| 2070 | | addr = EA_AY_PI_32(m68k); |
| 2071 | | m68040_do_fsave(m68k, addr, reg, 1); |
| 2072 | | break; |
| 2073 | | |
| 2074 | | case 4: // -(An) |
| 2075 | | addr = EA_AY_PD_32(m68k); |
| 2076 | | m68040_do_fsave(m68k, addr, reg, 0); |
| 2077 | | break; |
| 2078 | | |
| 2079 | | case 5: // (D16, An) |
| 2080 | | addr = EA_AY_DI_16(m68k); |
| 2081 | | m68040_do_fsave(m68k, addr, -1, 1); |
| 2082 | | break; |
| 2083 | | |
| 2084 | | case 7: // |
| 2085 | | switch (reg) |
| 2086 | | { |
| 2087 | | case 1: // (abs32) |
| 2088 | | { |
| 2089 | | addr = EA_AL_32(m68k); |
| 2090 | | m68040_do_fsave(m68k, addr, -1, 1); |
| 2091 | | break; |
| 2092 | | } |
| 2093 | | case 2: // (d16, PC) |
| 2094 | | { |
| 2095 | | addr = EA_PCDI_16(m68k); |
| 2096 | | m68040_do_fsave(m68k, addr, -1, 1); |
| 2097 | | break; |
| 2098 | | } |
| 2099 | | default: |
| 2100 | | fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); |
| 2101 | | } |
| 2102 | | |
| 2103 | | break; |
| 2104 | | |
| 2105 | | default: |
| 2106 | | fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); |
| 2107 | | } |
| 2108 | | break; |
| 2109 | | } |
| 2110 | | break; |
| 2111 | | |
| 2112 | | case 1: // FRESTORE <ea> |
| 2113 | | { |
| 2114 | | switch (mode) |
| 2115 | | { |
| 2116 | | case 2: // (An) |
| 2117 | | addr = REG_A(m68k)[reg]; |
| 2118 | | m68040_do_frestore(m68k, addr, -1); |
| 2119 | | break; |
| 2120 | | |
| 2121 | | case 3: // (An)+ |
| 2122 | | addr = EA_AY_PI_32(m68k); |
| 2123 | | m68040_do_frestore(m68k, addr, reg); |
| 2124 | | break; |
| 2125 | | |
| 2126 | | case 5: // (D16, An) |
| 2127 | | addr = EA_AY_DI_16(m68k); |
| 2128 | | m68040_do_frestore(m68k, addr, -1); |
| 2129 | | break; |
| 2130 | | |
| 2131 | | case 7: // |
| 2132 | | switch (reg) |
| 2133 | | { |
| 2134 | | case 1: // (abs32) |
| 2135 | | { |
| 2136 | | addr = EA_AL_32(m68k); |
| 2137 | | m68040_do_frestore(m68k, addr, -1); |
| 2138 | | break; |
| 2139 | | } |
| 2140 | | case 2: // (d16, PC) |
| 2141 | | { |
| 2142 | | addr = EA_PCDI_16(m68k); |
| 2143 | | m68040_do_frestore(m68k, addr, -1); |
| 2144 | | break; |
| 2145 | | } |
| 2146 | | default: |
| 2147 | | fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); |
| 2148 | | } |
| 2149 | | |
| 2150 | | break; |
| 2151 | | |
| 2152 | | default: |
| 2153 | | fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); |
| 2154 | | } |
| 2155 | | break; |
| 2156 | | } |
| 2157 | | break; |
| 2158 | | |
| 2159 | | default: fatalerror("m68040_fpu_op1: unimplemented op %d at %08X\n", (m68k->ir >> 6) & 0x3, REG_PC(m68k)-2); |
| 2160 | | } |
| 2161 | | } |
trunk/src/emu/cpu/m68000/m68kfpu.inc
| r0 | r28739 | |
| 1 | #include <math.h> |
| 2 | |
| 3 | #define FPCC_N 0x08000000 |
| 4 | #define FPCC_Z 0x04000000 |
| 5 | #define FPCC_I 0x02000000 |
| 6 | #define FPCC_NAN 0x01000000 |
| 7 | |
| 8 | #define FPES_OE 0x00002000 |
| 9 | #define FPAE_IOP 0x00000080 |
| 10 | |
| 11 | #define DOUBLE_INFINITY U64(0x7ff0000000000000) |
| 12 | #define DOUBLE_EXPONENT U64(0x7ff0000000000000) |
| 13 | #define DOUBLE_MANTISSA U64(0x000fffffffffffff) |
| 14 | |
| 15 | extern flag floatx80_is_nan( floatx80 a ); |
| 16 | |
| 17 | // masks for packed dwords, positive k-factor |
| 18 | static const UINT32 pkmask2[18] = |
| 19 | { |
| 20 | 0xffffffff, 0, 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000, |
| 21 | 0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff, |
| 22 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, |
| 23 | 0xffffffff, 0xffffffff, 0xffffffff |
| 24 | }; |
| 25 | |
| 26 | static const UINT32 pkmask3[18] = |
| 27 | { |
| 28 | 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 29 | 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000, |
| 30 | 0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff, |
| 31 | }; |
| 32 | |
| 33 | INLINE double fx80_to_double(floatx80 fx) |
| 34 | { |
| 35 | UINT64 d; |
| 36 | double *foo; |
| 37 | |
| 38 | foo = (double *)&d; |
| 39 | |
| 40 | d = floatx80_to_float64(fx); |
| 41 | |
| 42 | return *foo; |
| 43 | } |
| 44 | |
| 45 | INLINE floatx80 double_to_fx80(double in) |
| 46 | { |
| 47 | UINT64 *d; |
| 48 | |
| 49 | d = (UINT64 *)∈ |
| 50 | |
| 51 | return float64_to_floatx80(*d); |
| 52 | } |
| 53 | |
| 54 | INLINE floatx80 load_extended_float80(m68000_base_device *m68k, UINT32 ea) |
| 55 | { |
| 56 | UINT32 d1,d2; |
| 57 | UINT16 d3; |
| 58 | floatx80 fp; |
| 59 | |
| 60 | d3 = m68ki_read_16(m68k, ea); |
| 61 | d1 = m68ki_read_32(m68k, ea+4); |
| 62 | d2 = m68ki_read_32(m68k, ea+8); |
| 63 | |
| 64 | fp.high = d3; |
| 65 | fp.low = ((UINT64)d1<<32) | (d2 & 0xffffffff); |
| 66 | |
| 67 | return fp; |
| 68 | } |
| 69 | |
| 70 | INLINE void store_extended_float80(m68000_base_device *m68k, UINT32 ea, floatx80 fpr) |
| 71 | { |
| 72 | m68ki_write_16(m68k, ea+0, fpr.high); |
| 73 | m68ki_write_16(m68k, ea+2, 0); |
| 74 | m68ki_write_32(m68k, ea+4, (fpr.low>>32)&0xffffffff); |
| 75 | m68ki_write_32(m68k, ea+8, fpr.low&0xffffffff); |
| 76 | } |
| 77 | |
| 78 | INLINE floatx80 load_pack_float80(m68000_base_device *m68k, UINT32 ea) |
| 79 | { |
| 80 | UINT32 dw1, dw2, dw3; |
| 81 | floatx80 result; |
| 82 | double tmp; |
| 83 | char str[128], *ch; |
| 84 | |
| 85 | dw1 = m68ki_read_32(m68k, ea); |
| 86 | dw2 = m68ki_read_32(m68k, ea+4); |
| 87 | dw3 = m68ki_read_32(m68k, ea+8); |
| 88 | |
| 89 | ch = &str[0]; |
| 90 | if (dw1 & 0x80000000) // mantissa sign |
| 91 | { |
| 92 | *ch++ = '-'; |
| 93 | } |
| 94 | *ch++ = (char)((dw1 & 0xf) + '0'); |
| 95 | *ch++ = '.'; |
| 96 | *ch++ = (char)(((dw2 >> 28) & 0xf) + '0'); |
| 97 | *ch++ = (char)(((dw2 >> 24) & 0xf) + '0'); |
| 98 | *ch++ = (char)(((dw2 >> 20) & 0xf) + '0'); |
| 99 | *ch++ = (char)(((dw2 >> 16) & 0xf) + '0'); |
| 100 | *ch++ = (char)(((dw2 >> 12) & 0xf) + '0'); |
| 101 | *ch++ = (char)(((dw2 >> 8) & 0xf) + '0'); |
| 102 | *ch++ = (char)(((dw2 >> 4) & 0xf) + '0'); |
| 103 | *ch++ = (char)(((dw2 >> 0) & 0xf) + '0'); |
| 104 | *ch++ = (char)(((dw3 >> 28) & 0xf) + '0'); |
| 105 | *ch++ = (char)(((dw3 >> 24) & 0xf) + '0'); |
| 106 | *ch++ = (char)(((dw3 >> 20) & 0xf) + '0'); |
| 107 | *ch++ = (char)(((dw3 >> 16) & 0xf) + '0'); |
| 108 | *ch++ = (char)(((dw3 >> 12) & 0xf) + '0'); |
| 109 | *ch++ = (char)(((dw3 >> 8) & 0xf) + '0'); |
| 110 | *ch++ = (char)(((dw3 >> 4) & 0xf) + '0'); |
| 111 | *ch++ = (char)(((dw3 >> 0) & 0xf) + '0'); |
| 112 | *ch++ = 'E'; |
| 113 | if (dw1 & 0x40000000) // exponent sign |
| 114 | { |
| 115 | *ch++ = '-'; |
| 116 | } |
| 117 | *ch++ = (char)(((dw1 >> 24) & 0xf) + '0'); |
| 118 | *ch++ = (char)(((dw1 >> 20) & 0xf) + '0'); |
| 119 | *ch++ = (char)(((dw1 >> 16) & 0xf) + '0'); |
| 120 | *ch = '\0'; |
| 121 | |
| 122 | sscanf(str, "%le", &tmp); |
| 123 | |
| 124 | result = double_to_fx80(tmp); |
| 125 | |
| 126 | return result; |
| 127 | } |
| 128 | |
| 129 | INLINE void store_pack_float80(m68000_base_device *m68k, UINT32 ea, int k, floatx80 fpr) |
| 130 | { |
| 131 | UINT32 dw1, dw2, dw3; |
| 132 | char str[128], *ch; |
| 133 | int i, j, exp; |
| 134 | |
| 135 | dw1 = dw2 = dw3 = 0; |
| 136 | ch = &str[0]; |
| 137 | |
| 138 | sprintf(str, "%.16e", fx80_to_double(fpr)); |
| 139 | |
| 140 | if (*ch == '-') |
| 141 | { |
| 142 | ch++; |
| 143 | dw1 = 0x80000000; |
| 144 | } |
| 145 | |
| 146 | if (*ch == '+') |
| 147 | { |
| 148 | ch++; |
| 149 | } |
| 150 | |
| 151 | dw1 |= (*ch++ - '0'); |
| 152 | |
| 153 | if (*ch == '.') |
| 154 | { |
| 155 | ch++; |
| 156 | } |
| 157 | |
| 158 | // handle negative k-factor here |
| 159 | if ((k <= 0) && (k >= -13)) |
| 160 | { |
| 161 | exp = 0; |
| 162 | for (i = 0; i < 3; i++) |
| 163 | { |
| 164 | if (ch[18+i] >= '0' && ch[18+i] <= '9') |
| 165 | { |
| 166 | exp = (exp << 4) | (ch[18+i] - '0'); |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | if (ch[17] == '-') |
| 171 | { |
| 172 | exp = -exp; |
| 173 | } |
| 174 | |
| 175 | k = -k; |
| 176 | // last digit is (k + exponent - 1) |
| 177 | k += (exp - 1); |
| 178 | |
| 179 | // round up the last significant mantissa digit |
| 180 | if (ch[k+1] >= '5') |
| 181 | { |
| 182 | ch[k]++; |
| 183 | } |
| 184 | |
| 185 | // zero out the rest of the mantissa digits |
| 186 | for (j = (k+1); j < 16; j++) |
| 187 | { |
| 188 | ch[j] = '0'; |
| 189 | } |
| 190 | |
| 191 | // now zero out K to avoid tripping the positive K detection below |
| 192 | k = 0; |
| 193 | } |
| 194 | |
| 195 | // crack 8 digits of the mantissa |
| 196 | for (i = 0; i < 8; i++) |
| 197 | { |
| 198 | dw2 <<= 4; |
| 199 | if (*ch >= '0' && *ch <= '9') |
| 200 | { |
| 201 | dw2 |= *ch++ - '0'; |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | // next 8 digits of the mantissa |
| 206 | for (i = 0; i < 8; i++) |
| 207 | { |
| 208 | dw3 <<= 4; |
| 209 | if (*ch >= '0' && *ch <= '9') |
| 210 | dw3 |= *ch++ - '0'; |
| 211 | } |
| 212 | |
| 213 | // handle masking if k is positive |
| 214 | if (k >= 1) |
| 215 | { |
| 216 | if (k <= 17) |
| 217 | { |
| 218 | dw2 &= pkmask2[k]; |
| 219 | dw3 &= pkmask3[k]; |
| 220 | } |
| 221 | else |
| 222 | { |
| 223 | dw2 &= pkmask2[17]; |
| 224 | dw3 &= pkmask3[17]; |
| 225 | // m68k->fpcr |= (need to set OPERR bit) |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | // finally, crack the exponent |
| 230 | if (*ch == 'e' || *ch == 'E') |
| 231 | { |
| 232 | ch++; |
| 233 | if (*ch == '-') |
| 234 | { |
| 235 | ch++; |
| 236 | dw1 |= 0x40000000; |
| 237 | } |
| 238 | |
| 239 | if (*ch == '+') |
| 240 | { |
| 241 | ch++; |
| 242 | } |
| 243 | |
| 244 | j = 0; |
| 245 | for (i = 0; i < 3; i++) |
| 246 | { |
| 247 | if (*ch >= '0' && *ch <= '9') |
| 248 | { |
| 249 | j = (j << 4) | (*ch++ - '0'); |
| 250 | } |
| 251 | } |
| 252 | |
| 253 | dw1 |= (j << 16); |
| 254 | } |
| 255 | |
| 256 | m68ki_write_32(m68k, ea, dw1); |
| 257 | m68ki_write_32(m68k, ea+4, dw2); |
| 258 | m68ki_write_32(m68k, ea+8, dw3); |
| 259 | } |
| 260 | |
| 261 | INLINE void SET_CONDITION_CODES(m68000_base_device *m68k, floatx80 reg) |
| 262 | { |
| 263 | // UINT64 *regi; |
| 264 | |
| 265 | // regi = (UINT64 *)® |
| 266 | |
| 267 | REG_FPSR(m68k) &= ~(FPCC_N|FPCC_Z|FPCC_I|FPCC_NAN); |
| 268 | |
| 269 | // sign flag |
| 270 | if (reg.high & 0x8000) |
| 271 | { |
| 272 | REG_FPSR(m68k) |= FPCC_N; |
| 273 | } |
| 274 | |
| 275 | // zero flag |
| 276 | if (((reg.high & 0x7fff) == 0) && ((reg.low<<1) == 0)) |
| 277 | { |
| 278 | REG_FPSR(m68k) |= FPCC_Z; |
| 279 | } |
| 280 | |
| 281 | // infinity flag |
| 282 | if (((reg.high & 0x7fff) == 0x7fff) && ((reg.low<<1) == 0)) |
| 283 | { |
| 284 | REG_FPSR(m68k) |= FPCC_I; |
| 285 | } |
| 286 | |
| 287 | // NaN flag |
| 288 | if (floatx80_is_nan(reg)) |
| 289 | { |
| 290 | REG_FPSR(m68k) |= FPCC_NAN; |
| 291 | } |
| 292 | } |
| 293 | |
| 294 | INLINE int TEST_CONDITION(m68000_base_device *m68k, int condition) |
| 295 | { |
| 296 | int n = (REG_FPSR(m68k) & FPCC_N) != 0; |
| 297 | int z = (REG_FPSR(m68k) & FPCC_Z) != 0; |
| 298 | int nan = (REG_FPSR(m68k) & FPCC_NAN) != 0; |
| 299 | int r = 0; |
| 300 | switch (condition) |
| 301 | { |
| 302 | case 0x10: |
| 303 | case 0x00: return 0; // False |
| 304 | |
| 305 | case 0x11: |
| 306 | case 0x01: return (z); // Equal |
| 307 | |
| 308 | case 0x12: |
| 309 | case 0x02: return (!(nan || z || n)); // Greater Than |
| 310 | |
| 311 | case 0x13: |
| 312 | case 0x03: return (z || !(nan || n)); // Greater or Equal |
| 313 | |
| 314 | case 0x14: |
| 315 | case 0x04: return (n && !(nan || z)); // Less Than |
| 316 | |
| 317 | case 0x15: |
| 318 | case 0x05: return (z || (n && !nan)); // Less Than or Equal |
| 319 | |
| 320 | case 0x16: |
| 321 | case 0x06: return !nan && !z; |
| 322 | |
| 323 | case 0x17: |
| 324 | case 0x07: return !nan; |
| 325 | |
| 326 | case 0x18: |
| 327 | case 0x08: return nan; |
| 328 | |
| 329 | case 0x19: |
| 330 | case 0x09: return nan || z; |
| 331 | |
| 332 | case 0x1a: |
| 333 | case 0x0a: return (nan || !(n || z)); // Not Less Than or Equal |
| 334 | |
| 335 | case 0x1b: |
| 336 | case 0x0b: return (nan || z || !n); // Not Less Than |
| 337 | |
| 338 | case 0x1c: |
| 339 | case 0x0c: return (nan || (n && !z)); // Not Greater or Equal Than |
| 340 | |
| 341 | case 0x1d: |
| 342 | case 0x0d: return (nan || z || n); // Not Greater Than |
| 343 | |
| 344 | case 0x1e: |
| 345 | case 0x0e: return (!z); // Not Equal |
| 346 | |
| 347 | case 0x1f: |
| 348 | case 0x0f: return 1; // True |
| 349 | |
| 350 | default: fatalerror("M68kFPU: test_condition: unhandled condition %02X\n", condition); |
| 351 | } |
| 352 | |
| 353 | return r; |
| 354 | } |
| 355 | |
| 356 | static UINT8 READ_EA_8(m68000_base_device *m68k, int ea) |
| 357 | { |
| 358 | int mode = (ea >> 3) & 0x7; |
| 359 | int reg = (ea & 0x7); |
| 360 | |
| 361 | switch (mode) |
| 362 | { |
| 363 | case 0: // Dn |
| 364 | { |
| 365 | return REG_D(m68k)[reg]; |
| 366 | } |
| 367 | case 2: // (An) |
| 368 | { |
| 369 | UINT32 ea = REG_A(m68k)[reg]; |
| 370 | return m68ki_read_8(m68k, ea); |
| 371 | } |
| 372 | case 3: // (An)+ |
| 373 | { |
| 374 | UINT32 ea = EA_AY_PI_8(m68k); |
| 375 | return m68ki_read_8(m68k, ea); |
| 376 | } |
| 377 | case 4: // -(An) |
| 378 | { |
| 379 | UINT32 ea = EA_AY_PD_8(m68k); |
| 380 | return m68ki_read_8(m68k, ea); |
| 381 | } |
| 382 | case 5: // (d16, An) |
| 383 | { |
| 384 | UINT32 ea = EA_AY_DI_8(m68k); |
| 385 | return m68ki_read_8(m68k, ea); |
| 386 | } |
| 387 | case 6: // (An) + (Xn) + d8 |
| 388 | { |
| 389 | UINT32 ea = EA_AY_IX_8(m68k); |
| 390 | return m68ki_read_8(m68k, ea); |
| 391 | } |
| 392 | case 7: |
| 393 | { |
| 394 | switch (reg) |
| 395 | { |
| 396 | case 0: // (xxx).W |
| 397 | { |
| 398 | UINT32 ea = (UINT32)OPER_I_16(m68k); |
| 399 | return m68ki_read_8(m68k, ea); |
| 400 | } |
| 401 | case 1: // (xxx).L |
| 402 | { |
| 403 | UINT32 d1 = OPER_I_16(m68k); |
| 404 | UINT32 d2 = OPER_I_16(m68k); |
| 405 | UINT32 ea = (d1 << 16) | d2; |
| 406 | return m68ki_read_8(m68k, ea); |
| 407 | } |
| 408 | case 2: // (d16, PC) |
| 409 | { |
| 410 | UINT32 ea = EA_PCDI_8(m68k); |
| 411 | return m68ki_read_8(m68k, ea); |
| 412 | } |
| 413 | case 3: // (PC) + (Xn) + d8 |
| 414 | { |
| 415 | UINT32 ea = EA_PCIX_8(m68k); |
| 416 | return m68ki_read_8(m68k, ea); |
| 417 | } |
| 418 | case 4: // #<data> |
| 419 | { |
| 420 | return OPER_I_8(m68k); |
| 421 | } |
| 422 | default: fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 423 | } |
| 424 | break; |
| 425 | } |
| 426 | default: fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 427 | } |
| 428 | |
| 429 | return 0; |
| 430 | } |
| 431 | |
| 432 | static UINT16 READ_EA_16(m68000_base_device *m68k, int ea) |
| 433 | { |
| 434 | int mode = (ea >> 3) & 0x7; |
| 435 | int reg = (ea & 0x7); |
| 436 | |
| 437 | switch (mode) |
| 438 | { |
| 439 | case 0: // Dn |
| 440 | { |
| 441 | return (UINT16)(REG_D(m68k)[reg]); |
| 442 | } |
| 443 | case 2: // (An) |
| 444 | { |
| 445 | UINT32 ea = REG_A(m68k)[reg]; |
| 446 | return m68ki_read_16(m68k, ea); |
| 447 | } |
| 448 | case 3: // (An)+ |
| 449 | { |
| 450 | UINT32 ea = EA_AY_PI_16(m68k); |
| 451 | return m68ki_read_16(m68k, ea); |
| 452 | } |
| 453 | case 4: // -(An) |
| 454 | { |
| 455 | UINT32 ea = EA_AY_PD_16(m68k); |
| 456 | return m68ki_read_16(m68k, ea); |
| 457 | } |
| 458 | case 5: // (d16, An) |
| 459 | { |
| 460 | UINT32 ea = EA_AY_DI_16(m68k); |
| 461 | return m68ki_read_16(m68k, ea); |
| 462 | } |
| 463 | case 6: // (An) + (Xn) + d8 |
| 464 | { |
| 465 | UINT32 ea = EA_AY_IX_16(m68k); |
| 466 | return m68ki_read_16(m68k, ea); |
| 467 | } |
| 468 | case 7: |
| 469 | { |
| 470 | switch (reg) |
| 471 | { |
| 472 | case 0: // (xxx).W |
| 473 | { |
| 474 | UINT32 ea = (UINT32)OPER_I_16(m68k); |
| 475 | return m68ki_read_16(m68k, ea); |
| 476 | } |
| 477 | case 1: // (xxx).L |
| 478 | { |
| 479 | UINT32 d1 = OPER_I_16(m68k); |
| 480 | UINT32 d2 = OPER_I_16(m68k); |
| 481 | UINT32 ea = (d1 << 16) | d2; |
| 482 | return m68ki_read_16(m68k, ea); |
| 483 | } |
| 484 | case 2: // (d16, PC) |
| 485 | { |
| 486 | UINT32 ea = EA_PCDI_16(m68k); |
| 487 | return m68ki_read_16(m68k, ea); |
| 488 | } |
| 489 | case 3: // (PC) + (Xn) + d8 |
| 490 | { |
| 491 | UINT32 ea = EA_PCIX_16(m68k); |
| 492 | return m68ki_read_16(m68k, ea); |
| 493 | } |
| 494 | case 4: // #<data> |
| 495 | { |
| 496 | return OPER_I_16(m68k); |
| 497 | } |
| 498 | |
| 499 | default: fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 500 | } |
| 501 | break; |
| 502 | } |
| 503 | default: fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 504 | } |
| 505 | |
| 506 | return 0; |
| 507 | } |
| 508 | |
| 509 | static UINT32 READ_EA_32(m68000_base_device *m68k, int ea) |
| 510 | { |
| 511 | int mode = (ea >> 3) & 0x7; |
| 512 | int reg = (ea & 0x7); |
| 513 | |
| 514 | switch (mode) |
| 515 | { |
| 516 | case 0: // Dn |
| 517 | { |
| 518 | return REG_D(m68k)[reg]; |
| 519 | } |
| 520 | case 2: // (An) |
| 521 | { |
| 522 | UINT32 ea = REG_A(m68k)[reg]; |
| 523 | return m68ki_read_32(m68k, ea); |
| 524 | } |
| 525 | case 3: // (An)+ |
| 526 | { |
| 527 | UINT32 ea = EA_AY_PI_32(m68k); |
| 528 | return m68ki_read_32(m68k, ea); |
| 529 | } |
| 530 | case 4: // -(An) |
| 531 | { |
| 532 | UINT32 ea = EA_AY_PD_32(m68k); |
| 533 | return m68ki_read_32(m68k, ea); |
| 534 | } |
| 535 | case 5: // (d16, An) |
| 536 | { |
| 537 | UINT32 ea = EA_AY_DI_32(m68k); |
| 538 | return m68ki_read_32(m68k, ea); |
| 539 | } |
| 540 | case 6: // (An) + (Xn) + d8 |
| 541 | { |
| 542 | UINT32 ea = EA_AY_IX_32(m68k); |
| 543 | return m68ki_read_32(m68k, ea); |
| 544 | } |
| 545 | case 7: |
| 546 | { |
| 547 | switch (reg) |
| 548 | { |
| 549 | case 0: // (xxx).W |
| 550 | { |
| 551 | UINT32 ea = (UINT32)OPER_I_16(m68k); |
| 552 | return m68ki_read_32(m68k, ea); |
| 553 | } |
| 554 | case 1: // (xxx).L |
| 555 | { |
| 556 | UINT32 d1 = OPER_I_16(m68k); |
| 557 | UINT32 d2 = OPER_I_16(m68k); |
| 558 | UINT32 ea = (d1 << 16) | d2; |
| 559 | return m68ki_read_32(m68k, ea); |
| 560 | } |
| 561 | case 2: // (d16, PC) |
| 562 | { |
| 563 | UINT32 ea = EA_PCDI_32(m68k); |
| 564 | return m68ki_read_32(m68k, ea); |
| 565 | } |
| 566 | case 3: // (PC) + (Xn) + d8 |
| 567 | { |
| 568 | UINT32 ea = EA_PCIX_32(m68k); |
| 569 | return m68ki_read_32(m68k, ea); |
| 570 | } |
| 571 | case 4: // #<data> |
| 572 | { |
| 573 | return OPER_I_32(m68k); |
| 574 | } |
| 575 | default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 576 | } |
| 577 | break; |
| 578 | } |
| 579 | default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 580 | } |
| 581 | return 0; |
| 582 | } |
| 583 | |
| 584 | static UINT64 READ_EA_64(m68000_base_device *m68k, int ea) |
| 585 | { |
| 586 | int mode = (ea >> 3) & 0x7; |
| 587 | int reg = (ea & 0x7); |
| 588 | UINT32 h1, h2; |
| 589 | |
| 590 | switch (mode) |
| 591 | { |
| 592 | case 2: // (An) |
| 593 | { |
| 594 | UINT32 ea = REG_A(m68k)[reg]; |
| 595 | h1 = m68ki_read_32(m68k, ea+0); |
| 596 | h2 = m68ki_read_32(m68k, ea+4); |
| 597 | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 598 | } |
| 599 | case 3: // (An)+ |
| 600 | { |
| 601 | UINT32 ea = REG_A(m68k)[reg]; |
| 602 | REG_A(m68k)[reg] += 8; |
| 603 | h1 = m68ki_read_32(m68k, ea+0); |
| 604 | h2 = m68ki_read_32(m68k, ea+4); |
| 605 | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 606 | } |
| 607 | case 4: // -(An) |
| 608 | { |
| 609 | UINT32 ea = REG_A(m68k)[reg]-8; |
| 610 | REG_A(m68k)[reg] -= 8; |
| 611 | h1 = m68ki_read_32(m68k, ea+0); |
| 612 | h2 = m68ki_read_32(m68k, ea+4); |
| 613 | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 614 | } |
| 615 | case 5: // (d16, An) |
| 616 | { |
| 617 | UINT32 ea = EA_AY_DI_32(m68k); |
| 618 | h1 = m68ki_read_32(m68k, ea+0); |
| 619 | h2 = m68ki_read_32(m68k, ea+4); |
| 620 | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 621 | } |
| 622 | case 6: // (An) + (Xn) + d8 |
| 623 | { |
| 624 | UINT32 ea = EA_AY_IX_32(m68k); |
| 625 | h1 = m68ki_read_32(m68k, ea+0); |
| 626 | h2 = m68ki_read_32(m68k, ea+4); |
| 627 | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 628 | } |
| 629 | case 7: |
| 630 | { |
| 631 | switch (reg) |
| 632 | { |
| 633 | case 1: // (xxx).L |
| 634 | { |
| 635 | UINT32 d1 = OPER_I_16(m68k); |
| 636 | UINT32 d2 = OPER_I_16(m68k); |
| 637 | UINT32 ea = (d1 << 16) | d2; |
| 638 | return (UINT64)(m68ki_read_32(m68k, ea)) << 32 | (UINT64)(m68ki_read_32(m68k, ea+4)); |
| 639 | } |
| 640 | case 3: // (PC) + (Xn) + d8 |
| 641 | { |
| 642 | UINT32 ea = EA_PCIX_32(m68k); |
| 643 | h1 = m68ki_read_32(m68k, ea+0); |
| 644 | h2 = m68ki_read_32(m68k, ea+4); |
| 645 | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 646 | } |
| 647 | case 4: // #<data> |
| 648 | { |
| 649 | h1 = OPER_I_32(m68k); |
| 650 | h2 = OPER_I_32(m68k); |
| 651 | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 652 | } |
| 653 | case 2: // (d16, PC) |
| 654 | { |
| 655 | UINT32 ea = EA_PCDI_32(m68k); |
| 656 | h1 = m68ki_read_32(m68k, ea+0); |
| 657 | h2 = m68ki_read_32(m68k, ea+4); |
| 658 | return (UINT64)(h1) << 32 | (UINT64)(h2); |
| 659 | } |
| 660 | default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 661 | } |
| 662 | break; |
| 663 | } |
| 664 | default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 665 | } |
| 666 | |
| 667 | return 0; |
| 668 | } |
| 669 | |
| 670 | |
| 671 | static floatx80 READ_EA_FPE(m68000_base_device *m68k, int ea) |
| 672 | { |
| 673 | floatx80 fpr; |
| 674 | int mode = (ea >> 3) & 0x7; |
| 675 | int reg = (ea & 0x7); |
| 676 | |
| 677 | switch (mode) |
| 678 | { |
| 679 | case 2: // (An) |
| 680 | { |
| 681 | UINT32 ea = REG_A(m68k)[reg]; |
| 682 | fpr = load_extended_float80(m68k, ea); |
| 683 | break; |
| 684 | } |
| 685 | |
| 686 | case 3: // (An)+ |
| 687 | { |
| 688 | UINT32 ea = REG_A(m68k)[reg]; |
| 689 | REG_A(m68k)[reg] += 12; |
| 690 | fpr = load_extended_float80(m68k, ea); |
| 691 | break; |
| 692 | } |
| 693 | case 4: // -(An) |
| 694 | { |
| 695 | UINT32 ea = REG_A(m68k)[reg]-12; |
| 696 | REG_A(m68k)[reg] -= 12; |
| 697 | fpr = load_extended_float80(m68k, ea); |
| 698 | break; |
| 699 | } |
| 700 | case 5: // (d16, An) |
| 701 | { |
| 702 | // FIXME: will fail for fmovem |
| 703 | UINT32 ea = EA_AY_DI_32(m68k); |
| 704 | fpr = load_extended_float80(m68k, ea); |
| 705 | break; |
| 706 | } |
| 707 | case 6: // (An) + (Xn) + d8 |
| 708 | { |
| 709 | // FIXME: will fail for fmovem |
| 710 | UINT32 ea = EA_AY_IX_32(m68k); |
| 711 | fpr = load_extended_float80(m68k, ea); |
| 712 | break; |
| 713 | } |
| 714 | |
| 715 | case 7: // extended modes |
| 716 | { |
| 717 | switch (reg) |
| 718 | { |
| 719 | case 2: // (d16, PC) |
| 720 | { |
| 721 | UINT32 ea = EA_PCDI_32(m68k); |
| 722 | fpr = load_extended_float80(m68k, ea); |
| 723 | } |
| 724 | break; |
| 725 | |
| 726 | case 3: // (d16,PC,Dx.w) |
| 727 | { |
| 728 | UINT32 ea = EA_PCIX_32(m68k); |
| 729 | fpr = load_extended_float80(m68k, ea); |
| 730 | } |
| 731 | break; |
| 732 | |
| 733 | default: |
| 734 | fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); |
| 735 | break; |
| 736 | } |
| 737 | } |
| 738 | break; |
| 739 | |
| 740 | default: fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); break; |
| 741 | } |
| 742 | |
| 743 | return fpr; |
| 744 | } |
| 745 | |
| 746 | static floatx80 READ_EA_PACK(m68000_base_device *m68k, int ea) |
| 747 | { |
| 748 | floatx80 fpr; |
| 749 | int mode = (ea >> 3) & 0x7; |
| 750 | int reg = (ea & 0x7); |
| 751 | |
| 752 | switch (mode) |
| 753 | { |
| 754 | case 2: // (An) |
| 755 | { |
| 756 | UINT32 ea = REG_A(m68k)[reg]; |
| 757 | fpr = load_pack_float80(m68k, ea); |
| 758 | break; |
| 759 | } |
| 760 | |
| 761 | case 3: // (An)+ |
| 762 | { |
| 763 | UINT32 ea = REG_A(m68k)[reg]; |
| 764 | REG_A(m68k)[reg] += 12; |
| 765 | fpr = load_pack_float80(m68k, ea); |
| 766 | break; |
| 767 | } |
| 768 | |
| 769 | case 7: // extended modes |
| 770 | { |
| 771 | switch (reg) |
| 772 | { |
| 773 | case 3: // (d16,PC,Dx.w) |
| 774 | { |
| 775 | UINT32 ea = EA_PCIX_32(m68k); |
| 776 | fpr = load_pack_float80(m68k, ea); |
| 777 | } |
| 778 | break; |
| 779 | |
| 780 | default: |
| 781 | fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); |
| 782 | break; |
| 783 | } |
| 784 | } |
| 785 | break; |
| 786 | |
| 787 | default: fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); break; |
| 788 | } |
| 789 | |
| 790 | return fpr; |
| 791 | } |
| 792 | |
| 793 | static void WRITE_EA_8(m68000_base_device *m68k, int ea, UINT8 data) |
| 794 | { |
| 795 | int mode = (ea >> 3) & 0x7; |
| 796 | int reg = (ea & 0x7); |
| 797 | |
| 798 | switch (mode) |
| 799 | { |
| 800 | case 0: // Dn |
| 801 | { |
| 802 | REG_D(m68k)[reg] = data; |
| 803 | break; |
| 804 | } |
| 805 | case 2: // (An) |
| 806 | { |
| 807 | UINT32 ea = REG_A(m68k)[reg]; |
| 808 | m68ki_write_8(m68k, ea, data); |
| 809 | break; |
| 810 | } |
| 811 | case 3: // (An)+ |
| 812 | { |
| 813 | UINT32 ea = EA_AY_PI_8(m68k); |
| 814 | m68ki_write_8(m68k, ea, data); |
| 815 | break; |
| 816 | } |
| 817 | case 4: // -(An) |
| 818 | { |
| 819 | UINT32 ea = EA_AY_PD_8(m68k); |
| 820 | m68ki_write_8(m68k, ea, data); |
| 821 | break; |
| 822 | } |
| 823 | case 5: // (d16, An) |
| 824 | { |
| 825 | UINT32 ea = EA_AY_DI_8(m68k); |
| 826 | m68ki_write_8(m68k, ea, data); |
| 827 | break; |
| 828 | } |
| 829 | case 6: // (An) + (Xn) + d8 |
| 830 | { |
| 831 | UINT32 ea = EA_AY_IX_8(m68k); |
| 832 | m68ki_write_8(m68k, ea, data); |
| 833 | break; |
| 834 | } |
| 835 | case 7: |
| 836 | { |
| 837 | switch (reg) |
| 838 | { |
| 839 | case 1: // (xxx).B |
| 840 | { |
| 841 | UINT32 d1 = OPER_I_16(m68k); |
| 842 | UINT32 d2 = OPER_I_16(m68k); |
| 843 | UINT32 ea = (d1 << 16) | d2; |
| 844 | m68ki_write_8(m68k, ea, data); |
| 845 | break; |
| 846 | } |
| 847 | case 2: // (d16, PC) |
| 848 | { |
| 849 | UINT32 ea = EA_PCDI_16(m68k); |
| 850 | m68ki_write_8(m68k, ea, data); |
| 851 | break; |
| 852 | } |
| 853 | default: fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 854 | } |
| 855 | break; |
| 856 | } |
| 857 | default: fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC(m68k)); |
| 858 | } |
| 859 | } |
| 860 | |
| 861 | static void WRITE_EA_16(m68000_base_device *m68k, int ea, UINT16 data) |
| 862 | { |
| 863 | int mode = (ea >> 3) & 0x7; |
| 864 | int reg = (ea & 0x7); |
| 865 | |
| 866 | switch (mode) |
| 867 | { |
| 868 | case 0: // Dn |
| 869 | { |
| 870 | REG_D(m68k)[reg] = data; |
| 871 | break; |
| 872 | } |
| 873 | case 2: // (An) |
| 874 | { |
| 875 | UINT32 ea = REG_A(m68k)[reg]; |
| 876 | m68ki_write_16(m68k, ea, data); |
| 877 | break; |
| 878 | } |
| 879 | case 3: // (An)+ |
| 880 | { |
| 881 | UINT32 ea = EA_AY_PI_16(m68k); |
| 882 | m68ki_write_16(m68k, ea, data); |
| 883 | break; |
| 884 | } |
| 885 | case 4: // -(An) |
| 886 | { |
| 887 | UINT32 ea = EA_AY_PD_16(m68k); |
| 888 | m68ki_write_16(m68k, ea, data); |
| 889 | break; |
| 890 | } |
| 891 | case 5: // (d16, An) |
| 892 | { |
| 893 | UINT32 ea = EA_AY_DI_16(m68k); |
| 894 | m68ki_write_16(m68k, ea, data); |
| 895 | break; |
| 896 | } |
| 897 | case 6: // (An) + (Xn) + d8 |
| 898 | { |
| 899 | UINT32 ea = EA_AY_IX_16(m68k); |
| 900 | m68ki_write_16(m68k, ea, data); |
| 901 | break; |
| 902 | } |
| 903 | case 7: |
| 904 | { |
| 905 | switch (reg) |
| 906 | { |
| 907 | case 1: // (xxx).W |
| 908 | { |
| 909 | UINT32 d1 = OPER_I_16(m68k); |
| 910 | UINT32 d2 = OPER_I_16(m68k); |
| 911 | UINT32 ea = (d1 << 16) | d2; |
| 912 | m68ki_write_16(m68k, ea, data); |
| 913 | break; |
| 914 | } |
| 915 | case 2: // (d16, PC) |
| 916 | { |
| 917 | UINT32 ea = EA_PCDI_16(m68k); |
| 918 | m68ki_write_16(m68k, ea, data); |
| 919 | break; |
| 920 | } |
| 921 | default: fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 922 | } |
| 923 | break; |
| 924 | } |
| 925 | default: fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC(m68k)); |
| 926 | } |
| 927 | } |
| 928 | |
| 929 | static void WRITE_EA_32(m68000_base_device *m68k, int ea, UINT32 data) |
| 930 | { |
| 931 | int mode = (ea >> 3) & 0x7; |
| 932 | int reg = (ea & 0x7); |
| 933 | |
| 934 | switch (mode) |
| 935 | { |
| 936 | case 0: // Dn |
| 937 | { |
| 938 | REG_D(m68k)[reg] = data; |
| 939 | break; |
| 940 | } |
| 941 | case 1: // An |
| 942 | { |
| 943 | REG_A(m68k)[reg] = data; |
| 944 | break; |
| 945 | } |
| 946 | case 2: // (An) |
| 947 | { |
| 948 | UINT32 ea = REG_A(m68k)[reg]; |
| 949 | m68ki_write_32(m68k, ea, data); |
| 950 | break; |
| 951 | } |
| 952 | case 3: // (An)+ |
| 953 | { |
| 954 | UINT32 ea = EA_AY_PI_32(m68k); |
| 955 | m68ki_write_32(m68k, ea, data); |
| 956 | break; |
| 957 | } |
| 958 | case 4: // -(An) |
| 959 | { |
| 960 | UINT32 ea = EA_AY_PD_32(m68k); |
| 961 | m68ki_write_32(m68k, ea, data); |
| 962 | break; |
| 963 | } |
| 964 | case 5: // (d16, An) |
| 965 | { |
| 966 | UINT32 ea = EA_AY_DI_32(m68k); |
| 967 | m68ki_write_32(m68k, ea, data); |
| 968 | break; |
| 969 | } |
| 970 | case 6: // (An) + (Xn) + d8 |
| 971 | { |
| 972 | UINT32 ea = EA_AY_IX_32(m68k); |
| 973 | m68ki_write_32(m68k, ea, data); |
| 974 | break; |
| 975 | } |
| 976 | case 7: |
| 977 | { |
| 978 | switch (reg) |
| 979 | { |
| 980 | case 1: // (xxx).L |
| 981 | { |
| 982 | UINT32 d1 = OPER_I_16(m68k); |
| 983 | UINT32 d2 = OPER_I_16(m68k); |
| 984 | UINT32 ea = (d1 << 16) | d2; |
| 985 | m68ki_write_32(m68k, ea, data); |
| 986 | break; |
| 987 | } |
| 988 | case 2: // (d16, PC) |
| 989 | { |
| 990 | UINT32 ea = EA_PCDI_32(m68k); |
| 991 | m68ki_write_32(m68k, ea, data); |
| 992 | break; |
| 993 | } |
| 994 | default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 995 | } |
| 996 | break; |
| 997 | } |
| 998 | default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC(m68k)); |
| 999 | } |
| 1000 | } |
| 1001 | |
| 1002 | static void WRITE_EA_64(m68000_base_device *m68k, int ea, UINT64 data) |
| 1003 | { |
| 1004 | int mode = (ea >> 3) & 0x7; |
| 1005 | int reg = (ea & 0x7); |
| 1006 | |
| 1007 | switch (mode) |
| 1008 | { |
| 1009 | case 2: // (An) |
| 1010 | { |
| 1011 | UINT32 ea = REG_A(m68k)[reg]; |
| 1012 | m68ki_write_32(m68k, ea, (UINT32)(data >> 32)); |
| 1013 | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1014 | break; |
| 1015 | } |
| 1016 | case 3: // (An)+ |
| 1017 | { |
| 1018 | UINT32 ea = REG_A(m68k)[reg]; |
| 1019 | REG_A(m68k)[reg] += 8; |
| 1020 | m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); |
| 1021 | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1022 | break; |
| 1023 | } |
| 1024 | case 4: // -(An) |
| 1025 | { |
| 1026 | UINT32 ea; |
| 1027 | REG_A(m68k)[reg] -= 8; |
| 1028 | ea = REG_A(m68k)[reg]; |
| 1029 | m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); |
| 1030 | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1031 | break; |
| 1032 | } |
| 1033 | case 5: // (d16, An) |
| 1034 | { |
| 1035 | UINT32 ea = EA_AY_DI_32(m68k); |
| 1036 | m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); |
| 1037 | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1038 | break; |
| 1039 | } |
| 1040 | case 6: // (An) + (Xn) + d8 |
| 1041 | { |
| 1042 | UINT32 ea = EA_AY_IX_32(m68k); |
| 1043 | m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); |
| 1044 | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1045 | break; |
| 1046 | } |
| 1047 | case 7: |
| 1048 | { |
| 1049 | switch (reg) |
| 1050 | { |
| 1051 | case 1: // (xxx).L |
| 1052 | { |
| 1053 | UINT32 d1 = OPER_I_16(m68k); |
| 1054 | UINT32 d2 = OPER_I_16(m68k); |
| 1055 | UINT32 ea = (d1 << 16) | d2; |
| 1056 | m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); |
| 1057 | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1058 | break; |
| 1059 | } |
| 1060 | case 2: // (d16, PC) |
| 1061 | { |
| 1062 | UINT32 ea = EA_PCDI_32(m68k); |
| 1063 | m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); |
| 1064 | m68ki_write_32(m68k, ea+4, (UINT32)(data)); |
| 1065 | break; |
| 1066 | } |
| 1067 | default: fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); |
| 1068 | } |
| 1069 | break; |
| 1070 | } |
| 1071 | default: fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d, data %08X%08X at %08X\n", mode, reg, (UINT32)(data >> 32), (UINT32)(data), REG_PC(m68k)); |
| 1072 | } |
| 1073 | } |
| 1074 | |
| 1075 | static void WRITE_EA_FPE(m68000_base_device *m68k, int ea, floatx80 fpr) |
| 1076 | { |
| 1077 | int mode = (ea >> 3) & 0x7; |
| 1078 | int reg = (ea & 0x7); |
| 1079 | |
| 1080 | switch (mode) |
| 1081 | { |
| 1082 | case 2: // (An) |
| 1083 | { |
| 1084 | UINT32 ea; |
| 1085 | ea = REG_A(m68k)[reg]; |
| 1086 | store_extended_float80(m68k, ea, fpr); |
| 1087 | break; |
| 1088 | } |
| 1089 | |
| 1090 | case 3: // (An)+ |
| 1091 | { |
| 1092 | UINT32 ea; |
| 1093 | ea = REG_A(m68k)[reg]; |
| 1094 | store_extended_float80(m68k, ea, fpr); |
| 1095 | REG_A(m68k)[reg] += 12; |
| 1096 | break; |
| 1097 | } |
| 1098 | |
| 1099 | case 4: // -(An) |
| 1100 | { |
| 1101 | UINT32 ea; |
| 1102 | REG_A(m68k)[reg] -= 12; |
| 1103 | ea = REG_A(m68k)[reg]; |
| 1104 | store_extended_float80(m68k, ea, fpr); |
| 1105 | break; |
| 1106 | } |
| 1107 | |
| 1108 | case 7: |
| 1109 | { |
| 1110 | switch (reg) |
| 1111 | { |
| 1112 | default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); |
| 1113 | } |
| 1114 | } |
| 1115 | default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); |
| 1116 | } |
| 1117 | } |
| 1118 | |
| 1119 | static void WRITE_EA_PACK(m68000_base_device *m68k, int ea, int k, floatx80 fpr) |
| 1120 | { |
| 1121 | int mode = (ea >> 3) & 0x7; |
| 1122 | int reg = (ea & 0x7); |
| 1123 | |
| 1124 | switch (mode) |
| 1125 | { |
| 1126 | case 2: // (An) |
| 1127 | { |
| 1128 | UINT32 ea; |
| 1129 | ea = REG_A(m68k)[reg]; |
| 1130 | store_pack_float80(m68k, ea, k, fpr); |
| 1131 | break; |
| 1132 | } |
| 1133 | |
| 1134 | case 3: // (An)+ |
| 1135 | { |
| 1136 | UINT32 ea; |
| 1137 | ea = REG_A(m68k)[reg]; |
| 1138 | store_pack_float80(m68k, ea, k, fpr); |
| 1139 | REG_A(m68k)[reg] += 12; |
| 1140 | break; |
| 1141 | } |
| 1142 | |
| 1143 | case 4: // -(An) |
| 1144 | { |
| 1145 | UINT32 ea; |
| 1146 | REG_A(m68k)[reg] -= 12; |
| 1147 | ea = REG_A(m68k)[reg]; |
| 1148 | store_pack_float80(m68k, ea, k, fpr); |
| 1149 | break; |
| 1150 | } |
| 1151 | |
| 1152 | case 7: |
| 1153 | { |
| 1154 | switch (reg) |
| 1155 | { |
| 1156 | default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); |
| 1157 | } |
| 1158 | } |
| 1159 | default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC(m68k)); |
| 1160 | } |
| 1161 | } |
| 1162 | |
| 1163 | static void fpgen_rm_reg(m68000_base_device *m68k, UINT16 w2) |
| 1164 | { |
| 1165 | int ea = m68k->ir & 0x3f; |
| 1166 | int rm = (w2 >> 14) & 0x1; |
| 1167 | int src = (w2 >> 10) & 0x7; |
| 1168 | int dst = (w2 >> 7) & 0x7; |
| 1169 | int opmode = w2 & 0x7f; |
| 1170 | floatx80 source; |
| 1171 | |
| 1172 | // fmovecr #$f, fp0 f200 5c0f |
| 1173 | |
| 1174 | if (rm) |
| 1175 | { |
| 1176 | switch (src) |
| 1177 | { |
| 1178 | case 0: // Long-Word Integer |
| 1179 | { |
| 1180 | INT32 d = READ_EA_32(m68k, ea); |
| 1181 | source = int32_to_floatx80(d); |
| 1182 | break; |
| 1183 | } |
| 1184 | case 1: // Single-precision Real |
| 1185 | { |
| 1186 | UINT32 d = READ_EA_32(m68k, ea); |
| 1187 | source = float32_to_floatx80(d); |
| 1188 | break; |
| 1189 | } |
| 1190 | case 2: // Extended-precision Real |
| 1191 | { |
| 1192 | source = READ_EA_FPE(m68k, ea); |
| 1193 | break; |
| 1194 | } |
| 1195 | case 3: // Packed-decimal Real |
| 1196 | { |
| 1197 | source = READ_EA_PACK(m68k, ea); |
| 1198 | break; |
| 1199 | } |
| 1200 | case 4: // Word Integer |
| 1201 | { |
| 1202 | INT16 d = READ_EA_16(m68k, ea); |
| 1203 | source = int32_to_floatx80((INT32)d); |
| 1204 | break; |
| 1205 | } |
| 1206 | case 5: // Double-precision Real |
| 1207 | { |
| 1208 | UINT64 d = READ_EA_64(m68k, ea); |
| 1209 | |
| 1210 | source = float64_to_floatx80(d); |
| 1211 | break; |
| 1212 | } |
| 1213 | case 6: // Byte Integer |
| 1214 | { |
| 1215 | INT8 d = READ_EA_8(m68k, ea); |
| 1216 | source = int32_to_floatx80((INT32)d); |
| 1217 | break; |
| 1218 | } |
| 1219 | case 7: // FMOVECR load from constant ROM |
| 1220 | { |
| 1221 | switch (w2 & 0x7f) |
| 1222 | { |
| 1223 | case 0x0: // Pi |
| 1224 | source.high = 0x4000; |
| 1225 | source.low = U64(0xc90fdaa22168c235); |
| 1226 | break; |
| 1227 | |
| 1228 | case 0xb: // log10(2) |
| 1229 | source.high = 0x3ffd; |
| 1230 | source.low = U64(0x9a209a84fbcff798); |
| 1231 | break; |
| 1232 | |
| 1233 | case 0xc: // e |
| 1234 | source.high = 0x4000; |
| 1235 | source.low = U64(0xadf85458a2bb4a9b); |
| 1236 | break; |
| 1237 | |
| 1238 | case 0xd: // log2(e) |
| 1239 | source.high = 0x3fff; |
| 1240 | source.low = U64(0xb8aa3b295c17f0bc); |
| 1241 | break; |
| 1242 | |
| 1243 | case 0xe: // log10(e) |
| 1244 | source.high = 0x3ffd; |
| 1245 | source.low = U64(0xde5bd8a937287195); |
| 1246 | break; |
| 1247 | |
| 1248 | case 0xf: // 0.0 |
| 1249 | source = int32_to_floatx80((INT32)0); |
| 1250 | break; |
| 1251 | |
| 1252 | case 0x30: // ln(2) |
| 1253 | source.high = 0x3ffe; |
| 1254 | source.low = U64(0xb17217f7d1cf79ac); |
| 1255 | break; |
| 1256 | |
| 1257 | case 0x31: // ln(10) |
| 1258 | source.high = 0x4000; |
| 1259 | source.low = U64(0x935d8dddaaa8ac17); |
| 1260 | break; |
| 1261 | |
| 1262 | case 0x32: // 1 (or 100? manuals are unclear, but 1 would make more sense) |
| 1263 | source = int32_to_floatx80((INT32)1); |
| 1264 | break; |
| 1265 | |
| 1266 | case 0x33: // 10^1 |
| 1267 | source = int32_to_floatx80((INT32)10); |
| 1268 | break; |
| 1269 | |
| 1270 | case 0x34: // 10^2 |
| 1271 | source = int32_to_floatx80((INT32)10*10); |
| 1272 | break; |
| 1273 | |
| 1274 | case 0x35: // 10^4 |
| 1275 | source = int32_to_floatx80((INT32)1000*10); |
| 1276 | break; |
| 1277 | |
| 1278 | case 0x36: // 1.0e8 |
| 1279 | source = int32_to_floatx80((INT32)10000000*10); |
| 1280 | break; |
| 1281 | |
| 1282 | case 0x37: // 1.0e16 - can't get the right precision from INT32 so go "direct" with constants from h/w |
| 1283 | source.high = 0x4034; |
| 1284 | source.low = U64(0x8e1bc9bf04000000); |
| 1285 | break; |
| 1286 | |
| 1287 | case 0x38: // 1.0e32 |
| 1288 | source.high = 0x4069; |
| 1289 | source.low = U64(0x9dc5ada82b70b59e); |
| 1290 | break; |
| 1291 | |
| 1292 | case 0x39: // 1.0e64 |
| 1293 | source.high = 0x40d3; |
| 1294 | source.low = U64(0xc2781f49ffcfa6d5); |
| 1295 | break; |
| 1296 | |
| 1297 | case 0x3a: // 1.0e128 |
| 1298 | source.high = 0x41a8; |
| 1299 | source.low = U64(0x93ba47c980e98ce0); |
| 1300 | break; |
| 1301 | |
| 1302 | case 0x3b: // 1.0e256 |
| 1303 | source.high = 0x4351; |
| 1304 | source.low = U64(0xaa7eebfb9df9de8e); |
| 1305 | break; |
| 1306 | |
| 1307 | case 0x3c: // 1.0e512 |
| 1308 | source.high = 0x46a3; |
| 1309 | source.low = U64(0xe319a0aea60e91c7); |
| 1310 | break; |
| 1311 | |
| 1312 | case 0x3d: // 1.0e1024 |
| 1313 | source.high = 0x4d48; |
| 1314 | source.low = U64(0xc976758681750c17); |
| 1315 | break; |
| 1316 | |
| 1317 | case 0x3e: // 1.0e2048 |
| 1318 | source.high = 0x5a92; |
| 1319 | source.low = U64(0x9e8b3b5dc53d5de5); |
| 1320 | break; |
| 1321 | |
| 1322 | case 0x3f: // 1.0e4096 |
| 1323 | source.high = 0x7525; |
| 1324 | source.low = U64(0xc46052028a20979b); |
| 1325 | break; |
| 1326 | |
| 1327 | default: |
| 1328 | fatalerror("fmove_rm_reg: unknown constant ROM offset %x at %08x\n", w2&0x7f, REG_PC(m68k)-4); |
| 1329 | break; |
| 1330 | } |
| 1331 | |
| 1332 | // handle it right here, the usual opmode bits aren't valid in the FMOVECR case |
| 1333 | REG_FP(m68k)[dst] = source; |
| 1334 | m68k->remaining_cycles -= 4; |
| 1335 | return; |
| 1336 | } |
| 1337 | default: fatalerror("fmove_rm_reg: invalid source specifier %x at %08X\n", src, REG_PC(m68k)-4); |
| 1338 | } |
| 1339 | } |
| 1340 | else |
| 1341 | { |
| 1342 | source = REG_FP(m68k)[src]; |
| 1343 | } |
| 1344 | |
| 1345 | |
| 1346 | |
| 1347 | switch (opmode) |
| 1348 | { |
| 1349 | case 0x00: // FMOVE |
| 1350 | { |
| 1351 | REG_FP(m68k)[dst] = source; |
| 1352 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1353 | m68k->remaining_cycles -= 4; |
| 1354 | break; |
| 1355 | } |
| 1356 | case 0x01: // FINT |
| 1357 | { |
| 1358 | INT32 temp; |
| 1359 | temp = floatx80_to_int32(source); |
| 1360 | REG_FP(m68k)[dst] = int32_to_floatx80(temp); |
| 1361 | break; |
| 1362 | } |
| 1363 | case 0x03: // FINTRZ |
| 1364 | { |
| 1365 | INT32 temp; |
| 1366 | temp = floatx80_to_int32_round_to_zero(source); |
| 1367 | REG_FP(m68k)[dst] = int32_to_floatx80(temp); |
| 1368 | break; |
| 1369 | } |
| 1370 | case 0x04: // FSQRT |
| 1371 | { |
| 1372 | REG_FP(m68k)[dst] = floatx80_sqrt(source); |
| 1373 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1374 | m68k->remaining_cycles -= 109; |
| 1375 | break; |
| 1376 | } |
| 1377 | case 0x06: // FLOGNP1 |
| 1378 | { |
| 1379 | REG_FP(m68k)[dst] = floatx80_flognp1 (source); |
| 1380 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1381 | m68k->remaining_cycles -= 594; // for MC68881 |
| 1382 | break; |
| 1383 | } |
| 1384 | case 0x0e: // FSIN |
| 1385 | { |
| 1386 | REG_FP(m68k)[dst] = source; |
| 1387 | floatx80_fsin(REG_FP(m68k)[dst]); |
| 1388 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1389 | m68k->remaining_cycles -= 75; |
| 1390 | break; |
| 1391 | } |
| 1392 | case 0x0f: // FTAN |
| 1393 | { |
| 1394 | REG_FP(m68k)[dst] = source; |
| 1395 | floatx80_ftan(REG_FP(m68k)[dst]); |
| 1396 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1397 | m68k->remaining_cycles -= 75; |
| 1398 | break; |
| 1399 | } |
| 1400 | case 0x14: // FLOGN |
| 1401 | { |
| 1402 | REG_FP(m68k)[dst] = floatx80_flogn (source); |
| 1403 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1404 | m68k->remaining_cycles -= 548; // for MC68881 |
| 1405 | break; |
| 1406 | } |
| 1407 | case 0x15: // FLOG10 |
| 1408 | { |
| 1409 | REG_FP(m68k)[dst] = floatx80_flog10 (source); |
| 1410 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1411 | m68k->remaining_cycles -= 604; // for MC68881 |
| 1412 | break; |
| 1413 | } |
| 1414 | case 0x16: // FLOG2 |
| 1415 | { |
| 1416 | REG_FP(m68k)[dst] = floatx80_flog2 (source); |
| 1417 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1418 | m68k->remaining_cycles -= 604; // for MC68881 |
| 1419 | break; |
| 1420 | } |
| 1421 | case 0x18: // FABS |
| 1422 | { |
| 1423 | REG_FP(m68k)[dst] = source; |
| 1424 | REG_FP(m68k)[dst].high &= 0x7fff; |
| 1425 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1426 | m68k->remaining_cycles -= 3; |
| 1427 | break; |
| 1428 | } |
| 1429 | case 0x1a: // FNEG |
| 1430 | { |
| 1431 | REG_FP(m68k)[dst] = source; |
| 1432 | REG_FP(m68k)[dst].high ^= 0x8000; |
| 1433 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1434 | m68k->remaining_cycles -= 3; |
| 1435 | break; |
| 1436 | } |
| 1437 | case 0x1d: // FCOS |
| 1438 | { |
| 1439 | REG_FP(m68k)[dst] = source; |
| 1440 | floatx80_fcos(REG_FP(m68k)[dst]); |
| 1441 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1442 | m68k->remaining_cycles -= 75; |
| 1443 | break; |
| 1444 | } |
| 1445 | case 0x1e: // FGETEXP |
| 1446 | { |
| 1447 | INT16 temp2; |
| 1448 | |
| 1449 | temp2 = source.high; // get the exponent |
| 1450 | temp2 -= 0x3fff; // take off the bias |
| 1451 | REG_FP(m68k)[dst] = double_to_fx80((double)temp2); |
| 1452 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1453 | m68k->remaining_cycles -= 6; |
| 1454 | break; |
| 1455 | } |
| 1456 | case 0x20: // FDIV |
| 1457 | { |
| 1458 | REG_FP(m68k)[dst] = floatx80_div(REG_FP(m68k)[dst], source); |
| 1459 | m68k->remaining_cycles -= 43; |
| 1460 | break; |
| 1461 | } |
| 1462 | case 0x22: // FADD |
| 1463 | { |
| 1464 | REG_FP(m68k)[dst] = floatx80_add(REG_FP(m68k)[dst], source); |
| 1465 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1466 | m68k->remaining_cycles -= 9; |
| 1467 | break; |
| 1468 | } |
| 1469 | case 0x23: // FMUL |
| 1470 | { |
| 1471 | REG_FP(m68k)[dst] = floatx80_mul(REG_FP(m68k)[dst], source); |
| 1472 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1473 | m68k->remaining_cycles -= 11; |
| 1474 | break; |
| 1475 | } |
| 1476 | case 0x24: // FSGLDIV |
| 1477 | { |
| 1478 | float32 a = floatx80_to_float32( REG_FP(m68k)[dst] ); |
| 1479 | float32 b = floatx80_to_float32( source ); |
| 1480 | REG_FP(m68k)[dst] = float32_to_floatx80( float32_div(a, b) ); |
| 1481 | m68k->remaining_cycles -= 43; // // ? (value is from FDIV) |
| 1482 | break; |
| 1483 | } |
| 1484 | case 0x25: // FREM |
| 1485 | { |
| 1486 | REG_FP(m68k)[dst] = floatx80_rem(REG_FP(m68k)[dst], source); |
| 1487 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1488 | m68k->remaining_cycles -= 43; // guess |
| 1489 | break; |
| 1490 | } |
| 1491 | case 0x26: // FSCALE |
| 1492 | { |
| 1493 | REG_FP(m68k)[dst] = floatx80_scale(REG_FP(m68k)[dst], source); |
| 1494 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1495 | m68k->remaining_cycles -= 46; // (better?) guess |
| 1496 | break; |
| 1497 | } |
| 1498 | case 0x27: // FSGLMUL |
| 1499 | { |
| 1500 | float32 a = floatx80_to_float32( REG_FP(m68k)[dst] ); |
| 1501 | float32 b = floatx80_to_float32( source ); |
| 1502 | REG_FP(m68k)[dst] = float32_to_floatx80( float32_mul(a, b) ); |
| 1503 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1504 | m68k->remaining_cycles -= 11; // ? (value is from FMUL) |
| 1505 | break; |
| 1506 | } |
| 1507 | case 0x28: // FSUB |
| 1508 | { |
| 1509 | REG_FP(m68k)[dst] = floatx80_sub(REG_FP(m68k)[dst], source); |
| 1510 | SET_CONDITION_CODES(m68k, REG_FP(m68k)[dst]); |
| 1511 | m68k->remaining_cycles -= 9; |
| 1512 | break; |
| 1513 | } |
| 1514 | case 0x38: // FCMP |
| 1515 | { |
| 1516 | floatx80 res; |
| 1517 | res = floatx80_sub(REG_FP(m68k)[dst], source); |
| 1518 | SET_CONDITION_CODES(m68k, res); |
| 1519 | m68k->remaining_cycles -= 7; |
| 1520 | break; |
| 1521 | } |
| 1522 | case 0x3a: // FTST |
| 1523 | { |
| 1524 | floatx80 res; |
| 1525 | res = source; |
| 1526 | SET_CONDITION_CODES(m68k, res); |
| 1527 | m68k->remaining_cycles -= 7; |
| 1528 | break; |
| 1529 | } |
| 1530 | |
| 1531 | default: fatalerror("fpgen_rm_reg: unimplemented opmode %02X at %08X\n", opmode, REG_PPC(m68k)); |
| 1532 | } |
| 1533 | } |
| 1534 | |
| 1535 | static void fmove_reg_mem(m68000_base_device *m68k, UINT16 w2) |
| 1536 | { |
| 1537 | int ea = m68k->ir & 0x3f; |
| 1538 | int src = (w2 >> 7) & 0x7; |
| 1539 | int dst = (w2 >> 10) & 0x7; |
| 1540 | int k = (w2 & 0x7f); |
| 1541 | |
| 1542 | switch (dst) |
| 1543 | { |
| 1544 | case 0: // Long-Word Integer |
| 1545 | { |
| 1546 | INT32 d = (INT32)floatx80_to_int32(REG_FP(m68k)[src]); |
| 1547 | WRITE_EA_32(m68k, ea, d); |
| 1548 | break; |
| 1549 | } |
| 1550 | case 1: // Single-precision Real |
| 1551 | { |
| 1552 | UINT32 d = floatx80_to_float32(REG_FP(m68k)[src]); |
| 1553 | WRITE_EA_32(m68k, ea, d); |
| 1554 | break; |
| 1555 | } |
| 1556 | case 2: // Extended-precision Real |
| 1557 | { |
| 1558 | WRITE_EA_FPE(m68k, ea, REG_FP(m68k)[src]); |
| 1559 | break; |
| 1560 | } |
| 1561 | case 3: // Packed-decimal Real with Static K-factor |
| 1562 | { |
| 1563 | // sign-extend k |
| 1564 | k = (k & 0x40) ? (k | 0xffffff80) : (k & 0x7f); |
| 1565 | WRITE_EA_PACK(m68k, ea, k, REG_FP(m68k)[src]); |
| 1566 | break; |
| 1567 | } |
| 1568 | case 4: // Word Integer |
| 1569 | { |
| 1570 | int32 value = floatx80_to_int32(REG_FP(m68k)[src]); |
| 1571 | if (value > 0x7fff || value < -0x8000 ) |
| 1572 | { |
| 1573 | REG_FPSR(m68k) |= FPES_OE | FPAE_IOP; |
| 1574 | } |
| 1575 | WRITE_EA_16(m68k, ea, (INT16)value); |
| 1576 | break; |
| 1577 | } |
| 1578 | case 5: // Double-precision Real |
| 1579 | { |
| 1580 | UINT64 d; |
| 1581 | |
| 1582 | d = floatx80_to_float64(REG_FP(m68k)[src]); |
| 1583 | |
| 1584 | WRITE_EA_64(m68k, ea, d); |
| 1585 | break; |
| 1586 | } |
| 1587 | case 6: // Byte Integer |
| 1588 | { |
| 1589 | int32 value = floatx80_to_int32(REG_FP(m68k)[src]); |
| 1590 | if (value > 127 || value < -128) |
| 1591 | { |
| 1592 | REG_FPSR(m68k) |= FPES_OE | FPAE_IOP; |
| 1593 | } |
| 1594 | WRITE_EA_8(m68k, ea, (INT8) value); |
| 1595 | break; |
| 1596 | } |
| 1597 | case 7: // Packed-decimal Real with Dynamic K-factor |
| 1598 | { |
| 1599 | WRITE_EA_PACK(m68k, ea, REG_D(m68k)[k>>4], REG_FP(m68k)[src]); |
| 1600 | break; |
| 1601 | } |
| 1602 | } |
| 1603 | |
| 1604 | m68k->remaining_cycles -= 12; |
| 1605 | } |
| 1606 | |
| 1607 | static void fmove_fpcr(m68000_base_device *m68k, UINT16 w2) |
| 1608 | { |
| 1609 | int ea = m68k->ir & 0x3f; |
| 1610 | int dir = (w2 >> 13) & 0x1; |
| 1611 | int regsel = (w2 >> 10) & 0x7; |
| 1612 | int mode = (ea >> 3) & 0x7; |
| 1613 | |
| 1614 | if ((mode == 5) || (mode == 6)) |
| 1615 | { |
| 1616 | UINT32 address = 0xffffffff; // force a bus error if this doesn't get assigned |
| 1617 | |
| 1618 | if (mode == 5) |
| 1619 | { |
| 1620 | address = EA_AY_DI_32(m68k); |
| 1621 | } |
| 1622 | else if (mode == 6) |
| 1623 | { |
| 1624 | address = EA_AY_IX_32(m68k); |
| 1625 | } |
| 1626 | |
| 1627 | if (dir) // From system control reg to <ea> |
| 1628 | { |
| 1629 | if (regsel & 4) { m68ki_write_32(m68k, address, REG_FPCR(m68k)); address += 4; } |
| 1630 | if (regsel & 2) { m68ki_write_32(m68k, address, REG_FPSR(m68k)); address += 4; } |
| 1631 | if (regsel & 1) { m68ki_write_32(m68k, address, REG_FPIAR(m68k)); address += 4; } |
| 1632 | } |
| 1633 | else // From <ea> to system control reg |
| 1634 | { |
| 1635 | if (regsel & 4) { REG_FPCR(m68k) = m68ki_read_32(m68k, address); address += 4; } |
| 1636 | if (regsel & 2) { REG_FPSR(m68k) = m68ki_read_32(m68k, address); address += 4; } |
| 1637 | if (regsel & 1) { REG_FPIAR(m68k) = m68ki_read_32(m68k, address); address += 4; } |
| 1638 | } |
| 1639 | } |
| 1640 | else |
| 1641 | { |
| 1642 | if (dir) // From system control reg to <ea> |
| 1643 | { |
| 1644 | if (regsel & 4) WRITE_EA_32(m68k, ea, REG_FPCR(m68k)); |
| 1645 | if (regsel & 2) WRITE_EA_32(m68k, ea, REG_FPSR(m68k)); |
| 1646 | if (regsel & 1) WRITE_EA_32(m68k, ea, REG_FPIAR(m68k)); |
| 1647 | } |
| 1648 | else // From <ea> to system control reg |
| 1649 | { |
| 1650 | if (regsel & 4) REG_FPCR(m68k) = READ_EA_32(m68k, ea); |
| 1651 | if (regsel & 2) REG_FPSR(m68k) = READ_EA_32(m68k, ea); |
| 1652 | if (regsel & 1) REG_FPIAR(m68k) = READ_EA_32(m68k, ea); |
| 1653 | } |
| 1654 | } |
| 1655 | |
| 1656 | #if 0 |
| 1657 | // FIXME: (2011-12-18 ost) |
| 1658 | // rounding_mode and rounding_precision of softfloat.c should be set according to current fpcr |
| 1659 | // but: with this code on Apollo the following programs in /systest/fptest will fail: |
| 1660 | // 1. Single Precision Whetstone will return wrong results never the less |
| 1661 | // 2. Vector Test will fault with 00040004: reference to illegal address |
| 1662 | |
| 1663 | if ((regsel & 4) && dir == 0) |
| 1664 | { |
| 1665 | int rnd = (REG_FPCR(m68k) >> 4) & 3; |
| 1666 | int prec = (REG_FPCR(m68k) >> 6) & 3; |
| 1667 | |
| 1668 | logerror("m68k_fpsp:fmove_fpcr fpcr=%04x prec=%d rnd=%d\n", REG_FPCR(m68k), prec, rnd); |
| 1669 | |
| 1670 | #ifdef FLOATX80 |
| 1671 | switch (prec) |
| 1672 | { |
| 1673 | case 0: // Extend (X) |
| 1674 | floatx80_rounding_precision = 80; |
| 1675 | break; |
| 1676 | case 1: // Single (S) |
| 1677 | floatx80_rounding_precision = 32; |
| 1678 | break; |
| 1679 | case 2: // Double (D) |
| 1680 | floatx80_rounding_precision = 64; |
| 1681 | break; |
| 1682 | case 3: // Undefined |
| 1683 | floatx80_rounding_precision = 80; |
| 1684 | break; |
| 1685 | } |
| 1686 | #endif |
| 1687 | |
| 1688 | switch (rnd) |
| 1689 | { |
| 1690 | case 0: // To Nearest (RN) |
| 1691 | float_rounding_mode = float_round_nearest_even; |
| 1692 | break; |
| 1693 | case 1: // To Zero (RZ) |
| 1694 | float_rounding_mode = float_round_to_zero; |
| 1695 | break; |
| 1696 | case 2: // To Minus Infinitiy (RM) |
| 1697 | float_rounding_mode = float_round_down; |
| 1698 | break; |
| 1699 | case 3: // To Plus Infinitiy (RP) |
| 1700 | float_rounding_mode = float_round_up; |
| 1701 | break; |
| 1702 | } |
| 1703 | } |
| 1704 | #endif |
| 1705 | |
| 1706 | m68k->remaining_cycles -= 10; |
| 1707 | } |
| 1708 | |
| 1709 | static void fmovem(m68000_base_device *m68k, UINT16 w2) |
| 1710 | { |
| 1711 | int i; |
| 1712 | int ea = m68k->ir & 0x3f; |
| 1713 | int dir = (w2 >> 13) & 0x1; |
| 1714 | int mode = (w2 >> 11) & 0x3; |
| 1715 | int reglist = w2 & 0xff; |
| 1716 | |
| 1717 | UINT32 mem_addr = 0; |
| 1718 | switch (ea >> 3) |
| 1719 | { |
| 1720 | case 5: // (d16, An) |
| 1721 | mem_addr= EA_AY_DI_32(m68k); |
| 1722 | break; |
| 1723 | case 6: // (An) + (Xn) + d8 |
| 1724 | mem_addr= EA_AY_IX_32(m68k); |
| 1725 | break; |
| 1726 | } |
| 1727 | |
| 1728 | if (dir) // From FP regs to mem |
| 1729 | { |
| 1730 | switch (mode) |
| 1731 | { |
| 1732 | case 1: // Dynamic register list, postincrement or control addressing mode. |
| 1733 | // FIXME: not really tested, but seems to work |
| 1734 | reglist = REG_D(m68k)[(reglist >> 4) & 7]; |
| 1735 | |
| 1736 | case 0: // Static register list, predecrement or control addressing mode |
| 1737 | { |
| 1738 | for (i=0; i < 8; i++) |
| 1739 | { |
| 1740 | if (reglist & (1 << i)) |
| 1741 | { |
| 1742 | switch (ea >> 3) |
| 1743 | { |
| 1744 | case 5: // (d16, An) |
| 1745 | case 6: // (An) + (Xn) + d8 |
| 1746 | store_extended_float80(m68k, mem_addr, REG_FP(m68k)[i]); |
| 1747 | mem_addr += 12; |
| 1748 | break; |
| 1749 | default: |
| 1750 | WRITE_EA_FPE(m68k, ea, REG_FP(m68k)[i]); |
| 1751 | break; |
| 1752 | } |
| 1753 | |
| 1754 | m68k->remaining_cycles -= 2; |
| 1755 | } |
| 1756 | } |
| 1757 | break; |
| 1758 | } |
| 1759 | |
| 1760 | case 2: // Static register list, postdecrement or control addressing mode |
| 1761 | { |
| 1762 | for (i=0; i < 8; i++) |
| 1763 | { |
| 1764 | if (reglist & (1 << i)) |
| 1765 | { |
| 1766 | switch (ea >> 3) |
| 1767 | { |
| 1768 | case 5: // (d16, An) |
| 1769 | case 6: // (An) + (Xn) + d8 |
| 1770 | store_extended_float80(m68k, mem_addr, REG_FP(m68k)[7-i]); |
| 1771 | mem_addr += 12; |
| 1772 | break; |
| 1773 | default: |
| 1774 | WRITE_EA_FPE(m68k, ea, REG_FP(m68k)[7-i]); |
| 1775 | break; |
| 1776 | } |
| 1777 | |
| 1778 | m68k->remaining_cycles -= 2; |
| 1779 | } |
| 1780 | } |
| 1781 | break; |
| 1782 | } |
| 1783 | |
| 1784 | default: fatalerror("M680x0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC(m68k)-4); |
| 1785 | } |
| 1786 | } |
| 1787 | else // From mem to FP regs |
| 1788 | { |
| 1789 | switch (mode) |
| 1790 | { |
| 1791 | case 3: // Dynamic register list, predecrement addressing mode. |
| 1792 | // FIXME: not really tested, but seems to work |
| 1793 | reglist = REG_D(m68k)[(reglist >> 4) & 7]; |
| 1794 | |
| 1795 | case 2: // Static register list, postincrement or control addressing mode |
| 1796 | { |
| 1797 | for (i=0; i < 8; i++) |
| 1798 | { |
| 1799 | if (reglist & (1 << i)) |
| 1800 | { |
| 1801 | switch (ea >> 3) |
| 1802 | { |
| 1803 | case 5: // (d16, An) |
| 1804 | case 6: // (An) + (Xn) + d8 |
| 1805 | REG_FP(m68k)[7-i] = load_extended_float80(m68k, mem_addr); |
| 1806 | mem_addr += 12; |
| 1807 | break; |
| 1808 | default: |
| 1809 | REG_FP(m68k)[7-i] = READ_EA_FPE(m68k, ea); |
| 1810 | break; |
| 1811 | } |
| 1812 | m68k->remaining_cycles -= 2; |
| 1813 | } |
| 1814 | } |
| 1815 | break; |
| 1816 | } |
| 1817 | |
| 1818 | default: fatalerror("M680x0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC(m68k)-4); |
| 1819 | } |
| 1820 | } |
| 1821 | } |
| 1822 | |
| 1823 | static void fscc(m68000_base_device *m68k) |
| 1824 | { |
| 1825 | int ea = m68k->ir & 0x3f; |
| 1826 | int condition = (INT16)(OPER_I_16(m68k)); |
| 1827 | |
| 1828 | WRITE_EA_8(m68k, ea, TEST_CONDITION(m68k, condition) ? 0xff : 0); |
| 1829 | m68k->remaining_cycles -= 7; // ??? |
| 1830 | } |
| 1831 | |
| 1832 | static void fbcc16(m68000_base_device *m68k) |
| 1833 | { |
| 1834 | INT32 offset; |
| 1835 | int condition = m68k->ir & 0x3f; |
| 1836 | |
| 1837 | offset = (INT16)(OPER_I_16(m68k)); |
| 1838 | |
| 1839 | // TODO: condition and jump!!! |
| 1840 | if (TEST_CONDITION(m68k, condition)) |
| 1841 | { |
| 1842 | m68ki_trace_t0(m68k); /* auto-disable (see m68kcpu.h) */ |
| 1843 | m68ki_branch_16(m68k, offset-2); |
| 1844 | } |
| 1845 | |
| 1846 | m68k->remaining_cycles -= 7; |
| 1847 | } |
| 1848 | |
| 1849 | static void fbcc32(m68000_base_device *m68k) |
| 1850 | { |
| 1851 | INT32 offset; |
| 1852 | int condition = m68k->ir & 0x3f; |
| 1853 | |
| 1854 | offset = OPER_I_32(m68k); |
| 1855 | |
| 1856 | // TODO: condition and jump!!! |
| 1857 | if (TEST_CONDITION(m68k, condition)) |
| 1858 | { |
| 1859 | m68ki_trace_t0(m68k); /* auto-disable (see m68kcpu.h) */ |
| 1860 | m68ki_branch_32(m68k, offset-4); |
| 1861 | } |
| 1862 | |
| 1863 | m68k->remaining_cycles -= 7; |
| 1864 | } |
| 1865 | |
| 1866 | |
| 1867 | void m68040_fpu_op0(m68000_base_device *m68k) |
| 1868 | { |
| 1869 | m68k->fpu_just_reset = 0; |
| 1870 | |
| 1871 | switch ((m68k->ir >> 6) & 0x3) |
| 1872 | { |
| 1873 | case 0: |
| 1874 | { |
| 1875 | UINT16 w2 = OPER_I_16(m68k); |
| 1876 | switch ((w2 >> 13) & 0x7) |
| 1877 | { |
| 1878 | case 0x0: // FPU ALU FP, FP |
| 1879 | case 0x2: // FPU ALU ea, FP |
| 1880 | { |
| 1881 | fpgen_rm_reg(m68k, w2); |
| 1882 | break; |
| 1883 | } |
| 1884 | |
| 1885 | case 0x3: // FMOVE FP, ea |
| 1886 | { |
| 1887 | fmove_reg_mem(m68k, w2); |
| 1888 | break; |
| 1889 | } |
| 1890 | |
| 1891 | case 0x4: // FMOVEM ea, FPCR |
| 1892 | case 0x5: // FMOVEM FPCR, ea |
| 1893 | { |
| 1894 | fmove_fpcr(m68k, w2); |
| 1895 | break; |
| 1896 | } |
| 1897 | |
| 1898 | case 0x6: // FMOVEM ea, list |
| 1899 | case 0x7: // FMOVEM list, ea |
| 1900 | { |
| 1901 | fmovem(m68k, w2); |
| 1902 | break; |
| 1903 | } |
| 1904 | |
| 1905 | default: fatalerror("M68kFPU: unimplemented subop %d at %08X\n", (w2 >> 13) & 0x7, REG_PC(m68k)-4); |
| 1906 | } |
| 1907 | break; |
| 1908 | } |
| 1909 | |
| 1910 | case 1: // FBcc disp16 |
| 1911 | { |
| 1912 | switch ((m68k->ir >> 3) & 0x7) { |
| 1913 | case 1: // FDBcc |
| 1914 | // TODO: |
| 1915 | break; |
| 1916 | default: // FScc (?) |
| 1917 | fscc(m68k); |
| 1918 | return; |
| 1919 | } |
| 1920 | fatalerror("M68kFPU: unimplemented main op %d with mode %d at %08X\n", (m68k->ir >> 6) & 0x3, (m68k->ir >> 3) & 0x7, REG_PPC(m68k)); |
| 1921 | } |
| 1922 | |
| 1923 | case 2: // FBcc disp16 |
| 1924 | { |
| 1925 | fbcc16(m68k); |
| 1926 | break; |
| 1927 | } |
| 1928 | case 3: // FBcc disp32 |
| 1929 | { |
| 1930 | fbcc32(m68k); |
| 1931 | break; |
| 1932 | } |
| 1933 | |
| 1934 | default: fatalerror("M68kFPU: unimplemented main op %d\n", (m68k->ir >> 6) & 0x3); |
| 1935 | } |
| 1936 | } |
| 1937 | |
| 1938 | static int perform_fsave(m68000_base_device *m68k, UINT32 addr, int inc) |
| 1939 | { |
| 1940 | if(m68k->cpu_type & CPU_TYPE_040) |
| 1941 | { |
| 1942 | if(inc) |
| 1943 | { |
| 1944 | m68ki_write_32(m68k, addr, 0x41000000); |
| 1945 | return 4; |
| 1946 | } |
| 1947 | else |
| 1948 | { |
| 1949 | m68ki_write_32(m68k, addr-4, 0x41000000); |
| 1950 | return -4; |
| 1951 | } |
| 1952 | } |
| 1953 | |
| 1954 | if (inc) |
| 1955 | { |
| 1956 | // 68881 IDLE, version 0x1f |
| 1957 | m68ki_write_32(m68k, addr, 0x1f180000); |
| 1958 | m68ki_write_32(m68k, addr+4, 0); |
| 1959 | m68ki_write_32(m68k, addr+8, 0); |
| 1960 | m68ki_write_32(m68k, addr+12, 0); |
| 1961 | m68ki_write_32(m68k, addr+16, 0); |
| 1962 | m68ki_write_32(m68k, addr+20, 0); |
| 1963 | m68ki_write_32(m68k, addr+24, 0x70000000); |
| 1964 | return 7*4; |
| 1965 | } |
| 1966 | else |
| 1967 | { |
| 1968 | m68ki_write_32(m68k, addr-4, 0x70000000); |
| 1969 | m68ki_write_32(m68k, addr-8, 0); |
| 1970 | m68ki_write_32(m68k, addr-12, 0); |
| 1971 | m68ki_write_32(m68k, addr-16, 0); |
| 1972 | m68ki_write_32(m68k, addr-20, 0); |
| 1973 | m68ki_write_32(m68k, addr-24, 0); |
| 1974 | m68ki_write_32(m68k, addr-28, 0x1f180000); |
| 1975 | return -7*4; |
| 1976 | } |
| 1977 | } |
| 1978 | |
| 1979 | // FRESTORE on a NULL frame reboots the FPU - all registers to NaN, the 3 status regs to 0 |
| 1980 | static void do_frestore_null(m68000_base_device *m68k) |
| 1981 | { |
| 1982 | int i; |
| 1983 | |
| 1984 | REG_FPCR(m68k) = 0; |
| 1985 | REG_FPSR(m68k) = 0; |
| 1986 | REG_FPIAR(m68k) = 0; |
| 1987 | for (i = 0; i < 8; i++) |
| 1988 | { |
| 1989 | REG_FP(m68k)[i].high = 0x7fff; |
| 1990 | REG_FP(m68k)[i].low = U64(0xffffffffffffffff); |
| 1991 | } |
| 1992 | |
| 1993 | // Mac IIci at 408458e6 wants an FSAVE of a just-restored NULL frame to also be NULL |
| 1994 | // The PRM says it's possible to generate a NULL frame, but not how/when/why. (need the 68881/68882 manual!) |
| 1995 | m68k->fpu_just_reset = 1; |
| 1996 | } |
| 1997 | |
| 1998 | static void m68040_do_fsave(m68000_base_device *m68k, UINT32 addr, int reg, int inc) |
| 1999 | { |
| 2000 | if (m68k->fpu_just_reset) |
| 2001 | { |
| 2002 | m68ki_write_32(m68k, addr, 0); |
| 2003 | } |
| 2004 | else |
| 2005 | { |
| 2006 | // we normally generate an IDLE frame |
| 2007 | int delta = perform_fsave(m68k, addr, inc); |
| 2008 | if(reg != -1) |
| 2009 | REG_A(m68k)[reg] += delta; |
| 2010 | } |
| 2011 | } |
| 2012 | |
| 2013 | static void m68040_do_frestore(m68000_base_device *m68k, UINT32 addr, int reg) |
| 2014 | { |
| 2015 | bool m40 = m68k->cpu_type & CPU_TYPE_040; |
| 2016 | UINT32 temp = m68ki_read_32(m68k, addr); |
| 2017 | |
| 2018 | // check for NULL frame |
| 2019 | if (temp & 0xff000000) |
| 2020 | { |
| 2021 | // we don't handle non-NULL frames |
| 2022 | m68k->fpu_just_reset = 0; |
| 2023 | |
| 2024 | if (reg != -1) |
| 2025 | { |
| 2026 | // how about an IDLE frame? |
| 2027 | if (!m40 && ((temp & 0x00ff0000) == 0x00180000)) |
| 2028 | { |
| 2029 | REG_A(m68k)[reg] += 7*4; |
| 2030 | } |
| 2031 | else if (m40 && ((temp & 0xffff0000) == 0x41000000)) |
| 2032 | { |
| 2033 | REG_A(m68k)[reg] += 4; |
| 2034 | } // check UNIMP |
| 2035 | else if ((temp & 0x00ff0000) == 0x00380000) |
| 2036 | { |
| 2037 | REG_A(m68k)[reg] += 14*4; |
| 2038 | } // check BUSY |
| 2039 | else if ((temp & 0x00ff0000) == 0x00b40000) |
| 2040 | { |
| 2041 | REG_A(m68k)[reg] += 45*4; |
| 2042 | } |
| 2043 | } |
| 2044 | } |
| 2045 | else |
| 2046 | { |
| 2047 | do_frestore_null(m68k); |
| 2048 | } |
| 2049 | } |
| 2050 | |
| 2051 | void m68040_fpu_op1(m68000_base_device *m68k) |
| 2052 | { |
| 2053 | int ea = m68k->ir & 0x3f; |
| 2054 | int mode = (ea >> 3) & 0x7; |
| 2055 | int reg = (ea & 0x7); |
| 2056 | UINT32 addr; |
| 2057 | |
| 2058 | switch ((m68k->ir >> 6) & 0x3) |
| 2059 | { |
| 2060 | case 0: // FSAVE <ea> |
| 2061 | { |
| 2062 | switch (mode) |
| 2063 | { |
| 2064 | case 2: // (An) |
| 2065 | addr = REG_A(m68k)[reg]; |
| 2066 | m68040_do_fsave(m68k, addr, -1, 1); |
| 2067 | break; |
| 2068 | |
| 2069 | case 3: // (An)+ |
| 2070 | addr = EA_AY_PI_32(m68k); |
| 2071 | m68040_do_fsave(m68k, addr, reg, 1); |
| 2072 | break; |
| 2073 | |
| 2074 | case 4: // -(An) |
| 2075 | addr = EA_AY_PD_32(m68k); |
| 2076 | m68040_do_fsave(m68k, addr, reg, 0); |
| 2077 | break; |
| 2078 | |
| 2079 | case 5: // (D16, An) |
| 2080 | addr = EA_AY_DI_16(m68k); |
| 2081 | m68040_do_fsave(m68k, addr, -1, 1); |
| 2082 | break; |
| 2083 | |
| 2084 | case 7: // |
| 2085 | switch (reg) |
| 2086 | { |
| 2087 | case 1: // (abs32) |
| 2088 | { |
| 2089 | addr = EA_AL_32(m68k); |
| 2090 | m68040_do_fsave(m68k, addr, -1, 1); |
| 2091 | break; |
| 2092 | } |
| 2093 | case 2: // (d16, PC) |
| 2094 | { |
| 2095 | addr = EA_PCDI_16(m68k); |
| 2096 | m68040_do_fsave(m68k, addr, -1, 1); |
| 2097 | break; |
| 2098 | } |
| 2099 | default: |
| 2100 | fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); |
| 2101 | } |
| 2102 | |
| 2103 | break; |
| 2104 | |
| 2105 | default: |
| 2106 | fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); |
| 2107 | } |
| 2108 | break; |
| 2109 | } |
| 2110 | break; |
| 2111 | |
| 2112 | case 1: // FRESTORE <ea> |
| 2113 | { |
| 2114 | switch (mode) |
| 2115 | { |
| 2116 | case 2: // (An) |
| 2117 | addr = REG_A(m68k)[reg]; |
| 2118 | m68040_do_frestore(m68k, addr, -1); |
| 2119 | break; |
| 2120 | |
| 2121 | case 3: // (An)+ |
| 2122 | addr = EA_AY_PI_32(m68k); |
| 2123 | m68040_do_frestore(m68k, addr, reg); |
| 2124 | break; |
| 2125 | |
| 2126 | case 5: // (D16, An) |
| 2127 | addr = EA_AY_DI_16(m68k); |
| 2128 | m68040_do_frestore(m68k, addr, -1); |
| 2129 | break; |
| 2130 | |
| 2131 | case 7: // |
| 2132 | switch (reg) |
| 2133 | { |
| 2134 | case 1: // (abs32) |
| 2135 | { |
| 2136 | addr = EA_AL_32(m68k); |
| 2137 | m68040_do_frestore(m68k, addr, -1); |
| 2138 | break; |
| 2139 | } |
| 2140 | case 2: // (d16, PC) |
| 2141 | { |
| 2142 | addr = EA_PCDI_16(m68k); |
| 2143 | m68040_do_frestore(m68k, addr, -1); |
| 2144 | break; |
| 2145 | } |
| 2146 | default: |
| 2147 | fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); |
| 2148 | } |
| 2149 | |
| 2150 | break; |
| 2151 | |
| 2152 | default: |
| 2153 | fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC(m68k)); |
| 2154 | } |
| 2155 | break; |
| 2156 | } |
| 2157 | break; |
| 2158 | |
| 2159 | default: fatalerror("m68040_fpu_op1: unimplemented op %d at %08X\n", (m68k->ir >> 6) & 0x3, REG_PC(m68k)-2); |
| 2160 | } |
| 2161 | } |
trunk/src/emu/cpu/m6800/6800tbl.c
| r28738 | r28739 | |
| 1 | | |
| 2 | | const m6800_cpu_device::op_func m6800_cpu_device::m6800_insn[0x100] = { |
| 3 | | &m6800_cpu_device::illegal,&m6800_cpu_device::nop, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::tap, &m6800_cpu_device::tpa, |
| 4 | | &m6800_cpu_device::inx, &m6800_cpu_device::dex, &m6800_cpu_device::clv, &m6800_cpu_device::sev, &m6800_cpu_device::clc, &m6800_cpu_device::sec, &m6800_cpu_device::cli, &m6800_cpu_device::sei, |
| 5 | | &m6800_cpu_device::sba, &m6800_cpu_device::cba, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::tab, &m6800_cpu_device::tba, |
| 6 | | &m6800_cpu_device::illegal,&m6800_cpu_device::daa, &m6800_cpu_device::illegal,&m6800_cpu_device::aba, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal, |
| 7 | | &m6800_cpu_device::bra, &m6800_cpu_device::brn, &m6800_cpu_device::bhi, &m6800_cpu_device::bls, &m6800_cpu_device::bcc, &m6800_cpu_device::bcs, &m6800_cpu_device::bne, &m6800_cpu_device::beq, |
| 8 | | &m6800_cpu_device::bvc, &m6800_cpu_device::bvs, &m6800_cpu_device::bpl, &m6800_cpu_device::bmi, &m6800_cpu_device::bge, &m6800_cpu_device::blt, &m6800_cpu_device::bgt, &m6800_cpu_device::ble, |
| 9 | | &m6800_cpu_device::tsx, &m6800_cpu_device::ins, &m6800_cpu_device::pula, &m6800_cpu_device::pulb, &m6800_cpu_device::des, &m6800_cpu_device::txs, &m6800_cpu_device::psha, &m6800_cpu_device::pshb, |
| 10 | | &m6800_cpu_device::illegal,&m6800_cpu_device::rts, &m6800_cpu_device::illegal,&m6800_cpu_device::rti, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::wai, &m6800_cpu_device::swi, |
| 11 | | &m6800_cpu_device::nega, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::coma, &m6800_cpu_device::lsra, &m6800_cpu_device::illegal,&m6800_cpu_device::rora, &m6800_cpu_device::asra, |
| 12 | | &m6800_cpu_device::asla, &m6800_cpu_device::rola, &m6800_cpu_device::deca, &m6800_cpu_device::illegal,&m6800_cpu_device::inca, &m6800_cpu_device::tsta, &m6800_cpu_device::illegal,&m6800_cpu_device::clra, |
| 13 | | &m6800_cpu_device::negb, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::comb, &m6800_cpu_device::lsrb, &m6800_cpu_device::illegal,&m6800_cpu_device::rorb, &m6800_cpu_device::asrb, |
| 14 | | &m6800_cpu_device::aslb, &m6800_cpu_device::rolb, &m6800_cpu_device::decb, &m6800_cpu_device::illegal,&m6800_cpu_device::incb, &m6800_cpu_device::tstb, &m6800_cpu_device::illegal,&m6800_cpu_device::clrb, |
| 15 | | &m6800_cpu_device::neg_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::com_ix, &m6800_cpu_device::lsr_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::ror_ix, &m6800_cpu_device::asr_ix, |
| 16 | | &m6800_cpu_device::asl_ix, &m6800_cpu_device::rol_ix, &m6800_cpu_device::dec_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::inc_ix, &m6800_cpu_device::tst_ix, &m6800_cpu_device::jmp_ix, &m6800_cpu_device::clr_ix, |
| 17 | | &m6800_cpu_device::neg_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::com_ex, &m6800_cpu_device::lsr_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::ror_ex, &m6800_cpu_device::asr_ex, |
| 18 | | &m6800_cpu_device::asl_ex, &m6800_cpu_device::rol_ex, &m6800_cpu_device::dec_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::inc_ex, &m6800_cpu_device::tst_ex, &m6800_cpu_device::jmp_ex, &m6800_cpu_device::clr_ex, |
| 19 | | &m6800_cpu_device::suba_im,&m6800_cpu_device::cmpa_im,&m6800_cpu_device::sbca_im,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_im,&m6800_cpu_device::bita_im,&m6800_cpu_device::lda_im, &m6800_cpu_device::sta_im, |
| 20 | | &m6800_cpu_device::eora_im,&m6800_cpu_device::adca_im,&m6800_cpu_device::ora_im, &m6800_cpu_device::adda_im,&m6800_cpu_device::cmpx_im,&m6800_cpu_device::bsr, &m6800_cpu_device::lds_im, &m6800_cpu_device::sts_im, |
| 21 | | &m6800_cpu_device::suba_di,&m6800_cpu_device::cmpa_di,&m6800_cpu_device::sbca_di,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_di,&m6800_cpu_device::bita_di,&m6800_cpu_device::lda_di, &m6800_cpu_device::sta_di, |
| 22 | | &m6800_cpu_device::eora_di,&m6800_cpu_device::adca_di,&m6800_cpu_device::ora_di, &m6800_cpu_device::adda_di,&m6800_cpu_device::cmpx_di,&m6800_cpu_device::jsr_di, &m6800_cpu_device::lds_di, &m6800_cpu_device::sts_di, |
| 23 | | &m6800_cpu_device::suba_ix,&m6800_cpu_device::cmpa_ix,&m6800_cpu_device::sbca_ix,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_ix,&m6800_cpu_device::bita_ix,&m6800_cpu_device::lda_ix, &m6800_cpu_device::sta_ix, |
| 24 | | &m6800_cpu_device::eora_ix,&m6800_cpu_device::adca_ix,&m6800_cpu_device::ora_ix, &m6800_cpu_device::adda_ix,&m6800_cpu_device::cmpx_ix,&m6800_cpu_device::jsr_ix, &m6800_cpu_device::lds_ix, &m6800_cpu_device::sts_ix, |
| 25 | | &m6800_cpu_device::suba_ex,&m6800_cpu_device::cmpa_ex,&m6800_cpu_device::sbca_ex,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_ex,&m6800_cpu_device::bita_ex,&m6800_cpu_device::lda_ex, &m6800_cpu_device::sta_ex, |
| 26 | | &m6800_cpu_device::eora_ex,&m6800_cpu_device::adca_ex,&m6800_cpu_device::ora_ex, &m6800_cpu_device::adda_ex,&m6800_cpu_device::cmpx_ex,&m6800_cpu_device::jsr_ex, &m6800_cpu_device::lds_ex, &m6800_cpu_device::sts_ex, |
| 27 | | &m6800_cpu_device::subb_im,&m6800_cpu_device::cmpb_im,&m6800_cpu_device::sbcb_im,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_im,&m6800_cpu_device::bitb_im,&m6800_cpu_device::ldb_im, &m6800_cpu_device::stb_im, |
| 28 | | &m6800_cpu_device::eorb_im,&m6800_cpu_device::adcb_im,&m6800_cpu_device::orb_im, &m6800_cpu_device::addb_im,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::ldx_im, &m6800_cpu_device::stx_im, |
| 29 | | &m6800_cpu_device::subb_di,&m6800_cpu_device::cmpb_di,&m6800_cpu_device::sbcb_di,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_di,&m6800_cpu_device::bitb_di,&m6800_cpu_device::ldb_di, &m6800_cpu_device::stb_di, |
| 30 | | &m6800_cpu_device::eorb_di,&m6800_cpu_device::adcb_di,&m6800_cpu_device::orb_di, &m6800_cpu_device::addb_di,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::ldx_di, &m6800_cpu_device::stx_di, |
| 31 | | &m6800_cpu_device::subb_ix,&m6800_cpu_device::cmpb_ix,&m6800_cpu_device::sbcb_ix,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_ix,&m6800_cpu_device::bitb_ix,&m6800_cpu_device::ldb_ix, &m6800_cpu_device::stb_ix, |
| 32 | | &m6800_cpu_device::eorb_ix,&m6800_cpu_device::adcb_ix,&m6800_cpu_device::orb_ix, &m6800_cpu_device::addb_ix,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::ldx_ix, &m6800_cpu_device::stx_ix, |
| 33 | | &m6800_cpu_device::subb_ex,&m6800_cpu_device::cmpb_ex,&m6800_cpu_device::sbcb_ex,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_ex,&m6800_cpu_device::bitb_ex,&m6800_cpu_device::ldb_ex, &m6800_cpu_device::stb_ex, |
| 34 | | &m6800_cpu_device::eorb_ex,&m6800_cpu_device::adcb_ex,&m6800_cpu_device::orb_ex, &m6800_cpu_device::addb_ex,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::ldx_ex, &m6800_cpu_device::stx_ex |
| 35 | | }; |
| 36 | | |
| 37 | | const m6800_cpu_device::op_func m6800_cpu_device::m6803_insn[0x100] = { |
| 38 | | &m6800_cpu_device::illegal,&m6800_cpu_device::nop, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::lsrd, &m6800_cpu_device::asld, &m6800_cpu_device::tap, &m6800_cpu_device::tpa, |
| 39 | | &m6800_cpu_device::inx, &m6800_cpu_device::dex, &m6800_cpu_device::clv, &m6800_cpu_device::sev, &m6800_cpu_device::clc, &m6800_cpu_device::sec, &m6800_cpu_device::cli, &m6800_cpu_device::sei, |
| 40 | | &m6800_cpu_device::sba, &m6800_cpu_device::cba, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::tab, &m6800_cpu_device::tba, |
| 41 | | &m6800_cpu_device::illegal,&m6800_cpu_device::daa, &m6800_cpu_device::illegal,&m6800_cpu_device::aba, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal, |
| 42 | | &m6800_cpu_device::bra, &m6800_cpu_device::brn, &m6800_cpu_device::bhi, &m6800_cpu_device::bls, &m6800_cpu_device::bcc, &m6800_cpu_device::bcs, &m6800_cpu_device::bne, &m6800_cpu_device::beq, |
| 43 | | &m6800_cpu_device::bvc, &m6800_cpu_device::bvs, &m6800_cpu_device::bpl, &m6800_cpu_device::bmi, &m6800_cpu_device::bge, &m6800_cpu_device::blt, &m6800_cpu_device::bgt, &m6800_cpu_device::ble, |
| 44 | | &m6800_cpu_device::tsx, &m6800_cpu_device::ins, &m6800_cpu_device::pula, &m6800_cpu_device::pulb, &m6800_cpu_device::des, &m6800_cpu_device::txs, &m6800_cpu_device::psha, &m6800_cpu_device::pshb, |
| 45 | | &m6800_cpu_device::pulx, &m6800_cpu_device::rts, &m6800_cpu_device::abx, &m6800_cpu_device::rti, &m6800_cpu_device::pshx, &m6800_cpu_device::mul, &m6800_cpu_device::wai, &m6800_cpu_device::swi, |
| 46 | | &m6800_cpu_device::nega, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::coma, &m6800_cpu_device::lsra, &m6800_cpu_device::illegal,&m6800_cpu_device::rora, &m6800_cpu_device::asra, |
| 47 | | &m6800_cpu_device::asla, &m6800_cpu_device::rola, &m6800_cpu_device::deca, &m6800_cpu_device::illegal,&m6800_cpu_device::inca, &m6800_cpu_device::tsta, &m6800_cpu_device::illegal,&m6800_cpu_device::clra, |
| 48 | | &m6800_cpu_device::negb, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::comb, &m6800_cpu_device::lsrb, &m6800_cpu_device::illegal,&m6800_cpu_device::rorb, &m6800_cpu_device::asrb, |
| 49 | | &m6800_cpu_device::aslb, &m6800_cpu_device::rolb, &m6800_cpu_device::decb, &m6800_cpu_device::illegal,&m6800_cpu_device::incb, &m6800_cpu_device::tstb, &m6800_cpu_device::illegal,&m6800_cpu_device::clrb, |
| 50 | | &m6800_cpu_device::neg_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::com_ix, &m6800_cpu_device::lsr_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::ror_ix, &m6800_cpu_device::asr_ix, |
| 51 | | &m6800_cpu_device::asl_ix, &m6800_cpu_device::rol_ix, &m6800_cpu_device::dec_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::inc_ix, &m6800_cpu_device::tst_ix, &m6800_cpu_device::jmp_ix, &m6800_cpu_device::clr_ix, |
| 52 | | &m6800_cpu_device::neg_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::com_ex, &m6800_cpu_device::lsr_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::ror_ex, &m6800_cpu_device::asr_ex, |
| 53 | | &m6800_cpu_device::asl_ex, &m6800_cpu_device::rol_ex, &m6800_cpu_device::dec_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::inc_ex, &m6800_cpu_device::tst_ex, &m6800_cpu_device::jmp_ex, &m6800_cpu_device::clr_ex, |
| 54 | | &m6800_cpu_device::suba_im,&m6800_cpu_device::cmpa_im,&m6800_cpu_device::sbca_im,&m6800_cpu_device::subd_im,&m6800_cpu_device::anda_im,&m6800_cpu_device::bita_im,&m6800_cpu_device::lda_im, &m6800_cpu_device::sta_im, |
| 55 | | &m6800_cpu_device::eora_im,&m6800_cpu_device::adca_im,&m6800_cpu_device::ora_im, &m6800_cpu_device::adda_im,&m6800_cpu_device::cpx_im ,&m6800_cpu_device::bsr, &m6800_cpu_device::lds_im, &m6800_cpu_device::sts_im, |
| 56 | | &m6800_cpu_device::suba_di,&m6800_cpu_device::cmpa_di,&m6800_cpu_device::sbca_di,&m6800_cpu_device::subd_di,&m6800_cpu_device::anda_di,&m6800_cpu_device::bita_di,&m6800_cpu_device::lda_di, &m6800_cpu_device::sta_di, |
| 57 | | &m6800_cpu_device::eora_di,&m6800_cpu_device::adca_di,&m6800_cpu_device::ora_di, &m6800_cpu_device::adda_di,&m6800_cpu_device::cpx_di ,&m6800_cpu_device::jsr_di, &m6800_cpu_device::lds_di, &m6800_cpu_device::sts_di, |
| 58 | | &m6800_cpu_device::suba_ix,&m6800_cpu_device::cmpa_ix,&m6800_cpu_device::sbca_ix,&m6800_cpu_device::subd_ix,&m6800_cpu_device::anda_ix,&m6800_cpu_device::bita_ix,&m6800_cpu_device::lda_ix, &m6800_cpu_device::sta_ix, |
| 59 | | &m6800_cpu_device::eora_ix,&m6800_cpu_device::adca_ix,&m6800_cpu_device::ora_ix, &m6800_cpu_device::adda_ix,&m6800_cpu_device::cpx_ix ,&m6800_cpu_device::jsr_ix, &m6800_cpu_device::lds_ix, &m6800_cpu_device::sts_ix, |
| 60 | | &m6800_cpu_device::suba_ex,&m6800_cpu_device::cmpa_ex,&m6800_cpu_device::sbca_ex,&m6800_cpu_device::subd_ex,&m6800_cpu_device::anda_ex,&m6800_cpu_device::bita_ex,&m6800_cpu_device::lda_ex, &m6800_cpu_device::sta_ex, |
| 61 | | &m6800_cpu_device::eora_ex,&m6800_cpu_device::adca_ex,&m6800_cpu_device::ora_ex, &m6800_cpu_device::adda_ex,&m6800_cpu_device::cpx_ex ,&m6800_cpu_device::jsr_ex, &m6800_cpu_device::lds_ex, &m6800_cpu_device::sts_ex, |
| 62 | | &m6800_cpu_device::subb_im,&m6800_cpu_device::cmpb_im,&m6800_cpu_device::sbcb_im,&m6800_cpu_device::addd_im,&m6800_cpu_device::andb_im,&m6800_cpu_device::bitb_im,&m6800_cpu_device::ldb_im, &m6800_cpu_device::stb_im, |
| 63 | | &m6800_cpu_device::eorb_im,&m6800_cpu_device::adcb_im,&m6800_cpu_device::orb_im, &m6800_cpu_device::addb_im,&m6800_cpu_device::ldd_im, &m6800_cpu_device::std_im, &m6800_cpu_device::ldx_im, &m6800_cpu_device::stx_im, |
| 64 | | &m6800_cpu_device::subb_di,&m6800_cpu_device::cmpb_di,&m6800_cpu_device::sbcb_di,&m6800_cpu_device::addd_di,&m6800_cpu_device::andb_di,&m6800_cpu_device::bitb_di,&m6800_cpu_device::ldb_di, &m6800_cpu_device::stb_di, |
| 65 | | &m6800_cpu_device::eorb_di,&m6800_cpu_device::adcb_di,&m6800_cpu_device::orb_di, &m6800_cpu_device::addb_di,&m6800_cpu_device::ldd_di, &m6800_cpu_device::std_di, &m6800_cpu_device::ldx_di, &m6800_cpu_device::stx_di, |
| 66 | | &m6800_cpu_device::subb_ix,&m6800_cpu_device::cmpb_ix,&m6800_cpu_device::sbcb_ix,&m6800_cpu_device::addd_ix,&m6800_cpu_device::andb_ix,&m6800_cpu_device::bitb_ix,&m6800_cpu_device::ldb_ix, &m6800_cpu_device::stb_ix, |
| 67 | | &m6800_cpu_device::eorb_ix,&m6800_cpu_device::adcb_ix,&m6800_cpu_device::orb_ix, &m6800_cpu_device::addb_ix,&m6800_cpu_device::ldd_ix, &m6800_cpu_device::std_ix, &m6800_cpu_device::ldx_ix, &m6800_cpu_device::stx_ix, |
| 68 | | &m6800_cpu_device::subb_ex,&m6800_cpu_device::cmpb_ex,&m6800_cpu_device::sbcb_ex,&m6800_cpu_device::addd_ex,&m6800_cpu_device::andb_ex,&m6800_cpu_device::bitb_ex,&m6800_cpu_device::ldb_ex, &m6800_cpu_device::stb_ex, |
| 69 | | &m6800_cpu_device::eorb_ex,&m6800_cpu_device::adcb_ex,&m6800_cpu_device::orb_ex, &m6800_cpu_device::addb_ex,&m6800_cpu_device::ldd_ex, &m6800_cpu_device::std_ex, &m6800_cpu_device::ldx_ex, &m6800_cpu_device::stx_ex |
| 70 | | }; |
| 71 | | |
| 72 | | const m6800_cpu_device::op_func m6800_cpu_device::hd63701_insn[0x100] = { |
| 73 | | &m6800_cpu_device::trap, &m6800_cpu_device::nop, &m6800_cpu_device::trap, &m6800_cpu_device::trap, &m6800_cpu_device::lsrd, &m6800_cpu_device::asld, &m6800_cpu_device::tap, &m6800_cpu_device::tpa, |
| 74 | | &m6800_cpu_device::inx, &m6800_cpu_device::dex, &m6800_cpu_device::clv, &m6800_cpu_device::sev, &m6800_cpu_device::clc, &m6800_cpu_device::sec, &m6800_cpu_device::cli, &m6800_cpu_device::sei, |
| 75 | | &m6800_cpu_device::sba, &m6800_cpu_device::cba, &m6800_cpu_device::undoc1, &m6800_cpu_device::undoc2, &m6800_cpu_device::trap, &m6800_cpu_device::trap, &m6800_cpu_device::tab, &m6800_cpu_device::tba, |
| 76 | | &m6800_cpu_device::xgdx, &m6800_cpu_device::daa, &m6800_cpu_device::slp, &m6800_cpu_device::aba, &m6800_cpu_device::trap, &m6800_cpu_device::trap, &m6800_cpu_device::trap, &m6800_cpu_device::trap, |
| 77 | | &m6800_cpu_device::bra, &m6800_cpu_device::brn, &m6800_cpu_device::bhi, &m6800_cpu_device::bls, &m6800_cpu_device::bcc, &m6800_cpu_device::bcs, &m6800_cpu_device::bne, &m6800_cpu_device::beq, |
| 78 | | &m6800_cpu_device::bvc, &m6800_cpu_device::bvs, &m6800_cpu_device::bpl, &m6800_cpu_device::bmi, &m6800_cpu_device::bge, &m6800_cpu_device::blt, &m6800_cpu_device::bgt, &m6800_cpu_device::ble, |
| 79 | | &m6800_cpu_device::tsx, &m6800_cpu_device::ins, &m6800_cpu_device::pula, &m6800_cpu_device::pulb, &m6800_cpu_device::des, &m6800_cpu_device::txs, &m6800_cpu_device::psha, &m6800_cpu_device::pshb, |
| 80 | | &m6800_cpu_device::pulx, &m6800_cpu_device::rts, &m6800_cpu_device::abx, &m6800_cpu_device::rti, &m6800_cpu_device::pshx, &m6800_cpu_device::mul, &m6800_cpu_device::wai, &m6800_cpu_device::swi, |
| 81 | | &m6800_cpu_device::nega, &m6800_cpu_device::trap, &m6800_cpu_device::trap, &m6800_cpu_device::coma, &m6800_cpu_device::lsra, &m6800_cpu_device::trap, &m6800_cpu_device::rora, &m6800_cpu_device::asra, |
| 82 | | &m6800_cpu_device::asla, &m6800_cpu_device::rola, &m6800_cpu_device::deca, &m6800_cpu_device::trap, &m6800_cpu_device::inca, &m6800_cpu_device::tsta, &m6800_cpu_device::trap, &m6800_cpu_device::clra, |
| 83 | | &m6800_cpu_device::negb, &m6800_cpu_device::trap, &m6800_cpu_device::trap, &m6800_cpu_device::comb, &m6800_cpu_device::lsrb, &m6800_cpu_device::trap, &m6800_cpu_device::rorb, &m6800_cpu_device::asrb, |
| 84 | | &m6800_cpu_device::aslb, &m6800_cpu_device::rolb, &m6800_cpu_device::decb, &m6800_cpu_device::trap, &m6800_cpu_device::incb, &m6800_cpu_device::tstb, &m6800_cpu_device::trap, &m6800_cpu_device::clrb, |
| 85 | | &m6800_cpu_device::neg_ix, &m6800_cpu_device::aim_ix, &m6800_cpu_device::oim_ix, &m6800_cpu_device::com_ix, &m6800_cpu_device::lsr_ix, &m6800_cpu_device::eim_ix, &m6800_cpu_device::ror_ix, &m6800_cpu_device::asr_ix, |
| 86 | | &m6800_cpu_device::asl_ix, &m6800_cpu_device::rol_ix, &m6800_cpu_device::dec_ix, &m6800_cpu_device::tim_ix, &m6800_cpu_device::inc_ix, &m6800_cpu_device::tst_ix, &m6800_cpu_device::jmp_ix, &m6800_cpu_device::clr_ix, |
| 87 | | &m6800_cpu_device::neg_ex, &m6800_cpu_device::aim_di, &m6800_cpu_device::oim_di, &m6800_cpu_device::com_ex, &m6800_cpu_device::lsr_ex, &m6800_cpu_device::eim_di, &m6800_cpu_device::ror_ex, &m6800_cpu_device::asr_ex, |
| 88 | | &m6800_cpu_device::asl_ex, &m6800_cpu_device::rol_ex, &m6800_cpu_device::dec_ex, &m6800_cpu_device::tim_di, &m6800_cpu_device::inc_ex, &m6800_cpu_device::tst_ex, &m6800_cpu_device::jmp_ex, &m6800_cpu_device::clr_ex, |
| 89 | | &m6800_cpu_device::suba_im,&m6800_cpu_device::cmpa_im,&m6800_cpu_device::sbca_im,&m6800_cpu_device::subd_im,&m6800_cpu_device::anda_im,&m6800_cpu_device::bita_im,&m6800_cpu_device::lda_im, &m6800_cpu_device::sta_im, |
| 90 | | &m6800_cpu_device::eora_im,&m6800_cpu_device::adca_im,&m6800_cpu_device::ora_im, &m6800_cpu_device::adda_im,&m6800_cpu_device::cpx_im ,&m6800_cpu_device::bsr, &m6800_cpu_device::lds_im, &m6800_cpu_device::sts_im, |
| 91 | | &m6800_cpu_device::suba_di,&m6800_cpu_device::cmpa_di,&m6800_cpu_device::sbca_di,&m6800_cpu_device::subd_di,&m6800_cpu_device::anda_di,&m6800_cpu_device::bita_di,&m6800_cpu_device::lda_di, &m6800_cpu_device::sta_di, |
| 92 | | &m6800_cpu_device::eora_di,&m6800_cpu_device::adca_di,&m6800_cpu_device::ora_di, &m6800_cpu_device::adda_di,&m6800_cpu_device::cpx_di ,&m6800_cpu_device::jsr_di, &m6800_cpu_device::lds_di, &m6800_cpu_device::sts_di, |
| 93 | | &m6800_cpu_device::suba_ix,&m6800_cpu_device::cmpa_ix,&m6800_cpu_device::sbca_ix,&m6800_cpu_device::subd_ix,&m6800_cpu_device::anda_ix,&m6800_cpu_device::bita_ix,&m6800_cpu_device::lda_ix, &m6800_cpu_device::sta_ix, |
| 94 | | &m6800_cpu_device::eora_ix,&m6800_cpu_device::adca_ix,&m6800_cpu_device::ora_ix, &m6800_cpu_device::adda_ix,&m6800_cpu_device::cpx_ix ,&m6800_cpu_device::jsr_ix, &m6800_cpu_device::lds_ix, &m6800_cpu_device::sts_ix, |
| 95 | | &m6800_cpu_device::suba_ex,&m6800_cpu_device::cmpa_ex,&m6800_cpu_device::sbca_ex,&m6800_cpu_device::subd_ex,&m6800_cpu_device::anda_ex,&m6800_cpu_device::bita_ex,&m6800_cpu_device::lda_ex, &m6800_cpu_device::sta_ex, |
| 96 | | &m6800_cpu_device::eora_ex,&m6800_cpu_device::adca_ex,&m6800_cpu_device::ora_ex, &m6800_cpu_device::adda_ex,&m6800_cpu_device::cpx_ex ,&m6800_cpu_device::jsr_ex, &m6800_cpu_device::lds_ex, &m6800_cpu_device::sts_ex, |
| 97 | | &m6800_cpu_device::subb_im,&m6800_cpu_device::cmpb_im,&m6800_cpu_device::sbcb_im,&m6800_cpu_device::addd_im,&m6800_cpu_device::andb_im,&m6800_cpu_device::bitb_im,&m6800_cpu_device::ldb_im, &m6800_cpu_device::stb_im, |
| 98 | | &m6800_cpu_device::eorb_im,&m6800_cpu_device::adcb_im,&m6800_cpu_device::orb_im, &m6800_cpu_device::addb_im,&m6800_cpu_device::ldd_im, &m6800_cpu_device::std_im, &m6800_cpu_device::ldx_im, &m6800_cpu_device::stx_im, |
| 99 | | &m6800_cpu_device::subb_di,&m6800_cpu_device::cmpb_di,&m6800_cpu_device::sbcb_di,&m6800_cpu_device::addd_di,&m6800_cpu_device::andb_di,&m6800_cpu_device::bitb_di,&m6800_cpu_device::ldb_di, &m6800_cpu_device::stb_di, |
| 100 | | &m6800_cpu_device::eorb_di,&m6800_cpu_device::adcb_di,&m6800_cpu_device::orb_di, &m6800_cpu_device::addb_di,&m6800_cpu_device::ldd_di, &m6800_cpu_device::std_di, &m6800_cpu_device::ldx_di, &m6800_cpu_device::stx_di, |
| 101 | | &m6800_cpu_device::subb_ix,&m6800_cpu_device::cmpb_ix,&m6800_cpu_device::sbcb_ix,&m6800_cpu_device::addd_ix,&m6800_cpu_device::andb_ix,&m6800_cpu_device::bitb_ix,&m6800_cpu_device::ldb_ix, &m6800_cpu_device::stb_ix, |
| 102 | | &m6800_cpu_device::eorb_ix,&m6800_cpu_device::adcb_ix,&m6800_cpu_device::orb_ix, &m6800_cpu_device::addb_ix,&m6800_cpu_device::ldd_ix, &m6800_cpu_device::std_ix, &m6800_cpu_device::ldx_ix, &m6800_cpu_device::stx_ix, |
| 103 | | &m6800_cpu_device::subb_ex,&m6800_cpu_device::cmpb_ex,&m6800_cpu_device::sbcb_ex,&m6800_cpu_device::addd_ex,&m6800_cpu_device::andb_ex,&m6800_cpu_device::bitb_ex,&m6800_cpu_device::ldb_ex, &m6800_cpu_device::stb_ex, |
| 104 | | &m6800_cpu_device::eorb_ex,&m6800_cpu_device::adcb_ex,&m6800_cpu_device::orb_ex, &m6800_cpu_device::addb_ex,&m6800_cpu_device::ldd_ex, &m6800_cpu_device::std_ex, &m6800_cpu_device::ldx_ex, &m6800_cpu_device::stx_ex |
| 105 | | }; |
| 106 | | |
| 107 | | const m6800_cpu_device::op_func m6800_cpu_device::nsc8105_insn[0x100] = { |
| 108 | | &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::nop, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::tap, &m6800_cpu_device::illegal,&m6800_cpu_device::tpa, |
| 109 | | &m6800_cpu_device::inx, &m6800_cpu_device::clv, &m6800_cpu_device::dex, &m6800_cpu_device::sev, &m6800_cpu_device::clc, &m6800_cpu_device::cli, &m6800_cpu_device::sec, &m6800_cpu_device::sei, |
| 110 | | &m6800_cpu_device::sba, &m6800_cpu_device::illegal,&m6800_cpu_device::cba, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::tab, &m6800_cpu_device::illegal,&m6800_cpu_device::tba, |
| 111 | | &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::daa, &m6800_cpu_device::aba, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal, |
| 112 | | &m6800_cpu_device::bra, &m6800_cpu_device::bhi, &m6800_cpu_device::brn, &m6800_cpu_device::bls, &m6800_cpu_device::bcc, &m6800_cpu_device::bne, &m6800_cpu_device::bcs, &m6800_cpu_device::beq, |
| 113 | | &m6800_cpu_device::bvc, &m6800_cpu_device::bpl, &m6800_cpu_device::bvs, &m6800_cpu_device::bmi, &m6800_cpu_device::bge, &m6800_cpu_device::bgt, &m6800_cpu_device::blt, &m6800_cpu_device::ble, |
| 114 | | &m6800_cpu_device::tsx, &m6800_cpu_device::pula, &m6800_cpu_device::ins, &m6800_cpu_device::pulb, &m6800_cpu_device::des, &m6800_cpu_device::psha, &m6800_cpu_device::txs, &m6800_cpu_device::pshb, |
| 115 | | &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::rts, &m6800_cpu_device::rti, &m6800_cpu_device::illegal,&m6800_cpu_device::wai, &m6800_cpu_device::illegal,&m6800_cpu_device::swi, |
| 116 | | &m6800_cpu_device::suba_im,&m6800_cpu_device::sbca_im,&m6800_cpu_device::cmpa_im,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_im,&m6800_cpu_device::lda_im, &m6800_cpu_device::bita_im,&m6800_cpu_device::sta_im, |
| 117 | | &m6800_cpu_device::eora_im,&m6800_cpu_device::ora_im, &m6800_cpu_device::adca_im,&m6800_cpu_device::adda_im,&m6800_cpu_device::cmpx_im,&m6800_cpu_device::lds_im, &m6800_cpu_device::bsr, &m6800_cpu_device::sts_im, |
| 118 | | &m6800_cpu_device::suba_di,&m6800_cpu_device::sbca_di,&m6800_cpu_device::cmpa_di,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_di,&m6800_cpu_device::lda_di, &m6800_cpu_device::bita_di,&m6800_cpu_device::sta_di, |
| 119 | | &m6800_cpu_device::eora_di,&m6800_cpu_device::ora_di, &m6800_cpu_device::adca_di,&m6800_cpu_device::adda_di,&m6800_cpu_device::cmpx_di,&m6800_cpu_device::lds_di, &m6800_cpu_device::jsr_di, &m6800_cpu_device::sts_di, |
| 120 | | &m6800_cpu_device::suba_ix,&m6800_cpu_device::sbca_ix,&m6800_cpu_device::cmpa_ix,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_ix,&m6800_cpu_device::lda_ix, &m6800_cpu_device::bita_ix,&m6800_cpu_device::sta_ix, |
| 121 | | &m6800_cpu_device::eora_ix,&m6800_cpu_device::ora_ix, &m6800_cpu_device::adca_ix,&m6800_cpu_device::adda_ix,&m6800_cpu_device::cmpx_ix,&m6800_cpu_device::lds_ix, &m6800_cpu_device::jsr_ix, &m6800_cpu_device::sts_ix, |
| 122 | | &m6800_cpu_device::suba_ex,&m6800_cpu_device::sbca_ex,&m6800_cpu_device::cmpa_ex,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_ex,&m6800_cpu_device::lda_ex, &m6800_cpu_device::bita_ex,&m6800_cpu_device::sta_ex, |
| 123 | | &m6800_cpu_device::eora_ex,&m6800_cpu_device::ora_ex, &m6800_cpu_device::adca_ex,&m6800_cpu_device::adda_ex,&m6800_cpu_device::cmpx_ex,&m6800_cpu_device::lds_ex, &m6800_cpu_device::jsr_ex, &m6800_cpu_device::sts_ex, |
| 124 | | &m6800_cpu_device::nega, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::coma, &m6800_cpu_device::lsra, &m6800_cpu_device::rora, &m6800_cpu_device::illegal,&m6800_cpu_device::asra, |
| 125 | | &m6800_cpu_device::asla, &m6800_cpu_device::deca, &m6800_cpu_device::rola, &m6800_cpu_device::illegal,&m6800_cpu_device::inca, &m6800_cpu_device::illegal,&m6800_cpu_device::tsta, &m6800_cpu_device::clra, |
| 126 | | &m6800_cpu_device::negb, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::comb, &m6800_cpu_device::lsrb, &m6800_cpu_device::rorb, &m6800_cpu_device::illegal,&m6800_cpu_device::asrb, |
| 127 | | &m6800_cpu_device::aslb, &m6800_cpu_device::decb, &m6800_cpu_device::rolb, &m6800_cpu_device::illegal,&m6800_cpu_device::incb, &m6800_cpu_device::illegal,&m6800_cpu_device::tstb, &m6800_cpu_device::clrb, |
| 128 | | &m6800_cpu_device::neg_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::com_ix, &m6800_cpu_device::lsr_ix, &m6800_cpu_device::ror_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::asr_ix, |
| 129 | | &m6800_cpu_device::asl_ix, &m6800_cpu_device::dec_ix, &m6800_cpu_device::rol_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::inc_ix, &m6800_cpu_device::jmp_ix, &m6800_cpu_device::tst_ix, &m6800_cpu_device::clr_ix, |
| 130 | | &m6800_cpu_device::neg_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::com_ex, &m6800_cpu_device::lsr_ex, &m6800_cpu_device::ror_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::asr_ex, |
| 131 | | &m6800_cpu_device::asl_ex, &m6800_cpu_device::dec_ex, &m6800_cpu_device::rol_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::inc_ex, &m6800_cpu_device::jmp_ex, &m6800_cpu_device::tst_ex, &m6800_cpu_device::clr_ex, |
| 132 | | &m6800_cpu_device::subb_im,&m6800_cpu_device::sbcb_im,&m6800_cpu_device::cmpb_im,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_im,&m6800_cpu_device::ldb_im, &m6800_cpu_device::bitb_im,&m6800_cpu_device::stb_im, |
| 133 | | &m6800_cpu_device::eorb_im,&m6800_cpu_device::orb_im, &m6800_cpu_device::adcb_im,&m6800_cpu_device::addb_im,&m6800_cpu_device::illegal,&m6800_cpu_device::ldx_im, &m6800_cpu_device::illegal,&m6800_cpu_device::stx_im, |
| 134 | | &m6800_cpu_device::subb_di,&m6800_cpu_device::sbcb_di,&m6800_cpu_device::cmpb_di,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_di,&m6800_cpu_device::ldb_di, &m6800_cpu_device::bitb_di,&m6800_cpu_device::stb_di, |
| 135 | | &m6800_cpu_device::eorb_di,&m6800_cpu_device::orb_di, &m6800_cpu_device::adcb_di,&m6800_cpu_device::addb_di,&m6800_cpu_device::illegal,&m6800_cpu_device::ldx_di, &m6800_cpu_device::illegal,&m6800_cpu_device::stx_di, |
| 136 | | &m6800_cpu_device::subb_ix,&m6800_cpu_device::sbcb_ix,&m6800_cpu_device::cmpb_ix,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_ix,&m6800_cpu_device::ldb_ix, &m6800_cpu_device::bitb_ix,&m6800_cpu_device::stb_ix, |
| 137 | | &m6800_cpu_device::eorb_ix,&m6800_cpu_device::orb_ix, &m6800_cpu_device::adcb_ix,&m6800_cpu_device::addb_ix,&m6800_cpu_device::adcx_im,&m6800_cpu_device::ldx_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::stx_ix, |
| 138 | | &m6800_cpu_device::subb_ex,&m6800_cpu_device::sbcb_ex,&m6800_cpu_device::cmpb_ex,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_ex,&m6800_cpu_device::ldb_ex, &m6800_cpu_device::bitb_ex,&m6800_cpu_device::stb_ex, |
| 139 | | &m6800_cpu_device::eorb_ex,&m6800_cpu_device::orb_ex, &m6800_cpu_device::adcb_ex,&m6800_cpu_device::addb_ex,&m6800_cpu_device::addx_ex,&m6800_cpu_device::ldx_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::stx_ex |
| 140 | | }; |
trunk/src/emu/cpu/m6800/6800tbl.inc
| r0 | r28739 | |
| 1 | |
| 2 | const m6800_cpu_device::op_func m6800_cpu_device::m6800_insn[0x100] = { |
| 3 | &m6800_cpu_device::illegal,&m6800_cpu_device::nop, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::tap, &m6800_cpu_device::tpa, |
| 4 | &m6800_cpu_device::inx, &m6800_cpu_device::dex, &m6800_cpu_device::clv, &m6800_cpu_device::sev, &m6800_cpu_device::clc, &m6800_cpu_device::sec, &m6800_cpu_device::cli, &m6800_cpu_device::sei, |
| 5 | &m6800_cpu_device::sba, &m6800_cpu_device::cba, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::tab, &m6800_cpu_device::tba, |
| 6 | &m6800_cpu_device::illegal,&m6800_cpu_device::daa, &m6800_cpu_device::illegal,&m6800_cpu_device::aba, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal, |
| 7 | &m6800_cpu_device::bra, &m6800_cpu_device::brn, &m6800_cpu_device::bhi, &m6800_cpu_device::bls, &m6800_cpu_device::bcc, &m6800_cpu_device::bcs, &m6800_cpu_device::bne, &m6800_cpu_device::beq, |
| 8 | &m6800_cpu_device::bvc, &m6800_cpu_device::bvs, &m6800_cpu_device::bpl, &m6800_cpu_device::bmi, &m6800_cpu_device::bge, &m6800_cpu_device::blt, &m6800_cpu_device::bgt, &m6800_cpu_device::ble, |
| 9 | &m6800_cpu_device::tsx, &m6800_cpu_device::ins, &m6800_cpu_device::pula, &m6800_cpu_device::pulb, &m6800_cpu_device::des, &m6800_cpu_device::txs, &m6800_cpu_device::psha, &m6800_cpu_device::pshb, |
| 10 | &m6800_cpu_device::illegal,&m6800_cpu_device::rts, &m6800_cpu_device::illegal,&m6800_cpu_device::rti, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::wai, &m6800_cpu_device::swi, |
| 11 | &m6800_cpu_device::nega, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::coma, &m6800_cpu_device::lsra, &m6800_cpu_device::illegal,&m6800_cpu_device::rora, &m6800_cpu_device::asra, |
| 12 | &m6800_cpu_device::asla, &m6800_cpu_device::rola, &m6800_cpu_device::deca, &m6800_cpu_device::illegal,&m6800_cpu_device::inca, &m6800_cpu_device::tsta, &m6800_cpu_device::illegal,&m6800_cpu_device::clra, |
| 13 | &m6800_cpu_device::negb, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::comb, &m6800_cpu_device::lsrb, &m6800_cpu_device::illegal,&m6800_cpu_device::rorb, &m6800_cpu_device::asrb, |
| 14 | &m6800_cpu_device::aslb, &m6800_cpu_device::rolb, &m6800_cpu_device::decb, &m6800_cpu_device::illegal,&m6800_cpu_device::incb, &m6800_cpu_device::tstb, &m6800_cpu_device::illegal,&m6800_cpu_device::clrb, |
| 15 | &m6800_cpu_device::neg_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::com_ix, &m6800_cpu_device::lsr_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::ror_ix, &m6800_cpu_device::asr_ix, |
| 16 | &m6800_cpu_device::asl_ix, &m6800_cpu_device::rol_ix, &m6800_cpu_device::dec_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::inc_ix, &m6800_cpu_device::tst_ix, &m6800_cpu_device::jmp_ix, &m6800_cpu_device::clr_ix, |
| 17 | &m6800_cpu_device::neg_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::com_ex, &m6800_cpu_device::lsr_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::ror_ex, &m6800_cpu_device::asr_ex, |
| 18 | &m6800_cpu_device::asl_ex, &m6800_cpu_device::rol_ex, &m6800_cpu_device::dec_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::inc_ex, &m6800_cpu_device::tst_ex, &m6800_cpu_device::jmp_ex, &m6800_cpu_device::clr_ex, |
| 19 | &m6800_cpu_device::suba_im,&m6800_cpu_device::cmpa_im,&m6800_cpu_device::sbca_im,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_im,&m6800_cpu_device::bita_im,&m6800_cpu_device::lda_im, &m6800_cpu_device::sta_im, |
| 20 | &m6800_cpu_device::eora_im,&m6800_cpu_device::adca_im,&m6800_cpu_device::ora_im, &m6800_cpu_device::adda_im,&m6800_cpu_device::cmpx_im,&m6800_cpu_device::bsr, &m6800_cpu_device::lds_im, &m6800_cpu_device::sts_im, |
| 21 | &m6800_cpu_device::suba_di,&m6800_cpu_device::cmpa_di,&m6800_cpu_device::sbca_di,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_di,&m6800_cpu_device::bita_di,&m6800_cpu_device::lda_di, &m6800_cpu_device::sta_di, |
| 22 | &m6800_cpu_device::eora_di,&m6800_cpu_device::adca_di,&m6800_cpu_device::ora_di, &m6800_cpu_device::adda_di,&m6800_cpu_device::cmpx_di,&m6800_cpu_device::jsr_di, &m6800_cpu_device::lds_di, &m6800_cpu_device::sts_di, |
| 23 | &m6800_cpu_device::suba_ix,&m6800_cpu_device::cmpa_ix,&m6800_cpu_device::sbca_ix,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_ix,&m6800_cpu_device::bita_ix,&m6800_cpu_device::lda_ix, &m6800_cpu_device::sta_ix, |
| 24 | &m6800_cpu_device::eora_ix,&m6800_cpu_device::adca_ix,&m6800_cpu_device::ora_ix, &m6800_cpu_device::adda_ix,&m6800_cpu_device::cmpx_ix,&m6800_cpu_device::jsr_ix, &m6800_cpu_device::lds_ix, &m6800_cpu_device::sts_ix, |
| 25 | &m6800_cpu_device::suba_ex,&m6800_cpu_device::cmpa_ex,&m6800_cpu_device::sbca_ex,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_ex,&m6800_cpu_device::bita_ex,&m6800_cpu_device::lda_ex, &m6800_cpu_device::sta_ex, |
| 26 | &m6800_cpu_device::eora_ex,&m6800_cpu_device::adca_ex,&m6800_cpu_device::ora_ex, &m6800_cpu_device::adda_ex,&m6800_cpu_device::cmpx_ex,&m6800_cpu_device::jsr_ex, &m6800_cpu_device::lds_ex, &m6800_cpu_device::sts_ex, |
| 27 | &m6800_cpu_device::subb_im,&m6800_cpu_device::cmpb_im,&m6800_cpu_device::sbcb_im,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_im,&m6800_cpu_device::bitb_im,&m6800_cpu_device::ldb_im, &m6800_cpu_device::stb_im, |
| 28 | &m6800_cpu_device::eorb_im,&m6800_cpu_device::adcb_im,&m6800_cpu_device::orb_im, &m6800_cpu_device::addb_im,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::ldx_im, &m6800_cpu_device::stx_im, |
| 29 | &m6800_cpu_device::subb_di,&m6800_cpu_device::cmpb_di,&m6800_cpu_device::sbcb_di,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_di,&m6800_cpu_device::bitb_di,&m6800_cpu_device::ldb_di, &m6800_cpu_device::stb_di, |
| 30 | &m6800_cpu_device::eorb_di,&m6800_cpu_device::adcb_di,&m6800_cpu_device::orb_di, &m6800_cpu_device::addb_di,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::ldx_di, &m6800_cpu_device::stx_di, |
| 31 | &m6800_cpu_device::subb_ix,&m6800_cpu_device::cmpb_ix,&m6800_cpu_device::sbcb_ix,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_ix,&m6800_cpu_device::bitb_ix,&m6800_cpu_device::ldb_ix, &m6800_cpu_device::stb_ix, |
| 32 | &m6800_cpu_device::eorb_ix,&m6800_cpu_device::adcb_ix,&m6800_cpu_device::orb_ix, &m6800_cpu_device::addb_ix,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::ldx_ix, &m6800_cpu_device::stx_ix, |
| 33 | &m6800_cpu_device::subb_ex,&m6800_cpu_device::cmpb_ex,&m6800_cpu_device::sbcb_ex,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_ex,&m6800_cpu_device::bitb_ex,&m6800_cpu_device::ldb_ex, &m6800_cpu_device::stb_ex, |
| 34 | &m6800_cpu_device::eorb_ex,&m6800_cpu_device::adcb_ex,&m6800_cpu_device::orb_ex, &m6800_cpu_device::addb_ex,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::ldx_ex, &m6800_cpu_device::stx_ex |
| 35 | }; |
| 36 | |
| 37 | const m6800_cpu_device::op_func m6800_cpu_device::m6803_insn[0x100] = { |
| 38 | &m6800_cpu_device::illegal,&m6800_cpu_device::nop, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::lsrd, &m6800_cpu_device::asld, &m6800_cpu_device::tap, &m6800_cpu_device::tpa, |
| 39 | &m6800_cpu_device::inx, &m6800_cpu_device::dex, &m6800_cpu_device::clv, &m6800_cpu_device::sev, &m6800_cpu_device::clc, &m6800_cpu_device::sec, &m6800_cpu_device::cli, &m6800_cpu_device::sei, |
| 40 | &m6800_cpu_device::sba, &m6800_cpu_device::cba, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::tab, &m6800_cpu_device::tba, |
| 41 | &m6800_cpu_device::illegal,&m6800_cpu_device::daa, &m6800_cpu_device::illegal,&m6800_cpu_device::aba, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal, |
| 42 | &m6800_cpu_device::bra, &m6800_cpu_device::brn, &m6800_cpu_device::bhi, &m6800_cpu_device::bls, &m6800_cpu_device::bcc, &m6800_cpu_device::bcs, &m6800_cpu_device::bne, &m6800_cpu_device::beq, |
| 43 | &m6800_cpu_device::bvc, &m6800_cpu_device::bvs, &m6800_cpu_device::bpl, &m6800_cpu_device::bmi, &m6800_cpu_device::bge, &m6800_cpu_device::blt, &m6800_cpu_device::bgt, &m6800_cpu_device::ble, |
| 44 | &m6800_cpu_device::tsx, &m6800_cpu_device::ins, &m6800_cpu_device::pula, &m6800_cpu_device::pulb, &m6800_cpu_device::des, &m6800_cpu_device::txs, &m6800_cpu_device::psha, &m6800_cpu_device::pshb, |
| 45 | &m6800_cpu_device::pulx, &m6800_cpu_device::rts, &m6800_cpu_device::abx, &m6800_cpu_device::rti, &m6800_cpu_device::pshx, &m6800_cpu_device::mul, &m6800_cpu_device::wai, &m6800_cpu_device::swi, |
| 46 | &m6800_cpu_device::nega, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::coma, &m6800_cpu_device::lsra, &m6800_cpu_device::illegal,&m6800_cpu_device::rora, &m6800_cpu_device::asra, |
| 47 | &m6800_cpu_device::asla, &m6800_cpu_device::rola, &m6800_cpu_device::deca, &m6800_cpu_device::illegal,&m6800_cpu_device::inca, &m6800_cpu_device::tsta, &m6800_cpu_device::illegal,&m6800_cpu_device::clra, |
| 48 | &m6800_cpu_device::negb, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::comb, &m6800_cpu_device::lsrb, &m6800_cpu_device::illegal,&m6800_cpu_device::rorb, &m6800_cpu_device::asrb, |
| 49 | &m6800_cpu_device::aslb, &m6800_cpu_device::rolb, &m6800_cpu_device::decb, &m6800_cpu_device::illegal,&m6800_cpu_device::incb, &m6800_cpu_device::tstb, &m6800_cpu_device::illegal,&m6800_cpu_device::clrb, |
| 50 | &m6800_cpu_device::neg_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::com_ix, &m6800_cpu_device::lsr_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::ror_ix, &m6800_cpu_device::asr_ix, |
| 51 | &m6800_cpu_device::asl_ix, &m6800_cpu_device::rol_ix, &m6800_cpu_device::dec_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::inc_ix, &m6800_cpu_device::tst_ix, &m6800_cpu_device::jmp_ix, &m6800_cpu_device::clr_ix, |
| 52 | &m6800_cpu_device::neg_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::com_ex, &m6800_cpu_device::lsr_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::ror_ex, &m6800_cpu_device::asr_ex, |
| 53 | &m6800_cpu_device::asl_ex, &m6800_cpu_device::rol_ex, &m6800_cpu_device::dec_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::inc_ex, &m6800_cpu_device::tst_ex, &m6800_cpu_device::jmp_ex, &m6800_cpu_device::clr_ex, |
| 54 | &m6800_cpu_device::suba_im,&m6800_cpu_device::cmpa_im,&m6800_cpu_device::sbca_im,&m6800_cpu_device::subd_im,&m6800_cpu_device::anda_im,&m6800_cpu_device::bita_im,&m6800_cpu_device::lda_im, &m6800_cpu_device::sta_im, |
| 55 | &m6800_cpu_device::eora_im,&m6800_cpu_device::adca_im,&m6800_cpu_device::ora_im, &m6800_cpu_device::adda_im,&m6800_cpu_device::cpx_im ,&m6800_cpu_device::bsr, &m6800_cpu_device::lds_im, &m6800_cpu_device::sts_im, |
| 56 | &m6800_cpu_device::suba_di,&m6800_cpu_device::cmpa_di,&m6800_cpu_device::sbca_di,&m6800_cpu_device::subd_di,&m6800_cpu_device::anda_di,&m6800_cpu_device::bita_di,&m6800_cpu_device::lda_di, &m6800_cpu_device::sta_di, |
| 57 | &m6800_cpu_device::eora_di,&m6800_cpu_device::adca_di,&m6800_cpu_device::ora_di, &m6800_cpu_device::adda_di,&m6800_cpu_device::cpx_di ,&m6800_cpu_device::jsr_di, &m6800_cpu_device::lds_di, &m6800_cpu_device::sts_di, |
| 58 | &m6800_cpu_device::suba_ix,&m6800_cpu_device::cmpa_ix,&m6800_cpu_device::sbca_ix,&m6800_cpu_device::subd_ix,&m6800_cpu_device::anda_ix,&m6800_cpu_device::bita_ix,&m6800_cpu_device::lda_ix, &m6800_cpu_device::sta_ix, |
| 59 | &m6800_cpu_device::eora_ix,&m6800_cpu_device::adca_ix,&m6800_cpu_device::ora_ix, &m6800_cpu_device::adda_ix,&m6800_cpu_device::cpx_ix ,&m6800_cpu_device::jsr_ix, &m6800_cpu_device::lds_ix, &m6800_cpu_device::sts_ix, |
| 60 | &m6800_cpu_device::suba_ex,&m6800_cpu_device::cmpa_ex,&m6800_cpu_device::sbca_ex,&m6800_cpu_device::subd_ex,&m6800_cpu_device::anda_ex,&m6800_cpu_device::bita_ex,&m6800_cpu_device::lda_ex, &m6800_cpu_device::sta_ex, |
| 61 | &m6800_cpu_device::eora_ex,&m6800_cpu_device::adca_ex,&m6800_cpu_device::ora_ex, &m6800_cpu_device::adda_ex,&m6800_cpu_device::cpx_ex ,&m6800_cpu_device::jsr_ex, &m6800_cpu_device::lds_ex, &m6800_cpu_device::sts_ex, |
| 62 | &m6800_cpu_device::subb_im,&m6800_cpu_device::cmpb_im,&m6800_cpu_device::sbcb_im,&m6800_cpu_device::addd_im,&m6800_cpu_device::andb_im,&m6800_cpu_device::bitb_im,&m6800_cpu_device::ldb_im, &m6800_cpu_device::stb_im, |
| 63 | &m6800_cpu_device::eorb_im,&m6800_cpu_device::adcb_im,&m6800_cpu_device::orb_im, &m6800_cpu_device::addb_im,&m6800_cpu_device::ldd_im, &m6800_cpu_device::std_im, &m6800_cpu_device::ldx_im, &m6800_cpu_device::stx_im, |
| 64 | &m6800_cpu_device::subb_di,&m6800_cpu_device::cmpb_di,&m6800_cpu_device::sbcb_di,&m6800_cpu_device::addd_di,&m6800_cpu_device::andb_di,&m6800_cpu_device::bitb_di,&m6800_cpu_device::ldb_di, &m6800_cpu_device::stb_di, |
| 65 | &m6800_cpu_device::eorb_di,&m6800_cpu_device::adcb_di,&m6800_cpu_device::orb_di, &m6800_cpu_device::addb_di,&m6800_cpu_device::ldd_di, &m6800_cpu_device::std_di, &m6800_cpu_device::ldx_di, &m6800_cpu_device::stx_di, |
| 66 | &m6800_cpu_device::subb_ix,&m6800_cpu_device::cmpb_ix,&m6800_cpu_device::sbcb_ix,&m6800_cpu_device::addd_ix,&m6800_cpu_device::andb_ix,&m6800_cpu_device::bitb_ix,&m6800_cpu_device::ldb_ix, &m6800_cpu_device::stb_ix, |
| 67 | &m6800_cpu_device::eorb_ix,&m6800_cpu_device::adcb_ix,&m6800_cpu_device::orb_ix, &m6800_cpu_device::addb_ix,&m6800_cpu_device::ldd_ix, &m6800_cpu_device::std_ix, &m6800_cpu_device::ldx_ix, &m6800_cpu_device::stx_ix, |
| 68 | &m6800_cpu_device::subb_ex,&m6800_cpu_device::cmpb_ex,&m6800_cpu_device::sbcb_ex,&m6800_cpu_device::addd_ex,&m6800_cpu_device::andb_ex,&m6800_cpu_device::bitb_ex,&m6800_cpu_device::ldb_ex, &m6800_cpu_device::stb_ex, |
| 69 | &m6800_cpu_device::eorb_ex,&m6800_cpu_device::adcb_ex,&m6800_cpu_device::orb_ex, &m6800_cpu_device::addb_ex,&m6800_cpu_device::ldd_ex, &m6800_cpu_device::std_ex, &m6800_cpu_device::ldx_ex, &m6800_cpu_device::stx_ex |
| 70 | }; |
| 71 | |
| 72 | const m6800_cpu_device::op_func m6800_cpu_device::hd63701_insn[0x100] = { |
| 73 | &m6800_cpu_device::trap, &m6800_cpu_device::nop, &m6800_cpu_device::trap, &m6800_cpu_device::trap, &m6800_cpu_device::lsrd, &m6800_cpu_device::asld, &m6800_cpu_device::tap, &m6800_cpu_device::tpa, |
| 74 | &m6800_cpu_device::inx, &m6800_cpu_device::dex, &m6800_cpu_device::clv, &m6800_cpu_device::sev, &m6800_cpu_device::clc, &m6800_cpu_device::sec, &m6800_cpu_device::cli, &m6800_cpu_device::sei, |
| 75 | &m6800_cpu_device::sba, &m6800_cpu_device::cba, &m6800_cpu_device::undoc1, &m6800_cpu_device::undoc2, &m6800_cpu_device::trap, &m6800_cpu_device::trap, &m6800_cpu_device::tab, &m6800_cpu_device::tba, |
| 76 | &m6800_cpu_device::xgdx, &m6800_cpu_device::daa, &m6800_cpu_device::slp, &m6800_cpu_device::aba, &m6800_cpu_device::trap, &m6800_cpu_device::trap, &m6800_cpu_device::trap, &m6800_cpu_device::trap, |
| 77 | &m6800_cpu_device::bra, &m6800_cpu_device::brn, &m6800_cpu_device::bhi, &m6800_cpu_device::bls, &m6800_cpu_device::bcc, &m6800_cpu_device::bcs, &m6800_cpu_device::bne, &m6800_cpu_device::beq, |
| 78 | &m6800_cpu_device::bvc, &m6800_cpu_device::bvs, &m6800_cpu_device::bpl, &m6800_cpu_device::bmi, &m6800_cpu_device::bge, &m6800_cpu_device::blt, &m6800_cpu_device::bgt, &m6800_cpu_device::ble, |
| 79 | &m6800_cpu_device::tsx, &m6800_cpu_device::ins, &m6800_cpu_device::pula, &m6800_cpu_device::pulb, &m6800_cpu_device::des, &m6800_cpu_device::txs, &m6800_cpu_device::psha, &m6800_cpu_device::pshb, |
| 80 | &m6800_cpu_device::pulx, &m6800_cpu_device::rts, &m6800_cpu_device::abx, &m6800_cpu_device::rti, &m6800_cpu_device::pshx, &m6800_cpu_device::mul, &m6800_cpu_device::wai, &m6800_cpu_device::swi, |
| 81 | &m6800_cpu_device::nega, &m6800_cpu_device::trap, &m6800_cpu_device::trap, &m6800_cpu_device::coma, &m6800_cpu_device::lsra, &m6800_cpu_device::trap, &m6800_cpu_device::rora, &m6800_cpu_device::asra, |
| 82 | &m6800_cpu_device::asla, &m6800_cpu_device::rola, &m6800_cpu_device::deca, &m6800_cpu_device::trap, &m6800_cpu_device::inca, &m6800_cpu_device::tsta, &m6800_cpu_device::trap, &m6800_cpu_device::clra, |
| 83 | &m6800_cpu_device::negb, &m6800_cpu_device::trap, &m6800_cpu_device::trap, &m6800_cpu_device::comb, &m6800_cpu_device::lsrb, &m6800_cpu_device::trap, &m6800_cpu_device::rorb, &m6800_cpu_device::asrb, |
| 84 | &m6800_cpu_device::aslb, &m6800_cpu_device::rolb, &m6800_cpu_device::decb, &m6800_cpu_device::trap, &m6800_cpu_device::incb, &m6800_cpu_device::tstb, &m6800_cpu_device::trap, &m6800_cpu_device::clrb, |
| 85 | &m6800_cpu_device::neg_ix, &m6800_cpu_device::aim_ix, &m6800_cpu_device::oim_ix, &m6800_cpu_device::com_ix, &m6800_cpu_device::lsr_ix, &m6800_cpu_device::eim_ix, &m6800_cpu_device::ror_ix, &m6800_cpu_device::asr_ix, |
| 86 | &m6800_cpu_device::asl_ix, &m6800_cpu_device::rol_ix, &m6800_cpu_device::dec_ix, &m6800_cpu_device::tim_ix, &m6800_cpu_device::inc_ix, &m6800_cpu_device::tst_ix, &m6800_cpu_device::jmp_ix, &m6800_cpu_device::clr_ix, |
| 87 | &m6800_cpu_device::neg_ex, &m6800_cpu_device::aim_di, &m6800_cpu_device::oim_di, &m6800_cpu_device::com_ex, &m6800_cpu_device::lsr_ex, &m6800_cpu_device::eim_di, &m6800_cpu_device::ror_ex, &m6800_cpu_device::asr_ex, |
| 88 | &m6800_cpu_device::asl_ex, &m6800_cpu_device::rol_ex, &m6800_cpu_device::dec_ex, &m6800_cpu_device::tim_di, &m6800_cpu_device::inc_ex, &m6800_cpu_device::tst_ex, &m6800_cpu_device::jmp_ex, &m6800_cpu_device::clr_ex, |
| 89 | &m6800_cpu_device::suba_im,&m6800_cpu_device::cmpa_im,&m6800_cpu_device::sbca_im,&m6800_cpu_device::subd_im,&m6800_cpu_device::anda_im,&m6800_cpu_device::bita_im,&m6800_cpu_device::lda_im, &m6800_cpu_device::sta_im, |
| 90 | &m6800_cpu_device::eora_im,&m6800_cpu_device::adca_im,&m6800_cpu_device::ora_im, &m6800_cpu_device::adda_im,&m6800_cpu_device::cpx_im ,&m6800_cpu_device::bsr, &m6800_cpu_device::lds_im, &m6800_cpu_device::sts_im, |
| 91 | &m6800_cpu_device::suba_di,&m6800_cpu_device::cmpa_di,&m6800_cpu_device::sbca_di,&m6800_cpu_device::subd_di,&m6800_cpu_device::anda_di,&m6800_cpu_device::bita_di,&m6800_cpu_device::lda_di, &m6800_cpu_device::sta_di, |
| 92 | &m6800_cpu_device::eora_di,&m6800_cpu_device::adca_di,&m6800_cpu_device::ora_di, &m6800_cpu_device::adda_di,&m6800_cpu_device::cpx_di ,&m6800_cpu_device::jsr_di, &m6800_cpu_device::lds_di, &m6800_cpu_device::sts_di, |
| 93 | &m6800_cpu_device::suba_ix,&m6800_cpu_device::cmpa_ix,&m6800_cpu_device::sbca_ix,&m6800_cpu_device::subd_ix,&m6800_cpu_device::anda_ix,&m6800_cpu_device::bita_ix,&m6800_cpu_device::lda_ix, &m6800_cpu_device::sta_ix, |
| 94 | &m6800_cpu_device::eora_ix,&m6800_cpu_device::adca_ix,&m6800_cpu_device::ora_ix, &m6800_cpu_device::adda_ix,&m6800_cpu_device::cpx_ix ,&m6800_cpu_device::jsr_ix, &m6800_cpu_device::lds_ix, &m6800_cpu_device::sts_ix, |
| 95 | &m6800_cpu_device::suba_ex,&m6800_cpu_device::cmpa_ex,&m6800_cpu_device::sbca_ex,&m6800_cpu_device::subd_ex,&m6800_cpu_device::anda_ex,&m6800_cpu_device::bita_ex,&m6800_cpu_device::lda_ex, &m6800_cpu_device::sta_ex, |
| 96 | &m6800_cpu_device::eora_ex,&m6800_cpu_device::adca_ex,&m6800_cpu_device::ora_ex, &m6800_cpu_device::adda_ex,&m6800_cpu_device::cpx_ex ,&m6800_cpu_device::jsr_ex, &m6800_cpu_device::lds_ex, &m6800_cpu_device::sts_ex, |
| 97 | &m6800_cpu_device::subb_im,&m6800_cpu_device::cmpb_im,&m6800_cpu_device::sbcb_im,&m6800_cpu_device::addd_im,&m6800_cpu_device::andb_im,&m6800_cpu_device::bitb_im,&m6800_cpu_device::ldb_im, &m6800_cpu_device::stb_im, |
| 98 | &m6800_cpu_device::eorb_im,&m6800_cpu_device::adcb_im,&m6800_cpu_device::orb_im, &m6800_cpu_device::addb_im,&m6800_cpu_device::ldd_im, &m6800_cpu_device::std_im, &m6800_cpu_device::ldx_im, &m6800_cpu_device::stx_im, |
| 99 | &m6800_cpu_device::subb_di,&m6800_cpu_device::cmpb_di,&m6800_cpu_device::sbcb_di,&m6800_cpu_device::addd_di,&m6800_cpu_device::andb_di,&m6800_cpu_device::bitb_di,&m6800_cpu_device::ldb_di, &m6800_cpu_device::stb_di, |
| 100 | &m6800_cpu_device::eorb_di,&m6800_cpu_device::adcb_di,&m6800_cpu_device::orb_di, &m6800_cpu_device::addb_di,&m6800_cpu_device::ldd_di, &m6800_cpu_device::std_di, &m6800_cpu_device::ldx_di, &m6800_cpu_device::stx_di, |
| 101 | &m6800_cpu_device::subb_ix,&m6800_cpu_device::cmpb_ix,&m6800_cpu_device::sbcb_ix,&m6800_cpu_device::addd_ix,&m6800_cpu_device::andb_ix,&m6800_cpu_device::bitb_ix,&m6800_cpu_device::ldb_ix, &m6800_cpu_device::stb_ix, |
| 102 | &m6800_cpu_device::eorb_ix,&m6800_cpu_device::adcb_ix,&m6800_cpu_device::orb_ix, &m6800_cpu_device::addb_ix,&m6800_cpu_device::ldd_ix, &m6800_cpu_device::std_ix, &m6800_cpu_device::ldx_ix, &m6800_cpu_device::stx_ix, |
| 103 | &m6800_cpu_device::subb_ex,&m6800_cpu_device::cmpb_ex,&m6800_cpu_device::sbcb_ex,&m6800_cpu_device::addd_ex,&m6800_cpu_device::andb_ex,&m6800_cpu_device::bitb_ex,&m6800_cpu_device::ldb_ex, &m6800_cpu_device::stb_ex, |
| 104 | &m6800_cpu_device::eorb_ex,&m6800_cpu_device::adcb_ex,&m6800_cpu_device::orb_ex, &m6800_cpu_device::addb_ex,&m6800_cpu_device::ldd_ex, &m6800_cpu_device::std_ex, &m6800_cpu_device::ldx_ex, &m6800_cpu_device::stx_ex |
| 105 | }; |
| 106 | |
| 107 | const m6800_cpu_device::op_func m6800_cpu_device::nsc8105_insn[0x100] = { |
| 108 | &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::nop, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::tap, &m6800_cpu_device::illegal,&m6800_cpu_device::tpa, |
| 109 | &m6800_cpu_device::inx, &m6800_cpu_device::clv, &m6800_cpu_device::dex, &m6800_cpu_device::sev, &m6800_cpu_device::clc, &m6800_cpu_device::cli, &m6800_cpu_device::sec, &m6800_cpu_device::sei, |
| 110 | &m6800_cpu_device::sba, &m6800_cpu_device::illegal,&m6800_cpu_device::cba, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::tab, &m6800_cpu_device::illegal,&m6800_cpu_device::tba, |
| 111 | &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::daa, &m6800_cpu_device::aba, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::illegal, |
| 112 | &m6800_cpu_device::bra, &m6800_cpu_device::bhi, &m6800_cpu_device::brn, &m6800_cpu_device::bls, &m6800_cpu_device::bcc, &m6800_cpu_device::bne, &m6800_cpu_device::bcs, &m6800_cpu_device::beq, |
| 113 | &m6800_cpu_device::bvc, &m6800_cpu_device::bpl, &m6800_cpu_device::bvs, &m6800_cpu_device::bmi, &m6800_cpu_device::bge, &m6800_cpu_device::bgt, &m6800_cpu_device::blt, &m6800_cpu_device::ble, |
| 114 | &m6800_cpu_device::tsx, &m6800_cpu_device::pula, &m6800_cpu_device::ins, &m6800_cpu_device::pulb, &m6800_cpu_device::des, &m6800_cpu_device::psha, &m6800_cpu_device::txs, &m6800_cpu_device::pshb, |
| 115 | &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::rts, &m6800_cpu_device::rti, &m6800_cpu_device::illegal,&m6800_cpu_device::wai, &m6800_cpu_device::illegal,&m6800_cpu_device::swi, |
| 116 | &m6800_cpu_device::suba_im,&m6800_cpu_device::sbca_im,&m6800_cpu_device::cmpa_im,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_im,&m6800_cpu_device::lda_im, &m6800_cpu_device::bita_im,&m6800_cpu_device::sta_im, |
| 117 | &m6800_cpu_device::eora_im,&m6800_cpu_device::ora_im, &m6800_cpu_device::adca_im,&m6800_cpu_device::adda_im,&m6800_cpu_device::cmpx_im,&m6800_cpu_device::lds_im, &m6800_cpu_device::bsr, &m6800_cpu_device::sts_im, |
| 118 | &m6800_cpu_device::suba_di,&m6800_cpu_device::sbca_di,&m6800_cpu_device::cmpa_di,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_di,&m6800_cpu_device::lda_di, &m6800_cpu_device::bita_di,&m6800_cpu_device::sta_di, |
| 119 | &m6800_cpu_device::eora_di,&m6800_cpu_device::ora_di, &m6800_cpu_device::adca_di,&m6800_cpu_device::adda_di,&m6800_cpu_device::cmpx_di,&m6800_cpu_device::lds_di, &m6800_cpu_device::jsr_di, &m6800_cpu_device::sts_di, |
| 120 | &m6800_cpu_device::suba_ix,&m6800_cpu_device::sbca_ix,&m6800_cpu_device::cmpa_ix,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_ix,&m6800_cpu_device::lda_ix, &m6800_cpu_device::bita_ix,&m6800_cpu_device::sta_ix, |
| 121 | &m6800_cpu_device::eora_ix,&m6800_cpu_device::ora_ix, &m6800_cpu_device::adca_ix,&m6800_cpu_device::adda_ix,&m6800_cpu_device::cmpx_ix,&m6800_cpu_device::lds_ix, &m6800_cpu_device::jsr_ix, &m6800_cpu_device::sts_ix, |
| 122 | &m6800_cpu_device::suba_ex,&m6800_cpu_device::sbca_ex,&m6800_cpu_device::cmpa_ex,&m6800_cpu_device::illegal,&m6800_cpu_device::anda_ex,&m6800_cpu_device::lda_ex, &m6800_cpu_device::bita_ex,&m6800_cpu_device::sta_ex, |
| 123 | &m6800_cpu_device::eora_ex,&m6800_cpu_device::ora_ex, &m6800_cpu_device::adca_ex,&m6800_cpu_device::adda_ex,&m6800_cpu_device::cmpx_ex,&m6800_cpu_device::lds_ex, &m6800_cpu_device::jsr_ex, &m6800_cpu_device::sts_ex, |
| 124 | &m6800_cpu_device::nega, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::coma, &m6800_cpu_device::lsra, &m6800_cpu_device::rora, &m6800_cpu_device::illegal,&m6800_cpu_device::asra, |
| 125 | &m6800_cpu_device::asla, &m6800_cpu_device::deca, &m6800_cpu_device::rola, &m6800_cpu_device::illegal,&m6800_cpu_device::inca, &m6800_cpu_device::illegal,&m6800_cpu_device::tsta, &m6800_cpu_device::clra, |
| 126 | &m6800_cpu_device::negb, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::comb, &m6800_cpu_device::lsrb, &m6800_cpu_device::rorb, &m6800_cpu_device::illegal,&m6800_cpu_device::asrb, |
| 127 | &m6800_cpu_device::aslb, &m6800_cpu_device::decb, &m6800_cpu_device::rolb, &m6800_cpu_device::illegal,&m6800_cpu_device::incb, &m6800_cpu_device::illegal,&m6800_cpu_device::tstb, &m6800_cpu_device::clrb, |
| 128 | &m6800_cpu_device::neg_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::com_ix, &m6800_cpu_device::lsr_ix, &m6800_cpu_device::ror_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::asr_ix, |
| 129 | &m6800_cpu_device::asl_ix, &m6800_cpu_device::dec_ix, &m6800_cpu_device::rol_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::inc_ix, &m6800_cpu_device::jmp_ix, &m6800_cpu_device::tst_ix, &m6800_cpu_device::clr_ix, |
| 130 | &m6800_cpu_device::neg_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::illegal,&m6800_cpu_device::com_ex, &m6800_cpu_device::lsr_ex, &m6800_cpu_device::ror_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::asr_ex, |
| 131 | &m6800_cpu_device::asl_ex, &m6800_cpu_device::dec_ex, &m6800_cpu_device::rol_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::inc_ex, &m6800_cpu_device::jmp_ex, &m6800_cpu_device::tst_ex, &m6800_cpu_device::clr_ex, |
| 132 | &m6800_cpu_device::subb_im,&m6800_cpu_device::sbcb_im,&m6800_cpu_device::cmpb_im,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_im,&m6800_cpu_device::ldb_im, &m6800_cpu_device::bitb_im,&m6800_cpu_device::stb_im, |
| 133 | &m6800_cpu_device::eorb_im,&m6800_cpu_device::orb_im, &m6800_cpu_device::adcb_im,&m6800_cpu_device::addb_im,&m6800_cpu_device::illegal,&m6800_cpu_device::ldx_im, &m6800_cpu_device::illegal,&m6800_cpu_device::stx_im, |
| 134 | &m6800_cpu_device::subb_di,&m6800_cpu_device::sbcb_di,&m6800_cpu_device::cmpb_di,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_di,&m6800_cpu_device::ldb_di, &m6800_cpu_device::bitb_di,&m6800_cpu_device::stb_di, |
| 135 | &m6800_cpu_device::eorb_di,&m6800_cpu_device::orb_di, &m6800_cpu_device::adcb_di,&m6800_cpu_device::addb_di,&m6800_cpu_device::illegal,&m6800_cpu_device::ldx_di, &m6800_cpu_device::illegal,&m6800_cpu_device::stx_di, |
| 136 | &m6800_cpu_device::subb_ix,&m6800_cpu_device::sbcb_ix,&m6800_cpu_device::cmpb_ix,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_ix,&m6800_cpu_device::ldb_ix, &m6800_cpu_device::bitb_ix,&m6800_cpu_device::stb_ix, |
| 137 | &m6800_cpu_device::eorb_ix,&m6800_cpu_device::orb_ix, &m6800_cpu_device::adcb_ix,&m6800_cpu_device::addb_ix,&m6800_cpu_device::adcx_im,&m6800_cpu_device::ldx_ix, &m6800_cpu_device::illegal,&m6800_cpu_device::stx_ix, |
| 138 | &m6800_cpu_device::subb_ex,&m6800_cpu_device::sbcb_ex,&m6800_cpu_device::cmpb_ex,&m6800_cpu_device::illegal,&m6800_cpu_device::andb_ex,&m6800_cpu_device::ldb_ex, &m6800_cpu_device::bitb_ex,&m6800_cpu_device::stb_ex, |
| 139 | &m6800_cpu_device::eorb_ex,&m6800_cpu_device::orb_ex, &m6800_cpu_device::adcb_ex,&m6800_cpu_device::addb_ex,&m6800_cpu_device::addx_ex,&m6800_cpu_device::ldx_ex, &m6800_cpu_device::illegal,&m6800_cpu_device::stx_ex |
| 140 | }; |
trunk/src/emu/cpu/dsp56k/dsp56ops.c
| r28738 | r28739 | |
| 1 | | /*************************************************************************** |
| 2 | | |
| 3 | | dsp56ops.c |
| 4 | | Core implementation for the portable Motorola/Freescale DSP56k emulator. |
| 5 | | Written by Andrew Gardner |
| 6 | | |
| 7 | | ***************************************************************************/ |
| 8 | | |
| 9 | | /* NOTES For register setting: |
| 10 | | FM.3-4 : When A2 or B2 is read, the register contents occupy the low-order portion |
| 11 | | (bits 7-0) of the word; the high-order portion (bits 16-8) is sign-extended. When A2 or B2 |
| 12 | | is written, the register receives the low-order portion of the word; the high-order portion is not used |
| 13 | | : ...much more! |
| 14 | | : ...shifter/limiter/overflow notes too. |
| 15 | | |
| 16 | | */ |
| 17 | | |
| 18 | | /* |
| 19 | | TODO: |
| 20 | | - 0x01ee: should this move sign extend? otherwise the test-against-minus means nothing. |
| 21 | | - Restore only the proper bits upon loop termination! |
| 22 | | - BFCLR has some errata in the docs that may need to be applied. |
| 23 | | */ |
| 24 | | |
| 25 | | /************************/ |
| 26 | | /* Datatypes and macros */ |
| 27 | | /************************/ |
| 28 | | enum addSubOpType { OP_ADD, |
| 29 | | OP_SUB, |
| 30 | | OP_OTHER }; |
| 31 | | |
| 32 | | enum dataType { DT_BYTE, |
| 33 | | DT_WORD, |
| 34 | | DT_DOUBLE_WORD, |
| 35 | | DT_LONG_WORD }; |
| 36 | | |
| 37 | | struct typed_pointer |
| 38 | | { |
| 39 | | void* addr; |
| 40 | | char data_type; |
| 41 | | }; |
| 42 | | |
| 43 | | //#define ADDRESS(X) (X<<1) |
| 44 | | #define BITS(CUR,MASK) (Dsp56kOpMask(CUR,MASK)) |
| 45 | | |
| 46 | | /*********************/ |
| 47 | | /* Opcode prototypes */ |
| 48 | | /*********************/ |
| 49 | | static size_t dsp56k_op_addsub_2 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 50 | | static size_t dsp56k_op_mac_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 51 | | static size_t dsp56k_op_macr_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 52 | | static size_t dsp56k_op_move_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 53 | | static size_t dsp56k_op_mpy_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 54 | | static size_t dsp56k_op_mpyr_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 55 | | static size_t dsp56k_op_tfr_2 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 56 | | static size_t dsp56k_op_mpy_2 (dsp56k_core* cpustate, const UINT16 op_byte, UINT8* cycles); |
| 57 | | static size_t dsp56k_op_mac_2 (dsp56k_core* cpustate, const UINT16 op_byte, UINT8* cycles); |
| 58 | | static size_t dsp56k_op_clr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 59 | | static size_t dsp56k_op_add (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 60 | | static size_t dsp56k_op_move (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 61 | | static size_t dsp56k_op_tfr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 62 | | static size_t dsp56k_op_rnd (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 63 | | static size_t dsp56k_op_tst (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 64 | | static size_t dsp56k_op_inc (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 65 | | static size_t dsp56k_op_inc24 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 66 | | static size_t dsp56k_op_or (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 67 | | static size_t dsp56k_op_asr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 68 | | static size_t dsp56k_op_asl (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 69 | | static size_t dsp56k_op_lsr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 70 | | static size_t dsp56k_op_lsl (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 71 | | static size_t dsp56k_op_eor (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 72 | | static size_t dsp56k_op_subl (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 73 | | static size_t dsp56k_op_sub (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 74 | | static size_t dsp56k_op_clr24 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 75 | | static size_t dsp56k_op_sbc (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 76 | | static size_t dsp56k_op_cmp (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 77 | | static size_t dsp56k_op_neg (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 78 | | static size_t dsp56k_op_not (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 79 | | static size_t dsp56k_op_dec (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 80 | | static size_t dsp56k_op_dec24 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 81 | | static size_t dsp56k_op_and (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 82 | | static size_t dsp56k_op_abs (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 83 | | static size_t dsp56k_op_ror (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 84 | | static size_t dsp56k_op_rol (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 85 | | static size_t dsp56k_op_cmpm (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 86 | | static size_t dsp56k_op_mpy (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 87 | | static size_t dsp56k_op_mpyr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 88 | | static size_t dsp56k_op_mac (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 89 | | static size_t dsp56k_op_macr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 90 | | static size_t dsp56k_op_adc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 91 | | static size_t dsp56k_op_andi (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 92 | | static size_t dsp56k_op_asl4 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 93 | | static size_t dsp56k_op_asr4 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 94 | | static size_t dsp56k_op_asr16 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 95 | | static size_t dsp56k_op_bfop (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 96 | | static size_t dsp56k_op_bfop_1 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 97 | | static size_t dsp56k_op_bfop_2 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 98 | | static size_t dsp56k_op_bcc (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 99 | | static size_t dsp56k_op_bcc_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 100 | | static size_t dsp56k_op_bcc_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 101 | | static size_t dsp56k_op_bra (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 102 | | static size_t dsp56k_op_bra_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 103 | | static size_t dsp56k_op_bra_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 104 | | static size_t dsp56k_op_brkcc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 105 | | static size_t dsp56k_op_bscc (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 106 | | static size_t dsp56k_op_bscc_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 107 | | static size_t dsp56k_op_bsr (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 108 | | static size_t dsp56k_op_bsr_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 109 | | static size_t dsp56k_op_chkaau (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 110 | | static size_t dsp56k_op_debug (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 111 | | static size_t dsp56k_op_debugcc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 112 | | static size_t dsp56k_op_div (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 113 | | static size_t dsp56k_op_dmac (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 114 | | static size_t dsp56k_op_do (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 115 | | static size_t dsp56k_op_do_1 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 116 | | static size_t dsp56k_op_do_2 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 117 | | static size_t dsp56k_op_doforever(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 118 | | static size_t dsp56k_op_enddo (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 119 | | static size_t dsp56k_op_ext (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 120 | | static size_t dsp56k_op_illegal (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 121 | | static size_t dsp56k_op_imac (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 122 | | static size_t dsp56k_op_impy (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 123 | | static size_t dsp56k_op_jcc (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 124 | | static size_t dsp56k_op_jcc_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 125 | | static size_t dsp56k_op_jmp (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 126 | | static size_t dsp56k_op_jmp_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 127 | | static size_t dsp56k_op_jscc (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 128 | | static size_t dsp56k_op_jscc_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 129 | | static size_t dsp56k_op_jsr (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 130 | | static size_t dsp56k_op_jsr_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 131 | | static size_t dsp56k_op_jsr_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 132 | | static size_t dsp56k_op_lea (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 133 | | static size_t dsp56k_op_lea_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 134 | | static size_t dsp56k_op_macsuuu (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 135 | | static size_t dsp56k_op_move_2 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 136 | | static size_t dsp56k_op_movec (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 137 | | static size_t dsp56k_op_movec_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 138 | | static size_t dsp56k_op_movec_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 139 | | static size_t dsp56k_op_movec_3 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 140 | | static size_t dsp56k_op_movec_4 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 141 | | static size_t dsp56k_op_movec_5 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 142 | | static size_t dsp56k_op_movei (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 143 | | static size_t dsp56k_op_movem (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 144 | | static size_t dsp56k_op_movem_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 145 | | static size_t dsp56k_op_movem_2 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 146 | | static size_t dsp56k_op_movep (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 147 | | static size_t dsp56k_op_movep_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 148 | | static size_t dsp56k_op_moves (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 149 | | static size_t dsp56k_op_mpysuuu (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 150 | | static size_t dsp56k_op_negc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 151 | | static size_t dsp56k_op_nop (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 152 | | static size_t dsp56k_op_norm (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 153 | | static size_t dsp56k_op_ori (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 154 | | static size_t dsp56k_op_rep (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 155 | | static size_t dsp56k_op_rep_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 156 | | static size_t dsp56k_op_rep_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 157 | | static size_t dsp56k_op_repcc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 158 | | static size_t dsp56k_op_reset (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 159 | | static size_t dsp56k_op_rti (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 160 | | static size_t dsp56k_op_rts (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 161 | | static size_t dsp56k_op_stop (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 162 | | static size_t dsp56k_op_swap (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 163 | | static size_t dsp56k_op_swi (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 164 | | static size_t dsp56k_op_tcc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 165 | | static size_t dsp56k_op_tfr2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 166 | | static size_t dsp56k_op_tfr3 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 167 | | static size_t dsp56k_op_tst2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 168 | | static size_t dsp56k_op_wait (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 169 | | static size_t dsp56k_op_zero (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 170 | | |
| 171 | | |
| 172 | | static void execute_register_to_register_data_move(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value); |
| 173 | | static void execute_address_register_update(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value); |
| 174 | | static void execute_x_memory_data_move (dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value); |
| 175 | | static void execute_x_memory_data_move2(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register); |
| 176 | | static void execute_dual_x_memory_data_read(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register); |
| 177 | | static void execute_x_memory_data_move_with_short_displacement(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2); |
| 178 | | |
| 179 | | static UINT16 decode_BBB_bitmask(dsp56k_core* cpustate, UINT16 BBB, UINT16 *iVal); |
| 180 | | static int decode_cccc_table(dsp56k_core* cpustate, UINT16 cccc); |
| 181 | | static void decode_DDDDD_table(dsp56k_core* cpustate, UINT16 DDDDD, typed_pointer* ret); |
| 182 | | static void decode_DD_table(dsp56k_core* cpustate, UINT16 DD, typed_pointer* ret); |
| 183 | | static void decode_DDF_table(dsp56k_core* cpustate, UINT16 DD, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret); |
| 184 | | static void decode_F_table(dsp56k_core* cpustate, UINT16 F, typed_pointer* ret); |
| 185 | | static void decode_h0hF_table(dsp56k_core* cpustate, UINT16 h0h, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret); |
| 186 | | static void decode_HH_table(dsp56k_core* cpustate, UINT16 HH, typed_pointer* ret); |
| 187 | | static void decode_HHH_table(dsp56k_core* cpustate, UINT16 HHH, typed_pointer* ret); |
| 188 | | static void decode_IIII_table(dsp56k_core* cpustate, UINT16 IIII, typed_pointer* src_ret, typed_pointer* dst_ret, void* working); |
| 189 | | static void decode_JJJF_table(dsp56k_core* cpustate, UINT16 JJJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret); |
| 190 | | static void decode_JJF_table(dsp56k_core* cpustate, UINT16 JJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret); |
| 191 | | static void decode_JF_table(dsp56k_core* cpustate, UINT16 JJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret); |
| 192 | | static void decode_KKK_table(dsp56k_core* cpustate, UINT16 KKK, typed_pointer* dst_ret1, typed_pointer* dst_ret2, void* working); |
| 193 | | static void decode_QQF_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D); |
| 194 | | static void decode_QQF_special_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D); |
| 195 | | static void decode_QQQF_table(dsp56k_core* cpustate, UINT16 QQQ, UINT16 F, void **S1, void **S2, void **D); |
| 196 | | static void decode_RR_table(dsp56k_core* cpustate, UINT16 RR, typed_pointer* ret); |
| 197 | | static void decode_TT_table(dsp56k_core* cpustate, UINT16 TT, typed_pointer* ret); |
| 198 | | static void decode_uuuuF_table(dsp56k_core* cpustate, UINT16 uuuu, UINT16 F, UINT8 add_sub_other, typed_pointer* src_ret, typed_pointer* dst_ret); |
| 199 | | static void decode_Z_table(dsp56k_core* cpustate, UINT16 Z, typed_pointer* ret); |
| 200 | | |
| 201 | | static void execute_m_table(dsp56k_core* cpustate, int x, UINT16 m); |
| 202 | | static void execute_mm_table(dsp56k_core* cpustate, UINT16 rnum, UINT16 mm); |
| 203 | | static void execute_MM_table(dsp56k_core* cpustate, UINT16 rnum, UINT16 MM); |
| 204 | | static UINT16 execute_q_table(dsp56k_core* cpustate, int RR, UINT16 q); |
| 205 | | static void execute_z_table(dsp56k_core* cpustate, int RR, UINT16 z); |
| 206 | | |
| 207 | | static UINT16 assemble_address_from_Pppppp_table(dsp56k_core* cpustate, UINT16 P, UINT16 ppppp); |
| 208 | | static UINT16 assemble_address_from_IO_short_address(dsp56k_core* cpustate, UINT16 pp); |
| 209 | | static UINT16 assemble_address_from_6bit_signed_relative_short_address(dsp56k_core* cpustate, UINT16 srs); |
| 210 | | |
| 211 | | static void dsp56k_process_loop(dsp56k_core* cpustate); |
| 212 | | static void dsp56k_process_rep(dsp56k_core* cpustate, size_t repSize); |
| 213 | | |
| 214 | | |
| 215 | | |
| 216 | | /********************/ |
| 217 | | /* Helper Functions */ |
| 218 | | /********************/ |
| 219 | | static UINT16 Dsp56kOpMask(UINT16 op, UINT16 mask); |
| 220 | | |
| 221 | | /* These arguments are written source->destination to fall in line with the processor's paradigm. */ |
| 222 | | static void SetDestinationValue(typed_pointer source, typed_pointer dest); |
| 223 | | |
| 224 | | static void SetDataMemoryValue(dsp56k_core* cpustate, typed_pointer source, UINT32 destinationAddr); |
| 225 | | static void SetProgramMemoryValue(dsp56k_core* cpustate, typed_pointer source, UINT32 destinationAddr); |
| 226 | | |
| 227 | | |
| 228 | | |
| 229 | | /*************************************************************************** |
| 230 | | IMPLEMENTATION |
| 231 | | ***************************************************************************/ |
| 232 | | |
| 233 | | static void execute_one(dsp56k_core* cpustate) |
| 234 | | { |
| 235 | | UINT16 op; |
| 236 | | UINT16 op2; |
| 237 | | size_t size = 0x1337; |
| 238 | | UINT8 cycle_count = 0; |
| 239 | | |
| 240 | | /* For MAME */ |
| 241 | | cpustate->op = ROPCODE(ADDRESS(PC)); |
| 242 | | debugger_instruction_hook(cpustate->device, PC); |
| 243 | | |
| 244 | | /* The words we're going to be working with */ |
| 245 | | op = ROPCODE(ADDRESS(PC)); |
| 246 | | op2 = ROPCODE(ADDRESS(PC) + ADDRESS(1)); |
| 247 | | |
| 248 | | |
| 249 | | /* DECODE */ |
| 250 | | /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/ |
| 251 | | if ((op & 0xe000) == 0x6000) |
| 252 | | { |
| 253 | | typed_pointer d_register = {NULL, DT_BYTE}; |
| 254 | | |
| 255 | | /* Quote: (MOVE, MAC(R), MPY(R), ADD, SUB, TFR) */ |
| 256 | | UINT16 op_byte = op & 0x00ff; |
| 257 | | |
| 258 | | /* ADD : 011m mKKK 0rru Fuuu : A-22 */ |
| 259 | | /* SUB : 011m mKKK 0rru Fuuu : A-202 */ |
| 260 | | /* Note: 0x0094 check allows command to drop through to MOVE and TFR */ |
| 261 | | if (((op & 0xe080) == 0x6000) && ((op & 0x0094) != 0x0010)) |
| 262 | | { |
| 263 | | size = dsp56k_op_addsub_2(cpustate, op_byte, &d_register, &cycle_count); |
| 264 | | } |
| 265 | | /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */ |
| 266 | | else if ((op & 0xe094) == 0x6084) |
| 267 | | { |
| 268 | | size = dsp56k_op_mac_1(cpustate, op_byte, &d_register, &cycle_count); |
| 269 | | } |
| 270 | | /* MACR: 011m mKKK 1--1 F1QQ : A-124 */ |
| 271 | | else if ((op & 0xe094) == 0x6094) |
| 272 | | { |
| 273 | | size = dsp56k_op_macr_1(cpustate, op_byte, &d_register, &cycle_count); |
| 274 | | } |
| 275 | | /* TFR : 011m mKKK 0rr1 F0DD : A-212 */ |
| 276 | | else if ((op & 0xe094) == 0x6010) |
| 277 | | { |
| 278 | | size = dsp56k_op_tfr_2(cpustate, op_byte, &d_register, &cycle_count); |
| 279 | | } |
| 280 | | /* MOVE : 011m mKKK 0rr1 0000 : A-128 */ |
| 281 | | else if ((op & 0xe09f) == 0x6010) |
| 282 | | { |
| 283 | | /* Note: The opcode encoding : 011x xxxx 0xx1 0000 (move + double memory read) |
| 284 | | is .identical. to (tfr X0,A + two parallel reads). This sparks the notion |
| 285 | | that these 'move' opcodes don't actually exist and are just there as |
| 286 | | documentation. Real-world examples would need to be examined to come |
| 287 | | to a satisfactory conclusion, but as it stands, tfr will override this |
| 288 | | move operation. */ |
| 289 | | size = dsp56k_op_move_1(cpustate, op_byte, &d_register, &cycle_count); |
| 290 | | } |
| 291 | | /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */ |
| 292 | | else if ((op & 0xe094) == 0x6080) |
| 293 | | { |
| 294 | | size = dsp56k_op_mpy_1(cpustate, op_byte, &d_register, &cycle_count); |
| 295 | | } |
| 296 | | /* MPYR : 011m mKKK 1--1 F0QQ : A-162 */ |
| 297 | | else if ((op & 0xe094) == 0x6090) |
| 298 | | { |
| 299 | | size = dsp56k_op_mpyr_1(cpustate, op_byte, &d_register, &cycle_count); |
| 300 | | } |
| 301 | | |
| 302 | | /* Now evaluate the parallel data move */ |
| 303 | | execute_dual_x_memory_data_read(cpustate, op, &d_register); |
| 304 | | } |
| 305 | | /* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */ |
| 306 | | else if ((op & 0xfe00) == 0x1600) |
| 307 | | { |
| 308 | | /* Quote: (MPY or MAC) */ |
| 309 | | UINT16 op_byte = op & 0x00ff; |
| 310 | | |
| 311 | | /* MPY : 0001 0110 RRDD FQQQ : A-160 */ |
| 312 | | if ((op & 0xff00) == 0x1600) |
| 313 | | { |
| 314 | | size = dsp56k_op_mpy_2(cpustate, op_byte, &cycle_count); |
| 315 | | } |
| 316 | | /* MAC : 0001 0111 RRDD FQQQ : A-122 */ |
| 317 | | else if ((op & 0xff00) == 0x1700) |
| 318 | | { |
| 319 | | size = dsp56k_op_mac_2(cpustate, op_byte, &cycle_count); |
| 320 | | } |
| 321 | | |
| 322 | | /* Now evaluate the parallel data move */ |
| 323 | | /* TODO // decode_x_memory_data_write_and_register_data_move(op, parallel_move_str, parallel_move_str2); */ |
| 324 | | logerror("DSP56k: Unemulated Dual X Memory Data And Register Data Move @ 0x%x\n", PC); |
| 325 | | } |
| 326 | | |
| 327 | | /* Handle Other parallel types */ |
| 328 | | else |
| 329 | | { |
| 330 | | /***************************************/ |
| 331 | | /* 32 General parallel move operations */ |
| 332 | | /***************************************/ |
| 333 | | |
| 334 | | enum pType { kNoParallelDataMove, |
| 335 | | kRegisterToRegister, |
| 336 | | kAddressRegister, |
| 337 | | kXMemoryDataMove, |
| 338 | | kXMemoryDataMove2, |
| 339 | | kXMemoryDataMoveWithDisp }; |
| 340 | | |
| 341 | | int parallelType = -1; |
| 342 | | UINT16 op_byte = 0x0000; |
| 343 | | typed_pointer d_register = {NULL, DT_BYTE}; |
| 344 | | UINT64 prev_accum_value = U64(0x0000000000000000); |
| 345 | | |
| 346 | | /* Note: it's important that NPDM comes before RtRDM here */ |
| 347 | | /* No Parallel Data Move : 0100 1010 .... .... : A-131 */ |
| 348 | | if ((op & 0xff00) == 0x4a00) |
| 349 | | { |
| 350 | | op_byte = op & 0x00ff; |
| 351 | | parallelType = kNoParallelDataMove; |
| 352 | | } |
| 353 | | /* Register to Register Data Move : 0100 IIII .... .... : A-133 */ |
| 354 | | else if ((op & 0xf000) == 0x4000) |
| 355 | | { |
| 356 | | op_byte = op & 0x00ff; |
| 357 | | parallelType = kRegisterToRegister; |
| 358 | | } |
| 359 | | /* Address Register Update : 0011 0zRR .... .... : A-135 */ |
| 360 | | else if ((op & 0xf800) == 0x3000) |
| 361 | | { |
| 362 | | op_byte = op & 0x00ff; |
| 363 | | parallelType = kAddressRegister; |
| 364 | | } |
| 365 | | /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */ |
| 366 | | else if ((op & 0x8000) == 0x8000) |
| 367 | | { |
| 368 | | op_byte = op & 0x00ff; |
| 369 | | parallelType = kXMemoryDataMove; |
| 370 | | } |
| 371 | | /* X Memory Data Move : 0101 HHHW .... .... : A-137 */ |
| 372 | | else if ((op & 0xf000) == 0x5000) |
| 373 | | { |
| 374 | | op_byte = op & 0x00ff; |
| 375 | | parallelType = kXMemoryDataMove2; |
| 376 | | } |
| 377 | | /* X Memory Data Move with short displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */ |
| 378 | | else if ((op & 0xff00) == 0x0500) |
| 379 | | { |
| 380 | | /* Now check it against all the other potential collisions */ |
| 381 | | /* This is necessary because "don't care bits" get in the way. */ |
| 382 | | /* |
| 383 | | MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 |
| 384 | | MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 |
| 385 | | MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 |
| 386 | | */ |
| 387 | | if (((op2 & 0xfe20) != 0x0200) && |
| 388 | | ((op2 & 0xf810) != 0x3800) && |
| 389 | | ((op2 & 0x00ff) != 0x0011)) |
| 390 | | { |
| 391 | | op_byte = op2 & 0x00ff; |
| 392 | | parallelType = kXMemoryDataMoveWithDisp; |
| 393 | | } |
| 394 | | } |
| 395 | | |
| 396 | | |
| 397 | | if (parallelType != -1) |
| 398 | | { |
| 399 | | /* Note: There is much overlap between opcodes down here */ |
| 400 | | /* To this end, certain ops must come before others in the list */ |
| 401 | | |
| 402 | | /* CLR : .... .... 0000 F001 : A-60 */ |
| 403 | | if ((op_byte & 0x00f7) == 0x0001) |
| 404 | | { |
| 405 | | size = dsp56k_op_clr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 406 | | } |
| 407 | | /* ADD : .... .... 0000 FJJJ : A-22 */ |
| 408 | | else if ((op_byte & 0x00f0) == 0x0000) |
| 409 | | { |
| 410 | | size = dsp56k_op_add(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 411 | | } |
| 412 | | |
| 413 | | |
| 414 | | /* MOVE : .... .... 0001 0001 : A-128 */ |
| 415 | | else if ((op_byte & 0x00ff) == 0x0011) |
| 416 | | { |
| 417 | | size = dsp56k_op_move(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 418 | | } |
| 419 | | /* TFR : .... .... 0001 FJJJ : A-212 */ |
| 420 | | else if ((op_byte & 0x00f0) == 0x0010) |
| 421 | | { |
| 422 | | size = dsp56k_op_tfr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 423 | | } |
| 424 | | |
| 425 | | |
| 426 | | /* RND : .... .... 0010 F000 : A-188 */ |
| 427 | | else if ((op_byte & 0x00f7) == 0x0020) |
| 428 | | { |
| 429 | | size = dsp56k_op_rnd(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 430 | | } |
| 431 | | /* TST : .... .... 0010 F001 : A-218 */ |
| 432 | | else if ((op_byte & 0x00f7) == 0x0021) |
| 433 | | { |
| 434 | | size = dsp56k_op_tst(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 435 | | } |
| 436 | | /* INC : .... .... 0010 F010 : A-104 */ |
| 437 | | else if ((op_byte & 0x00f7) == 0x0022) |
| 438 | | { |
| 439 | | size = dsp56k_op_inc(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 440 | | } |
| 441 | | /* INC24 : .... .... 0010 F011 : A-106 */ |
| 442 | | else if ((op_byte & 0x00f7) == 0x0023) |
| 443 | | { |
| 444 | | size = dsp56k_op_inc24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 445 | | } |
| 446 | | /* OR : .... .... 0010 F1JJ : A-176 */ |
| 447 | | else if ((op_byte & 0x00f4) == 0x0024) |
| 448 | | { |
| 449 | | size = dsp56k_op_or(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 450 | | } |
| 451 | | |
| 452 | | |
| 453 | | /* ASR : .... .... 0011 F000 : A-32 */ |
| 454 | | else if ((op_byte & 0x00f7) == 0x0030) |
| 455 | | { |
| 456 | | size = dsp56k_op_asr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 457 | | } |
| 458 | | /* ASL : .... .... 0011 F001 : A-28 */ |
| 459 | | else if ((op_byte & 0x00f7) == 0x0031) |
| 460 | | { |
| 461 | | size = dsp56k_op_asl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 462 | | } |
| 463 | | /* LSR : .... .... 0011 F010 : A-120 */ |
| 464 | | else if ((op_byte & 0x00f7) == 0x0032) |
| 465 | | { |
| 466 | | size = dsp56k_op_lsr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 467 | | } |
| 468 | | /* LSL : .... .... 0011 F011 : A-118 */ |
| 469 | | else if ((op_byte & 0x00f7) == 0x0033) |
| 470 | | { |
| 471 | | size = dsp56k_op_lsl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 472 | | } |
| 473 | | /* EOR : .... .... 0011 F1JJ : A-94 */ |
| 474 | | else if ((op_byte & 0x00f4) == 0x0034) |
| 475 | | { |
| 476 | | size = dsp56k_op_eor(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 477 | | } |
| 478 | | |
| 479 | | |
| 480 | | /* SUBL : .... .... 0100 F001 : A-204 */ |
| 481 | | else if ((op_byte & 0x00f7) == 0x0041) |
| 482 | | { |
| 483 | | size = dsp56k_op_subl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 484 | | } |
| 485 | | /* SUB : .... .... 0100 FJJJ : A-202 */ |
| 486 | | else if ((op_byte & 0x00f0) == 0x0040) |
| 487 | | { |
| 488 | | size = dsp56k_op_sub(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 489 | | } |
| 490 | | |
| 491 | | |
| 492 | | /* CLR24 : .... .... 0101 F001 : A-62 */ |
| 493 | | else if ((op_byte & 0x00f7) == 0x0051) |
| 494 | | { |
| 495 | | size = dsp56k_op_clr24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 496 | | } |
| 497 | | /* SBC : .... .... 0101 F01J : A-198 */ |
| 498 | | else if ((op_byte & 0x00f6) == 0x0052) |
| 499 | | { |
| 500 | | size = dsp56k_op_sbc(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 501 | | } |
| 502 | | /* CMP : .... .... 0101 FJJJ : A-64 */ |
| 503 | | else if ((op_byte & 0x00f0) == 0x0050) |
| 504 | | { |
| 505 | | size = dsp56k_op_cmp(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 506 | | } |
| 507 | | |
| 508 | | |
| 509 | | /* NEG : .... .... 0110 F000 : A-166 */ |
| 510 | | else if ((op_byte & 0x00f7) == 0x0060) |
| 511 | | { |
| 512 | | size = dsp56k_op_neg(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 513 | | } |
| 514 | | /* NOT : .... .... 0110 F001 : A-174 */ |
| 515 | | else if ((op_byte & 0x00f7) == 0x0061) |
| 516 | | { |
| 517 | | size = dsp56k_op_not(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 518 | | } |
| 519 | | /* DEC : .... .... 0110 F010 : A-72 */ |
| 520 | | else if ((op_byte & 0x00f7) == 0x0062) |
| 521 | | { |
| 522 | | size = dsp56k_op_dec(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 523 | | } |
| 524 | | /* DEC24 : .... .... 0110 F011 : A-74 */ |
| 525 | | else if ((op_byte & 0x00f7) == 0x0063) |
| 526 | | { |
| 527 | | size = dsp56k_op_dec24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 528 | | } |
| 529 | | /* AND : .... .... 0110 F1JJ : A-24 */ |
| 530 | | else if ((op_byte & 0x00f4) == 0x0064) |
| 531 | | { |
| 532 | | size = dsp56k_op_and(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 533 | | } |
| 534 | | |
| 535 | | |
| 536 | | /* ABS : .... .... 0111 F001 : A-18 */ |
| 537 | | if ((op_byte & 0x00f7) == 0x0071) |
| 538 | | { |
| 539 | | size = dsp56k_op_abs(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 540 | | } |
| 541 | | /* ROR : .... .... 0111 F010 : A-192 */ |
| 542 | | else if ((op_byte & 0x00f7) == 0x0072) |
| 543 | | { |
| 544 | | size = dsp56k_op_ror(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 545 | | } |
| 546 | | /* ROL : .... .... 0111 F011 : A-190 */ |
| 547 | | else if ((op_byte & 0x00f7) == 0x0073) |
| 548 | | { |
| 549 | | size = dsp56k_op_rol(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 550 | | } |
| 551 | | /* CMPM : .... .... 0111 FJJJ : A-66 */ |
| 552 | | else if ((op_byte & 0x00f0) == 0x0070) |
| 553 | | { |
| 554 | | size = dsp56k_op_cmpm(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 555 | | } |
| 556 | | |
| 557 | | |
| 558 | | /* MPY : .... .... 1k00 FQQQ : A-160 -- CONFIRMED TYPO IN DOCS (HHHH vs HHHW) */ |
| 559 | | else if ((op_byte & 0x00b0) == 0x0080) |
| 560 | | { |
| 561 | | size = dsp56k_op_mpy(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 562 | | } |
| 563 | | /* MPYR : .... .... 1k01 FQQQ : A-162 */ |
| 564 | | else if ((op_byte & 0x00b0) == 0x0090) |
| 565 | | { |
| 566 | | size = dsp56k_op_mpyr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 567 | | } |
| 568 | | /* MAC : .... .... 1k10 FQQQ : A-122 */ |
| 569 | | else if ((op_byte & 0x00b0) == 0x00a0) |
| 570 | | { |
| 571 | | size = dsp56k_op_mac(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 572 | | } |
| 573 | | /* MACR : .... .... 1k11 FQQQ : A-124 -- DRAMA - rr vs xx (805) */ |
| 574 | | else if ((op_byte & 0x00b0) == 0x00b0) |
| 575 | | { |
| 576 | | size = dsp56k_op_macr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 577 | | } |
| 578 | | |
| 579 | | |
| 580 | | /* Now evaluate the parallel data move */ |
| 581 | | switch (parallelType) |
| 582 | | { |
| 583 | | case kNoParallelDataMove: |
| 584 | | /* DO NOTHING */ |
| 585 | | break; |
| 586 | | case kRegisterToRegister: |
| 587 | | execute_register_to_register_data_move(cpustate, op, &d_register, &prev_accum_value); |
| 588 | | break; |
| 589 | | case kAddressRegister: |
| 590 | | execute_address_register_update(cpustate, op, &d_register, &prev_accum_value); |
| 591 | | break; |
| 592 | | case kXMemoryDataMove: |
| 593 | | execute_x_memory_data_move(cpustate, op, &d_register, &prev_accum_value); |
| 594 | | break; |
| 595 | | case kXMemoryDataMove2: |
| 596 | | execute_x_memory_data_move2(cpustate, op, &d_register); |
| 597 | | break; |
| 598 | | case kXMemoryDataMoveWithDisp: |
| 599 | | execute_x_memory_data_move_with_short_displacement(cpustate, op, op2); |
| 600 | | size = 2; |
| 601 | | break; |
| 602 | | } |
| 603 | | } |
| 604 | | } |
| 605 | | |
| 606 | | /* Drop out if you've already completed your work. */ |
| 607 | | if (size != 0x1337) |
| 608 | | { |
| 609 | | PC += size; |
| 610 | | |
| 611 | | dsp56k_process_loop(cpustate); |
| 612 | | dsp56k_process_rep(cpustate, size); |
| 613 | | |
| 614 | | cpustate->icount -= 4; /* Temporarily hard-coded at 4 clocks per opcode */ /* cycle_count */ |
| 615 | | return; |
| 616 | | } |
| 617 | | |
| 618 | | |
| 619 | | /******************************/ |
| 620 | | /* Remaining non-parallel ops */ |
| 621 | | /******************************/ |
| 622 | | |
| 623 | | /* ADC : 0001 0101 0000 F01J : A-20 */ |
| 624 | | if ((op & 0xfff6) == 0x1502) |
| 625 | | { |
| 626 | | size = dsp56k_op_adc(cpustate, op, &cycle_count); |
| 627 | | } |
| 628 | | /* ANDI : 0001 1EE0 iiii iiii : A-26 */ |
| 629 | | /* (MoveP sneaks in here if you don't check 0x0600) */ |
| 630 | | else if (((op & 0xf900) == 0x1800) & ((op & 0x0600) != 0x0000)) |
| 631 | | { |
| 632 | | size = dsp56k_op_andi(cpustate, op, &cycle_count); |
| 633 | | } |
| 634 | | /* ASL4 : 0001 0101 0011 F001 : A-30 */ |
| 635 | | else if ((op & 0xfff7) == 0x1531) |
| 636 | | { |
| 637 | | size = dsp56k_op_asl4(cpustate, op, &cycle_count); |
| 638 | | } |
| 639 | | /* ASR4 : 0001 0101 0011 F000 : A-34 */ |
| 640 | | else if ((op & 0xfff7) == 0x1530) |
| 641 | | { |
| 642 | | size = dsp56k_op_asr4(cpustate, op, &cycle_count); |
| 643 | | } |
| 644 | | /* ASR16 : 0001 0101 0111 F000 : A-36 */ |
| 645 | | else if ((op & 0xfff7) == 0x1570) |
| 646 | | { |
| 647 | | size = dsp56k_op_asr16(cpustate, op, &cycle_count); |
| 648 | | } |
| 649 | | /* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */ |
| 650 | | else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x1200)) |
| 651 | | { |
| 652 | | size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count); |
| 653 | | } |
| 654 | | /* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */ |
| 655 | | else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x1200)) |
| 656 | | { |
| 657 | | size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count); |
| 658 | | } |
| 659 | | /* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */ |
| 660 | | else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x1200)) |
| 661 | | { |
| 662 | | size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count); |
| 663 | | } |
| 664 | | /* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */ |
| 665 | | else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x0400)) |
| 666 | | { |
| 667 | | size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count); |
| 668 | | } |
| 669 | | /* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */ |
| 670 | | else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x0400)) |
| 671 | | { |
| 672 | | size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count); |
| 673 | | } |
| 674 | | /* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */ |
| 675 | | else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x0400)) |
| 676 | | { |
| 677 | | size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count); |
| 678 | | } |
| 679 | | /* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */ |
| 680 | | else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x1800)) |
| 681 | | { |
| 682 | | size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count); |
| 683 | | } |
| 684 | | /* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */ |
| 685 | | else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x1800)) |
| 686 | | { |
| 687 | | size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count); |
| 688 | | } |
| 689 | | /* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */ |
| 690 | | else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x1800)) |
| 691 | | { |
| 692 | | size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count); |
| 693 | | } |
| 694 | | /* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */ |
| 695 | | else if (((op & 0xffc0) == 0x1440) && ((op2 & 0x1f00) == 0x1000)) |
| 696 | | { |
| 697 | | size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count); |
| 698 | | } |
| 699 | | /* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */ |
| 700 | | else if (((op & 0xffe0) == 0x1420) && ((op2 & 0x1f00) == 0x1000)) |
| 701 | | { |
| 702 | | size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count); |
| 703 | | } |
| 704 | | /* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */ |
| 705 | | else if (((op & 0xffe0) == 0x1400) && ((op2 & 0x1f00) == 0x1000)) |
| 706 | | { |
| 707 | | size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count); |
| 708 | | } |
| 709 | | /* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */ |
| 710 | | else if (((op & 0xffc0) == 0x1440) && ((op2 & 0x1f00) == 0x0000)) |
| 711 | | { |
| 712 | | size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count); |
| 713 | | } |
| 714 | | /* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */ |
| 715 | | else if (((op & 0xffe0) == 0x1420) && ((op2 & 0x1f00) == 0x0000)) |
| 716 | | { |
| 717 | | size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count); |
| 718 | | } |
| 719 | | /* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */ |
| 720 | | else if (((op & 0xffe0) == 0x1400) && ((op2 & 0x1f00) == 0x0000)) |
| 721 | | { |
| 722 | | size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count); |
| 723 | | } |
| 724 | | /* Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 */ |
| 725 | | else if (((op & 0xff30) == 0x0730) && ((op2 & 0x0000) == 0x0000)) |
| 726 | | { |
| 727 | | size = dsp56k_op_bcc(cpustate, op, op2, &cycle_count); |
| 728 | | } |
| 729 | | /* Bcc : 0010 11cc ccee eeee : A-48 */ |
| 730 | | else if ((op & 0xfc00) == 0x2c00) |
| 731 | | { |
| 732 | | size = dsp56k_op_bcc_1(cpustate, op, &cycle_count); |
| 733 | | } |
| 734 | | /* Bcc : 0000 0111 RR10 cccc : A-48 */ |
| 735 | | else if ((op & 0xff30) == 0x0720) |
| 736 | | { |
| 737 | | size = dsp56k_op_bcc_2(cpustate, op, &cycle_count); |
| 738 | | } |
| 739 | | /* BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 */ |
| 740 | | else if (((op & 0xfffc) == 0x013c) && ((op2 & 0x0000) == 0x0000)) |
| 741 | | { |
| 742 | | size = dsp56k_op_bra(cpustate, op, op2, &cycle_count); |
| 743 | | } |
| 744 | | /* BRA : 0000 1011 aaaa aaaa : A-50 */ |
| 745 | | else if ((op & 0xff00) == 0x0b00) |
| 746 | | { |
| 747 | | size = dsp56k_op_bra_1(cpustate, op, &cycle_count); |
| 748 | | } |
| 749 | | /* BRA : 0000 0001 0010 11RR : A-50 */ |
| 750 | | else if ((op & 0xfffc) == 0x012c) |
| 751 | | { |
| 752 | | size = dsp56k_op_bra_2(cpustate, op, &cycle_count); |
| 753 | | } |
| 754 | | /* BRKc : 0000 0001 0001 cccc : A-52 */ |
| 755 | | else if ((op & 0xfff0) == 0x0110) |
| 756 | | { |
| 757 | | size = dsp56k_op_brkcc(cpustate, op, &cycle_count); |
| 758 | | } |
| 759 | | /* BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 */ |
| 760 | | else if (((op & 0xff30) == 0x0710) && ((op2 & 0x0000) == 0x0000)) |
| 761 | | { |
| 762 | | size = dsp56k_op_bscc(cpustate, op, op2, &cycle_count); |
| 763 | | } |
| 764 | | /* BScc : 0000 0111 RR00 cccc : A-54 */ |
| 765 | | else if ((op & 0xff30) == 0x0700) |
| 766 | | { |
| 767 | | size = dsp56k_op_bscc_1(cpustate, op, &cycle_count); |
| 768 | | } |
| 769 | | /* BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 */ |
| 770 | | else if (((op & 0xfffc) == 0x0138) && ((op2 & 0x0000) == 0x0000)) |
| 771 | | { |
| 772 | | size = dsp56k_op_bsr(cpustate, op, op2, &cycle_count); |
| 773 | | } |
| 774 | | /* BSR : 0000 0001 0010 10RR : A-56 */ |
| 775 | | else if ((op & 0xfffc) == 0x0128) |
| 776 | | { |
| 777 | | size = dsp56k_op_bsr_1(cpustate, op, &cycle_count); |
| 778 | | } |
| 779 | | /* CHKAAU : 0000 0000 0000 0100 : A-58 */ |
| 780 | | else if ((op & 0xffff) == 0x0004) |
| 781 | | { |
| 782 | | size = dsp56k_op_chkaau(cpustate, op, &cycle_count); |
| 783 | | } |
| 784 | | /* DEBUG : 0000 0000 0000 0001 : A-68 */ |
| 785 | | else if ((op & 0xffff) == 0x0001) |
| 786 | | { |
| 787 | | size = dsp56k_op_debug(cpustate, op, &cycle_count); |
| 788 | | } |
| 789 | | /* DEBUGcc : 0000 0000 0101 cccc : A-70 */ |
| 790 | | else if ((op & 0xfff0) == 0x0050) |
| 791 | | { |
| 792 | | size = dsp56k_op_debugcc(cpustate, op, &cycle_count); |
| 793 | | } |
| 794 | | /* DIV : 0001 0101 0--0 F1DD : A-76 */ |
| 795 | | else if ((op & 0xff94) == 0x1504) |
| 796 | | { |
| 797 | | size = dsp56k_op_div(cpustate, op, &cycle_count); |
| 798 | | } |
| 799 | | /* DMAC : 0001 0101 10s1 FsQQ : A-80 */ |
| 800 | | else if ((op & 0xffd0) == 0x1590) |
| 801 | | { |
| 802 | | size = dsp56k_op_dmac(cpustate, op, &cycle_count); |
| 803 | | } |
| 804 | | /* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */ |
| 805 | | else if (((op & 0xffe0) == 0x00c0) && ((op2 & 0x0000) == 0x0000)) |
| 806 | | { |
| 807 | | size = dsp56k_op_do(cpustate, op, op2, &cycle_count); |
| 808 | | } |
| 809 | | /* DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 */ |
| 810 | | else if (((op & 0xff00) == 0x0e00) && ((op2 & 0x0000) == 0x0000)) |
| 811 | | { |
| 812 | | size = dsp56k_op_do_1(cpustate, op, op2, &cycle_count); |
| 813 | | } |
| 814 | | /* DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 */ |
| 815 | | else if (((op & 0xffe0) == 0x0400) && ((op2 & 0x0000) == 0x0000)) |
| 816 | | { |
| 817 | | size = dsp56k_op_do_2(cpustate, op, op2, &cycle_count); |
| 818 | | } |
| 819 | | /* DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 */ |
| 820 | | else if (((op & 0xffff) == 0x0002) && ((op2 & 0x0000) == 0x0000)) |
| 821 | | { |
| 822 | | size = dsp56k_op_doforever(cpustate, op, op2, &cycle_count); |
| 823 | | } |
| 824 | | /* ENDDO : 0000 0000 0000 1001 : A-92 */ |
| 825 | | else if ((op & 0xffff) == 0x0009) |
| 826 | | { |
| 827 | | size = dsp56k_op_enddo(cpustate, op, &cycle_count); |
| 828 | | } |
| 829 | | /* EXT : 0001 0101 0101 F010 : A-96 */ |
| 830 | | else if ((op & 0xfff7) == 0x1552) |
| 831 | | { |
| 832 | | size = dsp56k_op_ext(cpustate, op, &cycle_count); |
| 833 | | } |
| 834 | | /* ILLEGAL : 0000 0000 0000 1111 : A-98 */ |
| 835 | | else if ((op & 0xffff) == 0x000f) |
| 836 | | { |
| 837 | | size = dsp56k_op_illegal(cpustate, op, &cycle_count); |
| 838 | | } |
| 839 | | /* IMAC : 0001 0101 1010 FQQQ : A-100 */ |
| 840 | | else if ((op & 0xfff0) == 0x15a0) |
| 841 | | { |
| 842 | | size = dsp56k_op_imac(cpustate, op, &cycle_count); |
| 843 | | } |
| 844 | | /* IMPY : 0001 0101 1000 FQQQ : A-102 */ |
| 845 | | else if ((op & 0xfff0) == 0x1580) |
| 846 | | { |
| 847 | | size = dsp56k_op_impy(cpustate, op, &cycle_count); |
| 848 | | } |
| 849 | | /* Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 */ |
| 850 | | else if (((op & 0xff30) == 0x0630) && ((op2 & 0x0000) == 0x0000)) |
| 851 | | { |
| 852 | | size = dsp56k_op_jcc(cpustate, op, op2, &cycle_count); |
| 853 | | } |
| 854 | | /* Jcc : 0000 0110 RR10 cccc : A-108 */ |
| 855 | | else if ((op & 0xff30) == 0x0620 ) |
| 856 | | { |
| 857 | | size = dsp56k_op_jcc_1(cpustate, op, &cycle_count); |
| 858 | | } |
| 859 | | /* JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 */ |
| 860 | | else if (((op & 0xfffc) == 0x0134) && ((op2 & 0x0000) == 0x0000)) |
| 861 | | { |
| 862 | | size = dsp56k_op_jmp(cpustate, op, op2, &cycle_count); |
| 863 | | } |
| 864 | | /* JMP : 0000 0001 0010 01RR : A-110 */ |
| 865 | | else if ((op & 0xfffc) == 0x0124) |
| 866 | | { |
| 867 | | size = dsp56k_op_jmp_1(cpustate, op, &cycle_count); |
| 868 | | } |
| 869 | | /* JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 */ |
| 870 | | else if (((op & 0xff30) == 0x0610) && ((op2 & 0x0000) == 0x0000)) |
| 871 | | { |
| 872 | | size = dsp56k_op_jscc(cpustate, op, op2, &cycle_count); |
| 873 | | } |
| 874 | | /* JScc : 0000 0110 RR00 cccc : A-112 */ |
| 875 | | else if ((op & 0xff30) == 0x0600) |
| 876 | | { |
| 877 | | size = dsp56k_op_jscc_1(cpustate, op, &cycle_count); |
| 878 | | } |
| 879 | | /* JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 */ |
| 880 | | else if (((op & 0xfffc) == 0x0130) && ((op2 & 0x0000) == 0x0000)) |
| 881 | | { |
| 882 | | size = dsp56k_op_jsr(cpustate, op, op2, &cycle_count); |
| 883 | | } |
| 884 | | /* JSR : 0000 1010 AAAA AAAA : A-114 */ |
| 885 | | else if ((op & 0xff00) == 0x0a00) |
| 886 | | { |
| 887 | | size = dsp56k_op_jsr_1(cpustate, op, &cycle_count); |
| 888 | | } |
| 889 | | /* JSR : 0000 0001 0010 00RR : A-114 */ |
| 890 | | else if ((op & 0xfffc) == 0x0120) |
| 891 | | { |
| 892 | | size = dsp56k_op_jsr_2(cpustate, op, &cycle_count); |
| 893 | | } |
| 894 | | /* LEA : 0000 0001 11TT MMRR : A-116 */ |
| 895 | | else if ((op & 0xffc0) == 0x01c0) |
| 896 | | { |
| 897 | | size = dsp56k_op_lea(cpustate, op, &cycle_count); |
| 898 | | } |
| 899 | | /* LEA : 0000 0001 10NN MMRR : A-116 */ |
| 900 | | else if ((op & 0xffc0) == 0x0180) |
| 901 | | { |
| 902 | | size = dsp56k_op_lea_1(cpustate, op, &cycle_count); |
| 903 | | } |
| 904 | | /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */ |
| 905 | | else if ((op & 0xfff0) == 0x15e0) |
| 906 | | { |
| 907 | | size = dsp56k_op_macsuuu(cpustate, op, &cycle_count); |
| 908 | | } |
| 909 | | /* MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 */ |
| 910 | | else if (((op & 0xff00) == 0x0500) && ((op2 & 0x00ff) == 0x0011)) |
| 911 | | { |
| 912 | | size = dsp56k_op_move_2(cpustate, op, op2, &cycle_count); |
| 913 | | } |
| 914 | | /* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */ |
| 915 | | else if ((op & 0xf810) == 0x3800) |
| 916 | | { |
| 917 | | size = dsp56k_op_movec(cpustate, op, &cycle_count); |
| 918 | | } |
| 919 | | /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */ |
| 920 | | else if ((op & 0xf814) == 0x3810) |
| 921 | | { |
| 922 | | size = dsp56k_op_movec_1(cpustate, op, &cycle_count); |
| 923 | | } |
| 924 | | /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */ |
| 925 | | else if ((op & 0xf816) == 0x3816) |
| 926 | | { |
| 927 | | size = dsp56k_op_movec_2(cpustate, op, &cycle_count); |
| 928 | | } |
| 929 | | /* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */ |
| 930 | | else if (((op & 0xf816) == 0x3814) && ((op2 & 0x0000) == 0x0000)) |
| 931 | | { |
| 932 | | size = dsp56k_op_movec_3(cpustate, op, op2, &cycle_count); |
| 933 | | } |
| 934 | | /* MOVE(C) : 0010 10dd dddD DDDD : A-144 */ |
| 935 | | else if ((op & 0xfc00) == 0x2800) |
| 936 | | { |
| 937 | | size = dsp56k_op_movec_4(cpustate, op, &cycle_count); |
| 938 | | } |
| 939 | | /* MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 */ |
| 940 | | else if (((op & 0xff00) == 0x0500) && ((op2 & 0xf810) == 0x3800)) |
| 941 | | { |
| 942 | | size = dsp56k_op_movec_5(cpustate, op, op2, &cycle_count); |
| 943 | | } |
| 944 | | /* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */ |
| 945 | | else if ((op & 0xfc00) == 0x2000) |
| 946 | | { |
| 947 | | size = dsp56k_op_movei(cpustate, op, &cycle_count); |
| 948 | | } |
| 949 | | /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */ |
| 950 | | else if ((op & 0xfe20) == 0x0200) |
| 951 | | { |
| 952 | | size = dsp56k_op_movem(cpustate, op, &cycle_count); |
| 953 | | } |
| 954 | | /* MOVE(M) : 0000 001W RR11 mmRR : A-152 */ |
| 955 | | else if ((op & 0xfe30) == 0x0230) |
| 956 | | { |
| 957 | | size = dsp56k_op_movem_1(cpustate, op, &cycle_count); |
| 958 | | } |
| 959 | | /* MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 */ |
| 960 | | else if (((op & 0xff00) == 0x0500) && ((op2 & 0xfe20) == 0x0200)) |
| 961 | | { |
| 962 | | size = dsp56k_op_movem_2(cpustate, op, op2, &cycle_count); |
| 963 | | } |
| 964 | | /* MOVE(P) : 0001 100W HH1p pppp : A-156 */ |
| 965 | | else if ((op & 0xfe20) == 0x1820) |
| 966 | | { |
| 967 | | size = dsp56k_op_movep(cpustate, op, &cycle_count); |
| 968 | | } |
| 969 | | /* MOVE(P) : 0000 110W RRmp pppp : A-156 */ |
| 970 | | else if ((op & 0xfe00) == 0x0c00) |
| 971 | | { |
| 972 | | size = dsp56k_op_movep_1(cpustate, op, &cycle_count); |
| 973 | | } |
| 974 | | /* MOVE(S) : 0001 100W HH0a aaaa : A-158 */ |
| 975 | | else if ((op & 0xfe20) == 0x1800) |
| 976 | | { |
| 977 | | size = dsp56k_op_moves(cpustate, op, &cycle_count); |
| 978 | | } |
| 979 | | /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */ |
| 980 | | else if ((op & 0xfff0) == 0x15c0) |
| 981 | | { |
| 982 | | size = dsp56k_op_mpysuuu(cpustate, op, &cycle_count); |
| 983 | | } |
| 984 | | /* NEGC : 0001 0101 0110 F000 : A-168 */ |
| 985 | | else if ((op & 0xfff7) == 0x1560) |
| 986 | | { |
| 987 | | size = dsp56k_op_negc(cpustate, op, &cycle_count); |
| 988 | | } |
| 989 | | /* NOP : 0000 0000 0000 0000 : A-170 */ |
| 990 | | else if ((op & 0xffff) == 0x0000) |
| 991 | | { |
| 992 | | size = dsp56k_op_nop(cpustate, op, &cycle_count); |
| 993 | | } |
| 994 | | /* NORM : 0001 0101 0010 F0RR : A-172 */ |
| 995 | | else if ((op & 0xfff4) == 0x1520) |
| 996 | | { |
| 997 | | size = dsp56k_op_norm(cpustate, op, &cycle_count); |
| 998 | | } |
| 999 | | /* ORI : 0001 1EE1 iiii iiii : A-178 */ |
| 1000 | | else if ((op & 0xf900) == 0x1900) |
| 1001 | | { |
| 1002 | | size = dsp56k_op_ori(cpustate, op, &cycle_count); |
| 1003 | | } |
| 1004 | | /* REP : 0000 0000 111- --RR : A-180 */ |
| 1005 | | else if ((op & 0xffe0) == 0x00e0) |
| 1006 | | { |
| 1007 | | size = dsp56k_op_rep(cpustate, op, &cycle_count); |
| 1008 | | } |
| 1009 | | /* REP : 0000 1111 iiii iiii : A-180 */ |
| 1010 | | else if ((op & 0xff00) == 0x0f00) |
| 1011 | | { |
| 1012 | | size = dsp56k_op_rep_1(cpustate, op, &cycle_count); |
| 1013 | | } |
| 1014 | | /* REP : 0000 0100 001D DDDD : A-180 */ |
| 1015 | | else if ((op & 0xffe0) == 0x0420) |
| 1016 | | { |
| 1017 | | size = dsp56k_op_rep_2(cpustate, op, &cycle_count); |
| 1018 | | } |
| 1019 | | /* REPcc : 0000 0001 0101 cccc : A-184 */ |
| 1020 | | else if ((op & 0xfff0) == 0x0150) |
| 1021 | | { |
| 1022 | | size = dsp56k_op_repcc(cpustate, op, &cycle_count); |
| 1023 | | } |
| 1024 | | /* RESET : 0000 0000 0000 1000 : A-186 */ |
| 1025 | | else if ((op & 0xffff) == 0x0008) |
| 1026 | | { |
| 1027 | | size = dsp56k_op_reset(cpustate, op, &cycle_count); |
| 1028 | | } |
| 1029 | | /* RTI : 0000 0000 0000 0111 : A-194 */ |
| 1030 | | else if ((op & 0xffff) == 0x0007) |
| 1031 | | { |
| 1032 | | size = dsp56k_op_rti(cpustate, op, &cycle_count); |
| 1033 | | } |
| 1034 | | /* RTS : 0000 0000 0000 0110 : A-196 */ |
| 1035 | | else if ((op & 0xffff) == 0x0006) |
| 1036 | | { |
| 1037 | | size = dsp56k_op_rts(cpustate, op, &cycle_count); |
| 1038 | | } |
| 1039 | | /* STOP : 0000 0000 0000 1010 : A-200 */ |
| 1040 | | else if ((op & 0xffff) == 0x000a) |
| 1041 | | { |
| 1042 | | size = dsp56k_op_stop(cpustate, op, &cycle_count); |
| 1043 | | } |
| 1044 | | /* SWAP : 0001 0101 0111 F001 : A-206 */ |
| 1045 | | else if ((op & 0xfff7) == 0x1571) |
| 1046 | | { |
| 1047 | | size = dsp56k_op_swap(cpustate, op, &cycle_count); |
| 1048 | | } |
| 1049 | | /* SWI : 0000 0000 0000 0101 : A-208 */ |
| 1050 | | else if ((op & 0xffff) == 0x0005) |
| 1051 | | { |
| 1052 | | size = dsp56k_op_swi(cpustate, op, &cycle_count); |
| 1053 | | } |
| 1054 | | /* Tcc : 0001 00cc ccTT Fh0h : A-210 */ |
| 1055 | | else if ((op & 0xfc02) == 0x1000) |
| 1056 | | { |
| 1057 | | size = dsp56k_op_tcc(cpustate, op, &cycle_count); |
| 1058 | | } |
| 1059 | | /* TFR(2) : 0001 0101 0000 F00J : A-214 */ |
| 1060 | | else if ((op & 0xfff6) == 0x1500) |
| 1061 | | { |
| 1062 | | size = dsp56k_op_tfr2(cpustate, op, &cycle_count); |
| 1063 | | } |
| 1064 | | /* TFR(3) : 0010 01mW RRDD FHHH : A-216 */ |
| 1065 | | else if ((op & 0xfc00) == 0x2400) |
| 1066 | | { |
| 1067 | | size = dsp56k_op_tfr3(cpustate, op, &cycle_count); |
| 1068 | | } |
| 1069 | | /* TST(2) : 0001 0101 0001 -1DD : A-220 */ |
| 1070 | | else if ((op & 0xfff4) == 0x1514) |
| 1071 | | { |
| 1072 | | size = dsp56k_op_tst2(cpustate, op, &cycle_count); |
| 1073 | | } |
| 1074 | | /* WAIT : 0000 0000 0000 1011 : A-222 */ |
| 1075 | | else if ((op & 0xffff) == 0x000b) |
| 1076 | | { |
| 1077 | | size = dsp56k_op_wait(cpustate, op, &cycle_count); |
| 1078 | | } |
| 1079 | | /* ZERO : 0001 0101 0101 F000 : A-224 */ |
| 1080 | | else if ((op & 0xfff7) == 0x1550) |
| 1081 | | { |
| 1082 | | size = dsp56k_op_zero(cpustate, op, &cycle_count); |
| 1083 | | } |
| 1084 | | |
| 1085 | | |
| 1086 | | /* Not recognized? Nudge debugger onto the next word */ |
| 1087 | | if (size == 0x1337) |
| 1088 | | { |
| 1089 | | logerror("DSP56k: Unimplemented opcode at 0x%04x : %04x\n", PC, op); |
| 1090 | | size = 1 ; /* Just to get the debugger past the bad opcode */ |
| 1091 | | } |
| 1092 | | |
| 1093 | | /* Must have been a good opcode */ |
| 1094 | | PC += size; |
| 1095 | | |
| 1096 | | dsp56k_process_loop(cpustate); |
| 1097 | | dsp56k_process_rep(cpustate, size); |
| 1098 | | |
| 1099 | | cpustate->icount -= 4; /* Temporarily hard-coded at 4 clocks per opcode */ /* cycle_count */ |
| 1100 | | } |
| 1101 | | |
| 1102 | | |
| 1103 | | |
| 1104 | | |
| 1105 | | /*************************************************************************** |
| 1106 | | Opcode implementations |
| 1107 | | ***************************************************************************/ |
| 1108 | | |
| 1109 | | /*******************************/ |
| 1110 | | /* 32 Parallel move operations */ |
| 1111 | | /*******************************/ |
| 1112 | | |
| 1113 | | /* ADD : 011m mKKK 0rru Fuuu : A-22 */ |
| 1114 | | /* SUB : 011m mKKK 0rru Fuuu : A-202 */ |
| 1115 | | static size_t dsp56k_op_addsub_2(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1116 | | { |
| 1117 | | UINT64 useVal = 0; |
| 1118 | | UINT8 op_type = OP_OTHER; |
| 1119 | | typed_pointer S = {NULL, DT_BYTE}; |
| 1120 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1121 | | |
| 1122 | | decode_uuuuF_table(cpustate, BITS(op_byte,0x0017), BITS(op_byte,0x0008), op_type, &S, &D); |
| 1123 | | |
| 1124 | | /* If you gave an invalid operation type, presume it's a nop and move on with the parallel move */ |
| 1125 | | if (op_type == OP_OTHER) |
| 1126 | | { |
| 1127 | | d_register->addr = NULL; |
| 1128 | | d_register->data_type = DT_BYTE; |
| 1129 | | cycles += 2; |
| 1130 | | return 1; |
| 1131 | | } |
| 1132 | | |
| 1133 | | /* It's a real operation. Get on with it. */ |
| 1134 | | switch(S.data_type) |
| 1135 | | { |
| 1136 | | case DT_WORD: useVal = (UINT64)*((UINT16*)S.addr) << 16; break; |
| 1137 | | case DT_DOUBLE_WORD: useVal = (UINT64)*((UINT32*)S.addr); break; |
| 1138 | | case DT_LONG_WORD: useVal = (UINT64)*((UINT64*)S.addr); break; |
| 1139 | | } |
| 1140 | | |
| 1141 | | /* Sign-extend word for proper add/sub op */ |
| 1142 | | if ((S.data_type == DT_WORD) && useVal & U64(0x0000000080000000)) |
| 1143 | | useVal |= U64(0x000000ff00000000); |
| 1144 | | |
| 1145 | | /* Operate*/ |
| 1146 | | if (op_type == OP_ADD) |
| 1147 | | *((UINT64*)D.addr) += useVal; |
| 1148 | | else if (op_type == OP_SUB) |
| 1149 | | *((UINT64*)D.addr) -= useVal; |
| 1150 | | |
| 1151 | | d_register->addr = D.addr; |
| 1152 | | d_register->data_type = D.data_type; |
| 1153 | | |
| 1154 | | /* S L E U N Z V C */ |
| 1155 | | /* * * * * * * * * */ |
| 1156 | | /* TODO S, L, E, U, V, C */ |
| 1157 | | if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1158 | | if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1159 | | |
| 1160 | | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1161 | | return 1; |
| 1162 | | } |
| 1163 | | |
| 1164 | | /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */ |
| 1165 | | static size_t dsp56k_op_mac_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1166 | | { |
| 1167 | | INT64 opD = 0; |
| 1168 | | INT64 result = 0; |
| 1169 | | |
| 1170 | | INT32 s1 = 0; |
| 1171 | | INT32 s2 = 0; |
| 1172 | | |
| 1173 | | void* D = NULL; |
| 1174 | | void* S1 = NULL; |
| 1175 | | void* S2 = NULL; |
| 1176 | | |
| 1177 | | decode_QQF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S1, &S2, &D); |
| 1178 | | |
| 1179 | | /* Cast both values as being signed */ |
| 1180 | | s1 = *((INT16*)S1); |
| 1181 | | s2 = *((INT16*)S2); |
| 1182 | | |
| 1183 | | /* Fixed-point 2's complement multiplication requires a shift */ |
| 1184 | | result = (s1 * s2) << 1; |
| 1185 | | |
| 1186 | | /* Sign extend D into a temp variable */ |
| 1187 | | opD = (*((UINT64*)D)); |
| 1188 | | if (opD & U64(0x0000008000000000)) |
| 1189 | | opD |= U64(0xffffff0000000000); |
| 1190 | | else |
| 1191 | | opD &= U64(0x000000ffffffffff); |
| 1192 | | |
| 1193 | | /* Accumulate */ |
| 1194 | | opD += result; |
| 1195 | | |
| 1196 | | /* And out the bits that don't live in the register */ |
| 1197 | | opD &= U64(0x000000ffffffffff); |
| 1198 | | |
| 1199 | | (*((UINT64*)D)) = (UINT64)opD; |
| 1200 | | |
| 1201 | | /* For the parallel move */ |
| 1202 | | d_register->addr = D; |
| 1203 | | d_register->data_type = DT_LONG_WORD; |
| 1204 | | |
| 1205 | | /* S L E U N Z V C */ |
| 1206 | | /* * * * * * * * - */ |
| 1207 | | /* TODO: S, L, E, V */ |
| 1208 | | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1209 | | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1210 | | |
| 1211 | | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 1212 | | return 1; |
| 1213 | | } |
| 1214 | | |
| 1215 | | /* MACR: 011m mKKK 1--1 F1QQ : A-124 */ |
| 1216 | | static size_t dsp56k_op_macr_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1217 | | { |
| 1218 | | /* S L E U N Z V C */ |
| 1219 | | /* * * * * * * * - */ |
| 1220 | | return 0; |
| 1221 | | } |
| 1222 | | |
| 1223 | | /* MOVE : 011m mKKK 0rr1 0000 : A-128 */ |
| 1224 | | static size_t dsp56k_op_move_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1225 | | { |
| 1226 | | /* S L E U N Z V C */ |
| 1227 | | /* * * - - - - - - */ |
| 1228 | | return 0; |
| 1229 | | } |
| 1230 | | |
| 1231 | | /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */ |
| 1232 | | static size_t dsp56k_op_mpy_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1233 | | { |
| 1234 | | INT64 result = 0; |
| 1235 | | |
| 1236 | | INT32 s1 = 0; |
| 1237 | | INT32 s2 = 0; |
| 1238 | | |
| 1239 | | void* D = NULL; |
| 1240 | | void* S1 = NULL; |
| 1241 | | void* S2 = NULL; |
| 1242 | | |
| 1243 | | decode_QQF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S1, &S2, &D); |
| 1244 | | |
| 1245 | | /* Cast both values as being signed */ |
| 1246 | | s1 = *((INT16*)S1); |
| 1247 | | s2 = *((INT16*)S2); |
| 1248 | | |
| 1249 | | /* Fixed-point 2's complement multiplication requires a shift */ |
| 1250 | | result = (s1 * s2) << 1; |
| 1251 | | |
| 1252 | | /* And out the bits that don't live in the register */ |
| 1253 | | (*((UINT64*)D)) = result & U64(0x000000ffffffffff); |
| 1254 | | |
| 1255 | | /* For the parallel move */ |
| 1256 | | d_register->addr = D; |
| 1257 | | d_register->data_type = DT_LONG_WORD; |
| 1258 | | |
| 1259 | | /* S L E U N Z V C */ |
| 1260 | | /* * * * * * * * - */ |
| 1261 | | /* TODO: S, L, E, V */ |
| 1262 | | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1263 | | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1264 | | |
| 1265 | | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 1266 | | return 1; |
| 1267 | | } |
| 1268 | | |
| 1269 | | /* MPYR : 011m mKKK 1--1 F0QQ : A-162 */ |
| 1270 | | static size_t dsp56k_op_mpyr_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1271 | | { |
| 1272 | | /* S L E U N Z V C */ |
| 1273 | | /* * * * * * * * - */ |
| 1274 | | return 0; |
| 1275 | | } |
| 1276 | | |
| 1277 | | /* TFR : 011m mKKK 0rr1 F0DD : A-212 */ |
| 1278 | | static size_t dsp56k_op_tfr_2(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1279 | | { |
| 1280 | | /* S L E U N Z V C */ |
| 1281 | | /* - - - - - - - - */ |
| 1282 | | return 0; |
| 1283 | | } |
| 1284 | | |
| 1285 | | /* MPY : 0001 0110 RRDD FQQQ : A-160 */ |
| 1286 | | static size_t dsp56k_op_mpy_2(dsp56k_core* cpustate, const UINT16 op_byte, UINT8* cycles) |
| 1287 | | { |
| 1288 | | /* S L E U N Z V C */ |
| 1289 | | /* * * * * * * * - */ |
| 1290 | | return 0; |
| 1291 | | } |
| 1292 | | |
| 1293 | | /* MAC : 0001 0111 RRDD FQQQ : A-122 */ |
| 1294 | | static size_t dsp56k_op_mac_2(dsp56k_core* cpustate, const UINT16 op_byte, UINT8* cycles) |
| 1295 | | { |
| 1296 | | /* S L E U N Z V C */ |
| 1297 | | /* * * * * * * * - */ |
| 1298 | | return 0; |
| 1299 | | } |
| 1300 | | |
| 1301 | | /* CLR : .... .... 0000 F001 : A-60 */ |
| 1302 | | static size_t dsp56k_op_clr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1303 | | { |
| 1304 | | typed_pointer D = {NULL, DT_LONG_WORD}; |
| 1305 | | typed_pointer clear = {NULL, DT_LONG_WORD}; |
| 1306 | | UINT64 clear_val = U64(0x0000000000000000); |
| 1307 | | |
| 1308 | | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1309 | | |
| 1310 | | *p_accum = *((UINT64*)D.addr); |
| 1311 | | |
| 1312 | | clear.addr = &clear_val; |
| 1313 | | clear.data_type = DT_LONG_WORD; |
| 1314 | | SetDestinationValue(clear, D); |
| 1315 | | |
| 1316 | | d_register->addr = D.addr; |
| 1317 | | d_register->data_type = D.data_type; |
| 1318 | | |
| 1319 | | /* S L E U N Z V C */ |
| 1320 | | /* * * * * * * 0 - */ |
| 1321 | | /* TODO - S, L */ |
| 1322 | | DSP56K_E_CLEAR(); |
| 1323 | | DSP56K_U_SET(); |
| 1324 | | DSP56K_N_CLEAR(); |
| 1325 | | DSP56K_Z_SET(); |
| 1326 | | DSP56K_V_CLEAR(); |
| 1327 | | |
| 1328 | | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1329 | | return 1; |
| 1330 | | } |
| 1331 | | |
| 1332 | | /* ADD : .... .... 0000 FJJJ : A-22 */ |
| 1333 | | static size_t dsp56k_op_add(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1334 | | { |
| 1335 | | UINT64 addVal = 0; |
| 1336 | | |
| 1337 | | typed_pointer S = {NULL, DT_BYTE}; |
| 1338 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1339 | | decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D); |
| 1340 | | |
| 1341 | | *p_accum = *((UINT64*)D.addr); |
| 1342 | | |
| 1343 | | switch(S.data_type) |
| 1344 | | { |
| 1345 | | case DT_WORD: addVal = (UINT64)*((UINT16*)S.addr) << 16; break; |
| 1346 | | case DT_DOUBLE_WORD: addVal = (UINT64)*((UINT32*)S.addr); break; |
| 1347 | | case DT_LONG_WORD: addVal = (UINT64)*((UINT64*)S.addr); break; |
| 1348 | | } |
| 1349 | | |
| 1350 | | /* Sign-extend word for proper add/sub op */ |
| 1351 | | if ((S.data_type == DT_WORD) && addVal & U64(0x0000000080000000)) |
| 1352 | | addVal |= U64(0x000000ff00000000); |
| 1353 | | |
| 1354 | | /* Operate*/ |
| 1355 | | *((UINT64*)D.addr) += addVal; |
| 1356 | | |
| 1357 | | d_register->addr = D.addr; |
| 1358 | | d_register->data_type = D.data_type; |
| 1359 | | |
| 1360 | | /* S L E U N Z V C */ |
| 1361 | | /* * * * * * * * * */ |
| 1362 | | /* TODO S, L, E, U, V, C */ |
| 1363 | | if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1364 | | if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1365 | | |
| 1366 | | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1367 | | return 1; |
| 1368 | | } |
| 1369 | | |
| 1370 | | /* MOVE : .... .... 0001 0001 : A-128 */ |
| 1371 | | static size_t dsp56k_op_move(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1372 | | { |
| 1373 | | /* Equivalent to a nop with a parallel move */ |
| 1374 | | /* These can't be used later. Hopefully compilers would pick this up. */ |
| 1375 | | *p_accum = 0; |
| 1376 | | d_register->addr = NULL; |
| 1377 | | d_register->data_type = DT_BYTE; |
| 1378 | | |
| 1379 | | /* S L E U N Z V C */ |
| 1380 | | /* * * - - - - - - */ |
| 1381 | | /* TODO: S, L */ |
| 1382 | | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1383 | | return 1; |
| 1384 | | } |
| 1385 | | |
| 1386 | | /* TFR : .... .... 0001 FJJJ : A-212 */ |
| 1387 | | static size_t dsp56k_op_tfr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1388 | | { |
| 1389 | | typed_pointer S = {NULL, DT_BYTE}; |
| 1390 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1391 | | |
| 1392 | | decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D); |
| 1393 | | |
| 1394 | | *p_accum = *((UINT64*)D.addr); |
| 1395 | | |
| 1396 | | SetDestinationValue(S, D); |
| 1397 | | |
| 1398 | | d_register->addr = D.addr; |
| 1399 | | d_register->data_type = D.data_type; |
| 1400 | | |
| 1401 | | /* S L E U N Z V C */ |
| 1402 | | /* * * - - - - - - */ |
| 1403 | | /* TODO: S, L */ |
| 1404 | | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1405 | | return 1; |
| 1406 | | } |
| 1407 | | |
| 1408 | | /* RND : .... .... 0010 F000 : A-188 */ |
| 1409 | | static size_t dsp56k_op_rnd(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1410 | | { |
| 1411 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1412 | | |
| 1413 | | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1414 | | |
| 1415 | | *p_accum = *((UINT64*)D.addr); |
| 1416 | | |
| 1417 | | /* WARNING : ROUNDING NOT FULLY IMPLEMENTED YET! */ |
| 1418 | | if ((*((UINT64*)D.addr) & U64(0x000000000000ffff)) >= 0x8000) |
| 1419 | | *((UINT64*)D.addr) += U64(0x0000000000010000); |
| 1420 | | |
| 1421 | | *((UINT64*)D.addr) = *((UINT64*)D.addr) & U64(0x000000ffffff0000); |
| 1422 | | |
| 1423 | | d_register->addr = D.addr; |
| 1424 | | d_register->data_type = D.data_type; |
| 1425 | | |
| 1426 | | /* S L E U N Z V C */ |
| 1427 | | /* * * * * * * * - */ |
| 1428 | | /* TODO: S, L, E, U, V */ |
| 1429 | | if ((*((UINT64*)D.addr)) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1430 | | if ((*((UINT64*)D.addr)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1431 | | |
| 1432 | | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1433 | | return 1; |
| 1434 | | } |
| 1435 | | |
| 1436 | | /* TST : .... .... 0010 F001 : A-218 */ |
| 1437 | | static size_t dsp56k_op_tst(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1438 | | { |
| 1439 | | typed_pointer D = {NULL, DT_LONG_WORD}; |
| 1440 | | |
| 1441 | | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1442 | | |
| 1443 | | *p_accum = *((UINT64*)D.addr); |
| 1444 | | |
| 1445 | | d_register->addr = D.addr; |
| 1446 | | d_register->data_type = D.data_type; |
| 1447 | | |
| 1448 | | /* S L E U N Z V C */ |
| 1449 | | /* 0 * * * * * 0 0 */ |
| 1450 | | /* TODO: S, L, E, U */ |
| 1451 | | if ((*((UINT64*)D.addr)) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1452 | | if ((*((UINT64*)D.addr)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1453 | | DSP56K_V_CLEAR(); |
| 1454 | | DSP56K_C_CLEAR(); |
| 1455 | | |
| 1456 | | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1457 | | return 1; |
| 1458 | | } |
| 1459 | | |
| 1460 | | /* INC : .... .... 0010 F010 : A-104 */ |
| 1461 | | static size_t dsp56k_op_inc(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1462 | | { |
| 1463 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1464 | | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1465 | | |
| 1466 | | /* Save some data for the parallel move */ |
| 1467 | | *p_accum = *((UINT64*)D.addr); |
| 1468 | | |
| 1469 | | /* Make sure the destination is a real 40-bit value */ |
| 1470 | | *((UINT64*)D.addr) &= U64(0x000000ffffffffff); |
| 1471 | | |
| 1472 | | /* Increment */ |
| 1473 | | *((UINT64*)D.addr) = *((UINT64*)D.addr) + 1; |
| 1474 | | |
| 1475 | | d_register->addr = D.addr; |
| 1476 | | d_register->data_type = D.data_type; |
| 1477 | | |
| 1478 | | /* S L E U N Z V C */ |
| 1479 | | /* * * * * * * * * */ |
| 1480 | | /* TODO: S, L, E, U */ |
| 1481 | | if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1482 | | if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1483 | | if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 1484 | | if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1485 | | |
| 1486 | | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 1487 | | return 1; |
| 1488 | | } |
| 1489 | | |
| 1490 | | /* INC24 : .... .... 0010 F011 : A-106 */ |
| 1491 | | static size_t dsp56k_op_inc24(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1492 | | { |
| 1493 | | UINT32 workBits24; |
| 1494 | | |
| 1495 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1496 | | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1497 | | |
| 1498 | | /* Save some data for the parallel move */ |
| 1499 | | *p_accum = *((UINT64*)D.addr); |
| 1500 | | |
| 1501 | | /* TODO: I wonder if workBits24 should be signed? */ |
| 1502 | | workBits24 = ((*((UINT64*)D.addr)) & U64(0x000000ffffff0000)) >> 16; |
| 1503 | | workBits24++; |
| 1504 | | //workBits24 &= 0x00ffffff; /* Solves -x issues - TODO: huh? */ |
| 1505 | | |
| 1506 | | /* Set the D bits with the dec result */ |
| 1507 | | *((UINT64*)D.addr) &= U64(0x000000000000ffff); |
| 1508 | | *((UINT64*)D.addr) |= (((UINT64)(workBits24)) << 16); |
| 1509 | | |
| 1510 | | d_register->addr = D.addr; |
| 1511 | | d_register->data_type = D.data_type; |
| 1512 | | |
| 1513 | | /* S L E U N Z V C */ |
| 1514 | | /* * * * * * ? * * */ |
| 1515 | | /* TODO: S, L, E, U */ |
| 1516 | | if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1517 | | if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1518 | | if ((workBits24 & 0xff000000) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 1519 | | if ((workBits24 & 0xff000000) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1520 | | |
| 1521 | | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1522 | | return 1; |
| 1523 | | } |
| 1524 | | |
| 1525 | | /* OR : .... .... 0010 F1JJ : A-176 */ |
| 1526 | | static size_t dsp56k_op_or(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1527 | | { |
| 1528 | | typed_pointer S = {NULL, DT_BYTE}; |
| 1529 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1530 | | |
| 1531 | | decode_JJF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S, &D); |
| 1532 | | |
| 1533 | | /* Save some data for the parallel move */ |
| 1534 | | *p_accum = *((UINT64*)D.addr); |
| 1535 | | |
| 1536 | | /* OR a word of S with A1|B1 */ |
| 1537 | | ((PAIR64*)D.addr)->w.h = *((UINT16*)S.addr) | ((PAIR64*)D.addr)->w.h; |
| 1538 | | |
| 1539 | | d_register->addr = D.addr; |
| 1540 | | d_register->data_type = D.data_type; |
| 1541 | | |
| 1542 | | /* S L E U N Z V C */ |
| 1543 | | /* * * - - ? ? 0 - */ |
| 1544 | | /* TODO: S, L */ |
| 1545 | | if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1546 | | if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1547 | | DSP56K_V_CLEAR(); |
| 1548 | | |
| 1549 | | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1550 | | return 1; |
| 1551 | | } |
| 1552 | | |
| 1553 | | /* ASR : .... .... 0011 F000 : A-32 */ |
| 1554 | | static size_t dsp56k_op_asr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1555 | | { |
| 1556 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1557 | | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1558 | | |
| 1559 | | *p_accum = *((UINT64*)D.addr); |
| 1560 | | |
| 1561 | | *((UINT64*)D.addr) = (*((UINT64*)D.addr)) >> 1; |
| 1562 | | |
| 1563 | | /* Make sure the MSB is maintained */ |
| 1564 | | if (*p_accum & U64(0x0000008000000000)) |
| 1565 | | *((UINT64*)D.addr) |= U64(0x0000008000000000); |
| 1566 | | else |
| 1567 | | *((UINT64*)D.addr) &= (~U64(0x0000008000000000)); |
| 1568 | | |
| 1569 | | /* For the parallel move */ |
| 1570 | | d_register->addr = D.addr; |
| 1571 | | d_register->data_type = D.data_type; |
| 1572 | | |
| 1573 | | /* S L E U N Z V C */ |
| 1574 | | /* * * * * * * 0 ? */ |
| 1575 | | /* TODO: S, L, E, U */ |
| 1576 | | if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1577 | | if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1578 | | DSP56K_V_CLEAR(); |
| 1579 | | if (*p_accum & U64(0x0000000000000001)) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1580 | | |
| 1581 | | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1582 | | return 1; |
| 1583 | | } |
| 1584 | | |
| 1585 | | /* ASL : .... .... 0011 F001 : A-28 */ |
| 1586 | | static size_t dsp56k_op_asl(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1587 | | { |
| 1588 | | /* S L E U N Z V C */ |
| 1589 | | /* * * * * * * ? ? */ |
| 1590 | | /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significant |
| 1591 | | bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */ |
| 1592 | | /* C - Set if bit 39 of source operand is set. Cleared otherwise. */ |
| 1593 | | return 0; |
| 1594 | | } |
| 1595 | | |
| 1596 | | /* LSR : .... .... 0011 F010 : A-120 */ |
| 1597 | | static size_t dsp56k_op_lsr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1598 | | { |
| 1599 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1600 | | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1601 | | |
| 1602 | | *p_accum = *((UINT64*)D.addr); |
| 1603 | | |
| 1604 | | ((PAIR64*)D.addr)->w.h = (((PAIR64*)D.addr)->w.h) >> 1; |
| 1605 | | |
| 1606 | | /* Make sure bit 31 gets a 0 */ |
| 1607 | | ((PAIR64*)D.addr)->w.h &= (~0x8000); |
| 1608 | | |
| 1609 | | /* For the parallel move */ |
| 1610 | | d_register->addr = D.addr; |
| 1611 | | d_register->data_type = D.data_type; |
| 1612 | | |
| 1613 | | /* S L E U N Z V C */ |
| 1614 | | /* * * - - ? ? 0 ? */ |
| 1615 | | /* TODO: S, L */ |
| 1616 | | DSP56K_N_CLEAR(); |
| 1617 | | if (((PAIR64*)D.addr)->w.h == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1618 | | DSP56K_V_CLEAR(); |
| 1619 | | if (*p_accum & U64(0x0000000000010000)) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1620 | | |
| 1621 | | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1622 | | return 1; |
| 1623 | | } |
| 1624 | | |
| 1625 | | /* LSL : .... .... 0011 F011 : A-118 */ |
| 1626 | | static size_t dsp56k_op_lsl(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1627 | | { |
| 1628 | | /* S L E U N Z V C */ |
| 1629 | | /* * * - - ? ? 0 ? */ |
| 1630 | | /* N - Set if bit 31 of the result is set. Cleared otherwise. */ |
| 1631 | | /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */ |
| 1632 | | /* C - Set if bit 31 of the source operand is set. Cleared otherwise. */ |
| 1633 | | return 0; |
| 1634 | | } |
| 1635 | | |
| 1636 | | /* EOR : .... .... 0011 F1JJ : A-94 */ |
| 1637 | | static size_t dsp56k_op_eor(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1638 | | { |
| 1639 | | /* S L E U N Z V C */ |
| 1640 | | /* * * - - ? ? 0 - */ |
| 1641 | | /* N - Set if bit 31 of the result is set. Cleared otherwise. */ |
| 1642 | | /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */ |
| 1643 | | return 0; |
| 1644 | | } |
| 1645 | | |
| 1646 | | /* SUBL : .... .... 0100 F001 : A-204 */ |
| 1647 | | static size_t dsp56k_op_subl(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1648 | | { |
| 1649 | | /* S L E U N Z V C */ |
| 1650 | | /* * * * * * * ? * */ |
| 1651 | | /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significant |
| 1652 | | bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */ |
| 1653 | | return 0; |
| 1654 | | } |
| 1655 | | |
| 1656 | | /* SUB : .... .... 0100 FJJJ : A-202 */ |
| 1657 | | static size_t dsp56k_op_sub(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1658 | | { |
| 1659 | | UINT64 useVal = 0; |
| 1660 | | typed_pointer S = {NULL, DT_BYTE}; |
| 1661 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1662 | | |
| 1663 | | decode_JJJF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S, &D); |
| 1664 | | |
| 1665 | | /* Get on with it. */ |
| 1666 | | switch(S.data_type) |
| 1667 | | { |
| 1668 | | case DT_WORD: useVal = (UINT64)*((UINT16*)S.addr) << 16; break; |
| 1669 | | case DT_DOUBLE_WORD: useVal = (UINT64)*((UINT32*)S.addr); break; |
| 1670 | | case DT_LONG_WORD: useVal = (UINT64)*((UINT64*)S.addr); break; |
| 1671 | | } |
| 1672 | | |
| 1673 | | /* Sign-extend word for proper sub op */ |
| 1674 | | if ((S.data_type == DT_WORD) && useVal & U64(0x0000000080000000)) |
| 1675 | | useVal |= U64(0x000000ff00000000); |
| 1676 | | |
| 1677 | | /* Make sure they're both real 40-bit values */ |
| 1678 | | useVal &= U64(0x000000ffffffffff); |
| 1679 | | *((UINT64*)D.addr) &= U64(0x000000ffffffffff); |
| 1680 | | |
| 1681 | | /* Operate*/ |
| 1682 | | *((UINT64*)D.addr) -= useVal; |
| 1683 | | |
| 1684 | | d_register->addr = D.addr; |
| 1685 | | d_register->data_type = D.data_type; |
| 1686 | | |
| 1687 | | /* S L E U N Z V C */ |
| 1688 | | /* * * * * * * * * */ |
| 1689 | | /* TODO S, L, E, U */ |
| 1690 | | if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1691 | | if ( *((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1692 | | if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 1693 | | if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1694 | | |
| 1695 | | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1696 | | return 1; |
| 1697 | | } |
| 1698 | | |
| 1699 | | /* CLR24 : .... .... 0101 F001 : A-62 */ |
| 1700 | | static size_t dsp56k_op_clr24(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1701 | | { |
| 1702 | | /* S L E U N Z V C */ |
| 1703 | | /* * * * * * ? 0 - */ |
| 1704 | | /* Z - Set if the 24 most significant bits of the destination result are all zeroes. */ |
| 1705 | | return 0; |
| 1706 | | } |
| 1707 | | |
| 1708 | | /* SBC : .... .... 0101 F01J : A-198 */ |
| 1709 | | static size_t dsp56k_op_sbc(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1710 | | { |
| 1711 | | /* S L E U N Z V C */ |
| 1712 | | /* * * * * * * * * */ |
| 1713 | | return 0; |
| 1714 | | } |
| 1715 | | |
| 1716 | | /* CMP : .... .... 0101 FJJJ : A-64 */ |
| 1717 | | static size_t dsp56k_op_cmp(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1718 | | { |
| 1719 | | UINT64 cmpVal = 0; |
| 1720 | | UINT64 result = 0; |
| 1721 | | |
| 1722 | | typed_pointer S = {NULL, DT_BYTE}; |
| 1723 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1724 | | |
| 1725 | | decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D); |
| 1726 | | |
| 1727 | | *p_accum = *((UINT64*)D.addr); |
| 1728 | | |
| 1729 | | switch(S.data_type) |
| 1730 | | { |
| 1731 | | case DT_WORD: cmpVal = (UINT64)*((UINT16*)S.addr) << 16; break; |
| 1732 | | case DT_DOUBLE_WORD: cmpVal = (UINT64)*((UINT32*)S.addr); break; |
| 1733 | | case DT_LONG_WORD: cmpVal = (UINT64)*((UINT64*)S.addr); break; |
| 1734 | | } |
| 1735 | | |
| 1736 | | /* Sign-extend word for proper subtraction op */ |
| 1737 | | if ((S.data_type == DT_WORD) && cmpVal & U64(0x0000000080000000)) |
| 1738 | | cmpVal |= U64(0x000000ff00000000); |
| 1739 | | |
| 1740 | | /* Make sure they're both real 40-bit values */ |
| 1741 | | cmpVal &= U64(0x000000ffffffffff); |
| 1742 | | *((UINT64*)D.addr) &= U64(0x000000ffffffffff); |
| 1743 | | |
| 1744 | | /* Operate */ |
| 1745 | | result = *((UINT64*)D.addr) - cmpVal; |
| 1746 | | |
| 1747 | | d_register->addr = D.addr; |
| 1748 | | d_register->data_type = D.data_type; |
| 1749 | | |
| 1750 | | /* S L E U N Z V C */ |
| 1751 | | /* * * * * * * * * */ |
| 1752 | | /* TODO: S, L, E, U */ |
| 1753 | | if ( result & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1754 | | if ( result == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1755 | | if ((result & U64(0xffffff0000000000)) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 1756 | | if ((result & U64(0xffffff0000000000)) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1757 | | |
| 1758 | | |
| 1759 | | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1760 | | return 1; |
| 1761 | | } |
| 1762 | | |
| 1763 | | /* NEG : .... .... 0110 F000 : A-166 */ |
| 1764 | | static size_t dsp56k_op_neg(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1765 | | { |
| 1766 | | /* S L E U N Z V C */ |
| 1767 | | /* * * * * * * * * */ |
| 1768 | | return 0; |
| 1769 | | } |
| 1770 | | |
| 1771 | | /* NOT : .... .... 0110 F001 : A-174 */ |
| 1772 | | static size_t dsp56k_op_not(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1773 | | { |
| 1774 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1775 | | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1776 | | |
| 1777 | | *p_accum = *((UINT64*)D.addr); |
| 1778 | | |
| 1779 | | /* Invert bits [16:31] of D */ |
| 1780 | | ((PAIR64*)D.addr)->w.h = ~(((PAIR64*)D.addr)->w.h); |
| 1781 | | |
| 1782 | | d_register->addr = D.addr; |
| 1783 | | d_register->data_type = D.data_type; |
| 1784 | | |
| 1785 | | /* S L E U N Z V C */ |
| 1786 | | /* * * - - ? ? 0 - */ |
| 1787 | | /* TODO: S?, L */ |
| 1788 | | if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1789 | | if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1790 | | DSP56K_V_CLEAR(); |
| 1791 | | |
| 1792 | | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1793 | | return 1; |
| 1794 | | } |
| 1795 | | |
| 1796 | | /* DEC : .... .... 0110 F010 : A-72 */ |
| 1797 | | static size_t dsp56k_op_dec(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1798 | | { |
| 1799 | | /* S L E U N Z V C */ |
| 1800 | | /* * * * * * * * * */ |
| 1801 | | return 0; |
| 1802 | | } |
| 1803 | | |
| 1804 | | /* DEC24 : .... .... 0110 F011 : A-74 */ |
| 1805 | | static size_t dsp56k_op_dec24(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1806 | | { |
| 1807 | | UINT32 workBits24; |
| 1808 | | |
| 1809 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1810 | | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1811 | | |
| 1812 | | /* Save some data for the parallel move */ |
| 1813 | | *p_accum = *((UINT64*)D.addr); |
| 1814 | | |
| 1815 | | /* TODO: I wonder if workBits24 should be signed? */ |
| 1816 | | workBits24 = ((*((UINT64*)D.addr)) & U64(0x000000ffffff0000)) >> 16; |
| 1817 | | workBits24--; |
| 1818 | | workBits24 &= 0x00ffffff; /* Solves -x issues */ |
| 1819 | | |
| 1820 | | /* Set the D bits with the dec result */ |
| 1821 | | *((UINT64*)D.addr) &= U64(0x000000000000ffff); |
| 1822 | | *((UINT64*)D.addr) |= (((UINT64)(workBits24)) << 16); |
| 1823 | | |
| 1824 | | d_register->addr = D.addr; |
| 1825 | | d_register->data_type = D.data_type; |
| 1826 | | |
| 1827 | | /* S L E U N Z V C */ |
| 1828 | | /* * * * * * ? * * */ |
| 1829 | | /* TODO: S, L, E, U, V, C */ |
| 1830 | | if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1831 | | if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1832 | | |
| 1833 | | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1834 | | return 1; |
| 1835 | | } |
| 1836 | | |
| 1837 | | /* AND : .... .... 0110 F1JJ : A-24 */ |
| 1838 | | static size_t dsp56k_op_and(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1839 | | { |
| 1840 | | typed_pointer S = {NULL, DT_BYTE}; |
| 1841 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1842 | | |
| 1843 | | decode_JJF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S, &D); |
| 1844 | | |
| 1845 | | /* Save some data for the parallel move */ |
| 1846 | | *p_accum = *((UINT64*)D.addr); |
| 1847 | | |
| 1848 | | /* AND a word of S with A1|B1 */ |
| 1849 | | ((PAIR64*)D.addr)->w.h = *((UINT16*)S.addr) & ((PAIR64*)D.addr)->w.h; |
| 1850 | | |
| 1851 | | d_register->addr = D.addr; |
| 1852 | | d_register->data_type = D.data_type; |
| 1853 | | |
| 1854 | | /* S L E U N Z V C */ |
| 1855 | | /* * * - - ? ? 0 - */ |
| 1856 | | /* TODO: S, L */ |
| 1857 | | if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1858 | | if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1859 | | DSP56K_V_CLEAR(); |
| 1860 | | |
| 1861 | | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1862 | | return 1; |
| 1863 | | } |
| 1864 | | |
| 1865 | | /* ABS : .... .... 0111 F001 : A-18 */ |
| 1866 | | static size_t dsp56k_op_abs(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1867 | | { |
| 1868 | | INT64 opD = 0; |
| 1869 | | typed_pointer D = {NULL, DT_LONG_WORD}; |
| 1870 | | |
| 1871 | | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1872 | | |
| 1873 | | *p_accum = *((UINT64*)D.addr); |
| 1874 | | |
| 1875 | | /* Sign extend D into a temp variable */ |
| 1876 | | opD = *p_accum; |
| 1877 | | if (opD & U64(0x0000008000000000)) |
| 1878 | | opD |= U64(0xffffff0000000000); |
| 1879 | | else |
| 1880 | | opD &= U64(0x000000ffffffffff); |
| 1881 | | |
| 1882 | | /* Take the absolute value and clean up */ |
| 1883 | | opD = (opD < 0) ? -opD : opD; |
| 1884 | | opD &= U64(0x000000ffffffffff); |
| 1885 | | |
| 1886 | | /* Reassign */ |
| 1887 | | *((UINT64*)D.addr) = opD; |
| 1888 | | |
| 1889 | | /* Special overflow case */ |
| 1890 | | if ((*p_accum) == U64(0x0000008000000000)) |
| 1891 | | *((UINT64*)D.addr) = U64(0x0000007fffffffff); |
| 1892 | | |
| 1893 | | /* S L E U N Z V C */ |
| 1894 | | /* * * * * * * * - */ |
| 1895 | | /* TODO: S, L, E, U */ |
| 1896 | | if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1897 | | if ((*((UINT64*)D.addr) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1898 | | if ((*p_accum) == U64(0x0000008000000000)) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 1899 | | |
| 1900 | | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1901 | | return 1; |
| 1902 | | } |
| 1903 | | |
| 1904 | | /* ROR : .... .... 0111 F010 : A-192 */ |
| 1905 | | static size_t dsp56k_op_ror(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1906 | | { |
| 1907 | | /* S L E U N Z V C */ |
| 1908 | | /* * * - - ? ? 0 ? */ |
| 1909 | | /* N - Set if bit 31 of the result is set. Cleared otherwise. */ |
| 1910 | | /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */ |
| 1911 | | /* C - Set if bit 16 of the source operand is set. Cleared otherwise. */ |
| 1912 | | return 0; |
| 1913 | | } |
| 1914 | | |
| 1915 | | /* ROL : .... .... 0111 F011 : A-190 */ |
| 1916 | | static size_t dsp56k_op_rol(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1917 | | { |
| 1918 | | /* S L E U N Z V C */ |
| 1919 | | /* * * - - ? ? 0 ? */ |
| 1920 | | /* N - Set if bit 31 of the result is set. Cleared otherwise. */ |
| 1921 | | /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */ |
| 1922 | | /* C - Set if bit 31 of the source operand is set. Cleared otherwise. */ |
| 1923 | | return 0; |
| 1924 | | } |
| 1925 | | |
| 1926 | | /* CMPM : .... .... 0111 FJJJ : A-66 */ |
| 1927 | | static size_t dsp56k_op_cmpm(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1928 | | { |
| 1929 | | INT64 absS; |
| 1930 | | INT64 absD; |
| 1931 | | INT64 absResult; |
| 1932 | | |
| 1933 | | typed_pointer S = {NULL, DT_BYTE}; |
| 1934 | | typed_pointer D = {NULL, DT_BYTE}; |
| 1935 | | |
| 1936 | | decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D); |
| 1937 | | |
| 1938 | | *p_accum = *((UINT64*)D.addr); |
| 1939 | | |
| 1940 | | /* Sign extend and get absolute value of the source */ |
| 1941 | | if (S.addr == &A || S.addr == &B) |
| 1942 | | { |
| 1943 | | absS = *((UINT64*)S.addr); |
| 1944 | | if (absS & U64(0x0000008000000000)) |
| 1945 | | absS |= U64(0xffffff8000000000); |
| 1946 | | } |
| 1947 | | else |
| 1948 | | { |
| 1949 | | absS = (*((UINT16*)S.addr)) << 16; |
| 1950 | | if (absS & U64(0x0000000080000000)) |
| 1951 | | absS |= U64(0xffffffff80000000); |
| 1952 | | } |
| 1953 | | absS = (absS < 0) ? -absS : absS; |
| 1954 | | |
| 1955 | | /* Sign extend and get absolute value of the destination */ |
| 1956 | | if (D.addr == &A || D.addr == &B) |
| 1957 | | { |
| 1958 | | absD = *((UINT64*)D.addr); |
| 1959 | | if (absD & U64(0x0000008000000000)) |
| 1960 | | absD |= U64(0xffffff8000000000); |
| 1961 | | } |
| 1962 | | else |
| 1963 | | { |
| 1964 | | absD = (*((UINT16*)D.addr)) << 16; |
| 1965 | | if (absS & U64(0x0000000080000000)) |
| 1966 | | absS |= U64(0xffffffff80000000); |
| 1967 | | } |
| 1968 | | absD = (absD < 0) ? -absD : absD; |
| 1969 | | |
| 1970 | | /* Compare */ |
| 1971 | | absResult = absD - absS; |
| 1972 | | |
| 1973 | | d_register->addr = D.addr; |
| 1974 | | d_register->data_type = D.data_type; |
| 1975 | | |
| 1976 | | /* S L E U N Z V C */ |
| 1977 | | /* * * * * * * * * */ |
| 1978 | | /* TODO: S, L, E, U */ |
| 1979 | | if ( (absResult) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1980 | | if (((absResult) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1981 | | if ( (absResult & U64(0xffffff0000000000)) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 1982 | | if ( (absResult & U64(0xffffff0000000000)) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1983 | | |
| 1984 | | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 1985 | | return 1; |
| 1986 | | } |
| 1987 | | |
| 1988 | | /* MPY : .... .... 1k00 FQQQ : A-160 -- CONFIRMED TYPO IN DOCS (HHHH vs HHHW) */ |
| 1989 | | static size_t dsp56k_op_mpy(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1990 | | { |
| 1991 | | UINT16 k = 0; |
| 1992 | | INT64 result = 0; |
| 1993 | | |
| 1994 | | INT32 s1 = 0; |
| 1995 | | INT32 s2 = 0; |
| 1996 | | |
| 1997 | | void* D = NULL; |
| 1998 | | void* S1 = NULL; |
| 1999 | | void* S2 = NULL; |
| 2000 | | |
| 2001 | | decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D); |
| 2002 | | |
| 2003 | | k = BITS(op_byte,0x0040); |
| 2004 | | |
| 2005 | | /* Cast both values as being signed */ |
| 2006 | | s1 = *((INT16*)S1); |
| 2007 | | s2 = *((INT16*)S2); |
| 2008 | | |
| 2009 | | /* Fixed-point 2's complement multiplication requires a shift */ |
| 2010 | | result = (s1 * s2) << 1; |
| 2011 | | |
| 2012 | | /* Negate the product if necessary */ |
| 2013 | | if (k) |
| 2014 | | result *= -1; |
| 2015 | | |
| 2016 | | (*((UINT64*)D)) = result & U64(0x000000ffffffffff); |
| 2017 | | |
| 2018 | | /* S L E U N Z V C */ |
| 2019 | | /* * * * * * * * - */ |
| 2020 | | /* TODO: S, L, E, V */ |
| 2021 | | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2022 | | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2023 | | |
| 2024 | | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 2025 | | return 1; |
| 2026 | | } |
| 2027 | | |
| 2028 | | /* MPYR : .... .... 1k01 FQQQ : A-162 */ |
| 2029 | | static size_t dsp56k_op_mpyr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 2030 | | { |
| 2031 | | /* S L E U N Z V C */ |
| 2032 | | /* * * * * * * * - */ |
| 2033 | | return 0; |
| 2034 | | } |
| 2035 | | |
| 2036 | | /* MAC : .... .... 1k10 FQQQ : A-122 */ |
| 2037 | | static size_t dsp56k_op_mac(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 2038 | | { |
| 2039 | | UINT16 k = 0; |
| 2040 | | INT64 opD = 0; |
| 2041 | | INT64 result = 0; |
| 2042 | | |
| 2043 | | INT32 s1 = 0; |
| 2044 | | INT32 s2 = 0; |
| 2045 | | |
| 2046 | | void* D = NULL; |
| 2047 | | void* S1 = NULL; |
| 2048 | | void* S2 = NULL; |
| 2049 | | |
| 2050 | | decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D); |
| 2051 | | |
| 2052 | | k = BITS(op_byte,0x0040); |
| 2053 | | |
| 2054 | | /* Cast both values as being signed */ |
| 2055 | | s1 = *((INT16*)S1); |
| 2056 | | s2 = *((INT16*)S2); |
| 2057 | | |
| 2058 | | /* Fixed-point 2's complement multiplication requires a shift */ |
| 2059 | | result = (s1 * s2) << 1; |
| 2060 | | |
| 2061 | | /* Sign extend D into a temp variable */ |
| 2062 | | opD = (*((UINT64*)D)); |
| 2063 | | if (opD & U64(0x0000008000000000)) |
| 2064 | | opD |= U64(0xffffff0000000000); |
| 2065 | | else |
| 2066 | | opD &= U64(0x000000ffffffffff); |
| 2067 | | |
| 2068 | | /* Negate if necessary */ |
| 2069 | | if (k) |
| 2070 | | result *= -1; |
| 2071 | | |
| 2072 | | /* Accumulate */ |
| 2073 | | opD += result; |
| 2074 | | |
| 2075 | | /* And out the bits that don't live in the register */ |
| 2076 | | opD &= U64(0x000000ffffffffff); |
| 2077 | | |
| 2078 | | (*((UINT64*)D)) = (UINT64)opD; |
| 2079 | | |
| 2080 | | /* For the parallel move */ |
| 2081 | | d_register->addr = D; |
| 2082 | | d_register->data_type = DT_LONG_WORD; |
| 2083 | | |
| 2084 | | /* S L E U N Z V C */ |
| 2085 | | /* * * * * * * * - */ |
| 2086 | | /* TODO: S, L, E, V */ |
| 2087 | | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2088 | | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2089 | | |
| 2090 | | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 2091 | | return 1; |
| 2092 | | } |
| 2093 | | |
| 2094 | | /* MACR : .... .... 1k11 FQQQ : A-124 -- DRAMA - rr vs xx (805) */ |
| 2095 | | static size_t dsp56k_op_macr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 2096 | | { |
| 2097 | | UINT16 k = 0; |
| 2098 | | INT64 opD = 0; |
| 2099 | | INT64 result = 0; |
| 2100 | | |
| 2101 | | INT32 s1 = 0; |
| 2102 | | INT32 s2 = 0; |
| 2103 | | |
| 2104 | | void* D = NULL; |
| 2105 | | void* S1 = NULL; |
| 2106 | | void* S2 = NULL; |
| 2107 | | |
| 2108 | | decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D); |
| 2109 | | |
| 2110 | | k = BITS(op_byte,0x0040); |
| 2111 | | |
| 2112 | | /* Cast both values as being signed */ |
| 2113 | | s1 = *((INT16*)S1); |
| 2114 | | s2 = *((INT16*)S2); |
| 2115 | | |
| 2116 | | /* Fixed-point 2's complement multiplication requires a shift */ |
| 2117 | | result = (s1 * s2) << 1; |
| 2118 | | |
| 2119 | | /* Sign extend D into a temp variable */ |
| 2120 | | opD = (*((UINT64*)D)); |
| 2121 | | if (opD & U64(0x0000008000000000)) |
| 2122 | | opD |= U64(0xffffff0000000000); |
| 2123 | | else |
| 2124 | | opD &= U64(0x000000ffffffffff); |
| 2125 | | |
| 2126 | | /* Negate if necessary */ |
| 2127 | | if (k) |
| 2128 | | result *= -1; |
| 2129 | | |
| 2130 | | /* Accumulate */ |
| 2131 | | opD += result; |
| 2132 | | |
| 2133 | | /* Round the result */ |
| 2134 | | /* WARNING : ROUNDING NOT FULLY IMPLEMENTED YET! */ |
| 2135 | | if ((opD & U64(0x000000000000ffff)) >= 0x8000) |
| 2136 | | opD += U64(0x0000000000010000); |
| 2137 | | |
| 2138 | | opD &= U64(0x000000ffffff0000); |
| 2139 | | |
| 2140 | | /* And out the bits that don't live in the register */ |
| 2141 | | opD &= U64(0x000000ffffffffff); |
| 2142 | | |
| 2143 | | /* Store the result */ |
| 2144 | | (*((UINT64*)D)) = (UINT64)opD; |
| 2145 | | |
| 2146 | | /* For the parallel move */ |
| 2147 | | d_register->addr = D; |
| 2148 | | d_register->data_type = DT_LONG_WORD; |
| 2149 | | |
| 2150 | | /* S L E U N Z V C */ |
| 2151 | | /* * * * * * * * - */ |
| 2152 | | /* TODO: S, L, E, V */ |
| 2153 | | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2154 | | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2155 | | |
| 2156 | | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 2157 | | return 1; |
| 2158 | | } |
| 2159 | | |
| 2160 | | |
| 2161 | | /******************************/ |
| 2162 | | /* Remaining non-parallel ops */ |
| 2163 | | /******************************/ |
| 2164 | | |
| 2165 | | /* ADC : 0001 0101 0000 F01J : A-20 */ |
| 2166 | | static size_t dsp56k_op_adc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2167 | | { |
| 2168 | | /* S L E U N Z V C */ |
| 2169 | | /* - * * * * * * * */ |
| 2170 | | return 0; |
| 2171 | | } |
| 2172 | | |
| 2173 | | /* ANDI : 0001 1EE0 iiii iiii : A-26 */ |
| 2174 | | static size_t dsp56k_op_andi(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2175 | | { |
| 2176 | | UINT16 immediate = BITS(op,0x00ff); |
| 2177 | | |
| 2178 | | /* There is not currently a good way to refer to CCR or MR. Explicitly decode here. */ |
| 2179 | | switch(BITS(op,0x0600)) |
| 2180 | | { |
| 2181 | | case 0x01: /* MR */ |
| 2182 | | SR &= ((immediate << 8) | 0x00ff); |
| 2183 | | break; |
| 2184 | | |
| 2185 | | case 0x02: /* CCR */ |
| 2186 | | SR &= (immediate | 0xff00); |
| 2187 | | break; |
| 2188 | | |
| 2189 | | case 0x03: /* OMR */ |
| 2190 | | OMR &= (UINT8)(immediate); |
| 2191 | | break; |
| 2192 | | |
| 2193 | | default: |
| 2194 | | fatalerror("DSP56k - BAD EE value in andi operation\n") ; |
| 2195 | | } |
| 2196 | | |
| 2197 | | /* S L E U N Z V C */ |
| 2198 | | /* - ? ? ? ? ? ? ? */ |
| 2199 | | /* All ? bits - Cleared if the corresponding bit in the immediate data is cleared and if the operand |
| 2200 | | is the CCR. Not affected otherwise. */ |
| 2201 | | cycles += 2; |
| 2202 | | return 1; |
| 2203 | | } |
| 2204 | | |
| 2205 | | /* ASL4 : 0001 0101 0011 F001 : A-30 */ |
| 2206 | | static size_t dsp56k_op_asl4(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2207 | | { |
| 2208 | | UINT64 p_accum = 0; |
| 2209 | | typed_pointer D = {NULL, DT_BYTE}; |
| 2210 | | decode_F_table(cpustate, BITS(op,0x0008), &D); |
| 2211 | | |
| 2212 | | p_accum = *((UINT64*)D.addr); |
| 2213 | | |
| 2214 | | *((UINT64*)D.addr) = (*((UINT64*)D.addr)) << 4; |
| 2215 | | *((UINT64*)D.addr) = (*((UINT64*)D.addr)) & U64(0x000000ffffffffff); |
| 2216 | | |
| 2217 | | /* S L E U N Z V C */ |
| 2218 | | /* - ? * * * * ? ? */ |
| 2219 | | /* TODO: L, E, U */ |
| 2220 | | /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if bit 35 through 39 are |
| 2221 | | not the same. */ |
| 2222 | | /* C - Set if bit 36 of source operand is set. Cleared otherwise. */ |
| 2223 | | if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2224 | | if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2225 | | if ( (*((UINT64*)D.addr) & U64(0x000000ff00000000)) != (p_accum & U64(0x000000ff00000000)) ) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 2226 | | if (p_accum & U64(0x0000001000000000)) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 2227 | | |
| 2228 | | cycles += 2; |
| 2229 | | return 1; |
| 2230 | | } |
| 2231 | | |
| 2232 | | /* ASR4 : 0001 0101 0011 F000 : A-34 */ |
| 2233 | | static size_t dsp56k_op_asr4(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2234 | | { |
| 2235 | | UINT64 p_accum = 0; |
| 2236 | | typed_pointer D = {NULL, DT_BYTE}; |
| 2237 | | decode_F_table(cpustate, BITS(op,0x0008), &D); |
| 2238 | | |
| 2239 | | p_accum = *((UINT64*)D.addr); |
| 2240 | | |
| 2241 | | *((UINT64*)D.addr) = (*((UINT64*)D.addr)) >> 4; |
| 2242 | | *((UINT64*)D.addr) = (*((UINT64*)D.addr)) & U64(0x000000ffffffffff); |
| 2243 | | |
| 2244 | | /* The top 4 bits become the old bit 39 */ |
| 2245 | | if (p_accum & U64(0x0000008000000000)) |
| 2246 | | *((UINT64*)D.addr) |= U64(0x000000f000000000); |
| 2247 | | else |
| 2248 | | *((UINT64*)D.addr) &= (~U64(0x000000f000000000)); |
| 2249 | | |
| 2250 | | /* S L E U N Z V C */ |
| 2251 | | /* - * * * * * 0 ? */ |
| 2252 | | /* TODO: E, U */ |
| 2253 | | /* C - Set if bit 3 of source operand is set. Cleared otherwise. */ |
| 2254 | | if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2255 | | if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2256 | | DSP56K_V_CLEAR(); |
| 2257 | | if (p_accum & U64(0x0000000000000008)) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 2258 | | |
| 2259 | | cycles += 2; |
| 2260 | | return 1; |
| 2261 | | } |
| 2262 | | |
| 2263 | | /* ASR16 : 0001 0101 0111 F000 : A-36 */ |
| 2264 | | static size_t dsp56k_op_asr16(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2265 | | { |
| 2266 | | UINT64 backupVal; |
| 2267 | | typed_pointer D = {NULL, DT_BYTE}; |
| 2268 | | |
| 2269 | | decode_F_table(cpustate, BITS(op,0x0008), &D); |
| 2270 | | |
| 2271 | | backupVal = *((UINT64*)D.addr); |
| 2272 | | |
| 2273 | | *((UINT64*)D.addr) = *((UINT64*)D.addr) >> 16; |
| 2274 | | |
| 2275 | | if(backupVal & U64(0x0000008000000000)) |
| 2276 | | *((UINT64*)D.addr) |= U64(0x000000ffff000000); |
| 2277 | | else |
| 2278 | | *((UINT64*)D.addr) &= U64(0x0000000000ffffff); |
| 2279 | | |
| 2280 | | /* S L E U N Z V C */ |
| 2281 | | /* - * * * * * 0 ? */ |
| 2282 | | /* TODO: E, U */ |
| 2283 | | if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2284 | | if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2285 | | DSP56K_V_CLEAR(); |
| 2286 | | if (backupVal & U64(0x0000000000008000)) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 2287 | | |
| 2288 | | cycles += 2; |
| 2289 | | return 1; |
| 2290 | | } |
| 2291 | | |
| 2292 | | /* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */ |
| 2293 | | /* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */ |
| 2294 | | /* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */ |
| 2295 | | /* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */ |
| 2296 | | /* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */ |
| 2297 | | static size_t dsp56k_op_bfop(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2298 | | { |
| 2299 | | UINT16 workAddr = 0x0000; |
| 2300 | | UINT16 workingWord = 0x0000; |
| 2301 | | UINT16 previousValue = 0x0000; |
| 2302 | | typed_pointer tempTP = { NULL, DT_BYTE }; |
| 2303 | | |
| 2304 | | UINT16 iVal = op2 & 0x00ff; |
| 2305 | | decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal); |
| 2306 | | |
| 2307 | | workAddr = assemble_address_from_Pppppp_table(cpustate, BITS(op,0x0020), BITS(op,0x001f)); |
| 2308 | | previousValue = cpustate->data->read_word(ADDRESS(workAddr)); |
| 2309 | | workingWord = previousValue; |
| 2310 | | |
| 2311 | | switch(BITS(op2, 0x1f00)) |
| 2312 | | { |
| 2313 | | case 0x12: /* BFCHG */ |
| 2314 | | workingWord ^= iVal; |
| 2315 | | break; |
| 2316 | | case 0x04: /* BFCLR */ |
| 2317 | | workingWord = workingWord & (~iVal); |
| 2318 | | break; |
| 2319 | | case 0x18: /* BFSET */ |
| 2320 | | workingWord = workingWord | iVal; |
| 2321 | | break; |
| 2322 | | case 0x10: /* BFTSTH */ |
| 2323 | | /* Just the test below */ |
| 2324 | | break; |
| 2325 | | case 0x00: /* BFTSTL */ |
| 2326 | | /* Just the test below */ |
| 2327 | | break; |
| 2328 | | } |
| 2329 | | |
| 2330 | | tempTP.addr = &workingWord; |
| 2331 | | tempTP.data_type = DT_WORD; |
| 2332 | | SetDataMemoryValue(cpustate, tempTP, ADDRESS(workAddr)); |
| 2333 | | |
| 2334 | | /* S L E U N Z V C */ |
| 2335 | | /* - * - - - - - ? */ |
| 2336 | | /* TODO: L */ |
| 2337 | | switch(BITS(op2, 0x1f00)) |
| 2338 | | { |
| 2339 | | case 0x12: /* BFCHG */ |
| 2340 | | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2341 | | case 0x04: /* BFCLR */ |
| 2342 | | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2343 | | case 0x18: /* BFSET */ |
| 2344 | | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2345 | | case 0x10: /* BFTSTH */ |
| 2346 | | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2347 | | case 0x00: /* BFTSTL */ |
| 2348 | | if ((iVal & previousValue) == 0x0000) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2349 | | } |
| 2350 | | |
| 2351 | | cycles += 4; /* TODO: + mvb oscillator clock cycles */ |
| 2352 | | return 2; |
| 2353 | | } |
| 2354 | | |
| 2355 | | /* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */ |
| 2356 | | /* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */ |
| 2357 | | /* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */ |
| 2358 | | /* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */ |
| 2359 | | /* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */ |
| 2360 | | static size_t dsp56k_op_bfop_1(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2361 | | { |
| 2362 | | UINT16 workAddr = 0x0000; |
| 2363 | | UINT16 workingWord = 0x0000; |
| 2364 | | UINT16 previousValue = 0x0000; |
| 2365 | | typed_pointer R = { NULL, DT_BYTE }; |
| 2366 | | typed_pointer tempTP = { NULL, DT_BYTE }; |
| 2367 | | |
| 2368 | | UINT16 iVal = op2 & 0x00ff; |
| 2369 | | decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal); |
| 2370 | | |
| 2371 | | decode_RR_table(cpustate, BITS(op,0x0003), &R); |
| 2372 | | |
| 2373 | | workAddr = *((UINT16*)R.addr); |
| 2374 | | previousValue = cpustate->data->read_word(ADDRESS(workAddr)); |
| 2375 | | workingWord = previousValue; |
| 2376 | | |
| 2377 | | switch(BITS(op2, 0x1f00)) |
| 2378 | | { |
| 2379 | | case 0x12: /* BFCHG */ |
| 2380 | | workingWord ^= iVal; |
| 2381 | | break; |
| 2382 | | case 0x04: /* BFCLR */ |
| 2383 | | workingWord = workingWord & (~iVal); |
| 2384 | | break; |
| 2385 | | case 0x18: /* BFSET */ |
| 2386 | | workingWord = workingWord | iVal; |
| 2387 | | break; |
| 2388 | | case 0x10: /* BFTSTH */ |
| 2389 | | /* Just the test below */ |
| 2390 | | break; |
| 2391 | | case 0x00: /* BFTSTL */ |
| 2392 | | /* Just the test below */ |
| 2393 | | break; |
| 2394 | | } |
| 2395 | | |
| 2396 | | tempTP.addr = &workingWord; |
| 2397 | | tempTP.data_type = DT_WORD; |
| 2398 | | SetDataMemoryValue(cpustate, tempTP, ADDRESS(workAddr)); |
| 2399 | | |
| 2400 | | /* S L E U N Z V C */ |
| 2401 | | /* - * - - - - - ? */ |
| 2402 | | /* TODO: L */ |
| 2403 | | switch(BITS(op2, 0x1f00)) |
| 2404 | | { |
| 2405 | | case 0x12: /* BFCHG */ |
| 2406 | | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2407 | | case 0x04: /* BFCLR */ |
| 2408 | | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2409 | | case 0x18: /* BFSET */ |
| 2410 | | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2411 | | case 0x10: /* BFTSTH */ |
| 2412 | | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2413 | | case 0x00: /* BFTSTL */ |
| 2414 | | if ((iVal & previousValue) == 0x0000) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2415 | | } |
| 2416 | | |
| 2417 | | cycles += 4; /* TODO: + mvb oscillator clock cycles */ |
| 2418 | | return 2; |
| 2419 | | } |
| 2420 | | |
| 2421 | | /* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */ |
| 2422 | | /* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */ |
| 2423 | | /* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */ |
| 2424 | | /* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */ |
| 2425 | | /* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */ |
| 2426 | | static size_t dsp56k_op_bfop_2(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2427 | | { |
| 2428 | | UINT16 workingWord = 0x0000; |
| 2429 | | UINT16 previousValue = 0x0000; |
| 2430 | | |
| 2431 | | UINT16 iVal = op2 & 0x00ff; |
| 2432 | | typed_pointer S = { NULL, DT_BYTE }; |
| 2433 | | |
| 2434 | | decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal); |
| 2435 | | decode_DDDDD_table(cpustate, BITS(op,0x001f), &S); |
| 2436 | | |
| 2437 | | /* A & B are special */ |
| 2438 | | if (S.data_type == DT_LONG_WORD) |
| 2439 | | previousValue = ((PAIR64*)S.addr)->w.h; |
| 2440 | | else |
| 2441 | | previousValue = *((UINT16*)S.addr); |
| 2442 | | |
| 2443 | | workingWord = previousValue; |
| 2444 | | |
| 2445 | | switch(BITS(op2, 0x1f00)) |
| 2446 | | { |
| 2447 | | case 0x12: /* BFCHG */ |
| 2448 | | workingWord ^= iVal; |
| 2449 | | break; |
| 2450 | | case 0x04: /* BFCLR */ |
| 2451 | | workingWord = workingWord & (~iVal); |
| 2452 | | break; |
| 2453 | | case 0x18: /* BFSET */ |
| 2454 | | workingWord = workingWord | iVal; |
| 2455 | | break; |
| 2456 | | case 0x10: /* BFTSTH */ |
| 2457 | | /* Just the test below */ |
| 2458 | | break; |
| 2459 | | case 0x00: /* BFTSTL */ |
| 2460 | | /* Just the test below */ |
| 2461 | | break; |
| 2462 | | } |
| 2463 | | |
| 2464 | | /* Put the data back where it belongs (A & B are special) */ |
| 2465 | | if (S.data_type == DT_LONG_WORD) |
| 2466 | | ((PAIR64*)S.addr)->w.h = workingWord; |
| 2467 | | else |
| 2468 | | *((UINT16*)S.addr) = workingWord; |
| 2469 | | |
| 2470 | | /* S L E U N Z V C */ |
| 2471 | | /* - * - - - - - ? */ |
| 2472 | | /* TODO: L */ |
| 2473 | | switch(BITS(op2, 0x1f00)) |
| 2474 | | { |
| 2475 | | case 0x12: /* BFCHG */ |
| 2476 | | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2477 | | case 0x04: /* BFCLR */ |
| 2478 | | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2479 | | case 0x18: /* BFSET */ |
| 2480 | | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2481 | | case 0x10: /* BFTSTH */ |
| 2482 | | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2483 | | case 0x00: /* BFTSTL */ |
| 2484 | | if ((iVal & previousValue) == 0x0000) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2485 | | } |
| 2486 | | |
| 2487 | | cycles += 4; /* TODO: + mvb oscillator clock cycles */ |
| 2488 | | return 2; |
| 2489 | | } |
| 2490 | | |
| 2491 | | /* Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 */ |
| 2492 | | static size_t dsp56k_op_bcc(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2493 | | { |
| 2494 | | int shouldBranch = decode_cccc_table(cpustate, BITS(op,0x000f)); |
| 2495 | | |
| 2496 | | if (shouldBranch) |
| 2497 | | { |
| 2498 | | INT16 offset = (INT16)op2; |
| 2499 | | |
| 2500 | | PC += 2; |
| 2501 | | |
| 2502 | | cpustate->ppc = PC; |
| 2503 | | PC += offset; |
| 2504 | | |
| 2505 | | cycles += 4; |
| 2506 | | return 0; |
| 2507 | | } |
| 2508 | | else |
| 2509 | | { |
| 2510 | | cycles += 4; |
| 2511 | | return 2; |
| 2512 | | } |
| 2513 | | |
| 2514 | | /* S L E U N Z V C */ |
| 2515 | | /* - - - - - - - - */ |
| 2516 | | return 0; |
| 2517 | | } |
| 2518 | | |
| 2519 | | /* Bcc : 0010 11cc ccee eeee : A-48 */ |
| 2520 | | static size_t dsp56k_op_bcc_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2521 | | { |
| 2522 | | int shouldBranch = decode_cccc_table(cpustate, BITS(op,0x03c0)); |
| 2523 | | |
| 2524 | | if (shouldBranch) |
| 2525 | | { |
| 2526 | | INT16 offset = (INT16)assemble_address_from_6bit_signed_relative_short_address(cpustate, BITS(op,0x003f)); |
| 2527 | | |
| 2528 | | PC += 1; |
| 2529 | | |
| 2530 | | cpustate->ppc = PC; |
| 2531 | | PC += offset; |
| 2532 | | |
| 2533 | | cycles += 4; |
| 2534 | | return 0; |
| 2535 | | } |
| 2536 | | else |
| 2537 | | { |
| 2538 | | cycles += 4; |
| 2539 | | return 1; |
| 2540 | | } |
| 2541 | | |
| 2542 | | /* S L E U N Z V C */ |
| 2543 | | /* - - - - - - - - */ |
| 2544 | | return 0; |
| 2545 | | } |
| 2546 | | |
| 2547 | | /* Bcc : 0000 0111 RR10 cccc : A-48 */ |
| 2548 | | static size_t dsp56k_op_bcc_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2549 | | { |
| 2550 | | /* S L E U N Z V C */ |
| 2551 | | /* - - - - - - - - */ |
| 2552 | | return 0; |
| 2553 | | } |
| 2554 | | |
| 2555 | | /* BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 */ |
| 2556 | | static size_t dsp56k_op_bra(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2557 | | { |
| 2558 | | /* S L E U N Z V C */ |
| 2559 | | /* - - - - - - - - */ |
| 2560 | | return 0; |
| 2561 | | } |
| 2562 | | |
| 2563 | | /* BRA : 0000 1011 aaaa aaaa : A-50 */ |
| 2564 | | static size_t dsp56k_op_bra_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2565 | | { |
| 2566 | | /* 8 bit immediate, relative offset */ |
| 2567 | | INT8 branchOffset = (INT8)BITS(op,0x00ff); |
| 2568 | | |
| 2569 | | /* "The PC Contains the address of the next instruction" */ |
| 2570 | | PC += 1; |
| 2571 | | |
| 2572 | | /* Jump */ |
| 2573 | | cpustate->ppc = PC; |
| 2574 | | PC += branchOffset; |
| 2575 | | |
| 2576 | | /* S L E U N Z V C */ |
| 2577 | | /* - - - - - - - - */ |
| 2578 | | cycles += 4; /* TODO: + jx oscillator clock cycles */ |
| 2579 | | return 0; |
| 2580 | | } |
| 2581 | | |
| 2582 | | /* BRA : 0000 0001 0010 11RR : A-50 */ |
| 2583 | | static size_t dsp56k_op_bra_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2584 | | { |
| 2585 | | /* S L E U N Z V C */ |
| 2586 | | /* - - - - - - - - */ |
| 2587 | | return 0; |
| 2588 | | } |
| 2589 | | |
| 2590 | | /* BRKcc : 0000 0001 0001 cccc : A-52 */ |
| 2591 | | static size_t dsp56k_op_brkcc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2592 | | { |
| 2593 | | int shouldBreak = decode_cccc_table(cpustate, BITS(op,0x000f)); |
| 2594 | | |
| 2595 | | if (shouldBreak) |
| 2596 | | { |
| 2597 | | /* TODO: I think this PC = LA thing is off-by-1, but it's working this way because its consistently so */ |
| 2598 | | cpustate->ppc = PC; |
| 2599 | | PC = LA; |
| 2600 | | |
| 2601 | | SR = SSL; /* TODO: A-83. I believe only the Loop Flag and Forever Flag come back here. */ |
| 2602 | | SP--; |
| 2603 | | |
| 2604 | | LA = SSH; |
| 2605 | | LC = SSL; |
| 2606 | | SP--; |
| 2607 | | |
| 2608 | | cycles += 8; |
| 2609 | | return 0; |
| 2610 | | } |
| 2611 | | else |
| 2612 | | { |
| 2613 | | cycles += 2; |
| 2614 | | return 1; |
| 2615 | | } |
| 2616 | | |
| 2617 | | /* S L E U N Z V C */ |
| 2618 | | /* - - - - - - - - */ |
| 2619 | | return 0; |
| 2620 | | } |
| 2621 | | |
| 2622 | | /* BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 */ |
| 2623 | | static size_t dsp56k_op_bscc(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2624 | | { |
| 2625 | | int shouldBranch = decode_cccc_table(cpustate, BITS(op,0x000f)); |
| 2626 | | |
| 2627 | | if (shouldBranch) |
| 2628 | | { |
| 2629 | | /* The PC Contains the address of the next instruction */ |
| 2630 | | PC += 2; |
| 2631 | | |
| 2632 | | /* Push */ |
| 2633 | | SP++; |
| 2634 | | SSH = PC; |
| 2635 | | SSL = SR; |
| 2636 | | |
| 2637 | | /* Change */ |
| 2638 | | cpustate->ppc = PC; |
| 2639 | | PC = PC + (INT16)op2; |
| 2640 | | |
| 2641 | | /* S L E U N Z V C */ |
| 2642 | | /* - - - - - - - - */ |
| 2643 | | cycles += 4; /* TODO: + jx oscillator clock cycles */ |
| 2644 | | return 0; |
| 2645 | | } |
| 2646 | | |
| 2647 | | /* S L E U N Z V C */ |
| 2648 | | /* - - - - - - - - */ |
| 2649 | | cycles += 4; /* TODO: + jx oscillator clock cycles */ |
| 2650 | | return 2; |
| 2651 | | } |
| 2652 | | |
| 2653 | | /* BScc : 0000 0111 RR00 cccc : A-54 */ |
| 2654 | | static size_t dsp56k_op_bscc_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2655 | | { |
| 2656 | | /* S L E U N Z V C */ |
| 2657 | | /* - - - - - - - - */ |
| 2658 | | return 0; |
| 2659 | | } |
| 2660 | | |
| 2661 | | /* BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 */ |
| 2662 | | static size_t dsp56k_op_bsr(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2663 | | { |
| 2664 | | /* The PC Contains the address of the next instruction */ |
| 2665 | | PC += 2; |
| 2666 | | |
| 2667 | | /* Push */ |
| 2668 | | SP++; |
| 2669 | | SSH = PC; |
| 2670 | | SSL = SR; |
| 2671 | | |
| 2672 | | /* Change */ |
| 2673 | | cpustate->ppc = PC; |
| 2674 | | PC = PC + (INT16)op2; |
| 2675 | | |
| 2676 | | /* S L E U N Z V C */ |
| 2677 | | /* - - - - - - - - */ |
| 2678 | | cycles += 4; /* TODO: + jx oscillator clock cycles */ |
| 2679 | | return 0; |
| 2680 | | } |
| 2681 | | |
| 2682 | | /* BSR : 0000 0001 0010 10RR : A-56 */ |
| 2683 | | static size_t dsp56k_op_bsr_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2684 | | { |
| 2685 | | /* S L E U N Z V C */ |
| 2686 | | /* - - - - - - - - */ |
| 2687 | | return 0; |
| 2688 | | } |
| 2689 | | |
| 2690 | | /* CHKAAU : 0000 0000 0000 0100 : A-58 */ |
| 2691 | | static size_t dsp56k_op_chkaau(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2692 | | { |
| 2693 | | /* S L E U N Z V C */ |
| 2694 | | /* - - - - ? ? ? - */ |
| 2695 | | /* V - Set if the result of the last address ALU update performed a modulo wrap. Cleared if |
| 2696 | | result of the last address ALU did not perform a modulo wrap.*/ |
| 2697 | | /* Z - Set if the result of the last address ALU update is 0. Cleared if the result of the last |
| 2698 | | address ALU is positive. */ |
| 2699 | | /* N - Set if the result of the last address ALU update is negative. Cleared if the result of the |
| 2700 | | last address ALU is positive. */ |
| 2701 | | return 0; |
| 2702 | | } |
| 2703 | | |
| 2704 | | /* DEBUG : 0000 0000 0000 0001 : A-68 */ |
| 2705 | | static size_t dsp56k_op_debug(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2706 | | { |
| 2707 | | /* S L E U N Z V C */ |
| 2708 | | /* - - - - - - - - */ |
| 2709 | | return 0; |
| 2710 | | } |
| 2711 | | |
| 2712 | | /* DEBUGcc : 0000 0000 0101 cccc : A-70 */ |
| 2713 | | static size_t dsp56k_op_debugcc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2714 | | { |
| 2715 | | /* S L E U N Z V C */ |
| 2716 | | /* - - - - - - - - */ |
| 2717 | | return 0; |
| 2718 | | } |
| 2719 | | |
| 2720 | | /* DIV : 0001 0101 0--0 F1DD : A-76 */ |
| 2721 | | /* WARNING : DOCS SAY THERE IS A PARALLEL MOVE HERE !!! */ |
| 2722 | | static size_t dsp56k_op_div(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2723 | | { |
| 2724 | | /* WARNING : THIS DOES NOT WORK. IT DOESN'T EVEN TRY !!! */ |
| 2725 | | typed_pointer S = {NULL, DT_BYTE}; |
| 2726 | | typed_pointer D = {NULL, DT_BYTE}; |
| 2727 | | |
| 2728 | | decode_DDF_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S, &D); |
| 2729 | | |
| 2730 | | /* S L E U N Z V C */ |
| 2731 | | /* - * - - - - ? ? */ |
| 2732 | | /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significantst |
| 2733 | | bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */ |
| 2734 | | /* C - Set if bit 39 of the result is cleared. Cleared otherwise. */ |
| 2735 | | cycles += 2; |
| 2736 | | return 1; |
| 2737 | | } |
| 2738 | | |
| 2739 | | /* DMAC : 0001 0101 10s1 FsQQ : A-80 */ |
| 2740 | | static size_t dsp56k_op_dmac(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2741 | | { |
| 2742 | | UINT8 ss = 0; |
| 2743 | | INT64 result = 0; |
| 2744 | | |
| 2745 | | void* D = NULL; |
| 2746 | | void* S1 = NULL; |
| 2747 | | void* S2 = NULL; |
| 2748 | | |
| 2749 | | decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D); |
| 2750 | | |
| 2751 | | ss = BITS(op,0x0024); |
| 2752 | | |
| 2753 | | /* Fixed-point 2's complement multiplication requires a shift */ |
| 2754 | | if (ss == 0x00 || ss == 0x01) |
| 2755 | | { |
| 2756 | | /* Signed * Signed */ |
| 2757 | | INT32 s1 = ((INT32)(*((UINT16*)S1))); |
| 2758 | | INT32 s2 = ((INT32)(*((UINT16*)S2))); |
| 2759 | | result = ( s1 * s2 ) << 1; |
| 2760 | | } |
| 2761 | | else if (ss == 0x2) |
| 2762 | | { |
| 2763 | | /* Signed * Unsigned */ |
| 2764 | | /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */ |
| 2765 | | INT32 s1 = ((INT32)(*((UINT16*)S1))); |
| 2766 | | INT32 s2 = (UINT32)(*((UINT16*)S2)); |
| 2767 | | result = ( s1 * s2 ) << 1; |
| 2768 | | } |
| 2769 | | else if (ss == 0x3) |
| 2770 | | { |
| 2771 | | /* Unsigned * Unsigned */ |
| 2772 | | UINT32 s1 = (UINT32)(*((UINT16*)S1)); |
| 2773 | | UINT32 s2 = (UINT32)(*((UINT16*)S2)); |
| 2774 | | result = ( s1 * s2 ) << 1; |
| 2775 | | } |
| 2776 | | |
| 2777 | | /* Shift right, then accumulate */ |
| 2778 | | (*((UINT64*)D)) = (*((UINT64*)D)) >> 16; |
| 2779 | | (*((UINT64*)D)) += result; |
| 2780 | | |
| 2781 | | /* S L E U N Z V C */ |
| 2782 | | /* - * * * * * * - */ |
| 2783 | | /* TODO: L, E, U, V */ |
| 2784 | | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2785 | | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2786 | | |
| 2787 | | cycles += 2; |
| 2788 | | return 1; |
| 2789 | | } |
| 2790 | | |
| 2791 | | /* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */ |
| 2792 | | static size_t dsp56k_op_do(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2793 | | { |
| 2794 | | /* S L E U N Z V C */ |
| 2795 | | /* - * - - - - - - */ |
| 2796 | | return 0; |
| 2797 | | } |
| 2798 | | |
| 2799 | | /* DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 */ |
| 2800 | | static size_t dsp56k_op_do_1(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2801 | | { |
| 2802 | | UINT8 retSize = 0; |
| 2803 | | UINT8 iValue = BITS(op,0x00ff); |
| 2804 | | |
| 2805 | | /* Don't execute if the loop counter == 0 */ |
| 2806 | | if (iValue != 0x00) |
| 2807 | | { |
| 2808 | | /* First instruction cycle */ |
| 2809 | | SP++; /* TODO: Should i really inc here first? */ |
| 2810 | | SSH = LA; |
| 2811 | | SSL = LC; |
| 2812 | | LC = (UINT16)iValue; |
| 2813 | | |
| 2814 | | |
| 2815 | | /* Second instruction cycle */ |
| 2816 | | SP++; /* TODO: See above */ |
| 2817 | | SSH = PC + 2; /* Keep these stack entries in 'word-based-index' space */ |
| 2818 | | SSL = SR; |
| 2819 | | LA = PC + 2 + op2; /* TODO: The docs subtract 1 from here? */ |
| 2820 | | |
| 2821 | | |
| 2822 | | /* Third instruction cycle */ |
| 2823 | | LF_bit_set(cpustate, 1); |
| 2824 | | |
| 2825 | | /* Undocumented, but it must be true to nest Dos in DoForevers */ |
| 2826 | | FV_bit_set(cpustate, 0); |
| 2827 | | |
| 2828 | | |
| 2829 | | /* S L E U N Z V C */ |
| 2830 | | /* - * - - - - - - */ |
| 2831 | | /* TODO : L */ |
| 2832 | | |
| 2833 | | cycles += 6; /* TODO: + mv oscillator cycles */ |
| 2834 | | retSize = 2; |
| 2835 | | } |
| 2836 | | else |
| 2837 | | { |
| 2838 | | /* Skip over the contents of the loop */ |
| 2839 | | cpustate->ppc = PC; |
| 2840 | | PC = PC + 2 + op2; |
| 2841 | | |
| 2842 | | cycles += 10; /* TODO: + mv oscillator cycles */ |
| 2843 | | retSize = 0; |
| 2844 | | } |
| 2845 | | |
| 2846 | | return retSize; |
| 2847 | | } |
| 2848 | | |
| 2849 | | /* DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 */ |
| 2850 | | static size_t dsp56k_op_do_2(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2851 | | { |
| 2852 | | UINT8 retSize = 0; |
| 2853 | | UINT16 lValue = 0x0000; |
| 2854 | | typed_pointer S = {NULL, DT_BYTE}; |
| 2855 | | decode_DDDDD_table(cpustate, BITS(op,0x001f), &S); |
| 2856 | | |
| 2857 | | /* TODO: Does not properly shift-limit sources A&B - Fix per the docs. */ |
| 2858 | | /* TODO: There are other cases besides A&B this code won't work. */ |
| 2859 | | if (S.addr == &A) lValue = *((UINT16*)(&A1)); |
| 2860 | | else if (S.addr == &B) lValue = *((UINT16*)(&B1)); |
| 2861 | | else lValue = *((UINT16*)S.addr); |
| 2862 | | |
| 2863 | | /* HACK */ |
| 2864 | | if (lValue >= 0xfff0) |
| 2865 | | { |
| 2866 | | logerror("Dsp56k : DO_2 operation changed %04x to 0000.\n", lValue); |
| 2867 | | lValue = 0x0000; |
| 2868 | | } |
| 2869 | | |
| 2870 | | /* TODO: Fix for special cased SP S */ |
| 2871 | | if (S.addr == &SP) |
| 2872 | | logerror("DSP56k: do with SP as the source not properly implemented yet.\n"); |
| 2873 | | |
| 2874 | | /* TODO: Fix for special cased SSSL S */ |
| 2875 | | if (S.addr == &SSL) |
| 2876 | | logerror("DSP56k: do with SP as the source not properly implemented yet.\n"); |
| 2877 | | |
| 2878 | | /* Don't execute if the loop counter == 0 */ |
| 2879 | | if (lValue != 0x00) |
| 2880 | | { |
| 2881 | | /* First instruction cycle */ |
| 2882 | | SP++; /* TODO: Should i really inc here first? */ |
| 2883 | | SSH = LA; |
| 2884 | | SSL = LC; |
| 2885 | | LC = (UINT16)lValue; |
| 2886 | | |
| 2887 | | |
| 2888 | | /* Second instruction cycle */ |
| 2889 | | SP++; /* TODO: See above */ |
| 2890 | | SSH = PC + 2; /* Keep these stack entries in 'word-based-index' space */ |
| 2891 | | SSL = SR; |
| 2892 | | LA = PC + 2 + op2; /* TODO: The docs subtract 1 from here? */ |
| 2893 | | |
| 2894 | | |
| 2895 | | /* Third instruction cycle */ |
| 2896 | | LF_bit_set(cpustate, 1); |
| 2897 | | |
| 2898 | | |
| 2899 | | /* S L E U N Z V C */ |
| 2900 | | /* - * - - - - - - */ |
| 2901 | | /* TODO : L */ |
| 2902 | | |
| 2903 | | cycles += 6; /* TODO: + mv oscillator cycles */ |
| 2904 | | retSize = 2; |
| 2905 | | } |
| 2906 | | else |
| 2907 | | { |
| 2908 | | /* Skip over the contents of the loop */ |
| 2909 | | cpustate->ppc = PC; |
| 2910 | | PC = PC + 2 + op2; |
| 2911 | | |
| 2912 | | cycles += 10; /* TODO: + mv oscillator cycles */ |
| 2913 | | retSize = 0; |
| 2914 | | } |
| 2915 | | |
| 2916 | | return retSize; |
| 2917 | | } |
| 2918 | | |
| 2919 | | /* DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 */ |
| 2920 | | static size_t dsp56k_op_doforever(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2921 | | { |
| 2922 | | /* First instruction cycle */ |
| 2923 | | SP++; |
| 2924 | | SSH = LA; |
| 2925 | | SSL = LC; |
| 2926 | | |
| 2927 | | /* Second instruction cycle */ |
| 2928 | | SP++; |
| 2929 | | SSH = PC + 2; |
| 2930 | | SSL = SR; |
| 2931 | | LA = PC + 2 + op2; |
| 2932 | | |
| 2933 | | /* Third instruction cycle */ |
| 2934 | | LF_bit_set(cpustate, 1); |
| 2935 | | FV_bit_set(cpustate, 1); |
| 2936 | | |
| 2937 | | /* S L E U N Z V C */ |
| 2938 | | /* - - - - - - - - */ |
| 2939 | | cycles += 6; |
| 2940 | | return 2; |
| 2941 | | } |
| 2942 | | |
| 2943 | | /* ENDDO : 0000 0000 0000 1001 : A-92 */ |
| 2944 | | static size_t dsp56k_op_enddo(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2945 | | { |
| 2946 | | /* S L E U N Z V C */ |
| 2947 | | /* - - - - - - - - */ |
| 2948 | | return 0; |
| 2949 | | } |
| 2950 | | |
| 2951 | | /* EXT : 0001 0101 0101 F010 : A-96 */ |
| 2952 | | static size_t dsp56k_op_ext(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2953 | | { |
| 2954 | | /* S L E U N Z V C */ |
| 2955 | | /* - * * * * * * - */ |
| 2956 | | return 0; |
| 2957 | | } |
| 2958 | | |
| 2959 | | /* ILLEGAL : 0000 0000 0000 1111 : A-98 */ |
| 2960 | | static size_t dsp56k_op_illegal(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2961 | | { |
| 2962 | | /* S L E U N Z V C */ |
| 2963 | | /* - - - - - - - - */ |
| 2964 | | return 0; |
| 2965 | | } |
| 2966 | | |
| 2967 | | /* IMAC : 0001 0101 1010 FQQQ : A-100 */ |
| 2968 | | static size_t dsp56k_op_imac(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2969 | | { |
| 2970 | | INT64 opD = 0; |
| 2971 | | INT64 result = 0; |
| 2972 | | |
| 2973 | | INT32 s1 = 0; |
| 2974 | | INT32 s2 = 0; |
| 2975 | | |
| 2976 | | void* D = NULL; |
| 2977 | | void* S1 = NULL; |
| 2978 | | void* S2 = NULL; |
| 2979 | | |
| 2980 | | decode_QQQF_table(cpustate, BITS(op,0x0007), BITS(op,0x0008), &S1, &S2, &D); |
| 2981 | | |
| 2982 | | /* Cast both values as being signed */ |
| 2983 | | s1 = *((INT16*)S1); |
| 2984 | | s2 = *((INT16*)S2); |
| 2985 | | |
| 2986 | | /* Integral multiply doesn't require the shift */ |
| 2987 | | result = (s1 * s2); |
| 2988 | | |
| 2989 | | /* Shift result 16 bits to the left before adding to destination */ |
| 2990 | | result = (result << 16) & 0xffff0000; |
| 2991 | | |
| 2992 | | /* Sign extend D into a temp variable */ |
| 2993 | | opD = (*((UINT64*)D)); |
| 2994 | | if (opD & U64(0x0000008000000000)) |
| 2995 | | opD |= U64(0xffffff0000000000); |
| 2996 | | else |
| 2997 | | opD &= U64(0x000000ffffffffff); |
| 2998 | | |
| 2999 | | /* Accumulate */ |
| 3000 | | opD += result; |
| 3001 | | |
| 3002 | | /* And out the bits that don't live in the register */ |
| 3003 | | opD &= U64(0x000000ffffffffff); |
| 3004 | | |
| 3005 | | (*((UINT64*)D)) = (UINT64)opD; |
| 3006 | | |
| 3007 | | /* S L E U N Z V C */ |
| 3008 | | /* - * ? ? * ? ? - */ |
| 3009 | | /* TODO: L */ |
| 3010 | | /* U,E - Will not be set correctly by this instruction*/ |
| 3011 | | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 3012 | | if ((*((UINT64*)D) & U64(0x000000ffffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 3013 | | DSP56K_V_CLEAR(); |
| 3014 | | |
| 3015 | | cycles += 2; |
| 3016 | | return 1; |
| 3017 | | } |
| 3018 | | |
| 3019 | | /* IMPY : 0001 0101 1000 FQQQ : A-102 */ |
| 3020 | | static size_t dsp56k_op_impy(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3021 | | { |
| 3022 | | /* S L E U N Z V C */ |
| 3023 | | /* - * ? ? * ? ? - */ |
| 3024 | | /* Z - Set if the 24 most significant bits of the destination result are all zeroes. */ |
| 3025 | | /* U,E - Will not be set correctly by this instruction*/ |
| 3026 | | /* V - Set to zero regardless of the overflow */ |
| 3027 | | return 0; |
| 3028 | | } |
| 3029 | | |
| 3030 | | /* Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 */ |
| 3031 | | static size_t dsp56k_op_jcc(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3032 | | { |
| 3033 | | /* S L E U N Z V C */ |
| 3034 | | /* - - - - - - - - */ |
| 3035 | | return 0; |
| 3036 | | } |
| 3037 | | |
| 3038 | | /* Jcc : 0000 0110 RR10 cccc : A-108 */ |
| 3039 | | static size_t dsp56k_op_jcc_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3040 | | { |
| 3041 | | /* S L E U N Z V C */ |
| 3042 | | /* - - - - - - - - */ |
| 3043 | | return 0; |
| 3044 | | } |
| 3045 | | |
| 3046 | | /* JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 */ |
| 3047 | | static size_t dsp56k_op_jmp(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3048 | | { |
| 3049 | | cpustate->ppc = PC; |
| 3050 | | PC = op2; |
| 3051 | | |
| 3052 | | /* S L E U N Z V C */ |
| 3053 | | /* - - - - - - - - */ |
| 3054 | | |
| 3055 | | cycles += 4; /* TODO: + jx */ |
| 3056 | | return 0; |
| 3057 | | } |
| 3058 | | |
| 3059 | | /* JMP : 0000 0001 0010 01RR : A-110 */ |
| 3060 | | static size_t dsp56k_op_jmp_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3061 | | { |
| 3062 | | typed_pointer R = { NULL, DT_BYTE }; |
| 3063 | | decode_RR_table(cpustate, BITS(op,0x0003), &R); |
| 3064 | | |
| 3065 | | cpustate->ppc = PC; |
| 3066 | | PC = *((UINT16*)R.addr); |
| 3067 | | |
| 3068 | | /* S L E U N Z V C */ |
| 3069 | | /* - - - - - - - - */ |
| 3070 | | |
| 3071 | | cycles += 4; /* TODO: + jx */ |
| 3072 | | return 0; |
| 3073 | | } |
| 3074 | | |
| 3075 | | /* JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 */ |
| 3076 | | static size_t dsp56k_op_jscc(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3077 | | { |
| 3078 | | int shouldJump = decode_cccc_table(cpustate, BITS(op,0x000f)); |
| 3079 | | |
| 3080 | | if(shouldJump) |
| 3081 | | { |
| 3082 | | /* TODO: It says "signed" absolute offset. Weird. */ |
| 3083 | | UINT16 branchOffset = op2; |
| 3084 | | |
| 3085 | | /* TODO: Verify, since it's not in the docs, but it must be true */ |
| 3086 | | PC += 2; |
| 3087 | | |
| 3088 | | SP++; |
| 3089 | | SSH = PC; |
| 3090 | | SSL = SR; |
| 3091 | | |
| 3092 | | cpustate->ppc = PC; |
| 3093 | | PC = branchOffset; |
| 3094 | | |
| 3095 | | cycles += 4; /* TODO: +jx oscillator clock cycles */ |
| 3096 | | return 0; |
| 3097 | | } |
| 3098 | | else |
| 3099 | | { |
| 3100 | | cycles += 4; /* TODO: +jx oscillator clock cycles */ |
| 3101 | | return 2; |
| 3102 | | } |
| 3103 | | |
| 3104 | | /* S L E U N Z V C */ |
| 3105 | | /* - - - - - - - - */ |
| 3106 | | return 0; |
| 3107 | | } |
| 3108 | | |
| 3109 | | /* JScc : 0000 0110 RR00 cccc : A-112 */ |
| 3110 | | static size_t dsp56k_op_jscc_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3111 | | { |
| 3112 | | /* S L E U N Z V C */ |
| 3113 | | /* - - - - - - - - */ |
| 3114 | | return 0; |
| 3115 | | } |
| 3116 | | |
| 3117 | | /* JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 */ |
| 3118 | | static size_t dsp56k_op_jsr(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3119 | | { |
| 3120 | | /* TODO: It says "signed" absolute offset. Weird. */ |
| 3121 | | UINT16 branchOffset = op2; |
| 3122 | | |
| 3123 | | /* TODO: Verify, since it's not in the docs, but it must be true */ |
| 3124 | | PC += 2; |
| 3125 | | |
| 3126 | | /* TODO: This is a hacky implementation of Long vs Fast Interrupts. Do it right someday! */ |
| 3127 | | if (PC < ADDRESS(0x40)) |
| 3128 | | { |
| 3129 | | /* Long interrupt gets the previous PC, not the current one */ |
| 3130 | | SP++; |
| 3131 | | SSH = cpustate->ppc; |
| 3132 | | SSL = SR; |
| 3133 | | |
| 3134 | | cpustate->ppc = cpustate->ppc; |
| 3135 | | PC = branchOffset; |
| 3136 | | } |
| 3137 | | else |
| 3138 | | { |
| 3139 | | /* Normal operation */ |
| 3140 | | SP++; |
| 3141 | | SSH = PC; |
| 3142 | | SSL = SR; |
| 3143 | | |
| 3144 | | cpustate->ppc = PC; |
| 3145 | | PC = branchOffset; |
| 3146 | | } |
| 3147 | | |
| 3148 | | /* S L E U N Z V C */ |
| 3149 | | /* - - - - - - - - */ |
| 3150 | | cycles += 4; /* TODO: + jx oscillator cycles */ |
| 3151 | | return 0; |
| 3152 | | } |
| 3153 | | |
| 3154 | | /* JSR : 0000 1010 AAAA AAAA : A-114 */ |
| 3155 | | static size_t dsp56k_op_jsr_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3156 | | { |
| 3157 | | /* S L E U N Z V C */ |
| 3158 | | /* - - - - - - - - */ |
| 3159 | | return 0; |
| 3160 | | } |
| 3161 | | |
| 3162 | | /* JSR : 0000 0001 0010 00RR : A-114 */ |
| 3163 | | static size_t dsp56k_op_jsr_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3164 | | { |
| 3165 | | /* S L E U N Z V C */ |
| 3166 | | /* - - - - - - - - */ |
| 3167 | | return 0; |
| 3168 | | } |
| 3169 | | |
| 3170 | | /* LEA : 0000 0001 11TT MMRR : A-116 */ |
| 3171 | | static size_t dsp56k_op_lea(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3172 | | { |
| 3173 | | UINT16 ea = 0; |
| 3174 | | UINT16 *rX = NULL; |
| 3175 | | UINT16 *nX = NULL; |
| 3176 | | typed_pointer D = {NULL, DT_BYTE}; |
| 3177 | | decode_TT_table(cpustate, BITS(op,0x0030), &D); |
| 3178 | | |
| 3179 | | /* TODO: change the execute_mm_functions to return values. Maybe */ |
| 3180 | | /* Because this calculation isn't applied, do everything locally */ |
| 3181 | | /* RR table */ |
| 3182 | | switch(BITS(op,0x0003)) |
| 3183 | | { |
| 3184 | | case 0x0: rX = &R0; nX = &N0; break; |
| 3185 | | case 0x1: rX = &R1; nX = &N1; break; |
| 3186 | | case 0x2: rX = &R2; nX = &N2; break; |
| 3187 | | case 0x3: rX = &R3; nX = &N3; break; |
| 3188 | | } |
| 3189 | | |
| 3190 | | /* MM table */ |
| 3191 | | switch(BITS(op,0x000c)) |
| 3192 | | { |
| 3193 | | case 0x0: ea = *rX; break; |
| 3194 | | case 0x1: ea = *rX + 1; break; |
| 3195 | | case 0x2: ea = *rX - 1; break; |
| 3196 | | case 0x3: ea = *rX + *nX; break; |
| 3197 | | } |
| 3198 | | |
| 3199 | | *((UINT16*)D.addr) = ea; |
| 3200 | | |
| 3201 | | /* S L E U N Z V C */ |
| 3202 | | /* - - - - - - - - */ |
| 3203 | | return 1; |
| 3204 | | } |
| 3205 | | |
| 3206 | | /* LEA : 0000 0001 10NN MMRR : A-116 */ |
| 3207 | | static size_t dsp56k_op_lea_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3208 | | { |
| 3209 | | /* S L E U N Z V C */ |
| 3210 | | /* - - - - - - - - */ |
| 3211 | | return 0; |
| 3212 | | } |
| 3213 | | |
| 3214 | | /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */ |
| 3215 | | static size_t dsp56k_op_macsuuu(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3216 | | { |
| 3217 | | UINT8 s = 0; |
| 3218 | | INT64 result = 0; |
| 3219 | | |
| 3220 | | void* D = NULL; |
| 3221 | | void* S1 = NULL; |
| 3222 | | void* S2 = NULL; |
| 3223 | | |
| 3224 | | decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D); |
| 3225 | | |
| 3226 | | s = BITS(op,0x0004); |
| 3227 | | |
| 3228 | | /* Fixed-point 2's complement multiplication requires a shift */ |
| 3229 | | if (s) |
| 3230 | | { |
| 3231 | | /* Unsigned * Unsigned */ |
| 3232 | | UINT32 s1 = (UINT32)(*((UINT16*)S1)); |
| 3233 | | UINT32 s2 = (UINT32)(*((UINT16*)S2)); |
| 3234 | | result = ( s1 * s2 ) << 1; |
| 3235 | | } |
| 3236 | | else |
| 3237 | | { |
| 3238 | | /* Signed * Unsigned */ |
| 3239 | | /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */ |
| 3240 | | INT32 s1 = ((INT32)(*((UINT16*)S1))); |
| 3241 | | INT32 s2 = (UINT32)(*((UINT16*)S2)); |
| 3242 | | result = ( s1 * s2 ) << 1; |
| 3243 | | } |
| 3244 | | |
| 3245 | | (*((UINT64*)D)) += result; |
| 3246 | | |
| 3247 | | /* And out the bits that don't live in the register */ |
| 3248 | | (*((UINT64*)D)) &= U64(0x000000ffffffffff); |
| 3249 | | |
| 3250 | | /* S L E U N Z V C */ |
| 3251 | | /* - * * * * * * - */ |
| 3252 | | /* TODO: L, E, U, V */ |
| 3253 | | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 3254 | | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 3255 | | |
| 3256 | | cycles += 2; |
| 3257 | | return 1; |
| 3258 | | } |
| 3259 | | |
| 3260 | | /* MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 */ |
| 3261 | | static size_t dsp56k_op_move_2(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3262 | | { |
| 3263 | | /* S L E U N Z V C */ |
| 3264 | | /* * * - - - - - - */ |
| 3265 | | return 0; |
| 3266 | | } |
| 3267 | | |
| 3268 | | /* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */ |
| 3269 | | static size_t dsp56k_op_movec(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3270 | | { |
| 3271 | | UINT8 W; |
| 3272 | | typed_pointer R = { NULL, DT_BYTE }; |
| 3273 | | typed_pointer SD = { NULL, DT_BYTE }; |
| 3274 | | |
| 3275 | | W = BITS(op,0x0400); |
| 3276 | | decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD); |
| 3277 | | decode_RR_table(cpustate, BITS(op,0x0003), &R); |
| 3278 | | |
| 3279 | | if (W) |
| 3280 | | { |
| 3281 | | /* Write D */ |
| 3282 | | UINT16 value = cpustate->data->read_word(ADDRESS(*((UINT16*)R.addr))) ; |
| 3283 | | typed_pointer temp_src = { &value, DT_WORD }; |
| 3284 | | SetDestinationValue(temp_src, SD); |
| 3285 | | } |
| 3286 | | else |
| 3287 | | { |
| 3288 | | /* Read S */ |
| 3289 | | UINT16 dataMemOffset = *((UINT16*)R.addr); |
| 3290 | | SetDataMemoryValue(cpustate, SD, ADDRESS(dataMemOffset)); |
| 3291 | | } |
| 3292 | | |
| 3293 | | execute_MM_table(cpustate, BITS(op,0x0003), BITS(op,0x000c)); |
| 3294 | | |
| 3295 | | /* S L E U N Z V C */ |
| 3296 | | /* * ? ? ? ? ? ? ? */ |
| 3297 | | /* All ? bits - If SR is specified as a destination operand, set according to the corresponding |
| 3298 | | bit of the source operand. If SR is not specified as a destination operand, L is set if data |
| 3299 | | limiting occurred. All ? bits are not affected otherwise.*/ |
| 3300 | | if (W && (SD.addr != &SR)) |
| 3301 | | { |
| 3302 | | /* If you're writing to something other than the SR */ |
| 3303 | | /* TODO */ |
| 3304 | | } |
| 3305 | | |
| 3306 | | cycles += 2; /* TODO: + mvc */ |
| 3307 | | return 1; |
| 3308 | | } |
| 3309 | | |
| 3310 | | /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */ |
| 3311 | | static size_t dsp56k_op_movec_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3312 | | { |
| 3313 | | UINT8 W; |
| 3314 | | UINT16 memOffset; |
| 3315 | | typed_pointer SD = {NULL, DT_BYTE}; |
| 3316 | | |
| 3317 | | W = BITS(op,0x0400); |
| 3318 | | decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD); |
| 3319 | | memOffset = execute_q_table(cpustate, BITS(op,0x0003), BITS(op,0x0008)); |
| 3320 | | |
| 3321 | | if (W) |
| 3322 | | { |
| 3323 | | /* Write D */ |
| 3324 | | UINT16 tempData = cpustate->data->read_word(ADDRESS(memOffset)); |
| 3325 | | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3326 | | SetDestinationValue(temp_src, SD); |
| 3327 | | } |
| 3328 | | else |
| 3329 | | { |
| 3330 | | /* Read S */ |
| 3331 | | UINT16 tempData = *((UINT16*)SD.addr); |
| 3332 | | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3333 | | SetDataMemoryValue(cpustate, temp_src, ADDRESS(memOffset)); |
| 3334 | | } |
| 3335 | | |
| 3336 | | /* S L E U N Z V C */ |
| 3337 | | /* * ? ? ? ? ? ? ? */ |
| 3338 | | /* All ? bits - If SR is specified as a destination operand, set according to the corresponding |
| 3339 | | bit of the source operand. If SR is not specified as a destination operand, L is set if data |
| 3340 | | limiting occurred. All ? bits are not affected otherwise.*/ |
| 3341 | | if (W && (SD.addr != &SR)) |
| 3342 | | { |
| 3343 | | /* If you're writing to something other than the SR */ |
| 3344 | | /* TODO */ |
| 3345 | | } |
| 3346 | | |
| 3347 | | cycles += 2; /* + mvc oscillator clock cycles */ |
| 3348 | | return 1; |
| 3349 | | } |
| 3350 | | |
| 3351 | | /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */ |
| 3352 | | static size_t dsp56k_op_movec_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3353 | | { |
| 3354 | | UINT8 W; |
| 3355 | | UINT16 memOffset; |
| 3356 | | typed_pointer SD = {NULL, DT_BYTE}; |
| 3357 | | typed_pointer XMemOffset = {NULL, DT_BYTE}; |
| 3358 | | |
| 3359 | | W = BITS(op,0x0400); |
| 3360 | | decode_Z_table(cpustate, BITS(op,0x0008), &XMemOffset); |
| 3361 | | decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD); |
| 3362 | | |
| 3363 | | memOffset = *((UINT16*)XMemOffset.addr); |
| 3364 | | |
| 3365 | | if (W) |
| 3366 | | { |
| 3367 | | /* Write D */ |
| 3368 | | UINT16 tempData = cpustate->data->read_word(ADDRESS(memOffset)); |
| 3369 | | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3370 | | SetDestinationValue(temp_src, SD); |
| 3371 | | } |
| 3372 | | else |
| 3373 | | { |
| 3374 | | /* Read S */ |
| 3375 | | UINT16 tempData = *((UINT16*)SD.addr); |
| 3376 | | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3377 | | SetDataMemoryValue(cpustate, temp_src, ADDRESS(memOffset)); |
| 3378 | | } |
| 3379 | | |
| 3380 | | |
| 3381 | | /* S L E U N Z V C */ |
| 3382 | | /* * ? ? ? ? ? ? ? */ |
| 3383 | | /* All ? bits - If SR is specified as a destination operand, set according to the corresponding |
| 3384 | | bit of the source operand. If SR is not specified as a destination operand, L is set if data |
| 3385 | | limiting occurred. All ? bits are not affected otherwise.*/ |
| 3386 | | if (W && (SD.addr != &SR)) |
| 3387 | | { |
| 3388 | | /* If you're writing to something other than the SR */ |
| 3389 | | /* TODO */ |
| 3390 | | } |
| 3391 | | |
| 3392 | | cycles += 2; /* + mvc oscillator clock cycles */ |
| 3393 | | return 1; |
| 3394 | | } |
| 3395 | | |
| 3396 | | /* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */ |
| 3397 | | static size_t dsp56k_op_movec_3(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3398 | | { |
| 3399 | | UINT8 W; |
| 3400 | | UINT8 t; |
| 3401 | | typed_pointer SD = { NULL, DT_BYTE }; |
| 3402 | | |
| 3403 | | W = BITS(op,0x0400); |
| 3404 | | t = BITS(op,0x0008); |
| 3405 | | decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD); |
| 3406 | | |
| 3407 | | if (W) |
| 3408 | | { |
| 3409 | | /* Write D */ |
| 3410 | | if (t) |
| 3411 | | { |
| 3412 | | /* 16-bit long data */ |
| 3413 | | typed_pointer temp_src = { (void*)&op2, DT_WORD }; |
| 3414 | | SetDestinationValue(temp_src, SD); |
| 3415 | | } |
| 3416 | | else |
| 3417 | | { |
| 3418 | | /* 16-bit long address */ |
| 3419 | | UINT16 tempD = cpustate->data->read_word(ADDRESS(op2)); |
| 3420 | | typed_pointer tempTP = {&tempD, DT_WORD}; |
| 3421 | | SetDestinationValue(tempTP, SD); |
| 3422 | | } |
| 3423 | | } |
| 3424 | | else |
| 3425 | | { |
| 3426 | | /* Read S */ |
| 3427 | | if (t) |
| 3428 | | { |
| 3429 | | /* 16-bit long data */ |
| 3430 | | logerror("DSP56k: Movec - I don't think this exists?"); |
| 3431 | | } |
| 3432 | | else |
| 3433 | | { |
| 3434 | | /* 16-bit long address */ |
| 3435 | | SetDataMemoryValue(cpustate, SD, ADDRESS(op2)); |
| 3436 | | } |
| 3437 | | } |
| 3438 | | |
| 3439 | | /* S L E U N Z V C */ |
| 3440 | | /* * ? ? ? ? ? ? ? */ |
| 3441 | | /* All ? bits - If SR is specified as a destination operand, set according to the corresponding |
| 3442 | | bit of the source operand. If SR is not specified as a destination operand, L is set if data |
| 3443 | | limiting occurred. All ? bits are not affected otherwise.*/ |
| 3444 | | if (W && (SD.addr != &SR)) |
| 3445 | | { |
| 3446 | | /* If you're writing to something other than the SR */ |
| 3447 | | /* TODO */ |
| 3448 | | } |
| 3449 | | |
| 3450 | | cycles += 2; /* TODO: + mvc */ |
| 3451 | | return 2; |
| 3452 | | } |
| 3453 | | |
| 3454 | | /* MOVE(C) : 0010 10dd dddD DDDD : A-144 */ |
| 3455 | | static size_t dsp56k_op_movec_4(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3456 | | { |
| 3457 | | typed_pointer S = {NULL, DT_BYTE}; |
| 3458 | | typed_pointer D = {NULL, DT_BYTE}; |
| 3459 | | |
| 3460 | | decode_DDDDD_table(cpustate, BITS(op,0x03e0), &S); |
| 3461 | | decode_DDDDD_table(cpustate, BITS(op,0x001f), &D); |
| 3462 | | |
| 3463 | | SetDestinationValue(S, D); |
| 3464 | | |
| 3465 | | /* S L E U N Z V C */ |
| 3466 | | /* * ? ? ? ? ? ? ? */ |
| 3467 | | /* All ? bits - If SR is specified as a destination operand, set according to the corresponding |
| 3468 | | bit of the source operand. If SR is not specified as a destination operand, L is set if data |
| 3469 | | limiting occurred. All ? bits are not affected otherwise.*/ |
| 3470 | | if (D.addr != &SR) |
| 3471 | | { |
| 3472 | | /* If you're writing to something other than the SR */ |
| 3473 | | /* TODO */ |
| 3474 | | } |
| 3475 | | |
| 3476 | | cycles += 2; |
| 3477 | | return 1; |
| 3478 | | } |
| 3479 | | |
| 3480 | | /* MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 */ |
| 3481 | | static size_t dsp56k_op_movec_5(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3482 | | { |
| 3483 | | INT8 xx; |
| 3484 | | UINT8 W; |
| 3485 | | UINT16 memOffset; |
| 3486 | | typed_pointer SD = { NULL, DT_BYTE }; |
| 3487 | | |
| 3488 | | xx = (INT8)(op & 0x00ff); |
| 3489 | | W = BITS(op2,0x0400); |
| 3490 | | decode_DDDDD_table(cpustate, BITS(op2,0x03e0), &SD); |
| 3491 | | |
| 3492 | | memOffset = R2 + (INT16)xx; |
| 3493 | | |
| 3494 | | if (W) |
| 3495 | | { |
| 3496 | | /* Write D */ |
| 3497 | | UINT16 tempData = cpustate->data->read_word(ADDRESS(memOffset)); |
| 3498 | | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3499 | | SetDestinationValue(temp_src, SD); |
| 3500 | | } |
| 3501 | | else |
| 3502 | | { |
| 3503 | | /* Read S */ |
| 3504 | | UINT16 tempData = *((UINT16*)SD.addr); |
| 3505 | | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3506 | | SetDataMemoryValue(cpustate, temp_src, ADDRESS(memOffset)); |
| 3507 | | } |
| 3508 | | |
| 3509 | | /* S L E U N Z V C */ |
| 3510 | | /* * ? ? ? ? ? ? ? */ |
| 3511 | | /* All ? bits - If SR is specified as a destination operand, set according to the corresponding |
| 3512 | | bit of the source operand. If SR is not specified as a destination operand, L is set if data |
| 3513 | | limiting occurred. All ? bits are not affected otherwise.*/ |
| 3514 | | if (W && (SD.addr != &SR)) |
| 3515 | | { |
| 3516 | | /* If you're writing to something other than the SR */ |
| 3517 | | /* TODO */ |
| 3518 | | } |
| 3519 | | |
| 3520 | | cycles += 2; /* TODO: + mvc oscillator clock cycles */ |
| 3521 | | return 2; |
| 3522 | | } |
| 3523 | | |
| 3524 | | /* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */ |
| 3525 | | static size_t dsp56k_op_movei(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3526 | | { |
| 3527 | | typed_pointer D = {NULL, DT_BYTE}; |
| 3528 | | typed_pointer immTP = {NULL, DT_BYTE}; |
| 3529 | | |
| 3530 | | /* Typecasting to INT16 sign-extends the BBBBBBBB operand */ |
| 3531 | | UINT16 immediateSignExtended = (INT16)(op & 0x00ff); |
| 3532 | | immTP.addr = &immediateSignExtended; |
| 3533 | | immTP.data_type = DT_WORD; |
| 3534 | | |
| 3535 | | decode_DD_table(cpustate, BITS(op,0x0300), &D); |
| 3536 | | |
| 3537 | | SetDestinationValue(immTP, D); |
| 3538 | | |
| 3539 | | /* S L E U N Z V C */ |
| 3540 | | /* - - - - - - - - */ |
| 3541 | | cycles += 2; |
| 3542 | | return 1; |
| 3543 | | } |
| 3544 | | |
| 3545 | | /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */ |
| 3546 | | static size_t dsp56k_op_movem(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3547 | | { |
| 3548 | | UINT8 W; |
| 3549 | | typed_pointer R = { NULL, DT_BYTE }; |
| 3550 | | typed_pointer SD = { NULL, DT_BYTE }; |
| 3551 | | |
| 3552 | | W = BITS(op,0x0100); |
| 3553 | | decode_RR_table(cpustate, BITS(op,0x00c0), &R); |
| 3554 | | decode_HHH_table(cpustate, BITS(op,0x0007), &SD); |
| 3555 | | |
| 3556 | | if (W) |
| 3557 | | { |
| 3558 | | /* Read from Program Memory */ |
| 3559 | | typed_pointer data; |
| 3560 | | UINT16 ldata = cpustate->program->read_word(ADDRESS(*((UINT16*)R.addr))); |
| 3561 | | |
| 3562 | | data.addr = &ldata; |
| 3563 | | data.data_type = DT_WORD; |
| 3564 | | SetDestinationValue(data, SD) ; |
| 3565 | | } |
| 3566 | | else |
| 3567 | | { |
| 3568 | | /* Write to Program Memory */ |
| 3569 | | SetProgramMemoryValue(cpustate, SD, ADDRESS(*((UINT16*)R.addr))) ; |
| 3570 | | } |
| 3571 | | |
| 3572 | | execute_MM_table(cpustate, BITS(op,0x00c0), BITS(op,0x0018)); |
| 3573 | | |
| 3574 | | /* S L E U N Z V C */ |
| 3575 | | /* * * - - - - - - */ |
| 3576 | | /* TODO: S, L */ |
| 3577 | | cycles += 2; /* TODO: + mvm oscillator clock cycles */ |
| 3578 | | return 1; |
| 3579 | | } |
| 3580 | | |
| 3581 | | /* MOVE(M) : 0000 001W RR11 mmRR : A-152 */ |
| 3582 | | static size_t dsp56k_op_movem_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3583 | | { |
| 3584 | | /* S L E U N Z V C */ |
| 3585 | | /* * * - - - - - - */ |
| 3586 | | return 0; |
| 3587 | | } |
| 3588 | | |
| 3589 | | /* MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 */ |
| 3590 | | static size_t dsp56k_op_movem_2(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3591 | | { |
| 3592 | | /* S L E U N Z V C */ |
| 3593 | | /* * * - - - - - - */ |
| 3594 | | return 0; |
| 3595 | | } |
| 3596 | | |
| 3597 | | /* MOVE(P) : 0001 100W HH1p pppp : A-156 */ |
| 3598 | | static size_t dsp56k_op_movep(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3599 | | { |
| 3600 | | UINT16 W; |
| 3601 | | UINT16 pp; |
| 3602 | | typed_pointer SD = {NULL, DT_BYTE}; |
| 3603 | | |
| 3604 | | decode_HH_table(cpustate, BITS(op,0x00c0), &SD); |
| 3605 | | /* TODO: Special cases for A & B */ |
| 3606 | | |
| 3607 | | pp = op & 0x001f; |
| 3608 | | pp = assemble_address_from_IO_short_address(cpustate, pp); |
| 3609 | | |
| 3610 | | W = BITS(op,0x0100); |
| 3611 | | |
| 3612 | | if (W) |
| 3613 | | { |
| 3614 | | UINT16 data = cpustate->data->read_word(ADDRESS(pp)); |
| 3615 | | |
| 3616 | | typed_pointer tempTP; |
| 3617 | | tempTP.addr = &data; |
| 3618 | | tempTP.data_type = DT_WORD; |
| 3619 | | |
| 3620 | | SetDestinationValue(tempTP, SD); |
| 3621 | | } |
| 3622 | | else |
| 3623 | | { |
| 3624 | | SetDataMemoryValue(cpustate, SD, ADDRESS(pp)); |
| 3625 | | } |
| 3626 | | |
| 3627 | | /* S L E U N Z V C */ |
| 3628 | | /* * * - - - - - - */ |
| 3629 | | /* TODO: S, L */ |
| 3630 | | |
| 3631 | | cycles += 4; /* TODO: + mvp oscillator cycles */ |
| 3632 | | return 1; |
| 3633 | | } |
| 3634 | | |
| 3635 | | /* MOVE(P) : 0000 110W RRmp pppp : A-156 */ |
| 3636 | | static size_t dsp56k_op_movep_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3637 | | { |
| 3638 | | /* X:<Rx> and X:<pp> */ |
| 3639 | | UINT16 W; |
| 3640 | | UINT16 pp; |
| 3641 | | |
| 3642 | | typed_pointer SD = {NULL, DT_BYTE}; |
| 3643 | | decode_RR_table(cpustate, BITS(op,0x00c0), &SD); |
| 3644 | | |
| 3645 | | pp = op & 0x001f; |
| 3646 | | pp = assemble_address_from_IO_short_address(cpustate, pp); |
| 3647 | | |
| 3648 | | W = BITS(op,0x0100); |
| 3649 | | |
| 3650 | | /* A little different than most W if's - opposite read and write */ |
| 3651 | | if (W) |
| 3652 | | { |
| 3653 | | UINT16 data = cpustate->data->read_word(ADDRESS(*((UINT16*)SD.addr))); |
| 3654 | | |
| 3655 | | typed_pointer tempTP; |
| 3656 | | tempTP.addr = &data; |
| 3657 | | tempTP.data_type = DT_WORD; |
| 3658 | | |
| 3659 | | SetDataMemoryValue(cpustate, tempTP, ADDRESS(pp)); |
| 3660 | | } |
| 3661 | | else |
| 3662 | | { |
| 3663 | | /* TODO */ |
| 3664 | | fatalerror("dsp56k : move(p) NOTHING HERE (yet)\n") ; |
| 3665 | | } |
| 3666 | | |
| 3667 | | /* Postincrement */ |
| 3668 | | execute_m_table(cpustate, BITS(op,0x00c0), BITS(op,0x0020)); |
| 3669 | | |
| 3670 | | /* S L E U N Z V C */ |
| 3671 | | /* * * - - - - - - */ |
| 3672 | | /* TODO: S, L */ |
| 3673 | | cycles += 4; /* TODO: + mvp oscillator cycles */ |
| 3674 | | return 1; |
| 3675 | | } |
| 3676 | | |
| 3677 | | /* MOVE(S) : 0001 100W HH0a aaaa : A-158 */ |
| 3678 | | static size_t dsp56k_op_moves(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3679 | | { |
| 3680 | | /* S L E U N Z V C */ |
| 3681 | | /* * * - - - - - - */ |
| 3682 | | return 0; |
| 3683 | | } |
| 3684 | | |
| 3685 | | /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */ |
| 3686 | | static size_t dsp56k_op_mpysuuu(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3687 | | { |
| 3688 | | UINT8 s = 0; |
| 3689 | | INT64 result = 0; |
| 3690 | | |
| 3691 | | void* D = NULL; |
| 3692 | | void* S1 = NULL; |
| 3693 | | void* S2 = NULL; |
| 3694 | | |
| 3695 | | decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D); |
| 3696 | | |
| 3697 | | s = BITS(op,0x0004); |
| 3698 | | |
| 3699 | | /* Fixed-point 2's complement multiplication requires a shift */ |
| 3700 | | if (s) |
| 3701 | | { |
| 3702 | | /* Unsigned * Unsigned */ |
| 3703 | | UINT32 s1 = (UINT32)(*((UINT16*)S1)); |
| 3704 | | UINT32 s2 = (UINT32)(*((UINT16*)S2)); |
| 3705 | | result = ( s1 * s2 ) << 1; |
| 3706 | | } |
| 3707 | | else |
| 3708 | | { |
| 3709 | | /* Signed * Unsigned */ |
| 3710 | | /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */ |
| 3711 | | INT32 s1 = ((INT32)(*((UINT16*)S1))); |
| 3712 | | INT32 s2 = (UINT32)(*((UINT16*)S2)); |
| 3713 | | result = ( s1 * s2 ) << 1; |
| 3714 | | } |
| 3715 | | |
| 3716 | | (*((UINT64*)D)) = result; |
| 3717 | | |
| 3718 | | /* And out the bits that don't live in the register */ |
| 3719 | | (*((UINT64*)D)) &= U64(0x000000ffffffffff); |
| 3720 | | |
| 3721 | | /* S L E U N Z V C */ |
| 3722 | | /* - * * * * * * - */ |
| 3723 | | /* TODO: L, E, U, V */ |
| 3724 | | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 3725 | | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 3726 | | |
| 3727 | | cycles += 2; |
| 3728 | | return 1; |
| 3729 | | } |
| 3730 | | |
| 3731 | | /* NEGC : 0001 0101 0110 F000 : A-168 */ |
| 3732 | | static size_t dsp56k_op_negc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3733 | | { |
| 3734 | | /* S L E U N Z V C */ |
| 3735 | | /* - * * * * * * * */ |
| 3736 | | return 0; |
| 3737 | | } |
| 3738 | | |
| 3739 | | /* NOP : 0000 0000 0000 0000 : A-170 */ |
| 3740 | | static size_t dsp56k_op_nop(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3741 | | { |
| 3742 | | /* S L E U N Z V C */ |
| 3743 | | /* - - - - - - - - */ |
| 3744 | | return 1; |
| 3745 | | } |
| 3746 | | |
| 3747 | | /* NORM : 0001 0101 0010 F0RR : A-172 */ |
| 3748 | | static size_t dsp56k_op_norm(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3749 | | { |
| 3750 | | /* S L E U N Z V C */ |
| 3751 | | /* - * * * * * ? - */ |
| 3752 | | /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significantst |
| 3753 | | bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */ |
| 3754 | | return 0; |
| 3755 | | } |
| 3756 | | |
| 3757 | | /* ORI : 0001 1EE1 iiii iiii : A-178 */ |
| 3758 | | static size_t dsp56k_op_ori(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3759 | | { |
| 3760 | | /* S L E U N Z V C */ |
| 3761 | | /* - ? ? ? ? ? ? ? */ |
| 3762 | | /* All ? bits - Set if the corresponding bit in the immediate data is set and if the operand is the |
| 3763 | | CCR. Not affected otherwise. */ |
| 3764 | | return 0; |
| 3765 | | } |
| 3766 | | |
| 3767 | | /* REP : 0000 0000 111- --RR : A-180 */ |
| 3768 | | static size_t dsp56k_op_rep(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3769 | | { |
| 3770 | | /* S L E U N Z V C */ |
| 3771 | | /* - * - - - - - - */ |
| 3772 | | return 0; |
| 3773 | | } |
| 3774 | | |
| 3775 | | /* REP : 0000 1111 iiii iiii : A-180 */ |
| 3776 | | static size_t dsp56k_op_rep_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3777 | | { |
| 3778 | | /* TODO: This is non-interruptable, probably have to turn off interrupts here */ |
| 3779 | | UINT16 iVal = op & 0x00ff; |
| 3780 | | |
| 3781 | | if (iVal != 0) |
| 3782 | | { |
| 3783 | | TEMP = LC; |
| 3784 | | LC = iVal; |
| 3785 | | |
| 3786 | | cpustate->repFlag = 1; |
| 3787 | | cpustate->repAddr = PC + ADDRESS(1); |
| 3788 | | |
| 3789 | | cycles += 4; /* TODO: + mv oscillator clock cycles */ |
| 3790 | | } |
| 3791 | | else |
| 3792 | | { |
| 3793 | | cycles += 6; /* TODO: + mv oscillator clock cycles */ |
| 3794 | | } |
| 3795 | | |
| 3796 | | |
| 3797 | | /* S L E U N Z V C */ |
| 3798 | | /* - * - - - - - - */ |
| 3799 | | /* TODO: L */ |
| 3800 | | return 1; |
| 3801 | | } |
| 3802 | | |
| 3803 | | /* REP : 0000 0100 001D DDDD : A-180 */ |
| 3804 | | static size_t dsp56k_op_rep_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3805 | | { |
| 3806 | | /* TODO: This is non-interruptable, probably have to turn off interrupts here */ |
| 3807 | | UINT16 repValue; |
| 3808 | | typed_pointer D = {NULL, DT_BYTE}; |
| 3809 | | decode_DDDDD_table(cpustate, BITS(op,0x001f), &D); |
| 3810 | | |
| 3811 | | /* TODO: handle special A&B source cases */ |
| 3812 | | if (D.addr == &A || D.addr == &B) |
| 3813 | | logerror("DSP56k ERROR : Rep with A or B instruction not implemented yet!\n"); |
| 3814 | | |
| 3815 | | repValue = *((UINT16*)D.addr); |
| 3816 | | |
| 3817 | | if (repValue != 0) |
| 3818 | | { |
| 3819 | | TEMP = LC; |
| 3820 | | LC = repValue; |
| 3821 | | |
| 3822 | | cpustate->repFlag = 1; |
| 3823 | | cpustate->repAddr = PC + ADDRESS(1); |
| 3824 | | |
| 3825 | | cycles += 4; /* TODO: + mv oscillator clock cycles */ |
| 3826 | | } |
| 3827 | | else |
| 3828 | | { |
| 3829 | | cycles += 6; /* TODO: + mv oscillator clock cycles */ |
| 3830 | | } |
| 3831 | | |
| 3832 | | /* S L E U N Z V C */ |
| 3833 | | /* - * - - - - - - */ |
| 3834 | | /* TODO: L */ |
| 3835 | | return 1; |
| 3836 | | } |
| 3837 | | |
| 3838 | | /* REPcc : 0000 0001 0101 cccc : A-184 */ |
| 3839 | | static size_t dsp56k_op_repcc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3840 | | { |
| 3841 | | /* S L E U N Z V C */ |
| 3842 | | /* - - - - - - - - */ |
| 3843 | | return 0; |
| 3844 | | } |
| 3845 | | |
| 3846 | | /* RESET : 0000 0000 0000 1000 : A-186 */ |
| 3847 | | static size_t dsp56k_op_reset(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3848 | | { |
| 3849 | | /* S L E U N Z V C */ |
| 3850 | | /* - - - - - - - - */ |
| 3851 | | return 0; |
| 3852 | | } |
| 3853 | | |
| 3854 | | /* RTI : 0000 0000 0000 0111 : A-194 */ |
| 3855 | | static size_t dsp56k_op_rti(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3856 | | { |
| 3857 | | /* WARNING : THERE SHOULD BE A MORE GENERAL HANDLING OF STACK ERRORS. */ |
| 3858 | | if (SP == 0) |
| 3859 | | { |
| 3860 | | dsp56k_add_pending_interrupt(cpustate, "Stack Error"); |
| 3861 | | return 0; |
| 3862 | | } |
| 3863 | | |
| 3864 | | cpustate->ppc = PC; |
| 3865 | | PC = SSH; |
| 3866 | | |
| 3867 | | SR = SSL; |
| 3868 | | SP = SP - 1; |
| 3869 | | |
| 3870 | | /* S L E U N Z V C */ |
| 3871 | | /* ? ? ? ? ? ? ? ? */ |
| 3872 | | /* All ? bits - Set according to value pulled from the stack. */ |
| 3873 | | cycles += 4; /* TODO: + rx oscillator clock cycles */ |
| 3874 | | return 0; |
| 3875 | | } |
| 3876 | | |
| 3877 | | /* RTS : 0000 0000 0000 0110 : A-196 */ |
| 3878 | | static size_t dsp56k_op_rts(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3879 | | { |
| 3880 | | /* Pop */ |
| 3881 | | cpustate->ppc = PC; |
| 3882 | | PC = SSH; |
| 3883 | | |
| 3884 | | /* SR = SSL; The status register is not affected. */ |
| 3885 | | |
| 3886 | | SP--; |
| 3887 | | |
| 3888 | | /* S L E U N Z V C */ |
| 3889 | | /* - - - - - - - - */ |
| 3890 | | cycles += 4; /* TODO: + rx oscillator clock cycles */ |
| 3891 | | return 0; |
| 3892 | | } |
| 3893 | | |
| 3894 | | /* STOP : 0000 0000 0000 1010 : A-200 */ |
| 3895 | | static size_t dsp56k_op_stop(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3896 | | { |
| 3897 | | /* S L E U N Z V C */ |
| 3898 | | /* - - - - - - - - */ |
| 3899 | | return 0; |
| 3900 | | } |
| 3901 | | |
| 3902 | | /* SWAP : 0001 0101 0111 F001 : A-206 */ |
| 3903 | | static size_t dsp56k_op_swap(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3904 | | { |
| 3905 | | /* S L E U N Z V C */ |
| 3906 | | /* - - - - - - - - */ |
| 3907 | | return 0; |
| 3908 | | } |
| 3909 | | |
| 3910 | | /* SWI : 0000 0000 0000 0101 : A-208 */ |
| 3911 | | static size_t dsp56k_op_swi(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3912 | | { |
| 3913 | | /* S L E U N Z V C */ |
| 3914 | | /* - - - - - - - - */ |
| 3915 | | return 0; |
| 3916 | | } |
| 3917 | | |
| 3918 | | /* Tcc : 0001 00cc ccTT Fh0h : A-210 */ |
| 3919 | | static size_t dsp56k_op_tcc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3920 | | { |
| 3921 | | int shouldTransfer = decode_cccc_table(cpustate, BITS(op,0x03c0)); |
| 3922 | | |
| 3923 | | if (shouldTransfer) |
| 3924 | | { |
| 3925 | | typed_pointer S = {NULL, DT_BYTE}; |
| 3926 | | typed_pointer D = {NULL, DT_BYTE}; |
| 3927 | | typed_pointer S2 = {&R0, DT_WORD}; |
| 3928 | | typed_pointer D2 = {NULL, DT_BYTE}; |
| 3929 | | |
| 3930 | | decode_h0hF_table(cpustate, BITS(op,0x0007),BITS(op,0x0008), &S, &D); |
| 3931 | | SetDestinationValue(S, D); |
| 3932 | | |
| 3933 | | /* TODO: What's up with that A,A* thing in the docs? Can you only ignore the R0->RX transfer if you do an A,A? */ |
| 3934 | | decode_RR_table(cpustate, BITS(op,0x0030), &D2); /* TT is the same as RR */ |
| 3935 | | SetDestinationValue(S2, D2); |
| 3936 | | } |
| 3937 | | |
| 3938 | | /* S L E U N Z V C */ |
| 3939 | | /* - - - - - - - - */ |
| 3940 | | cycles += 2; |
| 3941 | | return 1; |
| 3942 | | } |
| 3943 | | |
| 3944 | | /* TFR(2) : 0001 0101 0000 F00J : A-214 */ |
| 3945 | | static size_t dsp56k_op_tfr2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3946 | | { |
| 3947 | | typed_pointer S = {NULL, DT_BYTE}; |
| 3948 | | typed_pointer D = {NULL, DT_BYTE}; |
| 3949 | | |
| 3950 | | decode_JF_table(cpustate, BITS(op,0x0001), BITS(op,0x0008), &S, &D); |
| 3951 | | |
| 3952 | | SetDestinationValue(S, D); |
| 3953 | | |
| 3954 | | /* S L E U N Z V C */ |
| 3955 | | /* - * - - - - - - */ |
| 3956 | | /* TODO: L */ |
| 3957 | | cycles += 2; |
| 3958 | | return 1; |
| 3959 | | } |
| 3960 | | |
| 3961 | | /* TFR(3) : 0010 01mW RRDD FHHH : A-216 */ |
| 3962 | | static size_t dsp56k_op_tfr3(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3963 | | { |
| 3964 | | /* S L E U N Z V C */ |
| 3965 | | /* * * - - - - - - */ |
| 3966 | | return 0; |
| 3967 | | } |
| 3968 | | |
| 3969 | | /* TST(2) : 0001 0101 0001 -1DD : A-220 */ |
| 3970 | | static size_t dsp56k_op_tst2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3971 | | { |
| 3972 | | typed_pointer D = {NULL, DT_BYTE}; |
| 3973 | | decode_DD_table(cpustate, BITS(op,0x0003), &D); |
| 3974 | | |
| 3975 | | /* S L E U N Z V C */ |
| 3976 | | /* - * * * * * 0 0 */ |
| 3977 | | /* (L,E,U should be set to 0) */ |
| 3978 | | DSP56K_L_CLEAR(); |
| 3979 | | DSP56K_E_CLEAR(); |
| 3980 | | /* U_CLEAR(); */ /* TODO: Conflicting opinions? "Set if unnormalized." Documentation is weird (A&B?) */ |
| 3981 | | if ((*((UINT16*)D.addr)) & 0x8000) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 3982 | | if ((*((UINT16*)D.addr)) == 0x0000) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 3983 | | /* DSP56K_V_CLEAR(); */ /* Unaffected */ |
| 3984 | | DSP56K_C_CLEAR(); |
| 3985 | | |
| 3986 | | cycles += 2; |
| 3987 | | return 1; |
| 3988 | | } |
| 3989 | | |
| 3990 | | /* WAIT : 0000 0000 0000 1011 : A-222 */ |
| 3991 | | static size_t dsp56k_op_wait(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3992 | | { |
| 3993 | | /* S L E U N Z V C */ |
| 3994 | | /* - - - - - - - - */ |
| 3995 | | return 0; |
| 3996 | | } |
| 3997 | | |
| 3998 | | /* ZERO : 0001 0101 0101 F000 : A-224 */ |
| 3999 | | static size_t dsp56k_op_zero(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 4000 | | { |
| 4001 | | /* S L E U N Z V C */ |
| 4002 | | /* - * * * * * * - */ |
| 4003 | | return 0; |
| 4004 | | } |
| 4005 | | |
| 4006 | | |
| 4007 | | |
| 4008 | | /*************************************************************************** |
| 4009 | | Table decoding |
| 4010 | | ***************************************************************************/ |
| 4011 | | static UINT16 decode_BBB_bitmask(dsp56k_core* cpustate, UINT16 BBB, UINT16 *iVal) |
| 4012 | | { |
| 4013 | | UINT16 retVal = 0x0000; |
| 4014 | | |
| 4015 | | switch(BBB) |
| 4016 | | { |
| 4017 | | case 0x4: retVal = 0xff00; *iVal <<= 8; break; |
| 4018 | | case 0x2: retVal = 0x0ff0; *iVal <<= 4; break; |
| 4019 | | case 0x1: retVal = 0x00ff; *iVal <<= 0; break; |
| 4020 | | } |
| 4021 | | |
| 4022 | | return retVal; |
| 4023 | | } |
| 4024 | | |
| 4025 | | static int decode_cccc_table(dsp56k_core* cpustate, UINT16 cccc) |
| 4026 | | { |
| 4027 | | int retVal = 0; |
| 4028 | | |
| 4029 | | /* Not fully tested */ |
| 4030 | | switch (cccc) |
| 4031 | | { |
| 4032 | | /* Arranged according to mnemonic table - not decoding table */ |
| 4033 | | case 0x0: if( C() == 0) retVal = 1; break; /* cc(hs) */ |
| 4034 | | case 0x8: if( C() == 1) retVal = 1; break; /* cs(lo) */ |
| 4035 | | case 0x5: if( E() == 0) retVal = 1; break; /* ec */ |
| 4036 | | case 0xa: if( Z() == 1) retVal = 1; break; /* eq */ |
| 4037 | | case 0xd: if( E() == 1) retVal = 1; break; /* es */ |
| 4038 | | case 0x1: if((N() ^ V()) == 0) retVal = 1; break; /* ge */ |
| 4039 | | case 0x7: if((Z() | (N() ^ V())) == 0) retVal = 1; break; /* gt */ |
| 4040 | | case 0x6: if( L() == 0) retVal = 1; break; /* lc */ |
| 4041 | | case 0xf: if((Z() | (N() ^ V())) == 1) retVal = 1; break; /* le */ |
| 4042 | | case 0xe: if( L() == 1) retVal = 1; break; /* ls */ |
| 4043 | | case 0x9: if((N() ^ V()) == 1) retVal = 1; break; /* lt */ |
| 4044 | | case 0xb: if( N() == 1) retVal = 1; break; /* mi */ |
| 4045 | | case 0x2: if( Z() == 0) retVal = 1; break; /* ne */ |
| 4046 | | case 0xc: if((Z() | ((!U()) & (!E()))) == 1) retVal = 1; break; /* nr */ |
| 4047 | | case 0x3: if( N() == 0) retVal = 1; break; /* pl */ |
| 4048 | | case 0x4: if((Z() | ((!U()) & (!E()))) == 0) retVal = 1; break; /* nn */ |
| 4049 | | } |
| 4050 | | |
| 4051 | | return retVal; |
| 4052 | | } |
| 4053 | | |
| 4054 | | static void decode_DDDDD_table(dsp56k_core* cpustate, UINT16 DDDDD, typed_pointer* ret) |
| 4055 | | { |
| 4056 | | switch(DDDDD) |
| 4057 | | { |
| 4058 | | case 0x00: ret->addr = &X0; ret->data_type = DT_WORD; break; |
| 4059 | | case 0x01: ret->addr = &Y0; ret->data_type = DT_WORD; break; |
| 4060 | | case 0x02: ret->addr = &X1; ret->data_type = DT_WORD; break; |
| 4061 | | case 0x03: ret->addr = &Y1; ret->data_type = DT_WORD; break; |
| 4062 | | case 0x04: ret->addr = &A ; ret->data_type = DT_LONG_WORD; break; |
| 4063 | | case 0x05: ret->addr = &B ; ret->data_type = DT_LONG_WORD; break; |
| 4064 | | case 0x06: ret->addr = &A0; ret->data_type = DT_WORD; break; |
| 4065 | | case 0x07: ret->addr = &B0; ret->data_type = DT_WORD; break; |
| 4066 | | case 0x08: ret->addr = &LC; ret->data_type = DT_WORD; break; |
| 4067 | | case 0x09: ret->addr = &SR; ret->data_type = DT_WORD; break; |
| 4068 | | case 0x0a: ret->addr = &OMR; ret->data_type = DT_BYTE; break; |
| 4069 | | case 0x0b: ret->addr = &SP; ret->data_type = DT_BYTE; break; |
| 4070 | | case 0x0c: ret->addr = &A1; ret->data_type = DT_WORD; break; |
| 4071 | | case 0x0d: ret->addr = &B1; ret->data_type = DT_WORD; break; |
| 4072 | | case 0x0e: ret->addr = &A2; ret->data_type = DT_BYTE; break; |
| 4073 | | case 0x0f: ret->addr = &B2; ret->data_type = DT_BYTE; break; |
| 4074 | | |
| 4075 | | case 0x10: ret->addr = &R0; ret->data_type = DT_WORD; break; |
| 4076 | | case 0x11: ret->addr = &R1; ret->data_type = DT_WORD; break; |
| 4077 | | case 0x12: ret->addr = &R2; ret->data_type = DT_WORD; break; |
| 4078 | | case 0x13: ret->addr = &R3; ret->data_type = DT_WORD; break; |
| 4079 | | case 0x14: ret->addr = &M0; ret->data_type = DT_WORD; break; |
| 4080 | | case 0x15: ret->addr = &M1; ret->data_type = DT_WORD; break; |
| 4081 | | case 0x16: ret->addr = &M2; ret->data_type = DT_WORD; break; |
| 4082 | | case 0x17: ret->addr = &M3; ret->data_type = DT_WORD; break; |
| 4083 | | case 0x18: ret->addr = &SSH; ret->data_type = DT_WORD; break; |
| 4084 | | case 0x19: ret->addr = &SSL; ret->data_type = DT_WORD; break; |
| 4085 | | case 0x1a: ret->addr = &LA; ret->data_type = DT_WORD; break; |
| 4086 | | /*no 0x1b */ |
| 4087 | | case 0x1c: ret->addr = &N0; ret->data_type = DT_WORD; break; |
| 4088 | | case 0x1d: ret->addr = &N1; ret->data_type = DT_WORD; break; |
| 4089 | | case 0x1e: ret->addr = &N2; ret->data_type = DT_WORD; break; |
| 4090 | | case 0x1f: ret->addr = &N3; ret->data_type = DT_WORD; break; |
| 4091 | | } |
| 4092 | | } |
| 4093 | | |
| 4094 | | static void decode_DD_table(dsp56k_core* cpustate, UINT16 DD, typed_pointer* ret) |
| 4095 | | { |
| 4096 | | switch(DD) |
| 4097 | | { |
| 4098 | | case 0x00: ret->addr = &X0; ret->data_type = DT_WORD; break; |
| 4099 | | case 0x01: ret->addr = &Y0; ret->data_type = DT_WORD; break; |
| 4100 | | case 0x02: ret->addr = &X1; ret->data_type = DT_WORD; break; |
| 4101 | | case 0x03: ret->addr = &Y1; ret->data_type = DT_WORD; break; |
| 4102 | | } |
| 4103 | | } |
| 4104 | | |
| 4105 | | static void decode_DDF_table(dsp56k_core* cpustate, UINT16 DD, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret) |
| 4106 | | { |
| 4107 | | UINT16 switchVal = (DD << 1) | F; |
| 4108 | | |
| 4109 | | switch (switchVal) |
| 4110 | | { |
| 4111 | | case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4112 | | case 0x1: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4113 | | case 0x2: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4114 | | case 0x3: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4115 | | case 0x4: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4116 | | case 0x5: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4117 | | case 0x6: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4118 | | case 0x7: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4119 | | } |
| 4120 | | } |
| 4121 | | |
| 4122 | | static void decode_F_table(dsp56k_core* cpustate, UINT16 F, typed_pointer* ret) |
| 4123 | | { |
| 4124 | | switch(F) |
| 4125 | | { |
| 4126 | | case 0x0: ret->addr = &A; ret->data_type = DT_LONG_WORD; break; |
| 4127 | | case 0x1: ret->addr = &B; ret->data_type = DT_LONG_WORD; break; |
| 4128 | | } |
| 4129 | | } |
| 4130 | | |
| 4131 | | static void decode_h0hF_table(dsp56k_core* cpustate, UINT16 h0h, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret) |
| 4132 | | { |
| 4133 | | UINT16 switchVal = (h0h << 1) | F ; |
| 4134 | | |
| 4135 | | switch (switchVal) |
| 4136 | | { |
| 4137 | | case 0x8: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4138 | | case 0x9: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4139 | | case 0xa: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4140 | | case 0xb: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4141 | | case 0x2: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4142 | | case 0x1: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4143 | | case 0x0: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4144 | | case 0x3: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4145 | | } |
| 4146 | | } |
| 4147 | | |
| 4148 | | static void decode_HH_table(dsp56k_core* cpustate, UINT16 HH, typed_pointer* ret) |
| 4149 | | { |
| 4150 | | switch(HH) |
| 4151 | | { |
| 4152 | | case 0x0: ret->addr = &X0; ret->data_type = DT_WORD; break; |
| 4153 | | case 0x1: ret->addr = &Y0; ret->data_type = DT_WORD; break; |
| 4154 | | case 0x2: ret->addr = &A; ret->data_type = DT_LONG_WORD; break; |
| 4155 | | case 0x3: ret->addr = &B; ret->data_type = DT_LONG_WORD; break; |
| 4156 | | } |
| 4157 | | } |
| 4158 | | |
| 4159 | | static void decode_HHH_table(dsp56k_core* cpustate, UINT16 HHH, typed_pointer* ret) |
| 4160 | | { |
| 4161 | | switch(HHH) |
| 4162 | | { |
| 4163 | | case 0x0: ret->addr = &X0; ret->data_type = DT_WORD; break; |
| 4164 | | case 0x1: ret->addr = &Y0; ret->data_type = DT_WORD; break; |
| 4165 | | case 0x2: ret->addr = &X1; ret->data_type = DT_WORD; break; |
| 4166 | | case 0x3: ret->addr = &Y1; ret->data_type = DT_WORD; break; |
| 4167 | | case 0x4: ret->addr = &A; ret->data_type = DT_LONG_WORD; break; |
| 4168 | | case 0x5: ret->addr = &B; ret->data_type = DT_LONG_WORD; break; |
| 4169 | | case 0x6: ret->addr = &A0; ret->data_type = DT_WORD; break; |
| 4170 | | case 0x7: ret->addr = &B0; ret->data_type = DT_WORD; break; |
| 4171 | | } |
| 4172 | | } |
| 4173 | | |
| 4174 | | static void decode_IIII_table(dsp56k_core* cpustate, UINT16 IIII, typed_pointer* src_ret, typed_pointer* dst_ret, void *working) |
| 4175 | | { |
| 4176 | | void *opposite = 0x00 ; |
| 4177 | | |
| 4178 | | if (working == &A) opposite = &B ; |
| 4179 | | else opposite = &A ; |
| 4180 | | |
| 4181 | | switch(IIII) |
| 4182 | | { |
| 4183 | | case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; |
| 4184 | | case 0x1: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; |
| 4185 | | case 0x2: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; |
| 4186 | | case 0x3: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; |
| 4187 | | case 0x4: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X0; dst_ret->data_type = DT_WORD; break; |
| 4188 | | case 0x5: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y0; dst_ret->data_type = DT_WORD; break; |
| 4189 | | case 0x6: src_ret->addr = &A0; src_ret->data_type = DT_WORD; dst_ret->addr = &X0; dst_ret->data_type = DT_WORD; break; |
| 4190 | | case 0x7: src_ret->addr = &B0; src_ret->data_type = DT_WORD; dst_ret->addr = &Y0; dst_ret->data_type = DT_WORD; break; |
| 4191 | | case 0x8: src_ret->addr = working; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; |
| 4192 | | case 0x9: src_ret->addr = working; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; |
| 4193 | | case 0xc: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X1; dst_ret->data_type = DT_WORD; break; |
| 4194 | | case 0xd: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y1; dst_ret->data_type = DT_WORD; break; |
| 4195 | | case 0xe: src_ret->addr = &A0; src_ret->data_type = DT_WORD; dst_ret->addr = &X1; dst_ret->data_type = DT_WORD; break; |
| 4196 | | case 0xf: src_ret->addr = &B0; src_ret->data_type = DT_WORD; dst_ret->addr = &Y1; dst_ret->data_type = DT_WORD; break; |
| 4197 | | } |
| 4198 | | } |
| 4199 | | |
| 4200 | | static void decode_JJJF_table(dsp56k_core* cpustate, UINT16 JJJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret) |
| 4201 | | { |
| 4202 | | UINT16 switchVal = (JJJ << 1) | F ; |
| 4203 | | |
| 4204 | | switch(switchVal) |
| 4205 | | { |
| 4206 | | case 0x0: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4207 | | case 0x1: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4208 | | case 0x4: src_ret->addr = &X; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4209 | | case 0x5: src_ret->addr = &X; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4210 | | case 0x6: src_ret->addr = &Y; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4211 | | case 0x7: src_ret->addr = &Y; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4212 | | case 0x8: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4213 | | case 0x9: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4214 | | case 0xa: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4215 | | case 0xb: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4216 | | case 0xc: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4217 | | case 0xd: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4218 | | case 0xe: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4219 | | case 0xf: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4220 | | } |
| 4221 | | } |
| 4222 | | |
| 4223 | | static void decode_JJF_table(dsp56k_core* cpustate, UINT16 JJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret) |
| 4224 | | { |
| 4225 | | UINT16 switchVal = (JJ << 1) | F ; |
| 4226 | | |
| 4227 | | switch (switchVal) |
| 4228 | | { |
| 4229 | | case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4230 | | case 0x1: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4231 | | case 0x2: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4232 | | case 0x3: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4233 | | case 0x4: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4234 | | case 0x5: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4235 | | case 0x6: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4236 | | case 0x7: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4237 | | } |
| 4238 | | } |
| 4239 | | |
| 4240 | | static void decode_JF_table(dsp56k_core* cpustate, UINT16 J, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret) |
| 4241 | | { |
| 4242 | | UINT16 switchVal = (J << 1) | F ; |
| 4243 | | |
| 4244 | | switch (switchVal) |
| 4245 | | { |
| 4246 | | case 0x0: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X; dst_ret->data_type = DT_DOUBLE_WORD; break; |
| 4247 | | case 0x1: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X; dst_ret->data_type = DT_DOUBLE_WORD; break; |
| 4248 | | case 0x2: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y; dst_ret->data_type = DT_DOUBLE_WORD; break; |
| 4249 | | case 0x3: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y; dst_ret->data_type = DT_DOUBLE_WORD; break; |
| 4250 | | } |
| 4251 | | } |
| 4252 | | |
| 4253 | | static void decode_KKK_table(dsp56k_core* cpustate, UINT16 KKK, typed_pointer* dst_ret1, typed_pointer* dst_ret2, void* working) |
| 4254 | | { |
| 4255 | | void *opposite = 0x00 ; |
| 4256 | | |
| 4257 | | if (working == &A) opposite = &B ; |
| 4258 | | else opposite = &A ; |
| 4259 | | |
| 4260 | | switch(KKK) |
| 4261 | | { |
| 4262 | | case 0x0: dst_ret1->addr = opposite; dst_ret1->data_type = DT_LONG_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break; |
| 4263 | | case 0x1: dst_ret1->addr = &Y0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break; |
| 4264 | | case 0x2: dst_ret1->addr = &X1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break; |
| 4265 | | case 0x3: dst_ret1->addr = &Y1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break; |
| 4266 | | case 0x4: dst_ret1->addr = &X0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break; |
| 4267 | | case 0x5: dst_ret1->addr = &Y0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break; |
| 4268 | | case 0x6: dst_ret1->addr = opposite; dst_ret1->data_type = DT_LONG_WORD; dst_ret2->addr = &Y0; dst_ret2->data_type = DT_WORD; break; |
| 4269 | | case 0x7: dst_ret1->addr = &Y1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break; |
| 4270 | | } |
| 4271 | | } |
| 4272 | | |
| 4273 | | static void decode_QQF_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D) |
| 4274 | | { |
| 4275 | | UINT16 switchVal = (QQ << 1) | F ; |
| 4276 | | |
| 4277 | | switch(switchVal) |
| 4278 | | { |
| 4279 | | case 0x0: *S1 = &X0; *S2 = &Y0; *D = &A; break; |
| 4280 | | case 0x1: *S1 = &X0; *S2 = &Y0; *D = &B; break; |
| 4281 | | case 0x2: *S1 = &X0; *S2 = &Y1; *D = &A; break; |
| 4282 | | case 0x3: *S1 = &X0; *S2 = &Y1; *D = &B; break; |
| 4283 | | case 0x4: *S1 = &X1; *S2 = &Y0; *D = &A; break; |
| 4284 | | case 0x5: *S1 = &X1; *S2 = &Y0; *D = &B; break; |
| 4285 | | case 0x6: *S1 = &X1; *S2 = &Y1; *D = &A; break; |
| 4286 | | case 0x7: *S1 = &X1; *S2 = &Y1; *D = &B; break; |
| 4287 | | } |
| 4288 | | } |
| 4289 | | |
| 4290 | | static void decode_QQF_special_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D) |
| 4291 | | { |
| 4292 | | UINT16 switchVal = (QQ << 1) | F ; |
| 4293 | | |
| 4294 | | switch(switchVal) |
| 4295 | | { |
| 4296 | | case 0x0: *S1 = &Y0; *S2 = &X0; *D = &A; break; |
| 4297 | | case 0x1: *S1 = &Y0; *S2 = &X0; *D = &B; break; |
| 4298 | | case 0x2: *S1 = &Y1; *S2 = &X0; *D = &A; break; |
| 4299 | | case 0x3: *S1 = &Y1; *S2 = &X0; *D = &B; break; |
| 4300 | | case 0x4: *S1 = &X1; *S2 = &Y0; *D = &A; break; |
| 4301 | | case 0x5: *S1 = &X1; *S2 = &Y0; *D = &B; break; |
| 4302 | | case 0x6: *S1 = &X1; *S2 = &Y1; *D = &A; break; |
| 4303 | | case 0x7: *S1 = &X1; *S2 = &Y1; *D = &B; break; |
| 4304 | | } |
| 4305 | | } |
| 4306 | | |
| 4307 | | static void decode_QQQF_table(dsp56k_core* cpustate, UINT16 QQQ, UINT16 F, void **S1, void **S2, void **D) |
| 4308 | | { |
| 4309 | | UINT16 switchVal = (QQQ << 1) | F; |
| 4310 | | |
| 4311 | | switch(switchVal) |
| 4312 | | { |
| 4313 | | case 0x0: *S1 = &X0; *S2 = &X0; *D = &A; break; |
| 4314 | | case 0x1: *S1 = &X0; *S2 = &X0; *D = &B; break; |
| 4315 | | case 0x2: *S1 = &X1; *S2 = &X0; *D = &A; break; |
| 4316 | | case 0x3: *S1 = &X1; *S2 = &X0; *D = &B; break; |
| 4317 | | case 0x4: *S1 = &A1; *S2 = &Y0; *D = &A; break; |
| 4318 | | case 0x5: *S1 = &A1; *S2 = &Y0; *D = &B; break; |
| 4319 | | case 0x6: *S1 = &B1; *S2 = &X0; *D = &A; break; |
| 4320 | | case 0x7: *S1 = &B1; *S2 = &X0; *D = &B; break; |
| 4321 | | case 0x8: *S1 = &Y0; *S2 = &X0; *D = &A; break; |
| 4322 | | case 0x9: *S1 = &Y0; *S2 = &X0; *D = &B; break; |
| 4323 | | case 0xa: *S1 = &Y1; *S2 = &X0; *D = &A; break; |
| 4324 | | case 0xb: *S1 = &Y1; *S2 = &X0; *D = &B; break; |
| 4325 | | case 0xc: *S1 = &Y0; *S2 = &X1; *D = &A; break; |
| 4326 | | case 0xd: *S1 = &Y0; *S2 = &X1; *D = &B; break; |
| 4327 | | case 0xe: *S1 = &Y1; *S2 = &X1; *D = &A; break; |
| 4328 | | case 0xf: *S1 = &Y1; *S2 = &X1; *D = &B; break; |
| 4329 | | } |
| 4330 | | } |
| 4331 | | |
| 4332 | | static void decode_RR_table(dsp56k_core* cpustate, UINT16 RR, typed_pointer* ret) |
| 4333 | | { |
| 4334 | | switch(RR) |
| 4335 | | { |
| 4336 | | case 0x00: ret->addr = &R0; ret->data_type = DT_WORD; break; |
| 4337 | | case 0x01: ret->addr = &R1; ret->data_type = DT_WORD; break; |
| 4338 | | case 0x02: ret->addr = &R2; ret->data_type = DT_WORD; break; |
| 4339 | | case 0x03: ret->addr = &R3; ret->data_type = DT_WORD; break; |
| 4340 | | } |
| 4341 | | } |
| 4342 | | |
| 4343 | | static void decode_TT_table(dsp56k_core* cpustate, UINT16 TT, typed_pointer* ret) |
| 4344 | | { |
| 4345 | | switch(TT) |
| 4346 | | { |
| 4347 | | case 0x00: ret->addr = &R0; ret->data_type = DT_WORD; break; |
| 4348 | | case 0x01: ret->addr = &R1; ret->data_type = DT_WORD; break; |
| 4349 | | case 0x02: ret->addr = &R2; ret->data_type = DT_WORD; break; |
| 4350 | | case 0x03: ret->addr = &R3; ret->data_type = DT_WORD; break; |
| 4351 | | } |
| 4352 | | } |
| 4353 | | |
| 4354 | | |
| 4355 | | static void decode_uuuuF_table(dsp56k_core* cpustate, UINT16 uuuu, UINT16 F, UINT8 add_sub_other, typed_pointer* src_ret, typed_pointer* dst_ret) |
| 4356 | | { |
| 4357 | | UINT16 switchVal = (uuuu << 1) | F; |
| 4358 | | |
| 4359 | | /* Unknown uuuuFs have been seen in the wild */ |
| 4360 | | add_sub_other = OP_OTHER; |
| 4361 | | src_ret->addr = NULL; src_ret->data_type = DT_BYTE; |
| 4362 | | dst_ret->addr = NULL; dst_ret->data_type = DT_BYTE; |
| 4363 | | |
| 4364 | | switch(switchVal) |
| 4365 | | { |
| 4366 | | case 0x00: add_sub_other = OP_ADD; |
| 4367 | | src_ret->addr = &X0; src_ret->data_type = DT_WORD; |
| 4368 | | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4369 | | case 0x08: add_sub_other = OP_SUB; |
| 4370 | | src_ret->addr = &X0; src_ret->data_type = DT_WORD; |
| 4371 | | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4372 | | case 0x01: add_sub_other = OP_ADD; |
| 4373 | | src_ret->addr = &X0; src_ret->data_type = DT_WORD; |
| 4374 | | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4375 | | case 0x09: add_sub_other = OP_SUB; |
| 4376 | | src_ret->addr = &X0; src_ret->data_type = DT_WORD; |
| 4377 | | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4378 | | case 0x02: add_sub_other = OP_ADD; |
| 4379 | | src_ret->addr = &Y0; src_ret->data_type = DT_WORD; |
| 4380 | | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4381 | | case 0x0a: add_sub_other = OP_SUB; |
| 4382 | | src_ret->addr = &Y0; src_ret->data_type = DT_WORD; |
| 4383 | | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4384 | | case 0x03: add_sub_other = OP_ADD; |
| 4385 | | src_ret->addr = &Y0; src_ret->data_type = DT_WORD; |
| 4386 | | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4387 | | case 0x0b: add_sub_other = OP_SUB; |
| 4388 | | src_ret->addr = &Y0; src_ret->data_type = DT_WORD; |
| 4389 | | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4390 | | case 0x04: add_sub_other = OP_ADD; |
| 4391 | | src_ret->addr = &X1; src_ret->data_type = DT_WORD; |
| 4392 | | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4393 | | case 0x0c: add_sub_other = OP_SUB; |
| 4394 | | src_ret->addr = &X1; src_ret->data_type = DT_WORD; |
| 4395 | | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4396 | | case 0x05: add_sub_other = OP_ADD; |
| 4397 | | src_ret->addr = &X1; src_ret->data_type = DT_WORD; |
| 4398 | | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4399 | | case 0x0d: add_sub_other = OP_SUB; |
| 4400 | | src_ret->addr = &X1; src_ret->data_type = DT_WORD; |
| 4401 | | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4402 | | case 0x06: add_sub_other = OP_ADD; |
| 4403 | | src_ret->addr = &Y1; src_ret->data_type = DT_WORD; |
| 4404 | | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4405 | | case 0x0e: add_sub_other = OP_SUB; |
| 4406 | | src_ret->addr = &Y1; src_ret->data_type = DT_WORD; |
| 4407 | | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4408 | | case 0x07: add_sub_other = OP_ADD; |
| 4409 | | src_ret->addr = &Y1; src_ret->data_type = DT_WORD; |
| 4410 | | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4411 | | case 0x0f: add_sub_other = OP_SUB; |
| 4412 | | src_ret->addr = &Y1; src_ret->data_type = DT_WORD; |
| 4413 | | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4414 | | case 0x18: add_sub_other = OP_ADD; |
| 4415 | | src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; |
| 4416 | | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4417 | | case 0x1a: add_sub_other = OP_SUB; |
| 4418 | | src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; |
| 4419 | | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4420 | | case 0x19: add_sub_other = OP_ADD; |
| 4421 | | src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; |
| 4422 | | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4423 | | case 0x1b: add_sub_other = OP_SUB; |
| 4424 | | src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; |
| 4425 | | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4426 | | } |
| 4427 | | } |
| 4428 | | |
| 4429 | | static void decode_Z_table(dsp56k_core* cpustate, UINT16 Z, typed_pointer* ret) |
| 4430 | | { |
| 4431 | | switch(Z) |
| 4432 | | { |
| 4433 | | /* Fixed as per the Family Manual addendum */ |
| 4434 | | case 0x01: ret->addr = &A1; ret->data_type = DT_WORD; break; |
| 4435 | | case 0x00: ret->addr = &B1; ret->data_type = DT_WORD; break; |
| 4436 | | } |
| 4437 | | } |
| 4438 | | |
| 4439 | | static void execute_m_table(dsp56k_core* cpustate, int x, UINT16 m) |
| 4440 | | { |
| 4441 | | UINT16 *rX = 0x00 ; |
| 4442 | | UINT16 *nX = 0x00 ; |
| 4443 | | |
| 4444 | | switch(x) |
| 4445 | | { |
| 4446 | | case 0x0: rX = &R0; nX = &N0; break; |
| 4447 | | case 0x1: rX = &R1; nX = &N1; break; |
| 4448 | | case 0x2: rX = &R2; nX = &N2; break; |
| 4449 | | case 0x3: rX = &R3; nX = &N3; break; |
| 4450 | | } |
| 4451 | | |
| 4452 | | switch(m) |
| 4453 | | { |
| 4454 | | case 0x0: (*rX)++; break; |
| 4455 | | case 0x1: (*rX) = (*rX)+(*nX); break; |
| 4456 | | } |
| 4457 | | } |
| 4458 | | |
| 4459 | | static void execute_mm_table(dsp56k_core* cpustate, UINT16 rnum, UINT16 mm) |
| 4460 | | { |
| 4461 | | UINT16 *rX = NULL; |
| 4462 | | UINT16 *nX = NULL; |
| 4463 | | |
| 4464 | | switch(rnum) |
| 4465 | | { |
| 4466 | | case 0x0: rX = &R0; nX = &N0; break; |
| 4467 | | case 0x1: rX = &R1; nX = &N1; break; |
| 4468 | | case 0x2: rX = &R2; nX = &N2; break; |
| 4469 | | case 0x3: fatalerror("Dsp56k: Error. execute_mm_table specified R3 as its first source!\n"); break; |
| 4470 | | } |
| 4471 | | |
| 4472 | | switch(mm) |
| 4473 | | { |
| 4474 | | case 0x0: (*rX)++; R3++; break; |
| 4475 | | case 0x1: (*rX)++; R3 = R3 + N3; break; |
| 4476 | | case 0x2: (*rX) = (*rX) + (*nX); R3++; break; |
| 4477 | | case 0x3: (*rX) = (*rX) + (*nX); R3 = R3 + N3; break; |
| 4478 | | } |
| 4479 | | } |
| 4480 | | |
| 4481 | | static void execute_MM_table(dsp56k_core* cpustate, UINT16 rnum, UINT16 MM) |
| 4482 | | { |
| 4483 | | UINT16 *rX = 0x00 ; |
| 4484 | | UINT16 *nX = 0x00 ; |
| 4485 | | |
| 4486 | | switch(rnum) |
| 4487 | | { |
| 4488 | | case 0x0: rX = &R0; nX = &N0; break; |
| 4489 | | case 0x1: rX = &R1; nX = &N1; break; |
| 4490 | | case 0x2: rX = &R2; nX = &N2; break; |
| 4491 | | case 0x3: rX = &R3; nX = &N3; break; |
| 4492 | | } |
| 4493 | | |
| 4494 | | switch(MM) |
| 4495 | | { |
| 4496 | | case 0x0: /* do nothing */ break; |
| 4497 | | case 0x1: (*rX)++ ; break; |
| 4498 | | case 0x2: (*rX)-- ; break; |
| 4499 | | case 0x3: (*rX) = (*rX)+(*nX) ; break; |
| 4500 | | } |
| 4501 | | } |
| 4502 | | |
| 4503 | | /* Returns R value */ |
| 4504 | | static UINT16 execute_q_table(dsp56k_core* cpustate, int RR, UINT16 q) |
| 4505 | | { |
| 4506 | | UINT16 *rX = 0x0000; |
| 4507 | | UINT16 *nX = 0x0000; |
| 4508 | | |
| 4509 | | switch(RR) |
| 4510 | | { |
| 4511 | | case 0x0: rX = &R0; nX = &N0; break; |
| 4512 | | case 0x1: rX = &R1; nX = &N1; break; |
| 4513 | | case 0x2: rX = &R2; nX = &N2; break; |
| 4514 | | case 0x3: rX = &R3; nX = &N3; break; |
| 4515 | | } |
| 4516 | | |
| 4517 | | switch(q) |
| 4518 | | { |
| 4519 | | case 0x0: /* No permanent changes */ ; return (*rX)+(*nX); |
| 4520 | | case 0x1: (*rX)--; return (*rX); /* This one is special - it's a *PRE-decrement*! */ |
| 4521 | | } |
| 4522 | | |
| 4523 | | /* Should not get here */ |
| 4524 | | fatalerror("dsp56k: execute_q_table did something impossible!\n"); |
| 4525 | | return 0; |
| 4526 | | } |
| 4527 | | |
| 4528 | | static void execute_z_table(dsp56k_core* cpustate, int RR, UINT16 z) |
| 4529 | | { |
| 4530 | | UINT16 *rX = 0x00; |
| 4531 | | UINT16 *nX = 0x00; |
| 4532 | | |
| 4533 | | switch(RR) |
| 4534 | | { |
| 4535 | | case 0x0: rX = &R0; nX = &N0; break; |
| 4536 | | case 0x1: rX = &R1; nX = &N1; break; |
| 4537 | | case 0x2: rX = &R2; nX = &N2; break; |
| 4538 | | case 0x3: rX = &R3; nX = &N3; break; |
| 4539 | | } |
| 4540 | | |
| 4541 | | switch(z) |
| 4542 | | { |
| 4543 | | case 0x0: (*rX)--; break; |
| 4544 | | case 0x1: (*rX) = (*rX) + (*nX); break; |
| 4545 | | } |
| 4546 | | } |
| 4547 | | |
| 4548 | | static UINT16 assemble_address_from_Pppppp_table(dsp56k_core* cpustate, UINT16 P, UINT16 ppppp) |
| 4549 | | { |
| 4550 | | UINT16 destAddr = 0x00 ; |
| 4551 | | |
| 4552 | | switch (P) |
| 4553 | | { |
| 4554 | | case 0x0: destAddr = ppppp; break; /* TODO: Does this really only address up to 0x32? */ |
| 4555 | | case 0x1: destAddr = assemble_address_from_IO_short_address(cpustate, ppppp); break; |
| 4556 | | } |
| 4557 | | |
| 4558 | | return destAddr ; |
| 4559 | | } |
| 4560 | | |
| 4561 | | static UINT16 assemble_address_from_IO_short_address(dsp56k_core* cpustate, UINT16 pp) |
| 4562 | | { |
| 4563 | | UINT16 fullAddy = 0xffe0; |
| 4564 | | fullAddy |= pp; |
| 4565 | | return fullAddy; |
| 4566 | | } |
| 4567 | | |
| 4568 | | static UINT16 assemble_address_from_6bit_signed_relative_short_address(dsp56k_core* cpustate, UINT16 srs) |
| 4569 | | { |
| 4570 | | UINT16 fullAddy = srs ; |
| 4571 | | if (fullAddy & 0x0020) |
| 4572 | | fullAddy |= 0xffc0 ; |
| 4573 | | |
| 4574 | | return fullAddy ; |
| 4575 | | } |
| 4576 | | |
| 4577 | | static void dsp56k_process_loop(dsp56k_core* cpustate) |
| 4578 | | { |
| 4579 | | /* TODO: This might not work for dos nested in doForevers */ |
| 4580 | | if (LF_bit(cpustate) && FV_bit(cpustate)) |
| 4581 | | { |
| 4582 | | /* Do Forever*/ |
| 4583 | | if (PC == LA) |
| 4584 | | { |
| 4585 | | LC--; |
| 4586 | | |
| 4587 | | cpustate->ppc = PC; |
| 4588 | | PC = SSH; |
| 4589 | | } |
| 4590 | | } |
| 4591 | | else if (LF_bit(cpustate)) |
| 4592 | | { |
| 4593 | | /* Do */ |
| 4594 | | if (PC == LA) |
| 4595 | | { |
| 4596 | | if (LC == 1) |
| 4597 | | { |
| 4598 | | /* End of loop processing */ |
| 4599 | | SR = SSL; /* TODO: A-83. I believe only the Loop Flag comes back here. And maybe the do forever bit too. */ |
| 4600 | | SP--; |
| 4601 | | |
| 4602 | | LA = SSH; |
| 4603 | | LC = SSL; |
| 4604 | | SP--; |
| 4605 | | } |
| 4606 | | else |
| 4607 | | { |
| 4608 | | LC--; |
| 4609 | | PC = SSH; |
| 4610 | | } |
| 4611 | | } |
| 4612 | | } |
| 4613 | | } |
| 4614 | | |
| 4615 | | static void dsp56k_process_rep(dsp56k_core* cpustate, size_t repSize) |
| 4616 | | { |
| 4617 | | if (cpustate->repFlag) |
| 4618 | | { |
| 4619 | | if (PC == cpustate->repAddr) |
| 4620 | | { |
| 4621 | | if (LC == 1) |
| 4622 | | { |
| 4623 | | /* End of rep processing */ |
| 4624 | | LC = TEMP; |
| 4625 | | cpustate->repFlag = 0; |
| 4626 | | cpustate->repAddr = 0x0000; |
| 4627 | | } |
| 4628 | | else |
| 4629 | | { |
| 4630 | | LC--; |
| 4631 | | PC -= repSize; /* A little strange - rewind by the size of the rep'd op */ |
| 4632 | | } |
| 4633 | | } |
| 4634 | | } |
| 4635 | | } |
| 4636 | | |
| 4637 | | |
| 4638 | | /*************************************************************************** |
| 4639 | | Parallel Memory Ops |
| 4640 | | ***************************************************************************/ |
| 4641 | | /* Register to Register Data Move : 0100 IIII .... .... : A-132 */ |
| 4642 | | static void execute_register_to_register_data_move(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value) |
| 4643 | | { |
| 4644 | | typed_pointer S = {NULL, DT_BYTE}; |
| 4645 | | typed_pointer D = {NULL, DT_BYTE}; |
| 4646 | | |
| 4647 | | decode_IIII_table(cpustate, BITS(op,0x0f00), &S, &D, d_register->addr); |
| 4648 | | |
| 4649 | | /* If the source is the same as the ALU destination, use the previous accumulator value */ |
| 4650 | | if (d_register->addr == S.addr) |
| 4651 | | { |
| 4652 | | typed_pointer tempTP; |
| 4653 | | tempTP.addr = prev_accum_value; |
| 4654 | | tempTP.data_type = DT_LONG_WORD; |
| 4655 | | SetDestinationValue(tempTP, D); |
| 4656 | | } |
| 4657 | | else |
| 4658 | | { |
| 4659 | | SetDestinationValue(S, D); |
| 4660 | | } |
| 4661 | | } |
| 4662 | | |
| 4663 | | /* Address Register Update : 0011 0zRR .... .... : A-135 */ |
| 4664 | | static void execute_address_register_update(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value) |
| 4665 | | { |
| 4666 | | execute_z_table(cpustate, BITS(op,0x0300), BITS(op,0x0400)); |
| 4667 | | } |
| 4668 | | |
| 4669 | | /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */ |
| 4670 | | static void execute_x_memory_data_move(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value) |
| 4671 | | { |
| 4672 | | UINT16 W; |
| 4673 | | typed_pointer R = {NULL, DT_BYTE}; |
| 4674 | | typed_pointer SD = {NULL, DT_BYTE}; |
| 4675 | | |
| 4676 | | W = BITS(op,0x0100); |
| 4677 | | decode_HHH_table(cpustate, BITS(op,0x0e00), &SD); |
| 4678 | | decode_RR_table(cpustate, BITS(op,0x3000),&R); |
| 4679 | | |
| 4680 | | if (W) |
| 4681 | | { |
| 4682 | | /* From X:<ea> to SD */ |
| 4683 | | UINT16 data = cpustate->data->read_word(ADDRESS(*((UINT16*)R.addr))); |
| 4684 | | |
| 4685 | | typed_pointer tempTP; |
| 4686 | | tempTP.addr = &data; |
| 4687 | | tempTP.data_type = DT_WORD; |
| 4688 | | |
| 4689 | | SetDestinationValue(tempTP, SD); |
| 4690 | | } |
| 4691 | | else |
| 4692 | | { |
| 4693 | | /* From SD to X:<ea> */ |
| 4694 | | /* If the source is the same as the ALU destination, use the previous accumulator value */ |
| 4695 | | if (d_register->addr == SD.addr) |
| 4696 | | { |
| 4697 | | typed_pointer tempTP; |
| 4698 | | tempTP.addr = prev_accum_value; |
| 4699 | | tempTP.data_type = DT_LONG_WORD; |
| 4700 | | |
| 4701 | | SetDataMemoryValue(cpustate, tempTP, ADDRESS(*((UINT16*)R.addr))) ; |
| 4702 | | } |
| 4703 | | else |
| 4704 | | { |
| 4705 | | SetDataMemoryValue(cpustate, SD, ADDRESS(*((UINT16*)R.addr))) ; |
| 4706 | | } |
| 4707 | | } |
| 4708 | | |
| 4709 | | execute_m_table(cpustate, BITS(op,0x3000), BITS(op,0x4000)); |
| 4710 | | } |
| 4711 | | |
| 4712 | | /* X Memory Data Move : 0101 HHHW .... .... : A-137 */ |
| 4713 | | /* NOTE: previous accumulator value is not needed since ^F1 is always the opposite accumulator */ |
| 4714 | | static void execute_x_memory_data_move2(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register) |
| 4715 | | { |
| 4716 | | UINT16 W; |
| 4717 | | UINT16* mem_offset = NULL; |
| 4718 | | typed_pointer SD = {NULL, DT_BYTE}; |
| 4719 | | |
| 4720 | | W = BITS(op,0x0100); |
| 4721 | | decode_HHH_table(cpustate, BITS(op,0x0e000), &SD); |
| 4722 | | |
| 4723 | | if (d_register->addr == &A) |
| 4724 | | mem_offset = &B1; |
| 4725 | | else |
| 4726 | | mem_offset = &A1; |
| 4727 | | |
| 4728 | | if (W) |
| 4729 | | { |
| 4730 | | /* Write D */ |
| 4731 | | UINT16 value = cpustate->data->read_word(ADDRESS(*mem_offset)); |
| 4732 | | typed_pointer tempV = {&value, DT_WORD}; |
| 4733 | | SetDestinationValue(tempV, SD); |
| 4734 | | } |
| 4735 | | else |
| 4736 | | { |
| 4737 | | /* Read S */ |
| 4738 | | SetDataMemoryValue(cpustate, SD, ADDRESS(*mem_offset)); |
| 4739 | | } |
| 4740 | | } |
| 4741 | | |
| 4742 | | /* X Memory Data Move With Short Displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */ |
| 4743 | | static void execute_x_memory_data_move_with_short_displacement(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2) |
| 4744 | | { |
| 4745 | | INT8 xx; |
| 4746 | | UINT8 W; |
| 4747 | | UINT16 memOffset; |
| 4748 | | typed_pointer SD = { NULL, DT_BYTE }; |
| 4749 | | |
| 4750 | | xx = (INT8)(op & 0x00ff); |
| 4751 | | W = BITS(op2,0x0100); |
| 4752 | | decode_HHH_table(cpustate, BITS(op2,0x0e00), &SD); |
| 4753 | | |
| 4754 | | memOffset = R2 + (INT16)xx; |
| 4755 | | |
| 4756 | | if (W) |
| 4757 | | { |
| 4758 | | /* Write D */ |
| 4759 | | UINT16 tempData = cpustate->data->read_word(ADDRESS(memOffset)); |
| 4760 | | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 4761 | | SetDestinationValue(temp_src, SD); |
| 4762 | | } |
| 4763 | | else |
| 4764 | | { |
| 4765 | | /* Read S */ |
| 4766 | | UINT16 tempData = *((UINT16*)SD.addr); |
| 4767 | | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 4768 | | SetDataMemoryValue(cpustate, temp_src, ADDRESS(memOffset)); |
| 4769 | | } |
| 4770 | | } |
| 4771 | | |
| 4772 | | /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/ |
| 4773 | | static void execute_dual_x_memory_data_read(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register) |
| 4774 | | { |
| 4775 | | typed_pointer tempV; |
| 4776 | | UINT16 srcVal1 = 0x0000; |
| 4777 | | UINT16 srcVal2 = 0x0000; |
| 4778 | | typed_pointer R = {NULL, DT_BYTE}; |
| 4779 | | typed_pointer D1 = {NULL, DT_BYTE}; |
| 4780 | | typed_pointer D2 = {NULL, DT_BYTE}; |
| 4781 | | |
| 4782 | | decode_RR_table(cpustate, BITS(op,0x0060), &R); |
| 4783 | | decode_KKK_table(cpustate, BITS(op,0x0700), &D1, &D2, d_register->addr); |
| 4784 | | |
| 4785 | | /* Can't do an R3 for S1 */ |
| 4786 | | if (R.addr == &R3) |
| 4787 | | fatalerror("Dsp56k: Error. Dual x memory data read specified R3 as its first source!\n"); |
| 4788 | | |
| 4789 | | /* The note on A-142 is very interesting. |
| 4790 | | You can effectively access external memory in the last 64 bytes of X data memory! */ |
| 4791 | | if (*((UINT16*)D2.addr) >= 0xffc0) |
| 4792 | | fatalerror("Dsp56k: Unimplemented access to external X Data Memory >= 0xffc0 in Dual X Memory Data Read.\n"); |
| 4793 | | |
| 4794 | | /* First memmove */ |
| 4795 | | srcVal1 = cpustate->data->read_word(ADDRESS(*((UINT16*)R.addr))); |
| 4796 | | tempV.addr = &srcVal1; |
| 4797 | | tempV.data_type = DT_WORD; |
| 4798 | | SetDestinationValue(tempV, D1); |
| 4799 | | |
| 4800 | | /* Second memmove */ |
| 4801 | | srcVal2 = cpustate->data->read_word(ADDRESS(R3)); |
| 4802 | | tempV.addr = &srcVal2; |
| 4803 | | tempV.data_type = DT_WORD; |
| 4804 | | SetDestinationValue(tempV, D2); |
| 4805 | | |
| 4806 | | /* Touch up the R regs after all the moves */ |
| 4807 | | execute_mm_table(cpustate, BITS(op,0x0060), BITS(op,0x1800)); |
| 4808 | | } |
| 4809 | | |
| 4810 | | /*************************************************************************** |
| 4811 | | Helper Functions |
| 4812 | | ***************************************************************************/ |
| 4813 | | static UINT16 Dsp56kOpMask(UINT16 cur, UINT16 mask) |
| 4814 | | { |
| 4815 | | int i ; |
| 4816 | | |
| 4817 | | UINT16 retVal = (cur & mask) ; |
| 4818 | | UINT16 temp = 0x0000 ; |
| 4819 | | int offsetCount = 0 ; |
| 4820 | | |
| 4821 | | /* Shift everything right, eliminating 'whitespace' */ |
| 4822 | | for (i = 0; i < 16; i++) |
| 4823 | | { |
| 4824 | | if (mask & (0x1<<i)) /* If mask bit is non-zero */ |
| 4825 | | { |
| 4826 | | temp |= (((retVal >> i) & 0x1) << offsetCount) ; |
| 4827 | | offsetCount++ ; |
| 4828 | | } |
| 4829 | | } |
| 4830 | | |
| 4831 | | return temp ; |
| 4832 | | } |
| 4833 | | |
| 4834 | | static void SetDestinationValue(typed_pointer source, typed_pointer dest) |
| 4835 | | { |
| 4836 | | UINT64 destinationValue = 0 ; |
| 4837 | | |
| 4838 | | switch(dest.data_type) |
| 4839 | | { |
| 4840 | | /* Copying to an 8-bit value */ |
| 4841 | | case DT_BYTE: |
| 4842 | | switch(source.data_type) |
| 4843 | | { |
| 4844 | | /* From a ? */ |
| 4845 | | case DT_BYTE: *((UINT8*)dest.addr) = (*((UINT8*) source.addr)) & 0xff; break; |
| 4846 | | case DT_WORD: *((UINT8*)dest.addr) = (*((UINT16*)source.addr)) & 0x00ff; break; |
| 4847 | | case DT_DOUBLE_WORD: *((UINT8*)dest.addr) = (*((UINT32*)source.addr)) & 0x000000ff; break; |
| 4848 | | case DT_LONG_WORD: *((UINT8*)dest.addr) = (*((UINT64*)source.addr)) & U64(0x00000000000000ff); break; |
| 4849 | | } |
| 4850 | | break ; |
| 4851 | | |
| 4852 | | /* Copying to a 16-bit value */ |
| 4853 | | case DT_WORD: |
| 4854 | | switch(source.data_type) |
| 4855 | | { |
| 4856 | | case DT_BYTE: *((UINT16*)dest.addr) = (*((UINT8*) source.addr)) & 0xff; break; |
| 4857 | | case DT_WORD: *((UINT16*)dest.addr) = (*((UINT16*)source.addr)) & 0xffff; break; |
| 4858 | | case DT_DOUBLE_WORD: *((UINT16*)dest.addr) = (*((UINT32*)source.addr)) & 0x0000ffff; break; |
| 4859 | | case DT_LONG_WORD: *((UINT16*)dest.addr) = (*((UINT64*)source.addr)) & U64(0x000000000000ffff); break; /* TODO: Shift limiter action! A-147 */ |
| 4860 | | } |
| 4861 | | break ; |
| 4862 | | |
| 4863 | | /* Copying to a 32-bit value */ |
| 4864 | | case DT_DOUBLE_WORD: |
| 4865 | | switch(source.data_type) |
| 4866 | | { |
| 4867 | | case DT_BYTE: *((UINT32*)dest.addr) = (*((UINT8*) source.addr)) & 0xff; break; |
| 4868 | | case DT_WORD: *((UINT32*)dest.addr) = (*((UINT16*)source.addr)) & 0xffff; break; |
| 4869 | | case DT_DOUBLE_WORD: *((UINT32*)dest.addr) = (*((UINT32*)source.addr)) & 0xffffffff; break; |
| 4870 | | case DT_LONG_WORD: *((UINT32*)dest.addr) = (*((UINT64*)source.addr)) & U64(0x00000000ffffffff); break; |
| 4871 | | } |
| 4872 | | break ; |
| 4873 | | |
| 4874 | | /* Copying to a 64-bit value */ |
| 4875 | | case DT_LONG_WORD: |
| 4876 | | switch(source.data_type) |
| 4877 | | { |
| 4878 | | case DT_BYTE: *((UINT64*)dest.addr) = (*((UINT8*)source.addr)) & 0xff; break; |
| 4879 | | |
| 4880 | | case DT_WORD: destinationValue = (*((UINT16*)source.addr)) << 16; |
| 4881 | | if (destinationValue & U64(0x0000000080000000)) |
| 4882 | | destinationValue |= U64(0x000000ff00000000); |
| 4883 | | *((UINT64*)dest.addr) = (UINT64)destinationValue; break; /* Forget not, yon shift register */ |
| 4884 | | |
| 4885 | | case DT_DOUBLE_WORD: *((UINT64*)dest.addr) = (*((UINT32*)source.addr)) & 0xffffffff; break; |
| 4886 | | case DT_LONG_WORD: *((UINT64*)dest.addr) = (*((UINT64*)source.addr)) & U64(0x000000ffffffffff); break; |
| 4887 | | } |
| 4888 | | break ; |
| 4889 | | } |
| 4890 | | } |
| 4891 | | |
| 4892 | | /* TODO: Wait-state timings! */ |
| 4893 | | static void SetDataMemoryValue(dsp56k_core* cpustate, typed_pointer source, UINT32 destinationAddr) |
| 4894 | | { |
| 4895 | | switch(source.data_type) |
| 4896 | | { |
| 4897 | | case DT_BYTE: cpustate->data->write_word(destinationAddr, (UINT16)( (*((UINT8*) source.addr) & 0xff) ) ) ; break ; |
| 4898 | | case DT_WORD: cpustate->data->write_word(destinationAddr, (UINT16)( (*((UINT16*)source.addr) & 0xffff) ) ) ; break ; |
| 4899 | | case DT_DOUBLE_WORD: cpustate->data->write_word(destinationAddr, (UINT16)( (*((UINT32*)source.addr) & 0x0000ffff) ) ) ; break ; |
| 4900 | | |
| 4901 | | /* !!! Is this universal ??? */ |
| 4902 | | /* !!! Forget not, yon shift-limiter !!! */ |
| 4903 | | case DT_LONG_WORD: cpustate->data->write_word(destinationAddr, (UINT16)( ((*((UINT64*)source.addr)) & U64(0x00000000ffff0000)) >> 16) ) ; break ; |
| 4904 | | } |
| 4905 | | } |
| 4906 | | |
| 4907 | | /* TODO: Wait-state timings! */ |
| 4908 | | static void SetProgramMemoryValue(dsp56k_core* cpustate, typed_pointer source, UINT32 destinationAddr) |
| 4909 | | { |
| 4910 | | switch(source.data_type) |
| 4911 | | { |
| 4912 | | case DT_BYTE: cpustate->program->write_word(destinationAddr, (UINT16)( (*((UINT8*) source.addr) & 0xff) ) ) ; break ; |
| 4913 | | case DT_WORD: cpustate->program->write_word(destinationAddr, (UINT16)( (*((UINT16*)source.addr) & 0xffff) ) ) ; break ; |
| 4914 | | case DT_DOUBLE_WORD: cpustate->program->write_word(destinationAddr, (UINT16)( (*((UINT32*)source.addr) & 0x0000ffff) ) ) ; break ; |
| 4915 | | |
| 4916 | | /* !!! Is this universal ??? */ |
| 4917 | | /* !!! Forget not, yon shift-limiter !!! */ |
| 4918 | | case DT_LONG_WORD: cpustate->program->write_word(destinationAddr, (UINT16)( ((*((UINT64*)source.addr)) & U64(0x00000000ffff0000)) >> 16) ) ; break ; |
| 4919 | | } |
| 4920 | | } |
trunk/src/emu/cpu/dsp56k/dsp56ops.inc
| r0 | r28739 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | dsp56ops.inc |
| 4 | Core implementation for the portable Motorola/Freescale DSP56k emulator. |
| 5 | Written by Andrew Gardner |
| 6 | |
| 7 | ***************************************************************************/ |
| 8 | |
| 9 | /* NOTES For register setting: |
| 10 | FM.3-4 : When A2 or B2 is read, the register contents occupy the low-order portion |
| 11 | (bits 7-0) of the word; the high-order portion (bits 16-8) is sign-extended. When A2 or B2 |
| 12 | is written, the register receives the low-order portion of the word; the high-order portion is not used |
| 13 | : ...much more! |
| 14 | : ...shifter/limiter/overflow notes too. |
| 15 | |
| 16 | */ |
| 17 | |
| 18 | /* |
| 19 | TODO: |
| 20 | - 0x01ee: should this move sign extend? otherwise the test-against-minus means nothing. |
| 21 | - Restore only the proper bits upon loop termination! |
| 22 | - BFCLR has some errata in the docs that may need to be applied. |
| 23 | */ |
| 24 | |
| 25 | /************************/ |
| 26 | /* Datatypes and macros */ |
| 27 | /************************/ |
| 28 | enum addSubOpType { OP_ADD, |
| 29 | OP_SUB, |
| 30 | OP_OTHER }; |
| 31 | |
| 32 | enum dataType { DT_BYTE, |
| 33 | DT_WORD, |
| 34 | DT_DOUBLE_WORD, |
| 35 | DT_LONG_WORD }; |
| 36 | |
| 37 | struct typed_pointer |
| 38 | { |
| 39 | void* addr; |
| 40 | char data_type; |
| 41 | }; |
| 42 | |
| 43 | //#define ADDRESS(X) (X<<1) |
| 44 | #define BITS(CUR,MASK) (Dsp56kOpMask(CUR,MASK)) |
| 45 | |
| 46 | /*********************/ |
| 47 | /* Opcode prototypes */ |
| 48 | /*********************/ |
| 49 | static size_t dsp56k_op_addsub_2 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 50 | static size_t dsp56k_op_mac_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 51 | static size_t dsp56k_op_macr_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 52 | static size_t dsp56k_op_move_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 53 | static size_t dsp56k_op_mpy_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 54 | static size_t dsp56k_op_mpyr_1 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 55 | static size_t dsp56k_op_tfr_2 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles); |
| 56 | static size_t dsp56k_op_mpy_2 (dsp56k_core* cpustate, const UINT16 op_byte, UINT8* cycles); |
| 57 | static size_t dsp56k_op_mac_2 (dsp56k_core* cpustate, const UINT16 op_byte, UINT8* cycles); |
| 58 | static size_t dsp56k_op_clr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 59 | static size_t dsp56k_op_add (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 60 | static size_t dsp56k_op_move (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 61 | static size_t dsp56k_op_tfr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 62 | static size_t dsp56k_op_rnd (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 63 | static size_t dsp56k_op_tst (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 64 | static size_t dsp56k_op_inc (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 65 | static size_t dsp56k_op_inc24 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 66 | static size_t dsp56k_op_or (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 67 | static size_t dsp56k_op_asr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 68 | static size_t dsp56k_op_asl (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 69 | static size_t dsp56k_op_lsr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 70 | static size_t dsp56k_op_lsl (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 71 | static size_t dsp56k_op_eor (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 72 | static size_t dsp56k_op_subl (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 73 | static size_t dsp56k_op_sub (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 74 | static size_t dsp56k_op_clr24 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 75 | static size_t dsp56k_op_sbc (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 76 | static size_t dsp56k_op_cmp (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 77 | static size_t dsp56k_op_neg (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 78 | static size_t dsp56k_op_not (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 79 | static size_t dsp56k_op_dec (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 80 | static size_t dsp56k_op_dec24 (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 81 | static size_t dsp56k_op_and (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 82 | static size_t dsp56k_op_abs (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 83 | static size_t dsp56k_op_ror (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 84 | static size_t dsp56k_op_rol (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 85 | static size_t dsp56k_op_cmpm (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 86 | static size_t dsp56k_op_mpy (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 87 | static size_t dsp56k_op_mpyr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 88 | static size_t dsp56k_op_mac (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 89 | static size_t dsp56k_op_macr (dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles); |
| 90 | static size_t dsp56k_op_adc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 91 | static size_t dsp56k_op_andi (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 92 | static size_t dsp56k_op_asl4 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 93 | static size_t dsp56k_op_asr4 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 94 | static size_t dsp56k_op_asr16 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 95 | static size_t dsp56k_op_bfop (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 96 | static size_t dsp56k_op_bfop_1 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 97 | static size_t dsp56k_op_bfop_2 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 98 | static size_t dsp56k_op_bcc (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 99 | static size_t dsp56k_op_bcc_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 100 | static size_t dsp56k_op_bcc_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 101 | static size_t dsp56k_op_bra (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 102 | static size_t dsp56k_op_bra_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 103 | static size_t dsp56k_op_bra_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 104 | static size_t dsp56k_op_brkcc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 105 | static size_t dsp56k_op_bscc (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 106 | static size_t dsp56k_op_bscc_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 107 | static size_t dsp56k_op_bsr (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 108 | static size_t dsp56k_op_bsr_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 109 | static size_t dsp56k_op_chkaau (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 110 | static size_t dsp56k_op_debug (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 111 | static size_t dsp56k_op_debugcc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 112 | static size_t dsp56k_op_div (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 113 | static size_t dsp56k_op_dmac (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 114 | static size_t dsp56k_op_do (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 115 | static size_t dsp56k_op_do_1 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 116 | static size_t dsp56k_op_do_2 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 117 | static size_t dsp56k_op_doforever(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 118 | static size_t dsp56k_op_enddo (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 119 | static size_t dsp56k_op_ext (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 120 | static size_t dsp56k_op_illegal (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 121 | static size_t dsp56k_op_imac (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 122 | static size_t dsp56k_op_impy (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 123 | static size_t dsp56k_op_jcc (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 124 | static size_t dsp56k_op_jcc_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 125 | static size_t dsp56k_op_jmp (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 126 | static size_t dsp56k_op_jmp_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 127 | static size_t dsp56k_op_jscc (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 128 | static size_t dsp56k_op_jscc_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 129 | static size_t dsp56k_op_jsr (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 130 | static size_t dsp56k_op_jsr_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 131 | static size_t dsp56k_op_jsr_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 132 | static size_t dsp56k_op_lea (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 133 | static size_t dsp56k_op_lea_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 134 | static size_t dsp56k_op_macsuuu (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 135 | static size_t dsp56k_op_move_2 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 136 | static size_t dsp56k_op_movec (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 137 | static size_t dsp56k_op_movec_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 138 | static size_t dsp56k_op_movec_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 139 | static size_t dsp56k_op_movec_3 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 140 | static size_t dsp56k_op_movec_4 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 141 | static size_t dsp56k_op_movec_5 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 142 | static size_t dsp56k_op_movei (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 143 | static size_t dsp56k_op_movem (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 144 | static size_t dsp56k_op_movem_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 145 | static size_t dsp56k_op_movem_2 (dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles); |
| 146 | static size_t dsp56k_op_movep (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 147 | static size_t dsp56k_op_movep_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 148 | static size_t dsp56k_op_moves (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 149 | static size_t dsp56k_op_mpysuuu (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 150 | static size_t dsp56k_op_negc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 151 | static size_t dsp56k_op_nop (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 152 | static size_t dsp56k_op_norm (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 153 | static size_t dsp56k_op_ori (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 154 | static size_t dsp56k_op_rep (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 155 | static size_t dsp56k_op_rep_1 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 156 | static size_t dsp56k_op_rep_2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 157 | static size_t dsp56k_op_repcc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 158 | static size_t dsp56k_op_reset (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 159 | static size_t dsp56k_op_rti (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 160 | static size_t dsp56k_op_rts (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 161 | static size_t dsp56k_op_stop (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 162 | static size_t dsp56k_op_swap (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 163 | static size_t dsp56k_op_swi (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 164 | static size_t dsp56k_op_tcc (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 165 | static size_t dsp56k_op_tfr2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 166 | static size_t dsp56k_op_tfr3 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 167 | static size_t dsp56k_op_tst2 (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 168 | static size_t dsp56k_op_wait (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 169 | static size_t dsp56k_op_zero (dsp56k_core* cpustate, const UINT16 op, UINT8* cycles); |
| 170 | |
| 171 | |
| 172 | static void execute_register_to_register_data_move(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value); |
| 173 | static void execute_address_register_update(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value); |
| 174 | static void execute_x_memory_data_move (dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value); |
| 175 | static void execute_x_memory_data_move2(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register); |
| 176 | static void execute_dual_x_memory_data_read(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register); |
| 177 | static void execute_x_memory_data_move_with_short_displacement(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2); |
| 178 | |
| 179 | static UINT16 decode_BBB_bitmask(dsp56k_core* cpustate, UINT16 BBB, UINT16 *iVal); |
| 180 | static int decode_cccc_table(dsp56k_core* cpustate, UINT16 cccc); |
| 181 | static void decode_DDDDD_table(dsp56k_core* cpustate, UINT16 DDDDD, typed_pointer* ret); |
| 182 | static void decode_DD_table(dsp56k_core* cpustate, UINT16 DD, typed_pointer* ret); |
| 183 | static void decode_DDF_table(dsp56k_core* cpustate, UINT16 DD, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret); |
| 184 | static void decode_F_table(dsp56k_core* cpustate, UINT16 F, typed_pointer* ret); |
| 185 | static void decode_h0hF_table(dsp56k_core* cpustate, UINT16 h0h, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret); |
| 186 | static void decode_HH_table(dsp56k_core* cpustate, UINT16 HH, typed_pointer* ret); |
| 187 | static void decode_HHH_table(dsp56k_core* cpustate, UINT16 HHH, typed_pointer* ret); |
| 188 | static void decode_IIII_table(dsp56k_core* cpustate, UINT16 IIII, typed_pointer* src_ret, typed_pointer* dst_ret, void* working); |
| 189 | static void decode_JJJF_table(dsp56k_core* cpustate, UINT16 JJJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret); |
| 190 | static void decode_JJF_table(dsp56k_core* cpustate, UINT16 JJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret); |
| 191 | static void decode_JF_table(dsp56k_core* cpustate, UINT16 JJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret); |
| 192 | static void decode_KKK_table(dsp56k_core* cpustate, UINT16 KKK, typed_pointer* dst_ret1, typed_pointer* dst_ret2, void* working); |
| 193 | static void decode_QQF_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D); |
| 194 | static void decode_QQF_special_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D); |
| 195 | static void decode_QQQF_table(dsp56k_core* cpustate, UINT16 QQQ, UINT16 F, void **S1, void **S2, void **D); |
| 196 | static void decode_RR_table(dsp56k_core* cpustate, UINT16 RR, typed_pointer* ret); |
| 197 | static void decode_TT_table(dsp56k_core* cpustate, UINT16 TT, typed_pointer* ret); |
| 198 | static void decode_uuuuF_table(dsp56k_core* cpustate, UINT16 uuuu, UINT16 F, UINT8 add_sub_other, typed_pointer* src_ret, typed_pointer* dst_ret); |
| 199 | static void decode_Z_table(dsp56k_core* cpustate, UINT16 Z, typed_pointer* ret); |
| 200 | |
| 201 | static void execute_m_table(dsp56k_core* cpustate, int x, UINT16 m); |
| 202 | static void execute_mm_table(dsp56k_core* cpustate, UINT16 rnum, UINT16 mm); |
| 203 | static void execute_MM_table(dsp56k_core* cpustate, UINT16 rnum, UINT16 MM); |
| 204 | static UINT16 execute_q_table(dsp56k_core* cpustate, int RR, UINT16 q); |
| 205 | static void execute_z_table(dsp56k_core* cpustate, int RR, UINT16 z); |
| 206 | |
| 207 | static UINT16 assemble_address_from_Pppppp_table(dsp56k_core* cpustate, UINT16 P, UINT16 ppppp); |
| 208 | static UINT16 assemble_address_from_IO_short_address(dsp56k_core* cpustate, UINT16 pp); |
| 209 | static UINT16 assemble_address_from_6bit_signed_relative_short_address(dsp56k_core* cpustate, UINT16 srs); |
| 210 | |
| 211 | static void dsp56k_process_loop(dsp56k_core* cpustate); |
| 212 | static void dsp56k_process_rep(dsp56k_core* cpustate, size_t repSize); |
| 213 | |
| 214 | |
| 215 | |
| 216 | /********************/ |
| 217 | /* Helper Functions */ |
| 218 | /********************/ |
| 219 | static UINT16 Dsp56kOpMask(UINT16 op, UINT16 mask); |
| 220 | |
| 221 | /* These arguments are written source->destination to fall in line with the processor's paradigm. */ |
| 222 | static void SetDestinationValue(typed_pointer source, typed_pointer dest); |
| 223 | |
| 224 | static void SetDataMemoryValue(dsp56k_core* cpustate, typed_pointer source, UINT32 destinationAddr); |
| 225 | static void SetProgramMemoryValue(dsp56k_core* cpustate, typed_pointer source, UINT32 destinationAddr); |
| 226 | |
| 227 | |
| 228 | |
| 229 | /*************************************************************************** |
| 230 | IMPLEMENTATION |
| 231 | ***************************************************************************/ |
| 232 | |
| 233 | static void execute_one(dsp56k_core* cpustate) |
| 234 | { |
| 235 | UINT16 op; |
| 236 | UINT16 op2; |
| 237 | size_t size = 0x1337; |
| 238 | UINT8 cycle_count = 0; |
| 239 | |
| 240 | /* For MAME */ |
| 241 | cpustate->op = ROPCODE(ADDRESS(PC)); |
| 242 | debugger_instruction_hook(cpustate->device, PC); |
| 243 | |
| 244 | /* The words we're going to be working with */ |
| 245 | op = ROPCODE(ADDRESS(PC)); |
| 246 | op2 = ROPCODE(ADDRESS(PC) + ADDRESS(1)); |
| 247 | |
| 248 | |
| 249 | /* DECODE */ |
| 250 | /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/ |
| 251 | if ((op & 0xe000) == 0x6000) |
| 252 | { |
| 253 | typed_pointer d_register = {NULL, DT_BYTE}; |
| 254 | |
| 255 | /* Quote: (MOVE, MAC(R), MPY(R), ADD, SUB, TFR) */ |
| 256 | UINT16 op_byte = op & 0x00ff; |
| 257 | |
| 258 | /* ADD : 011m mKKK 0rru Fuuu : A-22 */ |
| 259 | /* SUB : 011m mKKK 0rru Fuuu : A-202 */ |
| 260 | /* Note: 0x0094 check allows command to drop through to MOVE and TFR */ |
| 261 | if (((op & 0xe080) == 0x6000) && ((op & 0x0094) != 0x0010)) |
| 262 | { |
| 263 | size = dsp56k_op_addsub_2(cpustate, op_byte, &d_register, &cycle_count); |
| 264 | } |
| 265 | /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */ |
| 266 | else if ((op & 0xe094) == 0x6084) |
| 267 | { |
| 268 | size = dsp56k_op_mac_1(cpustate, op_byte, &d_register, &cycle_count); |
| 269 | } |
| 270 | /* MACR: 011m mKKK 1--1 F1QQ : A-124 */ |
| 271 | else if ((op & 0xe094) == 0x6094) |
| 272 | { |
| 273 | size = dsp56k_op_macr_1(cpustate, op_byte, &d_register, &cycle_count); |
| 274 | } |
| 275 | /* TFR : 011m mKKK 0rr1 F0DD : A-212 */ |
| 276 | else if ((op & 0xe094) == 0x6010) |
| 277 | { |
| 278 | size = dsp56k_op_tfr_2(cpustate, op_byte, &d_register, &cycle_count); |
| 279 | } |
| 280 | /* MOVE : 011m mKKK 0rr1 0000 : A-128 */ |
| 281 | else if ((op & 0xe09f) == 0x6010) |
| 282 | { |
| 283 | /* Note: The opcode encoding : 011x xxxx 0xx1 0000 (move + double memory read) |
| 284 | is .identical. to (tfr X0,A + two parallel reads). This sparks the notion |
| 285 | that these 'move' opcodes don't actually exist and are just there as |
| 286 | documentation. Real-world examples would need to be examined to come |
| 287 | to a satisfactory conclusion, but as it stands, tfr will override this |
| 288 | move operation. */ |
| 289 | size = dsp56k_op_move_1(cpustate, op_byte, &d_register, &cycle_count); |
| 290 | } |
| 291 | /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */ |
| 292 | else if ((op & 0xe094) == 0x6080) |
| 293 | { |
| 294 | size = dsp56k_op_mpy_1(cpustate, op_byte, &d_register, &cycle_count); |
| 295 | } |
| 296 | /* MPYR : 011m mKKK 1--1 F0QQ : A-162 */ |
| 297 | else if ((op & 0xe094) == 0x6090) |
| 298 | { |
| 299 | size = dsp56k_op_mpyr_1(cpustate, op_byte, &d_register, &cycle_count); |
| 300 | } |
| 301 | |
| 302 | /* Now evaluate the parallel data move */ |
| 303 | execute_dual_x_memory_data_read(cpustate, op, &d_register); |
| 304 | } |
| 305 | /* X Memory Data Write and Register Data Move : 0001 011k RRDD .... : A-140 */ |
| 306 | else if ((op & 0xfe00) == 0x1600) |
| 307 | { |
| 308 | /* Quote: (MPY or MAC) */ |
| 309 | UINT16 op_byte = op & 0x00ff; |
| 310 | |
| 311 | /* MPY : 0001 0110 RRDD FQQQ : A-160 */ |
| 312 | if ((op & 0xff00) == 0x1600) |
| 313 | { |
| 314 | size = dsp56k_op_mpy_2(cpustate, op_byte, &cycle_count); |
| 315 | } |
| 316 | /* MAC : 0001 0111 RRDD FQQQ : A-122 */ |
| 317 | else if ((op & 0xff00) == 0x1700) |
| 318 | { |
| 319 | size = dsp56k_op_mac_2(cpustate, op_byte, &cycle_count); |
| 320 | } |
| 321 | |
| 322 | /* Now evaluate the parallel data move */ |
| 323 | /* TODO // decode_x_memory_data_write_and_register_data_move(op, parallel_move_str, parallel_move_str2); */ |
| 324 | logerror("DSP56k: Unemulated Dual X Memory Data And Register Data Move @ 0x%x\n", PC); |
| 325 | } |
| 326 | |
| 327 | /* Handle Other parallel types */ |
| 328 | else |
| 329 | { |
| 330 | /***************************************/ |
| 331 | /* 32 General parallel move operations */ |
| 332 | /***************************************/ |
| 333 | |
| 334 | enum pType { kNoParallelDataMove, |
| 335 | kRegisterToRegister, |
| 336 | kAddressRegister, |
| 337 | kXMemoryDataMove, |
| 338 | kXMemoryDataMove2, |
| 339 | kXMemoryDataMoveWithDisp }; |
| 340 | |
| 341 | int parallelType = -1; |
| 342 | UINT16 op_byte = 0x0000; |
| 343 | typed_pointer d_register = {NULL, DT_BYTE}; |
| 344 | UINT64 prev_accum_value = U64(0x0000000000000000); |
| 345 | |
| 346 | /* Note: it's important that NPDM comes before RtRDM here */ |
| 347 | /* No Parallel Data Move : 0100 1010 .... .... : A-131 */ |
| 348 | if ((op & 0xff00) == 0x4a00) |
| 349 | { |
| 350 | op_byte = op & 0x00ff; |
| 351 | parallelType = kNoParallelDataMove; |
| 352 | } |
| 353 | /* Register to Register Data Move : 0100 IIII .... .... : A-133 */ |
| 354 | else if ((op & 0xf000) == 0x4000) |
| 355 | { |
| 356 | op_byte = op & 0x00ff; |
| 357 | parallelType = kRegisterToRegister; |
| 358 | } |
| 359 | /* Address Register Update : 0011 0zRR .... .... : A-135 */ |
| 360 | else if ((op & 0xf800) == 0x3000) |
| 361 | { |
| 362 | op_byte = op & 0x00ff; |
| 363 | parallelType = kAddressRegister; |
| 364 | } |
| 365 | /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */ |
| 366 | else if ((op & 0x8000) == 0x8000) |
| 367 | { |
| 368 | op_byte = op & 0x00ff; |
| 369 | parallelType = kXMemoryDataMove; |
| 370 | } |
| 371 | /* X Memory Data Move : 0101 HHHW .... .... : A-137 */ |
| 372 | else if ((op & 0xf000) == 0x5000) |
| 373 | { |
| 374 | op_byte = op & 0x00ff; |
| 375 | parallelType = kXMemoryDataMove2; |
| 376 | } |
| 377 | /* X Memory Data Move with short displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */ |
| 378 | else if ((op & 0xff00) == 0x0500) |
| 379 | { |
| 380 | /* Now check it against all the other potential collisions */ |
| 381 | /* This is necessary because "don't care bits" get in the way. */ |
| 382 | /* |
| 383 | MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 |
| 384 | MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 |
| 385 | MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 |
| 386 | */ |
| 387 | if (((op2 & 0xfe20) != 0x0200) && |
| 388 | ((op2 & 0xf810) != 0x3800) && |
| 389 | ((op2 & 0x00ff) != 0x0011)) |
| 390 | { |
| 391 | op_byte = op2 & 0x00ff; |
| 392 | parallelType = kXMemoryDataMoveWithDisp; |
| 393 | } |
| 394 | } |
| 395 | |
| 396 | |
| 397 | if (parallelType != -1) |
| 398 | { |
| 399 | /* Note: There is much overlap between opcodes down here */ |
| 400 | /* To this end, certain ops must come before others in the list */ |
| 401 | |
| 402 | /* CLR : .... .... 0000 F001 : A-60 */ |
| 403 | if ((op_byte & 0x00f7) == 0x0001) |
| 404 | { |
| 405 | size = dsp56k_op_clr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 406 | } |
| 407 | /* ADD : .... .... 0000 FJJJ : A-22 */ |
| 408 | else if ((op_byte & 0x00f0) == 0x0000) |
| 409 | { |
| 410 | size = dsp56k_op_add(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 411 | } |
| 412 | |
| 413 | |
| 414 | /* MOVE : .... .... 0001 0001 : A-128 */ |
| 415 | else if ((op_byte & 0x00ff) == 0x0011) |
| 416 | { |
| 417 | size = dsp56k_op_move(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 418 | } |
| 419 | /* TFR : .... .... 0001 FJJJ : A-212 */ |
| 420 | else if ((op_byte & 0x00f0) == 0x0010) |
| 421 | { |
| 422 | size = dsp56k_op_tfr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 423 | } |
| 424 | |
| 425 | |
| 426 | /* RND : .... .... 0010 F000 : A-188 */ |
| 427 | else if ((op_byte & 0x00f7) == 0x0020) |
| 428 | { |
| 429 | size = dsp56k_op_rnd(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 430 | } |
| 431 | /* TST : .... .... 0010 F001 : A-218 */ |
| 432 | else if ((op_byte & 0x00f7) == 0x0021) |
| 433 | { |
| 434 | size = dsp56k_op_tst(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 435 | } |
| 436 | /* INC : .... .... 0010 F010 : A-104 */ |
| 437 | else if ((op_byte & 0x00f7) == 0x0022) |
| 438 | { |
| 439 | size = dsp56k_op_inc(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 440 | } |
| 441 | /* INC24 : .... .... 0010 F011 : A-106 */ |
| 442 | else if ((op_byte & 0x00f7) == 0x0023) |
| 443 | { |
| 444 | size = dsp56k_op_inc24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 445 | } |
| 446 | /* OR : .... .... 0010 F1JJ : A-176 */ |
| 447 | else if ((op_byte & 0x00f4) == 0x0024) |
| 448 | { |
| 449 | size = dsp56k_op_or(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 450 | } |
| 451 | |
| 452 | |
| 453 | /* ASR : .... .... 0011 F000 : A-32 */ |
| 454 | else if ((op_byte & 0x00f7) == 0x0030) |
| 455 | { |
| 456 | size = dsp56k_op_asr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 457 | } |
| 458 | /* ASL : .... .... 0011 F001 : A-28 */ |
| 459 | else if ((op_byte & 0x00f7) == 0x0031) |
| 460 | { |
| 461 | size = dsp56k_op_asl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 462 | } |
| 463 | /* LSR : .... .... 0011 F010 : A-120 */ |
| 464 | else if ((op_byte & 0x00f7) == 0x0032) |
| 465 | { |
| 466 | size = dsp56k_op_lsr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 467 | } |
| 468 | /* LSL : .... .... 0011 F011 : A-118 */ |
| 469 | else if ((op_byte & 0x00f7) == 0x0033) |
| 470 | { |
| 471 | size = dsp56k_op_lsl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 472 | } |
| 473 | /* EOR : .... .... 0011 F1JJ : A-94 */ |
| 474 | else if ((op_byte & 0x00f4) == 0x0034) |
| 475 | { |
| 476 | size = dsp56k_op_eor(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 477 | } |
| 478 | |
| 479 | |
| 480 | /* SUBL : .... .... 0100 F001 : A-204 */ |
| 481 | else if ((op_byte & 0x00f7) == 0x0041) |
| 482 | { |
| 483 | size = dsp56k_op_subl(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 484 | } |
| 485 | /* SUB : .... .... 0100 FJJJ : A-202 */ |
| 486 | else if ((op_byte & 0x00f0) == 0x0040) |
| 487 | { |
| 488 | size = dsp56k_op_sub(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 489 | } |
| 490 | |
| 491 | |
| 492 | /* CLR24 : .... .... 0101 F001 : A-62 */ |
| 493 | else if ((op_byte & 0x00f7) == 0x0051) |
| 494 | { |
| 495 | size = dsp56k_op_clr24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 496 | } |
| 497 | /* SBC : .... .... 0101 F01J : A-198 */ |
| 498 | else if ((op_byte & 0x00f6) == 0x0052) |
| 499 | { |
| 500 | size = dsp56k_op_sbc(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 501 | } |
| 502 | /* CMP : .... .... 0101 FJJJ : A-64 */ |
| 503 | else if ((op_byte & 0x00f0) == 0x0050) |
| 504 | { |
| 505 | size = dsp56k_op_cmp(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 506 | } |
| 507 | |
| 508 | |
| 509 | /* NEG : .... .... 0110 F000 : A-166 */ |
| 510 | else if ((op_byte & 0x00f7) == 0x0060) |
| 511 | { |
| 512 | size = dsp56k_op_neg(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 513 | } |
| 514 | /* NOT : .... .... 0110 F001 : A-174 */ |
| 515 | else if ((op_byte & 0x00f7) == 0x0061) |
| 516 | { |
| 517 | size = dsp56k_op_not(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 518 | } |
| 519 | /* DEC : .... .... 0110 F010 : A-72 */ |
| 520 | else if ((op_byte & 0x00f7) == 0x0062) |
| 521 | { |
| 522 | size = dsp56k_op_dec(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 523 | } |
| 524 | /* DEC24 : .... .... 0110 F011 : A-74 */ |
| 525 | else if ((op_byte & 0x00f7) == 0x0063) |
| 526 | { |
| 527 | size = dsp56k_op_dec24(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 528 | } |
| 529 | /* AND : .... .... 0110 F1JJ : A-24 */ |
| 530 | else if ((op_byte & 0x00f4) == 0x0064) |
| 531 | { |
| 532 | size = dsp56k_op_and(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 533 | } |
| 534 | |
| 535 | |
| 536 | /* ABS : .... .... 0111 F001 : A-18 */ |
| 537 | if ((op_byte & 0x00f7) == 0x0071) |
| 538 | { |
| 539 | size = dsp56k_op_abs(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 540 | } |
| 541 | /* ROR : .... .... 0111 F010 : A-192 */ |
| 542 | else if ((op_byte & 0x00f7) == 0x0072) |
| 543 | { |
| 544 | size = dsp56k_op_ror(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 545 | } |
| 546 | /* ROL : .... .... 0111 F011 : A-190 */ |
| 547 | else if ((op_byte & 0x00f7) == 0x0073) |
| 548 | { |
| 549 | size = dsp56k_op_rol(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 550 | } |
| 551 | /* CMPM : .... .... 0111 FJJJ : A-66 */ |
| 552 | else if ((op_byte & 0x00f0) == 0x0070) |
| 553 | { |
| 554 | size = dsp56k_op_cmpm(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 555 | } |
| 556 | |
| 557 | |
| 558 | /* MPY : .... .... 1k00 FQQQ : A-160 -- CONFIRMED TYPO IN DOCS (HHHH vs HHHW) */ |
| 559 | else if ((op_byte & 0x00b0) == 0x0080) |
| 560 | { |
| 561 | size = dsp56k_op_mpy(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 562 | } |
| 563 | /* MPYR : .... .... 1k01 FQQQ : A-162 */ |
| 564 | else if ((op_byte & 0x00b0) == 0x0090) |
| 565 | { |
| 566 | size = dsp56k_op_mpyr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 567 | } |
| 568 | /* MAC : .... .... 1k10 FQQQ : A-122 */ |
| 569 | else if ((op_byte & 0x00b0) == 0x00a0) |
| 570 | { |
| 571 | size = dsp56k_op_mac(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 572 | } |
| 573 | /* MACR : .... .... 1k11 FQQQ : A-124 -- DRAMA - rr vs xx (805) */ |
| 574 | else if ((op_byte & 0x00b0) == 0x00b0) |
| 575 | { |
| 576 | size = dsp56k_op_macr(cpustate, op_byte, &d_register, &prev_accum_value, &cycle_count); |
| 577 | } |
| 578 | |
| 579 | |
| 580 | /* Now evaluate the parallel data move */ |
| 581 | switch (parallelType) |
| 582 | { |
| 583 | case kNoParallelDataMove: |
| 584 | /* DO NOTHING */ |
| 585 | break; |
| 586 | case kRegisterToRegister: |
| 587 | execute_register_to_register_data_move(cpustate, op, &d_register, &prev_accum_value); |
| 588 | break; |
| 589 | case kAddressRegister: |
| 590 | execute_address_register_update(cpustate, op, &d_register, &prev_accum_value); |
| 591 | break; |
| 592 | case kXMemoryDataMove: |
| 593 | execute_x_memory_data_move(cpustate, op, &d_register, &prev_accum_value); |
| 594 | break; |
| 595 | case kXMemoryDataMove2: |
| 596 | execute_x_memory_data_move2(cpustate, op, &d_register); |
| 597 | break; |
| 598 | case kXMemoryDataMoveWithDisp: |
| 599 | execute_x_memory_data_move_with_short_displacement(cpustate, op, op2); |
| 600 | size = 2; |
| 601 | break; |
| 602 | } |
| 603 | } |
| 604 | } |
| 605 | |
| 606 | /* Drop out if you've already completed your work. */ |
| 607 | if (size != 0x1337) |
| 608 | { |
| 609 | PC += size; |
| 610 | |
| 611 | dsp56k_process_loop(cpustate); |
| 612 | dsp56k_process_rep(cpustate, size); |
| 613 | |
| 614 | cpustate->icount -= 4; /* Temporarily hard-coded at 4 clocks per opcode */ /* cycle_count */ |
| 615 | return; |
| 616 | } |
| 617 | |
| 618 | |
| 619 | /******************************/ |
| 620 | /* Remaining non-parallel ops */ |
| 621 | /******************************/ |
| 622 | |
| 623 | /* ADC : 0001 0101 0000 F01J : A-20 */ |
| 624 | if ((op & 0xfff6) == 0x1502) |
| 625 | { |
| 626 | size = dsp56k_op_adc(cpustate, op, &cycle_count); |
| 627 | } |
| 628 | /* ANDI : 0001 1EE0 iiii iiii : A-26 */ |
| 629 | /* (MoveP sneaks in here if you don't check 0x0600) */ |
| 630 | else if (((op & 0xf900) == 0x1800) & ((op & 0x0600) != 0x0000)) |
| 631 | { |
| 632 | size = dsp56k_op_andi(cpustate, op, &cycle_count); |
| 633 | } |
| 634 | /* ASL4 : 0001 0101 0011 F001 : A-30 */ |
| 635 | else if ((op & 0xfff7) == 0x1531) |
| 636 | { |
| 637 | size = dsp56k_op_asl4(cpustate, op, &cycle_count); |
| 638 | } |
| 639 | /* ASR4 : 0001 0101 0011 F000 : A-34 */ |
| 640 | else if ((op & 0xfff7) == 0x1530) |
| 641 | { |
| 642 | size = dsp56k_op_asr4(cpustate, op, &cycle_count); |
| 643 | } |
| 644 | /* ASR16 : 0001 0101 0111 F000 : A-36 */ |
| 645 | else if ((op & 0xfff7) == 0x1570) |
| 646 | { |
| 647 | size = dsp56k_op_asr16(cpustate, op, &cycle_count); |
| 648 | } |
| 649 | /* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */ |
| 650 | else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x1200)) |
| 651 | { |
| 652 | size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count); |
| 653 | } |
| 654 | /* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */ |
| 655 | else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x1200)) |
| 656 | { |
| 657 | size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count); |
| 658 | } |
| 659 | /* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */ |
| 660 | else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x1200)) |
| 661 | { |
| 662 | size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count); |
| 663 | } |
| 664 | /* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */ |
| 665 | else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x0400)) |
| 666 | { |
| 667 | size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count); |
| 668 | } |
| 669 | /* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */ |
| 670 | else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x0400)) |
| 671 | { |
| 672 | size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count); |
| 673 | } |
| 674 | /* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */ |
| 675 | else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x0400)) |
| 676 | { |
| 677 | size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count); |
| 678 | } |
| 679 | /* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */ |
| 680 | else if (((op & 0xffc0) == 0x14c0) && ((op2 & 0x1f00) == 0x1800)) |
| 681 | { |
| 682 | size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count); |
| 683 | } |
| 684 | /* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */ |
| 685 | else if (((op & 0xffe0) == 0x14a0) && ((op2 & 0x1f00) == 0x1800)) |
| 686 | { |
| 687 | size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count); |
| 688 | } |
| 689 | /* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */ |
| 690 | else if (((op & 0xffe0) == 0x1480) && ((op2 & 0x1f00) == 0x1800)) |
| 691 | { |
| 692 | size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count); |
| 693 | } |
| 694 | /* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */ |
| 695 | else if (((op & 0xffc0) == 0x1440) && ((op2 & 0x1f00) == 0x1000)) |
| 696 | { |
| 697 | size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count); |
| 698 | } |
| 699 | /* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */ |
| 700 | else if (((op & 0xffe0) == 0x1420) && ((op2 & 0x1f00) == 0x1000)) |
| 701 | { |
| 702 | size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count); |
| 703 | } |
| 704 | /* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */ |
| 705 | else if (((op & 0xffe0) == 0x1400) && ((op2 & 0x1f00) == 0x1000)) |
| 706 | { |
| 707 | size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count); |
| 708 | } |
| 709 | /* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */ |
| 710 | else if (((op & 0xffc0) == 0x1440) && ((op2 & 0x1f00) == 0x0000)) |
| 711 | { |
| 712 | size = dsp56k_op_bfop(cpustate, op, op2, &cycle_count); |
| 713 | } |
| 714 | /* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */ |
| 715 | else if (((op & 0xffe0) == 0x1420) && ((op2 & 0x1f00) == 0x0000)) |
| 716 | { |
| 717 | size = dsp56k_op_bfop_1(cpustate, op, op2, &cycle_count); |
| 718 | } |
| 719 | /* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */ |
| 720 | else if (((op & 0xffe0) == 0x1400) && ((op2 & 0x1f00) == 0x0000)) |
| 721 | { |
| 722 | size = dsp56k_op_bfop_2(cpustate, op, op2, &cycle_count); |
| 723 | } |
| 724 | /* Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 */ |
| 725 | else if (((op & 0xff30) == 0x0730) && ((op2 & 0x0000) == 0x0000)) |
| 726 | { |
| 727 | size = dsp56k_op_bcc(cpustate, op, op2, &cycle_count); |
| 728 | } |
| 729 | /* Bcc : 0010 11cc ccee eeee : A-48 */ |
| 730 | else if ((op & 0xfc00) == 0x2c00) |
| 731 | { |
| 732 | size = dsp56k_op_bcc_1(cpustate, op, &cycle_count); |
| 733 | } |
| 734 | /* Bcc : 0000 0111 RR10 cccc : A-48 */ |
| 735 | else if ((op & 0xff30) == 0x0720) |
| 736 | { |
| 737 | size = dsp56k_op_bcc_2(cpustate, op, &cycle_count); |
| 738 | } |
| 739 | /* BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 */ |
| 740 | else if (((op & 0xfffc) == 0x013c) && ((op2 & 0x0000) == 0x0000)) |
| 741 | { |
| 742 | size = dsp56k_op_bra(cpustate, op, op2, &cycle_count); |
| 743 | } |
| 744 | /* BRA : 0000 1011 aaaa aaaa : A-50 */ |
| 745 | else if ((op & 0xff00) == 0x0b00) |
| 746 | { |
| 747 | size = dsp56k_op_bra_1(cpustate, op, &cycle_count); |
| 748 | } |
| 749 | /* BRA : 0000 0001 0010 11RR : A-50 */ |
| 750 | else if ((op & 0xfffc) == 0x012c) |
| 751 | { |
| 752 | size = dsp56k_op_bra_2(cpustate, op, &cycle_count); |
| 753 | } |
| 754 | /* BRKc : 0000 0001 0001 cccc : A-52 */ |
| 755 | else if ((op & 0xfff0) == 0x0110) |
| 756 | { |
| 757 | size = dsp56k_op_brkcc(cpustate, op, &cycle_count); |
| 758 | } |
| 759 | /* BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 */ |
| 760 | else if (((op & 0xff30) == 0x0710) && ((op2 & 0x0000) == 0x0000)) |
| 761 | { |
| 762 | size = dsp56k_op_bscc(cpustate, op, op2, &cycle_count); |
| 763 | } |
| 764 | /* BScc : 0000 0111 RR00 cccc : A-54 */ |
| 765 | else if ((op & 0xff30) == 0x0700) |
| 766 | { |
| 767 | size = dsp56k_op_bscc_1(cpustate, op, &cycle_count); |
| 768 | } |
| 769 | /* BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 */ |
| 770 | else if (((op & 0xfffc) == 0x0138) && ((op2 & 0x0000) == 0x0000)) |
| 771 | { |
| 772 | size = dsp56k_op_bsr(cpustate, op, op2, &cycle_count); |
| 773 | } |
| 774 | /* BSR : 0000 0001 0010 10RR : A-56 */ |
| 775 | else if ((op & 0xfffc) == 0x0128) |
| 776 | { |
| 777 | size = dsp56k_op_bsr_1(cpustate, op, &cycle_count); |
| 778 | } |
| 779 | /* CHKAAU : 0000 0000 0000 0100 : A-58 */ |
| 780 | else if ((op & 0xffff) == 0x0004) |
| 781 | { |
| 782 | size = dsp56k_op_chkaau(cpustate, op, &cycle_count); |
| 783 | } |
| 784 | /* DEBUG : 0000 0000 0000 0001 : A-68 */ |
| 785 | else if ((op & 0xffff) == 0x0001) |
| 786 | { |
| 787 | size = dsp56k_op_debug(cpustate, op, &cycle_count); |
| 788 | } |
| 789 | /* DEBUGcc : 0000 0000 0101 cccc : A-70 */ |
| 790 | else if ((op & 0xfff0) == 0x0050) |
| 791 | { |
| 792 | size = dsp56k_op_debugcc(cpustate, op, &cycle_count); |
| 793 | } |
| 794 | /* DIV : 0001 0101 0--0 F1DD : A-76 */ |
| 795 | else if ((op & 0xff94) == 0x1504) |
| 796 | { |
| 797 | size = dsp56k_op_div(cpustate, op, &cycle_count); |
| 798 | } |
| 799 | /* DMAC : 0001 0101 10s1 FsQQ : A-80 */ |
| 800 | else if ((op & 0xffd0) == 0x1590) |
| 801 | { |
| 802 | size = dsp56k_op_dmac(cpustate, op, &cycle_count); |
| 803 | } |
| 804 | /* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */ |
| 805 | else if (((op & 0xffe0) == 0x00c0) && ((op2 & 0x0000) == 0x0000)) |
| 806 | { |
| 807 | size = dsp56k_op_do(cpustate, op, op2, &cycle_count); |
| 808 | } |
| 809 | /* DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 */ |
| 810 | else if (((op & 0xff00) == 0x0e00) && ((op2 & 0x0000) == 0x0000)) |
| 811 | { |
| 812 | size = dsp56k_op_do_1(cpustate, op, op2, &cycle_count); |
| 813 | } |
| 814 | /* DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 */ |
| 815 | else if (((op & 0xffe0) == 0x0400) && ((op2 & 0x0000) == 0x0000)) |
| 816 | { |
| 817 | size = dsp56k_op_do_2(cpustate, op, op2, &cycle_count); |
| 818 | } |
| 819 | /* DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 */ |
| 820 | else if (((op & 0xffff) == 0x0002) && ((op2 & 0x0000) == 0x0000)) |
| 821 | { |
| 822 | size = dsp56k_op_doforever(cpustate, op, op2, &cycle_count); |
| 823 | } |
| 824 | /* ENDDO : 0000 0000 0000 1001 : A-92 */ |
| 825 | else if ((op & 0xffff) == 0x0009) |
| 826 | { |
| 827 | size = dsp56k_op_enddo(cpustate, op, &cycle_count); |
| 828 | } |
| 829 | /* EXT : 0001 0101 0101 F010 : A-96 */ |
| 830 | else if ((op & 0xfff7) == 0x1552) |
| 831 | { |
| 832 | size = dsp56k_op_ext(cpustate, op, &cycle_count); |
| 833 | } |
| 834 | /* ILLEGAL : 0000 0000 0000 1111 : A-98 */ |
| 835 | else if ((op & 0xffff) == 0x000f) |
| 836 | { |
| 837 | size = dsp56k_op_illegal(cpustate, op, &cycle_count); |
| 838 | } |
| 839 | /* IMAC : 0001 0101 1010 FQQQ : A-100 */ |
| 840 | else if ((op & 0xfff0) == 0x15a0) |
| 841 | { |
| 842 | size = dsp56k_op_imac(cpustate, op, &cycle_count); |
| 843 | } |
| 844 | /* IMPY : 0001 0101 1000 FQQQ : A-102 */ |
| 845 | else if ((op & 0xfff0) == 0x1580) |
| 846 | { |
| 847 | size = dsp56k_op_impy(cpustate, op, &cycle_count); |
| 848 | } |
| 849 | /* Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 */ |
| 850 | else if (((op & 0xff30) == 0x0630) && ((op2 & 0x0000) == 0x0000)) |
| 851 | { |
| 852 | size = dsp56k_op_jcc(cpustate, op, op2, &cycle_count); |
| 853 | } |
| 854 | /* Jcc : 0000 0110 RR10 cccc : A-108 */ |
| 855 | else if ((op & 0xff30) == 0x0620 ) |
| 856 | { |
| 857 | size = dsp56k_op_jcc_1(cpustate, op, &cycle_count); |
| 858 | } |
| 859 | /* JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 */ |
| 860 | else if (((op & 0xfffc) == 0x0134) && ((op2 & 0x0000) == 0x0000)) |
| 861 | { |
| 862 | size = dsp56k_op_jmp(cpustate, op, op2, &cycle_count); |
| 863 | } |
| 864 | /* JMP : 0000 0001 0010 01RR : A-110 */ |
| 865 | else if ((op & 0xfffc) == 0x0124) |
| 866 | { |
| 867 | size = dsp56k_op_jmp_1(cpustate, op, &cycle_count); |
| 868 | } |
| 869 | /* JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 */ |
| 870 | else if (((op & 0xff30) == 0x0610) && ((op2 & 0x0000) == 0x0000)) |
| 871 | { |
| 872 | size = dsp56k_op_jscc(cpustate, op, op2, &cycle_count); |
| 873 | } |
| 874 | /* JScc : 0000 0110 RR00 cccc : A-112 */ |
| 875 | else if ((op & 0xff30) == 0x0600) |
| 876 | { |
| 877 | size = dsp56k_op_jscc_1(cpustate, op, &cycle_count); |
| 878 | } |
| 879 | /* JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 */ |
| 880 | else if (((op & 0xfffc) == 0x0130) && ((op2 & 0x0000) == 0x0000)) |
| 881 | { |
| 882 | size = dsp56k_op_jsr(cpustate, op, op2, &cycle_count); |
| 883 | } |
| 884 | /* JSR : 0000 1010 AAAA AAAA : A-114 */ |
| 885 | else if ((op & 0xff00) == 0x0a00) |
| 886 | { |
| 887 | size = dsp56k_op_jsr_1(cpustate, op, &cycle_count); |
| 888 | } |
| 889 | /* JSR : 0000 0001 0010 00RR : A-114 */ |
| 890 | else if ((op & 0xfffc) == 0x0120) |
| 891 | { |
| 892 | size = dsp56k_op_jsr_2(cpustate, op, &cycle_count); |
| 893 | } |
| 894 | /* LEA : 0000 0001 11TT MMRR : A-116 */ |
| 895 | else if ((op & 0xffc0) == 0x01c0) |
| 896 | { |
| 897 | size = dsp56k_op_lea(cpustate, op, &cycle_count); |
| 898 | } |
| 899 | /* LEA : 0000 0001 10NN MMRR : A-116 */ |
| 900 | else if ((op & 0xffc0) == 0x0180) |
| 901 | { |
| 902 | size = dsp56k_op_lea_1(cpustate, op, &cycle_count); |
| 903 | } |
| 904 | /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */ |
| 905 | else if ((op & 0xfff0) == 0x15e0) |
| 906 | { |
| 907 | size = dsp56k_op_macsuuu(cpustate, op, &cycle_count); |
| 908 | } |
| 909 | /* MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 */ |
| 910 | else if (((op & 0xff00) == 0x0500) && ((op2 & 0x00ff) == 0x0011)) |
| 911 | { |
| 912 | size = dsp56k_op_move_2(cpustate, op, op2, &cycle_count); |
| 913 | } |
| 914 | /* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */ |
| 915 | else if ((op & 0xf810) == 0x3800) |
| 916 | { |
| 917 | size = dsp56k_op_movec(cpustate, op, &cycle_count); |
| 918 | } |
| 919 | /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */ |
| 920 | else if ((op & 0xf814) == 0x3810) |
| 921 | { |
| 922 | size = dsp56k_op_movec_1(cpustate, op, &cycle_count); |
| 923 | } |
| 924 | /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */ |
| 925 | else if ((op & 0xf816) == 0x3816) |
| 926 | { |
| 927 | size = dsp56k_op_movec_2(cpustate, op, &cycle_count); |
| 928 | } |
| 929 | /* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */ |
| 930 | else if (((op & 0xf816) == 0x3814) && ((op2 & 0x0000) == 0x0000)) |
| 931 | { |
| 932 | size = dsp56k_op_movec_3(cpustate, op, op2, &cycle_count); |
| 933 | } |
| 934 | /* MOVE(C) : 0010 10dd dddD DDDD : A-144 */ |
| 935 | else if ((op & 0xfc00) == 0x2800) |
| 936 | { |
| 937 | size = dsp56k_op_movec_4(cpustate, op, &cycle_count); |
| 938 | } |
| 939 | /* MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 */ |
| 940 | else if (((op & 0xff00) == 0x0500) && ((op2 & 0xf810) == 0x3800)) |
| 941 | { |
| 942 | size = dsp56k_op_movec_5(cpustate, op, op2, &cycle_count); |
| 943 | } |
| 944 | /* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */ |
| 945 | else if ((op & 0xfc00) == 0x2000) |
| 946 | { |
| 947 | size = dsp56k_op_movei(cpustate, op, &cycle_count); |
| 948 | } |
| 949 | /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */ |
| 950 | else if ((op & 0xfe20) == 0x0200) |
| 951 | { |
| 952 | size = dsp56k_op_movem(cpustate, op, &cycle_count); |
| 953 | } |
| 954 | /* MOVE(M) : 0000 001W RR11 mmRR : A-152 */ |
| 955 | else if ((op & 0xfe30) == 0x0230) |
| 956 | { |
| 957 | size = dsp56k_op_movem_1(cpustate, op, &cycle_count); |
| 958 | } |
| 959 | /* MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 */ |
| 960 | else if (((op & 0xff00) == 0x0500) && ((op2 & 0xfe20) == 0x0200)) |
| 961 | { |
| 962 | size = dsp56k_op_movem_2(cpustate, op, op2, &cycle_count); |
| 963 | } |
| 964 | /* MOVE(P) : 0001 100W HH1p pppp : A-156 */ |
| 965 | else if ((op & 0xfe20) == 0x1820) |
| 966 | { |
| 967 | size = dsp56k_op_movep(cpustate, op, &cycle_count); |
| 968 | } |
| 969 | /* MOVE(P) : 0000 110W RRmp pppp : A-156 */ |
| 970 | else if ((op & 0xfe00) == 0x0c00) |
| 971 | { |
| 972 | size = dsp56k_op_movep_1(cpustate, op, &cycle_count); |
| 973 | } |
| 974 | /* MOVE(S) : 0001 100W HH0a aaaa : A-158 */ |
| 975 | else if ((op & 0xfe20) == 0x1800) |
| 976 | { |
| 977 | size = dsp56k_op_moves(cpustate, op, &cycle_count); |
| 978 | } |
| 979 | /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */ |
| 980 | else if ((op & 0xfff0) == 0x15c0) |
| 981 | { |
| 982 | size = dsp56k_op_mpysuuu(cpustate, op, &cycle_count); |
| 983 | } |
| 984 | /* NEGC : 0001 0101 0110 F000 : A-168 */ |
| 985 | else if ((op & 0xfff7) == 0x1560) |
| 986 | { |
| 987 | size = dsp56k_op_negc(cpustate, op, &cycle_count); |
| 988 | } |
| 989 | /* NOP : 0000 0000 0000 0000 : A-170 */ |
| 990 | else if ((op & 0xffff) == 0x0000) |
| 991 | { |
| 992 | size = dsp56k_op_nop(cpustate, op, &cycle_count); |
| 993 | } |
| 994 | /* NORM : 0001 0101 0010 F0RR : A-172 */ |
| 995 | else if ((op & 0xfff4) == 0x1520) |
| 996 | { |
| 997 | size = dsp56k_op_norm(cpustate, op, &cycle_count); |
| 998 | } |
| 999 | /* ORI : 0001 1EE1 iiii iiii : A-178 */ |
| 1000 | else if ((op & 0xf900) == 0x1900) |
| 1001 | { |
| 1002 | size = dsp56k_op_ori(cpustate, op, &cycle_count); |
| 1003 | } |
| 1004 | /* REP : 0000 0000 111- --RR : A-180 */ |
| 1005 | else if ((op & 0xffe0) == 0x00e0) |
| 1006 | { |
| 1007 | size = dsp56k_op_rep(cpustate, op, &cycle_count); |
| 1008 | } |
| 1009 | /* REP : 0000 1111 iiii iiii : A-180 */ |
| 1010 | else if ((op & 0xff00) == 0x0f00) |
| 1011 | { |
| 1012 | size = dsp56k_op_rep_1(cpustate, op, &cycle_count); |
| 1013 | } |
| 1014 | /* REP : 0000 0100 001D DDDD : A-180 */ |
| 1015 | else if ((op & 0xffe0) == 0x0420) |
| 1016 | { |
| 1017 | size = dsp56k_op_rep_2(cpustate, op, &cycle_count); |
| 1018 | } |
| 1019 | /* REPcc : 0000 0001 0101 cccc : A-184 */ |
| 1020 | else if ((op & 0xfff0) == 0x0150) |
| 1021 | { |
| 1022 | size = dsp56k_op_repcc(cpustate, op, &cycle_count); |
| 1023 | } |
| 1024 | /* RESET : 0000 0000 0000 1000 : A-186 */ |
| 1025 | else if ((op & 0xffff) == 0x0008) |
| 1026 | { |
| 1027 | size = dsp56k_op_reset(cpustate, op, &cycle_count); |
| 1028 | } |
| 1029 | /* RTI : 0000 0000 0000 0111 : A-194 */ |
| 1030 | else if ((op & 0xffff) == 0x0007) |
| 1031 | { |
| 1032 | size = dsp56k_op_rti(cpustate, op, &cycle_count); |
| 1033 | } |
| 1034 | /* RTS : 0000 0000 0000 0110 : A-196 */ |
| 1035 | else if ((op & 0xffff) == 0x0006) |
| 1036 | { |
| 1037 | size = dsp56k_op_rts(cpustate, op, &cycle_count); |
| 1038 | } |
| 1039 | /* STOP : 0000 0000 0000 1010 : A-200 */ |
| 1040 | else if ((op & 0xffff) == 0x000a) |
| 1041 | { |
| 1042 | size = dsp56k_op_stop(cpustate, op, &cycle_count); |
| 1043 | } |
| 1044 | /* SWAP : 0001 0101 0111 F001 : A-206 */ |
| 1045 | else if ((op & 0xfff7) == 0x1571) |
| 1046 | { |
| 1047 | size = dsp56k_op_swap(cpustate, op, &cycle_count); |
| 1048 | } |
| 1049 | /* SWI : 0000 0000 0000 0101 : A-208 */ |
| 1050 | else if ((op & 0xffff) == 0x0005) |
| 1051 | { |
| 1052 | size = dsp56k_op_swi(cpustate, op, &cycle_count); |
| 1053 | } |
| 1054 | /* Tcc : 0001 00cc ccTT Fh0h : A-210 */ |
| 1055 | else if ((op & 0xfc02) == 0x1000) |
| 1056 | { |
| 1057 | size = dsp56k_op_tcc(cpustate, op, &cycle_count); |
| 1058 | } |
| 1059 | /* TFR(2) : 0001 0101 0000 F00J : A-214 */ |
| 1060 | else if ((op & 0xfff6) == 0x1500) |
| 1061 | { |
| 1062 | size = dsp56k_op_tfr2(cpustate, op, &cycle_count); |
| 1063 | } |
| 1064 | /* TFR(3) : 0010 01mW RRDD FHHH : A-216 */ |
| 1065 | else if ((op & 0xfc00) == 0x2400) |
| 1066 | { |
| 1067 | size = dsp56k_op_tfr3(cpustate, op, &cycle_count); |
| 1068 | } |
| 1069 | /* TST(2) : 0001 0101 0001 -1DD : A-220 */ |
| 1070 | else if ((op & 0xfff4) == 0x1514) |
| 1071 | { |
| 1072 | size = dsp56k_op_tst2(cpustate, op, &cycle_count); |
| 1073 | } |
| 1074 | /* WAIT : 0000 0000 0000 1011 : A-222 */ |
| 1075 | else if ((op & 0xffff) == 0x000b) |
| 1076 | { |
| 1077 | size = dsp56k_op_wait(cpustate, op, &cycle_count); |
| 1078 | } |
| 1079 | /* ZERO : 0001 0101 0101 F000 : A-224 */ |
| 1080 | else if ((op & 0xfff7) == 0x1550) |
| 1081 | { |
| 1082 | size = dsp56k_op_zero(cpustate, op, &cycle_count); |
| 1083 | } |
| 1084 | |
| 1085 | |
| 1086 | /* Not recognized? Nudge debugger onto the next word */ |
| 1087 | if (size == 0x1337) |
| 1088 | { |
| 1089 | logerror("DSP56k: Unimplemented opcode at 0x%04x : %04x\n", PC, op); |
| 1090 | size = 1 ; /* Just to get the debugger past the bad opcode */ |
| 1091 | } |
| 1092 | |
| 1093 | /* Must have been a good opcode */ |
| 1094 | PC += size; |
| 1095 | |
| 1096 | dsp56k_process_loop(cpustate); |
| 1097 | dsp56k_process_rep(cpustate, size); |
| 1098 | |
| 1099 | cpustate->icount -= 4; /* Temporarily hard-coded at 4 clocks per opcode */ /* cycle_count */ |
| 1100 | } |
| 1101 | |
| 1102 | |
| 1103 | |
| 1104 | |
| 1105 | /*************************************************************************** |
| 1106 | Opcode implementations |
| 1107 | ***************************************************************************/ |
| 1108 | |
| 1109 | /*******************************/ |
| 1110 | /* 32 Parallel move operations */ |
| 1111 | /*******************************/ |
| 1112 | |
| 1113 | /* ADD : 011m mKKK 0rru Fuuu : A-22 */ |
| 1114 | /* SUB : 011m mKKK 0rru Fuuu : A-202 */ |
| 1115 | static size_t dsp56k_op_addsub_2(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1116 | { |
| 1117 | UINT64 useVal = 0; |
| 1118 | UINT8 op_type = OP_OTHER; |
| 1119 | typed_pointer S = {NULL, DT_BYTE}; |
| 1120 | typed_pointer D = {NULL, DT_BYTE}; |
| 1121 | |
| 1122 | decode_uuuuF_table(cpustate, BITS(op_byte,0x0017), BITS(op_byte,0x0008), op_type, &S, &D); |
| 1123 | |
| 1124 | /* If you gave an invalid operation type, presume it's a nop and move on with the parallel move */ |
| 1125 | if (op_type == OP_OTHER) |
| 1126 | { |
| 1127 | d_register->addr = NULL; |
| 1128 | d_register->data_type = DT_BYTE; |
| 1129 | cycles += 2; |
| 1130 | return 1; |
| 1131 | } |
| 1132 | |
| 1133 | /* It's a real operation. Get on with it. */ |
| 1134 | switch(S.data_type) |
| 1135 | { |
| 1136 | case DT_WORD: useVal = (UINT64)*((UINT16*)S.addr) << 16; break; |
| 1137 | case DT_DOUBLE_WORD: useVal = (UINT64)*((UINT32*)S.addr); break; |
| 1138 | case DT_LONG_WORD: useVal = (UINT64)*((UINT64*)S.addr); break; |
| 1139 | } |
| 1140 | |
| 1141 | /* Sign-extend word for proper add/sub op */ |
| 1142 | if ((S.data_type == DT_WORD) && useVal & U64(0x0000000080000000)) |
| 1143 | useVal |= U64(0x000000ff00000000); |
| 1144 | |
| 1145 | /* Operate*/ |
| 1146 | if (op_type == OP_ADD) |
| 1147 | *((UINT64*)D.addr) += useVal; |
| 1148 | else if (op_type == OP_SUB) |
| 1149 | *((UINT64*)D.addr) -= useVal; |
| 1150 | |
| 1151 | d_register->addr = D.addr; |
| 1152 | d_register->data_type = D.data_type; |
| 1153 | |
| 1154 | /* S L E U N Z V C */ |
| 1155 | /* * * * * * * * * */ |
| 1156 | /* TODO S, L, E, U, V, C */ |
| 1157 | if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1158 | if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1159 | |
| 1160 | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1161 | return 1; |
| 1162 | } |
| 1163 | |
| 1164 | /* MAC : 011m mKKK 1xx0 F1QQ : A-122 */ |
| 1165 | static size_t dsp56k_op_mac_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1166 | { |
| 1167 | INT64 opD = 0; |
| 1168 | INT64 result = 0; |
| 1169 | |
| 1170 | INT32 s1 = 0; |
| 1171 | INT32 s2 = 0; |
| 1172 | |
| 1173 | void* D = NULL; |
| 1174 | void* S1 = NULL; |
| 1175 | void* S2 = NULL; |
| 1176 | |
| 1177 | decode_QQF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S1, &S2, &D); |
| 1178 | |
| 1179 | /* Cast both values as being signed */ |
| 1180 | s1 = *((INT16*)S1); |
| 1181 | s2 = *((INT16*)S2); |
| 1182 | |
| 1183 | /* Fixed-point 2's complement multiplication requires a shift */ |
| 1184 | result = (s1 * s2) << 1; |
| 1185 | |
| 1186 | /* Sign extend D into a temp variable */ |
| 1187 | opD = (*((UINT64*)D)); |
| 1188 | if (opD & U64(0x0000008000000000)) |
| 1189 | opD |= U64(0xffffff0000000000); |
| 1190 | else |
| 1191 | opD &= U64(0x000000ffffffffff); |
| 1192 | |
| 1193 | /* Accumulate */ |
| 1194 | opD += result; |
| 1195 | |
| 1196 | /* And out the bits that don't live in the register */ |
| 1197 | opD &= U64(0x000000ffffffffff); |
| 1198 | |
| 1199 | (*((UINT64*)D)) = (UINT64)opD; |
| 1200 | |
| 1201 | /* For the parallel move */ |
| 1202 | d_register->addr = D; |
| 1203 | d_register->data_type = DT_LONG_WORD; |
| 1204 | |
| 1205 | /* S L E U N Z V C */ |
| 1206 | /* * * * * * * * - */ |
| 1207 | /* TODO: S, L, E, V */ |
| 1208 | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1209 | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1210 | |
| 1211 | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 1212 | return 1; |
| 1213 | } |
| 1214 | |
| 1215 | /* MACR: 011m mKKK 1--1 F1QQ : A-124 */ |
| 1216 | static size_t dsp56k_op_macr_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1217 | { |
| 1218 | /* S L E U N Z V C */ |
| 1219 | /* * * * * * * * - */ |
| 1220 | return 0; |
| 1221 | } |
| 1222 | |
| 1223 | /* MOVE : 011m mKKK 0rr1 0000 : A-128 */ |
| 1224 | static size_t dsp56k_op_move_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1225 | { |
| 1226 | /* S L E U N Z V C */ |
| 1227 | /* * * - - - - - - */ |
| 1228 | return 0; |
| 1229 | } |
| 1230 | |
| 1231 | /* MPY : 011m mKKK 1xx0 F0QQ : A-160 */ |
| 1232 | static size_t dsp56k_op_mpy_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1233 | { |
| 1234 | INT64 result = 0; |
| 1235 | |
| 1236 | INT32 s1 = 0; |
| 1237 | INT32 s2 = 0; |
| 1238 | |
| 1239 | void* D = NULL; |
| 1240 | void* S1 = NULL; |
| 1241 | void* S2 = NULL; |
| 1242 | |
| 1243 | decode_QQF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S1, &S2, &D); |
| 1244 | |
| 1245 | /* Cast both values as being signed */ |
| 1246 | s1 = *((INT16*)S1); |
| 1247 | s2 = *((INT16*)S2); |
| 1248 | |
| 1249 | /* Fixed-point 2's complement multiplication requires a shift */ |
| 1250 | result = (s1 * s2) << 1; |
| 1251 | |
| 1252 | /* And out the bits that don't live in the register */ |
| 1253 | (*((UINT64*)D)) = result & U64(0x000000ffffffffff); |
| 1254 | |
| 1255 | /* For the parallel move */ |
| 1256 | d_register->addr = D; |
| 1257 | d_register->data_type = DT_LONG_WORD; |
| 1258 | |
| 1259 | /* S L E U N Z V C */ |
| 1260 | /* * * * * * * * - */ |
| 1261 | /* TODO: S, L, E, V */ |
| 1262 | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1263 | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1264 | |
| 1265 | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 1266 | return 1; |
| 1267 | } |
| 1268 | |
| 1269 | /* MPYR : 011m mKKK 1--1 F0QQ : A-162 */ |
| 1270 | static size_t dsp56k_op_mpyr_1(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1271 | { |
| 1272 | /* S L E U N Z V C */ |
| 1273 | /* * * * * * * * - */ |
| 1274 | return 0; |
| 1275 | } |
| 1276 | |
| 1277 | /* TFR : 011m mKKK 0rr1 F0DD : A-212 */ |
| 1278 | static size_t dsp56k_op_tfr_2(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT8* cycles) |
| 1279 | { |
| 1280 | /* S L E U N Z V C */ |
| 1281 | /* - - - - - - - - */ |
| 1282 | return 0; |
| 1283 | } |
| 1284 | |
| 1285 | /* MPY : 0001 0110 RRDD FQQQ : A-160 */ |
| 1286 | static size_t dsp56k_op_mpy_2(dsp56k_core* cpustate, const UINT16 op_byte, UINT8* cycles) |
| 1287 | { |
| 1288 | /* S L E U N Z V C */ |
| 1289 | /* * * * * * * * - */ |
| 1290 | return 0; |
| 1291 | } |
| 1292 | |
| 1293 | /* MAC : 0001 0111 RRDD FQQQ : A-122 */ |
| 1294 | static size_t dsp56k_op_mac_2(dsp56k_core* cpustate, const UINT16 op_byte, UINT8* cycles) |
| 1295 | { |
| 1296 | /* S L E U N Z V C */ |
| 1297 | /* * * * * * * * - */ |
| 1298 | return 0; |
| 1299 | } |
| 1300 | |
| 1301 | /* CLR : .... .... 0000 F001 : A-60 */ |
| 1302 | static size_t dsp56k_op_clr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1303 | { |
| 1304 | typed_pointer D = {NULL, DT_LONG_WORD}; |
| 1305 | typed_pointer clear = {NULL, DT_LONG_WORD}; |
| 1306 | UINT64 clear_val = U64(0x0000000000000000); |
| 1307 | |
| 1308 | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1309 | |
| 1310 | *p_accum = *((UINT64*)D.addr); |
| 1311 | |
| 1312 | clear.addr = &clear_val; |
| 1313 | clear.data_type = DT_LONG_WORD; |
| 1314 | SetDestinationValue(clear, D); |
| 1315 | |
| 1316 | d_register->addr = D.addr; |
| 1317 | d_register->data_type = D.data_type; |
| 1318 | |
| 1319 | /* S L E U N Z V C */ |
| 1320 | /* * * * * * * 0 - */ |
| 1321 | /* TODO - S, L */ |
| 1322 | DSP56K_E_CLEAR(); |
| 1323 | DSP56K_U_SET(); |
| 1324 | DSP56K_N_CLEAR(); |
| 1325 | DSP56K_Z_SET(); |
| 1326 | DSP56K_V_CLEAR(); |
| 1327 | |
| 1328 | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1329 | return 1; |
| 1330 | } |
| 1331 | |
| 1332 | /* ADD : .... .... 0000 FJJJ : A-22 */ |
| 1333 | static size_t dsp56k_op_add(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1334 | { |
| 1335 | UINT64 addVal = 0; |
| 1336 | |
| 1337 | typed_pointer S = {NULL, DT_BYTE}; |
| 1338 | typed_pointer D = {NULL, DT_BYTE}; |
| 1339 | decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D); |
| 1340 | |
| 1341 | *p_accum = *((UINT64*)D.addr); |
| 1342 | |
| 1343 | switch(S.data_type) |
| 1344 | { |
| 1345 | case DT_WORD: addVal = (UINT64)*((UINT16*)S.addr) << 16; break; |
| 1346 | case DT_DOUBLE_WORD: addVal = (UINT64)*((UINT32*)S.addr); break; |
| 1347 | case DT_LONG_WORD: addVal = (UINT64)*((UINT64*)S.addr); break; |
| 1348 | } |
| 1349 | |
| 1350 | /* Sign-extend word for proper add/sub op */ |
| 1351 | if ((S.data_type == DT_WORD) && addVal & U64(0x0000000080000000)) |
| 1352 | addVal |= U64(0x000000ff00000000); |
| 1353 | |
| 1354 | /* Operate*/ |
| 1355 | *((UINT64*)D.addr) += addVal; |
| 1356 | |
| 1357 | d_register->addr = D.addr; |
| 1358 | d_register->data_type = D.data_type; |
| 1359 | |
| 1360 | /* S L E U N Z V C */ |
| 1361 | /* * * * * * * * * */ |
| 1362 | /* TODO S, L, E, U, V, C */ |
| 1363 | if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1364 | if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1365 | |
| 1366 | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1367 | return 1; |
| 1368 | } |
| 1369 | |
| 1370 | /* MOVE : .... .... 0001 0001 : A-128 */ |
| 1371 | static size_t dsp56k_op_move(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1372 | { |
| 1373 | /* Equivalent to a nop with a parallel move */ |
| 1374 | /* These can't be used later. Hopefully compilers would pick this up. */ |
| 1375 | *p_accum = 0; |
| 1376 | d_register->addr = NULL; |
| 1377 | d_register->data_type = DT_BYTE; |
| 1378 | |
| 1379 | /* S L E U N Z V C */ |
| 1380 | /* * * - - - - - - */ |
| 1381 | /* TODO: S, L */ |
| 1382 | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1383 | return 1; |
| 1384 | } |
| 1385 | |
| 1386 | /* TFR : .... .... 0001 FJJJ : A-212 */ |
| 1387 | static size_t dsp56k_op_tfr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1388 | { |
| 1389 | typed_pointer S = {NULL, DT_BYTE}; |
| 1390 | typed_pointer D = {NULL, DT_BYTE}; |
| 1391 | |
| 1392 | decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D); |
| 1393 | |
| 1394 | *p_accum = *((UINT64*)D.addr); |
| 1395 | |
| 1396 | SetDestinationValue(S, D); |
| 1397 | |
| 1398 | d_register->addr = D.addr; |
| 1399 | d_register->data_type = D.data_type; |
| 1400 | |
| 1401 | /* S L E U N Z V C */ |
| 1402 | /* * * - - - - - - */ |
| 1403 | /* TODO: S, L */ |
| 1404 | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1405 | return 1; |
| 1406 | } |
| 1407 | |
| 1408 | /* RND : .... .... 0010 F000 : A-188 */ |
| 1409 | static size_t dsp56k_op_rnd(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1410 | { |
| 1411 | typed_pointer D = {NULL, DT_BYTE}; |
| 1412 | |
| 1413 | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1414 | |
| 1415 | *p_accum = *((UINT64*)D.addr); |
| 1416 | |
| 1417 | /* WARNING : ROUNDING NOT FULLY IMPLEMENTED YET! */ |
| 1418 | if ((*((UINT64*)D.addr) & U64(0x000000000000ffff)) >= 0x8000) |
| 1419 | *((UINT64*)D.addr) += U64(0x0000000000010000); |
| 1420 | |
| 1421 | *((UINT64*)D.addr) = *((UINT64*)D.addr) & U64(0x000000ffffff0000); |
| 1422 | |
| 1423 | d_register->addr = D.addr; |
| 1424 | d_register->data_type = D.data_type; |
| 1425 | |
| 1426 | /* S L E U N Z V C */ |
| 1427 | /* * * * * * * * - */ |
| 1428 | /* TODO: S, L, E, U, V */ |
| 1429 | if ((*((UINT64*)D.addr)) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1430 | if ((*((UINT64*)D.addr)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1431 | |
| 1432 | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1433 | return 1; |
| 1434 | } |
| 1435 | |
| 1436 | /* TST : .... .... 0010 F001 : A-218 */ |
| 1437 | static size_t dsp56k_op_tst(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1438 | { |
| 1439 | typed_pointer D = {NULL, DT_LONG_WORD}; |
| 1440 | |
| 1441 | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1442 | |
| 1443 | *p_accum = *((UINT64*)D.addr); |
| 1444 | |
| 1445 | d_register->addr = D.addr; |
| 1446 | d_register->data_type = D.data_type; |
| 1447 | |
| 1448 | /* S L E U N Z V C */ |
| 1449 | /* 0 * * * * * 0 0 */ |
| 1450 | /* TODO: S, L, E, U */ |
| 1451 | if ((*((UINT64*)D.addr)) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1452 | if ((*((UINT64*)D.addr)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1453 | DSP56K_V_CLEAR(); |
| 1454 | DSP56K_C_CLEAR(); |
| 1455 | |
| 1456 | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1457 | return 1; |
| 1458 | } |
| 1459 | |
| 1460 | /* INC : .... .... 0010 F010 : A-104 */ |
| 1461 | static size_t dsp56k_op_inc(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1462 | { |
| 1463 | typed_pointer D = {NULL, DT_BYTE}; |
| 1464 | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1465 | |
| 1466 | /* Save some data for the parallel move */ |
| 1467 | *p_accum = *((UINT64*)D.addr); |
| 1468 | |
| 1469 | /* Make sure the destination is a real 40-bit value */ |
| 1470 | *((UINT64*)D.addr) &= U64(0x000000ffffffffff); |
| 1471 | |
| 1472 | /* Increment */ |
| 1473 | *((UINT64*)D.addr) = *((UINT64*)D.addr) + 1; |
| 1474 | |
| 1475 | d_register->addr = D.addr; |
| 1476 | d_register->data_type = D.data_type; |
| 1477 | |
| 1478 | /* S L E U N Z V C */ |
| 1479 | /* * * * * * * * * */ |
| 1480 | /* TODO: S, L, E, U */ |
| 1481 | if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1482 | if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1483 | if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 1484 | if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1485 | |
| 1486 | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 1487 | return 1; |
| 1488 | } |
| 1489 | |
| 1490 | /* INC24 : .... .... 0010 F011 : A-106 */ |
| 1491 | static size_t dsp56k_op_inc24(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1492 | { |
| 1493 | UINT32 workBits24; |
| 1494 | |
| 1495 | typed_pointer D = {NULL, DT_BYTE}; |
| 1496 | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1497 | |
| 1498 | /* Save some data for the parallel move */ |
| 1499 | *p_accum = *((UINT64*)D.addr); |
| 1500 | |
| 1501 | /* TODO: I wonder if workBits24 should be signed? */ |
| 1502 | workBits24 = ((*((UINT64*)D.addr)) & U64(0x000000ffffff0000)) >> 16; |
| 1503 | workBits24++; |
| 1504 | //workBits24 &= 0x00ffffff; /* Solves -x issues - TODO: huh? */ |
| 1505 | |
| 1506 | /* Set the D bits with the dec result */ |
| 1507 | *((UINT64*)D.addr) &= U64(0x000000000000ffff); |
| 1508 | *((UINT64*)D.addr) |= (((UINT64)(workBits24)) << 16); |
| 1509 | |
| 1510 | d_register->addr = D.addr; |
| 1511 | d_register->data_type = D.data_type; |
| 1512 | |
| 1513 | /* S L E U N Z V C */ |
| 1514 | /* * * * * * ? * * */ |
| 1515 | /* TODO: S, L, E, U */ |
| 1516 | if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1517 | if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1518 | if ((workBits24 & 0xff000000) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 1519 | if ((workBits24 & 0xff000000) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1520 | |
| 1521 | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1522 | return 1; |
| 1523 | } |
| 1524 | |
| 1525 | /* OR : .... .... 0010 F1JJ : A-176 */ |
| 1526 | static size_t dsp56k_op_or(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1527 | { |
| 1528 | typed_pointer S = {NULL, DT_BYTE}; |
| 1529 | typed_pointer D = {NULL, DT_BYTE}; |
| 1530 | |
| 1531 | decode_JJF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S, &D); |
| 1532 | |
| 1533 | /* Save some data for the parallel move */ |
| 1534 | *p_accum = *((UINT64*)D.addr); |
| 1535 | |
| 1536 | /* OR a word of S with A1|B1 */ |
| 1537 | ((PAIR64*)D.addr)->w.h = *((UINT16*)S.addr) | ((PAIR64*)D.addr)->w.h; |
| 1538 | |
| 1539 | d_register->addr = D.addr; |
| 1540 | d_register->data_type = D.data_type; |
| 1541 | |
| 1542 | /* S L E U N Z V C */ |
| 1543 | /* * * - - ? ? 0 - */ |
| 1544 | /* TODO: S, L */ |
| 1545 | if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1546 | if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1547 | DSP56K_V_CLEAR(); |
| 1548 | |
| 1549 | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1550 | return 1; |
| 1551 | } |
| 1552 | |
| 1553 | /* ASR : .... .... 0011 F000 : A-32 */ |
| 1554 | static size_t dsp56k_op_asr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1555 | { |
| 1556 | typed_pointer D = {NULL, DT_BYTE}; |
| 1557 | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1558 | |
| 1559 | *p_accum = *((UINT64*)D.addr); |
| 1560 | |
| 1561 | *((UINT64*)D.addr) = (*((UINT64*)D.addr)) >> 1; |
| 1562 | |
| 1563 | /* Make sure the MSB is maintained */ |
| 1564 | if (*p_accum & U64(0x0000008000000000)) |
| 1565 | *((UINT64*)D.addr) |= U64(0x0000008000000000); |
| 1566 | else |
| 1567 | *((UINT64*)D.addr) &= (~U64(0x0000008000000000)); |
| 1568 | |
| 1569 | /* For the parallel move */ |
| 1570 | d_register->addr = D.addr; |
| 1571 | d_register->data_type = D.data_type; |
| 1572 | |
| 1573 | /* S L E U N Z V C */ |
| 1574 | /* * * * * * * 0 ? */ |
| 1575 | /* TODO: S, L, E, U */ |
| 1576 | if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1577 | if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1578 | DSP56K_V_CLEAR(); |
| 1579 | if (*p_accum & U64(0x0000000000000001)) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1580 | |
| 1581 | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1582 | return 1; |
| 1583 | } |
| 1584 | |
| 1585 | /* ASL : .... .... 0011 F001 : A-28 */ |
| 1586 | static size_t dsp56k_op_asl(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1587 | { |
| 1588 | /* S L E U N Z V C */ |
| 1589 | /* * * * * * * ? ? */ |
| 1590 | /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significant |
| 1591 | bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */ |
| 1592 | /* C - Set if bit 39 of source operand is set. Cleared otherwise. */ |
| 1593 | return 0; |
| 1594 | } |
| 1595 | |
| 1596 | /* LSR : .... .... 0011 F010 : A-120 */ |
| 1597 | static size_t dsp56k_op_lsr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1598 | { |
| 1599 | typed_pointer D = {NULL, DT_BYTE}; |
| 1600 | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1601 | |
| 1602 | *p_accum = *((UINT64*)D.addr); |
| 1603 | |
| 1604 | ((PAIR64*)D.addr)->w.h = (((PAIR64*)D.addr)->w.h) >> 1; |
| 1605 | |
| 1606 | /* Make sure bit 31 gets a 0 */ |
| 1607 | ((PAIR64*)D.addr)->w.h &= (~0x8000); |
| 1608 | |
| 1609 | /* For the parallel move */ |
| 1610 | d_register->addr = D.addr; |
| 1611 | d_register->data_type = D.data_type; |
| 1612 | |
| 1613 | /* S L E U N Z V C */ |
| 1614 | /* * * - - ? ? 0 ? */ |
| 1615 | /* TODO: S, L */ |
| 1616 | DSP56K_N_CLEAR(); |
| 1617 | if (((PAIR64*)D.addr)->w.h == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1618 | DSP56K_V_CLEAR(); |
| 1619 | if (*p_accum & U64(0x0000000000010000)) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1620 | |
| 1621 | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1622 | return 1; |
| 1623 | } |
| 1624 | |
| 1625 | /* LSL : .... .... 0011 F011 : A-118 */ |
| 1626 | static size_t dsp56k_op_lsl(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1627 | { |
| 1628 | /* S L E U N Z V C */ |
| 1629 | /* * * - - ? ? 0 ? */ |
| 1630 | /* N - Set if bit 31 of the result is set. Cleared otherwise. */ |
| 1631 | /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */ |
| 1632 | /* C - Set if bit 31 of the source operand is set. Cleared otherwise. */ |
| 1633 | return 0; |
| 1634 | } |
| 1635 | |
| 1636 | /* EOR : .... .... 0011 F1JJ : A-94 */ |
| 1637 | static size_t dsp56k_op_eor(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1638 | { |
| 1639 | /* S L E U N Z V C */ |
| 1640 | /* * * - - ? ? 0 - */ |
| 1641 | /* N - Set if bit 31 of the result is set. Cleared otherwise. */ |
| 1642 | /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */ |
| 1643 | return 0; |
| 1644 | } |
| 1645 | |
| 1646 | /* SUBL : .... .... 0100 F001 : A-204 */ |
| 1647 | static size_t dsp56k_op_subl(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1648 | { |
| 1649 | /* S L E U N Z V C */ |
| 1650 | /* * * * * * * ? * */ |
| 1651 | /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significant |
| 1652 | bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */ |
| 1653 | return 0; |
| 1654 | } |
| 1655 | |
| 1656 | /* SUB : .... .... 0100 FJJJ : A-202 */ |
| 1657 | static size_t dsp56k_op_sub(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1658 | { |
| 1659 | UINT64 useVal = 0; |
| 1660 | typed_pointer S = {NULL, DT_BYTE}; |
| 1661 | typed_pointer D = {NULL, DT_BYTE}; |
| 1662 | |
| 1663 | decode_JJJF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S, &D); |
| 1664 | |
| 1665 | /* Get on with it. */ |
| 1666 | switch(S.data_type) |
| 1667 | { |
| 1668 | case DT_WORD: useVal = (UINT64)*((UINT16*)S.addr) << 16; break; |
| 1669 | case DT_DOUBLE_WORD: useVal = (UINT64)*((UINT32*)S.addr); break; |
| 1670 | case DT_LONG_WORD: useVal = (UINT64)*((UINT64*)S.addr); break; |
| 1671 | } |
| 1672 | |
| 1673 | /* Sign-extend word for proper sub op */ |
| 1674 | if ((S.data_type == DT_WORD) && useVal & U64(0x0000000080000000)) |
| 1675 | useVal |= U64(0x000000ff00000000); |
| 1676 | |
| 1677 | /* Make sure they're both real 40-bit values */ |
| 1678 | useVal &= U64(0x000000ffffffffff); |
| 1679 | *((UINT64*)D.addr) &= U64(0x000000ffffffffff); |
| 1680 | |
| 1681 | /* Operate*/ |
| 1682 | *((UINT64*)D.addr) -= useVal; |
| 1683 | |
| 1684 | d_register->addr = D.addr; |
| 1685 | d_register->data_type = D.data_type; |
| 1686 | |
| 1687 | /* S L E U N Z V C */ |
| 1688 | /* * * * * * * * * */ |
| 1689 | /* TODO S, L, E, U */ |
| 1690 | if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1691 | if ( *((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1692 | if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 1693 | if ((*((UINT64*)D.addr) & U64(0xffffff0000000000)) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1694 | |
| 1695 | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1696 | return 1; |
| 1697 | } |
| 1698 | |
| 1699 | /* CLR24 : .... .... 0101 F001 : A-62 */ |
| 1700 | static size_t dsp56k_op_clr24(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1701 | { |
| 1702 | /* S L E U N Z V C */ |
| 1703 | /* * * * * * ? 0 - */ |
| 1704 | /* Z - Set if the 24 most significant bits of the destination result are all zeroes. */ |
| 1705 | return 0; |
| 1706 | } |
| 1707 | |
| 1708 | /* SBC : .... .... 0101 F01J : A-198 */ |
| 1709 | static size_t dsp56k_op_sbc(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1710 | { |
| 1711 | /* S L E U N Z V C */ |
| 1712 | /* * * * * * * * * */ |
| 1713 | return 0; |
| 1714 | } |
| 1715 | |
| 1716 | /* CMP : .... .... 0101 FJJJ : A-64 */ |
| 1717 | static size_t dsp56k_op_cmp(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1718 | { |
| 1719 | UINT64 cmpVal = 0; |
| 1720 | UINT64 result = 0; |
| 1721 | |
| 1722 | typed_pointer S = {NULL, DT_BYTE}; |
| 1723 | typed_pointer D = {NULL, DT_BYTE}; |
| 1724 | |
| 1725 | decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D); |
| 1726 | |
| 1727 | *p_accum = *((UINT64*)D.addr); |
| 1728 | |
| 1729 | switch(S.data_type) |
| 1730 | { |
| 1731 | case DT_WORD: cmpVal = (UINT64)*((UINT16*)S.addr) << 16; break; |
| 1732 | case DT_DOUBLE_WORD: cmpVal = (UINT64)*((UINT32*)S.addr); break; |
| 1733 | case DT_LONG_WORD: cmpVal = (UINT64)*((UINT64*)S.addr); break; |
| 1734 | } |
| 1735 | |
| 1736 | /* Sign-extend word for proper subtraction op */ |
| 1737 | if ((S.data_type == DT_WORD) && cmpVal & U64(0x0000000080000000)) |
| 1738 | cmpVal |= U64(0x000000ff00000000); |
| 1739 | |
| 1740 | /* Make sure they're both real 40-bit values */ |
| 1741 | cmpVal &= U64(0x000000ffffffffff); |
| 1742 | *((UINT64*)D.addr) &= U64(0x000000ffffffffff); |
| 1743 | |
| 1744 | /* Operate */ |
| 1745 | result = *((UINT64*)D.addr) - cmpVal; |
| 1746 | |
| 1747 | d_register->addr = D.addr; |
| 1748 | d_register->data_type = D.data_type; |
| 1749 | |
| 1750 | /* S L E U N Z V C */ |
| 1751 | /* * * * * * * * * */ |
| 1752 | /* TODO: S, L, E, U */ |
| 1753 | if ( result & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1754 | if ( result == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1755 | if ((result & U64(0xffffff0000000000)) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 1756 | if ((result & U64(0xffffff0000000000)) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1757 | |
| 1758 | |
| 1759 | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1760 | return 1; |
| 1761 | } |
| 1762 | |
| 1763 | /* NEG : .... .... 0110 F000 : A-166 */ |
| 1764 | static size_t dsp56k_op_neg(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1765 | { |
| 1766 | /* S L E U N Z V C */ |
| 1767 | /* * * * * * * * * */ |
| 1768 | return 0; |
| 1769 | } |
| 1770 | |
| 1771 | /* NOT : .... .... 0110 F001 : A-174 */ |
| 1772 | static size_t dsp56k_op_not(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1773 | { |
| 1774 | typed_pointer D = {NULL, DT_BYTE}; |
| 1775 | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1776 | |
| 1777 | *p_accum = *((UINT64*)D.addr); |
| 1778 | |
| 1779 | /* Invert bits [16:31] of D */ |
| 1780 | ((PAIR64*)D.addr)->w.h = ~(((PAIR64*)D.addr)->w.h); |
| 1781 | |
| 1782 | d_register->addr = D.addr; |
| 1783 | d_register->data_type = D.data_type; |
| 1784 | |
| 1785 | /* S L E U N Z V C */ |
| 1786 | /* * * - - ? ? 0 - */ |
| 1787 | /* TODO: S?, L */ |
| 1788 | if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1789 | if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1790 | DSP56K_V_CLEAR(); |
| 1791 | |
| 1792 | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1793 | return 1; |
| 1794 | } |
| 1795 | |
| 1796 | /* DEC : .... .... 0110 F010 : A-72 */ |
| 1797 | static size_t dsp56k_op_dec(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1798 | { |
| 1799 | /* S L E U N Z V C */ |
| 1800 | /* * * * * * * * * */ |
| 1801 | return 0; |
| 1802 | } |
| 1803 | |
| 1804 | /* DEC24 : .... .... 0110 F011 : A-74 */ |
| 1805 | static size_t dsp56k_op_dec24(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1806 | { |
| 1807 | UINT32 workBits24; |
| 1808 | |
| 1809 | typed_pointer D = {NULL, DT_BYTE}; |
| 1810 | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1811 | |
| 1812 | /* Save some data for the parallel move */ |
| 1813 | *p_accum = *((UINT64*)D.addr); |
| 1814 | |
| 1815 | /* TODO: I wonder if workBits24 should be signed? */ |
| 1816 | workBits24 = ((*((UINT64*)D.addr)) & U64(0x000000ffffff0000)) >> 16; |
| 1817 | workBits24--; |
| 1818 | workBits24 &= 0x00ffffff; /* Solves -x issues */ |
| 1819 | |
| 1820 | /* Set the D bits with the dec result */ |
| 1821 | *((UINT64*)D.addr) &= U64(0x000000000000ffff); |
| 1822 | *((UINT64*)D.addr) |= (((UINT64)(workBits24)) << 16); |
| 1823 | |
| 1824 | d_register->addr = D.addr; |
| 1825 | d_register->data_type = D.data_type; |
| 1826 | |
| 1827 | /* S L E U N Z V C */ |
| 1828 | /* * * * * * ? * * */ |
| 1829 | /* TODO: S, L, E, U, V, C */ |
| 1830 | if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1831 | if ((*((UINT64*)D.addr) & U64(0x000000ffffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1832 | |
| 1833 | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1834 | return 1; |
| 1835 | } |
| 1836 | |
| 1837 | /* AND : .... .... 0110 F1JJ : A-24 */ |
| 1838 | static size_t dsp56k_op_and(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1839 | { |
| 1840 | typed_pointer S = {NULL, DT_BYTE}; |
| 1841 | typed_pointer D = {NULL, DT_BYTE}; |
| 1842 | |
| 1843 | decode_JJF_table(cpustate, BITS(op_byte,0x0003), BITS(op_byte,0x0008), &S, &D); |
| 1844 | |
| 1845 | /* Save some data for the parallel move */ |
| 1846 | *p_accum = *((UINT64*)D.addr); |
| 1847 | |
| 1848 | /* AND a word of S with A1|B1 */ |
| 1849 | ((PAIR64*)D.addr)->w.h = *((UINT16*)S.addr) & ((PAIR64*)D.addr)->w.h; |
| 1850 | |
| 1851 | d_register->addr = D.addr; |
| 1852 | d_register->data_type = D.data_type; |
| 1853 | |
| 1854 | /* S L E U N Z V C */ |
| 1855 | /* * * - - ? ? 0 - */ |
| 1856 | /* TODO: S, L */ |
| 1857 | if ( *((UINT64*)D.addr) & U64(0x0000000080000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1858 | if ((*((UINT64*)D.addr) & U64(0x00000000ffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1859 | DSP56K_V_CLEAR(); |
| 1860 | |
| 1861 | cycles += 2; /* TODO: + mv oscillator cycles */ |
| 1862 | return 1; |
| 1863 | } |
| 1864 | |
| 1865 | /* ABS : .... .... 0111 F001 : A-18 */ |
| 1866 | static size_t dsp56k_op_abs(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1867 | { |
| 1868 | INT64 opD = 0; |
| 1869 | typed_pointer D = {NULL, DT_LONG_WORD}; |
| 1870 | |
| 1871 | decode_F_table(cpustate, BITS(op_byte,0x0008), &D); |
| 1872 | |
| 1873 | *p_accum = *((UINT64*)D.addr); |
| 1874 | |
| 1875 | /* Sign extend D into a temp variable */ |
| 1876 | opD = *p_accum; |
| 1877 | if (opD & U64(0x0000008000000000)) |
| 1878 | opD |= U64(0xffffff0000000000); |
| 1879 | else |
| 1880 | opD &= U64(0x000000ffffffffff); |
| 1881 | |
| 1882 | /* Take the absolute value and clean up */ |
| 1883 | opD = (opD < 0) ? -opD : opD; |
| 1884 | opD &= U64(0x000000ffffffffff); |
| 1885 | |
| 1886 | /* Reassign */ |
| 1887 | *((UINT64*)D.addr) = opD; |
| 1888 | |
| 1889 | /* Special overflow case */ |
| 1890 | if ((*p_accum) == U64(0x0000008000000000)) |
| 1891 | *((UINT64*)D.addr) = U64(0x0000007fffffffff); |
| 1892 | |
| 1893 | /* S L E U N Z V C */ |
| 1894 | /* * * * * * * * - */ |
| 1895 | /* TODO: S, L, E, U */ |
| 1896 | if ( *((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1897 | if ((*((UINT64*)D.addr) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1898 | if ((*p_accum) == U64(0x0000008000000000)) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 1899 | |
| 1900 | cycles += 2; /* TODO: + mv oscillator clock cycles */ |
| 1901 | return 1; |
| 1902 | } |
| 1903 | |
| 1904 | /* ROR : .... .... 0111 F010 : A-192 */ |
| 1905 | static size_t dsp56k_op_ror(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1906 | { |
| 1907 | /* S L E U N Z V C */ |
| 1908 | /* * * - - ? ? 0 ? */ |
| 1909 | /* N - Set if bit 31 of the result is set. Cleared otherwise. */ |
| 1910 | /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */ |
| 1911 | /* C - Set if bit 16 of the source operand is set. Cleared otherwise. */ |
| 1912 | return 0; |
| 1913 | } |
| 1914 | |
| 1915 | /* ROL : .... .... 0111 F011 : A-190 */ |
| 1916 | static size_t dsp56k_op_rol(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1917 | { |
| 1918 | /* S L E U N Z V C */ |
| 1919 | /* * * - - ? ? 0 ? */ |
| 1920 | /* N - Set if bit 31 of the result is set. Cleared otherwise. */ |
| 1921 | /* Z - Set if bits 16-31 of the result are zero. Cleared otherwise. */ |
| 1922 | /* C - Set if bit 31 of the source operand is set. Cleared otherwise. */ |
| 1923 | return 0; |
| 1924 | } |
| 1925 | |
| 1926 | /* CMPM : .... .... 0111 FJJJ : A-66 */ |
| 1927 | static size_t dsp56k_op_cmpm(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1928 | { |
| 1929 | INT64 absS; |
| 1930 | INT64 absD; |
| 1931 | INT64 absResult; |
| 1932 | |
| 1933 | typed_pointer S = {NULL, DT_BYTE}; |
| 1934 | typed_pointer D = {NULL, DT_BYTE}; |
| 1935 | |
| 1936 | decode_JJJF_table(cpustate, BITS(op_byte,0x0007),BITS(op_byte,0x0008), &S, &D); |
| 1937 | |
| 1938 | *p_accum = *((UINT64*)D.addr); |
| 1939 | |
| 1940 | /* Sign extend and get absolute value of the source */ |
| 1941 | if (S.addr == &A || S.addr == &B) |
| 1942 | { |
| 1943 | absS = *((UINT64*)S.addr); |
| 1944 | if (absS & U64(0x0000008000000000)) |
| 1945 | absS |= U64(0xffffff8000000000); |
| 1946 | } |
| 1947 | else |
| 1948 | { |
| 1949 | absS = (*((UINT16*)S.addr)) << 16; |
| 1950 | if (absS & U64(0x0000000080000000)) |
| 1951 | absS |= U64(0xffffffff80000000); |
| 1952 | } |
| 1953 | absS = (absS < 0) ? -absS : absS; |
| 1954 | |
| 1955 | /* Sign extend and get absolute value of the destination */ |
| 1956 | if (D.addr == &A || D.addr == &B) |
| 1957 | { |
| 1958 | absD = *((UINT64*)D.addr); |
| 1959 | if (absD & U64(0x0000008000000000)) |
| 1960 | absD |= U64(0xffffff8000000000); |
| 1961 | } |
| 1962 | else |
| 1963 | { |
| 1964 | absD = (*((UINT16*)D.addr)) << 16; |
| 1965 | if (absS & U64(0x0000000080000000)) |
| 1966 | absS |= U64(0xffffffff80000000); |
| 1967 | } |
| 1968 | absD = (absD < 0) ? -absD : absD; |
| 1969 | |
| 1970 | /* Compare */ |
| 1971 | absResult = absD - absS; |
| 1972 | |
| 1973 | d_register->addr = D.addr; |
| 1974 | d_register->data_type = D.data_type; |
| 1975 | |
| 1976 | /* S L E U N Z V C */ |
| 1977 | /* * * * * * * * * */ |
| 1978 | /* TODO: S, L, E, U */ |
| 1979 | if ( (absResult) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 1980 | if (((absResult) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 1981 | if ( (absResult & U64(0xffffff0000000000)) != 0) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 1982 | if ( (absResult & U64(0xffffff0000000000)) != 0) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 1983 | |
| 1984 | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 1985 | return 1; |
| 1986 | } |
| 1987 | |
| 1988 | /* MPY : .... .... 1k00 FQQQ : A-160 -- CONFIRMED TYPO IN DOCS (HHHH vs HHHW) */ |
| 1989 | static size_t dsp56k_op_mpy(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 1990 | { |
| 1991 | UINT16 k = 0; |
| 1992 | INT64 result = 0; |
| 1993 | |
| 1994 | INT32 s1 = 0; |
| 1995 | INT32 s2 = 0; |
| 1996 | |
| 1997 | void* D = NULL; |
| 1998 | void* S1 = NULL; |
| 1999 | void* S2 = NULL; |
| 2000 | |
| 2001 | decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D); |
| 2002 | |
| 2003 | k = BITS(op_byte,0x0040); |
| 2004 | |
| 2005 | /* Cast both values as being signed */ |
| 2006 | s1 = *((INT16*)S1); |
| 2007 | s2 = *((INT16*)S2); |
| 2008 | |
| 2009 | /* Fixed-point 2's complement multiplication requires a shift */ |
| 2010 | result = (s1 * s2) << 1; |
| 2011 | |
| 2012 | /* Negate the product if necessary */ |
| 2013 | if (k) |
| 2014 | result *= -1; |
| 2015 | |
| 2016 | (*((UINT64*)D)) = result & U64(0x000000ffffffffff); |
| 2017 | |
| 2018 | /* S L E U N Z V C */ |
| 2019 | /* * * * * * * * - */ |
| 2020 | /* TODO: S, L, E, V */ |
| 2021 | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2022 | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2023 | |
| 2024 | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 2025 | return 1; |
| 2026 | } |
| 2027 | |
| 2028 | /* MPYR : .... .... 1k01 FQQQ : A-162 */ |
| 2029 | static size_t dsp56k_op_mpyr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 2030 | { |
| 2031 | /* S L E U N Z V C */ |
| 2032 | /* * * * * * * * - */ |
| 2033 | return 0; |
| 2034 | } |
| 2035 | |
| 2036 | /* MAC : .... .... 1k10 FQQQ : A-122 */ |
| 2037 | static size_t dsp56k_op_mac(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 2038 | { |
| 2039 | UINT16 k = 0; |
| 2040 | INT64 opD = 0; |
| 2041 | INT64 result = 0; |
| 2042 | |
| 2043 | INT32 s1 = 0; |
| 2044 | INT32 s2 = 0; |
| 2045 | |
| 2046 | void* D = NULL; |
| 2047 | void* S1 = NULL; |
| 2048 | void* S2 = NULL; |
| 2049 | |
| 2050 | decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D); |
| 2051 | |
| 2052 | k = BITS(op_byte,0x0040); |
| 2053 | |
| 2054 | /* Cast both values as being signed */ |
| 2055 | s1 = *((INT16*)S1); |
| 2056 | s2 = *((INT16*)S2); |
| 2057 | |
| 2058 | /* Fixed-point 2's complement multiplication requires a shift */ |
| 2059 | result = (s1 * s2) << 1; |
| 2060 | |
| 2061 | /* Sign extend D into a temp variable */ |
| 2062 | opD = (*((UINT64*)D)); |
| 2063 | if (opD & U64(0x0000008000000000)) |
| 2064 | opD |= U64(0xffffff0000000000); |
| 2065 | else |
| 2066 | opD &= U64(0x000000ffffffffff); |
| 2067 | |
| 2068 | /* Negate if necessary */ |
| 2069 | if (k) |
| 2070 | result *= -1; |
| 2071 | |
| 2072 | /* Accumulate */ |
| 2073 | opD += result; |
| 2074 | |
| 2075 | /* And out the bits that don't live in the register */ |
| 2076 | opD &= U64(0x000000ffffffffff); |
| 2077 | |
| 2078 | (*((UINT64*)D)) = (UINT64)opD; |
| 2079 | |
| 2080 | /* For the parallel move */ |
| 2081 | d_register->addr = D; |
| 2082 | d_register->data_type = DT_LONG_WORD; |
| 2083 | |
| 2084 | /* S L E U N Z V C */ |
| 2085 | /* * * * * * * * - */ |
| 2086 | /* TODO: S, L, E, V */ |
| 2087 | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2088 | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2089 | |
| 2090 | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 2091 | return 1; |
| 2092 | } |
| 2093 | |
| 2094 | /* MACR : .... .... 1k11 FQQQ : A-124 -- DRAMA - rr vs xx (805) */ |
| 2095 | static size_t dsp56k_op_macr(dsp56k_core* cpustate, const UINT16 op_byte, typed_pointer* d_register, UINT64* p_accum, UINT8* cycles) |
| 2096 | { |
| 2097 | UINT16 k = 0; |
| 2098 | INT64 opD = 0; |
| 2099 | INT64 result = 0; |
| 2100 | |
| 2101 | INT32 s1 = 0; |
| 2102 | INT32 s2 = 0; |
| 2103 | |
| 2104 | void* D = NULL; |
| 2105 | void* S1 = NULL; |
| 2106 | void* S2 = NULL; |
| 2107 | |
| 2108 | decode_QQQF_table(cpustate, BITS(op_byte,0x0007), BITS(op_byte,0x0008), &S1, &S2, &D); |
| 2109 | |
| 2110 | k = BITS(op_byte,0x0040); |
| 2111 | |
| 2112 | /* Cast both values as being signed */ |
| 2113 | s1 = *((INT16*)S1); |
| 2114 | s2 = *((INT16*)S2); |
| 2115 | |
| 2116 | /* Fixed-point 2's complement multiplication requires a shift */ |
| 2117 | result = (s1 * s2) << 1; |
| 2118 | |
| 2119 | /* Sign extend D into a temp variable */ |
| 2120 | opD = (*((UINT64*)D)); |
| 2121 | if (opD & U64(0x0000008000000000)) |
| 2122 | opD |= U64(0xffffff0000000000); |
| 2123 | else |
| 2124 | opD &= U64(0x000000ffffffffff); |
| 2125 | |
| 2126 | /* Negate if necessary */ |
| 2127 | if (k) |
| 2128 | result *= -1; |
| 2129 | |
| 2130 | /* Accumulate */ |
| 2131 | opD += result; |
| 2132 | |
| 2133 | /* Round the result */ |
| 2134 | /* WARNING : ROUNDING NOT FULLY IMPLEMENTED YET! */ |
| 2135 | if ((opD & U64(0x000000000000ffff)) >= 0x8000) |
| 2136 | opD += U64(0x0000000000010000); |
| 2137 | |
| 2138 | opD &= U64(0x000000ffffff0000); |
| 2139 | |
| 2140 | /* And out the bits that don't live in the register */ |
| 2141 | opD &= U64(0x000000ffffffffff); |
| 2142 | |
| 2143 | /* Store the result */ |
| 2144 | (*((UINT64*)D)) = (UINT64)opD; |
| 2145 | |
| 2146 | /* For the parallel move */ |
| 2147 | d_register->addr = D; |
| 2148 | d_register->data_type = DT_LONG_WORD; |
| 2149 | |
| 2150 | /* S L E U N Z V C */ |
| 2151 | /* * * * * * * * - */ |
| 2152 | /* TODO: S, L, E, V */ |
| 2153 | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2154 | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2155 | |
| 2156 | cycles += 2; /* TODO: +mv oscillator cycles */ |
| 2157 | return 1; |
| 2158 | } |
| 2159 | |
| 2160 | |
| 2161 | /******************************/ |
| 2162 | /* Remaining non-parallel ops */ |
| 2163 | /******************************/ |
| 2164 | |
| 2165 | /* ADC : 0001 0101 0000 F01J : A-20 */ |
| 2166 | static size_t dsp56k_op_adc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2167 | { |
| 2168 | /* S L E U N Z V C */ |
| 2169 | /* - * * * * * * * */ |
| 2170 | return 0; |
| 2171 | } |
| 2172 | |
| 2173 | /* ANDI : 0001 1EE0 iiii iiii : A-26 */ |
| 2174 | static size_t dsp56k_op_andi(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2175 | { |
| 2176 | UINT16 immediate = BITS(op,0x00ff); |
| 2177 | |
| 2178 | /* There is not currently a good way to refer to CCR or MR. Explicitly decode here. */ |
| 2179 | switch(BITS(op,0x0600)) |
| 2180 | { |
| 2181 | case 0x01: /* MR */ |
| 2182 | SR &= ((immediate << 8) | 0x00ff); |
| 2183 | break; |
| 2184 | |
| 2185 | case 0x02: /* CCR */ |
| 2186 | SR &= (immediate | 0xff00); |
| 2187 | break; |
| 2188 | |
| 2189 | case 0x03: /* OMR */ |
| 2190 | OMR &= (UINT8)(immediate); |
| 2191 | break; |
| 2192 | |
| 2193 | default: |
| 2194 | fatalerror("DSP56k - BAD EE value in andi operation\n") ; |
| 2195 | } |
| 2196 | |
| 2197 | /* S L E U N Z V C */ |
| 2198 | /* - ? ? ? ? ? ? ? */ |
| 2199 | /* All ? bits - Cleared if the corresponding bit in the immediate data is cleared and if the operand |
| 2200 | is the CCR. Not affected otherwise. */ |
| 2201 | cycles += 2; |
| 2202 | return 1; |
| 2203 | } |
| 2204 | |
| 2205 | /* ASL4 : 0001 0101 0011 F001 : A-30 */ |
| 2206 | static size_t dsp56k_op_asl4(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2207 | { |
| 2208 | UINT64 p_accum = 0; |
| 2209 | typed_pointer D = {NULL, DT_BYTE}; |
| 2210 | decode_F_table(cpustate, BITS(op,0x0008), &D); |
| 2211 | |
| 2212 | p_accum = *((UINT64*)D.addr); |
| 2213 | |
| 2214 | *((UINT64*)D.addr) = (*((UINT64*)D.addr)) << 4; |
| 2215 | *((UINT64*)D.addr) = (*((UINT64*)D.addr)) & U64(0x000000ffffffffff); |
| 2216 | |
| 2217 | /* S L E U N Z V C */ |
| 2218 | /* - ? * * * * ? ? */ |
| 2219 | /* TODO: L, E, U */ |
| 2220 | /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if bit 35 through 39 are |
| 2221 | not the same. */ |
| 2222 | /* C - Set if bit 36 of source operand is set. Cleared otherwise. */ |
| 2223 | if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2224 | if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2225 | if ( (*((UINT64*)D.addr) & U64(0x000000ff00000000)) != (p_accum & U64(0x000000ff00000000)) ) DSP56K_V_SET(); else DSP56K_V_CLEAR(); |
| 2226 | if (p_accum & U64(0x0000001000000000)) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 2227 | |
| 2228 | cycles += 2; |
| 2229 | return 1; |
| 2230 | } |
| 2231 | |
| 2232 | /* ASR4 : 0001 0101 0011 F000 : A-34 */ |
| 2233 | static size_t dsp56k_op_asr4(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2234 | { |
| 2235 | UINT64 p_accum = 0; |
| 2236 | typed_pointer D = {NULL, DT_BYTE}; |
| 2237 | decode_F_table(cpustate, BITS(op,0x0008), &D); |
| 2238 | |
| 2239 | p_accum = *((UINT64*)D.addr); |
| 2240 | |
| 2241 | *((UINT64*)D.addr) = (*((UINT64*)D.addr)) >> 4; |
| 2242 | *((UINT64*)D.addr) = (*((UINT64*)D.addr)) & U64(0x000000ffffffffff); |
| 2243 | |
| 2244 | /* The top 4 bits become the old bit 39 */ |
| 2245 | if (p_accum & U64(0x0000008000000000)) |
| 2246 | *((UINT64*)D.addr) |= U64(0x000000f000000000); |
| 2247 | else |
| 2248 | *((UINT64*)D.addr) &= (~U64(0x000000f000000000)); |
| 2249 | |
| 2250 | /* S L E U N Z V C */ |
| 2251 | /* - * * * * * 0 ? */ |
| 2252 | /* TODO: E, U */ |
| 2253 | /* C - Set if bit 3 of source operand is set. Cleared otherwise. */ |
| 2254 | if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2255 | if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2256 | DSP56K_V_CLEAR(); |
| 2257 | if (p_accum & U64(0x0000000000000008)) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 2258 | |
| 2259 | cycles += 2; |
| 2260 | return 1; |
| 2261 | } |
| 2262 | |
| 2263 | /* ASR16 : 0001 0101 0111 F000 : A-36 */ |
| 2264 | static size_t dsp56k_op_asr16(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2265 | { |
| 2266 | UINT64 backupVal; |
| 2267 | typed_pointer D = {NULL, DT_BYTE}; |
| 2268 | |
| 2269 | decode_F_table(cpustate, BITS(op,0x0008), &D); |
| 2270 | |
| 2271 | backupVal = *((UINT64*)D.addr); |
| 2272 | |
| 2273 | *((UINT64*)D.addr) = *((UINT64*)D.addr) >> 16; |
| 2274 | |
| 2275 | if(backupVal & U64(0x0000008000000000)) |
| 2276 | *((UINT64*)D.addr) |= U64(0x000000ffff000000); |
| 2277 | else |
| 2278 | *((UINT64*)D.addr) &= U64(0x0000000000ffffff); |
| 2279 | |
| 2280 | /* S L E U N Z V C */ |
| 2281 | /* - * * * * * 0 ? */ |
| 2282 | /* TODO: E, U */ |
| 2283 | if (*((UINT64*)D.addr) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2284 | if (*((UINT64*)D.addr) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2285 | DSP56K_V_CLEAR(); |
| 2286 | if (backupVal & U64(0x0000000000008000)) DSP56K_C_SET(); else DSP56K_C_CLEAR(); |
| 2287 | |
| 2288 | cycles += 2; |
| 2289 | return 1; |
| 2290 | } |
| 2291 | |
| 2292 | /* BFCHG : 0001 0100 11Pp pppp BBB1 0010 iiii iiii : A-38 */ |
| 2293 | /* BFCLR : 0001 0100 11Pp pppp BBB0 0100 iiii iiii : A-40 */ |
| 2294 | /* BFSET : 0001 0100 11Pp pppp BBB1 1000 iiii iiii : A-42 */ |
| 2295 | /* BFTSTH : 0001 0100 01Pp pppp BBB1 0000 iiii iiii : A-44 */ |
| 2296 | /* BFTSTL : 0001 0100 01Pp pppp BBB0 0000 iiii iiii : A-46 */ |
| 2297 | static size_t dsp56k_op_bfop(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2298 | { |
| 2299 | UINT16 workAddr = 0x0000; |
| 2300 | UINT16 workingWord = 0x0000; |
| 2301 | UINT16 previousValue = 0x0000; |
| 2302 | typed_pointer tempTP = { NULL, DT_BYTE }; |
| 2303 | |
| 2304 | UINT16 iVal = op2 & 0x00ff; |
| 2305 | decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal); |
| 2306 | |
| 2307 | workAddr = assemble_address_from_Pppppp_table(cpustate, BITS(op,0x0020), BITS(op,0x001f)); |
| 2308 | previousValue = cpustate->data->read_word(ADDRESS(workAddr)); |
| 2309 | workingWord = previousValue; |
| 2310 | |
| 2311 | switch(BITS(op2, 0x1f00)) |
| 2312 | { |
| 2313 | case 0x12: /* BFCHG */ |
| 2314 | workingWord ^= iVal; |
| 2315 | break; |
| 2316 | case 0x04: /* BFCLR */ |
| 2317 | workingWord = workingWord & (~iVal); |
| 2318 | break; |
| 2319 | case 0x18: /* BFSET */ |
| 2320 | workingWord = workingWord | iVal; |
| 2321 | break; |
| 2322 | case 0x10: /* BFTSTH */ |
| 2323 | /* Just the test below */ |
| 2324 | break; |
| 2325 | case 0x00: /* BFTSTL */ |
| 2326 | /* Just the test below */ |
| 2327 | break; |
| 2328 | } |
| 2329 | |
| 2330 | tempTP.addr = &workingWord; |
| 2331 | tempTP.data_type = DT_WORD; |
| 2332 | SetDataMemoryValue(cpustate, tempTP, ADDRESS(workAddr)); |
| 2333 | |
| 2334 | /* S L E U N Z V C */ |
| 2335 | /* - * - - - - - ? */ |
| 2336 | /* TODO: L */ |
| 2337 | switch(BITS(op2, 0x1f00)) |
| 2338 | { |
| 2339 | case 0x12: /* BFCHG */ |
| 2340 | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2341 | case 0x04: /* BFCLR */ |
| 2342 | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2343 | case 0x18: /* BFSET */ |
| 2344 | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2345 | case 0x10: /* BFTSTH */ |
| 2346 | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2347 | case 0x00: /* BFTSTL */ |
| 2348 | if ((iVal & previousValue) == 0x0000) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2349 | } |
| 2350 | |
| 2351 | cycles += 4; /* TODO: + mvb oscillator clock cycles */ |
| 2352 | return 2; |
| 2353 | } |
| 2354 | |
| 2355 | /* BFCHG : 0001 0100 101- --RR BBB1 0010 iiii iiii : A-38 */ |
| 2356 | /* BFCLR : 0001 0100 101- --RR BBB0 0100 iiii iiii : A-40 */ |
| 2357 | /* BFSET : 0001 0100 101- --RR BBB1 1000 iiii iiii : A-42 */ |
| 2358 | /* BFTSTH : 0001 0100 001- --RR BBB1 0000 iiii iiii : A-44 */ |
| 2359 | /* BFTSTL : 0001 0100 001- --RR BBB0 0000 iiii iiii : A-46 */ |
| 2360 | static size_t dsp56k_op_bfop_1(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2361 | { |
| 2362 | UINT16 workAddr = 0x0000; |
| 2363 | UINT16 workingWord = 0x0000; |
| 2364 | UINT16 previousValue = 0x0000; |
| 2365 | typed_pointer R = { NULL, DT_BYTE }; |
| 2366 | typed_pointer tempTP = { NULL, DT_BYTE }; |
| 2367 | |
| 2368 | UINT16 iVal = op2 & 0x00ff; |
| 2369 | decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal); |
| 2370 | |
| 2371 | decode_RR_table(cpustate, BITS(op,0x0003), &R); |
| 2372 | |
| 2373 | workAddr = *((UINT16*)R.addr); |
| 2374 | previousValue = cpustate->data->read_word(ADDRESS(workAddr)); |
| 2375 | workingWord = previousValue; |
| 2376 | |
| 2377 | switch(BITS(op2, 0x1f00)) |
| 2378 | { |
| 2379 | case 0x12: /* BFCHG */ |
| 2380 | workingWord ^= iVal; |
| 2381 | break; |
| 2382 | case 0x04: /* BFCLR */ |
| 2383 | workingWord = workingWord & (~iVal); |
| 2384 | break; |
| 2385 | case 0x18: /* BFSET */ |
| 2386 | workingWord = workingWord | iVal; |
| 2387 | break; |
| 2388 | case 0x10: /* BFTSTH */ |
| 2389 | /* Just the test below */ |
| 2390 | break; |
| 2391 | case 0x00: /* BFTSTL */ |
| 2392 | /* Just the test below */ |
| 2393 | break; |
| 2394 | } |
| 2395 | |
| 2396 | tempTP.addr = &workingWord; |
| 2397 | tempTP.data_type = DT_WORD; |
| 2398 | SetDataMemoryValue(cpustate, tempTP, ADDRESS(workAddr)); |
| 2399 | |
| 2400 | /* S L E U N Z V C */ |
| 2401 | /* - * - - - - - ? */ |
| 2402 | /* TODO: L */ |
| 2403 | switch(BITS(op2, 0x1f00)) |
| 2404 | { |
| 2405 | case 0x12: /* BFCHG */ |
| 2406 | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2407 | case 0x04: /* BFCLR */ |
| 2408 | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2409 | case 0x18: /* BFSET */ |
| 2410 | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2411 | case 0x10: /* BFTSTH */ |
| 2412 | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2413 | case 0x00: /* BFTSTL */ |
| 2414 | if ((iVal & previousValue) == 0x0000) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2415 | } |
| 2416 | |
| 2417 | cycles += 4; /* TODO: + mvb oscillator clock cycles */ |
| 2418 | return 2; |
| 2419 | } |
| 2420 | |
| 2421 | /* BFCHG : 0001 0100 100D DDDD BBB1 0010 iiii iiii : A-38 */ |
| 2422 | /* BFCLR : 0001 0100 100D DDDD BBB0 0100 iiii iiii : A-40 */ |
| 2423 | /* BFSET : 0001 0100 100D DDDD BBB1 1000 iiii iiii : A-42 */ |
| 2424 | /* BFTSTH : 0001 0100 000D DDDD BBB1 0000 iiii iiii : A-44 */ |
| 2425 | /* BFTSTL : 0001 0100 000D DDDD BBB0 0000 iiii iiii : A-46 */ |
| 2426 | static size_t dsp56k_op_bfop_2(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2427 | { |
| 2428 | UINT16 workingWord = 0x0000; |
| 2429 | UINT16 previousValue = 0x0000; |
| 2430 | |
| 2431 | UINT16 iVal = op2 & 0x00ff; |
| 2432 | typed_pointer S = { NULL, DT_BYTE }; |
| 2433 | |
| 2434 | decode_BBB_bitmask(cpustate, BITS(op2,0xe000), &iVal); |
| 2435 | decode_DDDDD_table(cpustate, BITS(op,0x001f), &S); |
| 2436 | |
| 2437 | /* A & B are special */ |
| 2438 | if (S.data_type == DT_LONG_WORD) |
| 2439 | previousValue = ((PAIR64*)S.addr)->w.h; |
| 2440 | else |
| 2441 | previousValue = *((UINT16*)S.addr); |
| 2442 | |
| 2443 | workingWord = previousValue; |
| 2444 | |
| 2445 | switch(BITS(op2, 0x1f00)) |
| 2446 | { |
| 2447 | case 0x12: /* BFCHG */ |
| 2448 | workingWord ^= iVal; |
| 2449 | break; |
| 2450 | case 0x04: /* BFCLR */ |
| 2451 | workingWord = workingWord & (~iVal); |
| 2452 | break; |
| 2453 | case 0x18: /* BFSET */ |
| 2454 | workingWord = workingWord | iVal; |
| 2455 | break; |
| 2456 | case 0x10: /* BFTSTH */ |
| 2457 | /* Just the test below */ |
| 2458 | break; |
| 2459 | case 0x00: /* BFTSTL */ |
| 2460 | /* Just the test below */ |
| 2461 | break; |
| 2462 | } |
| 2463 | |
| 2464 | /* Put the data back where it belongs (A & B are special) */ |
| 2465 | if (S.data_type == DT_LONG_WORD) |
| 2466 | ((PAIR64*)S.addr)->w.h = workingWord; |
| 2467 | else |
| 2468 | *((UINT16*)S.addr) = workingWord; |
| 2469 | |
| 2470 | /* S L E U N Z V C */ |
| 2471 | /* - * - - - - - ? */ |
| 2472 | /* TODO: L */ |
| 2473 | switch(BITS(op2, 0x1f00)) |
| 2474 | { |
| 2475 | case 0x12: /* BFCHG */ |
| 2476 | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2477 | case 0x04: /* BFCLR */ |
| 2478 | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2479 | case 0x18: /* BFSET */ |
| 2480 | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2481 | case 0x10: /* BFTSTH */ |
| 2482 | if ((iVal & previousValue) == iVal) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2483 | case 0x00: /* BFTSTL */ |
| 2484 | if ((iVal & previousValue) == 0x0000) DSP56K_C_SET(); else DSP56K_C_CLEAR(); break; |
| 2485 | } |
| 2486 | |
| 2487 | cycles += 4; /* TODO: + mvb oscillator clock cycles */ |
| 2488 | return 2; |
| 2489 | } |
| 2490 | |
| 2491 | /* Bcc : 0000 0111 --11 cccc xxxx xxxx xxxx xxxx : A-48 */ |
| 2492 | static size_t dsp56k_op_bcc(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2493 | { |
| 2494 | int shouldBranch = decode_cccc_table(cpustate, BITS(op,0x000f)); |
| 2495 | |
| 2496 | if (shouldBranch) |
| 2497 | { |
| 2498 | INT16 offset = (INT16)op2; |
| 2499 | |
| 2500 | PC += 2; |
| 2501 | |
| 2502 | cpustate->ppc = PC; |
| 2503 | PC += offset; |
| 2504 | |
| 2505 | cycles += 4; |
| 2506 | return 0; |
| 2507 | } |
| 2508 | else |
| 2509 | { |
| 2510 | cycles += 4; |
| 2511 | return 2; |
| 2512 | } |
| 2513 | |
| 2514 | /* S L E U N Z V C */ |
| 2515 | /* - - - - - - - - */ |
| 2516 | return 0; |
| 2517 | } |
| 2518 | |
| 2519 | /* Bcc : 0010 11cc ccee eeee : A-48 */ |
| 2520 | static size_t dsp56k_op_bcc_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2521 | { |
| 2522 | int shouldBranch = decode_cccc_table(cpustate, BITS(op,0x03c0)); |
| 2523 | |
| 2524 | if (shouldBranch) |
| 2525 | { |
| 2526 | INT16 offset = (INT16)assemble_address_from_6bit_signed_relative_short_address(cpustate, BITS(op,0x003f)); |
| 2527 | |
| 2528 | PC += 1; |
| 2529 | |
| 2530 | cpustate->ppc = PC; |
| 2531 | PC += offset; |
| 2532 | |
| 2533 | cycles += 4; |
| 2534 | return 0; |
| 2535 | } |
| 2536 | else |
| 2537 | { |
| 2538 | cycles += 4; |
| 2539 | return 1; |
| 2540 | } |
| 2541 | |
| 2542 | /* S L E U N Z V C */ |
| 2543 | /* - - - - - - - - */ |
| 2544 | return 0; |
| 2545 | } |
| 2546 | |
| 2547 | /* Bcc : 0000 0111 RR10 cccc : A-48 */ |
| 2548 | static size_t dsp56k_op_bcc_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2549 | { |
| 2550 | /* S L E U N Z V C */ |
| 2551 | /* - - - - - - - - */ |
| 2552 | return 0; |
| 2553 | } |
| 2554 | |
| 2555 | /* BRA : 0000 0001 0011 11-- xxxx xxxx xxxx xxxx : A-50 */ |
| 2556 | static size_t dsp56k_op_bra(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2557 | { |
| 2558 | /* S L E U N Z V C */ |
| 2559 | /* - - - - - - - - */ |
| 2560 | return 0; |
| 2561 | } |
| 2562 | |
| 2563 | /* BRA : 0000 1011 aaaa aaaa : A-50 */ |
| 2564 | static size_t dsp56k_op_bra_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2565 | { |
| 2566 | /* 8 bit immediate, relative offset */ |
| 2567 | INT8 branchOffset = (INT8)BITS(op,0x00ff); |
| 2568 | |
| 2569 | /* "The PC Contains the address of the next instruction" */ |
| 2570 | PC += 1; |
| 2571 | |
| 2572 | /* Jump */ |
| 2573 | cpustate->ppc = PC; |
| 2574 | PC += branchOffset; |
| 2575 | |
| 2576 | /* S L E U N Z V C */ |
| 2577 | /* - - - - - - - - */ |
| 2578 | cycles += 4; /* TODO: + jx oscillator clock cycles */ |
| 2579 | return 0; |
| 2580 | } |
| 2581 | |
| 2582 | /* BRA : 0000 0001 0010 11RR : A-50 */ |
| 2583 | static size_t dsp56k_op_bra_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2584 | { |
| 2585 | /* S L E U N Z V C */ |
| 2586 | /* - - - - - - - - */ |
| 2587 | return 0; |
| 2588 | } |
| 2589 | |
| 2590 | /* BRKcc : 0000 0001 0001 cccc : A-52 */ |
| 2591 | static size_t dsp56k_op_brkcc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2592 | { |
| 2593 | int shouldBreak = decode_cccc_table(cpustate, BITS(op,0x000f)); |
| 2594 | |
| 2595 | if (shouldBreak) |
| 2596 | { |
| 2597 | /* TODO: I think this PC = LA thing is off-by-1, but it's working this way because its consistently so */ |
| 2598 | cpustate->ppc = PC; |
| 2599 | PC = LA; |
| 2600 | |
| 2601 | SR = SSL; /* TODO: A-83. I believe only the Loop Flag and Forever Flag come back here. */ |
| 2602 | SP--; |
| 2603 | |
| 2604 | LA = SSH; |
| 2605 | LC = SSL; |
| 2606 | SP--; |
| 2607 | |
| 2608 | cycles += 8; |
| 2609 | return 0; |
| 2610 | } |
| 2611 | else |
| 2612 | { |
| 2613 | cycles += 2; |
| 2614 | return 1; |
| 2615 | } |
| 2616 | |
| 2617 | /* S L E U N Z V C */ |
| 2618 | /* - - - - - - - - */ |
| 2619 | return 0; |
| 2620 | } |
| 2621 | |
| 2622 | /* BScc : 0000 0111 --01 cccc xxxx xxxx xxxx xxxx : A-54 */ |
| 2623 | static size_t dsp56k_op_bscc(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2624 | { |
| 2625 | int shouldBranch = decode_cccc_table(cpustate, BITS(op,0x000f)); |
| 2626 | |
| 2627 | if (shouldBranch) |
| 2628 | { |
| 2629 | /* The PC Contains the address of the next instruction */ |
| 2630 | PC += 2; |
| 2631 | |
| 2632 | /* Push */ |
| 2633 | SP++; |
| 2634 | SSH = PC; |
| 2635 | SSL = SR; |
| 2636 | |
| 2637 | /* Change */ |
| 2638 | cpustate->ppc = PC; |
| 2639 | PC = PC + (INT16)op2; |
| 2640 | |
| 2641 | /* S L E U N Z V C */ |
| 2642 | /* - - - - - - - - */ |
| 2643 | cycles += 4; /* TODO: + jx oscillator clock cycles */ |
| 2644 | return 0; |
| 2645 | } |
| 2646 | |
| 2647 | /* S L E U N Z V C */ |
| 2648 | /* - - - - - - - - */ |
| 2649 | cycles += 4; /* TODO: + jx oscillator clock cycles */ |
| 2650 | return 2; |
| 2651 | } |
| 2652 | |
| 2653 | /* BScc : 0000 0111 RR00 cccc : A-54 */ |
| 2654 | static size_t dsp56k_op_bscc_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2655 | { |
| 2656 | /* S L E U N Z V C */ |
| 2657 | /* - - - - - - - - */ |
| 2658 | return 0; |
| 2659 | } |
| 2660 | |
| 2661 | /* BSR : 0000 0001 0011 10-- xxxx xxxx xxxx xxxx : A-56 */ |
| 2662 | static size_t dsp56k_op_bsr(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2663 | { |
| 2664 | /* The PC Contains the address of the next instruction */ |
| 2665 | PC += 2; |
| 2666 | |
| 2667 | /* Push */ |
| 2668 | SP++; |
| 2669 | SSH = PC; |
| 2670 | SSL = SR; |
| 2671 | |
| 2672 | /* Change */ |
| 2673 | cpustate->ppc = PC; |
| 2674 | PC = PC + (INT16)op2; |
| 2675 | |
| 2676 | /* S L E U N Z V C */ |
| 2677 | /* - - - - - - - - */ |
| 2678 | cycles += 4; /* TODO: + jx oscillator clock cycles */ |
| 2679 | return 0; |
| 2680 | } |
| 2681 | |
| 2682 | /* BSR : 0000 0001 0010 10RR : A-56 */ |
| 2683 | static size_t dsp56k_op_bsr_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2684 | { |
| 2685 | /* S L E U N Z V C */ |
| 2686 | /* - - - - - - - - */ |
| 2687 | return 0; |
| 2688 | } |
| 2689 | |
| 2690 | /* CHKAAU : 0000 0000 0000 0100 : A-58 */ |
| 2691 | static size_t dsp56k_op_chkaau(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2692 | { |
| 2693 | /* S L E U N Z V C */ |
| 2694 | /* - - - - ? ? ? - */ |
| 2695 | /* V - Set if the result of the last address ALU update performed a modulo wrap. Cleared if |
| 2696 | result of the last address ALU did not perform a modulo wrap.*/ |
| 2697 | /* Z - Set if the result of the last address ALU update is 0. Cleared if the result of the last |
| 2698 | address ALU is positive. */ |
| 2699 | /* N - Set if the result of the last address ALU update is negative. Cleared if the result of the |
| 2700 | last address ALU is positive. */ |
| 2701 | return 0; |
| 2702 | } |
| 2703 | |
| 2704 | /* DEBUG : 0000 0000 0000 0001 : A-68 */ |
| 2705 | static size_t dsp56k_op_debug(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2706 | { |
| 2707 | /* S L E U N Z V C */ |
| 2708 | /* - - - - - - - - */ |
| 2709 | return 0; |
| 2710 | } |
| 2711 | |
| 2712 | /* DEBUGcc : 0000 0000 0101 cccc : A-70 */ |
| 2713 | static size_t dsp56k_op_debugcc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2714 | { |
| 2715 | /* S L E U N Z V C */ |
| 2716 | /* - - - - - - - - */ |
| 2717 | return 0; |
| 2718 | } |
| 2719 | |
| 2720 | /* DIV : 0001 0101 0--0 F1DD : A-76 */ |
| 2721 | /* WARNING : DOCS SAY THERE IS A PARALLEL MOVE HERE !!! */ |
| 2722 | static size_t dsp56k_op_div(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2723 | { |
| 2724 | /* WARNING : THIS DOES NOT WORK. IT DOESN'T EVEN TRY !!! */ |
| 2725 | typed_pointer S = {NULL, DT_BYTE}; |
| 2726 | typed_pointer D = {NULL, DT_BYTE}; |
| 2727 | |
| 2728 | decode_DDF_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S, &D); |
| 2729 | |
| 2730 | /* S L E U N Z V C */ |
| 2731 | /* - * - - - - ? ? */ |
| 2732 | /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significantst |
| 2733 | bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */ |
| 2734 | /* C - Set if bit 39 of the result is cleared. Cleared otherwise. */ |
| 2735 | cycles += 2; |
| 2736 | return 1; |
| 2737 | } |
| 2738 | |
| 2739 | /* DMAC : 0001 0101 10s1 FsQQ : A-80 */ |
| 2740 | static size_t dsp56k_op_dmac(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2741 | { |
| 2742 | UINT8 ss = 0; |
| 2743 | INT64 result = 0; |
| 2744 | |
| 2745 | void* D = NULL; |
| 2746 | void* S1 = NULL; |
| 2747 | void* S2 = NULL; |
| 2748 | |
| 2749 | decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D); |
| 2750 | |
| 2751 | ss = BITS(op,0x0024); |
| 2752 | |
| 2753 | /* Fixed-point 2's complement multiplication requires a shift */ |
| 2754 | if (ss == 0x00 || ss == 0x01) |
| 2755 | { |
| 2756 | /* Signed * Signed */ |
| 2757 | INT32 s1 = ((INT32)(*((UINT16*)S1))); |
| 2758 | INT32 s2 = ((INT32)(*((UINT16*)S2))); |
| 2759 | result = ( s1 * s2 ) << 1; |
| 2760 | } |
| 2761 | else if (ss == 0x2) |
| 2762 | { |
| 2763 | /* Signed * Unsigned */ |
| 2764 | /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */ |
| 2765 | INT32 s1 = ((INT32)(*((UINT16*)S1))); |
| 2766 | INT32 s2 = (UINT32)(*((UINT16*)S2)); |
| 2767 | result = ( s1 * s2 ) << 1; |
| 2768 | } |
| 2769 | else if (ss == 0x3) |
| 2770 | { |
| 2771 | /* Unsigned * Unsigned */ |
| 2772 | UINT32 s1 = (UINT32)(*((UINT16*)S1)); |
| 2773 | UINT32 s2 = (UINT32)(*((UINT16*)S2)); |
| 2774 | result = ( s1 * s2 ) << 1; |
| 2775 | } |
| 2776 | |
| 2777 | /* Shift right, then accumulate */ |
| 2778 | (*((UINT64*)D)) = (*((UINT64*)D)) >> 16; |
| 2779 | (*((UINT64*)D)) += result; |
| 2780 | |
| 2781 | /* S L E U N Z V C */ |
| 2782 | /* - * * * * * * - */ |
| 2783 | /* TODO: L, E, U, V */ |
| 2784 | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 2785 | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 2786 | |
| 2787 | cycles += 2; |
| 2788 | return 1; |
| 2789 | } |
| 2790 | |
| 2791 | /* DO : 0000 0000 110- --RR xxxx xxxx xxxx xxxx : A-82 */ |
| 2792 | static size_t dsp56k_op_do(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2793 | { |
| 2794 | /* S L E U N Z V C */ |
| 2795 | /* - * - - - - - - */ |
| 2796 | return 0; |
| 2797 | } |
| 2798 | |
| 2799 | /* DO : 0000 1110 iiii iiii xxxx xxxx xxxx xxxx : A-82 */ |
| 2800 | static size_t dsp56k_op_do_1(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2801 | { |
| 2802 | UINT8 retSize = 0; |
| 2803 | UINT8 iValue = BITS(op,0x00ff); |
| 2804 | |
| 2805 | /* Don't execute if the loop counter == 0 */ |
| 2806 | if (iValue != 0x00) |
| 2807 | { |
| 2808 | /* First instruction cycle */ |
| 2809 | SP++; /* TODO: Should i really inc here first? */ |
| 2810 | SSH = LA; |
| 2811 | SSL = LC; |
| 2812 | LC = (UINT16)iValue; |
| 2813 | |
| 2814 | |
| 2815 | /* Second instruction cycle */ |
| 2816 | SP++; /* TODO: See above */ |
| 2817 | SSH = PC + 2; /* Keep these stack entries in 'word-based-index' space */ |
| 2818 | SSL = SR; |
| 2819 | LA = PC + 2 + op2; /* TODO: The docs subtract 1 from here? */ |
| 2820 | |
| 2821 | |
| 2822 | /* Third instruction cycle */ |
| 2823 | LF_bit_set(cpustate, 1); |
| 2824 | |
| 2825 | /* Undocumented, but it must be true to nest Dos in DoForevers */ |
| 2826 | FV_bit_set(cpustate, 0); |
| 2827 | |
| 2828 | |
| 2829 | /* S L E U N Z V C */ |
| 2830 | /* - * - - - - - - */ |
| 2831 | /* TODO : L */ |
| 2832 | |
| 2833 | cycles += 6; /* TODO: + mv oscillator cycles */ |
| 2834 | retSize = 2; |
| 2835 | } |
| 2836 | else |
| 2837 | { |
| 2838 | /* Skip over the contents of the loop */ |
| 2839 | cpustate->ppc = PC; |
| 2840 | PC = PC + 2 + op2; |
| 2841 | |
| 2842 | cycles += 10; /* TODO: + mv oscillator cycles */ |
| 2843 | retSize = 0; |
| 2844 | } |
| 2845 | |
| 2846 | return retSize; |
| 2847 | } |
| 2848 | |
| 2849 | /* DO : 0000 0100 000D DDDD xxxx xxxx xxxx xxxx : A-82 */ |
| 2850 | static size_t dsp56k_op_do_2(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2851 | { |
| 2852 | UINT8 retSize = 0; |
| 2853 | UINT16 lValue = 0x0000; |
| 2854 | typed_pointer S = {NULL, DT_BYTE}; |
| 2855 | decode_DDDDD_table(cpustate, BITS(op,0x001f), &S); |
| 2856 | |
| 2857 | /* TODO: Does not properly shift-limit sources A&B - Fix per the docs. */ |
| 2858 | /* TODO: There are other cases besides A&B this code won't work. */ |
| 2859 | if (S.addr == &A) lValue = *((UINT16*)(&A1)); |
| 2860 | else if (S.addr == &B) lValue = *((UINT16*)(&B1)); |
| 2861 | else lValue = *((UINT16*)S.addr); |
| 2862 | |
| 2863 | /* HACK */ |
| 2864 | if (lValue >= 0xfff0) |
| 2865 | { |
| 2866 | logerror("Dsp56k : DO_2 operation changed %04x to 0000.\n", lValue); |
| 2867 | lValue = 0x0000; |
| 2868 | } |
| 2869 | |
| 2870 | /* TODO: Fix for special cased SP S */ |
| 2871 | if (S.addr == &SP) |
| 2872 | logerror("DSP56k: do with SP as the source not properly implemented yet.\n"); |
| 2873 | |
| 2874 | /* TODO: Fix for special cased SSSL S */ |
| 2875 | if (S.addr == &SSL) |
| 2876 | logerror("DSP56k: do with SP as the source not properly implemented yet.\n"); |
| 2877 | |
| 2878 | /* Don't execute if the loop counter == 0 */ |
| 2879 | if (lValue != 0x00) |
| 2880 | { |
| 2881 | /* First instruction cycle */ |
| 2882 | SP++; /* TODO: Should i really inc here first? */ |
| 2883 | SSH = LA; |
| 2884 | SSL = LC; |
| 2885 | LC = (UINT16)lValue; |
| 2886 | |
| 2887 | |
| 2888 | /* Second instruction cycle */ |
| 2889 | SP++; /* TODO: See above */ |
| 2890 | SSH = PC + 2; /* Keep these stack entries in 'word-based-index' space */ |
| 2891 | SSL = SR; |
| 2892 | LA = PC + 2 + op2; /* TODO: The docs subtract 1 from here? */ |
| 2893 | |
| 2894 | |
| 2895 | /* Third instruction cycle */ |
| 2896 | LF_bit_set(cpustate, 1); |
| 2897 | |
| 2898 | |
| 2899 | /* S L E U N Z V C */ |
| 2900 | /* - * - - - - - - */ |
| 2901 | /* TODO : L */ |
| 2902 | |
| 2903 | cycles += 6; /* TODO: + mv oscillator cycles */ |
| 2904 | retSize = 2; |
| 2905 | } |
| 2906 | else |
| 2907 | { |
| 2908 | /* Skip over the contents of the loop */ |
| 2909 | cpustate->ppc = PC; |
| 2910 | PC = PC + 2 + op2; |
| 2911 | |
| 2912 | cycles += 10; /* TODO: + mv oscillator cycles */ |
| 2913 | retSize = 0; |
| 2914 | } |
| 2915 | |
| 2916 | return retSize; |
| 2917 | } |
| 2918 | |
| 2919 | /* DO FOREVER : 0000 0000 0000 0010 xxxx xxxx xxxx xxxx : A-88 */ |
| 2920 | static size_t dsp56k_op_doforever(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 2921 | { |
| 2922 | /* First instruction cycle */ |
| 2923 | SP++; |
| 2924 | SSH = LA; |
| 2925 | SSL = LC; |
| 2926 | |
| 2927 | /* Second instruction cycle */ |
| 2928 | SP++; |
| 2929 | SSH = PC + 2; |
| 2930 | SSL = SR; |
| 2931 | LA = PC + 2 + op2; |
| 2932 | |
| 2933 | /* Third instruction cycle */ |
| 2934 | LF_bit_set(cpustate, 1); |
| 2935 | FV_bit_set(cpustate, 1); |
| 2936 | |
| 2937 | /* S L E U N Z V C */ |
| 2938 | /* - - - - - - - - */ |
| 2939 | cycles += 6; |
| 2940 | return 2; |
| 2941 | } |
| 2942 | |
| 2943 | /* ENDDO : 0000 0000 0000 1001 : A-92 */ |
| 2944 | static size_t dsp56k_op_enddo(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2945 | { |
| 2946 | /* S L E U N Z V C */ |
| 2947 | /* - - - - - - - - */ |
| 2948 | return 0; |
| 2949 | } |
| 2950 | |
| 2951 | /* EXT : 0001 0101 0101 F010 : A-96 */ |
| 2952 | static size_t dsp56k_op_ext(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2953 | { |
| 2954 | /* S L E U N Z V C */ |
| 2955 | /* - * * * * * * - */ |
| 2956 | return 0; |
| 2957 | } |
| 2958 | |
| 2959 | /* ILLEGAL : 0000 0000 0000 1111 : A-98 */ |
| 2960 | static size_t dsp56k_op_illegal(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2961 | { |
| 2962 | /* S L E U N Z V C */ |
| 2963 | /* - - - - - - - - */ |
| 2964 | return 0; |
| 2965 | } |
| 2966 | |
| 2967 | /* IMAC : 0001 0101 1010 FQQQ : A-100 */ |
| 2968 | static size_t dsp56k_op_imac(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 2969 | { |
| 2970 | INT64 opD = 0; |
| 2971 | INT64 result = 0; |
| 2972 | |
| 2973 | INT32 s1 = 0; |
| 2974 | INT32 s2 = 0; |
| 2975 | |
| 2976 | void* D = NULL; |
| 2977 | void* S1 = NULL; |
| 2978 | void* S2 = NULL; |
| 2979 | |
| 2980 | decode_QQQF_table(cpustate, BITS(op,0x0007), BITS(op,0x0008), &S1, &S2, &D); |
| 2981 | |
| 2982 | /* Cast both values as being signed */ |
| 2983 | s1 = *((INT16*)S1); |
| 2984 | s2 = *((INT16*)S2); |
| 2985 | |
| 2986 | /* Integral multiply doesn't require the shift */ |
| 2987 | result = (s1 * s2); |
| 2988 | |
| 2989 | /* Shift result 16 bits to the left before adding to destination */ |
| 2990 | result = (result << 16) & 0xffff0000; |
| 2991 | |
| 2992 | /* Sign extend D into a temp variable */ |
| 2993 | opD = (*((UINT64*)D)); |
| 2994 | if (opD & U64(0x0000008000000000)) |
| 2995 | opD |= U64(0xffffff0000000000); |
| 2996 | else |
| 2997 | opD &= U64(0x000000ffffffffff); |
| 2998 | |
| 2999 | /* Accumulate */ |
| 3000 | opD += result; |
| 3001 | |
| 3002 | /* And out the bits that don't live in the register */ |
| 3003 | opD &= U64(0x000000ffffffffff); |
| 3004 | |
| 3005 | (*((UINT64*)D)) = (UINT64)opD; |
| 3006 | |
| 3007 | /* S L E U N Z V C */ |
| 3008 | /* - * ? ? * ? ? - */ |
| 3009 | /* TODO: L */ |
| 3010 | /* U,E - Will not be set correctly by this instruction*/ |
| 3011 | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 3012 | if ((*((UINT64*)D) & U64(0x000000ffffff0000)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 3013 | DSP56K_V_CLEAR(); |
| 3014 | |
| 3015 | cycles += 2; |
| 3016 | return 1; |
| 3017 | } |
| 3018 | |
| 3019 | /* IMPY : 0001 0101 1000 FQQQ : A-102 */ |
| 3020 | static size_t dsp56k_op_impy(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3021 | { |
| 3022 | /* S L E U N Z V C */ |
| 3023 | /* - * ? ? * ? ? - */ |
| 3024 | /* Z - Set if the 24 most significant bits of the destination result are all zeroes. */ |
| 3025 | /* U,E - Will not be set correctly by this instruction*/ |
| 3026 | /* V - Set to zero regardless of the overflow */ |
| 3027 | return 0; |
| 3028 | } |
| 3029 | |
| 3030 | /* Jcc : 0000 0110 --11 cccc xxxx xxxx xxxx xxxx : A-108 */ |
| 3031 | static size_t dsp56k_op_jcc(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3032 | { |
| 3033 | /* S L E U N Z V C */ |
| 3034 | /* - - - - - - - - */ |
| 3035 | return 0; |
| 3036 | } |
| 3037 | |
| 3038 | /* Jcc : 0000 0110 RR10 cccc : A-108 */ |
| 3039 | static size_t dsp56k_op_jcc_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3040 | { |
| 3041 | /* S L E U N Z V C */ |
| 3042 | /* - - - - - - - - */ |
| 3043 | return 0; |
| 3044 | } |
| 3045 | |
| 3046 | /* JMP : 0000 0001 0011 01-- xxxx xxxx xxxx xxxx : A-110 */ |
| 3047 | static size_t dsp56k_op_jmp(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3048 | { |
| 3049 | cpustate->ppc = PC; |
| 3050 | PC = op2; |
| 3051 | |
| 3052 | /* S L E U N Z V C */ |
| 3053 | /* - - - - - - - - */ |
| 3054 | |
| 3055 | cycles += 4; /* TODO: + jx */ |
| 3056 | return 0; |
| 3057 | } |
| 3058 | |
| 3059 | /* JMP : 0000 0001 0010 01RR : A-110 */ |
| 3060 | static size_t dsp56k_op_jmp_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3061 | { |
| 3062 | typed_pointer R = { NULL, DT_BYTE }; |
| 3063 | decode_RR_table(cpustate, BITS(op,0x0003), &R); |
| 3064 | |
| 3065 | cpustate->ppc = PC; |
| 3066 | PC = *((UINT16*)R.addr); |
| 3067 | |
| 3068 | /* S L E U N Z V C */ |
| 3069 | /* - - - - - - - - */ |
| 3070 | |
| 3071 | cycles += 4; /* TODO: + jx */ |
| 3072 | return 0; |
| 3073 | } |
| 3074 | |
| 3075 | /* JScc : 0000 0110 --01 cccc xxxx xxxx xxxx xxxx : A-112 */ |
| 3076 | static size_t dsp56k_op_jscc(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3077 | { |
| 3078 | int shouldJump = decode_cccc_table(cpustate, BITS(op,0x000f)); |
| 3079 | |
| 3080 | if(shouldJump) |
| 3081 | { |
| 3082 | /* TODO: It says "signed" absolute offset. Weird. */ |
| 3083 | UINT16 branchOffset = op2; |
| 3084 | |
| 3085 | /* TODO: Verify, since it's not in the docs, but it must be true */ |
| 3086 | PC += 2; |
| 3087 | |
| 3088 | SP++; |
| 3089 | SSH = PC; |
| 3090 | SSL = SR; |
| 3091 | |
| 3092 | cpustate->ppc = PC; |
| 3093 | PC = branchOffset; |
| 3094 | |
| 3095 | cycles += 4; /* TODO: +jx oscillator clock cycles */ |
| 3096 | return 0; |
| 3097 | } |
| 3098 | else |
| 3099 | { |
| 3100 | cycles += 4; /* TODO: +jx oscillator clock cycles */ |
| 3101 | return 2; |
| 3102 | } |
| 3103 | |
| 3104 | /* S L E U N Z V C */ |
| 3105 | /* - - - - - - - - */ |
| 3106 | return 0; |
| 3107 | } |
| 3108 | |
| 3109 | /* JScc : 0000 0110 RR00 cccc : A-112 */ |
| 3110 | static size_t dsp56k_op_jscc_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3111 | { |
| 3112 | /* S L E U N Z V C */ |
| 3113 | /* - - - - - - - - */ |
| 3114 | return 0; |
| 3115 | } |
| 3116 | |
| 3117 | /* JSR : 0000 0001 0011 00-- xxxx xxxx xxxx xxxx : A-114 */ |
| 3118 | static size_t dsp56k_op_jsr(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3119 | { |
| 3120 | /* TODO: It says "signed" absolute offset. Weird. */ |
| 3121 | UINT16 branchOffset = op2; |
| 3122 | |
| 3123 | /* TODO: Verify, since it's not in the docs, but it must be true */ |
| 3124 | PC += 2; |
| 3125 | |
| 3126 | /* TODO: This is a hacky implementation of Long vs Fast Interrupts. Do it right someday! */ |
| 3127 | if (PC < ADDRESS(0x40)) |
| 3128 | { |
| 3129 | /* Long interrupt gets the previous PC, not the current one */ |
| 3130 | SP++; |
| 3131 | SSH = cpustate->ppc; |
| 3132 | SSL = SR; |
| 3133 | |
| 3134 | cpustate->ppc = cpustate->ppc; |
| 3135 | PC = branchOffset; |
| 3136 | } |
| 3137 | else |
| 3138 | { |
| 3139 | /* Normal operation */ |
| 3140 | SP++; |
| 3141 | SSH = PC; |
| 3142 | SSL = SR; |
| 3143 | |
| 3144 | cpustate->ppc = PC; |
| 3145 | PC = branchOffset; |
| 3146 | } |
| 3147 | |
| 3148 | /* S L E U N Z V C */ |
| 3149 | /* - - - - - - - - */ |
| 3150 | cycles += 4; /* TODO: + jx oscillator cycles */ |
| 3151 | return 0; |
| 3152 | } |
| 3153 | |
| 3154 | /* JSR : 0000 1010 AAAA AAAA : A-114 */ |
| 3155 | static size_t dsp56k_op_jsr_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3156 | { |
| 3157 | /* S L E U N Z V C */ |
| 3158 | /* - - - - - - - - */ |
| 3159 | return 0; |
| 3160 | } |
| 3161 | |
| 3162 | /* JSR : 0000 0001 0010 00RR : A-114 */ |
| 3163 | static size_t dsp56k_op_jsr_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3164 | { |
| 3165 | /* S L E U N Z V C */ |
| 3166 | /* - - - - - - - - */ |
| 3167 | return 0; |
| 3168 | } |
| 3169 | |
| 3170 | /* LEA : 0000 0001 11TT MMRR : A-116 */ |
| 3171 | static size_t dsp56k_op_lea(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3172 | { |
| 3173 | UINT16 ea = 0; |
| 3174 | UINT16 *rX = NULL; |
| 3175 | UINT16 *nX = NULL; |
| 3176 | typed_pointer D = {NULL, DT_BYTE}; |
| 3177 | decode_TT_table(cpustate, BITS(op,0x0030), &D); |
| 3178 | |
| 3179 | /* TODO: change the execute_mm_functions to return values. Maybe */ |
| 3180 | /* Because this calculation isn't applied, do everything locally */ |
| 3181 | /* RR table */ |
| 3182 | switch(BITS(op,0x0003)) |
| 3183 | { |
| 3184 | case 0x0: rX = &R0; nX = &N0; break; |
| 3185 | case 0x1: rX = &R1; nX = &N1; break; |
| 3186 | case 0x2: rX = &R2; nX = &N2; break; |
| 3187 | case 0x3: rX = &R3; nX = &N3; break; |
| 3188 | } |
| 3189 | |
| 3190 | /* MM table */ |
| 3191 | switch(BITS(op,0x000c)) |
| 3192 | { |
| 3193 | case 0x0: ea = *rX; break; |
| 3194 | case 0x1: ea = *rX + 1; break; |
| 3195 | case 0x2: ea = *rX - 1; break; |
| 3196 | case 0x3: ea = *rX + *nX; break; |
| 3197 | } |
| 3198 | |
| 3199 | *((UINT16*)D.addr) = ea; |
| 3200 | |
| 3201 | /* S L E U N Z V C */ |
| 3202 | /* - - - - - - - - */ |
| 3203 | return 1; |
| 3204 | } |
| 3205 | |
| 3206 | /* LEA : 0000 0001 10NN MMRR : A-116 */ |
| 3207 | static size_t dsp56k_op_lea_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3208 | { |
| 3209 | /* S L E U N Z V C */ |
| 3210 | /* - - - - - - - - */ |
| 3211 | return 0; |
| 3212 | } |
| 3213 | |
| 3214 | /* MAC(su,uu) : 0001 0101 1110 FsQQ : A-126 */ |
| 3215 | static size_t dsp56k_op_macsuuu(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3216 | { |
| 3217 | UINT8 s = 0; |
| 3218 | INT64 result = 0; |
| 3219 | |
| 3220 | void* D = NULL; |
| 3221 | void* S1 = NULL; |
| 3222 | void* S2 = NULL; |
| 3223 | |
| 3224 | decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D); |
| 3225 | |
| 3226 | s = BITS(op,0x0004); |
| 3227 | |
| 3228 | /* Fixed-point 2's complement multiplication requires a shift */ |
| 3229 | if (s) |
| 3230 | { |
| 3231 | /* Unsigned * Unsigned */ |
| 3232 | UINT32 s1 = (UINT32)(*((UINT16*)S1)); |
| 3233 | UINT32 s2 = (UINT32)(*((UINT16*)S2)); |
| 3234 | result = ( s1 * s2 ) << 1; |
| 3235 | } |
| 3236 | else |
| 3237 | { |
| 3238 | /* Signed * Unsigned */ |
| 3239 | /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */ |
| 3240 | INT32 s1 = ((INT32)(*((UINT16*)S1))); |
| 3241 | INT32 s2 = (UINT32)(*((UINT16*)S2)); |
| 3242 | result = ( s1 * s2 ) << 1; |
| 3243 | } |
| 3244 | |
| 3245 | (*((UINT64*)D)) += result; |
| 3246 | |
| 3247 | /* And out the bits that don't live in the register */ |
| 3248 | (*((UINT64*)D)) &= U64(0x000000ffffffffff); |
| 3249 | |
| 3250 | /* S L E U N Z V C */ |
| 3251 | /* - * * * * * * - */ |
| 3252 | /* TODO: L, E, U, V */ |
| 3253 | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 3254 | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 3255 | |
| 3256 | cycles += 2; |
| 3257 | return 1; |
| 3258 | } |
| 3259 | |
| 3260 | /* MOVE : 0000 0101 BBBB BBBB ---- HHHW 0001 0001 : A-128 */ |
| 3261 | static size_t dsp56k_op_move_2(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3262 | { |
| 3263 | /* S L E U N Z V C */ |
| 3264 | /* * * - - - - - - */ |
| 3265 | return 0; |
| 3266 | } |
| 3267 | |
| 3268 | /* MOVE(C) : 0011 1WDD DDD0 MMRR : A-144 */ |
| 3269 | static size_t dsp56k_op_movec(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3270 | { |
| 3271 | UINT8 W; |
| 3272 | typed_pointer R = { NULL, DT_BYTE }; |
| 3273 | typed_pointer SD = { NULL, DT_BYTE }; |
| 3274 | |
| 3275 | W = BITS(op,0x0400); |
| 3276 | decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD); |
| 3277 | decode_RR_table(cpustate, BITS(op,0x0003), &R); |
| 3278 | |
| 3279 | if (W) |
| 3280 | { |
| 3281 | /* Write D */ |
| 3282 | UINT16 value = cpustate->data->read_word(ADDRESS(*((UINT16*)R.addr))) ; |
| 3283 | typed_pointer temp_src = { &value, DT_WORD }; |
| 3284 | SetDestinationValue(temp_src, SD); |
| 3285 | } |
| 3286 | else |
| 3287 | { |
| 3288 | /* Read S */ |
| 3289 | UINT16 dataMemOffset = *((UINT16*)R.addr); |
| 3290 | SetDataMemoryValue(cpustate, SD, ADDRESS(dataMemOffset)); |
| 3291 | } |
| 3292 | |
| 3293 | execute_MM_table(cpustate, BITS(op,0x0003), BITS(op,0x000c)); |
| 3294 | |
| 3295 | /* S L E U N Z V C */ |
| 3296 | /* * ? ? ? ? ? ? ? */ |
| 3297 | /* All ? bits - If SR is specified as a destination operand, set according to the corresponding |
| 3298 | bit of the source operand. If SR is not specified as a destination operand, L is set if data |
| 3299 | limiting occurred. All ? bits are not affected otherwise.*/ |
| 3300 | if (W && (SD.addr != &SR)) |
| 3301 | { |
| 3302 | /* If you're writing to something other than the SR */ |
| 3303 | /* TODO */ |
| 3304 | } |
| 3305 | |
| 3306 | cycles += 2; /* TODO: + mvc */ |
| 3307 | return 1; |
| 3308 | } |
| 3309 | |
| 3310 | /* MOVE(C) : 0011 1WDD DDD1 q0RR : A-144 */ |
| 3311 | static size_t dsp56k_op_movec_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3312 | { |
| 3313 | UINT8 W; |
| 3314 | UINT16 memOffset; |
| 3315 | typed_pointer SD = {NULL, DT_BYTE}; |
| 3316 | |
| 3317 | W = BITS(op,0x0400); |
| 3318 | decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD); |
| 3319 | memOffset = execute_q_table(cpustate, BITS(op,0x0003), BITS(op,0x0008)); |
| 3320 | |
| 3321 | if (W) |
| 3322 | { |
| 3323 | /* Write D */ |
| 3324 | UINT16 tempData = cpustate->data->read_word(ADDRESS(memOffset)); |
| 3325 | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3326 | SetDestinationValue(temp_src, SD); |
| 3327 | } |
| 3328 | else |
| 3329 | { |
| 3330 | /* Read S */ |
| 3331 | UINT16 tempData = *((UINT16*)SD.addr); |
| 3332 | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3333 | SetDataMemoryValue(cpustate, temp_src, ADDRESS(memOffset)); |
| 3334 | } |
| 3335 | |
| 3336 | /* S L E U N Z V C */ |
| 3337 | /* * ? ? ? ? ? ? ? */ |
| 3338 | /* All ? bits - If SR is specified as a destination operand, set according to the corresponding |
| 3339 | bit of the source operand. If SR is not specified as a destination operand, L is set if data |
| 3340 | limiting occurred. All ? bits are not affected otherwise.*/ |
| 3341 | if (W && (SD.addr != &SR)) |
| 3342 | { |
| 3343 | /* If you're writing to something other than the SR */ |
| 3344 | /* TODO */ |
| 3345 | } |
| 3346 | |
| 3347 | cycles += 2; /* + mvc oscillator clock cycles */ |
| 3348 | return 1; |
| 3349 | } |
| 3350 | |
| 3351 | /* MOVE(C) : 0011 1WDD DDD1 Z11- : A-144 */ |
| 3352 | static size_t dsp56k_op_movec_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3353 | { |
| 3354 | UINT8 W; |
| 3355 | UINT16 memOffset; |
| 3356 | typed_pointer SD = {NULL, DT_BYTE}; |
| 3357 | typed_pointer XMemOffset = {NULL, DT_BYTE}; |
| 3358 | |
| 3359 | W = BITS(op,0x0400); |
| 3360 | decode_Z_table(cpustate, BITS(op,0x0008), &XMemOffset); |
| 3361 | decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD); |
| 3362 | |
| 3363 | memOffset = *((UINT16*)XMemOffset.addr); |
| 3364 | |
| 3365 | if (W) |
| 3366 | { |
| 3367 | /* Write D */ |
| 3368 | UINT16 tempData = cpustate->data->read_word(ADDRESS(memOffset)); |
| 3369 | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3370 | SetDestinationValue(temp_src, SD); |
| 3371 | } |
| 3372 | else |
| 3373 | { |
| 3374 | /* Read S */ |
| 3375 | UINT16 tempData = *((UINT16*)SD.addr); |
| 3376 | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3377 | SetDataMemoryValue(cpustate, temp_src, ADDRESS(memOffset)); |
| 3378 | } |
| 3379 | |
| 3380 | |
| 3381 | /* S L E U N Z V C */ |
| 3382 | /* * ? ? ? ? ? ? ? */ |
| 3383 | /* All ? bits - If SR is specified as a destination operand, set according to the corresponding |
| 3384 | bit of the source operand. If SR is not specified as a destination operand, L is set if data |
| 3385 | limiting occurred. All ? bits are not affected otherwise.*/ |
| 3386 | if (W && (SD.addr != &SR)) |
| 3387 | { |
| 3388 | /* If you're writing to something other than the SR */ |
| 3389 | /* TODO */ |
| 3390 | } |
| 3391 | |
| 3392 | cycles += 2; /* + mvc oscillator clock cycles */ |
| 3393 | return 1; |
| 3394 | } |
| 3395 | |
| 3396 | /* MOVE(C) : 0011 1WDD DDD1 t10- xxxx xxxx xxxx xxxx : A-144 */ |
| 3397 | static size_t dsp56k_op_movec_3(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3398 | { |
| 3399 | UINT8 W; |
| 3400 | UINT8 t; |
| 3401 | typed_pointer SD = { NULL, DT_BYTE }; |
| 3402 | |
| 3403 | W = BITS(op,0x0400); |
| 3404 | t = BITS(op,0x0008); |
| 3405 | decode_DDDDD_table(cpustate, BITS(op,0x03e0), &SD); |
| 3406 | |
| 3407 | if (W) |
| 3408 | { |
| 3409 | /* Write D */ |
| 3410 | if (t) |
| 3411 | { |
| 3412 | /* 16-bit long data */ |
| 3413 | typed_pointer temp_src = { (void*)&op2, DT_WORD }; |
| 3414 | SetDestinationValue(temp_src, SD); |
| 3415 | } |
| 3416 | else |
| 3417 | { |
| 3418 | /* 16-bit long address */ |
| 3419 | UINT16 tempD = cpustate->data->read_word(ADDRESS(op2)); |
| 3420 | typed_pointer tempTP = {&tempD, DT_WORD}; |
| 3421 | SetDestinationValue(tempTP, SD); |
| 3422 | } |
| 3423 | } |
| 3424 | else |
| 3425 | { |
| 3426 | /* Read S */ |
| 3427 | if (t) |
| 3428 | { |
| 3429 | /* 16-bit long data */ |
| 3430 | logerror("DSP56k: Movec - I don't think this exists?"); |
| 3431 | } |
| 3432 | else |
| 3433 | { |
| 3434 | /* 16-bit long address */ |
| 3435 | SetDataMemoryValue(cpustate, SD, ADDRESS(op2)); |
| 3436 | } |
| 3437 | } |
| 3438 | |
| 3439 | /* S L E U N Z V C */ |
| 3440 | /* * ? ? ? ? ? ? ? */ |
| 3441 | /* All ? bits - If SR is specified as a destination operand, set according to the corresponding |
| 3442 | bit of the source operand. If SR is not specified as a destination operand, L is set if data |
| 3443 | limiting occurred. All ? bits are not affected otherwise.*/ |
| 3444 | if (W && (SD.addr != &SR)) |
| 3445 | { |
| 3446 | /* If you're writing to something other than the SR */ |
| 3447 | /* TODO */ |
| 3448 | } |
| 3449 | |
| 3450 | cycles += 2; /* TODO: + mvc */ |
| 3451 | return 2; |
| 3452 | } |
| 3453 | |
| 3454 | /* MOVE(C) : 0010 10dd dddD DDDD : A-144 */ |
| 3455 | static size_t dsp56k_op_movec_4(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3456 | { |
| 3457 | typed_pointer S = {NULL, DT_BYTE}; |
| 3458 | typed_pointer D = {NULL, DT_BYTE}; |
| 3459 | |
| 3460 | decode_DDDDD_table(cpustate, BITS(op,0x03e0), &S); |
| 3461 | decode_DDDDD_table(cpustate, BITS(op,0x001f), &D); |
| 3462 | |
| 3463 | SetDestinationValue(S, D); |
| 3464 | |
| 3465 | /* S L E U N Z V C */ |
| 3466 | /* * ? ? ? ? ? ? ? */ |
| 3467 | /* All ? bits - If SR is specified as a destination operand, set according to the corresponding |
| 3468 | bit of the source operand. If SR is not specified as a destination operand, L is set if data |
| 3469 | limiting occurred. All ? bits are not affected otherwise.*/ |
| 3470 | if (D.addr != &SR) |
| 3471 | { |
| 3472 | /* If you're writing to something other than the SR */ |
| 3473 | /* TODO */ |
| 3474 | } |
| 3475 | |
| 3476 | cycles += 2; |
| 3477 | return 1; |
| 3478 | } |
| 3479 | |
| 3480 | /* MOVE(C) : 0000 0101 BBBB BBBB 0011 1WDD DDD0 ---- : A-144 */ |
| 3481 | static size_t dsp56k_op_movec_5(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3482 | { |
| 3483 | INT8 xx; |
| 3484 | UINT8 W; |
| 3485 | UINT16 memOffset; |
| 3486 | typed_pointer SD = { NULL, DT_BYTE }; |
| 3487 | |
| 3488 | xx = (INT8)(op & 0x00ff); |
| 3489 | W = BITS(op2,0x0400); |
| 3490 | decode_DDDDD_table(cpustate, BITS(op2,0x03e0), &SD); |
| 3491 | |
| 3492 | memOffset = R2 + (INT16)xx; |
| 3493 | |
| 3494 | if (W) |
| 3495 | { |
| 3496 | /* Write D */ |
| 3497 | UINT16 tempData = cpustate->data->read_word(ADDRESS(memOffset)); |
| 3498 | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3499 | SetDestinationValue(temp_src, SD); |
| 3500 | } |
| 3501 | else |
| 3502 | { |
| 3503 | /* Read S */ |
| 3504 | UINT16 tempData = *((UINT16*)SD.addr); |
| 3505 | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 3506 | SetDataMemoryValue(cpustate, temp_src, ADDRESS(memOffset)); |
| 3507 | } |
| 3508 | |
| 3509 | /* S L E U N Z V C */ |
| 3510 | /* * ? ? ? ? ? ? ? */ |
| 3511 | /* All ? bits - If SR is specified as a destination operand, set according to the corresponding |
| 3512 | bit of the source operand. If SR is not specified as a destination operand, L is set if data |
| 3513 | limiting occurred. All ? bits are not affected otherwise.*/ |
| 3514 | if (W && (SD.addr != &SR)) |
| 3515 | { |
| 3516 | /* If you're writing to something other than the SR */ |
| 3517 | /* TODO */ |
| 3518 | } |
| 3519 | |
| 3520 | cycles += 2; /* TODO: + mvc oscillator clock cycles */ |
| 3521 | return 2; |
| 3522 | } |
| 3523 | |
| 3524 | /* MOVE(I) : 0010 00DD BBBB BBBB : A-150 */ |
| 3525 | static size_t dsp56k_op_movei(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3526 | { |
| 3527 | typed_pointer D = {NULL, DT_BYTE}; |
| 3528 | typed_pointer immTP = {NULL, DT_BYTE}; |
| 3529 | |
| 3530 | /* Typecasting to INT16 sign-extends the BBBBBBBB operand */ |
| 3531 | UINT16 immediateSignExtended = (INT16)(op & 0x00ff); |
| 3532 | immTP.addr = &immediateSignExtended; |
| 3533 | immTP.data_type = DT_WORD; |
| 3534 | |
| 3535 | decode_DD_table(cpustate, BITS(op,0x0300), &D); |
| 3536 | |
| 3537 | SetDestinationValue(immTP, D); |
| 3538 | |
| 3539 | /* S L E U N Z V C */ |
| 3540 | /* - - - - - - - - */ |
| 3541 | cycles += 2; |
| 3542 | return 1; |
| 3543 | } |
| 3544 | |
| 3545 | /* MOVE(M) : 0000 001W RR0M MHHH : A-152 */ |
| 3546 | static size_t dsp56k_op_movem(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3547 | { |
| 3548 | UINT8 W; |
| 3549 | typed_pointer R = { NULL, DT_BYTE }; |
| 3550 | typed_pointer SD = { NULL, DT_BYTE }; |
| 3551 | |
| 3552 | W = BITS(op,0x0100); |
| 3553 | decode_RR_table(cpustate, BITS(op,0x00c0), &R); |
| 3554 | decode_HHH_table(cpustate, BITS(op,0x0007), &SD); |
| 3555 | |
| 3556 | if (W) |
| 3557 | { |
| 3558 | /* Read from Program Memory */ |
| 3559 | typed_pointer data; |
| 3560 | UINT16 ldata = cpustate->program->read_word(ADDRESS(*((UINT16*)R.addr))); |
| 3561 | |
| 3562 | data.addr = &ldata; |
| 3563 | data.data_type = DT_WORD; |
| 3564 | SetDestinationValue(data, SD) ; |
| 3565 | } |
| 3566 | else |
| 3567 | { |
| 3568 | /* Write to Program Memory */ |
| 3569 | SetProgramMemoryValue(cpustate, SD, ADDRESS(*((UINT16*)R.addr))) ; |
| 3570 | } |
| 3571 | |
| 3572 | execute_MM_table(cpustate, BITS(op,0x00c0), BITS(op,0x0018)); |
| 3573 | |
| 3574 | /* S L E U N Z V C */ |
| 3575 | /* * * - - - - - - */ |
| 3576 | /* TODO: S, L */ |
| 3577 | cycles += 2; /* TODO: + mvm oscillator clock cycles */ |
| 3578 | return 1; |
| 3579 | } |
| 3580 | |
| 3581 | /* MOVE(M) : 0000 001W RR11 mmRR : A-152 */ |
| 3582 | static size_t dsp56k_op_movem_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3583 | { |
| 3584 | /* S L E U N Z V C */ |
| 3585 | /* * * - - - - - - */ |
| 3586 | return 0; |
| 3587 | } |
| 3588 | |
| 3589 | /* MOVE(M) : 0000 0101 BBBB BBBB 0000 001W --0- -HHH : A-152 */ |
| 3590 | static size_t dsp56k_op_movem_2(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2, UINT8* cycles) |
| 3591 | { |
| 3592 | /* S L E U N Z V C */ |
| 3593 | /* * * - - - - - - */ |
| 3594 | return 0; |
| 3595 | } |
| 3596 | |
| 3597 | /* MOVE(P) : 0001 100W HH1p pppp : A-156 */ |
| 3598 | static size_t dsp56k_op_movep(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3599 | { |
| 3600 | UINT16 W; |
| 3601 | UINT16 pp; |
| 3602 | typed_pointer SD = {NULL, DT_BYTE}; |
| 3603 | |
| 3604 | decode_HH_table(cpustate, BITS(op,0x00c0), &SD); |
| 3605 | /* TODO: Special cases for A & B */ |
| 3606 | |
| 3607 | pp = op & 0x001f; |
| 3608 | pp = assemble_address_from_IO_short_address(cpustate, pp); |
| 3609 | |
| 3610 | W = BITS(op,0x0100); |
| 3611 | |
| 3612 | if (W) |
| 3613 | { |
| 3614 | UINT16 data = cpustate->data->read_word(ADDRESS(pp)); |
| 3615 | |
| 3616 | typed_pointer tempTP; |
| 3617 | tempTP.addr = &data; |
| 3618 | tempTP.data_type = DT_WORD; |
| 3619 | |
| 3620 | SetDestinationValue(tempTP, SD); |
| 3621 | } |
| 3622 | else |
| 3623 | { |
| 3624 | SetDataMemoryValue(cpustate, SD, ADDRESS(pp)); |
| 3625 | } |
| 3626 | |
| 3627 | /* S L E U N Z V C */ |
| 3628 | /* * * - - - - - - */ |
| 3629 | /* TODO: S, L */ |
| 3630 | |
| 3631 | cycles += 4; /* TODO: + mvp oscillator cycles */ |
| 3632 | return 1; |
| 3633 | } |
| 3634 | |
| 3635 | /* MOVE(P) : 0000 110W RRmp pppp : A-156 */ |
| 3636 | static size_t dsp56k_op_movep_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3637 | { |
| 3638 | /* X:<Rx> and X:<pp> */ |
| 3639 | UINT16 W; |
| 3640 | UINT16 pp; |
| 3641 | |
| 3642 | typed_pointer SD = {NULL, DT_BYTE}; |
| 3643 | decode_RR_table(cpustate, BITS(op,0x00c0), &SD); |
| 3644 | |
| 3645 | pp = op & 0x001f; |
| 3646 | pp = assemble_address_from_IO_short_address(cpustate, pp); |
| 3647 | |
| 3648 | W = BITS(op,0x0100); |
| 3649 | |
| 3650 | /* A little different than most W if's - opposite read and write */ |
| 3651 | if (W) |
| 3652 | { |
| 3653 | UINT16 data = cpustate->data->read_word(ADDRESS(*((UINT16*)SD.addr))); |
| 3654 | |
| 3655 | typed_pointer tempTP; |
| 3656 | tempTP.addr = &data; |
| 3657 | tempTP.data_type = DT_WORD; |
| 3658 | |
| 3659 | SetDataMemoryValue(cpustate, tempTP, ADDRESS(pp)); |
| 3660 | } |
| 3661 | else |
| 3662 | { |
| 3663 | /* TODO */ |
| 3664 | fatalerror("dsp56k : move(p) NOTHING HERE (yet)\n") ; |
| 3665 | } |
| 3666 | |
| 3667 | /* Postincrement */ |
| 3668 | execute_m_table(cpustate, BITS(op,0x00c0), BITS(op,0x0020)); |
| 3669 | |
| 3670 | /* S L E U N Z V C */ |
| 3671 | /* * * - - - - - - */ |
| 3672 | /* TODO: S, L */ |
| 3673 | cycles += 4; /* TODO: + mvp oscillator cycles */ |
| 3674 | return 1; |
| 3675 | } |
| 3676 | |
| 3677 | /* MOVE(S) : 0001 100W HH0a aaaa : A-158 */ |
| 3678 | static size_t dsp56k_op_moves(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3679 | { |
| 3680 | /* S L E U N Z V C */ |
| 3681 | /* * * - - - - - - */ |
| 3682 | return 0; |
| 3683 | } |
| 3684 | |
| 3685 | /* MPY(su,uu) : 0001 0101 1100 FsQQ : A-164 */ |
| 3686 | static size_t dsp56k_op_mpysuuu(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3687 | { |
| 3688 | UINT8 s = 0; |
| 3689 | INT64 result = 0; |
| 3690 | |
| 3691 | void* D = NULL; |
| 3692 | void* S1 = NULL; |
| 3693 | void* S2 = NULL; |
| 3694 | |
| 3695 | decode_QQF_special_table(cpustate, BITS(op,0x0003), BITS(op,0x0008), &S1, &S2, &D); |
| 3696 | |
| 3697 | s = BITS(op,0x0004); |
| 3698 | |
| 3699 | /* Fixed-point 2's complement multiplication requires a shift */ |
| 3700 | if (s) |
| 3701 | { |
| 3702 | /* Unsigned * Unsigned */ |
| 3703 | UINT32 s1 = (UINT32)(*((UINT16*)S1)); |
| 3704 | UINT32 s2 = (UINT32)(*((UINT16*)S2)); |
| 3705 | result = ( s1 * s2 ) << 1; |
| 3706 | } |
| 3707 | else |
| 3708 | { |
| 3709 | /* Signed * Unsigned */ |
| 3710 | /* WARNING : THERE IS A HUGE CHANCE THIS DOESN'T WORK RIGHT */ |
| 3711 | INT32 s1 = ((INT32)(*((UINT16*)S1))); |
| 3712 | INT32 s2 = (UINT32)(*((UINT16*)S2)); |
| 3713 | result = ( s1 * s2 ) << 1; |
| 3714 | } |
| 3715 | |
| 3716 | (*((UINT64*)D)) = result; |
| 3717 | |
| 3718 | /* And out the bits that don't live in the register */ |
| 3719 | (*((UINT64*)D)) &= U64(0x000000ffffffffff); |
| 3720 | |
| 3721 | /* S L E U N Z V C */ |
| 3722 | /* - * * * * * * - */ |
| 3723 | /* TODO: L, E, U, V */ |
| 3724 | if ( *((UINT64*)D) & U64(0x0000008000000000)) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 3725 | if ((*((UINT64*)D) & U64(0x000000ffffffffff)) == 0) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 3726 | |
| 3727 | cycles += 2; |
| 3728 | return 1; |
| 3729 | } |
| 3730 | |
| 3731 | /* NEGC : 0001 0101 0110 F000 : A-168 */ |
| 3732 | static size_t dsp56k_op_negc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3733 | { |
| 3734 | /* S L E U N Z V C */ |
| 3735 | /* - * * * * * * * */ |
| 3736 | return 0; |
| 3737 | } |
| 3738 | |
| 3739 | /* NOP : 0000 0000 0000 0000 : A-170 */ |
| 3740 | static size_t dsp56k_op_nop(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3741 | { |
| 3742 | /* S L E U N Z V C */ |
| 3743 | /* - - - - - - - - */ |
| 3744 | return 1; |
| 3745 | } |
| 3746 | |
| 3747 | /* NORM : 0001 0101 0010 F0RR : A-172 */ |
| 3748 | static size_t dsp56k_op_norm(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3749 | { |
| 3750 | /* S L E U N Z V C */ |
| 3751 | /* - * * * * * ? - */ |
| 3752 | /* V - Set if an arithmetic overflow occurs in the 40 bit result. Also set if the most significantst |
| 3753 | bit of the destination operand is changed as a result of the left shift. Cleared otherwise. */ |
| 3754 | return 0; |
| 3755 | } |
| 3756 | |
| 3757 | /* ORI : 0001 1EE1 iiii iiii : A-178 */ |
| 3758 | static size_t dsp56k_op_ori(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3759 | { |
| 3760 | /* S L E U N Z V C */ |
| 3761 | /* - ? ? ? ? ? ? ? */ |
| 3762 | /* All ? bits - Set if the corresponding bit in the immediate data is set and if the operand is the |
| 3763 | CCR. Not affected otherwise. */ |
| 3764 | return 0; |
| 3765 | } |
| 3766 | |
| 3767 | /* REP : 0000 0000 111- --RR : A-180 */ |
| 3768 | static size_t dsp56k_op_rep(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3769 | { |
| 3770 | /* S L E U N Z V C */ |
| 3771 | /* - * - - - - - - */ |
| 3772 | return 0; |
| 3773 | } |
| 3774 | |
| 3775 | /* REP : 0000 1111 iiii iiii : A-180 */ |
| 3776 | static size_t dsp56k_op_rep_1(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3777 | { |
| 3778 | /* TODO: This is non-interruptable, probably have to turn off interrupts here */ |
| 3779 | UINT16 iVal = op & 0x00ff; |
| 3780 | |
| 3781 | if (iVal != 0) |
| 3782 | { |
| 3783 | TEMP = LC; |
| 3784 | LC = iVal; |
| 3785 | |
| 3786 | cpustate->repFlag = 1; |
| 3787 | cpustate->repAddr = PC + ADDRESS(1); |
| 3788 | |
| 3789 | cycles += 4; /* TODO: + mv oscillator clock cycles */ |
| 3790 | } |
| 3791 | else |
| 3792 | { |
| 3793 | cycles += 6; /* TODO: + mv oscillator clock cycles */ |
| 3794 | } |
| 3795 | |
| 3796 | |
| 3797 | /* S L E U N Z V C */ |
| 3798 | /* - * - - - - - - */ |
| 3799 | /* TODO: L */ |
| 3800 | return 1; |
| 3801 | } |
| 3802 | |
| 3803 | /* REP : 0000 0100 001D DDDD : A-180 */ |
| 3804 | static size_t dsp56k_op_rep_2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3805 | { |
| 3806 | /* TODO: This is non-interruptable, probably have to turn off interrupts here */ |
| 3807 | UINT16 repValue; |
| 3808 | typed_pointer D = {NULL, DT_BYTE}; |
| 3809 | decode_DDDDD_table(cpustate, BITS(op,0x001f), &D); |
| 3810 | |
| 3811 | /* TODO: handle special A&B source cases */ |
| 3812 | if (D.addr == &A || D.addr == &B) |
| 3813 | logerror("DSP56k ERROR : Rep with A or B instruction not implemented yet!\n"); |
| 3814 | |
| 3815 | repValue = *((UINT16*)D.addr); |
| 3816 | |
| 3817 | if (repValue != 0) |
| 3818 | { |
| 3819 | TEMP = LC; |
| 3820 | LC = repValue; |
| 3821 | |
| 3822 | cpustate->repFlag = 1; |
| 3823 | cpustate->repAddr = PC + ADDRESS(1); |
| 3824 | |
| 3825 | cycles += 4; /* TODO: + mv oscillator clock cycles */ |
| 3826 | } |
| 3827 | else |
| 3828 | { |
| 3829 | cycles += 6; /* TODO: + mv oscillator clock cycles */ |
| 3830 | } |
| 3831 | |
| 3832 | /* S L E U N Z V C */ |
| 3833 | /* - * - - - - - - */ |
| 3834 | /* TODO: L */ |
| 3835 | return 1; |
| 3836 | } |
| 3837 | |
| 3838 | /* REPcc : 0000 0001 0101 cccc : A-184 */ |
| 3839 | static size_t dsp56k_op_repcc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3840 | { |
| 3841 | /* S L E U N Z V C */ |
| 3842 | /* - - - - - - - - */ |
| 3843 | return 0; |
| 3844 | } |
| 3845 | |
| 3846 | /* RESET : 0000 0000 0000 1000 : A-186 */ |
| 3847 | static size_t dsp56k_op_reset(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3848 | { |
| 3849 | /* S L E U N Z V C */ |
| 3850 | /* - - - - - - - - */ |
| 3851 | return 0; |
| 3852 | } |
| 3853 | |
| 3854 | /* RTI : 0000 0000 0000 0111 : A-194 */ |
| 3855 | static size_t dsp56k_op_rti(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3856 | { |
| 3857 | /* WARNING : THERE SHOULD BE A MORE GENERAL HANDLING OF STACK ERRORS. */ |
| 3858 | if (SP == 0) |
| 3859 | { |
| 3860 | dsp56k_add_pending_interrupt(cpustate, "Stack Error"); |
| 3861 | return 0; |
| 3862 | } |
| 3863 | |
| 3864 | cpustate->ppc = PC; |
| 3865 | PC = SSH; |
| 3866 | |
| 3867 | SR = SSL; |
| 3868 | SP = SP - 1; |
| 3869 | |
| 3870 | /* S L E U N Z V C */ |
| 3871 | /* ? ? ? ? ? ? ? ? */ |
| 3872 | /* All ? bits - Set according to value pulled from the stack. */ |
| 3873 | cycles += 4; /* TODO: + rx oscillator clock cycles */ |
| 3874 | return 0; |
| 3875 | } |
| 3876 | |
| 3877 | /* RTS : 0000 0000 0000 0110 : A-196 */ |
| 3878 | static size_t dsp56k_op_rts(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3879 | { |
| 3880 | /* Pop */ |
| 3881 | cpustate->ppc = PC; |
| 3882 | PC = SSH; |
| 3883 | |
| 3884 | /* SR = SSL; The status register is not affected. */ |
| 3885 | |
| 3886 | SP--; |
| 3887 | |
| 3888 | /* S L E U N Z V C */ |
| 3889 | /* - - - - - - - - */ |
| 3890 | cycles += 4; /* TODO: + rx oscillator clock cycles */ |
| 3891 | return 0; |
| 3892 | } |
| 3893 | |
| 3894 | /* STOP : 0000 0000 0000 1010 : A-200 */ |
| 3895 | static size_t dsp56k_op_stop(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3896 | { |
| 3897 | /* S L E U N Z V C */ |
| 3898 | /* - - - - - - - - */ |
| 3899 | return 0; |
| 3900 | } |
| 3901 | |
| 3902 | /* SWAP : 0001 0101 0111 F001 : A-206 */ |
| 3903 | static size_t dsp56k_op_swap(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3904 | { |
| 3905 | /* S L E U N Z V C */ |
| 3906 | /* - - - - - - - - */ |
| 3907 | return 0; |
| 3908 | } |
| 3909 | |
| 3910 | /* SWI : 0000 0000 0000 0101 : A-208 */ |
| 3911 | static size_t dsp56k_op_swi(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3912 | { |
| 3913 | /* S L E U N Z V C */ |
| 3914 | /* - - - - - - - - */ |
| 3915 | return 0; |
| 3916 | } |
| 3917 | |
| 3918 | /* Tcc : 0001 00cc ccTT Fh0h : A-210 */ |
| 3919 | static size_t dsp56k_op_tcc(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3920 | { |
| 3921 | int shouldTransfer = decode_cccc_table(cpustate, BITS(op,0x03c0)); |
| 3922 | |
| 3923 | if (shouldTransfer) |
| 3924 | { |
| 3925 | typed_pointer S = {NULL, DT_BYTE}; |
| 3926 | typed_pointer D = {NULL, DT_BYTE}; |
| 3927 | typed_pointer S2 = {&R0, DT_WORD}; |
| 3928 | typed_pointer D2 = {NULL, DT_BYTE}; |
| 3929 | |
| 3930 | decode_h0hF_table(cpustate, BITS(op,0x0007),BITS(op,0x0008), &S, &D); |
| 3931 | SetDestinationValue(S, D); |
| 3932 | |
| 3933 | /* TODO: What's up with that A,A* thing in the docs? Can you only ignore the R0->RX transfer if you do an A,A? */ |
| 3934 | decode_RR_table(cpustate, BITS(op,0x0030), &D2); /* TT is the same as RR */ |
| 3935 | SetDestinationValue(S2, D2); |
| 3936 | } |
| 3937 | |
| 3938 | /* S L E U N Z V C */ |
| 3939 | /* - - - - - - - - */ |
| 3940 | cycles += 2; |
| 3941 | return 1; |
| 3942 | } |
| 3943 | |
| 3944 | /* TFR(2) : 0001 0101 0000 F00J : A-214 */ |
| 3945 | static size_t dsp56k_op_tfr2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3946 | { |
| 3947 | typed_pointer S = {NULL, DT_BYTE}; |
| 3948 | typed_pointer D = {NULL, DT_BYTE}; |
| 3949 | |
| 3950 | decode_JF_table(cpustate, BITS(op,0x0001), BITS(op,0x0008), &S, &D); |
| 3951 | |
| 3952 | SetDestinationValue(S, D); |
| 3953 | |
| 3954 | /* S L E U N Z V C */ |
| 3955 | /* - * - - - - - - */ |
| 3956 | /* TODO: L */ |
| 3957 | cycles += 2; |
| 3958 | return 1; |
| 3959 | } |
| 3960 | |
| 3961 | /* TFR(3) : 0010 01mW RRDD FHHH : A-216 */ |
| 3962 | static size_t dsp56k_op_tfr3(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3963 | { |
| 3964 | /* S L E U N Z V C */ |
| 3965 | /* * * - - - - - - */ |
| 3966 | return 0; |
| 3967 | } |
| 3968 | |
| 3969 | /* TST(2) : 0001 0101 0001 -1DD : A-220 */ |
| 3970 | static size_t dsp56k_op_tst2(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3971 | { |
| 3972 | typed_pointer D = {NULL, DT_BYTE}; |
| 3973 | decode_DD_table(cpustate, BITS(op,0x0003), &D); |
| 3974 | |
| 3975 | /* S L E U N Z V C */ |
| 3976 | /* - * * * * * 0 0 */ |
| 3977 | /* (L,E,U should be set to 0) */ |
| 3978 | DSP56K_L_CLEAR(); |
| 3979 | DSP56K_E_CLEAR(); |
| 3980 | /* U_CLEAR(); */ /* TODO: Conflicting opinions? "Set if unnormalized." Documentation is weird (A&B?) */ |
| 3981 | if ((*((UINT16*)D.addr)) & 0x8000) DSP56K_N_SET(); else DSP56K_N_CLEAR(); |
| 3982 | if ((*((UINT16*)D.addr)) == 0x0000) DSP56K_Z_SET(); else DSP56K_Z_CLEAR(); |
| 3983 | /* DSP56K_V_CLEAR(); */ /* Unaffected */ |
| 3984 | DSP56K_C_CLEAR(); |
| 3985 | |
| 3986 | cycles += 2; |
| 3987 | return 1; |
| 3988 | } |
| 3989 | |
| 3990 | /* WAIT : 0000 0000 0000 1011 : A-222 */ |
| 3991 | static size_t dsp56k_op_wait(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 3992 | { |
| 3993 | /* S L E U N Z V C */ |
| 3994 | /* - - - - - - - - */ |
| 3995 | return 0; |
| 3996 | } |
| 3997 | |
| 3998 | /* ZERO : 0001 0101 0101 F000 : A-224 */ |
| 3999 | static size_t dsp56k_op_zero(dsp56k_core* cpustate, const UINT16 op, UINT8* cycles) |
| 4000 | { |
| 4001 | /* S L E U N Z V C */ |
| 4002 | /* - * * * * * * - */ |
| 4003 | return 0; |
| 4004 | } |
| 4005 | |
| 4006 | |
| 4007 | |
| 4008 | /*************************************************************************** |
| 4009 | Table decoding |
| 4010 | ***************************************************************************/ |
| 4011 | static UINT16 decode_BBB_bitmask(dsp56k_core* cpustate, UINT16 BBB, UINT16 *iVal) |
| 4012 | { |
| 4013 | UINT16 retVal = 0x0000; |
| 4014 | |
| 4015 | switch(BBB) |
| 4016 | { |
| 4017 | case 0x4: retVal = 0xff00; *iVal <<= 8; break; |
| 4018 | case 0x2: retVal = 0x0ff0; *iVal <<= 4; break; |
| 4019 | case 0x1: retVal = 0x00ff; *iVal <<= 0; break; |
| 4020 | } |
| 4021 | |
| 4022 | return retVal; |
| 4023 | } |
| 4024 | |
| 4025 | static int decode_cccc_table(dsp56k_core* cpustate, UINT16 cccc) |
| 4026 | { |
| 4027 | int retVal = 0; |
| 4028 | |
| 4029 | /* Not fully tested */ |
| 4030 | switch (cccc) |
| 4031 | { |
| 4032 | /* Arranged according to mnemonic table - not decoding table */ |
| 4033 | case 0x0: if( C() == 0) retVal = 1; break; /* cc(hs) */ |
| 4034 | case 0x8: if( C() == 1) retVal = 1; break; /* cs(lo) */ |
| 4035 | case 0x5: if( E() == 0) retVal = 1; break; /* ec */ |
| 4036 | case 0xa: if( Z() == 1) retVal = 1; break; /* eq */ |
| 4037 | case 0xd: if( E() == 1) retVal = 1; break; /* es */ |
| 4038 | case 0x1: if((N() ^ V()) == 0) retVal = 1; break; /* ge */ |
| 4039 | case 0x7: if((Z() | (N() ^ V())) == 0) retVal = 1; break; /* gt */ |
| 4040 | case 0x6: if( L() == 0) retVal = 1; break; /* lc */ |
| 4041 | case 0xf: if((Z() | (N() ^ V())) == 1) retVal = 1; break; /* le */ |
| 4042 | case 0xe: if( L() == 1) retVal = 1; break; /* ls */ |
| 4043 | case 0x9: if((N() ^ V()) == 1) retVal = 1; break; /* lt */ |
| 4044 | case 0xb: if( N() == 1) retVal = 1; break; /* mi */ |
| 4045 | case 0x2: if( Z() == 0) retVal = 1; break; /* ne */ |
| 4046 | case 0xc: if((Z() | ((!U()) & (!E()))) == 1) retVal = 1; break; /* nr */ |
| 4047 | case 0x3: if( N() == 0) retVal = 1; break; /* pl */ |
| 4048 | case 0x4: if((Z() | ((!U()) & (!E()))) == 0) retVal = 1; break; /* nn */ |
| 4049 | } |
| 4050 | |
| 4051 | return retVal; |
| 4052 | } |
| 4053 | |
| 4054 | static void decode_DDDDD_table(dsp56k_core* cpustate, UINT16 DDDDD, typed_pointer* ret) |
| 4055 | { |
| 4056 | switch(DDDDD) |
| 4057 | { |
| 4058 | case 0x00: ret->addr = &X0; ret->data_type = DT_WORD; break; |
| 4059 | case 0x01: ret->addr = &Y0; ret->data_type = DT_WORD; break; |
| 4060 | case 0x02: ret->addr = &X1; ret->data_type = DT_WORD; break; |
| 4061 | case 0x03: ret->addr = &Y1; ret->data_type = DT_WORD; break; |
| 4062 | case 0x04: ret->addr = &A ; ret->data_type = DT_LONG_WORD; break; |
| 4063 | case 0x05: ret->addr = &B ; ret->data_type = DT_LONG_WORD; break; |
| 4064 | case 0x06: ret->addr = &A0; ret->data_type = DT_WORD; break; |
| 4065 | case 0x07: ret->addr = &B0; ret->data_type = DT_WORD; break; |
| 4066 | case 0x08: ret->addr = &LC; ret->data_type = DT_WORD; break; |
| 4067 | case 0x09: ret->addr = &SR; ret->data_type = DT_WORD; break; |
| 4068 | case 0x0a: ret->addr = &OMR; ret->data_type = DT_BYTE; break; |
| 4069 | case 0x0b: ret->addr = &SP; ret->data_type = DT_BYTE; break; |
| 4070 | case 0x0c: ret->addr = &A1; ret->data_type = DT_WORD; break; |
| 4071 | case 0x0d: ret->addr = &B1; ret->data_type = DT_WORD; break; |
| 4072 | case 0x0e: ret->addr = &A2; ret->data_type = DT_BYTE; break; |
| 4073 | case 0x0f: ret->addr = &B2; ret->data_type = DT_BYTE; break; |
| 4074 | |
| 4075 | case 0x10: ret->addr = &R0; ret->data_type = DT_WORD; break; |
| 4076 | case 0x11: ret->addr = &R1; ret->data_type = DT_WORD; break; |
| 4077 | case 0x12: ret->addr = &R2; ret->data_type = DT_WORD; break; |
| 4078 | case 0x13: ret->addr = &R3; ret->data_type = DT_WORD; break; |
| 4079 | case 0x14: ret->addr = &M0; ret->data_type = DT_WORD; break; |
| 4080 | case 0x15: ret->addr = &M1; ret->data_type = DT_WORD; break; |
| 4081 | case 0x16: ret->addr = &M2; ret->data_type = DT_WORD; break; |
| 4082 | case 0x17: ret->addr = &M3; ret->data_type = DT_WORD; break; |
| 4083 | case 0x18: ret->addr = &SSH; ret->data_type = DT_WORD; break; |
| 4084 | case 0x19: ret->addr = &SSL; ret->data_type = DT_WORD; break; |
| 4085 | case 0x1a: ret->addr = &LA; ret->data_type = DT_WORD; break; |
| 4086 | /*no 0x1b */ |
| 4087 | case 0x1c: ret->addr = &N0; ret->data_type = DT_WORD; break; |
| 4088 | case 0x1d: ret->addr = &N1; ret->data_type = DT_WORD; break; |
| 4089 | case 0x1e: ret->addr = &N2; ret->data_type = DT_WORD; break; |
| 4090 | case 0x1f: ret->addr = &N3; ret->data_type = DT_WORD; break; |
| 4091 | } |
| 4092 | } |
| 4093 | |
| 4094 | static void decode_DD_table(dsp56k_core* cpustate, UINT16 DD, typed_pointer* ret) |
| 4095 | { |
| 4096 | switch(DD) |
| 4097 | { |
| 4098 | case 0x00: ret->addr = &X0; ret->data_type = DT_WORD; break; |
| 4099 | case 0x01: ret->addr = &Y0; ret->data_type = DT_WORD; break; |
| 4100 | case 0x02: ret->addr = &X1; ret->data_type = DT_WORD; break; |
| 4101 | case 0x03: ret->addr = &Y1; ret->data_type = DT_WORD; break; |
| 4102 | } |
| 4103 | } |
| 4104 | |
| 4105 | static void decode_DDF_table(dsp56k_core* cpustate, UINT16 DD, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret) |
| 4106 | { |
| 4107 | UINT16 switchVal = (DD << 1) | F; |
| 4108 | |
| 4109 | switch (switchVal) |
| 4110 | { |
| 4111 | case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4112 | case 0x1: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4113 | case 0x2: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4114 | case 0x3: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4115 | case 0x4: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4116 | case 0x5: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4117 | case 0x6: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4118 | case 0x7: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4119 | } |
| 4120 | } |
| 4121 | |
| 4122 | static void decode_F_table(dsp56k_core* cpustate, UINT16 F, typed_pointer* ret) |
| 4123 | { |
| 4124 | switch(F) |
| 4125 | { |
| 4126 | case 0x0: ret->addr = &A; ret->data_type = DT_LONG_WORD; break; |
| 4127 | case 0x1: ret->addr = &B; ret->data_type = DT_LONG_WORD; break; |
| 4128 | } |
| 4129 | } |
| 4130 | |
| 4131 | static void decode_h0hF_table(dsp56k_core* cpustate, UINT16 h0h, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret) |
| 4132 | { |
| 4133 | UINT16 switchVal = (h0h << 1) | F ; |
| 4134 | |
| 4135 | switch (switchVal) |
| 4136 | { |
| 4137 | case 0x8: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4138 | case 0x9: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4139 | case 0xa: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4140 | case 0xb: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4141 | case 0x2: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4142 | case 0x1: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4143 | case 0x0: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4144 | case 0x3: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4145 | } |
| 4146 | } |
| 4147 | |
| 4148 | static void decode_HH_table(dsp56k_core* cpustate, UINT16 HH, typed_pointer* ret) |
| 4149 | { |
| 4150 | switch(HH) |
| 4151 | { |
| 4152 | case 0x0: ret->addr = &X0; ret->data_type = DT_WORD; break; |
| 4153 | case 0x1: ret->addr = &Y0; ret->data_type = DT_WORD; break; |
| 4154 | case 0x2: ret->addr = &A; ret->data_type = DT_LONG_WORD; break; |
| 4155 | case 0x3: ret->addr = &B; ret->data_type = DT_LONG_WORD; break; |
| 4156 | } |
| 4157 | } |
| 4158 | |
| 4159 | static void decode_HHH_table(dsp56k_core* cpustate, UINT16 HHH, typed_pointer* ret) |
| 4160 | { |
| 4161 | switch(HHH) |
| 4162 | { |
| 4163 | case 0x0: ret->addr = &X0; ret->data_type = DT_WORD; break; |
| 4164 | case 0x1: ret->addr = &Y0; ret->data_type = DT_WORD; break; |
| 4165 | case 0x2: ret->addr = &X1; ret->data_type = DT_WORD; break; |
| 4166 | case 0x3: ret->addr = &Y1; ret->data_type = DT_WORD; break; |
| 4167 | case 0x4: ret->addr = &A; ret->data_type = DT_LONG_WORD; break; |
| 4168 | case 0x5: ret->addr = &B; ret->data_type = DT_LONG_WORD; break; |
| 4169 | case 0x6: ret->addr = &A0; ret->data_type = DT_WORD; break; |
| 4170 | case 0x7: ret->addr = &B0; ret->data_type = DT_WORD; break; |
| 4171 | } |
| 4172 | } |
| 4173 | |
| 4174 | static void decode_IIII_table(dsp56k_core* cpustate, UINT16 IIII, typed_pointer* src_ret, typed_pointer* dst_ret, void *working) |
| 4175 | { |
| 4176 | void *opposite = 0x00 ; |
| 4177 | |
| 4178 | if (working == &A) opposite = &B ; |
| 4179 | else opposite = &A ; |
| 4180 | |
| 4181 | switch(IIII) |
| 4182 | { |
| 4183 | case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; |
| 4184 | case 0x1: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; |
| 4185 | case 0x2: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; |
| 4186 | case 0x3: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; |
| 4187 | case 0x4: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X0; dst_ret->data_type = DT_WORD; break; |
| 4188 | case 0x5: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y0; dst_ret->data_type = DT_WORD; break; |
| 4189 | case 0x6: src_ret->addr = &A0; src_ret->data_type = DT_WORD; dst_ret->addr = &X0; dst_ret->data_type = DT_WORD; break; |
| 4190 | case 0x7: src_ret->addr = &B0; src_ret->data_type = DT_WORD; dst_ret->addr = &Y0; dst_ret->data_type = DT_WORD; break; |
| 4191 | case 0x8: src_ret->addr = working; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; |
| 4192 | case 0x9: src_ret->addr = working; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = opposite; dst_ret->data_type = DT_LONG_WORD; break; |
| 4193 | case 0xc: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X1; dst_ret->data_type = DT_WORD; break; |
| 4194 | case 0xd: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y1; dst_ret->data_type = DT_WORD; break; |
| 4195 | case 0xe: src_ret->addr = &A0; src_ret->data_type = DT_WORD; dst_ret->addr = &X1; dst_ret->data_type = DT_WORD; break; |
| 4196 | case 0xf: src_ret->addr = &B0; src_ret->data_type = DT_WORD; dst_ret->addr = &Y1; dst_ret->data_type = DT_WORD; break; |
| 4197 | } |
| 4198 | } |
| 4199 | |
| 4200 | static void decode_JJJF_table(dsp56k_core* cpustate, UINT16 JJJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret) |
| 4201 | { |
| 4202 | UINT16 switchVal = (JJJ << 1) | F ; |
| 4203 | |
| 4204 | switch(switchVal) |
| 4205 | { |
| 4206 | case 0x0: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4207 | case 0x1: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4208 | case 0x4: src_ret->addr = &X; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4209 | case 0x5: src_ret->addr = &X; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4210 | case 0x6: src_ret->addr = &Y; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4211 | case 0x7: src_ret->addr = &Y; src_ret->data_type = DT_DOUBLE_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4212 | case 0x8: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4213 | case 0x9: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4214 | case 0xa: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4215 | case 0xb: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4216 | case 0xc: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4217 | case 0xd: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4218 | case 0xe: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4219 | case 0xf: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4220 | } |
| 4221 | } |
| 4222 | |
| 4223 | static void decode_JJF_table(dsp56k_core* cpustate, UINT16 JJ, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret) |
| 4224 | { |
| 4225 | UINT16 switchVal = (JJ << 1) | F ; |
| 4226 | |
| 4227 | switch (switchVal) |
| 4228 | { |
| 4229 | case 0x0: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4230 | case 0x1: src_ret->addr = &X0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4231 | case 0x2: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4232 | case 0x3: src_ret->addr = &Y0; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4233 | case 0x4: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4234 | case 0x5: src_ret->addr = &X1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4235 | case 0x6: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4236 | case 0x7: src_ret->addr = &Y1; src_ret->data_type = DT_WORD; dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4237 | } |
| 4238 | } |
| 4239 | |
| 4240 | static void decode_JF_table(dsp56k_core* cpustate, UINT16 J, UINT16 F, typed_pointer* src_ret, typed_pointer* dst_ret) |
| 4241 | { |
| 4242 | UINT16 switchVal = (J << 1) | F ; |
| 4243 | |
| 4244 | switch (switchVal) |
| 4245 | { |
| 4246 | case 0x0: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X; dst_ret->data_type = DT_DOUBLE_WORD; break; |
| 4247 | case 0x1: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &X; dst_ret->data_type = DT_DOUBLE_WORD; break; |
| 4248 | case 0x2: src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y; dst_ret->data_type = DT_DOUBLE_WORD; break; |
| 4249 | case 0x3: src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; dst_ret->addr = &Y; dst_ret->data_type = DT_DOUBLE_WORD; break; |
| 4250 | } |
| 4251 | } |
| 4252 | |
| 4253 | static void decode_KKK_table(dsp56k_core* cpustate, UINT16 KKK, typed_pointer* dst_ret1, typed_pointer* dst_ret2, void* working) |
| 4254 | { |
| 4255 | void *opposite = 0x00 ; |
| 4256 | |
| 4257 | if (working == &A) opposite = &B ; |
| 4258 | else opposite = &A ; |
| 4259 | |
| 4260 | switch(KKK) |
| 4261 | { |
| 4262 | case 0x0: dst_ret1->addr = opposite; dst_ret1->data_type = DT_LONG_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break; |
| 4263 | case 0x1: dst_ret1->addr = &Y0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break; |
| 4264 | case 0x2: dst_ret1->addr = &X1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break; |
| 4265 | case 0x3: dst_ret1->addr = &Y1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X0; dst_ret2->data_type = DT_WORD; break; |
| 4266 | case 0x4: dst_ret1->addr = &X0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break; |
| 4267 | case 0x5: dst_ret1->addr = &Y0; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break; |
| 4268 | case 0x6: dst_ret1->addr = opposite; dst_ret1->data_type = DT_LONG_WORD; dst_ret2->addr = &Y0; dst_ret2->data_type = DT_WORD; break; |
| 4269 | case 0x7: dst_ret1->addr = &Y1; dst_ret1->data_type = DT_WORD; dst_ret2->addr = &X1; dst_ret2->data_type = DT_WORD; break; |
| 4270 | } |
| 4271 | } |
| 4272 | |
| 4273 | static void decode_QQF_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D) |
| 4274 | { |
| 4275 | UINT16 switchVal = (QQ << 1) | F ; |
| 4276 | |
| 4277 | switch(switchVal) |
| 4278 | { |
| 4279 | case 0x0: *S1 = &X0; *S2 = &Y0; *D = &A; break; |
| 4280 | case 0x1: *S1 = &X0; *S2 = &Y0; *D = &B; break; |
| 4281 | case 0x2: *S1 = &X0; *S2 = &Y1; *D = &A; break; |
| 4282 | case 0x3: *S1 = &X0; *S2 = &Y1; *D = &B; break; |
| 4283 | case 0x4: *S1 = &X1; *S2 = &Y0; *D = &A; break; |
| 4284 | case 0x5: *S1 = &X1; *S2 = &Y0; *D = &B; break; |
| 4285 | case 0x6: *S1 = &X1; *S2 = &Y1; *D = &A; break; |
| 4286 | case 0x7: *S1 = &X1; *S2 = &Y1; *D = &B; break; |
| 4287 | } |
| 4288 | } |
| 4289 | |
| 4290 | static void decode_QQF_special_table(dsp56k_core* cpustate, UINT16 QQ, UINT16 F, void **S1, void **S2, void **D) |
| 4291 | { |
| 4292 | UINT16 switchVal = (QQ << 1) | F ; |
| 4293 | |
| 4294 | switch(switchVal) |
| 4295 | { |
| 4296 | case 0x0: *S1 = &Y0; *S2 = &X0; *D = &A; break; |
| 4297 | case 0x1: *S1 = &Y0; *S2 = &X0; *D = &B; break; |
| 4298 | case 0x2: *S1 = &Y1; *S2 = &X0; *D = &A; break; |
| 4299 | case 0x3: *S1 = &Y1; *S2 = &X0; *D = &B; break; |
| 4300 | case 0x4: *S1 = &X1; *S2 = &Y0; *D = &A; break; |
| 4301 | case 0x5: *S1 = &X1; *S2 = &Y0; *D = &B; break; |
| 4302 | case 0x6: *S1 = &X1; *S2 = &Y1; *D = &A; break; |
| 4303 | case 0x7: *S1 = &X1; *S2 = &Y1; *D = &B; break; |
| 4304 | } |
| 4305 | } |
| 4306 | |
| 4307 | static void decode_QQQF_table(dsp56k_core* cpustate, UINT16 QQQ, UINT16 F, void **S1, void **S2, void **D) |
| 4308 | { |
| 4309 | UINT16 switchVal = (QQQ << 1) | F; |
| 4310 | |
| 4311 | switch(switchVal) |
| 4312 | { |
| 4313 | case 0x0: *S1 = &X0; *S2 = &X0; *D = &A; break; |
| 4314 | case 0x1: *S1 = &X0; *S2 = &X0; *D = &B; break; |
| 4315 | case 0x2: *S1 = &X1; *S2 = &X0; *D = &A; break; |
| 4316 | case 0x3: *S1 = &X1; *S2 = &X0; *D = &B; break; |
| 4317 | case 0x4: *S1 = &A1; *S2 = &Y0; *D = &A; break; |
| 4318 | case 0x5: *S1 = &A1; *S2 = &Y0; *D = &B; break; |
| 4319 | case 0x6: *S1 = &B1; *S2 = &X0; *D = &A; break; |
| 4320 | case 0x7: *S1 = &B1; *S2 = &X0; *D = &B; break; |
| 4321 | case 0x8: *S1 = &Y0; *S2 = &X0; *D = &A; break; |
| 4322 | case 0x9: *S1 = &Y0; *S2 = &X0; *D = &B; break; |
| 4323 | case 0xa: *S1 = &Y1; *S2 = &X0; *D = &A; break; |
| 4324 | case 0xb: *S1 = &Y1; *S2 = &X0; *D = &B; break; |
| 4325 | case 0xc: *S1 = &Y0; *S2 = &X1; *D = &A; break; |
| 4326 | case 0xd: *S1 = &Y0; *S2 = &X1; *D = &B; break; |
| 4327 | case 0xe: *S1 = &Y1; *S2 = &X1; *D = &A; break; |
| 4328 | case 0xf: *S1 = &Y1; *S2 = &X1; *D = &B; break; |
| 4329 | } |
| 4330 | } |
| 4331 | |
| 4332 | static void decode_RR_table(dsp56k_core* cpustate, UINT16 RR, typed_pointer* ret) |
| 4333 | { |
| 4334 | switch(RR) |
| 4335 | { |
| 4336 | case 0x00: ret->addr = &R0; ret->data_type = DT_WORD; break; |
| 4337 | case 0x01: ret->addr = &R1; ret->data_type = DT_WORD; break; |
| 4338 | case 0x02: ret->addr = &R2; ret->data_type = DT_WORD; break; |
| 4339 | case 0x03: ret->addr = &R3; ret->data_type = DT_WORD; break; |
| 4340 | } |
| 4341 | } |
| 4342 | |
| 4343 | static void decode_TT_table(dsp56k_core* cpustate, UINT16 TT, typed_pointer* ret) |
| 4344 | { |
| 4345 | switch(TT) |
| 4346 | { |
| 4347 | case 0x00: ret->addr = &R0; ret->data_type = DT_WORD; break; |
| 4348 | case 0x01: ret->addr = &R1; ret->data_type = DT_WORD; break; |
| 4349 | case 0x02: ret->addr = &R2; ret->data_type = DT_WORD; break; |
| 4350 | case 0x03: ret->addr = &R3; ret->data_type = DT_WORD; break; |
| 4351 | } |
| 4352 | } |
| 4353 | |
| 4354 | |
| 4355 | static void decode_uuuuF_table(dsp56k_core* cpustate, UINT16 uuuu, UINT16 F, UINT8 add_sub_other, typed_pointer* src_ret, typed_pointer* dst_ret) |
| 4356 | { |
| 4357 | UINT16 switchVal = (uuuu << 1) | F; |
| 4358 | |
| 4359 | /* Unknown uuuuFs have been seen in the wild */ |
| 4360 | add_sub_other = OP_OTHER; |
| 4361 | src_ret->addr = NULL; src_ret->data_type = DT_BYTE; |
| 4362 | dst_ret->addr = NULL; dst_ret->data_type = DT_BYTE; |
| 4363 | |
| 4364 | switch(switchVal) |
| 4365 | { |
| 4366 | case 0x00: add_sub_other = OP_ADD; |
| 4367 | src_ret->addr = &X0; src_ret->data_type = DT_WORD; |
| 4368 | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4369 | case 0x08: add_sub_other = OP_SUB; |
| 4370 | src_ret->addr = &X0; src_ret->data_type = DT_WORD; |
| 4371 | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4372 | case 0x01: add_sub_other = OP_ADD; |
| 4373 | src_ret->addr = &X0; src_ret->data_type = DT_WORD; |
| 4374 | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4375 | case 0x09: add_sub_other = OP_SUB; |
| 4376 | src_ret->addr = &X0; src_ret->data_type = DT_WORD; |
| 4377 | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4378 | case 0x02: add_sub_other = OP_ADD; |
| 4379 | src_ret->addr = &Y0; src_ret->data_type = DT_WORD; |
| 4380 | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4381 | case 0x0a: add_sub_other = OP_SUB; |
| 4382 | src_ret->addr = &Y0; src_ret->data_type = DT_WORD; |
| 4383 | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4384 | case 0x03: add_sub_other = OP_ADD; |
| 4385 | src_ret->addr = &Y0; src_ret->data_type = DT_WORD; |
| 4386 | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4387 | case 0x0b: add_sub_other = OP_SUB; |
| 4388 | src_ret->addr = &Y0; src_ret->data_type = DT_WORD; |
| 4389 | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4390 | case 0x04: add_sub_other = OP_ADD; |
| 4391 | src_ret->addr = &X1; src_ret->data_type = DT_WORD; |
| 4392 | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4393 | case 0x0c: add_sub_other = OP_SUB; |
| 4394 | src_ret->addr = &X1; src_ret->data_type = DT_WORD; |
| 4395 | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4396 | case 0x05: add_sub_other = OP_ADD; |
| 4397 | src_ret->addr = &X1; src_ret->data_type = DT_WORD; |
| 4398 | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4399 | case 0x0d: add_sub_other = OP_SUB; |
| 4400 | src_ret->addr = &X1; src_ret->data_type = DT_WORD; |
| 4401 | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4402 | case 0x06: add_sub_other = OP_ADD; |
| 4403 | src_ret->addr = &Y1; src_ret->data_type = DT_WORD; |
| 4404 | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4405 | case 0x0e: add_sub_other = OP_SUB; |
| 4406 | src_ret->addr = &Y1; src_ret->data_type = DT_WORD; |
| 4407 | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4408 | case 0x07: add_sub_other = OP_ADD; |
| 4409 | src_ret->addr = &Y1; src_ret->data_type = DT_WORD; |
| 4410 | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4411 | case 0x0f: add_sub_other = OP_SUB; |
| 4412 | src_ret->addr = &Y1; src_ret->data_type = DT_WORD; |
| 4413 | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4414 | case 0x18: add_sub_other = OP_ADD; |
| 4415 | src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; |
| 4416 | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4417 | case 0x1a: add_sub_other = OP_SUB; |
| 4418 | src_ret->addr = &B; src_ret->data_type = DT_LONG_WORD; |
| 4419 | dst_ret->addr = &A; dst_ret->data_type = DT_LONG_WORD; break; |
| 4420 | case 0x19: add_sub_other = OP_ADD; |
| 4421 | src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; |
| 4422 | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4423 | case 0x1b: add_sub_other = OP_SUB; |
| 4424 | src_ret->addr = &A; src_ret->data_type = DT_LONG_WORD; |
| 4425 | dst_ret->addr = &B; dst_ret->data_type = DT_LONG_WORD; break; |
| 4426 | } |
| 4427 | } |
| 4428 | |
| 4429 | static void decode_Z_table(dsp56k_core* cpustate, UINT16 Z, typed_pointer* ret) |
| 4430 | { |
| 4431 | switch(Z) |
| 4432 | { |
| 4433 | /* Fixed as per the Family Manual addendum */ |
| 4434 | case 0x01: ret->addr = &A1; ret->data_type = DT_WORD; break; |
| 4435 | case 0x00: ret->addr = &B1; ret->data_type = DT_WORD; break; |
| 4436 | } |
| 4437 | } |
| 4438 | |
| 4439 | static void execute_m_table(dsp56k_core* cpustate, int x, UINT16 m) |
| 4440 | { |
| 4441 | UINT16 *rX = 0x00 ; |
| 4442 | UINT16 *nX = 0x00 ; |
| 4443 | |
| 4444 | switch(x) |
| 4445 | { |
| 4446 | case 0x0: rX = &R0; nX = &N0; break; |
| 4447 | case 0x1: rX = &R1; nX = &N1; break; |
| 4448 | case 0x2: rX = &R2; nX = &N2; break; |
| 4449 | case 0x3: rX = &R3; nX = &N3; break; |
| 4450 | } |
| 4451 | |
| 4452 | switch(m) |
| 4453 | { |
| 4454 | case 0x0: (*rX)++; break; |
| 4455 | case 0x1: (*rX) = (*rX)+(*nX); break; |
| 4456 | } |
| 4457 | } |
| 4458 | |
| 4459 | static void execute_mm_table(dsp56k_core* cpustate, UINT16 rnum, UINT16 mm) |
| 4460 | { |
| 4461 | UINT16 *rX = NULL; |
| 4462 | UINT16 *nX = NULL; |
| 4463 | |
| 4464 | switch(rnum) |
| 4465 | { |
| 4466 | case 0x0: rX = &R0; nX = &N0; break; |
| 4467 | case 0x1: rX = &R1; nX = &N1; break; |
| 4468 | case 0x2: rX = &R2; nX = &N2; break; |
| 4469 | case 0x3: fatalerror("Dsp56k: Error. execute_mm_table specified R3 as its first source!\n"); break; |
| 4470 | } |
| 4471 | |
| 4472 | switch(mm) |
| 4473 | { |
| 4474 | case 0x0: (*rX)++; R3++; break; |
| 4475 | case 0x1: (*rX)++; R3 = R3 + N3; break; |
| 4476 | case 0x2: (*rX) = (*rX) + (*nX); R3++; break; |
| 4477 | case 0x3: (*rX) = (*rX) + (*nX); R3 = R3 + N3; break; |
| 4478 | } |
| 4479 | } |
| 4480 | |
| 4481 | static void execute_MM_table(dsp56k_core* cpustate, UINT16 rnum, UINT16 MM) |
| 4482 | { |
| 4483 | UINT16 *rX = 0x00 ; |
| 4484 | UINT16 *nX = 0x00 ; |
| 4485 | |
| 4486 | switch(rnum) |
| 4487 | { |
| 4488 | case 0x0: rX = &R0; nX = &N0; break; |
| 4489 | case 0x1: rX = &R1; nX = &N1; break; |
| 4490 | case 0x2: rX = &R2; nX = &N2; break; |
| 4491 | case 0x3: rX = &R3; nX = &N3; break; |
| 4492 | } |
| 4493 | |
| 4494 | switch(MM) |
| 4495 | { |
| 4496 | case 0x0: /* do nothing */ break; |
| 4497 | case 0x1: (*rX)++ ; break; |
| 4498 | case 0x2: (*rX)-- ; break; |
| 4499 | case 0x3: (*rX) = (*rX)+(*nX) ; break; |
| 4500 | } |
| 4501 | } |
| 4502 | |
| 4503 | /* Returns R value */ |
| 4504 | static UINT16 execute_q_table(dsp56k_core* cpustate, int RR, UINT16 q) |
| 4505 | { |
| 4506 | UINT16 *rX = 0x0000; |
| 4507 | UINT16 *nX = 0x0000; |
| 4508 | |
| 4509 | switch(RR) |
| 4510 | { |
| 4511 | case 0x0: rX = &R0; nX = &N0; break; |
| 4512 | case 0x1: rX = &R1; nX = &N1; break; |
| 4513 | case 0x2: rX = &R2; nX = &N2; break; |
| 4514 | case 0x3: rX = &R3; nX = &N3; break; |
| 4515 | } |
| 4516 | |
| 4517 | switch(q) |
| 4518 | { |
| 4519 | case 0x0: /* No permanent changes */ ; return (*rX)+(*nX); |
| 4520 | case 0x1: (*rX)--; return (*rX); /* This one is special - it's a *PRE-decrement*! */ |
| 4521 | } |
| 4522 | |
| 4523 | /* Should not get here */ |
| 4524 | fatalerror("dsp56k: execute_q_table did something impossible!\n"); |
| 4525 | return 0; |
| 4526 | } |
| 4527 | |
| 4528 | static void execute_z_table(dsp56k_core* cpustate, int RR, UINT16 z) |
| 4529 | { |
| 4530 | UINT16 *rX = 0x00; |
| 4531 | UINT16 *nX = 0x00; |
| 4532 | |
| 4533 | switch(RR) |
| 4534 | { |
| 4535 | case 0x0: rX = &R0; nX = &N0; break; |
| 4536 | case 0x1: rX = &R1; nX = &N1; break; |
| 4537 | case 0x2: rX = &R2; nX = &N2; break; |
| 4538 | case 0x3: rX = &R3; nX = &N3; break; |
| 4539 | } |
| 4540 | |
| 4541 | switch(z) |
| 4542 | { |
| 4543 | case 0x0: (*rX)--; break; |
| 4544 | case 0x1: (*rX) = (*rX) + (*nX); break; |
| 4545 | } |
| 4546 | } |
| 4547 | |
| 4548 | static UINT16 assemble_address_from_Pppppp_table(dsp56k_core* cpustate, UINT16 P, UINT16 ppppp) |
| 4549 | { |
| 4550 | UINT16 destAddr = 0x00 ; |
| 4551 | |
| 4552 | switch (P) |
| 4553 | { |
| 4554 | case 0x0: destAddr = ppppp; break; /* TODO: Does this really only address up to 0x32? */ |
| 4555 | case 0x1: destAddr = assemble_address_from_IO_short_address(cpustate, ppppp); break; |
| 4556 | } |
| 4557 | |
| 4558 | return destAddr ; |
| 4559 | } |
| 4560 | |
| 4561 | static UINT16 assemble_address_from_IO_short_address(dsp56k_core* cpustate, UINT16 pp) |
| 4562 | { |
| 4563 | UINT16 fullAddy = 0xffe0; |
| 4564 | fullAddy |= pp; |
| 4565 | return fullAddy; |
| 4566 | } |
| 4567 | |
| 4568 | static UINT16 assemble_address_from_6bit_signed_relative_short_address(dsp56k_core* cpustate, UINT16 srs) |
| 4569 | { |
| 4570 | UINT16 fullAddy = srs ; |
| 4571 | if (fullAddy & 0x0020) |
| 4572 | fullAddy |= 0xffc0 ; |
| 4573 | |
| 4574 | return fullAddy ; |
| 4575 | } |
| 4576 | |
| 4577 | static void dsp56k_process_loop(dsp56k_core* cpustate) |
| 4578 | { |
| 4579 | /* TODO: This might not work for dos nested in doForevers */ |
| 4580 | if (LF_bit(cpustate) && FV_bit(cpustate)) |
| 4581 | { |
| 4582 | /* Do Forever*/ |
| 4583 | if (PC == LA) |
| 4584 | { |
| 4585 | LC--; |
| 4586 | |
| 4587 | cpustate->ppc = PC; |
| 4588 | PC = SSH; |
| 4589 | } |
| 4590 | } |
| 4591 | else if (LF_bit(cpustate)) |
| 4592 | { |
| 4593 | /* Do */ |
| 4594 | if (PC == LA) |
| 4595 | { |
| 4596 | if (LC == 1) |
| 4597 | { |
| 4598 | /* End of loop processing */ |
| 4599 | SR = SSL; /* TODO: A-83. I believe only the Loop Flag comes back here. And maybe the do forever bit too. */ |
| 4600 | SP--; |
| 4601 | |
| 4602 | LA = SSH; |
| 4603 | LC = SSL; |
| 4604 | SP--; |
| 4605 | } |
| 4606 | else |
| 4607 | { |
| 4608 | LC--; |
| 4609 | PC = SSH; |
| 4610 | } |
| 4611 | } |
| 4612 | } |
| 4613 | } |
| 4614 | |
| 4615 | static void dsp56k_process_rep(dsp56k_core* cpustate, size_t repSize) |
| 4616 | { |
| 4617 | if (cpustate->repFlag) |
| 4618 | { |
| 4619 | if (PC == cpustate->repAddr) |
| 4620 | { |
| 4621 | if (LC == 1) |
| 4622 | { |
| 4623 | /* End of rep processing */ |
| 4624 | LC = TEMP; |
| 4625 | cpustate->repFlag = 0; |
| 4626 | cpustate->repAddr = 0x0000; |
| 4627 | } |
| 4628 | else |
| 4629 | { |
| 4630 | LC--; |
| 4631 | PC -= repSize; /* A little strange - rewind by the size of the rep'd op */ |
| 4632 | } |
| 4633 | } |
| 4634 | } |
| 4635 | } |
| 4636 | |
| 4637 | |
| 4638 | /*************************************************************************** |
| 4639 | Parallel Memory Ops |
| 4640 | ***************************************************************************/ |
| 4641 | /* Register to Register Data Move : 0100 IIII .... .... : A-132 */ |
| 4642 | static void execute_register_to_register_data_move(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value) |
| 4643 | { |
| 4644 | typed_pointer S = {NULL, DT_BYTE}; |
| 4645 | typed_pointer D = {NULL, DT_BYTE}; |
| 4646 | |
| 4647 | decode_IIII_table(cpustate, BITS(op,0x0f00), &S, &D, d_register->addr); |
| 4648 | |
| 4649 | /* If the source is the same as the ALU destination, use the previous accumulator value */ |
| 4650 | if (d_register->addr == S.addr) |
| 4651 | { |
| 4652 | typed_pointer tempTP; |
| 4653 | tempTP.addr = prev_accum_value; |
| 4654 | tempTP.data_type = DT_LONG_WORD; |
| 4655 | SetDestinationValue(tempTP, D); |
| 4656 | } |
| 4657 | else |
| 4658 | { |
| 4659 | SetDestinationValue(S, D); |
| 4660 | } |
| 4661 | } |
| 4662 | |
| 4663 | /* Address Register Update : 0011 0zRR .... .... : A-135 */ |
| 4664 | static void execute_address_register_update(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value) |
| 4665 | { |
| 4666 | execute_z_table(cpustate, BITS(op,0x0300), BITS(op,0x0400)); |
| 4667 | } |
| 4668 | |
| 4669 | /* X Memory Data Move : 1mRR HHHW .... .... : A-137 */ |
| 4670 | static void execute_x_memory_data_move(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register, UINT64* prev_accum_value) |
| 4671 | { |
| 4672 | UINT16 W; |
| 4673 | typed_pointer R = {NULL, DT_BYTE}; |
| 4674 | typed_pointer SD = {NULL, DT_BYTE}; |
| 4675 | |
| 4676 | W = BITS(op,0x0100); |
| 4677 | decode_HHH_table(cpustate, BITS(op,0x0e00), &SD); |
| 4678 | decode_RR_table(cpustate, BITS(op,0x3000),&R); |
| 4679 | |
| 4680 | if (W) |
| 4681 | { |
| 4682 | /* From X:<ea> to SD */ |
| 4683 | UINT16 data = cpustate->data->read_word(ADDRESS(*((UINT16*)R.addr))); |
| 4684 | |
| 4685 | typed_pointer tempTP; |
| 4686 | tempTP.addr = &data; |
| 4687 | tempTP.data_type = DT_WORD; |
| 4688 | |
| 4689 | SetDestinationValue(tempTP, SD); |
| 4690 | } |
| 4691 | else |
| 4692 | { |
| 4693 | /* From SD to X:<ea> */ |
| 4694 | /* If the source is the same as the ALU destination, use the previous accumulator value */ |
| 4695 | if (d_register->addr == SD.addr) |
| 4696 | { |
| 4697 | typed_pointer tempTP; |
| 4698 | tempTP.addr = prev_accum_value; |
| 4699 | tempTP.data_type = DT_LONG_WORD; |
| 4700 | |
| 4701 | SetDataMemoryValue(cpustate, tempTP, ADDRESS(*((UINT16*)R.addr))) ; |
| 4702 | } |
| 4703 | else |
| 4704 | { |
| 4705 | SetDataMemoryValue(cpustate, SD, ADDRESS(*((UINT16*)R.addr))) ; |
| 4706 | } |
| 4707 | } |
| 4708 | |
| 4709 | execute_m_table(cpustate, BITS(op,0x3000), BITS(op,0x4000)); |
| 4710 | } |
| 4711 | |
| 4712 | /* X Memory Data Move : 0101 HHHW .... .... : A-137 */ |
| 4713 | /* NOTE: previous accumulator value is not needed since ^F1 is always the opposite accumulator */ |
| 4714 | static void execute_x_memory_data_move2(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register) |
| 4715 | { |
| 4716 | UINT16 W; |
| 4717 | UINT16* mem_offset = NULL; |
| 4718 | typed_pointer SD = {NULL, DT_BYTE}; |
| 4719 | |
| 4720 | W = BITS(op,0x0100); |
| 4721 | decode_HHH_table(cpustate, BITS(op,0x0e000), &SD); |
| 4722 | |
| 4723 | if (d_register->addr == &A) |
| 4724 | mem_offset = &B1; |
| 4725 | else |
| 4726 | mem_offset = &A1; |
| 4727 | |
| 4728 | if (W) |
| 4729 | { |
| 4730 | /* Write D */ |
| 4731 | UINT16 value = cpustate->data->read_word(ADDRESS(*mem_offset)); |
| 4732 | typed_pointer tempV = {&value, DT_WORD}; |
| 4733 | SetDestinationValue(tempV, SD); |
| 4734 | } |
| 4735 | else |
| 4736 | { |
| 4737 | /* Read S */ |
| 4738 | SetDataMemoryValue(cpustate, SD, ADDRESS(*mem_offset)); |
| 4739 | } |
| 4740 | } |
| 4741 | |
| 4742 | /* X Memory Data Move With Short Displacement : 0000 0101 BBBB BBBB ---- HHHW .... .... : A-139 */ |
| 4743 | static void execute_x_memory_data_move_with_short_displacement(dsp56k_core* cpustate, const UINT16 op, const UINT16 op2) |
| 4744 | { |
| 4745 | INT8 xx; |
| 4746 | UINT8 W; |
| 4747 | UINT16 memOffset; |
| 4748 | typed_pointer SD = { NULL, DT_BYTE }; |
| 4749 | |
| 4750 | xx = (INT8)(op & 0x00ff); |
| 4751 | W = BITS(op2,0x0100); |
| 4752 | decode_HHH_table(cpustate, BITS(op2,0x0e00), &SD); |
| 4753 | |
| 4754 | memOffset = R2 + (INT16)xx; |
| 4755 | |
| 4756 | if (W) |
| 4757 | { |
| 4758 | /* Write D */ |
| 4759 | UINT16 tempData = cpustate->data->read_word(ADDRESS(memOffset)); |
| 4760 | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 4761 | SetDestinationValue(temp_src, SD); |
| 4762 | } |
| 4763 | else |
| 4764 | { |
| 4765 | /* Read S */ |
| 4766 | UINT16 tempData = *((UINT16*)SD.addr); |
| 4767 | typed_pointer temp_src = { (void*)&tempData, DT_WORD }; |
| 4768 | SetDataMemoryValue(cpustate, temp_src, ADDRESS(memOffset)); |
| 4769 | } |
| 4770 | } |
| 4771 | |
| 4772 | /* Dual X Memory Data Read : 011m mKKK .rr. .... : A-142*/ |
| 4773 | static void execute_dual_x_memory_data_read(dsp56k_core* cpustate, const UINT16 op, typed_pointer* d_register) |
| 4774 | { |
| 4775 | typed_pointer tempV; |
| 4776 | UINT16 srcVal1 = 0x0000; |
| 4777 | UINT16 srcVal2 = 0x0000; |
| 4778 | typed_pointer R = {NULL, DT_BYTE}; |
| 4779 | typed_pointer D1 = {NULL, DT_BYTE}; |
| 4780 | typed_pointer D2 = {NULL, DT_BYTE}; |
| 4781 | |
| 4782 | decode_RR_table(cpustate, BITS(op,0x0060), &R); |
| 4783 | decode_KKK_table(cpustate, BITS(op,0x0700), &D1, &D2, d_register->addr); |
| 4784 | |
| 4785 | /* Can't do an R3 for S1 */ |
| 4786 | if (R.addr == &R3) |
| 4787 | fatalerror("Dsp56k: Error. Dual x memory data read specified R3 as its first source!\n"); |
| 4788 | |
| 4789 | /* The note on A-142 is very interesting. |
| 4790 | You can effectively access external memory in the last 64 bytes of X data memory! */ |
| 4791 | if (*((UINT16*)D2.addr) >= 0xffc0) |
| 4792 | fatalerror("Dsp56k: Unimplemented access to external X Data Memory >= 0xffc0 in Dual X Memory Data Read.\n"); |
| 4793 | |
| 4794 | /* First memmove */ |
| 4795 | srcVal1 = cpustate->data->read_word(ADDRESS(*((UINT16*)R.addr))); |
| 4796 | tempV.addr = &srcVal1; |
| 4797 | tempV.data_type = DT_WORD; |
| 4798 | SetDestinationValue(tempV, D1); |
| 4799 | |
| 4800 | /* Second memmove */ |
| 4801 | srcVal2 = cpustate->data->read_word(ADDRESS(R3)); |
| 4802 | tempV.addr = &srcVal2; |
| 4803 | tempV.data_type = DT_WORD; |
| 4804 | SetDestinationValue(tempV, D2); |
| 4805 | |
| 4806 | /* Touch up the R regs after all the moves */ |
| 4807 | execute_mm_table(cpustate, BITS(op,0x0060), BITS(op,0x1800)); |
| 4808 | } |
| 4809 | |
| 4810 | /*************************************************************************** |
| 4811 | Helper Functions |
| 4812 | ***************************************************************************/ |
| 4813 | static UINT16 Dsp56kOpMask(UINT16 cur, UINT16 mask) |
| 4814 | { |
| 4815 | int i ; |
| 4816 | |
| 4817 | UINT16 retVal = (cur & mask) ; |
| 4818 | UINT16 temp = 0x0000 ; |
| 4819 | int offsetCount = 0 ; |
| 4820 | |
| 4821 | /* Shift everything right, eliminating 'whitespace' */ |
| 4822 | for (i = 0; i < 16; i++) |
| 4823 | { |
| 4824 | if (mask & (0x1<<i)) /* If mask bit is non-zero */ |
| 4825 | { |
| 4826 | temp |= (((retVal >> i) & 0x1) << offsetCount) ; |
| 4827 | offsetCount++ ; |
| 4828 | } |
| 4829 | } |
| 4830 | |
| 4831 | return temp ; |
| 4832 | } |
| 4833 | |
| 4834 | static void SetDestinationValue(typed_pointer source, typed_pointer dest) |
| 4835 | { |
| 4836 | UINT64 destinationValue = 0 ; |
| 4837 | |
| 4838 | switch(dest.data_type) |
| 4839 | { |
| 4840 | /* Copying to an 8-bit value */ |
| 4841 | case DT_BYTE: |
| 4842 | switch(source.data_type) |
| 4843 | { |
| 4844 | /* From a ? */ |
| 4845 | case DT_BYTE: *((UINT8*)dest.addr) = (*((UINT8*) source.addr)) & 0xff; break; |
| 4846 | case DT_WORD: *((UINT8*)dest.addr) = (*((UINT16*)source.addr)) & 0x00ff; break; |
| 4847 | case DT_DOUBLE_WORD: *((UINT8*)dest.addr) = (*((UINT32*)source.addr)) & 0x000000ff; break; |
| 4848 | case DT_LONG_WORD: *((UINT8*)dest.addr) = (*((UINT64*)source.addr)) & U64(0x00000000000000ff); break; |
| 4849 | } |
| 4850 | break ; |
| 4851 | |
| 4852 | /* Copying to a 16-bit value */ |
| 4853 | case DT_WORD: |
| 4854 | switch(source.data_type) |
| 4855 | { |
| 4856 | case DT_BYTE: *((UINT16*)dest.addr) = (*((UINT8*) source.addr)) & 0xff; break; |
| 4857 | case DT_WORD: *((UINT16*)dest.addr) = (*((UINT16*)source.addr)) & 0xffff; break; |
| 4858 | case DT_DOUBLE_WORD: *((UINT16*)dest.addr) = (*((UINT32*)source.addr)) & 0x0000ffff; break; |
| 4859 | case DT_LONG_WORD: *((UINT16*)dest.addr) = (*((UINT64*)source.addr)) & U64(0x000000000000ffff); break; /* TODO: Shift limiter action! A-147 */ |
| 4860 | } |
| 4861 | break ; |
| 4862 | |
| 4863 | /* Copying to a 32-bit value */ |
| 4864 | case DT_DOUBLE_WORD: |
| 4865 | switch(source.data_type) |
| 4866 | { |
| 4867 | case DT_BYTE: *((UINT32*)dest.addr) = (*((UINT8*) source.addr)) & 0xff; break; |
| 4868 | case DT_WORD: *((UINT32*)dest.addr) = (*((UINT16*)source.addr)) & 0xffff; break; |
| 4869 | case DT_DOUBLE_WORD: *((UINT32*)dest.addr) = (*((UINT32*)source.addr)) & 0xffffffff; break; |
| 4870 | case DT_LONG_WORD: *((UINT32*)dest.addr) = (*((UINT64*)source.addr)) & U64(0x00000000ffffffff); break; |
| 4871 | } |
| 4872 | break ; |
| 4873 | |
| 4874 | /* Copying to a 64-bit value */ |
| 4875 | case DT_LONG_WORD: |
| 4876 | switch(source.data_type) |
| 4877 | { |
| 4878 | case DT_BYTE: *((UINT64*)dest.addr) = (*((UINT8*)source.addr)) & 0xff; break; |
| 4879 | |
| 4880 | case DT_WORD: destinationValue = (*((UINT16*)source.addr)) << 16; |
| 4881 | if (destinationValue & U64(0x0000000080000000)) |
| 4882 | destinationValue |= U64(0x000000ff00000000); |
| 4883 | *((UINT64*)dest.addr) = (UINT64)destinationValue; break; /* Forget not, yon shift register */ |
| 4884 | |
| 4885 | case DT_DOUBLE_WORD: *((UINT64*)dest.addr) = (*((UINT32*)source.addr)) & 0xffffffff; break; |
| 4886 | case DT_LONG_WORD: *((UINT64*)dest.addr) = (*((UINT64*)source.addr)) & U64(0x000000ffffffffff); break; |
| 4887 | } |
| 4888 | break ; |
| 4889 | } |
| 4890 | } |
| 4891 | |
| 4892 | /* TODO: Wait-state timings! */ |
| 4893 | static void SetDataMemoryValue(dsp56k_core* cpustate, typed_pointer source, UINT32 destinationAddr) |
| 4894 | { |
| 4895 | switch(source.data_type) |
| 4896 | { |
| 4897 | case DT_BYTE: cpustate->data->write_word(destinationAddr, (UINT16)( (*((UINT8*) source.addr) & 0xff) ) ) ; break ; |
| 4898 | case DT_WORD: cpustate->data->write_word(destinationAddr, (UINT16)( (*((UINT16*)source.addr) & 0xffff) ) ) ; break ; |
| 4899 | case DT_DOUBLE_WORD: cpustate->data->write_word(destinationAddr, (UINT16)( (*((UINT32*)source.addr) & 0x0000ffff) ) ) ; break ; |
| 4900 | |
| 4901 | /* !!! Is this universal ??? */ |
| 4902 | /* !!! Forget not, yon shift-limiter !!! */ |
| 4903 | case DT_LONG_WORD: cpustate->data->write_word(destinationAddr, (UINT16)( ((*((UINT64*)source.addr)) & U64(0x00000000ffff0000)) >> 16) ) ; break ; |
| 4904 | } |
| 4905 | } |
| 4906 | |
| 4907 | /* TODO: Wait-state timings! */ |
| 4908 | static void SetProgramMemoryValue(dsp56k_core* cpustate, typed_pointer source, UINT32 destinationAddr) |
| 4909 | { |
| 4910 | switch(source.data_type) |
| 4911 | { |
| 4912 | case DT_BYTE: cpustate->program->write_word(destinationAddr, (UINT16)( (*((UINT8*) source.addr) & 0xff) ) ) ; break ; |
| 4913 | case DT_WORD: cpustate->program->write_word(destinationAddr, (UINT16)( (*((UINT16*)source.addr) & 0xffff) ) ) ; break ; |
| 4914 | case DT_DOUBLE_WORD: cpustate->program->write_word(destinationAddr, (UINT16)( (*((UINT32*)source.addr) & 0x0000ffff) ) ) ; break ; |
| 4915 | |
| 4916 | /* !!! Is this universal ??? */ |
| 4917 | /* !!! Forget not, yon shift-limiter !!! */ |
| 4918 | case DT_LONG_WORD: cpustate->program->write_word(destinationAddr, (UINT16)( ((*((UINT64*)source.addr)) & U64(0x00000000ffff0000)) >> 16) ) ; break ; |
| 4919 | } |
| 4920 | } |