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