sparc: fix wrong reg-width in double->int Conv
[libfirm] / ir / be / sparc / sparc_spec.pl
index 0231f81..0ab5f73 100644 (file)
@@ -1,5 +1,4 @@
 # Creation: 2006/02/13
-# $Id$
 
 $arch = "sparc";
 
@@ -8,7 +7,7 @@ $mode_flags   = "mode_Bu";
 $mode_fpflags = "mode_Bu";
 $mode_fp      = "mode_F";
 $mode_fp2     = "mode_D";
-$mode_fp4     = "mode_E"; # not correct, we need to register a new mode
+$mode_fp4     = "mode_Q";
 
 # available SPARC registers: 8 globals, 24 window regs (8 ins, 8 outs, 8 locals)
 %reg_classes = (
@@ -104,9 +103,11 @@ $mode_fp4     = "mode_E"; # not correct, we need to register a new mode
 # emit source reg or imm dep. on node's arity
        RI  => "${arch}_emit_reg_or_imm(node, -1);",
        R1I => "${arch}_emit_reg_or_imm(node, 1);",
+       R2I => "${arch}_emit_reg_or_imm(node, 2);",
        S0  => "${arch}_emit_source_register(node, 0);",
        S1  => "${arch}_emit_source_register(node, 1);",
        D0  => "${arch}_emit_dest_register(node, 0);",
+       D1  => "${arch}_emit_dest_register(node, 1);",
        HIM => "${arch}_emit_high_immediate(node);",
        LM  => "${arch}_emit_load_mode(node);",
        SM  => "${arch}_emit_store_mode(node);",
@@ -116,36 +117,39 @@ $mode_fp4     = "mode_E"; # not correct, we need to register a new mode
        FCONVD => "${arch}_emit_fp_conv_destination(node);",
        O1     => "${arch}_emit_offset(node, 1);",
        O2     => "${arch}_emit_offset(node, 2);",
+       S0O1   => "${arch}_emit_source_reg_and_offset(node, 0, 1);",
+       S1O2   => "${arch}_emit_source_reg_and_offset(node, 1, 2);",
 );
+$indent_line_func = "sparc_emit_indent()";
 
 $default_attr_type = "sparc_attr_t";
 $default_copy_attr = "sparc_copy_attr";
 
-
 %init_attr = (
-       sparc_attr_t             => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);",
-       sparc_load_store_attr_t  => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);",
-       sparc_jmp_cond_attr_t    => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);",
-       sparc_switch_jmp_attr_t  => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
-                                   "\tinit_sparc_switch_jmp_attributes(res, default_pn, jump_table);\n",
-       sparc_fp_attr_t          => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);\n".
+       sparc_attr_t             => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, n_res);",
+       sparc_load_store_attr_t  => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, n_res);",
+       sparc_jmp_cond_attr_t    => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, n_res);",
+       sparc_switch_jmp_attr_t  => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, n_res);\n".
+                                   "\tinit_sparc_switch_jmp_attributes(res, table, jump_table);\n",
+       sparc_fp_attr_t          => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, n_res);\n".
                                    "\tinit_sparc_fp_attributes(res, fp_mode);\n",
-       sparc_fp_conv_attr_t     => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, exec_units, n_res);".
+       sparc_fp_conv_attr_t     => "\tinit_sparc_attributes(res, irn_flags_, in_reqs, n_res);".
                                    "\tinit_sparc_fp_conv_attributes(res, src_mode, dest_mode);\n",
 );
 
 %compare_attr = (
        sparc_attr_t            => "cmp_attr_sparc",
-       sparc_load_store_attr_t => "cmp_attr_sparc_load_store",
-       sparc_jmp_cond_attr_t   => "cmp_attr_sparc_jmp_cond",
-       sparc_switch_jmp_attr_t => "cmp_attr_sparc_switch_jmp",
        sparc_fp_attr_t         => "cmp_attr_sparc_fp",
        sparc_fp_conv_attr_t    => "cmp_attr_sparc_fp_conv",
+       sparc_jmp_cond_attr_t   => "cmp_attr_sparc_jmp_cond",
+       sparc_load_store_attr_t => "cmp_attr_sparc_load_store",
+       sparc_switch_jmp_attr_t => "cmp_attr_sparc",
 );
 
 %custom_irn_flags = (
        modifies_flags    => "(arch_irn_flags_t)sparc_arch_irn_flag_modifies_flags",
        modifies_fp_flags => "(arch_irn_flags_t)sparc_arch_irn_flag_modifies_fp_flags",
+       has_delay_slot    => "(arch_irn_flags_t)sparc_arch_irn_flag_has_delay_slot",
 );
 
 my %cmp_operand_constructors = (
@@ -265,12 +269,19 @@ Add => {
 },
 
 AddCC => {
-       irn_flags    => [ "rematerializable" ],
+       irn_flags    => [ "rematerializable", "modifies_flags" ],
        emit         => '. addcc %S0, %R1I, %D0',
        outs         => [ "res", "flags" ],
        constructors => \%binopcc_operand_constructors,
 },
 
+AddCCZero => {
+       irn_flags    => [ "rematerializable", "modifies_flags" ],
+       emit         => '. addcc %S0, %R1I, %%g0',
+       mode         => $mode_flags,
+       constructors => \%binopcczero_operand_constructors,
+},
+
 AddX => {
        # At the moment not rematerializable because of assert in beflags.c/
        # (it claims that spiller can't rematerialize flag stuff correctly)
@@ -301,12 +312,19 @@ Sub => {
 },
 
 SubCC => {
-       irn_flags    => [ "rematerializable" ],
+       irn_flags    => [ "rematerializable", "modifies_flags" ],
        emit         => '. subcc %S0, %R1I, %D0',
        outs         => [ "res", "flags" ],
        constructors => \%binopcc_operand_constructors,
 },
 
+SubCCZero => {
+       irn_flags    => [ "rematerializable", "modifies_flags" ],
+       emit         => '. subcc %S0, %R1I, %%g0',
+       mode         => $mode_flags,
+       constructors => \%binopcczero_operand_constructors,
+},
+
 SubX => {
        # Not rematerializable (see AddX)
        emit         => '. subx %S0, %R1I, %D0',
@@ -348,7 +366,7 @@ Ld => {
        ins       => [ "ptr", "mem" ],
        outs      => [ "res", "M" ],
        attr_type => "sparc_load_store_attr_t",
-       emit      => '. ld%LM [%S0%O1], %D0'
+       emit      => '. ld%LM [%S0O1], %D0'
 },
 
 SetHi => {
@@ -382,7 +400,7 @@ St => {
        ins       => [ "val", "ptr", "mem" ],
        outs      => [ "M" ],
        attr_type => "sparc_load_store_attr_t",
-       emit      => '. st%SM %S0, [%S1%O2]'
+       emit      => '. st%SM %S0, [%S1O2]'
 },
 
 Save => {
@@ -405,22 +423,19 @@ Save => {
 },
 
 Restore => {
-       emit => '. restore %S0, %R1I, %D0',
-       outs => [ "stack" ],
-       ins  => [ "stack" ],
+       outs => [ "stack", "res" ],
        constructors => {
                imm => {
                        attr       => "ir_entity *immediate_entity, int32_t immediate_value",
                        custominit => "sparc_set_attr_imm(res, immediate_entity, immediate_value);",
-                       reg_req    => { in => [ "sp" ], out => [ "sp:I|S" ] },
-                       ins        => [ "stack" ],
+                       reg_req    => { in => [ "frame_pointer", "gp" ], out => [ "sp:I|S", "gp" ] },
+                       ins        => [ "frame_pointer", "left" ],
                },
                reg => {
-                       reg_req    => { in => [ "sp", "gp" ], out => [ "sp:I|S" ] },
-                       ins        => [ "stack", "increment" ],
+                       reg_req    => { in => [ "frame_pointer", "gp", "gp" ], out => [ "sp:I|S", "gp" ] },
+                       ins        => [ "frame_pointer", "left", "right" ],
                }
        },
-       mode => $mode_gp,
 },
 
 RestoreZero => {
@@ -460,6 +475,7 @@ FrameAddr => {
 
 Bicc => {
        op_flags  => [ "labeled", "cfopcode", "forking" ],
+       irn_flags => [ "has_delay_slot" ],
        state     => "pinned",
        mode      => "mode_T",
        attr_type => "sparc_jmp_cond_attr_t",
@@ -472,6 +488,7 @@ Bicc => {
 
 fbfcc => {
        op_flags  => [ "labeled", "cfopcode", "forking" ],
+       irn_flags => [ "has_delay_slot" ],
        state     => "pinned",
        mode      => "mode_T",
        attr_type => "sparc_jmp_cond_attr_t",
@@ -483,6 +500,8 @@ fbfcc => {
 },
 
 Ba => {
+       # Note: has_delay_slot depends on wether it is a fallthrough or not, so we
+       # have special code for this in sparc_emitter
        state     => "pinned",
        op_flags  => [ "cfopcode" ],
        irn_flags => [ "simple_jump" ],
@@ -496,11 +515,12 @@ Start => {
        ins       => [],
 },
 
-# This is a JumpLink instruction, but with the addition that you can add custom
+# This is a Jump instruction, but with the addition that you can add custom
 # register constraints to model your calling conventions
 Return => {
        state     => "pinned",
        op_flags  => [ "cfopcode" ],
+       irn_flags => [ "has_delay_slot" ],
        arity     => "variable",
        mode      => "mode_X",
        constructors => {
@@ -517,8 +537,10 @@ Return => {
        },
 },
 
+# This is a JumpLink instruction, but with the addition that you can add custom
+# register constraints to model your calling conventions
 Call => {
-       irn_flags => [ "modifies_flags", "modifies_fp_flags" ],
+       irn_flags => [ "modifies_flags", "modifies_fp_flags", "has_delay_slot" ],
        state     => "exc_pinned",
        arity     => "variable",
        out_arity => "variable",
@@ -526,7 +548,7 @@ Call => {
                imm => {
                        attr       => "ir_entity *entity, int32_t offset, bool aggregate_return",
                        custominit => "\tsparc_set_attr_imm(res, entity, offset);".
-                                     "\tif (aggregate_return) arch_add_irn_flags(res, sparc_arch_irn_flag_aggregate_return);",
+                                     "\tif (aggregate_return) arch_add_irn_flags(res, (arch_irn_flags_t)sparc_arch_irn_flag_aggregate_return);",
                        arity     => "variable",
                        out_arity => "variable",
                },
@@ -534,7 +556,7 @@ Call => {
                        attr       => "bool aggregate_return",
                        arity      => "variable",
                        out_arity  => "variable",
-                       custominit => "\tif (aggregate_return) arch_add_irn_flags(res, sparc_arch_irn_flag_aggregate_return);",
+                       custominit => "\tif (aggregate_return) arch_add_irn_flags(res, (arch_irn_flags_t)sparc_arch_irn_flag_aggregate_return);",
                }
        },
 },
@@ -548,12 +570,13 @@ Cmp => {  # aka SubccZero
 
 SwitchJmp => {
        op_flags     => [ "labeled", "cfopcode", "forking" ],
+       irn_flags    => [ "has_delay_slot" ],
        state        => "pinned",
        mode         => "mode_T",
        reg_req      => { in => [ "gp" ], out => [ ] },
+       out_arity    => "variable",
        attr_type    => "sparc_switch_jmp_attr_t",
-       attr         => "long default_pn, ir_entity *jump_table",
-       init_attr => "info->out_infos = NULL;", # XXX ugly hack for out requirements
+       attr         => "const ir_switch_table *table, ir_entity *jump_table",
 },
 
 Sll => {
@@ -668,6 +691,13 @@ Mul => {
        constructors => \%binop_operand_constructors,
 },
 
+MulCCZero => {
+       irn_flags    => [ "rematerializable", "modifies_flags" ],
+       emit         => '. smulcc %S0, %R1I, %%g0',
+       mode         => $mode_flags,
+       constructors => \%binopcczero_operand_constructors,
+},
+
 SMulh => {
        irn_flags    => [ "rematerializable" ],
        outs         => [ "low", "high" ],
@@ -681,7 +711,7 @@ UMulh => {
 },
 
 SDiv => {
-       irn_flags    => [ "rematerializable" ],
+       irn_flags    => [ "rematerializable", "has_delay_slot" ],
        state        => "exc_pinned",
        ins          => [ "dividend_high", "dividend_low", "divisor" ],
        outs         => [ "res", "M" ],
@@ -689,7 +719,7 @@ SDiv => {
 },
 
 UDiv => {
-       irn_flags    => [ "rematerializable" ],
+       irn_flags    => [ "rematerializable", "has_delay_slot" ],
        state        => "exc_pinned",
        ins          => [ "dividend_high", "dividend_low", "divisor" ],
        outs         => [ "res", "M" ],