- tftp_send_optack() was not 64-bit clean (patch from SF bug #1787500)
[bochs-mirror.git] / cpu / arith8.cc
blob5c5d83bc378eb808e63436413fd6fa30d7b4f787
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: arith8.cc,v 1.39 2006/03/26 18:58:00 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
28 #define NEED_CPU_REG_SHORTCUTS 1
29 #include "bochs.h"
30 #include "cpu.h"
31 #define LOG_THIS BX_CPU_THIS_PTR
34 void BX_CPU_C::ADD_EbGb(bxInstruction_c *i)
36 Bit8u op2, op1, sum;
38 op2 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
40 if (i->modC0()) {
41 op1 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
42 sum = op1 + op2;
43 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), sum);
45 else {
46 read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
47 sum = op1 + op2;
48 write_RMW_virtual_byte(sum);
51 SET_FLAGS_OSZAPC_8(op1, op2, sum, BX_INSTR_ADD8);
54 void BX_CPU_C::ADD_GbEb(bxInstruction_c *i)
56 Bit8u op1, op2, sum;
58 op1 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
60 if (i->modC0()) {
61 op2 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
62 sum = op1 + op2;
64 else {
65 read_virtual_byte(i->seg(), RMAddr(i), &op2);
66 sum = op1 + op2;
69 BX_WRITE_8BIT_REGx(i->nnn(), i->extend8bitL(), sum);
71 SET_FLAGS_OSZAPC_8(op1, op2, sum, BX_INSTR_ADD8);
74 void BX_CPU_C::ADD_ALIb(bxInstruction_c *i)
76 Bit8u op1, op2, sum;
78 op1 = AL;
79 op2 = i->Ib();
80 sum = op1 + op2;
81 AL = sum;
83 SET_FLAGS_OSZAPC_8(op1, op2, sum, BX_INSTR_ADD8);
86 void BX_CPU_C::ADC_EbGb(bxInstruction_c *i)
88 Bit8u op2, op1, sum;
89 bx_bool temp_CF = getB_CF();
91 op2 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
93 if (i->modC0()) {
94 op1 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
95 sum = op1 + op2 + temp_CF;
96 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), sum);
98 else {
99 read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
100 sum = op1 + op2 + temp_CF;
101 write_RMW_virtual_byte(sum);
104 SET_FLAGS_OSZAPC_8(op1, op2, sum, BX_INSTR_ADD_ADC8(temp_CF));
107 void BX_CPU_C::ADC_GbEb(bxInstruction_c *i)
109 Bit8u op1, op2, sum;
110 bx_bool temp_CF = getB_CF();
112 op1 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
114 if (i->modC0()) {
115 op2 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
117 else {
118 read_virtual_byte(i->seg(), RMAddr(i), &op2);
121 sum = op1 + op2 + temp_CF;
123 SET_FLAGS_OSZAPC_8(op1, op2, sum, BX_INSTR_ADD_ADC8(temp_CF));
125 BX_WRITE_8BIT_REGx(i->nnn(), i->extend8bitL(), sum);
128 void BX_CPU_C::ADC_ALIb(bxInstruction_c *i)
130 Bit8u op1, op2, sum;
131 bx_bool temp_CF = getB_CF();
133 op1 = AL;
134 op2 = i->Ib();
135 sum = op1 + op2 + temp_CF;
136 AL = sum;
138 SET_FLAGS_OSZAPC_8(op1, op2, sum, BX_INSTR_ADD_ADC8(temp_CF));
141 void BX_CPU_C::SBB_EbGb(bxInstruction_c *i)
143 Bit8u op2_8, op1_8, diff_8;
144 bx_bool temp_CF = getB_CF();
146 op2_8 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
148 if (i->modC0()) {
149 op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
150 diff_8 = op1_8 - (op2_8 + temp_CF);
151 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), diff_8);
153 else {
154 read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
155 diff_8 = op1_8 - (op2_8 + temp_CF);
156 write_RMW_virtual_byte(diff_8);
159 SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_SUB_SBB8(temp_CF));
162 void BX_CPU_C::SBB_GbEb(bxInstruction_c *i)
164 Bit8u op1_8, op2_8, diff_8;
165 bx_bool temp_CF = getB_CF();
167 op1_8 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
169 if (i->modC0()) {
170 op2_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
172 else {
173 read_virtual_byte(i->seg(), RMAddr(i), &op2_8);
176 diff_8 = op1_8 - (op2_8 + temp_CF);
178 BX_WRITE_8BIT_REGx(i->nnn(), i->extend8bitL(), diff_8);
180 SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_SUB_SBB8(temp_CF));
183 void BX_CPU_C::SBB_ALIb(bxInstruction_c *i)
185 Bit8u op1_8, op2_8, diff_8;
186 bx_bool temp_CF = getB_CF();
188 op1_8 = AL;
189 op2_8 = i->Ib();
190 diff_8 = op1_8 - (op2_8 + temp_CF);
191 AL = diff_8;
193 SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_SUB_SBB8(temp_CF));
196 void BX_CPU_C::SBB_EbIb(bxInstruction_c *i)
198 Bit8u op2_8, op1_8, diff_8;
199 bx_bool temp_CF = getB_CF();
201 op2_8 = i->Ib();
203 if (i->modC0()) {
204 op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
205 diff_8 = op1_8 - (op2_8 + temp_CF);
206 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), diff_8);
208 else {
209 read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
210 diff_8 = op1_8 - (op2_8 + temp_CF);
211 write_RMW_virtual_byte(diff_8);
214 SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_SUB_SBB8(temp_CF));
217 void BX_CPU_C::SUB_EbGb(bxInstruction_c *i)
219 Bit8u op2_8, op1_8, diff_8;
221 op2_8 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
223 if (i->modC0()) {
224 op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
225 diff_8 = op1_8 - op2_8;
226 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), diff_8);
228 else {
229 read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
230 diff_8 = op1_8 - op2_8;
231 write_RMW_virtual_byte(diff_8);
234 SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_SUB8);
237 void BX_CPU_C::SUB_GbEb(bxInstruction_c *i)
239 Bit8u op1_8, op2_8, diff_8;
241 op1_8 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
243 if (i->modC0()) {
244 op2_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
246 else {
247 read_virtual_byte(i->seg(), RMAddr(i), &op2_8);
250 diff_8 = op1_8 - op2_8;
252 BX_WRITE_8BIT_REGx(i->nnn(), i->extend8bitL(), diff_8);
254 SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_SUB8);
257 void BX_CPU_C::SUB_ALIb(bxInstruction_c *i)
259 Bit8u op1_8, op2_8, diff_8;
261 op1_8 = AL;
262 op2_8 = i->Ib();
263 diff_8 = op1_8 - op2_8;
264 AL = diff_8;
266 SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_SUB8);
269 void BX_CPU_C::CMP_EbGb(bxInstruction_c *i)
271 Bit8u op2_8, op1_8;
273 op2_8 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
275 if (i->modC0()) {
276 op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
278 else {
279 read_virtual_byte(i->seg(), RMAddr(i), &op1_8);
282 #if defined(BX_HostAsm_Cmp8)
283 Bit32u flags32;
284 asmCmp8(op1_8, op2_8, flags32);
285 setEFlagsOSZAPC(flags32);
286 #else
287 Bit8u diff_8 = op1_8 - op2_8;
288 SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_COMPARE8);
289 #endif
292 void BX_CPU_C::CMP_GbEb(bxInstruction_c *i)
294 Bit8u op1_8, op2_8;
296 op1_8 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
298 if (i->modC0()) {
299 op2_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
301 else {
302 read_virtual_byte(i->seg(), RMAddr(i), &op2_8);
305 #if defined(BX_HostAsm_Cmp8)
306 Bit32u flags32;
307 asmCmp8(op1_8, op2_8, flags32);
308 setEFlagsOSZAPC(flags32);
309 #else
310 Bit8u diff_8 = op1_8 - op2_8;
311 SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_COMPARE8);
312 #endif
315 void BX_CPU_C::CMP_ALIb(bxInstruction_c *i)
317 Bit8u op1_8 = AL;
318 Bit8u op2_8 = i->Ib();
320 #if defined(BX_HostAsm_Cmp8)
321 Bit32u flags32;
322 asmCmp8(op1_8, op2_8, flags32);
323 setEFlagsOSZAPC(flags32);
324 #else
325 Bit8u diff_8 = op1_8 - op2_8;
326 SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_COMPARE8);
327 #endif
330 void BX_CPU_C::XADD_EbGb(bxInstruction_c *i)
332 #if (BX_CPU_LEVEL >= 4) || (BX_CPU_LEVEL_HACKED >= 4)
333 Bit8u op2, op1, sum;
335 /* XADD dst(r/m8), src(r8)
336 * temp <-- src + dst | sum = op2 + op1
337 * src <-- dst | op2 = op1
338 * dst <-- tmp | op1 = sum
341 op2 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
343 if (i->modC0()) {
344 op1 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
345 sum = op1 + op2;
346 // and write destination into source
347 // Note: if both op1 & op2 are registers, the last one written
348 // should be the sum, as op1 & op2 may be the same register.
349 // For example: XADD AL, AL
350 BX_WRITE_8BIT_REGx(i->nnn(), i->extend8bitL(), op1);
351 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), sum);
353 else {
354 read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
355 sum = op1 + op2;
356 write_RMW_virtual_byte(sum);
357 /* and write destination into source */
358 BX_WRITE_8BIT_REGx(i->nnn(), i->extend8bitL(), op1);
361 SET_FLAGS_OSZAPC_8(op1, op2, sum, BX_INSTR_ADD8);
362 #else
363 BX_INFO(("XADD_EbGb: not supported on < 80486"));
364 UndefinedOpcode(i);
365 #endif
368 void BX_CPU_C::ADD_EbIb(bxInstruction_c *i)
370 Bit8u op2, op1, sum;
372 op2 = i->Ib();
374 if (i->modC0()) {
375 op1 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
376 sum = op1 + op2;
377 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), sum);
379 else {
380 read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
381 sum = op1 + op2;
382 write_RMW_virtual_byte(sum);
385 SET_FLAGS_OSZAPC_8(op1, op2, sum, BX_INSTR_ADD8);
388 void BX_CPU_C::ADC_EbIb(bxInstruction_c *i)
390 Bit8u op2, op1, sum;
391 bx_bool temp_CF = getB_CF();
393 op2 = i->Ib();
395 if (i->modC0()) {
396 op1 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
397 sum = op1 + op2 + temp_CF;
398 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), sum);
400 else {
401 read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
402 sum = op1 + op2 + temp_CF;
403 write_RMW_virtual_byte(sum);
406 SET_FLAGS_OSZAPC_8(op1, op2, sum, BX_INSTR_ADD_ADC8(temp_CF));
409 void BX_CPU_C::SUB_EbIb(bxInstruction_c *i)
411 Bit8u op2_8, op1_8, diff_8;
413 op2_8 = i->Ib();
415 if (i->modC0()) {
416 op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
417 diff_8 = op1_8 - op2_8;
418 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), diff_8);
420 else {
421 read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
422 diff_8 = op1_8 - op2_8;
423 write_RMW_virtual_byte(diff_8);
426 SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_SUB8);
429 void BX_CPU_C::CMP_EbIb(bxInstruction_c *i)
431 Bit8u op2_8, op1_8;
433 op2_8 = i->Ib();
435 if (i->modC0()) {
436 op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
438 else {
439 read_virtual_byte(i->seg(), RMAddr(i), &op1_8);
442 #if defined(BX_HostAsm_Cmp8)
443 Bit32u flags32;
444 asmCmp8(op1_8, op2_8, flags32);
445 setEFlagsOSZAPC(flags32);
446 #else
447 Bit8u diff_8 = op1_8 - op2_8;
448 SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_COMPARE8);
449 #endif
452 void BX_CPU_C::NEG_Eb(bxInstruction_c *i)
454 Bit8u op1_8, diff_8;
456 if (i->modC0()) {
457 op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
458 diff_8 = -op1_8;
459 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), diff_8);
461 else {
462 read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
463 diff_8 = -op1_8;
464 write_RMW_virtual_byte(diff_8);
467 SET_FLAGS_OSZAPC_RESULT_8(diff_8, BX_INSTR_NEG8);
470 void BX_CPU_C::INC_Eb(bxInstruction_c *i)
472 Bit8u op1;
474 if (i->modC0()) {
475 op1 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
476 op1++;
477 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), op1);
479 else {
480 read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
481 op1++;
482 write_RMW_virtual_byte(op1);
485 SET_FLAGS_OSZAP_RESULT_8(op1, BX_INSTR_INC8);
488 void BX_CPU_C::DEC_Eb(bxInstruction_c *i)
490 Bit8u op1_8;
492 if (i->modC0()) {
493 op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
494 op1_8--;
495 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), op1_8);
497 else {
498 read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
499 op1_8--;
500 write_RMW_virtual_byte(op1_8);
503 SET_FLAGS_OSZAP_RESULT_8(op1_8, BX_INSTR_DEC8);
506 void BX_CPU_C::CMPXCHG_EbGb(bxInstruction_c *i)
508 #if (BX_CPU_LEVEL >= 4) || (BX_CPU_LEVEL_HACKED >= 4)
509 Bit8u op2_8, op1_8, diff_8;
511 if (i->modC0()) {
512 op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
514 else {
515 read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
518 diff_8 = AL - op1_8;
520 SET_FLAGS_OSZAPC_8(AL, op1_8, diff_8, BX_INSTR_COMPARE8);
522 if (diff_8 == 0) { // if accumulator == dest
523 // dest <-- src
524 op2_8 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
526 if (i->modC0()) {
527 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), op2_8);
529 else {
530 write_RMW_virtual_byte(op2_8);
533 else {
534 // accumulator <-- dest
535 AL = op1_8;
538 #else
539 BX_INFO(("CMPXCHG_EbGb: not supported for cpulevel <= 3"));
540 UndefinedOpcode(i);
541 #endif