]> git.proxmox.com Git - qemu.git/blob - ops_template.h
18b2ffb4920fc83370246dfa714126622738b940
[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_sub, SUFFIX)(void)
51 {
52 int cf, pf, af, zf, sf, of;
53 int src1, src2;
54 src1 = CC_SRC;
55 src2 = CC_SRC - CC_DST;
56 cf = (DATA_TYPE)src1 < (DATA_TYPE)src2;
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_sub, SUFFIX)(void)
66 {
67 int src1, src2, cf;
68 src1 = CC_SRC;
69 src2 = CC_SRC - CC_DST;
70 cf = (DATA_TYPE)src1 < (DATA_TYPE)src1;
71 return cf;
72 }
73
74 static int glue(compute_all_logic, SUFFIX)(void)
75 {
76 int cf, pf, af, zf, sf, of;
77 cf = 0;
78 pf = parity_table[(uint8_t)CC_DST];
79 af = 0;
80 zf = ((DATA_TYPE)CC_DST != 0) << 6;
81 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
82 of = 0;
83 return cf | pf | af | zf | sf | of;
84 }
85
86 static int glue(compute_c_logic, SUFFIX)(void)
87 {
88 return 0;
89 }
90
91 static int glue(compute_all_inc, SUFFIX)(void)
92 {
93 int cf, pf, af, zf, sf, of;
94 int src1, src2;
95 src1 = CC_DST - 1;
96 src2 = 1;
97 cf = CC_SRC;
98 pf = parity_table[(uint8_t)CC_DST];
99 af = (CC_DST ^ src1 ^ src2) & 0x10;
100 zf = ((DATA_TYPE)CC_DST != 0) << 6;
101 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
102 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
103 return cf | pf | af | zf | sf | of;
104 }
105
106 static int glue(compute_c_inc, SUFFIX)(void)
107 {
108 return CC_SRC;
109 }
110
111 static int glue(compute_all_dec, SUFFIX)(void)
112 {
113 int cf, pf, af, zf, sf, of;
114 int src1, src2;
115 src1 = CC_DST + 1;
116 src2 = 1;
117 cf = CC_SRC;
118 pf = parity_table[(uint8_t)CC_DST];
119 af = (CC_DST ^ src1 ^ src2) & 0x10;
120 zf = ((DATA_TYPE)CC_DST != 0) << 6;
121 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
122 of = lshift((src1 ^ src2 ^ -1) & (src1 ^ CC_DST), 12 - DATA_BITS) & CC_O;
123 return cf | pf | af | zf | sf | of;
124 }
125
126 static int glue(compute_all_shl, SUFFIX)(void)
127 {
128 int cf, pf, af, zf, sf, of;
129 cf = CC_SRC & 1;
130 pf = parity_table[(uint8_t)CC_DST];
131 af = 0; /* undefined */
132 zf = ((DATA_TYPE)CC_DST != 0) << 6;
133 sf = lshift(CC_DST, 8 - DATA_BITS) & 0x80;
134 of = sf << 4; /* only meaniful for shr with count == 1 */
135 return cf | pf | af | zf | sf | of;
136 }
137
138 static int glue(compute_c_shl, SUFFIX)(void)
139 {
140 return CC_SRC & 1;
141 }
142
143 /* various optimized jumps cases */
144
145 void OPPROTO glue(op_jb_sub, SUFFIX)(void)
146 {
147 int src1, src2;
148 src1 = CC_SRC;
149 src2 = CC_SRC - CC_DST;
150
151 if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
152 PC += PARAM1;
153 else
154 PC += PARAM2;
155 FORCE_RET();
156 }
157
158 void OPPROTO glue(op_jz_sub, SUFFIX)(void)
159 {
160 if ((DATA_TYPE)CC_DST != 0)
161 PC += PARAM1;
162 else
163 PC += PARAM2;
164 FORCE_RET();
165 }
166
167 void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
168 {
169 int src1, src2;
170 src1 = CC_SRC;
171 src2 = CC_SRC - CC_DST;
172
173 if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
174 PC += PARAM1;
175 else
176 PC += PARAM2;
177 FORCE_RET();
178 }
179
180 void OPPROTO glue(op_js_sub, SUFFIX)(void)
181 {
182 if (CC_DST & SIGN_MASK)
183 PC += PARAM1;
184 else
185 PC += PARAM2;
186 FORCE_RET();
187 }
188
189 void OPPROTO glue(op_jl_sub, SUFFIX)(void)
190 {
191 int src1, src2;
192 src1 = CC_SRC;
193 src2 = CC_SRC - CC_DST;
194
195 if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
196 PC += PARAM1;
197 else
198 PC += PARAM2;
199 FORCE_RET();
200 }
201
202 void OPPROTO glue(op_jle_sub, SUFFIX)(void)
203 {
204 int src1, src2;
205 src1 = CC_SRC;
206 src2 = CC_SRC - CC_DST;
207
208 if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
209 PC += PARAM1;
210 else
211 PC += PARAM2;
212 FORCE_RET();
213 }
214
215 /* various optimized set cases */
216
217 void OPPROTO glue(op_setb_T0_sub, SUFFIX)(void)
218 {
219 int src1, src2;
220 src1 = CC_SRC;
221 src2 = CC_SRC - CC_DST;
222
223 T0 = ((DATA_TYPE)src1 < (DATA_TYPE)src2);
224 }
225
226 void OPPROTO glue(op_setz_T0_sub, SUFFIX)(void)
227 {
228 T0 = ((DATA_TYPE)CC_DST != 0);
229 }
230
231 void OPPROTO glue(op_setbe_T0_sub, SUFFIX)(void)
232 {
233 int src1, src2;
234 src1 = CC_SRC;
235 src2 = CC_SRC - CC_DST;
236
237 T0 = ((DATA_TYPE)src1 <= (DATA_TYPE)src2);
238 }
239
240 void OPPROTO glue(op_sets_T0_sub, SUFFIX)(void)
241 {
242 T0 = lshift(CC_DST, -(DATA_BITS - 1)) & 1;
243 }
244
245 void OPPROTO glue(op_setl_T0_sub, SUFFIX)(void)
246 {
247 int src1, src2;
248 src1 = CC_SRC;
249 src2 = CC_SRC - CC_DST;
250
251 T0 = ((DATA_STYPE)src1 < (DATA_STYPE)src2);
252 }
253
254 void OPPROTO glue(op_setle_T0_sub, SUFFIX)(void)
255 {
256 int src1, src2;
257 src1 = CC_SRC;
258 src2 = CC_SRC - CC_DST;
259
260 T0 = ((DATA_STYPE)src1 <= (DATA_STYPE)src2);
261 }
262
263 /* shifts */
264
265 void OPPROTO glue(glue(op_rol, SUFFIX), _T0_T1_cc)(void)
266 {
267 int count, src;
268 count = T1 & SHIFT_MASK;
269 if (count) {
270 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
271 src = T0;
272 T0 &= DATA_MASK;
273 T0 = (T0 << count) | (T0 >> (DATA_BITS - count));
274 CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
275 (T0 & CC_C);
276 CC_OP = CC_OP_EFLAGS;
277 }
278 }
279
280 void OPPROTO glue(glue(op_ror, SUFFIX), _T0_T1_cc)(void)
281 {
282 int count, src;
283 count = T1 & SHIFT_MASK;
284 if (count) {
285 CC_SRC = cc_table[CC_OP].compute_all() & ~(CC_O | CC_C);
286 src = T0;
287 T0 &= DATA_MASK;
288 T0 = (T0 >> count) | (T0 << (DATA_BITS - count));
289 CC_SRC |= (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
290 ((T0 >> (DATA_BITS - 1)) & CC_C);
291 CC_OP = CC_OP_EFLAGS;
292 }
293 }
294
295 void OPPROTO glue(glue(op_rcl, SUFFIX), _T0_T1_cc)(void)
296 {
297 int count, res, eflags;
298 unsigned int src;
299
300 count = T1 & 0x1f;
301 #if DATA_BITS == 16
302 count = rclw_table[count];
303 #elif DATA_BITS == 8
304 count = rclb_table[count];
305 #endif
306 if (count) {
307 eflags = cc_table[CC_OP].compute_all();
308 src = T0;
309 res = (T0 << count) | ((eflags & CC_C) << (count - 1));
310 if (count > 1)
311 res |= T0 >> (DATA_BITS + 1 - count);
312 T0 = res;
313 CC_SRC = (eflags & ~(CC_C | CC_O)) |
314 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
315 ((src >> (DATA_BITS - count)) & CC_C);
316 CC_OP = CC_OP_EFLAGS;
317 }
318 }
319
320 void OPPROTO glue(glue(op_rcr, SUFFIX), _T0_T1_cc)(void)
321 {
322 int count, res, eflags;
323 unsigned int src;
324
325 count = T1 & 0x1f;
326 #if DATA_BITS == 16
327 count = rclw_table[count];
328 #elif DATA_BITS == 8
329 count = rclb_table[count];
330 #endif
331 if (count) {
332 eflags = cc_table[CC_OP].compute_all();
333 src = T0;
334 res = (T0 >> count) | ((eflags & CC_C) << (DATA_BITS - count));
335 if (count > 1)
336 res |= T0 << (DATA_BITS + 1 - count);
337 T0 = res;
338 CC_SRC = (eflags & ~(CC_C | CC_O)) |
339 (lshift(src ^ T0, 11 - (DATA_BITS - 1)) & CC_O) |
340 ((src >> (count - 1)) & CC_C);
341 CC_OP = CC_OP_EFLAGS;
342 }
343 }
344
345 void OPPROTO glue(glue(op_shl, SUFFIX), _T0_T1_cc)(void)
346 {
347 int count;
348 count = T1 & 0x1f;
349 if (count == 1) {
350 CC_SRC = T0;
351 T0 = T0 << 1;
352 CC_DST = T0;
353 CC_OP = CC_OP_ADDB + SHIFT;
354 } else if (count) {
355 CC_SRC = T0 >> (DATA_BITS - count);
356 T0 = T0 << count;
357 CC_DST = T0;
358 CC_OP = CC_OP_SHLB + SHIFT;
359 }
360 }
361
362 void OPPROTO glue(glue(op_shr, SUFFIX), _T0_T1_cc)(void)
363 {
364 int count;
365 count = T1 & 0x1f;
366 if (count) {
367 T0 &= DATA_MASK;
368 CC_SRC = T0 >> (count - 1);
369 T0 = T0 >> count;
370 CC_DST = T0;
371 CC_OP = CC_OP_SHLB + SHIFT;
372 }
373 }
374
375 void OPPROTO glue(glue(op_sar, SUFFIX), _T0_T1_cc)(void)
376 {
377 int count, src;
378 count = T1 & 0x1f;
379 if (count) {
380 src = (DATA_STYPE)T0;
381 CC_SRC = src >> (count - 1);
382 T0 = src >> count;
383 CC_DST = T0;
384 CC_OP = CC_OP_SHLB + SHIFT;
385 }
386 }
387
388 /* string operations */
389 /* XXX: maybe use lower level instructions to ease exception handling */
390
391 void OPPROTO glue(op_movs, SUFFIX)(void)
392 {
393 int v;
394 v = glue(ldu, SUFFIX)((void *)ESI);
395 glue(st, SUFFIX)((void *)EDI, v);
396 ESI += (DF << SHIFT);
397 EDI += (DF << SHIFT);
398 }
399
400 void OPPROTO glue(op_rep_movs, SUFFIX)(void)
401 {
402 int v, inc;
403 inc = (DF << SHIFT);
404 while (ECX != 0) {
405 v = glue(ldu, SUFFIX)((void *)ESI);
406 glue(st, SUFFIX)((void *)EDI, v);
407 ESI += inc;
408 EDI += inc;
409 ECX--;
410 }
411 }
412
413 void OPPROTO glue(op_stos, SUFFIX)(void)
414 {
415 glue(st, SUFFIX)((void *)EDI, EAX);
416 EDI += (DF << SHIFT);
417 }
418
419 void OPPROTO glue(op_rep_stos, SUFFIX)(void)
420 {
421 int inc;
422 inc = (DF << SHIFT);
423 while (ECX != 0) {
424 glue(st, SUFFIX)((void *)EDI, EAX);
425 EDI += inc;
426 ECX--;
427 }
428 }
429
430 void OPPROTO glue(op_lods, SUFFIX)(void)
431 {
432 int v;
433 v = glue(ldu, SUFFIX)((void *)ESI);
434 #if SHIFT == 0
435 EAX = (EAX & ~0xff) | v;
436 #elif SHIFT == 1
437 EAX = (EAX & ~0xffff) | v;
438 #else
439 EAX = v;
440 #endif
441 ESI += (DF << SHIFT);
442 }
443
444 /* don't know if it is used */
445 void OPPROTO glue(op_rep_lods, SUFFIX)(void)
446 {
447 int v, inc;
448 inc = (DF << SHIFT);
449 while (ECX != 0) {
450 v = glue(ldu, SUFFIX)((void *)ESI);
451 #if SHIFT == 0
452 EAX = (EAX & ~0xff) | v;
453 #elif SHIFT == 1
454 EAX = (EAX & ~0xffff) | v;
455 #else
456 EAX = v;
457 #endif
458 ESI += inc;
459 ECX--;
460 }
461 }
462
463 void OPPROTO glue(op_scas, SUFFIX)(void)
464 {
465 int v;
466
467 v = glue(ldu, SUFFIX)((void *)ESI);
468 ESI += (DF << SHIFT);
469 CC_SRC = EAX;
470 CC_DST = EAX - v;
471 }
472
473 void OPPROTO glue(op_repz_scas, SUFFIX)(void)
474 {
475 int v1, v2, inc;
476
477 if (ECX != 0) {
478 /* NOTE: the flags are not modified if ECX == 0 */
479 #if SHIFT == 0
480 v1 = EAX & 0xff;
481 #elif SHIFT == 1
482 v1 = EAX & 0xffff;
483 #else
484 v1 = EAX;
485 #endif
486 inc = (DF << SHIFT);
487 do {
488 v2 = glue(ldu, SUFFIX)((void *)ESI);
489 if (v1 != v2)
490 break;
491 ESI += inc;
492 ECX--;
493 } while (ECX != 0);
494 CC_SRC = v1;
495 CC_DST = v1 - v2;
496 CC_OP = CC_OP_SUBB + SHIFT;
497 }
498 }
499
500 void OPPROTO glue(op_repnz_scas, SUFFIX)(void)
501 {
502 int v1, v2, inc;
503
504 if (ECX != 0) {
505 /* NOTE: the flags are not modified if ECX == 0 */
506 #if SHIFT == 0
507 v1 = EAX & 0xff;
508 #elif SHIFT == 1
509 v1 = EAX & 0xffff;
510 #else
511 v1 = EAX;
512 #endif
513 inc = (DF << SHIFT);
514 do {
515 v2 = glue(ldu, SUFFIX)((void *)ESI);
516 if (v1 == v2)
517 break;
518 ESI += inc;
519 ECX--;
520 } while (ECX != 0);
521 CC_SRC = v1;
522 CC_DST = v1 - v2;
523 CC_OP = CC_OP_SUBB + SHIFT;
524 }
525 }
526
527 void OPPROTO glue(op_cmps, SUFFIX)(void)
528 {
529 int v1, v2;
530 v1 = glue(ldu, SUFFIX)((void *)ESI);
531 v2 = glue(ldu, SUFFIX)((void *)EDI);
532 ESI += (DF << SHIFT);
533 EDI += (DF << SHIFT);
534 CC_SRC = v1;
535 CC_DST = v1 - v2;
536 }
537
538 void OPPROTO glue(op_repz_cmps, SUFFIX)(void)
539 {
540 int v1, v2, inc;
541 if (ECX != 0) {
542 inc = (DF << SHIFT);
543 do {
544 v1 = glue(ldu, SUFFIX)((void *)ESI);
545 v2 = glue(ldu, SUFFIX)((void *)EDI);
546 if (v1 != v2)
547 break;
548 ESI += inc;
549 EDI += inc;
550 ECX--;
551 } while (ECX != 0);
552 CC_SRC = v1;
553 CC_DST = v1 - v2;
554 CC_OP = CC_OP_SUBB + SHIFT;
555 }
556 }
557
558 void OPPROTO glue(op_repnz_cmps, SUFFIX)(void)
559 {
560 int v1, v2, inc;
561 if (ECX != 0) {
562 inc = (DF << SHIFT);
563 do {
564 v1 = glue(ldu, SUFFIX)((void *)ESI);
565 v2 = glue(ldu, SUFFIX)((void *)EDI);
566 if (v1 == v2)
567 break;
568 ESI += inc;
569 EDI += inc;
570 ECX--;
571 } while (ECX != 0);
572 CC_SRC = v1;
573 CC_DST = v1 - v2;
574 CC_OP = CC_OP_SUBB + SHIFT;
575 }
576 }
577
578 /* port I/O */
579
580 void OPPROTO glue(op_outs, SUFFIX)(void)
581 {
582 int v, dx;
583 dx = EDX & 0xffff;
584 v = glue(ldu, SUFFIX)((void *)ESI);
585 glue(cpu_x86_out, SUFFIX)(dx, v);
586 ESI += (DF << SHIFT);
587 }
588
589 void OPPROTO glue(op_rep_outs, SUFFIX)(void)
590 {
591 int v, dx, inc;
592 inc = (DF << SHIFT);
593 dx = EDX & 0xffff;
594 while (ECX != 0) {
595 v = glue(ldu, SUFFIX)((void *)ESI);
596 glue(cpu_x86_out, SUFFIX)(dx, v);
597 ESI += inc;
598 ECX--;
599 }
600 }
601
602 void OPPROTO glue(op_ins, SUFFIX)(void)
603 {
604 int v, dx;
605 dx = EDX & 0xffff;
606 v = glue(cpu_x86_in, SUFFIX)(dx);
607 glue(st, SUFFIX)((void *)EDI, v);
608 EDI += (DF << SHIFT);
609 }
610
611 void OPPROTO glue(op_rep_ins, SUFFIX)(void)
612 {
613 int v, dx, inc;
614 inc = (DF << SHIFT);
615 dx = EDX & 0xffff;
616 while (ECX != 0) {
617 v = glue(cpu_x86_in, SUFFIX)(dx);
618 glue(st, SUFFIX)((void *)EDI, v);
619 EDI += (DF << SHIFT);
620 ECX--;
621 }
622 }
623
624 void OPPROTO glue(glue(op_out, SUFFIX), _T0_T1)(void)
625 {
626 glue(cpu_x86_out, SUFFIX)(T0 & 0xffff, T1 & DATA_MASK);
627 }
628
629 void OPPROTO glue(glue(op_in, SUFFIX), _T0_T1)(void)
630 {
631 T1 = glue(cpu_x86_in, SUFFIX)(T0 & 0xffff);
632 }
633
634 #undef DATA_BITS
635 #undef SHIFT_MASK
636 #undef SIGN_MASK
637 #undef DATA_TYPE
638 #undef DATA_STYPE
639 #undef DATA_MASK
640 #undef SUFFIX