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