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 38 #ifndef _FP_DECODE_H 39 #define _FP_DECODE_H 40 41 /* These macros do the dirty work of the instr decoding, several variables 42 * can be defined in the source file to modify the work of these macros, 43 * currently the following variables are used: 44 * ... 45 * The register usage: 46 * d0 - will contain source operand for data direct mode, 47 * otherwise scratch register 48 * d1 - upper 16bit are reserved for caller 49 * lower 16bit may contain further arguments, 50 * is destroyed during decoding 51 * d2 - contains first two instruction words, 52 * first word will be used for extension word 53 * a0 - will point to source/dest operand for any indirect mode 54 * otherwise scratch register 55 * a1 - scratch register 56 * a2 - base addr to the task structure 57 * 58 * the current implementation doesn't check for every disallowed 59 * addressing mode (e.g. pc relative modes as destination), as long 60 * as it only means a new addressing mode, which should not appear 61 * in a program and that doesn't crash the emulation, I think it's 62 * not a problem to allow these modes. 63 */ 64 65 do_fmovem=0 66 do_fmovem_cr=0 67 do_no_pc_mode=0 68 do_fscc=0 69 70 | first decoding of the instr type 71 | this separates the conditional instr 72 .macro fp_decode_cond_instr_type 73 bfextu %d2{#8,#2},%d0 74 jmp ([0f:w,%pc,%d0*4]) 75 76 .align 4 77 0: 78 | .long "f<op>","fscc/fdbcc" 79 | .long "fbccw","fbccl" 80 .endm 81 82 | second decoding of the instr type 83 | this separates most move instr 84 .macro fp_decode_move_instr_type 85 bfextu %d2{#16,#3},%d0 86 jmp ([0f:w,%pc,%d0*4]) 87 88 .align 4 89 0: 90 | .long "f<op> fpx,fpx","invalid instr" 91 | .long "f<op> <ea>,fpx","fmove fpx,<ea>" 92 | .long "fmovem <ea>,fpcr","fmovem <ea>,fpx" 93 | .long "fmovem fpcr,<ea>","fmovem fpx,<ea>" 94 .endm 95 96 | extract the source specifier, specifies 97 | either source fp register or data format 98 .macro fp_decode_sourcespec 99 bfextu %d2{#19,#3},%d0 100 .endm 101 102 | decode destination format for fmove reg,ea 103 .macro fp_decode_dest_format 104 bfextu %d2{#19,#3},%d0 105 .endm 106 107 | decode source register for fmove reg,ea 108 .macro fp_decode_src_reg 109 bfextu %d2{#22,#3},%d0 110 .endm 111 112 | extract the addressing mode 113 | it depends on the instr which of the modes is valid 114 .macro fp_decode_addr_mode 115 bfextu %d2{#10,#3},%d0 116 jmp ([0f:w,%pc,%d0*4]) 117 118 .align 4 119 0: 120 | .long "data register direct","addr register direct" 121 | .long "addr register indirect" 122 | .long "addr register indirect postincrement" 123 | .long "addr register indirect predecrement" 124 | .long "addr register + index16" 125 | .long "extension mode1","extension mode2" 126 .endm 127 128 | extract the register for the addressing mode 129 .macro fp_decode_addr_reg 130 bfextu %d2{#13,#3},%d0 131 .endm 132 133 | decode the 8bit diplacement from the brief extension word 134 .macro fp_decode_disp8 135 move.b %d2,%d0 136 ext.w %d0 137 .endm 138 139 | decode the index of the brief/full extension word 140 .macro fp_decode_index 141 bfextu %d2{#17,#3},%d0 | get the register nr 142 btst #15,%d2 | test for data/addr register 143 jne 1\@f 144 printf PDECODE,"d%d",1,%d0 145 jsr fp_get_data_reg 146 jra 2\@f 147 1\@: printf PDECODE,"a%d",1,%d0 148 jsr fp_get_addr_reg 149 move.l %a0,%d0 150 2\@: 151 debug lea "'l'.w,%a0" 152 btst #11,%d2 | 16/32 bit size? 153 jne 3\@f 154 debug lea "'w'.w,%a0" 155 ext.l %d0 156 3\@: printf PDECODE,":%c",1,%a0 157 move.w %d2,%d1 | scale factor 158 rol.w #7,%d1 159 and.w #3,%d1 160 debug move.l "%d1,-(%sp)" 161 debug ext.l "%d1" 162 printf PDECODE,":%d",1,%d1 163 debug move.l "(%sp)+,%d1" 164 lsl.l %d1,%d0 165 .endm 166 167 | decode the base displacement size 168 .macro fp_decode_basedisp 169 bfextu %d2{#26,#2},%d0 170 jmp ([0f:w,%pc,%d0*4]) 171 172 .align 4 173 0: 174 | .long "reserved","null displacement" 175 | .long "word displacement","long displacement" 176 .endm 177 178 .macro fp_decode_outerdisp 179 bfextu %d2{#30,#2},%d0 180 jmp ([0f:w,%pc,%d0*4]) 181 182 .align 4 183 0: 184 | .long "no memory indirect action/reserved","null outer displacement" 185 | .long "word outer displacement","long outer displacement" 186 .endm 187 188 | get the extension word and test for brief or full extension type 189 .macro fp_get_test_extword label 190 fp_get_instr_word %d2,fp_err_ua1 191 btst #8,%d2 192 jne \label 193 .endm 194 195 196 | test if %pc is the base register for the indirect addr mode 197 .macro fp_test_basereg_d16 label 198 btst #20,%d2 199 jeq \label 200 .endm 201 202 | test if %pc is the base register for one of the extended modes 203 .macro fp_test_basereg_ext label 204 btst #19,%d2 205 jeq \label 206 .endm 207 208 .macro fp_test_suppr_index label 209 btst #6,%d2 210 jne \label 211 .endm 212 213 214 | addressing mode: data register direct 215 .macro fp_mode_data_direct 216 fp_decode_addr_reg 217 printf PDECODE,"d%d",1,%d0 218 .endm 219 220 | addressing mode: address register indirect 221 .macro fp_mode_addr_indirect 222 fp_decode_addr_reg 223 printf PDECODE,"(a%d)",1,%d0 224 jsr fp_get_addr_reg 225 .endm 226 227 | adjust stack for byte moves from/to stack 228 .macro fp_test_sp_byte_move 229 .if !do_fmovem 230 .if do_fscc 231 move.w #6,%d1 232 .endif 233 cmp.w #7,%d0 234 jne 1\@f 235 .if !do_fscc 236 cmp.w #6,%d1 237 jne 1\@f 238 .endif 239 move.w #4,%d1 240 1\@: 241 .endif 242 .endm 243 244 | addressing mode: address register indirect with postincrement 245 .macro fp_mode_addr_indirect_postinc 246 fp_decode_addr_reg 247 printf PDECODE,"(a%d)+",1,%d0 248 fp_test_sp_byte_move 249 jsr fp_get_addr_reg 250 move.l %a0,%a1 | save addr 251 .if do_fmovem 252 lea (%a0,%d1.w*4),%a0 253 .if !do_fmovem_cr 254 lea (%a0,%d1.w*8),%a0 255 .endif 256 .else 257 add.w (fp_datasize,%d1.w*2),%a0 258 .endif 259 jsr fp_put_addr_reg 260 move.l %a1,%a0 261 .endm 262 263 | addressing mode: address register indirect with predecrement 264 .macro fp_mode_addr_indirect_predec 265 fp_decode_addr_reg 266 printf PDECODE,"-(a%d)",1,%d0 267 fp_test_sp_byte_move 268 jsr fp_get_addr_reg 269 .if do_fmovem 270 .if !do_fmovem_cr 271 lea (-12,%a0),%a1 | setup to addr of 1st reg to move 272 neg.w %d1 273 lea (%a0,%d1.w*4),%a0 274 add.w %d1,%d1 275 lea (%a0,%d1.w*4),%a0 276 jsr fp_put_addr_reg 277 move.l %a1,%a0 278 .else 279 neg.w %d1 280 lea (%a0,%d1.w*4),%a0 281 jsr fp_put_addr_reg 282 .endif 283 .else 284 sub.w (fp_datasize,%d1.w*2),%a0 285 jsr fp_put_addr_reg 286 .endif 287 .endm 288 289 | addressing mode: address register/programm counter indirect 290 | with 16bit displacement 291 .macro fp_mode_addr_indirect_disp16 292 .if !do_no_pc_mode 293 fp_test_basereg_d16 1f 294 printf PDECODE,"pc" 295 fp_get_pc %a0 296 jra 2f 297 .endif 298 1: fp_decode_addr_reg 299 printf PDECODE,"a%d",1,%d0 300 jsr fp_get_addr_reg 301 2: fp_get_instr_word %a1,fp_err_ua1 302 printf PDECODE,"@(%x)",1,%a1 303 add.l %a1,%a0 304 .endm 305 306 | perform preindex (if I/IS == 0xx and xx != 00) 307 .macro fp_do_preindex 308 moveq #3,%d0 309 and.w %d2,%d0 310 jeq 1f 311 btst #2,%d2 312 jne 1f 313 printf PDECODE,")@(" 314 getuser.l (%a1),%a1,fp_err_ua1,%a1 315 debug jra "2f" 316 1: printf PDECODE,"," 317 2: 318 .endm 319 320 | perform postindex (if I/IS == 1xx) 321 .macro fp_do_postindex 322 btst #2,%d2 323 jeq 1f 324 printf PDECODE,")@(" 325 getuser.l (%a1),%a1,fp_err_ua1,%a1 326 debug jra "2f" 327 1: printf PDECODE,"," 328 2: 329 .endm 330 331 | all other indirect addressing modes will finally end up here 332 .macro fp_mode_addr_indirect_extmode0 333 .if !do_no_pc_mode 334 fp_test_basereg_ext 1f 335 printf PDECODE,"pc" 336 fp_get_pc %a0 337 jra 2f 338 .endif 339 1: fp_decode_addr_reg 340 printf PDECODE,"a%d",1,%d0 341 jsr fp_get_addr_reg 342 2: move.l %a0,%a1 343 swap %d2 344 fp_get_test_extword 3f 345 | addressing mode: address register/programm counter indirect 346 | with index and 8bit displacement 347 fp_decode_disp8 348 debug ext.l "%d0" 349 printf PDECODE,"@(%x,",1,%d0 350 add.w %d0,%a1 351 fp_decode_index 352 add.l %d0,%a1 353 printf PDECODE,")" 354 jra 9f 355 3: | addressing mode: address register/programm counter memory indirect 356 | with base and/or outer displacement 357 btst #7,%d2 | base register suppressed? 358 jeq 1f 359 printf PDECODE,"!" 360 sub.l %a1,%a1 361 1: printf PDECODE,"@(" 362 fp_decode_basedisp 363 364 .long fp_ill,1f 365 .long 2f,3f 366 367 #ifdef FPU_EMU_DEBUG 368 1: printf PDECODE,"0" | null base displacement 369 jra 1f 370 #endif 371 2: fp_get_instr_word %a0,fp_err_ua1 | 16bit base displacement 372 printf PDECODE,"%x:w",1,%a0 373 jra 4f 374 3: fp_get_instr_long %a0,fp_err_ua1 | 32bit base displacement 375 printf PDECODE,"%x:l",1,%a0 376 4: add.l %a0,%a1 377 1: 378 fp_do_postindex 379 fp_test_suppr_index 1f 380 fp_decode_index 381 add.l %d0,%a1 382 1: fp_do_preindex 383 384 fp_decode_outerdisp 385 386 .long 5f,1f 387 .long 2f,3f 388 389 #ifdef FPU_EMU_DEBUG 390 1: printf PDECODE,"0" | null outer displacement 391 jra 1f 392 #endif 393 2: fp_get_instr_word %a0,fp_err_ua1 | 16bit outer displacement 394 printf PDECODE,"%x:w",1,%a0 395 jra 4f 396 3: fp_get_instr_long %a0,fp_err_ua1 | 32bit outer displacement 397 printf PDECODE,"%x:l",1,%a0 398 4: add.l %a0,%a1 399 1: 400 5: printf PDECODE,")" 401 9: move.l %a1,%a0 402 swap %d2 403 .endm 404 405 | get the absolute short address from user space 406 .macro fp_mode_abs_short 407 fp_get_instr_word %a0,fp_err_ua1 408 printf PDECODE,"%x.w",1,%a0 409 .endm 410 411 | get the absolute long address from user space 412 .macro fp_mode_abs_long 413 fp_get_instr_long %a0,fp_err_ua1 414 printf PDECODE,"%x.l",1,%a0 415 .endm 416 417 #endif /* _FP_DECODE_H */ 418