Bug 594296 - Fix the implementation of Assembler::asm_cmov() in the SH4 backend (r=nnethercote r=rreitmai sr=edwsmith)

--HG--
extra : convert_revision : 616a6130e06155aead8751eba04981e3760999c8
This commit is contained in:
Cédric VINCENT 2010-09-08 01:50:00 -07:00
parent d2c59c063a
commit 7eb372bec3

View File

@ -2141,27 +2141,63 @@ namespace nanojit
RegisterMask allow = inst->isD() ? FpRegs : GpRegs; RegisterMask allow = inst->isD() ? FpRegs : GpRegs;
Register dest_reg = prepareResultReg(inst, allow); Register dest_reg = prepareResultReg(inst, allow);
Register src_reg = findRegFor(if_false, allow & ~rmask(dest_reg));
// 3. If the test is "true", we branched over the copy. // Try to re-use the result register for one of the arguments.
underrunProtect(2 * sizeof(NIns)); Register src_true_reg = if_true->isInReg() ? if_true->getReg() : dest_reg;
NIns *after_mov = _nIns; Register src_false_reg = if_false->isInReg() ? if_false->getReg() : dest_reg;
// 2. If the test is "false", copy the register. // Note that iftrue and iffalse may actually be the same, though
// it shouldn't happen with the LIR optimizers turned on.
if (src_true_reg == src_false_reg && if_true != if_false) {
// We can't re-use the result register for both arguments,
// so force one into its own register.
src_false_reg = findRegFor(if_false, allow & ~rmask(dest_reg));
NanoAssert(if_false->isInReg());
}
underrunProtect(6 * sizeof(NIns));
// 3. If the test is "true", copy the "true" source register.
NIns *after_mov_true = _nIns;
if (inst->isop(LIR_cmovd)) { if (inst->isop(LIR_cmovd)) {
SH4_fmov(src_reg, dest_reg); SH4_fmov(src_true_reg, dest_reg);
SH4_fmov(Register(src_reg + 1), Register(dest_reg + 1)); SH4_fmov(Register(src_true_reg + 1), Register(dest_reg + 1));
} }
else { else {
SH4_mov(src_reg, dest_reg); SH4_mov(src_true_reg, dest_reg);
} }
findSpecificRegFor(if_true, dest_reg); // 2. If the test is "false", copy the "false" source register
// then jump over the "mov if true".
NIns *after_mov_false = _nIns;
// 1. Branch [or not] according to the condition. SH4_nop();
asm_branch(false, condition, after_mov); SH4_bra(SH4_LABEL(after_mov_true));
if (inst->isop(LIR_cmovd)) {
SH4_fmov(src_false_reg, dest_reg);
SH4_fmov(Register(src_false_reg + 1), Register(dest_reg + 1));
}
else {
SH4_mov(src_false_reg, dest_reg);
}
freeResourcesOf(inst); freeResourcesOf(inst);
// If we re-used the result register, mark it as active for either if_true
// or if_false (or both in the corner-case where they're the same).
if (src_true_reg == dest_reg) {
NanoAssert(!if_true->isInReg());
findSpecificRegForUnallocated(if_true, dest_reg);
} else if (src_false_reg == dest_reg) {
NanoAssert(!if_false->isInReg());
findSpecificRegForUnallocated(if_false, dest_reg);
} else {
NanoAssert(if_false->isInReg());
NanoAssert(if_true->isInReg());
}
// 1. Branch [or not] according to the condition.
asm_branch(false, condition, after_mov_false);
} }
void Assembler::asm_cond(LIns *inst) { void Assembler::asm_cond(LIns *inst) {