GP-4241: Port EmulateInstructionStateModifiers to PcodeUseropLibraryFactories.

This commit is contained in:
Dan
2026-03-18 12:09:45 +00:00
parent 7afd08a2e2
commit fa23479747
69 changed files with 1438 additions and 88 deletions
@@ -0,0 +1,47 @@
/* ###
* 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.pcode.emu.stdoplib;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.pcode.exec.*;
import ghidra.pcode.exec.PcodeUseropLibraryFactory.UseropLibrary;
// This treads on GP-4240 a bit. Still, enough to demonstrate the framework can support it.
@UseropLibrary("trig")
public class TrigPcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
@Override
@SuppressWarnings("unchecked")
public <T> PcodeUseropLibrary<T> create(SleighLanguage language,
PcodeArithmetic<T> arithmetic) {
return (PcodeUseropLibrary<T>) TrigPcodeUseropLibrary.INSTANCE;
}
public static class TrigPcodeUseropLibrary<T> extends AnnotatedPcodeUseropLibrary<T> {
public static final TrigPcodeUseropLibrary<?> INSTANCE = new TrigPcodeUseropLibrary<>();
@PcodeUserop(functional = true)
public float sin(float a) {
return (float) Math.sin(a);
}
// GP-5339: This won't work until we support overloaded userops
@PcodeUserop(functional = true)
public double sin(double a) {
return Math.sin(a);
}
}
}
@@ -20,6 +20,7 @@ import java.util.*;
import java.util.stream.Collectors;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.program.model.lang.GhidraLanguagePropertyKeys;
import ghidra.util.Msg;
import ghidra.util.classfinder.ClassSearcher;
import ghidra.util.classfinder.ExtensionPoint;
@@ -33,7 +34,7 @@ import ghidra.util.classfinder.ExtensionPoint;
*/
public interface PcodeUseropLibraryFactory extends ExtensionPoint {
/** The property key for useropLib ids in pspec files */
public static final String KEY_USEROP_LIBS = "useropLibs";
public static final String KEY_USEROP_LIBS = GhidraLanguagePropertyKeys.USEROP_LIBS;
/**
* A required annotation for identifying the library in pspec files
@@ -0,0 +1,243 @@
/* ###
* 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.pcode.exec;
import static org.junit.Assert.assertEquals;
import java.math.BigInteger;
import java.util.*;
import org.junit.AssumptionViolatedException;
import org.junit.Before;
import generic.test.AbstractGenericTest;
import ghidra.app.plugin.assembler.*;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.pcode.emu.*;
import ghidra.pcode.emulate.BreakTableCallBack;
import ghidra.pcode.emulate.Emulate;
import ghidra.pcode.exec.PcodeArithmetic.Purpose;
import ghidra.pcode.exec.PcodeExecutorStatePiece.Reason;
import ghidra.pcode.memstate.*;
import ghidra.program.model.address.*;
import ghidra.program.model.lang.Register;
import ghidra.program.model.pcode.PcodeOp;
import ghidra.util.Msg;
import ghidra.util.NumericUtilities;
import ghidra.util.classfinder.ClassSearcher;
import ghidra.util.exception.MultipleCauses;
import ghidra.util.task.ConsoleTaskMonitor;
import ghidra.util.task.TaskMonitor;
public class AbstractEmulationEquivalenceTest extends AbstractGenericTest {
protected static final TaskMonitor MONITOR = new ConsoleTaskMonitor();
protected static class TestMemoryFaultHandler implements MemoryFaultHandler {
@Override
public boolean uninitializedRead(Address address, int size, byte[] buf, int bufOffset) {
return false;
}
@Override
public boolean unknownAddress(Address address, boolean write) {
return false;
}
}
protected interface DoAsm {
void accept(AssemblyBuffer buf) throws Exception;
}
@Before
public void setupSearch() throws Exception {
ClassSearcher.search(MONITOR);
}
protected long getEntryOffset() {
return 0x00400000;
}
protected void doTestEquivOld(SleighLanguage language, Map<String, String> init,
AssemblyBuffer buf, int count, Map<String, String> expected) throws Exception {
Address entry = buf.getEntry();
MemoryState state = new DefaultMemoryState(language);
Emulate emu = new Emulate(language, state, new BreakTableCallBack(language));
AddressSet regsUnchecked = new AddressSet();
state.setMemoryBank(new MemoryPageBank(language.getAddressFactory().getRegisterSpace(),
language.isBigEndian(), 0x1000, new TestMemoryFaultHandler()) {
@Override
public void setChunk(long offset, int size, byte[] val) {
super.setChunk(offset, size, val);
try {
regsUnchecked.add(new AddressRangeImpl(getSpace().getAddress(offset), size));
}
catch (AddressOverflowException | AddressOutOfBoundsException e) {
throw new AssertionError(e);
}
}
});
state.setMemoryBank(new MemoryPageBank(language.getDefaultSpace(),
language.isBigEndian(), 0x1000, new TestMemoryFaultHandler()) {
@Override
public void setChunk(long offset, int size, byte[] val) {
/*Msg.info(this, "Old set ram[0x%x]:%d = %s".formatted(offset, size,
NumericUtilities.convertBytesToString(val)));*/
super.setChunk(offset, size, val);
}
});
byte[] bytes = buf.getBytes();
state.setChunk(bytes, language.getDefaultSpace(), entry.getOffset(), bytes.length);
for (Map.Entry<String, String> ent : init.entrySet()) {
state.setValue(ent.getKey(), new BigInteger(ent.getValue(), 16));
}
emu.setExecuteAddress(entry);
for (int i = 0; i < count; i++) {
emu.executeInstruction(false, MONITOR);
}
for (Map.Entry<String, String> ent : expected.entrySet()) {
assertEquals("Old register value mismatch on " + ent.getKey(), ent.getValue(),
state.getBigInteger(ent.getKey()).toString(16));
Register reg = language.getRegister(ent.getKey());
if (!reg.getAddressSpace().isRegisterSpace()) {
continue;
}
regsUnchecked.delete(new AddressRangeImpl(reg.getAddress(), reg.getNumBytes()));
}
if (!regsUnchecked.isEmpty()) {
Set<String> regs = new TreeSet<>();
nextAddr: while (!regsUnchecked.isEmpty()) {
Address min = regsUnchecked.getMinAddress();
List<Register> found = Arrays.asList(language.getRegisters(min));
found.sort((r1, r2) -> r1.getBitLength() - r2.getBitLength());
for (Register r : found) {
AddressRange rng = new AddressRangeImpl(r.getAddress(), r.getNumBytes());
if (!regsUnchecked.contains(rng.getMinAddress(), rng.getMaxAddress())) {
continue;
}
regs.add(r.getName());
regsUnchecked.delete(rng);
continue nextAddr;
}
regsUnchecked.delete(min, min);
}
if (!regs.isEmpty()) {
throw new AssertionError("Some written registers were not asserted: " + regs);
}
}
}
protected void doTestEquivNew(SleighLanguage language, Map<String, String> init,
AssemblyBuffer buf, int count, Map<String, String> expected) throws Exception {
Address entry = buf.getEntry();
@SuppressWarnings("unused") // uncomment arg to PcodeEmulator to enable
PcodeEmulationCallbacks<byte[]> cb = new PcodeEmulationCallbacks<>() {
public <A, U> void dataWritten(PcodeThread<byte[]> thread,
PcodeExecutorStatePiece<A, U> piece, Address address, int length, U value) {
if (!address.isMemoryAddress()) {
return;
}
if (!(value instanceof byte[] v)) {
return;
}
Msg.info(this, "New set ram[0x%x]:%d = %s".formatted(address.getOffset(), length,
NumericUtilities.convertBytesToString(v)));
};
};
PcodeEmulator emu = new PcodeEmulator(language/*, cb*/) {
@Override
protected BytesPcodeThread createThread(String name) {
/**
* TODO: There's a branch somewhere that will make this not work.
*/
return new BytesPcodeThread(name, this) {
@Override
protected boolean onMissingUseropDef(PcodeOp op, String opName) {
return false;
}
};
}
};
byte[] bytes = buf.getBytes();
emu.getSharedState().setVar(entry, bytes.length, false, bytes);
PcodeThread<byte[]> thread = emu.newThread();
PcodeExecutorState<byte[]> state = thread.getState();
PcodeArithmetic<byte[]> arithmetic = thread.getArithmetic();
for (Map.Entry<String, String> ent : init.entrySet()) {
Register reg = language.getRegister(ent.getKey());
state.setVar(reg,
arithmetic.fromConst(new BigInteger(ent.getValue(), 16), reg.getNumBytes()));
}
thread.setCounter(entry);
thread.overrideContextWithDefault();
thread.stepInstruction(count);
for (Map.Entry<String, String> ent : expected.entrySet()) {
Register reg = language.getRegister(ent.getKey());
assertEquals("New register value mismatch on " + ent.getKey(), ent.getValue(),
arithmetic.toBigInteger(state.getVar(reg, Reason.INSPECT), Purpose.INSPECT)
.toString(16));
}
}
protected void doTestEquiv(SleighLanguage language, Map<String, String> init, DoAsm doAsm,
int count, Map<String, String> expected) throws Exception {
//Msg.info(this, "Language: " + language.getLanguageID());
Assembler asm = Assemblers.getAssembler(language);
Address entry = language.getDefaultSpace().getAddress(getEntryOffset());
AssemblyBuffer buf = new AssemblyBuffer(asm, entry);
doAsm.accept(buf);
AssertionError oldFailure = null;
AssertionError newFailure = null;
try {
doTestEquivOld(language, init, buf, count, expected);
}
catch (AssertionError e) {
oldFailure = e;
Msg.error("Old failed: " + e, e);
}
try {
doTestEquivNew(language, init, buf, count, expected);
}
catch (AssertionError e) {
newFailure = e;
Msg.error("New failed: " + e, e);
}
if (newFailure != null && oldFailure != null) {
throw new AssertionError("Both old and new failed",
new MultipleCauses(List.of(oldFailure, newFailure)));
}
if (newFailure != null) {
throw newFailure;
}
if (oldFailure != null) {
throw new AssumptionViolatedException(
"Old failed, but new passed: " + oldFailure.getMessage(), oldFailure);
}
}
}
@@ -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.
@@ -89,6 +89,16 @@ public final class GhidraLanguagePropertyKeys {
public static final String EMULATE_INSTRUCTION_STATE_MODIFIER_CLASS =
"emulateInstructionStateModifierClass";
/**
* USEROP_LIBS is a string property that indicates keys for matching one or more
* {@code PcodeUseropLibaryFactory}s, which will be composed to form the library of custom
* userop implementations available to an emulator. The default is empty. NOTE: This is
* <em>not</em> the name of a class, but a comma-separated list of IDs. Each factory is also
* tagged with a list of IDs. If any ID matches, then that factory is given a chance to
* contribute userops.
*/
public static final String USEROP_LIBS = "useropLibs";
/**
* PCODE_INJECT_LIBRARY_CLASS indicates the classname of a PcodeInjectLibrary implementation
* that is used to generate p-code injection payloads which can replace either CALLs or CALLOTHERs
@@ -3,6 +3,7 @@
<processor_spec>
<properties>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.m68kEmulateInstructionStateModifier"/>
<property key="useropLibs" value="m68k,trig"/>
<property key="assemblyRating:68000:BE:32:default" value="PLATINUM"/>
</properties>
<programcounter register="PC"/>
@@ -0,0 +1,29 @@
/* ###
* 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.program.emulation;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.pcode.exec.*;
import ghidra.pcode.exec.PcodeUseropLibraryFactory.UseropLibrary;
@UseropLibrary("m68k")
public class M68kPcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
@Override
public <T> PcodeUseropLibrary<T> create(SleighLanguage language,
PcodeArithmetic<T> arithmetic) {
return PcodeUseropLibrary.nil();
}
}
@@ -22,6 +22,7 @@ import ghidra.pcode.memstate.MemoryState;
import ghidra.pcodeCPort.error.LowlevelError;
import ghidra.program.model.pcode.Varnode;
@Deprecated(forRemoval = true, since = "12.1")
public class m68kEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
/*
@@ -25,6 +25,7 @@ import ghidra.pcode.memstate.MemoryState;
import ghidra.program.model.pcode.Varnode;
//import ghidra.pcode.emulate.callother.SignalingNaNOpBehavior;
@Deprecated(forRemoval = true, since = "12.1")
public class AARCH64EmulateInstructionStateModifier extends EmulateInstructionStateModifier {
public AARCH64EmulateInstructionStateModifier(Emulate emu) {
@@ -27,25 +27,25 @@ import ghidra.program.model.pcode.Varnode;
* https://developer.arm.com/documentation/ddi0602/2024-12/SIMD-FP-Instructions/TBL--Table-vector-lookup-
*/
@UseropLibrary("aarch64")
public class AARCH64PcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
public class Aarch64PcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
@Override
public <T> PcodeUseropLibrary<T> create(SleighLanguage language,
PcodeArithmetic<T> arithmetic) {
return new AARCH64PcodeUseropLibrary<>(language);
return new Aarch64PcodeUseropLibrary<>(language);
}
public static class AARCH64PcodeUseropLibrary<T> extends DefaultPcodeUseropLibrary<T> {
public AARCH64PcodeUseropLibrary(SleighLanguage language) {
public static class Aarch64PcodeUseropLibrary<T> extends AnnotatedPcodeUseropLibrary<T> {
public Aarch64PcodeUseropLibrary(SleighLanguage language) {
SleighPcodeUseropDefinition.Factory factory =
new SleighPcodeUseropDefinition.Factory(language);
putOp(factory.define("MP_INT_ABS").params("n").body(args -> """
if (n >= 0) goto <pos>;
__op_output = -n;
goto <done>;
<pos>:
goto <done>;
<pos>
__op_output = n;
<done>:
<done>
""").build());
putOp(factory.define("SIMD_PIECE").params("simdBytes", "offset").body(args -> """
@@ -74,7 +74,7 @@ public class AARCH64PcodeUseropLibraryFactory implements PcodeUseropLibraryFacto
return "local table:16 = %s;\n".formatted(regs[0]);
}
int size = 16; // Table is always made up of 16-byte (128-bit) regs
StringBuffer buf = new StringBuffer();
StringBuilder buf = new StringBuilder();
buf.append("local table:%d;\n".formatted(size * regs.length));
for (int i = 0; i < regs.length; i++) {
buf.append("table[%d,%d] = %s;\n".formatted(8 * size * i, 8 * size, regs[i]));
@@ -84,7 +84,7 @@ public class AARCH64PcodeUseropLibraryFactory implements PcodeUseropLibraryFacto
protected String genIndex(int size, int regCount) {
int tableSize = 16 * regCount;
StringBuffer buf = new StringBuffer();
StringBuilder buf = new StringBuilder();
buf.append("local indicies:%d = m;\n".formatted(size));
buf.append("local result:%d = init;\n".formatted(size));
for (int i = 0; i < size; i++) {
@@ -103,5 +103,19 @@ public class AARCH64PcodeUseropLibraryFactory implements PcodeUseropLibraryFacto
buf.append("__op_output = result;");
return buf.toString();
}
@PcodeUserop(functional = true)
public void CallSecureMonitor(int imm16) {
}
@PcodeUserop(functional = true)
public int ExclusiveMonitorPass(long addr, int rsize) {
return 0;
}
@PcodeUserop(functional = true)
public byte ExclusiveMonitorsStatus() {
return 0;
}
}
}
@@ -45,7 +45,7 @@ import ghidra.util.exception.MultipleCauses;
import ghidra.util.task.ConsoleTaskMonitor;
import ghidra.util.task.TaskMonitor;
public class AARCH64PcodeLibraryTest extends AbstractGhidraHeadlessIntegrationTest {
public class Aarch64PcodeLibraryTest extends AbstractGhidraHeadlessIntegrationTest {
static final LanguageID LANG_ID_AARCH64 = new LanguageID("AARCH64:LE:64:v8A");
private SleighLanguage aarch64;
+17 -22
View File
@@ -293,19 +293,20 @@
<pentry minsize="1" maxsize="500" align="4">
<addr offset="0" space="stack"/>
</pentry>
</input>
<output killedbycall="true">
<pentry minsize="1" maxsize="4">
<register name="r0"/>
</pentry>
</output>
<unaffected>
<register name="sp"/>
</unaffected>
</prototype>
</input>
<output killedbycall="true">
<pentry minsize="1" maxsize="4">
<register name="r0"/>
</pentry>
</output>
<unaffected>
<register name="sp"/>
</unaffected>
</prototype>
<callotherfixup targetop="setISAMode">
<pcode incidentalcopy="true">
<input name="newTB"/>
<!-- NOP -->
<body><![CDATA[
r0 = r0;
@@ -338,8 +339,7 @@
r12 = lr + r3;
ISAModeSwitch = (r12 & 1) != 1;
TB = ISAModeSwitch;
TB = (r12 & 1) != 1;
pc = r12 & 0xfffffffe;
goto [pc];
]]></body>
@@ -356,8 +356,7 @@
offset = *:1 (tmpptr + r0);
lr = lr + 2 * zext(offset);
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -374,8 +373,7 @@
offset = *:1 (tmpptr + r0);
lr = lr + 2 * sext(offset);
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -393,8 +391,7 @@
offset = *:2 (tmpptr + index);
lr = lr + 2 * sext(offset);
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -412,8 +409,7 @@
offset = *:2 (tmpptr + index);
lr = lr + 2 * zext(offset);
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -432,8 +428,7 @@
offset = offset * 4;
lr = lr + offset;
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -15,7 +15,6 @@ define register offset=0x0084 size=4 [ r14_svc r13_svc spsr_svc ];
define register offset=0x0090 size=8 [ mult_dat8 ]; # Special internal register for dealing with multiple stores/loads
define register offset=0x0090 size=16 [ mult_dat16 ]; # Special internal register for dealing with multiple stores/loads
define register offset=0x00A0 size=4 [ fpsr ]; # floating point state register (for FPA10 floating-point accelerator)
define register offset=0x0078 size=1 [ ISAModeSwitch ]; # generic name for TB ThumbBit - set same as TB
@define FPSCR_N "fpscr[31,1]"
@define FPSCR_Z "fpscr[30,1]"
@@ -193,7 +192,7 @@ define pcodeop ReverseBitOrder;
define pcodeop SendEvent;
define pcodeop setEndianState;
# Copies ISAModeSwitch to TMode
# Copies TB to TMode
define pcodeop setISAMode;
macro affectflags() {
@@ -204,14 +203,9 @@ macro affect_resflags() {
ZR = tmpZR; NG = tmpNG;
}
macro SetISAModeSwitch(value) {
ISAModeSwitch = value;
TB = ISAModeSwitch;
}
macro SetThumbMode(value) {
SetISAModeSwitch(value);
setISAMode();
TB = value;
setISAMode(TB);
}
#
@@ -7,6 +7,7 @@
<property key="useNewFunctionStackAnalysis" value="true"/>
<property key="enableContiguousFunctionsOnly" value="false"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
<property key="useropLibs" value="arm"/>
</properties>
<programcounter register="pc"/>
<context_data>
@@ -18,7 +19,11 @@
<set name="spsr" val="0"/>
</tracked_set>
</context_data>
<register_data>
<register name="TB" alias="ISAModeSwitch"/>
</register_data>
<default_symbols>
<symbol name="MasterStackPointer" address="ram:0x0" entry="false" type="code_ptr"/>
<symbol name="Reset" address="ram:0x4" entry="true" type="code_ptr"/>
@@ -162,6 +162,7 @@
<callotherfixup targetop="setISAMode">
<pcode incidentalcopy="true">
<input name="newTB"/>
<!-- NOP -->
<body><![CDATA[
r0 = r0;
@@ -194,8 +195,7 @@
r12 = lr + r3;
ISAModeSwitch = (r12 & 1) != 1;
TB = ISAModeSwitch;
TB = (r12 & 1) != 1;
pc = r12 & 0xfffffffe;
goto [pc];
]]></body>
@@ -212,8 +212,7 @@
offset = *:1 (tmpptr + r0);
lr = lr + 2 * zext(offset);
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -230,8 +229,7 @@
offset = *:1 (tmpptr + r0);
lr = lr + 2 * sext(offset);
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -249,8 +247,7 @@
offset = *:2 (tmpptr + index);
lr = lr + 2 * sext(offset);
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -268,8 +265,7 @@
offset = *:2 (tmpptr + index);
lr = lr + 2 * zext(offset);
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -288,8 +284,7 @@
offset = offset * 4;
lr = lr + offset;
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -82,6 +82,7 @@
<callotherfixup targetop="setISAMode">
<pcode incidentalcopy="true">
<input name="newTB"/>
<!-- NOP -->
<body><![CDATA[
r0 = r0;
@@ -113,8 +114,7 @@
r12 = lr + r3;
ISAModeSwitch = (r12 & 1) != 1;
TB = ISAModeSwitch;
TB = (r12 & 1) != 1;
pc = r12 & 0xfffffffe;
goto [pc];
]]></body>
@@ -131,8 +131,7 @@
offset = *:1 (tmpptr + r0);
lr = lr + 2 * zext(offset);
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -149,8 +148,7 @@
offset = *:1 (tmpptr + r0);
lr = lr + 2 * sext(offset);
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -168,8 +166,7 @@
offset = *:2 (tmpptr + index);
lr = lr + 2 * sext(offset);
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -187,8 +184,7 @@
offset = *:2 (tmpptr + index);
lr = lr + 2 * zext(offset);
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -207,8 +203,7 @@
offset = offset * 4;
lr = lr + offset;
ISAModeSwitch = (lr & 1) != 0;
TB = ISAModeSwitch;
TB = (lr & 1) != 0;
pc = lr & 0xfffffffe;
goto [pc];
]]></body>
@@ -8,6 +8,7 @@
<property key="enableSharedReturnAnalysis" value="false"/>
<property key="enableContiguousFunctionsOnly" value="false"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
<property key="useropLibs" value="arm"/>
</properties>
<programcounter register="pc"/>
<context_data>
@@ -18,7 +19,11 @@
<set name="spsr" val="0"/>
</tracked_set>
</context_data>
<register_data>
<register name="TB" alias="ISAModeSwitch"/>
</register_data>
<default_symbols>
<symbol name="Reset" address="ram:0x0" entry="true"/>
<symbol name="UndefinedInstruction" address="ram:0x4" entry="true"/>
@@ -228,6 +228,7 @@
<callotherfixup targetop="setISAMode">
<pcode incidentalcopy="true">
<input name="newTB"/>
<!-- NOP -->
<body><![CDATA[
r0 = r0;
@@ -2317,7 +2317,7 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
:blx HAddr24 is $(AMODE) & CALLoverride=0 & ARMcond=0 & cond=15 & c2527=5 & H24=0 & HAddr24
{
lr = inst_next;
SetISAModeSwitch(1); # TMode done by HAddr24's globalset
SetThumbMode(1); # TMode done by HAddr24's globalset
call HAddr24;
# don't do causes decompiler trouble TB = 0;
} # Always changes to THUMB mode
@@ -2325,7 +2325,7 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
:blx HAddr24 is $(AMODE) & CALLoverride=1 & ARMcond=0 & cond=15 & c2527=5 & H24=0 & HAddr24
{
lr = inst_next;
SetISAModeSwitch(1); # TMode done by HAddr24's globalset
SetThumbMode(1); # TMode done by HAddr24's globalset
goto HAddr24;
} # Always changes to THUMB mode
@@ -2333,7 +2333,7 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
:blx HAddr24 is $(AMODE) & ARMcond=0 & CALLoverride=0 & cond=15 & c2527=5 & H24=1 & HAddr24
{
lr = inst_next;
SetISAModeSwitch(1); # TMode done by HAddr24's globalset
SetThumbMode(1); # TMode done by HAddr24's globalset
call HAddr24;
# don't do causes decompiler trouble TB = 0;
} # Always changes to THUMB mode
@@ -2341,7 +2341,7 @@ ArmPCRelImmed12: reloff is U23=0 & immed & rotate
:blx HAddr24 is $(AMODE) & ARMcond=0 & CALLoverride=1 & cond=15 & c2527=5 & H24=1 & HAddr24
{
lr = inst_next;
SetISAModeSwitch(1); # TMode done by HAddr24's globalset
SetThumbMode(1); # TMode done by HAddr24's globalset
goto HAddr24;
} # Always changes to THUMB mode
@@ -7,6 +7,7 @@
<property key="useNewFunctionStackAnalysis" value="true"/>
<property key="enableContiguousFunctionsOnly" value="false"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
<property key="useropLibs" value="arm"/>
<property key="assemblyRating:ARM:BE:32:v7" value="PLATINUM"/>
<property key="assemblyRating:ARM:LE:32:v7" value="PLATINUM"/>
</properties>
@@ -42,6 +43,8 @@
</default_symbols>
<register_data>
<register name="TB" alias="ISAModeSwitch"/>
<register name="q0" group="NEON" vector_lane_sizes="1,2,4"/>
<register name="q1" group="NEON" vector_lane_sizes="1,2,4"/>
<register name="q2" group="NEON" vector_lane_sizes="1,2,4"/>
@@ -8,6 +8,7 @@
<property key="useNewFunctionStackAnalysis" value="true"/>
<property key="enableContiguousFunctionsOnly" value="false"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
<property key="useropLibs" value="arm"/>
<property key="assemblyRating:ARM:BE:32:v7" value="PLATINUM"/>
<property key="assemblyRating:ARM:LE:32:v7" value="PLATINUM"/>
</properties>
@@ -43,6 +44,8 @@
</default_symbols>
<register_data>
<register name="TB" alias="ISAModeSwitch"/>
<register name="q0" group="NEON" vector_lane_sizes="1,2,4"/>
<register name="q1" group="NEON" vector_lane_sizes="1,2,4"/>
<register name="q2" group="NEON" vector_lane_sizes="1,2,4"/>
@@ -8,6 +8,7 @@
<property key="enableSharedReturnAnalysis" value="false"/>
<property key="enableContiguousFunctionsOnly" value="false"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
<property key="useropLibs" value="arm"/>
</properties>
<programcounter register="pc"/>
<context_data>
@@ -19,7 +20,11 @@
<set name="spsr" val="0"/>
</tracked_set>
</context_data>
<register_data>
<register name="TB" alias="ISAModeSwitch"/>
</register_data>
<default_symbols>
<symbol name="Reset" address="ram:0x0" entry="true"/>
<symbol name="UndefinedInstruction" address="ram:0x4" entry="true"/>
@@ -7,6 +7,7 @@
<property key="useNewFunctionStackAnalysis" value="true"/>
<property key="enableContiguousFunctionsOnly" value="false"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
<property key="useropLibs" value="arm"/>
<property key="assemblyRating:ARM:BE:32:v7" value="PLATINUM"/>
<property key="assemblyRating:ARM:LE:32:v7" value="PLATINUM"/>
</properties>
@@ -20,7 +21,11 @@
<set name="spsr" val="0"/>
</tracked_set>
</context_data>
<register_data>
<register name="TB" alias="ISAModeSwitch"/>
</register_data>
<default_symbols>
<symbol name="Reset" address="ram:0x0" entry="true"/>
<symbol name="UndefinedInstruction" address="ram:0x4" entry="true"/>
@@ -26,6 +26,7 @@ import ghidra.program.model.lang.Register;
import ghidra.program.model.lang.RegisterValue;
import ghidra.program.model.pcode.Varnode;
@Deprecated(forRemoval = true, since = "12.1")
public class ARMEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
private Register TModeReg;
@@ -0,0 +1,83 @@
/* ###
* 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.program.emulation;
public class ArmCpuState {
private volatile boolean irqEnabled = true;
private volatile boolean privileged = true;
private volatile long mainStackPointer;
private volatile long processStackPointer;
private volatile boolean threadModePrivileged;
private volatile boolean threadMode;
private volatile long basePriority;
public boolean isIrqEnabled() {
return irqEnabled;
}
public void setIrqEnabled(boolean irqEnabled) {
this.irqEnabled = irqEnabled;
}
public boolean isPrivileged() {
return privileged;
}
public void setPrivileged(boolean privileged) {
this.privileged = privileged;
}
public long getMainStackPointer() {
return mainStackPointer;
}
public void setMainStackPointer(long mainStackPointer) {
this.mainStackPointer = mainStackPointer;
}
public long getProcessStackPointer() {
return processStackPointer;
}
public void setProcessStackPointer(long processStackPointer) {
this.processStackPointer = processStackPointer;
}
public boolean isThreadModePrivileged() {
return threadModePrivileged;
}
public void setThreadModePrivileged(boolean threadModePrivileged) {
this.threadModePrivileged = threadModePrivileged;
}
public boolean isThreadMode() {
return threadMode;
}
public void setThreadMode(boolean threadMode) {
this.threadMode = threadMode;
}
public long getBasePriority() {
return basePriority;
}
public void setBasePriority(long basePriority) {
this.basePriority = basePriority;
}
}
@@ -0,0 +1,117 @@
/* ###
* 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.program.emulation;
import java.math.BigInteger;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.pcode.emu.DefaultPcodeThread.PcodeThreadExecutor;
import ghidra.pcode.exec.*;
import ghidra.pcode.exec.PcodeUseropLibraryFactory.UseropLibrary;
import ghidra.program.model.lang.*;
import ghidra.util.Msg;
@UseropLibrary("arm")
public class ArmPcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
@Override
public <T> PcodeUseropLibrary<T> create(SleighLanguage language,
PcodeArithmetic<T> arithmetic) {
return new ArmPcodeUseropLibrary<>(language);
}
public static class ArmPcodeUseropLibrary<T> extends AnnotatedPcodeUseropLibrary<T> {
private final RegisterValue tMode;
private final RegisterValue aMode;
// LATER: This should probably be injected
private final ArmCpuState cpuState = new ArmCpuState();
public ArmPcodeUseropLibrary(Language language) {
Register tModeReg = language.getRegister("TMode");
if (tModeReg != null) {
tMode = new RegisterValue(tModeReg, BigInteger.ONE);
aMode = new RegisterValue(tModeReg, BigInteger.ZERO);
}
else {
tMode = null;
aMode = null;
}
}
@PcodeUserop(modifiesContext = true)
public void setISAMode(@OpExecutor PcodeExecutor<T> exec, boolean tb) {
if (!(exec instanceof PcodeThreadExecutor<T> tExec)) {
return;
}
tExec.getThread().overrideContext(tb ? tMode : aMode);
}
@PcodeUserop(functional = true)
public void disableIRQinterrupts() {
cpuState.setIrqEnabled(false);
}
@PcodeUserop(functional = true)
public void enableIRQinterrupts() {
cpuState.setIrqEnabled(true);
}
@PcodeUserop(functional = true, hasSideEffects = false)
public boolean isCurrentModePrivileged() {
return cpuState.isPrivileged();
}
@PcodeUserop(functional = true)
public void setMainStackPointer(long mainStackPointer) {
cpuState.setMainStackPointer(mainStackPointer);
}
@PcodeUserop(functional = true)
public void setProcessStackPointer(long processStackPointer) {
cpuState.setProcessStackPointer(processStackPointer);
}
@PcodeUserop(functional = true, hasSideEffects = false)
public long getProcessStackPointer() {
return cpuState.getProcessStackPointer();
}
@PcodeUserop(functional = true/*Maybe not*/)
public void DataSynchronizationBarrier(int todo) {
Msg.warn(this, "TODO:DataSyncBarrier");
}
@PcodeUserop(functional = true/*Maybe not*/)
public void InstructionSynchronizationBarrier(int todo) {
Msg.warn(this, "TODO:InsSyncBarrier");
}
@PcodeUserop(functional = true)
public void setThreadModePrivileged(boolean privileged) {
cpuState.setThreadModePrivileged(privileged);
}
@PcodeUserop(functional = true, hasSideEffects = false)
public boolean isThreadMode() {
return cpuState.isThreadMode();
}
@PcodeUserop(functional = true)
public void setBasePriority(long basePriority) {
cpuState.setBasePriority(basePriority);
}
}
}
@@ -919,9 +919,12 @@ DXuPos: pos is lsb [ pos = lsb + 32; ] { tmp:1
DinsXSize: mysize is msbd & lsb [ mysize = msbd - lsb + 1 + 32; ] { tmp:1 = mysize; export tmp; }
@endif
define pcodeop setISAMode;
macro JXWritePC(addr) {
@ifdef ISA_VARIANT
ISAModeSwitch = (addr & 0x1) != 0;
setISAMode(ISAModeSwitch);
tmp:$(REGSIZE) = -2;
tmp = tmp & addr;
pc = tmp;
@@ -639,9 +639,10 @@ SAVE_TOP: SAVE_ARG^EXT_FRAME^SAVE_RA^SAVE_SREG^SAVE_STAT is EXT_FRAME & SAVE_RA
:jalx Abs26_m16 is ISA_MODE=1 & RELP=1 & ext_isjal=1 & ext_tgt_x=1 & Abs26_m16
[ ext_delay=0b10; ISA_MODE = 0; globalset(Abs26_m16, ISA_MODE); globalset(inst_next, ext_delay); ] {
ra = inst_next | 0x1;
ra = inst_next | 0x1;
delayslot( 1 );
ISAModeSwitch = 0;
ISAModeSwitch = 0;
setISAMode(ISAModeSwitch);
call Abs26_m16;
}
@@ -4,6 +4,7 @@
<properties>
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
<property key="useropLibs" value="mips"/>
<property key="assemblyRating:MIPS:BE:32:default" value="PLATINUM"/>
</properties>
<programcounter register="pc"/>
@@ -1018,6 +1018,7 @@ define pcodeop SYNC;
ra = inst_next;
delayslot( 1 );
ISAModeSwitch = 1;
setISAMode(ISAModeSwitch);
call Abs26;
}
@endif
@@ -4,6 +4,7 @@
<properties>
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
<property key="useropLibs" value="mips"/>
<property key="assemblyRating:MIPS:BE:32:R6" value="PLATINUM"/>
</properties>
<programcounter register="pc"/>
@@ -154,5 +154,15 @@
</localrange>
</prototype>
</default_proto>
<callotherfixup targetop="setISAMode">
<pcode incidentalcopy="true">
<input name="newMode"/>
<!-- NOP -->
<body><![CDATA[
v0 = v0;
]]></body>
</pcode>
</callotherfixup>
</compiler_spec>
@@ -84,5 +84,15 @@
</localrange>
</prototype>
</default_proto>
<callotherfixup targetop="setISAMode">
<pcode incidentalcopy="true">
<input name="newMode"/>
<!-- NOP -->
<body><![CDATA[
v0 = v0;
]]></body>
</pcode>
</callotherfixup>
</compiler_spec>
@@ -183,6 +183,15 @@
<register name="gp"/> <!-- Compilers may save gp to the stack before a call and restore it afterward -->
</internal_storage>
</prototype>
<callotherfixup targetop="setISAMode">
<pcode incidentalcopy="true">
<input name="newMode"/>
<!-- NOP -->
<body><![CDATA[
v0 = v0;
]]></body>
</pcode>
</callotherfixup>
</compiler_spec>
@@ -174,5 +174,15 @@
<register name="gp"/> <!-- Compilers may save gp to the stack before a call and restore it afterward -->
</internal_storage>
</prototype>
<callotherfixup targetop="setISAMode">
<pcode incidentalcopy="true">
<input name="newMode"/>
<!-- NOP -->
<body><![CDATA[
v0 = v0;
]]></body>
</pcode>
</callotherfixup>
</compiler_spec>
@@ -4,6 +4,7 @@
<properties>
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
<property key="useropLibs" value="mips"/>
<property key="assemblyRating:MIPS:BE:32:micro" value="PLATINUM"/>
</properties>
<programcounter register="pc"/>
@@ -4,6 +4,7 @@
<properties>
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
<property key="useropLibs" value="mips"/>
<property key="assemblyRating:MIPS:BE:64:64-32addr" value="PLATINUM"/>
<property key="assemblyRating:MIPS:BE:64:default" value="PLATINUM"/>
</properties>
@@ -4,6 +4,7 @@
<properties>
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
<property key="useropLibs" value="mips"/>
<property key="assemblyRating:MIPS:BE:64:R6" value="PLATINUM"/>
</properties>
<programcounter register="pc"/>
@@ -133,4 +133,15 @@
</unaffected>
</prototype>
</default_proto>
<callotherfixup targetop="setISAMode">
<pcode incidentalcopy="true">
<input name="newMode"/>
<!-- NOP -->
<body><![CDATA[
v0 = v0;
]]></body>
</pcode>
</callotherfixup>
</compiler_spec>
@@ -125,4 +125,15 @@
</localrange>
</prototype>
</default_proto>
<callotherfixup targetop="setISAMode">
<pcode incidentalcopy="true">
<input name="newMode"/>
<!-- NOP -->
<body><![CDATA[
v0 = v0;
]]></body>
</pcode>
</callotherfixup>
</compiler_spec>
@@ -95,4 +95,15 @@
</unaffected>
</prototype>
</default_proto>
<callotherfixup targetop="setISAMode">
<pcode incidentalcopy="true">
<input name="newMode"/>
<!-- NOP -->
<body><![CDATA[
v0 = v0;
]]></body>
</pcode>
</callotherfixup>
</compiler_spec>
@@ -186,4 +186,15 @@
</killedbycall>
</prototype>
</default_proto>
<callotherfixup targetop="setISAMode">
<pcode incidentalcopy="true">
<input name="newMode"/>
<!-- NOP -->
<body><![CDATA[
v0 = v0;
]]></body>
</pcode>
</callotherfixup>
</compiler_spec>
@@ -170,4 +170,15 @@
</killedbycall>
</prototype>
</default_proto>
<callotherfixup targetop="setISAMode">
<pcode incidentalcopy="true">
<input name="newMode"/>
<!-- NOP -->
<body><![CDATA[
v0 = v0;
]]></body>
</pcode>
</callotherfixup>
</compiler_spec>
@@ -4,6 +4,7 @@
<properties>
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
<property key="useropLibs" value="mips"/>
</properties>
<programcounter register="pc"/>
<context_data>
@@ -2369,7 +2369,8 @@ STORE_TOP16: STORE_SREG^ra,EXT_CODE4E(sp) is mic_listr6 & REL6=1 & STORE_SREG &
:jalx Abs26_mic2 is ISA_MODE=1 & RELP=0 & mic_op=0b111100 & REL6=0 & mic_code ; Abs26_mic2 [ ext_32_code = mic_code; ISA_MODE = 0; globalset(Abs26_mic2, ISA_MODE);] {
ra = inst_next | 0x1;
delayslot( 1 );
ISAModeSwitch = 0;
ISAModeSwitch = 0;
setISAMode(ISAModeSwitch);
call Abs26_mic2;
}
@@ -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.
@@ -26,6 +26,7 @@ import ghidra.program.model.lang.RegisterValue;
import ghidra.program.model.pcode.PcodeOp;
//import ghidra.pcode.emulate.callother.SignalingNaNOpBehavior;
@Deprecated(forRemoval = true, since = "12.1")
public class MIPSEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
private Register ismReg;
@@ -0,0 +1,58 @@
/* ###
* 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.program.emulation;
import java.math.BigInteger;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.pcode.emu.DefaultPcodeThread.PcodeThreadExecutor;
import ghidra.pcode.exec.*;
import ghidra.pcode.exec.PcodeUseropLibraryFactory.UseropLibrary;
import ghidra.program.model.lang.*;
@UseropLibrary("mips")
public class MipsPcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
@Override
public <T> PcodeUseropLibrary<T> create(SleighLanguage language,
PcodeArithmetic<T> arithmetic) {
return new MipsPcodeUseropLibrary<>(language);
}
public static class MipsPcodeUseropLibrary<T> extends AnnotatedPcodeUseropLibrary<T> {
private final RegisterValue mode0;
private final RegisterValue mode1;
public MipsPcodeUseropLibrary(Language language) {
Register isaModeReg = language.getRegister("ISA_MODE");
if (isaModeReg != null) {
mode0 = new RegisterValue(isaModeReg, BigInteger.ZERO);
mode1 = new RegisterValue(isaModeReg, BigInteger.ONE);
}
else {
mode0 = null;
mode1 = null;
}
}
@PcodeUserop(modifiesContext = true)
public void setISAMode(@OpExecutor PcodeExecutor<T> exec, boolean mode) {
if (!(exec instanceof PcodeThreadExecutor<T> tExec)) {
return;
}
tExec.getThread().overrideContext(mode ? mode1 : mode0);
}
}
}
@@ -4,6 +4,7 @@
<properties>
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.PPCEmulateInstructionStateModifier"/>
<property key="useropLibs" value="ppc"/>
<property key="assemblyRating:PowerPC:BE:32:default" value="PLATINUM"/>
</properties>
<programcounter register="pc"/>
@@ -5,6 +5,7 @@
<properties>
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.PPCEmulateInstructionStateModifier"/>
<property key="useropLibs" value="ppc"/>
</properties>
<programcounter register="pc"/>
@@ -4,6 +4,7 @@
<properties>
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.PPCEmulateInstructionStateModifier"/>
<property key="useropLibs" value="ppc"/>
<property key="assemblyRating:PowerPC:BE:64:A2-32addr" value="PLATINUM"/>
<property key="assemblyRating:PowerPC:BE:64:A2ALT-32addr" value="PLATINUM"/>
<property key="assemblyRating:PowerPC:BE:64:default" value="PLATINUM"/>
@@ -24,6 +24,7 @@ import ghidra.pcode.memstate.MemoryState;
import ghidra.pcodeCPort.error.LowlevelError;
import ghidra.program.model.pcode.Varnode;
@Deprecated(forRemoval = true, since = "12.1")
public class PPCEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
public PPCEmulateInstructionStateModifier(Emulate emu) {

Some files were not shown because too many files have changed in this diff Show More