]> git.proxmox.com Git - qemu.git/blame - target-i386/op.c
converted BCD ops to TCG
[qemu.git] / target-i386 / op.c
CommitLineData
2c0262af
FB
1/*
2 * i386 micro operations
5fafdf24 3 *
2c0262af
FB
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 */
f68dd770 20
f68dd770 21#define ASM_SOFTMMU
2c0262af
FB
22#include "exec.h"
23
2c0262af
FB
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
14ce26e7
FB
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
2c0262af
FB
126/* constant load & misc op */
127
14ce26e7 128/* XXX: consistent names */
2c0262af
FB
129void 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
2c0262af
FB
139void OPPROTO op_cmpxchg8b(void)
140{
b8b6a50b 141 helper_cmpxchg8b(A0);
2c0262af
FB
142}
143
2c0262af
FB
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
14ce26e7
FB
160#ifdef TARGET_X86_64
161
162#define SHIFT 3
163#include "ops_template.h"
164#undef SHIFT
165
166#endif
167
2c0262af
FB
168/* segment handling */
169
2c0262af
FB
170/* faster VM86 version */
171void OPPROTO op_movl_seg_T0_vm(void)
172{
173 int selector;
174 SegmentCache *sc;
3b46e624 175
2c0262af
FB
176 selector = T0 & 0xffff;
177 /* env->segs[] access */
178 sc = (SegmentCache *)((char *)env + PARAM1);
179 sc->selector = selector;
14ce26e7 180 sc->base = (selector << 4);
2c0262af
FB
181}
182
183void OPPROTO op_movl_T0_seg(void)
184{
185 T0 = env->segs[PARAM1].selector;
186}
187
2c0262af
FB
188void OPPROTO op_lsl(void)
189{
b8b6a50b
FB
190 uint32_t val;
191 val = helper_lsl(T0);
192 if (CC_SRC & CC_Z)
193 T1 = val;
194 FORCE_RET();
2c0262af
FB
195}
196
197void OPPROTO op_lar(void)
198{
b8b6a50b
FB
199 uint32_t val;
200 val = helper_lar(T0);
201 if (CC_SRC & CC_Z)
202 T1 = val;
203 FORCE_RET();
2c0262af
FB
204}
205
3ab493de
FB
206void OPPROTO op_verr(void)
207{
b5b38f61 208 helper_verr(T0);
3ab493de
FB
209}
210
211void OPPROTO op_verw(void)
212{
b5b38f61 213 helper_verw(T0);
3ab493de
FB
214}
215
216void OPPROTO op_arpl(void)
217{
218 if ((T0 & 3) < (T1 & 3)) {
219 /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
220 T0 = (T0 & ~3) | (T1 & 3);
221 T1 = CC_Z;
222 } else {
223 T1 = 0;
224 }
225 FORCE_RET();
226}
3b46e624 227
3ab493de
FB
228void OPPROTO op_arpl_update(void)
229{
230 int eflags;
231 eflags = cc_table[CC_OP].compute_all();
232 CC_SRC = (eflags & ~CC_Z) | T1;
233}
3b46e624 234
2c0262af
FB
235void OPPROTO op_movl_T0_env(void)
236{
237 T0 = *(uint32_t *)((char *)env + PARAM1);
238}
239
240void OPPROTO op_movl_env_T0(void)
241{
242 *(uint32_t *)((char *)env + PARAM1) = T0;
243}
244
245void OPPROTO op_movl_env_T1(void)
246{
247 *(uint32_t *)((char *)env + PARAM1) = T1;
248}
249
14ce26e7
FB
250void OPPROTO op_movtl_T0_env(void)
251{
252 T0 = *(target_ulong *)((char *)env + PARAM1);
253}
254
255void OPPROTO op_movtl_env_T0(void)
256{
257 *(target_ulong *)((char *)env + PARAM1) = T0;
258}
259
260void OPPROTO op_movtl_T1_env(void)
261{
262 T1 = *(target_ulong *)((char *)env + PARAM1);
263}
264
265void OPPROTO op_movtl_env_T1(void)
266{
267 *(target_ulong *)((char *)env + PARAM1) = T1;
268}
269
2c0262af
FB
270/* flags handling */
271
14ce26e7
FB
272void OPPROTO op_jmp_label(void)
273{
274 GOTO_LABEL_PARAM(1);
2c0262af
FB
275}
276
14ce26e7 277void OPPROTO op_jnz_T0_label(void)
2c0262af
FB
278{
279 if (T0)
14ce26e7 280 GOTO_LABEL_PARAM(1);
39c61f49 281 FORCE_RET();
14ce26e7
FB
282}
283
2c0262af
FB
284/* slow set cases (compute x86 flags) */
285void OPPROTO op_seto_T0_cc(void)
286{
287 int eflags;
288 eflags = cc_table[CC_OP].compute_all();
289 T0 = (eflags >> 11) & 1;
290}
291
292void OPPROTO op_setb_T0_cc(void)
293{
294 T0 = cc_table[CC_OP].compute_c();
295}
296
297void OPPROTO op_setz_T0_cc(void)
298{
299 int eflags;
300 eflags = cc_table[CC_OP].compute_all();
301 T0 = (eflags >> 6) & 1;
302}
303
304void OPPROTO op_setbe_T0_cc(void)
305{
306 int eflags;
307 eflags = cc_table[CC_OP].compute_all();
308 T0 = (eflags & (CC_Z | CC_C)) != 0;
309}
310
311void OPPROTO op_sets_T0_cc(void)
312{
313 int eflags;
314 eflags = cc_table[CC_OP].compute_all();
315 T0 = (eflags >> 7) & 1;
316}
317
318void OPPROTO op_setp_T0_cc(void)
319{
320 int eflags;
321 eflags = cc_table[CC_OP].compute_all();
322 T0 = (eflags >> 2) & 1;
323}
324
325void OPPROTO op_setl_T0_cc(void)
326{
327 int eflags;
328 eflags = cc_table[CC_OP].compute_all();
329 T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
330}
331
332void OPPROTO op_setle_T0_cc(void)
333{
334 int eflags;
335 eflags = cc_table[CC_OP].compute_all();
336 T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
337}
338
339void OPPROTO op_xor_T0_1(void)
340{
341 T0 ^= 1;
342}
343
4136f33c 344/* XXX: clear VIF/VIP in all ops ? */
2c0262af
FB
345
346void OPPROTO op_movl_eflags_T0(void)
347{
4b7aba51 348 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK));
2c0262af
FB
349}
350
351void OPPROTO op_movw_eflags_T0(void)
352{
4b7aba51 353 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
4136f33c
FB
354}
355
356void OPPROTO op_movl_eflags_T0_io(void)
357{
4b7aba51 358 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK));
4136f33c
FB
359}
360
361void OPPROTO op_movw_eflags_T0_io(void)
362{
4b7aba51 363 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
2c0262af
FB
364}
365
366void OPPROTO op_movl_eflags_T0_cpl0(void)
367{
4b7aba51 368 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK));
2c0262af
FB
369}
370
371void OPPROTO op_movw_eflags_T0_cpl0(void)
372{
4b7aba51 373 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
2c0262af
FB
374}
375
376#if 0
377/* vm86plus version */
378void OPPROTO op_movw_eflags_T0_vm(void)
379{
380 int eflags;
381 eflags = T0;
382 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
383 DF = 1 - (2 * ((eflags >> 10) & 1));
384 /* we also update some system flags as in user mode */
385 env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
386 (eflags & FL_UPDATE_MASK16);
387 if (eflags & IF_MASK) {
388 env->eflags |= VIF_MASK;
389 if (env->eflags & VIP_MASK) {
390 EIP = PARAM1;
391 raise_exception(EXCP0D_GPF);
392 }
393 }
394 FORCE_RET();
395}
396
397void OPPROTO op_movl_eflags_T0_vm(void)
398{
399 int eflags;
400 eflags = T0;
401 CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
402 DF = 1 - (2 * ((eflags >> 10) & 1));
403 /* we also update some system flags as in user mode */
404 env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
405 (eflags & FL_UPDATE_MASK32);
406 if (eflags & IF_MASK) {
407 env->eflags |= VIF_MASK;
408 if (env->eflags & VIP_MASK) {
409 EIP = PARAM1;
410 raise_exception(EXCP0D_GPF);
411 }
412 }
413 FORCE_RET();
414}
415#endif
416
417/* XXX: compute only O flag */
418void OPPROTO op_movb_eflags_T0(void)
419{
420 int of;
421 of = cc_table[CC_OP].compute_all() & CC_O;
422 CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of;
423}
424
425void OPPROTO op_movl_T0_eflags(void)
426{
427 int eflags;
428 eflags = cc_table[CC_OP].compute_all();
429 eflags |= (DF & DF_MASK);
430 eflags |= env->eflags & ~(VM_MASK | RF_MASK);
431 T0 = eflags;
432}
433
434/* vm86plus version */
435#if 0
436void OPPROTO op_movl_T0_eflags_vm(void)
437{
438 int eflags;
439 eflags = cc_table[CC_OP].compute_all();
440 eflags |= (DF & DF_MASK);
441 eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
442 if (env->eflags & VIF_MASK)
443 eflags |= IF_MASK;
444 T0 = eflags;
445}
446#endif
447
2c0262af
FB
448void OPPROTO op_clc(void)
449{
450 int eflags;
451 eflags = cc_table[CC_OP].compute_all();
452 eflags &= ~CC_C;
453 CC_SRC = eflags;
454}
455
456void OPPROTO op_stc(void)
457{
458 int eflags;
459 eflags = cc_table[CC_OP].compute_all();
460 eflags |= CC_C;
461 CC_SRC = eflags;
462}
463
464void OPPROTO op_cmc(void)
465{
466 int eflags;
467 eflags = cc_table[CC_OP].compute_all();
468 eflags ^= CC_C;
469 CC_SRC = eflags;
470}
471
472void OPPROTO op_salc(void)
473{
474 int cf;
475 cf = cc_table[CC_OP].compute_c();
476 EAX = (EAX & ~0xff) | ((-cf) & 0xff);
477}
478
19e6c4b8 479void OPPROTO op_fcomi_dummy(void)
2c0262af 480{
19e6c4b8 481 T0 = 0;
2c0262af
FB
482}
483
14ce26e7 484/* SSE support */
5af45186 485void OPPROTO op_com_dummy(void)
14ce26e7 486{
5af45186 487 T0 = 0;
664e0f19 488}