Chromium Code Reviews| Index: src/x64/assembler-x64.cc |
| diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc |
| index 3d03949f25633f7cdefbfe1b5de5801b26bee995..8bdce9cb09cd440eab6d0058c62f7d5deb557c4f 100644 |
| --- a/src/x64/assembler-x64.cc |
| +++ b/src/x64/assembler-x64.cc |
| @@ -239,6 +239,49 @@ Operand::Operand(Register index, |
| } |
| +Operand::Operand(const Operand& operand, int32_t offset) { |
| + ASSERT(operand.len_ >= 1); |
| + // Operand encodes REX ModR/M [SIB] [Disp]. |
| + byte modrm = operand.buf_[0]; |
| + ASSERT(modrm < 0xC0); // Disallow mode 3 (register target). |
| + bool has_sib = ((modrm & 0x07) == 0x04); |
| + byte mode = modrm & 0xC0; |
| + int disp_offset = has_sib ? 2 : 1; |
| + int base_reg = (has_sib ? operand.buf_[1] : modrm) & 0x07; |
| + // Mode 0 with rbp/r13 as ModR/M or SIB base register always has a 32-bit |
| + // displacement. |
| + bool is_baseless = (mode == 0) && (base_reg == 0x05); // No base or RIP base. |
| + int32_t disp_value = 0; |
| + if (mode == 0x80 || is_baseless) { |
| + // Mode 2 or mode 0 with rbp/r13 as base: Word displacement. |
| + disp_value = *reinterpret_cast<const int32_t*>(&operand.buf_[disp_offset]); |
| + } else if (mode == 0x40) { |
| + // Mode 1: Byte displacement. |
| + disp_value = static_cast<signed char>(operand.buf_[disp_offset]); |
| + } |
| + // Write new operand with same registers, but with modified displacement. |
|
William Hesse
2010/05/26 08:13:24
Insert blank line after reading and before writing
Lasse Reichstein
2010/05/26 08:34:11
Done.
|
| + disp_value += offset; |
|
William Hesse
2010/05/26 08:13:24
The assert for no overflow could be added:
ASSERT(
Lasse Reichstein
2010/05/26 08:34:11
Assertion added.
|
| + rex_ = operand.rex_; |
| + if (!is_int8(disp_value) || is_baseless) { |
| + // Need 32 bits of displacement, mode 2 or mode 1 with register rbp/r13. |
| + buf_[0] = (modrm & 0x3f) | (is_baseless ? 0x00 : 0x80); |
| + len_ = disp_offset + 4; |
| + Memory::int32_at(&buf_[disp_offset]) = disp_value; |
| + } else if (disp_value != 0 || (base_reg == 0x05)) { |
| + // Need 8 bits of displacement. |
| + buf_[0] = (modrm & 0x3f) | 0x40; // Mode 1. |
| + len_ = disp_offset + 1; |
| + buf_[disp_offset] = static_cast<byte>(disp_value); |
| + } else { |
| + // Need no displacement. |
| + buf_[0] = (modrm & 0x3f); // Mode 0. |
| + len_ = disp_offset; |
| + } |
| + if (has_sib) { |
| + buf_[1] = operand.buf_[1]; |
| + } |
| +} |
| + |
| // ----------------------------------------------------------------------------- |
| // Implementation of Assembler. |