How does MIPS store a number larger than 32 bits?
up vote
0
down vote
favorite
I was looking for an answer to this but couldn't find a clear one. Does it split the number between multiple registers or it can't simply cope with it?
I tried testing it with MARS and using the number 4294967296 which is 0x100000000 but the register saved only 0x00000000, so the '1' bit is omitted. Is there a way to cope with such numbers?
assembly memory mips mips32
add a comment |
up vote
0
down vote
favorite
I was looking for an answer to this but couldn't find a clear one. Does it split the number between multiple registers or it can't simply cope with it?
I tried testing it with MARS and using the number 4294967296 which is 0x100000000 but the register saved only 0x00000000, so the '1' bit is omitted. Is there a way to cope with such numbers?
assembly memory mips mips32
If you use only 32 bit register, then yes, everything above is thrown away, and values are "truncated" down to 32 bit only. So to store more bits you must use more bits (multiple registers, multiple words in memory, etc...) nothing in CPU will inflate dynamically just because suddenly 32 bits are not enough, all sizes are fixed in asm code, and the code must be prepared to handle more bits, otherwise it will not.
– Ped7g
Nov 10 at 16:55
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I was looking for an answer to this but couldn't find a clear one. Does it split the number between multiple registers or it can't simply cope with it?
I tried testing it with MARS and using the number 4294967296 which is 0x100000000 but the register saved only 0x00000000, so the '1' bit is omitted. Is there a way to cope with such numbers?
assembly memory mips mips32
I was looking for an answer to this but couldn't find a clear one. Does it split the number between multiple registers or it can't simply cope with it?
I tried testing it with MARS and using the number 4294967296 which is 0x100000000 but the register saved only 0x00000000, so the '1' bit is omitted. Is there a way to cope with such numbers?
assembly memory mips mips32
assembly memory mips mips32
asked Nov 10 at 15:04
PyFox
738
738
If you use only 32 bit register, then yes, everything above is thrown away, and values are "truncated" down to 32 bit only. So to store more bits you must use more bits (multiple registers, multiple words in memory, etc...) nothing in CPU will inflate dynamically just because suddenly 32 bits are not enough, all sizes are fixed in asm code, and the code must be prepared to handle more bits, otherwise it will not.
– Ped7g
Nov 10 at 16:55
add a comment |
If you use only 32 bit register, then yes, everything above is thrown away, and values are "truncated" down to 32 bit only. So to store more bits you must use more bits (multiple registers, multiple words in memory, etc...) nothing in CPU will inflate dynamically just because suddenly 32 bits are not enough, all sizes are fixed in asm code, and the code must be prepared to handle more bits, otherwise it will not.
– Ped7g
Nov 10 at 16:55
If you use only 32 bit register, then yes, everything above is thrown away, and values are "truncated" down to 32 bit only. So to store more bits you must use more bits (multiple registers, multiple words in memory, etc...) nothing in CPU will inflate dynamically just because suddenly 32 bits are not enough, all sizes are fixed in asm code, and the code must be prepared to handle more bits, otherwise it will not.
– Ped7g
Nov 10 at 16:55
If you use only 32 bit register, then yes, everything above is thrown away, and values are "truncated" down to 32 bit only. So to store more bits you must use more bits (multiple registers, multiple words in memory, etc...) nothing in CPU will inflate dynamically just because suddenly 32 bits are not enough, all sizes are fixed in asm code, and the code must be prepared to handle more bits, otherwise it will not.
– Ped7g
Nov 10 at 16:55
add a comment |
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
Use 2 registers, an extra one for the high half. MIPS doesn't have flags, so there isn't a 2-instruction add
/add-with-carry
way to add int64_t like there is on many other ISAs, but you can look at compiler output for a C function that adds two 64-bit integers easily enough.
#include <stdint.h>
int64_t add64(int64_t a, int64_t b)
return a+b;
compiled for MIPS on the Godbolt compiler explorer with gcc5.4 -O3
:
add64:
addu $3,$5,$7
sltu $5,$3,$5 # check for carry-out with sum_lo < a_lo (unsigned)
addu $2,$4,$6 # add high halves
j $31 # return (with a branch-delay slot)
addu $2,$5,$2 # add the carry-out from the low half into the high half
In memory, MIPS in big-endian mode (the more common choice for MIPS) stores the entire 64-bit integer in big-endian order, thus the "high half" (most significant 32 bits) is at the lower address, so the highest byte of that word is at the lowest address, and all 8 bytes are in descending order of place value.
void add64_store(int64_t a, int64_t b, int64_t *res)
*res = a+b;
## gcc5.4 -O3 for MIPS - big-endian, not MIPS (el)
addu $7,$5,$7 # low half
lw $2,16($sp)
sltu $5,$7,$5 # carry-out
addu $4,$4,$6
addu $5,$5,$4 # high half
sw $5,0($2) # store the high half to res[0..3]
j $31
sw $7,4($2) # store the low half to res[4..7]
As you can see from the register numbers used, the calling convention passes the high half in the lower-numbered register (earlier arg), unlike on little-endian architectures where the high-half goes in the later arg-passing slot. This makes things work as desired if you run out of register and an int64_t is passed on the stack.
On an architecture with flags and an add-with-carry instruction (like ARM32 for example), you get an add instruction that creates a 33 bit result in C:R0
(top bit in the carry flag, lower 32 in a register).
add64:
adds r0, r2, r0 @ ADD and set flags
adc r1, r3, r1 @ r1 = r1 + r3 + carry
bx lr
You tagged this MIPS32, so you don't have the 64-bit extension to ISA available (introduced in MIPS III in 1991). I think some modern embedded MIPS CPUs are still only 32-bit. (And the same reasoning applies to 128-bit integers on MIPS64).
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
Use 2 registers, an extra one for the high half. MIPS doesn't have flags, so there isn't a 2-instruction add
/add-with-carry
way to add int64_t like there is on many other ISAs, but you can look at compiler output for a C function that adds two 64-bit integers easily enough.
#include <stdint.h>
int64_t add64(int64_t a, int64_t b)
return a+b;
compiled for MIPS on the Godbolt compiler explorer with gcc5.4 -O3
:
add64:
addu $3,$5,$7
sltu $5,$3,$5 # check for carry-out with sum_lo < a_lo (unsigned)
addu $2,$4,$6 # add high halves
j $31 # return (with a branch-delay slot)
addu $2,$5,$2 # add the carry-out from the low half into the high half
In memory, MIPS in big-endian mode (the more common choice for MIPS) stores the entire 64-bit integer in big-endian order, thus the "high half" (most significant 32 bits) is at the lower address, so the highest byte of that word is at the lowest address, and all 8 bytes are in descending order of place value.
void add64_store(int64_t a, int64_t b, int64_t *res)
*res = a+b;
## gcc5.4 -O3 for MIPS - big-endian, not MIPS (el)
addu $7,$5,$7 # low half
lw $2,16($sp)
sltu $5,$7,$5 # carry-out
addu $4,$4,$6
addu $5,$5,$4 # high half
sw $5,0($2) # store the high half to res[0..3]
j $31
sw $7,4($2) # store the low half to res[4..7]
As you can see from the register numbers used, the calling convention passes the high half in the lower-numbered register (earlier arg), unlike on little-endian architectures where the high-half goes in the later arg-passing slot. This makes things work as desired if you run out of register and an int64_t is passed on the stack.
On an architecture with flags and an add-with-carry instruction (like ARM32 for example), you get an add instruction that creates a 33 bit result in C:R0
(top bit in the carry flag, lower 32 in a register).
add64:
adds r0, r2, r0 @ ADD and set flags
adc r1, r3, r1 @ r1 = r1 + r3 + carry
bx lr
You tagged this MIPS32, so you don't have the 64-bit extension to ISA available (introduced in MIPS III in 1991). I think some modern embedded MIPS CPUs are still only 32-bit. (And the same reasoning applies to 128-bit integers on MIPS64).
add a comment |
up vote
2
down vote
accepted
Use 2 registers, an extra one for the high half. MIPS doesn't have flags, so there isn't a 2-instruction add
/add-with-carry
way to add int64_t like there is on many other ISAs, but you can look at compiler output for a C function that adds two 64-bit integers easily enough.
#include <stdint.h>
int64_t add64(int64_t a, int64_t b)
return a+b;
compiled for MIPS on the Godbolt compiler explorer with gcc5.4 -O3
:
add64:
addu $3,$5,$7
sltu $5,$3,$5 # check for carry-out with sum_lo < a_lo (unsigned)
addu $2,$4,$6 # add high halves
j $31 # return (with a branch-delay slot)
addu $2,$5,$2 # add the carry-out from the low half into the high half
In memory, MIPS in big-endian mode (the more common choice for MIPS) stores the entire 64-bit integer in big-endian order, thus the "high half" (most significant 32 bits) is at the lower address, so the highest byte of that word is at the lowest address, and all 8 bytes are in descending order of place value.
void add64_store(int64_t a, int64_t b, int64_t *res)
*res = a+b;
## gcc5.4 -O3 for MIPS - big-endian, not MIPS (el)
addu $7,$5,$7 # low half
lw $2,16($sp)
sltu $5,$7,$5 # carry-out
addu $4,$4,$6
addu $5,$5,$4 # high half
sw $5,0($2) # store the high half to res[0..3]
j $31
sw $7,4($2) # store the low half to res[4..7]
As you can see from the register numbers used, the calling convention passes the high half in the lower-numbered register (earlier arg), unlike on little-endian architectures where the high-half goes in the later arg-passing slot. This makes things work as desired if you run out of register and an int64_t is passed on the stack.
On an architecture with flags and an add-with-carry instruction (like ARM32 for example), you get an add instruction that creates a 33 bit result in C:R0
(top bit in the carry flag, lower 32 in a register).
add64:
adds r0, r2, r0 @ ADD and set flags
adc r1, r3, r1 @ r1 = r1 + r3 + carry
bx lr
You tagged this MIPS32, so you don't have the 64-bit extension to ISA available (introduced in MIPS III in 1991). I think some modern embedded MIPS CPUs are still only 32-bit. (And the same reasoning applies to 128-bit integers on MIPS64).
add a comment |
up vote
2
down vote
accepted
up vote
2
down vote
accepted
Use 2 registers, an extra one for the high half. MIPS doesn't have flags, so there isn't a 2-instruction add
/add-with-carry
way to add int64_t like there is on many other ISAs, but you can look at compiler output for a C function that adds two 64-bit integers easily enough.
#include <stdint.h>
int64_t add64(int64_t a, int64_t b)
return a+b;
compiled for MIPS on the Godbolt compiler explorer with gcc5.4 -O3
:
add64:
addu $3,$5,$7
sltu $5,$3,$5 # check for carry-out with sum_lo < a_lo (unsigned)
addu $2,$4,$6 # add high halves
j $31 # return (with a branch-delay slot)
addu $2,$5,$2 # add the carry-out from the low half into the high half
In memory, MIPS in big-endian mode (the more common choice for MIPS) stores the entire 64-bit integer in big-endian order, thus the "high half" (most significant 32 bits) is at the lower address, so the highest byte of that word is at the lowest address, and all 8 bytes are in descending order of place value.
void add64_store(int64_t a, int64_t b, int64_t *res)
*res = a+b;
## gcc5.4 -O3 for MIPS - big-endian, not MIPS (el)
addu $7,$5,$7 # low half
lw $2,16($sp)
sltu $5,$7,$5 # carry-out
addu $4,$4,$6
addu $5,$5,$4 # high half
sw $5,0($2) # store the high half to res[0..3]
j $31
sw $7,4($2) # store the low half to res[4..7]
As you can see from the register numbers used, the calling convention passes the high half in the lower-numbered register (earlier arg), unlike on little-endian architectures where the high-half goes in the later arg-passing slot. This makes things work as desired if you run out of register and an int64_t is passed on the stack.
On an architecture with flags and an add-with-carry instruction (like ARM32 for example), you get an add instruction that creates a 33 bit result in C:R0
(top bit in the carry flag, lower 32 in a register).
add64:
adds r0, r2, r0 @ ADD and set flags
adc r1, r3, r1 @ r1 = r1 + r3 + carry
bx lr
You tagged this MIPS32, so you don't have the 64-bit extension to ISA available (introduced in MIPS III in 1991). I think some modern embedded MIPS CPUs are still only 32-bit. (And the same reasoning applies to 128-bit integers on MIPS64).
Use 2 registers, an extra one for the high half. MIPS doesn't have flags, so there isn't a 2-instruction add
/add-with-carry
way to add int64_t like there is on many other ISAs, but you can look at compiler output for a C function that adds two 64-bit integers easily enough.
#include <stdint.h>
int64_t add64(int64_t a, int64_t b)
return a+b;
compiled for MIPS on the Godbolt compiler explorer with gcc5.4 -O3
:
add64:
addu $3,$5,$7
sltu $5,$3,$5 # check for carry-out with sum_lo < a_lo (unsigned)
addu $2,$4,$6 # add high halves
j $31 # return (with a branch-delay slot)
addu $2,$5,$2 # add the carry-out from the low half into the high half
In memory, MIPS in big-endian mode (the more common choice for MIPS) stores the entire 64-bit integer in big-endian order, thus the "high half" (most significant 32 bits) is at the lower address, so the highest byte of that word is at the lowest address, and all 8 bytes are in descending order of place value.
void add64_store(int64_t a, int64_t b, int64_t *res)
*res = a+b;
## gcc5.4 -O3 for MIPS - big-endian, not MIPS (el)
addu $7,$5,$7 # low half
lw $2,16($sp)
sltu $5,$7,$5 # carry-out
addu $4,$4,$6
addu $5,$5,$4 # high half
sw $5,0($2) # store the high half to res[0..3]
j $31
sw $7,4($2) # store the low half to res[4..7]
As you can see from the register numbers used, the calling convention passes the high half in the lower-numbered register (earlier arg), unlike on little-endian architectures where the high-half goes in the later arg-passing slot. This makes things work as desired if you run out of register and an int64_t is passed on the stack.
On an architecture with flags and an add-with-carry instruction (like ARM32 for example), you get an add instruction that creates a 33 bit result in C:R0
(top bit in the carry flag, lower 32 in a register).
add64:
adds r0, r2, r0 @ ADD and set flags
adc r1, r3, r1 @ r1 = r1 + r3 + carry
bx lr
You tagged this MIPS32, so you don't have the 64-bit extension to ISA available (introduced in MIPS III in 1991). I think some modern embedded MIPS CPUs are still only 32-bit. (And the same reasoning applies to 128-bit integers on MIPS64).
edited Nov 10 at 19:14
answered Nov 10 at 15:13
Peter Cordes
114k16173298
114k16173298
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53240232%2fhow-does-mips-store-a-number-larger-than-32-bits%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
If you use only 32 bit register, then yes, everything above is thrown away, and values are "truncated" down to 32 bit only. So to store more bits you must use more bits (multiple registers, multiple words in memory, etc...) nothing in CPU will inflate dynamically just because suddenly 32 bits are not enough, all sizes are fixed in asm code, and the code must be prepared to handle more bits, otherwise it will not.
– Ped7g
Nov 10 at 16:55