root/kernel/math/get_put.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_short_real
  2. get_long_real
  3. get_temp_real
  4. get_short_int
  5. get_long_int
  6. get_longlong_int
  7. get_BCD
  8. put_short_real
  9. put_long_real
  10. put_temp_real
  11. put_short_int
  12. put_long_int
  13. put_longlong_int
  14. put_BCD

   1 /*
   2  * linux/kernel/math/get_put.c
   3  *
   4  * Copyright (C) 1991, 1992 Linus Torvalds
   5  */
   6 
   7 /*
   8  * This file handles all accesses to user memory: getting and putting
   9  * ints/reals/BCD etc. This is the only part that concerns itself with
  10  * other than temporary real format. All other cals are strictly temp_real.
  11  */
  12 #include <linux/signal.h>
  13 #include <linux/math_emu.h>
  14 #include <linux/kernel.h>
  15 #include <asm/segment.h>
  16 
  17 void get_short_real(temp_real * tmp,
     /* [previous][next][first][last][top][bottom][index][help] */
  18         struct info * info, unsigned short code)
  19 {
  20         char * addr;
  21         short_real sr;
  22 
  23         addr = ea(info,code);
  24         sr = get_fs_long((unsigned long *) addr);
  25         short_to_temp(&sr,tmp);
  26 }
  27 
  28 void get_long_real(temp_real * tmp,
     /* [previous][next][first][last][top][bottom][index][help] */
  29         struct info * info, unsigned short code)
  30 {
  31         char * addr;
  32         long_real lr;
  33 
  34         addr = ea(info,code);
  35         lr.a = get_fs_long((unsigned long *) addr);
  36         lr.b = get_fs_long(1 + (unsigned long *) addr);
  37         long_to_temp(&lr,tmp);
  38 }
  39 
  40 void get_temp_real(temp_real * tmp,
     /* [previous][next][first][last][top][bottom][index][help] */
  41         struct info * info, unsigned short code)
  42 {
  43         char * addr;
  44 
  45         addr = ea(info,code);
  46         tmp->a = get_fs_long((unsigned long *) addr);
  47         tmp->b = get_fs_long(1 + (unsigned long *) addr);
  48         tmp->exponent = get_fs_word(4 + (unsigned short *) addr);
  49 }
  50 
  51 void get_short_int(temp_real * tmp,
     /* [previous][next][first][last][top][bottom][index][help] */
  52         struct info * info, unsigned short code)
  53 {
  54         char * addr;
  55         temp_int ti;
  56 
  57         addr = ea(info,code);
  58         ti.a = (signed short) get_fs_word((unsigned short *) addr);
  59         ti.b = 0;
  60         if (ti.sign = (ti.a < 0))
  61                 ti.a = - ti.a;
  62         int_to_real(&ti,tmp);
  63 }
  64 
  65 void get_long_int(temp_real * tmp,
     /* [previous][next][first][last][top][bottom][index][help] */
  66         struct info * info, unsigned short code)
  67 {
  68         char * addr;
  69         temp_int ti;
  70 
  71         addr = ea(info,code);
  72         ti.a = get_fs_long((unsigned long *) addr);
  73         ti.b = 0;
  74         if (ti.sign = (ti.a < 0))
  75                 ti.a = - ti.a;
  76         int_to_real(&ti,tmp);
  77 }
  78 
  79 void get_longlong_int(temp_real * tmp,
     /* [previous][next][first][last][top][bottom][index][help] */
  80         struct info * info, unsigned short code)
  81 {
  82         char * addr;
  83         temp_int ti;
  84 
  85         addr = ea(info,code);
  86         ti.a = get_fs_long((unsigned long *) addr);
  87         ti.b = get_fs_long(1 + (unsigned long *) addr);
  88         if (ti.sign = (ti.b < 0))
  89                 __asm__("notl %0 ; notl %1\n\t"
  90                         "addl $1,%0 ; adcl $0,%1"
  91                         :"=r" (ti.a),"=r" (ti.b)
  92                         :"0" (ti.a),"1" (ti.b));
  93         int_to_real(&ti,tmp);
  94 }
  95 
  96 #define MUL10(low,high) \
  97 __asm__("addl %0,%0 ; adcl %1,%1\n\t" \
  98 "movl %0,%%ecx ; movl %1,%%ebx\n\t" \
  99 "addl %0,%0 ; adcl %1,%1\n\t" \
 100 "addl %0,%0 ; adcl %1,%1\n\t" \
 101 "addl %%ecx,%0 ; adcl %%ebx,%1" \
 102 :"=a" (low),"=d" (high) \
 103 :"0" (low),"1" (high):"cx","bx")
 104 
 105 #define ADD64(val,low,high) \
 106 __asm__("addl %4,%0 ; adcl $0,%1":"=r" (low),"=r" (high) \
 107 :"0" (low),"1" (high),"r" ((unsigned long) (val)))
 108 
 109 void get_BCD(temp_real * tmp, struct info * info, unsigned short code)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111         int k;
 112         char * addr;
 113         temp_int i;
 114         unsigned char c;
 115 
 116         addr = ea(info,code);
 117         addr += 9;
 118         i.sign = 0x80 & get_fs_byte(addr--);
 119         i.a = i.b = 0;
 120         for (k = 0; k < 9; k++) {
 121                 c = get_fs_byte(addr--);
 122                 MUL10(i.a, i.b);
 123                 ADD64((c>>4), i.a, i.b);
 124                 MUL10(i.a, i.b);
 125                 ADD64((c&0xf), i.a, i.b);
 126         }
 127         int_to_real(&i,tmp);
 128 }
 129 
 130 void put_short_real(const temp_real * tmp,
     /* [previous][next][first][last][top][bottom][index][help] */
 131         struct info * info, unsigned short code)
 132 {
 133         char * addr;
 134         short_real sr;
 135 
 136         addr = ea(info,code);
 137         verify_area(addr,4);
 138         temp_to_short(tmp,&sr);
 139         put_fs_long(sr,(unsigned long *) addr);
 140 }
 141 
 142 void put_long_real(const temp_real * tmp,
     /* [previous][next][first][last][top][bottom][index][help] */
 143         struct info * info, unsigned short code)
 144 {
 145         char * addr;
 146         long_real lr;
 147 
 148         addr = ea(info,code);
 149         verify_area(addr,8);
 150         temp_to_long(tmp,&lr);
 151         put_fs_long(lr.a, (unsigned long *) addr);
 152         put_fs_long(lr.b, 1 + (unsigned long *) addr);
 153 }
 154 
 155 void put_temp_real(const temp_real * tmp,
     /* [previous][next][first][last][top][bottom][index][help] */
 156         struct info * info, unsigned short code)
 157 {
 158         char * addr;
 159 
 160         addr = ea(info,code);
 161         verify_area(addr,10);
 162         put_fs_long(tmp->a, (unsigned long *) addr);
 163         put_fs_long(tmp->b, 1 + (unsigned long *) addr);
 164         put_fs_word(tmp->exponent, 4 + (short *) addr);
 165 }
 166 
 167 void put_short_int(const temp_real * tmp,
     /* [previous][next][first][last][top][bottom][index][help] */
 168         struct info * info, unsigned short code)
 169 {
 170         char * addr;
 171         temp_int ti;
 172 
 173         addr = ea(info,code);
 174         real_to_int(tmp,&ti);
 175         verify_area(addr,2);
 176         if (ti.sign)
 177                 ti.a = -ti.a;
 178         put_fs_word(ti.a,(short *) addr);
 179 }
 180 
 181 void put_long_int(const temp_real * tmp,
     /* [previous][next][first][last][top][bottom][index][help] */
 182         struct info * info, unsigned short code)
 183 {
 184         char * addr;
 185         temp_int ti;
 186 
 187         addr = ea(info,code);
 188         real_to_int(tmp,&ti);
 189         verify_area(addr,4);
 190         if (ti.sign)
 191                 ti.a = -ti.a;
 192         put_fs_long(ti.a,(unsigned long *) addr);
 193 }
 194 
 195 void put_longlong_int(const temp_real * tmp,
     /* [previous][next][first][last][top][bottom][index][help] */
 196         struct info * info, unsigned short code)
 197 {
 198         char * addr;
 199         temp_int ti;
 200 
 201         addr = ea(info,code);
 202         real_to_int(tmp,&ti);
 203         verify_area(addr,8);
 204         if (ti.sign)
 205                 __asm__("notl %0 ; notl %1\n\t"
 206                         "addl $1,%0 ; adcl $0,%1"
 207                         :"=r" (ti.a),"=r" (ti.b)
 208                         :"0" (ti.a),"1" (ti.b));
 209         put_fs_long(ti.a,(unsigned long *) addr);
 210         put_fs_long(ti.b,1 + (unsigned long *) addr);
 211 }
 212 
 213 #define DIV10(low,high,rem) \
 214 __asm__("divl %6 ; xchgl %1,%2 ; divl %6" \
 215         :"=d" (rem),"=a" (low),"=r" (high) \
 216         :"0" (0),"1" (high),"2" (low),"c" (10))
 217 
 218 void put_BCD(const temp_real * tmp,struct info * info, unsigned short code)
     /* [previous][next][first][last][top][bottom][index][help] */
 219 {
 220         int k,rem;
 221         char * addr;
 222         temp_int i;
 223         unsigned char c;
 224 
 225         addr = ea(info,code);
 226         verify_area(addr,10);
 227         real_to_int(tmp,&i);
 228         if (i.sign)
 229                 put_fs_byte(0x80, addr+9);
 230         else
 231                 put_fs_byte(0, addr+9);
 232         for (k = 0; k < 9; k++) {
 233                 DIV10(i.a,i.b,rem);
 234                 c = rem;
 235                 DIV10(i.a,i.b,rem);
 236                 c += rem<<4;
 237                 put_fs_byte(c,addr++);
 238         }
 239 }

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