diff --git a/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.md b/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.md index 55bfee889b..7475961002 100644 --- a/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.md +++ b/Ghidra/Configurations/Public_Release/src/global/docs/ChangeHistory.md @@ -1,3 +1,33 @@ +# Ghidra 12.0.4 Change History (March 2026) + +### Improvements +* _Analysis_. Updated the RTTI Analyzer to better handle the case where class names cannot be demangled correctly. Previously, class members would end up in global namespace. Now, a class namespace with the mangled name will be created so that items in that class can be correctly grouped together. (GP-6431, Issue #8944) +* _GUI_. Fixed a potential zip path traversal vulnerability when importing Ghidra theme zip files. (GP-6455) +* _Scripting_. Improved RTTI Windows script vbtable discovery to recognize some invalid tables. (GP-6446, Issue #8944) + +### Bugs +* _Analysis_. Fixed an issue with constants from one function finding their way into another function that is jumped to, and mid-constant propagation the jump is turned into a call. (GP-6442) +* _Analysis_. Corrected analysis problem which failed to properly link thunk functions in the EXTERNAL memory block to existing External library symbols instead of creating new external functions in the unknown external library. (GP-6465) +* _Bookmarks_. Corrected potential Bookmark exception which can occur if bookmarks were ever deleted: Missing bookmark table. (GP-6517) +* _Debugger_. Fixed a deadlock when saving Traces from the __Close Project__ dialog. (GP-6392) +* _Debugger:Memory_. Fixed a bug in the Memory viewer when looking at multiple address spaces. (GP-6449, Issue #8982) +* _Disassembly_. Refactored `PsuedoDisassembler` to use the normal high level Disassembler instead of calling `Language.parse()`. (GP-6496) +* _Exporter_. Enable cancellation for SARIF exports (GP-6469) +* _Listing_. Fixed Listing display to show single string operands. (GP-6095) +* _Processors_. Fixed the semantics of the AARCH64 `ldpsw` instruction. (GP-5590, Issue #6469, #8008) +* _Processors_. Fixed issue with PIC-18 instructions double-incrementing/decrementing. (GP-6004, Issue #3342, #8501) +* _Processors_. Corrected Xtensa slapsec token field naming. (GP-6080) +* _Processors_. Corrected semantics for the CR16 `tbit` instruction. (GP-6181, Issue #8716) +* _Processors_. Corrected mnemonic and semantics for eBPF atomic compare-and-exchange instructions. (GP-6182, Issue #8721) +* _Processors_. Added missing definition for PowerPC Altivec `vadduws` instruction that was mistakenly commented out. (GP-6268, Issue #8821) +* _Processors_. Added support for AARCH64 Common Short Sequence Compression (CSSC) instructions. (GP-6448, Issue #8973, #8979) +* _Processors_. Fixed semantics of AARCH64 `ldar` instruction. (GP-6473, Issue #6467, #8014) +* _Processors_. Corrected disassembly for MIPS instruction `sdbbp16`. (GP-6489) +* _Processors_. Added MIPS32 `save` and `restore` instructions, and refactored coprocessor register read/write. (GP-6501) + +### Notable API Changes +* _GUI_. (GP-6480) The resultsLimit and minLength parameters of the AddressRangeTableModel constructor have been removed. + # Ghidra 12.0.3 Change History (February 2026) ### New Features diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/BasicAutoReadMemorySpec.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/BasicAutoReadMemorySpec.java index 5fec26d692..13211c35c5 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/BasicAutoReadMemorySpec.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/action/BasicAutoReadMemorySpec.java @@ -36,6 +36,7 @@ import ghidra.program.model.address.*; import ghidra.program.model.mem.MemoryAccessException; import ghidra.trace.model.*; import ghidra.trace.model.memory.*; +import ghidra.util.MathUtilities; import ghidra.util.task.TaskMonitor; public enum BasicAutoReadMemorySpec implements AutoReadMemorySpec { @@ -52,7 +53,8 @@ public enum BasicAutoReadMemorySpec implements AutoReadMemorySpec { /** * Automatically read all visible memory */ - VISIBLE("1_READ_VISIBLE", AutoReadMemoryAction.NAME_VISIBLE, AutoReadMemoryAction.ICON_VISIBLE) { + VISIBLE("1_READ_VISIBLE", AutoReadMemoryAction.NAME_VISIBLE, + AutoReadMemoryAction.ICON_VISIBLE) { @Override public CompletableFuture readMemory(PluginTool tool, DebuggerCoordinates coordinates, @@ -77,7 +79,8 @@ public enum BasicAutoReadMemorySpec implements AutoReadMemorySpec { * Automatically read all visible memory, unless it is read-only, in which case, only read it if * it has not already been read. */ - VIS_RO_ONCE("2_READ_VIS_RO_ONCE", AutoReadMemoryAction.NAME_VIS_RO_ONCE, AutoReadMemoryAction.ICON_VIS_RO_ONCE) { + VIS_RO_ONCE("2_READ_VIS_RO_ONCE", AutoReadMemoryAction.NAME_VIS_RO_ONCE, + AutoReadMemoryAction.ICON_VIS_RO_ONCE) { @Override public CompletableFuture readMemory(PluginTool tool, DebuggerCoordinates coordinates, @@ -136,8 +139,15 @@ public enum BasicAutoReadMemorySpec implements AutoReadMemorySpec { // Not terribly efficient, but this is one range most of the time for (AddressRange range : set) { AddressSpace space = range.getAddressSpace(); - Address min = space.getAddress(range.getMinAddress().getOffset() & blockMask); - Address max = space.getAddress(range.getMaxAddress().getOffset() | ~blockMask); + long minOffset = range.getMinAddress().getOffset() & blockMask; + minOffset = MathUtilities.unsignedMax(minOffset, space.getMinAddress().getOffset()); + long maxOffset = range.getMaxAddress().getOffset() | ~blockMask; + maxOffset = MathUtilities.unsignedMin(maxOffset, space.getMaxAddress().getOffset()); + if (minOffset > maxOffset) { + continue; + } + Address min = space.getAddress(minOffset); + Address max = space.getAddress(maxOffset); result.add(new AddressRangeImpl(min, max)); } return result; diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/CachedBytePage.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/CachedBytePage.java index 01a87f1d42..88289b031a 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/CachedBytePage.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/memory/CachedBytePage.java @@ -47,6 +47,9 @@ public class CachedBytePage { record CacheKey(DebuggerCoordinates coordinates, Address start) { int computeOffset(DebuggerCoordinates coordinates, Address address) { if (coordsEqualForMemory(this.coordinates, coordinates)) { + if (start.getAddressSpace() != address.getAddressSpace()) { + return -1; + } long offset = address.subtract(start); if (0 <= offset && offset < PAGE_SIZE) { return (int) offset; diff --git a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServicePlugin.java b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServicePlugin.java index 7bd047d237..0825d1328d 100644 --- a/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServicePlugin.java +++ b/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/service/tracemgr/DebuggerTraceManagerServicePlugin.java @@ -634,7 +634,7 @@ public class DebuggerTraceManagerServicePlugin extends Plugin } @Override - public synchronized Collection getOpenTraces() { + public Collection getOpenTraces() { synchronized (listenersByTrace) { return Set.copyOf(tracesView); } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTrace.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTrace.java index 36021a0204..1c9c6284af 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTrace.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTrace.java @@ -15,7 +15,6 @@ */ package ghidra.trace.database; -import java.io.File; import java.io.IOException; import java.util.*; import java.util.function.Consumer; @@ -876,16 +875,10 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace } @Override - public void save(String comment, TaskMonitor monitor) throws IOException, CancelledException { - objectManager.flushWbCaches(); - super.save(comment, monitor); - } - - @Override - public void saveToPackedFile(File outputFile, TaskMonitor monitor) - throws IOException, CancelledException { - objectManager.flushWbCaches(); - super.saveToPackedFile(outputFile, monitor); + protected void prepareToSave() { + try (Transaction tx = openForcedTransaction("flush for save")) { + objectManager.flushWbCaches(); + } } public boolean isClosing() { @@ -895,9 +888,9 @@ public class DBTrace extends DBCachedDomainObjectAdapter implements Trace, Trace @Override protected void close() { closing = true; - objectManager.flushWbCaches(); - super.close(); + // NOTE: Any unsaved changes in the write-back cache are unrecoverable objectManager.waitWbWorkers(); + super.close(); } @Override diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTraceContentHandler.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTraceContentHandler.java index 093b571e13..a562af81e0 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTraceContentHandler.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/DBTraceContentHandler.java @@ -41,16 +41,16 @@ public class DBTraceContentHandler extends DBWithUserDataContentHandler static final Class TRACE_DOMAIN_OBJECT_CLASS = DBTrace.class; static final String TRACE_CONTENT_DEFAULT_TOOL = "Debugger"; - private static final DBTraceLinkContentHandler linkHandler = new DBTraceLinkContentHandler(); + private static final DBTraceLinkContentHandler LINK_HANDLER = new DBTraceLinkContentHandler(); @Override public long createFile(FileSystem fs, FileSystem userfs, String path, String name, DomainObject obj, TaskMonitor monitor) throws IOException, InvalidNameException, CancelledException { - if (!(obj instanceof DBTrace)) { + if (!(obj instanceof DBTrace trace)) { throw new IOException("Unsupported domain object: " + obj.getClass().getName()); } - return createFile((DBTrace) obj, TRACE_CONTENT_TYPE, fs, path, name, monitor); + return createFile(trace, TRACE_CONTENT_TYPE, fs, path, name, monitor); } @Override @@ -340,6 +340,6 @@ public class DBTraceContentHandler extends DBWithUserDataContentHandler @Override public DBTraceLinkContentHandler getLinkHandler() { - return linkHandler; + return LINK_HANDLER; } } diff --git a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectValueWriteBehindCache.java b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectValueWriteBehindCache.java index 13b0481e16..896a3d2b0d 100644 --- a/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectValueWriteBehindCache.java +++ b/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/target/DBTraceObjectValueWriteBehindCache.java @@ -40,8 +40,9 @@ class DBTraceObjectValueWriteBehindCache { private final AsyncReference busy = new AsyncReference<>(false); private volatile boolean flushing = false; - private final Map>> cachedValues = - new HashMap<>(); + private final Map>> cachedValues = + new HashMap<>(); public DBTraceObjectValueWriteBehindCache(DBTraceObjectManager manager) { this.manager = manager; @@ -51,7 +52,7 @@ class DBTraceObjectValueWriteBehindCache { } private void workLoop() { - while (!manager.trace.isClosed()) { + while (!manager.trace.isClosing()) { try { synchronized (cachedValues) { if (cachedValues.isEmpty()) { @@ -69,7 +70,7 @@ class DBTraceObjectValueWriteBehindCache { cachedValues.wait(left); } } - if (manager.trace.isClosed()) { + if (manager.trace.isClosing()) { break; } writeBatch(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/CreateThunkFunctionCmd.java b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/CreateThunkFunctionCmd.java index 52ea98aa69..28ca122bb1 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/CreateThunkFunctionCmd.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/cmd/function/CreateThunkFunctionCmd.java @@ -669,10 +669,12 @@ public class CreateThunkFunctionCmd extends BackgroundCommand { } /** - * Handle conversion of label within reserved EXTERNAL block to a real - * external function which can be thunked. This may be necessary when a - * loaded symbol failed to identify itself as a function. This will - * only handle single symbols contained within the global namespace. + * Facilitates conversion of a global label within the reserved EXTERNAL block to an + * external function which can be thunked. This may be necessary when a loaded symbol + * failed to identify itself as a function. + *

+ * NOTE: If a suitable External symbol is found or created the original symbol for the + * thunk function will be removed. * * @param program the program * @param entry function being created @@ -696,10 +698,29 @@ public class CreateThunkFunctionCmd extends BackgroundCommand { } try { ExternalManager extMgr = program.getExternalManager(); - ExternalLocation extLoc = - extMgr.addExtFunction(Library.UNKNOWN, s.getName(), null, s.getSource()); + + Symbol externalSymbol = null; + for (Symbol symbol : symbolTable.getSymbols(s.getName())) { + // Only consider external symbols directly in a Library root Namespace + if (!symbol.isExternal() || !symbol.getParentNamespace().isLibrary()) { + continue; + } + if (externalSymbol != null) { + // multiple ambiguous external symbols - can't decide + return null; + } + externalSymbol = symbol; + } + + if (externalSymbol == null) { + ExternalLocation extLoc = + extMgr.addExtFunction(Library.UNKNOWN, s.getName(), null, s.getSource()); + externalSymbol = extLoc.getSymbol(); + } + s.delete(); // remove original symbol from EXTERNAL block - return extLoc.getExternalSpaceAddress(); + + return externalSymbol.getAddress(); } catch (DuplicateNameException | InvalidInputException e) { // ignore - unexpected diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AddressRangeTableModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AddressRangeTableModel.java index 70b892d306..9bf1f6281d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AddressRangeTableModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/AddressRangeTableModel.java @@ -20,6 +20,7 @@ import java.util.stream.StreamSupport; import docking.widgets.table.AbstractDynamicTableColumn; import docking.widgets.table.TableColumnDescriptor; import ghidra.docking.settings.Settings; +import ghidra.framework.options.ToolOptions; import ghidra.framework.plugintool.PluginTool; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.model.address.*; @@ -43,20 +44,23 @@ public class AddressRangeTableModel extends GhidraProgramTableModel accumulator, TaskMonitor monitor) throws CancelledException { + ToolOptions options = tool.getOptions(CodeBrowserSelectionPlugin.OPTION_CATEGORY_NAME); + int resultsLimit = options.getInt(CodeBrowserSelectionPlugin.RANGES_LIMIT_OPTION_NAME, + CodeBrowserSelectionPlugin.RANGES_LIMIT_DEFAULT); + long minLength = options.getLong(CodeBrowserSelectionPlugin.MIN_RANGE_SIZE_OPTION_NAME, + CodeBrowserSelectionPlugin.MIN_RANGE_SIZE_DEFAULT); + AddressRangeIterator rangeIter = selection.getAddressRanges(); ReferenceManager refManager = program.getReferenceManager(); while (rangeIter.hasNext()) { @@ -103,11 +107,6 @@ public class AddressRangeTableModel extends GhidraProgramTableModel createTableColumnDescriptor() { TableColumnDescriptor descriptor = new TableColumnDescriptor<>(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserSelectionPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserSelectionPlugin.java index 2969d7c541..33eba0a28c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserSelectionPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/codebrowser/CodeBrowserSelectionPlugin.java @@ -151,11 +151,8 @@ public class CodeBrowserSelectionPlugin extends Plugin { tool.setStatusInfo("Unable to create selected ranges table: no addresses in selection"); return; } - ToolOptions options = tool.getOptions(OPTION_CATEGORY_NAME); - int resultsLimit = options.getInt(RANGES_LIMIT_OPTION_NAME, RANGES_LIMIT_DEFAULT); - long minLength = options.getLong(MIN_RANGE_SIZE_OPTION_NAME, MIN_RANGE_SIZE_DEFAULT); - AddressRangeTableModel model = - new AddressRangeTableModel(tool, program, selection, resultsLimit, minLength); + + AddressRangeTableModel model = new AddressRangeTableModel(tool, program, selection); Icon markerIcon = new GIcon("icon.plugin.codebrowser.cursor.marker"); String title = "Selected Ranges in " + program.getName(); TableComponentProvider tableProvider = diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/OperandFieldHelper.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/OperandFieldHelper.java index 09a5c63635..932603aca3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/OperandFieldHelper.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/OperandFieldHelper.java @@ -449,9 +449,6 @@ abstract class OperandFieldHelper extends FieldFactory { private ListingField getFieldForInstruction(Instruction inst, ProxyObj proxy, int varWidth) { int numOperands = inst.getNumOperands(); - if (numOperands == 0) { - return null; - } OpFieldResults results = new OpFieldResults(proxy); OperandFieldElement separator = createLeadingSeparatorElement(inst); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java index 301d84edbb..6e3ae287be 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/SymbolicPropogator.java @@ -450,7 +450,7 @@ public class SymbolicPropogator { this.destination = destination; this.pcodeIndex = pcodeIndex; this.continueAfterHittingFlow = continueAfterHittingFlow; - vContext.pushMemState(); + vContext.pushMemState(pcodeIndex != 0); } public boolean isContinueAfterHittingFlow() { @@ -484,6 +484,9 @@ public class SymbolicPropogator { throws CancelledException { visitedBody = new AddressSet(); AddressSet conflicts = new AddressSet(); + + // Locations that were jump and are now call targets and might be on saved future flows + HashSet

doNotFlowTo = new HashSet<>(); // prime the context stack with the entry point address Stack contextStack = new Stack<>(); @@ -536,6 +539,11 @@ public class SymbolicPropogator { } } } + + // don't follow flow if on list of jump targets that were turned into calls + if (doNotFlowTo.contains(nextAddr)) { + continue; + } HashSet
visitSet = visitedMap.get(nextAddr); if (visitSet != null) { @@ -636,6 +644,9 @@ public class SymbolicPropogator { Address targets[] = getInstructionFlows(instr); for (Address target : targets) { handleFunctionSideEffects(instr, target, monitor); + // a jump target has already been pushed as a future flow trace + // need to make sure values aren't propagated into the call targets + doNotFlowTo.add(target); } } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java index ec972ea291..69bbd150c0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/program/util/VarnodeContext.java @@ -36,6 +36,7 @@ import ghidra.program.model.scalar.Scalar; import ghidra.program.model.symbol.Reference; import ghidra.program.model.symbol.ReferenceIterator; import ghidra.util.Msg; +import ghidra.util.datastruct.FixedSizeHashMap; import ghidra.util.exception.AssertException; import ghidra.util.exception.DuplicateNameException; @@ -76,8 +77,16 @@ public class VarnodeContext implements ProcessorContext { // temp values for individual instruction computation before being merged into // the end flow state for an instruction private HashMap tempVals = new HashMap<>(); - protected HashMap tempUniqueVals = new HashMap<>(); + protected HashMap tempUniqueVals; protected boolean keepTempUniqueValues = false; + + // During tracing of paths, unique values need to be stored if the language has crossbuilds. + // MaxCrossBuilds is the general number of uniques with values that should be stored in the cache. + // The maxUniqueBytes is the number of actual entries (bytes) in the cache to keep. This is based + // on the size of a pointer, which is in general the size of a register. This is not intended + // to support general computation of values, and is more geared to 32/64 bit contstants and pointers. + private static final int MaxCrossBuilds = 200; // maximum instructions worth of uniques + private int maxUniqueBytes = 0; // number of bytes worth of uniques to keep // Values that must be cleared from final instruction flow state protected HashSet clearVals = new HashSet<>(); @@ -158,7 +167,10 @@ public class VarnodeContext implements ProcessorContext { memoryVals.push(new HashMap()); regVals.push((new HashMap())); - uniqueVals.push(new HashMap()); + + maxUniqueBytes = MaxCrossBuilds * program.getDefaultPointerSize(); + tempUniqueVals = new HashMap(); + uniqueVals.push(new FixedSizeHashMap(maxUniqueBytes)); setupValidSymbolicStackNames(program); @@ -169,6 +181,9 @@ public class VarnodeContext implements ProcessorContext { if (language instanceof SleighLanguage) { // Must preserve temp values if named pcode sections exist (i.e., cross-builds are used) keepTempUniqueValues = ((SleighLanguage) language).numSections() != 0; + if (keepTempUniqueValues) { + tempUniqueVals = new FixedSizeHashMap(maxUniqueBytes); + } } } @@ -419,9 +434,13 @@ public class VarnodeContext implements ProcessorContext { Varnode rvnode = null; if (varnode.isUnique()) { rvnode = getMemoryValue(tempUniqueVals,varnode,signed); - if (rvnode == null && keepTempUniqueValues) { - rvnode = getMemoryValue(uniqueVals,0,varnode,signed); - } + // TODO: if doing full cross build tracking, need to + // look back at uniqueVals stack. For now, + // since any cross builds are flushed on branches + // just use tempUniqueVals + // if (rvnode == null && keepTempUniqueValues) { + // rvnode = getMemoryValue(uniqueVals,0,varnode,signed); + //} } else { rvnode = getMemoryValue(tempVals, varnode, signed); @@ -1029,9 +1048,13 @@ public class VarnodeContext implements ProcessorContext { // merge tempvals to top of regVals regVals.peek().putAll(tempVals); - if (keepTempUniqueValues) { - uniqueVals.peek().putAll(tempUniqueVals); - } + // TODO: if doing full cross build tracking, need to + // save tmpuniques into uniqueVals. For now, + // since any cross builds are flushed on branches + // just use tempUniqueVals + //if (keepTempUniqueValues) { + // uniqueVals.peek().putAll(tempUniqueVals); + //} if (clearContext) { if (!keepTempUniqueValues) { @@ -1971,18 +1994,33 @@ public class VarnodeContext implements ProcessorContext { /** * Save the current memory state + * @param saveTempUniques - if internal branching, must save the tempUniques as well + * Note: currently unique values do not survive in the sleigh parser for crossbuild + * lookback if any branch is taken. In the future crossbuilds may be path based. + * This will need to be re-worked and the unique value state treated as other path + * tracing and stored in uniqueVals. */ - public void pushMemState() { + public void pushMemState(boolean saveTempUniques) { Stack> newRegValsTrace = (Stack>) regVals.clone(); regTraces.push(newRegValsTrace); regVals.push(new HashMap()); -// TODO: only save if need to Stack> newUniqueValsTrace = (Stack>) uniqueVals.clone(); uniqueTraces.push(newUniqueValsTrace); - uniqueVals.push(new HashMap()); + FixedSizeHashMap uniqueValsState = new FixedSizeHashMap(maxUniqueBytes); + // if pushing state for internal branching, must save unique state for restored path + // For now, only put temp unique values if internally branching. + // Note: saved tempUniqueVals are stored at the top of the trace stack, this is different than + // than other trace stacks, as those trace stacks, the top of the stack is the current + // state and the older stack entries are existing old states before a branch occurred. + if (saveTempUniques) { + newUniqueValsTrace.push((HashMap) tempUniqueVals.clone()); + } else { + newUniqueValsTrace.push(new FixedSizeHashMap<>(maxUniqueBytes)); + } + uniqueVals.push(uniqueValsState); Stack> newMemValsTrace = (Stack>) memoryVals.clone(); @@ -1999,9 +2037,14 @@ public class VarnodeContext implements ProcessorContext { public void popMemState() { regVals = regTraces.pop(); memoryVals = memTraces.pop(); - -// TODO: only save if need to + + // restore old temp values if any was saved + tempUniqueVals = uniqueTraces.peek().peek(); uniqueVals = uniqueTraces.pop(); + if (tempUniqueVals == null) { + // if no tempUnique values stored for this path + tempUniqueVals = new FixedSizeHashMap<>(maxUniqueBytes); + } lastSet = lastSetSaves.pop(); diff --git a/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/data/TransactionLockingTest.java b/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/data/TransactionLockingTest.java index b751a7e0a7..ea826a49ed 100644 --- a/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/data/TransactionLockingTest.java +++ b/Ghidra/Features/Base/src/test.slow/java/ghidra/framework/data/TransactionLockingTest.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIGccClassRecoverer.java b/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIGccClassRecoverer.java index f24230306d..b2f8764c48 100644 --- a/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIGccClassRecoverer.java +++ b/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIGccClassRecoverer.java @@ -25,8 +25,7 @@ import ghidra.app.cmd.label.DemanglerCmd; import ghidra.app.plugin.core.analysis.ReferenceAddressPair; import ghidra.app.util.NamespaceUtils; import ghidra.app.util.PseudoDisassembler; -import ghidra.app.util.demangler.DemangledObject; -import ghidra.app.util.demangler.DemanglerUtil; +import ghidra.app.util.demangler.*; import ghidra.framework.plugintool.ServiceProvider; import ghidra.program.flatapi.FlatProgramAPI; import ghidra.program.model.address.*; @@ -2859,7 +2858,7 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer { } mangledLabel = "_ZTS" + mangledLabel; - if (!isTypeinfoNameString(mangledLabel)) { + if (!isTypeinfoNameString(mangledLabel, typeinfoNameAddress)) { return null; } @@ -3029,15 +3028,27 @@ public class RTTIGccClassRecoverer extends RTTIClassRecoverer { return true; } - private boolean isTypeinfoNameString(String string) { + private boolean isTypeinfoNameString(String string, Address address) { - DemangledObject demangledObject = DemanglerUtil.demangle(string); - if (demangledObject == null) { + List demangledObjects = DemanglerUtil.demangle(program, string, address); + if (demangledObjects == null || demangledObjects.isEmpty()) { return false; } - if (demangledObject.getName().equals("typeinfo-name")) { - return true; + for (DemangledObject demangledObject : demangledObjects) { + + DemanglerOptions options = demangledObject.getMangledContext().getOptions(); + + // Currently no good way to do this since this is in Decompiler package and GnuDemangler + // is in its own package. Once no longer a script but an analyzer in Base, update to + // do !(options instanceof GnuDemanglerOptions) + if (!options.toString().contains("gnu")) { + continue; + } + + if (demangledObject.getName().equals("typeinfo-name")) { + return true; + } } return false; } diff --git a/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIWindowsClassRecoverer.java b/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIWindowsClassRecoverer.java index d775f045d0..31e5776379 100644 --- a/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIWindowsClassRecoverer.java +++ b/Ghidra/Features/Decompiler/ghidra_scripts/classrecovery/RTTIWindowsClassRecoverer.java @@ -1516,6 +1516,9 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer { highFunction, recoveredClass, constructor, vbtableOffset); if (vbtableAddress != null) { + if (isInvalidVbtable(vbtableAddress)) { + continue; + } return vbtableAddress; } } @@ -1541,6 +1544,9 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer { highFunction, recoveredClass, constructor, vbtableOffset); if (vbtableAddress != null) { + if (isInvalidVbtable(vbtableAddress)) { + continue; + } return vbtableAddress; } } @@ -1549,6 +1555,33 @@ public class RTTIWindowsClassRecoverer extends RTTIClassRecoverer { } + private boolean isInvalidVbtable(Address address) { + + // check to see if already has a non-default symbol that is not vbtable + Symbol symbol = program.getSymbolTable().getPrimarySymbol(address); + if (symbol.getSource() != SourceType.DEFAULT && + !symbol.getName().contains("vbtable")) { + return true; + } + + // check to see if table contains an address reference + // if it is an address then is very unlikely this is a vbtable since + // it needs offset values and most are either large negatives (FFFFF....) or small offsets + // both of which are not valid addresses in a normal PE binary + Address referencedAddress = extendedFlatAPI.getPointer(address); + + // if null then not an address so possibly valid + if (referencedAddress == null) { + return false; + } + // if is program memory location then invalid + if (program.getMemory().contains(referencedAddress)) { + return true; + } + return false; + + } + /** * Method to find the address of the vbtable referenced at the given offset in the given function * @param fillStructHelper a reusable {@link FillOutStructureHelper} instance to be used diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/CreateTypeDescriptorBackgroundCmd.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/CreateTypeDescriptorBackgroundCmd.java index f6a92889e2..99b1d35efe 100644 --- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/CreateTypeDescriptorBackgroundCmd.java +++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/CreateTypeDescriptorBackgroundCmd.java @@ -22,10 +22,10 @@ import ghidra.program.model.address.Address; import ghidra.program.model.data.*; import ghidra.program.model.listing.*; import ghidra.program.model.symbol.Namespace; +import ghidra.program.model.symbol.SourceType; import ghidra.program.model.util.CodeUnitInsertionException; import ghidra.util.Msg; -import ghidra.util.exception.CancelledException; -import ghidra.util.exception.InvalidInputException; +import ghidra.util.exception.*; /** * This command will create a TypeDescriptor data type. Since unsized arrays are not properly @@ -133,8 +133,10 @@ public class CreateTypeDescriptorBackgroundCmd Program program = model.getProgram(); String demangledName = model.getDemangledTypeDescriptor(); + + // if cannot demangle then use the mangled name if (demangledName == null) { - return false; + demangledName = model.getOriginalTypename(); } String prefix = demangledName + " "; @@ -147,9 +149,25 @@ public class CreateTypeDescriptorBackgroundCmd // Label Namespace classNamespace = model.getDescriptorAsNamespace(); - if (classNamespace == null) { - Msg.error(RttiUtil.class, "Cannot get namespace from model " + model.getAddress()); - return false; + // if cannot demangle then use the mangled name as the namespace + if (classNamespace == null || classNamespace.isGlobal()) { + Msg.error(RttiUtil.class, "Cannot get demangled namespace from model " + + model.getAddress() + " so will use the mangled name for the namespace"); + try { + classNamespace = program.getSymbolTable() + .getOrCreateNameSpace(program.getGlobalNamespace(), demangledName, + SourceType.IMPORTED); + } + catch (DuplicateNameException e) { + // ok if it is duplicate as it was likely created in another rtti handling method + } + catch (InvalidInputException e) { + Msg.error(TypeDescriptorModel.class, + "Failed to create mangled namespace: " + e.getMessage()); + classNamespace = null; + return false; + } + } // If PDB had been run, then the namespace here might already have been promoted to diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java index 9264228616..c99805ad24 100644 --- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java +++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/TypeDescriptorModel.java @@ -28,11 +28,9 @@ import ghidra.program.model.listing.Program; import ghidra.program.model.mem.DumbMemBufferImpl; import ghidra.program.model.mem.Memory; import ghidra.program.model.scalar.Scalar; -import ghidra.program.model.symbol.Namespace; -import ghidra.program.model.symbol.Symbol; +import ghidra.program.model.symbol.*; import ghidra.util.Msg; -import ghidra.util.exception.AssertException; -import ghidra.util.exception.CancelledException; +import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; /** @@ -473,6 +471,10 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel { return hasComplexType() ? demangledDataType.getOriginalDemangled() : null; } + public String getOriginalTypename() { + return originalTypeName; + } + /** * Gets just the name of the type descriptor. * @return the name of the thing referred to by this descriptor, or null if it couldn't @@ -583,6 +585,23 @@ public class TypeDescriptorModel extends AbstractCreateDataTypeModel { Program program = getProgram(); namespace = DemangledObject.createNamespace(program, demangledDataType, program.getGlobalNamespace(), false); + + // if for some reason the mangled name can't be demangled, use the mangled name + if (namespace.isGlobal()) { + try { + namespace = program.getSymbolTable() + .getOrCreateNameSpace(program.getGlobalNamespace(), originalTypeName, + SourceType.IMPORTED); + } + catch (DuplicateNameException e) { + // ok if it is duplicate as it was likely created in another rtti handling method + } + catch (InvalidInputException e) { + Msg.error(TypeDescriptorModel.class, + "Failed to create namespace: " + e.getMessage()); + namespace = null; + } + } return namespace; } diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/CreateVfTableBackgroundCmd.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/CreateVfTableBackgroundCmd.java index f45a80ce46..1d1d351c5a 100644 --- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/CreateVfTableBackgroundCmd.java +++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/CreateVfTableBackgroundCmd.java @@ -119,7 +119,7 @@ public class CreateVfTableBackgroundCmd extends AbstractCreateDataBackgroundCmd< String demangledTypeDescriptor = rtti0Model.getDemangledTypeDescriptor(); String prefixString = ((demangledTypeDescriptor != null) ? (demangledTypeDescriptor + Namespace.DELIMITER) - : ""); + : rtti0Model.getOriginalTypename() + Namespace.DELIMITER); data.setComment(CommentType.EOL, "terminator for " + prefixString + VF_TABLE_LABEL); return true; } diff --git a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/RttiUtil.java b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/RttiUtil.java index cbfb24b266..2584b88629 100644 --- a/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/RttiUtil.java +++ b/Ghidra/Features/MicrosoftCodeAnalyzer/src/main/java/ghidra/app/cmd/data/rtti/RttiUtil.java @@ -23,8 +23,10 @@ import ghidra.app.cmd.data.TypeDescriptorModel; import ghidra.app.util.NamespaceUtils; import ghidra.app.util.PseudoDisassembler; import ghidra.app.util.datatype.microsoft.MSDataTypeUtils; +import ghidra.app.util.demangler.DemangledException; import ghidra.app.util.demangler.DemangledObject; -import ghidra.app.util.demangler.DemanglerUtil; +import ghidra.app.util.demangler.microsoft.MicrosoftDemangler; +import ghidra.app.util.demangler.microsoft.MicrosoftMangledContext; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSetView; import ghidra.program.model.listing.*; @@ -82,16 +84,22 @@ public class RttiUtil { } // check for similar symbol + MicrosoftDemangler demangler = new MicrosoftDemangler(); DemangledObject matchingDemangledObject = null; SymbolIterator symbols = symbolTable.getSymbolsAsIterator(rttiAddress); for (Symbol symbol : symbols) { String name = symbol.getName(); - - // if mangled get the matching demangled object if there is one and save for after loop - // in case symbols are not demangled yet - DemangledObject demangledObject = DemanglerUtil.demangle(name); - if (demangledObject != null && demangledObject.getName().contains(rttiSuffix)) { - matchingDemangledObject = demangledObject; + try { + MicrosoftMangledContext mangledContext = + demangler.createMangledContext(name, null, program, symbol.getAddress()); + DemangledObject demangledObject = demangler.demangle(mangledContext); + if (demangledObject != null && demangledObject.getName().contains(rttiSuffix)) { + matchingDemangledObject = demangledObject; + continue; + } + } + catch (DemangledException e) { + // Couldn't demangle. continue; } @@ -313,7 +321,11 @@ public class RttiUtil { public static String getDescriptorTypeNamespace(TypeDescriptorModel rtti0Model) { String descriptorTypeNamespace = rtti0Model.getDescriptorTypeNamespace(); // Can be null. if (descriptorTypeNamespace == null) { - descriptorTypeNamespace = ""; // Couldn't get namespace so leave it off. + + descriptorTypeNamespace = rtti0Model.getOriginalTypename(); + + Msg.warn(RttiUtil.class, rtti0Model.getAddress().toString() + + ": Could not demangle TypeDescriptor namespace so using the mangled string as the namespace."); } return descriptorTypeNamespace; } diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/bkmk/SarifBookmarkWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/bkmk/SarifBookmarkWriter.java index dc8164fde6..20e9383338 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/bkmk/SarifBookmarkWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/bkmk/SarifBookmarkWriter.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -45,6 +45,7 @@ public class SarifBookmarkWriter extends AbstractExtWriter { private void genBookmarks(TaskMonitor monitor) throws CancelledException, IOException{ monitor.initialize(bookmarks.size()); for (Bookmark b : bookmarks) { + monitor.checkCancelled(); ExtBookmark isf = new ExtBookmark(b); SarifObject sarif = new SarifObject(BookmarksSarifMgr.SUBKEY, BookmarksSarifMgr.KEY, getTree(isf), b.getAddress(), b.getAddress()); objects.add(getTree(sarif)); diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/code/SarifCodeWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/code/SarifCodeWriter.java index 934fda3077..4bf552f9a3 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/code/SarifCodeWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/code/SarifCodeWriter.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -50,6 +50,7 @@ public class SarifCodeWriter extends AbstractExtWriter { private void genCode(TaskMonitor monitor) throws CancelledException, IOException{ monitor.initialize(blocks.size()); for (AddressRange range : blocks) { + monitor.checkCancelled(); ExtCodeBlock isf = new ExtCodeBlock(range); SarifObject sarif = new SarifObject(CodeSarifMgr.SUBKEY, CodeSarifMgr.KEY, getTree(isf), range.getMinAddress(), range.getMaxAddress()); objects.add(getTree(sarif)); diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/comments/SarifCommentWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/comments/SarifCommentWriter.java index 8655226cce..f30ce4033b 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/comments/SarifCommentWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/comments/SarifCommentWriter.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -56,6 +56,7 @@ public class SarifCommentWriter extends AbstractExtWriter { } monitor.initialize(comments0.size()); for (Pair> pair : comments0) { + monitor.checkCancelled(); CodeUnit cu = pair.first; ExtComment isf = new ExtComment(pair.second, true); SarifObject sarif = new SarifObject(CommentsSarifMgr.SUBKEY, CommentsSarifMgr.KEY, getTree(isf), cu.getMinAddress(), diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/dd/SarifDataWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/dd/SarifDataWriter.java index 1a592b6144..67aff5ce90 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/dd/SarifDataWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/dd/SarifDataWriter.java @@ -45,6 +45,7 @@ public class SarifDataWriter extends AbstractExtWriter { private void genData(TaskMonitor monitor) throws CancelledException { monitor.initialize(definedData.size()); for (Data d : definedData) { + monitor.checkCancelled(); ExtData isf = new ExtData(d); SarifObject sarif = new SarifObject("DefinedData", DefinedDataSarifMgr.KEY, getTree(isf), d.getMinAddress(), d.getMaxAddress()); diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/ep/SarifEntryPointWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/ep/SarifEntryPointWriter.java index 9d967a065b..f2660652f4 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/ep/SarifEntryPointWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/ep/SarifEntryPointWriter.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -44,6 +44,7 @@ public class SarifEntryPointWriter extends AbstractExtWriter { private void genCode(TaskMonitor monitor) throws CancelledException, IOException{ monitor.initialize(entryPoints.size()); for (Address addr : entryPoints) { + monitor.checkCancelled(); ExtEntryPoint isf = new ExtEntryPoint(addr); SarifObject sarif = new SarifObject(ExtEntryPointSarifMgr.SUBKEY, ExtEntryPointSarifMgr.KEY, getTree(isf), addr, addr); objects.add(getTree(sarif)); diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/equates/SarifEquateWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/equates/SarifEquateWriter.java index 989534d888..3398d156cd 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/equates/SarifEquateWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/equates/SarifEquateWriter.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -44,6 +44,7 @@ public class SarifEquateWriter extends AbstractExtWriter { private void genCode(TaskMonitor monitor) throws CancelledException, IOException{ monitor.initialize(equates.size()); for (Equate equate : equates) { + monitor.checkCancelled(); ExtEquate isf = new ExtEquate(equate); SarifObject sarif = new SarifObject(EquatesSarifMgr.SUBKEY, EquatesSarifMgr.KEY, getTree(isf), null); objects.add(getTree(sarif)); diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/extlib/SarifClassesNamespaceWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/extlib/SarifClassesNamespaceWriter.java index b52171ebff..e331b35d8b 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/extlib/SarifClassesNamespaceWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/extlib/SarifClassesNamespaceWriter.java @@ -53,6 +53,7 @@ public class SarifClassesNamespaceWriter extends AbstractExtWriter { monitor.initialize(classes.size()); Iterator classNamespaces = symbolTable.getClassNamespaces(); while (classNamespaces.hasNext()) { + monitor.checkCancelled(); GhidraClass next = classNamespaces.next(); walkSymbols(next); monitor.increment(); diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/extlib/SarifExternalLibraryWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/extlib/SarifExternalLibraryWriter.java index 7e902e05ab..2ba1dc8ad7 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/extlib/SarifExternalLibraryWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/extlib/SarifExternalLibraryWriter.java @@ -22,10 +22,7 @@ import java.util.List; import com.google.gson.JsonArray; -import ghidra.program.model.symbol.ExternalLocation; -import ghidra.program.model.symbol.ExternalLocationIterator; -import ghidra.program.model.symbol.ExternalManager; -import ghidra.program.model.symbol.SourceType; +import ghidra.program.model.symbol.*; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; import sarif.export.AbstractExtWriter; @@ -53,6 +50,7 @@ public class SarifExternalLibraryWriter extends AbstractExtWriter { private void genLibraries(TaskMonitor monitor) throws CancelledException, IOException { monitor.initialize(externalNames.size()); for (String n : externalNames) { + monitor.checkCancelled(); String path = externalManager.getExternalLibraryPath(n); if (path == null) { path = ""; @@ -63,6 +61,7 @@ public class SarifExternalLibraryWriter extends AbstractExtWriter { ExternalLocationIterator externalLocations = externalManager.getExternalLocations(n); while (externalLocations.hasNext()) { + monitor.checkCancelled(); ExternalLocation loc = externalLocations.next(); ExtLibraryLocation obj = new ExtLibraryLocation(loc); SarifObject sarif2 = new SarifObject(ExternalLibSarifMgr.SUBKEY1, ExternalLibSarifMgr.KEY, getTree(obj), loc.getAddress(), loc.getAddress()); diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/func/SarifFunctionWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/func/SarifFunctionWriter.java index 33ec4601e0..17196bda32 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/func/SarifFunctionWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/func/SarifFunctionWriter.java @@ -56,6 +56,7 @@ public class SarifFunctionWriter extends AbstractExtWriter { private void genFunctions(TaskMonitor monitor) throws CancelledException, IOException{ monitor.initialize(requestedFunctions.size()); for (Function f : requestedFunctions) { + monitor.checkCancelled(); addSymbol(f.getSymbol()); ExtFunction isf = new ExtFunction(f, monitor); SarifObject sarif = new SarifObject("Function", FunctionsSarifMgr.KEY, getTree(isf), f.getBody()); diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/mm/SarifMemoryMapWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/mm/SarifMemoryMapWriter.java index eb92676bce..173c86512f 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/mm/SarifMemoryMapWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/mm/SarifMemoryMapWriter.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -52,6 +52,7 @@ public class SarifMemoryMapWriter extends AbstractExtWriter { private void genMaps(TaskMonitor monitor) throws CancelledException, IOException { monitor.initialize(memory.size()); for (Pair m : memory) { + monitor.checkCancelled(); AddressRange range = m.first; ExtMemoryMap isf = new ExtMemoryMap(m.first, m.second, bytesFile, write); SarifObject sarif = new SarifObject(MemoryMapSarifMgr.SUBKEY, MemoryMapSarifMgr.KEY, getTree(isf), diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/props/SarifPropertyListWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/props/SarifPropertyListWriter.java index f565866fb8..acf86222a7 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/props/SarifPropertyListWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/props/SarifPropertyListWriter.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -52,9 +52,7 @@ public class SarifPropertyListWriter extends AbstractExtWriter { List propNames = propList.getOptionNames(); Collections.sort(propNames); for (String name : propNames) { - if (monitor.isCancelled()) { - throw new CancelledException(); - } + monitor.checkCancelled(); if (propList.isAlias(name)) { // don't write out properties that are just mirrors of some other property continue; } diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/props/SarifPropertyMapWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/props/SarifPropertyMapWriter.java index d040498992..506bdda1af 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/props/SarifPropertyMapWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/props/SarifPropertyMapWriter.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,16 +19,9 @@ import java.io.IOException; import java.io.Writer; import java.util.List; -import ghidra.program.model.address.Address; -import ghidra.program.model.address.AddressIterator; -import ghidra.program.model.address.AddressSetView; +import ghidra.program.model.address.*; import ghidra.program.model.listing.Program; -import ghidra.program.model.util.IntPropertyMap; -import ghidra.program.model.util.LongPropertyMap; -import ghidra.program.model.util.ObjectPropertyMap; -import ghidra.program.model.util.PropertyMap; -import ghidra.program.model.util.StringPropertyMap; -import ghidra.program.model.util.VoidPropertyMap; +import ghidra.program.model.util.*; import ghidra.util.SaveableColor; import ghidra.util.SaveablePoint; import ghidra.util.exception.CancelledException; @@ -78,6 +71,7 @@ public class SarifPropertyMapWriter extends AbstractExtWriter { private void genVoidMap(VoidPropertyMap map, TaskMonitor monitor) throws CancelledException { AddressIterator iter = set != null ? map.getPropertyIterator(set) : map.getPropertyIterator(); while (iter.hasNext()) { + monitor.checkCancelled(); Address addr = iter.next(); ExtProperty isf = new ExtProperty(map.getName(), "void", null); SarifObject sarif = new SarifObject(PropertiesSarifMgr.SUBKEY, PropertiesSarifMgr.KEY, getTree(isf), addr, @@ -90,9 +84,7 @@ public class SarifPropertyMapWriter extends AbstractExtWriter { private void genIntMap(IntPropertyMap map, TaskMonitor monitor) throws CancelledException { AddressIterator iter = set != null ? map.getPropertyIterator(set) : map.getPropertyIterator(); while (iter.hasNext()) { - if (monitor.isCancelled()) { - throw new CancelledException(); - } + monitor.checkCancelled(); try { Address addr = iter.next(); int value = map.getInt(addr); @@ -109,9 +101,7 @@ public class SarifPropertyMapWriter extends AbstractExtWriter { private void genLongMap(LongPropertyMap map, TaskMonitor monitor) throws CancelledException { AddressIterator iter = set != null ? map.getPropertyIterator(set) : map.getPropertyIterator(); while (iter.hasNext()) { - if (monitor.isCancelled()) { - throw new CancelledException(); - } + monitor.checkCancelled(); try { Address addr = iter.next(); long value = map.getLong(addr); @@ -129,9 +119,7 @@ public class SarifPropertyMapWriter extends AbstractExtWriter { private void genStringMap(StringPropertyMap map, TaskMonitor monitor) throws CancelledException { AddressIterator iter = set != null ? map.getPropertyIterator(set) : map.getPropertyIterator(); while (iter.hasNext()) { - if (monitor.isCancelled()) { - throw new CancelledException(); - } + monitor.checkCancelled(); Address addr = iter.next(); String value = map.getString(addr); ExtProperty isf = new ExtProperty(map.getName(), "string", value); @@ -145,9 +133,7 @@ public class SarifPropertyMapWriter extends AbstractExtWriter { private void genObjectMap(ObjectPropertyMap map, TaskMonitor monitor) throws CancelledException { AddressIterator iter = set != null ? map.getPropertyIterator(set) : map.getPropertyIterator(); while (iter.hasNext()) { - if (monitor.isCancelled()) { - throw new CancelledException(); - } + monitor.checkCancelled(); Address addr = iter.next(); Object value = map.get(addr); ExtProperty isf; diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/ref/SarifEquateRefWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/ref/SarifEquateRefWriter.java index 7b97c0f7aa..aa40003757 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/ref/SarifEquateRefWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/ref/SarifEquateRefWriter.java @@ -23,9 +23,7 @@ import com.google.gson.JsonArray; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSetView; -import ghidra.program.model.symbol.Equate; -import ghidra.program.model.symbol.EquateReference; -import ghidra.program.model.symbol.EquateTable; +import ghidra.program.model.symbol.*; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; import sarif.export.AbstractExtWriter; @@ -52,17 +50,12 @@ public class SarifEquateRefWriter extends AbstractExtWriter { Iterator iter = equateTable.getEquates(); while (iter.hasNext()) { - if (monitor.isCancelled()) { - throw new CancelledException(); - } Equate equate = iter.next(); String name = equate.getName(); long value = equate.getValue(); EquateReference[] refs = equate.getReferences(); for (int i = 0; i < refs.length; i++) { - if (monitor.isCancelled()) { - return; - } + monitor.checkCancelled(); Address addr = refs[i].getAddress(); if (!set.contains(addr)) { continue; diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/ref/SarifEquateWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/ref/SarifEquateWriter.java index 0c45cd8c94..10ef049d42 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/ref/SarifEquateWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/ref/SarifEquateWriter.java @@ -23,9 +23,7 @@ import com.google.gson.JsonArray; import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSetView; -import ghidra.program.model.symbol.Equate; -import ghidra.program.model.symbol.EquateReference; -import ghidra.program.model.symbol.EquateTable; +import ghidra.program.model.symbol.*; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; import sarif.export.AbstractExtWriter; @@ -60,9 +58,7 @@ public class SarifEquateWriter extends AbstractExtWriter { long value = equate.getValue(); EquateReference[] refs = equate.getReferences(); for (int i = 0; i < refs.length; i++) { - if (monitor.isCancelled()) { - return; - } + monitor.checkCancelled(); Address addr = refs[i].getAddress(); if (!set.contains(addr)) { continue; diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/ref/SarifReferenceWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/ref/SarifReferenceWriter.java index 63a6f5dba0..c7bb7f5d18 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/ref/SarifReferenceWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/ref/SarifReferenceWriter.java @@ -23,12 +23,7 @@ import java.util.List; import com.google.gson.JsonArray; import ghidra.program.model.address.Address; -import ghidra.program.model.symbol.ExternalLocation; -import ghidra.program.model.symbol.ExternalReference; -import ghidra.program.model.symbol.Reference; -import ghidra.program.model.symbol.ReferenceManager; -import ghidra.program.model.symbol.ShiftedReference; -import ghidra.program.model.symbol.StackReference; +import ghidra.program.model.symbol.*; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; import sarif.export.AbstractExtWriter; @@ -63,9 +58,7 @@ public class SarifReferenceWriter extends AbstractExtWriter { for (Address addr : references) { Reference[] refs = referenceManager.getReferencesFrom(addr); for (int i = 0; i < refs.length; i++) { - if (monitor.isCancelled()) { - throw new CancelledException(); - } + monitor.checkCancelled(); Reference ref = refs[i]; if (ref.isRegisterReference()) { ExtRegisterReference mref = new ExtRegisterReference(ref); diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/relocs/SarifRelocationWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/relocs/SarifRelocationWriter.java index 1e1215cb6d..7263de07ff 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/relocs/SarifRelocationWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/relocs/SarifRelocationWriter.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -44,6 +44,7 @@ public class SarifRelocationWriter extends AbstractExtWriter { private void genRelocation(TaskMonitor monitor) throws CancelledException, IOException { monitor.initialize(relocs.size()); for (Relocation r : relocs) { + monitor.checkCancelled(); ExtRelocation isf = new ExtRelocation(r); SarifObject sarif = new SarifObject(RelocationTableSarifMgr.SUBKEY, RelocationTableSarifMgr.KEY, getTree(isf), r.getAddress(), r.getAddress()); diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/symbols/SarifSymbolWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/symbols/SarifSymbolWriter.java index b044c58e36..603528d56b 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/symbols/SarifSymbolWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/symbols/SarifSymbolWriter.java @@ -22,9 +22,7 @@ import java.util.List; import com.google.gson.JsonArray; -import ghidra.program.model.symbol.SourceType; -import ghidra.program.model.symbol.Symbol; -import ghidra.program.model.symbol.SymbolType; +import ghidra.program.model.symbol.*; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; import sarif.export.AbstractExtWriter; @@ -49,6 +47,7 @@ public class SarifSymbolWriter extends AbstractExtWriter { private void genSymbols(TaskMonitor monitor) throws CancelledException, IOException{ monitor.initialize(symbols.size()); for (Symbol s : symbols) { + monitor.checkCancelled(); SymbolType symbolType = s.getSymbolType(); if (s.getSource() == SourceType.DEFAULT) { continue; diff --git a/Ghidra/Features/Sarif/src/main/java/sarif/export/trees/SarifTreeWriter.java b/Ghidra/Features/Sarif/src/main/java/sarif/export/trees/SarifTreeWriter.java index d1c4659734..783967e5ad 100644 --- a/Ghidra/Features/Sarif/src/main/java/sarif/export/trees/SarifTreeWriter.java +++ b/Ghidra/Features/Sarif/src/main/java/sarif/export/trees/SarifTreeWriter.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -47,6 +47,7 @@ public class SarifTreeWriter extends AbstractExtWriter { private void genTree(TaskMonitor monitor) throws CancelledException, IOException { monitor.initialize(modules.size()); for (Pair pair : modules) { + monitor.checkCancelled(); ExtModule isf = new ExtModule(pair.first, pair.second, visited); SarifObject sarif = new SarifObject(ProgramTreeSarifMgr.SUBKEY, ProgramTreeSarifMgr.KEY, getTree(isf), null); objects.add(getTree(sarif)); diff --git a/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java b/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java index 06a1626658..4b7b7e00bb 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/action/KeyBindingsManager.java @@ -15,6 +15,7 @@ */ package docking.action; +import java.awt.event.InputEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.*; @@ -102,6 +103,9 @@ public class KeyBindingsManager implements PropertyChangeListener { // map standard keystroke to action doAddKeyBinding(provider, action, keyStroke); + + // map workaround keystroke to action + fixupAltGraphKeyStrokeMapping(provider, action, keyStroke); } public String validateActionKeyBinding(DockingActionIf dockingAction, KeyStroke ks) { @@ -146,6 +150,24 @@ public class KeyBindingsManager implements PropertyChangeListener { doAddKeyBinding(provider, action, keyStroke, keyStroke); } + private void fixupAltGraphKeyStrokeMapping(ComponentProvider provider, DockingActionIf action, + KeyStroke keyStroke) { + + // special case + int modifiers = keyStroke.getModifiers(); + if ((modifiers & InputEvent.ALT_DOWN_MASK) == InputEvent.ALT_DOWN_MASK) { + // + // Also register the 'Alt' binding with the 'Alt Graph' mask. This fixes the but + // on Windows (https://bugs.openjdk.java.net/browse/JDK-8194873) + // that have different key codes for the left and right Alt keys. + // + modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK; + KeyStroke updateKeyStroke = + KeyStroke.getKeyStroke(keyStroke.getKeyCode(), modifiers, false); + doAddKeyBinding(provider, action, updateKeyStroke, keyStroke); + } + } + private void doAddKeyBinding(ComponentProvider provider, DockingActionIf action, KeyStroke mappingKeyStroke, KeyStroke actionKeyStroke) { diff --git a/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeReader.java b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeReader.java index a9db5d5a8c..eae40ccdd3 100644 --- a/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeReader.java +++ b/Ghidra/Framework/Gui/src/main/java/generic/theme/ThemeReader.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,6 +24,7 @@ import org.apache.commons.io.FileUtils; import ghidra.framework.Application; import ghidra.util.Msg; +import utilities.util.FileUtilities; /** * Reads Themes from a file or {@link Reader} @@ -138,6 +139,9 @@ class ThemeReader extends AbstractThemeReader { String relativePath = path.substring(indexOf, path.length()); File dir = Application.getUserSettingsDirectory(); File iconFile = new File(dir, relativePath); + if (!FileUtilities.isPathContainedWithin(dir, iconFile)) { + throw new IOException("Zip entry escapes target directory: " + relativePath); + } FileUtils.copyInputStreamToFile(is, iconFile); } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/AbstractTransactionManager.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/AbstractTransactionManager.java index 4d794d3e16..4f4b9efc94 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/AbstractTransactionManager.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/AbstractTransactionManager.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -55,31 +55,36 @@ abstract class AbstractTransactionManager { checkLockingTask(); + boolean doPrepare = false; synchronized (this) { if (getCurrentTransactionInfo() != null && !transactionTerminated) { return false; } if (lockCount == 0) { - for (DomainObjectAdapterDB domainObj : getDomainObjects()) { - if (domainObj.isChanged()) { - domainObj.prepareToSave(); - } - } + doPrepare = true; } lockReason = reason; ++lockCount; - return true; } + if (doPrepare) { + for (DomainObjectAdapterDB domainObj : getDomainObjects()) { + if (domainObj.isChanged()) { + domainObj.prepareToSave(); + } + } + } + return true; } /** - * Attempt to obtain a modification lock on the domain object when generating a - * background snapshot. + * Attempt to obtain a modification lock on the domain object when generating a background + * snapshot. + * * @param domainObj domain object corresponding to snapshot * @param hasProgress true if monitor has progress indicator * @param title title to be used for monitor * @return monitor object if lock obtained successfully, else null which indicates that a - * modification is in process. + * modification is in process. */ final synchronized LockingTaskMonitor lockForSnapshot(DomainObjectAdapterDB domainObj, boolean hasProgress, String title) { @@ -106,9 +111,10 @@ abstract class AbstractTransactionManager { /** * Force transaction lock and terminate current transaction. + * * @param rollback true if rollback of non-commited changes should occurs, false if commit - * should be done. NOTE: it can be potentially detrimental to commit an incomplete transaction - * and should be avoided. + * should be done. NOTE: it can be potentially detrimental to commit an incomplete + * transaction and should be avoided. * @param reason very short reason for requesting lock */ final void forceLock(boolean rollback, String reason) { @@ -131,9 +137,10 @@ abstract class AbstractTransactionManager { /** * Terminate current transaction. + * * @param rollback true if rollback of non-commited changes should occurs, false if commit - * should be done. NOTE: it can be potentially detrimental to commit an incomplete transaction - * and should be avoided. + * should be done. NOTE: it can be potentially detrimental to commit an incomplete + * transaction and should be avoided. * @param notify true for listeners to be notified else false */ abstract void terminateTransaction(boolean rollback, boolean notify); @@ -159,8 +166,7 @@ abstract class AbstractTransactionManager { } /** - * Block on active locking task. - * Do not invoke this method from within a synchronized block. + * Block on active locking task. Do not invoke this method from within a synchronized block. */ final void checkLockingTask() { synchronized (this) { @@ -173,6 +179,7 @@ abstract class AbstractTransactionManager { /** * Throw lock exception if currently locked + * * @throws DomainObjectLockedException if currently locked */ final void verifyNoLock() throws DomainObjectLockedException { @@ -194,7 +201,7 @@ abstract class AbstractTransactionManager { } } - final int startTransaction(DomainObjectAdapterDB object, String description, + final int startTransactionChecked(DomainObjectAdapterDB object, String description, AbortedTransactionListener listener, boolean notify) throws TerminatedTransactionException { @@ -222,47 +229,53 @@ abstract class AbstractTransactionManager { boolean commit, boolean notify) throws IllegalStateException; /** - * Returns the undo stack depth. - * (The number of items on the undo stack) - * This method is for JUnits. + * Returns the undo stack depth. (The number of items on the undo stack) This method is for + * JUnits. + * * @return the undo stack depth */ abstract int getUndoStackDepth(); /** * Returns true if there is at least one redo transaction to be redone. + * * @return true if there is at least one redo transaction to be redone */ abstract boolean canRedo(); /** * Returns true if there is at least one undo transaction to be undone. + * * @return true if there is at least one undo transaction to be undone */ abstract boolean canUndo(); /** * Returns the name of the next undo transaction (The most recent change). + * * @return the name of the next undo transaction (The most recent change) */ abstract String getRedoName(); /** * Returns the name of the next redo transaction (The most recent undo). + * * @return the name of the next redo transaction (The most recent undo) */ abstract String getUndoName(); /** - * Returns the names of all undoable transactions in reverse chronological order. In other - * words the transaction at the top of the list must be undone first. + * Returns the names of all undoable transactions in reverse chronological order. In other words + * the transaction at the top of the list must be undone first. + * * @return the names of all undoable transactions in reverse chronological order */ abstract List getAllUndoNames(); /** - * Returns the names of all redoable transactions in chronological order. In other words - * the transaction at the top of the list must be redone first. + * Returns the names of all redoable transactions in chronological order. In other words the + * transaction at the top of the list must be redone first. + * * @return the names of all redoable transactions in chronological order */ abstract List getAllRedoNames(); @@ -321,7 +334,7 @@ abstract class AbstractTransactionManager { abstract void doClose(DomainObjectAdapterDB object); /** - * Set instance as immutable by disabling use of transactions. Attempts to start a transaction + * Set instance as immutable by disabling use of transactions. Attempts to start a transaction * will result in a {@link TerminatedTransactionException}. */ public void setImmutable() { diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DomainObjectAdapterDB.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DomainObjectAdapterDB.java index 6a76c0d7c2..0b87dc05c1 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DomainObjectAdapterDB.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DomainObjectAdapterDB.java @@ -133,7 +133,7 @@ public abstract class DomainObjectAdapterDB extends DomainObjectAdapter implemen * using a shared transaction manager. If either or both is already shared, * a transition to a single shared transaction manager will be * performed. - * @param domainObj + * @param domainObj the domain object to synchronize with * @throws LockException if lock or open transaction is active on either * this or the specified domain object */ @@ -184,7 +184,7 @@ public abstract class DomainObjectAdapterDB extends DomainObjectAdapter implemen } /** - * Returns the open handle to the underlying database. + * {@return the open handle to the underlying database} */ public DBHandle getDBHandle() { return dbh; @@ -259,17 +259,17 @@ public abstract class DomainObjectAdapterDB extends DomainObjectAdapter implemen return transactionMgr.lock(reason); } - void prepareToSave() { - int txId = transactionMgr.startTransaction(this, "Update Metadata", null, true, true); - try { + /** + * Prepare to save and store any last minute DB data. The default behavior is to invoke + * {@link #updateMetadata()}. + */ + protected void prepareToSave() { + try (Transaction tx = openForcedTransaction("Update Metadata")) { updateMetadata(); } catch (IOException e) { dbError(e); } - finally { - transactionMgr.endTransaction(this, txId, true, true); - } } /** @@ -310,24 +310,40 @@ public abstract class DomainObjectAdapterDB extends DomainObjectAdapter implemen transactionMgr.unlock(handler); } + private class DomainObjectTransaction extends Transaction { + private final int txId; + + DomainObjectTransaction(int txId) { + this.txId = txId; + } + + @Override + protected boolean endTransaction(boolean commit) { + DomainObjectAdapterDB.this.endTransaction(txId, commit); + return commit; + } + + @Override + public boolean isSubTransaction() { + return true; + } + } + + /** + * Open forced transaction which bypasses any lock checking, although method should only be + * used in very controlled situations where a save lock is in place. + * @param description transaction description + * @return {@link AutoCloseable} transaction object + */ + protected Transaction openForcedTransaction(String description) { + int txId = transactionMgr.startTransaction(this, description, null, true, true); + return new DomainObjectTransaction(txId); + } + @Override public Transaction openTransaction(String description) throws TerminatedTransactionException, IllegalStateException { - return new Transaction() { - - int txId = startTransaction(description); - - @Override - protected boolean endTransaction(boolean commit) { - DomainObjectAdapterDB.this.endTransaction(txId, commit); - return commit; - } - - @Override - public boolean isSubTransaction() { - return true; - } - }; + return new DomainObjectTransaction(startTransaction(description)); } @Override @@ -348,7 +364,8 @@ public abstract class DomainObjectAdapterDB extends DomainObjectAdapter implemen while (true) { try { - return transactionMgr.startTransaction(this, description, listener, true); + return transactionMgr.startTransactionChecked(this, description, listener, + true); } catch (DomainObjectLockedException e) { if (!exceptionHandler.apply(e)) { diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DomainObjectTransactionManager.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DomainObjectTransactionManager.java index b4d98f16e7..d967888480 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DomainObjectTransactionManager.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/DomainObjectTransactionManager.java @@ -103,11 +103,12 @@ class DomainObjectTransactionManager extends AbstractTransactionManager { throw new IllegalArgumentException("invalid domain object"); } - if (!force) { - verifyNoLock(); - } - if (transaction == null) { + + if (!force) { + verifyNoLock(); + } + transactionTerminated = false; transaction = new DomainObjectDBTransaction(domainObj.dbh.startTransaction(), domainObj); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/GhidraFolderData.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/GhidraFolderData.java index d7685ee830..6295aaf801 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/GhidraFolderData.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/GhidraFolderData.java @@ -1037,7 +1037,7 @@ class GhidraFolderData { if (doa.isClosed()) { throw new ClosedException(); } - if (!doa.lock(null)) { + if (!doa.lock("create file")) { throw new IOException("Object is busy and can not be saved"); } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/SynchronizedTransactionManager.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/SynchronizedTransactionManager.java index 5665413f7c..5afa66dd38 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/SynchronizedTransactionManager.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/SynchronizedTransactionManager.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -152,11 +152,12 @@ class SynchronizedTransactionManager extends AbstractTransactionManager { synchronized int startTransaction(DomainObjectAdapterDB object, String description, AbortedTransactionListener listener, boolean force, boolean notify) { - if (!force) { - verifyNoLock(); - } - if (transaction == null) { + + if (!force) { + verifyNoLock(); + } + transactionTerminated = false; transaction = new SynchronizedTransaction(domainObjectTransactionManagers); int txId = transaction.addEntry(object, description, listener); diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FileActionManager.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FileActionManager.java index 4d24d55083..c98df4ac00 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FileActionManager.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/FileActionManager.java @@ -311,7 +311,7 @@ class FileActionManager { locked = false; break; } - if (!domainObjects[lastIndex].lock(null)) { + if (!domainObjects[lastIndex].lock("save changes")) { String title = "Exit Ghidra"; StringBuffer buf = new StringBuffer(); DomainObject d = domainObjects[lastIndex]; diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DomainObject.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DomainObject.java index fd0820e88f..9255d26daa 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DomainObject.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/model/DomainObject.java @@ -400,7 +400,7 @@ public interface DomainObject { * * * @param description a short description of the changes to be made. - * @return transaction object + * @return {@link AutoCloseable} transaction object * @throws IllegalStateException if this {@link DomainObject} has already been closed. */ public Transaction openTransaction(String description) throws IllegalStateException; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/PseudoDisassembler.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/PseudoDisassembler.java index 45b09b5962..5f69c6ce43 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/PseudoDisassembler.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/app/util/PseudoDisassembler.java @@ -19,6 +19,7 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.Iterator; +import ghidra.program.disassemble.Disassembler; import ghidra.program.model.address.*; import ghidra.program.model.data.DataType; import ghidra.program.model.data.PointerDataType; @@ -28,6 +29,7 @@ import ghidra.program.model.mem.*; import ghidra.program.model.pcode.PcodeOp; import ghidra.program.model.symbol.*; import ghidra.util.Msg; +import ghidra.util.task.TaskMonitor; /** * PseudoDisassembler.java @@ -71,7 +73,7 @@ public class PseudoDisassembler { private boolean respectExecuteFlag = false; - private int lastCheckValidDisassemblyCount; // number of last instructions disassembled + private int lastCheckValidDisassemblyCount; // number of last instructions disassembled in checkValidSubroutine /** * Create a pseudo disassembler for the given program. @@ -98,8 +100,11 @@ public class PseudoDisassembler { } /** - * Get the last number of disassembled instructions - * or the number of initial contiguous instruction if requireContiguous is true + * Get the last number of disassembled instructions, + * or the number of initial contiguous instruction if requireContiguous is true, + * after calls to in checkValidSubroutine() or isValidSubroutine() + * + * @return number of disassembled instructions */ public int getLastCheckValidInstructionCount() { return lastCheckValidDisassemblyCount; @@ -128,17 +133,15 @@ public class PseudoDisassembler { UnknownInstructionException, UnknownContextException { PseudoDisassemblerContext procContext = new PseudoDisassemblerContext(programContext); - - procContext.flowStart(addr); return disassemble(addr, procContext, false); } /** * Disassemble a single instruction. The program is not affected. - * @param addr - * @param disassemblerContext - * @param isInDelaySlot - * @return + * @param addr location to disassemble + * @param disassemblerContext context for disassembly + * @param isInDelaySlot true if instruction to be disassembled is in a delaySlot + * @return disassembled instruction * @throws InsufficientBytesException * @throws UnknownInstructionException * @throws UnknownContextException @@ -148,41 +151,18 @@ public class PseudoDisassembler { throws InsufficientBytesException, UnknownInstructionException, UnknownContextException { - MemBuffer memBuffer = new DumbMemBufferImpl(memory, addr); - - // check that address is defined in memory - try { - memBuffer.getByte(0); - } - catch (Exception e) { - return null; - } - - InstructionPrototype prototype = null; + addr = setTargetContextForDisassembly(disassemblerContext, addr); + RegisterValue entryContext = getTargetStartContext(addr, disassemblerContext); try { - prototype = language.parse(memBuffer, disassemblerContext, isInDelaySlot); + // Only disassemble one instruction, and always re-disassemble + // in case context has changed. + Instruction instr = pseudoDisassemble(addr, entryContext, 1, true); + return (PseudoInstruction) instr; } catch (UnknownInstructionException unknownExc) { return null; } - - if (prototype == null) { - return null; - } - - PseudoInstruction instr; - try { - instr = new PseudoInstruction(program, addr, prototype, memBuffer, disassemblerContext); - } - catch (Exception e) { - // this is here, if a prototype matches for some number of bytes, but - // the actual instruction is longer than the number of bytes needed for matching - // the prototype. And all the bytes for the instruction are not available. - return null; - } - - return instr; } /** @@ -224,34 +204,21 @@ public class PseudoDisassembler { PseudoDisassemblerContext disassemblerContext) throws InsufficientBytesException, UnknownInstructionException, UnknownContextException { + addr = setTargetContextForDisassembly(disassemblerContext, addr); + RegisterValue targetContext = getTargetStartContext(addr, disassemblerContext); + + pseudoDisassembler = Disassembler.getDisassembler(program, false, false, false, + TaskMonitor.DUMMY, msg -> { + // ignore log errors + }); + MemBuffer memBuffer = new ByteMemBufferImpl(addr, bytes, language.isBigEndian()); - - // check that address is defined in memory - try { - memBuffer.getByte(0); - } - catch (Exception e) { + InstructionBlock instrBlock = pseudoDisassembler.pseudoDisassembleBlock(memBuffer, targetContext, 1); + if (instrBlock == null) { return null; } - InstructionPrototype prototype = null; - disassemblerContext.flowStart(addr); - prototype = language.parse(memBuffer, disassemblerContext, false); - - if (prototype == null) { - return null; - } - - PseudoInstruction instr; - try { - instr = new PseudoInstruction(program, addr, prototype, memBuffer, disassemblerContext); - } - catch (AddressOverflowException e) { - throw new InsufficientBytesException( - "failed to build pseudo instruction at " + addr + ": " + e.getMessage()); - } - - return instr; + return (PseudoInstruction) instrBlock.getInstructionAt(addr); } /** @@ -265,9 +232,7 @@ public class PseudoDisassembler { * @return {@link PseudoData} that acts like Data */ public PseudoData applyDataType(Address addr, DataType dt) { - - Memory memory = program.getMemory(); - + MemBuffer memBuffer = new DumbMemBufferImpl(memory, addr); // check that address is defined in memory @@ -424,9 +389,10 @@ public class PseudoDisassembler { AddressSet body = new AddressSet(); AddressSet instrStarts = new AddressSet(); - entryPoint = setTargetContextForDisassembly(procContext, entryPoint); - Address target = entryPoint; + + entryPoint = setTargetContextForDisassembly(procContext, entryPoint); + RegisterValue entryContext = getTargetStartContext(entryPoint, procContext); ArrayList
targetList = new ArrayList<>(); // list of valid targets ArrayList
untriedTargetList = new ArrayList<>(); // list of valid targets @@ -458,17 +424,15 @@ public class PseudoDisassembler { return body; } - procContext.flowStart(entryPoint); - try { // look some number of fallthroughs to see if this // is a valid run of instructions. for (int i = 0; target != null && i < maxInstr; i++) { - PseudoInstruction instr; - instr = disassemble(target, procContext, false); + Instruction instr; + instr = pseudoDisassemble(target, entryContext, maxInstructions, false); - boolean doContinue = processor.process(instr); + boolean doContinue = processor.process((PseudoInstruction)instr); if (!doContinue) { return body; } @@ -482,7 +446,7 @@ public class PseudoDisassembler { instrStarts.addRange(instr.getMinAddress(), instr.getMinAddress()); // check whether processor wants to follow flow on this instruction - if (!processor.followFlows(instr)) { + if (!processor.followFlows((PseudoInstruction) instr)) { target = getNextTarget(body, untriedTargetList); continue; } @@ -530,13 +494,8 @@ public class PseudoDisassembler { target = newTarget; } } - catch (InsufficientBytesException e) { - processor.process(null); - } catch (UnknownInstructionException e) { - processor.process(null); - } - catch (UnknownContextException e) { + // bad instruction processor.process(null); } @@ -662,6 +621,7 @@ public class PseudoDisassembler { AddressSetView execSet = memory.getExecuteSet(); entryPoint = setTargetContextForDisassembly(procContext, entryPoint); + RegisterValue entryContext = getTargetStartContext(entryPoint, procContext); Address target = entryPoint; @@ -683,24 +643,12 @@ public class PseudoDisassembler { return false; } - RepeatInstructionByteTracker repeatInstructionByteTracker = - new RepeatInstructionByteTracker(MAX_REPEAT_BYTES_LIMIT, null); - - procContext.flowStart(entryPoint); try { // look some number of fallthroughs to see if this // is a valid run of instructions. for (int i = 0; target != null && i < maxInstructions; i++) { - if (target.compareTo(procContext.getAddress()) < 0) { - procContext.copyToFutureFlowState(target); - procContext.flowEnd(procContext.getAddress()); - procContext.flowStart(target); - } - else { - procContext.flowToAddress(target); - } - PseudoInstruction instr = disassemble(target, procContext, false); + Instruction instr = pseudoDisassemble(target, entryContext, maxInstructions, false); if (instr == null) { // if the target is in the external section, which is uninitialized, ignore it! @@ -712,7 +660,6 @@ public class PseudoDisassembler { } targetList.remove(target); target = getNextTarget(body, untriedTargetList); - repeatInstructionByteTracker.reset(); continue; } @@ -723,7 +670,7 @@ public class PseudoDisassembler { } // check if we are getting into bad instruction runs - if (repeatInstructionByteTracker.exceedsRepeatBytePattern(instr)) { + if (lastPseudoInstructionBlock.getInstructionConflict() != null) { return false; } @@ -743,8 +690,7 @@ public class PseudoDisassembler { catch (AddressOverflowException e) { return false; } - procContext.flowToAddress(addr); - PseudoInstruction dsInstr = disassemble(addr, procContext, true); + Instruction dsInstr = pseudoDisassemble(addr, entryContext, maxInstructions, false); if (dsInstr == null) { return false; } @@ -762,9 +708,8 @@ public class PseudoDisassembler { // if instruction has fall thru Address fallThru = null; if (instr.hasFallthrough()) { - if (checkNonReturning(program, flowType, instr)) { + if (checkNonReturning(flowType, instr)) { target = getNextTarget(body, untriedTargetList); - repeatInstructionByteTracker.reset(); continue; } newTarget = instr.getFallThrough(); @@ -793,7 +738,6 @@ public class PseudoDisassembler { if (newTarget == null) { newTarget = getNextTarget(body, untriedTargetList); - repeatInstructionByteTracker.reset(); } } @@ -817,7 +761,6 @@ public class PseudoDisassembler { if (func != null) { didCallValidSubroutine = true; newTarget = getNextTarget(body, untriedTargetList); - repeatInstructionByteTracker.reset(); continue; } targetList.add(address); @@ -865,18 +808,10 @@ public class PseudoDisassembler { target = newTarget; } } - catch (InsufficientBytesException e) { - // can't parse not enough bytes - return false; - } catch (UnknownInstructionException e) { // bad instruction return false; } - catch (UnknownContextException e) { - // something wrong with context - return false; - } // get rid of anything on target list that is in body of instruction Iterator
iter = targetList.iterator(); @@ -905,8 +840,71 @@ public class PseudoDisassembler { return false; } + + + private InstructionBlock lastPseudoInstructionBlock; + private Disassembler pseudoDisassembler; + + /** + * Disassemble a block of instructions + * + * @param addr location to disassemble + * @param entryContext context at the start of the block + * @param maxInstr maximum number of instructions to disassemble + * @param forceRedisassembly force re-disassembly (don't use cached block) + * + * @return the instruction (PseudoInstruction) + * @throws UnknownInstructionException if instruction at location not disassemblable + */ - private boolean checkNonReturning(Program program, FlowType flowType, PseudoInstruction instr) { + private Instruction pseudoDisassemble(Address addr, RegisterValue entryContext, int maxInstr, boolean forceRedisassembly) throws UnknownInstructionException { + Instruction instr; + if (!forceRedisassembly && lastPseudoInstructionBlock != null) { + instr = lastPseudoInstructionBlock.getInstructionAt(addr); + if (instr != null) { + return instr; + } + InstructionError error = lastPseudoInstructionBlock.getInstructionConflict(); + if (error != null && addr.equals(error.getInstructionAddress())) { + throw new UnknownInstructionException(error.getConflictMessage()); + } + lastPseudoInstructionBlock = null; + } + + if (pseudoDisassembler == null) { + pseudoDisassembler = Disassembler.getDisassembler(program, false, false, false, + TaskMonitor.DUMMY, msg -> { + // ignore log errors + }); + pseudoDisassembler.setRepeatPatternLimit(MAX_REPEAT_BYTES_LIMIT); + } else if (forceRedisassembly) { + pseudoDisassembler.resetDisassemblerContext(); + } + + lastPseudoInstructionBlock = + pseudoDisassembler.pseudoDisassembleBlock(addr, entryContext, maxInstr); + if (lastPseudoInstructionBlock != null) { + InstructionError error = lastPseudoInstructionBlock.getInstructionConflict(); // Look for zero-byte run first + if (error != null && + error.getConflictMessage().startsWith("Maximum run of Zero-Byte")) { + throw new UnknownInstructionException(error.getConflictMessage()); // Don't return any of the zero-byte instructions + } + instr = lastPseudoInstructionBlock.getInstructionAt(addr); + if (instr != null) { + return instr; + } + if (error != null && addr.equals(error.getInstructionAddress())) { + throw new UnknownInstructionException(error.getConflictMessage()); + } + if (program.getMemory().isExternalBlockAddress(addr)) { + throw new UnknownInstructionException( + "Unable to disassemble EXTERNAL block location: " + addr); + } + } + throw new UnknownInstructionException("Invalid instruction address (improperly aligned)"); + } + + private boolean checkNonReturning(FlowType flowType, Instruction instr) { if (!flowType.isCall()) { return false; } @@ -1059,6 +1057,25 @@ public class PseudoDisassembler { } return null; } + + /** + * Get the context register setup with the starting context for target + * + * @param target address to get context register value + * @param procContext disassembly context + * @return context register value set with current context for target + */ + private RegisterValue getTargetStartContext(Address target, + PseudoDisassemblerContext procContext) { + procContext.flowStart(target); + + RegisterValue entryContext = null; + Register baseContextRegister = procContext.getBaseContextRegister(); + if (baseContextRegister != null) { + entryContext = procContext.getRegisterValue(baseContextRegister); + } + return entryContext; + } /** * @return true if program has uses the low bit of an address to change Instruction Set mode diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/bookmark/BookmarkDBAdapterV3.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/bookmark/BookmarkDBAdapterV3.java index 4104e58b6e..c644b2bbb1 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/bookmark/BookmarkDBAdapterV3.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/bookmark/BookmarkDBAdapterV3.java @@ -71,27 +71,21 @@ public class BookmarkDBAdapterV3 extends BookmarkDBAdapter { throw new VersionException(true); } else if (typeIDs.length != 0) { + int version = -1; for (int i = 0; i < typeIDs.length; i++) { int id = typeIDs[i]; - tables[id] = handle.getTable(BOOKMARK_TABLE_NAME + id); - } - boolean noTables = (tables[typeIDs[0]] == null); - int version = noTables ? -1 : tables[typeIDs[0]].getSchema().getVersion(); - for (int i = 1; i < typeIDs.length; i++) { - int id = typeIDs[i]; - if (noTables) { - if (tables[id] != null) { - throw new IOException("Missing bookmark table"); + String tableName = BOOKMARK_TABLE_NAME + id; + Table table = handle.getTable(tableName); + if (table != null) { + int schemaVersion = table.getSchema().getVersion(); + if (version >= 0 && schemaVersion != version) { + throw new IOException("Inconsistent bookmark table versions"); } + version = schemaVersion; } - else if (tables[id].getSchema().getVersion() != version) { - throw new IOException("Inconsistent bookmark table versions"); - } + tables[id] = table; } - if (noTables) { - throw new VersionException(true); - } - else if (version != VERSION) { + if (version >= 0 && version != VERSION) { throw new VersionException(false); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/bookmark/BookmarkDBManager.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/bookmark/BookmarkDBManager.java index 1dbc8f1293..248aa15594 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/bookmark/BookmarkDBManager.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/bookmark/BookmarkDBManager.java @@ -103,7 +103,7 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager int typeId = (int) rec.getKey(); BookmarkTypeDB type = new BookmarkTypeDB(typeId, rec.getString(BookmarkTypeDBAdapter.TYPE_NAME_COL)); - type.setHasBookmarks(true); + type.setHasBookmarks(bookmarkAdapter.hasTable(typeId)); typesByName.put(type.getTypeString(), type); typesArray.put(typeId, type); } @@ -208,9 +208,11 @@ public class BookmarkDBManager implements BookmarkManager, ErrorHandler, Manager typesArray.put(typeId, bmt); } if (create && !bmt.hasBookmarks()) { + + // Ensure that both type record and bookmarks table exists bookmarkTypeAdapter.addType(bmt.getTypeId(), bmt.getTypeString()); - bmt.setHasBookmarks(true); bookmarkAdapter.addType(bmt.getTypeId()); + bmt.setHasBookmarks(true); // fire event program.setObjChanged(ProgramEvent.BOOKMARK_TYPE_ADDED, bmt, null, null); diff --git a/Ghidra/Processors/AARCH64/data/languages/AARCH64base.sinc b/Ghidra/Processors/AARCH64/data/languages/AARCH64base.sinc index 35ada38a4e..2811de5d48 100644 --- a/Ghidra/Processors/AARCH64/data/languages/AARCH64base.sinc +++ b/Ghidra/Processors/AARCH64/data/languages/AARCH64base.sinc @@ -2841,7 +2841,7 @@ is size.ldstr=3 & b_2429=0x8 & b_23=1 & L=1 & b_21=0 & b_15=1 & addrReg & Rt_GPR :ldar Rt_GPR32, addrReg is size.ldstr=2 & b_2429=0x8 & b_23=1 & L=1 & b_21=0 & b_1620=0b11111 & b_15=1 & b_1014=0b11111 & addrReg & Rt_GPR32 & Rt_GPR64 { - Rt_GPR64 = *addrReg; + Rt_GPR64 = zext(*:4 addrReg); } # C6.2.146 LDARB page C6-1516 line 89986 MATCH x08c08000/mask=xffe08000 @@ -3049,7 +3049,7 @@ is b_3031=0b10 & b_2529=0b10100 & (b_24=1 | b_23=1) & b_22=1 & Rt2_GPR64 & addrP is b_2531=0b0110100 & (b_24=1 | b_23=1) & b_22=1 & Rt2_GPR64 & addrPairIndexed & Rt_GPR64 { local addrval1:8 = sext(*:4 addrPairIndexed); - local addrval2:8 = sext(*:4 (addrPairIndexed + 8)); + local addrval2:8 = sext(*:4 (addrPairIndexed + 4)); Rt_GPR64 = addrval1; Rt2_GPR64 = addrval2; } @@ -8366,4 +8366,211 @@ is b_1231=0b11010101000000000100 & b_0007=0b00111111 OV = tmpOV; } +# FEAT_CSSC +:abs Rd_GPR32, Rn_GPR32 +is sf=0 & b_30=1 & S=0 & b_2428=0x1a & b_2123=0x6 & b_1620=0x0 & b_1015=0x8 & Rd_GPR32 & Rn_GPR32 +{ + local tmp = Rn_GPR32; + local test = tmp s< 0; + Rd_GPR32 = (zext(!test)*tmp) + (zext(test)*(-tmp)); +} +:abs Rd_GPR64, Rn_GPR64 +is sf=1 & b_30=1 & S=0 & b_2428=0x1a & b_2123=0x6 & b_1620=0x0 & b_1015=0x8 & Rd_GPR64 & Rn_GPR64 +{ + local tmp = Rn_GPR64; + local test = tmp s< 0; + Rd_GPR64 = (zext(!test)*tmp) + (zext(test)*(-tmp)); +} + +:cnt Rd_GPR32, Rn_GPR32 +is sf=0 & b_30=1 & S=0 & b_2428=0x1a & b_2123=0x6 & b_1620=0x0 & b_1015=0x7 & Rd_GPR32 & Rn_GPR32 +{ + local tmp = Rn_GPR32; + Rd_GPR32 = popcount(tmp); +} + +:cnt Rd_GPR64, Rn_GPR64 +is sf=1 & b_30=1 & S=0 & b_2428=0x1a & b_2123=0x6 & b_1620=0x0 & b_1015=0x7 & Rd_GPR64 & Rn_GPR64 +{ + local tmp = Rn_GPR64; + Rd_GPR64 = popcount(tmp); +} + +:ctz Rd_GPR32, Rn_GPR32 +is sf=0 & b_3030=1 & S=0 & b_2428=0x1a & b_2123=6 & dp1.opcode2=0x0 & b_1015=0x6 & Rn_GPR32 & Rd_GPR32 & Rd_GPR64 +{ + # equivalent to RBIT; CLZ + local tmp = Rn_GPR32; + tmp = (((tmp & 0xaaaaaaaa) >> 1) | ((tmp & 0x55555555) << 1)); + tmp = (((tmp & 0xcccccccc) >> 2) | ((tmp & 0x33333333) << 2)); + tmp = (((tmp & 0xf0f0f0f0) >> 4) | ((tmp & 0x0f0f0f0f) << 4)); + tmp = (((tmp & 0xff00ff00) >> 8) | ((tmp & 0x00ff00ff) << 8)); + tmp = ((tmp >> 16) | (tmp << 16)); + Rd_GPR64 = lzcount(tmp); +} + +:ctz Rd_GPR64, Rn_GPR64 +is sf=1 & b_3030=1 & S=0 & b_2428=0x1a & b_2123=6 & dp1.opcode2=0x0 & b_1015=0x6 & Rn_GPR64 & Rd_GPR64 +{ + # equivalent to RBIT; CLZ + local tmp = Rn_GPR64; + tmp = (((tmp & 0xaaaaaaaaaaaaaaaa) >> 1) | ((tmp & 0x5555555555555555) << 1)); + tmp = (((tmp & 0xcccccccccccccccc) >> 2) | ((tmp & 0x3333333333333333) << 2)); + tmp = (((tmp & 0xf0f0f0f0f0f0f0f0) >> 4) | ((tmp & 0x0f0f0f0f0f0f0f0f) << 4)); + tmp = (((tmp & 0xff00ff00ff00ff00) >> 8) | ((tmp & 0x00ff00ff00ff00ff) << 8)); + tmp = (((tmp & 0xffff0000ffff0000) >> 16) | ((tmp & 0x0000ffff0000ffff) << 16)); + tmp = ((tmp >> 32) | (tmp << 32)); + Rd_GPR64 = lzcount(tmp); +} + +cssc_simm32: "#"^val is simm8 [ val = simm8 * 1; ] { export *[const]:4 val; } +cssc_simm64: "#"^val is simm8 [ val = simm8 * 1; ] { export *[const]:8 val; } + +cssc_imm32: "#"^val is imm8 [ val = imm8 * 1; ] { export *[const]:4 val; } +cssc_imm64: "#"^val is imm8 [ val = imm8 * 1; ] { export *[const]:8 val; } + + +:smax Rd_GPR32, Rn_GPR32, cssc_simm32 +is sf=0 & b_30=0 & S=0 & b_2428=0x11 & b_2123=0x6 & b_1820=0x0 & Rd_GPR32 & Rn_GPR32 & cssc_simm32 +{ + local tmp = Rn_GPR32; + local tmp2 = cssc_simm32; + local test:1 = tmp s>= tmp2; + Rd_GPR32 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:smax Rd_GPR64, Rn_GPR64, cssc_simm64 +is sf=1 & b_30=0 & S=0 & b_2428=0x11 & b_2123=0x6 & b_1820=0x0 & Rd_GPR64 & Rn_GPR64 & cssc_simm64 +{ + local tmp = Rn_GPR64; + local tmp2 = cssc_simm64; + local test = tmp s>= tmp2; + Rd_GPR64 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:smax Rd_GPR32, Rn_GPR32, Rm_GPR32 +is sf=0 & b_30=0 & S=0 & b_2428=0x1a & b_2123=0x6 & b_1015=0x18 & Rd_GPR32 & Rn_GPR32 & Rm_GPR32 +{ + local tmp = Rn_GPR32; + local tmp2 = Rm_GPR32; + local test = tmp s>= tmp2; + Rd_GPR32 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:smax Rd_GPR64, Rn_GPR64, Rm_GPR64 +is sf=1 & b_30=0 & S=0 & b_2428=0x1a & b_2123=0x6 & b_1015=0x18 & Rd_GPR64 & Rn_GPR64 & Rm_GPR64 +{ + local tmp = Rn_GPR64; + local tmp2 = Rm_GPR64; + local test = tmp s>= tmp2; + Rd_GPR64 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:smin Rd_GPR32, Rn_GPR32, cssc_simm32 +is sf=0 & b_30=0 & S=0 & b_2428=0x11 & b_2123=0x6 & b_1820=0x2 & Rd_GPR32 & Rn_GPR32 & cssc_simm32 +{ + local tmp = Rn_GPR32; + local tmp2 = cssc_simm32; + local test:1 = tmp s<= tmp2; + Rd_GPR32 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:smin Rd_GPR64, Rn_GPR64, cssc_simm64 +is sf=1 & b_30=0 & S=0 & b_2428=0x11 & b_2123=0x6 & b_1820=0x2 & Rd_GPR64 & Rn_GPR64 & cssc_simm64 +{ + local tmp = Rn_GPR64; + local tmp2 = cssc_simm64; + local test = tmp s<= tmp2; + Rd_GPR64 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:smin Rd_GPR32, Rn_GPR32, Rm_GPR32 +is sf=0 & b_30=0 & S=0 & b_2428=0x1a & b_2123=0x6 & b_1015=0x1a & Rd_GPR32 & Rn_GPR32 & Rm_GPR32 +{ + local tmp = Rn_GPR32; + local tmp2 = Rm_GPR32; + local test = tmp s<= tmp2; + Rd_GPR32 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:smin Rd_GPR64, Rn_GPR64, Rm_GPR64 +is sf=1 & b_30=0 & S=0 & b_2428=0x1a & b_2123=0x6 & b_1015=0x1a & Rd_GPR64 & Rn_GPR64 & Rm_GPR64 +{ + local tmp = Rn_GPR64; + local tmp2 = Rm_GPR64; + local test = tmp s<= tmp2; + Rd_GPR64 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:umax Rd_GPR32, Rn_GPR32, cssc_imm32 +is sf=0 & b_30=0 & S=0 & b_2428=0x11 & b_2123=0x6 & b_1820=0x1 & Rd_GPR32 & Rn_GPR32 & cssc_imm32 +{ + local tmp = Rn_GPR32; + local tmp2 = cssc_imm32; + local test:1 = tmp >= tmp2; + Rd_GPR32 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:umax Rd_GPR64, Rn_GPR64, cssc_imm64 +is sf=1 & b_30=0 & S=0 & b_2428=0x11 & b_2123=0x6 & b_1820=0x1 & Rd_GPR64 & Rn_GPR64 & cssc_imm64 +{ + local tmp = Rn_GPR64; + local tmp2 = cssc_imm64; + local test = tmp >= tmp2; + Rd_GPR64 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:umax Rd_GPR32, Rn_GPR32, Rm_GPR32 +is sf=0 & b_30=0 & S=0 & b_2428=0x1a & b_2123=0x6 & b_1015=0x19 & Rd_GPR32 & Rn_GPR32 & Rm_GPR32 +{ + local tmp = Rn_GPR32; + local tmp2 = Rm_GPR32; + local test = tmp >= tmp2; + Rd_GPR32 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:umax Rd_GPR64, Rn_GPR64, Rm_GPR64 +is sf=1 & b_30=0 & S=0 & b_2428=0x1a & b_2123=0x6 & b_1015=0x19 & Rd_GPR64 & Rn_GPR64 & Rm_GPR64 +{ + local tmp = Rn_GPR64; + local tmp2 = Rm_GPR64; + local test = tmp >= tmp2; + Rd_GPR64 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:umin Rd_GPR32, Rn_GPR32, cssc_imm32 +is sf=0 & b_30=0 & S=0 & b_2428=0x11 & b_2123=0x6 & b_1820=0x3 & Rd_GPR32 & Rn_GPR32 & cssc_imm32 +{ + local tmp = Rn_GPR32; + local tmp2 = cssc_imm32; + local test:1 = tmp <= tmp2; + Rd_GPR32 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:umin Rd_GPR64, Rn_GPR64, cssc_imm64 +is sf=1 & b_30=0 & S=0 & b_2428=0x11 & b_2123=0x6 & b_1820=0x3 & Rd_GPR64 & Rn_GPR64 & cssc_imm64 +{ + local tmp = Rn_GPR64; + local tmp2 = cssc_imm64; + local test = tmp <= tmp2; + Rd_GPR64 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:umin Rd_GPR32, Rn_GPR32, Rm_GPR32 +is sf=0 & b_30=0 & S=0 & b_2428=0x1a & b_2123=0x6 & b_1015=0x1b & Rd_GPR32 & Rn_GPR32 & Rm_GPR32 +{ + local tmp = Rn_GPR32; + local tmp2 = Rm_GPR32; + local test = tmp <= tmp2; + Rd_GPR32 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} + +:umin Rd_GPR64, Rn_GPR64, Rm_GPR64 +is sf=1 & b_30=0 & S=0 & b_2428=0x1a & b_2123=0x6 & b_1015=0x1b & Rd_GPR64 & Rn_GPR64 & Rm_GPR64 +{ + local tmp = Rn_GPR64; + local tmp2 = Rm_GPR64; + local test = tmp <= tmp2; + Rd_GPR64 = (zext(test)*tmp) + (zext(!test)*(tmp2)); +} diff --git a/Ghidra/Processors/AARCH64/data/languages/AARCH64instructions.sinc b/Ghidra/Processors/AARCH64/data/languages/AARCH64instructions.sinc index f4eea8485a..03afdd1039 100644 --- a/Ghidra/Processors/AARCH64/data/languages/AARCH64instructions.sinc +++ b/Ghidra/Processors/AARCH64/data/languages/AARCH64instructions.sinc @@ -1131,10 +1131,12 @@ define token instrAARCH64 (32) endian = little imm6 = (10,15) aa_imm7 = (15,21) + imm8 = (10,17) imm12 = (10,21) imm16 = (5,20) simm7 = (15,21) signed + simm8 = (10,17) signed simm9 = (12,20) signed simm14 = (5,18) signed simm19 = (5,23) signed diff --git a/Ghidra/Processors/CR16/data/languages/CR16C.sinc b/Ghidra/Processors/CR16/data/languages/CR16C.sinc index f70a45749d..51a23c4fff 100644 --- a/Ghidra/Processors/CR16/data/languages/CR16C.sinc +++ b/Ghidra/Processors/CR16/data/languages/CR16C.sinc @@ -1240,20 +1240,14 @@ macro do_lshb(count, dest) { *:2 tmp = val | mask; # clear bit, store } -# TBIT - test bit +# TBIT - test bit in register :TBIT imm4a, src1 is hi=0x06 & imm4a & src1 { - tmp:4 = zext(src1); - val:2 = *:2 tmp; # load dst operand mask:2 = 1 << imm4a; - bit:2 = (val & mask) >> imm4a; - $(F) = bit:1; # save bit + $(F) = (src1 & mask) != 0; } :TBIT src, src1 is hi=0x07 & src & src1 { - tmp:4 = zext(src1); - val:2 = *:2 tmp; # load dst operand mask:2 = 1 << src; - bit:2 = (val & mask) >> src; - $(F) = bit:1; # save bit + $(F) = (src1 & mask) != 0; } # TBITB - test bit in low-order byte diff --git a/Ghidra/Processors/MIPS/data/languages/mips.sinc b/Ghidra/Processors/MIPS/data/languages/mips.sinc index c1e52917de..d9f24e1ad1 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips.sinc +++ b/Ghidra/Processors/MIPS/data/languages/mips.sinc @@ -502,6 +502,10 @@ define token instr(32) prime = (26,31) bit25 = (25,25) zero2425 = (24,25) + svrs_xreg = (23,25) + svrs_xregb0 = (23,23) + svrs_xregb1 = (24,24) + svrs_xregb2 = (25,25) zero2325 = (23,25) zero1 = (22,25) rs32 = (21,25) @@ -530,6 +534,7 @@ define token instr(32) off21 = (0,20) signed # 21 bit signed offset in conditional branch/link off16 = (0,15) signed # 16 bit signed offset in conditional branch/link bit21 = (21,21) + svrs_frame_hi = (19,22) bitz19 = (19,20) pcrel = (19,20) pcrel2 = (18,20) @@ -557,8 +562,16 @@ define token instr(32) lohiacx = (16,19) nd = (17,17) tf = (16,16) + svrs_aregb3 = (18,18) + svrs_aregb2 = (17,17) + svrs_aregb1 = (16,16) + svrs_aregb0 = (15,15) + svrs_areg = (15,18) + zero1320 = (13,20) zero1315 = (13,15) + save = (13,13) + svrs_ra = (12,12) szero = (11,25) mask = (11,20) baser6 = (11,15) @@ -600,7 +613,9 @@ define token instr(32) ac = (11,12) bp = (11,12) bit10 = (10,10) + svrs_s0 = (10,10) spec2 = (9,10) + svrs_s1 = (9,9) spec3 = (8,10) simmed9 = (7,15) zero2 = (7,10) @@ -613,7 +628,7 @@ define token instr(32) fct2 = (6,10) zero5 = (6,10) wsbh = (6,10) - + svrs_frame_low = (6,9) bp3 = (6,8) sel_0608 = (6,8) sa2 = (6,7) diff --git a/Ghidra/Processors/MIPS/data/languages/mips16.sinc b/Ghidra/Processors/MIPS/data/languages/mips16.sinc index 560b3406e0..0844ddf1b9 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips16.sinc +++ b/Ghidra/Processors/MIPS/data/languages/mips16.sinc @@ -12,6 +12,14 @@ define token m16instr (16) m16_op=(11,15) + m16_rd0_0 = (11,15) + m16_rd0_1 = (11,15) + m16_rd0_2 = (11,15) + m16_rd0_3 = (11,15) + m16_rd0_4 = (11,15) + m16_rd0_5 = (11,15) + m16_rd0_6 = (11,15) + m16_rd0_7 = (11,15) m16_i_imm=(0,4) m16_rx=(8,10) m16_rxa=(8,10) @@ -74,6 +82,95 @@ attach variables [ ext_m16r32 m16_i8_r32 ] [ t8 t9 k0 k1 gp sp s8 ra ]; + +attach variables [ m16_rd0_0 ] [ + Index Random EntryLo0 EntryLo1 + Context PageMask Wired HWREna + BadVAddr Count EntryHi Compare + Status Cause EPC PRId + Config LLAddr WatchLo WatchHi + XContext cop0_reg21 cop0_reg22 Debug + DEPC PerfCnt ErrCtl CacheErr + TagLo TagHi ErrorEPC DESAVE +]; + +attach variables [ m16_rd0_1 ] [ + MVPControl VPEControl TCStatus cop0_reg3.1 + ContextConfig PageGrain SRSConf0 cop0_reg7.1 + cop0_reg8.1 cop0_reg9.1 cop0_reg10.1 cop0_reg11.1 + IntCtl cop0_reg13.1 cop0_reg14.1 EBase + Config1 cop0_reg17.1 WatchLo.1 WatchHi.1 + cop0_reg20.1 cop0_reg21.1 cop0_reg22.1 TraceControl + cop0_reg24.1 PerfCnt.1 cop0_reg26.1 CacheErr.1 + DataLo.1 DataHi.1 cop0_reg30.1 cop0_reg31.1 +]; + +attach variables [ m16_rd0_2 ] [ + MVPConf0 VPEConf0 TCBind cop0_reg3.2 + cop0_reg4.2 cop0_reg5.2 SRSConf1 cop0_reg7.2 + cop0_reg8.2 cop0_reg9.2 cop0_reg10.2 cop0_reg11.2 + SRSCtl cop0_reg13.2 cop0_reg14.2 cop0_reg15.2 + Config2 cop0_reg17.2 WatchLo.2 WatchHi.2 + cop0_reg20.2 cop0_reg21.2 cop0_reg22.2 TraceControl2 + cop0_reg24.2 PerfCnt.2 cop0_reg26.2 CacheErr.2 + TagLo.2 TagHi.2 cop0_reg30.2 cop0_reg31.2 +]; + +attach variables [ m16_rd0_3 ] [ + MVPConf1 VPEConf1 TCRestart cop0_reg3.3 + cop0_reg4.3 cop0_reg5.3 SRSConf2 cop0_reg7.3 + cop0_reg8.3 cop0_reg9.3 cop0_reg10.3 cop0_reg11.3 + SRSMap cop0_reg13.3 cop0_reg14.3 cop0_reg15.3 + Config3 cop0_reg17.3 WatchLo.3 WatchHi.3 + cop0_reg20.3 cop0_reg21.3 cop0_reg22.3 UserTraceData + cop0_reg24.3 PerfCnt.3 cop0_reg26.3 CacheErr.3 + DataLo.3 DataHi.3 cop0_reg30.3 cop0_reg31.3 +]; + +attach variables [ m16_rd0_4 ] [ + cop0_reg0.4 YQMask TCHalt cop0_reg3.4 + cop0_reg4.4 cop0_reg5.4 SRSConf3 cop0_reg7.4 + cop0_reg8.4 cop0_reg9.4 cop0_reg10.4 cop0_reg11.4 + cop0_reg12.4 cop0_reg13.4 cop0_reg14.4 cop0_reg15.4 + cop0_reg16.4 cop0_reg17.4 WatchLo.4 WatchHi.4 + cop0_reg20.4 cop0_reg21.4 cop0_reg22.4 TraceBPC + cop0_reg24.4 PerfCnt.4 cop0_reg26.4 CacheErr.4 + TagLo.4 TagHi.4 cop0_reg30.4 cop0_reg31.4 +]; + +attach variables [ m16_rd0_5 ] [ + cop0_reg0.5 VPESchedule TCContext cop0_reg3.5 + cop0_reg4.5 cop0_reg5.5 SRSConf4 cop0_reg7.5 + cop0_reg8.5 cop0_reg9.5 cop0_reg10.5 cop0_reg11.5 + cop0_reg12.5 cop0_reg13.5 cop0_reg14.5 cop0_reg15.5 + cop0_reg16.5 cop0_reg17.5 WatchLo.5 WatchHi.5 + cop0_reg20.5 cop0_reg21.5 cop0_reg22.5 cop0_reg23.5 + cop0_reg24.5 PerfCnt.5 cop0_reg26.5 CacheErr.5 + DataLo.5 DataHi.5 cop0_reg30.5 cop0_reg31.5 +]; + +attach variables [ m16_rd0_6 ] [ + cop0_reg0.6 VPEScheFBack TCSchedule cop0_reg3.6 + cop0_reg4.6 cop0_reg5.6 cop0_reg6.6 cop0_reg7.6 + cop0_reg8.6 cop0_reg9.6 cop0_reg10.6 cop0_reg11.6 + cop0_reg12.6 cop0_reg13.6 cop0_reg14.6 cop0_reg15.6 + cop0_reg16.6 cop0_reg17.6 WatchLo.6 WatchHi.6 + cop0_reg20.6 cop0_reg21.6 cop0_reg22.6 cop0_reg23.6 + cop0_reg24.6 PerfCnt.6 cop0_reg26.6 CacheErr.6 + TagLo.6 TagHi.6 cop0_reg30.6 cop0_reg31.6 +]; + +attach variables [ m16_rd0_7 ] [ + cop0_reg0.7 VPEOpt TCScheFBack cop0_reg3.7 + cop0_reg4.7 cop0_reg5.7 cop0_reg6.7 cop0_reg7.7 + cop0_reg8.7 cop0_reg9.7 cop0_reg10.7 cop0_reg11.7 + cop0_reg12.7 cop0_reg13.7 cop0_reg14.7 cop0_reg15.7 + cop0_reg16.7 cop0_reg17.7 WatchLo.7 WatchHi.7 + cop0_reg20.7 cop0_reg21.7 cop0_reg22.7 cop0_reg23.7 + cop0_reg24.7 PerfCnt.7 cop0_reg26.7 CacheErr.7 + DataLo.7 DataHi.7 cop0_reg30.7 cop0_reg31.7 +]; + @ifdef MIPS64 attach variables [ m16_rxa m16_rya m16_rza m16_mv_rza] [ s0_lo s1_lo v0_lo v1_lo a0_lo a1_lo a2_lo a3_lo ]; @@ -87,6 +184,7 @@ attach variables [ ext_m16r32a m16_i8_r32a ] [ RZ: m16_rz is m16_rz { export m16_rz; } + @else # !MIPS64 attach variables [ m16_rxa m16_rya m16_rza m16_mv_rza ] [ s0 s1 v0 v1 a0 a1 a2 a3 ]; @@ -912,11 +1010,21 @@ E2_REGOFF: imm is ext_imm_2124 & m16_i_imm [ imm = m16_i_imm | (ext_imm_2124 << m16_rx = sext( valOrig | valLoad ); } -:mfc0 m16_ry, m16_i_imm, ext_imm_2123 is ISA_MODE=1 & RELP=1 & ext_isjal=0 & ext_is_ext=1 & ext_imm_2426=0 & ext_imm_2123 & ext_imm_1620=0 & m16_op=0b01100 & m16_rx=0b111 & m16_ry & m16_i_imm { - m16_ry = getCopReg(0:1,m16_i_imm:1,ext_imm_2123:1); + +m16_RD0: m16_rd0_0 is m16_rd0_0 & ext_imm_2123=0 { export m16_rd0_0; } +m16_RD0: m16_rd0_1 is m16_rd0_1 & ext_imm_2123=1 { export m16_rd0_1; } +m16_RD0: m16_rd0_2 is m16_rd0_2 & ext_imm_2123=2 { export m16_rd0_2; } +m16_RD0: m16_rd0_3 is m16_rd0_3 & ext_imm_2123=3 { export m16_rd0_3; } +m16_RD0: m16_rd0_4 is m16_rd0_4 & ext_imm_2123=4 { export m16_rd0_4; } +m16_RD0: m16_rd0_5 is m16_rd0_5 & ext_imm_2123=5 { export m16_rd0_5; } +m16_RD0: m16_rd0_6 is m16_rd0_6 & ext_imm_2123=6 { export m16_rd0_6; } +m16_RD0: m16_rd0_7 is m16_rd0_7 & ext_imm_2123=7 { export m16_rd0_7; } + +:mfc0 m16_ry, m16_RD0 is ISA_MODE=1 & RELP=1 & ext_isjal=0 & ext_is_ext=1 & ext_imm_2426=0 & ext_imm_2123 & ext_imm_1620=0 & m16_op=0b01100 & m16_rx=0b111 & m16_ry & m16_RD0 { + m16_ry = zext( m16_RD0:$(SIZETO4) ); } -:mtc0 m16_ry, m16_i_imm, ext_imm_2123 is ISA_MODE=1 & RELP=1 & ext_isjal=0 & ext_is_ext=1 & ext_imm_2426=0 & ext_imm_2123 & ext_imm_1620=1 & m16_op=0b01100 & m16_rx=0b111 & m16_ry & m16_i_imm { - setCopReg(0:1,m16_ry,m16_i_imm:1,ext_imm_2123:1); +:mtc0 m16_ry, m16_RD0 is ISA_MODE=1 & RELP=1 & ext_isjal=0 & ext_is_ext=1 & ext_imm_2426=0 & ext_imm_2123 & ext_imm_1620=1 & m16_op=0b01100 & m16_rx=0b111 & m16_ry & m16_RD0 { + setCopReg(0:1, m16_RD0, m16_ry); } :movz m16_rx, m16_ry, ext_rb is ISA_MODE=1 & RELP=1 & ext_isjal=0 & ext_is_ext=1 & ext_imm_2226=0 & ext_imm_21=1 & ext_imm_1920=0 & ext_rb & m16_op=0b00110 & m16_rx & m16_ry & m16_shft_sa=1 & m16_shft_f=0b10 { diff --git a/Ghidra/Processors/MIPS/data/languages/mips32Instructions.sinc b/Ghidra/Processors/MIPS/data/languages/mips32Instructions.sinc index de6a1fad5e..a5e59dcad9 100644 --- a/Ghidra/Processors/MIPS/data/languages/mips32Instructions.sinc +++ b/Ghidra/Processors/MIPS/data/languages/mips32Instructions.sinc @@ -191,11 +191,13 @@ define pcodeop special2; # 0100 0010 0000 0000 0000 0000 0001 1000 :eret is $(AMODE) & prime=0x10 & fct=0x18 & bit25=1 & copfill=0 { - return[EPC]; + JXWritePC(EPC); + return[EPC]; } :eretnc is $(AMODE) & prime=0x10 & fct=0x18 & bit25=1 & copfill=1 { - return[EPC]; + JXWritePC(EPC); + return[EPC]; } # 0111 11ss ssst tttt mmmm mLLL LL00 0000 @@ -423,13 +425,13 @@ define pcodeop special2; # 0100 1000 000t tttt iiii iiii iiii iiii :mfc2 RT, immed is $(AMODE) & prime=0x12 & copop=0 & RT & immed { - tmp:$(REGSIZE) = getCopReg(2:1, immed:4); + tmp:4 = getCopReg(2:1, immed:4); RT = sext( tmp ); } # 0100 1000 011t tttt iiii iiii iiii iiii :mfhc2 RT, immed is $(AMODE) & prime=0x12 & copop=3 & RT & fs & immed { - tmp:$(REGSIZE) = getCopReg(2:1, immed:4); + tmp:4 = getCopReg(2:1, immed:4); RT = sext(tmp >> 32); } @@ -450,16 +452,20 @@ define pcodeop special2; } # 0100 0000 100t tttt dddd d000 0000 0sss -:mtc0 RTsrc, RD0, sel is $(AMODE) & prime=0x10 & copop=4 & RTsrc & RD0 & zero6=0 & sel { - setCopReg(0:1, RD0, RTsrc, sel:1); +:mtc0 RTsrc, RD0 is $(AMODE) & prime=0x10 & copop=4 & RTsrc & RD0 & zero6=0 { + setCopReg(0:1, RD0, RTsrc); } + # 0100 1000 100t tttt iiii iiii iiii iiii :mtc2 RTsrc, immed is $(AMODE) & prime=0x12 & copop=4 & RTsrc & immed { setCopReg(2:1, immed:4, RTsrc); } :mthc0 RTsrc, RD0, sel is $(AMODE) & prime=0x10 & copop=6 & RTsrc & RD0 & zero6=0 & sel { - setCopReg(0:1, RD0, RTsrc, sel:1); + tmp:4 = RTsrc:$(SIZETO4); + low:4 = RD0:4; + val:8 = (zext(tmp) << 32) + zext(low); + setCopReg(0:1, RD0, val); } # 0100 1000 111t tttt iiii iiii iiii iiii @@ -1747,5 +1753,224 @@ define pcodeop SYNC; signalReservedInstruction(immed:2); } +rsRa: is svrs_ra=0 {} +rsRa: ra is svrs_ra=1 & ra { + tsp = tsp-$(REGSIZE); + MemSrcCast(ra,tsp); +} +svRa: is svrs_ra=0 {} +svRa: ra is svrs_ra=1 & ra { + tsp = tsp-$(REGSIZE); + MemDestCast(tsp,ra); +} + +rs_statReg: is svrs_areg {} +rs_statReg: ",a3" is (svrs_areg=1 | svrs_areg=5 | svrs_areg=9 |svrs_areg=0xd) { + tsp = tsp-4; + MemSrcCast(a3,tsp); +} +rs_statReg: ",a2-a3" is (svrs_areg=2 | svrs_areg=6 | svrs_areg=0xa) { + tsp = tsp-4; + MemSrcCast(a3,tsp); + tsp = tsp-4; + MemSrcCast(a2,tsp); +} +rs_statReg: ",a1-a3" is (svrs_areg=3 | svrs_areg=7) { + tsp = tsp-4; + MemSrcCast(a3,tsp); + tsp = tsp-4; + MemSrcCast(a2,tsp); + tsp = tsp-4; + MemSrcCast(a1,tsp); +} +rs_statReg: ",a0-a3" is svrs_areg=0xb { + tsp = tsp-4; + MemSrcCast(a3,tsp); + tsp = tsp-4; + MemSrcCast(a2,tsp); + tsp = tsp-4; + MemSrcCast(a1,tsp); + tsp = tsp-4; + MemSrcCast(a0,tsp); +} + +rsStat: is svrs_areg=0 | svrs_areg=4 | svrs_areg=8 | svrs_areg=0xc | svrs_areg=0xe {} +rsStat: rs_statReg is rs_statReg { + build rs_statReg; +} + + +sv_statReg: is svrs_areg {} +sv_statReg: ",a3" is (svrs_areg=1 | svrs_areg=5 | svrs_areg=9 | svrs_areg=0xd) { + tsp = tsp-4; + MemDestCast(tsp,a3); +} +sv_statReg: ",a2-a3" is (svrs_areg=2 | svrs_areg=6 | svrs_areg=0xa) { + tsp = tsp-4; + MemDestCast(tsp,a3); + tsp = tsp-4; + MemDestCast(tsp,a2); +} +sv_statReg: ",a1-a3" is (svrs_areg=3 | svrs_areg=7) { + tsp = tsp-4; + MemDestCast(tsp,a3); + tsp = tsp-4; + MemDestCast(tsp,a2); + tsp = tsp-4; + MemDestCast(tsp,a1); +} +sv_statReg: ",a0-a3" is svrs_areg=0xb { + tsp = tsp-4; + MemDestCast(tsp,a3); + tsp = tsp-4; + MemDestCast(tsp,a2); + tsp = tsp-4; + MemDestCast(tsp,a1); + tsp = tsp-4; + MemDestCast(tsp,a0); +} + +svStat: is svrs_areg=0 | svrs_areg=4 | svrs_areg=8 | svrs_areg=0xc | svrs_areg=0xe {} +svStat: sv_statReg is sv_statReg { + build sv_statReg; +} + +sv_areg1: is svrs_aregb2=0 {} +sv_areg1: "a0," is svrs_aregb2=1 { + ptr:$(REGSIZE) = sp; + MemDestCast(ptr,a0); +} + +sv_areg2: sv_areg1 is sv_areg1 { build sv_areg1; } +sv_areg2: "a0-a1," is svrs_aregb3=1 & svrs_aregb2=0 & (svrs_aregb1=0 | svrs_aregb0=0) { + ptr:$(REGSIZE) = sp; + MemDestCast(ptr,a0); + ptr = sp+4; + MemDestCast(ptr,a1); +} + +sv_areg3: sv_areg2 is sv_areg2 { build sv_areg2; } +sv_areg3: "a0-a2," is svrs_aregb3=1 & svrs_aregb2=1 & svrs_aregb1=0 { + ptr:$(REGSIZE) = sp; + MemDestCast(ptr,a0); + ptr = sp+4; + MemDestCast(ptr,a1); + ptr = sp+8; + MemDestCast(ptr,a2); +} + +sv_areg4: sv_areg3 is sv_areg3 { build sv_areg3; } +sv_areg4: "a0-a3," is svrs_areg=0xe { + ptr:$(REGSIZE) = sp; + MemDestCast(ptr,a0); + ptr = sp+4; + MemDestCast(ptr,a1); + ptr = sp+8; + MemDestCast(ptr,a2); + ptr = sp+12; + MemDestCast(ptr,a3); +} + +svAregs: is svrs_aregb3=0 | svrs_areg=0xb | svrs_areg=0xf {} +svAregs: sv_areg4 is sv_areg4 { + build sv_areg4; +} + +rs_s0: is svrs_s0 {} +rs_s0: is svrs_s0=1 { tsp = tsp-$(REGSIZE); MemSrcCast(s0,tsp); } + +rs_s1: is svrs_s1 {} +rs_s1: is svrs_s1=1 { tsp = tsp-$(REGSIZE); MemSrcCast(s1,tsp); } + +rs_s8: is svrs_xreg=6 {} +rs_s8: is svrs_xreg { tsp = tsp-$(REGSIZE); MemSrcCast(s8,tsp); } + +rs_s7: is svrs_xreg=5 {} +rs_s7: is rs_s8 { build rs_s8; tsp = tsp-$(REGSIZE); MemSrcCast(s7,tsp); } + +rs_s6: is svrs_xreg=4 {} +rs_s6: is rs_s7 { build rs_s7; tsp = tsp-$(REGSIZE); MemSrcCast(s6,tsp); } + +rs_s5: is svrs_xreg=3 {} +rs_s5: is rs_s6 { build rs_s6; tsp = tsp-$(REGSIZE); MemSrcCast(s5,tsp); } + +rs_s4: is svrs_xreg=2 {} +rs_s4: is rs_s5 { build rs_s5; tsp = tsp-$(REGSIZE); MemSrcCast(s4,tsp); } + +rs_s3: is svrs_xreg=1 {} +rs_s3: is rs_s4 { build rs_s4; tsp = tsp-$(REGSIZE); MemSrcCast(s3,tsp); } + +rs_s2: is svrs_xreg=0 {} +rs_s2: is rs_s3 { build rs_s3; tsp = tsp-$(REGSIZE); MemSrcCast(s2,tsp); } + +rsXsregs: is svrs_s0=0 & svrs_s1=0 & svrs_xreg=0 {} +rsXsregs: ","svrs_xreg is svrs_s0 & svrs_s1 & svrs_xreg & rs_s2 & rs_s1 & rs_s0 { + build rs_s2; + build rs_s1; + build rs_s0; +} + +sv_s0: is svrs_s0 {} +sv_s0: is svrs_s0=1 { tsp = tsp-$(REGSIZE); MemDestCast(tsp,s0);} + +sv_s1: is svrs_s1 {} +sv_s1: is svrs_s1=1 { tsp = tsp-$(REGSIZE); MemDestCast(tsp,s1); } + +sv_s8: is svrs_xreg=6 {} +sv_s8: is svrs_xreg { tsp = tsp-$(REGSIZE); MemDestCast(tsp,s8); } + +sv_s7: is svrs_xreg=5 {} +sv_s7: is sv_s8 { build sv_s8; tsp = tsp-$(REGSIZE); MemDestCast(tsp,s7); } + +sv_s6: is svrs_xreg=4 {} +sv_s6: is sv_s7 { build sv_s7; tsp = tsp-$(REGSIZE); MemDestCast(tsp,s6); } + +sv_s5: is svrs_xreg=3 {} +sv_s5: is sv_s6 { build sv_s6; tsp = tsp-$(REGSIZE); MemDestCast(tsp,s5); } + +sv_s4: is svrs_xreg=2 {} +sv_s4: is sv_s5 { build sv_s5; tsp = tsp-$(REGSIZE); MemDestCast(tsp,s4); } + +sv_s3: is svrs_xreg=1 {} +sv_s3: is sv_s4 { build sv_s4; tsp = tsp-$(REGSIZE); MemDestCast(tsp,s3); } + +sv_s2: is svrs_xreg=0 {} +sv_s2: is sv_s3 { build sv_s3; tsp = tsp-$(REGSIZE); MemDestCast(tsp,s2); } + +svXsregs: is svrs_s0=0 & svrs_s0=0 & svrs_xreg=0 {} +svXsregs: ","svrs_xreg is svrs_s0 & svrs_s1 & svrs_xreg & sv_s0 & sv_s1 & sv_s2 { + build sv_s2; + build sv_s1; + build sv_s0; +} + +svFramesize: ,val is svrs_frame_hi=0 & svrs_frame_low=0 [val = 128; ] {export *[const]:2 val;} +svFramesize: ,val is svrs_frame_hi & svrs_frame_low [val = ((svrs_frame_hi << 4) | svrs_frame_low) << 3;] {export *[const]:2 val;} + + +:save svRa^svXsregs^svAregs^svFramesize is $(AMODE) & REL6=1 & prime=0x1c & fct=0x1f & save=0x01 & svRa & svXsregs & svAregs & svStat & svFramesize { + tsp = sp; + build svAregs; + build svRa; + build svXsregs; + build svStat; + build svFramesize; + + tmp:2 = svFramesize; + sp = sp - zext(tmp); +} + +:restore rsRa^rsXsregs^rsStat^svFramesize is $(AMODE) & REL6=1 & prime=0x1c & fct=0x1f & save=0x00 & rsRa & rsXsregs & rsStat & svFramesize { + build svFramesize; + + tmp:2 = svFramesize; + tsp = sp+zext(tmp); + + build rsRa; + build rsXsregs; + build rsStat; + + sp = sp+zext(tmp); +} @include "mipsfloat.sinc" diff --git a/Ghidra/Processors/MIPS/data/languages/mipsmicro.sinc b/Ghidra/Processors/MIPS/data/languages/mipsmicro.sinc index f9fc0d9947..5ccf2c3447 100644 --- a/Ghidra/Processors/MIPS/data/languages/mipsmicro.sinc +++ b/Ghidra/Processors/MIPS/data/languages/mipsmicro.sinc @@ -1313,7 +1313,7 @@ STORE_TOP16: STORE_SREG^ra,EXT_CODE4E(sp) is mic_listr6 & REL6=1 & STORE_SREG & break(mic_code:2); } -:sdbbp16 SDB16 is ISA_MODE=1 & RELP=0 & mic_op=0b100010 & SDB16 & ((mic_break=0b101100 & REL6=0) | (mic_breakr6=0b111011 & REL6=1)) { +:sdbbp16 SDB16 is ISA_MODE=1 & RELP=0 & mic_op=0b010001 & SDB16 & ((mic_break=0b101100 & REL6=0) | (mic_breakr6=0b111011 & REL6=1)) { break(SDB16); } diff --git a/Ghidra/Processors/PIC/data/languages/pic18_instructions.sinc b/Ghidra/Processors/PIC/data/languages/pic18_instructions.sinc index a5c5fa85a6..da4b929978 100644 --- a/Ghidra/Processors/PIC/data/languages/pic18_instructions.sinc +++ b/Ghidra/Processors/PIC/data/languages/pic18_instructions.sinc @@ -340,7 +340,7 @@ fREGLoc: freg is a=0 & f8=0xdb & freg { } # Direct File register data -srcREG: fREGLoc is fREGLoc { export fREGLoc; } +srcREG: fREGLoc is fREGLoc { export fREGLoc; } # PCL read - latch PC into PCL, PCLATH, and PCLATU srcREG: "PC" is a=0 & f8=0xf9 { @@ -348,18 +348,128 @@ srcREG: "PC" is a=0 & f8=0xf9 { export PCL; } -# Destination register (either srcREG or WREG) -destREG: "0" is d=0 { export WREG; } -destREG: "1" is d=1 & srcREG { export srcREG; } -#destREG: "1" is d=1 & f8=0xf9 { -# # Storing to PCL must write the PC using both the stored PCL (PC<7:0>), PCLATH (PC<15:8>) and PCLATU (PC<21:16>) -# # The ADDWF and MOVWF definitions below have a specific case to handle this write to PCL -# export PCL; -#} +dfLoc: f8 is a=0 & f8_57=0x0 & f8 { export *[DATA]:1 f8; } # 0x00-0x1f (Access mode) +dfLoc: f8 is a=0 & f8_57=0x1 & f8 { export *[DATA]:1 f8; } # 0x20-0x3f (Access mode) +dfLoc: f8 is a=0 & f8_57=0x2 & f8 { export *[DATA]:1 f8; } # 0x40-0x5f (Access mode) +dfLoc: freg is a=0 & freg { export freg; } # 0xf60-0xfff (Access mode) + +# TOSL - access mirrored into stack space using STKPTR +dfLoc: freg is a=0 & f8=0xfd & freg { + addr:1 = STKPTR + 1; + export *[HWSTACK]:1 addr; +} + +# TOSH - access mirrored into stack space using STKPTR +dfLoc: freg is a=0 & f8=0xfe & freg { + addr:1 = STKPTR + 2; + export *[HWSTACK]:1 addr; +} + +# TOSU - access mirrored into stack space using STKPTR +dfLoc: freg is a=0 & f8=0xff & freg { + addr:1 = STKPTR + 3; + export *[HWSTACK]:1 addr; +} + +# Indirect File Register access - INDF0 +dfLoc: freg is a=0 & f8=0xef & freg { + addr:2 = FSR0; + export *[DATA]:1 addr; +} + +# Indirect File Register access - INDF1 +dfLoc: freg is a=0 & f8=0xe7 & freg { + addr:2 = FSR1; + export *[DATA]:1 addr; +} + +# Indirect File Register access - INDF2 +dfLoc: freg is a=0 & f8=0xdf & freg { + addr:2 = FSR2; + export *[DATA]:1 addr; +} + +## Post-increment File Register access - POSTINC0 +dfLoc: freg is a=0 & f8=0xee & freg { + addr:2 = FSR0; + export *[DATA]:1 addr; +} + +# Post-increment File Register access - POSTINC1 +dfLoc: freg is a=0 & f8=0xe6 & freg { + addr:2 = FSR1; + export *[DATA]:1 addr; +} + +# Post-increment File Register access - POSTINC2 +dfLoc: freg is a=0 & f8=0xde & freg { + addr:2 = FSR2; + export *[DATA]:1 addr; +} + +# Post-decrement File Register access - POSTDEC0 +dfLoc: freg is a=0 & f8=0xed & freg { + addr:2 = FSR0; + export *[DATA]:1 addr; +} + +# Post-decrement File Register access - POSTDEC1 +dfLoc: freg is a=0 & f8=0xe5 & freg { + addr:2 = FSR1; + export *[DATA]:1 addr; +} + +dfLoc: freg is a=0 & f8=0xdd & freg { + addr:2 = FSR2; + export *[DATA]:1 addr; +} + +# Pre-increment File Register access - PREINC0 +dfLoc: freg is a=0 & f8=0xec & freg { + FSR0 = FSR0 + 1; + addr:2 = FSR0; + export *[DATA]:1 addr; +} + +# Pre-increment File Register access - PREINC1 +dfLoc: freg is a=0 & f8=0xe4 & freg { + FSR1 = FSR1 + 1; + addr:2 = FSR1; + export *[DATA]:1 addr; +} + +# Pre-increment File Register access - PREINC2 +dfLoc: freg is a=0 & f8=0xdc & freg { + FSR2 = FSR2 + 1; + addr:2 = FSR2; + export *[DATA]:1 addr; +} + +# Pre-increment w/WREG-Offset File Register access - PLUSW0 +dfLoc: freg is a=0 & f8=0xeb & freg { + FSR0 = FSR0 + 1; + addr:2 = FSR0 + sext(WREG); + export *[DATA]:1 addr; +} + +# Pre-increment w/WREG-Offset File Register access - PLUSW1 +dfLoc: freg is a=0 & f8=0xe3 & freg { + FSR1 = FSR1 + 1; + addr:2 = FSR1 + sext(WREG); + export *[DATA]:1 addr; +} + +# Pre-increment w/WREG-Offset File Register access - PLUSW2 +dfLoc: freg is a=0 & f8=0xdb & freg { + FSR2 = FSR2 + 1; + addr:2 = FSR2 + sext(WREG); + export *[DATA]:1 addr; +} # Destination operand representation (w: W register is destination; f: specified fREG is destination) -D: "w" is d=0 { } -D: "f" is d=1 { } +# Destination register (either srcREG or WREG) +destREG: "0" is d=0 { export WREG; } +destREG: "1" is d=1 & dfLoc { export dfLoc; } # Source File Registers specified by a 12-bit absolute offsets within 32-bit instriction srcREG32: fs is fs { export *[DATA]:1 fs; } # 0x000-0xeff @@ -667,7 +777,7 @@ A: "BANKED" is a=1 { } # BYTE-ORIENTED FILE REGISTER OPERATIONS # -:ADDWF srcREG, D, A is op6=0x09 & srcREG & A & destREG & D { +:ADDWF srcREG, destREG, A is op6=0x09 & srcREG & destREG & A { # 0010 01da ffff ffff # 0010 0100 0000 0000 -> ADDWF DAT_DATA_0000, w, ACCESS # 0010 0101 0000 0000 -> ADDWF REG0x0, w, BANKED @@ -677,7 +787,8 @@ A: "BANKED" is a=1 { } # 0010 0111 0000 0000 -> ADDWF REG0x0, f, BANKED # 0010 0110 1101 1000 -> ADDWF STATUS, f, ACCESS # 0010 0111 1101 1000 -> ADDWF REG0xD8, f, BANKED - # 0010 0100 1111 1001 -> ADDWF PC, w, ACCESS + build destREG; + build srcREG; tmp:1 = srcREG; # read only once! setAddFlags(tmp, WREG); tmp = tmp + WREG; @@ -685,7 +796,7 @@ A: "BANKED" is a=1 { } setResultFlags(tmp); } -:ADDWF pcl, D, A is op6=0x09 & A & D & d=1 & pcl { +:ADDWF pcl, destREG, A is op6=0x09 & A & destREG & pcl { # 0010 01da ffff ffff # 0010 0110 1111 1001 -> ADDWF PC, f, ACCESS addr:3 = inst_start; @@ -700,7 +811,7 @@ A: "BANKED" is a=1 { } goto [addr]; } -:ADDWFC srcREG, D, A is op6=0x08 & srcREG & destREG & D & A { +:ADDWFC srcREG, destREG, A is op6=0x08 & srcREG & destREG & A { # 0010 00da ffff ffff # 0010 0000 0000 0000 -> ADDWFC DAT_DATA_0000, w, ACCESS # 0010 0001 0000 0000 -> ADDWFC REG0x0, w, BANKED @@ -710,6 +821,8 @@ A: "BANKED" is a=1 { } # 0010 0011 0000 0000 -> ADDWFC REG0x0, f, BANKED # 0010 0010 1101 1000 -> ADDWFC STATUS, f, ACCESS # 0010 0011 1101 1000 -> ADDWFC REG0xD8, f, BANKED + build destREG; + build srcREG; local tmpC = C & 1; tmp:1 = srcREG; setAddCFlags(tmp, WREG); @@ -718,7 +831,7 @@ A: "BANKED" is a=1 { } setResultFlags(tmp); } -:ANDWF srcREG, D, A is op6=0x05 & srcREG & destREG & D & A { +:ANDWF srcREG, destREG, A is op6=0x05 & srcREG & destREG & A { # 0001 01da ffff ffff # 0001 0100 0000 0000 -> ANDWF DAT_DATA_0000, w, ACCESS # 0001 0101 0000 0000 -> ANDWF REG0x0, w, BANKED @@ -728,6 +841,8 @@ A: "BANKED" is a=1 { } # 0001 0111 0000 0000 -> ANDWF REG0x0, f, BANKED # 0001 0110 1101 1000 -> ANDWF STATUS, f, ACCESS # 0001 0111 1101 1000 -> ANDWF REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = srcREG & WREG; destREG = tmp; setResultFlags(tmp); @@ -743,7 +858,7 @@ A: "BANKED" is a=1 { } Z = 1; } -:COMF srcREG, D, A is op6=0x07 & srcREG & destREG & D & A { +:COMF srcREG, destREG, A is op6=0x07 & srcREG & destREG & A { # 0001 11da ffff ffff # 0001 1100 0000 0000 -> COMF DAT_DATA_0000, w, ACCESS # 0001 1101 0000 0000 -> COMF REG0x0, w, BANKED @@ -753,6 +868,8 @@ A: "BANKED" is a=1 { } # 0001 1111 0000 0000 -> COMF REG0x0, f, BANKED # 0001 1110 1101 1000 -> COMF STATUS, f, ACCESS # 0001 1111 1101 1000 -> COMF REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = ~srcREG; destREG = tmp; setResultFlags(tmp); @@ -785,7 +902,7 @@ A: "BANKED" is a=1 { } if (srcREG < WREG) goto skipInst; } -:DECF srcREG, D, A is op6=0x01 & srcREG & destREG & D & A { +:DECF srcREG, destREG, A is op6=0x01 & srcREG & destREG & A { # 0000 01da ffff ffff # 0000 0100 0000 0000 -> DECF DAT_DATA_0000, w, ACCESS # 0000 0101 0000 0000 -> DECF REG0x0, w, BANKED @@ -795,6 +912,8 @@ A: "BANKED" is a=1 { } # 0000 0111 0000 0000 -> DECF REG0x0, f, BANKED # 0000 0110 1101 1000 -> DECF STATUS, f, ACCESS # 0000 0111 1101 1000 -> DECF REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = srcREG; setSubtractFlags(tmp, 1); tmp = tmp - 1; @@ -802,7 +921,7 @@ A: "BANKED" is a=1 { } setResultFlags(tmp); } -:DECFSZ srcREG, D, A is op6=0x0b & srcREG & destREG & D & A & skipInst { +:DECFSZ srcREG, destREG, A is op6=0x0b & srcREG & destREG & A & skipInst { # 0010 11da ffff ffff # 0010 1100 0000 0000 -> DECFSZ DAT_DATA_0000, w, ACCESS # 0010 1101 0000 0000 -> DECFSZ REG0x0, w, BANKED @@ -812,12 +931,15 @@ A: "BANKED" is a=1 { } # 0010 1111 0000 0000 -> DECFSZ REG0x0, f, BANKED # 0010 1110 1101 1000 -> DECFSZ STATUS, f, ACCESS # 0010 1111 1101 1000 -> DECFSZ REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = srcREG - 1; destREG = tmp; if (tmp == 0) goto skipInst; } -:DCFSNZ srcREG, D, A is op6=0x13 & srcREG & destREG & D & A & skipInst { + +:DCFSNZ srcREG, destREG, A is op6=0x13 & srcREG & destREG & A & skipInst { # 0100 11da ffff ffff # 0100 1100 0000 0000 -> DCFSNZ DAT_DATA_0000, w, ACCESS # 0100 1101 0000 0000 -> DCFSNZ REG0x0, w, BANKED @@ -827,12 +949,15 @@ A: "BANKED" is a=1 { } # 0100 1111 0000 0000 -> DCFSNZ REG0x0, f, BANKED # 0100 1110 1101 1000 -> DCFSNZ STATUS, f, ACCESS # 0100 1111 1101 1000 -> DCFSNZ REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = srcREG - 1; destREG = tmp; if (tmp != 0) goto skipInst; } -:INCF srcREG, D, A is op6=0x0a & srcREG & destREG & D & A { + +:INCF srcREG, destREG, A is op6=0x0a & srcREG & destREG & A { # 0010 10da ffff ffff # 0010 1000 0000 0000 -> INCF DAT_DATA_0000, w, ACCESS # 0010 1001 0000 0000 -> INCF REG0x0, w, BANKED @@ -842,6 +967,8 @@ A: "BANKED" is a=1 { } # 0010 1011 0000 0000 -> INCF REG0x0, f, BANKED # 0010 1010 1101 1000 -> INCF STATUS, f, ACCESS # 0010 1011 1101 1000 -> INCF REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = srcREG; # read once only! setAddFlags(tmp, 1); tmp = tmp + 1; @@ -849,7 +976,7 @@ A: "BANKED" is a=1 { } setResultFlags(tmp); } -:INCFSZ srcREG, D, A is op6=0x0f & srcREG & destREG & D & A & skipInst { +:INCFSZ srcREG, destREG, A is op6=0x0f & srcREG & destREG & A & skipInst { # 0011 11da ffff ffff # 0011 1100 0000 0000 -> INCFSZ DAT_DATA_0000, w, ACCESS # 0011 1101 0000 0000 -> INCFSZ REG0x0, w, BANKED @@ -859,12 +986,14 @@ A: "BANKED" is a=1 { } # 0011 1111 0000 0000 -> INCFSZ REG0x0, f, BANKED # 0011 1110 1101 1000 -> INCFSZ STATUS, f, ACCESS # 0011 1111 1101 1000 -> INCFSZ REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = srcREG + 1; destREG = tmp; if (tmp == 0) goto skipInst; } -:INFSNZ srcREG, D, A is op6=0x12 & srcREG & destREG & D & A & skipInst { +:INFSNZ srcREG, destREG, A is op6=0x12 & srcREG & destREG & A & skipInst { # 0100 10da ffff ffff # 0100 1000 0000 0000 -> INFSNZ DAT_DATA_0000, w, ACCESS # 0100 1001 0000 0000 -> INFSNZ REG0x0, w, BANKED @@ -874,12 +1003,14 @@ A: "BANKED" is a=1 { } # 0100 1011 0000 0000 -> INFSNZ REG0x0, f, BANKED # 0100 1010 1101 1000 -> INFSNZ STATUS, f, ACCESS # 0100 1011 1101 1000 -> INFSNZ REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = srcREG + 1; destREG = tmp; if (tmp != 0) goto skipInst; } -:IORWF srcREG, D, A is op6=0x04 & srcREG & destREG & D & A { +:IORWF srcREG, destREG, A is op6=0x04 & srcREG & destREG & A { # 0001 00da ffff ffff # 0001 0000 0000 0000 -> IORWF DAT_DATA_0000, w, ACCESS # 0001 0001 0000 0000 -> IORWF REG0x0, w, BANKED @@ -889,26 +1020,28 @@ A: "BANKED" is a=1 { } # 0001 0011 0000 0000 -> IORWF REG0x0, f, BANKED # 0001 0010 1101 1000 -> IORWF STATUS, f, ACCESS # 0001 0011 1101 1000 -> IORWF REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = srcREG | WREG; destREG = tmp; setResultFlags(tmp); } -:MOVF srcREG, D, A is op6=0x14 & srcREG & destREG & D & A { +:MOVF srcREG, destREG, A is op6=0x14 & srcREG & destREG & A { # 0101 00da ffff ffff # 0101 0000 0000 0000 -> MOVF DAT_DATA_0000, w, ACCESS # 0101 0001 0000 0000 -> MOVF REG0x0, w, BANKED # 0101 0000 1101 1000 -> MOVF STATUS, w, ACCESS # 0101 0001 1101 1000 -> MOVF REG0xD8, w, BANKED + # 0101 0000 1110 1111 -> MOVF INDF0, w, ACCESS + # 0101 0000 1110 0111 -> MOVF INDF1, w, ACCESS + # 0101 0000 1101 1111 -> MOVF INDF2, w, ACCESS # 0101 0010 0000 0000 -> MOVF DAT_DATA_0000, f, ACCESS # 0101 0011 0000 0000 -> MOVF REG0x0, f, BANKED # 0101 0010 1101 1000 -> MOVF STATUS, f, ACCESS # 0101 0011 1101 1000 -> MOVF REG0xD8, f, BANKED - - # 0101 0000 1110 1111 -> MOVF INDF0, w, ACCESS - # 0101 0000 1110 0111 -> MOVF INDF1, w, ACCESS - # 0101 0000 1101 1111 -> MOVF INDF2, w, ACCESS - + build destREG; + build srcREG; tmp:1 = srcREG; destREG = tmp; setResultFlags(tmp); @@ -967,7 +1100,7 @@ A: "BANKED" is a=1 { } setResultFlags(tmp); } -:RLCF srcREG, D, A is op6=0x0d & srcREG & destREG & D & A { +:RLCF srcREG, destREG, A is op6=0x0d & srcREG & destREG & A { # 0011 01da ffff ffff # 0011 0100 0000 0000 -> RLCF DAT_DATA_0000, w, ACCESS # 0011 0101 0000 0000 -> RLCF REG0x0, w, BANKED @@ -977,6 +1110,8 @@ A: "BANKED" is a=1 { } # 0011 0111 0000 0000 -> RLCF REG0x0, f, BANKED # 0011 0110 1101 1000 -> RLCF STATUS, f, ACCESS # 0011 0111 1101 1000 -> RLCF REG0xD8, f, BANKED + build destREG; + build srcREG; local tmpC = C & 1; tmp:1 = srcREG; C = (tmp s< 0); @@ -985,7 +1120,7 @@ A: "BANKED" is a=1 { } setResultFlags(tmp); } -:RLNCF srcREG, D, A is op6=0x11 & srcREG & destREG & D & A { +:RLNCF srcREG, destREG, A is op6=0x11 & srcREG & destREG & A { # 0100 01da ffff ffff # 0100 0100 0000 0000 -> RLNCF DAT_DATA_0000, w, ACCESS # 0100 0101 0000 0000 -> RLNCF REG0x0, w, BANKED @@ -995,12 +1130,14 @@ A: "BANKED" is a=1 { } # 0100 0111 0000 0000 -> RLNCF REG0x0, f, BANKED # 0100 0110 1101 1000 -> RLNCF STATUS, f, ACCESS # 0100 0111 1101 1000 -> RLNCF REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = srcREG << 1; destREG = tmp; setResultFlags(tmp); } -:RRCF srcREG, D, A is op6=0x0c & srcREG & destREG & D & A { +:RRCF srcREG, destREG, A is op6=0x0c & srcREG & destREG & A { # 0011 00da ffff ffff # 0011 0000 0000 0000 -> RRCF DAT_DATA_0000, w, ACCESS # 0011 0001 0000 0000 -> RRCF REG0x0, w, BANKED @@ -1010,6 +1147,8 @@ A: "BANKED" is a=1 { } # 0011 0011 0000 0000 -> RRCF REG0x0, f, BANKED # 0011 0010 1101 1000 -> RRCF STATUS, f, ACCESS # 0011 0011 1101 1000 -> RRCF REG0xD8, f, BANKED + build destREG; + build srcREG; local tmpC = C << 7; tmp:1 = srcREG; C = (tmp & 1); @@ -1018,16 +1157,14 @@ A: "BANKED" is a=1 { } setResultFlags(tmp); } -:RRNCF srcREG, D, A is op6=0x10 & srcREG & destREG & D & A { +:RRNCF srcREG, destREG, A is op6=0x10 & srcREG & destREG & A { # 0100 00da ffff ffff # 0100 0000 0000 0000 -> RRNCF DAT_DATA_0000, w, ACCESS # 0100 0001 0000 0000 -> RRNCF REG0x0, w, BANKED # 0100 0000 1101 1000 -> RRNCF STATUS, w, ACCESS # 0100 0001 1101 1000 -> RRNCF REG0xD8, w, BANKED - # 0100 0010 0000 0000 -> RRNCF DAT_DATA_0000, f, ACCESS - # 0100 0011 0000 0000 -> RRNCF REG0x0, f, BANKED - # 0100 0010 1101 1000 -> RRNCF STATUS, f, ACCESS - # 0100 0011 1101 1000 -> RRNCF REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = srcREG >> 1; destREG = tmp; setResultFlags(tmp); @@ -1042,7 +1179,7 @@ A: "BANKED" is a=1 { } srcREG = 0xff; } -:SUBFWB srcREG, D, A is op6=0x15 & srcREG & destREG & D & A { +:SUBFWB srcREG, destREG, A is op6=0x15 & srcREG & destREG & A { # 0101 01da ffff ffff # 0101 0100 0000 0000 -> SUBFWB DAT_DATA_0000, w, ACCESS # 0101 0101 0000 0000 -> SUBFWB REG0x0, w, BANKED @@ -1052,6 +1189,8 @@ A: "BANKED" is a=1 { } # 0101 0111 0000 0000 -> SUBFWB REG0x0, f, BANKED # 0101 0110 1101 1000 -> SUBFWB STATUS, f, ACCESS # 0101 0111 1101 1000 -> SUBFWB REG0xD8, f, BANKED + build destREG; + build srcREG; local notC = ~(C & 1); tmp:1 = srcREG; setSubtractCFlags(WREG, tmp); @@ -1060,7 +1199,7 @@ A: "BANKED" is a=1 { } setResultFlags(tmp); } -:SUBWF srcREG, D, A is op6=0x17 & srcREG & destREG & D & A { +:SUBWF srcREG, destREG, A is op6=0x17 & srcREG & destREG & A { # 0101 11da ffff ffff # 0101 1100 0000 0000 -> SUBWF DAT_DATA_0000, w, ACCESS # 0101 1101 0000 0000 -> SUBWF REG0x0, w, BANKED @@ -1070,6 +1209,8 @@ A: "BANKED" is a=1 { } # 0101 1111 0000 0000 -> SUBWF REG0x0, f, BANKED # 0101 1110 1101 1000 -> SUBWF STATUS, f, ACCESS # 0101 1111 1101 1000 -> SUBWF REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = srcREG; setSubtractFlags(tmp, WREG); tmp = tmp - WREG; @@ -1077,7 +1218,7 @@ A: "BANKED" is a=1 { } setResultFlags(tmp); } -:SUBWFB srcREG, D, A is op6=0x16 & srcREG & destREG & D & A { +:SUBWFB srcREG, destREG, A is op6=0x16 & srcREG & destREG & A { # 0101 10da ffff ffff # 0101 1000 0000 0000 -> SUBWFB DAT_DATA_0000, w, ACCESS # 0101 1001 0000 0000 -> SUBWFB REG0x0, w, BANKED @@ -1087,6 +1228,8 @@ A: "BANKED" is a=1 { } # 0101 1011 0000 0000 -> SUBWFB REG0x0, f, BANKED # 0101 1010 1101 1000 -> SUBWFB STATUS, f, ACCESS # 0101 1011 1101 1000 -> SUBWFB REG0xD8, f, BANKED + build destREG; + build srcREG; local notC = ~(C & 1); tmp:1 = srcREG; setSubtractCFlags(tmp, WREG); @@ -1095,7 +1238,7 @@ A: "BANKED" is a=1 { } setResultFlags(tmp); } -:SWAPF srcREG, D, A is op6=0x0e & srcREG & destREG & D & A { +:SWAPF srcREG, destREG, A is op6=0x0e & srcREG & destREG & A { # 0011 10da ffff ffff # 0011 1000 0000 0000 -> SWAPF DAT_DATA_0000, w, ACCESS # 0011 1001 0000 0000 -> SWAPF REG0x0, w, BANKED @@ -1105,8 +1248,10 @@ A: "BANKED" is a=1 { } # 0011 1011 0000 0000 -> SWAPF REG0x0, f, BANKED # 0011 1010 1101 1000 -> SWAPF STATUS, f, ACCESS # 0011 1011 1101 1000 -> SWAPF REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = srcREG; - destREG = (tmp << 4) | (tmp >> 4); + destREG = (tmp << 4) | (tmp >> 4); } :TSTFSZ srcREG, A is op6=0x19 & d=0x1 & srcREG & A & skipInst { @@ -1118,7 +1263,7 @@ A: "BANKED" is a=1 { } if (srcREG == 0) goto skipInst; } -:XORWF srcREG, D, A is op6=0x06 & srcREG & destREG & D & A { +:XORWF srcREG, destREG, A is op6=0x06 & srcREG & destREG & A { # 0001 10da ffff ffff # 0001 1000 0000 0000 -> XORWF DAT_DATA_0000, w, ACCESS # 0001 1001 0000 0000 -> XORWF REG0x0, w, BANKED @@ -1128,6 +1273,8 @@ A: "BANKED" is a=1 { } # 0001 1011 0000 0000 -> XORWF REG0x0, f, BANKED # 0001 1010 1101 1000 -> XORWF STATUS, f, ACCESS # 0001 1011 1101 1000 -> XORWF REG0xD8, f, BANKED + build destREG; + build srcREG; tmp:1 = WREG ^ srcREG; destREG = tmp; setResultFlags(tmp); diff --git a/Ghidra/Processors/PowerPC/data/languages/altivec.sinc b/Ghidra/Processors/PowerPC/data/languages/altivec.sinc index 720a3df089..2acecf52b0 100644 --- a/Ghidra/Processors/PowerPC/data/languages/altivec.sinc +++ b/Ghidra/Processors/PowerPC/data/languages/altivec.sinc @@ -381,11 +381,10 @@ vaddubm_part2: is vrA_8_8 & vrA_8_9 & vrA_8_10 & vrA_8_11 & vrA_8_12 & vrA_8_13 vrD_32_3 = vrA_32_3 + vrB_32_3; } -# Collides with vadduws -# :vadduws vrD,vrA,vrB is OP=4 & vrD & vrA & vrB & XOP_0_10=640 -# { # TODO definition -# vrD = vectorAddUnsignedWordSaturate(vrA,vrB); -# } +:vadduws vrD,vrA,vrB is OP=4 & vrD & vrA & vrB & XOP_0_10=640 +{ # TODO definition + vrD = vectorAddUnsignedWordSaturate(vrA,vrB); +} :vand vrD,vrA,vrB is OP=4 & vrD & vrA & vrB & XOP_0_10=1028 { # TODO definition diff --git a/Ghidra/Processors/Xtensa/data/languages/flix.sinc b/Ghidra/Processors/Xtensa/data/languages/flix.sinc index f012f83992..c03e07bc9c 100644 --- a/Ghidra/Processors/Xtensa/data/languages/flix.sinc +++ b/Ghidra/Processors/Xtensa/data/languages/flix.sinc @@ -4,6 +4,7 @@ # 16 bytes. Customizable, if found they should be flagged. define pcodeop flix; -:FLIX u_4_23 is op0=0xe & u_4_23 { +# Care probably needs to be taken here with BE support if any FLIX instructions are ever defined +:FLIX flix_i20 is op0=0xe & flix_i20 { flix(); } \ No newline at end of file diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensaArch.sinc b/Ghidra/Processors/Xtensa/data/languages/xtensaArch.sinc index a8d8d82cfb..fa03ef3983 100644 --- a/Ghidra/Processors/Xtensa/data/languages/xtensaArch.sinc +++ b/Ghidra/Processors/Xtensa/data/languages/xtensaArch.sinc @@ -108,6 +108,8 @@ define token insn(24) ar = (8,11) fr = (8,11) br = (8,11) + mw = (8,9) + mx = (10,10) as = (12,15) fs = (12,15) bs = (12,15) @@ -115,45 +117,42 @@ define token insn(24) at = (16,19) ft = (16,19) bt = (16,19) + my = (18,18) op0 = (20,23) - # Signed and unsigned immediates. Named [us]N_L.M, where u and s denote signedness, L and M the - # least and most significant bit of the immediate in the instruction word, and N the length - # (i.e. M-L+1). - u3_21_23 = (1,3) - u4_20_23 = (0,3) - s8_16_23 = (0,7) signed - u8_16_23 = (0,7) - u12_12_23 = (0,11) - s12_12_23 = (0,11) signed - u16_8_23 = (0,15) - s8_6_23 = (0,17) signed - u1_20 = (0,0) - u2_18_19 = (4,5) - u3_17_19 = (5,7) - u2_16_17 = (6,7) - u1_16 = (4,4) - u1_15_15 = (11,11) - u2_14_15 = (10,11) - u3_13_15 = (9,11) - u4_12_15 = (8,11) - m0m1_14_14 = (10,10) - u2_12_13 = (8,9) - mw_12_13 = (8,9) - u1_12 = (8,8) - u4_8_11 = (12,15) - u8_4_11 = (12,19) - s4_8_11 = (12,15) signed - u1_7_7 = (19,19) - u2_6_7 = (16,17) - u3_5_7 = (17,19) - u4_4_7 = (16,19) - s4_4_7 = (16,19) - m2m3_6_6 = (18,18) - u_4_23 = (0,19) - t2_4_5 = (16,17) - u2_4_5 = (18,19) - u1_4 = (16,16) + op2_1_3 = (1,3) + op2_0 = (0,0) + ri8_i8 = (0,7) + ri8_si8 = (0,7) signed + bri12_i12 = (0,11) + bri12_si12 = (0,11) signed + ri16_i16 = (0,15) + call_o18 = (0,17) signed + op1_1_3 = (5,7) + op1_0 = (4,4) + op_r_3 = (11,11) + op_r_2_2 = (10,11) + op_r_1_3 = (9,11) + op_r_0_2 = (8,9) + op_r_0 = (8,8) + op_r = (8,11) + op_s = (12,15) + op_st = (12,19) + op_st_i8 = (12,15) signed + op_t_3 = (19,19) + op_t_1_3 = (17,19) + op_t_0_2 = (16,17) + op_t = (16,19) + op_t_0 = (16,16) + op_t_si4 = (16,19) signed + + # If flix instructions are defined for a BE processor + # this will possibly need to be split for the operands + flix_i20 = (0,19) + + # Care needs to be taken with these for BE + bri8_n = (18,19) + bri8_m = (16,17) ; # little-endian -> big-endian 16-bit conversion chart @@ -167,14 +166,14 @@ define token narrowinsn(16) n_at = (8,11) n_op0 = (12,15) - n_u4_12_15 = (0,3) - n_s4_12_15 = (0,3) signed - n_u4_8_11 = (4,7) - n_u1_7 = (11,11) - n_u2_6_7 = (10,11) - n_u4_4_7 = (8,11) - n_s3_4_6 = (8,10) - n_u2_4_5 = (8,9) + ri6_i6_0_4 = (0,3) + ri6_si6_0_4 = (0,3) signed + n_op_t = (4,7) + n_op_s_3 = (11,11) + n_op_s_2_2 = (10,11) + n_op_s = (8,11) + n_op_s_0_3 = (8,10) + ri6_i6_4_2 = (8,9) ; @else @@ -182,9 +181,12 @@ define token narrowinsn(16) define token insn(24) # Named opcode/register fields. op2 = (20,23) + op1 = (16,19) ar = (12,15) fr = (12,15) br = (12,15) + mw = (12,13) + mx = (14,14) as = (8,11) fs = (8,11) bs = (8,11) @@ -192,46 +194,40 @@ define token insn(24) at = (4,7) ft = (4,7) bt = (4,7) - op1 = (16,19) + my = (6,6) op0 = (0,3) # Signed and unsigned immediates. Named [us]N_L_M, where u and s denote signedness, L and M the # least and most significant bit of the immediate in the instruction word, and N the length # (i.e. M-L+1). - u3_21_23 = (21,23) - u4_20_23 = (20,23) - s8_16_23 = (16,23) signed - u8_16_23 = (16,23) - u12_12_23 = (12,23) - s12_12_23 = (12,23) signed - u16_8_23 = (8,23) - s8_6_23 = (6,23) signed - u1_20 = (20,20) - u2_18_19 = (18,19) - u3_17_19 = (17,19) - u2_16_17 = (16,17) - u1_16 = (16,16) - u1_15_15 = (15,15) - u2_14_15 = (14,15) - u3_13_15 = (13,15) - u4_12_15 = (12,15) - m0m1_14_14 = (14,14) - u2_12_13 = (12,13) - mw_12_13 = (12,13) - u1_12 = (12,12) - u4_8_11 = (8,11) - u8_4_11 = (4,11) - s4_8_11 = (8,11) signed - u1_7_7 = (7,7) - u2_6_7 = (6,7) - u3_5_7 = (5,7) - u4_4_7 = (4,7) - s4_4_7 = (4,7) - m2m3_6_6 = (6,6) - u_4_23 = (4,23) - t2_4_5 = (4,5) - u2_4_5 = (4,5) - u1_4 = (4,4) + op2_1_3 = (21,23) + op2_0 = (20,20) + ri8_i8 = (16,23) + ri8_si8 = (16,23) signed + bri12_i12 = (12,23) + bri12_si12 = (12,23) signed + ri16_i16 = (8,23) + call_o18 = (6,23) signed + op1_1_3 = (17,19) + op1_0 = (16,16) + op_r_3 = (15,15) + op_r_2_2 = (14,15) + op_r_1_3 = (13,15) + op_r_0_2 = (12,13) + op_r_0 = (12,12) + op_r = (12,15) + op_s = (8,11) + op_st = (4,11) + op_st_i8 = (8,11) signed + op_t_3 = (7,7) + op_t_1_3 = (5,7) + op_t_0_2 = (4,5) + op_t_0 = (4,4) + op_t = (4,7) + op_t_si4 = (4,7) signed + flix_i20 = (4,23) + bri8_n = (4,5) + bri8_m = (6,7) ; # Narrow 16-bit instructions; fields are always prefixed with n_. @@ -241,14 +237,14 @@ define token narrowinsn(16) n_at = (4,7) n_op0 = (0, 3) - n_u4_12_15 = (12,15) - n_s4_12_15 = (12,15) signed - n_u4_8_11 = (8,11) - n_u1_7 = (7,7) - n_u2_6_7 = (6,7) - n_u4_4_7 = (4,7) - n_s3_4_6 = (4,6) - n_u2_4_5 = (4,5) + ri6_i6_0_4 = (12,15) + ri6_si6_0_4 = (12,15) signed + n_op_t = (8,11) + n_op_s_3 = (7,7) + n_op_s_2_2 = (6,7) + n_op_s = (4,7) + n_op_s_0_3 = (4,6) + ri6_i6_4_2 = (4,5) ; @endif diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensaInstructions.sinc b/Ghidra/Processors/Xtensa/data/languages/xtensaInstructions.sinc index f7e2d391c6..f06e61937a 100644 --- a/Ghidra/Processors/Xtensa/data/languages/xtensaInstructions.sinc +++ b/Ghidra/Processors/Xtensa/data/languages/xtensaInstructions.sinc @@ -29,8 +29,8 @@ } # ADDI - Add Immediate (RRI8), pg. 251. -:addi at, as, s8_16_23 is s8_16_23 & ar = 0b1100 & as & at & op0 = 0b0010 { - at = as + s8_16_23; +:addi at, as, ri8_si8 is ri8_si8 & ar = 0b1100 & as & at & op0 = 0b0010 { + at = as + ri8_si8; } # ADDI.N - Narrow Add Immediate (RRRN), pg. 252. @@ -38,27 +38,27 @@ n_ar = n_as + n_s4_4_7_nozero; } -# ADDMI - Add Immediate with Shift by 8, pg. 253. -:addmi at, as, s16_16_23_sb8 is s16_16_23_sb8 & ar = 0b1101 & as & at & op0 = 0b0010 { - at = as + s16_16_23_sb8; +# ADDMI - Add Immediate with Shift by 8 (RRI8), pg. 253. +:addmi at, as, ri8_si8_sh8 is ri8_si8_sh8 & ar = 0b1101 & as & at & op0 = 0b0010 { + at = as + ri8_si8_sh8; } -# ADDX2 - Add with Shift by 1, pg. 254. +# ADDX2 - Add with Shift by 1 (RRR), pg. 254. :addx2 ar, as, at is op2 = 0b1001 & op1 = 0 & ar & as & at & op0 = 0 { ar = (as << 1) + at; } -# ADDX4 - Add with Shift by 2, pg. 255. +# ADDX4 - Add with Shift by 2 (RRR), pg. 255. :addx4 ar, as, at is op2 = 0b1010 & op1 = 0 & ar & as & at & op0 = 0 { ar = (as << 2) + at; } -# ADDX8 - Add with Shift by 4, pg. 256. +# ADDX8 - Add with Shift by 4 (RRR), pg. 256. :addx8 ar, as, at is op2 = 0b1011 & op1 = 0 & ar & as & at & op0 = 0 { ar = (as << 3) + at; } -# ALL4 - All 4 Booleans True, pg. 257. +# ALL4 - All 4 Booleans True (RRR), pg. 257. :all4 bt, bs is op2 = 0 & op1 = 0 & ar = 0b1001 & bs & bt & op0 = 0 { local b = *[register]:1 &:4 bs+1; local c = *[register]:1 &:4 bs+2; @@ -66,7 +66,7 @@ bt = bs && b && c && d; } -# ALL8 - All 8 Booleans True, pg. 258. +# ALL8 - All 8 Booleans True (RRR), pg. 258. :all8 bt, bs is op2 = 0 & op1 = 0 & ar = 0b1011 & bs & bt & op0 = 0 { local b = *[register]:1 &:4 bs+1; local c = *[register]:1 &:4 bs+2; @@ -78,22 +78,22 @@ bt = bs && b && c && d && e && f && g && h; } -# AND - Bitwise Logical And, pg. 259. +# AND - Bitwise Logical And (RRR), pg. 259. :and ar, as, at is op2 = 0b0001 & op1 = 0 & ar & as & at & op0 = 0 { ar = as & at; } -# ANDB - Boolean And, pg. 260. +# ANDB - Boolean And (RRR), pg. 260. :andb br, bs, bt is op2 = 0 & op1 = 0b0010 & br & bs & bt & op0 = 0 { br = bs && bt; } -# ANDBC - Boolean And with Complement, pg. 261. +# ANDBC - Boolean And with Complement (RRR), pg. 261. :andbc br, bs, bt is op2 = 0b0001 & op1 = 0b0010 & br & bs & bt & op0 = 0 { br = bs && !bt; } -# ANY4 - Any 4 Booleans True, pg. 262. +# ANY4 - Any 4 Booleans True (RRR), pg. 262. :any4 bt, bs is op2 = 0 & op1 = 0 & ar = 0b1000 & bs & bt & op0 = 0 { local b = *[register]:1 &:4 bs+1; local c = *[register]:1 &:4 bs+2; @@ -101,7 +101,7 @@ bt = bs || b || c || d; } -# ANY8 - Any 8 Booleans True, pg. 263. +# ANY8 - Any 8 Booleans True (RRR), pg. 263. :any8 bt, bs is op2 = 0 & op1 = 0 & ar = 0b1010 & bs & bt & op0 = 0 { local b = *[register]:1 &:4 bs+1; local c = *[register]:1 &:4 bs+2; @@ -113,16 +113,16 @@ bt = bs || b || c || d || e || f || g || h; } -# BALL - Branch if All Bits Set, pg. 264. -:ball srel_16_23, as, at is srel_16_23 & ar = 0b0100 & as & at & op0 = 0b0111 { +# BALL - Branch if All Bits Set (RRI8), pg. 264. +:ball ri8_srel, as, at is ri8_srel & ar = 0b0100 & as & at & op0 = 0b0111 { local test:4 = ~as & at; - if (test == 0) goto srel_16_23; + if (test == 0) goto ri8_srel; } -# BANY - Branch if Any Bit Set, pg. 265. -:bany srel_16_23, as, at, is srel_16_23 & ar = 0b1000 & as & at & op0 = 0b0111 { +# BANY - Branch if Any Bit Set (RRI8), pg. 265. +:bany ri8_srel, as, at, is ri8_srel & ar = 0b1000 & as & at & op0 = 0b0111 { local test:4 = as & at; - if (test != 0) goto srel_16_23; + if (test != 0) goto ri8_srel; } macro extract_bit(bit, result) { @@ -133,230 +133,230 @@ macro extract_bit(bit, result) { @endif } -# BBC - Branch if Bit Clear, pg. 266. -:bbc as, at, srel_16_23 is srel_16_23 & ar = 0b0101 & as & at & op0 = 0b0111 { +# BBC - Branch if Bit Clear (RRR), pg. 266. +:bbc as, at, ri8_srel is ri8_srel & ar = 0b0101 & as & at & op0 = 0b0111 { local bval:4 = 0; extract_bit(at[0,5], bval); bval = as & bval; if (bval == 0) - goto srel_16_23; + goto ri8_srel; } -# BBCI - Branch if Bit Clear immediate, pg. 267 -:bbci as, u5_4_7_12, srel_16_23 is srel_16_23 & u3_13_15 = 0b011 & as & u5_4_7_12 & op0 = 0b0111 { +# BBCI - Branch if Bit Clear immediate (RRI8), pg. 267 +:bbci as, u5_4_7_12, ri8_srel is ri8_srel & op_r_1_3 = 0b011 & as & u5_4_7_12 & op0 = 0b0111 { local bval; extract_bit(u5_4_7_12, bval); bval = as & bval; if (bval == 0) - goto srel_16_23; + goto ri8_srel; } -# BBS - Branch if Bit Set, pg. 269. -:bbs as, at, srel_16_23 is srel_16_23 & ar = 0b1101 & as & at & op0 = 0b0111 { +# BBS - Branch if Bit Set (RRI8), pg. 269. +:bbs as, at, ri8_srel is ri8_srel & ar = 0b1101 & as & at & op0 = 0b0111 { local bval; extract_bit(at[0,5], bval); bval = as & bval; if (bval != 0) - goto srel_16_23; + goto ri8_srel; } -# BBSI - Branch if Bit Set immediate, pg. 270. -:bbsi as, u5_4_7_12, srel_16_23 is srel_16_23 & u3_13_15 = 0b111 & as & u5_4_7_12 & op0 = 0b0111 { +# BBSI - Branch if Bit Set immediate (RRI8), pg. 270. +:bbsi as, u5_4_7_12, ri8_srel is ri8_srel & op_r_1_3 = 0b111 & as & u5_4_7_12 & op0 = 0b0111 { local bval; extract_bit(u5_4_7_12, bval); bval = as & bval; if (bval != 0) - goto srel_16_23; + goto ri8_srel; } -# BEQ - Branch if Equal, pg. 272. -:beq as, at, srel_16_23 is srel_16_23 & ar = 0b0001 & as & at & op0 = 0b0111 { +# BEQ - Branch if Equal (RRI8), pg. 272. +:beq as, at, ri8_srel is ri8_srel & ar = 0b0001 & as & at & op0 = 0b0111 { if (as == at) - goto srel_16_23; + goto ri8_srel; } -# BEQI - Branch if Equal Immediate, pg. 273. -:beqi as, r_b4const, srel_16_23 is srel_16_23 & r_b4const & as & u2_6_7 = 0 & u2_4_5 = 0b10 & op0 = 0b0110 { +# BEQI - Branch if Equal Immediate (BRI8), pg. 273. +:beqi as, r_b4const, ri8_srel is ri8_srel & r_b4const & as & bri8_m = 0 & bri8_n = 0b10 & op0 = 0b0110 { if (as == r_b4const) - goto srel_16_23; + goto ri8_srel; } -# BEQZ - Branch if Equal Zero, pg. 274. -:beqz as, srel_12_23 is srel_12_23 & as & u2_6_7 = 0 & u2_4_5 = 0b01 & op0 = 0b0110 { +# BEQZ - Branch if Equal Zero (BRI12), pg. 274. +:beqz as, bri12_srel is bri12_srel & as & bri8_m = 0 & bri8_n = 0b01 & op0 = 0b0110 { if (as == 0) - goto srel_12_23; + goto bri12_srel; } -# BEQZ.N - Narrow Branch if Equal Zero, pg. 275. -:beqz.n n_as, urel_12_15_4_5 is urel_12_15_4_5 & n_as & n_u2_6_7 = 0b10 & n_op0 = 0b1100 { +# BEQZ.N - Narrow Branch if Equal Zero (RI6), pg. 275. +:beqz.n n_as, ri6_rel is ri6_rel & n_as & n_op_s_2_2 = 0b10 & n_op0 = 0b1100 { if (n_as == 0) - goto urel_12_15_4_5; + goto ri6_rel; } -# BF - Branch if False, pg. 276. -:bf bs, srel_16_23 is srel_16_23 & ar = 0 & bs & at = 0b0111 & op0 = 0b0110 { +# BF - Branch if False (RRI8), pg. 276. +:bf bs, ri8_srel is ri8_srel & ar = 0 & bs & at = 0b0111 & op0 = 0b0110 { if (!bs) - goto srel_16_23; + goto ri8_srel; } -# BGE - Branch if Greater Than or Equal, pg. 277. -:bge as, at, srel_16_23 is srel_16_23 & ar = 0b1010 & as & at & op0 = 0b0111 { +# BGE - Branch if Greater Than or Equal (RRI8), pg. 277. +:bge as, at, ri8_srel is ri8_srel & ar = 0b1010 & as & at & op0 = 0b0111 { if (as s>= at) - goto srel_16_23; + goto ri8_srel; } -# BGEI - Branch if Greater Than or Equal Immediate, pg. 278. -:bgei as, r_b4const, srel_16_23 is srel_16_23 & r_b4const & as & u2_6_7 = 0b11 & u2_4_5 = 0b10 & op0 = 0b0110 { +# BGEI - Branch if Greater Than or Equal Immediate (BRI8), pg. 278. +:bgei as, r_b4const, ri8_srel is ri8_srel & r_b4const & as & bri8_m = 0b11 & bri8_n = 0b10 & op0 = 0b0110 { if (as s>= r_b4const) - goto srel_16_23; + goto ri8_srel; } -# BGEU - Branch if Greater Than or Equal Unsigned, pg. 279. -:bgeu as, at, srel_16_23 is srel_16_23 & ar = 0b1011 & as & at & op0 = 0b0111 { +# BGEU - Branch if Greater Than or Equal Unsigned (RRI8), pg. 279. +:bgeu as, at, ri8_srel is ri8_srel & ar = 0b1011 & as & at & op0 = 0b0111 { if (as >= at) - goto srel_16_23; + goto ri8_srel; } -# BGEUI - Branch if Greater Than or Equal Unsigned Immediate, pg. 280. -:bgeui as, r_b4constu, srel_16_23 is srel_16_23 & r_b4constu & as & u2_6_7 = 0b11 & u2_4_5 = 0b11 & op0 = 0b0110 { +# BGEUI - Branch if Greater Than or Equal Unsigned Immediate (BRI8), pg. 280. +:bgeui as, r_b4constu, ri8_srel is ri8_srel & r_b4constu & as & bri8_m = 0b11 & bri8_n = 0b11 & op0 = 0b0110 { if (as >= r_b4constu) - goto srel_16_23; + goto ri8_srel; } -# BGEZ - Branch if Greater Than or Equal Zero, pg. 281. -:bgez as, srel_12_23 is srel_12_23 & as & u2_6_7 = 0b11 & u2_4_5 = 0b01 & op0 = 0b0110 { +# BGEZ - Branch if Greater Than or Equal Zero (BRI12), pg. 281. +:bgez as, bri12_srel is bri12_srel & as & bri8_m = 0b11 & bri8_n = 0b01 & op0 = 0b0110 { if (as s>= 0) - goto srel_12_23; + goto bri12_srel; } -# BLT - Branch if Less Than, pg. 282. -:blt as, at, srel_16_23 is srel_16_23 & ar = 0b0010 & as & at & op0 = 0b0111 { +# BLT - Branch if Less Than (RRI8), pg. 282. +:blt as, at, ri8_srel is ri8_srel & ar = 0b0010 & as & at & op0 = 0b0111 { if (as s< at) - goto srel_16_23; + goto ri8_srel; } -# BLTI - Branch if Less Than Immediate, pg. 283. -:blti as, r_b4const, srel_16_23 is srel_16_23 & r_b4const & as & u2_6_7 = 0b10 & u2_4_5 = 0b10 & op0 = 0b0110 { +# BLTI - Branch if Less Than Immediate (BRI8), pg. 283. +:blti as, r_b4const, ri8_srel is ri8_srel & r_b4const & as & bri8_m = 0b10 & bri8_n = 0b10 & op0 = 0b0110 { if (as s< r_b4const) - goto srel_16_23; + goto ri8_srel; } -# BLTU - Branch if Less Than Unsigned, pg. 284. -:bltu as, at, srel_16_23 is srel_16_23 & ar = 0b0011 & as & at & op0 = 0b0111 { +# BLTU - Branch if Less Than Unsigned (RRI8), pg. 284. +:bltu as, at, ri8_srel is ri8_srel & ar = 0b0011 & as & at & op0 = 0b0111 { if (as < at) - goto srel_16_23; + goto ri8_srel; } -# BLTUI - Branch if Less Than Unsigned Immediate, pg. 285. -:bltui as, r_b4constu, srel_16_23 is srel_16_23 & r_b4constu & as & u2_6_7 = 0b10 & u2_4_5 = 0b11 & op0 = 0b0110 { +# BLTUI - Branch if Less Than Unsigned Immediate (BRI8), pg. 285. +:bltui as, r_b4constu, ri8_srel is ri8_srel & r_b4constu & as & bri8_m = 0b10 & bri8_n = 0b11 & op0 = 0b0110 { if (as < r_b4constu) - goto srel_16_23; + goto ri8_srel; } -# BLTZ - Branch if Less Than Zero, pg. 286. -:bltz as, srel_12_23 is srel_12_23 & as & u2_6_7 = 0b10 & u2_4_5 = 0b01 & op0 = 0b0110 { +# BLTZ - Branch if Less Than Zero (BRI12), pg. 286. +:bltz as, bri12_srel is bri12_srel & as & bri8_m = 0b10 & bri8_n = 0b01 & op0 = 0b0110 { if (as s< 0) - goto srel_12_23; + goto bri12_srel; } -# BNALL - Branch if Not-All Bits Set, pg. 287. -:bnall srel_16_23, as, at is srel_16_23 & ar = 0b1100 & as & at & op0 = 0b0111 { +# BNALL - Branch if Not-All Bits Set (RRI8), pg. 287. +:bnall ri8_srel, as, at is ri8_srel & ar = 0b1100 & as & at & op0 = 0b0111 { if ((~as & at) != 0) - goto srel_16_23; + goto ri8_srel; } -# BNE - Branch if Not Equal, pg. 288. -:bne as, at, srel_16_23 is srel_16_23 & ar = 0b1001 & as & at & op0 = 0b0111 { +# BNE - Branch if Not Equal (RRI8), pg. 288. +:bne as, at, ri8_srel is ri8_srel & ar = 0b1001 & as & at & op0 = 0b0111 { if (as != at) - goto srel_16_23; + goto ri8_srel; } -# BNEI - Branch if Not EquaL Immediate, pg. 289. -:bnei as, r_b4const, srel_16_23 is srel_16_23 & r_b4const & as & u2_6_7 = 0b01 & u2_4_5 = 0b10 & op0 = 0b0110 { +# BNEI - Branch if Not EquaL Immediate (BRI8), pg. 289. +:bnei as, r_b4const, ri8_srel is ri8_srel & r_b4const & as & bri8_m = 0b01 & bri8_n = 0b10 & op0 = 0b0110 { if (as != r_b4const) - goto srel_16_23; + goto ri8_srel; } -# BNEZ - Branch if Not Equal Zero, pg. 290. -:bnez as, srel_12_23 is srel_12_23 & as & u2_6_7 = 0b01 & u2_4_5 = 0b01 & op0 = 0b0110 { +# BNEZ - Branch if Not Equal Zero (BRI12), pg. 290. +:bnez as, bri12_srel is bri12_srel & as & bri8_m = 0b01 & bri8_n = 0b01 & op0 = 0b0110 { if (as != 0) - goto srel_12_23; + goto bri12_srel; } -# BNEZ.N - Narrow Branch if Not Equal Zero, pg. 291. -:bnez.n n_as, urel_12_15_4_5 is urel_12_15_4_5 & n_as & n_u2_6_7 = 0b11 & n_op0 = 0b1100 { +# BNEZ.N - Narrow Branch if Not Equal Zero (RI6), pg. 291. +:bnez.n n_as, ri6_rel is ri6_rel & n_as & n_op_s_2_2 = 0b11 & n_op0 = 0b1100 { if (n_as != 0) - goto urel_12_15_4_5; + goto ri6_rel; } -# BNONE - Branch if No Bit Set, pg. 292. -:bnone srel_16_23, as, at, is srel_16_23 & ar = 0 & as & at & op0 = 0b0111 { +# BNONE - Branch if No Bit Set (RRI8), pg. 292. +:bnone ri8_srel, as, at, is ri8_srel & ar = 0 & as & at & op0 = 0b0111 { if ((as & at) == 0) - goto srel_16_23; + goto ri8_srel; } -# BREAK - Breakpoint, pg. 293. -:break u4_8_11, u4_4_7 is op2 = 0 & op1 = 0 & ar = 0b0100 & u4_8_11 & u4_4_7 & op0 = 0 { +# BREAK - Breakpoint (RRR), pg. 293. +:break op_s, op_t is op2 = 0 & op1 = 0 & ar = 0b0100 & op_s & op_t & op0 = 0 { break_inst:4 = inst_start; - breakpoint(0x001000:4, break_inst, u4_8_11:1, u4_4_7:1); + breakpoint(0x001000:4, break_inst, op_s:1, op_t:1); } -# BREAK.N - Narrow Breakpoint, pg. 295. -:break.n n_u4_8_11 is n_ar = 0b1111 & n_u4_8_11 & n_at = 0b0010 & n_op0 = 0b1101 { +# BREAK.N - Narrow Breakpoint (RRRN), pg. 295. +:break.n n_op_t is n_ar = 0b1111 & n_op_t & n_at = 0b0010 & n_op0 = 0b1101 { break_inst:4 = inst_start; - breakpoint(0x010000:4, break_inst, n_u4_8_11:1, 0:1); + breakpoint(0x010000:4, break_inst, n_op_t:1, 0:1); } -# BT - Branch if True, pg. 296. -:bt bs, srel_16_23 is srel_16_23 & ar = 0b0001 & bs & at = 0b0111 & op0 = 0b0110 { +# BT - Branch if True (RRI8), pg. 296. +:bt bs, ri8_srel is ri8_srel & ar = 0b0001 & bs & at = 0b0111 & op0 = 0b0110 { if (bs) - goto srel_16_23; + goto ri8_srel; } -# CALL0 - Non-windowed Call, pg. 297. -:call0 srel_6_23_sb2 is srel_6_23_sb2 & u2_4_5 = 0 & op0 = 0b0101 { +# CALL0 - Non-windowed Call (CALL), pg. 297. +:call0 call_srel_sh2 is call_srel_sh2 & bri8_n = 0 & op0 = 0b0101 { $(PS_CALLINC) = 0; a0 = inst_next; - call srel_6_23_sb2; + call call_srel_sh2; } -# CALL4 - Call PC-relative, Rotate Window by 4, pg. 298. -:call4 srel_6_23_sb2 is srel_6_23_sb2 & Ret4 & u2_4_5 = 0b01 & op0 = 0b0101 { +# CALL4 - Call PC-relative, Rotate Window by 4 (CALL), pg. 298. +:call4 call_srel_sh2 is call_srel_sh2 & Ret4 & bri8_n = 0b01 & op0 = 0b0101 { $(PS_CALLINC) = 1; a4 = Ret4; swap4(); - call srel_6_23_sb2; + call call_srel_sh2; restore4(); } -# CALL8 - Call PC-relative, Rotate Window by 8, pg. 300. -:call8 srel_6_23_sb2 is srel_6_23_sb2 & Ret8 & u2_4_5 = 0b10 & op0 = 0b0101 { +# CALL8 - Call PC-relative, Rotate Window by 8 (CALL), pg. 300. +:call8 call_srel_sh2 is call_srel_sh2 & Ret8 & bri8_n = 0b10 & op0 = 0b0101 { $(PS_CALLINC) = 2; a8 = Ret8; swap8(); - call srel_6_23_sb2; + call call_srel_sh2; restore8(); } -# CALL12 - Call PC-relative, Rotate Window by 12, pg. 302. -:call12 srel_6_23_sb2 is srel_6_23_sb2 & Ret12 & u2_4_5 = 0b11 & op0 = 0b0101 { +# CALL12 - Call PC-relative, Rotate Window by 12 (CALL), pg. 302. +:call12 call_srel_sh2 is call_srel_sh2 & Ret12 & bri8_n = 0b11 & op0 = 0b0101 { $(PS_CALLINC) = 3; a12 = Ret12; swap12(); - call srel_6_23_sb2; + call call_srel_sh2; restore12(); } -# CALLX0 - Non-windowed Call Register, pg. 304. -:callx0 as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6_7 = 0b11 & u2_4_5 = 0 & op0 = 0 { +# CALLX0 - Non-windowed Call Register (CALLX), pg. 304. +:callx0 as is op2 = 0 & op1 = 0 & ar = 0 & as & bri8_m = 0b11 & bri8_n = 0 & op0 = 0 { $(PS_CALLINC) = 0; local dst = as; a0 = inst_next; call [dst]; } -# CALLX4 - Call Register, Rotate Window by 4, pg. 305. -:callx4 as is op2 = 0 & op1 = 0 & ar = 0 & as & Ret4 & u2_6_7 = 0b11 & u2_4_5 = 0b01 & op0 = 0 { +# CALLX4 - Call Register, Rotate Window by 4 (CALLX), pg. 305. +:callx4 as is op2 = 0 & op1 = 0 & ar = 0 & as & Ret4 & bri8_m = 0b11 & bri8_n = 0b01 & op0 = 0 { $(PS_CALLINC) = 1; dest:4 = as; a4 = Ret4; @@ -365,8 +365,8 @@ macro extract_bit(bit, result) { restore4(); } -# CALLX8 - Call Register, Rotate Window by 8, pg. 307. -:callx8 as is op2 = 0 & op1 = 0 & ar = 0 & as & Ret8 & u2_6_7 = 0b11 & u2_4_5 = 0b10 & op0 = 0 { +# CALLX8 - Call Register, Rotate Window by 8 (CALLX), pg. 307. +:callx8 as is op2 = 0 & op1 = 0 & ar = 0 & as & Ret8 & bri8_m = 0b11 & bri8_n = 0b10 & op0 = 0 { $(PS_CALLINC) = 2; dest:4 = as; a8 = Ret8; @@ -375,8 +375,8 @@ macro extract_bit(bit, result) { restore8(); } -# CALLX12 - Call Register, Rotate Window by 12, pg. 308. -:callx12 as is op2 = 0 & op1 = 0 & ar = 0 & as & Ret12 & u2_6_7 = 0b11 & u2_4_5 = 0b11 & op0 = 0 { +# CALLX12 - Call Register, Rotate Window by 12 (CALLX), pg. 308. +:callx12 as is op2 = 0 & op1 = 0 & ar = 0 & as & Ret12 & bri8_m = 0b11 & bri8_n = 0b11 & op0 = 0 { $(PS_CALLINC) = 3; dest:4 = as; a12 = Ret12; @@ -385,13 +385,13 @@ macro extract_bit(bit, result) { restore12(); } -# CEIL.S - Ceiling Single to Fixed, pg. 311. -:ceil.s ar, fs, u4_4_7 is op2 = 0b1011 & op1 = 0b1010 & ar & fs & u4_4_7 & op0 = 0 { - local scale:4 = 1 << u4_4_7; +# CEIL.S - Ceiling Single to Fixed (RRR), pg. 311. +:ceil.s ar, fs, op_t is op2 = 0b1011 & op1 = 0b1010 & ar & fs & op_t & op0 = 0 { + local scale:4 = 1 << op_t; ar = ceil(fs f* int2float(scale)); } -# CLAMPS - Signed Clamp, pg. 312. +# CLAMPS - Signed Clamp (RRR), pg. 312. :clamps ar, as, u5_4_7_plus7 is op2 = 0b0011 & op1 = 0b0011 & ar & as & u5_4_7_plus7 & op0 = 0 { # ar min(max(as, -2^{u5_4_7_plus7}), 2^{u5_4_7_plus7}-1) local x:4 = as; @@ -402,457 +402,457 @@ macro extract_bit(bit, result) { ar = (zext(mt) * max) + (zext(!mt) * (clamp-1)); } -# DHI - Data Cache Hit Invalidate, pg. 313. -:dhi as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0111 & as & at = 0b0110 & op0 = 0b0010 { - dhi(as + u10_16_23_sb2); +# DHI - Data Cache Hit Invalidate (RRI8), pg. 313. +:dhi as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0111 & as & at = 0b0110 & op0 = 0b0010 { + dhi(as + ri8_i8_sh2); } -# DHU - Data Cache Hit Unlock, pg. 315. +# DHU - Data Cache Hit Unlock (RRI4), pg. 315. :dhu as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0b0010 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { dhu(as + u8_20_23_sb4); } -# DHWB - Data Cache Hit Writeback, pg. 317. -:dhwb as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0111 & as & at = 0b0100 & op0 = 0b0010 { - dhwb(as + u10_16_23_sb2); +# DHWB - Data Cache Hit Writeback (RRI8), pg. 317. +:dhwb as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0111 & as & at = 0b0100 & op0 = 0b0010 { + dhwb(as + ri8_i8_sh2); } -# DHWBI - Data Cache Hit Writeback Invalidate, pg. 319. -:dhwbi as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0111 & as & at = 0b0101 & op0 = 0b0010 { - dhwbi(as + u10_16_23_sb2); +# DHWBI - Data Cache Hit Writeback Invalidate (RRI8), pg. 319. +:dhwbi as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0111 & as & at = 0b0101 & op0 = 0b0010 { + dhwbi(as + ri8_i8_sh2); } -# DII - Data Cache Index Invalidate, pg. 321. -:dii as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0111 & as & at = 0b0111 & op0 = 0b0010 { - dii(as + u10_16_23_sb2); +# DII - Data Cache Index Invalidate (RRI8), pg. 321. +:dii as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0111 & as & at = 0b0111 & op0 = 0b0010 { + dii(as + ri8_i8_sh2); } -# DIU - Data Cache Index Unlock, pg. 323. +# DIU - Data Cache Index Unlock (RRI4), pg. 323. :diu as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0b0011 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { diu(as + u8_20_23_sb4); } -# DIWB - Data Cache Index Write Back, pg. 325. +# DIWB - Data Cache Index Write Back (RRI4), pg. 325. :diwb as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0b0100 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { diwb(as + u8_20_23_sb4); } -# DIWBI - Data Cache Index Write Back Invalidate, pg. 327. +# DIWBI - Data Cache Index Write Back Invalidate (RRI4), pg. 327. :diwbi as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0b0101 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { diwbi(as + u8_20_23_sb4); } -# DPFL - Data Cache Prefetch and Lock, pg. 329. +# DPFL - Data Cache Prefetch and Lock (RRI4), pg. 329. :dpfl as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0 & ar = 0b0111 & as & at = 0b1000 & op0 = 0b0010 { dpfl(as + u8_20_23_sb4); } -# DPFR - Data Cache Prefetch for Read, pg. 331. -:dpfr as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0111 & as & at = 0 & op0 = 0b0010 { - dpfr(as + u10_16_23_sb2); +# DPFR - Data Cache Prefetch for Read (RRI8), pg. 331. +:dpfr as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0111 & as & at = 0 & op0 = 0b0010 { + dpfr(as + ri8_i8_sh2); } -# DPFRO - Data Cache Prefetch for Read Once, pg. 333. -:dpfro as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0111 & as & at = 0b0010 & op0 = 0b0010 { - dpfro(as + u10_16_23_sb2); +# DPFRO - Data Cache Prefetch for Read Once (RRI8), pg. 333. +:dpfro as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0111 & as & at = 0b0010 & op0 = 0b0010 { + dpfro(as + ri8_i8_sh2); } -# DPFW - Data Cache Prefetch for Write, pg. 335. -:dpfw as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0111 & as & at = 0b0001 & op0 = 0b0010 { - dpfw(as + u10_16_23_sb2); +# DPFW - Data Cache Prefetch for Write (RRI8), pg. 335. +:dpfw as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0111 & as & at = 0b0001 & op0 = 0b0010 { + dpfw(as + ri8_i8_sh2); } -# DPFWO - Data Cache Prefetch for Write Once, pg. 337. -:dpfwo as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0111 & as & at = 0b0011 & op0 = 0b0010 { - dpfwo(as + u10_16_23_sb2); +# DPFWO - Data Cache Prefetch for Write Once (RRI8), pg. 337. +:dpfwo as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0111 & as & at = 0b0011 & op0 = 0b0010 { + dpfwo(as + ri8_i8_sh2); } -# DSYNC - Load/Store Synchronize, pg. 339. +# DSYNC - Load/Store Synchronize (RRR), pg. 339. :dsync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b0011 & op0 = 0 { dsync(); } -# ENTRY - Subroutine Entry, pg. 340. -:entry as, u15_12_23_sb3 is u15_12_23_sb3 & as & u2_6_7 = 0b00 & u2_4_5 = 0b11 & op0 = 0b0110 { +# ENTRY - Subroutine Entry (BRI12), pg. 340. +:entry as, bri12_i12_sh3 is bri12_i12_sh3 & as & bri8_m = 0b00 & bri8_n = 0b11 & op0 = 0b0110 { local callSP = a1; callinc:1 = $(PS_CALLINC); rotateRegWindow(callinc); - as = callSP - zext(u15_12_23_sb3); + as = callSP - zext(bri12_i12_sh3); } -# ESYNC - Execute Synchronize, pg. 342. +# ESYNC - Execute Synchronize (RRR), pg. 342. :esync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b0010 & op0 = 0 { esync(); } -# EXCW - Exception Wait, pg. 343. +# EXCW - Exception Wait (RRR), pg. 343. :excw is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1000 & op0 = 0 { excw(); } -# EXTUI - Extract Unsigned Immediate, pg. 344. -:extui ar, at, u5_8_11_16, u5_20_23_plus1 is u5_20_23_plus1 & u3_17_19 = 0b010 & u5_8_11_16 & ar & at & op0 = 0 { +# EXTUI - Extract Unsigned Immediate (RRR), pg. 344. +:extui ar, at, u5_8_11_16, u5_20_23_plus1 is u5_20_23_plus1 & op1_1_3 = 0b010 & u5_8_11_16 & ar & at & op0 = 0 { local shifted:4 = at >> u5_8_11_16; local mask:4 = (1:4 << (u5_20_23_plus1))-1; ar = shifted & mask; } -# EXTW - External Wait, pg. 345. +# EXTW - External Wait (RRR), pg. 345. :extw is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1101 & op0 = 0 { extw(); } -# FLOAT.S - Convert Fixed to Single, pg. 346. -:float.s fr, as, u4_4_7 is op2 = 0b1100 & op1 = 0b1010 & fr & as & u4_4_7 & op0 = 0 { - local scale:4 = 1 << u4_4_7; +# FLOAT.S - Convert Fixed to Single (RRR), pg. 346. +:float.s fr, as, op_t is op2 = 0b1100 & op1 = 0b1010 & fr & as & op_t & op0 = 0 { + local scale:4 = 1 << op_t; fr = int2float(as) f/ int2float(scale); } -# FLOOR.S - Floor Single to Fixed, pg. 347. -:floor.s ar, fs, u4_4_7 is op2 = 0b1010 & op1 = 0b1010 & ar & fs & u4_4_7 & op0 = 0 { - local scale:4 = 1 << u4_4_7; +# FLOOR.S - Floor Single to Fixed (RRR), pg. 347. +:floor.s ar, fs, op_t is op2 = 0b1010 & op1 = 0b1010 & ar & fs & op_t & op0 = 0 { + local scale:4 = 1 << op_t; ar = floor(fs f* int2float(scale)); } -# IDTLB - Invalidate Data TLB Entry, pg. 348. +# IDTLB - Invalidate Data TLB Entry (RRR), pg. 348. :idtlb as is op2 = 0b0101 & op1 = 0 & ar = 0b1100 & as & at = 0 & op0 = 0 { idtlb(); } -# IHI - Instruction Cache Hit Invalidate, pg. 349. -:ihi as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0111 & as & at = 0b1110 & op0 = 0b0010 { - ihi(as + u10_16_23_sb2); +# IHI - Instruction Cache Hit Invalidate (RRI8), pg. 349. +:ihi as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0111 & as & at = 0b1110 & op0 = 0b0010 { + ihi(as + ri8_i8_sh2); } -# IHU - Instruction Cache Hit Unlock, pg. 351. +# IHU - Instruction Cache Hit Unlock (RRI4), pg. 351. :ihu as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0b0010 & ar = 0b0111 & as & at = 0b1101 & op0 = 0b0010 { ihu(as + u8_20_23_sb4); } -# III - Instruction Cache Index Invalidate, pg. 353. -:iii as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0111 & as & at = 0b1111 & op0 = 0b0010 { - iii(as + u10_16_23_sb2); +# III - Instruction Cache Index Invalidate (RRI8), pg. 353. +:iii as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0111 & as & at = 0b1111 & op0 = 0b0010 { + iii(as + ri8_i8_sh2); } -# IITLB - Invalidate Instruction TLB Entry, pg. 355. +# IITLB - Invalidate Instruction TLB Entry (RRR), pg. 355. :iitlb as is op2 = 0b0101 & op1 = 0 & ar = 0b0100 & as & at = 0 & op0 = 0 { iitlb(as); } -# IIU - Instruction Cache Index Unlock, pg. 356. +# IIU - Instruction Cache Index Unlock (RRI4), pg. 356. :iiu as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0b0011 & ar = 0b0111 & as & at = 0b1101 & op0 = 0b0010 { iiu(as + u8_20_23_sb4); } -# ILL - Illegal Instruction, pg. 358. +# ILL - Illegal Instruction (CALLX), pg. 358. :ill is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & at = 0 & op0 = 0 { ill(); goto inst_start; } -# ILL.N - Narrow Illegal Instruction, pg. 359. +# ILL.N - Narrow Illegal Instruction (RRRN), pg. 359. :ill.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0110 & n_op0 = 0b1101 { ill(); goto inst_start; } -# IPF - Instruction Cache Prefetch, pg. 360. -:ipf as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0111 & as & at = 0b1100 & op0 = 0b0010 { - ipf(as + u10_16_23_sb2); +# IPF - Instruction Cache Prefetch (RRI8), pg. 360. +:ipf as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0111 & as & at = 0b1100 & op0 = 0b0010 { + ipf(as + ri8_i8_sh2); } -# IPFL - Instruction Cache Prefetch and Lock, pg. 362. +# IPFL - Instruction Cache Prefetch and Lock (RRI4), pg. 362. :ipfl as, u8_20_23_sb4 is u8_20_23_sb4 & op1 = 0 & ar = 0b0111 & as & at = 0b1101 & op0 = 0b0010 { ipfl(as + u8_20_23_sb4); } -# ISYNC - Instruction Fetch Synchronize, pg. 364. +# ISYNC - Instruction Fetch Synchronize (RRR), pg. 364. :isync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0 & op0 = 0 { isync(); } -# J - Unconditional Jump, pg. 366. -:j srel_6_23 is srel_6_23 & u2_4_5 = 0 & op0 = 0b0110 { - goto srel_6_23; +# J - Unconditional Jump (CALL), pg. 366. +:j call_srel is call_srel & bri8_n = 0 & op0 = 0b0110 { + goto call_srel; } # J.L is a macro. -# RET (JX A0) - Non-Windowed Return, pg. 478. -:ret is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & u2_6_7 = 0b10 & u2_4_5 = 0b10 & op0 = 0 { +# RET (JX A0) - Non-Windowed Return (CALLX), pg. 478. +:ret is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & bri8_m = 0b10 & bri8_n = 0b10 & op0 = 0 { return [a0]; } # The manual suggests that RET is equivalent to JX A0, yet RET has bit 5 unset, JX doesn’t. -:ret is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & u2_6_7 = 0b10 & u2_4_5 = 0b00 & op0 = 0 { +:ret is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & bri8_m = 0b10 & bri8_n = 0b00 & op0 = 0 { return [a0]; } -# JX - Uncoditional Jump Register, pg. 368. -:jx as is op2 = 0 & op1 = 0 & ar = 0 & as & u2_6_7 = 0b10 & u2_4_5 = 0b10 & op0 = 0 { +# JX - Uncoditional Jump Register (CALLX), pg. 368. +:jx as is op2 = 0 & op1 = 0 & ar = 0 & as & bri8_m = 0b10 & bri8_n = 0b10 & op0 = 0 { goto [as]; } -# L8UI - Load 8-bit Unsigned, pg. 369. -:l8ui at, as, u8_16_23 is u8_16_23 & ar = 0 & as & at & op0 = 0b0010 { - local addr:4 = as + zext(u8_16_23:1); +# L8UI - Load 8-bit Unsigned (RRI8), pg. 369. +:l8ui at, as, ri8_i8 is ri8_i8 & ar = 0 & as & at & op0 = 0b0010 { + local addr:4 = as + zext(ri8_i8:1); at = zext(*:1 addr); } -# L16SI - Load 16-bit Signed, pg. 370. +# L16SI - Load 16-bit Signed (RRI8), pg. 370. :l16si at, as, u9_16_23_sb1 is u9_16_23_sb1 & ar = 0b1001 & as & at & op0 = 0b0010 { local addr:4 = as + u9_16_23_sb1; at = sext(*:2 addr); } -# L16UI - Load 16-bit Unsigned, pg. 372. +# L16UI - Load 16-bit Unsigned (RRI8), pg. 372. :l16ui at, as, u9_16_23_sb1 is u9_16_23_sb1 & ar = 0b001 & as & at & op0 = 0b0010 { local addr:4 = as + u9_16_23_sb1; at = zext(*:2 addr); } -# L32AI - Load 32-bit Acquire, pg. 374. -:l32ai at, as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b1011 & as & at & op0 = 0b0010 { - local addr:4 = as + u10_16_23_sb2; +# L32AI - Load 32-bit Acquire (RRI8), pg. 374. +:l32ai at, as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b1011 & as & at & op0 = 0b0010 { + local addr:4 = as + ri8_i8_sh2; at = *:4 addr; acquire(addr); } -# L32E - Load 32-bit for Window Exceptions, pg. 376. +# L32E - Load 32-bit for Window Exceptions (RRI4), pg. 376. :l32e at, as, s5_12_15_oex is op2 = 0 & op1 = 0b1001 & s5_12_15_oex & as & at & op0 = 0 { ptr:4 = as + sext(s5_12_15_oex); at = *:4 ptr; } -# L32I - Load 32-bit, pg. 378. -:l32i at, as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0010 & as & at & op0 = 0b0010 { - local addr:4 = as + u10_16_23_sb2; +# L32I - Load 32-bit (RRI8), pg. 378. +:l32i at, as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0010 & as & at & op0 = 0b0010 { + local addr:4 = as + ri8_i8_sh2; at = *:4 addr; } -# L32I.N - Narrow Load 32-bit, pg. 380. +# L32I.N - Narrow Load 32-bit (RRRN), pg. 380. :l32i.n n_at, n_as, n_u6_12_15_sb2 is n_u6_12_15_sb2 & n_as & n_at & n_op0 = 0b1000 { local addr:4 = n_as + n_u6_12_15_sb2; n_at = *:4 addr; } -# L32R - Load 32-bit PC-relative, pg. 382. -:l32r at, srel_8_23_oex_sb2 is srel_8_23_oex_sb2 & at & op0 = 0b0001 { - at = srel_8_23_oex_sb2; +# L32R - Load 32-bit PC-relative (RI6), pg. 382. +:l32r at, srel_oex_sh2 is srel_oex_sh2 & at & op0 = 0b0001 { + at = srel_oex_sh2; } -# LDCT - Load Data Cache Tag, pg. 384. +# LDCT - Load Data Cache Tag (RRR), pg. 384. :ldct at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1000 & as & at & op0 = 0 { at = ldct(as); } -# LICT - Load Instruction Cache Tag, pg. 388. +# LICT - Load Instruction Cache Tag (RRR), pg. 388. :lict at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0 & as & at & op0 = 0 { at = lict(as); } -# LICW - Load Instruction Cache Word, pg. 390. +# LICW - Load Instruction Cache Word (RRR), pg. 390. :licw at, as is op2 = 0b1111 & op1 = 0b0010 & ar = 0 & as & at & op0 = 0 { at = licw(as); } -# LSI - Load Single Immediate, pg. 398. -:lsi ft, as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0 & as & ft & op0 = 0b0011 { - local addr:4 = as + u10_16_23_sb2; +# LSI - Load Single Immediate, (RRI8) pg. 398. +:lsi ft, as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0 & as & ft & op0 = 0b0011 { + local addr:4 = as + ri8_i8_sh2; ft = *:4 addr; } -# LSIU - Load Single Immediate with Update, pg. 400. -:lsiu ft, as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b1000 & as & ft & op0 = 0b0011 { - local addr:4 = as + u10_16_23_sb2; +# LSIU - Load Single Immediate with Update (RRI8), pg. 400. +:lsiu ft, as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b1000 & as & ft & op0 = 0b0011 { + local addr:4 = as + ri8_i8_sh2; ft = *:4 addr; as = addr; } -# LSX - Load Single Indexed, pg. 402. +# LSX - Load Single Indexed (RRR), pg. 402. :lsx fr, as, at is op2 = 0 & op1 = 0b1000 & fr & as & at & op0 = 0 { local addr:4 = as+at; fr = *:4 addr; } -# LSXU - Load Single Indexed with Update, pg. 404. +# LSXU - Load Single Indexed with Update (RRR), pg. 404. :lsxu fr, as, at is op2 = 0b0001 & op1 = 0b1000 & fr & as & at & op0 = 0 { local addr:4 = as+at; fr = *:4 addr; as = addr; } -# MADD.S - Multiply and Add Single, pg. 406. +# MADD.S - Multiply and Add Single (RRR), pg. 406. :madd.s fr, fs, ft is op2 = 0b0100 & op1 = 0b1010 & fr & fs & ft & op0 = 0 { fr = fr f+ (fs f* ft); } -# MAX - Maximum Value, pg. 407. +# MAX - Maximum Value (RRR), pg. 407. :max ar, as, at is op2 = 0b0101 & op1 = 0b0011 & ar & as & at & op0 = 0 { test:1 = as s< at; ar = (zext(test) * at) + (zext(!test) * as); } -# MAXU - Maximum Value Unsigned, pg. 408. +# MAXU - Maximum Value Unsigned (RRR), pg. 408. :maxu ar, as, at is op2 = 0b0111 & op1 = 0b0011 & ar & as & at & op0 = 0 { test:1 = as < at; ar = (zext(test) * at) + (zext(!test) * as); } -# MEMW - Memory Wait, pg. 409. +# MEMW - Memory Wait (RRR), pg. 409. :memw is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1100 & op0 = 0 { memw(); } -# MIN - Minimum Value, pg. 410. +# MIN - Minimum Value (RRR), pg. 410. :min ar, as, at is op2 = 0b0100 & op1 = 0b0011 & ar & as & at & op0 = 0 { test:1 = as s< at; ar = (zext(test) * as) + (zext(!test) * at); } -# MINU - Minimum Value Unsigned, pg. 411. +# MINU - Minimum Value Unsigned (RRR), pg. 411. :minu ar, as, at is op2 = 0b0110 & op1 = 0b0011 & ar & as & at & op0 = 0 { test:1 = as < at; ar = (zext(test) * as) + (zext(!test) * at); } -# MOV.N - Narrow Move, pg. 413. +# MOV.N - Narrow Move (RRRN), pg. 413. :mov.n n_at, n_as is n_ar = 0 & n_as & n_at & n_op0 = 0b1101 { n_at = n_as; } -# MOV.S - Move Single, pg. 414. +# MOV.S - Move Single (RRR), pg. 414. :mov.s fr, fs is op2 = 0b1111 & op1 = 0b1010 & fr & fs & at = 0 & op0 = 0 { fr = fs; } -# MOVEQZ - Move if Equal to Zero, pg. 415. +# MOVEQZ - Move if Equal to Zero (RRR), pg. 415. :moveqz ar, as, at is op2 = 0b1000 & op1 = 0b0011 & ar & as & at & op0 = 0 { if (at != 0) goto ; ar = as; } -# MOVEQZ.S - Move Single if Equal to Zero, pg. 416. +# MOVEQZ.S - Move Single if Equal to Zero (RRR), pg. 416. :moveqz.s fr, fs, at is op2 = 0b1000 & op1 = 0b1011 & fr & fs & at & op0 = 0 { if (at != 0) goto ; fr = fs; } -# MOVF - Move if False, pg. 417. +# MOVF - Move if False (RRR), pg. 417. :movf ar, as, bt is op2 = 0b1100 & op1 = 0b0011 & ar & as & bt & op0 = 0 { if (bt) goto ; ar = as; } -# MOVF.S - Move Single if False, pg. 418. +# MOVF.S - Move Single if False (RRR), pg. 418. :movf.s fr, fs, bt is op2 = 0b1100 & op1 = 0b1011 & fr & fs & bt & op0 = 0 { if (bt)goto ; fr = fs; } -# MOVGEZ - Move if Greater Than or Equal to Zero, pg. 419. +# MOVGEZ - Move if Greater Than or Equal to Zero (RRR), pg. 419. :movgez ar, as, at is op2 = 0b1011 & op1 = 0b0011 & ar & as & at & op0 = 0 { if (at s< 0) goto ; ar = as; } -# MOVGEZ.S - Move Single if Greater Than or Equal to Zero, pg. 420. +# MOVGEZ.S - Move Single if Greater Than or Equal to Zero (RRR), pg. 420. :movgez.s fr, fs, at is op2 = 0b1011 & op1 = 0b1011 & fr & fs & at & op0 = 0 { if (at s< 0) goto ; fr = fs; } -# MOVI - Move Immediate, pg. 421. -:movi at, s16_16_23_8_11 is s16_16_23_8_11 & ar = 0b1010 & at & op0 = 0b0010 { - local val:4 = sext(s16_16_23_8_11); +# MOVI - Move Immediate (RRI8), pg. 421. +:movi at, movi_si16 is movi_si16 & ar = 0b1010 & at & op0 = 0b0010 { + local val:4 = sext(movi_si16); at = val; } -# MOVI.N - Narrow Move Immediate, pg. 422. -:movi.n n_as, n_s8_12_15_4_6_asymm is n_s8_12_15_4_6_asymm & n_as & n_u1_7 = 0 & n_op0 = 0b1100 { - local val:4 = sext(n_s8_12_15_4_6_asymm); +# MOVI.N - Narrow Move Immediate (RI7), pg. 422. +:movi.n n_as, movin_si8 is movin_si8 & n_as & n_op_s_3 = 0 & n_op0 = 0b1100 { + local val:4 = sext(movin_si8); n_as = val; } -# MOVLTZ - Move if Less Than Zero, pg. 423. +# MOVLTZ - Move if Less Than Zero (RRR), pg. 423. :movltz ar, as, at is op2 = 0b1010 & op1 = 0b0011 & ar & as & at & op0 = 0 { if (at s>= 0) goto ; ar = as; } -# MOVLTZ.S - Move Single if Less Than Zero, pg. 424. +# MOVLTZ.S - Move Single if Less Than Zero (RRR), pg. 424. :movltz.s fr, fs, at is op2 = 0b1010 & op1 = 0b1011 & fr & fs & at & op0 = 0 { if (at s>= 0) goto ; fr = fs; } -# MOVNEZ - Move if Not Equal to Zero, pg. 425. +# MOVNEZ - Move if Not Equal to Zero (RRR), pg. 425. :movnez ar, as, at is op2 = 0b1001 & op1 = 0b0011 & ar & as & at & op0 = 0 { if (at == 0) goto ; ar = as; } -# MOVNEZ.S - Move Single if Not Equal to Zero, pg. 426. +# MOVNEZ.S - Move Single if Not Equal to Zero (RRR), pg. 426. :movnez.s fr, fs, at is op2 = 0b1001 & op1 = 0b1011 & fr & fs & at & op0 = 0 { if (at == 0) goto ; fr = fs; } -# MOVSP - Move to Stack Pointer, pg. 427. +# MOVSP - Move to Stack Pointer (RRR), pg. 427. :movsp at, as is op2 = 0 & op1 = 0 & ar = 0b0001 & as & at & op0 = 0 { at = (zext(WindowStart == 0) * at) + (zext(WindowStart != 0) * as); } -# MOVT - Move if True, pg. 428. +# MOVT - Move if True (RRR), pg. 428. :movt ar, as, bt is op2 = 0b1101 & op1 = 0b0011 & ar & as & bt & op0 = 0 { if (!bt) goto ; ar = as; } -# MOVT.S - Move Single if True, pg. 429. +# MOVT.S - Move Single if True (RRR), pg. 429. :movt.s fr, fs, bt is op2 = 0b1101 & op1 = 0b1011 & fr & fs & bt & op0 = 0 { if (!bt) goto ; fr = fs; } -# MSUB.S - Multiply and Subtract Single, pg. 430. +# MSUB.S - Multiply and Subtract Single (RRR), pg. 430. :msub.s fr, fs, ft is op2 = 0b0101 & op1 = 0b1010 & fr & fs & ft & op0 = 0 { fr = fr f- (fs f* ft); } -# MUL.S - Multiply Single, pg. 435. +# MUL.S - Multiply Single (RRR), pg. 435. :mul.s fr, fs, ft is op2 = 0b0010 & op1 = 0b1010 & fr & fs & ft & op0 = 0 { fr = fs f* ft; } -# MUL16S - Multiply 16-bit Signed, pg. 436. +# MUL16S - Multiply 16-bit Signed (RRR), pg. 436. :mul16s ar, as, at is op2 = 0b1101 & op1 = 0b0001 & ar & as & at & op0 = 0 { ar = sext(as:2) * sext(at:2); } -# MUL16U - Multiply 16-bit Unsigned, pg. 437. +# MUL16U - Multiply 16-bit Unsigned (RRR), pg. 437. :mul16u ar, as, at is op2 = 0b1100 & op1 = 0b0001 & ar & as & at & op0 = 0 { ar = zext(as:2) * zext(at:2); } -# MULL - Multiply Low, pg. 450. +# MULL - Multiply Low (RRR), pg. 450. :mull ar, as, at is op2 = 0b1000 & op1 = 0b0010 & ar & as & at & op0 = 0 { ar = as * at; } -# MULSH - Multiply Signed High, pg. 455. +# MULSH - Multiply Signed High (RRR), pg. 455. :mulsh ar, as, at is op2 = 0b1011 & op1 = 0b0010 & ar & as & at & op0 = 0 { local s64:8 = sext(as); local t64:8 = sext(at); @@ -860,7 +860,7 @@ macro extract_bit(bit, result) { ar = p(4); } -# MULUH - Multiply Unsigned High, pg. 456. +# MULUH - Multiply Unsigned High (RRR), pg. 456. :muluh ar, as, at is op2 = 0b1010 & op1 = 0b0010 & ar & as & at & op0 = 0 { local s64:8 = zext(as); local t64:8 = zext(at); @@ -868,214 +868,214 @@ macro extract_bit(bit, result) { ar = p(4); } -# NEG - Negate, pg. 457. +# NEG - Negate (RRR), pg. 457. :neg ar, at is op2 = 0b0110 & op1 = 0 & ar & as = 0 & at & op0 = 0 { ar = -at; } -# NEG.S - Negate Single, pg. 458. +# NEG.S - Negate Single (RRR), pg. 458. :neg.s fr, fs is op2 = 0b1111 & op1 = 0b1010 & fr & fs & at = 0b0110 & op0 = 0 { fr = 0 f- fs; } -# NOP - No Operation, pg. 459. +# NOP - No Operation (RRR), pg. 459. :nop is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b1111 & op0 = 0 { } -# NOP.N - Narrow No Operation, pg. 460. +# NOP.N - Narrow No Operation (RRRN), pg. 460. :nop.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0011 & n_op0 = 0b1101 { } -# NSA - Normalization Shift Amount, pg. 461. +# NSA - Normalization Shift Amount (RRR), pg. 461. :nsa at, as is op2 = 0b0100 & op1 = 0 & ar = 0b1110 & as & at & op0 = 0 { at = lzcount(~as); } -# NSAU - Normalization Shift Amount Unsigned, pg. 462. (Count leading zeros) +# NSAU - Normalization Shift Amount Unsigned (RRR), pg. 462. (Count leading zeros) :nsau at, as is op2 = 0b0100 & op1 = 0 & ar = 0b1111 & as & at & op0 = 0 { at = lzcount(as); } -# OEQ.S - Compare Single Equal, pg. 463. +# OEQ.S - Compare Single Equal (RRR), pg. 463. :oeq.s br, fs, ft is op2 = 0b0010 & op1 = 0b1011 & br & fs & ft & op0 = 0 { br = !nan(fs) && !nan(ft) && fs f== ft; } -# OLE.S - Compare Single Ordered and Less Than or Equal, pg. 464 +# OLE.S - Compare Single Ordered and Less Than or Equal (RRR), pg. 464 :ole.s br, fs, ft is op2 = 0b0110 & op1 = 0b1011 & br & fs & ft & op0 = 0 { br = !nan(fs) && !nan(ft) && fs f<= ft; } -# OLT.S - Compare Single Ordered and Less Than, pg. 465. +# OLT.S - Compare Single Ordered and Less Than (RRR), pg. 465. :olt.s br, fs, ft is op2 = 0b0100 & op1 = 0b1011 & br & fs & ft & op0 = 0 { br = !nan(fs) && !nan(ft) && fs f< ft; } -# MOV - Move, pg. 412. Special case of OR as, at, at. +# MOV - Move (RRR), pg. 412. Special case of OR as, at, at. :mov ar, as is op2 = 0b0010 & op1 = 0 & ar & as & as = at & op0 = 0 { ar = as; } -# OR - Bitwise Logical Or, pg. 466. +# OR - Bitwise Logical Or (RRR), pg. 466. :or ar, as, at is op2 = 0b0010 & op1 = 0 & ar & as & at & op0 = 0 { ar = as | at; } -# ORB - Boolean Or, pg. 467. +# ORB - Boolean Or (RRR), pg. 467. :orb br, bs, bt is op2 = 0b0010 & op1 = 0b0010 & br & bs & bt & op0 = 0 { br = bs || bt; } -# ORBC - Boolean Or with Complement, pg. 468. +# ORBC - Boolean Or with Complement (RRR), pg. 468. :orbc br, bs, bt is op2 = 0b0011 & op1 = 0b0010 & br & bs & bt & op0 = 0 { br = bs || !bt; } -# PDTLB - Probe Data TLB, pg. 469. +# PDTLB - Probe Data TLB (RRR), pg. 469. :pdtlb at, as is op2 = 0b0101 & op1 = 0 & ar = 0b1101 & as & at & op0 = 0 { at = pdtlb(as); } -# PITLB - Probe Instruction TLB, pg. 470. +# PITLB - Probe Instruction TLB (RRR), pg. 470. :pitlb at, as is op2 = 0b0101 & op1 = 0 & ar = 0b0101 & as & at & op0 = 0 { at = pitlb(as); } -# QUOS - Quotient Signed, pg. 471. +# QUOS - Quotient Signed (RRR), pg. 471. :quos ar, as, at is op2 = 0b1101 & op1 = 0b0010 & ar & as & at & op0 = 0 { ar = as s/ at; } -# QUOU - Quotient Unsigned, pg. 472. +# QUOU - Quotient Unsigned (RRR), pg. 472. :quou ar, as, at is op2 = 0b1100 & op1 = 0b0010 & ar & as & at & op0 = 0 { ar = as / at; } -# RDTLB0 - Read Data TLB Virtual Entry, pg. 473. +# RDTLB0 - Read Data TLB Virtual Entry (RRR), pg. 473. :rdtlb0 at, as is op2 = 0b0101 & op1 = 0 & ar = 0b1011 & as & at & op0 = 0 { at = rdtlb0(as); } -# RDTLB1 - Read Data TLB Entry Translation, pg. 474. +# RDTLB1 - Read Data TLB Entry Translation (RRR), pg. 474. :rdtlb1 at, as is op2 = 0b0101 & op1 = 0 & ar = 0b1111 & as & at & op0 = 0 { at = rdtlb1(as); } -# REMS - Remainder Signed, pg. 475. +# REMS - Remainder Signed (RRR), pg. 475. :rems ar, as, at, is op2 = 0b1111 & op1 = 0b0010 & ar & as & at & op0 = 0 { ar = as s% at; } -# REMU - Remainder Unsigned, pg. 476. +# REMU - Remainder Unsigned (RRR), pg. 476. :remu ar, as, at, is op2 = 0b1110 & op1 = 0b0010 & ar & as & at & op0 = 0 { ar = as % at; } -# RER - Read External Register, pg. 477. +# RER - Read External Register (RRR), pg. 477. :rer as, at is op2 = 0b0100 & op1 = 0 & ar = 0b0110 & as & at & op0 = 0 { as = rer(at); } -# RET.N - Narrow Non-Windowed Return, pg. 479. +# RET.N - Narrow Non-Windowed Return (RRRN), pg. 479. :ret.n is n_ar = 0b1111 & n_as = 0 & n_at = 0 & n_op0 = 0b1101 { return [a0]; } -# RETW - Windowed Return, pg. 480. -:retw is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & u2_6_7 = 0b10 & u2_4_5 = 0b01 & op0 = 0 { +# RETW - Windowed Return (CALLX), pg. 480. +:retw is op2 = 0 & op1 = 0 & ar = 0 & as = 0 & bri8_m = 0b10 & bri8_n = 0b01 & op0 = 0 { local addr:4 = (a0 & 0x3fffffff) | (inst_start & 0xc0000000); restoreRegWindow(); return [addr]; } -# RETW.N - Narrow Windowed Return, pg. 482. +# RETW.N - Narrow Windowed Return (RRRN), pg. 482. :retw.n is n_ar = 0b1111 & n_as = 0 & n_at = 0b0001 & n_op0 = 0b1101 { local addr:4 = (a0 & 0x3fffffff) | (inst_start & 0xc0000000); restoreRegWindow(); return [addr]; } -# RFDD - Return from Debug and Dispatch, pg. 484. +# RFDD - Return from Debug and Dispatch (RRR), pg. 484. :rfdd is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1110 & (as = 0b0000 | as = 0b0001) & at = 0b0001 & op0 = 0 { local tmp:4 = rfdd(); return [tmp]; } -# RFDE _ Return From Double Exception, pg. 485. +# RFDE _ Return From Double Exception (RRR), pg. 485. :rfde is op2 = 0 & op1 = 0 & ar = 0b0011 & as =0b0010 & at = 0 & op0 = 0 { local tmp:4 = rfde(); return [tmp]; } -# RFDO - Return from Debug Operation, pg. 486. +# RFDO - Return from Debug Operation (RRR), pg. 486. :rfdo is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1110 & as = 0 & at = 0 & op0 = 0 { local tmp:4 = rfdo(); return [tmp]; } -# RFE - Return From Exception, pg. 487. +# RFE - Return From Exception (RRR), pg. 487. :rfe is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0 & at = 0 & op0 = 0 { local tmp:4 = rfe(); return [tmp]; } -rfi_epc: ptr is u4_8_11 [ ptr = $(EPC_BASE) + (4 * u4_8_11); ] { export *[register]:4 ptr; } -rfi_eps: ptr is u4_8_11 [ ptr = $(EPS_BASE) + (4 * u4_8_11); ] { export *[register]:4 ptr; } +rfi_epc: ptr is op_s [ ptr = $(EPC_BASE) + (4 * op_s); ] { export *[register]:4 ptr; } +rfi_eps: ptr is op_s [ ptr = $(EPS_BASE) + (4 * op_s); ] { export *[register]:4 ptr; } -# RFI - Return from High-Priority Interrupt, pg. 488. -:rfi u4_8_11 is op2 = 0 & op1 = 0 & ar = 0b0011 & u4_8_11 & at = 0b0001 & op0 = 0 & rfi_epc & rfi_eps { +# RFI - Return from High-Priority Interrupt (RRR), pg. 488. +:rfi op_s is op2 = 0 & op1 = 0 & ar = 0b0011 & op_s & at = 0b0001 & op0 = 0 & rfi_epc & rfi_eps { PS = rfi_eps; return [rfi_epc]; } -# RFME - Return from Memory Error, pg. 489. +# RFME - Return from Memory Error (RRR), pg. 489. :rfme is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0 & at = 0b0010 & op0 = 0 { PS = MEPS; MESR[0,1] = 0; return [MEPC]; } -# RFR - Move FR to AR, pg. 490. +# RFR - Move FR to AR (RRR), pg. 490. :rfr ar, fs is op2 = 0b1111 & op1 = 0b1010 & ar & fs & at = 0b0100 & op0 = 0 { ar = fs; } -# RFUE - Return from User-Mode Exception, pg. 491. +# RFUE - Return from User-Mode Exception (RRR), pg. 491. :rfue is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0b0001 & at = 0 & op0 = 0 { local tmp:4 = rfue(); return [tmp]; } -# RFWO - Return from Window Overflow, pg. 492. +# RFWO - Return from Window Overflow (RRR), pg. 492. :rfwo is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0b0100 & at = 0 & op0 = 0 { $(PS_EXCM) = 0; rfwo(); return [EPC1]; } -# RFWU - Return from Window Underflow, pg. 493. +# RFWU - Return from Window Underflow (RRR), pg. 493. :rfwu is op2 = 0 & op1 = 0 & ar = 0b0011 & as = 0b0101 & at = 0 & op0 = 0 { $(PS_EXCM) = 0; rfwu(); return [EPC1]; } -# RITLB0 - Read Instruction TLB Virtual Entry, pg. 494. +# RITLB0 - Read Instruction TLB Virtual Entry (RRR), pg. 494. :ritlb0 at, as is op2 = 0b0101 & op1 = 0 & ar = 0b0011 & as & at & op0 = 0 { at = ritlb0(as); } -# RITLB1 - Read Instruction TLB Entry Translation, pg. 495. +# RITLB1 - Read Instruction TLB Entry Translation (RRR), pg. 495. :ritlb1 at, as is op2 = 0b0101 & op1 = 0 & ar = 0b0111 & as & at & op0 = 0 { at = ritlb1(as); } -# ROTW - Rotate Window, pg. 496. -:rotw s4_4_7 is op2 = 0b0100 & op1 = 0 & ar = 0b1000 & as = 0 & s4_4_7 & op0 = 0 { - WindowBase = WindowBase + s4_4_7; +# ROTW - Rotate Window (RRR), pg. 496. +:rotw op_t_si4 is op2 = 0b0100 & op1 = 0 & ar = 0b1000 & as = 0 & op_t_si4 & op0 = 0 { + WindowBase = WindowBase + op_t_si4; } -# ROUND.S - Round Single to Fixed, pg. 497. -:round.s ar, fs, u4_4_7 is op2 = 0b1000 & op1 = 0b1010 & ar & fs & u4_4_7 & op0 = 0 { - local scale:4 = 1 << u4_4_7; +# ROUND.S - Round Single to Fixed (RRR), pg. 497. +:round.s ar, fs, op_t is op2 = 0b1000 & op1 = 0b1010 & ar & fs & op_t & op0 = 0 { + local scale:4 = 1 << op_t; local result = fs f* int2float(scale); isNan:1 = nan(result); if (isNan) goto ; @@ -1088,41 +1088,41 @@ rfi_eps: ptr is u4_8_11 [ ptr = $(EPS_BASE) + (4 * u4_8_11); ] { export *[regist } -# RSIL - Read and Set Interrupt Level, pg. 498. -:rsil at, u4_8_11 is op2 = 0 & op1 = 0 & ar = 0b0110 & u4_8_11 & at & op0 = 0 { - at = rsil(u4_8_11:1); +# RSIL - Read and Set Interrupt Level (RRR), pg. 498. +:rsil at, op_s is op2 = 0 & op1 = 0 & ar = 0b0110 & op_s & at & op0 = 0 { + at = rsil(op_s:1); } -# RSR - Read Special Register, pg. 500. +# RSR - Read Special Register (RSR), pg. 500. :rsr at, sr is op0 = 0 & op1 = 0b0011 & sr & at & op0 = 0 { at = rsr(sr:1); } -# RSYNC - Register Read Synchronize, pg. 502. +# RSYNC - Register Read Synchronize (RRR), pg. 502. :rsync is op2 = 0 & op1 = 0 & ar = 0b0010 & as = 0 & at = 0b0001 & op0 = 0 { rsync(); } -# RUR - Read User Register, pg. 503. -:rur ar, u8_4_11 is op2 = 0b1110 & op1 = 0b0011 & ar & u8_4_11 & op0 = 0 { - ar = rur(u8_4_11:1); +# RUR - Read User Register (RRR), pg. 503. +:rur ar, op_st is op2 = 0b1110 & op1 = 0b0011 & ar & op_st & op0 = 0 { + ar = rur(op_st:1); } -# S8I - Store 8-bit, pg. 504. -:s8i at, as, u8_16_23 is u8_16_23 & ar = 0b0100 & as & at & op0 = 0b0010 { - local addr:4 = as + zext(u8_16_23:1); - *:1 addr = at:1; +# S8I - Store 8-bit (RRI8), pg. 504. +:s8i at, as, ri8_i8 is ri8_i8 & ar = 0b0100 & as & at & op0 = 0b0010 { + local addr:4 = as + zext(ri8_i8:1); + *:1 addr = at:1; } -# S16I - Store 16-bit, pg. 505. +# S16I - Store 16-bit (RRI8), pg. 505. :s16i at, as, u9_16_23_sb1 is u9_16_23_sb1 & ar = 0b0101 & as & at & op0 = 0b0010 { - local addr:4 = as + u9_16_23_sb1; - *:2 addr = at:2; + local addr:4 = as + u9_16_23_sb1; + *:2 addr = at:2; } -# S32C1I - Store 32-bit Compare Conditional, pg. 506 -:s32c1i at, as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b1110 & as & at & op0 = 0b0010 { - local addr:4 = as + u10_16_23_sb2; +# S32C1I - Store 32-bit Compare Conditional (RRI8), pg. 506 +:s32c1i at, as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b1110 & as & at & op0 = 0b0010 { + local addr:4 = as + ri8_i8_sh2; old:4 = *:4 addr; if (old != SCOMPARE1) goto ; *:4 addr = at; @@ -1130,86 +1130,87 @@ rfi_eps: ptr is u4_8_11 [ ptr = $(EPS_BASE) + (4 * u4_8_11); ] { export *[regist at = old; } -# S32E - Store 32-bit for Window Exceptions, pg. 508. +# S32E - Store 32-bit for Window Exceptions (RRI4), pg. 508. :s32e at, as, s5_12_15_oex is op2 = 0b0100 & op1 = 0b1001 & s5_12_15_oex & as & at & op0 = 0 { ptr:4 = as + sext(s5_12_15_oex); *:4 ptr = at; } -# S32I - Store 32-bit, pg. 510. -:s32i at, as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0110 & as & at & op0 = 0b0010 { - local addr:4 = as + u10_16_23_sb2; - *:4 addr = at; +# S32I - Store 32-bit (RRR), pg. 510. +:s32i at, as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0110 & as & at & op0 = 0b0010 { + local addr:4 = as + ri8_i8_sh2; + *:4 addr = at; } -# S32I.N - Narrow Store 32-bit, pg. 512. +# S32I.N - Narrow Store 32-bit (RRRN), pg. 512. :s32i.n n_at, n_as, n_u6_12_15_sb2 is n_u6_12_15_sb2 & n_as & n_at & n_op0 = 0b1001 { - local addr:4 = n_as + n_u6_12_15_sb2; - *:4 addr = n_at; + local addr:4 = n_as + n_u6_12_15_sb2; + *:4 addr = n_at; } -# S32RI - Store 32-bit Release, pg. 514. -:s32ri at, as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b1111 & as & at & op0 = 0b0010 { - local addr:4 = as + u10_16_23_sb2; +# S32RI - Store 32-bit Release (RRI8), pg. 514. +:s32ri at, as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b1111 & as & at & op0 = 0b0010 { + local addr:4 = as + ri8_i8_sh2; release(addr); *:4 addr = at; } -# SDCT - Store Data Cache Tag, pg. 516. +# SDCT - Store Data Cache Tag (RRR), pg. 516. :sdct at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b1001 & as & at & op0 = 0 { sdct(as, at); } -# SEXT - Sign Extend, pg. 518. -:sext ar, as, u5_4_7_plus7 is op2 = 0b0010 & op1 = 0b0011 & ar & as & u5_4_7_plus7 & op0 = 0 { +# SEXT - Sign Extend (RRR), pg. 518. +# quoting mnemonic to prevent it showing up as an error in the sleigh editor +:^"sext" ar, as, u5_4_7_plus7 is op2 = 0b0010 & op1 = 0b0011 & ar & as & u5_4_7_plus7 & op0 = 0 { local shift:4 = 31 - u5_4_7_plus7; local tmp:4 = as << shift; ar = tmp s>> shift; } -:sext ar, as, 7 is op2 = 0b0010 & op1 = 0b0011 & ar & as & u4_4_7 = 0 & op0 = 0 { +:^"sext" ar, as, 7 is op2 = 0b0010 & op1 = 0b0011 & ar & as & op_t = 0 & op0 = 0 { ar = sext(as:1); } -:sext ar, as, 15 is op2 = 0b0010 & op1 = 0b0011 & ar & as & u4_4_7 = 8 & op0 = 0 { +:^"sext" ar, as, 15 is op2 = 0b0010 & op1 = 0b0011 & ar & as & op_t = 8 & op0 = 0 { ar = sext(as:2); } -# SICT - Store Instruction Cache Tag, pg. 519. +# SICT - Store Instruction Cache Tag (RRR), pg. 519. :sict at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b0001 & as & at & op0 = 0 { sict(as, at); } -# SICW - Store Instruction Cache word, pg. 521. +# SICW - Store Instruction Cache word (RRR), pg. 521. :sicw at, as is op2 = 0b1111 & op1 = 0b0001 & ar = 0b0011 & as & at & op0 = 0 { sicw(as, at); } -# SIMCALL - Simulator Call, pg. 523. +# SIMCALL - Simulator Call (RRR), pg. 523. :simcall is op2 = 0 & op1 = 0 & ar = 0b0101 & as = 0b0001 & at = 0 & op0 = 0 { simcall(); } -# SLL - Shift Left Logical, pg. 524. +# SLL - Shift Left Logical (RRR), pg. 524. :sll ar, as is op2 = 0b1010 & op1 = 0b0001 & ar & as & at = 0 & op0 = 0 { local sa:4 = 32 - SAR; ar = as << sa; } -# SLLI - Shift Left Logical Immediate, pg. 525. -:slli ar, as, u5_4_7_20 is u3_21_23 = 0 & u5_4_7_20 & op1 = 0b0001 & ar & as & op0 = 0 { +# SLLI - Shift Left Logical Immediate (RRR), pg. 525. +:slli ar, as, u5_4_7_20 is op2_1_3 = 0 & u5_4_7_20 & op1 = 0b0001 & ar & as & op0 = 0 { ar = as << u5_4_7_20; } -# SRA - Shift Right Arithmetic, pg. 526. +# SRA - Shift Right Arithmetic (RRR), pg. 526. :sra ar, at is op2 = 0b1011 & op1 = 0b0001 & ar & as = 0 & at & op0 = 0 { - ar = at s>> SAR; + ar = at s>> SAR; } -# SRAI - Shift Right Arithmetic Immediate, pg. 527. -:srai ar, at, u5_8_11_20 is u3_21_23 = 0b001 & u5_8_11_20 & op1 = 0b0001 & ar & at & op0 = 0 { +# SRAI - Shift Right Arithmetic Immediate (RRR), pg. 527. +:srai ar, at, u5_8_11_20 is op2_1_3 = 0b001 & u5_8_11_20 & op1 = 0b0001 & ar & at & op0 = 0 { ar = at s>> u5_8_11_20; } -# SRC - Shift Right Combined, pg. 528. +# SRC - Shift Right Combined (RRR), pg. 528. :src ar, as, at is op2 = 0b1000 & op1 = 0b0001 & ar & as & at & op0 = 0 { local s64:8 = zext(as); local t64:8 = zext(at); @@ -1218,102 +1219,102 @@ rfi_eps: ptr is u4_8_11 [ ptr = $(EPS_BASE) + (4 * u4_8_11); ] { export *[regist ar = shifted:4; } -# SRL - Shift Right Logical, pg. 529. +# SRL - Shift Right Logical (RRR), pg. 529. :srl ar, at is op2 = 0b1001 & op1 = 0b0001 & ar & as = 0 & at & op0 = 0 { ar = at >> SAR; } -# SRLI - Shift Right Logical Immediate, pg. 530. -:srli ar, at, u4_8_11 is op2 = 0b0100 & op1 = 0b0001 & ar & u4_8_11 & at & op0 = 0 { - ar = at >> u4_8_11; +# SRLI - Shift Right Logical Immediate (RRR), pg. 530. +:srli ar, at, op_s is op2 = 0b0100 & op1 = 0b0001 & ar & op_s & at & op0 = 0 { + ar = at >> op_s; } -# SSA8B - Set Shift Amount for BE Byte Shift, pg. 531. +# SSA8B - Set Shift Amount for BE Byte Shift (RRR), pg. 531. :ssa8b as is op2 = 0b0100 & op1 = 0 & ar = 0b0011 & as & at = 0 & op0 = 0 { local lsa:4 = (as&3)*8; SAR = 32 - lsa; } -# SSA8L - Set Shift Amount for LE Byte Shift, pg. 532. +# SSA8L - Set Shift Amount for LE Byte Shift (RRR), pg. 532. :ssa8l as is op2 = 0b0100 & op1 = 0 & ar = 0b0010 & as & at = 0 & op0 = 0 { local rsa:4 = (as & 3)*8; SAR = rsa; } -# SSAI - Set Shift Amount Immediate, pg. 533. -:ssai u5_8_11_4 is op2 = 0b0100 & op1 = 0 & ar = 0b0100 & u5_8_11_4 & u3_5_7 = 0 & op0 = 0 { +# SSAI - Set Shift Amount Immediate (RRR), pg. 533. +:ssai u5_8_11_4 is op2 = 0b0100 & op1 = 0 & ar = 0b0100 & u5_8_11_4 & op_t_1_3 = 0 & op0 = 0 { SAR = u5_8_11_4; } -# SSI - Store Single Immediate, pg. 534. -:ssi ft, as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b0100 & as & ft & op0 = 0b0011 { - local addr:4 = as + u10_16_23_sb2; +# SSI - Store Single Immediate (RRI8), pg. 534. +:ssi ft, as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b0100 & as & ft & op0 = 0b0011 { + local addr:4 = as + ri8_i8_sh2; *:4 addr = ft; } -# SSIU - Store Single Immediate with Update, pg. 536. -:ssiu ft, as, u10_16_23_sb2 is u10_16_23_sb2 & ar = 0b1100 & as & ft & op0 = 0b0011 { - local addr:4 = as + u10_16_23_sb2; +# SSIU - Store Single Immediate with Update (RRI8), pg. 536. +:ssiu ft, as, ri8_i8_sh2 is ri8_i8_sh2 & ar = 0b1100 & as & ft & op0 = 0b0011 { + local addr:4 = as + ri8_i8_sh2; *:4 addr = ft; as = addr; } -# SSL - Set Shift Amount for Left Shift, pg. 538. +# SSL - Set Shift Amount for Left Shift (RRR), pg. 538. :ssl as is op2 = 0b0100 & op1 = 0 & ar = 0b0001 & as & at = 0 & op0 = 0 { SAR = 32 - (as & 0x1f); } -# SSR - Set Shift Amount for Right Shift, pg. 539. +# SSR - Set Shift Amount for Right Shift (RRR), pg. 539. :ssr as is op2 = 0b0100 & op1 = 0 & ar = 0 & as & at = 0 & op0 = 0 { SAR = (as & 0x1f); } -# SSX - Store Single Indexed, pg. 540. +# SSX - Store Single Indexed (RRR), pg. 540. :ssx fr, as, at is op2 = 0b0100 & op1 = 0b1000 & fr & as & at & op0 = 0 { local addr:4 = as+at; *:4 addr = fr; } -# SSXU - Store Single Indexed with Update, pg. 541. +# SSXU - Store Single Indexed with Update (RRR), pg. 541. :ssxu fr, as, at is op2 = 0b0101 & op1 = 0b1000 & fr & as & at & op0 = 0 { local addr:4 = as+at; *:4 addr = fr; as = addr; } -# SUB - Subtract, pg. 542. +# SUB - Subtract (RRR), pg. 542. :sub ar, as, at is op2 = 0b1100 & op1 = 0 & ar & as & at & op0 = 0 { ar = as - at; } -# SUB.S - Subtract Single, pg. 543. +# SUB.S - Subtract Single (RRR), pg. 543. :sub.s fr, fs, ft is op2 = 0b0001 & op1 = 0b1010 & fr & fs & ft & op0 = 0 { fr = fs f- ft; } -# SUBX2 - Subtract with Shift by 1, pg. 544. +# SUBX2 - Subtract with Shift by 1 (RRR), pg. 544. :subx2 ar, as, at is op2 = 0b1101 & op1 = 0 & ar & as & at & op0 = 0 { ar = (as << 1) - at; } -# SUBX4 - Subtract with Shift by 2, pg. 545. +# SUBX4 - Subtract with Shift by 2 (RRR), pg. 545. :subx4 ar, as, at is op2 = 0b1110 & op1 = 0 & ar & as & at & op0 = 0 { ar = (as << 2) - at; } -# SUBX8 - Subtract with Shift by 3, pg. 546. +# SUBX8 - Subtract with Shift by 3 (RRR), pg. 546. :subx8 ar, as, at is op2 = 0b1111 & op1 = 0 & ar & as & at & op0 = 0 { ar = (as << 3) - at; } -# SYSCALL - System Call, pg. 547. +# SYSCALL - System Call (RRR), pg. 547. :syscall is op2 = 0 & op1 = 0 & ar = 0b0101 & as = 0 & at = 0 & op0 = 0 { syscall(); } -# TRUNC.S - Truncate Single to Fixed, pg. 548 -:trunc.s ar, fs, u4_4_7 is op2 = 0b1001 & op1 = 0b1010 & ar & fs & u4_4_7 & op0 = 0 { - local scale:4 = 1 << u4_4_7; +# TRUNC.S - Truncate Single to Fixed (RRR), pg. 548 +:trunc.s ar, fs, op_t is op2 = 0b1001 & op1 = 0b1010 & ar & fs & op_t & op0 = 0 { + local scale:4 = 1 << op_t; local result = fs f* int2float(scale); isNan:1 = nan(result); if (isNan) goto ; @@ -1326,36 +1327,36 @@ rfi_eps: ptr is u4_8_11 [ ptr = $(EPS_BASE) + (4 * u4_8_11); ] { export *[regist } -# UEQ.S - Compare Single Unordered or Equal, pg. 549. +# UEQ.S - Compare Single Unordered or Equal (RRR), pg. 549. :ueq.s br, fs, ft is op2 = 0b0011 & op1 = 0b1011 & br & fs & ft & op0 = 0 { br = nan(fs) || nan(ft) || fs f== ft; } -# UFLOAT.S - Convert Unsigned Fixed to Single, pg. 550. -:ufloat.s fr, as, u4_4_7 is op2 = 0b1101 & op1 = 0b1010 & fr & as & u4_4_7 & op0 = 0 { +# UFLOAT.S - Convert Unsigned Fixed to Single (RRR), pg. 550. +:ufloat.s fr, as, op_t is op2 = 0b1101 & op1 = 0b1010 & fr & as & op_t & op0 = 0 { local tmp:8 = zext(as); - local scale:4 = 1 << u4_4_7; + local scale:4 = 1 << op_t; fr = int2float(tmp) f/ int2float(scale); } -# ULE.S - Compare Single Unordered or Less Than or Equal, pg. 551. +# ULE.S - Compare Single Unordered or Less Than or Equal (RRR), pg. 551. :ule.s br, fs, ft is op2 = 0b0111 & op1 = 0b1011 & br & fs & ft & op0 = 0 { br = nan(fs) || nan(ft) || fs f<= ft; } -# ULT.S - Compare Single Unordered or Less Than, pg. 552. +# ULT.S - Compare Single Unordered or Less Than (RRR), pg. 552. :ult.s br, fs, ft is op2 = 0b0101 & op1 = 0b1011 & br & fs & ft & op0 = 0 { br = nan(fs) || nan(ft) || fs f< ft; } -# UN.S - Compare Single Unordered, pg. 554. +# UN.S - Compare Single Unordered (RRR), pg. 554. :un.s br, fs, ft is op2 = 0b0001 & op1 = 0b1011 & br & fs & ft & op0 = 0 { br = nan(fs) || nan(ft); } -# UTRUNC.S - Truncate Single to Fixed Unsigned, pg. 555. -:utrunc.s ar, fs, u4_4_7 is op2 = 0b1110 & op1 = 0b1010 & ar & fs & u4_4_7 & op0 = 0 { - local scale:4 = int2float(1:2 << u4_4_7:2); +# UTRUNC.S - Truncate Single to Fixed Unsigned (RRR), pg. 555. +:utrunc.s ar, fs, op_t is op2 = 0b1110 & op1 = 0b1010 & ar & fs & op_t & op0 = 0 { + local scale:4 = int2float(1:2 << op_t:2); local tmp:8 = trunc(fs f* scale); local posof = nan(fs) || (tmp >> 16) != 0; local negof = tmp s< 0; @@ -1363,73 +1364,73 @@ rfi_eps: ptr is u4_8_11 [ ptr = $(EPS_BASE) + (4 * u4_8_11); ] { export *[regist ar = zext(posof)*0xffffffff + zext(negof)*0x80000000 + zext(noof)*tmp:4; } -# WAITI - Wait Interrupt, pg. 556. -:waiti u4_8_11 is op2 = 0 & op1 = 0 & ar = 0b0111 & u4_8_11 & at = 0 & op0 = 0 { - waiti(u4_8_11:4); +# WAITI - Wait Interrupt (RRR), pg. 556. +:waiti op_s is op2 = 0 & op1 = 0 & ar = 0b0111 & op_s & at = 0 & op0 = 0 { + waiti(op_s:4); } -# WDTLB - Write Data TLB Entry, pg. 557. +# WDTLB - Write Data TLB Entry (RRR), pg. 557. :wdtlb at, as is op2 = 0b0101 & op1 = 0 & ar = 0b1110 & as & at & op0 = 0 { wdtlb(as, at); } -# WER - Write External Register, pg. 558. +# WER - Write External Register (RRR), pg. 558. :wer as, at is op2 = 0b0100 & op1 = 0 & ar = 0b0111 & as & at & op0 = 0 { wer(as, at); } -# WFR - Move AR to FR, pg. 559. +# WFR - Move AR to FR (RRR), pg. 559. :wfr fr, as is op2 = 0b1111 & op1 = 0b1010 & fr & as & at = 0b0101 & op0 = 0 { fr = as; } -# WITLB - Write Instruction TLB Entry, pg. 560. +# WITLB - Write Instruction TLB Entry (RRR), pg. 560. :witlb at, as is op2 = 0b0101 & op1 = 0 & ar = 0b0110 & as & at & op0 = 0 { witlb(as, at); } -# WSR - Write Special Register, pg. 561. +# WSR - Write Special Register (RRR), pg. 561. :wsr at, sr is op2 = 0b0001 & op1 = 0b0011 & sr & at & op0 = 0 { wsr(sr:1, at); } -# WUR - Write User Register, pg. 563. +# WUR - Write User Register (RSR), pg. 563. :wur at, sr is op2 = 0b1111 & op1 = 0b0011 & sr & at & op0 = 0 { wur(sr:1, at); } -# XOR - Bitwise Exclusive Or, pg. 564. +# XOR - Bitwise Exclusive Or (RRR), pg. 564. :xor ar, as, at is op2 = 0b0011 & op1 = 0 & ar & as & at & op0 = 0 { ar = as ^ at; } -# XORB - Boolean Exclusive Or, pg. 565. +# XORB - Boolean Exclusive Or (RRR), pg. 565. :xorb br, bs, bt is op2 = 0b0100 & op1 = 0b0010 & br & bs & bt & op0 = 0 { br = bs ^^ bt; } -# XSR - Exchange Special Register, pg. 566. +# XSR - Exchange Special Register (RSR), pg. 566. :xsr at, sr is op2 = 0b0110 & op1 = 0b0001 & sr & at & op0 = 0 { at = xsr(sr:1, at); } ## MAC16 option ## -# LDDEC - Load with Autodecrement, pg. 386. -:lddec "MAC16_REGS[" mw_12_13 "]", as is op2 = 0b1001 & op1 = 0 & u2_14_15 = 0 & mw_12_13 & as & at = 0 & op0 = 0b0100 { +# LDDEC - Load with Autodecrement (RRR), pg. 386. +:lddec "MAC16_REGS[" mw "]", as is op2 = 0b1001 & op1 = 0 & op_r_2_2 = 0 & mw & as & at = 0 & op0 = 0b0100 { local ptr:4 = as - 4; - mw_12_13 = *:4 ptr; + mw = *:4 ptr; as = ptr; } -# LDINC - Load with Autoincrement, pg. 387. -:ldinc "MAC16_REGS[" mw_12_13 "]", as is op2 = 0b1000 & op1 = 0 & u2_14_15 = 0 & mw_12_13 & as & at = 0 & op0 = 0b0100 { +# LDINC - Load with Autoincrement (RRR), pg. 387. +:ldinc "MAC16_REGS[" mw "]", as is op2 = 0b1000 & op1 = 0 & op_r_2_2 = 0 & mw & as & at = 0 & op0 = 0b0100 { local ptr:4 = as + 4; - mw_12_13 = *:4 ptr; + mw = *:4 ptr; as = ptr; } -# MUL.AA.* - Signed Multiply, pg. 431. +# MUL.AA.* - Signed Multiply (RRR), pg. 431. :mul.aa.ll as, at is op2 = 0x7 & op1 = 0x4 & ar = 0 & as & at & op0 = 0x4 { tm1:2 = as:2; tm2:2 = at:2; @@ -1461,104 +1462,104 @@ rfi_eps: ptr is u4_8_11 [ ptr = $(EPS_BASE) + (4 * u4_8_11); ] { export *[regist ACC = sext(M1:2) * sext(M2:2); } -# MUL.AD.* - Signed Multiply, pg. 432. -:mul.ad.ll as, m2m3_6_6 is op2 = 0x3 & op1 = 0x4 & ar = 0 & as & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +# MUL.AD.* - Signed Multiply (RRR), pg. 432. +:mul.ad.ll as, my is op2 = 0x3 & op1 = 0x4 & ar = 0 & as & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { tm1:2 = as:2; - tm2:2 = m2m3_6_6:2; + tm2:2 = my:2; M1 = zext(tm1); M2 = zext(tm2); ACC = sext(M1:2) * sext(M2:2); } -:mul.ad.hl as, m2m3_6_6 is op2 = 0x3 & op1 = 0x5 & ar = 0 & as & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +:mul.ad.hl as, my is op2 = 0x3 & op1 = 0x5 & ar = 0 & as & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { tm1:2 = as(2); - tm2:2 = m2m3_6_6:2; + tm2:2 = my:2; M1 = zext(tm1); M2 = zext(tm2); ACC = sext(M1:2) * sext(M2:2); } -:mul.ad.lh as, m2m3_6_6 is op2 = 0x3 & op1 = 0x6 & ar = 0 & as & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +:mul.ad.lh as, my is op2 = 0x3 & op1 = 0x6 & ar = 0 & as & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { tm1:2 = as:2; - tm2:2 = m2m3_6_6(2); + tm2:2 = my(2); M1 = zext(tm1); M2 = zext(tm2); ACC = sext(M1:2) * sext(M2:2); } -:mul.ad.hh as, m2m3_6_6 is op2 = 0x3 & op1 = 0x7 & ar = 0 & as & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +:mul.ad.hh as, my is op2 = 0x3 & op1 = 0x7 & ar = 0 & as & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { tm1:2 = as(2); - tm2:2 = m2m3_6_6(2); + tm2:2 = my(2); M1 = zext(tm1); M2 = zext(tm2); ACC = sext(M1:2) * sext(M2:2); } -# MUL.AD.* - Signed Multiply, pg. 433. -:mul.da.ll m0m1_14_14, at is op2 = 0x6 & at & op1 = 0x4 & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & op0 = 0x4 { - tm1:2 = m0m1_14_14:2; +# MUL.AD.* - Signed Multiply (RRR), pg. 433. +:mul.da.ll mx, at is op2 = 0x6 & at & op1 = 0x4 & as = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & op0 = 0x4 { + tm1:2 = mx:2; tm2:2 = at:2; M1 = zext(tm1); M2 = zext(tm2); ACC = sext(M1:2) * sext(M2:2); } -:mul.da.hl m0m1_14_14, at is op2 = 0x6 & op1 = 0x5 & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & at & op0 = 0x4 { - tm1:2 = m0m1_14_14:2; +:mul.da.hl mx, at is op2 = 0x6 & op1 = 0x5 & as = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & at & op0 = 0x4 { + tm1:2 = mx:2; tm2:2 = at(2); M1 = zext(tm1); M2 = zext(tm2); ACC = sext(M1:2) * sext(M2:2); } -:mul.da.lh m0m1_14_14, at is op2 = 0x6 & op1 = 0x6 & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & at & op0 = 0x4 { - tm1:2 = m0m1_14_14(2); +:mul.da.lh mx, at is op2 = 0x6 & op1 = 0x6 & as = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & at & op0 = 0x4 { + tm1:2 = mx(2); tm2:2 = at:2; M1 = zext(tm1); M2 = zext(tm2); ACC = sext(M1:2) * sext(M2:2); } -:mul.da.hh m0m1_14_14, at is op2 = 0x6 & op1 = 0x7 & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & at & op0 = 0x4 { - tm1:2 = m0m1_14_14(2); +:mul.da.hh mx, at is op2 = 0x6 & op1 = 0x7 & as = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & at & op0 = 0x4 { + tm1:2 = mx(2); tm2:2 = at(2); M1 = zext(tm1); M2 = zext(tm2); ACC = sext(M1:2) * sext(M2:2); } -# MUL.AD.* - Signed Multiply, pg. 434. -:mul.dd.ll m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0x4 & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { - tm1:2 = m0m1_14_14:2; - tm2:2 = m2m3_6_6:2; +# MUL.AD.* - Signed Multiply (RRR), pg. 434. +:mul.dd.ll mx, my is op2 = 0x2 & op1 = 0x4 & ar = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { + tm1:2 = mx:2; + tm2:2 = my:2; M1 = zext(tm1); M2 = zext(tm2); ACC = sext(M1:2) * sext(M2:2); } -:mul.dd.hl m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0x5 & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { - tm1:2 = m0m1_14_14(2); - tm2:2 = m2m3_6_6:2; +:mul.dd.hl mx, my is op2 = 0x2 & op1 = 0x5 & ar = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { + tm1:2 = mx(2); + tm2:2 = my:2; M1 = zext(tm1); M2 = zext(tm2); ACC = sext(M1:2) * sext(M2:2); } -:mul.dd.lh m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0x6 & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { - tm1:2 = m0m1_14_14:2; - tm2:2 = m2m3_6_6(2); +:mul.dd.lh mx, my is op2 = 0x2 & op1 = 0x6 & ar = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { + tm1:2 = mx:2; + tm2:2 = my(2); M1 = zext(tm1); M2 = zext(tm2); ACC = sext(M1:2) * sext(M2:2); } -:mul.dd.hh m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0x7 & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { - tm1:2 = m0m1_14_14(2); - tm2:2 = m2m3_6_6(2); +:mul.dd.hh mx, my is op2 = 0x2 & op1 = 0x7 & ar = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { + tm1:2 = mx(2); + tm2:2 = my(2); M1 = zext(tm1); M2 = zext(tm2); ACC = sext(M1:2) * sext(M2:2); } -# MULA.AA.* - Signed Multiply, pg. 431. +# MULA.AA.* - Signed Multiply (RRR), pg. 431. :mula.aa.ll as, at is op2 = 0x7 & op1 = 0x8 & ar = 0 & as & at & op0 = 0x4 { tm1:2 = as:2; tm2:2 = at:2; @@ -1590,281 +1591,281 @@ rfi_eps: ptr is u4_8_11 [ ptr = $(EPS_BASE) + (4 * u4_8_11); ] { export *[regist ACC = ACC + (sext(M1:2) * sext(M2:2)); } -:mula.ad.ll as, m2m3_6_6 is op2 = 0x3 & op1 = 0x8 & ar = 0 & as & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +:mula.ad.ll as, my is op2 = 0x3 & op1 = 0x8 & ar = 0 & as & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { tm1:2 = as:2; - tm2:2 = m2m3_6_6:2; + tm2:2 = my:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); } -:mula.ad.hl as, m2m3_6_6 is op2 = 0x3 & op1 = 0x9 & ar = 0 & as & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +:mula.ad.hl as, my is op2 = 0x3 & op1 = 0x9 & ar = 0 & as & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { tm1:2 = as(2); - tm2:2 = m2m3_6_6:2; + tm2:2 = my:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); } -:mula.ad.lh as, m2m3_6_6 is op2 = 0x3 & op1 = 0xa & ar = 0 & as & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +:mula.ad.lh as, my is op2 = 0x3 & op1 = 0xa & ar = 0 & as & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { tm1:2 = as:2; - tm2:2 = m2m3_6_6(2); + tm2:2 = my(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); } -:mula.ad.hh as, m2m3_6_6 is op2 = 0x3 & op1 = 0xb & ar = 0 & as & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +:mula.ad.hh as, my is op2 = 0x3 & op1 = 0xb & ar = 0 & as & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { tm1:2 = as(2); - tm2:2 = m2m3_6_6(2); + tm2:2 = my(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); } -:mula.da.ll m0m1_14_14, at is op2 = 0x6 & at & op1 = 0x8 & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & op0 = 0x4 { - tm1:2 = m0m1_14_14:2; +:mula.da.ll mx, at is op2 = 0x6 & at & op1 = 0x8 & as = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & op0 = 0x4 { + tm1:2 = mx:2; tm2:2 = at:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); } -:mula.da.hl m0m1_14_14, at is op2 = 0x6 & op1 = 0x9 & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & at & op0 = 0x4 { - tm1:2 = m0m1_14_14:2; +:mula.da.hl mx, at is op2 = 0x6 & op1 = 0x9 & as = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & at & op0 = 0x4 { + tm1:2 = mx:2; tm2:2 = at(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); } -:mula.da.lh m0m1_14_14, at is op2 = 0x6 & op1 = 0xa & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & at & op0 = 0x4 { - tm1:2 = m0m1_14_14(2); +:mula.da.lh mx, at is op2 = 0x6 & op1 = 0xa & as = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & at & op0 = 0x4 { + tm1:2 = mx(2); tm2:2 = at:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); } -:mula.da.hh m0m1_14_14, at is op2 = 0x6 & op1 = 0xb & as = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & at & op0 = 0x4 { - tm1:2 = m0m1_14_14(2); +:mula.da.hh mx, at is op2 = 0x6 & op1 = 0xb & as = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & at & op0 = 0x4 { + tm1:2 = mx(2); tm2:2 = at(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); } -:mula.dd.ll m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0x8 & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { - tm1:2 = m0m1_14_14:2; - tm2:2 = m2m3_6_6:2; +:mula.dd.ll mx, my is op2 = 0x2 & op1 = 0x8 & ar = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { + tm1:2 = mx:2; + tm2:2 = my:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); } -:mula.dd.hl m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0x9 & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { - tm1:2 = m0m1_14_14(2); - tm2:2 = m2m3_6_6:2; +:mula.dd.hl mx, my is op2 = 0x2 & op1 = 0x9 & ar = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { + tm1:2 = mx(2); + tm2:2 = my:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); } -:mula.dd.lh m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0xa & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { - tm1:2 = m0m1_14_14:2; - tm2:2 = m2m3_6_6(2); +:mula.dd.lh mx, my is op2 = 0x2 & op1 = 0xa & ar = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { + tm1:2 = mx:2; + tm2:2 = my(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); } -:mula.dd.hh m0m1_14_14, m2m3_6_6 is op2 = 0x2 & op1 = 0xb & ar = 0 & u1_15_15 = 0 & u2_12_13 = 0 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { - tm1:2 = m0m1_14_14(2); - tm2:2 = m2m3_6_6(2); +:mula.dd.hh mx, my is op2 = 0x2 & op1 = 0xb & ar = 0 & op_r_3 = 0 & op_r_0_2 = 0 & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { + tm1:2 = mx(2); + tm2:2 = my(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); } -# Signed Mult/Accum, Ld/Autodec MULA.DA.*.LDDEC, pg. 441. -:mula.da.ll.lddec mw_12_13, as, m0m1_14_14, at is op2 = 0x5 & at & op1 = 0x8 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & op0 = 0x4 { +# Signed Mult/Accum, Ld/Autodec MULA.DA.*.LDDEC (RRR), pg. 441. +:mula.da.ll.lddec mw, as, mx, at is op2 = 0x5 & at & op1 = 0x8 & as & op_r_3 = 0 & mw & mx & op0 = 0x4 { local vaddr:4 = as - 4; - tm1:2 = m0m1_14_14:2; + tm1:2 = mx:2; tm2:2 = at:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -:mula.da.hl.lddec mw_12_13, as, m0m1_14_14, at is op2 = 0x5 & op1 = 0x9 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & at & op0 = 0x4 { +:mula.da.hl.lddec mw, as, mx, at is op2 = 0x5 & op1 = 0x9 & as & op_r_3 = 0 & mw & mx & at & op0 = 0x4 { local vaddr:4 = as - 4; - tm1:2 = m0m1_14_14:2; + tm1:2 = mx:2; tm2:2 = at(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -:mula.da.lh.lddec mw_12_13, as, m0m1_14_14, at is op2 = 0x5 & op1 = 0xa & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & at & op0 = 0x4 { +:mula.da.lh.lddec mw, as, mx, at is op2 = 0x5 & op1 = 0xa & as & op_r_3 = 0 & mw & mx & at & op0 = 0x4 { local vaddr:4 = as - 4; - tm1:2 = m0m1_14_14(2); + tm1:2 = mx(2); tm2:2 = at:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -:mula.da.hh.lddec mw_12_13, as, m0m1_14_14, at is op2 = 0x5 & op1 = 0xb & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & at & op0 = 0x4 { +:mula.da.hh.lddec mw, as, mx, at is op2 = 0x5 & op1 = 0xb & as & op_r_3 = 0 & mw & mx & at & op0 = 0x4 { local vaddr:4 = as - 4; - tm1:2 = m0m1_14_14(2); + tm1:2 = mx(2); tm2:2 = at(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -# Signed Mult/Accum, Ld/Autoinc MULA.DA.*.LDINC, pg. 443. -:mula.da.ll.ldinc mw_12_13, as, m0m1_14_14, at is op2 = 0x4 & at & op1 = 0x8 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & op0 = 0x4 { +# Signed Mult/Accum, Ld/Autoinc MULA.DA.*.LDINC (RRR), pg. 443. +:mula.da.ll.ldinc mw, as, mx, at is op2 = 0x4 & at & op1 = 0x8 & as & op_r_3 = 0 & mw & mx & op0 = 0x4 { local vaddr:4 = as + 4; - tm1:2 = m0m1_14_14:2; + tm1:2 = mx:2; tm2:2 = at:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -:mula.da.hl.ldinc mw_12_13, as, m0m1_14_14, at is op2 = 0x4 & op1 = 0x9 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & at & op0 = 0x4 { +:mula.da.hl.ldinc mw, as, mx, at is op2 = 0x4 & op1 = 0x9 & as & op_r_3 = 0 & mw & mx & at & op0 = 0x4 { local vaddr:4 = as + 4; - tm1:2 = m0m1_14_14:2; + tm1:2 = mx:2; tm2:2 = at(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -:mula.da.lh.ldinc mw_12_13, as, m0m1_14_14, at is op2 = 0x4 & op1 = 0xa & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & at & op0 = 0x4 { +:mula.da.lh.ldinc mw, as, mx, at is op2 = 0x4 & op1 = 0xa & as & op_r_3 = 0 & mw & mx & at & op0 = 0x4 { local vaddr:4 = as + 4; - tm1:2 = m0m1_14_14(2); + tm1:2 = mx(2); tm2:2 = at:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -:mula.da.hh.ldinc mw_12_13, as, m0m1_14_14, at is op2 = 0x4 & op1 = 0xb & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & at & op0 = 0x4 { +:mula.da.hh.ldinc mw, as, mx, at is op2 = 0x4 & op1 = 0xb & as & op_r_3 = 0 & mw & mx & at & op0 = 0x4 { local vaddr:4 = as + 4; - tm1:2 = m0m1_14_14(2); + tm1:2 = mx(2); tm2:2 = at(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -# Signed Mult/Accum, Ld/Autodec MULA.DD.*.LDDEC, pg. 446. -:mula.dd.ll.lddec mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x1 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op1 = 0x8 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & op0 = 0x4 { +# Signed Mult/Accum, Ld/Autodec MULA.DD.*.LDDEC (RRR), pg. 446. +:mula.dd.ll.lddec mw, as, mx, my is op2 = 0x1 & op1 = 0x8 & as & op_r_3 = 0 & op_t_3 = 0 & op_t_0_2 = 0 & my & mw & mx & op0 = 0x4 { local vaddr:4 = as - 4; - tm1:2 = m0m1_14_14:2; - tm2:2 = m2m3_6_6:2; + tm1:2 = mx:2; + tm2:2 = my:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -:mula.dd.hl.lddec mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x1 & op1 = 0x9 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +:mula.dd.hl.lddec mw, as, mx, my is op2 = 0x1 & op1 = 0x9 & as & op_r_3 = 0 & mw & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { local vaddr:4 = as - 4; - tm1:2 = m0m1_14_14:2; - tm2:2 = m2m3_6_6(2); + tm1:2 = mx:2; + tm2:2 = my(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -:mula.dd.lh.lddec mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x1 & op1 = 0xa & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +:mula.dd.lh.lddec mw, as, mx, my is op2 = 0x1 & op1 = 0xa & as & op_r_3 = 0 & mw & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { local vaddr:4 = as - 4; - tm1:2 = m0m1_14_14(2); - tm2:2 = m2m3_6_6:2; + tm1:2 = mx(2); + tm2:2 = my:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -:mula.dd.hh.lddec mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x1 & op1 = 0xb & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +:mula.dd.hh.lddec mw, as, mx, my is op2 = 0x1 & op1 = 0xb & as & op_r_3 = 0 & mw & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { local vaddr:4 = as - 4; - tm1:2 = m0m1_14_14(2); - tm2:2 = m2m3_6_6(2); + tm1:2 = mx(2); + tm2:2 = my(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -# Signed Mult/Accum, Ld/Autoinc MULA.DD.*.LDINC, pg. 448. -:mula.da.ll.ldinc mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x0 & op1 = 0x8 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +# Signed Mult/Accum, Ld/Autoinc MULA.DD.*.LDINC (RRR), pg. 448. +:mula.da.ll.ldinc mw, as, mx, my is op2 = 0x0 & op1 = 0x8 & as & op_r_3 = 0 & mw & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { local vaddr:4 = as + 4; - tm1:2 = m0m1_14_14:2; - tm2:2 = m2m3_6_6:2; + tm1:2 = mx:2; + tm2:2 = my:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -:mula.da.hl.ldinc mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x0 & op1 = 0x9 & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +:mula.da.hl.ldinc mw, as, mx, my is op2 = 0x0 & op1 = 0x9 & as & op_r_3 = 0 & mw & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { local vaddr:4 = as + 4; - tm1:2 = m0m1_14_14:2; - tm2:2 = m2m3_6_6(2); + tm1:2 = mx:2; + tm2:2 = my(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -:mula.da.lh.ldinc mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x0 & op1 = 0xa & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +:mula.da.lh.ldinc mw, as, mx, my is op2 = 0x0 & op1 = 0xa & as & op_r_3 = 0 & mw & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { local vaddr:4 = as + 4; - tm1:2 = m0m1_14_14(2); - tm2:2 = m2m3_6_6:2; + tm1:2 = mx(2); + tm2:2 = my:2; M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -:mula.da.hh.ldinc mw_12_13, as, m0m1_14_14, m2m3_6_6 is op2 = 0x0 & op1 = 0xb & as & u1_15_15 = 0 & mw_12_13 & m0m1_14_14 & u1_7_7 = 0 & t2_4_5 = 0 & m2m3_6_6 & op0 = 0x4 { +:mula.da.hh.ldinc mw, as, mx, my is op2 = 0x0 & op1 = 0xb & as & op_r_3 = 0 & mw & mx & op_t_3 = 0 & op_t_0_2 = 0 & my & op0 = 0x4 { local vaddr:4 = as + 4; - tm1:2 = m0m1_14_14(2); - tm2:2 = m2m3_6_6(2); + tm1:2 = mx(2); + tm2:2 = my(2); M1 = zext(tm1); M2 = zext(tm2); ACC = ACC + (sext(M1:2) * sext(M2:2)); as = vaddr; - mw_12_13 = *:4 vaddr; + mw = *:4 vaddr; } -# UMUL.AA.* - Unsigned Multiply, pg. 553. +# UMUL.AA.* - Unsigned Multiply (RRR), pg. 553. :umul.aa.ll as, at is op2 = 0x7 & op1 = 0x0 & ar = 0 & as & at & op0 = 0x4 { tm1:2 = as:2; tm2:2 = at:2; @@ -1898,9 +1899,9 @@ rfi_eps: ptr is u4_8_11 [ ptr = $(EPS_BASE) + (4 * u4_8_11); ] { export *[regist ## Loop Option ## -LoopOffset8: loc is u8_16_23 [ loc = inst_start + u8_16_23 + 4; ] { export *:4 loc; } +LoopOffset8: loc is ri8_i8 [ loc = inst_start + ri8_i8 + 4; ] { export *:4 loc; } -# LOOP - Loop, pg. 392. +# LOOP - Loop (BRI8), pg. 392. :loop as, LoopOffset8 is LoopOffset8 & ar = 8 & as & at = 0b0111 & op0 = 6 [ loopMode=1; loopEnd = 1; globalset(LoopOffset8, loopEnd); ] { LCOUNT = as - 1; @@ -1908,7 +1909,7 @@ LoopOffset8: loc is u8_16_23 [ loc = inst_start + u8_16_23 + 4; ] { export *:4 l LEND = &LoopOffset8; } -# LOOPGTZ - Loop if Greater Than Zero, pg. 394. +# LOOPGTZ - Loop if Greater Than Zero (BRI8), pg. 394. :loopgtz as, LoopOffset8 is LoopOffset8 & ar = 0b1010 & as & at = 0b0111 & op0 = 0b0110 [ loopMode=1; loopEnd = 1; globalset(LoopOffset8, loopEnd); ] { LCOUNT = as - 1; @@ -1917,7 +1918,7 @@ LoopOffset8: loc is u8_16_23 [ loc = inst_start + u8_16_23 + 4; ] { export *:4 l if (as s<= 0) goto LoopOffset8; } -# LOOPNEZ - Loop if Not Equal Zero, pg. 396. +# LOOPNEZ - Loop if Not Equal Zero (BRI8), pg. 396. :loopnez as, LoopOffset8 is LoopOffset8 & ar = 0b1001 & as & at = 0b0111 & op0 = 0b0110 [ loopMode=1; loopEnd = 1; globalset(LoopOffset8, loopEnd); ] { LCOUNT = as - 1; diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensaMain.sinc b/Ghidra/Processors/Xtensa/data/languages/xtensaMain.sinc index 55a1e2e25d..6aee9c3ae7 100644 --- a/Ghidra/Processors/Xtensa/data/languages/xtensaMain.sinc +++ b/Ghidra/Processors/Xtensa/data/languages/xtensaMain.sinc @@ -87,15 +87,15 @@ attach variables [ br bs bt ] [ # bits are named foo_LL.LM_ML.MM, where LL is the least significant bits of the least # singificant operand half, LM the most significant bits of the least significant operand half, etc. -attach variables [ mw_12_13 ] [ +attach variables [ mw ] [ M0 M1 M2 M3 ]; -attach variables [ m2m3_6_6 ] [ +attach variables [ my ] [ M2 M3 ]; -attach variables [ m0m1_14_14 ] [ +attach variables [ mx ] [ M0 M1 ]; @@ -184,62 +184,62 @@ define pcodeop xsr; # bits are named foo_LL_LM_ML_MM, where LL is the least significant bits of the least # singificant operand half, LM the most significant bits of the least significant operand half, etc. -srel_16_23: rel is s8_16_23 [ rel = inst_start + s8_16_23 + 4; ] { export *:4 rel; } +ri8_srel: rel is ri8_si8 [ rel = inst_start + ri8_si8 + 4; ] { export *:4 rel; } -srel_12_23: rel is s12_12_23 [ rel = inst_start + s12_12_23 + 4; ] { export *:4 rel; } +bri12_srel: rel is bri12_si12 [ rel = inst_start + bri12_si12 + 4; ] { export *:4 rel; } -srel_6_23: rel is s8_6_23 [ rel = inst_start + s8_6_23 + 4; ] { export *:4 rel; } - -urel_12_15_4_5: rel is n_u2_4_5 & n_u4_12_15 [ - rel = inst_start + ((n_u2_4_5 << 4) | n_u4_12_15) + 4; +ri6_rel: rel is ri6_i6_4_2 & ri6_i6_0_4 [ + rel = inst_start + ((ri6_i6_4_2 << 4) | ri6_i6_0_4) + 4; ] { export *:4 rel; } -srel_6_23_sb2: rel is s8_6_23 [ - rel = (inst_start & ~3) + ( s8_6_23 << 2 ) + 4; +call_srel: rel is call_o18 [ rel = inst_start + call_o18 + 4; ] { export *:4 rel; } + +call_srel_sh2: rel is call_o18 [ + rel = (inst_start & ~3) + ( call_o18 << 2 ) + 4; ] { export *:4 rel; } -srel_8_23_oex_sb2: rel is u16_8_23 [ - rel = ((inst_start + 3) & ~3) + ((u16_8_23 | 0xffff0000) << 2); +srel_oex_sh2: rel is ri16_i16 [ + rel = ((inst_start + 3) & ~3) + ((ri16_i16 | 0xffff0000) << 2); ] { export *:4 rel; } # Immediates split across the instruction. -u5_8_11_20: tmp is u1_20 & u4_8_11 [ tmp = (u1_20 << 4) | u4_8_11; ] { export *[const]:4 tmp; } -u5_4_7_20: tmp is u1_20 & u4_4_7 [ tmp = 32 - ((u1_20 << 4) | u4_4_7); ] { export *[const]:4 tmp; } -u5_8_11_16: tmp is u1_16 & u4_8_11 [ tmp = (u1_16 << 4) | u4_8_11; ] { export *[const]:4 tmp; } -u5_4_7_12: tmp is u1_12 & u4_4_7 [ tmp = (u1_12 << 4) | u4_4_7; ] { export *[const]:4 tmp; } -u5_8_11_4: tmp is u1_4 & u4_8_11 [ tmp = (u1_4 << 4) | u4_8_11; ] { export *[const]:4 tmp; } +u5_8_11_20: tmp is op2_0 & op_s [ tmp = (op2_0 << 4) | op_s; ] { export *[const]:4 tmp; } +u5_4_7_20: tmp is op2_0 & op_t [ tmp = 32 - ((op2_0 << 4) | op_t); ] { export *[const]:4 tmp; } +u5_8_11_16: tmp is op1_0 & op_s [ tmp = (op1_0 << 4) | op_s; ] { export *[const]:4 tmp; } +u5_4_7_12: tmp is op_r_0 & op_t [ tmp = (op_r_0 << 4) | op_t; ] { export *[const]:4 tmp; } +u5_8_11_4: tmp is op_t_0 & op_s [ tmp = (op_t_0 << 4) | op_s; ] { export *[const]:4 tmp; } # Signed 12-bit (extended to 16) immediate, used by MOVI. -s16_16_23_8_11: tmp is s4_8_11 & u8_16_23 [ - tmp = (s4_8_11 << 8) | u8_16_23; +movi_si16: tmp is op_st_i8 & ri8_i8 [ + tmp = (op_st_i8 << 8) | ri8_i8; ] { export *[const]:2 tmp; } # An “asymmetric” immediate from -32..95, used by MOVI.N. -n_s8_12_15_4_6_asymm: tmp is n_s3_4_6 & n_s4_12_15 [ - tmp = ((((n_s3_4_6 & 7) << 4) | (n_s4_12_15 & 15)) | - ((((n_s3_4_6 >> 2) & 1) & ((n_s3_4_6 >> 1) & 1)) << 7)); +movin_si8: tmp is n_op_s_0_3 & ri6_si6_0_4 [ + tmp = ((((n_op_s_0_3 & 7) << 4) | (ri6_si6_0_4 & 15)) | + ((((n_op_s_0_3 >> 2) & 1) & ((n_op_s_0_3 >> 1) & 1)) << 7)); ] { export *[const]:1 tmp; } # Immediates shifted or with offset. -s16_16_23_sb8: tmp is s8_16_23 [ tmp = s8_16_23 << 8; ] { export *[const]:4 tmp; } -u15_12_23_sb3: tmp is u12_12_23 [ tmp = u12_12_23 << 3; ] { export *[const]:4 tmp; } -u10_16_23_sb2: tmp is u8_16_23 [ tmp = u8_16_23 << 2; ] { export *[const]:4 tmp; } -u9_16_23_sb1: tmp is u8_16_23 [ tmp = u8_16_23 << 1; ] { export *[const]:4 tmp; } -u5_20_23_plus1: tmp is u4_20_23 [ tmp = u4_20_23 + 1; ] { export *[const]:4 tmp; } -u8_20_23_sb4: tmp is u4_20_23 [ tmp = u4_20_23 << 4; ] { export *[const]:4 tmp; } -u5_4_7_plus7: tmp is u4_4_7 [ tmp = u4_4_7 + 7; ] { export *[const]:4 tmp; } +ri8_si8_sh8: tmp is ri8_si8 [ tmp = ri8_si8 << 8; ] { export *[const]:4 tmp; } +bri12_i12_sh3: tmp is bri12_i12 [ tmp = bri12_i12 << 3; ] { export *[const]:4 tmp; } +ri8_i8_sh2: tmp is ri8_i8 [ tmp = ri8_i8 << 2; ] { export *[const]:4 tmp; } +u9_16_23_sb1: tmp is ri8_i8 [ tmp = ri8_i8 << 1; ] { export *[const]:4 tmp; } +u5_20_23_plus1: tmp is op2 [ tmp = op2 + 1; ] { export *[const]:4 tmp; } +u8_20_23_sb4: tmp is op2 [ tmp = op2 << 4; ] { export *[const]:4 tmp; } +u5_4_7_plus7: tmp is op_t [ tmp = op_t + 7; ] { export *[const]:4 tmp; } -n_u6_12_15_sb2: tmp is n_u4_12_15 [ tmp = n_u4_12_15 << 2; ] { export *[const]:4 tmp; } +n_u6_12_15_sb2: tmp is ri6_i6_0_4 [ tmp = ri6_i6_0_4 << 2; ] { export *[const]:4 tmp; } # One-extended. FIXME: Verify this. Only used by [LS]32E (window extension), which aren’t yet # implemented. -s5_12_15_oex: tmp is u4_12_15 [ tmp = (u4_12_15 << 2) - 64; ] { export *[const]:2 tmp; } +s5_12_15_oex: tmp is op_r [ tmp = (op_r << 2) - 64; ] { export *[const]:2 tmp; } # Some 4-bit immediates with mappings that can’t be (easily) expressed in a single disassembly action. # n_u4_4_7 with 0 being -1, used by ADDI.N. -n_s4_4_7_nozero: tmp is n_u4_4_7 = 0 [ tmp = -1; ] { export *[const]:4 tmp; } -n_s4_4_7_nozero: tmp is n_u4_4_7 [ tmp = n_u4_4_7+0; ] { export *[const]:4 tmp; } +n_s4_4_7_nozero: tmp is n_op_s = 0 [ tmp = -1; ] { export *[const]:4 tmp; } +n_s4_4_7_nozero: tmp is n_op_s [ tmp = n_op_s+0; ] { export *[const]:4 tmp; } # B4CONST(ar) (Branch Immediate) encodings, pg. 41 f. r_b4const: tmp is ar = 0 [ tmp = 0xffffffff; ] { export *[const]:4 tmp; } diff --git a/Ghidra/Processors/Xtensa/data/languages/xtensa_depbits.sinc b/Ghidra/Processors/Xtensa/data/languages/xtensa_depbits.sinc index ccf799116e..6cf3037e86 100644 --- a/Ghidra/Processors/Xtensa/data/languages/xtensa_depbits.sinc +++ b/Ghidra/Processors/Xtensa/data/languages/xtensa_depbits.sinc @@ -2,9 +2,9 @@ # This is broken out because it collides with the floating point instructions. It is not included by default # DEPBITS - Add (RRR), pg. 394. -shiftimm: simm is u4_20_23 & u1_16 [ simm = u1_16 << 4 + u4_20_23; ] { export *[const]:4 simm; } -:depbits as, at, shiftimm, u4_12_15 is u3_17_19=0x5 & u4_12_15 & as & at & op0 = 0 & shiftimm { - mask:4 = (1 << u4_12_15) - 1; +shiftimm: simm is op2 & op1_0 [ simm = op1_0 << 4 + op2; ] { export *[const]:4 simm; } +:depbits as, at, shiftimm, u4_12_15 is op1_1_3=0x5 & op_r & as & at & op0 = 0 & shiftimm { + mask:4 = (1 << op_r) - 1; bits:4 = (as & mask) << shiftimm; mask = mask << shiftimm; at = (~mask & at) | bits; diff --git a/Ghidra/Processors/eBPF/data/languages/eBPF.sinc b/Ghidra/Processors/eBPF/data/languages/eBPF.sinc index 62a77a1065..32cbc7ee8a 100644 --- a/Ghidra/Processors/eBPF/data/languages/eBPF.sinc +++ b/Ghidra/Processors/eBPF/data/languages/eBPF.sinc @@ -272,38 +272,38 @@ DST4: dst is dst { local tmp:4 = dst:4; export tmp; } # BPF_ADD: # BPF_STX | BPF_ATOMIC | BPF_W -:STXXADDW [dst + off], src is imm=0x0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) + src:4; } +:AADD32 [dst + off], src is imm=0x0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) + src:4; } # BPF_STX | BPF_ATOMIC | BPF_DW -:STXXADDDW [dst + off], src is imm=0x0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) + src; } +:AADD [dst + off], src is imm=0x0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) + src; } # BPF_OR: -:STXXADDW [dst + off], src is imm=0x40 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) | src:4; } +:AOR32 [dst + off], src is imm=0x40 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) | src:4; } -:STXXADDDW [dst + off], src is imm=0x40 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) | src; } +:AOR [dst + off], src is imm=0x40 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) | src; } # BPF_AND: -:STXXADDW [dst + off], src is imm=0x50 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) & src:4; } +:AAND32 [dst + off], src is imm=0x50 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) & src:4; } -:STXXADDDW [dst + off], src is imm=0x50 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) & src; } +:AAND [dst + off], src is imm=0x50 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) & src; } # BPF_XOR: -:STXXADDW [dst + off], src is imm=0xa0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) ^ src:4; } +:AXOR32 [dst + off], src is imm=0xa0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { *:4 (dst + off) = *:4 (dst + off) ^ src:4; } -:STXXADDDW [dst + off], src is imm=0xa0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) ^ src; } +:AXOR [dst + off], src is imm=0xa0 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { *:8 (dst + off) = *:8 (dst + off) ^ src; } # BPF_ADD | BPF_FETCH -> src = atomic_fetch_add(dst + off, src): -:STXXADDW [dst + off], src is imm=0x1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { +:AFADD32 [dst + off], src is imm=0x1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { local tmp:4 = *:4 (dst + off); *:4 (dst + off) = *:4 (dst + off) + src:4; src = zext(tmp); } -:STXXADDDW [dst + off], src is imm=0x1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { +:AFADD [dst + off], src is imm=0x1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { local tmp:8 = *:8 (dst + off); *:8 (dst + off) = *:8 (dst + off) + src; src = tmp; @@ -311,13 +311,13 @@ DST4: dst is dst { local tmp:4 = dst:4; export tmp; } # BPF_OR | BPF_FETCH -> src = atomic_fetch_or(dst + off, src): -:STXXADDW [dst + off], src is imm=0x41 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { +:AFOR32 [dst + off], src is imm=0x41 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { local tmp:4 = *:4 (dst + off); *:4 (dst + off) = *:4 (dst + off) | src:4; src = zext(tmp); } -:STXXADDDW [dst + off], src is imm=0x41 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { +:AFOR [dst + off], src is imm=0x41 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { local tmp:8 = *:8 (dst + off); *:8 (dst + off) = *:8 (dst + off) | src; src = tmp; @@ -325,13 +325,13 @@ DST4: dst is dst { local tmp:4 = dst:4; export tmp; } # BPF_AND | BPF_FETCH -> src = atomic_fetch_and(dst + off, src): -:STXXADDW [dst + off], src is imm=0x51 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { +:AFAND32 [dst + off], src is imm=0x51 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { local tmp:4 = *:4 (dst + off); *:4 (dst + off) = *:4 (dst + off) & src:4; src = zext(tmp); } -:STXXADDDW [dst + off], src is imm=0x51 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { +:AFAND [dst + off], src is imm=0x51 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { local tmp:8 = *:8 (dst + off); *:8 (dst + off) = *:8 (dst + off) & src; src = tmp; @@ -339,13 +339,13 @@ DST4: dst is dst { local tmp:4 = dst:4; export tmp; } # BPF_XOR | BPF_FETCH -> src = atomic_fetch_xor(dst + off, src): -:STXXADDW [dst + off], src is imm=0xa1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { +:AFXOR32 [dst + off], src is imm=0xa1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { local tmp:4 = *:4 (dst + off); *:4 (dst + off) = *:4 (dst + off) ^ src:4; src = zext(tmp); } -:STXXADDDW [dst + off], src is imm=0xa1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { +:AFXOR [dst + off], src is imm=0xa1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { local tmp:8 = *:8 (dst + off); *:8 (dst + off) = *:8 (dst + off) ^ src; src = tmp; @@ -353,13 +353,13 @@ DST4: dst is dst { local tmp:4 = dst:4; export tmp; } # BPF_XCHG -> src_reg = atomic_xchg(dst + off, src): -:STXXADDW [dst + off], src is imm=0xe1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { +:AXCHG32 [dst + off], src is imm=0xe1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { local tmp:4 = *:4 (dst + off); *:4 (dst + off) = src:4; src = zext(tmp); } -:STXXADDDW [dst + off], src is imm=0xe1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { +:AXCHG [dst + off], src is imm=0xe1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { local tmp:8 = *:8 (dst + off); *:8 (dst + off) = src; src = tmp; @@ -367,20 +367,21 @@ DST4: dst is dst { local tmp:4 = dst:4; export tmp; } # BPF_CMPXCHG -> R0 = atomic_cmpxchg(dst + off, R0, src): -:STXXADDW [dst + off], src is imm=0xf1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { +:ACMP32 [dst + off], src is imm=0xf1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x0 & op_insn_class=0x3 { local tmp:4 = *:4 (dst + off); - if (R0:4 == tmp) goto ; - R0 = zext(tmp); - + if (R0:4 != tmp) goto ; *:4 (dst + off) = src:4; + + R0 = zext(tmp); } -:STXXADDDW [dst + off], src is imm=0xf1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { +:ACMP [dst + off], src is imm=0xf1 & off & src & dst & op_ld_st_mode=0x6 & op_ld_st_size=0x3 & op_insn_class=0x3 { local tmp:8 = *:8 (dst + off); - if (R0 == tmp) goto ; - R0 = tmp; - - *:8 (dst + off) = src; + if (R0 != tmp) goto ; + *:8 (dst + off) = src; + goto inst_next; + + R0 = tmp; } #Jump instructions (BPF_JMP, BPF_JMP32) diff --git a/Ghidra/application.properties b/Ghidra/application.properties index 9e1f98909f..72fc7ab7f8 100644 --- a/Ghidra/application.properties +++ b/Ghidra/application.properties @@ -1,5 +1,5 @@ application.name=Ghidra -application.version=12.0.3 +application.version=12.0.4 application.release.name=DEV application.layout.version=3 application.gradle.min=8.5