Commit b8921436 authored by smartcontracts's avatar smartcontracts Committed by Adrian Sutton

fix: correctly verify mips instruction encoding (#237)

A lot of instructions in the MIPS spec require that certain fields
be set to zero. Most of the time this isn't actually a problem but
this can cause side-effects in a few cases. A buggy compiler could
create an issue if it ever spit out non-compliant instructions.
This PR implements those zero value enforcement checks for all
instructions that we implement.
parent db61d2bb
...@@ -78,6 +78,9 @@ func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memor ...@@ -78,6 +78,9 @@ func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memor
} }
} }
// Verify that the instruction is properly encoded.
CheckZeroEncoding(insn)
// ALU // ALU
val := ExecuteMipsInstruction(insn, opcode, fun, rs, rt, mem) val := ExecuteMipsInstruction(insn, opcode, fun, rs, rt, mem)
...@@ -120,6 +123,56 @@ func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memor ...@@ -120,6 +123,56 @@ func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memor
return HandleRd(cpu, registers, rdReg, val, true) return HandleRd(cpu, registers, rdReg, val, true)
} }
func CheckZeroEncoding(insn uint32) {
// Pick out the opcode and function code.
opcode := uint8(insn >> 26)
funcCode := uint8(insn & 0x3F)
// Pick out the registers.
rs := uint8((insn >> 21) & 0x1F)
rt := uint8((insn >> 16) & 0x1F)
rd := uint8((insn >> 11) & 0x1F)
shamt := uint8((insn >> 6) & 0x1F)
// Checks for R-type instructions.
if opcode == 0x00 {
// Check for zero rs.
if funcCode == 0x00 || funcCode == 0x02 || funcCode == 0x03 || funcCode == 0x10 || funcCode == 0x12 {
if rs != 0 {
panic("rs not zero")
}
}
// Check for zero rt.
if funcCode == 0x08 || funcCode == 0x09 || (funcCode >= 0x10 && funcCode <= 0x13) {
if rt != 0 {
panic("rt not zero")
}
}
// Check for zero rd.
if funcCode == 0x08 || funcCode == 0x11 || funcCode == 0x13 || (funcCode >= 0x18 && funcCode <= 0x1B) {
if rd != 0 {
panic("rd not zero")
}
}
// Check for zero shamt.
if funcCode == 0x08 || funcCode == 0x09 || funcCode == 0x0F || (funcCode >= 0x10 && funcCode <= 0x13) || (funcCode >= 0x18 && funcCode <= 0x1B) || (funcCode >= 0x20 && funcCode <= 0x27) || funcCode == 0x2A || funcCode == 0x2B {
if shamt != 0 {
panic("shamt not zero")
}
}
}
// Check for zero rs in LUI.
if opcode == 0x0F {
if rs != 0 {
panic("rs not zero")
}
}
}
func ExecuteMipsInstruction(insn, opcode, fun, rs, rt, mem uint32) uint32 { func ExecuteMipsInstruction(insn, opcode, fun, rs, rt, mem uint32) uint32 {
if opcode == 0 || (opcode >= 8 && opcode < 0xF) { if opcode == 0 || (opcode >= 8 && opcode < 0xF) {
// transform ArithLogI to SPECIAL // transform ArithLogI to SPECIAL
......
...@@ -103,6 +103,8 @@ func TestEVM(t *testing.T) { ...@@ -103,6 +103,8 @@ func TestEVM(t *testing.T) {
require.NotEqual(t, uint32(testutil.EndAddr), goState.GetState().GetPC(), "must not reach end") require.NotEqual(t, uint32(testutil.EndAddr), goState.GetState().GetPC(), "must not reach end")
require.True(t, goState.GetState().GetExited(), "must set exited state") require.True(t, goState.GetState().GetExited(), "must set exited state")
require.Equal(t, uint8(1), goState.GetState().GetExitCode(), "must exit with 1") require.Equal(t, uint8(1), goState.GetState().GetExitCode(), "must exit with 1")
} else if expectPanic {
require.NotEqual(t, uint32(testutil.EndAddr), state.Cpu.PC, "must not reach end")
} else { } else {
require.Equal(t, uint32(testutil.EndAddr), state.Cpu.PC, "must reach end") require.Equal(t, uint32(testutil.EndAddr), state.Cpu.PC, "must reach end")
// inspect test result // inspect test result
......
# Utility for generating assembly test files for the MIPS instructions that panic when specific
# fields in the encoded instruction are nonzero. Using a script to do this is much less prone to
# human error than writing these tests by hand.
import os
# Format is (opcode, funct, shamt, rd, rt, rs, field_to_make_nonzero)
tests = {
'ADD': [('000000', '100000', '00001', '01011', '01010', '01001', 'shamt')], # SHAMT nonzero
'ADDU': [('000000', '100001', '00001', '01011', '01010', '01001', 'shamt')], # SHAMT nonzero
'AND': [('000000', '100100', '00001', '01011', '01010', '01001', 'shamt')], # SHAMT nonzero
'DIV': [
('000000', '011010', '00001', '01010', '00000', '01001', 'rd'), # RD nonzero
('000000', '011010', '00001', '00000', '01010', '01001', 'shamt'), # SHAMT nonzero
],
'DIVU': [
('000000', '011011', '00001', '01010', '00000', '01001', 'rd'), # RD nonzero
('000000', '011011', '00001', '00000', '01010', '01001', 'shamt'), # SHAMT nonzero
],
'JALR': [
('000000', '001001', '00000', '01011', '01001', '01010', 'rt'), # RT nonzero
('000000', '001001', '00001', '01011', '01001', '00000', 'shamt'), # SHAMT nonzero
],
'JR': [
('000000', '001000', '00000', '01011', '01001', '00000', 'rd'), # RD nonzero
('000000', '001000', '00000', '00000', '01001', '01010', 'rt'), # RT nonzero
('000000', '001000', '00001', '00000', '01001', '00000', 'shamt'), # SHAMT nonzero
],
'LUI': [('001111', '00000', '01010', '00000', '00000', '01001', 'rs')], # RS nonzero
'MFHI': [
('000000', '010000', '00000', '01011', '01010', '00000', 'rt'), # RT nonzero
('000000', '010000', '00001', '01011', '00000', '00000', 'shamt'), # SHAMT nonzero
('000000', '010000', '00000', '01011', '00000', '01001', 'rs'), # RS nonzero
],
'MFLO': [
('000000', '010010', '00000', '01011', '01010', '00000', 'rt'), # RT nonzero
('000000', '010010', '00001', '01011', '00000', '00000', 'shamt'), # SHAMT nonzero
('000000', '010010', '00000', '01011', '00000', '01001', 'rs'), # RS nonzero
],
'MTHI': [
('000000', '010001', '00000', '01011', '01010', '00000', 'rd'), # RD nonzero
('000000', '010001', '00000', '01001', '01010', '00000', 'rt'), # RT nonzero
('000000', '010001', '00001', '01001', '00000', '00000', 'shamt'), # SHAMT nonzero
],
'MTLO': [
('000000', '010011', '00000', '01011', '01010', '00000', 'rd'), # RD nonzero
('000000', '010011', '00000', '01001', '01010', '00000', 'rt'), # RT nonzero
('000000', '010011', '00001', '01001', '00000', '00000', 'shamt'), # SHAMT nonzero
],
'MULT': [
('000000', '011000', '00000', '01011', '01010', '00000', 'rd'), # RD nonzero
('000000', '011000', '00001', '00000', '01010', '01001', 'shamt'), # SHAMT nonzero
],
'MULTU': [
('000000', '011001', '00000', '01011', '01010', '00000', 'rd'), # RD nonzero
('000000', '011001', '00001', '00000', '01010', '01001', 'shamt'), # SHAMT nonzero
],
'NOR': [('000000', '100111', '00001', '01011', '01010', '01001', 'shamt')], # SHAMT nonzero
'OR': [('000000', '100101', '00001', '01011', '01010', '01001', 'shamt')], # SHAMT nonzero
'SLL': [('000000', '000000', '00001', '01011', '01010', '01001', 'shamt')], # SHAMT nonzero
'SLT': [('000000', '101010', '00001', '01011', '01010', '01001', 'shamt')], # SHAMT nonzero
'SLTU': [('000000', '101011', '00001', '01011', '01010', '01001', 'shamt')], # SHAMT nonzero
'SRA': [
('000000', '000011', '00001', '01011', '01010', '01001', 'shamt'), # SHAMT nonzero
('000000', '000011', '00000', '01011', '01010', '01001', 'rs'), # RS nonzero
],
'SRL': [
('000000', '000010', '00001', '01011', '01010', '01001', 'shamt'), # SHAMT nonzero
('000000', '000010', '00000', '01011', '01010', '01001', 'rs'), # RS nonzero
],
'SUB': [('000000', '100010', '00001', '01011', '01010', '01001', 'shamt')], # SHAMT nonzero
'SUBU': [('000000', '100011', '00001', '01011', '01010', '01001', 'shamt')], # SHAMT nonzero
'SYNC': [('000000', '001111', '00001', '00000', '00000', '00000', 'shamt')], # SHAMT nonzero
'XOR': [('000000', '100110', '00001', '01011', '01010', '01001', 'shamt')], # SHAMT nonzero
}
def pad_to_length(binary_str, length):
return binary_str.zfill(length)
def generate_instruction(opcode, rs, rt, rd, shamt, funct):
binary_instruction = (
pad_to_length(opcode, 6) +
pad_to_length(rs, 5) +
pad_to_length(rt, 5) +
pad_to_length(rd, 5) +
pad_to_length(shamt, 5) +
pad_to_length(funct, 6)
)
hex_instruction = hex(int(binary_instruction, 2))[2:].zfill(8)
return '0x' + hex_instruction
def create_test_file(instruction, field, hex_instruction):
return f"""###############################################################################
# Description:
# Tests that the '{instruction.lower()}' instruction panics when the {field} field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid {instruction} (nonzero {field} field)
.word {hex_instruction}
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
"""
def write_test_file(filename, content):
os.makedirs('./test', exist_ok=True)
with open(f'./test/{filename}', 'w') as file:
file.write(content)
for instr, cases in tests.items():
for params in cases:
opcode, funct, shamt, rd, rt, rs, field = params
hex_instr = generate_instruction(opcode, rs, rt, rd, shamt, funct)
test_content = create_test_file(instr, field, hex_instr)
filename = f"{instr.lower()}_nonzero_{field}_panic.asm"
write_test_file(filename, test_content)
###############################################################################
# Description:
# Tests that the 'add' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid ADD (nonzero shamt field)
.word 0x012a5860
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'addu' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid ADDU (nonzero shamt field)
.word 0x012a5861
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'and' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid AND (nonzero shamt field)
.word 0x012a5864
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'div' instruction panics when the rd field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid DIV (nonzero rd field)
.word 0x0120505a
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'div' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid DIV (nonzero shamt field)
.word 0x012a005a
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'divu' instruction panics when the rd field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid DIVU (nonzero rd field)
.word 0x0120505b
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'divu' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid DIVU (nonzero shamt field)
.word 0x012a005b
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'jalr' instruction panics when the rt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid JALR (nonzero rt field)
.word 0x01495809
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'jalr' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid JALR (nonzero shamt field)
.word 0x00095849
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'jr' instruction panics when the rd field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid JR (nonzero rd field)
.word 0x00095808
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'jr' instruction panics when the rt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid JR (nonzero rt field)
.word 0x01490008
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'jr' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid JR (nonzero shamt field)
.word 0x00090048
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'lui' instruction panics when the rs field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid LUI (nonzero rs field)
.word 0x3d200280
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mfhi' instruction panics when the rs field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MFHI (nonzero rs field)
.word 0x01205810
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mfhi' instruction panics when the rt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MFHI (nonzero rt field)
.word 0x000a5810
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mfhi' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MFHI (nonzero shamt field)
.word 0x00005850
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mflo' instruction panics when the rs field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MFLO (nonzero rs field)
.word 0x01205812
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mflo' instruction panics when the rt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MFLO (nonzero rt field)
.word 0x000a5812
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mflo' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MFLO (nonzero shamt field)
.word 0x00005852
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mthi' instruction panics when the rd field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MTHI (nonzero rd field)
.word 0x000a5811
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mthi' instruction panics when the rt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MTHI (nonzero rt field)
.word 0x000a4811
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mthi' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MTHI (nonzero shamt field)
.word 0x00004851
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mtlo' instruction panics when the rd field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MTLO (nonzero rd field)
.word 0x000a5813
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mtlo' instruction panics when the rt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MTLO (nonzero rt field)
.word 0x000a4813
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mtlo' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MTLO (nonzero shamt field)
.word 0x00004853
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mult' instruction panics when the rd field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MULT (nonzero rd field)
.word 0x000a5818
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'mult' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MULT (nonzero shamt field)
.word 0x012a0058
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'multu' instruction panics when the rd field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MULTU (nonzero rd field)
.word 0x000a5819
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'multu' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid MULTU (nonzero shamt field)
.word 0x012a0059
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'nor' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid NOR (nonzero shamt field)
.word 0x012a5867
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'or' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid OR (nonzero shamt field)
.word 0x012a5865
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'sll' instruction panics when the rs field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid SLL (nonzero SHAMT)
.word 0x00200000
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'sll' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid SLL (nonzero shamt field)
.word 0x012a5840
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'slt' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid SLT (nonzero shamt field)
.word 0x012a586a
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'sltu' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid SLTU (nonzero shamt field)
.word 0x012a586b
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'sra' instruction panics when the rs field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid SRA (nonzero rs field)
.word 0x012a5803
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'sra' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid SRA (nonzero shamt field)
.word 0x012a5843
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'srl' instruction panics when the rs field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid SRL (nonzero rs field)
.word 0x012a5802
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'srl' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid SRL (nonzero shamt field)
.word 0x012a5842
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'sub' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid SUB (nonzero shamt field)
.word 0x012a5862
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'subu' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid SUBU (nonzero shamt field)
.word 0x012a5863
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'sync' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid SYNC (nonzero shamt field)
.word 0x0000004f
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
###############################################################################
# Description:
# Tests that the 'xor' instruction panics when the shamt field is nonzero.
#
###############################################################################
.section .test, "x"
.balign 4
.set noreorder
.global test
.ent test
test:
lui $s0, 0xbfff
ori $s0, 0xfff0
ori $s1, $0, 1
# Invalid XOR (nonzero shamt field)
.word 0x012a5866
sw $zero, 8($s0)
sw $s1, 4($s0)
$done:
jr $ra
nop
.end test
...@@ -79,6 +79,8 @@ func RunVMTests_OpenMips[T mipsevm.FPVMState](t *testing.T, stateFactory StateFa ...@@ -79,6 +79,8 @@ func RunVMTests_OpenMips[T mipsevm.FPVMState](t *testing.T, stateFactory StateFa
require.NotEqual(t, uint32(EndAddr), us.GetState().GetPC(), "must not reach end") require.NotEqual(t, uint32(EndAddr), us.GetState().GetPC(), "must not reach end")
require.True(t, us.GetState().GetExited(), "must set exited state") require.True(t, us.GetState().GetExited(), "must set exited state")
require.Equal(t, uint8(1), us.GetState().GetExitCode(), "must exit with 1") require.Equal(t, uint8(1), us.GetState().GetExitCode(), "must exit with 1")
} else if expectPanic {
require.NotEqual(t, uint32(EndAddr), us.GetState().GetPC(), "must not reach end")
} else { } else {
require.Equal(t, uint32(EndAddr), us.GetState().GetPC(), "must reach end") require.Equal(t, uint32(EndAddr), us.GetState().GetPC(), "must reach end")
done, result := state.GetMemory().GetMemory(BaseAddrEnd+4), state.GetMemory().GetMemory(BaseAddrEnd+8) done, result := state.GetMemory().GetMemory(BaseAddrEnd+4), state.GetMemory().GetMemory(BaseAddrEnd+8)
......
...@@ -140,11 +140,11 @@ ...@@ -140,11 +140,11 @@
"sourceCodeHash": "0x3ff4a3f21202478935412d47fd5ef7f94a170402ddc50e5c062013ce5544c83f" "sourceCodeHash": "0x3ff4a3f21202478935412d47fd5ef7f94a170402ddc50e5c062013ce5544c83f"
}, },
"src/cannon/MIPS.sol": { "src/cannon/MIPS.sol": {
"initCodeHash": "0x8c59913b880e1529a543657e24ac30b17c2ce901b4309211b5c2bc703219271d", "initCodeHash": "0xc783f01a426b889cd80d242cf01901fc34c595e59e74d50e3a0a8cb1fa226b3f",
"sourceCodeHash": "0xfa6e6eacba6be2c9489f828f8a50dda40565eef5c73a2cf8e274e1fd4410d38a" "sourceCodeHash": "0xfa6e6eacba6be2c9489f828f8a50dda40565eef5c73a2cf8e274e1fd4410d38a"
}, },
"src/cannon/MIPS2.sol": { "src/cannon/MIPS2.sol": {
"initCodeHash": "0xf3ff16b352e256534761844d49e159c267dd09e79bc9ddec78d0c90f8746ea20", "initCodeHash": "0xeac747751362183e6e0e4caa34f07284823449867897a39bd036db5ea189e2c7",
"sourceCodeHash": "0x115bd6a4c4d77ed210dfd468675b409fdae9f79b932063c138f0765ba9063462" "sourceCodeHash": "0x115bd6a4c4d77ed210dfd468675b409fdae9f79b932063c138f0765ba9063462"
}, },
"src/cannon/PreimageOracle.sol": { "src/cannon/PreimageOracle.sol": {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -122,6 +122,9 @@ library MIPSInstructions { ...@@ -122,6 +122,9 @@ library MIPSInstructions {
} }
} }
// Verify that the instruction is properly encoded.
checkZeroEncoding(_insn);
// ALU // ALU
// Note: swr outputs more than 4 bytes without the mask 0xffFFffFF // Note: swr outputs more than 4 bytes without the mask 0xffFFffFF
uint32 val = executeMipsInstruction(_insn, _opcode, _fun, rs, rt, mem) & 0xffFFffFF; uint32 val = executeMipsInstruction(_insn, _opcode, _fun, rs, rt, mem) & 0xffFFffFF;
...@@ -170,6 +173,81 @@ library MIPSInstructions { ...@@ -170,6 +173,81 @@ library MIPSInstructions {
} }
} }
/// @notice Checks if an instruction is properly encoded with zeroes in the right places as per
/// the MIPS instruction encoding rules defined in the MIPS specification. Reverts if
/// the instruction is not properly encoded. Proper encoding is generally not harmful
/// but can potentially have side-effects for specific opcodes.
/// @param _insn Encoded instruction to check.
function checkZeroEncoding(uint32 _insn) internal pure {
// Pick out the opcode and function code.
uint8 opcode = uint8(_insn >> 26);
uint8 func = uint8(_insn & 0x3F);
// Pick out the registers.
uint8 rs = uint8((_insn >> 21) & 0x1F);
uint8 rt = uint8((_insn >> 16) & 0x1F);
uint8 rd = uint8((_insn >> 11) & 0x1F);
uint8 shamt = uint8((_insn >> 6) & 0x1F);
// Checks for R-type instructions.
if (opcode == 0x00) {
// Check for zero rs.
if (
// SLL, SRL, SRA
func == 0x00 || func == 0x02 || func == 0x03
// MFHI, MFLO
|| func == 0x10 || func == 0x12
) {
require(rs == 0, "MIPS: rs not zero");
}
// Check for zero rt.
if (
// JR, JALR
func == 0x08 || func == 0x09
// MFHI, MFLO, MTHI, MTLO
|| (func >= 0x10 && func <= 0x13)
) {
require(rt == 0, "MIPS: rt not zero");
}
// Check for zero rd.
if (
// JR
func == 0x08
// MTHI, MTLO
|| func == 0x11 || func == 0x13
// MULT, MULTU, DIV, DIVU
|| (func >= 0x18 && func <= 0x1B)
) {
require(rd == 0, "MIPS: rd not zero");
}
// Check for zero shamt.
if (
// JR, JALR
func == 0x08 || func == 0x09
// SYNC
|| func == 0x0F
// MFHI, MFLO, MTHI, MTLO
|| (func >= 0x10 && func <= 0x13)
// MULT, MULTU, DIV, DIVU
|| (func >= 0x18 && func <= 0x1B)
// ADD, ADDU, SUB, SUBU, AND, OR, XOR, NOR
|| (func >= 0x20 && func <= 0x27)
// SLT, SLTU
|| func == 0x2A || func == 0x2B
) {
require(shamt == 0, "MIPS: shamt not zero");
}
}
// Check for zero rs in LUI.
if (opcode == 0x0F) {
require(rs == 0, "MIPS: rs not zero");
}
}
/// @notice Execute an instruction. /// @notice Execute an instruction.
function executeMipsInstruction( function executeMipsInstruction(
uint32 _insn, uint32 _insn,
......
...@@ -140,6 +140,18 @@ contract MIPS_Test is CommonTest { ...@@ -140,6 +140,18 @@ contract MIPS_Test is CommonTest {
mips.step(encodedState, proof, 0); mips.step(encodedState, proof, 0);
} }
function test_add_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x20); // add t0, s1, s2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = 12;
state.registers[18] = 20;
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodedState, proof, 0);
}
function test_addu_succeeds() external { function test_addu_succeeds() external {
uint32 insn = encodespec(17, 18, 8, 0x21); // addu t0, s1, s2 uint32 insn = encodespec(17, 18, 8, 0x21); // addu t0, s1, s2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
...@@ -189,6 +201,18 @@ contract MIPS_Test is CommonTest { ...@@ -189,6 +201,18 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_addu_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x21); // addu t0, s1, s2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = 12;
state.registers[18] = 20;
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodedState, proof, 0);
}
function test_addi_succeeds() external { function test_addi_succeeds() external {
uint16 imm = 40; uint16 imm = 40;
uint32 insn = encodeitype(0x8, 17, 8, imm); // addi t0, s1, 40 uint32 insn = encodeitype(0x8, 17, 8, imm); // addi t0, s1, 40
...@@ -371,6 +395,18 @@ contract MIPS_Test is CommonTest { ...@@ -371,6 +395,18 @@ contract MIPS_Test is CommonTest {
mips.step(encodedState, proof, 0); mips.step(encodedState, proof, 0);
} }
function test_sub_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x22); // sub t0, s1, s2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = 20;
state.registers[18] = 12;
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodedState, proof, 0);
}
function test_subu_succeeds() external { function test_subu_succeeds() external {
uint32 insn = encodespec(17, 18, 8, 0x23); // subu t0, s1, s2 uint32 insn = encodespec(17, 18, 8, 0x23); // subu t0, s1, s2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
...@@ -420,6 +456,18 @@ contract MIPS_Test is CommonTest { ...@@ -420,6 +456,18 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_subu_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x23); // subu t0, s1, s2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = 20;
state.registers[18] = 12;
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodedState, proof, 0);
}
function test_and_succeeds() external { function test_and_succeeds() external {
uint32 insn = encodespec(17, 18, 8, 0x24); // and t0, s1, s2 uint32 insn = encodespec(17, 18, 8, 0x24); // and t0, s1, s2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
...@@ -440,6 +488,18 @@ contract MIPS_Test is CommonTest { ...@@ -440,6 +488,18 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_and_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x24); // and t0, s1, s2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = 1200;
state.registers[18] = 490;
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodedState, proof, 0);
}
function test_andi_succeeds() external { function test_andi_succeeds() external {
uint16 imm = 40; uint16 imm = 40;
uint32 insn = encodeitype(0xc, 17, 8, imm); // andi t0, s1, 40 uint32 insn = encodeitype(0xc, 17, 8, imm); // andi t0, s1, 40
...@@ -480,6 +540,18 @@ contract MIPS_Test is CommonTest { ...@@ -480,6 +540,18 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_or_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x25); // or t0, s1, s2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = 1200;
state.registers[18] = 490;
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodedState, proof, 0);
}
function test_ori_succeeds() external { function test_ori_succeeds() external {
uint16 imm = 40; uint16 imm = 40;
uint32 insn = encodeitype(0xd, 17, 8, imm); // ori t0, s1, 40 uint32 insn = encodeitype(0xd, 17, 8, imm); // ori t0, s1, 40
...@@ -520,6 +592,18 @@ contract MIPS_Test is CommonTest { ...@@ -520,6 +592,18 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_xor_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x26); // xor t0, s1, s2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = 1200;
state.registers[18] = 490;
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodedState, proof, 0);
}
function test_xori_succeeds() external { function test_xori_succeeds() external {
uint16 imm = 40; uint16 imm = 40;
uint32 insn = encodeitype(0xe, 17, 8, imm); // xori t0, s1, 40 uint32 insn = encodeitype(0xe, 17, 8, imm); // xori t0, s1, 40
...@@ -560,6 +644,18 @@ contract MIPS_Test is CommonTest { ...@@ -560,6 +644,18 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_nor_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x27); // nor t0, s1, s2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = 1200;
state.registers[18] = 490;
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodedState, proof, 0);
}
function test_slt_succeeds() external { function test_slt_succeeds() external {
uint32 insn = encodespec(17, 18, 8, 0x2a); // slt t0, s1, s2 uint32 insn = encodespec(17, 18, 8, 0x2a); // slt t0, s1, s2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
...@@ -589,6 +685,18 @@ contract MIPS_Test is CommonTest { ...@@ -589,6 +685,18 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_slt_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x2a); // slt t0, s1, s2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = 0xFF_FF_FF_FE; // -2
state.registers[18] = 5;
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodedState, proof, 0);
}
function test_sltu_succeeds() external { function test_sltu_succeeds() external {
uint32 insn = encodespec(17, 18, 8, 0x2b); // sltu t0, s1, s2 uint32 insn = encodespec(17, 18, 8, 0x2b); // sltu t0, s1, s2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
...@@ -609,6 +717,18 @@ contract MIPS_Test is CommonTest { ...@@ -609,6 +717,18 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_sltu_shamtNotZero_fails() external {
uint32 insn = encodespec(17, 18, 8, 0x2b); // sltu t0, s1, s2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[17] = 1200;
state.registers[18] = 490;
bytes memory encodedState = encodeState(state);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodedState, proof, 0);
}
function test_lb_succeeds() external { function test_lb_succeeds() external {
uint32 t1 = 0x100; uint32 t1 = 0x100;
uint32 insn = encodeitype(0x20, 0x9, 0x8, 0x4); // lb $t0, 4($t1) uint32 insn = encodeitype(0x20, 0x9, 0x8, 0x4); // lb $t0, 4($t1)
...@@ -975,6 +1095,31 @@ contract MIPS_Test is CommonTest { ...@@ -975,6 +1095,31 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_mflo_shamtNotZero_fails() external {
uint32 insn = encodespec(0x0, 0x0, 0x8, 0x12); // mflo $t0
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_mflo_rtNotZero_fails() external {
uint32 insn = encodespec(0x0, 0x1, 0x8, 0x12); // mflo $t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_mflo_rsNotZero_fails() external {
uint32 insn = encodespec(0x1, 0x0, 0x8, 0x12); // mflo $t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rs not zero");
mips.step(encodeState(state), proof, 0);
}
function test_mfhi_succeeds() external { function test_mfhi_succeeds() external {
uint32 insn = encodespec(0x0, 0x0, 0x8, 0x10); // mfhi $t0 uint32 insn = encodespec(0x0, 0x0, 0x8, 0x10); // mfhi $t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
...@@ -992,6 +1137,31 @@ contract MIPS_Test is CommonTest { ...@@ -992,6 +1137,31 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_mfhi_shamtNotZero_fails() external {
uint32 insn = encodespec(0x0, 0x0, 0x8, 0x10); // mfhi $t0
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_mfhi_rtNotZero_fails() external {
uint32 insn = encodespec(0x0, 0x1, 0x8, 0x10); // mfhi $t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_mfhi_rsNotZero_fails() external {
uint32 insn = encodespec(0x1, 0x0, 0x8, 0x10); // mfhi $t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rs not zero");
mips.step(encodeState(state), proof, 0);
}
function test_mthi_succeeds() external { function test_mthi_succeeds() external {
uint32 insn = encodespec(0x8, 0x0, 0x0, 0x11); // mthi $t0 uint32 insn = encodespec(0x8, 0x0, 0x0, 0x11); // mthi $t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
...@@ -1009,6 +1179,31 @@ contract MIPS_Test is CommonTest { ...@@ -1009,6 +1179,31 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_mthi_shamtNotZero_fails() external {
uint32 insn = encodespec(0x8, 0x0, 0x0, 0x11); // mthi $t0
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_mthi_rtNotZero_fails() external {
uint32 insn = encodespec(0x8, 0x1, 0x0, 0x11); // mthi $t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_mthi_rdNotZero_fails() external {
uint32 insn = encodespec(0x8, 0x0, 0x1, 0x11); // mthi $t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rd not zero");
mips.step(encodeState(state), proof, 0);
}
function test_mtlo_succeeds() external { function test_mtlo_succeeds() external {
uint32 insn = encodespec(0x8, 0x0, 0x0, 0x13); // mtlo $t0 uint32 insn = encodespec(0x8, 0x0, 0x0, 0x13); // mtlo $t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
...@@ -1026,6 +1221,31 @@ contract MIPS_Test is CommonTest { ...@@ -1026,6 +1221,31 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_mtlo_shamtNotZero_fails() external {
uint32 insn = encodespec(0x8, 0x0, 0x0, 0x13); // mtlo $t0
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_mtlo_rtNotZero_fails() external {
uint32 insn = encodespec(0x8, 0x1, 0x0, 0x13); // mtlo $t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_mtlo_rdNotZero_fails() external {
uint32 insn = encodespec(0x8, 0x0, 0x1, 0x13); // mtlo $t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rd not zero");
mips.step(encodeState(state), proof, 0);
}
function test_mul_succeeds() external { function test_mul_succeeds() external {
uint32 insn = encodespec2(0x9, 0xa, 0x8, 0x2); // mul t0, t1, t2 uint32 insn = encodespec2(0x9, 0xa, 0x8, 0x2); // mul t0, t1, t2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
...@@ -1066,6 +1286,25 @@ contract MIPS_Test is CommonTest { ...@@ -1066,6 +1286,25 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_mult_shamtNotZero_fails() external {
uint32 insn = encodespec(0x9, 0xa, 0x0, 0x18); // mult t1, t2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[9] = 0x0F_FF_00_00; // t1
state.registers[10] = 100; // t2
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_mult_rdNotZero_fails() external {
uint32 insn = encodespec(0x9, 0xa, 0x1, 0x18); // mult t1, t2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rd not zero");
mips.step(encodeState(state), proof, 0);
}
function test_multu_succeeds() external { function test_multu_succeeds() external {
uint32 insn = encodespec(0x9, 0xa, 0x0, 0x19); // multu t1, t2 uint32 insn = encodespec(0x9, 0xa, 0x0, 0x19); // multu t1, t2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
...@@ -1087,6 +1326,25 @@ contract MIPS_Test is CommonTest { ...@@ -1087,6 +1326,25 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_multu_shamtNotZero_fails() external {
uint32 insn = encodespec(0x9, 0xa, 0x0, 0x19); // multu t1, t2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[9] = 0x0F_FF_00_00; // t1
state.registers[10] = 100; // t2
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_multu_rdNotZero_fails() external {
uint32 insn = encodespec(0x9, 0xa, 0x1, 0x19); // multu t1, t2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rd not zero");
mips.step(encodeState(state), proof, 0);
}
function test_div_succeeds() external { function test_div_succeeds() external {
uint32 insn = encodespec(0x9, 0xa, 0x0, 0x1a); // div t1, t2 uint32 insn = encodespec(0x9, 0xa, 0x0, 0x1a); // div t1, t2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
...@@ -1108,6 +1366,27 @@ contract MIPS_Test is CommonTest { ...@@ -1108,6 +1366,27 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_div_rdNotZero_fails() external {
uint32 insn = encodespec(0x9, 0xa, 0x1, 0x1a); // div t1, t2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[9] = 5; // t1
state.registers[10] = 2; // t2
vm.expectRevert("MIPS: rd not zero");
mips.step(encodeState(state), proof, 0);
}
function test_div_shamtNotZero_fails() external {
uint32 insn = encodespec(0x9, 0xa, 0x0, 0x1a); // div t1, t2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[9] = 5; // t1
state.registers[10] = 2; // t2
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_divu_succeeds() external { function test_divu_succeeds() external {
uint32 insn = encodespec(0x9, 0xa, 0x0, 0x1b); // divu t1, t2 uint32 insn = encodespec(0x9, 0xa, 0x0, 0x1b); // divu t1, t2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
...@@ -1129,6 +1408,27 @@ contract MIPS_Test is CommonTest { ...@@ -1129,6 +1408,27 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_divu_rdNotZero_fails() external {
uint32 insn = encodespec(0x9, 0xa, 0x1, 0x1b); // divu t1, t2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[9] = 5; // t1
state.registers[10] = 2; // t2
vm.expectRevert("MIPS: rd not zero");
mips.step(encodeState(state), proof, 0);
}
function test_divu_shamtNotZero_fails() external {
uint32 insn = encodespec(0x9, 0xa, 0x0, 0x1b); // divu t1, t2
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[9] = 5; // t1
state.registers[10] = 2; // t2
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_div_byZero_fails() external { function test_div_byZero_fails() external {
uint32 insn = encodespec(0x9, 0xa, 0x0, 0x1a); // div t1, t2 uint32 insn = encodespec(0x9, 0xa, 0x0, 0x1a); // div t1, t2
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
...@@ -1345,6 +1645,31 @@ contract MIPS_Test is CommonTest { ...@@ -1345,6 +1645,31 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_jr_shamtNotZero_fails() external {
uint32 insn = encodespec(0x8, 0, 0, 0x8); // jr t0
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_jr_rtNotZero_fails() external {
uint32 insn = encodespec(0x8, 0x1, 0, 0x8); // jr t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_jr_rdNotZero_fails() external {
uint32 insn = encodespec(0x8, 0, 0x1, 0x8); // jr t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rd not zero");
mips.step(encodeState(state), proof, 0);
}
function test_jalr_succeeds() external { function test_jalr_succeeds() external {
uint16 tgt = 0x34; uint16 tgt = 0x34;
uint32 insn = encodespec(0x8, 0, 0x9, 0x9); // jalr t1, t0 uint32 insn = encodespec(0x8, 0, 0x9, 0x9); // jalr t1, t0
...@@ -1363,6 +1688,23 @@ contract MIPS_Test is CommonTest { ...@@ -1363,6 +1688,23 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_jalr_shamtNotZero_fails() external {
uint32 insn = encodespec(0x8, 0, 0x9, 0x9); // jalr t1, t0
insn |= 0x1F << 6;
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: shamt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_jalr_rtNotZero_fails() external {
uint32 insn = encodespec(0x8, 0x1, 0x9, 0x9); // jalr t1, t0
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rt not zero");
mips.step(encodeState(state), proof, 0);
}
function test_sll_succeeds() external { function test_sll_succeeds() external {
uint8 shiftamt = 4; uint8 shiftamt = 4;
uint32 insn = encodespec(0x0, 0x9, 0x8, uint16(shiftamt) << 6); // sll t0, t1, 3 uint32 insn = encodespec(0x0, 0x9, 0x8, uint16(shiftamt) << 6); // sll t0, t1, 3
...@@ -1382,6 +1724,16 @@ contract MIPS_Test is CommonTest { ...@@ -1382,6 +1724,16 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_sll_rsNotZero_fails() external {
uint8 shiftamt = 4;
uint32 insn = encodespec(0x1, 0x9, 0x8, uint16(shiftamt) << 6); // sll t0, t1, 3
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[9] = 0x20; // t1
vm.expectRevert("MIPS: rs not zero");
mips.step(encodeState(state), proof, 0);
}
function test_srl_succeeds() external { function test_srl_succeeds() external {
uint8 shiftamt = 4; uint8 shiftamt = 4;
uint32 insn = encodespec(0x0, 0x9, 0x8, uint16(shiftamt) << 6 | 2); // srl t0, t1, 3 uint32 insn = encodespec(0x0, 0x9, 0x8, uint16(shiftamt) << 6 | 2); // srl t0, t1, 3
...@@ -1401,6 +1753,16 @@ contract MIPS_Test is CommonTest { ...@@ -1401,6 +1753,16 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_srl_rsNotZero_fails() external {
uint8 shiftamt = 4;
uint32 insn = encodespec(0x1, 0x9, 0x8, uint16(shiftamt) << 6 | 2); // srl t0, t1, 3
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
state.registers[9] = 0x20; // t1
vm.expectRevert("MIPS: rs not zero");
mips.step(encodeState(state), proof, 0);
}
function test_sra_succeeds() external { function test_sra_succeeds() external {
uint8 shiftamt = 4; uint8 shiftamt = 4;
uint32 insn = encodespec(0x0, 0x9, 0x8, uint16(shiftamt) << 6 | 3); // sra t0, t1, 3 uint32 insn = encodespec(0x0, 0x9, 0x8, uint16(shiftamt) << 6 | 3); // sra t0, t1, 3
...@@ -1527,6 +1889,14 @@ contract MIPS_Test is CommonTest { ...@@ -1527,6 +1889,14 @@ contract MIPS_Test is CommonTest {
assertEq(postState, outputState(expect), "unexpected post state"); assertEq(postState, outputState(expect), "unexpected post state");
} }
function test_lui_rsNotZero_fails() external {
uint32 insn = encodeitype(0xf, 0x1, 0x8, 0x4); // lui $t0, 0x04
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
vm.expectRevert("MIPS: rs not zero");
mips.step(encodeState(state), proof, 0);
}
function test_clo_succeeds() external { function test_clo_succeeds() external {
uint32 insn = encodespec2(0x9, 0x0, 0x8, 0x21); // clo t0, t1 uint32 insn = encodespec2(0x9, 0x0, 0x8, 0x21); // clo t0, t1
(MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0); (MIPS.State memory state, bytes memory proof) = constructMIPSState(0, insn, 0x4, 0);
......
...@@ -27,7 +27,7 @@ contract DeploymentSummary is DeploymentSummaryCode { ...@@ -27,7 +27,7 @@ contract DeploymentSummary is DeploymentSummaryCode {
address internal constant l1StandardBridgeProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D; address internal constant l1StandardBridgeProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D;
address internal constant l2OutputOracleAddress = 0x19652082F846171168Daf378C4fD3ee85a0D4A60; address internal constant l2OutputOracleAddress = 0x19652082F846171168Daf378C4fD3ee85a0D4A60;
address internal constant l2OutputOracleProxyAddress = 0x39Af23E00F1e662025aA01b0cEdA19542B78DF99; address internal constant l2OutputOracleProxyAddress = 0x39Af23E00F1e662025aA01b0cEdA19542B78DF99;
address internal constant mipsAddress = 0x3629E5c6FCCaA06C25aD8Fe5c9de82d7A39E9Df8; address internal constant mipsAddress = 0x2875d50F393FfE847bFD3D517E80097b87f10928;
address internal constant optimismMintableERC20FactoryAddress = 0x39Aea2Dd53f2d01c15877aCc2791af6BDD7aD567; address internal constant optimismMintableERC20FactoryAddress = 0x39Aea2Dd53f2d01c15877aCc2791af6BDD7aD567;
address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB; address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB;
address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131; address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -27,7 +27,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode { ...@@ -27,7 +27,7 @@ contract DeploymentSummaryFaultProofs is DeploymentSummaryFaultProofsCode {
address internal constant l1StandardBridgeProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D; address internal constant l1StandardBridgeProxyAddress = 0x20A42a5a785622c6Ba2576B2D6e924aA82BFA11D;
address internal constant l2OutputOracleAddress = 0x19652082F846171168Daf378C4fD3ee85a0D4A60; address internal constant l2OutputOracleAddress = 0x19652082F846171168Daf378C4fD3ee85a0D4A60;
address internal constant l2OutputOracleProxyAddress = 0x39Af23E00F1e662025aA01b0cEdA19542B78DF99; address internal constant l2OutputOracleProxyAddress = 0x39Af23E00F1e662025aA01b0cEdA19542B78DF99;
address internal constant mipsAddress = 0x3629E5c6FCCaA06C25aD8Fe5c9de82d7A39E9Df8; address internal constant mipsAddress = 0x2875d50F393FfE847bFD3D517E80097b87f10928;
address internal constant optimismMintableERC20FactoryAddress = 0x39Aea2Dd53f2d01c15877aCc2791af6BDD7aD567; address internal constant optimismMintableERC20FactoryAddress = 0x39Aea2Dd53f2d01c15877aCc2791af6BDD7aD567;
address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB; address internal constant optimismMintableERC20FactoryProxyAddress = 0xc7B87b2b892EA5C3CfF47168881FE168C00377FB;
address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131; address internal constant optimismPortalAddress = 0xbdD90485FCbcac869D5b5752179815a3103d8131;
......
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