PCem
view src/x86_ops_stack.h @ 142:bd46c39a78e8
Implemented selector limits on some instructions - fixes LBA2.
GPFs in real mode now work.
Selectors correctly zeroed on far return to lower privilege.
| author | TomW |
|---|---|
| date | Wed Aug 13 20:33:56 2014 +0100 |
| parents | 626d3074b545 |
| children |
line source
1 #define PUSH_W_OP(reg) \
2 static int opPUSH_ ## reg (uint32_t fetchdat) \
3 { \
4 PUSH_W(reg); \
5 cycles -= (is486) ? 1 : 2; \
6 return 0; \
7 }
9 #define PUSH_L_OP(reg) \
10 static int opPUSH_ ## reg (uint32_t fetchdat) \
11 { \
12 PUSH_L(reg); \
13 cycles -= (is486) ? 1 : 2; \
14 return 0; \
15 }
17 #define POP_W_OP(reg) \
18 static int opPOP_ ## reg (uint32_t fetchdat) \
19 { \
20 reg = POP_W(); \
21 cycles -= (is486) ? 1 : 4; \
22 return 0; \
23 }
25 #define POP_L_OP(reg) \
26 static int opPOP_ ## reg (uint32_t fetchdat) \
27 { \
28 reg = POP_L(); \
29 cycles -= (is486) ? 1 : 4; \
30 return 0; \
31 }
33 PUSH_W_OP(AX)
34 PUSH_W_OP(BX)
35 PUSH_W_OP(CX)
36 PUSH_W_OP(DX)
37 PUSH_W_OP(SI)
38 PUSH_W_OP(DI)
39 PUSH_W_OP(BP)
40 PUSH_W_OP(SP)
42 PUSH_L_OP(EAX)
43 PUSH_L_OP(EBX)
44 PUSH_L_OP(ECX)
45 PUSH_L_OP(EDX)
46 PUSH_L_OP(ESI)
47 PUSH_L_OP(EDI)
48 PUSH_L_OP(EBP)
49 PUSH_L_OP(ESP)
51 POP_W_OP(AX)
52 POP_W_OP(BX)
53 POP_W_OP(CX)
54 POP_W_OP(DX)
55 POP_W_OP(SI)
56 POP_W_OP(DI)
57 POP_W_OP(BP)
58 POP_W_OP(SP)
60 POP_L_OP(EAX)
61 POP_L_OP(EBX)
62 POP_L_OP(ECX)
63 POP_L_OP(EDX)
64 POP_L_OP(ESI)
65 POP_L_OP(EDI)
66 POP_L_OP(EBP)
67 POP_L_OP(ESP)
70 static int opPUSHA_w(uint32_t fetchdat)
71 {
72 if (stack32)
73 {
74 writememw(ss, ESP - 2, AX);
75 writememw(ss, ESP - 4, CX);
76 writememw(ss, ESP - 6, DX);
77 writememw(ss, ESP - 8, BX);
78 writememw(ss, ESP - 10, SP);
79 writememw(ss, ESP - 12, BP);
80 writememw(ss, ESP - 14, SI);
81 writememw(ss, ESP - 16, DI);
82 if (!abrt) ESP -= 16;
83 }
84 else
85 {
86 writememw(ss, ((SP - 2) & 0xFFFF), AX);
87 writememw(ss, ((SP - 4) & 0xFFFF), CX);
88 writememw(ss, ((SP - 6) & 0xFFFF), DX);
89 writememw(ss, ((SP - 8) & 0xFFFF), BX);
90 writememw(ss, ((SP - 10) & 0xFFFF), SP);
91 writememw(ss, ((SP - 12) & 0xFFFF), BP);
92 writememw(ss, ((SP - 14) & 0xFFFF), SI);
93 writememw(ss, ((SP - 16) & 0xFFFF), DI);
94 if (!abrt) SP -= 16;
95 }
96 cycles -= (is486) ? 11 : 18;
97 return 0;
98 }
99 static int opPUSHA_l(uint32_t fetchdat)
100 {
101 if (stack32)
102 {
103 writememl(ss, ESP - 4, EAX);
104 writememl(ss, ESP - 8, ECX);
105 writememl(ss, ESP - 12, EDX);
106 writememl(ss, ESP - 16, EBX);
107 writememl(ss, ESP - 20, ESP);
108 writememl(ss, ESP - 24, EBP);
109 writememl(ss, ESP - 28, ESI);
110 writememl(ss, ESP - 32, EDI);
111 if (!abrt) ESP -= 32;
112 }
113 else
114 {
115 writememl(ss, ((SP - 4) & 0xFFFF), EAX);
116 writememl(ss, ((SP - 8) & 0xFFFF), ECX);
117 writememl(ss, ((SP - 12) & 0xFFFF), EDX);
118 writememl(ss, ((SP - 16) & 0xFFFF), EBX);
119 writememl(ss, ((SP - 20) & 0xFFFF), ESP);
120 writememl(ss, ((SP - 24) & 0xFFFF), EBP);
121 writememl(ss, ((SP - 28) & 0xFFFF), ESI);
122 writememl(ss, ((SP - 32) & 0xFFFF), EDI);
123 if (!abrt) SP -= 32;
124 }
125 cycles -= (is486) ? 11 : 18;
126 return 0;
127 }
129 static int opPOPA_w(uint32_t fetchdat)
130 {
131 if (stack32)
132 {
133 DI = readmemw(ss, ESP); if (abrt) return 0;
134 SI = readmemw(ss, ESP + 2); if (abrt) return 0;
135 BP = readmemw(ss, ESP + 4); if (abrt) return 0;
136 BX = readmemw(ss, ESP + 8); if (abrt) return 0;
137 DX = readmemw(ss, ESP + 10); if (abrt) return 0;
138 CX = readmemw(ss, ESP + 12); if (abrt) return 0;
139 AX = readmemw(ss, ESP + 14); if (abrt) return 0;
140 ESP += 16;
141 }
142 else
143 {
144 DI = readmemw(ss, ((SP) & 0xFFFF)); if (abrt) return 0;
145 SI = readmemw(ss, ((SP + 2) & 0xFFFF)); if (abrt) return 0;
146 BP = readmemw(ss, ((SP + 4) & 0xFFFF)); if (abrt) return 0;
147 BX = readmemw(ss, ((SP + 8) & 0xFFFF)); if (abrt) return 0;
148 DX = readmemw(ss, ((SP + 10) & 0xFFFF)); if (abrt) return 0;
149 CX = readmemw(ss, ((SP + 12) & 0xFFFF)); if (abrt) return 0;
150 AX = readmemw(ss, ((SP + 14) & 0xFFFF)); if (abrt) return 0;
151 SP += 16;
152 }
153 cycles -= (is486) ? 9 : 24;
154 return 0;
155 }
156 static int opPOPA_l(uint32_t fetchdat)
157 {
158 if (stack32)
159 {
160 EDI = readmeml(ss, ESP); if (abrt) return 0;
161 ESI = readmeml(ss, ESP + 4); if (abrt) return 0;
162 EBP = readmeml(ss, ESP + 8); if (abrt) return 0;
163 EBX = readmeml(ss, ESP + 16); if (abrt) return 0;
164 EDX = readmeml(ss, ESP + 20); if (abrt) return 0;
165 ECX = readmeml(ss, ESP + 24); if (abrt) return 0;
166 EAX = readmeml(ss, ESP + 28); if (abrt) return 0;
167 ESP += 32;
168 }
169 else
170 {
171 EDI = readmeml(ss, ((SP) & 0xFFFF)); if (abrt) return 0;
172 ESI = readmeml(ss, ((SP + 4) & 0xFFFF)); if (abrt) return 0;
173 EBP = readmeml(ss, ((SP + 8) & 0xFFFF)); if (abrt) return 0;
174 EBX = readmeml(ss, ((SP + 16) & 0xFFFF)); if (abrt) return 0;
175 EDX = readmeml(ss, ((SP + 20) & 0xFFFF)); if (abrt) return 0;
176 ECX = readmeml(ss, ((SP + 24) & 0xFFFF)); if (abrt) return 0;
177 EAX = readmeml(ss, ((SP + 28) & 0xFFFF)); if (abrt) return 0;
178 SP += 32;
179 }
180 cycles -= (is486) ? 9 : 24;
181 return 0;
182 }
184 static int opPUSH_imm_w(uint32_t fetchdat)
185 {
186 uint16_t val = getwordf();
187 PUSH_W(val);
188 cycles -= 2;
189 return 0;
190 }
191 static int opPUSH_imm_l(uint32_t fetchdat)
192 {
193 uint32_t val = getlong();
194 PUSH_L(val);
195 cycles -= 2;
196 return 0;
197 }
199 static int opPUSH_imm_bw(uint32_t fetchdat)
200 {
201 uint16_t tempw = getbytef();
203 if (tempw & 0x80) tempw |= 0xFF00;
204 PUSH_W(tempw);
206 cycles -= 2;
207 return 0;
208 }
209 static int opPUSH_imm_bl(uint32_t fetchdat)
210 {
211 uint32_t templ = getbytef();
213 if (templ & 0x80) templ |= 0xFFFFFF00;
214 PUSH_L(templ);
216 cycles -= 2;
217 return 0;
218 }
220 static int opPOPW_a16(uint32_t fetchdat)
221 {
222 uint16_t temp;
224 temp = POP_W(); if (abrt) return 0;
226 fetch_ea_16(fetchdat);
227 seteaw(temp);
228 if (abrt)
229 {
230 if (stack32) ESP -= 2;
231 else SP -= 2;
232 }
234 if (is486) cycles -= ((mod == 3) ? 1 : 6);
235 else cycles -= ((mod == 3) ? 4 : 5);
236 return 0;
237 }
238 static int opPOPW_a32(uint32_t fetchdat)
239 {
240 uint16_t temp;
242 temp = POP_W(); if (abrt) return 0;
244 fetch_ea_32(fetchdat);
245 seteaw(temp);
246 if (abrt)
247 {
248 if (stack32) ESP -= 2;
249 else SP -= 2;
250 }
252 if (is486) cycles -= ((mod == 3) ? 1 : 6);
253 else cycles -= ((mod == 3) ? 4 : 5);
254 return 0;
255 }
257 static int opPOPL_a16(uint32_t fetchdat)
258 {
259 uint32_t temp;
261 temp = POP_L(); if (abrt) return 0;
263 fetch_ea_16(fetchdat);
264 seteal(temp);
265 if (abrt)
266 {
267 if (stack32) ESP -= 4;
268 else SP -= 4;
269 }
271 if (is486) cycles -= ((mod == 3) ? 1 : 6);
272 else cycles -= ((mod == 3) ? 4 : 5);
273 return 0;
274 }
275 static int opPOPL_a32(uint32_t fetchdat)
276 {
277 uint32_t temp;
279 temp = POP_L(); if (abrt) return 0;
281 fetch_ea_32(fetchdat);
282 seteal(temp);
283 if (abrt)
284 {
285 if (stack32) ESP -= 4;
286 else SP -= 4;
287 }
289 if (is486) cycles -= ((mod == 3) ? 1 : 6);
290 else cycles -= ((mod == 3) ? 4 : 5);
291 return 0;
292 }
295 static int opENTER_w(uint32_t fetchdat)
296 {
297 uint16_t offset = getwordf();
298 int count = (fetchdat >> 16) & 0xff; pc++;
299 uint32_t tempEBP = EBP, tempESP = ESP, frame_ptr;
301 PUSH_W(BP); if (abrt) return 0;
302 frame_ptr = ESP;
304 if (count > 0)
305 {
306 while (--count)
307 {
308 uint16_t tempw;
310 BP -= 2;
311 tempw = readmemw(ss, BP);
312 if (abrt) { ESP = tempESP; EBP = tempEBP; return 0; }
313 PUSH_W(tempw);
314 if (abrt) { ESP = tempESP; EBP = tempEBP; return 0; }
315 cycles -= (is486) ? 3 : 4;
316 }
317 PUSH_W(frame_ptr);
318 if (abrt) { ESP = tempESP; EBP = tempEBP; return 0; }
319 cycles -= (is486) ? 3 : 5;
320 }
321 BP = frame_ptr;
323 if (stack32) ESP -= offset;
324 else SP -= offset;
325 cycles -= (is486) ? 14 : 10;
326 return 0;
327 }
328 static int opENTER_l(uint32_t fetchdat)
329 {
330 uint16_t offset = getwordf();
331 int count = (fetchdat >> 16) & 0xff; pc++;
332 uint32_t tempEBP = EBP, tempESP = ESP, frame_ptr;
334 PUSH_L(EBP); if (abrt) return 0;
335 frame_ptr = ESP;
337 if (count > 0)
338 {
339 while (--count)
340 {
341 uint32_t templ;
343 EBP -= 4;
344 templ = readmeml(ss, EBP);
345 if (abrt) { ESP = tempESP; EBP = tempEBP; return 0; }
346 PUSH_L(templ);
347 if (abrt) { ESP = tempESP; EBP = tempEBP; return 0; }
348 cycles -= (is486) ? 3 : 4;
349 }
350 PUSH_L(frame_ptr);
351 if (abrt) { ESP = tempESP; EBP = tempEBP; return 0; }
352 cycles -= (is486) ? 3 : 5;
353 }
354 EBP = frame_ptr;
356 if (stack32) ESP -= offset;
357 else SP -= offset;
358 cycles -= (is486) ? 14 : 10;
359 return 0;
360 }
363 static int opLEAVE_w(uint32_t fetchdat)
364 {
365 uint32_t tempESP = ESP;
366 uint16_t temp;
368 SP = BP;
369 temp = POP_W();
370 if (abrt) { ESP = tempESP; return 0; }
371 BP = temp;
373 cycles -= 4;
374 return 0;
375 }
376 static int opLEAVE_l(uint32_t fetchdat)
377 {
378 uint32_t tempESP = ESP;
379 uint32_t temp;
381 ESP = EBP;
382 temp = POP_L();
383 if (abrt) { ESP = tempESP; return 0; }
384 EBP = temp;
386 cycles -= 4;
387 return 0;
388 }
391 #define PUSH_SEG_OPS(seg) \
392 static int opPUSH_ ## seg ## _w(uint32_t fetchdat) \
393 { \
394 PUSH_W(seg); \
395 cycles -= 2; \
396 return 0; \
397 } \
398 static int opPUSH_ ## seg ## _l(uint32_t fetchdat) \
399 { \
400 PUSH_L(seg); \
401 cycles -= 2; \
402 return 0; \
403 }
405 #define POP_SEG_OPS(seg, realseg) \
406 static int opPOP_ ## seg ## _w(uint32_t fetchdat) \
407 { \
408 uint16_t temp_seg; \
409 uint32_t temp_esp = ESP; \
410 temp_seg = POP_W(); if (abrt) return 0; \
411 loadseg(temp_seg, realseg); if (abrt) ESP = temp_esp; \
412 cycles -= is486 ? 3 : 7; \
413 return 0; \
414 } \
415 static int opPOP_ ## seg ## _l(uint32_t fetchdat) \
416 { \
417 uint32_t temp_seg; \
418 uint32_t temp_esp = ESP; \
419 temp_seg = POP_L(); if (abrt) return 0; \
420 loadseg(temp_seg & 0xffff, realseg); if (abrt) ESP = temp_esp; \
421 cycles -= is486 ? 3 : 7; \
422 return 0; \
423 }
426 PUSH_SEG_OPS(CS);
427 PUSH_SEG_OPS(DS);
428 PUSH_SEG_OPS(ES);
429 PUSH_SEG_OPS(FS);
430 PUSH_SEG_OPS(GS);
431 PUSH_SEG_OPS(SS);
433 POP_SEG_OPS(DS, &_ds);
434 POP_SEG_OPS(ES, &_es);
435 POP_SEG_OPS(FS, &_fs);
436 POP_SEG_OPS(GS, &_gs);
437 POP_SEG_OPS(SS, &_ss);
