3333
3434#define pop_0 () { FPU_settag0(TAG_Empty); top++; }
3535
36+ /* index is a 5-bit value: (3-bit FPU_modrm.reg field | opcode[2,1]) */
3637static u_char const type_table [32 ] = {
37- _PUSH_ , _PUSH_ , _PUSH_ , _PUSH_ ,
38- _null_ , _null_ , _null_ , _null_ ,
39- _REG0_ , _REG0_ , _REG0_ , _REG0_ ,
40- _REG0_ , _REG0_ , _REG0_ , _REG0_ ,
38+ _PUSH_ , _PUSH_ , _PUSH_ , _PUSH_ , /* /0: d9:fld f32, db:fild m32, dd:fld f64, df:fild m16 */
39+ _null_ , _REG0_ , _REG0_ , _REG0_ , /* /1: d9:undef, db,dd,df:fisttp m32/64/16 */
40+ _REG0_ , _REG0_ , _REG0_ , _REG0_ , /* /2: d9:fst f32, db:fist m32, dd:fst f64, df:fist m16 */
41+ _REG0_ , _REG0_ , _REG0_ , _REG0_ , /* /3: d9:fstp f32, db:fistp m32, dd:fstp f64, df:fistp m16 */
4142 _NONE_ , _null_ , _NONE_ , _PUSH_ ,
4243 _NONE_ , _PUSH_ , _null_ , _PUSH_ ,
4344 _NONE_ , _null_ , _NONE_ , _REG0_ ,
4445 _NONE_ , _REG0_ , _NONE_ , _REG0_
4546};
4647
4748u_char const data_sizes_16 [32 ] = {
48- 4 , 4 , 8 , 2 , 0 , 0 , 0 , 0 ,
49- 4 , 4 , 8 , 2 , 4 , 4 , 8 , 2 ,
49+ 4 , 4 , 8 , 2 ,
50+ 0 , 4 , 8 , 2 , /* /1: d9:undef, db,dd,df:fisttp */
51+ 4 , 4 , 8 , 2 ,
52+ 4 , 4 , 8 , 2 ,
5053 14 , 0 , 94 , 10 , 2 , 10 , 0 , 8 ,
5154 14 , 0 , 94 , 10 , 2 , 10 , 2 , 8
5255};
5356
5457static u_char const data_sizes_32 [32 ] = {
55- 4 , 4 , 8 , 2 , 0 , 0 , 0 , 0 ,
56- 4 , 4 , 8 , 2 , 4 , 4 , 8 , 2 ,
58+ 4 , 4 , 8 , 2 ,
59+ 0 , 4 , 8 , 2 , /* /1: d9:undef, db,dd,df:fisttp */
60+ 4 , 4 , 8 , 2 ,
61+ 4 , 4 , 8 , 2 ,
5762 28 , 0 , 108 , 10 , 2 , 10 , 0 , 8 ,
5863 28 , 0 , 108 , 10 , 2 , 10 , 2 , 8
5964};
@@ -65,6 +70,7 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
6570 FPU_REG * st0_ptr ;
6671 u_char st0_tag = TAG_Empty ; /* This is just to stop a gcc warning. */
6772 u_char loaded_tag ;
73+ int sv_cw ;
6874
6975 st0_ptr = NULL ; /* Initialized just to stop compiler warnings. */
7076
@@ -111,7 +117,8 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
111117 }
112118
113119 switch (type ) {
114- case 000 : /* fld m32real */
120+ /* type is a 5-bit value: (3-bit FPU_modrm.reg field | opcode[2,1]) */
121+ case 000 : /* fld m32real (d9 /0) */
115122 clear_C1 ();
116123 loaded_tag =
117124 FPU_load_single ((float __user * )data_address , & loaded_data );
@@ -123,13 +130,13 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
123130 }
124131 FPU_copy_to_reg0 (& loaded_data , loaded_tag );
125132 break ;
126- case 001 : /* fild m32int */
133+ case 001 : /* fild m32int (db /0) */
127134 clear_C1 ();
128135 loaded_tag =
129136 FPU_load_int32 ((long __user * )data_address , & loaded_data );
130137 FPU_copy_to_reg0 (& loaded_data , loaded_tag );
131138 break ;
132- case 002 : /* fld m64real */
139+ case 002 : /* fld m64real (dd /0) */
133140 clear_C1 ();
134141 loaded_tag =
135142 FPU_load_double ((double __user * )data_address ,
@@ -142,12 +149,44 @@ int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
142149 }
143150 FPU_copy_to_reg0 (& loaded_data , loaded_tag );
144151 break ;
145- case 003 : /* fild m16int */
152+ case 003 : /* fild m16int (df /0) */
146153 clear_C1 ();
147154 loaded_tag =
148155 FPU_load_int16 ((short __user * )data_address , & loaded_data );
149156 FPU_copy_to_reg0 (& loaded_data , loaded_tag );
150157 break ;
158+ /* case 004: undefined (d9 /1) */
159+ /* fisttp are enabled if CPUID(1).ECX(0) "sse3" is set */
160+ case 005 : /* fisttp m32int (db /1) */
161+ clear_C1 ();
162+ sv_cw = control_word ;
163+ control_word |= RC_CHOP ;
164+ if (FPU_store_int32
165+ (st0_ptr , st0_tag , (long __user * )data_address ))
166+ pop_0 (); /* pop only if the number was actually stored
167+ (see the 80486 manual p16-28) */
168+ control_word = sv_cw ;
169+ break ;
170+ case 006 : /* fisttp m64int (dd /1) */
171+ clear_C1 ();
172+ sv_cw = control_word ;
173+ control_word |= RC_CHOP ;
174+ if (FPU_store_int64
175+ (st0_ptr , st0_tag , (long long __user * )data_address ))
176+ pop_0 (); /* pop only if the number was actually stored
177+ (see the 80486 manual p16-28) */
178+ control_word = sv_cw ;
179+ break ;
180+ case 007 : /* fisttp m16int (df /1) */
181+ clear_C1 ();
182+ sv_cw = control_word ;
183+ control_word |= RC_CHOP ;
184+ if (FPU_store_int16
185+ (st0_ptr , st0_tag , (short __user * )data_address ))
186+ pop_0 (); /* pop only if the number was actually stored
187+ (see the 80486 manual p16-28) */
188+ control_word = sv_cw ;
189+ break ;
151190 case 010 : /* fst m32real */
152191 clear_C1 ();
153192 FPU_store_single (st0_ptr , st0_tag ,
0 commit comments