/*
Simplifier9900.java
(c) 2008-2013 Edward Swartz
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
*/
package v9t9.tools.asm.transform;
import java.util.List;
import java.util.ListIterator;
import v9t9.common.asm.IInstruction;
import v9t9.common.asm.InstTableCommon;
import v9t9.machine.ti99.cpu.Inst9900;
import v9t9.tools.asm.LLInstruction;
import v9t9.tools.asm.operand.ll.LLOperand;
import v9t9.tools.asm.operand.ll.LLRegIndOperand;
import v9t9.tools.asm.operand.ll.LLRegOffsOperand;
/**
* @author Ed
*
*/
public class Simplifier9900 {
private final List<IInstruction> insts;
public Simplifier9900(List<IInstruction> insts) {
this.insts = insts;
}
public boolean run() {
boolean changed = false;
for (ListIterator<IInstruction> iterator = insts.listIterator();
iterator.hasNext();) {
IInstruction inst = iterator.next();
if (!(inst instanceof LLInstruction))
continue;
LLInstruction llInst = (LLInstruction) inst;
changed |= simplifyInstructionOperands(llInst);
changed |= convertInstruction(llInst);
if (llInst.getInst() == InstTableCommon.Idelete) {
System.err.println("Changed " + inst.toInfoString());
iterator.remove();
changed = true;
}
}
return changed;
}
private boolean simplifyInstructionOperands(LLInstruction llInst) {
boolean changed = false;
LLOperand op;
op = reduceOperand(llInst.getOp1());
if (op != llInst.getOp1()) {
llInst.setOp1(op);
changed = true;
}
op = reduceOperand(llInst.getOp2());
if (op != llInst.getOp2()) {
llInst.setOp2(op);
changed = true;
}
return changed;
}
private LLOperand reduceOperand(LLOperand op) {
if (!(op instanceof LLRegOffsOperand))
return op;
LLRegOffsOperand offs = (LLRegOffsOperand) op;
if (offs.getOffset() == 0)
return new LLRegIndOperand(offs.getRegister());
return op;
}
private boolean convertInstruction(LLInstruction llInst) {
if (llInst.getInst() == Inst9900.Ili) {
LLOperand op2 = llInst.getOp2();
int immed = op2.getImmediate();
if (immed == 0) {
llInst.setInst(Inst9900.Iclr);
llInst.setOp2(null);
return true;
} else if (immed == -1) {
llInst.setInst(Inst9900.Iseto);
llInst.setOp2(null);
return true;
}
}
else if (llInst.getInst() == Inst9900.Iai) {
LLOperand op2 = llInst.getOp2();
int immed = op2.getImmediate();
if (immed == 0) {
llInst.setInst(InstTableCommon.Idelete);
return true;
} else if (immed == 1) {
llInst.setInst(Inst9900.Iinc);
llInst.setOp2(null);
return true;
} else if (immed == -1) {
llInst.setInst(Inst9900.Idec);
llInst.setOp2(null);
return true;
} else if (immed == 2) {
llInst.setInst(Inst9900.Iinct);
llInst.setOp2(null);
return true;
} else if (immed == -2) {
llInst.setInst(Inst9900.Idect);
llInst.setOp2(null);
return true;
}
}
return false;
}
}