mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Merge remote-tracking branch 'origin/patch'
This commit is contained in:
commit
514564292f
12 changed files with 223 additions and 34 deletions
|
@ -133,12 +133,13 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
|
|||
|
||||
// repair the damage for all non-returning functions
|
||||
if (repairDamageEnabled) {
|
||||
AddressSet clearInstSet = new AddressSet();
|
||||
noreturns = noReturnSet.getAddresses(true);
|
||||
for (Address address : noreturns) {
|
||||
clearInstSet.add(findPotentialDamagedLocations(program, address));
|
||||
AddressSet potentialDamagedLocations = findPotentialDamagedLocations(program, address);
|
||||
|
||||
repairDamagedLocations(monitor, potentialDamagedLocations, noReturnSet);
|
||||
}
|
||||
repairDamagedLocations(monitor, clearInstSet);
|
||||
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
@ -154,8 +155,9 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
|
|||
*
|
||||
* @param taskMonitor for cancellation
|
||||
* @param clearInstSet locations to clear and repair
|
||||
* @param protectedLocations - locations that should be protected from clearing
|
||||
*/
|
||||
private void repairDamagedLocations(TaskMonitor taskMonitor, AddressSet clearInstSet) {
|
||||
private void repairDamagedLocations(TaskMonitor taskMonitor, AddressSet clearInstSet, AddressSet protectedLocations) {
|
||||
if (clearInstSet == null || clearInstSet.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -163,6 +165,14 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
|
|||
|
||||
AddressSetView protectedSet = analysisManager.getProtectedLocations();
|
||||
|
||||
protectedSet = protectedSet.union(protectedLocations);
|
||||
|
||||
// TODO: are there other protected locations,
|
||||
// that should never be seeds for locations to be cleared?
|
||||
// For example:
|
||||
// - functions that were marked non-returning by the analyzer.
|
||||
// - locations that are known function start patterns?
|
||||
|
||||
// entries including data flow referenced from instructions will be repaired
|
||||
|
||||
ClearFlowAndRepairCmd cmd =
|
||||
|
@ -243,7 +253,8 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Find locations that need repairing
|
||||
* Find locations that need repairing. The locations returned are only the
|
||||
* start of a flow that occurs after a call to a non-returning function.
|
||||
*
|
||||
* @param cp current program
|
||||
* @param entry non-returning function entry point
|
||||
|
@ -281,6 +292,11 @@ public class FindNoReturnFunctionsAnalyzer extends AbstractAnalyzer {
|
|||
continue;
|
||||
}
|
||||
|
||||
// never add in the entry point that is being marked no return
|
||||
if (fallthruAddr.equals(entry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// if location right below is an entry point, don't clear it
|
||||
Address checkAddr = skipNOPS(fallthruAddr);
|
||||
if (program.getSymbolTable().isExternalEntryPoint(checkAddr) ||
|
||||
|
|
|
@ -457,7 +457,7 @@ public class EnumEditorProvider extends ComponentProviderAdapter
|
|||
}
|
||||
|
||||
private void applyName(Enum newEnuum) {
|
||||
String editorName = editorPanel.getEnumName();
|
||||
String editorName = editorPanel.getEnumName().trim();
|
||||
if (originalEnumName.equals(editorName)) {
|
||||
return; // nothing to do
|
||||
}
|
||||
|
|
|
@ -604,7 +604,11 @@ public class AddEditDialog extends DialogComponentProvider {
|
|||
}
|
||||
|
||||
private String getText() {
|
||||
return labelNameChoices.getText();
|
||||
String text = labelNameChoices.getText();
|
||||
if (text != null) {
|
||||
text = text.trim();
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
public class NamespaceWrapper {
|
||||
|
|
|
@ -66,6 +66,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
|
|||
Category cat = program.getListing()
|
||||
.getDataTypeManager()
|
||||
.getCategory(new CategoryPath(CategoryPath.ROOT, "Category1"));
|
||||
|
||||
Enum enumm = new EnumDataType("Colors", 1);
|
||||
enumm.add("Red", 0);
|
||||
enumm.add("Green", 0x10);
|
||||
|
@ -102,6 +103,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
|
|||
Category cat = program.getListing()
|
||||
.getDataTypeManager()
|
||||
.getCategory(new CategoryPath(CategoryPath.ROOT, "Category1"));
|
||||
|
||||
Enum enumm = new EnumDataType("Colors", 1);
|
||||
enumm.add("Red", 0);
|
||||
enumm.add("Green", 0x10);
|
||||
|
@ -185,6 +187,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
|
|||
Category cat = program.getListing()
|
||||
.getDataTypeManager()
|
||||
.getCategory(new CategoryPath(CategoryPath.ROOT, "Category1"));
|
||||
|
||||
Enum enumm = new EnumDataType("Colors", 1);
|
||||
enumm.add("Red", 0);
|
||||
enumm.add("Green", 0x10);
|
||||
|
@ -230,6 +233,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
|
|||
Category cat = program.getListing()
|
||||
.getDataTypeManager()
|
||||
.getCategory(new CategoryPath(CategoryPath.ROOT, "Category1"));
|
||||
|
||||
Enum enumm = new EnumDataType("Colors", 1);
|
||||
enumm.add("Red", 0);
|
||||
enumm.add("Green", 0x10);
|
||||
|
@ -484,6 +488,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
|
|||
Category cat = program.getListing()
|
||||
.getDataTypeManager()
|
||||
.getCategory(new CategoryPath(CategoryPath.ROOT, "Category1"));
|
||||
|
||||
Enum enumm = new EnumDataType("Colors", 1);
|
||||
enumm.add("Red", 0);
|
||||
enumm.add("Green", 0x10);
|
||||
|
@ -528,6 +533,48 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameTrim() throws Exception {
|
||||
|
||||
Enum enummDt = editSampleEnum();
|
||||
|
||||
EnumEditorPanel panel = findEditorPanel(tool.getToolFrame());
|
||||
String newName = " MyNewName ";
|
||||
runSwing(() -> {
|
||||
JTextField nameField = getTextField(panel, "Name");
|
||||
nameField.setText(newName);
|
||||
});
|
||||
|
||||
DockingActionIf applyAction = getAction(plugin, "Apply Enum Changes");
|
||||
assertTrue(applyAction.isEnabled());
|
||||
|
||||
performAction(applyAction);
|
||||
waitForProgram(program);
|
||||
|
||||
assertEquals(newName.trim(), enummDt.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDescriptionTrim() throws Exception {
|
||||
|
||||
Enum enummDt = editSampleEnum();
|
||||
|
||||
EnumEditorPanel panel = findEditorPanel(tool.getToolFrame());
|
||||
String newDescription = " My new description ";
|
||||
runSwing(() -> {
|
||||
JTextField nameField = getTextField(panel, "Description");
|
||||
nameField.setText(newDescription);
|
||||
});
|
||||
|
||||
DockingActionIf applyAction = getAction(plugin, "Apply Enum Changes");
|
||||
assertTrue(applyAction.isEnabled());
|
||||
|
||||
performAction(applyAction);
|
||||
waitForProgram(program);
|
||||
|
||||
assertEquals(newDescription.trim(), enummDt.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDuplicateValue() throws Exception {
|
||||
|
||||
|
@ -775,8 +822,8 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
|
|||
return null;
|
||||
}
|
||||
|
||||
private void addEntry(JTable table, EnumTableModel model, String name,
|
||||
long value) throws Exception {
|
||||
private void addEntry(JTable table, EnumTableModel model, String name, long value)
|
||||
throws Exception {
|
||||
runSwing(() -> {
|
||||
int lastRow = model.getRowCount() - 1;
|
||||
if (lastRow >= 0) {
|
||||
|
@ -868,6 +915,7 @@ public class EnumEditor2Test extends AbstractGhidraHeadedIntegrationTest {
|
|||
Category cat = program.getListing()
|
||||
.getDataTypeManager()
|
||||
.getCategory(new CategoryPath(CategoryPath.ROOT, "Category1"));
|
||||
|
||||
Enum enumm = new EnumDataType("Colors", 1);
|
||||
enumm.add("Red", 0);
|
||||
enumm.add("Green", 0x10);
|
||||
|
|
|
@ -95,7 +95,7 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
dialog.close();
|
||||
close(dialog);
|
||||
env.dispose();
|
||||
}
|
||||
|
||||
|
@ -362,6 +362,34 @@ public class AddEditDialoglTest extends AbstractGhidraHeadedIntegrationTest {
|
|||
assertTrue(function.getSymbol().isPrimary());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRenameFunction_Trim() throws Exception {
|
||||
|
||||
Symbol s = getUniqueSymbol(program, "entry", null);
|
||||
Function function = program.getFunctionManager().getFunctionAt(s.getAddress());
|
||||
if (function == null) {
|
||||
tool.execute(new CreateFunctionCmd(s.getAddress()), program);
|
||||
program.flushEvents();
|
||||
waitForSwing();
|
||||
function = program.getFunctionManager().getFunctionAt(s.getAddress());
|
||||
s = getUniqueSymbol(program, "entry", null);
|
||||
}
|
||||
// add another label at this address
|
||||
AddLabelCmd cmd = new AddLabelCmd(addr(0x01006420), "fred", SourceType.USER_DEFINED);
|
||||
tool.execute(cmd, program);
|
||||
|
||||
// now attempt to rename the entry label
|
||||
editLabel(s);
|
||||
assertEquals("entry", getText());
|
||||
String newText = " bob ";
|
||||
setText(newText);
|
||||
pressOk();
|
||||
program.flushEvents();
|
||||
waitForSwing();
|
||||
assertEquals("bob", function.getName());
|
||||
assertTrue(function.getSymbol().isPrimary());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetPrimaryOnOtherLabel() throws Exception {
|
||||
Symbol s = getUniqueSymbol(program, "entry", null);
|
||||
|
|
|
@ -15,13 +15,11 @@
|
|||
*/
|
||||
package ghidra.program.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.junit.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.app.plugin.core.analysis.ConstantPropagationAnalyzer;
|
||||
|
@ -34,6 +32,7 @@ import ghidra.program.model.lang.RegisterValue;
|
|||
import ghidra.program.model.listing.*;
|
||||
import ghidra.program.model.pcode.Varnode;
|
||||
import ghidra.program.model.symbol.Reference;
|
||||
import ghidra.program.model.symbol.ReferenceIterator;
|
||||
import ghidra.program.util.SymbolicPropogator.Value;
|
||||
import ghidra.util.exception.NotFoundException;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
@ -308,6 +307,53 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
|||
assertOperandReferenceTo(1, instr, addr("0x00040100"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPIC_Call_X86_64() throws Exception {
|
||||
|
||||
builder = new ProgramBuilder("PICCode", ProgramBuilder._X64, "gcc", this);
|
||||
|
||||
// entry
|
||||
// 48 83 ec 28 SUB RSP,0x28
|
||||
// e8 00 00 00 00 CALL LAB_140020119
|
||||
// LAB_140020119
|
||||
// 8f c3 POP RBX
|
||||
// 48 8d 43 e0 LEA RAX,[RBX + -0x20]
|
||||
// ff d0 CALL RAX
|
||||
// 48 83 c4 28 ADD RSP,0x28
|
||||
// c3 RET
|
||||
|
||||
builder.setBytes("0x140020110",
|
||||
"48 83 ec 28 e8 00 00 00 00 8f c3 48 8d 43 e0 ff d0 48 83 c4 28 c3");
|
||||
|
||||
builder.setBytes("0x1400200f9",
|
||||
"15 02 2f 00 00 89 05 e8 b9 00 00 48 83 c4 38");
|
||||
|
||||
builder.disassemble("0x140020110", 21);
|
||||
|
||||
analyzer = new ConstantPropagationAnalyzer();
|
||||
|
||||
program = builder.getProgram();
|
||||
program.startTransaction("Test");
|
||||
|
||||
Address codeStart = addr("140020110");
|
||||
Listing listing = program.getListing();
|
||||
assertNotNull("Bad instruction disassembly", listing.getInstructionAt(codeStart));
|
||||
|
||||
AddressSet addressSet = new AddressSet(codeStart, codeStart.add(21));
|
||||
analyze(addressSet);
|
||||
|
||||
Instruction instr = listing.getInstructionAt(addr("0x140020114"));
|
||||
assertOperandReferenceTo(0, instr, addr("0x140020119"));
|
||||
instr = listing.getInstructionAt(addr("0x140020119"));
|
||||
ReferenceIterator referenceIteratorTo = instr.getReferenceIteratorTo();
|
||||
Reference ref = referenceIteratorTo.next();
|
||||
assertTrue(ref.getReferenceType().isJump());
|
||||
instr = listing.getInstructionAt(addr("0x14002011f"));
|
||||
Reference[] referencesFrom = instr.getReferencesFrom();
|
||||
assertTrue(referencesFrom[0].getReferenceType().isFlow());
|
||||
assertEquals("1400200f9", referencesFrom[0].getToAddress().toString());
|
||||
}
|
||||
|
||||
private void assertNoOperandReference(int opIndex, Instruction instr) {
|
||||
Reference[] refs = instr.getOperandReferences(opIndex);
|
||||
assertEquals("No reference on operand " + opIndex, 0, refs.length);
|
||||
|
|
|
@ -1023,6 +1023,28 @@ AddrSpace *ActionConstantPtr::selectInferSpace(Varnode *vn,PcodeOp *op,const vec
|
|||
return resSpace;
|
||||
}
|
||||
|
||||
/// \brief Check if we need to try to infer a constant pointer from the input of the given COPY
|
||||
///
|
||||
/// In general, we do want try, but there is a special case where the COPY feeds into a RETURN and
|
||||
/// the function does \e not return a pointer. We also consider the \b infer_pointers boolean.
|
||||
/// \param op is the given COPY op
|
||||
/// \param data is the function
|
||||
/// \return \b true if we should try to infer
|
||||
bool ActionConstantPtr::checkCopy(PcodeOp *op,Funcdata &data)
|
||||
|
||||
{
|
||||
Varnode *vn = op->getOut();
|
||||
PcodeOp *retOp = vn->loneDescend();
|
||||
if (retOp != (PcodeOp *)0 && retOp->code() == CPUI_RETURN && data.getFuncProto().isOutputLocked()) {
|
||||
type_metatype meta = data.getFuncProto().getOutput()->getType()->getMetatype();
|
||||
if (meta != TYPE_PTR && meta != TYPE_UNKNOWN) {
|
||||
return false; // Do NOT infer, we know the constant can't be pointer
|
||||
}
|
||||
return true; // Try to infer, regardless of infer_pointers config, because we KNOW it is a pointer
|
||||
}
|
||||
return data.getArch()->infer_pointers;
|
||||
}
|
||||
|
||||
/// \brief Determine if given Varnode might be a pointer constant.
|
||||
///
|
||||
/// If it is a pointer, return the symbol it points to, or NULL otherwise. If it is determined
|
||||
|
@ -1054,23 +1076,36 @@ SymbolEntry *ActionConstantPtr::isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op
|
|||
// Check if the constant is involved in a potential pointer expression
|
||||
// as the base
|
||||
switch(op->code()) {
|
||||
case CPUI_RETURN:
|
||||
case CPUI_CALL:
|
||||
case CPUI_CALLIND:
|
||||
// A constant parameter or return value could be a pointer
|
||||
if (!glb->infer_pointers)
|
||||
return (SymbolEntry *)0;
|
||||
{
|
||||
if (slot==0)
|
||||
return (SymbolEntry *)0;
|
||||
// A constant parameter could be a pointer
|
||||
FuncCallSpecs *fc = data.getCallSpecs(op);
|
||||
if (fc != (FuncCallSpecs *)0 && fc->isInputLocked() && fc->numParams() > slot-1) {
|
||||
type_metatype meta = fc->getParam(slot-1)->getType()->getMetatype();
|
||||
if (meta != TYPE_PTR && meta != TYPE_UNKNOWN) {
|
||||
return (SymbolEntry *)0; // Definitely not passing a pointer
|
||||
}
|
||||
}
|
||||
else if (!glb->infer_pointers)
|
||||
return (SymbolEntry *)0;
|
||||
break;
|
||||
}
|
||||
case CPUI_COPY:
|
||||
if (!checkCopy(op, data))
|
||||
return (SymbolEntry *)0;
|
||||
break;
|
||||
case CPUI_PIECE:
|
||||
// Pointers get concatenated in structures
|
||||
case CPUI_COPY:
|
||||
case CPUI_INT_EQUAL:
|
||||
case CPUI_INT_NOTEQUAL:
|
||||
case CPUI_INT_LESS:
|
||||
case CPUI_INT_LESSEQUAL:
|
||||
// A comparison with a constant could be a pointer
|
||||
if (!glb->infer_pointers)
|
||||
return (SymbolEntry *)0;
|
||||
break;
|
||||
case CPUI_INT_ADD:
|
||||
outvn = op->getOut();
|
||||
|
|
|
@ -189,6 +189,7 @@ class ActionConstantPtr : public Action {
|
|||
int4 localcount; ///< Number of passes made for this function
|
||||
static AddrSpace *searchForSpaceAttribute(Varnode *vn,PcodeOp *op);
|
||||
static AddrSpace *selectInferSpace(Varnode *vn,PcodeOp *op,const vector<AddrSpace *> &spaceList);
|
||||
static bool checkCopy(PcodeOp *op,Funcdata &data);
|
||||
static SymbolEntry *isPointer(AddrSpace *spc,Varnode *vn,PcodeOp *op,int4 slot,
|
||||
Address &rampoint,uintb &fullEncoding,Funcdata &data);
|
||||
public:
|
||||
|
|
|
@ -75,6 +75,8 @@ public abstract class RenameTask {
|
|||
dialog.setStatusText("Cannot have empty name");
|
||||
return false;
|
||||
}
|
||||
|
||||
name = name.trim();
|
||||
if (name.equals(oldName)) { // No change to name
|
||||
newName = name;
|
||||
return true; // but valid (ends up being equivalent to cancel
|
||||
|
|
|
@ -303,6 +303,17 @@ public class ReferenceDBManager implements ReferenceManager, ManagerDB, ErrorHan
|
|||
* @return combined reference type, or the newType if unable to combine
|
||||
*/
|
||||
private RefType combineReferenceType(RefType newType, RefType oldType) {
|
||||
// check if types are the same, if same no use doing work replacing reference
|
||||
if (newType == oldType) {
|
||||
return oldType;
|
||||
}
|
||||
// any flow reference should be used over the existing ref to the same location
|
||||
if (newType.isFlow()) {
|
||||
return newType; // allow any new flow ref to replace old type
|
||||
}
|
||||
if (oldType.isFlow()) {
|
||||
return oldType; // always keep flow over new data ref
|
||||
}
|
||||
if (newType == RefType.DATA) {
|
||||
if (oldType.isData()) {
|
||||
return oldType;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
##VERSION: 2.0
|
||||
Module.manifest||GHIDRA||||END|
|
||||
data/languages/ARM-32-golang.cspec||GHIDRA||||END|
|
||||
data/languages/ARM-32-golang.register.info||GHIDRA||||END|
|
||||
data/languages/ARM.cspec||GHIDRA||||END|
|
||||
data/languages/ARM.dwarf||GHIDRA||||END|
|
||||
data/languages/ARM.gdis||GHIDRA||||END|
|
||||
|
|
|
@ -495,14 +495,14 @@ vcvt_56_128_dt: ".u32.f32"
|
|||
is ((TMode=0 & ARMcond=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b10 & c1617=0b11 & c0911=0b011 & c0404=0 & c0606=0)
|
||||
| (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b11 & thv_c0911=0b011 & thv_c0404=0 & thv_c0606=0))
|
||||
& vcvt_56_64_dt & Dd & Dm
|
||||
unimpl
|
||||
{ }
|
||||
|
||||
# F6.1.60 p8002 A1 Q == 1 (c0606)
|
||||
:vcvt^vcvt_56_128_dt Qd,Qm
|
||||
is ((TMode=0 & ARMcond=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b10 & c1617=0b11 & c0911=0b011 & c0404=0 & c0606=1)
|
||||
| (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b11 & thv_c0911=0b011 & thv_c0404=0 & thv_c0606=1))
|
||||
& vcvt_56_128_dt & Qd & Qm
|
||||
unimpl
|
||||
{ }
|
||||
|
||||
# F6.1.61 p8005 A1 opc2==100 && size==10 (c1618, c0809)
|
||||
:vcvt^COND^".u32.f32" Sd,Sm
|
||||
|
@ -516,7 +516,7 @@ vcvt_56_128_dt: ".u32.f32"
|
|||
is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b111 & c1011=0b10 & c0607=0b11 & c0404=0 & c1618=0b101 & c0809=0b10)
|
||||
| (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b111 & thv_c1011=0b10 & thv_c0607=0b11 & thv_c0404=0 & thv_c1618=0b101 & thv_c0809=0b10))
|
||||
& COND & Sd & Sm
|
||||
{ build COND; Sd = zext(Sm f> 0) * (trunc(Sm)); }
|
||||
{ build COND; Sd = trunc(Sm); }
|
||||
|
||||
# F6.1.61 p8005 A1 opc2==100 && size==11 (c1618, c0809)
|
||||
:vcvt^COND^".u32.f64" Sd,Dm
|
||||
|
@ -530,7 +530,7 @@ vcvt_56_128_dt: ".u32.f32"
|
|||
is ((TMode=0 & ARMcond=1 & c2327=0b11101 & c1921=0b111 & c1011=0b10 & c0607=0b11 & c0404=0 & c1618=0b101 & c0809=0b11)
|
||||
| (TMode=1 & thv_c2831=0b1110 & thv_c2327=0b11101 & thv_c1921=0b111 & thv_c1011=0b10 & thv_c0607=0b11 & thv_c0404=0 & thv_c1618=0b101 & thv_c0809=0b11))
|
||||
& COND & Sd & Dm
|
||||
{ build COND; local tmp:8 = zext(Dm f> 0:8) * (trunc(Dm)); Sd = tmp:4; }
|
||||
{ build COND; local tmp:8 = trunc(Dm); Sd = tmp:4; }
|
||||
|
||||
# The rounding mode depends on c0707=0 => FPSCR else ZERO
|
||||
|
||||
|
@ -665,14 +665,14 @@ vcvt_59_64_dt: ".u16.f16"
|
|||
is ((TMode=0 & ARMcond=0 & c2831=0b1111 & c2527=0b001 & c2323=1 & c2121=1 & c1011=0b11 & c0707=0 & c0404=1 & c0606=0)
|
||||
| (TMode=1 & thv_c2931=0b111 & thv_c2327=0b11111 & thv_c2121=1 & thv_c1011=0b11 & thv_c0707=0 & thv_c0404=1 & thv_c0606=0))
|
||||
& vcvt_59_32_dt & vcvt_59_fbits & Dd & Dm
|
||||
unimpl
|
||||
{ }
|
||||
|
||||
# F6.1.63 p8012 A1 Q = 1 (c0606)
|
||||
:vcvt^vcvt_59_64_dt Qd,Qm,vcvt_59_fbits
|
||||
is ((TMode=0 & ARMcond=0 & c2831=0b1111 & c2527=0b001 & c2323=1 & c2121=1 & c1011=0b11 & c0707=0 & c0404=1 & c0606=1)
|
||||
| (TMode=1 & thv_c2931=0b111 & thv_c2327=0b11111 & thv_c2121=1 & thv_c1011=0b11 & thv_c0707=0 & thv_c0404=1 & thv_c0606=1))
|
||||
& vcvt_59_64_dt & vcvt_59_fbits & Qd & Qm
|
||||
unimpl
|
||||
{ }
|
||||
|
||||
vcvt_60_fbits_built: fbits is TMode=0 & c0707=0 & c0505 & c0003 [fbits = 16 - ( c0003 * 2 + c0505); ] { export * [const]:1 fbits; }
|
||||
vcvt_60_fbits_built: fbits is TMode=1 & thv_c0707=0 & thv_c0505 & thv_c0003 [fbits = 16 - (thv_c0003 * 2 + thv_c0505); ] { export * [const]:1 fbits; }
|
||||
|
@ -814,14 +814,14 @@ vcvt_amnp_simd_128_dt: ".u32" is TMode=1 & thv_c0707=1 & thv_c0809 & vcvt_amnp_s
|
|||
is ((TMode=0 & ARMcond=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b10 & c1617=0b11 & c1011=0b00 & c0404=0 & c0606=0)
|
||||
| (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b11 & thv_c1011=0b00 & thv_c0404=0 & thv_c0606=0))
|
||||
& vcvt_amnp_simd_RM & vcvt_amnp_simd_64_dt & Dd & Dm
|
||||
unimpl
|
||||
{ }
|
||||
|
||||
# F6.1.65,69,71,73 p8019,8028,8032,8036 A1 128-bit SIMD vector variant Q = 1(c0606)
|
||||
:vcvt^vcvt_amnp_simd_RM^vcvt_amnp_simd_128_dt^".f32" Qd,Qm
|
||||
is ((TMode=0 & ARMcond=0 & c2831=0b1111 & c2327=0b00111 & c2021=0b11 & c1819=0b10 & c1617=0b11 & c1011=0b00 & c0404=0 & c0606=1)
|
||||
| (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11111 & thv_c2021=0b11 & thv_c1819=0b10 & thv_c1617=0b11 & thv_c1011=0b00 & thv_c0404=0 & thv_c0606=1))
|
||||
& vcvt_amnp_simd_RM & vcvt_amnp_simd_128_dt & Qd & Qm
|
||||
unimpl
|
||||
{ }
|
||||
|
||||
vcvt_amnp_fp_RM: "a"
|
||||
is ((TMode=0 & c1617=0b00)
|
||||
|
@ -862,14 +862,14 @@ vcvt_amnp_fp_d_dt: ".s32" is TMode=1 & thv_c0707=1 & thv_c1617 & vcvt_amnp_fp_RM
|
|||
is ((TMode=0 & ARMcond=0 & c2831=0b1111 & c2327=0b11101 & c2021=0b11 & c1819=0b11 & c1011=0b10 & c0606=1 & c0404=0 & c0809=0b10)
|
||||
| (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11101 & thv_c2021=0b11 & thv_c1819=0b11 & thv_c1011=0b10 & thv_c0606=1 & thv_c0404=0 & thv_c0809=0b10))
|
||||
& vcvt_amnp_fp_RM & vcvt_amnp_fp_s_dt & Sd & Sm
|
||||
unimpl
|
||||
{ }
|
||||
|
||||
# F6.1.66,70,72,74 p8021,8030,8034,8038 Double-precision scalar variant size = 11 (c0809)
|
||||
:vcvt^vcvt_amnp_fp_RM^vcvt_amnp_fp_d_dt^".f64" Sd,Dm
|
||||
is ((TMode=0 & ARMcond=0 & c2831=0b1111 & c2327=0b11101 & c2021=0b11 & c1819=0b11 & c1011=0b10 & c0606=1 & c0404=0 & c0809=0b11)
|
||||
| (TMode=1 & thv_c2831=0b1111 & thv_c2327=0b11101 & thv_c2021=0b11 & thv_c1819=0b11 & thv_c1011=0b10 & thv_c0606=1 & thv_c0404=0 & thv_c0809=0b11))
|
||||
& vcvt_amnp_fp_RM & vcvt_amnp_fp_d_dt & Sd & Dm
|
||||
unimpl
|
||||
{ }
|
||||
|
||||
# vcvtb and vcvtt
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue