math-emu.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #ifndef _ASM_MATH_EMU_H
  2. #define _ASM_MATH_EMU_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. #if 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_D0)
  122. #define FPS_D1 (PT_D1)
  123. #define FPS_D2 (PT_D2)
  124. #define FPS_A0 (PT_A0)
  125. #define FPS_A1 (PT_A1)
  126. #define FPS_A2 (PT_A2)
  127. #define FPS_SR (PT_SR)
  128. #define FPS_PC (PT_PC)
  129. #define FPS_EA (PT_PC+6)
  130. #define FPS_PC2 (PT_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. .macro movestack nr,arg1,arg2,arg3,arg4,arg5
  190. .if \nr
  191. movestack (\nr-1),\arg2,\arg3,\arg4,\arg5
  192. move.l \arg1,-(%sp)
  193. .endif
  194. .endm
  195. .macro printf bit=-1,string,nr=0,arg1,arg2,arg3,arg4,arg5
  196. #ifdef FPU_EMU_DEBUG
  197. .data
  198. .Lpdata\@:
  199. .string "\string"
  200. .previous
  201. movem.l %d0/%d1/%a0/%a1,-(%sp)
  202. .if \bit+1
  203. #if 0
  204. moveq #\bit,%d0
  205. andw #7,%d0
  206. btst %d0,fp_debugprint+((31-\bit)/8)
  207. #else
  208. btst #\bit,fp_debugprint+((31-\bit)/8)
  209. #endif
  210. jeq .Lpskip\@
  211. .endif
  212. movestack \nr,\arg1,\arg2,\arg3,\arg4,\arg5
  213. pea .Lpdata\@
  214. jsr printk
  215. lea ((\nr+1)*4,%sp),%sp
  216. .Lpskip\@:
  217. movem.l (%sp)+,%d0/%d1/%a0/%a1
  218. #endif
  219. .endm
  220. .macro printx bit,fp
  221. #ifdef FPU_EMU_DEBUG
  222. movem.l %d0/%a0,-(%sp)
  223. lea \fp,%a0
  224. #if 0
  225. moveq #'+',%d0
  226. tst.w (%a0)
  227. jeq .Lx1\@
  228. moveq #'-',%d0
  229. .Lx1\@: printf \bit," %c",1,%d0
  230. move.l (4,%a0),%d0
  231. bclr #31,%d0
  232. jne .Lx2\@
  233. printf \bit,"0."
  234. jra .Lx3\@
  235. .Lx2\@: printf \bit,"1."
  236. .Lx3\@: printf \bit,"%08x%08x",2,%d0,%a0@(8)
  237. move.w (2,%a0),%d0
  238. ext.l %d0
  239. printf \bit,"E%04x",1,%d0
  240. #else
  241. printf \bit," %08x%08x%08x",3,%a0@,%a0@(4),%a0@(8)
  242. #endif
  243. movem.l (%sp)+,%d0/%a0
  244. #endif
  245. .endm
  246. .macro debug instr,args
  247. #ifdef FPU_EMU_DEBUG
  248. \instr \args
  249. #endif
  250. .endm
  251. #endif /* __ASSEMBLY__ */
  252. #endif /* _ASM_FRV_MATH_EMU_H */