2022-12-27 23:05:26 +00:00
|
|
|
package riscvemu
|
|
|
|
|
|
|
|
import (
|
2022-12-28 02:58:24 +00:00
|
|
|
"bytes"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"os/exec"
|
|
|
|
"strings"
|
2022-12-27 23:05:26 +00:00
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
2022-12-28 02:58:24 +00:00
|
|
|
// 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
|
2022-12-27 23:05:26 +00:00
|
|
|
|
2022-12-28 02:58:24 +00:00
|
|
|
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) {
|
2022-12-28 01:11:07 +00:00
|
|
|
env := NewVirtualEEI()
|
2022-12-28 02:58:24 +00:00
|
|
|
|
|
|
|
// ebreak
|
|
|
|
_, err := env.WriteAt([]byte{0x73, 0x00, 0x10, 0x00}, 0)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2022-12-27 23:05:26 +00:00
|
|
|
|
2022-12-28 01:11:07 +00:00
|
|
|
c := NewCPU(&env)
|
2022-12-27 23:05:26 +00:00
|
|
|
|
2022-12-28 02:58:24 +00:00
|
|
|
err = c.Step()
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("expected ErrBreak, got <nil>")
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
}
|
2022-12-27 23:05:26 +00:00
|
|
|
|
2022-12-28 02:58:24 +00:00
|
|
|
// 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])
|
|
|
|
}
|
2022-12-27 23:05:26 +00:00
|
|
|
}
|