CACAO
X86_64EmitHelper.hpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/X86_64EmitHelper.hpp - X86_64EmitHelper
2 
3  Copyright (C) 2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 #ifndef _JIT_COMPILER2_X86_64EMITHELPER
26 #define _JIT_COMPILER2_X86_64EMITHELPER
27 
32 #include "vm/types.hpp"
33 #include "toolbox/logging.hpp"
34 
35 namespace cacao {
36 namespace jit {
37 namespace compiler2 {
38 namespace x86_64 {
39 
40 /**
41  * Opcode ref field.
42  */
43 struct OpReg {
45  OpReg(X86_64Register *reg) : reg(reg) {}
47  return reg;
48  }
50  return reg;
51  }
52 };
53 
54 /**
55  * REX Prefix Builder.
56  */
57 struct REX {
58  enum Field {
59  W = 3, ///< 0 = Operand size determined by CS.D
60  ///< 1 = 64 Bit Operand Size
61  R = 2, ///< Extension of the ModR/M reg field
62  X = 1, ///< Extension of the SIB index field
63  B = 0 ///< Extension of the ModR/M r/m field, SIB base field, or Opcode reg field
64  };
66 
67  REX() : rex(0x4 << 4) {}
68 
69  /// convert to u1
70  operator u1() {
71  return rex;
72  }
73  /**
74  * @note (binary) operator+ is evaluated left to right
75  */
77  rex |= 1 << f;
78  return *this;
79  }
80  /**
81  * @note (binary) operator- is evaluated left to right
82  */
84  rex &= ~(1 << f);
85  return *this;
86  }
88  if (reg->extented)
89  rex |= 1 << B;
90  return *this;
91  }
92 };
93 
94 inline u1 get_rex(X86_64Register *reg, X86_64Register *rm = NULL,
95  bool opsiz64 = true) {
96  const unsigned rex_w = 3;
97  const unsigned rex_r = 2;
98  //const unsigned rex_x = 1;
99  const unsigned rex_b = 0;
100 
101  u1 rex = 0x40;
102 
103  // 64-bit operand size
104  if (opsiz64) {
105  rex |= (1 << rex_w);
106  }
107 
108  if (reg && reg->extented) {
109  rex |= (1 << rex_r);
110  }
111  if (rm && rm->extented) {
112  rex |= (1 << rex_b);
113  }
114  return rex;
115 }
116 
117 inline u1 get_rex(const X86_64Register *reg1, X86_64Register *reg2 = NULL,
119  X86_64Register *reg3 = NULL) {
120  const unsigned rex_w = 3;
121  const unsigned rex_r = 2;
122  const unsigned rex_x = 1;
123  const unsigned rex_b = 0;
124 
125  u1 rex = 0x40;
126 
127  // 64-bit operand size
128  if (op_size == GPInstruction::OS_64) {
129  rex |= (1 << rex_w);
130  }
131  if (reg1 && reg1->extented) {
132  rex |= (1 << rex_r);
133  }
134  if (reg2 && reg2->extented) {
135  rex |= (1 << rex_b);
136  }
137  if (reg3 && reg3->extented) {
138  rex |= (1 << rex_x);
139  }
140  return rex;
141 
142 }
143 
145  return index || base == &RSP || base == &R12;
146 }
147 
148 inline u1 get_modrm(u1 reg, u1 base, s4 disp, bool use_sib = false) {
149  u1 modrm_mod = 6;
150  u1 modrm_reg = 3;
151  u1 modrm_rm = 0;
152 
153  u1 mod = 0;
154  u1 rm = 0;
155  u1 modrm = 0;
156 
157  if (disp == 0 || base == 0x05 /* RBP */) {
158  // no disp
159  mod = 0x00; //0b00
160  }
161  else if (fits_into<s1>(disp)) {
162  // disp8
163  mod = 0x01; // 0b01
164  } else if (fits_into<s4>(disp)) {
165  // disp32
166  mod = 0x02; // 0b10
167  }
168  else {
169  ABORT_MSG("Illegal displacement", "Displacement: "<<disp);
170  }
171 
172  if (use_sib) {
173  rm = 0x04; // 0b100
174  }
175  else {
176  rm = base;
177  }
178 
179  modrm = mod << modrm_mod;
180  modrm |= reg << modrm_reg;
181  modrm |= rm << modrm_rm;
182 
183  return modrm;
184 }
185 
186 inline u1 get_modrm (X86_64Register *reg, X86_64Register *base, s4 disp, bool use_sib = false) {
187  return get_modrm((reg != NULL) ? reg->get_index() : 0, (base != NULL) ? base->get_index() : 0, disp, use_sib);
188 }
189 
190 inline u1 get_sib(X86_64Register *base, X86_64Register *index = NULL, u1 scale = 1) {
191  u1 sib_scale = 6;
192  u1 sib_index = 3;
193  u1 sib_base = 0;
194 
195  u1 sib = 0;
196 
197  sib = scale << sib_scale;
198  if (index) {
199  sib |= index->get_index() << sib_index;
200  }
201  else {
202  sib |= RSP.get_index() << sib_index;
203  }
204 
205  sib |= base->get_index() << sib_base;
206 
207  return sib;
208 }
209 
210 
211 inline u1 get_modrm_u1(u1 mod, u1 reg, u1 rm) {
212  const unsigned modrm_mod = 6;
213  const unsigned modrm_reg = 3;
214  const unsigned modrm_rm = 0;
215 
216  u1 modrm = (0x3 & mod) << modrm_mod;
217  modrm |= (0x7 & reg) << modrm_reg;
218  modrm |= (0x7 & rm) << modrm_rm;
219 
220  return modrm;
221 }
223  return get_modrm_u1(mod,reg->get_index(), rm->get_index());
224 }
226  return get_modrm(0x3,reg,rm);
227 }
228 inline u1 get_modrm_1reg(u1 reg, X86_64Register *rm) {
229  return get_modrm_u1(0x3,reg,rm->get_index());
230 }
231 
233  if (op->is_StackSlot()) {
234  StackSlot *slot = op->to_StackSlot();
235  return slot->get_index() * 8;
236  } else if (op->is_ManagedStackSlot()) {
238  StackSlotManager *SSM = slot->get_parent();
239  return -(SSM->get_number_of_machine_slots() - slot->get_index()) * 8;
240  }
241  assert(false && "Not a stackslot");
242 }
243 
245 private:
247 public:
248  typedef Container::iterator iterator;
249  typedef Container::const_iterator const_iterator;
250  typedef Container::value_type value_type;
251 
252  void push_front(u1 d) { data.push_front(d); }
253  void push_back(u1 d) { data.push_back(d); }
255  push_back(d);
256  return *this;
257  }
258  u1& operator[](std::size_t i) {
259  if (i >= size()) {
260  data.resize(i+1,0);
261  }
262  return data[i];
263  }
264  u1 operator[](std::size_t i) const {
265  assert(i < size());
266  return data[i];
267  }
268  std::size_t size() const { return data.size(); }
269  const_iterator begin() const { return data.begin(); }
270  const_iterator end() const { return data.end(); }
271  iterator begin() { return data.begin(); }
272  iterator end() { return data.end(); }
273 private:
275 };
276 
278  CodeFragment CF = CM->get_CodeFragment(CSB.size());
279  for (std::size_t i = 0, e = CSB.size(); i < e; ++i) {
280  CF[i] = CSB[i];
281  }
282 }
283 
284 template <>
286  switch (op->get_OperandID()) {
288  {
289  ManagedStackSlot *mslot = op->to_ManagedStackSlot();
290  assert(mslot);
291  StackSlot *slot = mslot->to_StackSlot();
292  assert(slot);
293  return slot;
294  }
296  {
297  StackSlot *slot = op->to_StackSlot();
298  assert(slot);
299  return slot;
300  }
301  default: break;
302  }
303  assert(0 && "Not a stackslot");
304  return NULL;
305 }
306 
307 template <>
309  Immediate* imm = op->to_Immediate();
310  assert(imm);
311  return imm;
312 }
313 
315  template <class T>
316  static void reg2reg(CodeMemory *CM, T opcode,
317  X86_64Register *reg, X86_64Register *rm) {
318  CodeFragment code = CM->get_CodeFragment(2 + sizeof(T));
319 
320  code[0] = get_rex(reg,rm);
321 
322  for (int i = 0, e = sizeof(T) ; i < e ; ++i) {
323  code[i + 1] = (u1) 0xff & (opcode >> (8 * (e - i - 1)));
324  }
325 
326  code[1 + sizeof(T)] = get_modrm_reg2reg(reg,rm);
327  }
328  template <class T>
329  static void reg2rbp_disp8(CodeMemory *CM, T opcode,
330  X86_64Register *reg, s1 disp) {
331  CodeFragment code = CM->get_CodeFragment(3 + sizeof(T));
332 
333  code[0] = get_rex(reg);
334 
335  for (int i = 0, e = sizeof(T) ; i < e ; ++i) {
336  code[i + 1] = (u1) 0xff & (opcode >> (8 * (e - i - 1)));
337  }
338 
339  code[1 + sizeof(T)] = get_modrm(0x1,reg,&RBP);
340  code[2 + sizeof(T)] = u1(disp);
341  }
342  template <class T>
343  static void reg2rbp_disp32(CodeMemory *CM, T opcode,
344  X86_64Register *reg, s4 disp) {
345  CodeFragment code = CM->get_CodeFragment(6 + sizeof(T));
346 
347  code[0] = get_rex(reg);
348 
349  for (int i = 0, e = sizeof(T) ; i < e ; ++i) {
350  code[i + 1] = (u1) 0xff & (opcode >> (8 * (e - i - 1)));
351  }
352 
353  code[1 + sizeof(T)] = get_modrm(0x2,reg,&RBP);
354  code[2 + sizeof(T)] = u1( 0xff & (disp >> (0 * 8)));
355  code[3 + sizeof(T)] = u1( 0xff & (disp >> (1 * 8)));
356  code[4 + sizeof(T)] = u1( 0xff & (disp >> (2 * 8)));
357  code[5 + sizeof(T)] = u1( 0xff & (disp >> (3 * 8)));
358  }
359  template <class O,class I>
360  static void reg2imm(CodeMemory *CM, O opcode,
361  X86_64Register *reg, I imm) {
362  CodeFragment code = CM->get_CodeFragment(1 + sizeof(O) + sizeof(I));
363 
364  code[0] = get_rex(reg);
365 
366  for (int i = 0, e = sizeof(O) ; i < e ; ++i) {
367  code[i + 1] = (u1) 0xff & (opcode >> (8 * (e - i - 1)));
368  }
369  for (int i = 0, e = sizeof(I) ; i < e ; ++i) {
370  code[i + sizeof(O) + 1] = (u1) 0xff & (imm >> (8 * i));
371  }
372 
373  }
374  template <class O,class I>
375  static void reg2imm_modrm(CodeMemory *CM, O opcode,
376  X86_64Register* reg, X86_64Register *rm, I imm) {
377  CodeFragment code = CM->get_CodeFragment(2 + sizeof(O) + sizeof(I));
378 
379  code[0] = get_rex(reg, rm);
380 
381  for (int i = 0, e = sizeof(O) ; i < e ; ++i) {
382  code[i + 1] = (u1) 0xff & (opcode >> (8 * (e - i - 1)));
383  }
384  code[1 + sizeof(O)] = get_modrm_1reg(reg->get_index(),rm);
385  for (int i = 0, e = sizeof(I) ; i < e ; ++i) {
386  code[i + sizeof(O) + 2] = (u1) 0xff & (imm >> (8 * i));
387  }
388 
389  }
390  template <class O,class I>
391  static void imm_op(CodeMemory *CM, O opcode, I imm) {
392  CodeFragment code = CM->get_CodeFragment(sizeof(O) + sizeof(I));
393 
394  for (int i = 0, e = sizeof(O) ; i < e ; ++i) {
395  code[i] = (u1) 0xff & (opcode >> (8 * (e - i - 1)));
396  }
397  for (int i = 0, e = sizeof(I) ; i < e ; ++i) {
398  code[i + sizeof(O)] = (u1) 0xff & (imm >> (8 * i));
399  }
400 
401  }
402  template <class O,class I>
403  static void imm_op(CodeFragment &code, O opcode, I imm) {
404  assert(code.size() == (sizeof(O) + sizeof(I)));
405 
406  for (int i = 0, e = sizeof(O) ; i < e ; ++i) {
407  code[i] = (u1) 0xff & (opcode >> (8 * (e - i - 1)));
408  }
409  for (int i = 0, e = sizeof(I) ; i < e ; ++i) {
410  code[i + sizeof(O)] = (u1) 0xff & (imm >> (8 * i));
411  }
412 
413  }
414  template <class I,class Seg>
415  static void imm(Seg seg,I imm) {
416  assert(seg.size() == sizeof(I));
417 
418  for (int i = 0, e = sizeof(I) ; i < e ; ++i) {
419  seg[i] = (u1) 0xff & *(reinterpret_cast<u1*>(&imm) + i);
420  }
421 
422  }
423 
424  static void emit (CodeMemory* CM, u1 primary_opcode, GPInstruction::OperandSize op_size, MachineOperand *src, MachineOperand *dst, u1 secondary_opcode = 0, u1 op_reg = 0, u1 prefix = 0, bool prefix_0f = false, bool encode_dst = true, bool imm_sign_extended = false) {
425  CodeSegmentBuilder code;
426  if (dst->is_Register()) {
427  X86_64Register *dst_reg = cast_to<X86_64Register>(dst);
428  if (src->is_Register()) {
429  X86_64Register *src_reg = cast_to<X86_64Register>(src);
430  u1 rex = get_rex(dst_reg,src_reg,op_size == GPInstruction::OS_64);
431  if (rex != 0x40)
432  code += rex;
433  if (prefix)
434  code += prefix;
435  if (prefix_0f)
436  code += 0x0F;
437  code += primary_opcode;
438  if (secondary_opcode != 0x00) {
439  code += secondary_opcode;
440  }
441  code += get_modrm_reg2reg (dst_reg,src_reg);
442  }
443  else if (src->is_Immediate()) {
444  Immediate *src_imm = cast_to<Immediate>(src);
445  u1 rex = get_rex(NULL,dst_reg,op_size == GPInstruction::OS_64);
446  if (rex != 0x40)
447  code += rex;
448  if (prefix)
449  code += prefix;
450  if (prefix_0f)
451  code += 0x0F;
452  if (!encode_dst)
453  primary_opcode += dst_reg->get_index();
454  code += primary_opcode;
455  if (secondary_opcode != 0x00) {
456  code += secondary_opcode;
457  }
458  if (encode_dst) {
459  code += get_modrm_1reg(op_reg,dst_reg);
460  }
461  if (!imm_sign_extended) {
462  switch(op_size) {
463  case GPInstruction::OS_8:
464  {
465  s1 immval = src_imm->get_value<s1>();
466  code += (u1) 0xff & (immval >> 0x00);
467  break;
468  }
470  {
471  s2 immval = src_imm->get_value<s2>();
472  code += (u1) 0xff & (immval >> 0x00);
473  code += (u1) 0xff & (immval >> 0x08);
474  break;
475  }
477  {
478  s4 immval = src_imm->get_value<s4>();
479  code += (u1) 0xff & (immval >> 0x00);
480  code += (u1) 0xff & (immval >> 0x08);
481  code += (u1) 0xff & (immval >> 0x10);
482  code += (u1) 0xff & (immval >> 0x18);
483  break;
484  }
486  {
487  s8 immval = src_imm->get_value<s8>();
488  code += (u1) 0xff & (immval >> 0x00);
489  code += (u1) 0xff & (immval >> 0x08);
490  code += (u1) 0xff & (immval >> 0x10);
491  code += (u1) 0xff & (immval >> 0x18);
492  code += (u1) 0xff & (immval >> 0x20);
493  code += (u1) 0xff & (immval >> 0x28);
494  code += (u1) 0xff & (immval >> 0x30);
495  code += (u1) 0xff & (immval >> 0x38);
496  break;
497  }
499  ABORT_MSG("Invalid Immediate Size",
500  "dst: " << dst_reg << " src: " << src_imm << " op_code: " << primary_opcode);
501  break;
502  }
503  }
504  else {
505  if (fits_into<s1>(src_imm->get_value<s8>())) {
506  s1 immval = src_imm->get_value<s1>();
507  code += (u1) 0xff & (immval >> 0x00);
508  }
509  else if (fits_into<s2>(src_imm->get_value<s8>())) {
510  s2 immval = src_imm->get_value<s2>();
511  code += (u1) 0xff & (immval >> 0x00);
512  code += (u1) 0xff & (immval >> 0x08);
513  }
514  else if (fits_into<s4>(src_imm->get_value<s8>())) {
515  s4 immval = src_imm->get_value<s4>();
516  code += (u1) 0xff & (immval >> 0x00);
517  code += (u1) 0xff & (immval >> 0x08);
518  code += (u1) 0xff & (immval >> 0x10);
519  code += (u1) 0xff & (immval >> 0x18);
520  }
521  else {
522  s8 immval = src_imm->get_value<s8>();
523  code += (u1) 0xff & (immval >> 0x00);
524  code += (u1) 0xff & (immval >> 0x08);
525  code += (u1) 0xff & (immval >> 0x10);
526  code += (u1) 0xff & (immval >> 0x18);
527  code += (u1) 0xff & (immval >> 0x20);
528  code += (u1) 0xff & (immval >> 0x28);
529  code += (u1) 0xff & (immval >> 0x30);
530  code += (u1) 0xff & (immval >> 0x38);
531  }
532  }
533  }
534  else if (src->is_stackslot()) {
535  s4 index = get_stack_position(src);
536  u1 rex = get_rex(dst_reg,NULL,op_size == GPInstruction::OS_64);
537  if (rex != 0x40)
538  code += rex;
539  if (prefix)
540  code += prefix;
541  if (prefix_0f)
542  code += 0x0F;
543  code += primary_opcode;
544  if (secondary_opcode != 0x00) {
545  code += secondary_opcode;
546  }
547  if (fits_into<s1>(index)) {
548  // Shouldn't mod be 0x0 for RIP relative addressing? needs test
549  code += get_modrm(0x1,dst_reg,&RBP);
550  code += index;
551  } else {
552  code += get_modrm(0x2,dst_reg,&RBP);
553  code += (u1) 0xff & (index >> 0x00);
554  code += (u1) 0xff & (index >> 0x08);
555  code += (u1) 0xff & (index >> 0x10);
556  code += (u1) 0xff & (index >> 0x18);
557  }
558  }
559  else if (src->is_Address()) {
561  X86_64Register *base = src_mod->getBase();
562  X86_64Register *index = src_mod->getIndex();
563  s4 disp = src_mod->getDisp();
564  u1 scale = src_mod->getScale();
565  u1 rex = get_rex(dst_reg, base, op_size, index);
566  if (rex != 0x40)
567  code += rex;
568  if (prefix)
569  code += prefix;
570  if (prefix_0f)
571  code += 0x0F;
572  code += primary_opcode;
573  if (secondary_opcode != 0x00) {
574  code += secondary_opcode;
575  }
576  bool sib = use_sib(base, index);
577  code += get_modrm(dst_reg,base,disp,sib);
578  if (sib) {
579  code += get_sib(base,index,scale);
580  }
581  if (disp != 0) {
582  if (fits_into<s1>(disp) && base != &RBP) {
583  code += (s1)disp;
584  }
585  else {
586  code += (u1) 0xff & (disp >> 0x00);
587  code += (u1) 0xff & (disp >> 0x08);
588  code += (u1) 0xff & (disp >> 0x10);
589  code += (u1) 0xff & (disp >> 0x18);
590  }
591  }
592  }
593  else {
594  ABORT_MSG("Operand(s) not supported",
595  "dst_reg: " << dst_reg << " src: " << src << " op_code: " << primary_opcode);
596  }
597  }
598  else if (dst->is_stackslot()) {
599  s4 index = get_stack_position(dst);
600  if (src->is_Register()) {
601  X86_64Register *src_reg = cast_to<X86_64Register>(src);
602  u1 rex = get_rex(src_reg,NULL,op_size == GPInstruction::OS_64);
603  if (rex != 0x40)
604  code += rex;
605  if (prefix)
606  code += prefix;
607  if (prefix_0f)
608  code += 0x0F;
609  code += primary_opcode;
610  if (secondary_opcode != 0x00) {
611  code += secondary_opcode;
612  }
613  if (fits_into<s1>(index)) {
614  // Shouldn't mod be 0x0 for RIP relative addressing? needs test
615  code += get_modrm(0x1,src_reg,&RBP);
616  code += index;
617  } else {
618  code += get_modrm(0x2,src_reg,&RBP);
619  code += (u1) 0xff & (index >> 0x00);
620  code += (u1) 0xff & (index >> 0x08);
621  code += (u1) 0xff & (index >> 0x10);
622  code += (u1) 0xff & (index >> 0x18);
623  }
624  }
625  else {
626  ABORT_MSG("Operand(s) not supported",
627  "dst: " << dst << " src: " << src << " op_code: " << primary_opcode);
628  }
629  }
630  else if (dst->is_Address()) {
632  X86_64Register *base = dst_mod->getBase();
633  X86_64Register *index = dst_mod->getIndex();
634  s4 disp = dst_mod->getDisp();
635  u1 scale = dst_mod->getScale();
636  if (src->is_Register()) {
637  X86_64Register *src_reg = cast_to<X86_64Register>(src);
638  u1 rex = get_rex(src_reg, base, op_size, index);
639  if (rex != 0x40)
640  code += rex;
641  if (prefix)
642  code += prefix;
643  if (prefix_0f)
644  code += 0x0F;
645  code += primary_opcode;
646  if (secondary_opcode != 0x00) {
647  code += secondary_opcode;
648  }
649  bool sib = use_sib(base, index);
650  code += get_modrm(src_reg,base,disp,sib);
651  if (sib) {
652  code += get_sib(base,index,scale);
653  }
654  if (disp != 0) {
655  if (fits_into<s1>(disp) && base != &RBP) {
656  code += (s1)disp;
657  }
658  else {
659  code += (u1) 0xff & (disp >> 0x00);
660  code += (u1) 0xff & (disp >> 0x08);
661  code += (u1) 0xff & (disp >> 0x10);
662  code += (u1) 0xff & (disp >> 0x18);
663  }
664  }
665  }
666  else if (src->is_Immediate()) {
667  Immediate *src_imm = cast_to<Immediate>(src);
668  u1 rex = get_rex(NULL, base, op_size, index);
669  if (rex != 0x40)
670  code += rex;
671  if (prefix)
672  code += prefix;
673  if (prefix_0f)
674  code += 0x0F;
675  code += primary_opcode;
676  if (secondary_opcode != 0x00) {
677  code += secondary_opcode;
678  }
679  bool sib = use_sib(base, index);
680  code += get_modrm(op_reg,base->get_index(),disp,sib);
681  if (sib) {
682  code += get_sib(base,index,scale);
683  }
684  if (disp != 0) {
685  if (fits_into<s1>(disp) && base != &RBP) {
686  code += (s1)disp;
687  }
688  else {
689  code += (u1) 0xff & (disp >> 0x00);
690  code += (u1) 0xff & (disp >> 0x08);
691  code += (u1) 0xff & (disp >> 0x10);
692  code += (u1) 0xff & (disp >> 0x18);
693  }
694  }
695  switch(op_size) {
696  case GPInstruction::OS_8:
697  {
698  s1 immval = src_imm->get_value<s1>();
699  code += (u1) 0xff & (immval >> 0x00);
700  break;
701  }
703  {
704  s2 immval = src_imm->get_value<s2>();
705  code += (u1) 0xff & (immval >> 0x00);
706  code += (u1) 0xff & (immval >> 0x08);
707  break;
708  }
710  {
711  s4 immval = src_imm->get_value<s4>();
712  code += (u1) 0xff & (immval >> 0x00);
713  code += (u1) 0xff & (immval >> 0x08);
714  code += (u1) 0xff & (immval >> 0x10);
715  code += (u1) 0xff & (immval >> 0x18);
716  break;
717  }
719  {
720  if (disp != 0) {
721  ABORT_MSG("Invalid Immediate Size (imm64 with disp not allowed)",
722  "dst: " << dst_mod << " src: " << src_imm << " op_code: " << primary_opcode);
723  }
724  s8 immval = src_imm->get_value<s8>();
725  code += (u1) 0xff & (immval >> 0x00);
726  code += (u1) 0xff & (immval >> 0x08);
727  code += (u1) 0xff & (immval >> 0x10);
728  code += (u1) 0xff & (immval >> 0x18);
729  code += (u1) 0xff & (immval >> 0x20);
730  code += (u1) 0xff & (immval >> 0x28);
731  code += (u1) 0xff & (immval >> 0x30);
732  code += (u1) 0xff & (immval >> 0x38);
733  break;
734  }
736  ABORT_MSG("Invalid Immediate Size",
737  "dst: " << dst_mod << " src: " << src_imm << " op_code: " << primary_opcode);
738  break;
739  }
740  }
741  else {
742  ABORT_MSG("Operand(s) not supported",
743  "dst: " << dst_mod << " src: " << src << " op_code: " << primary_opcode);
744  }
745  }
746  else {
747  ABORT_MSG("Operand(s) not supported!",
748  "dst: " << dst << " src: " << src << " op_code: " << primary_opcode);
749  }
750 
751 
752  add_CodeSegmentBuilder(CM,code);
753  }
754 
755 };
756 #if 0
757 template <>
758 static void InstructionEncoding::reg2reg<u1>(
759  CodeMemory *CM, u1 opcode,
760  X86_64Register *src, X86_64Register *dst) {
761  CodeFragment code = CM->get_CodeFragment(3);
762  code[0] = get_rex(src,dst);
763  code[1] = opcode;
764  code[2] = get_modrm_reg2reg(src,dst);
765 }
766 #endif
767 
768 } // end namespace x86_64
769 } // end namespace compiler2
770 } // end namespace jit
771 } // end namespace cacao
772 
773 #endif /* _JIT_COMPILER2_X86_64EMITHELPER */
774 
775 
776 /*
777  * These are local overrides for various environment variables in Emacs.
778  * Please do not remove this and leave it at the end of the file, where
779  * Emacs will automagically detect them.
780  * ---------------------------------------------------------------------
781  * Local variables:
782  * mode: c++
783  * indent-tabs-mode: t
784  * c-basic-offset: 4
785  * tab-width: 4
786  * End:
787  * vim:noexpandtab:sw=4:ts=4:
788  */
jlong jlong jlong jlong jint jmethodID jint slot
Definition: jvmti.h:497
std::size_t index
X86_64Register * cast_to< X86_64Register >(Register *reg)
CodeFragment get_CodeFragment(std::size_t size)
get a code fragment
Definition: CodeMemory.cpp:79
u1 get_modrm(u1 reg, u1 base, s4 disp, bool use_sib=false)
static void reg2rbp_disp8(CodeMemory *CM, T opcode, X86_64Register *reg, s1 disp)
virtual ManagedStackSlot * to_ManagedStackSlot()
u1 get_modrm_reg2reg(X86_64Register *reg, X86_64Register *rm)
static void reg2reg(CodeMemory *CM, T opcode, X86_64Register *reg, X86_64Register *rm)
u2 op
Definition: disass.cpp:129
alloc::set< EdgeType >::type mod
u1 get_modrm_1reg(u1 reg, X86_64Register *rm)
std::deque< T, Allocator< T > > type
Definition: deque.hpp:38
static void imm_op(CodeMemory *CM, O opcode, I imm)
void add_CodeSegmentBuilder(CodeMemory *CM, const CodeSegmentBuilder &CSB)
X86_64Register * operator*() const
uint8_t u1
Definition: types.hpp:40
u1 get_sib(X86_64Register *base, X86_64Register *index=NULL, u1 scale=1)
Extension of the ModR/M reg field.
int64_t s8
Definition: types.hpp:48
bool use_sib(X86_64Register *base, X86_64Register *index)
GPRegister R12("R12", 0x4, true, 0xc *8, 8)
u1 get_rex(X86_64Register *reg, X86_64Register *rm=NULL, bool opsiz64=true)
Extension of the SIB index field.
static void reg2imm(CodeMemory *CM, O opcode, X86_64Register *reg, I imm)
GPRegister RBP("RBP", 0x5, false, 0x5 *8, 8)
0 = Operand size determined by CS.D 1 = 64 Bit Operand Size
X86_64ModRMOperand * cast_to< X86_64ModRMOperand >(MachineOperand *op)
A &quot;virtual&quot; slot that will eventually be mapped to a machine-level slot.
StackSlot * cast_to< StackSlot >(MachineOperand *op)
std::size_t size() const
size of the reference
Definition: Segment.hpp:392
X86_64Register * operator->() const
MIIterator i
int32_t s4
Definition: types.hpp:45
Immediate * cast_to< Immediate >(MachineOperand *op)
static void emit(CodeMemory *CM, u1 primary_opcode, GPInstruction::OperandSize op_size, MachineOperand *src, MachineOperand *dst, u1 secondary_opcode=0, u1 op_reg=0, u1 prefix=0, bool prefix_0f=false, bool encode_dst=true, bool imm_sign_extended=false)
static void reg2imm_modrm(CodeMemory *CM, O opcode, X86_64Register *reg, X86_64Register *rm, I imm)
int get_stack_position(MachineOperand *op)
MIIterator e
StackSlotManager * get_parent() const
u1 get_modrm_u1(u1 mod, u1 reg, u1 rm)
#define I(value)
Definition: codegen.c:279
Operands that can be directly used by the machine (register, memory, stackslot)
int8_t s1
Definition: types.hpp:39
int16_t s2
Definition: types.hpp:42
Extension of the ModR/M r/m field, SIB base field, or Opcode reg field.
Segment reference.
Definition: Segment.hpp:44
static void imm_op(CodeFragment &code, O opcode, I imm)
static void reg2rbp_disp32(CodeMemory *CM, T opcode, X86_64Register *reg, s4 disp)
#define ABORT_MSG(EXPR_SHORT, EXPR_LONG)
Definition: logging.hpp:133
GPRegister RSP("RSP", 0x4, false, 0x4 *8, 8)