GP-2235 Eliminate threading conflict when using context for delayslot

This commit is contained in:
caheckman 2022-06-28 18:02:42 -04:00
parent 28f59b8fa3
commit ab31812dd4
2 changed files with 129 additions and 80 deletions

View file

@ -13,10 +13,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/*
* Created on Feb 9, 2005
*
*/
package ghidra.app.plugin.processors.sleigh; package ghidra.app.plugin.processors.sleigh;
import java.util.*; import java.util.*;
@ -161,19 +157,22 @@ public class SleighInstructionPrototype implements InstructionPrototype {
private static void addExplicitFlow(ConstructState state, OpTpl op, int flags, private static void addExplicitFlow(ConstructState state, OpTpl op, int flags,
FlowSummary summary) { FlowSummary summary) {
if (summary.flowState == null) if (summary.flowState == null) {
summary.flowState = new ArrayList<>(); summary.flowState = new ArrayList<>();
}
FlowRecord res = new FlowRecord(); FlowRecord res = new FlowRecord();
summary.flowState.add(res); summary.flowState.add(res);
res.flowFlags = flags; res.flowFlags = flags;
res.op = op; res.op = op;
res.addressnode = null; res.addressnode = null;
VarnodeTpl dest = op.getInput()[0]; // First varnode input contains the destination address VarnodeTpl dest = op.getInput()[0]; // First varnode input contains the destination address
if ((flags & (JUMPOUT | CALL | CROSSBUILD)) == 0) if ((flags & (JUMPOUT | CALL | CROSSBUILD)) == 0) {
return; return;
}
// If the flow is out of the instruction, store the ConstructState so we can easily calculate address // If the flow is out of the instruction, store the ConstructState so we can easily calculate address
if (state == null) if (state == null) {
return; return;
}
if ((flags & CROSSBUILD) != 0) { if ((flags & CROSSBUILD) != 0) {
res.addressnode = state; res.addressnode = state;
} }
@ -191,6 +190,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
* Walk the pcode templates in the order they would be emitted. * Walk the pcode templates in the order they would be emitted.
* Collect flowFlags FlowRecords * Collect flowFlags FlowRecords
* @param walker the pcode template walker * @param walker the pcode template walker
* @return a summary of the flow information
*/ */
public static FlowSummary walkTemplates(OpTplWalker walker) { public static FlowSummary walkTemplates(OpTplWalker walker) {
FlowSummary res = new FlowSummary(); FlowSummary res = new FlowSummary();
@ -218,24 +218,31 @@ public class SleighInstructionPrototype implements InstructionPrototype {
break; break;
case PcodeOp.BRANCH: case PcodeOp.BRANCH:
destType = res.lastop.getInput()[0].getOffset().getType(); destType = res.lastop.getInput()[0].getOffset().getType();
if (destType == ConstTpl.J_NEXT) if (destType == ConstTpl.J_NEXT) {
flags = BRANCH_TO_END; flags = BRANCH_TO_END;
else if (destType == ConstTpl.J_START) }
else if (destType == ConstTpl.J_START) {
flags = NO_FALLTHRU; flags = NO_FALLTHRU;
else if (destType == ConstTpl.J_RELATIVE) }
else if (destType == ConstTpl.J_RELATIVE) {
flags = NO_FALLTHRU; flags = NO_FALLTHRU;
else }
else {
flags = JUMPOUT | NO_FALLTHRU; flags = JUMPOUT | NO_FALLTHRU;
}
addExplicitFlow(walker.getState(), res.lastop, flags, res); addExplicitFlow(walker.getState(), res.lastop, flags, res);
break; break;
case PcodeOp.CBRANCH: case PcodeOp.CBRANCH:
destType = res.lastop.getInput()[0].getOffset().getType(); destType = res.lastop.getInput()[0].getOffset().getType();
if (destType == ConstTpl.J_NEXT) if (destType == ConstTpl.J_NEXT) {
flags = BRANCH_TO_END; flags = BRANCH_TO_END;
else if ((destType != ConstTpl.J_START) && (destType != ConstTpl.J_RELATIVE)) }
else if ((destType != ConstTpl.J_START) && (destType != ConstTpl.J_RELATIVE)) {
flags = JUMPOUT; flags = JUMPOUT;
else }
else {
flags = 0; flags = 0;
}
addExplicitFlow(walker.getState(), res.lastop, flags, res); addExplicitFlow(walker.getState(), res.lastop, flags, res);
break; break;
case PcodeOp.CALL: case PcodeOp.CALL:
@ -252,8 +259,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
break; break;
case PcodeOp.INDIRECT: // Encode delayslot case PcodeOp.INDIRECT: // Encode delayslot
destType = (int) res.lastop.getInput()[0].getOffset().getReal(); destType = (int) res.lastop.getInput()[0].getOffset().getReal();
if (destType > res.delay) if (destType > res.delay) {
res.delay = destType; res.delay = destType;
}
default: default:
break; break;
@ -263,8 +271,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
} }
public static FlowType flowListToFlowType(List<FlowRecord> flowstate) { public static FlowType flowListToFlowType(List<FlowRecord> flowstate) {
if (flowstate == null) if (flowstate == null) {
return RefType.FALL_THROUGH; return RefType.FALL_THROUGH;
}
int flags = 0; int flags = 0;
for (FlowRecord rec : flowstate) { for (FlowRecord rec : flowstate) {
flags &= ~(NO_FALLTHRU | CROSSBUILD | LABEL); flags &= ~(NO_FALLTHRU | CROSSBUILD | LABEL);
@ -307,8 +316,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
private static FlowType convertFlowFlags(int flowFlags) { private static FlowType convertFlowFlags(int flowFlags) {
if ((flowFlags & LABEL) != 0) if ((flowFlags & LABEL) != 0) {
flowFlags |= BRANCH_TO_END; flowFlags |= BRANCH_TO_END;
}
flowFlags &= ~(CROSSBUILD | LABEL); flowFlags &= ~(CROSSBUILD | LABEL);
// NOTE: If prototype has cross-build, flow must be determined dynamically // NOTE: If prototype has cross-build, flow must be determined dynamically
switch (flowFlags) { // Convert flags to a standard flowtype switch (flowFlags) { // Convert flags to a standard flowtype
@ -395,8 +405,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == null) if (obj == null) {
return false; return false;
}
return (hashCode() == obj.hashCode()); // Trust entirely in hash return (hashCode() == obj.hashCode()); // Trust entirely in hash
} }
@ -415,8 +426,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
@Override @Override
public FlowType getFlowType(InstructionContext context) { public FlowType getFlowType(InstructionContext context) {
if (!hasCrossBuilds) if (!hasCrossBuilds) {
return flowType; return flowType;
}
int flags = 0; int flags = 0;
try { try {
flags = gatherFlags(0, context, -1); flags = gatherFlags(0, context, -1);
@ -457,6 +469,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
} }
} }
catch (Exception e) { catch (Exception e) {
// Treat bad instructions as not part of delay slot
} }
return delayInstrCnt; return delayInstrCnt;
} }
@ -473,8 +486,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
@Override @Override
public int getOpType(int opIndex, InstructionContext context) { public int getOpType(int opIndex, InstructionContext context) {
if (opIndex < 0 || opIndex >= opresolve.length) if (opIndex < 0 || opIndex >= opresolve.length) {
return OperandType.DYNAMIC; return OperandType.DYNAMIC;
}
SleighParserContext protoContext; SleighParserContext protoContext;
try { try {
@ -485,20 +499,25 @@ public class SleighInstructionPrototype implements InstructionPrototype {
} }
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]); ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
FixedHandle hand = protoContext.getFixedHandle(opState); FixedHandle hand = protoContext.getFixedHandle(opState);
if (hand.isInvalid()) if (hand.isInvalid()) {
return OperandType.DYNAMIC; return OperandType.DYNAMIC;
}
int indirect = isIndirect(opresolve[opIndex]) ? OperandType.INDIRECT : 0; int indirect = isIndirect(opresolve[opIndex]) ? OperandType.INDIRECT : 0;
if (hand.offset_space == null) { // Static handle if (hand.offset_space == null) { // Static handle
int type = hand.space.getType(); int type = hand.space.getType();
if (type == AddressSpace.TYPE_REGISTER) if (type == AddressSpace.TYPE_REGISTER) {
return OperandType.REGISTER | indirect; return OperandType.REGISTER | indirect;
if (type == AddressSpace.TYPE_CONSTANT) }
if (type == AddressSpace.TYPE_CONSTANT) {
return OperandType.SCALAR | indirect; return OperandType.SCALAR | indirect;
}
OperandSymbol sym = mnemonicState.getConstructor().getOperand(opresolve[opIndex]); OperandSymbol sym = mnemonicState.getConstructor().getOperand(opresolve[opIndex]);
if (sym.isCodeAddress()) if (sym.isCodeAddress()) {
return (OperandType.ADDRESS | OperandType.CODE | indirect); return (OperandType.ADDRESS | OperandType.CODE | indirect);
if (type == AddressSpace.TYPE_RAM) }
if (type == AddressSpace.TYPE_RAM) {
return (OperandType.ADDRESS | OperandType.DATA | indirect); return (OperandType.ADDRESS | OperandType.DATA | indirect);
}
} }
return OperandType.DYNAMIC | indirect; return OperandType.DYNAMIC | indirect;
} }
@ -530,6 +549,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
return context.getAddress().addNoWrap(getFallThroughOffset(context)); return context.getAddress().addNoWrap(getFallThroughOffset(context));
} }
catch (AddressOverflowException e) { catch (AddressOverflowException e) {
// Return null if fallthru goes beyond boundary of address space
} }
} }
return null; return null;
@ -565,13 +585,16 @@ public class SleighInstructionPrototype implements InstructionPrototype {
private int gatherFlags(int curflags, InstructionContext context, int secnum) private int gatherFlags(int curflags, InstructionContext context, int secnum)
throws MemoryAccessException, UnknownContextException { throws MemoryAccessException, UnknownContextException {
List<FlowRecord> curlist = null; List<FlowRecord> curlist = null;
if (secnum < 0) if (secnum < 0) {
curlist = flowStateList; curlist = flowStateList;
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size())) }
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size())) {
curlist = flowStateListNamed.get(secnum); curlist = flowStateListNamed.get(secnum);
}
if (curlist == null) if (curlist == null) {
return curflags; return curflags;
}
for (FlowRecord rec : curlist) { for (FlowRecord rec : curlist) {
if ((rec.flowFlags & CROSSBUILD) != 0) { if ((rec.flowFlags & CROSSBUILD) != 0) {
@ -611,20 +634,23 @@ public class SleighInstructionPrototype implements InstructionPrototype {
* @param res is the resulting flow Addresses * @param res is the resulting flow Addresses
* @param parsecontext is the parsing context for the current instruction * @param parsecontext is the parsing context for the current instruction
* @param context is the context for the particular address so crossbuilds can be resolved * @param context is the context for the particular address so crossbuilds can be resolved
* @throws MemoryAccessException * @throws MemoryAccessException if a memory error occurred while resolving instruction details
* @throws UnknownContextException * @throws UnknownContextException if the gather encounters an instruction not previously parsed
*/ */
private void gatherFlows(ArrayList<Address> res, SleighParserContext parsecontext, private void gatherFlows(ArrayList<Address> res, SleighParserContext parsecontext,
InstructionContext context, int secnum) InstructionContext context, int secnum)
throws MemoryAccessException, UnknownContextException { throws MemoryAccessException, UnknownContextException {
List<FlowRecord> curlist = null; List<FlowRecord> curlist = null;
if (secnum < 0) if (secnum < 0) {
curlist = flowStateList; curlist = flowStateList;
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size())) }
else if ((flowStateListNamed != null) && (secnum < flowStateListNamed.size())) {
curlist = flowStateListNamed.get(secnum); curlist = flowStateListNamed.get(secnum);
}
if (curlist == null) if (curlist == null) {
return; return;
}
for (FlowRecord rec : curlist) { for (FlowRecord rec : curlist) {
if ((rec.flowFlags & CROSSBUILD) != 0) { if ((rec.flowFlags & CROSSBUILD) != 0) {
@ -654,8 +680,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
@Override @Override
public Address[] getFlows(InstructionContext context) { public Address[] getFlows(InstructionContext context) {
if (flowStateList.size() == 0) if (flowStateList.size() == 0) {
return emptyFlow; return emptyFlow;
}
ArrayList<Address> addresses = new ArrayList<>(); ArrayList<Address> addresses = new ArrayList<>();
try { try {
@ -668,8 +695,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
return emptyFlow; return emptyFlow;
} }
if (addresses.size() == 0) if (addresses.size() == 0) {
return emptyFlow; return emptyFlow;
}
return addresses.toArray(new Address[addresses.size()]); return addresses.toArray(new Address[addresses.size()]);
} }
@ -706,6 +734,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
sym.printList(walker, list); sym.printList(walker, list);
} }
catch (Exception e) { catch (Exception e) {
// If the instruction produces memory errors, treat as if it has no representation list
} }
AddressSpace curSpace = context.getAddress().getAddressSpace(); AddressSpace curSpace = context.getAddress().getAddressSpace();
@ -730,6 +759,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
return ct.getOperand(opresolve[opIndex]); return ct.getOperand(opresolve[opIndex]);
} }
catch (Exception e) { catch (Exception e) {
// Return null for an out-of bounds opIndex
} }
return null; return null;
} }
@ -746,8 +776,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
protoContext = (SleighParserContext) context.getParserContext(); protoContext = (SleighParserContext) context.getParserContext();
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]); ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
hand = protoContext.getFixedHandle(opState); hand = protoContext.getFixedHandle(opState);
if (hand.isInvalid()) if (hand.isInvalid()) {
return null; return null;
}
} }
catch (Exception e) { catch (Exception e) {
return null; return null;
@ -769,8 +800,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]); ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
FixedHandle hand = protoContext.getFixedHandle(opState); FixedHandle hand = protoContext.getFixedHandle(opState);
if (hand.isInvalid()) if (hand.isInvalid()) {
return null; return null;
}
if (hand.space.getType() == AddressSpace.TYPE_CONSTANT) { if (hand.space.getType() == AddressSpace.TYPE_CONSTANT) {
int size = hand.size; int size = hand.size;
if (size == 0) { if (size == 0) {
@ -784,6 +816,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
} }
} }
catch (Exception e) { catch (Exception e) {
// If opIndex is out of bounds (or if there are memory errors) return a null Scalar
} }
return null; return null;
} }
@ -798,13 +831,15 @@ public class SleighInstructionPrototype implements InstructionPrototype {
SleighParserContext protoContext = (SleighParserContext) context.getParserContext(); SleighParserContext protoContext = (SleighParserContext) context.getParserContext();
ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]); ConstructState opState = mnemonicState.getSubState(opresolve[opIndex]);
FixedHandle hand = protoContext.getFixedHandle(opState); FixedHandle hand = protoContext.getFixedHandle(opState);
if (hand.isInvalid()) if (hand.isInvalid()) {
return null; return null;
}
if (hand.space.getType() == AddressSpace.TYPE_REGISTER) { if (hand.space.getType() == AddressSpace.TYPE_REGISTER) {
return language.getRegister(hand.space, hand.offset_offset, hand.size); return language.getRegister(hand.space, hand.offset_offset, hand.size);
} }
} }
catch (Exception e) { catch (Exception e) {
// If opIndex is out of bounds (or if there are memory errors) return null
} }
return null; return null;
} }
@ -960,7 +995,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
bytecount += len; bytecount += len;
} }
while (bytecount < delaySlotByteCnt); while (bytecount < delaySlotByteCnt);
protoContext.setDelaySlotLength(bytecount); protoContext = new SleighParserContext(protoContext, bytecount);
} }
ParserWalker walker = new ParserWalker(protoContext); ParserWalker walker = new ParserWalker(protoContext);
walker.baseState(); walker.baseState();
@ -971,7 +1006,6 @@ public class SleighInstructionPrototype implements InstructionPrototype {
if (!isindelayslot) { if (!isindelayslot) {
emit.resolveFinalFallthrough(); emit.resolveFinalFallthrough();
} }
protoContext.setDelaySlotLength(0);
return emit.getPcodeOp(); return emit.getPcodeOp();
} }
catch (NotYetImplementedException e) { catch (NotYetImplementedException e) {
@ -1002,7 +1036,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
bytecount += len; bytecount += len;
} }
while (bytecount < delaySlotByteCnt); while (bytecount < delaySlotByteCnt);
protoContext.setDelaySlotLength(bytecount); protoContext = new SleighParserContext(protoContext, bytecount);
} }
ParserWalker walker = new ParserWalker(protoContext); ParserWalker walker = new ParserWalker(protoContext);
walker.baseState(); walker.baseState();
@ -1022,7 +1056,6 @@ public class SleighInstructionPrototype implements InstructionPrototype {
if (!isindelayslot) { if (!isindelayslot) {
emit.resolveFinalFallthrough(); emit.resolveFinalFallthrough();
} }
protoContext.setDelaySlotLength(0);
emit.write(PcodeEmitPacked.end_tag); // Terminate the inst_tag emit.write(PcodeEmitPacked.end_tag); // Terminate the inst_tag
return emit.getPackedBytes(); return emit.getPackedBytes();
} }
@ -1061,6 +1094,7 @@ public class SleighInstructionPrototype implements InstructionPrototype {
} }
} }
catch (Exception e) { catch (Exception e) {
// If opIndex is out of bounds (or if there are memory errors) return an empty p-code list
} }
return emptyPCode; return emptyPCode;
} }
@ -1342,8 +1376,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
if (subct != null) { if (subct != null) {
walker.setConstructor(subct); walker.setConstructor(subct);
subct.applyContext(walker, debug); subct.applyContext(walker, debug);
if (debug != null) if (debug != null) {
debug.indent(); debug.indent();
}
break; break;
} }
if (debug != null) { if (debug != null) {
@ -1355,8 +1390,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
} }
} }
else { else {
if (debug != null) if (debug != null) {
debug.dumpPattern(sym, walker); debug.dumpPattern(sym, walker);
}
} }
walker.setCurrentLength(sym.getMinimumLength()); walker.setCurrentLength(sym.getMinimumLength());
walker.popOperand(); walker.popOperand();
@ -1416,10 +1452,12 @@ public class SleighInstructionPrototype implements InstructionPrototype {
ConstructTpl templ = ct.getTempl(); ConstructTpl templ = ct.getTempl();
if (templ != null) { if (templ != null) {
HandleTpl res = templ.getResult(); HandleTpl res = templ.getResult();
if (res != null) // Pop up handle to containing operand if (res != null) { // Pop up handle to containing operand
res.fix(walker.getParentHandle(), walker); res.fix(walker.getParentHandle(), walker);
else }
else {
walker.getParentHandle().setInvalid(); walker.getParentHandle().setInvalid();
}
} }
walker.popOperand(); walker.popOperand();
} }
@ -1430,8 +1468,8 @@ public class SleighInstructionPrototype implements InstructionPrototype {
* Reconstruct the ParserContext's internal packed context array and its list of global ContextSet directives * Reconstruct the ParserContext's internal packed context array and its list of global ContextSet directives
* by walking a previously resolved ConstructState tree * by walking a previously resolved ConstructState tree
* @param protoContext is the SleighParserContext containing the tree and holding the context results * @param protoContext is the SleighParserContext containing the tree and holding the context results
* @param debug * @param debug (optional) logger for collecting information about the recovered context
* @throws MemoryAccessException * @throws MemoryAccessException if memory errors occur trying to recover context
*/ */
private void reconstructContext(SleighParserContext protoContext, SleighDebugLogger debug) private void reconstructContext(SleighParserContext protoContext, SleighDebugLogger debug)
throws MemoryAccessException { throws MemoryAccessException {
@ -1442,8 +1480,9 @@ public class SleighInstructionPrototype implements InstructionPrototype {
if (ct != null) { if (ct != null) {
int oper = walker.getOperand(); int oper = walker.getOperand();
int numoper = ct.getNumOperands(); int numoper = ct.getNumOperands();
if (oper == 0) // Upon first entry to this Constructor if (oper == 0) { // Upon first entry to this Constructor
ct.applyContext(walker, debug); // Apply its context changes ct.applyContext(walker, debug); // Apply its context changes
}
if (oper < numoper) { if (oper < numoper) {
walker.pushOperand(oper); walker.pushOperand(oper);
continue; continue;

View file

@ -13,10 +13,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
/*
* Created on Jan 26, 2005
*
*/
package ghidra.app.plugin.processors.sleigh; package ghidra.app.plugin.processors.sleigh;
import java.util.*; import java.util.*;
@ -36,7 +32,6 @@ import ghidra.program.model.mem.MemoryAccessException;
*/ */
public class SleighParserContext implements ParserContext { public class SleighParserContext implements ParserContext {
// private WeakReference<MemBuffer> memBufferRef;
private MemBuffer memBuffer; private MemBuffer memBuffer;
private Address addr; // Address of start of instruction private Address addr; // Address of start of instruction
private Address nextInstrAddr; // Address of next instruction private Address nextInstrAddr; // Address of next instruction
@ -44,23 +39,22 @@ public class SleighParserContext implements ParserContext {
private Address destAddr; // corresponds to inst_dest for call-fixup use private Address destAddr; // corresponds to inst_dest for call-fixup use
private SleighInstructionPrototype prototype; private SleighInstructionPrototype prototype;
private AddressSpace constantSpace; private AddressSpace constantSpace;
private HashMap<ConstructState, FixedHandle> handleMap = private HashMap<ConstructState, FixedHandle> handleMap;
new HashMap<ConstructState, FixedHandle>();
private ArrayList<ContextSet> contextcommit; // Pending changes to context private ArrayList<ContextSet> contextcommit; // Pending changes to context
private int[] context; // packed context bits private int[] context; // packed context bits
public SleighParserContext(MemBuffer memBuf, SleighInstructionPrototype prototype, public SleighParserContext(MemBuffer memBuf, SleighInstructionPrototype prototype,
ProcessorContextView processorContext) { ProcessorContextView processorContext) {
this.handleMap = new HashMap<>();
this.prototype = prototype; this.prototype = prototype;
this.constantSpace = prototype.getLanguage().getAddressFactory().getConstantSpace(); this.constantSpace = prototype.getLanguage().getAddressFactory().getConstantSpace();
// this.memBufferRef = new WeakReference<MemBuffer>(memBuf);
this.memBuffer = memBuf; this.memBuffer = memBuf;
this.addr = memBuf.getAddress(); this.addr = memBuf.getAddress();
int contextSize = prototype.getContextCache().getContextSize(); int contextSize = prototype.getContextCache().getContextSize();
context = new int[contextSize]; context = new int[contextSize];
contextcommit = new ArrayList<ContextSet>(); contextcommit = new ArrayList<>();
try { try {
nextInstrAddr = addr.add(prototype.getLength()); nextInstrAddr = addr.add(prototype.getLength());
} }
@ -69,7 +63,6 @@ public class SleighParserContext implements ParserContext {
nextInstrAddr = null; nextInstrAddr = null;
} }
prototype.getContextCache().getContext(processorContext, context); prototype.getContextCache().getContext(processorContext, context);
} }
@Override @Override
@ -95,6 +88,33 @@ public class SleighParserContext implements ParserContext {
destAddr = dAddr; destAddr = dAddr;
} }
/**
* Generate context specifically for an instruction that has a delayslot.
* When generating p-code SLEIGH has an alternate interpretation of the "inst_next"
* symbol that takes into account the instruction in the delay slot. This context is
* generated at the point when specific instruction(s) in the delay slot are known.
* @param origContext is the original context (for the instruction in isolation)
* @param delayByteCount is the number of bytes in instruction stream occupied by the delay slot
*/
public SleighParserContext(SleighParserContext origContext, int delayByteCount) {
memBuffer = origContext.memBuffer;
prototype = origContext.prototype;
context = origContext.context;
contextcommit = origContext.contextcommit;
addr = origContext.addr;
refAddr = origContext.refAddr;
destAddr = origContext.destAddr;
constantSpace = origContext.constantSpace;
handleMap = origContext.handleMap;
try {
nextInstrAddr = addr.add(prototype.getLength() + delayByteCount);
}
catch (AddressOutOfBoundsException exc) {
// no next instruction, last instruction in memory.
nextInstrAddr = null;
}
}
/** /**
* @return context commits for normal instruction parse. * @return context commits for normal instruction parse.
*/ */
@ -113,13 +133,13 @@ public class SleighParserContext implements ParserContext {
} }
public void applyCommits(ProcessorContext ctx) throws MemoryAccessException { public void applyCommits(ProcessorContext ctx) throws MemoryAccessException {
if (contextcommit.size() == 0) if (contextcommit.size() == 0) {
return; return;
}
ContextCache contextCache = prototype.getContextCache(); ContextCache contextCache = prototype.getContextCache();
ParserWalker walker = new ParserWalker(this); ParserWalker walker = new ParserWalker(this);
walker.baseState(); walker.baseState();
for (int i = 0; i < contextcommit.size(); ++i) { for (ContextSet set : contextcommit) {
ContextSet set = contextcommit.get(i);
FixedHandle hand; FixedHandle hand;
if (set.sym instanceof OperandSymbol) { // value of OperandSymbol is already calculated, find right node if (set.sym instanceof OperandSymbol) { // value of OperandSymbol is already calculated, find right node
int ind = ((OperandSymbol) set.sym).getIndex(); int ind = ((OperandSymbol) set.sym).getIndex();
@ -159,16 +179,6 @@ public class SleighParserContext implements ParserContext {
return nextInstrAddr; return nextInstrAddr;
} }
public void setDelaySlotLength(int delayByteLength) {
try {
nextInstrAddr = addr.add(prototype.getLength() + delayByteLength);
}
catch (AddressOutOfBoundsException exc) {
// no next instruction, last instruction in memory.
nextInstrAddr = null;
}
}
public AddressSpace getCurSpace() { public AddressSpace getCurSpace() {
return addr.getAddressSpace(); return addr.getAddressSpace();
} }
@ -187,7 +197,7 @@ public class SleighParserContext implements ParserContext {
* undefined memory will return zero byte values. * undefined memory will return zero byte values.
* @param offset offset relative start of this context * @param offset offset relative start of this context
* @param bytestart pattern byte offset relative to specified context offset * @param bytestart pattern byte offset relative to specified context offset
* @param size * @param size is the number of bytes to fetch
* @return requested byte-range value * @return requested byte-range value
* @throws MemoryAccessException if no bytes are available at first byte when (offset+bytestart==0). * @throws MemoryAccessException if no bytes are available at first byte when (offset+bytestart==0).
*/ */
@ -212,8 +222,8 @@ public class SleighParserContext implements ParserContext {
* (packed in big endian format). Uninitialized or * (packed in big endian format). Uninitialized or
* undefined memory will return zero bit values. * undefined memory will return zero bit values.
* @param offset offset relative start of this context * @param offset offset relative start of this context
* @param startbit * @param startbit is the index of the first bit to fetch
* @param size * @param size is the number of bits to fetch
* @return requested bit-range value * @return requested bit-range value
* @throws MemoryAccessException if no bytes are available at first byte when (offset+bytestart/8==0). * @throws MemoryAccessException if no bytes are available at first byte when (offset+bytestart/8==0).
*/ */
@ -242,9 +252,9 @@ public class SleighParserContext implements ParserContext {
/** /**
* Get bytes from context into an int * Get bytes from context into an int
* @param bytestart * @param bytestart is the index of the first byte to fetch
* @param bytesize number of bytes (range: 1 - 4) * @param bytesize number of bytes (range: 1 - 4)
* @return * @return the packed bytes from context
*/ */
public int getContextBytes(int bytestart, int bytesize) { public int getContextBytes(int bytestart, int bytesize) {
int intstart = bytestart / 4; int intstart = bytestart / 4;
@ -266,7 +276,7 @@ public class SleighParserContext implements ParserContext {
/** /**
* Get full set of context bytes. Sleigh only supports context * Get full set of context bytes. Sleigh only supports context
* which is a multiple of 4-bytes (i.e., size of int) * which is a multiple of 4-bytes (i.e., size of int)
* @return * @return the array of context data
*/ */
public int[] getContextBytes() { public int[] getContextBytes() {
return context; return context;
@ -274,9 +284,9 @@ public class SleighParserContext implements ParserContext {
/** /**
* Get bits from context into an int * Get bits from context into an int
* @param startbit * @param startbit is the index of the first bit to fetch
* @param bitsize number of bits (range: 1 - 32) * @param bitsize number of bits (range: 1 - 32)
* @return * @return the packed bits
*/ */
public int getContextBits(int startbit, int bitsize) { public int getContextBits(int startbit, int bitsize) {
int intstart = startbit / 32; int intstart = startbit / 32;