aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorMohammed Gamal <m.gamal005@gmail.com>2010-08-08 14:11:37 -0400
committerAvi Kivity <avi@redhat.com>2010-10-24 04:51:04 -0400
commit3f9f53b0d599aabb03db35208fb31768568ca83f (patch)
treed11accb85b182bd51df8ea96860ca26cafc9fb7b /arch/x86/kvm/emulate.c
parentba7ff2b76dcf05c4681c2648019b8301ada6f3df (diff)
KVM: x86 emulator: Add unary mul, imul, div, and idiv instructions
This adds unary mul, imul, div, and idiv instructions (group 3 r/m 4-7). Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index a9b2b9e6a3f0..f0415eab6591 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -315,6 +315,31 @@ struct group_dual {
315 } \ 315 } \
316 } while (0) 316 } while (0)
317 317
318#define __emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags, _suffix) \
319 do { \
320 unsigned long _tmp; \
321 \
322 __asm__ __volatile__ ( \
323 _PRE_EFLAGS("0", "4", "1") \
324 _op _suffix " %5; " \
325 _POST_EFLAGS("0", "4", "1") \
326 : "=m" (_eflags), "=&r" (_tmp), \
327 "+a" (_rax), "+d" (_rdx) \
328 : "i" (EFLAGS_MASK), "m" ((_src).val), \
329 "a" (_rax), "d" (_rdx)); \
330 } while (0)
331
332/* instruction has only one source operand, destination is implicit (e.g. mul, div, imul, idiv) */
333#define emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags) \
334 do { \
335 switch((_src).bytes) { \
336 case 1: __emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags, "b"); break; \
337 case 2: __emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags, "w"); break; \
338 case 4: __emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags, "l"); break; \
339 case 8: ON64(__emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags, "q")); break; \
340 } \
341 } while (0)
342
318/* Fetch next part of the instruction being emulated. */ 343/* Fetch next part of the instruction being emulated. */
319#define insn_fetch(_type, _size, _eip) \ 344#define insn_fetch(_type, _size, _eip) \
320({ unsigned long _x; \ 345({ unsigned long _x; \
@@ -1373,6 +1398,8 @@ static inline int emulate_grp3(struct x86_emulate_ctxt *ctxt,
1373 struct x86_emulate_ops *ops) 1398 struct x86_emulate_ops *ops)
1374{ 1399{
1375 struct decode_cache *c = &ctxt->decode; 1400 struct decode_cache *c = &ctxt->decode;
1401 unsigned long *rax = &c->regs[VCPU_REGS_RAX];
1402 unsigned long *rdx = &c->regs[VCPU_REGS_RDX];
1376 1403
1377 switch (c->modrm_reg) { 1404 switch (c->modrm_reg) {
1378 case 0 ... 1: /* test */ 1405 case 0 ... 1: /* test */
@@ -1384,6 +1411,18 @@ static inline int emulate_grp3(struct x86_emulate_ctxt *ctxt,
1384 case 3: /* neg */ 1411 case 3: /* neg */
1385 emulate_1op("neg", c->dst, ctxt->eflags); 1412 emulate_1op("neg", c->dst, ctxt->eflags);
1386 break; 1413 break;
1414 case 4: /* mul */
1415 emulate_1op_rax_rdx("mul", c->src, *rax, *rdx, ctxt->eflags);
1416 break;
1417 case 5: /* imul */
1418 emulate_1op_rax_rdx("imul", c->src, *rax, *rdx, ctxt->eflags);
1419 break;
1420 case 6: /* div */
1421 emulate_1op_rax_rdx("div", c->src, *rax, *rdx, ctxt->eflags);
1422 break;
1423 case 7: /* idiv */
1424 emulate_1op_rax_rdx("idiv", c->src, *rax, *rdx, ctxt->eflags);
1425 break;
1387 default: 1426 default:
1388 return 0; 1427 return 0;
1389 } 1428 }
@@ -2138,7 +2177,7 @@ static struct opcode group1A[] = {
2138static struct opcode group3[] = { 2177static struct opcode group3[] = {
2139 D(DstMem | SrcImm | ModRM), D(DstMem | SrcImm | ModRM), 2178 D(DstMem | SrcImm | ModRM), D(DstMem | SrcImm | ModRM),
2140 D(DstMem | SrcNone | ModRM | Lock), D(DstMem | SrcNone | ModRM | Lock), 2179 D(DstMem | SrcNone | ModRM | Lock), D(DstMem | SrcNone | ModRM | Lock),
2141 X4(D(Undefined)), 2180 X4(D(SrcMem | ModRM)),
2142}; 2181};
2143 2182
2144static struct opcode group4[] = { 2183static struct opcode group4[] = {