assembler.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  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.
  4. // Copyright (c) 1994-2006 Sun Microsystems Inc.
  5. // All Rights Reserved.
  6. //
  7. // Redistribution and use in source and binary forms, with or without
  8. // modification, are permitted provided that the following conditions are
  9. // met:
  10. //
  11. // - Redistributions of source code must retain the above copyright notice,
  12. // this list of conditions and the following disclaimer.
  13. //
  14. // - Redistribution in binary form must reproduce the above copyright
  15. // notice, this list of conditions and the following disclaimer in the
  16. // documentation and/or other materials provided with the distribution.
  17. //
  18. // - Neither the name of Sun Microsystems or the names of contributors may
  19. // be used to endorse or promote products derived from this software without
  20. // specific prior written permission.
  21. //
  22. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  23. // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  24. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  25. // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  26. // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  27. // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  28. // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  29. // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  30. // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  31. // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. // The original source code covered by the above license above has been
  34. // modified significantly by Google Inc.
  35. // Copyright 2006-2008 the V8 project authors. All rights reserved.
  36. // This implements a C++ assembler for dynamically generating machine code.
  37. // It is heavily based on the v8 assembler, which has a long history of its
  38. // own. Relocation information has been removed, and in general things were
  39. // made a bit simpler (and slower). Everything is implemented inline.
  40. #ifndef TRACELINE_ASSEMBLER_H_
  41. #define TRACELINE_ASSEMBLER_H_
  42. #include <windows.h>
  43. #include <stdio.h>
  44. #include <string>
  45. #include <stddef.h>
  46. #include "logging.h"
  47. #define ASSERT(x) CHECK(x)
  48. enum Register {
  49. EAX = 0,
  50. ECX = 1,
  51. EDX = 2,
  52. EBX = 3,
  53. ESP = 4,
  54. EBP = 5,
  55. ESI = 6,
  56. EDI = 7
  57. };
  58. enum Condition {
  59. overflow = 0,
  60. no_overflow = 1,
  61. below = 2,
  62. above_equal = 3,
  63. equal = 4,
  64. not_equal = 5,
  65. below_equal = 6,
  66. above = 7,
  67. sign = 8,
  68. not_sign = 9,
  69. parity_even = 10,
  70. parity_odd = 11,
  71. less = 12,
  72. greater_equal = 13,
  73. less_equal = 14,
  74. greater = 15,
  75. // aliases
  76. zero = equal,
  77. not_zero = not_equal,
  78. negative = sign,
  79. positive = not_sign
  80. };
  81. // Labels are used for branching, and marks an offset in the CodeBuffer.
  82. // A label can be in 3 states:
  83. // - Unused, the label has never be used in an instruction.
  84. // - Linked, the label has been referenced (by a jump, for example), but the
  85. // target is not yet known, because the label is unbound.
  86. // - Bound, the label has been bound so the offset is known.
  87. class Label {
  88. public:
  89. Label() { Unuse(); }
  90. ~Label() { ASSERT(!is_linked()); }
  91. void Unuse() {
  92. num_ = 0;
  93. }
  94. bool is_unused() const { return num_ == 0; }
  95. bool is_bound() const { return num_ == -1; }
  96. bool is_linked() const { return num_ > 0; }
  97. int binding_pos() const {
  98. ASSERT(is_bound());
  99. return table_[0];
  100. }
  101. int num_links() const {
  102. ASSERT(!is_bound());
  103. return num_; // Will return 0 if unused.
  104. }
  105. int link_pos(int i) const {
  106. ASSERT(is_linked());
  107. ASSERT(i < num_);
  108. return table_[i];
  109. }
  110. private:
  111. void bind_to(int pos) {
  112. ASSERT(!is_bound());
  113. table_[0] = pos;
  114. num_ = -1;
  115. }
  116. void link_to(int pos) {
  117. ASSERT(!is_bound());
  118. ASSERT(num_ < kTableSize);
  119. table_[num_] = pos;
  120. ++num_;
  121. }
  122. static const int kTableSize = 3;
  123. // We store all links in a fixed size table. When we're bound, we store the
  124. // binding position in the first entry of the table.
  125. int table_[kTableSize];
  126. // The number of entries in our table, if we're linked. If 0, then we're
  127. // unusued. If -1, then we are bound (and the pos is at table_[0]).
  128. int num_;
  129. friend class CodeBuffer; // For binding, linking, etc
  130. };
  131. enum ScaleFactor {
  132. SCALE_TIMES_1 = 0,
  133. SCALE_TIMES_2 = 1,
  134. SCALE_TIMES_4 = 2,
  135. SCALE_TIMES_8 = 3
  136. };
  137. class Operand {
  138. public:
  139. explicit Operand(const Operand& x) : len_(x.len_) {
  140. memcpy(buf_, x.buf_, sizeof(buf_));
  141. }
  142. // reg
  143. explicit Operand(Register reg) {
  144. Init(reg);
  145. }
  146. // [disp/r]
  147. explicit Operand(int disp) {
  148. Init(disp);
  149. }
  150. // [base + disp/r]
  151. Operand(Register base, int disp) {
  152. Init(base, disp);
  153. }
  154. // [base + index*scale + disp/r]
  155. Operand(Register base, Register index, ScaleFactor scale, int disp) {
  156. Init(base, index, scale, disp);
  157. }
  158. // [index*scale + disp/r]
  159. Operand(Register index, ScaleFactor scale, int disp) {
  160. Init(index, scale, disp);
  161. }
  162. void set_reg(Register reg) {
  163. ASSERT(len_ > 0);
  164. buf_[0] = (buf_[0] & ~0x38) | static_cast<char>(reg << 3);
  165. }
  166. char* data() { return buf_; }
  167. int length() { return len_; }
  168. private:
  169. // reg
  170. void Init(Register reg) {
  171. set_modrm(3, reg);
  172. }
  173. // [disp/r]
  174. void Init(int disp) {
  175. set_modrm(0, EBP);
  176. set_dispr(disp);
  177. }
  178. // [base + disp/r]
  179. void Init(Register base, int disp) {
  180. if (disp == 0) {
  181. // [base]
  182. set_modrm(0, base);
  183. if (base == ESP) set_sib(SCALE_TIMES_1, ESP, base);
  184. } else if (is_int8(disp)) {
  185. // [base + disp8]
  186. set_modrm(1, base);
  187. if (base == ESP) set_sib(SCALE_TIMES_1, ESP, base);
  188. set_disp8(disp);
  189. } else {
  190. // [base + disp/r]
  191. set_modrm(2, base);
  192. if (base == ESP) set_sib(SCALE_TIMES_1, ESP, base);
  193. set_dispr(disp);
  194. }
  195. }
  196. // [base + index*scale + disp/r]
  197. void Init(Register base,
  198. Register index,
  199. ScaleFactor scale,
  200. int disp) {
  201. ASSERT(index != ESP); // illegal addressing mode
  202. if (disp == 0 && base != EBP) {
  203. // [base + index*scale]
  204. set_modrm(0, ESP);
  205. set_sib(scale, index, base);
  206. } else if (is_int8(disp)) {
  207. // [base + index*scale + disp8]
  208. set_modrm(1, ESP);
  209. set_sib(scale, index, base);
  210. set_disp8(disp);
  211. } else {
  212. // [base + index*scale + disp/r]
  213. set_modrm(2, ESP);
  214. set_sib(scale, index, base);
  215. set_dispr(disp);
  216. }
  217. }
  218. // [index*scale + disp/r]
  219. void Init(Register index,
  220. ScaleFactor scale,
  221. int disp) {
  222. ASSERT(index != ESP); // illegal addressing mode
  223. // We can reduce instruction size by translating instructions of the form:
  224. // 8D044510000000 lea eax,[eax*2+0x10]
  225. // To the more concise scale=1 version:
  226. // 8D440010 lea eax,[eax+eax+0x10]
  227. if (scale == SCALE_TIMES_2) {
  228. Init(index, index, SCALE_TIMES_1, disp);
  229. } else {
  230. set_modrm(0, ESP);
  231. set_sib(scale, index, EBP);
  232. set_dispr(disp);
  233. }
  234. }
  235. // Returns true if this Operand is a wrapper for the specified register.
  236. bool is_reg(Register reg) const {
  237. return ((buf_[0] & 0xF8) == 0xC0) // addressing mode is register only.
  238. && ((buf_[0] & 0x07) == reg); // register codes match.
  239. }
  240. void set_modrm(int mod, Register rm) { // reg == 0
  241. ASSERT((mod & -4) == 0);
  242. buf_[0] = mod << 6 | rm;
  243. len_ = 1;
  244. }
  245. void set_sib(ScaleFactor scale, Register index, Register base) {
  246. ASSERT(len_ == 1);
  247. ASSERT((scale & -4) == 0);
  248. buf_[1] = scale << 6 | index << 3 | base;
  249. len_ = 2;
  250. }
  251. void set_disp8(char disp) {
  252. ASSERT(len_ == 1 || len_ == 2);
  253. *reinterpret_cast<char*>(&buf_[len_++]) = disp;
  254. }
  255. void set_dispr(int disp) {
  256. ASSERT(len_ == 1 || len_ == 2);
  257. *reinterpret_cast<int*>(&buf_[len_]) = disp;
  258. len_ += sizeof(int);
  259. }
  260. bool is_int8(int x) { return x >= -128 && x <= 127; }
  261. // Mutable because reg in ModR/M byte is set by Assembler via set_reg().
  262. char buf_[6];
  263. // The number of bytes in buf_.
  264. unsigned int len_;
  265. };
  266. // A convenient wrapper around a buffer for emitting code or data, etc.
  267. class CodeBuffer {
  268. public:
  269. // Use an externally managed buffer
  270. explicit CodeBuffer(char* buf) : pos_(0), buf_(buf) { }
  271. void* data() { return buf_; }
  272. int size() { return pos_; }
  273. void emit(unsigned char b) {
  274. buf_[pos_++] = b;
  275. }
  276. void emit_word(unsigned short w) {
  277. *reinterpret_cast<unsigned short*>(&buf_[pos_]) = w;
  278. pos_ += 2;
  279. }
  280. void emit_dword(unsigned int d) {
  281. *reinterpret_cast<unsigned int*>(&buf_[pos_]) = d;
  282. pos_ += 4;
  283. }
  284. void emit_bytes(const char* bytes, size_t size) {
  285. for (size_t i = 0; i < size; ++i)
  286. emit(bytes[i]);
  287. }
  288. void emit_bytes(const std::string& bytes) {
  289. emit_bytes(bytes.data(), bytes.size());
  290. }
  291. void put_dword_at(int pos, unsigned int d) {
  292. *reinterpret_cast<unsigned int*>(&buf_[pos]) = d;
  293. }
  294. // We pass by value so that we get a copy that we can modify.
  295. void emit_operand(Register reg, Operand operand) {
  296. operand.set_reg(reg);
  297. memcpy(&buf_[pos_], operand.data(), operand.length());
  298. pos_ += operand.length();
  299. }
  300. void bind(Label* l) {
  301. ASSERT(!l->is_bound());
  302. for (int i = 0; i < l->num_links(); ++i) {
  303. put_dword_at(l->link_pos(i), pos_ - (l->link_pos(i) + 4));
  304. }
  305. l->bind_to(pos_);
  306. }
  307. // TODO deprecate blah_imm and use blah(Immediate)
  308. void add(Register dst, Register src) {
  309. emit(0x01); emit(0xc0 | (src << 3) | dst);
  310. }
  311. void add_imm(Register dst, int d) {
  312. if (d >= -128 && d <= 127) {
  313. emit(0x83); emit(0xc0 | dst); emit(d & 0xff);
  314. } else {
  315. emit(0x81); emit(0xc0 | dst); emit_dword(d);
  316. }
  317. }
  318. void and_(Register r, unsigned int mask) {
  319. emit(0x81); emit(0xe0 | r); emit_dword(mask);
  320. }
  321. void call(Register r) {
  322. call(Operand(r));
  323. }
  324. void call(const Operand& dst) {
  325. emit(0xff); emit_operand(EDX, dst);
  326. }
  327. void cmp(Register r1, Register r2) {
  328. emit(0x39); emit(0xc0 | (r2 << 3) | r1);
  329. }
  330. void cmp_imm(Register r, int d) {
  331. if (d >= -128 && d <= 127) {
  332. emit(0x83); emit(0xf8 | r); emit(d & 0xff);
  333. } else {
  334. emit(0x81); emit(0xf8 | r); emit_dword(d);
  335. }
  336. }
  337. void fs() {
  338. emit(0x64);
  339. }
  340. // Atomically increment the dword at |mem| with the increment amount in the
  341. // register |inc|. Will replace |inc| with the old unincremented value.
  342. void inc_atomic(Register mem, Register inc) {
  343. // lock xadd [mem], inc
  344. emit(0xF0); emit(0x0F); emit(0xC1); emit((inc << 3) | mem);
  345. }
  346. void int3() {
  347. emit(0xcc);
  348. }
  349. void jcc(Condition cc, Label* l) {
  350. emit(0x0f); emit(0x80 | cc);
  351. if (l->is_bound()) {
  352. emit_dword(l->binding_pos() - (pos_ + 4));
  353. } else {
  354. // Will fix up when the label is bound.
  355. l->link_to(pos_);
  356. emit_dword(0);
  357. }
  358. }
  359. void jmp(Register r) {
  360. emit(0xff); emit(0xe0 | r);
  361. }
  362. void jmp(Label* l) {
  363. if (l->is_bound()) {
  364. jmp_rel(l->binding_pos() - (pos_ + 5));
  365. } else {
  366. // Will fix up when the label is bound.
  367. l->link_to(pos_ + 1);
  368. jmp_rel(0);
  369. }
  370. }
  371. void jmp_rel(int i) {
  372. emit(0xe9); emit_dword(i);
  373. }
  374. void jmp_rel_short(char c) {
  375. emit(0xeb); emit(c);
  376. }
  377. void lea(Register dst, const Operand& src) {
  378. emit(0x8d); emit_operand(dst, src);
  379. }
  380. void lodsb() {
  381. emit(0xac);
  382. }
  383. void lodsd() {
  384. emit(0xad);
  385. }
  386. void loop(Label* l) {
  387. ASSERT(l->is_bound());
  388. int pos = l->binding_pos() - (pos_ + 2);
  389. ASSERT(pos >= -128 && pos < 0);
  390. emit(0xe2); emit(pos & 0xff);
  391. }
  392. void mov(Register dst, Register src) {
  393. emit(0x89); emit(0xc0 | (src << 3) | dst);
  394. }
  395. void mov(Register dst, const Operand& src) {
  396. emit(0x8b); emit_operand(dst, src);
  397. }
  398. void mov_imm(Register r, unsigned int d) {
  399. emit(0xb8 | r); emit_dword(d);
  400. }
  401. void movsb() {
  402. emit(0xa4);
  403. }
  404. void movsd() {
  405. emit(0xa5);
  406. }
  407. void or_(Register r, unsigned int mask) {
  408. emit(0x81); emit(0xc8 | r); emit_dword(mask);
  409. }
  410. void pop(Register r) {
  411. emit(0x58 | r);
  412. }
  413. void pop(const Operand& dst) {
  414. emit(0x8f); emit_operand(EAX, dst);
  415. }
  416. void push(Register r) {
  417. emit(0x50 | r);
  418. }
  419. void push(const Operand& src) {
  420. emit(0xff); emit_operand(ESI, src);
  421. }
  422. void push_imm(int i) {
  423. if (i >= -128 && i <= 127) {
  424. emit(0x6a); emit(i & 0xff);
  425. } else {
  426. emit(0x68); emit_dword(i);
  427. }
  428. }
  429. // Puts the cycle counter into edx:eax.
  430. void rdtsc() {
  431. emit(0x0F); emit(0x31);
  432. }
  433. void rep() {
  434. emit(0xf3);
  435. }
  436. void ret() {
  437. ret(0);
  438. }
  439. void ret(short c) {
  440. if (c == 0) {
  441. emit(0xc3);
  442. } else {
  443. emit(0xc2); emit_word(c);
  444. }
  445. }
  446. void spin() {
  447. jmp_rel_short(-2);
  448. }
  449. void stosb() {
  450. emit(0xaa);
  451. }
  452. void stosd() {
  453. emit(0xab);
  454. }
  455. void sysenter() {
  456. emit(0x0f); emit(0x34);
  457. }
  458. // Puts a unique cpu identifier into eax, using sidt to fingerprint cores.
  459. void which_cpu() {
  460. // Make space
  461. push(EAX);
  462. push(EAX);
  463. // sidt [esp+2]
  464. emit(0x0f); emit(0x01); emit_operand(ECX, Operand(ESP, 2));
  465. pop(EAX);
  466. pop(EAX); // sidt address
  467. }
  468. // Puts a unique identifier for the thread we're executing on into eax.
  469. void which_thread() {
  470. // mov eax, [fs:0x24]
  471. emit(0x64); emit(0xa1); emit_dword(0x24);
  472. // TODO: We could do this but it will use an encoding that is 1 byte bigger.
  473. // fs(); mov(EAX, Operand(0x24));
  474. }
  475. void xchg(Register r1, Register r2) {
  476. if (r1 == EAX) {
  477. emit(0x90 | r2);
  478. } else if (r2 == EAX) {
  479. emit(0x90 | r1);
  480. } else {
  481. xchg(r1, Operand(r2));
  482. }
  483. }
  484. void xchg(Register r1, const Operand& oper) {
  485. emit(0x87); emit_operand(r1, oper);
  486. }
  487. private:
  488. int pos_;
  489. char* buf_;
  490. };
  491. #endif // TRACELINE_ASSEMBLER_H_