1

I want to test my program on random inputs, but each time I reset it, all of the registers and data reset.

Is it possible to run the program again without the registers and data resetting each time?

Eloo
  • 125
  • 11
  • There's a rewind button, which does undo most of the things, but memory content stays modified IIRC (if it works like that, you can store registers to memory at the end, and reload them at beginning)... but usually people want the exact opposite, to have after reset clean-state of machine. - that's a hack suggestion. In real SW you have to store state which should preserve to some storage device (disk) or SRAM. – Ped7g Dec 04 '17 at 19:30
  • The rewind button says "reset MIPS memory and registers". It lets you run the program again, but as it says the memory is reset too. – Eloo Dec 04 '17 at 19:34

2 Answers2

1

If there's no other way, the best option I found is just adding a chunk of code that adds the values to all the registers/data before running the actual program.

Eloo
  • 125
  • 11
  • BTW, it's accepted standard method, to "set up" the environment ahead of test, makes test results also reproducible (if fixed values are used, or the random values are part of test result, so they can be re-applied in case of need). So you are doing it at least as good, as majority of people do. – Ped7g Dec 05 '17 at 13:19
1

I think you want to check that your code doesn't depend on some registers or memory being zero. This is the low-level version of checking for use of uninitialized variables in higher level languages like C.

The industrial-strength version of this is Valgrind, which does support MIPS. IDK if you can build it to run inside SPIM, though; it's designed to run on real OSes like Linux (on MIPS). It only tracks memory, not uninitialized registers, though (because most people use it on asm generated by compilers, which generally don't have this problem). See for example pinpointing "conditional jump or move depends on uninitialized value(s)" valgrind message.


For your purposes, your best bet is to manually put "poison" values into all your registers, and as much memory as you want. The values that were present at the end of the last run are less likely to be good choices; that wouldn't catch a problem where either the initial zero or the value you write later both happen to work for some code that reads it before the write.

For example, 0xDEADBEEF is a good constant that you can recognize if you see it while debugging or in your program's output. It's also unlikely to be a valid pointer or index. See that link for more about what makes good poison.

e.g.

li  $t0,  0xDEADBEEF
move $t1, $t0
move $t2, $t0
...

You can probably write a macro to repeat it for all registers except the stack pointer, especially if you use the "raw" register numbers like $1, $2, etc. (mapping table from semantic names to raw names. Probably your macro should init everything except $29 ($sp), including $1 ($at) and the kernel-temporary regs). To write a macro like that, use text substitution to create $1..$28, after putting your constant into $30 and $31.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847