xref: /qemu/target/i386/emulate/x86_emu.c (revision 63d8bc669302ec22bd394c45380848a2d5947943)
1c97d6d2cSSergio Andres Gomez Del Real /*
2c97d6d2cSSergio Andres Gomez Del Real  * Copyright (C) 2016 Veertu Inc,
3c97d6d2cSSergio Andres Gomez Del Real  * Copyright (C) 2017 Google Inc,
4c97d6d2cSSergio Andres Gomez Del Real  *
5c97d6d2cSSergio Andres Gomez Del Real  * This program is free software; you can redistribute it and/or
6996feed4SSergio Andres Gomez Del Real  * modify it under the terms of the GNU Lesser General Public
7996feed4SSergio Andres Gomez Del Real  * License as published by the Free Software Foundation; either
88af82b8eSChetan Pant  * version 2.1 of the License, or (at your option) any later version.
9c97d6d2cSSergio Andres Gomez Del Real  *
10c97d6d2cSSergio Andres Gomez Del Real  * This program is distributed in the hope that it will be useful,
11c97d6d2cSSergio Andres Gomez Del Real  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12996feed4SSergio Andres Gomez Del Real  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13996feed4SSergio Andres Gomez Del Real  * Lesser General Public License for more details.
14c97d6d2cSSergio Andres Gomez Del Real  *
15996feed4SSergio Andres Gomez Del Real  * You should have received a copy of the GNU Lesser General Public
16996feed4SSergio Andres Gomez Del Real  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
17c97d6d2cSSergio Andres Gomez Del Real  */
18c97d6d2cSSergio Andres Gomez Del Real 
19c97d6d2cSSergio Andres Gomez Del Real /////////////////////////////////////////////////////////////////////////
20c97d6d2cSSergio Andres Gomez Del Real //
21c97d6d2cSSergio Andres Gomez Del Real //  Copyright (C) 2001-2012  The Bochs Project
22c97d6d2cSSergio Andres Gomez Del Real //
23c97d6d2cSSergio Andres Gomez Del Real //  This library is free software; you can redistribute it and/or
24c97d6d2cSSergio Andres Gomez Del Real //  modify it under the terms of the GNU Lesser General Public
25c97d6d2cSSergio Andres Gomez Del Real //  License as published by the Free Software Foundation; either
268af82b8eSChetan Pant //  version 2.1 of the License, or (at your option) any later version.
27c97d6d2cSSergio Andres Gomez Del Real //
28c97d6d2cSSergio Andres Gomez Del Real //  This library is distributed in the hope that it will be useful,
29c97d6d2cSSergio Andres Gomez Del Real //  but WITHOUT ANY WARRANTY; without even the implied warranty of
30c97d6d2cSSergio Andres Gomez Del Real //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
31c97d6d2cSSergio Andres Gomez Del Real //  Lesser General Public License for more details.
32c97d6d2cSSergio Andres Gomez Del Real //
33c97d6d2cSSergio Andres Gomez Del Real //  You should have received a copy of the GNU Lesser General Public
34c97d6d2cSSergio Andres Gomez Del Real //  License along with this library; if not, write to the Free Software
35c97d6d2cSSergio Andres Gomez Del Real //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
36c97d6d2cSSergio Andres Gomez Del Real /////////////////////////////////////////////////////////////////////////
37c97d6d2cSSergio Andres Gomez Del Real 
38c97d6d2cSSergio Andres Gomez Del Real #include "qemu/osdep.h"
39895f9fdfSPaolo Bonzini #include "panic.h"
40c97d6d2cSSergio Andres Gomez Del Real #include "x86_decode.h"
41c97d6d2cSSergio Andres Gomez Del Real #include "x86.h"
42c97d6d2cSSergio Andres Gomez Del Real #include "x86_emu.h"
43c97d6d2cSSergio Andres Gomez Del Real #include "x86_mmu.h"
44c97d6d2cSSergio Andres Gomez Del Real #include "x86_flags.h"
45c97d6d2cSSergio Andres Gomez Del Real #include "vmcs.h"
46c97d6d2cSSergio Andres Gomez Del Real #include "vmx.h"
47bc4fa8c3SWei Liu #include "hvf-i386.h"
48c97d6d2cSSergio Andres Gomez Del Real 
49e8a63257SPaolo Bonzini #define EXEC_2OP_FLAGS_CMD(env, decode, cmd, FLAGS_FUNC, save_res) \
50c97d6d2cSSergio Andres Gomez Del Real {                                                       \
51c97d6d2cSSergio Andres Gomez Del Real     fetch_operands(env, decode, 2, true, true, false);  \
52c97d6d2cSSergio Andres Gomez Del Real     switch (decode->operand_size) {                     \
53c97d6d2cSSergio Andres Gomez Del Real     case 1:                                         \
54c97d6d2cSSergio Andres Gomez Del Real     {                                               \
55c97d6d2cSSergio Andres Gomez Del Real         uint8_t v1 = (uint8_t)decode->op[0].val;    \
56c97d6d2cSSergio Andres Gomez Del Real         uint8_t v2 = (uint8_t)decode->op[1].val;    \
57c97d6d2cSSergio Andres Gomez Del Real         uint8_t diff = v1 cmd v2;                   \
58c97d6d2cSSergio Andres Gomez Del Real         if (save_res) {                              \
59c97d6d2cSSergio Andres Gomez Del Real             write_val_ext(env, decode->op[0].ptr, diff, 1);  \
60c97d6d2cSSergio Andres Gomez Del Real         } \
61e8a63257SPaolo Bonzini         FLAGS_FUNC##8(env, v1, v2, diff);           \
62c97d6d2cSSergio Andres Gomez Del Real         break;                                      \
63c97d6d2cSSergio Andres Gomez Del Real     }                                               \
64c97d6d2cSSergio Andres Gomez Del Real     case 2:                                        \
65c97d6d2cSSergio Andres Gomez Del Real     {                                               \
66c97d6d2cSSergio Andres Gomez Del Real         uint16_t v1 = (uint16_t)decode->op[0].val;  \
67c97d6d2cSSergio Andres Gomez Del Real         uint16_t v2 = (uint16_t)decode->op[1].val;  \
68c97d6d2cSSergio Andres Gomez Del Real         uint16_t diff = v1 cmd v2;                  \
69c97d6d2cSSergio Andres Gomez Del Real         if (save_res) {                              \
70c97d6d2cSSergio Andres Gomez Del Real             write_val_ext(env, decode->op[0].ptr, diff, 2); \
71c97d6d2cSSergio Andres Gomez Del Real         } \
72e8a63257SPaolo Bonzini         FLAGS_FUNC##16(env, v1, v2, diff);          \
73c97d6d2cSSergio Andres Gomez Del Real         break;                                      \
74c97d6d2cSSergio Andres Gomez Del Real     }                                               \
75c97d6d2cSSergio Andres Gomez Del Real     case 4:                                        \
76c97d6d2cSSergio Andres Gomez Del Real     {                                               \
77c97d6d2cSSergio Andres Gomez Del Real         uint32_t v1 = (uint32_t)decode->op[0].val;  \
78c97d6d2cSSergio Andres Gomez Del Real         uint32_t v2 = (uint32_t)decode->op[1].val;  \
79c97d6d2cSSergio Andres Gomez Del Real         uint32_t diff = v1 cmd v2;                  \
80c97d6d2cSSergio Andres Gomez Del Real         if (save_res) {                              \
81c97d6d2cSSergio Andres Gomez Del Real             write_val_ext(env, decode->op[0].ptr, diff, 4); \
82c97d6d2cSSergio Andres Gomez Del Real         } \
83e8a63257SPaolo Bonzini         FLAGS_FUNC##32(env, v1, v2, diff);          \
84c97d6d2cSSergio Andres Gomez Del Real         break;                                      \
85c97d6d2cSSergio Andres Gomez Del Real     }                                               \
86c97d6d2cSSergio Andres Gomez Del Real     default:                                        \
87c97d6d2cSSergio Andres Gomez Del Real         VM_PANIC("bad size\n");                    \
88c97d6d2cSSergio Andres Gomez Del Real     }                                                   \
89c97d6d2cSSergio Andres Gomez Del Real }                                                       \
90c97d6d2cSSergio Andres Gomez Del Real 
91ff2de166SPaolo Bonzini target_ulong read_reg(CPUX86State *env, int reg, int size)
92c97d6d2cSSergio Andres Gomez Del Real {
93c97d6d2cSSergio Andres Gomez Del Real     switch (size) {
94c97d6d2cSSergio Andres Gomez Del Real     case 1:
95167c6aefSRoman Bolshakov         return x86_reg(env, reg)->lx;
96c97d6d2cSSergio Andres Gomez Del Real     case 2:
97167c6aefSRoman Bolshakov         return x86_reg(env, reg)->rx;
98c97d6d2cSSergio Andres Gomez Del Real     case 4:
99167c6aefSRoman Bolshakov         return x86_reg(env, reg)->erx;
100c97d6d2cSSergio Andres Gomez Del Real     case 8:
101167c6aefSRoman Bolshakov         return x86_reg(env, reg)->rrx;
102c97d6d2cSSergio Andres Gomez Del Real     default:
103e62963bfSPaolo Bonzini         abort();
104c97d6d2cSSergio Andres Gomez Del Real     }
105c97d6d2cSSergio Andres Gomez Del Real     return 0;
106c97d6d2cSSergio Andres Gomez Del Real }
107c97d6d2cSSergio Andres Gomez Del Real 
108ff2de166SPaolo Bonzini void write_reg(CPUX86State *env, int reg, target_ulong val, int size)
109c97d6d2cSSergio Andres Gomez Del Real {
110c97d6d2cSSergio Andres Gomez Del Real     switch (size) {
111c97d6d2cSSergio Andres Gomez Del Real     case 1:
112167c6aefSRoman Bolshakov         x86_reg(env, reg)->lx = val;
113c97d6d2cSSergio Andres Gomez Del Real         break;
114c97d6d2cSSergio Andres Gomez Del Real     case 2:
115167c6aefSRoman Bolshakov         x86_reg(env, reg)->rx = val;
116c97d6d2cSSergio Andres Gomez Del Real         break;
117c97d6d2cSSergio Andres Gomez Del Real     case 4:
118167c6aefSRoman Bolshakov         x86_reg(env, reg)->rrx = (uint32_t)val;
119c97d6d2cSSergio Andres Gomez Del Real         break;
120c97d6d2cSSergio Andres Gomez Del Real     case 8:
121167c6aefSRoman Bolshakov         x86_reg(env, reg)->rrx = val;
122c97d6d2cSSergio Andres Gomez Del Real         break;
123c97d6d2cSSergio Andres Gomez Del Real     default:
124e62963bfSPaolo Bonzini         abort();
125c97d6d2cSSergio Andres Gomez Del Real     }
126c97d6d2cSSergio Andres Gomez Del Real }
127c97d6d2cSSergio Andres Gomez Del Real 
128ff2de166SPaolo Bonzini target_ulong read_val_from_reg(target_ulong reg_ptr, int size)
129c97d6d2cSSergio Andres Gomez Del Real {
130ff2de166SPaolo Bonzini     target_ulong val;
131c97d6d2cSSergio Andres Gomez Del Real 
132c97d6d2cSSergio Andres Gomez Del Real     switch (size) {
133c97d6d2cSSergio Andres Gomez Del Real     case 1:
134c97d6d2cSSergio Andres Gomez Del Real         val = *(uint8_t *)reg_ptr;
135c97d6d2cSSergio Andres Gomez Del Real         break;
136c97d6d2cSSergio Andres Gomez Del Real     case 2:
137c97d6d2cSSergio Andres Gomez Del Real         val = *(uint16_t *)reg_ptr;
138c97d6d2cSSergio Andres Gomez Del Real         break;
139c97d6d2cSSergio Andres Gomez Del Real     case 4:
140c97d6d2cSSergio Andres Gomez Del Real         val = *(uint32_t *)reg_ptr;
141c97d6d2cSSergio Andres Gomez Del Real         break;
142c97d6d2cSSergio Andres Gomez Del Real     case 8:
143c97d6d2cSSergio Andres Gomez Del Real         val = *(uint64_t *)reg_ptr;
144c97d6d2cSSergio Andres Gomez Del Real         break;
145c97d6d2cSSergio Andres Gomez Del Real     default:
146e62963bfSPaolo Bonzini         abort();
147c97d6d2cSSergio Andres Gomez Del Real     }
148c97d6d2cSSergio Andres Gomez Del Real     return val;
149c97d6d2cSSergio Andres Gomez Del Real }
150c97d6d2cSSergio Andres Gomez Del Real 
151ff2de166SPaolo Bonzini void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size)
152c97d6d2cSSergio Andres Gomez Del Real {
153c97d6d2cSSergio Andres Gomez Del Real     switch (size) {
154c97d6d2cSSergio Andres Gomez Del Real     case 1:
155c97d6d2cSSergio Andres Gomez Del Real         *(uint8_t *)reg_ptr = val;
156c97d6d2cSSergio Andres Gomez Del Real         break;
157c97d6d2cSSergio Andres Gomez Del Real     case 2:
158c97d6d2cSSergio Andres Gomez Del Real         *(uint16_t *)reg_ptr = val;
159c97d6d2cSSergio Andres Gomez Del Real         break;
160c97d6d2cSSergio Andres Gomez Del Real     case 4:
161c97d6d2cSSergio Andres Gomez Del Real         *(uint64_t *)reg_ptr = (uint32_t)val;
162c97d6d2cSSergio Andres Gomez Del Real         break;
163c97d6d2cSSergio Andres Gomez Del Real     case 8:
164c97d6d2cSSergio Andres Gomez Del Real         *(uint64_t *)reg_ptr = val;
165c97d6d2cSSergio Andres Gomez Del Real         break;
166c97d6d2cSSergio Andres Gomez Del Real     default:
167e62963bfSPaolo Bonzini         abort();
168c97d6d2cSSergio Andres Gomez Del Real     }
169c97d6d2cSSergio Andres Gomez Del Real }
170c97d6d2cSSergio Andres Gomez Del Real 
17136861198SPhilippe Mathieu-Daudé static bool is_host_reg(CPUX86State *env, target_ulong ptr)
172c97d6d2cSSergio Andres Gomez Del Real {
173167c6aefSRoman Bolshakov     return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs);
174c97d6d2cSSergio Andres Gomez Del Real }
175c97d6d2cSSergio Andres Gomez Del Real 
17636861198SPhilippe Mathieu-Daudé void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size)
177c97d6d2cSSergio Andres Gomez Del Real {
178c97d6d2cSSergio Andres Gomez Del Real     if (is_host_reg(env, ptr)) {
179c97d6d2cSSergio Andres Gomez Del Real         write_val_to_reg(ptr, val, size);
180c97d6d2cSSergio Andres Gomez Del Real         return;
181c97d6d2cSSergio Andres Gomez Del Real     }
182*63d8bc66SWei Liu     emul_ops->write_mem(env_cpu(env), &val, ptr, size);
183c97d6d2cSSergio Andres Gomez Del Real }
184c97d6d2cSSergio Andres Gomez Del Real 
18536861198SPhilippe Mathieu-Daudé uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes)
186c97d6d2cSSergio Andres Gomez Del Real {
187ae3c6134SWei Liu     emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, ptr, bytes);
188e9c40026SWei Liu     return env->emu_mmio_buf;
189c97d6d2cSSergio Andres Gomez Del Real }
190c97d6d2cSSergio Andres Gomez Del Real 
191c97d6d2cSSergio Andres Gomez Del Real 
19236861198SPhilippe Mathieu-Daudé target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size)
193c97d6d2cSSergio Andres Gomez Del Real {
194ff2de166SPaolo Bonzini     target_ulong val;
195c97d6d2cSSergio Andres Gomez Del Real     uint8_t *mmio_ptr;
196c97d6d2cSSergio Andres Gomez Del Real 
197c97d6d2cSSergio Andres Gomez Del Real     if (is_host_reg(env, ptr)) {
198c97d6d2cSSergio Andres Gomez Del Real         return read_val_from_reg(ptr, size);
199c97d6d2cSSergio Andres Gomez Del Real     }
200c97d6d2cSSergio Andres Gomez Del Real 
201c97d6d2cSSergio Andres Gomez Del Real     mmio_ptr = read_mmio(env, ptr, size);
202c97d6d2cSSergio Andres Gomez Del Real     switch (size) {
203c97d6d2cSSergio Andres Gomez Del Real     case 1:
204c97d6d2cSSergio Andres Gomez Del Real         val = *(uint8_t *)mmio_ptr;
205c97d6d2cSSergio Andres Gomez Del Real         break;
206c97d6d2cSSergio Andres Gomez Del Real     case 2:
207c97d6d2cSSergio Andres Gomez Del Real         val = *(uint16_t *)mmio_ptr;
208c97d6d2cSSergio Andres Gomez Del Real         break;
209c97d6d2cSSergio Andres Gomez Del Real     case 4:
210c97d6d2cSSergio Andres Gomez Del Real         val = *(uint32_t *)mmio_ptr;
211c97d6d2cSSergio Andres Gomez Del Real         break;
212c97d6d2cSSergio Andres Gomez Del Real     case 8:
213c97d6d2cSSergio Andres Gomez Del Real         val = *(uint64_t *)mmio_ptr;
214c97d6d2cSSergio Andres Gomez Del Real         break;
215c97d6d2cSSergio Andres Gomez Del Real     default:
216c97d6d2cSSergio Andres Gomez Del Real         VM_PANIC("bad size\n");
217c97d6d2cSSergio Andres Gomez Del Real         break;
218c97d6d2cSSergio Andres Gomez Del Real     }
219c97d6d2cSSergio Andres Gomez Del Real     return val;
220c97d6d2cSSergio Andres Gomez Del Real }
221c97d6d2cSSergio Andres Gomez Del Real 
22236861198SPhilippe Mathieu-Daudé static void fetch_operands(CPUX86State *env, struct x86_decode *decode,
223c97d6d2cSSergio Andres Gomez Del Real                            int n, bool val_op0, bool val_op1, bool val_op2)
224c97d6d2cSSergio Andres Gomez Del Real {
225c97d6d2cSSergio Andres Gomez Del Real     int i;
226c97d6d2cSSergio Andres Gomez Del Real     bool calc_val[3] = {val_op0, val_op1, val_op2};
227c97d6d2cSSergio Andres Gomez Del Real 
228c97d6d2cSSergio Andres Gomez Del Real     for (i = 0; i < n; i++) {
229c97d6d2cSSergio Andres Gomez Del Real         switch (decode->op[i].type) {
230c97d6d2cSSergio Andres Gomez Del Real         case X86_VAR_IMMEDIATE:
231c97d6d2cSSergio Andres Gomez Del Real             break;
232c97d6d2cSSergio Andres Gomez Del Real         case X86_VAR_REG:
233c97d6d2cSSergio Andres Gomez Del Real             VM_PANIC_ON(!decode->op[i].ptr);
234c97d6d2cSSergio Andres Gomez Del Real             if (calc_val[i]) {
235c97d6d2cSSergio Andres Gomez Del Real                 decode->op[i].val = read_val_from_reg(decode->op[i].ptr,
236c97d6d2cSSergio Andres Gomez Del Real                                                       decode->operand_size);
237c97d6d2cSSergio Andres Gomez Del Real             }
238c97d6d2cSSergio Andres Gomez Del Real             break;
239c97d6d2cSSergio Andres Gomez Del Real         case X86_VAR_RM:
240c97d6d2cSSergio Andres Gomez Del Real             calc_modrm_operand(env, decode, &decode->op[i]);
241c97d6d2cSSergio Andres Gomez Del Real             if (calc_val[i]) {
242c97d6d2cSSergio Andres Gomez Del Real                 decode->op[i].val = read_val_ext(env, decode->op[i].ptr,
243c97d6d2cSSergio Andres Gomez Del Real                                                  decode->operand_size);
244c97d6d2cSSergio Andres Gomez Del Real             }
245c97d6d2cSSergio Andres Gomez Del Real             break;
246c97d6d2cSSergio Andres Gomez Del Real         case X86_VAR_OFFSET:
247c97d6d2cSSergio Andres Gomez Del Real             decode->op[i].ptr = decode_linear_addr(env, decode,
248c97d6d2cSSergio Andres Gomez Del Real                                                    decode->op[i].ptr,
2496701d81dSPaolo Bonzini                                                    R_DS);
250c97d6d2cSSergio Andres Gomez Del Real             if (calc_val[i]) {
251c97d6d2cSSergio Andres Gomez Del Real                 decode->op[i].val = read_val_ext(env, decode->op[i].ptr,
252c97d6d2cSSergio Andres Gomez Del Real                                                  decode->operand_size);
253c97d6d2cSSergio Andres Gomez Del Real             }
254c97d6d2cSSergio Andres Gomez Del Real             break;
255c97d6d2cSSergio Andres Gomez Del Real         default:
256c97d6d2cSSergio Andres Gomez Del Real             break;
257c97d6d2cSSergio Andres Gomez Del Real         }
258c97d6d2cSSergio Andres Gomez Del Real     }
259c97d6d2cSSergio Andres Gomez Del Real }
260c97d6d2cSSergio Andres Gomez Del Real 
26136861198SPhilippe Mathieu-Daudé static void exec_mov(CPUX86State *env, struct x86_decode *decode)
262c97d6d2cSSergio Andres Gomez Del Real {
263c97d6d2cSSergio Andres Gomez Del Real     fetch_operands(env, decode, 2, false, true, false);
264c97d6d2cSSergio Andres Gomez Del Real     write_val_ext(env, decode->op[0].ptr, decode->op[1].val,
265c97d6d2cSSergio Andres Gomez Del Real                   decode->operand_size);
266c97d6d2cSSergio Andres Gomez Del Real 
2675d32173fSRoman Bolshakov     env->eip += decode->len;
268c97d6d2cSSergio Andres Gomez Del Real }
269c97d6d2cSSergio Andres Gomez Del Real 
27036861198SPhilippe Mathieu-Daudé static void exec_add(CPUX86State *env, struct x86_decode *decode)
271c97d6d2cSSergio Andres Gomez Del Real {
272e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
2735d32173fSRoman Bolshakov     env->eip += decode->len;
274c97d6d2cSSergio Andres Gomez Del Real }
275c97d6d2cSSergio Andres Gomez Del Real 
27636861198SPhilippe Mathieu-Daudé static void exec_or(CPUX86State *env, struct x86_decode *decode)
277c97d6d2cSSergio Andres Gomez Del Real {
278e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true);
2795d32173fSRoman Bolshakov     env->eip += decode->len;
280c97d6d2cSSergio Andres Gomez Del Real }
281c97d6d2cSSergio Andres Gomez Del Real 
28236861198SPhilippe Mathieu-Daudé static void exec_adc(CPUX86State *env, struct x86_decode *decode)
283c97d6d2cSSergio Andres Gomez Del Real {
284e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true);
2855d32173fSRoman Bolshakov     env->eip += decode->len;
286c97d6d2cSSergio Andres Gomez Del Real }
287c97d6d2cSSergio Andres Gomez Del Real 
28836861198SPhilippe Mathieu-Daudé static void exec_sbb(CPUX86State *env, struct x86_decode *decode)
289c97d6d2cSSergio Andres Gomez Del Real {
290e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true);
2915d32173fSRoman Bolshakov     env->eip += decode->len;
292c97d6d2cSSergio Andres Gomez Del Real }
293c97d6d2cSSergio Andres Gomez Del Real 
29436861198SPhilippe Mathieu-Daudé static void exec_and(CPUX86State *env, struct x86_decode *decode)
295c97d6d2cSSergio Andres Gomez Del Real {
296e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true);
2975d32173fSRoman Bolshakov     env->eip += decode->len;
298c97d6d2cSSergio Andres Gomez Del Real }
299c97d6d2cSSergio Andres Gomez Del Real 
30036861198SPhilippe Mathieu-Daudé static void exec_sub(CPUX86State *env, struct x86_decode *decode)
301c97d6d2cSSergio Andres Gomez Del Real {
302e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true);
3035d32173fSRoman Bolshakov     env->eip += decode->len;
304c97d6d2cSSergio Andres Gomez Del Real }
305c97d6d2cSSergio Andres Gomez Del Real 
30636861198SPhilippe Mathieu-Daudé static void exec_xor(CPUX86State *env, struct x86_decode *decode)
307c97d6d2cSSergio Andres Gomez Del Real {
308e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true);
3095d32173fSRoman Bolshakov     env->eip += decode->len;
310c97d6d2cSSergio Andres Gomez Del Real }
311c97d6d2cSSergio Andres Gomez Del Real 
31236861198SPhilippe Mathieu-Daudé static void exec_neg(CPUX86State *env, struct x86_decode *decode)
313c97d6d2cSSergio Andres Gomez Del Real {
314e8a63257SPaolo Bonzini     /*EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/
315c97d6d2cSSergio Andres Gomez Del Real     int32_t val;
316c97d6d2cSSergio Andres Gomez Del Real     fetch_operands(env, decode, 2, true, true, false);
317c97d6d2cSSergio Andres Gomez Del Real 
318c97d6d2cSSergio Andres Gomez Del Real     val = 0 - sign(decode->op[1].val, decode->operand_size);
319c97d6d2cSSergio Andres Gomez Del Real     write_val_ext(env, decode->op[1].ptr, val, decode->operand_size);
320c97d6d2cSSergio Andres Gomez Del Real 
321c97d6d2cSSergio Andres Gomez Del Real     if (4 == decode->operand_size) {
322e8a63257SPaolo Bonzini         SET_FLAGS_OSZAPC_SUB32(env, 0, 0 - val, val);
323c97d6d2cSSergio Andres Gomez Del Real     } else if (2 == decode->operand_size) {
324e8a63257SPaolo Bonzini         SET_FLAGS_OSZAPC_SUB16(env, 0, 0 - val, val);
325c97d6d2cSSergio Andres Gomez Del Real     } else if (1 == decode->operand_size) {
326e8a63257SPaolo Bonzini         SET_FLAGS_OSZAPC_SUB8(env, 0, 0 - val, val);
327c97d6d2cSSergio Andres Gomez Del Real     } else {
328c97d6d2cSSergio Andres Gomez Del Real         VM_PANIC("bad op size\n");
329c97d6d2cSSergio Andres Gomez Del Real     }
330c97d6d2cSSergio Andres Gomez Del Real 
331c97d6d2cSSergio Andres Gomez Del Real     /*lflags_to_rflags(env);*/
3325d32173fSRoman Bolshakov     env->eip += decode->len;
333c97d6d2cSSergio Andres Gomez Del Real }
334c97d6d2cSSergio Andres Gomez Del Real 
33536861198SPhilippe Mathieu-Daudé static void exec_cmp(CPUX86State *env, struct x86_decode *decode)
336c97d6d2cSSergio Andres Gomez Del Real {
337e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
3385d32173fSRoman Bolshakov     env->eip += decode->len;
339c97d6d2cSSergio Andres Gomez Del Real }
340c97d6d2cSSergio Andres Gomez Del Real 
34136861198SPhilippe Mathieu-Daudé static void exec_inc(CPUX86State *env, struct x86_decode *decode)
342c97d6d2cSSergio Andres Gomez Del Real {
343c97d6d2cSSergio Andres Gomez Del Real     decode->op[1].type = X86_VAR_IMMEDIATE;
344c97d6d2cSSergio Andres Gomez Del Real     decode->op[1].val = 0;
345c97d6d2cSSergio Andres Gomez Del Real 
346e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, +1+, SET_FLAGS_OSZAP_ADD, true);
347c97d6d2cSSergio Andres Gomez Del Real 
3485d32173fSRoman Bolshakov     env->eip += decode->len;
349c97d6d2cSSergio Andres Gomez Del Real }
350c97d6d2cSSergio Andres Gomez Del Real 
35136861198SPhilippe Mathieu-Daudé static void exec_dec(CPUX86State *env, struct x86_decode *decode)
352c97d6d2cSSergio Andres Gomez Del Real {
353c97d6d2cSSergio Andres Gomez Del Real     decode->op[1].type = X86_VAR_IMMEDIATE;
354c97d6d2cSSergio Andres Gomez Del Real     decode->op[1].val = 0;
355c97d6d2cSSergio Andres Gomez Del Real 
356e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, -1-, SET_FLAGS_OSZAP_SUB, true);
3575d32173fSRoman Bolshakov     env->eip += decode->len;
358c97d6d2cSSergio Andres Gomez Del Real }
359c97d6d2cSSergio Andres Gomez Del Real 
36036861198SPhilippe Mathieu-Daudé static void exec_tst(CPUX86State *env, struct x86_decode *decode)
361c97d6d2cSSergio Andres Gomez Del Real {
362e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false);
3635d32173fSRoman Bolshakov     env->eip += decode->len;
364c97d6d2cSSergio Andres Gomez Del Real }
365c97d6d2cSSergio Andres Gomez Del Real 
36636861198SPhilippe Mathieu-Daudé static void exec_not(CPUX86State *env, struct x86_decode *decode)
367c97d6d2cSSergio Andres Gomez Del Real {
368c97d6d2cSSergio Andres Gomez Del Real     fetch_operands(env, decode, 1, true, false, false);
369c97d6d2cSSergio Andres Gomez Del Real 
370c97d6d2cSSergio Andres Gomez Del Real     write_val_ext(env, decode->op[0].ptr, ~decode->op[0].val,
371c97d6d2cSSergio Andres Gomez Del Real                   decode->operand_size);
3725d32173fSRoman Bolshakov     env->eip += decode->len;
373c97d6d2cSSergio Andres Gomez Del Real }
374c97d6d2cSSergio Andres Gomez Del Real 
37536861198SPhilippe Mathieu-Daudé void exec_movzx(CPUX86State *env, struct x86_decode *decode)
376c97d6d2cSSergio Andres Gomez Del Real {
377c97d6d2cSSergio Andres Gomez Del Real     int src_op_size;
378c97d6d2cSSergio Andres Gomez Del Real     int op_size = decode->operand_size;
379c97d6d2cSSergio Andres Gomez Del Real 
380c97d6d2cSSergio Andres Gomez Del Real     fetch_operands(env, decode, 1, false, false, false);
381c97d6d2cSSergio Andres Gomez Del Real 
382c97d6d2cSSergio Andres Gomez Del Real     if (0xb6 == decode->opcode[1]) {
383c97d6d2cSSergio Andres Gomez Del Real         src_op_size = 1;
384c97d6d2cSSergio Andres Gomez Del Real     } else {
385c97d6d2cSSergio Andres Gomez Del Real         src_op_size = 2;
386c97d6d2cSSergio Andres Gomez Del Real     }
387c97d6d2cSSergio Andres Gomez Del Real     decode->operand_size = src_op_size;
388c97d6d2cSSergio Andres Gomez Del Real     calc_modrm_operand(env, decode, &decode->op[1]);
389c97d6d2cSSergio Andres Gomez Del Real     decode->op[1].val = read_val_ext(env, decode->op[1].ptr, src_op_size);
390c97d6d2cSSergio Andres Gomez Del Real     write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size);
391c97d6d2cSSergio Andres Gomez Del Real 
3925d32173fSRoman Bolshakov     env->eip += decode->len;
393c97d6d2cSSergio Andres Gomez Del Real }
394c97d6d2cSSergio Andres Gomez Del Real 
39536861198SPhilippe Mathieu-Daudé static void exec_out(CPUX86State *env, struct x86_decode *decode)
396c97d6d2cSSergio Andres Gomez Del Real {
397c97d6d2cSSergio Andres Gomez Del Real     switch (decode->opcode[0]) {
398c97d6d2cSSergio Andres Gomez Del Real     case 0xe6:
399444bae08SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 1, 1, 1);
400c97d6d2cSSergio Andres Gomez Del Real         break;
401c97d6d2cSSergio Andres Gomez Del Real     case 0xe7:
402444bae08SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &RAX(env), 1,
403c97d6d2cSSergio Andres Gomez Del Real                             decode->operand_size, 1);
404c97d6d2cSSergio Andres Gomez Del Real         break;
405c97d6d2cSSergio Andres Gomez Del Real     case 0xee:
406444bae08SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 1, 1, 1);
407c97d6d2cSSergio Andres Gomez Del Real         break;
408c97d6d2cSSergio Andres Gomez Del Real     case 0xef:
409444bae08SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &RAX(env), 1,
41029a0af61SRichard Henderson                             decode->operand_size, 1);
411c97d6d2cSSergio Andres Gomez Del Real         break;
412c97d6d2cSSergio Andres Gomez Del Real     default:
413c97d6d2cSSergio Andres Gomez Del Real         VM_PANIC("Bad out opcode\n");
414c97d6d2cSSergio Andres Gomez Del Real         break;
415c97d6d2cSSergio Andres Gomez Del Real     }
4165d32173fSRoman Bolshakov     env->eip += decode->len;
417c97d6d2cSSergio Andres Gomez Del Real }
418c97d6d2cSSergio Andres Gomez Del Real 
41936861198SPhilippe Mathieu-Daudé static void exec_in(CPUX86State *env, struct x86_decode *decode)
420c97d6d2cSSergio Andres Gomez Del Real {
421ff2de166SPaolo Bonzini     target_ulong val = 0;
422c97d6d2cSSergio Andres Gomez Del Real     switch (decode->opcode[0]) {
423c97d6d2cSSergio Andres Gomez Del Real     case 0xe4:
424444bae08SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &AL(env), 0, 1, 1);
425c97d6d2cSSergio Andres Gomez Del Real         break;
426c97d6d2cSSergio Andres Gomez Del Real     case 0xe5:
427444bae08SWei Liu         emul_ops->handle_io(env_cpu(env), decode->op[0].val, &val, 0,
42829a0af61SRichard Henderson                       decode->operand_size, 1);
429c97d6d2cSSergio Andres Gomez Del Real         if (decode->operand_size == 2) {
430c97d6d2cSSergio Andres Gomez Del Real             AX(env) = val;
431c97d6d2cSSergio Andres Gomez Del Real         } else {
432c97d6d2cSSergio Andres Gomez Del Real             RAX(env) = (uint32_t)val;
433c97d6d2cSSergio Andres Gomez Del Real         }
434c97d6d2cSSergio Andres Gomez Del Real         break;
435c97d6d2cSSergio Andres Gomez Del Real     case 0xec:
436444bae08SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &AL(env), 0, 1, 1);
437c97d6d2cSSergio Andres Gomez Del Real         break;
438c97d6d2cSSergio Andres Gomez Del Real     case 0xed:
439444bae08SWei Liu         emul_ops->handle_io(env_cpu(env), DX(env), &val, 0,
440444bae08SWei Liu                             decode->operand_size, 1);
441c97d6d2cSSergio Andres Gomez Del Real         if (decode->operand_size == 2) {
442c97d6d2cSSergio Andres Gomez Del Real             AX(env) = val;
443c97d6d2cSSergio Andres Gomez Del Real         } else {
444c97d6d2cSSergio Andres Gomez Del Real             RAX(env) = (uint32_t)val;
445c97d6d2cSSergio Andres Gomez Del Real         }
446c97d6d2cSSergio Andres Gomez Del Real 
447c97d6d2cSSergio Andres Gomez Del Real         break;
448c97d6d2cSSergio Andres Gomez Del Real     default:
449c97d6d2cSSergio Andres Gomez Del Real         VM_PANIC("Bad in opcode\n");
450c97d6d2cSSergio Andres Gomez Del Real         break;
451c97d6d2cSSergio Andres Gomez Del Real     }
452c97d6d2cSSergio Andres Gomez Del Real 
4535d32173fSRoman Bolshakov     env->eip += decode->len;
454c97d6d2cSSergio Andres Gomez Del Real }
455c97d6d2cSSergio Andres Gomez Del Real 
45636861198SPhilippe Mathieu-Daudé static inline void string_increment_reg(CPUX86State *env, int reg,
457c97d6d2cSSergio Andres Gomez Del Real                                         struct x86_decode *decode)
458c97d6d2cSSergio Andres Gomez Del Real {
459ff2de166SPaolo Bonzini     target_ulong val = read_reg(env, reg, decode->addressing_size);
460967f4da2SRoman Bolshakov     if (env->eflags & DF_MASK) {
461c97d6d2cSSergio Andres Gomez Del Real         val -= decode->operand_size;
462c97d6d2cSSergio Andres Gomez Del Real     } else {
463c97d6d2cSSergio Andres Gomez Del Real         val += decode->operand_size;
464c97d6d2cSSergio Andres Gomez Del Real     }
465c97d6d2cSSergio Andres Gomez Del Real     write_reg(env, reg, val, decode->addressing_size);
466c97d6d2cSSergio Andres Gomez Del Real }
467c97d6d2cSSergio Andres Gomez Del Real 
46836861198SPhilippe Mathieu-Daudé static inline void string_rep(CPUX86State *env, struct x86_decode *decode,
46936861198SPhilippe Mathieu-Daudé                               void (*func)(CPUX86State *env,
470c97d6d2cSSergio Andres Gomez Del Real                                            struct x86_decode *ins), int rep)
471c97d6d2cSSergio Andres Gomez Del Real {
472ff2de166SPaolo Bonzini     target_ulong rcx = read_reg(env, R_ECX, decode->addressing_size);
473c97d6d2cSSergio Andres Gomez Del Real     while (rcx--) {
474c97d6d2cSSergio Andres Gomez Del Real         func(env, decode);
4756701d81dSPaolo Bonzini         write_reg(env, R_ECX, rcx, decode->addressing_size);
476c97d6d2cSSergio Andres Gomez Del Real         if ((PREFIX_REP == rep) && !get_ZF(env)) {
477c97d6d2cSSergio Andres Gomez Del Real             break;
478c97d6d2cSSergio Andres Gomez Del Real         }
479c97d6d2cSSergio Andres Gomez Del Real         if ((PREFIX_REPN == rep) && get_ZF(env)) {
480c97d6d2cSSergio Andres Gomez Del Real             break;
481c97d6d2cSSergio Andres Gomez Del Real         }
482c97d6d2cSSergio Andres Gomez Del Real     }
483c97d6d2cSSergio Andres Gomez Del Real }
484c97d6d2cSSergio Andres Gomez Del Real 
48536861198SPhilippe Mathieu-Daudé static void exec_ins_single(CPUX86State *env, struct x86_decode *decode)
486c97d6d2cSSergio Andres Gomez Del Real {
48729a0af61SRichard Henderson     target_ulong addr = linear_addr_size(env_cpu(env), RDI(env),
48829a0af61SRichard Henderson                                          decode->addressing_size, R_ES);
489c97d6d2cSSergio Andres Gomez Del Real 
490e9c40026SWei Liu     emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 0,
491c97d6d2cSSergio Andres Gomez Del Real                         decode->operand_size, 1);
492*63d8bc66SWei Liu     emul_ops->write_mem(env_cpu(env), env->emu_mmio_buf, addr,
49329a0af61SRichard Henderson                         decode->operand_size);
494c97d6d2cSSergio Andres Gomez Del Real 
4956701d81dSPaolo Bonzini     string_increment_reg(env, R_EDI, decode);
496c97d6d2cSSergio Andres Gomez Del Real }
497c97d6d2cSSergio Andres Gomez Del Real 
49836861198SPhilippe Mathieu-Daudé static void exec_ins(CPUX86State *env, struct x86_decode *decode)
499c97d6d2cSSergio Andres Gomez Del Real {
500c97d6d2cSSergio Andres Gomez Del Real     if (decode->rep) {
501c97d6d2cSSergio Andres Gomez Del Real         string_rep(env, decode, exec_ins_single, 0);
502c97d6d2cSSergio Andres Gomez Del Real     } else {
503c97d6d2cSSergio Andres Gomez Del Real         exec_ins_single(env, decode);
504c97d6d2cSSergio Andres Gomez Del Real     }
505c97d6d2cSSergio Andres Gomez Del Real 
5065d32173fSRoman Bolshakov     env->eip += decode->len;
507c97d6d2cSSergio Andres Gomez Del Real }
508c97d6d2cSSergio Andres Gomez Del Real 
50936861198SPhilippe Mathieu-Daudé static void exec_outs_single(CPUX86State *env, struct x86_decode *decode)
510c97d6d2cSSergio Andres Gomez Del Real {
511ff2de166SPaolo Bonzini     target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS);
512c97d6d2cSSergio Andres Gomez Del Real 
513ae3c6134SWei Liu     emul_ops->read_mem(env_cpu(env), env->emu_mmio_buf, addr,
51429a0af61SRichard Henderson                        decode->operand_size);
515e9c40026SWei Liu     emul_ops->handle_io(env_cpu(env), DX(env), env->emu_mmio_buf, 1,
516c97d6d2cSSergio Andres Gomez Del Real                         decode->operand_size, 1);
517c97d6d2cSSergio Andres Gomez Del Real 
5186701d81dSPaolo Bonzini     string_increment_reg(env, R_ESI, decode);
519c97d6d2cSSergio Andres Gomez Del Real }
520c97d6d2cSSergio Andres Gomez Del Real 
52136861198SPhilippe Mathieu-Daudé static void exec_outs(CPUX86State *env, struct x86_decode *decode)
522c97d6d2cSSergio Andres Gomez Del Real {
523c97d6d2cSSergio Andres Gomez Del Real     if (decode->rep) {
524c97d6d2cSSergio Andres Gomez Del Real         string_rep(env, decode, exec_outs_single, 0);
525c97d6d2cSSergio Andres Gomez Del Real     } else {
526c97d6d2cSSergio Andres Gomez Del Real         exec_outs_single(env, decode);
527c97d6d2cSSergio Andres Gomez Del Real     }
528c97d6d2cSSergio Andres Gomez Del Real 
5295d32173fSRoman Bolshakov     env->eip += decode->len;
530c97d6d2cSSergio Andres Gomez Del Real }
531c97d6d2cSSergio Andres Gomez Del Real 
53236861198SPhilippe Mathieu-Daudé static void exec_movs_single(CPUX86State *env, struct x86_decode *decode)
533c97d6d2cSSergio Andres Gomez Del Real {
534ff2de166SPaolo Bonzini     target_ulong src_addr;
535ff2de166SPaolo Bonzini     target_ulong dst_addr;
536ff2de166SPaolo Bonzini     target_ulong val;
537c97d6d2cSSergio Andres Gomez Del Real 
5386701d81dSPaolo Bonzini     src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
53929a0af61SRichard Henderson     dst_addr = linear_addr_size(env_cpu(env), RDI(env),
54029a0af61SRichard Henderson                                 decode->addressing_size, R_ES);
541c97d6d2cSSergio Andres Gomez Del Real 
542c97d6d2cSSergio Andres Gomez Del Real     val = read_val_ext(env, src_addr, decode->operand_size);
543c97d6d2cSSergio Andres Gomez Del Real     write_val_ext(env, dst_addr, val, decode->operand_size);
544c97d6d2cSSergio Andres Gomez Del Real 
5456701d81dSPaolo Bonzini     string_increment_reg(env, R_ESI, decode);
5466701d81dSPaolo Bonzini     string_increment_reg(env, R_EDI, decode);
547c97d6d2cSSergio Andres Gomez Del Real }
548c97d6d2cSSergio Andres Gomez Del Real 
54936861198SPhilippe Mathieu-Daudé static void exec_movs(CPUX86State *env, struct x86_decode *decode)
550c97d6d2cSSergio Andres Gomez Del Real {
551c97d6d2cSSergio Andres Gomez Del Real     if (decode->rep) {
552c97d6d2cSSergio Andres Gomez Del Real         string_rep(env, decode, exec_movs_single, 0);
553c97d6d2cSSergio Andres Gomez Del Real     } else {
554c97d6d2cSSergio Andres Gomez Del Real         exec_movs_single(env, decode);
555c97d6d2cSSergio Andres Gomez Del Real     }
556c97d6d2cSSergio Andres Gomez Del Real 
5575d32173fSRoman Bolshakov     env->eip += decode->len;
558c97d6d2cSSergio Andres Gomez Del Real }
559c97d6d2cSSergio Andres Gomez Del Real 
56036861198SPhilippe Mathieu-Daudé static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode)
561c97d6d2cSSergio Andres Gomez Del Real {
562ff2de166SPaolo Bonzini     target_ulong src_addr;
563ff2de166SPaolo Bonzini     target_ulong dst_addr;
564c97d6d2cSSergio Andres Gomez Del Real 
5656701d81dSPaolo Bonzini     src_addr = decode_linear_addr(env, decode, RSI(env), R_DS);
56629a0af61SRichard Henderson     dst_addr = linear_addr_size(env_cpu(env), RDI(env),
56729a0af61SRichard Henderson                                 decode->addressing_size, R_ES);
568c97d6d2cSSergio Andres Gomez Del Real 
569c97d6d2cSSergio Andres Gomez Del Real     decode->op[0].type = X86_VAR_IMMEDIATE;
570c97d6d2cSSergio Andres Gomez Del Real     decode->op[0].val = read_val_ext(env, src_addr, decode->operand_size);
571c97d6d2cSSergio Andres Gomez Del Real     decode->op[1].type = X86_VAR_IMMEDIATE;
572c97d6d2cSSergio Andres Gomez Del Real     decode->op[1].val = read_val_ext(env, dst_addr, decode->operand_size);
573c97d6d2cSSergio Andres Gomez Del Real 
574e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
575c97d6d2cSSergio Andres Gomez Del Real 
5766701d81dSPaolo Bonzini     string_increment_reg(env, R_ESI, decode);
5776701d81dSPaolo Bonzini     string_increment_reg(env, R_EDI, decode);
578c97d6d2cSSergio Andres Gomez Del Real }
579c97d6d2cSSergio Andres Gomez Del Real 
58036861198SPhilippe Mathieu-Daudé static void exec_cmps(CPUX86State *env, struct x86_decode *decode)
581c97d6d2cSSergio Andres Gomez Del Real {
582c97d6d2cSSergio Andres Gomez Del Real     if (decode->rep) {
583c97d6d2cSSergio Andres Gomez Del Real         string_rep(env, decode, exec_cmps_single, decode->rep);
584c97d6d2cSSergio Andres Gomez Del Real     } else {
585c97d6d2cSSergio Andres Gomez Del Real         exec_cmps_single(env, decode);
586c97d6d2cSSergio Andres Gomez Del Real     }
5875d32173fSRoman Bolshakov     env->eip += decode->len;
588c97d6d2cSSergio Andres Gomez Del Real }
589c97d6d2cSSergio Andres Gomez Del Real 
590c97d6d2cSSergio Andres Gomez Del Real 
59136861198SPhilippe Mathieu-Daudé static void exec_stos_single(CPUX86State *env, struct x86_decode *decode)
592c97d6d2cSSergio Andres Gomez Del Real {
593ff2de166SPaolo Bonzini     target_ulong addr;
594ff2de166SPaolo Bonzini     target_ulong val;
595c97d6d2cSSergio Andres Gomez Del Real 
59629a0af61SRichard Henderson     addr = linear_addr_size(env_cpu(env), RDI(env),
59729a0af61SRichard Henderson                             decode->addressing_size, R_ES);
5986701d81dSPaolo Bonzini     val = read_reg(env, R_EAX, decode->operand_size);
599*63d8bc66SWei Liu     emul_ops->write_mem(env_cpu(env), &val, addr, decode->operand_size);
600c97d6d2cSSergio Andres Gomez Del Real 
6016701d81dSPaolo Bonzini     string_increment_reg(env, R_EDI, decode);
602c97d6d2cSSergio Andres Gomez Del Real }
603c97d6d2cSSergio Andres Gomez Del Real 
604c97d6d2cSSergio Andres Gomez Del Real 
60536861198SPhilippe Mathieu-Daudé static void exec_stos(CPUX86State *env, struct x86_decode *decode)
606c97d6d2cSSergio Andres Gomez Del Real {
607c97d6d2cSSergio Andres Gomez Del Real     if (decode->rep) {
608c97d6d2cSSergio Andres Gomez Del Real         string_rep(env, decode, exec_stos_single, 0);
609c97d6d2cSSergio Andres Gomez Del Real     } else {
610c97d6d2cSSergio Andres Gomez Del Real         exec_stos_single(env, decode);
611c97d6d2cSSergio Andres Gomez Del Real     }
612c97d6d2cSSergio Andres Gomez Del Real 
6135d32173fSRoman Bolshakov     env->eip += decode->len;
614c97d6d2cSSergio Andres Gomez Del Real }
615c97d6d2cSSergio Andres Gomez Del Real 
61636861198SPhilippe Mathieu-Daudé static void exec_scas_single(CPUX86State *env, struct x86_decode *decode)
617c97d6d2cSSergio Andres Gomez Del Real {
618ff2de166SPaolo Bonzini     target_ulong addr;
619c97d6d2cSSergio Andres Gomez Del Real 
62029a0af61SRichard Henderson     addr = linear_addr_size(env_cpu(env), RDI(env),
62129a0af61SRichard Henderson                             decode->addressing_size, R_ES);
622c97d6d2cSSergio Andres Gomez Del Real     decode->op[1].type = X86_VAR_IMMEDIATE;
623ae3c6134SWei Liu     emul_ops->read_mem(env_cpu(env), &decode->op[1].val, addr, decode->operand_size);
624c97d6d2cSSergio Andres Gomez Del Real 
625e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
6266701d81dSPaolo Bonzini     string_increment_reg(env, R_EDI, decode);
627c97d6d2cSSergio Andres Gomez Del Real }
628c97d6d2cSSergio Andres Gomez Del Real 
62936861198SPhilippe Mathieu-Daudé static void exec_scas(CPUX86State *env, struct x86_decode *decode)
630c97d6d2cSSergio Andres Gomez Del Real {
631c97d6d2cSSergio Andres Gomez Del Real     decode->op[0].type = X86_VAR_REG;
6326701d81dSPaolo Bonzini     decode->op[0].reg = R_EAX;
633c97d6d2cSSergio Andres Gomez Del Real     if (decode->rep) {
634c97d6d2cSSergio Andres Gomez Del Real         string_rep(env, decode, exec_scas_single, decode->rep);
635c97d6d2cSSergio Andres Gomez Del Real     } else {
636c97d6d2cSSergio Andres Gomez Del Real         exec_scas_single(env, decode);
637c97d6d2cSSergio Andres Gomez Del Real     }
638c97d6d2cSSergio Andres Gomez Del Real 
6395d32173fSRoman Bolshakov     env->eip += decode->len;
640c97d6d2cSSergio Andres Gomez Del Real }
641c97d6d2cSSergio Andres Gomez Del Real 
64236861198SPhilippe Mathieu-Daudé static void exec_lods_single(CPUX86State *env, struct x86_decode *decode)
643c97d6d2cSSergio Andres Gomez Del Real {
644ff2de166SPaolo Bonzini     target_ulong addr;
645ff2de166SPaolo Bonzini     target_ulong val = 0;
646c97d6d2cSSergio Andres Gomez Del Real 
6476701d81dSPaolo Bonzini     addr = decode_linear_addr(env, decode, RSI(env), R_DS);
648ae3c6134SWei Liu     emul_ops->read_mem(env_cpu(env), &val, addr,  decode->operand_size);
6496701d81dSPaolo Bonzini     write_reg(env, R_EAX, val, decode->operand_size);
650c97d6d2cSSergio Andres Gomez Del Real 
6516701d81dSPaolo Bonzini     string_increment_reg(env, R_ESI, decode);
652c97d6d2cSSergio Andres Gomez Del Real }
653c97d6d2cSSergio Andres Gomez Del Real 
65436861198SPhilippe Mathieu-Daudé static void exec_lods(CPUX86State *env, struct x86_decode *decode)
655c97d6d2cSSergio Andres Gomez Del Real {
656c97d6d2cSSergio Andres Gomez Del Real     if (decode->rep) {
657c97d6d2cSSergio Andres Gomez Del Real         string_rep(env, decode, exec_lods_single, 0);
658c97d6d2cSSergio Andres Gomez Del Real     } else {
659c97d6d2cSSergio Andres Gomez Del Real         exec_lods_single(env, decode);
660c97d6d2cSSergio Andres Gomez Del Real     }
661c97d6d2cSSergio Andres Gomez Del Real 
6625d32173fSRoman Bolshakov     env->eip += decode->len;
663c97d6d2cSSergio Andres Gomez Del Real }
664c97d6d2cSSergio Andres Gomez Del Real 
66599e5aaf9SWei Liu void x86_emul_raise_exception(CPUX86State *env, int exception_index, int error_code)
6660e27f3a5SPhil Dennis-Jordan {
6670e27f3a5SPhil Dennis-Jordan     env->exception_nr = exception_index;
6680e27f3a5SPhil Dennis-Jordan     env->error_code = error_code;
6690e27f3a5SPhil Dennis-Jordan     env->has_error_code = true;
6700e27f3a5SPhil Dennis-Jordan     env->exception_injected = 1;
6710e27f3a5SPhil Dennis-Jordan }
6720e27f3a5SPhil Dennis-Jordan 
67336861198SPhilippe Mathieu-Daudé static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode)
674c97d6d2cSSergio Andres Gomez Del Real {
67599e5aaf9SWei Liu     hvf_simulate_rdmsr(env);
6765d32173fSRoman Bolshakov     env->eip += decode->len;
677c97d6d2cSSergio Andres Gomez Del Real }
678c97d6d2cSSergio Andres Gomez Del Real 
67936861198SPhilippe Mathieu-Daudé static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode)
680c97d6d2cSSergio Andres Gomez Del Real {
68199e5aaf9SWei Liu     hvf_simulate_wrmsr(env);
6825d32173fSRoman Bolshakov     env->eip += decode->len;
683c97d6d2cSSergio Andres Gomez Del Real }
684c97d6d2cSSergio Andres Gomez Del Real 
685c97d6d2cSSergio Andres Gomez Del Real /*
686c97d6d2cSSergio Andres Gomez Del Real  * flag:
687c97d6d2cSSergio Andres Gomez Del Real  * 0 - bt, 1 - btc, 2 - bts, 3 - btr
688c97d6d2cSSergio Andres Gomez Del Real  */
68936861198SPhilippe Mathieu-Daudé static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag)
690c97d6d2cSSergio Andres Gomez Del Real {
691c97d6d2cSSergio Andres Gomez Del Real     int32_t displacement;
692c97d6d2cSSergio Andres Gomez Del Real     uint8_t index;
693c97d6d2cSSergio Andres Gomez Del Real     bool cf;
694c97d6d2cSSergio Andres Gomez Del Real     int mask = (4 == decode->operand_size) ? 0x1f : 0xf;
695c97d6d2cSSergio Andres Gomez Del Real 
696c97d6d2cSSergio Andres Gomez Del Real     VM_PANIC_ON(decode->rex.rex);
697c97d6d2cSSergio Andres Gomez Del Real 
698c97d6d2cSSergio Andres Gomez Del Real     fetch_operands(env, decode, 2, false, true, false);
699c97d6d2cSSergio Andres Gomez Del Real     index = decode->op[1].val & mask;
700c97d6d2cSSergio Andres Gomez Del Real 
701c97d6d2cSSergio Andres Gomez Del Real     if (decode->op[0].type != X86_VAR_REG) {
702c97d6d2cSSergio Andres Gomez Del Real         if (4 == decode->operand_size) {
703c97d6d2cSSergio Andres Gomez Del Real             displacement = ((int32_t) (decode->op[1].val & 0xffffffe0)) / 32;
704c97d6d2cSSergio Andres Gomez Del Real             decode->op[0].ptr += 4 * displacement;
705c97d6d2cSSergio Andres Gomez Del Real         } else if (2 == decode->operand_size) {
706c97d6d2cSSergio Andres Gomez Del Real             displacement = ((int16_t) (decode->op[1].val & 0xfff0)) / 16;
707c97d6d2cSSergio Andres Gomez Del Real             decode->op[0].ptr += 2 * displacement;
708c97d6d2cSSergio Andres Gomez Del Real         } else {
709c97d6d2cSSergio Andres Gomez Del Real             VM_PANIC("bt 64bit\n");
710c97d6d2cSSergio Andres Gomez Del Real         }
711c97d6d2cSSergio Andres Gomez Del Real     }
712c97d6d2cSSergio Andres Gomez Del Real     decode->op[0].val = read_val_ext(env, decode->op[0].ptr,
713c97d6d2cSSergio Andres Gomez Del Real                                      decode->operand_size);
714c97d6d2cSSergio Andres Gomez Del Real     cf = (decode->op[0].val >> index) & 0x01;
715c97d6d2cSSergio Andres Gomez Del Real 
716c97d6d2cSSergio Andres Gomez Del Real     switch (flag) {
717c97d6d2cSSergio Andres Gomez Del Real     case 0:
718c97d6d2cSSergio Andres Gomez Del Real         set_CF(env, cf);
719c97d6d2cSSergio Andres Gomez Del Real         return;
720c97d6d2cSSergio Andres Gomez Del Real     case 1:
721c97d6d2cSSergio Andres Gomez Del Real         decode->op[0].val ^= (1u << index);
722c97d6d2cSSergio Andres Gomez Del Real         break;
723c97d6d2cSSergio Andres Gomez Del Real     case 2:
724c97d6d2cSSergio Andres Gomez Del Real         decode->op[0].val |= (1u << index);
725c97d6d2cSSergio Andres Gomez Del Real         break;
726c97d6d2cSSergio Andres Gomez Del Real     case 3:
727c97d6d2cSSergio Andres Gomez Del Real         decode->op[0].val &= ~(1u << index);
728c97d6d2cSSergio Andres Gomez Del Real         break;
729c97d6d2cSSergio Andres Gomez Del Real     }
730c97d6d2cSSergio Andres Gomez Del Real     write_val_ext(env, decode->op[0].ptr, decode->op[0].val,
731c97d6d2cSSergio Andres Gomez Del Real                   decode->operand_size);
732c97d6d2cSSergio Andres Gomez Del Real     set_CF(env, cf);
733c97d6d2cSSergio Andres Gomez Del Real }
734c97d6d2cSSergio Andres Gomez Del Real 
73536861198SPhilippe Mathieu-Daudé static void exec_bt(CPUX86State *env, struct x86_decode *decode)
736c97d6d2cSSergio Andres Gomez Del Real {
737c97d6d2cSSergio Andres Gomez Del Real     do_bt(env, decode, 0);
7385d32173fSRoman Bolshakov     env->eip += decode->len;
739c97d6d2cSSergio Andres Gomez Del Real }
740c97d6d2cSSergio Andres Gomez Del Real 
74136861198SPhilippe Mathieu-Daudé static void exec_btc(CPUX86State *env, struct x86_decode *decode)
742c97d6d2cSSergio Andres Gomez Del Real {
743c97d6d2cSSergio Andres Gomez Del Real     do_bt(env, decode, 1);
7445d32173fSRoman Bolshakov     env->eip += decode->len;
745c97d6d2cSSergio Andres Gomez Del Real }
746c97d6d2cSSergio Andres Gomez Del Real 
74736861198SPhilippe Mathieu-Daudé static void exec_btr(CPUX86State *env, struct x86_decode *decode)
748c97d6d2cSSergio Andres Gomez Del Real {
749c97d6d2cSSergio Andres Gomez Del Real     do_bt(env, decode, 3);
7505d32173fSRoman Bolshakov     env->eip += decode->len;
751c97d6d2cSSergio Andres Gomez Del Real }
752c97d6d2cSSergio Andres Gomez Del Real 
75336861198SPhilippe Mathieu-Daudé static void exec_bts(CPUX86State *env, struct x86_decode *decode)
754c97d6d2cSSergio Andres Gomez Del Real {
755c97d6d2cSSergio Andres Gomez Del Real     do_bt(env, decode, 2);
7565d32173fSRoman Bolshakov     env->eip += decode->len;
757c97d6d2cSSergio Andres Gomez Del Real }
758c97d6d2cSSergio Andres Gomez Del Real 
75936861198SPhilippe Mathieu-Daudé void exec_shl(CPUX86State *env, struct x86_decode *decode)
760c97d6d2cSSergio Andres Gomez Del Real {
761c97d6d2cSSergio Andres Gomez Del Real     uint8_t count;
762c97d6d2cSSergio Andres Gomez Del Real     int of = 0, cf = 0;
763c97d6d2cSSergio Andres Gomez Del Real 
764c97d6d2cSSergio Andres Gomez Del Real     fetch_operands(env, decode, 2, true, true, false);
765c97d6d2cSSergio Andres Gomez Del Real 
766c97d6d2cSSergio Andres Gomez Del Real     count = decode->op[1].val;
767c97d6d2cSSergio Andres Gomez Del Real     count &= 0x1f;      /* count is masked to 5 bits*/
768c97d6d2cSSergio Andres Gomez Del Real     if (!count) {
769c97d6d2cSSergio Andres Gomez Del Real         goto exit;
770c97d6d2cSSergio Andres Gomez Del Real     }
771c97d6d2cSSergio Andres Gomez Del Real 
772c97d6d2cSSergio Andres Gomez Del Real     switch (decode->operand_size) {
773c97d6d2cSSergio Andres Gomez Del Real     case 1:
774c97d6d2cSSergio Andres Gomez Del Real     {
775c97d6d2cSSergio Andres Gomez Del Real         uint8_t res = 0;
776c97d6d2cSSergio Andres Gomez Del Real         if (count <= 8) {
777c97d6d2cSSergio Andres Gomez Del Real             res = (decode->op[0].val << count);
778c97d6d2cSSergio Andres Gomez Del Real             cf = (decode->op[0].val >> (8 - count)) & 0x1;
779c97d6d2cSSergio Andres Gomez Del Real             of = cf ^ (res >> 7);
780c97d6d2cSSergio Andres Gomez Del Real         }
781c97d6d2cSSergio Andres Gomez Del Real 
782c97d6d2cSSergio Andres Gomez Del Real         write_val_ext(env, decode->op[0].ptr, res, 1);
783e8a63257SPaolo Bonzini         SET_FLAGS_OSZAPC_LOGIC8(env, 0, 0, res);
784c97d6d2cSSergio Andres Gomez Del Real         SET_FLAGS_OxxxxC(env, of, cf);
785c97d6d2cSSergio Andres Gomez Del Real         break;
786c97d6d2cSSergio Andres Gomez Del Real     }
787c97d6d2cSSergio Andres Gomez Del Real     case 2:
788c97d6d2cSSergio Andres Gomez Del Real     {
789c97d6d2cSSergio Andres Gomez Del Real         uint16_t res = 0;
790c97d6d2cSSergio Andres Gomez Del Real 
791c97d6d2cSSergio Andres Gomez Del Real         /* from bochs */
792c97d6d2cSSergio Andres Gomez Del Real         if (count <= 16) {
793c97d6d2cSSergio Andres Gomez Del Real             res = (decode->op[0].val << count);
794c97d6d2cSSergio Andres Gomez Del Real             cf = (decode->op[0].val >> (16 - count)) & 0x1;
795c97d6d2cSSergio Andres Gomez Del Real             of = cf ^ (res >> 15); /* of = cf ^ result15 */
796c97d6d2cSSergio Andres Gomez Del Real         }
797c97d6d2cSSergio Andres Gomez Del Real 
798c97d6d2cSSergio Andres Gomez Del Real         write_val_ext(env, decode->op[0].ptr, res, 2);
799e8a63257SPaolo Bonzini         SET_FLAGS_OSZAPC_LOGIC16(env, 0, 0, res);
800c97d6d2cSSergio Andres Gomez Del Real         SET_FLAGS_OxxxxC(env, of, cf);
801c97d6d2cSSergio Andres Gomez Del Real         break;
802c97d6d2cSSergio Andres Gomez Del Real     }
803c97d6d2cSSergio Andres Gomez Del Real     case 4:
804c97d6d2cSSergio Andres Gomez Del Real     {
805c97d6d2cSSergio Andres Gomez Del Real         uint32_t res = decode->op[0].val << count;
806c97d6d2cSSergio Andres Gomez Del Real 
807c97d6d2cSSergio Andres Gomez Del Real         write_val_ext(env, decode->op[0].ptr, res, 4);
808e8a63257SPaolo Bonzini         SET_FLAGS_OSZAPC_LOGIC32(env, 0, 0, res);
809c97d6d2cSSergio Andres Gomez Del Real         cf = (decode->op[0].val >> (32 - count)) & 0x1;
810c97d6d2cSSergio Andres Gomez Del Real         of = cf ^ (res >> 31); /* of = cf ^ result31 */
811c97d6d2cSSergio Andres Gomez Del Real         SET_FLAGS_OxxxxC(env, of, cf);
812c97d6d2cSSergio Andres Gomez Del Real         break;
813c97d6d2cSSergio Andres Gomez Del Real     }
814c97d6d2cSSergio Andres Gomez Del Real     default:
815c97d6d2cSSergio Andres Gomez Del Real         abort();
816c97d6d2cSSergio Andres Gomez Del Real     }
817c97d6d2cSSergio Andres Gomez Del Real 
818c97d6d2cSSergio Andres Gomez Del Real exit:
819c97d6d2cSSergio Andres Gomez Del Real     /* lflags_to_rflags(env); */
8205d32173fSRoman Bolshakov     env->eip += decode->len;
821c97d6d2cSSergio Andres Gomez Del Real }
822c97d6d2cSSergio Andres Gomez Del Real 
823c97d6d2cSSergio Andres Gomez Del Real void exec_movsx(CPUX86State *env, struct x86_decode *decode)
824c97d6d2cSSergio Andres Gomez Del Real {
825c97d6d2cSSergio Andres Gomez Del Real     int src_op_size;
826c97d6d2cSSergio Andres Gomez Del Real     int op_size = decode->operand_size;
827c97d6d2cSSergio Andres Gomez Del Real 
828c97d6d2cSSergio Andres Gomez Del Real     fetch_operands(env, decode, 2, false, false, false);
829c97d6d2cSSergio Andres Gomez Del Real 
830c97d6d2cSSergio Andres Gomez Del Real     if (0xbe == decode->opcode[1]) {
831c97d6d2cSSergio Andres Gomez Del Real         src_op_size = 1;
832c97d6d2cSSergio Andres Gomez Del Real     } else {
833c97d6d2cSSergio Andres Gomez Del Real         src_op_size = 2;
834c97d6d2cSSergio Andres Gomez Del Real     }
835c97d6d2cSSergio Andres Gomez Del Real 
836c97d6d2cSSergio Andres Gomez Del Real     decode->operand_size = src_op_size;
837c97d6d2cSSergio Andres Gomez Del Real     calc_modrm_operand(env, decode, &decode->op[1]);
838c97d6d2cSSergio Andres Gomez Del Real     decode->op[1].val = sign(read_val_ext(env, decode->op[1].ptr, src_op_size),
839c97d6d2cSSergio Andres Gomez Del Real                              src_op_size);
840c97d6d2cSSergio Andres Gomez Del Real 
841c97d6d2cSSergio Andres Gomez Del Real     write_val_ext(env, decode->op[0].ptr, decode->op[1].val, op_size);
842c97d6d2cSSergio Andres Gomez Del Real 
8435d32173fSRoman Bolshakov     env->eip += decode->len;
844c97d6d2cSSergio Andres Gomez Del Real }
845c97d6d2cSSergio Andres Gomez Del Real 
84636861198SPhilippe Mathieu-Daudé void exec_ror(CPUX86State *env, struct x86_decode *decode)
847c97d6d2cSSergio Andres Gomez Del Real {
848c97d6d2cSSergio Andres Gomez Del Real     uint8_t count;
849c97d6d2cSSergio Andres Gomez Del Real 
850c97d6d2cSSergio Andres Gomez Del Real     fetch_operands(env, decode, 2, true, true, false);
851c97d6d2cSSergio Andres Gomez Del Real     count = decode->op[1].val;
852c97d6d2cSSergio Andres Gomez Del Real 
853c97d6d2cSSergio Andres Gomez Del Real     switch (decode->operand_size) {
854c97d6d2cSSergio Andres Gomez Del Real     case 1:
855c97d6d2cSSergio Andres Gomez Del Real     {
856c97d6d2cSSergio Andres Gomez Del Real         uint32_t bit6, bit7;
857c97d6d2cSSergio Andres Gomez Del Real         uint8_t res;
858c97d6d2cSSergio Andres Gomez Del Real 
859c97d6d2cSSergio Andres Gomez Del Real         if ((count & 0x07) == 0) {
860c97d6d2cSSergio Andres Gomez Del Real             if (count & 0x18) {
861c97d6d2cSSergio Andres Gomez Del Real                 bit6 = ((uint8_t)decode->op[0].val >> 6) & 1;
862c97d6d2cSSergio Andres Gomez Del Real                 bit7 = ((uint8_t)decode->op[0].val >> 7) & 1;
863c97d6d2cSSergio Andres Gomez Del Real                 SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
864c97d6d2cSSergio Andres Gomez Del Real              }
865c97d6d2cSSergio Andres Gomez Del Real         } else {
866c97d6d2cSSergio Andres Gomez Del Real             count &= 0x7; /* use only bottom 3 bits */
867c97d6d2cSSergio Andres Gomez Del Real             res = ((uint8_t)decode->op[0].val >> count) |
868c97d6d2cSSergio Andres Gomez Del Real                    ((uint8_t)decode->op[0].val << (8 - count));
869c97d6d2cSSergio Andres Gomez Del Real             write_val_ext(env, decode->op[0].ptr, res, 1);
870c97d6d2cSSergio Andres Gomez Del Real             bit6 = (res >> 6) & 1;
871c97d6d2cSSergio Andres Gomez Del Real             bit7 = (res >> 7) & 1;
872c97d6d2cSSergio Andres Gomez Del Real             /* set eflags: ROR count affects the following flags: C, O */
873c97d6d2cSSergio Andres Gomez Del Real             SET_FLAGS_OxxxxC(env, bit6 ^ bit7, bit7);
874c97d6d2cSSergio Andres Gomez Del Real         }
875c97d6d2cSSergio Andres Gomez Del Real         break;
876c97d6d2cSSergio Andres Gomez Del Real     }
877c97d6d2cSSergio Andres Gomez Del Real     case 2:
878c97d6d2cSSergio Andres Gomez Del Real     {
879c97d6d2cSSergio Andres Gomez Del Real         uint32_t bit14, bit15;
880c97d6d2cSSergio Andres Gomez Del Real         uint16_t res;
881c97d6d2cSSergio Andres Gomez Del Real 
882c97d6d2cSSergio Andres Gomez Del Real         if ((count & 0x0f) == 0) {
883c97d6d2cSSergio Andres Gomez Del Real             if (count & 0x10) {
884c97d6d2cSSergio Andres Gomez Del Real                 bit14 = ((uint16_t)decode->op[0].val >> 14) & 1;
885c97d6d2cSSergio Andres Gomez Del Real                 bit15 = ((uint16_t)decode->op[0].val >> 15) & 1;
886c97d6d2cSSergio Andres Gomez Del Real                 /* of = result14 ^ result15 */
887c97d6d2cSSergio Andres Gomez Del Real                 SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
888c97d6d2cSSergio Andres Gomez Del Real             }
889c97d6d2cSSergio Andres Gomez Del Real         } else {
890c97d6d2cSSergio Andres Gomez Del Real             count &= 0x0f;  /* use only 4 LSB's */
891c97d6d2cSSergio Andres Gomez Del Real             res = ((uint16_t)decode->op[0].val >> count) |
892c97d6d2cSSergio Andres Gomez Del Real                    ((uint16_t)decode->op[0].val << (16 - count));
893c97d6d2cSSergio Andres Gomez Del Real             write_val_ext(env, decode->op[0].ptr, res, 2);
894c97d6d2cSSergio Andres Gomez Del Real 
895c97d6d2cSSergio Andres Gomez Del Real             bit14 = (res >> 14) & 1;
896c97d6d2cSSergio Andres Gomez Del Real             bit15 = (res >> 15) & 1;
897c97d6d2cSSergio Andres Gomez Del Real             /* of = result14 ^ result15 */
898c97d6d2cSSergio Andres Gomez Del Real             SET_FLAGS_OxxxxC(env, bit14 ^ bit15, bit15);
899c97d6d2cSSergio Andres Gomez Del Real         }
900c97d6d2cSSergio Andres Gomez Del Real         break;
901c97d6d2cSSergio Andres Gomez Del Real     }
902c97d6d2cSSergio Andres Gomez Del Real     case 4:
903c97d6d2cSSergio Andres Gomez Del Real     {
904c97d6d2cSSergio Andres Gomez Del Real         uint32_t bit31, bit30;
905c97d6d2cSSergio Andres Gomez Del Real         uint32_t res;
906c97d6d2cSSergio Andres Gomez Del Real 
907c97d6d2cSSergio Andres Gomez Del Real         count &= 0x1f;
908c97d6d2cSSergio Andres Gomez Del Real         if (count) {
909c97d6d2cSSergio Andres Gomez Del Real             res = ((uint32_t)decode->op[0].val >> count) |
910c97d6d2cSSergio Andres Gomez Del Real                    ((uint32_t)decode->op[0].val << (32 - count));
911c97d6d2cSSergio Andres Gomez Del Real             write_val_ext(env, decode->op[0].ptr, res, 4);
912c97d6d2cSSergio Andres Gomez Del Real 
913c97d6d2cSSergio Andres Gomez Del Real             bit31 = (res >> 31) & 1;
914c97d6d2cSSergio Andres Gomez Del Real             bit30 = (res >> 30) & 1;
915c97d6d2cSSergio Andres Gomez Del Real             /* of = result30 ^ result31 */
916c97d6d2cSSergio Andres Gomez Del Real             SET_FLAGS_OxxxxC(env, bit30 ^ bit31, bit31);
917c97d6d2cSSergio Andres Gomez Del Real         }
918c97d6d2cSSergio Andres Gomez Del Real         break;
919c97d6d2cSSergio Andres Gomez Del Real         }
920c97d6d2cSSergio Andres Gomez Del Real     }
9215d32173fSRoman Bolshakov     env->eip += decode->len;
922c97d6d2cSSergio Andres Gomez Del Real }
923c97d6d2cSSergio Andres Gomez Del Real 
92436861198SPhilippe Mathieu-Daudé void exec_rol(CPUX86State *env, struct x86_decode *decode)
925c97d6d2cSSergio Andres Gomez Del Real {
926c97d6d2cSSergio Andres Gomez Del Real     uint8_t count;
927c97d6d2cSSergio Andres Gomez Del Real 
928c97d6d2cSSergio Andres Gomez Del Real     fetch_operands(env, decode, 2, true, true, false);
929c97d6d2cSSergio Andres Gomez Del Real     count = decode->op[1].val;
930c97d6d2cSSergio Andres Gomez Del Real 
931c97d6d2cSSergio Andres Gomez Del Real     switch (decode->operand_size) {
932c97d6d2cSSergio Andres Gomez Del Real     case 1:
933c97d6d2cSSergio Andres Gomez Del Real     {
934c97d6d2cSSergio Andres Gomez Del Real         uint32_t bit0, bit7;
935c97d6d2cSSergio Andres Gomez Del Real         uint8_t res;
936c97d6d2cSSergio Andres Gomez Del Real 
937c97d6d2cSSergio Andres Gomez Del Real         if ((count & 0x07) == 0) {
938c97d6d2cSSergio Andres Gomez Del Real             if (count & 0x18) {
939c97d6d2cSSergio Andres Gomez Del Real                 bit0 = ((uint8_t)decode->op[0].val & 1);
940c97d6d2cSSergio Andres Gomez Del Real                 bit7 = ((uint8_t)decode->op[0].val >> 7);
941c97d6d2cSSergio Andres Gomez Del Real                 SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
942c97d6d2cSSergio Andres Gomez Del Real             }
943c97d6d2cSSergio Andres Gomez Del Real         }  else {
944c97d6d2cSSergio Andres Gomez Del Real             count &= 0x7; /* use only lowest 3 bits */
945c97d6d2cSSergio Andres Gomez Del Real             res = ((uint8_t)decode->op[0].val << count) |
946c97d6d2cSSergio Andres Gomez Del Real                    ((uint8_t)decode->op[0].val >> (8 - count));
947c97d6d2cSSergio Andres Gomez Del Real 
948c97d6d2cSSergio Andres Gomez Del Real             write_val_ext(env, decode->op[0].ptr, res, 1);
949c97d6d2cSSergio Andres Gomez Del Real             /* set eflags:
950c97d6d2cSSergio Andres Gomez Del Real              * ROL count affects the following flags: C, O
951c97d6d2cSSergio Andres Gomez Del Real              */
952c97d6d2cSSergio Andres Gomez Del Real             bit0 = (res &  1);
953c97d6d2cSSergio Andres Gomez Del Real             bit7 = (res >> 7);
954c97d6d2cSSergio Andres Gomez Del Real             SET_FLAGS_OxxxxC(env, bit0 ^ bit7, bit0);
955c97d6d2cSSergio Andres Gomez Del Real         }
956c97d6d2cSSergio Andres Gomez Del Real         break;
957c97d6d2cSSergio Andres Gomez Del Real     }
958c97d6d2cSSergio Andres Gomez Del Real     case 2:
959c97d6d2cSSergio Andres Gomez Del Real     {
960c97d6d2cSSergio Andres Gomez Del Real         uint32_t bit0, bit15;
961c97d6d2cSSergio Andres Gomez Del Real         uint16_t res;
962c97d6d2cSSergio Andres Gomez Del Real 
963c97d6d2cSSergio Andres Gomez Del Real         if ((count & 0x0f) == 0) {
964c97d6d2cSSergio Andres Gomez Del Real             if (count & 0x10) {
965c97d6d2cSSergio Andres Gomez Del Real                 bit0  = ((uint16_t)decode->op[0].val & 0x1);
966c97d6d2cSSergio Andres Gomez Del Real                 bit15 = ((uint16_t)decode->op[0].val >> 15);
967c97d6d2cSSergio Andres Gomez Del Real                 /* of = cf ^ result15 */
968c97d6d2cSSergio Andres Gomez Del Real                 SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
969c97d6d2cSSergio Andres Gomez Del Real             }
970c97d6d2cSSergio Andres Gomez Del Real         } else {
971c97d6d2cSSergio Andres Gomez Del Real             count &= 0x0f; /* only use bottom 4 bits */
972c97d6d2cSSergio Andres Gomez Del Real             res = ((uint16_t)decode->op[0].val << count) |
973c97d6d2cSSergio Andres Gomez Del Real                    ((uint16_t)decode->op[0].val >> (16 - count));
974c97d6d2cSSergio Andres Gomez Del Real 
975c97d6d2cSSergio Andres Gomez Del Real             write_val_ext(env, decode->op[0].ptr, res, 2);
976c97d6d2cSSergio Andres Gomez Del Real             bit0  = (res & 0x1);
977c97d6d2cSSergio Andres Gomez Del Real             bit15 = (res >> 15);
978c97d6d2cSSergio Andres Gomez Del Real             /* of = cf ^ result15 */
979c97d6d2cSSergio Andres Gomez Del Real             SET_FLAGS_OxxxxC(env, bit0 ^ bit15, bit0);
980c97d6d2cSSergio Andres Gomez Del Real         }
981c97d6d2cSSergio Andres Gomez Del Real         break;
982c97d6d2cSSergio Andres Gomez Del Real     }
983c97d6d2cSSergio Andres Gomez Del Real     case 4:
984c97d6d2cSSergio Andres Gomez Del Real     {
985c97d6d2cSSergio Andres Gomez Del Real         uint32_t bit0, bit31;
986c97d6d2cSSergio Andres Gomez Del Real         uint32_t res;
987c97d6d2cSSergio Andres Gomez Del Real 
988c97d6d2cSSergio Andres Gomez Del Real         count &= 0x1f;
989c97d6d2cSSergio Andres Gomez Del Real         if (count) {
990c97d6d2cSSergio Andres Gomez Del Real             res = ((uint32_t)decode->op[0].val << count) |
991c97d6d2cSSergio Andres Gomez Del Real                    ((uint32_t)decode->op[0].val >> (32 - count));
992c97d6d2cSSergio Andres Gomez Del Real 
993c97d6d2cSSergio Andres Gomez Del Real             write_val_ext(env, decode->op[0].ptr, res, 4);
994c97d6d2cSSergio Andres Gomez Del Real             bit0  = (res & 0x1);
995c97d6d2cSSergio Andres Gomez Del Real             bit31 = (res >> 31);
996c97d6d2cSSergio Andres Gomez Del Real             /* of = cf ^ result31 */
997c97d6d2cSSergio Andres Gomez Del Real             SET_FLAGS_OxxxxC(env, bit0 ^ bit31, bit0);
998c97d6d2cSSergio Andres Gomez Del Real         }
999c97d6d2cSSergio Andres Gomez Del Real         break;
1000c97d6d2cSSergio Andres Gomez Del Real         }
1001c97d6d2cSSergio Andres Gomez Del Real     }
10025d32173fSRoman Bolshakov     env->eip += decode->len;
1003c97d6d2cSSergio Andres Gomez Del Real }
1004c97d6d2cSSergio Andres Gomez Del Real 
1005c97d6d2cSSergio Andres Gomez Del Real 
100636861198SPhilippe Mathieu-Daudé void exec_rcl(CPUX86State *env, struct x86_decode *decode)
1007c97d6d2cSSergio Andres Gomez Del Real {
1008c97d6d2cSSergio Andres Gomez Del Real     uint8_t count;
1009c97d6d2cSSergio Andres Gomez Del Real     int of = 0, cf = 0;
1010c97d6d2cSSergio Andres Gomez Del Real 
1011c97d6d2cSSergio Andres Gomez Del Real     fetch_operands(env, decode, 2, true, true, false);
1012c97d6d2cSSergio Andres Gomez Del Real     count = decode->op[1].val & 0x1f;
1013c97d6d2cSSergio Andres Gomez Del Real 
1014c97d6d2cSSergio Andres Gomez Del Real     switch (decode->operand_size) {
1015c97d6d2cSSergio Andres Gomez Del Real     case 1:
1016c97d6d2cSSergio Andres Gomez Del Real     {
1017c97d6d2cSSergio Andres Gomez Del Real         uint8_t op1_8 = decode->op[0].val;
1018c97d6d2cSSergio Andres Gomez Del Real         uint8_t res;
1019c97d6d2cSSergio Andres Gomez Del Real         count %= 9;
1020c97d6d2cSSergio Andres Gomez Del Real         if (!count) {
1021c97d6d2cSSergio Andres Gomez Del Real             break;
1022c97d6d2cSSergio Andres Gomez Del Real         }
1023c97d6d2cSSergio Andres Gomez Del Real 
1024c97d6d2cSSergio Andres Gomez Del Real         if (1 == count) {
1025c97d6d2cSSergio Andres Gomez Del Real             res = (op1_8 << 1) | get_CF(env);
1026c97d6d2cSSergio Andres Gomez Del Real         } else {
1027c97d6d2cSSergio Andres Gomez Del Real             res = (op1_8 << count) | (get_CF(env) << (count - 1)) |
1028c97d6d2cSSergio Andres Gomez Del Real                    (op1_8 >> (9 - count));
1029c97d6d2cSSergio Andres Gomez Del Real         }
1030c97d6d2cSSergio Andres Gomez Del Real 
1031c97d6d2cSSergio Andres Gomez Del Real         write_val_ext(env, decode->op[0].ptr, res, 1);
1032c97d6d2cSSergio Andres Gomez Del Real 
1033c97d6d2cSSergio Andres Gomez Del Real         cf = (op1_8 >> (8 - count)) & 0x01;
1034c97d6d2cSSergio Andres Gomez Del Real         of = cf ^ (res >> 7); /* of = cf ^ result7 */
1035c97d6d2cSSergio Andres Gomez Del Real         SET_FLAGS_OxxxxC(env, of, cf);
1036c97d6d2cSSergio Andres Gomez Del Real         break;
1037c97d6d2cSSergio Andres Gomez Del Real     }
1038c97d6d2cSSergio Andres Gomez Del Real     case 2:
1039c97d6d2cSSergio Andres Gomez Del Real     {
1040c97d6d2cSSergio Andres Gomez Del Real         uint16_t res;
1041c97d6d2cSSergio Andres Gomez Del Real         uint16_t op1_16 = decode->op[0].val;
1042c97d6d2cSSergio Andres Gomez Del Real 
1043c97d6d2cSSergio Andres Gomez Del Real         count %= 17;
1044c97d6d2cSSergio Andres Gomez Del Real         if (!count) {
1045c97d6d2cSSergio Andres Gomez Del Real             break;
1046c97d6d2cSSergio Andres Gomez Del Real         }
1047c97d6d2cSSergio Andres Gomez Del Real 
1048c97d6d2cSSergio Andres Gomez Del Real         if (1 == count) {
1049c97d6d2cSSergio Andres Gomez Del Real             res = (op1_16 << 1) | get_CF(env);
1050c97d6d2cSSergio Andres Gomez Del Real         } else if (count == 16) {
1051c97d6d2cSSergio Andres Gomez Del Real             res = (get_CF(env) << 15) | (op1_16 >> 1);
1052c97d6d2cSSergio Andres Gomez Del Real         } else { /* 2..15 */
1053c97d6d2cSSergio Andres Gomez Del Real             res = (op1_16 << count) | (get_CF(env) << (count - 1)) |
1054c97d6d2cSSergio Andres Gomez Del Real                    (op1_16 >> (17 - count));
1055c97d6d2cSSergio Andres Gomez Del Real         }
1056c97d6d2cSSergio Andres Gomez Del Real 
1057c97d6d2cSSergio Andres Gomez Del Real         write_val_ext(env, decode->op[0].ptr, res, 2);
1058c97d6d2cSSergio Andres Gomez Del Real 
1059c97d6d2cSSergio Andres Gomez Del Real         cf = (op1_16 >> (16 - count)) & 0x1;
1060c97d6d2cSSergio Andres Gomez Del Real         of = cf ^ (res >> 15); /* of = cf ^ result15 */
1061c97d6d2cSSergio Andres Gomez Del Real         SET_FLAGS_OxxxxC(env, of, cf);
1062c97d6d2cSSergio Andres Gomez Del Real         break;
1063c97d6d2cSSergio Andres Gomez Del Real     }
1064c97d6d2cSSergio Andres Gomez Del Real     case 4:
1065c97d6d2cSSergio Andres Gomez Del Real     {
1066c97d6d2cSSergio Andres Gomez Del Real         uint32_t res;
1067c97d6d2cSSergio Andres Gomez Del Real         uint32_t op1_32 = decode->op[0].val;
1068c97d6d2cSSergio Andres Gomez Del Real 
1069c97d6d2cSSergio Andres Gomez Del Real         if (!count) {
1070c97d6d2cSSergio Andres Gomez Del Real             break;
1071c97d6d2cSSergio Andres Gomez Del Real         }
1072c97d6d2cSSergio Andres Gomez Del Real 
1073c97d6d2cSSergio Andres Gomez Del Real         if (1 == count) {
1074c97d6d2cSSergio Andres Gomez Del Real             res = (op1_32 << 1) | get_CF(env);
1075c97d6d2cSSergio Andres Gomez Del Real         } else {
1076c97d6d2cSSergio Andres Gomez Del Real             res = (op1_32 << count) | (get_CF(env) << (count - 1)) |
1077c97d6d2cSSergio Andres Gomez Del Real                    (op1_32 >> (33 - count));
1078c97d6d2cSSergio Andres Gomez Del Real         }
1079c97d6d2cSSergio Andres Gomez Del Real 
1080c97d6d2cSSergio Andres Gomez Del Real         write_val_ext(env, decode->op[0].ptr, res, 4);
1081c97d6d2cSSergio Andres Gomez Del Real 
1082c97d6d2cSSergio Andres Gomez Del Real         cf = (op1_32 >> (32 - count)) & 0x1;
1083c97d6d2cSSergio Andres Gomez Del Real         of = cf ^ (res >> 31); /* of = cf ^ result31 */
1084c97d6d2cSSergio Andres Gomez Del Real         SET_FLAGS_OxxxxC(env, of, cf);
1085c97d6d2cSSergio Andres Gomez Del Real         break;
1086c97d6d2cSSergio Andres Gomez Del Real         }
1087c97d6d2cSSergio Andres Gomez Del Real     }
10885d32173fSRoman Bolshakov     env->eip += decode->len;
1089c97d6d2cSSergio Andres Gomez Del Real }
1090c97d6d2cSSergio Andres Gomez Del Real 
109136861198SPhilippe Mathieu-Daudé void exec_rcr(CPUX86State *env, struct x86_decode *decode)
1092c97d6d2cSSergio Andres Gomez Del Real {
1093c97d6d2cSSergio Andres Gomez Del Real     uint8_t count;
1094c97d6d2cSSergio Andres Gomez Del Real     int of = 0, cf = 0;
1095c97d6d2cSSergio Andres Gomez Del Real 
1096c97d6d2cSSergio Andres Gomez Del Real     fetch_operands(env, decode, 2, true, true, false);
1097c97d6d2cSSergio Andres Gomez Del Real     count = decode->op[1].val & 0x1f;
1098c97d6d2cSSergio Andres Gomez Del Real 
1099c97d6d2cSSergio Andres Gomez Del Real     switch (decode->operand_size) {
1100c97d6d2cSSergio Andres Gomez Del Real     case 1:
1101c97d6d2cSSergio Andres Gomez Del Real     {
1102c97d6d2cSSergio Andres Gomez Del Real         uint8_t op1_8 = decode->op[0].val;
1103c97d6d2cSSergio Andres Gomez Del Real         uint8_t res;
1104c97d6d2cSSergio Andres Gomez Del Real 
1105c97d6d2cSSergio Andres Gomez Del Real         count %= 9;
1106c97d6d2cSSergio Andres Gomez Del Real         if (!count) {
1107c97d6d2cSSergio Andres Gomez Del Real             break;
1108c97d6d2cSSergio Andres Gomez Del Real         }
1109c97d6d2cSSergio Andres Gomez Del Real         res = (op1_8 >> count) | (get_CF(env) << (8 - count)) |
1110c97d6d2cSSergio Andres Gomez Del Real                (op1_8 << (9 - count));
1111c97d6d2cSSergio Andres Gomez Del Real 
1112c97d6d2cSSergio Andres Gomez Del Real         write_val_ext(env, decode->op[0].ptr, res, 1);
1113c97d6d2cSSergio Andres Gomez Del Real 
1114c97d6d2cSSergio Andres Gomez Del Real         cf = (op1_8 >> (count - 1)) & 0x1;
1115c97d6d2cSSergio Andres Gomez Del Real         of = (((res << 1) ^ res) >> 7) & 0x1; /* of = result6 ^ result7 */
1116c97d6d2cSSergio Andres Gomez Del Real         SET_FLAGS_OxxxxC(env, of, cf);
1117c97d6d2cSSergio Andres Gomez Del Real         break;
1118c97d6d2cSSergio Andres Gomez Del Real     }
1119c97d6d2cSSergio Andres Gomez Del Real     case 2:
1120c97d6d2cSSergio Andres Gomez Del Real     {
1121c97d6d2cSSergio Andres Gomez Del Real         uint16_t op1_16 = decode->op[0].val;
1122c97d6d2cSSergio Andres Gomez Del Real         uint16_t res;
1123c97d6d2cSSergio Andres Gomez Del Real 
1124c97d6d2cSSergio Andres Gomez Del Real         count %= 17;
1125c97d6d2cSSergio Andres Gomez Del Real         if (!count) {
1126c97d6d2cSSergio Andres Gomez Del Real             break;
1127c97d6d2cSSergio Andres Gomez Del Real         }
1128c97d6d2cSSergio Andres Gomez Del Real         res = (op1_16 >> count) | (get_CF(env) << (16 - count)) |
1129c97d6d2cSSergio Andres Gomez Del Real                (op1_16 << (17 - count));
1130c97d6d2cSSergio Andres Gomez Del Real 
1131c97d6d2cSSergio Andres Gomez Del Real         write_val_ext(env, decode->op[0].ptr, res, 2);
1132c97d6d2cSSergio Andres Gomez Del Real 
1133c97d6d2cSSergio Andres Gomez Del Real         cf = (op1_16 >> (count - 1)) & 0x1;
1134c97d6d2cSSergio Andres Gomez Del Real         of = ((uint16_t)((res << 1) ^ res) >> 15) & 0x1; /* of = result15 ^
1135c97d6d2cSSergio Andres Gomez Del Real                                                             result14 */
1136c97d6d2cSSergio Andres Gomez Del Real         SET_FLAGS_OxxxxC(env, of, cf);
1137c97d6d2cSSergio Andres Gomez Del Real         break;
1138c97d6d2cSSergio Andres Gomez Del Real     }
1139c97d6d2cSSergio Andres Gomez Del Real     case 4:
1140c97d6d2cSSergio Andres Gomez Del Real     {
1141c97d6d2cSSergio Andres Gomez Del Real         uint32_t res;
1142c97d6d2cSSergio Andres Gomez Del Real         uint32_t op1_32 = decode->op[0].val;
1143c97d6d2cSSergio Andres Gomez Del Real 
1144c97d6d2cSSergio Andres Gomez Del Real         if (!count) {
1145c97d6d2cSSergio Andres Gomez Del Real             break;
1146c97d6d2cSSergio Andres Gomez Del Real         }
1147c97d6d2cSSergio Andres Gomez Del Real 
1148c97d6d2cSSergio Andres Gomez Del Real         if (1 == count) {
1149c97d6d2cSSergio Andres Gomez Del Real             res = (op1_32 >> 1) | (get_CF(env) << 31);
1150c97d6d2cSSergio Andres Gomez Del Real         } else {
1151c97d6d2cSSergio Andres Gomez Del Real             res = (op1_32 >> count) | (get_CF(env) << (32 - count)) |
1152c97d6d2cSSergio Andres Gomez Del Real                    (op1_32 << (33 - count));
1153c97d6d2cSSergio Andres Gomez Del Real         }
1154c97d6d2cSSergio Andres Gomez Del Real 
1155c97d6d2cSSergio Andres Gomez Del Real         write_val_ext(env, decode->op[0].ptr, res, 4);
1156c97d6d2cSSergio Andres Gomez Del Real 
1157c97d6d2cSSergio Andres Gomez Del Real         cf = (op1_32 >> (count - 1)) & 0x1;
1158c97d6d2cSSergio Andres Gomez Del Real         of = ((res << 1) ^ res) >> 31; /* of = result30 ^ result31 */
1159c97d6d2cSSergio Andres Gomez Del Real         SET_FLAGS_OxxxxC(env, of, cf);
1160c97d6d2cSSergio Andres Gomez Del Real         break;
1161c97d6d2cSSergio Andres Gomez Del Real         }
1162c97d6d2cSSergio Andres Gomez Del Real     }
11635d32173fSRoman Bolshakov     env->eip += decode->len;
1164c97d6d2cSSergio Andres Gomez Del Real }
1165c97d6d2cSSergio Andres Gomez Del Real 
116636861198SPhilippe Mathieu-Daudé static void exec_xchg(CPUX86State *env, struct x86_decode *decode)
1167c97d6d2cSSergio Andres Gomez Del Real {
1168c97d6d2cSSergio Andres Gomez Del Real     fetch_operands(env, decode, 2, true, true, false);
1169c97d6d2cSSergio Andres Gomez Del Real 
1170c97d6d2cSSergio Andres Gomez Del Real     write_val_ext(env, decode->op[0].ptr, decode->op[1].val,
1171c97d6d2cSSergio Andres Gomez Del Real                   decode->operand_size);
1172c97d6d2cSSergio Andres Gomez Del Real     write_val_ext(env, decode->op[1].ptr, decode->op[0].val,
1173c97d6d2cSSergio Andres Gomez Del Real                   decode->operand_size);
1174c97d6d2cSSergio Andres Gomez Del Real 
11755d32173fSRoman Bolshakov     env->eip += decode->len;
1176c97d6d2cSSergio Andres Gomez Del Real }
1177c97d6d2cSSergio Andres Gomez Del Real 
117836861198SPhilippe Mathieu-Daudé static void exec_xadd(CPUX86State *env, struct x86_decode *decode)
1179c97d6d2cSSergio Andres Gomez Del Real {
1180e8a63257SPaolo Bonzini     EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
1181c97d6d2cSSergio Andres Gomez Del Real     write_val_ext(env, decode->op[1].ptr, decode->op[0].val,
1182c97d6d2cSSergio Andres Gomez Del Real                   decode->operand_size);
1183c97d6d2cSSergio Andres Gomez Del Real 
11845d32173fSRoman Bolshakov     env->eip += decode->len;
1185c97d6d2cSSergio Andres Gomez Del Real }
1186c97d6d2cSSergio Andres Gomez Del Real 
1187c97d6d2cSSergio Andres Gomez Del Real static struct cmd_handler {
1188c97d6d2cSSergio Andres Gomez Del Real     enum x86_decode_cmd cmd;
118936861198SPhilippe Mathieu-Daudé     void (*handler)(CPUX86State *env, struct x86_decode *ins);
1190c97d6d2cSSergio Andres Gomez Del Real } handlers[] = {
1191c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_INVL, NULL,},
1192c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_MOV, exec_mov},
1193c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_ADD, exec_add},
1194c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_OR, exec_or},
1195c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_ADC, exec_adc},
1196c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_SBB, exec_sbb},
1197c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_AND, exec_and},
1198c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_SUB, exec_sub},
1199c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_NEG, exec_neg},
1200c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_XOR, exec_xor},
1201c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_CMP, exec_cmp},
1202c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_INC, exec_inc},
1203c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_DEC, exec_dec},
1204c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_TST, exec_tst},
1205c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_NOT, exec_not},
1206c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_MOVZX, exec_movzx},
1207c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_OUT, exec_out},
1208c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_IN, exec_in},
1209c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_INS, exec_ins},
1210c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_OUTS, exec_outs},
1211c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_RDMSR, exec_rdmsr},
1212c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_WRMSR, exec_wrmsr},
1213c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_BT, exec_bt},
1214c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_BTR, exec_btr},
1215c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_BTC, exec_btc},
1216c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_BTS, exec_bts},
1217c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_SHL, exec_shl},
1218c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_ROL, exec_rol},
1219c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_ROR, exec_ror},
1220c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_RCR, exec_rcr},
1221c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_RCL, exec_rcl},
1222c97d6d2cSSergio Andres Gomez Del Real     /*{X86_DECODE_CMD_CPUID, exec_cpuid},*/
1223c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_MOVS, exec_movs},
1224c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_CMPS, exec_cmps},
1225c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_STOS, exec_stos},
1226c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_SCAS, exec_scas},
1227c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_LODS, exec_lods},
1228c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_MOVSX, exec_movsx},
1229c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_XCHG, exec_xchg},
1230c97d6d2cSSergio Andres Gomez Del Real     {X86_DECODE_CMD_XADD, exec_xadd},
1231c97d6d2cSSergio Andres Gomez Del Real };
1232c97d6d2cSSergio Andres Gomez Del Real 
1233c97d6d2cSSergio Andres Gomez Del Real static struct cmd_handler _cmd_handler[X86_DECODE_CMD_LAST];
1234c97d6d2cSSergio Andres Gomez Del Real 
123526a44d9dSWei Liu const struct x86_emul_ops *emul_ops;
123626a44d9dSWei Liu 
12370e4e622eSPhil Dennis-Jordan static void init_cmd_handler(void)
1238c97d6d2cSSergio Andres Gomez Del Real {
1239c97d6d2cSSergio Andres Gomez Del Real     int i;
1240c97d6d2cSSergio Andres Gomez Del Real     for (i = 0; i < ARRAY_SIZE(handlers); i++) {
1241c97d6d2cSSergio Andres Gomez Del Real         _cmd_handler[handlers[i].cmd] = handlers[i];
1242c97d6d2cSSergio Andres Gomez Del Real     }
1243c97d6d2cSSergio Andres Gomez Del Real }
1244c97d6d2cSSergio Andres Gomez Del Real 
124536861198SPhilippe Mathieu-Daudé bool exec_instruction(CPUX86State *env, struct x86_decode *ins)
1246c97d6d2cSSergio Andres Gomez Del Real {
1247c97d6d2cSSergio Andres Gomez Del Real     if (!_cmd_handler[ins->cmd].handler) {
12485d32173fSRoman Bolshakov         printf("Unimplemented handler (%llx) for %d (%x %x) \n", env->eip,
1249c97d6d2cSSergio Andres Gomez Del Real                 ins->cmd, ins->opcode[0],
1250c97d6d2cSSergio Andres Gomez Del Real                 ins->opcode_len > 1 ? ins->opcode[1] : 0);
12515d32173fSRoman Bolshakov         env->eip += ins->len;
1252c97d6d2cSSergio Andres Gomez Del Real         return true;
1253c97d6d2cSSergio Andres Gomez Del Real     }
1254c97d6d2cSSergio Andres Gomez Del Real 
1255c97d6d2cSSergio Andres Gomez Del Real     _cmd_handler[ins->cmd].handler(env, ins);
1256c97d6d2cSSergio Andres Gomez Del Real     return true;
1257c97d6d2cSSergio Andres Gomez Del Real }
1258c97d6d2cSSergio Andres Gomez Del Real 
125926a44d9dSWei Liu void init_emu(const struct x86_emul_ops *o)
1260c97d6d2cSSergio Andres Gomez Del Real {
126126a44d9dSWei Liu     emul_ops = o;
1262c97d6d2cSSergio Andres Gomez Del Real     init_cmd_handler();
1263c97d6d2cSSergio Andres Gomez Del Real }
1264