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