Commit 93ca2941 authored by Inphi's avatar Inphi Committed by GitHub

cannon: Finish emulating rest of 64-bit instructions (#12483)

* cannon: Finish emulating rest of 64-bit instructions

This fixes the 64-bit stubs for various instructions (except lld/scd).

* review comments; fix dmult

* add todo

* test div by zero

* add a couple more dmultu tests

* remove dead code

* cannon: Fix remaining mips64 emulation bugs

* fix 64-bit Makefile build script; review comments

* fix build script
parent 239330b4
......@@ -43,7 +43,7 @@ elf:
make -C ./testdata/example elf
sanitize-program:
@if ! { mips-linux-gnu-objdump -d -j .text $$GUEST_PROGRAM | awk '{print $3}' | grep -Ew -m1 '(bgezal|bltzal)'; }; then \
@if ! { mips-linux-gnu-objdump -d -j .text $$GUEST_PROGRAM | awk '{print $3}' | grep -Ew -m1 '(bltzal)'; }; then \
echo "guest program is sanitized for unsupported instructions"; \
else \
echo "found unsupported instructions in the guest program"; \
......@@ -93,6 +93,8 @@ fuzz:
go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallCloneST ./mipsevm/tests
# Multi-threaded tests
go test $(FUZZLDFLAGS) -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateSyscallCloneMT ./mipsevm/tests
# 64-bit tests
go test $(FUZZLDFLAGS) -tags=cannon64 -run NOTAREALTEST -v -fuzztime 10s -fuzz=FuzzStateDmultInsn ./mipsevm/tests
.PHONY: \
cannon32-impl \
......
......@@ -12,6 +12,7 @@ Supported 63 instructions:
| `Conditional Branch` | `beq` | Branch on equal. |
| `Conditional Branch` | `bgez` | Branch on greater than or equal to zero. |
| `Conditional Branch` | `bgtz` | Branch on greater than zero. |
| `Conditional Branch` | `bgezal` | Branch and link on greater than or equal to zero. |
| `Conditional Branch` | `blez` | Branch on less than or equal to zero. |
| `Conditional Branch` | `bltz` | Branch on less than zero. |
| `Conditional Branch` | `bne` | Branch on not equal. |
......
......@@ -79,6 +79,8 @@ const (
SysLlseek = 4140
SysMinCore = 4217
SysTgkill = 4266
SysGetRLimit = 4076
SysLseek = 4019
// Profiling-related syscalls
SysSetITimer = 4104
SysTimerCreate = 4257
......
......@@ -25,10 +25,12 @@ const (
AddressMask = 0xFFFFFFFFFFFFFFF8
ExtMask = 0x7
HeapStart = 0x10_00_00_00_00_00_00_00
HeapEnd = 0x60_00_00_00_00_00_00_00
ProgramBreak = 0x40_00_00_00_00_00_00_00
HighMemoryStart = 0x7F_FF_FF_FF_D0_00_00_00
// Ensure virtual address is limited to 48-bits as many user programs assume such to implement packed pointers
// limit 0x00_00_FF_FF_FF_FF_FF_FF
HeapStart = 0x00_00_10_00_00_00_00_00
HeapEnd = 0x00_00_60_00_00_00_00_00
ProgramBreak = 0x00_00_40_00_00_00_00_00
HighMemoryStart = 0x00_00_7F_FF_FF_FF_F0_00
)
// MIPS64 syscall table - https://github.com/torvalds/linux/blob/3efc57369a0ce8f76bf0804f7e673982384e4ac9/arch/mips/kernel/syscalls/syscall_n64.tbl. Generate the syscall numbers using the Makefile in that directory.
......@@ -85,6 +87,8 @@ const (
SysLlseek = UndefinedSysNr
SysMinCore = 5026
SysTgkill = 5225
SysGetRLimit = 5095
SysLseek = 5008
// Profiling-related syscalls
SysSetITimer = 5036
SysTimerCreate = 5216
......
This diff is collapsed.
......@@ -11,11 +11,12 @@ import (
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/memory"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/program"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil"
)
func vmFactory(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM {
return NewInstrumentedState(state, po, stdOut, stdErr, log, nil)
func vmFactory(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, meta *program.Metadata) mipsevm.FPVM {
return NewInstrumentedState(state, po, stdOut, stdErr, log, meta)
}
func TestInstrumentedState_OpenMips(t *testing.T) {
......@@ -35,7 +36,7 @@ func TestInstrumentedState_Claim(t *testing.T) {
func TestInstrumentedState_MultithreadedProgram(t *testing.T) {
t.Parallel()
state, _ := testutil.LoadELFProgram(t, "../../testdata/example/bin/multithreaded.elf", CreateInitialState, false)
state, _ := testutil.LoadELFProgram(t, testutil.ProgramPath("multithreaded"), CreateInitialState, false)
oracle := testutil.StaticOracle(t, []byte{})
var stdOutBuf, stdErrBuf bytes.Buffer
......@@ -78,7 +79,7 @@ func TestInstrumentedState_Alloc(t *testing.T) {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
state, meta := testutil.LoadELFProgram(t, "../../testdata/example/bin/alloc.elf", CreateInitialState, false)
state, meta := testutil.LoadELFProgram(t, testutil.ProgramPath("alloc"), CreateInitialState, false)
oracle := testutil.AllocOracle(t, test.numAllocs, test.allocSize)
us := NewInstrumentedState(state, oracle, os.Stdout, os.Stderr, testutil.CreateLogger(), meta)
......
......@@ -168,9 +168,9 @@ func (m *InstrumentedState) handleSyscall() error {
m.memoryTracker.TrackMemAccess(effAddr)
m.state.Memory.SetWord(effAddr, secs)
m.handleMemoryUpdate(effAddr)
m.memoryTracker.TrackMemAccess2(effAddr + 4)
m.state.Memory.SetWord(effAddr+4, nsecs)
m.handleMemoryUpdate(effAddr + 4)
m.memoryTracker.TrackMemAccess2(effAddr + arch.WordSizeBytes)
m.state.Memory.SetWord(effAddr+arch.WordSizeBytes, nsecs)
m.handleMemoryUpdate(effAddr + arch.WordSizeBytes)
default:
v0 = exec.SysErrorSignal
v1 = exec.MipsEINVAL
......@@ -206,6 +206,8 @@ func (m *InstrumentedState) handleSyscall() error {
case arch.SysTimerCreate:
case arch.SysTimerSetTime:
case arch.SysTimerDelete:
case arch.SysGetRLimit:
case arch.SysLseek:
default:
// These syscalls have the same values on 64-bit. So we use if-stmts here to avoid "duplicate case" compiler error for the cannon64 build
if arch.IsMips32 && syscallNum == arch.SysFstat64 || syscallNum == arch.SysStat64 || syscallNum == arch.SysLlseek {
......
......@@ -7,10 +7,11 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/program"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/testutil"
)
func vmFactory(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM {
func vmFactory(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, meta *program.Metadata) mipsevm.FPVM {
return NewInstrumentedState(state, po, stdOut, stdErr, nil)
}
......
This diff is collapsed.
......@@ -991,3 +991,94 @@ func TestEntryEVM(t *testing.T) {
})
}
}
func TestEVMSingleStepBranch(t *testing.T) {
var tracer *tracing.Hooks
versions := GetMipsVersionTestCases(t)
cases := []struct {
name string
pc Word
expectNextPC Word
opcode uint32
regimm uint32
expectLink bool
rs arch.SignedInteger
rt Word
offset uint16
}{
// blez
{name: "blez", pc: 0, opcode: 0x6, rs: 0x5, offset: 0x100, expectNextPC: 0x8},
{name: "blez large rs", pc: 0x10, opcode: 0x6, rs: 0x7F_FF_FF_FF, offset: 0x100, expectNextPC: 0x18},
{name: "blez zero rs", pc: 0x10, opcode: 0x6, rs: 0x0, offset: 0x100, expectNextPC: 0x414},
{name: "blez sign rs", pc: 0x10, opcode: 0x6, rs: -1, offset: 0x100, expectNextPC: 0x414},
{name: "blez rs only sign bit set", pc: 0x10, opcode: 0x6, rs: testutil.ToSignedInteger(0x80_00_00_00), offset: 0x100, expectNextPC: 0x414},
{name: "blez sign-extended offset", pc: 0x10, opcode: 0x6, rs: -1, offset: 0x80_00, expectNextPC: 0xFF_FE_00_14},
// bgtz
{name: "bgtz", pc: 0, opcode: 0x7, rs: 0x5, offset: 0x100, expectNextPC: 0x404},
{name: "bgtz sign-extended offset", pc: 0x10, opcode: 0x7, rs: 0x5, offset: 0x80_00, expectNextPC: 0xFF_FE_00_14},
{name: "bgtz large rs", pc: 0x10, opcode: 0x7, rs: 0x7F_FF_FF_FF, offset: 0x100, expectNextPC: 0x414},
{name: "bgtz zero rs", pc: 0x10, opcode: 0x7, rs: 0x0, offset: 0x100, expectNextPC: 0x18},
{name: "bgtz sign rs", pc: 0x10, opcode: 0x7, rs: -1, offset: 0x100, expectNextPC: 0x18},
{name: "bgtz rs only sign bit set", pc: 0x10, opcode: 0x7, rs: testutil.ToSignedInteger(0x80_00_00_00), offset: 0x100, expectNextPC: 0x18},
// bltz t0, $x
{name: "bltz", pc: 0, opcode: 0x1, regimm: 0x0, rs: 0x5, offset: 0x100, expectNextPC: 0x8},
{name: "bltz large rs", pc: 0x10, opcode: 0x1, regimm: 0x0, rs: 0x7F_FF_FF_FF, offset: 0x100, expectNextPC: 0x18},
{name: "bltz zero rs", pc: 0x10, opcode: 0x1, regimm: 0x0, rs: 0x0, offset: 0x100, expectNextPC: 0x18},
{name: "bltz sign rs", pc: 0x10, opcode: 0x1, regimm: 0x0, rs: -1, offset: 0x100, expectNextPC: 0x414},
{name: "bltz rs only sign bit set", pc: 0x10, opcode: 0x1, regimm: 0x0, rs: testutil.ToSignedInteger(0x80_00_00_00), offset: 0x100, expectNextPC: 0x414},
{name: "bltz sign-extended offset", pc: 0x10, opcode: 0x1, regimm: 0x0, rs: -1, offset: 0x80_00, expectNextPC: 0xFF_FE_00_14},
{name: "bltz large offset no-sign", pc: 0x10, opcode: 0x1, regimm: 0x0, rs: -1, offset: 0x7F_FF, expectNextPC: 0x2_00_10},
// bgez t0, $x
{name: "bgez", pc: 0, opcode: 0x1, regimm: 0x1, rs: 0x5, offset: 0x100, expectNextPC: 0x404},
{name: "bgez large rs", pc: 0x10, opcode: 0x1, regimm: 0x1, rs: 0x7F_FF_FF_FF, offset: 0x100, expectNextPC: 0x414},
{name: "bgez zero rs", pc: 0x10, opcode: 0x1, regimm: 0x1, rs: 0x0, offset: 0x100, expectNextPC: 0x414},
{name: "bgez branch not taken", pc: 0x10, opcode: 0x1, regimm: 0x1, rs: -1, offset: 0x100, expectNextPC: 0x18},
{name: "bgez sign-extended offset", pc: 0x10, opcode: 0x1, regimm: 0x1, rs: 1, offset: 0x80_00, expectNextPC: 0xFF_FE_00_14},
{name: "bgez large offset no-sign", pc: 0x10, opcode: 0x1, regimm: 0x1, rs: 1, offset: 0x70_00, expectNextPC: 0x1_C0_14},
{name: "bgez fill bit offset except sign", pc: 0x10, opcode: 0x1, regimm: 0x1, rs: 1, offset: 0x7F_FF, expectNextPC: 0x2_00_10},
// bgezal t0, $x
{name: "bgezal", pc: 0, opcode: 0x1, regimm: 0x11, rs: 0x5, offset: 0x100, expectNextPC: 0x404, expectLink: true},
{name: "bgezal large rs", pc: 0x10, opcode: 0x1, regimm: 0x11, rs: 0x7F_FF_FF_FF, offset: 0x100, expectNextPC: 0x414, expectLink: true},
{name: "bgezal zero rs", pc: 0x10, opcode: 0x1, regimm: 0x11, rs: 0x0, offset: 0x100, expectNextPC: 0x414, expectLink: true},
{name: "bgezal branch not taken", pc: 0x10, opcode: 0x1, regimm: 0x11, rs: -1, offset: 0x100, expectNextPC: 0x18, expectLink: true},
{name: "bgezal sign-extended offset", pc: 0x10, opcode: 0x1, regimm: 0x11, rs: 1, offset: 0x80_00, expectNextPC: 0xFF_FE_00_14, expectLink: true},
{name: "bgezal large offset no-sign", pc: 0x10, opcode: 0x1, regimm: 0x11, rs: 1, offset: 0x70_00, expectNextPC: 0x1_C0_14, expectLink: true},
{name: "bgezal fill bit offset except sign", pc: 0x10, opcode: 0x1, regimm: 0x11, rs: 1, offset: 0x7F_FF, expectNextPC: 0x2_00_10, expectLink: true},
}
for _, v := range versions {
for i, tt := range cases {
testName := fmt.Sprintf("%v (%v)", tt.name, v.Name)
t.Run(testName, func(t *testing.T) {
goVm := v.VMFactory(nil, os.Stdout, os.Stderr, testutil.CreateLogger(), testutil.WithRandomization(int64(i)), testutil.WithPCAndNextPC(tt.pc))
state := goVm.GetState()
const rsReg = 8 // t0
insn := tt.opcode<<26 | rsReg<<21 | tt.regimm<<16 | uint32(tt.offset)
state.GetMemory().SetUint32(tt.pc, insn)
state.GetRegistersRef()[rsReg] = Word(tt.rs)
step := state.GetStep()
// Setup expectations
expected := testutil.NewExpectedState(state)
expected.Step += 1
expected.PC = state.GetCpu().NextPC
expected.NextPC = tt.expectNextPC
if tt.expectLink {
expected.Registers[31] = state.GetPC() + 8
}
stepWitness, err := goVm.Step(true)
require.NoError(t, err)
// Check expectations
expected.Validate(t, state)
testutil.ValidateEVM(t, stepWitness, step, goVm, v.StateHashFn, v.Contracts, tracer)
})
}
}
}
......@@ -1011,7 +1011,7 @@ func testEVM_SysClockGettime(t *testing.T, clkid Word) {
goVm, state, contracts := setup(t, 2101, nil)
mttestutil.InitializeSingleThread(2101+i, state, i%2 == 1)
effAddr := c.timespecAddr & arch.AddressMask
effAddr2 := effAddr + 4
effAddr2 := effAddr + arch.WordSizeBytes
step := state.Step
// Define LL-related params
......@@ -1121,6 +1121,8 @@ var NoopSyscalls = map[string]uint32{
"SysLlseek": 4140,
"SysMinCore": 4217,
"SysTgkill": 4266,
"SysGetRLimit": 4076,
"SysLseek": 4019,
"SysMunmap": 4091,
"SysSetITimer": 4104,
"SysTimerCreate": 4257,
......
......@@ -40,3 +40,9 @@ func SetMemoryUint64(t require.TestingT, mem *memory.Memory, addr Word, value ui
actual := mem.GetWord(effAddr)
require.Equal(t, Word(value), actual)
}
// ToSignedInteger converts the unsigend Word to a SignedInteger.
// Useful for avoiding Go compiler warnings for literals that don't fit in a signed type
func ToSignedInteger(x Word) arch.SignedInteger {
return arch.SignedInteger(x)
}
......@@ -6,6 +6,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/arch"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/program"
)
......@@ -26,3 +27,12 @@ func LoadELFProgram[T mipsevm.FPVMState](t require.TestingT, name string, initSt
require.NoError(t, program.PatchStack(state), "add initial stack")
return state, meta
}
// ProgramPath returns the appropriate ELF test program for the current architecture
func ProgramPath(programName string) string {
basename := programName + ".elf"
if !arch.IsMips32 {
basename = programName + ".64.elf"
}
return "../../testdata/example/bin/" + basename
}
......@@ -67,7 +67,7 @@ func StaticPrecompileOracle(t *testing.T, precompile common.Address, requiredGas
}
func ClaimTestOracle(t *testing.T) (po mipsevm.PreimageOracle, stdOut string, stdErr string) {
s := uint64(1000)
s := uint64(0x00FFFFFF_00001000)
a := uint64(3)
b := uint64(4)
......
......@@ -16,10 +16,14 @@ import (
"github.com/ethereum-optimism/optimism/cannon/mipsevm/program"
)
type VMFactory[T mipsevm.FPVMState] func(state T, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM
type VMFactory[T mipsevm.FPVMState] func(state T, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger, meta *program.Metadata) mipsevm.FPVM
type StateFactory[T mipsevm.FPVMState] func() T
func RunVMTests_OpenMips[T mipsevm.FPVMState](t *testing.T, stateFactory StateFactory[T], vmFactory VMFactory[T], excludedTests ...string) {
if !arch.IsMips32 {
// TODO: guard these tests by the cannon32 build tag
t.Skip("Open MIPS tests are not appropriate for cannon64")
}
testFiles, err := os.ReadDir("../tests/open_mips_tests/test/bin")
require.NoError(t, err)
......@@ -52,7 +56,7 @@ func RunVMTests_OpenMips[T mipsevm.FPVMState](t *testing.T, stateFactory StateFa
// set the return address ($ra) to jump into when test completes
state.GetRegistersRef()[31] = EndAddr
us := vmFactory(state, oracle, os.Stdout, os.Stderr, CreateLogger())
us := vmFactory(state, oracle, os.Stdout, os.Stderr, CreateLogger(), nil)
// Catch panics and check if they are expected
defer func() {
......@@ -94,12 +98,13 @@ func RunVMTests_OpenMips[T mipsevm.FPVMState](t *testing.T, stateFactory StateFa
}
func RunVMTest_Hello[T mipsevm.FPVMState](t *testing.T, initState program.CreateInitialFPVMState[T], vmFactory VMFactory[T], doPatchGo bool) {
state, _ := LoadELFProgram(t, "../../testdata/example/bin/hello.elf", initState, doPatchGo)
state, meta := LoadELFProgram(t, ProgramPath("hello"), initState, doPatchGo)
var stdOutBuf, stdErrBuf bytes.Buffer
us := vmFactory(state, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), CreateLogger())
us := vmFactory(state, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), CreateLogger(), meta)
for i := 0; i < 400_000; i++ {
maxSteps := 430_000
for i := 0; i < maxSteps; i++ {
if us.GetState().GetExited() {
break
}
......@@ -107,7 +112,7 @@ func RunVMTest_Hello[T mipsevm.FPVMState](t *testing.T, initState program.Create
require.NoError(t, err)
}
require.True(t, state.GetExited(), "must complete program")
require.Truef(t, state.GetExited(), "must complete program. reached %d of max %d steps", state.GetStep(), maxSteps)
require.Equal(t, uint8(0), state.GetExitCode(), "exit with 0")
require.Equal(t, "hello world!\n", stdOutBuf.String(), "stdout says hello")
......@@ -115,12 +120,12 @@ func RunVMTest_Hello[T mipsevm.FPVMState](t *testing.T, initState program.Create
}
func RunVMTest_Claim[T mipsevm.FPVMState](t *testing.T, initState program.CreateInitialFPVMState[T], vmFactory VMFactory[T], doPatchGo bool) {
state, _ := LoadELFProgram(t, "../../testdata/example/bin/claim.elf", initState, doPatchGo)
state, meta := LoadELFProgram(t, ProgramPath("claim"), initState, doPatchGo)
oracle, expectedStdOut, expectedStdErr := ClaimTestOracle(t)
var stdOutBuf, stdErrBuf bytes.Buffer
us := vmFactory(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), CreateLogger())
us := vmFactory(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), CreateLogger(), meta)
for i := 0; i < 2000_000; i++ {
if us.GetState().GetExited() {
......
all: elf
.PHONY: elf32
elf32: $(patsubst %/go.mod,bin/%.elf,$(wildcard */go.mod))
.PHONY: elf64
elf64: $(patsubst %/go.mod,bin/%.64.elf,$(wildcard */go.mod))
.PHONY: elf
elf: $(patsubst %/go.mod,bin/%.elf,$(wildcard */go.mod))
elf: elf32 elf64
.PHONY: dump
dump: $(patsubst %/go.mod,bin/%.dump,$(wildcard */go.mod))
......@@ -9,6 +15,9 @@ dump: $(patsubst %/go.mod,bin/%.dump,$(wildcard */go.mod))
bin:
mkdir bin
bin/%.64.elf: bin
cd $(@:bin/%.64.elf=%) && GOOS=linux GOARCH=mips64 GOMIPS64=softfloat go build -o ../$@ .
# take any directory with a go mod, and build an ELF
# verify output with: readelf -h bin/<name>.elf
# result is mips32, big endian, R3000
......
module alloc
go 1.22
go 1.22.0
toolchain go1.22.7
......
module claim
go 1.22
go 1.22.0
toolchain go1.22.7
......
module hello
go 1.22
go 1.22.0
toolchain go1.22.0
toolchain go1.22.7
module github.com/ethereum-optimism/optimism
go 1.22
go 1.22.0
toolchain go1.22.7
......@@ -47,11 +47,10 @@ require (
github.com/stretchr/testify v1.9.0
github.com/urfave/cli/v2 v2.27.5
golang.org/x/crypto v0.28.0
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c
golang.org/x/sync v0.8.0
golang.org/x/term v0.25.0
golang.org/x/time v0.7.0
lukechampine.com/uint128 v1.3.0
)
require (
......@@ -95,7 +94,7 @@ require (
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/felixge/fgprof v0.9.3 // indirect
github.com/felixge/fgprof v0.9.5 // indirect
github.com/ferranbt/fastssz v0.1.2 // indirect
github.com/flynn/noise v1.1.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
......@@ -114,7 +113,7 @@ require (
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
github.com/google/pprof v0.0.0-20241009165004-a3522334989c // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/graph-gophers/graphql-go v1.3.0 // indirect
......@@ -234,11 +233,11 @@ require (
go.uber.org/mock v0.4.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/mod v0.20.0 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/tools v0.24.0 // indirect
golang.org/x/tools v0.26.0 // indirect
google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 // indirect
......
This diff is collapsed.
......@@ -140,12 +140,12 @@
"sourceCodeHash": "0x2ab6be69795109a1ee04c5693a34d6ce0ff90b62e404cdeb18178bab18d06784"
},
"src/cannon/MIPS.sol": {
"initCodeHash": "0x8fb590d45fa06fdc7ae55860827d6b1abf070c9dc5e18cd28176e844fa1da6c9",
"sourceCodeHash": "0x01d3d59020ec29ce78f68f977da5b7754455743121bda65626509864ab6c9da9"
"initCodeHash": "0x696c3ce334c11d0f9633945babac22b1b65848ff00d2cf6c4cb18116bbf138b2",
"sourceCodeHash": "0x3c2e5d6d39b29a60dcd1a776363518c87fcfef9a8d80e38696f56b6eec5bd53a"
},
"src/cannon/MIPS2.sol": {
"initCodeHash": "0x88acf3297642c2c9e0c1e92b48f59f7015915f25fb816cac44ee0073a1c93ccb",
"sourceCodeHash": "0x3dd89839f268569cbf2659beb42e3ac3c53887472cfc94a6e339d2b3a963b941"
"initCodeHash": "0x5c292882075bd06e68b89119be9096040bc913f51bb878ce4a9dfdd674330dd5",
"sourceCodeHash": "0x17c7b0edb9d20932eaf1b038e3e05e457f0461d2c8691ba1940fb4c2b0dfd123"
},
"src/cannon/PreimageOracle.sol": {
"initCodeHash": "0x5d7e8ae64f802bd9d760e3d52c0a620bd02405dc2c8795818db9183792ffe81c",
......
......@@ -44,8 +44,8 @@ contract MIPS is ISemver {
}
/// @notice The semantic version of the MIPS contract.
/// @custom:semver 1.2.1-beta.4
string public constant version = "1.2.1-beta.4";
/// @custom:semver 1.2.1-beta.5
string public constant version = "1.2.1-beta.5";
/// @notice The preimage oracle contract.
IPreimageOracle internal immutable ORACLE;
......
......@@ -60,8 +60,8 @@ contract MIPS2 is ISemver {
}
/// @notice The semantic version of the MIPS2 contract.
/// @custom:semver 1.0.0-beta.17
string public constant version = "1.0.0-beta.17";
/// @custom:semver 1.0.0-beta.18
string public constant version = "1.0.0-beta.18";
/// @notice The preimage oracle contract.
IPreimageOracle internal immutable ORACLE;
......@@ -593,6 +593,10 @@ contract MIPS2 is ISemver {
// ignored
} else if (syscall_no == sys.SYS_TIMERDELETE) {
// ignored
} else if (syscall_no == sys.SYS_GETRLIMIT) {
// ignored
} else if (syscall_no == sys.SYS_LSEEK) {
// ignored
} else {
if (syscall_no == sys.SYS_FSTAT64 || syscall_no == sys.SYS_STAT64 || syscall_no == sys.SYS_LLSEEK) {
// noop
......
......@@ -7,6 +7,7 @@ import { MIPSState as st } from "src/cannon/libraries/MIPSState.sol";
library MIPSInstructions {
uint32 internal constant OP_LOAD_LINKED = 0x30;
uint32 internal constant OP_STORE_CONDITIONAL = 0x38;
uint32 internal constant REG_RA = 31;
struct CoreStepLogicParams {
/// @param opcode The opcode value parsed from insn_.
......@@ -501,6 +502,11 @@ library MIPSInstructions {
if (rtv == 1) {
shouldBranch = int32(_rs) >= 0;
}
// bgezal (i.e. bal mnemonic)
if (rtv == 0x11) {
shouldBranch = int32(_rs) >= 0;
_registers[REG_RA] = _cpu.pc + 8; // always set regardless of branch taken
}
}
// Update the state's previous PC
......
......@@ -71,6 +71,8 @@ library MIPSSyscalls {
uint32 internal constant SYS_LLSEEK = 4140;
uint32 internal constant SYS_MINCORE = 4217;
uint32 internal constant SYS_TGKILL = 4266;
uint32 internal constant SYS_GETRLIMIT = 4076;
uint32 internal constant SYS_LSEEK = 4019;
// profiling-related syscalls - ignored
uint32 internal constant SYS_SETITIMER = 4104;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment