Annotation of coherent/b/kernel/emulator/reg_add_sub.c, revision 1.1.1.1

1.1       root        1: /*---------------------------------------------------------------------------+
                      2:  |  reg_add_sub.c                                                            |
                      3:  |                                                                           |
                      4:  | Functions to add or subtract two registers and put the result in a third. |
                      5:  |                                                                           |
                      6:  | Copyright (C) 1992    W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
                      7:  |                       Australia.  E-mail [email protected]    |
                      8:  |                                                                           |
                      9:  |                                                                           |
                     10:  +---------------------------------------------------------------------------*/
                     11: 
                     12: /*---------------------------------------------------------------------------+
                     13:  | For each function, the destination may be any FPU_REG, including one of   |
                     14:  | the source FPU_REGs.                                                      |
                     15:  +---------------------------------------------------------------------------*/
                     16: 
                     17: #include "fpu_system.h"
                     18: #include "exception.h"
                     19: #include "reg_constant.h"
                     20: #include "fpu_emu.h"
                     21: 
                     22: 
                     23: 
                     24: void reg_add(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
                     25: {
                     26:   int diff;
                     27:   
                     28:   if ( !(a->tag | b->tag) )
                     29:     {
                     30:       /* Both registers are valid */
                     31:       if (!(a->sign ^ b->sign))
                     32:        {
                     33:          /* signs are the same */
                     34:          reg_u_add(a, b, dest);
                     35:          dest->sign = a->sign;
                     36:          return;
                     37:        }
                     38:       
                     39:       /* The signs are different, so do a subtraction */
                     40:       diff = a->exp - b->exp;
                     41:       if (!diff)
                     42:        {
                     43:          diff = a->sigh - b->sigh;  /* Works only if ms bits are identical */
                     44:          if (!diff)
                     45:            diff = a->sigl > b->sigl;
                     46:        }
                     47:       
                     48:       if (diff > 0)
                     49:        {
                     50:          reg_u_sub(a, b, dest);
                     51:          dest->sign = a->sign;
                     52:          return;
                     53:        }
                     54:       else
                     55:        {
                     56:          reg_u_sub(b, a, dest);
                     57:          dest->sign = b->sign;
                     58:          return;
                     59:        }
                     60:     }
                     61:   else
                     62:     {
                     63:       if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) )
                     64:        { real_2op_NaN(a, b, dest); return; }
                     65:       else if (a->tag == TW_Zero)
                     66:        { reg_move(b, dest); return; }
                     67:       else if (b->tag == TW_Zero)
                     68:        { reg_move(a, dest); return; }
                     69:       else if (a->tag == TW_Infinity)
                     70:        {
                     71:          if (b->tag != TW_Infinity)
                     72:            { reg_move(a, dest); return; }
                     73:          /* They are both + or - infinity */
                     74:          if (a->sign == b->sign)
                     75:            { reg_move(a, dest); return; }
                     76:          reg_move(&CONST_QNaN, dest);  /* inf - inf is undefined. */
                     77:          return;
                     78:        }
                     79:       else if (b->tag == TW_Infinity)
                     80:        { reg_move(b, dest); return; }
                     81:     }
                     82: #ifdef PARANOID
                     83:   EXCEPTION(EX_INTERNAL|0x101);
                     84: #endif
                     85: }
                     86: 
                     87: 
                     88: /* Subtract b from a.  (a-b) -> dest */
                     89: void reg_sub(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
                     90: {
                     91:   int diff;
                     92: 
                     93:   if ( !(a->tag | b->tag) )
                     94:     {
                     95:       /* Both registers are valid */
                     96:       diff = a->exp - b->exp;
                     97:       if (!diff)
                     98:        {
                     99:          diff = a->sigh - b->sigh;  /* Works only if ms bits are identical */
                    100:          if (!diff)
                    101:            diff = a->sigl > b->sigl;
                    102:        }
                    103:       
                    104:       switch (a->sign*2 + b->sign)
                    105:        {
                    106:        case 0: /* P - P */
                    107:        case 3: /* N - N */
                    108:          if (diff > 0)
                    109:            {
                    110:              reg_u_sub(a, b, dest);
                    111:              dest->sign = a->sign;
                    112:            }
                    113:          else
                    114:            {
                    115:              reg_u_sub(b, a, dest);
                    116:              dest->sign = a->sign ^ SIGN_POS^SIGN_NEG;
                    117:            }
                    118:          return;
                    119:        case 1: /* P - N */
                    120:          reg_u_add(a, b, dest);
                    121:          dest->sign = SIGN_POS;
                    122:          return;
                    123:        case 2: /* N - P */
                    124:          reg_u_add(a, b, dest);
                    125:          dest->sign = SIGN_NEG;
                    126:          return;
                    127:        }
                    128:     }
                    129:   else
                    130:     {
                    131:       if ( (a->tag == TW_NaN) || (b->tag == TW_NaN) )
                    132:        { real_2op_NaN(a, b, dest); return; }
                    133:       else if (b->tag == TW_Zero)
                    134:        { reg_move(a, dest); return; }
                    135:       else if (a->tag == TW_Zero)
                    136:        {
                    137:          reg_move(b, dest);
                    138:          dest->sign ^= SIGN_POS^SIGN_NEG;
                    139:          return;
                    140:        }
                    141:       else if (a->tag == TW_Infinity)
                    142:        {
                    143:          if (b->tag != TW_Infinity)
                    144:            { reg_move(a, dest); return; }
                    145:          if (a->sign == b->sign)
                    146:            { reg_move(&CONST_QNaN, dest); return; }
                    147:          reg_move(a, dest);
                    148:          return;
                    149:        }
                    150:       else if (b->tag == TW_Infinity)
                    151:        {
                    152:          reg_move(b, dest);
                    153:          dest->sign ^= SIGN_POS^SIGN_NEG;
                    154:          return;
                    155:        }
                    156:     }
                    157: #ifdef PARANOID
                    158:   EXCEPTION(EX_INTERNAL|0x110);
                    159: #endif
                    160: }
                    161: 

unix.superglobalmegacorp.com

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