fp_decode.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. /*
  2. * fp_decode.h
  3. *
  4. * Copyright Roman Zippel, 1997. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, and the entire permission notice in its entirety,
  11. * including the disclaimer of warranties.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. The name of the author may not be used to endorse or promote
  16. * products derived from this software without specific prior
  17. * written permission.
  18. *
  19. * ALTERNATIVELY, this product may be distributed under the terms of
  20. * the GNU General Public License, in which case the provisions of the GPL are
  21. * required INSTEAD OF the above restrictions. (This clause is
  22. * necessary due to a potential bad interaction between the GPL and
  23. * the restrictions contained in a BSD-style copyright.)
  24. *
  25. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  26. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  27. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  28. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  29. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  30. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  31. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  33. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  35. * OF THE POSSIBILITY OF SUCH DAMAGE.
  36. */
  37. #ifndef _FP_DECODE_H
  38. #define _FP_DECODE_H
  39. /* These macros do the dirty work of the instr decoding, several variables
  40. * can be defined in the source file to modify the work of these macros,
  41. * currently the following variables are used:
  42. * ...
  43. * The register usage:
  44. * d0 - will contain source operand for data direct mode,
  45. * otherwise scratch register
  46. * d1 - upper 16bit are reserved for caller
  47. * lower 16bit may contain further arguments,
  48. * is destroyed during decoding
  49. * d2 - contains first two instruction words,
  50. * first word will be used for extension word
  51. * a0 - will point to source/dest operand for any indirect mode
  52. * otherwise scratch register
  53. * a1 - scratch register
  54. * a2 - base addr to the task structure
  55. *
  56. * the current implementation doesn't check for every disallowed
  57. * addressing mode (e.g. pc relative modes as destination), as long
  58. * as it only means a new addressing mode, which should not appear
  59. * in a program and that doesn't crash the emulation, I think it's
  60. * not a problem to allow these modes.
  61. */
  62. do_fmovem=0
  63. do_fmovem_cr=0
  64. do_no_pc_mode=0
  65. do_fscc=0
  66. | first decoding of the instr type
  67. | this separates the conditional instr
  68. .macro fp_decode_cond_instr_type
  69. bfextu %d2{#8,#2},%d0
  70. jmp ([0f:w,%pc,%d0*4])
  71. .align 4
  72. 0:
  73. | .long "f<op>","fscc/fdbcc"
  74. | .long "fbccw","fbccl"
  75. .endm
  76. | second decoding of the instr type
  77. | this separates most move instr
  78. .macro fp_decode_move_instr_type
  79. bfextu %d2{#16,#3},%d0
  80. jmp ([0f:w,%pc,%d0*4])
  81. .align 4
  82. 0:
  83. | .long "f<op> fpx,fpx","invalid instr"
  84. | .long "f<op> <ea>,fpx","fmove fpx,<ea>"
  85. | .long "fmovem <ea>,fpcr","fmovem <ea>,fpx"
  86. | .long "fmovem fpcr,<ea>","fmovem fpx,<ea>"
  87. .endm
  88. | extract the source specifier, specifies
  89. | either source fp register or data format
  90. .macro fp_decode_sourcespec
  91. bfextu %d2{#19,#3},%d0
  92. .endm
  93. | decode destination format for fmove reg,ea
  94. .macro fp_decode_dest_format
  95. bfextu %d2{#19,#3},%d0
  96. .endm
  97. | decode source register for fmove reg,ea
  98. .macro fp_decode_src_reg
  99. bfextu %d2{#22,#3},%d0
  100. .endm
  101. | extract the addressing mode
  102. | it depends on the instr which of the modes is valid
  103. .macro fp_decode_addr_mode
  104. bfextu %d2{#10,#3},%d0
  105. jmp ([0f:w,%pc,%d0*4])
  106. .align 4
  107. 0:
  108. | .long "data register direct","addr register direct"
  109. | .long "addr register indirect"
  110. | .long "addr register indirect postincrement"
  111. | .long "addr register indirect predecrement"
  112. | .long "addr register + index16"
  113. | .long "extension mode1","extension mode2"
  114. .endm
  115. | extract the register for the addressing mode
  116. .macro fp_decode_addr_reg
  117. bfextu %d2{#13,#3},%d0
  118. .endm
  119. | decode the 8bit displacement from the brief extension word
  120. .macro fp_decode_disp8
  121. move.b %d2,%d0
  122. ext.w %d0
  123. .endm
  124. | decode the index of the brief/full extension word
  125. .macro fp_decode_index
  126. bfextu %d2{#17,#3},%d0 | get the register nr
  127. btst #15,%d2 | test for data/addr register
  128. jne 1\@f
  129. printf PDECODE,"d%d",1,%d0
  130. jsr fp_get_data_reg
  131. jra 2\@f
  132. 1\@: printf PDECODE,"a%d",1,%d0
  133. jsr fp_get_addr_reg
  134. move.l %a0,%d0
  135. 2\@:
  136. debug lea "'l'.w,%a0"
  137. btst #11,%d2 | 16/32 bit size?
  138. jne 3\@f
  139. debug lea "'w'.w,%a0"
  140. ext.l %d0
  141. 3\@: printf PDECODE,":%c",1,%a0
  142. move.w %d2,%d1 | scale factor
  143. rol.w #7,%d1
  144. and.w #3,%d1
  145. debug move.l "%d1,-(%sp)"
  146. debug ext.l "%d1"
  147. printf PDECODE,":%d",1,%d1
  148. debug move.l "(%sp)+,%d1"
  149. lsl.l %d1,%d0
  150. .endm
  151. | decode the base displacement size
  152. .macro fp_decode_basedisp
  153. bfextu %d2{#26,#2},%d0
  154. jmp ([0f:w,%pc,%d0*4])
  155. .align 4
  156. 0:
  157. | .long "reserved","null displacement"
  158. | .long "word displacement","long displacement"
  159. .endm
  160. .macro fp_decode_outerdisp
  161. bfextu %d2{#30,#2},%d0
  162. jmp ([0f:w,%pc,%d0*4])
  163. .align 4
  164. 0:
  165. | .long "no memory indirect action/reserved","null outer displacement"
  166. | .long "word outer displacement","long outer displacement"
  167. .endm
  168. | get the extension word and test for brief or full extension type
  169. .macro fp_get_test_extword label
  170. fp_get_instr_word %d2,fp_err_ua1
  171. btst #8,%d2
  172. jne \label
  173. .endm
  174. | test if %pc is the base register for the indirect addr mode
  175. .macro fp_test_basereg_d16 label
  176. btst #20,%d2
  177. jeq \label
  178. .endm
  179. | test if %pc is the base register for one of the extended modes
  180. .macro fp_test_basereg_ext label
  181. btst #19,%d2
  182. jeq \label
  183. .endm
  184. .macro fp_test_suppr_index label
  185. btst #6,%d2
  186. jne \label
  187. .endm
  188. | addressing mode: data register direct
  189. .macro fp_mode_data_direct
  190. fp_decode_addr_reg
  191. printf PDECODE,"d%d",1,%d0
  192. .endm
  193. | addressing mode: address register indirect
  194. .macro fp_mode_addr_indirect
  195. fp_decode_addr_reg
  196. printf PDECODE,"(a%d)",1,%d0
  197. jsr fp_get_addr_reg
  198. .endm
  199. | adjust stack for byte moves from/to stack
  200. .macro fp_test_sp_byte_move
  201. .if !do_fmovem
  202. .if do_fscc
  203. move.w #6,%d1
  204. .endif
  205. cmp.w #7,%d0
  206. jne 1\@f
  207. .if !do_fscc
  208. cmp.w #6,%d1
  209. jne 1\@f
  210. .endif
  211. move.w #4,%d1
  212. 1\@:
  213. .endif
  214. .endm
  215. | addressing mode: address register indirect with postincrement
  216. .macro fp_mode_addr_indirect_postinc
  217. fp_decode_addr_reg
  218. printf PDECODE,"(a%d)+",1,%d0
  219. fp_test_sp_byte_move
  220. jsr fp_get_addr_reg
  221. move.l %a0,%a1 | save addr
  222. .if do_fmovem
  223. lea (%a0,%d1.w*4),%a0
  224. .if !do_fmovem_cr
  225. lea (%a0,%d1.w*8),%a0
  226. .endif
  227. .else
  228. add.w (fp_datasize,%d1.w*2),%a0
  229. .endif
  230. jsr fp_put_addr_reg
  231. move.l %a1,%a0
  232. .endm
  233. | addressing mode: address register indirect with predecrement
  234. .macro fp_mode_addr_indirect_predec
  235. fp_decode_addr_reg
  236. printf PDECODE,"-(a%d)",1,%d0
  237. fp_test_sp_byte_move
  238. jsr fp_get_addr_reg
  239. .if do_fmovem
  240. .if !do_fmovem_cr
  241. lea (-12,%a0),%a1 | setup to addr of 1st reg to move
  242. neg.w %d1
  243. lea (%a0,%d1.w*4),%a0
  244. add.w %d1,%d1
  245. lea (%a0,%d1.w*4),%a0
  246. jsr fp_put_addr_reg
  247. move.l %a1,%a0
  248. .else
  249. neg.w %d1
  250. lea (%a0,%d1.w*4),%a0
  251. jsr fp_put_addr_reg
  252. .endif
  253. .else
  254. sub.w (fp_datasize,%d1.w*2),%a0
  255. jsr fp_put_addr_reg
  256. .endif
  257. .endm
  258. | addressing mode: address register/programm counter indirect
  259. | with 16bit displacement
  260. .macro fp_mode_addr_indirect_disp16
  261. .if !do_no_pc_mode
  262. fp_test_basereg_d16 1f
  263. printf PDECODE,"pc"
  264. fp_get_pc %a0
  265. jra 2f
  266. .endif
  267. 1: fp_decode_addr_reg
  268. printf PDECODE,"a%d",1,%d0
  269. jsr fp_get_addr_reg
  270. 2: fp_get_instr_word %a1,fp_err_ua1
  271. printf PDECODE,"@(%x)",1,%a1
  272. add.l %a1,%a0
  273. .endm
  274. | perform preindex (if I/IS == 0xx and xx != 00)
  275. .macro fp_do_preindex
  276. moveq #3,%d0
  277. and.w %d2,%d0
  278. jeq 1f
  279. btst #2,%d2
  280. jne 1f
  281. printf PDECODE,")@("
  282. getuser.l (%a1),%a1,fp_err_ua1,%a1
  283. debug jra "2f"
  284. 1: printf PDECODE,","
  285. 2:
  286. .endm
  287. | perform postindex (if I/IS == 1xx)
  288. .macro fp_do_postindex
  289. btst #2,%d2
  290. jeq 1f
  291. printf PDECODE,")@("
  292. getuser.l (%a1),%a1,fp_err_ua1,%a1
  293. debug jra "2f"
  294. 1: printf PDECODE,","
  295. 2:
  296. .endm
  297. | all other indirect addressing modes will finally end up here
  298. .macro fp_mode_addr_indirect_extmode0
  299. .if !do_no_pc_mode
  300. fp_test_basereg_ext 1f
  301. printf PDECODE,"pc"
  302. fp_get_pc %a0
  303. jra 2f
  304. .endif
  305. 1: fp_decode_addr_reg
  306. printf PDECODE,"a%d",1,%d0
  307. jsr fp_get_addr_reg
  308. 2: move.l %a0,%a1
  309. swap %d2
  310. fp_get_test_extword 3f
  311. | addressing mode: address register/programm counter indirect
  312. | with index and 8bit displacement
  313. fp_decode_disp8
  314. debug ext.l "%d0"
  315. printf PDECODE,"@(%x,",1,%d0
  316. add.w %d0,%a1
  317. fp_decode_index
  318. add.l %d0,%a1
  319. printf PDECODE,")"
  320. jra 9f
  321. 3: | addressing mode: address register/programm counter memory indirect
  322. | with base and/or outer displacement
  323. btst #7,%d2 | base register suppressed?
  324. jeq 1f
  325. printf PDECODE,"!"
  326. sub.l %a1,%a1
  327. 1: printf PDECODE,"@("
  328. fp_decode_basedisp
  329. .long fp_ill,1f
  330. .long 2f,3f
  331. #ifdef FPU_EMU_DEBUG
  332. 1: printf PDECODE,"0" | null base displacement
  333. jra 1f
  334. #endif
  335. 2: fp_get_instr_word %a0,fp_err_ua1 | 16bit base displacement
  336. printf PDECODE,"%x:w",1,%a0
  337. jra 4f
  338. 3: fp_get_instr_long %a0,fp_err_ua1 | 32bit base displacement
  339. printf PDECODE,"%x:l",1,%a0
  340. 4: add.l %a0,%a1
  341. 1:
  342. fp_do_postindex
  343. fp_test_suppr_index 1f
  344. fp_decode_index
  345. add.l %d0,%a1
  346. 1: fp_do_preindex
  347. fp_decode_outerdisp
  348. .long 5f,1f
  349. .long 2f,3f
  350. #ifdef FPU_EMU_DEBUG
  351. 1: printf PDECODE,"0" | null outer displacement
  352. jra 1f
  353. #endif
  354. 2: fp_get_instr_word %a0,fp_err_ua1 | 16bit outer displacement
  355. printf PDECODE,"%x:w",1,%a0
  356. jra 4f
  357. 3: fp_get_instr_long %a0,fp_err_ua1 | 32bit outer displacement
  358. printf PDECODE,"%x:l",1,%a0
  359. 4: add.l %a0,%a1
  360. 1:
  361. 5: printf PDECODE,")"
  362. 9: move.l %a1,%a0
  363. swap %d2
  364. .endm
  365. | get the absolute short address from user space
  366. .macro fp_mode_abs_short
  367. fp_get_instr_word %a0,fp_err_ua1
  368. printf PDECODE,"%x.w",1,%a0
  369. .endm
  370. | get the absolute long address from user space
  371. .macro fp_mode_abs_long
  372. fp_get_instr_long %a0,fp_err_ua1
  373. printf PDECODE,"%x.l",1,%a0
  374. .endm
  375. #endif /* _FP_DECODE_H */