kopia lustrzana https://github.com/maccasoft/z80-tools
Refactored debugger source map builder
rodzic
228160fb62
commit
fc0b5db0a7
|
@ -27,10 +27,8 @@ import java.io.Writer;
|
|||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.eclipse.core.databinding.observable.Realm;
|
||||
|
@ -89,6 +87,7 @@ import org.eclipse.swt.widgets.Shell;
|
|||
import org.eclipse.swt.widgets.ToolBar;
|
||||
import org.eclipse.swt.widgets.ToolItem;
|
||||
|
||||
import com.maccasoft.tools.SourceMap.LineEntry;
|
||||
import com.maccasoft.tools.editor.Z80TokenMarker;
|
||||
import com.maccasoft.tools.internal.BusyIndicator;
|
||||
import com.maccasoft.tools.internal.ImageRegistry;
|
||||
|
@ -134,19 +133,7 @@ public class Application {
|
|||
|
||||
Z80 proc;
|
||||
MemIoOps memIoOps;
|
||||
int entryAddress;
|
||||
|
||||
class LineEntry {
|
||||
int lineNumber;
|
||||
Line line;
|
||||
|
||||
LineEntry(int lineNumber, Line line) {
|
||||
this.lineNumber = lineNumber;
|
||||
this.line = line;
|
||||
}
|
||||
}
|
||||
|
||||
Map<Integer, LineEntry> list;
|
||||
SourceMap sourceMap;
|
||||
|
||||
int stepOverPC1;
|
||||
int stepOverPC2;
|
||||
|
@ -2518,27 +2505,15 @@ public class Application {
|
|||
});
|
||||
proc.setBreakpoint(0x0005, true);
|
||||
|
||||
list = new HashMap<Integer, LineEntry>();
|
||||
|
||||
entryAddress = -1;
|
||||
|
||||
int lineNumber = 0;
|
||||
for (Line line : source.getLines()) {
|
||||
int address = line.getScope().getAddress();
|
||||
byte[] code = line.getBytes();
|
||||
if (code.length != 0 && entryAddress == -1) {
|
||||
entryAddress = address;
|
||||
}
|
||||
System.arraycopy(code, 0, memIoOps.getRam(), address, code.length);
|
||||
list.put(address, new LineEntry(lineNumber++, line));
|
||||
}
|
||||
sourceMap = new SourceMap(source, memIoOps);
|
||||
sourceMap.build();
|
||||
|
||||
display.syncExec(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
memory.setData(memIoOps.getRam());
|
||||
viewer.setSource(source);
|
||||
viewer.setSourceMap(sourceMap);
|
||||
handleReset();
|
||||
|
||||
reparentControls();
|
||||
|
@ -2613,9 +2588,9 @@ public class Application {
|
|||
|
||||
proc.setPinReset();
|
||||
proc.reset();
|
||||
proc.setRegPC(entryAddress);
|
||||
proc.setRegPC(sourceMap.getEntryAddress());
|
||||
|
||||
memory.setSelection(entryAddress);
|
||||
memory.setSelection(sourceMap.getEntryAddress());
|
||||
|
||||
updateDebuggerState();
|
||||
}
|
||||
|
@ -2625,16 +2600,16 @@ public class Application {
|
|||
memory.clearUpdates();
|
||||
viewer.getControl().setFocus();
|
||||
|
||||
LineEntry lineEntry = list.get(proc.getRegPC());
|
||||
LineEntry lineEntry = sourceMap.getLineAtAddress(proc.getRegPC());
|
||||
if (lineEntry != null) {
|
||||
stepOverPC1 = proc.getRegPC() + lineEntry.line.getSize();
|
||||
stepOverPC1 = proc.getRegPC() + lineEntry.code.length;
|
||||
stepOverPC2 = memIoOps.peek16(proc.getRegSP());
|
||||
stepOverSP = proc.getRegSP();
|
||||
boolean repeat = isRepeatInstruction();
|
||||
|
||||
proc.execute();
|
||||
|
||||
if (repeat || list.get(proc.getRegPC()) == null) {
|
||||
if (repeat || sourceMap.getLineAtAddress(proc.getRegPC()) == null) {
|
||||
display.asyncExec(stepOverRunnable);
|
||||
return;
|
||||
}
|
||||
|
@ -2670,9 +2645,9 @@ public class Application {
|
|||
memory.clearUpdates();
|
||||
viewer.getControl().setFocus();
|
||||
|
||||
LineEntry lineEntry = list.get(proc.getRegPC());
|
||||
LineEntry lineEntry = sourceMap.getLineAtAddress(proc.getRegPC());
|
||||
if (lineEntry != null) {
|
||||
stepOverPC1 = proc.getRegPC() + lineEntry.line.getSize();
|
||||
stepOverPC1 = proc.getRegPC() + lineEntry.code.length;
|
||||
stepOverPC2 = memIoOps.peek16(proc.getRegSP());
|
||||
stepOverSP = proc.getRegSP();
|
||||
display.asyncExec(stepOverRunnable);
|
||||
|
@ -2691,10 +2666,10 @@ public class Application {
|
|||
int caretOffset = viewer.getStyledText().getCaretOffset();
|
||||
int lineAtOffset = viewer.getStyledText().getLineAtOffset(caretOffset);
|
||||
|
||||
Line line = viewer.getSource().getLines().get(lineAtOffset);
|
||||
LineEntry lineEntry = viewer.getSourceMap().getLines().get(lineAtOffset);
|
||||
|
||||
if (line.getScope().getAddress() != proc.getRegPC()) {
|
||||
stepOverPC1 = line.getScope().getAddress();
|
||||
if (lineEntry.address != proc.getRegPC()) {
|
||||
stepOverPC1 = lineEntry.address;
|
||||
display.asyncExec(runToLineRunnable);
|
||||
}
|
||||
}
|
||||
|
@ -2709,9 +2684,9 @@ public class Application {
|
|||
int caretOffset = viewer.getStyledText().getCaretOffset();
|
||||
int lineAtOffset = viewer.getStyledText().getLineAtOffset(caretOffset);
|
||||
|
||||
Line line = viewer.getSource().getLines().get(lineAtOffset);
|
||||
if (line != null) {
|
||||
int address = line.getScope().getAddress();
|
||||
LineEntry lineEntry = viewer.getSourceMap().getLines().get(lineAtOffset);
|
||||
if (lineEntry != null) {
|
||||
int address = lineEntry.address;
|
||||
viewer.toggleBreakpoint(address);
|
||||
proc.setBreakpoint(address, viewer.isBreakpoint(address));
|
||||
}
|
||||
|
@ -2735,7 +2710,7 @@ public class Application {
|
|||
memory.update();
|
||||
registers.updateRegisters(proc);
|
||||
|
||||
LineEntry lineEntry = list.get(proc.getRegPC());
|
||||
LineEntry lineEntry = sourceMap.getLineAtAddress(proc.getRegPC());
|
||||
if (lineEntry != null) {
|
||||
viewer.gotToLineColumn(lineEntry.lineNumber, 0);
|
||||
}
|
||||
|
|
|
@ -30,8 +30,7 @@ import org.eclipse.swt.widgets.Composite;
|
|||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.ScrollBar;
|
||||
|
||||
import nl.grauw.glass.Line;
|
||||
import nl.grauw.glass.Source;
|
||||
import com.maccasoft.tools.SourceMap.LineEntry;
|
||||
|
||||
public class CodeRuler {
|
||||
|
||||
|
@ -40,7 +39,7 @@ public class CodeRuler {
|
|||
FontMetrics fontMetrics;
|
||||
|
||||
StyledText text;
|
||||
Source source;
|
||||
SourceMap sourceMap;
|
||||
boolean[] breakpoint;
|
||||
|
||||
int leftMargin;
|
||||
|
@ -119,8 +118,8 @@ public class CodeRuler {
|
|||
this.text.addCaretListener(caretListener);
|
||||
}
|
||||
|
||||
public void setSource(Source source) {
|
||||
this.source = source;
|
||||
public void setSourceMap(SourceMap sourceMap) {
|
||||
this.sourceMap = sourceMap;
|
||||
}
|
||||
|
||||
void onPaintControl(GC gc) {
|
||||
|
@ -136,18 +135,16 @@ public class CodeRuler {
|
|||
break;
|
||||
}
|
||||
|
||||
if (source != null && lineNumber >= 0 && lineNumber < source.getLines().size()) {
|
||||
Line line = source.getLines().get(lineNumber);
|
||||
int address = line.getScope().getAddress();
|
||||
byte[] code = line.getBytes();
|
||||
if (sourceMap != null && lineNumber >= 0 && lineNumber < sourceMap.getLines().size()) {
|
||||
LineEntry line = sourceMap.getLine(lineNumber);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(String.format("%04X ", line.getScope().getAddress()));
|
||||
for (int i = 0; i < code.length; i++) {
|
||||
sb.append(String.format("%04X ", line.address));
|
||||
for (int i = 0; i < line.code.length; i++) {
|
||||
if (i != 0) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append(String.format("%02X", code[i]));
|
||||
sb.append(String.format("%02X", line.code[i]));
|
||||
}
|
||||
if (lineNumber == currentLine) {
|
||||
gc.setBackground(currentLineBackground);
|
||||
|
@ -156,7 +153,7 @@ public class CodeRuler {
|
|||
else {
|
||||
gc.setBackground(canvas.getBackground());
|
||||
}
|
||||
gc.setFont((breakpoint[address] && code.length != 0) ? fontBold : font);
|
||||
gc.setFont((breakpoint[line.address] && line.code.length != 0) ? fontBold : font);
|
||||
gc.drawString(sb.toString(), leftMargin, y, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2018-19 Marco Maccaferri and others.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program and the accompanying materials are made available under
|
||||
* the terms of the Eclipse Public License v1.0 which accompanies this
|
||||
* distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
|
||||
package com.maccasoft.tools;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import nl.grauw.glass.AssemblyException;
|
||||
import nl.grauw.glass.Line;
|
||||
import nl.grauw.glass.Scope;
|
||||
import nl.grauw.glass.Source;
|
||||
import nl.grauw.glass.directives.If;
|
||||
import z80core.MemIoOps;
|
||||
|
||||
public class SourceMap {
|
||||
|
||||
Source source;
|
||||
MemIoOps memIoOps;
|
||||
|
||||
int address;
|
||||
int entryAddress;
|
||||
|
||||
public static class LineEntry {
|
||||
public final Line line;
|
||||
public final int lineNumber;
|
||||
|
||||
public final int address;
|
||||
public final byte[] code;
|
||||
|
||||
public LineEntry(int lineNumber, int address, Line line) {
|
||||
this.line = line;
|
||||
this.address = address;
|
||||
this.lineNumber = lineNumber;
|
||||
|
||||
Scope scope = line.getScope();
|
||||
|
||||
if (line.getDirective() instanceof If) {
|
||||
this.code = new byte[0];
|
||||
}
|
||||
else if (scope.isAddressSet()) {
|
||||
this.code = line.getBytes();
|
||||
}
|
||||
else {
|
||||
this.code = new byte[0];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Map<Integer, LineEntry> map;
|
||||
List<LineEntry> list;
|
||||
|
||||
public SourceMap(Source source, MemIoOps memIoOps) {
|
||||
this.source = source;
|
||||
this.memIoOps = memIoOps;
|
||||
}
|
||||
|
||||
public void build() {
|
||||
address = 0;
|
||||
entryAddress = -1;
|
||||
|
||||
list = new ArrayList<LineEntry>();
|
||||
map = new HashMap<Integer, LineEntry>();
|
||||
|
||||
build(source, 0);
|
||||
}
|
||||
|
||||
int build(Source source, int lineNumber) {
|
||||
for (Line line : source.getLines()) {
|
||||
try {
|
||||
if (line.getScope().isAddressSet()) {
|
||||
address = line.getScope().getAddress();
|
||||
}
|
||||
LineEntry lineEntry = new LineEntry(lineNumber++, address, line);
|
||||
if (lineEntry.code.length != 0) {
|
||||
if (entryAddress == -1) {
|
||||
entryAddress = address;
|
||||
}
|
||||
System.arraycopy(lineEntry.code, 0, memIoOps.getRam(), lineEntry.address, lineEntry.code.length);
|
||||
map.put(lineEntry.address, lineEntry);
|
||||
}
|
||||
list.add(lineEntry);
|
||||
|
||||
if (line.getDirective() instanceof If) {
|
||||
if (line.getInstructionObject() != null) {
|
||||
nl.grauw.glass.instructions.If ins = (nl.grauw.glass.instructions.If) line.getInstruction();
|
||||
lineNumber = build(ins.getThenSource(), lineNumber);
|
||||
if (ins.getElseSource() != null) {
|
||||
lineNumber = build(ins.getElseSource(), lineNumber);
|
||||
}
|
||||
}
|
||||
else {
|
||||
If ins = (If) line.getDirective();
|
||||
lineNumber = build(ins.getThenSource(), lineNumber);
|
||||
if (ins.getElseSource() != null) {
|
||||
lineNumber = build(ins.getElseSource(), lineNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (AssemblyException e) {
|
||||
e.addContext(line);
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
public int getEntryAddress() {
|
||||
return entryAddress;
|
||||
}
|
||||
|
||||
public LineEntry getLineAtAddress(int address) {
|
||||
return map.get(address);
|
||||
}
|
||||
|
||||
public List<LineEntry> getLines() {
|
||||
return list;
|
||||
}
|
||||
|
||||
public LineEntry getLine(int lineNumber) {
|
||||
return list.get(lineNumber);
|
||||
}
|
||||
|
||||
}
|
|
@ -38,15 +38,13 @@ import org.eclipse.swt.widgets.Composite;
|
|||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
|
||||
import com.maccasoft.tools.SourceMap.LineEntry;
|
||||
import com.maccasoft.tools.editor.EditorUtil;
|
||||
import com.maccasoft.tools.editor.LineNumbersRuler;
|
||||
import com.maccasoft.tools.editor.Token;
|
||||
import com.maccasoft.tools.editor.TokenId;
|
||||
import com.maccasoft.tools.editor.TokenMarker;
|
||||
|
||||
import nl.grauw.glass.Line;
|
||||
import nl.grauw.glass.Source;
|
||||
|
||||
public class SourceViewer {
|
||||
|
||||
Composite container;
|
||||
|
@ -62,7 +60,7 @@ public class SourceViewer {
|
|||
private Font fontBold;
|
||||
private Map<TokenId, TextStyle> styleMap = new HashMap<TokenId, TextStyle>();
|
||||
|
||||
Source source;
|
||||
SourceMap sourceMap;
|
||||
|
||||
boolean showLineNumbers = true;
|
||||
|
||||
|
@ -183,21 +181,21 @@ public class SourceViewer {
|
|||
return text;
|
||||
}
|
||||
|
||||
public Source getSource() {
|
||||
return source;
|
||||
public SourceMap getSourceMap() {
|
||||
return sourceMap;
|
||||
}
|
||||
|
||||
public void setSource(Source source) {
|
||||
this.source = source;
|
||||
public void setSourceMap(SourceMap sourceMap) {
|
||||
this.sourceMap = sourceMap;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Line line : source.getLines()) {
|
||||
sb.append(line.getSourceText());
|
||||
for (LineEntry lineEntry : sourceMap.getLines()) {
|
||||
sb.append(lineEntry.line.getSourceText());
|
||||
sb.append("\r\n");
|
||||
}
|
||||
String text = sb.toString();
|
||||
|
||||
codeRuler.setSource(source);
|
||||
codeRuler.setSourceMap(sourceMap);
|
||||
|
||||
currentLine = 0;
|
||||
this.text.setText(text);
|
||||
|
|
Ładowanie…
Reference in New Issue