1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Copyright (c) 1994-2006 Sun Microsystems Inc.
6 // All Rights Reserved.
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are
12 // - Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
15 // - Redistribution in binary form must reproduce the above copyright
16 // notice, this list of conditions and the following disclaimer in the
17 // documentation and/or other materials provided with the distribution.
19 // - Neither the name of Sun Microsystems or the names of contributors may
20 // be used to endorse or promote products derived from this software without
21 // specific prior written permission.
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 // The original source code covered by the above license above has been
36 // modified significantly by Google Inc.
37 // Copyright 2006-2008 the V8 project authors. All rights reserved.
39 // This implements a C++ assembler for dynamically generating machine code.
40 // It is heavily based on the v8 assembler, which has a long history of its
41 // own. Relocation information has been removed, and in general things were
42 // made a bit simpler (and slower). Everything is implemented inline.
44 #ifndef TRACELINE_ASSEMBLER_H_
45 #define TRACELINE_ASSEMBLER_H_
53 #define ASSERT(x) CHECK(x)
91 // Labels are used for branching, and marks an offset in the CodeBuffer.
92 // A label can be in 3 states:
93 // - Unused, the label has never be used in an instruction.
94 // - Linked, the label has been referenced (by a jump, for example), but the
95 // target is not yet known, because the label is unbound.
96 // - Bound, the label has been bound so the offset is known.
100 ~Label() { ASSERT(!is_linked()); }
106 bool is_unused() const { return num_
== 0; }
107 bool is_bound() const { return num_
== -1; }
108 bool is_linked() const { return num_
> 0; }
110 int binding_pos() const {
115 int num_links() const {
117 return num_
; // Will return 0 if unused.
120 int link_pos(int i
) const {
127 void bind_to(int pos
) {
132 void link_to(int pos
) {
134 ASSERT(num_
< kTableSize
);
140 static const int kTableSize
= 3;
142 // We store all links in a fixed size table. When we're bound, we store the
143 // binding position in the first entry of the table.
144 int table_
[kTableSize
];
145 // The number of entries in our table, if we're linked. If 0, then we're
146 // unusued. If -1, then we are bound (and the pos is at table_[0]).
149 friend class CodeBuffer
; // For binding, linking, etc
163 explicit Operand(const Operand
& x
) : len_(x
.len_
) {
164 memcpy(buf_
, x
.buf_
, sizeof(buf_
));
168 explicit Operand(Register reg
) {
173 explicit Operand(int disp
) {
178 Operand(Register base
, int disp
) {
182 // [base + index*scale + disp/r]
183 Operand(Register base
, Register index
, ScaleFactor scale
, int disp
) {
184 Init(base
, index
, scale
, disp
);
187 // [index*scale + disp/r]
188 Operand(Register index
, ScaleFactor scale
, int disp
) {
189 Init(index
, scale
, disp
);
192 void set_reg(Register reg
) {
194 buf_
[0] = (buf_
[0] & ~0x38) | static_cast<char>(reg
<< 3);
197 char* data() { return buf_
; }
198 int length() { return len_
; }
202 void Init(Register reg
) {
207 void Init(int disp
) {
213 void Init(Register base
, int disp
) {
217 if (base
== ESP
) set_sib(SCALE_TIMES_1
, ESP
, base
);
218 } else if (is_int8(disp
)) {
221 if (base
== ESP
) set_sib(SCALE_TIMES_1
, ESP
, base
);
226 if (base
== ESP
) set_sib(SCALE_TIMES_1
, ESP
, base
);
231 // [base + index*scale + disp/r]
232 void Init(Register base
,
236 ASSERT(index
!= ESP
); // illegal addressing mode
237 if (disp
== 0 && base
!= EBP
) {
238 // [base + index*scale]
240 set_sib(scale
, index
, base
);
241 } else if (is_int8(disp
)) {
242 // [base + index*scale + disp8]
244 set_sib(scale
, index
, base
);
247 // [base + index*scale + disp/r]
249 set_sib(scale
, index
, base
);
254 // [index*scale + disp/r]
255 void Init(Register index
,
258 ASSERT(index
!= ESP
); // illegal addressing mode
259 // We can reduce instruction size by translating instructions of the form:
260 // 8D044510000000 lea eax,[eax*2+0x10]
261 // To the more concise scale=1 version:
262 // 8D440010 lea eax,[eax+eax+0x10]
263 if (scale
== SCALE_TIMES_2
) {
264 Init(index
, index
, SCALE_TIMES_1
, disp
);
267 set_sib(scale
, index
, EBP
);
272 // Returns true if this Operand is a wrapper for the specified register.
273 bool is_reg(Register reg
) const {
274 return ((buf_
[0] & 0xF8) == 0xC0) // addressing mode is register only.
275 && ((buf_
[0] & 0x07) == reg
); // register codes match.
278 void set_modrm(int mod
, Register rm
) { // reg == 0
279 ASSERT((mod
& -4) == 0);
280 buf_
[0] = mod
<< 6 | rm
;
284 void set_sib(ScaleFactor scale
, Register index
, Register base
) {
286 ASSERT((scale
& -4) == 0);
287 buf_
[1] = scale
<< 6 | index
<< 3 | base
;
291 void set_disp8(char disp
) {
292 ASSERT(len_
== 1 || len_
== 2);
293 *reinterpret_cast<char*>(&buf_
[len_
++]) = disp
;
296 void set_dispr(int disp
) {
297 ASSERT(len_
== 1 || len_
== 2);
298 *reinterpret_cast<int*>(&buf_
[len_
]) = disp
;
302 bool is_int8(int x
) { return x
>= -128 && x
<= 127; }
304 // Mutable because reg in ModR/M byte is set by Assembler via set_reg().
306 // The number of bytes in buf_.
310 // A convenient wrapper around a buffer for emitting code or data, etc.
313 // Use an externally managed buffer
314 explicit CodeBuffer(char* buf
) : pos_(0), buf_(buf
) { }
316 void* data() { return buf_
; }
317 int size() { return pos_
; }
319 void emit(unsigned char b
) {
322 void emit_word(unsigned short w
) {
323 *reinterpret_cast<unsigned short*>(&buf_
[pos_
]) = w
;
326 void emit_dword(unsigned int d
) {
327 *reinterpret_cast<unsigned int*>(&buf_
[pos_
]) = d
;
331 void emit_bytes(const char* bytes
, size_t size
) {
332 for (size_t i
= 0; i
< size
; ++i
)
336 void emit_bytes(const std::string
& bytes
) {
337 emit_bytes(bytes
.data(), bytes
.size());
340 void put_dword_at(int pos
, unsigned int d
) {
341 *reinterpret_cast<unsigned int*>(&buf_
[pos
]) = d
;
344 // We pass by value so that we get a copy that we can modify.
345 void emit_operand(Register reg
, Operand operand
) {
346 operand
.set_reg(reg
);
347 memcpy(&buf_
[pos_
], operand
.data(), operand
.length());
348 pos_
+= operand
.length();
351 void bind(Label
* l
) {
352 ASSERT(!l
->is_bound());
353 for (int i
= 0; i
< l
->num_links(); ++i
) {
354 put_dword_at(l
->link_pos(i
), pos_
- (l
->link_pos(i
) + 4));
359 // TODO deprecate blah_imm and use blah(Immediate)
361 void add(Register dst
, Register src
) {
362 emit(0x01); emit(0xc0 | (src
<< 3) | dst
);
364 void add_imm(Register dst
, int d
) {
365 if (d
>= -128 && d
<= 127) {
366 emit(0x83); emit(0xc0 | dst
); emit(d
& 0xff);
368 emit(0x81); emit(0xc0 | dst
); emit_dword(d
);
372 void and_(Register r
, unsigned int mask
) {
373 emit(0x81); emit(0xe0 | r
); emit_dword(mask
);
376 void call(Register r
) {
379 void call(const Operand
& dst
) {
380 emit(0xff); emit_operand(EDX
, dst
);
383 void cmp(Register r1
, Register r2
) {
384 emit(0x39); emit(0xc0 | (r2
<< 3) | r1
);
387 void cmp_imm(Register r
, int d
) {
388 if (d
>= -128 && d
<= 127) {
389 emit(0x83); emit(0xf8 | r
); emit(d
& 0xff);
391 emit(0x81); emit(0xf8 | r
); emit_dword(d
);
399 // Atomically increment the dword at |mem| with the increment amount in the
400 // register |inc|. Will replace |inc| with the old unincremented value.
401 void inc_atomic(Register mem
, Register inc
) {
402 // lock xadd [mem], inc
403 emit(0xF0); emit(0x0F); emit(0xC1); emit((inc
<< 3) | mem
);
410 void jcc(Condition cc
, Label
* l
) {
411 emit(0x0f); emit(0x80 | cc
);
413 emit_dword(l
->binding_pos() - (pos_
+ 4));
415 // Will fix up when the label is bound.
421 void jmp(Register r
) {
422 emit(0xff); emit(0xe0 | r
);
427 jmp_rel(l
->binding_pos() - (pos_
+ 5));
429 // Will fix up when the label is bound.
430 l
->link_to(pos_
+ 1);
435 void jmp_rel(int i
) {
436 emit(0xe9); emit_dword(i
);
439 void jmp_rel_short(char c
) {
443 void lea(Register dst
, const Operand
& src
) {
444 emit(0x8d); emit_operand(dst
, src
);
454 void loop(Label
* l
) {
455 ASSERT(l
->is_bound());
456 int pos
= l
->binding_pos() - (pos_
+ 2);
457 ASSERT(pos
>= -128 && pos
< 0);
459 emit(0xe2); emit(pos
& 0xff);
462 void mov(Register dst
, Register src
) {
463 emit(0x89); emit(0xc0 | (src
<< 3) | dst
);
465 void mov(Register dst
, const Operand
& src
) {
466 emit(0x8b); emit_operand(dst
, src
);
468 void mov_imm(Register r
, unsigned int d
) {
469 emit(0xb8 | r
); emit_dword(d
);
479 void or_(Register r
, unsigned int mask
) {
480 emit(0x81); emit(0xc8 | r
); emit_dword(mask
);
483 void pop(Register r
) {
486 void pop(const Operand
& dst
) {
487 emit(0x8f); emit_operand(EAX
, dst
);
490 void push(Register r
) {
493 void push(const Operand
& src
) {
494 emit(0xff); emit_operand(ESI
, src
);
496 void push_imm(int i
) {
497 if (i
>= -128 && i
<= 127) {
498 emit(0x6a); emit(i
& 0xff);
500 emit(0x68); emit_dword(i
);
504 // Puts the cycle counter into edx:eax.
506 emit(0x0F); emit(0x31);
520 emit(0xc2); emit_word(c
);
536 emit(0x0f); emit(0x34);
539 // Puts a unique cpu identifier into eax, using sidt to fingerprint cores.
545 emit(0x0f); emit(0x01); emit_operand(ECX
, Operand(ESP
, 2));
547 pop(EAX
); // sidt address
550 // Puts a unique identifier for the thread we're executing on into eax.
551 void which_thread() {
552 // mov eax, [fs:0x24]
553 emit(0x64); emit(0xa1); emit_dword(0x24);
554 // TODO: We could do this but it will use an encoding that is 1 byte bigger.
555 // fs(); mov(EAX, Operand(0x24));
558 void xchg(Register r1
, Register r2
) {
561 } else if (r2
== EAX
) {
564 xchg(r1
, Operand(r2
));
567 void xchg(Register r1
, const Operand
& oper
) {
568 emit(0x87); emit_operand(r1
, oper
);
576 #endif // TRACELINE_ASSEMBLER_H_