VirtualBox

source: vbox/trunk/src/recompiler/target-i386/ops_template.h@ 13832

Last change on this file since 13832 was 11982, checked in by vboxsync, 16 years ago

All: license header changes for 2.0 (OSE headers, add Sun GPL/LGPL disclaimer)

  • Property svn:eol-style set to native
File size: 13.5 KB
Line 
1/*
2 * i386 micro operations (included several times to generate
3 * different operand sizes)
4 *
5 * Copyright (c) 2003 Fabrice Bellard
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22/*
23 * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
24 * other than GPL or LGPL is available it will apply instead, Sun elects to use only
25 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
26 * a choice of LGPL license versions is made available with the language indicating
27 * that LGPLv2 or any later version may be used, or where a choice of which version
28 * of the LGPL is applied is otherwise unspecified.
29 */
30#define DATA_BITS (1 << (3 + SHIFT))
31#define SHIFT_MASK (DATA_BITS - 1)
32#define SIGN_MASK (((target_ulong)1) << (DATA_BITS - 1))
33#if DATA_BITS <= 32
34#define SHIFT1_MASK 0x1f
35#else
36#define SHIFT1_MASK 0x3f
37#endif
38
39#if DATA_BITS == 8
40#define SUFFIX b
41#define DATA_TYPE uint8_t
42#define DATA_STYPE int8_t
43#define DATA_MASK 0xff
44#elif DATA_BITS == 16
45#define SUFFIX w
46#define DATA_TYPE uint16_t
47#define DATA_STYPE int16_t
48#define DATA_MASK 0xffff
49#elif DATA_BITS == 32
50#define SUFFIX l
51#define DATA_TYPE uint32_t
52#define DATA_STYPE int32_t
53#define DATA_MASK 0xffffffff
54#elif DATA_BITS == 64
55#define SUFFIX q
56#define DATA_TYPE uint64_t
57#define DATA_STYPE int64_t
58#define DATA_MASK 0xffffffffffffffffULL
59#else
60#error unhandled operand size
61#endif
62
63/* dynamic flags computation */
64
65static int glue(compute_all_add, SUFFIX)(void)
66{
67 int cf, pf, af, zf, sf, of;
68 target_long src1, src2;
69 src1 = CC_SRC;
70 src2 = CC_DST - CC_SRC;
71 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
72 pf = parity_table[(uint8_t)CC_DST];
73 af = (CC_DST ^ src1 ^ src2) & 0x10;
74 zf = ((DATA_TYPE)CC_DST == 0) << 6;
75 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
76 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
77 return cf | pf | af | zf | sf | of;
78}
79
80static int glue(compute_c_add, SUFFIX)(void)
81{
82 int cf;
83 target_long src1;
84 src1 = CC_SRC;
85 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
86 return cf;
87}
88
89static int glue(compute_all_adc, SUFFIX)(void)
90{
91 int cf, pf, af, zf, sf, of;
92 target_long src1, src2;
93 src1 = CC_SRC;
94 src2 = CC_DST - CC_SRC - 1;
95 cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
96 pf = parity_table[(uint8_t)CC_DST];
97 af = (CC_DST ^ src1 ^ src2) & 0x10;
98 zf = ((DATA_TYPE)CC_DST == 0) << 6;
99 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
100 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
101 return cf | pf | af | zf | sf | of;
102}
103
104static int glue(compute_c_adc, SUFFIX)(void)
105{
106 int cf;
107 target_long src1;
108 src1 = CC_SRC;
109 cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
110 return cf;
111}
112
113static int glue(compute_all_sub, SUFFIX)(void)
114{
115 int cf, pf, af, zf, sf, of;
116 target_long src1, src2;
117 src1 = CC_DST + CC_SRC;
118 src2 = CC_SRC;
119 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
120 pf = parity_table[(uint8_t)CC_DST];
121 af = (CC_DST ^ src1 ^ src2) & 0x10;
122 zf = ((DATA_TYPE)CC_DST == 0) << 6;
123 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
124 of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
125 return cf | pf | af | zf | sf | of;
126}
127
128static int glue(compute_c_sub, SUFFIX)(void)
129{
130 int cf;
131 target_long src1, src2;
132 src1 = CC_DST + CC_SRC;
133 src2 = CC_SRC;
134 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
135 return cf;
136}
137
138static int glue(compute_all_sbb, SUFFIX)(void)
139{
140 int cf, pf, af, zf, sf, of;
141 target_long src1, src2;
142 src1 = CC_DST + CC_SRC + 1;
143 src2 = CC_SRC;
144 cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
145 pf = parity_table[(uint8_t)CC_DST];
146 af = (CC_DST ^ src1 ^ src2) & 0x10;
147 zf = ((DATA_TYPE)CC_DST == 0) << 6;
148 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
149 of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
150 return cf | pf | af | zf | sf | of;
151}
152
153static int glue(compute_c_sbb, SUFFIX)(void)
154{
155 int cf;
156 target_long src1, src2;
157 src1 = CC_DST + CC_SRC + 1;
158 src2 = CC_SRC;
159 cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
160 return cf;
161}
162
163static int glue(compute_all_logic, SUFFIX)(void)
164{
165 int cf, pf, af, zf, sf, of;
166 cf = 0;
167 pf = parity_table[(uint8_t)CC_DST];
168 af = 0;
169 zf = ((DATA_TYPE)CC_DST == 0) << 6;
170 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
171 of = 0;
172 return cf | pf | af | zf | sf | of;
173}
174
175static int glue(compute_c_logic, SUFFIX)(void)
176{
177 return 0;
178}
179
180static int glue(compute_all_inc, SUFFIX)(void)
181{
182 int cf, pf, af, zf, sf, of;
183 target_long src1, src2;
184 src1 = CC_DST - 1;
185 src2 = 1;
186 cf = CC_SRC;
187 pf = parity_table[(uint8_t)CC_DST];
188 af = (CC_DST ^ src1 ^ src2) & 0x10;
189 zf = ((DATA_TYPE)CC_DST == 0) << 6;
190 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
191 of = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;
192 return cf | pf | af | zf | sf | of;
193}
194
195#if DATA_BITS == 32
196static int glue(compute_c_inc, SUFFIX)(void)
197{
198 return CC_SRC;
199}
200#endif
201
202static int glue(compute_all_dec, SUFFIX)(void)
203{
204 int cf, pf, af, zf, sf, of;
205 target_long src1, src2;
206 src1 = CC_DST + 1;
207 src2 = 1;
208 cf = CC_SRC;
209 pf = parity_table[(uint8_t)CC_DST];
210 af = (CC_DST ^ src1 ^ src2) & 0x10;
211 zf = ((DATA_TYPE)CC_DST == 0) << 6;
212 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
213 of = ((CC_DST & DATA_MASK) == ((target_ulong)SIGN_MASK - 1)) << 11;
214 return cf | pf | af | zf | sf | of;
215}
216
217static int glue(compute_all_shl, SUFFIX)(void)
218{
219 int cf, pf, af, zf, sf, of;
220 cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C;
221 pf = parity_table[(uint8_t)CC_DST];
222 af = 0; /* undefined */
223 zf = ((DATA_TYPE)CC_DST == 0) << 6;
224 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
225 /* of is defined if shift count == 1 */
226 of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
227 return cf | pf | af | zf | sf | of;
228}
229
230static int glue(compute_c_shl, SUFFIX)(void)
231{
232 return (CC_SRC >> (DATA_BITS - 1)) & CC_C;
233}
234
235#if DATA_BITS == 32
236static int glue(compute_c_sar, SUFFIX)(void)
237{
238 return CC_SRC & 1;
239}
240#endif
241
242static int glue(compute_all_sar, SUFFIX)(void)
243{
244 int cf, pf, af, zf, sf, of;
245 cf = CC_SRC & 1;
246 pf = parity_table[(uint8_t)CC_DST];
247 af = 0; /* undefined */
248 zf = ((DATA_TYPE)CC_DST == 0) << 6;
249 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
250 /* of is defined if shift count == 1 */
251 of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
252 return cf | pf | af | zf | sf | of;
253}
254
255#if DATA_BITS == 32
256static int glue(compute_c_mul, SUFFIX)(void)
257{
258 int cf;
259 cf = (CC_SRC != 0);
260 return cf;
261}
262#endif
263
264/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
265 CF are modified and it is slower to do that. */
266static int glue(compute_all_mul, SUFFIX)(void)
267{
268 int cf, pf, af, zf, sf, of;
269 cf = (CC_SRC != 0);
270 pf = parity_table[(uint8_t)CC_DST];
271 af = 0; /* undefined */
272 zf = ((DATA_TYPE)CC_DST == 0) << 6;
273 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
274 of = cf << 11;
275 return cf | pf | af | zf | sf | of;
276}
277
278/* various optimized jumps cases */
279
280void OPPROTO glue(op_jb_sub, SUFFIX)(void)
281{
282 target_long src1, src2;
283 src1 = CC_DST + CC_SRC;
284 src2 = CC_SRC;
285
286 if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
287 GOTO_LABEL_PARAM(1);
288 FORCE_RET();
289}
290
291void OPPROTO glue(op_jz_sub, SUFFIX)(void)
292{
293 if ((DATA_TYPE)CC_DST == 0)
294 GOTO_LABEL_PARAM(1);
295 FORCE_RET();
296}
297
298void OPPROTO glue(op_jnz_sub, SUFFIX)(void)
299{
300 if ((DATA_TYPE)CC_DST != 0)
301 GOTO_LABEL_PARAM(1);
302 FORCE_RET();
303}
304
305void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
306{
307 target_long src1, src2;
308 src1 = CC_DST + CC_SRC;
309 src2 = CC_SRC;
310
311 if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
312 GOTO_LABEL_PARAM(1);
313 FORCE_RET();
314}
315
316void OPPROTO glue(op_js_sub, SUFFIX)(void)
317{
318 if (CC_DST & SIGN_MASK)
319 GOTO_LABEL_PARAM(1);
320 FORCE_RET();
321}
322
323void OPPROTO glue(op_jl_sub, SUFFIX)(void)
324{
325 target_long src1, src2;
326 src1 = CC_DST + CC_SRC;
327 src2 = CC_SRC;
328
329 if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
330 GOTO_LABEL_PARAM(1);
331 FORCE_RET();
332}
333
334void OPPROTO glue(op_jle_sub, SUFFIX)(void)
335{
336 target_long src1, src2;
337 src1 = CC_DST + CC_SRC;
338 src2 = CC_SRC;
339
340 if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
341 GOTO_LABEL_PARAM(1);
342 FORCE_RET();
343}
344
345/* oldies */
346
347#if DATA_BITS >= 16
348
349void OPPROTO glue(op_loopnz, SUFFIX)(void)
350{
351 if ((DATA_TYPE)ECX != 0 && !(T0 & CC_Z))
352 GOTO_LABEL_PARAM(1);
353 FORCE_RET();
354}
355
356void OPPROTO glue(op_loopz, SUFFIX)(void)
357{
358 if ((DATA_TYPE)ECX != 0 && (T0 & CC_Z))
359 GOTO_LABEL_PARAM(1);
360 FORCE_RET();
361}
362
363void OPPROTO glue(op_jz_ecx, SUFFIX)(void)
364{
365 if ((DATA_TYPE)ECX == 0)
366 GOTO_LABEL_PARAM(1);
367 FORCE_RET();
368}
369
370void OPPROTO glue(op_jnz_ecx, SUFFIX)(void)
371{
372 if ((DATA_TYPE)ECX != 0)
373 GOTO_LABEL_PARAM(1);
374 FORCE_RET();
375}
376
377#endif
378
379/* various optimized set cases */
380
381void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
382{
383 target_long src1, src2;
384 src1 = CC_DST + CC_SRC;
385 src2 = CC_SRC;
386
387 T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
388}
389
390void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
391{
392 T0 = ((DATA_TYPE)CC_DST == 0);
393}
394
395void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
396{
397 target_long src1, src2;
398 src1 = CC_DST + CC_SRC;
399 src2 = CC_SRC;
400
401 T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
402}
403
404void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
405{
406 T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
407}
408
409void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
410{
411 target_long src1, src2;
412 src1 = CC_DST + CC_SRC;
413 src2 = CC_SRC;
414
415 T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
416}
417
418void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
419{
420 target_long src1, src2;
421 src1 = CC_DST + CC_SRC;
422 src2 = CC_SRC;
423
424 T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
425}
426
427/* shifts */
428
429void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1)(void)
430{
431 int count;
432 count = T1 & SHIFT1_MASK;
433 T0 = T0 << count;
434 FORCE_RET();
435}
436
437void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1)(void)
438{
439 int count;
440 count = T1 & SHIFT1_MASK;
441 T0 &= DATA_MASK;
442 T0 = T0 >> count;
443 FORCE_RET();
444}
445
446void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1)(void)
447{
448 int count;
449 target_long src;
450
451 count = T1 & SHIFT1_MASK;
452 src = (DATA_STYPE)T0;
453 T0 = src >> count;
454 FORCE_RET();
455}
456
457#undef MEM_WRITE
458#include "ops_template_mem.h"
459
460#define MEM_WRITE 0
461#include "ops_template_mem.h"
462
463#if !defined(CONFIG_USER_ONLY)
464#define MEM_WRITE 1
465#include "ops_template_mem.h"
466
467#define MEM_WRITE 2
468#include "ops_template_mem.h"
469#endif
470
471/* bit operations */
472#if DATA_BITS >= 16
473
474void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
475{
476 int count;
477 count = T1 & SHIFT_MASK;
478 CC_SRC = T0 >> count;
479}
480
481void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
482{
483 int count;
484 count = T1 & SHIFT_MASK;
485 T1 = T0 >> count;
486 T0 |= (((target_long)1) << count);
487}
488
489void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
490{
491 int count;
492 count = T1 & SHIFT_MASK;
493 T1 = T0 >> count;
494 T0 &= ~(((target_long)1) << count);
495}
496
497void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
498{
499 int count;
500 count = T1 & SHIFT_MASK;
501 T1 = T0 >> count;
502 T0 ^= (((target_long)1) << count);
503}
504
505void OPPROTO glue(glue(op_add_bit, SUFFIX), _A0_T1)(void)
506{
507 A0 += ((DATA_STYPE)T1 >> (3 + SHIFT)) << SHIFT;
508}
509
510void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
511{
512 int count;
513 target_long res;
514
515 res = T0 & DATA_MASK;
516 if (res != 0) {
517 count = 0;
518 while ((res & 1) == 0) {
519 count++;
520 res >>= 1;
521 }
522 T1 = count;
523 CC_DST = 1; /* ZF = 0 */
524 } else {
525 CC_DST = 0; /* ZF = 1 */
526 }
527 FORCE_RET();
528}
529
530void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
531{
532 int count;
533 target_long res;
534
535 res = T0 & DATA_MASK;
536 if (res != 0) {
537 count = DATA_BITS - 1;
538 while ((res & SIGN_MASK) == 0) {
539 count--;
540 res <<= 1;
541 }
542 T1 = count;
543 CC_DST = 1; /* ZF = 0 */
544 } else {
545 CC_DST = 0; /* ZF = 1 */
546 }
547 FORCE_RET();
548}
549
550#endif
551
552#if DATA_BITS == 32
553void OPPROTO op_update_bt_cc(void)
554{
555 CC_SRC = T1;
556}
557#endif
558
559/* string operations */
560
561void OPPROTO glue(op_movl_T0_Dshift, SUFFIX)(void)
562{
563 T0 = DF << SHIFT;
564}
565
566/* port I/O */
567#if DATA_BITS <= 32
568void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
569{
570 glue(cpu_out, SUFFIX)(env, T0, T1 & DATA_MASK);
571}
572
573void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
574{
575 T1 = glue(cpu_in, SUFFIX)(env, T0);
576}
577
578void OPPROTO glue(glue(op_in, SUFFIX), _DX_T0)(void)
579{
580 T0 = glue(cpu_in, SUFFIX)(env, EDX & 0xffff);
581}
582
583void OPPROTO glue(glue(op_out, SUFFIX), _DX_T0)(void)
584{
585 glue(cpu_out, SUFFIX)(env, EDX & 0xffff, T0);
586}
587
588void OPPROTO glue(glue(op_check_io, SUFFIX), _T0)(void)
589{
590 glue(glue(check_io, SUFFIX), _T0)();
591}
592
593void OPPROTO glue(glue(op_check_io, SUFFIX), _DX)(void)
594{
595 glue(glue(check_io, SUFFIX), _DX)();
596}
597#endif
598
599#undef DATA_BITS
600#undef SHIFT_MASK
601#undef SHIFT1_MASK
602#undef SIGN_MASK
603#undef DATA_TYPE
604#undef DATA_STYPE
605#undef DATA_MASK
606#undef SUFFIX
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette