CACAO
Aarch64Emitter.cpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/aarch64/Aarch64Emitter.cpp
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 
27 
28 namespace cacao {
29 namespace jit {
30 namespace compiler2 {
31 namespace aarch64 {
32 
33 
34 const Shift::SHIFT Shift::LSL(0x0);
35 const Shift::SHIFT Shift::LSR(0x1);
36 const Shift::SHIFT Shift::ASR(0x2);
37 
38 Reg::RegConfiguration Reg::XConf{1, 0, 3, 0, &Reg::XZR};
39 Reg::RegConfiguration Reg::WConf{0, 0, 2, 0, &Reg::WZR};
40 Reg::RegConfiguration Reg::HConf{0, 0, 1, 0, &Reg::WZR};
41 Reg::RegConfiguration Reg::BConf{0, 0, 0, 0, &Reg::WZR};
42 
43 Reg::RegConfiguration Reg::DConf{1, 1, 3, 1, &Reg::XZR};
44 Reg::RegConfiguration Reg::SConf{0, 0, 2, 1, &Reg::WZR};
45 
46 Reg Reg::XZR(0x1f, &XConf);
47 Reg Reg::WZR(0x1f, &WConf);
48 
49 Reg Reg::XSP(0x1f, &XConf);
50 Reg Reg::XFP(0x1d, &XConf);
51 
52 
55  for (; rit != instructions.rend() ; ++rit) {
56  CodeFragment cf = cm->get_CodeFragment(4);
57  cf[0] = *rit & 0xff;
58  cf[1] = (*rit >> 8) & 0xff;
59  cf[2] = (*rit >> 16) & 0xff;
60  cf[3] = (*rit >> 24) & 0xfff;
61  }
62 }
63 
64 
66  assert(instructions.size() == 1);
67  u4 instr = instructions[0];
68  cf[0] = instr & 0xff;
69  cf[1] = (instr >> 8) & 0xff;
70  cf[2] = (instr >> 16) & 0xff;
71  cf[3] = (instr >> 24) & 0xff;
72 }
73 
74 void Emitter::ldr(const Reg& rt, s4 offset) {
75  load_literal(rt.sf(), rt.v(), offset, rt.r());
76 }
77 
78 void Emitter::ldur(const Reg& rt, const Reg& rn, s2 imm) {
79  load_store_unscaled(rt.size(), rt.v(), 1, imm, rn.r(), rt.r());
80 }
81 
82 void Emitter::stur(const Reg& rt, const Reg& rn, s2 imm) {
83  load_store_unscaled(rt.size(), rt.v(), 0, imm, rn.r(), rt.r());
84 }
85 
86 void Emitter::ldr(const Reg& rt, const Reg& rn, s2 imm) {
87  load_store_unsigned(rt.size(), rt.v(), 1, imm, rn.r(), rt.r());
88 }
89 
90 void Emitter::str(const Reg& rt, const Reg& rn, s2 imm) {
91  load_store_unsigned(rt.size(), rt.v(), 0, imm, rn.r(), rt.r());
92 }
93 
94 void Emitter::ldr(const Reg& rt, const Reg& rn, const Reg& rm) {
95  load_store_register(rt.size(), rt.v(), 1, rm.r(), 3, 0, rn.r(), rt.r());
96 }
97 
98 void Emitter::sbfm(const Reg& rd, const Reg& rn, u1 immr, u1 imms) {
99  bitfield(rd.sf(), 0, rd.sf(), immr, imms, rn.r(), rd.r());
100 }
101 
102 void Emitter::ubfm(const Reg& rd, const Reg& rn, u1 immr, u1 imms) {
103  bitfield(rd.sf(), 2, rd.sf(), immr, imms, rn.r(), rd.r());
104 }
105 
106 void Emitter::movn(const Reg& rd, u2 imm) {
107  move_wide_immediate(rd.sf(), 0, 0, imm, rd.r());
108 }
109 
110 void Emitter::movz(const Reg& rd, u2 imm) {
111  move_wide_immediate(rd.sf(), 2, 0, imm, rd.r());
112 }
113 
114 void Emitter::movk(const Reg& rd, u2 imm, u1 shift) {
115  move_wide_immediate(rd.sf(), 3, shift, imm, rd.r());
116 }
117 
118 void Emitter::add(const Reg& rd, const Reg& rn, s2 imm) {
119  add_subtract_immediate(rd.sf(), 0, 0, 0, imm, rn.r(), rd.r());
120 }
121 
122 void Emitter::sub(const Reg& rd, const Reg& rn, s2 imm) {
123  add_subtract_immediate(rd.sf(), 1, 0, 0, imm, rn.r(), rd.r());
124 }
125 
126 void Emitter::subs(const Reg& rd, const Reg& rn, s2 imm) {
127  add_subtract_immediate(rd.sf(), 1, 1, 0, imm, rn.r(), rd.r());
128 }
129 
130 void Emitter::andd(const Reg& rd, const Reg& rn, const Reg& rm) {
131  logical_shifted_register(rd.sf(), 0, 0, rm.r(), rn.r(), rd.r());
132 }
133 
134 void Emitter::orr(const Reg& rd, const Reg& rn, const Reg& rm) {
135  logical_shifted_register(rd.sf(), 1, 0, rm.r(), rn.r(), rd.r());
136 }
137 
138 void Emitter::sdiv(const Reg& rd, const Reg& rn, const Reg& rm) {
139  data_processing_2_source(rd.sf(), 0, rm.r(), 3, rn.r(), rd.r());
140 }
141 
142 void Emitter::madd(const Reg& rd, const Reg& rn, const Reg& rm, const Reg& ra) {
143  data_processing_3_source(rd.sf(), 0, 0, rm.r(), 0, ra.r(), rn.r(), rd.r());
144 }
145 
146 void Emitter::msub(const Reg& rd, const Reg& rn, const Reg& rm, const Reg& ra) {
147  data_processing_3_source(rd.sf(), 0, 0, rm.r(), 1, ra.r(), rn.r(), rd.r());
148 }
149 
150 void Emitter::add(const Reg& rd, const Reg& rn, const Reg& rm,
151  Shift::SHIFT shift, u1 amount) {
152  add_subtract_shifted_register(rd.sf(), 0, 0, shift.code, rm.r(),
153  amount, rn.r(), rd.r());
154 }
155 
156 void Emitter::subs(const Reg& rd, const Reg& rn, const Reg& rm) {
157  add_subtract_shifted_register(rd.sf(), 1, 1, 0, rm.r(), 0, rn.r(), rd.r());
158 }
159 
160 void Emitter::cmp(const Reg& rn, const Reg& rm) { subs(*rn.zero(), rn, rm); }
161 
162 void Emitter::sub(const Reg& rd, const Reg& rn, const Reg& rm) {
163  add_subtract_shifted_register(rd.sf(), 1, 0, 0, rm.r(), 0, rn.r(), rd.r());
164 }
165 
166 void Emitter::neg(const Reg& rd, const Reg& rm) { sub(rd, *rd.zero(), rm); }
167 
168 void Emitter::csel(const Reg& rd, const Reg& rn, const Reg& rm,
169  Cond::COND cond) {
170  conditional_select(rd.sf(), 0, 0, rm.r(), cond.code, 0, rn.r(), rd.r());
171 }
172 
173 void Emitter::mul(const Reg& rd, const Reg& rn, const Reg& rm) {
174  madd(rd, rn, rm, *rd.zero());
175 }
176 
177 void Emitter::fneg(const Reg& rd, const Reg& rn) {
178  fp_data_processing_1(0, 0, rd.type(), 2, rn.r(), rd.r());
179 }
180 
181 void Emitter::fadd(const Reg& rd, const Reg& rn, const Reg& rm) {
182  fp_data_processing_2(0, 0, rd.type(), rm.r(), 2, rn.r(), rd.r());
183 }
184 
185 void Emitter::fsub(const Reg& rd, const Reg& rn, const Reg& rm) {
186  fp_data_processing_2(0, 0, rd.type(), rm.r(), 3, rn.r(), rd.r());
187 }
188 
189 void Emitter::fmul(const Reg& rd, const Reg& rn, const Reg& rm) {
190  fp_data_processing_2(0, 0, rd.type(), rm.r(), 0, rn.r(), rd.r());
191 }
192 
193 void Emitter::fdiv(const Reg& rd, const Reg& rn, const Reg& rm) {
194  fp_data_processing_2(0, 0, rd.type(), rm.r(), 1, rn.r(), rd.r());
195 }
196 
197 void Emitter::fcmp(const Reg& rn, const Reg& rm) {
198  fp_compare(0, 0, rn.type(), rm.r(), 0, rn.r(), 0);
199 }
200 
201 void Emitter::fmov(const Reg& rd, const Reg& rn) {
202  fp_data_processing_1(0, 0, rd.type(), 0, rn.r(), rd.r());
203 }
204 
205 void Emitter::fcvt(const Reg& rd, const Reg& rn) {
206  fp_data_processing_1(0, 0, rn.type(), 4 + rd.type(), rn.r(), rd.r());
207 }
208 
209 void Emitter::scvtf(const Reg& rd, const Reg& rn) {
210  conversion_fp_integer(rn.sf(), 0, rd.type(), 0, 2, rn.r(), rd.r());
211 }
212 
213 void Emitter::trap(const Reg& rd, int type) {
214  trap_encode(rd.r(), type);
215 }
216 
217 } // end namespace aarch64
218 } // end namespace compiler2
219 } // end namespace jit
220 } // end namespace cacao
221 
222 
223 /*
224  * These are local overrides for various environment variables in Emacs.
225  * Please do not remove this and leave it at the end of the file, where
226  * Emacs will automagically detect them.
227  * ---------------------------------------------------------------------
228  * Local variables:
229  * mode: c++
230  * indent-tabs-mode: t
231  * c-basic-offset: 4
232  * tab-width: 4
233  * End:
234  * vim:noexpandtab:sw=4:ts=4:
235  */
void movk(const Reg &rd, u2 imm, u1 shift=0)
CodeFragment get_CodeFragment(std::size_t size)
get a code fragment
Definition: CodeMemory.cpp:79
#define ra
Definition: md-asm.hpp:62
void move_wide_immediate(u1 sf, u1 opc, u1 hw, u2 imm, u1 rd)
void fneg(const Reg &rd, const Reg &rn)
void add_subtract_shifted_register(u1 sf, u1 opc, u1 s, u1 shift, u1 rm, u1 imm, u1 rn, u1 rd)
void load_store_register(u1 size, u1 v, u1 opc, u1 rm, u1 option, u1 s, u1 rn, u1 rt)
void fp_data_processing_2(u1 m, u1 s, u1 type, u1 rm, u1 op, u1 rn, u1 rd)
void ldur(const Reg &rt, const Reg &rn, s2 imm=0)
void fmul(const Reg &rd, const Reg &rn, const Reg &rm)
void csel(const Reg &rd, const Reg &rn, const Reg &rm, Cond::COND cond)
void fadd(const Reg &rd, const Reg &rn, const Reg &rm)
void fcvt(const Reg &rd, const Reg &rn)
void add(const Reg &rd, const Reg &rn, s2 imm)
void msub(const Reg &rd, const Reg &rn, const Reg &rm, const Reg &ra)
void neg(const Reg &rd, const Reg &rm)
uint8_t u1
Definition: types.hpp:40
void str(const Reg &rt, const Reg &rn, s2 imm=0)
void orr(const Reg &rd, const Reg &rn, const Reg &rm)
void bitfield(u1 sf, u1 opc, u1 n, u1 immr, u1 imms, u1 rn, u1 rd)
void sdiv(const Reg &rd, const Reg &rn, const Reg &rm)
void load_store_unscaled(u1 size, u1 v, u1 opc, s2 imm, u1 rn, u1 rt)
void andd(const Reg &rd, const Reg &rn, const Reg &rm)
void fdiv(const Reg &rd, const Reg &rn, const Reg &rm)
void data_processing_3_source(u1 sf, u1 op54, u1 op31, u1 rm, u1 o0, u1 ra, u1 rn, u1 rd)
uint16_t u2
Definition: types.hpp:43
void sub(const Reg &rd, const Reg &rn, s2 imm)
void scvtf(const Reg &rd, const Reg &rn)
void ubfm(const Reg &rd, const Reg &rn, u1 immr, u1 imms)
int32_t s4
Definition: types.hpp:45
void stur(const Reg &rt, const Reg &rn, s2 imm=0)
void subs(const Reg &rd, const Reg &rn, s2 imm)
void fmov(const Reg &rd, const Reg &rn)
void conditional_select(u1 sf, u1 op, u1 s, u1 rm, u1 cond, u1 op2, u1 rn, u1 rd)
uint32_t u4
Definition: types.hpp:46
void mul(const Reg &rd, const Reg &rn, const Reg &rm)
void madd(const Reg &rd, const Reg &rn, const Reg &rm, const Reg &ra)
#define SHIFT(x, s)
Definition: codegen.hpp:56
void fcmp(const Reg &rn, const Reg &rm)
void logical_shifted_register(u1 sf, u1 opc, u1 n, u1 rm, u1 rn, u1 rd)
void fsub(const Reg &rd, const Reg &rn, const Reg &rm)
void fp_data_processing_1(u1 m, u1 s, u1 type, u1 op, u1 rn, u1 rd)
void ldr(const Reg &rt, s4 offset)
void trap(const Reg &rd, int type)
void add_subtract_immediate(u1 sf, u1 op, u1 s, u1 shift, s2 imm, u1 rn, u1 rd)
int16_t s2
Definition: types.hpp:42
Segment reference.
Definition: Segment.hpp:44
void fp_compare(u1 m, u1 s, u1 type, u1 rm, u1 op, u1 rn, u1 op2)
void data_processing_2_source(u1 sf, u1 s, u1 rm, u1 op, u1 rn, u1 rd)
void load_literal(u1 opc, u1 v, s4 imm, u1 rt)
void sbfm(const Reg &rd, const Reg &rn, u1 immr, u1 imms)
void load_store_unsigned(u1 size, u1 v, u1 opc, s2 imm, u1 rn, u1 rt)
void conversion_fp_integer(u1 sf, u1 s, u1 type, u1 rmode, u1 op, u1 rn, u1 rd)