Clean up emulator internal error messages
[jpcrr.git] / org / jpc / emulator / processor / Processor.java
blobae292f1747d97cc6cf8bae24569e771099fd26a9
1 /*
2 JPC-RR: A x86 PC Hardware Emulator
3 Release 1
5 Copyright (C) 2007-2009 Isis Innovation Limited
6 Copyright (C) 2009 H. Ilari Liusvaara
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License version 2 as published by
10 the Free Software Foundation.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 Based on JPC x86 PC Hardware emulator,
22 A project from the Physics Dept, The University of Oxford
24 Details about original JPC can be found at:
26 www-jpc.physics.ox.ac.uk
30 package org.jpc.emulator.processor;
32 import org.jpc.emulator.HardwareComponent;
33 import org.jpc.emulator.motherboard.*;
34 import org.jpc.emulator.memory.*;
35 import org.jpc.emulator.processor.fpu64.*;
36 import org.jpc.emulator.Clock;
37 import org.jpc.emulator.SRLoader;
38 import org.jpc.emulator.SRDumper;
39 import org.jpc.emulator.StatusDumper;
41 import java.io.*;
42 import java.util.*;
44 /**
46 * @author Chris Dennis
47 * @author Ian Preston
49 public class Processor implements HardwareComponent
51 public static final int STATE_VERSION = 1;
52 public static final int STATE_MINOR_VERSION = 0;
54 public int clockDivider; //CPU "Clock Speed" divider (yes, divider, not multiplier).
55 public static final int IFLAGS_HARDWARE_INTERRUPT = 0x1;
56 public static final int IFLAGS_PROCESSOR_EXCEPTION = 0x2;
57 public static final int IFLAGS_RESET_REQUEST = 0x4;
58 public static final int IFLAGS_IOPL_MASK = 3 << 12;
60 public static final int CR0_PROTECTION_ENABLE = 0x1;
61 public static final int CR0_MONITOR_COPROCESSOR = 0x2;
62 public static final int CR0_FPU_EMULATION = 0x4;
63 public static final int CR0_TASK_SWITCHED = 0x8;
64 public static final int CR0_EXTENSION_TYPE = 0x10;
65 public static final int CR0_NUMERIC_ERROR = 0x20;
66 public static final int CR0_WRITE_PROTECT = 0x10000;
67 public static final int CR0_ALIGNMENT_MASK = 0x40000;
68 public static final int CR0_NOT_WRITETHROUGH = 0x20000000;
69 public static final int CR0_CACHE_DISABLE = 0x40000000;
70 public static final int CR0_PAGING = 0x80000000;
72 public static final int CR3_PAGE_CACHE_DISABLE = 0x10;
73 public static final int CR3_PAGE_WRITES_TRANSPARENT = 0x8;
75 public static final int CR4_VIRTUAL8086_MODE_EXTENSIONS = 0x1;
76 public static final int CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS = 0x2;
77 public static final int CR4_TIME_STAMP_DISABLE = 0x4;
78 public static final int CR4_DEBUGGING_EXTENSIONS = 0x8;
79 public static final int CR4_PAGE_SIZE_EXTENSIONS = 0x10;
80 public static final int CR4_PHYSICAL_ADDRESS_EXTENSION = 0x20;
81 public static final int CR4_MACHINE_CHECK_ENABLE = 0x40;
82 public static final int CR4_PAGE_GLOBAL_ENABLE = 0x80;
83 public static final int CR4_PERFORMANCE_MONITORING_COUNTER_ENABLE = 0x100;
84 public static final int CR4_OS_SUPPORT_FXSAVE_FXSTORE = 0x200;
85 public static final int CR4_OS_SUPPORT_UNMASKED_SIMD_EXCEPTIONS = 0x400;
87 public static final int SYSENTER_CS_MSR = 0x174;
88 public static final int SYSENTER_ESP_MSR = 0x175;
89 public static final int SYSENTER_EIP_MSR = 0x176;
91 public long instructionsExecuted;
92 public int eax, ebx, edx, ecx;
93 public int esi, edi, esp, ebp;
94 public int eip;
96 private int cr0, cr1, cr2, cr3, cr4;
97 public int dr0, dr1, dr2, dr3, dr4, dr5, dr6, dr7;
99 public Segment cs, ds, ss, es, fs, gs;
100 public Segment idtr, gdtr, ldtr, tss;
102 //protected int eflags;
103 //program status and control register
104 public boolean eflagsCarry; //done
105 public boolean eflagsParity; //done
106 public boolean eflagsAuxiliaryCarry; //done
107 public boolean eflagsZero; //to do
108 public boolean eflagsSign; //to do
109 public boolean eflagsTrap;
110 public boolean eflagsInterruptEnable;
111 public boolean eflagsDirection;
112 public boolean eflagsOverflow; //done
113 public int eflagsIOPrivilegeLevel;
114 public boolean eflagsNestedTask;
115 public boolean eflagsResume;
116 public boolean eflagsVirtual8086Mode;
117 public boolean eflagsAlignmentCheck;
118 public boolean eflagsVirtualInterrupt;
119 public boolean eflagsVirtualInterruptPending;
120 public boolean eflagsID;
121 public boolean eflagsInterruptEnableSoon;
122 public boolean eflagsMachineHalt; //Machine Halting.
123 public boolean eflagsLastAborted; //Last block aborted. No need to save this.
124 public boolean eflagsWaiting; //Machine is in WAIT. This needs to be saved.
126 public LinearAddressSpace linearMemory;
127 public PhysicalAddressSpace physicalMemory;
128 public AlignmentCheckedAddressSpace alignmentCheckedMemory;
129 public IOPortHandler ioports;
131 private volatile int interruptFlags;
132 private InterruptController interruptController;
133 private boolean alignmentChecking;
135 private Map<Integer, Long> modelSpecificRegisters;
137 private long resetTime;
138 private int currentPrivilegeLevel;
139 private boolean started = false;
140 private Clock vmClock;
142 public FpuState fpu;
144 private long fpuUsedNotPresent; //Not saved.
145 private long fpuUsedNotPresentCount; //Not saved.
146 private static final long FPU_USED_SILENCE_TIME = 50000;
148 public static class TripleFault extends IllegalStateException
150 private static final long serialVersionUID = 7;
151 public TripleFault(String message)
153 super(message);
157 public Processor(Clock clock, int cpuClockDivider)
159 vmClock = clock;
160 clockDivider = cpuClockDivider;
161 fpu = null;
162 linearMemory = null;
163 physicalMemory = null;
164 alignmentCheckedMemory = null;
165 ioports = null;
166 alignmentChecking = false;
167 modelSpecificRegisters = new HashMap<Integer, Long>();
168 if(fpu != null) {
169 fpu.init();
170 cr0 |= CR0_EXTENSION_TYPE;
171 } else
172 cr0 |= CR0_FPU_EMULATION;
175 public void setFPU(FpuState newFPU)
177 fpu = newFPU;
178 if(fpu != null) {
179 fpu.init();
180 cr0 |= CR0_EXTENSION_TYPE;
181 cr0 &= ~CR0_FPU_EMULATION;
182 } else {
183 cr0 |= CR0_FPU_EMULATION;
184 cr0 &= ~CR0_EXTENSION_TYPE;
188 public void printState()
190 System.out.println("********************************");
191 System.out.println("CPU State:");
192 if (isProtectedMode())
193 if (isVirtual8086Mode())
194 System.out.println("Virtual8086 Mode");
195 else
196 System.out.println("Protected Mode");
197 else
198 System.out.println("Real Mode");
199 System.out.println("EAX: " + Integer.toHexString(eax));
200 System.out.println("EBX: " + Integer.toHexString(ebx));
201 System.out.println("EDX: " + Integer.toHexString(edx));
202 System.out.println("ECX: " + Integer.toHexString(ecx));
203 System.out.println("ESI: " + Integer.toHexString(esi));
204 System.out.println("EDI: " + Integer.toHexString(edi));
205 System.out.println("ESP: " + Integer.toHexString(esp));
206 System.out.println("EBP: " + Integer.toHexString(ebp));
207 System.out.println("EIP: " + Integer.toHexString(eip));
208 System.out.println("EFLAGS: " + Integer.toHexString(getEFlags()));
209 System.out.println("CS selector-base: " + Integer.toHexString(cs.getSelector()) + "-" + Integer.toHexString(cs.getBase()) + " (" + cs.getClass().toString() + ")");
210 System.out.println("DS selector-base: " + Integer.toHexString(ds.getSelector()) + "-" + Integer.toHexString(ds.getBase()) + " (" + cs.getClass().toString() + ")");
211 System.out.println("ES selector-base: " + Integer.toHexString(es.getSelector()) + "-" + Integer.toHexString(es.getBase()) + " (" + cs.getClass().toString() + ")");
212 System.out.println("FS selector-base: " + Integer.toHexString(fs.getSelector()) + "-" + Integer.toHexString(fs.getBase()) + " (" + cs.getClass().toString() + ")");
213 System.out.println("GS selector-base: " + Integer.toHexString(gs.getSelector()) + "-" + Integer.toHexString(gs.getBase()) + " (" + cs.getClass().toString() + ")");
214 System.out.println("SS selector-base: " + Integer.toHexString(ss.getSelector()) + "-" + Integer.toHexString(ss.getBase()) + " (" + cs.getClass().toString() + ")");
215 System.out.println("GDTR base-limit: " + Integer.toHexString(gdtr.getBase()) + "-" + Integer.toHexString(gdtr.getLimit()) + " (" + cs.getClass().toString() + ")");
216 System.out.println("IDTR base-limit: " + Integer.toHexString(idtr.getBase()) + "-" + Integer.toHexString(idtr.getLimit()) + " (" + cs.getClass().toString() + ")");
217 if (ldtr == SegmentFactory.NULL_SEGMENT)
218 System.out.println("Null LDTR");
219 else
220 System.out.println("LDTR base-limit: " + Integer.toHexString(ldtr.getBase()) + "-" + Integer.toHexString(ldtr.getLimit()) + " (" + cs.getClass().toString() + ")");
221 if (tss == SegmentFactory.NULL_SEGMENT)
222 System.out.println("Null TSS");
223 else
224 System.out.println("TSS selector-base: " + Integer.toHexString(tss.getSelector()) + "-" + Integer.toHexString(tss.getBase()) + " (" + cs.getClass().toString() + ")");
225 System.out.println("CR0: " + Integer.toHexString(cr0));
226 System.out.println("CR1: " + Integer.toHexString(cr1));
227 System.out.println("CR2: " + Integer.toHexString(cr2));
228 System.out.println("CR3: " + Integer.toHexString(cr3));
229 System.out.println("CR4: " + Integer.toHexString(cr4));
230 System.out.println("Executed: " + instructionsExecuted);
231 System.out.println("********************************");
234 public void dumpStatusPartial(StatusDumper output)
236 output.println("\tinstructionsExecuted " + instructionsExecuted);
237 output.println("\teax " + eax + " ebx " + ebx + " ecx " + ecx + " edx " + edx + " esi " + esi + " edi " + edi);
238 output.println("\tesp " + esp + " ebp " + ebp + " eip " + eip + " cr0 " + cr0 + " cr1 " + cr1 + " cr2 " + cr2);
239 output.println("\tcr3 " + cr3 + " cr4 " + cr4 + " dr0 " + dr0 + " dr1 " + dr1 + " dr2 " + dr2 + " dr3 " + dr3);
240 output.println("\tdr4 " + dr4 + " dr5 " + dr5 + " dr6 " + dr6 + " dr7 " + dr7);
241 output.println("\teflags:" +
242 (eflagsCarry ? " CARRY" : "") + (eflagsParity ? " PARITY" : "") +
243 (eflagsAuxiliaryCarry ? " AUXCARRY" : "") + (eflagsZero ? " ZERO" : "") +
244 (eflagsSign ? " SIGN" : "") + (eflagsTrap ? " TRAP" : "") +
245 (eflagsInterruptEnable ? " INTENABLE" : "") + (eflagsDirection ? " DIRECTION" : "") +
246 (eflagsOverflow ? " OVERFLOW" : "") + " IOPL" + eflagsIOPrivilegeLevel +
247 (eflagsNestedTask ? " NESTED" : "") + (eflagsResume ? " RESUME" : "") +
248 (eflagsVirtual8086Mode? " VM86" : "") + (eflagsAlignmentCheck ? " ALIGN" : "") +
249 (eflagsVirtualInterrupt? " VINTENABLE" : "") + (eflagsVirtualInterruptPending ? " VINTPENDING" : "") +
250 (eflagsID? " IDFLAG" : "") + (eflagsInterruptEnableSoon ? " INTENABLESOON" : ""));
251 output.println("\tinterruptFlags " + interruptFlags + " alignmentChecking " + alignmentChecking);
252 output.println("\tresetTime" + resetTime + " currentPrivilegeLevel " + currentPrivilegeLevel);
253 output.println("\tstarted " + started + " clockDivider " + clockDivider);
254 output.println("\toverflowOne " + overflowOne + " overflowTwo " + overflowTwo);
255 output.println("\toverflowThree " + overflowThree + " overflowLong " + overflowLong);
256 output.println("\toverflowCalculated " + overflowCalculated + " overflowMethod " + overflowMethod);
257 output.println("\tauxiliaryCarryOne " + auxiliaryCarryOne + " auxiliaryCarryTwo " + auxiliaryCarryTwo);
258 output.println("\tauxiliaryCarryThree " + overflowThree + " auxiliaryCarryMethod " + auxiliaryCarryMethod);
259 output.println("\tauxiliaryCarryCalculated " + auxiliaryCarryCalculated + " zeroOne " + zeroOne);
260 output.println("\tzeroCalculated " + zeroCalculated + " carryMethod " + carryMethod);
261 output.println("\tcarryCalculated " + carryCalculated + " carryLong " + carryLong);
262 output.println("\tcarryOne " + carryOne + " carryTwo " + carryTwo);
263 output.println("\tcs <object #" + output.objectNumber(cs) + ">"); if(cs != null) cs.dumpStatus(output);
264 output.println("\tds <object #" + output.objectNumber(ds) + ">"); if(ds != null) ds.dumpStatus(output);
265 output.println("\tes <object #" + output.objectNumber(es) + ">"); if(es != null) es.dumpStatus(output);
266 output.println("\tfs <object #" + output.objectNumber(fs) + ">"); if(fs != null) fs.dumpStatus(output);
267 output.println("\tgs <object #" + output.objectNumber(gs) + ">"); if(gs != null) gs.dumpStatus(output);
268 output.println("\tss <object #" + output.objectNumber(ss) + ">"); if(ss != null) ss.dumpStatus(output);
269 output.println("\tidtr <object #" + output.objectNumber(idtr) + ">"); if(idtr != null) idtr.dumpStatus(output);
270 output.println("\tgdtr <object #" + output.objectNumber(gdtr) + ">"); if(gdtr != null) gdtr.dumpStatus(output);
271 output.println("\tldtr <object #" + output.objectNumber(ldtr) + ">"); if(ldtr != null) ldtr.dumpStatus(output);
272 output.println("\ttss <object #" + output.objectNumber(tss) + ">"); if(tss != null) tss.dumpStatus(output);
273 output.println("\tlinearMemory <object #" + output.objectNumber(linearMemory) + ">"); if(linearMemory != null) linearMemory.dumpStatus(output);
274 output.println("\tphysicalMemory <object #" + output.objectNumber(physicalMemory) + ">"); if(physicalMemory != null) physicalMemory.dumpStatus(output);
275 output.println("\talignmentCheckedMemory <object #" + output.objectNumber(alignmentCheckedMemory) + ">"); if(alignmentCheckedMemory != null) alignmentCheckedMemory.dumpStatus(output);
276 output.println("\tioports <object #" + output.objectNumber(ioports) + ">"); if(ioports != null) ioports.dumpStatus(output);
277 output.println("\tinterruptController <object #" + output.objectNumber(interruptController) + ">"); if(interruptController != null) interruptController.dumpStatus(output);
278 output.println("\tvmClock <object #" + output.objectNumber(vmClock) + ">"); if(vmClock != null) vmClock.dumpStatus(output);
279 output.println("\tfpu <object #" + output.objectNumber(fpu) + ">"); if(fpu != null) fpu.dumpStatus(output);
280 output.println("\tmodelSpecificRegisters:");
281 Set<Map.Entry<Integer, Long> > entries = modelSpecificRegisters.entrySet();
282 Iterator<Map.Entry<Integer, Long> > itt = entries.iterator();
283 while (itt.hasNext())
285 Map.Entry<Integer, Long> entry = itt.next();
286 output.println("\t\t" + entry.getKey().intValue() + " -> " + entry.getValue().longValue());
288 output.println("\teflagsMachineHalt " + eflagsMachineHalt);
289 output.println("\teflagsLastAborted " + eflagsLastAborted + " eflagsWaiting " + eflagsWaiting);
292 public void dumpStatus(StatusDumper output)
294 if(output.dumped(this))
295 return;
296 output.println("#" + output.objectNumber(this) + ": Processor:");
297 dumpStatusPartial(output);
298 output.endObject();
301 public void dumpSRPartial(SRDumper output) throws IOException
303 output.dumpLong(instructionsExecuted);
304 output.dumpInt(eax);
305 output.dumpInt(ebx);
306 output.dumpInt(edx);
307 output.dumpInt(ecx);
308 output.dumpInt(esi);
309 output.dumpInt(edi);
310 output.dumpInt(esp);
311 output.dumpInt(ebp);
312 output.dumpInt(eip);
313 output.dumpInt(cr0);
314 output.dumpInt(cr1);
315 output.dumpInt(cr2);
316 output.dumpInt(cr3);
317 output.dumpInt(cr4);
318 output.dumpInt(dr0);
319 output.dumpInt(dr1);
320 output.dumpInt(dr2);
321 output.dumpInt(dr3);
322 output.dumpInt(dr4);
323 output.dumpInt(dr5);
324 output.dumpInt(dr6);
325 output.dumpInt(dr7);
326 output.dumpObject(cs);
327 output.dumpObject(ds);
328 output.dumpObject(ss);
329 output.dumpObject(es);
330 output.dumpObject(fs);
331 output.dumpObject(gs);
332 output.dumpObject(idtr);
333 output.dumpObject(gdtr);
334 output.dumpObject(ldtr);
335 output.dumpObject(tss);
336 output.dumpInt(clockDivider);
337 output.dumpBoolean(eflagsCarry);
338 output.dumpBoolean(eflagsParity);
339 output.dumpBoolean(eflagsAuxiliaryCarry);
340 output.dumpBoolean(eflagsZero);
341 output.dumpBoolean(eflagsSign);
342 output.dumpBoolean(eflagsTrap);
343 output.dumpBoolean(eflagsInterruptEnable);
344 output.dumpBoolean(eflagsDirection);
345 output.dumpBoolean(eflagsOverflow);
346 output.dumpInt(eflagsIOPrivilegeLevel);
347 output.dumpBoolean(eflagsNestedTask);
348 output.dumpBoolean(eflagsResume);
349 output.dumpBoolean(eflagsVirtual8086Mode);
350 output.dumpBoolean(eflagsAlignmentCheck);
351 output.dumpBoolean(eflagsVirtualInterrupt);
352 output.dumpBoolean(eflagsVirtualInterruptPending);
353 output.dumpBoolean(eflagsID);
354 output.dumpBoolean(eflagsInterruptEnableSoon);
355 output.dumpObject(linearMemory);
356 output.dumpObject(physicalMemory);
357 output.dumpObject(alignmentCheckedMemory);
358 output.dumpObject(ioports);
359 output.dumpInt(interruptFlags);
360 output.dumpObject(interruptController);
361 output.dumpObject(vmClock);
362 output.dumpBoolean(alignmentChecking);
363 output.dumpLong(resetTime);
364 output.dumpInt(currentPrivilegeLevel);
365 output.dumpBoolean(started);
366 output.dumpObject(fpu);
367 output.dumpInt(parityOne);
368 output.dumpBoolean(parityCalculated);
369 output.dumpInt(auxiliaryCarryOne);
370 output.dumpInt(auxiliaryCarryTwo);
371 output.dumpInt(auxiliaryCarryThree);
372 output.dumpBoolean(auxiliaryCarryCalculated);
373 output.dumpInt(auxiliaryCarryMethod);
374 output.dumpInt(overflowOne);
375 output.dumpInt(overflowTwo);
376 output.dumpInt(overflowThree);
377 output.dumpLong(overflowLong);
378 output.dumpBoolean(overflowCalculated);
379 output.dumpInt(overflowMethod);
380 output.dumpInt(carryOne);
381 output.dumpInt(carryTwo);
382 output.dumpLong(carryLong);
383 output.dumpBoolean(carryCalculated);
384 output.dumpInt(carryMethod);
385 output.dumpInt(zeroOne);
386 output.dumpBoolean(zeroCalculated);
387 output.dumpInt(signOne);
388 output.dumpBoolean(signCalculated);
390 Set<Map.Entry<Integer,Long> > entries = modelSpecificRegisters.entrySet();
391 Iterator<Map.Entry<Integer,Long> > itt = entries.iterator();
392 while (itt.hasNext())
394 Map.Entry<Integer,Long> entry = itt.next();
395 output.dumpBoolean(true);
396 output.dumpInt(entry.getKey().intValue());
397 output.dumpLong(entry.getValue().longValue());
399 output.dumpBoolean(false);
400 output.dumpBoolean(eflagsWaiting);
403 public Processor(SRLoader input) throws IOException
405 input.objectCreated(this);
406 instructionsExecuted = input.loadLong();
407 eax = input.loadInt();
408 ebx = input.loadInt();
409 edx = input.loadInt();
410 ecx = input.loadInt();
411 esi = input.loadInt();
412 edi = input.loadInt();
413 esp = input.loadInt();
414 ebp = input.loadInt();
415 eip = input.loadInt();
416 cr0 = input.loadInt();
417 cr1 = input.loadInt();
418 cr2 = input.loadInt();
419 cr3 = input.loadInt();
420 cr4 = input.loadInt();
421 dr0 = input.loadInt();
422 dr1 = input.loadInt();
423 dr2 = input.loadInt();
424 dr3 = input.loadInt();
425 dr4 = input.loadInt();
426 dr5 = input.loadInt();
427 dr6 = input.loadInt();
428 dr7 = input.loadInt();
429 cs = (Segment)input.loadObject();
430 ds = (Segment)input.loadObject();
431 ss = (Segment)input.loadObject();
432 es = (Segment)input.loadObject();
433 fs = (Segment)input.loadObject();
434 gs = (Segment)input.loadObject();
435 idtr = (Segment)input.loadObject();
436 gdtr = (Segment)input.loadObject();
437 ldtr = (Segment)input.loadObject();
438 tss = (Segment)input.loadObject();
439 clockDivider = input.loadInt();
440 eflagsCarry = input.loadBoolean();
441 eflagsParity = input.loadBoolean();
442 eflagsAuxiliaryCarry = input.loadBoolean();
443 eflagsZero = input.loadBoolean();
444 eflagsSign = input.loadBoolean();
445 eflagsTrap = input.loadBoolean();
446 eflagsInterruptEnable = input.loadBoolean();
447 eflagsDirection = input.loadBoolean();
448 eflagsOverflow = input.loadBoolean();
449 eflagsIOPrivilegeLevel = input.loadInt();
450 eflagsNestedTask = input.loadBoolean();
451 eflagsResume = input.loadBoolean();
452 eflagsVirtual8086Mode = input.loadBoolean();
453 eflagsAlignmentCheck = input.loadBoolean();
454 eflagsVirtualInterrupt = input.loadBoolean();
455 eflagsVirtualInterruptPending = input.loadBoolean();
456 eflagsID = input.loadBoolean();
457 eflagsInterruptEnableSoon = input.loadBoolean();
458 linearMemory = (LinearAddressSpace)input.loadObject();
459 physicalMemory = (PhysicalAddressSpace)input.loadObject();
460 alignmentCheckedMemory = (AlignmentCheckedAddressSpace)input.loadObject();
461 ioports = (IOPortHandler)input.loadObject();
462 interruptFlags = input.loadInt();
463 interruptController = (InterruptController)input.loadObject();
464 vmClock = (Clock)input.loadObject();
465 alignmentChecking = input.loadBoolean();
466 resetTime = input.loadLong();
467 currentPrivilegeLevel = input.loadInt();
468 started = input.loadBoolean();
469 fpu = (FpuState)input.loadObject();
470 parityOne = input.loadInt();
471 parityCalculated = input.loadBoolean();
472 auxiliaryCarryOne = input.loadInt();
473 auxiliaryCarryTwo = input.loadInt();
474 auxiliaryCarryThree = input.loadInt();
475 auxiliaryCarryCalculated = input.loadBoolean();
476 auxiliaryCarryMethod = input.loadInt();
477 overflowOne = input.loadInt();
478 overflowTwo = input.loadInt();
479 overflowThree = input.loadInt();
480 overflowLong = input.loadLong();
481 overflowCalculated = input.loadBoolean();
482 overflowMethod = input.loadInt();
483 carryOne = input.loadInt();
484 carryTwo = input.loadInt();
485 carryLong = input.loadLong();
486 carryCalculated = input.loadBoolean();
487 carryMethod = input.loadInt();
488 zeroOne = input.loadInt();
489 zeroCalculated = input.loadBoolean();
490 signOne = input.loadInt();
491 signCalculated = input.loadBoolean();
493 modelSpecificRegisters = new HashMap<Integer, Long>();
494 boolean present = input.loadBoolean();
495 while (present)
497 int key = input.loadInt();
498 long value = input.loadLong();
499 modelSpecificRegisters.put(key, value);
501 eflagsWaiting = input.loadBoolean();
505 public int getIOPrivilegeLevel()
507 return eflagsIOPrivilegeLevel;
510 public int getEFlags()
512 int result = 0x2;
513 if (getCarryFlag())
514 result |= 0x1;
515 if (getParityFlag())
516 result |= 0x4;
517 if (getAuxiliaryCarryFlag())
518 result |= 0x10;
519 if (getZeroFlag())
520 result |= 0x40;
521 if (getSignFlag())
522 result |= 0x80;
523 if (eflagsTrap)
524 result |= 0x100;
525 if (eflagsInterruptEnable)
526 result |= 0x200;
527 if (eflagsDirection)
528 result |= 0x400;
529 if (getOverflowFlag())
530 result |= 0x800;
531 result |= (eflagsIOPrivilegeLevel << 12);
532 if (eflagsNestedTask)
533 result |= 0x4000;
534 if (eflagsResume)
535 result |= 0x10000;
536 if (eflagsVirtual8086Mode)
537 result |= 0x20000;
538 if (eflagsAlignmentCheck)
539 result |= 0x40000;
540 if (eflagsVirtualInterrupt)
541 result |= 0x80000;
542 if (eflagsVirtualInterruptPending)
543 result |= 0x100000;
544 if (eflagsID)
545 result |= 0x200000;
547 return result;
550 public void setEFlags(int eflags)
552 // TODO: check that there aren't flags which can't be set this way!
553 setCarryFlag((eflags & 1 ) != 0);
554 setParityFlag((eflags & (1 << 2)) != 0);
555 setAuxiliaryCarryFlag((eflags & (1 << 4)) != 0);
556 setZeroFlag((eflags & (1 << 6)) != 0);
557 setSignFlag((eflags & (1 << 7)) != 0);
558 eflagsTrap = ((eflags & (1 << 8)) != 0);
559 eflagsInterruptEnableSoon
560 = eflagsInterruptEnable = ((eflags & (1 << 9)) != 0);
561 eflagsDirection = ((eflags & (1 << 10)) != 0);
562 setOverflowFlag((eflags & (1 << 11)) != 0);
563 eflagsIOPrivilegeLevel = ((eflags >> 12) & 3);
564 eflagsNestedTask = ((eflags & (1 << 14)) != 0);
565 eflagsResume = ((eflags & (1 << 16)) != 0);
567 eflagsVirtualInterrupt = ((eflags & (1 << 19)) != 0);
568 eflagsVirtualInterruptPending = ((eflags & (1 << 20)) != 0);
569 eflagsID = ((eflags & (1 << 21)) != 0);
571 if (eflagsAlignmentCheck != ((eflags & (1 << 18)) != 0)) {
572 eflagsAlignmentCheck = ((eflags & (1 << 18)) != 0);
573 checkAlignmentChecking();
576 if (eflagsVirtual8086Mode != ((eflags & (1 << 17)) != 0)) {
577 eflagsVirtual8086Mode = ((eflags & (1 << 17)) != 0);
578 if (eflagsVirtual8086Mode) {
579 throw ModeSwitchException.VIRTUAL8086_MODE_EXCEPTION;
580 } else {
581 throw ModeSwitchException.PROTECTED_MODE_EXCEPTION;
586 public void setCPL(int value)
588 currentPrivilegeLevel = value;
589 linearMemory.setSupervisor(currentPrivilegeLevel == 0);
590 checkAlignmentChecking();
593 public int getCPL()
595 return currentPrivilegeLevel;
598 public void reportFPUException()
600 if ((cr0 & CR0_NUMERIC_ERROR) == 0) {
601 System.err.println("Emulated: Reporting FPU error via IRQ #13");
602 interruptController.setIRQ(13, 1);
603 } else {
604 System.err.println("Emulated: Reporting FPU error via exception 0x10");
605 throw ProcessorException.FLOATING_POINT;
609 public void raiseInterrupt()
611 interruptFlags |= IFLAGS_HARDWARE_INTERRUPT;
614 public void clearInterrupt()
616 interruptFlags &= ~IFLAGS_HARDWARE_INTERRUPT;
619 public void waitForInterrupt()
621 eflagsWaiting = true;
623 if(eflagsInterruptEnableSoon)
624 eflagsInterruptEnable = true; //Force to enable interrupts in this case.
626 while((interruptFlags & IFLAGS_HARDWARE_INTERRUPT) == 0) {
627 Clock.timePasses(vmClock, this.clockDivider);
628 //If machine is halting, raise special TR exception. We will get called again.
629 if(eflagsMachineHalt) {
630 System.err.println("Informational: HALT aborted.");
631 throw ProcessorException.TRACESTOP;
634 eflagsWaiting = false;
636 if (isProtectedMode()) {
637 if (isVirtual8086Mode()) {
638 processProtectedModeInterrupts(0);
639 } else {
640 processProtectedModeInterrupts(0);
642 } else {
643 processRealModeInterrupts(0);
647 public void instructionExecuted()
649 Clock.timePasses(vmClock, this.clockDivider);
652 public void useFPU(boolean fwait)
654 if(fpu == null || (cr0 & CR0_FPU_EMULATION) != 0) {
655 if(fpu == null) {
656 fpuUsedNotPresentCount++;
657 if(fpuUsedNotPresent == 0 || vmClock.getTime() > fpuUsedNotPresent + FPU_USED_SILENCE_TIME) {
658 fpuUsedNotPresent = vmClock.getTime();
659 System.err.println("Warning: FPU used but not present (" + fpuUsedNotPresentCount +
660 "times already).");
663 throw ProcessorException.FPU_NA_0;
666 if(fwait && (cr0 & CR0_MONITOR_COPROCESSOR) == 0)
667 return; /* Waits with TS and not MP are OK. */
669 if((cr0 & CR0_TASK_SWITCHED) != 0)
670 throw ProcessorException.FPU_NA_0;
672 return;
675 public void requestReset()
677 interruptFlags |= IFLAGS_RESET_REQUEST;
680 public boolean isProtectedMode()
682 return (cr0 & CR0_PROTECTION_ENABLE) == 1;
685 public boolean isVirtual8086Mode()
687 return eflagsVirtual8086Mode;
690 // Need to think about the TS flag for when we have an FPU - Section 2.5 Vol 3
691 public void setCR0(int value)
693 value |= 0x10;
694 int changedBits = value ^ cr0;
695 if (changedBits == 0)
696 return;
698 //actually set the value!
699 cr0 = value;
701 boolean pagingChanged = (changedBits & CR0_PAGING) != 0;
702 boolean cachingChanged = (changedBits & CR0_CACHE_DISABLE) != 0;
703 boolean modeSwitch = (changedBits & CR0_PROTECTION_ENABLE) != 0;
704 boolean wpUserPagesChanged = (changedBits & CR0_WRITE_PROTECT) != 0;
705 boolean alignmentChanged = (changedBits & CR0_ALIGNMENT_MASK) != 0;
707 if ((changedBits & CR0_NOT_WRITETHROUGH)!= 0)
708 System.err.println("Warning: Unimplemented CR0 flags change " + Integer.toHexString(changedBits) + ". " +
709 "Value now is " + Integer.toHexString(value) + ".");
711 if (pagingChanged) {
712 if (((value & CR0_PROTECTION_ENABLE) == 0) && ((value & CR0_PAGING) != 0))
713 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
716 if (alignmentChanged)
717 checkAlignmentChecking();
719 if (pagingChanged || cachingChanged) {
720 linearMemory.setPagingEnabled((value & CR0_PAGING) != 0);
721 linearMemory.setPageCacheEnabled((value & CR0_CACHE_DISABLE) == 0);
724 if (wpUserPagesChanged)
725 linearMemory.setWriteProtectUserPages((value & CR0_WRITE_PROTECT) != 0);
727 if (modeSwitch) {
728 if ((value & CR0_PROTECTION_ENABLE) != 0) {
729 convertSegmentsToProtectedMode();
730 throw ModeSwitchException.PROTECTED_MODE_EXCEPTION;
731 } else {
732 // linearMemory.flush();
733 setCPL(0);
734 convertSegmentsToRealMode();
735 throw ModeSwitchException.REAL_MODE_EXCEPTION;
740 public int getCR0()
742 return cr0;
745 public void setCR3(int value)
747 cr3 = value;
748 linearMemory.setPageWriteThroughEnabled((value & CR3_PAGE_WRITES_TRANSPARENT) != 0);
749 linearMemory.setPageCacheEnabled((value & CR3_PAGE_CACHE_DISABLE) == 0);
750 linearMemory.setPageDirectoryBaseAddress(value);
753 public int getCR3()
755 return cr3;
758 public int getCR2()
760 return cr2;
763 public void setCR2(int value)
765 cr2 = value;
768 public void setCR4(int value)
770 if (cr4 == value)
771 return;
773 cr4 = (cr4 & ~0x5f) | (value & 0x5f);
774 if ((cr4 & CR4_VIRTUAL8086_MODE_EXTENSIONS) != 0)
775 System.err.println("Warning: Virtual-8086 mode extensions enabled in the processor");
776 if ((cr4 & CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS) != 0)
777 System.err.println("Warning: Protected mode virtual interrupts enabled in the processor");
778 if ((cr4 & CR4_OS_SUPPORT_UNMASKED_SIMD_EXCEPTIONS) != 0)
779 System.err.println("Warning: SIMD instruction support modified in the processor");
780 if ((cr4 & CR4_OS_SUPPORT_FXSAVE_FXSTORE) != 0)
781 System.err.println("Warning: FXSave and FXRStore enabled in the processor");
782 if ((cr4 & CR4_DEBUGGING_EXTENSIONS) != 0)
783 System.err.println("Warning: Debugging extensions enabled");
784 if ((cr4 & CR4_TIME_STAMP_DISABLE) != 0)
785 System.err.println("Warning: Timestamp restricted to CPL0");
786 if ((cr4 & CR4_PHYSICAL_ADDRESS_EXTENSION) != 0) {
787 System.err.println("Critical error: 36-bit addressing enabled.");
788 throw new IllegalStateException("36-bit addressing not supported");
790 linearMemory.setGlobalPagesEnabled((value & CR4_PAGE_GLOBAL_ENABLE) != 0);
791 linearMemory.setPageSizeExtensionsEnabled((cr4 & CR4_PAGE_SIZE_EXTENSIONS) != 0);
794 public int getCR4()
796 return cr4;
799 public void setDR0(int value)
801 dr0 = value;
803 public void setDR1(int value)
805 dr1 = value;
807 public void setDR2(int value)
809 dr2 = value;
811 public void setDR3(int value)
813 dr3 = value;
815 public void setDR6(int value)
817 dr6 = value;
819 public void setDR7(int value)
821 dr7 = value;
824 public int getDR0()
826 return dr0;
828 public int getDR1()
830 return dr1;
832 public int getDR2()
834 return dr2;
836 public int getDR3()
838 return dr3;
840 public int getDR6()
842 return dr6;
844 public int getDR7()
846 return dr7;
849 public long getMSR(int index)
851 try {
852 return modelSpecificRegisters.get(Integer.valueOf(index)).longValue();
853 } catch (NullPointerException e) {
854 System.err.println("Emulated: Reading unset MSR " + index + ", giving 0.");
855 return 0L;
859 public void setMSR(int index, long value)
861 modelSpecificRegisters.put(Integer.valueOf(index), Long.valueOf(value));
864 private void convertSegmentsToRealMode()
868 cs = SegmentFactory.createRealModeSegment(physicalMemory, cs);
869 } catch (ProcessorException e)
871 cs = SegmentFactory.createRealModeSegment(physicalMemory, 0);
876 ds = SegmentFactory.createRealModeSegment(physicalMemory, ds);
877 } catch (ProcessorException e)
879 ds = SegmentFactory.createRealModeSegment(physicalMemory, 0);
884 ss = SegmentFactory.createRealModeSegment(physicalMemory, ss);
885 } catch (ProcessorException e)
887 ss = SegmentFactory.createRealModeSegment(physicalMemory, 0);
892 es = SegmentFactory.createRealModeSegment(physicalMemory, es);
893 } catch (ProcessorException e)
895 es = SegmentFactory.createRealModeSegment(physicalMemory, 0);
900 fs = SegmentFactory.createRealModeSegment(physicalMemory, fs);
901 } catch (ProcessorException e)
903 fs = SegmentFactory.createRealModeSegment(physicalMemory, 0);
908 gs = SegmentFactory.createRealModeSegment(physicalMemory, gs);
909 } catch (ProcessorException e)
911 gs = SegmentFactory.createRealModeSegment(physicalMemory, 0);
915 private void convertSegmentsToProtectedMode()
917 cs.setAddressSpace(linearMemory);
918 ds.setAddressSpace(linearMemory);
919 ss.setAddressSpace(linearMemory);
920 es.setAddressSpace(linearMemory);
921 fs.setAddressSpace(linearMemory);
922 gs.setAddressSpace(linearMemory);
925 private void updateAlignmentCheckingInDataSegments()
927 if (alignmentChecking)
929 ds.setAddressSpace(alignmentCheckedMemory);
930 ss.setAddressSpace(alignmentCheckedMemory);
931 es.setAddressSpace(alignmentCheckedMemory);
932 fs.setAddressSpace(alignmentCheckedMemory);
933 gs.setAddressSpace(alignmentCheckedMemory);
935 else
937 ds.setAddressSpace(linearMemory);
938 ss.setAddressSpace(linearMemory);
939 es.setAddressSpace(linearMemory);
940 fs.setAddressSpace(linearMemory);
941 gs.setAddressSpace(linearMemory);
945 public Segment createDescriptorTableSegment(int base, int limit)
947 return SegmentFactory.createDescriptorTableSegment(linearMemory, base, limit);
950 public void correctAlignmentChecking(Segment segment)
952 if (alignmentChecking) {
953 if ((segment.getType() & 0x18) == 0x10) // Should make this a data segment
954 segment.setAddressSpace(alignmentCheckedMemory);
958 public Segment getSegment(int segmentSelector)
960 boolean isSup = linearMemory.isSupervisor();
963 long segmentDescriptor = 0;
964 linearMemory.setSupervisor(true);
965 if ((segmentSelector & 0x4) != 0)
966 segmentDescriptor = ldtr.getQuadWord(segmentSelector & 0xfff8);
967 else
969 if (segmentSelector < 0x4)
970 return SegmentFactory.NULL_SEGMENT;
971 segmentDescriptor = gdtr.getQuadWord(segmentSelector & 0xfff8);
973 Segment result = SegmentFactory.createProtectedModeSegment(linearMemory, segmentSelector, segmentDescriptor);
974 if (alignmentChecking)
976 if ((result.getType() & 0x18) == 0x10) // Should make this a data segment
977 result.setAddressSpace(alignmentCheckedMemory);
980 return result;
982 finally
984 linearMemory.setSupervisor(isSup);
989 public Segment getSegment(int segmentSelector, Segment local, Segment global)
991 boolean isSup = linearMemory.isSupervisor();
994 long segmentDescriptor = 0;
995 linearMemory.setSupervisor(true);
996 if ((segmentSelector & 0x4) != 0)
997 segmentDescriptor = local.getQuadWord(segmentSelector & 0xfff8);
998 else
1000 if (segmentSelector < 0x4)
1001 return SegmentFactory.NULL_SEGMENT;
1002 segmentDescriptor = global.getQuadWord(segmentSelector & 0xfff8);
1005 Segment result = SegmentFactory.createProtectedModeSegment(linearMemory, segmentSelector, segmentDescriptor);
1006 if (alignmentChecking)
1008 if ((result.getType() & 0x18) == 0x10) // Should make this a data segment
1009 result.setAddressSpace(alignmentCheckedMemory);
1012 return result;
1014 finally
1016 linearMemory.setSupervisor(isSup);
1020 public void reset()
1022 resetTime = instructionsExecuted;
1023 eax = ebx = ecx = edx = 0;
1024 edi = esi = ebp = esp = 0;
1025 edx = 0x00000633; // Pentium II Model 3 Stepping 3
1027 interruptFlags = 0;
1028 currentPrivilegeLevel = 0;
1029 linearMemory.reset();
1030 alignmentChecking = false;
1032 eip = 0x0000fff0;
1034 cr0 = CR0_CACHE_DISABLE | CR0_NOT_WRITETHROUGH | 0x10;
1035 cr2 = cr3 = cr4 = 0x0;
1037 dr0 = dr1 = dr2 = dr3 = 0x0;
1038 dr6 = 0xffff0ff0;
1039 dr7 = 0x00000700;
1041 eflagsCarry = eflagsParity = eflagsAuxiliaryCarry = eflagsZero = eflagsSign = eflagsTrap = eflagsInterruptEnable = false;
1042 carryCalculated = parityCalculated = auxiliaryCarryCalculated = zeroCalculated = signCalculated = true;
1043 eflagsDirection = eflagsOverflow = eflagsNestedTask = eflagsResume = eflagsVirtual8086Mode = false;
1044 overflowCalculated = true;
1046 eflagsAlignmentCheck = eflagsVirtualInterrupt = eflagsVirtualInterruptPending = eflagsID = false;
1048 eflagsIOPrivilegeLevel = 0;
1049 eflagsInterruptEnableSoon = false;
1051 cs = SegmentFactory.createRealModeSegment(physicalMemory, 0xf000);
1052 ds = SegmentFactory.createRealModeSegment(physicalMemory, 0);
1053 ss = SegmentFactory.createRealModeSegment(physicalMemory, 0);
1054 es = SegmentFactory.createRealModeSegment(physicalMemory, 0);
1055 fs = SegmentFactory.createRealModeSegment(physicalMemory, 0);
1056 gs = SegmentFactory.createRealModeSegment(physicalMemory, 0);
1058 idtr = SegmentFactory.createDescriptorTableSegment(physicalMemory, 0, 0xFFFF);
1059 ldtr = SegmentFactory.NULL_SEGMENT;
1060 gdtr = SegmentFactory.createDescriptorTableSegment(physicalMemory, 0, 0xFFFF);
1061 tss = SegmentFactory.NULL_SEGMENT;
1063 modelSpecificRegisters.clear();
1064 //Will need to set any MSRs here
1066 if(fpu != null) {
1067 fpu.init();
1068 cr0 |= CR0_EXTENSION_TYPE;
1069 } else
1070 cr0 |= CR0_FPU_EMULATION;
1073 public long getClockCount()
1075 return instructionsExecuted - resetTime;
1078 public final int getInstructionPointer()
1080 return cs.translateAddressRead(eip);
1083 public final void processRealModeInterrupts(int instructions)
1085 //Note only hardware interrupts go here, software interrupts are handled in the codeblock
1086 if (eflagsInterruptEnable) {
1088 if ((interruptFlags & IFLAGS_RESET_REQUEST) != 0) {
1089 reset();
1090 return;
1093 if ((interruptFlags & IFLAGS_HARDWARE_INTERRUPT) != 0) {
1094 interruptFlags &= ~IFLAGS_HARDWARE_INTERRUPT;
1095 int vector = interruptController.cpuGetInterrupt();
1096 handleRealModeInterrupt(vector);
1099 eflagsInterruptEnable = eflagsInterruptEnableSoon;
1102 public final void processProtectedModeInterrupts(int instructions)
1104 if (eflagsInterruptEnable) {
1106 if ((interruptFlags & IFLAGS_RESET_REQUEST) != 0) {
1107 reset();
1108 return;
1111 if ((interruptFlags & IFLAGS_HARDWARE_INTERRUPT) != 0) {
1112 interruptFlags &= ~IFLAGS_HARDWARE_INTERRUPT;
1113 handleHardProtectedModeInterrupt(interruptController.cpuGetInterrupt());
1116 eflagsInterruptEnable = eflagsInterruptEnableSoon;
1119 public final void processVirtual8086ModeInterrupts(int instructions)
1121 if (eflagsInterruptEnable) {
1123 if ((interruptFlags & IFLAGS_RESET_REQUEST) != 0) {
1124 reset();
1125 return;
1128 if ((interruptFlags & IFLAGS_HARDWARE_INTERRUPT) != 0) {
1129 interruptFlags &= ~IFLAGS_HARDWARE_INTERRUPT;
1130 if ((getCR4() & CR4_VIRTUAL8086_MODE_EXTENSIONS) != 0) {
1131 System.err.println("Critical error: VM8086 extensions not supported.");
1132 throw new IllegalStateException("VM8086 extensions not supported");
1133 } else
1134 handleHardVirtual8086ModeInterrupt(interruptController.cpuGetInterrupt());
1138 eflagsInterruptEnable = eflagsInterruptEnableSoon;
1141 public final void handleRealModeException(ProcessorException e)
1143 handleRealModeInterrupt(e.getType().vector());
1146 private final void handleRealModeInterrupt(int vector)
1148 if (vector*4 +3 > idtr.getLimit())
1149 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);
1151 vector *= 4;
1152 int newEip = 0xffff & idtr.getWord(vector);
1153 int newSelector = 0xffff & idtr.getWord(vector+2);
1155 short sesp = (short) esp;
1156 sesp -= 2;
1157 int eflags = getEFlags() & 0xffff;
1158 ss.setWord(sesp & 0xffff, (short)eflags);
1159 eflagsInterruptEnable = false;
1160 eflagsInterruptEnableSoon = false;
1161 eflagsTrap = false;
1162 eflagsAlignmentCheck = false;
1163 eflagsResume=false;
1164 sesp -= 2;
1165 ss.setWord(sesp & 0xffff, (short)cs.getSelector());
1166 sesp -= 2;
1167 ss.setWord(sesp & 0xffff, (short)eip);
1168 esp = (0xFFFF0000 & esp) | (sesp & 0xFFFF);
1169 // read interrupt vector
1170 eip = newEip;
1172 if (!cs.setSelector(newSelector))
1174 System.err.println("Emulated: Setting CS to RM in RM interrupt");
1175 cs = SegmentFactory.createRealModeSegment(physicalMemory, newSelector);
1176 setCPL(0);
1180 public final void handleProtectedModeException(ProcessorException pe)
1182 int savedESP = esp;
1183 int savedEIP = eip;
1184 Segment savedCS = cs;
1185 Segment savedSS = ss;
1187 try {
1188 followProtectedModeException(pe.getType().vector(), pe.hasErrorCode(), pe.getErrorCode(), false, false);
1189 } catch (ProcessorException e) {
1190 System.err.println("Emulated: Double Fault: " + e);
1191 //return cpu to original state
1192 esp = savedESP;
1193 eip = savedEIP;
1194 cs = savedCS;
1195 ss = savedSS;
1197 if (pe.getType() == ProcessorException.Type.DOUBLE_FAULT) {
1198 System.err.println("Emulated: Triple fault. Unhandleable, CPU shutting down: " + e);
1199 throw new TripleFault("Triple Fault, CPU shutting down.");
1200 } else if (e.combinesToDoubleFault(pe))
1201 handleProtectedModeException(ProcessorException.DOUBLE_FAULT_0);
1202 else
1203 handleProtectedModeException(e);
1207 public final void handleSoftProtectedModeInterrupt(int vector, int instructionLength)
1209 int savedESP = esp;
1210 int savedEIP = eip;
1211 Segment savedCS = cs;
1212 Segment savedSS = ss;
1214 try {
1215 followProtectedModeException(vector, false, 0, false, true);
1216 } catch (ProcessorException e) {
1217 //return cpu to original state
1218 esp = savedESP;
1219 eip = savedEIP;
1220 cs = savedCS;
1221 ss = savedSS;
1223 //make eip point at INT instruction which threw an exception
1224 if (e.pointsToSelf())
1225 eip -= instructionLength;
1227 handleProtectedModeException(e);
1231 public final void handleHardProtectedModeInterrupt(int vector)
1233 int savedESP = esp;
1234 int savedEIP = eip;
1235 Segment savedCS = cs;
1236 Segment savedSS = ss;
1238 try {
1239 followProtectedModeException(vector, false, 0, true, false);
1240 } catch (ProcessorException e) {
1241 //return cpu to original state
1242 esp = savedESP;
1243 eip = savedEIP;
1244 cs = savedCS;
1245 ss = savedSS;
1247 handleProtectedModeException(e);
1251 private final void checkGate(Segment gate, int selector, boolean software)
1253 if (software) {
1254 if (gate.getDPL() < currentPrivilegeLevel)
1255 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, selector + 2, true);
1258 if (!gate.isPresent())
1259 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, selector +2, true);
1262 public final void setSupervisorQuadWord(Segment seg, int offset, long data)
1264 boolean isSup = linearMemory.isSupervisor();
1265 linearMemory.setSupervisor(true);
1266 seg.setQuadWord(offset, data);
1267 linearMemory.setSupervisor(isSup);
1270 public final void setSupervisorDoubleWord(Segment seg, int offset, int data)
1272 boolean isSup = linearMemory.isSupervisor();
1273 linearMemory.setSupervisor(true);
1274 seg.setDoubleWord(offset, data);
1275 linearMemory.setSupervisor(isSup);
1278 public final long readSupervisorQuadWord(Segment seg, int offset)
1280 boolean isSup = linearMemory.isSupervisor();
1281 linearMemory.setSupervisor(true);
1282 long data = seg.getQuadWord(offset);
1283 linearMemory.setSupervisor(isSup);
1284 return data;
1287 public final int readSupervisorDoubleWord(Segment seg, int offset)
1289 boolean isSup = linearMemory.isSupervisor();
1290 linearMemory.setSupervisor(true);
1291 int data = seg.getDoubleWord(offset);
1292 linearMemory.setSupervisor(isSup);
1293 return data;
1296 public final int readSupervisorWord(Segment seg, int offset)
1298 boolean isSup = linearMemory.isSupervisor();
1299 linearMemory.setSupervisor(true);
1300 int data = seg.getWord(offset);
1301 linearMemory.setSupervisor(isSup);
1302 return data;
1305 public final int readSupervisorByte(Segment seg, int offset)
1307 boolean isSup = linearMemory.isSupervisor();
1308 linearMemory.setSupervisor(true);
1309 int data = seg.getByte(offset);
1310 linearMemory.setSupervisor(isSup);
1311 return data;
1314 private final void followProtectedModeException(int vector, boolean hasErrorCode, int errorCode, boolean hardware, boolean software)
1316 if (vector == ProcessorException.Type.PAGE_FAULT.vector())
1318 setCR2(linearMemory.getLastWalkedAddress());
1319 if (linearMemory.getLastWalkedAddress() == 0xbff9a3c0)
1321 System.err.println("Emulated: Found it ********* @ " + Integer.toHexString(getInstructionPointer()));
1322 System.exit(0);
1326 int selector = vector << 3; //multiply by 8 to get offset into idt
1327 int EXT = hardware ? 1 : 0;
1329 Segment gate;
1330 boolean isSup = linearMemory.isSupervisor();
1331 try {
1332 linearMemory.setSupervisor(true);
1333 long descriptor = idtr.getQuadWord(selector);
1334 gate = SegmentFactory.createProtectedModeSegment(linearMemory, selector, descriptor);
1335 } catch (ProcessorException e) {
1336 System.err.println("Emulated: Failed to create gate in PM excp: selector=" +
1337 Integer.toHexString(selector));
1338 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, selector + 2 + EXT, true);
1339 } finally {
1340 linearMemory.setSupervisor(isSup);
1343 switch (gate.getType()) {
1344 default:
1345 System.err.println("Emulated: Invalid gate type for throwing interrupt: " +
1346 Integer.toHexString(gate.getType()) + ".");
1347 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, selector + 2 + EXT, true);
1348 case 0x05: //Interrupt Handler: Task Gate
1349 System.err.println("Critical error: Task gates as interrupt handlers not implemented.");
1350 throw new IllegalStateException("Unimplemented Interrupt Handler: Task Gate");
1351 case 0x06: //Interrupt Handler: 16-bit Interrupt Gate
1353 ProtectedModeSegment.InterruptGate16Bit interruptGate = ((ProtectedModeSegment.InterruptGate16Bit)gate);
1355 checkGate(interruptGate, selector, software);
1357 int targetSegmentSelector = interruptGate.getTargetSegment();
1359 Segment targetSegment;
1360 try {
1361 targetSegment = getSegment(targetSegmentSelector);
1362 } catch (ProcessorException e) {
1363 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
1366 if (targetSegment.getDPL() > currentPrivilegeLevel)
1367 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
1368 switch(targetSegment.getType()) {
1369 default:
1370 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
1372 case 0x18: //Code, Execute-Only
1373 case 0x19: //Code, Execute-Only, Accessed
1374 case 0x1a: //Code, Execute/Read
1375 case 0x1b: //Code, Execute/Read, Accessed
1377 if (!targetSegment.isPresent())
1378 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSegmentSelector + EXT, true);
1379 if (targetSegment.getDPL() < currentPrivilegeLevel) {
1380 //INTER-PRIVILEGE-LEVEL
1381 int newStackSelector = 0;
1382 int newESP = 0;
1383 if ((tss.getType() & 0x8) != 0) {
1384 int tssStackAddress = (targetSegment.getDPL() * 8) + 4;
1385 if ((tssStackAddress + 7) > tss.getLimit())
1386 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, tss.getSelector(), true);
1388 isSup = linearMemory.isSupervisor();
1391 linearMemory.setSupervisor(true);
1392 newStackSelector = 0xffff & tss.getWord(tssStackAddress + 4);
1393 newESP = tss.getDoubleWord(tssStackAddress);
1395 finally
1397 linearMemory.setSupervisor(isSup);
1399 } else {
1400 int tssStackAddress = (targetSegment.getDPL() * 4) + 2;
1401 if ((tssStackAddress + 4) > tss.getLimit())
1402 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, tss.getSelector(), true);
1403 newStackSelector = 0xffff & tss.getWord(tssStackAddress + 2);
1404 newESP = 0xffff & tss.getWord(tssStackAddress);
1407 Segment newStackSegment;
1408 try {
1409 newStackSegment = getSegment(newStackSelector);
1410 } catch (ProcessorException e) {
1411 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
1414 if (newStackSegment.getRPL() != targetSegment.getDPL())
1415 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
1417 if ((newStackSegment.getDPL() != targetSegment.getDPL()) || ((newStackSegment.getType() & 0x1a) != 0x12))
1418 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
1420 if (!(newStackSegment.isPresent()))
1421 throw new ProcessorException(ProcessorException.Type.STACK_SEGMENT, newStackSelector, true);
1423 if (hasErrorCode) {
1424 if ((newStackSegment.getDefaultSizeFlag() && (esp < 12) && (esp > 0)) ||
1425 !newStackSegment.getDefaultSizeFlag() && ((esp & 0xffff) < 12))
1426 throw ProcessorException.STACK_SEGMENT_0;
1427 } else {
1428 if ((newStackSegment.getDefaultSizeFlag() && (esp < 10) && (esp > 0)) ||
1429 !newStackSegment.getDefaultSizeFlag() && ((esp & 0xffff) < 10))
1430 throw ProcessorException.STACK_SEGMENT_0;
1433 int targetOffset = interruptGate.getTargetOffset();
1434 targetSegment.checkAddress(targetOffset);
1436 int oldSS = ss.getSelector();
1437 int oldESP = esp;
1438 int oldCS = cs.getSelector();
1439 int oldEIP = eip;
1440 ss = newStackSegment;
1441 esp = newESP;
1442 ss.setRPL(targetSegment.getDPL());
1444 cs = targetSegment;
1445 eip = targetOffset;
1446 setCPL(cs.getDPL());
1447 if (ss.getDefaultSizeFlag()) {
1448 esp -= 2;
1449 ss.setWord(esp, (short)oldSS);
1450 esp -= 2;
1451 ss.setWord(esp, (short)oldESP);
1452 esp -= 2;
1453 ss.setWord(esp, (short)getEFlags());
1454 esp -= 2;
1455 ss.setWord(esp, (short)oldCS);
1456 esp -= 2;
1457 ss.setWord(esp, (short)oldEIP);
1458 if (hasErrorCode) {
1459 esp -= 2;
1460 ss.setWord(esp, (short)errorCode);
1462 } else {
1463 esp = (esp & ~0xffff) | ((esp - 2) & 0xffff);
1464 ss.setWord(esp & 0xffff, (short)oldSS);
1465 esp = (esp & ~0xffff) | ((esp - 2) & 0xffff);
1466 ss.setWord(esp & 0xffff, (short)oldESP);
1467 esp = (esp & ~0xffff) | ((esp - 2) & 0xffff);
1468 ss.setWord(esp & 0xffff, (short)getEFlags());
1469 esp = (esp & ~0xffff) | ((esp - 2) & 0xffff);
1470 ss.setWord(esp & 0xffff, (short)oldCS);
1471 esp = (esp & ~0xffff) | ((esp - 2) & 0xffff);
1472 ss.setWord(esp & 0xffff, (short)oldEIP);
1473 if (hasErrorCode) {
1474 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1475 ss.setWord(esp & 0xffff, (short)errorCode);
1480 eflagsInterruptEnable = eflagsInterruptEnableSoon = false;
1482 eflagsTrap = false;
1483 eflagsNestedTask = false;
1484 eflagsVirtual8086Mode = false;
1485 eflagsResume = false;
1486 } else if (targetSegment.getDPL() == currentPrivilegeLevel) {
1487 //INTRA-PRIVILEGE-LEVEL-INTERRUPT
1488 //check there is room on stack
1489 if (hasErrorCode) {
1490 if ((ss.getDefaultSizeFlag() && (esp < 8) && (esp > 0)) ||
1491 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 8))
1492 throw ProcessorException.STACK_SEGMENT_0;
1493 } else {
1494 if ((ss.getDefaultSizeFlag() && (esp < 6) && (esp > 0)) ||
1495 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 6))
1496 throw ProcessorException.STACK_SEGMENT_0;
1499 int targetOffset = interruptGate.getTargetOffset();
1500 targetSegment.checkAddress(targetOffset);
1502 if (ss.getDefaultSizeFlag()) {
1503 esp -= 2;
1504 ss.setWord(esp, (short)getEFlags());
1505 esp -= 2;
1506 ss.setWord(esp, (short)cs.getSelector());
1507 esp -= 2;
1508 ss.setWord(esp, (short)eip);
1509 if (hasErrorCode) {
1510 esp -= 2;
1511 ss.setWord(esp, (short)errorCode);
1513 } else {
1514 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1515 ss.setWord(esp & 0xffff, (short)getEFlags());
1516 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1517 ss.setWord(esp & 0xffff, (short)cs.getSelector());
1518 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1519 ss.setWord(esp & 0xffff, (short)eip);
1520 if (hasErrorCode) {
1521 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1522 ss.setWord(esp & 0xffff, (short)errorCode);
1526 cs = targetSegment;
1527 eip = targetOffset;
1529 cs.setRPL(currentPrivilegeLevel);
1530 eflagsInterruptEnable = eflagsInterruptEnableSoon = false;
1532 eflagsTrap = false;
1533 eflagsNestedTask = false;
1534 eflagsVirtual8086Mode = false;
1535 eflagsResume = false;
1536 } else {
1537 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
1540 break;
1541 case 0x1c: //Code: Execute-Only, Conforming
1542 case 0x1d: //Code: Execute-Only, Conforming, Accessed
1543 case 0x1e: //Code: Execute/Read, Conforming
1544 case 0x1f: //Code: Execute/Read, Conforming, Accessed
1546 if (!targetSegment.isPresent())
1547 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, selector, true);
1549 //SAME-PRIVILEGE
1550 //check there is room on stack
1551 if (hasErrorCode) {
1552 if ((ss.getDefaultSizeFlag() && (esp < 8) && (esp > 0)) ||
1553 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 8))
1554 throw ProcessorException.STACK_SEGMENT_0;
1555 } else {
1556 if ((ss.getDefaultSizeFlag() && (esp < 6) && (esp > 0)) ||
1557 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 6))
1558 throw ProcessorException.STACK_SEGMENT_0;
1561 int targetOffset = interruptGate.getTargetOffset();
1563 targetSegment.checkAddress(targetOffset);
1564 if (ss.getDefaultSizeFlag()) {
1565 esp -= 2;
1566 ss.setWord(esp, (short)getEFlags());
1567 esp -= 2;
1568 ss.setWord(esp, (short)cs.getSelector());
1569 esp -= 2;
1570 ss.setWord(esp, (short)eip);
1571 if (hasErrorCode) {
1572 esp -= 2;
1573 ss.setWord(esp, (short)errorCode);
1575 } else {
1576 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1577 ss.setWord(esp & 0xffff, (short)getEFlags());
1578 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1579 ss.setWord(esp & 0xffff, (short)cs.getSelector());
1580 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1581 ss.setWord(esp & 0xffff, (short)eip);
1582 if (hasErrorCode) {
1583 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1584 ss.setWord(esp & 0xffff, (short)errorCode);
1588 cs = targetSegment;
1589 eip = targetOffset;
1591 cs.setRPL(currentPrivilegeLevel);
1593 eflagsInterruptEnable = eflagsInterruptEnableSoon = false;
1594 eflagsTrap = false;
1595 eflagsNestedTask = false;
1596 eflagsVirtual8086Mode = false;
1597 eflagsResume = false;
1599 break;
1602 break;
1603 case 0x07: //Interrupt Handler: 16-bit Trap Gate
1605 ProtectedModeSegment.TrapGate16Bit trapGate = ((ProtectedModeSegment.TrapGate16Bit)gate);
1607 checkGate(trapGate, selector, software);
1609 int targetSegmentSelector = trapGate.getTargetSegment();
1611 Segment targetSegment;
1612 try {
1613 targetSegment = getSegment(targetSegmentSelector);
1614 } catch (ProcessorException e) {
1615 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
1618 if (targetSegment.getDPL() > currentPrivilegeLevel)
1619 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
1620 switch(targetSegment.getType()) {
1621 default:
1622 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
1624 case 0x18: //Code, Execute-Only
1625 case 0x19: //Code, Execute-Only, Accessed
1626 case 0x1a: //Code, Execute/Read
1627 case 0x1b: //Code, Execute/Read, Accessed
1629 if (!targetSegment.isPresent())
1630 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSegmentSelector + EXT, true);
1631 if (targetSegment.getDPL() < currentPrivilegeLevel) {
1632 //INTER-PRIVILEGE-LEVEL
1633 int newStackSelector = 0;
1634 int newESP = 0;
1635 if ((tss.getType() & 0x8) != 0) {
1636 int tssStackAddress = (targetSegment.getDPL() * 8) + 4;
1637 if ((tssStackAddress + 7) > tss.getLimit())
1638 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, tss.getSelector(), true);
1640 isSup = linearMemory.isSupervisor();
1643 linearMemory.setSupervisor(true);
1644 newStackSelector = 0xffff & tss.getWord(tssStackAddress + 4);
1645 newESP = tss.getDoubleWord(tssStackAddress);
1647 finally
1649 linearMemory.setSupervisor(isSup);
1651 } else {
1652 int tssStackAddress = (targetSegment.getDPL() * 4) + 2;
1653 if ((tssStackAddress + 4) > tss.getLimit())
1654 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, tss.getSelector(), true);
1655 newStackSelector = 0xffff & tss.getWord(tssStackAddress + 2);
1656 newESP = 0xffff & tss.getWord(tssStackAddress);
1659 Segment newStackSegment;
1660 try {
1661 newStackSegment = getSegment(newStackSelector);
1662 } catch (ProcessorException e) {
1663 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
1666 if (newStackSegment.getRPL() != targetSegment.getDPL())
1667 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
1669 if ((newStackSegment.getDPL() != targetSegment.getDPL()) || ((newStackSegment.getType() & 0x1a) != 0x12))
1670 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
1672 if (!(newStackSegment.isPresent()))
1673 throw new ProcessorException(ProcessorException.Type.STACK_SEGMENT, newStackSelector, true);
1675 if (hasErrorCode) {
1676 if ((newStackSegment.getDefaultSizeFlag() && (esp < 12) && (esp > 0)) ||
1677 !newStackSegment.getDefaultSizeFlag() && ((esp & 0xffff) < 12))
1678 throw ProcessorException.STACK_SEGMENT_0;
1679 } else {
1680 if ((newStackSegment.getDefaultSizeFlag() && (esp < 10) && (esp > 0)) ||
1681 !newStackSegment.getDefaultSizeFlag() && ((esp & 0xffff) < 10))
1682 throw ProcessorException.STACK_SEGMENT_0;
1685 int targetOffset = trapGate.getTargetOffset();
1686 targetSegment.checkAddress(targetOffset);
1688 int oldSS = ss.getSelector();
1689 int oldESP = esp;
1690 int oldCS = cs.getSelector();
1691 int oldEIP = eip;
1692 ss = newStackSegment;
1693 esp = newESP;
1694 ss.setRPL(targetSegment.getDPL());
1696 cs = targetSegment;
1697 eip = targetOffset;
1698 setCPL(cs.getDPL());
1699 if (ss.getDefaultSizeFlag()) {
1700 esp -= 2;
1701 ss.setWord(esp, (short)oldSS);
1702 esp -= 2;
1703 ss.setWord(esp, (short)oldESP);
1704 esp -= 2;
1705 ss.setWord(esp, (short)getEFlags());
1706 esp -= 2;
1707 ss.setWord(esp, (short)oldCS);
1708 esp -= 2;
1709 ss.setWord(esp, (short)oldEIP);
1710 if (hasErrorCode) {
1711 esp -= 2;
1712 ss.setWord(esp, (short)errorCode);
1714 } else {
1715 esp = (esp & ~0xffff) | ((esp - 2) & 0xffff);
1716 ss.setWord(esp & 0xffff, (short)oldSS);
1717 esp = (esp & ~0xffff) | ((esp - 2) & 0xffff);
1718 ss.setWord(esp & 0xffff, (short)oldESP);
1719 esp = (esp & ~0xffff) | ((esp - 2) & 0xffff);
1720 ss.setWord(esp & 0xffff, (short)getEFlags());
1721 esp = (esp & ~0xffff) | ((esp - 2) & 0xffff);
1722 ss.setWord(esp & 0xffff, (short)oldCS);
1723 esp = (esp & ~0xffff) | ((esp - 2) & 0xffff);
1724 ss.setWord(esp & 0xffff, (short)oldEIP);
1725 if (hasErrorCode) {
1726 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1727 ss.setWord(esp & 0xffff, (short)errorCode);
1732 eflagsTrap = false;
1733 eflagsNestedTask = false;
1734 eflagsVirtual8086Mode = false;
1735 eflagsResume = false;
1736 } else if (targetSegment.getDPL() == currentPrivilegeLevel) {
1737 //INTRA-PRIVILEGE-LEVEL-INTERRUPT
1738 //check there is room on stack
1739 if (hasErrorCode) {
1740 if ((ss.getDefaultSizeFlag() && (esp < 8) && (esp > 0)) ||
1741 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 8))
1742 throw ProcessorException.STACK_SEGMENT_0;
1743 } else {
1744 if ((ss.getDefaultSizeFlag() && (esp < 6) && (esp > 0)) ||
1745 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 6))
1746 throw ProcessorException.STACK_SEGMENT_0;
1749 int targetOffset = trapGate.getTargetOffset();
1750 targetSegment.checkAddress(targetOffset);
1752 if (ss.getDefaultSizeFlag()) {
1753 esp -= 2;
1754 ss.setWord(esp, (short)getEFlags());
1755 esp -= 2;
1756 ss.setWord(esp, (short)cs.getSelector());
1757 esp -= 2;
1758 ss.setWord(esp, (short)eip);
1759 if (hasErrorCode) {
1760 esp -= 2;
1761 ss.setWord(esp, (short)errorCode);
1763 } else {
1764 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1765 ss.setWord(esp & 0xffff, (short)getEFlags());
1766 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1767 ss.setWord(esp & 0xffff, (short)cs.getSelector());
1768 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1769 ss.setWord(esp & 0xffff, (short)eip);
1770 if (hasErrorCode) {
1771 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1772 ss.setWord(esp & 0xffff, (short)errorCode);
1776 cs = targetSegment;
1777 eip = targetOffset;
1779 cs.setRPL(currentPrivilegeLevel);
1781 eflagsTrap = false;
1782 eflagsNestedTask = false;
1783 eflagsVirtual8086Mode = false;
1784 eflagsResume = false;
1785 } else {
1786 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
1789 break;
1790 case 0x1c: //Code: Execute-Only, Conforming
1791 case 0x1d: //Code: Execute-Only, Conforming, Accessed
1792 case 0x1e: //Code: Execute/Read, Conforming
1793 case 0x1f: //Code: Execute/Read, Conforming, Accessed
1795 if (!targetSegment.isPresent())
1796 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, selector, true);
1798 //SAME-PRIVILEGE
1799 //check there is room on stack
1800 if (hasErrorCode) {
1801 if ((ss.getDefaultSizeFlag() && (esp < 8) && (esp > 0)) ||
1802 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 8))
1803 throw ProcessorException.STACK_SEGMENT_0;
1804 } else {
1805 if ((ss.getDefaultSizeFlag() && (esp < 6) && (esp > 0)) ||
1806 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 6))
1807 throw ProcessorException.STACK_SEGMENT_0;
1810 int targetOffset = trapGate.getTargetOffset();
1812 targetSegment.checkAddress(targetOffset);
1813 if (ss.getDefaultSizeFlag()) {
1814 esp -= 2;
1815 ss.setWord(esp, (short)getEFlags());
1816 esp -= 2;
1817 ss.setWord(esp, (short)cs.getSelector());
1818 esp -= 2;
1819 ss.setWord(esp, (short)eip);
1820 if (hasErrorCode) {
1821 esp -= 2;
1822 ss.setWord(esp, (short)errorCode);
1824 } else {
1825 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1826 ss.setWord(esp & 0xffff, (short)getEFlags());
1827 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1828 ss.setWord(esp & 0xffff, (short)cs.getSelector());
1829 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1830 ss.setWord(esp & 0xffff, (short)eip);
1831 if (hasErrorCode) {
1832 esp = (esp & ~ 0xffff) | ((esp - 2) & 0xffff);
1833 ss.setWord(esp & 0xffff, (short)errorCode);
1837 cs = targetSegment;
1838 eip = targetOffset;
1840 cs.setRPL(currentPrivilegeLevel);
1842 eflagsTrap = false;
1843 eflagsNestedTask = false;
1844 eflagsVirtual8086Mode = false;
1845 eflagsResume = false;
1847 break;
1850 break;
1851 case 0x0e: //Interrupt Handler: 32-bit Interrupt Gate
1853 ProtectedModeSegment.InterruptGate32Bit interruptGate = ((ProtectedModeSegment.InterruptGate32Bit)gate);
1855 checkGate(gate, selector, software);
1857 int targetSegmentSelector = interruptGate.getTargetSegment();
1859 Segment targetSegment;
1860 try {
1861 targetSegment = getSegment(targetSegmentSelector);
1862 } catch (ProcessorException e) {
1863 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
1866 if (targetSegment.getDPL() > currentPrivilegeLevel)
1867 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
1869 switch(targetSegment.getType()) {
1870 default:
1871 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
1873 case 0x18: //Code, Execute-Only
1874 case 0x19: //Code, Execute-Only, Accessed
1875 case 0x1a: //Code, Execute/Read
1876 case 0x1b: //Code, Execute/Read, Accessed
1878 if (!targetSegment.isPresent())
1879 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSegmentSelector + EXT, true);
1881 if (targetSegment.getDPL() < currentPrivilegeLevel) {
1882 //INTER-PRIVILEGE-LEVEL
1883 int newStackSelector = 0;
1884 int newESP = 0;
1885 if ((tss.getType() & 0x8) != 0) {
1886 int tssStackAddress = (targetSegment.getDPL() * 8) + 4;
1887 if ((tssStackAddress + 7) > tss.getLimit())
1888 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, tss.getSelector(), true);
1890 isSup = linearMemory.isSupervisor();
1893 linearMemory.setSupervisor(true);
1894 newStackSelector = 0xffff & tss.getWord(tssStackAddress + 4);
1895 newESP = tss.getDoubleWord(tssStackAddress);
1897 finally
1899 linearMemory.setSupervisor(isSup);
1901 } else {
1902 int tssStackAddress = (targetSegment.getDPL() * 4) + 2;
1903 if ((tssStackAddress + 4) > tss.getLimit())
1904 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, tss.getSelector(), true);
1905 newStackSelector = 0xffff & tss.getWord(tssStackAddress + 2);
1906 newESP = 0xffff & tss.getWord(tssStackAddress);
1909 Segment newStackSegment;
1910 try {
1911 newStackSegment = getSegment(newStackSelector);
1912 } catch (ProcessorException e) {
1913 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
1916 if (newStackSegment.getRPL() != targetSegment.getDPL())
1917 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
1919 if ((newStackSegment.getDPL() != targetSegment.getDPL()) || ((newStackSegment.getType() & 0x1a) != 0x12))
1920 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
1922 if (!(newStackSegment.isPresent()))
1923 throw new ProcessorException(ProcessorException.Type.STACK_SEGMENT, newStackSelector, true);
1925 if (hasErrorCode) {
1926 if ((newStackSegment.getDefaultSizeFlag() && (esp < 24) && (esp > 0)) ||
1927 !newStackSegment.getDefaultSizeFlag() && ((esp & 0xffff) < 24))
1928 throw ProcessorException.STACK_SEGMENT_0;
1929 } else {
1930 if ((newStackSegment.getDefaultSizeFlag() && (esp < 20) && (esp > 0)) ||
1931 !newStackSegment.getDefaultSizeFlag() && ((esp & 0xffff) < 20))
1932 throw ProcessorException.STACK_SEGMENT_0;
1935 int targetOffset = interruptGate.getTargetOffset();
1936 targetSegment.checkAddress(targetOffset);
1938 int oldSS = ss.getSelector();
1939 int oldESP = esp;
1940 int oldCS = cs.getSelector();
1941 int oldEIP = eip;
1942 ss = newStackSegment;
1943 esp = newESP;
1944 ss.setRPL(targetSegment.getDPL());
1946 cs = targetSegment;
1947 eip = targetOffset;
1948 setCPL(cs.getDPL());
1950 if (ss.getDefaultSizeFlag()) {
1951 esp -= 4;
1952 ss.setDoubleWord(esp, oldSS);
1953 esp -= 4;
1954 ss.setDoubleWord(esp, oldESP);
1955 esp -= 4;
1956 ss.setDoubleWord(esp, getEFlags());
1957 esp -= 4;
1958 ss.setDoubleWord(esp, oldCS);
1959 esp -= 4;
1960 ss.setDoubleWord(esp, oldEIP);
1961 if (hasErrorCode) {
1962 esp -= 4;
1963 ss.setDoubleWord(esp, errorCode);
1965 } else {
1966 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
1967 ss.setDoubleWord(esp & 0xffff, oldSS);
1968 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
1969 ss.setDoubleWord(esp & 0xffff, oldESP);
1970 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
1971 ss.setDoubleWord(esp & 0xffff, getEFlags());
1972 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
1973 ss.setDoubleWord(esp & 0xffff, oldCS);
1974 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
1975 ss.setDoubleWord(esp & 0xffff, oldEIP);
1976 if (hasErrorCode) {
1977 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
1978 ss.setDoubleWord(esp & 0xffff, errorCode);
1983 eflagsInterruptEnable = eflagsInterruptEnableSoon = false;
1985 eflagsTrap = false;
1986 eflagsNestedTask = false;
1987 eflagsVirtual8086Mode = false;
1988 eflagsResume = false;
1989 } else if (targetSegment.getDPL() == currentPrivilegeLevel) {
1990 //SAME-PRIVILEGE
1991 //check there is room on stack
1992 if (hasErrorCode) {
1993 if ((ss.getDefaultSizeFlag() && (esp < 16) && (esp > 0)) ||
1994 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 16))
1995 throw ProcessorException.STACK_SEGMENT_0;
1996 } else {
1997 if ((ss.getDefaultSizeFlag() && (esp < 12) && (esp > 0)) ||
1998 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 12))
1999 throw ProcessorException.STACK_SEGMENT_0;
2002 int targetOffset = interruptGate.getTargetOffset();
2003 targetSegment.checkAddress(targetOffset);
2006 if (ss.getDefaultSizeFlag()) {
2007 esp -= 4;
2008 ss.setDoubleWord(esp, getEFlags());
2009 esp -= 4;
2010 ss.setDoubleWord(esp, cs.getSelector());
2011 esp -= 4;
2012 ss.setDoubleWord(esp, eip);
2013 if (hasErrorCode) {
2014 esp -= 4;
2015 ss.setDoubleWord(esp, errorCode);
2017 } else {
2018 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2019 ss.setDoubleWord(esp & 0xffff, getEFlags());
2020 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2021 ss.setDoubleWord(esp & 0xffff, cs.getSelector());
2022 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2023 ss.setDoubleWord(esp & 0xffff, eip);
2024 if (hasErrorCode) {
2025 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2026 ss.setDoubleWord(esp & 0xffff, errorCode);
2030 cs = targetSegment;
2031 eip = targetOffset;
2033 cs.setRPL(currentPrivilegeLevel);
2034 eflagsInterruptEnable = eflagsInterruptEnableSoon = false;
2036 eflagsTrap = false;
2037 eflagsNestedTask = false;
2038 eflagsVirtual8086Mode = false;
2039 eflagsResume = false;
2040 } else {
2041 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
2044 break;
2045 case 0x1c: //Code: Execute-Only, Conforming
2046 case 0x1d: //Code: Execute-Only, Conforming, Accessed
2047 case 0x1e: //Code: Execute/Read, Conforming
2048 case 0x1f: //Code: Execute/Read, Conforming, Accessed
2050 if (!targetSegment.isPresent())
2051 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, selector, true);
2053 //SAME-PRIVILEGE
2054 //check there is room on stack
2055 if (hasErrorCode) {
2056 if((ss.getDefaultSizeFlag() && (esp < 16) && (esp > 0)) ||
2057 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 16)) {
2058 System.err.println("Emulated: Insufficient stack space for interrupt (case #1).");
2059 throw ProcessorException.STACK_SEGMENT_0;}
2060 } else {
2061 if((ss.getDefaultSizeFlag() && (esp < 12) && (esp > 0)) ||
2062 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 12)) {
2063 System.err.println("Emulated: Insufficient stack space for interrupt (case #2).");
2064 throw ProcessorException.STACK_SEGMENT_0;}
2067 int targetOffset = interruptGate.getTargetOffset();
2069 targetSegment.checkAddress(targetOffset);
2071 if (ss.getDefaultSizeFlag()) {
2072 esp -= 4;
2073 ss.setDoubleWord(esp, getEFlags());
2074 esp -= 4;
2075 ss.setDoubleWord(esp, cs.getSelector());
2076 esp -= 4;
2077 ss.setDoubleWord(esp, eip);
2078 if (hasErrorCode) {
2079 esp -= 4;
2080 ss.setDoubleWord(esp, errorCode);
2082 } else {
2083 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2084 ss.setDoubleWord(esp & 0xffff, getEFlags());
2085 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2086 ss.setDoubleWord(esp & 0xffff, cs.getSelector());
2087 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2088 ss.setDoubleWord(esp & 0xffff, eip);
2089 if (hasErrorCode) {
2090 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2091 ss.setDoubleWord(esp & 0xffff, errorCode);
2095 cs = targetSegment;
2096 eip = targetOffset;
2098 cs.setRPL(currentPrivilegeLevel);
2100 eflagsInterruptEnable = eflagsInterruptEnableSoon = false;
2101 eflagsTrap = false;
2102 eflagsNestedTask = false;
2103 eflagsVirtual8086Mode = false;
2104 eflagsResume = false;
2106 break;
2109 break;
2110 case 0x0f: //Interrupt Handler: 32-bit Trap Gate
2112 ProtectedModeSegment.TrapGate32Bit trapGate = ((ProtectedModeSegment.TrapGate32Bit)gate);
2114 checkGate(gate, selector, software);
2116 int targetSegmentSelector = trapGate.getTargetSegment();
2118 Segment targetSegment;
2119 try {
2120 targetSegment = getSegment(targetSegmentSelector);
2121 } catch (ProcessorException e) {
2122 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
2125 if (targetSegment.getDPL() > currentPrivilegeLevel)
2126 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
2128 switch(targetSegment.getType()) {
2129 default:
2130 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
2132 case 0x18: //Code, Execute-Only
2133 case 0x19: //Code, Execute-Only, Accessed
2134 case 0x1a: //Code, Execute/Read
2135 case 0x1b: //Code, Execute/Read, Accessed
2137 if (!targetSegment.isPresent())
2138 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSegmentSelector + EXT, true);
2140 if (targetSegment.getDPL() < currentPrivilegeLevel) {
2141 //INTER-PRIVILEGE-LEVEL
2142 int newStackSelector = 0;
2143 int newESP = 0;
2144 if ((tss.getType() & 0x8) != 0) {
2145 int tssStackAddress = (targetSegment.getDPL() * 8) + 4;
2146 if ((tssStackAddress + 7) > tss.getLimit())
2147 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, tss.getSelector(), true);
2149 isSup = linearMemory.isSupervisor();
2152 linearMemory.setSupervisor(true);
2153 newStackSelector = 0xffff & tss.getWord(tssStackAddress + 4);
2154 newESP = tss.getDoubleWord(tssStackAddress);
2156 finally
2158 linearMemory.setSupervisor(isSup);
2160 } else {
2161 int tssStackAddress = (targetSegment.getDPL() * 4) + 2;
2162 if ((tssStackAddress + 4) > tss.getLimit())
2163 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, tss.getSelector(), true);
2164 newStackSelector = 0xffff & tss.getWord(tssStackAddress + 2);
2165 newESP = 0xffff & tss.getWord(tssStackAddress);
2168 Segment newStackSegment;
2169 try {
2170 newStackSegment = getSegment(newStackSelector);
2171 } catch (ProcessorException e) {
2172 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
2175 if (newStackSegment.getRPL() != targetSegment.getDPL())
2176 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
2178 if ((newStackSegment.getDPL() != targetSegment.getDPL()) || ((newStackSegment.getType() & 0x1a) != 0x12))
2179 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
2181 if (!(newStackSegment.isPresent()))
2182 throw new ProcessorException(ProcessorException.Type.STACK_SEGMENT, newStackSelector, true);
2184 if (hasErrorCode) {
2185 if((newStackSegment.getDefaultSizeFlag() && (esp < 24) && (esp > 0)) ||
2186 !newStackSegment.getDefaultSizeFlag() && ((esp & 0xffff) < 24)) {
2187 System.err.println("Emulated: Insufficient stack space for interrupt (case #3).");
2188 throw ProcessorException.STACK_SEGMENT_0;
2190 } else {
2191 if((newStackSegment.getDefaultSizeFlag() && (esp < 20) && (esp > 0)) ||
2192 !newStackSegment.getDefaultSizeFlag() && ((esp & 0xffff) < 20)) {
2193 System.err.println("Emulated: Insufficient stack space for interrupt (case #4).");
2194 throw ProcessorException.STACK_SEGMENT_0;
2198 int targetOffset = trapGate.getTargetOffset();
2199 targetSegment.checkAddress(targetOffset);
2201 int oldSS = ss.getSelector();
2202 int oldESP = esp;
2203 int oldCS = cs.getSelector();
2204 int oldEIP = eip;
2206 ss = newStackSegment;
2207 esp = newESP;
2208 ss.setRPL(targetSegment.getDPL());
2210 cs = targetSegment;
2211 eip = targetOffset;
2212 setCPL(cs.getDPL());
2214 if (ss.getDefaultSizeFlag()) {
2215 esp -= 4;
2216 ss.setDoubleWord(esp, oldSS);
2217 esp -= 4;
2218 ss.setDoubleWord(esp, oldESP);
2219 esp -= 4;
2220 ss.setDoubleWord(esp, getEFlags());
2221 esp -= 4;
2222 ss.setDoubleWord(esp, oldCS);
2223 esp -= 4;
2224 ss.setDoubleWord(esp, oldEIP);
2225 if (hasErrorCode) {
2226 esp -= 4;
2227 ss.setDoubleWord(esp, errorCode);
2229 } else {
2230 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2231 ss.setDoubleWord(esp & 0xffff, oldSS);
2232 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2233 ss.setDoubleWord(esp & 0xffff, oldESP);
2234 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2235 ss.setDoubleWord(esp & 0xffff, getEFlags());
2236 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2237 ss.setDoubleWord(esp & 0xffff, oldCS);
2238 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2239 ss.setDoubleWord(esp & 0xffff, oldEIP);
2240 if (hasErrorCode) {
2241 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2242 ss.setDoubleWord(esp & 0xffff, errorCode);
2246 eflagsTrap = false;
2247 eflagsNestedTask = false;
2248 eflagsVirtual8086Mode = false;
2249 eflagsResume = false;
2250 } else if (targetSegment.getDPL() == currentPrivilegeLevel) {
2251 //SAME-PRIVILEGE
2252 //check there is room on stack
2253 if (hasErrorCode) {
2254 if((ss.getDefaultSizeFlag() && (esp < 16) && (esp > 0)) ||
2255 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 16)) {
2256 System.err.println("Emulated: Insufficient stack space for interrupt (case #5).");
2257 throw ProcessorException.STACK_SEGMENT_0;
2259 } else {
2260 if((ss.getDefaultSizeFlag() && (esp < 12) && (esp > 0)) ||
2261 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 12)) {
2262 System.err.println("Emulated: Insufficient stack space for interrupt (case #6).");
2263 throw ProcessorException.STACK_SEGMENT_0;
2267 int targetOffset = trapGate.getTargetOffset();
2269 targetSegment.checkAddress(targetOffset);
2271 if (ss.getDefaultSizeFlag()) {
2272 esp -= 4;
2273 ss.setDoubleWord(esp, getEFlags());
2274 esp -= 4;
2275 ss.setDoubleWord(esp, cs.getSelector());
2276 esp -= 4;
2277 ss.setDoubleWord(esp, eip);
2278 if (hasErrorCode) {
2279 esp -= 4;
2280 ss.setDoubleWord(esp, errorCode);
2282 } else {
2283 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2284 ss.setDoubleWord(esp & 0xffff, getEFlags());
2285 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2286 ss.setDoubleWord(esp & 0xffff, cs.getSelector());
2287 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2288 ss.setDoubleWord(esp & 0xffff, eip);
2289 if (hasErrorCode) {
2290 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2291 ss.setDoubleWord(esp & 0xffff, errorCode);
2295 cs = targetSegment;
2296 eip = targetOffset;
2298 cs.setRPL(currentPrivilegeLevel);
2300 eflagsTrap = false;
2301 eflagsNestedTask = false;
2302 eflagsVirtual8086Mode = false;
2303 eflagsResume = false;
2304 } else {
2305 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
2308 break;
2309 case 0x1c: //Code: Execute-Only, Conforming
2310 case 0x1d: //Code: Execute-Only, Conforming, Accessed
2311 case 0x1e: //Code: Execute/Read, Conforming
2312 case 0x1f: //Code: Execute/Read, Conforming, Accessed
2314 if (!targetSegment.isPresent())
2315 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, selector, true);
2317 //SAME-PRIVILEGE
2318 //check there is room on stack
2319 if (hasErrorCode) {
2320 if((ss.getDefaultSizeFlag() && (esp < 16) && (esp > 0)) ||
2321 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 16)) {
2322 System.err.println("Emulated: Insufficient stack space for interrupt (case #7).");
2323 throw ProcessorException.STACK_SEGMENT_0;
2325 } else {
2326 if((ss.getDefaultSizeFlag() && (esp < 12) && (esp > 0)) ||
2327 !ss.getDefaultSizeFlag() && ((esp & 0xffff) < 12)) {
2328 System.err.println("Emulated: Insufficient stack space for interrupt (case #8).");
2329 throw ProcessorException.STACK_SEGMENT_0;
2333 int targetOffset = trapGate.getTargetOffset();
2335 targetSegment.checkAddress(targetOffset);
2337 if (ss.getDefaultSizeFlag()) {
2338 esp -= 4;
2339 ss.setDoubleWord(esp, getEFlags());
2340 esp -= 4;
2341 ss.setDoubleWord(esp, cs.getSelector());
2342 esp -= 4;
2343 ss.setDoubleWord(esp, eip);
2344 if (hasErrorCode) {
2345 esp -= 4;
2346 ss.setDoubleWord(esp, errorCode);
2348 } else {
2349 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2350 ss.setDoubleWord(esp & 0xffff, getEFlags());
2351 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2352 ss.setDoubleWord(esp & 0xffff, cs.getSelector());
2353 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2354 ss.setDoubleWord(esp & 0xffff, eip);
2355 if (hasErrorCode) {
2356 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2357 ss.setDoubleWord(esp & 0xffff, errorCode);
2361 cs = targetSegment;
2362 eip = targetOffset;
2363 cs.setRPL(currentPrivilegeLevel);
2365 eflagsTrap = false;
2366 eflagsNestedTask = false;
2367 eflagsVirtual8086Mode = false;
2368 eflagsResume = false;
2370 break;
2373 break;
2377 public final void handleVirtual8086ModeException(ProcessorException pe)
2379 int savedESP = esp;
2380 int savedEIP = eip;
2381 Segment savedCS = cs;
2382 Segment savedSS = ss;
2384 try {
2385 followVirtual8086ModeException(pe.getType().vector(), pe.hasErrorCode(), pe.getErrorCode(), false, false);
2386 } catch (ProcessorException e) {
2387 System.err.println("Emulated: Double Fault: " + e);
2388 //return cpu to original state
2389 esp = savedESP;
2390 eip = savedEIP;
2391 cs = savedCS;
2392 ss = savedSS;
2394 if (pe.getType() == ProcessorException.Type.DOUBLE_FAULT) {
2395 System.err.println("Emulated: Triple fault. Unhandleable, CPU shutting down: " + e);
2396 throw new TripleFault("Triple Fault, CPU shutting down.");
2397 } else if (e.combinesToDoubleFault(pe))
2398 handleVirtual8086ModeException(ProcessorException.DOUBLE_FAULT_0);
2399 else
2400 handleVirtual8086ModeException(e);
2404 public final void handleSoftVirtual8086ModeInterrupt(int vector, int instructionLength)
2406 int savedESP = esp;
2407 int savedEIP = eip;
2408 Segment savedCS = cs;
2409 Segment savedSS = ss;
2411 if ((getCR4() & 0x1) != 0) {
2412 System.err.println("Critical error: VME not supported.");
2413 throw new IllegalStateException("VME not supported");
2414 } else if (eflagsIOPrivilegeLevel < 3) {
2415 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
2416 } else {
2417 try {
2418 followVirtual8086ModeException(vector, false, 0, false, true);
2419 } catch (ProcessorException e) {
2420 //return cpu to original state
2421 esp = savedESP;
2422 eip = savedEIP;
2423 cs = savedCS;
2424 ss = savedSS;
2426 //make eip point at INT instruction which threw an exception
2427 if (e.pointsToSelf())
2428 eip -= instructionLength;
2430 if (e.getType() == ProcessorException.Type.DOUBLE_FAULT) {
2431 System.err.println("Emulated: Triple fault. Unhandleable, CPU shutting down: " + e);
2432 throw new TripleFault("Triple Fault, CPU shutting down.");
2433 } else
2434 handleVirtual8086ModeException(e);
2439 public final void handleHardVirtual8086ModeInterrupt(int vector)
2441 int savedESP = esp;
2442 int savedEIP = eip;
2443 Segment savedCS = cs;
2444 Segment savedSS = ss;
2446 try {
2447 followVirtual8086ModeException(vector, false, 0, true, false);
2448 } catch (ProcessorException e) {
2449 //return cpu to original state
2450 esp = savedESP;
2451 eip = savedEIP;
2452 cs = savedCS;
2453 ss = savedSS;
2455 handleVirtual8086ModeException(e);
2459 private final void followVirtual8086ModeException(int vector, boolean hasErrorCode, int errorCode, boolean hardware, boolean software)
2461 if (vector == ProcessorException.Type.PAGE_FAULT.vector())
2462 setCR2(linearMemory.getLastWalkedAddress());
2464 int selector = vector << 3; //multiply by 8 to get offset into idt
2465 int EXT = hardware ? 1 : 0;
2467 if (selector +7 > idtr.getLimit())
2468 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, selector + 2 + EXT, true);
2470 Segment gate;
2471 boolean isSup = linearMemory.isSupervisor();
2474 linearMemory.setSupervisor(true);
2475 long descriptor = idtr.getQuadWord(selector);
2476 gate = SegmentFactory.createProtectedModeSegment(linearMemory, selector, descriptor);
2478 catch (ProcessorException e)
2480 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, selector + 2 + EXT, true);
2482 finally
2484 linearMemory.setSupervisor(isSup);
2487 if (!gate.isSystem())
2488 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, selector + 2, true);
2490 switch (gate.getType()) {
2491 default:
2492 System.err.println("Emulated: Invalid Gate Type For Throwing Interrupt: 0x" +
2493 Integer.toHexString(gate.getType()));
2494 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, selector + 2 + EXT, true);
2495 case 0x05: //Interrupt Handler: Task Gate
2496 System.err.println("Critical error: Unimplemented Interrupt Handler: Task Gate");
2497 throw new IllegalStateException("Unimplemented Interrupt Handler: Task Gate");
2498 case 0x06: //Interrupt Handler: 16-bit Interrupt Gate
2499 System.err.println("Critical error: Unimplemented Interrupt Handler: 16-bit Interrupt Gate");
2500 throw new IllegalStateException("Unimplemented Interrupt Handler: 16-bit Interrupt Gate");
2501 case 0x07: //Interrupt Handler: 16-bit Trap Gate
2502 System.err.println("Critical error: Unimplemented Interrupt Handler: 16-bit Trap Gate");
2503 throw new IllegalStateException("Unimplemented Interrupt Handler: 16-bit Trap Gate");
2504 case 0x0e: //Interrupt Handler: 32-bit Interrupt Gate
2506 ProtectedModeSegment.InterruptGate32Bit interruptGate = ((ProtectedModeSegment.InterruptGate32Bit)gate);
2508 checkGate(gate, selector, software);
2510 int targetSegmentSelector = interruptGate.getTargetSegment();
2512 if ((targetSegmentSelector & 0xFFFC) == 0)
2513 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);
2515 Segment targetSegment;
2516 try {
2517 targetSegment = getSegment(targetSegmentSelector);
2518 } catch (ProcessorException e) {
2519 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
2522 if ((targetSegment.getDPL() > currentPrivilegeLevel) | (targetSegment.isSystem()))
2523 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, (targetSegmentSelector & 0xfffc), true);
2525 if (!targetSegment.isPresent())
2526 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, (targetSegmentSelector & 0xfffc), true);
2528 switch(targetSegment.getType()) {
2529 default:
2530 System.err.println("Emulated: " + targetSegment);
2531 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, (targetSegmentSelector & 0xfffc), true);
2533 case 0x18: //Code, Execute-Only
2534 case 0x19: //Code, Execute-Only, Accessed
2535 case 0x1a: //Code, Execute/Read
2536 case 0x1b: //Code, Execute/Read, Accessed
2538 if (targetSegment.getDPL() < currentPrivilegeLevel) {
2539 if (targetSegment.getDPL() != 0)
2540 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector & 0xfffc, true);
2542 //INTERRUPT-TO-INNER-PRIVILEGE
2544 int newStackSelector = 0;
2545 int newESP = 0;
2546 if ((tss.getType() & 0x8) != 0) {
2547 int tssStackAddress = (targetSegment.getDPL() * 8) + 4;
2548 if ((tssStackAddress + 7) > tss.getLimit())
2549 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, tss.getSelector(), true);
2551 isSup = linearMemory.isSupervisor();
2554 linearMemory.setSupervisor(true);
2555 newStackSelector = 0xffff & tss.getWord(tssStackAddress + 4);
2556 newESP = tss.getDoubleWord(tssStackAddress);
2558 finally
2560 linearMemory.setSupervisor(isSup);
2562 } else {
2563 int tssStackAddress = (targetSegment.getDPL() * 4) + 2;
2564 if ((tssStackAddress + 4) > tss.getLimit())
2565 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, tss.getSelector(), true);
2566 newStackSelector = 0xffff & tss.getWord(tssStackAddress + 2);
2567 newESP = 0xffff & tss.getWord(tssStackAddress);
2570 if ((newStackSelector & 0xfffc) == 0)
2571 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, 0, true);
2573 Segment newStackSegment = null;
2574 try {
2575 newStackSegment = getSegment(newStackSelector);
2576 } catch (ProcessorException e) {
2577 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
2580 if (newStackSegment.getRPL() != targetSegment.getDPL())
2581 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector & 0xfffc, true);
2583 if ((newStackSegment.getDPL() != targetSegment.getDPL()) || ((newStackSegment.getType() & 0x1a) != 0x12))
2584 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector & 0xfffc, true);
2586 if (newStackSegment.isSystem())
2587 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector & 0xfffc, true);
2589 if (!(newStackSegment.isPresent()))
2590 throw new ProcessorException(ProcessorException.Type.STACK_SEGMENT, newStackSelector, true);
2592 if (hasErrorCode) {
2593 if ((newStackSegment.getDefaultSizeFlag() && (esp < 40) && (esp > 0)) ||
2594 !newStackSegment.getDefaultSizeFlag() && ((esp & 0xffff) < 40) && (esp > 0))
2595 throw new ProcessorException(ProcessorException.Type.STACK_SEGMENT, 0, true);
2596 } else {
2597 if ((newStackSegment.getDefaultSizeFlag() && (esp < 36) && (esp > 0)) ||
2598 !newStackSegment.getDefaultSizeFlag() && ((esp & 0xffff) < 36) && (esp > 0))
2599 throw new ProcessorException(ProcessorException.Type.STACK_SEGMENT, 0, true);
2602 int targetOffset = interruptGate.getTargetOffset();
2603 targetSegment.checkAddress(targetOffset);
2605 int oldSS = ss.getSelector() & 0xffff;
2606 int oldESP = esp;
2607 int oldCS = cs.getSelector() & 0xffff;
2608 int oldEIP = eip & 0xffff;
2609 ss = newStackSegment;
2610 esp = newESP;
2611 ss.setRPL(targetSegment.getDPL());
2613 cs = targetSegment;
2614 eip = targetOffset;
2615 setCPL(cs.getDPL());
2616 cs.setRPL(cs.getDPL());
2618 if (ss.getDefaultSizeFlag()) {
2619 esp -= 4;
2620 ss.setDoubleWord(esp, gs.getSelector() & 0xffff);
2621 esp -= 4;
2622 ss.setDoubleWord(esp, fs.getSelector() & 0xffff);
2623 esp -= 4;
2624 ss.setDoubleWord(esp, ds.getSelector() & 0xffff);
2625 esp -= 4;
2626 ss.setDoubleWord(esp, es.getSelector() & 0xffff);
2628 esp -= 4;
2629 ss.setDoubleWord(esp, oldSS);
2630 esp -= 4;
2631 ss.setDoubleWord(esp, oldESP);
2632 esp -= 4;
2633 ss.setDoubleWord(esp, getEFlags());
2634 esp -= 4;
2635 ss.setDoubleWord(esp, oldCS);
2636 esp -= 4;
2637 ss.setDoubleWord(esp, oldEIP);
2638 if (hasErrorCode) {
2639 esp -= 4;
2640 ss.setDoubleWord(esp, errorCode);
2642 } else {
2643 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2644 ss.setDoubleWord(esp & 0xffff, gs.getSelector() & 0xffff);
2645 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2646 ss.setDoubleWord(esp & 0xffff, fs.getSelector() & 0xffff);
2647 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2648 ss.setDoubleWord(esp & 0xffff, ds.getSelector() & 0xffff);
2649 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2650 ss.setDoubleWord(esp & 0xffff, es.getSelector() & 0xffff);
2653 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2654 ss.setDoubleWord(esp & 0xffff, oldSS);
2655 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2656 ss.setDoubleWord(esp & 0xffff, oldESP);
2657 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2658 ss.setDoubleWord(esp & 0xffff, getEFlags());
2659 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2660 ss.setDoubleWord(esp & 0xffff, oldCS);
2661 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2662 ss.setDoubleWord(esp & 0xffff, oldEIP);
2663 if (hasErrorCode) {
2664 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2665 ss.setDoubleWord(esp & 0xffff, errorCode);
2669 gs = SegmentFactory.NULL_SEGMENT;
2670 fs = SegmentFactory.NULL_SEGMENT;
2671 ds = SegmentFactory.NULL_SEGMENT;
2672 es = SegmentFactory.NULL_SEGMENT;
2674 eflagsInterruptEnable = eflagsInterruptEnableSoon = false;
2676 eflagsTrap = false;
2677 eflagsNestedTask = false;
2678 eflagsVirtual8086Mode = false;
2679 eflagsResume = false;
2680 throw ModeSwitchException.PROTECTED_MODE_EXCEPTION;
2681 } else {
2682 System.err.println("Critical error: Unimplemented same level exception in VM86 32 bit INT " +
2683 "gate (non conforming code segment)...");
2684 throw new IllegalStateException("Unimplemented same level exception in VM86 32 bit INT " +
2685 "gate (non conforming code segment)...");
2688 case 0x1c: //Code: Execute-Only, Conforming
2689 case 0x1d: //Code: Execute-Only, Conforming, Accessed
2690 case 0x1e: //Code: Execute/Read, Conforming
2691 case 0x1f: //Code: Execute/Read, Conforming, Accessed
2693 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
2696 case 0x0f: //Interrupt Handler: 32-bit Trap Gate
2698 ProtectedModeSegment.TrapGate32Bit trapGate = ((ProtectedModeSegment.TrapGate32Bit)gate);
2700 checkGate(gate, selector, software);
2702 int targetSegmentSelector = trapGate.getTargetSegment();
2704 if ((targetSegmentSelector & 0xfffc) == 0)
2705 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);
2707 Segment targetSegment;
2708 try {
2709 targetSegment = getSegment(targetSegmentSelector);
2710 } catch (ProcessorException e) {
2711 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, (targetSegmentSelector & 0xfffc) + EXT, true);
2714 if (targetSegment.getDPL() > currentPrivilegeLevel)
2715 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, (targetSegmentSelector & 0xfffc) + EXT, true);
2717 if (targetSegment.isSystem())
2718 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, (targetSegmentSelector & 0xfffc) + EXT, true);
2720 switch(targetSegment.getType()) {
2721 default:
2722 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector + EXT, true);
2724 case 0x18: //Code, Execute-Only
2725 case 0x19: //Code, Execute-Only, Accessed
2726 case 0x1a: //Code, Execute/Read
2727 case 0x1b: //Code, Execute/Read, Accessed
2729 if (!targetSegment.isPresent())
2730 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSegmentSelector + EXT, true);
2731 if (targetSegment.getDPL() < currentPrivilegeLevel) {
2732 if (targetSegment.getDPL() != 0)
2733 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector & 0xfffc, true);
2735 //INTERRUPT-TO-INNER-PRIVILEGE
2737 int newStackSelector = 0;
2738 int newESP = 0;
2739 if ((tss.getType() & 0x8) != 0) {
2740 int tssStackAddress = (targetSegment.getDPL() * 8) + 4;
2741 if ((tssStackAddress + 7) > tss.getLimit())
2742 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, tss.getSelector(), true);
2744 isSup = linearMemory.isSupervisor();
2747 linearMemory.setSupervisor(true);
2748 newStackSelector = 0xffff & tss.getWord(tssStackAddress + 4);
2749 newESP = tss.getDoubleWord(tssStackAddress);
2751 finally
2753 linearMemory.setSupervisor(isSup);
2755 } else {
2756 int tssStackAddress = (targetSegment.getDPL() * 4) + 2;
2757 if ((tssStackAddress + 4) > tss.getLimit())
2758 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, tss.getSelector(), true);
2759 newStackSelector = 0xffff & tss.getWord(tssStackAddress + 2);
2760 newESP = 0xffff & tss.getWord(tssStackAddress);
2763 if ((newStackSelector & 0xfffc) == 0)
2764 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, 0, true);
2766 Segment newStackSegment = null;
2767 try {
2768 newStackSegment = getSegment(newStackSelector);
2769 } catch (ProcessorException e) {
2770 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector + EXT, true);
2773 if (newStackSegment.getRPL() != targetSegment.getDPL())
2774 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector & 0xfffc, true);
2776 if ((newStackSegment.getDPL() != targetSegment.getDPL()) || ((newStackSegment.getType() & 0x1a) != 0x12))
2777 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector & 0xfffc, true);
2779 if (newStackSegment.isSystem())
2780 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector & 0xfffc, true);
2782 if (!(newStackSegment.isPresent()))
2783 throw new ProcessorException(ProcessorException.Type.STACK_SEGMENT, newStackSelector & 0xfffc, true);
2785 if (hasErrorCode) {
2786 if ((newStackSegment.getDefaultSizeFlag() && (esp < 40) && (esp > 0)) ||
2787 !newStackSegment.getDefaultSizeFlag() && ((esp & 0xffff) < 40) && (esp > 0))
2788 throw new ProcessorException(ProcessorException.Type.STACK_SEGMENT, 0, true);
2789 } else {
2790 if ((newStackSegment.getDefaultSizeFlag() && (esp < 36) && (esp > 0)) ||
2791 !newStackSegment.getDefaultSizeFlag() && ((esp & 0xffff) < 36) && (esp > 0))
2792 throw new ProcessorException(ProcessorException.Type.STACK_SEGMENT, 0, true);
2795 int targetOffset = trapGate.getTargetOffset();
2796 targetSegment.checkAddress(targetOffset);
2798 int oldSS = ss.getSelector() & 0xffff;
2799 int oldESP = esp;
2800 int oldCS = cs.getSelector() & 0xffff;
2801 int oldEIP = eip & 0xffff;
2803 ss = newStackSegment;
2804 esp = newESP;
2805 ss.setRPL(targetSegment.getDPL());
2807 cs = targetSegment;
2808 eip = targetOffset;
2809 setCPL(cs.getDPL());
2811 if (ss.getDefaultSizeFlag()) {
2812 esp -= 4;
2813 ss.setDoubleWord(esp, gs.getSelector() & 0xffff);
2814 esp -= 4;
2815 ss.setDoubleWord(esp, fs.getSelector() & 0xffff);
2816 esp -= 4;
2817 ss.setDoubleWord(esp, ds.getSelector() & 0xffff);
2818 esp -= 4;
2819 ss.setDoubleWord(esp, es.getSelector() & 0xffff);
2821 esp -= 4;
2822 ss.setDoubleWord(esp, oldSS);
2823 esp -= 4;
2824 ss.setDoubleWord(esp, oldESP);
2825 esp -= 4;
2826 ss.setDoubleWord(esp, getEFlags());
2827 esp -= 4;
2828 ss.setDoubleWord(esp, oldCS);
2829 esp -= 4;
2830 ss.setDoubleWord(esp, oldEIP);
2831 if (hasErrorCode) {
2832 esp -= 4;
2833 ss.setDoubleWord(esp, errorCode);
2835 } else {
2836 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2837 ss.setDoubleWord(esp & 0xffff, gs.getSelector() & 0xffff);
2838 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2839 ss.setDoubleWord(esp & 0xffff, fs.getSelector() & 0xffff);
2840 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2841 ss.setDoubleWord(esp & 0xffff, ds.getSelector() & 0xffff);
2842 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2843 ss.setDoubleWord(esp & 0xffff, es.getSelector() & 0xffff);
2845 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2846 ss.setDoubleWord(esp & 0xffff, oldSS);
2847 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2848 ss.setDoubleWord(esp & 0xffff, oldESP);
2849 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2850 ss.setDoubleWord(esp & 0xffff, getEFlags());
2851 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2852 ss.setDoubleWord(esp & 0xffff, oldCS);
2853 esp = (esp & ~0xffff) | ((esp - 4) & 0xffff);
2854 ss.setDoubleWord(esp & 0xffff, oldEIP);
2855 if (hasErrorCode) {
2856 esp = (esp & ~ 0xffff) | ((esp - 4) & 0xffff);
2857 ss.setDoubleWord(esp & 0xffff, errorCode);
2861 gs = SegmentFactory.NULL_SEGMENT;
2862 fs = SegmentFactory.NULL_SEGMENT;
2863 ds = SegmentFactory.NULL_SEGMENT;
2864 es = SegmentFactory.NULL_SEGMENT;
2866 eflagsTrap = false;
2867 eflagsNestedTask = false;
2868 eflagsVirtual8086Mode = false;
2869 eflagsResume = false;
2870 throw ModeSwitchException.PROTECTED_MODE_EXCEPTION;
2871 } else {
2872 System.err.println("Critical error: Unimplemented same level exception in VM86 32 bit TRAP " +
2873 "gate (non conforming code segment)...");
2874 throw new IllegalStateException("Unimplemented same level exception in VM86 32 bit TRAP" +
2875 " gate (non conforming code segment)...");
2878 case 0x1c: //Code: Execute-Only, Conforming
2879 case 0x1d: //Code: Execute-Only, Conforming, Accessed
2880 case 0x1e: //Code: Execute/Read, Conforming
2881 case 0x1f: //Code: Execute/Read, Conforming, Accessed
2882 if (!targetSegment.isPresent())
2883 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, selector, true);
2885 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
2891 private void checkAlignmentChecking()
2893 if ((getCPL() == 3) && eflagsAlignmentCheck && ((cr0 & CR0_ALIGNMENT_MASK) != 0)) {
2894 if (!alignmentChecking) {
2895 System.err.println("Emulated: Alignment checking enabled");
2896 alignmentChecking = true;
2897 updateAlignmentCheckingInDataSegments();
2898 //checking now enabled
2900 } else {
2901 if (alignmentChecking) {
2902 System.err.println("Emulated: Alignment checking disabled");
2903 alignmentChecking = false;
2904 updateAlignmentCheckingInDataSegments();
2905 //checking now disabled
2910 public boolean initialised()
2912 boolean result = ((physicalMemory != null) && (linearMemory != null) && (ioports != null) && (interruptController != null));
2913 if (result && !started)
2915 reset();
2916 started = true;
2918 return result;
2921 public void acceptComponent(HardwareComponent component)
2923 if (component instanceof LinearAddressSpace)
2925 linearMemory = (LinearAddressSpace) component;
2926 alignmentCheckedMemory = new AlignmentCheckedAddressSpace(linearMemory);
2928 if (component instanceof PhysicalAddressSpace)
2929 physicalMemory = (PhysicalAddressSpace) component;
2930 if (component instanceof IOPortHandler)
2931 ioports = (IOPortHandler) component;
2932 if ((component instanceof InterruptController)
2933 && component.initialised())
2934 interruptController = (InterruptController)component;
2937 private int auxiliaryCarryOne, auxiliaryCarryTwo, auxiliaryCarryThree;
2938 private boolean auxiliaryCarryCalculated;
2939 private int auxiliaryCarryMethod;
2941 public static final int AC_XOR = 1;
2942 public static final int AC_BIT4_NEQ = 2;
2943 public static final int AC_LNIBBLE_MAX = 3;
2944 public static final int AC_LNIBBLE_ZERO = 4;
2945 public static final int AC_LNIBBLE_NZERO = 5;
2947 public boolean getAuxiliaryCarryFlag()
2949 if (auxiliaryCarryCalculated)
2950 return eflagsAuxiliaryCarry;
2951 else {
2952 auxiliaryCarryCalculated = true;
2953 if (auxiliaryCarryMethod == AC_XOR)
2954 return (eflagsAuxiliaryCarry = ((((auxiliaryCarryOne ^ auxiliaryCarryTwo) ^ auxiliaryCarryThree) & 0x10) != 0));
2955 else if (auxiliaryCarryMethod == AC_LNIBBLE_MAX)
2956 return (eflagsAuxiliaryCarry = ((auxiliaryCarryOne & 0xf) == 0xf));
2957 else if (auxiliaryCarryMethod == AC_LNIBBLE_ZERO)
2958 return (eflagsAuxiliaryCarry = ((auxiliaryCarryOne & 0xf) == 0x0));
2959 else switch (auxiliaryCarryMethod) {
2960 case AC_BIT4_NEQ: return (eflagsAuxiliaryCarry = ((auxiliaryCarryOne & 0x08) != (auxiliaryCarryTwo & 0x08)));
2961 case AC_LNIBBLE_NZERO: return (eflagsAuxiliaryCarry = ((auxiliaryCarryOne & 0xf) != 0x0));
2963 System.err.println("Warning: Missing auxiliary-carry flag calculation method");
2964 return eflagsAuxiliaryCarry;
2968 private static final boolean[] parityMap;
2969 static
2971 parityMap = new boolean[256];
2972 for (int i = 0; i < parityMap.length; i++)
2973 parityMap[i] = ((Integer.bitCount(i) & 0x1) == 0);
2976 public void setAuxiliaryCarryFlag(int dataOne, int dataTwo, int dataThree, int method)
2978 auxiliaryCarryCalculated = false;
2979 auxiliaryCarryOne = dataOne;
2980 auxiliaryCarryTwo = dataTwo;
2981 auxiliaryCarryThree = dataThree;
2982 auxiliaryCarryMethod = method;
2985 public void setAuxiliaryCarryFlag(int dataOne, int dataTwo, int method)
2987 auxiliaryCarryCalculated = false;
2988 auxiliaryCarryOne = dataOne;
2989 auxiliaryCarryTwo = dataTwo;
2990 auxiliaryCarryMethod = method;
2993 public void setAuxiliaryCarryFlag(int dataOne, int method)
2995 auxiliaryCarryCalculated = false;
2996 auxiliaryCarryOne = dataOne;
2997 auxiliaryCarryMethod = method;
3000 public void setAuxiliaryCarryFlag(boolean value)
3002 auxiliaryCarryCalculated = true;
3003 eflagsAuxiliaryCarry = value;
3006 private int parityOne;
3007 private boolean parityCalculated;
3010 public boolean getParityFlag()
3012 if (parityCalculated)
3013 return eflagsParity;
3014 else
3015 parityCalculated = true;
3017 return (eflagsParity = parityMap[parityOne & 0xff]);
3020 public void setParityFlag(boolean value)
3022 parityCalculated = true;
3023 eflagsParity = value;
3025 public void setParityFlag(int data)
3027 parityCalculated = false;
3028 parityOne = data;
3031 private int overflowOne, overflowTwo, overflowThree;
3032 private long overflowLong;
3033 private boolean overflowCalculated;
3034 private int overflowMethod;
3036 public static final int OF_NZ = 1;
3037 public static final int OF_NOT_BYTE = 2;
3038 public static final int OF_NOT_SHORT = 3;
3039 public static final int OF_NOT_INT = 4;
3041 public static final int OF_LOW_WORD_NZ = 5;
3042 public static final int OF_HIGH_BYTE_NZ = 6;
3044 public static final int OF_BIT6_XOR_CARRY = 7;
3045 public static final int OF_BIT7_XOR_CARRY = 8;
3046 public static final int OF_BIT14_XOR_CARRY = 9;
3047 public static final int OF_BIT15_XOR_CARRY = 10;
3048 public static final int OF_BIT30_XOR_CARRY = 11;
3049 public static final int OF_BIT31_XOR_CARRY = 12;
3051 public static final int OF_BIT7_DIFFERENT = 13;
3052 public static final int OF_BIT15_DIFFERENT = 14;
3053 public static final int OF_BIT31_DIFFERENT = 15;
3055 public static final int OF_MAX_BYTE = 16;
3056 public static final int OF_MAX_SHORT = 17;
3057 public static final int OF_MAX_INT = 18;
3059 public static final int OF_MIN_BYTE = 19;
3060 public static final int OF_MIN_SHORT = 20;
3061 public static final int OF_MIN_INT = 21;
3063 public static final int OF_ADD_BYTE = 22;
3064 public static final int OF_ADD_SHORT = 23;
3065 public static final int OF_ADD_INT = 24;
3067 public static final int OF_SUB_BYTE = 25;
3068 public static final int OF_SUB_SHORT = 26;
3069 public static final int OF_SUB_INT = 27;
3071 public boolean getOverflowFlag()
3073 if (overflowCalculated)
3074 return eflagsOverflow;
3075 else {
3076 overflowCalculated = true;
3077 if (overflowMethod == OF_ADD_BYTE)
3078 return (((overflowTwo & 0x80) == (overflowThree & 0x80)) && ((overflowTwo & 0x80) != (overflowOne & 0x80)));
3079 else if (overflowMethod == OF_ADD_SHORT)
3080 return (((overflowTwo & 0x8000) == (overflowThree & 0x8000)) && ((overflowTwo & 0x8000) != (overflowOne & 0x8000)));
3081 else if (overflowMethod == OF_ADD_INT)
3082 return (((overflowTwo & 0x80000000) == (overflowThree & 0x80000000)) && ((overflowTwo & 0x80000000) != (overflowOne & 0x80000000)));
3083 else if (overflowMethod == OF_SUB_BYTE)
3084 return (((overflowTwo & 0x80) != (overflowThree & 0x80)) && ((overflowTwo & 0x80) != (overflowOne & 0x80)));
3085 else if (overflowMethod == OF_SUB_SHORT)
3086 return (((overflowTwo & 0x8000) != (overflowThree & 0x8000)) && ((overflowTwo & 0x8000) != (overflowOne & 0x8000)));
3087 else if (overflowMethod == OF_SUB_INT)
3088 return (((overflowTwo & 0x80000000) != (overflowThree & 0x80000000)) && ((overflowTwo & 0x80000000) != (overflowOne & 0x80000000)));
3089 else if (overflowMethod == OF_MAX_BYTE)
3090 return (eflagsOverflow = (overflowOne == 0x7f));
3091 else if (overflowMethod == OF_MAX_SHORT)
3092 return (eflagsOverflow = (overflowOne == 0x7fff));
3093 else if (overflowMethod == OF_MIN_SHORT)
3094 return (eflagsOverflow = (overflowOne == (short)0x8000));
3095 else if (overflowMethod == OF_BIT15_XOR_CARRY)
3096 return (eflagsOverflow = (((overflowOne & 0x8000) != 0) ^ getCarryFlag()));
3097 else switch (overflowMethod) {
3098 case OF_NZ: return (eflagsOverflow = (overflowOne != 0));
3099 case OF_NOT_BYTE: return (eflagsOverflow = (overflowOne != (byte)overflowOne));
3100 case OF_NOT_SHORT: return (eflagsOverflow = (overflowOne != (short)overflowOne));
3101 case OF_NOT_INT: return (eflagsOverflow = (overflowLong != (int)overflowLong));
3103 case OF_LOW_WORD_NZ: return (eflagsOverflow = ((overflowOne & 0xffff) != 0));
3104 case OF_HIGH_BYTE_NZ: return (eflagsOverflow = ((overflowOne & 0xff00) != 0));
3106 case OF_BIT6_XOR_CARRY: return (eflagsOverflow = (((overflowOne & 0x40) != 0) ^ getCarryFlag()));
3107 case OF_BIT7_XOR_CARRY: return (eflagsOverflow = (((overflowOne & 0x80) != 0) ^ getCarryFlag()));
3108 case OF_BIT14_XOR_CARRY: return (eflagsOverflow = (((overflowOne & 0x4000) != 0) ^ getCarryFlag()));
3109 case OF_BIT30_XOR_CARRY: return (eflagsOverflow = (((overflowOne & 0x40000000) != 0) ^ getCarryFlag()));
3110 case OF_BIT31_XOR_CARRY: return (eflagsOverflow = (((overflowOne & 0x80000000) != 0) ^ getCarryFlag()));
3112 case OF_BIT7_DIFFERENT: return (eflagsOverflow = ((overflowOne & 0x80) != (overflowTwo & 0x80)));
3113 case OF_BIT15_DIFFERENT: return (eflagsOverflow = ((overflowOne & 0x8000) != (overflowTwo & 0x8000)));
3114 case OF_BIT31_DIFFERENT: return (eflagsOverflow = ((overflowOne & 0x80000000) != (overflowTwo & 0x80000000)));
3116 case OF_MAX_INT: return (eflagsOverflow = (overflowOne == 0x7fffffff));
3118 case OF_MIN_BYTE: return (eflagsOverflow = (overflowOne == (byte)0x80));
3119 case OF_MIN_INT: return (eflagsOverflow = (overflowOne == 0x80000000));
3121 System.err.println("Warning: Missing overflow flag calculation method");
3122 return eflagsOverflow;
3126 public void setOverflowFlag(boolean value)
3128 overflowCalculated = true;
3129 eflagsOverflow = value;
3132 public void setOverflowFlag(long dataOne, int method)
3134 overflowCalculated = false;
3135 overflowLong = dataOne;
3136 overflowMethod = method;
3139 public void setOverflowFlag(int dataOne, int method)
3141 overflowCalculated = false;
3142 overflowOne = dataOne;
3143 overflowMethod = method;
3146 public void setOverflowFlag(int dataOne, int dataTwo, int method)
3148 overflowCalculated = false;
3149 overflowOne = dataOne;
3150 overflowTwo = dataTwo;
3151 overflowMethod = method;
3154 public void setOverflowFlag(int dataOne, int dataTwo, int dataThree, int method)
3156 overflowCalculated = false;
3157 overflowOne = dataOne;
3158 overflowTwo = dataTwo;
3159 overflowThree = dataThree;
3160 overflowMethod = method;
3163 private int carryOne, carryTwo;
3164 private long carryLong;
3165 private boolean carryCalculated;
3166 private int carryMethod;
3168 public static final int CY_NZ = 1;
3169 public static final int CY_NOT_BYTE = 2;
3170 public static final int CY_NOT_SHORT = 3;
3171 public static final int CY_NOT_INT = 4;
3173 public static final int CY_LOW_WORD_NZ = 5;
3174 public static final int CY_HIGH_BYTE_NZ = 6;
3176 public static final int CY_NTH_BIT_SET = 7;
3178 public static final int CY_GREATER_FF = 8;
3180 public static final int CY_TWIDDLE_FF = 9;
3181 public static final int CY_TWIDDLE_FFFF = 10;
3182 public static final int CY_TWIDDLE_FFFFFFFF = 11;
3184 public static final int CY_SHL_OUTBIT_BYTE = 12;
3185 public static final int CY_SHL_OUTBIT_SHORT = 13;
3186 public static final int CY_SHL_OUTBIT_INT = 14;
3188 public static final int CY_SHR_OUTBIT = 15;
3190 public static final int CY_LOWBIT = 16;
3192 public static final int CY_HIGHBIT_BYTE = 17;
3193 public static final int CY_HIGHBIT_SHORT = 18;
3194 public static final int CY_HIGHBIT_INT = 19;
3196 public static final int CY_OFFENDBIT_BYTE = 20;
3197 public static final int CY_OFFENDBIT_SHORT = 21;
3198 public static final int CY_OFFENDBIT_INT = 22;
3200 public boolean getCarryFlag()
3202 if (carryCalculated)
3203 return eflagsCarry;
3204 else {
3205 carryCalculated = true;
3206 if (carryMethod == CY_TWIDDLE_FFFF)
3207 return (eflagsCarry = ((carryOne & (~0xffff)) != 0));
3208 else if (carryMethod == CY_TWIDDLE_FF)
3209 return (eflagsCarry = ((carryOne & (~0xff)) != 0));
3210 else if (carryMethod == CY_SHR_OUTBIT)
3211 return (eflagsCarry = (((carryOne >>> (carryTwo - 1)) & 0x1) != 0));
3212 else if (carryMethod == CY_TWIDDLE_FFFFFFFF)
3213 return (eflagsCarry = ((carryLong & (~0xffffffffl)) != 0));
3214 else if (carryMethod == CY_SHL_OUTBIT_SHORT)
3215 return (eflagsCarry = (((carryOne << (carryTwo - 1)) & 0x8000) != 0));
3216 else switch (carryMethod) {
3217 case CY_NZ: return (eflagsCarry = (carryOne != 0));
3218 case CY_NOT_BYTE: return (eflagsCarry = (carryOne != (byte)carryOne));
3219 case CY_NOT_SHORT: return (eflagsCarry = (carryOne != (short)carryOne));
3220 case CY_NOT_INT: return (eflagsCarry = (carryLong != (int)carryLong));
3222 case CY_LOW_WORD_NZ: return (eflagsCarry = ((carryOne & 0xffff) != 0));
3223 case CY_HIGH_BYTE_NZ: return (eflagsCarry = ((carryOne & 0xff00) != 0));
3225 case CY_NTH_BIT_SET: return (eflagsCarry = ((carryOne & (1 << carryTwo)) != 0));
3227 case CY_GREATER_FF: return (eflagsCarry = (carryOne > 0xff));
3229 case CY_SHL_OUTBIT_BYTE: return (eflagsCarry = (((carryOne << (carryTwo - 1)) & 0x80) != 0));
3230 case CY_SHL_OUTBIT_INT: return (eflagsCarry = (((carryOne << (carryTwo - 1)) & 0x80000000) != 0));
3232 case CY_LOWBIT: return (eflagsCarry = ((carryOne & 0x1) != 0));
3233 case CY_HIGHBIT_BYTE: return (eflagsCarry = ((carryOne & 0x80) != 0));
3234 case CY_HIGHBIT_SHORT: return (eflagsCarry = ((carryOne & 0x8000) != 0));
3235 case CY_HIGHBIT_INT: return (eflagsCarry = ((carryOne & 0x80000000) != 0));
3237 case CY_OFFENDBIT_BYTE: return (eflagsCarry = ((carryOne & 0x100) != 0));
3238 case CY_OFFENDBIT_SHORT: return (eflagsCarry = ((carryOne & 0x10000) != 0));
3239 case CY_OFFENDBIT_INT: return (eflagsCarry = ((carryLong & 0x100000000L) != 0));
3241 System.err.println("Warning: Missing carry flag calculation method");
3242 return eflagsCarry;
3246 public void setCarryFlag(boolean value)
3248 carryCalculated = true;
3249 eflagsCarry = value;
3252 public void setCarryFlag(long dataOne, int method)
3254 carryCalculated = false;
3255 carryLong = dataOne;
3256 carryMethod = method;
3259 public void setCarryFlag(int dataOne, int method)
3261 carryCalculated = false;
3262 carryOne = dataOne;
3263 carryMethod = method;
3266 public void setCarryFlag(int dataOne, int dataTwo, int method)
3268 carryCalculated = false;
3269 carryOne = dataOne;
3270 carryTwo = dataTwo;
3271 carryMethod = method;
3274 private int zeroOne;
3275 private boolean zeroCalculated;
3277 public boolean getZeroFlag()
3279 if (zeroCalculated)
3280 return eflagsZero;
3281 else {
3282 zeroCalculated = true;
3283 return (eflagsZero = (zeroOne == 0));
3287 public void setZeroFlag(boolean value)
3289 zeroCalculated = true;
3290 eflagsZero = value;
3293 public void setZeroFlag(int data)
3295 zeroCalculated = false;
3296 zeroOne = data;
3299 private int signOne;
3300 private boolean signCalculated;
3302 public boolean getSignFlag()
3304 if (signCalculated)
3305 return eflagsSign;
3306 else {
3307 signCalculated = true;
3308 return (eflagsSign = (signOne < 0));
3312 public void setSignFlag(boolean value)
3314 signCalculated = true;
3315 eflagsSign = value;
3318 public void setSignFlag(int data)
3320 signCalculated = false;
3321 signOne = data;