1 : // Copyright 2014 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 : #ifndef SYZYGY_ASSM_ASSEMBLER_BASE_IMPL_H_
16 : #define SYZYGY_ASSM_ASSEMBLER_BASE_IMPL_H_
17 :
18 : #ifndef SYZYGY_ASSM_ASSEMBLER_BASE_H_
19 : #error Do not include this file directly.
20 : #endif // SYZYGY_ASSM_ASSEMBLER_BASE_H_
21 :
22 : #include <stdint.h>
23 : #include <limits>
24 :
25 : #include "syzygy/assm/const.h"
26 :
27 : namespace assm {
28 :
29 : // This class is used to buffer a single instruction during its creation.
30 : // TODO(siggi): Add a small state machine in debug mode to ensure the
31 : // correct order of invocation to opcode/modrm etc.
32 : // @note @p ReferenceType must either be a pointer type, or else have
33 : // a method bool IsValid() const.
34 : template <class ReferenceType>
35 : class AssemblerBase<ReferenceType>::InstructionBuffer {
36 : public:
37 : explicit InstructionBuffer(AssemblerBase* assm);
38 : ~InstructionBuffer();
39 :
40 : // @name Accessors.
41 : // @{
42 E : size_t len() const { return len_; }
43 E : const uint8* buf() const { return buf_; }
44 E : size_t num_reference_infos() const { return num_reference_infos_; }
45 E : const ReferenceInfo* reference_infos() const { return reference_infos_; }
46 : // @}
47 :
48 : // Emits operand size prefix (0x66) bytes.
49 : // @param count The number of operand size prefix bytes to emit.
50 : void EmitOperandSizePrefix(size_t count);
51 : // Emit an opcode byte.
52 : void EmitOpCodeByte(uint8 opcode);
53 : // Emit a ModR/M byte with an opcode extension.
54 : void EmitModRMByte(Mod mod, uint8 op, RegisterId reg1);
55 : // Emit a ModR/M byte with a destination register.
56 : void EmitModRMByte(Mod mod, RegisterId reg2, RegisterId reg1);
57 : // Emit a SIB byte.
58 : void EmitScaleIndexBaseByte(ScaleFactor scale,
59 : RegisterId index,
60 : RegisterId base);
61 : // Emit an operand.
62 : void EmitOperand(uint8 reg_op, const Operand& op);
63 :
64 : // Emit an 8-bit displacement, with optional reference info.
65 : void Emit8BitDisplacement(const Displacement& disp);
66 : // Emit an 8-bit immediate, with optional reference info.
67 : void Emit8BitImmediate(const Immediate& disp);
68 :
69 : // Emit a 32-bit displacement with optional reference info.
70 : void Emit32BitDisplacement(const Displacement& disp);
71 :
72 : // Emit a 32-bit immediate with optional reference info.
73 : void Emit32BitImmediate(const Immediate& disp);
74 :
75 : // Emit an 8-bit PC-relative value.
76 : void Emit8BitPCRelative(uint32 location, const Immediate& imm);
77 :
78 : // Emit a 32-bit PC-relative value.
79 : void Emit32BitPCRelative(uint32 location, const Immediate& imm);
80 :
81 : // Emit a 16-bit immediate value.
82 : void Emit16BitValue(uint16 value);
83 :
84 : // Emit an arithmetic instruction with various encoding.
85 : void EmitArithmeticInstruction(
86 : uint8 op, const Register& dst, const Register& src);
87 : void EmitArithmeticInstruction(
88 : uint8 op, const Register& dst, const Operand& src);
89 : void EmitArithmeticInstruction(
90 : uint8 op, const Operand& dst, const Register32& src);
91 : void EmitArithmeticInstructionToRegister32(uint8 op_eax, uint8 op_8,
92 : uint8 op_32, uint8 sub_op, const Register32& dst,
93 : const Immediate& src);
94 : void EmitArithmeticInstructionToRegister8(uint8 op_eax, uint8 op_8,
95 : uint8 sub_op, const Register8& dst, const Immediate& src);
96 : void EmitArithmeticInstructionToOperand(uint8 op_8, uint8 op_32,
97 : uint8 sub_op, const Operand& dst, const Immediate& src);
98 :
99 : // Emit an XCHG instruction.
100 : void EmitXchg(ValueSize size, RegisterId dst, RegisterId src);
101 :
102 : // Add reference at current location.
103 : void AddReference(const ReferenceType& reference,
104 : RegisterSize size,
105 : bool pc_relative);
106 :
107 : protected:
108 : void EmitByte(uint8 byte);
109 :
110 : AssemblerBase* asm_;
111 : size_t num_reference_infos_;
112 : ReferenceInfo reference_infos_[2];
113 : size_t len_;
114 : uint8 buf_[kMaxInstructionLength];
115 : };
116 :
117 : namespace details {
118 :
119 : template <class ReferenceType>
120 E : bool IsValidReference(const ReferenceType* ref) {
121 E : return ref != NULL;
122 E : }
123 :
124 : template <class ReferenceType>
125 E : bool IsValidReference(const ReferenceType& ref) {
126 E : return ref.IsValid();
127 E : }
128 :
129 : } // namespace details
130 :
131 : // Returns true if @p operand is a displacement only - e.g.
132 : // specifies neither a base, nor an index register.
133 : template <class ReferenceType>
134 E : bool IsDisplacementOnly(const OperandBase<ReferenceType>& operand) {
135 : return operand.displacement().size() != kSizeNone &&
136 : operand.base() == kRegisterNone &&
137 E : operand.index() == kRegisterNone;
138 E : }
139 :
140 : template <class ReferenceType>
141 : AssemblerBase<ReferenceType>::InstructionBuffer::InstructionBuffer(
142 E : AssemblerBase* assm) : asm_(assm), len_(0), num_reference_infos_(0) {
143 E : DCHECK(assm != NULL);
144 : #ifndef NDEBUG
145 : // Initialize the buffer in debug mode for easier debugging.
146 E : ::memset(buf_, 0xCC, sizeof(buf_));
147 : #endif
148 E : }
149 :
150 : template <class ReferenceType>
151 E : AssemblerBase<ReferenceType>::InstructionBuffer::~InstructionBuffer() {
152 E : asm_->Output(*this);
153 E : }
154 :
155 : template <class ReferenceType>
156 : void AssemblerBase<ReferenceType>::InstructionBuffer::EmitOperandSizePrefix(
157 E : size_t count) {
158 E : for (size_t i = 0; i < count; ++i)
159 E : EmitByte(kOperandSizePrefix);
160 E : }
161 :
162 : template <class ReferenceType>
163 : void AssemblerBase<ReferenceType>::InstructionBuffer::EmitOpCodeByte(
164 E : uint8 opcode) {
165 E : EmitByte(opcode);
166 E : }
167 :
168 : template <class ReferenceType>
169 : void AssemblerBase<ReferenceType>::InstructionBuffer::EmitModRMByte(
170 E : Mod mod, uint8 reg_op, RegisterId reg1) {
171 E : DCHECK_LE(reg_op, 8);
172 E : DCHECK_NE(kRegisterNone, reg1);
173 E : EmitByte((mod << 6) | (reg_op << 3) | Register::Code(reg1));
174 E : }
175 :
176 : template <class ReferenceType>
177 : void AssemblerBase<ReferenceType>::InstructionBuffer::EmitModRMByte(
178 E : Mod mod, RegisterId reg2, RegisterId reg1) {
179 E : DCHECK_NE(kRegisterNone, reg2);
180 E : DCHECK_NE(kRegisterNone, reg1);
181 E : EmitModRMByte(mod, Register::Code(reg2), reg1);
182 E : }
183 :
184 : template <class ReferenceType>
185 : void AssemblerBase<ReferenceType>::InstructionBuffer::EmitScaleIndexBaseByte(
186 E : ScaleFactor scale, RegisterId index, RegisterId base) {
187 E : DCHECK_NE(kRegisterNone, index);
188 E : DCHECK_NE(kRegisterNone, base);
189 :
190 E : EmitByte((scale << 6) | (Register::Code(index) << 3) | Register::Code(base));
191 E : }
192 :
193 : template <class ReferenceType>
194 : void AssemblerBase<ReferenceType>::InstructionBuffer::EmitOperand(
195 E : uint8 reg_op, const Operand& op) {
196 E : DCHECK_GE(8, reg_op);
197 :
198 : // The op operand can encode any one of the following things:
199 : // An indirect register access [EAX].
200 : // An indirect 32-bit displacement only [0xDEADBEEF].
201 : // An indirect base register + 32/8-bit displacement [EAX+0xDEADBEEF].
202 : // An indirect base + index register*scale [EAX+ECX*4].
203 : // An indirect base + index register*scale + 32/8-bit displacement
204 : // [EAX+ECX*4+0xDEADBEEF].
205 : // To complicate things, there are certain combinations that can't be encoded
206 : // canonically. The mode [ESP] or [ESP+disp] can never be encoded in a
207 : // ModR/M byte alone, as ESP in the ModR/M byte for any of the indirect modes
208 : // is overloaded to select the SIB representation.
209 : // Likewise [EBP] is overloaded to encode the [disp32] case.
210 : // See e.g. http://ref.x86asm.net/geek32-abc.html#modrm_byte_32 for a nice
211 : // overview table of the ModR/M byte encoding.
212 :
213 : // ESP can never be used as an index register on X86.
214 E : DCHECK_NE(kRegisterEsp, op.index());
215 :
216 : // Is there an index register?
217 E : if (op.index() == kRegisterNone) {
218 E : DCHECK_EQ(kTimes1, op.scale());
219 :
220 : // No index register, is there a base register?
221 E : if (op.base() == kRegisterNone) {
222 : // No base register, this is a displacement only.
223 E : DCHECK_NE(kSizeNone, op.displacement().size());
224 E : DCHECK_EQ(kTimes1, op.scale());
225 :
226 : // The [disp32] mode is encoded by overloading [EBP].
227 E : EmitModRMByte(kReg1Ind, reg_op, kRegisterEbp);
228 E : Emit32BitDisplacement(op.displacement());
229 E : } else {
230 : // Base register only, is it ESP?
231 E : if (op.base() == kRegisterEsp) {
232 : // The [ESP] and [ESP+disp] cases cannot be encoded without a SIB byte.
233 E : if (op.displacement().size() == kSizeNone) {
234 E : EmitModRMByte(kReg1Ind, reg_op, kRegisterEsp);
235 E : EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
236 E : } else if (op.displacement().size() == kSize8Bit) {
237 E : EmitModRMByte(kReg1ByteDisp, reg_op, kRegisterEsp);
238 E : EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
239 E : Emit8BitDisplacement(op.displacement());
240 E : } else {
241 E : DCHECK_EQ(kSize32Bit, op.displacement().size());
242 E : EmitModRMByte(kReg1WordDisp, reg_op, kRegisterEsp);
243 E : EmitScaleIndexBaseByte(kTimes1, kRegisterEsp, kRegisterEsp);
244 E : Emit32BitDisplacement(op.displacement());
245 E : }
246 E : } else if (op.displacement().size() == kSizeNone) {
247 E : if (op.base() == kRegisterEbp) {
248 : // The [EBP] case cannot be encoded canonically, there always must
249 : // be a (zero) displacement.
250 E : EmitModRMByte(kReg1ByteDisp, reg_op, op.base());
251 : Emit8BitDisplacement(
252 E : Displacement(0, kSize8Bit, ReferenceType()));
253 E : } else {
254 E : EmitModRMByte(kReg1Ind, reg_op, op.base());
255 E : }
256 E : } else if (op.displacement().size() == kSize8Bit) {
257 : // It's [base+disp8], or possibly [EBP].
258 E : EmitModRMByte(kReg1ByteDisp, reg_op, op.base());
259 E : Emit8BitDisplacement(op.displacement());
260 E : } else {
261 E : DCHECK_EQ(kSize32Bit, op.displacement().size());
262 : // It's [base+disp32].
263 E : EmitModRMByte(kReg1WordDisp, reg_op, op.base());
264 E : Emit32BitDisplacement(op.displacement());
265 : }
266 E : }
267 E : } else if (op.base() == kRegisterNone) {
268 : // Index, no base.
269 E : DCHECK_NE(kRegisterNone, op.index());
270 E : DCHECK_EQ(kRegisterNone, op.base());
271 :
272 : // This mode always has a 32 bit displacement.
273 E : EmitModRMByte(kReg1Ind, reg_op, kRegisterEsp);
274 E : EmitScaleIndexBaseByte(op.scale(), op.index(), kRegisterEbp);
275 E : Emit32BitDisplacement(op.displacement());
276 E : } else {
277 : // Index and base case.
278 E : DCHECK_NE(kRegisterNone, op.index());
279 E : DCHECK_NE(kRegisterNone, op.base());
280 :
281 : // Is there a displacement?
282 E : if (op.displacement().size() == kSizeNone) {
283 E : EmitModRMByte(kReg1Ind, reg_op, kRegisterEsp);
284 E : EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
285 E : } else if (op.displacement().size() == kSize8Bit) {
286 E : EmitModRMByte(kReg1ByteDisp, reg_op, kRegisterEsp);
287 E : EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
288 E : Emit8BitDisplacement(op.displacement());
289 E : } else {
290 E : DCHECK_EQ(kSize32Bit, op.displacement().size());
291 E : EmitModRMByte(kReg1WordDisp, reg_op, kRegisterEsp);
292 E : EmitScaleIndexBaseByte(op.scale(), op.index(), op.base());
293 E : Emit32BitDisplacement(op.displacement());
294 : }
295 : }
296 E : }
297 :
298 : template <class ReferenceType>
299 : void AssemblerBase<ReferenceType>::InstructionBuffer::Emit8BitDisplacement(
300 E : const Displacement& disp) {
301 E : DCHECK(disp.size() == kSize8Bit);
302 :
303 E : AddReference(disp.reference(), kSize8Bit, false);
304 :
305 E : EmitByte(disp.value());
306 E : }
307 :
308 : template <class ReferenceType>
309 : void AssemblerBase<ReferenceType>::InstructionBuffer::Emit8BitImmediate(
310 E : const Immediate& imm) {
311 E : DCHECK(imm.size() == kSize8Bit);
312 :
313 E : AddReference(imm.reference(), kSize8Bit, false);
314 :
315 E : EmitByte(imm.value());
316 E : }
317 :
318 : template <class ReferenceType>
319 : void AssemblerBase<ReferenceType>::InstructionBuffer::Emit32BitDisplacement(
320 E : const Displacement& disp) {
321 E : AddReference(disp.reference(), kSize32Bit, false);
322 :
323 E : uint32 value = disp.value();
324 E : EmitByte(value);
325 E : EmitByte(value >> 8);
326 E : EmitByte(value >> 16);
327 E : EmitByte(value >> 24);
328 E : }
329 :
330 : template <class ReferenceType>
331 : void AssemblerBase<ReferenceType>::InstructionBuffer::Emit32BitImmediate(
332 E : const Immediate& imm) {
333 E : AddReference(imm.reference(), kSize32Bit, false);
334 :
335 E : uint32 value = imm.value();
336 E : EmitByte(value);
337 E : EmitByte(value >> 8);
338 E : EmitByte(value >> 16);
339 E : EmitByte(value >> 24);
340 E : }
341 :
342 : template <class ReferenceType>
343 : void AssemblerBase<ReferenceType>::InstructionBuffer::Emit8BitPCRelative(
344 E : uint32 location, const Immediate& imm) {
345 E : DCHECK_EQ(kSize8Bit, imm.size());
346 :
347 E : AddReference(imm.reference(), kSize8Bit, true);
348 :
349 : // Turn the absolute imm into a imm relative to the address of
350 : // the end of the emitted constant.
351 E : int32 relative_value = imm.value() - (location + len_ + 1);
352 E : DCHECK_LE(std::numeric_limits<int8>::min(), relative_value);
353 E : DCHECK_GE(std::numeric_limits<int8>::max(), relative_value);
354 E : EmitByte(relative_value);
355 E : }
356 :
357 : template <class ReferenceType>
358 : void AssemblerBase<ReferenceType>::InstructionBuffer::Emit32BitPCRelative(
359 E : uint32 location, const Immediate& imm) {
360 E : DCHECK_EQ(kSize32Bit, imm.size());
361 :
362 E : AddReference(imm.reference(), kSize32Bit, true);
363 :
364 : // Turn the absolute imm into a imm relative to the address of
365 : // the end of the emitted constant.
366 E : uint32 relative_value = imm.value() - (location + len_ + 4);
367 E : EmitByte(relative_value);
368 E : EmitByte(relative_value >> 8);
369 E : EmitByte(relative_value >> 16);
370 E : EmitByte(relative_value >> 24);
371 E : }
372 :
373 : template <class ReferenceType>
374 : void AssemblerBase<ReferenceType>::InstructionBuffer::Emit16BitValue(
375 E : uint16 value) {
376 E : EmitByte(value);
377 E : EmitByte(value >> 8);
378 E : }
379 :
380 : template <class ReferenceType>
381 : void AssemblerBase<ReferenceType>::InstructionBuffer::
382 : EmitArithmeticInstruction(
383 E : uint8 op, const Register& dst, const Register& src) {
384 E : DCHECK_EQ(dst.size(), src.size());
385 E : EmitOpCodeByte(op);
386 E : EmitModRMByte(kReg1, dst.id(), src.id());
387 E : }
388 :
389 : template <class ReferenceType>
390 : void AssemblerBase<ReferenceType>::InstructionBuffer::
391 : EmitArithmeticInstruction(
392 E : uint8 op, const Register& dst, const Operand& src) {
393 E : EmitOpCodeByte(op);
394 E : EmitOperand(dst.code(), src);
395 E : }
396 :
397 : template <class ReferenceType>
398 : void AssemblerBase<ReferenceType>::InstructionBuffer::
399 : EmitArithmeticInstruction(
400 E : uint8 op, const Operand& dst, const Register32& src) {
401 E : EmitOpCodeByte(op);
402 E : EmitOperand(src.code(), dst);
403 E : }
404 :
405 : template <class ReferenceType>
406 : void AssemblerBase<ReferenceType>::InstructionBuffer::
407 : EmitArithmeticInstructionToRegister32(
408 : uint8 op_eax, uint8 op_8, uint8 op_32, uint8 sub_op,
409 E : const Register32& dst, const Immediate& src) {
410 E : if (dst.id() == kRegisterEax && src.size() == kSize32Bit) {
411 : // Special encoding for EAX.
412 E : EmitOpCodeByte(op_eax);
413 E : Emit32BitImmediate(src);
414 E : } else if (src.size() == kSize8Bit) {
415 E : EmitOpCodeByte(op_8);
416 E : EmitModRMByte(kReg1, sub_op, dst.id());
417 E : Emit8BitImmediate(src);
418 E : } else {
419 E : EmitOpCodeByte(op_32);
420 E : EmitModRMByte(kReg1, sub_op, dst.id());
421 E : Emit32BitImmediate(src);
422 : }
423 E : }
424 :
425 : template <class ReferenceType>
426 : void AssemblerBase<ReferenceType>::InstructionBuffer::
427 : EmitArithmeticInstructionToRegister8(
428 : uint8 op_eax, uint8 op_8, uint8 sub_op,
429 E : const Register8& dst, const Immediate& src) {
430 E : DCHECK(src.size() == kSize8Bit);
431 E : if (dst.code() == kAccumulatorCode) {
432 : // Special encoding for AL/AX/EAX.
433 E : EmitOpCodeByte(op_eax);
434 E : } else {
435 E : EmitOpCodeByte(op_8);
436 E : EmitModRMByte(kReg1, sub_op, dst.id());
437 : }
438 E : Emit8BitImmediate(src);
439 E : }
440 :
441 : template <class ReferenceType>
442 : void AssemblerBase<ReferenceType>::InstructionBuffer::
443 : EmitArithmeticInstructionToOperand(
444 : uint8 op_8, uint8 op_32, uint8 sub_op,
445 E : const Operand& dst, const Immediate& src) {
446 E : if (src.size() == kSize8Bit) {
447 E : EmitOpCodeByte(op_8);
448 E : EmitOperand(sub_op, dst);
449 E : Emit8BitImmediate(src);
450 E : } else {
451 E : EmitOpCodeByte(op_32);
452 E : EmitOperand(sub_op, dst);
453 E : Emit32BitImmediate(src);
454 : }
455 E : }
456 :
457 : template <class ReferenceType>
458 : void AssemblerBase<ReferenceType>::InstructionBuffer::EmitXchg(
459 E : ValueSize size, RegisterId dst, RegisterId src) {
460 : // Encoding for 8-bit registers.
461 E : if (size == kSize8Bit) {
462 E : EmitOpCodeByte(0x86);
463 E : EmitModRMByte(kReg1, src, dst);
464 E : } else {
465 : // 16-bit encodings are identical to 32-bit encodings, simply with
466 : // a operand size override prefix.
467 E : if (size == kSize16Bit)
468 E : EmitOperandSizePrefix(1);
469 :
470 : // If either register is EAX/AX there's a 1-byte encoding.
471 E : RegisterCode dst_code = Register::Code(dst);
472 E : RegisterCode src_code = Register::Code(src);
473 E : if (src_code == kAccumulatorCode || dst_code == kAccumulatorCode) {
474 E : RegisterCode other_register = dst_code;
475 E : if (dst_code == kAccumulatorCode)
476 E : other_register = src_code;
477 E : EmitOpCodeByte(0x90 | other_register);
478 E : } else {
479 : // Otherwise we use a 2-byte encoding with a ModR/M byte.
480 E : EmitOpCodeByte(0x87);
481 E : EmitModRMByte(kReg1, src, dst);
482 : }
483 : }
484 E : }
485 :
486 : template <class ReferenceType>
487 : void AssemblerBase<ReferenceType>::InstructionBuffer::AddReference(
488 E : const ReferenceType& reference, RegisterSize size, bool pc_relative) {
489 E : if (!details::IsValidReference(reference))
490 E : return;
491 :
492 E : DCHECK_GT(arraysize(reference_infos_), num_reference_infos_);
493 E : ReferenceInfo& info = reference_infos_[num_reference_infos_];
494 E : info.offset = len();
495 E : info.reference = reference;
496 E : info.size = size;
497 E : info.pc_relative = pc_relative;
498 E : ++num_reference_infos_;
499 E : }
500 :
501 : template <class ReferenceType>
502 E : void AssemblerBase<ReferenceType>::InstructionBuffer::EmitByte(uint8 byte) {
503 E : DCHECK_GT(sizeof(buf_), len_);
504 E : buf_[len_++] = byte;
505 E : }
506 :
507 : template <class ReferenceType>
508 : AssemblerBase<ReferenceType>::AssemblerBase(
509 : uint32 location, InstructionSerializer* serializer) :
510 E : location_(location), serializer_(serializer) {
511 E : DCHECK(serializer != NULL);
512 E : }
513 :
514 : template <class ReferenceType>
515 E : void AssemblerBase<ReferenceType>::nop(size_t size) {
516 : // These are NOP sequences suggested by the Intel Architecture
517 : // Software Developer's manual, page 4-8.
518 : //
519 : // 1: 0x90
520 : // 2: 0x66 0x90
521 : // 3: 0x66 0x66 0x90
522 : // 4: 0x0F 0x1F 0x40 0x00
523 : // 5: 0x0F 0x1F 0x44 0x00 0x00
524 : // 6: 0x66 0x0F 0x1F 0x44 0x00 0x00
525 : // 7: 0x0F 0x1F 0x80 0x00 0x00 0x00 0x00
526 : // 8: 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
527 : // 9: 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
528 : // 10: 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
529 : // 11: 0x66 0x66 0x66 0x0F 0x1F 0x84 0x00 0x00 0x00 0x00 0x00
530 : //
531 : // It is further suggested not to put consecutive XCHG NOPs with prefixes,
532 : // but rather to mix them with 0x1F NOPs or XCHG NOPs without prefixes. The
533 : // basic nops without any operand prefixes (0x66) have been implemented as
534 : // helper functions nop1, nop4, nop5, nop7 and nop8. This implementation of
535 : // NOP sequences has been inspired by Oracle's HotSpot JVM JIT assembler
536 : // (http://openjdk.java.net/groups/hotspot/).
537 :
538 : // Eat up the NOPs in chunks of 15 bytes.
539 E : while (size >= 15) {
540 E : nop8(3); // 11-byte non-XCHG NOP.
541 E : nop1(3); // 4-byte prefixed XCHG NOP.
542 E : size -= 15;
543 E : }
544 E : DCHECK_GE(14u, size);
545 :
546 : // Handle the last chunk of bytes.
547 E : size_t prefix_count = 0;
548 E : switch (size) {
549 : // Handle 12- to 14-byte NOPs.
550 : case 14:
551 E : ++prefix_count;
552 : case 13:
553 E : ++prefix_count;
554 : case 12:
555 E : nop8(prefix_count); // 8- to 10-byte non-XCHG NOP.
556 E : nop1(3); // 4-byte prefixed XCHG NOP.
557 E : return;
558 :
559 : // Handle 8- to 11-byte NOPs.
560 : case 11:
561 E : ++prefix_count;
562 : case 10:
563 E : ++prefix_count;
564 : case 9:
565 E : ++prefix_count;
566 : case 8:
567 E : nop8(prefix_count); // 8- to 11-byte non-XCHG NOP.
568 E : return;
569 :
570 : // Handle 7-byte NOPs.
571 : case 7:
572 E : nop7(prefix_count); // 7-byte non-XCHG NOP.
573 E : return;
574 :
575 : // Handle 5- to 6-byte NOPs.
576 : case 6:
577 E : ++prefix_count;
578 : case 5:
579 E : nop5(prefix_count); // 5- to 6-byte non-XCHG NOP.
580 E : return;
581 :
582 : // Handle 4-byte NOPs.
583 : case 4:
584 E : nop4(prefix_count); // 4-byte non-XCHG NOP.
585 E : return;
586 :
587 : // Handle 1- to 3-byte NOPs.
588 : case 3:
589 E : ++prefix_count;
590 : case 2:
591 E : ++prefix_count;
592 : case 1:
593 E : nop1(prefix_count); // 1- to 3-byte XCHG NOP.
594 : return;
595 :
596 : case 0:
597 : // Nothing to do!
598 : break;
599 : }
600 : return;
601 E : }
602 :
603 : template <class ReferenceType>
604 E : void AssemblerBase<ReferenceType>::call(const Immediate& dst) {
605 E : InstructionBuffer instr(this);
606 :
607 E : instr.EmitOpCodeByte(0xE8);
608 E : instr.Emit32BitPCRelative(location_, dst);
609 E : }
610 :
611 : template <class ReferenceType>
612 E : void AssemblerBase<ReferenceType>::call(const Operand& dst) {
613 E : InstructionBuffer instr(this);
614 :
615 E : instr.EmitOpCodeByte(0xFF);
616 E : instr.EmitOperand(0x2, dst);
617 E : }
618 :
619 : template <class ReferenceType>
620 E : void AssemblerBase<ReferenceType>::j(ConditionCode cc, const Immediate& dst) {
621 E : DCHECK_LE(kMinConditionCode, cc);
622 E : DCHECK_GE(kMaxConditionCode, cc);
623 :
624 E : InstructionBuffer instr(this);
625 E : if (dst.size() == kSize32Bit) {
626 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
627 E : instr.EmitOpCodeByte(0x80 | cc);
628 E : instr.Emit32BitPCRelative(location_, dst);
629 E : } else {
630 E : DCHECK_EQ(kSize8Bit, dst.size());
631 E : instr.EmitOpCodeByte(0x70 | cc);
632 E : instr.Emit8BitPCRelative(location_, dst);
633 : }
634 E : }
635 :
636 : template <class ReferenceType>
637 : bool AssemblerBase<ReferenceType>::j(ConditionCode cc,
638 : Label* label,
639 E : RegisterSize size) {
640 E : DCHECK(label != NULL);
641 E : DCHECK_LE(kMinConditionCode, cc);
642 E : DCHECK_GE(kMaxConditionCode, cc);
643 E : DCHECK(size == kSize8Bit || size == kSize32Bit || size == kSizeNone);
644 :
645 E : Immediate dst;
646 E : if (label->bound()) {
647 : // Check whether the short reach is in range.
648 : // TODO(siggi): Utility function for this.
649 E : int32 offs = label->location() - (location() + kShortBranchSize);
650 : if (offs > std::numeric_limits<int8>::max() ||
651 E : offs < std::numeric_limits<int8>::min()) {
652 : // Short is out of range, fail if that's requested.
653 E : if (size == kSize8Bit)
654 E : return false;
655 : // Short is out of range, go long.
656 E : size = kSize32Bit;
657 E : } else {
658 : // Short is in range, pick short if there's a choice.
659 E : if (size == kSizeNone)
660 E : size = kSize8Bit;
661 : }
662 :
663 E : dst = Immediate(label->location(), size);
664 E : } else {
665 E : if (size == kSizeNone)
666 E : size = kSize32Bit;
667 :
668 E : size_t opcode_size = kShortBranchOpcodeSize;
669 E : if (size == kSize32Bit)
670 E : opcode_size = kLongBranchOpcodeSize;
671 :
672 : // The label is not yet bound, declare our use.
673 E : label->Use(location() + opcode_size, size);
674 : // Point the destination to our own instruction as a debugging aid.
675 E : dst = Immediate(location(), size);
676 : }
677 :
678 E : j(cc, dst);
679 :
680 E : return true;
681 E : }
682 :
683 : template <class ReferenceType>
684 E : bool AssemblerBase<ReferenceType>::j(ConditionCode cc, Label* label) {
685 E : return j(cc, label, kSizeNone);
686 E : }
687 :
688 : template <class ReferenceType>
689 E : void AssemblerBase<ReferenceType>::jecxz(const Immediate& dst) {
690 E : DCHECK_EQ(kSize8Bit, dst.size());
691 E : InstructionBuffer instr(this);
692 E : instr.EmitOpCodeByte(0xE3);
693 E : instr.Emit8BitPCRelative(location_, dst);
694 E : }
695 :
696 : template <class ReferenceType>
697 E : void AssemblerBase<ReferenceType>::jmp(const Immediate& dst) {
698 E : InstructionBuffer instr(this);
699 :
700 E : if (dst.size() == kSize32Bit) {
701 E : instr.EmitOpCodeByte(0xE9);
702 E : instr.Emit32BitPCRelative(location_, dst);
703 E : } else {
704 E : DCHECK_EQ(kSize8Bit, dst.size());
705 E : instr.EmitOpCodeByte(0xEB);
706 E : instr.Emit8BitPCRelative(location_, dst);
707 : }
708 E : }
709 :
710 : template <class ReferenceType>
711 E : void AssemblerBase<ReferenceType>::jmp(const Operand& dst) {
712 E : InstructionBuffer instr(this);
713 :
714 E : instr.EmitOpCodeByte(0xFF);
715 E : instr.EmitOperand(0x4, dst);
716 E : }
717 :
718 : template <class ReferenceType>
719 E : void AssemblerBase<ReferenceType>::jmp(const Register32& dst) {
720 E : InstructionBuffer instr(this);
721 :
722 E : instr.EmitOpCodeByte(0xFF);
723 E : instr.EmitOpCodeByte(0xE0 | dst.code());
724 E : }
725 :
726 : template <class ReferenceType>
727 E : void AssemblerBase<ReferenceType>::l(LoopCode lc, const Immediate& dst) {
728 E : DCHECK_EQ(kSize8Bit, dst.size());
729 E : DCHECK_LE(0, lc);
730 E : DCHECK_GE(2, lc);
731 E : InstructionBuffer instr(this);
732 :
733 E : instr.EmitOpCodeByte(0xE0 | lc);
734 E : instr.Emit8BitPCRelative(location_, dst);
735 E : }
736 :
737 : template <class ReferenceType>
738 E : void AssemblerBase<ReferenceType>::ret() {
739 E : InstructionBuffer instr(this);
740 :
741 E : instr.EmitOpCodeByte(0xC3);
742 E : }
743 :
744 : template <class ReferenceType>
745 E : void AssemblerBase<ReferenceType>::ret(uint16 n) {
746 E : InstructionBuffer instr(this);
747 :
748 E : instr.EmitOpCodeByte(0xC2);
749 E : instr.Emit16BitValue(n);
750 E : }
751 :
752 : template <class ReferenceType>
753 : void AssemblerBase<ReferenceType>::set(ConditionCode cc,
754 E : const Register32& dst) {
755 E : DCHECK_LE(kMinConditionCode, cc);
756 E : DCHECK_GE(kMaxConditionCode, cc);
757 :
758 E : InstructionBuffer instr(this);
759 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
760 E : instr.EmitOpCodeByte(0x90 | cc);
761 :
762 : // AMD64 Architecture Programmers Manual Volume 3: General-Purpose and System
763 : // Instructions: The reg field in the ModR/M byte is unused.
764 E : const Register32& unused = eax;
765 E : instr.EmitModRMByte(kReg1, unused.id(), dst.id());
766 E : }
767 :
768 : template <class ReferenceType>
769 : void AssemblerBase<ReferenceType>::mov_b(const Operand& dst,
770 E : const Immediate& src) {
771 E : InstructionBuffer instr(this);
772 :
773 E : instr.EmitOpCodeByte(0xC6);
774 E : instr.EmitOperand(0, dst);
775 E : instr.Emit8BitImmediate(src);
776 E : }
777 :
778 : template <class ReferenceType>
779 : void AssemblerBase<ReferenceType>::movzx_b(const Register32& dst,
780 E : const Operand& src) {
781 E : InstructionBuffer instr(this);
782 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
783 E : instr.EmitOpCodeByte(0xB6);
784 E : instr.EmitOperand(dst.code(), src);
785 E : }
786 :
787 : template <class ReferenceType>
788 : void AssemblerBase<ReferenceType>::mov(const Register32& dst,
789 E : const Register32& src) {
790 E : InstructionBuffer instr(this);
791 :
792 E : instr.EmitOpCodeByte(0x8B);
793 E : instr.EmitModRMByte(kReg1, dst.id(), src.id());
794 E : }
795 :
796 : template <class ReferenceType>
797 : void AssemblerBase<ReferenceType>::mov(const Register32& dst,
798 E : const Operand& src) {
799 E : InstructionBuffer instr(this);
800 :
801 E : if (dst.id() == kRegisterEax && IsDisplacementOnly(src)) {
802 : // Special encoding for indirect displacement only to EAX.
803 E : instr.EmitOpCodeByte(0xA1);
804 E : instr.Emit32BitDisplacement(src.displacement());
805 E : } else {
806 E : instr.EmitOpCodeByte(0x8B);
807 E : instr.EmitOperand(dst.code(), src);
808 : }
809 E : }
810 :
811 : template <class ReferenceType>
812 : void AssemblerBase<ReferenceType>::mov(const Operand& dst,
813 E : const Register32& src) {
814 E : InstructionBuffer instr(this);
815 :
816 E : if (src.id() == kRegisterEax && IsDisplacementOnly(dst)) {
817 : // Special encoding for indirect displacement only from EAX.
818 E : instr.EmitOpCodeByte(0xA3);
819 E : instr.Emit32BitDisplacement(dst.displacement());
820 E : } else {
821 E : instr.EmitOpCodeByte(0x89);
822 E : instr.EmitOperand(src.code(), dst);
823 : }
824 E : }
825 :
826 : template <class ReferenceType>
827 : void AssemblerBase<ReferenceType>::mov(const Register32& dst,
828 E : const Immediate& src) {
829 E : DCHECK_NE(kSizeNone, src.size());
830 E : InstructionBuffer instr(this);
831 :
832 E : instr.EmitOpCodeByte(0xB8 | dst.code());
833 E : instr.Emit32BitImmediate(src);
834 E : }
835 :
836 : template <class ReferenceType>
837 : void AssemblerBase<ReferenceType>::mov(const Operand& dst,
838 E : const Immediate& src) {
839 E : InstructionBuffer instr(this);
840 :
841 E : instr.EmitOpCodeByte(0xC7);
842 E : instr.EmitOperand(0, dst);
843 E : instr.Emit32BitImmediate(src);
844 E : }
845 :
846 : template <class ReferenceType>
847 : void AssemblerBase<ReferenceType>::mov_fs(const Register32& dst,
848 E : const Operand& src) {
849 E : InstructionBuffer instr(this);
850 E : instr.EmitOpCodeByte(kFsSegmentPrefix);
851 :
852 E : if (dst.id() == kRegisterEax && IsDisplacementOnly(src)) {
853 : // Special encoding for indirect displacement only to EAX.
854 i : instr.EmitOpCodeByte(0xA1);
855 i : instr.Emit32BitDisplacement(src.displacement());
856 i : } else {
857 E : instr.EmitOpCodeByte(0x8B);
858 E : instr.EmitOperand(dst.code(), src);
859 : }
860 E : }
861 :
862 : template <class ReferenceType>
863 : void AssemblerBase<ReferenceType>::mov_fs(const Operand& dst,
864 E : const Register32& src) {
865 E : InstructionBuffer instr(this);
866 E : instr.EmitOpCodeByte(kFsSegmentPrefix);
867 :
868 E : if (src.id() == kRegisterEax && IsDisplacementOnly(dst)) {
869 : // Special encoding for indirect displacement only from EAX.
870 i : instr.EmitOpCodeByte(0xA3);
871 i : instr.Emit32BitDisplacement(dst.displacement());
872 i : } else {
873 E : instr.EmitOpCodeByte(0x89);
874 E : instr.EmitOperand(src.code(), dst);
875 : }
876 E : }
877 :
878 : template <class ReferenceType>
879 : void AssemblerBase<ReferenceType>::lea(const Register32& dst,
880 E : const Operand& src) {
881 E : InstructionBuffer instr(this);
882 :
883 E : instr.EmitOpCodeByte(0x8D);
884 E : instr.EmitOperand(dst.code(), src);
885 E : }
886 :
887 : template <class ReferenceType>
888 E : void AssemblerBase<ReferenceType>::push(const Register32& src) {
889 E : InstructionBuffer instr(this);
890 :
891 E : instr.EmitOpCodeByte(0x50 | src.code());
892 E : }
893 :
894 : template <class ReferenceType>
895 E : void AssemblerBase<ReferenceType>::push(const Immediate& src) {
896 E : DCHECK_EQ(kSize32Bit, src.size());
897 E : InstructionBuffer instr(this);
898 :
899 E : instr.EmitOpCodeByte(0x68);
900 E : instr.Emit32BitImmediate(src);
901 E : }
902 :
903 : template <class ReferenceType>
904 E : void AssemblerBase<ReferenceType>::push(const Operand& dst) {
905 E : InstructionBuffer instr(this);
906 :
907 E : instr.EmitOpCodeByte(0xFF);
908 E : instr.EmitOperand(0x6, dst);
909 E : }
910 :
911 : template <class ReferenceType>
912 E : void AssemblerBase<ReferenceType>::pushad() {
913 E : InstructionBuffer instr(this);
914 :
915 E : instr.EmitOpCodeByte(0x60);
916 E : }
917 :
918 : template <class ReferenceType>
919 E : void AssemblerBase<ReferenceType>::pop(const Register32& src) {
920 E : InstructionBuffer instr(this);
921 :
922 E : instr.EmitOpCodeByte(0x58 | src.code());
923 E : }
924 :
925 : template <class ReferenceType>
926 E : void AssemblerBase<ReferenceType>::pop(const Operand& dst) {
927 E : InstructionBuffer instr(this);
928 :
929 E : instr.EmitOpCodeByte(0x8F);
930 E : instr.EmitOperand(0, dst);
931 E : }
932 :
933 : template <class ReferenceType>
934 E : void AssemblerBase<ReferenceType>::popad() {
935 E : InstructionBuffer instr(this);
936 :
937 E : instr.EmitOpCodeByte(0x61);
938 E : }
939 :
940 : template <class ReferenceType>
941 E : void AssemblerBase<ReferenceType>::pushfd() {
942 E : InstructionBuffer instr(this);
943 E : instr.EmitOpCodeByte(0x9C);
944 E : }
945 :
946 : template <class ReferenceType>
947 E : void AssemblerBase<ReferenceType>::popfd() {
948 E : InstructionBuffer instr(this);
949 E : instr.EmitOpCodeByte(0x9D);
950 E : }
951 :
952 : template <class ReferenceType>
953 E : void AssemblerBase<ReferenceType>::lahf() {
954 E : InstructionBuffer instr(this);
955 E : instr.EmitOpCodeByte(0x9F);
956 E : }
957 :
958 : template <class ReferenceType>
959 E : void AssemblerBase<ReferenceType>::sahf() {
960 E : InstructionBuffer instr(this);
961 E : instr.EmitOpCodeByte(0x9E);
962 E : }
963 :
964 : template <class ReferenceType>
965 : void AssemblerBase<ReferenceType>::test(const Register8& dst,
966 E : const Register8& src) {
967 E : InstructionBuffer instr(this);
968 E : instr.EmitArithmeticInstruction(0x84, dst, src);
969 E : }
970 :
971 : template <class ReferenceType>
972 : void AssemblerBase<ReferenceType>::test(const Register8& dst,
973 E : const Immediate& src) {
974 E : InstructionBuffer instr(this);
975 E : instr.EmitArithmeticInstructionToRegister8(0xA8, 0xF6, 0, dst, src);
976 E : }
977 :
978 : template <class ReferenceType>
979 : void AssemblerBase<ReferenceType>::test(const Register32& dst,
980 E : const Register32& src) {
981 E : InstructionBuffer instr(this);
982 E : instr.EmitArithmeticInstruction(0x85, dst, src);
983 E : }
984 :
985 : template <class ReferenceType>
986 : void AssemblerBase<ReferenceType>::test(const Register32& dst,
987 E : const Operand& src) {
988 : // Use commutative property for a smaller encoding.
989 E : test(src, dst);
990 E : }
991 :
992 : template <class ReferenceType>
993 : void AssemblerBase<ReferenceType>::test(const Operand& dst,
994 E : const Register32& src) {
995 E : InstructionBuffer instr(this);
996 E : instr.EmitArithmeticInstruction(0x85, dst, src);
997 E : }
998 :
999 : template <class ReferenceType>
1000 : void AssemblerBase<ReferenceType>::test(const Register32& dst,
1001 E : const Immediate& src) {
1002 E : if (src.size() == kSize8Bit) {
1003 : // note: There is no encoding for a 8-bit immediate with 32-bit register.
1004 E : test(dst, Immediate(src.value(), kSize32Bit));
1005 E : } else {
1006 E : InstructionBuffer instr(this);
1007 E : instr.EmitArithmeticInstructionToRegister32(0xA9, 0xF7, 0xF7, 0, dst, src);
1008 E : }
1009 E : }
1010 :
1011 : template <class ReferenceType>
1012 : void AssemblerBase<ReferenceType>::test(const Operand& dst,
1013 E : const Immediate& src) {
1014 E : if (src.size() == kSize8Bit) {
1015 : // note: There is no encoding for a 8-bit immediate with 32-bit register.
1016 E : test(dst, Immediate(src.value(), kSize32Bit));
1017 E : } else {
1018 E : InstructionBuffer instr(this);
1019 E : instr.EmitArithmeticInstructionToOperand(0xF7, 0xF7, 0, dst, src);
1020 E : }
1021 E : }
1022 :
1023 : template <class ReferenceType>
1024 : void AssemblerBase<ReferenceType>::cmp(const Register8& dst,
1025 E : const Register8& src) {
1026 E : InstructionBuffer instr(this);
1027 E : instr.EmitArithmeticInstruction(0x3A, dst, src);
1028 E : }
1029 :
1030 : template <class ReferenceType>
1031 : void AssemblerBase<ReferenceType>::cmp(const Register8& dst,
1032 E : const Immediate& src) {
1033 E : InstructionBuffer instr(this);
1034 E : instr.EmitArithmeticInstructionToRegister8(0x3C, 0x80, 7, dst, src);
1035 E : }
1036 :
1037 : template <class ReferenceType>
1038 : void AssemblerBase<ReferenceType>::cmp(const Register32& dst,
1039 E : const Register32& src) {
1040 E : InstructionBuffer instr(this);
1041 E : instr.EmitArithmeticInstruction(0x3B, dst, src);
1042 E : }
1043 :
1044 : template <class ReferenceType>
1045 : void AssemblerBase<ReferenceType>::cmp(const Register32& dst,
1046 E : const Operand& src) {
1047 E : InstructionBuffer instr(this);
1048 E : instr.EmitArithmeticInstruction(0x3B, dst, src);
1049 E : }
1050 :
1051 : template <class ReferenceType>
1052 : void AssemblerBase<ReferenceType>::cmp(const Operand& dst,
1053 E : const Register32& src) {
1054 E : InstructionBuffer instr(this);
1055 E : instr.EmitArithmeticInstruction(0x39, dst, src);
1056 E : }
1057 :
1058 : template <class ReferenceType>
1059 : void AssemblerBase<ReferenceType>::cmp(const Register32& dst,
1060 E : const Immediate& src) {
1061 E : InstructionBuffer instr(this);
1062 E : instr.EmitArithmeticInstructionToRegister32(0x3D, 0x83, 0x81, 7, dst, src);
1063 E : }
1064 :
1065 : template <class ReferenceType>
1066 : void AssemblerBase<ReferenceType>::cmp(const Operand& dst,
1067 E : const Immediate& src) {
1068 E : InstructionBuffer instr(this);
1069 E : instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 7, dst, src);
1070 E : }
1071 :
1072 : template <class ReferenceType>
1073 : void AssemblerBase<ReferenceType>::add(const Register8& dst,
1074 E : const Register8& src) {
1075 E : InstructionBuffer instr(this);
1076 E : instr.EmitArithmeticInstruction(0x02, dst, src);
1077 E : }
1078 :
1079 : template <class ReferenceType>
1080 : void AssemblerBase<ReferenceType>::add(const Register8& dst,
1081 E : const Immediate& src) {
1082 E : InstructionBuffer instr(this);
1083 E : instr.EmitArithmeticInstructionToRegister8(0x04, 0x80, 0, dst, src);
1084 E : }
1085 :
1086 : template <class ReferenceType>
1087 : void AssemblerBase<ReferenceType>::add(const Register32& dst,
1088 E : const Register32& src) {
1089 E : InstructionBuffer instr(this);
1090 E : instr.EmitArithmeticInstruction(0x03, dst, src);
1091 E : }
1092 :
1093 : template <class ReferenceType>
1094 : void AssemblerBase<ReferenceType>::add(const Register32& dst,
1095 E : const Operand& src) {
1096 E : InstructionBuffer instr(this);
1097 E : instr.EmitArithmeticInstruction(0x03, dst, src);
1098 E : }
1099 :
1100 : template <class ReferenceType>
1101 : void AssemblerBase<ReferenceType>::add(const Operand& dst,
1102 E : const Register32& src) {
1103 E : InstructionBuffer instr(this);
1104 E : instr.EmitArithmeticInstruction(0x01, dst, src);
1105 E : }
1106 :
1107 : template <class ReferenceType>
1108 : void AssemblerBase<ReferenceType>::add(const Register32& dst,
1109 E : const Immediate& src) {
1110 E : InstructionBuffer instr(this);
1111 E : instr.EmitArithmeticInstructionToRegister32(0x05, 0x83, 0x81, 0, dst, src);
1112 E : }
1113 :
1114 : template <class ReferenceType>
1115 : void AssemblerBase<ReferenceType>::add(const Operand& dst,
1116 E : const Immediate& src) {
1117 E : InstructionBuffer instr(this);
1118 E : instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 0, dst, src);
1119 E : }
1120 :
1121 : template <class ReferenceType>
1122 : void AssemblerBase<ReferenceType>::sub(const Register8& dst,
1123 E : const Register8& src) {
1124 E : InstructionBuffer instr(this);
1125 E : instr.EmitArithmeticInstruction(0x2A, dst, src);
1126 E : }
1127 :
1128 : template <class ReferenceType>
1129 : void AssemblerBase<ReferenceType>::sub(const Register8& dst,
1130 E : const Immediate& src) {
1131 E : InstructionBuffer instr(this);
1132 E : instr.EmitArithmeticInstructionToRegister8(0x2C, 0x80, 5, dst, src);
1133 E : }
1134 :
1135 : template <class ReferenceType>
1136 : void AssemblerBase<ReferenceType>::sub(const Register32& dst,
1137 E : const Register32& src) {
1138 E : InstructionBuffer instr(this);
1139 E : instr.EmitArithmeticInstruction(0x2B, dst, src);
1140 E : }
1141 :
1142 : template <class ReferenceType>
1143 : void AssemblerBase<ReferenceType>::sub(const Register32& dst,
1144 E : const Operand& src) {
1145 E : InstructionBuffer instr(this);
1146 E : instr.EmitArithmeticInstruction(0x2B, dst, src);
1147 E : }
1148 :
1149 : template <class ReferenceType>
1150 : void AssemblerBase<ReferenceType>::sub(const Operand& dst,
1151 E : const Register32& src) {
1152 E : InstructionBuffer instr(this);
1153 E : instr.EmitArithmeticInstruction(0x29, dst, src);
1154 E : }
1155 :
1156 : template <class ReferenceType>
1157 : void AssemblerBase<ReferenceType>::sub(const Register32& dst,
1158 E : const Immediate& src) {
1159 E : InstructionBuffer instr(this);
1160 E : instr.EmitArithmeticInstructionToRegister32(0x2D, 0x83, 0x81, 5, dst, src);
1161 E : }
1162 :
1163 : template <class ReferenceType>
1164 : void AssemblerBase<ReferenceType>::sub(const Operand& dst,
1165 E : const Immediate& src) {
1166 E : InstructionBuffer instr(this);
1167 E : instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 5, dst, src);
1168 E : }
1169 :
1170 : template <class ReferenceType>
1171 : void AssemblerBase<ReferenceType>::and(const Register8& dst,
1172 : const Register8& src) {
1173 : InstructionBuffer instr(this);
1174 : instr.EmitArithmeticInstruction(0x20, src, dst);
1175 : }
1176 :
1177 : template <class ReferenceType>
1178 : void AssemblerBase<ReferenceType>::and(const Register8& dst,
1179 : const Immediate& src) {
1180 : InstructionBuffer instr(this);
1181 : instr.EmitArithmeticInstructionToRegister8(0x24, 0x80, 4, dst, src);
1182 : }
1183 :
1184 : template <class ReferenceType>
1185 : void AssemblerBase<ReferenceType>::and(const Register32& dst,
1186 E : const Register32& src) {
1187 E : InstructionBuffer instr(this);
1188 E : instr.EmitArithmeticInstruction(0x21, src, dst);
1189 E : }
1190 :
1191 : template <class ReferenceType>
1192 : void AssemblerBase<ReferenceType>::and(const Register32& dst,
1193 E : const Operand& src) {
1194 E : InstructionBuffer instr(this);
1195 E : instr.EmitArithmeticInstruction(0x23, dst, src);
1196 E : }
1197 :
1198 : template <class ReferenceType>
1199 : void AssemblerBase<ReferenceType>::and(const Operand& dst,
1200 E : const Register32& src) {
1201 E : InstructionBuffer instr(this);
1202 E : instr.EmitArithmeticInstruction(0x21, dst, src);
1203 E : }
1204 :
1205 : template <class ReferenceType>
1206 : void AssemblerBase<ReferenceType>::and(const Register32& dst,
1207 E : const Immediate& src) {
1208 E : InstructionBuffer instr(this);
1209 E : instr.EmitArithmeticInstructionToRegister32(0x25, 0x83, 0x81, 4, dst, src);
1210 E : }
1211 :
1212 : template <class ReferenceType>
1213 : void AssemblerBase<ReferenceType>::and(const Operand& dst,
1214 E : const Immediate& src) {
1215 E : InstructionBuffer instr(this);
1216 E : instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 4, dst, src);
1217 E : }
1218 :
1219 : template <class ReferenceType>
1220 : void AssemblerBase<ReferenceType>::xor(const Register8& dst,
1221 : const Register8& src) {
1222 : InstructionBuffer instr(this);
1223 : instr.EmitArithmeticInstruction(0x30, src, dst);
1224 : }
1225 :
1226 : template <class ReferenceType>
1227 : void AssemblerBase<ReferenceType>::xor(const Register8& dst,
1228 : const Immediate& src) {
1229 : InstructionBuffer instr(this);
1230 : instr.EmitArithmeticInstructionToRegister8(0x34, 0x80, 6, dst, src);
1231 : }
1232 :
1233 : template <class ReferenceType>
1234 : void AssemblerBase<ReferenceType>::xor(const Register32& dst,
1235 E : const Register32& src) {
1236 E : InstructionBuffer instr(this);
1237 E : instr.EmitArithmeticInstruction(0x31, src, dst);
1238 E : }
1239 :
1240 : template <class ReferenceType>
1241 : void AssemblerBase<ReferenceType>::xor(const Register32& dst,
1242 E : const Operand& src) {
1243 E : InstructionBuffer instr(this);
1244 E : instr.EmitArithmeticInstruction(0x33, dst, src);
1245 E : }
1246 :
1247 : template <class ReferenceType>
1248 : void AssemblerBase<ReferenceType>::xor(const Operand& dst,
1249 E : const Register32& src) {
1250 E : InstructionBuffer instr(this);
1251 E : instr.EmitArithmeticInstruction(0x31, dst, src);
1252 E : }
1253 :
1254 : template <class ReferenceType>
1255 : void AssemblerBase<ReferenceType>::xor(const Register32& dst,
1256 E : const Immediate& src) {
1257 E : InstructionBuffer instr(this);
1258 E : instr.EmitArithmeticInstructionToRegister32(0x35, 0x83, 0x81, 6, dst, src);
1259 E : }
1260 :
1261 : template <class ReferenceType>
1262 : void AssemblerBase<ReferenceType>::xor(const Operand& dst,
1263 E : const Immediate& src) {
1264 E : InstructionBuffer instr(this);
1265 E : instr.EmitArithmeticInstructionToOperand(0x83, 0x81, 6, dst, src);
1266 E : }
1267 :
1268 : template <class ReferenceType>
1269 : void AssemblerBase<ReferenceType>::shl(const Register32& dst,
1270 E : const Immediate& src) {
1271 E : InstructionBuffer instr(this);
1272 E : if (src.value() == 1) {
1273 E : instr.EmitOpCodeByte(0xD1);
1274 E : instr.EmitModRMByte(kReg1, 4, dst.id());
1275 E : } else {
1276 E : instr.EmitOpCodeByte(0xC1);
1277 E : instr.EmitModRMByte(kReg1, 4, dst.id());
1278 E : instr.Emit8BitImmediate(src);
1279 : }
1280 E : }
1281 :
1282 : template <class ReferenceType>
1283 : void AssemblerBase<ReferenceType>::shr(const Register32& dst,
1284 E : const Immediate& src) {
1285 E : InstructionBuffer instr(this);
1286 E : if (src.value() == 1) {
1287 E : instr.EmitOpCodeByte(0xD1);
1288 E : instr.EmitModRMByte(kReg1, 5, dst.id());
1289 E : } else {
1290 E : instr.EmitOpCodeByte(0xC1);
1291 E : instr.EmitModRMByte(kReg1, 5, dst.id());
1292 E : instr.Emit8BitImmediate(src);
1293 : }
1294 E : }
1295 :
1296 : template <class ReferenceType>
1297 : void AssemblerBase<ReferenceType>::xchg(const Register32& dst,
1298 E : const Register32& src) {
1299 E : InstructionBuffer instr(this);
1300 E : instr.EmitXchg(kSize32Bit, dst.id(), src.id());
1301 E : }
1302 :
1303 : template <class ReferenceType>
1304 : void AssemblerBase<ReferenceType>::xchg(const Register16& dst,
1305 E : const Register16& src) {
1306 E : InstructionBuffer instr(this);
1307 E : instr.EmitXchg(kSize16Bit, dst.id(), src.id());
1308 E : }
1309 :
1310 : template <class ReferenceType>
1311 : void AssemblerBase<ReferenceType>::xchg(const Register8& dst,
1312 E : const Register8& src) {
1313 E : InstructionBuffer instr(this);
1314 E : instr.EmitXchg(kSize8Bit, dst.id(), src.id());
1315 E : }
1316 :
1317 : template <class ReferenceType>
1318 : void AssemblerBase<ReferenceType>::xchg(const Register32& dst,
1319 E : const Operand& src) {
1320 E : InstructionBuffer instr(this);
1321 E : instr.EmitOpCodeByte(0x87);
1322 E : instr.EmitOperand(dst.code(), src);
1323 E : }
1324 :
1325 : template <class ReferenceType>
1326 E : void AssemblerBase<ReferenceType>::nop1(size_t prefix_count) {
1327 E : InstructionBuffer instr(this);
1328 E : instr.EmitOperandSizePrefix(prefix_count);
1329 E : instr.EmitXchg(kSize32Bit, kRegisterEax, kRegisterEax);
1330 E : }
1331 :
1332 : template <class ReferenceType>
1333 E : void AssemblerBase<ReferenceType>::nop4(size_t prefix_count) {
1334 E : InstructionBuffer instr(this);
1335 E : instr.EmitOperandSizePrefix(prefix_count);
1336 : // 4 bytes: NOP DWORD PTR [EAX + 0] 8-bit offset
1337 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1338 E : instr.EmitOpCodeByte(kNopOpCode);
1339 E : instr.EmitModRMByte(kReg1ByteDisp, 0, kRegisterEax);
1340 E : instr.Emit8BitDisplacement(Displacement(0, kSize8Bit));
1341 E : }
1342 :
1343 : template <class ReferenceType>
1344 E : void AssemblerBase<ReferenceType>::nop5(size_t prefix_count) {
1345 E : InstructionBuffer instr(this);
1346 E : instr.EmitOperandSizePrefix(prefix_count);
1347 : // 5 bytes: NOP DWORD PTR [EAX + EAX * 1 + 0] 8-bit offset
1348 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1349 E : instr.EmitOpCodeByte(kNopOpCode);
1350 : // esp in the ModR/M byte indicates SIB to follow.
1351 E : instr.EmitModRMByte(kReg1ByteDisp, 0, kRegisterEsp);
1352 E : instr.EmitScaleIndexBaseByte(kTimes1, kRegisterEax, kRegisterEax);
1353 E : instr.Emit8BitDisplacement(Displacement(0, kSize8Bit));
1354 E : }
1355 :
1356 : template <class ReferenceType>
1357 E : void AssemblerBase<ReferenceType>::nop7(size_t prefix_count) {
1358 E : InstructionBuffer instr(this);
1359 E : instr.EmitOperandSizePrefix(prefix_count);
1360 : // 7 bytes: NOP DWORD PTR [EAX + 0] 32-bit offset
1361 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1362 E : instr.EmitOpCodeByte(kNopOpCode);
1363 E : instr.EmitModRMByte(kReg1WordDisp, 0, kRegisterEax);
1364 E : instr.Emit32BitDisplacement(Displacement(0, kSize32Bit));
1365 E : }
1366 :
1367 : template <class ReferenceType>
1368 E : void AssemblerBase<ReferenceType>::nop8(size_t prefix_count) {
1369 E : InstructionBuffer instr(this);
1370 E : instr.EmitOperandSizePrefix(prefix_count);
1371 : // 8 bytes: NOP DWORD PTR [EAX + EAX * 1 + 0] 32-bit offset
1372 E : instr.EmitOpCodeByte(kTwoByteOpCodePrefix);
1373 E : instr.EmitOpCodeByte(kNopOpCode);
1374 : // esp in the ModR/M byte indicates SIB to follow.
1375 E : instr.EmitModRMByte(kReg1WordDisp, 0, kRegisterEsp);
1376 E : instr.EmitScaleIndexBaseByte(kTimes1, kRegisterEax, kRegisterEax);
1377 E : instr.Emit32BitDisplacement(Displacement(0, kSize32Bit));
1378 E : }
1379 :
1380 : template <class ReferenceType>
1381 E : void AssemblerBase<ReferenceType>::Output(const InstructionBuffer& instr) {
1382 : serializer_->AppendInstruction(location_,
1383 : instr.buf(),
1384 : instr.len(),
1385 : instr.reference_infos(),
1386 E : instr.num_reference_infos());
1387 :
1388 E : location_ += instr.len();
1389 E : }
1390 :
1391 : template <class ReferenceType>
1392 : bool AssemblerBase<ReferenceType>::FinalizeLabel(
1393 E : uint32 location, uint32 destination, RegisterSize size) {
1394 E : if (size == kSize8Bit) {
1395 : // Compute the relative value, note that this is computed relative to
1396 : // the end of the PC-relative constant, e.g. from the start of the next
1397 : // instruction.
1398 E : int32 relative_value = destination - (location + 1);
1399 : if (relative_value < std::numeric_limits<int8>::min() ||
1400 E : relative_value > std::numeric_limits<int8>::max()) {
1401 : // Out of bounds...
1402 E : return false;
1403 : }
1404 E : uint8 byte = relative_value & 0xFF;
1405 E : return serializer_->FinalizeLabel(location, &byte, sizeof(byte));
1406 i : } else {
1407 E : DCHECK_EQ(kSize32Bit, size);
1408 E : int32 relative_value = destination - (location + 4);
1409 :
1410 : return serializer_->FinalizeLabel(
1411 : location,
1412 : reinterpret_cast<const uint8*>(&relative_value),
1413 E : sizeof(relative_value));
1414 : }
1415 E : }
1416 :
1417 : } // namespace assm
1418 :
1419 : #endif // SYZYGY_ASSM_ASSEMBLER_BASE_IMPL_H_
|