math-emu.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. #ifndef _ASM_M68K_SETUP_H
  2. #define _ASM_M68K_SETUP_H
  3. #include <asm/setup.h>
  4. #include <linux/linkage.h>
  5. /* Status Register bits */
  6. /* accrued exception bits */
  7. #define FPSR_AEXC_INEX 3
  8. #define FPSR_AEXC_DZ 4
  9. #define FPSR_AEXC_UNFL 5
  10. #define FPSR_AEXC_OVFL 6
  11. #define FPSR_AEXC_IOP 7
  12. /* exception status bits */
  13. #define FPSR_EXC_INEX1 8
  14. #define FPSR_EXC_INEX2 9
  15. #define FPSR_EXC_DZ 10
  16. #define FPSR_EXC_UNFL 11
  17. #define FPSR_EXC_OVFL 12
  18. #define FPSR_EXC_OPERR 13
  19. #define FPSR_EXC_SNAN 14
  20. #define FPSR_EXC_BSUN 15
  21. /* quotient byte, assumes big-endian, of course */
  22. #define FPSR_QUOTIENT(fpsr) (*((signed char *) &(fpsr) + 1))
  23. /* condition code bits */
  24. #define FPSR_CC_NAN 24
  25. #define FPSR_CC_INF 25
  26. #define FPSR_CC_Z 26
  27. #define FPSR_CC_NEG 27
  28. /* Control register bits */
  29. /* rounding mode */
  30. #define FPCR_ROUND_RN 0 /* round to nearest/even */
  31. #define FPCR_ROUND_RZ 1 /* round to zero */
  32. #define FPCR_ROUND_RM 2 /* minus infinity */
  33. #define FPCR_ROUND_RP 3 /* plus infinity */
  34. /* rounding precision */
  35. #define FPCR_PRECISION_X 0 /* long double */
  36. #define FPCR_PRECISION_S 1 /* double */
  37. #define FPCR_PRECISION_D 2 /* float */
  38. /* Flags to select the debugging output */
  39. #define PDECODE 0
  40. #define PEXECUTE 1
  41. #define PCONV 2
  42. #define PNORM 3
  43. #define PREGISTER 4
  44. #define PINSTR 5
  45. #define PUNIMPL 6
  46. #define PMOVEM 7
  47. #define PMDECODE (1<<PDECODE)
  48. #define PMEXECUTE (1<<PEXECUTE)
  49. #define PMCONV (1<<PCONV)
  50. #define PMNORM (1<<PNORM)
  51. #define PMREGISTER (1<<PREGISTER)
  52. #define PMINSTR (1<<PINSTR)
  53. #define PMUNIMPL (1<<PUNIMPL)
  54. #define PMMOVEM (1<<PMOVEM)
  55. #ifndef __ASSEMBLY__
  56. #include <linux/kernel.h>
  57. #include <linux/sched.h>
  58. union fp_mant64 {
  59. unsigned long long m64;
  60. unsigned long m32[2];
  61. };
  62. union fp_mant128 {
  63. unsigned long long m64[2];
  64. unsigned long m32[4];
  65. };
  66. /* internal representation of extended fp numbers */
  67. struct fp_ext {
  68. unsigned char lowmant;
  69. unsigned char sign;
  70. unsigned short exp;
  71. union fp_mant64 mant;
  72. };
  73. /* C representation of FPU registers */
  74. /* NOTE: if you change this, you have to change the assembler offsets
  75. below and the size in <asm/fpu.h>, too */
  76. struct fp_data {
  77. struct fp_ext fpreg[8];
  78. unsigned int fpcr;
  79. unsigned int fpsr;
  80. unsigned int fpiar;
  81. unsigned short prec;
  82. unsigned short rnd;
  83. struct fp_ext temp[2];
  84. };
  85. #ifdef FPU_EMU_DEBUG
  86. extern unsigned int fp_debugprint;
  87. #define dprint(bit, fmt, args...) ({ \
  88. if (fp_debugprint & (1 << (bit))) \
  89. printk(fmt, ## args); \
  90. })
  91. #else
  92. #define dprint(bit, fmt, args...)
  93. #endif
  94. #define uprint(str) ({ \
  95. static int __count = 3; \
  96. \
  97. if (__count > 0) { \
  98. printk("You just hit an unimplemented " \
  99. "fpu instruction (%s)\n", str); \
  100. printk("Please report this to ....\n"); \
  101. __count--; \
  102. } \
  103. })
  104. #define FPDATA ((struct fp_data *)current->thread.fp)
  105. #else /* __ASSEMBLY__ */
  106. #define FPDATA %a2
  107. /* offsets from the base register to the floating point data in the task struct */
  108. #define FPD_FPREG (TASK_THREAD+THREAD_FPREG+0)
  109. #define FPD_FPCR (TASK_THREAD+THREAD_FPREG+96)
  110. #define FPD_FPSR (TASK_THREAD+THREAD_FPREG+100)
  111. #define FPD_FPIAR (TASK_THREAD+THREAD_FPREG+104)
  112. #define FPD_PREC (TASK_THREAD+THREAD_FPREG+108)
  113. #define FPD_RND (TASK_THREAD+THREAD_FPREG+110)
  114. #define FPD_TEMPFP1 (TASK_THREAD+THREAD_FPREG+112)
  115. #define FPD_TEMPFP2 (TASK_THREAD+THREAD_FPREG+124)
  116. #define FPD_SIZEOF (TASK_THREAD+THREAD_FPREG+136)
  117. /* offsets on the stack to access saved registers,
  118. * these are only used during instruction decoding
  119. * where we always know how deep we're on the stack.
  120. */
  121. #define FPS_DO (PT_OFF_D0)
  122. #define FPS_D1 (PT_OFF_D1)
  123. #define FPS_D2 (PT_OFF_D2)
  124. #define FPS_A0 (PT_OFF_A0)
  125. #define FPS_A1 (PT_OFF_A1)
  126. #define FPS_A2 (PT_OFF_A2)
  127. #define FPS_SR (PT_OFF_SR)
  128. #define FPS_PC (PT_OFF_PC)
  129. #define FPS_EA (PT_OFF_PC+6)
  130. #define FPS_PC2 (PT_OFF_PC+10)
  131. .macro fp_get_fp_reg
  132. lea (FPD_FPREG,FPDATA,%d0.w*4),%a0
  133. lea (%a0,%d0.w*8),%a0
  134. .endm
  135. /* Macros used to get/put the current program counter.
  136. * 020/030 use a different stack frame then 040/060, for the
  137. * 040/060 the return pc points already to the next location,
  138. * so this only needs to be modified for jump instructions.
  139. */
  140. .macro fp_get_pc dest
  141. move.l (FPS_PC+4,%sp),\dest
  142. .endm
  143. .macro fp_put_pc src,jump=0
  144. move.l \src,(FPS_PC+4,%sp)
  145. .endm
  146. .macro fp_get_instr_data f,s,dest,label
  147. getuser \f,%sp@(FPS_PC+4)@(0),\dest,\label,%sp@(FPS_PC+4)
  148. addq.l #\s,%sp@(FPS_PC+4)
  149. .endm
  150. .macro fp_get_instr_word dest,label,addr
  151. fp_get_instr_data w,2,\dest,\label,\addr
  152. .endm
  153. .macro fp_get_instr_long dest,label,addr
  154. fp_get_instr_data l,4,\dest,\label,\addr
  155. .endm
  156. /* These macros are used to read from/write to user space
  157. * on error we jump to the fixup section, load the fault
  158. * address into %a0 and jump to the exit.
  159. * (derived from <asm/uaccess.h>)
  160. */
  161. .macro getuser size,src,dest,label,addr
  162. | printf ,"[\size<%08x]",1,\addr
  163. .Lu1\@: moves\size \src,\dest
  164. .section .fixup,"ax"
  165. .even
  166. .Lu2\@: move.l \addr,%a0
  167. jra \label
  168. .previous
  169. .section __ex_table,"a"
  170. .align 4
  171. .long .Lu1\@,.Lu2\@
  172. .previous
  173. .endm
  174. .macro putuser size,src,dest,label,addr
  175. | printf ,"[\size>%08x]",1,\addr
  176. .Lu1\@: moves\size \src,\dest
  177. .Lu2\@:
  178. .section .fixup,"ax"
  179. .even
  180. .Lu3\@: move.l \addr,%a0
  181. jra \label
  182. .previous
  183. .section __ex_table,"a"
  184. .align 4
  185. .long .Lu1\@,.Lu3\@
  186. .long .Lu2\@,.Lu3\@
  187. .previous
  188. .endm
  189. /* work around binutils idiocy */
  190. old_gas=-1
  191. .irp gas_ident.x .x
  192. old_gas=old_gas+1
  193. .endr
  194. .if !old_gas
  195. .irp m b,w,l
  196. .macro getuser.\m src,dest,label,addr
  197. getuser .\m,\src,\dest,\label,\addr
  198. .endm
  199. .macro putuser.\m src,dest,label,addr
  200. putuser .\m,\src,\dest,\label,\addr
  201. .endm
  202. .endr
  203. .endif
  204. .macro movestack nr,arg1,arg2,arg3,arg4,arg5
  205. .if \nr
  206. movestack (\nr-1),\arg2,\arg3,\arg4,\arg5
  207. move.l \arg1,-(%sp)
  208. .endif
  209. .endm
  210. .macro printf bit=-1,string,nr=0,arg1,arg2,arg3,arg4,arg5
  211. #ifdef FPU_EMU_DEBUG
  212. .data
  213. .Lpdata\@:
  214. .string "\string"
  215. .previous
  216. movem.l %d0/%d1/%a0/%a1,-(%sp)
  217. .if \bit+1
  218. #if 0
  219. moveq #\bit,%d0
  220. andw #7,%d0
  221. btst %d0,fp_debugprint+((31-\bit)/8)
  222. #else
  223. btst #\bit,fp_debugprint+((31-\bit)/8)
  224. #endif
  225. jeq .Lpskip\@
  226. .endif
  227. movestack \nr,\arg1,\arg2,\arg3,\arg4,\arg5
  228. pea .Lpdata\@
  229. jsr printk
  230. lea ((\nr+1)*4,%sp),%sp
  231. .Lpskip\@:
  232. movem.l (%sp)+,%d0/%d1/%a0/%a1
  233. #endif
  234. .endm
  235. .macro printx bit,fp
  236. #ifdef FPU_EMU_DEBUG
  237. movem.l %d0/%a0,-(%sp)
  238. lea \fp,%a0
  239. #if 0
  240. moveq #'+',%d0
  241. tst.w (%a0)
  242. jeq .Lx1\@
  243. moveq #'-',%d0
  244. .Lx1\@: printf \bit," %c",1,%d0
  245. move.l (4,%a0),%d0
  246. bclr #31,%d0
  247. jne .Lx2\@
  248. printf \bit,"0."
  249. jra .Lx3\@
  250. .Lx2\@: printf \bit,"1."
  251. .Lx3\@: printf \bit,"%08x%08x",2,%d0,%a0@(8)
  252. move.w (2,%a0),%d0
  253. ext.l %d0
  254. printf \bit,"E%04x",1,%d0
  255. #else
  256. printf \bit," %08x%08x%08x",3,%a0@,%a0@(4),%a0@(8)
  257. #endif
  258. movem.l (%sp)+,%d0/%a0
  259. #endif
  260. .endm
  261. .macro debug instr,args
  262. #ifdef FPU_EMU_DEBUG
  263. \instr \args
  264. #endif
  265. .endm
  266. #endif /* __ASSEMBLY__ */
  267. #endif /* _ASM_M68K_SETUP_H */