## 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.pkgstipulate
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.pkgherein
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.