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" ],
263 emit => 'mov %D0, %O',
265 attr_type => "arm_shifter_operand_t",
266 constructors => \%unop_shifter_operand_constructors,
270 irn_flags => [ "rematerializable" ],
271 attr_type => "arm_shifter_operand_t",
272 emit => 'mvn %D0, %O',
274 constructors => \%unop_shifter_operand_constructors,
278 irn_flags => [ "rematerializable" ],
279 reg_req => { in => [ "gp" ], out => [ "gp" ] },
280 emit => 'clz %D0, %S0',
284 # mov lr, pc\n mov pc, XXX -- This combination is used for calls to function
287 state => "exc_pinned",
289 out_arity => "variable",
290 attr_type => "arm_shifter_operand_t",
291 attr => "arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot",
292 custominit => "init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);\n".
293 "\tarch_add_irn_flags(res, arch_irn_flags_modify_flags);",
294 emit => "mov lr, pc\n".
298 # mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function
301 state => "exc_pinned",
303 out_arity => "variable",
304 attr_type => "arm_load_store_attr_t",
305 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
306 custominit => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);",
307 emit => "mov lr, pc\n".
312 state => "exc_pinned",
314 out_arity => "variable",
315 attr_type => "arm_SymConst_attr_t",
316 attr => "ir_entity *entity, int symconst_offset",
317 custominit => "arch_add_irn_flags(res, arch_irn_flags_modify_flags);",
321 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
323 op_flags => [ "constlike" ],
324 irn_flags => [ "rematerializable" ],
325 reg_req => { out => [ "gp" ] },
326 emit => '/* %D0 now available for calculations */',
327 cmp_attr => 'return 1;',
333 attr => "unsigned size",
334 attr_type => "arm_CopyB_attr_t",
335 reg_req => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] },
340 op_flags => [ "constlike" ],
341 irn_flags => [ "rematerializable" ],
342 attr => "ir_entity *entity, int symconst_offset",
343 reg_req => { in => [ "gp" ], out => [ "gp" ] },
345 attr_type => "arm_SymConst_attr_t",
350 op_flags => [ "constlike" ],
351 irn_flags => [ "rematerializable" ],
352 attr => "ir_entity *entity, int symconst_offset",
353 reg_req => { out => [ "gp" ] },
354 attr_type => "arm_SymConst_attr_t",
359 irn_flags => [ "rematerializable", "modify_flags" ],
360 emit => 'cmp %S0, %O',
362 attr_type => "arm_cmp_attr_t",
363 constructors => \%cmp_shifter_operand_constructors,
367 irn_flags => [ "rematerializable", "modify_flags" ],
368 emit => 'tst %S0, %O',
370 attr_type => "arm_cmp_attr_t",
371 constructors => \%cmp_shifter_operand_constructors,
375 op_flags => [ "cfopcode", "forking" ],
378 reg_req => { in => [ "flags" ], out => [ "none", "none" ] },
379 attr => "ir_relation relation",
380 attr_type => "arm_CondJmp_attr_t",
381 init_attr => "\tset_arm_CondJmp_relation(res, relation);",
386 op_flags => [ "cfopcode" ],
387 irn_flags => [ "simple_jump" ],
388 reg_req => { out => [ "none" ] },
393 op_flags => [ "cfopcode", "forking" ],
396 attr => "const ir_switch_table *table",
397 init_attr => "init_arm_SwitchJmp_attributes(res, table);",
398 reg_req => { in => [ "gp" ], out => [ "none" ] },
399 out_arity => "variable",
400 attr_type => "arm_SwitchJmp_attr_t",
404 op_flags => [ "uses_memory" ],
405 state => "exc_pinned",
406 ins => [ "ptr", "mem" ],
407 outs => [ "res", "M" ],
408 reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
409 emit => 'ldr%ML %D0, [%S0, #%o]',
410 attr_type => "arm_load_store_attr_t",
411 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
415 op_flags => [ "uses_memory" ],
416 state => "exc_pinned",
417 ins => [ "ptr", "val", "mem" ],
419 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
420 emit => 'str%MS %S1, [%S0, #%o]',
422 attr_type => "arm_load_store_attr_t",
423 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
427 op_flags => [ "uses_memory" ],
428 irn_flags => [ "rematerializable" ],
429 state => "exc_pinned",
430 reg_req => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
431 emit => 'stmfd %S0!, {%S1, %S2, %S3, %S4}',
432 outs => [ "ptr", "M" ],
435 LoadStackM3Epilogue => {
436 op_flags => [ "uses_memory" ],
437 irn_flags => [ "rematerializable" ],
438 state => "exc_pinned",
439 reg_req => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
440 emit => 'ldmfd %S0, {%D0, %D1, %D2}',
441 outs => [ "res0", "res1", "res2", "M" ],
447 irn_flags => [ "rematerializable" ],
448 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
449 emit => 'adf%MA %D0, %S0, %S1',
450 attr_type => "arm_farith_attr_t",
451 attr => "ir_mode *op_mode",
456 irn_flags => [ "rematerializable" ],
457 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
458 emit => 'muf%MA %D0, %S0, %S1',
459 attr_type => "arm_farith_attr_t",
460 attr => "ir_mode *op_mode",
465 irn_flags => [ "rematerializable" ],
466 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
467 emit => 'suf%MA %D0, %S0, %S1',
468 attr_type => "arm_farith_attr_t",
469 attr => "ir_mode *op_mode",
474 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
475 emit => 'dvf%MA %D0, %S0, %S1',
476 outs => [ "res", "M" ],
477 attr_type => "arm_farith_attr_t",
478 attr => "ir_mode *op_mode",
483 irn_flags => [ "rematerializable" ],
484 reg_req => { in => [ "fpa" ], out => [ "fpa" ] },
485 emit => 'mvf%MA %S0, %D0',
486 attr_type => "arm_farith_attr_t",
487 attr => "ir_mode *op_mode",
492 irn_flags => [ "rematerializable" ],
493 reg_req => { in => [ "gp" ], out => [ "fpa" ] },
494 emit => 'flt%MA %D0, %S0',
495 attr_type => "arm_farith_attr_t",
496 attr => "ir_mode *op_mode",
501 irn_flags => [ "rematerializable", "modify_flags" ],
503 attr_type => "arm_cmp_attr_t",
504 attr => "bool ins_permuted",
505 init_attr => "init_arm_cmp_attr(res, ins_permuted, false);",
506 reg_req => { in => [ "fpa", "fpa" ], out => [ "flags" ] },
507 emit => 'cmfe %S0, %S1',
511 op_flags => [ "uses_memory" ],
512 state => "exc_pinned",
513 ins => [ "ptr", "mem" ],
514 outs => [ "res", "M" ],
515 reg_req => { in => [ "gp", "none" ], out => [ "fpa", "none" ] },
516 emit => 'ldf%MF %D0, [%S0, #%o]',
517 attr_type => "arm_load_store_attr_t",
518 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
522 op_flags => [ "uses_memory" ],
523 state => "exc_pinned",
524 ins => [ "ptr", "val", "mem" ],
527 reg_req => { in => [ "gp", "fpa", "none" ], out => [ "none" ] },
528 emit => 'stf%MF %S1, [%S0, #%o]',
529 attr_type => "arm_load_store_attr_t",
530 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
534 # floating point constants
537 op_flags => [ "constlike" ],
538 irn_flags => [ "rematerializable" ],
539 attr => "ir_tarval *tv",
540 init_attr => "attr->tv = tv;",
541 mode => "get_tarval_mode(tv)",
542 reg_req => { out => [ "fpa" ] },
543 attr_type => "arm_fConst_attr_t",