1 /////////////////////////////////////////////////////////////////////////
2 // $Id: arith16.cc,v 1.71 2008/08/09 21:05:05 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2001 MandrakeSoft S.A.
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
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
;
78 sum_16
= op1_16
+ op2_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();
119 sum_16
= op1_16
+ op2_16
+ temp_CF
;
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
;
160 diff_16
= op1_16
- (op2_16
+ temp_CF
);
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
;
224 diff_16
= op1_16
- op2_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
;
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 */
271 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CWD(bxInstruction_c
*i
)
273 /* CWD: no flags are affected */
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
);
305 BX_INFO(("XADD_EwGw: not supported on < 80486"));
306 exception(BX_UD_EXCEPTION
, 0, 0);
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
);
334 BX_INFO(("XADD_EwGw: not supported on < 80486"));
335 exception(BX_UD_EXCEPTION
, 0, 0);
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
)
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
)
459 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
461 op1_16
= read_RMW_virtual_word(i
->seg(), eaddr
);
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
)
472 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
474 op1_16
= read_RMW_virtual_word(i
->seg(), eaddr
);
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
494 op2_16
= BX_READ_16BIT_REG(i
->nnn());
495 write_RMW_virtual_word(op2_16
);
498 // accumulator <-- dest
502 BX_INFO(("CMPXCHG_EwGw: not supported for cpu-level <= 3"));
503 exception(BX_UD_EXCEPTION
, 0, 0);
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
518 op2_16
= BX_READ_16BIT_REG(i
->nnn());
519 BX_WRITE_16BIT_REG(i
->rm(), op2_16
);
522 // accumulator <-- dest
526 BX_INFO(("CMPXCHG_EwGw: not supported for cpu-level <= 3"));
527 exception(BX_UD_EXCEPTION
, 0, 0);