PreviousUpNext

15.4.259  src/lib/compiler/back/low/intel32/jmp/jump-size-ranges-intel32-g.pkg

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

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

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

stipulate
    package lem =  lowhalf_error_message;                       # lowhalf_error_message                 is from   src/lib/compiler/back/low/control/lowhalf-error-message.pkg
herein

    generic package  jump_size_ranges_intel32_g   (
        #            ==========================
        #
        package mcf: Machcode_Intel32;                          # Machcode_Intel32                      is from   src/lib/compiler/back/low/intel32/code/machcode-intel32.codemade.api

        package tce: Treecode_Eval                              # Treecode_Eval                         is from   src/lib/compiler/back/low/treecode/treecode-eval.api
                     where
                         tcf == mcf::tcf;                       # "tcf" == "treecode_form".

        package xe: Execode_Emitter                             # Execode_Emitter                       is from   src/lib/compiler/back/low/emit/execode-emitter.api
                    where
                        mcf == mcf;                             # "mcf" == "machcode_form" (abstract machine code).
    )
    : (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".

        stipulate
            package lac =  mcf::lac;                            # "lac" == "late_constant".
        herein

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

            esp = 4;                                            # XXX SUCKO FIXME We shouldn't need this here -- we already define this three(!) times in src/lib/compiler/back/low/intel32/intel32.architecture-description
            ebp = 5;                                            # "                                                                                                                                                        "

            branch_delayed_arch = FALSE;


            fun imm8 i
                =
                -128 <= i   and   i < 128;


            fun is_sdi (mcf::NOTE { op, ... } ) =>  is_sdi  op;

                is_sdi (mcf::LIVE _)             => TRUE;
                is_sdi (mcf::DEAD _)             => TRUE;
                is_sdi (mcf::COPY _)             => FALSE;

                is_sdi (mcf::BASE_OP base_op)
                    =>
                    case base_op
                        #
                        mcf::JMP (operand,      _   ) => do_operand operand;
                        mcf::JCC { operand,     ... } => do_operand operand;
                        #
                        mcf::BINARY { src, dst, ... } => do_operand src or do_operand dst;
                        mcf::MOVE   { src, dst, ... } => do_operand src or do_operand dst;
                        mcf::LEA { address,     ... } => do_operand address;
                        #
                        ( mcf::CMPL arg | mcf::CMPW arg | mcf::CMPB arg 
                         | mcf::TESTL arg | mcf::TESTW arg | mcf::TESTB arg) => cmptest arg;
                        #
                        mcf::MULTDIV { src,     ... } =>  do_operand src;
                        mcf::MUL3    { src1,    ... } =>  do_operand src1;
                        #
                        mcf::UNARY   { operand, ... } =>  do_operand operand;
                        mcf::SET     { operand, ... } =>  do_operand operand;
                        #
                        mcf::CMOV   { src, dst, ... } =>  do_operand src; 
                        #
                        mcf::PUSHL  operand =>  do_operand  operand;
                        mcf::PUSHW  operand =>  do_operand  operand;
                        mcf::PUSHB  operand =>  do_operand  operand;
                        mcf::POP    operand =>  do_operand  operand;
                        mcf::FSTPT  operand =>  do_operand  operand;
                        mcf::FSTPL  operand =>  do_operand  operand;
                        mcf::FSTPS  operand =>  do_operand  operand;
                        mcf::FSTL   operand =>  do_operand  operand;
                        mcf::FSTS   operand =>  do_operand  operand;
                        mcf::FLDT   operand =>  do_operand  operand;
                        mcf::FLDL   operand =>  do_operand  operand;
                        mcf::FLDS   operand =>  do_operand  operand;
                        mcf::FILD   operand =>  do_operand  operand;
                        mcf::FILDL  operand =>  do_operand  operand;
                        mcf::FILDLL operand =>  do_operand  operand;
                        #
                        mcf::FBINARY { src, dst, ... } => do_operand src or do_operand dst;
                        mcf::FIBINARY { src, ... } => do_operand src; 
                        _ => FALSE;
                    esac
                    where       
                        fun do_operand (mcf::IMMED_LABEL _) => TRUE;
                            do_operand (mcf::LABEL_EA _) => TRUE;
                            do_operand (mcf::DISPLACE { disp, ... } ) => do_operand disp;
                            do_operand (mcf::INDEXED { disp, ... } ) => do_operand disp;
                            do_operand _ => FALSE;
                        end;

                        fun cmptest { lsrc, rsrc }
                            =
                            do_operand lsrc or do_operand rsrc;
                    end;
            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::BASE_OP i)
                    => 
                    case i 
                        mcf::JMP _ => 2;
                        mcf::JCC _ => 2;
                        mcf::LEA _ => 2;
                         _ => 1;
                    esac;

                min_size_of _ =>   error "min_size_of";
            end;


            fun max_size_of _ = 12;

            # Value of span-dependent operand 
            #
            fun do_operand (mcf::IMMED_LABEL label_expression) => tce::value_of  label_expression;
                do_operand (mcf::LABEL_EA    label_expression) => tce::value_of  label_expression;
                #
                do_operand _ => error "do_operand";
            end;

            encode =  xe::op_to_bytevector;

            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::BASE_OP instruction, labmap, loc)
                    =>
                    {
                        fun branch (operand, short, long)
                            =
                            {   offset = do_operand operand - loc;

                                if (imm8 (offset - 2))   short;
                                else                     long;
                                fi;
                            };

                        case instruction
                            mcf::JMP (operand, _) => branch (operand, 2, 5);
                            mcf::JCC { operand, ... } => branch (operand, 2, 6);
                            _ => vector_of_one_byte_unts::length (encode (mcf::BASE_OP instruction));
                        esac;
                     };                         # fun sdi_size

                sdi_size _ => error "sdi_size";
            end;

            # Instantiate given instruction to 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::BASE_OP base_op, size_in_bytes, at }
                    => 
                    case base_op
                        #
                        mcf::JMP (operand, labs)
                            =>
                            [mcf::jmp (mcf::RELATIVE (do_operand operand - at), labs)];

                        mcf::JCC { cond, operand }
                            => 
                            [mcf::jcc { cond, operand=>mcf::RELATIVE (do_operand operand - at) } ];

                        operand =>   [mcf::BASE_OP operand];
                    esac;

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


## COPYRIGHT (c) 1997 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