d637423c65d3eddf475d77205fb78d60688b0298
[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 /* multiple size ops */
127
128 #define ldul ldl
129
130 #define SHIFT 0
131 #include "ops_template.h"
132 #undef SHIFT
133
134 #define SHIFT 1
135 #include "ops_template.h"
136 #undef SHIFT
137
138 #define SHIFT 2
139 #include "ops_template.h"
140 #undef SHIFT
141
142 #ifdef TARGET_X86_64
143
144 #define SHIFT 3
145 #include "ops_template.h"
146 #undef SHIFT
147
148 #endif
149
150 /* segment handling */
151
152 /* faster VM86 version */
153 void OPPROTO op_movl_seg_T0_vm(void)
154 {
155     int selector;
156     SegmentCache *sc;
157
158     selector = T0 & 0xffff;
159     /* env->segs[] access */
160     sc = (SegmentCache *)((char *)env + PARAM1);
161     sc->selector = selector;
162     sc->base = (selector << 4);
163 }
164
165 void OPPROTO op_movl_T0_seg(void)
166 {
167     T0 = env->segs[PARAM1].selector;
168 }
169
170 void OPPROTO op_arpl(void)
171 {
172     if ((T0 & 3) < (T1 & 3)) {
173         /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
174         T0 = (T0 & ~3) | (T1 & 3);
175         T1 = CC_Z;
176    } else {
177         T1 = 0;
178     }
179     FORCE_RET();
180 }
181
182 void OPPROTO op_arpl_update(void)
183 {
184     int eflags;
185     eflags = cc_table[CC_OP].compute_all();
186     CC_SRC = (eflags & ~CC_Z) | T1;
187 }
188
189 void OPPROTO op_movl_T0_env(void)
190 {
191     T0 = *(uint32_t *)((char *)env + PARAM1);
192 }
193
194 void OPPROTO op_movl_env_T0(void)
195 {
196     *(uint32_t *)((char *)env + PARAM1) = T0;
197 }
198
199 void OPPROTO op_movl_env_T1(void)
200 {
201     *(uint32_t *)((char *)env + PARAM1) = T1;
202 }
203
204 void OPPROTO op_movtl_T0_env(void)
205 {
206     T0 = *(target_ulong *)((char *)env + PARAM1);
207 }
208
209 void OPPROTO op_movtl_env_T0(void)
210 {
211     *(target_ulong *)((char *)env + PARAM1) = T0;
212 }
213
214 void OPPROTO op_movtl_T1_env(void)
215 {
216     T1 = *(target_ulong *)((char *)env + PARAM1);
217 }
218
219 void OPPROTO op_movtl_env_T1(void)
220 {
221     *(target_ulong *)((char *)env + PARAM1) = T1;
222 }
223
224 /* flags handling */
225
226 void OPPROTO op_jmp_label(void)
227 {
228     GOTO_LABEL_PARAM(1);
229 }
230
231 void OPPROTO op_jnz_T0_label(void)
232 {
233     if (T0)
234         GOTO_LABEL_PARAM(1);
235     FORCE_RET();
236 }
237
238 /* slow set cases (compute x86 flags) */
239 void OPPROTO op_seto_T0_cc(void)
240 {
241     int eflags;
242     eflags = cc_table[CC_OP].compute_all();
243     T0 = (eflags >> 11) & 1;
244 }
245
246 void OPPROTO op_setb_T0_cc(void)
247 {
248     T0 = cc_table[CC_OP].compute_c();
249 }
250
251 void OPPROTO op_setz_T0_cc(void)
252 {
253     int eflags;
254     eflags = cc_table[CC_OP].compute_all();
255     T0 = (eflags >> 6) & 1;
256 }
257
258 void OPPROTO op_setbe_T0_cc(void)
259 {
260     int eflags;
261     eflags = cc_table[CC_OP].compute_all();
262     T0 = (eflags & (CC_Z | CC_C)) != 0;
263 }
264
265 void OPPROTO op_sets_T0_cc(void)
266 {
267     int eflags;
268     eflags = cc_table[CC_OP].compute_all();
269     T0 = (eflags >> 7) & 1;
270 }
271
272 void OPPROTO op_setp_T0_cc(void)
273 {
274     int eflags;
275     eflags = cc_table[CC_OP].compute_all();
276     T0 = (eflags >> 2) & 1;
277 }
278
279 void OPPROTO op_setl_T0_cc(void)
280 {
281     int eflags;
282     eflags = cc_table[CC_OP].compute_all();
283     T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
284 }
285
286 void OPPROTO op_setle_T0_cc(void)
287 {
288     int eflags;
289     eflags = cc_table[CC_OP].compute_all();
290     T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
291 }
292
293 void OPPROTO op_xor_T0_1(void)
294 {
295     T0 ^= 1;
296 }
297
298 /* XXX: clear VIF/VIP in all ops ? */
299
300 void OPPROTO op_movl_eflags_T0(void)
301 {
302     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK));
303 }
304
305 void OPPROTO op_movw_eflags_T0(void)
306 {
307     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
308 }
309
310 void OPPROTO op_movl_eflags_T0_io(void)
311 {
312     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK));
313 }
314
315 void OPPROTO op_movw_eflags_T0_io(void)
316 {
317     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
318 }
319
320 void OPPROTO op_movl_eflags_T0_cpl0(void)
321 {
322     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK));
323 }
324
325 void OPPROTO op_movw_eflags_T0_cpl0(void)
326 {
327     load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
328 }
329
330 #if 0
331 /* vm86plus version */
332 void OPPROTO op_movw_eflags_T0_vm(void)
333 {
334     int eflags;
335     eflags = T0;
336     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
337     DF = 1 - (2 * ((eflags >> 10) & 1));
338     /* we also update some system flags as in user mode */
339     env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
340         (eflags & FL_UPDATE_MASK16);
341     if (eflags & IF_MASK) {
342         env->eflags |= VIF_MASK;
343         if (env->eflags & VIP_MASK) {
344             EIP = PARAM1;
345             raise_exception(EXCP0D_GPF);
346         }
347     }
348     FORCE_RET();
349 }
350
351 void OPPROTO op_movl_eflags_T0_vm(void)
352 {
353     int eflags;
354     eflags = T0;
355     CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
356     DF = 1 - (2 * ((eflags >> 10) & 1));
357     /* we also update some system flags as in user mode */
358     env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
359         (eflags & FL_UPDATE_MASK32);
360     if (eflags & IF_MASK) {
361         env->eflags |= VIF_MASK;
362         if (env->eflags & VIP_MASK) {
363             EIP = PARAM1;
364             raise_exception(EXCP0D_GPF);
365         }
366     }
367     FORCE_RET();
368 }
369 #endif
370
371 /* XXX: compute only O flag */
372 void OPPROTO op_movb_eflags_T0(void)
373 {
374     int of;
375     of = cc_table[CC_OP].compute_all() & CC_O;
376     CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
377 }
378
379 void OPPROTO op_movl_T0_eflags(void)
380 {
381     int eflags;
382     eflags = cc_table[CC_OP].compute_all();
383     eflags |= (DF & DF_MASK);
384     eflags |= env->eflags & ~(VM_MASK | RF_MASK);
385     T0 = eflags;
386 }
387
388 /* vm86plus version */
389 #if 0
390 void OPPROTO op_movl_T0_eflags_vm(void)
391 {
392     int eflags;
393     eflags = cc_table[CC_OP].compute_all();
394     eflags |= (DF & DF_MASK);
395     eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
396     if (env->eflags & VIF_MASK)
397         eflags |= IF_MASK;
398     T0 = eflags;
399 }
400 #endif
401
402 void OPPROTO op_clc(void)
403 {
404     int eflags;
405     eflags = cc_table[CC_OP].compute_all();
406     eflags &= ~CC_C;
407     CC_SRC = eflags;
408 }
409
410 void OPPROTO op_stc(void)
411 {
412     int eflags;
413     eflags = cc_table[CC_OP].compute_all();
414     eflags |= CC_C;
415     CC_SRC = eflags;
416 }
417
418 void OPPROTO op_cmc(void)
419 {
420     int eflags;
421     eflags = cc_table[CC_OP].compute_all();
422     eflags ^= CC_C;
423     CC_SRC = eflags;
424 }
425
426 void OPPROTO op_salc(void)
427 {
428     int cf;
429     cf = cc_table[CC_OP].compute_c();
430     EAX = (EAX & ~0xff) | ((-cf) & 0xff);
431 }