Less spam about HALTs on insufficient CPLs
[jpcrr.git] / org / jpc / emulator / memory / codeblock / optimised / ProtectedModeUBlock.java
blob8b128ddb2f22399b5155c1d46cd287656e828b3f
1 /*
2 JPC-RR: A x86 PC Hardware Emulator
3 Release 1
5 Copyright (C) 2007-2009 Isis Innovation Limited
6 Copyright (C) 2009-2010 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.memory.codeblock.optimised;
32 import org.jpc.emulator.processor.*;
33 import org.jpc.emulator.processor.fpu64.*;
34 import org.jpc.emulator.memory.codeblock.*;
35 import org.jpc.Misc;
36 import java.util.HashMap;
38 import static org.jpc.emulator.memory.codeblock.optimised.MicrocodeSet.*;
40 /**
42 * @author Chris Dennis
44 public class ProtectedModeUBlock implements ProtectedModeCodeBlock
46 private static final boolean[] parityMap;
48 static
50 parityMap = new boolean[256];
51 for(int i = 0; i < parityMap.length; i++)
52 parityMap[i] = ((Integer.bitCount(i) & 0x1) == 0);
55 private Processor cpu;
56 private FpuState fpu;
58 private int x86Count;
60 protected int[] microcodes;
61 protected int[] cumulativeX86Length;
62 private int executeCount;
63 private HashMap<Integer, Integer> haltComplained;
64 public static OpcodeLogger opcodeCounter = null;//new OpcodeLogger("PM Stats:");
66 public ProtectedModeUBlock()
68 haltComplained = new HashMap<Integer, Integer>();
71 public ProtectedModeUBlock(int[] microcodes, int[] x86lengths)
73 this();
74 this.microcodes = microcodes;
75 cumulativeX86Length = x86lengths;
76 if(cumulativeX86Length.length == 0)
77 x86Count = 0;
78 else {
79 int count = 1;
80 for(int i = 1; i < cumulativeX86Length.length; i++)
81 if(cumulativeX86Length[i] > cumulativeX86Length[i-1]) count++;
82 x86Count = count;
86 public int getX86Length()
88 if(microcodes.length == 0)
89 return 0;
90 return cumulativeX86Length[microcodes.length-1];
93 public int getX86Count()
95 return x86Count;
98 public boolean handleMemoryRegionChange(int startAddress, int endAddress)
100 return false;
103 public String getDisplayString()
105 StringBuilder buf = new StringBuilder();
106 buf.append(this.toString()).append('\n');
107 for(int i=0; i<microcodes.length; i++)
108 buf.append(i).append(": ").append(microcodes[i]).append('\n');
109 return buf.toString();
112 public String toString()
114 return "Protected Mode Interpreted Block";
117 public InstructionSource getAsInstructionSource()
119 int[] codes = new int[microcodes.length];
120 int[] positions = new int[microcodes.length];
121 System.arraycopy(microcodes, 0, codes, 0, codes.length);
122 System.arraycopy(cumulativeX86Length, 0, positions, 0, positions.length);
124 return new ArrayBackedInstructionSource(codes, positions);
127 public int[] getMicrocodes()
129 int[] result = new int[microcodes.length];
130 System.arraycopy(microcodes, 0, result, 0, result.length);
131 return result;
134 public int execute(Processor cpu)
136 this.fpu = cpu.fpu;
137 this.cpu = cpu;
139 if(opcodeCounter != null)
140 opcodeCounter.addBlock(getMicrocodes());
142 Segment seg0 = null;
143 int addr0 = 0, reg0 = 0, reg1 = 0, reg2 = 0;
144 long reg0l = 0;
146 executeCount = 0;
147 boolean eipUpdated = false;
148 int position = 0;
150 cpu.eflagsLastAborted = false;
151 if(fpu != null)
152 fpu.setProtectedMode(true);
154 try {
155 while(position < microcodes.length) {
156 switch(microcodes[position++]) {
157 case EIP_UPDATE:
158 if(!eipUpdated) {
159 eipUpdated = true;
160 cpu.eip += cumulativeX86Length[position - 1];
162 break;
164 case UNDEFINED:
165 System.err.println("Emulated: undefined opcode");
166 throw ProcessorException.UNDEFINED;
168 case MEM_RESET: addr0 = 0; seg0 = null; break;
170 case LOAD0_EAX: reg0 = cpu.eax; break;
171 case LOAD0_ECX: reg0 = cpu.ecx; break;
172 case LOAD0_EDX: reg0 = cpu.edx; break;
173 case LOAD0_EBX: reg0 = cpu.ebx; break;
174 case LOAD0_ESP: reg0 = cpu.esp; break;
175 case LOAD0_EBP: reg0 = cpu.ebp; break;
176 case LOAD0_ESI: reg0 = cpu.esi; break;
177 case LOAD0_EDI: reg0 = cpu.edi; break;
179 case STORE0_EAX: cpu.eax = reg0; break;
180 case STORE0_ECX: cpu.ecx = reg0; break;
181 case STORE0_EDX: cpu.edx = reg0; break;
182 case STORE0_EBX: cpu.ebx = reg0; break;
183 case STORE0_ESP: cpu.esp = reg0; break;
184 case STORE0_EBP: cpu.ebp = reg0; break;
185 case STORE0_ESI: cpu.esi = reg0; break;
186 case STORE0_EDI: cpu.edi = reg0; break;
188 case LOAD1_EAX: reg1 = cpu.eax; break;
189 case LOAD1_ECX: reg1 = cpu.ecx; break;
190 case LOAD1_EDX: reg1 = cpu.edx; break;
191 case LOAD1_EBX: reg1 = cpu.ebx; break;
192 case LOAD1_ESP: reg1 = cpu.esp; break;
193 case LOAD1_EBP: reg1 = cpu.ebp; break;
194 case LOAD1_ESI: reg1 = cpu.esi; break;
195 case LOAD1_EDI: reg1 = cpu.edi; break;
197 case STORE1_EAX: cpu.eax = reg1; break;
198 case STORE1_ECX: cpu.ecx = reg1; break;
199 case STORE1_EDX: cpu.edx = reg1; break;
200 case STORE1_EBX: cpu.ebx = reg1; break;
201 case STORE1_ESP: cpu.esp = reg1; break;
202 case STORE1_EBP: cpu.ebp = reg1; break;
203 case STORE1_ESI: cpu.esi = reg1; break;
204 case STORE1_EDI: cpu.edi = reg1; break;
206 case LOAD0_AX: reg0 = cpu.eax & 0xffff; break;
207 case LOAD0_CX: reg0 = cpu.ecx & 0xffff; break;
208 case LOAD0_DX: reg0 = cpu.edx & 0xffff; break;
209 case LOAD0_BX: reg0 = cpu.ebx & 0xffff; break;
210 case LOAD0_SP: reg0 = cpu.esp & 0xffff; break;
211 case LOAD0_BP: reg0 = cpu.ebp & 0xffff; break;
212 case LOAD0_SI: reg0 = cpu.esi & 0xffff; break;
213 case LOAD0_DI: reg0 = cpu.edi & 0xffff; break;
215 case STORE0_AX: cpu.eax = (cpu.eax & ~0xffff) | (reg0 & 0xffff); break;
216 case STORE0_CX: cpu.ecx = (cpu.ecx & ~0xffff) | (reg0 & 0xffff); break;
217 case STORE0_DX: cpu.edx = (cpu.edx & ~0xffff) | (reg0 & 0xffff); break;
218 case STORE0_BX: cpu.ebx = (cpu.ebx & ~0xffff) | (reg0 & 0xffff); break;
219 case STORE0_SP: cpu.esp = (cpu.esp & ~0xffff) | (reg0 & 0xffff); break;
220 case STORE0_BP: cpu.ebp = (cpu.ebp & ~0xffff) | (reg0 & 0xffff); break;
221 case STORE0_SI: cpu.esi = (cpu.esi & ~0xffff) | (reg0 & 0xffff); break;
222 case STORE0_DI: cpu.edi = (cpu.edi & ~0xffff) | (reg0 & 0xffff); break;
224 case STORE1_AX: cpu.eax = (cpu.eax & ~0xffff) | (reg1 & 0xffff); break;
225 case STORE1_CX: cpu.ecx = (cpu.ecx & ~0xffff) | (reg1 & 0xffff); break;
226 case STORE1_DX: cpu.edx = (cpu.edx & ~0xffff) | (reg1 & 0xffff); break;
227 case STORE1_BX: cpu.ebx = (cpu.ebx & ~0xffff) | (reg1 & 0xffff); break;
228 case STORE1_SP: cpu.esp = (cpu.esp & ~0xffff) | (reg1 & 0xffff); break;
229 case STORE1_BP: cpu.ebp = (cpu.ebp & ~0xffff) | (reg1 & 0xffff); break;
230 case STORE1_SI: cpu.esi = (cpu.esi & ~0xffff) | (reg1 & 0xffff); break;
231 case STORE1_DI: cpu.edi = (cpu.edi & ~0xffff) | (reg1 & 0xffff); break;
233 case LOAD1_AX: reg1 = cpu.eax & 0xffff; break;
234 case LOAD1_CX: reg1 = cpu.ecx & 0xffff; break;
235 case LOAD1_DX: reg1 = cpu.edx & 0xffff; break;
236 case LOAD1_BX: reg1 = cpu.ebx & 0xffff; break;
237 case LOAD1_SP: reg1 = cpu.esp & 0xffff; break;
238 case LOAD1_BP: reg1 = cpu.ebp & 0xffff; break;
239 case LOAD1_SI: reg1 = cpu.esi & 0xffff; break;
240 case LOAD1_DI: reg1 = cpu.edi & 0xffff; break;
242 case LOAD0_AL: reg0 = cpu.eax & 0xff; break;
243 case LOAD0_CL: reg0 = cpu.ecx & 0xff; break;
244 case LOAD0_DL: reg0 = cpu.edx & 0xff; break;
245 case LOAD0_BL: reg0 = cpu.ebx & 0xff; break;
246 case LOAD0_AH: reg0 = (cpu.eax >> 8) & 0xff; break;
247 case LOAD0_CH: reg0 = (cpu.ecx >> 8) & 0xff; break;
248 case LOAD0_DH: reg0 = (cpu.edx >> 8) & 0xff; break;
249 case LOAD0_BH: reg0 = (cpu.ebx >> 8) & 0xff; break;
251 case STORE0_AL: cpu.eax = (cpu.eax & ~0xff) | (reg0 & 0xff); break;
252 case STORE0_CL: cpu.ecx = (cpu.ecx & ~0xff) | (reg0 & 0xff); break;
253 case STORE0_DL: cpu.edx = (cpu.edx & ~0xff) | (reg0 & 0xff); break;
254 case STORE0_BL: cpu.ebx = (cpu.ebx & ~0xff) | (reg0 & 0xff); break;
255 case STORE0_AH: cpu.eax = (cpu.eax & ~0xff00) | ((reg0 << 8) & 0xff00); break;
256 case STORE0_CH: cpu.ecx = (cpu.ecx & ~0xff00) | ((reg0 << 8) & 0xff00); break;
257 case STORE0_DH: cpu.edx = (cpu.edx & ~0xff00) | ((reg0 << 8) & 0xff00); break;
258 case STORE0_BH: cpu.ebx = (cpu.ebx & ~0xff00) | ((reg0 << 8) & 0xff00); break;
260 case LOAD1_AL: reg1 = cpu.eax & 0xff; break;
261 case LOAD1_CL: reg1 = cpu.ecx & 0xff; break;
262 case LOAD1_DL: reg1 = cpu.edx & 0xff; break;
263 case LOAD1_BL: reg1 = cpu.ebx & 0xff; break;
264 case LOAD1_AH: reg1 = (cpu.eax >> 8) & 0xff; break;
265 case LOAD1_CH: reg1 = (cpu.ecx >> 8) & 0xff; break;
266 case LOAD1_DH: reg1 = (cpu.edx >> 8) & 0xff; break;
267 case LOAD1_BH: reg1 = (cpu.ebx >> 8) & 0xff; break;
269 case STORE1_AL: cpu.eax = (cpu.eax & ~0xff) | (reg1 & 0xff); break;
270 case STORE1_CL: cpu.ecx = (cpu.ecx & ~0xff) | (reg1 & 0xff); break;
271 case STORE1_DL: cpu.edx = (cpu.edx & ~0xff) | (reg1 & 0xff); break;
272 case STORE1_BL: cpu.ebx = (cpu.ebx & ~0xff) | (reg1 & 0xff); break;
273 case STORE1_AH: cpu.eax = (cpu.eax & ~0xff00) | ((reg1 << 8) & 0xff00); break;
274 case STORE1_CH: cpu.ecx = (cpu.ecx & ~0xff00) | ((reg1 << 8) & 0xff00); break;
275 case STORE1_DH: cpu.edx = (cpu.edx & ~0xff00) | ((reg1 << 8) & 0xff00); break;
276 case STORE1_BH: cpu.ebx = (cpu.ebx & ~0xff00) | ((reg1 << 8) & 0xff00); break;
278 case LOAD0_CR0: reg0 = cpu.getCR0(); break;
279 case LOAD0_CR2: reg0 = cpu.getCR2(); break;
280 case LOAD0_CR3: reg0 = cpu.getCR3(); break;
281 case LOAD0_CR4: reg0 = cpu.getCR4(); break;
283 case STORE0_CR0: cpu.setCR0(reg0); break;
284 case STORE0_CR2: cpu.setCR2(reg0); break;
285 case STORE0_CR3: cpu.setCR3(reg0); break;
286 case STORE0_CR4: cpu.setCR4(reg0); break;
288 case LOAD0_DR0: reg0 = cpu.getDR0(); break;
289 case LOAD0_DR1: reg0 = cpu.getDR1(); break;
290 case LOAD0_DR2: reg0 = cpu.getDR2(); break;
291 case LOAD0_DR3: reg0 = cpu.getDR3(); break;
292 case LOAD0_DR6: reg0 = cpu.getDR6(); break;
293 case LOAD0_DR7: reg0 = cpu.getDR7(); break;
295 case STORE0_DR0: cpu.setDR0(reg0); break;
296 case STORE0_DR1: cpu.setDR1(reg0); break;
297 case STORE0_DR2: cpu.setDR2(reg0); break;
298 case STORE0_DR3: cpu.setDR3(reg0); break;
299 case STORE0_DR6: cpu.setDR6(reg0); break;
300 case STORE0_DR7: cpu.setDR7(reg0); break;
302 case LOAD0_ES: reg0 = 0xffff & cpu.es.getSelector(); break;
303 case LOAD0_CS: reg0 = 0xffff & cpu.cs.getSelector(); break;
304 case LOAD0_SS: reg0 = 0xffff & cpu.ss.getSelector(); break;
305 case LOAD0_DS: reg0 = 0xffff & cpu.ds.getSelector(); break;
306 case LOAD0_FS: reg0 = 0xffff & cpu.fs.getSelector(); break;
307 case LOAD0_GS: reg0 = 0xffff & cpu.gs.getSelector(); break;
309 case STORE0_ES: cpu.es = loadSegment(reg0); break;
310 //case STORE0_CS:
311 case STORE0_SS: {
312 Segment temp = loadSegment(reg0);
313 if(temp == SegmentFactory.NULL_SEGMENT)
314 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
315 cpu.ss = temp; cpu.eflagsInterruptEnable = false;
316 } break;
317 case STORE0_DS: cpu.ds = loadSegment(reg0); break;
318 case STORE0_FS: cpu.fs = loadSegment(reg0); break;
319 case STORE0_GS: cpu.gs = loadSegment(reg0); break;
321 case STORE1_ES: cpu.es = loadSegment(reg1); break;
322 //case STORE1_CS:
323 case STORE1_SS: {
324 Segment temp = loadSegment(reg1);
325 if(temp == SegmentFactory.NULL_SEGMENT)
326 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
327 cpu.ss = temp; cpu.eflagsInterruptEnable = false;
328 } break;
329 case STORE1_DS: cpu.ds = loadSegment(reg1); break;
330 case STORE1_FS: cpu.fs = loadSegment(reg1); break;
331 case STORE1_GS: cpu.gs = loadSegment(reg1); break;
333 case STORE0_FLAGS: cpu.setEFlags((cpu.getEFlags() & ~0xffff) | (reg0 & 0xffff)); break;
334 case STORE0_EFLAGS: cpu.setEFlags(reg0); break;
336 case LOAD0_FLAGS: reg0 = 0xffff & cpu.getEFlags(); break;
337 case LOAD0_EFLAGS: reg0 = cpu.getEFlags(); break;
339 case LOAD0_IB: reg0 = microcodes[position++] & 0xff; break;
340 case LOAD0_IW: reg0 = microcodes[position++] & 0xffff; break;
341 case LOAD0_ID: reg0 = microcodes[position++]; break;
343 case LOAD1_IB: reg1 = microcodes[position++] & 0xff; break;
344 case LOAD1_IW: reg1 = microcodes[position++] & 0xffff; break;
345 case LOAD1_ID: reg1 = microcodes[position++]; break;
347 case LOAD2_EAX: reg2 = cpu.eax; break;
348 case LOAD2_AX: reg2 = cpu.eax & 0xffff; break;
349 case LOAD2_AL: reg2 = cpu.eax & 0xff; break;
350 case LOAD2_CL: reg2 = cpu.ecx & 0xffff; break;
351 case LOAD2_IB: reg2 = microcodes[position++] & 0xff; break;
353 case LOAD_SEG_ES: seg0 = cpu.es; break;
354 case LOAD_SEG_CS: seg0 = cpu.cs; break;
355 case LOAD_SEG_SS: seg0 = cpu.ss; break;
356 case LOAD_SEG_DS: seg0 = cpu.ds; break;
357 case LOAD_SEG_FS: seg0 = cpu.fs; break;
358 case LOAD_SEG_GS: seg0 = cpu.gs; break;
360 case ADDR_REG1: addr0 += reg1; break;
361 case ADDR_2REG1: addr0 += (reg1 << 1); break;
362 case ADDR_4REG1: addr0 += (reg1 << 2); break;
363 case ADDR_8REG1: addr0 += (reg1 << 3); break;
365 case ADDR_EAX: addr0 += cpu.eax; break;
366 case ADDR_ECX: addr0 += cpu.ecx; break;
367 case ADDR_EDX: addr0 += cpu.edx; break;
368 case ADDR_EBX: addr0 += cpu.ebx; break;
369 case ADDR_ESP: addr0 += cpu.esp; break;
370 case ADDR_EBP: addr0 += cpu.ebp; break;
371 case ADDR_ESI: addr0 += cpu.esi; break;
372 case ADDR_EDI: addr0 += cpu.edi; break;
374 case ADDR_AX: addr0 += ((short)cpu.eax); break;
375 case ADDR_CX: addr0 += ((short)cpu.ecx); break;
376 case ADDR_DX: addr0 += ((short)cpu.edx); break;
377 case ADDR_BX: addr0 += ((short)cpu.ebx); break;
378 case ADDR_SP: addr0 += ((short)cpu.esp); break;
379 case ADDR_BP: addr0 += ((short)cpu.ebp); break;
380 case ADDR_SI: addr0 += ((short)cpu.esi); break;
381 case ADDR_DI: addr0 += ((short)cpu.edi); break;
383 case ADDR_2EAX: addr0 += (cpu.eax << 1); break;
384 case ADDR_2ECX: addr0 += (cpu.ecx << 1); break;
385 case ADDR_2EDX: addr0 += (cpu.edx << 1); break;
386 case ADDR_2EBX: addr0 += (cpu.ebx << 1); break;
387 case ADDR_2ESP: addr0 += (cpu.esp << 1); break;
388 case ADDR_2EBP: addr0 += (cpu.ebp << 1); break;
389 case ADDR_2ESI: addr0 += (cpu.esi << 1); break;
390 case ADDR_2EDI: addr0 += (cpu.edi << 1); break;
392 case ADDR_4EAX: addr0 += (cpu.eax << 2); break;
393 case ADDR_4ECX: addr0 += (cpu.ecx << 2); break;
394 case ADDR_4EDX: addr0 += (cpu.edx << 2); break;
395 case ADDR_4EBX: addr0 += (cpu.ebx << 2); break;
396 case ADDR_4ESP: addr0 += (cpu.esp << 2); break;
397 case ADDR_4EBP: addr0 += (cpu.ebp << 2); break;
398 case ADDR_4ESI: addr0 += (cpu.esi << 2); break;
399 case ADDR_4EDI: addr0 += (cpu.edi << 2); break;
401 case ADDR_8EAX: addr0 += (cpu.eax << 3); break;
402 case ADDR_8ECX: addr0 += (cpu.ecx << 3); break;
403 case ADDR_8EDX: addr0 += (cpu.edx << 3); break;
404 case ADDR_8EBX: addr0 += (cpu.ebx << 3); break;
405 case ADDR_8ESP: addr0 += (cpu.esp << 3); break;
406 case ADDR_8EBP: addr0 += (cpu.ebp << 3); break;
407 case ADDR_8ESI: addr0 += (cpu.esi << 3); break;
408 case ADDR_8EDI: addr0 += (cpu.edi << 3); break;
410 case ADDR_IB: addr0 += ((byte)microcodes[position++]); break;
411 case ADDR_IW: addr0 += ((short)microcodes[position++]); break;
412 case ADDR_ID: addr0 += microcodes[position++]; break;
414 case ADDR_MASK16: addr0 &= 0xffff; break;
416 case ADDR_uAL: addr0 += 0xff & cpu.eax; break;
418 case LOAD0_ADDR: reg0 = addr0; break;
420 case LOAD0_MEM_BYTE: reg0 = 0xff & seg0.getByte(addr0); break;
421 case LOAD0_MEM_WORD: reg0 = 0xffff & seg0.getWord(addr0); break;
422 case LOAD0_MEM_DWORD: reg0 = seg0.getDoubleWord(addr0); break;
423 case LOAD0_MEM_QWORD: reg0l = seg0.getQuadWord(addr0); break;
425 case LOAD1_MEM_BYTE: reg1 = 0xff & seg0.getByte(addr0); break;
426 case LOAD1_MEM_WORD: reg1 = 0xffff & seg0.getWord(addr0); break;
427 case LOAD1_MEM_DWORD: reg1 = seg0.getDoubleWord(addr0); break;
429 case STORE0_MEM_BYTE: seg0.setByte(addr0, (byte)reg0); break;
430 case STORE0_MEM_WORD: seg0.setWord(addr0, (short)reg0); break;
431 case STORE0_MEM_DWORD: seg0.setDoubleWord(addr0, reg0); break;
432 case STORE0_MEM_QWORD: seg0.setQuadWord(addr0, reg0l); break;
434 case STORE1_MEM_BYTE: seg0.setByte(addr0, (byte)reg1); break;
435 case STORE1_MEM_WORD: seg0.setWord(addr0, (short)reg1); break;
436 case STORE1_MEM_DWORD: seg0.setDoubleWord(addr0, reg1); break;
438 case XOR: reg0 ^= reg1; break;
439 case AND: reg0 &= reg1; break;
440 case OR: reg0 |= reg1; break;
441 case NOT: reg0 = ~reg0; break;
443 case SUB: reg2 = reg0; reg0 = reg2 - reg1; break;
444 case SBB: reg2 = reg0; reg0 = reg2 - (reg1 + (cpu.getCarryFlag() ? 1 : 0)); break;
445 case ADD: reg2 = reg0; reg0 = reg2 + reg1; break;
446 case ADC: reg2 = reg0; reg0 = reg2 + reg1 + (cpu.getCarryFlag() ? 1 : 0); break;
447 case NEG: reg0 = -reg0; break;
449 case MUL_O8: mul_o8(reg0); break;
450 case MUL_O16: mul_o16(reg0); break;
451 case MUL_O32: mul_o32(reg0); break;
453 case IMULA_O8: imula_o8((byte)reg0); break;
454 case IMULA_O16: imula_o16((short)reg0); break;
455 case IMULA_O32: imula_o32(reg0); break;
457 case IMUL_O16: reg0 = imul_o16((short)reg0, (short)reg1); break;
458 case IMUL_O32: reg0 = imul_o32(reg0, reg1); break;
460 case DIV_O8: div_o8(reg0); break;
461 case DIV_O16: div_o16(reg0); break;
462 case DIV_O32: div_o32(reg0); break;
464 case IDIV_O8: idiv_o8((byte)reg0); break;
465 case IDIV_O16: idiv_o16((short)reg0); break;
466 case IDIV_O32: idiv_o32(reg0); break;
468 case BSF: reg0 = bsf(reg1, reg0); break;
469 case BSR: reg0 = bsr(reg1, reg0); break;
471 case BT_MEM: bt_mem(reg1, seg0, addr0); break;
472 case BTS_MEM: bts_mem(reg1, seg0, addr0); break;
473 case BTR_MEM: btr_mem(reg1, seg0, addr0); break;
474 case BTC_MEM: btc_mem(reg1, seg0, addr0); break;
476 case BT_O32: reg1 &= 0x1f; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); break;
477 case BT_O16: reg1 &= 0xf; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); break;
478 case BTS_O32: reg1 &= 0x1f; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); reg0 |= (1 << reg1); break;
479 case BTS_O16: reg1 &= 0xf; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); reg0 |= (1 << reg1); break;
480 case BTR_O32: reg1 &= 0x1f; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); reg0 &= ~(1 << reg1); break;
481 case BTR_O16: reg1 &= 0xf; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); reg0 &= ~(1 << reg1); break;
482 case BTC_O32: reg1 &= 0x1f; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); reg0 ^= (1 << reg1); break;
483 case BTC_O16: reg1 &= 0xf; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); reg0 ^= (1 << reg1); break;
485 case ROL_O8: reg2 = reg1 & 0x7; reg0 = (reg0 << reg2) | (reg0 >>> (8 - reg2)); break;
486 case ROL_O16: reg2 = reg1 & 0xf; reg0 = (reg0 << reg2) | (reg0 >>> (16 - reg2)); break;
487 case ROL_O32: reg1 &= 0x1f; reg0 = (reg0 << reg1) | (reg0 >>> (32 - reg1)); break;
489 case ROR_O8: reg1 &= 0x7; reg0 = (reg0 >>> reg1) | (reg0 << (8 - reg1)); break;
490 case ROR_O16: reg1 &= 0xf; reg0 = (reg0 >>> reg1) | (reg0 << (16 - reg1)); break;
491 case ROR_O32: reg1 &= 0x1f; reg0 = (reg0 >>> reg1) | (reg0 << (32 - reg1)); break;
493 case RCL_O8: reg1 &= 0x1f; reg1 %= 9; reg0 |= (cpu.getCarryFlag() ? 0x100 : 0);
494 reg0 = (reg0 << reg1) | (reg0 >>> (9 - reg1)); break;
495 case RCL_O16: reg1 &= 0x1f; reg1 %= 17; reg0 |= (cpu.getCarryFlag() ? 0x10000 : 0);
496 reg0 = (reg0 << reg1) | (reg0 >>> (17 - reg1)); break;
497 case RCL_O32: reg1 &= 0x1f; reg0l = (0xffffffffl & reg0) | (cpu.getCarryFlag() ? 0x100000000l : 0);
498 reg0 = (int)(reg0l = (reg0l << reg1) | (reg0l >>> (33 - reg1))); break;
500 case RCR_O8: reg1 &= 0x1f; reg1 %= 9; reg0 |= (cpu.getCarryFlag() ? 0x100 : 0);
501 reg2 = (cpu.getCarryFlag() ^ ((reg0 & 0x80) != 0) ? 1:0);
502 reg0 = (reg0 >>> reg1) | (reg0 << (9 - reg1));
503 break;
504 case RCR_O16: reg1 &= 0x1f; reg1 %= 17;
505 reg2 = (cpu.getCarryFlag() ^ ((reg0 & 0x8000) != 0) ? 1:0);
506 reg0 |= (cpu.getCarryFlag() ? 0x10000 : 0);
507 reg0 = (reg0 >>> reg1) | (reg0 << (17 - reg1));
508 break;
509 case RCR_O32: reg1 &= 0x1f; reg0l = (0xffffffffl & reg0) | (cpu.getCarryFlag() ? 0x100000000L : 0);
510 reg2 = (cpu.getCarryFlag() ^ ((reg0 & 0x80000000) != 0) ? 1:0);
511 reg0 = (int)(reg0l = (reg0l >>> reg1) | (reg0l << (33 - reg1)));
512 break;
514 case SHL: reg2 = reg0; reg0 <<= reg1; break;
515 case SHR: reg2 = reg0; reg0 >>>= reg1; break;
516 case SAR_O8: reg2 = reg0; reg0 = ((byte)reg0) >> reg1; break;
517 case SAR_O16: reg2 = reg0; reg0 = ((short)reg0) >> reg1; break;
518 case SAR_O32: reg2 = reg0; reg0 >>= reg1; break;
520 case SHLD_O16: {
521 int i = reg0; reg2 &= 0x1f;
522 if(reg2 < 16) {
523 reg0 = (reg0 << reg2) | (reg1 >>> (16 - reg2));
524 reg1 = reg2;
525 reg2 = i;
526 } else {
527 i = (reg1 & 0xFFFF) | (reg0 << 16);
528 reg0 = (reg1 << (reg2 - 16)) | ((reg0 & 0xFFFF) >>> (32 - reg2));
529 reg1 = reg2 - 15;
530 reg2 = i >> 1;
532 } break;
533 case SHLD_O32: {
534 int i = reg0; reg2 &= 0x1f;
535 if(reg2 != 0)
536 reg0 = (reg0 << reg2) | (reg1 >>> (32 - reg2));
537 reg1 = reg2; reg2 = i;
538 } break;
540 case SHRD_O16: {
541 int i = reg0; reg2 &= 0x1f;
542 if(reg2 < 16) {
543 reg0 = (reg0 >>> reg2) | (reg1 << (16 - reg2));
544 reg1 = reg2;
545 reg2 = i;
546 } else {
547 i = (reg0 & 0xFFFF) | (reg1 << 16);
548 reg0 = (reg1 >>> (reg2 -16)) | (reg0 << (32 - reg2));
549 reg1 = reg2;
550 reg2 = i;
552 } break;
553 case SHRD_O32: {
554 int i = reg0; reg2 &= 0x1f;
555 if(reg2 != 0)
556 reg0 = (reg0 >>> reg2) | (reg1 << (32 - reg2));
557 reg1 = reg2; reg2 = i;
558 } break;
560 case CWD: if((cpu.eax & 0x8000) == 0) cpu.edx &= 0xffff0000; else cpu.edx |= 0x0000ffff; break;
561 case CDQ: if((cpu.eax & 0x80000000) == 0) cpu.edx = 0; else cpu.edx = -1; break;
563 case AAA: aaa(); break;
564 case AAD: aad(reg0); break;
565 case AAM: aam(reg0); break;
566 case AAS: aas(); break;
568 case DAA: daa(); break;
569 case DAS: das(); break;
571 case LAHF: lahf(); break;
572 case SAHF: sahf(); break;
574 case CLC: cpu.setCarryFlag(false); break;
575 case STC: cpu.setCarryFlag(true); break;
576 case CLI:
577 if(cpu.getIOPrivilegeLevel() >= cpu.getCPL()) {
578 cpu.eflagsInterruptEnable = false;
579 cpu.eflagsInterruptEnableSoon = false;
580 } else
581 if((cpu.getIOPrivilegeLevel() < cpu.getCPL()) && (cpu.getCPL() == 3) && ((cpu.getCR4() & 1) != 0)) {
582 cpu.eflagsInterruptEnableSoon = false;
583 } else {
584 System.err.println("Emulated: IOPL=" + cpu.getIOPrivilegeLevel() + ", CPL=" + cpu.getCPL());
585 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);
587 break;
588 case STI:
589 if(cpu.getIOPrivilegeLevel() >= cpu.getCPL()) {
590 cpu.eflagsInterruptEnable = true;
591 cpu.eflagsInterruptEnableSoon = true;
592 } else
593 if((cpu.getIOPrivilegeLevel() < cpu.getCPL()) && (cpu.getCPL() == 3) && ((cpu.getEFlags() & (1 << 20)) == 0))
594 cpu.eflagsInterruptEnableSoon = true;
595 else
596 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);
597 break;
598 case CLD: cpu.eflagsDirection = false; break;
599 case STD: cpu.eflagsDirection = true; break;
600 case CMC: cpu.setCarryFlag(!cpu.getCarryFlag()); break;
602 case SIGN_EXTEND_8_16: reg0 = 0xffff & ((byte)reg0); break;
603 case SIGN_EXTEND_8_32: reg0 = (byte)reg0; break;
604 case SIGN_EXTEND_16_32: reg0 = (short)reg0; break;
606 case INC: reg0++; break;
607 case DEC: reg0--; break;
609 case HALT:
610 if(cpu.getCPL() != 0) {
611 if(haltComplained.containsKey(position - 1))
612 haltComplained.put(position - 1, haltComplained.get(position - 1) + 1);
613 else
614 haltComplained.put(position - 1, 1);
615 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);
616 } else
617 cpu.waitForInterrupt(); break;
619 case JO_O8: jo_o8((byte)reg0); break;
620 case JNO_O8: jno_o8((byte)reg0); break;
621 case JC_O8: jc_o8((byte)reg0); break;
622 case JNC_O8: jnc_o8((byte)reg0); break;
623 case JZ_O8: jz_o8((byte)reg0); break;
624 case JNZ_O8: jnz_o8((byte)reg0); break;
625 case JNA_O8: jna_o8((byte)reg0); break;
626 case JA_O8: ja_o8((byte)reg0); break;
627 case JS_O8: js_o8((byte)reg0); break;
628 case JNS_O8: jns_o8((byte)reg0); break;
629 case JP_O8: jp_o8((byte)reg0); break;
630 case JNP_O8: jnp_o8((byte)reg0); break;
631 case JL_O8: jl_o8((byte)reg0); break;
632 case JNL_O8: jnl_o8((byte)reg0); break;
633 case JNG_O8: jng_o8((byte)reg0); break;
634 case JG_O8: jg_o8((byte)reg0); break;
636 case JO_O16: jo_o16((short)reg0); break;
637 case JNO_O16: jno_o16((short)reg0); break;
638 case JC_O16: jc_o16((short)reg0); break;
639 case JNC_O16: jnc_o16((short)reg0); break;
640 case JZ_O16: jz_o16((short)reg0); break;
641 case JNZ_O16: jnz_o16((short)reg0); break;
642 case JNA_O16: jna_o16((short)reg0); break;
643 case JA_O16: ja_o16((short)reg0); break;
644 case JS_O16: js_o16((short)reg0); break;
645 case JNS_O16: jns_o16((short)reg0); break;
646 case JP_O16: jp_o16((short)reg0); break;
647 case JNP_O16: jnp_o16((short)reg0); break;
648 case JL_O16: jl_o16((short)reg0); break;
649 case JNL_O16: jnl_o16((short)reg0); break;
650 case JNG_O16: jng_o16((short)reg0); break;
651 case JG_O16: jg_o16((short)reg0); break;
653 case JO_O32: jo_o32(reg0); break;
654 case JNO_O32: jno_o32(reg0); break;
655 case JC_O32: jc_o32(reg0); break;
656 case JNC_O32: jnc_o32(reg0); break;
657 case JZ_O32: jz_o32(reg0); break;
658 case JNZ_O32: jnz_o32(reg0); break;
659 case JNA_O32: jna_o32(reg0); break;
660 case JA_O32: ja_o32(reg0); break;
661 case JS_O32: js_o32(reg0); break;
662 case JNS_O32: jns_o32(reg0); break;
663 case JP_O32: jp_o32(reg0); break;
664 case JNP_O32: jnp_o32(reg0); break;
665 case JL_O32: jl_o32(reg0); break;
666 case JNL_O32: jnl_o32(reg0); break;
667 case JNG_O32: jng_o32(reg0); break;
668 case JG_O32: jg_o32(reg0); break;
670 case JCXZ: jcxz((byte)reg0); break;
671 case JECXZ: jecxz((byte)reg0); break;
673 case LOOP_CX: loop_cx((byte)reg0); break;
674 case LOOP_ECX: loop_ecx((byte)reg0); break;
675 case LOOPZ_CX: loopz_cx((byte)reg0); break;
676 case LOOPZ_ECX: loopz_ecx((byte)reg0); break;
677 case LOOPNZ_CX: loopnz_cx((byte)reg0); break;
678 case LOOPNZ_ECX: loopnz_ecx((byte)reg0); break;
680 case JUMP_O8: jump_o8((byte)reg0); break;
681 case JUMP_O16: jump_o16((short)reg0); break;
682 case JUMP_O32: jump_o32(reg0); break;
684 case JUMP_ABS_O16: jump_abs(reg0); break;
685 case JUMP_ABS_O32: jump_abs(reg0); break;
687 case JUMP_FAR_O16: jump_far(reg0, reg1); break;
688 case JUMP_FAR_O32: jump_far(reg0, reg1); break;
691 case CALL_O16:
692 if(cpu.ss.getDefaultSizeFlag())
693 call_o16_a32(reg0);
694 else
695 call_o16_a16(reg0);
696 break;
698 case CALL_O32:
699 if(cpu.ss.getDefaultSizeFlag())
700 call_o32_a32(reg0);
701 else
702 call_o32_a16(reg0);
703 break;
705 case CALL_ABS_O16: {
706 if(cpu.ss.getDefaultSizeFlag())
707 call_abs_o16_a32(reg0);
708 else
709 call_abs_o16_a16(reg0);
710 } break;
712 case CALL_ABS_O32: {
713 if(cpu.ss.getDefaultSizeFlag())
714 call_abs_o32_a32(reg0);
715 else
716 call_abs_o32_a16(reg0);
717 } break;
719 case CALL_FAR_O16: {
720 if(cpu.ss.getDefaultSizeFlag())
721 call_far_o16_a32(reg0, reg1);
722 else
723 call_far_o16_a16(reg0, reg1);
724 } break;
726 case CALL_FAR_O32: {
727 if(cpu.ss.getDefaultSizeFlag())
728 call_far_o32_a32(reg0, reg1);
729 else
730 call_far_o32_a16(reg0, reg1);
731 } break;
733 case RET_O16: {
734 if(cpu.ss.getDefaultSizeFlag())
735 ret_o16_a32();
736 else
737 ret_o16_a16();
738 } break;
740 case RET_O32: {
741 if (cpu.ss.getDefaultSizeFlag())
742 ret_o32_a32();
743 else
744 ret_o32_a16();
745 } break;
747 case RET_IW_O16: {
748 if (cpu.ss.getDefaultSizeFlag())
749 ret_iw_o16_a32((short)reg0);
750 else
751 ret_iw_o16_a16((short)reg0);
752 } break;
754 case RET_IW_O32: {
755 if (cpu.ss.getDefaultSizeFlag())
756 ret_iw_o32_a32((short)reg0);
757 else
758 ret_iw_o32_a16((short)reg0);
759 } break;
761 case RET_FAR_O16: {
762 if (cpu.ss.getDefaultSizeFlag())
763 ret_far_o16_a32(0);
764 else
765 ret_far_o16_a16(0);
767 } break;
769 case RET_FAR_O32: {
770 if (cpu.ss.getDefaultSizeFlag())
771 ret_far_o32_a32(0);
772 else
773 ret_far_o32_a16(0);
774 } break;
776 case RET_FAR_IW_O16: {
777 if (cpu.ss.getDefaultSizeFlag())
778 ret_far_o16_a32((short)reg0);
779 else
780 ret_far_o16_a16((short)reg0);
782 } break;
784 case RET_FAR_IW_O32: {
785 if (cpu.ss.getDefaultSizeFlag())
786 ret_far_o32_a32((short)reg0);
787 else
788 ret_far_o32_a16((short)reg0);
789 } break;
792 case INT_O16:
793 cpu.handleSoftProtectedModeInterrupt(reg0, getInstructionLength(position));
794 break;
795 case INT_O32:
796 cpu.handleSoftProtectedModeInterrupt(reg0, getInstructionLength(position));
797 break;
798 case INT3_O16:
799 case INT3_O32:
800 cpu.handleSoftProtectedModeInterrupt(3, getInstructionLength(position));
801 break;
802 case INTO_O16:
803 case INTO_O32:
804 if (cpu.getOverflowFlag() == true)
805 cpu.handleSoftProtectedModeInterrupt(4, getInstructionLength(position));
806 break;
808 case IRET_O32:
809 if (cpu.ss.getDefaultSizeFlag())
810 reg0 = iret_o32_a32();
811 else
812 reg0 = iret_o32_a16();
813 break;
815 case IRET_O16:
816 if (cpu.ss.getDefaultSizeFlag())
817 reg0 = iret_o16_a32();
818 else
819 reg0 = iret_o16_a16();
820 break;
822 case SYSENTER: sysenter(); break;
823 case SYSEXIT: sysexit(reg0, reg1); break;
825 case IN_O8: reg0 = in_o8(reg0); break;
826 case IN_O16: reg0 = in_o16(reg0); break;
827 case IN_O32: reg0 = in_o32(reg0); break;
829 case OUT_O8: out_o8(reg0, reg1); break;
830 case OUT_O16: out_o16(reg0, reg1); break;
831 case OUT_O32: out_o32(reg0, reg1); break;
833 case CMOVO: if (cpu.getOverflowFlag()) reg0 = reg1; break;
834 case CMOVNO: if (!cpu.getOverflowFlag()) reg0 = reg1; break;
835 case CMOVC: if (cpu.getCarryFlag()) reg0 = reg1; break;
836 case CMOVNC: if (!cpu.getCarryFlag()) reg0 = reg1; break;
837 case CMOVZ: if (cpu.getZeroFlag()) reg0 = reg1; break;
838 case CMOVNZ: if (!cpu.getZeroFlag()) reg0 = reg1; break;
839 case CMOVNA: if (cpu.getCarryFlag() || cpu.getZeroFlag()) reg0 = reg1; break;
840 case CMOVA: if ((!cpu.getCarryFlag()) && (!cpu.getZeroFlag())) reg0 = reg1; break;
841 case CMOVS: if (cpu.getSignFlag()) reg0 = reg1; break;
842 case CMOVNS: if (!cpu.getSignFlag()) reg0 = reg1; break;
843 case CMOVP: if (cpu.getParityFlag()) reg0 = reg1; break;
844 case CMOVNP: if (!cpu.getParityFlag()) reg0 = reg1; break;
845 case CMOVL: if (cpu.getSignFlag() != cpu.getOverflowFlag()) reg0 = reg1; break;
846 case CMOVNL: if (cpu.getSignFlag() == cpu.getOverflowFlag()) reg0 = reg1; break;
847 case CMOVNG: if (cpu.getZeroFlag() || (cpu.getSignFlag() != cpu.getOverflowFlag())) reg0 = reg1; break;
848 case CMOVG: if ((!cpu.getZeroFlag()) && (cpu.getSignFlag() == cpu.getOverflowFlag())) reg0 = reg1; break;
850 case SETO: reg0 = cpu.getOverflowFlag() ? 1 : 0; break;
851 case SETNO: reg0 = cpu.getOverflowFlag() ? 0 : 1; break;
852 case SETC: reg0 = cpu.getCarryFlag() ? 1 : 0; break;
853 case SETNC: reg0 = cpu.getCarryFlag() ? 0 : 1; break;
854 case SETZ: reg0 = cpu.getZeroFlag() ? 1 : 0; break;
855 case SETNZ: reg0 = cpu.getZeroFlag() ? 0 : 1; break;
856 case SETNA: reg0 = cpu.getCarryFlag() || cpu.getZeroFlag() ? 1 : 0; break;
857 case SETA: reg0 = cpu.getCarryFlag() || cpu.getZeroFlag() ? 0 : 1; break;
858 case SETS: reg0 = cpu.getSignFlag() ? 1 : 0; break;
859 case SETNS: reg0 = cpu.getSignFlag() ? 0 : 1; break;
860 case SETP: reg0 = cpu.getParityFlag() ? 1 : 0; break;
861 case SETNP: reg0 = cpu.getParityFlag() ? 0 : 1; break;
862 case SETL: reg0 = cpu.getSignFlag() != cpu.getOverflowFlag() ? 1 : 0; break;
863 case SETNL: reg0 = cpu.getSignFlag() != cpu.getOverflowFlag() ? 0 : 1; break;
864 case SETNG: reg0 = cpu.getZeroFlag() || (cpu.getSignFlag() != cpu.getOverflowFlag()) ? 1 : 0; break;
865 case SETG: reg0 = cpu.getZeroFlag() || (cpu.getSignFlag() != cpu.getOverflowFlag()) ? 0 : 1; break;
867 case SALC: reg0 = cpu.getCarryFlag() ? -1 : 0; break;
869 case SMSW: reg0 = cpu.getCR0() & 0xffff; break;
870 case LMSW: if (cpu.getCPL() != 0) throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
871 cpu.setCR0((cpu.getCR0() & ~0xe) | (reg0 & 0xe)); break;
873 case CMPXCHG:
874 if (reg2 == reg0) {
875 reg0 = reg1;
876 reg1 = reg2;
877 } else
878 reg1 = reg0;
879 break;
881 case CMPXCHG8B: {
882 long edxeax = ((cpu.edx & 0xffffffffL) << 32) | (cpu.eax & 0xffffffffL);
883 if (edxeax == reg0l) {
884 cpu.setZeroFlag(true);
885 reg0l = ((cpu.ecx & 0xffffffffL) << 32) | (cpu.ebx & 0xffffffffL);
886 } else {
887 cpu.setZeroFlag(false);
888 cpu.edx = (int)(reg0l >> 32);
889 cpu.eax = (int)reg0l;
891 } break;
893 case BSWAP: reg0 = reverseBytes(reg0); break;
895 case ENTER_O32: {
896 if (cpu.ss.getDefaultSizeFlag())
897 enter_o32_a32(reg0, reg1);
898 else {
899 System.err.println("Critical error: need enter_o32_a16.");
900 throw new IllegalStateException("PMODE O32 A16 ENTER is unimplemented");
902 } break;
904 case ENTER_O16: {
905 if (cpu.ss.getDefaultSizeFlag())
906 enter_o16_a32(reg0, reg1);
907 else
908 enter_o16_a16(reg0, reg1);
909 } break;
911 case LEAVE_O32: {
912 if (cpu.ss.getDefaultSizeFlag())
913 leave_o32_a32();
914 else
915 leave_o32_a16();
916 } break;
918 case LEAVE_O16: {
919 if (cpu.ss.getDefaultSizeFlag())
920 leave_o16_a32();
921 else
922 leave_o16_a16();
923 } break;
925 case PUSH_O32: {
926 if (cpu.ss.getDefaultSizeFlag())
927 push_o32_a32(reg0);
928 else
929 push_o32_a16(reg0);
930 } break;
932 case PUSH_O16: {
933 if (cpu.ss.getDefaultSizeFlag())
934 push_o16_a32((short)reg0);
935 else
936 push_o16_a16((short)reg0);
937 } break;
939 case PUSHF_O32: {
940 if (cpu.ss.getDefaultSizeFlag())
941 push_o32_a32(~0x30000 & reg0);
942 else
943 push_o32_a16(~0x30000 & reg0);
944 } break;
946 case PUSHF_O16: {
947 if (cpu.ss.getDefaultSizeFlag())
948 push_o16_a32((short)reg0);
949 else
950 push_o16_a16((short)reg0);
951 } break;
953 case POP_O32: {
954 if (cpu.ss.getDefaultSizeFlag()) {
955 reg1 = cpu.esp + 4;
956 if (microcodes[position] == STORE0_SS)
957 cpu.eflagsInterruptEnable = false;
958 reg0 = cpu.ss.getDoubleWord(cpu.esp);
959 } else {
960 reg1 = (cpu.esp & ~0xffff) | ((cpu.esp + 4) & 0xffff);
961 if (microcodes[position] == STORE0_SS)
962 cpu.eflagsInterruptEnable = false;
963 reg0 = cpu.ss.getDoubleWord(0xffff & cpu.esp);
965 } break;
967 case POP_O16: {
968 if (cpu.ss.getDefaultSizeFlag()) {
969 reg1 = cpu.esp + 2;
970 if (microcodes[position] == STORE0_SS)
971 cpu.eflagsInterruptEnable = false;
972 reg0 = 0xffff & cpu.ss.getWord(cpu.esp);
973 } else {
974 reg1 = (cpu.esp & ~0xffff) | ((cpu.esp + 2) & 0xffff);
975 if (microcodes[position] == STORE0_SS)
976 cpu.eflagsInterruptEnable = false;
977 reg0 = 0xffff & cpu.ss.getWord(0xffff & cpu.esp);
979 } break;
981 case POPF_O32: {
982 if (cpu.ss.getDefaultSizeFlag()) {
983 reg0 = cpu.ss.getDoubleWord(cpu.esp);
984 cpu.esp += 4;
985 } else {
986 reg0 = cpu.ss.getDoubleWord(0xffff & cpu.esp);
987 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp + 4) & 0xffff);
989 if (cpu.getCPL() == 0)
990 reg0 = ((cpu.getEFlags() & 0x20000) | (reg0 & ~(0x20000 | 0x180000)));
991 else {
992 if (cpu.getCPL() > cpu.eflagsIOPrivilegeLevel)
993 reg0 = ((cpu.getEFlags() & 0x23200) | (reg0 & ~(0x23200 | 0x180000)));
994 else
995 reg0 = ((cpu.getEFlags() & 0x23000) | (reg0 & ~(0x23000 | 0x180000)));
997 } break;
999 case POPF_O16: {
1000 if (cpu.ss.getDefaultSizeFlag()) {
1001 reg0 = 0xffff & cpu.ss.getWord(cpu.esp);
1002 cpu.esp += 2;
1003 } else {
1004 reg0 = 0xffff & cpu.ss.getWord(0xffff & cpu.esp);
1005 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp + 2) & 0xffff);
1007 if (cpu.getCPL() != 0)
1008 if (cpu.getCPL() > cpu.eflagsIOPrivilegeLevel)
1009 reg0 = ((cpu.getEFlags() & 0x3200) | (reg0 & ~0x3200));
1010 else
1011 reg0 = ((cpu.getEFlags() & 0x3000) | (reg0 & ~0x3000));
1012 } break;
1014 case PUSHA:
1015 if (cpu.ss.getDefaultSizeFlag())
1016 pusha_a32();
1017 else
1018 pusha_a16();
1019 break;
1021 case PUSHAD:
1022 if (cpu.ss.getDefaultSizeFlag())
1023 pushad_a32();
1024 else
1025 pushad_a16();
1026 break;
1028 case POPA: {
1029 if (cpu.ss.getDefaultSizeFlag())
1030 popa_a32();
1031 else
1032 popa_a16();
1033 } break;
1035 case POPAD: {
1036 if (cpu.ss.getDefaultSizeFlag())
1037 popad_a32();
1038 else
1039 popad_a16();
1040 } break;
1042 case CMPSB_A32: cmpsb_a32(seg0); break;
1043 case CMPSW_A32: cmpsw_a32(seg0); break;
1044 case CMPSD_A32: cmpsd_a32(seg0); break;
1045 case REPE_CMPSB_A16: repe_cmpsb_a16(seg0); break;
1046 case REPE_CMPSB_A32: repe_cmpsb_a32(seg0); break;
1047 case REPE_CMPSW_A16: repe_cmpsw_a16(seg0); break;
1048 case REPE_CMPSW_A32: repe_cmpsw_a32(seg0); break;
1049 case REPE_CMPSD_A16: repe_cmpsd_a16(seg0); break;
1050 case REPE_CMPSD_A32: repe_cmpsd_a32(seg0); break;
1051 case REPNE_CMPSB_A16: repne_cmpsb_a16(seg0); break;
1052 case REPNE_CMPSW_A16: repne_cmpsw_a16(seg0); break;
1053 case REPNE_CMPSD_A16: repne_cmpsd_a16(seg0); break;
1054 case REPNE_CMPSB_A32: repne_cmpsb_a32(seg0); break;
1055 case REPNE_CMPSW_A32: repne_cmpsw_a32(seg0); break;
1056 case REPNE_CMPSD_A32: repne_cmpsd_a32(seg0); break;
1058 case INSB_A32: insb_a32(reg0); break;
1059 case INSW_A32: insw_a32(reg0); break;
1060 case INSD_A32: insd_a32(reg0); break;
1061 case REP_INSB_A32: rep_insb_a32(reg0); break;
1062 case REP_INSW_A32: rep_insw_a32(reg0); break;
1063 case REP_INSD_A32: rep_insd_a32(reg0); break;
1065 case LODSB_A16: lodsb_a16(seg0); break;
1066 case LODSB_A32: lodsb_a32(seg0); break;
1067 case LODSW_A16: lodsw_a16(seg0); break;
1068 case LODSW_A32: lodsw_a32(seg0); break;
1069 case LODSD_A32: lodsd_a32(seg0); break;
1070 case REP_LODSB_A32: rep_lodsb_a32(seg0); break;
1071 case REP_LODSW_A32: rep_lodsw_a32(seg0); break;
1072 case REP_LODSD_A32: rep_lodsd_a32(seg0); break;
1074 case MOVSB_A16: movsb_a16(seg0); break;
1075 case MOVSW_A16: movsw_a16(seg0); break;
1076 case MOVSD_A16: movsd_a16(seg0); break;
1077 case REP_MOVSB_A16: rep_movsb_a16(seg0); break;
1078 case REP_MOVSW_A16: rep_movsw_a16(seg0); break;
1079 case REP_MOVSD_A16: rep_movsd_a16(seg0); break;
1080 case MOVSB_A32: movsb_a32(seg0); break;
1081 case MOVSW_A32: movsw_a32(seg0); break;
1082 case MOVSD_A32: movsd_a32(seg0); break;
1083 case REP_MOVSB_A32: rep_movsb_a32(seg0); break;
1084 case REP_MOVSW_A32: rep_movsw_a32(seg0); break;
1085 case REP_MOVSD_A32: rep_movsd_a32(seg0); break;
1087 case OUTSB_A16: outsb_a16(reg0, seg0); break;
1088 case OUTSW_A16: outsw_a16(reg0, seg0); break;
1089 case OUTSD_A16: outsd_a16(reg0, seg0); break;
1090 case REP_OUTSB_A16: rep_outsb_a16(reg0, seg0); break;
1091 case REP_OUTSW_A16: rep_outsw_a16(reg0, seg0); break;
1092 case REP_OUTSD_A16: rep_outsd_a16(reg0, seg0); break;
1093 case OUTSB_A32: outsb_a32(reg0, seg0); break;
1094 case OUTSW_A32: outsw_a32(reg0, seg0); break;
1095 case OUTSD_A32: outsd_a32(reg0, seg0); break;
1096 case REP_OUTSB_A32: rep_outsb_a32(reg0, seg0); break;
1097 case REP_OUTSW_A32: rep_outsw_a32(reg0, seg0); break;
1098 case REP_OUTSD_A32: rep_outsd_a32(reg0, seg0); break;
1100 case SCASB_A16: scasb_a16(reg0); break;
1101 case SCASB_A32: scasb_a32(reg0); break;
1102 case SCASW_A32: scasw_a32(reg0); break;
1103 case SCASD_A32: scasd_a32(reg0); break;
1104 case REPE_SCASB_A16: repe_scasb_a16(reg0); break;
1105 case REPE_SCASB_A32: repe_scasb_a32(reg0); break;
1106 case REPE_SCASW_A16: repe_scasw_a16(reg0); break;
1107 case REPE_SCASW_A32: repe_scasw_a32(reg0); break;
1108 case REPE_SCASD_A16: repe_scasd_a16(reg0); break;
1109 case REPE_SCASD_A32: repe_scasd_a32(reg0); break;
1110 case REPNE_SCASB_A16: repne_scasb_a16(reg0); break;
1111 case REPNE_SCASB_A32: repne_scasb_a32(reg0); break;
1112 case REPNE_SCASW_A16: repne_scasw_a16(reg0); break;
1113 case REPNE_SCASW_A32: repne_scasw_a32(reg0); break;
1114 case REPNE_SCASD_A16: repne_scasd_a16(reg0); break;
1115 case REPNE_SCASD_A32: repne_scasd_a32(reg0); break;
1117 case STOSB_A16: stosb_a16(reg0); break;
1118 case STOSB_A32: stosb_a32(reg0); break;
1119 case STOSW_A16: stosw_a16(reg0); break;
1120 case STOSW_A32: stosw_a32(reg0); break;
1121 case STOSD_A16: stosd_a16(reg0); break;
1122 case STOSD_A32: stosd_a32(reg0); break;
1123 case REP_STOSB_A16: rep_stosb_a16(reg0); break;
1124 case REP_STOSB_A32: rep_stosb_a32(reg0); break;
1125 case REP_STOSW_A16: rep_stosw_a16(reg0); break;
1126 case REP_STOSW_A32: rep_stosw_a32(reg0); break;
1127 case REP_STOSD_A16: rep_stosd_a16(reg0); break;
1128 case REP_STOSD_A32: rep_stosd_a32(reg0); break;
1130 case LGDT_O16: cpu.gdtr = cpu.createDescriptorTableSegment(reg1 & 0x00ffffff, reg0); break;
1131 case LGDT_O32: cpu.gdtr = cpu.createDescriptorTableSegment(reg1, reg0); break;
1132 case SGDT_O16: reg1 = cpu.gdtr.getBase() & 0x00ffffff; reg0 = cpu.gdtr.getLimit(); break;
1133 case SGDT_O32: reg1 = cpu.gdtr.getBase(); reg0 = cpu.gdtr.getLimit(); break;
1135 case LIDT_O16: cpu.idtr = cpu.createDescriptorTableSegment(reg1 & 0x00ffffff, reg0); break;
1136 case LIDT_O32: cpu.idtr = cpu.createDescriptorTableSegment(reg1, reg0); break;
1137 case SIDT_O16: reg1 = cpu.idtr.getBase() & 0x00ffffff; reg0 = cpu.idtr.getLimit(); break;
1138 case SIDT_O32: reg1 = cpu.idtr.getBase(); reg0 = cpu.idtr.getLimit(); break;
1140 case LLDT: cpu.ldtr = lldt(reg0); break;
1141 case SLDT: reg0 = 0xffff & cpu.ldtr.getSelector(); break;
1143 case LTR: cpu.tss = ltr(reg0); break;
1144 case STR: reg0 = 0xffff & cpu.tss.getSelector(); break;
1146 case VERR:
1147 try {
1148 Segment test = cpu.getSegment(reg0 & 0xffff);
1149 int type = test.getType();
1150 if (((type & ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) == 0) || (((type & ProtectedModeSegment.TYPE_CODE_CONFORMING) == 0) && ((cpu.getCPL() > test.getDPL()) || (test.getRPL() > test.getDPL()))))
1151 cpu.setZeroFlag(false);
1152 else
1153 cpu.setZeroFlag(((type & ProtectedModeSegment.TYPE_CODE) == 0) || ((type & ProtectedModeSegment.TYPE_CODE_READABLE) != 0));
1154 } catch (ProcessorException e) {
1155 cpu.setZeroFlag(false);
1156 } break;
1158 case VERW:
1159 try {
1160 Segment test = cpu.getSegment(reg0 & 0xffff);
1161 int type = test.getType();
1162 if (((type & ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) == 0) || (((type & ProtectedModeSegment.TYPE_CODE_CONFORMING) == 0) && ((cpu.getCPL() > test.getDPL()) || (test.getRPL() > test.getDPL()))))
1163 cpu.setZeroFlag(false);
1164 else
1165 cpu.setZeroFlag(((type & ProtectedModeSegment.TYPE_CODE) == 0) && ((type & ProtectedModeSegment.TYPE_DATA_WRITABLE) != 0));
1166 } catch (ProcessorException e) {
1167 cpu.setZeroFlag(false);
1168 } break;
1170 case CLTS: if (cpu.getCPL() != 0) throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
1171 cpu.setCR0(cpu.getCR0() & ~0x8); break;
1173 case INVLPG: if (cpu.getCPL() != 0) throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
1174 cpu.linearMemory.invalidateTLBEntry(seg0.translateAddressRead(addr0)); break;
1176 case CPUID: cpuid(); break;
1178 case LAR: reg0 = lar(reg0, reg1); break;
1179 case LSL: reg0 = lsl(reg0, reg1); break;
1181 case WRMSR: if (cpu.getCPL() != 0) throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
1182 cpu.setMSR(reg0, (reg2 & 0xffffffffl) | ((reg1 & 0xffffffffl) << 32)); break;
1183 case RDMSR: if (cpu.getCPL() != 0) throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
1184 long msr = cpu.getMSR(reg0); reg0 = (int)msr; reg1 = (int)(msr >>> 32); break;
1186 case RDTSC: long tsc = rdtsc(); reg0 = (int)tsc; reg1 = (int)(tsc >>> 32); break;
1188 case CMPXCHG_O8_FLAGS: sub_o8_flags(reg2 - reg1, reg2, reg1); break;
1189 case CMPXCHG_O16_FLAGS: sub_o16_flags(reg2 - reg1, reg2, reg1); break;
1190 case CMPXCHG_O32_FLAGS: sub_o32_flags((0xffffffffl & reg2) - (0xffffffffl & reg1), reg2, reg1); break;
1192 case BITWISE_FLAGS_O8: bitwise_flags((byte)reg0); break;
1193 case BITWISE_FLAGS_O16: bitwise_flags((short)reg0); break;
1194 case BITWISE_FLAGS_O32: bitwise_flags(reg0); break;
1196 case SUB_O8_FLAGS: sub_o8_flags(reg0, reg2, reg1); break;
1197 case SUB_O16_FLAGS: sub_o16_flags(reg0, reg2, reg1); break;
1198 case SUB_O32_FLAGS: sub_o32_flags(reg0l, reg2, reg1); break;
1200 case ADD_O8_FLAGS: add_o8_flags(reg0, reg2, reg1); break;
1201 case ADD_O16_FLAGS: add_o16_flags(reg0, reg2, reg1); break;
1202 case ADD_O32_FLAGS: add_o32_flags(reg0l, reg2, reg1); break;
1204 case ADC_O8_FLAGS: adc_o8_flags(reg0, reg2, reg1); break;
1205 case ADC_O16_FLAGS: adc_o16_flags(reg0, reg2, reg1); break;
1206 case ADC_O32_FLAGS: adc_o32_flags(reg0l, reg2, reg1); break;
1208 case SBB_O8_FLAGS: sbb_o8_flags(reg0, reg2, reg1); break;
1209 case SBB_O16_FLAGS: sbb_o16_flags(reg0, reg2, reg1); break;
1210 case SBB_O32_FLAGS: sbb_o32_flags(reg0l, reg2, reg1); break;
1212 case INC_O8_FLAGS: inc_flags((byte)reg0); break;
1213 case INC_O16_FLAGS: inc_flags((short)reg0); break;
1214 case INC_O32_FLAGS: inc_flags(reg0); break;
1216 case DEC_O8_FLAGS: dec_flags((byte)reg0); break;
1217 case DEC_O16_FLAGS: dec_flags((short)reg0); break;
1218 case DEC_O32_FLAGS: dec_flags(reg0); break;
1220 case SHL_O8_FLAGS: shl_flags((byte)reg0, (byte)reg2, reg1); break;
1221 case SHL_O16_FLAGS: shl_flags((short)reg0, (short)reg2, reg1); break;
1222 case SHL_O32_FLAGS: shl_flags(reg0, reg2, reg1); break;
1224 case SHR_O8_FLAGS: shr_flags((byte)reg0, reg2, reg1); break;
1225 case SHR_O16_FLAGS: shr_flags((short)reg0, reg2, reg1); break;
1226 case SHR_O32_FLAGS: shr_flags(reg0, reg2, reg1); break;
1228 case SAR_O8_FLAGS: sar_flags((byte)reg0, (byte)reg2, reg1); break;
1229 case SAR_O16_FLAGS: sar_flags((short)reg0, (short)reg2, reg1); break;
1230 case SAR_O32_FLAGS: sar_flags(reg0, reg2, reg1); break;
1232 case RCL_O8_FLAGS: rcl_o8_flags(reg0, reg1); break;
1233 case RCL_O16_FLAGS: rcl_o16_flags(reg0, reg1); break;
1234 case RCL_O32_FLAGS: rcl_o32_flags(reg0l, reg1); break;
1236 case RCR_O8_FLAGS: rcr_o8_flags(reg0, reg1, reg2); break;
1237 case RCR_O16_FLAGS: rcr_o16_flags(reg0, reg1, reg2); break;
1238 case RCR_O32_FLAGS: rcr_o32_flags(reg0l, reg1, reg2); break;
1240 case ROL_O8_FLAGS: rol_flags((byte)reg0, reg1); break;
1241 case ROL_O16_FLAGS: rol_flags((short)reg0, reg1); break;
1242 case ROL_O32_FLAGS: rol_flags(reg0, reg1); break;
1244 case ROR_O8_FLAGS: ror_flags((byte)reg0, reg1); break;
1245 case ROR_O16_FLAGS: ror_flags((short)reg0, reg1); break;
1246 case ROR_O32_FLAGS: ror_flags(reg0, reg1); break;
1248 case NEG_O8_FLAGS: neg_flags((byte)reg0); break;
1249 case NEG_O16_FLAGS: neg_flags((short)reg0); break;
1250 case NEG_O32_FLAGS: neg_flags(reg0); break;
1252 case CPL_CHECK:
1253 if(cpu.getCPL() != 0)
1254 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);
1255 break;
1257 case INSTRUCTION_START:
1258 executeCount++;
1259 if(cpu.eflagsMachineHalt) throw ProcessorException.TRACESTOP;
1260 //HALT being aborted is special.
1261 if(!cpu.eflagsWaiting)
1262 cpu.instructionExecuted();
1263 break;
1264 default:
1265 if(!Misc.isFPUOp(microcodes[position - 1])) {
1266 System.err.println("Critical error: Unknown uCode " + microcodes[position - 1] + ".");
1267 throw new IllegalStateException("Unknown uCode P" + microcodes[position - 1]);
1270 cpu.useFPU(microcodes[position - 1] == FWAIT);
1271 int x = fpu.doFPUOp(microcodes[position - 1], microcodes[position], seg0, addr0, reg0, reg1, reg2,
1272 reg0l);
1273 //Handle buffer updates.
1274 if((x & 1) != 0) reg0 = fpu.getReg0();
1275 if((x & 2) != 0) reg1 = fpu.getReg1();
1276 if((x & 4) != 0) reg2 = fpu.getReg2();
1277 if((x & 8) != 0) reg0l = fpu.getReg0l();
1278 if((x & 16) != 0) position++;
1281 } catch (ProcessorException e) {
1282 int nextPosition = position - 1; //this makes position point at the microcode that just barfed
1284 if (eipUpdated)
1285 cpu.eip -= cumulativeX86Length[nextPosition]; // undo the eipUpdate
1287 if (!e.pointsToSelf()) {
1288 cpu.eip += cumulativeX86Length[nextPosition];
1289 } else {
1290 for (int selfPosition = nextPosition; selfPosition >= 0; selfPosition--) {
1291 if (cumulativeX86Length[selfPosition] != cumulativeX86Length[nextPosition]) {
1292 cpu.eip += cumulativeX86Length[selfPosition];
1293 break;
1298 if(e.getType() == ProcessorException.Type.TASK_SWITCH)
1299 e.printStackTrace();
1301 if(e.getType() != ProcessorException.Type.PAGE_FAULT && e.getType() != ProcessorException.Type.TRACESTOP && e.getType() != ProcessorException.Type.NO_FPU) {
1302 boolean isGPF = (e.getType() == ProcessorException.Type.GENERAL_PROTECTION);
1303 boolean isHalt = isGPF && haltComplained.containsKey(position -1);
1304 boolean isFirstHalt = isHalt && (haltComplained.get(position - 1) == 1);
1305 if(!isHalt && isGPF)
1306 e.printStackTrace();
1307 if(!isHalt || isFirstHalt) {
1308 System.err.println("Emulated: cs selector = " + Integer.toHexString(cpu.cs.getSelector())
1309 + ", cs base = " + Integer.toHexString(cpu.cs.getBase()) + ", EIP = "
1310 + Integer.toHexString(cpu.eip));
1311 System.err.println("Emulated: processor exception at 0x" +
1312 Integer.toHexString(cpu.cs.translateAddressRead(cpu.eip)) + ": " + e);
1316 if(e.getType() != ProcessorException.Type.TRACESTOP) //Swallow trace stops!
1317 cpu.handleProtectedModeException(e);
1318 else {
1319 executeCount--;
1320 cpu.eflagsLastAborted = true;
1322 } catch (IllegalStateException e) {
1323 System.err.println("Critical error: Failed at index: " + (position -1) + " with microcode: " +
1324 microcodes[position-1]);
1325 System.err.println("Informational: Microcodes for failed block:");
1326 System.err.println(this.getDisplayString());
1327 throw e;
1328 } catch (NullPointerException e) {
1329 System.err.println("Critical error: Failed at index: " + (position -1) + " with microcode: " +
1330 microcodes[position-1]);
1331 System.err.println("Informational: Microcodes for failed block:");
1332 System.err.println(this.getDisplayString());
1333 throw e;
1336 return Math.max(executeCount, 0);
1339 private int getInstructionLength(int position)
1341 int nextPosition = position - 1; //this makes position point at the microcode that just barfed
1343 int ans = -cumulativeX86Length[nextPosition]; // undo the eipUpdate
1345 for (int selfPosition = nextPosition; selfPosition >= 0; selfPosition--) {
1346 if (cumulativeX86Length[selfPosition] != cumulativeX86Length[nextPosition]) {
1347 ans += cumulativeX86Length[selfPosition];
1348 break;
1351 if (ans <= 0)
1352 ans = -ans; // instruction was first instruction in block
1353 return ans;
1356 private final void cmpsb_a32(Segment seg0)
1358 int addrOne = cpu.esi;
1359 int addrTwo = cpu.edi;
1361 int dataOne = 0xff & seg0.getByte(addrOne);
1362 int dataTwo = 0xff & cpu.es.getByte(addrTwo);
1363 if (cpu.eflagsDirection) {
1364 addrOne -= 1;
1365 addrTwo -= 1;
1366 } else {
1367 addrOne += 1;
1368 addrTwo += 1;
1371 cpu.esi = addrOne;
1372 cpu.edi = addrTwo;
1374 sub_o8_flags(dataOne - dataTwo, dataOne, dataTwo);
1377 private final void cmpsw_a32(Segment seg0)
1379 int addrOne = cpu.esi;
1380 int addrTwo = cpu.edi;
1382 int dataOne = 0xffff & seg0.getWord(addrOne);
1383 int dataTwo = 0xffff & cpu.es.getWord(addrTwo);
1384 if (cpu.eflagsDirection) {
1385 addrOne -= 2;
1386 addrTwo -= 2;
1387 } else {
1388 addrOne += 2;
1389 addrTwo += 2;
1392 cpu.esi = addrOne;
1393 cpu.edi = addrTwo;
1395 sub_o16_flags(dataOne - dataTwo, dataOne, dataTwo);
1398 private final void cmpsd_a32(Segment seg0)
1400 int addrOne = cpu.esi;
1401 int addrTwo = cpu.edi;
1403 int dataOne = seg0.getDoubleWord(addrOne);
1404 int dataTwo = cpu.es.getDoubleWord(addrTwo);
1405 if (cpu.eflagsDirection) {
1406 addrOne -= 4;
1407 addrTwo -= 4;
1408 } else {
1409 addrOne += 4;
1410 addrTwo += 4;
1413 cpu.esi = addrOne;
1414 cpu.edi = addrTwo;
1416 sub_o32_flags((0xffffffffl & dataOne) - (0xffffffffl & dataTwo), dataOne, dataTwo);
1419 private final void repe_cmpsb_a16(Segment seg0)
1421 int count = 0xFFFF & cpu.ecx;
1422 int addrOne = 0xFFFF & cpu.esi;
1423 int addrTwo = 0xFFFF & cpu.edi;
1424 boolean used = count != 0;
1425 int dataOne = 0;
1426 int dataTwo = 0;
1428 try {
1429 if (cpu.eflagsDirection) {
1430 while (count != 0) {
1431 //check hardware interrupts
1432 dataOne = 0xff & seg0.getByte(addrOne);
1433 dataTwo = 0xff & cpu.es.getByte(addrTwo);
1434 count--;
1435 addrOne -= 1;
1436 addrTwo -= 1;
1437 if (dataOne != dataTwo) break;
1439 } else {
1440 while (count != 0) {
1441 //check hardware interrupts
1442 dataOne = 0xff & seg0.getByte(addrOne);
1443 dataTwo = 0xff & cpu.es.getByte(addrTwo);
1444 count--;
1445 addrOne += 1;
1446 addrTwo += 1;
1447 if (dataOne != dataTwo) break;
1451 finally {
1452 executeCount += ((cpu.ecx &0xFFFF) - count);
1453 cpu.ecx = (cpu.ecx & ~0xFFFF)|(count & 0xFFFF);
1454 cpu.esi = (cpu.esi & ~0xFFFF)|(addrOne & 0xFFFF);
1455 cpu.edi = (cpu.edi & ~0xFFFF)|(addrTwo & 0xFFFF);
1457 if (used)
1458 sub_o8_flags(dataOne - dataTwo, dataOne, dataTwo);
1462 private final void repe_cmpsb_a32(Segment seg0)
1464 int count = cpu.ecx;
1465 int addrOne = cpu.esi;
1466 int addrTwo = cpu.edi;
1467 boolean used = count != 0;
1468 int dataOne = 0;
1469 int dataTwo = 0;
1471 try {
1472 if (cpu.eflagsDirection) {
1473 while (count != 0) {
1474 //check hardware interrupts
1475 dataOne = 0xff & seg0.getByte(addrOne);
1476 dataTwo = 0xff & cpu.es.getByte(addrTwo);
1477 count--;
1478 addrOne -= 1;
1479 addrTwo -= 1;
1480 if (dataOne != dataTwo) break;
1482 } else {
1483 while (count != 0) {
1484 //check hardware interrupts
1485 dataOne = 0xff & seg0.getByte(addrOne);
1486 dataTwo = 0xff & cpu.es.getByte(addrTwo);
1487 count--;
1488 addrOne += 1;
1489 addrTwo += 1;
1490 if (dataOne != dataTwo) break;
1494 finally {
1495 executeCount += (cpu.ecx - count);
1496 cpu.ecx = count;
1497 cpu.esi = addrOne;
1498 cpu.edi = addrTwo;
1500 if (used)
1501 sub_o8_flags(dataOne - dataTwo, dataOne, dataTwo);
1505 private final void repe_cmpsw_a16(Segment seg0)
1507 int count = 0xFFFF & cpu.ecx;
1508 int addrOne = 0xFFFF & cpu.esi;
1509 int addrTwo = 0xFFFF & cpu.edi;
1510 boolean used = count != 0;
1511 int dataOne = 0;
1512 int dataTwo = 0;
1514 try {
1515 if (cpu.eflagsDirection) {
1516 while (count != 0) {
1517 //check hardware interrupts
1518 dataOne = 0xffff & seg0.getWord(addrOne);
1519 dataTwo = 0xffff & cpu.es.getWord(addrTwo);
1520 count--;
1521 addrOne -= 2;
1522 addrTwo -= 2;
1523 if (dataOne != dataTwo) break;
1525 } else {
1526 while (count != 0) {
1527 //check hardware interrupts
1528 dataOne = 0xffff & seg0.getWord(addrOne);
1529 dataTwo = 0xffff & cpu.es.getWord(addrTwo);
1530 count--;
1531 addrOne += 2;
1532 addrTwo += 2;
1533 if (dataOne != dataTwo) break;
1537 finally {
1538 executeCount += ((cpu.ecx &0xFFFF) - count);
1539 cpu.ecx = (cpu.ecx & ~0xFFFF)|(count & 0xFFFF);
1540 cpu.esi = (cpu.esi & ~0xFFFF)|(addrOne & 0xFFFF);
1541 cpu.edi = (cpu.edi & ~0xFFFF)|(addrTwo & 0xFFFF);
1543 if (used)
1544 sub_o16_flags(dataOne - dataTwo, dataOne, dataTwo);
1548 private final void repe_cmpsw_a32(Segment seg0)
1550 int count = cpu.ecx;
1551 int addrOne = cpu.esi;
1552 int addrTwo = cpu.edi;
1553 boolean used = count != 0;
1554 int dataOne = 0;
1555 int dataTwo = 0;
1557 try {
1558 if (cpu.eflagsDirection) {
1559 while (count != 0) {
1560 //check hardware interrupts
1561 dataOne = 0xffff & seg0.getWord(addrOne);
1562 dataTwo = 0xffff & cpu.es.getWord(addrTwo);
1563 count--;
1564 addrOne -= 2;
1565 addrTwo -= 2;
1566 if (dataOne != dataTwo) break;
1568 } else {
1569 while (count != 0) {
1570 //check hardware interrupts
1571 dataOne = 0xffff & seg0.getWord(addrOne);
1572 dataTwo = 0xffff & cpu.es.getWord(addrTwo);
1573 count--;
1574 addrOne += 2;
1575 addrTwo += 2;
1576 if (dataOne != dataTwo) break;
1580 finally {
1581 executeCount += (cpu.ecx - count);
1582 cpu.ecx = count;
1583 cpu.esi = addrOne;
1584 cpu.edi = addrTwo;
1586 if (used)
1587 sub_o16_flags(dataOne - dataTwo, dataOne, dataTwo);
1591 private final void repe_cmpsd_a16(Segment seg0)
1593 int count = 0xFFFF & cpu.ecx;
1594 int addrOne = 0xFFFF & cpu.esi;
1595 int addrTwo = 0xFFFF & cpu.edi;
1596 boolean used = count != 0;
1597 int dataOne = 0;
1598 int dataTwo = 0;
1600 try {
1601 if (cpu.eflagsDirection) {
1602 while (count != 0) {
1603 //check hardware interrupts
1604 dataOne = seg0.getDoubleWord(addrOne);
1605 dataTwo = cpu.es.getDoubleWord(addrTwo);
1606 count--;
1607 addrOne -= 4;
1608 addrTwo -= 4;
1609 if (dataOne != dataTwo) break;
1611 } else {
1612 while (count != 0) {
1613 //check hardware interrupts
1614 dataOne = seg0.getDoubleWord(addrOne);
1615 dataTwo = cpu.es.getDoubleWord(addrTwo);
1616 count--;
1617 addrOne += 4;
1618 addrTwo += 4;
1619 if (dataOne != dataTwo) break;
1623 finally {
1624 executeCount += ((cpu.ecx &0xFFFF) - count);
1625 cpu.ecx = (cpu.ecx & ~0xFFFF)|(count & 0xFFFF);
1626 cpu.esi = (cpu.esi & ~0xFFFF)|(addrOne & 0xFFFF);
1627 cpu.edi = (cpu.edi & ~0xFFFF)|(addrTwo & 0xFFFF);
1629 if (used)
1630 sub_o32_flags((0xffffffffl & dataOne) - (0xffffffffl & dataTwo), dataOne, dataTwo);
1634 private final void repe_cmpsd_a32(Segment seg0)
1636 int count = cpu.ecx;
1637 int addrOne = cpu.esi;
1638 int addrTwo = cpu.edi;
1639 boolean used = count != 0;
1640 int dataOne = 0;
1641 int dataTwo = 0;
1643 try {
1644 if (cpu.eflagsDirection) {
1645 while (count != 0) {
1646 //check hardware interrupts
1647 dataOne = seg0.getDoubleWord(addrOne);
1648 dataTwo = cpu.es.getDoubleWord(addrTwo);
1649 count--;
1650 addrOne -= 4;
1651 addrTwo -= 4;
1652 if (dataOne != dataTwo) break;
1654 } else {
1655 while (count != 0) {
1656 //check hardware interrupts
1657 dataOne = seg0.getDoubleWord(addrOne);
1658 dataTwo = cpu.es.getDoubleWord(addrTwo);
1659 count--;
1660 addrOne += 4;
1661 addrTwo += 4;
1662 if (dataOne != dataTwo) break;
1666 finally {
1667 executeCount += (cpu.ecx - count);
1668 cpu.ecx = count;
1669 cpu.esi = addrOne;
1670 cpu.edi = addrTwo;
1672 if (used)
1673 sub_o32_flags((0xffffffffl & dataOne) - (0xffffffffl & dataTwo), dataOne, dataTwo);
1677 private final void repne_cmpsb_a16(Segment seg0)
1679 int count = 0xFFFF & cpu.ecx;
1680 int addrOne = 0xFFFF & cpu.esi;
1681 int addrTwo = 0xFFFF & cpu.edi;
1682 boolean used = count != 0;
1683 int dataOne = 0;
1684 int dataTwo = 0;
1686 try {
1687 if (cpu.eflagsDirection) {
1688 while (count != 0) {
1689 //check hardware interrupts
1690 dataOne = 0xff & seg0.getByte(addrOne);
1691 dataTwo = 0xff & cpu.es.getByte(addrTwo);
1692 count--;
1693 addrOne -= 1;
1694 addrTwo -= 1;
1695 if (dataOne == dataTwo) break;
1697 } else {
1698 while (count != 0) {
1699 //check hardware interrupts
1700 dataOne = 0xff & seg0.getByte(addrOne);
1701 dataTwo = 0xff & cpu.es.getByte(addrTwo);
1702 count--;
1703 addrOne += 1;
1704 addrTwo += 1;
1705 if (dataOne == dataTwo) break;
1709 finally {
1710 executeCount += ((cpu.ecx &0xFFFF) - count);
1711 cpu.ecx = (cpu.ecx & ~0xFFFF)|(count & 0xFFFF);
1712 cpu.esi = (cpu.esi & ~0xFFFF)|(addrOne & 0xFFFF);
1713 cpu.edi = (cpu.edi & ~0xFFFF)|(addrTwo & 0xFFFF);
1715 if (used)
1716 sub_o8_flags(dataOne - dataTwo, dataOne, dataTwo);
1721 private final void repne_cmpsb_a32(Segment seg0)
1723 int count = cpu.ecx;
1724 int addrOne = cpu.esi;
1725 int addrTwo = cpu.edi;
1726 boolean used = count != 0;
1727 int dataOne = 0;
1728 int dataTwo = 0;
1730 try {
1731 if (cpu.eflagsDirection) {
1732 while (count != 0) {
1733 //check hardware interrupts
1734 dataOne = 0xff & seg0.getByte(addrOne);
1735 dataTwo = 0xff & cpu.es.getByte(addrTwo);
1736 count--;
1737 addrOne -= 1;
1738 addrTwo -= 1;
1739 if (dataOne == dataTwo) break;
1741 } else {
1742 while (count != 0) {
1743 //check hardware interrupts
1744 dataOne = 0xff & seg0.getByte(addrOne);
1745 dataTwo = 0xff & cpu.es.getByte(addrTwo);
1746 count--;
1747 addrOne += 1;
1748 addrTwo += 1;
1749 if (dataOne == dataTwo) break;
1753 finally {
1754 executeCount += (cpu.ecx - count);
1755 cpu.ecx = count;
1756 cpu.esi = addrOne;
1757 cpu.edi = addrTwo;
1759 if (used)
1760 sub_o8_flags(dataOne - dataTwo, dataOne, dataTwo);
1764 private final void repne_cmpsw_a16(Segment seg0)
1766 int count = 0xFFFF & cpu.ecx;
1767 int addrOne = 0xFFFF & cpu.esi;
1768 int addrTwo = 0xFFFF & cpu.edi;
1769 boolean used = count != 0;
1770 int dataOne = 0;
1771 int dataTwo = 0;
1773 try {
1774 if (cpu.eflagsDirection) {
1775 while (count != 0) {
1776 //check hardware interrupts
1777 dataOne = 0xffff & seg0.getWord(addrOne);
1778 dataTwo = 0xffff & cpu.es.getWord(addrTwo);
1779 count--;
1780 addrOne -= 2;
1781 addrTwo -= 2;
1782 if (dataOne == dataTwo) break;
1784 } else {
1785 while (count != 0) {
1786 //check hardware interrupts
1787 dataOne = 0xffff & seg0.getWord(addrOne);
1788 dataTwo = 0xffff & cpu.es.getWord(addrTwo);
1789 count--;
1790 addrOne += 2;
1791 addrTwo += 2;
1792 if (dataOne == dataTwo) break;
1796 finally {
1797 executeCount += ((cpu.ecx &0xFFFF) - count);
1798 cpu.ecx = (cpu.ecx & ~0xFFFF)|(count & 0xFFFF);
1799 cpu.esi = (cpu.esi & ~0xFFFF)|(addrOne & 0xFFFF);
1800 cpu.edi = (cpu.edi & ~0xFFFF)|(addrTwo & 0xFFFF);
1802 if (used)
1803 sub_o16_flags(dataOne - dataTwo, dataOne, dataTwo);
1808 private final void repne_cmpsw_a32(Segment seg0)
1810 int count = cpu.ecx;
1811 int addrOne = cpu.esi;
1812 int addrTwo = cpu.edi;
1813 boolean used = count != 0;
1814 int dataOne = 0;
1815 int dataTwo = 0;
1817 try {
1818 if (cpu.eflagsDirection) {
1819 while (count != 0) {
1820 //check hardware interrupts
1821 dataOne = 0xffff & seg0.getWord(addrOne);
1822 dataTwo = 0xffff & cpu.es.getWord(addrTwo);
1823 count--;
1824 addrOne -= 2;
1825 addrTwo -= 2;
1826 if (dataOne == dataTwo) break;
1828 } else {
1829 while (count != 0) {
1830 //check hardware interrupts
1831 dataOne = 0xffff & seg0.getWord(addrOne);
1832 dataTwo = 0xffff & cpu.es.getWord(addrTwo);
1833 count--;
1834 addrOne += 2;
1835 addrTwo += 2;
1836 if (dataOne == dataTwo) break;
1840 finally {
1841 executeCount += (cpu.ecx - count);
1842 cpu.ecx = count;
1843 cpu.esi = addrOne;
1844 cpu.edi = addrTwo;
1846 if (used)
1847 sub_o16_flags(dataOne - dataTwo, dataOne, dataTwo);
1851 private final void repne_cmpsd_a16(Segment seg0)
1853 int count = 0xFFFF & cpu.ecx;
1854 int addrOne = 0xFFFF & cpu.esi;
1855 int addrTwo = 0xFFFF & cpu.edi;
1856 boolean used = count != 0;
1857 int dataOne = 0;
1858 int dataTwo = 0;
1860 try {
1861 if (cpu.eflagsDirection) {
1862 while (count != 0) {
1863 //check hardware interrupts
1864 dataOne = seg0.getDoubleWord(addrOne);
1865 dataTwo = cpu.es.getDoubleWord(addrTwo);
1866 count--;
1867 addrOne -= 4;
1868 addrTwo -= 4;
1869 if (dataOne == dataTwo) break;
1871 } else {
1872 while (count != 0) {
1873 //check hardware interrupts
1874 dataOne = seg0.getDoubleWord(addrOne);
1875 dataTwo = cpu.es.getDoubleWord(addrTwo);
1876 count--;
1877 addrOne += 4;
1878 addrTwo += 4;
1879 if (dataOne == dataTwo) break;
1883 finally {
1884 executeCount += ((cpu.ecx &0xFFFF) - count);
1885 cpu.ecx = (cpu.ecx & ~0xFFFF)|(count & 0xFFFF);
1886 cpu.esi = (cpu.esi & ~0xFFFF)|(addrOne & 0xFFFF);
1887 cpu.edi = (cpu.edi & ~0xFFFF)|(addrTwo & 0xFFFF);
1889 if (used)
1890 sub_o32_flags((0xffffffffl & dataOne) - (0xffffffffl & dataTwo), dataOne, dataTwo);
1894 private final void repne_cmpsd_a32(Segment seg0)
1896 int count = cpu.ecx;
1897 int addrOne = cpu.esi;
1898 int addrTwo = cpu.edi;
1899 boolean used = count != 0;
1900 int dataOne = 0;
1901 int dataTwo = 0;
1903 try {
1904 if (cpu.eflagsDirection) {
1905 while (count != 0) {
1906 //check hardware interrupts
1907 dataOne = seg0.getDoubleWord(addrOne);
1908 dataTwo = cpu.es.getDoubleWord(addrTwo);
1909 count--;
1910 addrOne -= 4;
1911 addrTwo -= 4;
1912 if (dataOne == dataTwo) break;
1914 } else {
1915 while (count != 0) {
1916 //check hardware interrupts
1917 dataOne = cpu.es.getDoubleWord(addrOne);
1918 dataTwo = seg0.getDoubleWord(addrTwo);
1919 count--;
1920 addrOne += 4;
1921 addrTwo += 4;
1922 if (dataOne == dataTwo) break;
1926 finally {
1927 executeCount += (cpu.ecx - count);
1928 cpu.ecx = count;
1929 cpu.esi = addrOne;
1930 cpu.edi = addrTwo;
1932 if (used)
1933 sub_o32_flags((0xffffffffl & dataOne) - (0xffffffffl & dataTwo), dataOne, dataTwo);
1937 private final void insb_a32(int port)
1939 if (!checkIOPermissionsByte(port)) {
1940 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
1941 " at cpl " + cpu.getCPL() + ".");
1942 throw ProcessorException.GENERAL_PROTECTION_0;
1945 int addr = cpu.edi;
1946 cpu.es.setByte(addr, (byte)cpu.ioports.ioPortReadByte(port));
1947 if (cpu.eflagsDirection) {
1948 addr -= 1;
1949 } else {
1950 addr += 1;
1953 cpu.edi = addr;
1956 private final void insw_a32(int port)
1958 if (!checkIOPermissionsShort(port)) {
1959 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
1960 " at cpl " + cpu.getCPL() + ".");
1961 throw ProcessorException.GENERAL_PROTECTION_0;
1964 int addr = cpu.edi;
1965 cpu.es.setWord(addr, (short)cpu.ioports.ioPortReadWord(port));
1966 if (cpu.eflagsDirection) {
1967 addr -= 2;
1968 } else {
1969 addr += 2;
1972 cpu.edi = addr;
1975 private final void insd_a32(int port)
1977 if (!checkIOPermissionsInt(port)) {
1978 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
1979 " at cpl " + cpu.getCPL() + ".");
1980 throw ProcessorException.GENERAL_PROTECTION_0;
1983 int addr = cpu.edi;
1984 cpu.es.setDoubleWord(addr, cpu.ioports.ioPortReadLong(port));
1985 if (cpu.eflagsDirection) {
1986 addr -= 4;
1987 } else {
1988 addr += 4;
1991 cpu.edi = addr;
1994 private final void rep_insb_a32(int port)
1996 if (!checkIOPermissionsByte(port)) {
1997 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
1998 " at cpl " + cpu.getCPL() + ".");
1999 throw ProcessorException.GENERAL_PROTECTION_0;
2002 int count = cpu.ecx;
2003 int addr = cpu.edi;
2004 executeCount += count;
2006 try {
2007 if (cpu.eflagsDirection) {
2008 while (count != 0) {
2009 //check hardware interrupts
2010 cpu.es.setByte(addr, (byte)cpu.ioports.ioPortReadByte(port));
2011 count--;
2012 addr -= 1;
2014 } else {
2015 while (count != 0) {
2016 //check hardware interrupts
2017 cpu.es.setByte(addr, (byte)cpu.ioports.ioPortReadByte(port));
2018 count--;
2019 addr += 1;
2023 finally {
2024 cpu.ecx = count;
2025 cpu.edi = addr;
2029 private final void rep_insw_a32(int port)
2031 if (!checkIOPermissionsShort(port)) {
2032 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2033 " at cpl " + cpu.getCPL() + ".");
2034 throw ProcessorException.GENERAL_PROTECTION_0;
2037 int count = cpu.ecx;
2038 int addr = cpu.edi;
2039 executeCount += count;
2041 try {
2042 if (cpu.eflagsDirection) {
2043 while (count != 0) {
2044 //check hardware interrupts
2045 cpu.es.setWord(addr, (short)cpu.ioports.ioPortReadWord(port));
2046 count--;
2047 addr -= 2;
2049 } else {
2050 while (count != 0) {
2051 //check hardware interrupts
2052 cpu.es.setWord(addr, (short)cpu.ioports.ioPortReadWord(port));
2053 count--;
2054 addr += 2;
2058 finally {
2059 cpu.ecx = count;
2060 cpu.edi = addr;
2064 private final void rep_insd_a32(int port)
2066 if (!checkIOPermissionsShort(port)) {
2067 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2068 " at cpl " + cpu.getCPL() + ".");
2069 throw ProcessorException.GENERAL_PROTECTION_0;
2072 int count = cpu.ecx;
2073 int addr = cpu.edi;
2074 executeCount += count;
2076 try {
2077 if (cpu.eflagsDirection) {
2078 while (count != 0) {
2079 //check hardware interrupts
2080 cpu.es.setDoubleWord(addr, cpu.ioports.ioPortReadLong(port));
2081 count--;
2082 addr -= 4;
2084 } else {
2085 while (count != 0) {
2086 //check hardware interrupts
2087 cpu.es.setDoubleWord(addr, cpu.ioports.ioPortReadLong(port));
2088 count--;
2089 addr += 4;
2093 finally {
2094 cpu.ecx = count;
2095 cpu.edi = addr;
2099 private final void lodsb_a16(Segment dataSegment)
2101 int addr = 0xFFFF & cpu.esi ;
2102 cpu.eax = (cpu.eax & ~0xff) | (0xff & dataSegment.getByte(addr));
2104 if (cpu.eflagsDirection)
2105 addr -= 1;
2106 else
2107 addr += 1;
2109 cpu.esi =(cpu.esi & ~0xffff) | (0xffff & addr);
2112 private final void lodsb_a32(Segment dataSegment)
2114 int addr = cpu.esi;
2115 cpu.eax = (cpu.eax & ~0xff) | (0xff & dataSegment.getByte(addr));
2117 if (cpu.eflagsDirection)
2118 addr -= 1;
2119 else
2120 addr += 1;
2122 cpu.esi = addr;
2125 private final void lodsw_a16(Segment dataSegment)
2127 int addr = cpu.esi & 0xFFFF;
2128 cpu.eax = (cpu.eax & ~0xffff) | (0xffff & dataSegment.getWord(addr));
2130 if (cpu.eflagsDirection)
2131 addr -= 2;
2132 else
2133 addr += 2;
2135 cpu.esi =(cpu.esi & ~0xffff) | (0xffff & addr);
2138 private final void lodsw_a32(Segment dataSegment)
2140 int addr = cpu.esi;
2141 cpu.eax = (cpu.eax & ~0xffff) | (0xffff & dataSegment.getWord(addr));
2143 if (cpu.eflagsDirection)
2144 addr -= 2;
2145 else
2146 addr += 2;
2148 cpu.esi = addr;
2151 private final void lodsd_a32(Segment dataSegment)
2153 int addr = cpu.esi;
2154 cpu.eax = dataSegment.getDoubleWord(addr);
2156 if (cpu.eflagsDirection)
2157 addr -= 4;
2158 else
2159 addr += 4;
2161 cpu.esi = addr;
2164 private final void rep_lodsb_a32(Segment dataSegment)
2166 int count = cpu.ecx;
2167 int addr = cpu.esi;
2168 int data = cpu.eax & 0xff;
2169 executeCount += count;
2171 try {
2172 if (cpu.eflagsDirection) {
2173 while (count != 0) {
2174 //check hardware interrupts
2175 data = 0xff & dataSegment.getByte(addr);
2176 count--;
2177 addr -= 1;
2179 } else {
2180 while (count != 0) {
2181 //check hardware interrupts
2182 data = 0xff & dataSegment.getByte(addr);
2183 count--;
2184 addr += 1;
2188 finally {
2189 cpu.eax = (cpu.eax & ~0xff) | data;
2190 cpu.ecx = count;
2191 cpu.esi = addr;
2195 private final void rep_lodsw_a32(Segment dataSegment)
2197 int count = cpu.ecx;
2198 int addr = cpu.esi;
2199 int data = cpu.eax & 0xffff;
2200 executeCount += count;
2202 try {
2203 if (cpu.eflagsDirection) {
2204 while (count != 0) {
2205 //check hardware interrupts
2206 data = 0xffff & dataSegment.getWord(addr);
2207 count--;
2208 addr -= 2;
2210 } else {
2211 while (count != 0) {
2212 //check hardware interrupts
2213 data = 0xffff & dataSegment.getWord(addr);
2214 count--;
2215 addr += 2;
2219 finally {
2220 cpu.eax = (cpu.eax & ~0xffff) | data;
2221 cpu.ecx = count;
2222 cpu.esi = addr;
2226 private final void rep_lodsd_a32(Segment dataSegment)
2228 int count = cpu.ecx;
2229 int addr = cpu.esi;
2230 int data = cpu.eax;
2231 executeCount += count;
2233 try {
2234 if (cpu.eflagsDirection) {
2235 while (count != 0) {
2236 //check hardware interrupts
2237 data = dataSegment.getDoubleWord(addr);
2238 count--;
2239 addr -= 4;
2241 } else {
2242 while (count != 0) {
2243 //check hardware interrupts
2244 data = dataSegment.getDoubleWord(addr);
2245 count--;
2246 addr += 4;
2250 finally {
2251 cpu.eax = data;
2252 cpu.ecx = count;
2253 cpu.esi = addr;
2257 private final void movsb_a16(Segment outSegment)
2259 int inAddr = cpu.edi & 0xffff;
2260 int outAddr = cpu.esi & 0xffff;
2262 cpu.es.setByte(inAddr, outSegment.getByte(outAddr));
2263 if (cpu.eflagsDirection) {
2264 outAddr -= 1;
2265 inAddr -= 1;
2266 } else {
2267 outAddr += 1;
2268 inAddr += 1;
2271 cpu.edi = (cpu.edi & ~0xffff) | (inAddr & 0xffff);
2272 cpu.esi = (cpu.esi & ~0xffff) | (outAddr & 0xffff);
2275 private final void movsw_a16(Segment outSegment)
2277 int inAddr = cpu.edi & 0xffff;
2278 int outAddr = cpu.esi & 0xffff;
2280 cpu.es.setWord(inAddr, outSegment.getWord(outAddr));
2281 if (cpu.eflagsDirection) {
2282 outAddr -= 2;
2283 inAddr -= 2;
2284 } else {
2285 outAddr += 2;
2286 inAddr += 2;
2289 cpu.edi = (cpu.edi & ~0xffff) | (inAddr & 0xffff);
2290 cpu.esi = (cpu.esi & ~0xffff) | (outAddr & 0xffff);
2293 private final void movsd_a16(Segment outSegment)
2295 int inAddr = cpu.edi & 0xffff;
2296 int outAddr = cpu.esi & 0xffff;
2298 cpu.es.setDoubleWord(inAddr, outSegment.getDoubleWord(outAddr));
2299 if (cpu.eflagsDirection) {
2300 outAddr -= 4;
2301 inAddr -= 4;
2302 } else {
2303 outAddr += 4;
2304 inAddr += 4;
2307 cpu.edi = (cpu.edi & ~0xffff) | (inAddr & 0xffff);
2308 cpu.esi = (cpu.esi & ~0xffff) | (outAddr & 0xffff);
2311 private final void rep_movsb_a16(Segment outSegment)
2313 int count = cpu.ecx & 0xffff;
2314 int inAddr = cpu.edi & 0xffff;
2315 int outAddr = cpu.esi & 0xffff;
2316 executeCount += count;
2318 try {
2319 if (cpu.eflagsDirection) {
2320 while (count != 0) {
2321 //check hardware interrupts
2322 cpu.es.setByte(inAddr & 0xffff, outSegment.getByte(outAddr & 0xffff));
2323 count--;
2324 outAddr -= 1;
2325 inAddr -= 1;
2327 } else {
2328 while (count != 0) {
2329 //check hardware interrupts
2330 cpu.es.setByte(inAddr & 0xffff, outSegment.getByte(outAddr & 0xffff));
2331 count--;
2332 outAddr += 1;
2333 inAddr += 1;
2337 finally {
2338 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2339 cpu.edi = (cpu.edi & ~0xffff) | (inAddr & 0xffff);
2340 cpu.esi = (cpu.esi & ~0xffff) | (outAddr & 0xffff);
2344 private final void rep_movsw_a16(Segment outSegment)
2346 int count = cpu.ecx & 0xffff;
2347 int inAddr = cpu.edi & 0xffff;
2348 int outAddr = cpu.esi & 0xffff;
2349 executeCount += count;
2351 try {
2352 if (cpu.eflagsDirection) {
2353 while (count != 0) {
2354 //check hardware interrupts
2355 cpu.es.setWord(inAddr & 0xffff, outSegment.getWord(outAddr & 0xffff));
2356 count--;
2357 outAddr -= 2;
2358 inAddr -= 2;
2360 } else {
2361 while (count != 0) {
2362 //check hardware interrupts
2363 cpu.es.setWord(inAddr & 0xffff, outSegment.getWord(outAddr & 0xffff));
2364 count--;
2365 outAddr += 2;
2366 inAddr += 2;
2370 finally {
2371 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2372 cpu.edi = (cpu.edi & ~0xffff) | (inAddr & 0xffff);
2373 cpu.esi = (cpu.esi & ~0xffff) | (outAddr & 0xffff);
2377 private final void rep_movsd_a16(Segment outSegment)
2379 int count = cpu.ecx & 0xffff;
2380 int inAddr = cpu.edi & 0xffff;
2381 int outAddr = cpu.esi & 0xffff;
2382 executeCount += count;
2384 try {
2385 if (cpu.eflagsDirection) {
2386 while (count != 0) {
2387 //check hardware interrupts
2388 cpu.es.setDoubleWord(inAddr & 0xffff, outSegment.getDoubleWord(outAddr & 0xffff));
2389 count--;
2390 outAddr -= 4;
2391 inAddr -= 4;
2393 } else {
2394 while (count != 0) {
2395 //check hardware interrupts
2396 cpu.es.setDoubleWord(inAddr & 0xffff, outSegment.getDoubleWord(outAddr & 0xffff));
2397 count--;
2398 outAddr += 4;
2399 inAddr += 4;
2403 finally {
2404 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2405 cpu.edi = (cpu.edi & ~0xffff) | (inAddr & 0xffff);
2406 cpu.esi = (cpu.esi & ~0xffff) | (outAddr & 0xffff);
2410 private final void movsb_a32(Segment outSegment)
2412 int inAddr = cpu.edi;
2413 int outAddr = cpu.esi;
2415 cpu.es.setByte(inAddr, outSegment.getByte(outAddr));
2416 if (cpu.eflagsDirection) {
2417 outAddr -= 1;
2418 inAddr -= 1;
2419 } else {
2420 outAddr += 1;
2421 inAddr += 1;
2424 cpu.edi = inAddr;
2425 cpu.esi = outAddr;
2428 private final void movsw_a32(Segment outSegment)
2430 int inAddr = cpu.edi;
2431 int outAddr = cpu.esi;
2433 cpu.es.setWord(inAddr, outSegment.getWord(outAddr));
2434 if (cpu.eflagsDirection) {
2435 outAddr -= 2;
2436 inAddr -= 2;
2437 } else {
2438 outAddr += 2;
2439 inAddr += 2;
2442 cpu.edi = inAddr;
2443 cpu.esi = outAddr;
2446 private final void movsd_a32(Segment outSegment)
2448 int inAddr = cpu.edi;
2449 int outAddr = cpu.esi;
2451 cpu.es.setDoubleWord(inAddr, outSegment.getDoubleWord(outAddr));
2452 if (cpu.eflagsDirection) {
2453 outAddr -= 4;
2454 inAddr -= 4;
2455 } else {
2456 outAddr += 4;
2457 inAddr += 4;
2460 cpu.edi = inAddr;
2461 cpu.esi = outAddr;
2464 private final void rep_movsb_a32(Segment outSegment)
2466 int count = cpu.ecx;
2467 int inAddr = cpu.edi;
2468 int outAddr = cpu.esi;
2469 executeCount += count;
2471 try {
2472 if (cpu.eflagsDirection) {
2473 while (count != 0) {
2474 //check hardware interrupts
2475 cpu.es.setByte(inAddr, outSegment.getByte(outAddr));
2476 count--;
2477 outAddr -= 1;
2478 inAddr -= 1;
2480 } else {
2481 while (count != 0) {
2482 //check hardware interrupts
2483 cpu.es.setByte(inAddr, outSegment.getByte(outAddr));
2484 count--;
2485 outAddr += 1;
2486 inAddr += 1;
2490 finally {
2491 cpu.ecx = count;
2492 cpu.edi = inAddr;
2493 cpu.esi = outAddr;
2497 private final void rep_movsw_a32(Segment outSegment)
2499 int count = cpu.ecx;
2500 int inAddr = cpu.edi;
2501 int outAddr = cpu.esi;
2502 executeCount += count;
2504 try {
2505 if (cpu.eflagsDirection) {
2506 while (count != 0) {
2507 //check hardware interrupts
2508 cpu.es.setWord(inAddr, outSegment.getWord(outAddr));
2509 count--;
2510 outAddr -= 2;
2511 inAddr -= 2;
2513 } else {
2514 while (count != 0) {
2515 //check hardware interrupts
2516 cpu.es.setWord(inAddr, outSegment.getWord(outAddr));
2517 count--;
2518 outAddr += 2;
2519 inAddr += 2;
2523 finally {
2524 cpu.ecx = count;
2525 cpu.edi = inAddr;
2526 cpu.esi = outAddr;
2530 private final void rep_movsd_a32(Segment outSegment)
2532 int count = cpu.ecx;
2533 int inAddr = cpu.edi;
2534 int outAddr = cpu.esi;
2535 executeCount += count;
2537 try {
2538 if (cpu.eflagsDirection) {
2539 while (count != 0) {
2540 //check hardware interrupts
2541 cpu.es.setDoubleWord(inAddr, outSegment.getDoubleWord(outAddr));
2542 count--;
2543 outAddr -= 4;
2544 inAddr -= 4;
2546 } else {
2547 while (count != 0) {
2548 //check hardware interrupts
2549 cpu.es.setDoubleWord(inAddr, outSegment.getDoubleWord(outAddr));
2550 count--;
2551 outAddr += 4;
2552 inAddr += 4;
2556 finally {
2557 cpu.ecx = count;
2558 cpu.edi = inAddr;
2559 cpu.esi = outAddr;
2563 private final void outsb_a16(int port, Segment storeSegment)
2565 if (!checkIOPermissionsByte(port)) {
2566 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2567 " at cpl " + cpu.getCPL() + ".");
2568 throw ProcessorException.GENERAL_PROTECTION_0;
2571 int addr = cpu.esi & 0xffff;
2573 cpu.ioports.ioPortWriteByte(port, 0xff & storeSegment.getByte(addr));
2575 if (cpu.eflagsDirection)
2576 addr -= 1;
2577 else
2578 addr += 1;
2580 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2583 private final void outsw_a16(int port, Segment storeSegment)
2585 if (!checkIOPermissionsShort(port)) {
2586 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2587 " at cpl " + cpu.getCPL() + ".");
2588 throw ProcessorException.GENERAL_PROTECTION_0;
2591 int addr = cpu.esi & 0xffff;
2593 cpu.ioports.ioPortWriteWord(port, 0xffff & storeSegment.getWord(addr));
2595 if (cpu.eflagsDirection)
2596 addr -= 2;
2597 else
2598 addr += 2;
2600 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2603 private final void outsd_a16(int port, Segment storeSegment)
2605 if (!checkIOPermissionsInt(port)) {
2606 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2607 " at cpl " + cpu.getCPL() + ".");
2608 throw ProcessorException.GENERAL_PROTECTION_0;
2611 int addr = cpu.esi & 0xffff;
2613 cpu.ioports.ioPortWriteLong(port, storeSegment.getDoubleWord(addr));
2615 if (cpu.eflagsDirection)
2616 addr -= 4;
2617 else
2618 addr += 4;
2620 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2623 private final void rep_outsb_a16(int port, Segment storeSegment)
2625 if (!checkIOPermissionsByte(port)) {
2626 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2627 " at cpl " + cpu.getCPL() + ".");
2628 throw ProcessorException.GENERAL_PROTECTION_0;
2631 int count = cpu.ecx & 0xffff;
2632 int addr = cpu.esi & 0xffff;
2633 executeCount += count;
2635 try {
2636 if (cpu.eflagsDirection) {
2637 while (count != 0) {
2638 //check hardware interrupts
2639 cpu.ioports.ioPortWriteByte(port, 0xffff & storeSegment.getByte(addr & 0xffff));
2640 count--;
2641 addr -= 1;
2643 } else {
2644 while (count != 0) {
2645 //check hardware interrupts
2646 cpu.ioports.ioPortWriteByte(port, 0xffff & storeSegment.getByte(addr & 0xffff));
2647 count--;
2648 addr += 1;
2652 finally {
2653 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2654 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2658 private final void rep_outsw_a16(int port, Segment storeSegment)
2660 if (!checkIOPermissionsShort(port)) {
2661 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2662 " at cpl " + cpu.getCPL() + ".");
2663 throw ProcessorException.GENERAL_PROTECTION_0;
2666 int count = cpu.ecx & 0xffff;
2667 int addr = cpu.esi & 0xffff;
2668 executeCount += count;
2670 try {
2671 if (cpu.eflagsDirection) {
2672 while (count != 0) {
2673 //check hardware interrupts
2674 cpu.ioports.ioPortWriteWord(port, 0xffff & storeSegment.getWord(addr & 0xffff));
2675 count--;
2676 addr -= 2;
2678 } else {
2679 while (count != 0) {
2680 //check hardware interrupts
2681 cpu.ioports.ioPortWriteWord(port, 0xffff & storeSegment.getWord(addr & 0xffff));
2682 count--;
2683 addr += 2;
2687 finally {
2688 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2689 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2693 private final void rep_outsd_a16(int port, Segment storeSegment)
2695 if (!checkIOPermissionsInt(port)) {
2696 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2697 " at cpl " + cpu.getCPL() + ".");
2698 throw ProcessorException.GENERAL_PROTECTION_0;
2701 int count = cpu.ecx & 0xffff;
2702 int addr = cpu.esi & 0xffff;
2703 executeCount += count;
2705 try {
2706 if (cpu.eflagsDirection) {
2707 while (count != 0) {
2708 //check hardware interrupts
2709 cpu.ioports.ioPortWriteLong(port, storeSegment.getDoubleWord(addr & 0xffff));
2710 count--;
2711 addr -= 4;
2713 } else {
2714 while (count != 0) {
2715 //check hardware interrupts
2716 cpu.ioports.ioPortWriteLong(port, storeSegment.getDoubleWord(addr & 0xffff));
2717 count--;
2718 addr += 4;
2722 finally {
2723 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2724 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2728 private final void outsb_a32(int port, Segment storeSegment)
2730 if (!checkIOPermissionsByte(port)) {
2731 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2732 " at cpl " + cpu.getCPL() + ".");
2733 throw ProcessorException.GENERAL_PROTECTION_0;
2736 int addr = cpu.esi;
2738 cpu.ioports.ioPortWriteByte(port, 0xff & storeSegment.getByte(addr));
2740 if (cpu.eflagsDirection)
2741 addr -= 1;
2742 else
2743 addr += 1;
2745 cpu.esi = addr;
2748 private final void outsw_a32(int port, Segment storeSegment)
2750 if (!checkIOPermissionsShort(port)) {
2751 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2752 " at cpl " + cpu.getCPL() + ".");
2753 throw ProcessorException.GENERAL_PROTECTION_0;
2756 int addr = cpu.esi;
2758 cpu.ioports.ioPortWriteWord(port, 0xffff & storeSegment.getWord(addr));
2760 if (cpu.eflagsDirection)
2761 addr -= 2;
2762 else
2763 addr += 2;
2765 cpu.esi = addr;
2768 private final void outsd_a32(int port, Segment storeSegment)
2770 if (!checkIOPermissionsInt(port)) {
2771 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2772 " at cpl " + cpu.getCPL() + ".");
2773 throw ProcessorException.GENERAL_PROTECTION_0;
2776 int addr = cpu.esi;
2778 cpu.ioports.ioPortWriteLong(port, storeSegment.getDoubleWord(addr));
2780 if (cpu.eflagsDirection)
2781 addr -= 4;
2782 else
2783 addr += 4;
2785 cpu.esi = addr;
2788 private final void rep_outsb_a32(int port, Segment storeSegment)
2790 if (!checkIOPermissionsByte(port)) {
2791 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2792 " at cpl " + cpu.getCPL() + ".");
2793 throw ProcessorException.GENERAL_PROTECTION_0;
2796 int count = cpu.ecx;
2797 int addr = cpu.esi;
2798 executeCount += count;
2800 try {
2801 if (cpu.eflagsDirection) {
2802 while (count != 0) {
2803 //check hardware interrupts
2804 cpu.ioports.ioPortWriteByte(port, 0xffff & storeSegment.getByte(addr));
2805 count--;
2806 addr -= 1;
2808 } else {
2809 while (count != 0) {
2810 //check hardware interrupts
2811 cpu.ioports.ioPortWriteByte(port, 0xffff & storeSegment.getByte(addr));
2812 count--;
2813 addr += 1;
2817 finally {
2818 cpu.ecx = count;
2819 cpu.esi = addr;
2823 private final void rep_outsw_a32(int port, Segment storeSegment)
2825 if (!checkIOPermissionsShort(port)) {
2826 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2827 " at cpl " + cpu.getCPL() + ".");
2828 throw ProcessorException.GENERAL_PROTECTION_0;
2831 int count = cpu.ecx;
2832 int addr = cpu.esi;
2833 executeCount += count;
2835 try {
2836 if (cpu.eflagsDirection) {
2837 while (count != 0) {
2838 //check hardware interrupts
2839 cpu.ioports.ioPortWriteWord(port, 0xffff & storeSegment.getWord(addr));
2840 count--;
2841 addr -= 2;
2843 } else {
2844 while (count != 0) {
2845 //check hardware interrupts
2846 cpu.ioports.ioPortWriteWord(port, 0xffff & storeSegment.getWord(addr));
2847 count--;
2848 addr += 2;
2852 finally {
2853 cpu.ecx = count;
2854 cpu.esi = addr;
2858 private final void rep_outsd_a32(int port, Segment storeSegment)
2860 if (!checkIOPermissionsInt(port)) {
2861 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
2862 " at cpl " + cpu.getCPL() + ".");
2863 throw ProcessorException.GENERAL_PROTECTION_0;
2866 int count = cpu.ecx;
2867 int addr = cpu.esi;
2868 executeCount += count;
2870 try {
2871 if (cpu.eflagsDirection) {
2872 while (count != 0) {
2873 //check hardware interrupts
2874 cpu.ioports.ioPortWriteLong(port, storeSegment.getDoubleWord(addr));
2875 count--;
2876 addr -= 4;
2878 } else {
2879 while (count != 0) {
2880 //check hardware interrupts
2881 cpu.ioports.ioPortWriteLong(port, storeSegment.getDoubleWord(addr));
2882 count--;
2883 addr += 4;
2887 finally {
2888 cpu.ecx = count;
2889 cpu.esi = addr;
2893 private final void scasb_a16(int data)
2895 int addr = 0xFFFF & cpu.edi;
2896 int input = 0xff & cpu.es.getByte(addr);
2898 if (cpu.eflagsDirection)
2899 addr -= 1;
2900 else
2901 addr += 1;
2903 cpu.edi = (cpu.edi & ~0xFFFF) | (0xFFFF & addr);
2904 sub_o8_flags(data - input, data, input);
2906 private final void scasb_a32(int data)
2908 int addr = cpu.edi;
2909 int input = 0xff & cpu.es.getByte(addr);
2911 if (cpu.eflagsDirection)
2912 addr -= 1;
2913 else
2914 addr += 1;
2916 cpu.edi = addr;
2917 sub_o8_flags(data - input, data, input);
2920 private final void scasw_a32(int data)
2922 int addr = cpu.edi;
2923 int input = 0xffff & cpu.es.getWord(addr);
2925 if (cpu.eflagsDirection)
2926 addr -= 2;
2927 else
2928 addr += 2;
2930 cpu.edi = addr;
2931 sub_o16_flags(data - input, data, input);
2934 private final void scasd_a32(int data)
2936 int addr = cpu.edi;
2937 int input = cpu.es.getDoubleWord(addr);
2939 if (cpu.eflagsDirection)
2940 addr -= 4;
2941 else
2942 addr += 4;
2944 cpu.edi = addr;
2945 sub_o32_flags((0xffffffffl & data) - (0xffffffffl & input), data, input);
2948 private final void repe_scasb_a16(int data)
2950 int count = 0xffff & cpu.ecx;
2951 int addr = 0xffff & cpu.edi;
2952 boolean used = count != 0;
2953 int input = 0;
2955 try {
2956 if (cpu.eflagsDirection) {
2957 while (count != 0) {
2958 input = 0xff & cpu.es.getByte(addr);
2959 count--;
2960 addr -= 1;
2961 if (data != input) break;
2963 } else {
2964 while (count != 0) {
2965 input = 0xff & cpu.es.getByte(addr);
2966 count--;
2967 addr += 1;
2968 if (data != input) break;
2971 } finally {
2972 executeCount += ((0xffff & cpu.ecx) - count);
2973 cpu.ecx = (cpu.ecx & ~0xffff) | (0xffff & count);
2974 cpu.edi = (cpu.edi & ~0xffff) | (0xffff & addr);
2975 if (used)
2976 sub_o8_flags(data - input, data, input);
2980 private final void repe_scasb_a32(int data)
2982 int count = cpu.ecx;
2983 int addr = cpu.edi;
2984 boolean used = count != 0;
2985 int input = 0;
2987 try {
2988 if (cpu.eflagsDirection) {
2989 while (count != 0) {
2990 input = 0xff & cpu.es.getByte(addr);
2991 count--;
2992 addr -= 1;
2993 if (data != input) break;
2995 } else {
2996 while (count != 0) {
2997 input = 0xff & cpu.es.getByte(addr);
2998 count--;
2999 addr += 1;
3000 if (data != input) break;
3003 } finally {
3004 executeCount += (cpu.ecx - count);
3005 cpu.ecx = count;
3006 cpu.edi = addr;
3007 if (used)
3008 sub_o8_flags(data - input, data, input);
3012 private final void repe_scasw_a16(int data)
3014 int count = 0xffff & cpu.ecx;
3015 int addr = 0xffff & cpu.edi;
3016 boolean used = count != 0;
3017 int input = 0;
3019 try {
3020 if (cpu.eflagsDirection) {
3021 while (count != 0) {
3022 input = 0xffff & cpu.es.getWord(addr);
3023 count--;
3024 addr -= 2;
3025 if (data != input) break;
3027 } else {
3028 while (count != 0) {
3029 input = 0xffff & cpu.es.getWord(addr);
3030 count--;
3031 addr += 2;
3032 if (data != input) break;
3035 } finally {
3036 executeCount += ((0xffff & cpu.ecx) - count);
3037 cpu.ecx = (cpu.ecx & ~0xffff) | (0xffff & count);
3038 cpu.edi = (cpu.edi & ~0xffff) | (0xffff & addr);
3039 if (used)
3040 sub_o16_flags(data - input, data, input);
3044 private final void repe_scasw_a32(int data)
3046 int count = cpu.ecx;
3047 int addr = cpu.edi;
3048 boolean used = count != 0;
3049 int input = 0;
3051 try {
3052 if (cpu.eflagsDirection) {
3053 while (count != 0) {
3054 input = 0xffff & cpu.es.getWord(addr);
3055 count--;
3056 addr -= 2;
3057 if (data != input) break;
3059 } else {
3060 while (count != 0) {
3061 input = 0xffff & cpu.es.getWord(addr);
3062 count--;
3063 addr += 2;
3064 if (data != input) break;
3067 } finally {
3068 executeCount += (cpu.ecx - count);
3069 cpu.ecx = count;
3070 cpu.edi = addr;
3071 if (used)
3072 sub_o16_flags(data - input, data, input);
3076 private final void repe_scasd_a16(int data)
3078 int count = 0xffff & cpu.ecx;
3079 int addr = 0xffff & cpu.edi;
3080 boolean used = count != 0;
3081 int input = 0;
3083 try {
3084 if (cpu.eflagsDirection) {
3085 while (count != 0) {
3086 input = cpu.es.getDoubleWord(addr);
3087 count--;
3088 addr -= 4;
3089 if (data != input) break;
3091 } else {
3092 while (count != 0) {
3093 input = cpu.es.getDoubleWord(addr);
3094 count--;
3095 addr += 4;
3096 if (data != input) break;
3099 } finally {
3100 executeCount += ((0xffff & cpu.ecx) - count);
3101 cpu.ecx = (cpu.ecx & ~0xffff) | (0xffff & count);
3102 cpu.edi = (cpu.edi & ~0xffff) | (0xffff & addr);
3103 if (used)
3104 sub_o32_flags((0xffffffffl & data) - (0xffffffffl & input), data, input);
3108 private final void repe_scasd_a32(int data)
3110 int count = cpu.ecx;
3111 int addr = cpu.edi;
3112 boolean used = count != 0;
3113 int input = 0;
3115 try {
3116 if (cpu.eflagsDirection) {
3117 while (count != 0) {
3118 input = cpu.es.getDoubleWord(addr);
3119 count--;
3120 addr -= 4;
3121 if (data != input) break;
3123 } else {
3124 while (count != 0) {
3125 input = cpu.es.getDoubleWord(addr);
3126 count--;
3127 addr += 4;
3128 if (data != input) break;
3131 } finally {
3132 executeCount += (cpu.ecx - count);
3133 cpu.ecx = count;
3134 cpu.edi = addr;
3135 if (used)
3137 sub_o32_flags((0xffffffffl & data) - (0xffffffffl & input), data, input);
3141 private final void repne_scasb_a16(int data)
3143 int count = 0xFFFF & cpu.ecx;
3144 int addr = 0xFFFF & cpu.edi;
3145 boolean used = count != 0;
3146 int input = 0;
3148 try {
3149 if (cpu.eflagsDirection) {
3150 while (count != 0) {
3151 input = 0xff & cpu.es.getByte(addr);
3152 count--;
3153 addr -= 1;
3154 if (data == input) break;
3156 } else {
3157 while (count != 0) {
3158 input = 0xff & cpu.es.getByte(addr);
3159 count--;
3160 addr += 1;
3161 if (data == input) break;
3164 } finally {
3165 executeCount += ((cpu.ecx & 0xFFFF) - count);
3166 cpu.ecx = (cpu.ecx & ~0xFFFF) | (0xFFFF & count);
3167 cpu.edi = (cpu.edi & ~0xFFFF) | (0xFFFF & addr);
3168 if (used)
3169 sub_o8_flags(data - input, data, input);
3173 private final void repne_scasb_a32(int data)
3175 int count = cpu.ecx;
3176 int addr = cpu.edi;
3177 boolean used = count != 0;
3178 int input = 0;
3180 try {
3181 if (cpu.eflagsDirection) {
3182 while (count != 0) {
3183 input = 0xff & cpu.es.getByte(addr);
3184 count--;
3185 addr -= 1;
3186 if (data == input) break;
3188 } else {
3189 while (count != 0) {
3190 input = 0xff & cpu.es.getByte(addr);
3191 count--;
3192 addr += 1;
3193 if (data == input) break;
3196 } finally {
3197 executeCount += (cpu.ecx - count);
3198 cpu.ecx = count;
3199 cpu.edi = addr;
3200 if (used)
3201 sub_o8_flags(data - input, data, input);
3205 private final void repne_scasw_a16(int data)
3207 int count = 0xffff & cpu.ecx;
3208 int addr = 0xffff & cpu.edi;
3209 boolean used = count != 0;
3210 int input = 0;
3212 try {
3213 if (cpu.eflagsDirection) {
3214 while (count != 0) {
3215 input = 0xffff & cpu.es.getWord(addr);
3216 count--;
3217 addr -= 2;
3218 if (data == input) break;
3220 } else {
3221 while (count != 0) {
3222 input = 0xffff & cpu.es.getWord(addr);
3223 count--;
3224 addr += 2;
3225 if (data == input) break;
3228 } finally {
3229 executeCount += ((0xffff & cpu.ecx) - count);
3230 cpu.ecx = (cpu.ecx & ~0xffff) | (0xffff & count);
3231 cpu.edi = (cpu.edi & ~0xffff) | (0xffff & addr);
3232 if (used)
3233 sub_o16_flags(data - input, data, input);
3237 private final void repne_scasw_a32(int data)
3239 int count = cpu.ecx;
3240 int addr = cpu.edi;
3241 boolean used = count != 0;
3242 int input = 0;
3244 try {
3245 if (cpu.eflagsDirection) {
3246 while (count != 0) {
3247 input = 0xffff & cpu.es.getWord(addr);
3248 count--;
3249 addr -= 2;
3250 if (data == input) break;
3252 } else {
3253 while (count != 0) {
3254 input = 0xffff & cpu.es.getWord(addr);
3255 count--;
3256 addr += 2;
3257 if (data == input) break;
3260 } finally {
3261 executeCount += (cpu.ecx - count);
3262 cpu.ecx = count;
3263 cpu.edi = addr;
3264 if (used)
3265 sub_o16_flags(data - input, data, input);
3269 private final void repne_scasd_a16(int data)
3271 int count = 0xffff & cpu.ecx;
3272 int addr = 0xffff & cpu.edi;
3273 boolean used = count != 0;
3274 int input = 0;
3276 try {
3277 if (cpu.eflagsDirection) {
3278 while (count != 0) {
3279 input = cpu.es.getDoubleWord(addr);
3280 count--;
3281 addr -= 4;
3282 if (data == input) break;
3284 } else {
3285 while (count != 0) {
3286 input = cpu.es.getDoubleWord(addr);
3287 count--;
3288 addr += 4;
3289 if (data == input) break;
3292 } finally {
3293 executeCount += ((0xffff & cpu.ecx) - count);
3294 cpu.ecx = (cpu.ecx & ~0xffff) | (0xffff & count);
3295 cpu.edi = (cpu.edi & ~0xffff) | (0xffff & addr);
3296 if (used)
3297 sub_o32_flags((0xffffffffl & data) - (0xffffffffl & input), data, input);
3302 private final void repne_scasd_a32(int data)
3304 int count = cpu.ecx;
3305 int addr = cpu.edi;
3306 boolean used = count != 0;
3307 int input = 0;
3309 try {
3310 if (cpu.eflagsDirection) {
3311 while (count != 0) {
3312 input = cpu.es.getDoubleWord(addr);
3313 count--;
3314 addr -= 4;
3315 if (data == input) break;
3317 } else {
3318 while (count != 0) {
3319 input = cpu.es.getDoubleWord(addr);
3320 count--;
3321 addr += 4;
3322 if (data == input) break;
3325 } finally {
3326 executeCount += (cpu.ecx - count);
3327 cpu.ecx = count;
3328 cpu.edi = addr;
3329 if (used)
3331 sub_o32_flags((0xffffffffl & data) - (0xffffffffl & input), data, input);
3335 private final void stosb_a16(int data)
3337 int addr = 0xFFFF & cpu.edi;
3338 cpu.es.setByte(addr, (byte)data);
3340 if (cpu.eflagsDirection)
3341 addr -= 1;
3342 else
3343 addr += 1;
3345 cpu.edi = (cpu.edi & ~0xFFFF) | (0xFFFF & addr);
3348 private final void stosb_a32(int data)
3350 int addr = cpu.edi;
3351 cpu.es.setByte(addr, (byte)data);
3353 if (cpu.eflagsDirection)
3354 addr -= 1;
3355 else
3356 addr += 1;
3358 cpu.edi = addr;
3361 private final void stosw_a16(int data)
3363 int addr = 0xFFFF & cpu.edi ;
3364 cpu.es.setWord(addr, (short) data);
3366 if (cpu.eflagsDirection)
3367 addr -= 2;
3368 else
3369 addr += 2;
3371 cpu.edi = (cpu.edi & ~0xffff) | (0xFFFF & addr);
3374 private final void stosw_a32(int data)
3376 int addr = cpu.edi;
3377 cpu.es.setWord(addr, (short)data);
3379 if (cpu.eflagsDirection)
3380 addr -= 2;
3381 else
3382 addr += 2;
3384 cpu.edi = addr;
3387 private final void stosd_a16(int data)
3389 int addr = 0xffff & cpu.edi;
3390 cpu.es.setDoubleWord(addr, data);
3392 if (cpu.eflagsDirection)
3393 addr -= 4;
3394 else
3395 addr += 4;
3397 cpu.edi = (cpu.edi & ~0xffff) | (0xFFFF & addr);
3400 private final void stosd_a32(int data)
3402 int addr = cpu.edi;
3403 cpu.es.setDoubleWord(addr, data);
3405 if (cpu.eflagsDirection)
3406 addr -= 4;
3407 else
3408 addr += 4;
3410 cpu.edi = addr;
3413 private final void rep_stosb_a16(int data)
3415 int count = 0xFFFF & cpu.ecx;
3416 int addr = 0xFFFF & cpu.edi;
3417 executeCount += count;
3419 try {
3420 if (cpu.eflagsDirection) {
3421 while (count != 0) {
3422 //check hardware interrupts
3423 cpu.es.setByte(addr, (byte)data);
3424 count--;
3425 addr = (addr - 1) & 0xFFFF;
3427 } else {
3428 while (count != 0) {
3429 //check hardware interrupts
3430 cpu.es.setByte(addr, (byte)data);
3431 count--;
3432 addr = (addr + 1) & 0xFFFF;
3436 finally {
3437 cpu.ecx = (cpu.ecx & ~0xFFFF) | count;
3438 cpu.edi = (cpu.edi & ~0xFFFF) | addr;
3442 private final void rep_stosb_a32(int data)
3444 int count = cpu.ecx;
3445 int addr = cpu.edi;
3446 executeCount += count;
3448 try {
3449 if (cpu.eflagsDirection) {
3450 while (count != 0) {
3451 //check hardware interrupts
3452 cpu.es.setByte(addr, (byte)data);
3453 count--;
3454 addr -= 1;
3456 } else {
3457 while (count != 0) {
3458 //check hardware interrupts
3459 cpu.es.setByte(addr, (byte)data);
3460 count--;
3461 addr += 1;
3465 finally {
3466 cpu.ecx = count;
3467 cpu.edi = addr;
3471 private final void rep_stosw_a16(int data)
3473 int count = 0xFFFF & cpu.ecx;
3474 int addr = 0xFFFF & cpu.edi;
3475 executeCount += count;
3477 try {
3478 if (cpu.eflagsDirection) {
3479 while (count != 0) {
3480 //check hardware interrupts
3481 cpu.es.setWord(addr, (short)data);
3482 count--;
3483 addr = (addr - 2) & 0xFFFF;
3485 } else {
3486 while (count != 0) {
3487 //check hardware interrupts
3488 cpu.es.setWord(addr, (short)data);
3489 count--;
3490 addr = (addr + 2) & 0xFFFF;
3494 finally {
3495 cpu.ecx = (cpu.ecx & ~0xFFFF) | (0xFFFF & count);
3496 cpu.edi = (cpu.edi & ~0xFFFF) | (0xFFFF & addr);
3500 private final void rep_stosw_a32(int data)
3502 int count = cpu.ecx;
3503 int addr = cpu.edi;
3504 executeCount += count;
3506 try {
3507 if (cpu.eflagsDirection) {
3508 while (count != 0) {
3509 //check hardware interrupts
3510 cpu.es.setWord(addr, (short)data);
3511 count--;
3512 addr -= 2;
3514 } else {
3515 while (count != 0) {
3516 //check hardware interrupts
3517 cpu.es.setWord(addr, (short)data);
3518 count--;
3519 addr += 2;
3523 finally {
3524 cpu.ecx = count;
3525 cpu.edi = addr;
3529 private final void rep_stosd_a16(int data)
3531 int count = 0xFFFF & cpu.ecx;
3532 int addr = 0xFFFF & cpu.edi;
3533 executeCount += count;
3535 try {
3536 if (cpu.eflagsDirection) {
3537 while (count != 0) {
3538 //check hardware interrupts
3539 cpu.es.setDoubleWord(addr, data);
3540 count--;
3541 addr = (addr - 4) & 0xFFFF;
3543 } else {
3544 while (count != 0) {
3545 //check hardware interrupts
3546 cpu.es.setDoubleWord(addr, data);
3547 count--;
3548 addr = (addr + 4) & 0xFFFF;
3552 finally {
3553 cpu.ecx = (cpu.ecx & ~0xFFFF) | (0xFFFF & count);
3554 cpu.edi = (cpu.edi & ~0xFFFF) | (0xFFFF & addr);
3558 private final void rep_stosd_a32(int data)
3560 int count = cpu.ecx;
3561 int addr = cpu.edi;
3562 executeCount += count;
3564 try {
3565 if (cpu.eflagsDirection) {
3566 while (count != 0) {
3567 //check hardware interrupts
3568 cpu.es.setDoubleWord(addr, data);
3569 count--;
3570 addr -= 4;
3572 } else {
3573 while (count != 0) {
3574 //check hardware interrupts
3575 cpu.es.setDoubleWord(addr, data);
3576 count--;
3577 addr += 4;
3581 finally {
3582 cpu.ecx = count;
3583 cpu.edi = addr;
3587 private final void mul_o8(int data)
3589 int x = cpu.eax & 0xff;
3591 int result = x * data;
3592 cpu.eax &= 0xffff0000;
3593 cpu.eax |= (result & 0xffff);
3595 cpu.setOverflowFlag(result, Processor.OF_HIGH_BYTE_NZ);
3596 cpu.setCarryFlag(result, Processor.CY_HIGH_BYTE_NZ);
3599 private final void mul_o16(int data)
3601 int x = cpu.eax & 0xffff;
3603 int result = x * data;
3604 cpu.eax = (cpu.eax & 0xffff0000) | (0xffff & result);
3605 result = result >>> 16;
3606 cpu.edx = (cpu.edx & 0xffff0000) | result;
3608 cpu.setOverflowFlag(result, Processor.OF_NZ);
3609 cpu.setCarryFlag(result, Processor.CY_NZ);
3612 private final void mul_o32(int data)
3614 long x = cpu.eax & 0xffffffffl;
3615 long y = 0xffffffffl & data;
3617 long result = x * y;
3618 cpu.eax = (int)result;
3619 result = result >>> 32;
3620 cpu.edx = (int)result;
3622 cpu.setOverflowFlag( cpu.edx, Processor.OF_NZ);
3623 cpu.setCarryFlag( cpu.edx, Processor.CY_NZ);
3626 private final void imula_o8(byte data)
3628 byte al = (byte)cpu.eax;
3629 int result = al * data;
3631 cpu.eax = (cpu.eax & ~0xffff) | (result & 0xffff);
3633 cpu.setOverflowFlag(result, Processor.OF_NOT_BYTE);
3634 cpu.setCarryFlag(result, Processor.CY_NOT_BYTE);
3637 private final void imula_o16(short data)
3639 short ax = (short)cpu.eax;
3640 int result = ax * data;
3642 cpu.eax = (cpu.eax & ~0xffff) | (result & 0xffff);
3643 cpu.edx = (cpu.edx & ~0xffff) | (result >>> 16);
3645 //answer too wide for 16-bits?
3646 cpu.setOverflowFlag(result, Processor.OF_NOT_SHORT);
3647 cpu.setCarryFlag(result, Processor.CY_NOT_SHORT);
3650 private final void imula_o32(int data)
3652 long eax = (long)cpu.eax;
3653 long y = (long)data;
3654 long result = eax * y;
3656 cpu.eax = (int)result;
3657 cpu.edx = (int)(result >>> 32);
3659 //answer too wide for 32-bits?
3660 cpu.setOverflowFlag(result, Processor.OF_NOT_INT);
3661 cpu.setCarryFlag(result, Processor.CY_NOT_INT);
3664 private final int imul_o16(short data0, short data1)
3666 int result = data0 * data1;
3667 cpu.setOverflowFlag(result, Processor.OF_NOT_SHORT);
3668 cpu.setCarryFlag(result, Processor.CY_NOT_SHORT);
3669 return result;
3672 private final int imul_o32(int data0, int data1)
3674 long x = (long)data0;
3675 long y = (long)data1;
3677 long result = x * y;
3678 cpu.setOverflowFlag(result, Processor.OF_NOT_INT);
3679 cpu.setCarryFlag(result, Processor.CY_NOT_INT);
3680 return (int)result;
3683 private final void div_o8(int data)
3685 if (data == 0)
3686 throw ProcessorException.DIVIDE_ERROR;
3688 int x = (cpu.eax & 0xffff);
3690 int result = x / data;
3691 if (result > 0xff)
3692 throw ProcessorException.DIVIDE_ERROR;
3694 int remainder = (x % data) << 8;
3695 cpu.eax = (cpu.eax & ~0xffff) | (0xff & result) | (0xff00 & remainder);
3698 private final void div_o16(int data)
3700 if (data == 0)
3701 throw ProcessorException.DIVIDE_ERROR;
3703 long x = (cpu.edx & 0xffffl);
3704 x <<= 16;
3705 x |= (cpu.eax & 0xffffl);
3707 long result = x / data;
3708 if (result > 0xffffl)
3709 throw ProcessorException.DIVIDE_ERROR;
3711 long remainder = x % data;
3712 cpu.eax = (cpu.eax & ~0xffff) | (int)(result & 0xffff);
3713 cpu.edx = (cpu.edx & ~0xffff) | (int)(remainder & 0xffff);
3716 private final void div_o32(int data)
3718 long d = 0xffffffffl & data;
3720 if (d == 0)
3721 throw ProcessorException.DIVIDE_ERROR;
3723 long temp = (long)cpu.edx;
3724 temp <<= 32;
3725 temp |= (0xffffffffl & cpu.eax);
3727 long r2 = (temp & 1);
3728 long n2 = (temp >>> 1);
3730 long q2 = n2 / d;
3731 long m2 = n2 % d;
3733 long q = (q2 << 1);
3734 long r = (m2 << 1) + r2;
3736 q += (r / d);
3737 r %= d;
3738 if (q > 0xffffffffl)
3739 throw ProcessorException.DIVIDE_ERROR;
3741 cpu.eax = (int)q;
3742 cpu.edx = (int)r;
3745 private final void idiv_o8(byte data)
3747 if (data == 0)
3748 throw ProcessorException.DIVIDE_ERROR;
3750 short temp = (short)cpu.eax;
3751 int result = temp / data;
3752 int remainder = temp % data;
3753 if ((result > Byte.MAX_VALUE) || (result < Byte.MIN_VALUE))
3754 throw ProcessorException.DIVIDE_ERROR;
3756 cpu.eax = (cpu.eax & ~0xffff) | (0xff & result) | ((0xff & remainder) << 8); //AH is remainder
3759 private final void idiv_o16(short data)
3761 if (data == 0) {
3762 throw ProcessorException.DIVIDE_ERROR;
3764 int temp = (cpu.edx << 16) | (cpu.eax & 0xffff);
3765 int result = temp / (int)data;
3766 int remainder = temp % data;
3768 if ((result > Short.MAX_VALUE) || (result < Short.MIN_VALUE))
3769 throw ProcessorException.DIVIDE_ERROR;
3771 cpu.eax = (cpu.eax & ~0xffff) | (0xffff & result); //AX is result
3772 cpu.edx = (cpu.edx & ~0xffff) | (0xffff & remainder); //DX is remainder
3775 private final void idiv_o32(int data)
3777 if (data == 0)
3778 throw ProcessorException.DIVIDE_ERROR;
3780 long temp = (0xffffffffl & cpu.edx) << 32;
3781 temp |= (0xffffffffl & cpu.eax);
3782 long result = temp / data;
3783 if ((result > Integer.MAX_VALUE) || (result < Integer.MIN_VALUE))
3784 throw ProcessorException.DIVIDE_ERROR;
3786 long remainder = temp % data;
3788 cpu.eax = (int)result; //EAX is result
3789 cpu.edx = (int)remainder; //EDX is remainder
3792 private final void btc_mem(int offset, Segment segment, int address) throws ProcessorException
3794 address += (offset >>> 3);
3795 offset &= 0x7;
3797 byte data = segment.getByte(address);
3798 segment.setByte(address, (byte)(data ^ (1 << offset)));
3799 cpu.setCarryFlag(data, offset, Processor.CY_NTH_BIT_SET);
3802 private final void bts_mem(int offset, Segment segment, int address) throws ProcessorException
3804 address += (offset >>> 3);
3805 offset &= 0x7;
3807 byte data = segment.getByte(address);
3808 segment.setByte(address, (byte)(data | (1 << offset)));
3809 cpu.setCarryFlag(data, offset, Processor.CY_NTH_BIT_SET);
3812 private final void btr_mem(int offset, Segment segment, int address) throws ProcessorException
3814 address += (offset >>> 3);
3815 offset &= 0x7;
3817 byte data = segment.getByte(address);
3818 segment.setByte(address, (byte)(data & ~(1 << offset)));
3819 cpu.setCarryFlag(data, offset, Processor.CY_NTH_BIT_SET);
3822 private final void bt_mem(int offset, Segment segment, int address) throws ProcessorException
3824 address += (offset >>> 3);
3825 offset &= 0x7;
3826 cpu.setCarryFlag(segment.getByte(address), offset, Processor.CY_NTH_BIT_SET);
3829 private final int bsf(int source, int initial) throws ProcessorException
3831 if (source == 0) {
3832 cpu.setZeroFlag(true);
3833 return initial;
3834 } else {
3835 cpu.setZeroFlag(false);
3836 return numberOfTrailingZeros(source);
3840 private final int bsr(int source, int initial) throws ProcessorException
3842 if (source == 0) {
3843 cpu.setZeroFlag(true);
3844 return initial;
3845 } else {
3846 cpu.setZeroFlag(false);
3847 return 31 - numberOfLeadingZeros(source);
3851 private final void aaa()
3853 if (((cpu.eax & 0xf) > 0x9) || cpu.getAuxiliaryCarryFlag()) {
3854 int alCarry = ((cpu.eax & 0xff) > 0xf9) ? 0x100 : 0x000;
3855 cpu.eax = (0xffff0000 & cpu.eax) | (0x0f & (cpu.eax + 6)) | (0xff00 & (cpu.eax + 0x100 + alCarry));
3856 cpu.setAuxiliaryCarryFlag(true);
3857 cpu.setCarryFlag(true);
3858 } else {
3859 cpu.setAuxiliaryCarryFlag(false);
3860 cpu.setCarryFlag(false);
3861 cpu.eax = cpu.eax & 0xffffff0f;
3865 private final void aad(int base) throws ProcessorException
3867 int tl = (cpu.eax & 0xff);
3868 int th = ((cpu.eax >> 8) & 0xff);
3870 int ax1 = th * base;
3871 int ax2 = ax1 + tl;
3873 cpu.eax = (cpu.eax & ~0xffff) | (ax2 & 0xff);
3876 bitwise_flags((byte)ax2);
3878 cpu.setAuxiliaryCarryFlag(ax1, ax2, Processor.AC_BIT4_NEQ);
3879 cpu.setCarryFlag(ax2, Processor.CY_GREATER_FF);
3880 cpu.setOverflowFlag(ax2, tl, Processor.OF_BIT7_DIFFERENT);
3883 private final void aam(int base) throws ProcessorException
3885 int tl = 0xff & cpu.eax;
3886 if (base == 0)
3887 throw ProcessorException.DIVIDE_ERROR;
3888 int ah = 0xff & (tl / base);
3889 int al = 0xff & (tl % base);
3890 cpu.eax &= ~0xffff;
3891 cpu.eax |= (al | (ah << 8));
3893 cpu.setAuxiliaryCarryFlag(false);
3894 bitwise_flags((byte)al);
3897 private final void aas()
3899 if (((cpu.eax & 0xf) > 0x9) || cpu.getAuxiliaryCarryFlag()) {
3900 int alBorrow = (cpu.eax & 0xff) < 6 ? 0x100 : 0x000;
3901 cpu.eax = (0xffff0000 & cpu.eax) | (0x0f & (cpu.eax - 6)) | (0xff00 & (cpu.eax - 0x100 - alBorrow));
3902 cpu.setAuxiliaryCarryFlag(true);
3903 cpu.setCarryFlag(true);
3904 } else {
3905 cpu.setAuxiliaryCarryFlag(false);
3906 cpu.setCarryFlag(false);
3907 cpu.eax = cpu.eax & 0xffffff0f;
3911 private final void daa()
3913 int al = cpu.eax & 0xff;
3914 boolean newCF;
3915 if (((cpu.eax & 0xf) > 0x9) || cpu.getAuxiliaryCarryFlag()) {
3916 al += 6;
3917 cpu.setAuxiliaryCarryFlag(true);
3918 } else
3919 cpu.setAuxiliaryCarryFlag(false);
3921 if (((al & 0xff) > 0x9f) || cpu.getCarryFlag()) {
3922 al += 0x60;
3923 newCF = true;
3924 } else
3925 newCF = false;
3927 cpu.eax = (cpu.eax & ~0xff) | (0xff & al);
3928 bitwise_flags((byte)al);
3929 cpu.setCarryFlag(newCF);
3932 private final void das()
3934 boolean tempCF = false;
3935 int tempAL = 0xff & cpu.eax;
3936 if (((tempAL & 0xf) > 0x9) || cpu.getAuxiliaryCarryFlag()) {
3937 cpu.setAuxiliaryCarryFlag(true);
3938 cpu.eax = (cpu.eax & ~0xff) | ((cpu.eax - 0x06) & 0xff);
3939 tempCF = (tempAL < 0x06) || cpu.getCarryFlag();
3942 if ((tempAL > 0x99) || cpu.getCarryFlag()) {
3943 cpu.eax = (cpu.eax & ~0xff) | ((cpu.eax - 0x60) & 0xff);
3944 tempCF = true;
3947 bitwise_flags((byte)cpu.eax);
3948 cpu.setCarryFlag(tempCF);
3951 private final void lahf()
3953 int result = 0x0200;
3954 if (cpu.getSignFlag()) result |= 0x8000;
3955 if (cpu.getZeroFlag()) result |= 0x4000;
3956 if (cpu.getAuxiliaryCarryFlag()) result |= 0x1000;
3957 if (cpu.getParityFlag()) result |= 0x0400;
3958 if (cpu.getCarryFlag()) result |= 0x0100;
3959 cpu.eax &= 0xffff00ff;
3960 cpu.eax |= result;
3963 private final void sahf()
3965 int ah = (cpu.eax & 0xff00);
3966 cpu.setCarryFlag(0 != (ah & 0x0100));
3967 cpu.setParityFlag(0 != (ah & 0x0400));
3968 cpu.setAuxiliaryCarryFlag(0 != (ah & 0x1000));
3969 cpu.setZeroFlag(0 != (ah & 0x4000));
3970 cpu.setSignFlag(0 != (ah & 0x8000));
3973 private final void jo_o8(byte offset)
3975 if (cpu.getOverflowFlag()) jump_o8(offset);
3978 private final void jno_o8(byte offset)
3980 if (!cpu.getOverflowFlag()) jump_o8(offset);
3983 private final void jc_o8(byte offset)
3985 if (cpu.getCarryFlag()) jump_o8(offset);
3988 private final void jnc_o8(byte offset)
3990 if (!cpu.getCarryFlag()) jump_o8(offset);
3993 private final void jz_o8(byte offset)
3995 if (cpu.getZeroFlag()) jump_o8(offset);
3998 private final void jnz_o8(byte offset)
4000 if (!cpu.getZeroFlag()) jump_o8(offset);
4003 private final void jna_o8(byte offset)
4005 if (cpu.getCarryFlag() || cpu.getZeroFlag()) jump_o8(offset);
4008 private final void ja_o8(byte offset)
4010 if ((!cpu.getCarryFlag()) && (!cpu.getZeroFlag())) jump_o8(offset);
4013 private final void js_o8(byte offset)
4015 if (cpu.getSignFlag()) jump_o8(offset);
4018 private final void jns_o8(byte offset)
4020 if (!cpu.getSignFlag()) jump_o8(offset);
4023 private final void jp_o8(byte offset)
4025 if (cpu.getParityFlag()) jump_o8(offset);
4028 private final void jnp_o8(byte offset)
4030 if (!cpu.getParityFlag()) jump_o8(offset);
4033 private final void jl_o8(byte offset)
4035 if (cpu.getSignFlag() != cpu.getOverflowFlag()) jump_o8(offset);
4038 private final void jnl_o8(byte offset)
4040 if (cpu.getSignFlag() == cpu.getOverflowFlag()) jump_o8(offset);
4043 private final void jng_o8(byte offset)
4045 if (cpu.getZeroFlag() || (cpu.getSignFlag() != cpu.getOverflowFlag())) jump_o8(offset);
4048 private final void jg_o8(byte offset)
4050 if ((!cpu.getZeroFlag()) && (cpu.getSignFlag() == cpu.getOverflowFlag())) jump_o8(offset);
4053 private final void jo_o16(short offset)
4055 if (cpu.getOverflowFlag()) jump_o16(offset);
4058 private final void jno_o16(short offset)
4060 if (!cpu.getOverflowFlag()) jump_o16(offset);
4063 private final void jc_o16(short offset)
4065 if (cpu.getCarryFlag()) jump_o16(offset);
4068 private final void jnc_o16(short offset)
4070 if (!cpu.getCarryFlag()) jump_o16(offset);
4073 private final void jz_o16(short offset)
4075 if (cpu.getZeroFlag()) jump_o16(offset);
4078 private final void jnz_o16(short offset)
4080 if (!cpu.getZeroFlag()) jump_o16(offset);
4083 private final void jna_o16(short offset)
4085 if (cpu.getCarryFlag() || cpu.getZeroFlag()) jump_o16(offset);
4088 private final void ja_o16(short offset)
4090 if ((!cpu.getCarryFlag()) && (!cpu.getZeroFlag())) jump_o16(offset);
4093 private final void js_o16(short offset)
4095 if (cpu.getSignFlag()) jump_o16(offset);
4098 private final void jns_o16(short offset)
4100 if (!cpu.getSignFlag()) jump_o16(offset);
4103 private final void jp_o16(short offset)
4105 if (cpu.getParityFlag()) jump_o16(offset);
4108 private final void jnp_o16(short offset)
4110 if (!cpu.getParityFlag()) jump_o16(offset);
4113 private final void jl_o16(short offset)
4115 if (cpu.getSignFlag() != cpu.getOverflowFlag()) jump_o16(offset);
4118 private final void jnl_o16(short offset)
4120 if (cpu.getSignFlag() == cpu.getOverflowFlag()) jump_o16(offset);
4123 private final void jng_o16(short offset)
4125 if (cpu.getZeroFlag() || (cpu.getSignFlag() != cpu.getOverflowFlag())) jump_o16(offset);
4128 private final void jg_o16(short offset)
4130 if ((!cpu.getZeroFlag()) && (cpu.getSignFlag() == cpu.getOverflowFlag())) jump_o16(offset);
4133 private final void jo_o32(int offset)
4135 if (cpu.getOverflowFlag()) jump_o32(offset);
4138 private final void jno_o32(int offset)
4140 if (!cpu.getOverflowFlag()) jump_o32(offset);
4143 private final void jc_o32(int offset)
4145 if (cpu.getCarryFlag()) jump_o32(offset);
4148 private final void jnc_o32(int offset)
4150 if (!cpu.getCarryFlag()) jump_o32(offset);
4153 private final void jz_o32(int offset)
4155 if (cpu.getZeroFlag()) jump_o32(offset);
4158 private final void jnz_o32(int offset)
4160 if (!cpu.getZeroFlag()) jump_o32(offset);
4163 private final void jna_o32(int offset)
4165 if (cpu.getCarryFlag() || cpu.getZeroFlag()) jump_o32(offset);
4168 private final void ja_o32(int offset)
4170 if ((!cpu.getCarryFlag()) && (!cpu.getZeroFlag())) jump_o32(offset);
4173 private final void js_o32(int offset)
4175 if (cpu.getSignFlag()) jump_o32(offset);
4178 private final void jns_o32(int offset)
4180 if (!cpu.getSignFlag()) jump_o32(offset);
4183 private final void jp_o32(int offset)
4185 if (cpu.getParityFlag()) jump_o32(offset);
4188 private final void jnp_o32(int offset)
4190 if (!cpu.getParityFlag()) jump_o32(offset);
4193 private final void jl_o32(int offset)
4195 if (cpu.getSignFlag() != cpu.getOverflowFlag()) jump_o32(offset);
4198 private final void jnl_o32(int offset)
4200 if (cpu.getSignFlag() == cpu.getOverflowFlag()) jump_o32(offset);
4203 private final void jng_o32(int offset)
4205 if (cpu.getZeroFlag() || (cpu.getSignFlag() != cpu.getOverflowFlag())) jump_o32(offset);
4208 private final void jg_o32(int offset)
4210 if ((!cpu.getZeroFlag()) && (cpu.getSignFlag() == cpu.getOverflowFlag())) jump_o32(offset);
4213 private final void jcxz(byte offset)
4215 if ((cpu.ecx & 0xffff) == 0) jump_o8(offset);
4218 private final void jecxz(byte offset)
4220 if (cpu.ecx == 0) jump_o8(offset);
4223 private final void loop_cx(byte offset)
4225 cpu.ecx= (cpu.ecx & ~0xFFFF) | (((0xFFFF &cpu.ecx)-1) & 0xFFFF);
4226 if ((cpu.ecx & 0xFFFF) != 0)
4227 jump_o8(offset);
4230 private final void loop_ecx(byte offset)
4232 cpu.ecx--;
4233 if (cpu.ecx != 0)
4234 jump_o8(offset);
4237 private final void loopz_cx(byte offset)
4239 cpu.ecx = (cpu.ecx & ~0xFFFF) | ((cpu.ecx - 1) & 0xFFFF);
4240 if (cpu.getZeroFlag() && ((cpu.ecx & 0xFFFF) != 0))
4241 jump_o8(offset);
4244 private final void loopz_ecx(byte offset)
4246 cpu.ecx--;
4247 if (cpu.getZeroFlag() && (cpu.ecx != 0))
4248 jump_o8(offset);
4251 private final void loopnz_cx(byte offset)
4253 cpu.ecx= (cpu.ecx & ~0xFFFF) | ((cpu.ecx-1) & 0xFFFF);
4254 if (!cpu.getZeroFlag() && ((cpu.ecx & 0xFFFF) != 0))
4255 jump_o8(offset);
4258 private final void loopnz_ecx(byte offset)
4260 cpu.ecx--;
4261 if (!cpu.getZeroFlag() && (cpu.ecx != 0))
4262 jump_o8(offset);
4265 private final void jump_o8(byte offset)
4267 if (offset == 0)
4268 return; //first protected mode throws on a jump 0 (some segment problem?)
4270 int tempEIP = cpu.eip + offset;
4271 cpu.cs.checkAddress(tempEIP);// check whether eip is outside cs limit
4272 cpu.eip = tempEIP;
4275 private final void jump_o16(short offset)
4277 int tempEIP = (cpu.eip + offset) & 0xffff;
4278 cpu.cs.checkAddress(tempEIP);// check whether eip is outside cs limit
4279 cpu.eip = tempEIP;
4282 private final void jump_o32(int offset)
4284 int tempEIP = cpu.eip + offset;
4285 cpu.cs.checkAddress(tempEIP);// check whether eip is outside cs limit
4286 cpu.eip = tempEIP;
4289 private final void jump_abs(int offset)
4291 cpu.cs.checkAddress(offset);// check whether eip is outside cs limit
4292 cpu.eip = offset;
4295 private final void jump_far(int targetEIP, int targetSelector)
4297 Segment newSegment = cpu.getSegment(targetSelector);
4298 if (newSegment == SegmentFactory.NULL_SEGMENT)
4299 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
4301 switch (newSegment.getType()) { // segment type
4302 default: // not a valid segment descriptor for a jump
4303 System.err.println("Emulated: Invalid segment type " + newSegment.getType() + ".");
4304 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4305 case 0x05: // Task Gate
4306 System.err.println("Critical error: Task gate not implemented");
4307 throw new IllegalStateException("Far jump through task gate is not implemented");
4308 case 0x0b: // TSS (Busy)
4309 case 0x09: // TSS (Not Busy)
4311 if ((newSegment.getDPL() < cpu.getCPL()) || (newSegment.getDPL() < newSegment.getRPL()) )
4312 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4313 if (!newSegment.isPresent())
4314 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSelector, true);
4315 if (newSegment.getLimit() < 0x67) // large enough to read ?
4316 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, targetSelector, true);
4317 if ((newSegment.getType() & 0x2) != 0) // busy ? if yes,error
4318 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4320 newSegment.getByte(0); // new TSS paged into memory ?
4321 cpu.tss.getByte(0);// old TSS paged into memory ?
4323 int esSelector = 0xFFFF & newSegment.getWord(72); // read new registers
4324 int csSelector = 0xFFFF & newSegment.getWord(76);
4325 int ssSelector = 0xFFFF & newSegment.getWord(80);
4326 int dsSelector = 0xFFFF & newSegment.getWord(84);
4327 int fsSelector = 0xFFFF & newSegment.getWord(88);
4328 int gsSelector = 0xFFFF & newSegment.getWord(92);
4329 int ldtSelector = 0xFFFF & newSegment.getWord(96);
4331 if((ldtSelector & 0x4) !=0) // not in gdt
4332 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, ldtSelector, true);
4333 cpu.gdtr.checkAddress((ldtSelector & ~0x7) + 7 ) ;// check ldtr is valid
4334 if((cpu.readSupervisorByte(cpu.gdtr, ((ldtSelector & ~0x7) + 5 )) & 0xE) != 2) { // not a ldt entry
4335 System.err.println("Accessed LDT selector global byte 5:" + cpu.readSupervisorByte(cpu.gdtr, ((ldtSelector & ~0x7) + 5 )));
4336 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, ldtSelector, true);
4338 Segment newLdtr=cpu.getSegment(ldtSelector); // get new ldt
4340 if ((esSelector & 0x4) !=0) // check es descriptor is in memory
4341 newLdtr.checkAddress((esSelector & ~0x7)+7);
4342 else
4343 cpu.gdtr.checkAddress((esSelector & ~0x7)+7);
4345 if ((csSelector & 0x4)!=0) // check cs descriptor is in memory
4346 newLdtr.checkAddress((csSelector & ~0x7)+7);
4347 else
4348 cpu.gdtr.checkAddress((csSelector & ~0x7)+7);
4350 if ((ssSelector & 0x4)!=0) // check ss descriptor is in memory
4351 newLdtr.checkAddress((ssSelector & ~0x7)+7);
4352 else
4353 cpu.gdtr.checkAddress((ssSelector & ~0x7)+7);
4355 if ((dsSelector & 0x4)!=0) // check ds descriptor is in memory
4356 newLdtr.checkAddress((dsSelector & ~0x7)+7);
4357 else
4358 cpu.gdtr.checkAddress((dsSelector & ~0x7)+7);
4360 if ((fsSelector & 0x4)!=0) // check fs descriptor is in memory
4361 newLdtr.checkAddress((fsSelector & ~0x7)+7);
4362 else
4363 cpu.gdtr.checkAddress((fsSelector & ~0x7)+7);
4365 if ((gsSelector & 0x4)!=0) // check gs descriptor is in memory
4366 newLdtr.checkAddress((gsSelector & ~0x7)+7);
4367 else
4368 cpu.gdtr.checkAddress((gsSelector & ~0x7)+7);
4370 cpu.setSupervisorDoubleWord(cpu.gdtr, (cpu.tss.getSelector() & ~0x7) + 4,
4371 ~0x200 & cpu.readSupervisorDoubleWord(cpu.gdtr, (cpu.tss.getSelector() & ~0x7) + 4)); // clear busy bit of current tss
4372 ((ProtectedModeSegment.AbstractTSS) cpu.tss).saveCPUState(cpu);
4374 cpu.setSupervisorDoubleWord(cpu.gdtr, (targetSelector & ~0x7) + 4,
4375 0x200 | cpu.readSupervisorDoubleWord(cpu.gdtr, (targetSelector & ~0x7) + 4)); // set busy bit of new tss
4378 cpu.setCR0(cpu.getCR0() | 0x8); // set TS flag in CR0;
4379 cpu.tss=newSegment;
4380 ((ProtectedModeSegment.AbstractTSS) cpu.tss).restoreCPUState(cpu);
4381 cpu.cs.checkAddress(cpu.eip);
4383 return;
4385 case 0x0c: // Call Gate
4386 System.err.println("Critical error: Call gate not implemented");
4387 throw new IllegalStateException("Far jump through call gate not implemented");
4388 case 0x18: // Non-conforming Code Segment
4389 case 0x19: // Non-conforming Code Segment
4390 case 0x1a: // Non-conforming Code Segment
4391 case 0x1b: { // Non-conforming Code Segment
4392 if ((newSegment.getRPL() != cpu.getCPL()) || (newSegment.getDPL() > cpu.getCPL()))
4393 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4394 if (!newSegment.isPresent())
4395 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSelector, true);
4397 newSegment.checkAddress(targetEIP);
4398 newSegment.setRPL(cpu.getCPL());
4399 cpu.cs = newSegment;
4400 cpu.eip = targetEIP;
4401 return;
4403 case 0x1c: // Conforming Code Segment (Not Readable & Not Accessed)
4404 case 0x1d: // Conforming Code Segment (Not Readable & Accessed)
4405 case 0x1e: // Conforming Code Segment (Readable & Not Accessed)
4406 case 0x1f: { // Conforming Code Segment (Readable & Accessed)
4407 if (newSegment.getDPL() > cpu.getCPL())
4408 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4409 if (!newSegment.isPresent())
4410 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSelector, true);
4412 newSegment.checkAddress(targetEIP);
4413 newSegment.setRPL(cpu.getCPL());
4414 cpu.cs = newSegment;
4415 cpu.eip = targetEIP;
4416 return;
4421 private final void call_o32_a32(int target)
4423 int tempEIP = cpu.eip + target;
4425 cpu.cs.checkAddress(tempEIP);
4427 if ((cpu.esp < 4) && (cpu.esp > 0))
4428 throw ProcessorException.STACK_SEGMENT_0;
4430 cpu.ss.setDoubleWord(cpu.esp - 4, cpu.eip );
4431 cpu.esp -= 4;
4433 cpu.eip = tempEIP;
4436 private final void call_o16_a16(int target)
4438 int tempEIP = 0xFFFF & (cpu.eip + target) ;
4440 cpu.cs.checkAddress(tempEIP);
4442 if ((0xffff & cpu.esp) < 2)
4443 throw ProcessorException.STACK_SEGMENT_0;
4445 cpu.ss.setWord((cpu.esp - 2) & 0xffff, (short) (0xFFFF & cpu.eip));
4446 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp - 2) & 0xffff);
4448 cpu.eip = tempEIP;
4451 private final void call_o16_a32(int target)
4453 int tempEIP = 0xFFFF & (cpu.eip + target) ;
4455 cpu.cs.checkAddress(tempEIP);
4457 if ((cpu.esp < 2) && (cpu.esp > 0))
4458 throw ProcessorException.STACK_SEGMENT_0;
4460 cpu.ss.setWord(cpu.esp - 2, (short) (0xFFFF & cpu.eip));
4461 cpu.esp -= 2;
4463 cpu.eip = tempEIP;
4466 private final void call_o32_a16(int target)
4468 int tempEIP = cpu.eip + target;
4470 cpu.cs.checkAddress(tempEIP);
4472 if ((0xffff & cpu.esp) < 4)
4473 throw ProcessorException.STACK_SEGMENT_0;
4475 cpu.ss.setDoubleWord((cpu.esp - 4) & 0xffff, cpu.eip);
4476 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp - 4) & 0xffff);
4478 cpu.eip = tempEIP;
4481 private final void call_abs_o16_a16(int target)
4483 cpu.cs.checkAddress(target & 0xFFFF);
4485 if ((cpu.esp & 0xffff) < 2)
4486 throw ProcessorException.STACK_SEGMENT_0;
4488 cpu.ss.setWord((cpu.esp - 2) & 0xffff, (short) (0xFFFF & cpu.eip));
4489 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp - 2) & 0xffff);
4491 cpu.eip = target & 0xFFFF;
4494 private final void call_abs_o16_a32(int target)
4496 cpu.cs.checkAddress(target & 0xFFFF);
4498 if ((cpu.esp < 2) && (cpu.esp > 0))
4499 throw ProcessorException.STACK_SEGMENT_0;
4501 cpu.ss.setWord(cpu.esp - 2, (short) (0xFFFF & cpu.eip));
4502 cpu.esp -= 2;
4504 cpu.eip = target & 0xFFFF;
4507 private final void call_abs_o32_a32(int target)
4509 cpu.cs.checkAddress(target);
4511 if ((cpu.esp < 4) && (cpu.esp > 0))
4512 throw ProcessorException.STACK_SEGMENT_0;
4514 cpu.ss.setDoubleWord(cpu.esp - 4, cpu.eip);
4515 cpu.esp -= 4;
4517 cpu.eip = target;
4520 private final void call_abs_o32_a16(int target)
4522 cpu.cs.checkAddress(target);
4524 if ((cpu.esp & 0xffff) < 4)
4525 throw ProcessorException.STACK_SEGMENT_0;
4527 cpu.ss.setDoubleWord((cpu.esp - 4) & 0xffff, cpu.eip);
4528 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp - 4) & 0xffff);
4530 cpu.eip = target;
4533 private final void call_far_o16_a32(int targetEIP, int targetSelector)
4535 Segment newSegment = cpu.getSegment(targetSelector);
4536 if (newSegment == SegmentFactory.NULL_SEGMENT)
4537 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
4539 switch (newSegment.getType())
4540 { // segment type
4541 default: // not a valid segment descriptor for a jump
4542 System.err.println("Emulated: Invalid segment type " + newSegment.getType() + ".");
4543 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4544 case 0x01: // TSS 16-bit (Not Busy)
4545 case 0x03: // TSS 16-bit (Busy)
4546 System.err.println("Critical error: 16-bit TSS not implemented");
4547 throw new IllegalStateException("O16 A32 CALL FAR to 16-bit TSS not implemented");
4548 case 0x04: // Call Gate 16-bit
4550 if ((newSegment.getRPL() > cpu.getCPL()) || (newSegment.getDPL() < cpu.getCPL()))
4551 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4552 if (!newSegment.isPresent())
4553 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSelector, true);
4555 ProtectedModeSegment.GateSegment gate = (ProtectedModeSegment.GateSegment) newSegment;
4557 int targetSegmentSelector = gate.getTargetSegment();
4559 Segment targetSegment;
4560 try {
4561 targetSegment = cpu.getSegment(targetSegmentSelector);
4562 } catch (ProcessorException e) {
4563 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
4565 if (targetSegment == SegmentFactory.NULL_SEGMENT)
4566 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
4568 if (targetSegment.getDPL() > cpu.getCPL())
4569 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4571 switch (targetSegment.getType()) {
4572 default:
4573 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
4575 case 0x18: //Code, Execute-Only
4576 case 0x19: //Code, Execute-Only, Accessed
4577 case 0x1a: //Code, Execute/Read
4578 case 0x1b: //Code, Execute/Read, Accessed
4580 if (!targetSegment.isPresent())
4581 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSegmentSelector, true);
4583 if (targetSegment.getDPL() < cpu.getCPL()) {
4584 System.err.println("Critical error: 16-bit call gate: jump to more privileged " +
4585 "segment not implemented");
4586 throw new IllegalStateException("O16 A32 CALL FAR to 16-bit call gate to more priviledged segment not implmented");
4587 //MORE-PRIVILEGE
4588 } else if (targetSegment.getDPL() == cpu.getCPL()) {
4589 System.err.println("O16 A32 CALL FAR: 16-bit call gate to same priviledge segment not implemented");
4590 throw new IllegalStateException("O16 A32 CALL FAR to 16-bit call gate to same priviledge segment not implemented");
4591 //SAME-PRIVILEGE
4592 } else
4593 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
4595 // break;
4596 case 0x1c: //Code: Execute-Only, Conforming
4597 case 0x1d: //Code: Execute-Only, Conforming, Accessed
4598 case 0x1e: //Code: Execute/Read, Conforming
4599 case 0x1f: //Code: Execute/Read, Conforming, Accessed
4601 if (!targetSegment.isPresent())
4602 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSegmentSelector, true);
4604 System.err.println("Critical error: 16-bit call gate: jump to same privilege " +
4605 "conforming segment not implemented");
4606 throw new IllegalStateException("O16 A32 CALL FAR to 16-bit call gate: Jump to " +
4607 "same privieledge conforming segment not implemented");
4608 //SAME-PRIVILEGE
4610 // break;
4613 // break;
4614 case 0x05: // Task Gate
4615 System.err.println("Critical error: Task gate not implemented");
4616 throw new IllegalStateException("O16 A32 CALL FAR to task gate not implemented");
4617 case 0x09: // TSS (Not Busy)
4618 case 0x0b: // TSS (Busy)
4619 System.err.println("Critical error: TSS not implemented");
4620 throw new IllegalStateException("O16 A32 CALL FAR to TSS not implemented");
4621 case 0x0c: // Call Gate
4622 System.err.println("Critical error: Call gate not implemented");
4623 throw new IllegalStateException("O16 A32 CALL FAR TO call gate not supported");
4624 case 0x18: // Non-conforming Code Segment
4625 case 0x19: // Non-conforming Code Segment
4626 case 0x1a: // Non-conforming Code Segment
4627 case 0x1b: // Non-conforming Code Segment
4629 if ((newSegment.getRPL() > cpu.getCPL()) || (newSegment.getDPL() != cpu.getCPL()))
4630 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4631 if (!newSegment.isPresent())
4632 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSelector, true);
4634 if ((cpu.esp < 4) && (cpu.esp > 0))
4635 throw ProcessorException.STACK_SEGMENT_0;
4637 newSegment.checkAddress(targetEIP&0xFFFF);
4639 cpu.ss.setWord(cpu.esp - 2, (short) (0xFFFF & cpu.cs.getSelector()));
4640 cpu.ss.setWord(cpu.esp - 4, (short) (0xFFFF & cpu.eip));
4641 cpu.esp -= 4;
4643 cpu.cs = newSegment;
4644 cpu.cs.setRPL(cpu.getCPL());
4645 cpu.eip = targetEIP & 0xFFFF;
4646 return;
4648 case 0x1c: // Conforming Code Segment (Not Readable & Not Accessed)
4649 case 0x1d: // Conforming Code Segment (Not Readable & Accessed)
4650 case 0x1e: // Conforming Code Segment (Readable & Not Accessed)
4651 case 0x1f: // Conforming Code Segment (Readable & Accessed)
4652 System.err.println("Critical error: Conforming code segment not implemented");
4653 throw new IllegalStateException("O16 A32 CALL FAR to conforming code segment not implemented");
4657 private final void call_far_o16_a16(int targetEIP, int targetSelector)
4659 if ((targetSelector & 0xfffc) == 0)
4660 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
4662 Segment newSegment = cpu.getSegment(targetSelector);
4663 if (newSegment == SegmentFactory.NULL_SEGMENT)
4664 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
4666 switch (newSegment.getType())
4667 { // segment type
4668 default: // not a valid segment descriptor for a jump
4669 System.err.println("Emulated: Invalid segment type " + newSegment.getType() + ".");
4670 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4671 case 0x01: // TSS 16-bit (Not Busy)
4672 case 0x03: // TSS 16-bit (Busy)
4673 System.err.println("Critical error: 16-bit TSS not implemented");
4674 throw new IllegalStateException("O16 A16 CALL FAR to 16-bit TSS not implemented");
4675 case 0x04: // Call Gate 16-bit
4677 if ((newSegment.getDPL() < newSegment.getRPL()) || (newSegment.getDPL() < cpu.getCPL()))
4678 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector & 0xfffc, true);
4679 if (!newSegment.isPresent())
4680 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSelector & 0xfffc, true);
4682 ProtectedModeSegment.CallGate16Bit gate = (ProtectedModeSegment.CallGate16Bit) newSegment;
4684 int targetSegmentSelector = gate.getTargetSegment();
4686 if ((targetSegmentSelector & 0xfffc) == 0)
4687 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, 0, true);
4689 Segment targetSegment;
4690 try {
4691 targetSegment = cpu.getSegment(targetSegmentSelector);
4692 } catch (ProcessorException e) {
4693 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector & 0xfffc, true);
4695 if (targetSegment == SegmentFactory.NULL_SEGMENT)
4696 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector & 0xfffc, true);
4698 if ((targetSegment.getDPL() > cpu.getCPL()) || (targetSegment.isSystem()) || ((targetSegment.getType() & 0x18) == 0x10))
4699 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector & 0xfffc, true);
4701 if (!targetSegment.isPresent())
4702 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSegmentSelector & 0xfffc, true);
4704 switch (targetSegment.getType()) {
4705 default:
4706 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
4708 case 0x18: //Code, Execute-Only
4709 case 0x19: //Code, Execute-Only, Accessed
4710 case 0x1a: //Code, Execute/Read
4711 case 0x1b: //Code, Execute/Read, Accessed
4714 if (targetSegment.getDPL() < cpu.getCPL()) {
4715 //MORE-PRIVILEGE
4716 int newStackSelector = 0;
4717 int newESP = 0;
4718 if ((cpu.tss.getType() & 0x8) != 0) {
4719 int tssStackAddress = (targetSegment.getDPL() * 8) + 4;
4720 if ((tssStackAddress + 7) > cpu.tss.getLimit())
4721 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, cpu.tss.getSelector(), true);
4723 boolean isSup = cpu.linearMemory.isSupervisor();
4724 try {
4725 cpu.linearMemory.setSupervisor(true);
4726 newStackSelector = 0xffff & cpu.tss.getWord(tssStackAddress + 4);
4727 newESP = cpu.tss.getDoubleWord(tssStackAddress);
4728 } finally {
4729 cpu.linearMemory.setSupervisor(isSup);
4731 } else {
4732 int tssStackAddress = (targetSegment.getDPL() * 4) + 2;
4733 if ((tssStackAddress + 4) > cpu.tss.getLimit())
4734 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, cpu.tss.getSelector(), true);
4735 newStackSelector = 0xffff & cpu.tss.getWord(tssStackAddress + 2);
4736 newESP = 0xffff & cpu.tss.getWord(tssStackAddress);
4739 if ((newStackSelector & 0xfffc) == 0)
4740 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, 0, true);
4742 Segment newStackSegment = null;
4743 try {
4744 newStackSegment = cpu.getSegment(newStackSelector);
4745 } catch (ProcessorException e) {
4746 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector, true);
4749 if (newStackSegment.getRPL() != targetSegment.getDPL())
4750 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector & 0xfffc, true);
4752 if ((newStackSegment.getDPL() != targetSegment.getDPL()) || ((newStackSegment.getType() & 0x1a) != 0x12))
4753 throw new ProcessorException(ProcessorException.Type.TASK_SWITCH, newStackSelector & 0xfffc, true);
4755 if (!(newStackSegment.isPresent()))
4756 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, newStackSelector & 0xfffc, true);
4758 int parameters = gate.getParameterCount() & 0x1f;
4759 if ((newStackSegment.getDefaultSizeFlag() && (cpu.esp < 8 + 2 * parameters) && (cpu.esp > 0)) ||
4760 !newStackSegment.getDefaultSizeFlag() && ((cpu.esp & 0xffff) < 8 + 2 * parameters))
4761 throw ProcessorException.STACK_SEGMENT_0;
4763 int targetOffset = 0xffff & gate.getTargetOffset();
4765 int returnSS = cpu.ss.getSelector();
4766 Segment oldStack = cpu.ss;
4767 int returnESP;
4768 if (cpu.ss.getDefaultSizeFlag())
4769 returnESP = cpu.esp;
4770 else
4771 returnESP = cpu.esp & 0xffff;
4772 int oldCS = cpu.cs.getSelector();
4773 int oldEIP;
4774 if (cpu.cs.getDefaultSizeFlag())
4775 oldEIP = cpu.eip;
4776 else
4777 oldEIP = cpu.eip & 0xffff;
4778 cpu.ss = newStackSegment;
4779 cpu.esp = newESP;
4780 cpu.ss.setRPL(targetSegment.getDPL());
4782 if (cpu.ss.getDefaultSizeFlag()) {
4783 cpu.esp -= 2;
4784 cpu.ss.setWord(cpu.esp, (short)returnSS);
4785 cpu.esp -= 2;
4786 cpu.ss.setWord(cpu.esp, (short)returnESP);
4787 for (int i = 0; i < parameters; i++) {
4788 cpu.esp -= 2;
4789 cpu.ss.setWord(cpu.esp, oldStack.getWord(returnESP + 2*parameters - 2*i -2));
4791 cpu.esp -= 2;
4792 cpu.ss.setWord(cpu.esp, (short)oldCS);
4793 cpu.esp -= 2;
4794 cpu.ss.setWord(cpu.esp, (short)oldEIP);
4795 } else {
4796 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp - 2) & 0xffff);
4797 cpu.ss.setWord(cpu.esp & 0xffff, (short)returnSS);
4798 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp - 2) & 0xffff);
4799 cpu.ss.setWord(cpu.esp & 0xffff, (short)returnESP);
4800 for (int i = 0; i < parameters; i++) {
4801 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp - 2) & 0xffff);
4802 cpu.ss.setWord(cpu.esp & 0xffff, oldStack.getWord((returnESP + 2*parameters - 2*i -2) & 0xffff));
4804 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp - 2) & 0xffff);
4805 cpu.ss.setWord(cpu.esp & 0xffff, (short)oldCS);
4806 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp - 2) & 0xffff);
4807 cpu.ss.setWord(cpu.esp & 0xffff, (short)oldEIP);
4809 targetSegment.checkAddress(targetOffset);
4810 cpu.cs = targetSegment;
4811 cpu.eip = targetOffset;
4812 cpu.setCPL(cpu.ss.getDPL());
4813 cpu.cs.setRPL(cpu.getCPL());
4815 } else if (targetSegment.getDPL() == cpu.getCPL()) {
4816 System.err.println("Critical error: 16-bit call gate: jump to same privilege " +
4817 "segment not implemented");
4818 throw new IllegalStateException("O16 A16 CALL FAR to 16-bit call gate same priviledge segment not implemented");
4819 //SAME-PRIVILEGE
4820 } else
4821 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
4823 break;
4824 case 0x1c: //Code: Execute-Only, Conforming
4825 case 0x1d: //Code: Execute-Only, Conforming, Accessed
4826 case 0x1e: //Code: Execute/Read, Conforming
4827 case 0x1f: //Code: Execute/Read, Conforming, Accessed
4829 System.err.println("Critical error: 16-bit call gate: jump to same privilege " +
4830 "conforming segment not implemented");
4831 throw new IllegalStateException("O16 A16 CALL FAR call gate to same priviledge conforming segment not implemented");
4832 //SAME-PRIVILEGE
4834 // break;
4837 break;
4838 case 0x05: // Task Gate
4839 System.err.println("Critical error: Task gate not implemented");
4840 throw new IllegalStateException("O16 A16 CALL FAR to task gate not implemented");
4841 case 0x09: // TSS (Not Busy)
4842 case 0x0b: // TSS (Busy)
4843 System.err.println("Critical error: TSS not implemented");
4844 throw new IllegalStateException("O16 A16 CALL FAR to TSS not implemented");
4845 case 0x0c: // Call Gate
4846 System.err.println("Critical error: Call gate not implemented");
4847 throw new IllegalStateException("O16 A16 CALL FAR to call gate not implemented");
4848 case 0x18: // Non-conforming Code Segment
4849 case 0x19: // Non-conforming Code Segment
4850 case 0x1a: // Non-conforming Code Segment
4851 case 0x1b: // Non-conforming Code Segment
4853 if(!newSegment.isPresent())
4854 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, newSegment.getSelector(), true);
4856 if ((cpu.esp < 4) && (cpu.esp > 0))
4857 throw ProcessorException.STACK_SEGMENT_0;
4859 newSegment.checkAddress(targetEIP&0xFFFF);
4861 int tempESP;
4862 if (cpu.ss.getDefaultSizeFlag())
4863 tempESP = cpu.esp;
4864 else
4865 tempESP = cpu.esp & 0xffff;
4867 cpu.ss.setWord((tempESP - 2), (short) (0xFFFF & cpu.cs.getSelector()));
4868 cpu.ss.setWord((tempESP - 4), (short) (0xFFFF & cpu.eip));
4869 cpu.esp = (cpu.esp & ~0xFFFF) | ((cpu.esp-4) & 0xFFFF);
4871 cpu.cs = newSegment;
4872 cpu.cs.setRPL(cpu.getCPL());
4873 cpu.eip = targetEIP & 0xFFFF;
4874 return;
4876 case 0x1c: // Conforming Code Segment (Not Readable & Not Accessed)
4877 case 0x1d: // Conforming Code Segment (Not Readable & Accessed)
4878 case 0x1e: // Conforming Code Segment (Readable & Not Accessed)
4879 case 0x1f: // Conforming Code Segment (Readable & Accessed)
4880 System.err.println("Critical error: Conforming code segment not implemented");
4881 throw new IllegalStateException("O16 A16 CALL FAR to conforming code segment not implemented");
4886 private final void call_far_o32_a32(int targetEIP, int targetSelector)
4888 Segment newSegment = cpu.getSegment(targetSelector);
4889 if (newSegment == SegmentFactory.NULL_SEGMENT)
4890 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
4892 switch (newSegment.getType()) { // segment type
4893 default: // not a valid segment descriptor for a jump
4894 System.err.println("Emulated: Invalid segment type " + newSegment.getType() + ".");
4895 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4896 case 0x01: // TSS 16-bit (Not Busy)
4897 case 0x03: // TSS 16-bit (Busy)
4898 System.err.println("Critical error: 16-bit TSS not implemented");
4899 throw new IllegalStateException("O32 A32 CALL FAR to 16-bit TSS not implemented");
4900 case 0x04: // Call Gate 16-bit
4902 if ((newSegment.getRPL() > cpu.getCPL()) || (newSegment.getDPL() < cpu.getCPL()))
4903 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4904 if (!newSegment.isPresent())
4905 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSelector, true);
4907 ProtectedModeSegment.GateSegment gate = (ProtectedModeSegment.GateSegment) newSegment;
4909 int targetSegmentSelector = gate.getTargetSegment();
4911 Segment targetSegment;
4912 try {
4913 targetSegment = cpu.getSegment(targetSegmentSelector);
4914 } catch (ProcessorException e) {
4915 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
4917 if (targetSegment == SegmentFactory.NULL_SEGMENT)
4918 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
4920 if (targetSegment.getDPL() > cpu.getCPL())
4921 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4923 switch (targetSegment.getType()) {
4924 default:
4925 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
4927 case 0x18: //Code, Execute-Only
4928 case 0x19: //Code, Execute-Only, Accessed
4929 case 0x1a: //Code, Execute/Read
4930 case 0x1b: //Code, Execute/Read, Accessed
4932 if (!targetSegment.isPresent())
4933 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSegmentSelector, true);
4935 if (targetSegment.getDPL() < cpu.getCPL()) {
4936 System.err.println("Critical error: 16-bit call gate: jump to more privileged " +
4937 "segment not implemented");
4938 throw new IllegalStateException("O32 A32 CALL FAR to 16-bit call gate: Jump to more priviledged segment not implemented");
4939 //MORE-PRIVILEGE
4940 } else if (targetSegment.getDPL() == cpu.getCPL()) {
4941 System.err.println("Critical error: 16-bit call gate: jump to same privilege " +
4942 "segment not implemented");
4943 throw new IllegalStateException("O32 A32 CALL FAR to 16-bit call gate: Jump to same-priviledge segment not implemented");
4944 //SAME-PRIVILEGE
4945 } else
4946 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
4948 // break;
4949 case 0x1c: //Code: Execute-Only, Conforming
4950 case 0x1d: //Code: Execute-Only, Conforming, Accessed
4951 case 0x1e: //Code: Execute/Read, Conforming
4952 case 0x1f: //Code: Execute/Read, Conforming, Accessed
4954 if (!targetSegment.isPresent())
4955 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSegmentSelector, true);
4957 System.err.println("Critical error: 16-bit call gate: jump to same privilege " +
4958 "conforming segment not implemented");
4959 throw new IllegalStateException("O32 A32 CALL FAR to 16-bit call gate: Jump to same priviledge conforming segment not implemented");
4960 //SAME-PRIVILEGE
4962 // break;
4965 // break;
4966 case 0x05: // Task Gate
4967 System.err.println("Critical error: Task gate not implemented");
4968 throw new IllegalStateException("O32 A32 CALL FAR to task gate not implemented");
4969 case 0x09: // TSS (Not Busy)
4970 case 0x0b: // TSS (Busy)
4971 System.err.println("Critical error: TSS not implemented");
4972 throw new IllegalStateException("O32 A32 CALL FAR to TSS not implemented");
4973 case 0x0c: // Call Gate
4974 System.err.println("Critical error: Call gate not implemented");
4975 throw new IllegalStateException("O32 A32 CALL FAR to call gate not implemented");
4976 case 0x18: // Non-conforming Code Segment
4977 case 0x19: // Non-conforming Code Segment
4978 case 0x1a: // Non-conforming Code Segment
4979 case 0x1b: // Non-conforming Code Segment
4981 if ((newSegment.getRPL() > cpu.getCPL()) || (newSegment.getDPL() != cpu.getCPL()))
4982 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
4983 if (!newSegment.isPresent())
4984 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSelector, true);
4986 if ((cpu.esp < 8) && (cpu.esp > 0))
4987 throw ProcessorException.STACK_SEGMENT_0;
4989 newSegment.checkAddress(targetEIP);
4991 cpu.ss.setDoubleWord(cpu.esp - 4, cpu.cs.getSelector());
4992 cpu.ss.setDoubleWord(cpu.esp - 8, cpu.eip);
4993 cpu.esp -= 8;
4995 cpu.cs = newSegment;
4996 cpu.cs.setRPL(cpu.getCPL());
4997 cpu.eip = targetEIP;
4998 return;
5000 case 0x1c: // Conforming Code Segment (Not Readable & Not Accessed)
5001 case 0x1d: // Conforming Code Segment (Not Readable & Accessed)
5002 case 0x1e: // Conforming Code Segment (Readable & Not Accessed)
5003 case 0x1f: // Conforming Code Segment (Readable & Accessed)
5004 System.err.println("Critical error: Conforming code segment not implemented");
5005 throw new IllegalStateException("O32 A32 CALL FAR to conforming code segment not implemented");
5009 private final void call_far_o32_a16(int targetEIP, int targetSelector)
5011 Segment newSegment = cpu.getSegment(targetSelector);
5012 if (newSegment == SegmentFactory.NULL_SEGMENT)
5013 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
5015 switch (newSegment.getType())
5016 { // segment type
5017 default: // not a valid segment descriptor for a jump
5018 System.err.println("Emulated: Invalid segment type " + newSegment.getType() + ".");
5019 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
5020 case 0x01: // TSS 16-bit (Not Busy)
5021 case 0x03: // TSS 16-bit (Busy)
5022 System.err.println("Critical error: 16-bit TSS not implemented");
5023 throw new IllegalStateException("O32 A16 CALL FAR to 16-bit TSS not implemented");
5024 case 0x04: // Call Gate 16-bit
5026 if ((newSegment.getRPL() > cpu.getCPL()) || (newSegment.getDPL() < cpu.getCPL()))
5027 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
5028 if (!newSegment.isPresent())
5029 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSelector, true);
5031 ProtectedModeSegment.GateSegment gate = (ProtectedModeSegment.GateSegment) newSegment;
5033 int targetSegmentSelector = gate.getTargetSegment();
5035 Segment targetSegment;
5036 try {
5037 targetSegment = cpu.getSegment(targetSegmentSelector);
5038 } catch (ProcessorException e) {
5039 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
5041 if (targetSegment == SegmentFactory.NULL_SEGMENT)
5042 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
5044 if (targetSegment.getDPL() > cpu.getCPL())
5045 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
5047 switch (targetSegment.getType()) {
5048 default:
5049 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
5051 case 0x18: //Code, Execute-Only
5052 case 0x19: //Code, Execute-Only, Accessed
5053 case 0x1a: //Code, Execute/Read
5054 case 0x1b: //Code, Execute/Read, Accessed
5056 if (!targetSegment.isPresent())
5057 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSegmentSelector, true);
5059 if (targetSegment.getDPL() < cpu.getCPL()) {
5060 System.err.println("Critical error: 16-bit call gate: jump to more privileged " +
5061 "segment not implemented");
5062 throw new IllegalStateException("O32 A16 CALL FAR to 16-bit call gate: Jump to more priviledged segmment not supported");
5063 //MORE-PRIVILEGE
5064 } else if (targetSegment.getDPL() == cpu.getCPL()) {
5065 System.err.println("Critical error: 16-bit call gate: jump to same privilege " +
5066 "segment not implemented");
5067 throw new IllegalStateException("O32 A16 CALL FAR to 16-bit call gate: Jump to same priviledge segmment not supported");
5068 //SAME-PRIVILEGE
5069 } else
5070 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSegmentSelector, true);
5072 // break;
5073 case 0x1c: //Code: Execute-Only, Conforming
5074 case 0x1d: //Code: Execute-Only, Conforming, Accessed
5075 case 0x1e: //Code: Execute/Read, Conforming
5076 case 0x1f: //Code: Execute/Read, Conforming, Accessed
5078 if (!targetSegment.isPresent())
5079 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSegmentSelector, true);
5081 System.err.println("Critical error: 16-bit call gate: jump to same privilege " +
5082 "conforming segment not implemented");
5083 throw new IllegalStateException("O32 A16 CALL FAR to 16-bit call gate: Jump to same priviledge conforming segment not implemented");
5084 //SAME-PRIVILEGE
5086 // break;
5089 // break;
5090 case 0x05: // Task Gate
5091 System.err.println("Critical error: Task gate not implemented");
5092 throw new IllegalStateException("O32 A16 CALL FAR to task gate not implemented");
5093 case 0x09: // TSS (Not Busy)
5094 case 0x0b: // TSS (Busy)
5095 System.err.println("Critical error: TSS not implemented");
5096 throw new IllegalStateException("O32 A16 CALL FAR to TSS not implemented");
5097 case 0x0c: // Call Gate
5098 System.err.println("Critical error: Call gate not implemented");
5099 throw new IllegalStateException("O32 A16 CALL FAR to call gate not implemented");
5100 case 0x18: // Non-conforming Code Segment
5101 case 0x19: // Non-conforming Code Segment
5102 case 0x1a: // Non-conforming Code Segment
5103 case 0x1b: // Non-conforming Code Segment
5105 if ((newSegment.getRPL() > cpu.getCPL()) || (newSegment.getDPL() != cpu.getCPL()))
5106 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, targetSelector, true);
5107 if (!newSegment.isPresent())
5108 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, targetSelector, true);
5110 if ((cpu.esp & 0xffff) < 8)
5111 throw ProcessorException.STACK_SEGMENT_0;
5113 newSegment.checkAddress(targetEIP);
5115 cpu.ss.setDoubleWord((cpu.esp - 4) & 0xffff, cpu.cs.getSelector());
5116 cpu.ss.setDoubleWord((cpu.esp - 8) & 0xffff, cpu.eip);
5117 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp - 8) & 0xffff);
5119 cpu.cs = newSegment;
5120 cpu.cs.setRPL(cpu.getCPL());
5121 cpu.eip = targetEIP;
5122 return;
5124 case 0x1c: // Conforming Code Segment (Not Readable & Not Accessed)
5125 case 0x1d: // Conforming Code Segment (Not Readable & Accessed)
5126 case 0x1e: // Conforming Code Segment (Readable & Not Accessed)
5127 case 0x1f: // Conforming Code Segment (Readable & Accessed)
5128 System.err.println("Critical error: Conforming code segment not implemented");
5129 throw new IllegalStateException("O32 A16 CALL FAR to conforming segment not implemented");
5133 private final void ret_o16_a32()
5135 // TODO: supposed to throw SS exception
5136 // "if top 6 bytes of stack not within stack limits"
5137 cpu.eip = cpu.ss.getWord(cpu.esp) & 0xffff;
5138 cpu.esp = cpu.esp + 2;
5141 private final void ret_o16_a16()
5143 // TODO: supposed to throw SS exception
5144 // "if top 6 bytes of stack not within stack limits"
5145 cpu.eip = cpu.ss.getWord(cpu.esp & 0xffff) & 0xffff;
5146 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp + 2) & 0xffff);
5149 private final void ret_o32_a32()
5151 // TODO: supposed to throw SS exception
5152 // "if top 6 bytes of stack not within stack limits"
5153 cpu.eip = cpu.ss.getDoubleWord(cpu.esp);
5154 cpu.esp = cpu.esp + 4;
5157 private final void ret_o32_a16()
5159 // TODO: supposed to throw SS exception
5160 // "if top 6 bytes of stack not within stack limits"
5161 cpu.eip = cpu.ss.getDoubleWord(0xffff & cpu.esp);
5162 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp + 4) & 0xffff);
5165 private final void ret_iw_o16_a32(short offset)
5167 ret_o16_a32();
5168 cpu.esp += offset;
5171 private final void ret_iw_o16_a16(short offset)
5173 ret_o16_a16();
5174 cpu.esp = (cpu.esp & ~0xffff) | (((cpu.esp & 0xFFFF) + offset) & 0xffff);
5178 private final void ret_iw_o32_a32(short offset)
5180 ret_o32_a32();
5181 cpu.esp += offset;
5184 private final void ret_iw_o32_a16(short offset)
5186 ret_o32_a16();
5187 cpu.esp = (cpu.esp & ~0xffff) | (((cpu.esp & 0xFFFF) + offset) & 0xffff);
5190 private final void ret_far_o16_a16(int stackdelta)
5192 try {
5193 cpu.ss.checkAddress((cpu.esp + 3) & 0xFFFF);
5194 } catch (ProcessorException e) {
5195 throw ProcessorException.STACK_SEGMENT_0;
5198 int tempEIP = 0xFFFF & cpu.ss.getWord(cpu.esp & 0xFFFF);
5199 int tempCS = 0xFFFF & cpu.ss.getWord((cpu.esp + 2) & 0xFFFF);
5201 if ((tempCS & 0xfffc) == 0)
5202 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);
5204 Segment returnSegment = cpu.getSegment(tempCS);
5205 if (returnSegment == SegmentFactory.NULL_SEGMENT)
5206 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
5208 if (returnSegment.getRPL() < cpu.getCPL())
5210 System.err.println("Emulated: RPL too small in far ret: RPL=" + returnSegment.getRPL() +
5211 ", CPL=" + cpu.getCPL() + ", new CS=" + Integer.toHexString(tempCS));
5212 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5215 switch (returnSegment.getType()) {
5216 default:
5217 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5219 case 0x18: //Code, Execute-Only
5220 case 0x19: //Code, Execute-Only, Accessed
5221 case 0x1a: //Code, Execute/Read
5222 case 0x1b: //Code, Execute/Read, Accessed
5224 if (!(returnSegment.isPresent()))
5225 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, tempCS, true);
5227 if (returnSegment.getRPL() > cpu.getCPL()) {
5228 //OUTER PRIVILEGE-LEVEL
5229 try {
5230 cpu.ss.checkAddress((cpu.esp + 7 + stackdelta) & 0xFFFF);
5231 } catch (ProcessorException e) {
5232 throw ProcessorException.STACK_SEGMENT_0;
5235 int returnESP = 0xffff & cpu.ss.getWord((cpu.esp + 4 + stackdelta) & 0xFFFF);
5236 int newSS = 0xffff & cpu.ss.getWord((cpu.esp + 6 + stackdelta) & 0xFFFF);
5238 if ((newSS & 0xfffc) == 0)
5239 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);
5241 Segment returnStackSegment = cpu.getSegment(newSS);
5243 if ((returnStackSegment.getRPL() != returnSegment.getRPL()) || ((returnStackSegment.getType() & 0x12) != 0x12) ||
5244 (returnStackSegment.getDPL() != returnSegment.getRPL()))
5245 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newSS & 0xfffc, true);
5247 if (!returnStackSegment.isPresent())
5248 throw new ProcessorException(ProcessorException.Type.STACK_SEGMENT, newSS & 0xfffc, true);
5250 returnSegment.checkAddress(tempEIP);
5252 cpu.eip = tempEIP;
5253 cpu.cs = returnSegment;
5255 cpu.ss = returnStackSegment;
5256 cpu.esp = returnESP + stackdelta;
5258 cpu.setCPL(cpu.cs.getRPL());
5260 try {
5261 if ((((cpu.es.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.es.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.es.getDPL()))
5262 // can't use lower dpl data segment at higher cpl
5263 System.err.println("Emulated: Setting ES to NULL in ret far");
5264 cpu.es = SegmentFactory.NULL_SEGMENT;
5265 } catch (ProcessorException e) {
5266 } catch (Exception e) {
5269 try {
5270 if ((((cpu.ds.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.ds.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.ds.getDPL()))
5271 // can't use lower dpl data segment at higher cpl
5272 System.err.println("Emulated: Setting DS to NULL in ret far");
5273 cpu.ds = SegmentFactory.NULL_SEGMENT;
5274 } catch (ProcessorException e) {
5275 } catch (Exception e) {
5278 try {
5279 if ((((cpu.fs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.fs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.fs.getDPL()))
5280 // can't use lower dpl data segment at higher cpl
5281 System.err.println("Emulated: Setting FS to NULL in ret far");
5282 cpu.fs = SegmentFactory.NULL_SEGMENT;
5283 } catch (ProcessorException e) {
5284 } catch (Exception e) {
5287 try {
5288 if ((((cpu.gs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.gs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.gs.getDPL()))
5289 // can't use lower dpl data segment at higher cpl
5290 System.err.println("Emulated: Setting GS to NULL in ret far");
5291 cpu.gs = SegmentFactory.NULL_SEGMENT;
5292 } catch (ProcessorException e) {
5293 } catch (Exception e) {
5295 } else {
5296 //SAME PRIVILEGE-LEVEL
5297 returnSegment.checkAddress(tempEIP);
5299 cpu.esp = (cpu.esp & ~0xFFFF)| ((cpu.esp + 4 + stackdelta) &0xFFFF);
5300 cpu.eip = tempEIP;
5301 cpu.cs = returnSegment;
5304 break;
5305 case 0x1c: //Code: Execute-Only, Conforming
5306 case 0x1d: //Code: Execute-Only, Conforming, Accessed
5307 case 0x1e: //Code: Execute/Read, Conforming
5308 case 0x1f: //Code: Execute/Read, Conforming, Accessed
5310 if (returnSegment.getDPL() > returnSegment.getRPL())
5311 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5313 if (!(returnSegment.isPresent()))
5314 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, tempCS, true);
5316 if (returnSegment.getRPL() > cpu.getCPL()) {
5317 //OUTER PRIVILEGE-LEVEL
5318 //cpu.esp += 8;
5319 System.err.println("Critical error: Conforming outer privilege level not implemented");
5320 throw new IllegalStateException("O16 A16 RETF to conforiming outer priviledge level not implemented");
5321 } else {
5322 //SAME PRIVILEGE-LEVEL
5323 returnSegment.checkAddress(tempEIP);
5325 cpu.esp = (cpu.esp & ~0xFFFF)| ((cpu.esp + 4 + stackdelta) &0xFFFF);
5326 cpu.eip = tempEIP;
5327 cpu.cs = returnSegment;
5333 private final void ret_far_o16_a32(int stackdelta)
5335 try {
5336 cpu.ss.checkAddress(cpu.esp + 3);
5337 } catch (ProcessorException e) {
5338 throw ProcessorException.STACK_SEGMENT_0;
5341 int tempEIP = 0xFFFF & cpu.ss.getWord(cpu.esp);
5342 int tempCS = 0xFFFF & cpu.ss.getWord(cpu.esp + 2);
5344 Segment returnSegment = cpu.getSegment(tempCS);
5346 if (returnSegment == SegmentFactory.NULL_SEGMENT)
5347 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
5349 switch (returnSegment.getType()) {
5350 default:
5351 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5353 case 0x18: //Code, Execute-Only
5354 case 0x19: //Code, Execute-Only, Accessed
5355 case 0x1a: //Code, Execute/Read
5356 case 0x1b: //Code, Execute/Read, Accessed
5358 if (returnSegment.getRPL() < cpu.getCPL())
5359 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5361 if (!(returnSegment.isPresent()))
5362 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, tempCS, true);
5364 if (returnSegment.getRPL() > cpu.getCPL()) {
5365 //OUTER PRIVILEGE-LEVEL
5366 //cpu.esp += 8;
5367 System.err.println("Critical error: Non-conforming outer privilege level not implemented");
5368 throw new IllegalStateException("O16 A32 RETF to non-conforming outer priviledge level not implemented");
5369 } else {
5370 //SAME PRIVILEGE-LEVEL
5371 returnSegment.checkAddress(tempEIP);
5373 cpu.esp = cpu.esp + 4 + stackdelta;
5374 cpu.eip = tempEIP;
5375 cpu.cs = returnSegment;
5378 break;
5379 case 0x1c: //Code: Execute-Only, Conforming
5380 case 0x1d: //Code: Execute-Only, Conforming, Accessed
5381 case 0x1e: //Code: Execute/Read, Conforming
5382 case 0x1f: //Code: Execute/Read, Conforming, Accessed
5384 if (returnSegment.getRPL() < cpu.getCPL())
5385 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5387 if (returnSegment.getDPL() > returnSegment.getRPL())
5388 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5390 if (!(returnSegment.isPresent()))
5391 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, tempCS, true);
5393 if (returnSegment.getRPL() > cpu.getCPL()) {
5394 //OUTER PRIVILEGE-LEVEL
5395 //cpu.esp += 8;
5396 System.err.println("Critical error: Conforming outer privilege level not implemented");
5397 throw new IllegalStateException("O16 A32 RETF to conforming outer priviledge level not implemented");
5398 } else {
5399 //SAME PRIVILEGE-LEVEL
5400 returnSegment.checkAddress(tempEIP & 0xFFFF);
5402 cpu.esp = cpu.esp + 4 + stackdelta;
5403 cpu.eip = (0xFFFF & tempEIP);
5404 cpu.cs = returnSegment;
5410 private final void ret_far_o32_a16(int stackdelta)
5412 try {
5413 cpu.ss.checkAddress((cpu.esp + 7) & 0xFFFF);
5414 } catch (ProcessorException e) {
5415 throw ProcessorException.STACK_SEGMENT_0;
5418 int tempEIP = cpu.ss.getDoubleWord(cpu.esp & 0xFFFF);
5419 int tempCS = 0xffff & cpu.ss.getDoubleWord((cpu.esp + 4) & 0xFFFF);
5421 Segment returnSegment = cpu.getSegment(tempCS);
5423 if (returnSegment == SegmentFactory.NULL_SEGMENT)
5424 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
5426 switch (returnSegment.getType()) {
5427 default:
5428 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5430 case 0x18: //Code, Execute-Only
5431 case 0x19: //Code, Execute-Only, Accessed
5432 case 0x1a: //Code, Execute/Read
5433 case 0x1b: //Code, Execute/Read, Accessed
5435 if (returnSegment.getRPL() < cpu.getCPL())
5436 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5438 if (!(returnSegment.isPresent()))
5439 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, tempCS, true);
5441 if (returnSegment.getRPL() > cpu.getCPL()) {
5442 //OUTER PRIVILEGE-LEVEL
5443 //cpu.esp += 8;
5444 System.err.println("Critical error: Non-conforming outer privilege level not implemented");
5445 throw new IllegalStateException("O32 A16 RETF to non-conforming outer privilege level not implemented");
5446 } else {
5447 //SAME PRIVILEGE-LEVEL
5448 returnSegment.checkAddress(tempEIP);
5450 cpu.esp = (cpu.esp & ~0xFFFF)| ((cpu.esp + 8 + stackdelta) &0xFFFF);
5451 cpu.eip = tempEIP;
5452 cpu.cs = returnSegment;
5455 break;
5456 case 0x1c: //Code: Execute-Only, Conforming
5457 case 0x1d: //Code: Execute-Only, Conforming, Accessed
5458 case 0x1e: //Code: Execute/Read, Conforming
5459 case 0x1f: //Code: Execute/Read, Conforming, Accessed
5461 if (returnSegment.getRPL() < cpu.getCPL())
5462 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5464 if (returnSegment.getDPL() > returnSegment.getRPL())
5465 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5467 if (!(returnSegment.isPresent()))
5468 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, tempCS, true);
5470 if (returnSegment.getRPL() > cpu.getCPL()) {
5471 //OUTER PRIVILEGE-LEVEL
5472 //cpu.esp += 8;
5473 System.err.println("Critical error: Conforming outer privilege level not implemented");
5474 throw new IllegalStateException("O32 A16 RETF to conforming outer privilege level not implemented");
5475 } else {
5476 //SAME PRIVILEGE-LEVEL
5477 returnSegment.checkAddress(tempEIP);
5479 cpu.esp = (cpu.esp & ~0xFFFF)| ((cpu.esp + 8 + stackdelta) &0xFFFF);
5480 cpu.eip = tempEIP;
5481 cpu.cs = returnSegment;
5487 private final void ret_far_o32_a32(int stackdelta)
5489 try {
5490 cpu.ss.checkAddress(cpu.esp + 7);
5491 } catch (ProcessorException e) {
5492 throw ProcessorException.STACK_SEGMENT_0;
5495 int tempEIP = cpu.ss.getDoubleWord(cpu.esp);
5496 int tempCS = 0xffff & cpu.ss.getDoubleWord(cpu.esp + 4);
5498 Segment returnSegment = cpu.getSegment(tempCS);
5500 if (returnSegment == SegmentFactory.NULL_SEGMENT)
5501 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
5503 switch (returnSegment.getType()) {
5504 default:
5505 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5507 case 0x18: //Code, Execute-Only
5508 case 0x19: //Code, Execute-Only, Accessed
5509 case 0x1a: //Code, Execute/Read
5510 case 0x1b: //Code, Execute/Read, Accessed
5512 if (returnSegment.getRPL() < cpu.getCPL())
5513 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5515 if (!(returnSegment.isPresent()))
5516 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, tempCS, true);
5518 if (returnSegment.getRPL() > cpu.getCPL()) {
5519 //OUTER PRIVILEGE-LEVEL
5520 try {
5521 cpu.ss.checkAddress(cpu.esp + 15);
5522 } catch (ProcessorException e) {
5523 throw ProcessorException.STACK_SEGMENT_0;
5526 int returnESP = cpu.ss.getDoubleWord(cpu.esp + 8 + stackdelta);
5527 int tempSS = 0xffff & cpu.ss.getDoubleWord(cpu.esp + 12 + stackdelta);
5529 Segment returnStackSegment = cpu.getSegment(tempSS);
5531 if ((returnStackSegment.getRPL() != returnSegment.getRPL()) || ((returnStackSegment.getType() & 0x12) != 0x12) ||
5532 (returnStackSegment.getDPL() != returnSegment.getRPL()))
5533 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempSS, true);
5535 if (!returnStackSegment.isPresent())
5536 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempSS, true);
5538 returnSegment.checkAddress(tempEIP);
5540 //cpu.esp += 20; //includes the 12 from earlier
5541 cpu.eip = tempEIP;
5542 cpu.cs = returnSegment;
5544 cpu.ss = returnStackSegment;
5545 cpu.esp = returnESP;
5547 cpu.setCPL(cpu.cs.getRPL());
5548 } else {
5549 //SAME PRIVILEGE-LEVEL
5550 returnSegment.checkAddress(tempEIP);
5552 cpu.esp += 8 + stackdelta;
5553 cpu.eip = tempEIP;
5554 cpu.cs = returnSegment;
5557 break;
5558 case 0x1c: //Code: Execute-Only, Conforming
5559 case 0x1d: //Code: Execute-Only, Conforming, Accessed
5560 case 0x1e: //Code: Execute/Read, Conforming
5561 case 0x1f: //Code: Execute/Read, Conforming, Accessed
5563 if (returnSegment.getRPL() < cpu.getCPL())
5564 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5566 if (returnSegment.getDPL() > returnSegment.getRPL())
5567 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempCS, true);
5569 if (!(returnSegment.isPresent()))
5570 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, tempCS, true);
5572 if (returnSegment.getRPL() > cpu.getCPL()) {
5573 //OUTER PRIVILEGE-LEVEL
5574 //cpu.esp += 8;
5575 System.err.println("Critical error: Conforming outer privilege level not implemented");
5576 throw new IllegalStateException("O32 A32 RETF to conforming outer priviledge level not implemented");
5577 } else {
5578 //SAME PRIVILEGE-LEVEL
5579 returnSegment.checkAddress(tempEIP);
5581 cpu.esp += 8;
5582 cpu.eip = tempEIP;
5583 cpu.cs = returnSegment;
5589 private final int iretToVirtual8086Mode16BitAddressing(int newCS, int newEIP, int newEFlags)
5591 try {
5592 cpu.ss.checkAddress((cpu.esp + 23) & 0xffff);
5593 } catch (ProcessorException e) {
5594 throw ProcessorException.STACK_SEGMENT_0;
5596 cpu.cs = SegmentFactory.createVirtual8086ModeSegment(cpu.linearMemory, newCS, true);
5597 cpu.eip = newEIP & 0xffff;
5598 int newESP = cpu.ss.getDoubleWord(cpu.esp & 0xffff);
5599 int newSS = 0xffff & cpu.ss.getDoubleWord((cpu.esp + 4) & 0xffff);
5600 cpu.es = SegmentFactory.createVirtual8086ModeSegment(cpu.linearMemory, 0xffff & cpu.ss.getDoubleWord((cpu.esp + 8) & 0xffff), false);
5601 cpu.ds = SegmentFactory.createVirtual8086ModeSegment(cpu.linearMemory, 0xffff & cpu.ss.getDoubleWord((cpu.esp + 12) & 0xffff), false);
5602 cpu.fs = SegmentFactory.createVirtual8086ModeSegment(cpu.linearMemory, 0xffff & cpu.ss.getDoubleWord((cpu.esp + 16) & 0xffff), false);
5603 cpu.gs = SegmentFactory.createVirtual8086ModeSegment(cpu.linearMemory, 0xffff & cpu.ss.getDoubleWord((cpu.esp + 20) & 0xffff), false);
5604 cpu.ss = SegmentFactory.createVirtual8086ModeSegment(cpu.linearMemory, newSS, false);
5605 cpu.esp = newESP;
5606 cpu.setCPL(3);
5608 return newEFlags;
5611 private final int iret32ProtectedMode16BitAddressing(int newCS, int newEIP, int newEFlags)
5613 Segment returnSegment = cpu.getSegment(newCS);
5615 if (returnSegment == SegmentFactory.NULL_SEGMENT)
5616 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
5618 switch (returnSegment.getType()) {
5619 default:
5620 System.err.println("Emulated: Invalid segment type " + returnSegment.getType() + ".");
5621 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
5623 case 0x18: //Code, Execute-Only
5624 case 0x19: //Code, Execute-Only, Accessed
5625 case 0x1a: //Code, Execute/Read
5626 case 0x1b: //Code, Execute/Read, Accessed
5628 if (returnSegment.getRPL() < cpu.getCPL())
5629 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
5631 if (!(returnSegment.isPresent()))
5632 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, newCS, true);
5634 if (returnSegment.getRPL() > cpu.getCPL()) {
5635 //OUTER PRIVILEGE-LEVEL
5636 try {
5637 cpu.ss.checkAddress((cpu.esp + 7) & 0xFFFF);
5638 } catch (ProcessorException e) {
5639 throw ProcessorException.STACK_SEGMENT_0;
5642 int returnESP = cpu.ss.getDoubleWord((cpu.esp)&0xFFFF);
5643 int newSS = 0xffff & cpu.ss.getDoubleWord((cpu.esp + 4)&0xFFFF);
5645 Segment returnStackSegment = cpu.getSegment(newSS);
5647 if ((returnStackSegment.getRPL() != returnSegment.getRPL()) || ((returnStackSegment.getType() & 0x12) != 0x12) ||
5648 (returnStackSegment.getDPL() != returnSegment.getRPL()))
5649 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newSS, true);
5651 if (!returnStackSegment.isPresent())
5652 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newSS, true);
5654 returnSegment.checkAddress(newEIP);
5656 //cpu.esp += 20; //includes the 12 from earlier
5657 cpu.eip = newEIP;
5658 cpu.cs = returnSegment;
5660 cpu.ss = returnStackSegment;
5661 cpu.esp = returnESP;
5663 int eflags = cpu.getEFlags();
5664 eflags &= ~0x254dd5;
5665 eflags |= (0x254dd5 & newEFlags);
5666 //overwrite: all; preserve: if, iopl, vm, vif, vip
5668 if (cpu.getCPL() <= cpu.eflagsIOPrivilegeLevel) {
5669 eflags &= ~0x200;
5670 eflags |= (0x200 & newEFlags);
5671 //overwrite: all; preserve: iopl, vm, vif, vip
5673 if (cpu.getCPL() == 0) {
5674 eflags &= ~0x1a3000;
5675 eflags |= (0x1a3000 & newEFlags);
5676 //overwrite: all;
5678 // cpu.setEFlags(eflags);
5680 cpu.setCPL(cpu.cs.getRPL());
5682 try {
5683 if ((((cpu.es.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.es.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.es.getDPL()))
5684 cpu.es = SegmentFactory.NULL_SEGMENT;
5685 } catch (ProcessorException e) {
5686 } catch (Exception e) {
5689 try {
5690 if ((((cpu.ds.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.ds.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.ds.getDPL()))
5691 cpu.ds = SegmentFactory.NULL_SEGMENT;
5692 } catch (ProcessorException e) {
5693 } catch (Exception e) {
5696 try {
5697 if ((((cpu.fs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.fs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.fs.getDPL()))
5698 cpu.fs = SegmentFactory.NULL_SEGMENT;
5699 } catch (ProcessorException e) {
5700 } catch (Exception e) {
5703 try {
5704 if ((((cpu.gs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.gs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.gs.getDPL()))
5705 cpu.gs = SegmentFactory.NULL_SEGMENT;
5706 } catch (ProcessorException e) {
5707 } catch (Exception e) {
5710 return eflags;
5711 } else {
5712 //SAME PRIVILEGE-LEVEL
5713 returnSegment.checkAddress(newEIP);
5715 // cpu.esp = (cpu.esp & ~0xFFFF) | ((cpu.esp+12)&0xFFFF);
5716 cpu.cs = returnSegment;
5717 cpu.eip = newEIP;
5719 //Set EFlags
5720 int eflags = cpu.getEFlags();
5722 eflags &= ~0x254dd5;
5723 eflags |= (0x254dd5 & newEFlags);
5725 if (cpu.getCPL() <= cpu.eflagsIOPrivilegeLevel) {
5726 eflags &= ~0x200;
5727 eflags |= (0x200 & newEFlags);
5730 if (cpu.getCPL() == 0) {
5731 eflags &= ~0x1a3000;
5732 eflags |= (0x1a3000 & newEFlags);
5735 // cpu.setEFlags(eflags);
5736 return eflags;
5739 case 0x1c: //Code: Execute-Only, Conforming
5740 case 0x1d: //Code: Execute-Only, Conforming, Accessed
5741 case 0x1e: //Code: Execute/Read, Conforming
5742 case 0x1f: //Code: Execute/Read, Conforming, Accessed
5744 if (returnSegment.getRPL() < cpu.getCPL())
5745 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
5747 if (returnSegment.getDPL() > returnSegment.getRPL())
5748 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
5750 if (!(returnSegment.isPresent()))
5751 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, newCS, true);
5753 if (returnSegment.getRPL() > cpu.getCPL()) {
5754 //OUTER PRIVILEGE-LEVEL
5755 System.err.println("Critical error: Conforming outer privilege level not implemented");
5756 throw new IllegalStateException("iret32ProtectedMode16BitAddressing to conforming outer priviledge level not implemented");
5757 } else {
5758 //SAME PRIVILEGE-LEVEL
5759 System.err.println("Critical error: Conforming same privilege level not implemented");
5760 throw new IllegalStateException("iret32ProtectedMode16BitAddressing to conforming same priviledge level not implemented");
5766 private final int iret_o32_a16()
5768 if (cpu.eflagsNestedTask)
5769 return iretFromTask();
5770 else {
5771 try {
5772 cpu.ss.checkAddress((cpu.esp + 11) & 0xffff);
5773 } catch (ProcessorException e) {
5774 throw ProcessorException.STACK_SEGMENT_0;
5776 int tempEIP = cpu.ss.getDoubleWord(cpu.esp & 0xFFFF);
5777 int tempCS = 0xffff & cpu.ss.getDoubleWord((cpu.esp + 4) & 0xFFFF);
5778 int tempEFlags = cpu.ss.getDoubleWord((cpu.esp + 8) & 0xFFFF);
5779 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp + 12) & 0xffff);
5781 if (((tempEFlags & (1 << 17)) != 0) && (cpu.getCPL() == 0)) {
5782 return iretToVirtual8086Mode16BitAddressing(tempCS, tempEIP, tempEFlags);
5783 } else {
5784 return iret32ProtectedMode16BitAddressing(tempCS, tempEIP, tempEFlags);
5789 private final int iretFromTask()
5791 System.err.println("Critical error: iretFromTask().");
5792 throw new IllegalStateException("IRET with NT set not implemented");
5795 private final int iretToVirtual8086Mode32BitAddressing(int newCS, int newEIP, int newEFlags)
5797 try {
5798 cpu.ss.checkAddress(cpu.esp + 23);
5799 } catch (ProcessorException e) {
5800 throw ProcessorException.STACK_SEGMENT_0;
5802 if (newEIP > 0xfffff)
5803 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION,0,true);//ProcessorException.GENERAL_PROTECTION_0;
5805 cpu.cs = SegmentFactory.createVirtual8086ModeSegment(cpu.linearMemory, newCS, true);
5806 cpu.eip = newEIP & 0xffff;
5807 int newESP = cpu.ss.getDoubleWord(cpu.esp);
5808 int newSS = 0xffff & cpu.ss.getDoubleWord(cpu.esp + 4);
5809 cpu.es = SegmentFactory.createVirtual8086ModeSegment(cpu.linearMemory, 0xffff & cpu.ss.getDoubleWord(cpu.esp + 8), false);
5810 cpu.ds = SegmentFactory.createVirtual8086ModeSegment(cpu.linearMemory, 0xffff & cpu.ss.getDoubleWord(cpu.esp + 12), false);
5811 cpu.fs = SegmentFactory.createVirtual8086ModeSegment(cpu.linearMemory, 0xffff & cpu.ss.getDoubleWord(cpu.esp + 16), false);
5812 cpu.gs = SegmentFactory.createVirtual8086ModeSegment(cpu.linearMemory, 0xffff & cpu.ss.getDoubleWord(cpu.esp + 20), false);
5813 cpu.ss = SegmentFactory.createVirtual8086ModeSegment(cpu.linearMemory, newSS, false);
5814 cpu.esp = newESP;
5815 cpu.setCPL(3);
5817 return newEFlags;
5820 private final int iret32ProtectedMode32BitAddressing(int newCS, int newEIP, int newEFlags)
5822 Segment returnSegment = cpu.getSegment(newCS);
5824 if (returnSegment == SegmentFactory.NULL_SEGMENT)
5825 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
5827 switch (returnSegment.getType()) {
5828 default:
5829 System.err.println("Emulated: Invalid segment type " + returnSegment.getType() + ".");
5830 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
5832 case 0x18: //Code, Execute-Only
5833 case 0x19: //Code, Execute-Only, Accessed
5834 case 0x1a: //Code, Execute/Read
5835 case 0x1b: { //Code, Execute/Read, Accessed
5836 if (returnSegment.getRPL() < cpu.getCPL())
5837 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
5839 if (!(returnSegment.isPresent()))
5840 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, newCS, true);
5842 if (returnSegment.getRPL() > cpu.getCPL()) {
5843 //OUTER PRIVILEGE-LEVEL
5844 try {
5845 cpu.ss.checkAddress(cpu.esp + 7);
5846 } catch (ProcessorException e) {
5847 throw ProcessorException.STACK_SEGMENT_0;
5850 int returnESP = cpu.ss.getDoubleWord(cpu.esp);
5851 int tempSS = 0xffff & cpu.ss.getDoubleWord(cpu.esp + 4);
5853 Segment returnStackSegment = cpu.getSegment(tempSS);
5855 if ((returnStackSegment.getRPL() != returnSegment.getRPL()) || ((returnStackSegment.getType() & 0x12) != 0x12) ||
5856 (returnStackSegment.getDPL() != returnSegment.getRPL()))
5857 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempSS, true);
5859 if (!returnStackSegment.isPresent())
5860 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempSS, true);
5862 returnSegment.checkAddress(newEIP);
5864 //cpu.esp += 20; //includes the 12 from earlier
5865 cpu.eip = newEIP;
5866 cpu.cs = returnSegment;
5868 cpu.ss = returnStackSegment;
5869 cpu.esp = returnESP;
5871 int eflags = cpu.getEFlags();
5872 eflags &= ~0x254dd5;
5873 eflags |= (0x254dd5 & newEFlags);
5874 //overwrite: all; preserve: if, iopl, vm, vif, vip
5876 if (cpu.getCPL() <= cpu.eflagsIOPrivilegeLevel) {
5877 eflags &= ~0x200;
5878 eflags |= (0x200 & newEFlags);
5879 //overwrite: all; preserve: iopl, vm, vif, vip
5881 if (cpu.getCPL() == 0) {
5882 eflags &= ~0x1a3000;
5883 eflags |= (0x1a3000 & newEFlags);
5884 //overwrite: all;
5886 // cpu.setEFlags(eflags);
5888 cpu.setCPL(cpu.cs.getRPL());
5890 try {
5891 if ((((cpu.es.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.es.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.es.getDPL()))
5892 cpu.es = SegmentFactory.NULL_SEGMENT;
5893 } catch (ProcessorException e) {
5894 } catch (Exception e) {
5897 try {
5898 if ((((cpu.ds.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.ds.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.ds.getDPL()))
5899 cpu.ds = SegmentFactory.NULL_SEGMENT;
5900 } catch (ProcessorException e) {
5901 } catch (Exception e) {
5904 try {
5905 if ((((cpu.fs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.fs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.fs.getDPL()))
5906 cpu.fs = SegmentFactory.NULL_SEGMENT;
5907 } catch (ProcessorException e) {
5908 } catch (Exception e) {
5911 try {
5912 if ((((cpu.gs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.gs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.gs.getDPL()))
5913 cpu.gs = SegmentFactory.NULL_SEGMENT;
5914 } catch (ProcessorException e) {
5915 } catch (Exception e) {
5918 return eflags;
5919 } else {
5920 //SAME PRIVILEGE-LEVEL
5921 returnSegment.checkAddress(newEIP);
5923 cpu.cs = returnSegment;
5924 cpu.eip = newEIP;
5926 //Set EFlags
5927 int eflags = cpu.getEFlags();
5929 eflags &= ~0x254dd5;
5930 eflags |= (0x254dd5 & newEFlags);
5932 if (cpu.getCPL() <= cpu.eflagsIOPrivilegeLevel) {
5933 eflags &= ~0x200;
5934 eflags |= (0x200 & newEFlags);
5937 if (cpu.getCPL() == 0) {
5938 eflags &= ~0x1a3000;
5939 eflags |= (0x1a3000 & newEFlags);
5941 // cpu.setEFlags(eflags);
5942 return eflags;
5945 case 0x1c: //Code: Execute-Only, Conforming
5946 case 0x1d: //Code: Execute-Only, Conforming, Accessed
5947 case 0x1e: //Code: Execute/Read, Conforming
5948 case 0x1f: { //Code: Execute/Read, Conforming, Accessed
5949 if (returnSegment.getRPL() < cpu.getCPL())
5950 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
5952 if (returnSegment.getDPL() > returnSegment.getRPL())
5953 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
5955 if (!(returnSegment.isPresent()))
5956 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, newCS, true);
5958 if (returnSegment.getRPL() > cpu.getCPL()) {
5959 //OUTER PRIVILEGE-LEVEL
5960 System.err.println("Critical error: Conforming outer privilege level not implemented");
5961 throw new IllegalStateException("iret32ProtectedMode32BitAddressing to conforming outer privilege level not implemented");
5962 } else {
5963 //SAME PRIVILEGE-LEVEL
5964 returnSegment.checkAddress(newEIP);
5965 cpu.eip = newEIP;
5966 cpu.cs = returnSegment; //do descriptor as well
5967 cpu.setCarryFlag((newEFlags & 1) != 0);
5968 cpu.setParityFlag((newEFlags & (1 << 2)) != 0);
5969 cpu.setAuxiliaryCarryFlag((newEFlags & (1 << 4)) != 0);
5970 cpu.setZeroFlag((newEFlags & (1 << 6)) != 0);
5971 cpu.setSignFlag((newEFlags & (1 << 7)) != 0);
5972 cpu.eflagsTrap = ((newEFlags & (1 << 8)) != 0);
5973 cpu.eflagsDirection = ((newEFlags & (1 << 10)) != 0);
5974 cpu.setOverflowFlag((newEFlags & (1 << 11)) != 0);
5975 cpu.eflagsNestedTask = ((newEFlags & (1 << 14)) != 0);
5976 cpu.eflagsResume = ((newEFlags & (1 << 16)) != 0);
5977 cpu.eflagsAlignmentCheck = ((newEFlags & (1 << 18)) != 0); //do we need to call checkAlignmentChecking()?
5978 cpu.eflagsID = ((newEFlags & (1 << 21)) != 0);
5979 if (cpu.getCPL() <= cpu.eflagsIOPrivilegeLevel)
5980 cpu.eflagsInterruptEnableSoon
5981 = cpu.eflagsInterruptEnable = ((newEFlags & (1 << 9)) != 0);
5982 if (cpu.getCPL() == 0) {
5983 cpu.eflagsIOPrivilegeLevel = ((newEFlags >> 12) & 3);
5984 cpu.eflagsVirtual8086Mode = ((newEFlags & (1 << 17)) != 0);
5985 cpu.eflagsVirtualInterrupt = ((newEFlags & (1 << 19)) != 0);
5986 cpu.eflagsVirtualInterruptPending = ((newEFlags & (1 << 20)) != 0);
5988 return newEFlags;
5994 private final int iret_o32_a32()
5996 if (cpu.eflagsNestedTask)
5997 return iretFromTask();
5998 else {
5999 try {
6000 cpu.ss.checkAddress(cpu.esp + 11);
6001 } catch (ProcessorException e) {
6002 throw ProcessorException.STACK_SEGMENT_0;
6004 int tempEIP = cpu.ss.getDoubleWord(cpu.esp);
6005 int tempCS = 0xffff & cpu.ss.getDoubleWord(cpu.esp + 4);
6006 int tempEFlags = cpu.ss.getDoubleWord(cpu.esp + 8);
6007 cpu.esp += 12;
6009 if (((tempEFlags & (1 << 17)) != 0) && (cpu.getCPL() == 0)) {
6010 return iretToVirtual8086Mode32BitAddressing(tempCS, tempEIP, tempEFlags);
6011 } else {
6012 return iret32ProtectedMode32BitAddressing(tempCS, tempEIP, tempEFlags);
6017 private final int iret_o16_a16()
6019 if (cpu.eflagsNestedTask)
6020 return iretFromTask();
6021 else {
6022 try {
6023 cpu.ss.checkAddress((cpu.esp + 5) & 0xffff);
6024 } catch (ProcessorException e) {
6025 throw ProcessorException.STACK_SEGMENT_0;
6027 int tempEIP = 0xffff & cpu.ss.getWord(cpu.esp & 0xFFFF);
6028 int tempCS = 0xffff & cpu.ss.getWord((cpu.esp + 2) & 0xFFFF);
6029 int tempEFlags = 0xffff & cpu.ss.getWord((cpu.esp + 4) & 0xFFFF);
6030 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp + 6) & 0xffff);
6032 return iret16ProtectedMode16BitAddressing(tempCS, tempEIP, tempEFlags);
6036 private final int iret_o16_a32()
6038 if (cpu.eflagsNestedTask)
6039 return iretFromTask();
6040 else {
6041 try {
6042 cpu.ss.checkAddress(cpu.esp + 5);
6043 } catch (ProcessorException e) {
6044 throw ProcessorException.STACK_SEGMENT_0;
6046 int tempEIP = 0xffff & cpu.ss.getWord(cpu.esp);
6047 int tempCS = 0xffff & cpu.ss.getWord(cpu.esp + 4);
6048 int tempEFlags = 0xffff & cpu.ss.getWord(cpu.esp + 8);
6049 cpu.esp += 12;
6051 return iret16ProtectedMode32BitAddressing(tempCS, tempEIP, tempEFlags);
6055 private final int iret16ProtectedMode16BitAddressing(int newCS, int newEIP, int newEFlags)
6057 Segment returnSegment = cpu.getSegment(newCS);
6059 if (returnSegment == SegmentFactory.NULL_SEGMENT)
6060 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
6062 switch (returnSegment.getType()) {
6063 default:
6064 System.err.println("Emulated: Invalid segment type " + returnSegment.getType() + ".");
6065 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
6067 case 0x18: //Code, Execute-Only
6068 case 0x19: //Code, Execute-Only, Accessed
6069 case 0x1a: //Code, Execute/Read
6070 case 0x1b: //Code, Execute/Read, Accessed
6072 if (returnSegment.getRPL() < cpu.getCPL())
6073 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
6075 if (!(returnSegment.isPresent()))
6076 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, newCS, true);
6078 if (returnSegment.getRPL() > cpu.getCPL()) {
6079 //OUTER PRIVILEGE-LEVEL
6080 try {
6081 cpu.ss.checkAddress((cpu.esp + 3) & 0xFFFF);
6082 } catch (ProcessorException e) {
6083 throw ProcessorException.STACK_SEGMENT_0;
6086 int returnESP = 0xffff & cpu.ss.getWord(cpu.esp & 0xFFFF);
6087 int newSS = 0xffff & cpu.ss.getWord((cpu.esp + 2) & 0xFFFF);
6089 Segment returnStackSegment = cpu.getSegment(newSS);
6091 if ((returnStackSegment.getRPL() != returnSegment.getRPL()) || ((returnStackSegment.getType() & 0x12) != 0x12) ||
6092 (returnStackSegment.getDPL() != returnSegment.getRPL()))
6093 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newSS, true);
6095 if (!returnStackSegment.isPresent())
6096 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newSS, true);
6098 returnSegment.checkAddress(newEIP);
6100 //cpu.esp += 20; //includes the 12 from earlier
6101 cpu.eip = newEIP;
6102 cpu.cs = returnSegment;
6104 cpu.ss = returnStackSegment;
6105 cpu.esp = returnESP;
6107 int eflags = cpu.getEFlags();
6108 eflags &= ~0x4dd5;
6109 eflags |= (0x4dd5 & newEFlags);
6110 //overwrite: all; preserve: if, iopl, vm, vif, vip
6112 if (cpu.getCPL() <= cpu.eflagsIOPrivilegeLevel) {
6113 eflags &= ~0x200;
6114 eflags |= (0x200 & newEFlags);
6115 //overwrite: all; preserve: iopl, vm, vif, vip
6117 if (cpu.getCPL() == 0) {
6118 eflags &= ~0x3000;
6119 eflags |= (0x3000 & newEFlags);
6120 //overwrite: all;
6122 // cpu.setEFlags(eflags);
6124 cpu.setCPL(cpu.cs.getRPL());
6126 try {
6127 if ((((cpu.es.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.es.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.es.getDPL()))
6128 cpu.es = SegmentFactory.NULL_SEGMENT;
6129 } catch (ProcessorException e) {
6130 } catch (Exception e) {
6133 try {
6134 if ((((cpu.ds.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.ds.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.ds.getDPL()))
6135 cpu.ds = SegmentFactory.NULL_SEGMENT;
6136 } catch (ProcessorException e) {
6137 } catch (Exception e) {
6140 try {
6141 if ((((cpu.fs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.fs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.fs.getDPL()))
6142 cpu.fs = SegmentFactory.NULL_SEGMENT;
6143 } catch (ProcessorException e) {
6144 } catch (Exception e) {
6147 try {
6148 if ((((cpu.gs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.gs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.gs.getDPL()))
6149 cpu.gs = SegmentFactory.NULL_SEGMENT;
6150 } catch (ProcessorException e) {
6151 } catch (Exception e) {
6154 return eflags;
6155 } else {
6156 //SAME PRIVILEGE-LEVEL
6157 returnSegment.checkAddress(newEIP);
6159 cpu.cs = returnSegment;
6160 cpu.eip = newEIP;
6162 //Set EFlags
6163 int eflags = cpu.getEFlags();
6165 eflags &= ~0x4dd5;
6166 eflags |= (0x4dd5 & newEFlags);
6168 if (cpu.getCPL() <= cpu.eflagsIOPrivilegeLevel) {
6169 eflags &= ~0x200;
6170 eflags |= (0x200 & newEFlags);
6173 if (cpu.getCPL() == 0) {
6174 eflags &= ~0x3000;
6175 eflags |= (0x3000 & newEFlags);
6178 // cpu.setEFlags(eflags);
6179 return eflags;
6182 case 0x1c: //Code: Execute-Only, Conforming
6183 case 0x1d: //Code: Execute-Only, Conforming, Accessed
6184 case 0x1e: //Code: Execute/Read, Conforming
6185 case 0x1f: //Code: Execute/Read, Conforming, Accessed
6187 if (returnSegment.getRPL() < cpu.getCPL())
6188 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
6190 if (returnSegment.getDPL() > returnSegment.getRPL())
6191 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
6193 if (!(returnSegment.isPresent()))
6194 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, newCS, true);
6196 if (returnSegment.getRPL() > cpu.getCPL()) {
6197 //OUTER PRIVILEGE-LEVEL
6198 System.err.println("Critical error: Conforming outer privilege level not implemented");
6199 throw new IllegalStateException("iret16ProtectedMode16BitAddressing to conforming outer privilege level not implemented");
6200 } else {
6201 //SAME PRIVILEGE-LEVEL
6202 System.err.println("Critical error: Conforming same privilege level not implemented");
6203 throw new IllegalStateException("iret16ProtectedMode16BitAddressing to conforming same privilege level not implemented");
6209 private final int iret16ProtectedMode32BitAddressing(int newCS, int newEIP, int newEFlags)
6211 Segment returnSegment = cpu.getSegment(newCS);
6213 if (returnSegment == SegmentFactory.NULL_SEGMENT)
6214 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
6216 switch (returnSegment.getType()) {
6217 default:
6218 System.err.println("Emulated: Invalid segment type " + returnSegment.getType() + ".");
6219 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
6221 case 0x18: //Code, Execute-Only
6222 case 0x19: //Code, Execute-Only, Accessed
6223 case 0x1a: //Code, Execute/Read
6224 case 0x1b: { //Code, Execute/Read, Accessed
6225 if (returnSegment.getRPL() < cpu.getCPL())
6226 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
6228 if (!(returnSegment.isPresent()))
6229 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, newCS, true);
6231 if (returnSegment.getRPL() > cpu.getCPL()) {
6232 //OUTER PRIVILEGE-LEVEL
6233 try {
6234 cpu.ss.checkAddress(cpu.esp + 3);
6235 } catch (ProcessorException e) {
6236 throw ProcessorException.STACK_SEGMENT_0;
6239 int returnESP = 0xffff & cpu.ss.getWord(cpu.esp);
6240 int tempSS = 0xffff & cpu.ss.getWord(cpu.esp + 2);
6242 Segment returnStackSegment = cpu.getSegment(tempSS);
6244 if ((returnStackSegment.getRPL() != returnSegment.getRPL()) || ((returnStackSegment.getType() & 0x12) != 0x12) ||
6245 (returnStackSegment.getDPL() != returnSegment.getRPL()))
6246 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempSS, true);
6248 if (!returnStackSegment.isPresent())
6249 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, tempSS, true);
6251 returnSegment.checkAddress(newEIP);
6253 //cpu.esp += 20; //includes the 12 from earlier
6254 cpu.eip = newEIP;
6255 cpu.cs = returnSegment;
6257 cpu.ss = returnStackSegment;
6258 cpu.esp = returnESP;
6260 int eflags = cpu.getEFlags();
6261 eflags &= ~0x4dd5;
6262 eflags |= (0x4dd5 & newEFlags);
6263 //overwrite: all; preserve: if, iopl, vm, vif, vip
6265 if (cpu.getCPL() <= cpu.eflagsIOPrivilegeLevel) {
6266 eflags &= ~0x200;
6267 eflags |= (0x200 & newEFlags);
6268 //overwrite: all; preserve: iopl, vm, vif, vip
6270 if (cpu.getCPL() == 0) {
6271 eflags &= ~0x3000;
6272 eflags |= (0x3000 & newEFlags);
6273 //overwrite: all;
6275 // cpu.setEFlags(eflags);
6277 cpu.setCPL(cpu.cs.getRPL());
6279 try {
6280 if ((((cpu.es.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.es.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.es.getDPL()))
6281 cpu.es = SegmentFactory.NULL_SEGMENT;
6282 } catch (ProcessorException e) {
6283 } catch (Exception e) {
6286 try {
6287 if ((((cpu.ds.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.ds.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.ds.getDPL()))
6288 cpu.ds = SegmentFactory.NULL_SEGMENT;
6289 } catch (ProcessorException e) {
6290 } catch (Exception e) {
6293 try {
6294 if ((((cpu.fs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.fs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.fs.getDPL()))
6295 cpu.fs = SegmentFactory.NULL_SEGMENT;
6296 } catch (ProcessorException e) {
6297 } catch (Exception e) {
6300 try {
6301 if ((((cpu.gs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE)) == ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA) || ((cpu.gs.getType() & (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING)) == (ProtectedModeSegment.DESCRIPTOR_TYPE_CODE_DATA | ProtectedModeSegment.TYPE_CODE))) && (cpu.getCPL() > cpu.gs.getDPL()))
6302 cpu.gs = SegmentFactory.NULL_SEGMENT;
6303 } catch (ProcessorException e) {
6304 } catch (Exception e) {
6307 return eflags;
6308 } else {
6309 //SAME PRIVILEGE-LEVEL
6310 returnSegment.checkAddress(newEIP);
6312 cpu.cs = returnSegment;
6313 cpu.eip = newEIP;
6315 //Set EFlags
6316 int eflags = cpu.getEFlags();
6318 eflags &= ~0x4dd5;
6319 eflags |= (0x4dd5 & newEFlags);
6321 if (cpu.getCPL() <= cpu.eflagsIOPrivilegeLevel) {
6322 eflags &= ~0x200;
6323 eflags |= (0x200 & newEFlags);
6326 if (cpu.getCPL() == 0) {
6327 eflags &= ~0x3000;
6328 eflags |= (0x3000 & newEFlags);
6330 // cpu.setEFlags(eflags);
6331 return eflags;
6334 case 0x1c: //Code: Execute-Only, Conforming
6335 case 0x1d: //Code: Execute-Only, Conforming, Accessed
6336 case 0x1e: //Code: Execute/Read, Conforming
6337 case 0x1f: { //Code: Execute/Read, Conforming, Accessed
6338 if (returnSegment.getRPL() < cpu.getCPL())
6339 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
6341 if (returnSegment.getDPL() > returnSegment.getRPL())
6342 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, newCS, true);
6344 if (!(returnSegment.isPresent()))
6345 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, newCS, true);
6347 if (returnSegment.getRPL() > cpu.getCPL()) {
6348 //OUTER PRIVILEGE-LEVEL
6349 System.err.println("Critical error: Conforming outer privilege level not implemented");
6350 throw new IllegalStateException("iret16ProtectedMode32BitAddressing to conforming outer privilege level not implemented");
6351 } else {
6352 //SAME PRIVILEGE-LEVEL
6353 System.err.println("Critical error: Conforming same privilege level not implemented");
6354 throw new IllegalStateException("iret16ProtectedMode32BitAddressing to conforming same privilege level not implemented");
6360 private final void sysenter()
6362 int csSelector = (int) cpu.getMSR(Processor.SYSENTER_CS_MSR);
6363 if (csSelector == 0)
6364 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0;
6365 cpu.eflagsInterruptEnable = cpu.eflagsInterruptEnableSoon = false;
6366 cpu.eflagsResume = false;
6368 cpu.cs = SegmentFactory.createProtectedModeSegment(cpu.linearMemory, csSelector & 0xfffc, 0x00cf9b000000ffffl);
6369 cpu.setCPL(0);
6370 cpu.ss = SegmentFactory.createProtectedModeSegment(cpu.linearMemory, (csSelector + 8) & 0xfffc, 0x00cf93000000ffffl);
6372 cpu.esp = (int) cpu.getMSR(Processor.SYSENTER_ESP_MSR);
6373 cpu.eip = (int) cpu.getMSR(Processor.SYSENTER_EIP_MSR);
6376 private final void sysexit(int esp, int eip)
6378 int csSelector= (int)cpu.getMSR(Processor.SYSENTER_CS_MSR);
6379 if (csSelector == 0)
6380 throw ProcessorException.GENERAL_PROTECTION_0;
6381 if (cpu.getCPL() != 0)
6382 throw ProcessorException.GENERAL_PROTECTION_0;
6384 cpu.cs = SegmentFactory.createProtectedModeSegment(cpu.linearMemory, (csSelector + 16) | 0x3, 0x00cffb000000ffffl);
6385 cpu.setCPL(3);
6386 cpu.ss = SegmentFactory.createProtectedModeSegment(cpu.linearMemory, (csSelector + 24) | 0x3, 0x00cff3000000ffffl);
6387 cpu.correctAlignmentChecking(cpu.ss);
6389 cpu.esp = esp;
6390 cpu.eip = eip;
6393 private final int in_o8(int port)
6395 if (checkIOPermissionsByte(port))
6396 return 0xff & cpu.ioports.ioPortReadByte(port);
6397 else {
6398 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
6399 " at cpl " + cpu.getCPL() + ".");
6400 throw ProcessorException.GENERAL_PROTECTION_0;
6404 private final int in_o16(int port)
6406 if (checkIOPermissionsShort(port))
6407 return 0xffff & cpu.ioports.ioPortReadWord(port);
6408 else {
6409 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
6410 " at cpl " + cpu.getCPL() + ".");
6411 throw ProcessorException.GENERAL_PROTECTION_0;
6415 private final int in_o32(int port)
6417 if (checkIOPermissionsInt(port))
6418 return cpu.ioports.ioPortReadLong(port);
6419 else {
6420 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
6421 " at cpl " + cpu.getCPL() + ".");
6422 throw ProcessorException.GENERAL_PROTECTION_0;
6426 private final void out_o8(int port, int data)
6428 if (checkIOPermissionsByte(port))
6429 cpu.ioports.ioPortWriteByte(port, 0xff & data);
6430 else {
6431 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
6432 " at cpl " + cpu.getCPL() + ".");
6433 throw ProcessorException.GENERAL_PROTECTION_0;
6437 private final void out_o16(int port, int data)
6439 if (checkIOPermissionsShort(port))
6440 cpu.ioports.ioPortWriteWord(port, 0xffff & data);
6441 else {
6442 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
6443 " at cpl " + cpu.getCPL() + ".");
6444 throw ProcessorException.GENERAL_PROTECTION_0;
6448 private final void out_o32(int port, int data)
6450 if (checkIOPermissionsInt(port))
6451 cpu.ioports.ioPortWriteLong(port, data);
6452 else {
6453 System.err.println("Emulated: denied access to io port 0x" + Integer.toHexString(port) +
6454 " at cpl " + cpu.getCPL() + ".");
6455 throw ProcessorException.GENERAL_PROTECTION_0;
6459 private final void enter_o16_a16(int frameSize, int nestingLevel)
6461 nestingLevel %= 32;
6463 int tempESP = 0xFFFF & cpu.esp;
6464 int tempEBP = 0xFFFF & cpu.ebp;
6466 if (nestingLevel == 0) {
6467 if ((tempESP < (2 + frameSize)) && (tempESP > 0))
6468 throw ProcessorException.STACK_SEGMENT_0;
6469 } else {
6470 if ((tempESP < (2 + frameSize + 2 * nestingLevel)) && (tempESP > 0))
6471 throw ProcessorException.STACK_SEGMENT_0;
6474 tempESP -= 2;
6475 cpu.ss.setWord(tempESP, (short) tempEBP);
6477 int frameTemp = tempESP;
6479 if (nestingLevel > 0) {
6480 while (--nestingLevel != 0) {
6481 tempEBP -= 2;
6482 tempESP -= 2;
6483 cpu.ss.setWord(tempESP, (short) (0xFFFF & cpu.ss.getWord(tempEBP)));
6486 tempESP -= 2;
6487 cpu.ss.setWord(tempESP, (short)frameTemp);
6490 cpu.ebp = (cpu.ebp & ~0xFFFF)| (0xFFFF & frameTemp);
6491 cpu.esp = (cpu.esp & ~0xFFFF)| (0xFFFF & (frameTemp - frameSize - 2*nestingLevel));
6494 private final void enter_o16_a32(int frameSize, int nestingLevel)
6496 nestingLevel %= 32;
6498 int tempESP = cpu.esp;
6499 int tempEBP = cpu.ebp;
6501 if (nestingLevel == 0) {
6502 if ((tempESP < (2 + frameSize)) && (tempESP > 0))
6503 throw ProcessorException.STACK_SEGMENT_0;
6504 } else {
6505 if ((tempESP < (2 + frameSize + 2 * nestingLevel)) && (tempESP > 0))
6506 throw ProcessorException.STACK_SEGMENT_0;
6509 tempESP -= 2;
6510 cpu.ss.setWord(tempESP, (short)tempEBP);
6512 int frameTemp = tempESP;
6514 if (nestingLevel > 0)
6516 int tmpLevel = nestingLevel;
6517 while (--tmpLevel != 0)
6519 tempEBP -= 2;
6520 tempESP -= 2;
6521 cpu.ss.setWord(tempESP, cpu.ss.getWord(tempEBP));
6524 tempESP -= 2;
6525 cpu.ss.setWord(tempESP, (short)frameTemp);
6528 cpu.ebp = frameTemp;
6529 cpu.esp = frameTemp - frameSize -2*nestingLevel;
6532 private final void enter_o32_a32(int frameSize, int nestingLevel)
6534 nestingLevel %= 32;
6536 int tempESP = cpu.esp;
6537 int tempEBP = cpu.ebp;
6539 if (nestingLevel == 0) {
6540 if ((tempESP < (4 + frameSize)) && (tempESP > 0))
6541 throw ProcessorException.STACK_SEGMENT_0;
6542 } else {
6543 if ((tempESP < (4 + frameSize + 4 * nestingLevel)) && (tempESP > 0))
6544 throw ProcessorException.STACK_SEGMENT_0;
6547 tempESP -= 4;
6548 cpu.ss.setDoubleWord(tempESP, tempEBP);
6550 int frameTemp = tempESP;
6552 int tmplevel = nestingLevel;
6553 if (nestingLevel != 0) {
6554 while (--tmplevel != 0) {
6555 tempEBP -= 4;
6556 tempESP -= 4;
6557 cpu.ss.setDoubleWord(tempESP, cpu.ss.getDoubleWord(tempEBP));
6559 tempESP -= 4;
6560 cpu.ss.setDoubleWord(tempESP, frameTemp);
6563 cpu.ebp = frameTemp;
6564 cpu.esp = frameTemp - frameSize - 4*nestingLevel;
6567 private final void leave_o32_a16()
6569 cpu.ss.checkAddress(cpu.ebp & 0xffff);
6570 int tempESP = cpu.ebp & 0xffff;
6571 int tempEBP = cpu.ss.getDoubleWord(tempESP);
6572 cpu.esp = (cpu.esp & ~0xffff) | ((tempESP + 4) & 0xffff);
6573 cpu.ebp = tempEBP;
6576 private final void leave_o32_a32()
6578 cpu.ss.checkAddress(cpu.ebp);
6579 int tempESP = cpu.ebp;
6580 int tempEBP = cpu.ss.getDoubleWord(tempESP);
6581 cpu.esp = tempESP + 4;
6582 cpu.ebp = tempEBP;
6585 private final void leave_o16_a16()
6587 cpu.ss.checkAddress(cpu.ebp & 0xffff);
6588 int tempESP = cpu.ebp & 0xffff;
6589 int tempEBP = 0xffff & cpu.ss.getWord(tempESP);
6590 cpu.esp = (cpu.esp & ~0xffff) | ((tempESP + 2) & 0xffff);
6591 cpu.ebp = (cpu.ebp & ~0xffff) | tempEBP;
6594 private final void leave_o16_a32()
6596 cpu.ss.checkAddress(cpu.ebp);
6597 int tempESP = cpu.ebp;
6598 int tempEBP = 0xffff & cpu.ss.getWord(tempESP);
6599 cpu.esp = tempESP + 2;
6600 cpu.ebp = (cpu.ebp & ~0xffff) | tempEBP;
6603 private final void push_o32_a32(int value)
6605 if ((cpu.esp < 4) && (cpu.esp > 0))
6606 throw ProcessorException.STACK_SEGMENT_0;
6608 cpu.ss.setDoubleWord(cpu.esp - 4, value);
6609 cpu.esp -= 4;
6612 private final void push_o32_a16(int value)
6614 if (((0xffff & cpu.esp) < 4) && ((0xffff & cpu.esp) > 0))
6615 throw ProcessorException.STACK_SEGMENT_0;
6617 cpu.ss.setDoubleWord((cpu.esp - 4) & 0xffff, value);
6618 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp - 4) & 0xffff);
6621 private final void push_o16_a32(short value)
6623 if ((cpu.esp < 2) && (cpu.esp > 0))
6624 throw ProcessorException.STACK_SEGMENT_0;
6626 cpu.ss.setWord(cpu.esp - 2, value);
6627 cpu.esp -= 2;
6630 private final void push_o16_a16(short value)
6632 if (((0xffff & cpu.esp) < 2) && ((0xffff & cpu.esp) > 0))
6633 throw ProcessorException.STACK_SEGMENT_0;
6635 cpu.ss.setWord(((0xFFFF & cpu.esp) - 2) & 0xffff, value);
6636 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp - 2) & 0xffff);
6639 private final void pushad_a32()
6641 int offset = cpu.esp;
6642 int temp = cpu.esp;
6643 if ((offset < 32) && (offset > 0))
6644 throw ProcessorException.STACK_SEGMENT_0;
6646 offset -= 4;
6647 cpu.ss.setDoubleWord(offset, cpu.eax);
6648 offset -= 4;
6649 cpu.ss.setDoubleWord(offset, cpu.ecx);
6650 offset -= 4;
6651 cpu.ss.setDoubleWord(offset, cpu.edx);
6652 offset -= 4;
6653 cpu.ss.setDoubleWord(offset, cpu.ebx);
6654 offset -= 4;
6655 cpu.ss.setDoubleWord(offset, temp);
6656 offset -= 4;
6657 cpu.ss.setDoubleWord(offset, cpu.ebp);
6658 offset -= 4;
6659 cpu.ss.setDoubleWord(offset, cpu.esi);
6660 offset -= 4;
6661 cpu.ss.setDoubleWord(offset, cpu.edi);
6663 cpu.esp = offset;
6666 private final void pushad_a16()
6668 int offset = 0xFFFF & cpu.esp;
6669 int temp = 0xFFFF & cpu.esp;
6670 if ((offset < 32) && (offset > 0))
6671 throw ProcessorException.STACK_SEGMENT_0;
6673 offset -= 4;
6674 cpu.ss.setDoubleWord(offset, cpu.eax);
6675 offset -= 4;
6676 cpu.ss.setDoubleWord(offset, cpu.ecx);
6677 offset -= 4;
6678 cpu.ss.setDoubleWord(offset, cpu.edx);
6679 offset -= 4;
6680 cpu.ss.setDoubleWord(offset, cpu.ebx);
6681 offset -= 4;
6682 cpu.ss.setDoubleWord(offset, temp);
6683 offset -= 4;
6684 cpu.ss.setDoubleWord(offset, cpu.ebp);
6685 offset -= 4;
6686 cpu.ss.setDoubleWord(offset, cpu.esi);
6687 offset -= 4;
6688 cpu.ss.setDoubleWord(offset, cpu.edi);
6690 cpu.esp = (cpu.esp & ~0xFFFF) | (0xFFFF & offset);
6693 private final void pusha_a32()
6695 int offset = cpu.esp;
6696 int temp = cpu.esp;
6697 if ((offset < 16) && (offset > 0))
6698 throw ProcessorException.STACK_SEGMENT_0;
6700 offset -= 2;
6701 cpu.ss.setWord(offset,(short)( 0xffff & cpu.eax));
6702 offset -= 2;
6703 cpu.ss.setWord(offset,(short)( 0xffff & cpu.ecx));
6704 offset -= 2;
6705 cpu.ss.setWord(offset,(short)( 0xffff & cpu.edx));
6706 offset -= 2;
6707 cpu.ss.setWord(offset,(short)( 0xffff & cpu.ebx));
6708 offset -= 2;
6709 cpu.ss.setWord(offset,(short)( 0xffff & temp));
6710 offset -= 2;
6711 cpu.ss.setWord(offset,(short)( 0xffff & cpu.ebp));
6712 offset -= 2;
6713 cpu.ss.setWord(offset,(short)( 0xffff & cpu.esi));
6714 offset -= 2;
6715 cpu.ss.setWord(offset,(short)( 0xffff & cpu.edi));
6717 cpu.esp = (cpu.esp & ~0xffff) | (offset & 0xffff);
6719 private final void pusha_a16()
6721 int offset = 0xFFFF & cpu.esp;
6722 int temp = 0xFFFF & cpu.esp;
6723 if ((offset < 16) && (offset > 0))
6724 throw ProcessorException.STACK_SEGMENT_0;
6726 offset -= 2;
6727 cpu.ss.setWord(offset,(short)(cpu.eax));
6728 offset -= 2;
6729 cpu.ss.setWord(offset,(short)( cpu.ecx));
6730 offset -= 2;
6731 cpu.ss.setWord(offset,(short)( cpu.edx));
6732 offset -= 2;
6733 cpu.ss.setWord(offset,(short)( cpu.ebx));
6734 offset -= 2;
6735 cpu.ss.setWord(offset,(short)(temp));
6736 offset -= 2;
6737 cpu.ss.setWord(offset,(short)(cpu.ebp));
6738 offset -= 2;
6739 cpu.ss.setWord(offset,(short)(cpu.esi));
6740 offset -= 2;
6741 cpu.ss.setWord(offset,(short)(cpu.edi));
6743 cpu.esp = (cpu.esp & ~0xffff) | (0xFFFF & offset);
6746 private final void popa_a16()
6748 int offset = 0xFFFF & cpu.esp;
6750 //Bochs claims no checking need on POPs
6751 //if (offset + 16 >= cpu.ss.limit)
6752 // throw ProcessorException.STACK_SEGMENT_0;
6754 int newedi = (cpu.edi & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6755 offset += 2;
6756 int newesi = (cpu.esi & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6757 offset += 2;
6758 int newebp = (cpu.ebp & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6759 offset += 4;// yes - skip an extra 2 bytes in order to skip ESP
6761 int newebx = (cpu.ebx & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6762 offset += 2;
6763 int newedx = (cpu.edx & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6764 offset += 2;
6765 int newecx = (cpu.ecx & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6766 offset += 2;
6767 int neweax = (cpu.eax & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6768 offset += 2;
6770 cpu.edi = newedi;
6771 cpu.esi = newesi;
6772 cpu.ebp = newebp;
6773 cpu.ebx = newebx;
6774 cpu.edx = newedx;
6775 cpu.ecx = newecx;
6776 cpu.eax = neweax;
6778 cpu.esp = (cpu.esp & ~0xffff) | (offset & 0xffff);
6781 private final void popad_a16()
6783 int offset = 0xFFFF &cpu.esp;
6785 //Bochs claims no checking need on POPs
6786 //if (offset + 16 >= cpu.ss.limit)
6787 // throw ProcessorException.STACK_SEGMENT_0;
6789 int newedi = cpu.ss.getDoubleWord(offset);
6790 offset += 4;
6791 int newesi = cpu.ss.getDoubleWord(offset);
6792 offset += 4;
6793 int newebp = cpu.ss.getDoubleWord(offset);
6794 offset += 8;// yes - skip an extra 4 bytes in order to skip ESP
6796 int newebx = cpu.ss.getDoubleWord(offset);
6797 offset += 4;
6798 int newedx = cpu.ss.getDoubleWord(offset);
6799 offset += 4;
6800 int newecx = cpu.ss.getDoubleWord(offset);
6801 offset += 4;
6802 int neweax = cpu.ss.getDoubleWord(offset);
6803 offset += 4;
6805 cpu.edi = newedi;
6806 cpu.esi = newesi;
6807 cpu.ebp = newebp;
6808 cpu.ebx = newebx;
6809 cpu.edx = newedx;
6810 cpu.ecx = newecx;
6811 cpu.eax = neweax;
6813 cpu.esp = (cpu.esp & ~0xffff) | (offset & 0xffff);
6816 private final void popa_a32()
6818 int offset = cpu.esp;
6820 //Bochs claims no checking need on POPs
6821 //if (offset + 16 >= cpu.ss.limit)
6822 // throw ProcessorException.STACK_SEGMENT_0;
6824 int newedi = (cpu.edi & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6825 offset += 2;
6826 int newesi = (cpu.esi & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6827 offset += 2;
6828 int newebp = (cpu.ebp & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6829 offset += 4;// yes - skip an extra 2 bytes in order to skip ESP
6831 int newebx = (cpu.ebx & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6832 offset += 2;
6833 int newedx = (cpu.edx & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6834 offset += 2;
6835 int newecx = (cpu.ecx & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6836 offset += 2;
6837 int neweax = (cpu.eax & ~0xffff) | (0xffff & cpu.ss.getWord(offset));
6838 offset += 2;
6840 cpu.edi = newedi;
6841 cpu.esi = newesi;
6842 cpu.ebp = newebp;
6843 cpu.ebx = newebx;
6844 cpu.edx = newedx;
6845 cpu.ecx = newecx;
6846 cpu.eax = neweax;
6848 cpu.esp = offset;
6851 private final void popad_a32()
6853 int offset = cpu.esp;
6855 //Bochs claims no checking need on POPs
6856 //if (offset + 16 >= cpu.ss.limit)
6857 // throw ProcessorException.STACK_SEGMENT_0;
6859 int newedi = cpu.ss.getDoubleWord(offset);
6860 offset += 4;
6861 int newesi = cpu.ss.getDoubleWord(offset);
6862 offset += 4;
6863 int newebp = cpu.ss.getDoubleWord(offset);
6864 offset += 8;// yes - skip an extra 4 bytes in order to skip ESP
6866 int newebx = cpu.ss.getDoubleWord(offset);
6867 offset += 4;
6868 int newedx = cpu.ss.getDoubleWord(offset);
6869 offset += 4;
6870 int newecx = cpu.ss.getDoubleWord(offset);
6871 offset += 4;
6872 int neweax = cpu.ss.getDoubleWord(offset);
6873 offset += 4;
6875 cpu.edi = newedi;
6876 cpu.esi = newesi;
6877 cpu.ebp = newebp;
6878 cpu.ebx = newebx;
6879 cpu.edx = newedx;
6880 cpu.ecx = newecx;
6881 cpu.eax = neweax;
6883 cpu.esp = offset;
6886 private final int lar(int selector, int original)
6888 if ((selector & 0xFFC) == 0)
6890 cpu.setZeroFlag(false);
6891 return original;
6893 int offset = selector & 0xfff8;
6895 //allow all normal segments
6896 // and available and busy 32 bit and 16 bit TSS (9, b, 3, 1)
6897 // and ldt and tsk gate (2, 5)
6898 // and 32 bit and 16 bit call gates (c, 4)
6899 final boolean valid[] = {
6900 false, true, true, true,
6901 true, true, false, false,
6902 false, true, false, true,
6903 true, false, false, false,
6904 true, true, true, true,
6905 true, true, true, true,
6906 true, true, true, true,
6907 true, true, true, true
6910 Segment descriptorTable;
6911 if ((selector & 0x4) != 0)
6912 descriptorTable = cpu.ldtr;
6913 else
6914 descriptorTable = cpu.gdtr;
6916 if ((offset + 7) > descriptorTable.getLimit()) {
6917 cpu.setZeroFlag(false);
6918 return original;
6921 int descriptor = cpu.readSupervisorDoubleWord(descriptorTable, offset + 4);
6922 int type = (descriptor & 0x1f00) >> 8;
6923 int dpl = (descriptor & 0x6000) >> 13;
6924 int rpl = (selector & 0x3);
6926 int conformingCode = ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING;
6927 if ((((type & conformingCode) != conformingCode) && ((cpu.getCPL() > dpl) || (rpl > dpl))) || !valid[type])
6929 cpu.setZeroFlag(false);
6930 return original;
6931 } else
6933 cpu.setZeroFlag(true);
6934 return descriptor & 0x00FFFF00;
6938 private final int lsl(int selector, int original)
6940 int offset = selector & 0xfff8;
6942 final boolean valid[] = {
6943 false, true, true, true,
6944 true, true, false, false,
6945 false, true, false, true,
6946 true, false, false, false,
6947 true, true, true, true,
6948 true, true, true, true,
6949 true, true, true, true,
6950 true, true, true, true
6953 Segment descriptorTable;
6954 if ((selector & 0x4) != 0)
6955 descriptorTable = cpu.ldtr;
6956 else
6957 descriptorTable = cpu.gdtr;
6959 if ((offset + 8) > descriptorTable.getLimit()) { //
6960 cpu.setZeroFlag(false);
6961 return original;
6964 int segmentDescriptor = cpu.readSupervisorDoubleWord(descriptorTable, offset + 4);
6966 int type = (segmentDescriptor & 0x1f00) >> 8;
6967 int dpl = (segmentDescriptor & 0x6000) >> 13;
6968 int rpl = (selector & 0x3);
6969 int conformingCode = ProtectedModeSegment.TYPE_CODE | ProtectedModeSegment.TYPE_CODE_CONFORMING;
6970 if ((((type & conformingCode) != conformingCode) && ((cpu.getCPL() > dpl) || (rpl > dpl))) || !valid[type]) {
6971 cpu.setZeroFlag(false);
6972 return original;
6975 int lowsize;
6976 if ((selector & 0x4) != 0) // ldtr or gtdr
6977 lowsize = cpu.readSupervisorWord(cpu.ldtr, offset);
6978 else
6979 lowsize = cpu.readSupervisorWord(cpu.gdtr, offset);
6981 int size = (segmentDescriptor & 0xf0000) | (lowsize & 0xFFFF);
6983 if ((segmentDescriptor & 0x800000) != 0) // granularity ==1
6984 size = (size << 12) | 0xFFF;
6986 cpu.setZeroFlag(true);
6987 return size;
6990 private final Segment lldt(int selector)
6992 selector &= 0xffff;
6994 if (selector == 0)
6995 return SegmentFactory.NULL_SEGMENT;
6997 Segment newSegment = cpu.getSegment(selector & ~0x4);
6998 if (newSegment.getType() != 0x02)
6999 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, selector, true);
7001 if (!(newSegment.isPresent()))
7002 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, selector, true);
7004 return newSegment;
7008 private final Segment ltr(int selector)
7010 if ((selector & 0x4) != 0) //must be gdtr table
7011 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, selector, true);
7013 Segment tempSegment = cpu.getSegment(selector);
7015 if ((tempSegment.getType() != 0x01) && (tempSegment.getType() != 0x09))
7016 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, selector, true);
7018 if (!(tempSegment.isPresent()))
7019 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, selector, true);
7021 long descriptor = cpu.readSupervisorQuadWord(cpu.gdtr, (selector & 0xfff8)) | (0x1l << 41); // set busy flag in segment descriptor
7022 cpu.setSupervisorQuadWord(cpu.gdtr, selector & 0xfff8, descriptor);
7024 //reload segment
7025 return cpu.getSegment(selector);
7028 private final void cpuid()
7030 switch (cpu.eax) {
7031 case 0x00:
7032 cpu.eax = 0x02;
7033 cpu.ebx = 0x756e6547; /* "Genu", with G in the low nibble of BL */
7034 cpu.edx = 0x49656e69; /* "ineI", with i in the low nibble of DL */
7035 cpu.ecx = 0x6c65746e; /* "ntel", with n in the low nibble of CL */
7036 return;
7037 case 0x01:
7038 cpu.eax = 0x00000633; // Pentium II Model 8 Stepping 3
7039 cpu.ebx = 8 << 8; //not implemented (should be brand index)
7040 cpu.ecx = 0;
7042 int features = 0;
7043 features |= 0x01; //Have an FPU;
7044 features |= (1<< 8); // Support CMPXCHG8B instruction
7045 features |= (1<< 4); // implement TSC
7046 features |= (1<< 5); // support RDMSR/WRMSR
7047 //features |= (1<<23); // support MMX
7048 //features |= (1<<24); // Implement FSAVE/FXRSTOR instructions.
7049 features |= (1<<15); // Implement CMOV instructions.
7050 //features |= (1<< 9); // APIC on chip
7051 //features |= (1<<25); // support SSE
7052 features |= (1<< 3); // Support Page-Size Extension (4M pages)
7053 features |= (1<<13); // Support Global pages.
7054 //features |= (1<< 6); // Support PAE.
7055 features |= (1<<11); // SYSENTER/SYSEXIT
7056 cpu.edx = features;
7057 return;
7058 default:
7059 case 0x02:
7060 cpu.eax = 0x410601;
7061 cpu.ebx = 0;
7062 cpu.ecx = 0;
7063 cpu.edx = 0;
7064 return;
7068 private final long rdtsc()
7070 if ((cpu.getCPL() == 0) || ((cpu.getCR4() & 0x4) == 0)) {
7071 return cpu.getClockCount();
7072 } else
7073 throw ProcessorException.GENERAL_PROTECTION_0;
7076 private final void bitwise_flags(byte result)
7078 cpu.setOverflowFlag(false);
7079 cpu.setCarryFlag(false);
7080 cpu.setZeroFlag(result);
7081 cpu.setParityFlag(result);
7082 cpu.setSignFlag(result);
7085 private final void bitwise_flags(short result)
7087 cpu.setOverflowFlag(false);
7088 cpu.setCarryFlag(false);
7089 cpu.setZeroFlag(result);
7090 cpu.setParityFlag(result);
7091 cpu.setSignFlag(result);
7094 private final void bitwise_flags(int result)
7096 cpu.setOverflowFlag(false);
7097 cpu.setCarryFlag(false);
7098 cpu.setZeroFlag(result);
7099 cpu.setParityFlag(result);
7100 cpu.setSignFlag(result);
7103 private final void arithmetic_flags_o8(int result, int operand1, int operand2)
7105 cpu.setZeroFlag((byte)result);
7106 cpu.setParityFlag(result);
7107 cpu.setSignFlag((byte)result);
7109 cpu.setCarryFlag(result, Processor.CY_TWIDDLE_FF);
7110 cpu.setAuxiliaryCarryFlag(operand1, operand2, result, Processor.AC_XOR);
7113 private final void arithmetic_flags_o16(int result, int operand1, int operand2)
7115 cpu.setZeroFlag((short)result);
7116 cpu.setParityFlag(result);
7117 cpu.setSignFlag((short)result);
7119 cpu.setCarryFlag(result, Processor.CY_TWIDDLE_FFFF);
7120 cpu.setAuxiliaryCarryFlag(operand1, operand2, result, Processor.AC_XOR);
7123 private final void arithmetic_flags_o32(long result, int operand1, int operand2)
7125 cpu.setZeroFlag((int)result);
7126 cpu.setParityFlag((int)result);
7127 cpu.setSignFlag((int)result);
7129 cpu.setCarryFlag(result, Processor.CY_TWIDDLE_FFFFFFFF);
7130 cpu.setAuxiliaryCarryFlag(operand1, operand2, (int)result, Processor.AC_XOR);
7133 private final void add_o32_flags(long result, int operand1, int operand2)
7135 result = (0xffffffffl & operand1) + (0xffffffffl & operand2);
7137 arithmetic_flags_o32(result, operand1, operand2);
7138 cpu.setOverflowFlag((int)result, operand1, operand2, Processor.OF_ADD_INT);
7141 private final void add_o16_flags(int result, int operand1, int operand2)
7143 arithmetic_flags_o16(result, operand1, operand2);
7144 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_ADD_SHORT);
7147 private final void add_o8_flags(int result, int operand1, int operand2)
7149 arithmetic_flags_o8(result, operand1, operand2);
7150 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_ADD_BYTE);
7153 private final void adc_o32_flags(long result, int operand1, int operand2)
7155 int carry = (cpu.getCarryFlag() ? 1 : 0);
7156 result = (0xffffffffl & operand1) + (0xffffffffl & operand2) + carry;
7158 if (cpu.getCarryFlag() && (operand2 == 0xffffffff)) {
7159 arithmetic_flags_o32(result, operand1, operand2);
7160 cpu.setOverflowFlag(false);
7161 cpu.setCarryFlag(true);
7162 } else {
7163 cpu.setOverflowFlag((int)result, operand1, operand2, Processor.OF_ADD_INT);
7164 arithmetic_flags_o32(result, operand1, operand2);
7168 private final void adc_o16_flags(int result, int operand1, int operand2)
7170 if (cpu.getCarryFlag() && (operand2 == 0xffff)) {
7171 arithmetic_flags_o16(result, operand1, operand2);
7172 cpu.setOverflowFlag(false);
7173 cpu.setCarryFlag(true);
7174 } else {
7175 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_ADD_SHORT);
7176 arithmetic_flags_o16(result, operand1, operand2);
7180 private final void adc_o8_flags(int result, int operand1, int operand2)
7182 if (cpu.getCarryFlag() && (operand2 == 0xff)) {
7183 arithmetic_flags_o8(result, operand1, operand2);
7184 cpu.setOverflowFlag(false);
7185 cpu.setCarryFlag(true);
7186 } else {
7187 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_ADD_BYTE);
7188 arithmetic_flags_o8(result, operand1, operand2);
7192 private final void sub_o32_flags(long result, int operand1, int operand2)
7194 result = (0xffffffffl & operand1) - (0xffffffffl & operand2);
7196 arithmetic_flags_o32(result, operand1, operand2);
7197 cpu.setOverflowFlag((int)result, operand1, operand2, Processor.OF_SUB_INT);
7200 private final void sub_o16_flags(int result, int operand1, int operand2)
7202 arithmetic_flags_o16(result, operand1, operand2);
7203 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_SUB_SHORT);
7206 private final void sub_o8_flags(int result, int operand1, int operand2)
7208 arithmetic_flags_o8(result, operand1, operand2);
7209 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_SUB_BYTE);
7212 private final void sbb_o32_flags(long result, int operand1, int operand2)
7214 int carry = (cpu.getCarryFlag() ? 1 : 0);
7215 result = (0xffffffffl & operand1) - ((0xffffffffl & operand2) + carry);
7217 cpu.setOverflowFlag((int)result, operand1, operand2, Processor.OF_SUB_INT);
7218 arithmetic_flags_o32(result, operand1, operand2);
7221 private final void sbb_o16_flags(int result, int operand1, int operand2)
7223 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_SUB_SHORT);
7224 arithmetic_flags_o16(result, operand1, operand2);
7227 private final void sbb_o8_flags(int result, int operand1, int operand2)
7229 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_SUB_BYTE);
7230 arithmetic_flags_o8(result, operand1, operand2);
7233 private final void dec_flags(int result)
7235 cpu.setZeroFlag(result);
7236 cpu.setParityFlag(result);
7237 cpu.setSignFlag(result);
7238 cpu.setOverflowFlag(result, Processor.OF_MAX_INT);
7239 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_MAX);
7242 private final void dec_flags(short result)
7244 cpu.setZeroFlag(result);
7245 cpu.setParityFlag(result);
7246 cpu.setSignFlag(result);
7247 cpu.setOverflowFlag(result, Processor.OF_MAX_SHORT);
7248 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_MAX);
7251 private final void dec_flags(byte result)
7253 cpu.setZeroFlag(result);
7254 cpu.setParityFlag(result);
7255 cpu.setSignFlag(result);
7256 cpu.setOverflowFlag(result, Processor.OF_MAX_BYTE);
7257 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_MAX);
7260 private final void inc_flags(int result)
7262 cpu.setZeroFlag(result);
7263 cpu.setParityFlag(result);
7264 cpu.setSignFlag(result);
7265 cpu.setOverflowFlag(result, Processor.OF_MIN_INT);
7266 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_ZERO);
7269 private final void inc_flags(short result)
7271 cpu.setZeroFlag(result);
7272 cpu.setParityFlag(result);
7273 cpu.setSignFlag(result);
7274 cpu.setOverflowFlag(result, Processor.OF_MIN_SHORT);
7275 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_ZERO);
7278 private final void inc_flags(byte result)
7280 cpu.setZeroFlag(result);
7281 cpu.setParityFlag(result);
7282 cpu.setSignFlag(result);
7283 cpu.setOverflowFlag(result, Processor.OF_MIN_BYTE);
7284 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_ZERO);
7287 private final void shl_flags(byte result, byte initial, int count)
7289 if (count > 0) {
7290 cpu.setCarryFlag(initial, count, Processor.CY_SHL_OUTBIT_BYTE);
7292 if (count == 1)
7293 cpu.setOverflowFlag(result, Processor.OF_BIT7_XOR_CARRY);
7295 cpu.setZeroFlag(result);
7296 cpu.setParityFlag(result);
7297 cpu.setSignFlag(result);
7301 private final void shl_flags(short result, short initial, int count)
7303 if (count > 0) {
7304 cpu.setCarryFlag(initial, count, Processor.CY_SHL_OUTBIT_SHORT);
7306 if (count == 1)
7307 cpu.setOverflowFlag(result, Processor.OF_BIT15_XOR_CARRY);
7309 cpu.setZeroFlag(result);
7310 cpu.setParityFlag(result);
7311 cpu.setSignFlag(result);
7315 private final void shl_flags(int result, int initial, int count)
7317 if (count > 0) {
7318 cpu.setCarryFlag(initial, count, Processor.CY_SHL_OUTBIT_INT);
7320 if (count == 1)
7321 cpu.setOverflowFlag(result, Processor.OF_BIT31_XOR_CARRY);
7323 cpu.setZeroFlag(result);
7324 cpu.setParityFlag(result);
7325 cpu.setSignFlag(result);
7329 private final void shr_flags(byte result, int initial, int count)
7331 if (count > 0) {
7332 cpu.setCarryFlag(initial, count, Processor.CY_SHR_OUTBIT);
7334 if (count == 1)
7335 cpu.setOverflowFlag(result, initial, Processor.OF_BIT7_DIFFERENT);
7337 cpu.setZeroFlag(result);
7338 cpu.setParityFlag(result);
7339 cpu.setSignFlag(result);
7343 private final void shr_flags(short result, int initial, int count)
7345 if (count > 0) {
7346 cpu.setCarryFlag(initial, count, Processor.CY_SHR_OUTBIT);
7348 if (count == 1)
7349 cpu.setOverflowFlag(result, initial, Processor.OF_BIT15_DIFFERENT);
7351 cpu.setZeroFlag(result);
7352 cpu.setParityFlag(result);
7353 cpu.setSignFlag(result);
7357 private final void shr_flags(int result, int initial, int count)
7359 if (count > 0) {
7360 cpu.setCarryFlag(initial, count, Processor.CY_SHR_OUTBIT);
7362 if (count == 1)
7363 cpu.setOverflowFlag(result, initial, Processor.OF_BIT31_DIFFERENT);
7365 cpu.setZeroFlag(result);
7366 cpu.setParityFlag(result);
7367 cpu.setSignFlag(result);
7372 private final void sar_flags(byte result, byte initial, int count)
7374 if (count > 0) {
7375 cpu.setCarryFlag(initial, count, Processor.CY_SHR_OUTBIT);
7376 if (count == 1) cpu.setOverflowFlag(false);
7378 cpu.setSignFlag(result);
7379 cpu.setZeroFlag(result);
7380 cpu.setParityFlag(result);
7384 private final void sar_flags(short result, short initial, int count)
7386 if (count > 0) {
7387 cpu.setCarryFlag(initial, count, Processor.CY_SHR_OUTBIT);
7388 if (count == 1) cpu.setOverflowFlag(false);
7390 cpu.setSignFlag(result);
7391 cpu.setZeroFlag(result);
7392 cpu.setParityFlag(result);
7396 private final void sar_flags(int result, int initial, int count)
7398 if (count > 0) {
7399 cpu.setCarryFlag(initial, count, Processor.CY_SHR_OUTBIT);
7400 if (count == 1) cpu.setOverflowFlag(false);
7402 cpu.setSignFlag(result);
7403 cpu.setZeroFlag(result);
7404 cpu.setParityFlag(result);
7408 private final void rol_flags(byte result, int count)
7410 if (count > 0) {
7411 cpu.setCarryFlag(result, Processor.CY_LOWBIT);
7412 if (count == 1)
7413 cpu.setOverflowFlag(result, Processor.OF_BIT7_XOR_CARRY);
7417 private final void rol_flags(short result, int count)
7419 if (count > 0) {
7420 cpu.setCarryFlag(result, Processor.CY_LOWBIT);
7421 if (count == 1)
7422 cpu.setOverflowFlag(result, Processor.OF_BIT15_XOR_CARRY);
7426 private final void rol_flags(int result, int count)
7428 if (count > 0) {
7429 cpu.setCarryFlag(result, Processor.CY_LOWBIT);
7430 if (count == 1)
7431 cpu.setOverflowFlag(result, Processor.OF_BIT31_XOR_CARRY);
7435 private final void ror_flags(byte result, int count)
7437 if (count > 0) {
7438 cpu.setCarryFlag(result, Processor.CY_HIGHBIT_BYTE);
7439 if (count == 1)
7440 cpu.setOverflowFlag(result, Processor.OF_BIT6_XOR_CARRY);
7444 private final void ror_flags(short result, int count)
7446 if (count > 0) {
7447 cpu.setCarryFlag(result, Processor.CY_HIGHBIT_SHORT);
7448 if (count == 1)
7449 cpu.setOverflowFlag(result, Processor.OF_BIT14_XOR_CARRY);
7453 private final void ror_flags(int result, int count)
7455 if (count > 0) {
7456 cpu.setCarryFlag(result, Processor.CY_HIGHBIT_INT);
7457 if (count == 1)
7458 cpu.setOverflowFlag(result, Processor.OF_BIT30_XOR_CARRY);
7462 private final void rcl_o8_flags(int result, int count)
7464 if (count > 0) {
7465 cpu.setCarryFlag(result, Processor.CY_OFFENDBIT_BYTE);
7466 if (count == 1)
7467 cpu.setOverflowFlag(result, Processor.OF_BIT7_XOR_CARRY);
7471 private final void rcl_o16_flags(int result, int count)
7473 if (count > 0) {
7474 cpu.setCarryFlag(result, Processor.CY_OFFENDBIT_SHORT);
7475 if (count == 1)
7476 cpu.setOverflowFlag(result, Processor.OF_BIT15_XOR_CARRY);
7480 private final void rcl_o32_flags(long result, int count)
7482 if (count > 0) {
7483 cpu.setCarryFlag(result, Processor.CY_OFFENDBIT_INT);
7484 if (count == 1)
7485 cpu.setOverflowFlag((int) result, Processor.OF_BIT31_XOR_CARRY);
7489 private final void rcr_o8_flags(int result, int count, int overflow)
7491 if (count > 0) {
7492 cpu.setCarryFlag(result, Processor.CY_OFFENDBIT_BYTE);
7493 if (count == 1)
7494 cpu.setOverflowFlag(overflow > 0);
7498 private final void rcr_o16_flags(int result, int count, int overflow)
7500 if (count > 0) {
7501 cpu.setCarryFlag(result, Processor.CY_OFFENDBIT_SHORT);
7502 if (count == 1)
7503 cpu.setOverflowFlag(overflow > 0);
7507 private final void rcr_o32_flags(long result, int count, int overflow)
7509 if (count > 0) {
7510 cpu.setCarryFlag(result, Processor.CY_OFFENDBIT_INT);
7511 if (count == 1)
7512 cpu.setOverflowFlag(overflow > 0);
7516 private final void neg_flags(byte result)
7518 cpu.setCarryFlag(result, Processor.CY_NZ);
7519 cpu.setOverflowFlag(result, Processor.OF_MIN_BYTE);
7521 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_NZERO);
7522 cpu.setZeroFlag(result);
7523 cpu.setParityFlag(result);
7524 cpu.setSignFlag(result);
7527 private final void neg_flags(short result)
7529 cpu.setCarryFlag(result, Processor.CY_NZ);
7530 cpu.setOverflowFlag(result, Processor.OF_MIN_SHORT);
7532 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_NZERO);
7533 cpu.setZeroFlag(result);
7534 cpu.setParityFlag(result);
7535 cpu.setSignFlag(result);
7538 private final void neg_flags(int result)
7540 cpu.setCarryFlag(result, Processor.CY_NZ);
7541 cpu.setOverflowFlag(result, Processor.OF_MIN_INT);
7543 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_NZERO);
7544 cpu.setZeroFlag(result);
7545 cpu.setParityFlag(result);
7546 cpu.setSignFlag(result);
7549 private final Segment loadSegment(int selector)
7551 selector &= 0xffff;
7552 if (selector < 0x4)
7553 return SegmentFactory.NULL_SEGMENT;
7555 Segment s = cpu.getSegment(selector);
7556 if (!s.isPresent())
7557 throw new ProcessorException(ProcessorException.Type.NOT_PRESENT, selector, true);
7558 return s;
7561 private final boolean checkIOPermissionsByte(int ioportAddress)
7563 if (cpu.getCPL() <= cpu.eflagsIOPrivilegeLevel)
7564 return true;
7566 int ioPermMapBaseAddress = 0xffff & cpu.tss.getWord(102);
7567 try {
7568 byte ioPermMapByte = cpu.tss.getByte(ioPermMapBaseAddress + (ioportAddress >>> 3));
7569 return (ioPermMapByte & (0x1 << (ioportAddress & 0x7))) == 0;
7570 } catch (ProcessorException p) {
7571 if (p.getType() == ProcessorException.Type.GENERAL_PROTECTION)
7572 return false;
7573 else
7574 throw p;
7578 private final boolean checkIOPermissionsShort(int ioportAddress)
7580 if (cpu.getCPL() <= cpu.eflagsIOPrivilegeLevel)
7581 return true;
7583 int ioPermMapBaseAddress = 0xffff & cpu.tss.getWord(102);
7584 try {
7585 short ioPermMapShort = cpu.tss.getWord(ioPermMapBaseAddress + (ioportAddress >>> 3));
7586 return (ioPermMapShort & (0x3 << (ioportAddress & 0x7))) == 0;
7587 } catch (ProcessorException p) {
7588 if (p.getType() == ProcessorException.Type.GENERAL_PROTECTION)
7589 return false;
7590 else
7591 throw p;
7595 private final boolean checkIOPermissionsInt(int ioportAddress)
7597 if (cpu.getCPL() <= cpu.eflagsIOPrivilegeLevel)
7598 return true;
7600 int ioPermMapBaseAddress = 0xffff & cpu.tss.getWord(102);
7601 try {
7602 short ioPermMapShort = cpu.tss.getWord(ioPermMapBaseAddress + (ioportAddress >>> 3));
7603 return (ioPermMapShort & (0xf << (ioportAddress & 0x7))) == 0;
7604 } catch (ProcessorException p) {
7605 if (p.getType() == ProcessorException.Type.GENERAL_PROTECTION)
7606 return false;
7607 else
7608 throw p;
7612 //borrowed from the j2se api as not in midp
7613 private static int numberOfTrailingZeros(int i) {
7614 // HD, Figure 5-14
7615 int y;
7616 if (i == 0) return 32;
7617 int n = 31;
7618 y = i <<16; if (y != 0) { n = n -16; i = y; }
7619 y = i << 8; if (y != 0) { n = n - 8; i = y; }
7620 y = i << 4; if (y != 0) { n = n - 4; i = y; }
7621 y = i << 2; if (y != 0) { n = n - 2; i = y; }
7622 return n - ((i << 1) >>> 31);
7625 private static int numberOfLeadingZeros(int i) {
7626 // HD, Figure 5-6
7627 if (i == 0)
7628 return 32;
7629 int n = 1;
7630 if (i >>> 16 == 0) { n += 16; i <<= 16; }
7631 if (i >>> 24 == 0) { n += 8; i <<= 8; }
7632 if (i >>> 28 == 0) { n += 4; i <<= 4; }
7633 if (i >>> 30 == 0) { n += 2; i <<= 2; }
7634 n -= i >>> 31;
7635 return n;
7638 private static int reverseBytes(int i) {
7639 return ((i >>> 24) ) |
7640 ((i >> 8) & 0xFF00) |
7641 ((i << 8) & 0xFF0000) |
7642 ((i << 24));