4 # the cpu architecture (ia32, ia64, mips, sparc, ppc, ...)
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 M => "${arch}_emit_mode(node);",
63 LM => "${arch}_emit_load_mode(node);",
64 SM => "${arch}_emit_store_mode(node);",
65 SO => "${arch}_emit_shifter_operand(node);",
66 S0 => "${arch}_emit_source_register(node, 0);",
67 SC => "${arch}_emit_symconst(node);",
68 S1 => "${arch}_emit_source_register(node, 1);",
69 S2 => "${arch}_emit_source_register(node, 2);",
70 S3 => "${arch}_emit_source_register(node, 3);",
71 S4 => "${arch}_emit_source_register(node, 4);",
72 D0 => "${arch}_emit_dest_register(node, 0);",
73 D1 => "${arch}_emit_dest_register(node, 1);",
74 D2 => "${arch}_emit_dest_register(node, 2);",
75 O => "${arch}_emit_offset(node);",
78 $default_attr_type = "arm_attr_t";
79 $default_copy_attr = "arm_copy_attr";
82 arm_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
83 arm_SymConst_attr_t =>
84 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
85 "\tinit_arm_SymConst_attributes(res, entity, symconst_offset);",
86 arm_CondJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
87 arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
88 arm_fpaConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
89 arm_load_store_attr_t =>
90 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
91 "\tinit_arm_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
92 arm_shifter_operand_t =>
93 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n",
95 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n",
97 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
98 "\tinit_arm_CopyB_attributes(res, size);",
102 arm_attr_t => "cmp_attr_arm",
103 arm_SymConst_attr_t => "cmp_attr_arm_SymConst",
104 arm_CondJmp_attr_t => "cmp_attr_arm_CondJmp",
105 arm_SwitchJmp_attr_t => "cmp_attr_arm_SwitchJmp",
106 arm_fpaConst_attr_t => "cmp_attr_arm_fpaConst",
107 arm_load_store_attr_t => "cmp_attr_arm_load_store",
108 arm_shifter_operand_t => "cmp_attr_arm_shifter_operand",
109 arm_CopyB_attr_t => "cmp_attr_arm_CopyB",
110 arm_cmp_attr_t => "cmp_attr_arm_cmp",
113 my %unop_shifter_operand_constructors = (
115 attr => "unsigned char immediate_value, unsigned char immediate_rot",
116 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
117 reg_req => { in => [], out => [ "gp" ] },
120 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
121 reg_req => { in => [ "gp" ], out => [ "gp" ] },
124 attr => "arm_shift_modifier_t shift_modifier",
125 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
126 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
129 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
130 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
131 reg_req => { in => [ "gp" ], out => [ "gp" ] },
135 my %binop_shifter_operand_constructors = (
137 attr => "unsigned char immediate_value, unsigned char immediate_rot",
138 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
139 reg_req => { in => [ "gp" ], out => [ "gp" ] },
143 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
144 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
145 ins => [ "left", "right" ],
148 attr => "arm_shift_modifier_t shift_modifier",
149 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
150 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "gp" ] },
151 ins => [ "left", "right", "shift" ],
154 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate",
155 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
156 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
157 ins => [ "left", "right" ],
161 my %cmp_shifter_operand_constructors = (
163 attr => "unsigned char immediate_value, unsigned char immediate_rot, bool ins_permuted, bool is_unsigned",
165 "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);\n".
166 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
167 reg_req => { in => [ "gp" ], out => [ "flags" ] },
171 attr => "bool ins_permuted, bool is_unsigned",
173 "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);\n".
174 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
175 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
176 ins => [ "left", "right" ],
179 attr => "arm_shift_modifier_t shift_modifier, bool ins_permuted, bool is_unsigned",
181 "init_arm_shifter_operand(res, 0, shift_modifier, 0);\n".
182 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
183 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "flags" ] },
184 ins => [ "left", "right", "shift" ],
187 attr => "arm_shift_modifier_t shift_modifier, unsigned shift_immediate, bool ins_permuted, bool is_unsigned",
189 "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);\n".
190 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
191 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
192 ins => [ "left", "right" ],
201 emit => '. add %D0, %S0, %SO',
203 attr_type => "arm_shifter_operand_t",
204 constructors => \%binop_shifter_operand_constructors,
209 reg_req => { in => [ "gp", "gp" ], out => [ "!in_r1" ] },
210 emit =>'. mul %D0, %S0, %S1',
216 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
217 emit =>'. smull %D0, %D1, %S0, %S1',
218 outs => [ "low", "high" ],
223 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
224 emit =>'. umull %D0, %D1, %S0, %S1',
225 outs => [ "low", "high" ],
231 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "!in_r1" ] },
232 emit =>'. mla %D0, %S0, %S1, %S2',
238 emit => '. and %D0, %S0, %SO',
240 attr_type => "arm_shifter_operand_t",
241 constructors => \%binop_shifter_operand_constructors,
246 emit => '. orr %D0, %S0, %SO',
248 attr_type => "arm_shifter_operand_t",
249 constructors => \%binop_shifter_operand_constructors,
254 emit => '. eor %D0, %S0, %SO',
256 attr_type => "arm_shifter_operand_t",
257 constructors => \%binop_shifter_operand_constructors,
262 emit => '. bic %D0, %S0, %SO',
264 attr_type => "arm_shifter_operand_t",
265 constructors => \%binop_shifter_operand_constructors,
270 emit => '. sub %D0, %S0, %SO',
272 attr_type => "arm_shifter_operand_t",
273 constructors => \%binop_shifter_operand_constructors,
278 emit => '. rsb %D0, %S0, %SO',
280 attr_type => "arm_shifter_operand_t",
281 constructors => \%binop_shifter_operand_constructors,
287 emit => '. mov %D0, %SO',
289 attr_type => "arm_shifter_operand_t",
290 constructors => \%unop_shifter_operand_constructors,
295 attr_type => "arm_shifter_operand_t",
297 emit => '. mvn %D0, %SO',
299 constructors => \%unop_shifter_operand_constructors,
302 # Deprecated - we should construct the movs and rsbmi directly...
305 reg_req => { in => [ "gp" ], out => [ "gp" ] },
308 . rsbmi %D0, %S0, #0',
312 # mov lr, pc\n mov pc, XXX -- This combination is used for calls to function
315 state => "exc_pinned",
317 out_arity => "variable",
318 attr_type => "arm_shifter_operand_t",
319 attr => "arm_shift_modifier_t shift_modifier, unsigned char immediate_value, unsigned char immediate_rot",
320 custominit => "init_arm_shifter_operand(res, immediate_value, shift_modifier, immediate_rot);\n".
321 "\tarch_irn_add_flags(res, arch_irn_flags_modify_flags);",
322 emit => ". mov lr, pc\n".
327 # mov lr, pc\n ldr pc, XXX -- This combination is used for calls to function
330 state => "exc_pinned",
332 out_arity => "variable",
333 attr_type => "arm_load_store_attr_t",
334 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
335 custominit => "arch_irn_add_flags(res, arch_irn_flags_modify_flags);",
336 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);",
352 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
356 reg_req => { out => [ "gp" ] },
357 emit => '. /* %D0 now available for calculations */',
358 cmp_attr => 'return 1;',
365 attr => "unsigned size",
366 attr_type => "arm_CopyB_attr_t",
367 reg_req => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] },
374 attr => "ir_entity *entity, int symconst_offset",
375 reg_req => { in => [ "gp" ], out => [ "gp" ] },
377 attr_type => "arm_SymConst_attr_t",
384 attr => "ir_entity *entity, int symconst_offset",
385 reg_req => { out => [ "gp" ] },
386 attr_type => "arm_SymConst_attr_t",
392 emit => '. cmp %S0, %SO',
394 attr_type => "arm_cmp_attr_t",
395 constructors => \%cmp_shifter_operand_constructors,
400 emit => '. tst %S0, %SO',
402 attr_type => "arm_cmp_attr_t",
403 constructors => \%cmp_shifter_operand_constructors,
410 reg_req => { in => [ "flags" ], out => [ "none", "none" ] },
411 attr => "pn_Cmp pnc",
412 attr_type => "arm_CondJmp_attr_t",
413 init_attr => "\tset_arm_CondJmp_pnc(res, pnc);",
420 reg_req => { out => [ "none" ] },
428 attr => "int n_projs, long def_proj_num",
429 init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n".
430 "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);",
431 reg_req => { in => [ "gp" ], out => [ "none" ] },
432 attr_type => "arm_SwitchJmp_attr_t",
437 state => "exc_pinned",
438 ins => [ "ptr", "mem" ],
439 outs => [ "res", "M" ],
440 reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
441 emit => '. ldr%LM %D0, [%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",
448 state => "exc_pinned",
449 ins => [ "ptr", "val", "mem" ],
451 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
452 emit => '. str%SM %S1, [%S0, #%O]',
454 attr_type => "arm_load_store_attr_t",
455 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
461 state => "exc_pinned",
462 reg_req => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
463 emit => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
464 outs => [ "ptr", "M" ],
467 LoadStackM3Epilogue => {
470 state => "exc_pinned",
471 reg_req => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
472 emit => '. ldmfd %S0, {%D0, %D1, %D2}',
473 outs => [ "res0", "res1", "res2", "M" ],
480 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
481 emit => '. adf%M %D0, %S0, %S1',
486 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
487 emit =>'. muf%M %D0, %S0, %S1',
492 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
493 emit =>'. fml%M %D0, %S0, %S1',
498 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
499 emit =>'. fmax %S0, %S1, %D0',
504 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
505 emit =>'. fmin %S0, %S1, %D0',
510 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
511 emit => '. suf%M %D0, %S0, %S1'
516 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
517 emit => '. rsf%M %D0, %S0, %S1'
521 attr => "ir_mode *op_mode",
522 init_attr => "attr->op_mode = op_mode;",
523 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
524 emit =>'. dvf%M %D0, %S0, %S1',
525 outs => [ "res", "M" ],
529 attr => "ir_mode *op_mode",
530 init_attr => "attr->op_mode = op_mode;",
531 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
532 emit =>'. rdf%M %D0, %S0, %S1',
533 outs => [ "res", "M" ],
537 attr => "ir_mode *op_mode",
538 init_attr => "attr->op_mode = op_mode;",
539 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
540 emit =>'. fdv%M %D0, %S0, %S1',
541 outs => [ "res", "M" ],
545 attr => "ir_mode *op_mode",
546 init_attr => "attr->op_mode = op_mode;",
547 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
548 emit =>'. frd%M %D0, %S0, %S1',
549 outs => [ "res", "M" ],
554 reg_req => { in => [ "fpa" ], out => [ "fpa" ] },
555 emit => '. mvf%M %S0, %D0',
560 reg_req => { in => [ "fpa" ], out => [ "fpa" ] },
561 emit => '. mnf%M %S0, %D0',
566 reg_req => { in => [ "fpa" ], out => [ "fpa" ] },
567 emit => '. abs%M %D0, %S0',
572 reg_req => { in => ["gp"], out => [ "fpa" ] },
573 emit => '. flt%M %D0, %S0',
578 reg_req => { in => ["fpa"], out => [ "gp" ] },
579 emit => '. fix %D0, %S0',
585 attr_type => "arm_cmp_attr_t",
586 attr => "bool ins_permuted",
587 init_attr => "init_arm_cmp_attr(res, ins_permuted, false);",
588 reg_req => { in => [ "fpa", "fpa" ], out => [ "flags" ] },
589 emit => '. cmf %S0, %S1',
595 attr_type => "arm_cmp_attr_t",
596 attr => "bool ins_permuted",
597 init_attr => "init_arm_cmp_attr(res, ins_permuted, false);",
598 reg_req => { in => [ "fpa", "fpa" ], out => [ "flags" ] },
599 emit => '. cmfe %S0, %S1',
605 state => "exc_pinned",
606 attr => "ir_mode *op_mode",
607 init_attr => "attr->op_mode = op_mode;",
608 reg_req => { in => [ "gp", "none" ], out => [ "fpa", "none" ] },
609 emit => '. ldf%M %D0, [%S0]',
610 outs => [ "res", "M" ],
616 state => "exc_pinned",
617 attr => "ir_mode *op_mode",
618 init_attr => "attr->op_mode = op_mode;",
619 reg_req => { in => [ "gp", "fpa", "none" ], out => [ "none" ] },
620 emit => '. stf%M %S1, [%S0]',
627 reg_req => { in => [ "fpa", "none" ], out => [ "gp", "gp", "none" ] },
628 outs => [ "low", "high", "M" ],
632 reg_req => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
633 emit => '. add %D0, %S0, %S1',
634 outs => [ "stack", "M" ],
638 reg_req => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
639 ins => [ "stack", "size", "mem" ],
640 emit => ". sub %D0, %S0, %S1\n".
642 outs => [ "stack", "addr", "M" ],
647 reg_req => { out => [ "gp" ] },
653 # floating point constants
658 attr => "tarval *tv",
659 init_attr => "attr->tv = tv;",
660 mode => "get_tarval_mode(tv)",
661 reg_req => { out => [ "fpa" ] },
662 attr_type => "arm_fpaConst_attr_t",