From mboxrd@z Thu Jan 1 00:00:00 1970 From: Avi Kivity Subject: Re: [Patch 4/5] x86_emulator: add the assembler code for three operands Date: Tue, 25 Nov 2008 16:59:00 +0200 Message-ID: <492C12B4.4050700@redhat.com> References: <20081103160036.499cb482@frecb000711> <20081103160504.3fa8c378@frecb000711> <4910222A.20201@redhat.com> <20081125085918.45bb29d2@frecb000711> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII; format=flowed Content-Transfer-Encoding: 7bit Cc: kvm To: Guillaume Thouvenin Return-path: Received: from mx2.redhat.com ([66.187.237.31]:40908 "EHLO mx2.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751128AbYKYO7q (ORCPT ); Tue, 25 Nov 2008 09:59:46 -0500 In-Reply-To: <20081125085918.45bb29d2@frecb000711> Sender: kvm-owner@vger.kernel.org List-ID: Guillaume Thouvenin wrote: > On Tue, 04 Nov 2008 12:21:30 +0200 > Avi Kivity wrote: > > >> Guillaume Thouvenin wrote: >> >>> Add the assembler code for three operands >>> >>> >>> +/* Instruction has three operands */ >>> +/* In the switch we only implement case 4 because we know that for shld instruction >>> + * bytes are equal to 4. When eveything will be fine, we will add others cases. >>> >>> >> No, shld is defined for 16, 32, and 64 bit operands. Need to implement >> those too. >> > > I tried something like: > > +/* Instruction has three operands */ > +/* In the switch we only implement case 4 because we know that for shld instruction > + * bytes are equal to 4. When eveything will be fine, we will add others cases. > + */ > +#define __emulate_2op_cl(_op,_src,_src2,_dst,_eflags,_by,_bx,_wx,_wy,_lx,_ly,_qx,_qy) \ > + do { \ > + unsigned long _tmp; \ > + \ > + switch((_dst).bytes) { \ > + case 2: \ > + __asm__ __volatile__ ( \ > + _PRE_EFLAGS("0", "5", "2") \ > + "mov %4, %%rcx \n\t" \ > + _op"w %%cl,%3,%1; \n\t" \ > + _POST_EFLAGS("0", "5", "2") \ > + : "=m" (_eflags), "=m" ((_dst).val), \ > + "=&r" (_tmp) \ > + : _wy ((_src).val) , _wy ((_src2).val), "i" (EFLAGS_MASK) \ > + : "%rcx" ); \ > + break; \ > + case 4: \ > + __asm__ __volatile__ ( \ > + _PRE_EFLAGS("0", "5", "2") \ > + "mov %4, %%rcx \n\t" \ > + _op"l %%cl,%3,%1; \n\t" \ > + _POST_EFLAGS("0", "5", "2") \ > + : "=m" (_eflags), "=m" ((_dst).val), \ > + "=&r" (_tmp) \ > + : _ly ((_src).val) , _ly ((_src2).val), "i" (EFLAGS_MASK) \ > + : "%rcx" ); \ > + break; \ > + case 8: \ > + __asm__ __volatile__ ( \ > + _PRE_EFLAGS("0", "5", "2") \ > + "mov %4, %%rcx \n\t" \ > + _op"q %%cl,%3,%1; \n\t" \ > + _POST_EFLAGS("0", "5", "2") \ > + : "=m" (_eflags), "=m" ((_dst).val), \ > + "=&r" (_tmp) \ > + : _ly ((_src).val) , _ly ((_src2).val), "i" (EFLAGS_MASK) \ > + : "%rcx" ); \ > + break; \ > + } \ > + } while (0) > + > +#define emulate_2op_cl(_op, _src, _src2, _dst, _eflags) \ > + __emulate_2op_cl(_op, _src, _src2, _dst, _eflags, \ > + "b", "r", "b", "r", "b", "r", "b", "r") > + > > but it doesn't work because shld can not be used with suffix 'l' or 'w' > etc... Is the solution is to have a single case for all operand size like: > > It does work, perhaps the variables were defined with the wrong size. This works: int shld(void) { unsigned short w1 = 3, w2 = 5; unsigned int l1 = 3, l2 = 5; unsigned long q1 = 3, q2 = 5; asm("shldw %1, %0" : "+r"(w1) : "r"(w2)); asm("shldl %1, %0" : "+r"(l1) : "r"(l2)); asm("shldq %1, %0" : "+r"(q1) : "r"(q2)); return w1 + l1 + q1; } > +#define __emulate_2op_cl(_op,_src,_src2,_dst,_eflags,_wx,_wy) \ > + do { \ > + unsigned long _tmp; \ > + \ > + __asm__ __volatile__ ( \ > + _PRE_EFLAGS("0", "5", "2") \ > + "mov %4, %%rcx \n\t" \ > + _op" %%cl,%3,%1; \n\t" \ > + _POST_EFLAGS("0", "5", "2") \ > + : "=m" (_eflags), "=m" ((_dst).val), \ > + "=&r" (_tmp) \ > + : _wy ((_src).val) , _wy ((_src2).val), "i" (EFLAGS_MASK) \ > + : "%rcx" ); \ > + } while (0) > > I tested the code and it seems to work. > That's actually better and could be used for the other emulations. Please disassemble x86_emulate.o and verify that there are three different shld instructions, one for each register size. -- error compiling committee.c: too many arguments to function