## 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.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_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;