1*5803Srrh /* 2*5803Srrh * Copyright (c) 1982 Regents of the University of California 3*5803Srrh */ 4*5803Srrh #ifndef lint 5*5803Srrh static char sccsid[] = "@(#)bignum2.c 4.1 02/14/82"; 6*5803Srrh #endif not lint 7*5803Srrh 8*5803Srrh #include <stdio.h> 9*5803Srrh #include "as.h" 10*5803Srrh Bignum Znumber; /* zero reference */ 11*5803Srrh #define MINEXP -32768 /* never generate; reserved for id 0 */ 12*5803Srrh 13*5803Srrh Bignum intconvert(number, convto) 14*5803Srrh Bignum number; 15*5803Srrh int convto; 16*5803Srrh { 17*5803Srrh reg int i; 18*5803Srrh if (number.num_tag == convto) 19*5803Srrh return(number); 20*5803Srrh if (ty_nbyte[number.num_tag] > ty_nbyte[convto] && (passno == 2)){ 21*5803Srrh yywarning("Conversion between %s and %s looses significance", 22*5803Srrh ty_string[number.num_tag], 23*5803Srrh ty_string[convto]); 24*5803Srrh } 25*5803Srrh for (i = ty_nbyte[convto]; i < ty_nbyte[TYPO]; i++) 26*5803Srrh number.num_uchar[i] = 0; 27*5803Srrh return(number); 28*5803Srrh } 29*5803Srrh 30*5803Srrh #define CONV(src, dst) (((src) << TYPLG) + (dst)) 31*5803Srrh 32*5803Srrh Bignum floatconvert(number, convto) 33*5803Srrh Bignum number; 34*5803Srrh int convto; 35*5803Srrh { 36*5803Srrh reg u_int *bp; /* r11 */ 37*5803Srrh int loss = 0; 38*5803Srrh int gain = 0; 39*5803Srrh int mixs = 0; 40*5803Srrh Ovf ovf; 41*5803Srrh 42*5803Srrh if (number.num_tag == convto) 43*5803Srrh return(number); 44*5803Srrh bp = &number.num_uint[0]; 45*5803Srrh #ifdef lint 46*5803Srrh *bp = *bp; 47*5803Srrh #endif lint 48*5803Srrh 49*5803Srrh switch(CONV(number.num_tag, convto)){ 50*5803Srrh 51*5803Srrh case CONV(TYPF, TYPD): asm("cvtfd (r11), (r11)"); break; 52*5803Srrh case CONV(TYPF, TYPG): mixs++; break; 53*5803Srrh case CONV(TYPF, TYPH): mixs++; break; 54*5803Srrh 55*5803Srrh case CONV(TYPD, TYPF): asm("cvtdf (r11), (r11)"); break; 56*5803Srrh case CONV(TYPD, TYPG): mixs++; break; 57*5803Srrh case CONV(TYPD, TYPH): mixs++; break; 58*5803Srrh 59*5803Srrh case CONV(TYPG, TYPF): mixs++; break; 60*5803Srrh case CONV(TYPG, TYPD): mixs++; break; 61*5803Srrh case CONV(TYPG, TYPH): mixs++; break; 62*5803Srrh 63*5803Srrh case CONV(TYPH, TYPF): mixs++; break; 64*5803Srrh case CONV(TYPH, TYPD): mixs++; break; 65*5803Srrh case CONV(TYPH, TYPG): mixs++; break; 66*5803Srrh default: panic("Bad floating point conversion?"); 67*5803Srrh } 68*5803Srrh if ((gain || mixs || loss) && (passno == 2)){ 69*5803Srrh yywarning("Converting from %s to %s: %s ", 70*5803Srrh ty_string[number.num_tag], 71*5803Srrh ty_string[convto], 72*5803Srrh gain ? "gains significance" : 73*5803Srrh (loss ? "looses significance" : "mixs exponent formats") 74*5803Srrh ); 75*5803Srrh } 76*5803Srrh if (mixs){ 77*5803Srrh number = bignumconvert(number, convto, &ovf); 78*5803Srrh if (ovf && passno == 2){ 79*5803Srrh yywarning("Floating conversion over/underflowed\n"); 80*5803Srrh } 81*5803Srrh } else { 82*5803Srrh number.num_tag = convto; 83*5803Srrh } 84*5803Srrh return(number); 85*5803Srrh } 86*5803Srrh 87*5803Srrh /* 88*5803Srrh * Convert a big number between various representations 89*5803Srrh */ 90*5803Srrh Bignum bignumconvert(number, toconv, ovfp) 91*5803Srrh Bignum number; 92*5803Srrh int toconv; 93*5803Srrh Ovf *ovfp; 94*5803Srrh { 95*5803Srrh int tag; 96*5803Srrh 97*5803Srrh *ovfp = 0; 98*5803Srrh tag = number.num_tag; 99*5803Srrh if (tag == toconv) 100*5803Srrh return(number); 101*5803Srrh if (tag == TYPUNPACKED){ 102*5803Srrh return(bignumpack(number, toconv, ovfp)); 103*5803Srrh } 104*5803Srrh if (toconv == TYPUNPACKED){ 105*5803Srrh return(bignumunpack(number, ovfp)); 106*5803Srrh } 107*5803Srrh return(bignumpack(bignumunpack(number, ovfp), toconv, ovfp)); 108*5803Srrh } 109*5803Srrh 110*5803Srrh Bignum bignumunpack(Packed, ovfp) 111*5803Srrh Bignum Packed; 112*5803Srrh Ovf *ovfp; 113*5803Srrh { 114*5803Srrh Bignum Mantissa; 115*5803Srrh Bignum Enumber; 116*5803Srrh reg int i; 117*5803Srrh int j; 118*5803Srrh int k; 119*5803Srrh reg struct ty_bigdesc *p; 120*5803Srrh reg chptr packed; 121*5803Srrh reg chptr mantissa; 122*5803Srrh reg chptr enumber; 123*5803Srrh u_short exponent; 124*5803Srrh int sign; 125*5803Srrh int mask; 126*5803Srrh 127*5803Srrh p = &ty_bigdesc[Packed.num_tag]; 128*5803Srrh 129*5803Srrh *ovfp = 0; 130*5803Srrh Mantissa = Znumber; 131*5803Srrh sign = 0; 132*5803Srrh exponent = 0; 133*5803Srrh mantissa = CH_FIELD(Mantissa); 134*5803Srrh enumber = CH_FIELD(Enumber); 135*5803Srrh packed = CH_FIELD(Packed); 136*5803Srrh 137*5803Srrh if (isclear(packed)){ 138*5803Srrh Mantissa.num_tag = TYPUNPACKED; 139*5803Srrh Mantissa.num_exponent = MINEXP; 140*5803Srrh return(Mantissa); 141*5803Srrh } 142*5803Srrh /* 143*5803Srrh * map the packed number into the mantissa, using 144*5803Srrh * the unpacking map 145*5803Srrh */ 146*5803Srrh mapnumber(mantissa, packed, 16, p->b_upmmap); 147*5803Srrh /* 148*5803Srrh * perform the mantissa shifting. 149*5803Srrh * This may appear to overflow; all that is lost 150*5803Srrh * is low order bits of the exponent. 151*5803Srrh */ 152*5803Srrh (void)numshift(p->b_mlshift, mantissa, mantissa); 153*5803Srrh /* 154*5803Srrh * handle sign and exponent 155*5803Srrh */ 156*5803Srrh switch(Packed.num_tag){ 157*5803Srrh case TYPB: 158*5803Srrh case TYPW: 159*5803Srrh case TYPL: 160*5803Srrh case TYPO: 161*5803Srrh case TYPQ: 162*5803Srrh sign = 0; 163*5803Srrh exponent = p->b_eexcess; 164*5803Srrh if (mantissa[HOC] & SIGNBIT){ 165*5803Srrh sign = -1; 166*5803Srrh *ovfp |= numnegate(mantissa, mantissa); 167*5803Srrh } 168*5803Srrh /* 169*5803Srrh * Normalize the packed by left shifting, 170*5803Srrh * adjusting the exponent as we go. 171*5803Srrh * Do a binary weighted left shift for some speed. 172*5803Srrh */ 173*5803Srrh k = 0; 174*5803Srrh for (j = 4; j >= 0; --j){ 175*5803Srrh i = 1 << j; /* 16, 8, 4, 2, 1 */ 176*5803Srrh while(1){ 177*5803Srrh if (k >= p->b_msigbits) 178*5803Srrh break; 179*5803Srrh mask = ONES(i) << (CH_BITS - i); 180*5803Srrh if (mantissa[HOC] & mask) 181*5803Srrh break; 182*5803Srrh (void)numshift(i, mantissa, mantissa); 183*5803Srrh k += i; 184*5803Srrh exponent -= i; 185*5803Srrh } 186*5803Srrh } 187*5803Srrh assert(mantissa[HOC] & SIGNBIT, "integer <<ing"); 188*5803Srrh /* 189*5803Srrh * now, kick the most significant bit off the top 190*5803Srrh */ 191*5803Srrh (void)numshift(1, mantissa, mantissa); 192*5803Srrh break; 193*5803Srrh default: 194*5803Srrh /* 195*5803Srrh * map the exponent into the local area. 196*5803Srrh */ 197*5803Srrh Enumber = Znumber; 198*5803Srrh mapnumber(enumber, packed, 2, p->b_upemap); 199*5803Srrh /* 200*5803Srrh * Extract the exponent, and get rid 201*5803Srrh * of the sign bit 202*5803Srrh */ 203*5803Srrh exponent = Enumber.num_ushort[0] & ONES(15); 204*5803Srrh /* 205*5803Srrh * shift the exponent, and get rid of high order 206*5803Srrh * trash 207*5803Srrh */ 208*5803Srrh exponent >>= p->b_ershift; 209*5803Srrh exponent &= ONES(p->b_esigbits); 210*5803Srrh /* 211*5803Srrh * un excess the exponent 212*5803Srrh */ 213*5803Srrh exponent -= p->b_eexcess; 214*5803Srrh /* 215*5803Srrh * extract and extend the sign bit 216*5803Srrh */ 217*5803Srrh sign = (Enumber.num_ushort[0] & ~ONES(15)) ? -1 : 0; 218*5803Srrh } 219*5803Srrh /* 220*5803Srrh * Assemble the pieces, and return the number 221*5803Srrh */ 222*5803Srrh Mantissa.num_tag = TYPUNPACKED; 223*5803Srrh Mantissa.num_sign = sign; 224*5803Srrh Mantissa.num_exponent = exponent; 225*5803Srrh return(Mantissa); 226*5803Srrh } 227*5803Srrh 228*5803Srrh Bignum bignumpack(Unpacked, toconv, ovfp) 229*5803Srrh Bignum Unpacked; 230*5803Srrh int toconv; 231*5803Srrh Ovf *ovfp; 232*5803Srrh { 233*5803Srrh Bignum Back; 234*5803Srrh Bignum Enumber; 235*5803Srrh Bignum Temp; 236*5803Srrh 237*5803Srrh short exponent; 238*5803Srrh char sign; 239*5803Srrh reg struct ty_bigdesc *p; 240*5803Srrh reg chptr back; 241*5803Srrh reg chptr enumber; 242*5803Srrh reg chptr temp; 243*5803Srrh reg chptr unpacked; 244*5803Srrh 245*5803Srrh int i,j; 246*5803Srrh 247*5803Srrh if (Unpacked.num_tag != TYPUNPACKED) 248*5803Srrh panic("Argument to bignumpack is not unpacked"); 249*5803Srrh 250*5803Srrh *ovfp = 0; 251*5803Srrh Back = Znumber; 252*5803Srrh Temp = Znumber; 253*5803Srrh Back.num_tag = toconv; 254*5803Srrh 255*5803Srrh back = CH_FIELD(Back); 256*5803Srrh temp = CH_FIELD(Temp); 257*5803Srrh enumber = CH_FIELD(Enumber); 258*5803Srrh unpacked = CH_FIELD(Unpacked); 259*5803Srrh p = &ty_bigdesc[toconv]; 260*5803Srrh 261*5803Srrh exponent = Unpacked.num_exponent; 262*5803Srrh sign = Unpacked.num_sign; 263*5803Srrh if (exponent == MINEXP) 264*5803Srrh return(Back); /* identically zero */ 265*5803Srrh 266*5803Srrh switch(toconv){ 267*5803Srrh case TYPB: 268*5803Srrh case TYPW: 269*5803Srrh case TYPL: 270*5803Srrh case TYPQ: 271*5803Srrh case TYPO: 272*5803Srrh /* 273*5803Srrh * Put back in the assumed high order fraction 274*5803Srrh * bit that is always a 1. 275*5803Srrh */ 276*5803Srrh (void)numshift(-1, temp, unpacked); 277*5803Srrh temp[HOC] |= SIGNBIT; 278*5803Srrh if (exponent > p->b_eexcess){ 279*5803Srrh /* 280*5803Srrh * Construct the largest positive integer 281*5803Srrh */ 282*5803Srrh (void)numclear(temp); 283*5803Srrh (void)num1comp(temp, temp); 284*5803Srrh temp[HOC] &= ~SIGNBIT; 285*5803Srrh sign = sign; 286*5803Srrh *ovfp |= OVF_OVERFLOW; 287*5803Srrh } else 288*5803Srrh if (exponent <= 0){ 289*5803Srrh /* 290*5803Srrh * chop the temp; underflow to integer 0 291*5803Srrh */ 292*5803Srrh (void)numclear(temp); 293*5803Srrh sign = 0; 294*5803Srrh *ovfp |= OVF_UNDERFLOW; 295*5803Srrh } else { 296*5803Srrh /* 297*5803Srrh * denormalize the temp. 298*5803Srrh * This will again chop, by shifting 299*5803Srrh * bits off the right end into oblivion. 300*5803Srrh */ 301*5803Srrh for (j = 4; j >= 0; --j){ 302*5803Srrh i = 1 << j; /* 16, 8, 4, 2, 1 */ 303*5803Srrh while(exponent + i <= p->b_eexcess){ 304*5803Srrh numshift(-i, temp, temp); 305*5803Srrh exponent += i; 306*5803Srrh } 307*5803Srrh } 308*5803Srrh } 309*5803Srrh /* 310*5803Srrh * negate the temp if the sign is set 311*5803Srrh */ 312*5803Srrh if (sign) 313*5803Srrh *ovfp |= numnegate(temp, temp); 314*5803Srrh /* 315*5803Srrh * Stuff the temp number into the return area 316*5803Srrh */ 317*5803Srrh mapnumber(back, temp, 16, p->b_pmmap); 318*5803Srrh return(Back); 319*5803Srrh default: 320*5803Srrh /* 321*5803Srrh * Shift the mantissa to the right, filling in zeroes on 322*5803Srrh * the left. This aligns the least significant bit 323*5803Srrh * on the bottom of a byte, something that upround 324*5803Srrh * will use. 325*5803Srrh * Put the result into a temporary. 326*5803Srrh * Even though the shift may be zero, there 327*5803Srrh * is still a copy involved here. 328*5803Srrh */ 329*5803Srrh (void)numshift(-(p->b_mlshift), temp, unpacked); 330*5803Srrh /* 331*5803Srrh * Perform the rounding by adding in 0.5 ulp's 332*5803Srrh */ 333*5803Srrh exponent = upround(&Temp, p, exponent); 334*5803Srrh /* 335*5803Srrh * Do a range check on the exponent, in preparation 336*5803Srrh * to stuffing it in. 337*5803Srrh */ 338*5803Srrh if ((short)(exponent + p->b_eexcess) == 0){ 339*5803Srrh /* 340*5803Srrh * Sorry, no gradual underflow on the 341*5803Srrh * VAX. Chop this beasty totally to zero 342*5803Srrh */ 343*5803Srrh goto zeroret; 344*5803Srrh } else 345*5803Srrh if ((short)(exponent + p->b_eexcess) < 0){ 346*5803Srrh /* 347*5803Srrh * True underflow will happen; 348*5803Srrh * Chop everything to positive zero 349*5803Srrh */ 350*5803Srrh zeroret: 351*5803Srrh (void)numclear(temp); 352*5803Srrh exponent = 0; 353*5803Srrh sign = 0; /* avoid reserved operand! */ 354*5803Srrh *ovfp |= OVF_UNDERFLOW; 355*5803Srrh } else 356*5803Srrh if ((unsigned)(exponent + p->b_eexcess) 357*5803Srrh >= (unsigned)(1 << p->b_esigbits)){ 358*5803Srrh /* 359*5803Srrh * Construct the largest magnitude possible 360*5803Srrh * floating point unpacked: 0.{1}111111111 361*5803Srrh */ 362*5803Srrh (void)numclear(temp); 363*5803Srrh (void)num1comp(temp, temp); 364*5803Srrh exponent = ONES(p->b_esigbits); 365*5803Srrh sign = sign; 366*5803Srrh *ovfp |= OVF_OVERFLOW; 367*5803Srrh } else { 368*5803Srrh /* 369*5803Srrh * The exponent will fit. 370*5803Srrh * Bias it up, and the common code will stuff it. 371*5803Srrh */ 372*5803Srrh exponent += p->b_eexcess; 373*5803Srrh } 374*5803Srrh exponent <<= p->b_ershift; 375*5803Srrh /* 376*5803Srrh * mask out trash for the sign, and put in the sign. 377*5803Srrh */ 378*5803Srrh exponent &= ONES(15); 379*5803Srrh if (sign) 380*5803Srrh exponent |= ~ONES(15); 381*5803Srrh Enumber.num_ushort[0] = exponent; 382*5803Srrh /* 383*5803Srrh * Map the unpacked exponent into the value going back 384*5803Srrh */ 385*5803Srrh mapnumber(back, enumber, 2, p->b_pemap); 386*5803Srrh /* 387*5803Srrh * Stuff the unpacked mantissa into the return area 388*5803Srrh */ 389*5803Srrh mapnumber(back, temp, 16, p->b_pmmap); 390*5803Srrh return(Back); 391*5803Srrh } 392*5803Srrh /*NOTREACHED*/ 393*5803Srrh } 394*5803Srrh 395*5803Srrh mapnumber(chp1, chp2, nbytes, themap) 396*5803Srrh chptr chp1, chp2; 397*5803Srrh int nbytes; 398*5803Srrh char *themap; 399*5803Srrh { 400*5803Srrh reg int i; 401*5803Srrh reg u_char *p1, *p2; 402*5803Srrh 403*5803Srrh p1 = (u_char *)chp1; 404*5803Srrh p2 = (u_char *)chp2; 405*5803Srrh for (i = 0; i < nbytes; i++){ 406*5803Srrh switch(themap[i]){ 407*5803Srrh case NOTAKE: 408*5803Srrh break; 409*5803Srrh default: 410*5803Srrh p1[themap[i]] |= p2[i]; 411*5803Srrh break; 412*5803Srrh } 413*5803Srrh } 414*5803Srrh } 415*5803Srrh 416*5803Srrh #define UPSHIFT 2 417*5803Srrh /* 418*5803Srrh * round in 1/2 ulp in the number, possibly modifying 419*5803Srrh * the binary exponent if there was total carry out. 420*5803Srrh * Return the modified exponent 421*5803Srrh */ 422*5803Srrh int upround(numberp, p, exponent) 423*5803Srrh reg Bignum *numberp; 424*5803Srrh reg struct ty_bigdesc *p; 425*5803Srrh int exponent; 426*5803Srrh { 427*5803Srrh reg u_char *bytep; 428*5803Srrh int nbytes; 429*5803Srrh int byteindex; 430*5803Srrh int hofractionbit; 431*5803Srrh int ovffractionbit; 432*5803Srrh reg int ovfbitindex; 433*5803Srrh reg chptr number; 434*5803Srrh static Bignum ulp; 435*5803Srrh 436*5803Srrh /* 437*5803Srrh * Find out the byte index of the byte containing the ulp 438*5803Srrh */ 439*5803Srrh number = CH_FIELD(numberp[0]); 440*5803Srrh bytep = numberp->num_uchar; 441*5803Srrh 442*5803Srrh nbytes = (p->b_msigbits - 1) + p->b_mlshift; 443*5803Srrh assert((nbytes % 8) == 0, "mantissa sig bits"); 444*5803Srrh nbytes /= 8; 445*5803Srrh byteindex = 15 - nbytes; 446*5803Srrh assert(byteindex >= 0, "ulp in outer space"); 447*5803Srrh /* 448*5803Srrh * Shift the number to the right by two places, 449*5803Srrh * so that we can do full arithmetic without overflowing 450*5803Srrh * to the left. 451*5803Srrh */ 452*5803Srrh numshift(-UPSHIFT, number, number); 453*5803Srrh /* 454*5803Srrh * Construct the missing high order fraction bit 455*5803Srrh */ 456*5803Srrh ovfbitindex = 8 - (p->b_mlshift + UPSHIFT); 457*5803Srrh assert(ovfbitindex >= 0, "Shifted byte 15 into byte 14"); 458*5803Srrh hofractionbit = (0x01 << ovfbitindex); 459*5803Srrh ovffractionbit = (0x02 << ovfbitindex); 460*5803Srrh bytep[15] |= hofractionbit; 461*5803Srrh /* 462*5803Srrh * construct the unit in the last place, and it 463*5803Srrh * to the fraction 464*5803Srrh */ 465*5803Srrh ulp.num_uchar[byteindex] |= (0x80 >> UPSHIFT); 466*5803Srrh numaddv(number, number, CH_FIELD(ulp)); 467*5803Srrh ulp.num_uchar[byteindex] &= ~(0x80 >> UPSHIFT); 468*5803Srrh /* 469*5803Srrh * Check if there was an overflow, 470*5803Srrh * and adjust by shifting. 471*5803Srrh * Also, bring the number back into canonical 472*5803Srrh * unpacked form by left shifting by two to undeo 473*5803Srrh * what we did before. 474*5803Srrh */ 475*5803Srrh if (bytep[15] & ovffractionbit){ 476*5803Srrh exponent += 1; 477*5803Srrh numshift(UPSHIFT - 1, number, number); 478*5803Srrh } else { 479*5803Srrh numshift(UPSHIFT, number, number); 480*5803Srrh } 481*5803Srrh /* 482*5803Srrh * Clear off trash in the unused bits of the high 483*5803Srrh * order byte of the number 484*5803Srrh */ 485*5803Srrh bytep[15] &= ONES(8 - p->b_mlshift); 486*5803Srrh return(exponent); 487*5803Srrh } 488*5803Srrh #ifdef DEBUG 489*5803Srrh bignumprint(number) 490*5803Srrh Bignum number; 491*5803Srrh { 492*5803Srrh printf("Bignum: %s (exp: %d, sign: %d) 0x%08x%08x%08x%08x", 493*5803Srrh ty_string[number.num_tag], 494*5803Srrh number.num_exponent, 495*5803Srrh number.num_sign, 496*5803Srrh number.num_uint[3], 497*5803Srrh number.num_uint[2], 498*5803Srrh number.num_uint[1], 499*5803Srrh number.num_uint[0]); 500*5803Srrh switch(number.num_tag){ 501*5803Srrh case TYPB: 502*5803Srrh case TYPW: 503*5803Srrh case TYPL: 504*5803Srrh case TYPQ: 505*5803Srrh case TYPO: 506*5803Srrh case TYPUNPACKED: 507*5803Srrh break; 508*5803Srrh case TYPF: 509*5803Srrh printf(" == %10.8e", number.num_num.numFf_float.Ff_value); 510*5803Srrh break; 511*5803Srrh case TYPD: 512*5803Srrh printf(" == %20.17e", number.num_num.numFd_float.Fd_value); 513*5803Srrh break; 514*5803Srrh case TYPG: 515*5803Srrh case TYPH: 516*5803Srrh break; 517*5803Srrh } 518*5803Srrh } 519*5803Srrh 520*5803Srrh numprintovf(ovf) 521*5803Srrh Ovf ovf; 522*5803Srrh { 523*5803Srrh int i; 524*5803Srrh static struct ovftab{ 525*5803Srrh Ovf which; 526*5803Srrh char *print; 527*5803Srrh } ovftab[] = { 528*5803Srrh OVF_POSOVF, "posovf", 529*5803Srrh OVF_MAXINT, "maxint", 530*5803Srrh OVF_ADDV, "addv", 531*5803Srrh OVF_LSHIFT, "lshift", 532*5803Srrh OVF_F, "F float", 533*5803Srrh OVF_D, "D float", 534*5803Srrh OVF_G, "G float", 535*5803Srrh OVF_H, "H float", 536*5803Srrh OVF_OVERFLOW, "cvt overflow", 537*5803Srrh OVF_UNDERFLOW, "cvt underflow", 538*5803Srrh 0, 0 539*5803Srrh }; 540*5803Srrh for(i = 0; ovftab[i].which; i++){ 541*5803Srrh if (ovf & ovftab[i].which) 542*5803Srrh printf("Overflow(%s) ", ovftab[i].print); 543*5803Srrh } 544*5803Srrh } 545*5803Srrh #endif DEBUG 546