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" }
51 $default_attr_type = "arm_attr_t";
52 $default_copy_attr = "arm_copy_attr";
55 arm_attr_t => "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);",
56 arm_SymConst_attr_t =>
57 "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n".
58 "\tinit_arm_SymConst_attributes(res, entity, symconst_offset);",
59 arm_CondJmp_attr_t => "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);",
60 arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);",
61 arm_fConst_attr_t => "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);",
62 arm_load_store_attr_t =>
63 "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n".
64 "\tinit_arm_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
65 arm_shifter_operand_t =>
66 "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n",
68 "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n",
70 "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n".
71 "\tinit_arm_farith_attributes(res, op_mode);",
73 "\tinit_arm_attributes(res, irn_flags_, in_reqs, n_res);\n".
74 "\tinit_arm_CopyB_attributes(res, size);",
78 arm_attr_t => "cmp_attr_arm",
79 arm_SymConst_attr_t => "cmp_attr_arm_SymConst",
80 arm_CondJmp_attr_t => "cmp_attr_arm_CondJmp",
81 arm_SwitchJmp_attr_t => "cmp_attr_arm_SwitchJmp",
82 arm_fConst_attr_t => "cmp_attr_arm_fConst",
83 arm_load_store_attr_t => "cmp_attr_arm_load_store",
84 arm_shifter_operand_t => "cmp_attr_arm_shifter_operand",
85 arm_CopyB_attr_t => "cmp_attr_arm_CopyB",
86 arm_cmp_attr_t => "cmp_attr_arm_cmp",
87 arm_farith_attr_t => "cmp_attr_arm_farith",
90 my %unop_shifter_operand_constructors = (
92 attr => "unsigned char immediate_value, unsigned char immediate_rot",
93 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
94 reg_req => { in => [], out => [ "gp" ] },
97 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
98 reg_req => { in => [ "gp" ], out => [ "gp" ] },
101 attr => "arm_shift_modifier_t shift_modifier",
102 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
103 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
106 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
107 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
108 reg_req => { in => [ "gp" ], out => [ "gp" ] },
112 my %binop_shifter_operand_constructors = (
114 attr => "unsigned char immediate_value, unsigned char immediate_rot",
115 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
116 reg_req => { in => [ "gp" ], out => [ "gp" ] },
120 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
121 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
122 ins => [ "left", "right" ],
125 attr => "arm_shift_modifier_t shift_modifier",
126 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
127 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "gp" ] },
128 ins => [ "left", "right", "shift" ],
131 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
132 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
133 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
134 ins => [ "left", "right" ],
138 my %cmp_shifter_operand_constructors = (
140 attr => "unsigned char immediate_value, unsigned char immediate_rot, bool ins_permuted, bool is_unsigned",
142 "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);\n".
143 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
144 reg_req => { in => [ "gp" ], out => [ "flags" ] },
148 attr => "bool ins_permuted, bool is_unsigned",
150 "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);\n".
151 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
152 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
153 ins => [ "left", "right" ],
156 attr => "arm_shift_modifier_t shift_modifier, bool ins_permuted, bool is_unsigned",
158 "init_arm_shifter_operand(res, 0, shift_modifier, 0);\n".
159 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
160 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "flags" ] },
161 ins => [ "left", "right", "shift" ],
164 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate, bool ins_permuted, bool is_unsigned",
166 "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);\n".
167 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
168 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
169 ins => [ "left", "right" ],
177 irn_flags => [ "rematerializable" ],
178 emit => 'add %D0, %S0, %O',
180 attr_type => "arm_shifter_operand_t",
181 constructors => \%binop_shifter_operand_constructors,
185 irn_flags => [ "rematerializable" ],
186 reg_req => { in => [ "gp", "gp" ], out => [ "!in_r1" ] },
187 emit => 'mul %D0, %S0, %S1',
192 irn_flags => [ "rematerializable" ],
193 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
194 emit => 'smull %D0, %D1, %S0, %S1',
195 outs => [ "low", "high" ],
199 irn_flags => [ "rematerializable" ],
200 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
201 emit =>'umull %D0, %D1, %S0, %S1',
202 outs => [ "low", "high" ],
207 irn_flags => [ "rematerializable" ],
208 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "!in_r1" ] },
209 emit =>'mla %D0, %S0, %S1, %S2',
214 irn_flags => [ "rematerializable" ],
215 emit => 'and %D0, %S0, %O',
217 attr_type => "arm_shifter_operand_t",
218 constructors => \%binop_shifter_operand_constructors,
222 irn_flags => [ "rematerializable" ],
223 emit => 'orr %D0, %S0, %O',
225 attr_type => "arm_shifter_operand_t",
226 constructors => \%binop_shifter_operand_constructors,
230 irn_flags => [ "rematerializable" ],
231 emit => 'eor %D0, %S0, %O',
233 attr_type => "arm_shifter_operand_t",
234 constructors => \%binop_shifter_operand_constructors,
238 irn_flags => [ "rematerializable" ],
239 emit => 'bic %D0, %S0, %O',
241 attr_type => "arm_shifter_operand_t",
242 constructors => \%binop_shifter_operand_constructors,
246 irn_flags => [ "rematerializable" ],
247 emit => 'sub %D0, %S0, %O',
249 attr_type => "arm_shifter_operand_t",
250 constructors => \%binop_shifter_operand_constructors,
254 irn_flags => [ "rematerializable" ],
255 emit => 'rsb %D0, %S0, %O',
257 attr_type => "arm_shifter_operand_t",
258 constructors => \%binop_shifter_operand_constructors,
262 irn_flags => [ "rematerializable" ],
264 emit => 'mov %D0, %O',
266 attr_type => "arm_shifter_operand_t",
267 constructors => \%unop_shifter_operand_constructors,
271 irn_flags => [ "rematerializable" ],
272 attr_type => "arm_shifter_operand_t",
274 emit => 'mvn %D0, %O',
276 constructors => \%unop_shifter_operand_constructors,
280 irn_flags => [ "rematerializable" ],
281 reg_req => { in => [ "gp" ], out => [ "gp" ] },
282 emit => 'clz %D0, %S0',
286 # mov lr, pc\n mov pc, XXX -- This combination is used for calls to function
289 state => "exc_pinned",
291 out_arity => "variable",
292 attr_type => "arm_shifter_operand_t",
293 attr => "arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot",
294 custominit => "init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);\n".
295 "\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);",
296 emit => "mov lr, pc\n".
300 # mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function
303 state => "exc_pinned",
305 out_arity => "variable",
306 attr_type => "arm_load_store_attr_t",
307 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
308 custominit => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);",
309 emit => "mov lr, pc\n".
314 state => "exc_pinned",
316 out_arity => "variable",
317 attr_type => "arm_SymConst_attr_t",
318 attr => "ir_entity *entity, int symconst_offset",
319 custominit => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);",
323 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
325 op_flags => [ "constlike" ],
326 irn_flags => [ "rematerializable" ],
327 reg_req => { out => [ "gp" ] },
328 emit => '/* %D0 now available for calculations */',
329 cmp_attr => 'return 1;',
335 attr => "unsigned size",
336 attr_type => "arm_CopyB_attr_t",
337 reg_req => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] },
342 op_flags => [ "constlike" ],
343 irn_flags => [ "rematerializable" ],
344 attr => "ir_entity *entity, int symconst_offset",
345 reg_req => { in => [ "gp" ], out => [ "gp" ] },
347 attr_type => "arm_SymConst_attr_t",
352 op_flags => [ "constlike" ],
353 irn_flags => [ "rematerializable" ],
354 attr => "ir_entity *entity, int symconst_offset",
355 reg_req => { out => [ "gp" ] },
356 attr_type => "arm_SymConst_attr_t",
361 irn_flags => [ "rematerializable", "modify_flags" ],
362 emit => 'cmp %S0, %O',
364 attr_type => "arm_cmp_attr_t",
365 constructors => \%cmp_shifter_operand_constructors,
369 irn_flags => [ "rematerializable", "modify_flags" ],
370 emit => 'tst %S0, %O',
372 attr_type => "arm_cmp_attr_t",
373 constructors => \%cmp_shifter_operand_constructors,
377 op_flags => [ "cfopcode", "forking" ],
380 reg_req => { in => [ "flags" ], out => [ "none", "none" ] },
381 attr => "ir_relation relation",
382 attr_type => "arm_CondJmp_attr_t",
383 init_attr => "\tset_arm_CondJmp_relation(res, relation);",
388 op_flags => [ "cfopcode" ],
389 irn_flags => [ "simple_jump" ],
390 reg_req => { out => [ "none" ] },
395 op_flags => [ "cfopcode", "forking" ],
398 attr => "const ir_switch_table *table",
399 init_attr => "init_arm_SwitchJmp_attributes(res, table);",
400 reg_req => { in => [ "gp" ], out => [ "none" ] },
401 out_arity => "variable",
402 attr_type => "arm_SwitchJmp_attr_t",
406 op_flags => [ "uses_memory" ],
407 state => "exc_pinned",
408 ins => [ "ptr", "mem" ],
409 outs => [ "res", "M" ],
410 reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
411 emit => 'ldr%ML %D0, [%S0, #%o]',
412 attr_type => "arm_load_store_attr_t",
413 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
417 op_flags => [ "uses_memory" ],
418 state => "exc_pinned",
419 ins => [ "ptr", "val", "mem" ],
421 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
422 emit => 'str%MS %S1, [%S0, #%o]',
424 attr_type => "arm_load_store_attr_t",
425 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
429 op_flags => [ "uses_memory" ],
430 irn_flags => [ "rematerializable" ],
431 state => "exc_pinned",
432 reg_req => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
433 emit => 'stmfd %S0!, {%S1, %S2, %S3, %S4}',
434 outs => [ "ptr", "M" ],
437 LoadStackM3Epilogue => {
438 op_flags => [ "uses_memory" ],
439 irn_flags => [ "rematerializable" ],
440 state => "exc_pinned",
441 reg_req => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
442 emit => 'ldmfd %S0, {%D0, %D1, %D2}',
443 outs => [ "res0", "res1", "res2", "M" ],
449 irn_flags => [ "rematerializable" ],
450 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
451 emit => 'adf%MA %D0, %S0, %S1',
452 attr_type => "arm_farith_attr_t",
453 attr => "ir_mode *op_mode",
458 irn_flags => [ "rematerializable" ],
459 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
460 emit => 'muf%MA %D0, %S0, %S1',
461 attr_type => "arm_farith_attr_t",
462 attr => "ir_mode *op_mode",
467 irn_flags => [ "rematerializable" ],
468 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
469 emit => 'suf%MA %D0, %S0, %S1',
470 attr_type => "arm_farith_attr_t",
471 attr => "ir_mode *op_mode",
476 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
477 emit => 'dvf%MA %D0, %S0, %S1',
478 outs => [ "res", "M" ],
479 attr_type => "arm_farith_attr_t",
480 attr => "ir_mode *op_mode",
485 irn_flags => [ "rematerializable" ],
486 reg_req => { in => [ "fpa" ], out => [ "fpa" ] },
487 emit => 'mvf%MA %S0, %D0',
488 attr_type => "arm_farith_attr_t",
489 attr => "ir_mode *op_mode",
494 irn_flags => [ "rematerializable" ],
495 reg_req => { in => [ "gp" ], out => [ "fpa" ] },
496 emit => 'flt%MA %D0, %S0',
497 attr_type => "arm_farith_attr_t",
498 attr => "ir_mode *op_mode",
503 irn_flags => [ "rematerializable", "modify_flags" ],
505 attr_type => "arm_cmp_attr_t",
506 attr => "bool ins_permuted",
507 init_attr => "init_arm_cmp_attr(res, ins_permuted, false);",
508 reg_req => { in => [ "fpa", "fpa" ], out => [ "flags" ] },
509 emit => 'cmfe %S0, %S1',
513 op_flags => [ "uses_memory" ],
514 state => "exc_pinned",
515 ins => [ "ptr", "mem" ],
516 outs => [ "res", "M" ],
517 reg_req => { in => [ "gp", "none" ], out => [ "fpa", "none" ] },
518 emit => 'ldf%MF %D0, [%S0, #%o]',
519 attr_type => "arm_load_store_attr_t",
520 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
524 op_flags => [ "uses_memory" ],
525 state => "exc_pinned",
526 ins => [ "ptr", "val", "mem" ],
529 reg_req => { in => [ "gp", "fpa", "none" ], out => [ "none" ] },
530 emit => 'stf%MF %S1, [%S0, #%o]',
531 attr_type => "arm_load_store_attr_t",
532 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
536 # floating point constants
539 op_flags => [ "constlike" ],
540 irn_flags => [ "rematerializable" ],
541 attr => "ir_tarval *tv",
542 init_attr => "attr->tv = tv;",
543 mode => "get_tarval_mode(tv)",
544 reg_req => { out => [ "fpa" ] },
545 attr_type => "arm_fConst_attr_t",