| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2011, 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 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_X64) |
| 7 |
| 8 #include "vm/assembler.h" |
| 9 #include "vm/heap.h" |
| 10 #include "vm/memory_region.h" |
| 11 #include "vm/runtime_entry.h" |
| 12 |
| 13 namespace dart { |
| 14 |
| 15 void Assembler::InitializeMemoryWithBreakpoints(uword data, int length) { |
| 16 memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); |
| 17 } |
| 18 |
| 19 |
| 20 void Assembler::call(Register reg) { |
| 21 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 22 Operand operand(reg); |
| 23 EmitOperandREX(2, operand, REX_NONE); |
| 24 EmitUint8(0xFF); |
| 25 EmitOperand(2, operand); |
| 26 } |
| 27 |
| 28 |
| 29 void Assembler::call(const Address& address) { |
| 30 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 31 EmitOperandREX(2, address, REX_NONE); |
| 32 EmitUint8(0xFF); |
| 33 EmitOperand(2, address); |
| 34 } |
| 35 |
| 36 |
| 37 void Assembler::call(Label* label) { |
| 38 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 39 static const int kSize = 5; |
| 40 EmitUint8(0xE8); |
| 41 EmitLabel(label, kSize); |
| 42 } |
| 43 |
| 44 |
| 45 void Assembler::call(const ExternalLabel* label) { |
| 46 movq(R11, Immediate(label->address())); |
| 47 call(R11); |
| 48 } |
| 49 |
| 50 |
| 51 void Assembler::pushq(Register reg) { |
| 52 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 53 EmitRegisterREX(reg, REX_NONE); |
| 54 EmitUint8(0x50 | (reg & 7)); |
| 55 } |
| 56 |
| 57 |
| 58 void Assembler::pushq(const Address& address) { |
| 59 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 60 EmitOperandREX(6, address, REX_NONE); |
| 61 EmitUint8(0xFF); |
| 62 EmitOperand(6, address); |
| 63 } |
| 64 |
| 65 |
| 66 void Assembler::popq(Register reg) { |
| 67 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 68 EmitRegisterREX(reg, REX_NONE); |
| 69 EmitUint8(0x58 | (reg & 7)); |
| 70 } |
| 71 |
| 72 |
| 73 void Assembler::popq(const Address& address) { |
| 74 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 75 EmitOperandREX(0, address, REX_NONE); |
| 76 EmitUint8(0x8F); |
| 77 EmitOperand(0, address); |
| 78 } |
| 79 |
| 80 |
| 81 void Assembler::movl(Register dst, Register src) { |
| 82 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 83 Operand operand(src); |
| 84 EmitOperandREX(dst, operand, REX_NONE); |
| 85 EmitUint8(0x8B); |
| 86 EmitOperand(dst & 7, operand); |
| 87 } |
| 88 |
| 89 |
| 90 void Assembler::movl(Register dst, const Immediate& imm) { |
| 91 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 92 Operand operand(dst); |
| 93 EmitOperandREX(0, operand, REX_NONE); |
| 94 EmitUint8(0xC7); |
| 95 EmitOperand(0, operand); |
| 96 ASSERT(imm.is_int32()); |
| 97 EmitImmediate(imm); |
| 98 } |
| 99 |
| 100 |
| 101 void Assembler::movl(Register dst, const Address& src) { |
| 102 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 103 EmitOperandREX(dst, src, REX_NONE); |
| 104 EmitUint8(0x8B); |
| 105 EmitOperand(dst & 7, src); |
| 106 } |
| 107 |
| 108 |
| 109 void Assembler::movl(const Address& dst, Register src) { |
| 110 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 111 EmitOperandREX(src, dst, REX_NONE); |
| 112 EmitUint8(0x89); |
| 113 EmitOperand(src & 7, dst); |
| 114 } |
| 115 |
| 116 |
| 117 void Assembler::movzxb(Register dst, Register src) { |
| 118 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 119 Operand operand(src); |
| 120 EmitOperandREX(dst, operand, REX_W); |
| 121 EmitUint8(0x0F); |
| 122 EmitUint8(0xB6); |
| 123 EmitOperand(dst & 7, operand); |
| 124 } |
| 125 |
| 126 |
| 127 void Assembler::movzxb(Register dst, const Address& src) { |
| 128 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 129 EmitOperandREX(dst, src, REX_W); |
| 130 EmitUint8(0x0F); |
| 131 EmitUint8(0xB6); |
| 132 EmitOperand(dst & 7, src); |
| 133 } |
| 134 |
| 135 |
| 136 void Assembler::movsxb(Register dst, Register src) { |
| 137 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 138 Operand operand(src); |
| 139 EmitOperandREX(dst, operand, REX_W); |
| 140 EmitUint8(0x0F); |
| 141 EmitUint8(0xBE); |
| 142 EmitOperand(dst & 7, operand); |
| 143 } |
| 144 |
| 145 |
| 146 void Assembler::movsxb(Register dst, const Address& src) { |
| 147 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 148 EmitOperandREX(dst, src, REX_W); |
| 149 EmitUint8(0x0F); |
| 150 EmitUint8(0xBE); |
| 151 EmitOperand(dst & 7, src); |
| 152 } |
| 153 |
| 154 |
| 155 void Assembler::movb(Register dst, const Address& src) { |
| 156 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 157 EmitOperandREX(dst, src, REX_NONE); |
| 158 EmitUint8(0x8A); |
| 159 EmitOperand(dst & 7, src); |
| 160 } |
| 161 |
| 162 |
| 163 void Assembler::movb(const Address& dst, const Immediate& imm) { |
| 164 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 165 EmitOperandREX(0, dst, REX_NONE); |
| 166 EmitUint8(0xC6); |
| 167 EmitOperand(0, dst); |
| 168 ASSERT(imm.is_int8()); |
| 169 EmitUint8(imm.value() & 0xFF); |
| 170 } |
| 171 |
| 172 |
| 173 void Assembler::movb(const Address& dst, Register src) { |
| 174 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 175 EmitOperandREX(src, dst, REX_NONE); |
| 176 EmitUint8(0x88); |
| 177 EmitOperand(src & 7, dst); |
| 178 } |
| 179 |
| 180 |
| 181 void Assembler::movzxw(Register dst, Register src) { |
| 182 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 183 Operand operand(src); |
| 184 EmitOperandREX(dst, operand, REX_W); |
| 185 EmitUint8(0x0F); |
| 186 EmitUint8(0xB7); |
| 187 EmitOperand(dst & 7, operand); |
| 188 } |
| 189 |
| 190 |
| 191 void Assembler::movzxw(Register dst, const Address& src) { |
| 192 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 193 EmitOperandREX(dst, src, REX_W); |
| 194 EmitUint8(0x0F); |
| 195 EmitUint8(0xB7); |
| 196 EmitOperand(dst & 7, src); |
| 197 } |
| 198 |
| 199 |
| 200 void Assembler::movsxw(Register dst, Register src) { |
| 201 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 202 Operand operand(src); |
| 203 EmitOperandREX(dst, operand, REX_W); |
| 204 EmitUint8(0x0F); |
| 205 EmitUint8(0xBF); |
| 206 EmitOperand(dst & 7, operand); |
| 207 } |
| 208 |
| 209 |
| 210 void Assembler::movsxw(Register dst, const Address& src) { |
| 211 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 212 EmitOperandREX(dst, src, REX_W); |
| 213 EmitUint8(0x0F); |
| 214 EmitUint8(0xBF); |
| 215 EmitOperand(dst & 7, src); |
| 216 } |
| 217 |
| 218 |
| 219 void Assembler::movw(Register dst, const Address& src) { |
| 220 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 221 EmitOperandREX(dst, src, REX_NONE); |
| 222 EmitOperandSizeOverride(); |
| 223 EmitUint8(0x8B); |
| 224 EmitOperand(dst & 7, src); |
| 225 } |
| 226 |
| 227 |
| 228 void Assembler::movw(const Address& dst, Register src) { |
| 229 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 230 EmitOperandREX(src, dst, REX_NONE); |
| 231 EmitOperandSizeOverride(); |
| 232 EmitUint8(0x89); |
| 233 EmitOperand(src & 7, dst); |
| 234 } |
| 235 |
| 236 |
| 237 void Assembler::movq(Register dst, const Immediate& imm) { |
| 238 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 239 if (imm.is_int32()) { |
| 240 Operand operand(dst); |
| 241 EmitOperandREX(0, operand, REX_W); |
| 242 EmitUint8(0xC7); |
| 243 EmitOperand(0, operand); |
| 244 } else { |
| 245 EmitRegisterREX(dst, REX_W); |
| 246 EmitUint8(0xB8 | (dst & 7)); |
| 247 } |
| 248 EmitImmediate(imm); |
| 249 } |
| 250 |
| 251 |
| 252 void Assembler::movq(Register dst, Register src) { |
| 253 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 254 Operand operand(src); |
| 255 EmitOperandREX(dst, operand, REX_W); |
| 256 EmitUint8(0x8B); |
| 257 EmitOperand(dst & 7, operand); |
| 258 } |
| 259 |
| 260 |
| 261 void Assembler::movq(Register dst, const Address& src) { |
| 262 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 263 EmitOperandREX(dst, src, REX_W); |
| 264 EmitUint8(0x8B); |
| 265 EmitOperand(dst & 7, src); |
| 266 } |
| 267 |
| 268 |
| 269 void Assembler::movq(const Address& dst, Register src) { |
| 270 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 271 EmitOperandREX(src, dst, REX_W); |
| 272 EmitUint8(0x89); |
| 273 EmitOperand(src & 7, dst); |
| 274 } |
| 275 |
| 276 |
| 277 void Assembler::movq(const Address& dst, const Immediate& imm) { |
| 278 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 279 ASSERT(imm.is_int32()); |
| 280 Operand operand(dst); |
| 281 EmitOperandREX(0, operand, REX_W); |
| 282 EmitUint8(0xC7); |
| 283 EmitOperand(0, operand); |
| 284 EmitImmediate(imm); |
| 285 } |
| 286 |
| 287 |
| 288 void Assembler::movsxl(Register dst, const Address& src) { |
| 289 UNIMPLEMENTED(); |
| 290 } |
| 291 |
| 292 |
| 293 void Assembler::leaq(Register dst, const Address& src) { |
| 294 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 295 EmitOperandREX(dst, src, REX_W); |
| 296 EmitUint8(0x8D); |
| 297 EmitOperand(dst & 7, src); |
| 298 } |
| 299 |
| 300 |
| 301 void Assembler::movss(XmmRegister dst, const Address& src) { |
| 302 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 303 ASSERT(dst <= XMM7); |
| 304 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 305 EmitUint8(0xF3); |
| 306 EmitOperandREX(0, src, REX_NONE); |
| 307 EmitUint8(0x0F); |
| 308 EmitUint8(0x10); |
| 309 EmitOperand(dst & 7, src); |
| 310 } |
| 311 |
| 312 |
| 313 void Assembler::movss(const Address& dst, XmmRegister src) { |
| 314 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 315 ASSERT(src <= XMM7); |
| 316 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 317 EmitUint8(0xF3); |
| 318 EmitOperandREX(0, dst, REX_NONE); |
| 319 EmitUint8(0x0F); |
| 320 EmitUint8(0x11); |
| 321 EmitOperand(src & 7, dst); |
| 322 } |
| 323 |
| 324 |
| 325 void Assembler::movss(XmmRegister dst, XmmRegister src) { |
| 326 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 327 ASSERT(src <= XMM7); |
| 328 ASSERT(dst <= XMM7); |
| 329 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 330 EmitUint8(0xF3); |
| 331 EmitUint8(0x0F); |
| 332 EmitUint8(0x11); |
| 333 EmitXmmRegisterOperand(src & 7, dst); |
| 334 } |
| 335 |
| 336 |
| 337 void Assembler::movd(XmmRegister dst, Register src) { |
| 338 ASSERT(dst <= XMM7); |
| 339 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 340 EmitUint8(0x66); |
| 341 EmitUint8(0x0F); |
| 342 EmitUint8(0x6E); |
| 343 EmitOperand(dst, Operand(src)); |
| 344 } |
| 345 |
| 346 |
| 347 void Assembler::movd(Register dst, XmmRegister src) { |
| 348 ASSERT(src <= XMM7); |
| 349 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 350 EmitUint8(0x66); |
| 351 EmitUint8(0x0F); |
| 352 EmitUint8(0x7E); |
| 353 EmitOperand(src, Operand(dst)); |
| 354 } |
| 355 |
| 356 |
| 357 void Assembler::addss(XmmRegister dst, XmmRegister src) { |
| 358 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 359 ASSERT(src <= XMM7); |
| 360 ASSERT(dst <= XMM7); |
| 361 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 362 EmitUint8(0xF3); |
| 363 EmitUint8(0x0F); |
| 364 EmitUint8(0x58); |
| 365 EmitXmmRegisterOperand(dst, src); |
| 366 } |
| 367 |
| 368 |
| 369 void Assembler::subss(XmmRegister dst, XmmRegister src) { |
| 370 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 371 ASSERT(src <= XMM7); |
| 372 ASSERT(dst <= XMM7); |
| 373 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 374 EmitUint8(0xF3); |
| 375 EmitUint8(0x0F); |
| 376 EmitUint8(0x5C); |
| 377 EmitXmmRegisterOperand(dst, src); |
| 378 } |
| 379 |
| 380 |
| 381 void Assembler::mulss(XmmRegister dst, XmmRegister src) { |
| 382 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 383 ASSERT(src <= XMM7); |
| 384 ASSERT(dst <= XMM7); |
| 385 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 386 EmitUint8(0xF3); |
| 387 EmitUint8(0x0F); |
| 388 EmitUint8(0x59); |
| 389 EmitXmmRegisterOperand(dst, src); |
| 390 } |
| 391 |
| 392 |
| 393 void Assembler::divss(XmmRegister dst, XmmRegister src) { |
| 394 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 395 ASSERT(src <= XMM7); |
| 396 ASSERT(dst <= XMM7); |
| 397 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 398 EmitUint8(0xF3); |
| 399 EmitUint8(0x0F); |
| 400 EmitUint8(0x5E); |
| 401 EmitXmmRegisterOperand(dst, src); |
| 402 } |
| 403 |
| 404 |
| 405 void Assembler::movsd(XmmRegister dst, const Address& src) { |
| 406 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 407 ASSERT(dst <= XMM7); |
| 408 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 409 EmitUint8(0xF2); |
| 410 EmitOperandREX(0, src, REX_NONE); |
| 411 EmitUint8(0x0F); |
| 412 EmitUint8(0x10); |
| 413 EmitOperand(dst & 7, src); |
| 414 } |
| 415 |
| 416 |
| 417 void Assembler::movsd(const Address& dst, XmmRegister src) { |
| 418 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 419 ASSERT(src <= XMM7); |
| 420 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 421 EmitUint8(0xF2); |
| 422 EmitOperandREX(0, dst, REX_NONE); |
| 423 EmitUint8(0x0F); |
| 424 EmitUint8(0x11); |
| 425 EmitOperand(src & 7, dst); |
| 426 } |
| 427 |
| 428 |
| 429 void Assembler::movsd(XmmRegister dst, XmmRegister src) { |
| 430 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 431 ASSERT(src <= XMM7); |
| 432 ASSERT(dst <= XMM7); |
| 433 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 434 EmitUint8(0xF2); |
| 435 EmitUint8(0x0F); |
| 436 EmitUint8(0x11); |
| 437 EmitXmmRegisterOperand(src & 7, dst); |
| 438 } |
| 439 |
| 440 |
| 441 void Assembler::addsd(XmmRegister dst, XmmRegister src) { |
| 442 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 443 ASSERT(src <= XMM7); |
| 444 ASSERT(dst <= XMM7); |
| 445 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 446 EmitUint8(0xF2); |
| 447 EmitUint8(0x0F); |
| 448 EmitUint8(0x58); |
| 449 EmitXmmRegisterOperand(dst, src); |
| 450 } |
| 451 |
| 452 |
| 453 void Assembler::subsd(XmmRegister dst, XmmRegister src) { |
| 454 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 455 ASSERT(src <= XMM7); |
| 456 ASSERT(dst <= XMM7); |
| 457 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 458 EmitUint8(0xF2); |
| 459 EmitUint8(0x0F); |
| 460 EmitUint8(0x5C); |
| 461 EmitXmmRegisterOperand(dst, src); |
| 462 } |
| 463 |
| 464 |
| 465 void Assembler::mulsd(XmmRegister dst, XmmRegister src) { |
| 466 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 467 ASSERT(src <= XMM7); |
| 468 ASSERT(dst <= XMM7); |
| 469 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 470 EmitUint8(0xF2); |
| 471 EmitUint8(0x0F); |
| 472 EmitUint8(0x59); |
| 473 EmitXmmRegisterOperand(dst, src); |
| 474 } |
| 475 |
| 476 |
| 477 void Assembler::divsd(XmmRegister dst, XmmRegister src) { |
| 478 // TODO(srdjan): implement and test XMM8 - XMM15. |
| 479 ASSERT(src <= XMM7); |
| 480 ASSERT(dst <= XMM7); |
| 481 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 482 EmitUint8(0xF2); |
| 483 EmitUint8(0x0F); |
| 484 EmitUint8(0x5E); |
| 485 EmitXmmRegisterOperand(dst, src); |
| 486 } |
| 487 |
| 488 |
| 489 void Assembler::xchgl(Register dst, Register src) { |
| 490 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 491 Operand operand(src); |
| 492 EmitOperandREX(dst, operand, REX_NONE); |
| 493 EmitUint8(0x87); |
| 494 EmitOperand(dst & 7, operand); |
| 495 } |
| 496 |
| 497 |
| 498 void Assembler::xchgq(Register dst, Register src) { |
| 499 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 500 Operand operand(src); |
| 501 EmitOperandREX(dst, operand, REX_W); |
| 502 EmitUint8(0x87); |
| 503 EmitOperand(dst & 7, operand); |
| 504 } |
| 505 |
| 506 |
| 507 void Assembler::cmpl(Register reg, const Immediate& imm) { |
| 508 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 509 EmitRegisterREX(reg, REX_NONE); |
| 510 EmitComplex(7, Operand(reg), imm); |
| 511 } |
| 512 |
| 513 |
| 514 void Assembler::cmpl(Register reg0, Register reg1) { |
| 515 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 516 Operand operand(reg1); |
| 517 EmitOperandREX(reg0, operand, REX_NONE); |
| 518 EmitUint8(0x3B); |
| 519 EmitOperand(reg0 & 7, operand); |
| 520 } |
| 521 |
| 522 |
| 523 void Assembler::cmpl(Register reg, const Address& address) { |
| 524 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 525 EmitOperandREX(reg, address, REX_NONE); |
| 526 EmitUint8(0x3B); |
| 527 EmitOperand(reg & 7, address); |
| 528 } |
| 529 |
| 530 |
| 531 void Assembler::cmpl(const Address& address, const Immediate& imm) { |
| 532 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 533 Operand operand(address); |
| 534 EmitOperandREX(7, operand, REX_NONE); |
| 535 EmitComplex(7, operand, imm); |
| 536 } |
| 537 |
| 538 |
| 539 void Assembler::cmpq(const Address& address, const Immediate& imm) { |
| 540 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 541 Operand operand(address); |
| 542 EmitOperandREX(7, operand, REX_W); |
| 543 EmitComplex(7, operand, imm); |
| 544 } |
| 545 |
| 546 |
| 547 void Assembler::cmpq(Register reg, const Immediate& imm) { |
| 548 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 549 EmitRegisterREX(reg, REX_W); |
| 550 EmitComplex(7, Operand(reg), imm); |
| 551 } |
| 552 |
| 553 |
| 554 void Assembler::cmpq(Register reg0, Register reg1) { |
| 555 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 556 Operand operand(reg1); |
| 557 EmitOperandREX(reg0, operand, REX_W); |
| 558 EmitUint8(0x3B); |
| 559 EmitOperand(reg0 & 7, operand); |
| 560 } |
| 561 |
| 562 |
| 563 void Assembler::cmpq(Register reg, const Address& address) { |
| 564 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 565 EmitOperandREX(reg, address, REX_W); |
| 566 EmitUint8(0x3B); |
| 567 EmitOperand(reg & 7, address); |
| 568 } |
| 569 |
| 570 |
| 571 void Assembler::testl(Register reg1, Register reg2) { |
| 572 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 573 Operand operand(reg2); |
| 574 EmitOperandREX(reg1, operand, REX_NONE); |
| 575 EmitUint8(0x85); |
| 576 EmitOperand(reg1 & 7, operand); |
| 577 } |
| 578 |
| 579 |
| 580 void Assembler::testl(Register reg, const Immediate& imm) { |
| 581 // TODO(kasperl): Deal with registers r8-r15 using the short |
| 582 // encoding form of the immediate? |
| 583 |
| 584 // We are using RBP for the exception marker. See testl(Label*). |
| 585 ASSERT(reg != RBP); |
| 586 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 587 // For registers that have a byte variant (RAX, RBX, RCX, and RDX) |
| 588 // we only test the byte register to keep the encoding short. |
| 589 if (imm.is_uint8() && reg < 4) { |
| 590 // Use zero-extended 8-bit immediate. |
| 591 if (reg == RAX) { |
| 592 EmitUint8(0xA8); |
| 593 } else { |
| 594 EmitUint8(0xF6); |
| 595 EmitUint8(0xC0 + reg); |
| 596 } |
| 597 EmitUint8(imm.value() & 0xFF); |
| 598 } else { |
| 599 ASSERT(imm.is_int32()); |
| 600 if (reg == RAX) { |
| 601 EmitUint8(0xA9); |
| 602 } else { |
| 603 EmitRegisterREX(reg, REX_NONE); |
| 604 EmitUint8(0xF7); |
| 605 EmitUint8(0xC0 | (reg & 7)); |
| 606 } |
| 607 EmitImmediate(imm); |
| 608 } |
| 609 } |
| 610 |
| 611 |
| 612 void Assembler::testq(Register reg1, Register reg2) { |
| 613 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 614 Operand operand(reg2); |
| 615 EmitOperandREX(reg1, operand, REX_W); |
| 616 EmitUint8(0x85); |
| 617 EmitOperand(reg1 & 7, operand); |
| 618 } |
| 619 |
| 620 |
| 621 void Assembler::testq(Register reg, const Immediate& imm) { |
| 622 // TODO(kasperl): Deal with registers r8-r15 using the short |
| 623 // encoding form of the immediate? |
| 624 |
| 625 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 626 // For registers that have a byte variant (RAX, RBX, RCX, and RDX) |
| 627 // we only test the byte register to keep the encoding short. |
| 628 if (imm.is_uint8() && reg < 4) { |
| 629 // Use zero-extended 8-bit immediate. |
| 630 if (reg == RAX) { |
| 631 EmitUint8(0xA8); |
| 632 } else { |
| 633 EmitUint8(0xF6); |
| 634 EmitUint8(0xC0 + reg); |
| 635 } |
| 636 EmitUint8(imm.value() & 0xFF); |
| 637 } else { |
| 638 ASSERT(imm.is_int32()); |
| 639 if (reg == RAX) { |
| 640 EmitUint8(0xA9 | REX_W); |
| 641 } else { |
| 642 EmitRegisterREX(reg, REX_W); |
| 643 EmitUint8(0xF7); |
| 644 EmitUint8(0xC0 | (reg & 7)); |
| 645 } |
| 646 EmitImmediate(imm); |
| 647 } |
| 648 } |
| 649 |
| 650 |
| 651 void Assembler::andl(Register dst, Register src) { |
| 652 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 653 Operand operand(src); |
| 654 EmitOperandREX(dst, operand, REX_NONE); |
| 655 EmitUint8(0x23); |
| 656 EmitOperand(dst & 7, operand); |
| 657 } |
| 658 |
| 659 |
| 660 void Assembler::andl(Register dst, const Immediate& imm) { |
| 661 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 662 EmitRegisterREX(dst, REX_NONE); |
| 663 EmitComplex(4, Operand(dst), imm); |
| 664 } |
| 665 |
| 666 |
| 667 void Assembler::orl(Register dst, Register src) { |
| 668 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 669 Operand operand(src); |
| 670 EmitOperandREX(dst, operand, REX_NONE); |
| 671 EmitUint8(0x0B); |
| 672 EmitOperand(dst & 7, operand); |
| 673 } |
| 674 |
| 675 |
| 676 void Assembler::orl(Register dst, const Immediate& imm) { |
| 677 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 678 EmitRegisterREX(dst, REX_NONE); |
| 679 EmitComplex(1, Operand(dst), imm); |
| 680 } |
| 681 |
| 682 |
| 683 void Assembler::xorl(Register dst, Register src) { |
| 684 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 685 Operand operand(src); |
| 686 EmitOperandREX(dst, operand, REX_NONE); |
| 687 EmitUint8(0x33); |
| 688 EmitOperand(dst & 7, operand); |
| 689 } |
| 690 |
| 691 |
| 692 void Assembler::andq(Register dst, Register src) { |
| 693 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 694 Operand operand(src); |
| 695 EmitOperandREX(dst, operand, REX_W); |
| 696 EmitUint8(0x23); |
| 697 EmitOperand(dst & 7, operand); |
| 698 } |
| 699 |
| 700 |
| 701 void Assembler::andq(Register dst, const Immediate& imm) { |
| 702 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 703 EmitRegisterREX(dst, REX_W); |
| 704 EmitComplex(4, Operand(dst), imm); |
| 705 } |
| 706 |
| 707 |
| 708 void Assembler::orq(Register dst, Register src) { |
| 709 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 710 Operand operand(src); |
| 711 EmitOperandREX(dst, operand, REX_W); |
| 712 EmitUint8(0x0B); |
| 713 EmitOperand(dst & 7, operand); |
| 714 } |
| 715 |
| 716 |
| 717 void Assembler::orq(Register dst, const Immediate& imm) { |
| 718 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 719 EmitRegisterREX(dst, REX_W); |
| 720 EmitComplex(1, Operand(dst), imm); |
| 721 } |
| 722 |
| 723 |
| 724 void Assembler::xorq(Register dst, Register src) { |
| 725 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 726 Operand operand(src); |
| 727 EmitOperandREX(dst, operand, REX_W); |
| 728 EmitUint8(0x33); |
| 729 EmitOperand(dst & 7, operand); |
| 730 } |
| 731 |
| 732 |
| 733 void Assembler::addl(Register dst, Register src) { |
| 734 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 735 Operand operand(src); |
| 736 EmitOperandREX(dst, operand, REX_NONE); |
| 737 EmitUint8(0x03); |
| 738 EmitOperand(dst & 7, operand); |
| 739 } |
| 740 |
| 741 |
| 742 void Assembler::addq(Register dst, Register src) { |
| 743 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 744 Operand operand(src); |
| 745 EmitOperandREX(dst, operand, REX_W); |
| 746 EmitUint8(0x03); |
| 747 EmitOperand(dst & 7, operand); |
| 748 } |
| 749 |
| 750 |
| 751 void Assembler::addl(const Address& address, const Immediate& imm) { |
| 752 UNIMPLEMENTED(); |
| 753 } |
| 754 |
| 755 |
| 756 void Assembler::addq(Register reg, const Immediate& imm) { |
| 757 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 758 EmitRegisterREX(reg, REX_W); |
| 759 EmitComplex(0, Operand(reg), imm); |
| 760 } |
| 761 |
| 762 |
| 763 void Assembler::addq(const Address& address, const Immediate& imm) { |
| 764 UNIMPLEMENTED(); |
| 765 } |
| 766 |
| 767 |
| 768 void Assembler::subl(Register dst, Register src) { |
| 769 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 770 Operand operand(src); |
| 771 EmitOperandREX(dst, operand, REX_NONE); |
| 772 EmitUint8(0x2B); |
| 773 EmitOperand(dst & 7, operand); |
| 774 } |
| 775 |
| 776 |
| 777 void Assembler::cdq() { |
| 778 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 779 EmitUint8(0x99); |
| 780 } |
| 781 |
| 782 |
| 783 void Assembler::cqo() { |
| 784 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 785 EmitRegisterREX(RAX, REX_W); |
| 786 EmitUint8(0x99); |
| 787 } |
| 788 |
| 789 |
| 790 void Assembler::idivl(Register reg) { |
| 791 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 792 EmitRegisterREX(reg, REX_NONE); |
| 793 EmitUint8(0xF7); |
| 794 EmitUint8(0xF8 | (reg & 7)); |
| 795 } |
| 796 |
| 797 |
| 798 void Assembler::idivq(Register reg) { |
| 799 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 800 EmitRegisterREX(reg, REX_W); |
| 801 EmitUint8(0xF7); |
| 802 EmitUint8(0xF8 | (reg & 7)); |
| 803 } |
| 804 |
| 805 |
| 806 void Assembler::imull(Register dst, Register src) { |
| 807 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 808 EmitUint8(0x0F); |
| 809 EmitUint8(0xAF); |
| 810 EmitOperand(dst, Operand(src)); |
| 811 } |
| 812 |
| 813 |
| 814 void Assembler::imull(Register reg, const Immediate& imm) { |
| 815 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 816 EmitUint8(0x69); |
| 817 EmitOperand(reg, Operand(reg)); |
| 818 EmitImmediate(imm); |
| 819 } |
| 820 |
| 821 |
| 822 void Assembler::imulq(Register dst, Register src) { |
| 823 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 824 Operand operand(src); |
| 825 EmitOperandREX(dst, operand, REX_W); |
| 826 EmitUint8(0x0F); |
| 827 EmitUint8(0xAF); |
| 828 EmitOperand(dst & 7, operand); |
| 829 } |
| 830 |
| 831 |
| 832 void Assembler::subq(Register dst, Register src) { |
| 833 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 834 Operand operand(src); |
| 835 EmitOperandREX(dst, operand, REX_W); |
| 836 EmitUint8(0x2B); |
| 837 EmitOperand(dst & 7, operand); |
| 838 } |
| 839 |
| 840 |
| 841 void Assembler::subq(Register reg, const Immediate& imm) { |
| 842 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 843 EmitRegisterREX(reg, REX_W); |
| 844 EmitComplex(5, Operand(reg), imm); |
| 845 } |
| 846 |
| 847 |
| 848 void Assembler::shll(Register reg, const Immediate& imm) { |
| 849 EmitGenericShift(false, 4, reg, imm); |
| 850 } |
| 851 |
| 852 |
| 853 void Assembler::shll(Register operand, Register shifter) { |
| 854 EmitGenericShift(false, 4, operand, shifter); |
| 855 } |
| 856 |
| 857 |
| 858 void Assembler::shrl(Register reg, const Immediate& imm) { |
| 859 EmitGenericShift(false, 5, reg, imm); |
| 860 } |
| 861 |
| 862 |
| 863 void Assembler::shrl(Register operand, Register shifter) { |
| 864 EmitGenericShift(false, 5, operand, shifter); |
| 865 } |
| 866 |
| 867 |
| 868 void Assembler::sarl(Register reg, const Immediate& imm) { |
| 869 EmitGenericShift(false, 7, reg, imm); |
| 870 } |
| 871 |
| 872 |
| 873 void Assembler::sarl(Register operand, Register shifter) { |
| 874 EmitGenericShift(false, 7, operand, shifter); |
| 875 } |
| 876 |
| 877 |
| 878 void Assembler::shlq(Register reg, const Immediate& imm) { |
| 879 EmitGenericShift(true, 4, reg, imm); |
| 880 } |
| 881 |
| 882 |
| 883 void Assembler::shlq(Register operand, Register shifter) { |
| 884 EmitGenericShift(true, 4, operand, shifter); |
| 885 } |
| 886 |
| 887 |
| 888 void Assembler::shrq(Register reg, const Immediate& imm) { |
| 889 EmitGenericShift(true, 5, reg, imm); |
| 890 } |
| 891 |
| 892 |
| 893 void Assembler::shrq(Register operand, Register shifter) { |
| 894 EmitGenericShift(true, 5, operand, shifter); |
| 895 } |
| 896 |
| 897 |
| 898 void Assembler::sarq(Register reg, const Immediate& imm) { |
| 899 EmitGenericShift(true, 7, reg, imm); |
| 900 } |
| 901 |
| 902 |
| 903 void Assembler::sarq(Register operand, Register shifter) { |
| 904 EmitGenericShift(true, 7, operand, shifter); |
| 905 } |
| 906 |
| 907 |
| 908 void Assembler::incl(const Address& address) { |
| 909 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 910 Operand operand(address); |
| 911 EmitOperandREX(0, operand, REX_NONE); |
| 912 EmitUint8(0xFF); |
| 913 EmitOperand(0, operand); |
| 914 } |
| 915 |
| 916 |
| 917 void Assembler::decl(const Address& address) { |
| 918 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 919 Operand operand(address); |
| 920 EmitOperandREX(1, operand, REX_NONE); |
| 921 EmitUint8(0xFF); |
| 922 EmitOperand(1, operand); |
| 923 } |
| 924 |
| 925 |
| 926 void Assembler::incq(Register reg) { |
| 927 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 928 Operand operand(reg); |
| 929 EmitOperandREX(0, operand, REX_W); |
| 930 EmitUint8(0xFF); |
| 931 EmitOperand(0, operand); |
| 932 } |
| 933 |
| 934 |
| 935 void Assembler::incq(const Address& address) { |
| 936 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 937 Operand operand(address); |
| 938 EmitOperandREX(0, operand, REX_W); |
| 939 EmitUint8(0xFF); |
| 940 EmitOperand(0, operand); |
| 941 } |
| 942 |
| 943 |
| 944 void Assembler::decq(Register reg) { |
| 945 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 946 Operand operand(reg); |
| 947 EmitOperandREX(1, operand, REX_W); |
| 948 EmitUint8(0xFF); |
| 949 EmitOperand(1, operand); |
| 950 } |
| 951 |
| 952 |
| 953 void Assembler::decq(const Address& address) { |
| 954 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 955 Operand operand(address); |
| 956 EmitOperandREX(1, operand, REX_W); |
| 957 EmitUint8(0xFF); |
| 958 EmitOperand(1, operand); |
| 959 } |
| 960 |
| 961 |
| 962 void Assembler::negl(Register reg) { |
| 963 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 964 EmitRegisterREX(reg, REX_NONE); |
| 965 EmitUint8(0xF7); |
| 966 EmitOperand(3, Operand(reg)); |
| 967 } |
| 968 |
| 969 |
| 970 void Assembler::negq(Register reg) { |
| 971 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 972 EmitRegisterREX(reg, REX_W); |
| 973 EmitUint8(0xF7); |
| 974 EmitOperand(3, Operand(reg)); |
| 975 } |
| 976 |
| 977 |
| 978 void Assembler::enter(const Immediate& imm) { |
| 979 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 980 EmitUint8(0xC8); |
| 981 ASSERT(imm.is_uint16()); |
| 982 EmitUint8(imm.value() & 0xFF); |
| 983 EmitUint8((imm.value() >> 8) & 0xFF); |
| 984 EmitUint8(0x00); |
| 985 } |
| 986 |
| 987 |
| 988 void Assembler::leave() { |
| 989 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 990 EmitUint8(0xC9); |
| 991 } |
| 992 |
| 993 |
| 994 void Assembler::ret() { |
| 995 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 996 EmitUint8(0xC3); |
| 997 } |
| 998 |
| 999 |
| 1000 void Assembler::nop() { |
| 1001 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1002 EmitUint8(0x90); |
| 1003 } |
| 1004 |
| 1005 |
| 1006 void Assembler::int3() { |
| 1007 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1008 EmitUint8(0xCC); |
| 1009 } |
| 1010 |
| 1011 |
| 1012 void Assembler::hlt() { |
| 1013 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1014 EmitUint8(0xF4); |
| 1015 } |
| 1016 |
| 1017 |
| 1018 void Assembler::j(Condition condition, Label* label, bool near) { |
| 1019 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1020 if (label->IsBound()) { |
| 1021 static const int kShortSize = 2; |
| 1022 static const int kLongSize = 6; |
| 1023 int offset = label->Position() - buffer_.Size(); |
| 1024 ASSERT(offset <= 0); |
| 1025 if (Utils::IsInt(8, offset - kShortSize)) { |
| 1026 EmitUint8(0x70 + condition); |
| 1027 EmitUint8((offset - kShortSize) & 0xFF); |
| 1028 } else { |
| 1029 EmitUint8(0x0F); |
| 1030 EmitUint8(0x80 + condition); |
| 1031 EmitInt32(offset - kLongSize); |
| 1032 } |
| 1033 } else if (near) { |
| 1034 EmitUint8(0x70 + condition); |
| 1035 EmitNearLabelLink(label); |
| 1036 } else { |
| 1037 EmitUint8(0x0F); |
| 1038 EmitUint8(0x80 + condition); |
| 1039 EmitLabelLink(label); |
| 1040 } |
| 1041 } |
| 1042 |
| 1043 |
| 1044 void Assembler::jmp(Register reg) { |
| 1045 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1046 Operand operand(reg); |
| 1047 EmitOperandREX(4, operand, REX_NONE); |
| 1048 EmitUint8(0xFF); |
| 1049 EmitOperand(4, operand); |
| 1050 } |
| 1051 |
| 1052 |
| 1053 void Assembler::jmp(Label* label, bool near) { |
| 1054 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1055 if (label->IsBound()) { |
| 1056 static const int kShortSize = 2; |
| 1057 static const int kLongSize = 5; |
| 1058 int offset = label->Position() - buffer_.Size(); |
| 1059 ASSERT(offset <= 0); |
| 1060 if (Utils::IsInt(8, offset - kShortSize)) { |
| 1061 EmitUint8(0xEB); |
| 1062 EmitUint8((offset - kShortSize) & 0xFF); |
| 1063 } else { |
| 1064 EmitUint8(0xE9); |
| 1065 EmitInt32(offset - kLongSize); |
| 1066 } |
| 1067 } else if (near) { |
| 1068 EmitUint8(0xEB); |
| 1069 EmitNearLabelLink(label); |
| 1070 } else { |
| 1071 EmitUint8(0xE9); |
| 1072 EmitLabelLink(label); |
| 1073 } |
| 1074 } |
| 1075 |
| 1076 |
| 1077 void Assembler::jmp(const ExternalLabel* label) { |
| 1078 movq(R11, Immediate(label->address())); |
| 1079 jmp(R11); |
| 1080 } |
| 1081 |
| 1082 |
| 1083 void Assembler::lock() { |
| 1084 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1085 EmitUint8(0xF0); |
| 1086 } |
| 1087 |
| 1088 |
| 1089 void Assembler::cmpxchgl(const Address& address, Register reg) { |
| 1090 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1091 EmitOperandREX(reg, address, REX_NONE); |
| 1092 EmitUint8(0x0F); |
| 1093 EmitUint8(0xB1); |
| 1094 EmitOperand(reg & 7, address); |
| 1095 } |
| 1096 |
| 1097 |
| 1098 void Assembler::cmpxchgq(const Address& address, Register reg) { |
| 1099 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1100 EmitOperandREX(reg, address, REX_W); |
| 1101 EmitUint8(0x0F); |
| 1102 EmitUint8(0xB1); |
| 1103 EmitOperand(reg & 7, address); |
| 1104 } |
| 1105 |
| 1106 |
| 1107 void Assembler::AddImmediate(Register reg, const Immediate& imm) { |
| 1108 int64_t value = imm.value(); |
| 1109 if (value > 0) { |
| 1110 if (value == 1) { |
| 1111 incq(reg); |
| 1112 } else if (value != 0) { |
| 1113 addq(reg, imm); |
| 1114 } |
| 1115 } else if (value < 0) { |
| 1116 value = -value; |
| 1117 if (value == 1) { |
| 1118 decq(reg); |
| 1119 } else if (value != 0) { |
| 1120 subq(reg, Immediate(value)); |
| 1121 } |
| 1122 } |
| 1123 } |
| 1124 |
| 1125 |
| 1126 void Assembler::LoadObject(Register dst, const Object& object) { |
| 1127 UNIMPLEMENTED(); |
| 1128 ASSERT(object.IsZoneHandle()); |
| 1129 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1130 EmitUint8(0xB8 + dst); |
| 1131 buffer_.EmitObject(object); |
| 1132 } |
| 1133 |
| 1134 |
| 1135 void Assembler::PushObject(const Object& object) { |
| 1136 UNIMPLEMENTED(); |
| 1137 ASSERT(object.IsZoneHandle()); |
| 1138 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1139 EmitUint8(0x68); |
| 1140 buffer_.EmitObject(object); |
| 1141 } |
| 1142 |
| 1143 |
| 1144 void Assembler::CompareObject(Register reg, const Object& object) { |
| 1145 UNIMPLEMENTED(); |
| 1146 ASSERT(object.IsZoneHandle()); |
| 1147 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1148 if (reg == RAX) { |
| 1149 EmitUint8(0x05 + (7 << 3)); |
| 1150 buffer_.EmitObject(object); |
| 1151 } else { |
| 1152 EmitUint8(0x81); |
| 1153 EmitOperand(7, Operand(reg)); |
| 1154 buffer_.EmitObject(object); |
| 1155 } |
| 1156 } |
| 1157 |
| 1158 |
| 1159 void Assembler::Stop(const char* message) { |
| 1160 // Emit the lower half and the higher half of the message address as immediate |
| 1161 // operands in the test rax instructions, followed by the int3 instruction. |
| 1162 // Execution can be resumed with the 'cont' command in gdb. |
| 1163 int64_t message_address = reinterpret_cast<int64_t>(message); |
| 1164 testl(RAX, Immediate(Utils::Low32Bits(message_address))); |
| 1165 testl(RAX, Immediate(Utils::High32Bits(message_address))); |
| 1166 int3(); |
| 1167 } |
| 1168 |
| 1169 |
| 1170 void Assembler::Bind(Label* label) { |
| 1171 int bound = buffer_.Size(); |
| 1172 ASSERT(!label->IsBound()); // Labels can only be bound once. |
| 1173 while (label->IsLinked()) { |
| 1174 int position = label->LinkPosition(); |
| 1175 int next = buffer_.Load<int32_t>(position); |
| 1176 buffer_.Store<int32_t>(position, bound - (position + 4)); |
| 1177 label->position_ = next; |
| 1178 } |
| 1179 while (label->HasNear()) { |
| 1180 int position = label->NearPosition(); |
| 1181 int offset = bound - (position + 1); |
| 1182 ASSERT(Utils::IsInt(8, offset)); |
| 1183 buffer_.Store<int8_t>(position, offset); |
| 1184 } |
| 1185 label->BindTo(bound); |
| 1186 } |
| 1187 |
| 1188 |
| 1189 void Assembler::Align(int alignment, int offset) { |
| 1190 UNIMPLEMENTED(); |
| 1191 } |
| 1192 |
| 1193 |
| 1194 void Assembler::EmitOperand(int rm, const Operand& operand) { |
| 1195 ASSERT(rm >= 0 && rm < 8); |
| 1196 const int length = operand.length_; |
| 1197 ASSERT(length > 0); |
| 1198 // Emit the ModRM byte updated with the given RM value. |
| 1199 ASSERT((operand.encoding_[0] & 0x38) == 0); |
| 1200 EmitUint8(operand.encoding_[0] + (rm << 3)); |
| 1201 // Emit the rest of the encoded operand. |
| 1202 for (int i = 1; i < length; i++) { |
| 1203 EmitUint8(operand.encoding_[i]); |
| 1204 } |
| 1205 } |
| 1206 |
| 1207 |
| 1208 void Assembler::EmitXmmRegisterOperand(int rm, XmmRegister xmm_reg) { |
| 1209 Operand operand; |
| 1210 operand.SetModRM(3, static_cast<Register>(xmm_reg)); |
| 1211 EmitOperand(rm, operand); |
| 1212 } |
| 1213 |
| 1214 |
| 1215 void Assembler::EmitImmediate(const Immediate& imm) { |
| 1216 if (imm.is_int32()) { |
| 1217 EmitInt32(static_cast<int32_t>(imm.value())); |
| 1218 } else { |
| 1219 EmitInt64(imm.value()); |
| 1220 } |
| 1221 } |
| 1222 |
| 1223 |
| 1224 void Assembler::EmitComplex(int rm, |
| 1225 const Operand& operand, |
| 1226 const Immediate& immediate) { |
| 1227 ASSERT(rm >= 0 && rm < 8); |
| 1228 ASSERT(immediate.is_int32()); |
| 1229 if (immediate.is_int8()) { |
| 1230 // Use sign-extended 8-bit immediate. |
| 1231 EmitUint8(0x83); |
| 1232 EmitOperand(rm, operand); |
| 1233 EmitUint8(immediate.value() & 0xFF); |
| 1234 } else if (operand.IsRegister(RAX)) { |
| 1235 // Use short form if the destination is rax. |
| 1236 EmitUint8(0x05 + (rm << 3)); |
| 1237 EmitImmediate(immediate); |
| 1238 } else { |
| 1239 EmitUint8(0x81); |
| 1240 EmitOperand(rm, operand); |
| 1241 EmitImmediate(immediate); |
| 1242 } |
| 1243 } |
| 1244 |
| 1245 |
| 1246 void Assembler::EmitLabel(Label* label, int instruction_size) { |
| 1247 if (label->IsBound()) { |
| 1248 int offset = label->Position() - buffer_.Size(); |
| 1249 ASSERT(offset <= 0); |
| 1250 EmitInt32(offset - instruction_size); |
| 1251 } else { |
| 1252 EmitLabelLink(label); |
| 1253 } |
| 1254 } |
| 1255 |
| 1256 |
| 1257 void Assembler::EmitLabelLink(Label* label) { |
| 1258 ASSERT(!label->IsBound()); |
| 1259 int position = buffer_.Size(); |
| 1260 EmitInt32(label->position_); |
| 1261 label->LinkTo(position); |
| 1262 } |
| 1263 |
| 1264 |
| 1265 void Assembler::EmitNearLabelLink(Label* label) { |
| 1266 ASSERT(!label->IsBound()); |
| 1267 int position = buffer_.Size(); |
| 1268 EmitUint8(0); |
| 1269 label->NearLinkTo(position); |
| 1270 } |
| 1271 |
| 1272 |
| 1273 void Assembler::EmitGenericShift(bool wide, |
| 1274 int rm, |
| 1275 Register reg, |
| 1276 const Immediate& imm) { |
| 1277 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1278 ASSERT(imm.is_int8()); |
| 1279 if (wide) { |
| 1280 EmitRegisterREX(reg, REX_W); |
| 1281 } else { |
| 1282 EmitRegisterREX(reg, REX_NONE); |
| 1283 } |
| 1284 if (imm.value() == 1) { |
| 1285 EmitUint8(0xD1); |
| 1286 EmitOperand(rm, Operand(reg)); |
| 1287 } else { |
| 1288 EmitUint8(0xC1); |
| 1289 EmitOperand(rm, Operand(reg)); |
| 1290 EmitUint8(imm.value() & 0xFF); |
| 1291 } |
| 1292 } |
| 1293 |
| 1294 |
| 1295 void Assembler::EmitGenericShift(bool wide, |
| 1296 int rm, |
| 1297 Register operand, |
| 1298 Register shifter) { |
| 1299 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 1300 ASSERT(shifter == RCX); |
| 1301 if (wide) { |
| 1302 EmitRegisterREX(operand, REX_W); |
| 1303 } else { |
| 1304 EmitRegisterREX(operand, REX_NONE); |
| 1305 } |
| 1306 EmitUint8(0xD3); |
| 1307 EmitOperand(rm, Operand(operand)); |
| 1308 } |
| 1309 |
| 1310 } // namespace dart |
| 1311 |
| 1312 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |