/***** * * Michael Riff * Multiprecision main program version 1.0 Februar 2022. * * Main routine calling the assember implemented multiprecision routines: * div.s : 64 bits and 96/64 bits as 128/64 bits divisions * lib_64.s : 64 bits additions and multiplication (result on 128 bits) * lib_128.s : 128 bits addition * * March 2022 clear renaming of routines and reordering in the files: * Addition of a full 128:128 bits division test * April 2024 addition of a 128/96 bits division test as well * as comparison checks with 128/64 and 128/128 (with top 32 bits=0) * * May 2024 additional 96/64 and 128/64 tests *****/ #include #include typedef struct { unsigned long high; unsigned long low; } Unsigned64; /* Unsigned 64 type defined in Toolbox as typdef struct { unsigned long high; unsignd long low; } Int64bit; */ // Signed 64 type defined typedef struct{ long high; //TBC unsigned long low; } Signed64; typedef struct { unsigned long high; unsigned long middle; unsigned long low; } Unsigned96; typedef struct { unsigned long high; unsigned long middle_u; unsigned long middle_l; unsigned long low; } Unsigned128; typedef struct { long high; long middle_u; long middle_l; long low; } Signed128; /* Definition of prototypes. Not necessary if not inferred. */ // File test.s for test (overflow & carry & division shifts) test_sub (int Val1, int Val2, unsigned int *OfwCry); test_add (int Val1, int Val2, unsigned int *OfwCry); void test_64_2 (Unsigned64 *dvd, Unsigned64 *dvs, Unsigned64 *quot, Unsigned64 *rem); void test_96 (Unsigned96 *dvd, Unsigned64 *dvs, Unsigned96 *quot, Unsigned64 *rem); void test_128 (Unsigned128 *dvd, Unsigned64 *dvs, Unsigned128 *quot, Unsigned64 *rem); void test_96_64 (Unsigned96 *dvd, Unsigned64 *dvs, Unsigned96 *quot, Unsigned64 *rem); void test_128_64 (Unsigned128 *dvd, Unsigned64 *dvs, Unsigned128 *quot, Unsigned64 *rem); // File div.s void div_64 (Unsigned64 *dvd, Unsigned64 *dvs, Unsigned64 *quot, Unsigned64 *rem); void div_64_2 (Unsigned64 *dvd, Unsigned64 *dvs, Unsigned64 *quot, Unsigned64 *rem); void div_96_64 (Unsigned96 *dvd, Unsigned64 *dvs, Unsigned96 *quot, Unsigned64 *rem); void div_128_64 (Unsigned128 *dvd, Unsigned64 *dvs, Unsigned128 *quot, Unsigned64 *rem); void div_128_128 (Unsigned128 *dvd, Unsigned128 *dvs, Unsigned128 *quot, Unsigned128 *rem); void div_128_96 (Unsigned128 *dvd, Unsigned96 *dvs, Unsigned128 *quot, Unsigned96 *rem); // Filde div2.s void div_96_63 (Unsigned96 *dvd, Unsigned64 *dvs, Unsigned96 *quot, Unsigned64 *rem); void div_128_63 (Unsigned128 *dvd, Unsigned64 *dvs, Unsigned128 *quot, Unsigned64 *rem); void div_128_95 (Unsigned128 *dvd, Unsigned96 *dvs, Unsigned128 *quot, Unsigned96 *rem); // File lib_64.s void add_64 (Unsigned64 *left, Unsigned64 *rigt, Unsigned64 *sum, int *ovflcry); void sub_64 (Signed64 *Substend, Signed64 *Substract, Signed64 *Result, int *ovflcry); void mul_64u (Unsigned64 *left, Unsigned64 *right, Unsigned128 *prod); void mul_64s (Signed64 *left, Signed64 *right, Signed128 *prod); // lib_128.s void add_128 (Signed128 *left, Signed128 *right, Signed128 *sum, int *ovfl); //void add_128_64 (Signed128 *left, Signed64 *right, Signed128 *sum, int *ovfl); void sub_128 (Signed128 *left, Signed128 *right, Signed128 *sum, int *ovfl); // Test utilities /* Backwards calculation for 64:64 bits division */ void Reverse64_64(Unsigned64 *Quotient, Unsigned64 *Remain, Unsigned64 *Divisor) { Unsigned64 Temp; Unsigned128 Result; int xer; mul_64u (Quotient, Divisor, &Result); if (Result.high !=0 || Result.middle_u !=0) { // Multiplication would be larger than 64 bits printf ("1 Error! 64 bits ovfw %x %x\n", Result.high, Result.low); } Temp.high = Result.middle_l; Temp.low = Result.low; add_64 (&Temp, Remain, &Temp, &xer); printf("64 rev %x %x %x %x, %x\n", Temp.high, Temp.low, xer); } /* Backwards calculation for 96:64 bits division */ void Reverse96_64(Unsigned96 *Quotient, Unsigned64 *Remain, Unsigned64 *Divisor) { Unsigned64 Temp; Unsigned128 Result; Signed128 SResult; int xer; // Multiply Quotient with divisor in 2 steps Temp.high = Quotient->high; Temp.low = Quotient->middle; mul_64u (Divisor, &Temp, &Result); // Shift by 32 bits Result.high = 0; Result.middle_u = Result.middle_l; Result.middle_l = Result.low; Result.low = 0; Temp.high = 0; Temp.low = Quotient->low; mul_64u (Divisor, &Temp, (Unsigned128*)&SResult); add_128 ((Signed128*)&Result, &SResult, (Signed128*)&Result, &xer); SResult.high = 0; SResult.middle_u = 0; SResult.middle_l = Remain->high; SResult.low = Remain->low; add_128 (&SResult, (Signed128*)&Result, (Signed128*)&Result, &xer); printf("96 div rev %x %x %x %x, %x\n", Result.high, Result.middle_u, Result.middle_l, Result.low, xer); } /* Backwards calculation for 128:64 bits division */ void Reverse128_64(Unsigned128 *Quotient, Unsigned64 *Remain, Unsigned64 *Divisor) { Unsigned64 Temp; Unsigned128 Result; Signed128 SResult; int xer; // Multiply Quotient with divisor in 2 steps Temp.high = Quotient->high; Temp.low = Quotient->middle_u; mul_64u (Divisor, &Temp, &Result); // Shift by 64 bits Result.high = Result.middle_l; Result.middle_u = Result.low; Result.middle_l = 0; Result.low = 0; Temp.high = Quotient->middle_l; Temp.low = Quotient->low; mul_64u (Divisor, &Temp, (Unsigned128*)&SResult); add_128 ((Signed128*)&Result, &SResult, (Signed128*)&Result, &xer); // Add remainder SResult.high = 0; SResult.middle_u = 0; SResult.middle_l = Remain->high; SResult.low = Remain->low; add_128 (&SResult, (Signed128*)&Result, (Signed128*)&Result, &xer); printf("128 div rev %x %x %x %x, %x\n", Result.high, Result.middle_u, Result.middle_l, Result.low, xer); } /* Backwards test for 128:96 division */ void Back_128_96 (Unsigned128 *Quot, Unsigned96 *Remain, Unsigned96 *Divisor) { Unsigned64 tmp1, tmp2; Unsigned128 Result1, Result2; Signed128 SResult; int xer; // First we check that the product of the 64 highest bits is 0 tmp1.high = Quot->high; tmp1.low = Quot->middle_u; tmp2.high = 0; tmp2.low = Divisor->high; mul_64u (&tmp1, &tmp2, &Result1); if (Result1.high !=0 || Result1.middle_u != 0 || Result1.middle_l != 0 || Result1.low !=0) { printf ("1 Error! 128_96 bits ovfw %x %x %x %x\n", Result1.high, Result1.middle_u, Result1.middle_l, Result1.low); } // Calculate the cross products tmp2.high = Divisor->middle; tmp2.low = Divisor->low; mul_64u (&tmp1, &tmp2, &Result1); tmp1.high = Quot->middle_l; tmp1.low = Quot->low; tmp2.high = 0; tmp2.low = Divisor->high; mul_64u (&tmp1, &tmp2, &Result2); add_128 ((Signed128*)&Result1, (Signed128*)&Result2, (Signed128*)&Result1, &xer); // Shift result by 64 bits if (Result1.high !=0 || Result1.middle_u != 0) { printf ("2 Error! 128_96 bits ovfw %x %x %x %x\n", Result1.high, Result1.middle_u, Result1.middle_l, Result1.low); } Result1.high = Result1.middle_l; Result1.middle_u = Result1.low; Result1.middle_l = 0x0; Result1.low = 0x0; // Calculate low product tmp2.high = Divisor->middle; tmp2.low = Divisor->low; mul_64u (&tmp1, &tmp2, &Result2); add_128 ((Signed128*)&Result1, (Signed128*)&Result2, (Signed128*)&Result1, &xer); // Add remainder SResult.high = 0; SResult.middle_u = Remain->high; SResult.middle_l = Remain->middle; SResult.low = Remain->low; add_128 ((Signed128*)&Result1, &SResult, (Signed128*)&Result2, &xer); printf ("128:96 rev %x %x %x %x\n", Result2.high, Result2.middle_u, Result2.middle_l, Result2.low); } /* Backwards test for 128:128 division */ void Back_128_128 (Unsigned128 *Quot, Unsigned128 *Remain, Unsigned128 *Divisor) { Unsigned64 tmp1, tmp2; Unsigned128 Result1, Result2; int xer; // First we check that the product of the 64 highest bits is 0 tmp1.high = Quot->high; tmp1.low = Quot->middle_u; tmp2.high = Divisor->high; tmp2.low = Divisor->middle_u; mul_64u (&tmp1, &tmp2, &Result1); if (Result1.high !=0 || Result1.middle_u != 0 || Result1.middle_l != 0 || Result1.low !=0) { printf ("1 Error! 128 bits ovfw %x %x %x %x\n", Result1.high, Result1.middle_u, Result1.middle_l, Result1.low); } // Calculate the cross products tmp2.high = Divisor->middle_l; tmp2.low = Divisor->low; mul_64u (&tmp1, &tmp2, &Result1); tmp1.high = Quot->middle_l; tmp1.low = Quot->low; tmp2.high = Divisor->high; tmp2.low = Divisor->middle_u; mul_64u (&tmp1, &tmp2, &Result2); add_128 ((Signed128*)&Result1, (Signed128*)&Result2, (Signed128*)&Result1, &xer); // Shift result by 64 bits if (Result1.high !=0 || Result1.middle_u != 0) { printf ("2 Error! 128 bits ovfw %x %x %x %x\n", Result1.high, Result1.middle_u, Result1.middle_l, Result1.low); } Result1.high = Result1.middle_l; Result1.middle_u = Result1.low; Result1.middle_l = 0x0; Result1.low = 0x0; // Calculate low product tmp2.high = Divisor->middle_l; tmp2.low = Divisor->low; mul_64u (&tmp1, &tmp2, &Result2); add_128 ((Signed128*)&Result1, (Signed128*)&Result2, (Signed128*)&Result1, &xer); add_128 ((Signed128*)&Result1, (Signed128*)Remain, (Signed128*)&Result2, &xer); printf ("128:128 rev %x %x %x %x\n", Result2.high, Result2.middle_u, Result2.middle_l, Result2.low); } // For addition/subtraction Signed64 Signed1, Signed2, Result; Unsigned64 UResult; Signed128 Signed128_1, Signed128_2, SResult128; Unsigned128 Divisor_128, Remain_128;; // For division (always done with unsiged types) Unsigned64 Divisor; Unsigned64 Test_64, Quot_64; Unsigned64 Remain_64; Unsigned96 Test_96, Quot_96, Quot_96_2; Unsigned96 Remain_96; Unsigned128 Test_128, Quot_128; int ofw; char dummy; int main() { unsigned int uVal1, uVal2, uVal3, OfwCry; int sVal1, sVal2, sVal3; printf("hello world\n"); /* OVERFLOW AND CARRY */ /* // Unsigned addition overflow uVal1 = 0x60000000; uVal2 = 0xC0000000; uVal3 = test_add (uVal1, uVal2, &OfwCry); printf("Usgn add %d %x\n", uVal3, OfwCry); // Unsigned subtraction underflow uVal1 = 0x08000000; uVal2 = 0x80000000; uVal3 = test_sub (uVal1, uVal2, &OfwCry); printf("Usgn sub %d %x\n", uVal3, OfwCry); // Signed addition overflow sVal1 = 0x70000000; sVal2 = 0x10000000; sVal3 = test_add (sVal1, sVal2, &OfwCry); printf("Sgn add %d %x\n", sVal3, OfwCry); // Signed addition underflow sVal1 = 0x80000000; sVal2 = 0xFFFFFFFF; // (-1) sVal3 = test_add (sVal1, sVal2, &OfwCry); printf("Sgn add %d %x\n", sVal3, OfwCry); // Signed subtraction overflow sVal1 = 0x70000000; sVal2 = 0xF0000000; // (-0x10000000) sVal3 = test_sub (sVal1, sVal2, &OfwCry); printf("Sgn sub %d %x\n", sVal3, OfwCry); // Signed subtraction underflow sVal1 = 0x80000000; sVal2 = 0x00010000; sVal3 = test_sub (sVal1, sVal2, &OfwCry); printf("Sgn sub %d %x\n", sVal3, OfwCry); */ /* ADDITION */ /* // 64 bits Divisor.high = 0x00405090; Divisor.low = 0x0F000000; Test_64.high = 0x05020505; Test_64.low = 0x60300000; add_64 (&Test_64, &Divisor, &Divisor, &ofw); printf("64 bit add %x %x, %x\n", Divisor.high, Divisor.low, ofw); Test_64.high = 0x0625a6e1; Test_64.low = 0xF53a4000; Quot_64.high = 0x0034b123; Quot_64.low = 0x6c987000; add_64 (&Test_64, &Quot_64, &Quot_64, &ofw); printf("64 bit add %x %x, %x\n", Quot_64.high, Quot_64.low, ofw); Test_64.high = 0x67a5b64c; Test_64.low = 0x14d0e32f; Quot_64.high = 0x12345678; Quot_64.low = 0xabcdef01; add_64 (&Test_64, & Quot_64, &Quot_64, &ofw); printf("64 bit add %x %x, %x\n", Quot_64.high, Quot_64.low, ofw); Signed1.high = 0x0625a6e1; Signed1.low = 0xF53a4000; Signed2.high = 0x0034b123; Signed2.low = 0x6c987000; sub_64(&Signed1, &Signed2, &Result, &ofw); printf("64 bit sub %x %x, %x\n", Result.high, Result.low, &ofw); Signed1.high = 0x0625a6e1; Signed1.low = 0x053a4000; sub_64(&Signed1, &Signed2, &Result, &ofw); printf("64 bit sub %x %x, %x\n", Result.high, Result.low, &ofw); Signed1.high = 0x065bc34c; Signed1.low = 0x17d0e820; Signed2.high = 0x0134b1e3; Signed2.low = 0x6c927050; sub_64(&Signed1, &Signed2, &Result, &ofw); printf("64 bit sub %x %x, %x\n", Result.high, Result.low, &ofw); // 128 bits Signed128_1.high = 0x38508253; Signed128_1.middle_u = 0x40129754; Signed128_1.middle_l = 0xabcdef00; Signed128_1.low = 0x3d7a9f7b; Signed128_2.high = 0x46af7c54; Signed128_2.middle_u = 0x210e3457; Signed128_2.middle_l = 0x3100fecc; Signed128_2.low = 0x4b1dc038; add_128(&Signed128_1, &Signed128_2, &SResult128, &ofw); printf("128 bit add %x %x %x %x, %x\n", SResult128.high, SResult128.middle_u , SResult128.middle_l, SResult128.low, ofw); Signed128_1.high = 0x38508253; Signed128_1.middle_u = 0x40129754; Signed128_1.middle_l = 0xabcdef00; Signed128_1.low = 0x3d7a9f7b; Signed128_2.high = 0x46af7c54; Signed128_2.middle_u = 0x210e3457; Signed128_2.middle_l = 0x7100fecc; Signed128_2.low = 0x4b1dc038; add_128(&Signed128_1, &Signed128_2, &SResult128, &ofw); printf("128 bit add %x %x %x %x, %x\n", SResult128.high, SResult128.middle_u , SResult128.middle_l, SResult128.low, ofw); Signed128_1.high = 0x38508253; Signed128_1.middle_u = 0x40129754; Signed128_1.middle_l = 0xabcdef00; Signed128_1.low = 0x3d7a9f7b; Signed128_2.high = 0x26af7c54; Signed128_2.middle_u = 0x210e3457; Signed128_2.middle_l = 0x3100fecc; Signed128_2.low = 0x4b1dc038; sub_128(&Signed128_1, &Signed128_2, &SResult128, &ofw); printf("128 bit sub %x %x %x %x, %x\n", SResult128.high, SResult128.middle_u , SResult128.middle_l, SResult128.low, ofw); Signed128_1.high = 0x38508253; Signed128_1.middle_u = 0x40129754; Signed128_1.middle_l = 0xabcdef00; Signed128_1.low = 0x3d7a9f7b; Signed128_2.high = 0x26af7c54; Signed128_2.middle_u = 0x210e3457; Signed128_2.middle_l = 0x3100fecc; Signed128_2.low = 0x4b1dc038; sub_128(&Signed128_1, &Signed128_2, &SResult128, &ofw); printf("128 bit sub %x %x %x %x, %x\n", SResult128.high, SResult128.middle_u , SResult128.middle_l, SResult128.low, ofw); */ /* MULTIPLICATION */ /* Test_64.high = 0x05020505; Test_64.low = 0x60300000; Remain_64.high = 0x05425595; Remain_64.low = 0x6f300000; mul_64u (&Test_64, &Remain_64, &Quot_128); printf("64 bit mulu %x %x %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low); Signed1.high = 0x05020505; Signed1.low = 0x60300000; Signed2.high = 0x05425595; Signed2.low = 0x6f300000; mul_64s (&Signed1, &Signed2, &SResult128); printf("64 bit muls %x %x %x %x\n", SResult128.high, SResult128.middle_u, SResult128.middle_l, SResult128.low); Quot_64.high = 0x05020505; Quot_64.low = 0x60300000; Remain_64.high = 0x14d0e32f; Remain_64.low = 0x1234cdef; mul_64u (&Quot_64, &Remain_64, &Quot_128); printf("64 bit mulu %x %x %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low); Signed1.high = 0x05020505; Signed1.low = 0x60300000; Signed2.high = 0x14d0e32f; Signed2.low = 0x1234cdef; mul_64s (&Signed1, &Signed2, &SResult128); printf("64 bit muls %x %x %x %x\n", SResult128.high, SResult128.middle_u, SResult128.middle_l, SResult128.low); */ /* DIVISION TESTS */ /* 64 : 64 bits */ // Shift < 32 Divisor.high = 0x00F00000; Divisor.low = 0x0F000000; Test_64.high = 0x05020505; Test_64.low = 0x60300000; div_64 (&Test_64, &Divisor, &Quot_64, &Remain_64); printf("--> 64_64 div %x %x / %x %x|\t%x %x + %x %x\n", Test_64.high, Test_64.low, Divisor.high, Divisor.low, Quot_64.high, Quot_64.low, Remain_64.high, Remain_64.low); Reverse64_64(&Quot_64, &Remain_64, &Divisor); // test_64_2 (&Test_64, &Divisor, &Quot_64, &Remain_64); div_64_2 (&Test_64, &Divisor, &Quot_64, &Remain_64); printf("--> 64_64 div %x %x / %x %x|\t%x %x + %x %x\n", Test_64.high, Test_64.low, Divisor.high, Divisor.low, Quot_64.high, Quot_64.low, Remain_64.high, Remain_64.low); Reverse64_64(&Quot_64, &Remain_64, &Divisor); Divisor.high = 0x0246809a; Divisor.low = 0xa1b3c4d5; Test_64.high = 0xa1b3c4d5; Test_64.low = 0xe6f72890; div_64_2 (&Test_64, &Divisor, &Quot_64, &Remain_64); printf("--> 64_64 div %x %x / %x %x|\t%x %x + %x %x\n", Test_64.high, Test_64.low, Divisor.high, Divisor.low, Quot_64.high, Quot_64.low, Remain_64.high, Remain_64.low); Reverse64_64(&Quot_64, &Remain_64, &Divisor); Divisor.high = 0x001f9d8e; Divisor.low = 0x2d3f4a5b; div_64_2 (&Test_64, &Divisor, &Quot_64, &Remain_64); printf("--> 64_64 div %x %x / %x %x|\t%x %x + %x %x\n", Test_64.high, Test_64.low, Divisor.high, Divisor.low, Quot_64.high, Quot_64.low, Remain_64.high, Remain_64.low); Reverse64_64(&Quot_64, &Remain_64, &Divisor); // Shift > 32 Divisor.high = 0x00000000; Divisor.low = 0x2d3f4a5b; Test_64.high = 0xa1b3c4d5; Test_64.low = 0xe6f72890; div_64_2 (&Test_64, &Divisor, &Quot_64, &Remain_64); printf("--> 64_64 div %x %x / %x %x|\t%x %x + %x %x\n", Test_64.high, Test_64.low, Divisor.high, Divisor.low, Quot_64.high, Quot_64.low, Remain_64.high, Remain_64.low); Reverse64_64(&Quot_64, &Remain_64, &Divisor); Divisor.high = 0x00000000; Divisor.low = 0x01f2e3d4; div_64_2 (&Test_64, &Divisor, &Quot_64, &Remain_64); printf("--> 64_64 div %x %x / %x %x|\t%x %x + %x %x\n", Test_64.high, Test_64.low, Divisor.high, Divisor.low, Quot_64.high, Quot_64.low, Remain_64.high, Remain_64.low); Reverse64_64(&Quot_64, &Remain_64, &Divisor); Divisor.high = 0x00000000; Divisor.low = 0x002fe3d4; div_64_2 (&Test_64, &Divisor, &Quot_64, &Remain_64); printf("--> 64_64 div %x %x / %x %x|\t%x %x + %x %x\n", Test_64.high, Test_64.low, Divisor.high, Divisor.low, Quot_64.high, Quot_64.low, Remain_64.high, Remain_64.low); Reverse64_64(&Quot_64, &Remain_64, &Divisor); scanf("%c\r", &dummy); /* 96 : 64 bits */ // Shift < 32 (22+5+1=28) 4*7 Divisor.high = 0x07F00000; Test_96.high = 0x00303030; Test_96.middle = 0x05050101; // dvsr 0x07F00000 Test_96.low = 0x13111121; // test_96 (&Test_96, &Divisor, &Quot_96, &Remain_64); printf("--> 96_64 div %x %x %x / %x %x|\n", Test_96.high, Test_96.middle, Test_96.low, Divisor.high, Divisor.low); div_96_64 (&Test_96, &Divisor, &Quot_96, &Remain_64); printf("%x %x %x + %x %x\n", Quot_96.high, Quot_96.middle, Quot_96.low, Remain_64.high, Remain_64.low); Reverse96_64(&Quot_96, &Remain_64, &Divisor); // Shift < 64 (28+19+1=48) 4*12 Divisor.high = 0x00001F00; Test_96.high = 0x0FF00001; Test_96.middle = 0x05810580; // dvsr 0x00001F00 Test_96.low = 0x13111121; // test_96 (&Test_96, &Divisor, &Quot_96, &Remain_64); printf("--> 96_64 div %x %x %x / %x %x|\n", Test_96.high, Test_96.middle, Test_96.low, Divisor.high, Divisor.low); div_96_64 (&Test_96, &Divisor, &Quot_96, &Remain_64); printf("%x %x %x + %x %x\n", Quot_96.high, Quot_96.middle, Quot_96.low, Remain_64.high, Remain_64.low); Reverse96_64(&Quot_96, &Remain_64, &Divisor); // Shift < 96 (32+32+3+1=68) 4*17 Divisor.high = 0x00000000; Divisor.low = 0x1F000000; Test_96.high = 0xF0F03030; Test_96.middle = 0x05050101; Test_96.low = 0x11111111; // dvsr 0x1F000000 // test_96 (&Test_96, &Divisor, &Quot_96, &Remain_64); printf("--> 96_64 div %x %x %x / %x %x|\n", Test_96.high, Test_96.middle, Test_96.low, Divisor.high, Divisor.low); div_96_64 (&Test_96, &Divisor, &Quot_96, &Remain_64); printf("%x %x %x + %x %x\n", Quot_96.high, Quot_96.middle, Quot_96.low, Remain_64.high, Remain_64.low); Reverse96_64(&Quot_96, &Remain_64, &Divisor); scanf("%c\r", &dummy); /* 128 : 64 bits */ // Shift < 32 (18+5+1=24) 4*6 Divisor.high = 0x07000000; Test_128.high = 0x00000000; Test_128.middle_u = 0x00035050; Test_128.middle_l = 0x03030303; // dvsr 0x0700000000 Test_128.low = 0x11111111; // test_128 (&Test_128, &Divisor, &Quot_128, &Remain_64); div_128_64 (&Test_128, &Divisor, &Quot_128, &Remain_64); printf("--> 128_64 div %x %x %x %x|\t", Test_128.high, Test_128.middle_u , Test_128.middle_l, Test_128.low); printf("%x %x %x %x + %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_64.high, Remain_64.low); Reverse128_64(&Quot_128, &Remain_64, &Divisor); // Shift < 64 (19+32+8+1=60) 4*15 Divisor.high = 0x00F00000; Test_128.high = 0x0070303; Test_128.middle_u = 0x05050505; Test_128.middle_l = 0x03030303; // dvsr 0x00F00000 Test_128.low = 0x11111111; // test_128 (&Test_128, &Divisor, &Quot_128, &Remain_64); div_128_64 (&Test_128, &Divisor, &Quot_128, &Remain_64); printf("--> 128_64 div %x %x %x %x|\t", Test_128.high, Test_128.middle_u , Test_128.middle_l, Test_128.low); printf("%x %x %x %x + %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_64.high, Remain_64.low); Reverse128_64(&Quot_128, &Remain_64, &Divisor); // Shift < 96 (23+32+32+4+1=92) 4*23 Divisor.high = 0x00000000; Divisor.low = 0x0F000000; Test_128.high = 0x00730303; Test_128.middle_u = 0x05050505; Test_128.middle_l = 0x03030303; Test_128.low = 0x11111111; // dvsr 0x0F000000 // test_128 (&Test_128, &Divisor, &Quot_128, &Remain_64); div_128_64 (&Test_128, &Divisor, &Quot_128, &Remain_64); printf("--> 128_64 div %x %x %x %x|\t", Test_128.high, Test_128.middle_u , Test_128.middle_l, Test_128.low); printf("%x %x %x %x + %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_64.high, Remain_64.low); Reverse128_64(&Quot_128, &Remain_64, &Divisor); // Shift >= 96 (31+32+32+4+1=100) Test_128.high = 0x71030303; Test_128.middle_u = 0x05050505; Test_128.middle_l = 0x03030303; Test_128.low = 0x11111111; // dvsr 0x0F000000 // test_128 (&Test_128, &Divisor, &Quot_128, &Remain_64); div_128_64 (&Test_128, &Divisor, &Quot_128, &Remain_64); printf("--> 128_64 div %x %x %x %x|\t", Test_128.high, Test_128.middle_u , Test_128.middle_l, Test_128.low); printf("%x %x %x %x + %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_64.high, Remain_64.low); Reverse128_64(&Quot_128, &Remain_64, &Divisor); // Test 128 bit Division with 2 96 bits divs Test_96.high = 0x71030303; Test_96.middle = 0x05050505; Test_96.low = 0x03030303; // dvsr 0x0F000000 div_96_64 (&Test_96, &Divisor, &Quot_96, &Remain_64); Test_96.high = Remain_64.high; Test_96.middle = Remain_64.low; Test_96.low = 0x11111111; // dvsr 0x0F000000 div_96_63 (&Test_96, &Divisor, &Quot_96_2, &Remain_64); Quot_128.high = Quot_96.high; Quot_96.high = Quot_96.middle + Quot_96_2.high; Quot_96.middle = Quot_96.low + Quot_96_2.middle; Quot_96.low = Quot_96_2.low; printf("--> 128_64 by 2 96 div %x %x %x %x + %x %x\n", Quot_128.high, Quot_96.high, Quot_96.middle, Quot_96.low, Remain_64.high, Remain_64.low); Reverse128_64(&Quot_128, &Remain_64, &Divisor); scanf("%c\r", &dummy); // Additional Divisor.high = 0x00000000; Divisor.low = 0x4c5d6e7f; Test_128.high = 0x67a5b64c; Test_128.middle_u = 0x14d0e32f; Test_128.middle_l = 0x12345678; Test_128.low = 0xabcdef01; // dvsr 0x4c5d6e7f // test_128 (&Test_128, &Divisor, &Quot_128, &Remain_64); div_128_64 (&Test_128, &Divisor, &Quot_128, &Remain_64); printf("--> 128_64 bit div %x %x %x %x|\t", Test_128.high, Test_128.middle_u , Test_128.middle_l, Test_128.low); printf("%x %x %x %x + %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_64.high, Remain_64.low); Reverse128_64(&Quot_128, &Remain_64, &Divisor); /* Additional division tests, to check the shift of a bit into the register of higher order than the divisor. See note! */ Test_128.high = 0x02020000; Test_128.middle_u = 0x00000000; Test_128.middle_l = 0x00000000; Test_128.low = 0x00000000; Divisor.high = 0x90000000; Divisor.low = 0x00000000; div_128_64 (&Test_128, &Divisor, &Quot_128, &Remain_64); printf("--> 128_64 bit div %x %x %x %x|\t", Test_128.high, Test_128.middle_u , Test_128.middle_l, Test_128.low); printf("%x %x %x %x + %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_64.high, Remain_64.low); Reverse128_64(&Quot_128, &Remain_64, &Divisor); Test_96.high = 0x02020000; Test_96.middle = 0x00000000; Test_96.low = 0x00000000; printf("--> 96_64 bit test %x %x %x / %x %x|\t", Test_96.high, Test_96.middle, Test_96.low, Divisor.high, Divisor.low); div_96_64 (&Test_96, &Divisor, &Quot_96, &Remain_64); printf(" %x %x %x + %x %x\n", Quot_96.high, Quot_96.middle, Quot_96.low, Remain_64.high, Remain_64.low); Reverse96_64(&Quot_96, &Remain_64, &Divisor); Test_96.high = 0x4b30c635; Test_96.middle = 0x1234fedc; Test_96.low = 0x00010000; Divisor.high = 0xb2f30101; Divisor.low = 0x00000001; printf("--> 96_64 bit test %x %x %x / %x %x|\t", Test_96.high, Test_96.middle, Test_96.low, Divisor.high, Divisor.low); div_96_64 (&Test_96, &Divisor, &Quot_96, &Remain_64); printf(" %x %x %x + %x %x\n", Quot_96.high, Quot_96.middle, Quot_96.low, Remain_64.high, Remain_64.low); Reverse96_64(&Quot_96, &Remain_64, &Divisor); Test_96.high = 0x3000000f; Test_96.middle = 0x00001111; Test_96.low = 0x00000000; Divisor.high = 0xe000000f; Divisor.low = 0x00000000; printf("--> 96_64 div %x %x %x / %x %x|\t", Test_96.high, Test_96.middle, Test_96.low, Divisor.high, Divisor.low); div_96_64 (&Test_96, &Divisor, &Quot_96, &Remain_64); printf(" %x %x %x + %x %x\n", Quot_96.high, Quot_96.middle, Quot_96.low, Remain_64.high, Remain_64.low); Reverse96_64(&Quot_96, &Remain_64, &Divisor); Test_128.high = 0x4b30c635; Test_128.middle_u = 0x1234fedc; Test_128.middle_l = 0x00010000; Test_128.low = 0x00000000; Divisor.high = 0xb2f30101; Divisor.low = 0x00000001; div_128_64 (&Test_128, &Divisor, &Quot_128, &Remain_64); printf("--> 128_64 div %x %x %x %x|\t", Test_128.high, Test_128.middle_u, Test_128.middle_l, Test_128.low); printf("%x %x %x %x + %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_64.high, Remain_64.low); Reverse128_64(&Quot_128, &Remain_64, &Divisor); /* 128:128 bits test */ Divisor_128.high = 0x054625ab; Divisor_128.middle_u = 0x1c5d6e8f; Divisor_128.middle_l = 0x98765432; Divisor_128.low = 0x05050505; printf("--> 128_128 div %x %x %x %x|\t", Test_128.high, Test_128.middle_u, Test_128.middle_l, Test_128.low); printf("/ %x %x %x %x\n", Divisor_128.high, Divisor_128.middle_u, Divisor_128.middle_l, Divisor_128.low); div_128_128 (&Test_128, &Divisor_128, &Quot_128, &Remain_128); printf("%x %x %x %x + %x %x %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_128.high, Remain_128.middle_u, Remain_128.middle_l, Remain_128.low); Back_128_128 (&Quot_128, &Remain_128, &Divisor_128); Test_128.high = 0xcb30c635; Test_128.middle_u = 0x1234fedc; Test_128.middle_l = 0x00010000; Test_128.low = 0x1a2b3c4d; Divisor_128.high = 0x054625ab; Divisor_128.middle_u = 0x1c5d6e8f; Divisor_128.middle_l = 0x98765432; Divisor_128.low = 0x50e060f0; printf("--> 128_128 div %x %x %x %x|\t", Test_128.high, Test_128.middle_u, Test_128.middle_l, Test_128.low); printf("/ %x %x %x %x\n", Divisor_128.high, Divisor_128.middle_u, Divisor_128.middle_l, Divisor_128.low); div_128_128 (&Test_128, &Divisor_128, &Quot_128, &Remain_128); printf("%x %x %x %x + %x %x %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_128.high, Remain_128.middle_u, Remain_128.middle_l, Remain_128.low); Back_128_128 (&Quot_128, &Remain_128, &Divisor_128); scanf("%c\r", &dummy); /* 128:96 bits test */ Test_128.high = 0x1468ace0; Test_128.middle_u = 0x98765432; Test_128.middle_l = 0x0abcdef1; Test_128.low = 0x7531fbd9; Test_96.high = 0x0; Test_96.middle = 0x6378fba1; Test_96.low = 0x4c5d209e; div_128_96 (&Test_128, &Test_96, &Quot_128, &Remain_96); printf("--> 128_96 div %x %x %x %x|\t", Test_128.high, Test_128.middle_u, Test_128.middle_l, Test_128.low); printf("%x %x %x %x + %x %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_96.high, Remain_96.middle, Remain_96.low); Back_128_96 (&Quot_128, &Remain_96, &Test_96); Test_64.high = 0x6378fba1; Test_64.low = 0x4c5d209e; div_128_64 (&Test_128, &Test_64, &Quot_128, &Remain_64); printf("--> 128_64 div %x %x %x %x|\t", Test_128.high, Test_128.middle_u, Test_128.middle_l, Test_128.low); printf("%x %x %x %x + %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_64.high, Remain_64.low); Reverse128_64(&Quot_128, &Remain_64, &Test_64); Divisor_128.high = 0x0; Divisor_128.middle_u = 0x0; Divisor_128.middle_l = 0x6378fba1; Divisor_128.low = 0x4c5d209e; div_128_128 (&Test_128, &Divisor_128, &Quot_128, &Remain_128); printf("--> 128_128 div %x %x %x %x|\t", Test_128.high, Test_128.middle_u, Test_128.middle_l, Test_128.low); printf("%x %x %x %x + %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_64.high, Remain_64.low); Back_128_128 (&Quot_128, &Remain_128, &Divisor_128); Test_128.high = 0x58765432; Test_128.middle_u = 0x1fedcba0; Test_128.middle_l = 0x2468ace0; Test_128.low = 0x13579bdf; Test_96.high = 0x68ace240; Test_96.middle = 0xfdb97531; Test_96.low = 0x3b4c9a1f; div_128_96 (&Test_128, &Test_96, &Quot_128, &Remain_96); printf("--> 128_96 div %x %x %x %x|\t", Test_128.high, Test_128.middle_u, Test_128.middle_l, Test_128.low); printf("%x %x %x %x + %x %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_96.high, Remain_96.middle, Remain_96.low); Back_128_96 (&Quot_128, &Remain_96, &Test_96); Divisor_128.high = 0x0; Divisor_128.middle_u = 0x68ace240; Divisor_128.middle_l = 0xfdb97531; Divisor_128.low = 0x3b4c9a1f; div_128_128 (&Test_128, &Divisor_128, &Quot_128, &Remain_128); printf("--> 128_128 div %x %x %x %x|\t", Test_128.high, Test_128.middle_u, Test_128.middle_l, Test_128.low); printf("%x %x %x %x + %x %x %x\n", Quot_128.high, Quot_128.middle_u, Quot_128.middle_l, Quot_128.low, Remain_128.middle_u, Remain_128.middle_l, Remain_128.low); Back_128_128 (&Quot_128, &Remain_128, &Divisor_128); return EXIT_SUCCESS; }