Example #1
0
func TestAdd(t *testing.T) {
	doTest(t,
		`set a, 0xffff
		 add a, 1`,
		cpu.Encode(cpu.SET, 0, 0x20),
		cpu.Encode(cpu.ADD, 0, 0x22),
	)
}
Example #2
0
func TestSub(t *testing.T) {
	doTest(t,
		`set a, 0
		 sub a, 1`,
		cpu.Encode(cpu.SET, 0x0, 0x21),
		cpu.Encode(cpu.SUB, 0x0, 0x22),
	)
}
Example #3
0
func TestAsr(t *testing.T) {
	doTest(t,
		`SET A, 10
		 ASR A, 1`,
		cpu.Encode(cpu.SET, 0, 0x2b),
		cpu.Encode(cpu.ASR, 0, 0x22),
	)
}
Example #4
0
File: asm.go Project: DanB91/dcpu
// buildInstruction compiles the given instruction.
func (a *assembler) buildInstruction(nodes []parser.Node) (err error) {
	name := nodes[0].(*parser.Name)

	if name.Data == "dat" {
		return a.buildData(nodes)
	}

	op, ok := opcodes[name.Data]

	if !ok {
		return NewBuildError(
			a.ast.Files[name.File()], name.Line(), name.Col(),
			"Unknown instruction: %s", name.Data,
		)
	}

	if len(nodes)-1 != op.argc {
		return NewBuildError(
			a.ast.Files[name.File()], name.Line(), name.Col(),
			"Invalid argument count for %q. Want %d", name.Data, op.argc,
		)
	}

	var va, vb cpu.Word
	var argv []cpu.Word
	var symbols []parser.Node

	symbols = append(symbols, name)

	switch op.argc {
	case 2:
		va, err = a.buildOperand(&argv, &symbols, nodes[1].(*parser.Expression).Children()[0], true)
		if err != nil {
			return
		}

		vb, err = a.buildOperand(&argv, &symbols, nodes[2].(*parser.Expression).Children()[0], false)

	case 1:
		va, err = a.buildOperand(&argv, &symbols, nodes[1].(*parser.Expression).Children()[0], false)
	}

	if err != nil {
		return
	}

	if op.ext {
		a.code = append(a.code, cpu.Encode(cpu.EXT, op.code, va))
	} else {
		a.code = append(a.code, cpu.Encode(op.code, va, vb))
	}

	a.debug.Emit(symbols...)
	a.code = append(a.code, argv...)
	return
}
Example #5
0
func TestEQU(t *testing.T) {
	doTest(t,
		`equ SomeValue, 16
		 equ AnotherValue, 'A'
		 set a, SomeValue
		 add a, AnotherValue
		`,
		cpu.Encode(cpu.SET, 0, 0x31), // set a, 16
		cpu.Encode(cpu.ADD, 0, 0x1f), // add a, 'A'
		cpu.Word('A'),
	)
}
Example #6
0
func TestSet(t *testing.T) {
	doTest(t,
		`set a, 0x30`,
		cpu.Encode(cpu.SET, 0, 0x1f),
		0x30,
	)
}
Example #7
0
func TestJsr(t *testing.T) {
	doTest(t,
		`  set a, 0xffff
		   jsr my_sub
		   exit
		 :my_sub
		   add a, 1
		   set pc, pop
		`,
		cpu.Encode(cpu.SET, 0, 0x20),
		cpu.Encode(cpu.EXT, cpu.JSR, 0x1f),
		0x4,
		cpu.Encode(cpu.EXT, cpu.EXIT, 0),
		cpu.Encode(cpu.ADD, 0, 0x22),
		cpu.Encode(cpu.SET, 0x1c, 0x18),
	)
}
Example #8
0
func TestHwi(t *testing.T) {
	doTest(t,
		`  set a,1
		   set b, 0x100
		   hwi 0
		   set a, [0x100]
		   exit
		`,
		cpu.Encode(cpu.SET, 0, 0x22),
		cpu.Encode(cpu.SET, 1, 0x1f),
		0x100,
		cpu.Encode(cpu.EXT, cpu.HWI, 0x21),
		cpu.Encode(cpu.SET, 0, 0x1e),
		0x100,
		cpu.Encode(cpu.EXT, cpu.EXIT, 0),
	)
}
Example #9
0
func TestDat(t *testing.T) {
	doTest(t,
		`:end
		    set pc, end
		 :dat
		    dat 0x170, "Hello, universe", 0
		`,
		cpu.Encode(cpu.SET, 0x1c, 0x21),
		0x170, 'H', 'e', 'l', 'l', 'o', ',', ' ',
		'u', 'n', 'i', 'v', 'e', 'r', 's', 'e', 0,
	)
}
Example #10
0
func TestNestedIf(t *testing.T) {
	doTest(t,
		`SET A, 0
		 IFG A, 1
		   IFG A, 2
		     IFE A, 0
               SET A, 4
         SET [100], A
		`,
		cpu.Encode(cpu.SET, 0, 0x21),
		cpu.Encode(cpu.IFG, 0, 0x22),
		cpu.Encode(cpu.IFG, 0, 0x23),
		cpu.Encode(cpu.IFE, 0, 0x21),
		cpu.Encode(cpu.SET, 0, 0x25),
		cpu.Encode(cpu.SET, 0x1e, 0),
		100,
	)
}
Example #11
0
func TestIntRfi(t *testing.T) {
	doTest(t,
		` ias my_handler
		  int 0xbeef
		  set a, b
		  exit
		:my_handler
		  set b, a
		  add b, 1
		  rfi a
		`,
		cpu.Encode(cpu.EXT, cpu.IAS, 0x1f),
		0x6,
		cpu.Encode(cpu.EXT, cpu.INT, 0x1f),
		0xbeef,
		cpu.Encode(cpu.SET, 0, 1),
		cpu.Encode(cpu.EXT, cpu.EXIT, 0),
		cpu.Encode(cpu.SET, 1, 0),
		cpu.Encode(cpu.ADD, 1, 0x22),
		cpu.Encode(cpu.EXT, cpu.RFI, 0),
	)
}
Example #12
0
func TestFunc(t *testing.T) {
	doTest(t,
		`def main
			equ LoopLimit, 16
			set i, 0
			ife i, LoopLimit
				return
			add i, 1
		end
		`,
		cpu.Encode(cpu.SET, 0x18, 6), // set push, i

		cpu.Encode(cpu.SET, 6, 0x21),    // set i, 0
		cpu.Encode(cpu.IFE, 6, 0x31),    // ife i, 16
		cpu.Encode(cpu.SET, 0x1c, 0x1f), // set pc, $__main_epilog
		0x6,
		cpu.Encode(cpu.ADD, 6, 0x22), // add i, 1

		cpu.Encode(cpu.SET, 6, 0x18),    // $__main_epilog: set i, pop
		cpu.Encode(cpu.SET, 0x1c, 0x18), // set pc, pop
	)
}
Example #13
0
func TestSetIndexExpr(t *testing.T) {
	test(t, "test/asm/set_index_expr", []cpu.Word{
		cpu.Encode(cpu.SET, 0x00, 0x11),
		0xff,
	})
}
Example #14
0
func TestSetIndex(t *testing.T) {
	test(t, "test/asm/set_index", []cpu.Word{
		cpu.Encode(cpu.SET, 0x08, 0x09),
	})
}
Example #15
0
func TestSet(t *testing.T) {
	test(t, "test/asm/set", []cpu.Word{
		cpu.Encode(cpu.SET, 0x00, 0x01),
	})
}
Example #16
0
func TestSetIndexNextWord(t *testing.T) {
	test(t, "test/asm/set_index_next_word", []cpu.Word{
		cpu.Encode(cpu.SET, 0x00, 0x1e),
		0xfffe,
	})
}
Example #17
0
func TestSetPushPop(t *testing.T) {
	test(t, "test/asm/set_pushpop", []cpu.Word{
		cpu.Encode(cpu.SET, 0x18, 0x03),
		cpu.Encode(cpu.SET, 0x03, 0x18),
	})
}
Example #18
0
// Ensure Read/Write roundtrip is the identity function.
func TestIdentity(t *testing.T) {
	var w bytes.Buffer

	code := []cpu.Word{
		cpu.Encode(cpu.SET, 0, 0x1f),
		0xffff,
		cpu.Encode(cpu.ADD, 0, 0x22),
		cpu.Encode(cpu.MUL, 0, 0x22),
		cpu.Encode(cpu.SET, 1, 0),
	}

	var dbg asm.DebugInfo
	dbg.Files = []asm.FileInfo{{"a.dasm", 0}}
	dbg.Functions = []asm.FuncInfo{{"main", 0, 5, 0, 4}}
	dbg.SourceMapping = make([]asm.SourceInfo, 5)

	a := New(code, &dbg)
	a.Update(0, nil)
	a.Update(2, nil)
	a.Update(3, nil)
	a.Update(4, nil)

	a.UpdateCost(2, 5)

	err := Write(a, &w)
	if err != nil {
		t.Fatalf("Write: %v", err)
	}

	b, err := Read(&w)
	if err != nil {
		t.Fatalf("Read: %v", err)
	}

	if len(a.Files) != len(b.Files) {
		t.Fatalf("len(a.Files) != len(b.Files)")
	}

	for i := range a.Files {
		if a.Files[i].Name != b.Files[i].Name {
			t.Fatalf("a.Files[i].Name != b.Files[i].Name")
		}

		if a.Files[i].StartAddr != b.Files[i].StartAddr {
			t.Fatalf("a.Files[i].Start != b.Files[i].Start")
		}
	}

	if len(a.Functions) != len(b.Functions) {
		t.Fatalf("len(a.Functions) != len(b.Functions)")
	}

	for i := range a.Functions {
		if a.Functions[i].StartAddr != b.Functions[i].StartAddr {
			t.Fatalf("a.Functions[i].StartAddr != b.Functions[i].StartAddr")
		}

		if a.Functions[i].EndAddr != b.Functions[i].EndAddr {
			t.Fatalf("a.Functions[i].EndAddr != b.Functions[i].EndAddr")
		}

		if a.Functions[i].StartLine != b.Functions[i].StartLine {
			t.Fatalf("a.Functions[i].StartLine != b.Functions[i].StartLine")
		}

		if a.Functions[i].EndLine != b.Functions[i].EndLine {
			t.Fatalf("a.Functions[i].EndLine != b.Functions[i].EndLine")
		}

		if a.Functions[i].Name != b.Functions[i].Name {
			t.Fatalf("a.Functions[i].Name != b.Functions[i].Name")
		}
	}

	if len(a.Data) != len(b.Data) {
		t.Fatalf("len(a.Data) != len(b.Data)")
	}

	for pc, va := range a.Data {
		vb := b.Data[pc]

		if va.Count != vb.Count {
			t.Fatalf("va.Count != vb.Count")
		}

		if va.File != vb.File {
			t.Fatalf("va.File != vb.File")
		}

		if va.Line != vb.Line {
			t.Fatalf("va.Line != vb.Line")
		}

		if va.Col != vb.Col {
			t.Fatalf("va.Col != vb.Col")
		}

		if va.Data != vb.Data {
			t.Fatalf("va.Data != vb.Data")
		}

		if va.Penalty != vb.Penalty {
			t.Fatalf("va.Penalty != vb.Penalty")
		}

		if va.Cost() != vb.Cost() {
			t.Fatalf("va.Cost() != vb.Cost()")
		}
	}
}