1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/core/assembler.h"
16 :
17 : #include <limits>
18 :
19 : namespace core {
20 :
21 : namespace {
22 :
23 : enum Mod {
24 : kReg1Ind = 0, // Register indirect mode.
25 : kReg1ByteDisp = 1, // Register + byte displacement.
26 : kReg1WordDisp = 2, // Register + word displacement.
27 : kReg1 = 3, // Register itself.
28 : };
29 :
30 : // The code that AL/AX/EAX/RAX registers all map to. There are special encodings
31 : // for arithmetic instructions with this register as the destination.
32 E : static const RegisterCode kAccumulatorCode = Register::Code(kRegisterEax);
33 :
34 : const uint8 kTwoByteOpCodePrefix = 0x0F;
35 : // Prefix group 2 (segment selection).
36 : const uint8 kFsSegmentPrefix = 0x64;
37 : // Prefix group 3 (operand size override).
38 : const uint8 kOperandSizePrefix = 0x66;
39 :
40 : // Some opcodes that are used repeatedly.
41 : const uint8 kNopOpCode = 0x1F;
42 :
43 : // Returns true if @p operand is a displacement only - e.g.
44 : // specifies neither a base, nor an index register.
45 E : bool IsDisplacementOnly(const OperandImpl& operand) {
46 : return operand.displacement().size() != kSizeNone &&
47 : operand.base() == kRegisterNone &&
48 E : operand.index() == kRegisterNone;
49 E : }
50 :
51 : } // namespace
52 :
53 : const size_t AssemblerImpl::kShortBranchOpcodeSize = 1;
54 : const size_t AssemblerImpl::kShortBranchSize = kShortBranchOpcodeSize + 1;
55 :
56 : const size_t AssemblerImpl::kLongBranchOpcodeSize = 2;
57 : const size_t AssemblerImpl::kLongBranchSize = kLongBranchOpcodeSize + 4;
58 :
59 : const size_t AssemblerImpl::kShortJumpOpcodeSize = 1;
60 : const size_t AssemblerImpl::kShortJumpSize = kShortJumpOpcodeSize + 1;
61 :
62 : const size_t AssemblerImpl::kLongJumpOpcodeSize = 1;
63 : const size_t AssemblerImpl::kLongJumpSize = kLongJumpOpcodeSize + 4;
64 :
65 : OperandImpl::OperandImpl(const Register32& base)
66 : : base_(base.id()),
67 : index_(kRegisterNone),
68 E : scale_(kTimes1) {
69 E : }
70 :
71 : OperandImpl::OperandImpl(const Register32& base,
72 : const DisplacementImpl& displacement)
73 : : base_(base.id()),
74 : index_(kRegisterNone),
75 : scale_(kTimes1),
76 E : displacement_(displacement) {
77 : // There must be a base register.
78 E : DCHECK_NE(kRegisterNone, base_);
79 E : }
80 :
81 : OperandImpl::OperandImpl(const DisplacementImpl& displacement)
82 : : base_(kRegisterNone),
83 : index_(kRegisterNone),
84 : scale_(kTimes1),
85 E : displacement_(displacement) {
86 E : DCHECK_NE(kSizeNone, displacement.size());
87 E : }
88 :
89 : OperandImpl::OperandImpl(const Register32& base,
90 : const Register32& index,
91 : ScaleFactor scale,
92 : const DisplacementImpl& displacement)
93 : : base_(base.id()),
94 : index_(index.id()),
95 : scale_(scale),
96 E : displacement_(displacement) {
97 : // ESP cannot be used as an index register.
98 E : DCHECK_NE(kRegisterEsp, index.id());
99 E : DCHECK_NE(kSizeNone, displacement.size());
100 E : }
101 :
102 : OperandImpl::OperandImpl(const Register32& base,
103 : const Register32& index,
104 : ScaleFactor scale)
105 : : base_(base.id()),
106 : index_(index.id()),
107 E : scale_(scale) {
108 : // ESP cannot be used as an index register.
109 E : DCHECK_NE(kRegisterEsp, index.id());
110 E : DCHECK_EQ(kSizeNone, displacement_.size());
111 E : }
112 :
113 : OperandImpl::OperandImpl(const Register32& index,
114 : ScaleFactor scale,
115 : const DisplacementImpl& displacement)
116 : : base_(kRegisterNone),
117 : index_(index.id()),
118 : scale_(scale),
119 E : displacement_(displacement) {
120 : // ESP cannot be used as an index register.
121 E : DCHECK_NE(kRegisterEsp, index.id());
122 E : DCHECK_NE(kSizeNone, displacement.size());
123 E : }
124 :
125 : OperandImpl::OperandImpl(RegisterId base,
126 : RegisterId index,
127 : ScaleFactor scale,
128 : const DisplacementImpl& displacement)
129 : : base_(base),
130 : index_(index),
131 : scale_(scale),
132 E : displacement_(displacement) {
133 E : }
134 :
135 : ValueImpl::ValueImpl()
136 E : : value_(0), reference_(NULL), size_(kSizeNone) {
137 E : }
138 :
139 : ValueImpl::ValueImpl(uint32 value, ValueSize size)
140 E : : value_(value), reference_(NULL), size_(size) {
141 E : }
142 :
143 : ValueImpl::ValueImpl(uint32 value,
144 : ValueSize size,
145 : const void* value_ref)
146 E : : value_(value), reference_(value_ref), size_(size) {
147 : // We can't have a 16-bit value *and* a reference, as there are no
148 : // addressing modes that accept 16-bit input.
149 E : DCHECK(value_ref == NULL || size != kSize16Bit);
150 E : }
151 :
152 E : bool ValueImpl::operator==(const ValueImpl& rhs) const {
153 : return value_ == rhs.value_ &&
154 : reference_ == rhs.reference_ &&
155 E : size_ == rhs.size_;
156 E : }
157 :
158 : // This class is used to buffer a single instruction during it's creation.
159 : // TODO(siggi): Add a small state machine in debug mode to ensure the
160 : // correct order of invocation to opcode/modrm etc.
161 : class AssemblerImpl::InstructionBuffer {
162 : public:
163 : explicit InstructionBuffer(AssemblerImpl* assm);
164 : ~InstructionBuffer();
165 :
166 : // @name Accessors.
167 : // @{
168 E : size_t len() const { return len_; }
169 E : const uint8* buf() const { return buf_; }
170 E : size_t num_references() const { return num_references_; }
171 E : const size_t *reference_offsets() const { return reference_offsets_; }
172 E : const void*const* references() const { return references_; }
173 : // @}
174 :
175 : // Emits operand size prefix (0x66) bytes.
176 : // @param count The number of operand size prefix bytes to emit.
177 : void EmitOperandSizePrefix(size_t count);
178 : // Emit an opcode byte.
179 : void EmitOpCodeByte(uint8 opcode);
180 : // Emit a ModR/M byte with an opcode extension.
181 : void EmitModRMByte(Mod mod, uint8 op, RegisterId reg1);
182 : // Emit a ModR/M byte with a destination register.
183 : void EmitModRMByte(Mod mod, RegisterId reg2, RegisterId reg1);
184 : // Emit a SIB byte.
185 : void EmitScaleIndexBaseByte(ScaleFactor scale,
186 : RegisterId index,
187 : RegisterId base);
188 : // Emit an operand.
189 : void EmitOperand(uint8 reg_op, const OperandImpl& op);
190 :
191 : // Emit an 8-bit displacement, with optional reference info.
192 : void Emit8BitDisplacement(const DisplacementImpl& disp);
193 :
194 : // Emit a 32-bit displacement with optional reference info.
195 : void Emit32BitDisplacement(const DisplacementImpl& disp);
196 :
197 : // Emit an 8-bit PC-relative value.
198 : void Emit8BitPCRelative(uint32 location, const ValueImpl& disp);
199 :
200 : // Emit a 32-bit PC-relative value.
201 : void Emit32BitPCRelative(uint32 location, const ValueImpl& disp);
202 :
203 : // Emit a 16-bit immediate value.
204 : void Emit16BitValue(uint16 value);
205 :
206 : // Emit an arithmetic instruction with various encoding.
207 : void EmitArithmeticInstruction(
208 : uint8 op, const Register& dst, const Register& src);
209 : void EmitArithmeticInstruction(
210 : uint8 op, const Register& dst, const OperandImpl& src);
211 : void EmitArithmeticInstruction(
212 : uint8 op, const OperandImpl& dst, const Register32& src);
213 : void EmitArithmeticInstructionToRegister32(uint8 op_eax, uint8 op_8,
214 : uint8 op_32, uint8 sub_op, const Register32& dst,
215 : const ImmediateImpl& src);
216 : void EmitArithmeticInstructionToRegister8(uint8 op_eax, uint8 op_8,
217 : uint8 sub_op, const Register8& dst, const ImmediateImpl& src);
218 : void EmitArithmeticInstructionToOperand(uint8 op_8, uint8 op_32, uint8 sub_op,
219 : const OperandImpl& dst, const ImmediateImpl& src);
220 :
221 : // Emit an XCHG instruction.
222 : void EmitXchg(ValueSize size, RegisterId dst, RegisterId src);
223 :
224 : // Add reference at current location.
225 : void AddReference(const void* reference);
226 :
227 : protected:
228 : void EmitByte(uint8 byte);
229 :
230 : AssemblerImpl* asm_;
231 : size_t num_references_;
232 : const void* (references_)[2];
233 : size_t reference_offsets_[2];
234 : size_t len_;
235 : uint8 buf_[kMaxInstructionLength];
236 : };
237 :
238 : AssemblerImpl::InstructionBuffer::InstructionBuffer(AssemblerImpl* assm)
239 E : : asm_(assm), len_(0), num_references_(0) {
240 E : DCHECK(assm != NULL);
241 : #ifndef NDEBUG
242 : // Initialize the buffer in debug mode for easier debugging.
243 E : ::memset(buf_, 0xCC, sizeof(buf_));
244 : #endif
245 E : }
246 :
247 E : AssemblerImpl::InstructionBuffer::~InstructionBuffer() {
248 E : asm_->Output(*this);
249 E : }
250 :
251 E : void AssemblerImpl::InstructionBuffer::EmitOperandSizePrefix(size_t count) {
252 E : for (size_t i = 0; i < count; ++i)
253 E : EmitByte(kOperandSizePrefix);
254 E : }
255 :
256 E : void AssemblerImpl::InstructionBuffer::EmitOpCodeByte(uint8 opcode) {
257 E : EmitByte(opcode);
258 E : }
259 :
260 : void AssemblerImpl::InstructionBuffer::EmitModRMByte(
261 E : Mod mod, uint8 reg_op, RegisterId reg1) {
262 E : DCHECK_LE(reg_op, 8);
263 E : DCHECK_NE(kRegisterNone, reg1);
264 E : EmitByte((mod << 6) | (reg_op << 3) | Register::Code(reg1));
265 E : }
266 :
267 : void AssemblerImpl::InstructionBuffer::EmitModRMByte(
268 E : Mod mod, RegisterId reg2, RegisterId reg1) {
269 E : DCHECK_NE(kRegisterNone, reg2);
270 E : DCHECK_NE(kRegisterNone, reg1);
271 E : EmitModRMByte(mod, Register::Code(reg2), reg1);
272 E : }
273 :
274 : void AssemblerImpl::InstructionBuffer::EmitScaleIndexBaseByte(
275 E : ScaleFactor scale, RegisterId index, RegisterId base) {
276 E : DCHECK_NE(kRegisterNone, index);
277 E : DCHECK_NE(kRegisterNone, base);
278 :
279 E : EmitByte((scale << 6) | (Register::Code(index) << 3) | Register::Code(base));
280 E : }
281 :
282 : void AssemblerImpl::InstructionBuffer::EmitOperand(
283 E : uint8 reg_op, const OperandImpl& op) {
284 E : DCHECK_GE(8, reg_op);
285 :
286 : // The op operand can encode any one of the following things:
287 : // An indirect register access [EAX].
288 : // An indirect 32-bit displacement only [0xDEADBEEF].
289 : // An indirect base register + 32/8-bit displacement [EAX+0xDEADBEEF].
290 : // An indirect base + index register*scale [EAX+ECX*4].
291 : // An indirect base + index register*scale + 32/8-bit displacement
292 : // [EAX+ECX*4+0xDEADBEEF].
293 : // To complicate things, there are certain combinations that can't be encoded
294 : // canonically. The mode [ESP] or [ESP+disp] can never be encoded in a
295 : // ModR/M byte alone, as ESP in the ModR/M byte for any of the indirect modes
296 : // is overloaded to select the SIB representation.
297 : // Likewise [EBP] is overloaded to encode the [disp32] case.
298 : // See e.g. http://ref.x86asm.net/geek32-abc.html#modrm_byte_32 for a nice
299 : // overview table of the ModR/M byte encoding.
300 :
301 : // ESP can never be used as an index register on X86.
302 E : DCHECK_NE(kRegisterEsp, op.index());
303 :
304 : // Is there an index register?
305 E : if (op.index() == kRegisterNone) {
306 E : DCHECK_EQ(kTimes1, op.scale());
307 :
308 : // No index register, is there a base register?
309 E : if (op.base() == kRegisterNone) {
310 : // No base register, this is a displacement only.
311 E : DCHECK_NE(kSizeNone, op.displacement().size());
312 E : DCHECK_EQ(kTimes1, op.scale());
313 :
314 : // The [disp32] mode is encoded by overloading [EBP].
315 E : EmitModRMByte(kReg1Ind, reg_op, kRegisterEbp);
316 E : Emit32BitDisplacement(op.displacement());
317 E : } else {
318 : // Base register only, is it ESP?
319 E : if (op.base() == kRegisterEsp) {
320 : // The [ESP] and [ESP+disp] cases cannot be encoded without a SIB byte.
321 E : if (op.displacement().size() == kSizeNone) {
322 E : EmitModRMByte(kReg1Ind, reg_op, kRegisterEsp);
323 E : EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
324 E : } else if (op.displacement().size() == kSize8Bit) {
325 E : EmitModRMByte(kReg1ByteDisp, reg_op, kRegisterEsp);
326 E : EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
327 E : Emit8BitDisplacement(op.displacement());
328 E : } else {
329 E : DCHECK_EQ(kSize32Bit, op.displacement().size());
330 E : EmitModRMByte(kReg1WordDisp, reg_op, kRegisterEsp);
331 E : EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
332 E : Emit32BitDisplacement(op.displacement());
333 E : }
334 E : } else if (op.displacement().size() == kSizeNone) {
335 E : if (op.base() == kRegisterEbp) {
336 : // The [EBP] case cannot be encoded canonically, there always must
337 : // be a (zero) displacement.
338 E : EmitModRMByte(kReg1ByteDisp, reg_op, op.base());
339 E : Emit8BitDisplacement(DisplacementImpl(0, kSize8Bit, NULL));
340 E : } else {
341 E : EmitModRMByte(kReg1Ind, reg_op, op.base());
342 E : }
343 E : } else if (op.displacement().size() == kSize8Bit) {
344 : // It's [base+disp8], or possibly [EBP].
345 E : EmitModRMByte(kReg1ByteDisp, reg_op, op.base());
346 E : Emit8BitDisplacement(op.displacement());
347 E : } else {
348 E : DCHECK_EQ(kSize32Bit, op.displacement().size());
349 : // It's [base+disp32].
350 E : EmitModRMByte(kReg1WordDisp, reg_op, op.base());
351 E : Emit32BitDisplacement(op.displacement());
352 : }
353 E : }
354 E : } else if (op.base() == kRegisterNone) {
355 : // Index, no base.
356 E : DCHECK_NE(kRegisterNone, op.index());
357 E : DCHECK_EQ(kRegisterNone, op.base());
358 :
359 : // This mode always has a 32 bit displacement.
360 E : EmitModRMByte(kReg1Ind, reg_op, kRegisterEsp);
361 E : EmitScaleIndexBaseByte(op.scale(), op.index(), kRegisterEbp);
362 E : Emit32BitDisplacement(op.displacement());
363 E : } else {
364 : // Index and base case.
365 E : DCHECK_NE(kRegisterNone, op.index());
366 E : DCHECK_NE(kRegisterNone, op.base());
367 :
368 : // Is there a displacement?
369 E : if (op.displacement().size() == kSizeNone) {
370 E : EmitModRMByte(kReg1Ind, reg_op, kRegisterEsp);
371 E : EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
372 E : } else if (op.displacement().size() == kSize8Bit) {
373 E : EmitModRMByte(kReg1ByteDisp, reg_op, kRegisterEsp);
374 E : EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
375 E : Emit8BitDisplacement(op.displacement());
376 E : } else {
377 E : DCHECK_EQ(kSize32Bit, op.displacement().size());
378 E : EmitModRMByte(kReg1WordDisp, reg_op, kRegisterEsp);
379 E : EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
380 E : Emit32BitDisplacement(op.displacement());
381 : }
382 : }
383 E : }
384 :
385 : void AssemblerImpl::InstructionBuffer::Emit8BitDisplacement(
386 E : const DisplacementImpl& disp) {
387 E : DCHECK(disp.size() == kSize8Bit);
388 :
389 E : AddReference(disp.reference());
390 :
391 E : EmitByte(disp.value());
392 E : }
393 :
394 : void AssemblerImpl::InstructionBuffer::Emit32BitDisplacement(
395 E : const DisplacementImpl& disp) {
396 E : AddReference(disp.reference());
397 :
398 E : uint32 value = disp.value();
399 E : EmitByte(value);
400 E : EmitByte(value >> 8);
401 E : EmitByte(value >> 16);
402 E : EmitByte(value >> 24);
403 E : }
404 :
405 : void AssemblerImpl::InstructionBuffer::Emit8BitPCRelative(
406 E : uint32 location, const ValueImpl& value) {
407 E : DCHECK_EQ(kSize8Bit, value.size());
408 :
409 E : AddReference(value.reference());
410 :
411 : // Turn the absolute value into a value relative to the address of
412 : // the end of the emitted constant.
413 E : int32 relative_value = value.value() - (location + len_ + 1);
414 E : DCHECK_LE(std::numeric_limits<int8>::min(), relative_value);
415 E : DCHECK_GE(std::numeric_limits<int8>::max(), relative_value);
416 E : EmitByte(relative_value);
417 E : }
418 :
419 : void AssemblerImpl::InstructionBuffer::Emit32BitPCRelative(
420 E : uint32 location, const ValueImpl& value) {
421 E : DCHECK_EQ(kSize32Bit, value.size());
422 :
423 E : AddReference(value.reference());
424 :
425 : // Turn the absolute value into a value relative to the address of
426 : // the end of the emitted constant.
427 E : uint32 relative_value = value.value() - (location + len_ + 4);
428 E : EmitByte(relative_value);
429 E : EmitByte(relative_value >> 8);
430 E : EmitByte(relative_value >> 16);
431 E : EmitByte(relative_value >> 24);
432 E : }
433 :
434 E : void AssemblerImpl::InstructionBuffer::Emit16BitValue(uint16 value) {
435 E : EmitByte(value);
436 E : EmitByte(value >> 8);
437 E : }
438 :
439 : void AssemblerImpl::InstructionBuffer::EmitArithmeticInstruction(
440 E : uint8 op, const Register& dst, const Register& src) {
441 E : DCHECK_EQ(dst.size(), src.size());
442 E : EmitOpCodeByte(op);
443 E : EmitModRMByte(kReg1, dst.id(), src.id());
444 E : }
445 :
446 : void AssemblerImpl::InstructionBuffer::EmitArithmeticInstruction(
447 E : uint8 op, const Register& dst, const OperandImpl& src) {
448 E : EmitOpCodeByte(op);
449 E : EmitOperand(dst.code(), src);
450 E : }
451 :
452 : void AssemblerImpl::InstructionBuffer::EmitArithmeticInstruction(
453 E : uint8 op, const OperandImpl& dst, const Register32& src) {
454 E : EmitOpCodeByte(op);
455 E : EmitOperand(src.code(), dst);
456 E : }
457 :
458 : void AssemblerImpl::InstructionBuffer::EmitArithmeticInstructionToRegister32(
459 : uint8 op_eax, uint8 op_8, uint8 op_32, uint8 sub_op,
460 E : const Register32& dst, const ImmediateImpl& src) {
461 E : if (dst.id() == kRegisterEax && src.size() == kSize32Bit) {
462 : // Special encoding for EAX.
463 E : EmitOpCodeByte(op_eax);
464 E : Emit32BitDisplacement(src);
465 E : } else if (src.size() == kSize8Bit) {
466 E : EmitOpCodeByte(op_8);
467 E : EmitModRMByte(kReg1, sub_op, dst.id());
468 E : Emit8BitDisplacement(src);
469 E : } else {
470 E : EmitOpCodeByte(op_32);
471 E : EmitModRMByte(kReg1, sub_op, dst.id());
472 E : Emit32BitDisplacement(src);
473 : }
474 E : }
475 :
476 : void AssemblerImpl::InstructionBuffer::EmitArithmeticInstructionToRegister8(
477 : uint8 op_eax, uint8 op_8, uint8 sub_op,
478 E : const Register8& dst, const ImmediateImpl& src) {
479 E : DCHECK(src.size() == kSize8Bit);
480 E : if (dst.code() == kAccumulatorCode) {
481 : // Special encoding for AL/AX/EAX.
482 E : EmitOpCodeByte(op_eax);
483 E : } else {
484 E : EmitOpCodeByte(op_8);
485 E : EmitModRMByte(kReg1, sub_op, dst.id());
486 : }
487 E : Emit8BitDisplacement(src);
488 E : }
489 :
490 : void AssemblerImpl::InstructionBuffer::EmitArithmeticInstructionToOperand(
491 : uint8 op_8, uint8 op_32, uint8 sub_op,
492 E : const OperandImpl& dst, const ImmediateImpl& src) {
493 E : if (src.size() == kSize8Bit) {
494 E : EmitOpCodeByte(op_8);
495 E : EmitOperand(sub_op, dst);
496 E : Emit8BitDisplacement(src);
497 E : } else {
498 E : EmitOpCodeByte(op_32);
499 E : EmitOperand(sub_op, dst);
500 E : Emit32BitDisplacement(src);
501 : }
502 E : }
503 :
504 : void AssemblerImpl::InstructionBuffer::EmitXchg(
505 E : ValueSize size, RegisterId dst, RegisterId src) {
506 : // Encoding for 8-bit registers.
507 E : if (size == kSize8Bit) {
508 E : EmitOpCodeByte(0x86);
509 E : EmitModRMByte(kReg1, src, dst);
510 E : } else {
511 : // 16-bit encodings are identical to 32-bit encodings, simply with
512 : // a operand size override prefix.
513 E : if (size == kSize16Bit)
514 E : EmitOperandSizePrefix(1);
515 :
516 : // If either register is EAX/AX there's a 1-byte encoding.
517 E : RegisterCode dst_code = Register::Code(dst);
518 E : RegisterCode src_code = Register::Code(src);
519 E : if (src_code == kAccumulatorCode || dst_code == kAccumulatorCode) {
520 E : RegisterCode other_register = dst_code;
521 E : if (dst_code == kAccumulatorCode)
522 E : other_register = src_code;
523 E : EmitOpCodeByte(0x90 | other_register);
524 E : } else {
525 : // Otherwise we use a 2-byte encoding with a ModR/M byte.
526 E : EmitOpCodeByte(0x87);
527 E : EmitModRMByte(kReg1, src, dst);
528 : }
529 : }
530 E : }
531 :
532 E : void AssemblerImpl::InstructionBuffer::AddReference(const void* reference) {
533 E : if (reference == NULL)
534 E : return;
535 :
536 E : DCHECK_GT(arraysize(references_), num_references_);
537 E : reference_offsets_[num_references_] = len();
538 E : references_[num_references_] = reference;
539 E : ++num_references_;
540 E : }
541 :
542 E : void AssemblerImpl::InstructionBuffer::EmitByte(uint8 byte) {
543 E : DCHECK_GT(sizeof(buf_), len_);
544 E : buf_[len_++] = byte;
545 E : }
546 :
547 : AssemblerImpl::AssemblerImpl(uint32 location, InstructionSerializer* serializer)
548 E : : location_(location), serializer_(serializer) {
549 E : DCHECK(serializer != NULL);
550 E : }
551 :
552 E : void AssemblerImpl::nop(size_t size) {
553 : // These are NOP sequences suggested by the Intel Architecture
554 : // Software Developer's manual, page 4-8.
555 : //
556 : // 1: 0x90
557 : // 2: 0x66 0x90
558 : // 3: 0x66 0x66 0x90
559 : // 4: 0x0F 0x1F 0x40 0x00
560 : // 5: 0x0F 0x1F 0x44 0x00 0x00
561 : // 6: 0x66 0x0F 0x1F 0x44 0x00 0x00
562 : // 7: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00
563 : // 8: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
564 : // 9: 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
565 : // 10: 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
566 : // 11: 0x66 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
567 : //
568 : // It is further suggested not to put consecutive XCHG NOPs with prefixes,
569 : // but rather to mix them with 0x1F NOPs or XCHG NOPs without prefixes. The
570 : // basic nops without any operand prefixes (0x66) have been implemented as
571 : // helper functions nop1, nop4, nop5, nop7 and nop8. This implementation of
572 : // NOP sequences has been inspired by Oracle's HotSpot JVM JIT assembler
573 : // (http://openjdk.java.net/groups/hotspot/).
574 :
575 : // Eat up the NOPs in chunks of 15 bytes.
576 E : while (size >= 15) {
577 E : nop8(3); // 11-byte non-XCHG NOP.
578 E : nop1(3); // 4-byte prefixed XCHG NOP.
579 E : size -= 15;
580 E : }
581 E : DCHECK_GE(14u, size);
582 :
583 : // Handle the last chunk of bytes.
584 E : size_t prefix_count = 0;
585 E : switch (size) {
586 : // Handle 12- to 14-byte NOPs.
587 : case 14:
588 E : ++prefix_count;
589 : case 13:
590 E : ++prefix_count;
591 : case 12:
592 E : nop8(prefix_count); // 8- to 10-byte non-XCHG NOP.
593 E : nop1(3); // 4-byte prefixed XCHG NOP.
594 E : return;
595 :
596 : // Handle 8- to 11-byte NOPs.
597 : case 11:
598 E : ++prefix_count;
599 : case 10:
600 E : ++prefix_count;
601 : case 9:
602 E : ++prefix_count;
603 : case 8:
604 E : nop8(prefix_count); // 8- to 11-byte non-XCHG NOP.
605 E : return;
606 :
607 : // Handle 7-byte NOPs.
608 : case 7:
609 E : nop7(prefix_count); // 7-byte non-XCHG NOP.
610 E : return;
611 :
612 : // Handle 5- to 6-byte NOPs.
613 : case 6:
614 E : ++prefix_count;
615 : case 5:
616 E : nop5(prefix_count); // 5- to 6-byte non-XCHG NOP.
617 E : return;
618 :
619 : // Handle 4-byte NOPs.
620 : case 4:
621 E : nop4(prefix_count); // 4-byte non-XCHG NOP.
622 E : return;
623 :
624 : // Handle 1- to 3-byte NOPs.
625 : case 3:
626 E : ++prefix_count;
627 : case 2:
628 E : ++prefix_count;
629 : case 1:
630 E : nop1(prefix_count); // 1- to 3-byte XCHG NOP.
631 : return;
632 :
633 : case 0:
634 : // Nothing to do!
635 : break;
636 : }
637 : return;
638 E : }
639 :
640 E : void AssemblerImpl::call(const ImmediateImpl& dst) {
641 E : InstructionBuffer instr(this);
642 :
643 E : instr.EmitOpCodeByte(0xE8);
644 E : instr.Emit32BitPCRelative(location_, dst);
645 E : }
646 :
647 E : void AssemblerImpl::call(const OperandImpl& dst) {
648 E : InstructionBuffer instr(this);
649 :
650 E : instr.EmitOpCodeByte(0xFF);
651 E : instr.EmitOperand(0x2, dst);
652 E : }
653 :
654 E : void AssemblerImpl::j(ConditionCode cc, const ImmediateImpl& dst) {
655 E : DCHECK_LE(kMinConditionCode, cc);
656 E : DCHECK_GE(kMaxConditionCode, cc);
657 :
658 E : InstructionBuffer instr(this);
659 E : if (dst.size() == kSize32Bit) {
660 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
661 E : instr.EmitOpCodeByte(0x80 | cc);
662 E : instr.Emit32BitPCRelative(location_, dst);
663 E : } else {
664 E : DCHECK_EQ(kSize8Bit, dst.size());
665 E : instr.EmitOpCodeByte(0x70 | cc);
666 E : instr.Emit8BitPCRelative(location_, dst);
667 : }
668 E : }
669 :
670 E : void AssemblerImpl::jecxz(const ImmediateImpl& dst) {
671 E : DCHECK_EQ(kSize8Bit, dst.size());
672 E : InstructionBuffer instr(this);
673 E : instr.EmitOpCodeByte(0xE3);
674 E : instr.Emit8BitPCRelative(location_, dst);
675 E : }
676 :
677 E : void AssemblerImpl::jmp(const ImmediateImpl& dst) {
678 E : InstructionBuffer instr(this);
679 :
680 E : if (dst.size() == kSize32Bit) {
681 E : instr.EmitOpCodeByte(0xE9);
682 E : instr.Emit32BitPCRelative(location_, dst);
683 E : } else {
684 E : DCHECK_EQ(kSize8Bit, dst.size());
685 E : instr.EmitOpCodeByte(0xEB);
686 E : instr.Emit8BitPCRelative(location_, dst);
687 : }
688 E : }
689 :
690 E : void AssemblerImpl::jmp(const OperandImpl& dst) {
691 E : InstructionBuffer instr(this);
692 :
693 E : instr.EmitOpCodeByte(0xFF);
694 E : instr.EmitOperand(0x4, dst);
695 E : }
696 :
697 E : void AssemblerImpl::l(LoopCode lc, const ImmediateImpl& dst) {
698 E : DCHECK_EQ(kSize8Bit, dst.size());
699 E : DCHECK_LE(0, lc);
700 E : DCHECK_GE(2, lc);
701 E : InstructionBuffer instr(this);
702 :
703 E : instr.EmitOpCodeByte(0xE0 | lc);
704 E : instr.Emit8BitPCRelative(location_, dst);
705 E : }
706 :
707 E : void AssemblerImpl::ret() {
708 E : InstructionBuffer instr(this);
709 :
710 E : instr.EmitOpCodeByte(0xC3);
711 E : }
712 :
713 E : void AssemblerImpl::ret(uint16 n) {
714 E : InstructionBuffer instr(this);
715 :
716 E : instr.EmitOpCodeByte(0xC2);
717 E : instr.Emit16BitValue(n);
718 E : }
719 :
720 E : void AssemblerImpl::set(ConditionCode cc, const Register32& dst) {
721 E : DCHECK_LE(kMinConditionCode, cc);
722 E : DCHECK_GE(kMaxConditionCode, cc);
723 :
724 E : InstructionBuffer instr(this);
725 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
726 E : instr.EmitOpCodeByte(0x90 | cc);
727 :
728 : // AMD64 Architecture Programmers Manual Volume 3: General-Purpose and System
729 : // Instructions: The reg field in the ModR/M byte is unused.
730 E : const Register32& unused = core::eax;
731 E : instr.EmitModRMByte(kReg1, unused.id(), dst.id());
732 E : }
733 :
734 E : void AssemblerImpl::mov_b(const OperandImpl& dst, const ImmediateImpl& src) {
735 E : InstructionBuffer instr(this);
736 :
737 E : instr.EmitOpCodeByte(0xC6);
738 E : instr.EmitOperand(0, dst);
739 E : instr.Emit8BitDisplacement(src);
740 E : }
741 :
742 E : void AssemblerImpl::movzx_b(const Register32& dst, const OperandImpl& src) {
743 E : InstructionBuffer instr(this);
744 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
745 E : instr.EmitOpCodeByte(0xB6);
746 E : instr.EmitOperand(dst.code(), src);
747 E : }
748 :
749 E : void AssemblerImpl::mov(const Register32& dst, const Register32& src) {
750 E : InstructionBuffer instr(this);
751 :
752 E : instr.EmitOpCodeByte(0x8B);
753 E : instr.EmitModRMByte(kReg1, dst.id(), src.id());
754 E : }
755 :
756 E : void AssemblerImpl::mov(const Register32& dst, const OperandImpl& src) {
757 E : InstructionBuffer instr(this);
758 :
759 E : if (dst.id() == kRegisterEax && IsDisplacementOnly(src)) {
760 : // Special encoding for indirect displacement only to EAX.
761 E : instr.EmitOpCodeByte(0xA1);
762 E : instr.Emit32BitDisplacement(src.displacement());
763 E : } else {
764 E : instr.EmitOpCodeByte(0x8B);
765 E : instr.EmitOperand(dst.code(), src);
766 : }
767 E : }
768 :
769 E : void AssemblerImpl::mov(const OperandImpl& dst, const Register32& src) {
770 E : InstructionBuffer instr(this);
771 :
772 E : if (src.id() == kRegisterEax && IsDisplacementOnly(dst)) {
773 : // Special encoding for indirect displacement only from EAX.
774 E : instr.EmitOpCodeByte(0xA3);
775 E : instr.Emit32BitDisplacement(dst.displacement());
776 E : } else {
777 E : instr.EmitOpCodeByte(0x89);
778 E : instr.EmitOperand(src.code(), dst);
779 : }
780 E : }
781 :
782 E : void AssemblerImpl::mov(const Register32& dst, const ValueImpl& src) {
783 E : DCHECK_NE(kSizeNone, src.size());
784 E : InstructionBuffer instr(this);
785 :
786 E : instr.EmitOpCodeByte(0xB8 | dst.code());
787 E : instr.Emit32BitDisplacement(src);
788 E : }
789 :
790 E : void AssemblerImpl::mov(const OperandImpl& dst, const ImmediateImpl& src) {
791 E : InstructionBuffer instr(this);
792 :
793 E : instr.EmitOpCodeByte(0xC7);
794 E : instr.EmitOperand(0, dst);
795 E : instr.Emit32BitDisplacement(src);
796 E : }
797 :
798 E : void AssemblerImpl::mov_fs(const Register32& dst, const OperandImpl& src) {
799 E : InstructionBuffer instr(this);
800 E : instr.EmitOpCodeByte(kFsSegmentPrefix);
801 :
802 E : if (dst.id() == kRegisterEax && IsDisplacementOnly(src)) {
803 : // Special encoding for indirect displacement only to EAX.
804 i : instr.EmitOpCodeByte(0xA1);
805 i : instr.Emit32BitDisplacement(src.displacement());
806 i : } else {
807 E : instr.EmitOpCodeByte(0x8B);
808 E : instr.EmitOperand(dst.code(), src);
809 : }
810 E : }
811 :
812 E : void AssemblerImpl::mov_fs(const OperandImpl& dst, const Register32& src) {
813 E : InstructionBuffer instr(this);
814 E : instr.EmitOpCodeByte(kFsSegmentPrefix);
815 :
816 E : if (src.id() == kRegisterEax && IsDisplacementOnly(dst)) {
817 : // Special encoding for indirect displacement only from EAX.
818 i : instr.EmitOpCodeByte(0xA3);
819 i : instr.Emit32BitDisplacement(dst.displacement());
820 i : } else {
821 E : instr.EmitOpCodeByte(0x89);
822 E : instr.EmitOperand(src.code(), dst);
823 : }
824 E : }
825 :
826 E : void AssemblerImpl::lea(const Register32& dst, const OperandImpl& src) {
827 E : InstructionBuffer instr(this);
828 :
829 E : instr.EmitOpCodeByte(0x8D);
830 E : instr.EmitOperand(dst.code(), src);
831 E : }
832 :
833 E : void AssemblerImpl::push(const Register32& src) {
834 E : InstructionBuffer instr(this);
835 :
836 E : instr.EmitOpCodeByte(0x50 | src.code());
837 E : }
838 :
839 E : void AssemblerImpl::push(const ImmediateImpl& src) {
840 E : DCHECK_EQ(kSize32Bit, src.size());
841 E : InstructionBuffer instr(this);
842 :
843 E : instr.EmitOpCodeByte(0x68);
844 E : instr.Emit32BitDisplacement(src);
845 E : }
846 :
847 E : void AssemblerImpl::push(const OperandImpl& dst) {
848 E : InstructionBuffer instr(this);
849 :
850 E : instr.EmitOpCodeByte(0xFF);
851 E : instr.EmitOperand(0x6, dst);
852 E : }
853 :
854 E : void AssemblerImpl::pop(const Register32& src) {
855 E : InstructionBuffer instr(this);
856 :
857 E : instr.EmitOpCodeByte(0x58 | src.code());
858 E : }
859 :
860 E : void AssemblerImpl::pop(const OperandImpl& dst) {
861 E : InstructionBuffer instr(this);
862 :
863 E : instr.EmitOpCodeByte(0x8F);
864 E : instr.EmitOperand(0, dst);
865 E : }
866 :
867 E : void AssemblerImpl::pushfd() {
868 E : InstructionBuffer instr(this);
869 E : instr.EmitOpCodeByte(0x9C);
870 E : }
871 :
872 E : void AssemblerImpl::popfd() {
873 E : InstructionBuffer instr(this);
874 E : instr.EmitOpCodeByte(0x9D);
875 E : }
876 :
877 E : void AssemblerImpl::lahf() {
878 E : InstructionBuffer instr(this);
879 E : instr.EmitOpCodeByte(0x9F);
880 E : }
881 :
882 E : void AssemblerImpl::sahf() {
883 E : InstructionBuffer instr(this);
884 E : instr.EmitOpCodeByte(0x9E);
885 E : }
886 :
887 E : void AssemblerImpl::test(const Register8& dst, const Register8& src) {
888 E : InstructionBuffer instr(this);
889 E : instr.EmitArithmeticInstruction(0x84, dst, src);
890 E : }
891 :
892 E : void AssemblerImpl::test(const Register8& dst, const ImmediateImpl& src) {
893 E : InstructionBuffer instr(this);
894 E : instr.EmitArithmeticInstructionToRegister8(0xA8, 0xF6, 0, dst, src);
895 E : }
896 :
897 E : void AssemblerImpl::test(const Register32& dst, const Register32& src) {
898 E : InstructionBuffer instr(this);
899 E : instr.EmitArithmeticInstruction(0x85, dst, src);
900 E : }
901 :
902 E : void AssemblerImpl::test(const Register32& dst, const OperandImpl& src) {
903 : // Use commutative property for a smaller encoding.
904 E : test(src, dst);
905 E : }
906 :
907 E : void AssemblerImpl::test(const OperandImpl& dst, const Register32& src) {
908 E : InstructionBuffer instr(this);
909 E : instr.EmitArithmeticInstruction(0x85, dst, src);
910 E : }
911 :
912 E : void AssemblerImpl::test(const Register32& dst, const ImmediateImpl& src) {
913 E : if (src.size() == kSize8Bit) {
914 : // note: There is no encoding for a 8-bit immediate with 32-bit register.
915 E : test(dst, ImmediateImpl(src.value(), kSize32Bit));
916 E : } else {
917 E : InstructionBuffer instr(this);
918 E : instr.EmitArithmeticInstructionToRegister32(0xA9, 0xF7, 0xF7, 0, dst, src);
919 E : }
920 E : }
921 :
922 E : void AssemblerImpl::test(const OperandImpl& dst, const ImmediateImpl& src) {
923 E : if (src.size() == kSize8Bit) {
924 : // note: There is no encoding for a 8-bit immediate with 32-bit register.
925 E : test(dst, ImmediateImpl(src.value(), kSize32Bit));
926 E : } else {
927 E : InstructionBuffer instr(this);
928 E : instr.EmitArithmeticInstructionToOperand(0xF7, 0xF7, 0, dst, src);
929 E : }
930 E : }
931 :
932 E : void AssemblerImpl::cmp(const Register8& dst, const Register8& src) {
933 E : InstructionBuffer instr(this);
934 E : instr.EmitArithmeticInstruction(0x3A, dst, src);
935 E : }
936 :
937 E : void AssemblerImpl::cmp(const Register8& dst, const ImmediateImpl& src) {
938 E : InstructionBuffer instr(this);
939 E : instr.EmitArithmeticInstructionToRegister8(0x3C, 0x80, 7, dst, src);
940 E : }
941 :
942 E : void AssemblerImpl::cmp(const Register32& dst, const Register32& src) {
943 E : InstructionBuffer instr(this);
944 E : instr.EmitArithmeticInstruction(0x3B, dst, src);
945 E : }
946 :
947 E : void AssemblerImpl::cmp(const Register32& dst, const OperandImpl& src) {
948 E : InstructionBuffer instr(this);
949 E : instr.EmitArithmeticInstruction(0x3B, dst, src);
950 E : }
951 :
952 E : void AssemblerImpl::cmp(const OperandImpl& dst, const Register32& src) {
953 E : InstructionBuffer instr(this);
954 E : instr.EmitArithmeticInstruction(0x39, dst, src);
955 E : }
956 :
957 E : void AssemblerImpl::cmp(const Register32& dst, const ImmediateImpl& src) {
958 E : InstructionBuffer instr(this);
959 E : instr.EmitArithmeticInstructionToRegister32(0x3D, 0x83, 0x81, 7, dst, src);
960 E : }
961 :
962 E : void AssemblerImpl::cmp(const OperandImpl& dst, const ImmediateImpl& src) {
963 E : InstructionBuffer instr(this);
964 E : instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 7, dst, src);
965 E : }
966 :
967 E : void AssemblerImpl::add(const Register8& dst, const Register8& src) {
968 E : InstructionBuffer instr(this);
969 E : instr.EmitArithmeticInstruction(0x02, dst, src);
970 E : }
971 :
972 E : void AssemblerImpl::add(const Register8& dst, const ImmediateImpl& src) {
973 E : InstructionBuffer instr(this);
974 E : instr.EmitArithmeticInstructionToRegister8(0x04, 0x80, 0, dst, src);
975 E : }
976 :
977 E : void AssemblerImpl::add(const Register32& dst, const Register32& src) {
978 E : InstructionBuffer instr(this);
979 E : instr.EmitArithmeticInstruction(0x03, dst, src);
980 E : }
981 :
982 E : void AssemblerImpl::add(const Register32& dst, const OperandImpl& src) {
983 E : InstructionBuffer instr(this);
984 E : instr.EmitArithmeticInstruction(0x03, dst, src);
985 E : }
986 :
987 E : void AssemblerImpl::add(const OperandImpl& dst, const Register32& src) {
988 E : InstructionBuffer instr(this);
989 E : instr.EmitArithmeticInstruction(0x01, dst, src);
990 E : }
991 :
992 E : void AssemblerImpl::add(const Register32& dst, const ImmediateImpl& src) {
993 E : InstructionBuffer instr(this);
994 E : instr.EmitArithmeticInstructionToRegister32(0x05, 0x83, 0x81, 0, dst, src);
995 E : }
996 :
997 E : void AssemblerImpl::add(const OperandImpl& dst, const ImmediateImpl& src) {
998 E : InstructionBuffer instr(this);
999 E : instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 0, dst, src);
1000 E : }
1001 :
1002 E : void AssemblerImpl::sub(const Register8& dst, const Register8& src) {
1003 E : InstructionBuffer instr(this);
1004 E : instr.EmitArithmeticInstruction(0x2A, dst, src);
1005 E : }
1006 :
1007 E : void AssemblerImpl::sub(const Register8& dst, const ImmediateImpl& src) {
1008 E : InstructionBuffer instr(this);
1009 E : instr.EmitArithmeticInstructionToRegister8(0x2C, 0x80, 5, dst, src);
1010 E : }
1011 :
1012 E : void AssemblerImpl::sub(const Register32& dst, const Register32& src) {
1013 E : InstructionBuffer instr(this);
1014 E : instr.EmitArithmeticInstruction(0x2B, dst, src);
1015 E : }
1016 :
1017 E : void AssemblerImpl::sub(const Register32& dst, const OperandImpl& src) {
1018 E : InstructionBuffer instr(this);
1019 E : instr.EmitArithmeticInstruction(0x2B, dst, src);
1020 E : }
1021 :
1022 E : void AssemblerImpl::sub(const OperandImpl& dst, const Register32& src) {
1023 E : InstructionBuffer instr(this);
1024 E : instr.EmitArithmeticInstruction(0x29, dst, src);
1025 E : }
1026 :
1027 E : void AssemblerImpl::sub(const Register32& dst, const ImmediateImpl& src) {
1028 E : InstructionBuffer instr(this);
1029 E : instr.EmitArithmeticInstructionToRegister32(0x2D, 0x83, 0x81, 5, dst, src);
1030 E : }
1031 :
1032 E : void AssemblerImpl::sub(const OperandImpl& dst, const ImmediateImpl& src) {
1033 E : InstructionBuffer instr(this);
1034 E : instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 5, dst, src);
1035 E : }
1036 :
1037 E : void AssemblerImpl::shl(const Register32& dst, const ImmediateImpl& src) {
1038 E : InstructionBuffer instr(this);
1039 E : if (src.value() == 1) {
1040 E : instr.EmitOpCodeByte(0xD1);
1041 E : instr.EmitModRMByte(kReg1, 4, dst.id());
1042 E : } else {
1043 E : instr.EmitOpCodeByte(0xC1);
1044 E : instr.EmitModRMByte(kReg1, 4, dst.id());
1045 E : instr.Emit8BitDisplacement(src);
1046 : }
1047 E : }
1048 :
1049 E : void AssemblerImpl::shr(const Register32& dst, const ImmediateImpl& src) {
1050 E : InstructionBuffer instr(this);
1051 E : if (src.value() == 1) {
1052 E : instr.EmitOpCodeByte(0xD1);
1053 E : instr.EmitModRMByte(kReg1, 5, dst.id());
1054 E : } else {
1055 E : instr.EmitOpCodeByte(0xC1);
1056 E : instr.EmitModRMByte(kReg1, 5, dst.id());
1057 E : instr.Emit8BitDisplacement(src);
1058 : }
1059 E : }
1060 :
1061 E : void AssemblerImpl::xchg(const Register32& dst, const Register32& src) {
1062 E : InstructionBuffer instr(this);
1063 E : instr.EmitXchg(kSize32Bit, dst.id(), src.id());
1064 E : }
1065 :
1066 E : void AssemblerImpl::xchg(const Register16& dst, const Register16& src) {
1067 E : InstructionBuffer instr(this);
1068 E : instr.EmitXchg(kSize16Bit, dst.id(), src.id());
1069 E : }
1070 :
1071 E : void AssemblerImpl::xchg(const Register8& dst, const Register8& src) {
1072 E : InstructionBuffer instr(this);
1073 E : instr.EmitXchg(kSize8Bit, dst.id(), src.id());
1074 E : }
1075 :
1076 E : void AssemblerImpl::nop1(size_t prefix_count) {
1077 E : InstructionBuffer instr(this);
1078 E : instr.EmitOperandSizePrefix(prefix_count);
1079 E : instr.EmitXchg(kSize32Bit, kRegisterEax, kRegisterEax);
1080 E : }
1081 :
1082 E : void AssemblerImpl::nop4(size_t prefix_count) {
1083 E : InstructionBuffer instr(this);
1084 E : instr.EmitOperandSizePrefix(prefix_count);
1085 : // 4 bytes: NOP DWORD PTR [EAX + 0] 8-bit offset
1086 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1087 E : instr.EmitOpCodeByte(kNopOpCode);
1088 E : instr.EmitModRMByte(kReg1ByteDisp, 0, kRegisterEax);
1089 E : instr.Emit8BitDisplacement(DisplacementImpl(0, kSize8Bit));
1090 E : }
1091 :
1092 E : void AssemblerImpl::nop5(size_t prefix_count) {
1093 E : InstructionBuffer instr(this);
1094 E : instr.EmitOperandSizePrefix(prefix_count);
1095 : // 5 bytes: NOP DWORD PTR [EAX + EAX * 1 + 0] 8-bit offset
1096 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1097 E : instr.EmitOpCodeByte(kNopOpCode);
1098 : // esp in the ModR/M byte indicates SIB to follow.
1099 E : instr.EmitModRMByte(kReg1ByteDisp, 0, kRegisterEsp);
1100 E : instr.EmitScaleIndexBaseByte(kTimes1, kRegisterEax, kRegisterEax);
1101 E : instr.Emit8BitDisplacement(DisplacementImpl(0, kSize8Bit));
1102 E : }
1103 :
1104 E : void AssemblerImpl::nop7(size_t prefix_count) {
1105 E : InstructionBuffer instr(this);
1106 E : instr.EmitOperandSizePrefix(prefix_count);
1107 : // 7 bytes: NOP DWORD PTR [EAX + 0] 32-bit offset
1108 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1109 E : instr.EmitOpCodeByte(kNopOpCode);
1110 E : instr.EmitModRMByte(kReg1WordDisp, 0, kRegisterEax);
1111 E : instr.Emit32BitDisplacement(DisplacementImpl(0, kSize32Bit));
1112 E : }
1113 :
1114 E : void AssemblerImpl::nop8(size_t prefix_count) {
1115 E : InstructionBuffer instr(this);
1116 E : instr.EmitOperandSizePrefix(prefix_count);
1117 : // 8 bytes: NOP DWORD PTR [EAX + EAX * 1 + 0] 32-bit offset
1118 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1119 E : instr.EmitOpCodeByte(kNopOpCode);
1120 : // esp in the ModR/M byte indicates SIB to follow.
1121 E : instr.EmitModRMByte(kReg1WordDisp, 0, kRegisterEsp);
1122 E : instr.EmitScaleIndexBaseByte(kTimes1, kRegisterEax, kRegisterEax);
1123 E : instr.Emit32BitDisplacement(DisplacementImpl(0, kSize32Bit));
1124 E : }
1125 :
1126 E : void AssemblerImpl::Output(const InstructionBuffer& instr) {
1127 : serializer_->AppendInstruction(location_,
1128 : instr.buf(),
1129 : instr.len(),
1130 : instr.reference_offsets(),
1131 : instr.references(),
1132 E : instr.num_references());
1133 :
1134 E : location_ += instr.len();
1135 E : }
1136 :
1137 : } // namespace core
|