Assembly:

SAVE u[, src1 [, src2 [, ...]]]

nanoMIPS, availability varies by format.

Save callee saved registers

Purpose:

Save callee saved registers.

Save registers src1,[src2,...]to addresses just below the

current stack pointer ($29) address and adjust the stack pointer by subtracting offset u to accommodate the saved registers and the local stack frame.

Availability:

nanoMIPS, availability varies by format.

Format:

SAVE[16]

000111

rt1

0

u[7:4]

count

6

1

1

4

4

rt = 30 if rt1 == 0 else 31
gp = 0

SAVE[32], gp case not available in NMS

100000

rt

0

count

0011

u[11:3]

gp

00

6

5

1

4

4

9

1

2

Operation:

if gp and C0.Config5.NMS:
    raise exception('RI')
i = 0
while i != count:
    this_rt = ( 28          if gp and (i + 1 == count) else
                rt + i      if rt + i < 32             else
                rt + i - 16                                 )
    this_offset = - ( (i+1) << 2 )
    va = effective_address(GPR[29], this_offset, 'Load')
    if va & 3:
        raise exception('ADES', badva=va)
    data = zero_extend(GPR[this_rt], from_nbits=32)
    write_memory_at_va(data, va, nbytes=4)
    i += 1
GPR[29] = effective_address(GPR[29], -u)

The purpose of the SAVE instruction is to save callee saved registers to the stack on entry to a subroutine, and adjust the stack pointer register ($29) to accommodate the saved registers and the subroutine’s local stack frame.

The instruction specification consists of the amount to decrement the stack by, and a list of registers to save to the stack. The stack decrement is a double word aligned immediate value u in the range

0 to 4092. The register list can contain up to 16 consecutive registers. The count of the number of registers in the register list is encoded in the instruction’s count field. The first register in the list is

encoded in the rt field of the instruction.

The register list is allowed to wrap around from register $31 back to register $16 and still be considered consecutive; this allows fp ($30) and ra ($31) and the saved temporary registers s0-s7 ($16 - $23) to

be saved in one instruction.

Additionally, $28 (the global pointer register) will be used in place of last register in the sequence if the ’gp’ bit in the instruction encoding is set. This feature (which is not available for NMS cores) makes it

possible to treat $28 as a callee saved register for environments such as Linux which require it.

The saved registers are written to memory addresses $29-4, $29-8, $29-12,...etc,i.e.just below the current stack pointer address. The stack pointer is then adjusted by subtracting offset u, which

should be chosen to accommodate the saved registers and current subroutine’s local stack frame, while maintaining the required stack pointer alignment.

SAVE with count=0 adjusts the stack pointer but does not save any registers to memory.Thus the

SAVE[16] instruction format can be used to provide ADDIU16$29, $29, -u behavior.

SAVE must be implemented in such a way as to make the instruction restartable, but the implementation does not need to be fully atomic. For instance, it is allowable for a SAVE instruction to be aborted

by an exception after a subset ofthe memory updates have occurred.To ensure restartability,the write to GPR $29 must be completed atomically,that is,the instruction must graduate if and only if

that write occurs.

Exceptions:

Address Error.Bus Error.Reserved Instruction for gp=1 cases on NMS cores.TLB Invalid.TLB Modified. TLB Refill. Watch.