[SOFT386]
[reactos.git] / lib / soft386 / opcodes.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: 386/486 CPU Emulation Library
4 * FILE: opcodes.c
5 * PURPOSE: Opcode handlers.
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 // #define WIN32_NO_STATUS
12 // #define _INC_WINDOWS
13 #include <windef.h>
14
15 #include <soft386.h>
16 #include "opcodes.h"
17 #include "common.h"
18
19 // #define NDEBUG
20 #include <debug.h>
21
22 /* PUBLIC VARIABLES ***********************************************************/
23
24 SOFT386_OPCODE_HANDLER_PROC
25 Soft386OpcodeHandlers[SOFT386_NUM_OPCODE_HANDLERS] =
26 {
27 NULL, // TODO: OPCODE 0x00 NOT SUPPORTED
28 NULL, // TODO: OPCODE 0x01 NOT SUPPORTED
29 NULL, // TODO: OPCODE 0x02 NOT SUPPORTED
30 NULL, // TODO: OPCODE 0x03 NOT SUPPORTED
31 NULL, // TODO: OPCODE 0x04 NOT SUPPORTED
32 NULL, // TODO: OPCODE 0x05 NOT SUPPORTED
33 NULL, // TODO: OPCODE 0x06 NOT SUPPORTED
34 NULL, // TODO: OPCODE 0x07 NOT SUPPORTED
35 NULL, // TODO: OPCODE 0x08 NOT SUPPORTED
36 NULL, // TODO: OPCODE 0x09 NOT SUPPORTED
37 NULL, // TODO: OPCODE 0x0A NOT SUPPORTED
38 NULL, // TODO: OPCODE 0x0B NOT SUPPORTED
39 NULL, // TODO: OPCODE 0x0C NOT SUPPORTED
40 NULL, // TODO: OPCODE 0x0D NOT SUPPORTED
41 NULL, // TODO: OPCODE 0x0E NOT SUPPORTED
42 NULL, // TODO: OPCODE 0x0F NOT SUPPORTED
43 NULL, // TODO: OPCODE 0x10 NOT SUPPORTED
44 NULL, // TODO: OPCODE 0x11 NOT SUPPORTED
45 NULL, // TODO: OPCODE 0x12 NOT SUPPORTED
46 NULL, // TODO: OPCODE 0x13 NOT SUPPORTED
47 NULL, // TODO: OPCODE 0x14 NOT SUPPORTED
48 NULL, // TODO: OPCODE 0x15 NOT SUPPORTED
49 NULL, // TODO: OPCODE 0x16 NOT SUPPORTED
50 NULL, // TODO: OPCODE 0x17 NOT SUPPORTED
51 NULL, // TODO: OPCODE 0x18 NOT SUPPORTED
52 NULL, // TODO: OPCODE 0x19 NOT SUPPORTED
53 NULL, // TODO: OPCODE 0x1A NOT SUPPORTED
54 NULL, // TODO: OPCODE 0x1B NOT SUPPORTED
55 NULL, // TODO: OPCODE 0x1C NOT SUPPORTED
56 NULL, // TODO: OPCODE 0x1D NOT SUPPORTED
57 NULL, // TODO: OPCODE 0x1E NOT SUPPORTED
58 NULL, // TODO: OPCODE 0x1F NOT SUPPORTED
59 NULL, // TODO: OPCODE 0x20 NOT SUPPORTED
60 NULL, // TODO: OPCODE 0x21 NOT SUPPORTED
61 NULL, // TODO: OPCODE 0x22 NOT SUPPORTED
62 NULL, // TODO: OPCODE 0x23 NOT SUPPORTED
63 NULL, // TODO: OPCODE 0x24 NOT SUPPORTED
64 NULL, // TODO: OPCODE 0x25 NOT SUPPORTED
65 Soft386OpcodePrefix,
66 NULL, // TODO: OPCODE 0x27 NOT SUPPORTED
67 NULL, // TODO: OPCODE 0x28 NOT SUPPORTED
68 NULL, // TODO: OPCODE 0x29 NOT SUPPORTED
69 NULL, // TODO: OPCODE 0x2A NOT SUPPORTED
70 NULL, // TODO: OPCODE 0x2B NOT SUPPORTED
71 NULL, // TODO: OPCODE 0x2C NOT SUPPORTED
72 NULL, // TODO: OPCODE 0x2D NOT SUPPORTED
73 Soft386OpcodePrefix,
74 NULL, // TODO: OPCODE 0x2F NOT SUPPORTED
75 NULL, // TODO: OPCODE 0x30 NOT SUPPORTED
76 NULL, // TODO: OPCODE 0x31 NOT SUPPORTED
77 NULL, // TODO: OPCODE 0x32 NOT SUPPORTED
78 NULL, // TODO: OPCODE 0x33 NOT SUPPORTED
79 NULL, // TODO: OPCODE 0x34 NOT SUPPORTED
80 NULL, // TODO: OPCODE 0x35 NOT SUPPORTED
81 Soft386OpcodePrefix,
82 NULL, // TODO: OPCODE 0x37 NOT SUPPORTED
83 NULL, // TODO: OPCODE 0x38 NOT SUPPORTED
84 NULL, // TODO: OPCODE 0x39 NOT SUPPORTED
85 NULL, // TODO: OPCODE 0x3A NOT SUPPORTED
86 NULL, // TODO: OPCODE 0x3B NOT SUPPORTED
87 NULL, // TODO: OPCODE 0x3C NOT SUPPORTED
88 NULL, // TODO: OPCODE 0x3D NOT SUPPORTED
89 Soft386OpcodePrefix,
90 NULL, // TODO: OPCODE 0x3F NOT SUPPORTED
91 Soft386OpcodeIncrement,
92 Soft386OpcodeIncrement,
93 Soft386OpcodeIncrement,
94 Soft386OpcodeIncrement,
95 Soft386OpcodeIncrement,
96 Soft386OpcodeIncrement,
97 Soft386OpcodeIncrement,
98 Soft386OpcodeIncrement,
99 Soft386OpcodeDecrement,
100 Soft386OpcodeDecrement,
101 Soft386OpcodeDecrement,
102 Soft386OpcodeDecrement,
103 Soft386OpcodeDecrement,
104 Soft386OpcodeDecrement,
105 Soft386OpcodeDecrement,
106 Soft386OpcodeDecrement,
107 Soft386OpcodePushReg,
108 Soft386OpcodePushReg,
109 Soft386OpcodePushReg,
110 Soft386OpcodePushReg,
111 Soft386OpcodePushReg,
112 Soft386OpcodePushReg,
113 Soft386OpcodePushReg,
114 Soft386OpcodePushReg,
115 Soft386OpcodePopReg,
116 Soft386OpcodePopReg,
117 Soft386OpcodePopReg,
118 Soft386OpcodePopReg,
119 Soft386OpcodePopReg,
120 Soft386OpcodePopReg,
121 Soft386OpcodePopReg,
122 Soft386OpcodePopReg,
123 NULL, // TODO: OPCODE 0x60 NOT SUPPORTED
124 NULL, // TODO: OPCODE 0x61 NOT SUPPORTED
125 NULL, // TODO: OPCODE 0x62 NOT SUPPORTED
126 NULL, // TODO: OPCODE 0x63 NOT SUPPORTED
127 Soft386OpcodePrefix,
128 Soft386OpcodePrefix,
129 Soft386OpcodePrefix,
130 Soft386OpcodePrefix,
131 NULL, // TODO: OPCODE 0x68 NOT SUPPORTED
132 NULL, // TODO: OPCODE 0x69 NOT SUPPORTED
133 NULL, // TODO: OPCODE 0x6A NOT SUPPORTED
134 NULL, // TODO: OPCODE 0x6B NOT SUPPORTED
135 NULL, // TODO: OPCODE 0x6C NOT SUPPORTED
136 NULL, // TODO: OPCODE 0x6D NOT SUPPORTED
137 NULL, // TODO: OPCODE 0x6E NOT SUPPORTED
138 NULL, // TODO: OPCODE 0x6F NOT SUPPORTED
139 Soft386OpcodeShortConditionalJmp,
140 Soft386OpcodeShortConditionalJmp,
141 Soft386OpcodeShortConditionalJmp,
142 Soft386OpcodeShortConditionalJmp,
143 Soft386OpcodeShortConditionalJmp,
144 Soft386OpcodeShortConditionalJmp,
145 Soft386OpcodeShortConditionalJmp,
146 Soft386OpcodeShortConditionalJmp,
147 Soft386OpcodeShortConditionalJmp,
148 Soft386OpcodeShortConditionalJmp,
149 Soft386OpcodeShortConditionalJmp,
150 Soft386OpcodeShortConditionalJmp,
151 Soft386OpcodeShortConditionalJmp,
152 Soft386OpcodeShortConditionalJmp,
153 Soft386OpcodeShortConditionalJmp,
154 Soft386OpcodeShortConditionalJmp,
155 NULL, // TODO: OPCODE 0x80 NOT SUPPORTED
156 NULL, // TODO: OPCODE 0x81 NOT SUPPORTED
157 NULL, // TODO: OPCODE 0x82 NOT SUPPORTED
158 NULL, // TODO: OPCODE 0x83 NOT SUPPORTED
159 NULL, // TODO: OPCODE 0x84 NOT SUPPORTED
160 NULL, // TODO: OPCODE 0x85 NOT SUPPORTED
161 NULL, // TODO: OPCODE 0x86 NOT SUPPORTED
162 NULL, // TODO: OPCODE 0x87 NOT SUPPORTED
163 NULL, // TODO: OPCODE 0x88 NOT SUPPORTED
164 NULL, // TODO: OPCODE 0x89 NOT SUPPORTED
165 NULL, // TODO: OPCODE 0x8A NOT SUPPORTED
166 NULL, // TODO: OPCODE 0x8B NOT SUPPORTED
167 NULL, // TODO: OPCODE 0x8C NOT SUPPORTED
168 NULL, // TODO: OPCODE 0x8D NOT SUPPORTED
169 NULL, // TODO: OPCODE 0x8E NOT SUPPORTED
170 NULL, // TODO: OPCODE 0x8F NOT SUPPORTED
171 Soft386OpcodeNop,
172 Soft386OpcodeExchangeEax,
173 Soft386OpcodeExchangeEax,
174 Soft386OpcodeExchangeEax,
175 Soft386OpcodeExchangeEax,
176 Soft386OpcodeExchangeEax,
177 Soft386OpcodeExchangeEax,
178 Soft386OpcodeExchangeEax,
179 NULL, // TODO: OPCODE 0x98 NOT SUPPORTED
180 NULL, // TODO: OPCODE 0x99 NOT SUPPORTED
181 NULL, // TODO: OPCODE 0x9A NOT SUPPORTED
182 NULL, // TODO: OPCODE 0x9B NOT SUPPORTED
183 NULL, // TODO: OPCODE 0x9C NOT SUPPORTED
184 NULL, // TODO: OPCODE 0x9D NOT SUPPORTED
185 NULL, // TODO: OPCODE 0x9E NOT SUPPORTED
186 NULL, // TODO: OPCODE 0x9F NOT SUPPORTED
187 NULL, // TODO: OPCODE 0xA0 NOT SUPPORTED
188 NULL, // TODO: OPCODE 0xA1 NOT SUPPORTED
189 NULL, // TODO: OPCODE 0xA2 NOT SUPPORTED
190 NULL, // TODO: OPCODE 0xA3 NOT SUPPORTED
191 NULL, // TODO: OPCODE 0xA4 NOT SUPPORTED
192 NULL, // TODO: OPCODE 0xA5 NOT SUPPORTED
193 NULL, // TODO: OPCODE 0xA6 NOT SUPPORTED
194 NULL, // TODO: OPCODE 0xA7 NOT SUPPORTED
195 NULL, // TODO: OPCODE 0xA8 NOT SUPPORTED
196 NULL, // TODO: OPCODE 0xA9 NOT SUPPORTED
197 NULL, // TODO: OPCODE 0xAA NOT SUPPORTED
198 NULL, // TODO: OPCODE 0xAB NOT SUPPORTED
199 NULL, // TODO: OPCODE 0xAC NOT SUPPORTED
200 NULL, // TODO: OPCODE 0xAD NOT SUPPORTED
201 NULL, // TODO: OPCODE 0xAE NOT SUPPORTED
202 NULL, // TODO: OPCODE 0xAF NOT SUPPORTED
203 NULL, // TODO: OPCODE 0xB0 NOT SUPPORTED
204 NULL, // TODO: OPCODE 0xB1 NOT SUPPORTED
205 NULL, // TODO: OPCODE 0xB2 NOT SUPPORTED
206 NULL, // TODO: OPCODE 0xB3 NOT SUPPORTED
207 NULL, // TODO: OPCODE 0xB4 NOT SUPPORTED
208 NULL, // TODO: OPCODE 0xB5 NOT SUPPORTED
209 NULL, // TODO: OPCODE 0xB6 NOT SUPPORTED
210 NULL, // TODO: OPCODE 0xB7 NOT SUPPORTED
211 NULL, // TODO: OPCODE 0xB8 NOT SUPPORTED
212 NULL, // TODO: OPCODE 0xB9 NOT SUPPORTED
213 NULL, // TODO: OPCODE 0xBA NOT SUPPORTED
214 NULL, // TODO: OPCODE 0xBB NOT SUPPORTED
215 NULL, // TODO: OPCODE 0xBC NOT SUPPORTED
216 NULL, // TODO: OPCODE 0xBD NOT SUPPORTED
217 NULL, // TODO: OPCODE 0xBE NOT SUPPORTED
218 NULL, // TODO: OPCODE 0xBF NOT SUPPORTED
219 NULL, // TODO: OPCODE 0xC0 NOT SUPPORTED
220 NULL, // TODO: OPCODE 0xC1 NOT SUPPORTED
221 NULL, // TODO: OPCODE 0xC2 NOT SUPPORTED
222 NULL, // TODO: OPCODE 0xC3 NOT SUPPORTED
223 NULL, // TODO: OPCODE 0xC4 NOT SUPPORTED
224 NULL, // TODO: OPCODE 0xC5 NOT SUPPORTED
225 NULL, // TODO: OPCODE 0xC6 NOT SUPPORTED
226 NULL, // TODO: OPCODE 0xC7 NOT SUPPORTED
227 NULL, // TODO: OPCODE 0xC8 NOT SUPPORTED
228 NULL, // TODO: OPCODE 0xC9 NOT SUPPORTED
229 NULL, // TODO: OPCODE 0xCA NOT SUPPORTED
230 NULL, // TODO: OPCODE 0xCB NOT SUPPORTED
231 NULL, // TODO: OPCODE 0xCC NOT SUPPORTED
232 NULL, // TODO: OPCODE 0xCD NOT SUPPORTED
233 NULL, // TODO: OPCODE 0xCE NOT SUPPORTED
234 NULL, // TODO: OPCODE 0xCF NOT SUPPORTED
235 NULL, // TODO: OPCODE 0xD0 NOT SUPPORTED
236 NULL, // TODO: OPCODE 0xD1 NOT SUPPORTED
237 NULL, // TODO: OPCODE 0xD2 NOT SUPPORTED
238 NULL, // TODO: OPCODE 0xD3 NOT SUPPORTED
239 NULL, // TODO: OPCODE 0xD4 NOT SUPPORTED
240 NULL, // TODO: OPCODE 0xD5 NOT SUPPORTED
241 NULL, // TODO: OPCODE 0xD6 NOT SUPPORTED
242 NULL, // TODO: OPCODE 0xD7 NOT SUPPORTED
243 NULL, // TODO: OPCODE 0xD8 NOT SUPPORTED
244 NULL, // TODO: OPCODE 0xD9 NOT SUPPORTED
245 NULL, // TODO: OPCODE 0xDA NOT SUPPORTED
246 NULL, // TODO: OPCODE 0xDB NOT SUPPORTED
247 NULL, // TODO: OPCODE 0xDC NOT SUPPORTED
248 NULL, // TODO: OPCODE 0xDD NOT SUPPORTED
249 NULL, // TODO: OPCODE 0xDE NOT SUPPORTED
250 NULL, // TODO: OPCODE 0xDF NOT SUPPORTED
251 NULL, // TODO: OPCODE 0xE0 NOT SUPPORTED
252 NULL, // TODO: OPCODE 0xE1 NOT SUPPORTED
253 NULL, // TODO: OPCODE 0xE2 NOT SUPPORTED
254 NULL, // TODO: OPCODE 0xE3 NOT SUPPORTED
255 NULL, // TODO: OPCODE 0xE4 NOT SUPPORTED
256 NULL, // TODO: OPCODE 0xE5 NOT SUPPORTED
257 NULL, // TODO: OPCODE 0xE6 NOT SUPPORTED
258 NULL, // TODO: OPCODE 0xE7 NOT SUPPORTED
259 NULL, // TODO: OPCODE 0xE8 NOT SUPPORTED
260 NULL, // TODO: OPCODE 0xE9 NOT SUPPORTED
261 NULL, // TODO: OPCODE 0xEA NOT SUPPORTED
262 NULL, // TODO: OPCODE 0xEB NOT SUPPORTED
263 NULL, // TODO: OPCODE 0xEC NOT SUPPORTED
264 NULL, // TODO: OPCODE 0xED NOT SUPPORTED
265 NULL, // TODO: OPCODE 0xEE NOT SUPPORTED
266 NULL, // TODO: OPCODE 0xEF NOT SUPPORTED
267 Soft386OpcodePrefix,
268 NULL, // Invalid
269 Soft386OpcodePrefix,
270 Soft386OpcodePrefix,
271 NULL, // TODO: OPCODE 0xF4 NOT SUPPORTED
272 NULL, // TODO: OPCODE 0xF5 NOT SUPPORTED
273 NULL, // TODO: OPCODE 0xF6 NOT SUPPORTED
274 NULL, // TODO: OPCODE 0xF7 NOT SUPPORTED
275 Soft386OpcodeClearCarry,
276 Soft386OpcodeSetCarry,
277 Soft386OpcodeClearInt,
278 Soft386OpcodeSetInt,
279 Soft386OpcodeClearDir,
280 Soft386OpcodeSetDir,
281 NULL, // TODO: OPCODE 0xFE NOT SUPPORTED
282 NULL, // TODO: OPCODE 0xFF NOT SUPPORTED
283 };
284
285 BOOLEAN
286 FASTCALL
287 Soft386OpcodePrefix(PSOFT386_STATE State, UCHAR Opcode)
288 {
289 BOOLEAN Valid = FALSE;
290
291 switch (Opcode)
292 {
293 /* ES: */
294 case 0x26:
295 {
296 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
297 {
298 State->PrefixFlags |= SOFT386_PREFIX_SEG;
299 State->SegmentOverride = SOFT386_REG_ES;
300 Valid = TRUE;
301 }
302
303 break;
304 }
305
306 /* CS: */
307 case 0x2E:
308 {
309 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
310 {
311 State->PrefixFlags |= SOFT386_PREFIX_SEG;
312 State->SegmentOverride = SOFT386_REG_CS;
313 Valid = TRUE;
314 }
315
316 break;
317 }
318
319 /* SS: */
320 case 0x36:
321 {
322 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
323 {
324 State->PrefixFlags |= SOFT386_PREFIX_SEG;
325 State->SegmentOverride = SOFT386_REG_SS;
326 Valid = TRUE;
327 }
328
329 break;
330 }
331
332 /* DS: */
333 case 0x3E:
334 {
335 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
336 {
337 State->PrefixFlags |= SOFT386_PREFIX_SEG;
338 State->SegmentOverride = SOFT386_REG_DS;
339 Valid = TRUE;
340 }
341
342 break;
343 }
344
345 /* FS: */
346 case 0x64:
347 {
348 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
349 {
350 State->PrefixFlags |= SOFT386_PREFIX_SEG;
351 State->SegmentOverride = SOFT386_REG_FS;
352 Valid = TRUE;
353 }
354
355 break;
356 }
357
358 /* GS: */
359 case 0x65:
360 {
361 if (!(State->PrefixFlags & SOFT386_PREFIX_SEG))
362 {
363 State->PrefixFlags |= SOFT386_PREFIX_SEG;
364 State->SegmentOverride = SOFT386_REG_GS;
365 Valid = TRUE;
366 }
367
368 break;
369 }
370
371 /* OPSIZE */
372 case 0x66:
373 {
374 if (!(State->PrefixFlags & SOFT386_PREFIX_OPSIZE))
375 {
376 State->PrefixFlags |= SOFT386_PREFIX_OPSIZE;
377 Valid = TRUE;
378 }
379
380 break;
381 }
382
383 /* ADSIZE */
384 case 0x67:
385 {
386 if (!(State->PrefixFlags & SOFT386_PREFIX_ADSIZE))
387 {
388 State->PrefixFlags |= SOFT386_PREFIX_ADSIZE;
389 Valid = TRUE;
390 }
391 break;
392 }
393
394 /* LOCK */
395 case 0xF0:
396 {
397 if (!(State->PrefixFlags & SOFT386_PREFIX_LOCK))
398 {
399 State->PrefixFlags |= SOFT386_PREFIX_LOCK;
400 Valid = TRUE;
401 }
402
403 break;
404 }
405
406 /* REPNZ */
407 case 0xF2:
408 {
409 /* Mutually exclusive with REP */
410 if (!(State->PrefixFlags
411 & (SOFT386_PREFIX_REPNZ | SOFT386_PREFIX_REP)))
412 {
413 State->PrefixFlags |= SOFT386_PREFIX_REPNZ;
414 Valid = TRUE;
415 }
416
417 break;
418 }
419
420 /* REP / REPZ */
421 case 0xF3:
422 {
423 /* Mutually exclusive with REPNZ */
424 if (!(State->PrefixFlags
425 & (SOFT386_PREFIX_REPNZ | SOFT386_PREFIX_REP)))
426 {
427 State->PrefixFlags |= SOFT386_PREFIX_REP;
428 Valid = TRUE;
429 }
430
431 break;
432 }
433 }
434
435 if (!Valid)
436 {
437 /* Clear all prefixes */
438 State->PrefixFlags = 0;
439
440 /* Throw an exception */
441 Soft386Exception(State, SOFT386_EXCEPTION_UD);
442 return FALSE;
443 }
444
445 return TRUE;
446 }
447
448 BOOLEAN
449 FASTCALL
450 Soft386OpcodeIncrement(PSOFT386_STATE State, UCHAR Opcode)
451 {
452 ULONG Value;
453 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
454
455 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
456 {
457 /* The OPSIZE prefix toggles the size */
458 Size = !Size;
459 }
460 else if (State->PrefixFlags != 0)
461 {
462 /* Invalid prefix */
463 Soft386Exception(State, SOFT386_EXCEPTION_UD);
464 return FALSE;
465 }
466
467 /* Make sure this is the right instruction */
468 ASSERT((Opcode & 0xF8) == 0x40);
469
470 if (Size)
471 {
472 Value = ++State->GeneralRegs[Opcode & 0x07].Long;
473
474 State->Flags.Of = (Value == SIGN_FLAG_LONG) ? TRUE : FALSE;
475 State->Flags.Sf = (Value & SIGN_FLAG_LONG) ? TRUE : FALSE;
476 }
477 else
478 {
479 Value = ++State->GeneralRegs[Opcode & 0x07].LowWord;
480
481 State->Flags.Of = (Value == SIGN_FLAG_WORD) ? TRUE : FALSE;
482 State->Flags.Sf = (Value & SIGN_FLAG_WORD) ? TRUE : FALSE;
483 }
484
485 State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
486 State->Flags.Af = ((Value & 0x0F) == 0) ? TRUE : FALSE;
487 State->Flags.Pf = Soft386CalculateParity(LOBYTE(Value));
488
489 /* Return success */
490 return TRUE;
491 }
492
493 BOOLEAN
494 FASTCALL
495 Soft386OpcodeDecrement(PSOFT386_STATE State, UCHAR Opcode)
496 {
497 ULONG Value;
498 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
499
500 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
501 {
502 /* The OPSIZE prefix toggles the size */
503 Size = !Size;
504 }
505 else if (State->PrefixFlags != 0)
506 {
507 /* Invalid prefix */
508 Soft386Exception(State, SOFT386_EXCEPTION_UD);
509 return FALSE;
510 }
511
512 /* Make sure this is the right instruction */
513 ASSERT((Opcode & 0xF8) == 0x48);
514
515 if (Size)
516 {
517 Value = --State->GeneralRegs[Opcode & 0x07].Long;
518
519 State->Flags.Of = (Value == (SIGN_FLAG_LONG - 1)) ? TRUE : FALSE;
520 State->Flags.Sf = (Value & SIGN_FLAG_LONG) ? TRUE : FALSE;
521 }
522 else
523 {
524 Value = --State->GeneralRegs[Opcode & 0x07].LowWord;
525
526 State->Flags.Of = (Value == (SIGN_FLAG_WORD - 1)) ? TRUE : FALSE;
527 State->Flags.Sf = (Value & SIGN_FLAG_WORD) ? TRUE : FALSE;
528 }
529
530 State->Flags.Zf = (Value == 0) ? TRUE : FALSE;
531 State->Flags.Af = ((Value & 0x0F) == 0x0F) ? TRUE : FALSE;
532 State->Flags.Pf = Soft386CalculateParity(LOBYTE(Value));
533
534 /* Return success */
535 return TRUE;
536 }
537
538 BOOLEAN
539 FASTCALL
540 Soft386OpcodePushReg(PSOFT386_STATE State, UCHAR Opcode)
541 {
542 if ((State->PrefixFlags != SOFT386_PREFIX_OPSIZE)
543 && (State->PrefixFlags != 0))
544 {
545 /* Invalid prefix */
546 Soft386Exception(State, SOFT386_EXCEPTION_UD);
547 return FALSE;
548 }
549
550 /* Make sure this is the right instruction */
551 ASSERT((Opcode & 0xF8) == 0x50);
552
553 /* Call the internal function */
554 return Soft386StackPush(State, State->GeneralRegs[Opcode & 0x07].Long);
555 }
556
557 BOOLEAN
558 FASTCALL
559 Soft386OpcodePopReg(PSOFT386_STATE State, UCHAR Opcode)
560 {
561 ULONG Value;
562 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_SS].Size;
563
564 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
565 {
566 /* The OPSIZE prefix toggles the size */
567 Size = !Size;
568 }
569 else if (State->PrefixFlags != 0)
570 {
571 /* Invalid prefix */
572 Soft386Exception(State, SOFT386_EXCEPTION_UD);
573 return FALSE;
574 }
575
576 /* Make sure this is the right instruction */
577 ASSERT((Opcode & 0xF8) == 0x58);
578
579 /* Call the internal function */
580 if (!Soft386StackPop(State, &Value)) return FALSE;
581
582 /* Store the value */
583 if (Size) State->GeneralRegs[Opcode & 0x07].Long = Value;
584 else State->GeneralRegs[Opcode & 0x07].LowWord = Value;
585
586 /* Return success */
587 return TRUE;
588 }
589
590 BOOLEAN
591 FASTCALL
592 Soft386OpcodeNop(PSOFT386_STATE State, UCHAR Opcode)
593 {
594 if (State->PrefixFlags & ~(SOFT386_PREFIX_OPSIZE | SOFT386_PREFIX_REP))
595 {
596 /* Allowed prefixes are REP and OPSIZE */
597 Soft386Exception(State, SOFT386_EXCEPTION_UD);
598 return FALSE;
599 }
600
601 if (State->PrefixFlags & SOFT386_PREFIX_REP)
602 {
603 /* Idle cycle */
604 State->IdleCallback(State);
605 }
606
607 return TRUE;
608 }
609
610 BOOLEAN
611 FASTCALL
612 Soft386OpcodeExchangeEax(PSOFT386_STATE State, UCHAR Opcode)
613 {
614 INT Reg = Opcode & 0x07;
615 BOOLEAN Size = State->SegmentRegs[SOFT386_REG_CS].Size;
616
617 if (State->PrefixFlags == SOFT386_PREFIX_OPSIZE)
618 {
619 /* The OPSIZE prefix toggles the size */
620 Size = !Size;
621 }
622 else if (State->PrefixFlags != 0)
623 {
624 /* Invalid prefix */
625 Soft386Exception(State, SOFT386_EXCEPTION_UD);
626 return FALSE;
627 }
628
629 /* Make sure this is the right instruction */
630 ASSERT((Opcode & 0xF8) == 0x90);
631
632 /* Exchange the values */
633 if (Size)
634 {
635 ULONG Value;
636
637 Value = State->GeneralRegs[Reg].Long;
638 State->GeneralRegs[Reg].Long = State->GeneralRegs[SOFT386_REG_EAX].Long;
639 State->GeneralRegs[SOFT386_REG_EAX].Long = Value;
640 }
641 else
642 {
643 USHORT Value;
644
645 Value = State->GeneralRegs[Reg].LowWord;
646 State->GeneralRegs[Reg].LowWord = State->GeneralRegs[SOFT386_REG_EAX].LowWord;
647 State->GeneralRegs[SOFT386_REG_EAX].LowWord = Value;
648 }
649
650 return TRUE;
651 }
652
653 BOOLEAN
654 FASTCALL
655 Soft386OpcodeShortConditionalJmp(PSOFT386_STATE State, UCHAR Opcode)
656 {
657 BOOLEAN Jump = FALSE;
658 CHAR Offset = 0;
659
660 /* Make sure this is the right instruction */
661 ASSERT((Opcode & 0xF0) == 0x70);
662
663 /* Fetch the offset */
664 if (!Soft386FetchByte(State, (PUCHAR)&Offset))
665 {
666 /* An exception occurred */
667 return FALSE;
668 }
669
670 switch ((Opcode & 0x0F) >> 1)
671 {
672 /* JO / JNO */
673 case 0:
674 {
675 Jump = State->Flags.Of;
676 break;
677 }
678
679 /* JC / JNC */
680 case 1:
681 {
682 Jump = State->Flags.Cf;
683 break;
684 }
685
686 /* JZ / JNZ */
687 case 2:
688 {
689 Jump = State->Flags.Zf;
690 break;
691 }
692
693 /* JBE / JNBE */
694 case 3:
695 {
696 Jump = State->Flags.Cf || State->Flags.Zf;
697 break;
698 }
699
700 /* JS / JNS */
701 case 4:
702 {
703 Jump = State->Flags.Sf;
704 break;
705 }
706
707 /* JP / JNP */
708 case 5:
709 {
710 Jump = State->Flags.Pf;
711 break;
712 }
713
714 /* JL / JNL */
715 case 6:
716 {
717 Jump = State->Flags.Sf != State->Flags.Of;
718 break;
719 }
720
721 /* JLE / JNLE */
722 case 7:
723 {
724 Jump = (State->Flags.Sf != State->Flags.Of) || State->Flags.Zf;
725 break;
726 }
727 }
728
729 if ((Opcode & 0xF0) & 1)
730 {
731 /* Invert the result */
732 Jump = !Jump;
733 }
734
735 if (Jump)
736 {
737 /* Move the instruction pointer */
738 State->InstPtr.Long += Offset;
739 }
740
741 /* Return success */
742 return TRUE;
743 }
744
745 BOOLEAN
746 FASTCALL
747 Soft386OpcodeClearCarry(PSOFT386_STATE State, UCHAR Opcode)
748 {
749 /* Make sure this is the right instruction */
750 ASSERT(Opcode == 0xF8);
751
752 /* No prefixes allowed */
753 if (State->PrefixFlags)
754 {
755 Soft386Exception(State, SOFT386_EXCEPTION_UD);
756 return FALSE;
757 }
758
759 /* Clear CF and return success */
760 State->Flags.Cf = FALSE;
761 return TRUE;
762 }
763
764 BOOLEAN
765 FASTCALL
766 Soft386OpcodeSetCarry(PSOFT386_STATE State, UCHAR Opcode)
767 {
768 /* Make sure this is the right instruction */
769 ASSERT(Opcode == 0xF9);
770
771 /* No prefixes allowed */
772 if (State->PrefixFlags)
773 {
774 Soft386Exception(State, SOFT386_EXCEPTION_UD);
775 return FALSE;
776 }
777
778 /* Set CF and return success*/
779 State->Flags.Cf = TRUE;
780 return TRUE;
781 }
782
783 BOOLEAN
784 FASTCALL
785 Soft386OpcodeClearInt(PSOFT386_STATE State, UCHAR Opcode)
786 {
787 /* Make sure this is the right instruction */
788 ASSERT(Opcode == 0xFA);
789
790 /* No prefixes allowed */
791 if (State->PrefixFlags)
792 {
793 Soft386Exception(State, SOFT386_EXCEPTION_UD);
794 return FALSE;
795 }
796
797 /* Check for protected mode */
798 if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
799 {
800 /* Check IOPL */
801 if (State->Flags.Iopl >= State->SegmentRegs[SOFT386_REG_CS].Dpl)
802 {
803 /* Clear the interrupt flag */
804 State->Flags.If = FALSE;
805 }
806 else
807 {
808 /* General Protection Fault */
809 Soft386Exception(State, SOFT386_EXCEPTION_GP);
810 return FALSE;
811 }
812 }
813 else
814 {
815 /* Just clear the interrupt flag */
816 State->Flags.If = FALSE;
817 }
818
819 /* Return success */
820 return TRUE;
821 }
822
823 BOOLEAN
824 FASTCALL
825 Soft386OpcodeSetInt(PSOFT386_STATE State, UCHAR Opcode)
826 {
827 /* Make sure this is the right instruction */
828 ASSERT(Opcode == 0xFB);
829
830 /* No prefixes allowed */
831 if (State->PrefixFlags)
832 {
833 Soft386Exception(State, SOFT386_EXCEPTION_UD);
834 return FALSE;
835 }
836
837 /* Check for protected mode */
838 if (State->ControlRegisters[SOFT386_REG_CR0] & SOFT386_CR0_PE)
839 {
840 /* Check IOPL */
841 if (State->Flags.Iopl >= State->SegmentRegs[SOFT386_REG_CS].Dpl)
842 {
843 /* Set the interrupt flag */
844 State->Flags.If = TRUE;
845 }
846 else
847 {
848 /* General Protection Fault */
849 Soft386Exception(State, SOFT386_EXCEPTION_GP);
850 return FALSE;
851 }
852 }
853 else
854 {
855 /* Just set the interrupt flag */
856 State->Flags.If = TRUE;
857 }
858
859 /* Return success */
860 return TRUE;
861 }
862
863 BOOLEAN
864 FASTCALL
865 Soft386OpcodeClearDir(PSOFT386_STATE State, UCHAR Opcode)
866 {
867 /* Make sure this is the right instruction */
868 ASSERT(Opcode == 0xFC);
869
870 /* No prefixes allowed */
871 if (State->PrefixFlags)
872 {
873 Soft386Exception(State, SOFT386_EXCEPTION_UD);
874 return FALSE;
875 }
876
877 /* Clear DF and return success */
878 State->Flags.Df = FALSE;
879 return TRUE;
880 }
881
882 BOOLEAN
883 FASTCALL
884 Soft386OpcodeSetDir(PSOFT386_STATE State, UCHAR Opcode)
885 {
886 /* Make sure this is the right instruction */
887 ASSERT(Opcode == 0xFD);
888
889 /* No prefixes allowed */
890 if (State->PrefixFlags)
891 {
892 Soft386Exception(State, SOFT386_EXCEPTION_UD);
893 return FALSE;
894 }
895
896 /* Set DF and return success*/
897 State->Flags.Df = TRUE;
898 return TRUE;
899 }
900
901 BOOLEAN
902 FASTCALL
903 Soft386OpcodeHalt(PSOFT386_STATE State, UCHAR Opcode)
904 {
905 /* Make sure this is the right instruction */
906 ASSERT(Opcode == 0xF4);
907
908 /* No prefixes allowed */
909 if (State->PrefixFlags)
910 {
911 Soft386Exception(State, SOFT386_EXCEPTION_UD);
912 return FALSE;
913 }
914
915 /* Privileged instructions can only be executed under CPL = 0 */
916 if (State->SegmentRegs[SOFT386_REG_CS].Dpl != 0)
917 {
918 Soft386Exception(State, SOFT386_EXCEPTION_GP);
919 return FALSE;
920 }
921
922 /* Halt */
923 while (!State->HardwareInt) State->IdleCallback(State);
924
925 /* Return success */
926 return TRUE;
927 }