1 /////////////////////////////////////////////////////////////////////////
2 // $Id: arith16.cc 13466 2018-02-16 07:57:32Z sshwarts $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //  Copyright (C) 2001-2018  The Bochs Project
6 //
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Lesser General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2 of the License, or (at your option) any later version.
11 //
12 //  This library 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 GNU
15 //  Lesser General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Lesser General Public
18 //  License along with this library; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
20 /////////////////////////////////////////////////////////////////////////
21 
22 #define NEED_CPU_REG_SHORTCUTS 1
23 #include "bochs.h"
24 #include "cpu.h"
25 #define LOG_THIS BX_CPU_THIS_PTR
26 
INC_EwR(bxInstruction_c * i)27 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_EwR(bxInstruction_c *i)
28 {
29   Bit32u rx = ++BX_READ_16BIT_REG(i->dst());
30   SET_FLAGS_OSZAP_ADD_16(rx - 1, 0, rx);
31 
32   BX_NEXT_INSTR(i);
33 }
34 
DEC_EwR(bxInstruction_c * i)35 void BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_EwR(bxInstruction_c *i)
36 {
37   Bit32u rx = --BX_READ_16BIT_REG(i->dst());
38   SET_FLAGS_OSZAP_SUB_16(rx + 1, 0, rx);
39 
40   BX_NEXT_INSTR(i);
41 }
42 
ADD_EwGwM(bxInstruction_c * i)43 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EwGwM(bxInstruction_c *i)
44 {
45   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
46 
47   Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
48   Bit32u op2_16 = BX_READ_16BIT_REG(i->src());
49   Bit32u sum_16 = op1_16 + op2_16;
50 
51   write_RMW_linear_word(sum_16);
52 
53   SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
54 
55   BX_NEXT_INSTR(i);
56 }
57 
ADD_GwEwR(bxInstruction_c * i)58 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GwEwR(bxInstruction_c *i)
59 {
60   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
61   Bit32u op2_16 = BX_READ_16BIT_REG(i->src());
62   Bit32u sum_16 = op1_16 + op2_16;
63 
64   BX_WRITE_16BIT_REG(i->dst(), sum_16);
65 
66   SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
67 
68   BX_NEXT_INSTR(i);
69 }
70 
ADD_GwEwM(bxInstruction_c * i)71 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GwEwM(bxInstruction_c *i)
72 {
73   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
74 
75   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
76   Bit32u op2_16 = read_virtual_word(i->seg(), eaddr);
77   Bit32u sum_16 = op1_16 + op2_16;
78 
79   BX_WRITE_16BIT_REG(i->dst(), sum_16);
80 
81   SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
82 
83   BX_NEXT_INSTR(i);
84 }
85 
ADC_EwGwM(bxInstruction_c * i)86 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EwGwM(bxInstruction_c *i)
87 {
88   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
89 
90   Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
91   Bit32u op2_16 = BX_READ_16BIT_REG(i->src());
92   Bit32u sum_16 = op1_16 + op2_16 + getB_CF();
93 
94   write_RMW_linear_word(sum_16);
95 
96   SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
97 
98   BX_NEXT_INSTR(i);
99 }
100 
ADC_GwEwR(bxInstruction_c * i)101 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GwEwR(bxInstruction_c *i)
102 {
103   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
104   Bit32u op2_16 = BX_READ_16BIT_REG(i->src());
105   Bit32u sum_16 = op1_16 + op2_16 + getB_CF();
106 
107   BX_WRITE_16BIT_REG(i->dst(), sum_16);
108 
109   SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
110 
111   BX_NEXT_INSTR(i);
112 }
113 
ADC_GwEwM(bxInstruction_c * i)114 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GwEwM(bxInstruction_c *i)
115 {
116   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
117 
118   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
119   Bit32u op2_16 = read_virtual_word(i->seg(), eaddr);
120   Bit32u sum_16 = op1_16 + op2_16 + getB_CF();
121 
122   BX_WRITE_16BIT_REG(i->dst(), sum_16);
123 
124   SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
125 
126   BX_NEXT_INSTR(i);
127 }
128 
SBB_EwGwM(bxInstruction_c * i)129 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EwGwM(bxInstruction_c *i)
130 {
131   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
132 
133   Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
134   Bit32u op2_16 = BX_READ_16BIT_REG(i->src());
135   Bit32u diff_16 = op1_16 - (op2_16 + getB_CF());
136 
137   write_RMW_linear_word(diff_16);
138 
139   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
140 
141   BX_NEXT_INSTR(i);
142 }
143 
SBB_GwEwR(bxInstruction_c * i)144 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GwEwR(bxInstruction_c *i)
145 {
146   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
147   Bit32u op2_16 = BX_READ_16BIT_REG(i->src());
148   Bit32u diff_16 = op1_16 - (op2_16 + getB_CF());
149 
150   BX_WRITE_16BIT_REG(i->dst(), diff_16);
151 
152   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
153 
154   BX_NEXT_INSTR(i);
155 }
156 
SBB_GwEwM(bxInstruction_c * i)157 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GwEwM(bxInstruction_c *i)
158 {
159   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
160 
161   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
162   Bit32u op2_16 = read_virtual_word(i->seg(), eaddr);
163   Bit32u diff_16 = op1_16 - (op2_16 + getB_CF());
164 
165   BX_WRITE_16BIT_REG(i->dst(), diff_16);
166 
167   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
168 
169   BX_NEXT_INSTR(i);
170 }
171 
SBB_EwIwM(bxInstruction_c * i)172 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EwIwM(bxInstruction_c *i)
173 {
174   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
175 
176   Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
177   Bit32u op2_16 = i->Iw();
178   Bit32u diff_16 = op1_16 - (op2_16 + getB_CF());
179 
180   write_RMW_linear_word(diff_16);
181 
182   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
183 
184   BX_NEXT_INSTR(i);
185 }
186 
SBB_EwIwR(bxInstruction_c * i)187 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EwIwR(bxInstruction_c *i)
188 {
189   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
190   Bit32u op2_16 = i->Iw();
191   Bit32u diff_16 = op1_16 - (op2_16 + getB_CF());
192 
193   BX_WRITE_16BIT_REG(i->dst(), diff_16);
194 
195   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
196 
197   BX_NEXT_INSTR(i);
198 }
199 
SUB_EwGwM(bxInstruction_c * i)200 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EwGwM(bxInstruction_c *i)
201 {
202   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
203 
204   Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
205   Bit32u op2_16 = BX_READ_16BIT_REG(i->src());
206   Bit32u diff_16 = op1_16 - op2_16;
207 
208   write_RMW_linear_word(diff_16);
209 
210   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
211 
212   BX_NEXT_INSTR(i);
213 }
214 
SUB_GwEwR(bxInstruction_c * i)215 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GwEwR(bxInstruction_c *i)
216 {
217   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
218   Bit32u op2_16 = BX_READ_16BIT_REG(i->src());
219   Bit32u diff_16 = op1_16 - op2_16;
220 
221   BX_WRITE_16BIT_REG(i->dst(), diff_16);
222 
223   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
224 
225   BX_NEXT_INSTR(i);
226 }
227 
SUB_GwEwM(bxInstruction_c * i)228 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GwEwM(bxInstruction_c *i)
229 {
230   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
231 
232   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
233   Bit32u op2_16 = read_virtual_word(i->seg(), eaddr);
234   Bit32u diff_16 = op1_16 - op2_16;
235 
236   BX_WRITE_16BIT_REG(i->dst(), diff_16);
237 
238   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
239 
240   BX_NEXT_INSTR(i);
241 }
242 
CMP_EwGwM(bxInstruction_c * i)243 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EwGwM(bxInstruction_c *i)
244 {
245   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
246 
247   Bit32u op1_16 = read_virtual_word(i->seg(), eaddr);
248   Bit32u op2_16 = BX_READ_16BIT_REG(i->src());
249   Bit32u diff_16 = op1_16 - op2_16;
250 
251   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
252 
253   BX_NEXT_INSTR(i);
254 }
255 
CMP_GwEwR(bxInstruction_c * i)256 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GwEwR(bxInstruction_c *i)
257 {
258   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
259   Bit32u op2_16 = BX_READ_16BIT_REG(i->src());
260   Bit32u diff_16 = op1_16 - op2_16;
261 
262   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
263 
264   BX_NEXT_INSTR(i);
265 }
266 
CMP_GwEwM(bxInstruction_c * i)267 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GwEwM(bxInstruction_c *i)
268 {
269   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
270 
271   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
272   Bit32u op2_16 = read_virtual_word(i->seg(), eaddr);
273   Bit32u diff_16 = op1_16 - op2_16;
274 
275   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
276 
277   BX_NEXT_INSTR(i);
278 }
279 
CBW(bxInstruction_c * i)280 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CBW(bxInstruction_c *i)
281 {
282   /* CBW: no flags are effected */
283   AX = (Bit8s) AL;
284 
285   BX_NEXT_INSTR(i);
286 }
287 
CWD(bxInstruction_c * i)288 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CWD(bxInstruction_c *i)
289 {
290   /* CWD: no flags are affected */
291   if (AX & 0x8000) {
292     DX = 0xFFFF;
293   }
294   else {
295     DX = 0x0000;
296   }
297 
298   BX_NEXT_INSTR(i);
299 }
300 
XADD_EwGwM(bxInstruction_c * i)301 void BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EwGwM(bxInstruction_c *i)
302 {
303   /* XADD dst(r/m), src(r)
304    * temp <-- src + dst         | sum = op2 + op1
305    * src  <-- dst               | op2 = op1
306    * dst  <-- tmp               | op1 = sum
307    */
308 
309   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
310 
311   Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
312   Bit32u op2_16 = BX_READ_16BIT_REG(i->src());
313   Bit32u sum_16 = op1_16 + op2_16;
314 
315   write_RMW_linear_word(sum_16);
316 
317   /* and write destination into source */
318   BX_WRITE_16BIT_REG(i->src(), op1_16);
319 
320   SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
321 
322   BX_NEXT_INSTR(i);
323 }
324 
XADD_EwGwR(bxInstruction_c * i)325 void BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EwGwR(bxInstruction_c *i)
326 {
327   /* XADD dst(r/m), src(r)
328    * temp <-- src + dst         | sum = op2 + op1
329    * src  <-- dst               | op2 = op1
330    * dst  <-- tmp               | op1 = sum
331    */
332 
333   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
334   Bit32u op2_16 = BX_READ_16BIT_REG(i->src());
335   Bit32u sum_16 = op1_16 + op2_16;
336 
337   // and write destination into source
338   // Note: if both op1 & op2 are registers, the last one written
339   //       should be the sum, as op1 & op2 may be the same register.
340   //       For example:  XADD AL, AL
341   BX_WRITE_16BIT_REG(i->src(), op1_16);
342   BX_WRITE_16BIT_REG(i->dst(), sum_16);
343 
344   SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
345 
346   BX_NEXT_INSTR(i);
347 }
348 
ADD_EwIwM(bxInstruction_c * i)349 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EwIwM(bxInstruction_c *i)
350 {
351   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
352 
353   Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
354   Bit32u op2_16 = i->Iw();
355   Bit32u sum_16 = op1_16 + op2_16;
356 
357   write_RMW_linear_word(sum_16);
358 
359   SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
360 
361   BX_NEXT_INSTR(i);
362 }
363 
ADD_EwIwR(bxInstruction_c * i)364 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EwIwR(bxInstruction_c *i)
365 {
366   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
367   Bit32u op2_16 = i->Iw();
368   Bit32u sum_16 = op1_16 + op2_16;
369   BX_WRITE_16BIT_REG(i->dst(), sum_16);
370 
371   SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
372 
373   BX_NEXT_INSTR(i);
374 }
375 
ADC_EwIwM(bxInstruction_c * i)376 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EwIwM(bxInstruction_c *i)
377 {
378   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
379 
380   Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
381   Bit32u op2_16 = i->Iw();
382   Bit32u sum_16 = op1_16 + op2_16 + getB_CF();
383 
384   write_RMW_linear_word(sum_16);
385 
386   SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
387 
388   BX_NEXT_INSTR(i);
389 }
390 
ADC_EwIwR(bxInstruction_c * i)391 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EwIwR(bxInstruction_c *i)
392 {
393   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
394   Bit32u op2_16 = i->Iw();
395   Bit32u sum_16 = op1_16 + op2_16 + getB_CF();
396 
397   BX_WRITE_16BIT_REG(i->dst(), sum_16);
398 
399   SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16);
400 
401   BX_NEXT_INSTR(i);
402 }
403 
SUB_EwIwM(bxInstruction_c * i)404 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EwIwM(bxInstruction_c *i)
405 {
406   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
407 
408   Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
409   Bit32u op2_16 = i->Iw();
410   Bit32u diff_16 = op1_16 - op2_16;
411 
412   write_RMW_linear_word(diff_16);
413 
414   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
415 
416   BX_NEXT_INSTR(i);
417 }
418 
SUB_EwIwR(bxInstruction_c * i)419 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EwIwR(bxInstruction_c *i)
420 {
421   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
422   Bit32u op2_16 = i->Iw();
423   Bit32u diff_16 = op1_16 - op2_16;
424 
425   BX_WRITE_16BIT_REG(i->dst(), diff_16);
426 
427   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
428 
429   BX_NEXT_INSTR(i);
430 }
431 
CMP_EwIwM(bxInstruction_c * i)432 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EwIwM(bxInstruction_c *i)
433 {
434   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
435 
436   Bit32u op1_16 = read_virtual_word(i->seg(), eaddr);
437   Bit32u op2_16 = i->Iw();
438   Bit32u diff_16 = op1_16 - op2_16;
439 
440   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
441 
442   BX_NEXT_INSTR(i);
443 }
444 
CMP_EwIwR(bxInstruction_c * i)445 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EwIwR(bxInstruction_c *i)
446 {
447   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
448   Bit32u op2_16 = i->Iw();
449   Bit32u diff_16 = op1_16 - op2_16;
450 
451   SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16);
452 
453   BX_NEXT_INSTR(i);
454 }
455 
NEG_EwM(bxInstruction_c * i)456 void BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EwM(bxInstruction_c *i)
457 {
458   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
459 
460   Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
461   op1_16 = 0 - (Bit32s)(Bit16s)(op1_16);
462   write_RMW_linear_word(op1_16);
463 
464   SET_FLAGS_OSZAPC_SUB_16(0, 0 - op1_16, op1_16);
465 
466   BX_NEXT_INSTR(i);
467 }
468 
NEG_EwR(bxInstruction_c * i)469 void BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EwR(bxInstruction_c *i)
470 {
471   Bit32u op1_16 = BX_READ_16BIT_REG(i->dst());
472   op1_16 = 0 - (Bit32s)(Bit16s)(op1_16);
473   BX_WRITE_16BIT_REG(i->dst(), op1_16);
474 
475   SET_FLAGS_OSZAPC_SUB_16(0, 0 - op1_16, op1_16);
476 
477   BX_NEXT_INSTR(i);
478 }
479 
INC_EwM(bxInstruction_c * i)480 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_EwM(bxInstruction_c *i)
481 {
482   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
483 
484   Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
485   op1_16++;
486   write_RMW_linear_word(op1_16);
487 
488   SET_FLAGS_OSZAP_ADD_16(op1_16 - 1, 0, op1_16);
489 
490   BX_NEXT_INSTR(i);
491 }
492 
DEC_EwM(bxInstruction_c * i)493 void BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_EwM(bxInstruction_c *i)
494 {
495   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
496 
497   Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
498   op1_16--;
499   write_RMW_linear_word(op1_16);
500 
501   SET_FLAGS_OSZAP_SUB_16(op1_16 + 1, 0, op1_16);
502 
503   BX_NEXT_INSTR(i);
504 }
505 
CMPXCHG_EwGwM(bxInstruction_c * i)506 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EwGwM(bxInstruction_c *i)
507 {
508   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
509 
510   Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
511   Bit16u diff_16 = AX - op1_16;
512 
513   SET_FLAGS_OSZAPC_SUB_16(AX, op1_16, diff_16);
514 
515   if (diff_16 == 0) {  // if accumulator == dest
516     // dest <-- src
517     write_RMW_linear_word(BX_READ_16BIT_REG(i->src()));
518   }
519   else {
520     // accumulator <-- dest
521     write_RMW_linear_word(op1_16);
522     AX = op1_16;
523   }
524 
525   BX_NEXT_INSTR(i);
526 }
527 
CMPXCHG_EwGwR(bxInstruction_c * i)528 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EwGwR(bxInstruction_c *i)
529 {
530   Bit16u op1_16 = BX_READ_16BIT_REG(i->dst());
531   Bit16u diff_16 = AX - op1_16;
532 
533   SET_FLAGS_OSZAPC_SUB_16(AX, op1_16, diff_16);
534 
535   if (diff_16 == 0) {  // if accumulator == dest
536     // dest <-- src
537     BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
538   }
539   else {
540     // accumulator <-- dest
541     AX = op1_16;
542   }
543 
544   BX_NEXT_INSTR(i);
545 }
546