The Micro-Executable Format support (experimental).
This commit is contained in:
parent
874217b5b7
commit
1f1f2e12ed
6
tools/z80/java/.classpath
Normal file
6
tools/z80/java/.classpath
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="output" path="bin"/>
|
||||||
|
</classpath>
|
1
tools/z80/java/.cvsignore
Normal file
1
tools/z80/java/.cvsignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
bin
|
17
tools/z80/java/.project
Normal file
17
tools/z80/java/.project
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>org.markn.contiki.z80</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
53
tools/z80/java/src/org/markn/contiki/z80/linker/Area.java
Normal file
53
tools/z80/java/src/org/markn/contiki/z80/linker/Area.java
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.markn.contiki.z80.linker;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class Area {
|
||||||
|
private short _offset;
|
||||||
|
private int _index;
|
||||||
|
private String _name;
|
||||||
|
private int _size;
|
||||||
|
/**
|
||||||
|
* Line data.
|
||||||
|
*/
|
||||||
|
private List<Line> _lines;
|
||||||
|
|
||||||
|
public Area(int index, String name, int size) {
|
||||||
|
_index = index;
|
||||||
|
_name = name;
|
||||||
|
_size = size;
|
||||||
|
_lines = new ArrayList<Line>();
|
||||||
|
}
|
||||||
|
public short getOffset() {
|
||||||
|
return _offset;
|
||||||
|
}
|
||||||
|
public int getIndex() {
|
||||||
|
return _index;
|
||||||
|
}
|
||||||
|
public String getName() {
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
public int getSize() {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
public void setOffset(short offset) {
|
||||||
|
_offset = offset;
|
||||||
|
}
|
||||||
|
public void addLine(Line line) {
|
||||||
|
_lines.add(line);
|
||||||
|
}
|
||||||
|
public void relocate(Objfile object, byte[] image) {
|
||||||
|
for (Line line: _lines) {
|
||||||
|
line.fill(object, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buf = new StringBuffer(120);
|
||||||
|
buf.append(_name);
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
}
|
132
tools/z80/java/src/org/markn/contiki/z80/linker/Line.java
Normal file
132
tools/z80/java/src/org/markn/contiki/z80/linker/Line.java
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
package org.markn.contiki.z80.linker;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class Line {
|
||||||
|
private static final Pattern WORD = Pattern.compile("([\\dA-F]{2})\\s([\\dA-F]{2})");
|
||||||
|
private static final Pattern BYTE = Pattern.compile("([\\dA-F]{2})");
|
||||||
|
|
||||||
|
private class Relocation {
|
||||||
|
private int _mode;
|
||||||
|
private int _offset;
|
||||||
|
// area index(!S) or symbol index(S)
|
||||||
|
private int _symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Area _area;
|
||||||
|
private int _address;
|
||||||
|
private List<Short> _bytes;
|
||||||
|
private List<Relocation> _relocs;
|
||||||
|
|
||||||
|
public Line(Objfile object, String tline, String rline) {
|
||||||
|
_relocs = new ArrayList<Relocation>(16);
|
||||||
|
_bytes = new ArrayList<Short>(16);
|
||||||
|
rline = rline.substring(8);
|
||||||
|
int areaindex = getWord(rline);
|
||||||
|
_area = object.getArea(areaindex);
|
||||||
|
if (_area == null) {
|
||||||
|
throw new IllegalArgumentException("no such area:" + areaindex);
|
||||||
|
}
|
||||||
|
_area.addLine(this);
|
||||||
|
tline = tline.substring(2);
|
||||||
|
_address = getWord(tline);
|
||||||
|
tline = tline.substring(3);
|
||||||
|
while (true) {
|
||||||
|
if (tline.length() < 3) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tline = tline.substring(3);
|
||||||
|
_bytes.add(getByte(tline));
|
||||||
|
}
|
||||||
|
// relocation line
|
||||||
|
while (true) {
|
||||||
|
if (rline.length() < 6) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Relocation reloc = new Relocation();
|
||||||
|
_relocs.add(reloc);
|
||||||
|
rline = rline.substring(6);
|
||||||
|
reloc._mode = getByte(rline);
|
||||||
|
rline = rline.substring(3);
|
||||||
|
reloc._offset = getByte(rline) - 2;
|
||||||
|
rline = rline.substring(3);
|
||||||
|
reloc._symbol = getWord(rline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private int getWord(String line) {
|
||||||
|
Matcher m = WORD.matcher(line);
|
||||||
|
if (!m.find()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
String hexstr = m.group(2) + m.group(1);
|
||||||
|
return Integer.parseInt(hexstr, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
private short getByte(String line) {
|
||||||
|
Matcher m = BYTE.matcher(line);
|
||||||
|
if (!m.find()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
String hexstr = m.group(1);
|
||||||
|
return Short.parseShort(hexstr, 16);
|
||||||
|
}
|
||||||
|
public void fill(Objfile object, byte[] image) {
|
||||||
|
int address = _address + _area.getOffset();
|
||||||
|
for (Relocation reloc : _relocs) {
|
||||||
|
int target = 0;
|
||||||
|
byte mode = 0; // Ext/Int MSB/LSB Byte/Word
|
||||||
|
RelocationInformation info = new RelocationInformation();
|
||||||
|
if ((reloc._mode & 2) > 0) {
|
||||||
|
// external
|
||||||
|
Symbol symbol = object.getSymbol(reloc._symbol);
|
||||||
|
target = symbol.calcOffset();
|
||||||
|
System.out.printf("%s %04X=>%04X\n", symbol, symbol.getOffset(), target);
|
||||||
|
if (symbol.isAbsolute()) {
|
||||||
|
mode |= 0x80;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// internal
|
||||||
|
Area area = object.getArea(reloc._symbol);
|
||||||
|
int offset = area.getOffset();
|
||||||
|
short source = (short) ((_bytes.get(reloc._offset + 1) << 8) + _bytes.get(reloc._offset));
|
||||||
|
target = (short) (source + offset);
|
||||||
|
// TODO: save relocation information
|
||||||
|
System.out.printf("%s:%04X=>%04X\n", area, source, target);
|
||||||
|
}
|
||||||
|
info.setAddress(address);
|
||||||
|
if ((reloc._mode & 1) > 0) {
|
||||||
|
// byte mode
|
||||||
|
if ((reloc._mode & 128) > 0) {
|
||||||
|
// MSB
|
||||||
|
mode |= 0x60;
|
||||||
|
_bytes.set(reloc._offset, (short) (target >> 8));
|
||||||
|
_bytes.set(reloc._offset + 1, (short) -1);
|
||||||
|
} else {
|
||||||
|
// LSB
|
||||||
|
mode |= 0x20;
|
||||||
|
_bytes.set(reloc._offset, (short) -1);
|
||||||
|
_bytes.set(reloc._offset, (short) (target & 0xff));
|
||||||
|
}
|
||||||
|
address++;
|
||||||
|
} else {
|
||||||
|
// word mode
|
||||||
|
_bytes.set(reloc._offset, (short) (target & 0xff));
|
||||||
|
_bytes.set(reloc._offset + 1, (short) (target >> 8));
|
||||||
|
address += 2;
|
||||||
|
}
|
||||||
|
info.setMode(mode);
|
||||||
|
info.setData(target);
|
||||||
|
object.getLinker().addRelocation(info);
|
||||||
|
}
|
||||||
|
address = _address + _area.getOffset();
|
||||||
|
for (int data : _bytes) {
|
||||||
|
if (data >= 0) {
|
||||||
|
image[address++] = (byte) data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
192
tools/z80/java/src/org/markn/contiki/z80/linker/Linker.java
Normal file
192
tools/z80/java/src/org/markn/contiki/z80/linker/Linker.java
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
package org.markn.contiki.z80.linker;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class Linker {
|
||||||
|
private static final String _DATA = "_DATA";
|
||||||
|
|
||||||
|
private static final String _GSINIT = "_GSINIT";
|
||||||
|
|
||||||
|
private static final String _CODE = "_CODE";
|
||||||
|
|
||||||
|
private static final Pattern SYMLINE = Pattern.compile("^00:([\\dA-F]{4})\\s(\\w+)");
|
||||||
|
|
||||||
|
public static void main(String[] arg) throws IOException {
|
||||||
|
File target = new File(arg[0]);
|
||||||
|
if (!target.exists()) {
|
||||||
|
System.out.println(arg[0] + " is no exist.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Linker linker = new Linker();
|
||||||
|
linker.prepare();
|
||||||
|
linker.make(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Symbol> _symbols;
|
||||||
|
|
||||||
|
private Map<File, Objfile> _objfiles;
|
||||||
|
|
||||||
|
private List<RelocationInformation> _relocations;
|
||||||
|
|
||||||
|
public Linker() {
|
||||||
|
_symbols = new HashMap<String, Symbol>();
|
||||||
|
_objfiles = new HashMap<File, Objfile>();
|
||||||
|
_relocations = new ArrayList<RelocationInformation>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepare() throws IOException {
|
||||||
|
loadSymfile("contiki.sym");
|
||||||
|
loadLibfile("contiki-pc-6001.lib");
|
||||||
|
loadLibfile("c:/dev/sdcc/lib/z80/z80.lib");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void make(File file) throws IOException {
|
||||||
|
List<Objfile> required = new ArrayList<Objfile>();
|
||||||
|
Objfile object = _objfiles.get(file);
|
||||||
|
make(required, object);
|
||||||
|
short codeSize = 0;
|
||||||
|
for (Objfile obj : required) {
|
||||||
|
obj.setAreaOffset(_CODE, codeSize);
|
||||||
|
codeSize += obj.getAreaSize(_CODE);
|
||||||
|
}
|
||||||
|
short gsinitSize = 0;
|
||||||
|
short gsinitOffset = codeSize;
|
||||||
|
for (Objfile obj : required) {
|
||||||
|
obj.setAreaOffset(_GSINIT, gsinitOffset);
|
||||||
|
gsinitSize += obj.getAreaSize(_GSINIT);
|
||||||
|
gsinitOffset += obj.getAreaSize(_GSINIT);
|
||||||
|
}
|
||||||
|
// add space for C9 (ret)
|
||||||
|
gsinitSize++;
|
||||||
|
gsinitOffset++;
|
||||||
|
short dataSize = 0;
|
||||||
|
short dataOffset = gsinitOffset;
|
||||||
|
for (Objfile obj : required) {
|
||||||
|
obj.setAreaOffset(_DATA, dataOffset);
|
||||||
|
dataSize += obj.getAreaSize(_DATA);
|
||||||
|
dataOffset += obj.getAreaSize(_DATA);
|
||||||
|
}
|
||||||
|
byte[] image = new byte[gsinitOffset];
|
||||||
|
for (Objfile obj : required) {
|
||||||
|
System.out.printf("Relocating: %s %s=%04X %s=%04X %s=%04X\n", obj.getFile(),
|
||||||
|
_CODE, obj.getArea(_CODE).getOffset(),
|
||||||
|
_GSINIT, obj.getArea(_GSINIT).getOffset(),
|
||||||
|
_DATA, obj.getArea(_DATA).getOffset());
|
||||||
|
obj.relocate(_CODE, image);
|
||||||
|
obj.relocate(_GSINIT, image);
|
||||||
|
}
|
||||||
|
// the end of GSINIT
|
||||||
|
image[image.length - 1] = (byte) 0xc9;
|
||||||
|
|
||||||
|
System.out.println("_CODE:" + Integer.toHexString(codeSize));
|
||||||
|
System.out.println("_GSINIT:" + Integer.toHexString(gsinitSize));
|
||||||
|
System.out.println("_DATA:" + Integer.toHexString(dataSize));
|
||||||
|
dump(image, dataOffset);
|
||||||
|
out(new File("tmp.out"), image, dataOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dump(byte[] image, int size) {
|
||||||
|
int address = 0;
|
||||||
|
System.out.printf("size:%04X", size);
|
||||||
|
while (address < image.length) {
|
||||||
|
if (address % 16 == 0) {
|
||||||
|
System.out.printf("\n%04X:", address);
|
||||||
|
}
|
||||||
|
System.out.printf("%02x ", image[address++]);
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Relocations:" + _relocations.size());
|
||||||
|
for (RelocationInformation reloc : _relocations) {
|
||||||
|
System.out.println(reloc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void out(File file, byte[] image, int size) throws IOException {
|
||||||
|
FileOutputStream stream = new FileOutputStream(file);
|
||||||
|
stream.write(size & 0xff);
|
||||||
|
stream.write(size >> 8);
|
||||||
|
stream.write(image);
|
||||||
|
stream.write(_relocations.size() & 0xff);
|
||||||
|
stream.write(_relocations.size() >> 8);
|
||||||
|
for (RelocationInformation reloc : _relocations) {
|
||||||
|
reloc.write(stream);
|
||||||
|
}
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void make(List<Objfile> objects, Objfile obj) {
|
||||||
|
if (objects.contains(obj)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
objects.add(obj);
|
||||||
|
Set<File> required = obj.getRequiredFiles();
|
||||||
|
for (File require : required) {
|
||||||
|
make(objects, _objfiles.get(require));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadLibfile(String filename) throws IOException {
|
||||||
|
File file = new File(filename);
|
||||||
|
File dir = file.getParentFile();
|
||||||
|
BufferedReader isr = new BufferedReader(new FileReader(file));
|
||||||
|
while (true) {
|
||||||
|
String line = isr.readLine();
|
||||||
|
if (line == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
File objfile = new File(dir, line);
|
||||||
|
Objfile object = new Objfile(this, objfile);
|
||||||
|
_objfiles.put(objfile, object);
|
||||||
|
object.analyze();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSymbol(String name, Symbol symbol) {
|
||||||
|
if (!_symbols.containsKey(name)) {
|
||||||
|
_symbols.put(name, symbol);
|
||||||
|
} else if (_symbols.get(name).getArea() != null) {
|
||||||
|
System.out.println("Warning: duplicate symbol:" + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRelocation(RelocationInformation info) {
|
||||||
|
_relocations.add(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Symbol getSymbol(String name) {
|
||||||
|
return _symbols.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadSymfile(String filename) throws IOException {
|
||||||
|
File file = new File(filename);
|
||||||
|
BufferedReader isr = new BufferedReader(new FileReader(file));
|
||||||
|
while (true) {
|
||||||
|
String line = isr.readLine();
|
||||||
|
if (line == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (line.startsWith(";")) {
|
||||||
|
// comment
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Matcher m = SYMLINE.matcher(line);
|
||||||
|
if (!m.find()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Symbol symbol = new Symbol(file, Integer.parseInt(m.group(1), 16));
|
||||||
|
_symbols.put(m.group(2), symbol);
|
||||||
|
}
|
||||||
|
isr.close();
|
||||||
|
}
|
||||||
|
}
|
175
tools/z80/java/src/org/markn/contiki/z80/linker/Objfile.java
Normal file
175
tools/z80/java/src/org/markn/contiki/z80/linker/Objfile.java
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
package org.markn.contiki.z80.linker;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author markn
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Objfile {
|
||||||
|
private static final Pattern REFLINE = Pattern.compile("^S\\s(\\w+)\\sRef([\\dA-F]{4})");
|
||||||
|
private static final Pattern DEFLINE = Pattern.compile("^S\\s(\\w+)\\sDef([\\dA-F]{4})");
|
||||||
|
private static final Pattern AREALINE = Pattern.compile("^A\\s(\\w+)\\ssize\\s([\\dA-F]+)");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent object.
|
||||||
|
*/
|
||||||
|
private Linker _linker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A file that this object indicates.
|
||||||
|
*/
|
||||||
|
private File _file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* References to be imported.
|
||||||
|
*/
|
||||||
|
private List<String> _refs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Area name and its size.
|
||||||
|
*/
|
||||||
|
private Map<String, Area> _areas;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param linker
|
||||||
|
* @param file
|
||||||
|
*/
|
||||||
|
public Objfile(Linker linker, File file) {
|
||||||
|
_linker = linker;
|
||||||
|
_file = file;
|
||||||
|
_refs = new ArrayList<String>();
|
||||||
|
_areas = new HashMap<String, Area>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getFile() {
|
||||||
|
return _file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<File> getRequiredFiles() {
|
||||||
|
Set<File> files = new HashSet<File>();
|
||||||
|
for (String ref : _refs) {
|
||||||
|
if (_linker.getSymbol(ref).isAbsolute()) {
|
||||||
|
// no need to link
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Symbol symbol = _linker.getSymbol(ref);
|
||||||
|
if (symbol != null) {
|
||||||
|
files.add(symbol.getFile());
|
||||||
|
} else {
|
||||||
|
System.out.println("undefined symbol:" + ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Linker getLinker() {
|
||||||
|
return _linker;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Area getArea(String name) {
|
||||||
|
return _areas.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAreaSize(String name) {
|
||||||
|
Area area = _areas.get(name);
|
||||||
|
if (area != null) {
|
||||||
|
return area.getSize();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAreaOffset(String name, short offset) {
|
||||||
|
Area area = _areas.get(name);
|
||||||
|
if (area != null) {
|
||||||
|
area.setOffset(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void analyze() throws IOException {
|
||||||
|
System.out.println("analyzing:" + _file);
|
||||||
|
int areaindex = 0;
|
||||||
|
BufferedReader isr = new BufferedReader(new FileReader(_file));
|
||||||
|
String tline = null;
|
||||||
|
Area area = null;
|
||||||
|
while (true) {
|
||||||
|
String line = isr.readLine();
|
||||||
|
if (line == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Matcher m = AREALINE.matcher(line);
|
||||||
|
if (m.find()) {
|
||||||
|
String areaname = m.group(1);
|
||||||
|
area = new Area(areaindex, areaname, Integer.parseInt(m.group(2), 16));
|
||||||
|
_areas.put(areaname, area);
|
||||||
|
areaindex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
m = REFLINE.matcher(line);
|
||||||
|
if (m.find()) {
|
||||||
|
_refs.add(m.group(1));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
m = DEFLINE.matcher(line);
|
||||||
|
if (m.find()) {
|
||||||
|
String symbolname = m.group(1);
|
||||||
|
int address = Integer.parseInt(m.group(2), 16);
|
||||||
|
Symbol symbol = new Symbol(_file, area, (short) address);
|
||||||
|
_linker.addSymbol(symbolname, symbol);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (line.startsWith("T")) {
|
||||||
|
// process T line
|
||||||
|
tline = line;
|
||||||
|
}
|
||||||
|
if (line.startsWith("R")) {
|
||||||
|
// process R line
|
||||||
|
if (tline == null) {
|
||||||
|
System.out.println("wrong format as object file:" + _file);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
new Line(this, tline, line);
|
||||||
|
tline = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isr.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Area getArea(int index) {
|
||||||
|
for (Area area : _areas.values()) {
|
||||||
|
if (area.getIndex() == index) {
|
||||||
|
return area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Symbol getSymbol(int index) {
|
||||||
|
String name = _refs.get(index);
|
||||||
|
return _linker.getSymbol(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void relocate(String areaname, byte[] image) {
|
||||||
|
Area area = _areas.get(areaname);
|
||||||
|
if (area != null) {
|
||||||
|
area.relocate(this, image);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
System.out.println("no such area:" + areaname + " on " + _file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.markn.contiki.z80.linker;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class RelocationInformation {
|
||||||
|
private byte _mode;
|
||||||
|
private int _address;
|
||||||
|
private int _data;
|
||||||
|
public byte getMode() {
|
||||||
|
return _mode;
|
||||||
|
}
|
||||||
|
public void setMode(byte mode) {
|
||||||
|
this._mode = mode;
|
||||||
|
}
|
||||||
|
public int getAddress() {
|
||||||
|
return _address;
|
||||||
|
}
|
||||||
|
public void setAddress(int address) {
|
||||||
|
_address = address;
|
||||||
|
}
|
||||||
|
public int getData() {
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
public void setData(int data) {
|
||||||
|
_data = data;
|
||||||
|
}
|
||||||
|
public void write(OutputStream stream) throws IOException {
|
||||||
|
stream.write(_mode);
|
||||||
|
stream.write(_address & 0xff);
|
||||||
|
stream.write(_address >> 8);
|
||||||
|
stream.write(_data & 0xff);
|
||||||
|
stream.write(_data >> 8);
|
||||||
|
}
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
buf.append((_mode & 0x80) > 0 ? 'E' : 'I');
|
||||||
|
if ((_mode & 0x60) == 0x60) {
|
||||||
|
buf.append("MB");
|
||||||
|
} else if ((_mode & 0x20) > 0) {
|
||||||
|
buf.append("LB");
|
||||||
|
} else {
|
||||||
|
buf.append("_W");
|
||||||
|
}
|
||||||
|
// buf.append((_mode & 0x60) > 0 ? 'M' : 'L');
|
||||||
|
// buf.append((_mode & 0x20) > 0 ? 'B' : 'W');
|
||||||
|
buf.append(String.format(":%04X:%04X", _address, _data));
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
52
tools/z80/java/src/org/markn/contiki/z80/linker/Symbol.java
Normal file
52
tools/z80/java/src/org/markn/contiki/z80/linker/Symbol.java
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
package org.markn.contiki.z80.linker;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class Symbol {
|
||||||
|
private File _file;
|
||||||
|
private Area _area;
|
||||||
|
private int _offset;
|
||||||
|
public Symbol(File file, int offset) {
|
||||||
|
this(file, null, offset);
|
||||||
|
}
|
||||||
|
public Symbol(File file, Area area, int offset) {
|
||||||
|
this._file = file;
|
||||||
|
this._area = area;
|
||||||
|
this._offset = offset;
|
||||||
|
}
|
||||||
|
public File getFile() {
|
||||||
|
return _file;
|
||||||
|
}
|
||||||
|
public Area getArea() {
|
||||||
|
return _area;
|
||||||
|
}
|
||||||
|
public boolean isAbsolute() {
|
||||||
|
return _area == null;
|
||||||
|
}
|
||||||
|
public int getOffset() {
|
||||||
|
return _offset;
|
||||||
|
}
|
||||||
|
public int calcOffset() {
|
||||||
|
if (isAbsolute()) {
|
||||||
|
return _offset;
|
||||||
|
} else {
|
||||||
|
return _offset + _area.getOffset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuffer buf = new StringBuffer(120);
|
||||||
|
buf.append(_file.toString());
|
||||||
|
buf.append(':');
|
||||||
|
if (_area != null) {
|
||||||
|
buf.append(_area);
|
||||||
|
} else {
|
||||||
|
buf.append("Absolute");
|
||||||
|
}
|
||||||
|
buf.append(':');
|
||||||
|
buf.append(Integer.toHexString(_offset));
|
||||||
|
return buf.toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue