1 /****************************************************************************
2 * real mode i286 emulator v1.4 by Fabrice Frances *
3 * (initial work based on David Hedley's pcemu) *
4 ****************************************************************************/
5
6 // file will be included in all cpu variants
7 // function renaming will be added when neccessary
8 // timing value should move to separate array
9
10 #undef ICOUNT
11
12 #ifdef V20
13 #define ICOUNT nec_ICount
14 #else
15 #define ICOUNT i86_ICount
16 #endif
17
18
PREFIX186(_pusha)19 static void PREFIX186(_pusha)(void) /* Opcode 0x60 */
20 {
21 unsigned tmp=I.regs.w[SP];
22
23 ICOUNT -= cycles.pusha;
24 PUSH(I.regs.w[AX]);
25 PUSH(I.regs.w[CX]);
26 PUSH(I.regs.w[DX]);
27 PUSH(I.regs.w[BX]);
28 PUSH(tmp);
29 PUSH(I.regs.w[BP]);
30 PUSH(I.regs.w[SI]);
31 PUSH(I.regs.w[DI]);
32 }
33
PREFIX186(_popa)34 static void PREFIX186(_popa)(void) /* Opcode 0x61 */
35 {
36 unsigned tmp;
37
38 ICOUNT -= cycles.popa;
39 POP(I.regs.w[DI]);
40 POP(I.regs.w[SI]);
41 POP(I.regs.w[BP]);
42 POP(tmp);
43 POP(I.regs.w[BX]);
44 POP(I.regs.w[DX]);
45 POP(I.regs.w[CX]);
46 POP(I.regs.w[AX]);
47 }
48
PREFIX186(_bound)49 static void PREFIX186(_bound)(void) /* Opcode 0x62 */
50 {
51 unsigned ModRM = FETCHOP;
52 int low = (INT16)GetRMWord(ModRM);
53 int high= (INT16)GetnextRMWord;
54 int tmp= (INT16)RegWord(ModRM);
55 if (tmp<low || tmp>high) {
56 /* OB: on NECs CS:IP points to instruction
57 FOLLOWING the BOUND instruction ! */
58 #if !defined(V20)
59 I.pc-=2;
60 PREFIX86(_interrupt)(5);
61 #else
62 PREFIX(_interrupt)(5,0);
63 #endif
64 }
65 ICOUNT -= cycles.bound;
66 }
67
PREFIX186(_push_d16)68 static void PREFIX186(_push_d16)(void) /* Opcode 0x68 */
69 {
70 unsigned tmp = FETCH;
71
72 ICOUNT -= cycles.push_imm;
73 tmp += FETCH << 8;
74 PUSH(tmp);
75 }
76
PREFIX186(_imul_d16)77 static void PREFIX186(_imul_d16)(void) /* Opcode 0x69 */
78 {
79 DEF_r16w(dst,src);
80 unsigned src2=FETCH;
81 src+=(FETCH<<8);
82
83 ICOUNT -= (ModRM >= 0xc0) ? cycles.imul_rri16 : cycles.imul_rmi16;
84
85 dst = (INT32)((INT16)src)*(INT32)((INT16)src2);
86 I.CarryVal = I.OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1);
87 RegWord(ModRM)=(WORD)dst;
88 }
89
90
PREFIX186(_push_d8)91 static void PREFIX186(_push_d8)(void) /* Opcode 0x6a */
92 {
93 unsigned tmp = (WORD)((INT16)((INT8)FETCH));
94
95 ICOUNT -= cycles.push_imm;
96 PUSH(tmp);
97 }
98
PREFIX186(_imul_d8)99 static void PREFIX186(_imul_d8)(void) /* Opcode 0x6b */
100 {
101 DEF_r16w(dst,src);
102 unsigned src2= (WORD)((INT16)((INT8)FETCH));
103
104 ICOUNT -= (ModRM >= 0xc0) ? cycles.imul_rri8 : cycles.imul_rmi8;
105
106 dst = (INT32)((INT16)src)*(INT32)((INT16)src2);
107 I.CarryVal = I.OverVal = (((INT32)dst) >> 15 != 0) && (((INT32)dst) >> 15 != -1);
108 RegWord(ModRM)=(WORD)dst;
109 }
110
PREFIX186(_insb)111 static void PREFIX186(_insb)(void) /* Opcode 0x6c */
112 {
113 ICOUNT -= cycles.ins8;
114 PutMemB(ES,I.regs.w[DI],read_port(I.regs.w[DX]));
115 I.regs.w[DI] += I.DirVal;
116 }
117
PREFIX186(_insw)118 static void PREFIX186(_insw)(void) /* Opcode 0x6d */
119 {
120 ICOUNT -= cycles.ins16;
121 PutMemB(ES,I.regs.w[DI],read_port(I.regs.w[DX]));
122 PutMemB(ES,I.regs.w[DI]+1,read_port(I.regs.w[DX]+1));
123 I.regs.w[DI] += 2 * I.DirVal;
124 }
125
PREFIX186(_outsb)126 static void PREFIX186(_outsb)(void) /* Opcode 0x6e */
127 {
128 ICOUNT -= cycles.outs8;
129 write_port(I.regs.w[DX],GetMemB(DS,I.regs.w[SI]));
130 I.regs.w[DI] += I.DirVal;
131 }
132
PREFIX186(_outsw)133 static void PREFIX186(_outsw)(void) /* Opcode 0x6f */
134 {
135 ICOUNT -= cycles.outs16;
136 write_port(I.regs.w[DX],GetMemB(DS,I.regs.w[SI]));
137 write_port(I.regs.w[DX]+1,GetMemB(DS,I.regs.w[SI]+1));
138 I.regs.w[DI] += 2 * I.DirVal;
139 }
140
PREFIX186(_rotshft_bd8)141 static void PREFIX186(_rotshft_bd8)(void) /* Opcode 0xc0 */
142 {
143 unsigned ModRM = FETCH;
144 unsigned count = FETCH;
145
146 PREFIX86(_rotate_shift_Byte)(ModRM,count);
147 }
148
PREFIX186(_rotshft_wd8)149 static void PREFIX186(_rotshft_wd8)(void) /* Opcode 0xc1 */
150 {
151 unsigned ModRM = FETCH;
152 unsigned count = FETCH;
153
154 PREFIX86(_rotate_shift_Word)(ModRM,count);
155 }
156
PREFIX186(_enter)157 static void PREFIX186(_enter)(void) /* Opcode 0xc8 */
158 {
159 unsigned nb = FETCH; unsigned i,level;
160
161 nb += FETCH << 8;
162 level = FETCH;
163 ICOUNT -= (level == 0) ? cycles.enter0 : (level == 1) ? cycles.enter1 : cycles.enter_base + level * cycles.enter_count;
164 PUSH(I.regs.w[BP]);
165 I.regs.w[BP]=I.regs.w[SP];
166 I.regs.w[SP] -= nb;
167 for (i=1;i<level;i++)
168 PUSH(GetMemW(SS,I.regs.w[BP]-i*2));
169 if (level) PUSH(I.regs.w[BP]);
170 }
171
PREFIX186(_leave)172 static void PREFIX186(_leave)(void) /* Opcode 0xc9 */
173 {
174 ICOUNT -= cycles.leave;
175 I.regs.w[SP]=I.regs.w[BP];
176 POP(I.regs.w[BP]);
177 }
178