2 # Arm Architecure Specification
3 # Author: Matthias Braun, Michael Beck, Oliver Richter, Tobias Gneist
12 $mode_flags = "mode_Bu";
15 # NOTE: Last entry of each class is the largest Firm-Mode a register can hold
49 { mode => $mode_flags, flags => "manual_ra" }
54 FM => "${arch}_emit_float_load_store_mode(node);",
55 AM => "${arch}_emit_float_arithmetic_mode(node);",
56 LM => "${arch}_emit_load_mode(node);",
57 SM => "${arch}_emit_store_mode(node);",
58 SO => "${arch}_emit_shifter_operand(node);",
59 S0 => "${arch}_emit_source_register(node, 0);",
60 SC => "${arch}_emit_symconst(node);",
61 S1 => "${arch}_emit_source_register(node, 1);",
62 S2 => "${arch}_emit_source_register(node, 2);",
63 S3 => "${arch}_emit_source_register(node, 3);",
64 S4 => "${arch}_emit_source_register(node, 4);",
65 D0 => "${arch}_emit_dest_register(node, 0);",
66 D1 => "${arch}_emit_dest_register(node, 1);",
67 D2 => "${arch}_emit_dest_register(node, 2);",
68 O => "${arch}_emit_offset(node);",
71 $default_attr_type = "arm_attr_t";
72 $default_copy_attr = "arm_copy_attr";
75 arm_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
76 arm_SymConst_attr_t =>
77 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
78 "\tinit_arm_SymConst_attributes(res, entity, symconst_offset);",
79 arm_CondJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
80 arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
81 arm_fConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
82 arm_load_store_attr_t =>
83 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
84 "\tinit_arm_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
85 arm_shifter_operand_t =>
86 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n",
88 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n",
90 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
91 "\tinit_arm_farith_attributes(res, op_mode);",
93 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
94 "\tinit_arm_CopyB_attributes(res, size);",
98 arm_attr_t => "cmp_attr_arm",
99 arm_SymConst_attr_t => "cmp_attr_arm_SymConst",
100 arm_CondJmp_attr_t => "cmp_attr_arm_CondJmp",
101 arm_SwitchJmp_attr_t => "cmp_attr_arm_SwitchJmp",
102 arm_fConst_attr_t => "cmp_attr_arm_fConst",
103 arm_load_store_attr_t => "cmp_attr_arm_load_store",
104 arm_shifter_operand_t => "cmp_attr_arm_shifter_operand",
105 arm_CopyB_attr_t => "cmp_attr_arm_CopyB",
106 arm_cmp_attr_t => "cmp_attr_arm_cmp",
107 arm_farith_attr_t => "cmp_attr_arm_farith",
110 my %unop_shifter_operand_constructors = (
112 attr => "unsigned char immediate_value, unsigned char immediate_rot",
113 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
114 reg_req => { in => [], out => [ "gp" ] },
117 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
118 reg_req => { in => [ "gp" ], out => [ "gp" ] },
121 attr => "arm_shift_modifier_t shift_modifier",
122 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
123 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
126 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
127 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
128 reg_req => { in => [ "gp" ], out => [ "gp" ] },
132 my %binop_shifter_operand_constructors = (
134 attr => "unsigned char immediate_value, unsigned char immediate_rot",
135 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
136 reg_req => { in => [ "gp" ], out => [ "gp" ] },
140 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
141 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
142 ins => [ "left", "right" ],
145 attr => "arm_shift_modifier_t shift_modifier",
146 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
147 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "gp" ] },
148 ins => [ "left", "right", "shift" ],
151 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
152 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
153 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
154 ins => [ "left", "right" ],
158 my %cmp_shifter_operand_constructors = (
160 attr => "unsigned char immediate_value, unsigned char immediate_rot, bool ins_permuted, bool is_unsigned",
162 "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);\n".
163 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
164 reg_req => { in => [ "gp" ], out => [ "flags" ] },
168 attr => "bool ins_permuted, bool is_unsigned",
170 "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);\n".
171 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
172 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
173 ins => [ "left", "right" ],
176 attr => "arm_shift_modifier_t shift_modifier, bool ins_permuted, bool is_unsigned",
178 "init_arm_shifter_operand(res, 0, shift_modifier, 0);\n".
179 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
180 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "flags" ] },
181 ins => [ "left", "right", "shift" ],
184 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate, bool ins_permuted, bool is_unsigned",
186 "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);\n".
187 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
188 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
189 ins => [ "left", "right" ],
197 irn_flags => [ "rematerializable" ],
198 emit => '. add %D0, %S0, %SO',
200 attr_type => "arm_shifter_operand_t",
201 constructors => \%binop_shifter_operand_constructors,
205 irn_flags => [ "rematerializable" ],
206 reg_req => { in => [ "gp", "gp" ], out => [ "!in_r1" ] },
207 emit =>'. mul %D0, %S0, %S1',
212 irn_flags => [ "rematerializable" ],
213 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
214 emit =>'. smull %D0, %D1, %S0, %S1',
215 outs => [ "low", "high" ],
219 irn_flags => [ "rematerializable" ],
220 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
221 emit =>'. umull %D0, %D1, %S0, %S1',
222 outs => [ "low", "high" ],
227 irn_flags => [ "rematerializable" ],
228 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "!in_r1" ] },
229 emit =>'. mla %D0, %S0, %S1, %S2',
234 irn_flags => [ "rematerializable" ],
235 emit => '. and %D0, %S0, %SO',
237 attr_type => "arm_shifter_operand_t",
238 constructors => \%binop_shifter_operand_constructors,
242 irn_flags => [ "rematerializable" ],
243 emit => '. orr %D0, %S0, %SO',
245 attr_type => "arm_shifter_operand_t",
246 constructors => \%binop_shifter_operand_constructors,
250 irn_flags => [ "rematerializable" ],
251 emit => '. eor %D0, %S0, %SO',
253 attr_type => "arm_shifter_operand_t",
254 constructors => \%binop_shifter_operand_constructors,
258 irn_flags => [ "rematerializable" ],
259 emit => '. bic %D0, %S0, %SO',
261 attr_type => "arm_shifter_operand_t",
262 constructors => \%binop_shifter_operand_constructors,
266 irn_flags => [ "rematerializable" ],
267 emit => '. sub %D0, %S0, %SO',
269 attr_type => "arm_shifter_operand_t",
270 constructors => \%binop_shifter_operand_constructors,
274 irn_flags => [ "rematerializable" ],
275 emit => '. rsb %D0, %S0, %SO',
277 attr_type => "arm_shifter_operand_t",
278 constructors => \%binop_shifter_operand_constructors,
282 irn_flags => [ "rematerializable" ],
284 emit => '. mov %D0, %SO',
286 attr_type => "arm_shifter_operand_t",
287 constructors => \%unop_shifter_operand_constructors,
291 irn_flags => [ "rematerializable" ],
292 attr_type => "arm_shifter_operand_t",
294 emit => '. mvn %D0, %SO',
296 constructors => \%unop_shifter_operand_constructors,
300 irn_flags => [ "rematerializable" ],
301 reg_req => { in => [ "gp" ], out => [ "gp" ] },
302 emit =>'. clz %D0, %S0',
306 # mov lr, pc\n mov pc, XXX -- This combination is used for calls to function
309 state => "exc_pinned",
311 out_arity => "variable",
312 attr_type => "arm_shifter_operand_t",
313 attr => "arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot",
314 custominit => "init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);\n".
315 "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);",
316 emit => ". mov lr, pc\n".
320 # mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function
323 state => "exc_pinned",
325 out_arity => "variable",
326 attr_type => "arm_load_store_attr_t",
327 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
328 custominit => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);",
329 emit => ". mov lr, pc\n".
334 state => "exc_pinned",
336 out_arity => "variable",
337 attr_type => "arm_SymConst_attr_t",
338 attr => "ir_entity *entity, int symconst_offset",
339 custominit => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);",
343 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
345 op_flags => [ "constlike" ],
346 irn_flags => [ "rematerializable" ],
347 reg_req => { out => [ "gp" ] },
348 emit => '. /* %D0 now available for calculations */',
349 cmp_attr => 'return 1;',
354 op_flags => [ "fragile" ],
356 attr => "unsigned size",
357 attr_type => "arm_CopyB_attr_t",
358 reg_req => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] },
363 op_flags => [ "constlike" ],
364 irn_flags => [ "rematerializable" ],
365 attr => "ir_entity *entity, int symconst_offset",
366 reg_req => { in => [ "gp" ], out => [ "gp" ] },
368 attr_type => "arm_SymConst_attr_t",
373 op_flags => [ "constlike" ],
374 irn_flags => [ "rematerializable" ],
375 attr => "ir_entity *entity, int symconst_offset",
376 reg_req => { out => [ "gp" ] },
377 attr_type => "arm_SymConst_attr_t",
382 irn_flags => [ "rematerializable", "modify_flags" ],
383 emit => '. cmp %S0, %SO',
385 attr_type => "arm_cmp_attr_t",
386 constructors => \%cmp_shifter_operand_constructors,
390 irn_flags => [ "rematerializable", "modify_flags" ],
391 emit => '. tst %S0, %SO',
393 attr_type => "arm_cmp_attr_t",
394 constructors => \%cmp_shifter_operand_constructors,
398 op_flags => [ "labeled", "cfopcode", "forking" ],
401 reg_req => { in => [ "flags" ], out => [ "none", "none" ] },
402 attr => "ir_relation relation",
403 attr_type => "arm_CondJmp_attr_t",
404 init_attr => "\tset_arm_CondJmp_relation(res, relation);",
409 op_flags => [ "cfopcode" ],
410 irn_flags => [ "simple_jump" ],
411 reg_req => { out => [ "none" ] },
416 op_flags => [ "labeled", "cfopcode", "forking" ],
419 attr => "int n_projs, long def_proj_num",
420 init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n".
421 "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);\n".
422 "\tinfo->out_infos = NULL;",
423 reg_req => { in => [ "gp" ], out => [ "none" ] },
424 attr_type => "arm_SwitchJmp_attr_t",
428 op_flags => [ "labeled", "fragile" ],
429 state => "exc_pinned",
430 ins => [ "ptr", "mem" ],
431 outs => [ "res", "M" ],
432 reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
433 emit => '. ldr%LM %D0, [%S0, #%O]',
434 attr_type => "arm_load_store_attr_t",
435 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
439 op_flags => [ "labeled", "fragile" ],
440 state => "exc_pinned",
441 ins => [ "ptr", "val", "mem" ],
443 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
444 emit => '. str%SM %S1, [%S0, #%O]',
446 attr_type => "arm_load_store_attr_t",
447 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
451 op_flags => [ "labeled", "fragile" ],
452 irn_flags => [ "rematerializable" ],
453 state => "exc_pinned",
454 reg_req => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
455 emit => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
456 outs => [ "ptr", "M" ],
459 LoadStackM3Epilogue => {
460 op_flags => [ "labeled", "fragile" ],
461 irn_flags => [ "rematerializable" ],
462 state => "exc_pinned",
463 reg_req => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
464 emit => '. ldmfd %S0, {%D0, %D1, %D2}',
465 outs => [ "res0", "res1", "res2", "M" ],
471 irn_flags => [ "rematerializable" ],
472 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
473 emit => '. adf%AM %D0, %S0, %S1',
474 attr_type => "arm_farith_attr_t",
475 attr => "ir_mode *op_mode",
480 irn_flags => [ "rematerializable" ],
481 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
482 emit =>'. muf%AM %D0, %S0, %S1',
483 attr_type => "arm_farith_attr_t",
484 attr => "ir_mode *op_mode",
489 irn_flags => [ "rematerializable" ],
490 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
491 emit => '. suf%AM %D0, %S0, %S1',
492 attr_type => "arm_farith_attr_t",
493 attr => "ir_mode *op_mode",
498 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
499 emit =>'. dvf%AM %D0, %S0, %S1',
500 outs => [ "res", "M" ],
501 attr_type => "arm_farith_attr_t",
502 attr => "ir_mode *op_mode",
507 irn_flags => [ "rematerializable" ],
508 reg_req => { in => [ "fpa" ], out => [ "fpa" ] },
509 emit => '. mvf%AM %S0, %D0',
510 attr_type => "arm_farith_attr_t",
511 attr => "ir_mode *op_mode",
516 irn_flags => [ "rematerializable" ],
517 reg_req => { in => [ "gp" ], out => [ "fpa" ] },
518 emit => '. flt%AM %D0, %S0',
519 attr_type => "arm_farith_attr_t",
520 attr => "ir_mode *op_mode",
525 irn_flags => [ "rematerializable", "modify_flags" ],
527 attr_type => "arm_cmp_attr_t",
528 attr => "bool ins_permuted",
529 init_attr => "init_arm_cmp_attr(res, ins_permuted, false);",
530 reg_req => { in => [ "fpa", "fpa" ], out => [ "flags" ] },
531 emit => '. cmfe %S0, %S1',
535 op_flags => [ "labeled", "fragile" ],
536 state => "exc_pinned",
537 ins => [ "ptr", "mem" ],
538 outs => [ "res", "M" ],
539 reg_req => { in => [ "gp", "none" ], out => [ "fpa", "none" ] },
540 emit => '. ldf%FM %D0, [%S0, #%O]',
541 attr_type => "arm_load_store_attr_t",
542 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
546 op_flags => [ "labeled", "fragile" ],
547 state => "exc_pinned",
548 ins => [ "ptr", "val", "mem" ],
551 reg_req => { in => [ "gp", "fpa", "none" ], out => [ "none" ] },
552 emit => '. stf%FM %S1, [%S0, #%O]',
553 attr_type => "arm_load_store_attr_t",
554 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
558 # floating point constants
561 op_flags => [ "constlike" ],
562 irn_flags => [ "rematerializable" ],
563 attr => "ir_tarval *tv",
564 init_attr => "attr->tv = tv;",
565 mode => "get_tarval_mode(tv)",
566 reg_req => { out => [ "fpa" ] },
567 attr_type => "arm_fConst_attr_t",