1 /**************************************************************************
2  *
3  * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  **************************************************************************/
24 
25 #include "pipe/p_config.h"
26 #include "util/u_cpu_detect.h"
27 
28 #if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
29 
30 #include "pipe/p_compiler.h"
31 #include "util/u_debug.h"
32 #include "util/u_pointer.h"
33 
34 #include "rtasm_execmem.h"
35 #include "rtasm_x86sse.h"
36 
37 #define DISASSEM 0
38 #define X86_TWOB 0x0f
39 
40 
41 #define DUMP_SSE  0
42 
43 
x86_print_reg(struct x86_reg reg)44 void x86_print_reg( struct x86_reg reg )
45 {
46    if (reg.mod != mod_REG)
47       debug_printf( "[" );
48 
49    switch( reg.file ) {
50    case file_REG32:
51       switch( reg.idx ) {
52       case reg_AX: debug_printf( "EAX" ); break;
53       case reg_CX: debug_printf( "ECX" ); break;
54       case reg_DX: debug_printf( "EDX" ); break;
55       case reg_BX: debug_printf( "EBX" ); break;
56       case reg_SP: debug_printf( "ESP" ); break;
57       case reg_BP: debug_printf( "EBP" ); break;
58       case reg_SI: debug_printf( "ESI" ); break;
59       case reg_DI: debug_printf( "EDI" ); break;
60       }
61       break;
62    case file_MMX:
63       debug_printf( "MMX%u", reg.idx );
64       break;
65    case file_XMM:
66       debug_printf( "XMM%u", reg.idx );
67       break;
68    case file_x87:
69       debug_printf( "fp%u", reg.idx );
70       break;
71    }
72 
73    if (reg.mod == mod_DISP8 ||
74        reg.mod == mod_DISP32)
75       debug_printf("+%d", reg.disp);
76 
77    if (reg.mod != mod_REG)
78       debug_printf( "]" );
79 }
80 
81 #if DUMP_SSE
82 
83 #define DUMP_START() debug_printf( "\n" )
84 #define DUMP_END() debug_printf( "\n" )
85 
86 #define DUMP() do {                             \
87    const char *foo = __FUNCTION__;              \
88    while (*foo && *foo != '_')                  \
89       foo++;                                    \
90    if  (*foo)                                   \
91       foo++;                                    \
92    debug_printf( "\n%4x %14s ", p->csr - p->store, foo );             \
93 } while (0)
94 
95 #define DUMP_I( I ) do {                        \
96    DUMP();                                      \
97    debug_printf( "%u", I );                     \
98 } while( 0 )
99 
100 #define DUMP_R( R0 ) do {                       \
101    DUMP();                                      \
102    x86_print_reg( R0 );                            \
103 } while( 0 )
104 
105 #define DUMP_RR( R0, R1 ) do {                  \
106    DUMP();                                      \
107    x86_print_reg( R0 );                            \
108    debug_printf( ", " );                        \
109    x86_print_reg( R1 );                            \
110 } while( 0 )
111 
112 #define DUMP_RI( R0, I ) do {                   \
113    DUMP();                                      \
114    x86_print_reg( R0 );                            \
115    debug_printf( ", %u", I );                   \
116 } while( 0 )
117 
118 #define DUMP_RRI( R0, R1, I ) do {              \
119    DUMP();                                      \
120    x86_print_reg( R0 );                            \
121    debug_printf( ", " );                        \
122    x86_print_reg( R1 );                            \
123    debug_printf( ", %u", I );                   \
124 } while( 0 )
125 
126 #else
127 
128 #define DUMP_START()
129 #define DUMP_END()
130 #define DUMP( )
131 #define DUMP_I( I )
132 #define DUMP_R( R0 )
133 #define DUMP_RR( R0, R1 )
134 #define DUMP_RI( R0, I )
135 #define DUMP_RRI( R0, R1, I )
136 
137 #endif
138 
139 
do_realloc(struct x86_function * p)140 static void do_realloc( struct x86_function *p )
141 {
142    if (p->store == p->error_overflow) {
143       p->csr = p->store;
144    }
145    else if (p->size == 0) {
146       p->size = 1024;
147       p->store = rtasm_exec_malloc(p->size);
148       p->csr = p->store;
149    }
150    else {
151       uintptr_t used = pointer_to_uintptr( p->csr ) - pointer_to_uintptr( p->store );
152       unsigned char *tmp = p->store;
153       p->size *= 2;
154       p->store = rtasm_exec_malloc(p->size);
155 
156       if (p->store) {
157          memcpy(p->store, tmp, used);
158          p->csr = p->store + used;
159       }
160       else {
161          p->csr = p->store;
162       }
163 
164       rtasm_exec_free(tmp);
165    }
166 
167    if (p->store == NULL) {
168       p->store = p->csr = p->error_overflow;
169       p->size = sizeof(p->error_overflow);
170    }
171 }
172 
173 /* Emit bytes to the instruction stream:
174  */
reserve(struct x86_function * p,int bytes)175 static unsigned char *reserve( struct x86_function *p, int bytes )
176 {
177    if (p->csr + bytes - p->store > (int) p->size)
178       do_realloc(p);
179 
180    {
181       unsigned char *csr = p->csr;
182       p->csr += bytes;
183       return csr;
184    }
185 }
186 
187 
188 
emit_1b(struct x86_function * p,char b0)189 static void emit_1b( struct x86_function *p, char b0 )
190 {
191    char *csr = (char *)reserve(p, 1);
192    *csr = b0;
193 }
194 
emit_1i(struct x86_function * p,int i0)195 static void emit_1i( struct x86_function *p, int i0 )
196 {
197    int *icsr = (int *)reserve(p, sizeof(i0));
198    *icsr = i0;
199 }
200 
emit_1ub(struct x86_function * p,unsigned char b0)201 static void emit_1ub( struct x86_function *p, unsigned char b0 )
202 {
203    unsigned char *csr = reserve(p, 1);
204    *csr++ = b0;
205 }
206 
emit_2ub(struct x86_function * p,unsigned char b0,unsigned char b1)207 static void emit_2ub( struct x86_function *p, unsigned char b0, unsigned char b1 )
208 {
209    unsigned char *csr = reserve(p, 2);
210    *csr++ = b0;
211    *csr++ = b1;
212 }
213 
emit_3ub(struct x86_function * p,unsigned char b0,unsigned char b1,unsigned char b2)214 static void emit_3ub( struct x86_function *p, unsigned char b0, unsigned char b1, unsigned char b2 )
215 {
216    unsigned char *csr = reserve(p, 3);
217    *csr++ = b0;
218    *csr++ = b1;
219    *csr++ = b2;
220 }
221 
222 
223 /* Build a modRM byte + possible displacement.  No treatment of SIB
224  * indexing.  BZZT - no way to encode an absolute address.
225  *
226  * This is the "/r" field in the x86 manuals...
227  */
emit_modrm(struct x86_function * p,struct x86_reg reg,struct x86_reg regmem)228 static void emit_modrm( struct x86_function *p,
229 			struct x86_reg reg,
230 			struct x86_reg regmem )
231 {
232    unsigned char val = 0;
233 
234    assert(reg.mod == mod_REG);
235 
236    /* TODO: support extended x86-64 registers */
237    assert(reg.idx < 8);
238    assert(regmem.idx < 8);
239 
240    val |= regmem.mod << 6;     	/* mod field */
241    val |= reg.idx << 3;		/* reg field */
242    val |= regmem.idx;		/* r/m field */
243 
244    emit_1ub(p, val);
245 
246    /* Oh-oh we've stumbled into the SIB thing.
247     */
248    if (regmem.file == file_REG32 &&
249        regmem.idx == reg_SP &&
250        regmem.mod != mod_REG) {
251       emit_1ub(p, 0x24);		/* simplistic! */
252    }
253 
254    switch (regmem.mod) {
255    case mod_REG:
256    case mod_INDIRECT:
257       break;
258    case mod_DISP8:
259       emit_1b(p, (char) regmem.disp);
260       break;
261    case mod_DISP32:
262       emit_1i(p, regmem.disp);
263       break;
264    default:
265       assert(0);
266       break;
267    }
268 }
269 
270 /* Emits the "/0".."/7" specialized versions of the modrm ("/r") bytes.
271  */
emit_modrm_noreg(struct x86_function * p,unsigned op,struct x86_reg regmem)272 static void emit_modrm_noreg( struct x86_function *p,
273 			      unsigned op,
274 			      struct x86_reg regmem )
275 {
276    struct x86_reg dummy = x86_make_reg(file_REG32, op);
277    emit_modrm(p, dummy, regmem);
278 }
279 
280 /* Many x86 instructions have two opcodes to cope with the situations
281  * where the destination is a register or memory reference
282  * respectively.  This function selects the correct opcode based on
283  * the arguments presented.
284  */
emit_op_modrm(struct x86_function * p,unsigned char op_dst_is_reg,unsigned char op_dst_is_mem,struct x86_reg dst,struct x86_reg src)285 static void emit_op_modrm( struct x86_function *p,
286 			   unsigned char op_dst_is_reg,
287 			   unsigned char op_dst_is_mem,
288 			   struct x86_reg dst,
289 			   struct x86_reg src )
290 {
291    switch (dst.mod) {
292    case mod_REG:
293       emit_1ub(p, op_dst_is_reg);
294       emit_modrm(p, dst, src);
295       break;
296    case mod_INDIRECT:
297    case mod_DISP32:
298    case mod_DISP8:
299       assert(src.mod == mod_REG);
300       emit_1ub(p, op_dst_is_mem);
301       emit_modrm(p, src, dst);
302       break;
303    default:
304       assert(0);
305       break;
306    }
307 }
308 
309 
310 
311 
312 
313 
314 
315 /* Create and manipulate registers and regmem values:
316  */
x86_make_reg(enum x86_reg_file file,enum x86_reg_name idx)317 struct x86_reg x86_make_reg( enum x86_reg_file file,
318 			     enum x86_reg_name idx )
319 {
320    struct x86_reg reg;
321 
322    reg.file = file;
323    reg.idx = idx;
324    reg.mod = mod_REG;
325    reg.disp = 0;
326 
327    return reg;
328 }
329 
x86_make_disp(struct x86_reg reg,int disp)330 struct x86_reg x86_make_disp( struct x86_reg reg,
331 			      int disp )
332 {
333    assert(reg.file == file_REG32);
334 
335    if (reg.mod == mod_REG)
336       reg.disp = disp;
337    else
338       reg.disp += disp;
339 
340    if (reg.disp == 0 && reg.idx != reg_BP)
341       reg.mod = mod_INDIRECT;
342    else if (reg.disp <= 127 && reg.disp >= -128)
343       reg.mod = mod_DISP8;
344    else
345       reg.mod = mod_DISP32;
346 
347    return reg;
348 }
349 
x86_deref(struct x86_reg reg)350 struct x86_reg x86_deref( struct x86_reg reg )
351 {
352    return x86_make_disp(reg, 0);
353 }
354 
x86_get_base_reg(struct x86_reg reg)355 struct x86_reg x86_get_base_reg( struct x86_reg reg )
356 {
357    return x86_make_reg( reg.file, reg.idx );
358 }
359 
x86_get_label(struct x86_function * p)360 int x86_get_label( struct x86_function *p )
361 {
362    return p->csr - p->store;
363 }
364 
365 
366 
367 /***********************************************************************
368  * x86 instructions
369  */
370 
371 
x64_rexw(struct x86_function * p)372 void x64_rexw(struct x86_function *p)
373 {
374    if(x86_target(p) != X86_32)
375       emit_1ub(p, 0x48);
376 }
377 
x86_jcc(struct x86_function * p,enum x86_cc cc,int label)378 void x86_jcc( struct x86_function *p,
379 	      enum x86_cc cc,
380 	      int label )
381 {
382    int offset = label - (x86_get_label(p) + 2);
383    DUMP_I(cc);
384 
385    if (offset < 0) {
386       /*assert(p->csr - p->store > -offset);*/
387       if (p->csr - p->store <= -offset) {
388          /* probably out of memory (using the error_overflow buffer) */
389          return;
390       }
391    }
392 
393    if (offset <= 127 && offset >= -128) {
394       emit_1ub(p, 0x70 + cc);
395       emit_1b(p, (char) offset);
396    }
397    else {
398       offset = label - (x86_get_label(p) + 6);
399       emit_2ub(p, 0x0f, 0x80 + cc);
400       emit_1i(p, offset);
401    }
402 }
403 
404 /* Always use a 32bit offset for forward jumps:
405  */
x86_jcc_forward(struct x86_function * p,enum x86_cc cc)406 int x86_jcc_forward( struct x86_function *p,
407                      enum x86_cc cc )
408 {
409    DUMP_I(cc);
410    emit_2ub(p, 0x0f, 0x80 + cc);
411    emit_1i(p, 0);
412    return x86_get_label(p);
413 }
414 
x86_jmp_forward(struct x86_function * p)415 int x86_jmp_forward( struct x86_function *p)
416 {
417    DUMP();
418    emit_1ub(p, 0xe9);
419    emit_1i(p, 0);
420    return x86_get_label(p);
421 }
422 
x86_call_forward(struct x86_function * p)423 int x86_call_forward( struct x86_function *p)
424 {
425    DUMP();
426 
427    emit_1ub(p, 0xe8);
428    emit_1i(p, 0);
429    return x86_get_label(p);
430 }
431 
432 /* Fixup offset from forward jump:
433  */
x86_fixup_fwd_jump(struct x86_function * p,int fixup)434 void x86_fixup_fwd_jump( struct x86_function *p,
435 			 int fixup )
436 {
437    *(int *)(p->store + fixup - 4) = x86_get_label(p) - fixup;
438 }
439 
x86_jmp(struct x86_function * p,int label)440 void x86_jmp( struct x86_function *p, int label)
441 {
442    DUMP_I( label );
443    emit_1ub(p, 0xe9);
444    emit_1i(p, label - x86_get_label(p) - 4);
445 }
446 
x86_call(struct x86_function * p,struct x86_reg reg)447 void x86_call( struct x86_function *p, struct x86_reg reg)
448 {
449    DUMP_R( reg );
450    emit_1ub(p, 0xff);
451    emit_modrm_noreg(p, 2, reg);
452 }
453 
454 
x86_mov_reg_imm(struct x86_function * p,struct x86_reg dst,int imm)455 void x86_mov_reg_imm( struct x86_function *p, struct x86_reg dst, int imm )
456 {
457    DUMP_RI( dst, imm );
458    assert(dst.file == file_REG32);
459    assert(dst.mod == mod_REG);
460    emit_1ub(p, 0xb8 + dst.idx);
461    emit_1i(p, imm);
462 }
463 
x86_mov_imm(struct x86_function * p,struct x86_reg dst,int imm)464 void x86_mov_imm( struct x86_function *p, struct x86_reg dst, int imm )
465 {
466    DUMP_RI( dst, imm );
467    if(dst.mod == mod_REG)
468       x86_mov_reg_imm(p, dst, imm);
469    else
470    {
471       emit_1ub(p, 0xc7);
472       emit_modrm_noreg(p, 0, dst);
473       emit_1i(p, imm);
474    }
475 }
476 
x86_mov16_imm(struct x86_function * p,struct x86_reg dst,uint16_t imm)477 void x86_mov16_imm( struct x86_function *p, struct x86_reg dst, uint16_t imm )
478 {
479    DUMP_RI( dst, imm );
480    emit_1ub(p, 0x66);
481    if(dst.mod == mod_REG)
482    {
483       emit_1ub(p, 0xb8 + dst.idx);
484       emit_2ub(p, imm & 0xff, imm >> 8);
485    }
486    else
487    {
488       emit_1ub(p, 0xc7);
489       emit_modrm_noreg(p, 0, dst);
490       emit_2ub(p, imm & 0xff, imm >> 8);
491    }
492 }
493 
x86_mov8_imm(struct x86_function * p,struct x86_reg dst,uint8_t imm)494 void x86_mov8_imm( struct x86_function *p, struct x86_reg dst, uint8_t imm )
495 {
496    DUMP_RI( dst, imm );
497    if(dst.mod == mod_REG)
498    {
499       emit_1ub(p, 0xb0 + dst.idx);
500       emit_1ub(p, imm);
501    }
502    else
503    {
504       emit_1ub(p, 0xc6);
505       emit_modrm_noreg(p, 0, dst);
506       emit_1ub(p, imm);
507    }
508 }
509 
510 /**
511  * Immediate group 1 instructions.
512  */
513 static inline void
x86_group1_imm(struct x86_function * p,unsigned op,struct x86_reg dst,int imm)514 x86_group1_imm( struct x86_function *p,
515                 unsigned op, struct x86_reg dst, int imm )
516 {
517    assert(dst.file == file_REG32);
518    assert(dst.mod == mod_REG);
519    if(-0x80 <= imm && imm < 0x80) {
520       emit_1ub(p, 0x83);
521       emit_modrm_noreg(p, op, dst);
522       emit_1b(p, (char)imm);
523    }
524    else {
525       emit_1ub(p, 0x81);
526       emit_modrm_noreg(p, op, dst);
527       emit_1i(p, imm);
528    }
529 }
530 
x86_add_imm(struct x86_function * p,struct x86_reg dst,int imm)531 void x86_add_imm( struct x86_function *p, struct x86_reg dst, int imm )
532 {
533    DUMP_RI( dst, imm );
534    x86_group1_imm(p, 0, dst, imm);
535 }
536 
x86_or_imm(struct x86_function * p,struct x86_reg dst,int imm)537 void x86_or_imm( struct x86_function *p, struct x86_reg dst, int imm )
538 {
539    DUMP_RI( dst, imm );
540    x86_group1_imm(p, 1, dst, imm);
541 }
542 
x86_and_imm(struct x86_function * p,struct x86_reg dst,int imm)543 void x86_and_imm( struct x86_function *p, struct x86_reg dst, int imm )
544 {
545    DUMP_RI( dst, imm );
546    x86_group1_imm(p, 4, dst, imm);
547 }
548 
x86_sub_imm(struct x86_function * p,struct x86_reg dst,int imm)549 void x86_sub_imm( struct x86_function *p, struct x86_reg dst, int imm )
550 {
551    DUMP_RI( dst, imm );
552    x86_group1_imm(p, 5, dst, imm);
553 }
554 
x86_xor_imm(struct x86_function * p,struct x86_reg dst,int imm)555 void x86_xor_imm( struct x86_function *p, struct x86_reg dst, int imm )
556 {
557    DUMP_RI( dst, imm );
558    x86_group1_imm(p, 6, dst, imm);
559 }
560 
x86_cmp_imm(struct x86_function * p,struct x86_reg dst,int imm)561 void x86_cmp_imm( struct x86_function *p, struct x86_reg dst, int imm )
562 {
563    DUMP_RI( dst, imm );
564    x86_group1_imm(p, 7, dst, imm);
565 }
566 
567 
x86_push(struct x86_function * p,struct x86_reg reg)568 void x86_push( struct x86_function *p,
569 	       struct x86_reg reg )
570 {
571    DUMP_R( reg );
572    if (reg.mod == mod_REG)
573       emit_1ub(p, 0x50 + reg.idx);
574    else
575    {
576       emit_1ub(p, 0xff);
577       emit_modrm_noreg(p, 6, reg);
578    }
579 
580 
581    p->stack_offset += sizeof(void*);
582 }
583 
x86_push_imm32(struct x86_function * p,int imm32)584 void x86_push_imm32( struct x86_function *p,
585                      int imm32 )
586 {
587    DUMP_I( imm32 );
588    emit_1ub(p, 0x68);
589    emit_1i(p,  imm32);
590 
591    p->stack_offset += sizeof(void*);
592 }
593 
594 
x86_pop(struct x86_function * p,struct x86_reg reg)595 void x86_pop( struct x86_function *p,
596 	      struct x86_reg reg )
597 {
598    DUMP_R( reg );
599    assert(reg.mod == mod_REG);
600    emit_1ub(p, 0x58 + reg.idx);
601    p->stack_offset -= sizeof(void*);
602 }
603 
x86_inc(struct x86_function * p,struct x86_reg reg)604 void x86_inc( struct x86_function *p,
605 	      struct x86_reg reg )
606 {
607    DUMP_R( reg );
608    if(x86_target(p) == X86_32 && reg.mod == mod_REG)
609    {
610       emit_1ub(p, 0x40 + reg.idx);
611       return;
612    }
613    emit_1ub(p, 0xff);
614    emit_modrm_noreg(p, 0, reg);
615 }
616 
x86_dec(struct x86_function * p,struct x86_reg reg)617 void x86_dec( struct x86_function *p,
618 	      struct x86_reg reg )
619 {
620    DUMP_R( reg );
621    if(x86_target(p) == X86_32 && reg.mod == mod_REG)
622    {
623       emit_1ub(p, 0x48 + reg.idx);
624       return;
625    }
626    emit_1ub(p, 0xff);
627    emit_modrm_noreg(p, 1, reg);
628 }
629 
x86_ret(struct x86_function * p)630 void x86_ret( struct x86_function *p )
631 {
632    DUMP();
633    assert(p->stack_offset == 0);
634    emit_1ub(p, 0xc3);
635 }
636 
x86_retw(struct x86_function * p,unsigned short imm)637 void x86_retw( struct x86_function *p, unsigned short imm )
638 {
639    DUMP();
640    emit_3ub(p, 0xc2, imm & 0xff, (imm >> 8) & 0xff);
641 }
642 
x86_sahf(struct x86_function * p)643 void x86_sahf( struct x86_function *p )
644 {
645    DUMP();
646    emit_1ub(p, 0x9e);
647 }
648 
x86_mov(struct x86_function * p,struct x86_reg dst,struct x86_reg src)649 void x86_mov( struct x86_function *p,
650 	      struct x86_reg dst,
651 	      struct x86_reg src )
652 {
653    DUMP_RR( dst, src );
654    /* special hack for reading arguments until we support x86-64 registers everywhere */
655    if(src.mod == mod_REG && dst.mod == mod_REG && (src.idx >= 8 || dst.idx >= 8))
656    {
657       uint8_t rex = 0x40;
658       if(dst.idx >= 8)
659       {
660          rex |= 4;
661          dst.idx -= 8;
662       }
663       if(src.idx >= 8)
664       {
665          rex |= 1;
666          src.idx -= 8;
667       }
668       emit_1ub(p, rex);
669    }
670    emit_op_modrm( p, 0x8b, 0x89, dst, src );
671 }
672 
x86_mov16(struct x86_function * p,struct x86_reg dst,struct x86_reg src)673 void x86_mov16( struct x86_function *p,
674 	      struct x86_reg dst,
675 	      struct x86_reg src )
676 {
677    DUMP_RR( dst, src );
678    emit_1ub(p, 0x66);
679    emit_op_modrm( p, 0x8b, 0x89, dst, src );
680 }
681 
x86_mov8(struct x86_function * p,struct x86_reg dst,struct x86_reg src)682 void x86_mov8( struct x86_function *p,
683 	      struct x86_reg dst,
684 	      struct x86_reg src )
685 {
686    DUMP_RR( dst, src );
687    emit_op_modrm( p, 0x8a, 0x88, dst, src );
688 }
689 
x64_mov64(struct x86_function * p,struct x86_reg dst,struct x86_reg src)690 void x64_mov64( struct x86_function *p,
691 	      struct x86_reg dst,
692 	      struct x86_reg src )
693 {
694    uint8_t rex = 0x48;
695    DUMP_RR( dst, src );
696    assert(x86_target(p) != X86_32);
697 
698    /* special hack for reading arguments until we support x86-64 registers everywhere */
699    if(src.mod == mod_REG && dst.mod == mod_REG && (src.idx >= 8 || dst.idx >= 8))
700    {
701       if(dst.idx >= 8)
702       {
703          rex |= 4;
704          dst.idx -= 8;
705       }
706       if(src.idx >= 8)
707       {
708          rex |= 1;
709          src.idx -= 8;
710       }
711    }
712    emit_1ub(p, rex);
713    emit_op_modrm( p, 0x8b, 0x89, dst, src );
714 }
715 
x86_movzx8(struct x86_function * p,struct x86_reg dst,struct x86_reg src)716 void x86_movzx8(struct x86_function *p, struct x86_reg dst, struct x86_reg src )
717 {
718    DUMP_RR( dst, src );
719    emit_2ub(p, 0x0f, 0xb6);
720    emit_modrm(p, dst, src);
721 }
722 
x86_movzx16(struct x86_function * p,struct x86_reg dst,struct x86_reg src)723 void x86_movzx16(struct x86_function *p, struct x86_reg dst, struct x86_reg src )
724 {
725    DUMP_RR( dst, src );
726    emit_2ub(p, 0x0f, 0xb7);
727    emit_modrm(p, dst, src);
728 }
729 
x86_cmovcc(struct x86_function * p,struct x86_reg dst,struct x86_reg src,enum x86_cc cc)730 void x86_cmovcc( struct x86_function *p,
731                  struct x86_reg dst,
732                  struct x86_reg src,
733                  enum x86_cc cc)
734 {
735    DUMP_RRI( dst, src, cc );
736    emit_2ub( p, 0x0f, 0x40 + cc );
737    emit_modrm( p, dst, src );
738 }
739 
x86_xor(struct x86_function * p,struct x86_reg dst,struct x86_reg src)740 void x86_xor( struct x86_function *p,
741 	      struct x86_reg dst,
742 	      struct x86_reg src )
743 {
744    DUMP_RR( dst, src );
745    emit_op_modrm( p, 0x33, 0x31, dst, src );
746 }
747 
x86_cmp(struct x86_function * p,struct x86_reg dst,struct x86_reg src)748 void x86_cmp( struct x86_function *p,
749 	      struct x86_reg dst,
750 	      struct x86_reg src )
751 {
752    DUMP_RR( dst, src );
753    emit_op_modrm( p, 0x3b, 0x39, dst, src );
754 }
755 
x86_lea(struct x86_function * p,struct x86_reg dst,struct x86_reg src)756 void x86_lea( struct x86_function *p,
757 	      struct x86_reg dst,
758 	      struct x86_reg src )
759 {
760    DUMP_RR( dst, src );
761    emit_1ub(p, 0x8d);
762    emit_modrm( p, dst, src );
763 }
764 
x86_test(struct x86_function * p,struct x86_reg dst,struct x86_reg src)765 void x86_test( struct x86_function *p,
766 	       struct x86_reg dst,
767 	       struct x86_reg src )
768 {
769    DUMP_RR( dst, src );
770    emit_1ub(p, 0x85);
771    emit_modrm( p, dst, src );
772 }
773 
x86_add(struct x86_function * p,struct x86_reg dst,struct x86_reg src)774 void x86_add( struct x86_function *p,
775 	       struct x86_reg dst,
776 	       struct x86_reg src )
777 {
778    DUMP_RR( dst, src );
779    emit_op_modrm(p, 0x03, 0x01, dst, src );
780 }
781 
782 /* Calculate EAX * src, results in EDX:EAX.
783  */
x86_mul(struct x86_function * p,struct x86_reg src)784 void x86_mul( struct x86_function *p,
785 	       struct x86_reg src )
786 {
787    DUMP_R(  src );
788    emit_1ub(p, 0xf7);
789    emit_modrm_noreg(p, 4, src );
790 }
791 
792 
x86_imul(struct x86_function * p,struct x86_reg dst,struct x86_reg src)793 void x86_imul( struct x86_function *p,
794 	       struct x86_reg dst,
795 	       struct x86_reg src )
796 {
797    DUMP_RR( dst, src );
798    emit_2ub(p, X86_TWOB, 0xAF);
799    emit_modrm(p, dst, src);
800 }
801 
802 
x86_sub(struct x86_function * p,struct x86_reg dst,struct x86_reg src)803 void x86_sub( struct x86_function *p,
804 	       struct x86_reg dst,
805 	       struct x86_reg src )
806 {
807    DUMP_RR( dst, src );
808    emit_op_modrm(p, 0x2b, 0x29, dst, src );
809 }
810 
x86_or(struct x86_function * p,struct x86_reg dst,struct x86_reg src)811 void x86_or( struct x86_function *p,
812              struct x86_reg dst,
813              struct x86_reg src )
814 {
815    DUMP_RR( dst, src );
816    emit_op_modrm( p, 0x0b, 0x09, dst, src );
817 }
818 
x86_and(struct x86_function * p,struct x86_reg dst,struct x86_reg src)819 void x86_and( struct x86_function *p,
820               struct x86_reg dst,
821               struct x86_reg src )
822 {
823    DUMP_RR( dst, src );
824    emit_op_modrm( p, 0x23, 0x21, dst, src );
825 }
826 
x86_div(struct x86_function * p,struct x86_reg src)827 void x86_div( struct x86_function *p,
828               struct x86_reg src )
829 {
830    assert(src.file == file_REG32 && src.mod == mod_REG);
831    emit_op_modrm(p, 0xf7, 0, x86_make_reg(file_REG32, 6), src);
832 }
833 
x86_bswap(struct x86_function * p,struct x86_reg reg)834 void x86_bswap( struct x86_function *p, struct x86_reg reg )
835 {
836    DUMP_R(reg);
837    assert(reg.file == file_REG32);
838    assert(reg.mod == mod_REG);
839    emit_2ub(p, 0x0f, 0xc8 + reg.idx);
840 }
841 
x86_shr_imm(struct x86_function * p,struct x86_reg reg,unsigned imm)842 void x86_shr_imm( struct x86_function *p, struct x86_reg reg, unsigned imm )
843 {
844    DUMP_RI(reg, imm);
845    if(imm == 1)
846    {
847       emit_1ub(p, 0xd1);
848       emit_modrm_noreg(p, 5, reg);
849    }
850    else
851    {
852       emit_1ub(p, 0xc1);
853       emit_modrm_noreg(p, 5, reg);
854       emit_1ub(p, imm);
855    }
856 }
857 
x86_sar_imm(struct x86_function * p,struct x86_reg reg,unsigned imm)858 void x86_sar_imm( struct x86_function *p, struct x86_reg reg, unsigned imm )
859 {
860    DUMP_RI(reg, imm);
861    if(imm == 1)
862    {
863       emit_1ub(p, 0xd1);
864       emit_modrm_noreg(p, 7, reg);
865    }
866    else
867    {
868       emit_1ub(p, 0xc1);
869       emit_modrm_noreg(p, 7, reg);
870       emit_1ub(p, imm);
871    }
872 }
873 
x86_shl_imm(struct x86_function * p,struct x86_reg reg,unsigned imm)874 void x86_shl_imm( struct x86_function *p, struct x86_reg reg, unsigned imm  )
875 {
876    DUMP_RI(reg, imm);
877    if(imm == 1)
878    {
879       emit_1ub(p, 0xd1);
880       emit_modrm_noreg(p, 4, reg);
881    }
882    else
883    {
884       emit_1ub(p, 0xc1);
885       emit_modrm_noreg(p, 4, reg);
886       emit_1ub(p, imm);
887    }
888 }
889 
890 
891 /***********************************************************************
892  * SSE instructions
893  */
894 
sse_prefetchnta(struct x86_function * p,struct x86_reg ptr)895 void sse_prefetchnta( struct x86_function *p, struct x86_reg ptr)
896 {
897    DUMP_R( ptr );
898    assert(ptr.mod != mod_REG);
899    emit_2ub(p, 0x0f, 0x18);
900    emit_modrm_noreg(p, 0, ptr);
901 }
902 
sse_prefetch0(struct x86_function * p,struct x86_reg ptr)903 void sse_prefetch0( struct x86_function *p, struct x86_reg ptr)
904 {
905    DUMP_R( ptr );
906    assert(ptr.mod != mod_REG);
907    emit_2ub(p, 0x0f, 0x18);
908    emit_modrm_noreg(p, 1, ptr);
909 }
910 
sse_prefetch1(struct x86_function * p,struct x86_reg ptr)911 void sse_prefetch1( struct x86_function *p, struct x86_reg ptr)
912 {
913    DUMP_R( ptr );
914    assert(ptr.mod != mod_REG);
915    emit_2ub(p, 0x0f, 0x18);
916    emit_modrm_noreg(p, 2, ptr);
917 }
918 
sse_movntps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)919 void sse_movntps( struct x86_function *p,
920                   struct x86_reg dst,
921                   struct x86_reg src)
922 {
923    DUMP_RR( dst, src );
924 
925    assert(dst.mod != mod_REG);
926    assert(src.mod == mod_REG);
927    emit_2ub(p, 0x0f, 0x2b);
928    emit_modrm(p, src, dst);
929 }
930 
931 
932 
933 
sse_movss(struct x86_function * p,struct x86_reg dst,struct x86_reg src)934 void sse_movss( struct x86_function *p,
935 		struct x86_reg dst,
936 		struct x86_reg src )
937 {
938    DUMP_RR( dst, src );
939    emit_2ub(p, 0xF3, X86_TWOB);
940    emit_op_modrm( p, 0x10, 0x11, dst, src );
941 }
942 
sse_movaps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)943 void sse_movaps( struct x86_function *p,
944 		 struct x86_reg dst,
945 		 struct x86_reg src )
946 {
947    DUMP_RR( dst, src );
948    emit_1ub(p, X86_TWOB);
949    emit_op_modrm( p, 0x28, 0x29, dst, src );
950 }
951 
sse_movups(struct x86_function * p,struct x86_reg dst,struct x86_reg src)952 void sse_movups( struct x86_function *p,
953 		 struct x86_reg dst,
954 		 struct x86_reg src )
955 {
956    DUMP_RR( dst, src );
957    emit_1ub(p, X86_TWOB);
958    emit_op_modrm( p, 0x10, 0x11, dst, src );
959 }
960 
sse_movhps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)961 void sse_movhps( struct x86_function *p,
962 		 struct x86_reg dst,
963 		 struct x86_reg src )
964 {
965    DUMP_RR( dst, src );
966    assert(dst.mod != mod_REG || src.mod != mod_REG);
967    emit_1ub(p, X86_TWOB);
968    emit_op_modrm( p, 0x16, 0x17, dst, src ); /* cf movlhps */
969 }
970 
sse_movlps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)971 void sse_movlps( struct x86_function *p,
972 		 struct x86_reg dst,
973 		 struct x86_reg src )
974 {
975    DUMP_RR( dst, src );
976    assert(dst.mod != mod_REG || src.mod != mod_REG);
977    emit_1ub(p, X86_TWOB);
978    emit_op_modrm( p, 0x12, 0x13, dst, src ); /* cf movhlps */
979 }
980 
sse_maxps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)981 void sse_maxps( struct x86_function *p,
982 		struct x86_reg dst,
983 		struct x86_reg src )
984 {
985    DUMP_RR( dst, src );
986    emit_2ub(p, X86_TWOB, 0x5F);
987    emit_modrm( p, dst, src );
988 }
989 
sse_maxss(struct x86_function * p,struct x86_reg dst,struct x86_reg src)990 void sse_maxss( struct x86_function *p,
991 		struct x86_reg dst,
992 		struct x86_reg src )
993 {
994    DUMP_RR( dst, src );
995    emit_3ub(p, 0xF3, X86_TWOB, 0x5F);
996    emit_modrm( p, dst, src );
997 }
998 
sse_divss(struct x86_function * p,struct x86_reg dst,struct x86_reg src)999 void sse_divss( struct x86_function *p,
1000 		struct x86_reg dst,
1001 		struct x86_reg src )
1002 {
1003    DUMP_RR( dst, src );
1004    emit_3ub(p, 0xF3, X86_TWOB, 0x5E);
1005    emit_modrm( p, dst, src );
1006 }
1007 
sse_minps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1008 void sse_minps( struct x86_function *p,
1009 		struct x86_reg dst,
1010 		struct x86_reg src )
1011 {
1012    DUMP_RR( dst, src );
1013    emit_2ub(p, X86_TWOB, 0x5D);
1014    emit_modrm( p, dst, src );
1015 }
1016 
sse_subps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1017 void sse_subps( struct x86_function *p,
1018 		struct x86_reg dst,
1019 		struct x86_reg src )
1020 {
1021    DUMP_RR( dst, src );
1022    emit_2ub(p, X86_TWOB, 0x5C);
1023    emit_modrm( p, dst, src );
1024 }
1025 
sse_mulps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1026 void sse_mulps( struct x86_function *p,
1027 		struct x86_reg dst,
1028 		struct x86_reg src )
1029 {
1030    DUMP_RR( dst, src );
1031    emit_2ub(p, X86_TWOB, 0x59);
1032    emit_modrm( p, dst, src );
1033 }
1034 
sse_mulss(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1035 void sse_mulss( struct x86_function *p,
1036 		struct x86_reg dst,
1037 		struct x86_reg src )
1038 {
1039    DUMP_RR( dst, src );
1040    emit_3ub(p, 0xF3, X86_TWOB, 0x59);
1041    emit_modrm( p, dst, src );
1042 }
1043 
sse_addps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1044 void sse_addps( struct x86_function *p,
1045 		struct x86_reg dst,
1046 		struct x86_reg src )
1047 {
1048    DUMP_RR( dst, src );
1049    emit_2ub(p, X86_TWOB, 0x58);
1050    emit_modrm( p, dst, src );
1051 }
1052 
sse_addss(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1053 void sse_addss( struct x86_function *p,
1054 		struct x86_reg dst,
1055 		struct x86_reg src )
1056 {
1057    DUMP_RR( dst, src );
1058    emit_3ub(p, 0xF3, X86_TWOB, 0x58);
1059    emit_modrm( p, dst, src );
1060 }
1061 
sse_andnps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1062 void sse_andnps( struct x86_function *p,
1063                  struct x86_reg dst,
1064                  struct x86_reg src )
1065 {
1066    DUMP_RR( dst, src );
1067    emit_2ub(p, X86_TWOB, 0x55);
1068    emit_modrm( p, dst, src );
1069 }
1070 
sse_andps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1071 void sse_andps( struct x86_function *p,
1072 		struct x86_reg dst,
1073 		struct x86_reg src )
1074 {
1075    DUMP_RR( dst, src );
1076    emit_2ub(p, X86_TWOB, 0x54);
1077    emit_modrm( p, dst, src );
1078 }
1079 
sse_rsqrtps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1080 void sse_rsqrtps( struct x86_function *p,
1081                   struct x86_reg dst,
1082                   struct x86_reg src )
1083 {
1084    DUMP_RR( dst, src );
1085    emit_2ub(p, X86_TWOB, 0x52);
1086    emit_modrm( p, dst, src );
1087 }
1088 
sse_rsqrtss(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1089 void sse_rsqrtss( struct x86_function *p,
1090 		  struct x86_reg dst,
1091 		  struct x86_reg src )
1092 {
1093    DUMP_RR( dst, src );
1094    emit_3ub(p, 0xF3, X86_TWOB, 0x52);
1095    emit_modrm( p, dst, src );
1096 
1097 }
1098 
sse_movhlps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1099 void sse_movhlps( struct x86_function *p,
1100 		  struct x86_reg dst,
1101 		  struct x86_reg src )
1102 {
1103    DUMP_RR( dst, src );
1104    assert(dst.mod == mod_REG && src.mod == mod_REG);
1105    emit_2ub(p, X86_TWOB, 0x12);
1106    emit_modrm( p, dst, src );
1107 }
1108 
sse_movlhps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1109 void sse_movlhps( struct x86_function *p,
1110 		  struct x86_reg dst,
1111 		  struct x86_reg src )
1112 {
1113    DUMP_RR( dst, src );
1114    assert(dst.mod == mod_REG && src.mod == mod_REG);
1115    emit_2ub(p, X86_TWOB, 0x16);
1116    emit_modrm( p, dst, src );
1117 }
1118 
sse_orps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1119 void sse_orps( struct x86_function *p,
1120                struct x86_reg dst,
1121                struct x86_reg src )
1122 {
1123    DUMP_RR( dst, src );
1124    emit_2ub(p, X86_TWOB, 0x56);
1125    emit_modrm( p, dst, src );
1126 }
1127 
sse_xorps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1128 void sse_xorps( struct x86_function *p,
1129                 struct x86_reg dst,
1130                 struct x86_reg src )
1131 {
1132    DUMP_RR( dst, src );
1133    emit_2ub(p, X86_TWOB, 0x57);
1134    emit_modrm( p, dst, src );
1135 }
1136 
sse_cvtps2pi(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1137 void sse_cvtps2pi( struct x86_function *p,
1138 		   struct x86_reg dst,
1139 		   struct x86_reg src )
1140 {
1141    DUMP_RR( dst, src );
1142    assert(dst.file == file_MMX &&
1143 	  (src.file == file_XMM || src.mod != mod_REG));
1144 
1145    p->need_emms = 1;
1146 
1147    emit_2ub(p, X86_TWOB, 0x2d);
1148    emit_modrm( p, dst, src );
1149 }
1150 
sse2_cvtdq2ps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1151 void sse2_cvtdq2ps( struct x86_function *p,
1152 		   struct x86_reg dst,
1153 		   struct x86_reg src )
1154 {
1155    DUMP_RR( dst, src );
1156    emit_2ub(p, X86_TWOB, 0x5b);
1157    emit_modrm( p, dst, src );
1158 }
1159 
1160 
1161 /* Shufps can also be used to implement a reduced swizzle when dest ==
1162  * arg0.
1163  */
sse_shufps(struct x86_function * p,struct x86_reg dst,struct x86_reg src,unsigned char shuf)1164 void sse_shufps( struct x86_function *p,
1165 		 struct x86_reg dst,
1166 		 struct x86_reg src,
1167 		 unsigned char shuf)
1168 {
1169    DUMP_RRI( dst, src, shuf );
1170    emit_2ub(p, X86_TWOB, 0xC6);
1171    emit_modrm(p, dst, src);
1172    emit_1ub(p, shuf);
1173 }
1174 
sse_unpckhps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1175 void sse_unpckhps( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1176 {
1177    DUMP_RR( dst, src );
1178    emit_2ub( p, X86_TWOB, 0x15 );
1179    emit_modrm( p, dst, src );
1180 }
1181 
sse_unpcklps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1182 void sse_unpcklps( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1183 {
1184    DUMP_RR( dst, src );
1185    emit_2ub( p, X86_TWOB, 0x14 );
1186    emit_modrm( p, dst, src );
1187 }
1188 
sse_cmpps(struct x86_function * p,struct x86_reg dst,struct x86_reg src,enum sse_cc cc)1189 void sse_cmpps( struct x86_function *p,
1190 		struct x86_reg dst,
1191 		struct x86_reg src,
1192 		enum sse_cc cc)
1193 {
1194    DUMP_RRI( dst, src, cc );
1195    emit_2ub(p, X86_TWOB, 0xC2);
1196    emit_modrm(p, dst, src);
1197    emit_1ub(p, cc);
1198 }
1199 
sse_pmovmskb(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1200 void sse_pmovmskb( struct x86_function *p,
1201                    struct x86_reg dst,
1202                    struct x86_reg src)
1203 {
1204    DUMP_RR( dst, src );
1205    emit_3ub(p, 0x66, X86_TWOB, 0xD7);
1206    emit_modrm(p, dst, src);
1207 }
1208 
sse_movmskps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1209 void sse_movmskps( struct x86_function *p,
1210                    struct x86_reg dst,
1211                    struct x86_reg src)
1212 {
1213    DUMP_RR( dst, src );
1214    emit_2ub(p, X86_TWOB, 0x50);
1215    emit_modrm(p, dst, src);
1216 }
1217 
1218 /***********************************************************************
1219  * SSE2 instructions
1220  */
1221 
sse2_movd(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1222 void sse2_movd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1223 {
1224    DUMP_RR(dst, src);
1225    emit_2ub(p, 0x66, 0x0f);
1226    if(dst.mod == mod_REG && dst.file == file_REG32)
1227    {
1228       emit_1ub(p, 0x7e);
1229       emit_modrm(p, src, dst);
1230    }
1231    else
1232    {
1233       emit_op_modrm(p, 0x6e, 0x7e, dst, src);
1234    }
1235 }
1236 
sse2_movq(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1237 void sse2_movq( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1238 {
1239    DUMP_RR(dst, src);
1240    switch (dst.mod) {
1241    case mod_REG:
1242       emit_3ub(p, 0xf3, 0x0f, 0x7e);
1243       emit_modrm(p, dst, src);
1244       break;
1245    case mod_INDIRECT:
1246    case mod_DISP32:
1247    case mod_DISP8:
1248       assert(src.mod == mod_REG);
1249       emit_3ub(p, 0x66, 0x0f, 0xd6);
1250       emit_modrm(p, src, dst);
1251       break;
1252    default:
1253       assert(0);
1254       break;
1255    }
1256 }
1257 
sse2_movdqu(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1258 void sse2_movdqu( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1259 {
1260    DUMP_RR(dst, src);
1261    emit_2ub(p, 0xf3, 0x0f);
1262    emit_op_modrm(p, 0x6f, 0x7f, dst, src);
1263 }
1264 
sse2_movdqa(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1265 void sse2_movdqa( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1266 {
1267    DUMP_RR(dst, src);
1268    emit_2ub(p, 0x66, 0x0f);
1269    emit_op_modrm(p, 0x6f, 0x7f, dst, src);
1270 }
1271 
sse2_movsd(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1272 void sse2_movsd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1273 {
1274    DUMP_RR(dst, src);
1275    emit_2ub(p, 0xf2, 0x0f);
1276    emit_op_modrm(p, 0x10, 0x11, dst, src);
1277 }
1278 
sse2_movupd(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1279 void sse2_movupd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1280 {
1281    DUMP_RR(dst, src);
1282    emit_2ub(p, 0x66, 0x0f);
1283    emit_op_modrm(p, 0x10, 0x11, dst, src);
1284 }
1285 
sse2_movapd(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1286 void sse2_movapd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1287 {
1288    DUMP_RR(dst, src);
1289    emit_2ub(p, 0x66, 0x0f);
1290    emit_op_modrm(p, 0x28, 0x29, dst, src);
1291 }
1292 
1293 /**
1294  * Perform a reduced swizzle:
1295  */
sse2_pshufd(struct x86_function * p,struct x86_reg dst,struct x86_reg src,unsigned char shuf)1296 void sse2_pshufd( struct x86_function *p,
1297 		  struct x86_reg dst,
1298 		  struct x86_reg src,
1299 		  unsigned char shuf)
1300 {
1301    DUMP_RRI( dst, src, shuf );
1302    emit_3ub(p, 0x66, X86_TWOB, 0x70);
1303    emit_modrm(p, dst, src);
1304    emit_1ub(p, shuf);
1305 }
1306 
sse2_pshuflw(struct x86_function * p,struct x86_reg dst,struct x86_reg src,unsigned char shuf)1307 void sse2_pshuflw( struct x86_function *p,
1308                   struct x86_reg dst,
1309                   struct x86_reg src,
1310                   unsigned char shuf)
1311 {
1312    DUMP_RRI( dst, src, shuf );
1313    emit_3ub(p, 0xf2, X86_TWOB, 0x70);
1314    emit_modrm(p, dst, src);
1315    emit_1ub(p, shuf);
1316 }
1317 
sse2_pshufhw(struct x86_function * p,struct x86_reg dst,struct x86_reg src,unsigned char shuf)1318 void sse2_pshufhw( struct x86_function *p,
1319                   struct x86_reg dst,
1320                   struct x86_reg src,
1321                   unsigned char shuf)
1322 {
1323    DUMP_RRI( dst, src, shuf );
1324    emit_3ub(p, 0xf3, X86_TWOB, 0x70);
1325    emit_modrm(p, dst, src);
1326    emit_1ub(p, shuf);
1327 }
1328 
sse2_cvttps2dq(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1329 void sse2_cvttps2dq( struct x86_function *p,
1330                      struct x86_reg dst,
1331                      struct x86_reg src )
1332 {
1333    DUMP_RR( dst, src );
1334    emit_3ub( p, 0xF3, X86_TWOB, 0x5B );
1335    emit_modrm( p, dst, src );
1336 }
1337 
sse2_cvtps2dq(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1338 void sse2_cvtps2dq( struct x86_function *p,
1339 		    struct x86_reg dst,
1340 		    struct x86_reg src )
1341 {
1342    DUMP_RR( dst, src );
1343    emit_3ub(p, 0x66, X86_TWOB, 0x5B);
1344    emit_modrm( p, dst, src );
1345 }
1346 
sse2_cvtsd2ss(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1347 void sse2_cvtsd2ss( struct x86_function *p,
1348                     struct x86_reg dst,
1349                     struct x86_reg src )
1350 {
1351    DUMP_RR( dst, src );
1352    emit_3ub(p, 0xf2, 0x0f, 0x5a);
1353    emit_modrm( p, dst, src );
1354 }
1355 
sse2_cvtpd2ps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1356 void sse2_cvtpd2ps( struct x86_function *p,
1357                     struct x86_reg dst,
1358                     struct x86_reg src )
1359 {
1360    DUMP_RR( dst, src );
1361    emit_3ub(p, 0x66, 0x0f, 0x5a);
1362    emit_modrm( p, dst, src );
1363 }
1364 
sse2_packssdw(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1365 void sse2_packssdw( struct x86_function *p,
1366 		    struct x86_reg dst,
1367 		    struct x86_reg src )
1368 {
1369    DUMP_RR( dst, src );
1370    emit_3ub(p, 0x66, X86_TWOB, 0x6B);
1371    emit_modrm( p, dst, src );
1372 }
1373 
sse2_packsswb(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1374 void sse2_packsswb( struct x86_function *p,
1375 		    struct x86_reg dst,
1376 		    struct x86_reg src )
1377 {
1378    DUMP_RR( dst, src );
1379    emit_3ub(p, 0x66, X86_TWOB, 0x63);
1380    emit_modrm( p, dst, src );
1381 }
1382 
sse2_packuswb(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1383 void sse2_packuswb( struct x86_function *p,
1384 		    struct x86_reg dst,
1385 		    struct x86_reg src )
1386 {
1387    DUMP_RR( dst, src );
1388    emit_3ub(p, 0x66, X86_TWOB, 0x67);
1389    emit_modrm( p, dst, src );
1390 }
1391 
sse2_punpcklbw(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1392 void sse2_punpcklbw( struct x86_function *p,
1393 		    struct x86_reg dst,
1394 		    struct x86_reg src )
1395 {
1396    DUMP_RR( dst, src );
1397    emit_3ub(p, 0x66, X86_TWOB, 0x60);
1398    emit_modrm( p, dst, src );
1399 }
1400 
sse2_punpcklwd(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1401 void sse2_punpcklwd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1402 {
1403    DUMP_RR( dst, src );
1404    emit_3ub(p, 0x66, 0x0f, 0x61);
1405    emit_modrm( p, dst, src );
1406 }
1407 
sse2_punpckldq(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1408 void sse2_punpckldq( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1409 {
1410    DUMP_RR( dst, src );
1411    emit_3ub(p, 0x66, 0x0f, 0x62);
1412    emit_modrm( p, dst, src );
1413 }
1414 
sse2_punpcklqdq(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1415 void sse2_punpcklqdq( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1416 {
1417    DUMP_RR( dst, src );
1418    emit_3ub(p, 0x66, 0x0f, 0x6c);
1419    emit_modrm( p, dst, src );
1420 }
1421 
sse2_psllw_imm(struct x86_function * p,struct x86_reg dst,unsigned imm)1422 void sse2_psllw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
1423 {
1424    DUMP_RI(dst, imm);
1425    emit_3ub(p, 0x66, 0x0f, 0x71);
1426    emit_modrm_noreg(p, 6, dst);
1427    emit_1ub(p, imm);
1428 }
1429 
sse2_pslld_imm(struct x86_function * p,struct x86_reg dst,unsigned imm)1430 void sse2_pslld_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
1431 {
1432    DUMP_RI(dst, imm);
1433    emit_3ub(p, 0x66, 0x0f, 0x72);
1434    emit_modrm_noreg(p, 6, dst);
1435    emit_1ub(p, imm);
1436 }
1437 
sse2_psllq_imm(struct x86_function * p,struct x86_reg dst,unsigned imm)1438 void sse2_psllq_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
1439 {
1440    DUMP_RI(dst, imm);
1441    emit_3ub(p, 0x66, 0x0f, 0x73);
1442    emit_modrm_noreg(p, 6, dst);
1443    emit_1ub(p, imm);
1444 }
1445 
sse2_psrlw_imm(struct x86_function * p,struct x86_reg dst,unsigned imm)1446 void sse2_psrlw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
1447 {
1448    DUMP_RI(dst, imm);
1449    emit_3ub(p, 0x66, 0x0f, 0x71);
1450    emit_modrm_noreg(p, 2, dst);
1451    emit_1ub(p, imm);
1452 }
1453 
sse2_psrld_imm(struct x86_function * p,struct x86_reg dst,unsigned imm)1454 void sse2_psrld_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
1455 {
1456    DUMP_RI(dst, imm);
1457    emit_3ub(p, 0x66, 0x0f, 0x72);
1458    emit_modrm_noreg(p, 2, dst);
1459    emit_1ub(p, imm);
1460 }
1461 
sse2_psrlq_imm(struct x86_function * p,struct x86_reg dst,unsigned imm)1462 void sse2_psrlq_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
1463 {
1464    DUMP_RI(dst, imm);
1465    emit_3ub(p, 0x66, 0x0f, 0x73);
1466    emit_modrm_noreg(p, 2, dst);
1467    emit_1ub(p, imm);
1468 }
1469 
sse2_psraw_imm(struct x86_function * p,struct x86_reg dst,unsigned imm)1470 void sse2_psraw_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
1471 {
1472    DUMP_RI(dst, imm);
1473    emit_3ub(p, 0x66, 0x0f, 0x71);
1474    emit_modrm_noreg(p, 4, dst);
1475    emit_1ub(p, imm);
1476 }
1477 
sse2_psrad_imm(struct x86_function * p,struct x86_reg dst,unsigned imm)1478 void sse2_psrad_imm( struct x86_function *p, struct x86_reg dst, unsigned imm )
1479 {
1480    DUMP_RI(dst, imm);
1481    emit_3ub(p, 0x66, 0x0f, 0x72);
1482    emit_modrm_noreg(p, 4, dst);
1483    emit_1ub(p, imm);
1484 }
1485 
sse2_por(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1486 void sse2_por( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1487 {
1488    DUMP_RR(dst, src);
1489    emit_3ub(p, 0x66, 0x0f, 0xeb);
1490    emit_modrm(p, dst, src);
1491 }
1492 
sse2_rcpps(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1493 void sse2_rcpps( struct x86_function *p,
1494                  struct x86_reg dst,
1495                  struct x86_reg src )
1496 {
1497    DUMP_RR( dst, src );
1498    emit_2ub(p, X86_TWOB, 0x53);
1499    emit_modrm( p, dst, src );
1500 }
1501 
sse2_rcpss(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1502 void sse2_rcpss( struct x86_function *p,
1503 		struct x86_reg dst,
1504 		struct x86_reg src )
1505 {
1506    DUMP_RR( dst, src );
1507    emit_3ub(p, 0xF3, X86_TWOB, 0x53);
1508    emit_modrm( p, dst, src );
1509 }
1510 
1511 /***********************************************************************
1512  * x87 instructions
1513  */
note_x87_pop(struct x86_function * p)1514 static void note_x87_pop( struct x86_function *p )
1515 {
1516    p->x87_stack--;
1517    assert(p->x87_stack >= 0);
1518 }
1519 
note_x87_push(struct x86_function * p)1520 static void note_x87_push( struct x86_function *p )
1521 {
1522    p->x87_stack++;
1523    assert(p->x87_stack <= 7);
1524 }
1525 
x87_assert_stack_empty(struct x86_function * p)1526 void x87_assert_stack_empty( struct x86_function *p )
1527 {
1528    assert (p->x87_stack == 0);
1529 }
1530 
1531 
x87_fist(struct x86_function * p,struct x86_reg dst)1532 void x87_fist( struct x86_function *p, struct x86_reg dst )
1533 {
1534    DUMP_R( dst );
1535    emit_1ub(p, 0xdb);
1536    emit_modrm_noreg(p, 2, dst);
1537 }
1538 
x87_fistp(struct x86_function * p,struct x86_reg dst)1539 void x87_fistp( struct x86_function *p, struct x86_reg dst )
1540 {
1541    DUMP_R( dst );
1542    emit_1ub(p, 0xdb);
1543    emit_modrm_noreg(p, 3, dst);
1544    note_x87_pop(p);
1545 }
1546 
x87_fild(struct x86_function * p,struct x86_reg arg)1547 void x87_fild( struct x86_function *p, struct x86_reg arg )
1548 {
1549    DUMP_R( arg );
1550    emit_1ub(p, 0xdf);
1551    emit_modrm_noreg(p, 0, arg);
1552    note_x87_push(p);
1553 }
1554 
x87_fldz(struct x86_function * p)1555 void x87_fldz( struct x86_function *p )
1556 {
1557    DUMP();
1558    emit_2ub(p, 0xd9, 0xee);
1559    note_x87_push(p);
1560 }
1561 
1562 
x87_fldcw(struct x86_function * p,struct x86_reg arg)1563 void x87_fldcw( struct x86_function *p, struct x86_reg arg )
1564 {
1565    DUMP_R( arg );
1566    assert(arg.file == file_REG32);
1567    assert(arg.mod != mod_REG);
1568    emit_1ub(p, 0xd9);
1569    emit_modrm_noreg(p, 5, arg);
1570 }
1571 
x87_fld1(struct x86_function * p)1572 void x87_fld1( struct x86_function *p )
1573 {
1574    DUMP();
1575    emit_2ub(p, 0xd9, 0xe8);
1576    note_x87_push(p);
1577 }
1578 
x87_fldl2e(struct x86_function * p)1579 void x87_fldl2e( struct x86_function *p )
1580 {
1581    DUMP();
1582    emit_2ub(p, 0xd9, 0xea);
1583    note_x87_push(p);
1584 }
1585 
x87_fldln2(struct x86_function * p)1586 void x87_fldln2( struct x86_function *p )
1587 {
1588    DUMP();
1589    emit_2ub(p, 0xd9, 0xed);
1590    note_x87_push(p);
1591 }
1592 
x87_fwait(struct x86_function * p)1593 void x87_fwait( struct x86_function *p )
1594 {
1595    DUMP();
1596    emit_1ub(p, 0x9b);
1597 }
1598 
x87_fnclex(struct x86_function * p)1599 void x87_fnclex( struct x86_function *p )
1600 {
1601    DUMP();
1602    emit_2ub(p, 0xdb, 0xe2);
1603 }
1604 
x87_fclex(struct x86_function * p)1605 void x87_fclex( struct x86_function *p )
1606 {
1607    x87_fwait(p);
1608    x87_fnclex(p);
1609 }
1610 
x87_fcmovb(struct x86_function * p,struct x86_reg arg)1611 void x87_fcmovb( struct x86_function *p, struct x86_reg arg )
1612 {
1613    DUMP_R( arg );
1614    assert(arg.file == file_x87);
1615    emit_2ub(p, 0xda, 0xc0+arg.idx);
1616 }
1617 
x87_fcmove(struct x86_function * p,struct x86_reg arg)1618 void x87_fcmove( struct x86_function *p, struct x86_reg arg )
1619 {
1620    DUMP_R( arg );
1621    assert(arg.file == file_x87);
1622    emit_2ub(p, 0xda, 0xc8+arg.idx);
1623 }
1624 
x87_fcmovbe(struct x86_function * p,struct x86_reg arg)1625 void x87_fcmovbe( struct x86_function *p, struct x86_reg arg )
1626 {
1627    DUMP_R( arg );
1628    assert(arg.file == file_x87);
1629    emit_2ub(p, 0xda, 0xd0+arg.idx);
1630 }
1631 
x87_fcmovnb(struct x86_function * p,struct x86_reg arg)1632 void x87_fcmovnb( struct x86_function *p, struct x86_reg arg )
1633 {
1634    DUMP_R( arg );
1635    assert(arg.file == file_x87);
1636    emit_2ub(p, 0xdb, 0xc0+arg.idx);
1637 }
1638 
x87_fcmovne(struct x86_function * p,struct x86_reg arg)1639 void x87_fcmovne( struct x86_function *p, struct x86_reg arg )
1640 {
1641    DUMP_R( arg );
1642    assert(arg.file == file_x87);
1643    emit_2ub(p, 0xdb, 0xc8+arg.idx);
1644 }
1645 
x87_fcmovnbe(struct x86_function * p,struct x86_reg arg)1646 void x87_fcmovnbe( struct x86_function *p, struct x86_reg arg )
1647 {
1648    DUMP_R( arg );
1649    assert(arg.file == file_x87);
1650    emit_2ub(p, 0xdb, 0xd0+arg.idx);
1651 }
1652 
1653 
1654 
x87_arith_op(struct x86_function * p,struct x86_reg dst,struct x86_reg arg,unsigned char dst0ub0,unsigned char dst0ub1,unsigned char arg0ub0,unsigned char arg0ub1,unsigned char argmem_noreg)1655 static void x87_arith_op( struct x86_function *p, struct x86_reg dst, struct x86_reg arg,
1656 			  unsigned char dst0ub0,
1657 			  unsigned char dst0ub1,
1658 			  unsigned char arg0ub0,
1659 			  unsigned char arg0ub1,
1660 			  unsigned char argmem_noreg)
1661 {
1662    assert(dst.file == file_x87);
1663 
1664    if (arg.file == file_x87) {
1665       if (dst.idx == 0)
1666 	 emit_2ub(p, dst0ub0, dst0ub1+arg.idx);
1667       else if (arg.idx == 0)
1668 	 emit_2ub(p, arg0ub0, arg0ub1+arg.idx);
1669       else
1670 	 assert(0);
1671    }
1672    else if (dst.idx == 0) {
1673       assert(arg.file == file_REG32);
1674       emit_1ub(p, 0xd8);
1675       emit_modrm_noreg(p, argmem_noreg, arg);
1676    }
1677    else
1678       assert(0);
1679 }
1680 
x87_fmul(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1681 void x87_fmul( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1682 {
1683    DUMP_RR( dst, src );
1684    x87_arith_op(p, dst, src,
1685 		0xd8, 0xc8,
1686 		0xdc, 0xc8,
1687 		4);
1688 }
1689 
x87_fsub(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1690 void x87_fsub( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1691 {
1692    DUMP_RR( dst, src );
1693    x87_arith_op(p, dst, src,
1694 		0xd8, 0xe0,
1695 		0xdc, 0xe8,
1696 		4);
1697 }
1698 
x87_fsubr(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1699 void x87_fsubr( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1700 {
1701    DUMP_RR( dst, src );
1702    x87_arith_op(p, dst, src,
1703 		0xd8, 0xe8,
1704 		0xdc, 0xe0,
1705 		5);
1706 }
1707 
x87_fadd(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1708 void x87_fadd( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1709 {
1710    DUMP_RR( dst, src );
1711    x87_arith_op(p, dst, src,
1712 		0xd8, 0xc0,
1713 		0xdc, 0xc0,
1714 		0);
1715 }
1716 
x87_fdiv(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1717 void x87_fdiv( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1718 {
1719    DUMP_RR( dst, src );
1720    x87_arith_op(p, dst, src,
1721 		0xd8, 0xf0,
1722 		0xdc, 0xf8,
1723 		6);
1724 }
1725 
x87_fdivr(struct x86_function * p,struct x86_reg dst,struct x86_reg src)1726 void x87_fdivr( struct x86_function *p, struct x86_reg dst, struct x86_reg src )
1727 {
1728    DUMP_RR( dst, src );
1729    x87_arith_op(p, dst, src,
1730 		0xd8, 0xf8,
1731 		0xdc, 0xf0,
1732 		7);
1733 }
1734 
x87_fmulp(struct x86_function * p,struct x86_reg dst)1735 void x87_fmulp( struct x86_function *p, struct x86_reg dst )
1736 {
1737    DUMP_R( dst );
1738    assert(dst.file == file_x87);
1739    assert(dst.idx >= 1);
1740    emit_2ub(p, 0xde, 0xc8+dst.idx);
1741    note_x87_pop(p);
1742 }
1743 
x87_fsubp(struct x86_function * p,struct x86_reg dst)1744 void x87_fsubp( struct x86_function *p, struct x86_reg dst )
1745 {
1746    DUMP_R( dst );
1747    assert(dst.file == file_x87);
1748    assert(dst.idx >= 1);
1749    emit_2ub(p, 0xde, 0xe8+dst.idx);
1750    note_x87_pop(p);
1751 }
1752 
x87_fsubrp(struct x86_function * p,struct x86_reg dst)1753 void x87_fsubrp( struct x86_function *p, struct x86_reg dst )
1754 {
1755    DUMP_R( dst );
1756    assert(dst.file == file_x87);
1757    assert(dst.idx >= 1);
1758    emit_2ub(p, 0xde, 0xe0+dst.idx);
1759    note_x87_pop(p);
1760 }
1761 
x87_faddp(struct x86_function * p,struct x86_reg dst)1762 void x87_faddp( struct x86_function *p, struct x86_reg dst )
1763 {
1764    DUMP_R( dst );
1765    assert(dst.file == file_x87);
1766    assert(dst.idx >= 1);
1767    emit_2ub(p, 0xde, 0xc0+dst.idx);
1768    note_x87_pop(p);
1769 }
1770 
x87_fdivp(struct x86_function * p,struct x86_reg dst)1771 void x87_fdivp( struct x86_function *p, struct x86_reg dst )
1772 {
1773    DUMP_R( dst );
1774    assert(dst.file == file_x87);
1775    assert(dst.idx >= 1);
1776    emit_2ub(p, 0xde, 0xf8+dst.idx);
1777    note_x87_pop(p);
1778 }
1779 
x87_fdivrp(struct x86_function * p,struct x86_reg dst)1780 void x87_fdivrp( struct x86_function *p, struct x86_reg dst )
1781 {
1782    DUMP_R( dst );
1783    assert(dst.file == file_x87);
1784    assert(dst.idx >= 1);
1785    emit_2ub(p, 0xde, 0xf0+dst.idx);
1786    note_x87_pop(p);
1787 }
1788 
x87_ftst(struct x86_function * p)1789 void x87_ftst( struct x86_function *p )
1790 {
1791    DUMP();
1792    emit_2ub(p, 0xd9, 0xe4);
1793 }
1794 
x87_fucom(struct x86_function * p,struct x86_reg arg)1795 void x87_fucom( struct x86_function *p, struct x86_reg arg )
1796 {
1797    DUMP_R( arg );
1798    assert(arg.file == file_x87);
1799    emit_2ub(p, 0xdd, 0xe0+arg.idx);
1800 }
1801 
x87_fucomp(struct x86_function * p,struct x86_reg arg)1802 void x87_fucomp( struct x86_function *p, struct x86_reg arg )
1803 {
1804    DUMP_R( arg );
1805    assert(arg.file == file_x87);
1806    emit_2ub(p, 0xdd, 0xe8+arg.idx);
1807    note_x87_pop(p);
1808 }
1809 
x87_fucompp(struct x86_function * p)1810 void x87_fucompp( struct x86_function *p )
1811 {
1812    DUMP();
1813    emit_2ub(p, 0xda, 0xe9);
1814    note_x87_pop(p);             /* pop twice */
1815    note_x87_pop(p);             /* pop twice */
1816 }
1817 
x87_fxch(struct x86_function * p,struct x86_reg arg)1818 void x87_fxch( struct x86_function *p, struct x86_reg arg )
1819 {
1820    DUMP_R( arg );
1821    assert(arg.file == file_x87);
1822    emit_2ub(p, 0xd9, 0xc8+arg.idx);
1823 }
1824 
x87_fabs(struct x86_function * p)1825 void x87_fabs( struct x86_function *p )
1826 {
1827    DUMP();
1828    emit_2ub(p, 0xd9, 0xe1);
1829 }
1830 
x87_fchs(struct x86_function * p)1831 void x87_fchs( struct x86_function *p )
1832 {
1833    DUMP();
1834    emit_2ub(p, 0xd9, 0xe0);
1835 }
1836 
x87_fcos(struct x86_function * p)1837 void x87_fcos( struct x86_function *p )
1838 {
1839    DUMP();
1840    emit_2ub(p, 0xd9, 0xff);
1841 }
1842 
1843 
x87_fprndint(struct x86_function * p)1844 void x87_fprndint( struct x86_function *p )
1845 {
1846    DUMP();
1847    emit_2ub(p, 0xd9, 0xfc);
1848 }
1849 
x87_fscale(struct x86_function * p)1850 void x87_fscale( struct x86_function *p )
1851 {
1852    DUMP();
1853    emit_2ub(p, 0xd9, 0xfd);
1854 }
1855 
x87_fsin(struct x86_function * p)1856 void x87_fsin( struct x86_function *p )
1857 {
1858    DUMP();
1859    emit_2ub(p, 0xd9, 0xfe);
1860 }
1861 
x87_fsincos(struct x86_function * p)1862 void x87_fsincos( struct x86_function *p )
1863 {
1864    DUMP();
1865    emit_2ub(p, 0xd9, 0xfb);
1866 }
1867 
x87_fsqrt(struct x86_function * p)1868 void x87_fsqrt( struct x86_function *p )
1869 {
1870    DUMP();
1871    emit_2ub(p, 0xd9, 0xfa);
1872 }
1873 
x87_fxtract(struct x86_function * p)1874 void x87_fxtract( struct x86_function *p )
1875 {
1876    DUMP();
1877    emit_2ub(p, 0xd9, 0xf4);
1878 }
1879 
1880 /* st0 = (2^st0)-1
1881  *
1882  * Restrictions: -1.0 <= st0 <= 1.0
1883  */
x87_f2xm1(struct x86_function * p)1884 void x87_f2xm1( struct x86_function *p )
1885 {
1886    DUMP();
1887    emit_2ub(p, 0xd9, 0xf0);
1888 }
1889 
1890 /* st1 = st1 * log2(st0);
1891  * pop_stack;
1892  */
x87_fyl2x(struct x86_function * p)1893 void x87_fyl2x( struct x86_function *p )
1894 {
1895    DUMP();
1896    emit_2ub(p, 0xd9, 0xf1);
1897    note_x87_pop(p);
1898 }
1899 
1900 /* st1 = st1 * log2(st0 + 1.0);
1901  * pop_stack;
1902  *
1903  * A fast operation, with restrictions: -.29 < st0 < .29
1904  */
x87_fyl2xp1(struct x86_function * p)1905 void x87_fyl2xp1( struct x86_function *p )
1906 {
1907    DUMP();
1908    emit_2ub(p, 0xd9, 0xf9);
1909    note_x87_pop(p);
1910 }
1911 
1912 
x87_fld(struct x86_function * p,struct x86_reg arg)1913 void x87_fld( struct x86_function *p, struct x86_reg arg )
1914 {
1915    DUMP_R( arg );
1916    if (arg.file == file_x87)
1917       emit_2ub(p, 0xd9, 0xc0 + arg.idx);
1918    else {
1919       emit_1ub(p, 0xd9);
1920       emit_modrm_noreg(p, 0, arg);
1921    }
1922    note_x87_push(p);
1923 }
1924 
x87_fst(struct x86_function * p,struct x86_reg dst)1925 void x87_fst( struct x86_function *p, struct x86_reg dst )
1926 {
1927    DUMP_R( dst );
1928    if (dst.file == file_x87)
1929       emit_2ub(p, 0xdd, 0xd0 + dst.idx);
1930    else {
1931       emit_1ub(p, 0xd9);
1932       emit_modrm_noreg(p, 2, dst);
1933    }
1934 }
1935 
x87_fstp(struct x86_function * p,struct x86_reg dst)1936 void x87_fstp( struct x86_function *p, struct x86_reg dst )
1937 {
1938    DUMP_R( dst );
1939    if (dst.file == file_x87)
1940       emit_2ub(p, 0xdd, 0xd8 + dst.idx);
1941    else {
1942       emit_1ub(p, 0xd9);
1943       emit_modrm_noreg(p, 3, dst);
1944    }
1945    note_x87_pop(p);
1946 }
1947 
x87_fpop(struct x86_function * p)1948 void x87_fpop( struct x86_function *p )
1949 {
1950    x87_fstp( p, x86_make_reg( file_x87, 0 ));
1951 }
1952 
1953 
x87_fcom(struct x86_function * p,struct x86_reg dst)1954 void x87_fcom( struct x86_function *p, struct x86_reg dst )
1955 {
1956    DUMP_R( dst );
1957    if (dst.file == file_x87)
1958       emit_2ub(p, 0xd8, 0xd0 + dst.idx);
1959    else {
1960       emit_1ub(p, 0xd8);
1961       emit_modrm_noreg(p, 2, dst);
1962    }
1963 }
1964 
1965 
x87_fcomp(struct x86_function * p,struct x86_reg dst)1966 void x87_fcomp( struct x86_function *p, struct x86_reg dst )
1967 {
1968    DUMP_R( dst );
1969    if (dst.file == file_x87)
1970       emit_2ub(p, 0xd8, 0xd8 + dst.idx);
1971    else {
1972       emit_1ub(p, 0xd8);
1973       emit_modrm_noreg(p, 3, dst);
1974    }
1975    note_x87_pop(p);
1976 }
1977 
x87_fcomi(struct x86_function * p,struct x86_reg arg)1978 void x87_fcomi( struct x86_function *p, struct x86_reg arg )
1979 {
1980    DUMP_R( arg );
1981    emit_2ub(p, 0xdb, 0xf0+arg.idx);
1982 }
1983 
x87_fcomip(struct x86_function * p,struct x86_reg arg)1984 void x87_fcomip( struct x86_function *p, struct x86_reg arg )
1985 {
1986    DUMP_R( arg );
1987    emit_2ub(p, 0xdb, 0xf0+arg.idx);
1988    note_x87_pop(p);
1989 }
1990 
1991 
x87_fnstsw(struct x86_function * p,struct x86_reg dst)1992 void x87_fnstsw( struct x86_function *p, struct x86_reg dst )
1993 {
1994    DUMP_R( dst );
1995    assert(dst.file == file_REG32);
1996 
1997    if (dst.idx == reg_AX &&
1998        dst.mod == mod_REG)
1999       emit_2ub(p, 0xdf, 0xe0);
2000    else {
2001       emit_1ub(p, 0xdd);
2002       emit_modrm_noreg(p, 7, dst);
2003    }
2004 }
2005 
2006 
x87_fnstcw(struct x86_function * p,struct x86_reg dst)2007 void x87_fnstcw( struct x86_function *p, struct x86_reg dst )
2008 {
2009    DUMP_R( dst );
2010    assert(dst.file == file_REG32);
2011 
2012    emit_1ub(p, 0x9b);           /* WAIT -- needed? */
2013    emit_1ub(p, 0xd9);
2014    emit_modrm_noreg(p, 7, dst);
2015 }
2016 
2017 
2018 
2019 
2020 /***********************************************************************
2021  * MMX instructions
2022  */
2023 
mmx_emms(struct x86_function * p)2024 void mmx_emms( struct x86_function *p )
2025 {
2026    DUMP();
2027    assert(p->need_emms);
2028    emit_2ub(p, 0x0f, 0x77);
2029    p->need_emms = 0;
2030 }
2031 
mmx_packssdw(struct x86_function * p,struct x86_reg dst,struct x86_reg src)2032 void mmx_packssdw( struct x86_function *p,
2033 		   struct x86_reg dst,
2034 		   struct x86_reg src )
2035 {
2036    DUMP_RR( dst, src );
2037    assert(dst.file == file_MMX &&
2038 	  (src.file == file_MMX || src.mod != mod_REG));
2039 
2040    p->need_emms = 1;
2041 
2042    emit_2ub(p, X86_TWOB, 0x6b);
2043    emit_modrm( p, dst, src );
2044 }
2045 
mmx_packuswb(struct x86_function * p,struct x86_reg dst,struct x86_reg src)2046 void mmx_packuswb( struct x86_function *p,
2047 		   struct x86_reg dst,
2048 		   struct x86_reg src )
2049 {
2050    DUMP_RR( dst, src );
2051    assert(dst.file == file_MMX &&
2052 	  (src.file == file_MMX || src.mod != mod_REG));
2053 
2054    p->need_emms = 1;
2055 
2056    emit_2ub(p, X86_TWOB, 0x67);
2057    emit_modrm( p, dst, src );
2058 }
2059 
mmx_movd(struct x86_function * p,struct x86_reg dst,struct x86_reg src)2060 void mmx_movd( struct x86_function *p,
2061 	       struct x86_reg dst,
2062 	       struct x86_reg src )
2063 {
2064    DUMP_RR( dst, src );
2065    p->need_emms = 1;
2066    emit_1ub(p, X86_TWOB);
2067    emit_op_modrm( p, 0x6e, 0x7e, dst, src );
2068 }
2069 
mmx_movq(struct x86_function * p,struct x86_reg dst,struct x86_reg src)2070 void mmx_movq( struct x86_function *p,
2071 	       struct x86_reg dst,
2072 	       struct x86_reg src )
2073 {
2074    DUMP_RR( dst, src );
2075    p->need_emms = 1;
2076    emit_1ub(p, X86_TWOB);
2077    emit_op_modrm( p, 0x6f, 0x7f, dst, src );
2078 }
2079 
2080 
2081 /***********************************************************************
2082  * Helper functions
2083  */
2084 
2085 
x86_cdecl_caller_push_regs(struct x86_function * p)2086 void x86_cdecl_caller_push_regs( struct x86_function *p )
2087 {
2088    x86_push(p, x86_make_reg(file_REG32, reg_AX));
2089    x86_push(p, x86_make_reg(file_REG32, reg_CX));
2090    x86_push(p, x86_make_reg(file_REG32, reg_DX));
2091 }
2092 
x86_cdecl_caller_pop_regs(struct x86_function * p)2093 void x86_cdecl_caller_pop_regs( struct x86_function *p )
2094 {
2095    x86_pop(p, x86_make_reg(file_REG32, reg_DX));
2096    x86_pop(p, x86_make_reg(file_REG32, reg_CX));
2097    x86_pop(p, x86_make_reg(file_REG32, reg_AX));
2098 }
2099 
2100 
x86_fn_arg(struct x86_function * p,unsigned arg)2101 struct x86_reg x86_fn_arg( struct x86_function *p,
2102                            unsigned arg )
2103 {
2104    switch(x86_target(p))
2105    {
2106    case X86_64_WIN64_ABI:
2107       /* Microsoft uses a different calling convention than the rest of the world */
2108       switch(arg)
2109       {
2110       case 1:
2111          return x86_make_reg(file_REG32, reg_CX);
2112       case 2:
2113          return x86_make_reg(file_REG32, reg_DX);
2114       case 3:
2115          return x86_make_reg(file_REG32, reg_R8);
2116       case 4:
2117          return x86_make_reg(file_REG32, reg_R9);
2118       default:
2119 	 /* Win64 allocates stack slots as if it pushed the first 4 arguments too */
2120          return x86_make_disp(x86_make_reg(file_REG32, reg_SP),
2121                p->stack_offset + arg * 8);
2122       }
2123    case X86_64_STD_ABI:
2124       switch(arg)
2125       {
2126       case 1:
2127          return x86_make_reg(file_REG32, reg_DI);
2128       case 2:
2129          return x86_make_reg(file_REG32, reg_SI);
2130       case 3:
2131          return x86_make_reg(file_REG32, reg_DX);
2132       case 4:
2133          return x86_make_reg(file_REG32, reg_CX);
2134       case 5:
2135          return x86_make_reg(file_REG32, reg_R8);
2136       case 6:
2137          return x86_make_reg(file_REG32, reg_R9);
2138       default:
2139          return x86_make_disp(x86_make_reg(file_REG32, reg_SP),
2140                p->stack_offset + (arg - 6) * 8);     /* ??? */
2141       }
2142    case X86_32:
2143       return x86_make_disp(x86_make_reg(file_REG32, reg_SP),
2144 			p->stack_offset + arg * 4);	/* ??? */
2145    default:
2146       assert(0 && "Unexpected x86 target ABI in x86_fn_arg");
2147       return x86_make_reg(file_REG32, reg_CX); /* not used / silence warning */
2148    }
2149 }
2150 
x86_init_func_common(struct x86_function * p)2151 static void x86_init_func_common( struct x86_function *p )
2152 {
2153    util_cpu_detect();
2154    p->caps = 0;
2155    if(util_cpu_caps.has_mmx)
2156       p->caps |= X86_MMX;
2157    if(util_cpu_caps.has_mmx2)
2158       p->caps |= X86_MMX2;
2159    if(util_cpu_caps.has_sse)
2160       p->caps |= X86_SSE;
2161    if(util_cpu_caps.has_sse2)
2162       p->caps |= X86_SSE2;
2163    if(util_cpu_caps.has_sse3)
2164       p->caps |= X86_SSE3;
2165    if(util_cpu_caps.has_sse4_1)
2166       p->caps |= X86_SSE4_1;
2167    p->csr = p->store;
2168    DUMP_START();
2169 }
2170 
x86_init_func(struct x86_function * p)2171 void x86_init_func( struct x86_function *p )
2172 {
2173    p->size = 0;
2174    p->store = NULL;
2175    x86_init_func_common(p);
2176 }
2177 
x86_init_func_size(struct x86_function * p,unsigned code_size)2178 void x86_init_func_size( struct x86_function *p, unsigned code_size )
2179 {
2180    p->size = code_size;
2181    p->store = rtasm_exec_malloc(code_size);
2182    if (p->store == NULL) {
2183       p->store = p->error_overflow;
2184    }
2185    x86_init_func_common(p);
2186 }
2187 
x86_release_func(struct x86_function * p)2188 void x86_release_func( struct x86_function *p )
2189 {
2190    if (p->store && p->store != p->error_overflow)
2191       rtasm_exec_free(p->store);
2192 
2193    p->store = NULL;
2194    p->csr = NULL;
2195    p->size = 0;
2196 }
2197 
2198 
2199 static inline x86_func
voidptr_to_x86_func(void * v)2200 voidptr_to_x86_func(void *v)
2201 {
2202    union {
2203       void *v;
2204       x86_func f;
2205    } u;
2206    STATIC_ASSERT(sizeof(u.v) == sizeof(u.f));
2207    u.v = v;
2208    return u.f;
2209 }
2210 
2211 
x86_get_func(struct x86_function * p)2212 x86_func x86_get_func( struct x86_function *p )
2213 {
2214    DUMP_END();
2215    if (DISASSEM && p->store)
2216       debug_printf("disassemble %p %p\n", p->store, p->csr);
2217 
2218    if (p->store == p->error_overflow)
2219       return voidptr_to_x86_func(NULL);
2220    else
2221       return voidptr_to_x86_func(p->store);
2222 }
2223 
2224 #else
2225 
2226 void x86sse_dummy( void );
2227 
x86sse_dummy(void)2228 void x86sse_dummy( void )
2229 {
2230 }
2231 
2232 #endif
2233