WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

codegen.rs 21.4 KB
Newer Older
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
1
// Copyright 2017 The Australian National University
qinsoon's avatar
qinsoon committed
2
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
3
4
5
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
qinsoon's avatar
qinsoon committed
6
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
7
//     http://www.apache.org/licenses/LICENSE-2.0
qinsoon's avatar
qinsoon committed
8
//
Isaac Oscar Gariano's avatar
Isaac Oscar Gariano committed
9
10
11
12
13
14
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

15
use ast::ir::*;
16
use ast::ptr::P;
17
18
use runtime::ValueLocation;

19
use compiler::backend::{Mem, Reg};
20
21
22
23
use compiler::machine_code::MachineCode;

pub trait CodeGenerator {
    fn start_code(&mut self, func_name: MuName, entry: MuName) -> ValueLocation;
qinsoon's avatar
qinsoon committed
24
25
    fn finish_code(&mut self, func_name: MuName)
        -> (Box<MachineCode + Sync + Send>, ValueLocation);
26
27
28
29
30
31
32
33

    // generate unnamed sequence of linear code (no branch)
    fn start_code_sequence(&mut self);
    fn finish_code_sequence(&mut self) -> Box<MachineCode + Sync + Send>;

    fn print_cur_code(&self);

    fn start_block(&mut self, block_name: MuName);
34
    fn block_exists(&self, block_name: MuName) -> bool;
35
36
37
38
    fn start_exception_block(&mut self, block_name: MuName) -> ValueLocation;
    fn end_block(&mut self, block_name: MuName);

    // add CFI info
39
    fn add_cfi_sections(&mut self, arg: &str);
40
41
    fn add_cfi_startproc(&mut self);
    fn add_cfi_endproc(&mut self);
42
    fn add_cfi_def_cfa(&mut self, reg: Reg, offset: i32);
43
44
45
46
    fn add_cfi_def_cfa_register(&mut self, reg: Reg);
    fn add_cfi_def_cfa_offset(&mut self, offset: i32);
    fn add_cfi_offset(&mut self, reg: Reg, offset: i32);

qinsoon's avatar
qinsoon committed
47
    //===========================================================================================
48
49
50
51
52
53
54
55

    // emit code to adjust frame
    fn emit_frame_grow(&mut self); // Emits a SUB

    // stack minimpulation
    fn emit_push_pair(&mut self, src1: Reg, src2: Reg, stack: Reg); // Emits a STP
    fn emit_pop_pair(&mut self, dest1: Reg, dest2: Reg, stack: Reg); // Emits a LDP

56
57
58
59
    // For callee saved loads and stores (flags them so that only they are removed)
    fn emit_ldr_callee_saved(&mut self, dest: Reg, src: Mem);
    fn emit_str_callee_saved(&mut self, dest: Mem, src: Reg);

qinsoon's avatar
qinsoon committed
60
    //===========================================================================================
61

62
63
64
    /* Bellow ar all ARMv8-A Aarch64 instruction menmonics (with all operand modes) except:
        PRFM, PRFUM, CRC32*
        All advanced SIMD instructions (except MOVI)
65
66

    NOTE:
qinsoon's avatar
qinsoon committed
67
68
69
70
        with loads and stores the menmonic indicated may be given a suffix indicating the size
        and signenedness of the access also b_cond's menmononic is 'B.cond' (where cond is the
        value of the 'cond' parameter) all other instructions have the menmonic being the first
        word of the function name after emit_
71
            (subsequent words are used to disambiguate different overloads)
72
    NOTE unless otherwise indicated:
qinsoon's avatar
qinsoon committed
73
74
75
76
        An instruction that dosn't start with an F operates on GPRS, those that start with
        an F operate on FPRs. All instructions operate on 32-bit and 64-bit registers (but all
        register arguments must be the same size) Also all arguments that may take the SP can't
        take the ZR (and vice versa)
77
78
79
    */

    // loads
qinsoon's avatar
qinsoon committed
80
81
    // supports the full full range of addressing modes
    fn emit_ldr(&mut self, dest: Reg /*GPR or FPR*/, src: Mem, signed: bool);
82
    fn emit_ldtr(&mut self, dest: Reg, src: Mem, signed: bool); // [base, #simm9]
qinsoon's avatar
qinsoon committed
83
84
85
86
    fn emit_ldur(&mut self, dest: Reg /*GPR or FPR*/, src: Mem, signed: bool); // [base, #simm9]
    fn emit_ldxr(&mut self, dest: Reg, src: Mem); // [base]
    fn emit_ldaxr(&mut self, dest: Reg, src: Mem); // [base]
    fn emit_ldar(&mut self, dest: Reg, src: Mem); // [base]
87

qinsoon's avatar
qinsoon committed
88
89
    // [base, #simm7], [base], #simm7, [base, #simm7]!
    fn emit_ldp(&mut self, dest1: Reg, dest2: Reg /*GPR or FPR*/, src: Mem);
90
91
    fn emit_ldxp(&mut self, dest1: Reg, dest2: Reg, src: Mem); // [base]
    fn emit_ldaxp(&mut self, dest1: Reg, dest2: Reg, src: Mem); // [base]
qinsoon's avatar
qinsoon committed
92
93
94
95
    fn emit_ldnp(
        &mut self,
        dest1: Reg, /*GPR or FPR*/
        dest2: Reg, /*GPR or FPR*/
96
        src: Mem,
qinsoon's avatar
qinsoon committed
97
    ); // [base, #simm7]
98

99
    // Stores
qinsoon's avatar
qinsoon committed
100
101
    // supports the full full range of addressing modes
    fn emit_str(&mut self, dest: Mem, src: Reg /*GPR or FPR*/);
102
    fn emit_sttr(&mut self, dest: Mem, src: Reg); // [base, #simm9]
qinsoon's avatar
qinsoon committed
103
    fn emit_stur(&mut self, dest: Mem, src: Reg /*GPR or FPR*/); // [base, #simm9]
104
105
106
107
    fn emit_stlr(&mut self, dest: Mem, src: Reg); // [base]
    fn emit_stxr(&mut self, dest: Mem, status: Reg, src: Reg); // [base]
    fn emit_stlxr(&mut self, dest: Mem, status: Reg, src: Reg); // [base]

qinsoon's avatar
qinsoon committed
108
109
    // [base, #simm7], [base], #simm7, [base, #simm7]!
    fn emit_stp(&mut self, dest: Mem, src1: Reg, src2: Reg);
110
111
    fn emit_stxp(&mut self, dest: Mem, status: Reg, src1: Reg, src2: Reg); // [base]
    fn emit_stlxp(&mut self, dest: Mem, status: Reg, src1: Reg, src2: Reg); // [base]
qinsoon's avatar
qinsoon committed
112
113
114
115
    fn emit_stnp(
        &mut self,
        dest: Mem,
        src1: Reg, /*GPR or FPR*/
116
        src2: Reg, /*GPR or FPR*/
qinsoon's avatar
qinsoon committed
117
    ); // [base, #simm7]
118

119
    // Calls
qinsoon's avatar
qinsoon committed
120
121
    fn emit_bl(
        &mut self,
122
        callsite: Option<MuName>,
qinsoon's avatar
qinsoon committed
123
124
125
        func: MuName,
        pe: Option<MuName>,
        args: Vec<P<Value>>,
126
        ret: Vec<P<Value>>,
127
        is_native: bool,
128
    ) -> Option<ValueLocation>;
qinsoon's avatar
qinsoon committed
129
130
    fn emit_blr(
        &mut self,
131
        callsite: Option<MuName>,
qinsoon's avatar
qinsoon committed
132
133
        func: Reg,
        pe: Option<MuName>,
134
        args: Vec<P<Value>>,
135
        ret: Vec<P<Value>>,
136
    ) -> Option<ValueLocation>;
137
    // Branches
138
139
140
    fn emit_b(&mut self, dest_name: MuName);
    fn emit_b_cond(&mut self, cond: &str, dest_name: MuName);
    fn emit_br(&mut self, dest_address: Reg);
141
142
    fn emit_b_call(
        &mut self,
143
        callsite: Option<MuName>,
144
145
146
147
148
        func: MuName,
        pe: Option<MuName>,
        args: Vec<P<Value>>,
        ret: Vec<P<Value>>,
        is_native: bool,
149
        may_return: bool,
150
151
152
    ) -> Option<ValueLocation>;
    fn emit_br_call(
        &mut self,
153
        callsite: Option<MuName>,
154
155
156
157
        func: Reg,
        pe: Option<MuName>,
        args: Vec<P<Value>>,
        ret: Vec<P<Value>>,
158
        may_return: bool,
159
160
    ) -> Option<ValueLocation>;

161
162
163
164
165
166
167
168
169
170
171
    fn emit_ret(&mut self, src: Reg);
    fn emit_cbnz(&mut self, src: Reg, dest_name: MuName);
    fn emit_cbz(&mut self, src: Reg, dest_name: MuName);
    fn emit_tbnz(&mut self, src1: Reg, src2: u8, dest_name: MuName);
    fn emit_tbz(&mut self, src1: Reg, src2: u8, dest_name: MuName);

    // Read and write flags
    fn emit_msr(&mut self, dest: &str, src: Reg);
    fn emit_mrs(&mut self, dest: Reg, src: &str);

    // Address calculation
172
173
    fn emit_adr(&mut self, dest: Reg, src: Mem);
    fn emit_adrp(&mut self, dest: Reg, src: Mem);
174
175

    // Unary ops
qinsoon's avatar
qinsoon committed
176
177
    // The SP and ZR cannot both be used
    fn emit_mov(&mut self, dest: Reg /*GPR or SP or ZR*/, src: Reg /*GPR or SP or ZR*/);
178
179
180
181
182
    fn emit_mvn(&mut self, dest: Reg, src: Reg);
    fn emit_neg(&mut self, dest: Reg, src: Reg);
    fn emit_negs(&mut self, dest: Reg, src: Reg);
    fn emit_ngc(&mut self, dest: Reg, src: Reg);
    fn emit_ngcs(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
183
184
185
186
187
    fn emit_sxtb(&mut self, dest: Reg /*32*/, src: Reg /*32*/);
    fn emit_sxth(&mut self, dest: Reg /*32*/, src: Reg /*32*/);
    fn emit_sxtw(&mut self, dest: Reg /*64*/, src: Reg /*32*/);
    fn emit_uxtb(&mut self, dest: Reg /*32*/, src: Reg /*32*/);
    fn emit_uxth(&mut self, dest: Reg /*32*/, src: Reg /*32*/);
188
189
190
191
192
    fn emit_cls(&mut self, dest: Reg, src: Reg);
    fn emit_clz(&mut self, dest: Reg, src: Reg);
    fn emit_rbit(&mut self, dest: Reg, src: Reg);
    fn emit_rev(&mut self, dest: Reg, src: Reg);
    fn emit_rev16(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
193
194
    fn emit_rev32(&mut self, dest: Reg /*64*/, src: Reg);
    fn emit_rev64(&mut self, dest: Reg /*64*/, src: Reg); // alias of REV
195
    fn emit_fabs(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
196
197
198
199
200
201
202
203
204
205
206
207
208
    fn emit_fcvt(&mut self, dest: Reg, src: Reg /*Must have different size*/);
    fn emit_fcvtas(&mut self, dest: Reg /*GPR, may have different size*/, src: Reg);
    fn emit_fcvtau(&mut self, dest: Reg /*GPR, may have different size*/, src: Reg);
    fn emit_fcvtms(&mut self, dest: Reg /*GPR, may have different size*/, src: Reg);
    fn emit_fcvtmu(&mut self, dest: Reg /*GPR, may have different size*/, src: Reg);
    fn emit_fcvtns(&mut self, dest: Reg /*GPR, may have different size*/, src: Reg);
    fn emit_fcvtnu(&mut self, dest: Reg /*GPR, may have different size*/, src: Reg);
    fn emit_fcvtps(&mut self, dest: Reg /*GPR, may have different size*/, src: Reg);
    fn emit_fcvtpu(&mut self, dest: Reg /*GPR, may have different size*/, src: Reg);
    fn emit_fcvtzs(&mut self, dest: Reg /*GPR, may have different size*/, src: Reg);
    fn emit_fcvtzu(&mut self, dest: Reg /*GPR, may have different size*/, src: Reg);
    // One register must be an FPR, the other may be a GPR or an FPR
    fn emit_fmov(&mut self, dest: Reg, src: Reg);
209
210
211
212
213
214
215
216
217
    fn emit_fneg(&mut self, dest: Reg, src: Reg);
    fn emit_frinta(&mut self, dest: Reg, src: Reg);
    fn emit_frinti(&mut self, dest: Reg, src: Reg);
    fn emit_frintm(&mut self, dest: Reg, src: Reg);
    fn emit_frintn(&mut self, dest: Reg, src: Reg);
    fn emit_frintp(&mut self, dest: Reg, src: Reg);
    fn emit_frintx(&mut self, dest: Reg, src: Reg);
    fn emit_frintz(&mut self, dest: Reg, src: Reg);
    fn emit_fsqrt(&mut self, dest: Reg, src: Reg);
qinsoon's avatar
qinsoon committed
218
219
    fn emit_scvtf(&mut self, dest: Reg /*FPR, may have different size*/, src: Reg);
    fn emit_ucvtf(&mut self, dest: Reg /*FPR, may have different size*/, src: Reg);
220
221
222
223
224
225
226
227
228
229
230
231

    // Unary operations with shift
    fn emit_mov_shift(&mut self, dest: Reg, src: Reg, shift: &str, ammount: u8);
    fn emit_mvn_shift(&mut self, dest: Reg, src: Reg, shift: &str, ammount: u8);
    fn emit_neg_shift(&mut self, dest: Reg, src: Reg, shift: &str, ammount: u8);
    fn emit_negs_shift(&mut self, dest: Reg, src: Reg, shift: &str, ammount: u8);

    // Unary operations with immediates
    fn emit_mov_imm(&mut self, dest: Reg, src: u64);
    fn emit_movz(&mut self, dest: Reg, src: u16, shift: u8);
    fn emit_movk(&mut self, dest: Reg, src: u16, shift: u8);
    fn emit_movn(&mut self, dest: Reg, src: u16, shift: u8);
232
    fn emit_movi(&mut self, dest: Reg /*FPR*/, src: u64);
233
234
235
    fn emit_fmov_imm(&mut self, dest: Reg, src: f32);

    // Extended binary ops
qinsoon's avatar
qinsoon committed
236
237
238
239
240
241
    fn emit_add_ext(
        &mut self,
        dest: Reg, /*GPR or SP*/
        src1: Reg, /*GPR or SP*/
        src2: Reg,
        signed: bool,
242
        shift: u8,
qinsoon's avatar
qinsoon committed
243
244
245
246
247
248
249
    );
    fn emit_adds_ext(
        &mut self,
        dest: Reg,
        src1: Reg, /*GPR or SP*/
        src2: Reg,
        signed: bool,
250
        shift: u8,
qinsoon's avatar
qinsoon committed
251
252
253
254
255
256
257
    );
    fn emit_sub_ext(
        &mut self,
        dest: Reg, /*GPR or SP*/
        src1: Reg, /*GPR or SP*/
        src2: Reg,
        signed: bool,
258
        shift: u8,
qinsoon's avatar
qinsoon committed
259
260
261
262
263
264
265
    );
    fn emit_subs_ext(
        &mut self,
        dest: Reg,
        src1: Reg, /*GPR or SP*/
        src2: Reg,
        signed: bool,
266
        shift: u8,
qinsoon's avatar
qinsoon committed
267
    );
268
269
270
271

    // Multiplication
    fn emit_mul(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_mneg(&mut self, dest: Reg, src1: Reg, src2: Reg);
qinsoon's avatar
qinsoon committed
272
273
274
275
276
277
    fn emit_smulh(&mut self, dest: Reg /*64*/, src1: Reg /*64*/, src2: Reg /*64*/);
    fn emit_umulh(&mut self, dest: Reg /*64*/, src1: Reg /*64*/, src2: Reg /*64*/);
    fn emit_smnegl(&mut self, dest: Reg /*64*/, src1: Reg /*32*/, src2: Reg /*32*/);
    fn emit_smull(&mut self, dest: Reg /*64*/, src1: Reg /*32*/, src2: Reg /*32*/);
    fn emit_umnegl(&mut self, dest: Reg /*64*/, src1: Reg /*32*/, src2: Reg /*32*/);
    fn emit_umull(&mut self, dest: Reg /*64*/, src1: Reg /*32*/, src2: Reg /*32*/);
278
279
280
281

    // Other binaries
    fn emit_adc(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_adcs(&mut self, dest: Reg, src1: Reg, src2: Reg);
qinsoon's avatar
qinsoon committed
282
283
    fn emit_add(&mut self, dest: Reg, src1: Reg /*GPR or SP*/, src2: Reg);
    fn emit_adds(&mut self, dest: Reg, src1: Reg /*GPR or SP*/, src2: Reg);
284
285
286
287
288
289
290
    fn emit_sbc(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_sbcs(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_sub(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_subs(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_sdiv(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_udiv(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_asr(&mut self, dest: Reg, src1: Reg, src2: Reg);
291
    fn emit_asrv(&mut self, dest: Reg, src1: Reg, src2: Reg); // Alias of ASR
292
    fn emit_lsl(&mut self, dest: Reg, src1: Reg, src2: Reg);
293
    fn emit_lslv(&mut self, dest: Reg, src1: Reg, src2: Reg); // Alias of LSL
294
    fn emit_lsr(&mut self, dest: Reg, src1: Reg, src2: Reg);
295
    fn emit_lsrv(&mut self, dest: Reg, src1: Reg, src2: Reg); // Alias of LSR
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
    fn emit_ror(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_bic(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_bics(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_and(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_ands(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_eon(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_eor(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_orn(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_orr(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_fadd(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_fdiv(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_fmax(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_fmaxnm(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_fmin(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_fminm(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_fmul(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_fnmul(&mut self, dest: Reg, src1: Reg, src2: Reg);
    fn emit_fsub(&mut self, dest: Reg, src1: Reg, src2: Reg);

    // Binary operations with shift
    fn emit_add_shift(&mut self, dest: Reg, src1: Reg, src2: Reg, shift: &str, amount: u8);
    fn emit_adds_shift(&mut self, dest: Reg, src1: Reg, src2: Reg, shift: &str, amount: u8);
    fn emit_sub_shift(&mut self, dest: Reg, src1: Reg, src2: Reg, shift: &str, amount: u8);
    fn emit_subs_shift(&mut self, dest: Reg, src1: Reg, src2: Reg, shift: &str, amount: u8);
    fn emit_bic_shift(&mut self, dest: Reg, src1: Reg, src2: Reg, shift: &str, amount: u8);
    fn emit_bics_shift(&mut self, dest: Reg, src1: Reg, src2: Reg, shift: &str, amount: u8);
    fn emit_and_shift(&mut self, dest: Reg, src1: Reg, src2: Reg, shift: &str, amount: u8);
    fn emit_ands_shift(&mut self, dest: Reg, src1: Reg, src2: Reg, shift: &str, amount: u8);
    fn emit_eon_shift(&mut self, dest: Reg, src1: Reg, src2: Reg, shift: &str, amount: u8);
    fn emit_eor_shift(&mut self, dest: Reg, src1: Reg, src2: Reg, shift: &str, amount: u8);
    fn emit_orn_shift(&mut self, dest: Reg, src1: Reg, src2: Reg, shift: &str, amount: u8);
    fn emit_orr_shift(&mut self, dest: Reg, src1: Reg, src2: Reg, shift: &str, amount: u8);

    // binary ops with immediates
qinsoon's avatar
qinsoon committed
330
331
332
333
334
    fn emit_add_imm(
        &mut self,
        dest: Reg, /*GPR or SP*/
        src1: Reg, /*GPR or SP*/
        src2: u16,
335
        shift: bool,
qinsoon's avatar
qinsoon committed
336
337
338
339
340
341
342
    );
    fn emit_adds_imm(&mut self, dest: Reg, src1: Reg /*GPR or SP*/, src2: u16, shift: bool);
    fn emit_sub_imm(
        &mut self,
        dest: Reg, /*GPR or SP*/
        src1: Reg, /*GPR or SP*/
        src2: u16,
343
        shift: bool,
qinsoon's avatar
qinsoon committed
344
345
346
347
    );
    fn emit_subs_imm(&mut self, dest: Reg, src1: Reg /*GPR or SP*/, src2: u16, shift: bool);

    fn emit_and_imm(&mut self, dest: Reg /*GPR or SP*/, src1: Reg, src2: u64);
348
    fn emit_ands_imm(&mut self, dest: Reg, src1: Reg, src2: u64);
qinsoon's avatar
qinsoon committed
349
350
    fn emit_eor_imm(&mut self, dest: Reg /*GPR or SP*/, src1: Reg, src2: u64);
    fn emit_orr_imm(&mut self, dest: Reg /*GPR or SP*/, src1: Reg, src2: u64);
351
352
353
354
355
356
357
358
359
360

    fn emit_asr_imm(&mut self, dest: Reg, src1: Reg, src2: u8);
    fn emit_lsr_imm(&mut self, dest: Reg, src1: Reg, src2: u8);
    fn emit_lsl_imm(&mut self, dest: Reg, src1: Reg, src2: u8);
    fn emit_ror_imm(&mut self, dest: Reg, src1: Reg, src2: u8);

    // ternary ops

    fn emit_madd(&mut self, dest: Reg, src1: Reg, src2: Reg, src3: Reg);
    fn emit_msub(&mut self, dest: Reg, src1: Reg, src2: Reg, src3: Reg);
qinsoon's avatar
qinsoon committed
361
362
363
364
365
    fn emit_smaddl(
        &mut self,
        dest: Reg, /*64*/
        src1: Reg, /*32*/
        src2: Reg, /*32*/
366
        src3: Reg, /*64*/
qinsoon's avatar
qinsoon committed
367
368
369
370
371
372
    );
    fn emit_smsubl(
        &mut self,
        dest: Reg, /*64*/
        src1: Reg, /*32*/
        src2: Reg, /*32*/
373
        src3: Reg, /*64*/
qinsoon's avatar
qinsoon committed
374
375
376
377
378
379
    );
    fn emit_umaddl(
        &mut self,
        dest: Reg, /*64*/
        src1: Reg, /*32*/
        src2: Reg, /*32*/
380
        src3: Reg, /*64*/
qinsoon's avatar
qinsoon committed
381
382
383
384
385
386
    );
    fn emit_umsubl(
        &mut self,
        dest: Reg, /*64*/
        src1: Reg, /*32*/
        src2: Reg, /*32*/
387
        src3: Reg, /*64*/
qinsoon's avatar
qinsoon committed
388
    );
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
    fn emit_fmadd(&mut self, dest: Reg, src1: Reg, src2: Reg, src3: Reg);
    fn emit_fmsub(&mut self, dest: Reg, src1: Reg, src2: Reg, src3: Reg);
    fn emit_fnmadd(&mut self, dest: Reg, src1: Reg, src2: Reg, src3: Reg);
    fn emit_fnmsub(&mut self, dest: Reg, src1: Reg, src2: Reg, src3: Reg);

    // Ternary ops with immediates
    fn emit_bfm(&mut self, dest: Reg, src1: Reg, src2: u8, src3: u8);
    fn emit_bfi(&mut self, dest: Reg, src1: Reg, src2: u8, src3: u8);
    fn emit_bfxil(&mut self, dest: Reg, src1: Reg, src2: u8, src3: u8);
    fn emit_ubfm(&mut self, dest: Reg, src1: Reg, src2: u8, src3: u8);
    fn emit_ubfx(&mut self, dest: Reg, src1: Reg, src2: u8, src3: u8);
    fn emit_ubfiz(&mut self, dest: Reg, src1: Reg, src2: u8, src3: u8);
    fn emit_sbfm(&mut self, dest: Reg, src1: Reg, src2: u8, src3: u8);
    fn emit_sbfx(&mut self, dest: Reg, src1: Reg, src2: u8, src3: u8);
    fn emit_sbfiz(&mut self, dest: Reg, src1: Reg, src2: u8, src3: u8);

    // Comparison (dosn't store a result, only updates flags)
    fn emit_tst(&mut self, src1: Reg, src2: Reg);
    fn emit_cmn(&mut self, src1: Reg, src2: Reg);
    fn emit_cmp(&mut self, src1: Reg, src2: Reg);
    fn emit_fcmp(&mut self, src1: Reg, src2: Reg);
    fn emit_fcmpe(&mut self, src1: Reg, src2: Reg);

    // Comparisons with extension
qinsoon's avatar
qinsoon committed
413
414
    fn emit_cmn_ext(&mut self, src1: Reg /*GPR or SP*/, src2: Reg, signed: bool, shift: u8);
    fn emit_cmp_ext(&mut self, src1: Reg /*GPR or SP*/, src2: Reg, signed: bool, shift: u8);
415
416
417
418
419
420
421
422

    // Comparisons with shift
    fn emit_tst_shift(&mut self, src1: Reg, src2: Reg, shift: &str, ammount: u8);
    fn emit_cmn_shift(&mut self, src1: Reg, src2: Reg, shift: &str, ammount: u8);
    fn emit_cmp_shift(&mut self, src1: Reg, src2: Reg, shift: &str, ammount: u8);

    // Immediat Comparisons
    fn emit_tst_imm(&mut self, src1: Reg, src2: u64);
qinsoon's avatar
qinsoon committed
423
424
    fn emit_cmn_imm(&mut self, src1: Reg /*GPR or SP*/, src2: u16, shift: bool);
    fn emit_cmp_imm(&mut self, src1: Reg /*GPR or SP*/, src2: u16, shift: bool);
425

426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
    // Comparison against 0
    fn emit_fcmp_0(&mut self, src: Reg);
    fn emit_fcmpe_0(&mut self, src: Reg);

    // Conditional ops
    fn emit_cset(&mut self, dest: Reg, cond: &str);
    fn emit_csetm(&mut self, dest: Reg, cond: &str);

    // Conditional unary ops
    fn emit_cinc(&mut self, dest: Reg, src: Reg, cond: &str);
    fn emit_cneg(&mut self, dest: Reg, src: Reg, cond: &str);
    fn emit_cinv(&mut self, dest: Reg, src: Reg, cond: &str);

    // Conditional binary ops
    fn emit_csel(&mut self, dest: Reg, src1: Reg, src2: Reg, cond: &str);
    fn emit_csinc(&mut self, dest: Reg, src1: Reg, src2: Reg, cond: &str);
    fn emit_csinv(&mut self, dest: Reg, src1: Reg, src2: Reg, cond: &str);
    fn emit_csneg(&mut self, dest: Reg, src1: Reg, src2: Reg, cond: &str);
    fn emit_fcsel(&mut self, dest: Reg, src1: Reg, src2: Reg, cond: &str);

    // Conditional comparisons
    fn emit_ccmn(&mut self, src1: Reg, src2: Reg, flags: u8, cond: &str);
    fn emit_ccmp(&mut self, src1: Reg, src2: Reg, flags: u8, cond: &str);
    fn emit_fccmp(&mut self, src1: Reg, src2: Reg, flags: u8, cond: &str);
    fn emit_fccmpe(&mut self, src1: Reg, src2: Reg, flags: u8, cond: &str);

    // Conditional comparisons (with immediate)
    fn emit_ccmn_imm(&mut self, src1: Reg, src2: u8, flags: u8, cond: &str);
    fn emit_ccmp_imm(&mut self, src1: Reg, src2: u8, flags: u8, cond: &str);

    fn emit_bfc(&mut self, dest: Reg, src1: u8, src2: u8);
    fn emit_extr(&mut self, dest: Reg, src1: Reg, src2: Reg, src3: u8);

    // Synchronisation
    fn emit_dsb(&mut self, option: &str);
    fn emit_dmb(&mut self, option: &str);
    fn emit_isb(&mut self, option: &str);
    fn emit_clrex(&mut self);

    // Hint instructions
    fn emit_sevl(&mut self);
    fn emit_sev(&mut self);
    fn emit_wfe(&mut self);
    fn emit_wfi(&mut self);
    fn emit_yield(&mut self);
    fn emit_nop(&mut self);
    fn emit_hint(&mut self, val: u8);

    // Debug instructions
    fn emit_drps(&mut self);
    fn emit_dcps1(&mut self, val: u16);
    fn emit_dcps2(&mut self, val: u16);
    fn emit_dcps3(&mut self, val: u16);

    // System instruction
    fn emit_dc(&mut self, option: &str, src: Reg);
    fn emit_at(&mut self, option: &str, src: Reg);
    fn emit_ic(&mut self, option: &str, src: Reg);
    fn emit_tlbi(&mut self, option: &str, src: Reg);

    fn emit_sys(&mut self, imm1: u8, cn: u8, cm: u8, imm2: u8, src: Reg);
    fn emit_sysl(&mut self, dest: Reg, imm1: u8, cn: u8, cm: u8, imm2: u8);

    // Exceptiuon instructions (NOTE: these will alter the PC)
    fn emit_brk(&mut self, val: u16);
    fn emit_hlt(&mut self, val: u16);
    fn emit_hvc(&mut self, val: u16);
    fn emit_smc(&mut self, val: u16);
    fn emit_svc(&mut self, val: u16);
    fn emit_eret(&mut self);
496
}