diff options
author | Avi Kivity <avi@redhat.com> | 2011-09-07 09:41:35 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-09-25 12:52:32 -0400 |
commit | a31b9ceadb61487042dec92f662736ccddadc75f (patch) | |
tree | ff5d289f81bd302b085d1bef991f5e32924433eb /arch/x86/kvm | |
parent | 821246a5a548858c78a5e8860862e91c9e035d6b (diff) |
KVM: x86 emulator: simplify emulate_2op_SrcV()
emulate_2op_SrcV(), and its siblings, emulate_2op_SrcV_nobyte()
and emulate_2op_SrcB(), all use the same calling conventions
and all get passed exactly the same parameters. Simplify them
by passing just the emulation context.
Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/emulate.c | 90 |
1 files changed, 44 insertions, 46 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index fe5eb6d9b3e..458914d0f4b 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -205,64 +205,62 @@ struct gprefix { | |||
205 | #define ON64(x) | 205 | #define ON64(x) |
206 | #endif | 206 | #endif |
207 | 207 | ||
208 | #define ____emulate_2op(_op, _src, _dst, _eflags, _x, _y, _suffix, _dsttype) \ | 208 | #define ____emulate_2op(ctxt, _op, _x, _y, _suffix, _dsttype) \ |
209 | do { \ | 209 | do { \ |
210 | __asm__ __volatile__ ( \ | 210 | __asm__ __volatile__ ( \ |
211 | _PRE_EFLAGS("0", "4", "2") \ | 211 | _PRE_EFLAGS("0", "4", "2") \ |
212 | _op _suffix " %"_x"3,%1; " \ | 212 | _op _suffix " %"_x"3,%1; " \ |
213 | _POST_EFLAGS("0", "4", "2") \ | 213 | _POST_EFLAGS("0", "4", "2") \ |
214 | : "=m" (_eflags), "+q" (*(_dsttype*)&(_dst).val),\ | 214 | : "=m" ((ctxt)->eflags), \ |
215 | "+q" (*(_dsttype*)&(ctxt)->dst.val), \ | ||
215 | "=&r" (_tmp) \ | 216 | "=&r" (_tmp) \ |
216 | : _y ((_src).val), "i" (EFLAGS_MASK)); \ | 217 | : _y ((ctxt)->src.val), "i" (EFLAGS_MASK)); \ |
217 | } while (0) | 218 | } while (0) |
218 | 219 | ||
219 | 220 | ||
220 | /* Raw emulation: instruction has two explicit operands. */ | 221 | /* Raw emulation: instruction has two explicit operands. */ |
221 | #define __emulate_2op_nobyte(_op,_src,_dst,_eflags,_wx,_wy,_lx,_ly,_qx,_qy) \ | 222 | #define __emulate_2op_nobyte(ctxt,_op,_wx,_wy,_lx,_ly,_qx,_qy) \ |
222 | do { \ | 223 | do { \ |
223 | unsigned long _tmp; \ | 224 | unsigned long _tmp; \ |
224 | \ | 225 | \ |
225 | switch ((_dst).bytes) { \ | 226 | switch ((ctxt)->dst.bytes) { \ |
226 | case 2: \ | 227 | case 2: \ |
227 | ____emulate_2op(_op,_src,_dst,_eflags,_wx,_wy,"w",u16);\ | 228 | ____emulate_2op(ctxt,_op,_wx,_wy,"w",u16); \ |
228 | break; \ | 229 | break; \ |
229 | case 4: \ | 230 | case 4: \ |
230 | ____emulate_2op(_op,_src,_dst,_eflags,_lx,_ly,"l",u32);\ | 231 | ____emulate_2op(ctxt,_op,_lx,_ly,"l",u32); \ |
231 | break; \ | 232 | break; \ |
232 | case 8: \ | 233 | case 8: \ |
233 | ON64(____emulate_2op(_op,_src,_dst,_eflags,_qx,_qy,"q",u64)); \ | 234 | ON64(____emulate_2op(ctxt,_op,_qx,_qy,"q",u64)); \ |
234 | break; \ | 235 | break; \ |
235 | } \ | 236 | } \ |
236 | } while (0) | 237 | } while (0) |
237 | 238 | ||
238 | #define __emulate_2op(_op,_src,_dst,_eflags,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \ | 239 | #define __emulate_2op(ctxt,_op,_bx,_by,_wx,_wy,_lx,_ly,_qx,_qy) \ |
239 | do { \ | 240 | do { \ |
240 | unsigned long _tmp; \ | 241 | unsigned long _tmp; \ |
241 | switch ((_dst).bytes) { \ | 242 | switch ((ctxt)->dst.bytes) { \ |
242 | case 1: \ | 243 | case 1: \ |
243 | ____emulate_2op(_op,_src,_dst,_eflags,_bx,_by,"b",u8); \ | 244 | ____emulate_2op(ctxt,_op,_bx,_by,"b",u8); \ |
244 | break; \ | 245 | break; \ |
245 | default: \ | 246 | default: \ |
246 | __emulate_2op_nobyte(_op, _src, _dst, _eflags, \ | 247 | __emulate_2op_nobyte(ctxt, _op, \ |
247 | _wx, _wy, _lx, _ly, _qx, _qy); \ | 248 | _wx, _wy, _lx, _ly, _qx, _qy); \ |
248 | break; \ | 249 | break; \ |
249 | } \ | 250 | } \ |
250 | } while (0) | 251 | } while (0) |
251 | 252 | ||
252 | /* Source operand is byte-sized and may be restricted to just %cl. */ | 253 | /* Source operand is byte-sized and may be restricted to just %cl. */ |
253 | #define emulate_2op_SrcB(_op, _src, _dst, _eflags) \ | 254 | #define emulate_2op_SrcB(ctxt, _op) \ |
254 | __emulate_2op(_op, _src, _dst, _eflags, \ | 255 | __emulate_2op(ctxt, _op, "b", "c", "b", "c", "b", "c", "b", "c") |
255 | "b", "c", "b", "c", "b", "c", "b", "c") | ||
256 | 256 | ||
257 | /* Source operand is byte, word, long or quad sized. */ | 257 | /* Source operand is byte, word, long or quad sized. */ |
258 | #define emulate_2op_SrcV(_op, _src, _dst, _eflags) \ | 258 | #define emulate_2op_SrcV(ctxt, _op) \ |
259 | __emulate_2op(_op, _src, _dst, _eflags, \ | 259 | __emulate_2op(ctxt, _op, "b", "q", "w", "r", _LO32, "r", "", "r") |
260 | "b", "q", "w", "r", _LO32, "r", "", "r") | ||
261 | 260 | ||
262 | /* Source operand is word, long or quad sized. */ | 261 | /* Source operand is word, long or quad sized. */ |
263 | #define emulate_2op_SrcV_nobyte(_op, _src, _dst, _eflags) \ | 262 | #define emulate_2op_SrcV_nobyte(ctxt, _op) \ |
264 | __emulate_2op_nobyte(_op, _src, _dst, _eflags, \ | 263 | __emulate_2op_nobyte(ctxt, _op, "w", "r", _LO32, "r", "", "r") |
265 | "w", "r", _LO32, "r", "", "r") | ||
266 | 264 | ||
267 | /* Instruction has three operands and one operand is stored in ECX register */ | 265 | /* Instruction has three operands and one operand is stored in ECX register */ |
268 | #define __emulate_2op_cl(_op, _cl, _src, _dst, _eflags, _suffix, _type) \ | 266 | #define __emulate_2op_cl(_op, _cl, _src, _dst, _eflags, _suffix, _type) \ |
@@ -1681,26 +1679,26 @@ static int em_grp2(struct x86_emulate_ctxt *ctxt) | |||
1681 | { | 1679 | { |
1682 | switch (ctxt->modrm_reg) { | 1680 | switch (ctxt->modrm_reg) { |
1683 | case 0: /* rol */ | 1681 | case 0: /* rol */ |
1684 | emulate_2op_SrcB("rol", ctxt->src, ctxt->dst, ctxt->eflags); | 1682 | emulate_2op_SrcB(ctxt, "rol"); |
1685 | break; | 1683 | break; |
1686 | case 1: /* ror */ | 1684 | case 1: /* ror */ |
1687 | emulate_2op_SrcB("ror", ctxt->src, ctxt->dst, ctxt->eflags); | 1685 | emulate_2op_SrcB(ctxt, "ror"); |
1688 | break; | 1686 | break; |
1689 | case 2: /* rcl */ | 1687 | case 2: /* rcl */ |
1690 | emulate_2op_SrcB("rcl", ctxt->src, ctxt->dst, ctxt->eflags); | 1688 | emulate_2op_SrcB(ctxt, "rcl"); |
1691 | break; | 1689 | break; |
1692 | case 3: /* rcr */ | 1690 | case 3: /* rcr */ |
1693 | emulate_2op_SrcB("rcr", ctxt->src, ctxt->dst, ctxt->eflags); | 1691 | emulate_2op_SrcB(ctxt, "rcr"); |
1694 | break; | 1692 | break; |
1695 | case 4: /* sal/shl */ | 1693 | case 4: /* sal/shl */ |
1696 | case 6: /* sal/shl */ | 1694 | case 6: /* sal/shl */ |
1697 | emulate_2op_SrcB("sal", ctxt->src, ctxt->dst, ctxt->eflags); | 1695 | emulate_2op_SrcB(ctxt, "sal"); |
1698 | break; | 1696 | break; |
1699 | case 5: /* shr */ | 1697 | case 5: /* shr */ |
1700 | emulate_2op_SrcB("shr", ctxt->src, ctxt->dst, ctxt->eflags); | 1698 | emulate_2op_SrcB(ctxt, "shr"); |
1701 | break; | 1699 | break; |
1702 | case 7: /* sar */ | 1700 | case 7: /* sar */ |
1703 | emulate_2op_SrcB("sar", ctxt->src, ctxt->dst, ctxt->eflags); | 1701 | emulate_2op_SrcB(ctxt, "sar"); |
1704 | break; | 1702 | break; |
1705 | } | 1703 | } |
1706 | return X86EMUL_CONTINUE; | 1704 | return X86EMUL_CONTINUE; |
@@ -1714,7 +1712,7 @@ static int em_grp3(struct x86_emulate_ctxt *ctxt) | |||
1714 | 1712 | ||
1715 | switch (ctxt->modrm_reg) { | 1713 | switch (ctxt->modrm_reg) { |
1716 | case 0 ... 1: /* test */ | 1714 | case 0 ... 1: /* test */ |
1717 | emulate_2op_SrcV("test", ctxt->src, ctxt->dst, ctxt->eflags); | 1715 | emulate_2op_SrcV(ctxt, "test"); |
1718 | break; | 1716 | break; |
1719 | case 2: /* not */ | 1717 | case 2: /* not */ |
1720 | ctxt->dst.val = ~ctxt->dst.val; | 1718 | ctxt->dst.val = ~ctxt->dst.val; |
@@ -2459,7 +2457,7 @@ static int em_das(struct x86_emulate_ctxt *ctxt) | |||
2459 | ctxt->src.type = OP_IMM; | 2457 | ctxt->src.type = OP_IMM; |
2460 | ctxt->src.val = 0; | 2458 | ctxt->src.val = 0; |
2461 | ctxt->src.bytes = 1; | 2459 | ctxt->src.bytes = 1; |
2462 | emulate_2op_SrcV("or", ctxt->src, ctxt->dst, ctxt->eflags); | 2460 | emulate_2op_SrcV(ctxt, "or"); |
2463 | ctxt->eflags &= ~(X86_EFLAGS_AF | X86_EFLAGS_CF); | 2461 | ctxt->eflags &= ~(X86_EFLAGS_AF | X86_EFLAGS_CF); |
2464 | if (cf) | 2462 | if (cf) |
2465 | ctxt->eflags |= X86_EFLAGS_CF; | 2463 | ctxt->eflags |= X86_EFLAGS_CF; |
@@ -2509,49 +2507,49 @@ static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt) | |||
2509 | 2507 | ||
2510 | static int em_add(struct x86_emulate_ctxt *ctxt) | 2508 | static int em_add(struct x86_emulate_ctxt *ctxt) |
2511 | { | 2509 | { |
2512 | emulate_2op_SrcV("add", ctxt->src, ctxt->dst, ctxt->eflags); | 2510 | emulate_2op_SrcV(ctxt, "add"); |
2513 | return X86EMUL_CONTINUE; | 2511 | return X86EMUL_CONTINUE; |
2514 | } | 2512 | } |
2515 | 2513 | ||
2516 | static int em_or(struct x86_emulate_ctxt *ctxt) | 2514 | static int em_or(struct x86_emulate_ctxt *ctxt) |
2517 | { | 2515 | { |
2518 | emulate_2op_SrcV("or", ctxt->src, ctxt->dst, ctxt->eflags); | 2516 | emulate_2op_SrcV(ctxt, "or"); |
2519 | return X86EMUL_CONTINUE; | 2517 | return X86EMUL_CONTINUE; |
2520 | } | 2518 | } |
2521 | 2519 | ||
2522 | static int em_adc(struct x86_emulate_ctxt *ctxt) | 2520 | static int em_adc(struct x86_emulate_ctxt *ctxt) |
2523 | { | 2521 | { |
2524 | emulate_2op_SrcV("adc", ctxt->src, ctxt->dst, ctxt->eflags); | 2522 | emulate_2op_SrcV(ctxt, "adc"); |
2525 | return X86EMUL_CONTINUE; | 2523 | return X86EMUL_CONTINUE; |
2526 | } | 2524 | } |
2527 | 2525 | ||
2528 | static int em_sbb(struct x86_emulate_ctxt *ctxt) | 2526 | static int em_sbb(struct x86_emulate_ctxt *ctxt) |
2529 | { | 2527 | { |
2530 | emulate_2op_SrcV("sbb", ctxt->src, ctxt->dst, ctxt->eflags); | 2528 | emulate_2op_SrcV(ctxt, "sbb"); |
2531 | return X86EMUL_CONTINUE; | 2529 | return X86EMUL_CONTINUE; |
2532 | } | 2530 | } |
2533 | 2531 | ||
2534 | static int em_and(struct x86_emulate_ctxt *ctxt) | 2532 | static int em_and(struct x86_emulate_ctxt *ctxt) |
2535 | { | 2533 | { |
2536 | emulate_2op_SrcV("and", ctxt->src, ctxt->dst, ctxt->eflags); | 2534 | emulate_2op_SrcV(ctxt, "and"); |
2537 | return X86EMUL_CONTINUE; | 2535 | return X86EMUL_CONTINUE; |
2538 | } | 2536 | } |
2539 | 2537 | ||
2540 | static int em_sub(struct x86_emulate_ctxt *ctxt) | 2538 | static int em_sub(struct x86_emulate_ctxt *ctxt) |
2541 | { | 2539 | { |
2542 | emulate_2op_SrcV("sub", ctxt->src, ctxt->dst, ctxt->eflags); | 2540 | emulate_2op_SrcV(ctxt, "sub"); |
2543 | return X86EMUL_CONTINUE; | 2541 | return X86EMUL_CONTINUE; |
2544 | } | 2542 | } |
2545 | 2543 | ||
2546 | static int em_xor(struct x86_emulate_ctxt *ctxt) | 2544 | static int em_xor(struct x86_emulate_ctxt *ctxt) |
2547 | { | 2545 | { |
2548 | emulate_2op_SrcV("xor", ctxt->src, ctxt->dst, ctxt->eflags); | 2546 | emulate_2op_SrcV(ctxt, "xor"); |
2549 | return X86EMUL_CONTINUE; | 2547 | return X86EMUL_CONTINUE; |
2550 | } | 2548 | } |
2551 | 2549 | ||
2552 | static int em_cmp(struct x86_emulate_ctxt *ctxt) | 2550 | static int em_cmp(struct x86_emulate_ctxt *ctxt) |
2553 | { | 2551 | { |
2554 | emulate_2op_SrcV("cmp", ctxt->src, ctxt->dst, ctxt->eflags); | 2552 | emulate_2op_SrcV(ctxt, "cmp"); |
2555 | /* Disable writeback. */ | 2553 | /* Disable writeback. */ |
2556 | ctxt->dst.type = OP_NONE; | 2554 | ctxt->dst.type = OP_NONE; |
2557 | return X86EMUL_CONTINUE; | 2555 | return X86EMUL_CONTINUE; |
@@ -2559,7 +2557,7 @@ static int em_cmp(struct x86_emulate_ctxt *ctxt) | |||
2559 | 2557 | ||
2560 | static int em_test(struct x86_emulate_ctxt *ctxt) | 2558 | static int em_test(struct x86_emulate_ctxt *ctxt) |
2561 | { | 2559 | { |
2562 | emulate_2op_SrcV("test", ctxt->src, ctxt->dst, ctxt->eflags); | 2560 | emulate_2op_SrcV(ctxt, "test"); |
2563 | return X86EMUL_CONTINUE; | 2561 | return X86EMUL_CONTINUE; |
2564 | } | 2562 | } |
2565 | 2563 | ||
@@ -2577,7 +2575,7 @@ static int em_xchg(struct x86_emulate_ctxt *ctxt) | |||
2577 | 2575 | ||
2578 | static int em_imul(struct x86_emulate_ctxt *ctxt) | 2576 | static int em_imul(struct x86_emulate_ctxt *ctxt) |
2579 | { | 2577 | { |
2580 | emulate_2op_SrcV_nobyte("imul", ctxt->src, ctxt->dst, ctxt->eflags); | 2578 | emulate_2op_SrcV_nobyte(ctxt, "imul"); |
2581 | return X86EMUL_CONTINUE; | 2579 | return X86EMUL_CONTINUE; |
2582 | } | 2580 | } |
2583 | 2581 | ||
@@ -4121,7 +4119,7 @@ twobyte_insn: | |||
4121 | ctxt->dst.type = OP_NONE; | 4119 | ctxt->dst.type = OP_NONE; |
4122 | /* only subword offset */ | 4120 | /* only subword offset */ |
4123 | ctxt->src.val &= (ctxt->dst.bytes << 3) - 1; | 4121 | ctxt->src.val &= (ctxt->dst.bytes << 3) - 1; |
4124 | emulate_2op_SrcV_nobyte("bt", ctxt->src, ctxt->dst, ctxt->eflags); | 4122 | emulate_2op_SrcV_nobyte(ctxt, "bt"); |
4125 | break; | 4123 | break; |
4126 | case 0xa4: /* shld imm8, r, r/m */ | 4124 | case 0xa4: /* shld imm8, r, r/m */ |
4127 | case 0xa5: /* shld cl, r, r/m */ | 4125 | case 0xa5: /* shld cl, r, r/m */ |
@@ -4135,7 +4133,7 @@ twobyte_insn: | |||
4135 | break; | 4133 | break; |
4136 | case 0xab: | 4134 | case 0xab: |
4137 | bts: /* bts */ | 4135 | bts: /* bts */ |
4138 | emulate_2op_SrcV_nobyte("bts", ctxt->src, ctxt->dst, ctxt->eflags); | 4136 | emulate_2op_SrcV_nobyte(ctxt, "bts"); |
4139 | break; | 4137 | break; |
4140 | case 0xac: /* shrd imm8, r, r/m */ | 4138 | case 0xac: /* shrd imm8, r, r/m */ |
4141 | case 0xad: /* shrd cl, r, r/m */ | 4139 | case 0xad: /* shrd cl, r, r/m */ |
@@ -4150,7 +4148,7 @@ twobyte_insn: | |||
4150 | */ | 4148 | */ |
4151 | ctxt->src.orig_val = ctxt->src.val; | 4149 | ctxt->src.orig_val = ctxt->src.val; |
4152 | ctxt->src.val = ctxt->regs[VCPU_REGS_RAX]; | 4150 | ctxt->src.val = ctxt->regs[VCPU_REGS_RAX]; |
4153 | emulate_2op_SrcV("cmp", ctxt->src, ctxt->dst, ctxt->eflags); | 4151 | emulate_2op_SrcV(ctxt, "cmp"); |
4154 | if (ctxt->eflags & EFLG_ZF) { | 4152 | if (ctxt->eflags & EFLG_ZF) { |
4155 | /* Success: write back to memory. */ | 4153 | /* Success: write back to memory. */ |
4156 | ctxt->dst.val = ctxt->src.orig_val; | 4154 | ctxt->dst.val = ctxt->src.orig_val; |
@@ -4165,7 +4163,7 @@ twobyte_insn: | |||
4165 | break; | 4163 | break; |
4166 | case 0xb3: | 4164 | case 0xb3: |
4167 | btr: /* btr */ | 4165 | btr: /* btr */ |
4168 | emulate_2op_SrcV_nobyte("btr", ctxt->src, ctxt->dst, ctxt->eflags); | 4166 | emulate_2op_SrcV_nobyte(ctxt, "btr"); |
4169 | break; | 4167 | break; |
4170 | case 0xb4: /* lfs */ | 4168 | case 0xb4: /* lfs */ |
4171 | rc = emulate_load_segment(ctxt, VCPU_SREG_FS); | 4169 | rc = emulate_load_segment(ctxt, VCPU_SREG_FS); |
@@ -4192,7 +4190,7 @@ twobyte_insn: | |||
4192 | break; | 4190 | break; |
4193 | case 0xbb: | 4191 | case 0xbb: |
4194 | btc: /* btc */ | 4192 | btc: /* btc */ |
4195 | emulate_2op_SrcV_nobyte("btc", ctxt->src, ctxt->dst, ctxt->eflags); | 4193 | emulate_2op_SrcV_nobyte(ctxt, "btc"); |
4196 | break; | 4194 | break; |
4197 | case 0xbc: { /* bsf */ | 4195 | case 0xbc: { /* bsf */ |
4198 | u8 zf; | 4196 | u8 zf; |
@@ -4224,7 +4222,7 @@ twobyte_insn: | |||
4224 | (s16) ctxt->src.val; | 4222 | (s16) ctxt->src.val; |
4225 | break; | 4223 | break; |
4226 | case 0xc0 ... 0xc1: /* xadd */ | 4224 | case 0xc0 ... 0xc1: /* xadd */ |
4227 | emulate_2op_SrcV("add", ctxt->src, ctxt->dst, ctxt->eflags); | 4225 | emulate_2op_SrcV(ctxt, "add"); |
4228 | /* Write back the register source. */ | 4226 | /* Write back the register source. */ |
4229 | ctxt->src.val = ctxt->dst.orig_val; | 4227 | ctxt->src.val = ctxt->dst.orig_val; |
4230 | write_register_operand(&ctxt->src); | 4228 | write_register_operand(&ctxt->src); |