1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * vim: set ts=8 sts=4 et sw=4 tw=99: 3 * 4 * ***** BEGIN LICENSE BLOCK ***** 5 * Copyright (C) 2008 Apple Inc. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * ***** END LICENSE BLOCK ***** */ 29 30 #ifndef jit_x86_shared_BaseAssembler_x86_shared_h 31 #define jit_x86_shared_BaseAssembler_x86_shared_h 32 33 #include "mozilla/IntegerPrintfMacros.h" 34 35 #include "jit/x86-shared/AssemblerBuffer-x86-shared.h" 36 #include "jit/x86-shared/Encoding-x86-shared.h" 37 #include "jit/x86-shared/Patching-x86-shared.h" 38 39 extern volatile uintptr_t* blackbox; 40 41 namespace js { 42 namespace jit { 43 44 namespace X86Encoding { 45 46 class BaseAssembler; 47 48 class BaseAssembler : public GenericAssembler { 49 public: BaseAssembler()50 BaseAssembler() : useVEX_(true) {} 51 disableVEX()52 void disableVEX() { useVEX_ = false; } 53 size()54 size_t size() const { return m_formatter.size(); } buffer()55 const unsigned char* buffer() const { return m_formatter.buffer(); } data()56 unsigned char* data() { return m_formatter.data(); } oom()57 bool oom() const { return m_formatter.oom(); } reserve(size_t size)58 bool reserve(size_t size) { return m_formatter.reserve(size); } swapBuffer(wasm::Bytes & other)59 bool swapBuffer(wasm::Bytes& other) { return m_formatter.swapBuffer(other); } 60 nop()61 void nop() { 62 spew("nop"); 63 m_formatter.oneByteOp(OP_NOP); 64 } 65 comment(const char * msg)66 void comment(const char* msg) { spew("; %s", msg); } 67 twoByteNop()68 MOZ_MUST_USE JmpSrc twoByteNop() { 69 spew("nop (2 byte)"); 70 JmpSrc r(m_formatter.size()); 71 m_formatter.prefix(PRE_OPERAND_SIZE); 72 m_formatter.oneByteOp(OP_NOP); 73 return r; 74 } 75 patchTwoByteNopToJump(uint8_t * jump,uint8_t * target)76 static void patchTwoByteNopToJump(uint8_t* jump, uint8_t* target) { 77 // Note: the offset is relative to the address of the instruction after 78 // the jump which is two bytes. 79 ptrdiff_t rel8 = target - jump - 2; 80 MOZ_RELEASE_ASSERT(rel8 >= INT8_MIN && rel8 <= INT8_MAX); 81 MOZ_RELEASE_ASSERT(jump[0] == PRE_OPERAND_SIZE); 82 MOZ_RELEASE_ASSERT(jump[1] == OP_NOP); 83 jump[0] = OP_JMP_rel8; 84 jump[1] = rel8; 85 } 86 patchJumpToTwoByteNop(uint8_t * jump)87 static void patchJumpToTwoByteNop(uint8_t* jump) { 88 // See twoByteNop. 89 MOZ_RELEASE_ASSERT(jump[0] == OP_JMP_rel8); 90 jump[0] = PRE_OPERAND_SIZE; 91 jump[1] = OP_NOP; 92 } 93 patchFiveByteNopToCall(uint8_t * callsite,uint8_t * target)94 static void patchFiveByteNopToCall(uint8_t* callsite, uint8_t* target) { 95 // Note: the offset is relative to the address of the instruction after 96 // the call which is five bytes. 97 uint8_t* inst = callsite - sizeof(int32_t) - 1; 98 // The nop can be already patched as call, overriding the call. 99 // See also nop_five. 100 MOZ_ASSERT(inst[0] == OP_NOP_0F || inst[0] == OP_CALL_rel32); 101 MOZ_ASSERT_IF(inst[0] == OP_NOP_0F, 102 inst[1] == OP_NOP_1F || inst[2] == OP_NOP_44 || 103 inst[3] == OP_NOP_00 || inst[4] == OP_NOP_00); 104 inst[0] = OP_CALL_rel32; 105 SetRel32(callsite, target); 106 } 107 patchCallToFiveByteNop(uint8_t * callsite)108 static void patchCallToFiveByteNop(uint8_t* callsite) { 109 // See also patchFiveByteNopToCall and nop_five. 110 uint8_t* inst = callsite - sizeof(int32_t) - 1; 111 // The call can be already patched as nop. 112 if (inst[0] == OP_NOP_0F) { 113 MOZ_ASSERT(inst[1] == OP_NOP_1F || inst[2] == OP_NOP_44 || 114 inst[3] == OP_NOP_00 || inst[4] == OP_NOP_00); 115 return; 116 } 117 MOZ_ASSERT(inst[0] == OP_CALL_rel32); 118 inst[0] = OP_NOP_0F; 119 inst[1] = OP_NOP_1F; 120 inst[2] = OP_NOP_44; 121 inst[3] = OP_NOP_00; 122 inst[4] = OP_NOP_00; 123 } 124 125 /* 126 * The nop multibytes sequences are directly taken from the Intel's 127 * architecture software developer manual. 128 * They are defined for sequences of sizes from 1 to 9 included. 129 */ nop_one()130 void nop_one() { m_formatter.oneByteOp(OP_NOP); } 131 nop_two()132 void nop_two() { 133 m_formatter.oneByteOp(OP_NOP_66); 134 m_formatter.oneByteOp(OP_NOP); 135 } 136 nop_three()137 void nop_three() { 138 m_formatter.oneByteOp(OP_NOP_0F); 139 m_formatter.oneByteOp(OP_NOP_1F); 140 m_formatter.oneByteOp(OP_NOP_00); 141 } 142 nop_four()143 void nop_four() { 144 m_formatter.oneByteOp(OP_NOP_0F); 145 m_formatter.oneByteOp(OP_NOP_1F); 146 m_formatter.oneByteOp(OP_NOP_40); 147 m_formatter.oneByteOp(OP_NOP_00); 148 } 149 nop_five()150 void nop_five() { 151 m_formatter.oneByteOp(OP_NOP_0F); 152 m_formatter.oneByteOp(OP_NOP_1F); 153 m_formatter.oneByteOp(OP_NOP_44); 154 m_formatter.oneByteOp(OP_NOP_00); 155 m_formatter.oneByteOp(OP_NOP_00); 156 } 157 nop_six()158 void nop_six() { 159 m_formatter.oneByteOp(OP_NOP_66); 160 nop_five(); 161 } 162 nop_seven()163 void nop_seven() { 164 m_formatter.oneByteOp(OP_NOP_0F); 165 m_formatter.oneByteOp(OP_NOP_1F); 166 m_formatter.oneByteOp(OP_NOP_80); 167 for (int i = 0; i < 4; ++i) m_formatter.oneByteOp(OP_NOP_00); 168 } 169 nop_eight()170 void nop_eight() { 171 m_formatter.oneByteOp(OP_NOP_0F); 172 m_formatter.oneByteOp(OP_NOP_1F); 173 m_formatter.oneByteOp(OP_NOP_84); 174 for (int i = 0; i < 5; ++i) m_formatter.oneByteOp(OP_NOP_00); 175 } 176 nop_nine()177 void nop_nine() { 178 m_formatter.oneByteOp(OP_NOP_66); 179 nop_eight(); 180 } 181 insert_nop(int size)182 void insert_nop(int size) { 183 switch (size) { 184 case 1: 185 nop_one(); 186 break; 187 case 2: 188 nop_two(); 189 break; 190 case 3: 191 nop_three(); 192 break; 193 case 4: 194 nop_four(); 195 break; 196 case 5: 197 nop_five(); 198 break; 199 case 6: 200 nop_six(); 201 break; 202 case 7: 203 nop_seven(); 204 break; 205 case 8: 206 nop_eight(); 207 break; 208 case 9: 209 nop_nine(); 210 break; 211 case 10: 212 nop_three(); 213 nop_seven(); 214 break; 215 case 11: 216 nop_four(); 217 nop_seven(); 218 break; 219 case 12: 220 nop_six(); 221 nop_six(); 222 break; 223 case 13: 224 nop_six(); 225 nop_seven(); 226 break; 227 case 14: 228 nop_seven(); 229 nop_seven(); 230 break; 231 case 15: 232 nop_one(); 233 nop_seven(); 234 nop_seven(); 235 break; 236 default: 237 MOZ_CRASH("Unhandled alignment"); 238 } 239 } 240 241 // Stack operations: 242 push_r(RegisterID reg)243 void push_r(RegisterID reg) { 244 spew("push %s", GPRegName(reg)); 245 m_formatter.oneByteOp(OP_PUSH_EAX, reg); 246 } 247 pop_r(RegisterID reg)248 void pop_r(RegisterID reg) { 249 spew("pop %s", GPRegName(reg)); 250 m_formatter.oneByteOp(OP_POP_EAX, reg); 251 } 252 push_i(int32_t imm)253 void push_i(int32_t imm) { 254 spew("push $%s0x%x", PRETTYHEX(imm)); 255 if (CAN_SIGN_EXTEND_8_32(imm)) { 256 m_formatter.oneByteOp(OP_PUSH_Ib); 257 m_formatter.immediate8s(imm); 258 } else { 259 m_formatter.oneByteOp(OP_PUSH_Iz); 260 m_formatter.immediate32(imm); 261 } 262 } 263 push_i32(int32_t imm)264 void push_i32(int32_t imm) { 265 spew("push $%s0x%04x", PRETTYHEX(imm)); 266 m_formatter.oneByteOp(OP_PUSH_Iz); 267 m_formatter.immediate32(imm); 268 } 269 push_m(int32_t offset,RegisterID base)270 void push_m(int32_t offset, RegisterID base) { 271 spew("push " MEM_ob, ADDR_ob(offset, base)); 272 m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, GROUP5_OP_PUSH); 273 } push_m(int32_t offset,RegisterID base,RegisterID index,int scale)274 void push_m(int32_t offset, RegisterID base, RegisterID index, int scale) { 275 spew("push " MEM_obs, ADDR_obs(offset, base, index, scale)); 276 m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, index, scale, 277 GROUP5_OP_PUSH); 278 } 279 pop_m(int32_t offset,RegisterID base)280 void pop_m(int32_t offset, RegisterID base) { 281 spew("pop " MEM_ob, ADDR_ob(offset, base)); 282 m_formatter.oneByteOp(OP_GROUP1A_Ev, offset, base, GROUP1A_OP_POP); 283 } 284 push_flags()285 void push_flags() { 286 spew("pushf"); 287 m_formatter.oneByteOp(OP_PUSHFLAGS); 288 } 289 pop_flags()290 void pop_flags() { 291 spew("popf"); 292 m_formatter.oneByteOp(OP_POPFLAGS); 293 } 294 295 // Arithmetic operations: 296 addl_rr(RegisterID src,RegisterID dst)297 void addl_rr(RegisterID src, RegisterID dst) { 298 spew("addl %s, %s", GPReg32Name(src), GPReg32Name(dst)); 299 m_formatter.oneByteOp(OP_ADD_GvEv, src, dst); 300 } 301 addw_rr(RegisterID src,RegisterID dst)302 void addw_rr(RegisterID src, RegisterID dst) { 303 spew("addw %s, %s", GPReg16Name(src), GPReg16Name(dst)); 304 m_formatter.prefix(PRE_OPERAND_SIZE); 305 m_formatter.oneByteOp(OP_ADD_GvEv, src, dst); 306 } 307 addl_mr(int32_t offset,RegisterID base,RegisterID dst)308 void addl_mr(int32_t offset, RegisterID base, RegisterID dst) { 309 spew("addl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst)); 310 m_formatter.oneByteOp(OP_ADD_GvEv, offset, base, dst); 311 } 312 addl_rm(RegisterID src,int32_t offset,RegisterID base)313 void addl_rm(RegisterID src, int32_t offset, RegisterID base) { 314 spew("addl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base)); 315 m_formatter.oneByteOp(OP_ADD_EvGv, offset, base, src); 316 } 317 addl_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)318 void addl_rm(RegisterID src, int32_t offset, RegisterID base, 319 RegisterID index, int scale) { 320 spew("addl %s, " MEM_obs, GPReg32Name(src), 321 ADDR_obs(offset, base, index, scale)); 322 m_formatter.oneByteOp(OP_ADD_EvGv, offset, base, index, scale, src); 323 } 324 addl_ir(int32_t imm,RegisterID dst)325 void addl_ir(int32_t imm, RegisterID dst) { 326 spew("addl $%d, %s", imm, GPReg32Name(dst)); 327 if (CAN_SIGN_EXTEND_8_32(imm)) { 328 m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_ADD); 329 m_formatter.immediate8s(imm); 330 } else { 331 if (dst == rax) 332 m_formatter.oneByteOp(OP_ADD_EAXIv); 333 else 334 m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_ADD); 335 m_formatter.immediate32(imm); 336 } 337 } 338 addw_ir(int32_t imm,RegisterID dst)339 void addw_ir(int32_t imm, RegisterID dst) { 340 spew("addw $%d, %s", int16_t(imm), GPReg16Name(dst)); 341 m_formatter.prefix(PRE_OPERAND_SIZE); 342 m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_ADD); 343 m_formatter.immediate16(imm); 344 } 345 addl_i32r(int32_t imm,RegisterID dst)346 void addl_i32r(int32_t imm, RegisterID dst) { 347 // 32-bit immediate always, for patching. 348 spew("addl $0x%04x, %s", imm, GPReg32Name(dst)); 349 if (dst == rax) 350 m_formatter.oneByteOp(OP_ADD_EAXIv); 351 else 352 m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_ADD); 353 m_formatter.immediate32(imm); 354 } 355 addl_im(int32_t imm,int32_t offset,RegisterID base)356 void addl_im(int32_t imm, int32_t offset, RegisterID base) { 357 spew("addl $%d, " MEM_ob, imm, ADDR_ob(offset, base)); 358 if (CAN_SIGN_EXTEND_8_32(imm)) { 359 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_ADD); 360 m_formatter.immediate8s(imm); 361 } else { 362 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_ADD); 363 m_formatter.immediate32(imm); 364 } 365 } 366 addl_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)367 void addl_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 368 int scale) { 369 spew("addl $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale)); 370 if (CAN_SIGN_EXTEND_8_32(imm)) { 371 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, 372 GROUP1_OP_ADD); 373 m_formatter.immediate8s(imm); 374 } else { 375 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, 376 GROUP1_OP_ADD); 377 m_formatter.immediate32(imm); 378 } 379 } 380 addl_im(int32_t imm,const void * addr)381 void addl_im(int32_t imm, const void* addr) { 382 spew("addl $%d, %p", imm, addr); 383 if (CAN_SIGN_EXTEND_8_32(imm)) { 384 m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_ADD); 385 m_formatter.immediate8s(imm); 386 } else { 387 m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_ADD); 388 m_formatter.immediate32(imm); 389 } 390 } addw_im(int32_t imm,const void * addr)391 void addw_im(int32_t imm, const void* addr) { 392 spew("addw $%d, %p", int16_t(imm), addr); 393 m_formatter.prefix(PRE_OPERAND_SIZE); 394 if (CAN_SIGN_EXTEND_8_32(imm)) { 395 m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_ADD); 396 m_formatter.immediate8s(imm); 397 } else { 398 m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_ADD); 399 m_formatter.immediate16(imm); 400 } 401 } 402 addw_im(int32_t imm,int32_t offset,RegisterID base)403 void addw_im(int32_t imm, int32_t offset, RegisterID base) { 404 spew("addw $%d, " MEM_ob, int16_t(imm), ADDR_ob(offset, base)); 405 m_formatter.prefix(PRE_OPERAND_SIZE); 406 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_ADD); 407 m_formatter.immediate16(imm); 408 } 409 addw_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)410 void addw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 411 int scale) { 412 spew("addw $%d, " MEM_obs, int16_t(imm), 413 ADDR_obs(offset, base, index, scale)); 414 m_formatter.prefix(PRE_OPERAND_SIZE); 415 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, 416 GROUP1_OP_ADD); 417 m_formatter.immediate16(imm); 418 } 419 addw_rm(RegisterID src,int32_t offset,RegisterID base)420 void addw_rm(RegisterID src, int32_t offset, RegisterID base) { 421 spew("addw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base)); 422 m_formatter.prefix(PRE_OPERAND_SIZE); 423 m_formatter.oneByteOp(OP_ADD_EvGv, offset, base, src); 424 } 425 addw_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)426 void addw_rm(RegisterID src, int32_t offset, RegisterID base, 427 RegisterID index, int scale) { 428 spew("addw %s, " MEM_obs, GPReg16Name(src), 429 ADDR_obs(offset, base, index, scale)); 430 m_formatter.prefix(PRE_OPERAND_SIZE); 431 m_formatter.oneByteOp(OP_ADD_EvGv, offset, base, index, scale, src); 432 } 433 addb_im(int32_t imm,int32_t offset,RegisterID base)434 void addb_im(int32_t imm, int32_t offset, RegisterID base) { 435 spew("addb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base)); 436 m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_ADD); 437 m_formatter.immediate8(imm); 438 } 439 addb_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)440 void addb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 441 int scale) { 442 spew("addb $%d, " MEM_obs, int8_t(imm), 443 ADDR_obs(offset, base, index, scale)); 444 m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, 445 GROUP1_OP_ADD); 446 m_formatter.immediate8(imm); 447 } 448 addb_rm(RegisterID src,int32_t offset,RegisterID base)449 void addb_rm(RegisterID src, int32_t offset, RegisterID base) { 450 spew("addb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base)); 451 m_formatter.oneByteOp8(OP_ADD_EbGb, offset, base, src); 452 } 453 addb_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)454 void addb_rm(RegisterID src, int32_t offset, RegisterID base, 455 RegisterID index, int scale) { 456 spew("addb %s, " MEM_obs, GPReg8Name(src), 457 ADDR_obs(offset, base, index, scale)); 458 m_formatter.oneByteOp8(OP_ADD_EbGb, offset, base, index, scale, src); 459 } 460 subb_im(int32_t imm,int32_t offset,RegisterID base)461 void subb_im(int32_t imm, int32_t offset, RegisterID base) { 462 spew("subb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base)); 463 m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_SUB); 464 m_formatter.immediate8(imm); 465 } 466 subb_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)467 void subb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 468 int scale) { 469 spew("subb $%d, " MEM_obs, int8_t(imm), 470 ADDR_obs(offset, base, index, scale)); 471 m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, 472 GROUP1_OP_SUB); 473 m_formatter.immediate8(imm); 474 } 475 subb_rm(RegisterID src,int32_t offset,RegisterID base)476 void subb_rm(RegisterID src, int32_t offset, RegisterID base) { 477 spew("subb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base)); 478 m_formatter.oneByteOp8(OP_SUB_EbGb, offset, base, src); 479 } 480 subb_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)481 void subb_rm(RegisterID src, int32_t offset, RegisterID base, 482 RegisterID index, int scale) { 483 spew("subb %s, " MEM_obs, GPReg8Name(src), 484 ADDR_obs(offset, base, index, scale)); 485 m_formatter.oneByteOp8(OP_SUB_EbGb, offset, base, index, scale, src); 486 } 487 andb_im(int32_t imm,int32_t offset,RegisterID base)488 void andb_im(int32_t imm, int32_t offset, RegisterID base) { 489 spew("andb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base)); 490 m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_AND); 491 m_formatter.immediate8(imm); 492 } 493 andb_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)494 void andb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 495 int scale) { 496 spew("andb $%d, " MEM_obs, int8_t(imm), 497 ADDR_obs(offset, base, index, scale)); 498 m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, 499 GROUP1_OP_AND); 500 m_formatter.immediate8(imm); 501 } 502 andb_rm(RegisterID src,int32_t offset,RegisterID base)503 void andb_rm(RegisterID src, int32_t offset, RegisterID base) { 504 spew("andb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base)); 505 m_formatter.oneByteOp8(OP_AND_EbGb, offset, base, src); 506 } 507 andb_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)508 void andb_rm(RegisterID src, int32_t offset, RegisterID base, 509 RegisterID index, int scale) { 510 spew("andb %s, " MEM_obs, GPReg8Name(src), 511 ADDR_obs(offset, base, index, scale)); 512 m_formatter.oneByteOp8(OP_AND_EbGb, offset, base, index, scale, src); 513 } 514 orb_im(int32_t imm,int32_t offset,RegisterID base)515 void orb_im(int32_t imm, int32_t offset, RegisterID base) { 516 spew("orb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base)); 517 m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_OR); 518 m_formatter.immediate8(imm); 519 } 520 orb_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)521 void orb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 522 int scale) { 523 spew("orb $%d, " MEM_obs, int8_t(imm), 524 ADDR_obs(offset, base, index, scale)); 525 m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, 526 GROUP1_OP_OR); 527 m_formatter.immediate8(imm); 528 } 529 orb_rm(RegisterID src,int32_t offset,RegisterID base)530 void orb_rm(RegisterID src, int32_t offset, RegisterID base) { 531 spew("orb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base)); 532 m_formatter.oneByteOp8(OP_OR_EbGb, offset, base, src); 533 } 534 orb_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)535 void orb_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, 536 int scale) { 537 spew("orb %s, " MEM_obs, GPReg8Name(src), 538 ADDR_obs(offset, base, index, scale)); 539 m_formatter.oneByteOp8(OP_OR_EbGb, offset, base, index, scale, src); 540 } 541 xorb_im(int32_t imm,int32_t offset,RegisterID base)542 void xorb_im(int32_t imm, int32_t offset, RegisterID base) { 543 spew("xorb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base)); 544 m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_XOR); 545 m_formatter.immediate8(imm); 546 } 547 xorb_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)548 void xorb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 549 int scale) { 550 spew("xorb $%d, " MEM_obs, int8_t(imm), 551 ADDR_obs(offset, base, index, scale)); 552 m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, 553 GROUP1_OP_XOR); 554 m_formatter.immediate8(imm); 555 } 556 xorb_rm(RegisterID src,int32_t offset,RegisterID base)557 void xorb_rm(RegisterID src, int32_t offset, RegisterID base) { 558 spew("xorb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base)); 559 m_formatter.oneByteOp8(OP_XOR_EbGb, offset, base, src); 560 } 561 xorb_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)562 void xorb_rm(RegisterID src, int32_t offset, RegisterID base, 563 RegisterID index, int scale) { 564 spew("xorb %s, " MEM_obs, GPReg8Name(src), 565 ADDR_obs(offset, base, index, scale)); 566 m_formatter.oneByteOp8(OP_XOR_EbGb, offset, base, index, scale, src); 567 } 568 lock_xaddb_rm(RegisterID srcdest,int32_t offset,RegisterID base)569 void lock_xaddb_rm(RegisterID srcdest, int32_t offset, RegisterID base) { 570 spew("lock xaddb %s, " MEM_ob, GPReg8Name(srcdest), ADDR_ob(offset, base)); 571 m_formatter.oneByteOp(PRE_LOCK); 572 m_formatter.twoByteOp8(OP2_XADD_EbGb, offset, base, srcdest); 573 } 574 lock_xaddb_rm(RegisterID srcdest,int32_t offset,RegisterID base,RegisterID index,int scale)575 void lock_xaddb_rm(RegisterID srcdest, int32_t offset, RegisterID base, 576 RegisterID index, int scale) { 577 spew("lock xaddb %s, " MEM_obs, GPReg8Name(srcdest), 578 ADDR_obs(offset, base, index, scale)); 579 m_formatter.oneByteOp(PRE_LOCK); 580 m_formatter.twoByteOp8(OP2_XADD_EbGb, offset, base, index, scale, srcdest); 581 } 582 lock_xaddl_rm(RegisterID srcdest,int32_t offset,RegisterID base)583 void lock_xaddl_rm(RegisterID srcdest, int32_t offset, RegisterID base) { 584 spew("lock xaddl %s, " MEM_ob, GPReg32Name(srcdest), ADDR_ob(offset, base)); 585 m_formatter.oneByteOp(PRE_LOCK); 586 m_formatter.twoByteOp(OP2_XADD_EvGv, offset, base, srcdest); 587 } 588 lock_xaddl_rm(RegisterID srcdest,int32_t offset,RegisterID base,RegisterID index,int scale)589 void lock_xaddl_rm(RegisterID srcdest, int32_t offset, RegisterID base, 590 RegisterID index, int scale) { 591 spew("lock xaddl %s, " MEM_obs, GPReg32Name(srcdest), 592 ADDR_obs(offset, base, index, scale)); 593 m_formatter.oneByteOp(PRE_LOCK); 594 m_formatter.twoByteOp(OP2_XADD_EvGv, offset, base, index, scale, srcdest); 595 } 596 vpaddb_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)597 void vpaddb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 598 twoByteOpSimd("vpaddb", VEX_PD, OP2_PADDB_VdqWdq, src1, src0, dst); 599 } vpaddb_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)600 void vpaddb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 601 XMMRegisterID dst) { 602 twoByteOpSimd("vpaddb", VEX_PD, OP2_PADDB_VdqWdq, offset, base, src0, dst); 603 } vpaddb_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)604 void vpaddb_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 605 twoByteOpSimd("vpaddb", VEX_PD, OP2_PADDB_VdqWdq, address, src0, dst); 606 } 607 vpaddsb_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)608 void vpaddsb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 609 twoByteOpSimd("vpaddsb", VEX_PD, OP2_PADDSB_VdqWdq, src1, src0, dst); 610 } vpaddsb_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)611 void vpaddsb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 612 XMMRegisterID dst) { 613 twoByteOpSimd("vpaddsb", VEX_PD, OP2_PADDSB_VdqWdq, offset, base, src0, 614 dst); 615 } vpaddsb_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)616 void vpaddsb_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 617 twoByteOpSimd("vpaddsb", VEX_PD, OP2_PADDSB_VdqWdq, address, src0, dst); 618 } 619 vpaddusb_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)620 void vpaddusb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 621 twoByteOpSimd("vpaddusb", VEX_PD, OP2_PADDUSB_VdqWdq, src1, src0, dst); 622 } vpaddusb_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)623 void vpaddusb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 624 XMMRegisterID dst) { 625 twoByteOpSimd("vpaddusb", VEX_PD, OP2_PADDUSB_VdqWdq, offset, base, src0, 626 dst); 627 } vpaddusb_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)628 void vpaddusb_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 629 twoByteOpSimd("vpaddusb", VEX_PD, OP2_PADDUSB_VdqWdq, address, src0, dst); 630 } 631 vpaddw_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)632 void vpaddw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 633 twoByteOpSimd("vpaddw", VEX_PD, OP2_PADDW_VdqWdq, src1, src0, dst); 634 } vpaddw_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)635 void vpaddw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 636 XMMRegisterID dst) { 637 twoByteOpSimd("vpaddw", VEX_PD, OP2_PADDW_VdqWdq, offset, base, src0, dst); 638 } vpaddw_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)639 void vpaddw_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 640 twoByteOpSimd("vpaddw", VEX_PD, OP2_PADDW_VdqWdq, address, src0, dst); 641 } 642 vpaddsw_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)643 void vpaddsw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 644 twoByteOpSimd("vpaddsw", VEX_PD, OP2_PADDSW_VdqWdq, src1, src0, dst); 645 } vpaddsw_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)646 void vpaddsw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 647 XMMRegisterID dst) { 648 twoByteOpSimd("vpaddsw", VEX_PD, OP2_PADDSW_VdqWdq, offset, base, src0, 649 dst); 650 } vpaddsw_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)651 void vpaddsw_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 652 twoByteOpSimd("vpaddsw", VEX_PD, OP2_PADDSW_VdqWdq, address, src0, dst); 653 } 654 vpaddusw_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)655 void vpaddusw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 656 twoByteOpSimd("vpaddusw", VEX_PD, OP2_PADDUSW_VdqWdq, src1, src0, dst); 657 } vpaddusw_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)658 void vpaddusw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 659 XMMRegisterID dst) { 660 twoByteOpSimd("vpaddusw", VEX_PD, OP2_PADDUSW_VdqWdq, offset, base, src0, 661 dst); 662 } vpaddusw_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)663 void vpaddusw_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 664 twoByteOpSimd("vpaddusw", VEX_PD, OP2_PADDUSW_VdqWdq, address, src0, dst); 665 } 666 vpaddd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)667 void vpaddd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 668 twoByteOpSimd("vpaddd", VEX_PD, OP2_PADDD_VdqWdq, src1, src0, dst); 669 } vpaddd_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)670 void vpaddd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 671 XMMRegisterID dst) { 672 twoByteOpSimd("vpaddd", VEX_PD, OP2_PADDD_VdqWdq, offset, base, src0, dst); 673 } vpaddd_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)674 void vpaddd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 675 twoByteOpSimd("vpaddd", VEX_PD, OP2_PADDD_VdqWdq, address, src0, dst); 676 } 677 vpsubb_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)678 void vpsubb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 679 twoByteOpSimd("vpsubb", VEX_PD, OP2_PSUBB_VdqWdq, src1, src0, dst); 680 } vpsubb_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)681 void vpsubb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 682 XMMRegisterID dst) { 683 twoByteOpSimd("vpsubb", VEX_PD, OP2_PSUBB_VdqWdq, offset, base, src0, dst); 684 } vpsubb_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)685 void vpsubb_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 686 twoByteOpSimd("vpsubb", VEX_PD, OP2_PSUBB_VdqWdq, address, src0, dst); 687 } 688 vpsubsb_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)689 void vpsubsb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 690 twoByteOpSimd("vpsubsb", VEX_PD, OP2_PSUBSB_VdqWdq, src1, src0, dst); 691 } vpsubsb_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)692 void vpsubsb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 693 XMMRegisterID dst) { 694 twoByteOpSimd("vpsubsb", VEX_PD, OP2_PSUBSB_VdqWdq, offset, base, src0, 695 dst); 696 } vpsubsb_mr(const void * subress,XMMRegisterID src0,XMMRegisterID dst)697 void vpsubsb_mr(const void* subress, XMMRegisterID src0, XMMRegisterID dst) { 698 twoByteOpSimd("vpsubsb", VEX_PD, OP2_PSUBSB_VdqWdq, subress, src0, dst); 699 } 700 vpsubusb_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)701 void vpsubusb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 702 twoByteOpSimd("vpsubusb", VEX_PD, OP2_PSUBUSB_VdqWdq, src1, src0, dst); 703 } vpsubusb_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)704 void vpsubusb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 705 XMMRegisterID dst) { 706 twoByteOpSimd("vpsubusb", VEX_PD, OP2_PSUBUSB_VdqWdq, offset, base, src0, 707 dst); 708 } vpsubusb_mr(const void * subress,XMMRegisterID src0,XMMRegisterID dst)709 void vpsubusb_mr(const void* subress, XMMRegisterID src0, XMMRegisterID dst) { 710 twoByteOpSimd("vpsubusb", VEX_PD, OP2_PSUBUSB_VdqWdq, subress, src0, dst); 711 } 712 vpsubw_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)713 void vpsubw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 714 twoByteOpSimd("vpsubw", VEX_PD, OP2_PSUBW_VdqWdq, src1, src0, dst); 715 } vpsubw_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)716 void vpsubw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 717 XMMRegisterID dst) { 718 twoByteOpSimd("vpsubw", VEX_PD, OP2_PSUBW_VdqWdq, offset, base, src0, dst); 719 } vpsubw_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)720 void vpsubw_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 721 twoByteOpSimd("vpsubw", VEX_PD, OP2_PSUBW_VdqWdq, address, src0, dst); 722 } 723 vpsubsw_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)724 void vpsubsw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 725 twoByteOpSimd("vpsubsw", VEX_PD, OP2_PSUBSW_VdqWdq, src1, src0, dst); 726 } vpsubsw_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)727 void vpsubsw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 728 XMMRegisterID dst) { 729 twoByteOpSimd("vpsubsw", VEX_PD, OP2_PSUBSW_VdqWdq, offset, base, src0, 730 dst); 731 } vpsubsw_mr(const void * subress,XMMRegisterID src0,XMMRegisterID dst)732 void vpsubsw_mr(const void* subress, XMMRegisterID src0, XMMRegisterID dst) { 733 twoByteOpSimd("vpsubsw", VEX_PD, OP2_PSUBSW_VdqWdq, subress, src0, dst); 734 } 735 vpsubusw_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)736 void vpsubusw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 737 twoByteOpSimd("vpsubusw", VEX_PD, OP2_PSUBUSW_VdqWdq, src1, src0, dst); 738 } vpsubusw_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)739 void vpsubusw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 740 XMMRegisterID dst) { 741 twoByteOpSimd("vpsubusw", VEX_PD, OP2_PSUBUSW_VdqWdq, offset, base, src0, 742 dst); 743 } vpsubusw_mr(const void * subress,XMMRegisterID src0,XMMRegisterID dst)744 void vpsubusw_mr(const void* subress, XMMRegisterID src0, XMMRegisterID dst) { 745 twoByteOpSimd("vpsubusw", VEX_PD, OP2_PSUBUSW_VdqWdq, subress, src0, dst); 746 } 747 vpsubd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)748 void vpsubd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 749 twoByteOpSimd("vpsubd", VEX_PD, OP2_PSUBD_VdqWdq, src1, src0, dst); 750 } vpsubd_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)751 void vpsubd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 752 XMMRegisterID dst) { 753 twoByteOpSimd("vpsubd", VEX_PD, OP2_PSUBD_VdqWdq, offset, base, src0, dst); 754 } vpsubd_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)755 void vpsubd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 756 twoByteOpSimd("vpsubd", VEX_PD, OP2_PSUBD_VdqWdq, address, src0, dst); 757 } 758 vpmuludq_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)759 void vpmuludq_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 760 twoByteOpSimd("vpmuludq", VEX_PD, OP2_PMULUDQ_VdqWdq, src1, src0, dst); 761 } vpmuludq_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)762 void vpmuludq_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 763 XMMRegisterID dst) { 764 twoByteOpSimd("vpmuludq", VEX_PD, OP2_PMULUDQ_VdqWdq, offset, base, src0, 765 dst); 766 } 767 vpmullw_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)768 void vpmullw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 769 twoByteOpSimd("vpmullw", VEX_PD, OP2_PMULLW_VdqWdq, src1, src0, dst); 770 } vpmullw_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)771 void vpmullw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 772 XMMRegisterID dst) { 773 twoByteOpSimd("vpmullw", VEX_PD, OP2_PMULLW_VdqWdq, offset, base, src0, 774 dst); 775 } 776 vpmulld_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)777 void vpmulld_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 778 threeByteOpSimd("vpmulld", VEX_PD, OP3_PMULLD_VdqWdq, ESCAPE_38, src1, src0, 779 dst); 780 } vpmulld_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)781 void vpmulld_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 782 XMMRegisterID dst) { 783 threeByteOpSimd("vpmulld", VEX_PD, OP3_PMULLD_VdqWdq, ESCAPE_38, offset, 784 base, src0, dst); 785 } vpmulld_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)786 void vpmulld_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 787 threeByteOpSimd("vpmulld", VEX_PD, OP3_PMULLD_VdqWdq, ESCAPE_38, address, 788 src0, dst); 789 } 790 vaddps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)791 void vaddps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 792 twoByteOpSimd("vaddps", VEX_PS, OP2_ADDPS_VpsWps, src1, src0, dst); 793 } vaddps_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)794 void vaddps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 795 XMMRegisterID dst) { 796 twoByteOpSimd("vaddps", VEX_PS, OP2_ADDPS_VpsWps, offset, base, src0, dst); 797 } vaddps_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)798 void vaddps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 799 twoByteOpSimd("vaddps", VEX_PS, OP2_ADDPS_VpsWps, address, src0, dst); 800 } 801 vsubps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)802 void vsubps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 803 twoByteOpSimd("vsubps", VEX_PS, OP2_SUBPS_VpsWps, src1, src0, dst); 804 } vsubps_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)805 void vsubps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 806 XMMRegisterID dst) { 807 twoByteOpSimd("vsubps", VEX_PS, OP2_SUBPS_VpsWps, offset, base, src0, dst); 808 } vsubps_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)809 void vsubps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 810 twoByteOpSimd("vsubps", VEX_PS, OP2_SUBPS_VpsWps, address, src0, dst); 811 } 812 vmulps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)813 void vmulps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 814 twoByteOpSimd("vmulps", VEX_PS, OP2_MULPS_VpsWps, src1, src0, dst); 815 } vmulps_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)816 void vmulps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 817 XMMRegisterID dst) { 818 twoByteOpSimd("vmulps", VEX_PS, OP2_MULPS_VpsWps, offset, base, src0, dst); 819 } vmulps_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)820 void vmulps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 821 twoByteOpSimd("vmulps", VEX_PS, OP2_MULPS_VpsWps, address, src0, dst); 822 } 823 vdivps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)824 void vdivps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 825 twoByteOpSimd("vdivps", VEX_PS, OP2_DIVPS_VpsWps, src1, src0, dst); 826 } vdivps_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)827 void vdivps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 828 XMMRegisterID dst) { 829 twoByteOpSimd("vdivps", VEX_PS, OP2_DIVPS_VpsWps, offset, base, src0, dst); 830 } vdivps_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)831 void vdivps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 832 twoByteOpSimd("vdivps", VEX_PS, OP2_DIVPS_VpsWps, address, src0, dst); 833 } 834 vmaxps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)835 void vmaxps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 836 twoByteOpSimd("vmaxps", VEX_PS, OP2_MAXPS_VpsWps, src1, src0, dst); 837 } vmaxps_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)838 void vmaxps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 839 XMMRegisterID dst) { 840 twoByteOpSimd("vmaxps", VEX_PS, OP2_MAXPS_VpsWps, offset, base, src0, dst); 841 } vmaxps_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)842 void vmaxps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 843 twoByteOpSimd("vmaxps", VEX_PS, OP2_MAXPS_VpsWps, address, src0, dst); 844 } 845 vminps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)846 void vminps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 847 twoByteOpSimd("vminps", VEX_PS, OP2_MINPS_VpsWps, src1, src0, dst); 848 } vminps_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)849 void vminps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 850 XMMRegisterID dst) { 851 twoByteOpSimd("vminps", VEX_PS, OP2_MINPS_VpsWps, offset, base, src0, dst); 852 } vminps_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)853 void vminps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 854 twoByteOpSimd("vminps", VEX_PS, OP2_MINPS_VpsWps, address, src0, dst); 855 } 856 andl_rr(RegisterID src,RegisterID dst)857 void andl_rr(RegisterID src, RegisterID dst) { 858 spew("andl %s, %s", GPReg32Name(src), GPReg32Name(dst)); 859 m_formatter.oneByteOp(OP_AND_GvEv, src, dst); 860 } 861 andw_rr(RegisterID src,RegisterID dst)862 void andw_rr(RegisterID src, RegisterID dst) { 863 spew("andw %s, %s", GPReg16Name(src), GPReg16Name(dst)); 864 m_formatter.prefix(PRE_OPERAND_SIZE); 865 m_formatter.oneByteOp(OP_AND_GvEv, src, dst); 866 } 867 andl_mr(int32_t offset,RegisterID base,RegisterID dst)868 void andl_mr(int32_t offset, RegisterID base, RegisterID dst) { 869 spew("andl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst)); 870 m_formatter.oneByteOp(OP_AND_GvEv, offset, base, dst); 871 } 872 andl_mr(int32_t offset,RegisterID base,RegisterID index,int scale,RegisterID dst)873 void andl_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 874 RegisterID dst) { 875 spew("andl " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), 876 GPReg32Name(dst)); 877 m_formatter.oneByteOp(OP_AND_GvEv, offset, base, index, scale, dst); 878 } 879 andl_rm(RegisterID src,int32_t offset,RegisterID base)880 void andl_rm(RegisterID src, int32_t offset, RegisterID base) { 881 spew("andl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base)); 882 m_formatter.oneByteOp(OP_AND_EvGv, offset, base, src); 883 } 884 andw_rm(RegisterID src,int32_t offset,RegisterID base)885 void andw_rm(RegisterID src, int32_t offset, RegisterID base) { 886 spew("andw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base)); 887 m_formatter.prefix(PRE_OPERAND_SIZE); 888 m_formatter.oneByteOp(OP_AND_EvGv, offset, base, src); 889 } 890 andl_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)891 void andl_rm(RegisterID src, int32_t offset, RegisterID base, 892 RegisterID index, int scale) { 893 spew("andl %s, " MEM_obs, GPReg32Name(src), 894 ADDR_obs(offset, base, index, scale)); 895 m_formatter.oneByteOp(OP_AND_EvGv, offset, base, index, scale, src); 896 } 897 andw_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)898 void andw_rm(RegisterID src, int32_t offset, RegisterID base, 899 RegisterID index, int scale) { 900 spew("andw %s, " MEM_obs, GPReg16Name(src), 901 ADDR_obs(offset, base, index, scale)); 902 m_formatter.prefix(PRE_OPERAND_SIZE); 903 m_formatter.oneByteOp(OP_AND_EvGv, offset, base, index, scale, src); 904 } 905 andl_ir(int32_t imm,RegisterID dst)906 void andl_ir(int32_t imm, RegisterID dst) { 907 spew("andl $0x%x, %s", imm, GPReg32Name(dst)); 908 if (CAN_SIGN_EXTEND_8_32(imm)) { 909 m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_AND); 910 m_formatter.immediate8s(imm); 911 } else { 912 if (dst == rax) 913 m_formatter.oneByteOp(OP_AND_EAXIv); 914 else 915 m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_AND); 916 m_formatter.immediate32(imm); 917 } 918 } 919 andw_ir(int32_t imm,RegisterID dst)920 void andw_ir(int32_t imm, RegisterID dst) { 921 spew("andw $0x%x, %s", int16_t(imm), GPReg16Name(dst)); 922 m_formatter.prefix(PRE_OPERAND_SIZE); 923 if (CAN_SIGN_EXTEND_8_32(imm)) { 924 m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_AND); 925 m_formatter.immediate8s(imm); 926 } else { 927 if (dst == rax) 928 m_formatter.oneByteOp(OP_AND_EAXIv); 929 else 930 m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_AND); 931 m_formatter.immediate16(imm); 932 } 933 } 934 andl_im(int32_t imm,int32_t offset,RegisterID base)935 void andl_im(int32_t imm, int32_t offset, RegisterID base) { 936 spew("andl $0x%x, " MEM_ob, imm, ADDR_ob(offset, base)); 937 if (CAN_SIGN_EXTEND_8_32(imm)) { 938 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_AND); 939 m_formatter.immediate8s(imm); 940 } else { 941 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_AND); 942 m_formatter.immediate32(imm); 943 } 944 } 945 andw_im(int32_t imm,int32_t offset,RegisterID base)946 void andw_im(int32_t imm, int32_t offset, RegisterID base) { 947 spew("andw $0x%x, " MEM_ob, int16_t(imm), ADDR_ob(offset, base)); 948 m_formatter.prefix(PRE_OPERAND_SIZE); 949 if (CAN_SIGN_EXTEND_8_32(imm)) { 950 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_AND); 951 m_formatter.immediate8s(imm); 952 } else { 953 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_AND); 954 m_formatter.immediate16(imm); 955 } 956 } 957 andl_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)958 void andl_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 959 int scale) { 960 spew("andl $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale)); 961 if (CAN_SIGN_EXTEND_8_32(imm)) { 962 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, 963 GROUP1_OP_AND); 964 m_formatter.immediate8s(imm); 965 } else { 966 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, 967 GROUP1_OP_AND); 968 m_formatter.immediate32(imm); 969 } 970 } 971 andw_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)972 void andw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 973 int scale) { 974 spew("andw $%d, " MEM_obs, int16_t(imm), 975 ADDR_obs(offset, base, index, scale)); 976 m_formatter.prefix(PRE_OPERAND_SIZE); 977 if (CAN_SIGN_EXTEND_8_32(imm)) { 978 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, 979 GROUP1_OP_AND); 980 m_formatter.immediate8s(imm); 981 } else { 982 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, 983 GROUP1_OP_AND); 984 m_formatter.immediate16(imm); 985 } 986 } 987 fld_m(int32_t offset,RegisterID base)988 void fld_m(int32_t offset, RegisterID base) { 989 spew("fld " MEM_ob, ADDR_ob(offset, base)); 990 m_formatter.oneByteOp(OP_FPU6, offset, base, FPU6_OP_FLD); 991 } fld32_m(int32_t offset,RegisterID base)992 void fld32_m(int32_t offset, RegisterID base) { 993 spew("fld " MEM_ob, ADDR_ob(offset, base)); 994 m_formatter.oneByteOp(OP_FPU6_F32, offset, base, FPU6_OP_FLD); 995 } faddp()996 void faddp() { 997 spew("addp "); 998 m_formatter.oneByteOp(OP_FPU6_ADDP); 999 m_formatter.oneByteOp(OP_ADDP_ST0_ST1); 1000 } fisttp_m(int32_t offset,RegisterID base)1001 void fisttp_m(int32_t offset, RegisterID base) { 1002 spew("fisttp " MEM_ob, ADDR_ob(offset, base)); 1003 m_formatter.oneByteOp(OP_FPU6, offset, base, FPU6_OP_FISTTP); 1004 } fistp_m(int32_t offset,RegisterID base)1005 void fistp_m(int32_t offset, RegisterID base) { 1006 spew("fistp " MEM_ob, ADDR_ob(offset, base)); 1007 m_formatter.oneByteOp(OP_FILD, offset, base, FPU6_OP_FISTP); 1008 } fstp_m(int32_t offset,RegisterID base)1009 void fstp_m(int32_t offset, RegisterID base) { 1010 spew("fstp " MEM_ob, ADDR_ob(offset, base)); 1011 m_formatter.oneByteOp(OP_FPU6, offset, base, FPU6_OP_FSTP); 1012 } fstp32_m(int32_t offset,RegisterID base)1013 void fstp32_m(int32_t offset, RegisterID base) { 1014 spew("fstp32 " MEM_ob, ADDR_ob(offset, base)); 1015 m_formatter.oneByteOp(OP_FPU6_F32, offset, base, FPU6_OP_FSTP); 1016 } fnstcw_m(int32_t offset,RegisterID base)1017 void fnstcw_m(int32_t offset, RegisterID base) { 1018 spew("fnstcw " MEM_ob, ADDR_ob(offset, base)); 1019 m_formatter.oneByteOp(OP_FPU6_F32, offset, base, FPU6_OP_FISTP); 1020 } fldcw_m(int32_t offset,RegisterID base)1021 void fldcw_m(int32_t offset, RegisterID base) { 1022 spew("fldcw " MEM_ob, ADDR_ob(offset, base)); 1023 m_formatter.oneByteOp(OP_FPU6_F32, offset, base, FPU6_OP_FLDCW); 1024 } fnstsw_m(int32_t offset,RegisterID base)1025 void fnstsw_m(int32_t offset, RegisterID base) { 1026 spew("fnstsw " MEM_ob, ADDR_ob(offset, base)); 1027 m_formatter.oneByteOp(OP_FPU6, offset, base, FPU6_OP_FISTP); 1028 } 1029 negl_r(RegisterID dst)1030 void negl_r(RegisterID dst) { 1031 spew("negl %s", GPReg32Name(dst)); 1032 m_formatter.oneByteOp(OP_GROUP3_Ev, dst, GROUP3_OP_NEG); 1033 } 1034 negl_m(int32_t offset,RegisterID base)1035 void negl_m(int32_t offset, RegisterID base) { 1036 spew("negl " MEM_ob, ADDR_ob(offset, base)); 1037 m_formatter.oneByteOp(OP_GROUP3_Ev, offset, base, GROUP3_OP_NEG); 1038 } 1039 notl_r(RegisterID dst)1040 void notl_r(RegisterID dst) { 1041 spew("notl %s", GPReg32Name(dst)); 1042 m_formatter.oneByteOp(OP_GROUP3_Ev, dst, GROUP3_OP_NOT); 1043 } 1044 notl_m(int32_t offset,RegisterID base)1045 void notl_m(int32_t offset, RegisterID base) { 1046 spew("notl " MEM_ob, ADDR_ob(offset, base)); 1047 m_formatter.oneByteOp(OP_GROUP3_Ev, offset, base, GROUP3_OP_NOT); 1048 } 1049 orl_rr(RegisterID src,RegisterID dst)1050 void orl_rr(RegisterID src, RegisterID dst) { 1051 spew("orl %s, %s", GPReg32Name(src), GPReg32Name(dst)); 1052 m_formatter.oneByteOp(OP_OR_GvEv, src, dst); 1053 } 1054 orw_rr(RegisterID src,RegisterID dst)1055 void orw_rr(RegisterID src, RegisterID dst) { 1056 spew("orw %s, %s", GPReg16Name(src), GPReg16Name(dst)); 1057 m_formatter.prefix(PRE_OPERAND_SIZE); 1058 m_formatter.oneByteOp(OP_OR_GvEv, src, dst); 1059 } 1060 orl_mr(int32_t offset,RegisterID base,RegisterID dst)1061 void orl_mr(int32_t offset, RegisterID base, RegisterID dst) { 1062 spew("orl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst)); 1063 m_formatter.oneByteOp(OP_OR_GvEv, offset, base, dst); 1064 } 1065 orl_rm(RegisterID src,int32_t offset,RegisterID base)1066 void orl_rm(RegisterID src, int32_t offset, RegisterID base) { 1067 spew("orl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base)); 1068 m_formatter.oneByteOp(OP_OR_EvGv, offset, base, src); 1069 } 1070 orw_rm(RegisterID src,int32_t offset,RegisterID base)1071 void orw_rm(RegisterID src, int32_t offset, RegisterID base) { 1072 spew("orw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base)); 1073 m_formatter.prefix(PRE_OPERAND_SIZE); 1074 m_formatter.oneByteOp(OP_OR_EvGv, offset, base, src); 1075 } 1076 orl_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)1077 void orl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, 1078 int scale) { 1079 spew("orl %s, " MEM_obs, GPReg32Name(src), 1080 ADDR_obs(offset, base, index, scale)); 1081 m_formatter.oneByteOp(OP_OR_EvGv, offset, base, index, scale, src); 1082 } 1083 orw_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)1084 void orw_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, 1085 int scale) { 1086 spew("orw %s, " MEM_obs, GPReg16Name(src), 1087 ADDR_obs(offset, base, index, scale)); 1088 m_formatter.prefix(PRE_OPERAND_SIZE); 1089 m_formatter.oneByteOp(OP_OR_EvGv, offset, base, index, scale, src); 1090 } 1091 orl_ir(int32_t imm,RegisterID dst)1092 void orl_ir(int32_t imm, RegisterID dst) { 1093 spew("orl $0x%x, %s", imm, GPReg32Name(dst)); 1094 if (CAN_SIGN_EXTEND_8_32(imm)) { 1095 m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_OR); 1096 m_formatter.immediate8s(imm); 1097 } else { 1098 if (dst == rax) 1099 m_formatter.oneByteOp(OP_OR_EAXIv); 1100 else 1101 m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_OR); 1102 m_formatter.immediate32(imm); 1103 } 1104 } 1105 orw_ir(int32_t imm,RegisterID dst)1106 void orw_ir(int32_t imm, RegisterID dst) { 1107 spew("orw $0x%x, %s", int16_t(imm), GPReg16Name(dst)); 1108 m_formatter.prefix(PRE_OPERAND_SIZE); 1109 if (CAN_SIGN_EXTEND_8_32(imm)) { 1110 m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_OR); 1111 m_formatter.immediate8s(imm); 1112 } else { 1113 if (dst == rax) 1114 m_formatter.oneByteOp(OP_OR_EAXIv); 1115 else 1116 m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_OR); 1117 m_formatter.immediate16(imm); 1118 } 1119 } 1120 orl_im(int32_t imm,int32_t offset,RegisterID base)1121 void orl_im(int32_t imm, int32_t offset, RegisterID base) { 1122 spew("orl $0x%x, " MEM_ob, imm, ADDR_ob(offset, base)); 1123 if (CAN_SIGN_EXTEND_8_32(imm)) { 1124 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_OR); 1125 m_formatter.immediate8s(imm); 1126 } else { 1127 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_OR); 1128 m_formatter.immediate32(imm); 1129 } 1130 } 1131 orw_im(int32_t imm,int32_t offset,RegisterID base)1132 void orw_im(int32_t imm, int32_t offset, RegisterID base) { 1133 spew("orw $0x%x, " MEM_ob, int16_t(imm), ADDR_ob(offset, base)); 1134 m_formatter.prefix(PRE_OPERAND_SIZE); 1135 if (CAN_SIGN_EXTEND_8_32(imm)) { 1136 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_OR); 1137 m_formatter.immediate8s(imm); 1138 } else { 1139 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_OR); 1140 m_formatter.immediate16(imm); 1141 } 1142 } 1143 orl_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)1144 void orl_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 1145 int scale) { 1146 spew("orl $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale)); 1147 if (CAN_SIGN_EXTEND_8_32(imm)) { 1148 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, 1149 GROUP1_OP_OR); 1150 m_formatter.immediate8s(imm); 1151 } else { 1152 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, 1153 GROUP1_OP_OR); 1154 m_formatter.immediate32(imm); 1155 } 1156 } 1157 orw_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)1158 void orw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 1159 int scale) { 1160 spew("orw $%d, " MEM_obs, int16_t(imm), 1161 ADDR_obs(offset, base, index, scale)); 1162 m_formatter.prefix(PRE_OPERAND_SIZE); 1163 if (CAN_SIGN_EXTEND_8_32(imm)) { 1164 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, 1165 GROUP1_OP_OR); 1166 m_formatter.immediate8s(imm); 1167 } else { 1168 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, 1169 GROUP1_OP_OR); 1170 m_formatter.immediate16(imm); 1171 } 1172 } 1173 sbbl_rr(RegisterID src,RegisterID dst)1174 void sbbl_rr(RegisterID src, RegisterID dst) { 1175 spew("sbbl %s, %s", GPReg32Name(src), GPReg32Name(dst)); 1176 m_formatter.oneByteOp(OP_SBB_GvEv, src, dst); 1177 } 1178 subl_rr(RegisterID src,RegisterID dst)1179 void subl_rr(RegisterID src, RegisterID dst) { 1180 spew("subl %s, %s", GPReg32Name(src), GPReg32Name(dst)); 1181 m_formatter.oneByteOp(OP_SUB_GvEv, src, dst); 1182 } 1183 subw_rr(RegisterID src,RegisterID dst)1184 void subw_rr(RegisterID src, RegisterID dst) { 1185 spew("subw %s, %s", GPReg16Name(src), GPReg16Name(dst)); 1186 m_formatter.prefix(PRE_OPERAND_SIZE); 1187 m_formatter.oneByteOp(OP_SUB_GvEv, src, dst); 1188 } 1189 subl_mr(int32_t offset,RegisterID base,RegisterID dst)1190 void subl_mr(int32_t offset, RegisterID base, RegisterID dst) { 1191 spew("subl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst)); 1192 m_formatter.oneByteOp(OP_SUB_GvEv, offset, base, dst); 1193 } 1194 subl_rm(RegisterID src,int32_t offset,RegisterID base)1195 void subl_rm(RegisterID src, int32_t offset, RegisterID base) { 1196 spew("subl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base)); 1197 m_formatter.oneByteOp(OP_SUB_EvGv, offset, base, src); 1198 } 1199 subw_rm(RegisterID src,int32_t offset,RegisterID base)1200 void subw_rm(RegisterID src, int32_t offset, RegisterID base) { 1201 spew("subw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base)); 1202 m_formatter.prefix(PRE_OPERAND_SIZE); 1203 m_formatter.oneByteOp(OP_SUB_EvGv, offset, base, src); 1204 } 1205 subl_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)1206 void subl_rm(RegisterID src, int32_t offset, RegisterID base, 1207 RegisterID index, int scale) { 1208 spew("subl %s, " MEM_obs, GPReg32Name(src), 1209 ADDR_obs(offset, base, index, scale)); 1210 m_formatter.oneByteOp(OP_SUB_EvGv, offset, base, index, scale, src); 1211 } 1212 subw_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)1213 void subw_rm(RegisterID src, int32_t offset, RegisterID base, 1214 RegisterID index, int scale) { 1215 spew("subw %s, " MEM_obs, GPReg16Name(src), 1216 ADDR_obs(offset, base, index, scale)); 1217 m_formatter.prefix(PRE_OPERAND_SIZE); 1218 m_formatter.oneByteOp(OP_SUB_EvGv, offset, base, index, scale, src); 1219 } 1220 subl_ir(int32_t imm,RegisterID dst)1221 void subl_ir(int32_t imm, RegisterID dst) { 1222 spew("subl $%d, %s", imm, GPReg32Name(dst)); 1223 if (CAN_SIGN_EXTEND_8_32(imm)) { 1224 m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_SUB); 1225 m_formatter.immediate8s(imm); 1226 } else { 1227 if (dst == rax) 1228 m_formatter.oneByteOp(OP_SUB_EAXIv); 1229 else 1230 m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_SUB); 1231 m_formatter.immediate32(imm); 1232 } 1233 } 1234 subw_ir(int32_t imm,RegisterID dst)1235 void subw_ir(int32_t imm, RegisterID dst) { 1236 spew("subw $%d, %s", int16_t(imm), GPReg16Name(dst)); 1237 m_formatter.prefix(PRE_OPERAND_SIZE); 1238 if (CAN_SIGN_EXTEND_8_32(imm)) { 1239 m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_SUB); 1240 m_formatter.immediate8s(imm); 1241 } else { 1242 if (dst == rax) 1243 m_formatter.oneByteOp(OP_SUB_EAXIv); 1244 else 1245 m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_SUB); 1246 m_formatter.immediate16(imm); 1247 } 1248 } 1249 subl_im(int32_t imm,int32_t offset,RegisterID base)1250 void subl_im(int32_t imm, int32_t offset, RegisterID base) { 1251 spew("subl $%d, " MEM_ob, imm, ADDR_ob(offset, base)); 1252 if (CAN_SIGN_EXTEND_8_32(imm)) { 1253 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_SUB); 1254 m_formatter.immediate8s(imm); 1255 } else { 1256 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_SUB); 1257 m_formatter.immediate32(imm); 1258 } 1259 } 1260 subw_im(int32_t imm,int32_t offset,RegisterID base)1261 void subw_im(int32_t imm, int32_t offset, RegisterID base) { 1262 spew("subw $%d, " MEM_ob, int16_t(imm), ADDR_ob(offset, base)); 1263 m_formatter.prefix(PRE_OPERAND_SIZE); 1264 if (CAN_SIGN_EXTEND_8_32(imm)) { 1265 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_SUB); 1266 m_formatter.immediate8s(imm); 1267 } else { 1268 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_SUB); 1269 m_formatter.immediate16(imm); 1270 } 1271 } 1272 subl_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)1273 void subl_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 1274 int scale) { 1275 spew("subl $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale)); 1276 if (CAN_SIGN_EXTEND_8_32(imm)) { 1277 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, 1278 GROUP1_OP_SUB); 1279 m_formatter.immediate8s(imm); 1280 } else { 1281 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, 1282 GROUP1_OP_SUB); 1283 m_formatter.immediate32(imm); 1284 } 1285 } 1286 subw_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)1287 void subw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 1288 int scale) { 1289 spew("subw $%d, " MEM_obs, int16_t(imm), 1290 ADDR_obs(offset, base, index, scale)); 1291 m_formatter.prefix(PRE_OPERAND_SIZE); 1292 if (CAN_SIGN_EXTEND_8_32(imm)) { 1293 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, 1294 GROUP1_OP_SUB); 1295 m_formatter.immediate8s(imm); 1296 } else { 1297 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, 1298 GROUP1_OP_SUB); 1299 m_formatter.immediate16(imm); 1300 } 1301 } 1302 xorl_rr(RegisterID src,RegisterID dst)1303 void xorl_rr(RegisterID src, RegisterID dst) { 1304 spew("xorl %s, %s", GPReg32Name(src), GPReg32Name(dst)); 1305 m_formatter.oneByteOp(OP_XOR_GvEv, src, dst); 1306 } 1307 xorw_rr(RegisterID src,RegisterID dst)1308 void xorw_rr(RegisterID src, RegisterID dst) { 1309 spew("xorw %s, %s", GPReg16Name(src), GPReg16Name(dst)); 1310 m_formatter.prefix(PRE_OPERAND_SIZE); 1311 m_formatter.oneByteOp(OP_XOR_GvEv, src, dst); 1312 } 1313 xorl_mr(int32_t offset,RegisterID base,RegisterID dst)1314 void xorl_mr(int32_t offset, RegisterID base, RegisterID dst) { 1315 spew("xorl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst)); 1316 m_formatter.oneByteOp(OP_XOR_GvEv, offset, base, dst); 1317 } 1318 xorl_rm(RegisterID src,int32_t offset,RegisterID base)1319 void xorl_rm(RegisterID src, int32_t offset, RegisterID base) { 1320 spew("xorl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base)); 1321 m_formatter.oneByteOp(OP_XOR_EvGv, offset, base, src); 1322 } 1323 xorw_rm(RegisterID src,int32_t offset,RegisterID base)1324 void xorw_rm(RegisterID src, int32_t offset, RegisterID base) { 1325 spew("xorw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base)); 1326 m_formatter.prefix(PRE_OPERAND_SIZE); 1327 m_formatter.oneByteOp(OP_XOR_EvGv, offset, base, src); 1328 } 1329 xorl_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)1330 void xorl_rm(RegisterID src, int32_t offset, RegisterID base, 1331 RegisterID index, int scale) { 1332 spew("xorl %s, " MEM_obs, GPReg32Name(src), 1333 ADDR_obs(offset, base, index, scale)); 1334 m_formatter.oneByteOp(OP_XOR_EvGv, offset, base, index, scale, src); 1335 } 1336 xorw_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)1337 void xorw_rm(RegisterID src, int32_t offset, RegisterID base, 1338 RegisterID index, int scale) { 1339 spew("xorw %s, " MEM_obs, GPReg16Name(src), 1340 ADDR_obs(offset, base, index, scale)); 1341 m_formatter.prefix(PRE_OPERAND_SIZE); 1342 m_formatter.oneByteOp(OP_XOR_EvGv, offset, base, index, scale, src); 1343 } 1344 xorl_im(int32_t imm,int32_t offset,RegisterID base)1345 void xorl_im(int32_t imm, int32_t offset, RegisterID base) { 1346 spew("xorl $0x%x, " MEM_ob, imm, ADDR_ob(offset, base)); 1347 if (CAN_SIGN_EXTEND_8_32(imm)) { 1348 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_XOR); 1349 m_formatter.immediate8s(imm); 1350 } else { 1351 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_XOR); 1352 m_formatter.immediate32(imm); 1353 } 1354 } 1355 xorw_im(int32_t imm,int32_t offset,RegisterID base)1356 void xorw_im(int32_t imm, int32_t offset, RegisterID base) { 1357 spew("xorw $0x%x, " MEM_ob, int16_t(imm), ADDR_ob(offset, base)); 1358 m_formatter.prefix(PRE_OPERAND_SIZE); 1359 if (CAN_SIGN_EXTEND_8_32(imm)) { 1360 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_XOR); 1361 m_formatter.immediate8s(imm); 1362 } else { 1363 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_XOR); 1364 m_formatter.immediate16(imm); 1365 } 1366 } 1367 xorl_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)1368 void xorl_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 1369 int scale) { 1370 spew("xorl $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale)); 1371 if (CAN_SIGN_EXTEND_8_32(imm)) { 1372 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, 1373 GROUP1_OP_XOR); 1374 m_formatter.immediate8s(imm); 1375 } else { 1376 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, 1377 GROUP1_OP_XOR); 1378 m_formatter.immediate32(imm); 1379 } 1380 } 1381 xorw_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)1382 void xorw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 1383 int scale) { 1384 spew("xorw $%d, " MEM_obs, int16_t(imm), 1385 ADDR_obs(offset, base, index, scale)); 1386 m_formatter.prefix(PRE_OPERAND_SIZE); 1387 if (CAN_SIGN_EXTEND_8_32(imm)) { 1388 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, 1389 GROUP1_OP_XOR); 1390 m_formatter.immediate8s(imm); 1391 } else { 1392 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, 1393 GROUP1_OP_XOR); 1394 m_formatter.immediate16(imm); 1395 } 1396 } 1397 xorl_ir(int32_t imm,RegisterID dst)1398 void xorl_ir(int32_t imm, RegisterID dst) { 1399 spew("xorl $%d, %s", imm, GPReg32Name(dst)); 1400 if (CAN_SIGN_EXTEND_8_32(imm)) { 1401 m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_XOR); 1402 m_formatter.immediate8s(imm); 1403 } else { 1404 if (dst == rax) 1405 m_formatter.oneByteOp(OP_XOR_EAXIv); 1406 else 1407 m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_XOR); 1408 m_formatter.immediate32(imm); 1409 } 1410 } 1411 xorw_ir(int32_t imm,RegisterID dst)1412 void xorw_ir(int32_t imm, RegisterID dst) { 1413 spew("xorw $%d, %s", int16_t(imm), GPReg16Name(dst)); 1414 m_formatter.prefix(PRE_OPERAND_SIZE); 1415 if (CAN_SIGN_EXTEND_8_32(imm)) { 1416 m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_XOR); 1417 m_formatter.immediate8s(imm); 1418 } else { 1419 if (dst == rax) 1420 m_formatter.oneByteOp(OP_XOR_EAXIv); 1421 else 1422 m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_XOR); 1423 m_formatter.immediate16(imm); 1424 } 1425 } 1426 sarl_ir(int32_t imm,RegisterID dst)1427 void sarl_ir(int32_t imm, RegisterID dst) { 1428 MOZ_ASSERT(imm < 32); 1429 spew("sarl $%d, %s", imm, GPReg32Name(dst)); 1430 if (imm == 1) 1431 m_formatter.oneByteOp(OP_GROUP2_Ev1, dst, GROUP2_OP_SAR); 1432 else { 1433 m_formatter.oneByteOp(OP_GROUP2_EvIb, dst, GROUP2_OP_SAR); 1434 m_formatter.immediate8u(imm); 1435 } 1436 } 1437 sarl_CLr(RegisterID dst)1438 void sarl_CLr(RegisterID dst) { 1439 spew("sarl %%cl, %s", GPReg32Name(dst)); 1440 m_formatter.oneByteOp(OP_GROUP2_EvCL, dst, GROUP2_OP_SAR); 1441 } 1442 shrl_ir(int32_t imm,RegisterID dst)1443 void shrl_ir(int32_t imm, RegisterID dst) { 1444 MOZ_ASSERT(imm < 32); 1445 spew("shrl $%d, %s", imm, GPReg32Name(dst)); 1446 if (imm == 1) 1447 m_formatter.oneByteOp(OP_GROUP2_Ev1, dst, GROUP2_OP_SHR); 1448 else { 1449 m_formatter.oneByteOp(OP_GROUP2_EvIb, dst, GROUP2_OP_SHR); 1450 m_formatter.immediate8u(imm); 1451 } 1452 } 1453 shrl_CLr(RegisterID dst)1454 void shrl_CLr(RegisterID dst) { 1455 spew("shrl %%cl, %s", GPReg32Name(dst)); 1456 m_formatter.oneByteOp(OP_GROUP2_EvCL, dst, GROUP2_OP_SHR); 1457 } 1458 shrdl_CLr(RegisterID src,RegisterID dst)1459 void shrdl_CLr(RegisterID src, RegisterID dst) { 1460 spew("shrdl %%cl, %s, %s", GPReg32Name(src), GPReg32Name(dst)); 1461 m_formatter.twoByteOp(OP2_SHRD_GvEv, dst, src); 1462 } 1463 shldl_CLr(RegisterID src,RegisterID dst)1464 void shldl_CLr(RegisterID src, RegisterID dst) { 1465 spew("shldl %%cl, %s, %s", GPReg32Name(src), GPReg32Name(dst)); 1466 m_formatter.twoByteOp(OP2_SHLD_GvEv, dst, src); 1467 } 1468 shll_ir(int32_t imm,RegisterID dst)1469 void shll_ir(int32_t imm, RegisterID dst) { 1470 MOZ_ASSERT(imm < 32); 1471 spew("shll $%d, %s", imm, GPReg32Name(dst)); 1472 if (imm == 1) 1473 m_formatter.oneByteOp(OP_GROUP2_Ev1, dst, GROUP2_OP_SHL); 1474 else { 1475 m_formatter.oneByteOp(OP_GROUP2_EvIb, dst, GROUP2_OP_SHL); 1476 m_formatter.immediate8u(imm); 1477 } 1478 } 1479 shll_CLr(RegisterID dst)1480 void shll_CLr(RegisterID dst) { 1481 spew("shll %%cl, %s", GPReg32Name(dst)); 1482 m_formatter.oneByteOp(OP_GROUP2_EvCL, dst, GROUP2_OP_SHL); 1483 } 1484 roll_ir(int32_t imm,RegisterID dst)1485 void roll_ir(int32_t imm, RegisterID dst) { 1486 MOZ_ASSERT(imm < 32); 1487 spew("roll $%d, %s", imm, GPReg32Name(dst)); 1488 if (imm == 1) 1489 m_formatter.oneByteOp(OP_GROUP2_Ev1, dst, GROUP2_OP_ROL); 1490 else { 1491 m_formatter.oneByteOp(OP_GROUP2_EvIb, dst, GROUP2_OP_ROL); 1492 m_formatter.immediate8u(imm); 1493 } 1494 } roll_CLr(RegisterID dst)1495 void roll_CLr(RegisterID dst) { 1496 spew("roll %%cl, %s", GPReg32Name(dst)); 1497 m_formatter.oneByteOp(OP_GROUP2_EvCL, dst, GROUP2_OP_ROL); 1498 } 1499 rorl_ir(int32_t imm,RegisterID dst)1500 void rorl_ir(int32_t imm, RegisterID dst) { 1501 MOZ_ASSERT(imm < 32); 1502 spew("rorl $%d, %s", imm, GPReg32Name(dst)); 1503 if (imm == 1) 1504 m_formatter.oneByteOp(OP_GROUP2_Ev1, dst, GROUP2_OP_ROR); 1505 else { 1506 m_formatter.oneByteOp(OP_GROUP2_EvIb, dst, GROUP2_OP_ROR); 1507 m_formatter.immediate8u(imm); 1508 } 1509 } rorl_CLr(RegisterID dst)1510 void rorl_CLr(RegisterID dst) { 1511 spew("rorl %%cl, %s", GPReg32Name(dst)); 1512 m_formatter.oneByteOp(OP_GROUP2_EvCL, dst, GROUP2_OP_ROR); 1513 } 1514 bsrl_rr(RegisterID src,RegisterID dst)1515 void bsrl_rr(RegisterID src, RegisterID dst) { 1516 spew("bsrl %s, %s", GPReg32Name(src), GPReg32Name(dst)); 1517 m_formatter.twoByteOp(OP2_BSR_GvEv, src, dst); 1518 } 1519 bsfl_rr(RegisterID src,RegisterID dst)1520 void bsfl_rr(RegisterID src, RegisterID dst) { 1521 spew("bsfl %s, %s", GPReg32Name(src), GPReg32Name(dst)); 1522 m_formatter.twoByteOp(OP2_BSF_GvEv, src, dst); 1523 } 1524 popcntl_rr(RegisterID src,RegisterID dst)1525 void popcntl_rr(RegisterID src, RegisterID dst) { 1526 spew("popcntl %s, %s", GPReg32Name(src), GPReg32Name(dst)); 1527 m_formatter.legacySSEPrefix(VEX_SS); 1528 m_formatter.twoByteOp(OP2_POPCNT_GvEv, src, dst); 1529 } 1530 imull_rr(RegisterID src,RegisterID dst)1531 void imull_rr(RegisterID src, RegisterID dst) { 1532 spew("imull %s, %s", GPReg32Name(src), GPReg32Name(dst)); 1533 m_formatter.twoByteOp(OP2_IMUL_GvEv, src, dst); 1534 } 1535 imull_r(RegisterID multiplier)1536 void imull_r(RegisterID multiplier) { 1537 spew("imull %s", GPReg32Name(multiplier)); 1538 m_formatter.oneByteOp(OP_GROUP3_Ev, multiplier, GROUP3_OP_IMUL); 1539 } 1540 imull_mr(int32_t offset,RegisterID base,RegisterID dst)1541 void imull_mr(int32_t offset, RegisterID base, RegisterID dst) { 1542 spew("imull " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst)); 1543 m_formatter.twoByteOp(OP2_IMUL_GvEv, offset, base, dst); 1544 } 1545 imull_ir(int32_t value,RegisterID src,RegisterID dst)1546 void imull_ir(int32_t value, RegisterID src, RegisterID dst) { 1547 spew("imull $%d, %s, %s", value, GPReg32Name(src), GPReg32Name(dst)); 1548 if (CAN_SIGN_EXTEND_8_32(value)) { 1549 m_formatter.oneByteOp(OP_IMUL_GvEvIb, src, dst); 1550 m_formatter.immediate8s(value); 1551 } else { 1552 m_formatter.oneByteOp(OP_IMUL_GvEvIz, src, dst); 1553 m_formatter.immediate32(value); 1554 } 1555 } 1556 mull_r(RegisterID multiplier)1557 void mull_r(RegisterID multiplier) { 1558 spew("mull %s", GPReg32Name(multiplier)); 1559 m_formatter.oneByteOp(OP_GROUP3_Ev, multiplier, GROUP3_OP_MUL); 1560 } 1561 idivl_r(RegisterID divisor)1562 void idivl_r(RegisterID divisor) { 1563 spew("idivl %s", GPReg32Name(divisor)); 1564 m_formatter.oneByteOp(OP_GROUP3_Ev, divisor, GROUP3_OP_IDIV); 1565 } 1566 divl_r(RegisterID divisor)1567 void divl_r(RegisterID divisor) { 1568 spew("div %s", GPReg32Name(divisor)); 1569 m_formatter.oneByteOp(OP_GROUP3_Ev, divisor, GROUP3_OP_DIV); 1570 } 1571 prefix_lock()1572 void prefix_lock() { 1573 spew("lock"); 1574 m_formatter.oneByteOp(PRE_LOCK); 1575 } 1576 prefix_16_for_32()1577 void prefix_16_for_32() { 1578 spew("[16-bit operands next]"); 1579 m_formatter.prefix(PRE_OPERAND_SIZE); 1580 } 1581 incl_m32(int32_t offset,RegisterID base)1582 void incl_m32(int32_t offset, RegisterID base) { 1583 spew("incl " MEM_ob, ADDR_ob(offset, base)); 1584 m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, GROUP5_OP_INC); 1585 } 1586 decl_m32(int32_t offset,RegisterID base)1587 void decl_m32(int32_t offset, RegisterID base) { 1588 spew("decl " MEM_ob, ADDR_ob(offset, base)); 1589 m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, GROUP5_OP_DEC); 1590 } 1591 1592 // Note that CMPXCHG performs comparison against REG = %al/%ax/%eax/%rax. 1593 // If %REG == [%base+offset], then %src -> [%base+offset]. 1594 // Otherwise, [%base+offset] -> %REG. 1595 // For the 8-bit operations src must also be an 8-bit register. 1596 cmpxchgb(RegisterID src,int32_t offset,RegisterID base)1597 void cmpxchgb(RegisterID src, int32_t offset, RegisterID base) { 1598 spew("cmpxchgb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base)); 1599 m_formatter.twoByteOp8(OP2_CMPXCHG_GvEb, offset, base, src); 1600 } cmpxchgb(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)1601 void cmpxchgb(RegisterID src, int32_t offset, RegisterID base, 1602 RegisterID index, int scale) { 1603 spew("cmpxchgb %s, " MEM_obs, GPReg8Name(src), 1604 ADDR_obs(offset, base, index, scale)); 1605 m_formatter.twoByteOp8(OP2_CMPXCHG_GvEb, offset, base, index, scale, src); 1606 } cmpxchgw(RegisterID src,int32_t offset,RegisterID base)1607 void cmpxchgw(RegisterID src, int32_t offset, RegisterID base) { 1608 spew("cmpxchgw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base)); 1609 m_formatter.prefix(PRE_OPERAND_SIZE); 1610 m_formatter.twoByteOp(OP2_CMPXCHG_GvEw, offset, base, src); 1611 } cmpxchgw(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)1612 void cmpxchgw(RegisterID src, int32_t offset, RegisterID base, 1613 RegisterID index, int scale) { 1614 spew("cmpxchgw %s, " MEM_obs, GPReg16Name(src), 1615 ADDR_obs(offset, base, index, scale)); 1616 m_formatter.prefix(PRE_OPERAND_SIZE); 1617 m_formatter.twoByteOp(OP2_CMPXCHG_GvEw, offset, base, index, scale, src); 1618 } cmpxchgl(RegisterID src,int32_t offset,RegisterID base)1619 void cmpxchgl(RegisterID src, int32_t offset, RegisterID base) { 1620 spew("cmpxchgl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base)); 1621 m_formatter.twoByteOp(OP2_CMPXCHG_GvEw, offset, base, src); 1622 } cmpxchgl(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)1623 void cmpxchgl(RegisterID src, int32_t offset, RegisterID base, 1624 RegisterID index, int scale) { 1625 spew("cmpxchgl %s, " MEM_obs, GPReg32Name(src), 1626 ADDR_obs(offset, base, index, scale)); 1627 m_formatter.twoByteOp(OP2_CMPXCHG_GvEw, offset, base, index, scale, src); 1628 } 1629 cmpxchg8b(RegisterID srcHi,RegisterID srcLo,RegisterID newHi,RegisterID newLo,int32_t offset,RegisterID base)1630 void cmpxchg8b(RegisterID srcHi, RegisterID srcLo, RegisterID newHi, 1631 RegisterID newLo, int32_t offset, RegisterID base) { 1632 MOZ_ASSERT(srcHi == edx.code() && srcLo == eax.code()); 1633 MOZ_ASSERT(newHi == ecx.code() && newLo == ebx.code()); 1634 spew("cmpxchg8b %s, " MEM_ob, "edx:eax", ADDR_ob(offset, base)); 1635 m_formatter.twoByteOp(OP2_CMPXCHGNB, offset, base, 1); 1636 } cmpxchg8b(RegisterID srcHi,RegisterID srcLo,RegisterID newHi,RegisterID newLo,int32_t offset,RegisterID base,RegisterID index,int scale)1637 void cmpxchg8b(RegisterID srcHi, RegisterID srcLo, RegisterID newHi, 1638 RegisterID newLo, int32_t offset, RegisterID base, 1639 RegisterID index, int scale) { 1640 MOZ_ASSERT(srcHi == edx.code() && srcLo == eax.code()); 1641 MOZ_ASSERT(newHi == ecx.code() && newLo == ebx.code()); 1642 spew("cmpxchg8b %s, " MEM_obs, "edx:eax", 1643 ADDR_obs(offset, base, index, scale)); 1644 m_formatter.twoByteOp(OP2_CMPXCHGNB, offset, base, index, scale, 1); 1645 } 1646 1647 // Comparisons: 1648 cmpl_rr(RegisterID rhs,RegisterID lhs)1649 void cmpl_rr(RegisterID rhs, RegisterID lhs) { 1650 spew("cmpl %s, %s", GPReg32Name(rhs), GPReg32Name(lhs)); 1651 m_formatter.oneByteOp(OP_CMP_GvEv, rhs, lhs); 1652 } 1653 cmpl_rm(RegisterID rhs,int32_t offset,RegisterID base)1654 void cmpl_rm(RegisterID rhs, int32_t offset, RegisterID base) { 1655 spew("cmpl %s, " MEM_ob, GPReg32Name(rhs), ADDR_ob(offset, base)); 1656 m_formatter.oneByteOp(OP_CMP_EvGv, offset, base, rhs); 1657 } 1658 cmpl_mr(int32_t offset,RegisterID base,RegisterID lhs)1659 void cmpl_mr(int32_t offset, RegisterID base, RegisterID lhs) { 1660 spew("cmpl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(lhs)); 1661 m_formatter.oneByteOp(OP_CMP_GvEv, offset, base, lhs); 1662 } 1663 cmpl_mr(const void * address,RegisterID lhs)1664 void cmpl_mr(const void* address, RegisterID lhs) { 1665 spew("cmpl %p, %s", address, GPReg32Name(lhs)); 1666 m_formatter.oneByteOp(OP_CMP_GvEv, address, lhs); 1667 } 1668 cmpl_ir(int32_t rhs,RegisterID lhs)1669 void cmpl_ir(int32_t rhs, RegisterID lhs) { 1670 if (rhs == 0) { 1671 testl_rr(lhs, lhs); 1672 return; 1673 } 1674 1675 spew("cmpl $0x%x, %s", rhs, GPReg32Name(lhs)); 1676 if (CAN_SIGN_EXTEND_8_32(rhs)) { 1677 m_formatter.oneByteOp(OP_GROUP1_EvIb, lhs, GROUP1_OP_CMP); 1678 m_formatter.immediate8s(rhs); 1679 } else { 1680 if (lhs == rax) 1681 m_formatter.oneByteOp(OP_CMP_EAXIv); 1682 else 1683 m_formatter.oneByteOp(OP_GROUP1_EvIz, lhs, GROUP1_OP_CMP); 1684 m_formatter.immediate32(rhs); 1685 } 1686 } 1687 cmpl_i32r(int32_t rhs,RegisterID lhs)1688 void cmpl_i32r(int32_t rhs, RegisterID lhs) { 1689 spew("cmpl $0x%04x, %s", rhs, GPReg32Name(lhs)); 1690 if (lhs == rax) 1691 m_formatter.oneByteOp(OP_CMP_EAXIv); 1692 else 1693 m_formatter.oneByteOp(OP_GROUP1_EvIz, lhs, GROUP1_OP_CMP); 1694 m_formatter.immediate32(rhs); 1695 } 1696 cmpl_im(int32_t rhs,int32_t offset,RegisterID base)1697 void cmpl_im(int32_t rhs, int32_t offset, RegisterID base) { 1698 spew("cmpl $0x%x, " MEM_ob, rhs, ADDR_ob(offset, base)); 1699 if (CAN_SIGN_EXTEND_8_32(rhs)) { 1700 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_CMP); 1701 m_formatter.immediate8s(rhs); 1702 } else { 1703 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_CMP); 1704 m_formatter.immediate32(rhs); 1705 } 1706 } 1707 cmpb_im(int32_t rhs,int32_t offset,RegisterID base)1708 void cmpb_im(int32_t rhs, int32_t offset, RegisterID base) { 1709 spew("cmpb $0x%x, " MEM_ob, rhs, ADDR_ob(offset, base)); 1710 m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_CMP); 1711 m_formatter.immediate8(rhs); 1712 } 1713 cmpb_im(int32_t rhs,int32_t offset,RegisterID base,RegisterID index,int scale)1714 void cmpb_im(int32_t rhs, int32_t offset, RegisterID base, RegisterID index, 1715 int scale) { 1716 spew("cmpb $0x%x, " MEM_obs, rhs, 1717 ADDR_obs(offset, base, index, scale)); 1718 m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, 1719 GROUP1_OP_CMP); 1720 m_formatter.immediate8(rhs); 1721 } 1722 cmpl_im(int32_t rhs,int32_t offset,RegisterID base,RegisterID index,int scale)1723 void cmpl_im(int32_t rhs, int32_t offset, RegisterID base, RegisterID index, 1724 int scale) { 1725 spew("cmpl $0x%x, " MEM_o32b, rhs, ADDR_o32b(offset, base)); 1726 if (CAN_SIGN_EXTEND_8_32(rhs)) { 1727 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, 1728 GROUP1_OP_CMP); 1729 m_formatter.immediate8s(rhs); 1730 } else { 1731 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, 1732 GROUP1_OP_CMP); 1733 m_formatter.immediate32(rhs); 1734 } 1735 } 1736 cmpl_im_disp32(int32_t rhs,int32_t offset,RegisterID base)1737 MOZ_MUST_USE JmpSrc cmpl_im_disp32(int32_t rhs, int32_t offset, 1738 RegisterID base) { 1739 spew("cmpl $0x%x, " MEM_o32b, rhs, ADDR_o32b(offset, base)); 1740 JmpSrc r; 1741 if (CAN_SIGN_EXTEND_8_32(rhs)) { 1742 m_formatter.oneByteOp_disp32(OP_GROUP1_EvIb, offset, base, GROUP1_OP_CMP); 1743 r = JmpSrc(m_formatter.size()); 1744 m_formatter.immediate8s(rhs); 1745 } else { 1746 m_formatter.oneByteOp_disp32(OP_GROUP1_EvIz, offset, base, GROUP1_OP_CMP); 1747 r = JmpSrc(m_formatter.size()); 1748 m_formatter.immediate32(rhs); 1749 } 1750 return r; 1751 } 1752 cmpl_im_disp32(int32_t rhs,const void * addr)1753 MOZ_MUST_USE JmpSrc cmpl_im_disp32(int32_t rhs, const void* addr) { 1754 spew("cmpl $0x%x, %p", rhs, addr); 1755 JmpSrc r; 1756 if (CAN_SIGN_EXTEND_8_32(rhs)) { 1757 m_formatter.oneByteOp_disp32(OP_GROUP1_EvIb, addr, GROUP1_OP_CMP); 1758 r = JmpSrc(m_formatter.size()); 1759 m_formatter.immediate8s(rhs); 1760 } else { 1761 m_formatter.oneByteOp_disp32(OP_GROUP1_EvIz, addr, GROUP1_OP_CMP); 1762 r = JmpSrc(m_formatter.size()); 1763 m_formatter.immediate32(rhs); 1764 } 1765 return r; 1766 } 1767 cmpl_i32m(int32_t rhs,int32_t offset,RegisterID base)1768 void cmpl_i32m(int32_t rhs, int32_t offset, RegisterID base) { 1769 spew("cmpl $0x%04x, " MEM_ob, rhs, ADDR_ob(offset, base)); 1770 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_CMP); 1771 m_formatter.immediate32(rhs); 1772 } 1773 cmpl_i32m(int32_t rhs,const void * addr)1774 void cmpl_i32m(int32_t rhs, const void* addr) { 1775 spew("cmpl $0x%04x, %p", rhs, addr); 1776 m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_CMP); 1777 m_formatter.immediate32(rhs); 1778 } 1779 cmpl_rm(RegisterID rhs,const void * addr)1780 void cmpl_rm(RegisterID rhs, const void* addr) { 1781 spew("cmpl %s, %p", GPReg32Name(rhs), addr); 1782 m_formatter.oneByteOp(OP_CMP_EvGv, addr, rhs); 1783 } 1784 cmpl_rm_disp32(RegisterID rhs,const void * addr)1785 void cmpl_rm_disp32(RegisterID rhs, const void* addr) { 1786 spew("cmpl %s, %p", GPReg32Name(rhs), addr); 1787 m_formatter.oneByteOp_disp32(OP_CMP_EvGv, addr, rhs); 1788 } 1789 cmpl_im(int32_t rhs,const void * addr)1790 void cmpl_im(int32_t rhs, const void* addr) { 1791 spew("cmpl $0x%x, %p", rhs, addr); 1792 if (CAN_SIGN_EXTEND_8_32(rhs)) { 1793 m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_CMP); 1794 m_formatter.immediate8s(rhs); 1795 } else { 1796 m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_CMP); 1797 m_formatter.immediate32(rhs); 1798 } 1799 } 1800 cmpw_rr(RegisterID rhs,RegisterID lhs)1801 void cmpw_rr(RegisterID rhs, RegisterID lhs) { 1802 spew("cmpw %s, %s", GPReg16Name(rhs), GPReg16Name(lhs)); 1803 m_formatter.prefix(PRE_OPERAND_SIZE); 1804 m_formatter.oneByteOp(OP_CMP_GvEv, rhs, lhs); 1805 } 1806 cmpw_rm(RegisterID rhs,int32_t offset,RegisterID base,RegisterID index,int scale)1807 void cmpw_rm(RegisterID rhs, int32_t offset, RegisterID base, 1808 RegisterID index, int scale) { 1809 spew("cmpw %s, " MEM_obs, GPReg16Name(rhs), 1810 ADDR_obs(offset, base, index, scale)); 1811 m_formatter.prefix(PRE_OPERAND_SIZE); 1812 m_formatter.oneByteOp(OP_CMP_EvGv, offset, base, index, scale, rhs); 1813 } 1814 cmpw_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)1815 void cmpw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 1816 int scale) { 1817 spew("cmpw $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale)); 1818 if (CAN_SIGN_EXTEND_8_32(imm)) { 1819 m_formatter.prefix(PRE_OPERAND_SIZE); 1820 m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, 1821 GROUP1_OP_CMP); 1822 m_formatter.immediate8s(imm); 1823 } else { 1824 m_formatter.prefix(PRE_OPERAND_SIZE); 1825 m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, 1826 GROUP1_OP_CMP); 1827 m_formatter.immediate16(imm); 1828 } 1829 } 1830 testl_rr(RegisterID rhs,RegisterID lhs)1831 void testl_rr(RegisterID rhs, RegisterID lhs) { 1832 spew("testl %s, %s", GPReg32Name(rhs), GPReg32Name(lhs)); 1833 m_formatter.oneByteOp(OP_TEST_EvGv, lhs, rhs); 1834 } 1835 testb_rr(RegisterID rhs,RegisterID lhs)1836 void testb_rr(RegisterID rhs, RegisterID lhs) { 1837 spew("testb %s, %s", GPReg8Name(rhs), GPReg8Name(lhs)); 1838 m_formatter.oneByteOp(OP_TEST_EbGb, lhs, rhs); 1839 } 1840 testl_ir(int32_t rhs,RegisterID lhs)1841 void testl_ir(int32_t rhs, RegisterID lhs) { 1842 // If the mask fits in an 8-bit immediate, we can use testb with an 1843 // 8-bit subreg. 1844 if (CAN_ZERO_EXTEND_8_32(rhs) && HasSubregL(lhs)) { 1845 testb_ir(rhs, lhs); 1846 return; 1847 } 1848 // If the mask is a subset of 0xff00, we can use testb with an h reg, if 1849 // one happens to be available. 1850 if (CAN_ZERO_EXTEND_8H_32(rhs) && HasSubregH(lhs)) { 1851 testb_ir_norex(rhs >> 8, GetSubregH(lhs)); 1852 return; 1853 } 1854 spew("testl $0x%x, %s", rhs, GPReg32Name(lhs)); 1855 if (lhs == rax) 1856 m_formatter.oneByteOp(OP_TEST_EAXIv); 1857 else 1858 m_formatter.oneByteOp(OP_GROUP3_EvIz, lhs, GROUP3_OP_TEST); 1859 m_formatter.immediate32(rhs); 1860 } 1861 testl_i32m(int32_t rhs,int32_t offset,RegisterID base)1862 void testl_i32m(int32_t rhs, int32_t offset, RegisterID base) { 1863 spew("testl $0x%x, " MEM_ob, rhs, ADDR_ob(offset, base)); 1864 m_formatter.oneByteOp(OP_GROUP3_EvIz, offset, base, GROUP3_OP_TEST); 1865 m_formatter.immediate32(rhs); 1866 } 1867 testl_i32m(int32_t rhs,const void * addr)1868 void testl_i32m(int32_t rhs, const void* addr) { 1869 spew("testl $0x%x, %p", rhs, addr); 1870 m_formatter.oneByteOp(OP_GROUP3_EvIz, addr, GROUP3_OP_TEST); 1871 m_formatter.immediate32(rhs); 1872 } 1873 testb_im(int32_t rhs,int32_t offset,RegisterID base)1874 void testb_im(int32_t rhs, int32_t offset, RegisterID base) { 1875 spew("testb $0x%x, " MEM_ob, rhs, ADDR_ob(offset, base)); 1876 m_formatter.oneByteOp(OP_GROUP3_EbIb, offset, base, GROUP3_OP_TEST); 1877 m_formatter.immediate8(rhs); 1878 } 1879 testb_im(int32_t rhs,int32_t offset,RegisterID base,RegisterID index,int scale)1880 void testb_im(int32_t rhs, int32_t offset, RegisterID base, RegisterID index, 1881 int scale) { 1882 spew("testb $0x%x, " MEM_obs, rhs, 1883 ADDR_obs(offset, base, index, scale)); 1884 m_formatter.oneByteOp(OP_GROUP3_EbIb, offset, base, index, scale, 1885 GROUP3_OP_TEST); 1886 m_formatter.immediate8(rhs); 1887 } 1888 testl_i32m(int32_t rhs,int32_t offset,RegisterID base,RegisterID index,int scale)1889 void testl_i32m(int32_t rhs, int32_t offset, RegisterID base, 1890 RegisterID index, int scale) { 1891 spew("testl $0x%4x, " MEM_obs, rhs, 1892 ADDR_obs(offset, base, index, scale)); 1893 m_formatter.oneByteOp(OP_GROUP3_EvIz, offset, base, index, scale, 1894 GROUP3_OP_TEST); 1895 m_formatter.immediate32(rhs); 1896 } 1897 testw_rr(RegisterID rhs,RegisterID lhs)1898 void testw_rr(RegisterID rhs, RegisterID lhs) { 1899 spew("testw %s, %s", GPReg16Name(rhs), GPReg16Name(lhs)); 1900 m_formatter.prefix(PRE_OPERAND_SIZE); 1901 m_formatter.oneByteOp(OP_TEST_EvGv, lhs, rhs); 1902 } 1903 testb_ir(int32_t rhs,RegisterID lhs)1904 void testb_ir(int32_t rhs, RegisterID lhs) { 1905 spew("testb $0x%x, %s", rhs, GPReg8Name(lhs)); 1906 if (lhs == rax) 1907 m_formatter.oneByteOp8(OP_TEST_EAXIb); 1908 else 1909 m_formatter.oneByteOp8(OP_GROUP3_EbIb, lhs, GROUP3_OP_TEST); 1910 m_formatter.immediate8(rhs); 1911 } 1912 1913 // Like testb_ir, but never emits a REX prefix. This may be used to 1914 // reference ah..bh. testb_ir_norex(int32_t rhs,HRegisterID lhs)1915 void testb_ir_norex(int32_t rhs, HRegisterID lhs) { 1916 spew("testb $0x%x, %s", rhs, HRegName8(lhs)); 1917 m_formatter.oneByteOp8_norex(OP_GROUP3_EbIb, lhs, GROUP3_OP_TEST); 1918 m_formatter.immediate8(rhs); 1919 } 1920 setCC_r(Condition cond,RegisterID lhs)1921 void setCC_r(Condition cond, RegisterID lhs) { 1922 spew("set%s %s", CCName(cond), GPReg8Name(lhs)); 1923 m_formatter.twoByteOp8(setccOpcode(cond), lhs, (GroupOpcodeID)0); 1924 } 1925 sete_r(RegisterID dst)1926 void sete_r(RegisterID dst) { setCC_r(ConditionE, dst); } 1927 setz_r(RegisterID dst)1928 void setz_r(RegisterID dst) { sete_r(dst); } 1929 setne_r(RegisterID dst)1930 void setne_r(RegisterID dst) { setCC_r(ConditionNE, dst); } 1931 setnz_r(RegisterID dst)1932 void setnz_r(RegisterID dst) { setne_r(dst); } 1933 1934 // Various move ops: 1935 cdq()1936 void cdq() { 1937 spew("cdq "); 1938 m_formatter.oneByteOp(OP_CDQ); 1939 } 1940 xchgb_rm(RegisterID src,int32_t offset,RegisterID base)1941 void xchgb_rm(RegisterID src, int32_t offset, RegisterID base) { 1942 spew("xchgb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base)); 1943 m_formatter.oneByteOp8(OP_XCHG_GbEb, offset, base, src); 1944 } xchgb_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)1945 void xchgb_rm(RegisterID src, int32_t offset, RegisterID base, 1946 RegisterID index, int scale) { 1947 spew("xchgb %s, " MEM_obs, GPReg8Name(src), 1948 ADDR_obs(offset, base, index, scale)); 1949 m_formatter.oneByteOp8(OP_XCHG_GbEb, offset, base, index, scale, src); 1950 } 1951 xchgw_rm(RegisterID src,int32_t offset,RegisterID base)1952 void xchgw_rm(RegisterID src, int32_t offset, RegisterID base) { 1953 spew("xchgw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base)); 1954 m_formatter.prefix(PRE_OPERAND_SIZE); 1955 m_formatter.oneByteOp(OP_XCHG_GvEv, offset, base, src); 1956 } xchgw_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)1957 void xchgw_rm(RegisterID src, int32_t offset, RegisterID base, 1958 RegisterID index, int scale) { 1959 spew("xchgw %s, " MEM_obs, GPReg16Name(src), 1960 ADDR_obs(offset, base, index, scale)); 1961 m_formatter.prefix(PRE_OPERAND_SIZE); 1962 m_formatter.oneByteOp(OP_XCHG_GvEv, offset, base, index, scale, src); 1963 } 1964 xchgl_rr(RegisterID src,RegisterID dst)1965 void xchgl_rr(RegisterID src, RegisterID dst) { 1966 spew("xchgl %s, %s", GPReg32Name(src), GPReg32Name(dst)); 1967 m_formatter.oneByteOp(OP_XCHG_GvEv, src, dst); 1968 } xchgl_rm(RegisterID src,int32_t offset,RegisterID base)1969 void xchgl_rm(RegisterID src, int32_t offset, RegisterID base) { 1970 spew("xchgl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base)); 1971 m_formatter.oneByteOp(OP_XCHG_GvEv, offset, base, src); 1972 } xchgl_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)1973 void xchgl_rm(RegisterID src, int32_t offset, RegisterID base, 1974 RegisterID index, int scale) { 1975 spew("xchgl %s, " MEM_obs, GPReg32Name(src), 1976 ADDR_obs(offset, base, index, scale)); 1977 m_formatter.oneByteOp(OP_XCHG_GvEv, offset, base, index, scale, src); 1978 } 1979 cmovCCl_rr(Condition cond,RegisterID src,RegisterID dst)1980 void cmovCCl_rr(Condition cond, RegisterID src, RegisterID dst) { 1981 spew("cmov%s %s, %s", CCName(cond), GPReg32Name(src), GPReg32Name(dst)); 1982 m_formatter.twoByteOp(cmovccOpcode(cond), src, dst); 1983 } cmovCCl_mr(Condition cond,int32_t offset,RegisterID base,RegisterID dst)1984 void cmovCCl_mr(Condition cond, int32_t offset, RegisterID base, 1985 RegisterID dst) { 1986 spew("cmov%s " MEM_ob ", %s", CCName(cond), ADDR_ob(offset, base), 1987 GPReg32Name(dst)); 1988 m_formatter.twoByteOp(cmovccOpcode(cond), offset, base, dst); 1989 } cmovCCl_mr(Condition cond,int32_t offset,RegisterID base,RegisterID index,int scale,RegisterID dst)1990 void cmovCCl_mr(Condition cond, int32_t offset, RegisterID base, 1991 RegisterID index, int scale, RegisterID dst) { 1992 spew("cmov%s " MEM_obs ", %s", CCName(cond), 1993 ADDR_obs(offset, base, index, scale), GPReg32Name(dst)); 1994 m_formatter.twoByteOp(cmovccOpcode(cond), offset, base, index, scale, dst); 1995 } 1996 movl_rr(RegisterID src,RegisterID dst)1997 void movl_rr(RegisterID src, RegisterID dst) { 1998 spew("movl %s, %s", GPReg32Name(src), GPReg32Name(dst)); 1999 m_formatter.oneByteOp(OP_MOV_GvEv, src, dst); 2000 } 2001 movw_rm(RegisterID src,int32_t offset,RegisterID base)2002 void movw_rm(RegisterID src, int32_t offset, RegisterID base) { 2003 spew("movw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base)); 2004 m_formatter.prefix(PRE_OPERAND_SIZE); 2005 m_formatter.oneByteOp(OP_MOV_EvGv, offset, base, src); 2006 } 2007 movw_rm_disp32(RegisterID src,int32_t offset,RegisterID base)2008 void movw_rm_disp32(RegisterID src, int32_t offset, RegisterID base) { 2009 spew("movw %s, " MEM_o32b, GPReg16Name(src), ADDR_o32b(offset, base)); 2010 m_formatter.prefix(PRE_OPERAND_SIZE); 2011 m_formatter.oneByteOp_disp32(OP_MOV_EvGv, offset, base, src); 2012 } 2013 movw_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)2014 void movw_rm(RegisterID src, int32_t offset, RegisterID base, 2015 RegisterID index, int scale) { 2016 spew("movw %s, " MEM_obs, GPReg16Name(src), 2017 ADDR_obs(offset, base, index, scale)); 2018 m_formatter.prefix(PRE_OPERAND_SIZE); 2019 m_formatter.oneByteOp(OP_MOV_EvGv, offset, base, index, scale, src); 2020 } 2021 movw_rm(RegisterID src,const void * addr)2022 void movw_rm(RegisterID src, const void* addr) { 2023 spew("movw %s, %p", GPReg16Name(src), addr); 2024 m_formatter.prefix(PRE_OPERAND_SIZE); 2025 m_formatter.oneByteOp_disp32(OP_MOV_EvGv, addr, src); 2026 } 2027 movl_rm(RegisterID src,int32_t offset,RegisterID base)2028 void movl_rm(RegisterID src, int32_t offset, RegisterID base) { 2029 spew("movl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base)); 2030 m_formatter.oneByteOp(OP_MOV_EvGv, offset, base, src); 2031 } 2032 movl_rm_disp32(RegisterID src,int32_t offset,RegisterID base)2033 void movl_rm_disp32(RegisterID src, int32_t offset, RegisterID base) { 2034 spew("movl %s, " MEM_o32b, GPReg32Name(src), ADDR_o32b(offset, base)); 2035 m_formatter.oneByteOp_disp32(OP_MOV_EvGv, offset, base, src); 2036 } 2037 movl_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)2038 void movl_rm(RegisterID src, int32_t offset, RegisterID base, 2039 RegisterID index, int scale) { 2040 spew("movl %s, " MEM_obs, GPReg32Name(src), 2041 ADDR_obs(offset, base, index, scale)); 2042 m_formatter.oneByteOp(OP_MOV_EvGv, offset, base, index, scale, src); 2043 } 2044 movl_mEAX(const void * addr)2045 void movl_mEAX(const void* addr) { 2046 #ifdef JS_CODEGEN_X64 2047 if (IsAddressImmediate(addr)) { 2048 movl_mr(addr, rax); 2049 return; 2050 } 2051 #endif 2052 2053 #ifdef JS_CODEGEN_X64 2054 spew("movabs %p, %%eax", addr); 2055 #else 2056 spew("movl %p, %%eax", addr); 2057 #endif 2058 m_formatter.oneByteOp(OP_MOV_EAXOv); 2059 #ifdef JS_CODEGEN_X64 2060 m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); 2061 #else 2062 m_formatter.immediate32(reinterpret_cast<int32_t>(addr)); 2063 #endif 2064 } 2065 movl_mr(int32_t offset,RegisterID base,RegisterID dst)2066 void movl_mr(int32_t offset, RegisterID base, RegisterID dst) { 2067 spew("movl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst)); 2068 m_formatter.oneByteOp(OP_MOV_GvEv, offset, base, dst); 2069 } 2070 movl_mr_disp32(int32_t offset,RegisterID base,RegisterID dst)2071 void movl_mr_disp32(int32_t offset, RegisterID base, RegisterID dst) { 2072 spew("movl " MEM_o32b ", %s", ADDR_o32b(offset, base), 2073 GPReg32Name(dst)); 2074 m_formatter.oneByteOp_disp32(OP_MOV_GvEv, offset, base, dst); 2075 } 2076 movl_mr(const void * base,RegisterID index,int scale,RegisterID dst)2077 void movl_mr(const void* base, RegisterID index, int scale, RegisterID dst) { 2078 int32_t disp = AddressImmediate(base); 2079 2080 spew("movl " MEM_os ", %s", ADDR_os(disp, index, scale), 2081 GPReg32Name(dst)); 2082 m_formatter.oneByteOp_disp32(OP_MOV_GvEv, disp, index, scale, dst); 2083 } 2084 movl_mr(int32_t offset,RegisterID base,RegisterID index,int scale,RegisterID dst)2085 void movl_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 2086 RegisterID dst) { 2087 spew("movl " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), 2088 GPReg32Name(dst)); 2089 m_formatter.oneByteOp(OP_MOV_GvEv, offset, base, index, scale, dst); 2090 } 2091 movl_mr(const void * addr,RegisterID dst)2092 void movl_mr(const void* addr, RegisterID dst) { 2093 if (dst == rax 2094 #ifdef JS_CODEGEN_X64 2095 && !IsAddressImmediate(addr) 2096 #endif 2097 ) { 2098 movl_mEAX(addr); 2099 return; 2100 } 2101 2102 spew("movl %p, %s", addr, GPReg32Name(dst)); 2103 m_formatter.oneByteOp(OP_MOV_GvEv, addr, dst); 2104 } 2105 movl_i32r(int32_t imm,RegisterID dst)2106 void movl_i32r(int32_t imm, RegisterID dst) { 2107 spew("movl $0x%x, %s", imm, GPReg32Name(dst)); 2108 m_formatter.oneByteOp(OP_MOV_EAXIv, dst); 2109 m_formatter.immediate32(imm); 2110 } 2111 movb_ir(int32_t imm,RegisterID reg)2112 void movb_ir(int32_t imm, RegisterID reg) { 2113 spew("movb $0x%x, %s", imm, GPReg8Name(reg)); 2114 m_formatter.oneByteOp8(OP_MOV_EbIb, reg); 2115 m_formatter.immediate8(imm); 2116 } 2117 movb_im(int32_t imm,int32_t offset,RegisterID base)2118 void movb_im(int32_t imm, int32_t offset, RegisterID base) { 2119 spew("movb $0x%x, " MEM_ob, imm, ADDR_ob(offset, base)); 2120 m_formatter.oneByteOp(OP_GROUP11_EvIb, offset, base, GROUP11_MOV); 2121 m_formatter.immediate8(imm); 2122 } 2123 movb_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)2124 void movb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 2125 int scale) { 2126 spew("movb $0x%x, " MEM_obs, imm, 2127 ADDR_obs(offset, base, index, scale)); 2128 m_formatter.oneByteOp(OP_GROUP11_EvIb, offset, base, index, scale, 2129 GROUP11_MOV); 2130 m_formatter.immediate8(imm); 2131 } 2132 movb_im(int32_t imm,const void * addr)2133 void movb_im(int32_t imm, const void* addr) { 2134 spew("movb $%d, %p", imm, addr); 2135 m_formatter.oneByteOp_disp32(OP_GROUP11_EvIb, addr, GROUP11_MOV); 2136 m_formatter.immediate8(imm); 2137 } 2138 movw_im(int32_t imm,int32_t offset,RegisterID base)2139 void movw_im(int32_t imm, int32_t offset, RegisterID base) { 2140 spew("movw $0x%x, " MEM_ob, imm, ADDR_ob(offset, base)); 2141 m_formatter.prefix(PRE_OPERAND_SIZE); 2142 m_formatter.oneByteOp(OP_GROUP11_EvIz, offset, base, GROUP11_MOV); 2143 m_formatter.immediate16(imm); 2144 } 2145 movw_im(int32_t imm,const void * addr)2146 void movw_im(int32_t imm, const void* addr) { 2147 spew("movw $%d, %p", imm, addr); 2148 m_formatter.prefix(PRE_OPERAND_SIZE); 2149 m_formatter.oneByteOp_disp32(OP_GROUP11_EvIz, addr, GROUP11_MOV); 2150 m_formatter.immediate16(imm); 2151 } 2152 movl_i32m(int32_t imm,int32_t offset,RegisterID base)2153 void movl_i32m(int32_t imm, int32_t offset, RegisterID base) { 2154 spew("movl $0x%x, " MEM_ob, imm, ADDR_ob(offset, base)); 2155 m_formatter.oneByteOp(OP_GROUP11_EvIz, offset, base, GROUP11_MOV); 2156 m_formatter.immediate32(imm); 2157 } 2158 movw_im(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)2159 void movw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 2160 int scale) { 2161 spew("movw $0x%x, " MEM_obs, imm, 2162 ADDR_obs(offset, base, index, scale)); 2163 m_formatter.prefix(PRE_OPERAND_SIZE); 2164 m_formatter.oneByteOp(OP_GROUP11_EvIz, offset, base, index, scale, 2165 GROUP11_MOV); 2166 m_formatter.immediate16(imm); 2167 } 2168 movl_i32m(int32_t imm,int32_t offset,RegisterID base,RegisterID index,int scale)2169 void movl_i32m(int32_t imm, int32_t offset, RegisterID base, RegisterID index, 2170 int scale) { 2171 spew("movl $0x%x, " MEM_obs, imm, 2172 ADDR_obs(offset, base, index, scale)); 2173 m_formatter.oneByteOp(OP_GROUP11_EvIz, offset, base, index, scale, 2174 GROUP11_MOV); 2175 m_formatter.immediate32(imm); 2176 } 2177 movl_EAXm(const void * addr)2178 void movl_EAXm(const void* addr) { 2179 #ifdef JS_CODEGEN_X64 2180 if (IsAddressImmediate(addr)) { 2181 movl_rm(rax, addr); 2182 return; 2183 } 2184 #endif 2185 2186 spew("movl %%eax, %p", addr); 2187 m_formatter.oneByteOp(OP_MOV_OvEAX); 2188 #ifdef JS_CODEGEN_X64 2189 m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); 2190 #else 2191 m_formatter.immediate32(reinterpret_cast<int32_t>(addr)); 2192 #endif 2193 } 2194 vmovq_rm(XMMRegisterID src,int32_t offset,RegisterID base)2195 void vmovq_rm(XMMRegisterID src, int32_t offset, RegisterID base) { 2196 // vmovq_rm can be encoded either as a true vmovq or as a vmovd with a 2197 // REX prefix modifying it to be 64-bit. We choose the vmovq encoding 2198 // because it's smaller (when it doesn't need a REX prefix for other 2199 // reasons) and because it works on 32-bit x86 too. 2200 twoByteOpSimd("vmovq", VEX_PD, OP2_MOVQ_WdVd, offset, base, invalid_xmm, 2201 src); 2202 } 2203 vmovq_rm_disp32(XMMRegisterID src,int32_t offset,RegisterID base)2204 void vmovq_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base) { 2205 twoByteOpSimd_disp32("vmovq", VEX_PD, OP2_MOVQ_WdVd, offset, base, 2206 invalid_xmm, src); 2207 } 2208 vmovq_rm(XMMRegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)2209 void vmovq_rm(XMMRegisterID src, int32_t offset, RegisterID base, 2210 RegisterID index, int scale) { 2211 twoByteOpSimd("vmovq", VEX_PD, OP2_MOVQ_WdVd, offset, base, index, scale, 2212 invalid_xmm, src); 2213 } 2214 vmovq_rm(XMMRegisterID src,const void * addr)2215 void vmovq_rm(XMMRegisterID src, const void* addr) { 2216 twoByteOpSimd("vmovq", VEX_PD, OP2_MOVQ_WdVd, addr, invalid_xmm, src); 2217 } 2218 vmovq_mr(int32_t offset,RegisterID base,XMMRegisterID dst)2219 void vmovq_mr(int32_t offset, RegisterID base, XMMRegisterID dst) { 2220 // vmovq_mr can be encoded either as a true vmovq or as a vmovd with a 2221 // REX prefix modifying it to be 64-bit. We choose the vmovq encoding 2222 // because it's smaller (when it doesn't need a REX prefix for other 2223 // reasons) and because it works on 32-bit x86 too. 2224 twoByteOpSimd("vmovq", VEX_SS, OP2_MOVQ_VdWd, offset, base, invalid_xmm, 2225 dst); 2226 } 2227 vmovq_mr_disp32(int32_t offset,RegisterID base,XMMRegisterID dst)2228 void vmovq_mr_disp32(int32_t offset, RegisterID base, XMMRegisterID dst) { 2229 twoByteOpSimd_disp32("vmovq", VEX_SS, OP2_MOVQ_VdWd, offset, base, 2230 invalid_xmm, dst); 2231 } 2232 vmovq_mr(int32_t offset,RegisterID base,RegisterID index,int32_t scale,XMMRegisterID dst)2233 void vmovq_mr(int32_t offset, RegisterID base, RegisterID index, 2234 int32_t scale, XMMRegisterID dst) { 2235 twoByteOpSimd("vmovq", VEX_SS, OP2_MOVQ_VdWd, offset, base, index, scale, 2236 invalid_xmm, dst); 2237 } 2238 vmovq_mr(const void * addr,XMMRegisterID dst)2239 void vmovq_mr(const void* addr, XMMRegisterID dst) { 2240 twoByteOpSimd("vmovq", VEX_SS, OP2_MOVQ_VdWd, addr, invalid_xmm, dst); 2241 } 2242 movl_rm(RegisterID src,const void * addr)2243 void movl_rm(RegisterID src, const void* addr) { 2244 if (src == rax 2245 #ifdef JS_CODEGEN_X64 2246 && !IsAddressImmediate(addr) 2247 #endif 2248 ) { 2249 movl_EAXm(addr); 2250 return; 2251 } 2252 2253 spew("movl %s, %p", GPReg32Name(src), addr); 2254 m_formatter.oneByteOp(OP_MOV_EvGv, addr, src); 2255 } 2256 movl_i32m(int32_t imm,const void * addr)2257 void movl_i32m(int32_t imm, const void* addr) { 2258 spew("movl $%d, %p", imm, addr); 2259 m_formatter.oneByteOp(OP_GROUP11_EvIz, addr, GROUP11_MOV); 2260 m_formatter.immediate32(imm); 2261 } 2262 movb_rm(RegisterID src,int32_t offset,RegisterID base)2263 void movb_rm(RegisterID src, int32_t offset, RegisterID base) { 2264 spew("movb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base)); 2265 m_formatter.oneByteOp8(OP_MOV_EbGv, offset, base, src); 2266 } 2267 movb_rm_disp32(RegisterID src,int32_t offset,RegisterID base)2268 void movb_rm_disp32(RegisterID src, int32_t offset, RegisterID base) { 2269 spew("movb %s, " MEM_o32b, GPReg8Name(src), ADDR_o32b(offset, base)); 2270 m_formatter.oneByteOp8_disp32(OP_MOV_EbGv, offset, base, src); 2271 } 2272 movb_rm(RegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)2273 void movb_rm(RegisterID src, int32_t offset, RegisterID base, 2274 RegisterID index, int scale) { 2275 spew("movb %s, " MEM_obs, GPReg8Name(src), 2276 ADDR_obs(offset, base, index, scale)); 2277 m_formatter.oneByteOp8(OP_MOV_EbGv, offset, base, index, scale, src); 2278 } 2279 movb_rm(RegisterID src,const void * addr)2280 void movb_rm(RegisterID src, const void* addr) { 2281 spew("movb %s, %p", GPReg8Name(src), addr); 2282 m_formatter.oneByteOp8(OP_MOV_EbGv, addr, src); 2283 } 2284 movb_mr(int32_t offset,RegisterID base,RegisterID dst)2285 void movb_mr(int32_t offset, RegisterID base, RegisterID dst) { 2286 spew("movb " MEM_ob ", %s", ADDR_ob(offset, base), GPReg8Name(dst)); 2287 m_formatter.oneByteOp(OP_MOV_GvEb, offset, base, dst); 2288 } 2289 movb_mr(int32_t offset,RegisterID base,RegisterID index,int scale,RegisterID dst)2290 void movb_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 2291 RegisterID dst) { 2292 spew("movb " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), 2293 GPReg8Name(dst)); 2294 m_formatter.oneByteOp(OP_MOV_GvEb, offset, base, index, scale, dst); 2295 } 2296 movzbl_mr(int32_t offset,RegisterID base,RegisterID dst)2297 void movzbl_mr(int32_t offset, RegisterID base, RegisterID dst) { 2298 spew("movzbl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst)); 2299 m_formatter.twoByteOp(OP2_MOVZX_GvEb, offset, base, dst); 2300 } 2301 movzbl_mr_disp32(int32_t offset,RegisterID base,RegisterID dst)2302 void movzbl_mr_disp32(int32_t offset, RegisterID base, RegisterID dst) { 2303 spew("movzbl " MEM_o32b ", %s", ADDR_o32b(offset, base), 2304 GPReg32Name(dst)); 2305 m_formatter.twoByteOp_disp32(OP2_MOVZX_GvEb, offset, base, dst); 2306 } 2307 movzbl_mr(int32_t offset,RegisterID base,RegisterID index,int scale,RegisterID dst)2308 void movzbl_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 2309 RegisterID dst) { 2310 spew("movzbl " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), 2311 GPReg32Name(dst)); 2312 m_formatter.twoByteOp(OP2_MOVZX_GvEb, offset, base, index, scale, dst); 2313 } 2314 movzbl_mr(const void * addr,RegisterID dst)2315 void movzbl_mr(const void* addr, RegisterID dst) { 2316 spew("movzbl %p, %s", addr, GPReg32Name(dst)); 2317 m_formatter.twoByteOp(OP2_MOVZX_GvEb, addr, dst); 2318 } 2319 movsbl_rr(RegisterID src,RegisterID dst)2320 void movsbl_rr(RegisterID src, RegisterID dst) { 2321 spew("movsbl %s, %s", GPReg8Name(src), GPReg32Name(dst)); 2322 m_formatter.twoByteOp8_movx(OP2_MOVSX_GvEb, src, dst); 2323 } 2324 movsbl_mr(int32_t offset,RegisterID base,RegisterID dst)2325 void movsbl_mr(int32_t offset, RegisterID base, RegisterID dst) { 2326 spew("movsbl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst)); 2327 m_formatter.twoByteOp(OP2_MOVSX_GvEb, offset, base, dst); 2328 } 2329 movsbl_mr_disp32(int32_t offset,RegisterID base,RegisterID dst)2330 void movsbl_mr_disp32(int32_t offset, RegisterID base, RegisterID dst) { 2331 spew("movsbl " MEM_o32b ", %s", ADDR_o32b(offset, base), 2332 GPReg32Name(dst)); 2333 m_formatter.twoByteOp_disp32(OP2_MOVSX_GvEb, offset, base, dst); 2334 } 2335 movsbl_mr(int32_t offset,RegisterID base,RegisterID index,int scale,RegisterID dst)2336 void movsbl_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 2337 RegisterID dst) { 2338 spew("movsbl " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), 2339 GPReg32Name(dst)); 2340 m_formatter.twoByteOp(OP2_MOVSX_GvEb, offset, base, index, scale, dst); 2341 } 2342 movsbl_mr(const void * addr,RegisterID dst)2343 void movsbl_mr(const void* addr, RegisterID dst) { 2344 spew("movsbl %p, %s", addr, GPReg32Name(dst)); 2345 m_formatter.twoByteOp(OP2_MOVSX_GvEb, addr, dst); 2346 } 2347 movzwl_rr(RegisterID src,RegisterID dst)2348 void movzwl_rr(RegisterID src, RegisterID dst) { 2349 spew("movzwl %s, %s", GPReg16Name(src), GPReg32Name(dst)); 2350 m_formatter.twoByteOp(OP2_MOVZX_GvEw, src, dst); 2351 } 2352 movzwl_mr(int32_t offset,RegisterID base,RegisterID dst)2353 void movzwl_mr(int32_t offset, RegisterID base, RegisterID dst) { 2354 spew("movzwl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst)); 2355 m_formatter.twoByteOp(OP2_MOVZX_GvEw, offset, base, dst); 2356 } 2357 movzwl_mr_disp32(int32_t offset,RegisterID base,RegisterID dst)2358 void movzwl_mr_disp32(int32_t offset, RegisterID base, RegisterID dst) { 2359 spew("movzwl " MEM_o32b ", %s", ADDR_o32b(offset, base), 2360 GPReg32Name(dst)); 2361 m_formatter.twoByteOp_disp32(OP2_MOVZX_GvEw, offset, base, dst); 2362 } 2363 movzwl_mr(int32_t offset,RegisterID base,RegisterID index,int scale,RegisterID dst)2364 void movzwl_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 2365 RegisterID dst) { 2366 spew("movzwl " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), 2367 GPReg32Name(dst)); 2368 m_formatter.twoByteOp(OP2_MOVZX_GvEw, offset, base, index, scale, dst); 2369 } 2370 movzwl_mr(const void * addr,RegisterID dst)2371 void movzwl_mr(const void* addr, RegisterID dst) { 2372 spew("movzwl %p, %s", addr, GPReg32Name(dst)); 2373 m_formatter.twoByteOp(OP2_MOVZX_GvEw, addr, dst); 2374 } 2375 movswl_rr(RegisterID src,RegisterID dst)2376 void movswl_rr(RegisterID src, RegisterID dst) { 2377 spew("movswl %s, %s", GPReg16Name(src), GPReg32Name(dst)); 2378 m_formatter.twoByteOp(OP2_MOVSX_GvEw, src, dst); 2379 } 2380 movswl_mr(int32_t offset,RegisterID base,RegisterID dst)2381 void movswl_mr(int32_t offset, RegisterID base, RegisterID dst) { 2382 spew("movswl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst)); 2383 m_formatter.twoByteOp(OP2_MOVSX_GvEw, offset, base, dst); 2384 } 2385 movswl_mr_disp32(int32_t offset,RegisterID base,RegisterID dst)2386 void movswl_mr_disp32(int32_t offset, RegisterID base, RegisterID dst) { 2387 spew("movswl " MEM_o32b ", %s", ADDR_o32b(offset, base), 2388 GPReg32Name(dst)); 2389 m_formatter.twoByteOp_disp32(OP2_MOVSX_GvEw, offset, base, dst); 2390 } 2391 movswl_mr(int32_t offset,RegisterID base,RegisterID index,int scale,RegisterID dst)2392 void movswl_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 2393 RegisterID dst) { 2394 spew("movswl " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), 2395 GPReg32Name(dst)); 2396 m_formatter.twoByteOp(OP2_MOVSX_GvEw, offset, base, index, scale, dst); 2397 } 2398 movswl_mr(const void * addr,RegisterID dst)2399 void movswl_mr(const void* addr, RegisterID dst) { 2400 spew("movswl %p, %s", addr, GPReg32Name(dst)); 2401 m_formatter.twoByteOp(OP2_MOVSX_GvEw, addr, dst); 2402 } 2403 movzbl_rr(RegisterID src,RegisterID dst)2404 void movzbl_rr(RegisterID src, RegisterID dst) { 2405 spew("movzbl %s, %s", GPReg8Name(src), GPReg32Name(dst)); 2406 m_formatter.twoByteOp8_movx(OP2_MOVZX_GvEb, src, dst); 2407 } 2408 leal_mr(int32_t offset,RegisterID base,RegisterID index,int scale,RegisterID dst)2409 void leal_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 2410 RegisterID dst) { 2411 spew("leal " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), 2412 GPReg32Name(dst)); 2413 m_formatter.oneByteOp(OP_LEA, offset, base, index, scale, dst); 2414 } 2415 leal_mr(int32_t offset,RegisterID base,RegisterID dst)2416 void leal_mr(int32_t offset, RegisterID base, RegisterID dst) { 2417 spew("leal " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst)); 2418 m_formatter.oneByteOp(OP_LEA, offset, base, dst); 2419 } 2420 2421 // Flow control: 2422 call()2423 MOZ_MUST_USE JmpSrc call() { 2424 m_formatter.oneByteOp(OP_CALL_rel32); 2425 JmpSrc r = m_formatter.immediateRel32(); 2426 spew("call .Lfrom%d", r.offset()); 2427 return r; 2428 } 2429 call_r(RegisterID dst)2430 void call_r(RegisterID dst) { 2431 m_formatter.oneByteOp(OP_GROUP5_Ev, dst, GROUP5_OP_CALLN); 2432 spew("call *%s", GPRegName(dst)); 2433 } 2434 call_m(int32_t offset,RegisterID base)2435 void call_m(int32_t offset, RegisterID base) { 2436 spew("call *" MEM_ob, ADDR_ob(offset, base)); 2437 m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, GROUP5_OP_CALLN); 2438 } 2439 2440 // Comparison of EAX against a 32-bit immediate. The immediate is patched 2441 // in as if it were a jump target. The intention is to toggle the first 2442 // byte of the instruction between a CMP and a JMP to produce a pseudo-NOP. cmp_eax()2443 MOZ_MUST_USE JmpSrc cmp_eax() { 2444 m_formatter.oneByteOp(OP_CMP_EAXIv); 2445 JmpSrc r = m_formatter.immediateRel32(); 2446 spew("cmpl %%eax, .Lfrom%d", r.offset()); 2447 return r; 2448 } 2449 jmp_i(JmpDst dst)2450 void jmp_i(JmpDst dst) { 2451 int32_t diff = dst.offset() - m_formatter.size(); 2452 spew("jmp .Llabel%d", dst.offset()); 2453 2454 // The jump immediate is an offset from the end of the jump instruction. 2455 // A jump instruction is either 1 byte opcode and 1 byte offset, or 1 2456 // byte opcode and 4 bytes offset. 2457 if (CAN_SIGN_EXTEND_8_32(diff - 2)) { 2458 m_formatter.oneByteOp(OP_JMP_rel8); 2459 m_formatter.immediate8s(diff - 2); 2460 } else { 2461 m_formatter.oneByteOp(OP_JMP_rel32); 2462 m_formatter.immediate32(diff - 5); 2463 } 2464 } jmp()2465 MOZ_MUST_USE JmpSrc jmp() { 2466 m_formatter.oneByteOp(OP_JMP_rel32); 2467 JmpSrc r = m_formatter.immediateRel32(); 2468 spew("jmp .Lfrom%d", r.offset()); 2469 return r; 2470 } 2471 jmp_r(RegisterID dst)2472 void jmp_r(RegisterID dst) { 2473 spew("jmp *%s", GPRegName(dst)); 2474 m_formatter.oneByteOp(OP_GROUP5_Ev, dst, GROUP5_OP_JMPN); 2475 } 2476 jmp_m(int32_t offset,RegisterID base)2477 void jmp_m(int32_t offset, RegisterID base) { 2478 spew("jmp *" MEM_ob, ADDR_ob(offset, base)); 2479 m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, GROUP5_OP_JMPN); 2480 } 2481 jmp_m(int32_t offset,RegisterID base,RegisterID index,int scale)2482 void jmp_m(int32_t offset, RegisterID base, RegisterID index, int scale) { 2483 spew("jmp *" MEM_obs, ADDR_obs(offset, base, index, scale)); 2484 m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, index, scale, 2485 GROUP5_OP_JMPN); 2486 } 2487 jCC_i(Condition cond,JmpDst dst)2488 void jCC_i(Condition cond, JmpDst dst) { 2489 int32_t diff = dst.offset() - m_formatter.size(); 2490 spew("j%s .Llabel%d", CCName(cond), dst.offset()); 2491 2492 // The jump immediate is an offset from the end of the jump instruction. 2493 // A conditional jump instruction is either 1 byte opcode and 1 byte 2494 // offset, or 2 bytes opcode and 4 bytes offset. 2495 if (CAN_SIGN_EXTEND_8_32(diff - 2)) { 2496 m_formatter.oneByteOp(jccRel8(cond)); 2497 m_formatter.immediate8s(diff - 2); 2498 } else { 2499 m_formatter.twoByteOp(jccRel32(cond)); 2500 m_formatter.immediate32(diff - 6); 2501 } 2502 } 2503 jCC(Condition cond)2504 MOZ_MUST_USE JmpSrc jCC(Condition cond) { 2505 m_formatter.twoByteOp(jccRel32(cond)); 2506 JmpSrc r = m_formatter.immediateRel32(); 2507 spew("j%s .Lfrom%d", CCName(cond), r.offset()); 2508 return r; 2509 } 2510 2511 // SSE operations: 2512 vpcmpeqb_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2513 void vpcmpeqb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2514 twoByteOpSimd("vpcmpeqb", VEX_PD, OP2_PCMPEQB_VdqWdq, src1, src0, dst); 2515 } vpcmpeqb_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2516 void vpcmpeqb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2517 XMMRegisterID dst) { 2518 twoByteOpSimd("vpcmpeqb", VEX_PD, OP2_PCMPEQB_VdqWdq, offset, base, src0, 2519 dst); 2520 } vpcmpeqb_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)2521 void vpcmpeqb_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 2522 twoByteOpSimd("vpcmpeqb", VEX_PD, OP2_PCMPEQB_VdqWdq, address, src0, dst); 2523 } 2524 vpcmpgtb_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2525 void vpcmpgtb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2526 twoByteOpSimd("vpcmpgtb", VEX_PD, OP2_PCMPGTB_VdqWdq, src1, src0, dst); 2527 } vpcmpgtb_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2528 void vpcmpgtb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2529 XMMRegisterID dst) { 2530 twoByteOpSimd("vpcmpgtb", VEX_PD, OP2_PCMPGTB_VdqWdq, offset, base, src0, 2531 dst); 2532 } vpcmpgtb_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)2533 void vpcmpgtb_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 2534 twoByteOpSimd("vpcmpgtb", VEX_PD, OP2_PCMPGTB_VdqWdq, address, src0, dst); 2535 } 2536 vpcmpeqw_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2537 void vpcmpeqw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2538 twoByteOpSimd("vpcmpeqw", VEX_PD, OP2_PCMPEQW_VdqWdq, src1, src0, dst); 2539 } vpcmpeqw_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2540 void vpcmpeqw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2541 XMMRegisterID dst) { 2542 twoByteOpSimd("vpcmpeqw", VEX_PD, OP2_PCMPEQW_VdqWdq, offset, base, src0, 2543 dst); 2544 } vpcmpeqw_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)2545 void vpcmpeqw_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 2546 twoByteOpSimd("vpcmpeqw", VEX_PD, OP2_PCMPEQW_VdqWdq, address, src0, dst); 2547 } 2548 vpcmpgtw_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2549 void vpcmpgtw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2550 twoByteOpSimd("vpcmpgtw", VEX_PD, OP2_PCMPGTW_VdqWdq, src1, src0, dst); 2551 } vpcmpgtw_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2552 void vpcmpgtw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2553 XMMRegisterID dst) { 2554 twoByteOpSimd("vpcmpgtw", VEX_PD, OP2_PCMPGTW_VdqWdq, offset, base, src0, 2555 dst); 2556 } vpcmpgtw_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)2557 void vpcmpgtw_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 2558 twoByteOpSimd("vpcmpgtw", VEX_PD, OP2_PCMPGTW_VdqWdq, address, src0, dst); 2559 } 2560 vpcmpeqd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2561 void vpcmpeqd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2562 twoByteOpSimd("vpcmpeqd", VEX_PD, OP2_PCMPEQD_VdqWdq, src1, src0, dst); 2563 } vpcmpeqd_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2564 void vpcmpeqd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2565 XMMRegisterID dst) { 2566 twoByteOpSimd("vpcmpeqd", VEX_PD, OP2_PCMPEQD_VdqWdq, offset, base, src0, 2567 dst); 2568 } vpcmpeqd_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)2569 void vpcmpeqd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 2570 twoByteOpSimd("vpcmpeqd", VEX_PD, OP2_PCMPEQD_VdqWdq, address, src0, dst); 2571 } 2572 vpcmpgtd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2573 void vpcmpgtd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2574 twoByteOpSimd("vpcmpgtd", VEX_PD, OP2_PCMPGTD_VdqWdq, src1, src0, dst); 2575 } vpcmpgtd_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2576 void vpcmpgtd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2577 XMMRegisterID dst) { 2578 twoByteOpSimd("vpcmpgtd", VEX_PD, OP2_PCMPGTD_VdqWdq, offset, base, src0, 2579 dst); 2580 } vpcmpgtd_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)2581 void vpcmpgtd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 2582 twoByteOpSimd("vpcmpgtd", VEX_PD, OP2_PCMPGTD_VdqWdq, address, src0, dst); 2583 } 2584 vcmpps_rr(uint8_t order,XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2585 void vcmpps_rr(uint8_t order, XMMRegisterID src1, XMMRegisterID src0, 2586 XMMRegisterID dst) { 2587 twoByteOpImmSimd("vcmpps", VEX_PS, OP2_CMPPS_VpsWps, order, src1, src0, 2588 dst); 2589 } vcmpps_mr(uint8_t order,int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2590 void vcmpps_mr(uint8_t order, int32_t offset, RegisterID base, 2591 XMMRegisterID src0, XMMRegisterID dst) { 2592 twoByteOpImmSimd("vcmpps", VEX_PS, OP2_CMPPS_VpsWps, order, offset, base, 2593 src0, dst); 2594 } vcmpps_mr(uint8_t order,const void * address,XMMRegisterID src0,XMMRegisterID dst)2595 void vcmpps_mr(uint8_t order, const void* address, XMMRegisterID src0, 2596 XMMRegisterID dst) { 2597 twoByteOpImmSimd("vcmpps", VEX_PS, OP2_CMPPS_VpsWps, order, address, src0, 2598 dst); 2599 } 2600 vrcpps_rr(XMMRegisterID src,XMMRegisterID dst)2601 void vrcpps_rr(XMMRegisterID src, XMMRegisterID dst) { 2602 twoByteOpSimd("vrcpps", VEX_PS, OP2_RCPPS_VpsWps, src, invalid_xmm, dst); 2603 } vrcpps_mr(int32_t offset,RegisterID base,XMMRegisterID dst)2604 void vrcpps_mr(int32_t offset, RegisterID base, XMMRegisterID dst) { 2605 twoByteOpSimd("vrcpps", VEX_PS, OP2_RCPPS_VpsWps, offset, base, invalid_xmm, 2606 dst); 2607 } vrcpps_mr(const void * address,XMMRegisterID dst)2608 void vrcpps_mr(const void* address, XMMRegisterID dst) { 2609 twoByteOpSimd("vrcpps", VEX_PS, OP2_RCPPS_VpsWps, address, invalid_xmm, 2610 dst); 2611 } 2612 vrsqrtps_rr(XMMRegisterID src,XMMRegisterID dst)2613 void vrsqrtps_rr(XMMRegisterID src, XMMRegisterID dst) { 2614 twoByteOpSimd("vrsqrtps", VEX_PS, OP2_RSQRTPS_VpsWps, src, invalid_xmm, 2615 dst); 2616 } vrsqrtps_mr(int32_t offset,RegisterID base,XMMRegisterID dst)2617 void vrsqrtps_mr(int32_t offset, RegisterID base, XMMRegisterID dst) { 2618 twoByteOpSimd("vrsqrtps", VEX_PS, OP2_RSQRTPS_VpsWps, offset, base, 2619 invalid_xmm, dst); 2620 } vrsqrtps_mr(const void * address,XMMRegisterID dst)2621 void vrsqrtps_mr(const void* address, XMMRegisterID dst) { 2622 twoByteOpSimd("vrsqrtps", VEX_PS, OP2_RSQRTPS_VpsWps, address, invalid_xmm, 2623 dst); 2624 } 2625 vsqrtps_rr(XMMRegisterID src,XMMRegisterID dst)2626 void vsqrtps_rr(XMMRegisterID src, XMMRegisterID dst) { 2627 twoByteOpSimd("vsqrtps", VEX_PS, OP2_SQRTPS_VpsWps, src, invalid_xmm, dst); 2628 } vsqrtps_mr(int32_t offset,RegisterID base,XMMRegisterID dst)2629 void vsqrtps_mr(int32_t offset, RegisterID base, XMMRegisterID dst) { 2630 twoByteOpSimd("vsqrtps", VEX_PS, OP2_SQRTPS_VpsWps, offset, base, 2631 invalid_xmm, dst); 2632 } vsqrtps_mr(const void * address,XMMRegisterID dst)2633 void vsqrtps_mr(const void* address, XMMRegisterID dst) { 2634 twoByteOpSimd("vsqrtps", VEX_PS, OP2_SQRTPS_VpsWps, address, invalid_xmm, 2635 dst); 2636 } 2637 vaddsd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2638 void vaddsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2639 twoByteOpSimd("vaddsd", VEX_SD, OP2_ADDSD_VsdWsd, src1, src0, dst); 2640 } 2641 vaddss_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2642 void vaddss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2643 twoByteOpSimd("vaddss", VEX_SS, OP2_ADDSD_VsdWsd, src1, src0, dst); 2644 } 2645 vaddsd_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2646 void vaddsd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2647 XMMRegisterID dst) { 2648 twoByteOpSimd("vaddsd", VEX_SD, OP2_ADDSD_VsdWsd, offset, base, src0, dst); 2649 } 2650 vaddss_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2651 void vaddss_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2652 XMMRegisterID dst) { 2653 twoByteOpSimd("vaddss", VEX_SS, OP2_ADDSD_VsdWsd, offset, base, src0, dst); 2654 } 2655 vaddsd_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)2656 void vaddsd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 2657 twoByteOpSimd("vaddsd", VEX_SD, OP2_ADDSD_VsdWsd, address, src0, dst); 2658 } vaddss_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)2659 void vaddss_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 2660 twoByteOpSimd("vaddss", VEX_SS, OP2_ADDSD_VsdWsd, address, src0, dst); 2661 } 2662 vcvtss2sd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2663 void vcvtss2sd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2664 twoByteOpSimd("vcvtss2sd", VEX_SS, OP2_CVTSS2SD_VsdEd, src1, src0, dst); 2665 } 2666 vcvtsd2ss_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2667 void vcvtsd2ss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2668 twoByteOpSimd("vcvtsd2ss", VEX_SD, OP2_CVTSD2SS_VsdEd, src1, src0, dst); 2669 } 2670 vcvtsi2ss_rr(RegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2671 void vcvtsi2ss_rr(RegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2672 twoByteOpInt32Simd("vcvtsi2ss", VEX_SS, OP2_CVTSI2SD_VsdEd, src1, src0, 2673 dst); 2674 } 2675 vcvtsi2sd_rr(RegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2676 void vcvtsi2sd_rr(RegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2677 twoByteOpInt32Simd("vcvtsi2sd", VEX_SD, OP2_CVTSI2SD_VsdEd, src1, src0, 2678 dst); 2679 } 2680 vcvttps2dq_rr(XMMRegisterID src,XMMRegisterID dst)2681 void vcvttps2dq_rr(XMMRegisterID src, XMMRegisterID dst) { 2682 twoByteOpSimd("vcvttps2dq", VEX_SS, OP2_CVTTPS2DQ_VdqWps, src, invalid_xmm, 2683 dst); 2684 } 2685 vcvtdq2ps_rr(XMMRegisterID src,XMMRegisterID dst)2686 void vcvtdq2ps_rr(XMMRegisterID src, XMMRegisterID dst) { 2687 twoByteOpSimd("vcvtdq2ps", VEX_PS, OP2_CVTDQ2PS_VpsWdq, src, invalid_xmm, 2688 dst); 2689 } 2690 vcvtsi2sd_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2691 void vcvtsi2sd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2692 XMMRegisterID dst) { 2693 twoByteOpSimd("vcvtsi2sd", VEX_SD, OP2_CVTSI2SD_VsdEd, offset, base, src0, 2694 dst); 2695 } 2696 vcvtsi2sd_mr(int32_t offset,RegisterID base,RegisterID index,int scale,XMMRegisterID src0,XMMRegisterID dst)2697 void vcvtsi2sd_mr(int32_t offset, RegisterID base, RegisterID index, 2698 int scale, XMMRegisterID src0, XMMRegisterID dst) { 2699 twoByteOpSimd("vcvtsi2sd", VEX_SD, OP2_CVTSI2SD_VsdEd, offset, base, index, 2700 scale, src0, dst); 2701 } 2702 vcvtsi2ss_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2703 void vcvtsi2ss_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2704 XMMRegisterID dst) { 2705 twoByteOpSimd("vcvtsi2ss", VEX_SS, OP2_CVTSI2SD_VsdEd, offset, base, src0, 2706 dst); 2707 } 2708 vcvtsi2ss_mr(int32_t offset,RegisterID base,RegisterID index,int scale,XMMRegisterID src0,XMMRegisterID dst)2709 void vcvtsi2ss_mr(int32_t offset, RegisterID base, RegisterID index, 2710 int scale, XMMRegisterID src0, XMMRegisterID dst) { 2711 twoByteOpSimd("vcvtsi2ss", VEX_SS, OP2_CVTSI2SD_VsdEd, offset, base, index, 2712 scale, src0, dst); 2713 } 2714 vcvttsd2si_rr(XMMRegisterID src,RegisterID dst)2715 void vcvttsd2si_rr(XMMRegisterID src, RegisterID dst) { 2716 twoByteOpSimdInt32("vcvttsd2si", VEX_SD, OP2_CVTTSD2SI_GdWsd, src, dst); 2717 } 2718 vcvttss2si_rr(XMMRegisterID src,RegisterID dst)2719 void vcvttss2si_rr(XMMRegisterID src, RegisterID dst) { 2720 twoByteOpSimdInt32("vcvttss2si", VEX_SS, OP2_CVTTSD2SI_GdWsd, src, dst); 2721 } 2722 vunpcklps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2723 void vunpcklps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2724 twoByteOpSimd("vunpcklps", VEX_PS, OP2_UNPCKLPS_VsdWsd, src1, src0, dst); 2725 } vunpcklps_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2726 void vunpcklps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2727 XMMRegisterID dst) { 2728 twoByteOpSimd("vunpcklps", VEX_PS, OP2_UNPCKLPS_VsdWsd, offset, base, src0, 2729 dst); 2730 } vunpcklps_mr(const void * addr,XMMRegisterID src0,XMMRegisterID dst)2731 void vunpcklps_mr(const void* addr, XMMRegisterID src0, XMMRegisterID dst) { 2732 twoByteOpSimd("vunpcklps", VEX_PS, OP2_UNPCKLPS_VsdWsd, addr, src0, dst); 2733 } 2734 vunpckhps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2735 void vunpckhps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2736 twoByteOpSimd("vunpckhps", VEX_PS, OP2_UNPCKHPS_VsdWsd, src1, src0, dst); 2737 } vunpckhps_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2738 void vunpckhps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2739 XMMRegisterID dst) { 2740 twoByteOpSimd("vunpckhps", VEX_PS, OP2_UNPCKHPS_VsdWsd, offset, base, src0, 2741 dst); 2742 } vunpckhps_mr(const void * addr,XMMRegisterID src0,XMMRegisterID dst)2743 void vunpckhps_mr(const void* addr, XMMRegisterID src0, XMMRegisterID dst) { 2744 twoByteOpSimd("vunpckhps", VEX_PS, OP2_UNPCKHPS_VsdWsd, addr, src0, dst); 2745 } 2746 vpand_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2747 void vpand_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2748 twoByteOpSimd("vpand", VEX_PD, OP2_PANDDQ_VdqWdq, src1, src0, dst); 2749 } vpand_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2750 void vpand_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2751 XMMRegisterID dst) { 2752 twoByteOpSimd("vpand", VEX_PD, OP2_PANDDQ_VdqWdq, offset, base, src0, dst); 2753 } vpand_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)2754 void vpand_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 2755 twoByteOpSimd("vpand", VEX_PD, OP2_PANDDQ_VdqWdq, address, src0, dst); 2756 } vpor_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2757 void vpor_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2758 twoByteOpSimd("vpor", VEX_PD, OP2_PORDQ_VdqWdq, src1, src0, dst); 2759 } vpor_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2760 void vpor_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2761 XMMRegisterID dst) { 2762 twoByteOpSimd("vpor", VEX_PD, OP2_PORDQ_VdqWdq, offset, base, src0, dst); 2763 } vpor_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)2764 void vpor_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 2765 twoByteOpSimd("vpor", VEX_PD, OP2_PORDQ_VdqWdq, address, src0, dst); 2766 } vpxor_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2767 void vpxor_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2768 twoByteOpSimd("vpxor", VEX_PD, OP2_PXORDQ_VdqWdq, src1, src0, dst); 2769 } vpxor_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2770 void vpxor_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2771 XMMRegisterID dst) { 2772 twoByteOpSimd("vpxor", VEX_PD, OP2_PXORDQ_VdqWdq, offset, base, src0, dst); 2773 } vpxor_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)2774 void vpxor_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 2775 twoByteOpSimd("vpxor", VEX_PD, OP2_PXORDQ_VdqWdq, address, src0, dst); 2776 } vpandn_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2777 void vpandn_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2778 twoByteOpSimd("vpandn", VEX_PD, OP2_PANDNDQ_VdqWdq, src1, src0, dst); 2779 } vpandn_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2780 void vpandn_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 2781 XMMRegisterID dst) { 2782 twoByteOpSimd("vpandn", VEX_PD, OP2_PANDNDQ_VdqWdq, offset, base, src0, 2783 dst); 2784 } vpandn_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)2785 void vpandn_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 2786 twoByteOpSimd("vpandn", VEX_PD, OP2_PANDNDQ_VdqWdq, address, src0, dst); 2787 } 2788 vpshufd_irr(uint32_t mask,XMMRegisterID src,XMMRegisterID dst)2789 void vpshufd_irr(uint32_t mask, XMMRegisterID src, XMMRegisterID dst) { 2790 twoByteOpImmSimd("vpshufd", VEX_PD, OP2_PSHUFD_VdqWdqIb, mask, src, 2791 invalid_xmm, dst); 2792 } vpshufd_imr(uint32_t mask,int32_t offset,RegisterID base,XMMRegisterID dst)2793 void vpshufd_imr(uint32_t mask, int32_t offset, RegisterID base, 2794 XMMRegisterID dst) { 2795 twoByteOpImmSimd("vpshufd", VEX_PD, OP2_PSHUFD_VdqWdqIb, mask, offset, base, 2796 invalid_xmm, dst); 2797 } vpshufd_imr(uint32_t mask,const void * address,XMMRegisterID dst)2798 void vpshufd_imr(uint32_t mask, const void* address, XMMRegisterID dst) { 2799 twoByteOpImmSimd("vpshufd", VEX_PD, OP2_PSHUFD_VdqWdqIb, mask, address, 2800 invalid_xmm, dst); 2801 } 2802 vpshuflw_irr(uint32_t mask,XMMRegisterID src,XMMRegisterID dst)2803 void vpshuflw_irr(uint32_t mask, XMMRegisterID src, XMMRegisterID dst) { 2804 twoByteOpImmSimd("vpshuflw", VEX_SD, OP2_PSHUFLW_VdqWdqIb, mask, src, 2805 invalid_xmm, dst); 2806 } 2807 vpshufhw_irr(uint32_t mask,XMMRegisterID src,XMMRegisterID dst)2808 void vpshufhw_irr(uint32_t mask, XMMRegisterID src, XMMRegisterID dst) { 2809 twoByteOpImmSimd("vpshufhw", VEX_SS, OP2_PSHUFHW_VdqWdqIb, mask, src, 2810 invalid_xmm, dst); 2811 } 2812 vpshufb_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2813 void vpshufb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2814 threeByteOpSimd("vpshufb", VEX_PD, OP3_PSHUFB_VdqWdq, ESCAPE_38, src1, src0, 2815 dst); 2816 } 2817 vshufps_irr(uint32_t mask,XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2818 void vshufps_irr(uint32_t mask, XMMRegisterID src1, XMMRegisterID src0, 2819 XMMRegisterID dst) { 2820 twoByteOpImmSimd("vshufps", VEX_PS, OP2_SHUFPS_VpsWpsIb, mask, src1, src0, 2821 dst); 2822 } vshufps_imr(uint32_t mask,int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)2823 void vshufps_imr(uint32_t mask, int32_t offset, RegisterID base, 2824 XMMRegisterID src0, XMMRegisterID dst) { 2825 twoByteOpImmSimd("vshufps", VEX_PS, OP2_SHUFPS_VpsWpsIb, mask, offset, base, 2826 src0, dst); 2827 } vshufps_imr(uint32_t mask,const void * address,XMMRegisterID src0,XMMRegisterID dst)2828 void vshufps_imr(uint32_t mask, const void* address, XMMRegisterID src0, 2829 XMMRegisterID dst) { 2830 twoByteOpImmSimd("vshufps", VEX_PS, OP2_SHUFPS_VpsWpsIb, mask, address, 2831 src0, dst); 2832 } 2833 vmovddup_rr(XMMRegisterID src,XMMRegisterID dst)2834 void vmovddup_rr(XMMRegisterID src, XMMRegisterID dst) { 2835 twoByteOpSimd("vmovddup", VEX_SD, OP2_MOVDDUP_VqWq, src, invalid_xmm, dst); 2836 } 2837 vmovhlps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2838 void vmovhlps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2839 twoByteOpSimd("vmovhlps", VEX_PS, OP2_MOVHLPS_VqUq, src1, src0, dst); 2840 } 2841 vmovlhps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2842 void vmovlhps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2843 twoByteOpSimd("vmovlhps", VEX_PS, OP2_MOVLHPS_VqUq, src1, src0, dst); 2844 } 2845 vpsrldq_ir(uint32_t count,XMMRegisterID src,XMMRegisterID dst)2846 void vpsrldq_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst) { 2847 MOZ_ASSERT(count < 16); 2848 shiftOpImmSimd("vpsrldq", OP2_PSRLDQ_Vd, ShiftID::vpsrldq, count, src, dst); 2849 } 2850 vpsllq_ir(uint32_t count,XMMRegisterID src,XMMRegisterID dst)2851 void vpsllq_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst) { 2852 MOZ_ASSERT(count < 64); 2853 shiftOpImmSimd("vpsllq", OP2_PSRLDQ_Vd, ShiftID::vpsllx, count, src, dst); 2854 } 2855 vpsrlq_ir(uint32_t count,XMMRegisterID src,XMMRegisterID dst)2856 void vpsrlq_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst) { 2857 MOZ_ASSERT(count < 64); 2858 shiftOpImmSimd("vpsrlq", OP2_PSRLDQ_Vd, ShiftID::vpsrlx, count, src, dst); 2859 } 2860 vpslld_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2861 void vpslld_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2862 twoByteOpSimd("vpslld", VEX_PD, OP2_PSLLD_VdqWdq, src1, src0, dst); 2863 } 2864 vpslld_ir(uint32_t count,XMMRegisterID src,XMMRegisterID dst)2865 void vpslld_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst) { 2866 MOZ_ASSERT(count < 32); 2867 shiftOpImmSimd("vpslld", OP2_PSLLD_UdqIb, ShiftID::vpsllx, count, src, dst); 2868 } 2869 vpsrad_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2870 void vpsrad_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2871 twoByteOpSimd("vpsrad", VEX_PD, OP2_PSRAD_VdqWdq, src1, src0, dst); 2872 } 2873 vpsrad_ir(int32_t count,XMMRegisterID src,XMMRegisterID dst)2874 void vpsrad_ir(int32_t count, XMMRegisterID src, XMMRegisterID dst) { 2875 MOZ_ASSERT(count < 32); 2876 shiftOpImmSimd("vpsrad", OP2_PSRAD_UdqIb, ShiftID::vpsrad, count, src, dst); 2877 } 2878 vpsrld_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2879 void vpsrld_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2880 twoByteOpSimd("vpsrld", VEX_PD, OP2_PSRLD_VdqWdq, src1, src0, dst); 2881 } 2882 vpsrld_ir(uint32_t count,XMMRegisterID src,XMMRegisterID dst)2883 void vpsrld_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst) { 2884 MOZ_ASSERT(count < 32); 2885 shiftOpImmSimd("vpsrld", OP2_PSRLD_UdqIb, ShiftID::vpsrlx, count, src, dst); 2886 } 2887 vpsllw_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2888 void vpsllw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2889 twoByteOpSimd("vpsllw", VEX_PD, OP2_PSLLW_VdqWdq, src1, src0, dst); 2890 } 2891 vpsllw_ir(uint32_t count,XMMRegisterID src,XMMRegisterID dst)2892 void vpsllw_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst) { 2893 MOZ_ASSERT(count < 16); 2894 shiftOpImmSimd("vpsllw", OP2_PSLLW_UdqIb, ShiftID::vpsllx, count, src, dst); 2895 } 2896 vpsraw_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2897 void vpsraw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2898 twoByteOpSimd("vpsraw", VEX_PD, OP2_PSRAW_VdqWdq, src1, src0, dst); 2899 } 2900 vpsraw_ir(int32_t count,XMMRegisterID src,XMMRegisterID dst)2901 void vpsraw_ir(int32_t count, XMMRegisterID src, XMMRegisterID dst) { 2902 MOZ_ASSERT(count < 16); 2903 shiftOpImmSimd("vpsraw", OP2_PSRAW_UdqIb, ShiftID::vpsrad, count, src, dst); 2904 } 2905 vpsrlw_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)2906 void vpsrlw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 2907 twoByteOpSimd("vpsrlw", VEX_PD, OP2_PSRLW_VdqWdq, src1, src0, dst); 2908 } 2909 vpsrlw_ir(uint32_t count,XMMRegisterID src,XMMRegisterID dst)2910 void vpsrlw_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst) { 2911 MOZ_ASSERT(count < 16); 2912 shiftOpImmSimd("vpsrlw", OP2_PSRLW_UdqIb, ShiftID::vpsrlx, count, src, dst); 2913 } 2914 vmovmskpd_rr(XMMRegisterID src,RegisterID dst)2915 void vmovmskpd_rr(XMMRegisterID src, RegisterID dst) { 2916 twoByteOpSimdInt32("vmovmskpd", VEX_PD, OP2_MOVMSKPD_EdVd, src, dst); 2917 } 2918 vmovmskps_rr(XMMRegisterID src,RegisterID dst)2919 void vmovmskps_rr(XMMRegisterID src, RegisterID dst) { 2920 twoByteOpSimdInt32("vmovmskps", VEX_PS, OP2_MOVMSKPD_EdVd, src, dst); 2921 } 2922 vpmovmskb_rr(XMMRegisterID src,RegisterID dst)2923 void vpmovmskb_rr(XMMRegisterID src, RegisterID dst) { 2924 twoByteOpSimdInt32("vpmovmskb", VEX_PD, OP2_PMOVMSKB_EdVd, src, dst); 2925 } 2926 vptest_rr(XMMRegisterID rhs,XMMRegisterID lhs)2927 void vptest_rr(XMMRegisterID rhs, XMMRegisterID lhs) { 2928 threeByteOpSimd("vptest", VEX_PD, OP3_PTEST_VdVd, ESCAPE_38, rhs, 2929 invalid_xmm, lhs); 2930 } 2931 vmovd_rr(XMMRegisterID src,RegisterID dst)2932 void vmovd_rr(XMMRegisterID src, RegisterID dst) { 2933 twoByteOpSimdInt32("vmovd", VEX_PD, OP2_MOVD_EdVd, (XMMRegisterID)dst, 2934 (RegisterID)src); 2935 } 2936 vmovd_rr(RegisterID src,XMMRegisterID dst)2937 void vmovd_rr(RegisterID src, XMMRegisterID dst) { 2938 twoByteOpInt32Simd("vmovd", VEX_PD, OP2_MOVD_VdEd, src, invalid_xmm, dst); 2939 } 2940 vmovd_mr(int32_t offset,RegisterID base,XMMRegisterID dst)2941 void vmovd_mr(int32_t offset, RegisterID base, XMMRegisterID dst) { 2942 twoByteOpSimd("vmovd", VEX_PD, OP2_MOVD_VdEd, offset, base, invalid_xmm, 2943 dst); 2944 } 2945 vmovd_mr(int32_t offset,RegisterID base,RegisterID index,int32_t scale,XMMRegisterID dst)2946 void vmovd_mr(int32_t offset, RegisterID base, RegisterID index, 2947 int32_t scale, XMMRegisterID dst) { 2948 twoByteOpSimd("vmovd", VEX_PD, OP2_MOVD_VdEd, offset, base, index, scale, 2949 invalid_xmm, dst); 2950 } 2951 vmovd_mr_disp32(int32_t offset,RegisterID base,XMMRegisterID dst)2952 void vmovd_mr_disp32(int32_t offset, RegisterID base, XMMRegisterID dst) { 2953 twoByteOpSimd_disp32("vmovd", VEX_PD, OP2_MOVD_VdEd, offset, base, 2954 invalid_xmm, dst); 2955 } 2956 vmovd_mr(const void * address,XMMRegisterID dst)2957 void vmovd_mr(const void* address, XMMRegisterID dst) { 2958 twoByteOpSimd("vmovd", VEX_PD, OP2_MOVD_VdEd, address, invalid_xmm, dst); 2959 } 2960 vmovd_rm(XMMRegisterID src,int32_t offset,RegisterID base)2961 void vmovd_rm(XMMRegisterID src, int32_t offset, RegisterID base) { 2962 twoByteOpSimd("vmovd", VEX_PD, OP2_MOVD_EdVd, offset, base, invalid_xmm, 2963 src); 2964 } 2965 vmovd_rm(XMMRegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)2966 void vmovd_rm(XMMRegisterID src, int32_t offset, RegisterID base, 2967 RegisterID index, int scale) { 2968 twoByteOpSimd("vmovd", VEX_PD, OP2_MOVD_EdVd, offset, base, index, scale, 2969 invalid_xmm, src); 2970 } 2971 vmovd_rm_disp32(XMMRegisterID src,int32_t offset,RegisterID base)2972 void vmovd_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base) { 2973 twoByteOpSimd_disp32("vmovd", VEX_PD, OP2_MOVD_EdVd, offset, base, 2974 invalid_xmm, src); 2975 } 2976 vmovd_rm(XMMRegisterID src,const void * address)2977 void vmovd_rm(XMMRegisterID src, const void* address) { 2978 twoByteOpSimd("vmovd", VEX_PD, OP2_MOVD_EdVd, address, invalid_xmm, src); 2979 } 2980 vmovsd_rm(XMMRegisterID src,int32_t offset,RegisterID base)2981 void vmovsd_rm(XMMRegisterID src, int32_t offset, RegisterID base) { 2982 twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_WsdVsd, offset, base, invalid_xmm, 2983 src); 2984 } 2985 vmovsd_rm_disp32(XMMRegisterID src,int32_t offset,RegisterID base)2986 void vmovsd_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base) { 2987 twoByteOpSimd_disp32("vmovsd", VEX_SD, OP2_MOVSD_WsdVsd, offset, base, 2988 invalid_xmm, src); 2989 } 2990 vmovss_rm(XMMRegisterID src,int32_t offset,RegisterID base)2991 void vmovss_rm(XMMRegisterID src, int32_t offset, RegisterID base) { 2992 twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_WsdVsd, offset, base, invalid_xmm, 2993 src); 2994 } 2995 vmovss_rm_disp32(XMMRegisterID src,int32_t offset,RegisterID base)2996 void vmovss_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base) { 2997 twoByteOpSimd_disp32("vmovss", VEX_SS, OP2_MOVSD_WsdVsd, offset, base, 2998 invalid_xmm, src); 2999 } 3000 vmovss_mr(int32_t offset,RegisterID base,XMMRegisterID dst)3001 void vmovss_mr(int32_t offset, RegisterID base, XMMRegisterID dst) { 3002 twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_VsdWsd, offset, base, invalid_xmm, 3003 dst); 3004 } 3005 vmovss_mr_disp32(int32_t offset,RegisterID base,XMMRegisterID dst)3006 void vmovss_mr_disp32(int32_t offset, RegisterID base, XMMRegisterID dst) { 3007 twoByteOpSimd_disp32("vmovss", VEX_SS, OP2_MOVSD_VsdWsd, offset, base, 3008 invalid_xmm, dst); 3009 } 3010 vmovsd_rm(XMMRegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)3011 void vmovsd_rm(XMMRegisterID src, int32_t offset, RegisterID base, 3012 RegisterID index, int scale) { 3013 twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_WsdVsd, offset, base, index, 3014 scale, invalid_xmm, src); 3015 } 3016 vmovss_rm(XMMRegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)3017 void vmovss_rm(XMMRegisterID src, int32_t offset, RegisterID base, 3018 RegisterID index, int scale) { 3019 twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_WsdVsd, offset, base, index, 3020 scale, invalid_xmm, src); 3021 } 3022 vmovss_mr(int32_t offset,RegisterID base,RegisterID index,int scale,XMMRegisterID dst)3023 void vmovss_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 3024 XMMRegisterID dst) { 3025 twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_VsdWsd, offset, base, index, 3026 scale, invalid_xmm, dst); 3027 } 3028 vmovsd_mr(int32_t offset,RegisterID base,XMMRegisterID dst)3029 void vmovsd_mr(int32_t offset, RegisterID base, XMMRegisterID dst) { 3030 twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_VsdWsd, offset, base, invalid_xmm, 3031 dst); 3032 } 3033 vmovsd_mr_disp32(int32_t offset,RegisterID base,XMMRegisterID dst)3034 void vmovsd_mr_disp32(int32_t offset, RegisterID base, XMMRegisterID dst) { 3035 twoByteOpSimd_disp32("vmovsd", VEX_SD, OP2_MOVSD_VsdWsd, offset, base, 3036 invalid_xmm, dst); 3037 } 3038 vmovsd_mr(int32_t offset,RegisterID base,RegisterID index,int scale,XMMRegisterID dst)3039 void vmovsd_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 3040 XMMRegisterID dst) { 3041 twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_VsdWsd, offset, base, index, 3042 scale, invalid_xmm, dst); 3043 } 3044 3045 // Note that the register-to-register form of vmovsd does not write to the 3046 // entire output register. For general-purpose register-to-register moves, 3047 // use vmovapd instead. vmovsd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3048 void vmovsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3049 twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_VsdWsd, src1, src0, dst); 3050 } 3051 3052 // The register-to-register form of vmovss has the same problem as vmovsd 3053 // above. Prefer vmovaps for register-to-register moves. vmovss_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3054 void vmovss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3055 twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_VsdWsd, src1, src0, dst); 3056 } 3057 vmovsd_mr(const void * address,XMMRegisterID dst)3058 void vmovsd_mr(const void* address, XMMRegisterID dst) { 3059 twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_VsdWsd, address, invalid_xmm, 3060 dst); 3061 } 3062 vmovss_mr(const void * address,XMMRegisterID dst)3063 void vmovss_mr(const void* address, XMMRegisterID dst) { 3064 twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_VsdWsd, address, invalid_xmm, 3065 dst); 3066 } 3067 vmovups_mr(const void * address,XMMRegisterID dst)3068 void vmovups_mr(const void* address, XMMRegisterID dst) { 3069 twoByteOpSimd("vmovups", VEX_PS, OP2_MOVPS_VpsWps, address, invalid_xmm, 3070 dst); 3071 } 3072 vmovdqu_mr(const void * address,XMMRegisterID dst)3073 void vmovdqu_mr(const void* address, XMMRegisterID dst) { 3074 twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_VdqWdq, address, invalid_xmm, 3075 dst); 3076 } 3077 vmovsd_rm(XMMRegisterID src,const void * address)3078 void vmovsd_rm(XMMRegisterID src, const void* address) { 3079 twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_WsdVsd, address, invalid_xmm, 3080 src); 3081 } 3082 vmovss_rm(XMMRegisterID src,const void * address)3083 void vmovss_rm(XMMRegisterID src, const void* address) { 3084 twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_WsdVsd, address, invalid_xmm, 3085 src); 3086 } 3087 vmovdqa_rm(XMMRegisterID src,const void * address)3088 void vmovdqa_rm(XMMRegisterID src, const void* address) { 3089 twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_WdqVdq, address, invalid_xmm, 3090 src); 3091 } 3092 vmovaps_rm(XMMRegisterID src,const void * address)3093 void vmovaps_rm(XMMRegisterID src, const void* address) { 3094 twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_WsdVsd, address, invalid_xmm, 3095 src); 3096 } 3097 vmovdqu_rm(XMMRegisterID src,const void * address)3098 void vmovdqu_rm(XMMRegisterID src, const void* address) { 3099 twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_WdqVdq, address, invalid_xmm, 3100 src); 3101 } 3102 vmovups_rm(XMMRegisterID src,const void * address)3103 void vmovups_rm(XMMRegisterID src, const void* address) { 3104 twoByteOpSimd("vmovups", VEX_PS, OP2_MOVPS_WpsVps, address, invalid_xmm, 3105 src); 3106 } 3107 vmovaps_rr(XMMRegisterID src,XMMRegisterID dst)3108 void vmovaps_rr(XMMRegisterID src, XMMRegisterID dst) { 3109 #ifdef JS_CODEGEN_X64 3110 // There are two opcodes that can encode this instruction. If we have 3111 // one register in [xmm8,xmm15] and one in [xmm0,xmm7], use the 3112 // opcode which swaps the operands, as that way we can get a two-byte 3113 // VEX in that case. 3114 if (src >= xmm8 && dst < xmm8) { 3115 twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_WsdVsd, dst, invalid_xmm, 3116 src); 3117 return; 3118 } 3119 #endif 3120 twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_VsdWsd, src, invalid_xmm, dst); 3121 } vmovaps_rm(XMMRegisterID src,int32_t offset,RegisterID base)3122 void vmovaps_rm(XMMRegisterID src, int32_t offset, RegisterID base) { 3123 twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_WsdVsd, offset, base, 3124 invalid_xmm, src); 3125 } vmovaps_rm(XMMRegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)3126 void vmovaps_rm(XMMRegisterID src, int32_t offset, RegisterID base, 3127 RegisterID index, int scale) { 3128 twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_WsdVsd, offset, base, index, 3129 scale, invalid_xmm, src); 3130 } vmovaps_mr(int32_t offset,RegisterID base,XMMRegisterID dst)3131 void vmovaps_mr(int32_t offset, RegisterID base, XMMRegisterID dst) { 3132 twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_VsdWsd, offset, base, 3133 invalid_xmm, dst); 3134 } vmovaps_mr(int32_t offset,RegisterID base,RegisterID index,int scale,XMMRegisterID dst)3135 void vmovaps_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 3136 XMMRegisterID dst) { 3137 twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_VsdWsd, offset, base, index, 3138 scale, invalid_xmm, dst); 3139 } 3140 vmovups_rm(XMMRegisterID src,int32_t offset,RegisterID base)3141 void vmovups_rm(XMMRegisterID src, int32_t offset, RegisterID base) { 3142 twoByteOpSimd("vmovups", VEX_PS, OP2_MOVPS_WpsVps, offset, base, 3143 invalid_xmm, src); 3144 } vmovups_rm_disp32(XMMRegisterID src,int32_t offset,RegisterID base)3145 void vmovups_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base) { 3146 twoByteOpSimd_disp32("vmovups", VEX_PS, OP2_MOVPS_WpsVps, offset, base, 3147 invalid_xmm, src); 3148 } vmovups_rm(XMMRegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)3149 void vmovups_rm(XMMRegisterID src, int32_t offset, RegisterID base, 3150 RegisterID index, int scale) { 3151 twoByteOpSimd("vmovups", VEX_PS, OP2_MOVPS_WpsVps, offset, base, index, 3152 scale, invalid_xmm, src); 3153 } vmovups_mr(int32_t offset,RegisterID base,XMMRegisterID dst)3154 void vmovups_mr(int32_t offset, RegisterID base, XMMRegisterID dst) { 3155 twoByteOpSimd("vmovups", VEX_PS, OP2_MOVPS_VpsWps, offset, base, 3156 invalid_xmm, dst); 3157 } vmovups_mr_disp32(int32_t offset,RegisterID base,XMMRegisterID dst)3158 void vmovups_mr_disp32(int32_t offset, RegisterID base, XMMRegisterID dst) { 3159 twoByteOpSimd_disp32("vmovups", VEX_PS, OP2_MOVPS_VpsWps, offset, base, 3160 invalid_xmm, dst); 3161 } vmovups_mr(int32_t offset,RegisterID base,RegisterID index,int scale,XMMRegisterID dst)3162 void vmovups_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 3163 XMMRegisterID dst) { 3164 twoByteOpSimd("vmovups", VEX_PS, OP2_MOVPS_VpsWps, offset, base, index, 3165 scale, invalid_xmm, dst); 3166 } 3167 vmovapd_rr(XMMRegisterID src,XMMRegisterID dst)3168 void vmovapd_rr(XMMRegisterID src, XMMRegisterID dst) { 3169 #ifdef JS_CODEGEN_X64 3170 // There are two opcodes that can encode this instruction. If we have 3171 // one register in [xmm8,xmm15] and one in [xmm0,xmm7], use the 3172 // opcode which swaps the operands, as that way we can get a two-byte 3173 // VEX in that case. 3174 if (src >= xmm8 && dst < xmm8) { 3175 twoByteOpSimd("vmovapd", VEX_PD, OP2_MOVAPS_WsdVsd, dst, invalid_xmm, 3176 src); 3177 return; 3178 } 3179 #endif 3180 twoByteOpSimd("vmovapd", VEX_PD, OP2_MOVAPD_VsdWsd, src, invalid_xmm, dst); 3181 } 3182 vmovdqu_rm(XMMRegisterID src,int32_t offset,RegisterID base)3183 void vmovdqu_rm(XMMRegisterID src, int32_t offset, RegisterID base) { 3184 twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_WdqVdq, offset, base, 3185 invalid_xmm, src); 3186 } 3187 vmovdqu_rm_disp32(XMMRegisterID src,int32_t offset,RegisterID base)3188 void vmovdqu_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base) { 3189 twoByteOpSimd_disp32("vmovdqu", VEX_SS, OP2_MOVDQ_WdqVdq, offset, base, 3190 invalid_xmm, src); 3191 } 3192 vmovdqu_rm(XMMRegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)3193 void vmovdqu_rm(XMMRegisterID src, int32_t offset, RegisterID base, 3194 RegisterID index, int scale) { 3195 twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_WdqVdq, offset, base, index, 3196 scale, invalid_xmm, src); 3197 } 3198 vmovdqu_mr(int32_t offset,RegisterID base,XMMRegisterID dst)3199 void vmovdqu_mr(int32_t offset, RegisterID base, XMMRegisterID dst) { 3200 twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_VdqWdq, offset, base, 3201 invalid_xmm, dst); 3202 } 3203 vmovdqu_mr_disp32(int32_t offset,RegisterID base,XMMRegisterID dst)3204 void vmovdqu_mr_disp32(int32_t offset, RegisterID base, XMMRegisterID dst) { 3205 twoByteOpSimd_disp32("vmovdqu", VEX_SS, OP2_MOVDQ_VdqWdq, offset, base, 3206 invalid_xmm, dst); 3207 } 3208 vmovdqu_mr(int32_t offset,RegisterID base,RegisterID index,int scale,XMMRegisterID dst)3209 void vmovdqu_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 3210 XMMRegisterID dst) { 3211 twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_VdqWdq, offset, base, index, 3212 scale, invalid_xmm, dst); 3213 } 3214 vmovdqa_rr(XMMRegisterID src,XMMRegisterID dst)3215 void vmovdqa_rr(XMMRegisterID src, XMMRegisterID dst) { 3216 #ifdef JS_CODEGEN_X64 3217 // There are two opcodes that can encode this instruction. If we have 3218 // one register in [xmm8,xmm15] and one in [xmm0,xmm7], use the 3219 // opcode which swaps the operands, as that way we can get a two-byte 3220 // VEX in that case. 3221 if (src >= xmm8 && dst < xmm8) { 3222 twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_WdqVdq, dst, invalid_xmm, src); 3223 return; 3224 } 3225 #endif 3226 twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_VdqWdq, src, invalid_xmm, dst); 3227 } 3228 vmovdqa_rm(XMMRegisterID src,int32_t offset,RegisterID base)3229 void vmovdqa_rm(XMMRegisterID src, int32_t offset, RegisterID base) { 3230 twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_WdqVdq, offset, base, 3231 invalid_xmm, src); 3232 } 3233 vmovdqa_rm(XMMRegisterID src,int32_t offset,RegisterID base,RegisterID index,int scale)3234 void vmovdqa_rm(XMMRegisterID src, int32_t offset, RegisterID base, 3235 RegisterID index, int scale) { 3236 twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_WdqVdq, offset, base, index, 3237 scale, invalid_xmm, src); 3238 } 3239 vmovdqa_mr(int32_t offset,RegisterID base,XMMRegisterID dst)3240 void vmovdqa_mr(int32_t offset, RegisterID base, XMMRegisterID dst) { 3241 twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_VdqWdq, offset, base, 3242 invalid_xmm, dst); 3243 } 3244 vmovdqa_mr(int32_t offset,RegisterID base,RegisterID index,int scale,XMMRegisterID dst)3245 void vmovdqa_mr(int32_t offset, RegisterID base, RegisterID index, int scale, 3246 XMMRegisterID dst) { 3247 twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_VdqWdq, offset, base, index, 3248 scale, invalid_xmm, dst); 3249 } 3250 vmulsd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3251 void vmulsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3252 twoByteOpSimd("vmulsd", VEX_SD, OP2_MULSD_VsdWsd, src1, src0, dst); 3253 } 3254 vmulss_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3255 void vmulss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3256 twoByteOpSimd("vmulss", VEX_SS, OP2_MULSD_VsdWsd, src1, src0, dst); 3257 } 3258 vmulsd_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3259 void vmulsd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 3260 XMMRegisterID dst) { 3261 twoByteOpSimd("vmulsd", VEX_SD, OP2_MULSD_VsdWsd, offset, base, src0, dst); 3262 } 3263 vmulss_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3264 void vmulss_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 3265 XMMRegisterID dst) { 3266 twoByteOpSimd("vmulss", VEX_SS, OP2_MULSD_VsdWsd, offset, base, src0, dst); 3267 } 3268 vpinsrw_irr(uint32_t whichWord,RegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3269 void vpinsrw_irr(uint32_t whichWord, RegisterID src1, XMMRegisterID src0, 3270 XMMRegisterID dst) { 3271 MOZ_ASSERT(whichWord < 8); 3272 twoByteOpImmInt32Simd("vpinsrw", VEX_PD, OP2_PINSRW, whichWord, src1, src0, 3273 dst); 3274 } 3275 vpextrw_irr(uint32_t whichWord,XMMRegisterID src,RegisterID dst)3276 void vpextrw_irr(uint32_t whichWord, XMMRegisterID src, RegisterID dst) { 3277 MOZ_ASSERT(whichWord < 8); 3278 twoByteOpImmSimdInt32("vpextrw", VEX_PD, OP2_PEXTRW_GdUdIb, whichWord, src, 3279 dst); 3280 } 3281 vsubsd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3282 void vsubsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3283 twoByteOpSimd("vsubsd", VEX_SD, OP2_SUBSD_VsdWsd, src1, src0, dst); 3284 } 3285 vsubss_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3286 void vsubss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3287 twoByteOpSimd("vsubss", VEX_SS, OP2_SUBSD_VsdWsd, src1, src0, dst); 3288 } 3289 vsubsd_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3290 void vsubsd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 3291 XMMRegisterID dst) { 3292 twoByteOpSimd("vsubsd", VEX_SD, OP2_SUBSD_VsdWsd, offset, base, src0, dst); 3293 } 3294 vsubss_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3295 void vsubss_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 3296 XMMRegisterID dst) { 3297 twoByteOpSimd("vsubss", VEX_SS, OP2_SUBSD_VsdWsd, offset, base, src0, dst); 3298 } 3299 vucomiss_rr(XMMRegisterID rhs,XMMRegisterID lhs)3300 void vucomiss_rr(XMMRegisterID rhs, XMMRegisterID lhs) { 3301 twoByteOpSimdFlags("vucomiss", VEX_PS, OP2_UCOMISD_VsdWsd, rhs, lhs); 3302 } 3303 vucomisd_rr(XMMRegisterID rhs,XMMRegisterID lhs)3304 void vucomisd_rr(XMMRegisterID rhs, XMMRegisterID lhs) { 3305 twoByteOpSimdFlags("vucomisd", VEX_PD, OP2_UCOMISD_VsdWsd, rhs, lhs); 3306 } 3307 vucomisd_mr(int32_t offset,RegisterID base,XMMRegisterID lhs)3308 void vucomisd_mr(int32_t offset, RegisterID base, XMMRegisterID lhs) { 3309 twoByteOpSimdFlags("vucomisd", VEX_PD, OP2_UCOMISD_VsdWsd, offset, base, 3310 lhs); 3311 } 3312 vdivsd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3313 void vdivsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3314 twoByteOpSimd("vdivsd", VEX_SD, OP2_DIVSD_VsdWsd, src1, src0, dst); 3315 } 3316 vdivss_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3317 void vdivss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3318 twoByteOpSimd("vdivss", VEX_SS, OP2_DIVSD_VsdWsd, src1, src0, dst); 3319 } 3320 vdivsd_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3321 void vdivsd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 3322 XMMRegisterID dst) { 3323 twoByteOpSimd("vdivsd", VEX_SD, OP2_DIVSD_VsdWsd, offset, base, src0, dst); 3324 } 3325 vdivss_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3326 void vdivss_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 3327 XMMRegisterID dst) { 3328 twoByteOpSimd("vdivss", VEX_SS, OP2_DIVSD_VsdWsd, offset, base, src0, dst); 3329 } 3330 vxorpd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3331 void vxorpd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3332 twoByteOpSimd("vxorpd", VEX_PD, OP2_XORPD_VpdWpd, src1, src0, dst); 3333 } 3334 vorpd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3335 void vorpd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3336 twoByteOpSimd("vorpd", VEX_PD, OP2_ORPD_VpdWpd, src1, src0, dst); 3337 } 3338 vandpd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3339 void vandpd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3340 twoByteOpSimd("vandpd", VEX_PD, OP2_ANDPD_VpdWpd, src1, src0, dst); 3341 } 3342 vandps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3343 void vandps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3344 twoByteOpSimd("vandps", VEX_PS, OP2_ANDPS_VpsWps, src1, src0, dst); 3345 } 3346 vandps_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3347 void vandps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 3348 XMMRegisterID dst) { 3349 twoByteOpSimd("vandps", VEX_PS, OP2_ANDPS_VpsWps, offset, base, src0, dst); 3350 } 3351 vandps_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)3352 void vandps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 3353 twoByteOpSimd("vandps", VEX_PS, OP2_ANDPS_VpsWps, address, src0, dst); 3354 } 3355 vandnps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3356 void vandnps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3357 twoByteOpSimd("vandnps", VEX_PS, OP2_ANDNPS_VpsWps, src1, src0, dst); 3358 } 3359 vandnps_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3360 void vandnps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 3361 XMMRegisterID dst) { 3362 twoByteOpSimd("vandnps", VEX_PS, OP2_ANDNPS_VpsWps, offset, base, src0, 3363 dst); 3364 } 3365 vandnps_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)3366 void vandnps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 3367 twoByteOpSimd("vandnps", VEX_PS, OP2_ANDNPS_VpsWps, address, src0, dst); 3368 } 3369 vorps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3370 void vorps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3371 twoByteOpSimd("vorps", VEX_PS, OP2_ORPS_VpsWps, src1, src0, dst); 3372 } 3373 vorps_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3374 void vorps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 3375 XMMRegisterID dst) { 3376 twoByteOpSimd("vorps", VEX_PS, OP2_ORPS_VpsWps, offset, base, src0, dst); 3377 } 3378 vorps_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)3379 void vorps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 3380 twoByteOpSimd("vorps", VEX_PS, OP2_ORPS_VpsWps, address, src0, dst); 3381 } 3382 vxorps_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3383 void vxorps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3384 twoByteOpSimd("vxorps", VEX_PS, OP2_XORPS_VpsWps, src1, src0, dst); 3385 } 3386 vxorps_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3387 void vxorps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 3388 XMMRegisterID dst) { 3389 twoByteOpSimd("vxorps", VEX_PS, OP2_XORPS_VpsWps, offset, base, src0, dst); 3390 } 3391 vxorps_mr(const void * address,XMMRegisterID src0,XMMRegisterID dst)3392 void vxorps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst) { 3393 twoByteOpSimd("vxorps", VEX_PS, OP2_XORPS_VpsWps, address, src0, dst); 3394 } 3395 vsqrtsd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3396 void vsqrtsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3397 twoByteOpSimd("vsqrtsd", VEX_SD, OP2_SQRTSD_VsdWsd, src1, src0, dst); 3398 } 3399 vsqrtss_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3400 void vsqrtss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3401 twoByteOpSimd("vsqrtss", VEX_SS, OP2_SQRTSS_VssWss, src1, src0, dst); 3402 } 3403 vroundsd_irr(RoundingMode mode,XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3404 void vroundsd_irr(RoundingMode mode, XMMRegisterID src1, XMMRegisterID src0, 3405 XMMRegisterID dst) { 3406 threeByteOpImmSimd("vroundsd", VEX_PD, OP3_ROUNDSD_VsdWsd, ESCAPE_3A, mode, 3407 src1, src0, dst); 3408 } 3409 vroundss_irr(RoundingMode mode,XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3410 void vroundss_irr(RoundingMode mode, XMMRegisterID src1, XMMRegisterID src0, 3411 XMMRegisterID dst) { 3412 threeByteOpImmSimd("vroundss", VEX_PD, OP3_ROUNDSS_VsdWsd, ESCAPE_3A, mode, 3413 src1, src0, dst); 3414 } 3415 vinsertps_irr(uint32_t mask,XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3416 void vinsertps_irr(uint32_t mask, XMMRegisterID src1, XMMRegisterID src0, 3417 XMMRegisterID dst) { 3418 threeByteOpImmSimd("vinsertps", VEX_PD, OP3_INSERTPS_VpsUps, ESCAPE_3A, 3419 mask, src1, src0, dst); 3420 } vinsertps_imr(uint32_t mask,int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3421 void vinsertps_imr(uint32_t mask, int32_t offset, RegisterID base, 3422 XMMRegisterID src0, XMMRegisterID dst) { 3423 threeByteOpImmSimd("vinsertps", VEX_PD, OP3_INSERTPS_VpsUps, ESCAPE_3A, 3424 mask, offset, base, src0, dst); 3425 } 3426 vpinsrb_irr(unsigned lane,RegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3427 void vpinsrb_irr(unsigned lane, RegisterID src1, XMMRegisterID src0, 3428 XMMRegisterID dst) { 3429 MOZ_ASSERT(lane < 16); 3430 threeByteOpImmInt32Simd("vpinsrb", VEX_PD, OP3_PINSRB_VdqEdIb, ESCAPE_3A, 3431 lane, src1, src0, dst); 3432 } 3433 vpinsrd_irr(unsigned lane,RegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3434 void vpinsrd_irr(unsigned lane, RegisterID src1, XMMRegisterID src0, 3435 XMMRegisterID dst) { 3436 MOZ_ASSERT(lane < 4); 3437 threeByteOpImmInt32Simd("vpinsrd", VEX_PD, OP3_PINSRD_VdqEdIb, ESCAPE_3A, 3438 lane, src1, src0, dst); 3439 } 3440 vpextrb_irr(unsigned lane,XMMRegisterID src,RegisterID dst)3441 void vpextrb_irr(unsigned lane, XMMRegisterID src, RegisterID dst) { 3442 MOZ_ASSERT(lane < 16); 3443 threeByteOpImmSimdInt32("vpextrb", VEX_PD, OP3_PEXTRB_EdVdqIb, ESCAPE_3A, 3444 lane, (XMMRegisterID)dst, (RegisterID)src); 3445 } 3446 vpextrd_irr(unsigned lane,XMMRegisterID src,RegisterID dst)3447 void vpextrd_irr(unsigned lane, XMMRegisterID src, RegisterID dst) { 3448 MOZ_ASSERT(lane < 4); 3449 threeByteOpImmSimdInt32("vpextrd", VEX_PD, OP3_PEXTRD_EdVdqIb, ESCAPE_3A, 3450 lane, (XMMRegisterID)dst, (RegisterID)src); 3451 } 3452 vblendps_irr(unsigned imm,XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3453 void vblendps_irr(unsigned imm, XMMRegisterID src1, XMMRegisterID src0, 3454 XMMRegisterID dst) { 3455 MOZ_ASSERT(imm < 16); 3456 // Despite being a "ps" instruction, vblendps is encoded with the "pd" 3457 // prefix. 3458 threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, 3459 src1, src0, dst); 3460 } 3461 vblendps_imr(unsigned imm,int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3462 void vblendps_imr(unsigned imm, int32_t offset, RegisterID base, 3463 XMMRegisterID src0, XMMRegisterID dst) { 3464 MOZ_ASSERT(imm < 16); 3465 // Despite being a "ps" instruction, vblendps is encoded with the "pd" 3466 // prefix. 3467 threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, 3468 offset, base, src0, dst); 3469 } 3470 vblendvps_rr(XMMRegisterID mask,XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3471 void vblendvps_rr(XMMRegisterID mask, XMMRegisterID src1, XMMRegisterID src0, 3472 XMMRegisterID dst) { 3473 vblendvOpSimd(mask, src1, src0, dst); 3474 } vblendvps_mr(XMMRegisterID mask,int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3475 void vblendvps_mr(XMMRegisterID mask, int32_t offset, RegisterID base, 3476 XMMRegisterID src0, XMMRegisterID dst) { 3477 vblendvOpSimd(mask, offset, base, src0, dst); 3478 } 3479 vmovsldup_rr(XMMRegisterID src,XMMRegisterID dst)3480 void vmovsldup_rr(XMMRegisterID src, XMMRegisterID dst) { 3481 twoByteOpSimd("vmovsldup", VEX_SS, OP2_MOVSLDUP_VpsWps, src, invalid_xmm, 3482 dst); 3483 } vmovsldup_mr(int32_t offset,RegisterID base,XMMRegisterID dst)3484 void vmovsldup_mr(int32_t offset, RegisterID base, XMMRegisterID dst) { 3485 twoByteOpSimd("vmovsldup", VEX_SS, OP2_MOVSLDUP_VpsWps, offset, base, 3486 invalid_xmm, dst); 3487 } 3488 vmovshdup_rr(XMMRegisterID src,XMMRegisterID dst)3489 void vmovshdup_rr(XMMRegisterID src, XMMRegisterID dst) { 3490 twoByteOpSimd("vmovshdup", VEX_SS, OP2_MOVSHDUP_VpsWps, src, invalid_xmm, 3491 dst); 3492 } vmovshdup_mr(int32_t offset,RegisterID base,XMMRegisterID dst)3493 void vmovshdup_mr(int32_t offset, RegisterID base, XMMRegisterID dst) { 3494 twoByteOpSimd("vmovshdup", VEX_SS, OP2_MOVSHDUP_VpsWps, offset, base, 3495 invalid_xmm, dst); 3496 } 3497 vminsd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3498 void vminsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3499 twoByteOpSimd("vminsd", VEX_SD, OP2_MINSD_VsdWsd, src1, src0, dst); 3500 } vminsd_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3501 void vminsd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 3502 XMMRegisterID dst) { 3503 twoByteOpSimd("vminsd", VEX_SD, OP2_MINSD_VsdWsd, offset, base, src0, dst); 3504 } 3505 vminss_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3506 void vminss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3507 twoByteOpSimd("vminss", VEX_SS, OP2_MINSS_VssWss, src1, src0, dst); 3508 } 3509 vmaxsd_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3510 void vmaxsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3511 twoByteOpSimd("vmaxsd", VEX_SD, OP2_MAXSD_VsdWsd, src1, src0, dst); 3512 } vmaxsd_mr(int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3513 void vmaxsd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, 3514 XMMRegisterID dst) { 3515 twoByteOpSimd("vmaxsd", VEX_SD, OP2_MAXSD_VsdWsd, offset, base, src0, dst); 3516 } 3517 vmaxss_rr(XMMRegisterID src1,XMMRegisterID src0,XMMRegisterID dst)3518 void vmaxss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) { 3519 twoByteOpSimd("vmaxss", VEX_SS, OP2_MAXSS_VssWss, src1, src0, dst); 3520 } 3521 3522 // Misc instructions: 3523 int3()3524 void int3() { 3525 spew("int3"); 3526 m_formatter.oneByteOp(OP_INT3); 3527 } 3528 ud2()3529 void ud2() { 3530 spew("ud2"); 3531 m_formatter.twoByteOp(OP2_UD2); 3532 } 3533 ret()3534 void ret() { 3535 spew("ret"); 3536 m_formatter.oneByteOp(OP_RET); 3537 } 3538 ret_i(int32_t imm)3539 void ret_i(int32_t imm) { 3540 spew("ret $%d", imm); 3541 m_formatter.oneByteOp(OP_RET_Iz); 3542 m_formatter.immediate16u(imm); 3543 } 3544 lfence()3545 void lfence() { 3546 spew("lfence"); 3547 m_formatter.twoByteOp(OP_FENCE, (RegisterID)0, 0b101); 3548 } mfence()3549 void mfence() { 3550 spew("mfence"); 3551 m_formatter.twoByteOp(OP_FENCE, (RegisterID)0, 0b110); 3552 } 3553 3554 // Assembler admin methods: 3555 label()3556 JmpDst label() { 3557 JmpDst r = JmpDst(m_formatter.size()); 3558 spew(".set .Llabel%d, .", r.offset()); 3559 return r; 3560 } 3561 currentOffset()3562 size_t currentOffset() const { return m_formatter.size(); } 3563 3564 static JmpDst labelFor(JmpSrc jump, intptr_t offset = 0) { 3565 return JmpDst(jump.offset() + offset); 3566 } 3567 haltingAlign(int alignment)3568 void haltingAlign(int alignment) { 3569 spew(".balign %d, 0x%x # hlt", alignment, OP_HLT); 3570 while (!m_formatter.isAligned(alignment)) m_formatter.oneByteOp(OP_HLT); 3571 } 3572 nopAlign(int alignment)3573 void nopAlign(int alignment) { 3574 spew(".balign %d", alignment); 3575 3576 int remainder = m_formatter.size() % alignment; 3577 if (remainder > 0) insert_nop(alignment - remainder); 3578 } 3579 jumpTablePointer(uintptr_t ptr)3580 void jumpTablePointer(uintptr_t ptr) { 3581 #ifdef JS_CODEGEN_X64 3582 spew(".quad 0x%" PRIxPTR, ptr); 3583 #else 3584 spew(".int 0x%" PRIxPTR, ptr); 3585 #endif 3586 m_formatter.jumpTablePointer(ptr); 3587 } 3588 doubleConstant(double d)3589 void doubleConstant(double d) { 3590 spew(".double %.16g", d); 3591 m_formatter.doubleConstant(d); 3592 } floatConstant(float f)3593 void floatConstant(float f) { 3594 spew(".float %.16g", f); 3595 m_formatter.floatConstant(f); 3596 } 3597 simd128Constant(const void * data)3598 void simd128Constant(const void* data) { 3599 const uint32_t* dw = reinterpret_cast<const uint32_t*>(data); 3600 spew(".int 0x%08x,0x%08x,0x%08x,0x%08x", dw[0], dw[1], dw[2], dw[3]); 3601 MOZ_ASSERT(m_formatter.isAligned(16)); 3602 m_formatter.simd128Constant(data); 3603 } 3604 int32Constant(int32_t i)3605 void int32Constant(int32_t i) { 3606 spew(".int %d", i); 3607 m_formatter.int32Constant(i); 3608 } int64Constant(int64_t i)3609 void int64Constant(int64_t i) { 3610 spew(".quad %lld", (long long)i); 3611 m_formatter.int64Constant(i); 3612 } 3613 3614 // Linking & patching: 3615 assertValidJmpSrc(JmpSrc src)3616 void assertValidJmpSrc(JmpSrc src) { 3617 // The target offset is stored at offset - 4. 3618 MOZ_RELEASE_ASSERT(src.offset() > int32_t(sizeof(int32_t))); 3619 MOZ_RELEASE_ASSERT(size_t(src.offset()) <= size()); 3620 } 3621 nextJump(const JmpSrc & from,JmpSrc * next)3622 bool nextJump(const JmpSrc& from, JmpSrc* next) { 3623 // Sanity check - if the assembler has OOM'd, it will start overwriting 3624 // its internal buffer and thus our links could be garbage. 3625 if (oom()) return false; 3626 3627 assertValidJmpSrc(from); 3628 3629 const unsigned char* code = m_formatter.data(); 3630 int32_t offset = GetInt32(code + from.offset()); 3631 if (offset == -1) return false; 3632 3633 if (MOZ_UNLIKELY(size_t(offset) >= size())) { 3634 #ifdef NIGHTLY_BUILD 3635 // Stash some data on the stack so we can retrieve it from minidumps, 3636 // see bug 1124397. 3637 int32_t startOffset = from.offset() - 1; 3638 while (startOffset >= 0 && code[startOffset] == 0xe5) startOffset--; 3639 int32_t endOffset = from.offset() - 1; 3640 while (endOffset < int32_t(size()) && code[endOffset] == 0xe5) 3641 endOffset++; 3642 volatile uintptr_t dump[10]; 3643 blackbox = dump; 3644 blackbox[0] = uintptr_t(0xABCD1234); 3645 blackbox[1] = uintptr_t(offset); 3646 blackbox[2] = uintptr_t(size()); 3647 blackbox[3] = uintptr_t(from.offset()); 3648 blackbox[4] = uintptr_t(code[from.offset() - 5]); 3649 blackbox[5] = uintptr_t(code[from.offset() - 4]); 3650 blackbox[6] = uintptr_t(code[from.offset() - 3]); 3651 blackbox[7] = uintptr_t(startOffset); 3652 blackbox[8] = uintptr_t(endOffset); 3653 blackbox[9] = uintptr_t(0xFFFF7777); 3654 #endif 3655 MOZ_CRASH("nextJump bogus offset"); 3656 } 3657 3658 *next = JmpSrc(offset); 3659 return true; 3660 } setNextJump(const JmpSrc & from,const JmpSrc & to)3661 void setNextJump(const JmpSrc& from, const JmpSrc& to) { 3662 // Sanity check - if the assembler has OOM'd, it will start overwriting 3663 // its internal buffer and thus our links could be garbage. 3664 if (oom()) return; 3665 3666 assertValidJmpSrc(from); 3667 MOZ_RELEASE_ASSERT(to.offset() == -1 || size_t(to.offset()) <= size()); 3668 3669 unsigned char* code = m_formatter.data(); 3670 SetInt32(code + from.offset(), to.offset()); 3671 } 3672 linkJump(JmpSrc from,JmpDst to)3673 void linkJump(JmpSrc from, JmpDst to) { 3674 MOZ_ASSERT(from.offset() != -1); 3675 MOZ_ASSERT(to.offset() != -1); 3676 3677 // Sanity check - if the assembler has OOM'd, it will start overwriting 3678 // its internal buffer and thus our links could be garbage. 3679 if (oom()) return; 3680 3681 assertValidJmpSrc(from); 3682 MOZ_RELEASE_ASSERT(size_t(to.offset()) <= size()); 3683 3684 spew(".set .Lfrom%d, .Llabel%d", from.offset(), to.offset()); 3685 unsigned char* code = m_formatter.data(); 3686 SetRel32(code + from.offset(), code + to.offset()); 3687 } 3688 executableCopy(void * dst)3689 void executableCopy(void* dst) { 3690 const unsigned char* src = m_formatter.buffer(); 3691 memcpy(dst, src, size()); 3692 } appendRawCode(const uint8_t * code,size_t numBytes)3693 MOZ_MUST_USE bool appendRawCode(const uint8_t* code, size_t numBytes) { 3694 return m_formatter.append(code, numBytes); 3695 } 3696 3697 protected: CAN_SIGN_EXTEND_8_32(int32_t value)3698 static bool CAN_SIGN_EXTEND_8_32(int32_t value) { 3699 return value == (int32_t)(int8_t)value; 3700 } CAN_SIGN_EXTEND_16_32(int32_t value)3701 static bool CAN_SIGN_EXTEND_16_32(int32_t value) { 3702 return value == (int32_t)(int16_t)value; 3703 } CAN_ZERO_EXTEND_8_32(int32_t value)3704 static bool CAN_ZERO_EXTEND_8_32(int32_t value) { 3705 return value == (int32_t)(uint8_t)value; 3706 } CAN_ZERO_EXTEND_8H_32(int32_t value)3707 static bool CAN_ZERO_EXTEND_8H_32(int32_t value) { 3708 return value == (value & 0xff00); 3709 } CAN_ZERO_EXTEND_16_32(int32_t value)3710 static bool CAN_ZERO_EXTEND_16_32(int32_t value) { 3711 return value == (int32_t)(uint16_t)value; 3712 } CAN_ZERO_EXTEND_32_64(int32_t value)3713 static bool CAN_ZERO_EXTEND_32_64(int32_t value) { return value >= 0; } 3714 3715 // Methods for encoding SIMD instructions via either legacy SSE encoding or 3716 // VEX encoding. 3717 useLegacySSEEncoding(XMMRegisterID src0,XMMRegisterID dst)3718 bool useLegacySSEEncoding(XMMRegisterID src0, XMMRegisterID dst) { 3719 // If we don't have AVX or it's disabled, use the legacy SSE encoding. 3720 if (!useVEX_) { 3721 MOZ_ASSERT( 3722 src0 == invalid_xmm || src0 == dst, 3723 "Legacy SSE (pre-AVX) encoding requires the output register to be " 3724 "the same as the src0 input register"); 3725 return true; 3726 } 3727 3728 // If src0 is the same as the output register, we might as well use 3729 // the legacy SSE encoding, since it is smaller. However, this is only 3730 // beneficial as long as we're not using ymm registers anywhere. 3731 return src0 == dst; 3732 } 3733 useLegacySSEEncodingForVblendv(XMMRegisterID mask,XMMRegisterID src0,XMMRegisterID dst)3734 bool useLegacySSEEncodingForVblendv(XMMRegisterID mask, XMMRegisterID src0, 3735 XMMRegisterID dst) { 3736 // Similar to useLegacySSEEncoding, but for vblendv the Legacy SSE 3737 // encoding also requires the mask to be in xmm0. 3738 3739 if (!useVEX_) { 3740 MOZ_ASSERT( 3741 src0 == dst, 3742 "Legacy SSE (pre-AVX) encoding requires the output register to be " 3743 "the same as the src0 input register"); 3744 MOZ_ASSERT( 3745 mask == xmm0, 3746 "Legacy SSE (pre-AVX) encoding for blendv requires the mask to be " 3747 "in xmm0"); 3748 return true; 3749 } 3750 3751 return src0 == dst && mask == xmm0; 3752 } 3753 useLegacySSEEncodingForOtherOutput()3754 bool useLegacySSEEncodingForOtherOutput() { return !useVEX_; } 3755 legacySSEOpName(const char * name)3756 const char* legacySSEOpName(const char* name) { 3757 MOZ_ASSERT(name[0] == 'v'); 3758 return name + 1; 3759 } 3760 twoByteOpSimd(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,XMMRegisterID rm,XMMRegisterID src0,XMMRegisterID dst)3761 void twoByteOpSimd(const char* name, VexOperandType ty, 3762 TwoByteOpcodeID opcode, XMMRegisterID rm, 3763 XMMRegisterID src0, XMMRegisterID dst) { 3764 if (useLegacySSEEncoding(src0, dst)) { 3765 if (IsXMMReversedOperands(opcode)) 3766 spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(dst), 3767 XMMRegName(rm)); 3768 else 3769 spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(rm), 3770 XMMRegName(dst)); 3771 m_formatter.legacySSEPrefix(ty); 3772 m_formatter.twoByteOp(opcode, (RegisterID)rm, dst); 3773 return; 3774 } 3775 3776 if (src0 == invalid_xmm) { 3777 if (IsXMMReversedOperands(opcode)) 3778 spew("%-11s%s, %s", name, XMMRegName(dst), XMMRegName(rm)); 3779 else 3780 spew("%-11s%s, %s", name, XMMRegName(rm), XMMRegName(dst)); 3781 } else { 3782 spew("%-11s%s, %s, %s", name, XMMRegName(rm), XMMRegName(src0), 3783 XMMRegName(dst)); 3784 } 3785 m_formatter.twoByteOpVex(ty, opcode, (RegisterID)rm, src0, dst); 3786 } 3787 twoByteOpImmSimd(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,uint32_t imm,XMMRegisterID rm,XMMRegisterID src0,XMMRegisterID dst)3788 void twoByteOpImmSimd(const char* name, VexOperandType ty, 3789 TwoByteOpcodeID opcode, uint32_t imm, XMMRegisterID rm, 3790 XMMRegisterID src0, XMMRegisterID dst) { 3791 if (useLegacySSEEncoding(src0, dst)) { 3792 spew("%-11s$0x%x, %s, %s", legacySSEOpName(name), imm, XMMRegName(rm), 3793 XMMRegName(dst)); 3794 m_formatter.legacySSEPrefix(ty); 3795 m_formatter.twoByteOp(opcode, (RegisterID)rm, dst); 3796 m_formatter.immediate8u(imm); 3797 return; 3798 } 3799 3800 if (src0 == invalid_xmm) 3801 spew("%-11s$0x%x, %s, %s", name, imm, XMMRegName(rm), XMMRegName(dst)); 3802 else 3803 spew("%-11s$0x%x, %s, %s, %s", name, imm, XMMRegName(rm), 3804 XMMRegName(src0), XMMRegName(dst)); 3805 m_formatter.twoByteOpVex(ty, opcode, (RegisterID)rm, src0, dst); 3806 m_formatter.immediate8u(imm); 3807 } 3808 twoByteOpSimd(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3809 void twoByteOpSimd(const char* name, VexOperandType ty, 3810 TwoByteOpcodeID opcode, int32_t offset, RegisterID base, 3811 XMMRegisterID src0, XMMRegisterID dst) { 3812 if (useLegacySSEEncoding(src0, dst)) { 3813 if (IsXMMReversedOperands(opcode)) { 3814 spew("%-11s%s, " MEM_ob, legacySSEOpName(name), XMMRegName(dst), 3815 ADDR_ob(offset, base)); 3816 } else { 3817 spew("%-11s" MEM_ob ", %s", legacySSEOpName(name), 3818 ADDR_ob(offset, base), XMMRegName(dst)); 3819 } 3820 m_formatter.legacySSEPrefix(ty); 3821 m_formatter.twoByteOp(opcode, offset, base, dst); 3822 return; 3823 } 3824 3825 if (src0 == invalid_xmm) { 3826 if (IsXMMReversedOperands(opcode)) 3827 spew("%-11s%s, " MEM_ob, name, XMMRegName(dst), ADDR_ob(offset, base)); 3828 else 3829 spew("%-11s" MEM_ob ", %s", name, ADDR_ob(offset, base), 3830 XMMRegName(dst)); 3831 } else { 3832 spew("%-11s" MEM_ob ", %s, %s", name, ADDR_ob(offset, base), 3833 XMMRegName(src0), XMMRegName(dst)); 3834 } 3835 m_formatter.twoByteOpVex(ty, opcode, offset, base, src0, dst); 3836 } 3837 twoByteOpSimd_disp32(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3838 void twoByteOpSimd_disp32(const char* name, VexOperandType ty, 3839 TwoByteOpcodeID opcode, int32_t offset, 3840 RegisterID base, XMMRegisterID src0, 3841 XMMRegisterID dst) { 3842 if (useLegacySSEEncoding(src0, dst)) { 3843 if (IsXMMReversedOperands(opcode)) 3844 spew("%-11s%s, " MEM_o32b, legacySSEOpName(name), XMMRegName(dst), 3845 ADDR_o32b(offset, base)); 3846 else 3847 spew("%-11s" MEM_o32b ", %s", legacySSEOpName(name), 3848 ADDR_o32b(offset, base), XMMRegName(dst)); 3849 m_formatter.legacySSEPrefix(ty); 3850 m_formatter.twoByteOp_disp32(opcode, offset, base, dst); 3851 return; 3852 } 3853 3854 if (src0 == invalid_xmm) { 3855 if (IsXMMReversedOperands(opcode)) 3856 spew("%-11s%s, " MEM_o32b, name, XMMRegName(dst), 3857 ADDR_o32b(offset, base)); 3858 else 3859 spew("%-11s" MEM_o32b ", %s", name, ADDR_o32b(offset, base), 3860 XMMRegName(dst)); 3861 } else { 3862 spew("%-11s" MEM_o32b ", %s, %s", name, ADDR_o32b(offset, base), 3863 XMMRegName(src0), XMMRegName(dst)); 3864 } 3865 m_formatter.twoByteOpVex_disp32(ty, opcode, offset, base, src0, dst); 3866 } 3867 twoByteOpImmSimd(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,uint32_t imm,int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)3868 void twoByteOpImmSimd(const char* name, VexOperandType ty, 3869 TwoByteOpcodeID opcode, uint32_t imm, int32_t offset, 3870 RegisterID base, XMMRegisterID src0, 3871 XMMRegisterID dst) { 3872 if (useLegacySSEEncoding(src0, dst)) { 3873 spew("%-11s$0x%x, " MEM_ob ", %s", legacySSEOpName(name), imm, 3874 ADDR_ob(offset, base), XMMRegName(dst)); 3875 m_formatter.legacySSEPrefix(ty); 3876 m_formatter.twoByteOp(opcode, offset, base, dst); 3877 m_formatter.immediate8u(imm); 3878 return; 3879 } 3880 3881 spew("%-11s$0x%x, " MEM_ob ", %s, %s", name, imm, ADDR_ob(offset, base), 3882 XMMRegName(src0), XMMRegName(dst)); 3883 m_formatter.twoByteOpVex(ty, opcode, offset, base, src0, dst); 3884 m_formatter.immediate8u(imm); 3885 } 3886 twoByteOpSimd(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,int32_t offset,RegisterID base,RegisterID index,int scale,XMMRegisterID src0,XMMRegisterID dst)3887 void twoByteOpSimd(const char* name, VexOperandType ty, 3888 TwoByteOpcodeID opcode, int32_t offset, RegisterID base, 3889 RegisterID index, int scale, XMMRegisterID src0, 3890 XMMRegisterID dst) { 3891 if (useLegacySSEEncoding(src0, dst)) { 3892 if (IsXMMReversedOperands(opcode)) { 3893 spew("%-11s%s, " MEM_obs, legacySSEOpName(name), XMMRegName(dst), 3894 ADDR_obs(offset, base, index, scale)); 3895 } else { 3896 spew("%-11s" MEM_obs ", %s", legacySSEOpName(name), 3897 ADDR_obs(offset, base, index, scale), XMMRegName(dst)); 3898 } 3899 m_formatter.legacySSEPrefix(ty); 3900 m_formatter.twoByteOp(opcode, offset, base, index, scale, dst); 3901 return; 3902 } 3903 3904 if (src0 == invalid_xmm) { 3905 if (IsXMMReversedOperands(opcode)) { 3906 spew("%-11s%s, " MEM_obs, name, XMMRegName(dst), 3907 ADDR_obs(offset, base, index, scale)); 3908 } else { 3909 spew("%-11s" MEM_obs ", %s", name, ADDR_obs(offset, base, index, scale), 3910 XMMRegName(dst)); 3911 } 3912 } else { 3913 spew("%-11s" MEM_obs ", %s, %s", name, 3914 ADDR_obs(offset, base, index, scale), XMMRegName(src0), 3915 XMMRegName(dst)); 3916 } 3917 m_formatter.twoByteOpVex(ty, opcode, offset, base, index, scale, src0, dst); 3918 } 3919 twoByteOpSimd(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,const void * address,XMMRegisterID src0,XMMRegisterID dst)3920 void twoByteOpSimd(const char* name, VexOperandType ty, 3921 TwoByteOpcodeID opcode, const void* address, 3922 XMMRegisterID src0, XMMRegisterID dst) { 3923 if (useLegacySSEEncoding(src0, dst)) { 3924 if (IsXMMReversedOperands(opcode)) 3925 spew("%-11s%s, %p", legacySSEOpName(name), XMMRegName(dst), address); 3926 else 3927 spew("%-11s%p, %s", legacySSEOpName(name), address, XMMRegName(dst)); 3928 m_formatter.legacySSEPrefix(ty); 3929 m_formatter.twoByteOp(opcode, address, dst); 3930 return; 3931 } 3932 3933 if (src0 == invalid_xmm) { 3934 if (IsXMMReversedOperands(opcode)) 3935 spew("%-11s%s, %p", name, XMMRegName(dst), address); 3936 else 3937 spew("%-11s%p, %s", name, address, XMMRegName(dst)); 3938 } else { 3939 spew("%-11s%p, %s, %s", name, address, XMMRegName(src0), XMMRegName(dst)); 3940 } 3941 m_formatter.twoByteOpVex(ty, opcode, address, src0, dst); 3942 } 3943 twoByteOpImmSimd(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,uint32_t imm,const void * address,XMMRegisterID src0,XMMRegisterID dst)3944 void twoByteOpImmSimd(const char* name, VexOperandType ty, 3945 TwoByteOpcodeID opcode, uint32_t imm, 3946 const void* address, XMMRegisterID src0, 3947 XMMRegisterID dst) { 3948 if (useLegacySSEEncoding(src0, dst)) { 3949 spew("%-11s$0x%x, %p, %s", legacySSEOpName(name), imm, address, 3950 XMMRegName(dst)); 3951 m_formatter.legacySSEPrefix(ty); 3952 m_formatter.twoByteOp(opcode, address, dst); 3953 m_formatter.immediate8u(imm); 3954 return; 3955 } 3956 3957 spew("%-11s$0x%x, %p, %s, %s", name, imm, address, XMMRegName(src0), 3958 XMMRegName(dst)); 3959 m_formatter.twoByteOpVex(ty, opcode, address, src0, dst); 3960 m_formatter.immediate8u(imm); 3961 } 3962 twoByteOpInt32Simd(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,RegisterID rm,XMMRegisterID src0,XMMRegisterID dst)3963 void twoByteOpInt32Simd(const char* name, VexOperandType ty, 3964 TwoByteOpcodeID opcode, RegisterID rm, 3965 XMMRegisterID src0, XMMRegisterID dst) { 3966 if (useLegacySSEEncoding(src0, dst)) { 3967 if (IsXMMReversedOperands(opcode)) 3968 spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(dst), 3969 GPReg32Name(rm)); 3970 else 3971 spew("%-11s%s, %s", legacySSEOpName(name), GPReg32Name(rm), 3972 XMMRegName(dst)); 3973 m_formatter.legacySSEPrefix(ty); 3974 m_formatter.twoByteOp(opcode, rm, dst); 3975 return; 3976 } 3977 3978 if (src0 == invalid_xmm) { 3979 if (IsXMMReversedOperands(opcode)) 3980 spew("%-11s%s, %s", name, XMMRegName(dst), GPReg32Name(rm)); 3981 else 3982 spew("%-11s%s, %s", name, GPReg32Name(rm), XMMRegName(dst)); 3983 } else { 3984 spew("%-11s%s, %s, %s", name, GPReg32Name(rm), XMMRegName(src0), 3985 XMMRegName(dst)); 3986 } 3987 m_formatter.twoByteOpVex(ty, opcode, rm, src0, dst); 3988 } 3989 twoByteOpSimdInt32(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,XMMRegisterID rm,RegisterID dst)3990 void twoByteOpSimdInt32(const char* name, VexOperandType ty, 3991 TwoByteOpcodeID opcode, XMMRegisterID rm, 3992 RegisterID dst) { 3993 if (useLegacySSEEncodingForOtherOutput()) { 3994 if (IsXMMReversedOperands(opcode)) 3995 spew("%-11s%s, %s", legacySSEOpName(name), GPReg32Name(dst), 3996 XMMRegName(rm)); 3997 else if (opcode == OP2_MOVD_EdVd) 3998 spew("%-11s%s, %s", legacySSEOpName(name), 3999 XMMRegName((XMMRegisterID)dst), GPReg32Name((RegisterID)rm)); 4000 else 4001 spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(rm), 4002 GPReg32Name(dst)); 4003 m_formatter.legacySSEPrefix(ty); 4004 m_formatter.twoByteOp(opcode, (RegisterID)rm, dst); 4005 return; 4006 } 4007 4008 if (IsXMMReversedOperands(opcode)) 4009 spew("%-11s%s, %s", name, GPReg32Name(dst), XMMRegName(rm)); 4010 else if (opcode == OP2_MOVD_EdVd) 4011 spew("%-11s%s, %s", name, XMMRegName((XMMRegisterID)dst), 4012 GPReg32Name((RegisterID)rm)); 4013 else 4014 spew("%-11s%s, %s", name, XMMRegName(rm), GPReg32Name(dst)); 4015 m_formatter.twoByteOpVex(ty, opcode, (RegisterID)rm, invalid_xmm, dst); 4016 } 4017 twoByteOpImmSimdInt32(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,uint32_t imm,XMMRegisterID rm,RegisterID dst)4018 void twoByteOpImmSimdInt32(const char* name, VexOperandType ty, 4019 TwoByteOpcodeID opcode, uint32_t imm, 4020 XMMRegisterID rm, RegisterID dst) { 4021 if (useLegacySSEEncodingForOtherOutput()) { 4022 spew("%-11s$0x%x, %s, %s", legacySSEOpName(name), imm, XMMRegName(rm), 4023 GPReg32Name(dst)); 4024 m_formatter.legacySSEPrefix(ty); 4025 m_formatter.twoByteOp(opcode, (RegisterID)rm, dst); 4026 m_formatter.immediate8u(imm); 4027 return; 4028 } 4029 4030 spew("%-11s$0x%x, %s, %s", name, imm, XMMRegName(rm), GPReg32Name(dst)); 4031 m_formatter.twoByteOpVex(ty, opcode, (RegisterID)rm, invalid_xmm, dst); 4032 m_formatter.immediate8u(imm); 4033 } 4034 twoByteOpImmInt32Simd(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,uint32_t imm,RegisterID rm,XMMRegisterID src0,XMMRegisterID dst)4035 void twoByteOpImmInt32Simd(const char* name, VexOperandType ty, 4036 TwoByteOpcodeID opcode, uint32_t imm, 4037 RegisterID rm, XMMRegisterID src0, 4038 XMMRegisterID dst) { 4039 if (useLegacySSEEncodingForOtherOutput()) { 4040 spew("%-11s$0x%x, %s, %s", legacySSEOpName(name), imm, GPReg32Name(rm), 4041 XMMRegName(dst)); 4042 m_formatter.legacySSEPrefix(ty); 4043 m_formatter.twoByteOp(opcode, rm, dst); 4044 m_formatter.immediate8u(imm); 4045 return; 4046 } 4047 4048 spew("%-11s$0x%x, %s, %s", name, imm, GPReg32Name(rm), XMMRegName(dst)); 4049 m_formatter.twoByteOpVex(ty, opcode, rm, src0, dst); 4050 m_formatter.immediate8u(imm); 4051 } 4052 twoByteOpSimdFlags(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,XMMRegisterID rm,XMMRegisterID reg)4053 void twoByteOpSimdFlags(const char* name, VexOperandType ty, 4054 TwoByteOpcodeID opcode, XMMRegisterID rm, 4055 XMMRegisterID reg) { 4056 if (useLegacySSEEncodingForOtherOutput()) { 4057 spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(rm), 4058 XMMRegName(reg)); 4059 m_formatter.legacySSEPrefix(ty); 4060 m_formatter.twoByteOp(opcode, (RegisterID)rm, reg); 4061 return; 4062 } 4063 4064 spew("%-11s%s, %s", name, XMMRegName(rm), XMMRegName(reg)); 4065 m_formatter.twoByteOpVex(ty, opcode, (RegisterID)rm, invalid_xmm, 4066 (XMMRegisterID)reg); 4067 } 4068 twoByteOpSimdFlags(const char * name,VexOperandType ty,TwoByteOpcodeID opcode,int32_t offset,RegisterID base,XMMRegisterID reg)4069 void twoByteOpSimdFlags(const char* name, VexOperandType ty, 4070 TwoByteOpcodeID opcode, int32_t offset, 4071 RegisterID base, XMMRegisterID reg) { 4072 if (useLegacySSEEncodingForOtherOutput()) { 4073 spew("%-11s" MEM_ob ", %s", legacySSEOpName(name), ADDR_ob(offset, base), 4074 XMMRegName(reg)); 4075 m_formatter.legacySSEPrefix(ty); 4076 m_formatter.twoByteOp(opcode, offset, base, reg); 4077 return; 4078 } 4079 4080 spew("%-11s" MEM_ob ", %s", name, ADDR_ob(offset, base), XMMRegName(reg)); 4081 m_formatter.twoByteOpVex(ty, opcode, offset, base, invalid_xmm, 4082 (XMMRegisterID)reg); 4083 } 4084 threeByteOpSimd(const char * name,VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,XMMRegisterID rm,XMMRegisterID src0,XMMRegisterID dst)4085 void threeByteOpSimd(const char* name, VexOperandType ty, 4086 ThreeByteOpcodeID opcode, ThreeByteEscape escape, 4087 XMMRegisterID rm, XMMRegisterID src0, 4088 XMMRegisterID dst) { 4089 if (useLegacySSEEncoding(src0, dst)) { 4090 spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(rm), 4091 XMMRegName(dst)); 4092 m_formatter.legacySSEPrefix(ty); 4093 m_formatter.threeByteOp(opcode, escape, (RegisterID)rm, dst); 4094 return; 4095 } 4096 4097 spew("%-11s%s, %s, %s", name, XMMRegName(rm), XMMRegName(src0), 4098 XMMRegName(dst)); 4099 m_formatter.threeByteOpVex(ty, opcode, escape, (RegisterID)rm, src0, dst); 4100 } 4101 threeByteOpImmSimd(const char * name,VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,uint32_t imm,XMMRegisterID rm,XMMRegisterID src0,XMMRegisterID dst)4102 void threeByteOpImmSimd(const char* name, VexOperandType ty, 4103 ThreeByteOpcodeID opcode, ThreeByteEscape escape, 4104 uint32_t imm, XMMRegisterID rm, XMMRegisterID src0, 4105 XMMRegisterID dst) { 4106 if (useLegacySSEEncoding(src0, dst)) { 4107 spew("%-11s$0x%x, %s, %s", legacySSEOpName(name), imm, XMMRegName(rm), 4108 XMMRegName(dst)); 4109 m_formatter.legacySSEPrefix(ty); 4110 m_formatter.threeByteOp(opcode, escape, (RegisterID)rm, dst); 4111 m_formatter.immediate8u(imm); 4112 return; 4113 } 4114 4115 spew("%-11s$0x%x, %s, %s, %s", name, imm, XMMRegName(rm), XMMRegName(src0), 4116 XMMRegName(dst)); 4117 m_formatter.threeByteOpVex(ty, opcode, escape, (RegisterID)rm, src0, dst); 4118 m_formatter.immediate8u(imm); 4119 } 4120 threeByteOpSimd(const char * name,VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)4121 void threeByteOpSimd(const char* name, VexOperandType ty, 4122 ThreeByteOpcodeID opcode, ThreeByteEscape escape, 4123 int32_t offset, RegisterID base, XMMRegisterID src0, 4124 XMMRegisterID dst) { 4125 if (useLegacySSEEncoding(src0, dst)) { 4126 spew("%-11s" MEM_ob ", %s", legacySSEOpName(name), ADDR_ob(offset, base), 4127 XMMRegName(dst)); 4128 m_formatter.legacySSEPrefix(ty); 4129 m_formatter.threeByteOp(opcode, escape, offset, base, dst); 4130 return; 4131 } 4132 4133 spew("%-11s" MEM_ob ", %s, %s", name, ADDR_ob(offset, base), 4134 XMMRegName(src0), XMMRegName(dst)); 4135 m_formatter.threeByteOpVex(ty, opcode, escape, offset, base, src0, dst); 4136 } 4137 threeByteOpImmSimd(const char * name,VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,uint32_t imm,int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)4138 void threeByteOpImmSimd(const char* name, VexOperandType ty, 4139 ThreeByteOpcodeID opcode, ThreeByteEscape escape, 4140 uint32_t imm, int32_t offset, RegisterID base, 4141 XMMRegisterID src0, XMMRegisterID dst) { 4142 if (useLegacySSEEncoding(src0, dst)) { 4143 spew("%-11s$0x%x, " MEM_ob ", %s", legacySSEOpName(name), imm, 4144 ADDR_ob(offset, base), XMMRegName(dst)); 4145 m_formatter.legacySSEPrefix(ty); 4146 m_formatter.threeByteOp(opcode, escape, offset, base, dst); 4147 m_formatter.immediate8u(imm); 4148 return; 4149 } 4150 4151 spew("%-11s$0x%x, " MEM_ob ", %s, %s", name, imm, ADDR_ob(offset, base), 4152 XMMRegName(src0), XMMRegName(dst)); 4153 m_formatter.threeByteOpVex(ty, opcode, escape, offset, base, src0, dst); 4154 m_formatter.immediate8u(imm); 4155 } 4156 threeByteOpSimd(const char * name,VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,const void * address,XMMRegisterID src0,XMMRegisterID dst)4157 void threeByteOpSimd(const char* name, VexOperandType ty, 4158 ThreeByteOpcodeID opcode, ThreeByteEscape escape, 4159 const void* address, XMMRegisterID src0, 4160 XMMRegisterID dst) { 4161 if (useLegacySSEEncoding(src0, dst)) { 4162 spew("%-11s%p, %s", legacySSEOpName(name), address, XMMRegName(dst)); 4163 m_formatter.legacySSEPrefix(ty); 4164 m_formatter.threeByteOp(opcode, escape, address, dst); 4165 return; 4166 } 4167 4168 spew("%-11s%p, %s, %s", name, address, XMMRegName(src0), XMMRegName(dst)); 4169 m_formatter.threeByteOpVex(ty, opcode, escape, address, src0, dst); 4170 } 4171 threeByteOpImmInt32Simd(const char * name,VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,uint32_t imm,RegisterID src1,XMMRegisterID src0,XMMRegisterID dst)4172 void threeByteOpImmInt32Simd(const char* name, VexOperandType ty, 4173 ThreeByteOpcodeID opcode, ThreeByteEscape escape, 4174 uint32_t imm, RegisterID src1, 4175 XMMRegisterID src0, XMMRegisterID dst) { 4176 if (useLegacySSEEncoding(src0, dst)) { 4177 spew("%-11s$0x%x, %s, %s", legacySSEOpName(name), imm, GPReg32Name(src1), 4178 XMMRegName(dst)); 4179 m_formatter.legacySSEPrefix(ty); 4180 m_formatter.threeByteOp(opcode, escape, src1, dst); 4181 m_formatter.immediate8u(imm); 4182 return; 4183 } 4184 4185 spew("%-11s$0x%x, %s, %s, %s", name, imm, GPReg32Name(src1), 4186 XMMRegName(src0), XMMRegName(dst)); 4187 m_formatter.threeByteOpVex(ty, opcode, escape, src1, src0, dst); 4188 m_formatter.immediate8u(imm); 4189 } 4190 threeByteOpImmInt32Simd(const char * name,VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,uint32_t imm,int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)4191 void threeByteOpImmInt32Simd(const char* name, VexOperandType ty, 4192 ThreeByteOpcodeID opcode, ThreeByteEscape escape, 4193 uint32_t imm, int32_t offset, RegisterID base, 4194 XMMRegisterID src0, XMMRegisterID dst) { 4195 if (useLegacySSEEncoding(src0, dst)) { 4196 spew("%-11s$0x%x, " MEM_ob ", %s", legacySSEOpName(name), imm, 4197 ADDR_ob(offset, base), XMMRegName(dst)); 4198 m_formatter.legacySSEPrefix(ty); 4199 m_formatter.threeByteOp(opcode, escape, offset, base, dst); 4200 m_formatter.immediate8u(imm); 4201 return; 4202 } 4203 4204 spew("%-11s$0x%x, " MEM_ob ", %s, %s", name, imm, ADDR_ob(offset, base), 4205 XMMRegName(src0), XMMRegName(dst)); 4206 m_formatter.threeByteOpVex(ty, opcode, escape, offset, base, src0, dst); 4207 m_formatter.immediate8u(imm); 4208 } 4209 threeByteOpImmSimdInt32(const char * name,VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,uint32_t imm,XMMRegisterID src,RegisterID dst)4210 void threeByteOpImmSimdInt32(const char* name, VexOperandType ty, 4211 ThreeByteOpcodeID opcode, ThreeByteEscape escape, 4212 uint32_t imm, XMMRegisterID src, 4213 RegisterID dst) { 4214 if (useLegacySSEEncodingForOtherOutput()) { 4215 spew("%-11s$0x%x, %s, %s", legacySSEOpName(name), imm, XMMRegName(src), 4216 GPReg32Name(dst)); 4217 m_formatter.legacySSEPrefix(ty); 4218 m_formatter.threeByteOp(opcode, escape, (RegisterID)src, dst); 4219 m_formatter.immediate8u(imm); 4220 return; 4221 } 4222 4223 if (opcode == OP3_PEXTRD_EdVdqIb) 4224 spew("%-11s$0x%x, %s, %s", name, imm, XMMRegName((XMMRegisterID)dst), 4225 GPReg32Name((RegisterID)src)); 4226 else 4227 spew("%-11s$0x%x, %s, %s", name, imm, XMMRegName(src), GPReg32Name(dst)); 4228 m_formatter.threeByteOpVex(ty, opcode, escape, (RegisterID)src, invalid_xmm, 4229 dst); 4230 m_formatter.immediate8u(imm); 4231 } 4232 threeByteOpImmSimdInt32(const char * name,VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,uint32_t imm,int32_t offset,RegisterID base,RegisterID dst)4233 void threeByteOpImmSimdInt32(const char* name, VexOperandType ty, 4234 ThreeByteOpcodeID opcode, ThreeByteEscape escape, 4235 uint32_t imm, int32_t offset, RegisterID base, 4236 RegisterID dst) { 4237 if (useLegacySSEEncodingForOtherOutput()) { 4238 spew("%-11s$0x%x, " MEM_ob ", %s", legacySSEOpName(name), imm, 4239 ADDR_ob(offset, base), GPReg32Name(dst)); 4240 m_formatter.legacySSEPrefix(ty); 4241 m_formatter.threeByteOp(opcode, escape, offset, base, dst); 4242 m_formatter.immediate8u(imm); 4243 return; 4244 } 4245 4246 spew("%-11s$0x%x, " MEM_ob ", %s", name, imm, ADDR_ob(offset, base), 4247 GPReg32Name(dst)); 4248 m_formatter.threeByteOpVex(ty, opcode, escape, offset, base, invalid_xmm, 4249 dst); 4250 m_formatter.immediate8u(imm); 4251 } 4252 4253 // Blendv is a three-byte op, but the VEX encoding has a different opcode 4254 // than the SSE encoding, so we handle it specially. vblendvOpSimd(XMMRegisterID mask,XMMRegisterID rm,XMMRegisterID src0,XMMRegisterID dst)4255 void vblendvOpSimd(XMMRegisterID mask, XMMRegisterID rm, XMMRegisterID src0, 4256 XMMRegisterID dst) { 4257 if (useLegacySSEEncodingForVblendv(mask, src0, dst)) { 4258 spew("blendvps %s, %s", XMMRegName(rm), XMMRegName(dst)); 4259 // Even though a "ps" instruction, vblendv is encoded with the "pd" 4260 // prefix. 4261 m_formatter.legacySSEPrefix(VEX_PD); 4262 m_formatter.threeByteOp(OP3_BLENDVPS_VdqWdq, ESCAPE_3A, (RegisterID)rm, 4263 dst); 4264 return; 4265 } 4266 4267 spew("vblendvps %s, %s, %s, %s", XMMRegName(mask), XMMRegName(rm), 4268 XMMRegName(src0), XMMRegName(dst)); 4269 // Even though a "ps" instruction, vblendv is encoded with the "pd" prefix. 4270 m_formatter.vblendvOpVex(VEX_PD, OP3_VBLENDVPS_VdqWdq, ESCAPE_3A, mask, 4271 (RegisterID)rm, src0, dst); 4272 } 4273 vblendvOpSimd(XMMRegisterID mask,int32_t offset,RegisterID base,XMMRegisterID src0,XMMRegisterID dst)4274 void vblendvOpSimd(XMMRegisterID mask, int32_t offset, RegisterID base, 4275 XMMRegisterID src0, XMMRegisterID dst) { 4276 if (useLegacySSEEncodingForVblendv(mask, src0, dst)) { 4277 spew("blendvps " MEM_ob ", %s", ADDR_ob(offset, base), XMMRegName(dst)); 4278 // Even though a "ps" instruction, vblendv is encoded with the "pd" 4279 // prefix. 4280 m_formatter.legacySSEPrefix(VEX_PD); 4281 m_formatter.threeByteOp(OP3_BLENDVPS_VdqWdq, ESCAPE_3A, offset, base, 4282 dst); 4283 return; 4284 } 4285 4286 spew("vblendvps %s, " MEM_ob ", %s, %s", XMMRegName(mask), 4287 ADDR_ob(offset, base), XMMRegName(src0), XMMRegName(dst)); 4288 // Even though a "ps" instruction, vblendv is encoded with the "pd" prefix. 4289 m_formatter.vblendvOpVex(VEX_PD, OP3_VBLENDVPS_VdqWdq, ESCAPE_3A, mask, 4290 offset, base, src0, dst); 4291 } 4292 shiftOpImmSimd(const char * name,TwoByteOpcodeID opcode,ShiftID shiftKind,uint32_t imm,XMMRegisterID src,XMMRegisterID dst)4293 void shiftOpImmSimd(const char* name, TwoByteOpcodeID opcode, 4294 ShiftID shiftKind, uint32_t imm, XMMRegisterID src, 4295 XMMRegisterID dst) { 4296 if (useLegacySSEEncoding(src, dst)) { 4297 spew("%-11s$%d, %s", legacySSEOpName(name), imm, XMMRegName(dst)); 4298 m_formatter.legacySSEPrefix(VEX_PD); 4299 m_formatter.twoByteOp(opcode, (RegisterID)dst, (int)shiftKind); 4300 m_formatter.immediate8u(imm); 4301 return; 4302 } 4303 4304 spew("%-11s$%d, %s, %s", name, imm, XMMRegName(src), XMMRegName(dst)); 4305 m_formatter.twoByteOpVex(VEX_PD, opcode, (RegisterID)dst, src, 4306 (int)shiftKind); 4307 m_formatter.immediate8u(imm); 4308 } 4309 4310 class X86InstructionFormatter { 4311 public: 4312 // Legacy prefix bytes: 4313 // 4314 // These are emmitted prior to the instruction. 4315 prefix(OneByteOpcodeID pre)4316 void prefix(OneByteOpcodeID pre) { m_buffer.putByte(pre); } 4317 legacySSEPrefix(VexOperandType ty)4318 void legacySSEPrefix(VexOperandType ty) { 4319 switch (ty) { 4320 case VEX_PS: 4321 break; 4322 case VEX_PD: 4323 prefix(PRE_SSE_66); 4324 break; 4325 case VEX_SS: 4326 prefix(PRE_SSE_F3); 4327 break; 4328 case VEX_SD: 4329 prefix(PRE_SSE_F2); 4330 break; 4331 } 4332 } 4333 4334 /* clang-format off */ 4335 // 4336 // Word-sized operands / no operand instruction formatters. 4337 // 4338 // In addition to the opcode, the following operand permutations are supported: 4339 // * None - instruction takes no operands. 4340 // * One register - the low three bits of the RegisterID are added into the opcode. 4341 // * Two registers - encode a register form ModRm (for all ModRm formats, the reg field is passed first, and a GroupOpcodeID may be passed in its place). 4342 // * Three argument ModRM - a register, and a register and an offset describing a memory operand. 4343 // * Five argument ModRM - a register, and a base register, an index, scale, and offset describing a memory operand. 4344 // 4345 // For 32-bit x86 targets, the address operand may also be provided as a 4346 // void*. On 64-bit targets REX prefixes will be planted as necessary, 4347 // where high numbered registers are used. 4348 // 4349 // The twoByteOp methods plant two-byte Intel instructions sequences 4350 // (first opcode byte 0x0F). 4351 // 4352 /* clang-format on */ 4353 oneByteOp(OneByteOpcodeID opcode)4354 void oneByteOp(OneByteOpcodeID opcode) { 4355 m_buffer.ensureSpace(MaxInstructionSize); 4356 m_buffer.putByteUnchecked(opcode); 4357 } 4358 oneByteOp(OneByteOpcodeID opcode,RegisterID reg)4359 void oneByteOp(OneByteOpcodeID opcode, RegisterID reg) { 4360 m_buffer.ensureSpace(MaxInstructionSize); 4361 emitRexIfNeeded(0, 0, reg); 4362 m_buffer.putByteUnchecked(opcode + (reg & 7)); 4363 } 4364 oneByteOp(OneByteOpcodeID opcode,RegisterID rm,int reg)4365 void oneByteOp(OneByteOpcodeID opcode, RegisterID rm, int reg) { 4366 m_buffer.ensureSpace(MaxInstructionSize); 4367 emitRexIfNeeded(reg, 0, rm); 4368 m_buffer.putByteUnchecked(opcode); 4369 registerModRM(rm, reg); 4370 } 4371 oneByteOp(OneByteOpcodeID opcode,int32_t offset,RegisterID base,int reg)4372 void oneByteOp(OneByteOpcodeID opcode, int32_t offset, RegisterID base, 4373 int reg) { 4374 m_buffer.ensureSpace(MaxInstructionSize); 4375 emitRexIfNeeded(reg, 0, base); 4376 m_buffer.putByteUnchecked(opcode); 4377 memoryModRM(offset, base, reg); 4378 } 4379 oneByteOp_disp32(OneByteOpcodeID opcode,int32_t offset,RegisterID base,int reg)4380 void oneByteOp_disp32(OneByteOpcodeID opcode, int32_t offset, 4381 RegisterID base, int reg) { 4382 m_buffer.ensureSpace(MaxInstructionSize); 4383 emitRexIfNeeded(reg, 0, base); 4384 m_buffer.putByteUnchecked(opcode); 4385 memoryModRM_disp32(offset, base, reg); 4386 } 4387 oneByteOp(OneByteOpcodeID opcode,int32_t offset,RegisterID base,RegisterID index,int scale,int reg)4388 void oneByteOp(OneByteOpcodeID opcode, int32_t offset, RegisterID base, 4389 RegisterID index, int scale, int reg) { 4390 m_buffer.ensureSpace(MaxInstructionSize); 4391 emitRexIfNeeded(reg, index, base); 4392 m_buffer.putByteUnchecked(opcode); 4393 memoryModRM(offset, base, index, scale, reg); 4394 } 4395 oneByteOp_disp32(OneByteOpcodeID opcode,int32_t offset,RegisterID index,int scale,int reg)4396 void oneByteOp_disp32(OneByteOpcodeID opcode, int32_t offset, 4397 RegisterID index, int scale, int reg) { 4398 m_buffer.ensureSpace(MaxInstructionSize); 4399 emitRexIfNeeded(reg, index, 0); 4400 m_buffer.putByteUnchecked(opcode); 4401 memoryModRM_disp32(offset, index, scale, reg); 4402 } 4403 oneByteOp(OneByteOpcodeID opcode,const void * address,int reg)4404 void oneByteOp(OneByteOpcodeID opcode, const void* address, int reg) { 4405 m_buffer.ensureSpace(MaxInstructionSize); 4406 emitRexIfNeeded(reg, 0, 0); 4407 m_buffer.putByteUnchecked(opcode); 4408 memoryModRM_disp32(address, reg); 4409 } 4410 oneByteOp_disp32(OneByteOpcodeID opcode,const void * address,int reg)4411 void oneByteOp_disp32(OneByteOpcodeID opcode, const void* address, 4412 int reg) { 4413 m_buffer.ensureSpace(MaxInstructionSize); 4414 emitRexIfNeeded(reg, 0, 0); 4415 m_buffer.putByteUnchecked(opcode); 4416 memoryModRM_disp32(address, reg); 4417 } 4418 #ifdef JS_CODEGEN_X64 oneByteRipOp(OneByteOpcodeID opcode,int ripOffset,int reg)4419 void oneByteRipOp(OneByteOpcodeID opcode, int ripOffset, int reg) { 4420 m_buffer.ensureSpace(MaxInstructionSize); 4421 emitRexIfNeeded(reg, 0, 0); 4422 m_buffer.putByteUnchecked(opcode); 4423 putModRm(ModRmMemoryNoDisp, noBase, reg); 4424 m_buffer.putIntUnchecked(ripOffset); 4425 } 4426 oneByteRipOp64(OneByteOpcodeID opcode,int ripOffset,int reg)4427 void oneByteRipOp64(OneByteOpcodeID opcode, int ripOffset, int reg) { 4428 m_buffer.ensureSpace(MaxInstructionSize); 4429 emitRexW(reg, 0, 0); 4430 m_buffer.putByteUnchecked(opcode); 4431 putModRm(ModRmMemoryNoDisp, noBase, reg); 4432 m_buffer.putIntUnchecked(ripOffset); 4433 } 4434 twoByteRipOp(TwoByteOpcodeID opcode,int ripOffset,int reg)4435 void twoByteRipOp(TwoByteOpcodeID opcode, int ripOffset, int reg) { 4436 m_buffer.ensureSpace(MaxInstructionSize); 4437 emitRexIfNeeded(reg, 0, 0); 4438 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4439 m_buffer.putByteUnchecked(opcode); 4440 putModRm(ModRmMemoryNoDisp, noBase, reg); 4441 m_buffer.putIntUnchecked(ripOffset); 4442 } 4443 twoByteRipOpVex(VexOperandType ty,TwoByteOpcodeID opcode,int ripOffset,XMMRegisterID src0,XMMRegisterID reg)4444 void twoByteRipOpVex(VexOperandType ty, TwoByteOpcodeID opcode, 4445 int ripOffset, XMMRegisterID src0, XMMRegisterID reg) { 4446 int r = (reg >> 3), x = 0, b = 0; 4447 int m = 1; // 0x0F 4448 int w = 0, v = src0, l = 0; 4449 threeOpVex(ty, r, x, b, m, w, v, l, opcode); 4450 putModRm(ModRmMemoryNoDisp, noBase, reg); 4451 m_buffer.putIntUnchecked(ripOffset); 4452 } 4453 #endif 4454 twoByteOp(TwoByteOpcodeID opcode)4455 void twoByteOp(TwoByteOpcodeID opcode) { 4456 m_buffer.ensureSpace(MaxInstructionSize); 4457 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4458 m_buffer.putByteUnchecked(opcode); 4459 } 4460 twoByteOp(TwoByteOpcodeID opcode,RegisterID rm,int reg)4461 void twoByteOp(TwoByteOpcodeID opcode, RegisterID rm, int reg) { 4462 m_buffer.ensureSpace(MaxInstructionSize); 4463 emitRexIfNeeded(reg, 0, rm); 4464 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4465 m_buffer.putByteUnchecked(opcode); 4466 registerModRM(rm, reg); 4467 } 4468 twoByteOpVex(VexOperandType ty,TwoByteOpcodeID opcode,RegisterID rm,XMMRegisterID src0,int reg)4469 void twoByteOpVex(VexOperandType ty, TwoByteOpcodeID opcode, RegisterID rm, 4470 XMMRegisterID src0, int reg) { 4471 int r = (reg >> 3), x = 0, b = (rm >> 3); 4472 int m = 1; // 0x0F 4473 int w = 0, v = src0, l = 0; 4474 threeOpVex(ty, r, x, b, m, w, v, l, opcode); 4475 registerModRM(rm, reg); 4476 } 4477 twoByteOp(TwoByteOpcodeID opcode,int32_t offset,RegisterID base,int reg)4478 void twoByteOp(TwoByteOpcodeID opcode, int32_t offset, RegisterID base, 4479 int reg) { 4480 m_buffer.ensureSpace(MaxInstructionSize); 4481 emitRexIfNeeded(reg, 0, base); 4482 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4483 m_buffer.putByteUnchecked(opcode); 4484 memoryModRM(offset, base, reg); 4485 } 4486 twoByteOpVex(VexOperandType ty,TwoByteOpcodeID opcode,int32_t offset,RegisterID base,XMMRegisterID src0,int reg)4487 void twoByteOpVex(VexOperandType ty, TwoByteOpcodeID opcode, int32_t offset, 4488 RegisterID base, XMMRegisterID src0, int reg) { 4489 int r = (reg >> 3), x = 0, b = (base >> 3); 4490 int m = 1; // 0x0F 4491 int w = 0, v = src0, l = 0; 4492 threeOpVex(ty, r, x, b, m, w, v, l, opcode); 4493 memoryModRM(offset, base, reg); 4494 } 4495 twoByteOp_disp32(TwoByteOpcodeID opcode,int32_t offset,RegisterID base,int reg)4496 void twoByteOp_disp32(TwoByteOpcodeID opcode, int32_t offset, 4497 RegisterID base, int reg) { 4498 m_buffer.ensureSpace(MaxInstructionSize); 4499 emitRexIfNeeded(reg, 0, base); 4500 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4501 m_buffer.putByteUnchecked(opcode); 4502 memoryModRM_disp32(offset, base, reg); 4503 } 4504 twoByteOpVex_disp32(VexOperandType ty,TwoByteOpcodeID opcode,int32_t offset,RegisterID base,XMMRegisterID src0,int reg)4505 void twoByteOpVex_disp32(VexOperandType ty, TwoByteOpcodeID opcode, 4506 int32_t offset, RegisterID base, 4507 XMMRegisterID src0, int reg) { 4508 int r = (reg >> 3), x = 0, b = (base >> 3); 4509 int m = 1; // 0x0F 4510 int w = 0, v = src0, l = 0; 4511 threeOpVex(ty, r, x, b, m, w, v, l, opcode); 4512 memoryModRM_disp32(offset, base, reg); 4513 } 4514 twoByteOp(TwoByteOpcodeID opcode,int32_t offset,RegisterID base,RegisterID index,int scale,int reg)4515 void twoByteOp(TwoByteOpcodeID opcode, int32_t offset, RegisterID base, 4516 RegisterID index, int scale, int reg) { 4517 m_buffer.ensureSpace(MaxInstructionSize); 4518 emitRexIfNeeded(reg, index, base); 4519 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4520 m_buffer.putByteUnchecked(opcode); 4521 memoryModRM(offset, base, index, scale, reg); 4522 } 4523 twoByteOpVex(VexOperandType ty,TwoByteOpcodeID opcode,int32_t offset,RegisterID base,RegisterID index,int scale,XMMRegisterID src0,int reg)4524 void twoByteOpVex(VexOperandType ty, TwoByteOpcodeID opcode, int32_t offset, 4525 RegisterID base, RegisterID index, int scale, 4526 XMMRegisterID src0, int reg) { 4527 int r = (reg >> 3), x = (index >> 3), b = (base >> 3); 4528 int m = 1; // 0x0F 4529 int w = 0, v = src0, l = 0; 4530 threeOpVex(ty, r, x, b, m, w, v, l, opcode); 4531 memoryModRM(offset, base, index, scale, reg); 4532 } 4533 twoByteOp(TwoByteOpcodeID opcode,const void * address,int reg)4534 void twoByteOp(TwoByteOpcodeID opcode, const void* address, int reg) { 4535 m_buffer.ensureSpace(MaxInstructionSize); 4536 emitRexIfNeeded(reg, 0, 0); 4537 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4538 m_buffer.putByteUnchecked(opcode); 4539 memoryModRM(address, reg); 4540 } 4541 twoByteOpVex(VexOperandType ty,TwoByteOpcodeID opcode,const void * address,XMMRegisterID src0,int reg)4542 void twoByteOpVex(VexOperandType ty, TwoByteOpcodeID opcode, 4543 const void* address, XMMRegisterID src0, int reg) { 4544 int r = (reg >> 3), x = 0, b = 0; 4545 int m = 1; // 0x0F 4546 int w = 0, v = src0, l = 0; 4547 threeOpVex(ty, r, x, b, m, w, v, l, opcode); 4548 memoryModRM(address, reg); 4549 } 4550 threeByteOp(ThreeByteOpcodeID opcode,ThreeByteEscape escape,RegisterID rm,int reg)4551 void threeByteOp(ThreeByteOpcodeID opcode, ThreeByteEscape escape, 4552 RegisterID rm, int reg) { 4553 m_buffer.ensureSpace(MaxInstructionSize); 4554 emitRexIfNeeded(reg, 0, rm); 4555 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4556 m_buffer.putByteUnchecked(escape); 4557 m_buffer.putByteUnchecked(opcode); 4558 registerModRM(rm, reg); 4559 } 4560 threeByteOpVex(VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,RegisterID rm,XMMRegisterID src0,int reg)4561 void threeByteOpVex(VexOperandType ty, ThreeByteOpcodeID opcode, 4562 ThreeByteEscape escape, RegisterID rm, 4563 XMMRegisterID src0, int reg) { 4564 int r = (reg >> 3), x = 0, b = (rm >> 3); 4565 int m = 0, w = 0, v = src0, l = 0; 4566 switch (escape) { 4567 case ESCAPE_38: 4568 m = 2; 4569 break; 4570 case ESCAPE_3A: 4571 m = 3; 4572 break; 4573 default: 4574 MOZ_CRASH("unexpected escape"); 4575 } 4576 threeOpVex(ty, r, x, b, m, w, v, l, opcode); 4577 registerModRM(rm, reg); 4578 } 4579 threeByteOp(ThreeByteOpcodeID opcode,ThreeByteEscape escape,int32_t offset,RegisterID base,int reg)4580 void threeByteOp(ThreeByteOpcodeID opcode, ThreeByteEscape escape, 4581 int32_t offset, RegisterID base, int reg) { 4582 m_buffer.ensureSpace(MaxInstructionSize); 4583 emitRexIfNeeded(reg, 0, base); 4584 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4585 m_buffer.putByteUnchecked(escape); 4586 m_buffer.putByteUnchecked(opcode); 4587 memoryModRM(offset, base, reg); 4588 } 4589 threeByteOpVex(VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,int32_t offset,RegisterID base,XMMRegisterID src0,int reg)4590 void threeByteOpVex(VexOperandType ty, ThreeByteOpcodeID opcode, 4591 ThreeByteEscape escape, int32_t offset, RegisterID base, 4592 XMMRegisterID src0, int reg) { 4593 int r = (reg >> 3), x = 0, b = (base >> 3); 4594 int m = 0, w = 0, v = src0, l = 0; 4595 switch (escape) { 4596 case ESCAPE_38: 4597 m = 2; 4598 break; 4599 case ESCAPE_3A: 4600 m = 3; 4601 break; 4602 default: 4603 MOZ_CRASH("unexpected escape"); 4604 } 4605 threeOpVex(ty, r, x, b, m, w, v, l, opcode); 4606 memoryModRM(offset, base, reg); 4607 } 4608 threeByteOp(ThreeByteOpcodeID opcode,ThreeByteEscape escape,const void * address,int reg)4609 void threeByteOp(ThreeByteOpcodeID opcode, ThreeByteEscape escape, 4610 const void* address, int reg) { 4611 m_buffer.ensureSpace(MaxInstructionSize); 4612 emitRexIfNeeded(reg, 0, 0); 4613 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4614 m_buffer.putByteUnchecked(escape); 4615 m_buffer.putByteUnchecked(opcode); 4616 memoryModRM(address, reg); 4617 } 4618 threeByteOpVex(VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,const void * address,XMMRegisterID src0,int reg)4619 void threeByteOpVex(VexOperandType ty, ThreeByteOpcodeID opcode, 4620 ThreeByteEscape escape, const void* address, 4621 XMMRegisterID src0, int reg) { 4622 int r = (reg >> 3), x = 0, b = 0; 4623 int m = 0, w = 0, v = src0, l = 0; 4624 switch (escape) { 4625 case ESCAPE_38: 4626 m = 2; 4627 break; 4628 case ESCAPE_3A: 4629 m = 3; 4630 break; 4631 default: 4632 MOZ_CRASH("unexpected escape"); 4633 } 4634 threeOpVex(ty, r, x, b, m, w, v, l, opcode); 4635 memoryModRM(address, reg); 4636 } 4637 vblendvOpVex(VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,XMMRegisterID mask,RegisterID rm,XMMRegisterID src0,int reg)4638 void vblendvOpVex(VexOperandType ty, ThreeByteOpcodeID opcode, 4639 ThreeByteEscape escape, XMMRegisterID mask, RegisterID rm, 4640 XMMRegisterID src0, int reg) { 4641 int r = (reg >> 3), x = 0, b = (rm >> 3); 4642 int m = 0, w = 0, v = src0, l = 0; 4643 switch (escape) { 4644 case ESCAPE_38: 4645 m = 2; 4646 break; 4647 case ESCAPE_3A: 4648 m = 3; 4649 break; 4650 default: 4651 MOZ_CRASH("unexpected escape"); 4652 } 4653 threeOpVex(ty, r, x, b, m, w, v, l, opcode); 4654 registerModRM(rm, reg); 4655 immediate8u(mask << 4); 4656 } 4657 vblendvOpVex(VexOperandType ty,ThreeByteOpcodeID opcode,ThreeByteEscape escape,XMMRegisterID mask,int32_t offset,RegisterID base,XMMRegisterID src0,int reg)4658 void vblendvOpVex(VexOperandType ty, ThreeByteOpcodeID opcode, 4659 ThreeByteEscape escape, XMMRegisterID mask, 4660 int32_t offset, RegisterID base, XMMRegisterID src0, 4661 int reg) { 4662 int r = (reg >> 3), x = 0, b = (base >> 3); 4663 int m = 0, w = 0, v = src0, l = 0; 4664 switch (escape) { 4665 case ESCAPE_38: 4666 m = 2; 4667 break; 4668 case ESCAPE_3A: 4669 m = 3; 4670 break; 4671 default: 4672 MOZ_CRASH("unexpected escape"); 4673 } 4674 threeOpVex(ty, r, x, b, m, w, v, l, opcode); 4675 memoryModRM(offset, base, reg); 4676 immediate8u(mask << 4); 4677 } 4678 4679 #ifdef JS_CODEGEN_X64 4680 // Quad-word-sized operands: 4681 // 4682 // Used to format 64-bit operantions, planting a REX.w prefix. When 4683 // planting d64 or f64 instructions, not requiring a REX.w prefix, the 4684 // normal (non-'64'-postfixed) formatters should be used. 4685 oneByteOp64(OneByteOpcodeID opcode)4686 void oneByteOp64(OneByteOpcodeID opcode) { 4687 m_buffer.ensureSpace(MaxInstructionSize); 4688 emitRexW(0, 0, 0); 4689 m_buffer.putByteUnchecked(opcode); 4690 } 4691 oneByteOp64(OneByteOpcodeID opcode,RegisterID reg)4692 void oneByteOp64(OneByteOpcodeID opcode, RegisterID reg) { 4693 m_buffer.ensureSpace(MaxInstructionSize); 4694 emitRexW(0, 0, reg); 4695 m_buffer.putByteUnchecked(opcode + (reg & 7)); 4696 } 4697 oneByteOp64(OneByteOpcodeID opcode,RegisterID rm,int reg)4698 void oneByteOp64(OneByteOpcodeID opcode, RegisterID rm, int reg) { 4699 m_buffer.ensureSpace(MaxInstructionSize); 4700 emitRexW(reg, 0, rm); 4701 m_buffer.putByteUnchecked(opcode); 4702 registerModRM(rm, reg); 4703 } 4704 oneByteOp64(OneByteOpcodeID opcode,int32_t offset,RegisterID base,int reg)4705 void oneByteOp64(OneByteOpcodeID opcode, int32_t offset, RegisterID base, 4706 int reg) { 4707 m_buffer.ensureSpace(MaxInstructionSize); 4708 emitRexW(reg, 0, base); 4709 m_buffer.putByteUnchecked(opcode); 4710 memoryModRM(offset, base, reg); 4711 } 4712 oneByteOp64_disp32(OneByteOpcodeID opcode,int32_t offset,RegisterID base,int reg)4713 void oneByteOp64_disp32(OneByteOpcodeID opcode, int32_t offset, 4714 RegisterID base, int reg) { 4715 m_buffer.ensureSpace(MaxInstructionSize); 4716 emitRexW(reg, 0, base); 4717 m_buffer.putByteUnchecked(opcode); 4718 memoryModRM_disp32(offset, base, reg); 4719 } 4720 oneByteOp64(OneByteOpcodeID opcode,int32_t offset,RegisterID base,RegisterID index,int scale,int reg)4721 void oneByteOp64(OneByteOpcodeID opcode, int32_t offset, RegisterID base, 4722 RegisterID index, int scale, int reg) { 4723 m_buffer.ensureSpace(MaxInstructionSize); 4724 emitRexW(reg, index, base); 4725 m_buffer.putByteUnchecked(opcode); 4726 memoryModRM(offset, base, index, scale, reg); 4727 } 4728 oneByteOp64(OneByteOpcodeID opcode,const void * address,int reg)4729 void oneByteOp64(OneByteOpcodeID opcode, const void* address, int reg) { 4730 m_buffer.ensureSpace(MaxInstructionSize); 4731 emitRexW(reg, 0, 0); 4732 m_buffer.putByteUnchecked(opcode); 4733 memoryModRM(address, reg); 4734 } 4735 twoByteOp64(TwoByteOpcodeID opcode,RegisterID rm,int reg)4736 void twoByteOp64(TwoByteOpcodeID opcode, RegisterID rm, int reg) { 4737 m_buffer.ensureSpace(MaxInstructionSize); 4738 emitRexW(reg, 0, rm); 4739 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4740 m_buffer.putByteUnchecked(opcode); 4741 registerModRM(rm, reg); 4742 } 4743 twoByteOp64(TwoByteOpcodeID opcode,int offset,RegisterID base,int reg)4744 void twoByteOp64(TwoByteOpcodeID opcode, int offset, RegisterID base, 4745 int reg) { 4746 m_buffer.ensureSpace(MaxInstructionSize); 4747 emitRexW(reg, 0, base); 4748 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4749 m_buffer.putByteUnchecked(opcode); 4750 memoryModRM(offset, base, reg); 4751 } 4752 twoByteOp64(TwoByteOpcodeID opcode,int offset,RegisterID base,RegisterID index,int scale,int reg)4753 void twoByteOp64(TwoByteOpcodeID opcode, int offset, RegisterID base, 4754 RegisterID index, int scale, int reg) { 4755 m_buffer.ensureSpace(MaxInstructionSize); 4756 emitRexW(reg, index, base); 4757 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4758 m_buffer.putByteUnchecked(opcode); 4759 memoryModRM(offset, base, index, scale, reg); 4760 } 4761 twoByteOp64(TwoByteOpcodeID opcode,const void * address,int reg)4762 void twoByteOp64(TwoByteOpcodeID opcode, const void* address, int reg) { 4763 m_buffer.ensureSpace(MaxInstructionSize); 4764 emitRexW(reg, 0, 0); 4765 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4766 m_buffer.putByteUnchecked(opcode); 4767 memoryModRM(address, reg); 4768 } 4769 twoByteOpVex64(VexOperandType ty,TwoByteOpcodeID opcode,RegisterID rm,XMMRegisterID src0,XMMRegisterID reg)4770 void twoByteOpVex64(VexOperandType ty, TwoByteOpcodeID opcode, 4771 RegisterID rm, XMMRegisterID src0, XMMRegisterID reg) { 4772 int r = (reg >> 3), x = 0, b = (rm >> 3); 4773 int m = 1; // 0x0F 4774 int w = 1, v = src0, l = 0; 4775 threeOpVex(ty, r, x, b, m, w, v, l, opcode); 4776 registerModRM(rm, reg); 4777 } 4778 #endif 4779 4780 // Byte-operands: 4781 // 4782 // These methods format byte operations. Byte operations differ from 4783 // the normal formatters in the circumstances under which they will 4784 // decide to emit REX prefixes. These should be used where any register 4785 // operand signifies a byte register. 4786 // 4787 // The disctinction is due to the handling of register numbers in the 4788 // range 4..7 on x86-64. These register numbers may either represent 4789 // the second byte of the first four registers (ah..bh) or the first 4790 // byte of the second four registers (spl..dil). 4791 // 4792 // Address operands should still be checked using regRequiresRex(), 4793 // while byteRegRequiresRex() is provided to check byte register 4794 // operands. 4795 oneByteOp8(OneByteOpcodeID opcode)4796 void oneByteOp8(OneByteOpcodeID opcode) { 4797 m_buffer.ensureSpace(MaxInstructionSize); 4798 m_buffer.putByteUnchecked(opcode); 4799 } 4800 oneByteOp8(OneByteOpcodeID opcode,RegisterID r)4801 void oneByteOp8(OneByteOpcodeID opcode, RegisterID r) { 4802 m_buffer.ensureSpace(MaxInstructionSize); 4803 emitRexIf(byteRegRequiresRex(r), 0, 0, r); 4804 m_buffer.putByteUnchecked(opcode + (r & 7)); 4805 } 4806 oneByteOp8(OneByteOpcodeID opcode,RegisterID rm,GroupOpcodeID groupOp)4807 void oneByteOp8(OneByteOpcodeID opcode, RegisterID rm, 4808 GroupOpcodeID groupOp) { 4809 m_buffer.ensureSpace(MaxInstructionSize); 4810 emitRexIf(byteRegRequiresRex(rm), 0, 0, rm); 4811 m_buffer.putByteUnchecked(opcode); 4812 registerModRM(rm, groupOp); 4813 } 4814 4815 // Like oneByteOp8, but never emits a REX prefix. oneByteOp8_norex(OneByteOpcodeID opcode,HRegisterID rm,GroupOpcodeID groupOp)4816 void oneByteOp8_norex(OneByteOpcodeID opcode, HRegisterID rm, 4817 GroupOpcodeID groupOp) { 4818 MOZ_ASSERT(!regRequiresRex(RegisterID(rm))); 4819 m_buffer.ensureSpace(MaxInstructionSize); 4820 m_buffer.putByteUnchecked(opcode); 4821 registerModRM(RegisterID(rm), groupOp); 4822 } 4823 oneByteOp8(OneByteOpcodeID opcode,int32_t offset,RegisterID base,RegisterID reg)4824 void oneByteOp8(OneByteOpcodeID opcode, int32_t offset, RegisterID base, 4825 RegisterID reg) { 4826 m_buffer.ensureSpace(MaxInstructionSize); 4827 emitRexIf(byteRegRequiresRex(reg), reg, 0, base); 4828 m_buffer.putByteUnchecked(opcode); 4829 memoryModRM(offset, base, reg); 4830 } 4831 oneByteOp8_disp32(OneByteOpcodeID opcode,int32_t offset,RegisterID base,RegisterID reg)4832 void oneByteOp8_disp32(OneByteOpcodeID opcode, int32_t offset, 4833 RegisterID base, RegisterID reg) { 4834 m_buffer.ensureSpace(MaxInstructionSize); 4835 emitRexIf(byteRegRequiresRex(reg), reg, 0, base); 4836 m_buffer.putByteUnchecked(opcode); 4837 memoryModRM_disp32(offset, base, reg); 4838 } 4839 oneByteOp8(OneByteOpcodeID opcode,int32_t offset,RegisterID base,RegisterID index,int scale,RegisterID reg)4840 void oneByteOp8(OneByteOpcodeID opcode, int32_t offset, RegisterID base, 4841 RegisterID index, int scale, RegisterID reg) { 4842 m_buffer.ensureSpace(MaxInstructionSize); 4843 emitRexIf(byteRegRequiresRex(reg), reg, index, base); 4844 m_buffer.putByteUnchecked(opcode); 4845 memoryModRM(offset, base, index, scale, reg); 4846 } 4847 oneByteOp8(OneByteOpcodeID opcode,const void * address,RegisterID reg)4848 void oneByteOp8(OneByteOpcodeID opcode, const void* address, 4849 RegisterID reg) { 4850 m_buffer.ensureSpace(MaxInstructionSize); 4851 emitRexIf(byteRegRequiresRex(reg), reg, 0, 0); 4852 m_buffer.putByteUnchecked(opcode); 4853 memoryModRM_disp32(address, reg); 4854 } 4855 twoByteOp8(TwoByteOpcodeID opcode,RegisterID rm,RegisterID reg)4856 void twoByteOp8(TwoByteOpcodeID opcode, RegisterID rm, RegisterID reg) { 4857 m_buffer.ensureSpace(MaxInstructionSize); 4858 emitRexIf(byteRegRequiresRex(reg) | byteRegRequiresRex(rm), reg, 0, rm); 4859 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4860 m_buffer.putByteUnchecked(opcode); 4861 registerModRM(rm, reg); 4862 } 4863 twoByteOp8(TwoByteOpcodeID opcode,int32_t offset,RegisterID base,RegisterID reg)4864 void twoByteOp8(TwoByteOpcodeID opcode, int32_t offset, RegisterID base, 4865 RegisterID reg) { 4866 m_buffer.ensureSpace(MaxInstructionSize); 4867 emitRexIf(byteRegRequiresRex(reg) | regRequiresRex(base), reg, 0, base); 4868 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4869 m_buffer.putByteUnchecked(opcode); 4870 memoryModRM(offset, base, reg); 4871 } 4872 twoByteOp8(TwoByteOpcodeID opcode,int32_t offset,RegisterID base,RegisterID index,int scale,RegisterID reg)4873 void twoByteOp8(TwoByteOpcodeID opcode, int32_t offset, RegisterID base, 4874 RegisterID index, int scale, RegisterID reg) { 4875 m_buffer.ensureSpace(MaxInstructionSize); 4876 emitRexIf(byteRegRequiresRex(reg) | regRequiresRex(base) | 4877 regRequiresRex(index), 4878 reg, index, base); 4879 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4880 m_buffer.putByteUnchecked(opcode); 4881 memoryModRM(offset, base, index, scale, reg); 4882 } 4883 4884 // Like twoByteOp8 but doesn't add a REX prefix if the destination reg 4885 // is in esp..edi. This may be used when the destination is not an 8-bit 4886 // register (as in a movzbl instruction), so it doesn't need a REX 4887 // prefix to disambiguate it from ah..bh. twoByteOp8_movx(TwoByteOpcodeID opcode,RegisterID rm,RegisterID reg)4888 void twoByteOp8_movx(TwoByteOpcodeID opcode, RegisterID rm, 4889 RegisterID reg) { 4890 m_buffer.ensureSpace(MaxInstructionSize); 4891 emitRexIf(regRequiresRex(reg) | byteRegRequiresRex(rm), reg, 0, rm); 4892 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4893 m_buffer.putByteUnchecked(opcode); 4894 registerModRM(rm, reg); 4895 } 4896 twoByteOp8(TwoByteOpcodeID opcode,RegisterID rm,GroupOpcodeID groupOp)4897 void twoByteOp8(TwoByteOpcodeID opcode, RegisterID rm, 4898 GroupOpcodeID groupOp) { 4899 m_buffer.ensureSpace(MaxInstructionSize); 4900 emitRexIf(byteRegRequiresRex(rm), 0, 0, rm); 4901 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE); 4902 m_buffer.putByteUnchecked(opcode); 4903 registerModRM(rm, groupOp); 4904 } 4905 4906 // Immediates: 4907 // 4908 // An immedaite should be appended where appropriate after an op has 4909 // been emitted. The writes are unchecked since the opcode formatters 4910 // above will have ensured space. 4911 4912 // A signed 8-bit immediate. immediate8s(int32_t imm)4913 MOZ_ALWAYS_INLINE void immediate8s(int32_t imm) { 4914 MOZ_ASSERT(CAN_SIGN_EXTEND_8_32(imm)); 4915 m_buffer.putByteUnchecked(imm); 4916 } 4917 4918 // An unsigned 8-bit immediate. immediate8u(uint32_t imm)4919 MOZ_ALWAYS_INLINE void immediate8u(uint32_t imm) { 4920 MOZ_ASSERT(CAN_ZERO_EXTEND_8_32(imm)); 4921 m_buffer.putByteUnchecked(int32_t(imm)); 4922 } 4923 4924 // An 8-bit immediate with is either signed or unsigned, for use in 4925 // instructions which actually only operate on 8 bits. immediate8(int32_t imm)4926 MOZ_ALWAYS_INLINE void immediate8(int32_t imm) { 4927 m_buffer.putByteUnchecked(imm); 4928 } 4929 4930 // A signed 16-bit immediate. immediate16s(int32_t imm)4931 MOZ_ALWAYS_INLINE void immediate16s(int32_t imm) { 4932 MOZ_ASSERT(CAN_SIGN_EXTEND_16_32(imm)); 4933 m_buffer.putShortUnchecked(imm); 4934 } 4935 4936 // An unsigned 16-bit immediate. immediate16u(int32_t imm)4937 MOZ_ALWAYS_INLINE void immediate16u(int32_t imm) { 4938 MOZ_ASSERT(CAN_ZERO_EXTEND_16_32(imm)); 4939 m_buffer.putShortUnchecked(imm); 4940 } 4941 4942 // A 16-bit immediate with is either signed or unsigned, for use in 4943 // instructions which actually only operate on 16 bits. immediate16(int32_t imm)4944 MOZ_ALWAYS_INLINE void immediate16(int32_t imm) { 4945 m_buffer.putShortUnchecked(imm); 4946 } 4947 immediate32(int32_t imm)4948 MOZ_ALWAYS_INLINE void immediate32(int32_t imm) { 4949 m_buffer.putIntUnchecked(imm); 4950 } 4951 immediate64(int64_t imm)4952 MOZ_ALWAYS_INLINE void immediate64(int64_t imm) { 4953 m_buffer.putInt64Unchecked(imm); 4954 } 4955 immediateRel32()4956 MOZ_ALWAYS_INLINE MOZ_MUST_USE JmpSrc immediateRel32() { 4957 m_buffer.putIntUnchecked(0); 4958 return JmpSrc(m_buffer.size()); 4959 } 4960 4961 // Data: 4962 jumpTablePointer(uintptr_t ptr)4963 void jumpTablePointer(uintptr_t ptr) { 4964 m_buffer.ensureSpace(sizeof(uintptr_t)); 4965 #ifdef JS_CODEGEN_X64 4966 m_buffer.putInt64Unchecked(ptr); 4967 #else 4968 m_buffer.putIntUnchecked(ptr); 4969 #endif 4970 } 4971 doubleConstant(double d)4972 void doubleConstant(double d) { 4973 m_buffer.ensureSpace(sizeof(double)); 4974 m_buffer.putInt64Unchecked(mozilla::BitwiseCast<uint64_t>(d)); 4975 } 4976 floatConstant(float f)4977 void floatConstant(float f) { 4978 m_buffer.ensureSpace(sizeof(float)); 4979 m_buffer.putIntUnchecked(mozilla::BitwiseCast<uint32_t>(f)); 4980 } 4981 simd128Constant(const void * data)4982 void simd128Constant(const void* data) { 4983 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data); 4984 m_buffer.ensureSpace(16); 4985 for (size_t i = 0; i < 16; ++i) m_buffer.putByteUnchecked(bytes[i]); 4986 } 4987 int64Constant(int64_t i)4988 void int64Constant(int64_t i) { 4989 m_buffer.ensureSpace(sizeof(int64_t)); 4990 m_buffer.putInt64Unchecked(i); 4991 } 4992 int32Constant(int32_t i)4993 void int32Constant(int32_t i) { 4994 m_buffer.ensureSpace(sizeof(int32_t)); 4995 m_buffer.putIntUnchecked(i); 4996 } 4997 4998 // Administrative methods: 4999 size()5000 size_t size() const { return m_buffer.size(); } buffer()5001 const unsigned char* buffer() const { return m_buffer.buffer(); } data()5002 unsigned char* data() { return m_buffer.data(); } oom()5003 bool oom() const { return m_buffer.oom(); } reserve(size_t size)5004 bool reserve(size_t size) { return m_buffer.reserve(size); } swapBuffer(wasm::Bytes & other)5005 bool swapBuffer(wasm::Bytes& other) { return m_buffer.swap(other); } isAligned(int alignment)5006 bool isAligned(int alignment) const { 5007 return m_buffer.isAligned(alignment); 5008 } 5009 append(const unsigned char * values,size_t size)5010 MOZ_MUST_USE bool append(const unsigned char* values, size_t size) { 5011 return m_buffer.append(values, size); 5012 } 5013 5014 private: 5015 // Internals; ModRm and REX formatters. 5016 5017 // Byte operand register spl & above requir a REX prefix, which precludes 5018 // use of the h registers in the same instruction. byteRegRequiresRex(RegisterID reg)5019 static bool byteRegRequiresRex(RegisterID reg) { 5020 #ifdef JS_CODEGEN_X64 5021 return reg >= rsp; 5022 #else 5023 return false; 5024 #endif 5025 } 5026 5027 // For non-byte sizes, registers r8 & above always require a REX prefix. regRequiresRex(RegisterID reg)5028 static bool regRequiresRex(RegisterID reg) { 5029 #ifdef JS_CODEGEN_X64 5030 return reg >= r8; 5031 #else 5032 return false; 5033 #endif 5034 } 5035 5036 #ifdef JS_CODEGEN_X64 5037 // Format a REX prefix byte. emitRex(bool w,int r,int x,int b)5038 void emitRex(bool w, int r, int x, int b) { 5039 m_buffer.putByteUnchecked(PRE_REX | ((int)w << 3) | ((r >> 3) << 2) | 5040 ((x >> 3) << 1) | (b >> 3)); 5041 } 5042 5043 // Used to plant a REX byte with REX.w set (for 64-bit operations). emitRexW(int r,int x,int b)5044 void emitRexW(int r, int x, int b) { emitRex(true, r, x, b); } 5045 5046 // Used for operations with byte operands - use byteRegRequiresRex() to 5047 // check register operands, regRequiresRex() to check other registers 5048 // (i.e. address base & index). 5049 // 5050 // NB: WebKit's use of emitRexIf() is limited such that the 5051 // reqRequiresRex() checks are not needed. SpiderMonkey extends 5052 // oneByteOp8 and twoByteOp8 functionality such that r, x, and b 5053 // can all be used. emitRexIf(bool condition,int r,int x,int b)5054 void emitRexIf(bool condition, int r, int x, int b) { 5055 if (condition || regRequiresRex(RegisterID(r)) || 5056 regRequiresRex(RegisterID(x)) || regRequiresRex(RegisterID(b))) { 5057 emitRex(false, r, x, b); 5058 } 5059 } 5060 5061 // Used for word sized operations, will plant a REX prefix if necessary 5062 // (if any register is r8 or above). emitRexIfNeeded(int r,int x,int b)5063 void emitRexIfNeeded(int r, int x, int b) { emitRexIf(false, r, x, b); } 5064 #else 5065 // No REX prefix bytes on 32-bit x86. emitRexIf(bool condition,int,int,int)5066 void emitRexIf(bool condition, int, int, int) { 5067 MOZ_ASSERT(!condition, "32-bit x86 should never use a REX prefix"); 5068 } emitRexIfNeeded(int,int,int)5069 void emitRexIfNeeded(int, int, int) {} 5070 #endif 5071 putModRm(ModRmMode mode,RegisterID rm,int reg)5072 void putModRm(ModRmMode mode, RegisterID rm, int reg) { 5073 m_buffer.putByteUnchecked((mode << 6) | ((reg & 7) << 3) | (rm & 7)); 5074 } 5075 putModRmSib(ModRmMode mode,RegisterID base,RegisterID index,int scale,int reg)5076 void putModRmSib(ModRmMode mode, RegisterID base, RegisterID index, 5077 int scale, int reg) { 5078 MOZ_ASSERT(mode != ModRmRegister); 5079 5080 putModRm(mode, hasSib, reg); 5081 m_buffer.putByteUnchecked((scale << 6) | ((index & 7) << 3) | (base & 7)); 5082 } 5083 registerModRM(RegisterID rm,int reg)5084 void registerModRM(RegisterID rm, int reg) { 5085 putModRm(ModRmRegister, rm, reg); 5086 } 5087 memoryModRM(int32_t offset,RegisterID base,int reg)5088 void memoryModRM(int32_t offset, RegisterID base, int reg) { 5089 // A base of esp or r12 would be interpreted as a sib, so force a 5090 // sib with no index & put the base in there. 5091 #ifdef JS_CODEGEN_X64 5092 if ((base == hasSib) || (base == hasSib2)) 5093 #else 5094 if (base == hasSib) 5095 #endif 5096 { 5097 if (!offset) // No need to check if the base is noBase, since we know 5098 // it is hasSib! 5099 putModRmSib(ModRmMemoryNoDisp, base, noIndex, 0, reg); 5100 else if (CAN_SIGN_EXTEND_8_32(offset)) { 5101 putModRmSib(ModRmMemoryDisp8, base, noIndex, 0, reg); 5102 m_buffer.putByteUnchecked(offset); 5103 } else { 5104 putModRmSib(ModRmMemoryDisp32, base, noIndex, 0, reg); 5105 m_buffer.putIntUnchecked(offset); 5106 } 5107 } else { 5108 #ifdef JS_CODEGEN_X64 5109 if (!offset && (base != noBase) && (base != noBase2)) 5110 #else 5111 if (!offset && (base != noBase)) 5112 #endif 5113 putModRm(ModRmMemoryNoDisp, base, reg); 5114 else if (CAN_SIGN_EXTEND_8_32(offset)) { 5115 putModRm(ModRmMemoryDisp8, base, reg); 5116 m_buffer.putByteUnchecked(offset); 5117 } else { 5118 putModRm(ModRmMemoryDisp32, base, reg); 5119 m_buffer.putIntUnchecked(offset); 5120 } 5121 } 5122 } 5123 memoryModRM_disp32(int32_t offset,RegisterID base,int reg)5124 void memoryModRM_disp32(int32_t offset, RegisterID base, int reg) { 5125 // A base of esp or r12 would be interpreted as a sib, so force a 5126 // sib with no index & put the base in there. 5127 #ifdef JS_CODEGEN_X64 5128 if ((base == hasSib) || (base == hasSib2)) 5129 #else 5130 if (base == hasSib) 5131 #endif 5132 { 5133 putModRmSib(ModRmMemoryDisp32, base, noIndex, 0, reg); 5134 m_buffer.putIntUnchecked(offset); 5135 } else { 5136 putModRm(ModRmMemoryDisp32, base, reg); 5137 m_buffer.putIntUnchecked(offset); 5138 } 5139 } 5140 memoryModRM(int32_t offset,RegisterID base,RegisterID index,int scale,int reg)5141 void memoryModRM(int32_t offset, RegisterID base, RegisterID index, 5142 int scale, int reg) { 5143 MOZ_ASSERT(index != noIndex); 5144 5145 #ifdef JS_CODEGEN_X64 5146 if (!offset && (base != noBase) && (base != noBase2)) 5147 #else 5148 if (!offset && (base != noBase)) 5149 #endif 5150 putModRmSib(ModRmMemoryNoDisp, base, index, scale, reg); 5151 else if (CAN_SIGN_EXTEND_8_32(offset)) { 5152 putModRmSib(ModRmMemoryDisp8, base, index, scale, reg); 5153 m_buffer.putByteUnchecked(offset); 5154 } else { 5155 putModRmSib(ModRmMemoryDisp32, base, index, scale, reg); 5156 m_buffer.putIntUnchecked(offset); 5157 } 5158 } 5159 memoryModRM_disp32(int32_t offset,RegisterID index,int scale,int reg)5160 void memoryModRM_disp32(int32_t offset, RegisterID index, int scale, 5161 int reg) { 5162 MOZ_ASSERT(index != noIndex); 5163 5164 // NB: the base-less memoryModRM overloads generate different code 5165 // then the base-full memoryModRM overloads in the base == noBase 5166 // case. The base-less overloads assume that the desired effective 5167 // address is: 5168 // 5169 // reg := [scaled index] + disp32 5170 // 5171 // which means the mod needs to be ModRmMemoryNoDisp. The base-full 5172 // overloads pass ModRmMemoryDisp32 in all cases and thus, when 5173 // base == noBase (== ebp), the effective address is: 5174 // 5175 // reg := [scaled index] + disp32 + [ebp] 5176 // 5177 // See Intel developer manual, Vol 2, 2.1.5, Table 2-3. 5178 putModRmSib(ModRmMemoryNoDisp, noBase, index, scale, reg); 5179 m_buffer.putIntUnchecked(offset); 5180 } 5181 memoryModRM_disp32(const void * address,int reg)5182 void memoryModRM_disp32(const void* address, int reg) { 5183 int32_t disp = AddressImmediate(address); 5184 5185 #ifdef JS_CODEGEN_X64 5186 // On x64-64, non-RIP-relative absolute mode requires a SIB. 5187 putModRmSib(ModRmMemoryNoDisp, noBase, noIndex, 0, reg); 5188 #else 5189 // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32! 5190 putModRm(ModRmMemoryNoDisp, noBase, reg); 5191 #endif 5192 m_buffer.putIntUnchecked(disp); 5193 } 5194 memoryModRM(const void * address,int reg)5195 void memoryModRM(const void* address, int reg) { 5196 memoryModRM_disp32(address, reg); 5197 } 5198 threeOpVex(VexOperandType p,int r,int x,int b,int m,int w,int v,int l,int opcode)5199 void threeOpVex(VexOperandType p, int r, int x, int b, int m, int w, int v, 5200 int l, int opcode) { 5201 m_buffer.ensureSpace(MaxInstructionSize); 5202 5203 if (v == invalid_xmm) v = XMMRegisterID(0); 5204 5205 if (x == 0 && b == 0 && m == 1 && w == 0) { 5206 // Two byte VEX. 5207 m_buffer.putByteUnchecked(PRE_VEX_C5); 5208 m_buffer.putByteUnchecked(((r << 7) | (v << 3) | (l << 2) | p) ^ 0xf8); 5209 } else { 5210 // Three byte VEX. 5211 m_buffer.putByteUnchecked(PRE_VEX_C4); 5212 m_buffer.putByteUnchecked(((r << 7) | (x << 6) | (b << 5) | m) ^ 0xe0); 5213 m_buffer.putByteUnchecked(((w << 7) | (v << 3) | (l << 2) | p) ^ 0x78); 5214 } 5215 5216 m_buffer.putByteUnchecked(opcode); 5217 } 5218 5219 AssemblerBuffer m_buffer; 5220 } m_formatter; 5221 5222 bool useVEX_; 5223 }; 5224 5225 } // namespace X86Encoding 5226 5227 } // namespace jit 5228 } // namespace js 5229 5230 #endif /* jit_x86_shared_BaseAssembler_x86_shared_h */ 5231