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 : #include "base/logging.h"
20 :
21 : namespace core {
22 :
23 E : const Register eax(kRegisterEax);
24 E : const Register ecx(kRegisterEcx);
25 E : const Register edx(kRegisterEdx);
26 E : const Register ebx(kRegisterEbx);
27 E : const Register esp(kRegisterEsp);
28 E : const Register ebp(kRegisterEbp);
29 E : const Register esi(kRegisterEsi);
30 E : const Register edi(kRegisterEdi);
31 :
32 : namespace {
33 :
34 : enum Mod {
35 : Reg1Ind = 0, // Register indirect mode.
36 : Reg1ByteDisp = 1, // Register + byte displacement.
37 : Reg1WordDisp = 2, // Register + word displacement.
38 : Reg1 = 3, // Register + word displacement.
39 : };
40 :
41 : const uint8 kTwoByteOpCodePrefix = 0x0F;
42 : const uint8 kFsSegmentPrefix = 0x64;
43 :
44 : // Returns true if @p operand is a displacement only - e.g.
45 : // specifies neither a base, nor an index register.
46 E : bool IsDisplacementOnly(const OperandImpl& operand) {
47 : return operand.displacement().size() != kSizeNone &&
48 : operand.base() == kRegisterNone &&
49 E : operand.index() == kRegisterNone;
50 E : }
51 :
52 : } // namespace
53 :
54 : const size_t AssemblerImpl::kShortBranchOpcodeSize = 1;
55 : const size_t AssemblerImpl::kShortBranchSize = kShortBranchOpcodeSize + 1;
56 :
57 : const size_t AssemblerImpl::kLongBranchOpcodeSize = 2;
58 : const size_t AssemblerImpl::kLongBranchSize = kLongBranchOpcodeSize + 4;
59 :
60 : const size_t AssemblerImpl::kShortJumpOpcodeSize = 1;
61 : const size_t AssemblerImpl::kShortJumpSize = kShortJumpOpcodeSize + 1;
62 :
63 : const size_t AssemblerImpl::kLongJumpOpcodeSize = 1;
64 : const size_t AssemblerImpl::kLongJumpSize = kLongJumpOpcodeSize + 4;
65 :
66 : OperandImpl::OperandImpl(Register base)
67 : : base_(base.code()),
68 : index_(kRegisterNone),
69 E : scale_(kTimes1) {
70 E : }
71 :
72 : OperandImpl::OperandImpl(Register base,
73 : const DisplacementImpl& displacement)
74 : : base_(base.code()),
75 : index_(kRegisterNone),
76 : scale_(kTimes1),
77 E : displacement_(displacement) {
78 : // There must be a base register.
79 E : DCHECK_NE(kRegisterNone, base_);
80 E : }
81 :
82 : OperandImpl::OperandImpl(const DisplacementImpl& displacement)
83 : : base_(kRegisterNone),
84 : index_(kRegisterNone),
85 : scale_(kTimes1),
86 E : displacement_(displacement) {
87 E : DCHECK_NE(kSizeNone, displacement.size());
88 E : }
89 :
90 : OperandImpl::OperandImpl(Register base,
91 : Register index,
92 : ScaleFactor scale,
93 : const DisplacementImpl& displacement)
94 : : base_(base.code()),
95 : index_(index.code()),
96 : scale_(scale),
97 E : displacement_(displacement) {
98 : // ESP cannot be used as an index register.
99 E : DCHECK_NE(kRegisterEsp, index.code());
100 E : DCHECK_NE(kSizeNone, displacement.size());
101 E : }
102 :
103 : OperandImpl::OperandImpl(Register base,
104 : Register index,
105 : ScaleFactor scale)
106 : : base_(base.code()),
107 : index_(index.code()),
108 E : scale_(scale) {
109 : // ESP cannot be used as an index register.
110 E : DCHECK_NE(kRegisterEsp, index.code());
111 E : DCHECK_EQ(kSizeNone, displacement_.size());
112 E : }
113 :
114 : OperandImpl::OperandImpl(Register index,
115 : ScaleFactor scale,
116 : const DisplacementImpl& displacement)
117 : : base_(kRegisterNone),
118 : index_(index.code()),
119 : scale_(scale),
120 E : displacement_(displacement) {
121 : // ESP cannot be used as an index register.
122 E : DCHECK_NE(kRegisterEsp, index.code());
123 E : DCHECK_NE(kSizeNone, displacement.size());
124 E : }
125 :
126 : OperandImpl::OperandImpl(RegisterCode base,
127 : RegisterCode index,
128 : ScaleFactor scale,
129 : const DisplacementImpl& displacement)
130 : : base_(base),
131 : index_(index),
132 : scale_(scale),
133 E : displacement_(displacement) {
134 E : }
135 :
136 : ValueImpl::ValueImpl()
137 E : : value_(0), reference_(NULL), size_(kSizeNone) {
138 E : }
139 :
140 : ValueImpl::ValueImpl(uint32 value, ValueSize size)
141 E : : value_(value), reference_(NULL), size_(size) {
142 E : }
143 :
144 : ValueImpl::ValueImpl(uint32 value,
145 : ValueSize size,
146 : const void* value_ref)
147 E : : value_(value), reference_(value_ref), size_(size) {
148 E : }
149 :
150 E : bool ValueImpl::operator==(const ValueImpl& rhs) const {
151 : return value_ == rhs.value_ &&
152 : reference_ == rhs.reference_ &&
153 E : size_ == rhs.size_;
154 E : }
155 :
156 : // This class is used to buffer a single instruction during it's creation.
157 : // TODO(siggi): Add a small state machine in debug mode to ensure the
158 : // correct order of invocation to opcode/modrm etc.
159 : class AssemblerImpl::InstructionBuffer {
160 : public:
161 : explicit InstructionBuffer(AssemblerImpl* assm);
162 : ~InstructionBuffer();
163 :
164 : // @name Accessors.
165 : // @{
166 E : size_t len() const { return len_; }
167 E : const uint8* buf() const { return buf_; }
168 E : size_t num_references() const { return num_references_; }
169 E : const size_t *reference_offsets() const { return reference_offsets_; }
170 E : const void*const* references() const { return references_; }
171 : // @}
172 :
173 : // Emit an opcode byte.
174 : void EmitOpCodeByte(uint8 opcode);
175 : // Emit a ModR/M byte, reg_op is either a register or an opcode
176 : // extension, as fits the instruction being generated.
177 : void EmitModRMByte(Mod mod, uint8 reg_op, RegisterCode reg1);
178 : // Emit a SIB byte.
179 : void EmitScaleIndexBaseByte(ScaleFactor scale,
180 : RegisterCode index,
181 : RegisterCode base);
182 : // Emit an operand.
183 : void EmitOperand(uint8 reg_op, const OperandImpl& op);
184 :
185 : // Emit an 8-bit displacement, with optional reference info.
186 : void Emit8BitDisplacement(const DisplacementImpl& disp);
187 :
188 : // Emit a 32-bit displacement with optional reference info.
189 : void Emit32BitDisplacement(const DisplacementImpl& disp);
190 :
191 : // Emit an 8-bit PC-relative value.
192 : void Emit8BitPCRelative(uint32 location, const ValueImpl& disp);
193 :
194 : // Emit a 32-bit PC-relative value.
195 : void Emit32BitPCRelative(uint32 location, const ValueImpl& disp);
196 :
197 : // Emit a 16-bit immediate value.
198 : void Emit16BitValue(uint16 value);
199 :
200 : // Emit an arithmetic instruction with various encoding.
201 : void EmitArithmeticInstruction(uint8 op, Register dst, Register src);
202 : void EmitArithmeticInstruction(
203 : uint8 op, Register dst, const OperandImpl& src);
204 : void EmitArithmeticInstruction(
205 : uint8 op, const OperandImpl& dst, Register src);
206 : void EmitArithmeticInstructionToRegister(uint8 op_eax, uint8 op_8,
207 : uint8 op_32, uint8 sub_op, Register dst, const ImmediateImpl& src);
208 : void EmitArithmeticInstructionToRegister8bit(uint8 op_eax, uint8 op_8,
209 : uint8 sub_op, Register dst, const ImmediateImpl& src);
210 : void EmitArithmeticInstructionToOperand(uint8 op_8, uint8 op_32, uint8 sub_op,
211 : const OperandImpl& dst, const ImmediateImpl& src);
212 :
213 : // Add reference at current location.
214 : void AddReference(const void* reference);
215 :
216 : protected:
217 : void EmitByte(uint8 byte);
218 :
219 : AssemblerImpl* asm_;
220 : size_t num_references_;
221 : const void* (references_)[2];
222 : size_t reference_offsets_[2];
223 : size_t len_;
224 : uint8 buf_[kMaxInstructionLength];
225 : };
226 :
227 : AssemblerImpl::InstructionBuffer::InstructionBuffer(AssemblerImpl* assm)
228 E : : asm_(assm), len_(0), num_references_(0) {
229 E : DCHECK(assm != NULL);
230 : #ifndef NDEBUG
231 : // Initialize the buffer in debug mode for easier debugging.
232 E : ::memset(buf_, 0xCC, sizeof(buf_));
233 : #endif
234 E : }
235 :
236 E : AssemblerImpl::InstructionBuffer::~InstructionBuffer() {
237 E : asm_->Output(*this);
238 E : }
239 :
240 E : void AssemblerImpl::InstructionBuffer::EmitOpCodeByte(uint8 opcode) {
241 E : EmitByte(opcode);
242 E : }
243 :
244 : void AssemblerImpl::InstructionBuffer::EmitModRMByte(
245 E : Mod mod, uint8 reg_op, RegisterCode reg1) {
246 E : DCHECK_LE(reg_op, 8);
247 E : DCHECK_NE(kRegisterNone, reg1);
248 :
249 E : EmitByte((mod << 6) | (reg_op << 3) | reg1);
250 E : }
251 :
252 : void AssemblerImpl::InstructionBuffer::EmitScaleIndexBaseByte(
253 E : ScaleFactor scale, RegisterCode index, RegisterCode base) {
254 E : DCHECK_NE(kRegisterNone, index);
255 E : DCHECK_NE(kRegisterNone, base);
256 :
257 E : EmitByte((scale << 6) | (index << 3) | base);
258 E : }
259 :
260 : void AssemblerImpl::InstructionBuffer::EmitOperand(
261 E : uint8 reg_op, const OperandImpl& op) {
262 E : DCHECK_GE(8, reg_op);
263 :
264 : // The op operand can encode any one of the following things:
265 : // An indirect register access [EAX].
266 : // An indirect 32-bit displacement only [0xDEADBEEF].
267 : // An indirect base register + 32/8-bit displacement [EAX+0xDEADBEEF].
268 : // An indirect base + index register*scale [EAX+ECX*4].
269 : // An indirect base + index register*scale + 32/8-bit displacement
270 : // [EAX+ECX*4+0xDEADBEEF].
271 : // To complicate things, there are certain combinations that can't be encoded
272 : // canonically. The mode [ESP] or [ESP+disp] can never be encoded in a
273 : // ModR/M byte alone, as ESP in the ModR/M byte for any of the indirect modes
274 : // is overloaded to select the SIB representation.
275 : // Likewise [EBP] is overloaded to encode the [disp32] case.
276 : // See e.g. http://ref.x86asm.net/geek32-abc.html#modrm_byte_32 for a nice
277 : // overview table of the ModR/M byte encoding.
278 :
279 : // ESP can never be used as an index register on X86.
280 E : DCHECK_NE(kRegisterEsp, op.index());
281 :
282 : // Is there an index register?
283 E : if (op.index() == kRegisterNone) {
284 E : DCHECK_EQ(kTimes1, op.scale());
285 :
286 : // No index register, is there a base register?
287 E : if (op.base() == kRegisterNone) {
288 : // No base register, this is a displacement only.
289 E : DCHECK_NE(kSizeNone, op.displacement().size());
290 E : DCHECK_EQ(kTimes1, op.scale());
291 :
292 : // The [disp32] mode is encoded by overloading [EBP].
293 E : EmitModRMByte(Reg1Ind, reg_op, kRegisterEbp);
294 E : Emit32BitDisplacement(op.displacement());
295 E : } else {
296 : // Base register only, is it ESP?
297 E : if (op.base() == kRegisterEsp) {
298 : // The [ESP] and [ESP+disp] cases cannot be encoded without a SIB byte.
299 E : if (op.displacement().size() == kSizeNone) {
300 E : EmitModRMByte(Reg1Ind, reg_op, kRegisterEsp);
301 E : EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
302 E : } else if (op.displacement().size() == kSize8Bit) {
303 E : EmitModRMByte(Reg1ByteDisp, reg_op, kRegisterEsp);
304 E : EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
305 E : Emit8BitDisplacement(op.displacement());
306 E : } else {
307 E : DCHECK_EQ(kSize32Bit, op.displacement().size());
308 E : EmitModRMByte(Reg1WordDisp, reg_op, kRegisterEsp);
309 E : EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
310 E : Emit32BitDisplacement(op.displacement());
311 E : }
312 E : } else if (op.displacement().size() == kSizeNone) {
313 E : if (op.base() == kRegisterEbp) {
314 : // The [EBP] case cannot be encoded canonically, there always must
315 : // be a (zero) displacement.
316 E : EmitModRMByte(Reg1ByteDisp, reg_op, op.base());
317 E : Emit8BitDisplacement(DisplacementImpl(0, kSize8Bit, NULL));
318 E : } else {
319 E : EmitModRMByte(Reg1Ind, reg_op, op.base());
320 E : }
321 E : } else if (op.displacement().size() == kSize8Bit) {
322 : // It's [base+disp8], or possibly [EBP].
323 E : EmitModRMByte(Reg1ByteDisp, reg_op, op.base());
324 E : Emit8BitDisplacement(op.displacement());
325 E : } else {
326 E : DCHECK_EQ(kSize32Bit, op.displacement().size());
327 : // It's [base+disp32].
328 E : EmitModRMByte(Reg1WordDisp, reg_op, op.base());
329 E : Emit32BitDisplacement(op.displacement());
330 : }
331 E : }
332 E : } else if (op.base() == kRegisterNone) {
333 : // Index, no base.
334 E : DCHECK_NE(kRegisterNone, op.index());
335 E : DCHECK_EQ(kRegisterNone, op.base());
336 :
337 : // This mode always has a 32 bit displacement.
338 E : EmitModRMByte(Reg1Ind, reg_op, kRegisterEsp);
339 E : EmitScaleIndexBaseByte(op.scale(), op.index(), kRegisterEbp);
340 E : Emit32BitDisplacement(op.displacement());
341 E : } else {
342 : // Index and base case.
343 E : DCHECK_NE(kRegisterNone, op.index());
344 E : DCHECK_NE(kRegisterNone, op.base());
345 :
346 : // Is there a displacement?
347 E : if (op.displacement().size() == kSizeNone) {
348 E : EmitModRMByte(Reg1Ind, reg_op, kRegisterEsp);
349 E : EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
350 E : } else if (op.displacement().size() == kSize8Bit) {
351 E : EmitModRMByte(Reg1ByteDisp, reg_op, kRegisterEsp);
352 E : EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
353 E : Emit8BitDisplacement(op.displacement());
354 E : } else {
355 E : DCHECK_EQ(kSize32Bit, op.displacement().size());
356 E : EmitModRMByte(Reg1WordDisp, reg_op, kRegisterEsp);
357 E : EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
358 E : Emit32BitDisplacement(op.displacement());
359 : }
360 : }
361 E : }
362 :
363 : void AssemblerImpl::InstructionBuffer::Emit8BitDisplacement(
364 E : const DisplacementImpl& disp) {
365 E : DCHECK(disp.size() == kSize8Bit);
366 :
367 E : AddReference(disp.reference());
368 :
369 E : EmitByte(disp.value());
370 E : }
371 :
372 : void AssemblerImpl::InstructionBuffer::Emit32BitDisplacement(
373 E : const DisplacementImpl& disp) {
374 E : AddReference(disp.reference());
375 :
376 E : uint32 value = disp.value();
377 E : EmitByte(value);
378 E : EmitByte(value >> 8);
379 E : EmitByte(value >> 16);
380 E : EmitByte(value >> 24);
381 E : }
382 :
383 : void AssemblerImpl::InstructionBuffer::Emit8BitPCRelative(
384 E : uint32 location, const ValueImpl& value) {
385 E : DCHECK_EQ(kSize8Bit, value.size());
386 :
387 E : AddReference(value.reference());
388 :
389 : // Turn the absolute value into a value relative to the address of
390 : // the end of the emitted constant.
391 E : int32 relative_value = value.value() - (location + len_ + 1);
392 E : DCHECK_LE(std::numeric_limits<int8>::min(), relative_value);
393 E : DCHECK_GE(std::numeric_limits<int8>::max(), relative_value);
394 E : EmitByte(relative_value);
395 E : }
396 :
397 : void AssemblerImpl::InstructionBuffer::Emit32BitPCRelative(
398 E : uint32 location, const ValueImpl& value) {
399 E : DCHECK_EQ(kSize32Bit, value.size());
400 :
401 E : AddReference(value.reference());
402 :
403 : // Turn the absolute value into a value relative to the address of
404 : // the end of the emitted constant.
405 E : uint32 relative_value = value.value() - (location + len_ + 4);
406 E : EmitByte(relative_value);
407 E : EmitByte(relative_value >> 8);
408 E : EmitByte(relative_value >> 16);
409 E : EmitByte(relative_value >> 24);
410 E : }
411 :
412 E : void AssemblerImpl::InstructionBuffer::Emit16BitValue(uint16 value) {
413 E : EmitByte(value);
414 E : EmitByte(value >> 8);
415 E : }
416 :
417 : void AssemblerImpl::InstructionBuffer::EmitArithmeticInstruction(
418 E : uint8 op, Register dst, Register src) {
419 E : EmitOpCodeByte(op);
420 E : EmitModRMByte(Reg1, dst.code(), src.code());
421 E : }
422 :
423 : void AssemblerImpl::InstructionBuffer::EmitArithmeticInstruction(
424 E : uint8 op, Register dst, const OperandImpl& src) {
425 E : EmitOpCodeByte(op);
426 E : EmitOperand(dst.code(), src);
427 E : }
428 :
429 : void AssemblerImpl::InstructionBuffer::EmitArithmeticInstruction(
430 E : uint8 op, const OperandImpl& dst, Register src) {
431 E : EmitOpCodeByte(op);
432 E : EmitOperand(src.code(), dst);
433 E : }
434 :
435 : void AssemblerImpl::InstructionBuffer::EmitArithmeticInstructionToRegister(
436 : uint8 op_eax, uint8 op_8, uint8 op_32, uint8 sub_op,
437 E : Register dst, const ImmediateImpl& src) {
438 E : if (dst.code() == kRegisterEax && src.size() == kSize32Bit) {
439 : // Special encoding for EAX.
440 E : EmitOpCodeByte(op_eax);
441 E : Emit32BitDisplacement(src);
442 E : } else if (src.size() == kSize8Bit) {
443 E : EmitOpCodeByte(op_8);
444 E : EmitModRMByte(Reg1, sub_op, dst.code());
445 E : Emit8BitDisplacement(src);
446 E : } else {
447 E : EmitOpCodeByte(op_32);
448 E : EmitModRMByte(Reg1, sub_op, dst.code());
449 E : Emit32BitDisplacement(src);
450 : }
451 E : }
452 :
453 : void AssemblerImpl::InstructionBuffer::EmitArithmeticInstructionToRegister8bit(
454 : uint8 op_eax, uint8 op_8, uint8 sub_op,
455 E : Register dst, const ImmediateImpl& src) {
456 E : DCHECK(src.size() == kSize8Bit);
457 E : if (dst.code() == kRegisterEax) {
458 : // Special encoding for EAX.
459 E : EmitOpCodeByte(op_eax);
460 E : } else {
461 E : EmitOpCodeByte(op_8);
462 E : EmitModRMByte(Reg1, sub_op, dst.code());
463 : }
464 E : Emit8BitDisplacement(src);
465 E : }
466 :
467 : void AssemblerImpl::InstructionBuffer::EmitArithmeticInstructionToOperand(
468 : uint8 op_8, uint8 op_32, uint8 sub_op,
469 E : const OperandImpl& dst, const ImmediateImpl& src) {
470 E : if (src.size() == kSize8Bit) {
471 E : EmitOpCodeByte(op_8);
472 E : EmitOperand(sub_op, dst);
473 E : Emit8BitDisplacement(src);
474 E : } else {
475 E : EmitOpCodeByte(op_32);
476 E : EmitOperand(sub_op, dst);
477 E : Emit32BitDisplacement(src);
478 : }
479 E : }
480 :
481 E : void AssemblerImpl::InstructionBuffer::AddReference(const void* reference) {
482 E : if (reference == NULL)
483 E : return;
484 :
485 E : DCHECK_GT(arraysize(references_), num_references_);
486 E : reference_offsets_[num_references_] = len();
487 E : references_[num_references_] = reference;
488 E : ++num_references_;
489 E : }
490 :
491 E : void AssemblerImpl::InstructionBuffer::EmitByte(uint8 byte) {
492 E : DCHECK_GT(sizeof(buf_), len_);
493 E : buf_[len_++] = byte;
494 E : }
495 :
496 : AssemblerImpl::AssemblerImpl(uint32 location, InstructionSerializer* serializer)
497 E : : location_(location), serializer_(serializer) {
498 E : DCHECK(serializer != NULL);
499 E : }
500 :
501 E : void AssemblerImpl::call(const ImmediateImpl& dst) {
502 E : InstructionBuffer instr(this);
503 :
504 E : instr.EmitOpCodeByte(0xE8);
505 E : instr.Emit32BitPCRelative(location_, dst);
506 E : }
507 :
508 E : void AssemblerImpl::call(const OperandImpl& dst) {
509 E : InstructionBuffer instr(this);
510 :
511 E : instr.EmitOpCodeByte(0xFF);
512 E : instr.EmitOperand(0x2, dst);
513 E : }
514 :
515 E : void AssemblerImpl::j(ConditionCode cc, const ImmediateImpl& dst) {
516 E : DCHECK_LE(kMinConditionCode, cc);
517 E : DCHECK_GE(kMaxConditionCode, cc);
518 :
519 E : InstructionBuffer instr(this);
520 E : if (dst.size() == kSize32Bit) {
521 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
522 E : instr.EmitOpCodeByte(0x80 | cc);
523 E : instr.Emit32BitPCRelative(location_, dst);
524 E : } else {
525 E : DCHECK_EQ(kSize8Bit, dst.size());
526 E : instr.EmitOpCodeByte(0x70 | cc);
527 E : instr.Emit8BitPCRelative(location_, dst);
528 : }
529 E : }
530 :
531 E : void AssemblerImpl::jecxz(const ImmediateImpl& dst) {
532 E : DCHECK_EQ(kSize8Bit, dst.size());
533 E : InstructionBuffer instr(this);
534 E : instr.EmitOpCodeByte(0xE3);
535 E : instr.Emit8BitPCRelative(location_, dst);
536 E : }
537 :
538 E : void AssemblerImpl::jmp(const ImmediateImpl& dst) {
539 E : InstructionBuffer instr(this);
540 :
541 E : if (dst.size() == kSize32Bit) {
542 E : instr.EmitOpCodeByte(0xE9);
543 E : instr.Emit32BitPCRelative(location_, dst);
544 E : } else {
545 E : DCHECK_EQ(kSize8Bit, dst.size());
546 E : instr.EmitOpCodeByte(0xEB);
547 E : instr.Emit8BitPCRelative(location_, dst);
548 : }
549 E : }
550 :
551 E : void AssemblerImpl::jmp(const OperandImpl& dst) {
552 E : InstructionBuffer instr(this);
553 :
554 E : instr.EmitOpCodeByte(0xFF);
555 E : instr.EmitOperand(0x4, dst);
556 E : }
557 :
558 E : void AssemblerImpl::l(LoopCode lc, const ImmediateImpl& dst) {
559 E : DCHECK_EQ(kSize8Bit, dst.size());
560 E : DCHECK_LE(0, lc);
561 E : DCHECK_GE(2, lc);
562 E : InstructionBuffer instr(this);
563 :
564 E : instr.EmitOpCodeByte(0xE0 | lc);
565 E : instr.Emit8BitPCRelative(location_, dst);
566 E : }
567 :
568 E : void AssemblerImpl::ret() {
569 E : InstructionBuffer instr(this);
570 :
571 E : instr.EmitOpCodeByte(0xC3);
572 E : }
573 :
574 E : void AssemblerImpl::ret(uint16 n) {
575 E : InstructionBuffer instr(this);
576 :
577 E : instr.EmitOpCodeByte(0xC2);
578 E : instr.Emit16BitValue(n);
579 E : }
580 :
581 E : void AssemblerImpl::set(ConditionCode cc, Register dst) {
582 E : DCHECK_LE(kMinConditionCode, cc);
583 E : DCHECK_GE(kMaxConditionCode, cc);
584 :
585 E : InstructionBuffer instr(this);
586 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
587 E : instr.EmitOpCodeByte(0x90 | cc);
588 :
589 : // AMD64 Architecture Programmers Manual Volume 3: General-Purpose and System
590 : // Instructions: The reg field in the ModR/M byte is unused.
591 E : Register unused = core::eax;
592 E : instr.EmitModRMByte(Reg1, unused.code(), dst.code());
593 E : }
594 :
595 E : void AssemblerImpl::mov_b(const OperandImpl& dst, const ImmediateImpl& src) {
596 E : InstructionBuffer instr(this);
597 :
598 E : instr.EmitOpCodeByte(0xC6);
599 E : instr.EmitOperand(0, dst);
600 E : instr.Emit8BitDisplacement(src);
601 E : }
602 :
603 E : void AssemblerImpl::movzx_b(Register dst, const OperandImpl& src) {
604 E : InstructionBuffer instr(this);
605 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
606 E : instr.EmitOpCodeByte(0xB6);
607 E : instr.EmitOperand(dst.code(), src);
608 E : }
609 :
610 E : void AssemblerImpl::mov(Register dst, Register src) {
611 E : InstructionBuffer instr(this);
612 :
613 E : instr.EmitOpCodeByte(0x8B);
614 E : instr.EmitModRMByte(Reg1, dst.code(), src.code());
615 E : }
616 :
617 E : void AssemblerImpl::mov(Register dst, const OperandImpl& src) {
618 E : InstructionBuffer instr(this);
619 :
620 E : if (dst.code() == kRegisterEax && IsDisplacementOnly(src)) {
621 : // Special encoding for indirect displacement only to EAX.
622 E : instr.EmitOpCodeByte(0xA1);
623 E : instr.Emit32BitDisplacement(src.displacement());
624 E : } else {
625 E : instr.EmitOpCodeByte(0x8B);
626 E : instr.EmitOperand(dst.code(), src);
627 : }
628 E : }
629 :
630 E : void AssemblerImpl::mov(const OperandImpl& dst, Register src) {
631 E : InstructionBuffer instr(this);
632 :
633 E : if (src.code() == kRegisterEax && IsDisplacementOnly(dst)) {
634 : // Special encoding for indirect displacement only from EAX.
635 E : instr.EmitOpCodeByte(0xA3);
636 E : instr.Emit32BitDisplacement(dst.displacement());
637 E : } else {
638 E : instr.EmitOpCodeByte(0x89);
639 E : instr.EmitOperand(src.code(), dst);
640 : }
641 E : }
642 :
643 E : void AssemblerImpl::mov(Register dst, const ValueImpl& src) {
644 E : DCHECK_NE(kSizeNone, src.size());
645 E : InstructionBuffer instr(this);
646 :
647 E : instr.EmitOpCodeByte(0xB8 | dst.code());
648 E : instr.Emit32BitDisplacement(src);
649 E : }
650 :
651 E : void AssemblerImpl::mov(const OperandImpl& dst, const ImmediateImpl& src) {
652 E : InstructionBuffer instr(this);
653 :
654 E : instr.EmitOpCodeByte(0xC7);
655 E : instr.EmitOperand(0, dst);
656 E : instr.Emit32BitDisplacement(src);
657 E : }
658 :
659 E : void AssemblerImpl::mov_fs(Register dst, const OperandImpl& src) {
660 E : InstructionBuffer instr(this);
661 E : instr.EmitOpCodeByte(kFsSegmentPrefix);
662 :
663 E : if (dst.code() == kRegisterEax && IsDisplacementOnly(src)) {
664 : // Special encoding for indirect displacement only to EAX.
665 E : instr.EmitOpCodeByte(0xA1);
666 E : instr.Emit32BitDisplacement(src.displacement());
667 E : } else {
668 E : instr.EmitOpCodeByte(0x8B);
669 E : instr.EmitOperand(dst.code(), src);
670 : }
671 E : }
672 :
673 E : void AssemblerImpl::mov_fs(const OperandImpl& dst, Register src) {
674 E : InstructionBuffer instr(this);
675 E : instr.EmitOpCodeByte(kFsSegmentPrefix);
676 :
677 E : if (src.code() == kRegisterEax && IsDisplacementOnly(dst)) {
678 : // Special encoding for indirect displacement only from EAX.
679 E : instr.EmitOpCodeByte(0xA3);
680 E : instr.Emit32BitDisplacement(dst.displacement());
681 E : } else {
682 E : instr.EmitOpCodeByte(0x89);
683 E : instr.EmitOperand(src.code(), dst);
684 : }
685 E : }
686 :
687 E : void AssemblerImpl::lea(Register dst, const OperandImpl& src) {
688 E : InstructionBuffer instr(this);
689 :
690 E : instr.EmitOpCodeByte(0x8D);
691 E : instr.EmitOperand(dst.code(), src);
692 E : }
693 :
694 E : void AssemblerImpl::push(Register src) {
695 E : InstructionBuffer instr(this);
696 :
697 E : instr.EmitOpCodeByte(0x50 | src.code());
698 E : }
699 :
700 E : void AssemblerImpl::push(const ImmediateImpl& src) {
701 E : DCHECK_EQ(kSize32Bit, src.size());
702 E : InstructionBuffer instr(this);
703 :
704 E : instr.EmitOpCodeByte(0x68);
705 E : instr.Emit32BitDisplacement(src);
706 E : }
707 :
708 E : void AssemblerImpl::push(const OperandImpl& dst) {
709 E : InstructionBuffer instr(this);
710 :
711 E : instr.EmitOpCodeByte(0xFF);
712 E : instr.EmitOperand(0x6, dst);
713 E : }
714 :
715 E : void AssemblerImpl::pop(Register src) {
716 E : InstructionBuffer instr(this);
717 :
718 E : instr.EmitOpCodeByte(0x58 | src.code());
719 E : }
720 :
721 E : void AssemblerImpl::pop(const OperandImpl& dst) {
722 E : InstructionBuffer instr(this);
723 :
724 E : instr.EmitOpCodeByte(0x8F);
725 E : instr.EmitOperand(0, dst);
726 E : }
727 :
728 E : void AssemblerImpl::pushfd() {
729 E : InstructionBuffer instr(this);
730 E : instr.EmitOpCodeByte(0x9C);
731 E : }
732 :
733 E : void AssemblerImpl::popfd() {
734 E : InstructionBuffer instr(this);
735 E : instr.EmitOpCodeByte(0x9D);
736 E : }
737 :
738 E : void AssemblerImpl::lahf() {
739 E : InstructionBuffer instr(this);
740 E : instr.EmitOpCodeByte(0x9F);
741 E : }
742 :
743 E : void AssemblerImpl::sahf() {
744 E : InstructionBuffer instr(this);
745 E : instr.EmitOpCodeByte(0x9E);
746 E : }
747 :
748 E : void AssemblerImpl::test_b(Register dst, Register src) {
749 E : InstructionBuffer instr(this);
750 E : instr.EmitArithmeticInstruction(0x84, dst, src);
751 E : }
752 :
753 E : void AssemblerImpl::test_b(Register dst, const ImmediateImpl& src) {
754 E : InstructionBuffer instr(this);
755 E : instr.EmitArithmeticInstructionToRegister8bit(0xA8, 0xF6, 0, dst, src);
756 E : }
757 :
758 E : void AssemblerImpl::test(Register dst, Register src) {
759 E : InstructionBuffer instr(this);
760 E : instr.EmitArithmeticInstruction(0x85, dst, src);
761 E : }
762 :
763 E : void AssemblerImpl::test(Register dst, const OperandImpl& src) {
764 : // Use commutative property for a smaller encoding.
765 E : test(src, dst);
766 E : }
767 :
768 E : void AssemblerImpl::test(const OperandImpl& dst, Register src) {
769 E : InstructionBuffer instr(this);
770 E : instr.EmitArithmeticInstruction(0x85, dst, src);
771 E : }
772 :
773 E : void AssemblerImpl::test(Register dst, const ImmediateImpl& src) {
774 E : if (src.size() == kSize8Bit) {
775 : // note: There is no encoding for a 8-bit immediate with 32-bit register.
776 E : test(dst, ImmediateImpl(src.value(), kSize32Bit));
777 E : } else {
778 E : InstructionBuffer instr(this);
779 E : instr.EmitArithmeticInstructionToRegister(0xA9, 0xF7, 0xF7, 0, dst, src);
780 E : }
781 E : }
782 :
783 E : void AssemblerImpl::test(const OperandImpl& dst, const ImmediateImpl& src) {
784 E : if (src.size() == kSize8Bit) {
785 : // note: There is no encoding for a 8-bit immediate with 32-bit register.
786 E : test(dst, ImmediateImpl(src.value(), kSize32Bit));
787 E : } else {
788 E : InstructionBuffer instr(this);
789 E : instr.EmitArithmeticInstructionToOperand(0xF7, 0xF7, 0, dst, src);
790 E : }
791 E : }
792 :
793 E : void AssemblerImpl::cmp_b(Register dst, Register src) {
794 E : InstructionBuffer instr(this);
795 E : instr.EmitArithmeticInstruction(0x3A, dst, src);
796 E : }
797 :
798 E : void AssemblerImpl::cmp_b(Register dst, const ImmediateImpl& src) {
799 E : InstructionBuffer instr(this);
800 E : instr.EmitArithmeticInstructionToRegister8bit(0x3C, 0x80, 7, dst, src);
801 E : }
802 :
803 E : void AssemblerImpl::cmp(Register dst, Register src) {
804 E : InstructionBuffer instr(this);
805 E : instr.EmitArithmeticInstruction(0x3B, dst, src);
806 E : }
807 :
808 E : void AssemblerImpl::cmp(Register dst, const OperandImpl& src) {
809 E : InstructionBuffer instr(this);
810 E : instr.EmitArithmeticInstruction(0x3B, dst, src);
811 E : }
812 :
813 E : void AssemblerImpl::cmp(const OperandImpl& dst, Register src) {
814 E : InstructionBuffer instr(this);
815 E : instr.EmitArithmeticInstruction(0x39, dst, src);
816 E : }
817 :
818 E : void AssemblerImpl::cmp(Register dst, const ImmediateImpl& src) {
819 E : InstructionBuffer instr(this);
820 E : instr.EmitArithmeticInstructionToRegister(0x3D, 0x83, 0x81, 7, dst, src);
821 E : }
822 :
823 E : void AssemblerImpl::cmp(const OperandImpl& dst, const ImmediateImpl& src) {
824 E : InstructionBuffer instr(this);
825 E : instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 7, dst, src);
826 E : }
827 :
828 E : void AssemblerImpl::add_b(Register dst, Register src) {
829 E : InstructionBuffer instr(this);
830 E : instr.EmitArithmeticInstruction(0x02, dst, src);
831 E : }
832 :
833 E : void AssemblerImpl::add_b(Register dst, const ImmediateImpl& src) {
834 E : InstructionBuffer instr(this);
835 E : instr.EmitArithmeticInstructionToRegister8bit(0x04, 0x80, 0, dst, src);
836 E : }
837 :
838 E : void AssemblerImpl::add(Register dst, Register src) {
839 E : InstructionBuffer instr(this);
840 E : instr.EmitArithmeticInstruction(0x03, dst, src);
841 E : }
842 :
843 E : void AssemblerImpl::add(Register dst, const OperandImpl& src) {
844 E : InstructionBuffer instr(this);
845 E : instr.EmitArithmeticInstruction(0x03, dst, src);
846 E : }
847 :
848 E : void AssemblerImpl::add(const OperandImpl& dst, Register src) {
849 E : InstructionBuffer instr(this);
850 E : instr.EmitArithmeticInstruction(0x01, dst, src);
851 E : }
852 :
853 E : void AssemblerImpl::add(Register dst, const ImmediateImpl& src) {
854 E : InstructionBuffer instr(this);
855 E : instr.EmitArithmeticInstructionToRegister(0x05, 0x83, 0x81, 0, dst, src);
856 E : }
857 :
858 E : void AssemblerImpl::add(const OperandImpl& dst, const ImmediateImpl& src) {
859 E : InstructionBuffer instr(this);
860 E : instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 0, dst, src);
861 E : }
862 :
863 E : void AssemblerImpl::sub_b(Register dst, Register src) {
864 E : InstructionBuffer instr(this);
865 E : instr.EmitArithmeticInstruction(0x2A, dst, src);
866 E : }
867 :
868 E : void AssemblerImpl::sub_b(Register dst, const ImmediateImpl& src) {
869 E : InstructionBuffer instr(this);
870 E : instr.EmitArithmeticInstructionToRegister8bit(0x2C, 0x80, 5, dst, src);
871 E : }
872 :
873 E : void AssemblerImpl::sub(Register dst, Register src) {
874 E : InstructionBuffer instr(this);
875 E : instr.EmitArithmeticInstruction(0x2B, dst, src);
876 E : }
877 :
878 E : void AssemblerImpl::sub(Register dst, const OperandImpl& src) {
879 E : InstructionBuffer instr(this);
880 E : instr.EmitArithmeticInstruction(0x2B, dst, src);
881 E : }
882 :
883 E : void AssemblerImpl::sub(const OperandImpl& dst, Register src) {
884 E : InstructionBuffer instr(this);
885 E : instr.EmitArithmeticInstruction(0x29, dst, src);
886 E : }
887 :
888 E : void AssemblerImpl::sub(Register dst, const ImmediateImpl& src) {
889 E : InstructionBuffer instr(this);
890 E : instr.EmitArithmeticInstructionToRegister(0x2D, 0x83, 0x81, 5, dst, src);
891 E : }
892 :
893 E : void AssemblerImpl::sub(const OperandImpl& dst, const ImmediateImpl& src) {
894 E : InstructionBuffer instr(this);
895 E : instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 5, dst, src);
896 E : }
897 :
898 E : void AssemblerImpl::shl(Register dst, const ImmediateImpl& src) {
899 E : InstructionBuffer instr(this);
900 E : if (src.value() == 1) {
901 E : instr.EmitOpCodeByte(0xD1);
902 E : instr.EmitModRMByte(Reg1, 4, dst.code());
903 E : } else {
904 E : instr.EmitOpCodeByte(0xC1);
905 E : instr.EmitModRMByte(Reg1, 4, dst.code());
906 E : instr.Emit8BitDisplacement(src);
907 : }
908 E : }
909 :
910 E : void AssemblerImpl::shr(Register dst, const ImmediateImpl& src) {
911 E : InstructionBuffer instr(this);
912 E : if (src.value() == 1) {
913 E : instr.EmitOpCodeByte(0xD1);
914 E : instr.EmitModRMByte(Reg1, 5, dst.code());
915 E : } else {
916 E : instr.EmitOpCodeByte(0xC1);
917 E : instr.EmitModRMByte(Reg1, 5, dst.code());
918 E : instr.Emit8BitDisplacement(src);
919 : }
920 E : }
921 :
922 E : void AssemblerImpl::Output(const InstructionBuffer& instr) {
923 : serializer_->AppendInstruction(location_,
924 : instr.buf(),
925 : instr.len(),
926 : instr.reference_offsets(),
927 : instr.references(),
928 E : instr.num_references());
929 :
930 E : location_ += instr.len();
931 E : }
932 :
933 : } // namespace core
|