2 JPC-RR: A x86 PC Hardware Emulator
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
;
46 * @author Chris Dennis
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
;
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
;
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
)
157 public Processor(Clock clock
, int cpuClockDivider
)
160 clockDivider
= cpuClockDivider
;
163 physicalMemory
= null;
164 alignmentCheckedMemory
= null;
166 alignmentChecking
= false;
167 modelSpecificRegisters
= new HashMap
<Integer
, Long
>();
170 cr0
|= CR0_EXTENSION_TYPE
;
172 cr0
|= CR0_FPU_EMULATION
;
175 public void setFPU(FpuState newFPU
)
180 cr0
|= CR0_EXTENSION_TYPE
;
181 cr0
&= ~CR0_FPU_EMULATION
;
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");
196 System
.out
.println("Protected Mode");
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");
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");
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))
296 output
.println("#" + output
.objectNumber(this) + ": Processor:");
297 dumpStatusPartial(output
);
301 public void dumpSRPartial(SRDumper output
) throws IOException
303 output
.dumpLong(instructionsExecuted
);
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();
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()
517 if (getAuxiliaryCarryFlag())
525 if (eflagsInterruptEnable
)
529 if (getOverflowFlag())
531 result
|= (eflagsIOPrivilegeLevel
<< 12);
532 if (eflagsNestedTask
)
536 if (eflagsVirtual8086Mode
)
538 if (eflagsAlignmentCheck
)
540 if (eflagsVirtualInterrupt
)
542 if (eflagsVirtualInterruptPending
)
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
;
581 throw ModeSwitchException
.PROTECTED_MODE_EXCEPTION
;
586 public void setCPL(int value
)
588 currentPrivilegeLevel
= value
;
589 linearMemory
.setSupervisor(currentPrivilegeLevel
== 0);
590 checkAlignmentChecking();
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);
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);
640 processProtectedModeInterrupts(0);
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) {
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
+
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
;
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
)
694 int changedBits
= value ^ cr0
;
695 if (changedBits
== 0)
698 //actually set the 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
) + ".");
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);
728 if ((value
& CR0_PROTECTION_ENABLE
) != 0) {
729 convertSegmentsToProtectedMode();
730 throw ModeSwitchException
.PROTECTED_MODE_EXCEPTION
;
732 // linearMemory.flush();
734 convertSegmentsToRealMode();
735 throw ModeSwitchException
.REAL_MODE_EXCEPTION
;
745 public void setCR3(int value
)
748 linearMemory
.setPageWriteThroughEnabled((value
& CR3_PAGE_WRITES_TRANSPARENT
) != 0);
749 linearMemory
.setPageCacheEnabled((value
& CR3_PAGE_CACHE_DISABLE
) == 0);
750 linearMemory
.setPageDirectoryBaseAddress(value
);
763 public void setCR2(int value
)
768 public void setCR4(int value
)
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);
799 public void setDR0(int value
)
803 public void setDR1(int value
)
807 public void setDR2(int value
)
811 public void setDR3(int value
)
815 public void setDR6(int value
)
819 public void setDR7(int value
)
849 public long getMSR(int index
)
852 return modelSpecificRegisters
.get(Integer
.valueOf(index
)).longValue();
853 } catch (NullPointerException e
) {
854 System
.err
.println("Emulated: Reading unset MSR " + index
+ ", giving 0.");
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
);
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);
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
);
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);
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
);
1016 linearMemory
.setSupervisor(isSup
);
1022 resetTime
= instructionsExecuted
;
1023 eax
= ebx
= ecx
= edx
= 0;
1024 edi
= esi
= ebp
= esp
= 0;
1025 edx
= 0x00000633; // Pentium II Model 3 Stepping 3
1028 currentPrivilegeLevel
= 0;
1029 linearMemory
.reset();
1030 alignmentChecking
= false;
1034 cr0
= CR0_CACHE_DISABLE
| CR0_NOT_WRITETHROUGH
| 0x10;
1035 cr2
= cr3
= cr4
= 0x0;
1037 dr0
= dr1
= dr2
= dr3
= 0x0;
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
1068 cr0
|= CR0_EXTENSION_TYPE
;
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) {
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) {
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) {
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");
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);
1152 int newEip
= 0xffff & idtr
.getWord(vector
);
1153 int newSelector
= 0xffff & idtr
.getWord(vector
+2);
1155 short sesp
= (short) esp
;
1157 int eflags
= getEFlags() & 0xffff;
1158 ss
.setWord(sesp
& 0xffff, (short)eflags
);
1159 eflagsInterruptEnable
= false;
1160 eflagsInterruptEnableSoon
= false;
1162 eflagsAlignmentCheck
= false;
1165 ss
.setWord(sesp
& 0xffff, (short)cs
.getSelector());
1167 ss
.setWord(sesp
& 0xffff, (short)eip
);
1168 esp
= (0xFFFF0000 & esp
) | (sesp
& 0xFFFF);
1169 // read interrupt vector
1172 if (!cs
.setSelector(newSelector
))
1174 System
.err
.println("Emulated: Setting CS to RM in RM interrupt");
1175 cs
= SegmentFactory
.createRealModeSegment(physicalMemory
, newSelector
);
1180 public final void handleProtectedModeException(ProcessorException pe
)
1184 Segment savedCS
= cs
;
1185 Segment savedSS
= ss
;
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
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
);
1203 handleProtectedModeException(e
);
1207 public final void handleSoftProtectedModeInterrupt(int vector
, int instructionLength
)
1211 Segment savedCS
= cs
;
1212 Segment savedSS
= ss
;
1215 followProtectedModeException(vector
, false, 0, false, true);
1216 } catch (ProcessorException e
) {
1217 //return cpu to original state
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
)
1235 Segment savedCS
= cs
;
1236 Segment savedSS
= ss
;
1239 followProtectedModeException(vector
, false, 0, true, false);
1240 } catch (ProcessorException e
) {
1241 //return cpu to original state
1247 handleProtectedModeException(e
);
1251 private final void checkGate(Segment gate
, int selector
, boolean 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
);
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
);
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
);
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
);
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()));
1326 int selector
= vector
<< 3; //multiply by 8 to get offset into idt
1327 int EXT
= hardware ?
1 : 0;
1330 boolean isSup
= linearMemory
.isSupervisor();
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);
1340 linearMemory
.setSupervisor(isSup
);
1343 switch (gate
.getType()) {
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
;
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()) {
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;
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
);
1397 linearMemory
.setSupervisor(isSup
);
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
;
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);
1424 if ((newStackSegment
.getDefaultSizeFlag() && (esp
< 12) && (esp
> 0)) ||
1425 !newStackSegment
.getDefaultSizeFlag() && ((esp
& 0xffff) < 12))
1426 throw ProcessorException
.STACK_SEGMENT_0
;
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();
1438 int oldCS
= cs
.getSelector();
1440 ss
= newStackSegment
;
1442 ss
.setRPL(targetSegment
.getDPL());
1446 setCPL(cs
.getDPL());
1447 if (ss
.getDefaultSizeFlag()) {
1449 ss
.setWord(esp
, (short)oldSS
);
1451 ss
.setWord(esp
, (short)oldESP
);
1453 ss
.setWord(esp
, (short)getEFlags());
1455 ss
.setWord(esp
, (short)oldCS
);
1457 ss
.setWord(esp
, (short)oldEIP
);
1460 ss
.setWord(esp
, (short)errorCode
);
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
);
1474 esp
= (esp
& ~
0xffff) | ((esp
- 2) & 0xffff);
1475 ss
.setWord(esp
& 0xffff, (short)errorCode
);
1480 eflagsInterruptEnable
= eflagsInterruptEnableSoon
= 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
1490 if ((ss
.getDefaultSizeFlag() && (esp
< 8) && (esp
> 0)) ||
1491 !ss
.getDefaultSizeFlag() && ((esp
& 0xffff) < 8))
1492 throw ProcessorException
.STACK_SEGMENT_0
;
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()) {
1504 ss
.setWord(esp
, (short)getEFlags());
1506 ss
.setWord(esp
, (short)cs
.getSelector());
1508 ss
.setWord(esp
, (short)eip
);
1511 ss
.setWord(esp
, (short)errorCode
);
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
);
1521 esp
= (esp
& ~
0xffff) | ((esp
- 2) & 0xffff);
1522 ss
.setWord(esp
& 0xffff, (short)errorCode
);
1529 cs
.setRPL(currentPrivilegeLevel
);
1530 eflagsInterruptEnable
= eflagsInterruptEnableSoon
= false;
1533 eflagsNestedTask
= false;
1534 eflagsVirtual8086Mode
= false;
1535 eflagsResume
= false;
1537 throw new ProcessorException(ProcessorException
.Type
.GENERAL_PROTECTION
, targetSegmentSelector
+ EXT
, true);
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);
1550 //check there is room on stack
1552 if ((ss
.getDefaultSizeFlag() && (esp
< 8) && (esp
> 0)) ||
1553 !ss
.getDefaultSizeFlag() && ((esp
& 0xffff) < 8))
1554 throw ProcessorException
.STACK_SEGMENT_0
;
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()) {
1566 ss
.setWord(esp
, (short)getEFlags());
1568 ss
.setWord(esp
, (short)cs
.getSelector());
1570 ss
.setWord(esp
, (short)eip
);
1573 ss
.setWord(esp
, (short)errorCode
);
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
);
1583 esp
= (esp
& ~
0xffff) | ((esp
- 2) & 0xffff);
1584 ss
.setWord(esp
& 0xffff, (short)errorCode
);
1591 cs
.setRPL(currentPrivilegeLevel
);
1593 eflagsInterruptEnable
= eflagsInterruptEnableSoon
= false;
1595 eflagsNestedTask
= false;
1596 eflagsVirtual8086Mode
= false;
1597 eflagsResume
= false;
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
;
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()) {
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;
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
);
1649 linearMemory
.setSupervisor(isSup
);
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
;
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);
1676 if ((newStackSegment
.getDefaultSizeFlag() && (esp
< 12) && (esp
> 0)) ||
1677 !newStackSegment
.getDefaultSizeFlag() && ((esp
& 0xffff) < 12))
1678 throw ProcessorException
.STACK_SEGMENT_0
;
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();
1690 int oldCS
= cs
.getSelector();
1692 ss
= newStackSegment
;
1694 ss
.setRPL(targetSegment
.getDPL());
1698 setCPL(cs
.getDPL());
1699 if (ss
.getDefaultSizeFlag()) {
1701 ss
.setWord(esp
, (short)oldSS
);
1703 ss
.setWord(esp
, (short)oldESP
);
1705 ss
.setWord(esp
, (short)getEFlags());
1707 ss
.setWord(esp
, (short)oldCS
);
1709 ss
.setWord(esp
, (short)oldEIP
);
1712 ss
.setWord(esp
, (short)errorCode
);
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
);
1726 esp
= (esp
& ~
0xffff) | ((esp
- 2) & 0xffff);
1727 ss
.setWord(esp
& 0xffff, (short)errorCode
);
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
1740 if ((ss
.getDefaultSizeFlag() && (esp
< 8) && (esp
> 0)) ||
1741 !ss
.getDefaultSizeFlag() && ((esp
& 0xffff) < 8))
1742 throw ProcessorException
.STACK_SEGMENT_0
;
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()) {
1754 ss
.setWord(esp
, (short)getEFlags());
1756 ss
.setWord(esp
, (short)cs
.getSelector());
1758 ss
.setWord(esp
, (short)eip
);
1761 ss
.setWord(esp
, (short)errorCode
);
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
);
1771 esp
= (esp
& ~
0xffff) | ((esp
- 2) & 0xffff);
1772 ss
.setWord(esp
& 0xffff, (short)errorCode
);
1779 cs
.setRPL(currentPrivilegeLevel
);
1782 eflagsNestedTask
= false;
1783 eflagsVirtual8086Mode
= false;
1784 eflagsResume
= false;
1786 throw new ProcessorException(ProcessorException
.Type
.GENERAL_PROTECTION
, targetSegmentSelector
+ EXT
, true);
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);
1799 //check there is room on stack
1801 if ((ss
.getDefaultSizeFlag() && (esp
< 8) && (esp
> 0)) ||
1802 !ss
.getDefaultSizeFlag() && ((esp
& 0xffff) < 8))
1803 throw ProcessorException
.STACK_SEGMENT_0
;
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()) {
1815 ss
.setWord(esp
, (short)getEFlags());
1817 ss
.setWord(esp
, (short)cs
.getSelector());
1819 ss
.setWord(esp
, (short)eip
);
1822 ss
.setWord(esp
, (short)errorCode
);
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
);
1832 esp
= (esp
& ~
0xffff) | ((esp
- 2) & 0xffff);
1833 ss
.setWord(esp
& 0xffff, (short)errorCode
);
1840 cs
.setRPL(currentPrivilegeLevel
);
1843 eflagsNestedTask
= false;
1844 eflagsVirtual8086Mode
= false;
1845 eflagsResume
= false;
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
;
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()) {
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;
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
);
1899 linearMemory
.setSupervisor(isSup
);
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
;
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);
1926 if ((newStackSegment
.getDefaultSizeFlag() && (esp
< 24) && (esp
> 0)) ||
1927 !newStackSegment
.getDefaultSizeFlag() && ((esp
& 0xffff) < 24))
1928 throw ProcessorException
.STACK_SEGMENT_0
;
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();
1940 int oldCS
= cs
.getSelector();
1942 ss
= newStackSegment
;
1944 ss
.setRPL(targetSegment
.getDPL());
1948 setCPL(cs
.getDPL());
1950 if (ss
.getDefaultSizeFlag()) {
1952 ss
.setDoubleWord(esp
, oldSS
);
1954 ss
.setDoubleWord(esp
, oldESP
);
1956 ss
.setDoubleWord(esp
, getEFlags());
1958 ss
.setDoubleWord(esp
, oldCS
);
1960 ss
.setDoubleWord(esp
, oldEIP
);
1963 ss
.setDoubleWord(esp
, errorCode
);
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
);
1977 esp
= (esp
& ~
0xffff) | ((esp
- 4) & 0xffff);
1978 ss
.setDoubleWord(esp
& 0xffff, errorCode
);
1983 eflagsInterruptEnable
= eflagsInterruptEnableSoon
= false;
1986 eflagsNestedTask
= false;
1987 eflagsVirtual8086Mode
= false;
1988 eflagsResume
= false;
1989 } else if (targetSegment
.getDPL() == currentPrivilegeLevel
) {
1991 //check there is room on stack
1993 if ((ss
.getDefaultSizeFlag() && (esp
< 16) && (esp
> 0)) ||
1994 !ss
.getDefaultSizeFlag() && ((esp
& 0xffff) < 16))
1995 throw ProcessorException
.STACK_SEGMENT_0
;
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()) {
2008 ss
.setDoubleWord(esp
, getEFlags());
2010 ss
.setDoubleWord(esp
, cs
.getSelector());
2012 ss
.setDoubleWord(esp
, eip
);
2015 ss
.setDoubleWord(esp
, errorCode
);
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
);
2025 esp
= (esp
& ~
0xffff) | ((esp
- 4) & 0xffff);
2026 ss
.setDoubleWord(esp
& 0xffff, errorCode
);
2033 cs
.setRPL(currentPrivilegeLevel
);
2034 eflagsInterruptEnable
= eflagsInterruptEnableSoon
= false;
2037 eflagsNestedTask
= false;
2038 eflagsVirtual8086Mode
= false;
2039 eflagsResume
= false;
2041 throw new ProcessorException(ProcessorException
.Type
.GENERAL_PROTECTION
, targetSegmentSelector
+ EXT
, true);
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);
2054 //check there is room on stack
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
;}
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()) {
2073 ss
.setDoubleWord(esp
, getEFlags());
2075 ss
.setDoubleWord(esp
, cs
.getSelector());
2077 ss
.setDoubleWord(esp
, eip
);
2080 ss
.setDoubleWord(esp
, errorCode
);
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
);
2090 esp
= (esp
& ~
0xffff) | ((esp
- 4) & 0xffff);
2091 ss
.setDoubleWord(esp
& 0xffff, errorCode
);
2098 cs
.setRPL(currentPrivilegeLevel
);
2100 eflagsInterruptEnable
= eflagsInterruptEnableSoon
= false;
2102 eflagsNestedTask
= false;
2103 eflagsVirtual8086Mode
= false;
2104 eflagsResume
= false;
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
;
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()) {
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;
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
);
2158 linearMemory
.setSupervisor(isSup
);
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
;
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);
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
;
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();
2203 int oldCS
= cs
.getSelector();
2206 ss
= newStackSegment
;
2208 ss
.setRPL(targetSegment
.getDPL());
2212 setCPL(cs
.getDPL());
2214 if (ss
.getDefaultSizeFlag()) {
2216 ss
.setDoubleWord(esp
, oldSS
);
2218 ss
.setDoubleWord(esp
, oldESP
);
2220 ss
.setDoubleWord(esp
, getEFlags());
2222 ss
.setDoubleWord(esp
, oldCS
);
2224 ss
.setDoubleWord(esp
, oldEIP
);
2227 ss
.setDoubleWord(esp
, errorCode
);
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
);
2241 esp
= (esp
& ~
0xffff) | ((esp
- 4) & 0xffff);
2242 ss
.setDoubleWord(esp
& 0xffff, errorCode
);
2247 eflagsNestedTask
= false;
2248 eflagsVirtual8086Mode
= false;
2249 eflagsResume
= false;
2250 } else if (targetSegment
.getDPL() == currentPrivilegeLevel
) {
2252 //check there is room on stack
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
;
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()) {
2273 ss
.setDoubleWord(esp
, getEFlags());
2275 ss
.setDoubleWord(esp
, cs
.getSelector());
2277 ss
.setDoubleWord(esp
, eip
);
2280 ss
.setDoubleWord(esp
, errorCode
);
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
);
2290 esp
= (esp
& ~
0xffff) | ((esp
- 4) & 0xffff);
2291 ss
.setDoubleWord(esp
& 0xffff, errorCode
);
2298 cs
.setRPL(currentPrivilegeLevel
);
2301 eflagsNestedTask
= false;
2302 eflagsVirtual8086Mode
= false;
2303 eflagsResume
= false;
2305 throw new ProcessorException(ProcessorException
.Type
.GENERAL_PROTECTION
, targetSegmentSelector
+ EXT
, true);
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);
2318 //check there is room on stack
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
;
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()) {
2339 ss
.setDoubleWord(esp
, getEFlags());
2341 ss
.setDoubleWord(esp
, cs
.getSelector());
2343 ss
.setDoubleWord(esp
, eip
);
2346 ss
.setDoubleWord(esp
, errorCode
);
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
);
2356 esp
= (esp
& ~
0xffff) | ((esp
- 4) & 0xffff);
2357 ss
.setDoubleWord(esp
& 0xffff, errorCode
);
2363 cs
.setRPL(currentPrivilegeLevel
);
2366 eflagsNestedTask
= false;
2367 eflagsVirtual8086Mode
= false;
2368 eflagsResume
= false;
2377 public final void handleVirtual8086ModeException(ProcessorException pe
)
2381 Segment savedCS
= cs
;
2382 Segment savedSS
= ss
;
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
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
);
2400 handleVirtual8086ModeException(e
);
2404 public final void handleSoftVirtual8086ModeInterrupt(int vector
, int instructionLength
)
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;
2418 followVirtual8086ModeException(vector
, false, 0, false, true);
2419 } catch (ProcessorException e
) {
2420 //return cpu to original state
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.");
2434 handleVirtual8086ModeException(e
);
2439 public final void handleHardVirtual8086ModeInterrupt(int vector
)
2443 Segment savedCS
= cs
;
2444 Segment savedSS
= ss
;
2447 followVirtual8086ModeException(vector
, false, 0, true, false);
2448 } catch (ProcessorException e
) {
2449 //return cpu to original state
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);
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);
2484 linearMemory
.setSupervisor(isSup
);
2487 if (!gate
.isSystem())
2488 throw new ProcessorException(ProcessorException
.Type
.GENERAL_PROTECTION
, selector
+ 2, true);
2490 switch (gate
.getType()) {
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
;
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()) {
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;
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
);
2560 linearMemory
.setSupervisor(isSup
);
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;
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);
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);
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;
2607 int oldCS
= cs
.getSelector() & 0xffff;
2608 int oldEIP
= eip
& 0xffff;
2609 ss
= newStackSegment
;
2611 ss
.setRPL(targetSegment
.getDPL());
2615 setCPL(cs
.getDPL());
2616 cs
.setRPL(cs
.getDPL());
2618 if (ss
.getDefaultSizeFlag()) {
2620 ss
.setDoubleWord(esp
, gs
.getSelector() & 0xffff);
2622 ss
.setDoubleWord(esp
, fs
.getSelector() & 0xffff);
2624 ss
.setDoubleWord(esp
, ds
.getSelector() & 0xffff);
2626 ss
.setDoubleWord(esp
, es
.getSelector() & 0xffff);
2629 ss
.setDoubleWord(esp
, oldSS
);
2631 ss
.setDoubleWord(esp
, oldESP
);
2633 ss
.setDoubleWord(esp
, getEFlags());
2635 ss
.setDoubleWord(esp
, oldCS
);
2637 ss
.setDoubleWord(esp
, oldEIP
);
2640 ss
.setDoubleWord(esp
, errorCode
);
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
);
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;
2677 eflagsNestedTask
= false;
2678 eflagsVirtual8086Mode
= false;
2679 eflagsResume
= false;
2680 throw ModeSwitchException
.PROTECTED_MODE_EXCEPTION
;
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
;
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()) {
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;
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
);
2753 linearMemory
.setSupervisor(isSup
);
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;
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);
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);
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;
2800 int oldCS
= cs
.getSelector() & 0xffff;
2801 int oldEIP
= eip
& 0xffff;
2803 ss
= newStackSegment
;
2805 ss
.setRPL(targetSegment
.getDPL());
2809 setCPL(cs
.getDPL());
2811 if (ss
.getDefaultSizeFlag()) {
2813 ss
.setDoubleWord(esp
, gs
.getSelector() & 0xffff);
2815 ss
.setDoubleWord(esp
, fs
.getSelector() & 0xffff);
2817 ss
.setDoubleWord(esp
, ds
.getSelector() & 0xffff);
2819 ss
.setDoubleWord(esp
, es
.getSelector() & 0xffff);
2822 ss
.setDoubleWord(esp
, oldSS
);
2824 ss
.setDoubleWord(esp
, oldESP
);
2826 ss
.setDoubleWord(esp
, getEFlags());
2828 ss
.setDoubleWord(esp
, oldCS
);
2830 ss
.setDoubleWord(esp
, oldEIP
);
2833 ss
.setDoubleWord(esp
, errorCode
);
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
);
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
;
2867 eflagsNestedTask
= false;
2868 eflagsVirtual8086Mode
= false;
2869 eflagsResume
= false;
2870 throw ModeSwitchException
.PROTECTED_MODE_EXCEPTION
;
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
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
)
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
;
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
;
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
;
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;
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
;
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
)
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");
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;
3263 carryMethod
= method
;
3266 public void setCarryFlag(int dataOne
, int dataTwo
, int method
)
3268 carryCalculated
= false;
3271 carryMethod
= method
;
3274 private int zeroOne
;
3275 private boolean zeroCalculated
;
3277 public boolean getZeroFlag()
3282 zeroCalculated
= true;
3283 return (eflagsZero
= (zeroOne
== 0));
3287 public void setZeroFlag(boolean value
)
3289 zeroCalculated
= true;
3293 public void setZeroFlag(int data
)
3295 zeroCalculated
= false;
3299 private int signOne
;
3300 private boolean signCalculated
;
3302 public boolean getSignFlag()
3307 signCalculated
= true;
3308 return (eflagsSign
= (signOne
< 0));
3312 public void setSignFlag(boolean value
)
3314 signCalculated
= true;
3318 public void setSignFlag(int data
)
3320 signCalculated
= false;