Skip to content

Fix so lw and sw handle negative offsets.

Joacim Norlén requested to merge joanor-0/mips:lw_sw_negative_offsets into master

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

Merge request reports