diff --git a/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin2Test.java b/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin2Test.java index 57802da619..62bec52378 100644 --- a/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin2Test.java +++ b/Ghidra/Features/ByteViewer/src/test.slow/java/ghidra/app/plugin/core/byteviewer/ByteViewerPlugin2Test.java @@ -4,9 +4,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,16 +15,19 @@ */ package ghidra.app.plugin.core.byteviewer; +import static java.awt.event.InputEvent.*; import static org.junit.Assert.*; import java.awt.*; -import java.awt.event.*; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; import java.math.BigInteger; import java.util.Date; import java.util.List; import java.util.Map; -import javax.swing.*; +import javax.swing.JCheckBox; +import javax.swing.JLabel; import org.junit.*; @@ -42,7 +45,6 @@ import ghidra.app.services.GoToService; import ghidra.app.services.ProgramManager; import ghidra.app.util.bean.FixedBitSizeValueField; import ghidra.framework.options.Options; -import ghidra.framework.plugintool.Plugin; import ghidra.framework.plugintool.PluginTool; import ghidra.program.database.ProgramBuilder; import ghidra.program.model.address.Address; @@ -56,6 +58,7 @@ import ghidra.program.util.ProgramLocation; import ghidra.test.AbstractGhidraHeadedIntegrationTest; import ghidra.test.TestEnv; import ghidra.util.task.TaskMonitor; +import utility.function.ExceptionalCallback; /** * Test editing in the Byte Viewer. @@ -71,45 +74,28 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { private ByteViewerPanel panel; private CodeBrowserPlugin cbPlugin; - /** - * Constructor for ByteViewerPlugin3Test. - * @param arg0 - */ - public ByteViewerPlugin2Test() { - super(); - } - - /* - * @see TestCase#setUp() - */ @Before public void setUp() throws Exception { env = new TestEnv(); - try { - tool = env.getTool(); - tool.addPlugin(GoToAddressLabelPlugin.class.getName()); - tool.addPlugin(NavigationHistoryPlugin.class.getName()); - tool.addPlugin(NextPrevAddressPlugin.class.getName()); - tool.addPlugin(CodeBrowserPlugin.class.getName()); + tool = env.getTool(); + tool.addPlugin(GoToAddressLabelPlugin.class.getName()); + tool.addPlugin(NavigationHistoryPlugin.class.getName()); + tool.addPlugin(NextPrevAddressPlugin.class.getName()); + tool.addPlugin(CodeBrowserPlugin.class.getName()); - tool.addPlugin(ByteViewerPlugin.class.getName()); + tool.addPlugin(ByteViewerPlugin.class.getName()); - plugin = env.getPlugin(ByteViewerPlugin.class); - tool.showComponentProvider(plugin.getProvider(), true); - cbPlugin = env.getPlugin(CodeBrowserPlugin.class); + plugin = env.getPlugin(ByteViewerPlugin.class); + tool.showComponentProvider(plugin.getProvider(), true); + cbPlugin = env.getPlugin(CodeBrowserPlugin.class); - program = buildNotepad(); - memory = program.getMemory(); - listing = program.getListing(); - ProgramManager pm = tool.getService(ProgramManager.class); - pm.openProgram(program.getDomainFile()); - panel = plugin.getProvider().getByteViewerPanel(); - waitForSwing(); - } - catch (Exception e) { - env.dispose(); - throw e; - } + program = buildNotepad(); + memory = program.getMemory(); + listing = program.getListing(); + ProgramManager pm = tool.getService(ProgramManager.class); + pm.openProgram(program.getDomainFile()); + panel = plugin.getProvider().getByteViewerPanel(); + waitForSwing(); } private Program buildNotepad() throws Exception { @@ -124,12 +110,8 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { return p; } - /* - * @see TestCase#tearDown() - */ @After public void tearDown() throws Exception { - env.release(program); env.dispose(); } @@ -137,34 +119,36 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { public void testEditModeHex() throws Exception { env.showTool(); - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - final FieldLocation loc = getFieldLocation(getAddr(0x01001000)); - SwingUtilities.invokeAndWait(() -> { + FieldLocation loc = getFieldLocation(getAddr(0x01001000)); + runSwing(() -> { ByteViewerComponent c = panel.getCurrentComponent(); c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); action.setSelected(true); action.actionPerformed(new DefaultActionContext()); }); assertTrue(action.isSelected()); - final ByteViewerComponent c = panel.getCurrentComponent(); + ByteViewerComponent c = panel.getCurrentComponent(); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, c.getFocusedCursorColor()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_A, 'a'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), c.getCurrentField()); }); program.flushEvents(); + waitForSwing(); + assertEquals((byte) 0xa0, program.getMemory().getByte(getAddr(0x01001000))); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, ((ByteField) c.getCurrentField()).getForeground()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { action.setSelected(false); action.actionPerformed(new DefaultActionContext()); }); - assertTrue(!action.isSelected()); + assertFalse(action.isSelected()); assertEquals(ByteViewerComponentProvider.CURSOR_ACTIVE_COLOR, c.getFocusedCursorColor()); } @@ -176,30 +160,30 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); Address addr = getAddr(0x01002000); - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - final FieldLocation loc = getFieldLocation(addr); + FieldLocation loc = getFieldLocation(addr); byte b = memory.getByte(addr); assertEquals((byte) 0x50, b); assertEquals(256, loc.getIndex().intValue()); assertEquals(0, loc.getFieldNum()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent c = panel.getCurrentComponent(); c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); action.setSelected(true); action.actionPerformed(new DefaultActionContext()); }); assertTrue(action.isSelected()); - final ByteViewerComponent c = panel.getCurrentComponent(); + ByteViewerComponent c = panel.getCurrentComponent(); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, c.getFocusedCursorColor()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_A, 'a'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), c.getCurrentField()); }); - Thread.sleep(100); + program.flushEvents(); waitForSwing(); assertEquals(b, program.getMemory().getByte(addr)); @@ -221,33 +205,32 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { waitForSwing(); - int transactionID = program.startTransaction("test"); - final Address addr = getAddr(0x01001530); - StructureDataType dt = new StructureDataType("test", 0); - for (int i = 0; i < 7; i++) { - dt.add(new ByteDataType()); - } - listing.createData(addr, dt, dt.getLength()); - program.endTransaction(transactionID, true); + Address addr = getAddr(0x01001530); + txSwing(() -> { + StructureDataType dt = new StructureDataType("test", 0); + for (int i = 0; i < 7; i++) { + dt.add(new ByteDataType()); + } + listing.createData(addr, dt, dt.getLength()); + }); - program.flushEvents(); - waitForSwing(); - - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { action.setSelected(true); action.actionPerformed(new DefaultActionContext()); }); - final ByteViewerComponent c = panel.getCurrentComponent(); + ByteViewerComponent c = panel.getCurrentComponent(); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { FieldLocation loc = getFieldLocation(addr); KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_A, 'a'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), c.getCurrentField()); }); program.flushEvents(); + waitForSwing(); + assertEquals((byte) 0xa0, program.getMemory().getByte(addr)); FieldLocation loc = getFieldLocation(addr); ByteField field = c.getField(loc.getIndex(), loc.getFieldNum()); @@ -263,50 +246,48 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { GoToService goToService = tool.getService(GoToService.class); goToService.goTo(new ProgramLocation(program, getAddr(01001530))); - waitForSwing(); - int transactionID = program.startTransaction("test"); - final Address addr = getAddr(0x01001530); - StructureDataType dt = new StructureDataType("test", 0); - for (int i = 0; i < 7; i++) { - dt.add(new ByteDataType()); - } - listing.createData(addr, dt, dt.getLength()); - program.endTransaction(transactionID, true); + Address addr = getAddr(0x01001530); + txSwing(() -> { + StructureDataType dt = new StructureDataType("test", 0); + for (int i = 0; i < 7; i++) { + dt.add(new ByteDataType()); + } + listing.createData(addr, dt, dt.getLength()); + }); - program.flushEvents(); - waitForSwing(); - - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { action.setSelected(true); action.actionPerformed(new DefaultActionContext()); }); - final ByteViewerComponent c = panel.getCurrentComponent(); + ByteViewerComponent c = panel.getCurrentComponent(); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { FieldLocation loc = getFieldLocation(addr); KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_A, 'a'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), c.getCurrentField()); }); program.flushEvents(); + waitForSwing(); + assertEquals((byte) 0xa0, program.getMemory().getByte(addr)); FieldLocation loc = getFieldLocation(addr); ByteField field = c.getField(loc.getIndex(), loc.getFieldNum()); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, field.getForeground()); - final ByteViewerComponent asciiC = findComponent(panel, "Ascii"); - SwingUtilities.invokeAndWait(() -> panel.setCurrentView(asciiC)); + ByteViewerComponent asciiC = findComponent(panel, "Ascii"); + runSwing(() -> panel.setCurrentView(asciiC)); loc = getFieldLocation(addr); field = asciiC.getField(loc.getIndex(), loc.getFieldNum()); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, field.getForeground()); - final ByteViewerComponent hexIntC = findComponent(panel, "Hex Integer"); - SwingUtilities.invokeAndWait(() -> panel.setCurrentView(hexIntC)); + ByteViewerComponent hexIntC = findComponent(panel, "Hex Integer"); + runSwing(() -> panel.setCurrentView(hexIntC)); loc = getFieldLocation(addr); field = asciiC.getField(loc.getIndex(), loc.getFieldNum()); @@ -316,30 +297,33 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { @Test public void testUndoRedo() throws Exception { env.showTool(); - final Address addr = getAddr(0x01001000); - final ToggleDockingAction action = + Address addr = getAddr(0x01001000); + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { FieldLocation loc = getFieldLocation(addr); ByteViewerComponent c = panel.getCurrentComponent(); c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); action.setSelected(true); action.actionPerformed(new DefaultActionContext()); }); - final ByteViewerComponent c = panel.getCurrentComponent(); + ByteViewerComponent c = panel.getCurrentComponent(); byte value = program.getMemory().getByte(addr); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { FieldLocation loc = getFieldLocation(addr); KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_A, 'a'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), c.getCurrentField()); }); program.flushEvents(); + waitForSwing(); + assertEquals((byte) 0xa0, memory.getByte(addr)); undo(program); program.flushEvents(); + waitForSwing(); assertEquals(value, memory.getByte(addr)); FieldLocation loc = getFieldLocation(addr); @@ -360,19 +344,17 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { @Test public void testUndoRedo2() throws Exception { - // remove code browser plugin so the cursor position does not - // get changed because of location events that the code browser - // generates. - tool.removePlugins(new Plugin[] { cbPlugin }); + + disableCodeBrowserLocationEvents(); env.showTool(); // make 5 changes // verify that the Undo button is enabled and undo can be done 5 times - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { Address addr = getAddr(0x01001000); FieldLocation loc = getFieldLocation(addr); ByteViewerComponent c = panel.getCurrentComponent(); @@ -380,9 +362,9 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { action.setSelected(true); action.actionPerformed(new DefaultActionContext()); }); - final ByteViewerComponent c = panel.getCurrentComponent(); + ByteViewerComponent c = panel.getCurrentComponent(); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { char[] values = { 'a', '1', '2', 'b', '3' }; int[] keyCodes = { KeyEvent.VK_P, KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_B, KeyEvent.VK_3 }; @@ -422,7 +404,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { undo(program); testFieldColor(loc1, null); testFieldColor(loc2, null); - assertTrue(!program.canUndo()); + assertFalse(program.canUndo()); redo(program); testFieldColor(loc1, ByteViewerComponentProvider.CHANGED_VALUE_COLOR); @@ -447,26 +429,18 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertTrue(program.canUndo()); } - private void testFieldColor(FieldLocation loc, Color color) { - ByteViewerComponent c = panel.getCurrentComponent(); - ByteField field = c.getField(loc.getIndex(), loc.getFieldNum()); - Color fieldColor = field.getForeground(); - assertEquals(fieldColor, color); - - } - @Test public void testUndoRedoHexShort() throws Exception { env.showTool(); addViews(); - final Address addr = getAddr(0x01001003); - final ToggleDockingAction action = + Address addr = getAddr(0x01001003); + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); ByteViewerComponent c = findComponent(panel, "Hex Short"); panel.setCurrentView(c); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { FieldLocation loc = getFieldLocation(addr); ByteViewerComponent currentComponent = panel.getCurrentComponent(); currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), loc.getRow(), @@ -475,7 +449,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { action.actionPerformed(new DefaultActionContext()); }); byte value = program.getMemory().getByte(addr); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent currentComponent = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(addr); KeyEvent ev = @@ -509,13 +483,13 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); - final Address addr = getAddr(0x01001003); - final ToggleDockingAction action = + Address addr = getAddr(0x01001003); + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); ByteViewerComponent c = findComponent(panel, "Hex Integer"); panel.setCurrentView(c); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { FieldLocation loc = getFieldLocation(addr); ByteViewerComponent currentComponent = panel.getCurrentComponent(); currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), loc.getRow(), @@ -524,7 +498,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { action.actionPerformed(new DefaultActionContext()); }); byte value = program.getMemory().getByte(addr); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent currentComponent = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(addr); KeyEvent ev = @@ -558,13 +532,13 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); - final Address addr = getAddr(0x01001003); - final ToggleDockingAction action = + Address addr = getAddr(0x01001003); + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); ByteViewerComponent c = findComponent(panel, "Hex Long"); panel.setCurrentView(c); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { FieldLocation loc = getFieldLocation(addr); ByteViewerComponent currentComponent = panel.getCurrentComponent(); currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), loc.getRow(), @@ -573,7 +547,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { action.actionPerformed(new DefaultActionContext()); }); byte value = program.getMemory().getByte(addr); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent currentComponent = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(addr); KeyEvent ev = @@ -607,13 +581,13 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); - final Address addr = getAddr(0x01001003); - final ToggleDockingAction action = + Address addr = getAddr(0x01001003); + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); ByteViewerComponent c = findComponent(panel, "Hex Long Long"); panel.setCurrentView(c); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { FieldLocation loc = getFieldLocation(addr); ByteViewerComponent currentComponent = panel.getCurrentComponent(); currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), loc.getRow(), @@ -622,7 +596,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { action.actionPerformed(new DefaultActionContext()); }); byte value = program.getMemory().getByte(addr); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent currentComponent = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(addr); KeyEvent ev = @@ -653,10 +627,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { @Test public void testUndoRedoHexShort2() throws Exception { - // remove code browser plugin so the cursor position does not - // get changed because of location events that the code browser - // generates. - tool.removePlugins(new Plugin[] { cbPlugin }); + disableCodeBrowserLocationEvents(); env.showTool(); addViews(); @@ -665,10 +636,10 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { panel.setCurrentView(c); // make 3 changes // verify that the Undo button is enabled and undo can be done 5 times - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { Address addr = getAddr(0x01001003); FieldLocation loc = getFieldLocation(addr); ByteViewerComponent currentComponent = panel.getCurrentComponent(); @@ -677,7 +648,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { action.actionPerformed(new DefaultActionContext()); }); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { char[] values = { 'a', '1', '2' }; int[] keyCodes = { KeyEvent.VK_P, KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_B, KeyEvent.VK_3 }; @@ -711,7 +682,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(fg, ByteViewerComponentProvider.CHANGED_VALUE_COLOR); } } - assertTrue(!program.canUndo()); + assertFalse(program.canUndo()); for (int i = 0; i < 3; i++) { @@ -728,10 +699,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { @Test public void testUndoRedoHexInteger2() throws Exception { - // remove code browser plugin so the cursor position does not - // get changed because of location events that the code browser - // generates. - tool.removePlugins(new Plugin[] { cbPlugin }); + disableCodeBrowserLocationEvents(); env.showTool(); addViews(); @@ -740,10 +708,10 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { panel.setCurrentView(c); // make 5 changes // verify that the Undo button is enabled and undo can be done 5 times - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { Address addr = getAddr(0x01001003); FieldLocation loc = getFieldLocation(addr); ByteViewerComponent currentComponent = panel.getCurrentComponent(); @@ -752,7 +720,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { action.actionPerformed(new DefaultActionContext()); }); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { char[] values = { 'a', '1', '2', 'b', '3' }; int[] keyCodes = { KeyEvent.VK_P, KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_B, KeyEvent.VK_3 }; @@ -786,7 +754,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(fg, ByteViewerComponentProvider.CHANGED_VALUE_COLOR); } } - assertTrue(!program.canUndo()); + assertFalse(program.canUndo()); for (int i = 0; i < 5; i++) { @@ -803,10 +771,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { @Test public void testUndoRedoHexLong2() throws Exception { - // remove code browser plugin so the cursor position does not - // get changed because of location events that the code browser - // generates. - tool.removePlugins(new Plugin[] { cbPlugin }); + disableCodeBrowserLocationEvents(); env.showTool(); addViews(); @@ -815,10 +780,10 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { panel.setCurrentView(c); // make 9 changes // verify that the Undo button is enabled and undo can be done 5 times - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { Address addr = getAddr(0x01001003); FieldLocation loc = getFieldLocation(addr); ByteViewerComponent currentComponent = panel.getCurrentComponent(); @@ -827,7 +792,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { action.actionPerformed(new DefaultActionContext()); }); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { char[] values = { 'a', '1', '2', 'b', '3', 'c', '4', 'd', '5' }; int[] keyCodes = { KeyEvent.VK_P, KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_B, KeyEvent.VK_3, @@ -862,7 +827,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(fg, ByteViewerComponentProvider.CHANGED_VALUE_COLOR); } } - assertTrue(!program.canUndo()); + assertFalse(program.canUndo()); for (int i = 0; i < 9; i++) { @@ -879,10 +844,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { @Test public void testUndoRedoHexLongLong2() throws Exception { - // remove code browser plugin so the cursor position does not - // get changed because of location events that the code browser - // generates. - tool.removePlugins(new Plugin[] { cbPlugin }); + disableCodeBrowserLocationEvents(); env.showTool(); addViews(); @@ -891,10 +853,10 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { panel.setCurrentView(c); // make 9 changes // verify that the Undo button is enabled and undo can be done 5 times - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { Address addr = getAddr(0x01001003); FieldLocation loc = getFieldLocation(addr); ByteViewerComponent currentComponent = panel.getCurrentComponent(); @@ -903,13 +865,15 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { action.actionPerformed(new DefaultActionContext()); }); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { char[] values = { 'a', '1', '2', 'b', '3', 'c', '4', 'd', '5', 'e', '6', 'f', '7', 'a', '8', 'b', '9' }; int[] keyCodes = { KeyEvent.VK_P, KeyEvent.VK_1, KeyEvent.VK_2, KeyEvent.VK_B, KeyEvent.VK_3, - KeyEvent.VK_C, KeyEvent.VK_4, KeyEvent.VK_D, KeyEvent.VK_5, KeyEvent.VK_E, KeyEvent.VK_6, - KeyEvent.VK_F, KeyEvent.VK_7, KeyEvent.VK_G, KeyEvent.VK_8, KeyEvent.VK_H, KeyEvent.VK_9 }; + KeyEvent.VK_C, KeyEvent.VK_4, KeyEvent.VK_D, KeyEvent.VK_5, KeyEvent.VK_E, + KeyEvent.VK_6, + KeyEvent.VK_F, KeyEvent.VK_7, KeyEvent.VK_G, KeyEvent.VK_8, KeyEvent.VK_H, + KeyEvent.VK_9 }; ByteViewerComponent currentComponent = panel.getCurrentComponent(); for (int i = 0; i < 17; i++) { @@ -940,7 +904,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(fg, ByteViewerComponentProvider.CHANGED_VALUE_COLOR); } } - assertTrue(!program.canUndo()); + assertFalse(program.canUndo()); for (int i = 0; i < 17; i++) { @@ -958,20 +922,20 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { @Test public void testEditInputHex() throws Exception { env.showTool(); - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - final FieldLocation loc = getFieldLocation(getAddr(0x01001000)); - SwingUtilities.invokeAndWait(() -> { + FieldLocation loc = getFieldLocation(getAddr(0x01001000)); + runSwing(() -> { ByteViewerComponent c = panel.getCurrentComponent(); c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); action.setSelected(true); action.actionPerformed(new DefaultActionContext()); }); assertTrue(action.isSelected()); - final ByteViewerComponent c = panel.getCurrentComponent(); + ByteViewerComponent c = panel.getCurrentComponent(); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, c.getFocusedCursorColor()); byte value = program.getMemory().getByte(getAddr(0x01001000)); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_P, 'p'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), c.getCurrentField()); @@ -985,13 +949,13 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); waitForSwing(); - final ByteViewerComponent c = findComponent(panel, "Ascii"); + ByteViewerComponent c = findComponent(panel, "Ascii"); panel.setCurrentView(c); - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - final FieldLocation loc = getFieldLocation(getAddr(0x01001000)); - SwingUtilities.invokeAndWait(() -> { + FieldLocation loc = getFieldLocation(getAddr(0x01001000)); + runSwing(() -> { ByteViewerComponent currentComponent = panel.getCurrentComponent(); currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); action.setSelected(true); @@ -1001,7 +965,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertTrue(action.isSelected()); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, c.getFocusedCursorColor()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_Z, 'z'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), c.getCurrentField()); @@ -1012,11 +976,11 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { ByteField field = c.getField(loc.getIndex(), loc.getFieldNum()); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, field.getForeground()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { action.setSelected(false); action.actionPerformed(new DefaultActionContext()); }); - assertTrue(!action.isSelected()); + assertFalse(action.isSelected()); assertEquals(ByteViewerComponentProvider.CURSOR_ACTIVE_COLOR, c.getFocusedCursorColor()); } @@ -1026,12 +990,12 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); waitForSwing(); - final ByteViewerComponent c = findComponent(panel, "Octal"); + ByteViewerComponent c = findComponent(panel, "Octal"); panel.setCurrentView(c); - final Address addr = getAddr(0x01001000); - final ToggleDockingAction action = + Address addr = getAddr(0x01001000); + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { FieldLocation loc = getFieldLocation(addr); ByteViewerComponent currentComponent = panel.getCurrentComponent(); currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); @@ -1041,7 +1005,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertTrue(action.isSelected()); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, c.getFocusedCursorColor()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { FieldLocation loc = getFieldLocation(addr); KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), @@ -1054,11 +1018,11 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { ByteField field = c.getField(loc.getIndex(), loc.getFieldNum()); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, field.getForeground()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { action.setSelected(false); action.actionPerformed(new DefaultActionContext()); }); - assertTrue(!action.isSelected()); + assertFalse(action.isSelected()); assertEquals(ByteViewerComponentProvider.CURSOR_ACTIVE_COLOR, c.getFocusedCursorColor()); } @@ -1068,13 +1032,13 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); waitForSwing(); - final ByteViewerComponent c = findComponent(panel, "Octal"); + ByteViewerComponent c = findComponent(panel, "Octal"); panel.setCurrentView(c); - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - final FieldLocation loc = getFieldLocation(getAddr(0x01001000)); - SwingUtilities.invokeAndWait(() -> { + FieldLocation loc = getFieldLocation(getAddr(0x01001000)); + runSwing(() -> { ByteViewerComponent currentComponent = panel.getCurrentComponent(); currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); action.setSelected(true); @@ -1084,7 +1048,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, c.getFocusedCursorColor()); byte value = program.getMemory().getByte(getAddr(0x01001000)); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_9, '9'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), c.getCurrentField()); @@ -1098,13 +1062,13 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); - final ByteViewerComponent c = findComponent(panel, "Hex Short"); + ByteViewerComponent c = findComponent(panel, "Hex Short"); panel.setCurrentView(c); - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - final FieldLocation loc = getFieldLocation(getAddr(0x01001003)); - SwingUtilities.invokeAndWait(() -> { + FieldLocation loc = getFieldLocation(getAddr(0x01001003)); + runSwing(() -> { ByteViewerComponent currentComponent = panel.getCurrentComponent(); currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); action.setSelected(true); @@ -1113,7 +1077,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertTrue(action.isSelected()); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, c.getFocusedCursorColor()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), c.getCurrentField()); @@ -1123,11 +1087,11 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, ((ByteField) c.getCurrentField()).getForeground()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { action.setSelected(false); action.actionPerformed(new DefaultActionContext()); }); - assertTrue(!action.isSelected()); + assertFalse(action.isSelected()); assertEquals(ByteViewerComponentProvider.CURSOR_ACTIVE_COLOR, c.getFocusedCursorColor()); } @@ -1137,13 +1101,13 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); - final ByteViewerComponent c = findComponent(panel, "Hex Integer"); + ByteViewerComponent c = findComponent(panel, "Hex Integer"); panel.setCurrentView(c); - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - final FieldLocation loc = getFieldLocation(getAddr(0x01001003)); - SwingUtilities.invokeAndWait(() -> { + FieldLocation loc = getFieldLocation(getAddr(0x01001003)); + runSwing(() -> { ByteViewerComponent currentComponent = panel.getCurrentComponent(); currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); action.setSelected(true); @@ -1152,7 +1116,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertTrue(action.isSelected()); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, c.getFocusedCursorColor()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), c.getCurrentField()); @@ -1162,11 +1126,11 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, ((ByteField) c.getCurrentField()).getForeground()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { action.setSelected(false); action.actionPerformed(new DefaultActionContext()); }); - assertTrue(!action.isSelected()); + assertFalse(action.isSelected()); assertEquals(ByteViewerComponentProvider.CURSOR_ACTIVE_COLOR, c.getFocusedCursorColor()); } @@ -1176,13 +1140,13 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); - final ByteViewerComponent c = findComponent(panel, "Hex Long"); + ByteViewerComponent c = findComponent(panel, "Hex Long"); panel.setCurrentView(c); - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - final FieldLocation loc = getFieldLocation(getAddr(0x01001003)); - SwingUtilities.invokeAndWait(() -> { + FieldLocation loc = getFieldLocation(getAddr(0x01001003)); + runSwing(() -> { ByteViewerComponent currentComponent = panel.getCurrentComponent(); currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); action.setSelected(true); @@ -1191,7 +1155,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertTrue(action.isSelected()); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, c.getFocusedCursorColor()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), c.getCurrentField()); @@ -1201,11 +1165,11 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, ((ByteField) c.getCurrentField()).getForeground()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { action.setSelected(false); action.actionPerformed(new DefaultActionContext()); }); - assertTrue(!action.isSelected()); + assertFalse(action.isSelected()); assertEquals(ByteViewerComponentProvider.CURSOR_ACTIVE_COLOR, c.getFocusedCursorColor()); } @@ -1215,13 +1179,13 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); - final ByteViewerComponent c = findComponent(panel, "Hex Long Long"); + ByteViewerComponent c = findComponent(panel, "Hex Long Long"); panel.setCurrentView(c); - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - final FieldLocation loc = getFieldLocation(getAddr(0x01001003)); - SwingUtilities.invokeAndWait(() -> { + FieldLocation loc = getFieldLocation(getAddr(0x01001003)); + runSwing(() -> { ByteViewerComponent currentComponent = panel.getCurrentComponent(); currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); action.setSelected(true); @@ -1230,7 +1194,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertTrue(action.isSelected()); assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, c.getFocusedCursorColor()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1'); c.keyPressed(ev, loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol(), c.getCurrentField()); @@ -1240,11 +1204,11 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(ByteViewerComponentProvider.CHANGED_VALUE_COLOR, ((ByteField) c.getCurrentField()).getForeground()); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { action.setSelected(false); action.actionPerformed(new DefaultActionContext()); }); - assertTrue(!action.isSelected()); + assertFalse(action.isSelected()); assertEquals(ByteViewerComponentProvider.CURSOR_ACTIVE_COLOR, c.getFocusedCursorColor()); } @@ -1254,23 +1218,22 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); // put the byte viewer in edit mode - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { action.setSelected(true); action.actionPerformed(new DefaultActionContext()); }); - // add a memory block - Address addr = getAddr(0x100); - int transactionID = program.startTransaction("test"); - memory.createInitializedBlock(".test", addr, 10, (byte) 0, null, false); - program.endTransaction(transactionID, true); - program.flushEvents(); + // add a memory block + txSwing(() -> { + Address addr = getAddr(0x100); + memory.createInitializedBlock(".test", addr, 10, (byte) 0, null, false); + }); // edit the first 3 bytes in the block - final ByteViewerComponent c = panel.getCurrentComponent(); - SwingUtilities.invokeAndWait(() -> { + ByteViewerComponent c = panel.getCurrentComponent(); + runSwing(() -> { Address testAddress = getAddr(0x100); FieldLocation loc = getFieldLocation(testAddress); KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1'); @@ -1290,7 +1253,9 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { c.getCurrentField()); }); program.flushEvents(); + waitForSwing(); + Address addr = getAddr(0x100); for (int i = 0; i < 3; i++) { // verify that the bytes are rendered in red FieldLocation loc = getFieldLocation(addr); @@ -1307,23 +1272,22 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); // put the byte viewer in edit mode - final ToggleDockingAction action = + ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { action.setSelected(true); action.actionPerformed(new DefaultActionContext()); }); // first add a memory block - Address addr = getAddr(0x100); - int transactionID = program.startTransaction("test"); - memory.createInitializedBlock(".test", addr, 10, (byte) 0, null, false); - program.endTransaction(transactionID, true); - program.flushEvents(); + txSwing(() -> { + Address addr = getAddr(0x100); + memory.createInitializedBlock(".test", addr, 10, (byte) 0, null, false); + }); // edit the first 3 bytes in the block - final ByteViewerComponent c = panel.getCurrentComponent(); - SwingUtilities.invokeAndWait(() -> { + ByteViewerComponent c = panel.getCurrentComponent(); + runSwing(() -> { Address testAddress = getAddr(0x100); FieldLocation loc = getFieldLocation(testAddress); KeyEvent ev = new KeyEvent(c, 0, new Date().getTime(), 0, KeyEvent.VK_1, '1'); @@ -1345,14 +1309,15 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { program.flushEvents(); // move the block - MemoryBlock block = memory.getBlock(addr); - Address newStart = getAddr(0x500); - transactionID = program.startTransaction("Test"); - memory.moveBlock(block, newStart, TaskMonitor.DUMMY); - program.endTransaction(transactionID, true); - program.flushEvents(); + txSwing(() -> { + Address addr = getAddr(0x100); + MemoryBlock block = memory.getBlock(addr); + Address newStart = getAddr(0x500); + memory.moveBlock(block, newStart, TaskMonitor.DUMMY); + }); - FieldLocation loc = getFieldLocation(newStart); + Address addr = getAddr(0x500); + FieldLocation loc = getFieldLocation(addr); ByteField field = c.getField(loc.getIndex(), loc.getFieldNum()); assertNotNull(field); @@ -1368,10 +1333,9 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { MemoryBlock block = memory.getBlock(addr); Address newaddr = getAddr(0x01002009); - int transactionID = program.startTransaction("Test"); - memory.split(block, newaddr); - program.endTransaction(transactionID, true); - program.flushEvents(); + txSwing(() -> { + memory.split(block, newaddr); + }); ByteViewerComponent c = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(newaddr); @@ -1384,7 +1348,8 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { @Test public void testMemoryBlockExpandUp() throws Exception { // expand up: create a block, then join to its successor - SwingUtilities.invokeAndWait(() -> tool.removePlugins(new Plugin[] { cbPlugin })); + + disableCodeBrowserLocationEvents(); env.showTool(); Address addr = getAddr(0x01001000); @@ -1394,30 +1359,29 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { Address newaddr = getAddr(0x01000500); - int transactionID = program.startTransaction("Test"); - MemoryBlock newblock = - memory.createInitializedBlock(".test", newaddr, 0xb00, (byte) 0, null, false); - memory.join(newblock, block); - program.endTransaction(transactionID, true); - program.flushEvents(); + txSwing(() -> { + MemoryBlock newblock = + memory.createInitializedBlock(".test", newaddr, 0xb00, (byte) 0, null, false); + memory.join(newblock, block); + }); ByteViewerComponent c = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(newaddr); ByteField field = c.getField(loc.getIndex(), loc.getFieldNum()); assertNotNull(field); - loc = c.getCursorLocation(); + // cursor should remain where it was before the block expansion + loc = c.getCursorLocation(); assertEquals(getFieldLocation(addr), loc); // there should be no separator above the current location field = c.getField(loc.getIndex().subtract(BigInteger.ONE), 0); - assertTrue(!field.getText().equals("..")); - + assertFalse(field.getText().equals("..")); } @Test public void testMemoryBlockExpandDown() throws Exception { - SwingUtilities.invokeAndWait(() -> tool.removePlugins(new Plugin[] { cbPlugin })); + disableCodeBrowserLocationEvents(); // expand block down: create a block, then join to its predecessor env.showTool(); @@ -1428,12 +1392,11 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { Address newaddr = getAddr(0x01003000L); - int transactionID = program.startTransaction("Test"); - MemoryBlock newblock = - memory.createInitializedBlock(".test", newaddr, 0x100, (byte) 0, null, false); - memory.join(block, newblock); - program.endTransaction(transactionID, true); - program.flushEvents(); + txSwing(() -> { + MemoryBlock newblock = + memory.createInitializedBlock(".test", newaddr, 0x100, (byte) 0, null, false); + memory.join(block, newblock); + }); ByteViewerComponent c = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(newaddr); @@ -1447,7 +1410,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { @Test public void testMemoryBlockDeletedInView() throws Exception { // delete a memory block that is showing in the view - SwingUtilities.invokeAndWait(() -> tool.removePlugins(new Plugin[] { cbPlugin })); + disableCodeBrowserLocationEvents(); env.showTool(); Address addr = getAddr(0x0f001000); MemoryBlock block = memory.getBlock(addr); @@ -1459,10 +1422,9 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { FieldLocation loc = c.getCursorLocation(); assertEquals(getFieldLocation(addr), loc); - int transactionID = program.startTransaction("Test"); - memory.removeBlock(block, TaskMonitor.DUMMY); - program.endTransaction(transactionID, true); - program.flushEvents(); + txSwing(() -> { + memory.removeBlock(block, TaskMonitor.DUMMY); + }); addr = getAddr(0x0f002000); loc = getFieldLocation(addr); @@ -1474,10 +1436,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { public void testMemoryBlockDeletedNotInView() throws Exception { // delete a memory block that is not showing in the view - // remove code browser plugin so the cursor position does not - // get changed because of location events that the code browser - // generates. - SwingUtilities.invokeAndWait(() -> tool.removePlugins(new Plugin[] { cbPlugin })); + disableCodeBrowserLocationEvents(); env.showTool(); Address addr = getAddr(0x0f001000); @@ -1490,10 +1449,9 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(getFieldLocation(addr), loc); MemoryBlock block = memory.getBlock(getAddr(0x01001000)); - int transactionID = program.startTransaction("Test"); - memory.removeBlock(block, TaskMonitor.DUMMY); - program.endTransaction(transactionID, true); - program.flushEvents(); + txSwing(() -> { + memory.removeBlock(block, TaskMonitor.DUMMY); + }); loc = getFieldLocation(addr); // cursor position should not be affected @@ -1511,27 +1469,29 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); ByteViewerOptionsDialog d = launchByteViewerOptions(); - final FixedBitSizeValueField field = + FixedBitSizeValueField field = (FixedBitSizeValueField) getInstanceField("bytesPerLineField", d); - SwingUtilities.invokeAndWait(() -> field.setValue(BigInteger.valueOf(10))); + runSwing(() -> field.setValue(BigInteger.valueOf(10))); pressButtonByText(d.getComponent(), "OK"); + // add the block - int transactionID = program.startTransaction("Test"); - Address addr = getAddr(0x30); - memory.createInitializedBlock(".test", addr, 0x12, (byte) 0, null, false); + txSwing(() -> { + Address addr = getAddr(0x30); + memory.createInitializedBlock(".test", addr, 0x12, (byte) 0, null, false); - // add the second block at 0x48 - addr = getAddr(0x48); - memory.createInitializedBlock(".test2", addr, 0x100, (byte) 0, null, false); - program.endTransaction(transactionID, true); - program.flushEvents(); + // add the second block at 0x48 + Address addr2 = getAddr(0x48); + memory.createInitializedBlock(".test2", addr2, 0x100, (byte) 0, null, false); + }); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent c = panel.getCurrentComponent(); Address a = getAddr(0x48); FieldLocation loc = getFieldLocation(a); c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol()); }); + + Address addr = getAddr(0x48); FieldLocation loc = getFieldLocation(addr); ByteViewerComponent c = panel.getCurrentComponent(); // cursor position should not be affected @@ -1543,55 +1503,40 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { public void testMemoryChange() throws Exception { env.showTool(); - SwingUtilities.invokeAndWait(() -> tool.showComponentProvider(plugin.getProvider(), false)); - final ProgramManager pm = tool.getService(ProgramManager.class); - SwingUtilities.invokeLater(() -> pm.closeProgram()); + runSwing(() -> tool.showComponentProvider(plugin.getProvider(), false)); + ProgramManager pm = tool.getService(ProgramManager.class); + runSwing(() -> pm.closeProgram(), false); waitForSwing(); pm.openProgram(program.getDomainFile()); // add a memory block - int transactionID = program.startTransaction("test"); - MemoryBlock block = null; - try { - block = memory.createInitializedBlock(".test", getAddr(0), 500, (byte) 0, - TaskMonitor.DUMMY, false); - } - finally { - program.endTransaction(transactionID, true); - } + txSwing(() -> { + memory.createInitializedBlock(".test", getAddr(0), 500, (byte) 0, TaskMonitor.DUMMY, + false); + }); - program.flushEvents(); - waitForSwing(); - - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { GoToService goToService = tool.getService(GoToService.class); goToService.goTo(new ProgramLocation(program, getAddr(0))); }); - SwingUtilities.invokeAndWait(() -> tool.showComponentProvider(plugin.getProvider(), true)); + runSwing(() -> tool.showComponentProvider(plugin.getProvider(), true)); waitForSwing(); - Thread.sleep(500); ByteViewerComponent c = panel.getCurrentComponent(); assertEquals(getFieldLocation(getAddr(0)), c.getCursorLocation()); - SwingUtilities.invokeAndWait(() -> tool.showComponentProvider(plugin.getProvider(), false)); + runSwing(() -> tool.showComponentProvider(plugin.getProvider(), false)); waitForSwing(); // now remove the block - transactionID = program.startTransaction("test"); - try { + txSwing(() -> { + MemoryBlock block = memory.getBlock(getAddr(0)); memory.removeBlock(block, TaskMonitor.DUMMY); - } - finally { - program.endTransaction(transactionID, true); - } - program.flushEvents(); - waitForSwing(); + }); - SwingUtilities.invokeAndWait(() -> tool.showComponentProvider(plugin.getProvider(), true)); + runSwing(() -> tool.showComponentProvider(plugin.getProvider(), true)); waitForSwing(); - Thread.sleep(500); c = panel.getCurrentComponent(); Address addr = cbPlugin.getCurrentAddress(); @@ -1607,35 +1552,35 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { pressButtonByText(dialog.getComponent(), "OK"); ByteViewerOptionsDialog d = launchByteViewerOptions(); - final FixedBitSizeValueField field = + FixedBitSizeValueField field = (FixedBitSizeValueField) getInstanceField("bytesPerLineField", d); - SwingUtilities.invokeAndWait(() -> field.setValue(BigInteger.valueOf(10))); + runSwing(() -> field.setValue(BigInteger.valueOf(10))); pressButtonByText(d.getComponent(), "OK"); - // add the block - int transactionID = program.startTransaction("Test"); - Address addr = getAddr(0x30); - memory.createInitializedBlock(".test", addr, 0x12, (byte) 0, null, false); - // add the second block at 0x48 - addr = getAddr(0x48); - memory.createInitializedBlock(".test2", addr, 0x100, (byte) 0, null, false); - program.endTransaction(transactionID, true); - program.flushEvents(); + // add the block + txSwing(() -> { + Address addr = getAddr(0x30); + memory.createInitializedBlock(".test", addr, 0x12, (byte) 0, null, false); - SwingUtilities.invokeAndWait(() -> { + // add the second block at 0x48 + Address addr2 = getAddr(0x48); + memory.createInitializedBlock(".test2", addr2, 0x100, (byte) 0, null, false); + }); + + runSwing(() -> { ByteViewerComponent c = panel.getCurrentComponent(); Address a = getAddr(0x30); FieldLocation loc = getFieldLocation(a); c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), loc.getRow(), loc.getCol()); }); - final FieldSelection fsel = new FieldSelection(); + FieldSelection fsel = new FieldSelection(); ByteViewerComponent c = panel.getCurrentComponent(); FieldLocation loc1 = c.getCursorLocation(); FieldLocation loc2 = getFieldLocation(getAddr(0x000000cb)); fsel.addRange(new FieldLocation(loc1.getIndex(), loc1.getFieldNum(), 0, 0), new FieldLocation(loc2.getIndex(), loc2.getFieldNum(), 0, 0)); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent currentComponent = panel.getCurrentComponent(); currentComponent.selectionChanged(fsel, EventTrigger.GUI_ACTION); }); @@ -1654,18 +1599,18 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); - SwingUtilities.invokeLater(() -> { + runSwing(() -> { ByteViewerComponent c = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(getAddr(0x01001000)); c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); - }); + }, false); ByteViewerOptionsDialog d = launchByteViewerOptions(); - final FixedBitSizeValueField field = + FixedBitSizeValueField field = (FixedBitSizeValueField) getInstanceField("bytesPerLineField", d); - SwingUtilities.invokeAndWait(() -> field.setValue(BigInteger.valueOf(10))); + runSwing(() -> field.setValue(BigInteger.valueOf(10))); pressButtonByText(d.getComponent(), "OK"); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); action.setSelected(true); @@ -1673,17 +1618,16 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { }); // add the block - int transactionID = program.startTransaction("Test"); - Address addr = getAddr(0x30); - memory.createInitializedBlock(".test", addr, 0x12, (byte) 0, null, false); + txSwing(() -> { + Address addr = getAddr(0x30); + memory.createInitializedBlock(".test", addr, 0x12, (byte) 0, null, false); - // add the second block at 0x48 - addr = getAddr(0x48); - memory.createInitializedBlock(".test2", addr, 0x100, (byte) 0, null, false); - program.endTransaction(transactionID, true); - program.flushEvents(); + // add the second block at 0x48 + Address addr2 = getAddr(0x48); + memory.createInitializedBlock(".test2", addr2, 0x100, (byte) 0, null, false); + }); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent c = panel.getCurrentComponent(); Address a = getAddr(0x41); FieldLocation loc = getFieldLocation(a); @@ -1694,6 +1638,8 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { c.getCurrentField()); }); program.flushEvents(); + waitForSwing(); + assertEquals((byte) 0x30, memory.getByte(getAddr(0x41))); } @@ -1701,7 +1647,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { public void testEditOptionCurrentViewColor() throws Exception { env.showTool(); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent c = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(getAddr(0x01001000)); c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); @@ -1721,7 +1667,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent c = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(getAddr(0x01001000)); c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); @@ -1741,7 +1687,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent c = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(getAddr(0x01001000)); c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); @@ -1756,21 +1702,13 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertColorsEqual(Palette.CYAN, c.getNonFocusCursorColor()); } - private void putFont(final Options options, final String optionName, final Font font) { - runSwing(() -> options.setFont(optionName, font)); - } - - private void putColor(final Options options, final String optionName, final Color color) { - runSwing(() -> options.setColor(optionName, color)); - } - @Test public void testEditOptionEditColor() throws Exception { // color for changed bytes env.showTool(); addViews(); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent c = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(getAddr(0x01001000)); c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); @@ -1780,8 +1718,8 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { // change the color for Edit Color putColor(opt, ByteViewerComponentProvider.CHANGED_VALUE_COLOR_OPTION_NAME, Palette.GREEN); - final FieldLocation loc = getFieldLocation(getAddr(0x01001000)); - SwingUtilities.invokeAndWait(() -> { + FieldLocation loc = getFieldLocation(getAddr(0x01001000)); + runSwing(() -> { ToggleDockingAction action = (ToggleDockingAction) getAction(plugin, "Enable/Disable Byteviewer Editing"); action.setSelected(true); @@ -1796,6 +1734,8 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { c.getCurrentField()); }); program.flushEvents(); + waitForSwing(); + ByteViewerComponent c = panel.getCurrentComponent(); ByteField field = c.getField(loc.getIndex(), loc.getFieldNum()); assertColorsEqual(Palette.GREEN, field.getForeground()); @@ -1806,7 +1746,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent c = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(getAddr(0x01001000)); c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); @@ -1828,7 +1768,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { env.showTool(); addViews(); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { ByteViewerComponent c = panel.getCurrentComponent(); FieldLocation loc = getFieldLocation(getAddr(0x01001000)); c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); @@ -1847,7 +1787,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { @Test public void testGoToUpdatesByteViewer() throws Exception { env.showTool(); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { GoToService goToService = tool.getService(GoToService.class); goToService.goTo(new ProgramLocation(program, getAddr(0x01001050))); }); @@ -1884,7 +1824,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { Assert.assertNotEquals("Snapshot triggered navigation unexpectedly", address, cbLocation.getAddress()); - modifiers = DockingUtils.CONTROL_KEY_MODIFIER_MASK | InputEvent.SHIFT_MASK; + modifiers = DockingUtils.CONTROL_KEY_MODIFIER_MASK | SHIFT_DOWN_MASK; clickLocation(snapshot, modifiers); cbLocation = cbPlugin.getCurrentLocation(); @@ -1918,11 +1858,96 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { assertEquals(null, currentHighlightText); } + @Test + public void testSaveRestoreState() throws Exception { + env.showTool(); + addViews(); + ByteViewerComponent c = panel.getCurrentComponent(); + + FieldLocation loc = getFieldLocation(getAddr(0x0100100b)); + runSwing(() -> { + ByteViewerComponent currentComponent = panel.getCurrentComponent(); + currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); + }); + + ByteViewerOptionsDialog dialog = launchByteViewerOptions(); + FixedBitSizeValueField field = + (FixedBitSizeValueField) getInstanceField("groupSizeField", dialog); + runSwing(() -> field.setValue(BigInteger.valueOf(4))); + pressButtonByText(dialog.getComponent(), "OK"); + + // change the font + Options opt = tool.getOptions("ByteViewer"); + Font font = new Font("Times New Roman", Font.BOLD, 12); + + runSwing(() -> { + + opt.setFont(ByteViewerComponentProvider.OPTION_FONT, font); + GoToService goToService = tool.getService(GoToService.class); + goToService.goTo(new ProgramLocation(program, getAddr(0x01002500))); + }); + assertEquals(4, plugin.getProvider().getGroupSize()); + + ViewerPosition vp = panel.getViewerPosition(); + runSwing(() -> env.saveRestoreToolState()); + + waitForSwing(); + c = panel.getCurrentComponent(); + assertEquals(4, plugin.getProvider().getGroupSize()); + + assertEquals(getFieldLocation(getAddr(0x01002500)), c.getCursorLocation()); + assertEquals(font, panel.getFontMetrics().getFont()); + waitForSwing(); + + assertEquals(vp, panel.getViewerPosition()); + } + + // Remove code browser plugin so the cursor position does not get changed because of location + // events that the code browser generates. + private void disableCodeBrowserLocationEvents() throws Exception { + runSwing(() -> tool.removePlugins(List.of(cbPlugin))); + } + + private void testFieldColor(FieldLocation loc, Color color) { + ByteViewerComponent c = panel.getCurrentComponent(); + ByteField field = c.getField(loc.getIndex(), loc.getFieldNum()); + Color fieldColor = field.getForeground(); + assertEquals(fieldColor, color); + } + + // perform the given callback in a transaction on the Swing thread + private void txSwing(ExceptionalCallback c) { + + int txId = program.startTransaction("Test - Function in Transaction"); + boolean commit = true; + try { + runSwingWithException(c); + program.flushEvents(); + } + catch (Exception e) { + commit = false; + failWithException("Exception modifying program '" + program.getName() + "'", e); + } + finally { + program.endTransaction(txId, commit); + } + + waitForSwing(); + } + + private void putFont(Options options, String optionName, Font font) { + runSwing(() -> options.setFont(optionName, font)); + } + + private void putColor(Options options, String optionName, Color color) { + runSwing(() -> options.setColor(optionName, color)); + } + private void clickMiddleMouseLocation(ProgramByteViewerComponentProvider testProvider, int mouseModifiers) { ByteViewerPanel byteViewerPanel = testProvider.getByteViewerPanel(); - final ByteViewerComponent component = byteViewerPanel.getCurrentComponent(); + ByteViewerComponent component = byteViewerPanel.getCurrentComponent(); Rectangle cursorBounds = component.getCursorBounds(); @@ -1935,7 +1960,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { int mouseModifiers) { ByteViewerPanel byteViewerPanel = testProvider.getByteViewerPanel(); - final ByteViewerComponent component = byteViewerPanel.getCurrentComponent(); + ByteViewerComponent component = byteViewerPanel.getCurrentComponent(); Rectangle cursorBounds = component.getCursorBounds(); @@ -1947,10 +1972,10 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { private void setByteViewerLocation(ProgramByteViewerComponentProvider testProvider, Address address) throws Exception { ByteViewerPanel byteViewerPanel = testProvider.getByteViewerPanel(); - final ByteViewerComponent component = byteViewerPanel.getCurrentComponent(); - final FieldLocation byteViewerLocation = getFieldLocation(address); + ByteViewerComponent component = byteViewerPanel.getCurrentComponent(); + FieldLocation byteViewerLocation = getFieldLocation(address); - SwingUtilities.invokeAndWait(() -> { + runSwing(() -> { component.setCursorPosition(byteViewerLocation.getIndex(), byteViewerLocation.getFieldNum(), byteViewerLocation.getRow(), byteViewerLocation.getCol()); @@ -1967,73 +1992,16 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { return providers.get(0); } - @Test - public void testSaveRestoreState() throws Exception { - env.showTool(); - addViews(); - ByteViewerComponent c = panel.getCurrentComponent(); - - final FieldLocation loc = getFieldLocation(getAddr(0x0100100b)); - SwingUtilities.invokeAndWait(() -> { - ByteViewerComponent currentComponent = panel.getCurrentComponent(); - currentComponent.setCursorPosition(loc.getIndex(), loc.getFieldNum(), 0, 0); - }); - - ByteViewerOptionsDialog dialog = launchByteViewerOptions(); - final FixedBitSizeValueField field = - (FixedBitSizeValueField) getInstanceField("groupSizeField", dialog); - SwingUtilities.invokeAndWait(() -> field.setValue(BigInteger.valueOf(4))); - pressButtonByText(dialog.getComponent(), "OK"); - - // change the font - final Options opt = tool.getOptions("ByteViewer"); - final Font font = new Font("Times New Roman", Font.BOLD, 12); - - SwingUtilities.invokeAndWait(() -> { - - opt.setFont(ByteViewerComponentProvider.OPTION_FONT, font); - GoToService goToService = tool.getService(GoToService.class); - goToService.goTo(new ProgramLocation(program, getAddr(0x01002500))); - -// FieldLocation loc = getFieldLocation(getAddr(0x0100f3ff)); -// ByteViewerComponent c = panel.getCurrentComponent(); -// c.setCursorPosition(loc.getIndex(), loc.getFieldNum(), -// loc.getRow(), loc.getCol()); -// c.scrollToCursor(); - }); - assertEquals(4, plugin.getProvider().getGroupSize()); - - ViewerPosition vp = panel.getViewerPosition(); - SwingUtilities.invokeAndWait(() -> env.saveRestoreToolState()); - - waitForSwing(); - c = panel.getCurrentComponent(); - assertEquals(4, plugin.getProvider().getGroupSize()); - - assertEquals(getFieldLocation(getAddr(0x01002500)), c.getCursorLocation()); - assertEquals(font, panel.getFontMetrics().getFont()); - waitForSwing(); - Thread.sleep(1000); - assertEquals(vp, panel.getViewerPosition()); - - } - private ByteViewerOptionsDialog launchByteViewerOptions() { - final DockingActionIf action = getAction(plugin, "Byte Viewer Options"); + DockingActionIf action = getAction(plugin, "Byte Viewer Options"); assertTrue(action.isEnabled()); - SwingUtilities.invokeLater(() -> action.actionPerformed(new DefaultActionContext())); + performAction(action, false); waitForSwing(); - ByteViewerOptionsDialog d = env.waitForDialogComponent(ByteViewerOptionsDialog.class, 2000); + ByteViewerOptionsDialog d = waitForDialogComponent(ByteViewerOptionsDialog.class); return d; } -// private boolean isHeaderShowing() { -// FieldScrollPane sp = (FieldScrollPane)findContainer(panel, FieldScrollPane.class); -// ByteViewerHeader header = (ByteViewerHeader)findContainer(sp, ByteViewerHeader.class); -// return header != null; -// } - private ByteViewerComponent findComponent(Container container, String name) { Component[] c = container.getComponents(); for (Component element : c) { @@ -2085,7 +2053,7 @@ public class ByteViewerPlugin2Test extends AbstractGhidraHeadedIntegrationTest { Component[] c = container.getComponents(); for (Component element : c) { if (element instanceof JLabel) { - if (name.equals(((JLabel) element).getName())) { + if (name.equals(element.getName())) { return ((JLabel) element).getText(); } } diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/IncrementalLoadJob.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/IncrementalLoadJob.java index 371dfc829e..6113e9676b 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/IncrementalLoadJob.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/table/threaded/IncrementalLoadJob.java @@ -38,9 +38,8 @@ public class IncrementalLoadJob extends Job implements ThreadedTable * by this job. By default, the value is 0, which means there is nothing to wait for. If we * flush, this will be set to 1. */ - private CountDownLatch completedCallbackLatch = new CountDownLatch(0); + private volatile CountDownLatch completedCallbackLatch = new CountDownLatch(0); private volatile boolean isCancelled = false; - private volatile IncrementalUpdatingAccumulator incrementalAccumulator; IncrementalLoadJob(ThreadedTableModel threadedModel, diff --git a/Ghidra/Processors/ARM/data/languages/ARMneon.sinc b/Ghidra/Processors/ARM/data/languages/ARMneon.sinc index b6c3b5db26..cf5a02eb3c 100644 --- a/Ghidra/Processors/ARM/data/languages/ARMneon.sinc +++ b/Ghidra/Processors/ARM/data/languages/ARMneon.sinc @@ -2808,14 +2808,14 @@ vld1DdList: "{"^buildVld1DdList^"}" is TMode=1 & thv_c0811=2 & thv_D22 & thv_c12 @define Vld1DdList "(c0811=2 | c0811=6 | c0811=7 | c0811=10)" @define thv_Vld1DdList "(thv_c0811=2 | thv_c0811=6 | thv_c0811=7 | thv_c0811=10)" -vldAlign45: is TMode=0 & c0405=0 { } -vldAlign45: "@64" is TMode=0 & c0405=1 { } -vldAlign45: "@128" is TMode=0 & c0405=2 { } -vldAlign45: "@256" is TMode=0 & c0405=3 { } -vldAlign45: is TMode=1 & thv_c0405=0 { } -vldAlign45: "@64" is TMode=1 & thv_c0405=1 { } -vldAlign45: "@128" is TMode=1 & thv_c0405=2 { } -vldAlign45: "@256" is TMode=1 & thv_c0405=3 { } +vldAlign45: is TMode=0 & c0405=0 { } +vldAlign45: ":64" is TMode=0 & c0405=1 { } +vldAlign45: ":128" is TMode=0 & c0405=2 { } +vldAlign45: ":256" is TMode=0 & c0405=3 { } +vldAlign45: is TMode=1 & thv_c0405=0 { } +vldAlign45: ":64" is TMode=1 & thv_c0405=1 { } +vldAlign45: ":128" is TMode=1 & thv_c0405=2 { } +vldAlign45: ":256" is TMode=1 & thv_c0405=3 { } RnAligned45: "["^VRn^vldAlign45^"]" is TMode=0 & VRn & vldAlign45 { export VRn; } RnAligned45: "["^VRn^vldAlign45^"]" is TMode=1 & VRn & vldAlign45 { export VRn; } @@ -2872,12 +2872,12 @@ vld1DdElement2: Dd^"["^vld1Index^"]" is Dd & vld1Index & ((TMode=0 & c1011=2) | @define T_Vld1DdElement2 "((thv_c1011=0 & thv_c0404=0) | (thv_c1011=1 & thv_c0505=0) | (thv_c1011=2 & (thv_c0406=0 | thv_c0406=3)))" -vld1Align2: is TMode=0 & c0404=0 { } -vld1Align2: "@16" is TMode=0 & c1011=1 & c0404=1 { } -vld1Align2: "@32" is TMode=0 & c1011=2 & c0404=1 { } -vld1Align2: is TMode=1 & thv_c0404=0 { } -vld1Align2: "@16" is TMode=1 & thv_c1011=1 & thv_c0404=1 { } -vld1Align2: "@32" is TMode=1 & thv_c1011=2 & thv_c0404=1 { } +vld1Align2: is TMode=0 & c0404=0 { } +vld1Align2: ":16" is TMode=0 & c1011=1 & c0404=1 { } +vld1Align2: ":32" is TMode=0 & c1011=2 & c0404=1 { } +vld1Align2: is TMode=1 & thv_c0404=0 { } +vld1Align2: ":16" is TMode=1 & thv_c1011=1 & thv_c0404=1 { } +vld1Align2: ":32" is TMode=1 & thv_c1011=2 & thv_c0404=1 { } RnAligned2: "["^VRn^vld1Align2^"]" is VRn & vld1Align2 { export VRn; } @@ -2944,9 +2944,9 @@ buildVld1DdList3: vld1Dd3,buildVld1DdList3 is vld1Dd3 & buildVld1DdList3 [ coun vld1DdList3: "{"^buildVld1DdList3^"}" is c0505=0 & D22 & c1215 & buildVld1DdList3 [ regNum=(D22<<4)+c1215-1; counter=1; ] { export 1:4; } vld1DdList3: "{"^buildVld1DdList3^"}" is c0505=1 & D22 & c1215 & buildVld1DdList3 [ regNum=(D22<<4)+c1215-1; counter=2; ] { export 2:4; } -vld1Align3: is c0404=0 { } -vld1Align3: "@16" is c0404=1 & c0607=1 { } -vld1Align3: "@32" is c0404=1 & c0607=2 { } +vld1Align3: is c0404=0 { } +vld1Align3: ":16" is c0404=1 & c0607=1 { } +vld1Align3: ":32" is c0404=1 & c0607=2 { } RnAligned3: "["^Rn^vld1Align3^"]" is Rn & vld1Align3 { export Rn; } @@ -2994,9 +2994,9 @@ thv_vld1RnReplicate: is VRn & thv_c0607=2 thv_vld1DdList3: "{"^buildVld1DdList3^"}" is thv_c0505=0 & thv_D22 & thv_c1215 & buildVld1DdList3 [ regNum=(thv_D22<<4)+thv_c1215-1; counter=1; ] { export 1:4; } thv_vld1DdList3: "{"^buildVld1DdList3^"}" is thv_c0505=1 & thv_D22 & thv_c1215 & buildVld1DdList3 [ regNum=(thv_D22<<4)+thv_c1215-1; counter=2; ] { export 2:4; } -thv_vld1Align3: is thv_c0404=0 { } -thv_vld1Align3: "@16" is thv_c0404=1 & thv_c0607=1 { } -thv_vld1Align3: "@32" is thv_c0404=1 & thv_c0607=2 { } +thv_vld1Align3: is thv_c0404=0 { } +thv_vld1Align3: ":16" is thv_c0404=1 & thv_c0607=1 { } +thv_vld1Align3: ":32" is thv_c0404=1 & thv_c0607=2 { } VRnAligned3: "["^VRn^thv_vld1Align3^"]" is VRn & thv_vld1Align3 { export VRn; } @@ -3145,14 +3145,14 @@ vld2DdElement2: Dreg^"["^vld2Index^"]" is Dreg & vld2Index { } -vld2Align2: is TMode=0 & c0404=0 & (c1111=0 | c0505=0) { } -vld2Align2: "@16" is TMode=0 & c1011=0 & c0404=1 { } -vld2Align2: "@32" is TMode=0 & c1011=1 & c0404=1 { } -vld2Align2: "@64" is TMode=0 & c1011=2 & c0405=1 { } -vld2Align2: is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0) { } -vld2Align2: "@16" is TMode=1 & thv_c1011=0 & thv_c0404=1 { } -vld2Align2: "@32" is TMode=1 & thv_c1011=1 & thv_c0404=1 { } -vld2Align2: "@64" is TMode=1 & thv_c1011=2 & thv_c0405=1 { } +vld2Align2: is TMode=0 & c0404=0 & (c1111=0 | c0505=0) { } +vld2Align2: ":16" is TMode=0 & c1011=0 & c0404=1 { } +vld2Align2: ":32" is TMode=0 & c1011=1 & c0404=1 { } +vld2Align2: ":64" is TMode=0 & c1011=2 & c0405=1 { } +vld2Align2: is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0) { } +vld2Align2: ":16" is TMode=1 & thv_c1011=0 & thv_c0404=1 { } +vld2Align2: ":32" is TMode=1 & thv_c1011=1 & thv_c0404=1 { } +vld2Align2: ":64" is TMode=1 & thv_c1011=2 & thv_c0405=1 { } vld2RnAligned2: "["^VRn^vld2Align2^"]" is VRn & vld2Align2 { export VRn; } @@ -3182,14 +3182,14 @@ vld2DdList2: "{"^buildVld2DdList2^"}" is TMode=1 & ((thv_c1011=1 & thv_c0505=1) # VLD2 (single 2-element structure to all lanes) # -vld2Align3: is TMode=0 & c0404=0 { } -vld2Align3: "@16" is TMode=0 & c0404=1 & c0607=0 { } -vld2Align3: "@32" is TMode=0 & c0404=1 & c0607=1 { } -vld2Align3: "@64" is TMode=0 & c0404=1 & c0607=2 { } -vld2Align3: is TMode=1 & thv_c0404=0 { } -vld2Align3: "@16" is TMode=1 & thv_c0404=1 & thv_c0607=0 { } -vld2Align3: "@32" is TMode=1 & thv_c0404=1 & thv_c0607=1 { } -vld2Align3: "@64" is TMode=1 & thv_c0404=1 & thv_c0607=2 { } +vld2Align3: is TMode=0 & c0404=0 { } +vld2Align3: ":16" is TMode=0 & c0404=1 & c0607=0 { } +vld2Align3: ":32" is TMode=0 & c0404=1 & c0607=1 { } +vld2Align3: ":64" is TMode=0 & c0404=1 & c0607=2 { } +vld2Align3: is TMode=1 & thv_c0404=0 { } +vld2Align3: ":16" is TMode=1 & thv_c0404=1 & thv_c0607=0 { } +vld2Align3: ":32" is TMode=1 & thv_c0404=1 & thv_c0607=1 { } +vld2Align3: ":64" is TMode=1 & thv_c0404=1 & thv_c0607=2 { } vld2RnAligned3: "["^VRn^vld2Align3^"]" is VRn & vld2Align3 { export VRn; } @@ -3217,11 +3217,10 @@ vld2DdList3: "{"^buildVld2DdList3^"}" is TMode=1 & thv_c0505=1 & thv_D22 & thv_c ####### # VLD3 (multiple 3-element structures) # - -vld3Align: is TMode=0 & c0404=0 { } -vld3Align: "@64" is TMode=0 & c0404=1 { } -vld3Align: is TMode=1 & thv_c0404=0 { } -vld3Align: "@64" is TMode=1 & thv_c0404=1 { } +vld3Align: is TMode=0 & c0404=0 { } +vld3Align: ":64" is TMode=0 & c0404=1 { } +vld3Align: is TMode=1 & thv_c0404=0 { } +vld3Align: ":64" is TMode=1 & thv_c0404=1 { } vld3RnAligned: "["^VRn^vld3Align^"]" is VRn & vld3Align { export VRn; } @@ -3306,24 +3305,43 @@ vld3DdList3: "{"^buildVld3DdList3^"}" is TMode=1 & thv_c0505=1 & thv_D22 & thv_c vld4Index: val is TMode=0 & c0507 & c1011 [ val = c0507 >> c1011; ] { tmp:4 = val; export tmp; } vld4Index: val is TMode=1 & thv_c0507 & thv_c1011 [ val = thv_c0507 >> thv_c1011; ] { tmp:4 = val; export tmp; } -vld4DdElement2: Dreg^"["^vld4Index^"]" is Dreg & vld4Index +vld4DdElement2: Dreg^"["^vld4Index^"]" is Dreg & vld4Index & ((TMode=0 & c1011=0) | (TMode=1 & thv_c1011=0)) { + ptr:4 = &Dreg + vld4Index; + *[register]:1 ptr = *:1 mult_addr; } -vld4Align2: is TMode=0 & c0404=0 & (c1111=0 | c0505=0) { } -vld4Align2: "@32" is TMode=0 & c1011=0 & c0404=1 { } -vld4Align2: "@64" is TMode=0 & ((c1011=1 & c0404=1) | (c1011=2 & c0405=1)) { } -vld4Align2: "@128" is TMode=0 & c1011=2 & c0405=2 { } -vld4Align2: is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0) { } -vld4Align2: "@32" is TMode=1 & thv_c1011=0 & thv_c0404=1 { } -vld4Align2: "@64" is TMode=1 & ((thv_c1011=1 & thv_c0404=1) | (thv_c1011=2 & thv_c0405=1)) { } -vld4Align2: "@128" is TMode=1 & thv_c1011=2 & thv_c0405=2 { } +vld4DdElement2: Dreg^"["^vld4Index^"]" is Dreg & vld4Index & ((TMode=0 & c1011=1) | (TMode=1 & thv_c1011=1)) +{ + ptr:4 = &Dreg + vld4Index; + *[register]:2 ptr = *:2 mult_addr; +} -vld4RnAligned2: "["^Rn^vld4Align2^"]" is Rn & vld4Align2 { export Rn; } +vld4DdElement2: Dreg^"["^vld4Index^"]" is Dreg & vld4Index & ((TMode=0 & c1011=2) | (TMode=1 & thv_c1011=2)) +{ + ptr:4 = &Dreg + vld4Index; + *[register]:4 ptr = *:4 mult_addr; +} + +vld4Align2: is TMode=0 & c0404=0 & (c1111=0 | c0505=0) { } +vld4Align2: ":32" is TMode=0 & c1011=0 & c0404=1 { } +vld4Align2: ":64" is TMode=0 & ((c1011=1 & c0404=1) | (c1011=2 & c0405=1)) { } +vld4Align2: ":128" is TMode=0 & c1011=2 & c0405=2 { } +vld4Align2: is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0) { } +vld4Align2: ":32" is TMode=1 & thv_c1011=0 & thv_c0404=1 { } +vld4Align2: ":64" is TMode=1 & ((thv_c1011=1 & thv_c0404=1) | (thv_c1011=2 & thv_c0405=1)) { } +vld4Align2: ":128" is TMode=1 & thv_c1011=2 & thv_c0405=2 { } + +vld4RnAligned2: "["^VRn^vld4Align2^"]" is VRn & vld4Align2 { export VRn; } buildVld4DdList2: is counter=0 { } -buildVld4DdList2: vld4DdElement2 is counter=1 & vld4DdElement2 [ counter=0; regNum=regNum+regInc; ] { } -buildVld4DdList2: vld4DdElement2,buildVld4DdList2 is vld4DdElement2 & buildVld4DdList2 [ counter=counter-1; regNum=regNum+regInc; ] { } +buildVld4DdList2: vld4DdElement2 is counter=1 & vld4DdElement2 [ counter=0; regNum=regNum+regInc; ] { build vld4DdElement2; } +buildVld4DdList2: vld4DdElement2,buildVld4DdList2 is vld4DdElement2 & buildVld4DdList2 & esize1011 [ counter=counter-1; regNum=regNum+regInc; ] +{ + build vld4DdElement2; + mult_addr = mult_addr + esize1011; + build buildVld4DdList2; +} vld4DdList2: "{"^buildVld4DdList2^"}" is TMode=0 & D22 & c1215 & buildVld4DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single vld4DdList2: "{"^buildVld4DdList2^"}" is TMode=0 & ((c1011=1 & c0505=1) | (c1011=2 & c0606=1)) & D22 & c1215 & buildVld4DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double @@ -3333,53 +3351,119 @@ vld4DdList2: "{"^buildVld4DdList2^"}" is TMode=1 & ((thv_c1011=1 & thv_c0505=1) :vld4.^esize1011 vld4DdList2,vld4RnAligned2 is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=3 & c0003=15) | ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=3 & thv_c0003=15 ) ) & esize1011 & vld4RnAligned2 & vld4DdList2 -unimpl +{ + mult_addr = vld4RnAligned2; + build vld4DdList2; +} :vld4.^esize1011 vld4DdList2,vld4RnAligned2^"!" is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=3 & c0003=13) | ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=3 & thv_c0003=13 ) ) & esize1011 & vld4RnAligned2 & vld4DdList2 -unimpl +{ + mult_addr = vld4RnAligned2; + build vld4DdList2; + vld4RnAligned2 = vld4RnAligned2 + (4 * esize1011); +} :vld4.^esize1011 vld4DdList2,vld4RnAligned2,VRm is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c1011<3 & c0809=3 & c0003) | ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c1011<3 & thv_c0809=3 & thv_c0003 ) ) & esize1011 & VRm & vld4RnAligned2 & vld4DdList2 - unimpl + { + mult_addr = vld4RnAligned2; + build vld4DdList2; + vld4RnAligned2 = vld4RnAligned2 + VRm; +} ####### # VLD4 (single 4-element structure to all lanes) # -vld4Align3: is c0404=0 { } -vld4Align3: "@32" is c0404=1 & c0607=0 { } -vld4Align3: "@64" is c0404=1 & (c0607=1 | c0607=2) { } -vld4Align3: "@128" is c0404=1 & c0607=3 { } +vld4size0607: "8" is TMode=0 & c0607=0 { export 1:4; } +vld4size0607: "16" is TMode=0 & c0607=1 { export 2:4; } +vld4size0607: "32" is TMode=0 & c0607=2 { export 4:4; } +vld4size0607: "32" is TMode=0 & c0607=3 { export 4:4; } # see VLD4 (single 4-element structure to all lanes) +vld4size0607: "8" is TMode=1 & thv_c0607=0 { export 1:4; } +vld4size0607: "16" is TMode=1 & thv_c0607=1 { export 2:4; } +vld4size0607: "32" is TMode=1 & thv_c0607=2 { export 4:4; } +vld4size0607: "32" is TMode=1 & thv_c0607=3 { export 4:4; } # see VLD4 (single 4-element structure to all lanes) -vld4RnAligned3: "["^Rn^vld4Align3^"]" is Rn & vld4Align3 { export Rn; } +vld4Align3: is TMode=0 & c0404=0 { } +vld4Align3: ":32" is TMode=0 & c0404=1 & c0607=0 { } +vld4Align3: ":64" is TMode=0 & c0404=1 & (c0607=1 | c0607=2) { } +vld4Align3: ":128" is TMode=0 & c0404=1 & c0607=3 { } +vld4Align3: is TMode=1 & thv_c0404=0 { } +vld4Align3: ":32" is TMode=1 & thv_c0404=1 & thv_c0607=0 { } +vld4Align3: ":64" is TMode=1 & thv_c0404=1 & (thv_c0607=1 | thv_c0607=2) { } +vld4Align3: ":128" is TMode=1 & thv_c0404=1 & thv_c0607=3 { } + +vld4RnAligned3: "["^VRn^vld4Align3^"]" is VRn & vld4Align3 { export VRn; } + +vld4DdElement3: is Dreg & ((TMode=0 & c0607=0) | (TMode=1 & thv_c0607=0)) +{ + data:1 = *:1 mult_addr; + replicate1to8(data, Dreg); +} + +vld4DdElement3: is Dreg & ((TMode=0 & c0607=1) | (TMode=1 & thv_c0607=1)) +{ + data:2 = *:2 mult_addr; + replicate2to8(data, Dreg); +} + +vld4DdElement3: is Dreg & ((TMode=0 & c0607>1) | (TMode=1 & thv_c0607>1)) +{ + data:4 = *:4 mult_addr; + replicate4to8(data, Dreg); +} buildVld4DdList3: is counter=0 { } -buildVld4DdList3: Dreg^"[]" is counter=1 & Dreg [ counter=0; regNum=regNum+regInc; ] { } -buildVld4DdList3: Dreg^"[]",buildVld4DdList3 is Dreg & buildVld4DdList3 [ counter=counter-1; regNum=regNum+regInc; ] { } +buildVld4DdList3: Dreg^"[]" is counter=1 & Dreg & vld4DdElement3 [ counter=0; regNum=regNum+regInc; ] { build vld4DdElement3; } +buildVld4DdList3: Dreg^"[]",buildVld4DdList3 is vld4DdElement3 & Dreg & buildVld4DdList3 & vld4size0607 [ counter=counter-1; regNum=regNum+regInc; ] +{ + build vld4DdElement3; + mult_addr = mult_addr + vld4size0607; + build buildVld4DdList3; +} -vld4DdList3: "{"^buildVld4DdList3^"}" is c0505=0 & D22 & c1215 & buildVld4DdList3 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single -vld4DdList3: "{"^buildVld4DdList3^"}" is c0505=1 & D22 & c1215 & buildVld4DdList3 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double +vld4DdList3: "{"^buildVld4DdList3^"}" is TMode=0 & c0505=0 & D22 & c1215 & buildVld4DdList3 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single +vld4DdList3: "{"^buildVld4DdList3^"}" is TMode=0 & c0505=1 & D22 & c1215 & buildVld4DdList3 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double +vld4DdList3: "{"^buildVld4DdList3^"}" is TMode=1 & thv_c0505=0 & thv_D22 & thv_c1215 & buildVld4DdList3 [ regNum=(thv_D22<<4)+thv_c1215-1; regInc=1; counter=4; ] { } # Single +vld4DdList3: "{"^buildVld4DdList3^"}" is TMode=1 & thv_c0505=1 & thv_D22 & thv_c1215 & buildVld4DdList3 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=4; ] { } # Double -:vld4.^esize0607 vld4DdList3,vld4RnAligned3 is $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & vld4RnAligned3 & c0811=15 & esize0607 & c0003=15 & vld4DdList3 unimpl -#thv_2327=0x12 -:vld4.^esize0607 vld4DdList3,vld4RnAligned3^"!" is $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & vld4RnAligned3 & c0811=15 & esize0607 & c0003=13 & vld4DdList3 unimpl +:vld4.^vld4size0607 vld4DdList3,vld4RnAligned3 is ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c0811=0xf & c0003=0xf) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=0xf & thv_c0003=0xf) & vld4size0607 & vld4RnAligned3 & vld4DdList3 +{ + mult_addr = vld4RnAligned3; + build vld4DdList3; +} -:vld4.^esize0607 vld4DdList3,vld4RnAligned3,VRm is $(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & vld4RnAligned3 & c0811=15 & esize0607 & VRm & vld4DdList3 unimpl +:vld4.^vld4size0607 vld4DdList3,vld4RnAligned3^"!" is ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c0811=0xf & c0003=0xd) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=0xf & thv_c0003=0xd) & vld4size0607 & vld4RnAligned3 & vld4DdList3 +{ + mult_addr = vld4RnAligned3; + build vld4DdList3; + vld4RnAligned3 = vld4RnAligned3 + (4 * vld4size0607); +} + +:vld4.^vld4size0607 vld4DdList3,vld4RnAligned3,VRm is ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=2 & c0811=0xf) | + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=2 & thv_c0811=0xf) & vld4size0607 & VRm & vld4RnAligned3 & vld4DdList3 +{ + mult_addr = vld4RnAligned3; + build vld4DdList3; + vld4RnAligned3 = vld4RnAligned3 + VRm; +} ####### # VLD4 (multiple 4-element structures) # -vld4Align: is TMode=0 & c0405=0 { } -vld4Align: "@64" is TMode=0 & c0405=1 { } -vld4Align: "@128" is TMode=0 & c0405=2 { } -vld4Align: "@256" is TMode=0 & c0405=3 { } -vld4Align: is TMode=1 & thv_c0405=0 { } -vld4Align: "@64" is TMode=1 & thv_c0405=1 { } -vld4Align: "@128" is TMode=1 & thv_c0405=2 { } -vld4Align: "@256" is TMode=1 & thv_c0405=3 { } +vld4Align: is TMode=0 & c0405=0 { } +vld4Align: ":64" is TMode=0 & c0405=1 { } +vld4Align: ":128" is TMode=0 & c0405=2 { } +vld4Align: ":256" is TMode=0 & c0405=3 { } +vld4Align: is TMode=1 & thv_c0405=0 { } +vld4Align: ":64" is TMode=1 & thv_c0405=1 { } +vld4Align: ":128" is TMode=1 & thv_c0405=2 { } +vld4Align: ":256" is TMode=1 & thv_c0405=3 { } vld4RnAligned: "["^VRn^vld4Align^"]" is VRn & vld4Align { export VRn; } @@ -5583,14 +5667,14 @@ vst2DdElement2: Dreg^"["^vld2Index^"]" is Dreg & vld2Index { } -vst2Align2: is TMode=0 & c0404=0 & (c1111=0 | c0505=0) { } -vst2Align2: "@16" is TMode=0 & c1011=0 & c0404=1 { } -vst2Align2: "@32" is TMode=0 & c1011=1 & c0404=1 { } -vst2Align2: "@64" is TMode=0 & c1011=2 & c0405=1 { } -vst2Align2: is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0) { } -vst2Align2: "@16" is TMode=1 & thv_c1011=0 & thv_c0404=1 { } -vst2Align2: "@32" is TMode=1 & thv_c1011=1 & thv_c0404=1 { } -vst2Align2: "@64" is TMode=1 & thv_c1011=2 & thv_c0405=1 { } +vst2Align2: is TMode=0 & c0404=0 & (c1111=0 | c0505=0) { } +vst2Align2: ":16" is TMode=0 & c1011=0 & c0404=1 { } +vst2Align2: ":32" is TMode=0 & c1011=1 & c0404=1 { } +vst2Align2: ":64" is TMode=0 & c1011=2 & c0405=1 { } +vst2Align2: is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0) { } +vst2Align2: ":16" is TMode=1 & thv_c1011=0 & thv_c0404=1 { } +vst2Align2: ":32" is TMode=1 & thv_c1011=1 & thv_c0404=1 { } +vst2Align2: ":64" is TMode=1 & thv_c1011=2 & thv_c0405=1 { } vst2RnAligned2: "["^VRn^vst2Align2^"]" is VRn & vst2Align2 { export VRn; } @@ -5625,10 +5709,10 @@ vst2DdList2: "{"^buildVst2DdList2^"}" is TMode=1 & ((thv_c1011=1 & thv_c0505=1) # -vst3Align: is TMode=0 & c0404=0 { } -vst3Align: "@64" is TMode=0 & c0404=1 { } -vst3Align: is TMode=1 & thv_c0404=0 { } -vst3Align: "@64" is TMode=1 & thv_c0404=1 { } +vst3Align: is TMode=0 & c0404=0 { } +vst3Align: ":64" is TMode=0 & c0404=1 { } +vst3Align: is TMode=1 & thv_c0404=0 { } +vst3Align: ":64" is TMode=1 & thv_c0404=1 { } vst3RnAligned: "["^VRn^vst3Align^"]" is VRn & vst3Align { export VRn; } @@ -5683,14 +5767,14 @@ vst3DdList2: "{"^buildvst3DdList^"}" is TMode=1 & ((thv_c1011=1 & thv_c0505=1) | # VST4 (multiple 4-element structures) # -vst4Align: is TMode=0 & c0405=0 { } -vst4Align: "@64" is TMode=0 & c0405=1 { } -vst4Align: "@128" is TMode=0 & c0405=2 { } -vst4Align: "@256" is TMode=0 & c0405=3 { } -vst4Align: is TMode=1 & thv_c0405=0 { } -vst4Align: "@64" is TMode=1 & thv_c0405=1 { } -vst4Align: "@128" is TMode=1 & thv_c0405=2 { } -vst4Align: "@256" is TMode=1 & thv_c0405=3 { } +vst4Align: is TMode=0 & c0405=0 { } +vst4Align: ":64" is TMode=0 & c0405=1 { } +vst4Align: ":128" is TMode=0 & c0405=2 { } +vst4Align: ":256" is TMode=0 & c0405=3 { } +vst4Align: is TMode=1 & thv_c0405=0 { } +vst4Align: ":64" is TMode=1 & thv_c0405=1 { } +vst4Align: ":128" is TMode=1 & thv_c0405=2 { } +vst4Align: ":256" is TMode=1 & thv_c0405=3 { } vst4RnAligned: "["^VRn^vst4Align^"]" is VRn & vst4Align { export VRn; } @@ -5720,24 +5804,48 @@ vst4Index: val is TMode=0 & c0507 & c1011 [ val = c0507 >> c1011; ] { tmp:4 = va vst4Index: val is TMode=1 & thv_c0507 & thv_c1011 [ val = thv_c0507 >> thv_c1011; ] { tmp:4 = val; export tmp; } -vst4DdElement2: Dreg^"["^vst4Index^"]" is Dreg & vst4Index +vst4DdElement2: Dreg^"["^vst4Index^"]" is Dreg & vst4Index & ((TMode=0 & c1011=0) | (TMode=1 & thv_c1011=0)) { + ptr:4 = &Dreg + vst4Index; + *:1 mult_addr = *[register]:1 ptr; } -vst4Align2: is TMode=0 & c0404=0 & (c1111=0 | c0505=0) { } -vst4Align2: "@32" is TMode=0 & c1011=0 & c0404=1 { } -vst4Align2: "@64" is TMode=0 & ((c1011=1 & c0404=1) | (c1011=2 & c0405=1)) { } -vst4Align2: "@128" is TMode=0 & c1011=2 & c0405=2 { } -vst4Align2: is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0) { } -vst4Align2: "@32" is TMode=1 & thv_c1011=0 & thv_c0404=1 { } -vst4Align2: "@64" is TMode=1 & ((thv_c1011=1 & thv_c0404=1) | (thv_c1011=2 & thv_c0405=1)) { } -vst4Align2: "@128" is TMode=1 & thv_c1011=2 & thv_c0405=2 { } +vst4DdElement2: Dreg^"["^vst4Index^"]" is Dreg & vst4Index & TMode=0 & ((TMode=0 & c1011=1) | (TMode=1 & thv_c1011=1)) +{ + ptr:4 = &Dreg + vst4Index; + *:2 mult_addr = *[register]:2 ptr; +} + +vst4DdElement2: Dreg^"["^vst4Index^"]" is Dreg & vst4Index & ((TMode=0 & c1011=2) | (TMode=1 & thv_c1011=2)) +{ + ptr:4 = &Dreg + vst4Index; + *:4 mult_addr = *[register]:4 ptr; +} + +vst4DdElement2: Dreg^"["^vst4Index^"]" is Dreg & vst4Index & ((TMode=0 & c1011=3) | (TMode=1 & thv_c1011=3)) +{ + *mult_addr = Dreg; +} + +vst4Align2: is TMode=0 & c0404=0 & (c1111=0 | c0505=0) { } +vst4Align2: ":32" is TMode=0 & c1011=0 & c0404=1 { } +vst4Align2: ":64" is TMode=0 & ((c1011=1 & c0404=1) | (c1011=2 & c0405=1)) { } +vst4Align2: ":128" is TMode=0 & c1011=2 & c0405=2 { } +vst4Align2: is TMode=1 & thv_c0404=0 & (thv_c1111=0 | thv_c0505=0) { } +vst4Align2: ":32" is TMode=1 & thv_c1011=0 & thv_c0404=1 { } +vst4Align2: ":64" is TMode=1 & ((thv_c1011=1 & thv_c0404=1) | (thv_c1011=2 & thv_c0405=1)) { } +vst4Align2: ":128" is TMode=1 & thv_c1011=2 & thv_c0405=2 { } vst4RnAligned2: "["^VRn^vst4Align2^"]" is VRn & vst4Align2 { export VRn; } buildVst4DdList2: is counter=0 { } -buildVst4DdList2: vst4DdElement2 is counter=1 & vst4DdElement2 [ counter=0; regNum=regNum+regInc; ] { } -buildVst4DdList2: vst4DdElement2,buildVst4DdList2 is vst4DdElement2 & buildVst4DdList2 [ counter=counter-1; regNum=regNum+regInc; ] { } +buildVst4DdList2: vst4DdElement2 is counter=1 & vst4DdElement2 [ counter=0; regNum=regNum+regInc; ] { build vst4DdElement2; } +buildVst4DdList2: vst4DdElement2,buildVst4DdList2 is vst4DdElement2 & buildVst4DdList2 & esize1011 [ counter=counter-1; regNum=regNum+regInc; ] +{ + build vst4DdElement2; + mult_addr = mult_addr + esize1011; + build buildVst4DdList2; +} vst4DdList2: "{"^buildVst4DdList2^"}" is TMode=0 & D22 & c1215 & buildVst4DdList2 [ regNum=(D22<<4)+c1215-1; regInc=1; counter=4; ] { } # Single vst4DdList2: "{"^buildVst4DdList2^"}" is TMode=0 & ((c1011=1 & c0505=1) | (c1011=2 & c0606=1)) & D22 & c1215 & buildVst4DdList2 [ regNum=(D22<<4)+c1215-2; regInc=2; counter=4; ] { } # Double @@ -5745,13 +5853,26 @@ vst4DdList2: "{"^buildVst4DdList2^"}" is TMode=1 & thv_D22 & thv_c1215 & buildVs vst4DdList2: "{"^buildVst4DdList2^"}" is TMode=1 & ((thv_c1011=1 & thv_c0505=1) | (thv_c1011=2 & thv_c0606=1)) & thv_D22 & thv_c1215 & buildVst4DdList2 [ regNum=(thv_D22<<4)+thv_c1215-2; regInc=2; counter=4; ] { } # Double :vst4.^esize1011 vst4DdList2,vst4RnAligned2 is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=3 & c0003=15) | - ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=3 & thv_c0003=15) ) & vst4RnAligned2 & esize1011 & vst4DdList2 unimpl + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=3 & thv_c0003=15) ) & vst4RnAligned2 & esize1011 & vst4DdList2 +{ + mult_addr = vst4RnAligned2; + build vst4DdList2; +} :vst4.^esize1011 vst4DdList2,vst4RnAligned2^"!" is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=3 & c0003=13) | - ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=3 & thv_c0003=13) ) & vst4RnAligned2 & esize1011 & vst4DdList2 unimpl - + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=3 & thv_c0003=13) ) & vst4RnAligned2 & esize1011 & vst4DdList2 +{ + mult_addr = vst4RnAligned2; + build vst4DdList2; + vst4RnAligned2 = vst4RnAligned2 + (4 * esize1011); +} :vst4.^esize1011 vst4DdList2,vst4RnAligned2,VRm is ( ($(AMODE) & ARMcond=0 & cond=15 & c2327=9 & c2021=0 & c1011<3 & c0809=3) | - ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=3) ) & VRm & vst4RnAligned2 & esize1011 & vst4DdList2 unimpl + ($(TMODE_F) & thv_c2327=0x13 & thv_c2021=0 & thv_c1011<3 & thv_c0809=3) ) & VRm & vst4RnAligned2 & esize1011 & vst4DdList2 +{ + mult_addr = vst4RnAligned2; + build vst4DdList2; + vst4RnAligned2 = vst4RnAligned2 + VRm; +} @endif # SIMD