Guillaume Thouvenin wrote:
On Tue, 04 Nov 2008 12:21:30 +0200
Avi Kivity <[EMAIL PROTECTED]> 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
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html