����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