package org.reasm.m68k.assembly.internal; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import org.reasm.AssemblyMessage; import org.reasm.commons.messages.UnrecognizedEscapeSequenceWarningMessage; import org.reasm.m68k.M68KArchitecture; import org.reasm.m68k.messages.*; import org.reasm.messages.DirectiveRequiresLabelErrorMessage; import org.reasm.messages.ParseErrorMessage; import org.reasm.messages.UnknownEncodingNameErrorMessage; import org.reasm.messages.UnknownMnemonicErrorMessage; import org.reasm.messages.UnresolvedSymbolReferenceErrorMessage; import org.reasm.messages.WrongNumberOfArgumentsErrorMessage; import org.reasm.source.parseerrors.UnterminatedStringParseError; /** * Test class for short M68000 programs. * * @author Francis Gagné */ @RunWith(Parameterized.class) public class ProgramsTest extends BaseProgramsTest { @Nonnull private static final AssemblyMessage ALIGNMENT_MUST_NOT_BE_ZERO_OR_NEGATIVE = new AlignmentMustNotBeZeroOrNegativeErrorMessage(); @Nonnull private static final AssemblyMessage WRONG_NUMBER_OF_ARGUMENTS = new WrongNumberOfArgumentsErrorMessage(); @Nonnull private static final ArrayList<Object[]> TEST_DATA = new ArrayList<>(); static { // ALIGN addDataItem(" ALIGN", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem(" ALIGN -1", 2, NO_DATA, ALIGNMENT_MUST_NOT_BE_ZERO_OR_NEGATIVE); addDataItem(" ALIGN 0", 2, NO_DATA, ALIGNMENT_MUST_NOT_BE_ZERO_OR_NEGATIVE); addDataItem(" ALIGN 1", 2, NO_DATA); addDataItem(" ALIGN 2", 2, NO_DATA); addDataItem(" ALIGN UNDEFINED", 2, NO_DATA, UNDEFINED_SYMBOL); addDataItem(" ALIGN ~", 2, NO_DATA, new InvalidExpressionErrorMessage("~")); addDataItem(" ALIGN.B 1", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED); addDataItem(" DC.B $77\n ALIGN 2", 3, new byte[] { 0x77, 0 }); addDataItem(" DC.B $77\n ALIGN +2", 3, new byte[] { 0x77, 0 }); addDataItem(" DC.B $77,$66\n ALIGN 2", 3, new byte[] { 0x77, 0x66 }); addDataItem(" DC.B $77,$66,$55\n ALIGN 2\n DC.B $44", 4, new byte[] { 0x77, 0x66, 0x55, 0, 0x44 }); addDataItem(" DC.B $77,$66,$55\n ALIGN 16\n DC.B $44", 4, new byte[] { 0x77, 0x66, 0x55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x44 }); // CNOP addDataItem(" CNOP", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem(" CNOP 0", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem(" CNOP 0,-1", 2, NO_DATA, ALIGNMENT_MUST_NOT_BE_ZERO_OR_NEGATIVE); addDataItem(" CNOP 0,0", 2, NO_DATA, ALIGNMENT_MUST_NOT_BE_ZERO_OR_NEGATIVE); addDataItem(" CNOP 0,1", 2, NO_DATA); addDataItem(" CNOP 0,2", 2, NO_DATA); addDataItem(" CNOP 0,UNDEFINED", 2, NO_DATA, UNDEFINED_SYMBOL); addDataItem(" CNOP 0,~", 2, NO_DATA, new InvalidExpressionErrorMessage("~")); addDataItem(" CNOP -1,2", 2, NO_DATA, new OffsetMustNotBeNegativeErrorMessage()); addDataItem(" CNOP 4,2", 2, new byte[] { 0, 0, 0, 0 }); addDataItem(" CNOP UNDEFINED,2", 2, NO_DATA, UNDEFINED_SYMBOL); addDataItem(" CNOP ~,2", 2, NO_DATA, new InvalidExpressionErrorMessage("~")); addDataItem(" CNOP.B 0,1", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED); addDataItem(" DC.B $77\n CNOP 0,2", 3, new byte[] { 0x77, 0 }); addDataItem(" DC.B $77\n CNOP 0,+2", 3, new byte[] { 0x77, 0 }); addDataItem(" DC.B $77,$66\n CNOP 0,2", 3, new byte[] { 0x77, 0x66 }); addDataItem(" DC.B $77,$66,$55\n CNOP 0,2\n DC.B $44", 4, new byte[] { 0x77, 0x66, 0x55, 0, 0x44 }); addDataItem(" DC.B $77,$66,$55\n CNOP 0,16\n DC.B $44", 4, new byte[] { 0x77, 0x66, 0x55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x44 }); addDataItem(" DCB.B 20,$FF\n CNOP 10,16\n DC.B $77", 4, new byte[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0x77 }); addDataItem(" DCB.B 20,$FF\n CNOP 2,16\n DC.B $77", 4, new byte[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x77 }); // DEPHASE final DephaseWithoutPhaseErrorMessage dephaseWithoutPhase = new DephaseWithoutPhaseErrorMessage(); addDataItem(" DEPHASE", 2, NO_DATA, dephaseWithoutPhase); addDataItem(" DEPHASE 0", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS, dephaseWithoutPhase); addDataItem(" DEPHASE.W", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED, dephaseWithoutPhase); // DO addDataItem(" DO\n DC.W $1234\n UNTIL", 6, new byte[] { 0x12, 0x34 }, WRONG_NUMBER_OF_OPERANDS); addDataItem(" DO\n DC.W $1234\n UNTIL 1", 6, new byte[] { 0x12, 0x34 }); addDataItem(" DO\n DC.W $1234\n UNTIL 1,1", 6, new byte[] { 0x12, 0x34 }, WRONG_NUMBER_OF_OPERANDS); addDataItem(" DO 1\n DC.W $1234\n UNTIL 1", 6, new byte[] { 0x12, 0x34 }, WRONG_NUMBER_OF_OPERANDS); addDataItem(" DO.W\n DC.W $1234\n UNTIL 1", 6, new byte[] { 0x12, 0x34 }, SIZE_ATTRIBUTE_NOT_ALLOWED); addDataItem("I SET 0\n DO\n DC.W $1234\nI SET I + 1\n UNTIL I = 5", 28, new byte[] { 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34 }); // ELSE final ElseWithoutIfErrorMessage elseWithoutIf = new ElseWithoutIfErrorMessage(); addDataItem(" ELSE", 2, NO_DATA, elseWithoutIf); addDataItem(" ELSE 1", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS, elseWithoutIf); addDataItem(" ELSE.W", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED, elseWithoutIf); // ELSEIF final ElseifWithoutIfErrorMessage elseifWithoutIf = new ElseifWithoutIfErrorMessage(); addDataItem(" ELSEIF 1", 2, NO_DATA, elseifWithoutIf); addDataItem(" ELSEIF.W 1", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED, elseifWithoutIf); // ENCODING addDataItem(" ENCODING", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem(" ENCODING 'US-ASCII'\n DC.B 'Hello'", 3, new byte[] { 'H', 'e', 'l', 'l', 'o' }); addDataItem(" ENCODING 'UTF-16BE'\n DC.B '\u3053\u3093\u306B\u3061\u306F'", 3, new byte[] { 0x30, 0x53, 0x30, (byte) 0x93, 0x30, 0x6B, 0x30, 0x61, 0x30, 0x6F }); addDataItem(" ENCODING 'UNKNOWN'", 2, NO_DATA, new UnknownEncodingNameErrorMessage("UNKNOWN", new UnsupportedCharsetException("UNKNOWN"))); addDataItem(" ENCODING '???'", 2, NO_DATA, new UnknownEncodingNameErrorMessage("???", new IllegalCharsetNameException("???"))); addDataItem(" ENCODING UNDEFINED", 2, NO_DATA, UNDEFINED_SYMBOL); // END addDataItem(" END", 2, NO_DATA); addDataItem(" END 1", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem(" END.W", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED); addDataItem(" DC.B 1\n END\n DC.B 2", 3, new byte[] { 1 }); // ENDIF final EndifWithoutIfErrorMessage endifWithoutIf = new EndifWithoutIfErrorMessage(); addDataItem(" ENDIF", 2, NO_DATA, endifWithoutIf); addDataItem(" ENDIF 1", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS, endifWithoutIf); addDataItem(" ENDIF.W", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED, endifWithoutIf); // ENDM final EndmWithoutMacroErrorMessage endmWithoutMacro = new EndmWithoutMacroErrorMessage(); addDataItem(" ENDM", 2, NO_DATA, endmWithoutMacro); addDataItem(" ENDM 1", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS, endmWithoutMacro); addDataItem(" ENDM.W", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED, endmWithoutMacro); // ENDNS final EndnsWithoutNamespaceErrorMessage endnsWithoutNamespace = new EndnsWithoutNamespaceErrorMessage(); addDataItem(" ENDNS", 2, NO_DATA, endnsWithoutNamespace); addDataItem(" ENDNS 1", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS, endnsWithoutNamespace); addDataItem(" ENDNS.W", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED, endnsWithoutNamespace); // ENDR final EndrWithoutReptErrorMessage endrWithoutRept = new EndrWithoutReptErrorMessage(); addDataItem(" ENDR", 2, NO_DATA, endrWithoutRept); addDataItem(" ENDR 1", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS, endrWithoutRept); addDataItem(" ENDR.W", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED, endrWithoutRept); // ENDTRANSFORM final EndtransformWithoutTransformErrorMessage endtransformWithoutTransform = new EndtransformWithoutTransformErrorMessage(); addDataItem(" ENDTRANSFORM", 2, NO_DATA, endtransformWithoutTransform); addDataItem(" ENDTRANSFORM 1", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS, endtransformWithoutTransform); addDataItem(" ENDTRANSFORM.W", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED, endtransformWithoutTransform); // ENDW final EndwWithoutWhileErrorMessage endwWithoutWhile = new EndwWithoutWhileErrorMessage(); addDataItem(" ENDW", 2, NO_DATA, endwWithoutWhile); addDataItem(" ENDW 1", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS, endwWithoutWhile); addDataItem(" ENDW.W", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED, endwWithoutWhile); // EVEN addDataItem(" EVEN", 2, NO_DATA); addDataItem(" EVEN 1", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem(" EVEN.W", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED); addDataItem(" DC.B 1, 2\n EVEN\n DC.B 3", 4, new byte[] { 1, 2, 3 }); addDataItem(" DC.B 1\n EVEN\n DC.B 2", 4, new byte[] { 1, 0, 2 }); // FOR addDataItem(" FOR\n DC.W $1234\n NEXT", 4, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem(" FOR 1\n DC.W $1234\n NEXT", 4, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem(" FOR 1,5\n DC.W $1234\n NEXT", 24, new byte[] { 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34 }); addDataItem(" FOR 1,5,2\n DC.W $1234\n NEXT", 16, new byte[] { 0x12, 0x34, 0x12, 0x34, 0x12, 0x34 }); addDataItem(" FOR 1,5,2,3\n DC.W $1234\n NEXT", 16, new byte[] { 0x12, 0x34, 0x12, 0x34, 0x12, 0x34 }, WRONG_NUMBER_OF_OPERANDS); addDataItem(" FOR 5,1,-2\n DC.W $1234\n NEXT", 16, new byte[] { 0x12, 0x34, 0x12, 0x34, 0x12, 0x34 }); addDataItem(" FOR UNDEFINED,5\n DC.W $1234\n NEXT", 4, NO_DATA, UNDEFINED_SYMBOL); addDataItem(" FOR 1,UNDEFINED\n DC.W $1234\n NEXT", 4, NO_DATA, UNDEFINED_SYMBOL); addDataItem(" FOR 1,5,UNDEFINED\n DC.W $1234\n NEXT", 8, new byte[] { 0x12, 0x34 }, UNDEFINED_SYMBOL); addDataItem("I FOR 11,15\n DC.B I\n NEXT", 24, new byte[] { 11, 12, 13, 14, 15 }); addDataItem("I: J: FOR 11,15\n DC.B I+J\n NEXT", 24, new byte[] { 22, 24, 26, 28, 30 }); // FUNCTION addDataItem(" FUNCTION", 2, NO_DATA, new DirectiveRequiresLabelErrorMessage("FUNCTION")); addDataItem("F FUNCTION\n DC.B F()", 3, new byte[] { 0 }, WRONG_NUMBER_OF_OPERANDS, new UnresolvedSymbolReferenceErrorMessage("F")); addDataItem("F FUNCTION 2+3\n DC.B F()", 3, new byte[] { 5 }); addDataItem("F FUNCTION <\n DC.B F()", 3, new byte[] { 0 }, new InvalidExpressionErrorMessage("<")); addDataItem("F FUNCTION A,A+3\n DC.B F(2)", 3, new byte[] { 5 }); addDataItem("F FUNCTION A,B,A+B\n DC.B F(2,3)", 3, new byte[] { 5 }); addDataItem("F FUNCTION 2,2+3\n DC.B F()", 3, new byte[] { 0 }, new FunctionParameterIsNotSimpleIdentifierErrorMessage("2")); addDataItem("F FUNCTION A!,2+3\n DC.B F()", 3, new byte[] { 0 }, new FunctionParameterIsNotSimpleIdentifierErrorMessage( "A!")); // IF addDataItem(" IF\n DC.W $1234\n ENDIF", 4, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem(" IF 0\n DC.W $1234\n ENDIF", 4, NO_DATA); addDataItem(" IF.W 0\n DC.W $1234\n ENDIF", 4, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED); addDataItem(" IF 1\n DC.W $1234\n ENDIF", 5, new byte[] { 0x12, 0x34 }); addDataItem(" IF 1,1\n DC.W $1234\n ENDIF", 5, new byte[] { 0x12, 0x34 }, WRONG_NUMBER_OF_OPERANDS); addDataItem(" IF 1\n DC.W $1234\n ENDC", 5, new byte[] { 0x12, 0x34 }); addDataItem(" IF UNDEFINED\n DC.W $1234\n ENDIF", 4, NO_DATA, UNDEFINED_SYMBOL); addDataItem(" IF 0\n DC.W $1234\n ELSE\n DC.W $2345\n ENDIF", 6, new byte[] { 0x23, 0x45 }); addDataItem(" IF 1\n DC.W $1234\n ELSE\n DC.W $2345\n ENDIF", 5, new byte[] { 0x12, 0x34 }); addDataItem(" IF UNDEFINED\n DC.W $1234\n ELSE\n DC.W $2345\n ENDIF", 6, new byte[] { 0x23, 0x45 }, UNDEFINED_SYMBOL); addDataItem(" IF 0\n DC.W $1234\n ELSEIF\n DC.W $2345\n ENDIF", 5, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem(" IF 0\n DC.W $1234\n ELSEIF 0\n DC.W $2345\n ENDIF", 5, NO_DATA); addDataItem(" IF 0\n DC.W $1234\n ELSEIF 1\n DC.W $2345\n ENDIF", 6, new byte[] { 0x23, 0x45 }); addDataItem(" IF 0\n DC.W $1234\n ELSEIF 1,1\n DC.W $2345\n ENDIF", 6, new byte[] { 0x23, 0x45 }, WRONG_NUMBER_OF_OPERANDS); addDataItem(" IF 1\n DC.W $1234\n ELSEIF 0\n DC.W $2345\n ENDIF", 5, new byte[] { 0x12, 0x34 }); addDataItem(" IF 1\n DC.W $1234\n ELSEIF 1\n DC.W $2345\n ENDIF", 5, new byte[] { 0x12, 0x34 }); addDataItem(" IF 0\n DC.W $1234\n ELSEIF 0\n DC.W $2345\n ELSE\n DC.W $3456\n ENDIF", 7, new byte[] { 0x34, 0x56 }); addDataItem(" IF 0\n DC.W $1234\n ELSEIF 1\n DC.W $2345\n ELSE\n DC.W $3456\n ENDIF", 6, new byte[] { 0x23, 0x45 }); addDataItem(" IF 1\n DC.W $1234\n ELSEIF 0\n DC.W $2345\n ELSE\n DC.W $3456\n ENDIF", 5, new byte[] { 0x12, 0x34 }); addDataItem(" IF 1\n DC.W $1234\n ELSEIF 1\n DC.W $2345\n ELSE\n DC.W $3456\n ENDIF", 5, new byte[] { 0x12, 0x34 }); // MACRO addDataItem(" MACRO\n ENDM", 4, NO_DATA, new DirectiveRequiresLabelErrorMessage(Mnemonics.MACRO)); addDataItem("A MACRO\n ENDM", 4, NO_DATA); addDataItem("A MACRO.W\n ENDM", 4, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED); addDataItem("A MACRO\n ENDM\n A", 6, NO_DATA); addDataItem("A MACRO Z\n ENDM\n A", 6, NO_DATA); addDataItem("A MACRO\n DC.B $7F\n ENDM\n A", 7, new byte[] { 0x7F }); addDataItem("A MACRO\n DC.B NARG\n ENDM\n A", 7, new byte[] { 0 }); addDataItem("A MACRO\n DC.B NARG\n ENDM\n A 0", 7, new byte[] { 1 }); addDataItem("A MACRO\n DC.B NARG\n ENDM\n A 0,0,0,0,0,0,0,0,0,0,0,0,0", 7, new byte[] { 13 }); addDataItem("A MACRO Z\n DC.B Z\n ENDM\n A", 7, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem("A MACRO Z\n DC.B Z\n ENDM\n A $7F", 7, new byte[] { 0x7F }); addDataItem("A MACRO Z\n DC.B 0Z\n ENDM\n A $7F", 7, new byte[] { 0x00 }, new InvalidExpressionErrorMessage("0Z")); addDataItem("A MACRO Z\n MOVE.B #Z,D0\n ENDM\n A $7F", 7, new byte[] { 0x10, 0x3C, 0x00, 0x7F }); addDataItem("A MACRO Z\n DC.B \\\n ENDM\n A $7F", 7, new byte[] { 0 }, new InvalidExpressionErrorMessage("\\")); addDataItem("A MACRO Z\n DC.B \\*\n ENDM\n A $7F", 7, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem("A MACRO Z\n DC.B \\*\n ENDM\nL A $7F\nL:", 16, new byte[] { 1 }); addDataItem("A MACRO\n DC.B B\\@\nB\\@:\n ENDM\n A\n A", 24, new byte[] { 0x01, 0x02 }); addDataItem("A MACRO Z\n DC.\\0 \\1\n ENDM\n A $7F", 7, new byte[] { 0x00, 0x7F }, INVALID_SIZE_ATTRIBUTE_EMPTY); addDataItem("A MACRO Z\n DC.\\0 \\1\n ENDM\n A.B $7F", 7, new byte[] { 0x7F }); addDataItem("A MACRO Z\n DC.B \\1\n ENDM\n A $7F", 7, new byte[] { 0x7F }); addDataItem("A MACRO\n DC.B \\1\n ENDM\n A $7F", 7, new byte[] { 0x7F }); addDataItem("A MACRO\n DC.B \\10\n ENDM\n A ,,,,,,,,,$7F", 7, new byte[] { 0x7F }); addDataItem("A MACRO\n DC.B \\2147483648\n ENDM\n A", 7, new byte[] { 0 }, new InvalidExpressionErrorMessage("\\2147483648")); addDataItem("A MACRO Z\n DC.B \\{\n ENDM\n A $7F", 7, new byte[] { 0 }, new InvalidExpressionErrorMessage("\\{")); addDataItem("A MACRO Z\n DC.B \\{}\n ENDM\n A $7F", 7, new byte[] { 0 }, new InvalidExpressionErrorMessage("\\{}")); addDataItem("A MACRO Z\n DC.B \\{1\n ENDM\n A $7F", 7, new byte[] { 0 }, new InvalidExpressionErrorMessage("\\{1")); addDataItem("A MACRO Z\n DC.B \\{1}\n ENDM\n A $7F", 7, new byte[] { 0x7F }); addDataItem("A MACRO\n DC.B \\{1}\n ENDM\n A $7F", 7, new byte[] { 0x7F }); addDataItem("A MACRO\n DC.B \\{10}\n ENDM\n A ,,,,,,,,,$7F", 7, new byte[] { 0x7F }); addDataItem("A MACRO\n DC.B \\{2147483648}\n ENDM\n A", 7, new byte[] { 0 }, new InvalidExpressionErrorMessage( "\\{2147483648}")); addDataItem("A MACRO Z\n DC.B \\{N}\n ENDM\n A $7F", 7, new byte[] { 0 }, new InvalidExpressionErrorMessage("\\{N}")); addDataItem("A MACRO Z\n DC.B \\{NARG}\n ENDM\n A 0,0,0,0,0,0,0,0,0,0,0,0,0", 7, new byte[] { 13 }); addDataItem("A MACRO Z\n DC.B \\{Z}\n ENDM\n A $7F", 7, new byte[] { 0x7F }); addDataItem("A MACRO Z\n DC.B 'Z'\n ENDM\n A $7F", 7, new byte[] { 'Z' }); addDataItem("A MACRO Z\n DC.B '\\'\n ENDM\n A $7F", 7, NO_DATA, new ParseErrorMessage(new UnterminatedStringParseError(0))); addDataItem("A MACRO Z\n DC.B '\\*'\n ENDM\n A $7F", 7, NO_DATA); addDataItem("A MACRO Z\n DC.B '\\*'\n ENDM\nL A $7F", 7, new byte[] { 'L' }); addDataItem("A MACRO Z\n DC.B '\\1'\n ENDM\n A $7F", 7, new byte[] { '1' }, new UnrecognizedEscapeSequenceWarningMessage( '1')); addDataItem("A MACRO Z\n DC.B '\\{'\n ENDM\n A $7F", 7, new byte[] { '{' }, new UnrecognizedEscapeSequenceWarningMessage( '{')); addDataItem("A MACRO Z\n DC.B '\\{}'\n ENDM\n A $7F", 7, new byte[] { '{', '}' }, new UnrecognizedEscapeSequenceWarningMessage('{')); addDataItem("A MACRO Z\n DC.B '\\{1'\n ENDM\n A $7F", 7, new byte[] { '{', '1' }, new UnrecognizedEscapeSequenceWarningMessage('{')); addDataItem("A MACRO Z\n DC.B '\\{1}'\n ENDM\n A $7F", 7, new byte[] { '$', '7', 'F' }); addDataItem("A MACRO Z\n DC.B '\\{2147483648}'\n ENDM\n A $7F", 7, new byte[] { '{', '2', '1', '4', '7', '4', '8', '3', '6', '4', '8', '}' }, new UnrecognizedEscapeSequenceWarningMessage('{')); addDataItem("A MACRO Z\n DC.B '\\{N}'\n ENDM\n A $7F", 7, new byte[] { '{', 'N', '}' }, new UnrecognizedEscapeSequenceWarningMessage('{')); addDataItem("A MACRO Z\n DC.B '\\{NARG}'\n ENDM\n A 0,0,0,0,0,0,0,0,0,0,0,0,0", 7, new byte[] { '1', '3' }); addDataItem("A MACRO Z\n DC.B '\\{Z}'\n ENDM\n A $7F", 7, new byte[] { '$', '7', 'F' }); addDataItem("A MACRO Z\n DC.B \"Z\"\n ENDM\n A $7F", 7, new byte[] { 'Z' }); addDataItem("A MACRO Z\n DC.B \"\\*\"\n ENDM\nL A $7F", 7, new byte[] { 'L' }); addDataItem("A MACRO Z\n DC.B \"\\1\"\n ENDM\n A $7F", 7, new byte[] { '1' }, new UnrecognizedEscapeSequenceWarningMessage( '1')); addDataItem("A MACRO Z\n DC.B \"\\{1}\"\n ENDM\n A $7F", 7, new byte[] { '$', '7', 'F' }); addDataItem("A MACRO Z\n DC.B \"\\{NARG}\"\n ENDM\n A 0,0,0,0,0,0,0,0,0,0,0,0,0", 7, new byte[] { '1', '3' }); addDataItem("A MACRO Z\n DC.B \"\\{Z}\"\n ENDM\n A $7F", 7, new byte[] { '$', '7', 'F' }); addDataItem("A MACRO\n DC.B $7F\n ENDM\n !A", 5, NO_DATA, new UnknownMnemonicErrorMessage()); addDataItem("NOP MACRO\n ENDM\n NOP\n DC.W $1111\n !NOP", 8, new byte[] { 0x11, 0x11, 0x4E, 0x71 }); addDataItem("M MACRO A,...\n IF NARG >= 1\n DC.B $FF\n DC.B A\n M ...\n ENDIF\n ENDM\n M 1,2,3", 30, new byte[] { (byte) 0xFF, 0x01, (byte) 0xFF, 0x02, (byte) 0xFF, 0x03 }); addDataItem("M MACRO ...,A\n IF NARG >= 1\n DC.B $FF\n DC.B A\n M ...\n ENDIF\n ENDM\n M 1,2,3", 30, new byte[] { (byte) 0xFF, 0x03, (byte) 0xFF, 0x02, (byte) 0xFF, 0x01 }); addDataItem("M MACRO A,B,...\n IF NARG >= 2\n DC.B $FF\n DC.B A\n DC.B B\n M ...\n ENDIF\n ENDM\n M 1,2,3,4,5,6", 33, new byte[] { (byte) 0xFF, 0x01, 0x02, (byte) 0xFF, 0x03, 0x04, (byte) 0xFF, 0x05, 0x06 }); addDataItem("M MACRO A,...,B\n IF NARG >= 2\n DC.B $FF\n DC.B A\n DC.B B\n M ...\n ENDIF\n ENDM\n M 1,2,3,4,5,6", 33, new byte[] { (byte) 0xFF, 0x01, 0x06, (byte) 0xFF, 0x02, 0x05, (byte) 0xFF, 0x03, 0x04 }); addDataItem("M MACRO A,...\n IF NARG >= 1\n DC.B $FF\n DC.B A\n M \\{...}\n ENDIF\n ENDM\n M 1,2,3", 30, new byte[] { (byte) 0xFF, 0x01, (byte) 0xFF, 0x02, (byte) 0xFF, 0x03 }); addDataItem("M MACRO A,...,B,...\n IF NARG >= 1\n DC.B $FF\n DC.B A\n M ...\n ENDIF\n ENDM\n M 1,2,3", 16, new byte[] { (byte) 0xFF, 0x01 }, new MultipleOperandPacksInMacroDefinitionErrorMessage()); addDataItem("M MACRO A,B,...\n IF NARG >= 2\n DC.B $FF\n DC.B A\n DC.B B\n M ..\n ENDIF\n ENDM\n M 1,2,3,4,5,6", 17, new byte[] { (byte) 0xFF, 0x01, 0x02 }); addDataItem("M MACRO A,B,...\n IF NARG >= 2\n DC.B $FF\n DC.B A\n DC.B B\n M .\n ENDIF\n ENDM\n M 1,2,3,4,5,6", 17, new byte[] { (byte) 0xFF, 0x01, 0x02 }); addDataItem("M MACRO A,B\n IF NARG >= 2\n DC.B $FF\n DC.B A\n DC.B B\n M ...\n ENDIF\n ENDM\n M 1,2,3,4,5,6", 17, new byte[] { (byte) 0xFF, 0x01, 0x02 }); addDataItem("M MACRO\n DC.B \\257\n ENDM\n M " + stringOf(',', 256) + "$7F", 7, new byte[] { 0x7F }); // bypass OperandSubstitutionSource.CACHE addDataItem( "M MACRO ...,A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,A17,A18,A19,A20,A21,A22,A23,A24,A25,A26,A27,A28,A29,A30,A31,A32,A33,A34,A35,A36,A37,A38,A39,A40,A41,A42,A43,A44,A45,A46,A47,A48,A49,A50,A51,A52,A53,A54,A55,A56,A57,A58,A59,A60,A61,A62,A63,A64,A65,A66,A67,A68,A69,A70,A71,A72,A73,A74,A75,A76,A77,A78,A79,A80,A81,A82,A83,A84,A85,A86,A87,A88,A89,A90,A91,A92,A93,A94,A95,A96,A97,A98,A99,A100,A101,A102,A103,A104,A105,A106,A107,A108,A109,A110,A111,A112,A113,A114,A115,A116,A117,A118,A119,A120,A121,A122,A123,A124,A125,A126,A127,A128,A129,A130,A131,A132,A133,A134,A135,A136,A137,A138,A139,A140,A141,A142,A143,A144,A145,A146,A147,A148,A149,A150,A151,A152,A153,A154,A155,A156,A157,A158,A159,A160,A161,A162,A163,A164,A165,A166,A167,A168,A169,A170,A171,A172,A173,A174,A175,A176,A177,A178,A179,A180,A181,A182,A183,A184,A185,A186,A187,A188,A189,A190,A191,A192,A193,A194,A195,A196,A197,A198,A199,A200,A201,A202,A203,A204,A205,A206,A207,A208,A209,A210,A211,A212,A213,A214,A215,A216,A217,A218,A219,A220,A221,A222,A223,A224,A225,A226,A227,A228,A229,A230,A231,A232,A233,A234,A235,A236,A237,A238,A239,A240,A241,A242,A243,A244,A245,A246,A247,A248,A249,A250,A251,A252,A253,A254,A255,A256\n DC.B A0\n ENDM\n" + " M $7F" + stringOf(',', 256), 7, new byte[] { 0x7F }); // bypass OperandFromEndSubstitutionSource.CACHE // NEXT final NextWithoutForErrorMessage nextWithoutFor = new NextWithoutForErrorMessage(); addDataItem(" NEXT", 2, NO_DATA, nextWithoutFor); addDataItem(" NEXT 1", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS, nextWithoutFor); addDataItem(" NEXT.W", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED, nextWithoutFor); // OBJ final InvalidDataTypeForOrgOrObjDirectiveErrorMessage invalidDataTypeForOrgOrObjDirective = new InvalidDataTypeForOrgOrObjDirectiveErrorMessage(); addDataItem(" OBJ\n DC.L *\n OBJEND", 6, new byte[] { 0, 0, 0, 0 }, WRONG_NUMBER_OF_OPERANDS); addDataItem(" OBJ UNDEFINED\n DC.L *\n OBJEND", 6, new byte[] { 0, 0, 0, 0 }, UNDEFINED_SYMBOL); addDataItem(" OBJ $400000\n DC.L *\n OBJEND", 6, new byte[] { 0, 0x40, 0, 0 }); addDataItem(" OBJ +$400000\n DC.L *\n OBJEND", 6, new byte[] { 0, 0x40, 0, 0 }); addDataItem(" OBJ 3.14159\n DC.L *\n OBJEND", 6, new byte[] { 0, 0, 0, 0 }, invalidDataTypeForOrgOrObjDirective); addDataItem(" OBJ '4'\n DC.L *\n OBJEND", 6, new byte[] { 0, 0, 0, 0 }, invalidDataTypeForOrgOrObjDirective); // TODO: test with a built-in function symbol //addDataItem(" OBJ STRLEN\n DC.L *\n OBJEND", 6, new byte[] { 0, 0, 0, 0 }, invalidDataTypeForOrgOrObjDirective); addDataItem(" OBJ.W $400000\n DC.L *\n OBJEND", 6, new byte[] { 0, 0x40, 0, 0 }, SIZE_ATTRIBUTE_NOT_ALLOWED); // OBJEND final ObjendWithoutObjErrorMessage objendWithoutObj = new ObjendWithoutObjErrorMessage(); addDataItem(" OBJEND", 2, NO_DATA, objendWithoutObj); addDataItem(" OBJEND 0", 2, NO_DATA, WRONG_NUMBER_OF_OPERANDS, objendWithoutObj); addDataItem(" OBJEND.W", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED, objendWithoutObj); // ORG addDataItem(" ORG\n DC.L *", 3, new byte[] { 0, 0, 0, 0 }, WRONG_NUMBER_OF_OPERANDS); addDataItem(" ORG UNDEFINED\n DC.L *", 3, new byte[] { 0, 0, 0, 0 }, UNDEFINED_SYMBOL); addDataItem(" ORG $400000\n DC.L *", 3, new byte[] { 0, 0x40, 0, 0 }); addDataItem(" ORG +$400000\n DC.L *", 3, new byte[] { 0, 0x40, 0, 0 }); addDataItem(" ORG 3.14159\n DC.L *", 3, new byte[] { 0, 0, 0, 0 }, invalidDataTypeForOrgOrObjDirective); addDataItem(" ORG '4'\n DC.L *", 3, new byte[] { 0, 0, 0, 0 }, invalidDataTypeForOrgOrObjDirective); // TODO: test with a built-in function symbol //addDataItem(" ORG STRLEN\n DC.L *", 3, new byte[] { 0, 0, 0, 0 }, invalidDataTypeForOrgOrObjDirective); addDataItem(" ORG.W $400000\n DC.L *", 3, new byte[] { 0, 0x40, 0, 0 }, SIZE_ATTRIBUTE_NOT_ALLOWED); // PHASE addDataItem(" PHASE\n DC.L *\n DEPHASE", 6, new byte[] { 0, 0, 0, 0 }, WRONG_NUMBER_OF_OPERANDS); addDataItem(" PHASE UNDEFINED\n DC.L *\n DEPHASE", 6, new byte[] { 0, 0, 0, 0 }, UNDEFINED_SYMBOL); addDataItem(" PHASE $400000\n DC.L *\n DEPHASE", 6, new byte[] { 0, 0x40, 0, 0 }); addDataItem(" PHASE +$400000\n DC.L *\n DEPHASE", 6, new byte[] { 0, 0x40, 0, 0 }); addDataItem(" PHASE 3.14159\n DC.L *\n DEPHASE", 6, new byte[] { 0, 0, 0, 0 }, invalidDataTypeForOrgOrObjDirective); addDataItem(" PHASE '4'\n DC.L *\n DEPHASE", 6, new byte[] { 0, 0, 0, 0 }, invalidDataTypeForOrgOrObjDirective); // TODO: test with a built-in function symbol //addDataItem(" PHASE STRLEN\n DC.L *\n DEPHASE", 6, new byte[] { 0, 0, 0, 0 }, invalidDataTypeForOrgOrObjDirective); addDataItem(" PHASE.W $400000\n DC.L *\n DEPHASE", 6, new byte[] { 0, 0x40, 0, 0 }, SIZE_ATTRIBUTE_NOT_ALLOWED); // REPT addDataItem(" REPT\n DC.W $1234\n ENDR", 5, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem(" REPT -1\n DC.W $1234\n ENDR", 5, NO_DATA, new CountMustNotBeNegativeErrorMessage()); addDataItem(" REPT 0\n DC.W $1234\n ENDR", 5, NO_DATA); addDataItem(" REPT.W 0\n DC.W $1234\n ENDR", 5, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED); addDataItem(" REPT 5\n DC.W $1234\n ENDR", 10, new byte[] { 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34 }); // UNTIL final UntilWithoutDoErrorMessage untilWithoutDo = new UntilWithoutDoErrorMessage(); addDataItem(" UNTIL", 2, NO_DATA, untilWithoutDo); addDataItem(" UNTIL.W", 2, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED, untilWithoutDo); // WHILE addDataItem(" WHILE\n DC.W $1234\n ENDW", 4, NO_DATA, WRONG_NUMBER_OF_OPERANDS); addDataItem(" WHILE 0\n DC.W $1234\n ENDW", 4, NO_DATA); addDataItem(" WHILE.W 0\n DC.W $1234\n ENDW", 4, NO_DATA, SIZE_ATTRIBUTE_NOT_ALLOWED); addDataItem("I SET 0\n WHILE I < 5\n DC.W $1234\nI SET I + 1\n ENDW", 30, new byte[] { 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34 }); addDataItem("I SET 0\n WHILE I < 5, I > 2\n DC.W $1234\nI SET I + 1\n ENDW", 30, new byte[] { 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34 }, WRONG_NUMBER_OF_OPERANDS); addDataItem(" WHILE UNDEFINED\n DC.W $1234\n ENDW", 4, NO_DATA, UNDEFINED_SYMBOL); // undefined mnemonic addDataItem(" UNDEFINED", 2, NO_DATA, UNDEFINED_SYMBOL); addDataItem("A: UNDEFINED\n DC.W A", 3, new byte[] { 0x00, 0x00 }, UNDEFINED_SYMBOL); // ! prefix on a block directive addDataItem(" !IF 0\n DC.W $0123\n !ELSEIF 1\n DC.W $1234\n !ENDIF", 6, new byte[] { 0x12, 0x34 }); // M68KAssemblyContext.getRegisterAliasByName() addDataItem("A EQUR D0\n MOVE.W A,D1", 3, new byte[] { 0x32, 0x00 }); addDataItem("A EQU 0\n MOVE.W A,D1", 3, new byte[] { 0x32, 0x38, 0x00, 0x00 }); addDataItem(" MOVE.W UNDEFINED,D1", 2, new byte[] { 0x32, 0x38, 0x00, 0x00 }, UNDEFINED_SYMBOL, UNDEFINED_SYMBOL); // M68KAssemblyContext.getRegisterAliasOrRegisterListAliasSymbolByName() addDataItem("A REG D0-D3/A2-A4\n MOVEM.L A,(A0)", 3, new byte[] { 0x48, (byte) 0xD0, 0x1C, 0x0F }); addDataItem("A EQUR D0\n MOVEM.L A,(A0)", 3, new byte[] { 0x48, (byte) 0xD0, 0x00, 0x01 }); addDataItem("A EQU 0\n MOVEM.L A,D0", 3, new byte[] { 0x4C, (byte) 0xF8, 0x00, 0x01, 0x00, 0x00 }); addDataItem(" MOVEM.L UNDEFINED,D0", 2, new byte[] { 0x4C, (byte) 0xF8, 0x00, 0x01, 0x00, 0x00 }, UNDEFINED_SYMBOL, UNDEFINED_SYMBOL, UNDEFINED_SYMBOL); // Mnemonic.identifyRegister() addDataItem("A EQUR D0\nB EQUR D3\n MOVEM A-B,(A0)", 4, new byte[] { 0x48, (byte) 0x90, 0x00, 0x0F }); // Mnemonic.parseRegisterList() addDataItem("A EQUR D0\nB EQUR D3\nC EQUR A2\nA REG D0-D7\nB REG D0-D7\nC REG D0-D7\n MOVEM A/B/C,(A0)", 8, new byte[] { 0x48, (byte) 0x90, 0x04, 0x09 }); // UserFunction class addDataItem("F FUNCTION A,B,A+B\n DC.B F()", 3, new byte[] { 0 }, WRONG_NUMBER_OF_ARGUMENTS); addDataItem("Z EQU 7\nF FUNCTION A,Z*A\n DC.B F(3)", 4, new byte[] { 21 }); addDataItem("Z.Y EQU 7\nX.W EQU 5\nF FUNCTION A,X.W*A.Y\n DC.B F()", 5, new byte[] { 0 }, WRONG_NUMBER_OF_ARGUMENTS); addDataItem("Z.Y EQU 7\nX.W EQU 5\nF FUNCTION A,X.W*A.Y\n DC.B F(Z)", 5, new byte[] { 35 }); addDataItem("Z EQU 7\nF FUNCTION A,(Z)*(A)\n DC.B F(3)", 4, new byte[] { 21 }); addDataItem("Z EQU 7\nF FUNCTION A,+Z*+A\n DC.B F(3)", 4, new byte[] { 21 }); addDataItem("Z.Y EQU 7\nX.W EQU 5\nV.U EQU 3\nF FUNCTION A,B,Z . Y * A . W * V . B\n DC.B F(X, U)", 6, new byte[] { 105 }); addDataItem("Z[0] EQU 7\nZ[1] EQU 5\nZ[2] EQU 3\nF FUNCTION A,B,Z[0] * Z[A] * B[2]\n DC.B F(1,Z)", 6, new byte[] { 105 }); addDataItem("Z EQU 7\nF FUNCTION A,(Z*1)*(A*1)\n DC.B F(3)", 4, new byte[] { 21 }); addDataItem("F FUNCTION 1?2:3\n DC.B F()", 3, new byte[] { 2 }); addDataItem("F FUNCTION A,A?2:3\n DC.B F(1)", 3, new byte[] { 2 }); addDataItem("F FUNCTION A,1?A:3\n DC.B F(2)", 3, new byte[] { 2 }); addDataItem("F FUNCTION A,1?2:A\n DC.B F(3)", 3, new byte[] { 2 }); addDataItem("G FUNCTION 1\nF FUNCTION G()\n DC.B F()", 4, new byte[] { 1 }); addDataItem("G FUNCTION 1\nF FUNCTION A,A()\n DC.B F(G)", 4, new byte[] { 1 }); addDataItem("G FUNCTION A,B,A*B\nF FUNCTION A,G(A,3)\n DC.B F(2)", 4, new byte[] { 6 }); addDataItem("Z EQU 5\nN1 NAMESPACE\nZ EQU 7\nF FUNCTION Z\n ENDNS\n DC.B N1.F()", 9, new byte[] { 7 }); addDataItem("Z EQU 5\nN1 NAMESPACE\nZ EQU 7\nF FUNCTION A,Z*A\n ENDNS\n DC.B N1.F(3)", 9, new byte[] { 21 }); addDataItem("Z EQU 5\nF FUNCTION A,Z*A\nN1 NAMESPACE\nZ EQU 7\n DC.B F(Z)\n ENDNS", 9, new byte[] { 35 }); addDataItem("Z.Y EQU 5\nF FUNCTION A,Z.Y*A.Y\nN1 NAMESPACE\nZ.Y EQU 7\n DC.B F(Z)\n ENDNS", 9, new byte[] { 35 }); // continuation characters addDataItem(" DC.B &\n1", 2, new byte[] { 1 }); addDataItem(" DC&\n.B 1", 2, new byte[] { 1 }); addDataItem(" DC&\r.B 1", 2, new byte[] { 1 }); addDataItem(" DC&\r\n.B 1", 2, new byte[] { 1 }); addDataItem(" DC&\n .B 1", 2, new byte[] { 1 }); addDataItem(" DC&\n\t.B 1", 2, new byte[] { 1 }); addDataItem(" DC&\n\t\t .B 1", 2, new byte[] { 1 }); addDataItem(" DC.B 1&\n1", 2, new byte[] { 11 }); } /** * Gets the test data for this parameterized test. * * @return the test data */ @Nonnull @Parameters public static List<Object[]> data() { return TEST_DATA; } private static void addDataItem(@Nonnull String code, int steps, @Nonnull byte[] output) { addDataItem(code, steps, output, (AssemblyMessage) null); } private static void addDataItem(@Nonnull String code, int steps, @Nonnull byte[] output, @CheckForNull AssemblyMessage expectedMessage) { TEST_DATA.add(new Object[] { code, steps, output, expectedMessage, null }); } private static void addDataItem(@Nonnull String code, int steps, @Nonnull byte[] output, @CheckForNull AssemblyMessage... expectedMessages) { TEST_DATA.add(new Object[] { code, steps, output, null, expectedMessages }); } private static String stringOf(char c, int count) { char[] arr = new char[count]; Arrays.fill(arr, c); return new String(arr); } /** * Initializes a new ProgramsTest. * * @param code * assembly code to assemble * @param steps * the number of steps the program is expected to take to assemble completely * @param output * the program's output * @param expectedMessage * an {@link AssemblyMessage} that is expected to be generated while assembling the code * @param expectedMessages * an array of {@link AssemblyMessage AssemblyMessages} that are expected to be generated while assembling the code. * Takes priority over <code>expectedMessage</code>. */ public ProgramsTest(@Nonnull String code, int steps, @Nonnull byte[] output, @CheckForNull AssemblyMessage expectedMessage, @CheckForNull AssemblyMessage[] expectedMessages) { super(code, steps, output, M68KArchitecture.MC68000, expectedMessage, expectedMessages, null); } }