summaryrefslogtreecommitdiffstats
path: root/chromium/tools/traceline/traceline/assembler.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/tools/traceline/traceline/assembler.h')
-rw-r--r--chromium/tools/traceline/traceline/assembler.h576
1 files changed, 0 insertions, 576 deletions
diff --git a/chromium/tools/traceline/traceline/assembler.h b/chromium/tools/traceline/traceline/assembler.h
deleted file mode 100644
index 6ae69587020..00000000000
--- a/chromium/tools/traceline/traceline/assembler.h
+++ /dev/null
@@ -1,576 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Copyright (c) 1994-2006 Sun Microsystems Inc.
-// All Rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// - Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// - Redistribution in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// - Neither the name of Sun Microsystems or the names of contributors may
-// be used to endorse or promote products derived from this software without
-// specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// The original source code covered by the above license above has been
-// modified significantly by Google Inc.
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
-
-// This implements a C++ assembler for dynamically generating machine code.
-// It is heavily based on the v8 assembler, which has a long history of its
-// own. Relocation information has been removed, and in general things were
-// made a bit simpler (and slower). Everything is implemented inline.
-
-#ifndef TRACELINE_ASSEMBLER_H_
-#define TRACELINE_ASSEMBLER_H_
-
-#include <windows.h>
-#include <stdio.h>
-#include <string>
-
-#include "logging.h"
-
-#define ASSERT(x) CHECK(x)
-
-enum Register {
- EAX = 0,
- ECX = 1,
- EDX = 2,
- EBX = 3,
- ESP = 4,
- EBP = 5,
- ESI = 6,
- EDI = 7
-};
-
-enum Condition {
- overflow = 0,
- no_overflow = 1,
- below = 2,
- above_equal = 3,
- equal = 4,
- not_equal = 5,
- below_equal = 6,
- above = 7,
- sign = 8,
- not_sign = 9,
- parity_even = 10,
- parity_odd = 11,
- less = 12,
- greater_equal = 13,
- less_equal = 14,
- greater = 15,
-
- // aliases
- zero = equal,
- not_zero = not_equal,
- negative = sign,
- positive = not_sign
-};
-
-// Labels are used for branching, and marks an offset in the CodeBuffer.
-// A label can be in 3 states:
-// - Unused, the label has never be used in an instruction.
-// - Linked, the label has been referenced (by a jump, for example), but the
-// target is not yet known, because the label is unbound.
-// - Bound, the label has been bound so the offset is known.
-class Label {
- public:
- Label() { Unuse(); }
- ~Label() { ASSERT(!is_linked()); }
-
- void Unuse() {
- num_ = 0;
- }
-
- bool is_unused() const { return num_ == 0; }
- bool is_bound() const { return num_ == -1; }
- bool is_linked() const { return num_ > 0; }
-
- int binding_pos() const {
- ASSERT(is_bound());
- return table_[0];
- }
-
- int num_links() const {
- ASSERT(!is_bound());
- return num_; // Will return 0 if unused.
- }
-
- int link_pos(int i) const {
- ASSERT(is_linked());
- ASSERT(i < num_);
- return table_[i];
- }
-
- private:
- void bind_to(int pos) {
- ASSERT(!is_bound());
- table_[0] = pos;
- num_ = -1;
- }
- void link_to(int pos) {
- ASSERT(!is_bound());
- ASSERT(num_ < kTableSize);
-
- table_[num_] = pos;
- ++num_;
- }
-
- static const int kTableSize = 3;
-
- // We store all links in a fixed size table. When we're bound, we store the
- // binding position in the first entry of the table.
- int table_[kTableSize];
- // The number of entries in our table, if we're linked. If 0, then we're
- // unusued. If -1, then we are bound (and the pos is at table_[0]).
- int num_;
-
- friend class CodeBuffer; // For binding, linking, etc
-};
-
-
-enum ScaleFactor {
- SCALE_TIMES_1 = 0,
- SCALE_TIMES_2 = 1,
- SCALE_TIMES_4 = 2,
- SCALE_TIMES_8 = 3
-};
-
-
-class Operand {
- public:
- explicit Operand(const Operand& x) : len_(x.len_) {
- memcpy(buf_, x.buf_, sizeof(buf_));
- }
-
- // reg
- explicit Operand(Register reg) {
- Init(reg);
- }
-
- // [disp/r]
- explicit Operand(int disp) {
- Init(disp);
- }
-
- // [base + disp/r]
- Operand(Register base, int disp) {
- Init(base, disp);
- }
-
- // [base + index*scale + disp/r]
- Operand(Register base, Register index, ScaleFactor scale, int disp) {
- Init(base, index, scale, disp);
- }
-
- // [index*scale + disp/r]
- Operand(Register index, ScaleFactor scale, int disp) {
- Init(index, scale, disp);
- }
-
- void set_reg(Register reg) {
- ASSERT(len_ > 0);
- buf_[0] = (buf_[0] & ~0x38) | static_cast<char>(reg << 3);
- }
-
- char* data() { return buf_; }
- int length() { return len_; }
-
- private:
- // reg
- void Init(Register reg) {
- set_modrm(3, reg);
- }
-
- // [disp/r]
- void Init(int disp) {
- set_modrm(0, EBP);
- set_dispr(disp);
- }
-
- // [base + disp/r]
- void Init(Register base, int disp) {
- if (disp == 0) {
- // [base]
- set_modrm(0, base);
- if (base == ESP) set_sib(SCALE_TIMES_1, ESP, base);
- } else if (is_int8(disp)) {
- // [base + disp8]
- set_modrm(1, base);
- if (base == ESP) set_sib(SCALE_TIMES_1, ESP, base);
- set_disp8(disp);
- } else {
- // [base + disp/r]
- set_modrm(2, base);
- if (base == ESP) set_sib(SCALE_TIMES_1, ESP, base);
- set_dispr(disp);
- }
- }
-
- // [base + index*scale + disp/r]
- void Init(Register base,
- Register index,
- ScaleFactor scale,
- int disp) {
- ASSERT(index != ESP); // illegal addressing mode
- if (disp == 0 && base != EBP) {
- // [base + index*scale]
- set_modrm(0, ESP);
- set_sib(scale, index, base);
- } else if (is_int8(disp)) {
- // [base + index*scale + disp8]
- set_modrm(1, ESP);
- set_sib(scale, index, base);
- set_disp8(disp);
- } else {
- // [base + index*scale + disp/r]
- set_modrm(2, ESP);
- set_sib(scale, index, base);
- set_dispr(disp);
- }
- }
-
- // [index*scale + disp/r]
- void Init(Register index,
- ScaleFactor scale,
- int disp) {
- ASSERT(index != ESP); // illegal addressing mode
- // We can reduce instruction size by translating instructions of the form:
- // 8D044510000000 lea eax,[eax*2+0x10]
- // To the more concise scale=1 version:
- // 8D440010 lea eax,[eax+eax+0x10]
- if (scale == SCALE_TIMES_2) {
- Init(index, index, SCALE_TIMES_1, disp);
- } else {
- set_modrm(0, ESP);
- set_sib(scale, index, EBP);
- set_dispr(disp);
- }
- }
-
- // Returns true if this Operand is a wrapper for the specified register.
- bool is_reg(Register reg) const {
- return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
- && ((buf_[0] & 0x07) == reg); // register codes match.
- }
-
- void set_modrm(int mod, Register rm) { // reg == 0
- ASSERT((mod & -4) == 0);
- buf_[0] = mod << 6 | rm;
- len_ = 1;
- }
-
- void set_sib(ScaleFactor scale, Register index, Register base) {
- ASSERT(len_ == 1);
- ASSERT((scale & -4) == 0);
- buf_[1] = scale << 6 | index << 3 | base;
- len_ = 2;
- }
-
- void set_disp8(char disp) {
- ASSERT(len_ == 1 || len_ == 2);
- *reinterpret_cast<char*>(&buf_[len_++]) = disp;
- }
-
- void set_dispr(int disp) {
- ASSERT(len_ == 1 || len_ == 2);
- *reinterpret_cast<int*>(&buf_[len_]) = disp;
- len_ += sizeof(int);
- }
-
- bool is_int8(int x) { return x >= -128 && x <= 127; }
-
- // Mutable because reg in ModR/M byte is set by Assembler via set_reg().
- char buf_[6];
- // The number of bytes in buf_.
- unsigned int len_;
-};
-
-// A convenient wrapper around a buffer for emitting code or data, etc.
-class CodeBuffer {
- public:
- // Use an externally managed buffer
- explicit CodeBuffer(char* buf) : pos_(0), buf_(buf) { }
-
- void* data() { return buf_; }
- int size() { return pos_; }
-
- void emit(unsigned char b) {
- buf_[pos_++] = b;
- }
- void emit_word(unsigned short w) {
- *reinterpret_cast<unsigned short*>(&buf_[pos_]) = w;
- pos_ += 2;
- }
- void emit_dword(unsigned int d) {
- *reinterpret_cast<unsigned int*>(&buf_[pos_]) = d;
- pos_ += 4;
- }
-
- void emit_bytes(const char* bytes, size_t size) {
- for (size_t i = 0; i < size; ++i)
- emit(bytes[i]);
- }
-
- void emit_bytes(const std::string& bytes) {
- emit_bytes(bytes.data(), bytes.size());
- }
-
- void put_dword_at(int pos, unsigned int d) {
- *reinterpret_cast<unsigned int*>(&buf_[pos]) = d;
- }
-
- // We pass by value so that we get a copy that we can modify.
- void emit_operand(Register reg, Operand operand) {
- operand.set_reg(reg);
- memcpy(&buf_[pos_], operand.data(), operand.length());
- pos_ += operand.length();
- }
-
- void bind(Label* l) {
- ASSERT(!l->is_bound());
- for (int i = 0; i < l->num_links(); ++i) {
- put_dword_at(l->link_pos(i), pos_ - (l->link_pos(i) + 4));
- }
- l->bind_to(pos_);
- }
-
- // TODO deprecate blah_imm and use blah(Immediate)
-
- void add(Register dst, Register src) {
- emit(0x01); emit(0xc0 | (src << 3) | dst);
- }
- void add_imm(Register dst, int d) {
- if (d >= -128 && d <= 127) {
- emit(0x83); emit(0xc0 | dst); emit(d & 0xff);
- } else {
- emit(0x81); emit(0xc0 | dst); emit_dword(d);
- }
- }
-
- void and_(Register r, unsigned int mask) {
- emit(0x81); emit(0xe0 | r); emit_dword(mask);
- }
-
- void call(Register r) {
- call(Operand(r));
- }
- void call(const Operand& dst) {
- emit(0xff); emit_operand(EDX, dst);
- }
-
- void cmp(Register r1, Register r2) {
- emit(0x39); emit(0xc0 | (r2 << 3) | r1);
- }
-
- void cmp_imm(Register r, int d) {
- if (d >= -128 && d <= 127) {
- emit(0x83); emit(0xf8 | r); emit(d & 0xff);
- } else {
- emit(0x81); emit(0xf8 | r); emit_dword(d);
- }
- }
-
- void fs() {
- emit(0x64);
- }
-
- // Atomically increment the dword at |mem| with the increment amount in the
- // register |inc|. Will replace |inc| with the old unincremented value.
- void inc_atomic(Register mem, Register inc) {
- // lock xadd [mem], inc
- emit(0xF0); emit(0x0F); emit(0xC1); emit((inc << 3) | mem);
- }
-
- void int3() {
- emit(0xcc);
- }
-
- void jcc(Condition cc, Label* l) {
- emit(0x0f); emit(0x80 | cc);
- if (l->is_bound()) {
- emit_dword(l->binding_pos() - (pos_ + 4));
- } else {
- // Will fix up when the label is bound.
- l->link_to(pos_);
- emit_dword(0);
- }
- }
-
- void jmp(Register r) {
- emit(0xff); emit(0xe0 | r);
- }
-
- void jmp(Label* l) {
- if (l->is_bound()) {
- jmp_rel(l->binding_pos() - (pos_ + 5));
- } else {
- // Will fix up when the label is bound.
- l->link_to(pos_ + 1);
- jmp_rel(0);
- }
- }
-
- void jmp_rel(int i) {
- emit(0xe9); emit_dword(i);
- }
-
- void jmp_rel_short(char c) {
- emit(0xeb); emit(c);
- }
-
- void lea(Register dst, const Operand& src) {
- emit(0x8d); emit_operand(dst, src);
- }
-
- void lodsb() {
- emit(0xac);
- }
- void lodsd() {
- emit(0xad);
- }
-
- void loop(Label* l) {
- ASSERT(l->is_bound());
- int pos = l->binding_pos() - (pos_ + 2);
- ASSERT(pos >= -128 && pos < 0);
-
- emit(0xe2); emit(pos & 0xff);
- }
-
- void mov(Register dst, Register src) {
- emit(0x89); emit(0xc0 | (src << 3) | dst);
- }
- void mov(Register dst, const Operand& src) {
- emit(0x8b); emit_operand(dst, src);
- }
- void mov_imm(Register r, unsigned int d) {
- emit(0xb8 | r); emit_dword(d);
- }
-
- void movsb() {
- emit(0xa4);
- }
- void movsd() {
- emit(0xa5);
- }
-
- void or_(Register r, unsigned int mask) {
- emit(0x81); emit(0xc8 | r); emit_dword(mask);
- }
-
- void pop(Register r) {
- emit(0x58 | r);
- }
- void pop(const Operand& dst) {
- emit(0x8f); emit_operand(EAX, dst);
- }
-
- void push(Register r) {
- emit(0x50 | r);
- }
- void push(const Operand& src) {
- emit(0xff); emit_operand(ESI, src);
- }
- void push_imm(int i) {
- if (i >= -128 && i <= 127) {
- emit(0x6a); emit(i & 0xff);
- } else {
- emit(0x68); emit_dword(i);
- }
- }
-
- // Puts the cycle counter into edx:eax.
- void rdtsc() {
- emit(0x0F); emit(0x31);
- }
-
- void rep() {
- emit(0xf3);
- }
-
- void ret() {
- ret(0);
- }
- void ret(short c) {
- if (c == 0) {
- emit(0xc3);
- } else {
- emit(0xc2); emit_word(c);
- }
- }
-
- void spin() {
- jmp_rel_short(-2);
- }
-
- void stosb() {
- emit(0xaa);
- }
- void stosd() {
- emit(0xab);
- }
-
- void sysenter() {
- emit(0x0f); emit(0x34);
- }
-
- // Puts a unique cpu identifier into eax, using sidt to fingerprint cores.
- void which_cpu() {
- // Make space
- push(EAX);
- push(EAX);
- // sidt [esp+2]
- emit(0x0f); emit(0x01); emit_operand(ECX, Operand(ESP, 2));
- pop(EAX);
- pop(EAX); // sidt address
- }
-
- // Puts a unique identifier for the thread we're executing on into eax.
- void which_thread() {
- // mov eax, [fs:0x24]
- emit(0x64); emit(0xa1); emit_dword(0x24);
- // TODO: We could do this but it will use an encoding that is 1 byte bigger.
- // fs(); mov(EAX, Operand(0x24));
- }
-
- void xchg(Register r1, Register r2) {
- if (r1 == EAX) {
- emit(0x90 | r2);
- } else if (r2 == EAX) {
- emit(0x90 | r1);
- } else {
- xchg(r1, Operand(r2));
- }
- }
- void xchg(Register r1, const Operand& oper) {
- emit(0x87); emit_operand(r1, oper);
- }
-
- private:
- int pos_;
- char* buf_;
-};
-
-#endif // TRACELINE_ASSEMBLER_H_