7 $mode_flags = "mode_Bu";
8 $mode_fpflags = "mode_Bu";
11 $mode_fp4 = "mode_E"; # not correct, we need to register a new mode
13 # available SPARC registers: 8 globals, 24 window regs (8 ins, 8 outs, 8 locals)
49 { name => "frame_pointer", realname => "fp" },
54 { name => "fpflags" },
55 { mode => $mode_fpflags, flags => "manual_ra" }
59 { mode => $mode_flags, flags => "manual_ra" }
63 { mode => $mode_gp, flags => "manual_ra" }
65 # fp registers can be accessed any time
104 # emit source reg or imm dep. on node's arity
105 RI => "${arch}_emit_reg_or_imm(node, -1);",
106 R1I => "${arch}_emit_reg_or_imm(node, 1);",
107 S0 => "${arch}_emit_source_register(node, 0);",
108 S1 => "${arch}_emit_source_register(node, 1);",
109 D0 => "${arch}_emit_dest_register(node, 0);",
110 HIM => "${arch}_emit_high_immediate(node);",
111 LM => "${arch}_emit_load_mode(node);",
112 SM => "${arch}_emit_store_mode(node);",
113 FLSM => "${arch}_emit_float_load_store_mode(node);",
114 FPM => "${arch}_emit_fp_mode_suffix(node);",
115 FCONVS => "${arch}_emit_fp_conv_source(node);",
116 FCONVD => "${arch}_emit_fp_conv_destination(node);",
117 O1 => "${arch}_emit_offset(node, 1);",
118 O2 => "${arch}_emit_offset(node, 2);",
121 $default_attr_type = "sparc_attr_t";
122 $default_copy_attr = "sparc_copy_attr";
125 sparc_attr_t => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);",
126 sparc_load_store_attr_t => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);",
127 sparc_jmp_cond_attr_t => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);",
128 sparc_switch_jmp_attr_t => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
129 "\tinit_sparc_switch_jmp_attributes(res, default_pn, jump_table);\n",
130 sparc_fp_attr_t => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
131 "\tinit_sparc_fp_attributes(res, fp_mode);\n",
132 sparc_fp_conv_attr_t => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);".
133 "\tinit_sparc_fp_conv_attributes(res, src_mode, dest_mode);\n",
137 sparc_attr_t => "cmp_attr_sparc",
138 sparc_load_store_attr_t => "cmp_attr_sparc_load_store",
139 sparc_jmp_cond_attr_t => "cmp_attr_sparc_jmp_cond",
140 sparc_switch_jmp_attr_t => "cmp_attr_sparc_switch_jmp",
141 sparc_fp_attr_t => "cmp_attr_sparc_fp",
142 sparc_fp_conv_attr_t => "cmp_attr_sparc_fp_conv",
145 %custom_irn_flags = (
146 modifies_flags => "(arch_irn_flags_t)sparc_arch_irn_flag_modifies_flags",
147 modifies_fp_flags => "(arch_irn_flags_t)sparc_arch_irn_flag_modifies_fp_flags",
148 has_delay_slot => "(arch_irn_flags_t)sparc_arch_irn_flag_has_delay_slot",
151 my %cmp_operand_constructors = (
153 attr => "ir_entity *immediate_entity, int32_t immediate_value",
154 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
155 reg_req => { in => [ "gp" ], out => [ "flags" ] },
159 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
160 ins => [ "left", "right" ],
164 my %binop_operand_constructors = (
166 attr => "ir_entity *immediate_entity, int32_t immediate_value",
167 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
168 reg_req => { in => [ "gp" ], out => [ "gp" ] },
172 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
173 ins => [ "left", "right" ],
177 my %binopcc_operand_constructors = (
179 attr => "ir_entity *immediate_entity, int32_t immediate_value",
180 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
181 reg_req => { in => [ "gp" ], out => [ "gp", "flags" ] },
185 reg_req => { in => [ "gp", "gp" ], out => [ "gp", "flags" ] },
186 ins => [ "left", "right" ],
190 my %binopx_operand_constructors = (
192 attr => "ir_entity *immediate_entity, int32_t immediate_value",
193 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
194 reg_req => { in => [ "gp", "flags" ], out => [ "gp" ] },
195 ins => [ "left", "carry" ],
198 reg_req => { in => [ "gp", "gp", "flags" ], out => [ "gp" ] },
199 ins => [ "left", "right", "carry" ],
204 my %binopcczero_operand_constructors = (
206 attr => "ir_entity *immediate_entity, int32_t immediate_value",
207 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
208 reg_req => { in => [ "gp" ], out => [ "flags" ] },
212 reg_req => { in => [ "gp", "gp" ], out => [ "flags" ] },
213 ins => [ "left", "right" ],
217 my %div_operand_constructors = (
219 attr => "ir_entity *immediate_entity, int32_t immediate_value",
220 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
221 reg_req => { in => [ "gp", "gp" ], out => [ "gp" ] },
224 reg_req => { in => [ "gp", "gp", "gp" ], out => [ "gp" ] },
228 my %float_binop_constructors = (
230 reg_req => { in => [ "fp", "fp" ], out => [ "fp" ] },
234 reg_req => { in => [ "fp:a|2", "fp:a|2" ], out => [ "fp:a|2" ] },
238 reg_req => { in => [ "fp:a|4", "fp:a|4" ], out => [ "fp:a|4" ] },
243 my %float_unop_constructors = (
245 reg_req => { in => [ "fp" ], out => [ "fp" ] },
249 reg_req => { in => [ "fp:a|2" ], out => [ "fp:a|2" ] },
253 reg_req => { in => [ "fp:a|4" ], out => [ "fp:a|4" ] },
261 irn_flags => [ "rematerializable" ],
263 emit => '. add %S0, %R1I, %D0',
264 constructors => \%binop_operand_constructors,
268 irn_flags => [ "rematerializable" ],
269 emit => '. addcc %S0, %R1I, %D0',
270 outs => [ "res", "flags" ],
271 constructors => \%binopcc_operand_constructors,
275 # At the moment not rematerializable because of assert in beflags.c/
276 # (it claims that spiller can't rematerialize flag stuff correctly)
277 #irn_flags => [ "rematerializable" ],
278 emit => '. addx %S0, %R1I, %D0',
279 constructors => \%binopx_operand_constructors,
284 ins => [ "left", "right" ],
285 outs => [ "res", "flags" ],
291 ins => [ "left", "right", "flags_input" ],
297 irn_flags => [ "rematerializable" ],
299 emit => '. sub %S0, %R1I, %D0',
300 constructors => \%binop_operand_constructors,
304 irn_flags => [ "rematerializable" ],
305 emit => '. subcc %S0, %R1I, %D0',
306 outs => [ "res", "flags" ],
307 constructors => \%binopcc_operand_constructors,
311 # Not rematerializable (see AddX)
312 emit => '. subx %S0, %R1I, %D0',
313 constructors => \%binopx_operand_constructors,
318 ins => [ "left", "right" ],
319 outs => [ "res", "flags" ],
325 ins => [ "left", "right", "flags_input" ],
332 op_flags => [ "labeled" ],
333 state => "exc_pinned",
336 reg_req => { in => [ "gp", "none" ], out => [ "gp", "none" ] },
337 ins => [ "ptr", "mem" ],
338 attr => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
339 custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
342 reg_req => { in => [ "gp", "gp", "none" ], out => [ "gp", "none" ] },
343 ins => [ "ptr", "ptr2", "mem" ],
344 attr => "ir_mode *ls_mode",
345 custominit => "init_sparc_load_store_attributes(res, ls_mode, NULL, 0, false, true);",
348 ins => [ "ptr", "mem" ],
349 outs => [ "res", "M" ],
350 attr_type => "sparc_load_store_attr_t",
351 emit => '. ld%LM [%S0%O1], %D0'
355 irn_flags => [ "rematerializable" ],
358 reg_req => { in => [], out => [ "gp" ] },
359 attr => "ir_entity *entity, int32_t immediate_value",
360 custominit => "sparc_set_attr_imm(res, entity, immediate_value);",
361 emit => '. sethi %HIM, %D0'
365 op_flags => [ "labeled" ],
367 state => "exc_pinned",
370 reg_req => { in => [ "gp", "gp", "none" ], out => [ "none" ] },
371 ins => [ "val", "ptr", "mem" ],
372 attr => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
373 custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
376 reg_req => { in => [ "gp", "gp", "gp", "none" ], out => [ "none" ] },
377 ins => [ "val", "ptr", "ptr2", "mem" ],
378 attr => "ir_mode *ls_mode",
379 custominit => "init_sparc_load_store_attributes(res, ls_mode, NULL, 0, false, true);",
382 ins => [ "val", "ptr", "mem" ],
384 attr_type => "sparc_load_store_attr_t",
385 emit => '. st%SM %S0, [%S1%O2]'
389 emit => '. save %S0, %R1I, %D0',
394 attr => "ir_entity *immediate_entity, int32_t immediate_value",
395 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
396 reg_req => { in => [ "sp" ], out => [ "sp:I|S" ] },
400 reg_req => { in => [ "sp", "gp" ], out => [ "sp:I|S" ] },
401 ins => [ "stack", "increment" ],
408 emit => '. restore %S0, %R1I, %D0',
413 attr => "ir_entity *immediate_entity, int32_t immediate_value",
414 custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
415 reg_req => { in => [ "sp" ], out => [ "sp:I|S" ] },
419 reg_req => { in => [ "sp", "gp" ], out => [ "sp:I|S" ] },
420 ins => [ "stack", "increment" ],
427 reg_req => { in => [ "frame_pointer" ], out => [ "sp:I|S" ] },
428 ins => [ "frame_pointer" ],
435 reg_req => { in => [ "sp", "gp" ], out => [ "sp:I|S" ] },
436 ins => [ "stack", "size" ],
438 emit => ". sub %S0, %S1, %D0\n",
443 reg_req => { in => [ "sp", "gp" ], out => [ "sp:I|S" ] },
444 ins => [ "stack", "size" ],
446 emit => ". add %S0, %S1, %D0\n",
451 op_flags => [ "constlike" ],
452 irn_flags => [ "rematerializable" ],
453 attr => "ir_entity *entity, int32_t offset",
454 reg_req => { in => [ "gp" ], out => [ "gp" ] },
456 attr_type => "sparc_attr_t",
457 custominit => "sparc_set_attr_imm(res, entity, offset);",
462 op_flags => [ "labeled", "cfopcode", "forking" ],
463 irn_flags => [ "has_delay_slot" ],
466 attr_type => "sparc_jmp_cond_attr_t",
467 attr => "ir_relation relation, bool is_unsigned",
468 init_attr => "\tinit_sparc_jmp_cond_attr(res, relation, is_unsigned);",
469 reg_req => { in => [ "flags" ], out => [ "none", "none" ] },
471 outs => [ "false", "true" ],
475 op_flags => [ "labeled", "cfopcode", "forking" ],
476 irn_flags => [ "has_delay_slot" ],
479 attr_type => "sparc_jmp_cond_attr_t",
480 attr => "ir_relation relation",
481 init_attr => "\tinit_sparc_jmp_cond_attr(res, relation, false);",
482 reg_req => { in => [ "fpflags" ], out => [ "none", "none" ] },
484 outs => [ "false", "true" ],
488 # Note: has_delay_slot depends on wether it is a fallthrough or not, so we
489 # have special code for this in sparc_emitter
491 op_flags => [ "cfopcode" ],
492 irn_flags => [ "simple_jump" ],
493 reg_req => { out => [ "none" ] },
499 out_arity => "variable",
503 # This is a JumpLink instruction, but with the addition that you can add custom
504 # register constraints to model your calling conventions
507 op_flags => [ "cfopcode" ],
508 irn_flags => [ "has_delay_slot" ],
513 attr => "ir_entity *entity, int32_t offset",
514 custominit => "\tsparc_set_attr_imm(res, entity, offset);",
516 reg_req => { out => [ "none" ] },
520 reg_req => { out => [ "none" ] },
526 irn_flags => [ "modifies_flags", "modifies_fp_flags", "has_delay_slot" ],
527 state => "exc_pinned",
529 out_arity => "variable",
532 attr => "ir_entity *entity, int32_t offset, bool aggregate_return",
533 custominit => "\tsparc_set_attr_imm(res, entity, offset);".
534 "\tif (aggregate_return) arch_add_irn_flags(res, sparc_arch_irn_flag_aggregate_return);",
536 out_arity => "variable",
539 attr => "bool aggregate_return",
541 out_arity => "variable",
542 custominit => "\tif (aggregate_return) arch_add_irn_flags(res, sparc_arch_irn_flag_aggregate_return);",
547 Cmp => { # aka SubccZero
548 irn_flags => [ "rematerializable", "modifies_flags" ],
549 emit => '. cmp %S0, %R1I',
551 constructors => \%binopcczero_operand_constructors,
555 op_flags => [ "labeled", "cfopcode", "forking" ],
556 irn_flags => [ "has_delay_slot" ],
559 reg_req => { in => [ "gp" ], out => [ ] },
560 attr_type => "sparc_switch_jmp_attr_t",
561 attr => "long default_pn, ir_entity *jump_table",
562 init_attr => "info->out_infos = NULL;", # XXX ugly hack for out requirements
566 irn_flags => [ "rematerializable" ],
568 emit => '. sll %S0, %R1I, %D0',
569 constructors => \%binop_operand_constructors,
573 irn_flags => [ "rematerializable" ],
575 emit => '. srl %S0, %R1I, %D0',
576 constructors => \%binop_operand_constructors,
580 irn_flags => [ "rematerializable" ],
582 emit => '. sra %S0, %R1I, %D0',
583 constructors => \%binop_operand_constructors,
587 irn_flags => [ "rematerializable" ],
589 emit => '. and %S0, %R1I, %D0',
590 constructors => \%binop_operand_constructors,
594 irn_flags => [ "rematerializable", "modifies_flags" ],
595 emit => '. andcc %S0, %R1I, %%g0',
597 constructors => \%binopcczero_operand_constructors,
601 irn_flags => [ "rematerializable" ],
603 emit => '. andn %S0, %R1I, %D0',
604 constructors => \%binop_operand_constructors,
608 irn_flags => [ "rematerializable", "modifies_flags" ],
609 emit => '. andncc %S0, %R1I, %%g0',
611 constructors => \%binopcczero_operand_constructors,
615 irn_flags => [ "rematerializable" ],
617 emit => '. or %S0, %R1I, %D0',
618 constructors => \%binop_operand_constructors,
622 irn_flags => [ "rematerializable", "modifies_flags" ],
623 emit => '. orcc %S0, %R1I, %%g0',
625 constructors => \%binopcczero_operand_constructors,
629 irn_flags => [ "rematerializable" ],
631 emit => '. orn %S0, %R1I, %D0',
632 constructors => \%binop_operand_constructors,
636 irn_flags => [ "rematerializable", "modifies_flags" ],
637 emit => '. orncc %S0, %R1I, %%g0',
639 constructors => \%binopcczero_operand_constructors,
643 irn_flags => [ "rematerializable" ],
645 emit => '. xor %S0, %R1I, %D0',
646 constructors => \%binop_operand_constructors,
650 irn_flags => [ "rematerializable", "modifies_flags" ],
651 emit => '. xorcc %S0, %R1I, %%g0',
653 constructors => \%binopcczero_operand_constructors,
657 irn_flags => [ "rematerializable" ],
659 emit => '. xnor %S0, %R1I, %D0',
660 constructors => \%binop_operand_constructors,
664 irn_flags => [ "rematerializable", "modifies_flags" ],
665 emit => '. xnorcc %S0, %R1I, %%g0',
667 constructors => \%binopcczero_operand_constructors,
671 irn_flags => [ "rematerializable" ],
673 emit => '. smul %S0, %R1I, %D0',
674 constructors => \%binop_operand_constructors,
678 irn_flags => [ "rematerializable" ],
679 outs => [ "low", "high" ],
680 constructors => \%binop_operand_constructors,
684 irn_flags => [ "rematerializable" ],
685 outs => [ "low", "high" ],
686 constructors => \%binop_operand_constructors,
690 irn_flags => [ "rematerializable", "has_delay_slot" ],
691 state => "exc_pinned",
692 ins => [ "dividend_high", "dividend_low", "divisor" ],
693 outs => [ "res", "M" ],
694 constructors => \%div_operand_constructors,
698 irn_flags => [ "rematerializable", "has_delay_slot" ],
699 state => "exc_pinned",
700 ins => [ "dividend_high", "dividend_low", "divisor" ],
701 outs => [ "res", "M" ],
702 constructors => \%div_operand_constructors,
706 irn_flags => [ "rematerializable", "modifies_fp_flags" ],
707 emit => '. fcmp%FPM %S0, %S1',
708 attr_type => "sparc_fp_attr_t",
709 attr => "ir_mode *fp_mode",
710 mode => $mode_fpflags,
713 reg_req => { in => [ "fp", "fp" ], out => [ "fpflags" ] },
716 reg_req => { in => [ "fp:a|2", "fp:a|2" ], out => [ "fpflags" ] },
719 reg_req => { in => [ "fp:a|4", "fp:a|4" ], out => [ "fpflags" ] },
725 op_flags => [ "commutative" ],
726 irn_flags => [ "rematerializable" ],
727 emit => '. fadd%FPM %S0, %S1, %D0',
728 attr_type => "sparc_fp_attr_t",
729 attr => "ir_mode *fp_mode",
730 ins => [ "left", "right" ],
731 constructors => \%float_binop_constructors,
735 irn_flags => [ "rematerializable" ],
736 emit => '. fsub%FPM %S0, %S1, %D0',
737 attr_type => "sparc_fp_attr_t",
738 attr => "ir_mode *fp_mode",
739 ins => [ "left", "right" ],
740 constructors => \%float_binop_constructors,
744 irn_flags => [ "rematerializable" ],
745 op_flags => [ "commutative" ],
746 emit =>'. fmul%FPM %S0, %S1, %D0',
747 attr_type => "sparc_fp_attr_t",
748 attr => "ir_mode *fp_mode",
749 ins => [ "left", "right" ],
750 constructors => \%float_binop_constructors,
754 irn_flags => [ "rematerializable" ],
755 emit => '. fdiv%FPM %S0, %S1, %D0',
756 attr_type => "sparc_fp_attr_t",
757 attr => "ir_mode *fp_mode",
758 ins => [ "left", "right" ],
759 outs => [ "res", "M" ],
762 reg_req => { in => [ "fp", "fp" ], out => [ "fp", "none" ] },
765 reg_req => { in => [ "fp:a|2", "fp:a|2" ], out => [ "fp:a|2", "none" ] },
768 reg_req => { in => [ "fp:a|4", "fp:a|4" ], out => [ "fp:a|4", "none" ] },
774 irn_flags => [ "rematerializable" ],
775 reg_req => { in => [ "fp" ], out => [ "fp" ] },
776 # note that we only need the first register even for wide-values
777 emit => '. fnegs %S0, %D0',
778 attr_type => "sparc_fp_attr_t",
779 attr => "ir_mode *fp_mode",
781 constructors => \%float_unop_constructors,
785 irn_flags => [ "rematerializable" ],
786 # note that we only need the first register even for wide-values
787 emit => '. fabs %S0, %D0',
788 attr_type => "sparc_fp_attr_t",
789 attr => "ir_mode *fp_mode",
791 constructors => \%float_unop_constructors,
795 irn_flags => [ "rematerializable" ],
796 emit => '. f%FCONVS%.to%FCONVD %S0, %D0',
797 attr_type => "sparc_fp_conv_attr_t",
798 attr => "ir_mode *src_mode, ir_mode *dest_mode",
801 reg_req => { in => [ "fp" ], out => [ "fp:a|2" ] },
805 reg_req => { in => [ "fp" ], out => [ "fp:a|2" ] },
809 reg_req => { in => [ "fp:a|2" ], out => [ "fp" ] },
813 reg_req => { in => [ "fp:a|2" ], out => [ "fp:a|4" ] },
817 reg_req => { in => [ "fp:a|4" ], out => [ "fp" ] },
821 reg_req => { in => [ "fp:a|4" ], out => [ "fp:a|2" ] },
828 irn_flags => [ "rematerializable" ],
829 emit => '. fito%FPM %S0, %D0',
830 attr_type => "sparc_fp_attr_t",
831 attr => "ir_mode *fp_mode",
834 reg_req => { in => [ "fp" ], out => [ "fp" ] },
838 reg_req => { in => [ "fp" ], out => [ "fp:a|2" ] },
842 reg_req => { in => [ "fp" ], out => [ "fp:a|4" ] },
849 irn_flags => [ "rematerializable" ],
850 emit => '. f%FPM%.toi %S0, %D0',
851 attr_type => "sparc_fp_attr_t",
852 attr => "ir_mode *fp_mode",
856 reg_req => { in => [ "fp" ], out => [ "fp" ] },
859 reg_req => { in => [ "fp:a|2" ], out => [ "fp" ] },
862 reg_req => { in => [ "fp:a|4" ], out => [ "fp" ] },
868 op_flags => [ "labeled" ],
869 state => "exc_pinned",
872 reg_req => { in => [ "gp", "none" ], out => [ "fp", "none" ] },
875 reg_req => { in => [ "gp", "none" ], out => [ "fp:a|2", "none" ] },
878 reg_req => { in => [ "gp", "none" ], out => [ "fp:a|4", "none" ] },
881 ins => [ "ptr", "mem" ],
882 outs => [ "res", "M" ],
883 attr_type => "sparc_load_store_attr_t",
884 attr => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
885 custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
886 emit => '. ld%FLSM [%S0%O1], %D0'
890 op_flags => [ "labeled" ],
891 state => "exc_pinned",
894 reg_req => { in => [ "fp", "gp", "none" ], out => [ "none" ] },
897 reg_req => { in => [ "fp:a|2", "gp", "none" ], out => [ "none" ] },
900 reg_req => { in => [ "fp:a|4", "gp", "none" ], out => [ "none" ] },
903 ins => [ "val", "ptr", "mem" ],
905 attr_type => "sparc_load_store_attr_t",
906 attr => "ir_mode *ls_mode, ir_entity *entity, int32_t offset, bool is_frame_entity",
907 custominit => "init_sparc_load_store_attributes(res, ls_mode, entity, offset, is_frame_entity, false);",
908 emit => '. st%FLSM %S0, [%S1%O2]',