We all know that usually a program will just return one value, but I have noticed that we have two value returning registers $v0
and $v1
in MIPS. T
Another use case is returning 64-bit numbers on 32-bit MIPS (or 128-bit numbers in 64-bit MIPS).
I can think of plenty of examples, but it's probably just up to your discretion. The best example is probably a function that returns a value in $v0 and may set an error code in $v1.
There are lots of uses for that
Returning a value twice the length of the register (64-bit values in MIPS32 and 128-bit values in MIPS64) as @Martin Rosenau mentioned
long long mult(int x, int y) {
return (long long)x * y;
}
Output assembly:
mult(int, int):
mult $4,$5
mflo $2
mfhi $3
j $31
nop
Returning structs that fit into 2 registers like these
typedef struct {
int a, b;
} ret_struct2x32;
ret_struct2x32 return_struct2x32() {
return ret_struct2x32{2, 3};
}
typedef struct {
short a, b, c, d;
} ret_struct4x16;
ret_struct4x16 return_struct4x16() {
return ret_struct4x16{(short)2, (short)0, (short)3, (short)0};
}
or returning tuples that appear in some languages like python
def func(x,y):
# code to compute x and y
return x,y
a, b = 1, 2
u, v = func(a, b)
In C++ we have std::pair
and std::tuple
std::pair<int, int> return_pair()
{
return std::make_pair(2, 3);
}
std::tuple<short, short, short, short> return_tuple()
{
return std::make_tuple((short)2, (short)0, (short)3, (short)0);
}
See the demo on Compiler Explorer. Unfortunately the gcc version for MIPS is too old and can't make use the struct-in-register optimization, so look at the x86 output and you'll see that the whole tuples are returned in only a single instruction
It's similar to the pair (E/R)DX:(E/R)AX in x86 to return a value double the size of the registers
See also