Refactor system flags
[jpcrr.git] / org / jpc / emulator / memory / codeblock / optimised / Virtual8086ModeUBlock.java
blob6bf1b8ed64343d0ff00e9e4d0217b515379d720a
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;
37 import static org.jpc.emulator.memory.codeblock.optimised.MicrocodeSet.*;
39 /**
41 * @author Chris Dennis
43 public class Virtual8086ModeUBlock implements Virtual8086ModeCodeBlock
45 private static final boolean[] parityMap;
47 static
49 parityMap = new boolean[256];
50 for (int i = 0; i < parityMap.length; i++)
51 parityMap[i] = ((Integer.bitCount(i) & 0x1) == 0);
54 private Processor cpu;
55 private FpuState fpu;
57 private int x86Count;
59 protected int[] microcodes;
60 protected int[] cumulativeX86Length;
61 private int executeCount;
62 public static OpcodeLogger opcodeCounter = null;//new OpcodeLogger("VM86 Stats:");
64 public Virtual8086ModeUBlock()
68 public Virtual8086ModeUBlock(int[] microcodes, int[] x86lengths)
70 this.microcodes = microcodes;
71 cumulativeX86Length = x86lengths;
72 if (cumulativeX86Length.length == 0)
73 x86Count = 0;
74 else {
75 int count = 1;
76 for (int i = 1; i < cumulativeX86Length.length; i++) {
77 if (cumulativeX86Length[i] > cumulativeX86Length[i-1]) count++;
79 x86Count = count;
83 public int getX86Length()
85 if (microcodes.length == 0)
86 return 0;
87 return cumulativeX86Length[microcodes.length-1];
90 public int getX86Count()
92 return x86Count;
95 public String getDisplayString()
97 StringBuilder buf = new StringBuilder();
98 buf.append(this.toString()).append('\n');
99 for (int i=0; i<microcodes.length; i++)
100 buf.append(i).append(": ").append(microcodes[i]).append('\n');
101 return buf.toString();
104 public boolean handleMemoryRegionChange(int startAddress, int endAddress)
106 return false;
108 public void invalidate()
110 invalidated = true;
113 public String toString()
115 return "Virtual8086 Mode Interpreted Block: "+hashCode();
118 public InstructionSource getAsInstructionSource()
120 int[] codes = new int[microcodes.length];
121 int[] positions = new int[microcodes.length];
122 System.arraycopy(microcodes, 0, codes, 0, codes.length);
123 System.arraycopy(cumulativeX86Length, 0, positions, 0, positions.length);
125 return new ArrayBackedInstructionSource(codes, positions);
128 public int[] getMicrocodes()
130 int[] result = new int[microcodes.length];
131 System.arraycopy(microcodes, 0, result, 0, result.length);
132 return result;
135 private Segment transferSeg0 = null;
136 private int transferAddr0 = 0;
137 private int transferReg0 = 0, transferReg1 = 0, transferReg2 = 0;
138 private long transferReg0l = 0;
139 private boolean transferEipUpdated = false;
140 private int transferPosition = 0;
142 private boolean invalidated = false;
144 private int uCodeXferReg0 = 0, uCodeXferReg1 = 0, uCodeXferReg2 = 0;
145 private boolean uCodeXferLoaded = false;
147 private void fullExecute(Processor cpu)
149 FpuState fpu = cpu.fpu;
151 //recover variables from instance storage
152 Segment seg0 = transferSeg0;
153 int addr0 = transferAddr0;
154 int reg0 = transferReg0, reg1 = transferReg1, reg2 = transferReg2;
155 long reg0l = transferReg0l;
157 boolean eipUpdated = transferEipUpdated;
158 int position = transferPosition;
160 try {
161 switch (microcodes[position++]) {
162 case EIP_UPDATE:
163 if (!eipUpdated) {
164 eipUpdated = true;
165 cpu.eip += cumulativeX86Length[position - 1];
167 break;
169 case UNDEFINED: throw ProcessorException.UNDEFINED;
171 case MEM_RESET: addr0 = 0; seg0 = null; break;
173 case LOAD0_EAX: reg0 = cpu.eax; break;
174 case LOAD0_ECX: reg0 = cpu.ecx; break;
175 case LOAD0_EDX: reg0 = cpu.edx; break;
176 case LOAD0_EBX: reg0 = cpu.ebx; break;
177 case LOAD0_ESP: reg0 = cpu.esp; break;
178 case LOAD0_EBP: reg0 = cpu.ebp; break;
179 case LOAD0_ESI: reg0 = cpu.esi; break;
180 case LOAD0_EDI: reg0 = cpu.edi; break;
182 case STORE0_EAX: cpu.eax = reg0; break;
183 case STORE0_ECX: cpu.ecx = reg0; break;
184 case STORE0_EDX: cpu.edx = reg0; break;
185 case STORE0_EBX: cpu.ebx = reg0; break;
186 case STORE0_ESP: cpu.esp = reg0; break;
187 case STORE0_EBP: cpu.ebp = reg0; break;
188 case STORE0_ESI: cpu.esi = reg0; break;
189 case STORE0_EDI: cpu.edi = reg0; break;
191 case LOAD1_EAX: reg1 = cpu.eax; break;
192 case LOAD1_ECX: reg1 = cpu.ecx; break;
193 case LOAD1_EDX: reg1 = cpu.edx; break;
194 case LOAD1_EBX: reg1 = cpu.ebx; break;
195 case LOAD1_ESP: reg1 = cpu.esp; break;
196 case LOAD1_EBP: reg1 = cpu.ebp; break;
197 case LOAD1_ESI: reg1 = cpu.esi; break;
198 case LOAD1_EDI: reg1 = cpu.edi; break;
200 case STORE1_EAX: cpu.eax = reg1; break;
201 case STORE1_ECX: cpu.ecx = reg1; break;
202 case STORE1_EDX: cpu.edx = reg1; break;
203 case STORE1_EBX: cpu.ebx = reg1; break;
204 case STORE1_ESP: cpu.esp = reg1; break;
205 case STORE1_EBP: cpu.ebp = reg1; break;
206 case STORE1_ESI: cpu.esi = reg1; break;
207 case STORE1_EDI: cpu.edi = reg1; break;
209 case LOAD0_AX: reg0 = cpu.eax & 0xffff; break;
210 case LOAD0_CX: reg0 = cpu.ecx & 0xffff; break;
211 case LOAD0_DX: reg0 = cpu.edx & 0xffff; break;
212 case LOAD0_BX: reg0 = cpu.ebx & 0xffff; break;
213 case LOAD0_SP: reg0 = cpu.esp & 0xffff; break;
214 case LOAD0_BP: reg0 = cpu.ebp & 0xffff; break;
215 case LOAD0_SI: reg0 = cpu.esi & 0xffff; break;
216 case LOAD0_DI: reg0 = cpu.edi & 0xffff; break;
218 case STORE0_AX: cpu.eax = (cpu.eax & ~0xffff) | (reg0 & 0xffff); break;
219 case STORE0_CX: cpu.ecx = (cpu.ecx & ~0xffff) | (reg0 & 0xffff); break;
220 case STORE0_DX: cpu.edx = (cpu.edx & ~0xffff) | (reg0 & 0xffff); break;
221 case STORE0_BX: cpu.ebx = (cpu.ebx & ~0xffff) | (reg0 & 0xffff); break;
222 case STORE0_SP: cpu.esp = (cpu.esp & ~0xffff) | (reg0 & 0xffff); break;
223 case STORE0_BP: cpu.ebp = (cpu.ebp & ~0xffff) | (reg0 & 0xffff); break;
224 case STORE0_SI: cpu.esi = (cpu.esi & ~0xffff) | (reg0 & 0xffff); break;
225 case STORE0_DI: cpu.edi = (cpu.edi & ~0xffff) | (reg0 & 0xffff); break;
227 case STORE1_AX: cpu.eax = (cpu.eax & ~0xffff) | (reg1 & 0xffff); break;
228 case STORE1_CX: cpu.ecx = (cpu.ecx & ~0xffff) | (reg1 & 0xffff); break;
229 case STORE1_DX: cpu.edx = (cpu.edx & ~0xffff) | (reg1 & 0xffff); break;
230 case STORE1_BX: cpu.ebx = (cpu.ebx & ~0xffff) | (reg1 & 0xffff); break;
231 case STORE1_SP: cpu.esp = (cpu.esp & ~0xffff) | (reg1 & 0xffff); break;
232 case STORE1_BP: cpu.ebp = (cpu.ebp & ~0xffff) | (reg1 & 0xffff); break;
233 case STORE1_SI: cpu.esi = (cpu.esi & ~0xffff) | (reg1 & 0xffff); break;
234 case STORE1_DI: cpu.edi = (cpu.edi & ~0xffff) | (reg1 & 0xffff); break;
236 case LOAD1_AX: reg1 = cpu.eax & 0xffff; break;
237 case LOAD1_CX: reg1 = cpu.ecx & 0xffff; break;
238 case LOAD1_DX: reg1 = cpu.edx & 0xffff; break;
239 case LOAD1_SP: reg1 = cpu.esp & 0xffff; break;
240 case LOAD1_BP: reg1 = cpu.ebp & 0xffff; break;
241 case LOAD1_SI: reg1 = cpu.esi & 0xffff; break;
242 case LOAD1_DI: reg1 = cpu.edi & 0xffff; break;
244 case LOAD0_AL: reg0 = cpu.eax & 0xff; break;
245 case LOAD0_CL: reg0 = cpu.ecx & 0xff; break;
246 case LOAD0_DL: reg0 = cpu.edx & 0xff; break;
247 case LOAD0_BL: reg0 = cpu.ebx & 0xff; break;
248 case LOAD0_AH: reg0 = (cpu.eax >> 8) & 0xff; break;
249 case LOAD0_CH: reg0 = (cpu.ecx >> 8) & 0xff; break;
250 case LOAD0_DH: reg0 = (cpu.edx >> 8) & 0xff; break;
251 case LOAD0_BH: reg0 = (cpu.ebx >> 8) & 0xff; break;
253 case STORE0_AL: cpu.eax = (cpu.eax & ~0xff) | (reg0 & 0xff); break;
254 case STORE0_CL: cpu.ecx = (cpu.ecx & ~0xff) | (reg0 & 0xff); break;
255 case STORE0_DL: cpu.edx = (cpu.edx & ~0xff) | (reg0 & 0xff); break;
256 case STORE0_AH: cpu.eax = (cpu.eax & ~0xff00) | ((reg0 << 8) & 0xff00); break;
257 case STORE0_CH: cpu.ecx = (cpu.ecx & ~0xff00) | ((reg0 << 8) & 0xff00); break;
258 case STORE0_DH: cpu.edx = (cpu.edx & ~0xff00) | ((reg0 << 8) & 0xff00); break;
259 case STORE0_BH: cpu.ebx = (cpu.ebx & ~0xff00) | ((reg0 << 8) & 0xff00); break;
261 case LOAD1_AL: reg1 = cpu.eax & 0xff; break;
262 case LOAD1_CL: reg1 = cpu.ecx & 0xff; break;
263 case LOAD1_DL: reg1 = cpu.edx & 0xff; break;
264 case LOAD1_BL: reg1 = cpu.ebx & 0xff; break;
265 case LOAD1_AH: reg1 = (cpu.eax >> 8) & 0xff; break;
266 case LOAD1_CH: reg1 = (cpu.ecx >> 8) & 0xff; break;
267 case LOAD1_DH: reg1 = (cpu.edx >> 8) & 0xff; break;
268 case LOAD1_BH: reg1 = (cpu.ebx >> 8) & 0xff; break;
270 case STORE1_AL: cpu.eax = (cpu.eax & ~0xff) | (reg1 & 0xff); break;
271 case STORE1_CL: cpu.ecx = (cpu.ecx & ~0xff) | (reg1 & 0xff); break;
272 case STORE1_DL: cpu.edx = (cpu.edx & ~0xff) | (reg1 & 0xff); break;
273 case STORE1_BL: cpu.ebx = (cpu.ebx & ~0xff) | (reg1 & 0xff); break;
274 case STORE1_AH: cpu.eax = (cpu.eax & ~0xff00) | ((reg1 << 8) & 0xff00); break;
275 case STORE1_CH: cpu.ecx = (cpu.ecx & ~0xff00) | ((reg1 << 8) & 0xff00); break;
276 case STORE1_DH: cpu.edx = (cpu.edx & ~0xff00) | ((reg1 << 8) & 0xff00); break;
277 case STORE1_BH: cpu.ebx = (cpu.ebx & ~0xff00) | ((reg1 << 8) & 0xff00); break;
279 case LOAD0_CR0: throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION,0,true);
280 case LOAD0_CR2: throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION,0,true);
281 case LOAD0_CR3: throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION,0,true);
282 case LOAD0_CR4: throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION,0,true);
284 case STORE0_CR0: throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION,0,true);
285 case STORE0_CR2: throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION,0,true);
286 case STORE0_CR3: throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION,0,true);
287 case STORE0_CR4: throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION,0,true);
289 case LOAD0_ES: reg0 = 0xffff & cpu.es.getSelector(); break;
290 case LOAD0_CS: reg0 = 0xffff & cpu.cs.getSelector(); break;
291 case LOAD0_SS: reg0 = 0xffff & cpu.ss.getSelector(); break;
292 case LOAD0_DS: reg0 = 0xffff & cpu.ds.getSelector(); break;
293 case LOAD0_FS: reg0 = 0xffff & cpu.fs.getSelector(); break;
294 case LOAD0_GS: reg0 = 0xffff & cpu.gs.getSelector(); break;
296 case STORE0_ES: cpu.es.setSelector(0xffff & reg0); break;
297 case STORE0_CS: cpu.cs.setSelector(0xffff & reg0); break;
298 case STORE0_SS: cpu.ss.setSelector(0xffff & reg0); break;
299 case STORE0_DS: cpu.ds.setSelector(0xffff & reg0); break;
300 case STORE0_FS: cpu.fs.setSelector(0xffff & reg0); break;
301 case STORE0_GS: cpu.gs.setSelector(0xffff & reg0); break;
303 case STORE1_CS: cpu.cs.setSelector(0xffff & reg1); break;
304 case STORE1_SS: cpu.ss.setSelector(0xffff & reg1); break;
305 case STORE1_DS: cpu.ds.setSelector(0xffff & reg1); break;
306 case STORE1_FS: cpu.fs.setSelector(0xffff & reg1); break;
307 case STORE1_GS: cpu.gs.setSelector(0xffff & reg1); break;
309 case STORE0_FLAGS: cpu.setEFlags((cpu.getEFlags() & ~0xcfff) | (reg0 & 0xcfff)); break;
310 case STORE0_EFLAGS: cpu.setEFlags((cpu.getEFlags() & ~0x24cfff) | (reg0 & 0x24cfff)); break;
312 case LOAD0_FLAGS: reg0 = 0xffff & cpu.getEFlags(); break;
313 case LOAD0_EFLAGS: reg0 = cpu.getEFlags(); break;
315 case LOAD0_IB: reg0 = microcodes[position++] & 0xff; break;
316 case LOAD0_IW: reg0 = microcodes[position++] & 0xffff; break;
317 case LOAD0_ID: reg0 = microcodes[position++]; break;
319 case LOAD1_IB: reg1 = microcodes[position++] & 0xff; break;
320 case LOAD1_IW: reg1 = microcodes[position++] & 0xffff; break;
321 case LOAD1_ID: reg1 = microcodes[position++]; break;
323 case LOAD2_EAX: reg2 = cpu.eax; break;
324 case LOAD2_AX: reg2 = 0xffff & cpu.eax; break;
325 case LOAD2_AL: reg2 = 0xff & cpu.eax; break;
326 case LOAD2_CL: reg2 = 0xff & cpu.ecx; break;
327 case LOAD2_IB: reg2 = 0xff & microcodes[position++]; break;
329 case LOAD_SEG_ES: seg0 = cpu.es; break;
330 case LOAD_SEG_CS: seg0 = cpu.cs; break;
331 case LOAD_SEG_SS: seg0 = cpu.ss; break;
332 case LOAD_SEG_DS: seg0 = cpu.ds; break;
333 case LOAD_SEG_FS: seg0 = cpu.fs; break;
334 case LOAD_SEG_GS: seg0 = cpu.gs; break;
336 case ADDR_EAX: addr0 += cpu.eax; break;
337 case ADDR_ECX: addr0 += cpu.ecx; break;
338 case ADDR_EDX: addr0 += cpu.edx; break;
339 case ADDR_EBX: addr0 += cpu.ebx; break;
340 case ADDR_ESP: addr0 += cpu.esp; break;
341 case ADDR_EBP: addr0 += cpu.ebp; break;
342 case ADDR_ESI: addr0 += cpu.esi; break;
343 case ADDR_EDI: addr0 += cpu.edi; break;
345 case ADDR_AX: addr0 += ((short)cpu.eax); break;
346 case ADDR_CX: addr0 += ((short)cpu.ecx); break;
347 case ADDR_DX: addr0 += ((short)cpu.edx); break;
348 case ADDR_BX: addr0 += ((short)cpu.ebx); break;
349 case ADDR_SP: addr0 += ((short)cpu.esp); break;
350 case ADDR_BP: addr0 += ((short)cpu.ebp); break;
351 case ADDR_SI: addr0 += ((short)cpu.esi); break;
352 case ADDR_DI: addr0 += ((short)cpu.edi); break;
354 case ADDR_2EAX: addr0 += (cpu.eax << 1); break;
355 case ADDR_2ECX: addr0 += (cpu.ecx << 1); break;
356 case ADDR_2EDX: addr0 += (cpu.edx << 1); break;
357 case ADDR_2EBX: addr0 += (cpu.ebx << 1); break;
358 case ADDR_2ESP: addr0 += (cpu.esp << 1); break;
359 case ADDR_2EBP: addr0 += (cpu.ebp << 1); break;
360 case ADDR_2ESI: addr0 += (cpu.esi << 1); break;
361 case ADDR_2EDI: addr0 += (cpu.edi << 1); break;
363 case ADDR_4EAX: addr0 += (cpu.eax << 2); break;
364 case ADDR_4ECX: addr0 += (cpu.ecx << 2); break;
365 case ADDR_4EDX: addr0 += (cpu.edx << 2); break;
366 case ADDR_4EBX: addr0 += (cpu.ebx << 2); break;
367 case ADDR_4ESP: addr0 += (cpu.esp << 2); break;
368 case ADDR_4EBP: addr0 += (cpu.ebp << 2); break;
369 case ADDR_4ESI: addr0 += (cpu.esi << 2); break;
370 case ADDR_4EDI: addr0 += (cpu.edi << 2); break;
372 case ADDR_8EAX: addr0 += (cpu.eax << 3); break;
373 case ADDR_8ECX: addr0 += (cpu.ecx << 3); break;
374 case ADDR_8EDX: addr0 += (cpu.edx << 3); break;
375 case ADDR_8EBX: addr0 += (cpu.ebx << 3); break;
376 case ADDR_8ESP: addr0 += (cpu.esp << 3); break;
377 case ADDR_8EBP: addr0 += (cpu.ebp << 3); break;
378 case ADDR_8ESI: addr0 += (cpu.esi << 3); break;
379 case ADDR_8EDI: addr0 += (cpu.edi << 3); break;
381 case ADDR_IB: addr0 += ((byte)microcodes[position++]); break;
382 case ADDR_IW: addr0 += ((short)microcodes[position++]); break;
383 case ADDR_ID: addr0 += microcodes[position++]; break;
385 case ADDR_MASK16: addr0 &= 0xffff; break;
387 case ADDR_uAL: addr0 += 0xff & cpu.eax; break;
389 case LOAD0_ADDR: reg0 = addr0; break;
391 case LOAD0_MEM_BYTE: reg0 = 0xff & seg0.getByte(addr0); break;
392 case LOAD0_MEM_WORD: reg0 = 0xffff & seg0.getWord(addr0); break;
393 case LOAD0_MEM_DWORD: reg0 = seg0.getDoubleWord(addr0); break;
394 case LOAD0_MEM_QWORD: reg0l = seg0.getQuadWord(addr0); break;
396 case LOAD1_MEM_BYTE: reg1 = 0xff & seg0.getByte(addr0); break;
397 case LOAD1_MEM_WORD: reg1 = 0xffff & seg0.getWord(addr0); break;
398 case LOAD1_MEM_DWORD: reg1 = seg0.getDoubleWord(addr0); break;
400 case STORE0_MEM_BYTE: seg0.setByte(addr0, (byte)reg0); break;
401 case STORE0_MEM_WORD: seg0.setWord(addr0, (short)reg0); break;
402 case STORE0_MEM_DWORD: seg0.setDoubleWord(addr0, reg0); break;
403 case STORE0_MEM_QWORD: seg0.setQuadWord(addr0, reg0); break;
405 case STORE1_MEM_BYTE: seg0.setByte(addr0, (byte)reg1); break;
406 case STORE1_MEM_WORD: seg0.setWord(addr0, (short)reg1); break;
407 case STORE1_MEM_DWORD: seg0.setDoubleWord(addr0, reg1); break;
409 case JUMP_FAR_O16: jump_far_o16(reg0, reg1); break;
410 case JUMP_FAR_O32: jump_far_o32(reg0, reg1); break;
412 case JUMP_ABS_O16: cpu.eip = reg0; break;
414 case CALL_FAR_O16: call_far_o16_a16(reg0, reg1); break;
416 case CALL_ABS_O16: call_abs_o16_a16(reg0); break;
418 case JUMP_O8: jump_o8((byte)reg0); break;
419 case JUMP_O16: jump_o16((short)reg0); break;
420 case JUMP_O32: jump_o32(reg0); break;
422 case INT_O16: int_o16_a16(reg0, position); break;
423 case INT3_O16: //call PM exception handler
424 cpu.handleSoftProtectedModeInterrupt(3, getInstructionLength(position));
425 break;
427 case IRET_O16: reg0 = iret_o16_a16(); break; //returns flags
429 case IN_O8: reg0 = in_o8(reg0); break;
430 case IN_O16: reg0 = in_o16(reg0); break;
431 case IN_O32: reg0 = in_o32(reg0); break;
433 case OUT_O8: out_o8(reg0, reg1); break;
434 case OUT_O16: out_o16(reg0, reg1); break;
435 case OUT_O32: out_o32(reg0, reg1); break;
437 case XOR: reg0 ^= reg1; break;
438 case AND: reg0 &= reg1; break;
439 case NOT: reg0 = ~reg0; break;
441 case SUB: reg2 = reg0; reg0 = reg2 - reg1; break;
442 case SBB: reg2 = reg0; reg0 = reg2 - (reg1 + (cpu.getCarryFlag() ? 1 : 0)); break;
443 case ADD: reg2 = reg0; reg0 = reg2 + reg1; break;
444 case ADC: reg2 = reg0; reg0 = reg2 + reg1 + (cpu.getCarryFlag() ? 1 : 0); break;
445 case NEG: reg0 = -reg0; break;
447 case MUL_O8: mul_o8(reg0); break;
448 case MUL_O16: mul_o16(reg0); break;
449 case MUL_O32: mul_o32(reg0); break;
451 case IMULA_O8: imula_o8((byte)reg0); break;
452 case IMULA_O16: imula_o16((short)reg0); break;
453 case IMULA_O32: imula_o32(reg0); break;
455 case IMUL_O16: reg0 = imul_o16((short)reg0, (short)reg1); break;
456 case IMUL_O32: reg0 = imul_o32(reg0, reg1); break;
458 case DIV_O8: div_o8(reg0); break;
459 case DIV_O16: div_o16(reg0); break;
460 case DIV_O32: div_o32(reg0); break;
462 case IDIV_O8: idiv_o8((byte)reg0); break;
463 case IDIV_O16: idiv_o16((short)reg0); break;
464 case IDIV_O32: idiv_o32(reg0); break;
466 case BSF: reg0 = bsf(reg1, reg0); break;
467 case BSR: reg0 = bsr(reg1, reg0); break;
469 case BT_MEM: bt_mem(reg1, seg0, addr0); break;
470 case BTS_MEM: bts_mem(reg1, seg0, addr0); break;
471 case BTR_MEM: btr_mem(reg1, seg0, addr0); break;
472 case BTC_MEM: btc_mem(reg1, seg0, addr0); break;
474 case BT_O32: reg1 &= 0x1f; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); break;
475 case BT_O16: reg1 &= 0xf; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); break;
476 case BTS_O32: reg1 &= 0x1f; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); reg0 |= (1 << reg1); break;
477 case BTS_O16: reg1 &= 0xf; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); reg0 |= (1 << reg1); break;
478 case BTR_O32: reg1 &= 0x1f; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); reg0 &= ~(1 << reg1); break;
479 case BTR_O16: reg1 &= 0xf; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); reg0 &= ~(1 << reg1); break;
480 case BTC_O32: reg1 &= 0x1f; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); reg0 ^= (1 << reg1); break;
481 case BTC_O16: reg1 &= 0xf; cpu.setCarryFlag(reg0, reg1, Processor.CY_NTH_BIT_SET); reg0 ^= (1 << reg1); break;
483 case ROL_O8: reg2 = reg1 & 0x7; reg0 = (reg0 << reg2) | (reg0 >>> (8 - reg2)); break;
484 case ROL_O16: reg2 = reg1 & 0xf; reg0 = (reg0 << reg2) | (reg0 >>> (16 - reg2)); break;
485 case ROL_O32: reg1 &= 0x1f; reg0 = (reg0 << reg1) | (reg0 >>> (32 - reg1)); break;
487 case ROR_O8: reg1 &= 0x7; reg0 = (reg0 >>> reg1) | (reg0 << (8 - reg1)); break;
488 case ROR_O16: reg1 &= 0xf; reg0 = (reg0 >>> reg1) | (reg0 << (16 - reg1)); break;
489 case ROR_O32: reg1 &= 0x1f; reg0 = (reg0 >>> reg1) | (reg0 << (32 - reg1)); break;
491 case RCL_O8: reg1 &= 0x1f; reg1 %= 9; reg0 |= (cpu.getCarryFlag() ? 0x100 : 0);
492 reg0 = (reg0 << reg1) | (reg0 >>> (9 - reg1)); break;
493 case RCL_O16: reg1 &= 0x1f; reg1 %= 17; reg0 |= (cpu.getCarryFlag() ? 0x10000 : 0);
494 reg0 = (reg0 << reg1) | (reg0 >>> (17 - reg1)); break;
495 case RCL_O32: reg1 &= 0x1f; reg0l = (0xffffffffl & reg0) | (cpu.getCarryFlag() ? 0x100000000l : 0);
496 reg0 = (int)(reg0l = (reg0l << reg1) | (reg0l >>> (33 - reg1))); break;
498 case RCR_O8:
499 reg1 &= 0x1f;
500 reg1 %= 9;
501 reg0 |= (cpu.getCarryFlag() ? 0x100 : 0);
502 reg2 = (cpu.getCarryFlag() ^ ((reg0 & 0x80) != 0) ? 1 : 0);
503 reg0 = (reg0 >>> reg1) | (reg0 << (9 - reg1));
504 break;
505 case RCR_O16:
506 reg1 &= 0x1f;
507 reg1 %= 17;
508 reg2 = (cpu.getCarryFlag() ^ ((reg0 & 0x8000) != 0) ? 1 : 0);
509 reg0 |= (cpu.getCarryFlag() ? 0x10000 : 0);
510 reg0 = (reg0 >>> reg1) | (reg0 << (17 - reg1));
511 break;
512 case RCR_O32:
513 reg1 &= 0x1f;
514 reg0l = (0xffffffffl & reg0) | (cpu.getCarryFlag() ? 0x100000000L : 0);
515 reg2 = (cpu.getCarryFlag() ^ ((reg0 & 0x80000000) != 0) ? 1 : 0);
516 reg0 = (int) (reg0l = (reg0l >>> reg1) | (reg0l << (33 - reg1)));
517 break;
518 case SHR: reg1 &= 0x1f; reg2 = reg0; reg0 >>>= reg1; break;
519 case SAR_O8: reg1 &= 0x1f; reg2 = reg0; reg0 = ((byte)reg0) >> reg1; break;
520 case SAR_O16: reg1 &= 0x1f; reg2 = reg0; reg0 = ((short)reg0) >> reg1; break;
521 case SAR_O32: reg1 &= 0x1f; reg2 = reg0; reg0 >>= reg1; break;
523 case SHLD_O16: {
524 int i = reg0;
525 reg2 &= 0x1f;
526 if (reg2 < 16)
528 reg0 = (reg0 << reg2) | (reg1 >>> (16 - reg2));
529 reg1 = reg2;
530 reg2 = i;
532 else
534 i = (reg1 & 0xFFFF) | (reg0 << 16);
535 reg0 = (reg1 << (reg2 - 16)) | ((reg0 & 0xFFFF) >>> (32 - reg2));
536 reg1 = reg2 - 15;
537 reg2 = i >> 1;
539 } break;
540 case SHLD_O32: {
541 int i = reg0; reg2 &= 0x1f;
542 if (reg2 != 0)
543 reg0 = (reg0 << reg2) | (reg1 >>> (32 - reg2));
544 reg1 = reg2; reg2 = i;
545 } break;
547 case SHRD_O16: {
548 int i = reg0;
549 reg2 &= 0x1f;
550 if (reg2 < 16)
552 reg0 = (reg0 >>> reg2) | (reg1 << (16 - reg2));
553 reg1 = reg2;
554 reg2 = i;
556 else
558 i = (reg0 & 0xFFFF) | (reg1 << 16);
559 reg0 = (reg1 >>> (reg2 - 16)) | (reg0 << (32 - reg2));
560 reg1 = reg2;
561 reg2 = i;
563 } break;
564 case SHRD_O32: {
565 int i = reg0; reg2 &= 0x1f;
566 if (reg2 != 0)
567 reg0 = (reg0 >>> reg2) | (reg1 << (32 - reg2));
568 reg1 = reg2; reg2 = i;
569 } break;
571 case CWD: if ((cpu.eax & 0x8000) == 0) cpu.edx &= 0xffff0000; else cpu.edx |= 0x0000ffff; break;
572 case CDQ: if ((cpu.eax & 0x80000000) == 0) cpu.edx = 0; else cpu.edx = -1; break;
574 case AAA: aaa(); break;
575 case AAD: aad(reg0); break;
576 case AAM: reg0 = aam(reg0); break;
577 case AAS: aas(); break;
579 case DAA: daa(); break;
580 case DAS: das(); break;
582 case BOUND_O16: {
583 short lower = (short)reg0;
584 short upper = (short)(reg0 >> 16);
585 short index = (short)reg1;
586 if ((index < lower) || (index > (upper + 2)))
587 throw ProcessorException.BOUND_RANGE;
588 } break;
590 case LAHF: lahf(); break;
591 case SAHF: sahf(); break;
593 case CLC: cpu.setCarryFlag(false); break;
594 case STC: cpu.setCarryFlag(true); break;
596 case CLI: {
597 if (cpu.eflagsIOPrivilegeLevel == 3)
598 cpu.eflagsInterruptEnable = cpu.eflagsInterruptEnableSoon = false;
599 else
600 if ((cpu.getCR4() & Processor.CR4_VIRTUAL8086_MODE_EXTENSIONS) != 0)
601 cpu.eflagsVirtualInterrupt = false;
602 else
603 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION,0,true);//ProcessorException.GENERAL_PROTECTION_0;
604 } break;
606 case STI: {
607 if (cpu.eflagsIOPrivilegeLevel == 3)
608 cpu.eflagsInterruptEnable = cpu.eflagsInterruptEnableSoon = true;
609 else
610 if (!cpu.eflagsVirtualInterruptPending && ((cpu.getCR4() & Processor.CR4_VIRTUAL8086_MODE_EXTENSIONS) != 0))
611 cpu.eflagsVirtualInterrupt = true;
612 else
613 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION,0,true);//ProcessorException.GENERAL_PROTECTION_0;
614 } break;
616 case CLD: cpu.eflagsDirection = false; break;
617 case STD: cpu.eflagsDirection = true; break;
618 case CMC: cpu.setCarryFlag(cpu.getCarryFlag() ^ true); break;
620 case CALL_O16: call_o16_a16((short)reg0); break;
621 case CALL_O32: call_o32_a16(reg0); break;
623 case RET_O16: ret_o16_a16(); break;
624 case RET_O32: ret_o32_a16(); break;
626 case RET_IW_O16: ret_iw_o16_a16((short)reg0); break;
628 case RET_FAR_O16: ret_far_o16_a16(); break;
629 case RET_FAR_IW_O16: ret_far_iw_o16_a16((short)reg0); break;
630 case ENTER_O16: enter_o16_a16(reg0, reg1); break;
631 case LEAVE_O16: leave_o16_a16(); break;
633 case PUSH_O16: push_o16((short)reg0); break;
634 case PUSH_O32: push_o32(reg0); break;
636 case PUSHF_O16:
637 if (cpu.eflagsIOPrivilegeLevel < 3)
638 throw ProcessorException.GENERAL_PROTECTION_0;
639 push_o16((short)reg0);
640 break;
641 case PUSHF_O32:
642 if (cpu.eflagsIOPrivilegeLevel < 3)
643 throw ProcessorException.GENERAL_PROTECTION_0;
644 push_o32(~0x30000 & reg0); break;
646 case POP_O16: {
647 if (cpu.ss.getDefaultSizeFlag()) {
648 reg1 = cpu.esp + 2;
649 if (microcodes[position] == STORE0_SS)
650 cpu.eflagsInterruptEnable = false;
651 reg0 = 0xffff & cpu.ss.getWord(cpu.esp);
652 } else {
653 reg1 = (cpu.esp & ~0xffff) | ((cpu.esp + 2) & 0xffff);
654 if (microcodes[position] == STORE0_SS)
655 cpu.eflagsInterruptEnable = false;
656 reg0 = 0xffff & cpu.ss.getWord(0xffff & cpu.esp);
658 } break;
660 case POP_O32: {
661 if (cpu.ss.getDefaultSizeFlag()) {
662 reg1 = cpu.esp + 4;
663 if (microcodes[position] == STORE0_SS)
664 cpu.eflagsInterruptEnable = false;
665 reg0 = cpu.ss.getDoubleWord(cpu.esp);
666 } else {
667 reg1 = (cpu.esp & ~0xffff) | ((cpu.esp + 4) & 0xffff);
668 if (microcodes[position] == STORE0_SS)
669 cpu.eflagsInterruptEnable = false;
670 reg0 = cpu.ss.getDoubleWord(0xffff & cpu.esp);
672 } break;
674 case POPF_O16:
675 if (cpu.eflagsIOPrivilegeLevel < 3)
676 throw ProcessorException.GENERAL_PROTECTION_0;
677 if (cpu.ss.getDefaultSizeFlag()) {
678 reg0 = 0xffff & cpu.ss.getWord(cpu.esp);
679 cpu.esp = cpu.esp + 2;
680 } else {
681 reg0 = 0xffff & cpu.ss.getWord(cpu.esp & 0xffff);
682 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp + 2) & 0xffff);
684 break;
686 case POPF_O32:
687 if (cpu.eflagsIOPrivilegeLevel < 3)
688 throw ProcessorException.GENERAL_PROTECTION_0;
689 if (cpu.ss.getDefaultSizeFlag()) {
690 reg0 = (cpu.getEFlags() & 0x20000) | (cpu.ss.getDoubleWord(cpu.esp) & ~0x1a0000);
691 cpu.esp = cpu.esp + 4;
692 } else {
693 reg0 = (cpu.getEFlags() & 0x20000) | (cpu.ss.getDoubleWord(cpu.esp & 0xffff) & ~0x1a0000);
694 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp + 4) & 0xffff);
696 break;
698 case PUSHA: pusha(); break;
699 case PUSHAD: pushad(); break;
701 case POPA: popa(); break;
702 case POPAD: popad(); break;
704 case SIGN_EXTEND_8_16: reg0 = 0xffff & ((byte)reg0); break;
705 case SIGN_EXTEND_8_32: reg0 = (byte)reg0; break;
706 case SIGN_EXTEND_16_32: reg0 = (short)reg0; break;
708 case CMPSB_A16: cmpsb_a16(seg0); break;
709 case CMPSW_A16: cmpsw_a16(seg0); break;
710 case CMPSD_A16: cmpsd_a16(seg0); break;
711 case REPE_CMPSB_A16: repe_cmpsb_a16(seg0); break;
712 case REPE_CMPSW_A16: repe_cmpsw_a16(seg0); break;
713 case REPE_CMPSD_A16: repe_cmpsd_a16(seg0); break;
715 case INSB_A16: insb_a16(reg0); break;
716 case INSW_A16: insw_a16(reg0); break;
717 case INSD_A16: insd_a16(reg0); break;
718 case REP_INSB_A16: rep_insb_a16(reg0); break;
719 case REP_INSW_A16: rep_insw_a16(reg0); break;
720 case REP_INSD_A16: rep_insd_a16(reg0); break;
722 case LODSB_A16: lodsb_a16(seg0); break;
723 case LODSW_A16: lodsw_a16(seg0); break;
724 case LODSD_A16: lodsd_a16(seg0); break;
725 case REP_LODSB_A16: rep_lodsb_a16(seg0); break;
726 case REP_LODSW_A16: rep_lodsw_a16(seg0); break;
727 case REP_LODSD_A16: rep_lodsd_a16(seg0); break;
728 case LODSB_A32: lodsb_a32(seg0); break;
729 case LODSW_A32: lodsw_a32(seg0); break;
730 case LODSD_A32: lodsd_a32(seg0); break;
731 case REP_LODSB_A32: rep_lodsb_a32(seg0); break;
732 case REP_LODSW_A32: rep_lodsw_a32(seg0); break;
733 case REP_LODSD_A32: rep_lodsd_a32(seg0); break;
735 case MOVSB_A16: movsb_a16(seg0); break;
736 case MOVSW_A16: movsw_a16(seg0); break;
737 case MOVSD_A16: movsd_a16(seg0); break;
738 case REP_MOVSB_A16: rep_movsb_a16(seg0); break;
739 case REP_MOVSW_A16: rep_movsw_a16(seg0); break;
740 case REP_MOVSD_A16: rep_movsd_a16(seg0); break;
741 case MOVSB_A32: movsb_a32(seg0); break;
742 case MOVSW_A32: movsw_a32(seg0); break;
743 case MOVSD_A32: movsd_a32(seg0); break;
744 case REP_MOVSB_A32: rep_movsb_a32(seg0); break;
745 case REP_MOVSW_A32: rep_movsw_a32(seg0); break;
746 case REP_MOVSD_A32: rep_movsd_a32(seg0); break;
748 case OUTSB_A16: outsb_a16(reg0, seg0); break;
749 case OUTSW_A16: outsw_a16(reg0, seg0); break;
750 case OUTSD_A16: outsd_a16(reg0, seg0); break;
752 case CMOVNS: if (!cpu.getSignFlag()) reg0 = reg1; break;
754 case REP_OUTSB_A16: rep_outsb_a16(reg0, seg0); break;
755 case REP_OUTSW_A16: rep_outsw_a16(reg0, seg0); break;
756 case REP_OUTSD_A16: rep_outsd_a16(reg0, seg0); break;
758 case SCASB_A16: scasb_a16(reg0); break;
759 case SCASW_A16: scasw_a16(reg0); break;
760 case SCASD_A16: scasd_a16(reg0); break;
761 case REPE_SCASB_A16: repe_scasb_a16(reg0); break;
762 case REPE_SCASW_A16: repe_scasw_a16(reg0); break;
763 case REPE_SCASD_A16: repe_scasd_a16(reg0); break;
764 case REPNE_SCASB_A16: repne_scasb_a16(reg0); break;
765 case REPNE_SCASW_A16: repne_scasw_a16(reg0); break;
766 case REPNE_SCASD_A16: repne_scasd_a16(reg0); break;
768 case STOSB_A16: stosb_a16(reg0); break;
769 case STOSW_A16: stosw_a16(reg0); break;
770 case STOSD_A16: stosd_a16(reg0); break;
771 case REP_STOSB_A16: rep_stosb_a16(reg0); break;
772 case REP_STOSW_A16: rep_stosw_a16(reg0); break;
773 case REP_STOSD_A16: rep_stosd_a16(reg0); break;
774 case STOSB_A32: stosb_a32(reg0); break;
775 case STOSW_A32: stosw_a32(reg0); break;
776 case STOSD_A32: stosd_a32(reg0); break;
777 case REP_STOSB_A32: rep_stosb_a32(reg0); break;
778 case REP_STOSW_A32: rep_stosw_a32(reg0); break;
779 case REP_STOSD_A32: rep_stosd_a32(reg0); break;
781 case LOOP_ECX: cpu.ecx--; if (cpu.ecx != 0) jump_o8((byte)reg0); break;
782 case LOOP_CX: cpu.ecx = (cpu.ecx & ~0xffff) | ((cpu.ecx - 1) & 0xffff); if ((0xffff & cpu.ecx) != 0) jump_o8((byte)reg0); break;
783 case LOOPZ_ECX: cpu.ecx--; if ((cpu.ecx != 0) && cpu.getZeroFlag()) jump_o8((byte)reg0); break;
784 case LOOPZ_CX: cpu.ecx = (cpu.ecx & ~0xffff) | ((cpu.ecx - 1) & 0xffff); if (((0xffff & cpu.ecx) != 0) && cpu.getZeroFlag()) jump_o8((byte)reg0); break;
785 case LOOPNZ_ECX: cpu.ecx--; if ((cpu.ecx != 0) && !cpu.getZeroFlag()) jump_o8((byte)reg0); break;
786 case LOOPNZ_CX: cpu.ecx = (cpu.ecx & ~0xffff) | ((cpu.ecx - 1) & 0xffff); if (((0xffff & cpu.ecx) != 0) && !cpu.getZeroFlag()) jump_o8((byte)reg0); break;
788 case JO_O8: jo_o8((byte)reg0); break;
789 case JNO_O8: jno_o8((byte)reg0); break;
790 case JC_O8: jc_o8((byte)reg0); break;
791 case JNC_O8: jnc_o8((byte)reg0); break;
792 case JZ_O8: jz_o8((byte)reg0); break;
793 case JNZ_O8: jnz_o8((byte)reg0); break;
794 case JNA_O8: jna_o8((byte)reg0); break;
795 case JA_O8: ja_o8((byte)reg0); break;
796 case JS_O8: js_o8((byte)reg0); break;
797 case JNS_O8: jns_o8((byte)reg0); break;
798 case JP_O8: jp_o8((byte)reg0); break;
799 case JNP_O8: jnp_o8((byte)reg0); break;
800 case JL_O8: jl_o8((byte)reg0); break;
801 case JNL_O8: jnl_o8((byte)reg0); break;
802 case JNG_O8: jng_o8((byte)reg0); break;
803 case JG_O8: jg_o8((byte)reg0); break;
805 case JO_O16: jo_o16((short)reg0); break;
806 case JNO_O16: jno_o16((short)reg0); break;
807 case JC_O16: jc_o16((short)reg0); break;
808 case JNC_O16: jnc_o16((short)reg0); break;
809 case JZ_O16: jz_o16((short)reg0); break;
810 case JNZ_O16: jnz_o16((short)reg0); break;
811 case JNA_O16: jna_o16((short)reg0); break;
812 case JA_O16: ja_o16((short)reg0); break;
813 case JS_O16: js_o16((short)reg0); break;
814 case JNS_O16: jns_o16((short)reg0); break;
815 case JP_O16: jp_o16((short)reg0); break;
816 case JNP_O16: jnp_o16((short)reg0); break;
817 case JL_O16: jl_o16((short)reg0); break;
818 case JNL_O16: jnl_o16((short)reg0); break;
819 case JNG_O16: jng_o16((short)reg0); break;
820 case JG_O16: jg_o16((short)reg0); break;
822 case JO_O32: jo_o32(reg0); break;
823 case JNO_O32: jno_o32(reg0); break;
824 case JC_O32: jc_o32(reg0); break;
825 case JNC_O32: jnc_o32(reg0); break;
826 case JZ_O32: jz_o32(reg0); break;
827 case JNZ_O32: jnz_o32(reg0); break;
828 case JNA_O32: jna_o32(reg0); break;
829 case JA_O32: ja_o32(reg0); break;
830 case JS_O32: js_o32(reg0); break;
831 case JNS_O32: jns_o32(reg0); break;
832 case JP_O32: jp_o32(reg0); break;
833 case JNP_O32: jnp_o32(reg0); break;
834 case JL_O32: jl_o32(reg0); break;
835 case JNL_O32: jnl_o32(reg0); break;
836 case JNG_O32: jng_o32(reg0); break;
837 case JG_O32: jg_o32(reg0); break;
839 case JCXZ: jcxz((byte)reg0); break;
840 case JECXZ: jecxz((byte)reg0); break;
842 case INC: reg0++; break;
843 case DEC: reg0--; break;
845 case HALT: throw ProcessorException.GENERAL_PROTECTION_0;
848 // case RDTSC: long tsc = cpu.getClockCount(); reg0 = (int)tsc; reg1 = (int)(tsc >>> 32); break;
849 // case WRMSR: cpu.setMSR(reg0, (reg2 & 0xffffffffl) | ((reg1 & 0xffffffffl) << 32)); break;
850 // case RDMSR: long msr = cpu.getMSR(reg0); reg0 = (int)msr; reg1 = (int)(msr >>> 32); break;
852 case SETO: reg0 = cpu.getOverflowFlag() ? 1 : 0; break;
853 case SETNO: reg0 = cpu.getOverflowFlag() ? 0 : 1; break;
854 case SETC: reg0 = cpu.getCarryFlag() ? 1 : 0; break;
855 case SETNC: reg0 = cpu.getCarryFlag() ? 0 : 1; break;
856 case SETZ: reg0 = cpu.getZeroFlag() ? 1 : 0; break;
857 case SETNZ: reg0 = cpu.getZeroFlag() ? 0 : 1; break;
858 case SETNA: reg0 = cpu.getCarryFlag() || cpu.getZeroFlag() ? 1 : 0; break;
859 case SETA: reg0 = cpu.getCarryFlag() || cpu.getZeroFlag() ? 0 : 1; break;
860 case SETS: reg0 = cpu.getSignFlag() ? 1 : 0; break;
861 case SETNS: reg0 = cpu.getSignFlag() ? 0 : 1; break;
862 case SETP: reg0 = cpu.getParityFlag() ? 1 : 0; break;
863 case SETNP: reg0 = cpu.getParityFlag() ? 0 : 1; break;
864 case SETL: reg0 = cpu.getSignFlag() != cpu.getOverflowFlag() ? 1 : 0; break;
865 case SETNL: reg0 = cpu.getSignFlag() != cpu.getOverflowFlag() ? 0 : 1; break;
866 case SETNG: reg0 = cpu.getZeroFlag() || (cpu.getSignFlag() != cpu.getOverflowFlag()) ? 1 : 0; break;
867 case SETG: reg0 = cpu.getZeroFlag() || (cpu.getSignFlag() != cpu.getOverflowFlag()) ? 0 : 1; break;
869 case SMSW: reg0 = cpu.getCR0() & 0xffff; break;
870 // case LMSW: cpu.setCR0((cpu.getCR0() & ~0xf) | (reg0 & 0xf)); break;
872 // case LGDT_O16: cpu.gdtr = cpu.createDescriptorTableSegment(reg1 & 0x00ffffff, reg0); break;
873 // case LGDT_O32: cpu.gdtr = cpu.createDescriptorTableSegment(reg1, reg0); break;
874 // case LIDT_O16: cpu.idtr = cpu.createDescriptorTableSegment(reg1 & 0x00ffffff, reg0); break;
875 // case LIDT_O32: cpu.idtr = cpu.createDescriptorTableSegment(reg1, reg0); break;
876 case SGDT_O16: reg1 = cpu.gdtr.getBase() & 0x00ffffff; reg0 = cpu.gdtr.getLimit(); break;
878 case CPUID: cpuid(); break;
880 // case CLTS: cpu.setCR0(cpu.getCR0() & ~0x8); break;
882 case BITWISE_FLAGS_O8: bitwise_flags((byte)reg0); break;
883 case BITWISE_FLAGS_O16: bitwise_flags((short)reg0); break;
884 case BITWISE_FLAGS_O32: bitwise_flags(reg0); break;
886 case SUB_O8_FLAGS: sub_o8_flags(reg0, reg2, reg1); break;
887 case SUB_O16_FLAGS: sub_o16_flags(reg0, reg2, reg1); break;
888 case SUB_O32_FLAGS: sub_o32_flags(reg0l, reg2, reg1); break;
890 case REP_SUB_O8_FLAGS: rep_sub_o8_flags(reg0, reg2, reg1); break;
891 case REP_SUB_O16_FLAGS: rep_sub_o16_flags(reg0, reg2, reg1); break;
892 case REP_SUB_O32_FLAGS: rep_sub_o32_flags(reg0, reg2, reg1); break;
894 case ADD_O8_FLAGS: add_o8_flags(reg0, reg2, reg1); break;
895 case ADD_O16_FLAGS: add_o16_flags(reg0, reg2, reg1); break;
896 case ADD_O32_FLAGS: add_o32_flags(reg0l, reg2, reg1); break;
898 case ADC_O8_FLAGS: adc_o8_flags(reg0, reg2, reg1); break;
899 case ADC_O16_FLAGS: adc_o16_flags(reg0, reg2, reg1); break;
900 case ADC_O32_FLAGS: adc_o32_flags(reg0l, reg2, reg1); break;
902 case SBB_O8_FLAGS: sbb_o8_flags(reg0, reg2, reg1); break;
903 case SBB_O16_FLAGS: sbb_o16_flags(reg0, reg2, reg1); break;
904 case SBB_O32_FLAGS: sbb_o32_flags(reg0l, reg2, reg1); break;
906 case INC_O8_FLAGS: inc_flags((byte)reg0); break;
907 case INC_O16_FLAGS: inc_flags((short)reg0); break;
908 case INC_O32_FLAGS: inc_flags(reg0); break;
910 case DEC_O8_FLAGS: dec_flags((byte)reg0); break;
911 case DEC_O16_FLAGS: dec_flags((short)reg0); break;
912 case DEC_O32_FLAGS: dec_flags(reg0); break;
914 case SHL_O8_FLAGS: shl_flags((byte)reg0, (byte)reg2, reg1); break;
915 case SHL_O32_FLAGS: shl_flags(reg0, reg2, reg1); break;
917 case SHR_O8_FLAGS: shr_flags((byte)reg0, reg2, reg1); break;
918 case SHR_O16_FLAGS: shr_flags((short)reg0, reg2, reg1); break;
919 case SHR_O32_FLAGS: shr_flags(reg0, reg2, reg1); break;
921 case SAR_O8_FLAGS: sar_flags((byte)reg0, (byte)reg2, reg1); break;
922 case SAR_O16_FLAGS: sar_flags((short)reg0, (short)reg2, reg1); break;
923 case SAR_O32_FLAGS: sar_flags(reg0, reg2, reg1); break;
925 case RCL_O8_FLAGS: rcl_o8_flags(reg0, reg1); break;
926 case RCL_O16_FLAGS: rcl_o16_flags(reg0, reg1); break;
927 case RCL_O32_FLAGS: rcl_o32_flags(reg0l, reg1); break;
929 case RCR_O8_FLAGS: rcr_o8_flags(reg0, reg1, reg2); break;
930 case RCR_O16_FLAGS: rcr_o16_flags(reg0, reg1, reg2); break;
931 case RCR_O32_FLAGS: rcr_o32_flags(reg0l, reg1, reg2); break;
933 case ROL_O8_FLAGS: rol_flags((byte)reg0, reg1); break;
934 case ROL_O16_FLAGS: rol_flags((short)reg0, reg1); break;
935 case ROL_O32_FLAGS: rol_flags(reg0, reg1); break;
937 case ROR_O8_FLAGS: ror_flags((byte)reg0, reg1); break;
938 case ROR_O16_FLAGS: ror_flags((short)reg0, reg1); break;
939 case ROR_O32_FLAGS: ror_flags(reg0, reg1); break;
941 case NEG_O8_FLAGS: neg_flags((byte)reg0); break;
942 case NEG_O16_FLAGS: neg_flags((short)reg0); break;
943 case NEG_O32_FLAGS: neg_flags(reg0); break;
945 case CPL_CHECK: throw ProcessorException.GENERAL_PROTECTION_0;
947 default:
948 if(!Misc.isFPUOp(microcodes[position - 1])) {
949 System.err.println("Critical error: Unknown uCode " + microcodes[position - 1] + ".");
950 throw new IllegalStateException("Unknown uCode V" + microcodes[position - 1]);
953 cpu.useFPU(microcodes[position - 1] == FWAIT);
954 int x = fpu.doFPUOp(microcodes[position - 1], microcodes[position], seg0, addr0, reg0, reg1, reg2,
955 reg0l);
956 //Handle buffer updates.
957 if((x & 1) != 0) reg0 = fpu.getReg0();
958 if((x & 2) != 0) reg1 = fpu.getReg1();
959 if((x & 4) != 0) reg2 = fpu.getReg2();
960 if((x & 8) != 0) reg0l = fpu.getReg0l();
961 if((x & 16) != 0) position++;
963 } finally {
964 //copy local variables back to instance storage
965 transferSeg0 = seg0;
966 transferAddr0 = addr0;
967 transferReg0 = reg0;
968 transferReg1 = reg1;
969 transferReg2 = reg2;
970 transferReg0l = reg0l;
971 transferEipUpdated = eipUpdated;
972 transferPosition = position;
976 private int getInstructionLength(int position)
978 int nextPosition = position - 1; //this makes position point at the microcode that just barfed
980 int ans = -cumulativeX86Length[nextPosition]; // undo the eipUpdate
982 for (int selfPosition = nextPosition; selfPosition >= 0; selfPosition--) {
983 if (cumulativeX86Length[selfPosition] != cumulativeX86Length[nextPosition]) {
984 ans += cumulativeX86Length[selfPosition];
985 break;
988 if (ans <= 0)
989 ans = -ans;
990 return ans;
993 public int execute(Processor cpu)
995 this.fpu = cpu.fpu;
996 this.cpu = cpu;
998 if (opcodeCounter != null)
999 opcodeCounter.addBlock(getMicrocodes());
1001 Segment seg0 = null;
1002 int addr0 = 0;
1003 int reg0 = 0, reg1 = 0, reg2 = 0;
1004 long reg0l = 0;
1006 executeCount = 0;
1007 boolean eipUpdated = false;
1009 int position = 0;
1010 cpu.eflagsLastAborted = false;
1011 if(fpu != null)
1012 fpu.setProtectedMode(false);
1016 while (position < microcodes.length) {
1017 if (uCodeXferLoaded)
1019 uCodeXferLoaded = false;
1020 reg0 = uCodeXferReg0;
1021 reg1 = uCodeXferReg1;
1022 reg2 = uCodeXferReg2;
1024 switch (microcodes[position++]) {
1025 case MEM_RESET: addr0 = 0; seg0 = null; break; //4653406
1026 case ADDR_MASK16: addr0 &= 0xffff; break; //4653406
1027 case EIP_UPDATE: if (!eipUpdated) { //4253320
1028 eipUpdated = true;
1029 cpu.eip += cumulativeX86Length[position - 1];
1030 } break;
1031 case ADDR_IB: addr0 += ((byte)microcodes[position++]); break; //3832219
1032 case PUSH_O16: push_o16((short)reg0); break; //3221577
1033 case LOAD_SEG_SS: seg0 = cpu.ss; break; //2739696
1034 case LOAD0_AX: reg0 = cpu.eax & 0xffff; break; //2718333
1035 case ADDR_BP: addr0 += ((short)cpu.ebp); break; //2701629
1036 case LOAD0_IB: reg0 = microcodes[position++] & 0xff; break; //2567113
1037 case LOAD0_MEM_WORD: reg0 = 0xffff & seg0.getWord(addr0); break; //2352051
1039 case STORE1_ESP: cpu.esp = reg1; break; //2252894
1040 case POP_O16: { //2251454
1041 if (cpu.ss.getDefaultSizeFlag()) {
1042 reg1 = cpu.esp + 2;
1043 if (microcodes[position] == STORE0_SS)
1044 cpu.eflagsInterruptEnable = false;
1045 reg0 = 0xffff & cpu.ss.getWord(cpu.esp);
1046 } else {
1047 reg1 = (cpu.esp & ~0xffff) | ((cpu.esp + 2) & 0xffff);
1048 if (microcodes[position] == STORE0_SS)
1049 cpu.eflagsInterruptEnable = false;
1050 reg0 = 0xffff & cpu.ss.getWord(0xffff & cpu.esp);
1052 } break;
1053 case STORE0_AX: cpu.eax = (cpu.eax & ~0xffff) | (reg0 & 0xffff); break; //2211780
1054 case LOAD0_IW: reg0 = microcodes[position++] & 0xffff; break; //1748064
1055 case LOAD_SEG_DS: seg0 = cpu.ds; break; //1556141
1056 case STORE0_BX: cpu.ebx = (cpu.ebx & ~0xffff) | (reg0 & 0xffff); break; //1295862
1057 case SUB: reg2 = reg0; reg0 = reg2 - reg1; break; //1166414
1058 case STORE0_BP: cpu.ebp = (cpu.ebp & ~0xffff) | (reg0 & 0xffff); break; //1077742
1059 case ADDR_BX: addr0 += ((short)cpu.ebx); break; //1018423
1060 case LOAD0_SP: reg0 = cpu.esp & 0xffff; break; //1017910
1062 case ADD: reg2 = reg0; reg0 = reg2 + reg1; break; //1004121
1063 case STORE0_MEM_WORD: seg0.setWord(addr0, (short)reg0); break; //896323
1064 case LOAD0_MEM_BYTE: reg0 = 0xff & seg0.getByte(addr0); break; //839821
1065 case JNZ_O8: jnz_o8((byte)reg0); break; //837018
1066 case STORE0_AL: cpu.eax = (cpu.eax & ~0xff) | (reg0 & 0xff); break; //814558
1067 case LOAD0_BX: reg0 = cpu.ebx & 0xffff; break; //813659
1068 case LOAD1_IB: reg1 = microcodes[position++] & 0xff; break; //809491
1069 case LOAD1_IW: reg1 = microcodes[position++] & 0xffff; break; //805651
1070 case CALL_O16: call_o16_a16((short)reg0); break; //791837
1071 case STORE0_CX: cpu.ecx = (cpu.ecx & ~0xffff) | (reg0 & 0xffff); break; //775713
1073 case LOAD0_CX: reg0 = cpu.ecx & 0xffff; break; //773832
1074 case LOAD0_BP: reg0 = cpu.ebp & 0xffff; break; //763561
1075 case RET_O16: ret_o16_a16(); break; //720729
1076 case STORE0_SP: cpu.esp = (cpu.esp & ~0xffff) | (reg0 & 0xffff); break; //681228
1077 case LOAD0_AL: reg0 = cpu.eax & 0xff; break; //680163
1078 case ADD_O16_FLAGS: add_o16_flags(reg0, reg2, reg1); break; //667848
1079 case SUB_O16_FLAGS: sub_o16_flags(reg0, reg2, reg1); break; //664323
1080 case STORE0_DS: cpu.ds.setSelector(0xffff & reg0); break; //654678
1081 case LOAD0_DX: reg0 = cpu.edx & 0xffff; break; //620350
1082 case BITWISE_FLAGS_O8: bitwise_flags((byte)reg0); break; //606068
1084 case STORE0_SI: cpu.esi = (cpu.esi & ~0xffff) | (reg0 & 0xffff); break; //601955
1085 case XOR: reg0 ^= reg1; break; //552649
1086 case STORE0_DX: cpu.edx = (cpu.edx & ~0xffff) | (reg0 & 0xffff); break; //516299
1087 case ADDR_SI: addr0 += ((short)cpu.esi); break; //514379
1088 case SUB_O8_FLAGS: sub_o8_flags(reg0, reg2, reg1); break; //500672
1089 case JZ_O8: jz_o8((byte)reg0); break; //499451
1090 case LOAD0_AH: reg0 = (cpu.eax >> 8) & 0xff; break; //497132
1091 case STORE0_DI: cpu.edi = (cpu.edi & ~0xffff) | (reg0 & 0xffff); break; //490840
1092 case LOAD0_SI: reg0 = cpu.esi & 0xffff; break; //473018
1093 case ADDR_IW: addr0 += ((short)microcodes[position++]); break; //449628
1095 case BITWISE_FLAGS_O16: bitwise_flags((short)reg0); break; //426086
1096 case LOAD0_DS: reg0 = 0xffff & cpu.ds.getSelector(); break; //425449
1097 case LOAD1_MEM_WORD: reg1 = 0xffff & seg0.getWord(addr0); break; //417691
1098 case LOAD0_DI: reg0 = cpu.edi & 0xffff; break; //402655
1099 case INC: reg0++; break; //377084
1100 case STORE0_ES: cpu.es.setSelector(0xffff & reg0); break; //374908
1101 case INC_O16_FLAGS: inc_flags((short)reg0); break; //369608
1102 case AND: reg0 &= reg1; break; //364104
1103 case STORE0_BH: cpu.ebx = (cpu.ebx & ~0xff00) | ((reg0 << 8) & 0xff00); break; //363053
1104 case LOAD_SEG_ES: seg0 = cpu.es; break; //345778
1106 case STORE0_AH: cpu.eax = (cpu.eax & ~0xff00) | ((reg0 << 8) & 0xff00); break; //341158
1107 case LOAD1_CX: reg1 = cpu.ecx & 0xffff; break; //338002
1108 case ADD_O8_FLAGS: add_o8_flags(reg0, reg2, reg1); break; //336258
1109 case LOAD1_AX: reg1 = cpu.eax & 0xffff; break; //330347
1110 case LOAD1_BH: reg1 = (cpu.ebx >> 8) & 0xff; break; //322337
1111 case LOAD0_BH: reg0 = (cpu.ebx >> 8) & 0xff; break; //295205
1112 case STORE0_MEM_BYTE: seg0.setByte(addr0, (byte)reg0); break; //259410
1113 case LOAD0_ES: reg0 = 0xffff & cpu.es.getSelector(); break; //239972
1114 case LOAD1_AH: reg1 = (cpu.eax >> 8) & 0xff; break; //233962
1115 case ADC: reg2 = reg0; reg0 = reg2 + reg1 + (cpu.getCarryFlag() ? 1 : 0); break; //219410
1117 case JUMP_O8: jump_o8((byte)reg0); break; //189393
1118 case JNC_O8: jnc_o8((byte)reg0); break; //183798
1119 case JC_O8: jc_o8((byte)reg0); break; //174366
1120 case LOAD1_AL: reg1 = cpu.eax & 0xff; break; //169225
1121 case ADC_O16_FLAGS: adc_o16_flags(reg0, reg2, reg1); break; //164196
1122 case JUMP_O16: jump_o16((short)reg0); break; //159616
1123 case LOAD_SEG_CS: seg0 = cpu.cs; break; //151531
1124 case DEC: reg0--; break; //150476
1125 case DEC_O16_FLAGS: dec_flags((short)reg0); break; //143631
1126 case LOAD0_ADDR: reg0 = addr0; break; //131311
1128 case SHL: reg1 &= 0x1f; reg2 = reg0; reg0 <<= reg1; break;
1129 case STORE0_BL: cpu.ebx = (cpu.ebx & ~0xff) | (reg0 & 0xff); break;
1130 case SHL_O16_FLAGS: shl_flags((short)reg0, (short)reg2, reg1); break;
1131 case LOAD1_BX: reg1 = cpu.ebx & 0xffff; break;
1132 case OR: reg0 |= reg1; break;
1133 case STORE1_ES: cpu.es.setSelector(0xffff & reg1); break;
1134 case STORE1_AX: cpu.eax = (cpu.eax & ~0xffff) | (reg1 & 0xffff); break;
1135 case LOAD1_DI: reg1 = cpu.edi & 0xffff; break;
1136 case LOAD1_MEM_BYTE: reg1 = 0xff & seg0.getByte(addr0); break;
1137 case JCXZ: jcxz((byte)reg0); break;
1139 case LOAD1_SI: reg1 = cpu.esi & 0xffff; break;
1140 case STORE1_DS: cpu.ds.setSelector(0xffff & reg1); break;
1141 case LOAD1_CL: reg1 = cpu.ecx & 0xff; break;
1142 case JUMP_ABS_O16: cpu.eip = reg0; break;
1143 case STORE0_CL: cpu.ecx = (cpu.ecx & ~0xff) | (reg0 & 0xff); break;
1144 case ADDR_DI: addr0 += ((short)cpu.edi); break;
1145 case SHR: reg2 = reg0; reg0 >>>= reg1; break;
1146 case SHR_O16_FLAGS: shr_flags((short)reg0, reg2, reg1); break;
1147 case JA_O8: ja_o8((byte)reg0); break;
1148 case JNA_O8: jna_o8((byte)reg0); break;
1149 case INSTRUCTION_START:
1150 if(cpu.eflagsMachineHalt) throw ProcessorException.TRACESTOP;
1151 if(invalidated && cpu.SYSFLAG_FLUSHONMODIFY) {
1152 invalidated = false;
1153 throw ProcessorException.SELFMODIFIED;
1155 cpu.instructionExecuted();
1156 executeCount++; break;
1158 default:
1160 //copy local variables to instance storage
1161 transferSeg0 = seg0;
1162 transferAddr0 = addr0;
1163 transferReg0 = reg0;
1164 transferReg1 = reg1;
1165 transferReg2 = reg2;
1166 transferReg0l = reg0l;
1167 transferEipUpdated = eipUpdated;
1168 transferPosition = position - 1;
1169 try {
1170 fullExecute(cpu);
1171 } finally {
1172 seg0 = transferSeg0;
1173 addr0 = transferAddr0;
1174 reg0 = transferReg0;
1175 reg1 = transferReg1;
1176 reg2 = transferReg2;
1177 reg0l = transferReg0l;
1178 eipUpdated = transferEipUpdated;
1179 position = transferPosition;
1181 } break;
1185 catch (ProcessorException e)
1187 int nextPosition = position - 1; //this makes position point at the microcode that just barfed
1188 if (eipUpdated)
1189 cpu.eip -= cumulativeX86Length[nextPosition]; // undo the eipUpdate
1191 if (!e.pointsToSelf())
1192 cpu.eip += cumulativeX86Length[nextPosition];
1193 else
1194 for (int selfPosition = nextPosition; selfPosition >= 0; selfPosition--)
1195 if (cumulativeX86Length[selfPosition] != cumulativeX86Length[nextPosition])
1197 cpu.eip += cumulativeX86Length[selfPosition];
1198 break;
1200 if(e.getType() != ProcessorException.Type.SELFMODIFIED &&
1201 e.getType() != ProcessorException.Type.TRACESTOP) //Swallow trace stops!
1202 cpu.handleVirtual8086ModeException(e);
1203 else
1204 cpu.eflagsLastAborted = true;
1207 return Math.max(executeCount, 0);
1210 private final void jo_o8(byte offset)
1212 if (cpu.getOverflowFlag()) jump_o8(offset);
1215 private final void jno_o8(byte offset)
1217 if (!cpu.getOverflowFlag()) jump_o8(offset);
1220 private final void jc_o8(byte offset)
1222 if (cpu.getCarryFlag()) jump_o8(offset);
1225 private final void jnc_o8(byte offset)
1227 if (!cpu.getCarryFlag()) jump_o8(offset);
1230 private final void jz_o8(byte offset)
1232 if (cpu.getZeroFlag()) jump_o8(offset);
1235 private final void jnz_o8(byte offset)
1237 if (!cpu.getZeroFlag()) jump_o8(offset);
1240 private final void jna_o8(byte offset)
1242 if (cpu.getCarryFlag() || cpu.getZeroFlag()) jump_o8(offset);
1245 private final void ja_o8(byte offset)
1247 if ((!cpu.getCarryFlag()) && (!cpu.getZeroFlag())) jump_o8(offset);
1250 private final void js_o8(byte offset)
1252 if (cpu.getSignFlag()) jump_o8(offset);
1255 private final void jns_o8(byte offset)
1257 if (!cpu.getSignFlag()) jump_o8(offset);
1260 private final void jp_o8(byte offset)
1262 if (cpu.getParityFlag()) jump_o8(offset);
1265 private final void jnp_o8(byte offset)
1267 if (!cpu.getParityFlag()) jump_o8(offset);
1270 private final void jl_o8(byte offset)
1272 if (cpu.getSignFlag() != cpu.getOverflowFlag()) jump_o8(offset);
1275 private final void jnl_o8(byte offset)
1277 if (cpu.getSignFlag() == cpu.getOverflowFlag()) jump_o8(offset);
1280 private final void jng_o8(byte offset)
1282 if (cpu.getZeroFlag() || (cpu.getSignFlag() != cpu.getOverflowFlag())) jump_o8(offset);
1285 private final void jg_o8(byte offset)
1287 if ((!cpu.getZeroFlag()) && (cpu.getSignFlag() == cpu.getOverflowFlag())) jump_o8(offset);
1290 private final void jo_o16(short offset)
1292 if (cpu.getOverflowFlag()) jump_o16(offset);
1295 private final void jno_o16(short offset)
1297 if (!cpu.getOverflowFlag()) jump_o16(offset);
1300 private final void jc_o16(short offset)
1302 if (cpu.getCarryFlag()) jump_o16(offset);
1305 private final void jnc_o16(short offset)
1307 if (!cpu.getCarryFlag()) jump_o16(offset);
1310 private final void jz_o16(short offset)
1312 if (cpu.getZeroFlag()) jump_o16(offset);
1315 private final void jnz_o16(short offset)
1317 if (!cpu.getZeroFlag()) jump_o16(offset);
1320 private final void jna_o16(short offset)
1322 if (cpu.getCarryFlag() || cpu.getZeroFlag()) jump_o16(offset);
1325 private final void ja_o16(short offset)
1327 if ((!cpu.getCarryFlag()) && (!cpu.getZeroFlag())) jump_o16(offset);
1330 private final void js_o16(short offset)
1332 if (cpu.getSignFlag()) jump_o16(offset);
1335 private final void jns_o16(short offset)
1337 if (!cpu.getSignFlag()) jump_o16(offset);
1340 private final void jp_o16(short offset)
1342 if (cpu.getParityFlag()) jump_o16(offset);
1345 private final void jnp_o16(short offset)
1347 if (!cpu.getParityFlag()) jump_o16(offset);
1350 private final void jl_o16(short offset)
1352 if (cpu.getSignFlag() != cpu.getOverflowFlag()) jump_o16(offset);
1355 private final void jnl_o16(short offset)
1357 if (cpu.getSignFlag() == cpu.getOverflowFlag()) jump_o16(offset);
1360 private final void jng_o16(short offset)
1362 if (cpu.getZeroFlag() || (cpu.getSignFlag() != cpu.getOverflowFlag())) jump_o16(offset);
1365 private final void jg_o16(short offset)
1367 if ((!cpu.getZeroFlag()) && (cpu.getSignFlag() == cpu.getOverflowFlag())) jump_o16(offset);
1370 private final void jo_o32(int offset)
1372 if (cpu.getOverflowFlag()) jump_o32(offset);
1375 private final void jno_o32(int offset)
1377 if (!cpu.getOverflowFlag()) jump_o32(offset);
1380 private final void jc_o32(int offset)
1382 if (cpu.getCarryFlag()) jump_o32(offset);
1385 private final void jnc_o32(int offset)
1387 if (!cpu.getCarryFlag()) jump_o32(offset);
1390 private final void jz_o32(int offset)
1392 if (cpu.getZeroFlag()) jump_o32(offset);
1395 private final void jnz_o32(int offset)
1397 if (!cpu.getZeroFlag()) jump_o32(offset);
1400 private final void jna_o32(int offset)
1402 if (cpu.getCarryFlag() || cpu.getZeroFlag()) jump_o32(offset);
1405 private final void ja_o32(int offset)
1407 if ((!cpu.getCarryFlag()) && (!cpu.getZeroFlag())) jump_o32(offset);
1410 private final void js_o32(int offset)
1412 if (cpu.getSignFlag()) jump_o32(offset);
1415 private final void jns_o32(int offset)
1417 if (!cpu.getSignFlag()) jump_o32(offset);
1420 private final void jp_o32(int offset)
1422 if (cpu.getParityFlag()) jump_o32(offset);
1425 private final void jnp_o32(int offset)
1427 if (!cpu.getParityFlag()) jump_o32(offset);
1430 private final void jl_o32(int offset)
1432 if (cpu.getSignFlag() != cpu.getOverflowFlag()) jump_o32(offset);
1435 private final void jnl_o32(int offset)
1437 if (cpu.getSignFlag() == cpu.getOverflowFlag()) jump_o32(offset);
1440 private final void jng_o32(int offset)
1442 if (cpu.getZeroFlag() || (cpu.getSignFlag() != cpu.getOverflowFlag())) jump_o32(offset);
1445 private final void jg_o32(int offset)
1447 if ((!cpu.getZeroFlag()) && (cpu.getSignFlag() == cpu.getOverflowFlag())) jump_o32(offset);
1450 private final void jcxz(byte offset)
1452 if ((cpu.ecx & 0xffff) == 0) jump_o8(offset);
1455 private final void jecxz(byte offset)
1457 if (cpu.ecx == 0) jump_o8(offset);
1461 private final void jump_o8(byte offset)
1463 cpu.eip += offset;
1464 // check whether eip is outside of 0x0000 and 0xffff
1465 if ((cpu.eip & 0xFFFF0000) != 0)
1467 cpu.eip -= offset;
1468 throw ProcessorException.GENERAL_PROTECTION_0;
1472 private final void jump_o16(short offset)
1474 cpu.eip = (cpu.eip + offset) & 0xffff;
1477 private final void jump_o32(int offset)
1479 cpu.eip += offset;
1480 if ((cpu.eip & 0xFFFF0000) != 0)
1482 cpu.eip -= offset;
1483 throw ProcessorException.GENERAL_PROTECTION_0;
1487 private final void call_o16_a16(short target)
1489 if (((cpu.esp & 0xffff) < 2) && ((cpu.esp & 0xffff) > 0))
1490 throw ProcessorException.STACK_SEGMENT_0;
1492 int offset = (cpu.esp - 2) & 0xffff;
1493 cpu.ss.setWord(offset, (short)cpu.eip);
1494 cpu.esp = (cpu.esp & 0xffff0000) | offset;
1495 cpu.eip = (cpu.eip + target) & 0xffff;
1498 private final void call_o32_a16(int target)
1500 if (((cpu.esp & 0xffff) < 4) && ((cpu.esp & 0xffff) > 0))
1501 throw ProcessorException.STACK_SEGMENT_0;
1503 if ((cpu.eip + target) > 0xffff)
1504 throw ProcessorException.GENERAL_PROTECTION_0;
1506 int offset = (cpu.esp - 4) & 0xffff;
1507 cpu.ss.setDoubleWord(offset, cpu.eip);
1508 cpu.esp = (cpu.esp & 0xffff0000) | offset;
1509 cpu.eip = cpu.eip + target;
1512 private final void ret_o16_a16()
1514 // TODO: supposed to throw SS exception
1515 // "if top 6 bytes of stack not within stack limits"
1516 cpu.eip = cpu.ss.getWord(cpu.esp & 0xffff) & 0xffff;
1517 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp + 2) & 0xffff);
1520 private final void ret_o32_a16()
1522 // TODO: supposed to throw SS exception
1523 // "if top 6 bytes of stack not within stack limits"
1524 cpu.eip = cpu.ss.getDoubleWord(cpu.esp & 0xffff) & 0xffff;
1525 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp + 4) & 0xffff);
1528 private final void ret_iw_o16_a16(short data)
1530 ret_o16_a16();
1531 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp + data) & 0xffff);
1534 private final void ret_far_o16_a16()
1536 // TODO: supposed to throw SS exception
1537 // "if top 6 bytes of stack not within stack limits"
1538 cpu.eip = cpu.ss.getWord(cpu.esp & 0xffff) & 0xffff;
1539 cpu.cs.setSelector(cpu.ss.getWord((cpu.esp + 2) & 0xffff) & 0xffff);
1540 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp + 4) & 0xffff);
1543 private final void ret_far_iw_o16_a16(short offset)
1545 // TODO: supposed to throw SS exception
1546 // "if top 6 bytes of stack not within stack limits"
1547 ret_far_o16_a16();
1548 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp + offset) & 0xffff);
1551 private final void enter_o16_a16(int frameSize, int nestingLevel)
1553 nestingLevel %= 32;
1555 int tempESP = cpu.esp;
1556 int tempEBP = cpu.ebp;
1558 tempESP = (tempESP & ~0xffff) | ((tempESP - 2) & 0xffff);
1559 cpu.ss.setWord(tempESP & 0xffff, (short)tempEBP);
1561 int frameTemp = tempESP & 0xffff;
1563 if (nestingLevel != 0) {
1564 while (--nestingLevel != 0) {
1565 tempEBP = (tempEBP & ~0xffff) | ((tempEBP - 2) & 0xffff);
1566 tempESP = (tempESP & ~0xffff) | ((tempESP - 2) & 0xffff);
1567 cpu.ss.setWord(tempESP & 0xffff, cpu.ss.getWord(tempEBP & 0xffff));
1570 tempESP = (tempESP & ~0xffff) | ((tempESP - 2) & 0xffff);
1571 cpu.ss.setWord(tempESP & 0xffff, (short)frameTemp);
1574 cpu.ebp = (tempEBP & ~0xffff) | (frameTemp & 0xffff);
1575 cpu.esp = (tempESP & ~0xffff) | ((tempESP - frameSize -2*nestingLevel) & 0xffff);
1578 private final void leave_o16_a16()
1580 try {
1581 cpu.ss.checkAddress(cpu.ebp & 0xffff);
1582 } catch (ProcessorException e) {
1583 throw ProcessorException.STACK_SEGMENT_0;
1585 int tempESP = (cpu.esp & ~0xffff) | (cpu.ebp & 0xffff);
1586 int tempEBP = (cpu.ebp & ~0xffff) | (cpu.ss.getWord(tempESP & 0xffff) & 0xffff);
1587 if (((tempESP & 0xffff) > 0xffff) || ((tempESP & 0xffff) < 0)) {
1588 System.err.println("Emulated: Throwing dodgy leave exception.");
1589 throw ProcessorException.GENERAL_PROTECTION_0;
1591 cpu.esp = (tempESP & ~0xffff) | ((tempESP + 2) & 0xffff);
1592 cpu.ebp = tempEBP;
1595 private final void push_o16(short data)
1597 if (cpu.ss.getDefaultSizeFlag()) {
1598 if ((cpu.esp < 2) && (cpu.esp > 0))
1599 throw ProcessorException.STACK_SEGMENT_0;
1601 int offset = cpu.esp - 2;
1602 cpu.ss.setWord(offset, data);
1603 cpu.esp = offset;
1604 } else {
1605 if (((cpu.esp & 0xffff) < 2) && ((cpu.esp & 0xffff) > 0))
1606 throw ProcessorException.STACK_SEGMENT_0;
1608 int offset = (cpu.esp - 2) & 0xffff;
1609 cpu.ss.setWord(offset, data);
1610 cpu.esp = (cpu.esp & ~0xffff) | offset;
1614 private final void push_o32(int data)
1616 if (cpu.ss.getDefaultSizeFlag()) {
1617 if ((cpu.esp < 4) && (cpu.esp > 0))
1618 throw ProcessorException.STACK_SEGMENT_0;
1620 int offset = cpu.esp - 4;
1621 cpu.ss.setDoubleWord(offset, data);
1622 cpu.esp = offset;
1623 } else {
1624 if (((cpu.esp & 0xffff) < 4) && ((cpu.esp & 0xffff) > 0))
1625 throw ProcessorException.STACK_SEGMENT_0;
1627 int offset = (cpu.esp - 4) & 0xffff;
1628 cpu.ss.setDoubleWord(offset, data);
1629 cpu.esp = (cpu.esp & ~0xffff) | offset;
1633 private final void pusha()
1635 int offset, offmask;
1636 if (cpu.ss.getDefaultSizeFlag()) {
1637 offset = cpu.esp;
1638 offmask = 0xffffffff;
1639 } else {
1640 offset = cpu.esp & 0xffff;
1641 offmask = 0xffff;
1644 //it seems that it checks at every push (we will simulate this)
1645 if ((offset < 16) && ((offset & 0x1) == 0x1)) {
1646 if (offset < 6)
1647 System.err.println("Emulated: Should shutdown machine (PUSHA with small ESP).");
1648 throw ProcessorException.GENERAL_PROTECTION_0;
1651 int temp = cpu.esp;
1653 offset -= 2;
1654 cpu.ss.setWord(offset, (short) cpu.eax);
1655 offset -= 2;
1656 cpu.ss.setWord(offset, (short) cpu.ecx);
1657 offset -= 2;
1658 cpu.ss.setWord(offset, (short) cpu.edx);
1659 offset -= 2;
1660 cpu.ss.setWord(offset, (short) cpu.ebx);
1661 offset -= 2;
1662 cpu.ss.setWord(offset, (short) temp);
1663 offset -= 2;
1664 cpu.ss.setWord(offset, (short) cpu.ebp);
1665 offset -= 2;
1666 cpu.ss.setWord(offset, (short) cpu.esi);
1667 offset -= 2;
1668 cpu.ss.setWord(offset, (short) cpu.edi);
1670 cpu.esp = (cpu.esp & ~offmask) | (offset & offmask);
1673 private final void pushad()
1675 int offset, offmask;
1676 if (cpu.ss.getDefaultSizeFlag()) {
1677 offset = cpu.esp;
1678 offmask = 0xffffffff;
1679 } else {
1680 offset = cpu.esp & 0xffff;
1681 offmask = 0xffff;
1684 int temp = cpu.esp;
1685 if ((offset < 32) && (offset > 0)) {
1686 System.err.println("Emulated: Throwing dodgy pushad exception.");
1687 throw ProcessorException.GENERAL_PROTECTION_0;
1690 offset -= 4;
1691 cpu.ss.setDoubleWord(offset, cpu.eax);
1692 offset -= 4;
1693 cpu.ss.setDoubleWord(offset, cpu.ecx);
1694 offset -= 4;
1695 cpu.ss.setDoubleWord(offset, cpu.edx);
1696 offset -= 4;
1697 cpu.ss.setDoubleWord(offset, cpu.ebx);
1698 offset -= 4;
1699 cpu.ss.setDoubleWord(offset, temp);
1700 offset -= 4;
1701 cpu.ss.setDoubleWord(offset, cpu.ebp);
1702 offset -= 4;
1703 cpu.ss.setDoubleWord(offset, cpu.esi);
1704 offset -= 4;
1705 cpu.ss.setDoubleWord(offset, cpu.edi);
1707 cpu.esp = (cpu.esp & ~offmask) | (offset & offmask);
1710 private final void popa()
1712 int offset, offmask;
1713 if (cpu.ss.getDefaultSizeFlag()) {
1714 offset = cpu.esp;
1715 offmask = 0xffffffff;
1716 } else {
1717 offset = cpu.esp & 0xffff;
1718 offmask = 0xffff;
1721 //Bochs claims no checking need on POPs
1722 //if (offset + 16 >= cpu.ss.limit)
1723 // throw exceptionSS;
1724 cpu.edi = (cpu.edi & ~0xffff) | (0xffff & cpu.ss.getWord(offmask & offset));
1725 offset += 2;
1726 cpu.esi = (cpu.esi & ~0xffff) | (0xffff & cpu.ss.getWord(offmask & offset));
1727 offset += 2;
1728 cpu.ebp = (cpu.ebp & ~0xffff) | (0xffff & cpu.ss.getWord(offmask & offset));
1729 offset += 4;// yes - skip 2 bytes in order to skip SP
1730 cpu.ebx = (cpu.ebx & ~0xffff) | (0xffff & cpu.ss.getWord(offmask & offset));
1731 offset += 2;
1732 cpu.edx = (cpu.edx & ~0xffff) | (0xffff & cpu.ss.getWord(offmask & offset));
1733 offset += 2;
1734 cpu.ecx = (cpu.ecx & ~0xffff) | (0xffff & cpu.ss.getWord(offmask & offset));
1735 offset += 2;
1736 cpu.eax = (cpu.eax & ~0xffff) | (0xffff & cpu.ss.getWord(offmask & offset));
1737 offset += 2;
1739 cpu.esp = (cpu.esp & ~offmask) | (offset & offmask);
1742 private final void popad()
1744 int offset, offmask;
1745 if (cpu.ss.getDefaultSizeFlag()) {
1746 offset = cpu.esp;
1747 offmask = 0xffffffff;
1748 } else {
1749 offset = cpu.esp & 0xffff;
1750 offmask = 0xffff;
1753 //Bochs claims no checking need on POPs
1754 //if (offset + 16 >= cpu.ss.limit)
1755 // throw exceptionSS;
1757 cpu.edi = cpu.ss.getDoubleWord(offmask & offset);
1758 offset += 4;
1759 cpu.esi = cpu.ss.getDoubleWord(offmask & offset);
1760 offset += 4;
1761 cpu.ebp = cpu.ss.getDoubleWord(offmask & offset);
1762 offset += 8;// yes - skip an extra 4 bytes in order to skip SP
1764 cpu.ebx = cpu.ss.getDoubleWord(offmask & offset);
1765 offset += 4;
1766 cpu.edx = cpu.ss.getDoubleWord(offmask & offset);
1767 offset += 4;
1768 cpu.ecx = cpu.ss.getDoubleWord(offmask & offset);
1769 offset += 4;
1770 cpu.eax = cpu.ss.getDoubleWord(offmask & offset);
1771 offset += 4;
1773 cpu.esp = (cpu.esp & ~offmask) | (offset & offmask);
1776 private final void jump_far_o16(int targetEIP, int targetSelector)
1778 cpu.eip = targetEIP;
1779 cpu.cs.setSelector(targetSelector);
1782 private final void jump_far_o32(int targetEIP, int targetSelector)
1784 cpu.eip = targetEIP;
1785 cpu.cs.setSelector(targetSelector);
1788 private final void call_far_o16_a16(int targetEIP, int targetSelector)
1790 if (((cpu.esp & 0xffff) < 4) && ((cpu.esp & 0xffff) > 0))
1791 throw ProcessorException.STACK_SEGMENT_0;
1793 cpu.ss.setWord((cpu.esp - 2) & 0xffff, (short)cpu.cs.getSelector());
1794 cpu.ss.setWord((cpu.esp - 4) & 0xffff, (short)cpu.eip);
1795 cpu.esp = (cpu.esp & ~0xffff) | ((cpu.esp - 4) & 0xffff);
1797 cpu.eip = targetEIP;
1798 cpu.cs.setSelector(targetSelector);
1801 private final void call_abs_o16_a16(int target)
1803 if (((cpu.esp & 0xffff) < 2) && ((cpu.esp & 0xffff) > 0))
1804 throw ProcessorException.STACK_SEGMENT_0;
1805 cpu.ss.setWord((cpu.esp - 2) & 0xffff, (short)cpu.eip);
1806 cpu.esp = (cpu.esp & 0xffff0000) | ((cpu.esp - 2) & 0xffff);
1807 cpu.eip = target;
1810 private final void int_o16_a16(int vector, int position)
1812 if ((cpu.getCR4() & Processor.CR4_VIRTUAL8086_MODE_EXTENSIONS) != 0) {
1813 System.err.println("Critical error: VM8086 extensions not supported.");
1814 throw new IllegalStateException("VM8086 extensions not supported");
1816 if (cpu.eflagsIOPrivilegeLevel < 3)
1818 throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);
1820 cpu.handleSoftVirtual8086ModeInterrupt(vector, getInstructionLength(position));
1823 private final int iret_o16_a16()
1825 if (cpu.eflagsIOPrivilegeLevel == 3) {
1826 try {
1827 cpu.ss.checkAddress((cpu.esp + 5) & 0xffff);
1828 } catch (ProcessorException e) {
1829 throw ProcessorException.STACK_SEGMENT_0;
1831 int newEIP = 0xffff & cpu.ss.getWord(cpu.esp & 0xffff);
1832 if (newEIP > 0xffff)
1833 throw ProcessorException.GENERAL_PROTECTION_0;
1835 int newCS = 0xffff & cpu.ss.getWord((cpu.esp + 2) & 0xffff);
1836 cpu.eip = newEIP;
1837 cpu.cs = SegmentFactory.createVirtual8086ModeSegment(cpu.linearMemory, newCS, true);
1838 int newEFlags = 0xffff & cpu.ss.getWord((cpu.esp + 4) & 0xffff);
1840 cpu.esp = (cpu.esp & 0xffff0000) | ((cpu.esp + 6) & 0xffff);
1842 //don't modify the IOPL
1843 int iopl = (cpu.getEFlags() >> 12) & 3;
1844 newEFlags = newEFlags & ~Processor.IFLAGS_IOPL_MASK;
1845 newEFlags |= (iopl << 12);
1846 return newEFlags;
1847 } else
1848 throw ProcessorException.GENERAL_PROTECTION_0;
1851 private final void cmpsb_a16(Segment seg0)
1853 int addrOne = cpu.esi & 0xffff;
1854 int addrTwo = cpu.edi & 0xffff;
1856 int dataOne = 0xff & seg0.getByte(addrOne);
1857 int dataTwo = 0xff & cpu.es.getByte(addrTwo);
1858 if (cpu.eflagsDirection) {
1859 addrOne -= 1;
1860 addrTwo -= 1;
1861 } else {
1862 addrOne += 1;
1863 addrTwo += 1;
1866 cpu.esi = (cpu.esi & ~0xffff) | (addrOne & 0xffff);
1867 cpu.edi = (cpu.edi & ~0xffff) | (addrTwo & 0xffff);
1869 // sub_o8_flags(dataOne - dataTwo, dataOne, dataTwo);
1870 uCodeXferReg0 = dataOne - dataTwo;
1871 uCodeXferReg1 = dataTwo;
1872 uCodeXferReg2 = dataOne;
1873 uCodeXferLoaded = true;
1876 private final void cmpsw_a16(Segment seg0)
1878 int addrOne = cpu.esi & 0xffff;
1879 int addrTwo = cpu.edi & 0xffff;
1881 int dataOne = 0xffff & seg0.getWord(addrOne);
1882 int dataTwo = 0xffff & cpu.es.getWord(addrTwo);
1883 if (cpu.eflagsDirection) {
1884 addrOne -= 2;
1885 addrTwo -= 2;
1886 } else {
1887 addrOne += 2;
1888 addrTwo += 2;
1891 cpu.esi = (cpu.esi & ~0xffff) | (addrOne & 0xffff);
1892 cpu.edi = (cpu.edi & ~0xffff) | (addrTwo & 0xffff);
1894 // sub_o16_flags(dataOne - dataTwo, dataOne, dataTwo);
1895 uCodeXferReg0 = dataOne - dataTwo;
1896 uCodeXferReg1 = dataTwo;
1897 uCodeXferReg2 = dataOne;
1898 uCodeXferLoaded = true;
1901 private final void cmpsd_a16(Segment seg0)
1903 int addrOne = cpu.esi & 0xffff;
1904 int addrTwo = cpu.edi & 0xffff;
1906 int dataOne = seg0.getDoubleWord(addrOne);
1907 int dataTwo = cpu.es.getDoubleWord(addrTwo);
1908 if (cpu.eflagsDirection) {
1909 addrOne -= 4;
1910 addrTwo -= 4;
1911 } else {
1912 addrOne += 4;
1913 addrTwo += 4;
1916 cpu.esi = (cpu.esi & ~0xffff) | (addrOne & 0xffff);
1917 cpu.edi = (cpu.edi & ~0xffff) | (addrTwo & 0xffff);
1919 // sub_o32_flags((0xffffffffl & dataOne) - (0xffffffffl & dataTwo), dataOne, dataTwo);
1920 uCodeXferReg0 = (int) ((0xffffffffl & dataOne) - (0xffffffffl & dataTwo));
1921 uCodeXferReg1 = dataTwo;
1922 uCodeXferReg2 = dataOne;
1923 uCodeXferLoaded = true;
1926 private final void repe_cmpsb_a16(Segment seg0)
1928 int count = cpu.ecx & 0xffff;
1929 int addrOne = cpu.esi & 0xffff;
1930 int addrTwo = cpu.edi & 0xffff;
1931 boolean used = count != 0;
1932 int dataOne = 0;
1933 int dataTwo = 0;
1935 try {
1936 if (cpu.eflagsDirection) {
1937 while (count != 0) {
1938 //check hardware interrupts
1939 dataOne = 0xff & seg0.getByte(addrOne);
1940 dataTwo = 0xff & cpu.es.getByte(addrTwo);
1941 count--;
1942 addrOne -= 1;
1943 addrTwo -= 1;
1944 if (dataOne != dataTwo) break;
1946 } else {
1947 while (count != 0) {
1948 //check hardware interrupts
1949 dataOne = 0xff & seg0.getByte(addrOne);
1950 dataTwo = 0xff & cpu.es.getByte(addrTwo);
1951 count--;
1952 addrOne += 1;
1953 addrTwo += 1;
1954 if (dataOne != dataTwo) break;
1958 finally {
1959 executeCount += ((cpu.ecx & 0xffff) - count);
1960 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
1961 cpu.esi = (cpu.esi & ~0xffff) | (addrOne & 0xffff);
1962 cpu.edi = (cpu.edi & ~0xffff) | (addrTwo & 0xffff);
1964 // if (used)
1965 // sub_o8_flags(dataOne - dataTwo, dataOne, dataTwo);
1966 uCodeXferReg0 = used ? 1 : 0;
1967 uCodeXferReg1 = dataTwo;
1968 uCodeXferReg2 = dataOne;
1969 uCodeXferLoaded = true;
1973 private final void repe_cmpsw_a16(Segment seg0)
1975 int count = cpu.ecx & 0xffff;
1976 int addrOne = cpu.esi & 0xffff;
1977 int addrTwo = cpu.edi & 0xffff;
1978 boolean used = count != 0;
1979 int dataOne = 0;
1980 int dataTwo = 0;
1982 try {
1983 if (cpu.eflagsDirection) {
1984 while (count != 0) {
1985 //check hardware interrupts
1986 dataOne = 0xffff & seg0.getWord(addrOne);
1987 dataTwo = 0xffff & cpu.es.getWord(addrTwo);
1988 count--;
1989 addrOne -= 2;
1990 addrTwo -= 2;
1991 if (dataOne != dataTwo) break;
1993 } else {
1994 while (count != 0) {
1995 //check hardware interrupts
1996 dataOne = 0xffff & seg0.getWord(addrOne);
1997 dataTwo = 0xffff & cpu.es.getWord(addrTwo);
1998 count--;
1999 addrOne += 2;
2000 addrTwo += 2;
2001 if (dataOne != dataTwo) break;
2005 finally {
2006 executeCount += ((cpu.ecx & 0xffff) - count);
2007 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2008 cpu.esi = (cpu.esi & ~0xffff) | (addrOne & 0xffff);
2009 cpu.edi = (cpu.edi & ~0xffff) | (addrTwo & 0xffff);
2011 // if (used)
2012 // sub_o16_flags(dataOne - dataTwo, dataOne, dataTwo);
2013 uCodeXferReg0 = used ? 1 : 0;
2014 uCodeXferReg1 = dataTwo;
2015 uCodeXferReg2 = dataOne;
2016 uCodeXferLoaded = true;
2020 private final void repe_cmpsd_a16(Segment seg0)
2022 int count = cpu.ecx & 0xffff;
2023 int addrOne = cpu.esi & 0xffff;
2024 int addrTwo = cpu.edi & 0xffff;
2025 boolean used = count != 0;
2026 int dataOne = 0;
2027 int dataTwo = 0;
2029 try {
2030 if (cpu.eflagsDirection) {
2031 while (count != 0) {
2032 //check hardware interrupts
2033 dataOne = seg0.getDoubleWord(addrOne);
2034 dataTwo = cpu.es.getDoubleWord(addrTwo);
2035 count--;
2036 addrOne -= 4;
2037 addrTwo -= 4;
2038 if (dataOne != dataTwo) break;
2040 } else {
2041 while (count != 0) {
2042 //check hardware interrupts
2043 dataOne = seg0.getDoubleWord(addrOne);
2044 dataTwo = cpu.es.getDoubleWord(addrTwo);
2045 count--;
2046 addrOne += 4;
2047 addrTwo += 4;
2048 if (dataOne != dataTwo) break;
2052 finally {
2053 executeCount += ((cpu.ecx & 0xffff) - count);
2054 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2055 cpu.esi = (cpu.esi & ~0xffff) | (addrOne & 0xffff);
2056 cpu.edi = (cpu.edi & ~0xffff) | (addrTwo & 0xffff);
2058 // if (used)
2059 // sub_o32_flags((0xffffffffl & dataOne) - (0xffffffffl & dataTwo), dataOne, dataTwo);
2060 uCodeXferReg0 = used ? 1 : 0;
2061 uCodeXferReg1 = dataTwo;
2062 uCodeXferReg2 = dataOne;
2063 uCodeXferLoaded = true;
2067 private final void insb_a16(int port)
2069 if (!checkIOPermissionsByte(port))
2070 throw ProcessorException.GENERAL_PROTECTION_0;
2072 int addr = cpu.edi & 0xffff;
2074 cpu.es.setByte(addr & 0xffff, (byte)cpu.ioports.ioPortReadByte(port));
2075 if (cpu.eflagsDirection) {
2076 addr -= 1;
2077 } else {
2078 addr += 1;
2081 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
2084 private final void insw_a16(int port)
2086 if (!checkIOPermissionsShort(port))
2087 throw ProcessorException.GENERAL_PROTECTION_0;
2089 int addr = cpu.edi & 0xffff;
2091 cpu.es.setWord(addr & 0xffff, (short)cpu.ioports.ioPortReadWord(port));
2092 if (cpu.eflagsDirection) {
2093 addr -= 2;
2094 } else {
2095 addr += 2;
2098 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
2101 private final void insd_a16(int port)
2103 if (!checkIOPermissionsInt(port))
2104 throw ProcessorException.GENERAL_PROTECTION_0;
2106 int addr = cpu.edi & 0xffff;
2108 cpu.es.setDoubleWord(addr & 0xffff, cpu.ioports.ioPortReadLong(port));
2109 if (cpu.eflagsDirection) {
2110 addr -= 4;
2111 } else {
2112 addr += 4;
2115 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
2118 private final void rep_insb_a16(int port)
2120 if (!checkIOPermissionsByte(port))
2121 throw ProcessorException.GENERAL_PROTECTION_0;
2123 int count = cpu.ecx & 0xffff;
2124 int addr = cpu.edi & 0xffff;
2125 executeCount += count;
2127 try {
2128 if (cpu.eflagsDirection) {
2129 while (count != 0) {
2130 //check hardware interrupts
2131 cpu.es.setByte(addr & 0xffff, (byte)cpu.ioports.ioPortReadByte(port));
2132 count--;
2133 addr -= 1;
2135 } else {
2136 while (count != 0) {
2137 //check hardware interrupts
2138 cpu.es.setByte(addr & 0xffff, (byte)cpu.ioports.ioPortReadByte(port));
2139 count--;
2140 addr += 1;
2144 finally {
2145 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2146 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
2150 private final void rep_insw_a16(int port)
2152 if (!checkIOPermissionsShort(port))
2153 throw ProcessorException.GENERAL_PROTECTION_0;
2155 int count = cpu.ecx & 0xffff;
2156 int addr = cpu.edi & 0xffff;
2157 executeCount += count;
2159 try {
2160 if (cpu.eflagsDirection) {
2161 while (count != 0) {
2162 //check hardware interrupts
2163 cpu.es.setWord(addr & 0xffff, (short)cpu.ioports.ioPortReadWord(port));
2164 count--;
2165 addr -= 2;
2167 } else {
2168 while (count != 0) {
2169 //check hardware interrupts
2170 cpu.es.setWord(addr & 0xffff, (short)cpu.ioports.ioPortReadWord(port));
2171 count--;
2172 addr += 2;
2176 finally {
2177 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2178 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
2182 private final void rep_insd_a16(int port)
2184 if (!checkIOPermissionsInt(port))
2185 throw ProcessorException.GENERAL_PROTECTION_0;
2187 int count = cpu.ecx & 0xffff;
2188 int addr = cpu.edi & 0xffff;
2189 executeCount += count;
2191 try {
2192 if (cpu.eflagsDirection) {
2193 while (count != 0) {
2194 //check hardware interrupts
2195 cpu.es.setDoubleWord(addr & 0xffff, cpu.ioports.ioPortReadLong(port));
2196 count--;
2197 addr -= 4;
2199 } else {
2200 while (count != 0) {
2201 //check hardware interrupts
2202 cpu.es.setDoubleWord(addr & 0xffff, cpu.ioports.ioPortReadLong(port));
2203 count--;
2204 addr += 4;
2208 finally {
2209 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2210 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
2214 private final void lodsb_a16(Segment dataSegment)
2216 int addr = cpu.esi & 0xffff;
2217 cpu.eax = (cpu.eax & ~0xff) | (0xff & dataSegment.getByte(addr));
2219 if (cpu.eflagsDirection)
2220 addr -= 1;
2221 else
2222 addr += 1;
2224 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2227 private final void lodsw_a16(Segment dataSegment)
2229 int addr = cpu.esi & 0xffff;
2230 cpu.eax = (cpu.eax & ~0xffff) | (0xffff & dataSegment.getWord(addr));
2232 if (cpu.eflagsDirection)
2233 addr -= 2;
2234 else
2235 addr += 2;
2237 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2240 private final void lodsd_a16(Segment dataSegment)
2242 int addr = cpu.esi & 0xffff;
2243 cpu.eax = dataSegment.getDoubleWord(addr);
2245 if (cpu.eflagsDirection)
2246 addr -= 4;
2247 else
2248 addr += 4;
2250 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2253 private final void rep_lodsb_a16(Segment dataSegment)
2255 int count = cpu.ecx & 0xffff;
2256 int addr = cpu.esi & 0xffff;
2257 int data = cpu.eax & 0xff;
2258 executeCount += count;
2260 try {
2261 if (cpu.eflagsDirection) {
2262 while (count != 0) {
2263 //check hardware interrupts
2264 data = 0xff & dataSegment.getByte(addr & 0xffff);
2265 count--;
2266 addr -= 1;
2268 } else {
2269 while (count != 0) {
2270 //check hardware interrupts
2271 data = 0xff & dataSegment.getByte(addr & 0xffff);
2272 count--;
2273 addr += 1;
2277 finally {
2278 cpu.eax = (cpu.eax & ~0xff) | data;
2279 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2280 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2284 private final void rep_lodsw_a16(Segment dataSegment)
2286 int count = cpu.ecx & 0xffff;
2287 int addr = cpu.esi & 0xffff;
2288 int data = cpu.eax & 0xffff;
2289 executeCount += count;
2291 try {
2292 if (cpu.eflagsDirection) {
2293 while (count != 0) {
2294 //check hardware interrupts
2295 data = 0xffff & dataSegment.getWord(addr & 0xffff);
2296 count--;
2297 addr -= 2;
2299 } else {
2300 while (count != 0) {
2301 //check hardware interrupts
2302 data = 0xffff & dataSegment.getWord(addr & 0xffff);
2303 count--;
2304 addr += 2;
2308 finally {
2309 cpu.eax = (cpu.eax & ~0xffff) | data;
2310 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2311 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2315 private final void rep_lodsd_a16(Segment dataSegment)
2317 int count = cpu.ecx & 0xffff;
2318 int addr = cpu.esi & 0xffff;
2319 int data = cpu.eax;
2320 executeCount += count;
2322 try {
2323 if (cpu.eflagsDirection) {
2324 while (count != 0) {
2325 //check hardware interrupts
2326 data = dataSegment.getDoubleWord(addr & 0xffff);
2327 count--;
2328 addr -= 4;
2330 } else {
2331 while (count != 0) {
2332 //check hardware interrupts
2333 data = dataSegment.getDoubleWord(addr & 0xffff);
2334 count--;
2335 addr += 4;
2339 finally {
2340 cpu.eax = data;
2341 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2342 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2346 private final void lodsb_a32(Segment dataSegment)
2348 int addr = cpu.esi;
2349 cpu.eax = (cpu.eax & ~0xff) | (0xff & dataSegment.getByte(addr));
2351 if (cpu.eflagsDirection)
2352 addr -= 1;
2353 else
2354 addr += 1;
2356 cpu.esi = addr;
2359 private final void lodsw_a32(Segment dataSegment)
2361 int addr = cpu.esi;
2362 cpu.eax = (cpu.eax & ~0xffff) | (0xffff & dataSegment.getWord(addr));
2364 if (cpu.eflagsDirection)
2365 addr -= 2;
2366 else
2367 addr += 2;
2369 cpu.esi = addr;
2372 private final void lodsd_a32(Segment dataSegment)
2374 int addr = cpu.esi;
2375 cpu.eax = dataSegment.getDoubleWord(addr);
2377 if (cpu.eflagsDirection)
2378 addr -= 4;
2379 else
2380 addr += 4;
2382 cpu.esi = addr;
2385 private final void rep_lodsb_a32(Segment dataSegment)
2387 int count = cpu.ecx;
2388 int addr = cpu.esi;
2389 int data = cpu.eax & 0xff;
2390 executeCount += count;
2392 try {
2393 if (cpu.eflagsDirection) {
2394 while (count != 0) {
2395 //check hardware interrupts
2396 data = 0xff & dataSegment.getByte(addr);
2397 count--;
2398 addr -= 1;
2400 } else {
2401 while (count != 0) {
2402 //check hardware interrupts
2403 data = 0xff & dataSegment.getByte(addr);
2404 count--;
2405 addr += 1;
2409 finally {
2410 cpu.eax = (cpu.eax & ~0xff) | data;
2411 cpu.ecx = count;
2412 cpu.esi = addr;
2416 private final void rep_lodsw_a32(Segment dataSegment)
2418 int count = cpu.ecx;
2419 int addr = cpu.esi;
2420 int data = cpu.eax & 0xffff;
2421 executeCount += count;
2423 try {
2424 if (cpu.eflagsDirection) {
2425 while (count != 0) {
2426 //check hardware interrupts
2427 data = 0xffff & dataSegment.getWord(addr);
2428 count--;
2429 addr -= 2;
2431 } else {
2432 while (count != 0) {
2433 //check hardware interrupts
2434 data = 0xffff & dataSegment.getWord(addr);
2435 count--;
2436 addr += 2;
2440 finally {
2441 cpu.eax = (cpu.eax & ~0xffff) | data;
2442 cpu.ecx = count;
2443 cpu.esi = addr;
2447 private final void rep_lodsd_a32(Segment dataSegment)
2449 int count = cpu.ecx;
2450 int addr = cpu.esi;
2451 int data = cpu.eax;
2452 executeCount += count;
2454 try {
2455 if (cpu.eflagsDirection) {
2456 while (count != 0) {
2457 //check hardware interrupts
2458 data = dataSegment.getDoubleWord(addr);
2459 count--;
2460 addr -= 4;
2462 } else {
2463 while (count != 0) {
2464 //check hardware interrupts
2465 data = dataSegment.getDoubleWord(addr);
2466 count--;
2467 addr += 4;
2471 finally {
2472 cpu.eax = data;
2473 cpu.ecx = count;
2474 cpu.esi = addr;
2478 private final void movsb_a16(Segment outSegment)
2480 int inAddr = cpu.edi & 0xffff;
2481 int outAddr = cpu.esi & 0xffff;
2483 cpu.es.setByte(inAddr, outSegment.getByte(outAddr));
2484 if (cpu.eflagsDirection) {
2485 outAddr -= 1;
2486 inAddr -= 1;
2487 } else {
2488 outAddr += 1;
2489 inAddr += 1;
2492 cpu.edi = (cpu.edi & ~0xffff) | (inAddr & 0xffff);
2493 cpu.esi = (cpu.esi & ~0xffff) | (outAddr & 0xffff);
2496 private final void movsw_a16(Segment outSegment)
2498 int inAddr = cpu.edi & 0xffff;
2499 int outAddr = cpu.esi & 0xffff;
2501 cpu.es.setWord(inAddr, outSegment.getWord(outAddr));
2502 if (cpu.eflagsDirection) {
2503 outAddr -= 2;
2504 inAddr -= 2;
2505 } else {
2506 outAddr += 2;
2507 inAddr += 2;
2510 cpu.edi = (cpu.edi & ~0xffff) | (inAddr & 0xffff);
2511 cpu.esi = (cpu.esi & ~0xffff) | (outAddr & 0xffff);
2514 private final void movsd_a16(Segment outSegment)
2516 int inAddr = cpu.edi & 0xffff;
2517 int outAddr = cpu.esi & 0xffff;
2519 cpu.es.setDoubleWord(inAddr, outSegment.getDoubleWord(outAddr));
2520 if (cpu.eflagsDirection) {
2521 outAddr -= 4;
2522 inAddr -= 4;
2523 } else {
2524 outAddr += 4;
2525 inAddr += 4;
2528 cpu.edi = (cpu.edi & ~0xffff) | (inAddr & 0xffff);
2529 cpu.esi = (cpu.esi & ~0xffff) | (outAddr & 0xffff);
2532 private final void rep_movsb_a16(Segment outSegment)
2534 int count = cpu.ecx & 0xffff;
2535 int inAddr = cpu.edi & 0xffff;
2536 int outAddr = cpu.esi & 0xffff;
2537 executeCount += count;
2539 try {
2540 if (cpu.eflagsDirection) {
2541 while (count != 0) {
2542 //check hardware interrupts
2543 cpu.es.setByte(inAddr & 0xffff, outSegment.getByte(outAddr & 0xffff));
2544 count--;
2545 outAddr -= 1;
2546 inAddr -= 1;
2548 } else {
2549 while (count != 0) {
2550 //check hardware interrupts
2551 cpu.es.setByte(inAddr & 0xffff, outSegment.getByte(outAddr & 0xffff));
2552 count--;
2553 outAddr += 1;
2554 inAddr += 1;
2558 finally {
2559 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2560 cpu.edi = (cpu.edi & ~0xffff) | (inAddr & 0xffff);
2561 cpu.esi = (cpu.esi & ~0xffff) | (outAddr & 0xffff);
2565 private final void rep_movsw_a16(Segment outSegment)
2567 int count = cpu.ecx & 0xffff;
2568 int inAddr = cpu.edi & 0xffff;
2569 int outAddr = cpu.esi & 0xffff;
2570 executeCount += count;
2572 try {
2573 if (cpu.eflagsDirection) {
2574 while (count != 0) {
2575 //check hardware interrupts
2576 cpu.es.setWord(inAddr & 0xffff, outSegment.getWord(outAddr & 0xffff));
2577 count--;
2578 outAddr -= 2;
2579 inAddr -= 2;
2581 } else {
2582 while (count != 0) {
2583 //check hardware interrupts
2584 cpu.es.setWord(inAddr & 0xffff, outSegment.getWord(outAddr & 0xffff));
2585 count--;
2586 outAddr += 2;
2587 inAddr += 2;
2591 finally {
2592 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2593 cpu.edi = (cpu.edi & ~0xffff) | (inAddr & 0xffff);
2594 cpu.esi = (cpu.esi & ~0xffff) | (outAddr & 0xffff);
2598 private final void rep_movsd_a16(Segment outSegment)
2600 int count = cpu.ecx & 0xffff;
2601 int inAddr = cpu.edi & 0xffff;
2602 int outAddr = cpu.esi & 0xffff;
2603 executeCount += count;
2605 try {
2606 if (cpu.eflagsDirection) {
2607 while (count != 0) {
2608 //check hardware interrupts
2609 cpu.es.setDoubleWord(inAddr & 0xffff, outSegment.getDoubleWord(outAddr & 0xffff));
2610 count--;
2611 outAddr -= 4;
2612 inAddr -= 4;
2614 } else {
2615 while (count != 0) {
2616 //check hardware interrupts
2617 cpu.es.setDoubleWord(inAddr & 0xffff, outSegment.getDoubleWord(outAddr & 0xffff));
2618 count--;
2619 outAddr += 4;
2620 inAddr += 4;
2624 finally {
2625 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2626 cpu.edi = (cpu.edi & ~0xffff) | (inAddr & 0xffff);
2627 cpu.esi = (cpu.esi & ~0xffff) | (outAddr & 0xffff);
2631 private final void movsb_a32(Segment outSegment)
2633 int inAddr = cpu.edi;
2634 int outAddr = cpu.esi;
2636 cpu.es.setByte(inAddr, outSegment.getByte(outAddr));
2637 if (cpu.eflagsDirection) {
2638 outAddr -= 1;
2639 inAddr -= 1;
2640 } else {
2641 outAddr += 1;
2642 inAddr += 1;
2645 cpu.edi = inAddr;
2646 cpu.esi = outAddr;
2649 private final void movsw_a32(Segment outSegment)
2651 int inAddr = cpu.edi;
2652 int outAddr = cpu.esi;
2654 cpu.es.setWord(inAddr, outSegment.getWord(outAddr));
2655 if (cpu.eflagsDirection) {
2656 outAddr -= 2;
2657 inAddr -= 2;
2658 } else {
2659 outAddr += 2;
2660 inAddr += 2;
2663 cpu.edi = inAddr;
2664 cpu.esi = outAddr;
2667 private final void movsd_a32(Segment outSegment)
2669 int inAddr = cpu.edi;
2670 int outAddr = cpu.esi;
2672 cpu.es.setDoubleWord(inAddr, outSegment.getDoubleWord(outAddr));
2673 if (cpu.eflagsDirection) {
2674 outAddr -= 4;
2675 inAddr -= 4;
2676 } else {
2677 outAddr += 4;
2678 inAddr += 4;
2681 cpu.edi = inAddr & 0xffff;
2682 cpu.esi = outAddr & 0xffff;
2685 private final void rep_movsb_a32(Segment outSegment)
2687 int count = cpu.ecx;
2688 int inAddr = cpu.edi;
2689 int outAddr = cpu.esi;
2690 executeCount += count;
2692 try {
2693 if (cpu.eflagsDirection) {
2694 while (count != 0) {
2695 //check hardware interrupts
2696 cpu.es.setByte(inAddr, outSegment.getByte(outAddr));
2697 count--;
2698 outAddr -= 1;
2699 inAddr -= 1;
2701 } else {
2702 while (count != 0) {
2703 //check hardware interrupts
2704 cpu.es.setByte(inAddr, outSegment.getByte(outAddr));
2705 count--;
2706 outAddr += 1;
2707 inAddr += 1;
2711 finally {
2712 cpu.ecx = count;
2713 cpu.edi = inAddr;
2714 cpu.esi = outAddr;
2718 private final void rep_movsw_a32(Segment outSegment)
2720 int count = cpu.ecx;
2721 int inAddr = cpu.edi;
2722 int outAddr = cpu.esi;
2723 executeCount += count;
2725 try {
2726 if (cpu.eflagsDirection) {
2727 while (count != 0) {
2728 //check hardware interrupts
2729 cpu.es.setWord(inAddr, outSegment.getWord(outAddr));
2730 count--;
2731 outAddr -= 2;
2732 inAddr -= 2;
2734 } else {
2735 while (count != 0) {
2736 //check hardware interrupts
2737 cpu.es.setWord(inAddr, outSegment.getWord(outAddr));
2738 count--;
2739 outAddr += 2;
2740 inAddr += 2;
2744 finally {
2745 cpu.ecx = count;
2746 cpu.edi = inAddr;
2747 cpu.esi = outAddr;
2751 private final void rep_movsd_a32(Segment outSegment)
2753 int count = cpu.ecx;
2754 int inAddr = cpu.edi;
2755 int outAddr = cpu.esi;
2756 executeCount += count;
2758 try {
2759 if (cpu.eflagsDirection) {
2760 while (count != 0) {
2761 //check hardware interrupts
2762 cpu.es.setDoubleWord(inAddr, outSegment.getDoubleWord(outAddr));
2763 count--;
2764 outAddr -= 4;
2765 inAddr -= 4;
2767 } else {
2768 while (count != 0) {
2769 //check hardware interrupts
2770 cpu.es.setDoubleWord(inAddr, outSegment.getDoubleWord(outAddr));
2771 count--;
2772 outAddr += 4;
2773 inAddr += 4;
2777 finally {
2778 cpu.ecx = count;
2779 cpu.edi = inAddr;
2780 cpu.esi = outAddr;
2784 private final void outsb_a16(int port, Segment storeSegment)
2786 if (!checkIOPermissionsByte(port))
2787 throw ProcessorException.GENERAL_PROTECTION_0;
2789 int addr = cpu.esi & 0xffff;
2791 cpu.ioports.ioPortWriteByte(port, 0xff & storeSegment.getByte(addr));
2793 if (cpu.eflagsDirection)
2794 addr -= 1;
2795 else
2796 addr += 1;
2798 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2801 private final void outsw_a16(int port, Segment storeSegment)
2803 if (!checkIOPermissionsShort(port))
2804 throw ProcessorException.GENERAL_PROTECTION_0;
2806 int addr = cpu.esi & 0xffff;
2808 cpu.ioports.ioPortWriteWord(port, 0xffff & storeSegment.getWord(addr));
2810 if (cpu.eflagsDirection)
2811 addr -= 2;
2812 else
2813 addr += 2;
2815 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2818 private final void outsd_a16(int port, Segment storeSegment)
2820 if (!checkIOPermissionsInt(port))
2821 throw ProcessorException.GENERAL_PROTECTION_0;
2823 int addr = cpu.esi & 0xffff;
2825 cpu.ioports.ioPortWriteLong(port, storeSegment.getDoubleWord(addr));
2827 if (cpu.eflagsDirection)
2828 addr -= 4;
2829 else
2830 addr += 4;
2832 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2835 private final void rep_outsb_a16(int port, Segment storeSegment)
2837 if (!checkIOPermissionsByte(port))
2838 throw ProcessorException.GENERAL_PROTECTION_0;
2840 int count = cpu.ecx & 0xffff;
2841 int addr = cpu.esi & 0xffff;
2842 executeCount += count;
2844 try {
2845 if (cpu.eflagsDirection) {
2846 while (count != 0) {
2847 //check hardware interrupts
2848 cpu.ioports.ioPortWriteByte(port, 0xffff & storeSegment.getByte(addr & 0xffff));
2849 count--;
2850 addr -= 1;
2852 } else {
2853 while (count != 0) {
2854 //check hardware interrupts
2855 cpu.ioports.ioPortWriteByte(port, 0xffff & storeSegment.getByte(addr & 0xffff));
2856 count--;
2857 addr += 1;
2861 finally {
2862 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2863 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2867 private final void rep_outsw_a16(int port, Segment storeSegment)
2869 if (!checkIOPermissionsShort(port))
2870 throw ProcessorException.GENERAL_PROTECTION_0;
2872 int count = cpu.ecx & 0xffff;
2873 int addr = cpu.esi & 0xffff;
2874 executeCount += count;
2876 try {
2877 if (cpu.eflagsDirection) {
2878 while (count != 0) {
2879 //check hardware interrupts
2880 cpu.ioports.ioPortWriteWord(port, 0xffff & storeSegment.getWord(addr & 0xffff));
2881 count--;
2882 addr -= 2;
2884 } else {
2885 while (count != 0) {
2886 //check hardware interrupts
2887 cpu.ioports.ioPortWriteWord(port, 0xffff & storeSegment.getWord(addr & 0xffff));
2888 count--;
2889 addr += 2;
2893 finally {
2894 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2895 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2899 private final void rep_outsd_a16(int port, Segment storeSegment)
2901 if (!checkIOPermissionsInt(port))
2902 throw ProcessorException.GENERAL_PROTECTION_0;
2904 int count = cpu.ecx & 0xffff;
2905 int addr = cpu.esi & 0xffff;
2906 executeCount += count;
2908 try {
2909 if (cpu.eflagsDirection) {
2910 while (count != 0) {
2911 //check hardware interrupts
2912 cpu.ioports.ioPortWriteLong(port, storeSegment.getDoubleWord(addr & 0xffff));
2913 count--;
2914 addr -= 4;
2916 } else {
2917 while (count != 0) {
2918 //check hardware interrupts
2919 cpu.ioports.ioPortWriteLong(port, storeSegment.getDoubleWord(addr & 0xffff));
2920 count--;
2921 addr += 4;
2925 finally {
2926 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
2927 cpu.esi = (cpu.esi & ~0xffff) | (addr & 0xffff);
2931 private final void scasb_a16(int data)
2933 int addr = cpu.edi & 0xffff;
2934 int input = 0xff & cpu.es.getByte(addr);
2936 if (cpu.eflagsDirection)
2937 addr -= 1;
2938 else
2939 addr += 1;
2941 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
2942 // sub_o8_flags(data - input, data, input);
2943 uCodeXferReg0 = data - input;
2944 uCodeXferReg1 = input;
2945 uCodeXferReg2 = data;
2946 uCodeXferLoaded = true;
2949 private final void scasw_a16(int data)
2951 int addr = cpu.edi & 0xffff;
2952 int input = 0xffff & cpu.es.getWord(addr);
2954 if (cpu.eflagsDirection)
2955 addr -= 2;
2956 else
2957 addr += 2;
2959 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
2960 // sub_o16_flags(data - input, data, input);
2961 uCodeXferReg0 = data - input;
2962 uCodeXferReg1 = input;
2963 uCodeXferReg2 = data;
2964 uCodeXferLoaded = true;
2967 private final void scasd_a16(int data)
2969 int addr = cpu.edi & 0xffff;
2970 int input = cpu.es.getDoubleWord(addr);
2972 if (cpu.eflagsDirection)
2973 addr -= 4;
2974 else
2975 addr += 4;
2977 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
2978 // sub_o32_flags((0xffffffffl & data) - (0xffffffffl & input), data, input);
2979 uCodeXferReg0 = (int) ((0xffffffffl & data) - (0xffffffffl & input));
2980 uCodeXferReg1 = input;
2981 uCodeXferReg2 = data;
2982 uCodeXferLoaded = true;
2985 private final void repe_scasb_a16(int data)
2987 int count = cpu.ecx & 0xffff;
2988 int addr = cpu.edi & 0xffff;
2989 boolean used = count != 0;
2990 int input = 0;
2992 try {
2993 if (cpu.eflagsDirection) {
2994 while (count != 0) {
2995 input = 0xff & cpu.es.getByte(addr);
2996 count--;
2997 addr -= 1;
2998 if (data != input) break;
3000 } else {
3001 while (count != 0) {
3002 input = 0xff & cpu.es.getByte(addr);
3003 count--;
3004 addr += 1;
3005 if (data != input) break;
3008 } finally {
3009 executeCount += ((cpu.ecx & 0xffff) - count);
3010 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
3011 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
3012 // if (used)
3013 // sub_o8_flags(data - input, data, input);
3014 uCodeXferReg0 = used ? 1 : 0;
3015 uCodeXferReg1 = input;
3016 uCodeXferReg2 = data;
3017 uCodeXferLoaded = true;
3021 private final void repe_scasw_a16(int data)
3023 int count = cpu.ecx & 0xffff;
3024 int addr = cpu.edi & 0xffff;
3025 int input = 0;
3027 try {
3028 if (cpu.eflagsDirection) {
3029 while (count != 0) {
3030 input = 0xffff & cpu.es.getWord(addr);
3031 count--;
3032 addr -= 2;
3033 if (data != input) break;
3035 } else {
3036 while (count != 0) {
3037 input = 0xffff & cpu.es.getWord(addr);
3038 count--;
3039 addr += 2;
3040 if (data != input) break;
3043 } finally {
3044 executeCount += ((cpu.ecx & 0xffff) - count);
3045 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
3046 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
3047 // if (used)
3048 // sub_o16_flags(data - input, data, input);
3049 uCodeXferReg0 = data - input;
3050 uCodeXferReg1 = input;
3051 uCodeXferReg2 = data;
3052 uCodeXferLoaded = true;
3056 private final void repe_scasd_a16(int data)
3058 int count = cpu.ecx & 0xffff;
3059 int addr = cpu.edi & 0xffff;
3060 boolean used = count != 0;
3061 int input = 0;
3063 try {
3064 if (cpu.eflagsDirection) {
3065 while (count != 0) {
3066 input = cpu.es.getDoubleWord(addr);
3067 count--;
3068 addr -= 4;
3069 if (data != input) break;
3071 } else {
3072 while (count != 0) {
3073 input = cpu.es.getDoubleWord(addr);
3074 count--;
3075 addr += 4;
3076 if (data != input) break;
3079 } finally {
3080 executeCount += ((cpu.ecx & 0xffff) - count);
3081 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
3082 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
3083 // if (used)
3084 // sub_o32_flags((0xffffffffl & data) - (0xffffffffl & input), data, input);
3085 uCodeXferReg0 = used ? 1 : 0;
3086 uCodeXferReg1 = input;
3087 uCodeXferReg2 = data;
3088 uCodeXferLoaded = true;
3092 private final void repne_scasb_a16(int data)
3094 int count = cpu.ecx & 0xffff;
3095 int addr = cpu.edi & 0xffff;
3096 boolean used = count != 0;
3097 int input = 0;
3099 try {
3100 if (cpu.eflagsDirection) {
3101 while (count != 0) {
3102 input = 0xff & cpu.es.getByte(addr);
3103 count--;
3104 addr -= 1;
3105 if (data == input) break;
3107 } else {
3108 while (count != 0) {
3109 input = 0xff & cpu.es.getByte(addr);
3110 count--;
3111 addr += 1;
3112 if (data == input) break;
3115 } finally {
3116 executeCount += ((cpu.ecx & 0xffff) - count);
3117 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
3118 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
3119 // if (used)
3120 // sub_o8_flags(data - input, data, input);
3121 uCodeXferReg0 = used ? 1 : 0;
3122 uCodeXferReg1 = input;
3123 uCodeXferReg2 = data;
3124 uCodeXferLoaded = true;
3128 private final void repne_scasw_a16(int data)
3130 int count = cpu.ecx & 0xffff;
3131 int addr = cpu.edi & 0xffff;
3132 boolean used = count != 0;
3133 int input = 0;
3135 try {
3136 if (cpu.eflagsDirection) {
3137 while (count != 0) {
3138 input = 0xffff & cpu.es.getWord(addr);
3139 count--;
3140 addr -= 2;
3141 if (data == input) break;
3143 } else {
3144 while (count != 0) {
3145 input = 0xffff & cpu.es.getWord(addr);
3146 count--;
3147 addr += 2;
3148 if (data == input) break;
3151 } finally {
3152 executeCount += ((cpu.ecx & 0xffff) - count);
3153 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
3154 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
3155 // if (used)
3156 // sub_o16_flags(data - input, data, input);
3157 uCodeXferReg0 = used ? 1 : 0;
3158 uCodeXferReg1 = input;
3159 uCodeXferReg2 = data;
3160 uCodeXferLoaded = true;
3164 private final void repne_scasd_a16(int data)
3166 int count = cpu.ecx & 0xffff;
3167 int addr = cpu.edi & 0xffff;
3168 boolean used = count != 0;
3169 int input = 0;
3171 try {
3172 if (cpu.eflagsDirection) {
3173 while (count != 0) {
3174 input = cpu.es.getDoubleWord(addr);
3175 count--;
3176 addr -= 4;
3177 if (data == input) break;
3179 } else {
3180 while (count != 0) {
3181 input = cpu.es.getDoubleWord(addr);
3182 count--;
3183 addr += 4;
3184 if (data == input) break;
3187 } finally {
3188 executeCount += ((cpu.ecx & 0xffff) - count);
3189 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
3190 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
3191 // if (used)
3192 // sub_o32_flags((0xffffffffl & data) - (0xffffffffl & input), data, input);
3193 uCodeXferReg0 = used ? 1 : 0;
3194 uCodeXferReg1 = input;
3195 uCodeXferReg2 = data;
3196 uCodeXferLoaded = true;
3200 private final void stosb_a16(int data)
3202 int addr = cpu.edi & 0xffff;
3203 cpu.es.setByte(addr, (byte)data);
3205 if (cpu.eflagsDirection)
3206 addr -= 1;
3207 else
3208 addr += 1;
3210 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
3213 private final void stosw_a16(int data)
3215 int addr = cpu.edi & 0xffff;
3216 cpu.es.setWord(addr, (short)data);
3218 if (cpu.eflagsDirection)
3219 addr -= 2;
3220 else
3221 addr += 2;
3223 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
3226 private final void stosd_a16(int data)
3228 int addr = cpu.edi & 0xffff;
3229 cpu.es.setDoubleWord(addr, data);
3231 if (cpu.eflagsDirection)
3232 addr -= 4;
3233 else
3234 addr += 4;
3236 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
3239 private final void rep_stosb_a16(int data)
3241 int count = cpu.ecx & 0xffff;
3242 int addr = cpu.edi & 0xffff;
3243 executeCount += count;
3245 try {
3246 if (cpu.eflagsDirection) {
3247 while (count != 0) {
3248 //check hardware interrupts
3249 cpu.es.setByte(addr & 0xffff, (byte)data);
3250 count--;
3251 addr -= 1;
3253 } else {
3254 while (count != 0) {
3255 //check hardware interrupts
3256 cpu.es.setByte(addr & 0xffff, (byte)data);
3257 count--;
3258 addr += 1;
3262 finally {
3263 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
3264 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
3268 private final void rep_stosw_a16(int data)
3270 int count = cpu.ecx & 0xffff;
3271 int addr = cpu.edi & 0xffff;
3272 executeCount += count;
3274 try {
3275 if (cpu.eflagsDirection) {
3276 while (count != 0) {
3277 //check hardware interrupts
3278 cpu.es.setWord(addr & 0xffff, (short)data);
3279 count--;
3280 addr -= 2;
3282 } else {
3283 while (count != 0) {
3284 //check hardware interrupts
3285 cpu.es.setWord(addr & 0xffff, (short)data);
3286 count--;
3287 addr += 2;
3291 finally {
3292 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
3293 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
3297 private final void rep_stosd_a16(int data)
3299 int count = cpu.ecx & 0xffff;
3300 int addr = cpu.edi & 0xffff;
3301 executeCount += count;
3303 try {
3304 if (cpu.eflagsDirection) {
3305 while (count != 0) {
3306 //check hardware interrupts
3307 cpu.es.setDoubleWord(addr & 0xffff, data);
3308 count--;
3309 addr -= 4;
3311 } else {
3312 while (count != 0) {
3313 //check hardware interrupts
3314 cpu.es.setDoubleWord(addr & 0xffff, data);
3315 count--;
3316 addr += 4;
3320 finally {
3321 cpu.ecx = (cpu.ecx & ~0xffff) | (count & 0xffff);
3322 cpu.edi = (cpu.edi & ~0xffff) | (addr & 0xffff);
3326 private final void stosb_a32(int data)
3328 int addr = cpu.edi;
3329 cpu.es.setByte(addr, (byte)data);
3331 if (cpu.eflagsDirection)
3332 addr -= 1;
3333 else
3334 addr += 1;
3336 cpu.edi = addr;
3339 private final void stosw_a32(int data)
3341 int addr = cpu.edi;
3342 cpu.es.setWord(addr, (short)data);
3344 if (cpu.eflagsDirection)
3345 addr -= 2;
3346 else
3347 addr += 2;
3349 cpu.edi = addr;
3352 private final void stosd_a32(int data)
3354 int addr = cpu.edi;
3355 cpu.es.setDoubleWord(addr, data);
3357 if (cpu.eflagsDirection)
3358 addr -= 4;
3359 else
3360 addr += 4;
3362 cpu.edi = addr;
3365 private final void rep_stosb_a32(int data)
3367 int count = cpu.ecx;
3368 int addr = cpu.edi;
3369 executeCount += count;
3371 try {
3372 if (cpu.eflagsDirection) {
3373 while (count != 0) {
3374 //check hardware interrupts
3375 cpu.es.setByte(addr, (byte)data);
3376 count--;
3377 addr -= 1;
3379 } else {
3380 while (count != 0) {
3381 //check hardware interrupts
3382 cpu.es.setByte(addr, (byte)data);
3383 count--;
3384 addr += 1;
3388 finally {
3389 cpu.ecx = count;
3390 cpu.edi = addr;
3394 private final void rep_stosw_a32(int data)
3396 int count = cpu.ecx;
3397 int addr = cpu.edi;
3398 executeCount += count;
3400 try {
3401 if (cpu.eflagsDirection) {
3402 while (count != 0) {
3403 //check hardware interrupts
3404 cpu.es.setWord(addr, (short)data);
3405 count--;
3406 addr -= 2;
3408 } else {
3409 while (count != 0) {
3410 //check hardware interrupts
3411 cpu.es.setWord(addr, (short)data);
3412 count--;
3413 addr += 2;
3417 finally {
3418 cpu.ecx = count;
3419 cpu.edi = addr;
3423 private final void rep_stosd_a32(int data)
3425 int count = cpu.ecx;
3426 int addr = cpu.edi;
3427 executeCount += count;
3429 try {
3430 if (cpu.eflagsDirection) {
3431 while (count != 0) {
3432 //check hardware interrupts
3433 cpu.es.setDoubleWord(addr, data);
3434 count--;
3435 addr -= 4;
3437 } else {
3438 while (count != 0) {
3439 //check hardware interrupts
3440 cpu.es.setDoubleWord(addr, data);
3441 count--;
3442 addr += 4;
3446 finally {
3447 cpu.ecx = count;
3448 cpu.edi = addr;
3452 private final void mul_o8(int data)
3454 int x = cpu.eax & 0xff;
3456 int result = x * data;
3457 cpu.eax &= 0xffff0000;
3458 cpu.eax |= (result & 0xffff);
3460 cpu.setOverflowFlag(result, Processor.OF_HIGH_BYTE_NZ);
3461 cpu.setCarryFlag(result, Processor.CY_HIGH_BYTE_NZ);
3464 private final void mul_o16(int data)
3466 int x = cpu.eax & 0xffff;
3468 int result = x * data;
3469 cpu.eax = (cpu.eax & 0xffff0000) | (0xffff & result);
3470 result = result >> 16;
3471 cpu.edx = (cpu.edx & 0xffff0000) | (0xffff & result);
3473 cpu.setOverflowFlag(result, Processor.OF_LOW_WORD_NZ);
3474 cpu.setCarryFlag(result, Processor.CY_LOW_WORD_NZ);
3477 private final void mul_o32(int data)
3479 long x = cpu.eax & 0xffffffffl;
3480 long y = 0xffffffffl & data;
3482 long result = x * y;
3483 cpu.eax = (int)result;
3484 result = result >>> 32;
3485 cpu.edx = (int)result;
3487 cpu.setOverflowFlag((int)result, Processor.OF_NZ);
3488 cpu.setCarryFlag((int)result, Processor.CY_NZ);
3491 private final void imula_o8(byte data)
3493 byte al = (byte)cpu.eax;
3494 int result = al * data;
3496 cpu.eax = (cpu.eax & ~0xffff) | (result & 0xffff);
3498 cpu.setOverflowFlag(result, Processor.OF_NOT_BYTE);
3499 cpu.setCarryFlag(result, Processor.CY_NOT_BYTE);
3502 private final void imula_o16(short data)
3504 short ax = (short)cpu.eax;
3505 int result = ax * data;
3507 cpu.eax = (cpu.eax & ~0xffff) | (result & 0xffff);
3508 cpu.edx = (cpu.edx & ~0xffff) | (result >>> 16);
3510 //answer too wide for 16-bits?
3511 cpu.setOverflowFlag(result, Processor.OF_NOT_SHORT);
3512 cpu.setCarryFlag(result, Processor.CY_NOT_SHORT);
3515 private final void imula_o32(int data)
3517 long eax = (long)cpu.eax;
3518 long y = (long)data;
3519 long result = eax * y;
3521 cpu.eax = (int)result;
3522 cpu.edx = (int)(result >>> 32);
3524 //answer too wide for 32-bits?
3525 cpu.setOverflowFlag(result, Processor.OF_NOT_INT);
3526 cpu.setCarryFlag(result, Processor.CY_NOT_INT);
3529 private final int imul_o16(short data0, short data1)
3531 int result = data0 * data1;
3532 cpu.setOverflowFlag(result, Processor.OF_NOT_SHORT);
3533 cpu.setCarryFlag(result, Processor.CY_NOT_SHORT);
3534 return result;
3537 private final int imul_o32(int data0, int data1)
3539 long x = (long)data0;
3540 long y = (long)data1;
3542 long result = x * y;
3543 cpu.setOverflowFlag(result, Processor.OF_NOT_INT);
3544 cpu.setCarryFlag(result, Processor.CY_NOT_INT);
3545 return (int)result;
3548 private final void div_o8(int data)
3550 if (data == 0)
3551 throw ProcessorException.DIVIDE_ERROR;
3553 int x = (cpu.eax & 0xffff);
3555 int result = x / data;
3556 if (result > 0xff)
3557 throw ProcessorException.DIVIDE_ERROR;
3559 int remainder = (x % data) << 8;
3560 cpu.eax = (cpu.eax & ~0xffff) | (0xff & result) | (0xff00 & remainder);
3563 private final void div_o16(int data)
3565 if (data == 0)
3566 throw ProcessorException.DIVIDE_ERROR;
3568 long x = (cpu.edx & 0xffffl);
3569 x <<= 16;
3570 x |= (cpu.eax & 0xffffl);
3572 long result = x / data;
3573 if (result > 0xffffl)
3574 throw ProcessorException.DIVIDE_ERROR;
3576 long remainder = x % data;
3577 cpu.eax = (cpu.eax & ~0xffff) | (int)(result & 0xffff);
3578 cpu.edx = (cpu.edx & ~0xffff) | (int)(remainder & 0xffff);
3581 private final void div_o32(int data)
3583 long d = 0xffffffffl & data;
3585 if (d == 0)
3586 throw ProcessorException.DIVIDE_ERROR;
3588 long temp = (long)cpu.edx;
3589 temp <<= 32;
3590 temp |= (0xffffffffl & cpu.eax);
3592 long r2 = (temp & 1);
3593 long n2 = (temp >>> 1);
3595 long q2 = n2 / d;
3596 long m2 = n2 % d;
3598 long q = (q2 << 1);
3599 long r = (m2 << 1) + r2;
3601 q += (r / d);
3602 r %= d;
3603 if (q > 0xffffffffl)
3604 throw ProcessorException.DIVIDE_ERROR;
3606 cpu.eax = (int)q;
3607 cpu.edx = (int)r;
3610 private final void idiv_o8(byte data)
3612 if (data == 0)
3613 throw ProcessorException.DIVIDE_ERROR;
3615 short temp = (short)cpu.eax;
3616 int result = temp / data;
3617 int remainder = temp % data;
3618 if ((result > Byte.MAX_VALUE) || (result < Byte.MIN_VALUE))
3619 throw ProcessorException.DIVIDE_ERROR;
3621 cpu.eax = (cpu.eax & ~0xffff) | (0xff & result) | ((0xff & remainder) << 8); //AH is remainder
3624 private final void idiv_o16(short data)
3626 if (data == 0) {
3627 throw ProcessorException.DIVIDE_ERROR;
3629 int temp = (cpu.edx << 16) | (cpu.eax & 0xffff);
3630 int result = temp / (int)data;
3631 int remainder = temp % data;
3633 if ((result > Short.MAX_VALUE) || (result < Short.MIN_VALUE))
3634 throw ProcessorException.DIVIDE_ERROR;
3636 cpu.eax = (cpu.eax & ~0xffff) | (0xffff & result); //AX is result
3637 cpu.edx = (cpu.edx & ~0xffff) | (0xffff & remainder); //DX is remainder
3640 private final void idiv_o32(int data)
3642 if (data == 0)
3643 throw ProcessorException.DIVIDE_ERROR;
3645 long temp = (0xffffffffl & cpu.edx) << 32;
3646 temp |= (0xffffffffl & cpu.eax);
3647 long result = temp / data;
3648 if ((result > Integer.MAX_VALUE) || (result < Integer.MIN_VALUE))
3649 throw ProcessorException.DIVIDE_ERROR;
3651 long remainder = temp % data;
3653 cpu.eax = (int)result; //EAX is result
3654 cpu.edx = (int)remainder; //EDX is remainder
3657 private final void btc_mem(int offset, Segment segment, int address) throws ProcessorException
3659 address += (offset >>> 3);
3660 offset &= 0x7;
3662 byte data = segment.getByte(address);
3663 segment.setByte(address, (byte)(data ^ (1 << offset)));
3664 cpu.setCarryFlag(data, offset, Processor.CY_NTH_BIT_SET);
3667 private final void bts_mem(int offset, Segment segment, int address) throws ProcessorException
3669 address += (offset >>> 3);
3670 offset &= 0x7;
3672 byte data = segment.getByte(address);
3673 segment.setByte(address, (byte)(data | (1 << offset)));
3674 cpu.setCarryFlag(data, offset, Processor.CY_NTH_BIT_SET);
3677 private final void btr_mem(int offset, Segment segment, int address) throws ProcessorException
3679 address += (offset >>> 3);
3680 offset &= 0x7;
3682 byte data = segment.getByte(address);
3683 segment.setByte(address, (byte)(data & ~(1 << offset)));
3684 cpu.setCarryFlag(data, offset, Processor.CY_NTH_BIT_SET);
3687 private final void bt_mem(int offset, Segment segment, int address) throws ProcessorException
3689 address += (offset >>> 3);
3690 offset &= 0x7;
3692 cpu.setCarryFlag(segment.getByte(address), offset, Processor.CY_NTH_BIT_SET);
3695 private final int bsf(int source, int initial) throws ProcessorException
3697 if (source == 0) {
3698 cpu.setZeroFlag(true);
3699 return initial;
3700 } else {
3701 cpu.setZeroFlag(false);
3702 return numberOfTrailingZeros(source);
3706 private final int bsr(int source, int initial) throws ProcessorException
3708 if (source == 0) {
3709 cpu.setZeroFlag(true);
3710 return initial;
3711 } else {
3712 cpu.setZeroFlag(false);
3713 return 31 - numberOfLeadingZeros(source);
3717 private final void aaa()
3719 if (((cpu.eax & 0xf) > 0x9) || cpu.getAuxiliaryCarryFlag()) {
3720 int alCarry = ((cpu.eax & 0xff) > 0xf9) ? 0x100 : 0x000;
3721 cpu.eax = (0xffff0000 & cpu.eax) | (0x0f & (cpu.eax + 6)) | (0xff00 & (cpu.eax + 0x100 + alCarry));
3722 cpu.setAuxiliaryCarryFlag(true);
3723 cpu.setCarryFlag(true);
3724 } else {
3725 cpu.setAuxiliaryCarryFlag(false);
3726 cpu.setCarryFlag(false);
3727 cpu.eax = cpu.eax & 0xffffff0f;
3731 private final void aad(int base) throws ProcessorException
3733 int tl = (cpu.eax & 0xff);
3734 int th = ((cpu.eax >> 8) & 0xff);
3736 int ax1 = th * base;
3737 int ax2 = ax1 + tl;
3739 cpu.eax = (cpu.eax & ~0xffff) | (ax2 & 0xff);
3742 // bitwise_flags((byte)ax2);
3744 cpu.setZeroFlag((byte)ax2);
3745 cpu.setParityFlag((byte)ax2);
3746 cpu.setSignFlag((byte)ax2);
3748 cpu.setAuxiliaryCarryFlag(ax1, ax2, Processor.AC_BIT4_NEQ);
3749 cpu.setCarryFlag(ax2, Processor.CY_GREATER_FF);
3750 cpu.setOverflowFlag(ax2, tl, Processor.OF_BIT7_DIFFERENT);
3753 private final int aam(int base) throws ProcessorException
3755 int tl = 0xff & cpu.eax;
3756 if (base == 0)
3757 throw ProcessorException.DIVIDE_ERROR;
3758 int ah = 0xff & (tl / base);
3759 int al = 0xff & (tl % base);
3760 cpu.eax &= ~0xffff;
3761 cpu.eax |= (al | (ah << 8));
3763 cpu.setAuxiliaryCarryFlag(false);
3765 // bitwise_flags((byte)al);
3766 return (byte) al;
3769 private final void aas()
3771 if (((cpu.eax & 0xf) > 0x9) || cpu.getAuxiliaryCarryFlag()) {
3772 int alBorrow = (cpu.eax & 0xff) < 6 ? 0x100 : 0x000;
3773 cpu.eax = (0xffff0000 & cpu.eax) | (0x0f & (cpu.eax - 6)) | (0xff00 & (cpu.eax - 0x100 - alBorrow));
3774 cpu.setAuxiliaryCarryFlag(true);
3775 cpu.setCarryFlag(true);
3776 } else {
3777 cpu.setAuxiliaryCarryFlag(false);
3778 cpu.setCarryFlag(false);
3779 cpu.eax = cpu.eax & 0xffffff0f;
3783 private final void daa()
3785 int al = cpu.eax & 0xff;
3786 boolean newCF;
3787 if (((cpu.eax & 0xf) > 0x9) || cpu.getAuxiliaryCarryFlag()) {
3788 al += 6;
3789 cpu.setAuxiliaryCarryFlag(true);
3790 } else
3791 cpu.setAuxiliaryCarryFlag(false);
3793 if (((al & 0xff) > 0x9f) || cpu.getCarryFlag()) {
3794 al += 0x60;
3795 newCF = true;
3796 } else
3797 newCF = false;
3799 cpu.eax = (cpu.eax & ~0xff) | (0xff & al);
3801 // bitwise_flags((byte)al);
3803 cpu.setOverflowFlag(false);
3804 cpu.setZeroFlag((byte)al);
3805 cpu.setParityFlag((byte)al);
3806 cpu.setSignFlag((byte)al);
3808 cpu.setCarryFlag(newCF);
3811 private final void das()
3813 boolean tempCF = false;
3814 int tempAL = 0xff & cpu.eax;
3815 if (((tempAL & 0xf) > 0x9) || cpu.getAuxiliaryCarryFlag()) {
3816 cpu.setAuxiliaryCarryFlag(true);
3817 cpu.eax = (cpu.eax & ~0xff) | ((cpu.eax - 0x06) & 0xff);
3818 tempCF = (tempAL < 0x06) || cpu.getCarryFlag();
3821 if ((tempAL > 0x99) || cpu.getCarryFlag()) {
3822 cpu.eax = (cpu.eax & ~0xff) | ((cpu.eax - 0x60) & 0xff);
3823 tempCF = true;
3826 // bitwise_flags((byte)cpu.eax);
3828 cpu.setOverflowFlag(false);
3829 cpu.setZeroFlag((byte)cpu.eax);
3830 cpu.setParityFlag((byte)cpu.eax);
3831 cpu.setSignFlag((byte)cpu.eax);
3833 cpu.setCarryFlag(tempCF);
3836 private final void lahf()
3838 int result = 0x0200;
3839 if (cpu.getSignFlag()) result |= 0x8000;
3840 if (cpu.getZeroFlag()) result |= 0x4000;
3841 if (cpu.getAuxiliaryCarryFlag()) result |= 0x1000;
3842 if (cpu.getParityFlag()) result |= 0x0400;
3843 if (cpu.getCarryFlag()) result |= 0x0100;
3844 cpu.eax &= 0xffff00ff;
3845 cpu.eax |= result;
3848 private final void sahf()
3850 int ah = (cpu.eax & 0xff00);
3851 cpu.setCarryFlag(0 != (ah & 0x0100));
3852 cpu.setParityFlag(0 != (ah & 0x0400));
3853 cpu.setAuxiliaryCarryFlag(0 != (ah & 0x1000));
3854 cpu.setZeroFlag(0 != (ah & 0x4000));
3855 cpu.setSignFlag(0 != (ah & 0x8000));
3859 private final void cpuid()
3861 switch (cpu.eax) {
3862 case 0x00:
3863 cpu.eax = 0x02;
3864 cpu.ebx = 0x756e6547; /* "Genu", with G in the low nibble of BL */
3865 cpu.edx = 0x49656e69; /* "ineI", with i in the low nibble of DL */
3866 cpu.ecx = 0x6c65746e; /* "ntel", with n in the low nibble of CL */
3867 return;
3868 case 0x01:
3869 cpu.eax = 0x00000633; // Pentium II Model 8 Stepping 3
3870 cpu.ebx = 8 << 8; //not implemented (should be brand index)
3871 cpu.ecx = 0;
3873 int features = 0;
3874 features |= 0x01; //Have an FPU;
3875 features |= (1<< 8); // Support CMPXCHG8B instruction
3876 features |= (1<< 4); // implement TSC
3877 features |= (1<< 5); // support RDMSR/WRMSR
3878 //features |= (1<<23); // support MMX
3879 //features |= (1<<24); // Implement FSAVE/FXRSTOR instructions.
3880 features |= (1<<15); // Implement CMOV instructions.
3881 //features |= (1<< 9); // APIC on chip
3882 //features |= (1<<25); // support SSE
3883 features |= (1<< 3); // Support Page-Size Extension (4M pages)
3884 features |= (1<<13); // Support Global pages.
3885 //features |= (1<< 6); // Support PAE.
3886 features |= (1<<11); // SYSENTER/SYSEXIT
3887 cpu.edx = features;
3888 return;
3889 default:
3890 case 0x02:
3891 cpu.eax = 0x410601;
3892 cpu.ebx = 0;
3893 cpu.ecx = 0;
3894 cpu.edx = 0;
3895 return;
3899 private final void bitwise_flags(byte result)
3901 cpu.setOverflowFlag(false);
3902 cpu.setCarryFlag(false);
3903 cpu.setZeroFlag(result);
3904 cpu.setParityFlag(result);
3905 cpu.setSignFlag(result);
3908 private final void bitwise_flags(short result)
3910 cpu.setOverflowFlag(false);
3911 cpu.setCarryFlag(false);
3912 cpu.setZeroFlag(result);
3913 cpu.setParityFlag(result);
3914 cpu.setSignFlag(result);
3917 private final void bitwise_flags(int result)
3919 cpu.setOverflowFlag(false);
3920 cpu.setCarryFlag(false);
3921 cpu.setZeroFlag(result);
3922 cpu.setParityFlag(result);
3923 cpu.setSignFlag(result);
3926 private final void arithmetic_flags_o8(int result, int operand1, int operand2)
3928 cpu.setZeroFlag((byte)result);
3929 cpu.setParityFlag(result);
3930 cpu.setSignFlag((byte)result);
3932 cpu.setCarryFlag(result, Processor.CY_TWIDDLE_FF);
3933 cpu.setAuxiliaryCarryFlag(operand1, operand2, result, Processor.AC_XOR);
3936 private final void arithmetic_flags_o16(int result, int operand1, int operand2)
3938 cpu.setZeroFlag((short)result);
3939 cpu.setParityFlag(result);
3940 cpu.setSignFlag((short)result);
3942 cpu.setCarryFlag(result, Processor.CY_TWIDDLE_FFFF);
3943 cpu.setAuxiliaryCarryFlag(operand1, operand2, result, Processor.AC_XOR);
3946 private final void arithmetic_flags_o32(long result, int operand1, int operand2)
3948 cpu.setZeroFlag((int)result);
3949 cpu.setParityFlag((int)result);
3950 cpu.setSignFlag((int)result);
3952 cpu.setCarryFlag(result, Processor.CY_TWIDDLE_FFFFFFFF);
3953 cpu.setAuxiliaryCarryFlag(operand1, operand2, (int)result, Processor.AC_XOR);
3956 private final void add_o32_flags(long result, int operand1, int operand2)
3958 result = (0xffffffffl & operand1) + (0xffffffffl & operand2);
3960 arithmetic_flags_o32(result, operand1, operand2);
3961 cpu.setOverflowFlag((int)result, operand1 , operand2, Processor.OF_ADD_INT);
3964 private final void add_o16_flags(int result, int operand1, int operand2)
3966 arithmetic_flags_o16(result, operand1, operand2);
3967 cpu.setOverflowFlag(result, operand1 , operand2, Processor.OF_ADD_SHORT);
3970 private final void add_o8_flags(int result, int operand1, int operand2)
3972 arithmetic_flags_o8(result, operand1, operand2);
3973 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_ADD_BYTE);
3976 private final void adc_o32_flags(long result, int operand1, int operand2)
3978 int carry = (cpu.getCarryFlag() ? 1 : 0);
3980 result = (0xffffffffl & operand1) + (0xffffffffl & operand2) + carry;
3982 if (cpu.getCarryFlag() && (operand2 == 0xffffffff)) {
3983 arithmetic_flags_o32(result, operand1, operand2);
3984 cpu.setOverflowFlag(false);
3985 cpu.setCarryFlag(true);
3986 } else {
3987 cpu.setOverflowFlag((int)result, operand1, operand2, Processor.OF_ADD_INT);
3988 arithmetic_flags_o32(result, operand1, operand2);
3992 private final void adc_o16_flags(int result, int operand1, int operand2)
3994 if (cpu.getCarryFlag() && (operand2 == 0xffff)) {
3995 arithmetic_flags_o16(result, operand1, operand2);
3996 cpu.setOverflowFlag(false);
3997 cpu.setCarryFlag(true);
3998 } else {
3999 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_ADD_SHORT);
4000 arithmetic_flags_o16(result, operand1, operand2);
4004 private final void adc_o8_flags(int result, int operand1, int operand2)
4006 if (cpu.getCarryFlag() && (operand2 == 0xff)) {
4007 arithmetic_flags_o8(result, operand1, operand2);
4008 cpu.setOverflowFlag(false);
4009 cpu.setCarryFlag(true);
4010 } else {
4011 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_ADD_BYTE);
4012 arithmetic_flags_o8(result, operand1, operand2);
4016 private final void sub_o32_flags(long result, int operand1, int operand2)
4018 result = (0xffffffffl & operand1) - (0xffffffffl & operand2);
4020 arithmetic_flags_o32(result, operand1, operand2);
4021 cpu.setOverflowFlag((int)result, operand1, operand2, Processor.OF_SUB_INT);
4024 private final void sub_o16_flags(int result, int operand1, int operand2)
4026 arithmetic_flags_o16(result, operand1, operand2);
4027 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_SUB_SHORT);
4030 private final void sub_o8_flags(int result, int operand1, int operand2)
4032 arithmetic_flags_o8(result, operand1, operand2);
4033 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_SUB_BYTE);
4036 private final void rep_sub_o32_flags(int used, int operand1, int operand2)
4038 if (used == 0)
4039 return;
4041 long result = (0xffffffffl & operand1) - (0xffffffffl & operand2);
4043 arithmetic_flags_o32(result, operand1, operand2);
4044 cpu.setOverflowFlag((int)result, operand1, operand2, Processor.OF_SUB_INT);
4047 private final void rep_sub_o16_flags(int used, int operand1, int operand2)
4049 if (used == 0)
4050 return;
4052 int result = operand1 - operand2;
4054 arithmetic_flags_o16(result, operand1, operand2);
4055 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_SUB_SHORT);
4058 private final void rep_sub_o8_flags(int used, int operand1, int operand2)
4060 if (used == 0)
4061 return;
4063 int result = operand1 - operand2;
4065 arithmetic_flags_o8(result, operand1, operand2);
4066 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_SUB_BYTE);
4069 private final void sbb_o32_flags(long result, int operand1, int operand2)
4071 int carry = (cpu.getCarryFlag() ? 1 : 0);
4072 result = (0xffffffffl & operand1) - ((0xffffffffl & operand2) + carry);
4074 cpu.setOverflowFlag((int)result, operand1, operand2, Processor.OF_SUB_INT);
4075 arithmetic_flags_o32(result, operand1, operand2);
4078 private final void sbb_o16_flags(int result, int operand1, int operand2)
4080 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_SUB_SHORT);
4081 arithmetic_flags_o16(result, operand1, operand2);
4084 private final void sbb_o8_flags(int result, int operand1, int operand2)
4086 cpu.setOverflowFlag(result, operand1, operand2, Processor.OF_SUB_BYTE);
4087 arithmetic_flags_o8(result, operand1, operand2);
4090 private final void dec_flags(int result)
4092 cpu.setZeroFlag(result);
4093 cpu.setParityFlag(result);
4094 cpu.setSignFlag(result);
4095 cpu.setOverflowFlag(result, Processor.OF_MAX_INT);
4096 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_MAX);
4099 private final void dec_flags(short result)
4101 cpu.setZeroFlag(result);
4102 cpu.setParityFlag(result);
4103 cpu.setSignFlag(result);
4104 cpu.setOverflowFlag(result, Processor.OF_MAX_SHORT);
4105 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_MAX);
4108 private final void dec_flags(byte result)
4110 cpu.setZeroFlag(result);
4111 cpu.setParityFlag(result);
4112 cpu.setSignFlag(result);
4113 cpu.setOverflowFlag(result, Processor.OF_MAX_BYTE);
4114 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_MAX);
4117 private final void inc_flags(int result)
4119 cpu.setZeroFlag(result);
4120 cpu.setParityFlag(result);
4121 cpu.setSignFlag(result);
4122 cpu.setOverflowFlag(result, Processor.OF_MIN_INT);
4123 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_ZERO);
4126 private final void inc_flags(short result)
4128 cpu.setZeroFlag(result);
4129 cpu.setParityFlag(result);
4130 cpu.setSignFlag(result);
4131 cpu.setOverflowFlag(result, Processor.OF_MIN_SHORT);
4132 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_ZERO);
4135 private final void inc_flags(byte result)
4137 cpu.setZeroFlag(result);
4138 cpu.setParityFlag(result);
4139 cpu.setSignFlag(result);
4140 cpu.setOverflowFlag(result, Processor.OF_MIN_BYTE);
4141 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_ZERO);
4144 private final void shl_flags(byte result, byte initial, int count)
4146 if (count > 0) {
4147 cpu.setCarryFlag(initial, count, Processor.CY_SHL_OUTBIT_BYTE);
4149 if (count == 1)
4150 cpu.setOverflowFlag(result, Processor.OF_BIT7_XOR_CARRY);
4152 cpu.setZeroFlag(result);
4153 cpu.setParityFlag(result);
4154 cpu.setSignFlag(result);
4158 private final void shl_flags(short result, short initial, int count)
4160 if (count > 0) {
4161 cpu.setCarryFlag(initial, count, Processor.CY_SHL_OUTBIT_SHORT);
4163 if (count == 1)
4164 cpu.setOverflowFlag(result, Processor.OF_BIT15_XOR_CARRY);
4166 cpu.setZeroFlag(result);
4167 cpu.setParityFlag(result);
4168 cpu.setSignFlag(result);
4172 private final void shl_flags(int result, int initial, int count)
4174 if (count > 0) {
4175 cpu.setCarryFlag(initial, count, Processor.CY_SHL_OUTBIT_INT);
4177 if (count == 1)
4178 cpu.setOverflowFlag(result, Processor.OF_BIT31_XOR_CARRY);
4180 cpu.setZeroFlag(result);
4181 cpu.setParityFlag(result);
4182 cpu.setSignFlag(result);
4186 private final void shr_flags(byte result, int initial, int count)
4188 if (count > 0) {
4189 cpu.setCarryFlag(initial, count, Processor.CY_SHR_OUTBIT);
4191 if (count == 1)
4192 cpu.setOverflowFlag(result, initial, Processor.OF_BIT7_DIFFERENT);
4194 cpu.setZeroFlag(result);
4195 cpu.setParityFlag(result);
4196 cpu.setSignFlag(result);
4200 private final void shr_flags(short result, int initial, int count)
4202 if (count > 0) {
4203 cpu.setCarryFlag(initial, count, Processor.CY_SHR_OUTBIT);
4205 if (count == 1)
4206 cpu.setOverflowFlag(result, initial, Processor.OF_BIT15_DIFFERENT);
4208 cpu.setZeroFlag(result);
4209 cpu.setParityFlag(result);
4210 cpu.setSignFlag(result);
4214 private final void shr_flags(int result, int initial, int count)
4216 if (count > 0) {
4217 cpu.setCarryFlag(initial, count, Processor.CY_SHR_OUTBIT);
4219 if (count == 1)
4220 cpu.setOverflowFlag(result, initial, Processor.OF_BIT31_DIFFERENT);
4222 cpu.setZeroFlag(result);
4223 cpu.setParityFlag(result);
4224 cpu.setSignFlag(result);
4229 private final void sar_flags(byte result, byte initial, int count)
4231 if (count > 0) {
4232 cpu.setCarryFlag(initial, count, Processor.CY_SHR_OUTBIT);
4233 if (count == 1) cpu.setOverflowFlag(false);
4235 cpu.setSignFlag(result);
4236 cpu.setZeroFlag(result);
4237 cpu.setParityFlag(result);
4241 private final void sar_flags(short result, short initial, int count)
4243 if (count > 0) {
4244 cpu.setCarryFlag(initial, count, Processor.CY_SHR_OUTBIT);
4245 if (count == 1) cpu.setOverflowFlag(false);
4247 cpu.setSignFlag(result);
4248 cpu.setZeroFlag(result);
4249 cpu.setParityFlag(result);
4253 private final void sar_flags(int result, int initial, int count)
4255 if (count > 0) {
4256 cpu.setCarryFlag(initial, count, Processor.CY_SHR_OUTBIT);
4257 if (count == 1) cpu.setOverflowFlag(false);
4259 cpu.setSignFlag(result);
4260 cpu.setZeroFlag(result);
4261 cpu.setParityFlag(result);
4265 private final void rol_flags(byte result, int count)
4267 if (count > 0) {
4268 cpu.setCarryFlag(result, Processor.CY_LOWBIT);
4269 if (count == 1)
4270 cpu.setOverflowFlag(result, Processor.OF_BIT7_XOR_CARRY);
4274 private final void rol_flags(short result, int count)
4276 if (count > 0) {
4277 cpu.setCarryFlag(result, Processor.CY_LOWBIT);
4278 if (count == 1)
4279 cpu.setOverflowFlag(result, Processor.OF_BIT15_XOR_CARRY);
4283 private final void rol_flags(int result, int count)
4285 if (count > 0) {
4286 cpu.setCarryFlag(result, Processor.CY_LOWBIT);
4287 if (count == 1)
4288 cpu.setOverflowFlag(result, Processor.OF_BIT31_XOR_CARRY);
4292 private final void ror_flags(byte result, int count)
4294 if (count > 0) {
4295 cpu.setCarryFlag(result, Processor.CY_HIGHBIT_BYTE);
4296 if (count == 1)
4297 cpu.setOverflowFlag(result, Processor.OF_BIT6_XOR_CARRY);
4301 private final void ror_flags(short result, int count)
4303 if (count > 0) {
4304 cpu.setCarryFlag(result, Processor.CY_HIGHBIT_SHORT);
4305 if (count == 1)
4306 cpu.setOverflowFlag(result, Processor.OF_BIT14_XOR_CARRY);
4310 private final void ror_flags(int result, int count)
4312 if (count > 0) {
4313 cpu.setCarryFlag(result, Processor.CY_HIGHBIT_INT);
4314 if (count == 1)
4315 cpu.setOverflowFlag(result, Processor.OF_BIT30_XOR_CARRY);
4319 private final void rcl_o8_flags(int result, int count)
4321 if (count > 0) {
4322 cpu.setCarryFlag(result, Processor.CY_OFFENDBIT_BYTE);
4323 if (count == 1)
4324 cpu.setOverflowFlag(result, Processor.OF_BIT7_XOR_CARRY);
4328 private final void rcl_o16_flags(int result, int count)
4330 if (count > 0) {
4331 cpu.setCarryFlag(result, Processor.CY_OFFENDBIT_SHORT);
4332 if (count == 1)
4333 cpu.setOverflowFlag(result, Processor.OF_BIT15_XOR_CARRY);
4337 private final void rcl_o32_flags(long result, int count)
4339 if (count > 0) {
4340 cpu.setCarryFlag(result, Processor.CY_OFFENDBIT_INT);
4341 if (count == 1)
4342 cpu.setOverflowFlag(result, Processor.OF_BIT31_XOR_CARRY);
4346 private final void rcr_o8_flags(int result, int count, int overflow)
4348 if (count > 0) {
4349 cpu.setCarryFlag(result, Processor.CY_OFFENDBIT_BYTE);
4350 if (count == 1)
4351 cpu.setOverflowFlag(overflow > 0);
4355 private final void rcr_o16_flags(int result, int count, int overflow)
4357 if (count > 0) {
4358 cpu.setCarryFlag(result, Processor.CY_OFFENDBIT_SHORT);
4359 if (count == 1)
4360 cpu.setOverflowFlag(overflow > 0);
4364 private final void rcr_o32_flags(long result, int count, int overflow)
4366 if (count > 0) {
4367 cpu.setCarryFlag(result, Processor.CY_OFFENDBIT_INT);
4368 if (count == 1)
4369 cpu.setOverflowFlag(overflow > 0);
4373 private final void neg_flags(byte result)
4375 cpu.setCarryFlag(result, Processor.CY_NZ);
4376 cpu.setOverflowFlag(result, Processor.OF_MIN_BYTE);
4378 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_NZERO);
4379 cpu.setZeroFlag(result);
4380 cpu.setParityFlag(result);
4381 cpu.setSignFlag(result);
4384 private final void neg_flags(short result)
4386 cpu.setCarryFlag(result, Processor.CY_NZ);
4387 cpu.setOverflowFlag(result, Processor.OF_MIN_SHORT);
4389 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_NZERO);
4390 cpu.setZeroFlag(result);
4391 cpu.setParityFlag(result);
4392 cpu.setSignFlag(result);
4395 private final void neg_flags(int result)
4397 cpu.setCarryFlag(result, Processor.CY_NZ);
4398 cpu.setOverflowFlag(result, Processor.OF_MIN_INT);
4400 cpu.setAuxiliaryCarryFlag(result, Processor.AC_LNIBBLE_NZERO);
4401 cpu.setZeroFlag(result);
4402 cpu.setParityFlag(result);
4403 cpu.setSignFlag(result);
4407 private final int in_o8(int ioport)
4409 if (checkIOPermissionsByte(ioport))
4410 return 0xff & cpu.ioports.ioPortReadByte(ioport);
4411 else
4412 throw ProcessorException.GENERAL_PROTECTION_0;
4415 private final int in_o16(int ioport)
4417 if (checkIOPermissionsShort(ioport))
4418 return 0xffff & cpu.ioports.ioPortReadWord(ioport);
4419 else
4420 throw ProcessorException.GENERAL_PROTECTION_0;
4423 private final int in_o32(int ioport)
4425 if (checkIOPermissionsInt(ioport))
4426 return cpu.ioports.ioPortReadLong(ioport);
4427 else
4428 throw ProcessorException.GENERAL_PROTECTION_0;
4431 private final void out_o8(int ioport, int data)
4433 if (checkIOPermissionsByte(ioport))
4434 cpu.ioports.ioPortWriteByte(ioport, 0xff & data);
4435 else
4436 throw ProcessorException.GENERAL_PROTECTION_0;
4439 private final void out_o16(int ioport, int data)
4441 if (checkIOPermissionsShort(ioport))
4442 cpu.ioports.ioPortWriteWord(ioport, 0xffff & data);
4443 else
4444 throw ProcessorException.GENERAL_PROTECTION_0;
4447 private final void out_o32(int ioport, int data)
4449 if (checkIOPermissionsInt(ioport))
4450 cpu.ioports.ioPortWriteLong(ioport, data);
4451 else
4452 throw ProcessorException.GENERAL_PROTECTION_0;
4455 private final boolean checkIOPermissionsByte(int ioportAddress)
4457 try {
4458 int ioPermMapBaseAddress = 0xffff & cpu.tss.getWord(102);
4459 try {
4460 byte ioPermMapByte = cpu.tss.getByte(ioPermMapBaseAddress + (ioportAddress >>> 3));
4461 return (ioPermMapByte & (0x1 << (ioportAddress & 0x7))) == 0;
4462 } catch (ProcessorException p) {
4463 if (p.getType() == ProcessorException.Type.GENERAL_PROTECTION)
4464 return false;
4465 else
4466 throw p;
4468 } catch (ProcessorException p) {
4469 System.err.println("Emulated: Processor exception thrown while accessing TSS : " + p);
4470 throw p;
4474 private final boolean checkIOPermissionsShort(int ioportAddress)
4476 try {
4477 int ioPermMapBaseAddress = 0xffff & cpu.tss.getWord(102);
4478 try {
4479 short ioPermMapShort = cpu.tss.getWord(ioPermMapBaseAddress + (ioportAddress >>> 3));
4480 return (ioPermMapShort & (0x3 << (ioportAddress & 0x7))) == 0;
4481 } catch (ProcessorException p) {
4482 if (p.getType() == ProcessorException.Type.GENERAL_PROTECTION)
4483 return false;
4484 else
4485 throw p;
4487 } catch (ProcessorException p) {
4488 System.err.println("Emulated: Processor exception thrown while accessing TSS : " + p);
4489 throw p;
4493 private final boolean checkIOPermissionsInt(int ioportAddress)
4495 try {
4496 int ioPermMapBaseAddress = 0xffff & cpu.tss.getWord(102);
4497 try {
4498 short ioPermMapShort = cpu.tss.getWord(ioPermMapBaseAddress + (ioportAddress >>> 3));
4499 return (ioPermMapShort & (0xf << (ioportAddress & 0x7))) == 0;
4500 } catch (ProcessorException p) {
4501 if (p.getType() == ProcessorException.Type.GENERAL_PROTECTION)
4502 return false;
4503 else
4504 throw p;
4506 } catch (ProcessorException p) {
4507 System.err.println("Emulated: Processor exception thrown while accessing TSS: " + p);
4508 throw p;
4512 private static int numberOfTrailingZeros(int i) {
4513 int y;
4514 if (i == 0) return 32;
4515 int n = 31;
4516 y = i <<16; if (y != 0) { n = n -16; i = y; }
4517 y = i << 8; if (y != 0) { n = n - 8; i = y; }
4518 y = i << 4; if (y != 0) { n = n - 4; i = y; }
4519 y = i << 2; if (y != 0) { n = n - 2; i = y; }
4520 return n - ((i << 1) >>> 31);
4523 private static int numberOfLeadingZeros(int i) {
4524 if (i == 0)
4525 return 32;
4526 int n = 1;
4527 if (i >>> 16 == 0) { n += 16; i <<= 16; }
4528 if (i >>> 24 == 0) { n += 8; i <<= 8; }
4529 if (i >>> 28 == 0) { n += 4; i <<= 4; }
4530 if (i >>> 30 == 0) { n += 2; i <<= 2; }
4531 n -= i >>> 31;
4532 return n;