Annotation of hatari/src/cpu/softfloat/softfloat_decimal.c, revision 1.1.1.1

1.1       root        1: /*============================================================================
                      2: 
                      3: This C source file is an extension to the SoftFloat IEC/IEEE Floating-point 
                      4: Arithmetic Package, Release 2a.
                      5: 
                      6: =============================================================================*/
                      7: 
                      8: #include <stdint.h>
                      9: 
                     10: #include "sysconfig.h"
                     11: #include "sysdeps.h"
                     12: 
                     13: #define DECIMAL_LOG 0
                     14: 
                     15: #if DECIMAL_LOG
                     16: #define decimal_log write_log
                     17: #else
                     18: #define decimal_log(fmt, ...)
                     19: #endif
                     20: 
                     21: #include "softfloat.h"
                     22: #include "softfloat-macros.h"
                     23: #include "softfloat/softfloat-specialize.h"
                     24: 
                     25: /*----------------------------------------------------------------------------
                     26: | Methods for converting decimal floats to binary extended precision floats.
                     27: *----------------------------------------------------------------------------*/
                     28: 
                     29: static void round128to64(flag aSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, float_status *status)
                     30: {
                     31:        flag increment;
                     32:        int32_t zExp;
                     33:        uint64_t zSig0, zSig1;
                     34:        
                     35:        zExp = *aExp;
                     36:        zSig0 = *aSig0;
                     37:        zSig1 = *aSig1;
                     38:        
                     39:        increment = ( (int64_t) zSig1 < 0 );
                     40:        if (status->float_rounding_mode != float_round_nearest_even) {
                     41:                if (status->float_rounding_mode == float_round_to_zero) {
                     42:                        increment = 0;
                     43:                } else {
                     44:                        if (aSign) {
                     45:                                increment = (status->float_rounding_mode == float_round_down) && zSig1;
                     46:                        } else {
                     47:                                increment = (status->float_rounding_mode == float_round_up) && zSig1;
                     48:                        }
                     49:                }
                     50:        }
                     51:        
                     52:        if (increment) {
                     53:                ++zSig0;
                     54:                if (zSig0 == 0) {
                     55:                        ++zExp;
                     56:                        zSig0 = LIT64(0x8000000000000000);
                     57:                } else {
                     58:                        zSig0 &= ~ (((uint64_t) (zSig1<<1) == 0) & (status->float_rounding_mode == float_round_nearest_even));
                     59:                }
                     60:        } else {
                     61:                if ( zSig0 == 0 ) zExp = 0;
                     62:        }
                     63:        
                     64:        *aExp = zExp;
                     65:        *aSig0 = zSig0;
                     66:        *aSig1 = 0;
                     67: }
                     68: 
                     69: static void mul128by128round(int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, int32_t bExp, uint64_t bSig0, uint64_t bSig1, float_status *status)
                     70: {
                     71:        int32_t zExp;
                     72:        uint64_t zSig0, zSig1, zSig2, zSig3;
                     73:        
                     74:        zExp = *aExp;
                     75:        zSig0 = *aSig0;
                     76:        zSig1 = *aSig1;
                     77:        
                     78:        round128to64(0, &bExp, &bSig0, &bSig1, status);
                     79:        
                     80:        zExp += bExp - 0x3FFE;
                     81:        mul128To256(zSig0, zSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3);
                     82:        zSig1 |= (zSig2 | zSig3) != 0;
                     83:        if ( 0 < (int64_t) zSig0 ) {
                     84:                shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
                     85:                --zExp;
                     86:        }
                     87:        *aExp = zExp;
                     88:        *aSig0 = zSig0;
                     89:        *aSig1 = zSig1;
                     90:        
                     91:        round128to64(0, aExp, aSig0, aSig1, status);
                     92: }
                     93: 
                     94: static void mul128by128(int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, int32_t bExp, uint64_t bSig0, uint64_t bSig1)
                     95: {
                     96:        int32_t zExp;
                     97:        uint64_t zSig0, zSig1, zSig2, zSig3;
                     98:        
                     99:        zExp = *aExp;
                    100:        zSig0 = *aSig0;
                    101:        zSig1 = *aSig1;
                    102: 
                    103:        zExp += bExp - 0x3FFE;
                    104:        mul128To256(zSig0, zSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3);
                    105:        zSig1 |= (zSig2 | zSig3) != 0;
                    106:        if ( 0 < (int64_t) zSig0 ) {
                    107:                shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
                    108:                --zExp;
                    109:        }
                    110:        *aExp = zExp;
                    111:        *aSig0 = zSig0;
                    112:        *aSig1 = zSig1;
                    113: }
                    114: 
                    115: static void div128by128(int32_t *paExp, uint64_t *paSig0, uint64_t *paSig1, int32_t bExp, uint64_t bSig0, uint64_t bSig1)
                    116: {
                    117:        int32_t zExp, aExp;
                    118:        uint64_t zSig0, zSig1, aSig0, aSig1;
                    119:        uint64_t rem0, rem1, rem2, rem3, term0, term1, term2, term3;
                    120:        
                    121:        aExp = *paExp;
                    122:        aSig0 = *paSig0;
                    123:        aSig1 = *paSig1;
                    124:        
                    125:        zExp = aExp - bExp + 0x3FFE;
                    126:        if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) {
                    127:                shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 );
                    128:                ++zExp;
                    129:        }
                    130:        zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 );
                    131:        mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 );
                    132:        sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 );
                    133:        while ( (int64_t) rem0 < 0 ) {
                    134:                --zSig0;
                    135:                add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 );
                    136:        }
                    137:        zSig1 = estimateDiv128To64( rem1, rem2, bSig0 );
                    138:        if ( ( zSig1 & 0x3FFF ) <= 4 ) {
                    139:                mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 );
                    140:                sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 );
                    141:                while ( (int64_t) rem1 < 0 ) {
                    142:                        --zSig1;
                    143:                        add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 );
                    144:                }
                    145:                zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
                    146:        }
                    147: 
                    148:        *paExp = zExp;
                    149:        *paSig0 = zSig0;
                    150:        *paSig1 = zSig1;
                    151: }
                    152: 
                    153: #if 0
                    154: 
                    155: void tentoint128(flag mSign, flag eSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, int32_t scale, float_status *status)
                    156: {
                    157:     int32_t mExp;
                    158:     uint64_t mSig0, mSig1;
                    159: 
                    160:     
                    161:     *aExp = 0x3FFF;
                    162:     *aSig0 = LIT64(0x8000000000000000);
                    163:     *aSig1 = 0;
                    164: 
                    165:     mExp = 0x4002;
                    166:     mSig0 = LIT64(0xA000000000000000);
                    167:     mSig1 = 0;
                    168: 
                    169:     
                    170:     while (scale) {
                    171:         if (scale & 1) {
                    172:             mul128by128round(aExp, aSig0, aSig1, mExp, mSig0, mSig1, status);
                    173:         }
                    174:         mul128by128(&mExp, &mSig0, &mSig1, mExp, mSig0, mSig1);
                    175:         scale >>= 1;
                    176:     }
                    177: }
                    178: 
                    179: #else
                    180: 
                    181: static void tentoint128(flag mSign, flag eSign, int32_t *aExp, uint64_t *aSig0, uint64_t *aSig1, int32_t scale, float_status *status)
                    182:  {
                    183:     int8_t save_rounding_mode;
                    184:     int32_t mExp;
                    185:     uint64_t mSig0, mSig1;
                    186:      
                    187:     save_rounding_mode = status->float_rounding_mode;
                    188:     switch (status->float_rounding_mode) {
                    189:         case float_round_nearest_even:
                    190:             break;
                    191:         case float_round_down:
                    192:             if (mSign != eSign) {
                    193:                 set_float_rounding_mode(float_round_up, status);
                    194:             }
                    195:             break;
                    196:         case float_round_up:
                    197:             if (mSign != eSign) {
                    198:                 set_float_rounding_mode(float_round_down, status);
                    199:             }
                    200:             break;
                    201:         case float_round_to_zero:
                    202:             if (eSign == 0) {
                    203:                 set_float_rounding_mode(float_round_down, status);
                    204:             } else {
                    205:                 set_float_rounding_mode(float_round_up, status);
                    206:             }
                    207:             break;
                    208:         default:
                    209:             break;
                    210:     }  
                    211: 
                    212:        *aExp = 0x3FFF;
                    213:        *aSig0 = LIT64(0x8000000000000000);
                    214:        *aSig1 = 0;
                    215: 
                    216:        mExp = 0x4002;
                    217:        mSig0 = LIT64(0xA000000000000000);
                    218:        mSig1 = 0;
                    219:        
                    220:        while (scale) {
                    221:                if (scale & 1) {
                    222:                        mul128by128round(aExp, aSig0, aSig1, mExp, mSig0, mSig1, status);
                    223:                }
                    224:                mul128by128(&mExp, &mSig0, &mSig1, mExp, mSig0, mSig1);
                    225:                scale >>= 1;
                    226:        }
                    227: 
                    228:        set_float_rounding_mode(save_rounding_mode, status);
                    229: }
                    230: 
                    231: #endif
                    232: 
                    233: static int64_t tentointdec(int32_t scale)
                    234: {
                    235:        uint64_t decM, decX;
                    236:         
                    237:        decX = 1;
                    238:        decM = 10;
                    239:         
                    240:        while (scale) {
                    241:                if (scale & 1) {
                    242:                        decX *= decM;
                    243:                }
                    244:                decM *= decM;
                    245:                scale >>= 1;
                    246:         }
                    247:        
                    248:        return decX;
                    249: }
                    250: 
                    251: 
                    252: static int64_t float128toint64(flag zSign, int32_t zExp, uint64_t zSig0, uint64_t zSig1, float_status *status)
                    253: {
                    254:        int8_t roundingMode;
                    255:        flag roundNearestEven, increment;
                    256:        int64_t z;
                    257:        
                    258:        shift128RightJamming(zSig0, zSig1, 0x403E - zExp, &zSig0, &zSig1);
                    259: 
                    260:        roundingMode = status->float_rounding_mode;
                    261:        roundNearestEven = (roundingMode == float_round_nearest_even);
                    262:        increment = ((int64_t)zSig1 < 0);
                    263:        if (!roundNearestEven) {
                    264:                if (roundingMode == float_round_to_zero) {
                    265:                        increment = 0;
                    266:                } else {
                    267:                        if (zSign) {
                    268:                                increment = (roundingMode == float_round_down ) && zSig1;
                    269:                        } else {
                    270:                                increment = (roundingMode == float_round_up ) && zSig1;
                    271:                        }
                    272:                }
                    273:        }
                    274:        if (increment) {
                    275:                ++zSig0;
                    276:                zSig0 &= ~ (((uint64_t)(zSig1<<1) == 0) & roundNearestEven);
                    277:        }
                    278:        z = zSig0;
                    279:        if (zSig1) float_raise(float_flag_inexact, status);
                    280:        return z;
                    281: }
                    282: 
                    283: static int32_t getDecimalExponent(int32_t aExp, uint64_t aSig)
                    284: {
                    285:        flag zSign;
                    286:        int32_t zExp, shiftCount;
                    287:        uint64_t zSig0, zSig1;
                    288:        
                    289:        if (aSig == 0 || aExp == 0x3FFF) {
                    290:                return 0;
                    291:        }
                    292:        if (aExp < 0) {
                    293:                return -4932;
                    294:        }
                    295: 
                    296:        aSig ^= LIT64(0x8000000000000000);
                    297:        aExp -= 0x3FFF;
                    298:        zSign = (aExp < 0);
                    299:        aExp = zSign ? -aExp : aExp;
                    300:        shiftCount = 31 - countLeadingZeros32(aExp);
                    301:        zExp = 0x3FFF + shiftCount;
                    302:        
                    303:        if (shiftCount < 0) {
                    304:                shortShift128Left(aSig, 0, -shiftCount, &zSig0, &zSig1);
                    305:        } else {
                    306:                shift128Right(aSig, 0, shiftCount, &zSig0, &zSig1);
                    307:                aSig = (uint64_t)aExp << (63 - shiftCount);
                    308:                if (zSign) {
                    309:                        sub128(aSig, 0, zSig0, zSig1, &zSig0, &zSig1);
                    310:                } else {
                    311:                        add128(aSig, 0, zSig0, zSig1, &zSig0, &zSig1);
                    312:                }
                    313:        }
                    314:        
                    315:        shiftCount = countLeadingZeros64(zSig0);
                    316:        shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1);
                    317:        zExp -= shiftCount;
                    318:        mul128by128(&zExp, &zSig0, &zSig1, 0x3FFD, LIT64(0x9A209A84FBCFF798), LIT64(0x8F8959AC0B7C9178));
                    319:        
                    320:        shiftCount = 0x403E - zExp;
                    321:        shift128RightJamming(zSig0, zSig1, shiftCount, &zSig0, &zSig1);
                    322: 
                    323:        if ((int64_t)zSig1 < 0) {
                    324:                ++zSig0;
                    325:                zSig0 &= ~(((int64_t)(zSig1<<1) == 0) & 1);
                    326:        }
                    327:        
                    328:        zExp = zSign ? -zSig0 : zSig0;
                    329: 
                    330:        return zExp;
                    331: }
                    332: 
                    333: /*----------------------------------------------------------------------------
                    334: | Decimal to binary
                    335: *----------------------------------------------------------------------------*/
                    336: 
                    337: floatx80 floatdecimal_to_floatx80(floatx80 a, float_status *status)
                    338: {
                    339:        flag decSign, zSign, decExpSign;
                    340:        int32_t decExp, zExp, xExp, shiftCount;
                    341:        uint64_t decSig, zSig0, zSig1, xSig0, xSig1;
                    342:        
                    343:        decSign = extractFloatx80Sign(a);
                    344:        decExp = extractFloatx80Exp(a);
                    345:        decSig = extractFloatx80Frac(a);
                    346:        
                    347:        if (decExp == 0x7FFF) return a;
                    348:        
                    349:        if (decExp == 0 && decSig == 0) return a;
                    350:        
                    351:        decExpSign = (decExp >> 14) & 1;
                    352:        decExp &= 0x3FFF;
                    353:        
                    354:        shiftCount = countLeadingZeros64( decSig );
                    355:        zExp = 0x403E - shiftCount;
                    356:        zSig0 = decSig << shiftCount;
                    357:        zSig1 = 0;
                    358:        zSign = decSign;
                    359:        
                    360:        tentoint128(decSign, decExpSign, &xExp, &xSig0, &xSig1, decExp, status);
                    361: 
                    362:        if (decExpSign) {
                    363:                div128by128(&zExp, &zSig0, &zSig1, xExp, xSig0, xSig1);
                    364:        } else {
                    365:                mul128by128(&zExp, &zSig0, &zSig1, xExp, xSig0, xSig1);
                    366:        }
                    367:        
                    368:        if (zSig1) float_raise(float_flag_decimal, status);
                    369:        round128to64(zSign, &zExp, &zSig0, &zSig1, status);
                    370:        
                    371:        return packFloatx80( zSign, zExp, zSig0 );
                    372:        
                    373: }
                    374: 
                    375: /*----------------------------------------------------------------------------
                    376:  | Binary to decimal
                    377:  *----------------------------------------------------------------------------*/
                    378: 
                    379: floatx80 floatx80_to_floatdecimal(floatx80 a, int32_t *k, float_status *status)
                    380: {
                    381:        flag aSign, decSign;
                    382:        int32_t aExp, decExp, zExp, xExp;
                    383:        uint64_t aSig, decSig, decX, zSig0, zSig1, xSig0, xSig1;
                    384:        flag ictr, lambda;
                    385:        int32_t kfactor, ilog, iscale, len;
                    386:        
                    387:        aSign = extractFloatx80Sign(a);
                    388:        aExp = extractFloatx80Exp(a);
                    389:        aSig = extractFloatx80Frac(a);
                    390:        
                    391:        if (aExp == 0x7FFF) {
                    392:                if ((uint64_t) (aSig<<1)) return propagateFloatx80NaNOneArg(a, status);
                    393:                return a;
                    394:        }
                    395:        
                    396:        if (aExp == 0) {
                    397:                if (aSig == 0) return packFloatx80(aSign, 0, 0);
                    398:                normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
                    399:        }
                    400: 
                    401:        kfactor = *k;
                    402: 
                    403:        ilog = getDecimalExponent(aExp, aSig);
                    404:        
                    405:        ictr = 0;
                    406: 
                    407: try_again:
                    408:        decimal_log(_T("ILOG = %i\n"), ilog);
                    409:        
                    410:        if (kfactor > 0) {
                    411:                if (kfactor > 17) {
                    412:                        kfactor = 17;
                    413:                        float_raise(float_flag_invalid, status);
                    414:                }
                    415:                len = kfactor;
                    416:        } else {
                    417:                len = ilog + 1 - kfactor;
                    418:                if (len > 17) {
                    419:                        len = 17;
                    420:                }
                    421:                if (len < 1) {
                    422:                        len = 1;
                    423:                }
                    424:                if (kfactor > ilog) {
                    425:                        ilog = kfactor;
                    426:                        decimal_log(_T("ILOG is kfactor = %i\n"), ilog);
                    427:                }
                    428:        }
                    429:        
                    430:        decimal_log(_T("LEN = %i\n"),len);
                    431:        
                    432:        lambda = 0;
                    433:        iscale = ilog + 1 - len;
                    434: 
                    435:        if (iscale < 0) {
                    436:                lambda = 1;
                    437:                iscale = -iscale;
                    438:        }
                    439:        
                    440:        decimal_log(_T("ISCALE = %i, LAMBDA = %i\n"),iscale, lambda);
                    441:        
                    442:        tentoint128(lambda, 0, &xExp, &xSig0, &xSig1, iscale, status);
                    443: 
                    444:        decimal_log(_T("AFTER tentoint128: zExp = %04x, zSig0 = %16llx, zSig1 = %16llx\n"), xExp, xSig0, xSig1);
                    445: 
                    446:        zExp = aExp;
                    447:        zSig0 = aSig;
                    448:        zSig1 = 0;
                    449:        
                    450:        if (lambda) {
                    451:                mul128by128(&zExp, &zSig0, &zSig1, xExp, xSig0, xSig1);
                    452:        } else {
                    453:                div128by128(&zExp, &zSig0, &zSig1, xExp, xSig0, xSig1);
                    454:        }
                    455: 
                    456:        decimal_log(_T("BEFORE: zExp = %04x, zSig0 = %16llx, zSig1 = %16llx\n"),zExp,zSig0,zSig1);
                    457: 
                    458:        decSig = float128toint64(aSign, zExp, zSig0, zSig1, status);
                    459: 
                    460:        decimal_log(_T("AFTER: decSig = %llu\n"),decSig);
                    461: 
                    462:        if (ictr == 0) {
                    463: 
                    464:                decX = tentointdec(len - 1);
                    465: 
                    466:                if (decSig < decX) { // z < x
                    467:                        ilog -= 1;
                    468:                        ictr = 1;
                    469:                        goto try_again;
                    470:                }
                    471:                
                    472:                decX *= 10;
                    473:                
                    474:                if (decSig > decX) { // z > x
                    475:                        ilog += 1;
                    476:                        ictr = 1;
                    477:                        goto try_again;
                    478:                }
                    479:        }
                    480:        
                    481:        decSign = aSign;
                    482:        decExp = (ilog < 0) ? -ilog : ilog;
                    483:        if (decExp > 999) {
                    484:                float_raise(float_flag_invalid, status);
                    485:        }
                    486:        if (ilog < 0) decExp |= 0x4000;
                    487:        
                    488:        *k = len;
                    489:        
                    490:        return packFloatx80(decSign, decExp, decSig);
                    491: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.