root/kernel/math/add.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. signify
  2. unsignify
  3. fadd

   1 /*
   2  * linux/kernel/math/add.c
   3  *
   4  * Copyright (C) 1991, 1992 Linus Torvalds
   5  */
   6 
   7 /*
   8  * temporary real addition routine.
   9  *
  10  * NOTE! These aren't exact: they are only 62 bits wide, and don't do
  11  * correct rounding. Fast hack. The reason is that we shift right the
  12  * values by two, in order not to have overflow (1 bit), and to be able
  13  * to move the sign into the mantissa (1 bit). Much simpler algorithms,
  14  * and 62 bits (61 really - no rounding) accuracy is usually enough. The
  15  * only time you should notice anything weird is when adding 64-bit
  16  * integers together. When using doubles (52 bits accuracy), the
  17  * 61-bit accuracy never shows at all.
  18  */
  19 
  20 #include <linux/math_emu.h>
  21 
  22 #define NEGINT(a) \
  23 __asm__("notl %0 ; notl %1 ; addl $1,%0 ; adcl $0,%1" \
  24         :"=r" (a->a),"=r" (a->b) \
  25         :"0" (a->a),"1" (a->b))
  26 
  27 static void signify(temp_real * a)
     /* [previous][next][first][last][top][bottom][index][help] */
  28 {
  29         a->exponent += 2;
  30         __asm__("shrdl $2,%1,%0 ; shrl $2,%1"
  31                 :"=r" (a->a),"=r" (a->b)
  32                 :"0" (a->a),"1" (a->b));
  33         if (a->exponent < 0)
  34                 NEGINT(a);
  35         a->exponent &= 0x7fff;
  36 }
  37 
  38 static void unsignify(temp_real * a)
     /* [previous][next][first][last][top][bottom][index][help] */
  39 {
  40         if (!(a->a || a->b)) {
  41                 a->exponent = 0;
  42                 return;
  43         }
  44         a->exponent &= 0x7fff;
  45         if (a->b < 0) {
  46                 NEGINT(a);
  47                 a->exponent |= 0x8000;
  48         }
  49         while (a->b >= 0) {
  50                 a->exponent--;
  51                 __asm__("addl %0,%0 ; adcl %1,%1"
  52                         :"=r" (a->a),"=r" (a->b)
  53                         :"0" (a->a),"1" (a->b));
  54         }
  55 }
  56 
  57 void fadd(const temp_real * src1, const temp_real * src2, temp_real * result)
     /* [previous][next][first][last][top][bottom][index][help] */
  58 {
  59         temp_real a,b;
  60         int x1,x2,shift;
  61 
  62         x1 = src1->exponent & 0x7fff;
  63         x2 = src2->exponent & 0x7fff;
  64         if (x1 > x2) {
  65                 a = *src1;
  66                 b = *src2;
  67                 shift = x1-x2;
  68         } else {
  69                 a = *src2;
  70                 b = *src1;
  71                 shift = x2-x1;
  72         }
  73         if (shift >= 64) {
  74                 *result = a;
  75                 return;
  76         }
  77         if (shift >= 32) {
  78                 b.a = b.b;
  79                 b.b = 0;
  80                 shift -= 32;
  81         }
  82         __asm__("shrdl %4,%1,%0 ; shrl %4,%1"
  83                 :"=r" (b.a),"=r" (b.b)
  84                 :"0" (b.a),"1" (b.b),"c" ((char) shift));
  85         signify(&a);
  86         signify(&b);
  87         __asm__("addl %4,%0 ; adcl %5,%1"
  88                 :"=r" (a.a),"=r" (a.b)
  89                 :"0" (a.a),"1" (a.b),"g" (b.a),"g" (b.b));
  90         unsignify(&a);
  91         *result = a;
  92 }

/* [previous][next][first][last][top][bottom][index][help] */