From b5871337ab35e1604b04885f6555f0b8ba887f51 Mon Sep 17 00:00:00 2001 From: mappu Date: Wed, 28 Dec 2022 15:58:24 +1300 Subject: [PATCH] cpu.test: add test cases for add, ebreak, assembling fragments with llvm --- cpu_test.go | 84 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 5 deletions(-) diff --git a/cpu_test.go b/cpu_test.go index 71ce102..b132a77 100644 --- a/cpu_test.go +++ b/cpu_test.go @@ -1,17 +1,91 @@ package riscvemu import ( + "bytes" + "errors" + "fmt" + "os/exec" + "strings" "testing" ) -func TestCPU(t *testing.T) { +// assemble_llvm assembles RISC-V source code with the installed system LLVM +// compiler and returns the raw bytes from the resulting .text section. +func assemble_llvm(source string) ([]byte, error) { + // echo 'nop' | clang --target=riscv32 -march=rv32i -x assembler - -c -o - | llvm-objcopy - /dev/null --dump-section .text=/dev/stdout | xxd + cmd := exec.Command(`/bin/bash`, `-c`, `/usr/bin/clang --target=riscv32 -march=rv32i -x assembler - -c -o - | /usr/bin/llvm-objcopy - /dev/null --dump-section .text=/dev/stdout`) + cmd.Stdin = strings.NewReader(source) + + so_buff := bytes.Buffer{} + cmd.Stdout = &so_buff + + err := cmd.Wait() + if err != nil { + return nil, err + } + + return so_buff.Bytes(), nil +} + +func runUntilEbreak(c *CPUState, expect_insns int) error { + for i := 0; i < expect_insns-1; i++ { + err := c.Step() + if err != nil { + return err + } + } + + err := c.Step() + if err != nil { + if eb := (ErrBreak{}); errors.As(err, &eb) { + return nil // Successfully got EBREAK precisely when wanted + } + return err // Some other real error + } + + return fmt.Errorf("Expected EBREAK at instruction count %d, but got %v", expect_insns, err) +} + +func TestBreak(t *testing.T) { env := NewVirtualEEI() - _ = env.Write32(0, 0b00000000000100000000000001110011) // EBREAK + + // ebreak + _, err := env.WriteAt([]byte{0x73, 0x00, 0x10, 0x00}, 0) + if err != nil { + t.Fatal(err) + } c := NewCPU(&env) - err := c.Step() - panic(err) - + err = c.Step() + if err == nil { + t.Fatal("expected ErrBreak, got ") + } + if eb := (ErrBreak{}); !errors.As(err, &eb) { + t.Fatalf("expected ErrBreak, got %#v", err) + } +} + +func TestAdd(t *testing.T) { + env := NewVirtualEEI() + + // li a0, 0xffff + // ebreak + _, err := env.WriteAt([]byte{0x37, 0xc5, 0xad, 0xde, 0x13, 0x05, 0xf5, 0xee, 0x73, 0x00, 0x10, 0x00}, 0) + if err != nil { + t.Fatal(err) + } + + c := NewCPU(&env) + + err = runUntilEbreak(&c, 3) + if err != nil { + t.Error(err) + } + + // Check that we managed to load into the register + if c.Registers[10] != 0xdeadbeef { + t.Errorf("expected register a0 (x10) to contain 0xdeadbeef, got %#v", c.Registers[10]) + } }