mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2024-11-27 14:40:28 +00:00
GP-1255: Allowing 32-bit x86 disassembly in x86-64 (WoW64).
This commit is contained in:
parent
e2ea7320e1
commit
25801da834
@ -344,6 +344,11 @@ public class DebuggerListingProvider extends CodeViewerProvider {
|
||||
return current.isAliveAndPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDynamicListing() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWindowGroup() {
|
||||
//TODO: Overriding this to align disconnected providers
|
||||
|
@ -71,20 +71,15 @@ public class DbgengX64DisassemblyInject implements DisassemblyInject {
|
||||
}
|
||||
Mode mode = modes.iterator().next();
|
||||
Language lang = trace.getBaseLanguage();
|
||||
Register addrsizeReg = lang.getRegister("addrsize");
|
||||
Register opsizeReg = lang.getRegister("opsize");
|
||||
Register longModeReg = lang.getRegister("longMode");
|
||||
ProgramContextImpl context = new ProgramContextImpl(lang);
|
||||
lang.applyContextSettings(context);
|
||||
RegisterValue ctxVal = context.getDisassemblyContext(first.getMinAddress());
|
||||
RegisterValue ctxVal = new RegisterValue(context.getBaseContextRegister());
|
||||
if (mode == Mode.X64) {
|
||||
command.setInitialContext(ctxVal
|
||||
.assign(addrsizeReg, BigInteger.TWO)
|
||||
.assign(opsizeReg, BigInteger.TWO));
|
||||
command.setInitialContext(ctxVal.assign(longModeReg, BigInteger.ONE));
|
||||
}
|
||||
else if (mode == Mode.X86) {
|
||||
command.setInitialContext(ctxVal
|
||||
.assign(addrsizeReg, BigInteger.ONE)
|
||||
.assign(opsizeReg, BigInteger.ONE));
|
||||
command.setInitialContext(ctxVal.assign(longModeReg, BigInteger.ZERO));
|
||||
}
|
||||
// Shouldn't ever get anything else.
|
||||
}
|
||||
|
@ -25,8 +25,7 @@ import org.junit.*;
|
||||
|
||||
import com.google.common.collect.Range;
|
||||
|
||||
import ghidra.app.cmd.disassemble.ArmDisassembleCommand;
|
||||
import ghidra.app.cmd.disassemble.MipsDisassembleCommand;
|
||||
import ghidra.app.cmd.disassemble.*;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.disassemble.Disassembler;
|
||||
import ghidra.program.model.address.AddressOverflowException;
|
||||
@ -215,4 +214,74 @@ public class DBTraceDisassemblerIntegrationTest extends AbstractGhidraHeadlessIn
|
||||
assertEquals("_nop", cu2.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@TestLanguage(ProgramBuilder._X64)
|
||||
public void test64BitX86DBTrace() throws Exception {
|
||||
try (UndoableTransaction tid = b.startTransaction()) {
|
||||
DBTraceMemoryManager memory = b.trace.getMemoryManager();
|
||||
memory.createRegion(".text", 0, b.range(0x00400000, 0x00400fff));
|
||||
memory.putBytes(0, b.addr(0x00400000), b.buf(
|
||||
// MOV RCX,RAX; Same encoding as DEC EAX; MOV ECX,EAX outside long mode
|
||||
0x48, 0x89, 0xc1));
|
||||
|
||||
AddressSet restricted = new AddressSet(b.addr(0x00400000), b.addr(0x00400002));
|
||||
X86_64DisassembleCommand x86Dis =
|
||||
new X86_64DisassembleCommand(b.addr(0x00400000), restricted, false);
|
||||
x86Dis.applyTo(b.trace.getFixedProgramView(0), TaskMonitor.DUMMY);
|
||||
|
||||
DBTraceCodeUnitsMemoryView cuManager = b.trace.getCodeManager().codeUnits();
|
||||
CodeUnit cu1 = cuManager.getAt(0, b.addr(0x00400000));
|
||||
assertEquals("MOV RCX,RAX", cu1.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestLanguage(ProgramBuilder._X64)
|
||||
public void test32BitX64CompatDBTrace() throws Exception {
|
||||
try (UndoableTransaction tid = b.startTransaction()) {
|
||||
DBTraceMemoryManager memory = b.trace.getMemoryManager();
|
||||
memory.createRegion(".text", 0, b.range(0x00400000, 0x00400fff));
|
||||
memory.putBytes(0, b.addr(0x00400000), b.buf(
|
||||
// DEC EAX; but REX.W if context not heeded
|
||||
0x48,
|
||||
// MOV ECX,EAX
|
||||
0x89, 0xc1));
|
||||
|
||||
AddressSet restricted = new AddressSet(b.addr(0x00400000), b.addr(0x00400002));
|
||||
X86_64DisassembleCommand x86Dis =
|
||||
new X86_64DisassembleCommand(b.addr(0x00400000), restricted, true);
|
||||
x86Dis.applyTo(b.trace.getFixedProgramView(0), TaskMonitor.DUMMY);
|
||||
|
||||
DBTraceCodeUnitsMemoryView cuManager = b.trace.getCodeManager().codeUnits();
|
||||
CodeUnit cu1 = cuManager.getAt(0, b.addr(0x00400000));
|
||||
assertEquals("DEC EAX", cu1.toString());
|
||||
CodeUnit cu2 = cuManager.getAt(0, b.addr(0x00400001));
|
||||
assertEquals("MOV ECX,EAX", cu2.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestLanguage(ProgramBuilder._X86)
|
||||
public void test32BitX86DBTrace() throws Exception {
|
||||
try (UndoableTransaction tid = b.startTransaction()) {
|
||||
DBTraceMemoryManager memory = b.trace.getMemoryManager();
|
||||
memory.createRegion(".text", 0, b.range(0x00400000, 0x00400fff));
|
||||
memory.putBytes(0, b.addr(0x00400000), b.buf(
|
||||
// DEC EAX
|
||||
0x48,
|
||||
// MOV ECX,EAX
|
||||
0x89, 0xc1));
|
||||
|
||||
AddressSet restricted = new AddressSet(b.addr(0x00400000), b.addr(0x00400002));
|
||||
DisassembleCommand dis =
|
||||
new DisassembleCommand(b.addr(0x00400000), restricted, true);
|
||||
dis.applyTo(b.trace.getFixedProgramView(0), TaskMonitor.DUMMY);
|
||||
|
||||
DBTraceCodeUnitsMemoryView cuManager = b.trace.getCodeManager().codeUnits();
|
||||
CodeUnit cu1 = cuManager.getAt(0, b.addr(0x00400000));
|
||||
assertEquals("DEC EAX", cu1.toString());
|
||||
CodeUnit cu2 = cuManager.getAt(0, b.addr(0x00400001));
|
||||
assertEquals("MOV ECX,EAX", cu2.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,7 @@ import ghidra.framework.cmd.BackgroundCommand;
|
||||
import ghidra.framework.model.DomainObject;
|
||||
import ghidra.program.disassemble.*;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.Register;
|
||||
import ghidra.program.model.lang.RegisterValue;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
@ -46,14 +45,15 @@ public class DisassembleCommand extends BackgroundCommand {
|
||||
|
||||
private int alignment; // required instruction alignment for the last doDisassembly
|
||||
protected boolean disassemblyPerformed; // if true don't report start problems
|
||||
protected String languageError; // non-null to indicate unsupported language
|
||||
protected boolean unalignedStart;
|
||||
protected boolean nonExecutableStart;
|
||||
|
||||
/**
|
||||
* Constructor for DisassembleCommand.
|
||||
*
|
||||
* @param start Address to start disassembly.
|
||||
* @param restrictedSet addresses that can be disassembled.
|
||||
* a null set implies no restrictions
|
||||
* @param restrictedSet addresses that can be disassembled. a null set implies no restrictions
|
||||
* @param followFlow true means the disassembly should follow flow
|
||||
*/
|
||||
public DisassembleCommand(Address start, AddressSetView restrictedSet, boolean followFlow) {
|
||||
@ -62,22 +62,22 @@ public class DisassembleCommand extends BackgroundCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for DisassembleCommand.
|
||||
* @param startSet set of addresses to be the start of a disassembly. The
|
||||
* Command object will attempt to start a disassembly at each address in this set.
|
||||
* @param restrictedSet addresses that can be disassembled.
|
||||
* a null set implies no restrictions
|
||||
*/
|
||||
* Constructor for DisassembleCommand.
|
||||
*
|
||||
* @param startSet set of addresses to be the start of a disassembly. The Command object will
|
||||
* attempt to start a disassembly at each address in this set.
|
||||
* @param restrictedSet addresses that can be disassembled. a null set implies no restrictions
|
||||
*/
|
||||
public DisassembleCommand(AddressSetView startSet, AddressSetView restrictedSet) {
|
||||
this(startSet, restrictedSet, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for DisassembleCommand.
|
||||
* @param startSet set of addresses to be the start of a disassembly. The
|
||||
* Command object will attempt to start a disassembly at each address in this set.
|
||||
* @param restrictedSet addresses that can be disassembled.
|
||||
* a null set implies no restrictions
|
||||
*
|
||||
* @param startSet set of addresses to be the start of a disassembly. The Command object will
|
||||
* attempt to start a disassembly at each address in this set.
|
||||
* @param restrictedSet addresses that can be disassembled. a null set implies no restrictions
|
||||
*/
|
||||
public DisassembleCommand(AddressSetView startSet, AddressSetView restrictedSet,
|
||||
boolean followFlow) {
|
||||
@ -93,11 +93,12 @@ public class DisassembleCommand extends BackgroundCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the disassembler context to be seeded for the various disassembly start
|
||||
* points which may be encountered using the future flow state of the specified seedContext.
|
||||
* Any initial context set via the {@link #setInitialContext(RegisterValue)} method will take
|
||||
* precedence when combined with any seed values.
|
||||
* The seedContext should remain unchanged while disassembler command is actively running.
|
||||
* Allows the disassembler context to be seeded for the various disassembly start points which
|
||||
* may be encountered using the future flow state of the specified seedContext. Any initial
|
||||
* context set via the {@link #setInitialContext(RegisterValue)} method will take precedence
|
||||
* when combined with any seed values. The seedContext should remain unchanged while
|
||||
* disassembler command is actively running.
|
||||
*
|
||||
* @param seedContext seed context or null
|
||||
*/
|
||||
public void setSeedContext(DisassemblerContextImpl seedContext) {
|
||||
@ -105,11 +106,11 @@ public class DisassembleCommand extends BackgroundCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows a specified initial context to be used at all start points. This value will take
|
||||
* Allows a specified initial context to be used at all start points. This value will take
|
||||
* precedence when combined with any individual seed context values specified by the
|
||||
* {@link #setSeedContext(DisassemblerContextImpl)} method.
|
||||
* The defaultSeedContext should remain unchanged while disassembler command
|
||||
* is actively running.
|
||||
* {@link #setSeedContext(DisassemblerContextImpl)} method. The defaultSeedContext should remain
|
||||
* unchanged while disassembler command is actively running.
|
||||
*
|
||||
* @param initialContextValue the initial context value to set or null to clear it
|
||||
*/
|
||||
public void setInitialContext(RegisterValue initialContextValue) {
|
||||
@ -121,8 +122,9 @@ public class DisassembleCommand extends BackgroundCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set code analysis enablement. By default new instructions will be
|
||||
* submitted for auto-analysis.
|
||||
* Set code analysis enablement. By default new instructions will be submitted for
|
||||
* auto-analysis.
|
||||
*
|
||||
* @param enable
|
||||
*/
|
||||
public void enableCodeAnalysis(boolean enable) {
|
||||
@ -134,6 +136,9 @@ public class DisassembleCommand extends BackgroundCommand {
|
||||
if (disassemblyPerformed) {
|
||||
return null;
|
||||
}
|
||||
if (languageError != null) {
|
||||
return "The program's language is not supported: " + languageError;
|
||||
}
|
||||
if (nonExecutableStart) {
|
||||
return "Disassembly of non-executable memory is disabled";
|
||||
}
|
||||
@ -312,7 +317,7 @@ public class DisassembleCommand extends BackgroundCommand {
|
||||
*
|
||||
* @param disassembler disassembler to use
|
||||
* @param seedSet set of addresses to be disassembled
|
||||
* @param mgr
|
||||
* @param mgr
|
||||
*
|
||||
* @return addresses actually disassembled
|
||||
*/
|
||||
@ -335,16 +340,17 @@ public class DisassembleCommand extends BackgroundCommand {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if intermediate analysis is required to reduce the risk of disassembling
|
||||
* data regions when performing static disassembly over a contiguous range if
|
||||
* addresses. This method attemps to identify this situation by checking the first
|
||||
* range of disassembledSet against the startSet. Analysis will be triggered if
|
||||
* startSet contains both the max address of the first range of disassembledSet
|
||||
* (M where M=disassembledSet.firstRange().getMaxAddress()) and the next address
|
||||
* (M.next()) which will be the next seed point.
|
||||
* Determine if intermediate analysis is required to reduce the risk of disassembling data
|
||||
* regions when performing static disassembly over a contiguous range if addresses. This method
|
||||
* attemps to identify this situation by checking the first range of disassembledSet against the
|
||||
* startSet. Analysis will be triggered if startSet contains both the max address of the first
|
||||
* range of disassembledSet (M where M=disassembledSet.firstRange().getMaxAddress()) and the
|
||||
* next address (M.next()) which will be the next seed point.
|
||||
*
|
||||
* @param mgr auto analysis manager or null if analysis disabled
|
||||
* @param startSet disassembly seed points (prior to removing disassembledSet)
|
||||
* @param disassembledSet last set of disassembled addresses using startSet min-address as seed point
|
||||
* @param disassembledSet last set of disassembled addresses using startSet min-address as seed
|
||||
* point
|
||||
*/
|
||||
private static void analyzeIfNeeded(AutoAnalysisManager mgr, AddressSetView startSet,
|
||||
AddressSetView disassembledSet, TaskMonitor monitor) {
|
||||
@ -366,6 +372,7 @@ public class DisassembleCommand extends BackgroundCommand {
|
||||
|
||||
/**
|
||||
* Returns an address set of all instructions that were disassembled.
|
||||
*
|
||||
* @return an address set of all instructions that were disassembled
|
||||
*/
|
||||
public AddressSet getDisassembledAddressSet() {
|
||||
|
@ -0,0 +1,158 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.cmd.disassemble;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import javax.help.UnsupportedOperationException;
|
||||
|
||||
import ghidra.framework.model.DomainObject;
|
||||
import ghidra.program.disassemble.DisassemblerContextImpl;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.lang.*;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.listing.ProgramContext;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* Command object for performing 64-/32-bit x86 disassembly
|
||||
*
|
||||
* <p>
|
||||
* This generally only comes up when debugging, since there can be multiple images loaded by an
|
||||
* x86-64 target. For WoW64, the images may be mixed. Thus, this command allows you to disassemble
|
||||
* 64-bit or 32-bit instructions whenever the language is set to 64-bit x86.
|
||||
*
|
||||
* <p>
|
||||
* <b>WARNING:</b> If used in static programs, i.e., not debug traces, there are some potential
|
||||
* remaining issues, particularly dealing with stored context and follow-on disassembly -- typically
|
||||
* called for by the analyzers. In most cases, this does not matter, since mixed 64- and 32-bit code
|
||||
* in a single image is likely a niche case and can be handled via careful commands from the user.
|
||||
* Nevertheless, TODO: Rework x86-64 analyzers to call the correct mode of disassembly.
|
||||
*/
|
||||
public class X86_64DisassembleCommand extends DisassembleCommand {
|
||||
|
||||
private final boolean size32Mode;
|
||||
|
||||
/**
|
||||
* Constructor for X86_64DisassembleCommand.
|
||||
*
|
||||
* @param startSet set of addresses to be the start of disassembly. The Command object will
|
||||
* attempt to start a disassembly at each address in this set.
|
||||
* @param restrictedSet addresses that can be disassembled. a null set implies no restrictions.
|
||||
* @param size32Mode pass true if disassembling in 32-bit compatibility mode, otherwise normal
|
||||
* 64-bit disassembly will be performed.
|
||||
*/
|
||||
public X86_64DisassembleCommand(AddressSetView startSet, AddressSetView restrictedSet,
|
||||
boolean size32Mode) {
|
||||
super(startSet, restrictedSet, true);
|
||||
this.size32Mode = size32Mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for X86_64DisassembleCommand.
|
||||
*
|
||||
* @param start address to be the start of a disassembly.
|
||||
* @param restrictedSet addresses that can be disassembled. a null set implies no restrictions.
|
||||
* @param size32Mode pass true if disassembling in 32-bit compatibility mode, otherwise normal
|
||||
* 64-bit disassembly will be performed.
|
||||
*/
|
||||
public X86_64DisassembleCommand(Address start, AddressSetView restrictedSet,
|
||||
boolean size32Mode) {
|
||||
super(start, restrictedSet, true);
|
||||
this.size32Mode = size32Mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Disassemble " + (size32Mode ? "32" : "64") + "-bit x86";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSeedContext(DisassemblerContextImpl seedContext) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInitialContext(RegisterValue initialContextValue) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public static AddressSet alignSet(int alignment, AddressSetView set)
|
||||
throws CancelledException {
|
||||
AddressSet result = new AddressSet();
|
||||
for (AddressRange range : set) {
|
||||
Address min = range.getMinAddress();
|
||||
long minOfffset = min.getOffset();
|
||||
if (minOfffset != min.getOffset()) {
|
||||
min = min.getNewAddress(minOfffset);
|
||||
}
|
||||
Address max = range.getMaxAddress();
|
||||
long maxOffset = max.getOffset();
|
||||
if (maxOffset < minOfffset) {
|
||||
// skip short unaligned range
|
||||
continue;
|
||||
}
|
||||
if (maxOffset != max.getOffset()) {
|
||||
max = max.getNewAddress(maxOffset);
|
||||
}
|
||||
result.addRange(min, max);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
|
||||
Program program = (Program) obj;
|
||||
|
||||
disassemblyPerformed = false;
|
||||
unalignedStart = false;
|
||||
|
||||
// get the longMode register and set accordingly
|
||||
ProgramContext context = program.getProgramContext();
|
||||
Register longModeReg = context.getRegister("longMode");
|
||||
|
||||
// Indicates we're not x86-64, or the spec has changed
|
||||
if (longModeReg == null) {
|
||||
languageError = "Requires x86:LE:64:default";
|
||||
return false;
|
||||
}
|
||||
RegisterValue ctx = new RegisterValue(context.getBaseContextRegister())
|
||||
.assign(longModeReg, size32Mode ? BigInteger.ZERO : BigInteger.ONE);
|
||||
|
||||
super.setInitialContext(ctx);
|
||||
|
||||
try {
|
||||
if (startSet != null) {
|
||||
// This is identity, no?
|
||||
AddressSet alignedSet = alignSet(1, startSet);
|
||||
if (alignedSet.isEmpty()) {
|
||||
unalignedStart = true;
|
||||
return false;
|
||||
}
|
||||
startSet = program.getListing().getUndefinedRanges(alignedSet, true, monitor);
|
||||
if (startSet.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return doDisassembly(monitor, program, 1);
|
||||
}
|
||||
}
|
@ -34,22 +34,19 @@ import ghidra.program.util.ProgramLocation;
|
||||
import ghidra.program.util.ProgramSelection;
|
||||
|
||||
/**
|
||||
* <CODE>DisassemblerPlugin</CODE> provides functionality for dynamic disassembly,
|
||||
* static disassembly.<BR>
|
||||
* In dynamic disassembly disassembling begins from the
|
||||
* selected addresses or if there is no selection then at the address of the
|
||||
* current cursor location and attempts to continue disassembling
|
||||
* through fallthroughs and along all flows from a disassembled instruction.
|
||||
* For instance, if a jump instruction is disassembled then the address being
|
||||
* jumped to will be disassembled. The dynamic disassembly will also follow
|
||||
* data pointers to addresses containing undefined data, which is then
|
||||
* disassembled.<BR>
|
||||
* In static disassembly a range or set of ranges
|
||||
* is given and disassembly is attempted on each range. Any defined code in the
|
||||
* ranges before the static disassembly are first removed.<BR>
|
||||
* <CODE>DisassemblerPlugin</CODE> provides functionality for dynamic disassembly, static
|
||||
* disassembly.<BR>
|
||||
* In dynamic disassembly disassembling begins from the selected addresses or if there is no
|
||||
* selection then at the address of the current cursor location and attempts to continue
|
||||
* disassembling through fallthroughs and along all flows from a disassembled instruction. For
|
||||
* instance, if a jump instruction is disassembled then the address being jumped to will be
|
||||
* disassembled. The dynamic disassembly will also follow data pointers to addresses containing
|
||||
* undefined data, which is then disassembled.<BR>
|
||||
* In static disassembly a range or set of ranges is given and disassembly is attempted on each
|
||||
* range. Any defined code in the ranges before the static disassembly are first removed.<BR>
|
||||
* <P>
|
||||
* <CODE>DisassemblerPlugin</CODE> provides access to its functions as a service
|
||||
* that another plugin may use and through the popup menu to the user.
|
||||
* <CODE>DisassemblerPlugin</CODE> provides access to its functions as a service that another plugin
|
||||
* may use and through the popup menu to the user.
|
||||
*/
|
||||
//@formatter:off
|
||||
@PluginInfo(
|
||||
@ -89,6 +86,8 @@ public class DisassemblerPlugin extends Plugin {
|
||||
private DockingAction mips16DisassembleAction;
|
||||
private DockingAction ppcDisassembleAction;
|
||||
private DockingAction ppcVleDisassembleAction;
|
||||
private DockingAction x86_64DisassembleAction;
|
||||
private DockingAction x86_32DisassembleAction;
|
||||
private DockingAction setFlowOverrideAction;
|
||||
|
||||
/** Dialog for obtaining the processor state to be used for disassembling. */
|
||||
@ -128,8 +127,7 @@ public class DisassemblerPlugin extends Plugin {
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Creates a new instance of the plugin giving it the tool that
|
||||
* it will work in.
|
||||
* Creates a new instance of the plugin giving it the tool that it will work in.
|
||||
*/
|
||||
public DisassemblerPlugin(PluginTool tool) {
|
||||
super(tool);
|
||||
@ -177,6 +175,8 @@ public class DisassemblerPlugin extends Plugin {
|
||||
mips16DisassembleAction = new MipsDisassembleAction(this, GROUP_NAME, true);
|
||||
ppcDisassembleAction = new PowerPCDisassembleAction(this, GROUP_NAME, false);
|
||||
ppcVleDisassembleAction = new PowerPCDisassembleAction(this, GROUP_NAME, true);
|
||||
x86_64DisassembleAction = new X86_64DisassembleAction(this, GROUP_NAME, false);
|
||||
x86_32DisassembleAction = new X86_64DisassembleAction(this, GROUP_NAME, true);
|
||||
setFlowOverrideAction = new SetFlowOverrideAction(this, GROUP_NAME);
|
||||
|
||||
tool.addAction(disassembleAction);
|
||||
@ -190,6 +190,8 @@ public class DisassemblerPlugin extends Plugin {
|
||||
tool.addAction(mips16DisassembleAction);
|
||||
tool.addAction(ppcDisassembleAction);
|
||||
tool.addAction(ppcVleDisassembleAction);
|
||||
tool.addAction(x86_64DisassembleAction);
|
||||
tool.addAction(x86_32DisassembleAction);
|
||||
tool.addAction(contextAction);
|
||||
tool.addAction(setFlowOverrideAction);
|
||||
}
|
||||
@ -244,7 +246,8 @@ public class DisassemblerPlugin extends Plugin {
|
||||
try {
|
||||
currentProgram.getMemory().getByte(addr);
|
||||
AddressSetView restrictedSet = null;
|
||||
if (isDynamicListing) {
|
||||
// I believe this is deprecated
|
||||
/*if (isDynamicListing) {
|
||||
// TODO: should we have option to control restricted range?
|
||||
Address min, max;
|
||||
try {
|
||||
@ -260,7 +263,7 @@ public class DisassemblerPlugin extends Plugin {
|
||||
max = addr.getAddressSpace().getMaxAddress();
|
||||
}
|
||||
restrictedSet = new AddressSet(min, max);
|
||||
}
|
||||
}*/
|
||||
cmd = new DisassembleCommand(addr, restrictedSet, true);
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
@ -409,4 +412,27 @@ public class DisassemblerPlugin extends Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
public void disassembleX86_64Callback(ListingActionContext context, boolean size32Mode) {
|
||||
ProgramSelection currentSelection = context.getSelection();
|
||||
ProgramLocation currentLocation = context.getLocation();
|
||||
Program currentProgram = context.getProgram();
|
||||
final X86_64DisassembleCommand cmd;
|
||||
|
||||
if ((currentSelection != null) && (!currentSelection.isEmpty())) {
|
||||
cmd = new X86_64DisassembleCommand(currentSelection, null, size32Mode);
|
||||
}
|
||||
else {
|
||||
Address addr = currentLocation.getAddress();
|
||||
try {
|
||||
currentProgram.getMemory().getByte(addr);
|
||||
cmd = new X86_64DisassembleCommand(addr, null, size32Mode);
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
tool.setStatusInfo("Can't disassemble uninitialized memory!", true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
tool.executeBackgroundCommand(cmd, currentProgram);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,80 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.plugin.core.disassembler;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import docking.action.KeyBindingData;
|
||||
import docking.action.MenuData;
|
||||
import ghidra.app.context.ListingActionContext;
|
||||
import ghidra.app.context.ListingContextAction;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeViewerActionContext;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.program.model.lang.Processor;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
||||
public class X86_64DisassembleAction extends ListingContextAction {
|
||||
private final DisassemblerPlugin plugin;
|
||||
private final boolean disassemble32Bit;
|
||||
|
||||
public X86_64DisassembleAction(DisassemblerPlugin plugin, String groupName,
|
||||
boolean disassemble32Bit) {
|
||||
super("Disassemble " + (disassemble32Bit ? "32" : "64") + "-bit x86", plugin.getName());
|
||||
|
||||
this.plugin = plugin;
|
||||
this.disassemble32Bit = disassemble32Bit;
|
||||
|
||||
setPopupMenuData(new MenuData(new String[] { getName() }, null, groupName));
|
||||
|
||||
int keyEvent = (disassemble32Bit ? KeyEvent.VK_F12 : KeyEvent.VK_F11);
|
||||
setKeyBindingData(new KeyBindingData(keyEvent, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ListingActionContext context) {
|
||||
plugin.disassembleX86_64Callback(context, disassemble32Bit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ListingActionContext context) {
|
||||
// STOPGAP: Disable these in the static context
|
||||
if (!(context instanceof CodeViewerActionContext)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Address address = context.getAddress();
|
||||
if (address == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Program program = context.getProgram();
|
||||
Language lang = program.getLanguage();
|
||||
Processor proc = lang.getProcessor();
|
||||
/*
|
||||
* Action only intended for use where 64-bit x86 is available. I'm just going to check for
|
||||
* x86 with size 64.
|
||||
*/
|
||||
if (!"x86".equals(proc.toString())) {
|
||||
return false;
|
||||
}
|
||||
if (lang.getLanguageDescription().getSize() != 64) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return plugin.checkDisassemblyEnabled(context, address, true);
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:ADCX Reg64, rm64 is vexMode=0 & opsize=2 & $(PRE_66) & byte=0x0F; byte=0x38; byte=0xF6; Reg64 ... & rm64 {
|
||||
:ADCX Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_66) & byte=0x0F; byte=0x38; byte=0xF6; Reg64 ... & rm64 {
|
||||
tmp:9 = zext(Reg64) + zext(rm64) + zext(CF);
|
||||
tmpCF:1 = tmp(8); # just the carry byte
|
||||
CF = tmpCF != 0;
|
||||
@ -24,7 +24,7 @@
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:ADOX Reg64, rm64 is vexMode=0 & opsize=2 & $(PRE_F3) & byte=0x0F; byte=0x38; byte=0xF6; Reg64 ... & rm64 {
|
||||
:ADOX Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & byte=0x0F; byte=0x38; byte=0xF6; Reg64 ... & rm64 {
|
||||
tmp:9 = zext(Reg64) + zext(rm64) + zext(OF);
|
||||
tmpOF:1 = tmp(8); # just the carry byte
|
||||
OF = tmpOF != 0;
|
||||
|
@ -684,7 +684,7 @@ define pcodeop vcvtsd2si_avx ;
|
||||
|
||||
# CVTSD2SI 3-253 PAGE 823 LINE 44317
|
||||
@ifdef IA64
|
||||
:VCVTSD2SI Reg64, XmmReg2_m64 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1); byte=0x2D; Reg64 ... & XmmReg2_m64
|
||||
:VCVTSD2SI Reg64, XmmReg2_m64 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1); byte=0x2D; Reg64 ... & XmmReg2_m64
|
||||
{
|
||||
Reg64 = vcvtsd2si_avx( XmmReg2_m64 );
|
||||
}
|
||||
@ -710,7 +710,7 @@ define pcodeop vcvtsi2sd_avx ;
|
||||
|
||||
# CVTSI2SD 3-257 PAGE 827 LINE 44519
|
||||
@ifdef IA64
|
||||
:VCVTSI2SD XmmReg1, vexVVVV_XmmReg, rm64 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x2A; (XmmReg1 & YmmReg1) ... & rm64
|
||||
:VCVTSI2SD XmmReg1, vexVVVV_XmmReg, rm64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x2A; (XmmReg1 & YmmReg1) ... & rm64
|
||||
{
|
||||
local tmp:16 = vcvtsi2sd_avx( vexVVVV_XmmReg, rm64 );
|
||||
YmmReg1 = zext(tmp);
|
||||
@ -729,7 +729,7 @@ define pcodeop vcvtsi2ss_avx ;
|
||||
|
||||
# CVTSI2SS 3-259 PAGE 829 LINE 44634
|
||||
@ifdef IA64
|
||||
:VCVTSI2SS XmmReg1, vexVVVV_XmmReg, rm64 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x2A; (XmmReg1 & YmmReg1) ... & rm64
|
||||
:VCVTSI2SS XmmReg1, vexVVVV_XmmReg, rm64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x2A; (XmmReg1 & YmmReg1) ... & rm64
|
||||
{
|
||||
local tmp:16 = vcvtsi2ss_avx( vexVVVV_XmmReg, rm64 );
|
||||
YmmReg1 = zext(tmp);
|
||||
@ -756,7 +756,7 @@ define pcodeop vcvtss2si_avx ;
|
||||
|
||||
# CVTSS2SI 3-263 PAGE 833 LINE 44837
|
||||
@ifdef IA64
|
||||
:VCVTSS2SI Reg64, XmmReg2_m32 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W1); byte=0x2D; Reg64 ... & XmmReg2_m32
|
||||
:VCVTSS2SI Reg64, XmmReg2_m32 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W1); byte=0x2D; Reg64 ... & XmmReg2_m32
|
||||
{
|
||||
Reg64 = vcvtss2si_avx( XmmReg2_m32 );
|
||||
}
|
||||
@ -805,7 +805,7 @@ define pcodeop vcvttsd2si_avx ;
|
||||
|
||||
# CVTTSD2SI 3-274 PAGE 844 LINE 45382
|
||||
@ifdef IA64
|
||||
:VCVTTSD2SI Reg64, XmmReg2_m64 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1); byte=0x2C; Reg64 ... & XmmReg2_m64
|
||||
:VCVTTSD2SI Reg64, XmmReg2_m64 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F2) & $(VEX_0F) & $(VEX_W1); byte=0x2C; Reg64 ... & XmmReg2_m64
|
||||
{
|
||||
Reg64 = vcvttsd2si_avx( XmmReg2_m64 );
|
||||
}
|
||||
@ -821,7 +821,7 @@ define pcodeop vcvttss2si_avx ;
|
||||
|
||||
# CVTTSS2SI 3-276 PAGE 846 LINE 45476
|
||||
@ifdef IA64
|
||||
:VCVTTSS2SI Reg64, XmmReg2_m32 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W1); byte=0x2C; Reg64 ... & XmmReg2_m32
|
||||
:VCVTTSS2SI Reg64, XmmReg2_m32 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_F3) & $(VEX_0F) & $(VEX_W1); byte=0x2C; Reg64 ... & XmmReg2_m32
|
||||
{
|
||||
Reg64 = vcvttss2si_avx( XmmReg2_m32 );
|
||||
}
|
||||
@ -1186,7 +1186,7 @@ define pcodeop vmovd_avx ;
|
||||
# MOVD/MOVQ 4-55 PAGE 1175 LINE 61360
|
||||
define pcodeop vmovq_avx ;
|
||||
@ifdef IA64
|
||||
:VMOVQ XmmReg1, rm64 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1); byte=0x6E; (XmmReg1 & YmmReg1) ... & rm64
|
||||
:VMOVQ XmmReg1, rm64 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1); byte=0x6E; (XmmReg1 & YmmReg1) ... & rm64
|
||||
{
|
||||
local tmp:16 = vmovq_avx( rm64 );
|
||||
YmmReg1 = zext(tmp);
|
||||
@ -1202,7 +1202,7 @@ define pcodeop vmovq_avx ;
|
||||
|
||||
# MOVD/MOVQ 4-55 PAGE 1175 LINE 61364
|
||||
@ifdef IA64
|
||||
:VMOVQ rm64, XmmReg1 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1); byte=0x7E; XmmReg1 ... & rm64
|
||||
:VMOVQ rm64, XmmReg1 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F) & $(VEX_W1); byte=0x7E; XmmReg1 ... & rm64
|
||||
{
|
||||
rm64 = vmovq_avx( XmmReg1 );
|
||||
}
|
||||
@ -1947,7 +1947,7 @@ define pcodeop vpextrd_avx ;
|
||||
# PEXTRB/PEXTRD/PEXTRQ 4-274 PAGE 1394 LINE 72330
|
||||
define pcodeop vpextrq_avx ;
|
||||
@ifdef IA64
|
||||
:VPEXTRQ rm64, XmmReg1, imm8 is $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1); byte=0x16; XmmReg1 ... & rm64; imm8
|
||||
:VPEXTRQ rm64, XmmReg1, imm8 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1); byte=0x16; XmmReg1 ... & rm64; imm8
|
||||
{
|
||||
rm64 = vpextrq_avx( XmmReg1, imm8:1 );
|
||||
}
|
||||
@ -2052,7 +2052,7 @@ define pcodeop vpinsrd_avx ;
|
||||
# PINSRB/PINSRD/PINSRQ 4-293 PAGE 1413 LINE 73327
|
||||
define pcodeop vpinsrq_avx ;
|
||||
@ifdef IA64
|
||||
:VPINSRQ XmmReg1, vexVVVV_XmmReg, rm64, imm8 is $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x22; (XmmReg1 & YmmReg1) ... & rm64; imm8
|
||||
:VPINSRQ XmmReg1, vexVVVV_XmmReg, rm64, imm8 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F3A) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x22; (XmmReg1 & YmmReg1) ... & rm64; imm8
|
||||
{
|
||||
local tmp:16 = vpinsrq_avx( vexVVVV_XmmReg, rm64, imm8:1 );
|
||||
YmmReg1 = zext(tmp);
|
||||
|
@ -33,7 +33,7 @@ define pcodeop vgatherdpd ;
|
||||
# VGATHERDPD/VGATHERQPD 5-251 PAGE 2075 LINE 106908
|
||||
@ifdef IA64
|
||||
define pcodeop vgatherqpd ;
|
||||
:VGATHERQPD XmmReg1, q_vm64x, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & q_vm64x {
|
||||
:VGATHERQPD XmmReg1, q_vm64x, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & q_vm64x {
|
||||
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
|
||||
# XmmReg1 = vgatherqpd(XmmReg1, q_vm64x, vexVVVV_XmmReg);
|
||||
local tmp:16 = vgatherqpd(XmmReg1, vexVVVV_XmmReg);
|
||||
@ -54,7 +54,7 @@ define pcodeop vgatherqpd ;
|
||||
|
||||
# VGATHERDPD/VGATHERQPD 5-251 PAGE 2075 LINE 106918
|
||||
@ifdef IA64
|
||||
:VGATHERQPD YmmReg1, q_vm64y, vexVVVV_YmmReg is $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x93; YmmReg1 ... & q_vm64y {
|
||||
:VGATHERQPD YmmReg1, q_vm64y, vexVVVV_YmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x93; YmmReg1 ... & q_vm64y {
|
||||
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
|
||||
# YmmReg1 = vgatherqpd(YmmReg1, q_vm64y, vexVVVV_YmmReg);
|
||||
YmmReg1 = vgatherqpd(YmmReg1, vexVVVV_YmmReg);
|
||||
@ -78,7 +78,7 @@ define pcodeop vgatherdps ;
|
||||
# VGATHERDPS/VGATHERQPS 5-256 PAGE 2080 LINE 107135
|
||||
@ifdef IA64
|
||||
define pcodeop vgatherqps ;
|
||||
:VGATHERQPS XmmReg1, d_vm64x, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & d_vm64x {
|
||||
:VGATHERQPS XmmReg1, d_vm64x, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & d_vm64x {
|
||||
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
|
||||
# XmmReg1 = vgatherqps(XmmReg1, d_vm64x, vexVVVV_XmmReg);
|
||||
local tmp:16 = vgatherqps(XmmReg1, vexVVVV_XmmReg);
|
||||
@ -99,7 +99,7 @@ define pcodeop vgatherqps ;
|
||||
|
||||
# VGATHERDPS/VGATHERQPS 5-256 PAGE 2080 LINE 107145
|
||||
@ifdef IA64
|
||||
:VGATHERQPS XmmReg1, d_vm64y, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & d_vm64y {
|
||||
:VGATHERQPS XmmReg1, d_vm64y, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x93; (XmmReg1 & YmmReg1) ... & d_vm64y {
|
||||
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
|
||||
# XmmReg1 = vgatherqps(XmmReg1, d_vm64y, vexVVVV_XmmReg);
|
||||
XmmReg1 = vgatherqps(XmmReg1, vexVVVV_XmmReg);
|
||||
@ -133,7 +133,7 @@ define pcodeop vpgatherdd ;
|
||||
# VPGATHERDD/VPGATHERQD 5-273 PAGE 2097 LINE 107888
|
||||
@ifdef IA64
|
||||
define pcodeop vpgatherqd ;
|
||||
:VPGATHERQD XmmReg1, d_vm64x, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & d_vm64x {
|
||||
:VPGATHERQD XmmReg1, d_vm64x, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & d_vm64x {
|
||||
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
|
||||
# XmmReg1 = vpgatherqd(XmmReg1, d_vm64x, vexVVVV_XmmReg);
|
||||
local tmp:16 = vpgatherqd(XmmReg1, vexVVVV_XmmReg);
|
||||
@ -154,7 +154,7 @@ define pcodeop vpgatherqd ;
|
||||
|
||||
# VPGATHERDD/VPGATHERQD 5-273 PAGE 2097 LINE 107896
|
||||
@ifdef IA64
|
||||
:VPGATHERQD XmmReg1, d_vm64y, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & d_vm64y {
|
||||
:VPGATHERQD XmmReg1, d_vm64y, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W0) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & d_vm64y {
|
||||
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
|
||||
# XmmReg1 = vpgatherqd(XmmReg1, d_vm64y, vexVVVV_XmmReg);
|
||||
local tmp:16 = vpgatherqd(XmmReg1, vexVVVV_XmmReg);
|
||||
@ -179,7 +179,7 @@ define pcodeop vpgatherdq ;
|
||||
# VPGATHERDQ/VPGATHERQQ 5-280 PAGE 2104 LINE 108238
|
||||
@ifdef IA64
|
||||
define pcodeop vpgatherqq ;
|
||||
:VPGATHERQQ XmmReg1, q_vm64x, vexVVVV_XmmReg is $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & q_vm64x {
|
||||
:VPGATHERQQ XmmReg1, q_vm64x, vexVVVV_XmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L128) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_XmmReg; byte=0x91; (XmmReg1 & YmmReg1) ... & q_vm64x {
|
||||
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
|
||||
# XmmReg1 = vpgatherqq(XmmReg1, q_vm64x, vexVVVV_XmmReg);
|
||||
local tmp:16 = vpgatherqq(XmmReg1, vexVVVV_XmmReg);
|
||||
@ -200,7 +200,7 @@ define pcodeop vpgatherqq ;
|
||||
|
||||
# VPGATHERDQ/VPGATHERQQ 5-280 PAGE 2104 LINE 108246
|
||||
@ifdef IA64
|
||||
:VPGATHERQQ YmmReg1, q_vm64y, vexVVVV_YmmReg is $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x91; YmmReg1 ... & q_vm64y {
|
||||
:VPGATHERQQ YmmReg1, q_vm64y, vexVVVV_YmmReg is $(LONGMODE_ON) & $(VEX_DDS) & $(VEX_L256) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_YmmReg; byte=0x91; YmmReg1 ... & q_vm64y {
|
||||
# TODO full semantics necessary for VSIB memory data access, leave out of data flow for now
|
||||
# YmmReg1 = vpgatherqq(YmmReg1, q_vm64y, vexVVVV_YmmReg);
|
||||
YmmReg1 = vpgatherqq(YmmReg1, vexVVVV_YmmReg);
|
||||
|
@ -21,7 +21,7 @@ macro tzcntflags(input, output) {
|
||||
|
||||
@ifdef IA64
|
||||
# TODO remove ANDN from ia.sinc ?????
|
||||
:ANDN Reg64, vexVVVV_r64, rm64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf2; Reg64 ... & rm64
|
||||
:ANDN Reg64, vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf2; Reg64 ... & rm64
|
||||
{
|
||||
Reg64 = ~(vexVVVV_r64) & rm64;
|
||||
resultflags(Reg64);
|
||||
@ -46,7 +46,7 @@ macro tzcntflags(input, output) {
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:BEXTR Reg64, rm64, vexVVVV_r64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
|
||||
:BEXTR Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
|
||||
{
|
||||
sourceTmp:1 = vexVVVV_r64[0,8];
|
||||
lengthTmp:1 = vexVVVV_r64[8,8];
|
||||
@ -74,7 +74,7 @@ macro tzcntflags(input, output) {
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:BLSI vexVVVV_r64, rm64 is $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=3 ... & rm64
|
||||
:BLSI vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=3 ... & rm64
|
||||
{
|
||||
vexVVVV_r64 = -rm64 & rm64;
|
||||
|
||||
@ -100,7 +100,7 @@ macro tzcntflags(input, output) {
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:BLSMSK vexVVVV_r64, rm64 is $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=2 ... & rm64
|
||||
:BLSMSK vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=2 ... & rm64
|
||||
{
|
||||
CF = (rm64 == 0);
|
||||
vexVVVV_r64 = (rm64 - 1) ^ rm64;
|
||||
@ -126,7 +126,7 @@ macro tzcntflags(input, output) {
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:BLSR vexVVVV_r64, rm64 is $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=1 ... & rm64
|
||||
:BLSR vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf3; reg_opcode=1 ... & rm64
|
||||
{
|
||||
CF = (rm64 == 0);
|
||||
vexVVVV_r64 = (rm64 - 1) & rm64;
|
||||
@ -176,7 +176,7 @@ macro tzcntflags(input, output) {
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:TZCNT Reg64, rm64 is vexMode=0 & opsize=2 & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0xBC; Reg64 ... & rm64 {
|
||||
:TZCNT Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0xBC; Reg64 ... & rm64 {
|
||||
|
||||
countTmp:8 = 0;
|
||||
inputTmp:8 = rm64;
|
||||
|
@ -22,7 +22,7 @@
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:BZHI Reg64, rm64, vexVVVV_r64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
|
||||
:BZHI Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_NONE) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
|
||||
{
|
||||
indexTmp:1 = vexVVVV_r64:1;
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:MULX Reg64, vexVVVV_r64, rm64 is $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf6; Reg64 ... & rm64
|
||||
:MULX Reg64, vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDD) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf6; Reg64 ... & rm64
|
||||
{
|
||||
temp:16 = zext(RDX) * zext(rm64);
|
||||
|
||||
@ -85,7 +85,7 @@
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:PDEP Reg64, vexVVVV_r64, rm64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
|
||||
:PDEP Reg64, vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
|
||||
{
|
||||
sourceTmp:8 = vexVVVV_r64;
|
||||
|
||||
@ -128,7 +128,7 @@
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:PEXT Reg64, vexVVVV_r64, rm64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F3) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
|
||||
:PEXT Reg64, vexVVVV_r64, rm64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F3) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf5; Reg64 ... & rm64
|
||||
{
|
||||
indexTmp:8 = 0x8000000000000000;
|
||||
resultTmp:8 = 0;
|
||||
@ -157,7 +157,7 @@
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:RORX Reg64, rm64, imm8 is $(VEX_NONE) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F3A) & $(VEX_W1); byte=0xf0; Reg64 ... & rm64; imm8
|
||||
:RORX Reg64, rm64, imm8 is $(LONGMODE_ON) & $(VEX_NONE) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F3A) & $(VEX_W1); byte=0xf0; Reg64 ... & rm64; imm8
|
||||
{
|
||||
shiftTmp:1 = (imm8:1 & 0x3F);
|
||||
|
||||
@ -173,7 +173,7 @@
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:SARX Reg64, rm64, vexVVVV_r64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F3) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
|
||||
:SARX Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F3) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
|
||||
{
|
||||
Reg64 = rm64 s>> (vexVVVV_r64 & 0x000000000000003F);
|
||||
}
|
||||
@ -187,7 +187,7 @@
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:SHLX Reg64, rm64, vexVVVV_r64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
|
||||
:SHLX Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_66) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
|
||||
{
|
||||
Reg64 = rm64 << (vexVVVV_r64 & 0x000000000000003F);
|
||||
}
|
||||
@ -201,7 +201,7 @@
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:SHRX Reg64, rm64, vexVVVV_r64 is $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
|
||||
:SHRX Reg64, rm64, vexVVVV_r64 is $(LONGMODE_ON) & $(VEX_NDS) & $(VEX_LZ) & $(VEX_PRE_F2) & $(VEX_0F38) & $(VEX_W1) & vexVVVV_r64; byte=0xf7; Reg64 ... & rm64
|
||||
{
|
||||
Reg64 = rm64 >> (vexVVVV_r64 & 0x000000000000003F);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ define pcodeop ShadowStackLoad4B;
|
||||
SSP = SSP + zext(4 * r32:1);
|
||||
}
|
||||
@ifdef IA64
|
||||
:INCSSPQ r64 is vexMode=0 & $(PRE_F3) & $(REX_W) & byte=0x0f; byte=0xae; reg_opcode=5 & r64 {
|
||||
:INCSSPQ r64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & $(REX_W) & byte=0x0f; byte=0xae; reg_opcode=5 & r64 {
|
||||
SSP = SSP + zext(8 * r64:1);
|
||||
}
|
||||
@endif
|
||||
@ -25,7 +25,7 @@ define pcodeop ShadowStackLoad4B;
|
||||
r32 = SSP:4;
|
||||
}
|
||||
@ifdef IA64
|
||||
:RDSSPQ r64 is vexMode=0 & $(PRE_F3) & $(REX_W) & byte=0x0f; byte=0x1e; mod=3 & reg_opcode=1 & r64 {
|
||||
:RDSSPQ r64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & $(REX_W) & byte=0x0f; byte=0x1e; mod=3 & reg_opcode=1 & r64 {
|
||||
r64 = SSP;
|
||||
}
|
||||
@endif
|
||||
@ -50,7 +50,7 @@ define pcodeop writeToUserShadowStack;
|
||||
writeToShadowStack(rm32, Reg32);
|
||||
}
|
||||
@ifdef IA64
|
||||
:WRSSQ rm64,Reg64 is vexMode=0 & $(REX_W) & byte=0x0f; byte=0x0f; byte=0x38; byte=0xf6; rm64 & Reg64 ... {
|
||||
:WRSSQ rm64,Reg64 is $(LONGMODE_ON) & vexMode=0 & $(REX_W) & byte=0x0f; byte=0x0f; byte=0x38; byte=0xf6; rm64 & Reg64 ... {
|
||||
writeToShadowStack(rm64, Reg64);
|
||||
}
|
||||
@endif
|
||||
@ -59,7 +59,7 @@ define pcodeop writeToUserShadowStack;
|
||||
writeToUserShadowStack(rm32, Reg32);
|
||||
}
|
||||
@ifdef IA64
|
||||
:WRUSSQ rm64,Reg64 is vexMode=0 & $(PRE_66) & $(REX_W) & byte=0x0f; byte=0x0f; byte=0x38; byte=0xf5; rm64 & Reg64 ... {
|
||||
:WRUSSQ rm64,Reg64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & $(REX_W) & byte=0x0f; byte=0x0f; byte=0x38; byte=0xf5; rm64 & Reg64 ... {
|
||||
writeToUserShadowStack(rm64, Reg64);
|
||||
}
|
||||
@endif
|
||||
@ -78,7 +78,7 @@ define pcodeop clearShadowStackBusy;
|
||||
|
||||
:ENDBR32 is vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0x1e; byte=0xfb {}
|
||||
@ifdef IA64
|
||||
:ENDBR64 is vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0x1e; byte=0xfa {}
|
||||
:ENDBR64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & (opsize=0 | opsize=1 | opsize=2 | opsize=3) & byte=0x0f; byte=0x1e; byte=0xfa {}
|
||||
@endif
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@ define pcodeop clwb;
|
||||
|
||||
@ifdef IA64
|
||||
define pcodeop clflushopt;
|
||||
:CLFLUSHOPT m8 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xAE; m8 & reg_opcode=7 ... {
|
||||
:CLFLUSHOPT m8 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0xAE; m8 & reg_opcode=7 ... {
|
||||
clflushopt(m8);
|
||||
}
|
||||
@endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -46,7 +46,7 @@ macro lzcntflags(input, output) {
|
||||
}
|
||||
|
||||
@ifdef IA64
|
||||
:LZCNT Reg64, rm64 is vexMode=0 & opsize=2 & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0xBD; Reg64 ... & rm64 {
|
||||
:LZCNT Reg64, rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(PRE_F3) & $(REX_W) & byte=0x0F; byte=0xBD; Reg64 ... & rm64 {
|
||||
|
||||
countTmp:8 = 0;
|
||||
inputTmp:8 = rm64;
|
||||
|
@ -5,7 +5,6 @@ define pcodeop br_exception;
|
||||
# - if no base register, needs 0
|
||||
|
||||
@ifdef IA64
|
||||
|
||||
bndmk_addr64: [Rmr64] is mod=0 & Rmr64 { export Rmr64; }
|
||||
bndmk_addr64: [Rmr64 + simm8_64] is mod=1 & Rmr64; simm8_64 { export Rmr64; }
|
||||
bndmk_addr64: [simm32_64 + Rmr64] is mod=2 & Rmr64; simm32_64 { export Rmr64; }
|
||||
@ -24,8 +23,8 @@ bndmk_addr64: [simm32_64 + Base64 + Index64*ss] is mod=2 & r_m=4; Index64 & Base
|
||||
bndmk_addr64: [simm32_64 + Base64] is mod=2 & r_m=4; rexXprefix=0 & index64=4 & Base64; simm32_64 { export Base64; }
|
||||
bndmk_addr64: [Base64 + Index64*ss] is mod=2 & r_m=4; Index64 & Base64 & ss; imm32=0 { export Base64; }
|
||||
bndmk_addr64: [Base64] is mod=2 & r_m=4; rexXprefix=0 & index64=4 & Base64; imm32=0 { export Base64; }
|
||||
@endif
|
||||
|
||||
@else
|
||||
bndmk_addr32: [Rmr32] is mod=0 & Rmr32 { export Rmr32; }
|
||||
bndmk_addr32: [Rmr32 + simm8_32] is mod=1 & Rmr32; simm8_32 { export Rmr32; }
|
||||
bndmk_addr32: [Rmr32] is mod=1 & r_m!=4 & Rmr32; simm8=0 { export Rmr32; }
|
||||
@ -44,13 +43,12 @@ bndmk_addr32: [imm32 + Base + Index*ss] is mod=2 & r_m=4; Index & Base & ss; i
|
||||
bndmk_addr32: [imm32 + Base] is mod=2 & r_m=4; index=4 & Base; imm32 { export Base; }
|
||||
bndmk_addr32: [Base + Index*ss] is mod=2 & r_m=4; Index & Base & ss; imm32=0 { export Base; }
|
||||
bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export Base; }
|
||||
@endif
|
||||
|
||||
|
||||
|
||||
@ifdef IA64
|
||||
|
||||
:BNDCL bnd1, Rmr64 is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_lb & Rmr64 {
|
||||
:BNDCL bnd1, Rmr64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_lb & Rmr64 {
|
||||
# if (reg < BND.LB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
|
||||
if !(Rmr64 < bnd1_lb) goto <done>;
|
||||
BNDSTATUS = 0x01;
|
||||
@ -58,7 +56,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
<done>
|
||||
}
|
||||
|
||||
:BNDCL bnd1, Mem is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_lb) ... & Mem {
|
||||
:BNDCL bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_lb) ... & Mem {
|
||||
# if (LEA(mem) < BND.LB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
|
||||
if !(Mem < bnd1_lb) goto <done>;
|
||||
BNDSTATUS = 0x01;
|
||||
@ -66,7 +64,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
<done>
|
||||
}
|
||||
|
||||
:BNDCU bnd1, Rmr64 is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_ub & Rmr64 {
|
||||
:BNDCU bnd1, Rmr64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_ub & Rmr64 {
|
||||
# if (reg > ~(BND.UB)) then BNDSTATUS = 01H; AND BOUND EXCEPTION
|
||||
if !(Rmr64 > ~bnd1_ub) goto <done>;
|
||||
BNDSTATUS = 0x01;
|
||||
@ -74,7 +72,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
<done>
|
||||
}
|
||||
|
||||
:BNDCU bnd1, Mem is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_ub) ... & Mem {
|
||||
:BNDCU bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_ub) ... & Mem {
|
||||
# if (LEA(mem) > ~(BND.UB)) then BNDSTATUS = 01H; AND BOUND EXCEPTION
|
||||
if !(Mem > ~bnd1_ub) goto <done>;
|
||||
BNDSTATUS = 0x01;
|
||||
@ -82,7 +80,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
<done>
|
||||
}
|
||||
|
||||
:BNDCN bnd1, Rmr64 is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd1_ub & Rmr64 {
|
||||
:BNDCN bnd1, Rmr64 is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd1_ub & Rmr64 {
|
||||
# if (reg > BND.UB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
|
||||
if !(Rmr64 > bnd1_ub) goto <done>;
|
||||
BNDSTATUS = 0x01;
|
||||
@ -90,7 +88,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
<done>
|
||||
}
|
||||
|
||||
:BNDCN bnd1, Mem is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; (bnd1 & bnd1_ub) ... & Mem {
|
||||
:BNDCN bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; (bnd1 & bnd1_ub) ... & Mem {
|
||||
# if (LEA(mem) > BND.UB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
|
||||
if !(Mem > bnd1_ub) goto <done>;
|
||||
BNDSTATUS = 0x01;
|
||||
@ -99,7 +97,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
}
|
||||
|
||||
#TODO: This probably cannot be fully modeled
|
||||
:BNDLDX bnd1, Mem is vexMode=0 & byte=0x0F; byte=0x1A; bnd1 ... & Mem {
|
||||
:BNDLDX bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & byte=0x0F; byte=0x1A; bnd1 ... & Mem {
|
||||
# BNDSTATUS = bndldx_status( Mem, BNDCFGS, BNDCFGU );
|
||||
# bnd1 = bndldx( Mem, BNDCFGS, BNDCFGU );
|
||||
|
||||
@ -107,30 +105,30 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
bnd1 = *:16 Mem;
|
||||
}
|
||||
|
||||
:BNDMK bnd1, Mem is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & ( bndmk_addr64 & Mem ) {
|
||||
:BNDMK bnd1, Mem is $(LONGMODE_ON) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & ( bndmk_addr64 & Mem ) {
|
||||
# BND.LB and BND.UB set from m64
|
||||
bnd1_lb = bndmk_addr64;
|
||||
bnd1_ub = Mem;
|
||||
}
|
||||
|
||||
:BNDMOV bnd1, m128 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; bnd1 ... & m128 {
|
||||
:BNDMOV bnd1, m128 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; bnd1 ... & m128 {
|
||||
bnd1 = m128;
|
||||
}
|
||||
|
||||
:BNDMOV bnd1, bnd2 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd2 {
|
||||
:BNDMOV bnd1, bnd2 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd2 {
|
||||
bnd1 = bnd2;
|
||||
}
|
||||
|
||||
:BNDMOV m128, bnd1 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; bnd1 ... & m128 {
|
||||
:BNDMOV m128, bnd1 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; bnd1 ... & m128 {
|
||||
m128 = bnd1;
|
||||
}
|
||||
|
||||
:BNDMOV bnd2, bnd1 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd2 {
|
||||
:BNDMOV bnd2, bnd1 is $(LONGMODE_ON) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd2 {
|
||||
bnd2 = bnd1;
|
||||
}
|
||||
|
||||
#TODO: This probably cannot be fully modeled
|
||||
:BNDSTX Mem, bnd1 is vexMode=0 & byte=0x0F; byte=0x1B; bnd1 ... & Mem {
|
||||
:BNDSTX Mem, bnd1 is $(LONGMODE_ON) & vexMode=0 & byte=0x0F; byte=0x1B; bnd1 ... & Mem {
|
||||
# BNDSTATUS = bndstx_status( bnd1, BNDCFGS, BNDCFGU );
|
||||
# Mem = bndstx( bnd1, BNDCFGS, BNDCFGU );
|
||||
|
||||
@ -138,11 +136,9 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
*:16 Mem = bnd1;
|
||||
}
|
||||
|
||||
@endif
|
||||
|
||||
|
||||
@else
|
||||
|
||||
:BNDCL bnd1, Rmr32 is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_lb & Rmr32 {
|
||||
:BNDCL bnd1, Rmr32 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_lb & Rmr32 {
|
||||
# if (reg < BND.LB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
|
||||
if !(zext(Rmr32) < bnd1_lb) goto <done>;
|
||||
BNDSTATUS = 0x01;
|
||||
@ -150,7 +146,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
<done>
|
||||
}
|
||||
|
||||
:BNDCL bnd1, Mem is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_lb) ... & Mem {
|
||||
:BNDCL bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_lb) ... & Mem {
|
||||
# if (LEA(mem) < BND.LB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
|
||||
if !(zext(Mem) < bnd1_lb) goto <done>;
|
||||
BNDSTATUS = 0x01;
|
||||
@ -158,7 +154,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
<done>
|
||||
}
|
||||
|
||||
:BNDCU bnd1, Rmr32 is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_ub & Rmr32 {
|
||||
:BNDCU bnd1, Rmr32 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd1_ub & Rmr32 {
|
||||
# if (reg > ~(BND.UB)) then BNDSTATUS = 01H; AND BOUND EXCEPTION
|
||||
if !(zext(Rmr32) > ~bnd1_ub) goto <done>;
|
||||
BNDSTATUS = 0x01;
|
||||
@ -166,7 +162,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
<done>
|
||||
}
|
||||
|
||||
:BNDCU bnd1, Mem is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_ub) ... & Mem {
|
||||
:BNDCU bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1A; (bnd1 & bnd1_ub) ... & Mem {
|
||||
# if (LEA(mem) > ~(BND.UB)) then BNDSTATUS = 01H; AND BOUND EXCEPTION
|
||||
if !(zext(Mem) > ~bnd1_ub) goto <done>;
|
||||
BNDSTATUS = 0x01;
|
||||
@ -174,7 +170,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
<done>
|
||||
}
|
||||
|
||||
:BNDCN bnd1, Rmr32 is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd1_ub & Rmr32 {
|
||||
:BNDCN bnd1, Rmr32 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd1_ub & Rmr32 {
|
||||
# if (reg > BND.UB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
|
||||
if !(zext(Rmr32) > bnd1_ub) goto <done>;
|
||||
BNDSTATUS = 0x01;
|
||||
@ -182,7 +178,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
<done>
|
||||
}
|
||||
|
||||
:BNDCN bnd1, Mem is vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; (bnd1 & bnd1_ub) ... & Mem {
|
||||
:BNDCN bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F2) & byte=0x0F; byte=0x1B; (bnd1 & bnd1_ub) ... & Mem {
|
||||
# if (LEA(mem) > BND.UB) then BNDSTATUS = 01H; AND BOUND EXCEPTION
|
||||
if !(zext(Mem) > bnd1_ub) goto <done>;
|
||||
BNDSTATUS = 0x01;
|
||||
@ -191,7 +187,7 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
}
|
||||
|
||||
#TODO: This probably cannot be fully modeled
|
||||
:BNDLDX bnd1, Mem is vexMode=0 & byte=0x0F; byte=0x1A; ( bnd1 & bnd1_lb & bnd1_ub ) ... & Mem {
|
||||
:BNDLDX bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & byte=0x0F; byte=0x1A; ( bnd1 & bnd1_lb & bnd1_ub ) ... & Mem {
|
||||
# BNDSTATUS = bndldx_status( Mem, BNDCFGS, BNDCFGU );
|
||||
# bnd1 = bndldx( Mem, BNDCFGS, BNDCFGU );
|
||||
|
||||
@ -202,33 +198,33 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
bnd1_ub = zext(tmp2);
|
||||
}
|
||||
|
||||
:BNDMK bnd1, Mem is vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & ( bndmk_addr32 & Mem ) {
|
||||
:BNDMK bnd1, Mem is $(LONGMODE_OFF) & vexMode=0 & $(PRE_F3) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & ( bndmk_addr32 & Mem ) {
|
||||
# BND.LB and BND.UB set from m32
|
||||
bnd1_lb = zext(bndmk_addr32);
|
||||
bnd1_ub = zext(Mem);
|
||||
}
|
||||
|
||||
:BNDMOV bnd1, m64 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; ( bnd1 & bnd1_lb & bnd1_ub ) ... & m64 {
|
||||
:BNDMOV bnd1, m64 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; ( bnd1 & bnd1_lb & bnd1_ub ) ... & m64 {
|
||||
tmp:8 = m64;
|
||||
bnd1_lb = zext(tmp:4);
|
||||
tmp2:4 = tmp(4);
|
||||
bnd1_ub = zext(tmp2);
|
||||
}
|
||||
|
||||
:BNDMOV bnd1, bnd2 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd2 {
|
||||
:BNDMOV bnd1, bnd2 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1A; mod=3 & bnd1 & bnd2 {
|
||||
bnd1 = bnd2;
|
||||
}
|
||||
|
||||
:BNDMOV m64, bnd1 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & m64 {
|
||||
:BNDMOV m64, bnd1 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & m64 {
|
||||
m64 = (zext(bnd1_ub:4) << 32) | zext(bnd1_lb:4);
|
||||
}
|
||||
|
||||
:BNDMOV bnd2, bnd1 is vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd2 {
|
||||
:BNDMOV bnd2, bnd1 is $(LONGMODE_OFF) & vexMode=0 & $(PRE_66) & byte=0x0F; byte=0x1B; mod=3 & bnd1 & bnd2 {
|
||||
bnd2 = bnd1;
|
||||
}
|
||||
|
||||
#TODO: This probably cannot be fully modeled
|
||||
:BNDSTX Mem, bnd1 is vexMode=0 & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & Mem {
|
||||
:BNDSTX Mem, bnd1 is $(LONGMODE_OFF) & vexMode=0 & byte=0x0F; byte=0x1B; ( bnd1 & bnd1_lb & bnd1_ub ) ... & Mem {
|
||||
# BNDSTATUS = bndstx_status( bnd1, BNDCFGS, BNDCFGU );
|
||||
# Mem = bndstx( bnd1, BNDCFGS, BNDCFGU );
|
||||
|
||||
@ -236,5 +232,3 @@ bndmk_addr32: [Base] is mod=2 & r_m=4; index=4 & Base; imm32=0 { export B
|
||||
*:8 Mem = (zext(bnd1_ub:4) << 32) | zext(bnd1_lb:4);
|
||||
}
|
||||
|
||||
|
||||
@endif
|
||||
|
@ -3,5 +3,5 @@ define pcodeop rdrandIsValid;
|
||||
:RDRAND rm16 is vexMode=0 & opsize=0 & byte=0x0f; byte=0xC7; (rm16 & reg_opcode=6 ...) { rm16 = rdrand(); CF=rdrandIsValid(); }
|
||||
:RDRAND rm32 is vexMode=0 & opsize=1 & byte=0x0f; byte=0xC7; (rm32 & reg_opcode=6 ...) { rm32 = rdrand(); CF=rdrandIsValid(); }
|
||||
@ifdef IA64
|
||||
:RDRAND rm64 is vexMode=0 & opsize=2 & $(REX_W) & byte=0x0f; byte=0xC7; (rm64 & reg_opcode=6 ...) { rm64 = rdrand(); CF=rdrandIsValid(); }
|
||||
:RDRAND rm64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(REX_W) & byte=0x0f; byte=0xC7; (rm64 & reg_opcode=6 ...) { rm64 = rdrand(); CF=rdrandIsValid(); }
|
||||
@endif
|
||||
|
@ -3,5 +3,5 @@ define pcodeop rdseedIsValid;
|
||||
:RDSEED r16 is vexMode=0 & opsize=0 & byte=0x0f; byte=0xC7; r16 & reg_opcode=7 { r16 = rdseed(); CF=rdseedIsValid(); }
|
||||
:RDSEED r32 is vexMode=0 & opsize=1 & byte=0x0f; byte=0xC7; r32 & reg_opcode=7 { r32 = rdseed(); CF=rdseedIsValid(); }
|
||||
@ifdef IA64
|
||||
:RDSEED r64 is vexMode=0 & opsize=2 & $(REX_W) & byte=0x0f; byte=0xC7; r64 & reg_opcode=7 { r64 = rdseed(); CF=rdseedIsValid(); }
|
||||
:RDSEED r64 is $(LONGMODE_ON) & vexMode=0 & opsize=2 & $(REX_W) & byte=0x0f; byte=0xC7; r64 & reg_opcode=7 { r64 = rdseed(); CF=rdseedIsValid(); }
|
||||
@endif
|
||||
|
@ -12,6 +12,7 @@
|
||||
<set name="bit64" val="1"/>
|
||||
<set name="opsize" val="1"/>
|
||||
<set name="rexprefix" val="0"/>
|
||||
<set name="longMode" val="1"/>
|
||||
</context_set>
|
||||
<tracked_set space="ram">
|
||||
<set name="DF" val="0"/>
|
||||
|
Loading…
Reference in New Issue
Block a user