1 # Arm Architecure Specification
2 # Author: Matthias Braun, Michael Beck, Oliver Richter, Tobias Gneist
10 $mode_flags = "mode_Bu";
13 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
16 { name => "r0", dwarf => 0 },
17 { name => "r1", dwarf => 1 },
18 { name => "r2", dwarf => 2 },
19 { name => "r3", dwarf => 3 },
20 { name => "r4", dwarf => 4 },
21 { name => "r5", dwarf => 5 },
22 { name => "r6", dwarf => 6 },
23 { name => "r7", dwarf => 7 },
24 { name => "r8", dwarf => 8 },
25 { name => "r9", dwarf => 9 },
26 { name => "r10", dwarf => 10 },
27 { name => "r11", dwarf => 11 },
28 { name => "r12", dwarf => 12 },
29 { name => "sp", dwarf => 13 },
30 { name => "lr", dwarf => 14 },
31 { name => "pc", dwarf => 15 },
35 { name => "f0", dwarf => 96 },
36 { name => "f1", dwarf => 97 },
37 { name => "f2", dwarf => 98 },
38 { name => "f3", dwarf => 99 },
39 { name => "f4", dwarf => 100 },
40 { name => "f5", dwarf => 101 },
41 { name => "f6", dwarf => 102 },
42 { name => "f7", dwarf => 103 },
47 { mode => $mode_flags, flags => "manual_ra" }
52 FM => "${arch}_emit_float_load_store_mode(node);",
53 AM => "${arch}_emit_float_arithmetic_mode(node);",
54 LM => "${arch}_emit_load_mode(node);",
55 SM => "${arch}_emit_store_mode(node);",
56 SO => "${arch}_emit_shifter_operand(node);",
57 S0 => "${arch}_emit_source_register(node, 0);",
58 SC => "${arch}_emit_symconst(node);",
59 S1 => "${arch}_emit_source_register(node, 1);",
60 S2 => "${arch}_emit_source_register(node, 2);",
61 S3 => "${arch}_emit_source_register(node, 3);",
62 S4 => "${arch}_emit_source_register(node, 4);",
63 D0 => "${arch}_emit_dest_register(node, 0);",
64 D1 => "${arch}_emit_dest_register(node, 1);",
65 D2 => "${arch}_emit_dest_register(node, 2);",
66 O => "${arch}_emit_offset(node);",
69 $default_attr_type = "arm_attr_t";
70 $default_copy_attr = "arm_copy_attr";
73 arm_attr_t => "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);",
74 arm_SymConst_attr_t =>
75 "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n".
76 "\tinit_arm_SymConst_attributes(res, entity, symconst_offset);",
77 arm_CondJmp_attr_t => "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);",
78 arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);",
79 arm_fConst_attr_t => "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);",
80 arm_load_store_attr_t =>
81 "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n".
82 "\tinit_arm_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
83 arm_shifter_operand_t =>
84 "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n",
86 "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n",
88 "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n".
89 "\tinit_arm_farith_attributes(res, op_mode);",
91 "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n".
92 "\tinit_arm_CopyB_attributes(res, size);",
96 arm_attr_t => "cmp_attr_arm",
97 arm_SymConst_attr_t => "cmp_attr_arm_SymConst",
98 arm_CondJmp_attr_t => "cmp_attr_arm_CondJmp",
99 arm_SwitchJmp_attr_t => "cmp_attr_arm_SwitchJmp",
100 arm_fConst_attr_t => "cmp_attr_arm_fConst",
101 arm_load_store_attr_t => "cmp_attr_arm_load_store",
102 arm_shifter_operand_t => "cmp_attr_arm_shifter_operand",
103 arm_CopyB_attr_t => "cmp_attr_arm_CopyB",
104 arm_cmp_attr_t => "cmp_attr_arm_cmp",
105 arm_farith_attr_t => "cmp_attr_arm_farith",
108 my %unop_shifter_operand_constructors = (
110 attr => "unsigned char immediate_value, unsigned char immediate_rot",
111 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
112 reg_req => { in => [], out => [ "gp" ] },
115 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
116 reg_req => { in => [ "gp" ], out => [ "gp" ] },
119 attr => "arm_shift_modifier_t shift_modifier",
120 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
121 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
124 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
125 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
126 reg_req => { in => [ "gp" ], out => [ "gp" ] },
130 my %binop_shifter_operand_constructors = (
132 attr => "unsigned char immediate_value, unsigned char immediate_rot",
133 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
134 reg_req => { in => [ "gp" ], out => [ "gp" ] },
138 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
139 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
140 ins => [ "left", "right" ],
143 attr => "arm_shift_modifier_t shift_modifier",
144 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
145 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "gp" ] },
146 ins => [ "left", "right", "shift" ],
149 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
150 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
151 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
152 ins => [ "left", "right" ],
156 my %cmp_shifter_operand_constructors = (
158 attr => "unsigned char immediate_value, unsigned char immediate_rot, bool ins_permuted, bool is_unsigned",
160 "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);\n".
161 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
162 reg_req => { in => [ "gp" ], out => [ "flags" ] },
166 attr => "bool ins_permuted, bool is_unsigned",
168 "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);\n".
169 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
170 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
171 ins => [ "left", "right" ],
174 attr => "arm_shift_modifier_t shift_modifier, bool ins_permuted, bool is_unsigned",
176 "init_arm_shifter_operand(res, 0, shift_modifier, 0);\n".
177 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
178 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "flags" ] },
179 ins => [ "left", "right", "shift" ],
182 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate, bool ins_permuted, bool is_unsigned",
184 "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);\n".
185 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
186 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
187 ins => [ "left", "right" ],
195 irn_flags => [ "rematerializable" ],
196 emit => '. add %D0, %S0, %SO',
198 attr_type => "arm_shifter_operand_t",
199 constructors => \%binop_shifter_operand_constructors,
203 irn_flags => [ "rematerializable" ],
204 reg_req => { in => [ "gp", "gp" ], out => [ "!in_r1" ] },
205 emit =>'. mul %D0, %S0, %S1',
210 irn_flags => [ "rematerializable" ],
211 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
212 emit =>'. smull %D0, %D1, %S0, %S1',
213 outs => [ "low", "high" ],
217 irn_flags => [ "rematerializable" ],
218 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
219 emit =>'. umull %D0, %D1, %S0, %S1',
220 outs => [ "low", "high" ],
225 irn_flags => [ "rematerializable" ],
226 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "!in_r1" ] },
227 emit =>'. mla %D0, %S0, %S1, %S2',
232 irn_flags => [ "rematerializable" ],
233 emit => '. and %D0, %S0, %SO',
235 attr_type => "arm_shifter_operand_t",
236 constructors => \%binop_shifter_operand_constructors,
240 irn_flags => [ "rematerializable" ],
241 emit => '. orr %D0, %S0, %SO',
243 attr_type => "arm_shifter_operand_t",
244 constructors => \%binop_shifter_operand_constructors,
248 irn_flags => [ "rematerializable" ],
249 emit => '. eor %D0, %S0, %SO',
251 attr_type => "arm_shifter_operand_t",
252 constructors => \%binop_shifter_operand_constructors,
256 irn_flags => [ "rematerializable" ],
257 emit => '. bic %D0, %S0, %SO',
259 attr_type => "arm_shifter_operand_t",
260 constructors => \%binop_shifter_operand_constructors,
264 irn_flags => [ "rematerializable" ],
265 emit => '. sub %D0, %S0, %SO',
267 attr_type => "arm_shifter_operand_t",
268 constructors => \%binop_shifter_operand_constructors,
272 irn_flags => [ "rematerializable" ],
273 emit => '. rsb %D0, %S0, %SO',
275 attr_type => "arm_shifter_operand_t",
276 constructors => \%binop_shifter_operand_constructors,
280 irn_flags => [ "rematerializable" ],
282 emit => '. mov %D0, %SO',
284 attr_type => "arm_shifter_operand_t",
285 constructors => \%unop_shifter_operand_constructors,
289 irn_flags => [ "rematerializable" ],
290 attr_type => "arm_shifter_operand_t",
292 emit => '. mvn %D0, %SO',
294 constructors => \%unop_shifter_operand_constructors,
298 irn_flags => [ "rematerializable" ],
299 reg_req => { in => [ "gp" ], out => [ "gp" ] },
300 emit =>'. clz %D0, %S0',
304 # mov lr, pc\n mov pc, XXX -- This combination is used for calls to function
307 state => "exc_pinned",
309 out_arity => "variable",
310 attr_type => "arm_shifter_operand_t",
311 attr => "arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot",
312 custominit => "init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);\n".
313 "\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);",
314 emit => ". mov lr, pc\n".
318 # mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function
321 state => "exc_pinned",
323 out_arity => "variable",
324 attr_type => "arm_load_store_attr_t",
325 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
326 custominit => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);",
327 emit => ". mov lr, pc\n".
332 state => "exc_pinned",
334 out_arity => "variable",
335 attr_type => "arm_SymConst_attr_t",
336 attr => "ir_entity *entity, int symconst_offset",
337 custominit => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);",
341 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
343 op_flags => [ "constlike" ],
344 irn_flags => [ "rematerializable" ],
345 reg_req => { out => [ "gp" ] },
346 emit => '. /* %D0 now available for calculations */',
347 cmp_attr => 'return 1;',
353 attr => "unsigned size",
354 attr_type => "arm_CopyB_attr_t",
355 reg_req => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] },
360 op_flags => [ "constlike" ],
361 irn_flags => [ "rematerializable" ],
362 attr => "ir_entity *entity, int symconst_offset",
363 reg_req => { in => [ "gp" ], out => [ "gp" ] },
365 attr_type => "arm_SymConst_attr_t",
370 op_flags => [ "constlike" ],
371 irn_flags => [ "rematerializable" ],
372 attr => "ir_entity *entity, int symconst_offset",
373 reg_req => { out => [ "gp" ] },
374 attr_type => "arm_SymConst_attr_t",
379 irn_flags => [ "rematerializable", "modify_flags" ],
380 emit => '. cmp %S0, %SO',
382 attr_type => "arm_cmp_attr_t",
383 constructors => \%cmp_shifter_operand_constructors,
387 irn_flags => [ "rematerializable", "modify_flags" ],
388 emit => '. tst %S0, %SO',
390 attr_type => "arm_cmp_attr_t",
391 constructors => \%cmp_shifter_operand_constructors,
395 op_flags => [ "cfopcode", "forking" ],
398 reg_req => { in => [ "flags" ], out => [ "none", "none" ] },
399 attr => "ir_relation relation",
400 attr_type => "arm_CondJmp_attr_t",
401 init_attr => "\tset_arm_CondJmp_relation(res, relation);",
406 op_flags => [ "cfopcode" ],
407 irn_flags => [ "simple_jump" ],
408 reg_req => { out => [ "none" ] },
413 op_flags => [ "cfopcode", "forking" ],
416 attr => "const ir_switch_table *table",
417 init_attr => "init_arm_SwitchJmp_attributes(res, table);",
418 reg_req => { in => [ "gp" ], out => [ "none" ] },
419 out_arity => "variable",
420 attr_type => "arm_SwitchJmp_attr_t",
424 op_flags => [ "uses_memory" ],
425 state => "exc_pinned",
426 ins => [ "ptr", "mem" ],
427 outs => [ "res", "M" ],
428 reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
429 emit => '. ldr%LM %D0, [%S0, #%O]',
430 attr_type => "arm_load_store_attr_t",
431 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
435 op_flags => [ "uses_memory" ],
436 state => "exc_pinned",
437 ins => [ "ptr", "val", "mem" ],
439 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
440 emit => '. str%SM %S1, [%S0, #%O]',
442 attr_type => "arm_load_store_attr_t",
443 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
447 op_flags => [ "uses_memory" ],
448 irn_flags => [ "rematerializable" ],
449 state => "exc_pinned",
450 reg_req => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
451 emit => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
452 outs => [ "ptr", "M" ],
455 LoadStackM3Epilogue => {
456 op_flags => [ "uses_memory" ],
457 irn_flags => [ "rematerializable" ],
458 state => "exc_pinned",
459 reg_req => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
460 emit => '. ldmfd %S0, {%D0, %D1, %D2}',
461 outs => [ "res0", "res1", "res2", "M" ],
467 irn_flags => [ "rematerializable" ],
468 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
469 emit => '. adf%AM %D0, %S0, %S1',
470 attr_type => "arm_farith_attr_t",
471 attr => "ir_mode *op_mode",
476 irn_flags => [ "rematerializable" ],
477 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
478 emit =>'. muf%AM %D0, %S0, %S1',
479 attr_type => "arm_farith_attr_t",
480 attr => "ir_mode *op_mode",
485 irn_flags => [ "rematerializable" ],
486 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
487 emit => '. suf%AM %D0, %S0, %S1',
488 attr_type => "arm_farith_attr_t",
489 attr => "ir_mode *op_mode",
494 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
495 emit =>'. dvf%AM %D0, %S0, %S1',
496 outs => [ "res", "M" ],
497 attr_type => "arm_farith_attr_t",
498 attr => "ir_mode *op_mode",
503 irn_flags => [ "rematerializable" ],
504 reg_req => { in => [ "fpa" ], out => [ "fpa" ] },
505 emit => '. mvf%AM %S0, %D0',
506 attr_type => "arm_farith_attr_t",
507 attr => "ir_mode *op_mode",
512 irn_flags => [ "rematerializable" ],
513 reg_req => { in => [ "gp" ], out => [ "fpa" ] },
514 emit => '. flt%AM %D0, %S0',
515 attr_type => "arm_farith_attr_t",
516 attr => "ir_mode *op_mode",
521 irn_flags => [ "rematerializable", "modify_flags" ],
523 attr_type => "arm_cmp_attr_t",
524 attr => "bool ins_permuted",
525 init_attr => "init_arm_cmp_attr(res, ins_permuted, false);",
526 reg_req => { in => [ "fpa", "fpa" ], out => [ "flags" ] },
527 emit => '. cmfe %S0, %S1',
531 op_flags => [ "uses_memory" ],
532 state => "exc_pinned",
533 ins => [ "ptr", "mem" ],
534 outs => [ "res", "M" ],
535 reg_req => { in => [ "gp", "none" ], out => [ "fpa", "none" ] },
536 emit => '. ldf%FM %D0, [%S0, #%O]',
537 attr_type => "arm_load_store_attr_t",
538 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
542 op_flags => [ "uses_memory" ],
543 state => "exc_pinned",
544 ins => [ "ptr", "val", "mem" ],
547 reg_req => { in => [ "gp", "fpa", "none" ], out => [ "none" ] },
548 emit => '. stf%FM %S1, [%S0, #%O]',
549 attr_type => "arm_load_store_attr_t",
550 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
554 # floating point constants
557 op_flags => [ "constlike" ],
558 irn_flags => [ "rematerializable" ],
559 attr => "ir_tarval *tv",
560 init_attr => "attr->tv = tv;",
561 mode => "get_tarval_mode(tv)",
562 reg_req => { out => [ "fpa" ] },
563 attr_type => "arm_fConst_attr_t",