kopia lustrzana https://github.com/maccasoft/z80-tools
891 wiersze
16 KiB
Java
891 wiersze
16 KiB
Java
package nl.grauw.glass;
|
|
|
|
import static org.junit.Assert.*;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.io.StringReader;
|
|
import java.util.ArrayList;
|
|
|
|
import nl.grauw.glass.Scope.SymbolNotFoundException;
|
|
import nl.grauw.glass.expressions.EvaluationException;
|
|
import nl.grauw.glass.instructions.ArgumentException;
|
|
import nl.grauw.glass.instructions.Error.ErrorDirectiveException;
|
|
|
|
import org.junit.Test;
|
|
|
|
public class SourceTest {
|
|
|
|
@Test
|
|
public void testNops() {
|
|
assertArrayEquals(b(0x00, 0x00), assemble(
|
|
" nop",
|
|
" nop"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testJumpSelf() {
|
|
assertArrayEquals(b(0x00, 0xC3, 0x01, 0x00), assemble(
|
|
" nop",
|
|
" jp $"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testJumpLabelSelf() {
|
|
assertArrayEquals(b(0x00, 0x00, 0xC3, 0x01, 0x00), assemble(
|
|
" nop",
|
|
"label: nop",
|
|
" jp label"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testJumpLabelBackward() {
|
|
assertArrayEquals(b(0x00, 0x00, 0xC3, 0x01, 0x00), assemble(
|
|
" nop",
|
|
"label: nop",
|
|
" jp label"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testJumpLabelForward() {
|
|
assertArrayEquals(b(0xC3, 0x03, 0x00), assemble(
|
|
" jp label",
|
|
"label:"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testEqu() {
|
|
assertArrayEquals(b(0x3E, 0x10), assemble(
|
|
" ld a,label",
|
|
"label: equ 10H"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testEquRegister() {
|
|
assertArrayEquals(b(0x78), assemble(
|
|
" ld a,label",
|
|
"label: equ b"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testEquIndirectRegister() {
|
|
assertArrayEquals(b(0x7E), assemble(
|
|
" ld a,label",
|
|
"label: equ (hl)"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testOrg() {
|
|
assertArrayEquals(b(0xC3, 0x32, 0x40, 0x00, 0x18, 0xFD), assemble(
|
|
" jp label",
|
|
" org 4032H",
|
|
"label:",
|
|
" nop",
|
|
" jr label"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testOrgLabel() {
|
|
assertArrayEquals(b(0xC3, 0x03, 0x00, 0x00), assemble(
|
|
" jp label",
|
|
"label: org 4032H",
|
|
" nop"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testOrgLabelBefore() {
|
|
assertArrayEquals(b(0xC3, 0x03, 0x00, 0x00), assemble(
|
|
" jp label",
|
|
"label:",
|
|
" org 4032H",
|
|
" nop"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testOrgSelfAddress() {
|
|
assertArrayEquals(b(0xC3, 0x04, 0x01, 0x00), assemble(
|
|
" jp label",
|
|
" org $ + 101H",
|
|
"label:",
|
|
" nop"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testRelativeJumpAssembly() {
|
|
assertArrayEquals(b(0x18, 0x05, 0x28, 0x03, 0x10, 0x01, 0x00), assemble(
|
|
" org 100H",
|
|
" jr label", // Because uninitialised labels use value 0, these
|
|
" jr z,label", // would be out of range if they would generate
|
|
" djnz label", // actual object code in the first pass.
|
|
" nop",
|
|
"label:"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testIndexDoubleAdd() {
|
|
assertArrayEquals(b(
|
|
0xDD, 0xA6, 0x03,
|
|
0xDD, 0xA6, 0x05,
|
|
0xDD, 0xA6, 0xFD,
|
|
0xDD, 0xA6, 0xFB,
|
|
0xDD, 0xA6, 0x06
|
|
), assemble(
|
|
" and (ix + 1 + 2)",
|
|
" and (ix + 7 - 2)",
|
|
" and (ix - 1 - 2)",
|
|
" and (ix - 7 + 2)",
|
|
" and (ix + 3 * 2)"
|
|
)
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testMacro() {
|
|
assertArrayEquals(b(0x00, 0x00), assemble(
|
|
"test: MACRO",
|
|
" nop",
|
|
" ENDM",
|
|
" test",
|
|
" test"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroAddress() {
|
|
assertArrayEquals(b(0x00, 0xC3, 0x01, 0x00, 0xC3, 0x04, 0x00), assemble(
|
|
" nop",
|
|
"test: MACRO",
|
|
" jp $",
|
|
" ENDM",
|
|
" test",
|
|
" test"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroArguments() {
|
|
assertArrayEquals(b(0x3E, 0x10, 0x3E, 0x20), assemble(
|
|
"test: MACRO arg",
|
|
" ld a,arg",
|
|
" ENDM",
|
|
" test 10H",
|
|
" test 20H"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroArgumentsTwo() {
|
|
assertArrayEquals(b(0x3E, 0x30, 0x3E, 0x77), assemble(
|
|
"test: MACRO arg1, arg2",
|
|
" ld a,arg1 + arg2",
|
|
" ENDM",
|
|
" test 10H, 20H",
|
|
" test 33H, 44H"
|
|
));
|
|
}
|
|
|
|
@Test(expected=ArgumentException.class)
|
|
public void testMacroTooManyArguments() {
|
|
assemble(
|
|
"test: MACRO",
|
|
" ENDM",
|
|
" test 10H"
|
|
);
|
|
}
|
|
|
|
@Test(expected=ArgumentException.class)
|
|
public void testMacroTooFewArguments() {
|
|
assemble(
|
|
"test: MACRO arg",
|
|
" ENDM",
|
|
" test"
|
|
);
|
|
}
|
|
|
|
@Test(expected=ArgumentException.class)
|
|
public void testMacroNonIdentifierArguments() {
|
|
assemble(
|
|
"test: MACRO (arg)",
|
|
" ENDM"
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testMacroDefaultArgument() {
|
|
assertArrayEquals(b(0x3E, 0x10, 0x3E, 0x20), assemble(
|
|
"test: MACRO arg = 10H",
|
|
" ld a,arg",
|
|
" ENDM",
|
|
" test",
|
|
" test 20H"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroDefaultFlagArgument() {
|
|
assertArrayEquals(b(0xC8, 0xC0), assemble(
|
|
"test: MACRO arg = z",
|
|
" ret arg",
|
|
" ENDM",
|
|
" test",
|
|
" test nz"
|
|
));
|
|
}
|
|
|
|
@Test(expected=AssemblyException.class)
|
|
public void testMacroNoEnd() {
|
|
assemble(
|
|
"test: MACRO"
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testMacroLabels() {
|
|
assertArrayEquals(b(0x00, 0x21, 0x04, 0x00, 0x21, 0x07, 0x00), assemble(
|
|
" nop",
|
|
"test: MACRO",
|
|
" ld hl,test2",
|
|
"test2:",
|
|
" ENDM",
|
|
" test",
|
|
" test"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroOuterScope() {
|
|
assertArrayEquals(b(0x3E, 0x11), assemble(
|
|
"test: MACRO arg",
|
|
" ld a,value + arg",
|
|
" ENDM",
|
|
" test 1H",
|
|
"value: equ 10H"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroNesting() {
|
|
assertArrayEquals(b(0x3E, 0x13, 0x3E, 0x23), assemble(
|
|
"test: MACRO arg",
|
|
"test: MACRO arg",
|
|
" ld a,20H + arg + value",
|
|
" ENDM",
|
|
" ld a,10H + arg + value",
|
|
" test arg",
|
|
"value: equ 2",
|
|
" ENDM",
|
|
" test 1H"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroTwiceWithLocalReferences() {
|
|
assertArrayEquals(b(0x3E, 0x14, 0x3E, 0x23), assemble(
|
|
"test: MACRO arg",
|
|
" ld a,10H + arg + value",
|
|
" test2 arg",
|
|
"value: equ 3",
|
|
" ENDM",
|
|
"test2: MACRO arg",
|
|
" ld a,20H + arg + value",
|
|
"value: equ 2",
|
|
" ENDM",
|
|
" test 1H"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroClosure() {
|
|
assertArrayEquals(b(0x3E, 0x14, 0x3E, 0x25), assemble(
|
|
"test: MACRO arg",
|
|
" ld a,10H + arg + value",
|
|
" test2 arg",
|
|
"value: equ 3",
|
|
" ENDM",
|
|
"test2: MACRO arg",
|
|
" ld a,20H + arg + value",
|
|
" ENDM",
|
|
"value: equ 4",
|
|
" test 1H"
|
|
));
|
|
}
|
|
|
|
@Test(expected=SymbolNotFoundException.class)
|
|
public void testMacroUnboundReference() {
|
|
assertArrayEquals(b(0x3E, 0x14, 0x3E, 0x24), assemble(
|
|
"test: MACRO arg",
|
|
" ld a,10H + arg + value",
|
|
" test2 arg",
|
|
"value: equ 3",
|
|
" ENDM",
|
|
"test2: MACRO arg",
|
|
" ld a,20H + arg + value",
|
|
" ENDM",
|
|
" test 1H"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroLabelsDereference() {
|
|
assertArrayEquals(b(0x11, 0x09, 0x00, 0x21, 0x06, 0x00, 0x21, 0x09, 0x00), assemble(
|
|
" ld de,test.z.test2",
|
|
"test: MACRO",
|
|
" ld hl,test2",
|
|
"test2:",
|
|
" ENDM",
|
|
" test",
|
|
"test.z: test"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroDefinitionDereference() {
|
|
assertArrayEquals(b(0x11, 0x03, 0x00), assemble(
|
|
" ld de,test.test2",
|
|
"test: MACRO",
|
|
" ld hl,test2",
|
|
"test2:",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroDefinitionWithArgumentsDereference() {
|
|
assertArrayEquals(b(0x11, 0x03, 0x00), assemble(
|
|
" ld de,test.test2",
|
|
"test: MACRO arg",
|
|
" ld hl,arg",
|
|
"test2:",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroDefinitionWithDefaultArgumentsDereference() {
|
|
assertArrayEquals(b(0x11, 0x03, 0x00), assemble(
|
|
" ld de,test.test2",
|
|
"test: MACRO arg = 0",
|
|
" ld hl,arg",
|
|
"test2:",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroDefinitionWithNonIntegerArgumentDereference() {
|
|
assertArrayEquals(b(0x11, 0x03, 0x00), assemble(
|
|
" ld de,test.test2",
|
|
"test: MACRO arg1, arg2",
|
|
" ld hl,arg1",
|
|
"test2:",
|
|
" ret arg2",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test(expected=EvaluationException.class)
|
|
public void testMacroDefinitionWithNonIntegerArgumentBeforeDereference() {
|
|
assertArrayEquals(b(0x11, 0x03, 0x00), assemble(
|
|
" ld de,test.test2",
|
|
"test: MACRO arg1, arg2",
|
|
" ld hl,arg1",
|
|
" ret arg2",
|
|
"test2:",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroDefinitionWithDefaultFlagArgumentBeforeDereference() {
|
|
assertArrayEquals(b(0x11, 0x01, 0x00), assemble(
|
|
" ld de,test.test2",
|
|
"test: MACRO arg = z",
|
|
" ret arg",
|
|
"test2:",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroContextArgumentDereference() {
|
|
assertArrayEquals(b(0x03), assemble(
|
|
"macro1: MACRO",
|
|
" ld hl,0",
|
|
"test:",
|
|
" ENDM",
|
|
"macro2: MACRO ?arg",
|
|
" db ?arg.test",
|
|
" ENDM",
|
|
" macro2 macro1"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroContextArgumentDereference2() {
|
|
assertArrayEquals(b(0x3E, 0x05, 0x21, 0x00, 0x00), assemble(
|
|
"macro1: MACRO",
|
|
" ld hl,0",
|
|
"test:",
|
|
" ENDM",
|
|
"macro2: MACRO ?arg",
|
|
" ld a,?arg.test",
|
|
" ENDM",
|
|
" macro2 (m1)",
|
|
"m1: macro1"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testMacroInstructionArgument() {
|
|
assertArrayEquals(b(0x3E, 0x10, 0xC9), assemble(
|
|
"test: MACRO arg",
|
|
" ld a,10H",
|
|
" arg",
|
|
" ENDM",
|
|
" test ret"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testRept() {
|
|
assertArrayEquals(b(0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF), assemble(
|
|
" REPT 3",
|
|
" nop",
|
|
" rst 38H",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testReptIndirect() {
|
|
assertArrayEquals(b(0x00, 0x00, 0x00, 0x00), assemble(
|
|
" REPT count",
|
|
" nop",
|
|
" ENDM",
|
|
"count: equ 4"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testReptParameter() {
|
|
assertArrayEquals(b(0x3E, 0x00, 0x3E, 0x01, 0x3E, 0x02), assemble(
|
|
" REPT 3, ?value",
|
|
" ld a,?value",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testReptParameterStart() {
|
|
assertArrayEquals(b(0x3E, 0x10, 0x3E, 0x11, 0x3E, 0x12), assemble(
|
|
" REPT 3, ?value, 10H",
|
|
" ld a,?value",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testReptParameterStartStep() {
|
|
assertArrayEquals(b(0x3E, 0x10, 0x3E, 0x13, 0x3E, 0x16), assemble(
|
|
" REPT 3, ?value, 10H, 3",
|
|
" ld a,?value",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testReptWithIndex() {
|
|
assertArrayEquals(b(0x21, 0x05, 0x00, 0x00, 0x00, 0x00), assemble(
|
|
" ld hl,test.2",
|
|
"test: REPT 3",
|
|
" nop",
|
|
"test: ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testReptWithLabel() {
|
|
assertArrayEquals(b(0x21, 0x06, 0x00, 0x00, 0x00, 0x00), assemble(
|
|
" ld hl,test.2.test",
|
|
"test: REPT 3",
|
|
" nop",
|
|
"test: ENDM"
|
|
));
|
|
}
|
|
|
|
@Test(expected=SymbolNotFoundException.class)
|
|
public void testReptWithLabelNoIndex() {
|
|
assemble(
|
|
" nop",
|
|
"test: REPT 2",
|
|
" nop",
|
|
"test: nop",
|
|
" ENDM",
|
|
" ld hl,test.test"
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testReptNested() {
|
|
assertArrayEquals(b(0x00, 0x01, 0x02, 0x10, 0x11, 0x12), assemble(
|
|
" REPT 2, ?value, 0, 10H",
|
|
" REPT 3, ?value2",
|
|
" db ?value + ?value2",
|
|
" ENDM",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testReptNoBody() {
|
|
assertArrayEquals(b(), assemble(
|
|
" REPT 3",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test(expected=ArgumentException.class)
|
|
public void testReptNoCount() {
|
|
assemble(
|
|
" REPT",
|
|
" ENDM"
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testIrp() {
|
|
assertArrayEquals(b(0x3E, 0x10, 0xFF, 0x3E, 0x20, 0xFF, 0x3E, 0x30, 0xFF), assemble(
|
|
" IRP ?value, 10H, 20H, 30H",
|
|
" ld a,?value",
|
|
" rst 38H",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testIrpNoValues() {
|
|
assertArrayEquals(b(), assemble(
|
|
" IRP ?value",
|
|
" ld a,?value",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testIrpNoBody() {
|
|
assertArrayEquals(b(), assemble(
|
|
" IRP ?value, 1, 2, 3",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testIrpRegisters() {
|
|
assertArrayEquals(b(0xC5, 0xD5, 0xE5, 0xF5), assemble(
|
|
" IRP ?register, bc, de, hl, af",
|
|
" push ?register",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test(expected=ArgumentException.class)
|
|
public void testIrpNoIdentifier() {
|
|
assertArrayEquals(b(), assemble(
|
|
" IRP",
|
|
" nop",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testIrpWithIndex() {
|
|
assertArrayEquals(b(0x21, 0x05, 0x00, 0x10, 0x20, 0x30), assemble(
|
|
" ld hl,test.2",
|
|
"test: IRP ?value, 10H, 20H, 30H",
|
|
"test: db ?value",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testIrpWithLabel() {
|
|
assertArrayEquals(b(0x21, 0x05, 0x00, 0x10, 0x20, 0x30), assemble(
|
|
" ld hl,test.2.test",
|
|
"test: IRP ?value, 10H, 20H, 30H",
|
|
"test: db ?value",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test(expected=SymbolNotFoundException.class)
|
|
public void testIrpWithLabelNoIndex() {
|
|
assemble(
|
|
" nop",
|
|
"test: IRP ?value, 10H, 20H, 30H",
|
|
" nop",
|
|
"test: nop",
|
|
" ENDM",
|
|
" ld hl,test.test"
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testProc() {
|
|
assertArrayEquals(b(0x21, 0x0A, 0x00, 0xC3, 0x06, 0x00, 0xFF, 0xC3, 0x0A, 0x00, 0xFF), assemble(
|
|
" ld hl,test2.test",
|
|
"test1: PROC",
|
|
" jp test",
|
|
"test: rst 38H",
|
|
" ENDP",
|
|
"test2: PROC",
|
|
" jp test",
|
|
"test: rst 38H",
|
|
" ENDP"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testIf() {
|
|
assertArrayEquals(b(0x00), assemble(
|
|
" IF 1",
|
|
" nop",
|
|
" ENDIF"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testIfThen() {
|
|
assertArrayEquals(b(0x00), assemble(
|
|
" IF 1 = 1",
|
|
" nop",
|
|
" ELSE",
|
|
" rst 38H",
|
|
" ENDIF"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testIfThenElse() {
|
|
assertArrayEquals(b(0xFF), assemble(
|
|
" IF 0 > 1",
|
|
" nop",
|
|
" ELSE",
|
|
" rst 38H",
|
|
" ENDIF"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testIfInsideRept() {
|
|
assertArrayEquals(b(0xFF, 0x00, 0xFF), assemble(
|
|
" IRP ?test, 00H, 10H, 11H",
|
|
" IF ?test = 10H",
|
|
" nop",
|
|
" ELSE",
|
|
" rst 38H",
|
|
" ENDIF",
|
|
" ENDM"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testIfWithEqu() {
|
|
assertArrayEquals(b(0xC3, 0x10, 0x00), assemble(
|
|
" IF 1",
|
|
"test: equ 10H",
|
|
" ELSE",
|
|
"test: equ 20H",
|
|
" ENDIF",
|
|
" jp test"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testIfWithLabel() {
|
|
assertArrayEquals(b(0x22, 0x22, 0xC3, 0x02, 0x00), assemble(
|
|
" IF 0",
|
|
" db 11H",
|
|
"test: ELSE",
|
|
" dw 2222H",
|
|
"test: ENDIF",
|
|
" jp test"
|
|
));
|
|
}
|
|
|
|
@Test(expected=SymbolNotFoundException.class)
|
|
public void testIfWithEquForward() {
|
|
assemble(
|
|
" jp test",
|
|
" IF 1",
|
|
"test: equ 10H",
|
|
" ENDIF"
|
|
);
|
|
}
|
|
|
|
@Test(expected=ErrorDirectiveException.class)
|
|
public void testError() {
|
|
assemble(
|
|
" ERROR"
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testErrorWithMessage() {
|
|
try {
|
|
assemble(
|
|
" ERROR \"Test\""
|
|
);
|
|
} catch (ErrorDirectiveException e) {
|
|
assertEquals("Test", e.getPlainMessage());
|
|
}
|
|
}
|
|
|
|
@Test(expected=ArgumentException.class)
|
|
public void testAnnotationNotSupported() {
|
|
assemble(
|
|
" or A 0"
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testDsVirtual() {
|
|
assertArrayEquals(b(0x3E, 0x86, 0x21, 0x12, 0x00), assemble(
|
|
" ld a,86H",
|
|
" ds VIRTUAL 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 testSection() {
|
|
assertArrayEquals(b(0x00, 0x21, 0x07, 0x00, 0x21, 0x04, 0x00, 0x86, 0x86, 0x00, 0x11, 0x07, 0x00), assemble(
|
|
" nop",
|
|
"ROM: ds 8H, 86H",
|
|
" nop",
|
|
" SECTION ROM",
|
|
" ld hl,label",
|
|
" ld hl,$",
|
|
"label: ENDS",
|
|
" ld de,label"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testSectionVirtual() {
|
|
assertArrayEquals(b(0x00, 0x00, 0x11, 0x07, 0x00), assemble(
|
|
" nop",
|
|
"RAM: ds VIRTUAL 8H",
|
|
" nop",
|
|
" SECTION RAM",
|
|
" ld hl,label",
|
|
" ld hl,$",
|
|
"label: ENDS",
|
|
" ld de,label"
|
|
));
|
|
}
|
|
|
|
@Test
|
|
public void testSectionFitsSpace() {
|
|
assemble(
|
|
"ROM: ds 3H",
|
|
" SECTION ROM",
|
|
" ld hl,$",
|
|
" ENDS"
|
|
);
|
|
}
|
|
|
|
@Test(expected=AssemblyException.class)
|
|
public void testSectionExceedsSpace() {
|
|
assemble(
|
|
"ROM: ds 2H",
|
|
" SECTION ROM",
|
|
" ld hl,$",
|
|
" ENDS"
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testSectionIndirect() {
|
|
assemble(
|
|
"ROM2: ds 3H",
|
|
"ROM: equ ROM2",
|
|
" SECTION ROM",
|
|
" ld hl,$",
|
|
" ENDS"
|
|
);
|
|
}
|
|
|
|
@Test(expected=AssemblyException.class)
|
|
public void testEndm() {
|
|
assemble(
|
|
" ENDM"
|
|
);
|
|
}
|
|
|
|
@Test(expected=AssemblyException.class)
|
|
public void testEndp() {
|
|
assemble(
|
|
" ENDP"
|
|
);
|
|
}
|
|
|
|
@Test(expected=AssemblyException.class)
|
|
public void testEnds() {
|
|
assemble(
|
|
" ENDS"
|
|
);
|
|
}
|
|
|
|
public byte[] assemble(String... sourceLines) {
|
|
StringBuilder builder = new StringBuilder();
|
|
for (String lineText : sourceLines)
|
|
builder.append(lineText).append("\n");
|
|
SourceBuilder sourceBuilder = new SourceBuilder(new ArrayList<File>());
|
|
Source source = sourceBuilder.parse(new StringReader(builder.toString()), null);
|
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
|
try {
|
|
source.assemble(output);
|
|
} catch (IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
return output.toByteArray();
|
|
}
|
|
|
|
public byte[] b(int... values) {
|
|
byte[] bytes = new byte[values.length];
|
|
for (int i = 0; i < values.length; i++)
|
|
bytes[i] = (byte)values[i];
|
|
return bytes;
|
|
}
|
|
|
|
|
|
}
|