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

1.1       root        1: /*---------------------------------------------------------------------------+
                      2:  |  reg_compare.c                                                            |
                      3:  |                                                                           |
                      4:  | Compare two floating point registers                                      |
                      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:  | compare() is the core FPU_REG comparison function                         |
                     14:  +---------------------------------------------------------------------------*/
                     15: 
                     16: #include "fpu_system.h"
                     17: #include "exception.h"
                     18: #include "fpu_emu.h"
                     19: #include "status_w.h"
                     20: 
                     21: 
                     22: int emCompare(FPU_REG *b)
                     23: {
                     24:   int diff;
                     25: 
                     26:   if ( FPU_st0_ptr->tag | b->tag )
                     27:     {
                     28:       if ( FPU_st0_ptr->tag == TW_Zero )
                     29:        {
                     30:          if ( b->tag == TW_Zero ) return COMP_A_EQ_B;
                     31:          if ( b->tag == TW_Valid )
                     32:            {
                     33:              return (b->sign == SIGN_POS) ? COMP_A_LT_B : COMP_A_GT_B ;
                     34:            }
                     35:        }
                     36:       else if ( b->tag == TW_Zero )
                     37:        {
                     38:          if ( FPU_st0_ptr->tag == TW_Valid )
                     39:            {
                     40:              return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_GT_B : COMP_A_LT_B ;
                     41:            }
                     42:        }
                     43: 
                     44:       if ( FPU_st0_ptr->tag == TW_Infinity )
                     45:        {
                     46:          if ( (b->tag == TW_Valid) || (b->tag == TW_Zero) )
                     47:            {
                     48:              return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_GT_B : COMP_A_LT_B;
                     49:            }
                     50:          else if ( b->tag == TW_Infinity )
                     51:            {
                     52:              /* The 80486 book says that infinities can be equal! */
                     53:              return (FPU_st0_ptr->sign == b->sign) ? COMP_A_EQ_B :
                     54:                ((FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_GT_B : COMP_A_LT_B);
                     55:            }
                     56:          /* Fall through to the NaN code */
                     57:        }
                     58:       else if ( b->tag == TW_Infinity )
                     59:        {
                     60:          if ( (FPU_st0_ptr->tag == TW_Valid) || (FPU_st0_ptr->tag == TW_Zero) )
                     61:            {
                     62:              return (b->sign == SIGN_POS) ? COMP_A_LT_B : COMP_A_GT_B;
                     63:            }
                     64:          /* Fall through to the NaN code */
                     65:        }
                     66: 
                     67:       /* The only possibility now should be that one of the arguments
                     68:         is a NaN */
                     69:       if ( (FPU_st0_ptr->tag == TW_NaN) || (b->tag == TW_NaN) )
                     70:        {
                     71:          if ( ((FPU_st0_ptr->tag == TW_NaN) && !(FPU_st0_ptr->sigh & 0x40000000))
                     72:              || ((b->tag == TW_NaN) && !(b->sigh & 0x40000000)) )
                     73:            /* At least one arg is a signaling NaN */
                     74:            return COMP_NOCOMP | COMP_SNAN | COMP_NAN;
                     75:          else
                     76:            /* Neither is a signaling NaN */
                     77:            return COMP_NOCOMP | COMP_NAN;
                     78:        }
                     79:       
                     80:       EXCEPTION(EX_Invalid);
                     81:     }
                     82:   
                     83: #ifdef PARANOID
                     84:   if (!(FPU_st0_ptr->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
                     85:   if (!(b->sigh & 0x80000000)) EXCEPTION(EX_Invalid);
                     86: #endif PARANOID
                     87:   
                     88:   if (FPU_st0_ptr->sign != b->sign)
                     89:     return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_GT_B : COMP_A_LT_B;
                     90:   
                     91:   diff = FPU_st0_ptr->exp - b->exp;
                     92:   if ( diff == 0 )
                     93:     {
                     94:       diff = FPU_st0_ptr->sigh - b->sigh;
                     95:       if ( diff == 0 )
                     96:        diff = FPU_st0_ptr->sigl - b->sigl;
                     97:     }
                     98: 
                     99:   if ( diff > 0 )
                    100:     return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_GT_B : COMP_A_LT_B ;
                    101:   if ( diff < 0 )
                    102:     return (FPU_st0_ptr->sign == SIGN_POS) ? COMP_A_LT_B : COMP_A_GT_B ;
                    103:   return COMP_A_EQ_B;
                    104: 
                    105: }
                    106: 
                    107: 
                    108: void compare_st_data(void)
                    109: {
                    110:   int f;
                    111:   int c = emCompare(&FPU_loaded_data);
                    112: 
                    113:   if (c & COMP_NAN)
                    114:     {
                    115:       EXCEPTION(EX_Invalid);
                    116:       f = SW_C3 | SW_C2 | SW_C0;
                    117:     }
                    118:   else
                    119:     switch (c)
                    120:       {
                    121:       case COMP_A_LT_B:
                    122:        f = SW_C0;
                    123:        break;
                    124:       case COMP_A_EQ_B:
                    125:        f = SW_C3;
                    126:        break;
                    127:       case COMP_A_GT_B:
                    128:        f = 0;
                    129:        break;
                    130:       case COMP_NOCOMP:
                    131:        f = SW_C3 | SW_C2 | SW_C0;
                    132:        break;
                    133: #ifdef PARANOID
                    134:       default:
                    135:        EXCEPTION(EX_INTERNAL|0x121);
                    136:        f = SW_C3 | SW_C2 | SW_C0;
                    137:        break;
                    138: #endif PARANOID
                    139:       }
                    140:   setcc(f);
                    141: }
                    142: 
                    143: 
                    144: static void compare_st_st(int nr)
                    145: {
                    146:   int c = emCompare(&st(nr));
                    147:   int f;
                    148:   if (c & COMP_NAN)
                    149:     {
                    150:       EXCEPTION(EX_Invalid);
                    151:       f = SW_C3 | SW_C2 | SW_C0;
                    152:     }
                    153:   else
                    154:     switch (c)
                    155:       {
                    156:       case COMP_A_LT_B:
                    157:        f = SW_C0;
                    158:        break;
                    159:       case COMP_A_EQ_B:
                    160:        f = SW_C3;
                    161:        break;
                    162:       case COMP_A_GT_B:
                    163:        f = 0;
                    164:        break;
                    165:       case COMP_NOCOMP:
                    166:        f = SW_C3 | SW_C2 | SW_C0;
                    167:        break;
                    168: #ifdef PARANOID
                    169:       default:
                    170:        EXCEPTION(EX_INTERNAL|0x122);
                    171:        f = SW_C3 | SW_C2 | SW_C0;
                    172:        break;
                    173: #endif PARANOID
                    174:       }
                    175:   setcc(f);
                    176: }
                    177: 
                    178: 
                    179: static void compare_u_st_st(int nr)
                    180: {
                    181:   int f;
                    182:   int c = emCompare(&st(nr));
                    183:   if (c & COMP_NAN)
                    184:     {
                    185:       if (c & COMP_SNAN)       /* This is the only difference between
                    186:                                  un-ordered and ordinary comparisons */
                    187:        EXCEPTION(EX_Invalid);
                    188:       f = SW_C3 | SW_C2 | SW_C0;
                    189:     }
                    190:   else
                    191:     switch (c)
                    192:       {
                    193:       case COMP_A_LT_B:
                    194:        f = SW_C0;
                    195:        break;
                    196:       case COMP_A_EQ_B:
                    197:        f = SW_C3;
                    198:        break;
                    199:       case COMP_A_GT_B:
                    200:        f = 0;
                    201:        break;
                    202:       case COMP_NOCOMP:
                    203:        f = SW_C3 | SW_C2 | SW_C0;
                    204:        break;
                    205: #ifdef PARANOID
                    206:       default:
                    207:        EXCEPTION(EX_INTERNAL|0x123);
                    208:        f = SW_C3 | SW_C2 | SW_C0;
                    209:        break;
                    210: #endif PARANOID
                    211:       }
                    212:   setcc(f);
                    213: }
                    214: 
                    215: /*---------------------------------------------------------------------------*/
                    216: 
                    217: void fcom_st()
                    218: {
                    219:   /* fcom st(i) */
                    220:   compare_st_st(FPU_rm);
                    221: }
                    222: 
                    223: 
                    224: void fcompst()
                    225: {
                    226:   /* fcomp st(i) */
                    227:   compare_st_st(FPU_rm);
                    228:   pop();
                    229: }
                    230: 
                    231: 
                    232: void fcompp()
                    233: {
                    234:   /* fcompp */
                    235:   if (FPU_rm != 1)
                    236:     return Un_impl();
                    237:   compare_st_st(1);
                    238:   pop(); FPU_st0_ptr = &st(0);
                    239:   pop();
                    240: }
                    241: 
                    242: 
                    243: void fucom_()
                    244: {
                    245:   /* fucom st(i) */
                    246:   compare_u_st_st(FPU_rm);
                    247: }
                    248: 
                    249: 
                    250: void fucomp()
                    251: {
                    252:   /* fucomp st(i) */
                    253:   compare_u_st_st(FPU_rm);
                    254:   pop();
                    255: }
                    256: 
                    257: 
                    258: void fucompp()
                    259: {
                    260:   /* fucompp */
                    261:   if (FPU_rm == 1)
                    262:     {
                    263:       compare_u_st_st(1);
                    264:       pop(); FPU_st0_ptr = &st(0);
                    265:       pop();
                    266:     }
                    267:   else
                    268:     Un_impl();
                    269: }

unix.superglobalmegacorp.com

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