kopia lustrzana https://github.com/maccasoft/z80-tools
Refactored ds and fill directives
rodzic
f5feadea32
commit
210919aa89
|
@ -692,27 +692,36 @@ public class SourceTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDsVirtual() {
|
||||
public void testDs() {
|
||||
assertArrayEquals(b(0x3E, 0x86, 0x21, 0x12, 0x00), assemble(
|
||||
" ld a,86H",
|
||||
" ds VIRTUAL 10H",
|
||||
" ds 10H",
|
||||
" ld hl,$"));
|
||||
}
|
||||
|
||||
@Test(expected = ArgumentException.class)
|
||||
public void testDsVirtualWithFill() {
|
||||
assemble(
|
||||
" ds VIRTUAL 10H, 0");
|
||||
}
|
||||
|
||||
@Test(expected = ArgumentException.class)
|
||||
public void testDsUnknownAnnotation() {
|
||||
assemble(
|
||||
" ds UNKNOWN 10H");
|
||||
@Test
|
||||
public void testDsWithFill() {
|
||||
assertArrayEquals(b(0x3E, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x0A, 0x00), assemble(
|
||||
" ld a,86H",
|
||||
" ds 8H, 0H",
|
||||
" ld hl,$"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSection() {
|
||||
public void testSectionWithFill() {
|
||||
assertArrayEquals(b(0x00, 0x21, 0x07, 0x00, 0x21, 0x04, 0x00, 0x86, 0x86, 0x00, 0x11, 0x07, 0x00), assemble(
|
||||
" nop",
|
||||
"ROM: fill 8H, 86H",
|
||||
" nop",
|
||||
" SECTION ROM",
|
||||
" ld hl,label",
|
||||
" ld hl,$",
|
||||
"label: ENDS",
|
||||
" ld de,label"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSectionWithDs() {
|
||||
assertArrayEquals(b(0x00, 0x21, 0x07, 0x00, 0x21, 0x04, 0x00, 0x86, 0x86, 0x00, 0x11, 0x07, 0x00), assemble(
|
||||
" nop",
|
||||
"ROM: ds 8H, 86H",
|
||||
|
@ -728,7 +737,7 @@ public class SourceTest {
|
|||
public void testSectionVirtual() {
|
||||
assertArrayEquals(b(0x00, 0x00, 0x11, 0x07, 0x00), assemble(
|
||||
" nop",
|
||||
"RAM: ds VIRTUAL 8H",
|
||||
"RAM: ds 8H",
|
||||
" nop",
|
||||
" SECTION RAM",
|
||||
" ld hl,label",
|
||||
|
|
|
@ -246,9 +246,9 @@ public class InstructionTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDs() {
|
||||
assertArrayEquals(b(0x00, 0x00, 0x00, 0x00, 0x00), parse("ds 5H"));
|
||||
assertArrayEquals(b(0x47, 0x47, 0x47, 0x47, 0x47), parse("ds 5H,47H"));
|
||||
public void testFill() {
|
||||
assertArrayEquals(b(0x00, 0x00, 0x00, 0x00, 0x00), parse("fill 5H"));
|
||||
assertArrayEquals(b(0x47, 0x47, 0x47, 0x47, 0x47), parse("fill 5H,47H"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.util.List;
|
|||
import nl.grauw.glass.directives.Directive;
|
||||
import nl.grauw.glass.directives.Ds;
|
||||
import nl.grauw.glass.directives.Equ;
|
||||
import nl.grauw.glass.directives.Fill;
|
||||
import nl.grauw.glass.directives.If;
|
||||
import nl.grauw.glass.directives.Incbin;
|
||||
import nl.grauw.glass.directives.Include;
|
||||
|
@ -221,6 +222,11 @@ public class SourceBuilder {
|
|||
throw new AssemblyException("Unexpected " + line.getMnemonic() + ".");
|
||||
}
|
||||
return new Instruction();
|
||||
case "fill":
|
||||
case "FILL":
|
||||
case ".fill":
|
||||
case ".FILL":
|
||||
return new Fill();
|
||||
default:
|
||||
return new Instruction();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package nl.grauw.glass.directives;
|
||||
|
||||
import nl.grauw.glass.Line;
|
||||
import nl.grauw.glass.Scope;
|
||||
import nl.grauw.glass.expressions.SectionContextLiteral;
|
||||
|
||||
public class Fill extends Directive {
|
||||
|
||||
@Override
|
||||
public void register(Scope scope, Line line) {
|
||||
nl.grauw.glass.instructions.Fill fill = new nl.grauw.glass.instructions.Fill();
|
||||
line.setInstruction(fill);
|
||||
if (line.getLabel() != null) {
|
||||
scope.addSymbol(line.getLabel(), new SectionContextLiteral(line.getScope(), fill));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -10,8 +10,6 @@ import java.util.List;
|
|||
import nl.grauw.glass.AssemblyException;
|
||||
import nl.grauw.glass.Scope;
|
||||
import nl.grauw.glass.expressions.Expression;
|
||||
import nl.grauw.glass.expressions.Identifier;
|
||||
import nl.grauw.glass.expressions.IntegerLiteral;
|
||||
import nl.grauw.glass.expressions.Schema;
|
||||
import nl.grauw.glass.expressions.SectionContext;
|
||||
|
||||
|
@ -30,30 +28,23 @@ public class Ds extends InstructionFactory implements SectionContext {
|
|||
@Override
|
||||
public InstructionObject createObject(Scope context, Expression arguments) {
|
||||
if (ARGUMENTS_N.check(arguments)) {
|
||||
return new Ds_N_N(context, arguments.getAnnotation(),
|
||||
arguments.getAnnotee(), IntegerLiteral.ZERO);
|
||||
return new Ds_N_N(context, arguments.getElement(0), null);
|
||||
}
|
||||
if (ARGUMENTS_N_N.check(arguments)) {
|
||||
return new Ds_N_N(context, null, arguments.getElement(0), arguments.getElement(1));
|
||||
return new Ds_N_N(context, arguments.getElement(0), arguments.getElement(1));
|
||||
}
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
public class Ds_N_N extends InstructionObject {
|
||||
|
||||
private final boolean virtual;
|
||||
private final Expression size;
|
||||
private final Expression value;
|
||||
|
||||
public Ds_N_N(Scope context, Identifier annotation, Expression size, Expression value) {
|
||||
public Ds_N_N(Scope context, Expression size, Expression value) {
|
||||
super(context);
|
||||
this.virtual = annotation != null && ("virtual".equals(annotation.getName()) || "VIRTUAL".equals(annotation.getName()));
|
||||
this.size = size;
|
||||
this.value = value;
|
||||
|
||||
if (annotation != null && !virtual) {
|
||||
throw new ArgumentException("Unsupported annotation: " + annotation.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,16 +69,14 @@ public class Ds extends InstructionFactory implements SectionContext {
|
|||
bytes.length + " bytes, available: " + size.getInteger() + " bytes).");
|
||||
}
|
||||
|
||||
if (virtual) {
|
||||
return;
|
||||
if (value != null) {
|
||||
output.write(bytes);
|
||||
|
||||
byte[] padding = new byte[size.getInteger() - bytes.length];
|
||||
Arrays.fill(padding, (byte) value.getInteger());
|
||||
|
||||
output.write(padding);
|
||||
}
|
||||
|
||||
output.write(bytes);
|
||||
|
||||
byte[] padding = new byte[size.getInteger() - bytes.length];
|
||||
Arrays.fill(padding, (byte) value.getInteger());
|
||||
|
||||
output.write(padding);
|
||||
}
|
||||
|
||||
public byte[] getSectionBytes() throws IOException {
|
||||
|
@ -100,7 +89,7 @@ public class Ds extends InstructionFactory implements SectionContext {
|
|||
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
if (virtual) {
|
||||
if (value == null) {
|
||||
return new byte[] {};
|
||||
}
|
||||
byte[] bytes = new byte[size.getInteger()];
|
||||
|
|
|
@ -1,17 +1,36 @@
|
|||
package nl.grauw.glass.instructions;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import nl.grauw.glass.AssemblyException;
|
||||
import nl.grauw.glass.Scope;
|
||||
import nl.grauw.glass.expressions.Expression;
|
||||
import nl.grauw.glass.expressions.IntegerLiteral;
|
||||
import nl.grauw.glass.expressions.Schema;
|
||||
import nl.grauw.glass.expressions.SectionContext;
|
||||
|
||||
public class Fill extends InstructionFactory {
|
||||
public class Fill extends InstructionFactory implements SectionContext {
|
||||
|
||||
public static Schema ARGUMENTS_N = new Schema(Schema.INTEGER);
|
||||
public static Schema ARGUMENTS_N_N = new Schema(Schema.INTEGER, Schema.INTEGER);
|
||||
|
||||
private final List<Section> sections = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void addSection(Section section) {
|
||||
sections.add(section);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstructionObject createObject(Scope context, Expression arguments) {
|
||||
if (ARGUMENTS_N.check(arguments)) {
|
||||
return new Fill_N_N(context, arguments.getElement(0), IntegerLiteral.ZERO);
|
||||
}
|
||||
if (ARGUMENTS_N_N.check(arguments)) {
|
||||
return new Fill_N_N(context, arguments.getElement(0), arguments.getElement(1));
|
||||
}
|
||||
|
@ -29,11 +48,44 @@ public class Fill extends InstructionFactory {
|
|||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int resolve(int address) {
|
||||
int innerAddress = address;
|
||||
for (Section section : sections) {
|
||||
innerAddress = section.getSource().resolve(innerAddress);
|
||||
}
|
||||
return super.resolve(address);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return size.getInteger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateObjectCode(OutputStream output) throws IOException {
|
||||
byte[] bytes = getSectionBytes();
|
||||
if (bytes.length > size.getInteger()) {
|
||||
throw new AssemblyException("Section size exceeds space (required: " +
|
||||
bytes.length + " bytes, available: " + size.getInteger() + " bytes).");
|
||||
}
|
||||
|
||||
output.write(bytes);
|
||||
|
||||
byte[] padding = new byte[size.getInteger() - bytes.length];
|
||||
Arrays.fill(padding, (byte) value.getInteger());
|
||||
|
||||
output.write(padding);
|
||||
}
|
||||
|
||||
public byte[] getSectionBytes() throws IOException {
|
||||
ByteArrayOutputStream sourceByteStream = new ByteArrayOutputStream(size.getInteger());
|
||||
for (Section section : sections) {
|
||||
section.getSource().generateObjectCode(sourceByteStream);
|
||||
}
|
||||
return sourceByteStream.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() {
|
||||
byte[] bytes = new byte[size.getInteger()];
|
||||
|
|
Ładowanie…
Reference in New Issue