Refactored ds and fill directives

master
Marco Maccaferri 2018-12-18 08:30:34 +01:00
rodzic f5feadea32
commit 210919aa89
6 zmienionych plików z 114 dodań i 40 usunięć

Wyświetl plik

@ -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",

Wyświetl plik

@ -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

Wyświetl plik

@ -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();
}

Wyświetl plik

@ -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));
}
}
}

Wyświetl plik

@ -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()];

Wyświetl plik

@ -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()];