diff --git a/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestCombinedTestResults.java b/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestCombinedTestResults.java index dd7939d9c0..c6f92bd228 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestCombinedTestResults.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestCombinedTestResults.java @@ -18,6 +18,7 @@ package ghidra.test.processors.support; import java.awt.Color; import java.io.*; import java.util.*; +import java.util.function.Predicate; import org.jdom.Document; import org.jdom.Element; @@ -44,6 +45,8 @@ public class PCodeTestCombinedTestResults { private File xmlFile; private File htmlFile; + private Map> ignoredJunitTestNames = new HashMap<>(); + private Map combinedResults = new HashMap<>(); PCodeTestCombinedTestResults(File reportsDir, boolean readExisting) throws IOException { @@ -57,12 +60,31 @@ public class PCodeTestCombinedTestResults { public PCodeTestResults getTestResults(String jUnitName, boolean create) { PCodeTestResults testResults = combinedResults.get(jUnitName); if (testResults == null && create) { - testResults = new PCodeTestResults(jUnitName); + testResults = new PCodeTestResults(jUnitName, new IgnoreTestPredicate(jUnitName)); combinedResults.put(jUnitName, testResults); } return testResults; } + private class IgnoreTestPredicate implements Predicate { + + private String jUnitName; + + IgnoreTestPredicate(String jUnitName) { + this.jUnitName = jUnitName; + } + + @Override + public boolean test(String testName) { + Set ignoredTestNames = ignoredJunitTestNames.get(jUnitName); + if (ignoredTestNames != null) { + return ignoredTestNames.contains(testName); + } + return false; + } + + } + private void restoreFromXml() throws IOException { FileInputStream istream = new FileInputStream(xmlFile); @@ -80,8 +102,10 @@ public class PCodeTestCombinedTestResults { @SuppressWarnings("unchecked") List elementList = root.getChildren(PCodeTestResults.TAG_NAME); for (Element element : elementList) { - PCodeTestResults testResults = new PCodeTestResults(element); - combinedResults.put(testResults.getJUnitName(), testResults); + String jUnitName = PCodeTestResults.getJunitName(element); + PCodeTestResults testResults = + new PCodeTestResults(element, new IgnoreTestPredicate(jUnitName)); + combinedResults.put(jUnitName, testResults); } } catch (org.jdom.JDOMException je) { @@ -93,6 +117,14 @@ public class PCodeTestCombinedTestResults { } + public void addIgnoredTests(String junitName, String... testNames) { + Set ignoredTestSet = + ignoredJunitTestNames.computeIfAbsent(junitName, n -> new HashSet<>()); + for (String testName : testNames) { + ignoredTestSet.add(testName); + } + } + void saveToXml() throws IOException { File dir = xmlFile.getParentFile(); @@ -226,7 +258,9 @@ public class PCodeTestCombinedTestResults { return; } int count = - computeCharCount(testResults.passCount) + computeCharCount(testResults.failCount) + + computeCharCount(testResults.passCount) + + computeCharCount(testResults.ignoredCount) + + computeCharCount(testResults.failCount) + computeCharCount(testResults.callOtherCount) + 2; charCount = Math.max(count, charCount); } @@ -433,6 +467,8 @@ public class PCodeTestCombinedTestResults { getSummaryHighlightColorClass(testResults) + "\">"); writeResultCount(w, testResults.summaryPassCount, Palette.GREEN); w.print("/"); + writeResultCount(w, testResults.summaryIgnoreCount, Palette.GRAY); + w.print("/"); writeResultCount(w, testResults.summaryFailCount, Palette.RED); w.print("/"); writeResultCount(w, testResults.summaryCallOtherCount, Palette.ORANGE); @@ -485,9 +521,10 @@ public class PCodeTestCombinedTestResults { for (NamedTestColumn namedTestColumn : namedTestColumns) { String testName = namedTestColumn.getTestName(); int pass = testResults.getPassResult(groupName, testName); + int ignored = testResults.getIgnoredResult(groupName, testName); int fail = testResults.getFailResult(groupName, testName); int callother = testResults.getCallOtherResult(groupName, testName); - int total = pass + fail + callother; + int total = pass + ignored + fail + callother; int totalAsserts = testResults.getTotalAsserts(groupName, testName); boolean severeFailure = testResults.hadSevereFailure(groupName, testName); @@ -515,6 +552,8 @@ public class PCodeTestCombinedTestResults { else { writeResultCount(w, pass, Palette.GREEN); w.print("/"); + writeResultCount(w, ignored, Palette.GRAY); + w.print("/"); writeResultCount(w, fail, Palette.RED); w.print("/"); writeResultCount(w, callother, Palette.ORANGE); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestControlBlock.java b/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestControlBlock.java index 9fe81b151b..0cc07d06f3 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestControlBlock.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestControlBlock.java @@ -48,6 +48,10 @@ public class PCodeTestControlBlock extends PCodeTestAbstractControlBlock { private List testGroups; // test group data + // accumulators for tests pass/fail results which have been designated as ignored + private int ignoredPassed = 0; + private int ignoredFailed = 0; + // TestInfo data read from program memory private Address onPassFunctionAddress; private Address onErrorFunctionAddress; @@ -319,6 +323,40 @@ public class PCodeTestControlBlock extends PCodeTestAbstractControlBlock { emuWrite(emuTestRunner.getEmulatorHelper(), addr, SIZEOF_U4, value); } + void resultIgnored(String testGroupName, String testName, boolean passed) { + if (passed) { + ++ignoredPassed; + } + else { + ++ignoredFailed; + } + testResults.addIgnoredResult(testGroupName, testName); + } + + /** + * Get the number of passed tests which should be ignored + * @return number of passed tests which should be ignored + */ + int getNumberPassedIgnored() { + return ignoredPassed; + } + + /** + * Get the number of failed tests which should be ignored + * @return number of failed tests which should be ignored + */ + int getNumberFailedIgnored() { + return ignoredFailed; + } + + /** + * Clear ignored test result accumulators + */ + void clearNumberIgnored() { + ignoredFailed = 0; + ignoredPassed = 0; + } + /** * Get 'numfail' field value from emulation memory state * @param emuTestRunner emulator test runner diff --git a/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestGroup.java b/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestGroup.java index 34fc81b7c8..2411144a23 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestGroup.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestGroup.java @@ -35,6 +35,10 @@ public class PCodeTestGroup implements Comparable { */ public static final String FUNCTION_NAME_PREFIX = "main_"; + public static final String IGNORED_TAG = "IGNORED"; + private static final String IGNORED_FAILED_TAG = "(" + IGNORED_TAG + ")"; + private static final String IGNORED_PASSED_TAG = "(Passed and " + IGNORED_TAG + ")"; + public final String testGroupName; public final Address functionEntryPtr; // public final int testCount; // TODO: not yet fully implemented - do not use! @@ -57,31 +61,41 @@ public class PCodeTestGroup implements Comparable { return testGroupName + "@" + functionEntryPtr; } + boolean isIgnoredTest(String testName) { + return mainTestControlBlock.getTestResults().isIgnoredTest(testName); + } + void testPassed(String testName, String errFileName, int errLineNum, Program program, TestLogger logger) { + if (isIgnoredTest(testName)) { + mainTestControlBlock.resultIgnored(testGroupName, testName, true); + String testDetail = + getTestDetail(testName, errFileName, errLineNum, program, IGNORED_PASSED_TAG); + testFailures.add(testDetail); + logger.log(this, "WARNING! Ignored Test Passed: " + testDetail); + return; + } mainTestControlBlock.getTestResults().addPassResult(testGroupName, testName); } void testFailed(String testName, String errFileName, int errLineNum, boolean callOtherFailure, Program program, TestLogger logger) { - if (callOtherFailure) { + String ignoreTag = ""; + if (isIgnoredTest(testName)) { + mainTestControlBlock.resultIgnored(testGroupName, testName, false); + ignoreTag = IGNORED_FAILED_TAG; + } + else if (callOtherFailure) { mainTestControlBlock.getTestResults().addCallOtherResult(testGroupName, testName); } else { mainTestControlBlock.getTestResults().addFailResult(testGroupName, testName); } - String failure = testName; - if (testName != null) { - Symbol symbol = SymbolUtilities.getLabelOrFunctionSymbol(program, testName, - err -> Msg.error(this, err)); - if (symbol != null) { - failure += " @ " + symbol.getAddress().toString(true); - } - failure += " (" + errFileName + ":" + errLineNum + ")"; - } - testFailures.add(failure); + String testDetail = getTestDetail(testName, errFileName, errLineNum, program, ignoreTag); + testFailures.add(testDetail); logger.log(this, - "Test Failed: " + failure + (callOtherFailure ? " (callother error)" : "")); + "Test Failed: " + testDetail + + (callOtherFailure ? " (callother error)" : "")); } void severeTestFailure(String testName, String errFileName, int errLineNum, Program program, @@ -94,6 +108,20 @@ public class PCodeTestGroup implements Comparable { testFailures.clear(); } + private String getTestDetail(String testName, String errFileName, int errLineNum, + Program program, String ignoreTag) { + String testDetail = testName; + if (testName != null) { + Symbol symbol = SymbolUtilities.getLabelOrFunctionSymbol(program, testName, + err -> Msg.error(this, err)); + if (symbol != null) { + testDetail += " @ " + symbol.getAddress().toString(true); + } + testDetail += " (" + errFileName + ":" + errLineNum + ") " + ignoreTag; + } + return testDetail; + } + /** * @return list of recorded emulation test failures */ diff --git a/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestResults.java b/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestResults.java index feaeb881a1..0da4bcdfb0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestResults.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/PCodeTestResults.java @@ -18,13 +18,15 @@ package ghidra.test.processors.support; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; +import java.util.function.Predicate; import org.jdom.Attribute; import org.jdom.Element; public class PCodeTestResults { - private String jUnitName; + private final String jUnitName; + private final Predicate ignoreTestPredicate; boolean summaryHasIngestErrors; boolean summaryHasRelocationErrors; @@ -32,6 +34,7 @@ public class PCodeTestResults { int summaryTotalAsserts; int summaryPassCount; + int summaryIgnoreCount; int summaryFailCount; int summaryCallOtherCount; int summarySevereFailures; @@ -41,17 +44,91 @@ public class PCodeTestResults { // map keys formed with "." string private Map results = new HashMap<>(); - PCodeTestResults(String jUnitName) { + private static String XML_VERSION = "1"; + + public static String TAG_NAME = "PCodeTestResults"; + + PCodeTestResults(String jUnitName, Predicate ignoreTestPredicate) { this.jUnitName = jUnitName; + this.ignoreTestPredicate = ignoreTestPredicate; time = System.currentTimeMillis(); } + public PCodeTestResults(Element root, Predicate ignoreTestPredicate) { + + if (!TAG_NAME.equals(root.getName())) { + throw new IllegalArgumentException("Unsupported root element: " + root.getName()); + } + String ver = root.getAttributeValue("VERSION"); + if (!XML_VERSION.equals(ver)) { + throw new IllegalArgumentException( + "Unsupported XML format version " + ver + ", required format is " + XML_VERSION); + } + + jUnitName = getJunitName(root); + this.ignoreTestPredicate = ignoreTestPredicate; + + time = 0; + String timeStr = root.getAttributeValue("TIME"); + if (timeStr != null) { + try { + time = Long.parseLong(timeStr); + } + catch (NumberFormatException e) { + // ignore + } + } + + summaryHasIngestErrors = getAttributeValue(root, "INGEST_ERR", false); + summaryHasRelocationErrors = getAttributeValue(root, "RELOC_ERR", false); + summaryHasDisassemblyErrors = getAttributeValue(root, "DIS_ERR", false); + + @SuppressWarnings("unchecked") + List elementList = root.getChildren("TestResults"); + for (Element element : elementList) { + + String testName = element.getAttributeValue("NAME"); + if (testName == null) { + throw new IllegalArgumentException("Invalid TestResults element in XML"); + } + TestResults testResults = new TestResults(); + testResults.totalAsserts = getAttributeValue(element, "TOTAL_ASSERTS", 0); + testResults.passCount = getAttributeValue(element, "PASS", 0); + testResults.ignoredCount = getAttributeValue(element, "IGNORE", 0); + testResults.failCount = getAttributeValue(element, "FAIL", 0); + testResults.callOtherCount = getAttributeValue(element, "CALLOTHER", 0); + testResults.severeFailure = getAttributeValue(element, "SEVERE_FAILURE", false); + + summaryTotalAsserts += testResults.totalAsserts; + summaryPassCount += testResults.passCount; + summaryIgnoreCount += testResults.ignoredCount; + summaryFailCount += testResults.failCount; + summaryCallOtherCount += testResults.callOtherCount; + if (testResults.severeFailure) { + ++summarySevereFailures; + } + + results.put(testName, testResults); + } + } + + static String getJunitName(Element root) { + return root.getAttributeValue("JUNIT"); + } + public String getJUnitName() { return jUnitName; } private static DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm"); + public boolean isIgnoredTest(String testName) { + if (ignoreTestPredicate != null) { + return ignoreTestPredicate.test(testName); + } + return false; + } + public String getTime() { if (time == 0) { return null; @@ -131,6 +208,21 @@ public class PCodeTestResults { return 0; } + void addIgnoredResult(String groupName, String testName) { + String groupTestName = getGroupTestName(groupName, testName); + getTestResults(groupTestName, true).ignoredCount++; + summaryIgnoreCount++; + } + + public int getIgnoredResult(String groupName, String testName) { + String groupTestName = getGroupTestName(groupName, testName); + TestResults testResults = getTestResults(groupTestName, false); + if (testResults != null) { + return testResults.ignoredCount; + } + return 0; + } + void addFailResult(String groupName, String testName) { String groupTestName = getGroupTestName(groupName, testName); getTestResults(groupTestName, true).failCount++; @@ -183,71 +275,13 @@ public class PCodeTestResults { summaryHasDisassemblyErrors = false; summaryTotalAsserts = 0; summaryPassCount = 0; + summaryIgnoreCount = 0; summaryFailCount = 0; summaryCallOtherCount = 0; summarySevereFailures = 0; time = System.currentTimeMillis(); } - private static String XML_VERSION = "1"; - - public static String TAG_NAME = "PCodeTestResults"; - - public PCodeTestResults(Element root) { - - if (!TAG_NAME.equals(root.getName())) { - throw new IllegalArgumentException("Unsupported root element: " + root.getName()); - } - String ver = root.getAttributeValue("VERSION"); - if (!XML_VERSION.equals(ver)) { - throw new IllegalArgumentException( - "Unsupported XML format version " + ver + ", required format is " + XML_VERSION); - } - - jUnitName = root.getAttributeValue("JUNIT"); - - time = 0; - String timeStr = root.getAttributeValue("TIME"); - if (timeStr != null) { - try { - time = Long.parseLong(timeStr); - } - catch (NumberFormatException e) { - // ignore - } - } - - summaryHasIngestErrors = getAttributeValue(root, "INGEST_ERR", false); - summaryHasRelocationErrors = getAttributeValue(root, "RELOC_ERR", false); - summaryHasDisassemblyErrors = getAttributeValue(root, "DIS_ERR", false); - - @SuppressWarnings("unchecked") - List elementList = root.getChildren("TestResults"); - for (Element element : elementList) { - - String testName = element.getAttributeValue("NAME"); - if (testName == null) { - throw new IllegalArgumentException("Invalid TestResults element in XML"); - } - TestResults testResults = new TestResults(); - testResults.totalAsserts = getAttributeValue(element, "TOTAL_ASSERTS", 0); - testResults.passCount = getAttributeValue(element, "PASS", 0); - testResults.failCount = getAttributeValue(element, "FAIL", 0); - testResults.callOtherCount = getAttributeValue(element, "CALLOTHER", 0); - testResults.severeFailure = getAttributeValue(element, "SEVERE_FAILURE", false); - - summaryTotalAsserts += testResults.totalAsserts; - summaryPassCount += testResults.passCount; - summaryFailCount += testResults.failCount; - summaryCallOtherCount += testResults.callOtherCount; - if (testResults.severeFailure) { - ++summarySevereFailures; - } - - results.put(testName, testResults); - } - } - int getAttributeValue(Element element, String attrName, int defaultValue) { String val = element.getAttributeValue(attrName); if (val == null) { @@ -305,6 +339,8 @@ public class PCodeTestResults { element.setAttribute( new Attribute("TOTAL_ASSERTS", Integer.toString(testResults.totalAsserts))); element.setAttribute(new Attribute("PASS", Integer.toString(testResults.passCount))); + element.setAttribute( + new Attribute("IGNORE", Integer.toString(testResults.ignoredCount))); element.setAttribute(new Attribute("FAIL", Integer.toString(testResults.failCount))); element.setAttribute( new Attribute("CALLOTHER", Integer.toString(testResults.callOtherCount))); @@ -319,6 +355,7 @@ public class PCodeTestResults { static class TestResults { int totalAsserts; int passCount; + int ignoredCount; int failCount; int callOtherCount; @@ -326,9 +363,10 @@ public class PCodeTestResults { @Override public String toString() { - // TODO Auto-generated method stub - return "{" + passCount + "/" + failCount + "/" + callOtherCount + "(" + totalAsserts + + return "{" + passCount + "/" + ignoredCount + "/" + failCount + "/" + callOtherCount + + "(" + totalAsserts + ")}"; } } + } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/ProcessorEmulatorTestAdapter.java b/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/ProcessorEmulatorTestAdapter.java index afbe5a3ab6..5b0fd0606a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/ProcessorEmulatorTestAdapter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/test/processors/support/ProcessorEmulatorTestAdapter.java @@ -18,7 +18,8 @@ package ghidra.test.processors.support; import java.io.*; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.math.*; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -1180,6 +1181,7 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E // Initialize pass/fail counts at runtime to detect severe failure testGroup.mainTestControlBlock.setNumberPassed(testRunner, Integer.MIN_VALUE); testGroup.mainTestControlBlock.setNumberFailed(testRunner, Integer.MIN_VALUE); + testGroup.mainTestControlBlock.clearNumberIgnored(); boolean done; if (traceDisabled) { @@ -1190,6 +1192,8 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E } int pass = testGroup.mainTestControlBlock.getNumberPassed(testRunner); + int ignoredPassed = testGroup.mainTestControlBlock.getNumberPassedIgnored(); + int ignoredFailed = testGroup.mainTestControlBlock.getNumberFailedIgnored(); int callOtherErrors = testRunner.getCallOtherErrors(); int fail = testGroup.mainTestControlBlock.getNumberFailed(testRunner); @@ -1199,20 +1203,30 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E pass + " fail " + fail); } + pass -= ignoredPassed; pass -= callOtherErrors; + fail -= ignoredFailed; - String passFailText = "Passed: " + pass + " Failed: " + fail; + String passFailText = "Passed: " + pass + " Ignored: " + + (ignoredFailed + ignoredPassed) + " Failed: " + fail; if (callOtherErrors != 0) { passFailText += " Passed(w/CALLOTHER): " + callOtherErrors; } passFailText += " Expected Assertions: " + totalExpectedAsserts; log(testGroup, passFailText); + boolean hasFailures = false; List testFailures = testGroup.getTestFailures(); if (!testFailures.isEmpty()) { - log(testGroup, "TEST FAILURES:"); + if (!traceDisabled) { + log(testGroup, "TEST FAILURE SUMMARY:"); + } for (String testFailure : testFailures) { - log(testGroup, " >>> " + testFailure); + if (!traceDisabled) { + log(testGroup, " >>> " + testFailure); + } + // failure is any entry not marked as ignored + hasFailures |= (testFailure.indexOf(PCodeTestGroup.IGNORED_TAG) < 0); } } @@ -1235,12 +1249,12 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E } failTest(testRunner, msg.toString()); } - int ranCnt = pass + fail + callOtherErrors; + int ranCnt = pass + fail + callOtherErrors + ignoredFailed + ignoredPassed; if ((totalExpectedAsserts != 0) && (totalExpectedAsserts != ranCnt)) { failTest(testRunner, "ERROR Unexpected number of assertions ( " + passFailText + " )"); } - if (fail != 0 || callOtherErrors != 0 || testFailures.size() != 0) { + if (fail != 0 || callOtherErrors != 0 || hasFailures) { failTest(testRunner, "ERROR One or more group tests failed ( " + passFailText + " )"); } @@ -1424,6 +1438,17 @@ public abstract class ProcessorEmulatorTestAdapter extends TestCase implements E return maxAddr; } + /** + * Add specified test names to the set of tests which should be ignored due to know issues + * or limitations. The tests will still be executed, if present, however they will + * not be included in pass/fail counts. They will appear in log as "(IGNORED)" test + * result. + * @param testNames one or more test names to be ignored + */ + protected void addIgnoredTests(String... testNames) { + combinedResults.addIgnoredTests(getClass().getSimpleName(), testNames); + } + // // Protected helper methods which may be overriden // diff --git a/Ghidra/Features/Base/src/main/resources/pcodetest/chunk1.hinc b/Ghidra/Features/Base/src/main/resources/pcodetest/chunk1.hinc index b7e0616b96..8ebc44b43f 100644 --- a/Ghidra/Features/Base/src/main/resources/pcodetest/chunk1.hinc +++ b/Ghidra/Features/Base/src/main/resources/pcodetest/chunk1.hinc @@ -136,7 +136,8 @@
- + diff --git a/Ghidra/Framework/Emulation/src/main/java/ghidra/app/emulator/EmulatorHelper.java b/Ghidra/Framework/Emulation/src/main/java/ghidra/app/emulator/EmulatorHelper.java index 38b461d17e..6aff080129 100644 --- a/Ghidra/Framework/Emulation/src/main/java/ghidra/app/emulator/EmulatorHelper.java +++ b/Ghidra/Framework/Emulation/src/main/java/ghidra/app/emulator/EmulatorHelper.java @@ -518,6 +518,9 @@ public class EmulatorHelper implements MemoryFaultHandler, EmulatorConfiguration if (t instanceof CancelledException) { throw (CancelledException) t; } + Msg.error(this, + "Emulation failure at " + emulator.getExecuteAddress() + ": " + program.getName(), + t); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/floatformat/BigFloat.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/floatformat/BigFloat.java index 44e67e3306..b8c8b68e28 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/floatformat/BigFloat.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/floatformat/BigFloat.java @@ -60,8 +60,7 @@ public strictfp class BigFloat implements Comparable { * @param scale value's scale (signed value with the biased range of expbits) * @throws IllegalArgumentException if invalid unscaled and scale values are specified based upon the fracbits and expbits values. */ - BigFloat(int fracbits, int expbits, FloatKind kind, int sign, BigInteger unscaled, - int scale) { + BigFloat(int fracbits, int expbits, FloatKind kind, int sign, BigInteger unscaled, int scale) { this.fracbits = fracbits; this.expbits = expbits; this.kind = kind; @@ -151,21 +150,6 @@ public strictfp class BigFloat implements Comparable { return true; } - /** - * Return the BigFloat with the given number of bits representing the given BigInteger. - * - * @param fracbits number of fractional bits - * @param expbits number of bits in the exponent - * @param i an integer - * @return a BigFloat representing i - */ - public static BigFloat valueOf(int fracbits, int expbits, BigInteger i) { - BigFloat f = new BigFloat(fracbits, expbits, FloatKind.FINITE, i.signum() >= 0 ? +1 : -1, - i.abs(), fracbits); - f.scaleUpTo(fracbits + 1); - return f; - } - /** * Return the BigFloat with the given number of bits representing zero. * diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/floatformat/FloatFormat.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/floatformat/FloatFormat.java index 9c3034161b..72418b438d 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/floatformat/FloatFormat.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/pcode/floatformat/FloatFormat.java @@ -897,7 +897,7 @@ public strictfp class FloatFormat { else { a = Utils.convertToUnsignedValue(a, sizein); } - return getEncoding(BigFloat.valueOf(frac_size, exp_size, a)); + return getEncoding(valueOf(a)); } public long opFloat2Float(long a, FloatFormat outformat) { // convert between floating @@ -967,5 +967,28 @@ public strictfp class FloatFormat { fa.round(); return getEncoding(fa); } + + public BigFloat valueOf(BigInteger value) { + + BigInteger unscaled = value; + int sign = 1; + if (unscaled.signum() < 0) { + sign = -1; + unscaled = unscaled.negate(); + } + + int ulen = unscaled.bitLength(); + int shift = frac_size + 1 - ulen; + + unscaled = unscaled.shiftLeft(shift); + + int scale = frac_size - shift; + + if (scale > bias) { + return BigFloat.infinity(frac_size, exp_size, sign); + } + + return new BigFloat(frac_size, exp_size, FloatKind.FINITE, sign, unscaled, scale); + } }
P-Code Test Results
Pass/Fail/CallOther
P-Code Test Results
+ Pass/Ignore/Fail/CallOther
DATE/TIME
SUMMARY