mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-27 12:03:39 +08:00
Merge remote-tracking branch 'origin/Ghidra_12.1'
This commit is contained in:
+47
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-1
@@ -20,6 +20,7 @@ import java.util.*;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
|
||||||
|
import ghidra.program.model.lang.GhidraLanguagePropertyKeys;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
import ghidra.util.classfinder.ClassSearcher;
|
import ghidra.util.classfinder.ClassSearcher;
|
||||||
import ghidra.util.classfinder.ExtensionPoint;
|
import ghidra.util.classfinder.ExtensionPoint;
|
||||||
@@ -33,7 +34,7 @@ import ghidra.util.classfinder.ExtensionPoint;
|
|||||||
*/
|
*/
|
||||||
public interface PcodeUseropLibraryFactory extends ExtensionPoint {
|
public interface PcodeUseropLibraryFactory extends ExtensionPoint {
|
||||||
/** The property key for useropLib ids in pspec files */
|
/** 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
|
* A required annotation for identifying the library in pspec files
|
||||||
|
|||||||
+243
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-2
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* 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 =
|
public static final String EMULATE_INSTRUCTION_STATE_MODIFIER_CLASS =
|
||||||
"emulateInstructionStateModifierClass";
|
"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
|
* 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
|
* that is used to generate p-code injection payloads which can replace either CALLs or CALLOTHERs
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<processor_spec>
|
<processor_spec>
|
||||||
<properties>
|
<properties>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.m68kEmulateInstructionStateModifier"/>
|
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.m68kEmulateInstructionStateModifier"/>
|
||||||
|
<property key="useropLibs" value="m68k,trig"/>
|
||||||
<property key="assemblyRating:68000:BE:32:default" value="PLATINUM"/>
|
<property key="assemblyRating:68000:BE:32:default" value="PLATINUM"/>
|
||||||
</properties>
|
</properties>
|
||||||
<programcounter register="PC"/>
|
<programcounter register="PC"/>
|
||||||
|
|||||||
+29
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -22,6 +22,7 @@ import ghidra.pcode.memstate.MemoryState;
|
|||||||
import ghidra.pcodeCPort.error.LowlevelError;
|
import ghidra.pcodeCPort.error.LowlevelError;
|
||||||
import ghidra.program.model.pcode.Varnode;
|
import ghidra.program.model.pcode.Varnode;
|
||||||
|
|
||||||
|
@Deprecated(forRemoval = true, since = "12.1")
|
||||||
public class m68kEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
public class m68kEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+1
@@ -25,6 +25,7 @@ import ghidra.pcode.memstate.MemoryState;
|
|||||||
import ghidra.program.model.pcode.Varnode;
|
import ghidra.program.model.pcode.Varnode;
|
||||||
//import ghidra.pcode.emulate.callother.SignalingNaNOpBehavior;
|
//import ghidra.pcode.emulate.callother.SignalingNaNOpBehavior;
|
||||||
|
|
||||||
|
@Deprecated(forRemoval = true, since = "12.1")
|
||||||
public class AARCH64EmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
public class AARCH64EmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
||||||
|
|
||||||
public AARCH64EmulateInstructionStateModifier(Emulate emu) {
|
public AARCH64EmulateInstructionStateModifier(Emulate emu) {
|
||||||
|
|||||||
+23
-9
@@ -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-
|
* https://developer.arm.com/documentation/ddi0602/2024-12/SIMD-FP-Instructions/TBL--Table-vector-lookup-
|
||||||
*/
|
*/
|
||||||
@UseropLibrary("aarch64")
|
@UseropLibrary("aarch64")
|
||||||
public class AARCH64PcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
|
public class Aarch64PcodeUseropLibraryFactory implements PcodeUseropLibraryFactory {
|
||||||
@Override
|
@Override
|
||||||
public <T> PcodeUseropLibrary<T> create(SleighLanguage language,
|
public <T> PcodeUseropLibrary<T> create(SleighLanguage language,
|
||||||
PcodeArithmetic<T> arithmetic) {
|
PcodeArithmetic<T> arithmetic) {
|
||||||
return new AARCH64PcodeUseropLibrary<>(language);
|
return new Aarch64PcodeUseropLibrary<>(language);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AARCH64PcodeUseropLibrary<T> extends DefaultPcodeUseropLibrary<T> {
|
public static class Aarch64PcodeUseropLibrary<T> extends AnnotatedPcodeUseropLibrary<T> {
|
||||||
public AARCH64PcodeUseropLibrary(SleighLanguage language) {
|
public Aarch64PcodeUseropLibrary(SleighLanguage language) {
|
||||||
SleighPcodeUseropDefinition.Factory factory =
|
SleighPcodeUseropDefinition.Factory factory =
|
||||||
new SleighPcodeUseropDefinition.Factory(language);
|
new SleighPcodeUseropDefinition.Factory(language);
|
||||||
|
|
||||||
putOp(factory.define("MP_INT_ABS").params("n").body(args -> """
|
putOp(factory.define("MP_INT_ABS").params("n").body(args -> """
|
||||||
if (n >= 0) goto <pos>;
|
if (n >= 0) goto <pos>;
|
||||||
__op_output = -n;
|
__op_output = -n;
|
||||||
goto <done>;
|
goto <done>;
|
||||||
<pos>:
|
<pos>
|
||||||
__op_output = n;
|
__op_output = n;
|
||||||
<done>:
|
<done>
|
||||||
""").build());
|
""").build());
|
||||||
|
|
||||||
putOp(factory.define("SIMD_PIECE").params("simdBytes", "offset").body(args -> """
|
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]);
|
return "local table:16 = %s;\n".formatted(regs[0]);
|
||||||
}
|
}
|
||||||
int size = 16; // Table is always made up of 16-byte (128-bit) regs
|
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));
|
buf.append("local table:%d;\n".formatted(size * regs.length));
|
||||||
for (int i = 0; i < regs.length; i++) {
|
for (int i = 0; i < regs.length; i++) {
|
||||||
buf.append("table[%d,%d] = %s;\n".formatted(8 * size * i, 8 * size, regs[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) {
|
protected String genIndex(int size, int regCount) {
|
||||||
int tableSize = 16 * 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 indicies:%d = m;\n".formatted(size));
|
||||||
buf.append("local result:%d = init;\n".formatted(size));
|
buf.append("local result:%d = init;\n".formatted(size));
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
@@ -103,5 +103,19 @@ public class AARCH64PcodeUseropLibraryFactory implements PcodeUseropLibraryFacto
|
|||||||
buf.append("__op_output = result;");
|
buf.append("__op_output = result;");
|
||||||
return buf.toString();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -45,7 +45,7 @@ import ghidra.util.exception.MultipleCauses;
|
|||||||
import ghidra.util.task.ConsoleTaskMonitor;
|
import ghidra.util.task.ConsoleTaskMonitor;
|
||||||
import ghidra.util.task.TaskMonitor;
|
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");
|
static final LanguageID LANG_ID_AARCH64 = new LanguageID("AARCH64:LE:64:v8A");
|
||||||
|
|
||||||
private SleighLanguage aarch64;
|
private SleighLanguage aarch64;
|
||||||
@@ -293,19 +293,20 @@
|
|||||||
<pentry minsize="1" maxsize="500" align="4">
|
<pentry minsize="1" maxsize="500" align="4">
|
||||||
<addr offset="0" space="stack"/>
|
<addr offset="0" space="stack"/>
|
||||||
</pentry>
|
</pentry>
|
||||||
</input>
|
</input>
|
||||||
<output killedbycall="true">
|
<output killedbycall="true">
|
||||||
<pentry minsize="1" maxsize="4">
|
<pentry minsize="1" maxsize="4">
|
||||||
<register name="r0"/>
|
<register name="r0"/>
|
||||||
</pentry>
|
</pentry>
|
||||||
</output>
|
</output>
|
||||||
<unaffected>
|
<unaffected>
|
||||||
<register name="sp"/>
|
<register name="sp"/>
|
||||||
</unaffected>
|
</unaffected>
|
||||||
</prototype>
|
</prototype>
|
||||||
|
|
||||||
<callotherfixup targetop="setISAMode">
|
<callotherfixup targetop="setISAMode">
|
||||||
<pcode incidentalcopy="true">
|
<pcode incidentalcopy="true">
|
||||||
|
<input name="newTB"/>
|
||||||
<!-- NOP -->
|
<!-- NOP -->
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
r0 = r0;
|
r0 = r0;
|
||||||
@@ -338,8 +339,7 @@
|
|||||||
|
|
||||||
r12 = lr + r3;
|
r12 = lr + r3;
|
||||||
|
|
||||||
ISAModeSwitch = (r12 & 1) != 1;
|
TB = (r12 & 1) != 1;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = r12 & 0xfffffffe;
|
pc = r12 & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -356,8 +356,7 @@
|
|||||||
offset = *:1 (tmpptr + r0);
|
offset = *:1 (tmpptr + r0);
|
||||||
lr = lr + 2 * zext(offset);
|
lr = lr + 2 * zext(offset);
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -374,8 +373,7 @@
|
|||||||
offset = *:1 (tmpptr + r0);
|
offset = *:1 (tmpptr + r0);
|
||||||
lr = lr + 2 * sext(offset);
|
lr = lr + 2 * sext(offset);
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -393,8 +391,7 @@
|
|||||||
offset = *:2 (tmpptr + index);
|
offset = *:2 (tmpptr + index);
|
||||||
lr = lr + 2 * sext(offset);
|
lr = lr + 2 * sext(offset);
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -412,8 +409,7 @@
|
|||||||
offset = *:2 (tmpptr + index);
|
offset = *:2 (tmpptr + index);
|
||||||
lr = lr + 2 * zext(offset);
|
lr = lr + 2 * zext(offset);
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -432,8 +428,7 @@
|
|||||||
offset = offset * 4;
|
offset = offset * 4;
|
||||||
lr = lr + offset;
|
lr = lr + offset;
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></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=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=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=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_N "fpscr[31,1]"
|
||||||
@define FPSCR_Z "fpscr[30,1]"
|
@define FPSCR_Z "fpscr[30,1]"
|
||||||
@@ -193,7 +192,7 @@ define pcodeop ReverseBitOrder;
|
|||||||
define pcodeop SendEvent;
|
define pcodeop SendEvent;
|
||||||
define pcodeop setEndianState;
|
define pcodeop setEndianState;
|
||||||
|
|
||||||
# Copies ISAModeSwitch to TMode
|
# Copies TB to TMode
|
||||||
define pcodeop setISAMode;
|
define pcodeop setISAMode;
|
||||||
|
|
||||||
macro affectflags() {
|
macro affectflags() {
|
||||||
@@ -204,14 +203,9 @@ macro affect_resflags() {
|
|||||||
ZR = tmpZR; NG = tmpNG;
|
ZR = tmpZR; NG = tmpNG;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro SetISAModeSwitch(value) {
|
|
||||||
ISAModeSwitch = value;
|
|
||||||
TB = ISAModeSwitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro SetThumbMode(value) {
|
macro SetThumbMode(value) {
|
||||||
SetISAModeSwitch(value);
|
TB = value;
|
||||||
setISAMode();
|
setISAMode(TB);
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
<property key="useNewFunctionStackAnalysis" value="true"/>
|
<property key="useNewFunctionStackAnalysis" value="true"/>
|
||||||
<property key="enableContiguousFunctionsOnly" value="false"/>
|
<property key="enableContiguousFunctionsOnly" value="false"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
||||||
|
<property key="useropLibs" value="arm"/>
|
||||||
</properties>
|
</properties>
|
||||||
<programcounter register="pc"/>
|
<programcounter register="pc"/>
|
||||||
<context_data>
|
<context_data>
|
||||||
@@ -18,7 +19,11 @@
|
|||||||
<set name="spsr" val="0"/>
|
<set name="spsr" val="0"/>
|
||||||
</tracked_set>
|
</tracked_set>
|
||||||
</context_data>
|
</context_data>
|
||||||
|
|
||||||
|
<register_data>
|
||||||
|
<register name="TB" alias="ISAModeSwitch"/>
|
||||||
|
</register_data>
|
||||||
|
|
||||||
<default_symbols>
|
<default_symbols>
|
||||||
<symbol name="MasterStackPointer" address="ram:0x0" entry="false" type="code_ptr"/>
|
<symbol name="MasterStackPointer" address="ram:0x0" entry="false" type="code_ptr"/>
|
||||||
<symbol name="Reset" address="ram:0x4" entry="true" type="code_ptr"/>
|
<symbol name="Reset" address="ram:0x4" entry="true" type="code_ptr"/>
|
||||||
|
|||||||
@@ -162,6 +162,7 @@
|
|||||||
|
|
||||||
<callotherfixup targetop="setISAMode">
|
<callotherfixup targetop="setISAMode">
|
||||||
<pcode incidentalcopy="true">
|
<pcode incidentalcopy="true">
|
||||||
|
<input name="newTB"/>
|
||||||
<!-- NOP -->
|
<!-- NOP -->
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
r0 = r0;
|
r0 = r0;
|
||||||
@@ -194,8 +195,7 @@
|
|||||||
|
|
||||||
r12 = lr + r3;
|
r12 = lr + r3;
|
||||||
|
|
||||||
ISAModeSwitch = (r12 & 1) != 1;
|
TB = (r12 & 1) != 1;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = r12 & 0xfffffffe;
|
pc = r12 & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -212,8 +212,7 @@
|
|||||||
offset = *:1 (tmpptr + r0);
|
offset = *:1 (tmpptr + r0);
|
||||||
lr = lr + 2 * zext(offset);
|
lr = lr + 2 * zext(offset);
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -230,8 +229,7 @@
|
|||||||
offset = *:1 (tmpptr + r0);
|
offset = *:1 (tmpptr + r0);
|
||||||
lr = lr + 2 * sext(offset);
|
lr = lr + 2 * sext(offset);
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -249,8 +247,7 @@
|
|||||||
offset = *:2 (tmpptr + index);
|
offset = *:2 (tmpptr + index);
|
||||||
lr = lr + 2 * sext(offset);
|
lr = lr + 2 * sext(offset);
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -268,8 +265,7 @@
|
|||||||
offset = *:2 (tmpptr + index);
|
offset = *:2 (tmpptr + index);
|
||||||
lr = lr + 2 * zext(offset);
|
lr = lr + 2 * zext(offset);
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -288,8 +284,7 @@
|
|||||||
offset = offset * 4;
|
offset = offset * 4;
|
||||||
lr = lr + offset;
|
lr = lr + offset;
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
|
|||||||
@@ -82,6 +82,7 @@
|
|||||||
|
|
||||||
<callotherfixup targetop="setISAMode">
|
<callotherfixup targetop="setISAMode">
|
||||||
<pcode incidentalcopy="true">
|
<pcode incidentalcopy="true">
|
||||||
|
<input name="newTB"/>
|
||||||
<!-- NOP -->
|
<!-- NOP -->
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
r0 = r0;
|
r0 = r0;
|
||||||
@@ -113,8 +114,7 @@
|
|||||||
|
|
||||||
r12 = lr + r3;
|
r12 = lr + r3;
|
||||||
|
|
||||||
ISAModeSwitch = (r12 & 1) != 1;
|
TB = (r12 & 1) != 1;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = r12 & 0xfffffffe;
|
pc = r12 & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -131,8 +131,7 @@
|
|||||||
offset = *:1 (tmpptr + r0);
|
offset = *:1 (tmpptr + r0);
|
||||||
lr = lr + 2 * zext(offset);
|
lr = lr + 2 * zext(offset);
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -149,8 +148,7 @@
|
|||||||
offset = *:1 (tmpptr + r0);
|
offset = *:1 (tmpptr + r0);
|
||||||
lr = lr + 2 * sext(offset);
|
lr = lr + 2 * sext(offset);
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -168,8 +166,7 @@
|
|||||||
offset = *:2 (tmpptr + index);
|
offset = *:2 (tmpptr + index);
|
||||||
lr = lr + 2 * sext(offset);
|
lr = lr + 2 * sext(offset);
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -187,8 +184,7 @@
|
|||||||
offset = *:2 (tmpptr + index);
|
offset = *:2 (tmpptr + index);
|
||||||
lr = lr + 2 * zext(offset);
|
lr = lr + 2 * zext(offset);
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
@@ -207,8 +203,7 @@
|
|||||||
offset = offset * 4;
|
offset = offset * 4;
|
||||||
lr = lr + offset;
|
lr = lr + offset;
|
||||||
|
|
||||||
ISAModeSwitch = (lr & 1) != 0;
|
TB = (lr & 1) != 0;
|
||||||
TB = ISAModeSwitch;
|
|
||||||
pc = lr & 0xfffffffe;
|
pc = lr & 0xfffffffe;
|
||||||
goto [pc];
|
goto [pc];
|
||||||
]]></body>
|
]]></body>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
<property key="enableSharedReturnAnalysis" value="false"/>
|
<property key="enableSharedReturnAnalysis" value="false"/>
|
||||||
<property key="enableContiguousFunctionsOnly" value="false"/>
|
<property key="enableContiguousFunctionsOnly" value="false"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
||||||
|
<property key="useropLibs" value="arm"/>
|
||||||
</properties>
|
</properties>
|
||||||
<programcounter register="pc"/>
|
<programcounter register="pc"/>
|
||||||
<context_data>
|
<context_data>
|
||||||
@@ -18,7 +19,11 @@
|
|||||||
<set name="spsr" val="0"/>
|
<set name="spsr" val="0"/>
|
||||||
</tracked_set>
|
</tracked_set>
|
||||||
</context_data>
|
</context_data>
|
||||||
|
|
||||||
|
<register_data>
|
||||||
|
<register name="TB" alias="ISAModeSwitch"/>
|
||||||
|
</register_data>
|
||||||
|
|
||||||
<default_symbols>
|
<default_symbols>
|
||||||
<symbol name="Reset" address="ram:0x0" entry="true"/>
|
<symbol name="Reset" address="ram:0x0" entry="true"/>
|
||||||
<symbol name="UndefinedInstruction" address="ram:0x4" entry="true"/>
|
<symbol name="UndefinedInstruction" address="ram:0x4" entry="true"/>
|
||||||
|
|||||||
@@ -228,6 +228,7 @@
|
|||||||
|
|
||||||
<callotherfixup targetop="setISAMode">
|
<callotherfixup targetop="setISAMode">
|
||||||
<pcode incidentalcopy="true">
|
<pcode incidentalcopy="true">
|
||||||
|
<input name="newTB"/>
|
||||||
<!-- NOP -->
|
<!-- NOP -->
|
||||||
<body><![CDATA[
|
<body><![CDATA[
|
||||||
r0 = r0;
|
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
|
:blx HAddr24 is $(AMODE) & CALLoverride=0 & ARMcond=0 & cond=15 & c2527=5 & H24=0 & HAddr24
|
||||||
{
|
{
|
||||||
lr = inst_next;
|
lr = inst_next;
|
||||||
SetISAModeSwitch(1); # TMode done by HAddr24's globalset
|
SetThumbMode(1); # TMode done by HAddr24's globalset
|
||||||
call HAddr24;
|
call HAddr24;
|
||||||
# don't do causes decompiler trouble TB = 0;
|
# don't do causes decompiler trouble TB = 0;
|
||||||
} # Always changes to THUMB mode
|
} # 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
|
:blx HAddr24 is $(AMODE) & CALLoverride=1 & ARMcond=0 & cond=15 & c2527=5 & H24=0 & HAddr24
|
||||||
{
|
{
|
||||||
lr = inst_next;
|
lr = inst_next;
|
||||||
SetISAModeSwitch(1); # TMode done by HAddr24's globalset
|
SetThumbMode(1); # TMode done by HAddr24's globalset
|
||||||
goto HAddr24;
|
goto HAddr24;
|
||||||
} # Always changes to THUMB mode
|
} # 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
|
:blx HAddr24 is $(AMODE) & ARMcond=0 & CALLoverride=0 & cond=15 & c2527=5 & H24=1 & HAddr24
|
||||||
{
|
{
|
||||||
lr = inst_next;
|
lr = inst_next;
|
||||||
SetISAModeSwitch(1); # TMode done by HAddr24's globalset
|
SetThumbMode(1); # TMode done by HAddr24's globalset
|
||||||
call HAddr24;
|
call HAddr24;
|
||||||
# don't do causes decompiler trouble TB = 0;
|
# don't do causes decompiler trouble TB = 0;
|
||||||
} # Always changes to THUMB mode
|
} # 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
|
:blx HAddr24 is $(AMODE) & ARMcond=0 & CALLoverride=1 & cond=15 & c2527=5 & H24=1 & HAddr24
|
||||||
{
|
{
|
||||||
lr = inst_next;
|
lr = inst_next;
|
||||||
SetISAModeSwitch(1); # TMode done by HAddr24's globalset
|
SetThumbMode(1); # TMode done by HAddr24's globalset
|
||||||
goto HAddr24;
|
goto HAddr24;
|
||||||
} # Always changes to THUMB mode
|
} # Always changes to THUMB mode
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
<property key="useNewFunctionStackAnalysis" value="true"/>
|
<property key="useNewFunctionStackAnalysis" value="true"/>
|
||||||
<property key="enableContiguousFunctionsOnly" value="false"/>
|
<property key="enableContiguousFunctionsOnly" value="false"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
<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:BE:32:v7" value="PLATINUM"/>
|
||||||
<property key="assemblyRating:ARM:LE:32:v7" value="PLATINUM"/>
|
<property key="assemblyRating:ARM:LE:32:v7" value="PLATINUM"/>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -42,6 +43,8 @@
|
|||||||
</default_symbols>
|
</default_symbols>
|
||||||
|
|
||||||
<register_data>
|
<register_data>
|
||||||
|
<register name="TB" alias="ISAModeSwitch"/>
|
||||||
|
|
||||||
<register name="q0" group="NEON" vector_lane_sizes="1,2,4"/>
|
<register name="q0" group="NEON" vector_lane_sizes="1,2,4"/>
|
||||||
<register name="q1" 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"/>
|
<register name="q2" group="NEON" vector_lane_sizes="1,2,4"/>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
<property key="useNewFunctionStackAnalysis" value="true"/>
|
<property key="useNewFunctionStackAnalysis" value="true"/>
|
||||||
<property key="enableContiguousFunctionsOnly" value="false"/>
|
<property key="enableContiguousFunctionsOnly" value="false"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
<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:BE:32:v7" value="PLATINUM"/>
|
||||||
<property key="assemblyRating:ARM:LE:32:v7" value="PLATINUM"/>
|
<property key="assemblyRating:ARM:LE:32:v7" value="PLATINUM"/>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -43,6 +44,8 @@
|
|||||||
</default_symbols>
|
</default_symbols>
|
||||||
|
|
||||||
<register_data>
|
<register_data>
|
||||||
|
<register name="TB" alias="ISAModeSwitch"/>
|
||||||
|
|
||||||
<register name="q0" group="NEON" vector_lane_sizes="1,2,4"/>
|
<register name="q0" group="NEON" vector_lane_sizes="1,2,4"/>
|
||||||
<register name="q1" 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"/>
|
<register name="q2" group="NEON" vector_lane_sizes="1,2,4"/>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
<property key="enableSharedReturnAnalysis" value="false"/>
|
<property key="enableSharedReturnAnalysis" value="false"/>
|
||||||
<property key="enableContiguousFunctionsOnly" value="false"/>
|
<property key="enableContiguousFunctionsOnly" value="false"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
||||||
|
<property key="useropLibs" value="arm"/>
|
||||||
</properties>
|
</properties>
|
||||||
<programcounter register="pc"/>
|
<programcounter register="pc"/>
|
||||||
<context_data>
|
<context_data>
|
||||||
@@ -19,7 +20,11 @@
|
|||||||
<set name="spsr" val="0"/>
|
<set name="spsr" val="0"/>
|
||||||
</tracked_set>
|
</tracked_set>
|
||||||
</context_data>
|
</context_data>
|
||||||
|
|
||||||
|
<register_data>
|
||||||
|
<register name="TB" alias="ISAModeSwitch"/>
|
||||||
|
</register_data>
|
||||||
|
|
||||||
<default_symbols>
|
<default_symbols>
|
||||||
<symbol name="Reset" address="ram:0x0" entry="true"/>
|
<symbol name="Reset" address="ram:0x0" entry="true"/>
|
||||||
<symbol name="UndefinedInstruction" address="ram:0x4" entry="true"/>
|
<symbol name="UndefinedInstruction" address="ram:0x4" entry="true"/>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
<property key="useNewFunctionStackAnalysis" value="true"/>
|
<property key="useNewFunctionStackAnalysis" value="true"/>
|
||||||
<property key="enableContiguousFunctionsOnly" value="false"/>
|
<property key="enableContiguousFunctionsOnly" value="false"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.ARMEmulateInstructionStateModifier"/>
|
<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:BE:32:v7" value="PLATINUM"/>
|
||||||
<property key="assemblyRating:ARM:LE:32:v7" value="PLATINUM"/>
|
<property key="assemblyRating:ARM:LE:32:v7" value="PLATINUM"/>
|
||||||
</properties>
|
</properties>
|
||||||
@@ -20,7 +21,11 @@
|
|||||||
<set name="spsr" val="0"/>
|
<set name="spsr" val="0"/>
|
||||||
</tracked_set>
|
</tracked_set>
|
||||||
</context_data>
|
</context_data>
|
||||||
|
|
||||||
|
<register_data>
|
||||||
|
<register name="TB" alias="ISAModeSwitch"/>
|
||||||
|
</register_data>
|
||||||
|
|
||||||
<default_symbols>
|
<default_symbols>
|
||||||
<symbol name="Reset" address="ram:0x0" entry="true"/>
|
<symbol name="Reset" address="ram:0x0" entry="true"/>
|
||||||
<symbol name="UndefinedInstruction" address="ram:0x4" entry="true"/>
|
<symbol name="UndefinedInstruction" address="ram:0x4" entry="true"/>
|
||||||
|
|||||||
+1
@@ -26,6 +26,7 @@ import ghidra.program.model.lang.Register;
|
|||||||
import ghidra.program.model.lang.RegisterValue;
|
import ghidra.program.model.lang.RegisterValue;
|
||||||
import ghidra.program.model.pcode.Varnode;
|
import ghidra.program.model.pcode.Varnode;
|
||||||
|
|
||||||
|
@Deprecated(forRemoval = true, since = "12.1")
|
||||||
public class ARMEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
public class ARMEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
||||||
|
|
||||||
private Register TModeReg;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+117
@@ -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; }
|
DinsXSize: mysize is msbd & lsb [ mysize = msbd - lsb + 1 + 32; ] { tmp:1 = mysize; export tmp; }
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
define pcodeop setISAMode;
|
||||||
|
|
||||||
macro JXWritePC(addr) {
|
macro JXWritePC(addr) {
|
||||||
@ifdef ISA_VARIANT
|
@ifdef ISA_VARIANT
|
||||||
ISAModeSwitch = (addr & 0x1) != 0;
|
ISAModeSwitch = (addr & 0x1) != 0;
|
||||||
|
setISAMode(ISAModeSwitch);
|
||||||
tmp:$(REGSIZE) = -2;
|
tmp:$(REGSIZE) = -2;
|
||||||
tmp = tmp & addr;
|
tmp = tmp & addr;
|
||||||
pc = tmp;
|
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
|
: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); ] {
|
[ 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 );
|
delayslot( 1 );
|
||||||
ISAModeSwitch = 0;
|
ISAModeSwitch = 0;
|
||||||
|
setISAMode(ISAModeSwitch);
|
||||||
call Abs26_m16;
|
call Abs26_m16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
||||||
|
<property key="useropLibs" value="mips"/>
|
||||||
<property key="assemblyRating:MIPS:BE:32:default" value="PLATINUM"/>
|
<property key="assemblyRating:MIPS:BE:32:default" value="PLATINUM"/>
|
||||||
</properties>
|
</properties>
|
||||||
<programcounter register="pc"/>
|
<programcounter register="pc"/>
|
||||||
|
|||||||
@@ -1018,6 +1018,7 @@ define pcodeop SYNC;
|
|||||||
ra = inst_next;
|
ra = inst_next;
|
||||||
delayslot( 1 );
|
delayslot( 1 );
|
||||||
ISAModeSwitch = 1;
|
ISAModeSwitch = 1;
|
||||||
|
setISAMode(ISAModeSwitch);
|
||||||
call Abs26;
|
call Abs26;
|
||||||
}
|
}
|
||||||
@endif
|
@endif
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
||||||
|
<property key="useropLibs" value="mips"/>
|
||||||
<property key="assemblyRating:MIPS:BE:32:R6" value="PLATINUM"/>
|
<property key="assemblyRating:MIPS:BE:32:R6" value="PLATINUM"/>
|
||||||
</properties>
|
</properties>
|
||||||
<programcounter register="pc"/>
|
<programcounter register="pc"/>
|
||||||
|
|||||||
@@ -154,5 +154,15 @@
|
|||||||
</localrange>
|
</localrange>
|
||||||
</prototype>
|
</prototype>
|
||||||
</default_proto>
|
</default_proto>
|
||||||
|
|
||||||
|
<callotherfixup targetop="setISAMode">
|
||||||
|
<pcode incidentalcopy="true">
|
||||||
|
<input name="newMode"/>
|
||||||
|
<!-- NOP -->
|
||||||
|
<body><![CDATA[
|
||||||
|
v0 = v0;
|
||||||
|
]]></body>
|
||||||
|
</pcode>
|
||||||
|
</callotherfixup>
|
||||||
|
|
||||||
</compiler_spec>
|
</compiler_spec>
|
||||||
|
|||||||
@@ -84,5 +84,15 @@
|
|||||||
</localrange>
|
</localrange>
|
||||||
</prototype>
|
</prototype>
|
||||||
</default_proto>
|
</default_proto>
|
||||||
|
|
||||||
|
<callotherfixup targetop="setISAMode">
|
||||||
|
<pcode incidentalcopy="true">
|
||||||
|
<input name="newMode"/>
|
||||||
|
<!-- NOP -->
|
||||||
|
<body><![CDATA[
|
||||||
|
v0 = v0;
|
||||||
|
]]></body>
|
||||||
|
</pcode>
|
||||||
|
</callotherfixup>
|
||||||
|
|
||||||
</compiler_spec>
|
</compiler_spec>
|
||||||
|
|||||||
@@ -183,6 +183,15 @@
|
|||||||
<register name="gp"/> <!-- Compilers may save gp to the stack before a call and restore it afterward -->
|
<register name="gp"/> <!-- Compilers may save gp to the stack before a call and restore it afterward -->
|
||||||
</internal_storage>
|
</internal_storage>
|
||||||
</prototype>
|
</prototype>
|
||||||
|
|
||||||
|
<callotherfixup targetop="setISAMode">
|
||||||
|
<pcode incidentalcopy="true">
|
||||||
|
<input name="newMode"/>
|
||||||
|
<!-- NOP -->
|
||||||
|
<body><![CDATA[
|
||||||
|
v0 = v0;
|
||||||
|
]]></body>
|
||||||
|
</pcode>
|
||||||
|
</callotherfixup>
|
||||||
|
|
||||||
</compiler_spec>
|
</compiler_spec>
|
||||||
|
|||||||
@@ -174,5 +174,15 @@
|
|||||||
<register name="gp"/> <!-- Compilers may save gp to the stack before a call and restore it afterward -->
|
<register name="gp"/> <!-- Compilers may save gp to the stack before a call and restore it afterward -->
|
||||||
</internal_storage>
|
</internal_storage>
|
||||||
</prototype>
|
</prototype>
|
||||||
|
|
||||||
|
<callotherfixup targetop="setISAMode">
|
||||||
|
<pcode incidentalcopy="true">
|
||||||
|
<input name="newMode"/>
|
||||||
|
<!-- NOP -->
|
||||||
|
<body><![CDATA[
|
||||||
|
v0 = v0;
|
||||||
|
]]></body>
|
||||||
|
</pcode>
|
||||||
|
</callotherfixup>
|
||||||
|
|
||||||
</compiler_spec>
|
</compiler_spec>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
||||||
|
<property key="useropLibs" value="mips"/>
|
||||||
<property key="assemblyRating:MIPS:BE:32:micro" value="PLATINUM"/>
|
<property key="assemblyRating:MIPS:BE:32:micro" value="PLATINUM"/>
|
||||||
</properties>
|
</properties>
|
||||||
<programcounter register="pc"/>
|
<programcounter register="pc"/>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
<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:64-32addr" value="PLATINUM"/>
|
||||||
<property key="assemblyRating:MIPS:BE:64:default" value="PLATINUM"/>
|
<property key="assemblyRating:MIPS:BE:64:default" value="PLATINUM"/>
|
||||||
</properties>
|
</properties>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
||||||
|
<property key="useropLibs" value="mips"/>
|
||||||
<property key="assemblyRating:MIPS:BE:64:R6" value="PLATINUM"/>
|
<property key="assemblyRating:MIPS:BE:64:R6" value="PLATINUM"/>
|
||||||
</properties>
|
</properties>
|
||||||
<programcounter register="pc"/>
|
<programcounter register="pc"/>
|
||||||
|
|||||||
@@ -133,4 +133,15 @@
|
|||||||
</unaffected>
|
</unaffected>
|
||||||
</prototype>
|
</prototype>
|
||||||
</default_proto>
|
</default_proto>
|
||||||
|
|
||||||
|
<callotherfixup targetop="setISAMode">
|
||||||
|
<pcode incidentalcopy="true">
|
||||||
|
<input name="newMode"/>
|
||||||
|
<!-- NOP -->
|
||||||
|
<body><![CDATA[
|
||||||
|
v0 = v0;
|
||||||
|
]]></body>
|
||||||
|
</pcode>
|
||||||
|
</callotherfixup>
|
||||||
|
|
||||||
</compiler_spec>
|
</compiler_spec>
|
||||||
|
|||||||
@@ -125,4 +125,15 @@
|
|||||||
</localrange>
|
</localrange>
|
||||||
</prototype>
|
</prototype>
|
||||||
</default_proto>
|
</default_proto>
|
||||||
|
|
||||||
|
<callotherfixup targetop="setISAMode">
|
||||||
|
<pcode incidentalcopy="true">
|
||||||
|
<input name="newMode"/>
|
||||||
|
<!-- NOP -->
|
||||||
|
<body><![CDATA[
|
||||||
|
v0 = v0;
|
||||||
|
]]></body>
|
||||||
|
</pcode>
|
||||||
|
</callotherfixup>
|
||||||
|
|
||||||
</compiler_spec>
|
</compiler_spec>
|
||||||
|
|||||||
@@ -95,4 +95,15 @@
|
|||||||
</unaffected>
|
</unaffected>
|
||||||
</prototype>
|
</prototype>
|
||||||
</default_proto>
|
</default_proto>
|
||||||
|
|
||||||
|
<callotherfixup targetop="setISAMode">
|
||||||
|
<pcode incidentalcopy="true">
|
||||||
|
<input name="newMode"/>
|
||||||
|
<!-- NOP -->
|
||||||
|
<body><![CDATA[
|
||||||
|
v0 = v0;
|
||||||
|
]]></body>
|
||||||
|
</pcode>
|
||||||
|
</callotherfixup>
|
||||||
|
|
||||||
</compiler_spec>
|
</compiler_spec>
|
||||||
|
|||||||
@@ -186,4 +186,15 @@
|
|||||||
</killedbycall>
|
</killedbycall>
|
||||||
</prototype>
|
</prototype>
|
||||||
</default_proto>
|
</default_proto>
|
||||||
|
|
||||||
|
<callotherfixup targetop="setISAMode">
|
||||||
|
<pcode incidentalcopy="true">
|
||||||
|
<input name="newMode"/>
|
||||||
|
<!-- NOP -->
|
||||||
|
<body><![CDATA[
|
||||||
|
v0 = v0;
|
||||||
|
]]></body>
|
||||||
|
</pcode>
|
||||||
|
</callotherfixup>
|
||||||
|
|
||||||
</compiler_spec>
|
</compiler_spec>
|
||||||
|
|||||||
@@ -170,4 +170,15 @@
|
|||||||
</killedbycall>
|
</killedbycall>
|
||||||
</prototype>
|
</prototype>
|
||||||
</default_proto>
|
</default_proto>
|
||||||
|
|
||||||
|
<callotherfixup targetop="setISAMode">
|
||||||
|
<pcode incidentalcopy="true">
|
||||||
|
<input name="newMode"/>
|
||||||
|
<!-- NOP -->
|
||||||
|
<body><![CDATA[
|
||||||
|
v0 = v0;
|
||||||
|
]]></body>
|
||||||
|
</pcode>
|
||||||
|
</callotherfixup>
|
||||||
|
|
||||||
</compiler_spec>
|
</compiler_spec>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.MIPSEmulateInstructionStateModifier"/>
|
||||||
|
<property key="useropLibs" value="mips"/>
|
||||||
</properties>
|
</properties>
|
||||||
<programcounter register="pc"/>
|
<programcounter register="pc"/>
|
||||||
<context_data>
|
<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);] {
|
: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;
|
ra = inst_next | 0x1;
|
||||||
delayslot( 1 );
|
delayslot( 1 );
|
||||||
ISAModeSwitch = 0;
|
ISAModeSwitch = 0;
|
||||||
|
setISAMode(ISAModeSwitch);
|
||||||
call Abs26_mic2;
|
call Abs26_mic2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -4,9 +4,9 @@
|
|||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* 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.program.model.pcode.PcodeOp;
|
||||||
//import ghidra.pcode.emulate.callother.SignalingNaNOpBehavior;
|
//import ghidra.pcode.emulate.callother.SignalingNaNOpBehavior;
|
||||||
|
|
||||||
|
@Deprecated(forRemoval = true, since = "12.1")
|
||||||
public class MIPSEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
public class MIPSEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
||||||
|
|
||||||
private Register ismReg;
|
private Register ismReg;
|
||||||
|
|||||||
+58
@@ -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>
|
<properties>
|
||||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.PPCEmulateInstructionStateModifier"/>
|
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.PPCEmulateInstructionStateModifier"/>
|
||||||
|
<property key="useropLibs" value="ppc"/>
|
||||||
<property key="assemblyRating:PowerPC:BE:32:default" value="PLATINUM"/>
|
<property key="assemblyRating:PowerPC:BE:32:default" value="PLATINUM"/>
|
||||||
</properties>
|
</properties>
|
||||||
<programcounter register="pc"/>
|
<programcounter register="pc"/>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.PPCEmulateInstructionStateModifier"/>
|
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.PPCEmulateInstructionStateModifier"/>
|
||||||
|
<property key="useropLibs" value="ppc"/>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<programcounter register="pc"/>
|
<programcounter register="pc"/>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
<property key="addressesDoNotAppearDirectlyInCode" value="true"/>
|
||||||
<property key="emulateInstructionStateModifierClass" value="ghidra.program.emulation.PPCEmulateInstructionStateModifier"/>
|
<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:A2-32addr" value="PLATINUM"/>
|
||||||
<property key="assemblyRating:PowerPC:BE:64:A2ALT-32addr" value="PLATINUM"/>
|
<property key="assemblyRating:PowerPC:BE:64:A2ALT-32addr" value="PLATINUM"/>
|
||||||
<property key="assemblyRating:PowerPC:BE:64:default" value="PLATINUM"/>
|
<property key="assemblyRating:PowerPC:BE:64:default" value="PLATINUM"/>
|
||||||
|
|||||||
+1
@@ -24,6 +24,7 @@ import ghidra.pcode.memstate.MemoryState;
|
|||||||
import ghidra.pcodeCPort.error.LowlevelError;
|
import ghidra.pcodeCPort.error.LowlevelError;
|
||||||
import ghidra.program.model.pcode.Varnode;
|
import ghidra.program.model.pcode.Varnode;
|
||||||
|
|
||||||
|
@Deprecated(forRemoval = true, since = "12.1")
|
||||||
public class PPCEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
public class PPCEmulateInstructionStateModifier extends EmulateInstructionStateModifier {
|
||||||
|
|
||||||
public PPCEmulateInstructionStateModifier(Emulate emu) {
|
public PPCEmulateInstructionStateModifier(Emulate emu) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user