/* This file is part of JOP, the Java Optimized Processor see <http://www.jopdesign.com/> Copyright (C) 2009, Benedikt Huber (benedikt.huber@gmail.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.jopdesign.timing.jop; import java.io.Serializable; import java.util.Vector; import com.jopdesign.timing.jop.MicrocodeAnalysis.MicrocodeVerificationException; import com.jopdesign.tools.Instruction; import com.jopdesign.tools.Jopa.Line; /** * A {@code MicrocodePath} represents a microcode instruction sequence. * Each path is a list of {@code PathEntry} objects, which correspond to * single microcode instructions, along with some static analysis information. * * @author Benedikt Huber <benedikt.huber@gmail.com> */ public class MicrocodePath implements Serializable { private static final long serialVersionUID = 1L; /** Path Entry, 'constant', i.e. you never modify any fields after construction */ public class PathEntry implements Serializable { private static final long serialVersionUID = 1L; private final Line line; private final Integer tos; /** TOS (op of stack), if available */ private PathEntry(Line l) { this(l,null); } private PathEntry(Line l, Integer tos) { this.line = l; this.tos = tos; } /** Get the microcode instruction * @return */ public Instruction getInstruction() { return line.getInstruction(); } /** Return the top of stack value, if it is known at this instruction * * @return the TOS, or {@code null} if the TOS isn't known at this point */ public Integer getTOS() { return tos; } @Override public String toString() { Instruction i = getInstruction(); String stringRepr = i.name; if(i.opdSize!=0) { if(line.getSymVal() != null) stringRepr += " "+line.getSymVal(); else stringRepr += " "+line.getIntVal(); } if(tos != null) { stringRepr += "{tos="+tos+"}"; } return stringRepr; } } private String opName; private Vector<PathEntry> path; private boolean nullPtrCheck = false, arrayBoundCheck = false, hasWait = false; private int minMultiplierDelay = Integer.MAX_VALUE; public MicrocodePath(String name) { this.opName = name; this.path = new Vector<PathEntry>(); } /** Get the micro code instruction sequence aggregated by this {@code MicrocodePath} * * @return */ public Vector<PathEntry> getPath() { return this.path; } /** * Query whether there is a byte code load instruction on the path * @return */ public boolean hasBytecodeLoad() { for(PathEntry instr : path) { if(instr.getInstruction().opcode == MicrocodeConstants.STBCRD) return true; } return false; } public MicrocodePath clone() { MicrocodePath cloned = new MicrocodePath(opName); cloned.path = new Vector<PathEntry>(path); cloned.nullPtrCheck = nullPtrCheck; cloned.arrayBoundCheck = arrayBoundCheck; cloned.hasWait = hasWait; cloned.minMultiplierDelay = minMultiplierDelay; return cloned; } public void addInstr(Line microInstr, Integer tos) { this.path.add(new PathEntry(microInstr,tos)); } /** check that the instruction before the current one did not modify the TOS value */ public void checkStableTOS() throws MicrocodeVerificationException { /* Unknown last instr: MAYBE modified TOS */ if (path.size() == 1) { throw new MicrocodeVerificationException("last instruction maybe modified TOS (empty path)"); } Instruction lastInstr = path.get(path.size() - 2).getInstruction(); /* Some statements do not use the stack */ if(lastInstr.noStackUse()) { return; } /* DUP does not modify the TOS */ if(lastInstr.opcode == MicrocodeConstants.DUP) { return; } /* If we have a DUP first, and the next instruction consumes one element without producing * any, the TOS values isn't modified */ if(path.size() >= 3 && path.get(path.size() - 3).getInstruction().opcode == MicrocodeConstants.DUP && lastInstr.isStackConsumer() && ! lastInstr.isStackProducer()) { return; } /* Unknown: TOS was MAYBE modified */ System.err.println("[WARNING] "+opName+" : "+ "last instruction maybe modified TOS: "+lastInstr); } @Override public String toString() { String s = path.toString(); if(hasWait) s+= "[wait]"; if(nullPtrCheck) s+= "[check-null-ptr]"; if(arrayBoundCheck) s+= "[check-array-bound]"; if(minMultiplierDelay != Integer.MAX_VALUE) s+= "[multiplier/delay "+minMultiplierDelay+"]"; return s; } public void setNullPtrCheck() { this.nullPtrCheck = true; } public void setArrayBoundCheck() { this.arrayBoundCheck = true; } public void setNeedsMultiplier(int delay) { this.minMultiplierDelay = Math.min(minMultiplierDelay, delay); } public void setHasWait() { this.hasWait = true; } }