- update sector count before calling write completion function (SF patch #2144692)
[bochs-mirror.git] / cpu / arith16.cc
blob9845c1df94512ef26d50f39f42576c76c2dcf91d
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: arith16.cc,v 1.71 2008/08/09 21:05:05 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2001 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /////////////////////////////////////////////////////////////////////////
28 #define NEED_CPU_REG_SHORTCUTS 1
29 #include "bochs.h"
30 #include "cpu.h"
31 #define LOG_THIS BX_CPU_THIS_PTR
33 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_RX(bxInstruction_c *i)
35 Bit16u rx = ++BX_READ_16BIT_REG(i->opcodeReg());
36 SET_FLAGS_OSZAPC_INC_16(rx);
39 void BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_RX(bxInstruction_c *i)
41 Bit16u rx = --BX_READ_16BIT_REG(i->opcodeReg());
42 SET_FLAGS_OSZAPC_DEC_16(rx);
45 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EwGwM(bxInstruction_c *i)
47 Bit16u op1_16, op2_16, sum_16;
49 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
51 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
52 op2_16 = BX_READ_16BIT_REG(i->nnn());
53 sum_16 = op1_16 + op2_16;
54 write_RMW_virtual_word(sum_16);
56 SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
59 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GwEwR(bxInstruction_c *i)
61 Bit16u op1_16, op2_16, sum_16;
63 op1_16 = BX_READ_16BIT_REG(i->nnn());
64 op2_16 = BX_READ_16BIT_REG(i->rm());
65 sum_16 = op1_16 + op2_16;
67 BX_WRITE_16BIT_REG(i->nnn(), sum_16);
69 SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
72 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_AXIw(bxInstruction_c *i)
74 Bit16u op1_16, op2_16, sum_16;
76 op1_16 = AX;
77 op2_16 = i->Iw();
78 sum_16 = op1_16 + op2_16;
79 AX = sum_16;
81 SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
84 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EwGwM(bxInstruction_c *i)
86 Bit16u op1_16, op2_16, sum_16;
87 bx_bool temp_CF = getB_CF();
89 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
91 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
92 op2_16 = BX_READ_16BIT_REG(i->nnn());
93 sum_16 = op1_16 + op2_16 + temp_CF;
94 write_RMW_virtual_word(sum_16);
96 SET_FLAGS_OSZAPC_16(op1_16, op2_16, sum_16, BX_LF_INSTR_ADD_ADC16(temp_CF));
99 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GwEwR(bxInstruction_c *i)
101 Bit16u op1_16, op2_16, sum_16;
102 bx_bool temp_CF = getB_CF();
104 op1_16 = BX_READ_16BIT_REG(i->nnn());
105 op2_16 = BX_READ_16BIT_REG(i->rm());
106 sum_16 = op1_16 + op2_16 + temp_CF;
107 BX_WRITE_16BIT_REG(i->nnn(), sum_16);
109 SET_FLAGS_OSZAPC_16(op1_16, op2_16, sum_16, BX_LF_INSTR_ADD_ADC16(temp_CF));
112 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_AXIw(bxInstruction_c *i)
114 Bit16u op1_16, op2_16, sum_16;
115 bx_bool temp_CF = getB_CF();
117 op1_16 = AX;
118 op2_16 = i->Iw();
119 sum_16 = op1_16 + op2_16 + temp_CF;
120 AX = sum_16;
122 SET_FLAGS_OSZAPC_16(op1_16, op2_16, sum_16, BX_LF_INSTR_ADD_ADC16(temp_CF));
125 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EwGwM(bxInstruction_c *i)
127 Bit16u op1_16, op2_16, diff_16;
128 bx_bool temp_CF = getB_CF();
130 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
132 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
133 op2_16 = BX_READ_16BIT_REG(i->nnn());
134 diff_16 = op1_16 - (op2_16 + temp_CF);
135 write_RMW_virtual_word(diff_16);
137 SET_FLAGS_OSZAPC_16(op1_16, op2_16, diff_16, BX_LF_INSTR_SUB_SBB16(temp_CF));
140 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GwEwR(bxInstruction_c *i)
142 Bit16u op1_16, op2_16, diff_16;
143 bx_bool temp_CF = getB_CF();
145 op1_16 = BX_READ_16BIT_REG(i->nnn());
146 op2_16 = BX_READ_16BIT_REG(i->rm());
147 diff_16 = op1_16 - (op2_16 + temp_CF);
148 BX_WRITE_16BIT_REG(i->nnn(), diff_16);
150 SET_FLAGS_OSZAPC_16(op1_16, op2_16, diff_16, BX_LF_INSTR_SUB_SBB16(temp_CF));
153 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_AXIw(bxInstruction_c *i)
155 bx_bool temp_CF = getB_CF();
156 Bit16u op1_16, op2_16, diff_16;
158 op1_16 = AX;
159 op2_16 = i->Iw();
160 diff_16 = op1_16 - (op2_16 + temp_CF);
161 AX = diff_16;
163 SET_FLAGS_OSZAPC_16(op1_16, op2_16, diff_16, BX_LF_INSTR_SUB_SBB16(temp_CF));
166 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EwIwM(bxInstruction_c *i)
168 bx_bool temp_CF = getB_CF();
169 Bit16u op1_16, op2_16 = i->Iw(), diff_16;
171 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
173 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
174 diff_16 = op1_16 - (op2_16 + temp_CF);
175 write_RMW_virtual_word(diff_16);
177 SET_FLAGS_OSZAPC_16(op1_16, op2_16, diff_16, BX_LF_INSTR_SUB_SBB16(temp_CF));
180 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EwIwR(bxInstruction_c *i)
182 bx_bool temp_CF = getB_CF();
183 Bit16u op1_16, op2_16 = i->Iw(), diff_16;
185 op1_16 = BX_READ_16BIT_REG(i->rm());
186 diff_16 = op1_16 - (op2_16 + temp_CF);
187 BX_WRITE_16BIT_REG(i->rm(), diff_16);
189 SET_FLAGS_OSZAPC_16(op1_16, op2_16, diff_16, BX_LF_INSTR_SUB_SBB16(temp_CF));
192 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EwGwM(bxInstruction_c *i)
194 Bit16u op1_16, op2_16, diff_16;
196 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
198 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
199 op2_16 = BX_READ_16BIT_REG(i->nnn());
200 diff_16 = op1_16 - op2_16;
201 write_RMW_virtual_word(diff_16);
203 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
206 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GwEwR(bxInstruction_c *i)
208 Bit16u op1_16, op2_16, diff_16;
210 op1_16 = BX_READ_16BIT_REG(i->nnn());
211 op2_16 = BX_READ_16BIT_REG(i->rm());
212 diff_16 = op1_16 - op2_16;
213 BX_WRITE_16BIT_REG(i->nnn(), diff_16);
215 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
218 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_AXIw(bxInstruction_c *i)
220 Bit16u op1_16, op2_16, diff_16;
222 op1_16 = AX;
223 op2_16 = i->Iw();
224 diff_16 = op1_16 - op2_16;
225 AX = diff_16;
227 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
230 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EwGwM(bxInstruction_c *i)
232 Bit16u op1_16, op2_16, diff_16;
234 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
236 op1_16 = read_virtual_word(i->seg(), eaddr);
237 op2_16 = BX_READ_16BIT_REG(i->nnn());
238 diff_16 = op1_16 - op2_16;
240 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
243 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GwEwR(bxInstruction_c *i)
245 Bit16u op1_16, op2_16, diff_16;
247 op1_16 = BX_READ_16BIT_REG(i->nnn());
248 op2_16 = BX_READ_16BIT_REG(i->rm());
249 diff_16 = op1_16 - op2_16;
251 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
254 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_AXIw(bxInstruction_c *i)
256 Bit16u op1_16, op2_16, diff_16;
258 op1_16 = AX;
259 op2_16 = i->Iw();
260 diff_16 = op1_16 - op2_16;
262 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
265 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CBW(bxInstruction_c *i)
267 /* CBW: no flags are effected */
268 AX = (Bit8s) AL;
271 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CWD(bxInstruction_c *i)
273 /* CWD: no flags are affected */
274 if (AX & 0x8000) {
275 DX = 0xFFFF;
277 else {
278 DX = 0x0000;
282 void BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EwGwM(bxInstruction_c *i)
284 #if BX_CPU_LEVEL >= 4
285 Bit16u op1_16, op2_16, sum_16;
287 /* XADD dst(r/m), src(r)
288 * temp <-- src + dst | sum = op2 + op1
289 * src <-- dst | op2 = op1
290 * dst <-- tmp | op1 = sum
293 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
295 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
296 op2_16 = BX_READ_16BIT_REG(i->nnn());
297 sum_16 = op1_16 + op2_16;
298 write_RMW_virtual_word(sum_16);
300 /* and write destination into source */
301 BX_WRITE_16BIT_REG(i->nnn(), op1_16);
303 SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
304 #else
305 BX_INFO(("XADD_EwGw: not supported on < 80486"));
306 exception(BX_UD_EXCEPTION, 0, 0);
307 #endif
310 void BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EwGwR(bxInstruction_c *i)
312 #if BX_CPU_LEVEL >= 4
313 Bit16u op1_16, op2_16, sum_16;
315 /* XADD dst(r/m), src(r)
316 * temp <-- src + dst | sum = op2 + op1
317 * src <-- dst | op2 = op1
318 * dst <-- tmp | op1 = sum
321 op1_16 = BX_READ_16BIT_REG(i->rm());
322 op2_16 = BX_READ_16BIT_REG(i->nnn());
323 sum_16 = op1_16 + op2_16;
325 // and write destination into source
326 // Note: if both op1 & op2 are registers, the last one written
327 // should be the sum, as op1 & op2 may be the same register.
328 // For example: XADD AL, AL
329 BX_WRITE_16BIT_REG(i->nnn(), op1_16);
330 BX_WRITE_16BIT_REG(i->rm(), sum_16);
332 SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
333 #else
334 BX_INFO(("XADD_EwGw: not supported on < 80486"));
335 exception(BX_UD_EXCEPTION, 0, 0);
336 #endif
339 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EwIwM(bxInstruction_c *i)
341 Bit16u op1_16, op2_16 = i->Iw(), sum_16;
343 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
345 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
346 sum_16 = op1_16 + op2_16;
347 write_RMW_virtual_word(sum_16);
349 SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
352 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EwIwR(bxInstruction_c *i)
354 Bit16u op1_16, op2_16 = i->Iw(), sum_16;
356 op1_16 = BX_READ_16BIT_REG(i->rm());
357 sum_16 = op1_16 + op2_16;
358 BX_WRITE_16BIT_REG(i->rm(), sum_16);
360 SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
363 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EwIwM(bxInstruction_c *i)
365 bx_bool temp_CF = getB_CF();
366 Bit16u op1_16, op2_16 = i->Iw(), sum_16;
368 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
370 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
371 sum_16 = op1_16 + op2_16 + temp_CF;
372 write_RMW_virtual_word(sum_16);
374 SET_FLAGS_OSZAPC_16(op1_16, op2_16, sum_16, BX_LF_INSTR_ADD_ADC16(temp_CF));
377 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EwIwR(bxInstruction_c *i)
379 bx_bool temp_CF = getB_CF();
380 Bit16u op1_16, op2_16 = i->Iw(), sum_16;
382 op1_16 = BX_READ_16BIT_REG(i->rm());
383 sum_16 = op1_16 + op2_16 + temp_CF;
384 BX_WRITE_16BIT_REG(i->rm(), sum_16);
386 SET_FLAGS_OSZAPC_16(op1_16, op2_16, sum_16, BX_LF_INSTR_ADD_ADC16(temp_CF));
389 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EwIwM(bxInstruction_c *i)
391 Bit16u op1_16, op2_16 = i->Iw(), diff_16;
393 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
395 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
396 diff_16 = op1_16 - op2_16;
397 write_RMW_virtual_word(diff_16);
399 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
402 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EwIwR(bxInstruction_c *i)
404 Bit16u op1_16, op2_16 = i->Iw(), diff_16;
406 op1_16 = BX_READ_16BIT_REG(i->rm());
407 diff_16 = op1_16 - op2_16;
408 BX_WRITE_16BIT_REG(i->rm(), diff_16);
410 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
413 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EwIwM(bxInstruction_c *i)
415 Bit16u op1_16, op2_16 = i->Iw(), diff_16;
417 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
419 op1_16 = read_virtual_word(i->seg(), eaddr);
420 diff_16 = op1_16 - op2_16;
421 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
424 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EwIwR(bxInstruction_c *i)
426 Bit16u op1_16, op2_16 = i->Iw(), diff_16;
428 op1_16 = BX_READ_16BIT_REG(i->rm());
429 diff_16 = op1_16 - op2_16;
430 SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
433 void BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EwM(bxInstruction_c *i)
435 Bit16u op1_16;
437 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
439 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
440 op1_16 = - (Bit16s)(op1_16);
441 write_RMW_virtual_word(op1_16);
443 SET_FLAGS_OSZAPC_RESULT_16(op1_16, BX_LF_INSTR_NEG16);
446 void BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EwR(bxInstruction_c *i)
448 Bit16u op1_16 = BX_READ_16BIT_REG(i->rm());
449 op1_16 = - (Bit16s)(op1_16);
450 BX_WRITE_16BIT_REG(i->rm(), op1_16);
452 SET_FLAGS_OSZAPC_RESULT_16(op1_16, BX_LF_INSTR_NEG16);
455 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_EwM(bxInstruction_c *i)
457 Bit16u op1_16;
459 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
461 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
462 op1_16++;
463 write_RMW_virtual_word(op1_16);
465 SET_FLAGS_OSZAPC_INC_16(op1_16);
468 void BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_EwM(bxInstruction_c *i)
470 Bit16u op1_16;
472 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
474 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
475 op1_16--;
476 write_RMW_virtual_word(op1_16);
478 SET_FLAGS_OSZAPC_DEC_16(op1_16);
481 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EwGwM(bxInstruction_c *i)
483 #if BX_CPU_LEVEL >= 4
484 Bit16u op1_16, op2_16, diff_16;
486 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
488 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
489 diff_16 = AX - op1_16;
490 SET_FLAGS_OSZAPC_SUB_16(AX, op1_16, diff_16);
492 if (diff_16 == 0) { // if accumulator == dest
493 // dest <-- src
494 op2_16 = BX_READ_16BIT_REG(i->nnn());
495 write_RMW_virtual_word(op2_16);
497 else {
498 // accumulator <-- dest
499 AX = op1_16;
501 #else
502 BX_INFO(("CMPXCHG_EwGw: not supported for cpu-level <= 3"));
503 exception(BX_UD_EXCEPTION, 0, 0);
504 #endif
507 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EwGwR(bxInstruction_c *i)
509 #if BX_CPU_LEVEL >= 4
510 Bit16u op1_16, op2_16, diff_16;
512 op1_16 = BX_READ_16BIT_REG(i->rm());
513 diff_16 = AX - op1_16;
514 SET_FLAGS_OSZAPC_SUB_16(AX, op1_16, diff_16);
516 if (diff_16 == 0) { // if accumulator == dest
517 // dest <-- src
518 op2_16 = BX_READ_16BIT_REG(i->nnn());
519 BX_WRITE_16BIT_REG(i->rm(), op2_16);
521 else {
522 // accumulator <-- dest
523 AX = op1_16;
525 #else
526 BX_INFO(("CMPXCHG_EwGw: not supported for cpu-level <= 3"));
527 exception(BX_UD_EXCEPTION, 0, 0);
528 #endif