PreviousUpNext

15.4.380  src/lib/compiler/back/low/sparc32/jmp/delay-slots-sparc32-g.pkg

## delay-slots-sparc32-g.pkg

# Compiled by:
#     src/lib/compiler/back/low/sparc32/backend-sparc32.lib

# We get invoked by:
#
#     src/lib/compiler/back/low/main/sparc32/backend-lowhalf-sparc32.pkg

stipulate
    package cos =  registerkinds_junk::cos;                                     # "cos" == "colorset".
    package lem =  lowhalf_error_message;                                       # lowhalf_error_message         is from   src/lib/compiler/back/low/control/lowhalf-error-message.pkg
    package rkj =  registerkinds_junk;                                          # registerkinds_junk            is from   src/lib/compiler/back/low/code/registerkinds-junk.pkg
herein

    generic package   delay_slots_sparc32_g   (
        #             =====================
        #
        package mcf: Machcode_Sparc32;                                          # Machcode_Sparc32              is from   src/lib/compiler/back/low/sparc32/code/machcode-sparc32.codemade.api

        package mu:  Machcode_Universals                                        # Machcode_Universals           is from   src/lib/compiler/back/low/code/machcode-universals.api
                     where
                         mcf == mcf;                                            # "mcf" == "machcode_form" (abstract machine code).

        #  sharing/defn conflict:   sharing p::i = i
    )
    : (weak)  Delay_Slot_Properties                                             # Delay_Slot_Properties         is from   src/lib/compiler/back/low/jmp/delay-slot-props.api
    {
        # Export to client packages:
        #
        package mcf =  mcf;                                                     # "mcf" == "machcode_form" (abstract machine code).

        stipulate
            package rgk =  mcf::rgk;                                            # "rgk" == "registerkinds".
        herein

            fun error msg
                =
                lem::error("SparcDelaySlotProps", msg);

            Delay_Slot = D_NONE | D_ERROR | D_ALWAYS | D_TAKEN | D_FALLTHRU;

            delay_slot_bytes = 4;

            fun delay_slot { instruction, backward }
                =
                case instruction
                    #
                    mcf::BASE_OP (mcf::CALL { nop, ... } ) => { n=>FALSE, n_on=>D_ERROR, n_off=>D_ALWAYS, nop };
                    mcf::BASE_OP (mcf::JMP { nop, ... } ) => { n=>FALSE, n_on=>D_ERROR, n_off=>D_ALWAYS, nop };
                    mcf::BASE_OP (mcf::JMPL { nop, ... } ) => { n=>FALSE, n_on=>D_ERROR, n_off=>D_ALWAYS, nop };
                    mcf::BASE_OP (mcf::RET { nop, ... } )  => { n=>FALSE, n_on=>D_ERROR, n_off=>D_ALWAYS, nop };
                    mcf::BASE_OP (mcf::BICC { b=>mcf::BA, a, nop, ... } ) => { n=>FALSE, n_on=>D_NONE, n_off=>D_ALWAYS, nop };
                    mcf::BASE_OP (mcf::BICC { a, nop, ... } ) => { n=>a, n_on=>D_TAKEN, n_off=>D_ALWAYS, nop };
                    mcf::BASE_OP (mcf::FBFCC { a, nop, ... } ) => { n=>a, n_on=>D_TAKEN, n_off=>D_ALWAYS, nop };
                    mcf::BASE_OP (mcf::BR { a, nop, ... } ) => { n=>a, n_on=>D_TAKEN, n_off=>D_ALWAYS, nop };
                    mcf::BASE_OP (mcf::BP { a, nop, ... } ) => { n=>a, n_on=>D_TAKEN, n_off=>D_ALWAYS, nop };
                    mcf::BASE_OP (mcf::FCMP { nop, ... } ) => { n=>FALSE, n_on=>D_ERROR, n_off=>D_ALWAYS, nop };
                    mcf::NOTE { op, ... } => delay_slot { instruction => op, backward };
                    #
                    _ => { n=>FALSE, n_on=>D_ERROR, n_off=>D_NONE, nop=>FALSE };
                esac;

            fun enable_delay_slot { instruction, n, nop }
                =
                case (instruction, n)
                    #
                    (mcf::BASE_OP (mcf::JMP { r, i, labs, ... } ), FALSE)         =>   mcf::jmp { r, i, labs, nop };
                    (mcf::BASE_OP (mcf::RET { leaf, ... } ), FALSE)               =>   mcf::ret { leaf, nop };
                    (mcf::BASE_OP (mcf::BICC { b, a, label, ... } ), _)           =>   mcf::bicc { b, a=>n, nop, label };
                    (mcf::BASE_OP (mcf::FBFCC { b, a, label, ... } ), _)          =>   mcf::fbfcc { b, a=>n, nop, label };
                    (mcf::BASE_OP (mcf::BR { nop, label, p, r, rcond, ... } ), _) =>   mcf::br { rcond, r, a=>n, nop, label, p };
                    (mcf::BASE_OP (mcf::BP { nop, label, p, cc, b, ... } ), _)    =>   mcf::bp { b, cc, a=>n, nop, label, p };
                    (mcf::BASE_OP (mcf::FCMP { cmp, r1, r2, ... } ), FALSE)       =>   mcf::fcmp { cmp, r1, r2, nop };
                    (mcf::NOTE { op, note }, n)                                  =>   mcf::NOTE { op => enable_delay_slot { instruction => op, n, nop }, note };

                    (mcf::BASE_OP (mcf::CALL { defs, uses, label, cuts_to, ramregion, ... } ), FALSE)
                        => 
                        mcf::call { defs, uses, label, cuts_to, nop, ramregion };

                    (mcf::BASE_OP (mcf::JMPL { r, i, d, defs, uses, ramregion, cuts_to, ... } ), FALSE)
                        => 
                        mcf::jmpl { r, i, d, defs, uses, cuts_to, nop, ramregion };

                    _ => error "enableDelaySlot";
                esac;

            def_use_i = mu::def_use rkj::INT_REGISTER;
            def_use_f = mu::def_use rkj::FLOAT_REGISTER;

            psr     = [rgk::psr]; 
            fsr     = [rgk::fsr];
            y       = [rgk::y];

            always_zero_register
                =
                null_or::the                                                    # We know it exists on sparc32.
                    (rgk::get_always_zero_register  rkj::INT_REGISTER);

            everything = [rgk::y, rgk::psr, rgk::fsr];

            fun conflict { src=>i, dst=>j }
                = 
                {   fun cc mcf::ANDCC  => TRUE;
                        cc mcf::ANDNCC => TRUE;
                        cc mcf::ORCC   => TRUE;
                        cc mcf::ORNCC  => TRUE;
                        cc mcf::XORCC  => TRUE;
                        cc mcf::XNORCC => TRUE;
                        cc mcf::ADDCC  => TRUE;
                        cc mcf::TADDCC  => TRUE;
                        cc mcf::TADDTVCC => TRUE;
                        cc mcf::SUBCC => TRUE;
                        cc mcf::TSUBCC => TRUE;
                        cc mcf::TSUBTVCC=> TRUE;
                        cc mcf::UMULCC => TRUE;
                        cc mcf::SMULCC => TRUE;
                        cc mcf::UDIVCC => TRUE;
                        cc mcf::SDIVCC => TRUE; 
                        cc _ => FALSE;
                    end;

                    fun def_use_other (mcf::BASE_OP (mcf::BICC { b=>mcf::BA, ... } )) => ([],[]);
                        def_use_other (mcf::BASE_OP (mcf::BICC _))    => ([], psr);
                        def_use_other (mcf::BASE_OP (mcf::TICC _))    => ([], psr);
                        def_use_other (mcf::BASE_OP (mcf::WRY _))     => (y,[]);
                        def_use_other (mcf::BASE_OP (mcf::RDY _))     => ([], y);
                        def_use_other (mcf::BASE_OP (mcf::FCMP _))    => (fsr,[]);
                        def_use_other (mcf::BASE_OP (mcf::FBFCC _))   => ([], fsr);
                        def_use_other (mcf::BASE_OP (mcf::MOVICC _))  => ([], psr);
                        def_use_other (mcf::BASE_OP (mcf::MOVFCC _))  => ([], fsr);
                        def_use_other (mcf::BASE_OP (mcf::FMOVICC _)) => ([], psr);
                        def_use_other (mcf::BASE_OP (mcf::FMOVFCC _)) => ([], fsr);
                        def_use_other (mcf::BASE_OP (mcf::CALL _))    => (everything,[]);
                        def_use_other (mcf::BASE_OP (mcf::JMPL _))    => (everything,[]);
                        def_use_other (mcf::BASE_OP (mcf::ARITH { a, ... } )) =>  if (cc a) (psr,[]);
                                                                                else      ([],[]);
                                                                                fi;
                        def_use_other (mcf::NOTE { op, ... } ) =>  def_use_other  op;
                        def_use_other _ => ([],[]);
                    end;

                    fun clash (def_use)
                        =
                        {   (def_use i) ->   (di, ui);
                            (def_use j) ->   (dj, uj);
                            #
                            not (cos::colorsets_intersection_is_empty (di, uj)) or
                            not (cos::colorsets_intersection_is_empty (di, dj)) or
                            not (cos::colorsets_intersection_is_empty (ui, dj)); 
                        };

                    fun to_sl f i
                        =
                        {   (f i) ->   (d, u);
                            #
                            ( cos::make_colorset d,
                              cos::make_colorset u
                            );
                        };

                    fun def_use_int i
                        = 
                        {   (def_use_i i) ->   (d, u);
                            #
                            d     = cos::make_colorset d;
                            u     = cos::make_colorset u;

                            ( cos::drop_codetemp_from_colorset (always_zero_register, d),                       # No dependence on register 0!
                              cos::drop_codetemp_from_colorset (always_zero_register, u)
                            );
                        };

                    clash (def_use_int) or 
                    clash (to_sl def_use_f) or
                    clash (to_sl def_use_other);
                };

            fun delay_slot_candidate { jmp, delay_slot=>
                      (  mcf::BASE_OP (mcf::CALL _) | mcf::BASE_OP (mcf::BICC _) | mcf::BASE_OP (mcf::FBFCC _) 
                       | mcf::BASE_OP (mcf::TICC _) | mcf::BASE_OP (mcf::BR _) | mcf::BASE_OP (mcf::JMP _) | mcf::BASE_OP (mcf::JMPL _) 
                       | mcf::BASE_OP (mcf::RET _) | mcf::BASE_OP (mcf::BP _) | mcf::BASE_OP (mcf::FCMP _)) }
                   =>
                   FALSE;

                delay_slot_candidate { jmp=>mcf::NOTE { op, ... }, delay_slot }
                    => 
                    delay_slot_candidate { jmp=>op, delay_slot };

                delay_slot_candidate { jmp, delay_slot=>mcf::NOTE { op, ... } }
                    => 
                    delay_slot_candidate { jmp, delay_slot => op };

                delay_slot_candidate _ => TRUE;
            end; 

            fun set_target (mcf::BASE_OP (mcf::BICC  { b, a, nop, ... } ), lab) =>   mcf::bicc  { b, a, nop, label=>lab };
                set_target (mcf::BASE_OP (mcf::FBFCC { b, a, nop, ... } ), lab) =>   mcf::fbfcc { b, a, nop, label=>lab };

                set_target (mcf::BASE_OP (mcf::BR { rcond, p, r, a, nop, ... } ), lab)
                    => 
                    mcf::br { rcond, p, r, a, nop, label=>lab };

                set_target (mcf::BASE_OP (mcf::BP { b, p, cc, a, nop, ... } ), lab)
                    => 
                    mcf::bp { b, p, cc, a, nop, label=>lab };

                set_target (mcf::NOTE { op, note }, lab)
                    =>
                    mcf::NOTE { op => set_target (op, lab), note };

                set_target _ => error "set_target";
            end;
        end;
    };
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext