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