load_store.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*---------------------------------------------------------------------------+
  3. | load_store.c |
  4. | |
  5. | This file contains most of the code to interpret the FPU instructions |
  6. | which load and store from user memory. |
  7. | |
  8. | Copyright (C) 1992,1993,1994,1997 |
  9. | W. Metzenthen, 22 Parker St, Ormond, Vic 3163, |
  10. | Australia. E-mail billm@suburbia.net |
  11. | |
  12. | |
  13. +---------------------------------------------------------------------------*/
  14. /*---------------------------------------------------------------------------+
  15. | Note: |
  16. | The file contains code which accesses user memory. |
  17. | Emulator static data may change when user memory is accessed, due to |
  18. | other processes using the emulator while swapping is in progress. |
  19. +---------------------------------------------------------------------------*/
  20. #include <linux/uaccess.h>
  21. #include "fpu_system.h"
  22. #include "exception.h"
  23. #include "fpu_emu.h"
  24. #include "status_w.h"
  25. #include "control_w.h"
  26. #define _NONE_ 0 /* st0_ptr etc not needed */
  27. #define _REG0_ 1 /* Will be storing st(0) */
  28. #define _PUSH_ 3 /* Need to check for space to push onto stack */
  29. #define _null_ 4 /* Function illegal or not implemented */
  30. #define pop_0() { FPU_settag0(TAG_Empty); top++; }
  31. /* index is a 5-bit value: (3-bit FPU_modrm.reg field | opcode[2,1]) */
  32. static u_char const type_table[32] = {
  33. _PUSH_, _PUSH_, _PUSH_, _PUSH_, /* /0: d9:fld f32, db:fild m32, dd:fld f64, df:fild m16 */
  34. _null_, _REG0_, _REG0_, _REG0_, /* /1: d9:undef, db,dd,df:fisttp m32/64/16 */
  35. _REG0_, _REG0_, _REG0_, _REG0_, /* /2: d9:fst f32, db:fist m32, dd:fst f64, df:fist m16 */
  36. _REG0_, _REG0_, _REG0_, _REG0_, /* /3: d9:fstp f32, db:fistp m32, dd:fstp f64, df:fistp m16 */
  37. _NONE_, _null_, _NONE_, _PUSH_,
  38. _NONE_, _PUSH_, _null_, _PUSH_,
  39. _NONE_, _null_, _NONE_, _REG0_,
  40. _NONE_, _REG0_, _NONE_, _REG0_
  41. };
  42. u_char const data_sizes_16[32] = {
  43. 4, 4, 8, 2,
  44. 0, 4, 8, 2, /* /1: d9:undef, db,dd,df:fisttp */
  45. 4, 4, 8, 2,
  46. 4, 4, 8, 2,
  47. 14, 0, 94, 10, 2, 10, 0, 8,
  48. 14, 0, 94, 10, 2, 10, 2, 8
  49. };
  50. static u_char const data_sizes_32[32] = {
  51. 4, 4, 8, 2,
  52. 0, 4, 8, 2, /* /1: d9:undef, db,dd,df:fisttp */
  53. 4, 4, 8, 2,
  54. 4, 4, 8, 2,
  55. 28, 0, 108, 10, 2, 10, 0, 8,
  56. 28, 0, 108, 10, 2, 10, 2, 8
  57. };
  58. int FPU_load_store(u_char type, fpu_addr_modes addr_modes,
  59. void __user * data_address)
  60. {
  61. FPU_REG loaded_data;
  62. FPU_REG *st0_ptr;
  63. u_char st0_tag = TAG_Empty; /* This is just to stop a gcc warning. */
  64. u_char loaded_tag;
  65. int sv_cw;
  66. st0_ptr = NULL; /* Initialized just to stop compiler warnings. */
  67. if (addr_modes.default_mode & PROTECTED) {
  68. if (addr_modes.default_mode == SEG32) {
  69. if (access_limit < data_sizes_32[type])
  70. math_abort(FPU_info, SIGSEGV);
  71. } else if (addr_modes.default_mode == PM16) {
  72. if (access_limit < data_sizes_16[type])
  73. math_abort(FPU_info, SIGSEGV);
  74. }
  75. #ifdef PARANOID
  76. else
  77. EXCEPTION(EX_INTERNAL | 0x140);
  78. #endif /* PARANOID */
  79. }
  80. switch (type_table[type]) {
  81. case _NONE_:
  82. break;
  83. case _REG0_:
  84. st0_ptr = &st(0); /* Some of these instructions pop after
  85. storing */
  86. st0_tag = FPU_gettag0();
  87. break;
  88. case _PUSH_:
  89. {
  90. if (FPU_gettagi(-1) != TAG_Empty) {
  91. FPU_stack_overflow();
  92. return 0;
  93. }
  94. top--;
  95. st0_ptr = &st(0);
  96. }
  97. break;
  98. case _null_:
  99. FPU_illegal();
  100. return 0;
  101. #ifdef PARANOID
  102. default:
  103. EXCEPTION(EX_INTERNAL | 0x141);
  104. return 0;
  105. #endif /* PARANOID */
  106. }
  107. switch (type) {
  108. /* type is a 5-bit value: (3-bit FPU_modrm.reg field | opcode[2,1]) */
  109. case 000: /* fld m32real (d9 /0) */
  110. clear_C1();
  111. loaded_tag =
  112. FPU_load_single((float __user *)data_address, &loaded_data);
  113. if ((loaded_tag == TAG_Special)
  114. && isNaN(&loaded_data)
  115. && (real_1op_NaN(&loaded_data) < 0)) {
  116. top++;
  117. break;
  118. }
  119. FPU_copy_to_reg0(&loaded_data, loaded_tag);
  120. break;
  121. case 001: /* fild m32int (db /0) */
  122. clear_C1();
  123. loaded_tag =
  124. FPU_load_int32((long __user *)data_address, &loaded_data);
  125. FPU_copy_to_reg0(&loaded_data, loaded_tag);
  126. break;
  127. case 002: /* fld m64real (dd /0) */
  128. clear_C1();
  129. loaded_tag =
  130. FPU_load_double((double __user *)data_address,
  131. &loaded_data);
  132. if ((loaded_tag == TAG_Special)
  133. && isNaN(&loaded_data)
  134. && (real_1op_NaN(&loaded_data) < 0)) {
  135. top++;
  136. break;
  137. }
  138. FPU_copy_to_reg0(&loaded_data, loaded_tag);
  139. break;
  140. case 003: /* fild m16int (df /0) */
  141. clear_C1();
  142. loaded_tag =
  143. FPU_load_int16((short __user *)data_address, &loaded_data);
  144. FPU_copy_to_reg0(&loaded_data, loaded_tag);
  145. break;
  146. /* case 004: undefined (d9 /1) */
  147. /* fisttp are enabled if CPUID(1).ECX(0) "sse3" is set */
  148. case 005: /* fisttp m32int (db /1) */
  149. clear_C1();
  150. sv_cw = control_word;
  151. control_word |= RC_CHOP;
  152. if (FPU_store_int32
  153. (st0_ptr, st0_tag, (long __user *)data_address))
  154. pop_0(); /* pop only if the number was actually stored
  155. (see the 80486 manual p16-28) */
  156. control_word = sv_cw;
  157. break;
  158. case 006: /* fisttp m64int (dd /1) */
  159. clear_C1();
  160. sv_cw = control_word;
  161. control_word |= RC_CHOP;
  162. if (FPU_store_int64
  163. (st0_ptr, st0_tag, (long long __user *)data_address))
  164. pop_0(); /* pop only if the number was actually stored
  165. (see the 80486 manual p16-28) */
  166. control_word = sv_cw;
  167. break;
  168. case 007: /* fisttp m16int (df /1) */
  169. clear_C1();
  170. sv_cw = control_word;
  171. control_word |= RC_CHOP;
  172. if (FPU_store_int16
  173. (st0_ptr, st0_tag, (short __user *)data_address))
  174. pop_0(); /* pop only if the number was actually stored
  175. (see the 80486 manual p16-28) */
  176. control_word = sv_cw;
  177. break;
  178. case 010: /* fst m32real */
  179. clear_C1();
  180. FPU_store_single(st0_ptr, st0_tag,
  181. (float __user *)data_address);
  182. break;
  183. case 011: /* fist m32int */
  184. clear_C1();
  185. FPU_store_int32(st0_ptr, st0_tag, (long __user *)data_address);
  186. break;
  187. case 012: /* fst m64real */
  188. clear_C1();
  189. FPU_store_double(st0_ptr, st0_tag,
  190. (double __user *)data_address);
  191. break;
  192. case 013: /* fist m16int */
  193. clear_C1();
  194. FPU_store_int16(st0_ptr, st0_tag, (short __user *)data_address);
  195. break;
  196. case 014: /* fstp m32real */
  197. clear_C1();
  198. if (FPU_store_single
  199. (st0_ptr, st0_tag, (float __user *)data_address))
  200. pop_0(); /* pop only if the number was actually stored
  201. (see the 80486 manual p16-28) */
  202. break;
  203. case 015: /* fistp m32int */
  204. clear_C1();
  205. if (FPU_store_int32
  206. (st0_ptr, st0_tag, (long __user *)data_address))
  207. pop_0(); /* pop only if the number was actually stored
  208. (see the 80486 manual p16-28) */
  209. break;
  210. case 016: /* fstp m64real */
  211. clear_C1();
  212. if (FPU_store_double
  213. (st0_ptr, st0_tag, (double __user *)data_address))
  214. pop_0(); /* pop only if the number was actually stored
  215. (see the 80486 manual p16-28) */
  216. break;
  217. case 017: /* fistp m16int */
  218. clear_C1();
  219. if (FPU_store_int16
  220. (st0_ptr, st0_tag, (short __user *)data_address))
  221. pop_0(); /* pop only if the number was actually stored
  222. (see the 80486 manual p16-28) */
  223. break;
  224. case 020: /* fldenv m14/28byte */
  225. fldenv(addr_modes, (u_char __user *) data_address);
  226. /* Ensure that the values just loaded are not changed by
  227. fix-up operations. */
  228. return 1;
  229. case 022: /* frstor m94/108byte */
  230. frstor(addr_modes, (u_char __user *) data_address);
  231. /* Ensure that the values just loaded are not changed by
  232. fix-up operations. */
  233. return 1;
  234. case 023: /* fbld m80dec */
  235. clear_C1();
  236. loaded_tag = FPU_load_bcd((u_char __user *) data_address);
  237. FPU_settag0(loaded_tag);
  238. break;
  239. case 024: /* fldcw */
  240. RE_ENTRANT_CHECK_OFF;
  241. FPU_access_ok(VERIFY_READ, data_address, 2);
  242. FPU_get_user(control_word,
  243. (unsigned short __user *)data_address);
  244. RE_ENTRANT_CHECK_ON;
  245. if (partial_status & ~control_word & CW_Exceptions)
  246. partial_status |= (SW_Summary | SW_Backward);
  247. else
  248. partial_status &= ~(SW_Summary | SW_Backward);
  249. #ifdef PECULIAR_486
  250. control_word |= 0x40; /* An 80486 appears to always set this bit */
  251. #endif /* PECULIAR_486 */
  252. return 1;
  253. case 025: /* fld m80real */
  254. clear_C1();
  255. loaded_tag =
  256. FPU_load_extended((long double __user *)data_address, 0);
  257. FPU_settag0(loaded_tag);
  258. break;
  259. case 027: /* fild m64int */
  260. clear_C1();
  261. loaded_tag = FPU_load_int64((long long __user *)data_address);
  262. if (loaded_tag == TAG_Error)
  263. return 0;
  264. FPU_settag0(loaded_tag);
  265. break;
  266. case 030: /* fstenv m14/28byte */
  267. fstenv(addr_modes, (u_char __user *) data_address);
  268. return 1;
  269. case 032: /* fsave */
  270. fsave(addr_modes, (u_char __user *) data_address);
  271. return 1;
  272. case 033: /* fbstp m80dec */
  273. clear_C1();
  274. if (FPU_store_bcd
  275. (st0_ptr, st0_tag, (u_char __user *) data_address))
  276. pop_0(); /* pop only if the number was actually stored
  277. (see the 80486 manual p16-28) */
  278. break;
  279. case 034: /* fstcw m16int */
  280. RE_ENTRANT_CHECK_OFF;
  281. FPU_access_ok(VERIFY_WRITE, data_address, 2);
  282. FPU_put_user(control_word,
  283. (unsigned short __user *)data_address);
  284. RE_ENTRANT_CHECK_ON;
  285. return 1;
  286. case 035: /* fstp m80real */
  287. clear_C1();
  288. if (FPU_store_extended
  289. (st0_ptr, st0_tag, (long double __user *)data_address))
  290. pop_0(); /* pop only if the number was actually stored
  291. (see the 80486 manual p16-28) */
  292. break;
  293. case 036: /* fstsw m2byte */
  294. RE_ENTRANT_CHECK_OFF;
  295. FPU_access_ok(VERIFY_WRITE, data_address, 2);
  296. FPU_put_user(status_word(),
  297. (unsigned short __user *)data_address);
  298. RE_ENTRANT_CHECK_ON;
  299. return 1;
  300. case 037: /* fistp m64int */
  301. clear_C1();
  302. if (FPU_store_int64
  303. (st0_ptr, st0_tag, (long long __user *)data_address))
  304. pop_0(); /* pop only if the number was actually stored
  305. (see the 80486 manual p16-28) */
  306. break;
  307. }
  308. return 0;
  309. }