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 S1 => "${arch}_emit_source_register(node, 1);",
68 S2 => "${arch}_emit_source_register(node, 2);",
69 S3 => "${arch}_emit_source_register(node, 3);",
70 S4 => "${arch}_emit_source_register(node, 4);",
71 D0 => "${arch}_emit_dest_register(node, 0);",
72 D1 => "${arch}_emit_dest_register(node, 1);",
73 D2 => "${arch}_emit_dest_register(node, 2);",
74 O => "${arch}_emit_offset(node);",
77 $default_attr_type = "arm_attr_t";
78 $default_copy_attr = "arm_copy_attr";
81 arm_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
82 arm_SymConst_attr_t =>
83 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
84 "\tinit_arm_SymConst_attributes(res, entity);",
85 arm_CondJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
86 arm_SwitchJmp_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
87 arm_fpaConst_attr_t => "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);",
88 arm_load_store_attr_t =>
89 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n".
90 "\tinit_arm_load_store_attributes(res, ls_mode, entity, entity_sign, offset, is_frame_entity);",
91 arm_shifter_operand_t =>
92 "\tinit_arm_attributes(res, flags, in_reqs, exec_units, n_res);\n",
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".
97 "\tinit_arm_CopyB_attributes(res, size);",
101 arm_attr_t => "cmp_attr_arm",
102 arm_SymConst_attr_t => "cmp_attr_arm_SymConst",
103 arm_CondJmp_attr_t => "cmp_attr_arm_CondJmp",
104 arm_SwitchJmp_attr_t => "cmp_attr_arm_SwitchJmp",
105 arm_fpaConst_attr_t => "cmp_attr_arm_fpaConst",
106 arm_load_store_attr_t => "cmp_attr_arm_load_store",
107 arm_shifter_operand_t => "cmp_attr_arm_shifter_operand",
108 arm_CopyB_attr_t => "cmp_attr_arm_CopyB",
109 arm_cmp_attr_t => "cmp_attr_arm_cmp",
112 my %unop_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 => [], out => [ "gp" ] },
119 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
120 reg_req => { in => [ "gp" ], out => [ "gp" ] },
123 attr => "arm_shift_modifier shift_modifier",
124 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
125 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
128 attr => "arm_shift_modifier shift_modifier, unsigned shift_immediate",
129 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
130 reg_req => { in => [ "gp" ], out => [ "gp" ] },
134 my %binop_shifter_operand_constructors = (
136 attr => "unsigned char immediate_value, unsigned char immediate_rot",
137 custominit => "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);",
138 reg_req => { in => [ "gp" ], out => [ "gp" ] },
142 custominit => "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);",
143 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
144 ins => [ "left", "right" ],
147 attr => "arm_shift_modifier shift_modifier",
148 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, 0);",
149 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "gp" ] },
150 ins => [ "left", "right", "shift" ],
153 attr => "arm_shift_modifier shift_modifier, unsigned shift_immediate",
154 custominit => "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);",
155 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
156 ins => [ "left", "right" ],
160 my %cmp_shifter_operand_constructors = (
162 attr => "unsigned char immediate_value, unsigned char immediate_rot, bool ins_permuted, bool is_unsigned",
164 "init_arm_shifter_operand(res, immediate_value, ARM_SHF_IMM, immediate_rot);\n".
165 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
166 reg_req => { in => [ "gp" ], out => [ "flags" ] },
170 attr => "bool ins_permuted, bool is_unsigned",
172 "init_arm_shifter_operand(res, 0, ARM_SHF_REG, 0);\n".
173 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
174 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
175 ins => [ "left", "right" ],
178 attr => "arm_shift_modifier shift_modifier, bool ins_permuted, bool is_unsigned",
180 "init_arm_shifter_operand(res, 0, shift_modifier, 0);\n".
181 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
182 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "flags" ] },
183 ins => [ "left", "right", "shift" ],
186 attr => "arm_shift_modifier shift_modifier, unsigned shift_immediate, bool ins_permuted, bool is_unsigned",
188 "init_arm_shifter_operand(res, 0, shift_modifier, shift_immediate);\n".
189 "\tinit_arm_cmp_attr(res, ins_permuted, is_unsigned);",
190 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
191 ins => [ "left", "right" ],
200 emit => '. add %D0, %S0, %SO',
202 attr_type => "arm_shifter_operand_t",
203 constructors => \%binop_shifter_operand_constructors,
208 reg_req => { in => [ "gp", "gp" ], out => [ "!in_r1" ] },
209 emit =>'. mul %D0, %S0, %S1',
215 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
216 emit =>'. smull %D0, %D1, %S0, %S1',
217 outs => [ "low", "high" ],
222 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "gp" ] },
223 emit =>'. umull %D0, %D1, %S0, %S1',
224 outs => [ "low", "high" ],
230 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "!in_r1" ] },
231 emit =>'. mla %D0, %S0, %S1, %S2',
237 emit => '. and %D0, %S0, %SO',
239 attr_type => "arm_shifter_operand_t",
240 constructors => \%binop_shifter_operand_constructors,
245 emit => '. orr %D0, %S0, %SO',
247 attr_type => "arm_shifter_operand_t",
248 constructors => \%binop_shifter_operand_constructors,
253 emit => '. eor %D0, %S0, %SO',
255 attr_type => "arm_shifter_operand_t",
256 constructors => \%binop_shifter_operand_constructors,
261 emit => '. bic %D0, %S0, %SO',
263 attr_type => "arm_shifter_operand_t",
264 constructors => \%binop_shifter_operand_constructors,
269 emit => '. sub %D0, %S0, %SO',
271 attr_type => "arm_shifter_operand_t",
272 constructors => \%binop_shifter_operand_constructors,
277 emit => '. rsb %D0, %S0, %SO',
279 attr_type => "arm_shifter_operand_t",
280 constructors => \%binop_shifter_operand_constructors,
286 emit => '. mov %D0, %SO',
288 attr_type => "arm_shifter_operand_t",
289 constructors => \%unop_shifter_operand_constructors,
294 attr_type => "arm_shifter_operand_t",
296 emit => '. mvn %D0, %SO',
298 constructors => \%unop_shifter_operand_constructors,
301 # Deprecated - we should construct the movs and rsbmi directly...
304 reg_req => { in => [ "gp" ], out => [ "gp" ] },
307 . rsbmi %D0, %S0, #0',
311 # this node produces ALWAYS an empty (tempary) gp reg and cannot be CSE'd
315 reg_req => { out => [ "gp" ] },
316 emit => '. /* %D0 now available for calculations */',
317 cmp_attr => 'return 1;',
324 attr => "unsigned size",
325 attr_type => "arm_CopyB_attr_t",
326 reg_req => { in => [ "!sp", "!sp", "gp", "gp", "gp", "none" ], out => [ "none" ] },
333 attr => "ir_entity *entity",
334 reg_req => { in => [ "gp" ], out => [ "gp" ] },
336 attr_type => "arm_SymConst_attr_t",
343 attr => "ir_entity *entity",
344 reg_req => { out => [ "gp" ] },
345 attr_type => "arm_SymConst_attr_t",
351 emit => '. cmp %S0, %SO',
353 attr_type => "arm_cmp_attr_t",
354 constructors => \%cmp_shifter_operand_constructors,
359 emit => '. tst %S0, %SO',
361 attr_type => "arm_cmp_attr_t",
362 constructors => \%cmp_shifter_operand_constructors,
369 reg_req => { in => [ "flags" ], out => [ "none", "none" ] },
370 attr => "int proj_num",
371 attr_type => "arm_CondJmp_attr_t",
372 init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
379 reg_req => { out => [ "none" ] },
387 attr => "int n_projs, long def_proj_num",
388 init_attr => "\tset_arm_SwitchJmp_n_projs(res, n_projs);\n".
389 "\tset_arm_SwitchJmp_default_proj_num(res, def_proj_num);",
390 reg_req => { in => [ "gp" ], out => [ "none" ] },
391 attr_type => "arm_SwitchJmp_attr_t",
396 state => "exc_pinned",
397 ins => [ "ptr", "mem" ],
398 outs => [ "res", "M" ],
399 reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
400 emit => '. ldr%LM %D0, [%S0, #%O]',
401 attr_type => "arm_load_store_attr_t",
402 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
407 state => "exc_pinned",
408 ins => [ "ptr", "val", "mem" ],
410 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
411 emit => '. str%SM %S1, [%S0, #%O]',
413 attr_type => "arm_load_store_attr_t",
414 attr => "ir_mode *ls_mode, ir_entity *entity, int entity_sign, long offset, bool is_frame_entity",
420 state => "exc_pinned",
421 reg_req => { in => [ "sp", "gp", "gp", "gp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
422 emit => '. stmfd %S0!, {%S1, %S2, %S3, %S4}',
423 outs => [ "ptr", "M" ],
426 LoadStackM3Epilogue => {
429 state => "exc_pinned",
430 reg_req => { in => [ "sp", "none" ], out => [ "r11:I", "sp:I|S", "pc:I", "none" ] },
431 emit => '. ldmfd %S0, {%D0, %D1, %D2}',
432 outs => [ "res0", "res1", "res2", "M" ],
439 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
440 emit => '. adf%M %D0, %S0, %S1',
445 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
446 emit =>'. muf%M %D0, %S0, %S1',
451 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
452 emit =>'. fml%M %D0, %S0, %S1',
457 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
458 emit =>'. fmax %S0, %S1, %D0',
463 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
464 emit =>'. fmin %S0, %S1, %D0',
469 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
470 emit => '. suf%M %D0, %S0, %S1'
475 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa" ] },
476 emit => '. rsf%M %D0, %S0, %S1'
480 attr => "ir_mode *op_mode",
481 init_attr => "attr->op_mode = op_mode;",
482 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
483 emit =>'. dvf%M %D0, %S0, %S1',
484 outs => [ "res", "M" ],
488 attr => "ir_mode *op_mode",
489 init_attr => "attr->op_mode = op_mode;",
490 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
491 emit =>'. rdf%M %D0, %S0, %S1',
492 outs => [ "res", "M" ],
496 attr => "ir_mode *op_mode",
497 init_attr => "attr->op_mode = op_mode;",
498 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
499 emit =>'. fdv%M %D0, %S0, %S1',
500 outs => [ "res", "M" ],
504 attr => "ir_mode *op_mode",
505 init_attr => "attr->op_mode = op_mode;",
506 reg_req => { in => [ "fpa", "fpa" ], out => [ "fpa", "none" ] },
507 emit =>'. frd%M %D0, %S0, %S1',
508 outs => [ "res", "M" ],
513 reg_req => { in => [ "fpa" ], out => [ "fpa" ] },
514 emit => '. mvf%M %S0, %D0',
519 reg_req => { in => [ "fpa" ], out => [ "fpa" ] },
520 emit => '. mnf%M %S0, %D0',
525 reg_req => { in => [ "fpa" ], out => [ "fpa" ] },
526 emit => '. abs%M %D0, %S0',
531 reg_req => { in => ["gp"], out => [ "fpa" ] },
532 emit => '. flt%M %D0, %S0',
537 reg_req => { in => ["fpa"], out => [ "gp" ] },
538 emit => '. fix %D0, %S0',
545 attr => "int proj_num",
546 init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
547 reg_req => { in => [ "fpa", "fpa" ], out => [ "none", "none"] },
548 attr_type => "arm_CondJmp_attr_t",
555 attr => "int proj_num",
556 init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
557 reg_req => { in => [ "fpa", "fpa" ], out => [ "none", "none"] },
558 attr_type => "arm_CondJmp_attr_t",
565 attr => "int proj_num",
566 init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
567 reg_req => { in => [ "fpa", "fpa" ], out => [ "none", "none"] },
568 attr_type => "arm_CondJmp_attr_t",
575 attr => "int proj_num",
576 init_attr => "\tset_arm_CondJmp_proj_num(res, proj_num);",
577 reg_req => { in => [ "fpa", "fpa" ], out => [ "none", "none"] },
578 attr_type => "arm_CondJmp_attr_t",
584 state => "exc_pinned",
585 attr => "ir_mode *op_mode",
586 init_attr => "attr->op_mode = op_mode;",
587 reg_req => { in => [ "gp", "none" ], out => [ "fpa", "none" ] },
588 emit => '. ldf%M %D0, [%S0]',
589 outs => [ "res", "M" ],
595 state => "exc_pinned",
596 attr => "ir_mode *op_mode",
597 init_attr => "attr->op_mode = op_mode;",
598 reg_req => { in => [ "gp", "fpa", "none" ], out => [ "none" ] },
599 emit => '. stf%M %S1, [%S0]',
606 reg_req => { in => [ "fpa", "none" ], out => [ "gp", "gp", "none" ] },
607 outs => [ "low", "high", "M" ],
611 reg_req => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "none" ] },
612 emit => '. add %D0, %S0, %S1',
613 outs => [ "stack", "M" ],
617 reg_req => { in => [ "sp", "gp", "none" ], out => [ "sp:I|S", "gp", "none" ] },
618 ins => [ "stack", "size", "mem" ],
619 emit => ". sub %D0, %S0, %S1\n".
621 outs => [ "stack", "addr", "M" ],
626 reg_req => { out => [ "gp" ] },
631 # floating point constants
636 attr => "tarval *tv",
637 init_attr => "attr->tv = tv;",
638 mode => "get_tarval_mode(tv)",
639 reg_req => { out => [ "fpa" ] },
640 attr_type => "arm_fpaConst_attr_t",