## delay-slots-sparc32-g.pkg
# Compiled by:
#
src/lib/compiler/back/low/sparc32/backend-sparc32.lib# We get invoked by:
#
#
src/lib/compiler/back/low/main/sparc32/backend-lowhalf-sparc32.pkgstipulate
package cos = registerkinds_junk::cos; # "cos" == "colorset".
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 delay_slots_sparc32_g (
# =====================
#
package mcf: Machcode_Sparc32; # Machcode_Sparc32 is from
src/lib/compiler/back/low/sparc32/code/machcode-sparc32.codemade.api package mu: Machcode_Universals # Machcode_Universals is from
src/lib/compiler/back/low/code/machcode-universals.api where
mcf == mcf; # "mcf" == "machcode_form" (abstract machine code).
# sharing/defn conflict: sharing p::i = i
)
: (weak) Delay_Slot_Properties # Delay_Slot_Properties is from
src/lib/compiler/back/low/jmp/delay-slot-props.api {
# Export to client packages:
#
package mcf = mcf; # "mcf" == "machcode_form" (abstract machine code).
stipulate
package rgk = mcf::rgk; # "rgk" == "registerkinds".
herein
fun error msg
=
lem::error("SparcDelaySlotProps", msg);
Delay_Slot = D_NONE
| D_ERROR | D_ALWAYS | D_TAKEN | D_FALLTHRU;
delay_slot_bytes = 4;
fun delay_slot { instruction, backward }
=
case instruction
#
mcf::BASE_OP (mcf::CALL { nop, ... } ) => { n=>FALSE, n_on=>D_ERROR, n_off=>D_ALWAYS, nop };
mcf::BASE_OP (mcf::JMP { nop, ... } ) => { n=>FALSE, n_on=>D_ERROR, n_off=>D_ALWAYS, nop };
mcf::BASE_OP (mcf::JMPL { nop, ... } ) => { n=>FALSE, n_on=>D_ERROR, n_off=>D_ALWAYS, nop };
mcf::BASE_OP (mcf::RET { nop, ... } ) => { n=>FALSE, n_on=>D_ERROR, n_off=>D_ALWAYS, nop };
mcf::BASE_OP (mcf::BICC { b=>mcf::BA, a, nop, ... } ) => { n=>FALSE, n_on=>D_NONE, n_off=>D_ALWAYS, nop };
mcf::BASE_OP (mcf::BICC { a, nop, ... } ) => { n=>a, n_on=>D_TAKEN, n_off=>D_ALWAYS, nop };
mcf::BASE_OP (mcf::FBFCC { a, nop, ... } ) => { n=>a, n_on=>D_TAKEN, n_off=>D_ALWAYS, nop };
mcf::BASE_OP (mcf::BR { a, nop, ... } ) => { n=>a, n_on=>D_TAKEN, n_off=>D_ALWAYS, nop };
mcf::BASE_OP (mcf::BP { a, nop, ... } ) => { n=>a, n_on=>D_TAKEN, n_off=>D_ALWAYS, nop };
mcf::BASE_OP (mcf::FCMP { nop, ... } ) => { n=>FALSE, n_on=>D_ERROR, n_off=>D_ALWAYS, nop };
mcf::NOTE { op, ... } => delay_slot { instruction => op, backward };
#
_ => { n=>FALSE, n_on=>D_ERROR, n_off=>D_NONE, nop=>FALSE };
esac;
fun enable_delay_slot { instruction, n, nop }
=
case (instruction, n)
#
(mcf::BASE_OP (mcf::JMP { r, i, labs, ... } ), FALSE) => mcf::jmp { r, i, labs, nop };
(mcf::BASE_OP (mcf::RET { leaf, ... } ), FALSE) => mcf::ret { leaf, nop };
(mcf::BASE_OP (mcf::BICC { b, a, label, ... } ), _) => mcf::bicc { b, a=>n, nop, label };
(mcf::BASE_OP (mcf::FBFCC { b, a, label, ... } ), _) => mcf::fbfcc { b, a=>n, nop, label };
(mcf::BASE_OP (mcf::BR { nop, label, p, r, rcond, ... } ), _) => mcf::br { rcond, r, a=>n, nop, label, p };
(mcf::BASE_OP (mcf::BP { nop, label, p, cc, b, ... } ), _) => mcf::bp { b, cc, a=>n, nop, label, p };
(mcf::BASE_OP (mcf::FCMP { cmp, r1, r2, ... } ), FALSE) => mcf::fcmp { cmp, r1, r2, nop };
(mcf::NOTE { op, note }, n) => mcf::NOTE { op => enable_delay_slot { instruction => op, n, nop }, note };
(mcf::BASE_OP (mcf::CALL { defs, uses, label, cuts_to, ramregion, ... } ), FALSE)
=>
mcf::call { defs, uses, label, cuts_to, nop, ramregion };
(mcf::BASE_OP (mcf::JMPL { r, i, d, defs, uses, ramregion, cuts_to, ... } ), FALSE)
=>
mcf::jmpl { r, i, d, defs, uses, cuts_to, nop, ramregion };
_ => error "enableDelaySlot";
esac;
def_use_i = mu::def_use rkj::INT_REGISTER;
def_use_f = mu::def_use rkj::FLOAT_REGISTER;
psr = [rgk::psr];
fsr = [rgk::fsr];
y = [rgk::y];
always_zero_register
=
null_or::the # We know it exists on sparc32.
(rgk::get_always_zero_register rkj::INT_REGISTER);
everything = [rgk::y, rgk::psr, rgk::fsr];
fun conflict { src=>i, dst=>j }
=
{ fun cc mcf::ANDCC => TRUE;
cc mcf::ANDNCC => TRUE;
cc mcf::ORCC => TRUE;
cc mcf::ORNCC => TRUE;
cc mcf::XORCC => TRUE;
cc mcf::XNORCC => TRUE;
cc mcf::ADDCC => TRUE;
cc mcf::TADDCC => TRUE;
cc mcf::TADDTVCC => TRUE;
cc mcf::SUBCC => TRUE;
cc mcf::TSUBCC => TRUE;
cc mcf::TSUBTVCC=> TRUE;
cc mcf::UMULCC => TRUE;
cc mcf::SMULCC => TRUE;
cc mcf::UDIVCC => TRUE;
cc mcf::SDIVCC => TRUE;
cc _ => FALSE;
end;
fun def_use_other (mcf::BASE_OP (mcf::BICC { b=>mcf::BA, ... } )) => ([],[]);
def_use_other (mcf::BASE_OP (mcf::BICC _)) => ([], psr);
def_use_other (mcf::BASE_OP (mcf::TICC _)) => ([], psr);
def_use_other (mcf::BASE_OP (mcf::WRY _)) => (y,[]);
def_use_other (mcf::BASE_OP (mcf::RDY _)) => ([], y);
def_use_other (mcf::BASE_OP (mcf::FCMP _)) => (fsr,[]);
def_use_other (mcf::BASE_OP (mcf::FBFCC _)) => ([], fsr);
def_use_other (mcf::BASE_OP (mcf::MOVICC _)) => ([], psr);
def_use_other (mcf::BASE_OP (mcf::MOVFCC _)) => ([], fsr);
def_use_other (mcf::BASE_OP (mcf::FMOVICC _)) => ([], psr);
def_use_other (mcf::BASE_OP (mcf::FMOVFCC _)) => ([], fsr);
def_use_other (mcf::BASE_OP (mcf::CALL _)) => (everything,[]);
def_use_other (mcf::BASE_OP (mcf::JMPL _)) => (everything,[]);
def_use_other (mcf::BASE_OP (mcf::ARITH { a, ... } )) => if (cc a) (psr,[]);
else ([],[]);
fi;
def_use_other (mcf::NOTE { op, ... } ) => def_use_other op;
def_use_other _ => ([],[]);
end;
fun clash (def_use)
=
{ (def_use i) -> (di, ui);
(def_use j) -> (dj, uj);
#
not (cos::colorsets_intersection_is_empty (di, uj)) or
not (cos::colorsets_intersection_is_empty (di, dj)) or
not (cos::colorsets_intersection_is_empty (ui, dj));
};
fun to_sl f i
=
{ (f i) -> (d, u);
#
( cos::make_colorset d,
cos::make_colorset u
);
};
fun def_use_int i
=
{ (def_use_i i) -> (d, u);
#
d = cos::make_colorset d;
u = cos::make_colorset u;
( cos::drop_codetemp_from_colorset (always_zero_register, d), # No dependence on register 0!
cos::drop_codetemp_from_colorset (always_zero_register, u)
);
};
clash (def_use_int) or
clash (to_sl def_use_f) or
clash (to_sl def_use_other);
};
fun delay_slot_candidate { jmp, delay_slot=>
( mcf::BASE_OP (mcf::CALL _)
| mcf::BASE_OP (mcf::BICC _) | mcf::BASE_OP (mcf::FBFCC _)
| mcf::BASE_OP (mcf::TICC _) | mcf::BASE_OP (mcf::BR _) | mcf::BASE_OP (mcf::JMP _) | mcf::BASE_OP (mcf::JMPL _)
| mcf::BASE_OP (mcf::RET _) | mcf::BASE_OP (mcf::BP _) | mcf::BASE_OP (mcf::FCMP _)) }
=>
FALSE;
delay_slot_candidate { jmp=>mcf::NOTE { op, ... }, delay_slot }
=>
delay_slot_candidate { jmp=>op, delay_slot };
delay_slot_candidate { jmp, delay_slot=>mcf::NOTE { op, ... } }
=>
delay_slot_candidate { jmp, delay_slot => op };
delay_slot_candidate _ => TRUE;
end;
fun set_target (mcf::BASE_OP (mcf::BICC { b, a, nop, ... } ), lab) => mcf::bicc { b, a, nop, label=>lab };
set_target (mcf::BASE_OP (mcf::FBFCC { b, a, nop, ... } ), lab) => mcf::fbfcc { b, a, nop, label=>lab };
set_target (mcf::BASE_OP (mcf::BR { rcond, p, r, a, nop, ... } ), lab)
=>
mcf::br { rcond, p, r, a, nop, label=>lab };
set_target (mcf::BASE_OP (mcf::BP { b, p, cc, a, nop, ... } ), lab)
=>
mcf::bp { b, p, cc, a, nop, label=>lab };
set_target (mcf::NOTE { op, note }, lab)
=>
mcf::NOTE { op => set_target (op, lab), note };
set_target _ => error "set_target";
end;
end;
};
end;