converted MUL/IMUL to TCG
[qemu] / target-i386 / op.c
1 /*
2  *  i386 micro operations
3  *
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #define ASM_SOFTMMU
22 #include "exec.h"
23
24 /* we define the various pieces of code used by the JIT */
25
26 #define REG EAX
27 #define REGNAME _EAX
28 #include "opreg_template.h"
29 #undef REG
30 #undef REGNAME
31
32 #define REG ECX
33 #define REGNAME _ECX
34 #include "opreg_template.h"
35 #undef REG
36 #undef REGNAME
37
38 #define REG EDX
39 #define REGNAME _EDX
40 #include "opreg_template.h"
41 #undef REG
42 #undef REGNAME
43
44 #define REG EBX
45 #define REGNAME _EBX
46 #include "opreg_template.h"
47 #undef REG
48 #undef REGNAME
49
50 #define REG ESP
51 #define REGNAME _ESP
52 #include "opreg_template.h"
53 #undef REG
54 #undef REGNAME
55
56 #define REG EBP
57 #define REGNAME _EBP
58 #include "opreg_template.h"
59 #undef REG
60 #undef REGNAME
61
62 #define REG ESI
63 #define REGNAME _ESI
64 #include "opreg_template.h"
65 #undef REG
66 #undef REGNAME
67
68 #define REG EDI
69 #define REGNAME _EDI
70 #include "opreg_template.h"
71 #undef REG
72 #undef REGNAME
73
74 #ifdef TARGET_X86_64
75
76 #define REG (env->regs[8])
77 #define REGNAME _R8
78 #include "opreg_template.h"
79 #undef REG
80 #undef REGNAME
81
82 #define REG (env->regs[9])
83 #define REGNAME _R9
84 #include "opreg_template.h"
85 #undef REG
86 #undef REGNAME
87
88 #define REG (env->regs[10])
89 #define REGNAME _R10
90 #include "opreg_template.h"
91 #undef REG
92 #undef REGNAME
93
94 #define REG (env->regs[11])
95 #define REGNAME _R11
96 #include "opreg_template.h"
97 #undef REG
98 #undef REGNAME
99
100 #define REG (env->regs[12])
101 #define REGNAME _R12
102 #include "opreg_template.h"
103 #undef REG
104 #undef REGNAME
105
106 #define REG (env->regs[13])
107 #define REGNAME _R13
108 #include "opreg_template.h"
109 #undef REG
110 #undef REGNAME
111
112 #define REG (env->regs[14])
113 #define REGNAME _R14
114 #include "opreg_template.h"
115 #undef REG
116 #undef REGNAME
117
118 #define REG (env->regs[15])
119 #define REGNAME _R15
120 #include "opreg_template.h"
121 #undef REG
122 #undef REGNAME
123
124 #endif
125
126 /* constant load & misc op */
127
128 /* XXX: consistent names */
129 void OPPROTO op_into(void)
130 {
131     int eflags;
132     eflags = cc_table[CC_OP].compute_all();
133     if (eflags & CC_O) {
134         raise_interrupt(EXCP04_INTO, 1, 0, PARAM1);
135     }
136     FORCE_RET();
137 }
138
139 void OPPROTO op_cmpxchg8b(void)
140 {
141     helper_cmpxchg8b(A0);
142 }
143
144 /* multiple size ops */
145
146 #define ldul ldl
147
148 #define SHIFT 0
149 #include "ops_template.h"
150 #undef SHIFT
151
152 #define SHIFT 1
153 #include "ops_template.h"
154 #undef SHIFT
155
156 #define SHIFT 2
157 #include "ops_template.h"
158 #undef SHIFT
159
160 #ifdef TARGET_X86_64
161
162 #define SHIFT 3
163 #include "ops_template.h"
164 #undef SHIFT
165
166 #endif
167
168 /* bcd */
169
170 void OPPROTO op_aam(void)
171 {
172     helper_aam(PARAM1);
173 }
174
175 void OPPROTO op_aad(void)
176 {
177     helper_aad(PARAM1);
178 }
179
180 void OPPROTO op_aaa(void)
181 {
182     helper_aaa();
183 }
184
185 void OPPROTO op_aas(void)
186 {
187     helper_aas();
188 }
189
190 void OPPROTO op_daa(void)
191 {
192     helper_daa();
193 }
194
195 void OPPROTO op_das(void)
196 {
197     helper_das();
198 }
199
200 /* segment handling */
201
202 /* faster VM86 version */
203 void OPPROTO op_movl_seg_T0_vm(void)
204 {
205     int selector;
206     SegmentCache *sc;
207
208     selector = T0 & 0xffff;
209     /* env->segs[] access */
210     sc = (SegmentCache *)((char *)env + PARAM1);
211     sc->selector = selector;
212     sc->base = (selector << 4);
213 }
214
215 void OPPROTO op_movl_T0_seg(void)
216 {
217     T0 = env->segs[PARAM1].selector;
218 }
219
220 void OPPROTO op_lsl(void)
221 {
222     uint32_t val;
223     val = helper_lsl(T0);
224     if (CC_SRC & CC_Z)
225         T1 = val;
226     FORCE_RET();
227 }
228
229 void OPPROTO op_lar(void)
230 {
231     uint32_t val;
232     val = helper_lar(T0);
233     if (CC_SRC & CC_Z)
234         T1 = val;
235     FORCE_RET();
236 }
237
238 void OPPROTO op_verr(void)
239 {
240     helper_verr(T0);
241 }
242
243 void OPPROTO op_verw(void)
244 {
245     helper_verw(T0);
246 }
247
248 void OPPROTO op_arpl(void)
249 {
250     if ((T0 & 3) < (T1 & 3)) {
251         /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
252         T0 = (T0 & ~3) | (T1 & 3);
253         T1 = CC_Z;
254    } else {
255         T1 = 0;
256     }
257     FORCE_RET();
258 }
259
260 void OPPROTO op_arpl_update(void)
261 {
262     int eflags;
263     eflags = cc_table[CC_OP].compute_all();
264     CC_SRC = (eflags & ~CC_Z) | T1;
265 }
266
267 void OPPROTO op_movl_T0_env(void)
268 {
269     T0 = *(uint32_t *)((char *)env + PARAM1);
270 }
271
272 void OPPROTO op_movl_env_T0(void)
273 {
274     *(uint32_t *)((char *)env + PARAM1) = T0;
275 }
276
277 void OPPROTO op_movl_env_T1(void)
278 {
279     *(uint32_t *)((char *)env + PARAM1) = T1;
280 }
281
282 void OPPROTO op_movtl_T0_env(void)
283 {
284     T0 = *(target_ulong *)((char *)env + PARAM1);
285 }
286
287 void OPPROTO op_movtl_env_T0(void)
288 {
289     *(target_ulong *)((char *)env + PARAM1) = T0;
290 }
291
292 void OPPROTO op_movtl_T1_env(void)
293 {
294     T1 = *(target_ulong *)((char *)env + PARAM1);
295 }
296
297 void OPPROTO op_movtl_env_T1(void)
298 {
299     *(target_ulong *)((char *)env + PARAM1) = T1;
300 }
301
302 /* flags handling */
303
304 void OPPROTO op_jmp_label(void)
305 {
306     GOTO_LABEL_PARAM(1);
307 }
308
309 void OPPROTO op_jnz_T0_label(void)
310 {
311     if (T0)
312         GOTO_LABEL_PARAM(1);
313     FORCE_RET();
314 }
315
316 /* slow set cases (compute x86 flags) */
317 void OPPROTO op_seto_T0_cc(void)
318 {
319     int eflags;
320     eflags = cc_table[CC_OP].compute_all();
321     T0 = (eflags >> 11) & 1;
322 }
323
324 void OPPROTO op_setb_T0_cc(void)
325 {
326     T0 = cc_table[CC_OP].compute_c();
327 }
328
329 void OPPROTO op_setz_T0_cc(void)
330 {
331     int eflags;
332     eflags = cc_table[CC_OP].compute_all();
333     T0 = (eflags >> 6) & 1;
334 }
335
336 void OPPROTO op_setbe_T0_cc(void)
337 {
338     int eflags;
339     eflags = cc_table[CC_OP].compute_all();
340     T0 = (eflags & (CC_Z | CC_C)) != 0;
341 }
342
343 void OPPROTO op_sets_T0_cc(void)
344 {
345     int eflags;
346     eflags = cc_table[CC_OP].compute_all();
347     T0 = (eflags >> 7) & 1;
348 }
349
350 void OPPROTO op_setp_T0_cc(void)
351 {
352     int eflags;
353     eflags = cc_table[CC_OP].compute_all();
354     T0 = (eflags >> 2) & 1;
355 }
356
357 void OPPROTO op_setl_T0_cc(void)
358 {
359     int eflags;
360     eflags = cc_table[CC_OP].compute_all();
361     T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
362 }
363
364 void OPPROTO op_setle_T0_cc(void)
365 {
366     int eflags;
367     eflags = cc_table[CC_OP].compute_all();
368     T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
369 }
370
371 void OPPROTO op_xor_T0_1(void)
372 {
373     T0 ^= 1;
374 }
375
376 /* XXX: clear VIF/VIP in all ops ? */
377
378 void OPPROTO op_movl_eflags_T0(void)
379 {
380     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK));
381 }
382
383 void OPPROTO op_movw_eflags_T0(void)
384 {
385     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
386 }
387
388 void OPPROTO op_movl_eflags_T0_io(void)
389 {
390     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK));
391 }
392
393 void OPPROTO op_movw_eflags_T0_io(void)
394 {
395     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
396 }
397
398 void OPPROTO op_movl_eflags_T0_cpl0(void)
399 {
400     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK));
401 }
402
403 void OPPROTO op_movw_eflags_T0_cpl0(void)
404 {
405     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
406 }
407
408 #if 0
409 /* vm86plus version */
410 void OPPROTO op_movw_eflags_T0_vm(void)
411 {
412     int eflags;
413     eflags = T0;
414     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
415     DF = 1 - (2 * ((eflags >> 10) & 1));
416     /* we also update some system flags as in user mode */
417     env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
418         (eflags & FL_UPDATE_MASK16);
419     if (eflags & IF_MASK) {
420         env->eflags |= VIF_MASK;
421         if (env->eflags & VIP_MASK) {
422             EIP = PARAM1;
423             raise_exception(EXCP0D_GPF);
424         }
425     }
426     FORCE_RET();
427 }
428
429 void OPPROTO op_movl_eflags_T0_vm(void)
430 {
431     int eflags;
432     eflags = T0;
433     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
434     DF = 1 - (2 * ((eflags >> 10) & 1));
435     /* we also update some system flags as in user mode */
436     env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
437         (eflags & FL_UPDATE_MASK32);
438     if (eflags & IF_MASK) {
439         env->eflags |= VIF_MASK;
440         if (env->eflags & VIP_MASK) {
441             EIP = PARAM1;
442             raise_exception(EXCP0D_GPF);
443         }
444     }
445     FORCE_RET();
446 }
447 #endif
448
449 /* XXX: compute only O flag */
450 void OPPROTO op_movb_eflags_T0(void)
451 {
452     int of;
453     of = cc_table[CC_OP].compute_all() & CC_O;
454     CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
455 }
456
457 void OPPROTO op_movl_T0_eflags(void)
458 {
459     int eflags;
460     eflags = cc_table[CC_OP].compute_all();
461     eflags |= (DF & DF_MASK);
462     eflags |= env->eflags & ~(VM_MASK | RF_MASK);
463     T0 = eflags;
464 }
465
466 /* vm86plus version */
467 #if 0
468 void OPPROTO op_movl_T0_eflags_vm(void)
469 {
470     int eflags;
471     eflags = cc_table[CC_OP].compute_all();
472     eflags |= (DF & DF_MASK);
473     eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
474     if (env->eflags & VIF_MASK)
475         eflags |= IF_MASK;
476     T0 = eflags;
477 }
478 #endif
479
480 void OPPROTO op_clc(void)
481 {
482     int eflags;
483     eflags = cc_table[CC_OP].compute_all();
484     eflags &= ~CC_C;
485     CC_SRC = eflags;
486 }
487
488 void OPPROTO op_stc(void)
489 {
490     int eflags;
491     eflags = cc_table[CC_OP].compute_all();
492     eflags |= CC_C;
493     CC_SRC = eflags;
494 }
495
496 void OPPROTO op_cmc(void)
497 {
498     int eflags;
499     eflags = cc_table[CC_OP].compute_all();
500     eflags ^= CC_C;
501     CC_SRC = eflags;
502 }
503
504 void OPPROTO op_salc(void)
505 {
506     int cf;
507     cf = cc_table[CC_OP].compute_c();
508     EAX = (EAX & ~0xff) | ((-cf) & 0xff);
509 }
510
511 void OPPROTO op_fcomi_dummy(void)
512 {
513     T0 = 0;
514 }
515
516 /* SSE support */
517 void OPPROTO op_com_dummy(void)
518 {
519     T0 = 0;
520 }