Why did the MARS MIPS Simulator throws a "Load from an Illegal Address" exception?

0

I created a simple, recursive factorial() function which calls a recursive multiplication function called mul_alt() whenever it evaluates n * factorial(n-1). So instead of return n * factorial(n-1) (in C notation), the factorial() function executes return mul_alt(n, factorial(n-1)), where the called function would add n + n + ... factorial(n-1) times. I made this convoluted program since my class demands so.

The program works fine for n <= 9, but when I tried n > 9, the program would return an exception at n = 10 with the following values of the coprocessor 0:

$8 (vaddr) = 0x7fbffffc
$12 (status) = 0x0000ff13
$13 (cause) = 0x00000014
$14 (epc) = 0x0040008c

From the first two bits of the status register, I learned that the exception handler returned an ADDRL exception which means loading from an illegal address. And the epc register shows the address of the instruction which caused the error, which is

0x0040008c: sw $s1, 4($sp)

and the value of my $sp register is 0x7fbffff8. So 0x7fbffff8 + 0x4 = 0x7fbffffc (which is the value stored in vaddr) is where store instruction tried to store the contents of $s1. I have a few questions regarding this situation:

  1. Why did I get an ADDRL exception though I actually used a store instruction -- not load?
  2. 0x7fbffffc is divisible by 4, so why am I not allowed to store word-sized data in there?

I hope I have stated my point clear. Thank you in advance.

mips
mars-simulator
asked on Stack Overflow Apr 10, 2021 by marshblocker

1 Answer

1

MIPS cause 0x14 is an ADDRS not an ADDRL. ExcCode = 0x14/4 = 5: ADDRS

This is a simple stack overflow.  The MARS stack can go to 0x7fc00000, so allows for about 4M bytes.


// from the default memory configuration menu selection
public static int stackPointer = MemoryConfigurations.getDefaultStackPointer(); //0x7fffeffc;
public static int stackBaseAddress = MemoryConfigurations.getDefaultStackBaseAddress(); //0x7ffffffc;
public static int stackLimitAddress = stackBaseAddress - BLOCK_LENGTH_WORDS * BLOCK_TABLE_LENGTH * WORD_LENGTH_BYTES;
//                          where these constants are 1024, 1024, and 4 respectively

The default values (from the default memory configuration) are 0x7ffffffc (stackBase), 0x7fffeffc (stackPointer), 0x7fc00000 (stackLimitAddress).

There is no menu option to increase the stack space beyond 4MB.

There is a menu for memory configuration, but it incorrectly reports stack limit as the same value as heap base for all available configurations.  This isn't the case: the stack limit is always stack base - 4MB, according to the source code.

The memory addresses between heap base address and stack limit address are protected unless you expand the heap using sbrk system call.  There is no expanding the stack further.


SPIM on the other hand, appears to expand the stack space as needed, but only when you modify the stack pointer register, rather than when storing into memory below the stack pointer.  Thus in SPIM, if you modify the stack pointer register to a random value, it will immediately fail to expand the stack space (without doing a store or load) even if you put the stack pointer back where it was before loading or storing relative to that register — odd behavior indeed but it seems they treat the $sp register specially rather than how the hardware would do it.

answered on Stack Overflow Apr 10, 2021 by Erik Eidt • edited Apr 11, 2021 by Erik Eidt

User contributions licensed under CC BY-SA 3.0