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