����11-7 linux/kernel/math/get_put.c


  1 /*

  2  * linux/kernel/math/get_put.c

  3  *

  4  * (C) 1991 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  */

    /*

     * �����������ж��û��ڴ�ķ��ʣ���ȡ�ʹ���ָ��/ʵ��ֵ/BCD��ֵ�ȡ�����

     * �漰��ʱʵ������������ʽ���еIJ��֡�������������ȫ��ʹ����ʱʵ����ʽ��

     */

 12 #include <signal.h>       // �ź�ͷ�ļ��������źŷ��ţ��źŽṹ���źŲ�������ԭ�͡�

 13

 14 #include <linux/math_emu.h> // Э������ͷ�ļ���������ʱʵ���ṹ��387�Ĵ���������ȡ�

 15 #include <linux/kernel.h>   // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣

 16 #include <asm/segment.h>    // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����

 17

    // ȡ�û��ڴ��еĶ�ʵ����������ʵ������

    // ���ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info�ṹ�е�ǰ�Ĵ����е����ݣ�ȡ�ö�ʵ��

    // ������Ч��ַ��math/ea.c����Ȼ����û���������ȡ��Ӧʵ��ֵ�������û���ʵ��ת����

    // ��ʱʵ����math/convert.c����

    // ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣

 18 void get_short_real(temp_real * tmp,

 19         struct info * info, unsigned short code)

 20 {

 21         char * addr;

 22         short_real sr;

 23

 24         addr = ea(info,code);                        // ������Ч��ַ��

 25         sr = get_fs_long((unsigned long *) addr);    // ȡ�û��������е�ֵ��

 26         short_to_temp(&sr,tmp);                      // ת������ʱʵ����ʽ��

 27 }

 28

    // ȡ�û��ڴ��еij�ʵ����˫����ʵ������

    // ���ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info�ṹ�е�ǰ�Ĵ����е����ݣ�ȡ�ó�

    // ʵ��������Ч��ַ��math/ea.c����Ȼ����û���������ȡ��Ӧʵ��ֵ�������û�ʵ��ֵת

    // ������ʱʵ����math/convert.c����

    // ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣

 29 void get_long_real(temp_real * tmp,

 30         struct info * info, unsigned short code)

 31 {

 32         char * addr;

 33         long_real lr;

 34

 35         addr = ea(info,code);                             // ȡָ���е���Ч��ֵַ��

 36         lr.a = get_fs_long((unsigned long *) addr);       // ȡ��8�ֽ�ʵ����

 37         lr.b = get_fs_long(1 + (unsigned long *) addr);

 38         long_to_temp(&lr,tmp);                            // ת������ʱʵ����ʽ��

 39 }

 40

    // ȡ�û��ڴ��е���ʱʵ����

    // ���ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info�ṹ�е�ǰ�Ĵ����е����ݣ�ȡ����

    // ʱʵ��������Ч��ַ��math/ea.c����Ȼ����û���������ȡ��Ӧ��ʱʵ��ֵ��

    // ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣

 41 void get_temp_real(temp_real * tmp,

 42         struct info * info, unsigned short code)

 43 {

 44         char * addr;

 45

 46         addr = ea(info,code);                             // ȡָ���е���Ч��ֵַ��

 47         tmp->a = get_fs_long((unsigned long *) addr);

 48         tmp->b = get_fs_long(1 + (unsigned long *) addr);

 49         tmp->exponent = get_fs_word(4 + (unsigned short *) addr);

 50 }

 51

    // ȡ�û��ڴ��еĶ�������ת������ʱʵ����ʽ��

    // ��ʱ����Ҳ��10�ֽڱ�ʾ�����е�8�ֽ����޷�������ֵ����2�ֽڱ�ʾָ��ֵ�ͷ���λ��

    // �����2�ֽ������ЧλΪ1�����ʾ�Ǹ������������Чλ��0����ʾ��������

    // �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ� info�ṹ�е�ǰ�Ĵ����е����ݣ�

    // ȡ�ö�����������Ч��ַ��math/ea.c����Ȼ����û���������ȡ��Ӧ����ֵ��������Ϊ��ʱ

    // ������ʽ��������ʱ����ֵת������ʱʵ����math/convert.c����

    // ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣

 52 void get_short_int(temp_real * tmp,

 53         struct info * info, unsigned short code)

 54 {

 55         char * addr;

 56         temp_int ti;

 57

 58         addr = ea(info,code);               // ȡָ���е���Ч��ֵַ��

 59         ti.a = (signed short) get_fs_word((unsigned short *) addr);

 60         ti.b = 0;

 61         if (ti.sign = (ti.a < 0))           // ���Ǹ�������������ʱ��������λ��

 62                 ti.a = - ti.a;              // ��ʱ������β��������Ϊ�޷�������

 63         int_to_real(&ti,tmp);               // ����ʱ����ת������ʱʵ����ʽ��

 64 }

 65

    // ȡ�û��ڴ��еij�������ת������ʱʵ����ʽ��

    // ���ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info�ṹ�е�ǰ�Ĵ����е����ݣ�ȡ�ó�

    // ����������Ч��ַ��math/ea.c����Ȼ����û���������ȡ��Ӧ����ֵ��������Ϊ��ʱ������

    // ʽ��������ʱ����ֵת������ʱʵ����math/convert.c����

    // ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣

 66 void get_long_int(temp_real * tmp,

 67         struct info * info, unsigned short code)

 68 {

 69         char * addr;

 70         temp_int ti;

 71

 72         addr = ea(info,code);               // ȡָ���е���Ч��ֵַ��

 73         ti.a = get_fs_long((unsigned long *) addr);

 74         ti.b = 0;

 75         if (ti.sign = (ti.a < 0))           // ���Ǹ�������������ʱ��������λ��

 76                 ti.a = - ti.a;              // ��ʱ������β��������Ϊ�޷�������

 77         int_to_real(&ti,tmp);               // ����ʱ����ת������ʱʵ����ʽ��

 78 }

 79

    // ȡ�û��ڴ��е�64λ��������ת������ʱʵ����ʽ��

    // ���ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�ȡ��

    // 64λ������������Ч��ַ��math/ea.c����Ȼ����û���������ȡ��Ӧ����ֵ��������Ϊ��

    // ʱ������ʽ������ٰ���ʱ����ֵת������ʱʵ����math/convert.c����

    // ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣

 80 void get_longlong_int(temp_real * tmp,

 81         struct info * info, unsigned short code)

 82 {

 83         char * addr;

 84         temp_int ti;

 85

 86         addr = ea(info,code);                            // ȡָ���е���Ч��ֵַ��

 87         ti.a = get_fs_long((unsigned long *) addr);      // ȡ�û�64λ��������

 88         ti.b = get_fs_long(1 + (unsigned long *) addr);

 89         if (ti.sign = (ti.b < 0))                   // ���Ǹ�����������ʱ��������λ��

 90                 __asm__("notl %0 ; notl %1\n\t"     // ͬʱȡ����1�ͽ�λ������

 91                         "addl $1,%0 ; adcl $0,%1"

 92                         :"=r" (ti.a),"=r" (ti.b)

 93                         :"" (ti.a),"1" (ti.b));

 94         int_to_real(&ti,tmp);                       // ����ʱ����ת������ʱʵ����ʽ��

 95 }

 96

    // ��һ��64λ����������N����10��

    // �������������BCD����ֵת������ʱʵ����ʽ�����С������ǣ�N<<1 + N<<3��

 97 #define MUL10(low,high) \

 98 __asm__("addl %0,%0 ; adcl %1,%1\n\t" \

 99 "movl %0,%%ecx ; movl %1,%%ebx\n\t" \

100 "addl %0,%0 ; adcl %1,%1\n\t" \

101 "addl %0,%0 ; adcl %1,%1\n\t" \

102 "addl %%ecx,%0 ; adcl %%ebx,%1" \

103 :"=a" (low),"=d" (high) \

104 :"" (low),"1" (high):"cx","bx")

105

    // 64λ�ӷ���

    // ��32λ���޷�����val�ӵ�64λ�� <high,low> �С�

106 #define ADD64(val,low,high) \

107 __asm__("addl %4,%0 ; adcl $0,%1":"=r" (low),"=r" (high) \

108 :"" (low),"1" (high),"r" ((unsigned long) (val)))

109

    // ȡ�û��ڴ��е�BCD����ֵ��ת������ʱʵ����ʽ��

    // �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�

    // ȡ�� BCD��������Ч��ַ��math/ea.c����Ȼ����û���������ȡ 10�ֽ���ӦBCD��ֵ����

    // ��1�ֽ����ڷ��ţ���ͬʱת������ʱ������ʽ��������ʱ����ֵת������ʱʵ����

    // ������tmp �C ת������ʱʵ�����ָ�룻info �C info�ṹָ�룻code �C ָ����롣

110 void get_BCD(temp_real * tmp, struct info * info, unsigned short code)

111 {

112         int k;

113         char * addr;

114         temp_int i;

115         unsigned char c;

116

    // ȡ��BCD����ֵ�����ڴ���Ч��ַ��Ȼ������1��BCD���ֽڣ������Чλ����ʼ������

    // ��ȡ��BCD����ֵ�ķ���λ����������ʱ�����ķ���λ��Ȼ���9�ֽڵ�BCD��ֵת����

    // ��ʱ������ʽ������ٰ���ʱ����ֵת������ʱʵ����

117         addr = ea(info,code);                      // ȡ��Ч��ַ��

118         addr += 9;                                 // ָ�����һ������10�����ֽڡ�

119         i.sign = 0x80 & get_fs_byte(addr--);       // ȡ���з���λ��

120         i.a = i.b = 0;

121         for (k = 0; k < 9; k++) {                  // ת������ʱ������ʽ��

122                 c = get_fs_byte(addr--);

123                 MUL10(i.a, i.b);

124                 ADD64((c>>4), i.a, i.b);

125                 MUL10(i.a, i.b);

126                 ADD64((c&0xf), i.a, i.b);

127         }

128         int_to_real(&i,tmp);                       // ת������ʱʵ����ʽ��

129 }

130

    // ���������Զ̣������ȣ�ʵ����ʽ���浽�û��������С�

    // �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�

    // ȡ�ñ���������Ч��ַaddr��Ȼ�����ʱʵ����ʽ�Ľ��ת���ɶ�ʵ����ʽ���洢����Ч

    // ��ַaddr����

    // ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣

131 void put_short_real(const temp_real * tmp,

132         struct info * info, unsigned short code)

133 {

134         char * addr;

135         short_real sr;

136

137         addr = ea(info,code);                       // ȡ��Ч��ַ��

138         verify_area(addr,4);                        // Ϊ��������֤������ڴ档

139         temp_to_short(tmp,&sr);                     // ���ת���ɶ�ʵ����ʽ��

140         put_fs_long(sr,(unsigned long *) addr);     // �洢���ݵ��û��ڴ�����

141 }

142

    // ���������Գ���˫���ȣ�ʵ����ʽ���浽�û��������С�

    // �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�

    // ȡ�ñ���������Ч��ַaddr��Ȼ�����ʱʵ����ʽ�Ľ��ת���ɳ�ʵ����ʽ�����洢����

    // Ч��ַaddr����

    // ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣

143 void put_long_real(const temp_real * tmp,

144         struct info * info, unsigned short code)

145 {

146         char * addr;

147         long_real lr;

148

149         addr = ea(info,code);                         // ȡ��Ч��ַ��

150         verify_area(addr,8);                          // Ϊ��������֤������ڴ档

151         temp_to_long(tmp,&lr);                       // ���ת���ɳ�ʵ����ʽ��

152         put_fs_long(lr.a, (unsigned long *) addr);   // �洢���ݵ��û��ڴ�����

153         put_fs_long(lr.b, 1 + (unsigned long *) addr);

154 }

155

    // ������������ʱʵ����ʽ���浽�û��������С�

    // �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�

    // ȡ�ñ���������Ч��ַaddr��Ȼ�����ʱʵ���洢����Ч��ַaddr����

    // ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣

156 void put_temp_real(const temp_real * tmp,

157         struct info * info, unsigned short code)

158 {

159         char * addr;

160

161         addr = ea(info,code);                        // ȡ��Ч��ַ��

162         verify_area(addr,10);                        // Ϊ��������֤������ڴ档

163         put_fs_long(tmp->a, (unsigned long *) addr); // �洢���ݵ��û��ڴ�����

164         put_fs_long(tmp->b, 1 + (unsigned long *) addr);

165         put_fs_word(tmp->exponent, 4 + (short *) addr);

166 }

167

    // ���������Զ�������ʽ���浽�û��������С�

    // �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�

    // ȡ�ñ���������Ч��ַaddr��Ȼ�����ʱʵ����ʽ�Ľ��ת������ʱ������ʽ������Ǹ�

    // ����������������λ�������������浽�û��ڴ��С�

    // ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣

168 void put_short_int(const temp_real * tmp,

169         struct info * info, unsigned short code)

170 {

171         char * addr;

172         temp_int ti;

173

174         addr = ea(info,code);                        // ȡ��Ч��ַ��

175         real_to_int(tmp,&ti);                        // ת������ʱ������ʽ��

176         verify_area(addr,2);                         // ��֤�����洢�ڴ档

177         if (ti.sign)                                 // ���з���λ����ȡ����ֵ��

178                 ti.a = -ti.a;

179         put_fs_word(ti.a,(short *) addr);            // �洢���û��������С�

180 }

181

    // ���������Գ�������ʽ���浽�û��������С�

    // �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�

    // ȡ�ñ���������Ч��ַaddr��Ȼ�����ʱʵ����ʽ�Ľ��ת������ʱ������ʽ������Ǹ�

    // ����������������λ�������������浽�û��ڴ��С�

    // ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣

182 void put_long_int(const temp_real * tmp,

183         struct info * info, unsigned short code)

184 {

185         char * addr;

186         temp_int ti;

187

188         addr = ea(info,code);                        // ȡ��Ч��ַ��

189         real_to_int(tmp,&ti);                        // ת������ʱ������ʽ��

190         verify_area(addr,4);                         // ��֤�����洢�ڴ档

191         if (ti.sign)                                 // ���з���λ����ȡ����ֵ��

192                 ti.a = -ti.a;

193         put_fs_long(ti.a,(unsigned long *) addr);    // �洢���û��������С�

194 }

195

    // ����������64λ������ʽ���浽�û��������С�

    // �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�

    // ȡ�ñ���������Ч��ַaddr��Ȼ�����ʱʵ����ʽ�Ľ��ת������ʱ������ʽ������Ǹ�

    // ����������������λ�������������浽�û��ڴ��С�

    // ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣

196 void put_longlong_int(const temp_real * tmp,

197         struct info * info, unsigned short code)

198 {

199         char * addr;

200         temp_int ti;

201

202         addr = ea(info,code);                        // ȡ��Ч��ַ��

203         real_to_int(tmp,&ti);                        // ת������ʱ������ʽ��

204         verify_area(addr,8);                         // ��֤�洢����

205         if (ti.sign)                                 // ���Ǹ�������ȡ����1��

206                 __asm__("notl %0 ; notl %1\n\t"

207                         "addl $1,%0 ; adcl $0,%1"

208                         :"=r" (ti.a),"=r" (ti.b)

209                         :"" (ti.a),"1" (ti.b));

210         put_fs_long(ti.a,(unsigned long *) addr);       // �洢���û��������С�

211         put_fs_long(ti.b,1 + (unsigned long *) addr);

212 }

213

    // �޷�����<high, low>����10����������rem�С�

214 #define DIV10(low,high,rem) \

215 __asm__("divl %6 ; xchgl %1,%2 ; divl %6" \

216         :"=d" (rem),"=a" (low),"=b" (high) \

217         :"" (0),"1" (high),"2" (low),"c" (10))

218

    // ����������BCD���ʽ���浽�û��������С�

    // �ú������ȸ��ݸ���ָ�������Ѱַģʽ�ֽ��е����ݺ�info �ṹ�е�ǰ�Ĵ����е����ݣ�

    // ȡ�ñ���������Ч��ַaddr������֤����10�ֽ�BCD����û��ռ䡣Ȼ�����ʱʵ����ʽ

    // �Ľ��ת����BCD���ʽ�����ݲ����浽�û��ڴ��С�����Ǹ�����������ߴ洢�ֽڵ����

    // ��Чλ��

    // ������tmp �C ��ʱʵ����ʽ���ֵ��info �C info�ṹָ�룻code �C ָ����롣

219 void put_BCD(const temp_real * tmp,struct info * info, unsigned short code)

220 {

221         int k,rem;

222         char * addr;

223         temp_int i;

224         unsigned char c;

225

226         addr = ea(info,code);                        // ȡ��Ч��ַ��

227         verify_area(addr,10);                        // ��֤�洢�ռ�������

228         real_to_int(tmp,&i);                         // ת������ʱ������ʽ��

229         if (i.sign)                           // ���Ǹ����������÷����ֽ������Чλ��

230                 put_fs_byte(0x80, addr+9);

231         else                                         // ��������ֽ�����Ϊ0��

232                 put_fs_byte(0, addr+9);

233         for (k = 0; k < 9; k++) {                    // ��ʱ����ת����BCD�벢���档

234                 DIV10(i.a,i.b,rem);

235                 c = rem;

236                 DIV10(i.a,i.b,rem);

237                 c += rem<<4;

238                 put_fs_byte(c,addr++);

239         }

240 }

241