prints hello world
[qemu] / 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