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,
308 irn_flags => [ "rematerializable" ],
309 reg_req => { in => [ "gp" ], out => [ "gp" ] },
310 emit =>'. clz %D0, %S0',
314 # mov lr, pc\n mov pc, XXX -- This combination is used for calls to function
317 state => "exc_pinned",
319 out_arity => "variable",
320 attr_type => "arm_shifter_operand_t",
321 attr => "arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot",
322 custominit => "init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);\n".
323 "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);",
324 emit => ". mov lr, pc\n".
328 # mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function
331 state => "exc_pinned",
333 out_arity => "variable",
334 attr_type => "arm_load_store_attr_t",
335 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
336 custominit => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);",
337 emit => ". mov lr, pc\n".
342 state => "exc_pinned",
344 out_arity => "variable",
345 attr_type => "arm_SymConst_attr_t",
346 attr => "ir_entity *entity, int symconst_offset",
347 custominit => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);",
351 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
353 op_flags => [ "constlike" ],
354 irn_flags => [ "rematerializable" ],
355 reg_req => { out => [ "gp" ] },
356 emit => '. /* %D0 now available for calculations */',
357 cmp_attr => 'return 1;',
362 op_flags => [ "fragile" ],
364 attr => "unsigned size",
365 attr_type => "arm_CopyB_attr_t",
366 reg_req => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] },
371 op_flags => [ "constlike" ],
372 irn_flags => [ "rematerializable" ],
373 attr => "ir_entity *entity, int symconst_offset",
374 reg_req => { in => [ "gp" ], out => [ "gp" ] },
376 attr_type => "arm_SymConst_attr_t",
381 op_flags => [ "constlike" ],
382 irn_flags => [ "rematerializable" ],
383 attr => "ir_entity *entity, int symconst_offset",
384 reg_req => { out => [ "gp" ] },
385 attr_type => "arm_SymConst_attr_t",
390 irn_flags => [ "rematerializable", "modify_flags" ],
391 emit => '. cmp %S0, %SO',
393 attr_type => "arm_cmp_attr_t",
394 constructors => \%cmp_shifter_operand_constructors,
398 irn_flags => [ "rematerializable", "modify_flags" ],
399 emit => '. tst %S0, %SO',
401 attr_type => "arm_cmp_attr_t",
402 constructors => \%cmp_shifter_operand_constructors,
406 op_flags => [ "labeled", "cfopcode", "forking" ],
409 reg_req => { in => [ "flags" ], out => [ "none", "none" ] },
410 attr => "pn_Cmp pnc",
411 attr_type => "arm_CondJmp_attr_t",
412 init_attr => "\tset_arm_CondJmp_pnc(res, pnc);",
417 op_flags => [ "cfopcode" ],
418 irn_flags => [ "simple_jump" ],
419 reg_req => { out => [ "none" ] },
424 op_flags => [ "labeled", "cfopcode", "forking" ],
427 attr => "int n_projs, long def_proj_num",
428 init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n".
429 "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);",
430 reg_req => { in => [ "gp" ], out => [ "none" ] },
431 attr_type => "arm_SwitchJmp_attr_t",
435 op_flags => [ "labeled", "fragile" ],
436 state => "exc_pinned",
437 ins => [ "ptr", "mem" ],
438 outs => [ "res", "M" ],
439 reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
440 emit => '. ldr%LM %D0, [%S0, #%O]',
441 attr_type => "arm_load_store_attr_t",
442 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
446 op_flags => [ "labeled", "fragile" ],
447 state => "exc_pinned",
448 ins => [ "ptr", "val", "mem" ],
450 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
451 emit => '. str%SM %S1, [%S0, #%O]',
453 attr_type => "arm_load_store_attr_t",
454 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
458 op_flags => [ "labeled", "fragile" ],
459 irn_flags => [ "rematerializable" ],
460 state => "exc_pinned",
461 reg_req => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
462 emit => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
463 outs => [ "ptr", "M" ],
466 LoadStackM3Epilogue => {
467 op_flags => [ "labeled", "fragile" ],
468 irn_flags => [ "rematerializable" ],
469 state => "exc_pinned",
470 reg_req => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
471 emit => '. ldmfd %S0, {%D0, %D1, %D2}',
472 outs => [ "res0", "res1", "res2", "M" ],
478 irn_flags => [ "rematerializable" ],
479 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
480 emit => '. adf%AM %D0, %S0, %S1',
481 attr_type => "arm_farith_attr_t",
482 attr => "ir_mode *op_mode",
487 irn_flags => [ "rematerializable" ],
488 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
489 emit =>'. muf%AM %D0, %S0, %S1',
490 attr_type => "arm_farith_attr_t",
491 attr => "ir_mode *op_mode",
496 irn_flags => [ "rematerializable" ],
497 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
498 emit => '. suf%AM %D0, %S0, %S1',
499 attr_type => "arm_farith_attr_t",
500 attr => "ir_mode *op_mode",
505 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
506 emit =>'. dvf%AM %D0, %S0, %S1',
507 outs => [ "res", "M" ],
508 attr_type => "arm_farith_attr_t",
509 attr => "ir_mode *op_mode",
514 irn_flags => [ "rematerializable" ],
515 reg_req => { in => [ "fpa" ], out => [ "fpa" ] },
516 emit => '. mvf%AM %S0, %D0',
517 attr_type => "arm_farith_attr_t",
518 attr => "ir_mode *op_mode",
523 irn_flags => [ "rematerializable" ],
524 reg_req => { in => [ "gp" ], out => [ "fpa" ] },
525 emit => '. flt%AM %D0, %S0',
526 attr_type => "arm_farith_attr_t",
527 attr => "ir_mode *op_mode",
532 irn_flags => [ "rematerializable", "modify_flags" ],
534 attr_type => "arm_cmp_attr_t",
535 attr => "bool ins_permuted",
536 init_attr => "init_arm_cmp_attr(res, ins_permuted, false);",
537 reg_req => { in => [ "fpa", "fpa" ], out => [ "flags" ] },
538 emit => '. cmfe %S0, %S1',
542 op_flags => [ "labeled", "fragile" ],
543 state => "exc_pinned",
544 ins => [ "ptr", "mem" ],
545 outs => [ "res", "M" ],
546 reg_req => { in => [ "gp", "none" ], out => [ "fpa", "none" ] },
547 emit => '. ldf%FM %D0, [%S0, #%O]',
548 attr_type => "arm_load_store_attr_t",
549 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
553 op_flags => [ "labeled", "fragile" ],
554 state => "exc_pinned",
555 ins => [ "ptr", "val", "mem" ],
558 reg_req => { in => [ "gp", "fpa", "none" ], out => [ "none" ] },
559 emit => '. stf%FM %S1, [%S0, #%O]',
560 attr_type => "arm_load_store_attr_t",
561 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
565 # floating point constants
568 op_flags => [ "constlike" ],
569 irn_flags => [ "rematerializable" ],
570 attr => "ir_tarval *tv",
571 init_attr => "attr->tv = tv;",
572 mode => "get_tarval_mode(tv)",
573 reg_req => { out => [ "fpa" ] },
574 attr_type => "arm_fConst_attr_t",