PreviousUpNext

15.4.381  src/lib/compiler/back/low/sparc32/jmp/jump-size-ranges-sparc32-g.pkg

## jump-size-ranges-sparc32-g.pkg --- information to resolve jumps. 
#
# See background comments in
#
#     src/lib/compiler/back/low/jmp/jump-size-ranges.api

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


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

stipulate
    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   jump_size_ranges_sparc32_g   (
        #             ==========================
        #
        package mcf: Machcode_Sparc32;                                          # Machcode_Sparc32                      is from   src/lib/compiler/back/low/sparc32/code/machcode-sparc32.codemade.api

        package crm: Compile_Register_Moves_Sparc32                             # Compile_Register_Moves_Sparc32        is from   src/lib/compiler/back/low/sparc32/code/compile-register-moves-sparc32.api
                     where
                         mcf == mcf;                                            # "mcf" == "machcode_form" (abstract machine code).

        package tce: Treecode_Eval                                              # Treecode_Eval                         is from   src/lib/compiler/back/low/treecode/treecode-eval.api
                     where
                         tcf == mcf::tcf;                                       # "tcf" == "treecode_form".
    )
    : (weak) Jump_Size_Ranges                                                   # Jump_Size_Ranges                      is from   src/lib/compiler/back/low/jmp/jump-size-ranges.api
    {
        # Export to client packages:
        #
        package mcf =  mcf;                                                     # "mcf" == "machcode_form" (abstract machine code).
        package rgk =  mcf::rgk;                                                # "rgk" == "registerkinds".


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

        branch_delayed_arch = TRUE;


        fun is_sdi (mcf::NOTE { op, ... } ) =>  is_sdi  op;
            is_sdi (mcf::LIVE _)                   => TRUE;
            is_sdi (mcf::DEAD _)                   => TRUE;
            is_sdi (mcf::COPY _)                   => TRUE;
            #
            is_sdi (mcf::BASE_OP instruction)
                =>
                {
                    fun op (mcf::IMMED n) => FALSE;
                           op (mcf::REG _) => FALSE;
                           op (mcf::HI _) => FALSE;
                           op (mcf::LO _) => FALSE;
                           op (mcf::LAB _) => TRUE;
                    end;
                    case instruction

                       mcf::ARITH { i, ... } => op i;
                       mcf::SHIFT { i, ... } => op i;
                       mcf::LOAD { i, ... } => op i;
                       mcf::STORE { i, ... } => op i;
                       mcf::FLOAD { i, ... } => op i;
                       mcf::FSTORE { i, ... } => op i;
                       mcf::JMPL { i, ... } => op i;
                       mcf::JMP { i, ... } => op i;
                       mcf::MOVICC { i, ... } => op i;
                       mcf::MOVFCC { i, ... } => op i;
                       mcf::MOVR { i, ... } => op i;
                       mcf::CALL _ => TRUE;
                       mcf::BICC _ => TRUE;
                       mcf::FBFCC _ => TRUE;
                       mcf::BR _ => TRUE;
                       mcf::BP _ => TRUE;
                       mcf::TICC { i, ... } => op i;
                       mcf::WRY { i, ... } => op i;
                       mcf::SAVE { i, ... } => op i;
                       mcf::RESTORE { i, ... } => op i;
                       #  The following is only TRUE of Version 8 
                       mcf::FPOP1 { a=>(mcf::FMOVD | mcf::FNEGD | mcf::FABSD), ... } => TRUE;
                       _ => FALSE;
                    esac;
                };
        end;

        fun min_size_of (mcf::NOTE { op, ... } ) =>  min_size_of  op;
            #
            min_size_of (mcf::LIVE _) =>  0;
            min_size_of (mcf::DEAD _) =>  0;
            min_size_of (mcf::COPY _) =>  0;            #  ? 
            #
            min_size_of (mcf::BASE_OP instruction)
                => 
                case instruction
                    #
                    (mcf::BICC  { nop=>TRUE, ... } ) => 8;
                    (mcf::FBFCC { nop=>TRUE, ... } ) => 8;
                    (mcf::JMP   { nop=>TRUE, ... } ) => 8;
                    (mcf::JMPL  { nop=>TRUE, ... } ) => 8;
                    (mcf::CALL  { nop=>TRUE, ... } ) => 8;
                    (mcf::BR    { nop=>TRUE, ... } ) => 8;
                    (mcf::BP    { nop=>TRUE, ... } ) => 8;
                    (mcf::RET   { nop=>TRUE, ... } ) => 8;
                    (mcf::FCMP  { nop=>TRUE, ... } ) => 8;
                    (mcf::FPOP1 { a=>(mcf::FMOVD | mcf::FNEGD | mcf::FABSD), ... } ) => 8;
                     _          => 4;
                esac;
        end;

        fun max_size_of (mcf::BASE_OP (mcf::FPOP1 { a=>(mcf::FMOVD | mcf::FNEGD | mcf::FABSD), ... } )) => 8;
            max_size_of (mcf::NOTE { op, ... } ) =>  max_size_of  op;
            max_size_of _                  => 4;
        end;

        fun immed13 n =      -4096 <= n  and  n < 4096;
        fun immed22 n =  -0x200000 <= n  and  n < 0x1fffff;
        fun immed16 n =    -0x8000 <= n  and  n < 0x8000;
        fun immed19 n =   -0x40000 <= n  and  n < 0x40000;
        fun immed30 n = -0x4000000 <= n  and  n < 0x3ffffff;

        fun instr_length ([], n)
                =>
                n;

            instr_length (mcf::BASE_OP (mcf::FPOP1 { a=>(mcf::FMOVD | mcf::FNEGD | mcf::FABSD), ... } ) ! is, n)
                =>
                instr_length (is, n+8);

            instr_length(_ ! is, n)
                =>
                instr_length (is, n+4);
        end;

        fun sdi_size (mcf::LIVE _, _, _) =>   0;
            sdi_size (mcf::DEAD _, _, _) =>   0;

            sdi_size (mcf::NOTE { op, ... }, labmap, loc)
                =>
                sdi_size (op, labmap, loc);

            sdi_size (mcf::COPY { kind => rkj::INT_REGISTER, src, dst, tmp, ... }, _, _)
                =>
                4 * length (crm::compile_int_register_moves { tmp, dst, src } );

            sdi_size (mcf::COPY { kind => rkj::FLOAT_REGISTER, src, dst, tmp, ... }, _, _)
                =>
                {   instrs = crm::compile_float_register_moves { src, dst, tmp };
                    instr_length (instrs, 0);
                };

            sdi_size (instruction as mcf::BASE_OP i, lab_map, loc)
                =>
                {   fun op (mcf::IMMED n, _) => 4;
                        op (mcf::REG _, _  ) => 4;
                        op (mcf::HI _, _   ) => 4;
                        op (mcf::LO _, _   ) => 4;
                        op (mcf::LAB lambda_expression, hi) => if (immed13 (tce::value_of lambda_expression) ) 4; else hi;fi;
                    end;

                    fun displacement lab
                        =
                        ((lab_map lab) - loc) / 4;

                    fun branch22 lab =   immed22 (displacement lab)   ??  4  :: 16;
                    fun branch19 lab =   immed19 (displacement lab)   ??  4  :: 16;
                    fun branch16 lab =   immed16 (displacement lab)   ??  4  :: 16;
                    fun call     lab =   immed30 (displacement lab)   ??  4  :: 20;

                    fun delay_slot FALSE => 0;
                        delay_slot TRUE  => 4;
                    end;

                    case i 

                        mcf::ARITH { a=>mcf::OR, r, i, ... }
                            => 
                            if (rkj::universal_register_id_of r == 0)   op (i,  8);
                            else                               op (i, 12);
                            fi;

                        mcf::ARITH { i, ... } => op (i, 12);
                        mcf::SHIFT { i, ... } => op (i, 12);
                        mcf::LOAD { i, ... } => op (i, 12);
                        mcf::STORE { i, ... } => op (i, 12);
                        mcf::FLOAD { i, ... } => op (i, 12);
                        mcf::FSTORE { i, ... } => op (i, 12);
                        mcf::TICC { i, ... } => op (i, 12);
                        mcf::SAVE { i, ... } => op (i, 12);
                        mcf::RESTORE { i, ... } => op (i, 12);
                        mcf::MOVICC { i, ... } => op (i, 12);
                        mcf::MOVFCC { i, ... } => op (i, 12);
                        mcf::MOVR { i, ... } => op (i, 12);
                        mcf::JMPL { i, nop, ... } => op (i, 12) + delay_slot nop;
                        mcf::JMP { i, nop, ... } => op (i, 12) + delay_slot nop;
                        mcf::BICC { label, nop, ... } => branch22 label + delay_slot nop;
                        mcf::FBFCC { label, nop, ... } => branch22 label + delay_slot nop;
                        mcf::BR { label, nop, ... } => branch16 label + delay_slot nop;
                        mcf::BP { label, nop, ... } => branch19 label + delay_slot nop;
                        mcf::CALL { label, ... } => call label;
                        mcf::WRY { i, ... } => op (i, 12);
                        mcf::FPOP1 { a=>(mcf::FMOVD | mcf::FNEGD | mcf::FABSD), ... } => 8;         
                        _ => error "sdiSize";
                    esac;
                };

            sdi_size _
                =>
                error "sdiSize";
        end;

        fun split22_10 n
            =
            {   w = one_word_unt::from_int n;

                { hi => one_word_unt::to_int (one_word_unt::(>>) (w, 0u10)),
                  lo => one_word_unt::to_int (one_word_unt::bitwise_and (w, 0ux3ff))
                };
            };

        fun split (mcf::LAB lambda_expression) => split22_10 (tce::value_of lambda_expression);
            split _ => error "split";
        end;


        # Expand an immediate constant
        # into two instructions:
        #
        fun expand_imm (immed, instruction)
            = 
            {   my { lo, hi } = split immed;

                [  mcf::sethi { i=>hi, d=>rgk::asm_tmp_r },
                   mcf::arith { a=>mcf::OR, r=>rgk::asm_tmp_r, i=>mcf::IMMED lo, d=>rgk::asm_tmp_r },
                   mcf::BASE_OP instruction
                ];
            };


        # Instantiate a span dependent instruction
        # as given size at given location:
        #
        fun instantiate_span_dependent_op  {  sdi => mcf::NOTE { op, ... },  size_in_bytes,  at  }
                =>
                instantiate_span_dependent_op {  sdi => op,  size_in_bytes,  at  };

            instantiate_span_dependent_op { sdi => mcf::LIVE _, ... } => [];
            instantiate_span_dependent_op { sdi => mcf::DEAD _, ... } => [];

            instantiate_span_dependent_op { sdi => mcf::COPY { kind => rkj::INT_REGISTER, src, tmp, dst, ... }, ... }
                => 
                crm::compile_int_register_moves { src, dst, tmp };

            instantiate_span_dependent_op { sdi => mcf::COPY { kind => rkj::FLOAT_REGISTER, src, tmp, dst, ... }, ... }
                => 
                crm::compile_float_register_moves { src, dst, tmp };

            instantiate_span_dependent_op { sdi => instruction as (mcf::BASE_OP i), size_in_bytes, at }
                => 
                case (i, size_in_bytes) 
                    #
                    (_, 4) => [instruction];

                    (mcf::ARITH { a=>mcf::OR, r, i, d }, 8)
                        =>
                        if (rkj::universal_register_id_of r == 0 )
                            #
                            (split i) ->   { lo, hi };

                            [ mcf::sethi { i=>hi, d=>rgk::asm_tmp_r },
                              mcf::arith { a=>mcf::OR, r=>rgk::asm_tmp_r, i=>mcf::IMMED lo, d }
                            ];
                        else
                             error "MATH";
                        fi;

                    (mcf::ARITH { a, r, i, d }, 12) 
                       =>
                       expand_imm (i, mcf::ARITH { a, r, i=>mcf::REG rgk::asm_tmp_r, d } );

                    (mcf::SHIFT { s, r, i, d }, 12) 
                       =>
                       expand_imm (i, mcf::SHIFT { s, r, i=>mcf::REG rgk::asm_tmp_r, d } );

                    (mcf::SAVE { r, i, d }, 12) 
                       =>
                       expand_imm (i, mcf::SAVE { r, i=>mcf::REG rgk::asm_tmp_r, d } );

                    (mcf::RESTORE { r, i, d }, 12) 
                       =>
                       expand_imm (i, mcf::RESTORE { r, i=>mcf::REG rgk::asm_tmp_r, d } );

                    (mcf::LOAD { l, r, i, d, ramregion }, 12)
                       =>  
                       expand_imm (i, mcf::LOAD { l, r, i=>mcf::REG rgk::asm_tmp_r, d, ramregion } );

                    (mcf::STORE { s, r, i, d, ramregion }, 12) 
                       =>
                       expand_imm (i, mcf::STORE { s, r, i=>mcf::REG rgk::asm_tmp_r, d, ramregion } );

                    (mcf::FLOAD { l, r, i, d, ramregion }, 12) 
                       =>
                       expand_imm (i, mcf::FLOAD { l, r, i=>mcf::REG rgk::asm_tmp_r, d, ramregion } );

                    (mcf::FSTORE { s, r, i, d, ramregion }, 12) 
                       =>
                       expand_imm (i, mcf::FSTORE { s, r, i=>mcf::REG rgk::asm_tmp_r, d, ramregion } );

                    (mcf::MOVICC { b, i, d }, 12) 
                       =>
                       expand_imm (i, mcf::MOVICC { b, i=>mcf::REG rgk::asm_tmp_r, d } );

                    (mcf::MOVFCC { b, i, d }, 12) 
                       =>
                       expand_imm (i, mcf::MOVFCC { b, i=>mcf::REG rgk::asm_tmp_r, d } );

                    (mcf::MOVR { rcond, r, i, d }, 12) 
                       =>
                       expand_imm (i, mcf::MOVR { rcond, r, i=>mcf::REG rgk::asm_tmp_r, d } );

                    (mcf::JMPL _, 8) => [instruction];
                    (mcf::JMP _, 8) => [instruction];
                    (mcf::BICC _, 8) => [instruction];
                    (mcf::FBFCC _, 8) => [instruction];
                    (mcf::BR _, 8) => [instruction];
                    (mcf::BP _, 8) => [instruction];

                    (mcf::JMPL { r, i, d, defs, uses, cuts_to, nop, ramregion }, (12 | 16))
                       => 
                       expand_imm (i, mcf::JMPL { r, i=>mcf::REG rgk::asm_tmp_r, d, defs, uses, cuts_to, nop, ramregion } );

                    (mcf::JMP { r, i, labs, nop }, (12 | 16))
                       => 
                       expand_imm (i, mcf::JMP { r, i=>mcf::REG rgk::asm_tmp_r, labs, nop } );

                    (mcf::TICC { t, cc, r, i }, 12)
                       =>
                       expand_imm (i, mcf::TICC { t, cc, r, i=>mcf::REG rgk::asm_tmp_r } );

                        # The sparc uses 22bits signed extended displacement offsets
                        # Let's hope it's enough                                                        XXX BUGGO FIXME

                    (mcf::BICC  { b, a, label, nop }, _) => error "BICC";  
                    (mcf::FBFCC { b, a, label, nop }, _) => error "FBFCC"; 
                    (mcf::FPOP1 { a, r, d }, _)
                        =>
                        {   fun next_reg_num  c
                                =
                                rgk::get_ith_float_hardware_register (rkj::intrakind_register_id_of  c  + 1);

                            # Note: if r==d then the move is not required.
                            # This needs to be factored into the size before it
                            # can be done here.

                            fun do_double (op)
                                = 
                                [   mcf::fpop1 { a=>op, r, d },
                                    mcf::fpop1 { a=>mcf::FMOVS, r=>next_reg_num r, d=>next_reg_num d }
                                ];

                            case  a 
                                #
                                mcf::FMOVD =>   do_double (mcf::FMOVS);
                                mcf::FNEGD =>   do_double (mcf::FNEGS);
                                mcf::FABSD =>   do_double (mcf::FABSS);
                                #
                                _        =>   error "instantiate_span_dependent_op: FPop1";
                            esac;
                       };

                    (mcf::WRY { r, i }, 12)
                        =>
                        expand_imm (i, mcf::WRY { r, i => mcf::REG  rgk::asm_tmp_r } );

                     _ => error "instantiate_span_dependent_op";
                esac;

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


## COPYRIGHT (c) 1996 Bell Laboratories.
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext