Fix so lw and sw handle negative offsets.
When trying to access a negative offset in lw/sw, e.g. lw(t0, -4, sp)
the immediate gets treated as unsigned later on in the VM. This fix treats the immediate as an i16
which is what was passed in.
The ugly part is that I cast the address and the immediate to i64
to prevent the overflow that would happen if i32
were used. If you have a better way of solving it I'd like to know.
The tests introduced fail in these way before the changes:
Trying sw
on sp
(0x80000000
) with offset -4
writes to address 0x8000fffc
.
running 1 test
[2021-10-06T06:29:54Z INFO mips::vm] [mips vm initialized]
[2021-10-06T06:29:54Z TRACE mips::mem] mem::write_word: addr=0
[2021-10-06T06:29:54Z TRACE mips::mem] mem::write_word: addr=4
[2021-10-06T06:29:54Z TRACE mips::mem] mem::write_word: addr=8
[2021-10-06T06:29:54Z TRACE mips::mem] mem::write_word: addr=c
[2021-10-06T06:29:54Z TRACE mips::mem] mem::write_word: addr=10
[2021-10-06T06:29:54Z INFO mips::vm] pc: 0x00000000: Addiu t0, zero, 5 (0x0005)
[2021-10-06T06:29:54Z TRACE mips::rf] reg[zero] -> 0x00000000
[2021-10-06T06:29:54Z TRACE mips::rf] reg[t0] <- 0x00000005
[2021-10-06T06:29:54Z INFO mips::vm] pc: 0x00000004: Sw t0, -4[sp] (0xfffc)
[2021-10-06T06:29:54Z TRACE mips::rf] reg[sp] -> 0x80000000
[2021-10-06T06:29:54Z TRACE mips::rf] reg[t0] -> 0x00000005
[2021-10-06T06:29:54Z TRACE mips::mem] mem::write_word: addr=8000fffc
[2021-10-06T06:29:54Z INFO mips::vm] pc: 0x00000008: Addiu sp, sp, -4 (0xfffc)
[2021-10-06T06:29:54Z TRACE mips::rf] reg[sp] -> 0x80000000
[2021-10-06T06:29:54Z TRACE mips::rf] reg[sp] <- 0x7FFFFFFC
[2021-10-06T06:29:54Z INFO mips::vm] pc: 0x0000000C: Lw t1, 0[sp] (0x0000)
[2021-10-06T06:29:54Z TRACE mips::rf] reg[sp] -> 0x7FFFFFFC
result: Err(AddressNotInitialized(7ffffffc))
thread 'vm::tests::negative_offset_sw' panicked at 'assertion failed: `(left == right)`
left: `Err(AddressNotInitialized(2147483644))`,
right: `Err(Halt)`', src/vm.rs:286:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
test vm::tests::negative_offset_sw ... FAILED
Trying lw
on sp (0x80000000
) with offset -4
tries to access the address 0x8000fffc
.
running 1 test
[2021-10-06T06:34:13Z INFO mips::vm] [mips vm initialized]
[2021-10-06T06:34:13Z INFO mips::vm] pc: 0x00000000: Addiu t0, zero, 5 (0x0005)
[2021-10-06T06:34:13Z TRACE mips::rf] reg[zero] -> 0x00000000
[2021-10-06T06:34:13Z TRACE mips::rf] reg[t0] <- 0x00000005
[2021-10-06T06:34:13Z INFO mips::vm] pc: 0x00000004: Addiu sp, sp, -4 (0xfffc)
[2021-10-06T06:34:13Z TRACE mips::rf] reg[sp] -> 0x80000000
[2021-10-06T06:34:13Z TRACE mips::rf] reg[sp] <- 0x7FFFFFFC
[2021-10-06T06:34:13Z INFO mips::vm] pc: 0x00000008: Sw t0, 0[sp] (0x0000)
[2021-10-06T06:34:13Z TRACE mips::rf] reg[sp] -> 0x7FFFFFFC
[2021-10-06T06:34:13Z TRACE mips::rf] reg[t0] -> 0x00000005
[2021-10-06T06:34:13Z INFO mips::vm] pc: 0x0000000C: Addiu sp, sp, 4 (0x0004)
[2021-10-06T06:34:13Z TRACE mips::rf] reg[sp] -> 0x7FFFFFFC
[2021-10-06T06:34:13Z TRACE mips::rf] reg[sp] <- 0x80000000
[2021-10-06T06:34:13Z INFO mips::vm] pc: 0x00000010: Lw t1, -4[sp] (0xfffc)
[2021-10-06T06:34:13Z TRACE mips::rf] reg[sp] -> 0x80000000
result: Err(AddressNotInitialized(8000fffc))
thread 'vm::tests::negative_offset_lw' panicked at 'assertion failed: `(left == right)`
left: `Err(AddressNotInitialized(2147549180))`,
right: `Err(Halt)`', src/vm.rs:311:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
test vm::tests::negative_offset_lw ... FAILED