]> git.proxmox.com Git - qemu.git/blob - ops_template.h
added loop/xadd/cmpxchg support
[qemu.git] / ops_template.h
1
2 #define DATA_BITS (1 << (3 + SHIFT))
3 #define SHIFT_MASK (DATA_BITS - 1)
4 #define SIGN_MASK (1 << (DATA_BITS - 1))
5
6 #if DATA_BITS == 8
7 #define SUFFIX b
8 #define DATA_TYPE uint8_t
9 #define DATA_STYPE int8_t
10 #define DATA_MASK 0xff
11 #elif DATA_BITS == 16
12 #define SUFFIX w
13 #define DATA_TYPE uint16_t
14 #define DATA_STYPE int16_t
15 #define DATA_MASK 0xffff
16 #elif DATA_BITS == 32
17 #define SUFFIX l
18 #define DATA_TYPE uint32_t
19 #define DATA_STYPE int32_t
20 #define DATA_MASK 0xffffffff
21 #else
22 #error unhandled operand size
23 #endif
24
25 /* dynamic flags computation */
26
27 static int glue(compute_all_add, SUFFIX)(void)
28 {
29 int cf, pf, af, zf, sf, of;
30 int src1, src2;
31 src1 = CC_SRC;
32 src2 = CC_DST - CC_SRC;
33 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
34 pf = parity_table[(uint8_t)CC_DST];
35 af = (CC_DST ^ src1 ^ src2) & 0x10;
36 zf = ((DATA_TYPE)CC_DST == 0) << 6;
37 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
38 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
39 return cf | pf | af | zf | sf | of;
40 }
41
42 static int glue(compute_c_add, SUFFIX)(void)
43 {
44 int src1, cf;
45 src1 = CC_SRC;
46 cf = (DATA_TYPE)CC_DST < (DATA_TYPE)src1;
47 return cf;
48 }
49
50 static int glue(compute_all_adc, SUFFIX)(void)
51 {
52 int cf, pf, af, zf, sf, of;
53 int src1, src2;
54 src1 = CC_SRC;
55 src2 = CC_DST - CC_SRC - 1;
56 cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
57 pf = parity_table[(uint8_t)CC_DST];
58 af = (CC_DST ^ src1 ^ src2) & 0x10;
59 zf = ((DATA_TYPE)CC_DST == 0) << 6;
60 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
61 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
62 return cf | pf | af | zf | sf | of;
63 }
64
65 static int glue(compute_c_adc, SUFFIX)(void)
66 {
67 int src1, cf;
68 src1 = CC_SRC;
69 cf = (DATA_TYPE)CC_DST <= (DATA_TYPE)src1;
70 return cf;
71 }
72
73 static int glue(compute_all_sub, SUFFIX)(void)
74 {
75 int cf, pf, af, zf, sf, of;
76 int src1, src2;
77 src1 = CC_SRC;
78 src2 = CC_SRC - CC_DST;
79 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
80 pf = parity_table[(uint8_t)CC_DST];
81 af = (CC_DST ^ src1 ^ src2) & 0x10;
82 zf = ((DATA_TYPE)CC_DST == 0) << 6;
83 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
84 of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
85 return cf | pf | af | zf | sf | of;
86 }
87
88 static int glue(compute_c_sub, SUFFIX)(void)
89 {
90 int src1, src2, cf;
91 src1 = CC_SRC;
92 src2 = CC_SRC - CC_DST;
93 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
94 return cf;
95 }
96
97 static int glue(compute_all_sbb, SUFFIX)(void)
98 {
99 int cf, pf, af, zf, sf, of;
100 int src1, src2;
101 src1 = CC_SRC;
102 src2 = CC_SRC - CC_DST - 1;
103 cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
104 pf = parity_table[(uint8_t)CC_DST];
105 af = (CC_DST ^ src1 ^ src2) & 0x10;
106 zf = ((DATA_TYPE)CC_DST == 0) << 6;
107 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
108 of = lshift((src1 ^ src2) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
109 return cf | pf | af | zf | sf | of;
110 }
111
112 static int glue(compute_c_sbb, SUFFIX)(void)
113 {
114 int src1, src2, cf;
115 src1 = CC_SRC;
116 src2 = CC_SRC - CC_DST - 1;
117 cf = (DATA_TYPE)src1 <= (DATA_TYPE)src2;
118 return cf;
119 }
120
121 static int glue(compute_all_logic, SUFFIX)(void)
122 {
123 int cf, pf, af, zf, sf, of;
124 cf = 0;
125 pf = parity_table[(uint8_t)CC_DST];
126 af = 0;
127 zf = ((DATA_TYPE)CC_DST == 0) << 6;
128 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
129 of = 0;
130 return cf | pf | af | zf | sf | of;
131 }
132
133 static int glue(compute_c_logic, SUFFIX)(void)
134 {
135 return 0;
136 }
137
138 static int glue(compute_all_inc, SUFFIX)(void)
139 {
140 int cf, pf, af, zf, sf, of;
141 int src1, src2;
142 src1 = CC_DST - 1;
143 src2 = 1;
144 cf = CC_SRC;
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 = ((CC_DST & DATA_MASK) == SIGN_MASK) << 11;
150 return cf | pf | af | zf | sf | of;
151 }
152
153 #if DATA_BITS == 32
154 static int glue(compute_c_inc, SUFFIX)(void)
155 {
156 return CC_SRC;
157 }
158 #endif
159
160 static int glue(compute_all_dec, SUFFIX)(void)
161 {
162 int cf, pf, af, zf, sf, of;
163 int src1, src2;
164 src1 = CC_DST + 1;
165 src2 = 1;
166 cf = CC_SRC;
167 pf = parity_table[(uint8_t)CC_DST];
168 af = (CC_DST ^ src1 ^ src2) & 0x10;
169 zf = ((DATA_TYPE)CC_DST == 0) << 6;
170 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
171 of = ((CC_DST & DATA_MASK) == ((uint32_t)SIGN_MASK - 1)) << 11;
172 return cf | pf | af | zf | sf | of;
173 }
174
175 static int glue(compute_all_shl, SUFFIX)(void)
176 {
177 int cf, pf, af, zf, sf, of;
178 cf = (CC_SRC >> (DATA_BITS - 1)) & CC_C;
179 pf = parity_table[(uint8_t)CC_DST];
180 af = 0; /* undefined */
181 zf = ((DATA_TYPE)CC_DST == 0) << 6;
182 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
183 /* of is defined if shift count == 1 */
184 of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
185 return cf | pf | af | zf | sf | of;
186 }
187
188 #if DATA_BITS == 32
189 static int glue(compute_c_shl, SUFFIX)(void)
190 {
191 return CC_SRC & 1;
192 }
193 #endif
194
195 static int glue(compute_all_sar, SUFFIX)(void)
196 {
197 int cf, pf, af, zf, sf, of;
198 cf = CC_SRC & 1;
199 pf = parity_table[(uint8_t)CC_DST];
200 af = 0; /* undefined */
201 zf = ((DATA_TYPE)CC_DST == 0) << 6;
202 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
203 /* of is defined if shift count == 1 */
204 of = lshift(CC_SRC ^ CC_DST, 12 - DATA_BITS) & CC_O;
205 return cf | pf | af | zf | sf | of;
206 }
207
208 /* various optimized jumps cases */
209
210 void OPPROTO glue(op_jb_sub, SUFFIX)(void)
211 {
212 int src1, src2;
213 src1 = CC_SRC;
214 src2 = CC_SRC - CC_DST;
215
216 if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
217 PC = PARAM1;
218 else
219 PC = PARAM2;
220 FORCE_RET();
221 }
222
223 void OPPROTO glue(op_jz_sub, SUFFIX)(void)
224 {
225 if ((DATA_TYPE)CC_DST == 0)
226 PC = PARAM1;
227 else
228 PC = PARAM2;
229 FORCE_RET();
230 }
231
232 void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
233 {
234 int src1, src2;
235 src1 = CC_SRC;
236 src2 = CC_SRC - CC_DST;
237
238 if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
239 PC = PARAM1;
240 else
241 PC = PARAM2;
242 FORCE_RET();
243 }
244
245 void OPPROTO glue(op_js_sub, SUFFIX)(void)
246 {
247 if (CC_DST & SIGN_MASK)
248 PC = PARAM1;
249 else
250 PC = PARAM2;
251 FORCE_RET();
252 }
253
254 void OPPROTO glue(op_jl_sub, SUFFIX)(void)
255 {
256 int src1, src2;
257 src1 = CC_SRC;
258 src2 = CC_SRC - CC_DST;
259
260 if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
261 PC = PARAM1;
262 else
263 PC = PARAM2;
264 FORCE_RET();
265 }
266
267 void OPPROTO glue(op_jle_sub, SUFFIX)(void)
268 {
269 int src1, src2;
270 src1 = CC_SRC;
271 src2 = CC_SRC - CC_DST;
272
273 if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
274 PC = PARAM1;
275 else
276 PC = PARAM2;
277 FORCE_RET();
278 }
279
280 /* oldies */
281
282 #if DATA_BITS >= 16
283
284 void OPPROTO glue(op_loopnz, SUFFIX)(void)
285 {
286 unsigned int tmp;
287 int eflags;
288 eflags = cc_table[CC_OP].compute_all();
289 tmp = (ECX - 1) & DATA_MASK;
290 ECX = (ECX & ~DATA_MASK) | tmp;
291 if (tmp != 0 && !(eflags & CC_Z))
292 PC = PARAM1;
293 else
294 PC = PARAM2;
295 FORCE_RET();
296 }
297
298 void OPPROTO glue(op_loopz, SUFFIX)(void)
299 {
300 unsigned int tmp;
301 int eflags;
302 eflags = cc_table[CC_OP].compute_all();
303 tmp = (ECX - 1) & DATA_MASK;
304 ECX = (ECX & ~DATA_MASK) | tmp;
305 if (tmp != 0 && (eflags & CC_Z))
306 PC = PARAM1;
307 else
308 PC = PARAM2;
309 FORCE_RET();
310 }
311
312 void OPPROTO glue(op_loop, SUFFIX)(void)
313 {
314 unsigned int tmp;
315 tmp = (ECX - 1) & DATA_MASK;
316 ECX = (ECX & ~DATA_MASK) | tmp;
317 if (tmp != 0)
318 PC = PARAM1;
319 else
320 PC = PARAM2;
321 FORCE_RET();
322 }
323
324 void OPPROTO glue(op_jecxz, SUFFIX)(void)
325 {
326 if ((DATA_TYPE)ECX == 0)
327 PC = PARAM1;
328 else
329 PC = PARAM2;
330 FORCE_RET();
331 }
332
333 #endif
334
335 /* various optimized set cases */
336
337 void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
338 {
339 int src1, src2;
340 src1 = CC_SRC;
341 src2 = CC_SRC - CC_DST;
342
343 T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
344 }
345
346 void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
347 {
348 T0 = ((DATA_TYPE)CC_DST == 0);
349 }
350
351 void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
352 {
353 int src1, src2;
354 src1 = CC_SRC;
355 src2 = CC_SRC - CC_DST;
356
357 T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
358 }
359
360 void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
361 {
362 T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
363 }
364
365 void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
366 {
367 int src1, src2;
368 src1 = CC_SRC;
369 src2 = CC_SRC - CC_DST;
370
371 T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
372 }
373
374 void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
375 {
376 int src1, src2;
377 src1 = CC_SRC;
378 src2 = CC_SRC - CC_DST;
379
380 T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
381 }
382
383 /* shifts */
384
385 void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
386 {
387 int count, src;
388 count = T1 & SHIFT_MASK;
389 if (count) {
390 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
391 src = T0;
392 T0 &= DATA_MASK;
393 T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
394 CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
395 (T0 & CC_C);
396 CC_OP = CC_OP_EFLAGS;
397 }
398 FORCE_RET();
399 }
400
401 void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
402 {
403 int count, src;
404 count = T1 & SHIFT_MASK;
405 if (count) {
406 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
407 src = T0;
408 T0 &= DATA_MASK;
409 T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
410 CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
411 ((T0 >> (DATA_BITS - 1)) & CC_C);
412 CC_OP = CC_OP_EFLAGS;
413 }
414 FORCE_RET();
415 }
416
417 void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
418 {
419 int count, res, eflags;
420 unsigned int src;
421
422 count = T1 & 0x1f;
423 #if DATA_BITS == 16
424 count = rclw_table[count];
425 #elif DATA_BITS == 8
426 count = rclb_table[count];
427 #endif
428 if (count) {
429 eflags = cc_table[CC_OP].compute_all();
430 T0 &= DATA_MASK;
431 src = T0;
432 res = (T0 << count) | ((eflags & CC_C) << (count - 1));
433 if (count > 1)
434 res |= T0 >> (DATA_BITS + 1 - count);
435 T0 = res;
436 CC_SRC = (eflags & ~(CC_C | CC_O)) |
437 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
438 ((src >> (DATA_BITS - count)) & CC_C);
439 CC_OP = CC_OP_EFLAGS;
440 }
441 FORCE_RET();
442 }
443
444 void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
445 {
446 int count, res, eflags;
447 unsigned int src;
448
449 count = T1 & 0x1f;
450 #if DATA_BITS == 16
451 count = rclw_table[count];
452 #elif DATA_BITS == 8
453 count = rclb_table[count];
454 #endif
455 if (count) {
456 eflags = cc_table[CC_OP].compute_all();
457 T0 &= DATA_MASK;
458 src = T0;
459 res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
460 if (count > 1)
461 res |= T0 << (DATA_BITS + 1 - count);
462 T0 = res;
463 CC_SRC = (eflags & ~(CC_C | CC_O)) |
464 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
465 ((src >> (count - 1)) & CC_C);
466 CC_OP = CC_OP_EFLAGS;
467 }
468 FORCE_RET();
469 }
470
471 void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
472 {
473 int count;
474 count = T1 & 0x1f;
475 if (count) {
476 CC_SRC = (DATA_TYPE)T0 << (count - 1);
477 T0 = T0 << count;
478 CC_DST = T0;
479 CC_OP = CC_OP_SHLB + SHIFT;
480 }
481 FORCE_RET();
482 }
483
484 void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
485 {
486 int count;
487 count = T1 & 0x1f;
488 if (count) {
489 T0 &= DATA_MASK;
490 CC_SRC = T0 >> (count - 1);
491 T0 = T0 >> count;
492 CC_DST = T0;
493 CC_OP = CC_OP_SARB + SHIFT;
494 }
495 FORCE_RET();
496 }
497
498 void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
499 {
500 int count, src;
501 count = T1 & 0x1f;
502 if (count) {
503 src = (DATA_STYPE)T0;
504 CC_SRC = src >> (count - 1);
505 T0 = src >> count;
506 CC_DST = T0;
507 CC_OP = CC_OP_SARB + SHIFT;
508 }
509 FORCE_RET();
510 }
511
512 #if DATA_BITS == 16
513 /* XXX: overflow flag might be incorrect in some cases in shldw */
514 void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
515 {
516 int count;
517 unsigned int res;
518 count = PARAM1;
519 T1 &= 0xffff;
520 res = T1 | (T0 << 16);
521 CC_SRC = res >> (32 - count);
522 res <<= count;
523 if (count > 16)
524 res |= T1 << (count - 16);
525 T0 = res >> 16;
526 CC_DST = T0;
527 }
528
529 void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
530 {
531 int count;
532 unsigned int res;
533 count = ECX & 0x1f;
534 if (count) {
535 T1 &= 0xffff;
536 res = T1 | (T0 << 16);
537 CC_SRC = res >> (32 - count);
538 res <<= count;
539 if (count > 16)
540 res |= T1 << (count - 16);
541 T0 = res >> 16;
542 CC_DST = T0;
543 CC_OP = CC_OP_SARB + SHIFT;
544 }
545 }
546
547 void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
548 {
549 int count;
550 unsigned int res;
551
552 count = PARAM1;
553 res = (T0 & 0xffff) | (T1 << 16);
554 CC_SRC = res >> (count - 1);
555 res >>= count;
556 if (count > 16)
557 res |= T1 << (32 - count);
558 T0 = res;
559 CC_DST = T0;
560 }
561
562
563 void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
564 {
565 int count;
566 unsigned int res;
567
568 count = ECX & 0x1f;
569 if (count) {
570 res = (T0 & 0xffff) | (T1 << 16);
571 CC_SRC = res >> (count - 1);
572 res >>= count;
573 if (count > 16)
574 res |= T1 << (32 - count);
575 T0 = res;
576 CC_DST = T0;
577 CC_OP = CC_OP_SARB + SHIFT;
578 }
579 }
580 #endif
581
582 #if DATA_BITS == 32
583 void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_im_cc)(void)
584 {
585 int count;
586 count = PARAM1;
587 T0 &= DATA_MASK;
588 T1 &= DATA_MASK;
589 CC_SRC = T0 << (count - 1);
590 T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
591 CC_DST = T0;
592 }
593
594 void OPPROTO glue(glue(op_shld, SUFFIX), _T0_T1_ECX_cc)(void)
595 {
596 int count;
597 count = ECX & 0x1f;
598 if (count) {
599 T0 &= DATA_MASK;
600 T1 &= DATA_MASK;
601 CC_SRC = T0 << (count - 1);
602 T0 = (T0 << count) | (T1 >> (DATA_BITS - count));
603 CC_DST = T0;
604 CC_OP = CC_OP_SHLB + SHIFT;
605 }
606 }
607
608 void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_im_cc)(void)
609 {
610 int count;
611 count = PARAM1;
612 T0 &= DATA_MASK;
613 T1 &= DATA_MASK;
614 CC_SRC = T0 >> (count - 1);
615 T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
616 CC_DST = T0;
617 }
618
619
620 void OPPROTO glue(glue(op_shrd, SUFFIX), _T0_T1_ECX_cc)(void)
621 {
622 int count;
623 count = ECX & 0x1f;
624 if (count) {
625 T0 &= DATA_MASK;
626 T1 &= DATA_MASK;
627 CC_SRC = T0 >> (count - 1);
628 T0 = (T0 >> count) | (T1 << (DATA_BITS - count));
629 CC_DST = T0;
630 CC_OP = CC_OP_SARB + SHIFT;
631 }
632 }
633 #endif
634
635 /* carry add/sub (we only need to set CC_OP differently) */
636
637 void OPPROTO glue(glue(op_adc, SUFFIX), _T0_T1_cc)(void)
638 {
639 int cf;
640 cf = cc_table[CC_OP].compute_c();
641 CC_SRC = T0;
642 T0 = T0 + T1 + cf;
643 CC_DST = T0;
644 CC_OP = CC_OP_ADDB + SHIFT + cf * 3;
645 }
646
647 void OPPROTO glue(glue(op_sbb, SUFFIX), _T0_T1_cc)(void)
648 {
649 int cf;
650 cf = cc_table[CC_OP].compute_c();
651 CC_SRC = T0;
652 T0 = T0 - T1 - cf;
653 CC_DST = T0;
654 CC_OP = CC_OP_SUBB + SHIFT + cf * 3;
655 }
656
657 void OPPROTO glue(glue(op_cmpxchg, SUFFIX), _T0_T1_EAX_cc)(void)
658 {
659 CC_SRC = EAX;
660 CC_DST = EAX - T0;
661 if ((DATA_TYPE)CC_DST == 0) {
662 T0 = T1;
663 } else {
664 EAX = (EAX & ~DATA_MASK) | (T0 & DATA_MASK);
665 }
666 FORCE_RET();
667 }
668
669 /* bit operations */
670 #if DATA_BITS >= 16
671
672 void OPPROTO glue(glue(op_bt, SUFFIX), _T0_T1_cc)(void)
673 {
674 int count;
675 count = T1 & SHIFT_MASK;
676 CC_SRC = T0 >> count;
677 }
678
679 void OPPROTO glue(glue(op_bts, SUFFIX), _T0_T1_cc)(void)
680 {
681 int count;
682 count = T1 & SHIFT_MASK;
683 CC_SRC = T0 >> count;
684 T0 |= (1 << count);
685 }
686
687 void OPPROTO glue(glue(op_btr, SUFFIX), _T0_T1_cc)(void)
688 {
689 int count;
690 count = T1 & SHIFT_MASK;
691 CC_SRC = T0 >> count;
692 T0 &= ~(1 << count);
693 }
694
695 void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
696 {
697 int count;
698 count = T1 & SHIFT_MASK;
699 CC_SRC = T0 >> count;
700 T0 ^= (1 << count);
701 }
702
703 void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
704 {
705 int res, count;
706 res = T0 & DATA_MASK;
707 if (res != 0) {
708 count = 0;
709 while ((res & 1) == 0) {
710 count++;
711 res >>= 1;
712 }
713 T0 = count;
714 CC_DST = 1; /* ZF = 1 */
715 } else {
716 CC_DST = 0; /* ZF = 1 */
717 }
718 FORCE_RET();
719 }
720
721 void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
722 {
723 int res, count;
724 res = T0 & DATA_MASK;
725 if (res != 0) {
726 count = DATA_BITS - 1;
727 while ((res & SIGN_MASK) == 0) {
728 count--;
729 res <<= 1;
730 }
731 T0 = count;
732 CC_DST = 1; /* ZF = 1 */
733 } else {
734 CC_DST = 0; /* ZF = 1 */
735 }
736 FORCE_RET();
737 }
738
739 #endif
740
741 /* string operations */
742 /* XXX: maybe use lower level instructions to ease exception handling */
743
744 void OPPROTO glue(op_movs, SUFFIX)(void)
745 {
746 int v;
747 v = glue(ldu, SUFFIX)((void *)ESI);
748 glue(st, SUFFIX)((void *)EDI, v);
749 ESI += (DF << SHIFT);
750 EDI += (DF << SHIFT);
751 }
752
753 void OPPROTO glue(op_rep_movs, SUFFIX)(void)
754 {
755 int v, inc;
756 inc = (DF << SHIFT);
757 while (ECX != 0) {
758 v = glue(ldu, SUFFIX)((void *)ESI);
759 glue(st, SUFFIX)((void *)EDI, v);
760 ESI += inc;
761 EDI += inc;
762 ECX--;
763 }
764 }
765
766 void OPPROTO glue(op_stos, SUFFIX)(void)
767 {
768 glue(st, SUFFIX)((void *)EDI, EAX);
769 EDI += (DF << SHIFT);
770 }
771
772 void OPPROTO glue(op_rep_stos, SUFFIX)(void)
773 {
774 int inc;
775 inc = (DF << SHIFT);
776 while (ECX != 0) {
777 glue(st, SUFFIX)((void *)EDI, EAX);
778 EDI += inc;
779 ECX--;
780 }
781 }
782
783 void OPPROTO glue(op_lods, SUFFIX)(void)
784 {
785 int v;
786 v = glue(ldu, SUFFIX)((void *)ESI);
787 #if SHIFT == 0
788 EAX = (EAX & ~0xff) | v;
789 #elif SHIFT == 1
790 EAX = (EAX & ~0xffff) | v;
791 #else
792 EAX = v;
793 #endif
794 ESI += (DF << SHIFT);
795 }
796
797 /* don't know if it is used */
798 void OPPROTO glue(op_rep_lods, SUFFIX)(void)
799 {
800 int v, inc;
801 inc = (DF << SHIFT);
802 while (ECX != 0) {
803 v = glue(ldu, SUFFIX)((void *)ESI);
804 #if SHIFT == 0
805 EAX = (EAX & ~0xff) | v;
806 #elif SHIFT == 1
807 EAX = (EAX & ~0xffff) | v;
808 #else
809 EAX = v;
810 #endif
811 ESI += inc;
812 ECX--;
813 }
814 }
815
816 void OPPROTO glue(op_scas, SUFFIX)(void)
817 {
818 int v;
819
820 v = glue(ldu, SUFFIX)((void *)EDI);
821 EDI += (DF << SHIFT);
822 CC_SRC = EAX;
823 CC_DST = EAX - v;
824 }
825
826 void OPPROTO glue(op_repz_scas, SUFFIX)(void)
827 {
828 int v1, v2, inc;
829
830 if (ECX != 0) {
831 /* NOTE: the flags are not modified if ECX == 0 */
832 v1 = EAX & DATA_MASK;
833 inc = (DF << SHIFT);
834 do {
835 v2 = glue(ldu, SUFFIX)((void *)EDI);
836 EDI += inc;
837 ECX--;
838 if (v1 != v2)
839 break;
840 } while (ECX != 0);
841 CC_SRC = v1;
842 CC_DST = v1 - v2;
843 CC_OP = CC_OP_SUBB + SHIFT;
844 }
845 }
846
847 void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
848 {
849 int v1, v2, inc;
850
851 if (ECX != 0) {
852 /* NOTE: the flags are not modified if ECX == 0 */
853 v1 = EAX & DATA_MASK;
854 inc = (DF << SHIFT);
855 do {
856 v2 = glue(ldu, SUFFIX)((void *)EDI);
857 EDI += inc;
858 ECX--;
859 if (v1 == v2)
860 break;
861 } while (ECX != 0);
862 CC_SRC = v1;
863 CC_DST = v1 - v2;
864 CC_OP = CC_OP_SUBB + SHIFT;
865 }
866 }
867
868 void OPPROTO glue(op_cmps, SUFFIX)(void)
869 {
870 int v1, v2;
871 v1 = glue(ldu, SUFFIX)((void *)ESI);
872 v2 = glue(ldu, SUFFIX)((void *)EDI);
873 ESI += (DF << SHIFT);
874 EDI += (DF << SHIFT);
875 CC_SRC = v1;
876 CC_DST = v1 - v2;
877 }
878
879 void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
880 {
881 int v1, v2, inc;
882 if (ECX != 0) {
883 inc = (DF << SHIFT);
884 do {
885 v1 = glue(ldu, SUFFIX)((void *)ESI);
886 v2 = glue(ldu, SUFFIX)((void *)EDI);
887 ESI += inc;
888 EDI += inc;
889 ECX--;
890 if (v1 != v2)
891 break;
892 } while (ECX != 0);
893 CC_SRC = v1;
894 CC_DST = v1 - v2;
895 CC_OP = CC_OP_SUBB + SHIFT;
896 }
897 }
898
899 void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
900 {
901 int v1, v2, inc;
902 if (ECX != 0) {
903 inc = (DF << SHIFT);
904 do {
905 v1 = glue(ldu, SUFFIX)((void *)ESI);
906 v2 = glue(ldu, SUFFIX)((void *)EDI);
907 ESI += inc;
908 EDI += inc;
909 ECX--;
910 if (v1 == v2)
911 break;
912 } while (ECX != 0);
913 CC_SRC = v1;
914 CC_DST = v1 - v2;
915 CC_OP = CC_OP_SUBB + SHIFT;
916 }
917 }
918
919 /* port I/O */
920
921 void OPPROTO glue(op_outs, SUFFIX)(void)
922 {
923 int v, dx;
924 dx = EDX & 0xffff;
925 v = glue(ldu, SUFFIX)((void *)ESI);
926 glue(cpu_x86_out, SUFFIX)(dx, v);
927 ESI += (DF << SHIFT);
928 }
929
930 void OPPROTO glue(op_rep_outs, SUFFIX)(void)
931 {
932 int v, dx, inc;
933 inc = (DF << SHIFT);
934 dx = EDX & 0xffff;
935 while (ECX != 0) {
936 v = glue(ldu, SUFFIX)((void *)ESI);
937 glue(cpu_x86_out, SUFFIX)(dx, v);
938 ESI += inc;
939 ECX--;
940 }
941 }
942
943 void OPPROTO glue(op_ins, SUFFIX)(void)
944 {
945 int v, dx;
946 dx = EDX & 0xffff;
947 v = glue(cpu_x86_in, SUFFIX)(dx);
948 glue(st, SUFFIX)((void *)EDI, v);
949 EDI += (DF << SHIFT);
950 }
951
952 void OPPROTO glue(op_rep_ins, SUFFIX)(void)
953 {
954 int v, dx, inc;
955 inc = (DF << SHIFT);
956 dx = EDX & 0xffff;
957 while (ECX != 0) {
958 v = glue(cpu_x86_in, SUFFIX)(dx);
959 glue(st, SUFFIX)((void *)EDI, v);
960 EDI += (DF << SHIFT);
961 ECX--;
962 }
963 }
964
965 void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
966 {
967 glue(cpu_x86_out, SUFFIX)(T0 & 0xffff, T1 & DATA_MASK);
968 }
969
970 void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
971 {
972 T1 = glue(cpu_x86_in, SUFFIX)(T0 & 0xffff);
973 }
974
975 #undef DATA_BITS
976 #undef SHIFT_MASK
977 #undef SIGN_MASK
978 #undef DATA_TYPE
979 #undef DATA_STYPE
980 #undef DATA_MASK
981 #undef SUFFIX