1 /////////////////////////////////////////////////////////////////////////
2 // $Id: arith64.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 
27 #if BX_SUPPORT_X86_64
28 
ADD_EqGqM(bxInstruction_c * i)29 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EqGqM(bxInstruction_c *i)
30 {
31   Bit64u op1_64, op2_64, sum_64;
32 
33   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
34 
35   /* pointer, segment address pair */
36   op1_64 = read_RMW_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
37   op2_64 = BX_READ_64BIT_REG(i->src());
38   sum_64 = op1_64 + op2_64;
39   write_RMW_linear_qword(sum_64);
40 
41   SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64);
42 
43   BX_NEXT_INSTR(i);
44 }
45 
ADD_GqEqR(bxInstruction_c * i)46 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GqEqR(bxInstruction_c *i)
47 {
48   Bit64u op1_64, op2_64, sum_64;
49 
50   op1_64 = BX_READ_64BIT_REG(i->dst());
51   op2_64 = BX_READ_64BIT_REG(i->src());
52   sum_64 = op1_64 + op2_64;
53   BX_WRITE_64BIT_REG(i->dst(), sum_64);
54 
55   SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64);
56 
57   BX_NEXT_INSTR(i);
58 }
59 
ADD_GqEqM(bxInstruction_c * i)60 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GqEqM(bxInstruction_c *i)
61 {
62   Bit64u op1_64, op2_64, sum_64;
63 
64   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
65 
66   op1_64 = BX_READ_64BIT_REG(i->dst());
67   op2_64 = read_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
68   sum_64 = op1_64 + op2_64;
69   BX_WRITE_64BIT_REG(i->dst(), sum_64);
70 
71   SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64);
72 
73   BX_NEXT_INSTR(i);
74 }
75 
ADC_EqGqM(bxInstruction_c * i)76 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EqGqM(bxInstruction_c *i)
77 {
78   Bit64u op1_64, op2_64, sum_64;
79 
80   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
81 
82   /* pointer, segment address pair */
83   op1_64 = read_RMW_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
84   op2_64 = BX_READ_64BIT_REG(i->src());
85   sum_64 = op1_64 + op2_64 + getB_CF();
86   write_RMW_linear_qword(sum_64);
87 
88   SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64);
89 
90   BX_NEXT_INSTR(i);
91 }
92 
ADC_GqEqR(bxInstruction_c * i)93 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GqEqR(bxInstruction_c *i)
94 {
95   Bit64u op1_64, op2_64, sum_64;
96 
97   op1_64 = BX_READ_64BIT_REG(i->dst());
98   op2_64 = BX_READ_64BIT_REG(i->src());
99   sum_64 = op1_64 + op2_64 + getB_CF();
100 
101   BX_WRITE_64BIT_REG(i->dst(), sum_64);
102 
103   SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64);
104 
105   BX_NEXT_INSTR(i);
106 }
107 
ADC_GqEqM(bxInstruction_c * i)108 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GqEqM(bxInstruction_c *i)
109 {
110   Bit64u op1_64, op2_64, sum_64;
111 
112   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
113 
114   op1_64 = BX_READ_64BIT_REG(i->dst());
115   op2_64 = read_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
116   sum_64 = op1_64 + op2_64 + getB_CF();
117 
118   BX_WRITE_64BIT_REG(i->dst(), sum_64);
119 
120   SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64);
121 
122   BX_NEXT_INSTR(i);
123 }
124 
SBB_EqGqM(bxInstruction_c * i)125 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EqGqM(bxInstruction_c *i)
126 {
127   Bit64u op1_64, op2_64, diff_64;
128 
129   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
130 
131   /* pointer, segment address pair */
132   op1_64 = read_RMW_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
133   op2_64 = BX_READ_64BIT_REG(i->src());
134   diff_64 = op1_64 - (op2_64 + getB_CF());
135   write_RMW_linear_qword(diff_64);
136 
137   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
138 
139   BX_NEXT_INSTR(i);
140 }
141 
SBB_GqEqR(bxInstruction_c * i)142 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GqEqR(bxInstruction_c *i)
143 {
144   Bit64u op1_64, op2_64, diff_64;
145 
146   op1_64 = BX_READ_64BIT_REG(i->dst());
147   op2_64 = BX_READ_64BIT_REG(i->src());
148   diff_64 = op1_64 - (op2_64 + getB_CF());
149 
150   BX_WRITE_64BIT_REG(i->dst(), diff_64);
151 
152   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
153 
154   BX_NEXT_INSTR(i);
155 }
156 
SBB_GqEqM(bxInstruction_c * i)157 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GqEqM(bxInstruction_c *i)
158 {
159   Bit64u op1_64, op2_64, diff_64;
160 
161   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
162 
163   op1_64 = BX_READ_64BIT_REG(i->dst());
164   op2_64 = read_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
165   diff_64 = op1_64 - (op2_64 + getB_CF());
166 
167   BX_WRITE_64BIT_REG(i->dst(), diff_64);
168 
169   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
170 
171   BX_NEXT_INSTR(i);
172 }
173 
SBB_EqIdM(bxInstruction_c * i)174 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EqIdM(bxInstruction_c *i)
175 {
176   Bit64u op1_64, op2_64, diff_64;
177 
178   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
179 
180   /* pointer, segment address pair */
181   op1_64 = read_RMW_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
182   op2_64 = (Bit32s) i->Id();
183   diff_64 = op1_64 - (op2_64 + getB_CF());
184   write_RMW_linear_qword(diff_64);
185 
186   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
187 
188   BX_NEXT_INSTR(i);
189 }
190 
SBB_EqIdR(bxInstruction_c * i)191 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EqIdR(bxInstruction_c *i)
192 {
193   Bit64u op1_64, op2_64, diff_64;
194 
195   op1_64 = BX_READ_64BIT_REG(i->dst());
196   op2_64 = (Bit32s) i->Id();
197   diff_64 = op1_64 - (op2_64 + getB_CF());
198   BX_WRITE_64BIT_REG(i->dst(), diff_64);
199 
200   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
201 
202   BX_NEXT_INSTR(i);
203 }
204 
SUB_EqGqM(bxInstruction_c * i)205 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EqGqM(bxInstruction_c *i)
206 {
207   Bit64u op1_64, op2_64, diff_64;
208 
209   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
210 
211   /* pointer, segment address pair */
212   op1_64 = read_RMW_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
213   op2_64 = BX_READ_64BIT_REG(i->src());
214   diff_64 = op1_64 - op2_64;
215   write_RMW_linear_qword(diff_64);
216 
217   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
218 
219   BX_NEXT_INSTR(i);
220 }
221 
SUB_GqEqR(bxInstruction_c * i)222 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GqEqR(bxInstruction_c *i)
223 {
224   Bit64u op1_64, op2_64, diff_64;
225 
226   op1_64 = BX_READ_64BIT_REG(i->dst());
227   op2_64 = BX_READ_64BIT_REG(i->src());
228   diff_64 = op1_64 - op2_64;
229 
230   BX_WRITE_64BIT_REG(i->dst(), diff_64);
231 
232   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
233 
234   BX_NEXT_INSTR(i);
235 }
236 
SUB_GqEqM(bxInstruction_c * i)237 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GqEqM(bxInstruction_c *i)
238 {
239   Bit64u op1_64, op2_64, diff_64;
240 
241   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
242 
243   op1_64 = BX_READ_64BIT_REG(i->dst());
244   op2_64 = read_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
245   diff_64 = op1_64 - op2_64;
246 
247   BX_WRITE_64BIT_REG(i->dst(), diff_64);
248 
249   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
250 
251   BX_NEXT_INSTR(i);
252 }
253 
CMP_EqGqM(bxInstruction_c * i)254 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EqGqM(bxInstruction_c *i)
255 {
256   Bit64u op1_64, op2_64, diff_64;
257 
258   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
259 
260   op1_64 = read_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
261   op2_64 = BX_READ_64BIT_REG(i->src());
262   diff_64 = op1_64 - op2_64;
263 
264   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
265 
266   BX_NEXT_INSTR(i);
267 }
268 
CMP_GqEqR(bxInstruction_c * i)269 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GqEqR(bxInstruction_c *i)
270 {
271   Bit64u op1_64, op2_64, diff_64;
272 
273   op1_64 = BX_READ_64BIT_REG(i->dst());
274   op2_64 = BX_READ_64BIT_REG(i->src());
275   diff_64 = op1_64 - op2_64;
276 
277   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
278 
279   BX_NEXT_INSTR(i);
280 }
281 
CMP_GqEqM(bxInstruction_c * i)282 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GqEqM(bxInstruction_c *i)
283 {
284   Bit64u op1_64, op2_64, diff_64;
285 
286   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
287 
288   op1_64 = BX_READ_64BIT_REG(i->dst());
289   op2_64 = read_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
290   diff_64 = op1_64 - op2_64;
291 
292   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
293 
294   BX_NEXT_INSTR(i);
295 }
296 
CDQE(bxInstruction_c * i)297 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CDQE(bxInstruction_c *i)
298 {
299   /* CWDE: no flags are affected */
300   RAX = (Bit32s) EAX;
301 
302   BX_NEXT_INSTR(i);
303 }
304 
CQO(bxInstruction_c * i)305 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CQO(bxInstruction_c *i)
306 {
307   /* CQO: no flags are affected */
308 
309   if (RAX & BX_CONST64(0x8000000000000000))
310       RDX = BX_CONST64(0xffffffffffffffff);
311   else
312       RDX = 0;
313 
314   BX_NEXT_INSTR(i);
315 }
316 
XADD_EqGqM(bxInstruction_c * i)317 void BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EqGqM(bxInstruction_c *i)
318 {
319   Bit64u op1_64, op2_64, sum_64;
320 
321   /* XADD dst(r/m), src(r)
322    * temp <-- src + dst         | sum = op2 + op1
323    * src  <-- dst               | op2 = op1
324    * dst  <-- tmp               | op1 = sum
325    */
326 
327   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
328 
329   /* pointer, segment address pair */
330   op1_64 = read_RMW_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
331   op2_64 = BX_READ_64BIT_REG(i->src());
332   sum_64 = op1_64 + op2_64;
333   write_RMW_linear_qword(sum_64);
334 
335   /* and write destination into source */
336   BX_WRITE_64BIT_REG(i->src(), op1_64);
337 
338   SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64);
339 
340   BX_NEXT_INSTR(i);
341 }
342 
XADD_EqGqR(bxInstruction_c * i)343 void BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EqGqR(bxInstruction_c *i)
344 {
345   Bit64u op1_64, op2_64, sum_64;
346 
347   /* XADD dst(r/m), src(r)
348    * temp <-- src + dst         | sum = op2 + op1
349    * src  <-- dst               | op2 = op1
350    * dst  <-- tmp               | op1 = sum
351    */
352 
353   op1_64 = BX_READ_64BIT_REG(i->dst());
354   op2_64 = BX_READ_64BIT_REG(i->src());
355   sum_64 = op1_64 + op2_64;
356 
357   // and write destination into source
358   // Note: if both op1 & op2 are registers, the last one written
359   //       should be the sum, as op1 & op2 may be the same register.
360   //       For example:  XADD AL, AL
361   BX_WRITE_64BIT_REG(i->src(), op1_64);
362   BX_WRITE_64BIT_REG(i->dst(), sum_64);
363 
364   SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64);
365 
366   BX_NEXT_INSTR(i);
367 }
368 
ADD_EqIdM(bxInstruction_c * i)369 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EqIdM(bxInstruction_c *i)
370 {
371   Bit64u op1_64, op2_64, sum_64;
372 
373   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
374 
375   /* pointer, segment address pair */
376   op1_64 = read_RMW_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
377   op2_64 = (Bit32s) i->Id();
378   sum_64 = op1_64 + op2_64;
379   write_RMW_linear_qword(sum_64);
380 
381   SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64);
382 
383   BX_NEXT_INSTR(i);
384 }
385 
ADD_EqIdR(bxInstruction_c * i)386 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EqIdR(bxInstruction_c *i)
387 {
388   Bit64u op1_64, op2_64, sum_64;
389 
390   op1_64 = BX_READ_64BIT_REG(i->dst());
391   op2_64 = (Bit32s) i->Id();
392   sum_64 = op1_64 + op2_64;
393   BX_WRITE_64BIT_REG(i->dst(), sum_64);
394 
395   SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64);
396 
397   BX_NEXT_INSTR(i);
398 }
399 
ADC_EqIdM(bxInstruction_c * i)400 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EqIdM(bxInstruction_c *i)
401 {
402   Bit64u op1_64, op2_64, sum_64;
403 
404   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
405 
406   /* pointer, segment address pair */
407   op1_64 = read_RMW_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
408   op2_64 = (Bit32s) i->Id();
409   sum_64 = op1_64 + op2_64 + getB_CF();
410   write_RMW_linear_qword(sum_64);
411 
412   SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64);
413 
414   BX_NEXT_INSTR(i);
415 }
416 
ADC_EqIdR(bxInstruction_c * i)417 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EqIdR(bxInstruction_c *i)
418 {
419   Bit64u op1_64, op2_64, sum_64;
420 
421   op1_64 = BX_READ_64BIT_REG(i->dst());
422   op2_64 = (Bit32s) i->Id();
423   sum_64 = op1_64 + op2_64 + getB_CF();
424   BX_WRITE_64BIT_REG(i->dst(), sum_64);
425 
426   SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64);
427 
428   BX_NEXT_INSTR(i);
429 }
430 
SUB_EqIdM(bxInstruction_c * i)431 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EqIdM(bxInstruction_c *i)
432 {
433   Bit64u op1_64, op2_64, diff_64;
434 
435   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
436 
437   /* pointer, segment address pair */
438   op1_64 = read_RMW_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
439   op2_64 = (Bit32s) i->Id();
440   diff_64 = op1_64 - op2_64;
441   write_RMW_linear_qword(diff_64);
442 
443   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
444 
445   BX_NEXT_INSTR(i);
446 }
447 
SUB_EqIdR(bxInstruction_c * i)448 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EqIdR(bxInstruction_c *i)
449 {
450   Bit64u op1_64, op2_64, diff_64;
451 
452   op1_64 = BX_READ_64BIT_REG(i->dst());
453   op2_64 = (Bit32s) i->Id();
454   diff_64 = op1_64 - op2_64;
455   BX_WRITE_64BIT_REG(i->dst(), diff_64);
456 
457   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
458 
459   BX_NEXT_INSTR(i);
460 }
461 
CMP_EqIdM(bxInstruction_c * i)462 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EqIdM(bxInstruction_c *i)
463 {
464   Bit64u op1_64, op2_64, diff_64;
465 
466   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
467 
468   op1_64 = read_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
469   op2_64 = (Bit32s) i->Id();
470   diff_64 = op1_64 - op2_64;
471 
472   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
473 
474   BX_NEXT_INSTR(i);
475 }
476 
CMP_EqIdR(bxInstruction_c * i)477 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EqIdR(bxInstruction_c *i)
478 {
479   Bit64u op1_64, op2_64, diff_64;
480 
481   op1_64 = BX_READ_64BIT_REG(i->dst());
482   op2_64 = (Bit32s) i->Id();
483   diff_64 = op1_64 - op2_64;
484 
485   SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64);
486 
487   BX_NEXT_INSTR(i);
488 }
489 
NEG_EqM(bxInstruction_c * i)490 void BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EqM(bxInstruction_c *i)
491 {
492   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
493 
494   Bit64u op1_64 = read_RMW_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
495   op1_64 = - (Bit64s)(op1_64);
496   write_RMW_linear_qword(op1_64);
497 
498   SET_FLAGS_OSZAPC_SUB_64(0, -op1_64, op1_64);
499 
500   BX_NEXT_INSTR(i);
501 }
502 
NEG_EqR(bxInstruction_c * i)503 void BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EqR(bxInstruction_c *i)
504 {
505   Bit64u op1_64 = BX_READ_64BIT_REG(i->dst());
506   op1_64 = - (Bit64s)(op1_64);
507   BX_WRITE_64BIT_REG(i->dst(), op1_64);
508 
509   SET_FLAGS_OSZAPC_SUB_64(0, -op1_64, op1_64);
510 
511   BX_NEXT_INSTR(i);
512 }
513 
INC_EqM(bxInstruction_c * i)514 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_EqM(bxInstruction_c *i)
515 {
516   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
517 
518   Bit64u op1_64 = read_RMW_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
519   op1_64++;
520   write_RMW_linear_qword(op1_64);
521 
522   SET_FLAGS_OSZAP_ADD_64(op1_64 - 1, 0, op1_64);
523 
524   BX_NEXT_INSTR(i);
525 }
526 
INC_EqR(bxInstruction_c * i)527 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_EqR(bxInstruction_c *i)
528 {
529   Bit64u rrx = ++BX_READ_64BIT_REG(i->dst());
530   SET_FLAGS_OSZAP_ADD_64(rrx - 1, 0, rrx);
531 
532   BX_NEXT_INSTR(i);
533 }
534 
DEC_EqM(bxInstruction_c * i)535 void BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_EqM(bxInstruction_c *i)
536 {
537   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
538 
539   Bit64u op1_64 = read_RMW_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
540   op1_64--;
541   write_RMW_linear_qword(op1_64);
542 
543   SET_FLAGS_OSZAP_SUB_64(op1_64 + 1, 0, op1_64);
544 
545   BX_NEXT_INSTR(i);
546 }
547 
DEC_EqR(bxInstruction_c * i)548 void BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_EqR(bxInstruction_c *i)
549 {
550   Bit64u rrx = --BX_READ_64BIT_REG(i->dst());
551   SET_FLAGS_OSZAP_SUB_64(rrx + 1, 0, rrx);
552 
553   BX_NEXT_INSTR(i);
554 }
555 
CMPXCHG_EqGqM(bxInstruction_c * i)556 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EqGqM(bxInstruction_c *i)
557 {
558   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
559 
560   Bit64u op1_64 = read_RMW_linear_qword(i->seg(), get_laddr64(i->seg(), eaddr));
561   Bit64u diff_64 = RAX - op1_64;
562   SET_FLAGS_OSZAPC_SUB_64(RAX, op1_64, diff_64);
563 
564   if (diff_64 == 0) {  // if accumulator == dest
565     // dest <-- src
566     write_RMW_linear_qword(BX_READ_64BIT_REG(i->src()));
567   }
568   else {
569     // accumulator <-- dest
570     write_RMW_linear_qword(op1_64);
571     RAX = op1_64;
572   }
573 
574   BX_NEXT_INSTR(i);
575 }
576 
CMPXCHG_EqGqR(bxInstruction_c * i)577 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EqGqR(bxInstruction_c *i)
578 {
579   Bit64u op1_64 = BX_READ_64BIT_REG(i->dst());
580   Bit64u diff_64 = RAX - op1_64;
581   SET_FLAGS_OSZAPC_SUB_64(RAX, op1_64, diff_64);
582 
583   if (diff_64 == 0) {  // if accumulator == dest
584     // dest <-- src
585     BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src()));
586   }
587   else {
588     // accumulator <-- dest
589     RAX = op1_64;
590   }
591 
592   BX_NEXT_INSTR(i);
593 }
594 
CMPXCHG16B(bxInstruction_c * i)595 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG16B(bxInstruction_c *i)
596 {
597   bx_address eaddr = BX_CPU_RESOLVE_ADDR_64(i);
598 
599   Bit64u op1_64_lo, op1_64_hi, diff;
600 
601   // check write permission for following write
602   read_RMW_linear_dqword_aligned_64(i->seg(), get_laddr64(i->seg(), eaddr), &op1_64_hi, &op1_64_lo);
603 
604   diff  = RAX - op1_64_lo;
605   diff |= RDX - op1_64_hi;
606 
607   if (diff == 0) {  // if accumulator == dest
608     write_RMW_linear_dqword(RCX, RBX);
609     assert_ZF();
610   }
611   else {
612     clear_ZF();
613     write_RMW_linear_dqword(op1_64_hi, op1_64_lo);
614     // accumulator <-- dest
615     RAX = op1_64_lo;
616     RDX = op1_64_hi;
617   }
618 
619   BX_NEXT_INSTR(i);
620 }
621 
622 #endif /* if BX_SUPPORT_X86_64 */
623