linux/arch/m68k/math-emu/fp_decode.h
<<
>>
Prefs
   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
  65do_fmovem=0
  66do_fmovem_cr=0
  67do_no_pc_mode=0
  68do_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
  770:
  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
  890:
  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
 1190:
 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 displacement 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
 1471\@:    printf  PDECODE,"a%d",1,%d0
 148        jsr     fp_get_addr_reg
 149        move.l  %a0,%d0
 1502\@:
 151debug   lea     "'l'.w,%a0"
 152        btst    #11,%d2                 | 16/32 bit size?
 153        jne     3\@f
 154debug   lea     "'w'.w,%a0"
 155        ext.l   %d0
 1563\@:    printf  PDECODE,":%c",1,%a0
 157        move.w  %d2,%d1                 | scale factor
 158        rol.w   #7,%d1
 159        and.w   #3,%d1
 160debug   move.l  "%d1,-(%sp)"
 161debug   ext.l   "%d1"
 162        printf  PDECODE,":%d",1,%d1
 163debug   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
 1730:
 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
 1830:
 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
 2401\@:
 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
 2981:      fp_decode_addr_reg
 299        printf  PDECODE,"a%d",1,%d0
 300        jsr     fp_get_addr_reg
 3012:      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
 315debug   jra     "2f"
 3161:      printf  PDECODE,","
 3172:
 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
 326debug   jra     "2f"
 3271:      printf  PDECODE,","
 3282:
 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
 3391:      fp_decode_addr_reg
 340        printf  PDECODE,"a%d",1,%d0
 341        jsr     fp_get_addr_reg
 3422:      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
 348debug   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
 3553:      | 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
 3611:      printf  PDECODE,"@("
 362        fp_decode_basedisp
 363
 364        .long   fp_ill,1f
 365        .long   2f,3f
 366
 367#ifdef FPU_EMU_DEBUG
 3681:      printf  PDECODE,"0"             | null base displacement
 369        jra     1f
 370#endif
 3712:      fp_get_instr_word %a0,fp_err_ua1 | 16bit base displacement
 372        printf  PDECODE,"%x:w",1,%a0
 373        jra     4f
 3743:      fp_get_instr_long %a0,fp_err_ua1 | 32bit base displacement
 375        printf  PDECODE,"%x:l",1,%a0
 3764:      add.l   %a0,%a1
 3771:
 378        fp_do_postindex
 379        fp_test_suppr_index 1f
 380        fp_decode_index
 381        add.l   %d0,%a1
 3821:      fp_do_preindex
 383
 384        fp_decode_outerdisp
 385
 386        .long   5f,1f
 387        .long   2f,3f
 388
 389#ifdef FPU_EMU_DEBUG
 3901:      printf  PDECODE,"0"             | null outer displacement
 391        jra     1f
 392#endif
 3932:      fp_get_instr_word %a0,fp_err_ua1 | 16bit outer displacement
 394        printf  PDECODE,"%x:w",1,%a0
 395        jra     4f
 3963:      fp_get_instr_long %a0,fp_err_ua1 | 32bit outer displacement
 397        printf  PDECODE,"%x:l",1,%a0
 3984:      add.l   %a0,%a1
 3991:
 4005:      printf  PDECODE,")"
 4019:      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