OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 // |
| 5 // Modified by the Subzero authors. |
| 6 // |
| 7 //===- subzero/src/assembler_ia32.cpp - Assembler for x86-32 -------------===// |
| 8 // |
| 9 // The Subzero Code Generator |
| 10 // |
| 11 // This file is distributed under the University of Illinois Open Source |
| 12 // License. See LICENSE.TXT for details. |
| 13 // |
| 14 //===----------------------------------------------------------------------===// |
| 15 // |
| 16 // This file implements the Assembler class for x86-32. |
| 17 // |
| 18 //===----------------------------------------------------------------------===// |
| 19 |
| 20 #include "assembler_ia32.h" |
| 21 #include "IceMemoryRegion.h" |
| 22 |
| 23 namespace Ice { |
| 24 namespace x86 { |
| 25 |
| 26 class DirectCallRelocation : public AssemblerFixup { |
| 27 public: |
| 28 void Process(const MemoryRegion ®ion, intptr_t position) { |
| 29 // Direct calls are relative to the following instruction on x86. |
| 30 int32_t pointer = region.Load<int32_t>(position); |
| 31 int32_t delta = region.start() + position + sizeof(int32_t); |
| 32 region.Store<int32_t>(position, pointer - delta); |
| 33 } |
| 34 }; |
| 35 |
| 36 void AssemblerX86::InitializeMemoryWithBreakpoints(uintptr_t data, |
| 37 intptr_t length) { |
| 38 memset(reinterpret_cast<void *>(data), Instr::kBreakPointInstruction, length); |
| 39 } |
| 40 |
| 41 void AssemblerX86::call(Register reg) { |
| 42 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 43 EmitUint8(0xFF); |
| 44 EmitRegisterOperand(2, reg); |
| 45 } |
| 46 |
| 47 void AssemblerX86::call(const Address &address) { |
| 48 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 49 EmitUint8(0xFF); |
| 50 EmitOperand(2, address); |
| 51 } |
| 52 |
| 53 void AssemblerX86::call(Label *label) { |
| 54 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 55 EmitUint8(0xE8); |
| 56 static const int kSize = 5; |
| 57 EmitLabel(label, kSize); |
| 58 } |
| 59 |
| 60 void AssemblerX86::call(const ConstantRelocatable *label) { |
| 61 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 62 intptr_t call_start = buffer_.GetPosition(); |
| 63 EmitUint8(0xE8); |
| 64 // TODO(jvoung): Actually track the label of the relocation. |
| 65 (void)label; |
| 66 EmitFixup(new (this->Allocate<DirectCallRelocation>()) |
| 67 DirectCallRelocation()); |
| 68 EmitInt32(-4); |
| 69 assert((buffer_.GetPosition() - call_start) == kCallExternalLabelSize); |
| 70 } |
| 71 |
| 72 void AssemblerX86::pushl(Register reg) { |
| 73 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 74 EmitUint8(0x50 + reg); |
| 75 } |
| 76 |
| 77 void AssemblerX86::pushl(const Address &address) { |
| 78 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 79 EmitUint8(0xFF); |
| 80 EmitOperand(6, address); |
| 81 } |
| 82 |
| 83 void AssemblerX86::pushl(const Immediate &imm) { |
| 84 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 85 EmitUint8(0x68); |
| 86 EmitImmediate(imm); |
| 87 } |
| 88 |
| 89 void AssemblerX86::popl(Register reg) { |
| 90 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 91 EmitUint8(0x58 + reg); |
| 92 } |
| 93 |
| 94 void AssemblerX86::popl(const Address &address) { |
| 95 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 96 EmitUint8(0x8F); |
| 97 EmitOperand(0, address); |
| 98 } |
| 99 |
| 100 void AssemblerX86::pushal() { |
| 101 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 102 EmitUint8(0x60); |
| 103 } |
| 104 |
| 105 void AssemblerX86::popal() { |
| 106 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 107 EmitUint8(0x61); |
| 108 } |
| 109 |
| 110 void AssemblerX86::setcc(Condition condition, ByteRegister dst) { |
| 111 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 112 EmitUint8(0x0F); |
| 113 EmitUint8(0x90 + condition); |
| 114 EmitUint8(0xC0 + dst); |
| 115 } |
| 116 |
| 117 void AssemblerX86::movl(Register dst, const Immediate &imm) { |
| 118 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 119 EmitUint8(0xB8 + dst); |
| 120 EmitImmediate(imm); |
| 121 } |
| 122 |
| 123 void AssemblerX86::movl(Register dst, Register src) { |
| 124 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 125 EmitUint8(0x89); |
| 126 EmitRegisterOperand(src, dst); |
| 127 } |
| 128 |
| 129 void AssemblerX86::movl(Register dst, const Address &src) { |
| 130 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 131 EmitUint8(0x8B); |
| 132 EmitOperand(dst, src); |
| 133 } |
| 134 |
| 135 void AssemblerX86::movl(const Address &dst, Register src) { |
| 136 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 137 EmitUint8(0x89); |
| 138 EmitOperand(src, dst); |
| 139 } |
| 140 |
| 141 void AssemblerX86::movl(const Address &dst, const Immediate &imm) { |
| 142 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 143 EmitUint8(0xC7); |
| 144 EmitOperand(0, dst); |
| 145 EmitImmediate(imm); |
| 146 } |
| 147 |
| 148 void AssemblerX86::movzxb(Register dst, ByteRegister src) { |
| 149 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 150 EmitUint8(0x0F); |
| 151 EmitUint8(0xB6); |
| 152 EmitRegisterOperand(dst, src); |
| 153 } |
| 154 |
| 155 void AssemblerX86::movzxb(Register dst, const Address &src) { |
| 156 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 157 EmitUint8(0x0F); |
| 158 EmitUint8(0xB6); |
| 159 EmitOperand(dst, src); |
| 160 } |
| 161 |
| 162 void AssemblerX86::movsxb(Register dst, ByteRegister src) { |
| 163 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 164 EmitUint8(0x0F); |
| 165 EmitUint8(0xBE); |
| 166 EmitRegisterOperand(dst, src); |
| 167 } |
| 168 |
| 169 void AssemblerX86::movsxb(Register dst, const Address &src) { |
| 170 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 171 EmitUint8(0x0F); |
| 172 EmitUint8(0xBE); |
| 173 EmitOperand(dst, src); |
| 174 } |
| 175 |
| 176 void AssemblerX86::movb(ByteRegister dst, const Address &src) { |
| 177 (void)dst; |
| 178 (void)src; |
| 179 // FATAL |
| 180 llvm_unreachable("Use movzxb or movsxb instead."); |
| 181 } |
| 182 |
| 183 void AssemblerX86::movb(const Address &dst, ByteRegister src) { |
| 184 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 185 EmitUint8(0x88); |
| 186 EmitOperand(src, dst); |
| 187 } |
| 188 |
| 189 void AssemblerX86::movb(const Address &dst, const Immediate &imm) { |
| 190 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 191 EmitUint8(0xC6); |
| 192 EmitOperand(EAX, dst); |
| 193 assert(imm.is_int8()); |
| 194 EmitUint8(imm.value() & 0xFF); |
| 195 } |
| 196 |
| 197 void AssemblerX86::movzxw(Register dst, Register src) { |
| 198 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 199 EmitUint8(0x0F); |
| 200 EmitUint8(0xB7); |
| 201 EmitRegisterOperand(dst, src); |
| 202 } |
| 203 |
| 204 void AssemblerX86::movzxw(Register dst, const Address &src) { |
| 205 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 206 EmitUint8(0x0F); |
| 207 EmitUint8(0xB7); |
| 208 EmitOperand(dst, src); |
| 209 } |
| 210 |
| 211 void AssemblerX86::movsxw(Register dst, Register src) { |
| 212 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 213 EmitUint8(0x0F); |
| 214 EmitUint8(0xBF); |
| 215 EmitRegisterOperand(dst, src); |
| 216 } |
| 217 |
| 218 void AssemblerX86::movsxw(Register dst, const Address &src) { |
| 219 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 220 EmitUint8(0x0F); |
| 221 EmitUint8(0xBF); |
| 222 EmitOperand(dst, src); |
| 223 } |
| 224 |
| 225 void AssemblerX86::movw(Register dst, const Address &src) { |
| 226 (void)dst; |
| 227 (void)src; |
| 228 // FATAL |
| 229 llvm_unreachable("Use movzxw or movsxw instead."); |
| 230 } |
| 231 |
| 232 void AssemblerX86::movw(const Address &dst, Register src) { |
| 233 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 234 EmitOperandSizeOverride(); |
| 235 EmitUint8(0x89); |
| 236 EmitOperand(src, dst); |
| 237 } |
| 238 |
| 239 void AssemblerX86::leal(Register dst, const Address &src) { |
| 240 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 241 EmitUint8(0x8D); |
| 242 EmitOperand(dst, src); |
| 243 } |
| 244 |
| 245 void AssemblerX86::cmov(Condition cond, Register dst, Register src) { |
| 246 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 247 EmitUint8(0x0F); |
| 248 EmitUint8(0x40 + cond); |
| 249 EmitRegisterOperand(dst, src); |
| 250 } |
| 251 |
| 252 void AssemblerX86::rep_movsb() { |
| 253 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 254 EmitUint8(0xF3); |
| 255 EmitUint8(0xA4); |
| 256 } |
| 257 |
| 258 void AssemblerX86::movss(XmmRegister dst, const Address &src) { |
| 259 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 260 EmitUint8(0xF3); |
| 261 EmitUint8(0x0F); |
| 262 EmitUint8(0x10); |
| 263 EmitOperand(dst, src); |
| 264 } |
| 265 |
| 266 void AssemblerX86::movss(const Address &dst, XmmRegister src) { |
| 267 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 268 EmitUint8(0xF3); |
| 269 EmitUint8(0x0F); |
| 270 EmitUint8(0x11); |
| 271 EmitOperand(src, dst); |
| 272 } |
| 273 |
| 274 void AssemblerX86::movss(XmmRegister dst, XmmRegister src) { |
| 275 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 276 EmitUint8(0xF3); |
| 277 EmitUint8(0x0F); |
| 278 EmitUint8(0x11); |
| 279 EmitXmmRegisterOperand(src, dst); |
| 280 } |
| 281 |
| 282 void AssemblerX86::movd(XmmRegister dst, Register src) { |
| 283 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 284 EmitUint8(0x66); |
| 285 EmitUint8(0x0F); |
| 286 EmitUint8(0x6E); |
| 287 EmitOperand(dst, Operand(src)); |
| 288 } |
| 289 |
| 290 void AssemblerX86::movd(Register dst, XmmRegister src) { |
| 291 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 292 EmitUint8(0x66); |
| 293 EmitUint8(0x0F); |
| 294 EmitUint8(0x7E); |
| 295 EmitOperand(src, Operand(dst)); |
| 296 } |
| 297 |
| 298 void AssemblerX86::movq(const Address &dst, XmmRegister src) { |
| 299 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 300 EmitUint8(0x66); |
| 301 EmitUint8(0x0F); |
| 302 EmitUint8(0xD6); |
| 303 EmitOperand(src, Operand(dst)); |
| 304 } |
| 305 |
| 306 void AssemblerX86::movq(XmmRegister dst, const Address &src) { |
| 307 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 308 EmitUint8(0xF3); |
| 309 EmitUint8(0x0F); |
| 310 EmitUint8(0x7E); |
| 311 EmitOperand(dst, Operand(src)); |
| 312 } |
| 313 |
| 314 // TODO(jvoung): In these xmm1, xmm2/mXX cases, the opcodes don't vary |
| 315 // based on operand-type. Should we just have an "addss_start()" method, |
| 316 // and then the caller can do EmitXmmRegisterOperand(dst, src) |
| 317 // or EmitOperand(dst, src)? Then we don't have to fill in the missing |
| 318 // variants which only handle Xmm, Xmm (but not Xmm, mXX). |
| 319 // Only thing is we'll be diverging, and we'll end up making the |
| 320 // EmitXmmRegisterOperand, etc. public instead of private. |
| 321 |
| 322 void AssemblerX86::addss(XmmRegister dst, XmmRegister src) { |
| 323 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 324 EmitUint8(0xF3); |
| 325 EmitUint8(0x0F); |
| 326 EmitUint8(0x58); |
| 327 EmitXmmRegisterOperand(dst, src); |
| 328 } |
| 329 |
| 330 void AssemblerX86::addss(XmmRegister dst, const Address &src) { |
| 331 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 332 EmitUint8(0xF3); |
| 333 EmitUint8(0x0F); |
| 334 EmitUint8(0x58); |
| 335 EmitOperand(dst, src); |
| 336 } |
| 337 |
| 338 void AssemblerX86::subss(XmmRegister dst, XmmRegister src) { |
| 339 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 340 EmitUint8(0xF3); |
| 341 EmitUint8(0x0F); |
| 342 EmitUint8(0x5C); |
| 343 EmitXmmRegisterOperand(dst, src); |
| 344 } |
| 345 |
| 346 void AssemblerX86::subss(XmmRegister dst, const Address &src) { |
| 347 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 348 EmitUint8(0xF3); |
| 349 EmitUint8(0x0F); |
| 350 EmitUint8(0x5C); |
| 351 EmitOperand(dst, src); |
| 352 } |
| 353 |
| 354 void AssemblerX86::mulss(XmmRegister dst, XmmRegister src) { |
| 355 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 356 EmitUint8(0xF3); |
| 357 EmitUint8(0x0F); |
| 358 EmitUint8(0x59); |
| 359 EmitXmmRegisterOperand(dst, src); |
| 360 } |
| 361 |
| 362 void AssemblerX86::mulss(XmmRegister dst, const Address &src) { |
| 363 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 364 EmitUint8(0xF3); |
| 365 EmitUint8(0x0F); |
| 366 EmitUint8(0x59); |
| 367 EmitOperand(dst, src); |
| 368 } |
| 369 |
| 370 void AssemblerX86::divss(XmmRegister dst, XmmRegister src) { |
| 371 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 372 EmitUint8(0xF3); |
| 373 EmitUint8(0x0F); |
| 374 EmitUint8(0x5E); |
| 375 EmitXmmRegisterOperand(dst, src); |
| 376 } |
| 377 |
| 378 void AssemblerX86::divss(XmmRegister dst, const Address &src) { |
| 379 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 380 EmitUint8(0xF3); |
| 381 EmitUint8(0x0F); |
| 382 EmitUint8(0x5E); |
| 383 EmitOperand(dst, src); |
| 384 } |
| 385 |
| 386 void AssemblerX86::flds(const Address &src) { |
| 387 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 388 EmitUint8(0xD9); |
| 389 EmitOperand(0, src); |
| 390 } |
| 391 |
| 392 void AssemblerX86::fstps(const Address &dst) { |
| 393 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 394 EmitUint8(0xD9); |
| 395 EmitOperand(3, dst); |
| 396 } |
| 397 |
| 398 void AssemblerX86::movsd(XmmRegister dst, const Address &src) { |
| 399 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 400 EmitUint8(0xF2); |
| 401 EmitUint8(0x0F); |
| 402 EmitUint8(0x10); |
| 403 EmitOperand(dst, src); |
| 404 } |
| 405 |
| 406 void AssemblerX86::movsd(const Address &dst, XmmRegister src) { |
| 407 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 408 EmitUint8(0xF2); |
| 409 EmitUint8(0x0F); |
| 410 EmitUint8(0x11); |
| 411 EmitOperand(src, dst); |
| 412 } |
| 413 |
| 414 void AssemblerX86::movsd(XmmRegister dst, XmmRegister src) { |
| 415 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 416 EmitUint8(0xF2); |
| 417 EmitUint8(0x0F); |
| 418 EmitUint8(0x11); |
| 419 EmitXmmRegisterOperand(src, dst); |
| 420 } |
| 421 |
| 422 void AssemblerX86::movaps(XmmRegister dst, XmmRegister src) { |
| 423 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 424 EmitUint8(0x0F); |
| 425 EmitUint8(0x28); |
| 426 EmitXmmRegisterOperand(dst, src); |
| 427 } |
| 428 |
| 429 void AssemblerX86::movups(XmmRegister dst, const Address &src) { |
| 430 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 431 EmitUint8(0x0F); |
| 432 EmitUint8(0x10); |
| 433 EmitOperand(dst, src); |
| 434 } |
| 435 |
| 436 void AssemblerX86::movups(const Address &dst, XmmRegister src) { |
| 437 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 438 EmitUint8(0x0F); |
| 439 EmitUint8(0x11); |
| 440 EmitOperand(src, dst); |
| 441 } |
| 442 |
| 443 void AssemblerX86::addsd(XmmRegister dst, XmmRegister src) { |
| 444 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 445 EmitUint8(0xF2); |
| 446 EmitUint8(0x0F); |
| 447 EmitUint8(0x58); |
| 448 EmitXmmRegisterOperand(dst, src); |
| 449 } |
| 450 |
| 451 void AssemblerX86::addsd(XmmRegister dst, const Address &src) { |
| 452 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 453 EmitUint8(0xF2); |
| 454 EmitUint8(0x0F); |
| 455 EmitUint8(0x58); |
| 456 EmitOperand(dst, src); |
| 457 } |
| 458 |
| 459 void AssemblerX86::addpl(XmmRegister dst, XmmRegister src) { |
| 460 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 461 EmitUint8(0x66); |
| 462 EmitUint8(0x0F); |
| 463 EmitUint8(0xFE); |
| 464 EmitXmmRegisterOperand(dst, src); |
| 465 } |
| 466 |
| 467 void AssemblerX86::subpl(XmmRegister dst, XmmRegister src) { |
| 468 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 469 EmitUint8(0x66); |
| 470 EmitUint8(0x0F); |
| 471 EmitUint8(0xFA); |
| 472 EmitXmmRegisterOperand(dst, src); |
| 473 } |
| 474 |
| 475 void AssemblerX86::addps(XmmRegister dst, XmmRegister src) { |
| 476 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 477 EmitUint8(0x0F); |
| 478 EmitUint8(0x58); |
| 479 EmitXmmRegisterOperand(dst, src); |
| 480 } |
| 481 |
| 482 void AssemblerX86::addps(XmmRegister dst, const Address &src) { |
| 483 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 484 EmitUint8(0x0F); |
| 485 EmitUint8(0x58); |
| 486 EmitOperand(dst, src); |
| 487 } |
| 488 |
| 489 void AssemblerX86::subps(XmmRegister dst, XmmRegister src) { |
| 490 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 491 EmitUint8(0x0F); |
| 492 EmitUint8(0x5C); |
| 493 EmitXmmRegisterOperand(dst, src); |
| 494 } |
| 495 |
| 496 void AssemblerX86::subps(XmmRegister dst, const Address &src) { |
| 497 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 498 EmitUint8(0x0F); |
| 499 EmitUint8(0x5C); |
| 500 EmitOperand(dst, src); |
| 501 } |
| 502 |
| 503 void AssemblerX86::divps(XmmRegister dst, XmmRegister src) { |
| 504 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 505 EmitUint8(0x0F); |
| 506 EmitUint8(0x5E); |
| 507 EmitXmmRegisterOperand(dst, src); |
| 508 } |
| 509 |
| 510 void AssemblerX86::divps(XmmRegister dst, const Address &src) { |
| 511 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 512 EmitUint8(0x0F); |
| 513 EmitUint8(0x5E); |
| 514 EmitOperand(dst, src); |
| 515 } |
| 516 |
| 517 void AssemblerX86::mulps(XmmRegister dst, XmmRegister src) { |
| 518 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 519 EmitUint8(0x0F); |
| 520 EmitUint8(0x59); |
| 521 EmitXmmRegisterOperand(dst, src); |
| 522 } |
| 523 |
| 524 void AssemblerX86::mulps(XmmRegister dst, const Address &src) { |
| 525 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 526 EmitUint8(0x0F); |
| 527 EmitUint8(0x59); |
| 528 EmitOperand(dst, src); |
| 529 } |
| 530 |
| 531 void AssemblerX86::minps(XmmRegister dst, XmmRegister src) { |
| 532 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 533 EmitUint8(0x0F); |
| 534 EmitUint8(0x5D); |
| 535 EmitXmmRegisterOperand(dst, src); |
| 536 } |
| 537 |
| 538 void AssemblerX86::maxps(XmmRegister dst, XmmRegister src) { |
| 539 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 540 EmitUint8(0x0F); |
| 541 EmitUint8(0x5F); |
| 542 EmitXmmRegisterOperand(dst, src); |
| 543 } |
| 544 |
| 545 void AssemblerX86::andps(XmmRegister dst, XmmRegister src) { |
| 546 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 547 EmitUint8(0x0F); |
| 548 EmitUint8(0x54); |
| 549 EmitXmmRegisterOperand(dst, src); |
| 550 } |
| 551 |
| 552 void AssemblerX86::andps(XmmRegister dst, const Address &src) { |
| 553 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 554 EmitUint8(0x0F); |
| 555 EmitUint8(0x54); |
| 556 EmitOperand(dst, src); |
| 557 } |
| 558 |
| 559 void AssemblerX86::orps(XmmRegister dst, XmmRegister src) { |
| 560 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 561 EmitUint8(0x0F); |
| 562 EmitUint8(0x56); |
| 563 EmitXmmRegisterOperand(dst, src); |
| 564 } |
| 565 |
| 566 void AssemblerX86::notps(XmmRegister dst) { |
| 567 static const struct ALIGN16 { |
| 568 uint32_t a; |
| 569 uint32_t b; |
| 570 uint32_t c; |
| 571 uint32_t d; |
| 572 } float_not_constant = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; |
| 573 xorps(dst, |
| 574 Address::Absolute(reinterpret_cast<uintptr_t>(&float_not_constant))); |
| 575 } |
| 576 |
| 577 void AssemblerX86::negateps(XmmRegister dst) { |
| 578 static const struct ALIGN16 { |
| 579 uint32_t a; |
| 580 uint32_t b; |
| 581 uint32_t c; |
| 582 uint32_t d; |
| 583 } float_negate_constant = {0x80000000, 0x80000000, 0x80000000, 0x80000000}; |
| 584 xorps(dst, |
| 585 Address::Absolute(reinterpret_cast<uintptr_t>(&float_negate_constant))); |
| 586 } |
| 587 |
| 588 void AssemblerX86::absps(XmmRegister dst) { |
| 589 static const struct ALIGN16 { |
| 590 uint32_t a; |
| 591 uint32_t b; |
| 592 uint32_t c; |
| 593 uint32_t d; |
| 594 } float_absolute_constant = {0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF}; |
| 595 andps(dst, Address::Absolute( |
| 596 reinterpret_cast<uintptr_t>(&float_absolute_constant))); |
| 597 } |
| 598 |
| 599 void AssemblerX86::zerowps(XmmRegister dst) { |
| 600 static const struct ALIGN16 { |
| 601 uint32_t a; |
| 602 uint32_t b; |
| 603 uint32_t c; |
| 604 uint32_t d; |
| 605 } float_zerow_constant = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000}; |
| 606 andps(dst, |
| 607 Address::Absolute(reinterpret_cast<uintptr_t>(&float_zerow_constant))); |
| 608 } |
| 609 |
| 610 void AssemblerX86::cmpps(XmmRegister dst, XmmRegister src, |
| 611 uint8_t CmpCondition) { |
| 612 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 613 EmitUint8(0x0F); |
| 614 EmitUint8(0xC2); |
| 615 EmitXmmRegisterOperand(dst, src); |
| 616 EmitUint8(CmpCondition); |
| 617 } |
| 618 |
| 619 void AssemblerX86::cmpps(XmmRegister dst, const Address &src, |
| 620 uint8_t CmpCondition) { |
| 621 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 622 EmitUint8(0x0F); |
| 623 EmitUint8(0xC2); |
| 624 EmitOperand(dst, src); |
| 625 EmitUint8(CmpCondition); |
| 626 } |
| 627 |
| 628 void AssemblerX86::sqrtps(XmmRegister dst) { |
| 629 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 630 EmitUint8(0x0F); |
| 631 EmitUint8(0x51); |
| 632 EmitXmmRegisterOperand(dst, dst); |
| 633 } |
| 634 |
| 635 void AssemblerX86::rsqrtps(XmmRegister dst) { |
| 636 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 637 EmitUint8(0x0F); |
| 638 EmitUint8(0x52); |
| 639 EmitXmmRegisterOperand(dst, dst); |
| 640 } |
| 641 |
| 642 void AssemblerX86::reciprocalps(XmmRegister dst) { |
| 643 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 644 EmitUint8(0x0F); |
| 645 EmitUint8(0x53); |
| 646 EmitXmmRegisterOperand(dst, dst); |
| 647 } |
| 648 |
| 649 void AssemblerX86::movhlps(XmmRegister dst, XmmRegister src) { |
| 650 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 651 EmitUint8(0x0F); |
| 652 EmitUint8(0x12); |
| 653 EmitXmmRegisterOperand(dst, src); |
| 654 } |
| 655 |
| 656 void AssemblerX86::movlhps(XmmRegister dst, XmmRegister src) { |
| 657 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 658 EmitUint8(0x0F); |
| 659 EmitUint8(0x16); |
| 660 EmitXmmRegisterOperand(dst, src); |
| 661 } |
| 662 |
| 663 void AssemblerX86::unpcklps(XmmRegister dst, XmmRegister src) { |
| 664 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 665 EmitUint8(0x0F); |
| 666 EmitUint8(0x14); |
| 667 EmitXmmRegisterOperand(dst, src); |
| 668 } |
| 669 |
| 670 void AssemblerX86::unpckhps(XmmRegister dst, XmmRegister src) { |
| 671 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 672 EmitUint8(0x0F); |
| 673 EmitUint8(0x15); |
| 674 EmitXmmRegisterOperand(dst, src); |
| 675 } |
| 676 |
| 677 void AssemblerX86::unpcklpd(XmmRegister dst, XmmRegister src) { |
| 678 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 679 EmitUint8(0x66); |
| 680 EmitUint8(0x0F); |
| 681 EmitUint8(0x14); |
| 682 EmitXmmRegisterOperand(dst, src); |
| 683 } |
| 684 |
| 685 void AssemblerX86::unpckhpd(XmmRegister dst, XmmRegister src) { |
| 686 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 687 EmitUint8(0x66); |
| 688 EmitUint8(0x0F); |
| 689 EmitUint8(0x15); |
| 690 EmitXmmRegisterOperand(dst, src); |
| 691 } |
| 692 |
| 693 void AssemblerX86::set1ps(XmmRegister dst, Register tmp1, |
| 694 const Immediate &imm) { |
| 695 // Load 32-bit immediate value into tmp1. |
| 696 movl(tmp1, imm); |
| 697 // Move value from tmp1 into dst. |
| 698 movd(dst, tmp1); |
| 699 // Broadcast low lane into other three lanes. |
| 700 shufps(dst, dst, Immediate(0x0)); |
| 701 } |
| 702 |
| 703 void AssemblerX86::shufps(XmmRegister dst, XmmRegister src, |
| 704 const Immediate &imm) { |
| 705 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 706 EmitUint8(0x0F); |
| 707 EmitUint8(0xC6); |
| 708 EmitXmmRegisterOperand(dst, src); |
| 709 assert(imm.is_uint8()); |
| 710 EmitUint8(imm.value()); |
| 711 } |
| 712 |
| 713 void AssemblerX86::addpd(XmmRegister dst, XmmRegister src) { |
| 714 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 715 EmitUint8(0x66); |
| 716 EmitUint8(0x0F); |
| 717 EmitUint8(0x58); |
| 718 EmitXmmRegisterOperand(dst, src); |
| 719 } |
| 720 |
| 721 void AssemblerX86::negatepd(XmmRegister dst) { |
| 722 static const struct ALIGN16 { |
| 723 uint64_t a; |
| 724 uint64_t b; |
| 725 } double_negate_constant = {0x8000000000000000LL, 0x8000000000000000LL}; |
| 726 xorpd(dst, Address::Absolute( |
| 727 reinterpret_cast<uintptr_t>(&double_negate_constant))); |
| 728 } |
| 729 |
| 730 void AssemblerX86::subpd(XmmRegister dst, XmmRegister src) { |
| 731 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 732 EmitUint8(0x66); |
| 733 EmitUint8(0x0F); |
| 734 EmitUint8(0x5C); |
| 735 EmitXmmRegisterOperand(dst, src); |
| 736 } |
| 737 |
| 738 void AssemblerX86::mulpd(XmmRegister dst, XmmRegister src) { |
| 739 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 740 EmitUint8(0x66); |
| 741 EmitUint8(0x0F); |
| 742 EmitUint8(0x59); |
| 743 EmitXmmRegisterOperand(dst, src); |
| 744 } |
| 745 |
| 746 void AssemblerX86::divpd(XmmRegister dst, XmmRegister src) { |
| 747 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 748 EmitUint8(0x66); |
| 749 EmitUint8(0x0F); |
| 750 EmitUint8(0x5E); |
| 751 EmitXmmRegisterOperand(dst, src); |
| 752 } |
| 753 |
| 754 void AssemblerX86::abspd(XmmRegister dst) { |
| 755 static const struct ALIGN16 { |
| 756 uint64_t a; |
| 757 uint64_t b; |
| 758 } double_absolute_constant = {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}; |
| 759 andpd(dst, Address::Absolute( |
| 760 reinterpret_cast<uintptr_t>(&double_absolute_constant))); |
| 761 } |
| 762 |
| 763 void AssemblerX86::minpd(XmmRegister dst, XmmRegister src) { |
| 764 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 765 EmitUint8(0x66); |
| 766 EmitUint8(0x0F); |
| 767 EmitUint8(0x5D); |
| 768 EmitXmmRegisterOperand(dst, src); |
| 769 } |
| 770 |
| 771 void AssemblerX86::maxpd(XmmRegister dst, XmmRegister src) { |
| 772 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 773 EmitUint8(0x66); |
| 774 EmitUint8(0x0F); |
| 775 EmitUint8(0x5F); |
| 776 EmitXmmRegisterOperand(dst, src); |
| 777 } |
| 778 |
| 779 void AssemblerX86::sqrtpd(XmmRegister dst) { |
| 780 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 781 EmitUint8(0x66); |
| 782 EmitUint8(0x0F); |
| 783 EmitUint8(0x51); |
| 784 EmitXmmRegisterOperand(dst, dst); |
| 785 } |
| 786 |
| 787 void AssemblerX86::cvtps2pd(XmmRegister dst, XmmRegister src) { |
| 788 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 789 EmitUint8(0x0F); |
| 790 EmitUint8(0x5A); |
| 791 EmitXmmRegisterOperand(dst, src); |
| 792 } |
| 793 |
| 794 void AssemblerX86::cvtpd2ps(XmmRegister dst, XmmRegister src) { |
| 795 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 796 EmitUint8(0x66); |
| 797 EmitUint8(0x0F); |
| 798 EmitUint8(0x5A); |
| 799 EmitXmmRegisterOperand(dst, src); |
| 800 } |
| 801 |
| 802 void AssemblerX86::shufpd(XmmRegister dst, XmmRegister src, |
| 803 const Immediate &imm) { |
| 804 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 805 EmitUint8(0x66); |
| 806 EmitUint8(0x0F); |
| 807 EmitUint8(0xC6); |
| 808 EmitXmmRegisterOperand(dst, src); |
| 809 assert(imm.is_uint8()); |
| 810 EmitUint8(imm.value()); |
| 811 } |
| 812 |
| 813 void AssemblerX86::subsd(XmmRegister dst, XmmRegister src) { |
| 814 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 815 EmitUint8(0xF2); |
| 816 EmitUint8(0x0F); |
| 817 EmitUint8(0x5C); |
| 818 EmitXmmRegisterOperand(dst, src); |
| 819 } |
| 820 |
| 821 void AssemblerX86::subsd(XmmRegister dst, const Address &src) { |
| 822 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 823 EmitUint8(0xF2); |
| 824 EmitUint8(0x0F); |
| 825 EmitUint8(0x5C); |
| 826 EmitOperand(dst, src); |
| 827 } |
| 828 |
| 829 void AssemblerX86::mulsd(XmmRegister dst, XmmRegister src) { |
| 830 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 831 EmitUint8(0xF2); |
| 832 EmitUint8(0x0F); |
| 833 EmitUint8(0x59); |
| 834 EmitXmmRegisterOperand(dst, src); |
| 835 } |
| 836 |
| 837 void AssemblerX86::mulsd(XmmRegister dst, const Address &src) { |
| 838 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 839 EmitUint8(0xF2); |
| 840 EmitUint8(0x0F); |
| 841 EmitUint8(0x59); |
| 842 EmitOperand(dst, src); |
| 843 } |
| 844 |
| 845 void AssemblerX86::divsd(XmmRegister dst, XmmRegister src) { |
| 846 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 847 EmitUint8(0xF2); |
| 848 EmitUint8(0x0F); |
| 849 EmitUint8(0x5E); |
| 850 EmitXmmRegisterOperand(dst, src); |
| 851 } |
| 852 |
| 853 void AssemblerX86::divsd(XmmRegister dst, const Address &src) { |
| 854 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 855 EmitUint8(0xF2); |
| 856 EmitUint8(0x0F); |
| 857 EmitUint8(0x5E); |
| 858 EmitOperand(dst, src); |
| 859 } |
| 860 |
| 861 void AssemblerX86::cvtsi2ss(XmmRegister dst, Register src) { |
| 862 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 863 EmitUint8(0xF3); |
| 864 EmitUint8(0x0F); |
| 865 EmitUint8(0x2A); |
| 866 EmitOperand(dst, Operand(src)); |
| 867 } |
| 868 |
| 869 void AssemblerX86::cvtsi2sd(XmmRegister dst, Register src) { |
| 870 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 871 EmitUint8(0xF2); |
| 872 EmitUint8(0x0F); |
| 873 EmitUint8(0x2A); |
| 874 EmitOperand(dst, Operand(src)); |
| 875 } |
| 876 |
| 877 void AssemblerX86::cvtss2si(Register dst, XmmRegister src) { |
| 878 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 879 EmitUint8(0xF3); |
| 880 EmitUint8(0x0F); |
| 881 EmitUint8(0x2D); |
| 882 EmitXmmRegisterOperand(dst, src); |
| 883 } |
| 884 |
| 885 void AssemblerX86::cvtss2sd(XmmRegister dst, XmmRegister src) { |
| 886 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 887 EmitUint8(0xF3); |
| 888 EmitUint8(0x0F); |
| 889 EmitUint8(0x5A); |
| 890 EmitXmmRegisterOperand(dst, src); |
| 891 } |
| 892 |
| 893 void AssemblerX86::cvtsd2si(Register dst, XmmRegister src) { |
| 894 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 895 EmitUint8(0xF2); |
| 896 EmitUint8(0x0F); |
| 897 EmitUint8(0x2D); |
| 898 EmitXmmRegisterOperand(dst, src); |
| 899 } |
| 900 |
| 901 void AssemblerX86::cvttss2si(Register dst, XmmRegister src) { |
| 902 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 903 EmitUint8(0xF3); |
| 904 EmitUint8(0x0F); |
| 905 EmitUint8(0x2C); |
| 906 EmitXmmRegisterOperand(dst, src); |
| 907 } |
| 908 |
| 909 void AssemblerX86::cvttsd2si(Register dst, XmmRegister src) { |
| 910 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 911 EmitUint8(0xF2); |
| 912 EmitUint8(0x0F); |
| 913 EmitUint8(0x2C); |
| 914 EmitXmmRegisterOperand(dst, src); |
| 915 } |
| 916 |
| 917 void AssemblerX86::cvtsd2ss(XmmRegister dst, XmmRegister src) { |
| 918 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 919 EmitUint8(0xF2); |
| 920 EmitUint8(0x0F); |
| 921 EmitUint8(0x5A); |
| 922 EmitXmmRegisterOperand(dst, src); |
| 923 } |
| 924 |
| 925 void AssemblerX86::cvtdq2pd(XmmRegister dst, XmmRegister src) { |
| 926 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 927 EmitUint8(0xF3); |
| 928 EmitUint8(0x0F); |
| 929 EmitUint8(0xE6); |
| 930 EmitXmmRegisterOperand(dst, src); |
| 931 } |
| 932 |
| 933 void AssemblerX86::comiss(XmmRegister a, XmmRegister b) { |
| 934 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 935 EmitUint8(0x0F); |
| 936 EmitUint8(0x2F); |
| 937 EmitXmmRegisterOperand(a, b); |
| 938 } |
| 939 |
| 940 void AssemblerX86::comisd(XmmRegister a, XmmRegister b) { |
| 941 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 942 EmitUint8(0x66); |
| 943 EmitUint8(0x0F); |
| 944 EmitUint8(0x2F); |
| 945 EmitXmmRegisterOperand(a, b); |
| 946 } |
| 947 |
| 948 void AssemblerX86::movmskpd(Register dst, XmmRegister src) { |
| 949 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 950 EmitUint8(0x66); |
| 951 EmitUint8(0x0F); |
| 952 EmitUint8(0x50); |
| 953 EmitXmmRegisterOperand(dst, src); |
| 954 } |
| 955 |
| 956 void AssemblerX86::movmskps(Register dst, XmmRegister src) { |
| 957 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 958 EmitUint8(0x0F); |
| 959 EmitUint8(0x50); |
| 960 EmitXmmRegisterOperand(dst, src); |
| 961 } |
| 962 |
| 963 void AssemblerX86::sqrtsd(XmmRegister dst, const Address &src) { |
| 964 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 965 EmitUint8(0xF2); |
| 966 EmitUint8(0x0F); |
| 967 EmitUint8(0x51); |
| 968 EmitOperand(dst, src); |
| 969 } |
| 970 |
| 971 void AssemblerX86::sqrtsd(XmmRegister dst, XmmRegister src) { |
| 972 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 973 EmitUint8(0xF2); |
| 974 EmitUint8(0x0F); |
| 975 EmitUint8(0x51); |
| 976 EmitXmmRegisterOperand(dst, src); |
| 977 } |
| 978 |
| 979 void AssemblerX86::sqrtss(XmmRegister dst, const Address &src) { |
| 980 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 981 EmitUint8(0xF3); |
| 982 EmitUint8(0x0F); |
| 983 EmitUint8(0x51); |
| 984 EmitOperand(dst, src); |
| 985 } |
| 986 |
| 987 void AssemblerX86::sqrtss(XmmRegister dst, XmmRegister src) { |
| 988 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 989 EmitUint8(0xF3); |
| 990 EmitUint8(0x0F); |
| 991 EmitUint8(0x51); |
| 992 EmitXmmRegisterOperand(dst, src); |
| 993 } |
| 994 |
| 995 void AssemblerX86::xorpd(XmmRegister dst, const Address &src) { |
| 996 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 997 EmitUint8(0x66); |
| 998 EmitUint8(0x0F); |
| 999 EmitUint8(0x57); |
| 1000 EmitOperand(dst, src); |
| 1001 } |
| 1002 |
| 1003 void AssemblerX86::xorpd(XmmRegister dst, XmmRegister src) { |
| 1004 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1005 EmitUint8(0x66); |
| 1006 EmitUint8(0x0F); |
| 1007 EmitUint8(0x57); |
| 1008 EmitXmmRegisterOperand(dst, src); |
| 1009 } |
| 1010 |
| 1011 void AssemblerX86::orpd(XmmRegister dst, XmmRegister src) { |
| 1012 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1013 EmitUint8(0x66); |
| 1014 EmitUint8(0x0F); |
| 1015 EmitUint8(0x56); |
| 1016 EmitXmmRegisterOperand(dst, src); |
| 1017 } |
| 1018 |
| 1019 void AssemblerX86::xorps(XmmRegister dst, const Address &src) { |
| 1020 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1021 EmitUint8(0x0F); |
| 1022 EmitUint8(0x57); |
| 1023 EmitOperand(dst, src); |
| 1024 } |
| 1025 |
| 1026 void AssemblerX86::xorps(XmmRegister dst, XmmRegister src) { |
| 1027 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1028 EmitUint8(0x0F); |
| 1029 EmitUint8(0x57); |
| 1030 EmitXmmRegisterOperand(dst, src); |
| 1031 } |
| 1032 |
| 1033 void AssemblerX86::andpd(XmmRegister dst, const Address &src) { |
| 1034 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1035 EmitUint8(0x66); |
| 1036 EmitUint8(0x0F); |
| 1037 EmitUint8(0x54); |
| 1038 EmitOperand(dst, src); |
| 1039 } |
| 1040 |
| 1041 void AssemblerX86::andpd(XmmRegister dst, XmmRegister src) { |
| 1042 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1043 EmitUint8(0x66); |
| 1044 EmitUint8(0x0F); |
| 1045 EmitUint8(0x54); |
| 1046 EmitXmmRegisterOperand(dst, src); |
| 1047 } |
| 1048 |
| 1049 void AssemblerX86::pextrd(Register dst, XmmRegister src, const Immediate &imm) { |
| 1050 // TODO(jvoung): Check Ice instead. |
| 1051 // assert(TargetCPUFeatures::sse4_1_supported()); |
| 1052 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1053 EmitUint8(0x66); |
| 1054 EmitUint8(0x0F); |
| 1055 EmitUint8(0x3A); |
| 1056 EmitUint8(0x16); |
| 1057 EmitOperand(src, Operand(dst)); |
| 1058 assert(imm.is_uint8()); |
| 1059 EmitUint8(imm.value()); |
| 1060 } |
| 1061 |
| 1062 void AssemblerX86::pmovsxdq(XmmRegister dst, XmmRegister src) { |
| 1063 // assert(TargetCPUFeatures::sse4_1_supported()); |
| 1064 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1065 EmitUint8(0x66); |
| 1066 EmitUint8(0x0F); |
| 1067 EmitUint8(0x38); |
| 1068 EmitUint8(0x25); |
| 1069 EmitXmmRegisterOperand(dst, src); |
| 1070 } |
| 1071 |
| 1072 void AssemblerX86::pcmpeqq(XmmRegister dst, XmmRegister src) { |
| 1073 // assert(TargetCPUFeatures::sse4_1_supported()); |
| 1074 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1075 EmitUint8(0x66); |
| 1076 EmitUint8(0x0F); |
| 1077 EmitUint8(0x38); |
| 1078 EmitUint8(0x29); |
| 1079 EmitXmmRegisterOperand(dst, src); |
| 1080 } |
| 1081 |
| 1082 void AssemblerX86::pxor(XmmRegister dst, XmmRegister src) { |
| 1083 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1084 EmitUint8(0x66); |
| 1085 EmitUint8(0x0F); |
| 1086 EmitUint8(0xEF); |
| 1087 EmitXmmRegisterOperand(dst, src); |
| 1088 } |
| 1089 |
| 1090 void AssemblerX86::roundsd(XmmRegister dst, XmmRegister src, |
| 1091 RoundingMode mode) { |
| 1092 // assert(TargetCPUFeatures::sse4_1_supported()); |
| 1093 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1094 EmitUint8(0x66); |
| 1095 EmitUint8(0x0F); |
| 1096 EmitUint8(0x3A); |
| 1097 EmitUint8(0x0B); |
| 1098 EmitXmmRegisterOperand(dst, src); |
| 1099 // Mask precision exeption. |
| 1100 EmitUint8(static_cast<uint8_t>(mode) | 0x8); |
| 1101 } |
| 1102 |
| 1103 void AssemblerX86::fldl(const Address &src) { |
| 1104 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1105 EmitUint8(0xDD); |
| 1106 EmitOperand(0, src); |
| 1107 } |
| 1108 |
| 1109 void AssemblerX86::fstpl(const Address &dst) { |
| 1110 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1111 EmitUint8(0xDD); |
| 1112 EmitOperand(3, dst); |
| 1113 } |
| 1114 |
| 1115 void AssemblerX86::fnstcw(const Address &dst) { |
| 1116 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1117 EmitUint8(0xD9); |
| 1118 EmitOperand(7, dst); |
| 1119 } |
| 1120 |
| 1121 void AssemblerX86::fldcw(const Address &src) { |
| 1122 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1123 EmitUint8(0xD9); |
| 1124 EmitOperand(5, src); |
| 1125 } |
| 1126 |
| 1127 void AssemblerX86::fistpl(const Address &dst) { |
| 1128 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1129 EmitUint8(0xDF); |
| 1130 EmitOperand(7, dst); |
| 1131 } |
| 1132 |
| 1133 void AssemblerX86::fistps(const Address &dst) { |
| 1134 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1135 EmitUint8(0xDB); |
| 1136 EmitOperand(3, dst); |
| 1137 } |
| 1138 |
| 1139 void AssemblerX86::fildl(const Address &src) { |
| 1140 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1141 EmitUint8(0xDF); |
| 1142 EmitOperand(5, src); |
| 1143 } |
| 1144 |
| 1145 void AssemblerX86::filds(const Address &src) { |
| 1146 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1147 EmitUint8(0xDB); |
| 1148 EmitOperand(0, src); |
| 1149 } |
| 1150 |
| 1151 void AssemblerX86::fincstp() { |
| 1152 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1153 EmitUint8(0xD9); |
| 1154 EmitUint8(0xF7); |
| 1155 } |
| 1156 |
| 1157 void AssemblerX86::xchgl(Register dst, Register src) { |
| 1158 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1159 EmitUint8(0x87); |
| 1160 EmitRegisterOperand(dst, src); |
| 1161 } |
| 1162 |
| 1163 void AssemblerX86::cmpl(Register reg, const Immediate &imm) { |
| 1164 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1165 EmitComplex(7, Operand(reg), imm); |
| 1166 } |
| 1167 |
| 1168 void AssemblerX86::cmpl(Register reg0, Register reg1) { |
| 1169 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1170 EmitUint8(0x3B); |
| 1171 EmitOperand(reg0, Operand(reg1)); |
| 1172 } |
| 1173 |
| 1174 void AssemblerX86::cmpl(Register reg, const Address &address) { |
| 1175 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1176 EmitUint8(0x3B); |
| 1177 EmitOperand(reg, address); |
| 1178 } |
| 1179 |
| 1180 void AssemblerX86::cmpl(const Address &address, Register reg) { |
| 1181 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1182 EmitUint8(0x39); |
| 1183 EmitOperand(reg, address); |
| 1184 } |
| 1185 |
| 1186 void AssemblerX86::cmpl(const Address &address, const Immediate &imm) { |
| 1187 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1188 EmitComplex(7, address, imm); |
| 1189 } |
| 1190 |
| 1191 void AssemblerX86::cmpb(const Address &address, const Immediate &imm) { |
| 1192 assert(imm.is_int8()); |
| 1193 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1194 EmitUint8(0x80); |
| 1195 EmitOperand(7, address); |
| 1196 EmitUint8(imm.value() & 0xFF); |
| 1197 } |
| 1198 |
| 1199 void AssemblerX86::testl(Register reg1, Register reg2) { |
| 1200 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1201 EmitUint8(0x85); |
| 1202 EmitRegisterOperand(reg1, reg2); |
| 1203 } |
| 1204 |
| 1205 void AssemblerX86::testl(Register reg, const Immediate &immediate) { |
| 1206 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1207 // For registers that have a byte variant (EAX, EBX, ECX, and EDX) |
| 1208 // we only test the byte register to keep the encoding short. |
| 1209 if (immediate.is_uint8() && reg < 4) { |
| 1210 // Use zero-extended 8-bit immediate. |
| 1211 if (reg == EAX) { |
| 1212 EmitUint8(0xA8); |
| 1213 } else { |
| 1214 EmitUint8(0xF6); |
| 1215 EmitUint8(0xC0 + reg); |
| 1216 } |
| 1217 EmitUint8(immediate.value() & 0xFF); |
| 1218 } else if (reg == EAX) { |
| 1219 // Use short form if the destination is EAX. |
| 1220 EmitUint8(0xA9); |
| 1221 EmitImmediate(immediate); |
| 1222 } else { |
| 1223 EmitUint8(0xF7); |
| 1224 EmitOperand(0, Operand(reg)); |
| 1225 EmitImmediate(immediate); |
| 1226 } |
| 1227 } |
| 1228 |
| 1229 void AssemblerX86::andl(Register dst, Register src) { |
| 1230 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1231 EmitUint8(0x23); |
| 1232 EmitOperand(dst, Operand(src)); |
| 1233 } |
| 1234 |
| 1235 void AssemblerX86::andl(Register dst, const Immediate &imm) { |
| 1236 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1237 EmitComplex(4, Operand(dst), imm); |
| 1238 } |
| 1239 |
| 1240 void AssemblerX86::andl(Register dst, const Address &address) { |
| 1241 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1242 EmitUint8(0x23); |
| 1243 EmitOperand(dst, address); |
| 1244 } |
| 1245 |
| 1246 void AssemblerX86::orl(Register dst, Register src) { |
| 1247 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1248 EmitUint8(0x0B); |
| 1249 EmitOperand(dst, Operand(src)); |
| 1250 } |
| 1251 |
| 1252 void AssemblerX86::orl(Register dst, const Immediate &imm) { |
| 1253 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1254 EmitComplex(1, Operand(dst), imm); |
| 1255 } |
| 1256 |
| 1257 void AssemblerX86::orl(Register dst, const Address &address) { |
| 1258 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1259 EmitUint8(0x0B); |
| 1260 EmitOperand(dst, address); |
| 1261 } |
| 1262 |
| 1263 void AssemblerX86::xorl(Register dst, Register src) { |
| 1264 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1265 EmitUint8(0x33); |
| 1266 EmitOperand(dst, Operand(src)); |
| 1267 } |
| 1268 |
| 1269 void AssemblerX86::xorl(Register dst, const Immediate &imm) { |
| 1270 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1271 EmitComplex(6, Operand(dst), imm); |
| 1272 } |
| 1273 |
| 1274 void AssemblerX86::xorl(Register dst, const Address &address) { |
| 1275 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1276 EmitUint8(0x33); |
| 1277 EmitOperand(dst, address); |
| 1278 } |
| 1279 |
| 1280 void AssemblerX86::addl(Register reg, const Immediate &imm) { |
| 1281 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1282 EmitComplex(0, Operand(reg), imm); |
| 1283 } |
| 1284 |
| 1285 void AssemblerX86::addl(const Address &address, Register reg) { |
| 1286 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1287 EmitUint8(0x01); |
| 1288 EmitOperand(reg, address); |
| 1289 } |
| 1290 |
| 1291 void AssemblerX86::addl(const Address &address, const Immediate &imm) { |
| 1292 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1293 EmitComplex(0, address, imm); |
| 1294 } |
| 1295 |
| 1296 void AssemblerX86::addl(Register dst, Register src) { |
| 1297 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1298 EmitUint8(0x03); |
| 1299 EmitRegisterOperand(dst, src); |
| 1300 } |
| 1301 |
| 1302 void AssemblerX86::addl(Register reg, const Address &address) { |
| 1303 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1304 EmitUint8(0x03); |
| 1305 EmitOperand(reg, address); |
| 1306 } |
| 1307 |
| 1308 void AssemblerX86::adcl(Register reg, const Immediate &imm) { |
| 1309 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1310 EmitComplex(2, Operand(reg), imm); |
| 1311 } |
| 1312 |
| 1313 void AssemblerX86::adcl(Register dst, Register src) { |
| 1314 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1315 EmitUint8(0x13); |
| 1316 EmitOperand(dst, Operand(src)); |
| 1317 } |
| 1318 |
| 1319 void AssemblerX86::adcl(Register dst, const Address &address) { |
| 1320 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1321 EmitUint8(0x13); |
| 1322 EmitOperand(dst, address); |
| 1323 } |
| 1324 |
| 1325 void AssemblerX86::adcl(const Address &address, Register reg) { |
| 1326 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1327 EmitUint8(0x11); |
| 1328 EmitOperand(reg, address); |
| 1329 } |
| 1330 |
| 1331 void AssemblerX86::subl(Register dst, Register src) { |
| 1332 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1333 EmitUint8(0x2B); |
| 1334 EmitOperand(dst, Operand(src)); |
| 1335 } |
| 1336 |
| 1337 void AssemblerX86::subl(Register reg, const Immediate &imm) { |
| 1338 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1339 EmitComplex(5, Operand(reg), imm); |
| 1340 } |
| 1341 |
| 1342 void AssemblerX86::subl(Register reg, const Address &address) { |
| 1343 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1344 EmitUint8(0x2B); |
| 1345 EmitOperand(reg, address); |
| 1346 } |
| 1347 |
| 1348 void AssemblerX86::subl(const Address &address, Register reg) { |
| 1349 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1350 EmitUint8(0x29); |
| 1351 EmitOperand(reg, address); |
| 1352 } |
| 1353 |
| 1354 void AssemblerX86::cbw() { |
| 1355 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1356 EmitOperandSizeOverride(); |
| 1357 EmitUint8(0x98); |
| 1358 } |
| 1359 |
| 1360 void AssemblerX86::cwd() { |
| 1361 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1362 EmitOperandSizeOverride(); |
| 1363 EmitUint8(0x99); |
| 1364 } |
| 1365 |
| 1366 void AssemblerX86::cdq() { |
| 1367 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1368 EmitUint8(0x99); |
| 1369 } |
| 1370 |
| 1371 void AssemblerX86::idivl(Register reg) { |
| 1372 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1373 EmitUint8(0xF7); |
| 1374 EmitUint8(0xF8 | reg); |
| 1375 } |
| 1376 |
| 1377 void AssemblerX86::imull(Register dst, Register src) { |
| 1378 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1379 EmitUint8(0x0F); |
| 1380 EmitUint8(0xAF); |
| 1381 EmitOperand(dst, Operand(src)); |
| 1382 } |
| 1383 |
| 1384 void AssemblerX86::imull(Register reg, const Immediate &imm) { |
| 1385 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1386 EmitUint8(0x69); |
| 1387 EmitOperand(reg, Operand(reg)); |
| 1388 EmitImmediate(imm); |
| 1389 } |
| 1390 |
| 1391 void AssemblerX86::imull(Register reg, const Address &address) { |
| 1392 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1393 EmitUint8(0x0F); |
| 1394 EmitUint8(0xAF); |
| 1395 EmitOperand(reg, address); |
| 1396 } |
| 1397 |
| 1398 void AssemblerX86::imull(Register reg) { |
| 1399 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1400 EmitUint8(0xF7); |
| 1401 EmitOperand(5, Operand(reg)); |
| 1402 } |
| 1403 |
| 1404 void AssemblerX86::imull(const Address &address) { |
| 1405 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1406 EmitUint8(0xF7); |
| 1407 EmitOperand(5, address); |
| 1408 } |
| 1409 |
| 1410 void AssemblerX86::mull(Register reg) { |
| 1411 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1412 EmitUint8(0xF7); |
| 1413 EmitOperand(4, Operand(reg)); |
| 1414 } |
| 1415 |
| 1416 void AssemblerX86::mull(const Address &address) { |
| 1417 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1418 EmitUint8(0xF7); |
| 1419 EmitOperand(4, address); |
| 1420 } |
| 1421 |
| 1422 void AssemblerX86::sbbl(Register dst, Register src) { |
| 1423 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1424 EmitUint8(0x1B); |
| 1425 EmitOperand(dst, Operand(src)); |
| 1426 } |
| 1427 |
| 1428 void AssemblerX86::sbbl(Register reg, const Immediate &imm) { |
| 1429 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1430 EmitComplex(3, Operand(reg), imm); |
| 1431 } |
| 1432 |
| 1433 void AssemblerX86::sbbl(Register dst, const Address &address) { |
| 1434 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1435 EmitUint8(0x1B); |
| 1436 EmitOperand(dst, address); |
| 1437 } |
| 1438 |
| 1439 void AssemblerX86::sbbl(const Address &address, Register dst) { |
| 1440 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1441 EmitUint8(0x19); |
| 1442 EmitOperand(dst, address); |
| 1443 } |
| 1444 |
| 1445 void AssemblerX86::incl(Register reg) { |
| 1446 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1447 EmitUint8(0x40 + reg); |
| 1448 } |
| 1449 |
| 1450 void AssemblerX86::incl(const Address &address) { |
| 1451 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1452 EmitUint8(0xFF); |
| 1453 EmitOperand(0, address); |
| 1454 } |
| 1455 |
| 1456 void AssemblerX86::decl(Register reg) { |
| 1457 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1458 EmitUint8(0x48 + reg); |
| 1459 } |
| 1460 |
| 1461 void AssemblerX86::decl(const Address &address) { |
| 1462 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1463 EmitUint8(0xFF); |
| 1464 EmitOperand(1, address); |
| 1465 } |
| 1466 |
| 1467 void AssemblerX86::shll(Register reg, const Immediate &imm) { |
| 1468 EmitGenericShift(4, reg, imm); |
| 1469 } |
| 1470 |
| 1471 void AssemblerX86::shll(Register operand, Register shifter) { |
| 1472 EmitGenericShift(4, Operand(operand), shifter); |
| 1473 } |
| 1474 |
| 1475 void AssemblerX86::shll(const Address &operand, Register shifter) { |
| 1476 EmitGenericShift(4, Operand(operand), shifter); |
| 1477 } |
| 1478 |
| 1479 void AssemblerX86::shrl(Register reg, const Immediate &imm) { |
| 1480 EmitGenericShift(5, reg, imm); |
| 1481 } |
| 1482 |
| 1483 void AssemblerX86::shrl(Register operand, Register shifter) { |
| 1484 EmitGenericShift(5, Operand(operand), shifter); |
| 1485 } |
| 1486 |
| 1487 void AssemblerX86::sarl(Register reg, const Immediate &imm) { |
| 1488 EmitGenericShift(7, reg, imm); |
| 1489 } |
| 1490 |
| 1491 void AssemblerX86::sarl(Register operand, Register shifter) { |
| 1492 EmitGenericShift(7, Operand(operand), shifter); |
| 1493 } |
| 1494 |
| 1495 void AssemblerX86::sarl(const Address &address, Register shifter) { |
| 1496 EmitGenericShift(7, Operand(address), shifter); |
| 1497 } |
| 1498 |
| 1499 void AssemblerX86::shld(Register dst, Register src) { |
| 1500 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1501 EmitUint8(0x0F); |
| 1502 EmitUint8(0xA5); |
| 1503 EmitRegisterOperand(src, dst); |
| 1504 } |
| 1505 |
| 1506 void AssemblerX86::shld(Register dst, Register src, const Immediate &imm) { |
| 1507 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1508 assert(imm.is_int8()); |
| 1509 EmitUint8(0x0F); |
| 1510 EmitUint8(0xA4); |
| 1511 EmitRegisterOperand(src, dst); |
| 1512 EmitUint8(imm.value() & 0xFF); |
| 1513 } |
| 1514 |
| 1515 void AssemblerX86::shld(const Address &operand, Register src) { |
| 1516 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1517 EmitUint8(0x0F); |
| 1518 EmitUint8(0xA5); |
| 1519 EmitOperand(src, Operand(operand)); |
| 1520 } |
| 1521 |
| 1522 void AssemblerX86::shrd(Register dst, Register src) { |
| 1523 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1524 EmitUint8(0x0F); |
| 1525 EmitUint8(0xAD); |
| 1526 EmitRegisterOperand(src, dst); |
| 1527 } |
| 1528 |
| 1529 void AssemblerX86::shrd(Register dst, Register src, const Immediate &imm) { |
| 1530 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1531 assert(imm.is_int8()); |
| 1532 EmitUint8(0x0F); |
| 1533 EmitUint8(0xAC); |
| 1534 EmitRegisterOperand(src, dst); |
| 1535 EmitUint8(imm.value() & 0xFF); |
| 1536 } |
| 1537 |
| 1538 void AssemblerX86::shrd(const Address &dst, Register src) { |
| 1539 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1540 EmitUint8(0x0F); |
| 1541 EmitUint8(0xAD); |
| 1542 EmitOperand(src, Operand(dst)); |
| 1543 } |
| 1544 |
| 1545 void AssemblerX86::negl(Register reg) { |
| 1546 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1547 EmitUint8(0xF7); |
| 1548 EmitOperand(3, Operand(reg)); |
| 1549 } |
| 1550 |
| 1551 void AssemblerX86::notl(Register reg) { |
| 1552 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1553 EmitUint8(0xF7); |
| 1554 EmitUint8(0xD0 | reg); |
| 1555 } |
| 1556 |
| 1557 void AssemblerX86::bsrl(Register dst, Register src) { |
| 1558 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1559 EmitUint8(0x0F); |
| 1560 EmitUint8(0xBD); |
| 1561 EmitRegisterOperand(dst, src); |
| 1562 } |
| 1563 |
| 1564 void AssemblerX86::bt(Register base, Register offset) { |
| 1565 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1566 EmitUint8(0x0F); |
| 1567 EmitUint8(0xA3); |
| 1568 EmitRegisterOperand(offset, base); |
| 1569 } |
| 1570 |
| 1571 void AssemblerX86::enter(const Immediate &imm) { |
| 1572 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1573 EmitUint8(0xC8); |
| 1574 assert(imm.is_uint16()); |
| 1575 EmitUint8(imm.value() & 0xFF); |
| 1576 EmitUint8((imm.value() >> 8) & 0xFF); |
| 1577 EmitUint8(0x00); |
| 1578 } |
| 1579 |
| 1580 void AssemblerX86::leave() { |
| 1581 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1582 EmitUint8(0xC9); |
| 1583 } |
| 1584 |
| 1585 void AssemblerX86::ret() { |
| 1586 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1587 EmitUint8(0xC3); |
| 1588 } |
| 1589 |
| 1590 void AssemblerX86::ret(const Immediate &imm) { |
| 1591 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1592 EmitUint8(0xC2); |
| 1593 assert(imm.is_uint16()); |
| 1594 EmitUint8(imm.value() & 0xFF); |
| 1595 EmitUint8((imm.value() >> 8) & 0xFF); |
| 1596 } |
| 1597 |
| 1598 void AssemblerX86::nop(int size) { |
| 1599 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1600 // There are nops up to size 15, but for now just provide up to size 8. |
| 1601 assert(0 < size && size <= MAX_NOP_SIZE); |
| 1602 switch (size) { |
| 1603 case 1: |
| 1604 EmitUint8(0x90); |
| 1605 break; |
| 1606 case 2: |
| 1607 EmitUint8(0x66); |
| 1608 EmitUint8(0x90); |
| 1609 break; |
| 1610 case 3: |
| 1611 EmitUint8(0x0F); |
| 1612 EmitUint8(0x1F); |
| 1613 EmitUint8(0x00); |
| 1614 break; |
| 1615 case 4: |
| 1616 EmitUint8(0x0F); |
| 1617 EmitUint8(0x1F); |
| 1618 EmitUint8(0x40); |
| 1619 EmitUint8(0x00); |
| 1620 break; |
| 1621 case 5: |
| 1622 EmitUint8(0x0F); |
| 1623 EmitUint8(0x1F); |
| 1624 EmitUint8(0x44); |
| 1625 EmitUint8(0x00); |
| 1626 EmitUint8(0x00); |
| 1627 break; |
| 1628 case 6: |
| 1629 EmitUint8(0x66); |
| 1630 EmitUint8(0x0F); |
| 1631 EmitUint8(0x1F); |
| 1632 EmitUint8(0x44); |
| 1633 EmitUint8(0x00); |
| 1634 EmitUint8(0x00); |
| 1635 break; |
| 1636 case 7: |
| 1637 EmitUint8(0x0F); |
| 1638 EmitUint8(0x1F); |
| 1639 EmitUint8(0x80); |
| 1640 EmitUint8(0x00); |
| 1641 EmitUint8(0x00); |
| 1642 EmitUint8(0x00); |
| 1643 EmitUint8(0x00); |
| 1644 break; |
| 1645 case 8: |
| 1646 EmitUint8(0x0F); |
| 1647 EmitUint8(0x1F); |
| 1648 EmitUint8(0x84); |
| 1649 EmitUint8(0x00); |
| 1650 EmitUint8(0x00); |
| 1651 EmitUint8(0x00); |
| 1652 EmitUint8(0x00); |
| 1653 EmitUint8(0x00); |
| 1654 break; |
| 1655 default: |
| 1656 llvm_unreachable("UNIMPLEMENTED"); |
| 1657 } |
| 1658 } |
| 1659 |
| 1660 void AssemblerX86::int3() { |
| 1661 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1662 EmitUint8(0xCC); |
| 1663 } |
| 1664 |
| 1665 void AssemblerX86::hlt() { |
| 1666 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1667 EmitUint8(0xF4); |
| 1668 } |
| 1669 |
| 1670 void AssemblerX86::j(Condition condition, Label *label, bool near) { |
| 1671 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1672 if (label->IsBound()) { |
| 1673 static const int kShortSize = 2; |
| 1674 static const int kLongSize = 6; |
| 1675 intptr_t offset = label->Position() - buffer_.Size(); |
| 1676 assert(offset <= 0); |
| 1677 if (Utils::IsInt(8, offset - kShortSize)) { |
| 1678 EmitUint8(0x70 + condition); |
| 1679 EmitUint8((offset - kShortSize) & 0xFF); |
| 1680 } else { |
| 1681 EmitUint8(0x0F); |
| 1682 EmitUint8(0x80 + condition); |
| 1683 EmitInt32(offset - kLongSize); |
| 1684 } |
| 1685 } else if (near) { |
| 1686 EmitUint8(0x70 + condition); |
| 1687 EmitNearLabelLink(label); |
| 1688 } else { |
| 1689 EmitUint8(0x0F); |
| 1690 EmitUint8(0x80 + condition); |
| 1691 EmitLabelLink(label); |
| 1692 } |
| 1693 } |
| 1694 |
| 1695 void AssemblerX86::j(Condition condition, const ConstantRelocatable *label) { |
| 1696 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1697 EmitUint8(0x0F); |
| 1698 EmitUint8(0x80 + condition); |
| 1699 // TODO(jvoung): actually track the target. |
| 1700 (void)label; |
| 1701 EmitFixup(new (this->Allocate<DirectCallRelocation>()) |
| 1702 DirectCallRelocation()); |
| 1703 EmitInt32(-4); |
| 1704 } |
| 1705 |
| 1706 void AssemblerX86::jmp(Register reg) { |
| 1707 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1708 EmitUint8(0xFF); |
| 1709 EmitRegisterOperand(4, reg); |
| 1710 } |
| 1711 |
| 1712 void AssemblerX86::jmp(Label *label, bool near) { |
| 1713 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1714 if (label->IsBound()) { |
| 1715 static const int kShortSize = 2; |
| 1716 static const int kLongSize = 5; |
| 1717 intptr_t offset = label->Position() - buffer_.Size(); |
| 1718 assert(offset <= 0); |
| 1719 if (Utils::IsInt(8, offset - kShortSize)) { |
| 1720 EmitUint8(0xEB); |
| 1721 EmitUint8((offset - kShortSize) & 0xFF); |
| 1722 } else { |
| 1723 EmitUint8(0xE9); |
| 1724 EmitInt32(offset - kLongSize); |
| 1725 } |
| 1726 } else if (near) { |
| 1727 EmitUint8(0xEB); |
| 1728 EmitNearLabelLink(label); |
| 1729 } else { |
| 1730 EmitUint8(0xE9); |
| 1731 EmitLabelLink(label); |
| 1732 } |
| 1733 } |
| 1734 |
| 1735 void AssemblerX86::jmp(const ConstantRelocatable *label) { |
| 1736 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1737 EmitUint8(0xE9); |
| 1738 // TODO(jvoung): Actually track the target. |
| 1739 (void)label; |
| 1740 EmitFixup(new (this->Allocate<DirectCallRelocation>()) |
| 1741 DirectCallRelocation()); |
| 1742 EmitInt32(-4); |
| 1743 } |
| 1744 |
| 1745 void AssemblerX86::lock() { |
| 1746 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1747 EmitUint8(0xF0); |
| 1748 } |
| 1749 |
| 1750 void AssemblerX86::cmpxchgl(const Address &address, Register reg) { |
| 1751 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1752 EmitUint8(0x0F); |
| 1753 EmitUint8(0xB1); |
| 1754 EmitOperand(reg, address); |
| 1755 } |
| 1756 |
| 1757 void AssemblerX86::cpuid() { |
| 1758 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1759 EmitUint8(0x0F); |
| 1760 EmitUint8(0xA2); |
| 1761 } |
| 1762 |
| 1763 void AssemblerX86::AddImmediate(Register reg, const Immediate &imm) { |
| 1764 const intptr_t value = imm.value(); |
| 1765 if (value == 0) { |
| 1766 return; |
| 1767 } |
| 1768 if ((value > 0) || (value == std::numeric_limits<int32_t>::min())) { |
| 1769 if (value == 1) { |
| 1770 incl(reg); |
| 1771 } else { |
| 1772 addl(reg, imm); |
| 1773 } |
| 1774 } else { |
| 1775 SubImmediate(reg, Immediate(-value)); |
| 1776 } |
| 1777 } |
| 1778 |
| 1779 void AssemblerX86::SubImmediate(Register reg, const Immediate &imm) { |
| 1780 const intptr_t value = imm.value(); |
| 1781 if (value == 0) { |
| 1782 return; |
| 1783 } |
| 1784 if ((value > 0) || (value == std::numeric_limits<int32_t>::min())) { |
| 1785 if (value == 1) { |
| 1786 decl(reg); |
| 1787 } else { |
| 1788 subl(reg, imm); |
| 1789 } |
| 1790 } else { |
| 1791 AddImmediate(reg, Immediate(-value)); |
| 1792 } |
| 1793 } |
| 1794 |
| 1795 void AssemblerX86::FloatNegate(XmmRegister f) { |
| 1796 static const struct ALIGN16 { |
| 1797 uint32_t a; |
| 1798 uint32_t b; |
| 1799 uint32_t c; |
| 1800 uint32_t d; |
| 1801 } float_negate_constant = {0x80000000, 0x00000000, 0x80000000, 0x00000000}; |
| 1802 xorps(f, |
| 1803 Address::Absolute(reinterpret_cast<uintptr_t>(&float_negate_constant))); |
| 1804 } |
| 1805 |
| 1806 void AssemblerX86::DoubleNegate(XmmRegister d) { |
| 1807 static const struct ALIGN16 { |
| 1808 uint64_t a; |
| 1809 uint64_t b; |
| 1810 } double_negate_constant = {0x8000000000000000LL, 0x8000000000000000LL}; |
| 1811 xorpd(d, Address::Absolute( |
| 1812 reinterpret_cast<uintptr_t>(&double_negate_constant))); |
| 1813 } |
| 1814 |
| 1815 void AssemblerX86::DoubleAbs(XmmRegister reg) { |
| 1816 static const struct ALIGN16 { |
| 1817 uint64_t a; |
| 1818 uint64_t b; |
| 1819 } double_abs_constant = {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}; |
| 1820 andpd(reg, |
| 1821 Address::Absolute(reinterpret_cast<uintptr_t>(&double_abs_constant))); |
| 1822 } |
| 1823 |
| 1824 void AssemblerX86::Align(intptr_t alignment, intptr_t offset) { |
| 1825 assert(llvm::isPowerOf2_32(alignment)); |
| 1826 intptr_t pos = offset + buffer_.GetPosition(); |
| 1827 intptr_t mod = pos & (alignment - 1); |
| 1828 if (mod == 0) { |
| 1829 return; |
| 1830 } |
| 1831 intptr_t bytes_needed = alignment - mod; |
| 1832 while (bytes_needed > MAX_NOP_SIZE) { |
| 1833 nop(MAX_NOP_SIZE); |
| 1834 bytes_needed -= MAX_NOP_SIZE; |
| 1835 } |
| 1836 if (bytes_needed) { |
| 1837 nop(bytes_needed); |
| 1838 } |
| 1839 assert(((offset + buffer_.GetPosition()) & (alignment - 1)) == 0); |
| 1840 } |
| 1841 |
| 1842 void AssemblerX86::Bind(Label *label) { |
| 1843 intptr_t bound = buffer_.Size(); |
| 1844 assert(!label->IsBound()); // Labels can only be bound once. |
| 1845 while (label->IsLinked()) { |
| 1846 intptr_t position = label->LinkPosition(); |
| 1847 intptr_t next = buffer_.Load<int32_t>(position); |
| 1848 buffer_.Store<int32_t>(position, bound - (position + 4)); |
| 1849 label->position_ = next; |
| 1850 } |
| 1851 while (label->HasNear()) { |
| 1852 intptr_t position = label->NearPosition(); |
| 1853 intptr_t offset = bound - (position + 1); |
| 1854 assert(Utils::IsInt(8, offset)); |
| 1855 buffer_.Store<int8_t>(position, offset); |
| 1856 } |
| 1857 label->BindTo(bound); |
| 1858 } |
| 1859 |
| 1860 void AssemblerX86::EmitOperand(int rm, const Operand &operand) { |
| 1861 assert(rm >= 0 && rm < 8); |
| 1862 const intptr_t length = operand.length_; |
| 1863 assert(length > 0); |
| 1864 // Emit the ModRM byte updated with the given RM value. |
| 1865 assert((operand.encoding_[0] & 0x38) == 0); |
| 1866 EmitUint8(operand.encoding_[0] + (rm << 3)); |
| 1867 // Emit the rest of the encoded operand. |
| 1868 for (intptr_t i = 1; i < length; i++) { |
| 1869 EmitUint8(operand.encoding_[i]); |
| 1870 } |
| 1871 } |
| 1872 |
| 1873 void AssemblerX86::EmitImmediate(const Immediate &imm) { |
| 1874 EmitInt32(imm.value()); |
| 1875 } |
| 1876 |
| 1877 void AssemblerX86::EmitComplex(int rm, const Operand &operand, |
| 1878 const Immediate &immediate) { |
| 1879 assert(rm >= 0 && rm < 8); |
| 1880 if (immediate.is_int8()) { |
| 1881 // Use sign-extended 8-bit immediate. |
| 1882 EmitUint8(0x83); |
| 1883 EmitOperand(rm, operand); |
| 1884 EmitUint8(immediate.value() & 0xFF); |
| 1885 } else if (operand.IsRegister(EAX)) { |
| 1886 // Use short form if the destination is eax. |
| 1887 EmitUint8(0x05 + (rm << 3)); |
| 1888 EmitImmediate(immediate); |
| 1889 } else { |
| 1890 EmitUint8(0x81); |
| 1891 EmitOperand(rm, operand); |
| 1892 EmitImmediate(immediate); |
| 1893 } |
| 1894 } |
| 1895 |
| 1896 void AssemblerX86::EmitLabel(Label *label, intptr_t instruction_size) { |
| 1897 if (label->IsBound()) { |
| 1898 intptr_t offset = label->Position() - buffer_.Size(); |
| 1899 assert(offset <= 0); |
| 1900 EmitInt32(offset - instruction_size); |
| 1901 } else { |
| 1902 EmitLabelLink(label); |
| 1903 } |
| 1904 } |
| 1905 |
| 1906 void AssemblerX86::EmitLabelLink(Label *label) { |
| 1907 assert(!label->IsBound()); |
| 1908 intptr_t position = buffer_.Size(); |
| 1909 EmitInt32(label->position_); |
| 1910 label->LinkTo(position); |
| 1911 } |
| 1912 |
| 1913 void AssemblerX86::EmitNearLabelLink(Label *label) { |
| 1914 assert(!label->IsBound()); |
| 1915 intptr_t position = buffer_.Size(); |
| 1916 EmitUint8(0); |
| 1917 label->NearLinkTo(position); |
| 1918 } |
| 1919 |
| 1920 void AssemblerX86::EmitGenericShift(int rm, Register reg, |
| 1921 const Immediate &imm) { |
| 1922 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1923 assert(imm.is_int8()); |
| 1924 if (imm.value() == 1) { |
| 1925 EmitUint8(0xD1); |
| 1926 EmitOperand(rm, Operand(reg)); |
| 1927 } else { |
| 1928 EmitUint8(0xC1); |
| 1929 EmitOperand(rm, Operand(reg)); |
| 1930 EmitUint8(imm.value() & 0xFF); |
| 1931 } |
| 1932 } |
| 1933 |
| 1934 void AssemblerX86::EmitGenericShift(int rm, const Operand &operand, |
| 1935 Register shifter) { |
| 1936 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1937 assert(shifter == ECX); |
| 1938 EmitUint8(0xD3); |
| 1939 EmitOperand(rm, Operand(operand)); |
| 1940 } |
| 1941 |
| 1942 } // end of namespace x86 |
| 1943 } // end of namespace Ice |
OLD | NEW |