From d4771688e68357f26b11efc19532edc1b6865de2 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Tue, 3 Nov 2026 10:45:39 +1000 Subject: [PATCH] SP int MIPS: support MIPS Release 6 MIPS Release 6 removed the HI/LO registers and the multu/dmultu, mflo and mfhi instructions. The SP int MIPS and MIPS64 assembly used them and listed $hi/$lo as clobbers, so builds for r6 CPUs failed with "the register '$hi' cannot be clobbered". Add SP_ASM_MIPS_MUL to put the low and high words of a multiplication into registers. Use mulu/muhu (dmulu/dmuhu for 64-bit) when __mips_isa_rev >= 6 and the existing multu/mflo/mfhi sequence otherwise. Only clobber HI/LO before r6. Mark the high word output as early clobber in the macros that write the result directly, as r6 writes it before the inputs are fully consumed. Code generated for pre-r6 targets is unchanged. --- .wolfssl_known_macro_extras | 1 + wolfcrypt/src/sp_int.c | 166 +++++++++++++++++++----------------- 2 files changed, 89 insertions(+), 78 deletions(-) diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 6ebc459788e..0edb315a9c3 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -1514,6 +1514,7 @@ __linux__ __llvm__ __mips __mips64 +__mips_isa_rev __must_check __ppc64__ __ppc__ diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index ab1c4d72042..a5abf9e16f1 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -4173,33 +4173,50 @@ static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo, * CPU: MIPS 64-bit */ +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 6) +/* MIPS Release 6 removed the HI/LO registers and dmultu/mflo/mfhi. + * Multiply va by vb putting the high and low words directly into registers. + * High word is calculated first so the low word output may share a register + * with an input. The high word output must be early clobber. + */ +#define SP_ASM_MIPS_MUL(l, h, a, b) \ + "dmuhu\t" h ", " a ", " b "\n\t" \ + "dmulu\t" l ", " a ", " b "\n\t" +/* No HI/LO registers to clobber. */ +#define SP_ASM_MIPS_HILO +#define SP_ASM_MIPS_HILO_C +#else +/* Multiply va by vb into HI/LO and move the low and high words out. */ +#define SP_ASM_MIPS_MUL(l, h, a, b) \ + "dmultu\t" a ", " b "\n\t" \ + "mflo\t" l "\n\t" \ + "mfhi\t" h "\n\t" +/* HI/LO registers are clobbered by multiplication. */ +#define SP_ASM_MIPS_HILO "$lo", "$hi" +#define SP_ASM_MIPS_HILO_C , "$lo", "$hi" +#endif + /* Multiply va by vb and store double size result in: vh | vl */ #define SP_ASM_MUL(vl, vh, va, vb) \ __asm__ __volatile__ ( \ - "dmultu %[a], %[b] \n\t" \ - "mflo %[l] \n\t" \ - "mfhi %[h] \n\t" \ - : [h] "+r" (vh), [l] "+r" (vl) \ + SP_ASM_MIPS_MUL("%[l]", "%[h]", "%[a]", "%[b]") \ + : [h] "+&r" (vh), [l] "+r" (vl) \ : [a] "r" (va), [b] "r" (vb) \ - : "$lo", "$hi" \ + : SP_ASM_MIPS_HILO \ ) /* Multiply va by vb and store double size result in: vo | vh | vl */ #define SP_ASM_MUL_SET(vl, vh, vo, va, vb) \ __asm__ __volatile__ ( \ - "dmultu %[a], %[b] \n\t" \ - "mflo %[l] \n\t" \ - "mfhi %[h] \n\t" \ + SP_ASM_MIPS_MUL("%[l]", "%[h]", "%[a]", "%[b]") \ "move %[o], $0 \n\t" \ - : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo) \ + : [l] "+r" (vl), [h] "+&r" (vh), [o] "=r" (vo) \ : [a] "r" (va), [b] "r" (vb) \ - : "$lo", "$hi" \ + : SP_ASM_MIPS_HILO \ ) /* Multiply va by vb and add double size result into: vo | vh | vl */ #define SP_ASM_MUL_ADD(vl, vh, vo, va, vb) \ __asm__ __volatile__ ( \ - "dmultu %[a], %[b] \n\t" \ - "mflo $10 \n\t" \ - "mfhi $11 \n\t" \ + SP_ASM_MIPS_MUL("$10", "$11", "%[a]", "%[b]") \ "daddu %[l], %[l], $10 \n\t" \ "sltu $12, %[l], $10 \n\t" \ "daddu %[h], %[h], $12 \n\t" \ @@ -4210,28 +4227,24 @@ static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo, "daddu %[o], %[o], $12 \n\t" \ : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo) \ : [a] "r" (va), [b] "r" (vb) \ - : "$10", "$11", "$12", "$lo", "$hi" \ + : "$10", "$11", "$12" SP_ASM_MIPS_HILO_C \ ) /* Multiply va by vb and add double size result into: vh | vl */ #define SP_ASM_MUL_ADD_NO(vl, vh, va, vb) \ __asm__ __volatile__ ( \ - "dmultu %[a], %[b] \n\t" \ - "mflo $10 \n\t" \ - "mfhi $11 \n\t" \ + SP_ASM_MIPS_MUL("$10", "$11", "%[a]", "%[b]") \ "daddu %[l], %[l], $10 \n\t" \ "sltu $12, %[l], $10 \n\t" \ "daddu %[h], %[h], $11 \n\t" \ "daddu %[h], %[h], $12 \n\t" \ : [l] "+r" (vl), [h] "+r" (vh) \ : [a] "r" (va), [b] "r" (vb) \ - : "$10", "$11", "$12", "$lo", "$hi" \ + : "$10", "$11", "$12" SP_ASM_MIPS_HILO_C \ ) /* Multiply va by vb and add double size result twice into: vo | vh | vl */ #define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb) \ __asm__ __volatile__ ( \ - "dmultu %[a], %[b] \n\t" \ - "mflo $10 \n\t" \ - "mfhi $11 \n\t" \ + SP_ASM_MIPS_MUL("$10", "$11", "%[a]", "%[b]") \ "daddu %[l], %[l], $10 \n\t" \ "sltu $12, %[l], $10 \n\t" \ "daddu %[h], %[h], $12 \n\t" \ @@ -4250,16 +4263,14 @@ static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo, "daddu %[o], %[o], $12 \n\t" \ : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo) \ : [a] "r" (va), [b] "r" (vb) \ - : "$10", "$11", "$12", "$lo", "$hi" \ + : "$10", "$11", "$12" SP_ASM_MIPS_HILO_C \ ) /* Multiply va by vb and add double size result twice into: vo | vh | vl * Assumes first add will not overflow vh | vl */ #define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb) \ __asm__ __volatile__ ( \ - "dmultu %[a], %[b] \n\t" \ - "mflo $10 \n\t" \ - "mfhi $11 \n\t" \ + SP_ASM_MIPS_MUL("$10", "$11", "%[a]", "%[b]") \ "daddu %[l], %[l], $10 \n\t" \ "sltu $12, %[l], $10 \n\t" \ "daddu %[h], %[h], $11 \n\t" \ @@ -4274,24 +4285,20 @@ static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo, "daddu %[o], %[o], $12 \n\t" \ : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo) \ : [a] "r" (va), [b] "r" (vb) \ - : "$10", "$11", "$12", "$lo", "$hi" \ + : "$10", "$11", "$12" SP_ASM_MIPS_HILO_C \ ) /* Square va and store double size result in: vh | vl */ #define SP_ASM_SQR(vl, vh, va) \ __asm__ __volatile__ ( \ - "dmultu %[a], %[a] \n\t" \ - "mflo %[l] \n\t" \ - "mfhi %[h] \n\t" \ - : [h] "+r" (vh), [l] "+r" (vl) \ + SP_ASM_MIPS_MUL("%[l]", "%[h]", "%[a]", "%[a]") \ + : [h] "+&r" (vh), [l] "+r" (vl) \ : [a] "r" (va) \ - : "$lo", "$hi" \ + : SP_ASM_MIPS_HILO \ ) /* Square va and add double size result into: vo | vh | vl */ #define SP_ASM_SQR_ADD(vl, vh, vo, va) \ __asm__ __volatile__ ( \ - "dmultu %[a], %[a] \n\t" \ - "mflo $10 \n\t" \ - "mfhi $11 \n\t" \ + SP_ASM_MIPS_MUL("$10", "$11", "%[a]", "%[a]") \ "daddu %[l], %[l], $10 \n\t" \ "sltu $12, %[l], $10 \n\t" \ "daddu %[h], %[h], $12 \n\t" \ @@ -4302,21 +4309,19 @@ static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo, "daddu %[o], %[o], $12 \n\t" \ : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo) \ : [a] "r" (va) \ - : "$10", "$11", "$12", "$lo", "$hi" \ + : "$10", "$11", "$12" SP_ASM_MIPS_HILO_C \ ) /* Square va and add double size result into: vh | vl */ #define SP_ASM_SQR_ADD_NO(vl, vh, va) \ __asm__ __volatile__ ( \ - "dmultu %[a], %[a] \n\t" \ - "mflo $10 \n\t" \ - "mfhi $11 \n\t" \ + SP_ASM_MIPS_MUL("$10", "$11", "%[a]", "%[a]") \ "daddu %[l], %[l], $10 \n\t" \ "sltu $12, %[l], $10 \n\t" \ "daddu %[h], %[h], $11 \n\t" \ "daddu %[h], %[h], $12 \n\t" \ : [l] "+r" (vl), [h] "+r" (vh) \ : [a] "r" (va) \ - : "$10", "$11", "$12", "$lo", "$hi" \ + : "$10", "$11", "$12" SP_ASM_MIPS_HILO_C \ ) /* Add va into: vh | vl */ #define SP_ASM_ADDC(vl, vh, va) \ @@ -4374,33 +4379,50 @@ static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo, * CPU: MIPS 32-bit */ +#if defined(__mips_isa_rev) && (__mips_isa_rev >= 6) +/* MIPS Release 6 removed the HI/LO registers and multu/mflo/mfhi. + * Multiply va by vb putting the high and low words directly into registers. + * High word is calculated first so the low word output may share a register + * with an input. The high word output must be early clobber. + */ +#define SP_ASM_MIPS_MUL(l, h, a, b) \ + "muhu\t" h ", " a ", " b "\n\t" \ + "mulu\t" l ", " a ", " b "\n\t" +/* No HI/LO registers to clobber. */ +#define SP_ASM_MIPS_HILO +#define SP_ASM_MIPS_HILO_C +#else +/* Multiply va by vb into HI/LO and move the low and high words out. */ +#define SP_ASM_MIPS_MUL(l, h, a, b) \ + "multu\t" a ", " b "\n\t" \ + "mflo\t" l "\n\t" \ + "mfhi\t" h "\n\t" +/* HI/LO registers are clobbered by multiplication. */ +#define SP_ASM_MIPS_HILO "%lo", "%hi" +#define SP_ASM_MIPS_HILO_C , "%lo", "%hi" +#endif + /* Multiply va by vb and store double size result in: vh | vl */ #define SP_ASM_MUL(vl, vh, va, vb) \ __asm__ __volatile__ ( \ - "multu %[a], %[b] \n\t" \ - "mflo %[l] \n\t" \ - "mfhi %[h] \n\t" \ - : [h] "+r" (vh), [l] "+r" (vl) \ + SP_ASM_MIPS_MUL("%[l]", "%[h]", "%[a]", "%[b]") \ + : [h] "+&r" (vh), [l] "+r" (vl) \ : [a] "r" (va), [b] "r" (vb) \ - : "%lo", "%hi" \ + : SP_ASM_MIPS_HILO \ ) /* Multiply va by vb and store double size result in: vo | vh | vl */ #define SP_ASM_MUL_SET(vl, vh, vo, va, vb) \ __asm__ __volatile__ ( \ - "multu %[a], %[b] \n\t" \ - "mflo %[l] \n\t" \ - "mfhi %[h] \n\t" \ + SP_ASM_MIPS_MUL("%[l]", "%[h]", "%[a]", "%[b]") \ "move %[o], $0 \n\t" \ - : [l] "+r" (vl), [h] "+r" (vh), [o] "=r" (vo) \ + : [l] "+r" (vl), [h] "+&r" (vh), [o] "=r" (vo) \ : [a] "r" (va), [b] "r" (vb) \ - : "%lo", "%hi" \ + : SP_ASM_MIPS_HILO \ ) /* Multiply va by vb and add double size result into: vo | vh | vl */ #define SP_ASM_MUL_ADD(vl, vh, vo, va, vb) \ __asm__ __volatile__ ( \ - "multu %[a], %[b] \n\t" \ - "mflo $10 \n\t" \ - "mfhi $11 \n\t" \ + SP_ASM_MIPS_MUL("$10", "$11", "%[a]", "%[b]") \ "addu %[l], %[l], $10 \n\t" \ "sltu $12, %[l], $10 \n\t" \ "addu %[h], %[h], $12 \n\t" \ @@ -4411,28 +4433,24 @@ static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo, "addu %[o], %[o], $12 \n\t" \ : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo) \ : [a] "r" (va), [b] "r" (vb) \ - : "$10", "$11", "$12", "%lo", "%hi" \ + : "$10", "$11", "$12" SP_ASM_MIPS_HILO_C \ ) /* Multiply va by vb and add double size result into: vh | vl */ #define SP_ASM_MUL_ADD_NO(vl, vh, va, vb) \ __asm__ __volatile__ ( \ - "multu %[a], %[b] \n\t" \ - "mflo $10 \n\t" \ - "mfhi $11 \n\t" \ + SP_ASM_MIPS_MUL("$10", "$11", "%[a]", "%[b]") \ "addu %[l], %[l], $10 \n\t" \ "sltu $12, %[l], $10 \n\t" \ "addu %[h], %[h], $11 \n\t" \ "addu %[h], %[h], $12 \n\t" \ : [l] "+r" (vl), [h] "+r" (vh) \ : [a] "r" (va), [b] "r" (vb) \ - : "$10", "$11", "$12", "%lo", "%hi" \ + : "$10", "$11", "$12" SP_ASM_MIPS_HILO_C \ ) /* Multiply va by vb and add double size result twice into: vo | vh | vl */ #define SP_ASM_MUL_ADD2(vl, vh, vo, va, vb) \ __asm__ __volatile__ ( \ - "multu %[a], %[b] \n\t" \ - "mflo $10 \n\t" \ - "mfhi $11 \n\t" \ + SP_ASM_MIPS_MUL("$10", "$11", "%[a]", "%[b]") \ "addu %[l], %[l], $10 \n\t" \ "sltu $12, %[l], $10 \n\t" \ "addu %[h], %[h], $12 \n\t" \ @@ -4451,16 +4469,14 @@ static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo, "addu %[o], %[o], $12 \n\t" \ : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo) \ : [a] "r" (va), [b] "r" (vb) \ - : "$10", "$11", "$12", "%lo", "%hi" \ + : "$10", "$11", "$12" SP_ASM_MIPS_HILO_C \ ) /* Multiply va by vb and add double size result twice into: vo | vh | vl * Assumes first add will not overflow vh | vl */ #define SP_ASM_MUL_ADD2_NO(vl, vh, vo, va, vb) \ __asm__ __volatile__ ( \ - "multu %[a], %[b] \n\t" \ - "mflo $10 \n\t" \ - "mfhi $11 \n\t" \ + SP_ASM_MIPS_MUL("$10", "$11", "%[a]", "%[b]") \ "addu %[l], %[l], $10 \n\t" \ "sltu $12, %[l], $10 \n\t" \ "addu %[h], %[h], $11 \n\t" \ @@ -4475,24 +4491,20 @@ static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo, "addu %[o], %[o], $12 \n\t" \ : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo) \ : [a] "r" (va), [b] "r" (vb) \ - : "$10", "$11", "$12", "%lo", "%hi" \ + : "$10", "$11", "$12" SP_ASM_MIPS_HILO_C \ ) /* Square va and store double size result in: vh | vl */ #define SP_ASM_SQR(vl, vh, va) \ __asm__ __volatile__ ( \ - "multu %[a], %[a] \n\t" \ - "mflo %[l] \n\t" \ - "mfhi %[h] \n\t" \ - : [h] "+r" (vh), [l] "+r" (vl) \ + SP_ASM_MIPS_MUL("%[l]", "%[h]", "%[a]", "%[a]") \ + : [h] "+&r" (vh), [l] "+r" (vl) \ : [a] "r" (va) \ - : "%lo", "%hi" \ + : SP_ASM_MIPS_HILO \ ) /* Square va and add double size result into: vo | vh | vl */ #define SP_ASM_SQR_ADD(vl, vh, vo, va) \ __asm__ __volatile__ ( \ - "multu %[a], %[a] \n\t" \ - "mflo $10 \n\t" \ - "mfhi $11 \n\t" \ + SP_ASM_MIPS_MUL("$10", "$11", "%[a]", "%[a]") \ "addu %[l], %[l], $10 \n\t" \ "sltu $12, %[l], $10 \n\t" \ "addu %[h], %[h], $12 \n\t" \ @@ -4503,21 +4515,19 @@ static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo, "addu %[o], %[o], $12 \n\t" \ : [l] "+r" (vl), [h] "+r" (vh), [o] "+r" (vo) \ : [a] "r" (va) \ - : "$10", "$11", "$12", "%lo", "%hi" \ + : "$10", "$11", "$12" SP_ASM_MIPS_HILO_C \ ) /* Square va and add double size result into: vh | vl */ #define SP_ASM_SQR_ADD_NO(vl, vh, va) \ __asm__ __volatile__ ( \ - "multu %[a], %[a] \n\t" \ - "mflo $10 \n\t" \ - "mfhi $11 \n\t" \ + SP_ASM_MIPS_MUL("$10", "$11", "%[a]", "%[a]") \ "addu %[l], %[l], $10 \n\t" \ "sltu $12, %[l], $10 \n\t" \ "addu %[h], %[h], $11 \n\t" \ "addu %[h], %[h], $12 \n\t" \ : [l] "+r" (vl), [h] "+r" (vh) \ : [a] "r" (va) \ - : "$10", "$11", "$12", "%lo", "%hi" \ + : "$10", "$11", "$12" SP_ASM_MIPS_HILO_C \ ) /* Add va into: vh | vl */ #define SP_ASM_ADDC(vl, vh, va) \