Search code examples
assemblymipsstack-memorystack-pointer

Why does the Stack Pointer in MIPS Typically Start at 0x7FFFFFFC but not 0x80000000?


According to Patterson & Hennessy's Computer Organization and Design (MIPS Edition),

  1. the stack pointer $sp is typically initialized to 0x7FFFFFFC.
    enter image description here

  2. the stack pointer $sp is always pointing at the most recently allocated address.
    enter image description here

So, if I want to push 1 word, say 0xCAFEBABE, in the stack pointer, I will

  1. subtract the stack pointer by 4 (because the stack pointer is pointing at the allocated address, I shall allocate more for new data).
  2. store 0xCAFEBABE to the address pointed by the stack pointer.

Now, the bytes at 0x7FFFFFF8, 0x7FFFFFF9, 0x7FFFFFFA, 0x7FFFFFFB will be 0xCA, 0xFE, 0xBA, 0xBE (order depending on the byte order). But the bytes at 0x7FFFFFFC, 0x7FFFFFFD, 0x7FFFFFFE, 0x7FFFFFFF will never be used!

I think this wastes 1 word in the memory. If the initial value of $sp were 0x80000000, that 1 word would not be wasted.


Solution

  • https://www.dyncall.org/docs/manual/manualse11.html:

    Multiple revisions of the MIPS Instruction set exist, namely MIPS I, MIPS II, MIPS III, MIPS IV, MIPS32 and MIPS64. Nowadays, MIPS32 and MIPS64 are the main ones used for 32-bit and 64-bit instruction sets, respectively. Given MIPS processors are often used for embedded devices, several add-on extensions exist for the MIPS family, for example:

    Unfortunately, there is actually no such thing as ”The MIPS Calling Convention”. Many possible conventions are used by many different environments such as O32[38], O64[39], N32[40], N64[40], EABI[41] and NUBI[42].

    https://courses.cs.washington.edu/courses/cse410/09sp/examples/MIPSCallingConventionsSummary.pdf:

    The value of the stack pointer is required to be multiple of 8 at all times.


    • That material you're quoting from the book is more informational than a requirement for all to follow.  I would venture that an operating system is free to use 0x8000000 (or 0x7ffffff0, a more aligned address than 0x7fffffc).  Let's note that 0x7fffffc is only word aligned, and not double word aligned, yet double floating point loads and stores require double word alignment, so following this text literally is problematic, which goes to the argument that it is suggestive rather than canon.

    • The book description of the calling convention is as of original MIPS, or out-of-date, depending on how to look at it.  Although the book has been reprinted and its latest version is 6th edition of 2020, the text remains the same.  We can also see the same identical text in the RISC-V version (using the same exact wording, i.e. MIPS and 0x7fffffc, etc..).  Here, in the RISC-V book, the use of 0x7FFFFFFC and MIPS is clearly suggestive of an approach for RISC-V rather than a rule for this newer follow-on processor.

    • Another answer goes to the way that the two popular MIPS simulators work: https://stackoverflow.com/a/64654885/471129

    • This stack usage model is called full descending.  Starting the stack pointer referring to an actual free word (or double word) allows an alternate stack usage model, called empty descending.

    • Wasting a word (or double word) per process is harmless.