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?










share|improve this question





















  • 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














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?










share|improve this question





















  • 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












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?










share|improve this question













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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










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
















  • 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












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).






share|improve this answer






















    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    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

























    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).






    share|improve this answer


























      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).






      share|improve this answer
























        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).






        share|improve this answer














        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).







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 10 at 19:14

























        answered Nov 10 at 15:13









        Peter Cordes

        114k16173298




        114k16173298



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            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





















































            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







            這個網誌中的熱門文章

            How to read a connectionString WITH PROVIDER in .NET Core?

            Node.js Script on GitHub Pages or Amazon S3

            Museum of Modern and Contemporary Art of Trento and Rovereto