PreviousUpNext

15.4.344  src/lib/compiler/back/low/pwrpc32/jmp/jump-size-ranges-pwrpc32-g.pkg

## jump-size-ranges-pwrpc32-g.pkg
#
# See background comments in
#
#     src/lib/compiler/back/low/jmp/jump-size-ranges.api

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

#                      "I much prefer the sharpest criticism
#                       of a single intelligent man to the
#                       thoughtless approval of the masses."
#
#                                         --Johann Kepler 

# We are invoked from:
#
#     src/lib/compiler/back/low/main/pwrpc32/backend-lowhalf-pwrpc32.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_pwrpc32_g   (
        #             ==========================
        #
        package mcf: Machcode_Pwrpc32;                                                  # Machcode_Pwrpc32                      is from   src/lib/compiler/back/low/pwrpc32/code/machcode-pwrpc32.codemade.api

        package crm: Compile_Register_Moves_Pwrpc32                                     # Compile_Register_Moves_Pwrpc32        is from   src/lib/compiler/back/low/pwrpc32/code/compile-register-moves-pwrpc32.api
                     where                                                              # "crm" == "ompile_register_moves".
                         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_pwrpc32_g", msg);

        warn_long_branch
            =
            lowhalf_control::make_bool ("pwrpc32-warn-long-branch",
                                  "whether to warn about long form of branch");

        branch_delayed_arch = FALSE;

        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 operand (mcf::LABEL_OP _) => TRUE;
                        operand _               => FALSE;
                    end;

                    case instruction
                        mcf::LL { d, ... } => operand d;
                        mcf::LF { d, ... } => operand d;
                        mcf::ST { d, ... } => operand d;
                        mcf::STF { d, ... } => operand d;
                        mcf::ARITHI { im, ... } => operand im;
                        mcf::ROTATEI { sh, ... } => operand sh;
                        mcf::COMPARE { rb, ... } => operand rb;
                        mcf::TW { si, ... } => operand si;
                        mcf::TD { si, ... } => operand si;
                        mcf::BC { address, ... } => operand address;
                        _ => FALSE;
                    esac;
                };
        end;


        # max Size is not used by the
        # PWRPC32 span dependency analysis:
        #
        fun max_size_of _
            =
            error "max_size";

        fun min_size_of (mcf::LIVE _)        =>  0;
            min_size_of (mcf::DEAD _)        =>  0;
            min_size_of (mcf::COPY _)        =>  0;
            #
            min_size_of (mcf::NOTE { op, ... } ) =>  min_size_of  op;
            #
            min_size_of _ => 4;
        end;

        fun sdi_size (mcf::NOTE { op, ... }, labmap, loc)
                =>
                sdi_size (op, labmap, loc);
            #   
            sdi_size (mcf::LIVE _, _, _) => 0;
            sdi_size (mcf::DEAD _, _, _) => 0;

            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, ... }, _, _)
                => 
                4 * length (crm::compile_float_register_moves { src, dst, tmp } );

            sdi_size (mcf::BASE_OP instruction, labmap, loc)
                =>
                {
                    fun signed16 n = -32768 <= n and n < 32768;
                    fun signed12 n = -2048 <= n and n < 2048;
                    fun signed14 n = -8192 <= n and n < 8192;
                    fun unsigned16 n = 0 <= n and n < 65536;
                    fun unsigned5 n = 0 <=n and n < 32;

                    fun operand (mcf::LABEL_OP le, in_range, lo, hi)
                            => 
                            in_range (tce::value_of le)
                              ??  lo
                              ::  hi;

                        operand _
                            =>
                            error "sdiSize: operand";
                    end;

                    case instruction

                        mcf::LL { ld=>(mcf::LBZ | mcf::LHZ | mcf::LHA | mcf::LWZ), d, ... }
                            => 
                            operand (d, signed16, 4, 8);

                        mcf::LL { d, ... } => operand (d, signed12, 4, 8);
                        mcf::LF { ld=>(mcf::LFS | mcf::LFD), d, ... } => operand (d, signed16, 4, 8);
                        mcf::LF { d, ... } => operand (d, signed12, 4, 8);
                        mcf::ST { st=>(mcf::STB | mcf::STH | mcf::STW), d, ... } => operand (d, signed16, 4, 8);
                        mcf::ST { d, ... } => operand (d, signed12, 4, 8);
                        mcf::STF { st=>(mcf::STFS | mcf::STFD), d, ... } => operand (d, signed16, 4, 8);
                        mcf::STF { d, ... } => operand (d, signed12, 4, 8);

                        mcf::ARITHI { oper, im, ... }
                            => 
                            case oper

                                mcf::ADDI
                                    =>
                                    operand (im, signed16, 4, 8);

                               (mcf::ADDIS | mcf::SUBFIC | mcf::MULLI)
                                    =>
                                    operand (im, signed16, 4, 12);

                               (mcf::ANDI_RC | mcf::ANDIS_RC | mcf::ORI | mcf::ORIS | mcf::XORI | mcf::XORIS)
                                   => 
                                   operand (im, unsigned16, 4, 12);

                               (mcf::SRAWI | mcf::SRADI)
                                   =>
                                   operand (im, unsigned5, 4, 12);
                            esac;

                        mcf::ROTATEI { sh, ... }
                            =>
                            error "sdiSize: ROTATE";

                        mcf::COMPARE { cmp, rb, ... }
                            => 
                            case cmp
                                mcf::CMP => operand (rb,   signed16, 4, 12);
                               mcf::CMPL => operand (rb, unsigned16, 4, 12);
                            esac;

                        mcf::BC { address=>mcf::LABEL_OP label_expression, ... }
                            => 
                            signed14((tce::value_of label_expression - loc) / 4)
                              ??  4
                              ::  8;

                        _   =>
                            error "sdiSize";
                    esac;
                };

            sdi_size _
                =>
                error "sdi_size";
        end;

        fun value_of (mcf::LABEL_OP  label_expression)
                =>
                tce::value_of  label_expression;

            value_of _
                =>
                error "value_of";
        end;

        fun split operand
            =
            {   i = value_of operand;
                w = unt::from_int i;
                hi = unt::(>>>) (w, 0u16);
                lo = unt::bitwise_and (w, 0u65535);

                my (high, low)
                    = 
                    if (lo <  0u32768)  (hi, lo);
                    else                (hi+0u1, lo - 0u65536);
                    fi;

               ( unt::to_int_x high,
                 unt::to_int_x low
               );
            };

        fun cnv mcf::ADDI    => mcf::ADD;
            cnv mcf::SUBFIC  => mcf::SUBF; 
            cnv mcf::MULLI   => mcf::MULLW; 
            cnv mcf::ANDI_RC => mcf::AND; 
            cnv mcf::ORI     => mcf::OR; 
            cnv mcf::XORI    => mcf::XOR; 
            cnv mcf::SRAWI   => mcf::SRAW; 
            cnv mcf::SRADI   => mcf::SRAD; 
            cnv _         => error "cnv";
        end;

        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
                    #
                    mcf::LL { ld, rt, ra, d, ramregion }
                        =>
                        case size_in_bytes
                            #
                            4 => [mcf::ll { ld, rt, ra, d=>mcf::IMMED_OP (value_of d), ramregion } ];

                            8 => {   (split d) ->   (hi, lo);

                                     [ mcf::arithi { oper=>mcf::ADDIS, rt=>rgk::asm_tmp_r, ra, im=>mcf::IMMED_OP hi },
                                       mcf::ll { ld, rt, ra=>rgk::asm_tmp_r, d=>mcf::IMMED_OP lo, ramregion }
                                     ];
                                 };

                            _ => error "instantiate_span_dependent_op: L";
                        esac;

                    mcf::LF { ld, ft, ra, d, ramregion }
                        =>
                        case size_in_bytes
                            #
                            4 => [mcf::lf { ld, ft, ra, d=>mcf::IMMED_OP (value_of d), ramregion } ];

                            8 => {   (split d) ->   (hi, lo);

                                     [ mcf::arithi { oper=>mcf::ADDIS, rt=>rgk::asm_tmp_r, ra, im=>mcf::IMMED_OP hi },
                                       mcf::lf { ld, ft, ra=>rgk::asm_tmp_r, d=>mcf::IMMED_OP lo, ramregion }
                                     ];
                                 };

                            _ => error "instantiate_span_dependent_op: LF";
                        esac;

                    mcf::ST { st, rs, ra, d, ramregion }
                        =>
                        case size_in_bytes 
                            #
                            4 => [mcf::st { st, rs, ra, d=>mcf::IMMED_OP (value_of d), ramregion } ];

                            8 => {   (split d) ->   (hi, lo);

                                     [ mcf::arithi { oper=>mcf::ADDIS, rt=>rgk::asm_tmp_r, ra, im=>mcf::IMMED_OP hi },
                                       mcf::st { st, rs, ra=>rgk::asm_tmp_r, d=>mcf::IMMED_OP lo, ramregion }
                                     ];
                                 };

                            _ => error "instantiate_span_dependent_op: ST";
                        esac;

                    mcf::STF { st, fs, ra, d, ramregion }
                        =>
                        case size_in_bytes 
                            #
                            4 => [mcf::stf { st, fs, ra, d=>mcf::IMMED_OP (value_of d), ramregion } ];

                            8 => {   (split d) ->   (hi, lo);

                                     [ mcf::arithi { oper=>mcf::ADDIS, rt=>rgk::asm_tmp_r, ra, im=>mcf::IMMED_OP hi },
                                       mcf::stf { st, fs, ra=>rgk::asm_tmp_r, d=>mcf::IMMED_OP lo, ramregion }
                                     ];
                             };

                          _ => error "instantiate_span_dependent_op: STF";
                        esac;

                    mcf::ARITHI { oper, rt, ra, im }
                        => 
                        case size_in_bytes
                            #
                            4 => [mcf::arithi { oper, rt, ra, im=>mcf::IMMED_OP (value_of im) } ];

                            8 => {   (split im) ->   (hi, lo);           # Must be ADDI.

                                     [ mcf::arithi { oper=>mcf::ADDIS, rt, ra, im=>mcf::IMMED_OP hi },
                                       mcf::arithi { oper=>mcf::ADDI, rt, ra=>rt, im=>mcf::IMMED_OP lo }
                                     ];
                                 };

                           12 => {   (split im) ->   (hi, lo);

                                     [ mcf::arithi { oper=>mcf::ADDIS, rt=>rgk::asm_tmp_r, ra=>rgk::get_ith_hardware_register_of_kind rkj::INT_REGISTER 0, im=>mcf::IMMED_OP hi },
                                       mcf::arithi { oper=>mcf::ADDI, rt=>rgk::asm_tmp_r, ra=>rgk::asm_tmp_r, im=>mcf::IMMED_OP lo },
                                       mcf::arith  { oper=>cnv oper, rt, ra, rb=>rgk::asm_tmp_r, oe=>FALSE, rc=>(oper == mcf::ANDI_RC) }
                                     ];
                                 };
                            _ => error "ARITHI";
                        esac;

                    mcf::BC { bo, bf, bit, fall, address, lk }
                        => 
                        case size_in_bytes
                            #
                            4 => [instruction];

                            8 => {   new_bo =   case bo
                                                    # 
                                                    mcf::TRUE => mcf::FALSE;
                                                    mcf::FALSE => mcf::TRUE;
                                                    mcf::ALWAYS => error "instantiate_span_dependent_op: newBO: BC";
                                                    mcf::COUNTER { eq_zero, cond } => error "instantiate_span_dependent_op: newBO: COUNTER";
                                                esac;

                                     if *warn_long_branch 
                                         print("emiting long form of branch"  + "\n");
                                     fi;

                                     [ mcf::bc { bo=>new_bo, bf, bit, address=>fall, fall, lk=>FALSE },
                                       mcf::bb { address, lk }
                                     ];
                                 };

                            _ => error "instantiate_span_dependent_op: BC";
                        esac;

                    # The other span dependent instructions are not generated 
                    #
                    mcf::COMPARE _ =>   error "instantiate_span_dependent_op: COMPARE";
                     _            =>   error "instantiate_span_dependent_op";
                 esac;

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


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext