2 # Arm Architecure Specification
3 # Author: Matthias Braun, Michael Beck, Oliver Richter, Tobias Gneist
12 $mode_flags = "mode_Bu";
16 $normal = 0; # no special type
17 $caller_save = 1; # caller save (register must be saved by the caller of a function)
18 $callee_save = 2; # callee save (register must be saved by the called function)
19 $ignore = 4; # ignore (do not assign this register)
20 $arbitrary = 8; # emitter can choose an arbitrary register of this class
21 $virtual = 16; # the register is a virtual one
22 $state = 32; # register represents a state
23 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
26 { name => "r0", type => $caller_save },
27 { name => "r1", type => $caller_save },
28 { name => "r2", type => $caller_save },
29 { name => "r3", type => $caller_save },
30 { name => "r4", type => $callee_save },
31 { name => "r5", type => $callee_save },
32 { name => "r6", type => $callee_save },
33 { name => "r7", type => $callee_save },
34 { name => "r8", type => $callee_save },
35 { name => "r9", type => $callee_save },
36 { name => "r10", type => $callee_save },
37 { name => "r11", type => $callee_save },
38 { name => "r12", type => $ignore }, # reserved for linker/immediate fixups
39 { name => "sp", type => $ignore }, # this is our stack pointer
40 { name => "lr", type => $callee_save | $caller_save }, # this is our return address
41 { name => "pc", type => $ignore }, # this is our program counter
45 { name => "f0", type => $caller_save },
46 { name => "f1", type => $caller_save },
47 { name => "f2", type => $caller_save },
48 { name => "f3", type => $caller_save },
49 { name => "f4", type => $caller_save },
50 { name => "f5", type => $caller_save },
51 { name => "f6", type => $caller_save },
52 { name => "f7", type => $caller_save },
56 { name => "fl", type => 0 },
57 { mode => $mode_flags, flags => "manual_ra" }
62 FM => "${arch}_emit_float_load_store_mode(node);",
63 AM => "${arch}_emit_float_arithmetic_mode(node);",
64 LM => "${arch}_emit_load_mode(node);",
65 SM => "${arch}_emit_store_mode(node);",
66 SO => "${arch}_emit_shifter_operand(node);",
67 S0 => "${arch}_emit_source_register(node, 0);",
68 SC => "${arch}_emit_symconst(node);",
69 S1 => "${arch}_emit_source_register(node, 1);",
70 S2 => "${arch}_emit_source_register(node, 2);",
71 S3 => "${arch}_emit_source_register(node, 3);",
72 S4 => "${arch}_emit_source_register(node, 4);",
73 D0 => "${arch}_emit_dest_register(node, 0);",
74 D1 => "${arch}_emit_dest_register(node, 1);",
75 D2 => "${arch}_emit_dest_register(node, 2);",
76 O => "${arch}_emit_offset(node);",
79 $default_attr_type = "arm_attr_t";
80 $default_copy_attr = "arm_copy_attr";
83 arm_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
84 arm_SymConst_attr_t =>
85 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
86 "\tinit_arm_SymConst_attributes(res, entity, symconst_offset);",
87 arm_CondJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
88 arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
89 arm_fConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
90 arm_load_store_attr_t =>
91 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
92 "\tinit_arm_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
93 arm_shifter_operand_t =>
94 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n",
96 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n",
98 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
99 "\tinit_arm_farith_attributes(res, op_mode);",
101 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
102 "\tinit_arm_CopyB_attributes(res, size);",
106 arm_attr_t => "cmp_attr_arm",
107 arm_SymConst_attr_t => "cmp_attr_arm_SymConst",
108 arm_CondJmp_attr_t => "cmp_attr_arm_CondJmp",
109 arm_SwitchJmp_attr_t => "cmp_attr_arm_SwitchJmp",
110 arm_fConst_attr_t => "cmp_attr_arm_fConst",
111 arm_load_store_attr_t => "cmp_attr_arm_load_store",
112 arm_shifter_operand_t => "cmp_attr_arm_shifter_operand",
113 arm_CopyB_attr_t => "cmp_attr_arm_CopyB",
114 arm_cmp_attr_t => "cmp_attr_arm_cmp",
115 arm_farith_attr_t => "cmp_attr_arm_farith",
118 my %unop_shifter_operand_constructors = (
120 attr => "unsigned char immediate_value, unsigned char immediate_rot",
121 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
122 reg_req => { in => [], out => [ "gp" ] },
125 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
126 reg_req => { in => [ "gp" ], out => [ "gp" ] },
129 attr => "arm_shift_modifier_t shift_modifier",
130 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
131 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
134 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
135 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
136 reg_req => { in => [ "gp" ], out => [ "gp" ] },
140 my %binop_shifter_operand_constructors = (
142 attr => "unsigned char immediate_value, unsigned char immediate_rot",
143 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
144 reg_req => { in => [ "gp" ], out => [ "gp" ] },
148 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
149 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
150 ins => [ "left", "right" ],
153 attr => "arm_shift_modifier_t shift_modifier",
154 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
155 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "gp" ] },
156 ins => [ "left", "right", "shift" ],
159 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
160 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
161 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
162 ins => [ "left", "right" ],
166 my %cmp_shifter_operand_constructors = (
168 attr => "unsigned char immediate_value, unsigned char immediate_rot, bool ins_permuted, bool is_unsigned",
170 "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);\n".
171 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
172 reg_req => { in => [ "gp" ], out => [ "flags" ] },
176 attr => "bool ins_permuted, bool is_unsigned",
178 "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);\n".
179 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
180 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
181 ins => [ "left", "right" ],
184 attr => "arm_shift_modifier_t shift_modifier, bool ins_permuted, bool is_unsigned",
186 "init_arm_shifter_operand(res, 0, shift_modifier, 0);\n".
187 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
188 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "flags" ] },
189 ins => [ "left", "right", "shift" ],
192 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate, bool ins_permuted, bool is_unsigned",
194 "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);\n".
195 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
196 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
197 ins => [ "left", "right" ],
205 irn_flags => [ "rematerializable" ],
206 emit => '. add %D0, %S0, %SO',
208 attr_type => "arm_shifter_operand_t",
209 constructors => \%binop_shifter_operand_constructors,
213 irn_flags => [ "rematerializable" ],
214 reg_req => { in => [ "gp", "gp" ], out => [ "!in_r1" ] },
215 emit =>'. mul %D0, %S0, %S1',
220 irn_flags => [ "rematerializable" ],
221 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
222 emit =>'. smull %D0, %D1, %S0, %S1',
223 outs => [ "low", "high" ],
227 irn_flags => [ "rematerializable" ],
228 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
229 emit =>'. umull %D0, %D1, %S0, %S1',
230 outs => [ "low", "high" ],
235 irn_flags => [ "rematerializable" ],
236 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "!in_r1" ] },
237 emit =>'. mla %D0, %S0, %S1, %S2',
242 irn_flags => [ "rematerializable" ],
243 emit => '. and %D0, %S0, %SO',
245 attr_type => "arm_shifter_operand_t",
246 constructors => \%binop_shifter_operand_constructors,
250 irn_flags => [ "rematerializable" ],
251 emit => '. orr %D0, %S0, %SO',
253 attr_type => "arm_shifter_operand_t",
254 constructors => \%binop_shifter_operand_constructors,
258 irn_flags => [ "rematerializable" ],
259 emit => '. eor %D0, %S0, %SO',
261 attr_type => "arm_shifter_operand_t",
262 constructors => \%binop_shifter_operand_constructors,
266 irn_flags => [ "rematerializable" ],
267 emit => '. bic %D0, %S0, %SO',
269 attr_type => "arm_shifter_operand_t",
270 constructors => \%binop_shifter_operand_constructors,
274 irn_flags => [ "rematerializable" ],
275 emit => '. sub %D0, %S0, %SO',
277 attr_type => "arm_shifter_operand_t",
278 constructors => \%binop_shifter_operand_constructors,
282 irn_flags => [ "rematerializable" ],
283 emit => '. rsb %D0, %S0, %SO',
285 attr_type => "arm_shifter_operand_t",
286 constructors => \%binop_shifter_operand_constructors,
290 irn_flags => [ "rematerializable" ],
292 emit => '. mov %D0, %SO',
294 attr_type => "arm_shifter_operand_t",
295 constructors => \%unop_shifter_operand_constructors,
299 irn_flags => [ "rematerializable" ],
300 attr_type => "arm_shifter_operand_t",
302 emit => '. mvn %D0, %SO',
304 constructors => \%unop_shifter_operand_constructors,
307 # mov lr, pc\n mov pc, XXX -- This combination is used for calls to function
310 state => "exc_pinned",
312 out_arity => "variable",
313 attr_type => "arm_shifter_operand_t",
314 attr => "arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot",
315 custominit => "init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);\n".
316 "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);",
317 emit => ". mov lr, pc\n".
322 # mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function
325 state => "exc_pinned",
327 out_arity => "variable",
328 attr_type => "arm_load_store_attr_t",
329 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
330 custominit => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);",
331 emit => ". mov lr, pc\n".
337 state => "exc_pinned",
339 out_arity => "variable",
340 attr_type => "arm_SymConst_attr_t",
341 attr => "ir_entity *entity, int symconst_offset",
342 custominit => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);",
347 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
349 op_flags => [ "constlike" ],
350 irn_flags => [ "rematerializable" ],
351 reg_req => { out => [ "gp" ] },
352 emit => '. /* %D0 now available for calculations */',
353 cmp_attr => 'return 1;',
358 op_flags => [ "fragile" ],
360 attr => "unsigned size",
361 attr_type => "arm_CopyB_attr_t",
362 reg_req => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] },
367 op_flags => [ "constlike" ],
368 irn_flags => [ "rematerializable" ],
369 attr => "ir_entity *entity, int symconst_offset",
370 reg_req => { in => [ "gp" ], out => [ "gp" ] },
372 attr_type => "arm_SymConst_attr_t",
377 op_flags => [ "constlike" ],
378 irn_flags => [ "rematerializable" ],
379 attr => "ir_entity *entity, int symconst_offset",
380 reg_req => { out => [ "gp" ] },
381 attr_type => "arm_SymConst_attr_t",
386 irn_flags => [ "rematerializable", "modify_flags" ],
387 emit => '. cmp %S0, %SO',
389 attr_type => "arm_cmp_attr_t",
390 constructors => \%cmp_shifter_operand_constructors,
394 irn_flags => [ "rematerializable", "modify_flags" ],
395 emit => '. tst %S0, %SO',
397 attr_type => "arm_cmp_attr_t",
398 constructors => \%cmp_shifter_operand_constructors,
402 op_flags => [ "labeled", "cfopcode", "forking" ],
405 reg_req => { in => [ "flags" ], out => [ "none", "none" ] },
406 attr => "pn_Cmp pnc",
407 attr_type => "arm_CondJmp_attr_t",
408 init_attr => "\tset_arm_CondJmp_pnc(res, pnc);",
413 op_flags => [ "cfopcode" ],
414 irn_flags => [ "simple_jump" ],
415 reg_req => { out => [ "none" ] },
420 op_flags => [ "labeled", "cfopcode", "forking" ],
423 attr => "int n_projs, long def_proj_num",
424 init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n".
425 "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);",
426 reg_req => { in => [ "gp" ], out => [ "none" ] },
427 attr_type => "arm_SwitchJmp_attr_t",
431 op_flags => [ "labeled", "fragile" ],
432 state => "exc_pinned",
433 ins => [ "ptr", "mem" ],
434 outs => [ "res", "M" ],
435 reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
436 emit => '. ldr%LM %D0, [%S0, #%O]',
437 attr_type => "arm_load_store_attr_t",
438 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
442 op_flags => [ "labeled", "fragile" ],
443 state => "exc_pinned",
444 ins => [ "ptr", "val", "mem" ],
446 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
447 emit => '. str%SM %S1, [%S0, #%O]',
449 attr_type => "arm_load_store_attr_t",
450 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
454 op_flags => [ "labeled", "fragile" ],
455 irn_flags => [ "rematerializable" ],
456 state => "exc_pinned",
457 reg_req => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
458 emit => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
459 outs => [ "ptr", "M" ],
462 LoadStackM3Epilogue => {
463 op_flags => [ "labeled", "fragile" ],
464 irn_flags => [ "rematerializable" ],
465 state => "exc_pinned",
466 reg_req => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
467 emit => '. ldmfd %S0, {%D0, %D1, %D2}',
468 outs => [ "res0", "res1", "res2", "M" ],
474 irn_flags => [ "rematerializable" ],
475 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
476 emit => '. adf%AM %D0, %S0, %S1',
477 attr_type => "arm_farith_attr_t",
478 attr => "ir_mode *op_mode",
483 irn_flags => [ "rematerializable" ],
484 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
485 emit =>'. muf%AM %D0, %S0, %S1',
486 attr_type => "arm_farith_attr_t",
487 attr => "ir_mode *op_mode",
492 irn_flags => [ "rematerializable" ],
493 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
494 emit => '. suf%AM %D0, %S0, %S1',
495 attr_type => "arm_farith_attr_t",
496 attr => "ir_mode *op_mode",
501 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
502 emit =>'. dvf%AM %D0, %S0, %S1',
503 outs => [ "res", "M" ],
504 attr_type => "arm_farith_attr_t",
505 attr => "ir_mode *op_mode",
510 irn_flags => [ "rematerializable" ],
511 reg_req => { in => [ "fpa" ], out => [ "fpa" ] },
512 emit => '. mvf%AM %S0, %D0',
513 attr_type => "arm_farith_attr_t",
514 attr => "ir_mode *op_mode",
519 irn_flags => [ "rematerializable" ],
520 reg_req => { in => [ "gp" ], out => [ "fpa" ] },
521 emit => '. flt%AM %D0, %S0',
522 attr_type => "arm_farith_attr_t",
523 attr => "ir_mode *op_mode",
528 irn_flags => [ "rematerializable", "modify_flags" ],
530 attr_type => "arm_cmp_attr_t",
531 attr => "bool ins_permuted",
532 init_attr => "init_arm_cmp_attr(res, ins_permuted, false);",
533 reg_req => { in => [ "fpa", "fpa" ], out => [ "flags" ] },
534 emit => '. cmfe %S0, %S1',
538 op_flags => [ "labeled", "fragile" ],
539 state => "exc_pinned",
540 ins => [ "ptr", "mem" ],
541 outs => [ "res", "M" ],
542 reg_req => { in => [ "gp", "none" ], out => [ "fpa", "none" ] },
543 emit => '. ldf%FM %D0, [%S0, #%O]',
544 attr_type => "arm_load_store_attr_t",
545 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
549 op_flags => [ "labeled", "fragile" ],
550 state => "exc_pinned",
551 ins => [ "ptr", "val", "mem" ],
554 reg_req => { in => [ "gp", "fpa", "none" ], out => [ "none" ] },
555 emit => '. stf%FM %S1, [%S0, #%O]',
556 attr_type => "arm_load_store_attr_t",
557 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
561 # floating point constants
564 op_flags => [ "constlike" ],
565 irn_flags => [ "rematerializable" ],
566 attr => "tarval *tv",
567 init_attr => "attr->tv = tv;",
568 mode => "get_tarval_mode(tv)",
569 reg_req => { out => [ "fpa" ] },
570 attr_type => "arm_fConst_attr_t",