1 /////////////////////////////////////////////////////////////////////////
2 // $Id: arith64.cc,v 1.57 2008/09/05 21:43:12 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
35 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EqGqM(bxInstruction_c
*i
)
37 Bit64u op1_64
, op2_64
, sum_64
;
39 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
41 /* pointer, segment address pair */
42 op1_64
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
43 op2_64
= BX_READ_64BIT_REG(i
->nnn());
44 sum_64
= op1_64
+ op2_64
;
45 write_RMW_virtual_qword(sum_64
);
47 SET_FLAGS_OSZAPC_ADD_64(op1_64
, op2_64
, sum_64
);
50 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GqEqR(bxInstruction_c
*i
)
52 Bit64u op1_64
, op2_64
, sum_64
;
54 op1_64
= BX_READ_64BIT_REG(i
->nnn());
55 op2_64
= BX_READ_64BIT_REG(i
->rm());
56 sum_64
= op1_64
+ op2_64
;
57 BX_WRITE_64BIT_REG(i
->nnn(), sum_64
);
59 SET_FLAGS_OSZAPC_ADD_64(op1_64
, op2_64
, sum_64
);
62 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_RAXId(bxInstruction_c
*i
)
64 Bit64u op1_64
, op2_64
, sum_64
;
67 op2_64
= (Bit32s
) i
->Id();
68 sum_64
= op1_64
+ op2_64
;
70 /* now write sum back to destination */
73 SET_FLAGS_OSZAPC_ADD_64(op1_64
, op2_64
, sum_64
);
76 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EqGqM(bxInstruction_c
*i
)
78 bx_bool temp_CF
= getB_CF();
80 Bit64u op1_64
, op2_64
, sum_64
;
82 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
84 /* pointer, segment address pair */
85 op1_64
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
86 op2_64
= BX_READ_64BIT_REG(i
->nnn());
87 sum_64
= op1_64
+ op2_64
+ temp_CF
;
88 write_RMW_virtual_qword(sum_64
);
90 SET_FLAGS_OSZAPC_64(op1_64
, op2_64
, sum_64
, BX_LF_INSTR_ADD_ADC64(temp_CF
));
93 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GqEqR(bxInstruction_c
*i
)
95 bx_bool temp_CF
= getB_CF();
97 Bit64u op1_64
, op2_64
, sum_64
;
99 op1_64
= BX_READ_64BIT_REG(i
->nnn());
100 op2_64
= BX_READ_64BIT_REG(i
->rm());
101 sum_64
= op1_64
+ op2_64
+ temp_CF
;
103 /* now write sum back to destination */
104 BX_WRITE_64BIT_REG(i
->nnn(), sum_64
);
106 SET_FLAGS_OSZAPC_64(op1_64
, op2_64
, sum_64
, BX_LF_INSTR_ADD_ADC64(temp_CF
));
109 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_RAXId(bxInstruction_c
*i
)
111 bx_bool temp_CF
= getB_CF();
113 Bit64u op1_64
, op2_64
, sum_64
;
116 op2_64
= (Bit32s
) i
->Id();
117 sum_64
= op1_64
+ op2_64
+ temp_CF
;
119 /* now write sum back to destination */
122 SET_FLAGS_OSZAPC_64(op1_64
, op2_64
, sum_64
, BX_LF_INSTR_ADD_ADC64(temp_CF
));
125 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EqGqM(bxInstruction_c
*i
)
127 bx_bool temp_CF
= getB_CF();
129 Bit64u op1_64
, op2_64
, diff_64
;
131 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
133 /* pointer, segment address pair */
134 op1_64
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
135 op2_64
= BX_READ_64BIT_REG(i
->nnn());
136 diff_64
= op1_64
- (op2_64
+ temp_CF
);
137 write_RMW_virtual_qword(diff_64
);
139 SET_FLAGS_OSZAPC_64(op1_64
, op2_64
, diff_64
, BX_LF_INSTR_SUB_SBB64(temp_CF
));
142 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GqEqR(bxInstruction_c
*i
)
144 bx_bool temp_CF
= getB_CF();
146 Bit64u op1_64
, op2_64
, diff_64
;
148 op1_64
= BX_READ_64BIT_REG(i
->nnn());
149 op2_64
= BX_READ_64BIT_REG(i
->rm());
150 diff_64
= op1_64
- (op2_64
+ temp_CF
);
152 /* now write diff back to destination */
153 BX_WRITE_64BIT_REG(i
->nnn(), diff_64
);
155 SET_FLAGS_OSZAPC_64(op1_64
, op2_64
, diff_64
, BX_LF_INSTR_SUB_SBB64(temp_CF
));
158 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_RAXId(bxInstruction_c
*i
)
160 bx_bool temp_CF
= getB_CF();
162 Bit64u op1_64
, op2_64
, diff_64
;
165 op2_64
= (Bit32s
) i
->Id();
166 diff_64
= op1_64
- (op2_64
+ temp_CF
);
168 /* now write diff back to destination */
171 SET_FLAGS_OSZAPC_64(op1_64
, op2_64
, diff_64
, BX_LF_INSTR_SUB_SBB64(temp_CF
));
174 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EqIdM(bxInstruction_c
*i
)
176 bx_bool temp_CF
= getB_CF();
178 Bit64u op1_64
, op2_64
, diff_64
;
180 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
182 /* pointer, segment address pair */
183 op1_64
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
184 op2_64
= (Bit32s
) i
->Id();
185 diff_64
= op1_64
- (op2_64
+ temp_CF
);
186 write_RMW_virtual_qword(diff_64
);
188 SET_FLAGS_OSZAPC_64(op1_64
, op2_64
, diff_64
, BX_LF_INSTR_SUB_SBB64(temp_CF
));
191 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EqIdR(bxInstruction_c
*i
)
193 bx_bool temp_CF
= getB_CF();
195 Bit64u op1_64
, op2_64
, diff_64
;
197 op1_64
= BX_READ_64BIT_REG(i
->rm());
198 op2_64
= (Bit32s
) i
->Id();
199 diff_64
= op1_64
- (op2_64
+ temp_CF
);
200 BX_WRITE_64BIT_REG(i
->rm(), diff_64
);
202 SET_FLAGS_OSZAPC_64(op1_64
, op2_64
, diff_64
, BX_LF_INSTR_SUB_SBB64(temp_CF
));
205 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EqGqM(bxInstruction_c
*i
)
207 Bit64u op1_64
, op2_64
, diff_64
;
209 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
211 /* pointer, segment address pair */
212 op1_64
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
213 op2_64
= BX_READ_64BIT_REG(i
->nnn());
214 diff_64
= op1_64
- op2_64
;
215 write_RMW_virtual_qword(diff_64
);
217 SET_FLAGS_OSZAPC_SUB_64(op1_64
, op2_64
, diff_64
);
220 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GqEqR(bxInstruction_c
*i
)
222 Bit64u op1_64
, op2_64
, diff_64
;
224 op1_64
= BX_READ_64BIT_REG(i
->nnn());
225 op2_64
= BX_READ_64BIT_REG(i
->rm());
226 diff_64
= op1_64
- op2_64
;
228 /* now write diff back to destination */
229 BX_WRITE_64BIT_REG(i
->nnn(), diff_64
);
231 SET_FLAGS_OSZAPC_SUB_64(op1_64
, op2_64
, diff_64
);
234 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_RAXId(bxInstruction_c
*i
)
236 Bit64u op1_64
, op2_64
, diff_64
;
239 op2_64
= (Bit32s
) i
->Id();
240 diff_64
= op1_64
- op2_64
;
242 /* now write diff back to destination */
245 SET_FLAGS_OSZAPC_SUB_64(op1_64
, op2_64
, diff_64
);
248 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EqGqM(bxInstruction_c
*i
)
250 Bit64u op1_64
, op2_64
, diff_64
;
252 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
254 op1_64
= read_virtual_qword_64(i
->seg(), eaddr
);
255 op2_64
= BX_READ_64BIT_REG(i
->nnn());
256 diff_64
= op1_64
- op2_64
;
258 SET_FLAGS_OSZAPC_SUB_64(op1_64
, op2_64
, diff_64
);
261 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GqEqR(bxInstruction_c
*i
)
263 Bit64u op1_64
, op2_64
, diff_64
;
265 op1_64
= BX_READ_64BIT_REG(i
->nnn());
266 op2_64
= BX_READ_64BIT_REG(i
->rm());
267 diff_64
= op1_64
- op2_64
;
269 SET_FLAGS_OSZAPC_SUB_64(op1_64
, op2_64
, diff_64
);
272 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_RAXId(bxInstruction_c
*i
)
274 Bit64u op1_64
, op2_64
, diff_64
;
277 op2_64
= (Bit32s
) i
->Id();
278 diff_64
= op1_64
- op2_64
;
280 SET_FLAGS_OSZAPC_SUB_64(op1_64
, op2_64
, diff_64
);
283 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CDQE(bxInstruction_c
*i
)
285 /* CWDE: no flags are affected */
289 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CQO(bxInstruction_c
*i
)
291 /* CQO: no flags are affected */
293 if (RAX
& BX_CONST64(0x8000000000000000))
294 RDX
= BX_CONST64(0xffffffffffffffff);
299 void BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EqGqM(bxInstruction_c
*i
)
301 Bit64u op1_64
, op2_64
, sum_64
;
303 /* XADD dst(r/m), src(r)
304 * temp <-- src + dst | sum = op2 + op1
305 * src <-- dst | op2 = op1
306 * dst <-- tmp | op1 = sum
309 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
311 /* pointer, segment address pair */
312 op1_64
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
313 op2_64
= BX_READ_64BIT_REG(i
->nnn());
314 sum_64
= op1_64
+ op2_64
;
315 write_RMW_virtual_qword(sum_64
);
317 /* and write destination into source */
318 BX_WRITE_64BIT_REG(i
->nnn(), op1_64
);
320 SET_FLAGS_OSZAPC_ADD_64(op1_64
, op2_64
, sum_64
);
323 void BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EqGqR(bxInstruction_c
*i
)
325 Bit64u op1_64
, op2_64
, sum_64
;
327 /* XADD dst(r/m), src(r)
328 * temp <-- src + dst | sum = op2 + op1
329 * src <-- dst | op2 = op1
330 * dst <-- tmp | op1 = sum
333 op1_64
= BX_READ_64BIT_REG(i
->rm());
334 op2_64
= BX_READ_64BIT_REG(i
->nnn());
335 sum_64
= op1_64
+ op2_64
;
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_64BIT_REG(i
->nnn(), op1_64
);
342 BX_WRITE_64BIT_REG(i
->rm(), sum_64
);
344 SET_FLAGS_OSZAPC_ADD_64(op1_64
, op2_64
, sum_64
);
347 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EqIdM(bxInstruction_c
*i
)
349 Bit64u op1_64
, op2_64
, sum_64
;
351 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
353 /* pointer, segment address pair */
354 op1_64
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
355 op2_64
= (Bit32s
) i
->Id();
356 sum_64
= op1_64
+ op2_64
;
357 write_RMW_virtual_qword(sum_64
);
359 SET_FLAGS_OSZAPC_ADD_64(op1_64
, op2_64
, sum_64
);
362 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EqIdR(bxInstruction_c
*i
)
364 Bit64u op1_64
, op2_64
, sum_64
;
366 op1_64
= BX_READ_64BIT_REG(i
->rm());
367 op2_64
= (Bit32s
) i
->Id();
368 sum_64
= op1_64
+ op2_64
;
369 BX_WRITE_64BIT_REG(i
->rm(), sum_64
);
371 SET_FLAGS_OSZAPC_ADD_64(op1_64
, op2_64
, sum_64
);
374 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EqIdM(bxInstruction_c
*i
)
376 bx_bool temp_CF
= getB_CF();
378 Bit64u op1_64
, op2_64
, sum_64
;
380 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
382 /* pointer, segment address pair */
383 op1_64
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
384 op2_64
= (Bit32s
) i
->Id();
385 sum_64
= op1_64
+ op2_64
+ temp_CF
;
386 write_RMW_virtual_qword(sum_64
);
388 SET_FLAGS_OSZAPC_64(op1_64
, op2_64
, sum_64
, BX_LF_INSTR_ADD_ADC64(temp_CF
));
391 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EqIdR(bxInstruction_c
*i
)
393 bx_bool temp_CF
= getB_CF();
395 Bit64u op1_64
, op2_64
, sum_64
;
397 op1_64
= BX_READ_64BIT_REG(i
->rm());
398 op2_64
= (Bit32s
) i
->Id();
399 sum_64
= op1_64
+ op2_64
+ temp_CF
;
400 BX_WRITE_64BIT_REG(i
->rm(), sum_64
);
402 SET_FLAGS_OSZAPC_64(op1_64
, op2_64
, sum_64
, BX_LF_INSTR_ADD_ADC64(temp_CF
));
405 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EqIdM(bxInstruction_c
*i
)
407 Bit64u op1_64
, op2_64
, diff_64
;
409 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
411 /* pointer, segment address pair */
412 op1_64
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
413 op2_64
= (Bit32s
) i
->Id();
414 diff_64
= op1_64
- op2_64
;
415 write_RMW_virtual_qword(diff_64
);
417 SET_FLAGS_OSZAPC_SUB_64(op1_64
, op2_64
, diff_64
);
420 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EqIdR(bxInstruction_c
*i
)
422 Bit64u op1_64
, op2_64
, diff_64
;
424 op1_64
= BX_READ_64BIT_REG(i
->rm());
425 op2_64
= (Bit32s
) i
->Id();
426 diff_64
= op1_64
- op2_64
;
427 BX_WRITE_64BIT_REG(i
->rm(), diff_64
);
429 SET_FLAGS_OSZAPC_SUB_64(op1_64
, op2_64
, diff_64
);
432 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EqIdM(bxInstruction_c
*i
)
434 Bit64u op1_64
, op2_64
, diff_64
;
436 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
438 op1_64
= read_virtual_qword_64(i
->seg(), eaddr
);
439 op2_64
= (Bit32s
) i
->Id();
440 diff_64
= op1_64
- op2_64
;
442 SET_FLAGS_OSZAPC_SUB_64(op1_64
, op2_64
, diff_64
);
445 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EqIdR(bxInstruction_c
*i
)
447 Bit64u op1_64
, op2_64
, diff_64
;
449 op1_64
= BX_READ_64BIT_REG(i
->rm());
450 op2_64
= (Bit32s
) i
->Id();
451 diff_64
= op1_64
- op2_64
;
453 SET_FLAGS_OSZAPC_SUB_64(op1_64
, op2_64
, diff_64
);
456 void BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EqM(bxInstruction_c
*i
)
460 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
462 /* pointer, segment address pair */
463 op1_64
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
464 op1_64
= - (Bit64s
)(op1_64
);
465 write_RMW_virtual_qword(op1_64
);
467 SET_FLAGS_OSZAPC_RESULT_64(op1_64
, BX_LF_INSTR_NEG64
);
470 void BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EqR(bxInstruction_c
*i
)
472 Bit64u op1_64
= BX_READ_64BIT_REG(i
->rm());
473 op1_64
= - (Bit64s
)(op1_64
);
474 BX_WRITE_64BIT_REG(i
->rm(), op1_64
);
476 SET_FLAGS_OSZAPC_RESULT_64(op1_64
, BX_LF_INSTR_NEG64
);
479 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_EqM(bxInstruction_c
*i
)
483 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
485 /* pointer, segment address pair */
486 op1_64
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
488 write_RMW_virtual_qword(op1_64
);
490 SET_FLAGS_OSZAPC_INC_64(op1_64
);
493 void BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_EqR(bxInstruction_c
*i
)
495 Bit64u rrx
= ++BX_READ_64BIT_REG(i
->rm());
496 SET_FLAGS_OSZAPC_INC_64(rrx
);
499 void BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_EqM(bxInstruction_c
*i
)
503 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
505 /* pointer, segment address pair */
506 op1_64
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
508 write_RMW_virtual_qword(op1_64
);
510 SET_FLAGS_OSZAPC_DEC_64(op1_64
);
513 void BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_EqR(bxInstruction_c
*i
)
515 Bit64u rrx
= --BX_READ_64BIT_REG(i
->rm());
516 SET_FLAGS_OSZAPC_INC_64(rrx
);
519 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EqGqM(bxInstruction_c
*i
)
521 Bit64u op1_64
, op2_64
, diff_64
;
523 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
525 /* pointer, segment address pair */
526 op1_64
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
527 diff_64
= RAX
- op1_64
;
528 SET_FLAGS_OSZAPC_SUB_64(RAX
, op1_64
, diff_64
);
530 if (diff_64
== 0) { // if accumulator == dest
532 op2_64
= BX_READ_64BIT_REG(i
->nnn());
533 write_RMW_virtual_qword(op2_64
);
536 // accumulator <-- dest
541 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EqGqR(bxInstruction_c
*i
)
543 Bit64u op1_64
, op2_64
, diff_64
;
545 op1_64
= BX_READ_64BIT_REG(i
->rm());
546 diff_64
= RAX
- op1_64
;
547 SET_FLAGS_OSZAPC_SUB_64(RAX
, op1_64
, diff_64
);
549 if (diff_64
== 0) { // if accumulator == dest
551 op2_64
= BX_READ_64BIT_REG(i
->nnn());
552 BX_WRITE_64BIT_REG(i
->rm(), op2_64
);
555 // accumulator <-- dest
560 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG16B(bxInstruction_c
*i
)
562 Bit64u op1_64_lo
, op1_64_hi
, diff
;
564 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
566 bx_address laddr
= get_laddr64(i
->seg(), eaddr
);
569 BX_ERROR(("CMPXCHG16B: not aligned memory location (#GP)"));
570 exception(BX_GP_EXCEPTION
, 0, 0);
573 // check write permission for following write
574 op1_64_lo
= read_RMW_virtual_qword_64(i
->seg(), eaddr
);
575 op1_64_hi
= read_RMW_virtual_qword_64(i
->seg(), eaddr
+ 8);
577 diff
= RAX
- op1_64_lo
;
578 diff
|= RDX
- op1_64_hi
;
580 if (diff
== 0) { // if accumulator == dest
581 // dest <-- src (RCX:RBX)
582 write_RMW_virtual_qword(RCX
);
583 // write permissions already checked by read_RMW_virtual_qword_64
584 write_virtual_qword_64(i
->seg(), eaddr
, RBX
);
589 // accumulator <-- dest
595 #endif /* if BX_SUPPORT_X86_64 */