VirtualBox

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

Last change on this file since 34585 was 33656, checked in by vboxsync, 14 years ago

*: rebrand Sun (L)GPL disclaimers

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