[BACK]Return to isp.s CVS log [TXT][DIR] Up to [local] / sys / arch / m68k / 060sp

Annotation of sys/arch/m68k/060sp/isp.s, Revision 1.1.1.1

1.1       nbrk        1: #
                      2: # $OpenBSD: isp.s,v 1.6 2007/04/10 17:47:54 miod Exp $
                      3: # $NetBSD: isp.s,v 1.2 1996/05/15 19:48:48 is Exp $
                      4: #
                      5:
                      6: #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                      7: # MOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP
                      8: # M68000 Hi-Performance Microprocessor Division
                      9: # M68060 Software Package Production Release
                     10: #
                     11: # M68060 Software Package Copyright (C) 1993, 1994, 1995, 1996 Motorola Inc.
                     12: # All rights reserved.
                     13: #
                     14: # THE SOFTWARE is provided on an "AS IS" basis and without warranty.
                     15: # To the maximum extent permitted by applicable law,
                     16: # MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED,
                     17: # INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS
                     18: # FOR A PARTICULAR PURPOSE and any warranty against infringement with
                     19: # regard to the SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF)
                     20: # and any accompanying written materials.
                     21: #
                     22: # To the maximum extent permitted by applicable law,
                     23: # IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
                     24: # (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
                     25: # BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS)
                     26: # ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
                     27: #
                     28: # Motorola assumes no responsibility for the maintenance and support
                     29: # of the SOFTWARE.
                     30: #
                     31: # You are hereby granted a copyright license to use, modify, and distribute the
                     32: # SOFTWARE so long as this entire notice is retained without alteration
                     33: # in any modified and/or redistributed versions, and that such modified
                     34: # versions are clearly identified as such.
                     35: # No licenses are granted by implication, estoppel or otherwise under any
                     36: # patents or trademarks of Motorola, Inc.
                     37: #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                     38:
                     39: #
                     40: # ireal.s:
                     41: #      This file is appended to the top of the 060ISP package
                     42: # and contains the entry points into the package. The user, in
                     43: # effect, branches to one of the branch table entries located
                     44: # after _060ISP_TABLE.
                     45: #      Also, subroutine stubs exist in this file (_isp_done for
                     46: # example) that are referenced by the ISP package itself in order
                     47: # to call a given routine. The stub routine actually performs the
                     48: # callout. The ISP code does a "bsr" to the stub routine. This
                     49: # extra layer of hierarchy adds a slight performance penalty but
                     50: # it makes the ISP code easier to read and more mainatinable.
                     51: #
                     52:
                     53: set    _off_chk,       0x00
                     54: set    _off_divbyzero, 0x04
                     55: set    _off_trace,     0x08
                     56: set    _off_access,    0x0c
                     57: set    _off_done,      0x10
                     58:
                     59: set    _off_cas,       0x14
                     60: set    _off_cas2,      0x18
                     61: set    _off_lock,      0x1c
                     62: set    _off_unlock,    0x20
                     63:
                     64: set    _off_imr,       0x40
                     65: set    _off_dmr,       0x44
                     66: set    _off_dmw,       0x48
                     67: set    _off_irw,       0x4c
                     68: set    _off_irl,       0x50
                     69: set    _off_drb,       0x54
                     70: set    _off_drw,       0x58
                     71: set    _off_drl,       0x5c
                     72: set    _off_dwb,       0x60
                     73: set    _off_dww,       0x64
                     74: set    _off_dwl,       0x68
                     75:
                     76: _060ISP_TABLE:
                     77:
                     78: # Here's the table of ENTRY POINTS for those linking the package.
                     79:        bra.l           _isp_unimp
                     80:        short           0x0000
                     81:
                     82:        bra.l           _isp_cas
                     83:        short           0x0000
                     84:
                     85:        bra.l           _isp_cas2
                     86:        short           0x0000
                     87:
                     88:        bra.l           _isp_cas_finish
                     89:        short           0x0000
                     90:
                     91:        bra.l           _isp_cas2_finish
                     92:        short           0x0000
                     93:
                     94:        bra.l           _isp_cas_inrange
                     95:        short           0x0000
                     96:
                     97:        bra.l           _isp_cas_terminate
                     98:        short           0x0000
                     99:
                    100:        bra.l           _isp_cas_restart
                    101:        short           0x0000
                    102:
                    103:        space           64
                    104:
                    105: #############################################################
                    106:
                    107:        global          _real_chk
                    108: _real_chk:
                    109:        mov.l           %d0,-(%sp)
                    110:        mov.l           (_060ISP_TABLE-0x80+_off_chk,%pc),%d0
                    111:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    112:        mov.l           0x4(%sp),%d0
                    113:        rtd             &0x4
                    114:
                    115:        global          _real_divbyzero
                    116: _real_divbyzero:
                    117:        mov.l           %d0,-(%sp)
                    118:        mov.l           (_060ISP_TABLE-0x80+_off_divbyzero,%pc),%d0
                    119:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    120:        mov.l           0x4(%sp),%d0
                    121:        rtd             &0x4
                    122:
                    123:        global          _real_trace
                    124: _real_trace:
                    125:        mov.l           %d0,-(%sp)
                    126:        mov.l           (_060ISP_TABLE-0x80+_off_trace,%pc),%d0
                    127:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    128:        mov.l           0x4(%sp),%d0
                    129:        rtd             &0x4
                    130:
                    131:        global          _real_access
                    132: _real_access:
                    133:        mov.l           %d0,-(%sp)
                    134:        mov.l           (_060ISP_TABLE-0x80+_off_access,%pc),%d0
                    135:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    136:        mov.l           0x4(%sp),%d0
                    137:        rtd             &0x4
                    138:
                    139:        global          _isp_done
                    140: _isp_done:
                    141:        mov.l           %d0,-(%sp)
                    142:        mov.l           (_060ISP_TABLE-0x80+_off_done,%pc),%d0
                    143:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    144:        mov.l           0x4(%sp),%d0
                    145:        rtd             &0x4
                    146:
                    147: #######################################
                    148:
                    149:        global          _real_cas
                    150: _real_cas:
                    151:        mov.l           %d0,-(%sp)
                    152:        mov.l           (_060ISP_TABLE-0x80+_off_cas,%pc),%d0
                    153:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    154:        mov.l           0x4(%sp),%d0
                    155:        rtd             &0x4
                    156:
                    157:        global          _real_cas2
                    158: _real_cas2:
                    159:        mov.l           %d0,-(%sp)
                    160:        mov.l           (_060ISP_TABLE-0x80+_off_cas2,%pc),%d0
                    161:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    162:        mov.l           0x4(%sp),%d0
                    163:        rtd             &0x4
                    164:
                    165:        global          _real_lock_page
                    166: _real_lock_page:
                    167:        mov.l           %d0,-(%sp)
                    168:        mov.l           (_060ISP_TABLE-0x80+_off_lock,%pc),%d0
                    169:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    170:        mov.l           0x4(%sp),%d0
                    171:        rtd             &0x4
                    172:
                    173:        global          _real_unlock_page
                    174: _real_unlock_page:
                    175:        mov.l           %d0,-(%sp)
                    176:        mov.l           (_060ISP_TABLE-0x80+_off_unlock,%pc),%d0
                    177:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    178:        mov.l           0x4(%sp),%d0
                    179:        rtd             &0x4
                    180:
                    181: #######################################
                    182:
                    183:        global          _imem_read
                    184: _imem_read:
                    185:        mov.l           %d0,-(%sp)
                    186:        mov.l           (_060ISP_TABLE-0x80+_off_imr,%pc),%d0
                    187:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    188:        mov.l           0x4(%sp),%d0
                    189:        rtd             &0x4
                    190:
                    191:        global          _dmem_read
                    192: _dmem_read:
                    193:        mov.l           %d0,-(%sp)
                    194:        mov.l           (_060ISP_TABLE-0x80+_off_dmr,%pc),%d0
                    195:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    196:        mov.l           0x4(%sp),%d0
                    197:        rtd             &0x4
                    198:
                    199:        global          _dmem_write
                    200: _dmem_write:
                    201:        mov.l           %d0,-(%sp)
                    202:        mov.l           (_060ISP_TABLE-0x80+_off_dmw,%pc),%d0
                    203:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    204:        mov.l           0x4(%sp),%d0
                    205:        rtd             &0x4
                    206:
                    207:        global          _imem_read_word
                    208: _imem_read_word:
                    209:        mov.l           %d0,-(%sp)
                    210:        mov.l           (_060ISP_TABLE-0x80+_off_irw,%pc),%d0
                    211:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    212:        mov.l           0x4(%sp),%d0
                    213:        rtd             &0x4
                    214:
                    215:        global          _imem_read_long
                    216: _imem_read_long:
                    217:        mov.l           %d0,-(%sp)
                    218:        mov.l           (_060ISP_TABLE-0x80+_off_irl,%pc),%d0
                    219:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    220:        mov.l           0x4(%sp),%d0
                    221:        rtd             &0x4
                    222:
                    223:        global          _dmem_read_byte
                    224: _dmem_read_byte:
                    225:        mov.l           %d0,-(%sp)
                    226:        mov.l           (_060ISP_TABLE-0x80+_off_drb,%pc),%d0
                    227:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    228:        mov.l           0x4(%sp),%d0
                    229:        rtd             &0x4
                    230:
                    231:        global          _dmem_read_word
                    232: _dmem_read_word:
                    233:        mov.l           %d0,-(%sp)
                    234:        mov.l           (_060ISP_TABLE-0x80+_off_drw,%pc),%d0
                    235:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    236:        mov.l           0x4(%sp),%d0
                    237:        rtd             &0x4
                    238:
                    239:        global          _dmem_read_long
                    240: _dmem_read_long:
                    241:        mov.l           %d0,-(%sp)
                    242:        mov.l           (_060ISP_TABLE-0x80+_off_drl,%pc),%d0
                    243:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    244:        mov.l           0x4(%sp),%d0
                    245:        rtd             &0x4
                    246:
                    247:        global          _dmem_write_byte
                    248: _dmem_write_byte:
                    249:        mov.l           %d0,-(%sp)
                    250:        mov.l           (_060ISP_TABLE-0x80+_off_dwb,%pc),%d0
                    251:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    252:        mov.l           0x4(%sp),%d0
                    253:        rtd             &0x4
                    254:
                    255:        global          _dmem_write_word
                    256: _dmem_write_word:
                    257:        mov.l           %d0,-(%sp)
                    258:        mov.l           (_060ISP_TABLE-0x80+_off_dww,%pc),%d0
                    259:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    260:        mov.l           0x4(%sp),%d0
                    261:        rtd             &0x4
                    262:
                    263:        global          _dmem_write_long
                    264: _dmem_write_long:
                    265:        mov.l           %d0,-(%sp)
                    266:        mov.l           (_060ISP_TABLE-0x80+_off_dwl,%pc),%d0
                    267:        pea.l           (_060ISP_TABLE-0x80,%pc,%d0)
                    268:        mov.l           0x4(%sp),%d0
                    269:        rtd             &0x4
                    270:
                    271: #
                    272: # This file contains a set of define statements for constants
                    273: # in oreder to promote readability within the core code itself.
                    274: #
                    275:
                    276: set LOCAL_SIZE,                96                      # stack frame size(bytes)
                    277: set LV,                        -LOCAL_SIZE             # stack offset
                    278:
                    279: set EXC_ISR,           0x4                     # stack status register
                    280: set EXC_IPC,           0x6                     # stack pc
                    281: set EXC_IVOFF,         0xa                     # stacked vector offset
                    282:
                    283: set EXC_AREGS,         LV+64                   # offset of all address regs
                    284: set EXC_DREGS,         LV+32                   # offset of all data regs
                    285:
                    286: set EXC_A7,            EXC_AREGS+(7*4)         # offset of a7
                    287: set EXC_A6,            EXC_AREGS+(6*4)         # offset of a6
                    288: set EXC_A5,            EXC_AREGS+(5*4)         # offset of a5
                    289: set EXC_A4,            EXC_AREGS+(4*4)         # offset of a4
                    290: set EXC_A3,            EXC_AREGS+(3*4)         # offset of a3
                    291: set EXC_A2,            EXC_AREGS+(2*4)         # offset of a2
                    292: set EXC_A1,            EXC_AREGS+(1*4)         # offset of a1
                    293: set EXC_A0,            EXC_AREGS+(0*4)         # offset of a0
                    294: set EXC_D7,            EXC_DREGS+(7*4)         # offset of d7
                    295: set EXC_D6,            EXC_DREGS+(6*4)         # offset of d6
                    296: set EXC_D5,            EXC_DREGS+(5*4)         # offset of d5
                    297: set EXC_D4,            EXC_DREGS+(4*4)         # offset of d4
                    298: set EXC_D3,            EXC_DREGS+(3*4)         # offset of d3
                    299: set EXC_D2,            EXC_DREGS+(2*4)         # offset of d2
                    300: set EXC_D1,            EXC_DREGS+(1*4)         # offset of d1
                    301: set EXC_D0,            EXC_DREGS+(0*4)         # offset of d0
                    302:
                    303: set EXC_TEMP,          LV+16                   # offset of temp stack space
                    304:
                    305: set EXC_SAVVAL,                LV+12                   # offset of old areg value
                    306: set EXC_SAVREG,                LV+11                   # offset of old areg index
                    307:
                    308: set SPCOND_FLG,                LV+10                   # offset of spc condition flg
                    309:
                    310: set EXC_CC,            LV+8                    # offset of cc register
                    311: set EXC_EXTWPTR,       LV+4                    # offset of current PC
                    312: set EXC_EXTWORD,       LV+2                    # offset of current ext opword
                    313: set EXC_OPWORD,                LV+0                    # offset of current opword
                    314:
                    315: ###########################
                    316: # SPecial CONDition FLaGs #
                    317: ###########################
                    318: set mia7_flg,          0x04                    # (a7)+ flag
                    319: set mda7_flg,          0x08                    # -(a7) flag
                    320: set ichk_flg,          0x10                    # chk exception flag
                    321: set idbyz_flg,         0x20                    # divbyzero flag
                    322: set restore_flg,       0x40                    # restore -(an)+ flag
                    323: set immed_flg,         0x80                    # immediate data flag
                    324:
                    325: set mia7_bit,          0x2                     # (a7)+ bit
                    326: set mda7_bit,          0x3                     # -(a7) bit
                    327: set ichk_bit,          0x4                     # chk exception bit
                    328: set idbyz_bit,         0x5                     # divbyzero bit
                    329: set restore_bit,       0x6                     # restore -(a7)+ bit
                    330: set immed_bit,         0x7                     # immediate data bit
                    331:
                    332: #########
                    333: # Misc. #
                    334: #########
                    335: set BYTE,              1                       # len(byte) == 1 byte
                    336: set WORD,              2                       # len(word) == 2 bytes
                    337: set LONG,              4                       # len(longword) == 4 bytes
                    338:
                    339: #########################################################################
                    340: # XDEF ****************************************************************        #
                    341: #      _isp_unimp(): 060ISP entry point for Unimplemented Instruction  #
                    342: #                                                                      #
                    343: #      This handler should be the first code executed upon taking the  #
                    344: #      "Unimplemented Integer Instruction" exception in an operating   #
                    345: #      system.                                                         #
                    346: #                                                                      #
                    347: # XREF ****************************************************************        #
                    348: #      _imem_read_{word,long}() - read instruction word/longword       #
                    349: #      _mul64() - emulate 64-bit multiply                              #
                    350: #      _div64() - emulate 64-bit divide                                #
                    351: #      _moveperipheral() - emulate "movep"                             #
                    352: #      _compandset() - emulate misaligned "cas"                        #
                    353: #      _compandset2() - emulate "cas2"                                 #
                    354: #      _chk2_cmp2() - emulate "cmp2" and "chk2"                        #
                    355: #      _isp_done() - "callout" for normal final exit                   #
                    356: #      _real_trace() - "callout" for Trace exception                   #
                    357: #      _real_chk() - "callout" for Chk exception                       #
                    358: #      _real_divbyzero() - "callout" for DZ exception                  #
                    359: #      _real_access() - "callout" for access error exception           #
                    360: #                                                                      #
                    361: # INPUT ***************************************************************        #
                    362: #      - The system stack contains the Unimp Int Instr stack frame     #
                    363: #                                                                      #
                    364: # OUTPUT **************************************************************        #
                    365: #      If Trace exception:                                             #
                    366: #      - The system stack changed to contain Trace exc stack frame     #
                    367: #      If Chk exception:                                               #
                    368: #      - The system stack changed to contain Chk exc stack frame       #
                    369: #      If DZ exception:                                                #
                    370: #      - The system stack changed to contain DZ exc stack frame        #
                    371: #      If access error exception:                                      #
                    372: #      - The system stack changed to contain access err exc stk frame  #
                    373: #      Else:                                                           #
                    374: #      - Results saved as appropriate                                  #
                    375: #                                                                      #
                    376: # ALGORITHM ***********************************************************        #
                    377: #      This handler fetches the first instruction longword from        #
                    378: # memory and decodes it to determine which of the unimplemented                #
                    379: # integer instructions caused this exception. This handler then calls  #
                    380: # one of _mul64(), _div64(), _moveperipheral(), _compandset(),                 #
                    381: # _compandset2(), or _chk2_cmp2() as appropriate.                      #
                    382: #      Some of these instructions, by their nature, may produce other  #
                    383: # types of exceptions. "div" can produce a divide-by-zero exception,   #
                    384: # and "chk2" can cause a "Chk" exception. In both cases, the current   #
                    385: # exception stack frame must be converted to an exception stack frame  #
                    386: # of the correct exception type and an exit must be made through       #
                    387: # _real_divbyzero() or _real_chk() as appropriate. In addition, all    #
                    388: # instructions may be executing while Trace is enabled. If so, then    #
                    389: # a Trace exception stack frame must be created and an exit made       #
                    390: # through _real_trace().                                               #
                    391: #      Meanwhile, if any read or write to memory using the             #
                    392: # _mem_{read,write}() "callout"s returns a failing value, then an      #
                    393: # access error frame must be created and an exit made through          #
                    394: # _real_access().                                                      #
                    395: #      If none of these occur, then a normal exit is made through      #
                    396: # _isp_done().                                                         #
                    397: #                                                                      #
                    398: #      This handler, upon entry, saves almost all user-visible         #
                    399: # address and data registers to the stack. Although this may seem to   #
                    400: # cause excess memory traffic, it was found that due to having to      #
                    401: # access these register files for things like data retrieval and <ea>  #
                    402: # calculations, it was more efficient to have them on the stack where  #
                    403: # they could be accessed by indexing rather than to make subroutine    #
                    404: # calls to retrieve a register of a particular index.                  #
                    405: #                                                                      #
                    406: #########################################################################
                    407:
                    408:        global          _isp_unimp
                    409: _isp_unimp:
                    410:        link.w          %a6,&-LOCAL_SIZE        # create room for stack frame
                    411:
                    412:        movm.l          &0x3fff,EXC_DREGS(%a6)  # store d0-d7/a0-a5
                    413:        mov.l           (%a6),EXC_A6(%a6)       # store a6
                    414:
                    415:        btst            &0x5,EXC_ISR(%a6)       # from s or u mode?
                    416:        bne.b           uieh_s                  # supervisor mode
                    417: uieh_u:
                    418:        mov.l           %usp,%a0                # fetch user stack pointer
                    419:        mov.l           %a0,EXC_A7(%a6)         # store a7
                    420:        bra.b           uieh_cont
                    421: uieh_s:
                    422:        lea             0xc(%a6),%a0
                    423:        mov.l           %a0,EXC_A7(%a6)         # store corrected sp
                    424:
                    425: ###############################################################################
                    426:
                    427: uieh_cont:
                    428:        clr.b           SPCOND_FLG(%a6)         # clear "special case" flag
                    429:
                    430:        mov.w           EXC_ISR(%a6),EXC_CC(%a6) # store cc copy on stack
                    431:        mov.l           EXC_IPC(%a6),EXC_EXTWPTR(%a6) # store extwptr on stack
                    432:
                    433: #
                    434: # fetch the opword and first extension word pointed to by the stacked pc
                    435: # and store them to the stack for now
                    436: #
                    437:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                    438:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                    439:        bsr.l           _imem_read_long         # fetch opword & extword
                    440:        mov.l           %d0,EXC_OPWORD(%a6)     # store extword on stack
                    441:
                    442:
                    443: #########################################################################
                    444: # muls.l       0100 1100 00 |<ea>|     0*** 1100 0000 0***             #
                    445: # mulu.l       0100 1100 00 |<ea>|     0*** 0100 0000 0***             #
                    446: #                                                                      #
                    447: # divs.l       0100 1100 01 |<ea>|     0*** 1100 0000 0***             #
                    448: # divu.l       0100 1100 01 |<ea>|     0*** 0100 0000 0***             #
                    449: #                                                                      #
                    450: # movep.w m2r  0000 ***1 00 001***     | <displacement>  |             #
                    451: # movep.l m2r  0000 ***1 01 001***     | <displacement>  |             #
                    452: # movep.w r2m  0000 ***1 10 001***     | <displacement>  |             #
                    453: # movep.l r2m  0000 ***1 11 001***     | <displacement>  |             #
                    454: #                                                                      #
                    455: # cas.w                0000 1100 11 |<ea>|     0000 000* **00 0***             #
                    456: # cas.l                0000 1110 11 |<ea>|     0000 000* **00 0***             #
                    457: #                                                                      #
                    458: # cas2.w       0000 1100 11 111100     **** 000* **00 0***             #
                    459: #                                      **** 000* **00 0***             #
                    460: # cas2.l       0000 1110 11 111100     **** 000* **00 0***             #
                    461: #                                      **** 000* **00 0***             #
                    462: #                                                                      #
                    463: # chk2.b       0000 0000 11 |<ea>|     **** 1000 0000 0000             #
                    464: # chk2.w       0000 0010 11 |<ea>|     **** 1000 0000 0000             #
                    465: # chk2.l       0000 0100 11 |<ea>|     **** 1000 0000 0000             #
                    466: #                                                                      #
                    467: # cmp2.b       0000 0000 11 |<ea>|     **** 0000 0000 0000             #
                    468: # cmp2.w       0000 0010 11 |<ea>|     **** 0000 0000 0000             #
                    469: # cmp2.l       0000 0100 11 |<ea>|     **** 0000 0000 0000             #
                    470: #########################################################################
                    471:
                    472: #
                    473: # using bit 14 of the operation word, separate into 2 groups:
                    474: # (group1) mul64, div64
                    475: # (group2) movep, chk2, cmp2, cas2, cas
                    476: #
                    477:        btst            &0x1e,%d0               # group1 or group2
                    478:        beq.b           uieh_group2             # go handle group2
                    479:
                    480: #
                    481: # now, w/ group1, make mul64's decode the fastest since it will
                    482: # most likely be used the most.
                    483: #
                    484: uieh_group1:
                    485:        btst            &0x16,%d0               # test for div64
                    486:        bne.b           uieh_div64              # go handle div64
                    487:
                    488: uieh_mul64:
                    489: # mul64() may use ()+ addressing and may, therefore, alter a7
                    490:
                    491:        bsr.l           _mul64                  # _mul64()
                    492:
                    493:        btst            &0x5,EXC_ISR(%a6)       # supervisor mode?
                    494:        beq.w           uieh_done
                    495:        btst            &mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
                    496:        beq.w           uieh_done               # no
                    497:        btst            &0x7,EXC_ISR(%a6)       # is trace enabled?
                    498:        bne.w           uieh_trace_a7           # yes
                    499:        bra.w           uieh_a7                 # no
                    500:
                    501: uieh_div64:
                    502: # div64() may use ()+ addressing and may, therefore, alter a7.
                    503: # div64() may take a divide by zero exception.
                    504:
                    505:        bsr.l           _div64                  # _div64()
                    506:
                    507: # here, we sort out all of the special cases that may have happened.
                    508:        btst            &mia7_bit,SPCOND_FLG(%a6) # was a7 changed?
                    509:        bne.b           uieh_div64_a7           # yes
                    510: uieh_div64_dbyz:
                    511:        btst            &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
                    512:        bne.w           uieh_divbyzero          # yes
                    513:        bra.w           uieh_done               # no
                    514: uieh_div64_a7:
                    515:        btst            &0x5,EXC_ISR(%a6)       # supervisor mode?
                    516:        beq.b           uieh_div64_dbyz         # no
                    517: # here, a7 has been incremented by 4 bytes in supervisor mode. we still
                    518: # may have the following 3 cases:
                    519: #      (i)     (a7)+
                    520: #      (ii)    (a7)+; trace
                    521: #      (iii)   (a7)+; divide-by-zero
                    522: #
                    523:        btst            &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur?
                    524:        bne.w           uieh_divbyzero_a7       # yes
                    525:        tst.b           EXC_ISR(%a6)            # no; is trace enabled?
                    526:        bmi.w           uieh_trace_a7           # yes
                    527:        bra.w           uieh_a7                 # no
                    528:
                    529: #
                    530: # now, w/ group2, make movep's decode the fastest since it will
                    531: # most likely be used the most.
                    532: #
                    533: uieh_group2:
                    534:        btst            &0x18,%d0               # test for not movep
                    535:        beq.b           uieh_not_movep
                    536:
                    537:
                    538:        bsr.l           _moveperipheral         # _movep()
                    539:        bra.w           uieh_done
                    540:
                    541: uieh_not_movep:
                    542:        btst            &0x1b,%d0               # test for chk2,cmp2
                    543:        beq.b           uieh_chk2cmp2           # go handle chk2,cmp2
                    544:
                    545:        swap            %d0                     # put opword in lo word
                    546:        cmpi.b          %d0,&0xfc               # test for cas2
                    547:        beq.b           uieh_cas2               # go handle cas2
                    548:
                    549: uieh_cas:
                    550:
                    551:        bsr.l           _compandset             # _cas()
                    552:
                    553: # the cases of "cas Dc,Du,(a7)+" and "cas Dc,Du,-(a7)" used from supervisor
                    554: # mode are simply not considered valid and therefore are not handled.
                    555:
                    556:        bra.w           uieh_done
                    557:
                    558: uieh_cas2:
                    559:
                    560:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                    561:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                    562:        bsr.l           _imem_read_word         # read extension word
                    563:
                    564:        tst.l           %d1                     # ifetch error?
                    565:        bne.w           isp_iacc                # yes
                    566:
                    567:        bsr.l           _compandset2            # _cas2()
                    568:        bra.w           uieh_done
                    569:
                    570: uieh_chk2cmp2:
                    571: # chk2 may take a chk exception
                    572:
                    573:        bsr.l           _chk2_cmp2              # _chk2_cmp2()
                    574:
                    575: # here we check to see if a chk trap should be taken
                    576:        cmpi.b          SPCOND_FLG(%a6),&ichk_flg
                    577:        bne.w           uieh_done
                    578:        bra.b           uieh_chk_trap
                    579:
                    580: ###########################################################################
                    581:
                    582: #
                    583: # the required emulation has been completed. now, clean up the necessary stack
                    584: # info and prepare for rte
                    585: #
                    586: uieh_done:
                    587:        mov.b           EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
                    588:
                    589: # if exception occurred in user mode, then we have to restore a7 in case it
                    590: # changed. we don't have to update a7  for supervisor mose because that case
                    591: # doesn't flow through here
                    592:        btst            &0x5,EXC_ISR(%a6)       # user or supervisor?
                    593:        bne.b           uieh_finish             # supervisor
                    594:
                    595:        mov.l           EXC_A7(%a6),%a0         # fetch user stack pointer
                    596:        mov.l           %a0,%usp                # restore it
                    597:
                    598: uieh_finish:
                    599:        movm.l          EXC_DREGS(%a6),&0x3fff  # restore d0-d7/a0-a5
                    600:
                    601:        btst            &0x7,EXC_ISR(%a6)       # is trace mode on?
                    602:        bne.b           uieh_trace              # yes;go handle trace mode
                    603:
                    604:        mov.l           EXC_EXTWPTR(%a6),EXC_IPC(%a6) # new pc on stack frame
                    605:        mov.l           EXC_A6(%a6),(%a6)       # prepare new a6 for unlink
                    606:        unlk            %a6                     # unlink stack frame
                    607:        bra.l           _isp_done
                    608:
                    609: #
                    610: # The instruction that was just emulated was also being traced. The trace
                    611: # trap for this instruction will be lost unless we jump to the trace handler.
                    612: # So, here we create a Trace Exception format number two exception stack
                    613: # frame from the Unimplemented Integer Intruction Exception stack frame
                    614: # format number zero and jump to the user supplied hook "_real_trace()".
                    615: #
                    616: #                 UIEH FRAME              TRACE FRAME
                    617: #              *****************       *****************
                    618: #              * 0x0 *  0x0f4  *       *    Current    *
                    619: #              *****************       *      PC       *
                    620: #              *    Current    *       *****************
                    621: #              *      PC       *       * 0x2 *  0x024  *
                    622: #              *****************       *****************
                    623: #              *      SR       *       *     Next      *
                    624: #              *****************       *      PC       *
                    625: #            ->*     Old       *       *****************
                    626: #  from link -->*      A6      *       *      SR       *
                    627: #              *****************       *****************
                    628: #             /*      A7       *       *      New      * <-- for final unlink
                    629: #            / *               *       *      A6       *
                    630: # link frame <  *****************      *****************
                    631: #            \ ~               ~       ~               ~
                    632: #             \*****************       *****************
                    633: #
                    634: uieh_trace:
                    635:        mov.l           EXC_A6(%a6),-0x4(%a6)
                    636:        mov.w           EXC_ISR(%a6),0x0(%a6)
                    637:        mov.l           EXC_IPC(%a6),0x8(%a6)
                    638:        mov.l           EXC_EXTWPTR(%a6),0x2(%a6)
                    639:        mov.w           &0x2024,0x6(%a6)
                    640:        sub.l           &0x4,%a6
                    641:        unlk            %a6
                    642:        bra.l           _real_trace
                    643:
                    644: #
                    645: #         UIEH FRAME               CHK FRAME
                    646: #      *****************       *****************
                    647: #      * 0x0 *  0x0f4  *       *    Current    *
                    648: #      *****************       *      PC       *
                    649: #      *    Current    *       *****************
                    650: #      *      PC       *       * 0x2 *  0x018  *
                    651: #      *****************       *****************
                    652: #      *      SR       *       *     Next      *
                    653: #      *****************       *      PC       *
                    654: #          (4 words)           *****************
                    655: #                              *      SR       *
                    656: #                              *****************
                    657: #                                  (6 words)
                    658: #
                    659: # the chk2 instruction should take a chk trap. so, here we must create a
                    660: # chk stack frame from an unimplemented integer instruction exception frame
                    661: # and jump to the user supplied entry point "_real_chk()".
                    662: #
                    663: uieh_chk_trap:
                    664:        mov.b           EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
                    665:        movm.l          EXC_DREGS(%a6),&0x3fff  # restore d0-d7/a0-a5
                    666:
                    667:        mov.w           EXC_ISR(%a6),(%a6)      # put new SR on stack
                    668:        mov.l           EXC_IPC(%a6),0x8(%a6)   # put "Current PC" on stack
                    669:        mov.l           EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
                    670:        mov.w           &0x2018,0x6(%a6)        # put Vector Offset on stack
                    671:
                    672:        mov.l           EXC_A6(%a6),%a6         # restore a6
                    673:        add.l           &LOCAL_SIZE,%sp         # clear stack frame
                    674:
                    675:        bra.l           _real_chk
                    676:
                    677: #
                    678: #         UIEH FRAME            DIVBYZERO FRAME
                    679: #      *****************       *****************
                    680: #      * 0x0 *  0x0f4  *       *    Current    *
                    681: #      *****************       *      PC       *
                    682: #      *    Current    *       *****************
                    683: #      *      PC       *       * 0x2 *  0x014  *
                    684: #      *****************       *****************
                    685: #      *      SR       *       *     Next      *
                    686: #      *****************       *      PC       *
                    687: #          (4 words)           *****************
                    688: #                              *      SR       *
                    689: #                              *****************
                    690: #                                  (6 words)
                    691: #
                    692: # the divide instruction should take an integer divide by zero trap. so, here
                    693: # we must create a divbyzero stack frame from an unimplemented integer
                    694: # instruction exception frame and jump to the user supplied entry point
                    695: # "_real_divbyzero()".
                    696: #
                    697: uieh_divbyzero:
                    698:        mov.b           EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
                    699:        movm.l          EXC_DREGS(%a6),&0x3fff  # restore d0-d7/a0-a5
                    700:
                    701:        mov.w           EXC_ISR(%a6),(%a6)      # put new SR on stack
                    702:        mov.l           EXC_IPC(%a6),0x8(%a6)   # put "Current PC" on stack
                    703:        mov.l           EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack
                    704:        mov.w           &0x2014,0x6(%a6)        # put Vector Offset on stack
                    705:
                    706:        mov.l           EXC_A6(%a6),%a6         # restore a6
                    707:        add.l           &LOCAL_SIZE,%sp         # clear stack frame
                    708:
                    709:        bra.l           _real_divbyzero
                    710:
                    711: #
                    712: #                               DIVBYZERO FRAME
                    713: #                              *****************
                    714: #                              *    Current    *
                    715: #         UIEH FRAME           *      PC       *
                    716: #      *****************       *****************
                    717: #      * 0x0 *  0x0f4  *       * 0x2 * 0x014   *
                    718: #      *****************       *****************
                    719: #      *    Current    *       *     Next      *
                    720: #      *      PC       *       *      PC       *
                    721: #      *****************       *****************
                    722: #      *      SR       *       *      SR       *
                    723: #      *****************       *****************
                    724: #          (4 words)               (6 words)
                    725: #
                    726: # the divide instruction should take an integer divide by zero trap. so, here
                    727: # we must create a divbyzero stack frame from an unimplemented integer
                    728: # instruction exception frame and jump to the user supplied entry point
                    729: # "_real_divbyzero()".
                    730: #
                    731: # However, we must also deal with the fact that (a7)+ was used from supervisor
                    732: # mode, thereby shifting the stack frame up 4 bytes.
                    733: #
                    734: uieh_divbyzero_a7:
                    735:        mov.b           EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
                    736:        movm.l          EXC_DREGS(%a6),&0x3fff  # restore d0-d7/a0-a5
                    737:
                    738:        mov.l           EXC_IPC(%a6),0xc(%a6)   # put "Current PC" on stack
                    739:        mov.w           &0x2014,0xa(%a6)        # put Vector Offset on stack
                    740:        mov.l           EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
                    741:
                    742:        mov.l           EXC_A6(%a6),%a6         # restore a6
                    743:        add.l           &4+LOCAL_SIZE,%sp       # clear stack frame
                    744:
                    745:        bra.l           _real_divbyzero
                    746:
                    747: #
                    748: #                                 TRACE FRAME
                    749: #                              *****************
                    750: #                              *    Current    *
                    751: #         UIEH FRAME           *      PC       *
                    752: #      *****************       *****************
                    753: #      * 0x0 *  0x0f4  *       * 0x2 * 0x024   *
                    754: #      *****************       *****************
                    755: #      *    Current    *       *     Next      *
                    756: #      *      PC       *       *      PC       *
                    757: #      *****************       *****************
                    758: #      *      SR       *       *      SR       *
                    759: #      *****************       *****************
                    760: #          (4 words)               (6 words)
                    761: #
                    762: #
                    763: # The instruction that was just emulated was also being traced. The trace
                    764: # trap for this instruction will be lost unless we jump to the trace handler.
                    765: # So, here we create a Trace Exception format number two exception stack
                    766: # frame from the Unimplemented Integer Intruction Exception stack frame
                    767: # format number zero and jump to the user supplied hook "_real_trace()".
                    768: #
                    769: # However, we must also deal with the fact that (a7)+ was used from supervisor
                    770: # mode, thereby shifting the stack frame up 4 bytes.
                    771: #
                    772: uieh_trace_a7:
                    773:        mov.b           EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
                    774:        movm.l          EXC_DREGS(%a6),&0x3fff  # restore d0-d7/a0-a5
                    775:
                    776:        mov.l           EXC_IPC(%a6),0xc(%a6)   # put "Current PC" on stack
                    777:        mov.w           &0x2024,0xa(%a6)        # put Vector Offset on stack
                    778:        mov.l           EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack
                    779:
                    780:        mov.l           EXC_A6(%a6),%a6         # restore a6
                    781:        add.l           &4+LOCAL_SIZE,%sp       # clear stack frame
                    782:
                    783:        bra.l           _real_trace
                    784:
                    785: #
                    786: #                                 UIEH FRAME
                    787: #                              *****************
                    788: #                              * 0x0 * 0x0f4   *
                    789: #         UIEH FRAME           *****************
                    790: #      *****************       *     Next      *
                    791: #      * 0x0 *  0x0f4  *       *      PC       *
                    792: #      *****************       *****************
                    793: #      *    Current    *       *      SR       *
                    794: #      *      PC       *       *****************
                    795: #      *****************           (4 words)
                    796: #      *      SR       *
                    797: #      *****************
                    798: #          (4 words)
                    799: uieh_a7:
                    800:        mov.b           EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes
                    801:        movm.l          EXC_DREGS(%a6),&0x3fff  # restore d0-d7/a0-a5
                    802:
                    803:        mov.w           &0x00f4,0xe(%a6)        # put Vector Offset on stack
                    804:        mov.l           EXC_EXTWPTR(%a6),0xa(%a6) # put "Next PC" on stack
                    805:        mov.w           EXC_ISR(%a6),0x8(%a6)   # put SR on stack
                    806:
                    807:        mov.l           EXC_A6(%a6),%a6         # restore a6
                    808:        add.l           &8+LOCAL_SIZE,%sp       # clear stack frame
                    809:        bra.l           _isp_done
                    810:
                    811: ##########
                    812:
                    813: # this is the exit point if a data read or write fails.
                    814: # a0 = failing address
                    815: # d0 = fslw
                    816: isp_dacc:
                    817:        mov.l           %a0,(%a6)               # save address
                    818:        mov.l           %d0,-0x4(%a6)           # save partial fslw
                    819:
                    820:        lea             -64(%a6),%sp
                    821:        movm.l          (%sp)+,&0x7fff          # restore d0-d7/a0-a6
                    822:
                    823:        mov.l           0xc(%sp),-(%sp)         # move voff,hi(pc)
                    824:        mov.l           0x4(%sp),0x10(%sp)      # store fslw
                    825:        mov.l           0xc(%sp),0x4(%sp)       # store sr,lo(pc)
                    826:        mov.l           0x8(%sp),0xc(%sp)       # store address
                    827:        mov.l           (%sp)+,0x4(%sp)         # store voff,hi(pc)
                    828:        mov.w           &0x4008,0x6(%sp)        # store new voff
                    829:
                    830:        bra.b           isp_acc_exit
                    831:
                    832: # this is the exit point if an instruction word read fails.
                    833: # FSLW:
                    834: #      misaligned = true
                    835: #      read = true
                    836: #      size = word
                    837: #      instruction = true
                    838: #      software emulation error = true
                    839: isp_iacc:
                    840:        movm.l          EXC_DREGS(%a6),&0x3fff  # restore d0-d7/a0-a5
                    841:        unlk            %a6                     # unlink frame
                    842:        sub.w           &0x8,%sp                # make room for acc frame
                    843:        mov.l           0x8(%sp),(%sp)          # store sr,lo(pc)
                    844:        mov.w           0xc(%sp),0x4(%sp)       # store hi(pc)
                    845:        mov.w           &0x4008,0x6(%sp)        # store new voff
                    846:        mov.l           0x2(%sp),0x8(%sp)       # store address (=pc)
                    847:        mov.l           &0x09428001,0xc(%sp)    # store fslw
                    848:
                    849: isp_acc_exit:
                    850:        btst            &0x5,(%sp)              # user or supervisor?
                    851:        beq.b           isp_acc_exit2           # user
                    852:        bset            &0x2,0xd(%sp)           # set supervisor TM bit
                    853: isp_acc_exit2:
                    854:        bra.l           _real_access
                    855:
                    856: # if the addressing mode was (an)+ or -(an), the address register must
                    857: # be restored to its pre-exception value before entering _real_access.
                    858: isp_restore:
                    859:        cmpi.b          SPCOND_FLG(%a6),&restore_flg # do we need a restore?
                    860:        bne.b           isp_restore_done        # no
                    861:        clr.l           %d0
                    862:        mov.b           EXC_SAVREG(%a6),%d0     # regno to restore
                    863:        mov.l           EXC_SAVVAL(%a6),(EXC_AREGS,%a6,%d0.l*4) # restore value
                    864: isp_restore_done:
                    865:        rts
                    866:
                    867: #########################################################################
                    868: # XDEF ****************************************************************        #
                    869: #      _calc_ea(): routine to calculate effective address              #
                    870: #                                                                      #
                    871: # XREF ****************************************************************        #
                    872: #      _imem_read_word() - read instruction word                       #
                    873: #      _imem_read_long() - read instruction longword                   #
                    874: #      _dmem_read_long() - read data longword (for memory indirect)    #
                    875: #      isp_iacc() - handle instruction access error exception          #
                    876: #      isp_dacc() - handle data access error exception                 #
                    877: #                                                                      #
                    878: # INPUT ***************************************************************        #
                    879: #      d0 = number of bytes related to effective address (w,l)         #
                    880: #                                                                      #
                    881: # OUTPUT **************************************************************        #
                    882: #      If exiting through isp_dacc...                                  #
                    883: #              a0 = failing address                                    #
                    884: #              d0 = FSLW                                               #
                    885: #      elsif exiting though isp_iacc...                                #
                    886: #              none                                                    #
                    887: #      else                                                            #
                    888: #              a0 = effective address                                  #
                    889: #                                                                      #
                    890: # ALGORITHM ***********************************************************        #
                    891: #      The effective address type is decoded from the opword residing  #
                    892: # on the stack. A jump table is used to vector to a routine for the    #
                    893: # appropriate mode. Since none of the emulated integer instructions    #
                    894: # uses byte-sized operands, only handle word and long operations.      #
                    895: #                                                                      #
                    896: #      Dn,An   - shouldn't enter here                                  #
                    897: #      (An)    - fetch An value from stack                             #
                    898: #      -(An)   - fetch An value from stack; return decr value;         #
                    899: #                place decr value on stack; store old value in case of #
                    900: #                future access error; if -(a7), set mda7_flg in        #
                    901: #                SPCOND_FLG                                            #
                    902: #      (An)+   - fetch An value from stack; return value;              #
                    903: #                place incr value on stack; store old value in case of #
                    904: #                future access error; if (a7)+, set mia7_flg in        #
                    905: #                SPCOND_FLG                                            #
                    906: #      (d16,An) - fetch An value from stack; read d16 using            #
                    907: #                _imem_read_word(); fetch may fail -> branch to        #
                    908: #                isp_iacc()                                            #
                    909: #      (xxx).w,(xxx).l - use _imem_read_{word,long}() to fetch         #
                    910: #                address; fetch may fail                               #
                    911: #      #<data> - return address of immediate value; set immed_flg      #
                    912: #                in SPCOND_FLG                                         #
                    913: #      (d16,PC) - fetch stacked PC value; read d16 using               #
                    914: #                _imem_read_word(); fetch may fail -> branch to        #
                    915: #                isp_iacc()                                            #
                    916: #      everything else - read needed displacements as appropriate w/   #
                    917: #                _imem_read_{word,long}(); read may fail; if memory    #
                    918: #                indirect, read indirect address using                 #
                    919: #                _dmem_read_long() which may also fail                 #
                    920: #                                                                      #
                    921: #########################################################################
                    922:
                    923:        global          _calc_ea
                    924: _calc_ea:
                    925:        mov.l           %d0,%a0                 # move # bytes to a0
                    926:
                    927: # MODE and REG are taken from the EXC_OPWORD.
                    928:        mov.w           EXC_OPWORD(%a6),%d0     # fetch opcode word
                    929:        mov.w           %d0,%d1                 # make a copy
                    930:
                    931:        andi.w          &0x3f,%d0               # extract mode field
                    932:        andi.l          &0x7,%d1                # extract reg  field
                    933:
                    934: # jump to the corresponding function for each {MODE,REG} pair.
                    935:        mov.w           (tbl_ea_mode.b,%pc,%d0.w*2), %d0 # fetch jmp distance
                    936:        jmp             (tbl_ea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode
                    937:
                    938:        swbeg           &64
                    939: tbl_ea_mode:
                    940:        short           tbl_ea_mode     -       tbl_ea_mode
                    941:        short           tbl_ea_mode     -       tbl_ea_mode
                    942:        short           tbl_ea_mode     -       tbl_ea_mode
                    943:        short           tbl_ea_mode     -       tbl_ea_mode
                    944:        short           tbl_ea_mode     -       tbl_ea_mode
                    945:        short           tbl_ea_mode     -       tbl_ea_mode
                    946:        short           tbl_ea_mode     -       tbl_ea_mode
                    947:        short           tbl_ea_mode     -       tbl_ea_mode
                    948:
                    949:        short           tbl_ea_mode     -       tbl_ea_mode
                    950:        short           tbl_ea_mode     -       tbl_ea_mode
                    951:        short           tbl_ea_mode     -       tbl_ea_mode
                    952:        short           tbl_ea_mode     -       tbl_ea_mode
                    953:        short           tbl_ea_mode     -       tbl_ea_mode
                    954:        short           tbl_ea_mode     -       tbl_ea_mode
                    955:        short           tbl_ea_mode     -       tbl_ea_mode
                    956:        short           tbl_ea_mode     -       tbl_ea_mode
                    957:
                    958:        short           addr_ind_a0     -       tbl_ea_mode
                    959:        short           addr_ind_a1     -       tbl_ea_mode
                    960:        short           addr_ind_a2     -       tbl_ea_mode
                    961:        short           addr_ind_a3     -       tbl_ea_mode
                    962:        short           addr_ind_a4     -       tbl_ea_mode
                    963:        short           addr_ind_a5     -       tbl_ea_mode
                    964:        short           addr_ind_a6     -       tbl_ea_mode
                    965:        short           addr_ind_a7     -       tbl_ea_mode
                    966:
                    967:        short           addr_ind_p_a0   -       tbl_ea_mode
                    968:        short           addr_ind_p_a1   -       tbl_ea_mode
                    969:        short           addr_ind_p_a2   -       tbl_ea_mode
                    970:        short           addr_ind_p_a3   -       tbl_ea_mode
                    971:        short           addr_ind_p_a4   -       tbl_ea_mode
                    972:        short           addr_ind_p_a5   -       tbl_ea_mode
                    973:        short           addr_ind_p_a6   -       tbl_ea_mode
                    974:        short           addr_ind_p_a7   -       tbl_ea_mode
                    975:
                    976:        short           addr_ind_m_a0           -       tbl_ea_mode
                    977:        short           addr_ind_m_a1           -       tbl_ea_mode
                    978:        short           addr_ind_m_a2           -       tbl_ea_mode
                    979:        short           addr_ind_m_a3           -       tbl_ea_mode
                    980:        short           addr_ind_m_a4           -       tbl_ea_mode
                    981:        short           addr_ind_m_a5           -       tbl_ea_mode
                    982:        short           addr_ind_m_a6           -       tbl_ea_mode
                    983:        short           addr_ind_m_a7           -       tbl_ea_mode
                    984:
                    985:        short           addr_ind_disp_a0        -       tbl_ea_mode
                    986:        short           addr_ind_disp_a1        -       tbl_ea_mode
                    987:        short           addr_ind_disp_a2        -       tbl_ea_mode
                    988:        short           addr_ind_disp_a3        -       tbl_ea_mode
                    989:        short           addr_ind_disp_a4        -       tbl_ea_mode
                    990:        short           addr_ind_disp_a5        -       tbl_ea_mode
                    991:        short           addr_ind_disp_a6        -       tbl_ea_mode
                    992:        short           addr_ind_disp_a7        -       tbl_ea_mode
                    993:
                    994:        short           _addr_ind_ext           -       tbl_ea_mode
                    995:        short           _addr_ind_ext           -       tbl_ea_mode
                    996:        short           _addr_ind_ext           -       tbl_ea_mode
                    997:        short           _addr_ind_ext           -       tbl_ea_mode
                    998:        short           _addr_ind_ext           -       tbl_ea_mode
                    999:        short           _addr_ind_ext           -       tbl_ea_mode
                   1000:        short           _addr_ind_ext           -       tbl_ea_mode
                   1001:        short           _addr_ind_ext           -       tbl_ea_mode
                   1002:
                   1003:        short           abs_short               -       tbl_ea_mode
                   1004:        short           abs_long                -       tbl_ea_mode
                   1005:        short           pc_ind                  -       tbl_ea_mode
                   1006:        short           pc_ind_ext              -       tbl_ea_mode
                   1007:        short           immediate               -       tbl_ea_mode
                   1008:        short           tbl_ea_mode             -       tbl_ea_mode
                   1009:        short           tbl_ea_mode             -       tbl_ea_mode
                   1010:        short           tbl_ea_mode             -       tbl_ea_mode
                   1011:
                   1012: ###################################
                   1013: # Address register indirect: (An) #
                   1014: ###################################
                   1015: addr_ind_a0:
                   1016:        mov.l           EXC_A0(%a6),%a0         # Get current a0
                   1017:        rts
                   1018:
                   1019: addr_ind_a1:
                   1020:        mov.l           EXC_A1(%a6),%a0         # Get current a1
                   1021:        rts
                   1022:
                   1023: addr_ind_a2:
                   1024:        mov.l           EXC_A2(%a6),%a0         # Get current a2
                   1025:        rts
                   1026:
                   1027: addr_ind_a3:
                   1028:        mov.l           EXC_A3(%a6),%a0         # Get current a3
                   1029:        rts
                   1030:
                   1031: addr_ind_a4:
                   1032:        mov.l           EXC_A4(%a6),%a0         # Get current a4
                   1033:        rts
                   1034:
                   1035: addr_ind_a5:
                   1036:        mov.l           EXC_A5(%a6),%a0         # Get current a5
                   1037:        rts
                   1038:
                   1039: addr_ind_a6:
                   1040:        mov.l           EXC_A6(%a6),%a0         # Get current a6
                   1041:        rts
                   1042:
                   1043: addr_ind_a7:
                   1044:        mov.l           EXC_A7(%a6),%a0         # Get current a7
                   1045:        rts
                   1046:
                   1047: #####################################################
                   1048: # Address register indirect w/ postincrement: (An)+ #
                   1049: #####################################################
                   1050: addr_ind_p_a0:
                   1051:        mov.l           %a0,%d0                 # copy no. bytes
                   1052:        mov.l           EXC_A0(%a6),%a0         # load current value
                   1053:        add.l           %a0,%d0                 # increment
                   1054:        mov.l           %d0,EXC_A0(%a6)         # save incremented value
                   1055:
                   1056:        mov.l           %a0,EXC_SAVVAL(%a6)     # save in case of access error
                   1057:        mov.b           &0x0,EXC_SAVREG(%a6)    # save regno, too
                   1058:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1059:        rts
                   1060:
                   1061: addr_ind_p_a1:
                   1062:        mov.l           %a0,%d0                 # copy no. bytes
                   1063:        mov.l           EXC_A1(%a6),%a0         # load current value
                   1064:        add.l           %a0,%d0                 # increment
                   1065:        mov.l           %d0,EXC_A1(%a6)         # save incremented value
                   1066:
                   1067:        mov.l           %a0,EXC_SAVVAL(%a6)     # save in case of access error
                   1068:        mov.b           &0x1,EXC_SAVREG(%a6)    # save regno, too
                   1069:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1070:        rts
                   1071:
                   1072: addr_ind_p_a2:
                   1073:        mov.l           %a0,%d0                 # copy no. bytes
                   1074:        mov.l           EXC_A2(%a6),%a0         # load current value
                   1075:        add.l           %a0,%d0                 # increment
                   1076:        mov.l           %d0,EXC_A2(%a6)         # save incremented value
                   1077:
                   1078:        mov.l           %a0,EXC_SAVVAL(%a6)     # save in case of access error
                   1079:        mov.b           &0x2,EXC_SAVREG(%a6)    # save regno, too
                   1080:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1081:        rts
                   1082:
                   1083: addr_ind_p_a3:
                   1084:        mov.l           %a0,%d0                 # copy no. bytes
                   1085:        mov.l           EXC_A3(%a6),%a0         # load current value
                   1086:        add.l           %a0,%d0                 # increment
                   1087:        mov.l           %d0,EXC_A3(%a6)         # save incremented value
                   1088:
                   1089:        mov.l           %a0,EXC_SAVVAL(%a6)     # save in case of access error
                   1090:        mov.b           &0x3,EXC_SAVREG(%a6)    # save regno, too
                   1091:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1092:        rts
                   1093:
                   1094: addr_ind_p_a4:
                   1095:        mov.l           %a0,%d0                 # copy no. bytes
                   1096:        mov.l           EXC_A4(%a6),%a0         # load current value
                   1097:        add.l           %a0,%d0                 # increment
                   1098:        mov.l           %d0,EXC_A4(%a6)         # save incremented value
                   1099:
                   1100:        mov.l           %a0,EXC_SAVVAL(%a6)     # save in case of access error
                   1101:        mov.b           &0x4,EXC_SAVREG(%a6)    # save regno, too
                   1102:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1103:        rts
                   1104:
                   1105: addr_ind_p_a5:
                   1106:        mov.l           %a0,%d0                 # copy no. bytes
                   1107:        mov.l           EXC_A5(%a6),%a0         # load current value
                   1108:        add.l           %a0,%d0                 # increment
                   1109:        mov.l           %d0,EXC_A5(%a6)         # save incremented value
                   1110:
                   1111:        mov.l           %a0,EXC_SAVVAL(%a6)     # save in case of access error
                   1112:        mov.b           &0x5,EXC_SAVREG(%a6)    # save regno, too
                   1113:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1114:        rts
                   1115:
                   1116: addr_ind_p_a6:
                   1117:        mov.l           %a0,%d0                 # copy no. bytes
                   1118:        mov.l           EXC_A6(%a6),%a0         # load current value
                   1119:        add.l           %a0,%d0                 # increment
                   1120:        mov.l           %d0,EXC_A6(%a6)         # save incremented value
                   1121:
                   1122:        mov.l           %a0,EXC_SAVVAL(%a6)     # save in case of access error
                   1123:        mov.b           &0x6,EXC_SAVREG(%a6)    # save regno, too
                   1124:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1125:        rts
                   1126:
                   1127: addr_ind_p_a7:
                   1128:        mov.b           &mia7_flg,SPCOND_FLG(%a6) # set "special case" flag
                   1129:
                   1130:        mov.l           %a0,%d0                 # copy no. bytes
                   1131:        mov.l           EXC_A7(%a6),%a0         # load current value
                   1132:        add.l           %a0,%d0                 # increment
                   1133:        mov.l           %d0,EXC_A7(%a6)         # save incremented value
                   1134:        rts
                   1135:
                   1136: ####################################################
                   1137: # Address register indirect w/ predecrement: -(An) #
                   1138: ####################################################
                   1139: addr_ind_m_a0:
                   1140:        mov.l           EXC_A0(%a6),%d0         # Get current a0
                   1141:        mov.l           %d0,EXC_SAVVAL(%a6)     # save in case of access error
                   1142:        sub.l           %a0,%d0                 # Decrement
                   1143:        mov.l           %d0,EXC_A0(%a6)         # Save decr value
                   1144:        mov.l           %d0,%a0
                   1145:
                   1146:        mov.b           &0x0,EXC_SAVREG(%a6)    # save regno, too
                   1147:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1148:        rts
                   1149:
                   1150: addr_ind_m_a1:
                   1151:        mov.l           EXC_A1(%a6),%d0         # Get current a1
                   1152:        mov.l           %d0,EXC_SAVVAL(%a6)     # save in case of access error
                   1153:        sub.l           %a0,%d0                 # Decrement
                   1154:        mov.l           %d0,EXC_A1(%a6)         # Save decr value
                   1155:        mov.l           %d0,%a0
                   1156:
                   1157:        mov.b           &0x1,EXC_SAVREG(%a6)    # save regno, too
                   1158:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1159:        rts
                   1160:
                   1161: addr_ind_m_a2:
                   1162:        mov.l           EXC_A2(%a6),%d0         # Get current a2
                   1163:        mov.l           %d0,EXC_SAVVAL(%a6)     # save in case of access error
                   1164:        sub.l           %a0,%d0                 # Decrement
                   1165:        mov.l           %d0,EXC_A2(%a6)         # Save decr value
                   1166:        mov.l           %d0,%a0
                   1167:
                   1168:        mov.b           &0x2,EXC_SAVREG(%a6)    # save regno, too
                   1169:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1170:        rts
                   1171:
                   1172: addr_ind_m_a3:
                   1173:        mov.l           EXC_A3(%a6),%d0         # Get current a3
                   1174:        mov.l           %d0,EXC_SAVVAL(%a6)     # save in case of access error
                   1175:        sub.l           %a0,%d0                 # Decrement
                   1176:        mov.l           %d0,EXC_A3(%a6)         # Save decr value
                   1177:        mov.l           %d0,%a0
                   1178:
                   1179:        mov.b           &0x3,EXC_SAVREG(%a6)    # save regno, too
                   1180:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1181:        rts
                   1182:
                   1183: addr_ind_m_a4:
                   1184:        mov.l           EXC_A4(%a6),%d0         # Get current a4
                   1185:        mov.l           %d0,EXC_SAVVAL(%a6)     # save in case of access error
                   1186:        sub.l           %a0,%d0                 # Decrement
                   1187:        mov.l           %d0,EXC_A4(%a6)         # Save decr value
                   1188:        mov.l           %d0,%a0
                   1189:
                   1190:        mov.b           &0x4,EXC_SAVREG(%a6)    # save regno, too
                   1191:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1192:        rts
                   1193:
                   1194: addr_ind_m_a5:
                   1195:        mov.l           EXC_A5(%a6),%d0         # Get current a5
                   1196:        mov.l           %d0,EXC_SAVVAL(%a6)     # save in case of access error
                   1197:        sub.l           %a0,%d0                 # Decrement
                   1198:        mov.l           %d0,EXC_A5(%a6)         # Save decr value
                   1199:        mov.l           %d0,%a0
                   1200:
                   1201:        mov.b           &0x5,EXC_SAVREG(%a6)    # save regno, too
                   1202:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1203:        rts
                   1204:
                   1205: addr_ind_m_a6:
                   1206:        mov.l           EXC_A6(%a6),%d0         # Get current a6
                   1207:        mov.l           %d0,EXC_SAVVAL(%a6)     # save in case of access error
                   1208:        sub.l           %a0,%d0                 # Decrement
                   1209:        mov.l           %d0,EXC_A6(%a6)         # Save decr value
                   1210:        mov.l           %d0,%a0
                   1211:
                   1212:        mov.b           &0x6,EXC_SAVREG(%a6)    # save regno, too
                   1213:        mov.b           &restore_flg,SPCOND_FLG(%a6) # set flag
                   1214:        rts
                   1215:
                   1216: addr_ind_m_a7:
                   1217:        mov.b           &mda7_flg,SPCOND_FLG(%a6) # set "special case" flag
                   1218:
                   1219:        mov.l           EXC_A7(%a6),%d0         # Get current a7
                   1220:        sub.l           %a0,%d0                 # Decrement
                   1221:        mov.l           %d0,EXC_A7(%a6)         # Save decr value
                   1222:        mov.l           %d0,%a0
                   1223:        rts
                   1224:
                   1225: ########################################################
                   1226: # Address register indirect w/ displacement: (d16, An) #
                   1227: ########################################################
                   1228: addr_ind_disp_a0:
                   1229:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1230:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1231:        bsr.l           _imem_read_word
                   1232:
                   1233:        tst.l           %d1                     # ifetch error?
                   1234:        bne.l           isp_iacc                # yes
                   1235:
                   1236:        mov.w           %d0,%a0                 # sign extend displacement
                   1237:        add.l           EXC_A0(%a6),%a0         # a0 + d16
                   1238:        rts
                   1239:
                   1240: addr_ind_disp_a1:
                   1241:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1242:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1243:        bsr.l           _imem_read_word
                   1244:
                   1245:        tst.l           %d1                     # ifetch error?
                   1246:        bne.l           isp_iacc                # yes
                   1247:
                   1248:        mov.w           %d0,%a0                 # sign extend displacement
                   1249:        add.l           EXC_A1(%a6),%a0         # a1 + d16
                   1250:        rts
                   1251:
                   1252: addr_ind_disp_a2:
                   1253:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1254:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1255:        bsr.l           _imem_read_word
                   1256:
                   1257:        tst.l           %d1                     # ifetch error?
                   1258:        bne.l           isp_iacc                # yes
                   1259:
                   1260:        mov.w           %d0,%a0                 # sign extend displacement
                   1261:        add.l           EXC_A2(%a6),%a0         # a2 + d16
                   1262:        rts
                   1263:
                   1264: addr_ind_disp_a3:
                   1265:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1266:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1267:        bsr.l           _imem_read_word
                   1268:
                   1269:        tst.l           %d1                     # ifetch error?
                   1270:        bne.l           isp_iacc                # yes
                   1271:
                   1272:        mov.w           %d0,%a0                 # sign extend displacement
                   1273:        add.l           EXC_A3(%a6),%a0         # a3 + d16
                   1274:        rts
                   1275:
                   1276: addr_ind_disp_a4:
                   1277:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1278:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1279:        bsr.l           _imem_read_word
                   1280:
                   1281:        tst.l           %d1                     # ifetch error?
                   1282:        bne.l           isp_iacc                # yes
                   1283:
                   1284:        mov.w           %d0,%a0                 # sign extend displacement
                   1285:        add.l           EXC_A4(%a6),%a0         # a4 + d16
                   1286:        rts
                   1287:
                   1288: addr_ind_disp_a5:
                   1289:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1290:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1291:        bsr.l           _imem_read_word
                   1292:
                   1293:        tst.l           %d1                     # ifetch error?
                   1294:        bne.l           isp_iacc                # yes
                   1295:
                   1296:        mov.w           %d0,%a0                 # sign extend displacement
                   1297:        add.l           EXC_A5(%a6),%a0         # a5 + d16
                   1298:        rts
                   1299:
                   1300: addr_ind_disp_a6:
                   1301:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1302:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1303:        bsr.l           _imem_read_word
                   1304:
                   1305:        tst.l           %d1                     # ifetch error?
                   1306:        bne.l           isp_iacc                # yes
                   1307:
                   1308:        mov.w           %d0,%a0                 # sign extend displacement
                   1309:        add.l           EXC_A6(%a6),%a0         # a6 + d16
                   1310:        rts
                   1311:
                   1312: addr_ind_disp_a7:
                   1313:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1314:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1315:        bsr.l           _imem_read_word
                   1316:
                   1317:        tst.l           %d1                     # ifetch error?
                   1318:        bne.l           isp_iacc                # yes
                   1319:
                   1320:        mov.w           %d0,%a0                 # sign extend displacement
                   1321:        add.l           EXC_A7(%a6),%a0         # a7 + d16
                   1322:        rts
                   1323:
                   1324: ########################################################################
                   1325: # Address register indirect w/ index(8-bit displacement): (dn, An, Xn) #
                   1326: #    "       "         "    w/   "  (base displacement): (bd, An, Xn)  #
                   1327: # Memory indirect postindexed: ([bd, An], Xn, od)                     #
                   1328: # Memory indirect preindexed: ([bd, An, Xn], od)                      #
                   1329: ########################################################################
                   1330: _addr_ind_ext:
                   1331:        mov.l           %d1,-(%sp)
                   1332:
                   1333:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1334:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1335:        bsr.l           _imem_read_word         # fetch extword in d0
                   1336:
                   1337:        tst.l           %d1                     # ifetch error?
                   1338:        bne.l           isp_iacc                # yes
                   1339:
                   1340:        mov.l           (%sp)+,%d1
                   1341:
                   1342:        mov.l           (EXC_AREGS,%a6,%d1.w*4),%a0 # put base in a0
                   1343:
                   1344:        btst            &0x8,%d0
                   1345:        beq.b           addr_ind_index_8bit     # for ext word or not?
                   1346:
                   1347:        movm.l          &0x3c00,-(%sp)          # save d2-d5
                   1348:
                   1349:        mov.l           %d0,%d5                 # put extword in d5
                   1350:        mov.l           %a0,%d3                 # put base in d3
                   1351:
                   1352:        bra.l           calc_mem_ind            # calc memory indirect
                   1353:
                   1354: addr_ind_index_8bit:
                   1355:        mov.l           %d2,-(%sp)              # save old d2
                   1356:
                   1357:        mov.l           %d0,%d1
                   1358:        rol.w           &0x4,%d1
                   1359:        andi.w          &0xf,%d1                # extract index regno
                   1360:
                   1361:        mov.l           (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
                   1362:
                   1363:        btst            &0xb,%d0                # is it word or long?
                   1364:        bne.b           aii8_long
                   1365:        ext.l           %d1                     # sign extend word index
                   1366: aii8_long:
                   1367:        mov.l           %d0,%d2
                   1368:        rol.w           &0x7,%d2
                   1369:        andi.l          &0x3,%d2                # extract scale value
                   1370:
                   1371:        lsl.l           %d2,%d1                 # shift index by scale
                   1372:
                   1373:        extb.l          %d0                     # sign extend displacement
                   1374:        add.l           %d1,%d0                 # index + disp
                   1375:        add.l           %d0,%a0                 # An + (index + disp)
                   1376:
                   1377:        mov.l           (%sp)+,%d2              # restore old d2
                   1378:        rts
                   1379:
                   1380: ######################
                   1381: # Immediate: #<data> #
                   1382: #########################################################################
                   1383: # word, long: <ea> of the data is the current extension word           #
                   1384: #      pointer value. new extension word pointer is simply the old     #
                   1385: #      plus the number of bytes in the data type(2 or 4).              #
                   1386: #########################################################################
                   1387: immediate:
                   1388:        mov.b           &immed_flg,SPCOND_FLG(%a6) # set immediate flag
                   1389:
                   1390:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch extension word ptr
                   1391:        rts
                   1392:
                   1393: ###########################
                   1394: # Absolute short: (XXX).W #
                   1395: ###########################
                   1396: abs_short:
                   1397:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1398:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1399:        bsr.l           _imem_read_word         # fetch short address
                   1400:
                   1401:        tst.l           %d1                     # ifetch error?
                   1402:        bne.l           isp_iacc                # yes
                   1403:
                   1404:        mov.w           %d0,%a0                 # return <ea> in a0
                   1405:        rts
                   1406:
                   1407: ##########################
                   1408: # Absolute long: (XXX).L #
                   1409: ##########################
                   1410: abs_long:
                   1411:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1412:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1413:        bsr.l           _imem_read_long         # fetch long address
                   1414:
                   1415:        tst.l           %d1                     # ifetch error?
                   1416:        bne.l           isp_iacc                # yes
                   1417:
                   1418:        mov.l           %d0,%a0                 # return <ea> in a0
                   1419:        rts
                   1420:
                   1421: #######################################################
                   1422: # Program counter indirect w/ displacement: (d16, PC) #
                   1423: #######################################################
                   1424: pc_ind:
                   1425:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1426:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1427:        bsr.l           _imem_read_word         # fetch word displacement
                   1428:
                   1429:        tst.l           %d1                     # ifetch error?
                   1430:        bne.l           isp_iacc                # yes
                   1431:
                   1432:        mov.w           %d0,%a0                 # sign extend displacement
                   1433:
                   1434:        add.l           EXC_EXTWPTR(%a6),%a0    # pc + d16
                   1435:
                   1436: # _imem_read_word() increased the extwptr by 2. need to adjust here.
                   1437:        subq.l          &0x2,%a0                # adjust <ea>
                   1438:
                   1439:        rts
                   1440:
                   1441: ##########################################################
                   1442: # PC indirect w/ index(8-bit displacement): (d8, PC, An) #
                   1443: # "     "     w/   "  (base displacement): (bd, PC, An)  #
                   1444: # PC memory indirect postindexed: ([bd, PC], Xn, od)     #
                   1445: # PC memory indirect preindexed: ([bd, PC, Xn], od)      #
                   1446: ##########################################################
                   1447: pc_ind_ext:
                   1448:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1449:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1450:        bsr.l           _imem_read_word         # fetch ext word
                   1451:
                   1452:        tst.l           %d1                     # ifetch error?
                   1453:        bne.l           isp_iacc                # yes
                   1454:
                   1455:        mov.l           EXC_EXTWPTR(%a6),%a0    # put base in a0
                   1456:        subq.l          &0x2,%a0                # adjust base
                   1457:
                   1458:        btst            &0x8,%d0                # is disp only 8 bits?
                   1459:        beq.b           pc_ind_index_8bit       # yes
                   1460:
                   1461: # the indexed addressing mode uses a base displacement of size
                   1462: # word or long
                   1463:        movm.l          &0x3c00,-(%sp)          # save d2-d5
                   1464:
                   1465:        mov.l           %d0,%d5                 # put extword in d5
                   1466:        mov.l           %a0,%d3                 # put base in d3
                   1467:
                   1468:        bra.l           calc_mem_ind            # calc memory indirect
                   1469:
                   1470: pc_ind_index_8bit:
                   1471:        mov.l           %d2,-(%sp)              # create a temp register
                   1472:
                   1473:        mov.l           %d0,%d1                 # make extword copy
                   1474:        rol.w           &0x4,%d1                # rotate reg num into place
                   1475:        andi.w          &0xf,%d1                # extract register number
                   1476:
                   1477:        mov.l           (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value
                   1478:
                   1479:        btst            &0xb,%d0                # is index word or long?
                   1480:        bne.b           pii8_long               # long
                   1481:        ext.l           %d1                     # sign extend word index
                   1482: pii8_long:
                   1483:        mov.l           %d0,%d2                 # make extword copy
                   1484:        rol.w           &0x7,%d2                # rotate scale value into place
                   1485:        andi.l          &0x3,%d2                # extract scale value
                   1486:
                   1487:        lsl.l           %d2,%d1                 # shift index by scale
                   1488:
                   1489:        extb.l          %d0                     # sign extend displacement
                   1490:        add.l           %d1,%d0                 # index + disp
                   1491:        add.l           %d0,%a0                 # An + (index + disp)
                   1492:
                   1493:        mov.l           (%sp)+,%d2              # restore temp register
                   1494:
                   1495:        rts
                   1496:
                   1497: # a5 = exc_extwptr     (global to uaeh)
                   1498: # a4 = exc_opword      (global to uaeh)
                   1499: # a3 = exc_dregs       (global to uaeh)
                   1500:
                   1501: # d2 = index           (internal "     "    )
                   1502: # d3 = base            (internal "     "    )
                   1503: # d4 = od              (internal "     "    )
                   1504: # d5 = extword         (internal "     "    )
                   1505: calc_mem_ind:
                   1506:        btst            &0x6,%d5                # is the index suppressed?
                   1507:        beq.b           calc_index
                   1508:        clr.l           %d2                     # yes, so index = 0
                   1509:        bra.b           base_supp_ck
                   1510: calc_index:
                   1511:        bfextu          %d5{&16:&4},%d2
                   1512:        mov.l           (EXC_DREGS,%a6,%d2.w*4),%d2
                   1513:        btst            &0xb,%d5                # is index word or long?
                   1514:        bne.b           no_ext
                   1515:        ext.l           %d2
                   1516: no_ext:
                   1517:        bfextu          %d5{&21:&2},%d0
                   1518:        lsl.l           %d0,%d2
                   1519: base_supp_ck:
                   1520:        btst            &0x7,%d5                # is the bd suppressed?
                   1521:        beq.b           no_base_sup
                   1522:        clr.l           %d3
                   1523: no_base_sup:
                   1524:        bfextu          %d5{&26:&2},%d0 # get bd size
                   1525: #      beq.l           _error                  # if (size == 0) it's reserved
                   1526:        cmpi.b          %d0,&2
                   1527:        blt.b           no_bd
                   1528:        beq.b           get_word_bd
                   1529:
                   1530:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1531:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1532:        bsr.l           _imem_read_long
                   1533:
                   1534:        tst.l           %d1                     # ifetch error?
                   1535:        bne.l           isp_iacc                # yes
                   1536:
                   1537:        bra.b           chk_ind
                   1538: get_word_bd:
                   1539:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1540:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1541:        bsr.l           _imem_read_word
                   1542:
                   1543:        tst.l           %d1                     # ifetch error?
                   1544:        bne.l           isp_iacc                # yes
                   1545:
                   1546:        ext.l           %d0                     # sign extend bd
                   1547:
                   1548: chk_ind:
                   1549:        add.l           %d0,%d3                 # base += bd
                   1550: no_bd:
                   1551:        bfextu          %d5{&30:&2},%d0         # is od suppressed?
                   1552:        beq.w           aii_bd
                   1553:        cmpi.b          %d0,&0x2
                   1554:        blt.b           null_od
                   1555:        beq.b           word_od
                   1556:
                   1557:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1558:        addq.l          &0x4,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1559:        bsr.l           _imem_read_long
                   1560:
                   1561:        tst.l           %d1                     # ifetch error?
                   1562:        bne.l           isp_iacc                # yes
                   1563:
                   1564:        bra.b           add_them
                   1565:
                   1566: word_od:
                   1567:        mov.l           EXC_EXTWPTR(%a6),%a0    # fetch instruction addr
                   1568:        addq.l          &0x2,EXC_EXTWPTR(%a6)   # incr instruction ptr
                   1569:        bsr.l           _imem_read_word
                   1570:
                   1571:        tst.l           %d1                     # ifetch error?
                   1572:        bne.l           isp_iacc                # yes
                   1573:
                   1574:        ext.l           %d0                     # sign extend od
                   1575:        bra.b           add_them
                   1576:
                   1577: null_od:
                   1578:        clr.l           %d0
                   1579: add_them:
                   1580:        mov.l           %d0,%d4
                   1581:        btst            &0x2,%d5                # pre or post indexing?
                   1582:        beq.b           pre_indexed
                   1583:
                   1584:        mov.l           %d3,%a0
                   1585:        bsr.l           _dmem_read_long
                   1586:
                   1587:        tst.l           %d1                     # dfetch error?
                   1588:        bne.b           calc_ea_err             # yes
                   1589:
                   1590:        add.l           %d2,%d0                 # <ea> += index
                   1591:        add.l           %d4,%d0                 # <ea> += od
                   1592:        bra.b           done_ea
                   1593:
                   1594: pre_indexed:
                   1595:        add.l           %d2,%d3                 # preindexing
                   1596:        mov.l           %d3,%a0
                   1597:        bsr.l           _dmem_read_long
                   1598:
                   1599:        tst.l           %d1                     # ifetch error?
                   1600:        bne.b           calc_ea_err             # yes
                   1601:
                   1602:        add.l           %d4,%d0                 # ea += od
                   1603:        bra.b           done_ea
                   1604:
                   1605: aii_bd:
                   1606:        add.l           %d2,%d3                 # ea = (base + bd) + index
                   1607:        mov.l           %d3,%d0
                   1608: done_ea:
                   1609:        mov.l           %d0,%a0
                   1610:
                   1611:        movm.l          (%sp)+,&0x003c          # restore d2-d5
                   1612:        rts
                   1613:
                   1614: # if dmem_read_long() returns a fail message in d1, the package
                   1615: # must create an access error frame. here, we pass a skeleton fslw
                   1616: # and the failing address to the routine that creates the new frame.
                   1617: # FSLW:
                   1618: #      read = true
                   1619: #      size = longword
                   1620: #      TM = data
                   1621: #      software emulation error = true
                   1622: calc_ea_err:
                   1623:        mov.l           %d3,%a0                 # pass failing address
                   1624:        mov.l           &0x01010001,%d0         # pass fslw
                   1625:        bra.l           isp_dacc
                   1626:
                   1627: #########################################################################
                   1628: # XDEF **************************************************************** #
                   1629: #      _moveperipheral(): routine to emulate movep instruction         #
                   1630: #                                                                      #
                   1631: # XREF **************************************************************** #
                   1632: #      _dmem_read_byte() - read byte from memory                       #
                   1633: #      _dmem_write_byte() - write byte to memory                       #
                   1634: #      isp_dacc() - handle data access error exception                 #
                   1635: #                                                                      #
                   1636: # INPUT *************************************************************** #
                   1637: #      none                                                            #
                   1638: #                                                                      #
                   1639: # OUTPUT ************************************************************** #
                   1640: #      If exiting through isp_dacc...                                  #
                   1641: #              a0 = failing address                                    #
                   1642: #              d0 = FSLW                                               #
                   1643: #      else                                                            #
                   1644: #              none                                                    #
                   1645: #                                                                      #
                   1646: # ALGORITHM ***********************************************************        #
                   1647: #      Decode the movep instruction words stored at EXC_OPWORD and     #
                   1648: # either read or write the required bytes from/to memory. Use the      #
                   1649: # _dmem_{read,write}_byte() routines. If one of the memory routines    #
                   1650: # returns a failing value, we must pass the failing address and        a FSLW  #
                   1651: # to the _isp_dacc() routine.                                          #
                   1652: #      Since this instruction is used to access peripherals, make sure #
                   1653: # to only access the required bytes.                                   #
                   1654: #                                                                      #
                   1655: #########################################################################
                   1656:
                   1657: ###########################
                   1658: # movep.(w,l)  Dx,(d,Ay) #
                   1659: # movep.(w,l)  (d,Ay),Dx #
                   1660: ###########################
                   1661:        global          _moveperipheral
                   1662: _moveperipheral:
                   1663:        mov.w           EXC_OPWORD(%a6),%d1     # fetch the opcode word
                   1664:
                   1665:        mov.b           %d1,%d0
                   1666:        and.w           &0x7,%d0                # extract Ay from opcode word
                   1667:
                   1668:        mov.l           (EXC_AREGS,%a6,%d0.w*4),%a0 # fetch ay
                   1669:
                   1670:        add.w           EXC_EXTWORD(%a6),%a0    # add: an + sgn_ext(disp)
                   1671:
                   1672:        btst            &0x7,%d1                # (reg 2 mem) or (mem 2 reg)
                   1673:        beq.w           mem2reg
                   1674:
                   1675: # reg2mem: fetch dx, then write it to memory
                   1676: reg2mem:
                   1677:        mov.w           %d1,%d0
                   1678:        rol.w           &0x7,%d0
                   1679:        and.w           &0x7,%d0                # extract Dx from opcode word
                   1680:
                   1681:        mov.l           (EXC_DREGS,%a6,%d0.w*4), %d0 # fetch dx
                   1682:
                   1683:        btst            &0x6,%d1                # word or long operation?
                   1684:        beq.b           r2mwtrans
                   1685:
                   1686: # a0 = dst addr
                   1687: # d0 = Dx
                   1688: r2mltrans:
                   1689:        mov.l           %d0,%d2                 # store data
                   1690:        mov.l           %a0,%a2                 # store addr
                   1691:        rol.l           &0x8,%d2
                   1692:        mov.l           %d2,%d0
                   1693:
                   1694:        bsr.l           _dmem_write_byte        # os  : write hi
                   1695:
                   1696:        tst.l           %d1                     # dfetch error?
                   1697:        bne.w           movp_write_err          # yes
                   1698:
                   1699:        add.w           &0x2,%a2                # incr addr
                   1700:        mov.l           %a2,%a0
                   1701:        rol.l           &0x8,%d2
                   1702:        mov.l           %d2,%d0
                   1703:
                   1704:        bsr.l           _dmem_write_byte        # os  : write lo
                   1705:
                   1706:        tst.l           %d1                     # dfetch error?
                   1707:        bne.w           movp_write_err          # yes
                   1708:
                   1709:        add.w           &0x2,%a2                # incr addr
                   1710:        mov.l           %a2,%a0
                   1711:        rol.l           &0x8,%d2
                   1712:        mov.l           %d2,%d0
                   1713:
                   1714:        bsr.l           _dmem_write_byte        # os  : write lo
                   1715:
                   1716:        tst.l           %d1                     # dfetch error?
                   1717:        bne.w           movp_write_err          # yes
                   1718:
                   1719:        add.w           &0x2,%a2                # incr addr
                   1720:        mov.l           %a2,%a0
                   1721:        rol.l           &0x8,%d2
                   1722:        mov.l           %d2,%d0
                   1723:
                   1724:        bsr.l           _dmem_write_byte        # os  : write lo
                   1725:
                   1726:        tst.l           %d1                     # dfetch error?
                   1727:        bne.w           movp_write_err          # yes
                   1728:
                   1729:        rts
                   1730:
                   1731: # a0 = dst addr
                   1732: # d0 = Dx
                   1733: r2mwtrans:
                   1734:        mov.l           %d0,%d2                 # store data
                   1735:        mov.l           %a0,%a2                 # store addr
                   1736:        lsr.w           &0x8,%d0
                   1737:
                   1738:        bsr.l           _dmem_write_byte        # os  : write hi
                   1739:
                   1740:        tst.l           %d1                     # dfetch error?
                   1741:        bne.w           movp_write_err          # yes
                   1742:
                   1743:        add.w           &0x2,%a2
                   1744:        mov.l           %a2,%a0
                   1745:        mov.l           %d2,%d0
                   1746:
                   1747:        bsr.l           _dmem_write_byte        # os  : write lo
                   1748:
                   1749:        tst.l           %d1                     # dfetch error?
                   1750:        bne.w           movp_write_err          # yes
                   1751:
                   1752:        rts
                   1753:
                   1754: # mem2reg: read bytes from memory.
                   1755: # determines the dest register, and then writes the bytes into it.
                   1756: mem2reg:
                   1757:        btst            &0x6,%d1                # word or long operation?
                   1758:        beq.b           m2rwtrans
                   1759:
                   1760: # a0 = dst addr
                   1761: m2rltrans:
                   1762:        mov.l           %a0,%a2                 # store addr
                   1763:
                   1764:        bsr.l           _dmem_read_byte         # read first byte
                   1765:
                   1766:        tst.l           %d1                     # dfetch error?
                   1767:        bne.w           movp_read_err           # yes
                   1768:
                   1769:        mov.l           %d0,%d2
                   1770:
                   1771:        add.w           &0x2,%a2                # incr addr by 2 bytes
                   1772:        mov.l           %a2,%a0
                   1773:
                   1774:        bsr.l           _dmem_read_byte         # read second byte
                   1775:
                   1776:        tst.l           %d1                     # dfetch error?
                   1777:        bne.w           movp_read_err           # yes
                   1778:
                   1779:        lsl.w           &0x8,%d2
                   1780:        mov.b           %d0,%d2                 # append bytes
                   1781:
                   1782:        add.w           &0x2,%a2                # incr addr by 2 bytes
                   1783:        mov.l           %a2,%a0
                   1784:
                   1785:        bsr.l           _dmem_read_byte         # read second byte
                   1786:
                   1787:        tst.l           %d1                     # dfetch error?
                   1788:        bne.w           movp_read_err           # yes
                   1789:
                   1790:        lsl.l           &0x8,%d2
                   1791:        mov.b           %d0,%d2                 # append bytes
                   1792:
                   1793:        add.w           &0x2,%a2                # incr addr by 2 bytes
                   1794:        mov.l           %a2,%a0
                   1795:
                   1796:        bsr.l           _dmem_read_byte         # read second byte
                   1797:
                   1798:        tst.l           %d1                     # dfetch error?
                   1799:        bne.w           movp_read_err           # yes
                   1800:
                   1801:        lsl.l           &0x8,%d2
                   1802:        mov.b           %d0,%d2                 # append bytes
                   1803:
                   1804:        mov.b           EXC_OPWORD(%a6),%d1
                   1805:        lsr.b           &0x1,%d1
                   1806:        and.w           &0x7,%d1                # extract Dx from opcode word
                   1807:
                   1808:        mov.l           %d2,(EXC_DREGS,%a6,%d1.w*4) # store dx
                   1809:
                   1810:        rts
                   1811:
                   1812: # a0 = dst addr
                   1813: m2rwtrans:
                   1814:        mov.l           %a0,%a2                 # store addr
                   1815:
                   1816:        bsr.l           _dmem_read_byte         # read first byte
                   1817:
                   1818:        tst.l           %d1                     # dfetch error?
                   1819:        bne.w           movp_read_err           # yes
                   1820:
                   1821:        mov.l           %d0,%d2
                   1822:
                   1823:        add.w           &0x2,%a2                # incr addr by 2 bytes
                   1824:        mov.l           %a2,%a0
                   1825:
                   1826:        bsr.l           _dmem_read_byte         # read second byte
                   1827:
                   1828:        tst.l           %d1                     # dfetch error?
                   1829:        bne.w           movp_read_err           # yes
                   1830:
                   1831:        lsl.w           &0x8,%d2
                   1832:        mov.b           %d0,%d2                 # append bytes
                   1833:
                   1834:        mov.b           EXC_OPWORD(%a6),%d1
                   1835:        lsr.b           &0x1,%d1
                   1836:        and.w           &0x7,%d1                # extract Dx from opcode word
                   1837:
                   1838:        mov.w           %d2,(EXC_DREGS+2,%a6,%d1.w*4) # store dx
                   1839:
                   1840:        rts
                   1841:
                   1842: # if dmem_{read,write}_byte() returns a fail message in d1, the package
                   1843: # must create an access error frame. here, we pass a skeleton fslw
                   1844: # and the failing address to the routine that creates the new frame.
                   1845: # FSLW:
                   1846: #      write = true
                   1847: #      size = byte
                   1848: #      TM = data
                   1849: #      software emulation error = true
                   1850: movp_write_err:
                   1851:        mov.l           %a2,%a0                 # pass failing address
                   1852:        mov.l           &0x00a10001,%d0         # pass fslw
                   1853:        bra.l           isp_dacc
                   1854:
                   1855: # FSLW:
                   1856: #      read = true
                   1857: #      size = byte
                   1858: #      TM = data
                   1859: #      software emulation error = true
                   1860: movp_read_err:
                   1861:        mov.l           %a2,%a0                 # pass failing address
                   1862:        mov.l           &0x01210001,%d0         # pass fslw
                   1863:        bra.l           isp_dacc
                   1864:
                   1865: #########################################################################
                   1866: # XDEF ****************************************************************        #
                   1867: #      _chk2_cmp2(): routine to emulate chk2/cmp2 instructions         #
                   1868: #                                                                      #
                   1869: # XREF ****************************************************************        #
                   1870: #      _calc_ea(): calculate effective address                         #
                   1871: #      _dmem_read_long(): read operands                                #
                   1872: #      _dmem_read_word(): read operands                                #
                   1873: #      isp_dacc(): handle data access error exception                  #
                   1874: #                                                                      #
                   1875: # INPUT ***************************************************************        #
                   1876: #      none                                                            #
                   1877: #                                                                      #
                   1878: # OUTPUT **************************************************************        #
                   1879: #      If exiting through isp_dacc...                                  #
                   1880: #              a0 = failing address                                    #
                   1881: #              d0 = FSLW                                               #
                   1882: #      else                                                            #
                   1883: #              none                                                    #
                   1884: #                                                                      #
                   1885: # ALGORITHM ***********************************************************        #
                   1886: #      First, calculate the effective address, then fetch the byte,    #
                   1887: # word, or longword sized operands. Then, in the interest of           #
                   1888: # simplicity, all operands are converted to longword size whether the  #
                   1889: # operation is byte, word, or long. The bounds are sign extended       #
                   1890: # accordingly. If Rn is a data regsiter, Rn is also sign extended. If  #
                   1891: # Rn is an address register, it need not be sign extended since the    #
                   1892: # full register is always used.                                                #
                   1893: #      The comparisons are made and the condition codes calculated.    #
                   1894: # If the instruction is chk2 and the Rn value is out-of-bounds, set    #
                   1895: # the ichk_flg in SPCOND_FLG.                                          #
                   1896: #      If the memory fetch returns a failing value, pass the failing   #
                   1897: # address and FSLW to the isp_dacc() routine.                          #
                   1898: #                                                                      #
                   1899: #########################################################################
                   1900:
                   1901:        global          _chk2_cmp2
                   1902: _chk2_cmp2:
                   1903:
                   1904: # passing size parameter doesn't matter since chk2 & cmp2 can't do
                   1905: # either predecrement, postincrement, or immediate.
                   1906:        bsr.l           _calc_ea                # calculate <ea>
                   1907:
                   1908:        mov.b           EXC_EXTWORD(%a6), %d0   # fetch hi extension word
                   1909:        rol.b           &0x4, %d0               # rotate reg bits into lo
                   1910:        and.w           &0xf, %d0               # extract reg bits
                   1911:
                   1912:        mov.l           (EXC_DREGS,%a6,%d0.w*4), %d2 # get regval
                   1913:
                   1914:        cmpi.b          EXC_OPWORD(%a6), &0x2   # what size is operation?
                   1915:        blt.b           chk2_cmp2_byte          # size == byte
                   1916:        beq.b           chk2_cmp2_word          # size == word
                   1917:
                   1918: # the bounds are longword size. call routine to read the lower
                   1919: # bound into d0 and the higher bound into d1.
                   1920: chk2_cmp2_long:
                   1921:        mov.l           %a0,%a2                 # save copy of <ea>
                   1922:        bsr.l           _dmem_read_long         # fetch long lower bound
                   1923:
                   1924:        tst.l           %d1                     # dfetch error?
                   1925:        bne.w           chk2_cmp2_err_l         # yes
                   1926:
                   1927:        mov.l           %d0,%d3                 # save long lower bound
                   1928:        addq.l          &0x4,%a2
                   1929:        mov.l           %a2,%a0                 # pass <ea> of long upper bound
                   1930:        bsr.l           _dmem_read_long         # fetch long upper bound
                   1931:
                   1932:        tst.l           %d1                     # dfetch error?
                   1933:        bne.w           chk2_cmp2_err_l         # yes
                   1934:
                   1935:        mov.l           %d0,%d1                 # long upper bound in d1
                   1936:        mov.l           %d3,%d0                 # long lower bound in d0
                   1937:        bra.w           chk2_cmp2_compare       # go do the compare emulation
                   1938:
                   1939: # the bounds are word size. fetch them in one subroutine call by
                   1940: # reading a longword. sign extend both. if it's a data operation,
                   1941: # sign extend Rn to long, also.
                   1942: chk2_cmp2_word:
                   1943:        mov.l           %a0,%a2
                   1944:        bsr.l           _dmem_read_long         # fetch 2 word bounds
                   1945:
                   1946:        tst.l           %d1                     # dfetch error?
                   1947:        bne.w           chk2_cmp2_err_l         # yes
                   1948:
                   1949:        mov.w           %d0, %d1                # place hi in %d1
                   1950:        swap            %d0                     # place lo in %d0
                   1951:
                   1952:        ext.l           %d0                     # sign extend lo bnd
                   1953:        ext.l           %d1                     # sign extend hi bnd
                   1954:
                   1955:        btst            &0x7, EXC_EXTWORD(%a6)  # address compare?
                   1956:        bne.w           chk2_cmp2_compare       # yes; don't sign extend
                   1957:
                   1958: # operation is a data register compare.
                   1959: # sign extend word to long so we can do simple longword compares.
                   1960:        ext.l           %d2                     # sign extend data word
                   1961:        bra.w           chk2_cmp2_compare       # go emulate compare
                   1962:
                   1963: # the bounds are byte size. fetch them in one subroutine call by
                   1964: # reading a word. sign extend both. if it's a data operation,
                   1965: # sign extend Rn to long, also.
                   1966: chk2_cmp2_byte:
                   1967:        mov.l           %a0,%a2
                   1968:        bsr.l           _dmem_read_word         # fetch 2 byte bounds
                   1969:
                   1970:        tst.l           %d1                     # dfetch error?
                   1971:        bne.w           chk2_cmp2_err_w         # yes
                   1972:
                   1973:        mov.b           %d0, %d1                # place hi in %d1
                   1974:        lsr.w           &0x8, %d0               # place lo in %d0
                   1975:
                   1976:        extb.l          %d0                     # sign extend lo bnd
                   1977:        extb.l          %d1                     # sign extend hi bnd
                   1978:
                   1979:        btst            &0x7, EXC_EXTWORD(%a6)  # address compare?
                   1980:        bne.b           chk2_cmp2_compare       # yes; don't sign extend
                   1981:
                   1982: # operation is a data register compare.
                   1983: # sign extend byte to long so we can do simple longword compares.
                   1984:        extb.l          %d2                     # sign extend data byte
                   1985:
                   1986: #
                   1987: # To set the ccodes correctly:
                   1988: #      (1) save 'Z' bit from (Rn - lo)
                   1989: #      (2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi))
                   1990: #      (3) keep 'X', 'N', and 'V' from before instruction
                   1991: #      (4) combine ccodes
                   1992: #
                   1993: chk2_cmp2_compare:
                   1994:        sub.l           %d0, %d2                # (Rn - lo)
                   1995:        mov.w           %cc, %d3                # fetch resulting ccodes
                   1996:        andi.b          &0x4, %d3               # keep 'Z' bit
                   1997:        sub.l           %d0, %d1                # (hi - lo)
                   1998:        cmp.l           %d1,%d2                 # ((hi - lo) - (Rn - hi))
                   1999:
                   2000:        mov.w           %cc, %d4                # fetch resulting ccodes
                   2001:        or.b            %d4, %d3                # combine w/ earlier ccodes
                   2002:        andi.b          &0x5, %d3               # keep 'Z' and 'N'
                   2003:
                   2004:        mov.w           EXC_CC(%a6), %d4        # fetch old ccodes
                   2005:        andi.b          &0x1a, %d4              # keep 'X','N','V' bits
                   2006:        or.b            %d3, %d4                # insert new ccodes
                   2007:        mov.w           %d4, EXC_CC(%a6)        # save new ccodes
                   2008:
                   2009:        btst            &0x3, EXC_EXTWORD(%a6)  # separate chk2,cmp2
                   2010:        bne.b           chk2_finish             # it's a chk2
                   2011:
                   2012:        rts
                   2013:
                   2014: # this code handles the only difference between chk2 and cmp2. chk2 would
                   2015: # have trapped out if the value was out of bounds. we check this by seeing
                   2016: # if the 'N' bit was set by the operation.
                   2017: chk2_finish:
                   2018:        btst            &0x0, %d4               # is 'N' bit set?
                   2019:        bne.b           chk2_trap               # yes;chk2 should trap
                   2020:        rts
                   2021: chk2_trap:
                   2022:        mov.b           &ichk_flg,SPCOND_FLG(%a6) # set "special case" flag
                   2023:        rts
                   2024:
                   2025: # if dmem_read_{long,word}() returns a fail message in d1, the package
                   2026: # must create an access error frame. here, we pass a skeleton fslw
                   2027: # and the failing address to the routine that creates the new frame.
                   2028: # FSLW:
                   2029: #      read = true
                   2030: #      size = longword
                   2031: #      TM = data
                   2032: #      software emulation error = true
                   2033: chk2_cmp2_err_l:
                   2034:        mov.l           %a2,%a0                 # pass failing address
                   2035:        mov.l           &0x01010001,%d0         # pass fslw
                   2036:        bra.l           isp_dacc
                   2037:
                   2038: # FSLW:
                   2039: #      read = true
                   2040: #      size = word
                   2041: #      TM = data
                   2042: #      software emulation error = true
                   2043: chk2_cmp2_err_w:
                   2044:        mov.l           %a2,%a0                 # pass failing address
                   2045:        mov.l           &0x01410001,%d0         # pass fslw
                   2046:        bra.l           isp_dacc
                   2047:
                   2048: #########################################################################
                   2049: # XDEF ****************************************************************        #
                   2050: #      _div64(): routine to emulate div{u,s}.l <ea>,Dr:Dq              #
                   2051: #                                                      64/32->32r:32q  #
                   2052: #                                                                      #
                   2053: # XREF ****************************************************************        #
                   2054: #      _calc_ea() - calculate effective address                        #
                   2055: #      isp_iacc() - handle instruction access error exception          #
                   2056: #      isp_dacc() - handle data access error exception                 #
                   2057: #      isp_restore() - restore An on access error w/ -() or ()+        #
                   2058: #                                                                      #
                   2059: # INPUT ***************************************************************        #
                   2060: #      none                                                            #
                   2061: #                                                                      #
                   2062: # OUTPUT **************************************************************        #
                   2063: #      If exiting through isp_dacc...                                  #
                   2064: #              a0 = failing address                                    #
                   2065: #              d0 = FSLW                                               #
                   2066: #      else                                                            #
                   2067: #              none                                                    #
                   2068: #                                                                      #
                   2069: # ALGORITHM ***********************************************************        #
                   2070: #      First, decode the operand location. If it's in Dn, fetch from   #
                   2071: # the stack. If it's in memory, use _calc_ea() to calculate the        #
                   2072: # effective address. Use _dmem_read_long() to fetch at that address.   #
                   2073: # Unless the operand is immediate data. Then use _imem_read_long().    #
                   2074: # Send failures to isp_dacc() or isp_iacc() as appropriate.            #
                   2075: #      If the operands are signed, make them unsigned and save the     #
                   2076: # sign info for later. Separate out special cases like divide-by-zero  #
                   2077: # or 32-bit divides if possible. Else, use a special math algorithm    #
                   2078: # to calculate the result.                                             #
                   2079: #      Restore sign info if signed instruction. Set the condition      #
                   2080: # codes. Set idbyz_flg in SPCOND_FLG if divisor was zero. Store the    #
                   2081: # quotient and remainder in the appropriate data registers on the stack.#
                   2082: #                                                                      #
                   2083: #########################################################################
                   2084:
                   2085: set    NDIVISOR,       EXC_TEMP+0x0
                   2086: set    NDIVIDEND,      EXC_TEMP+0x1
                   2087: set    NDRSAVE,        EXC_TEMP+0x2
                   2088: set    NDQSAVE,        EXC_TEMP+0x4
                   2089: set    DDSECOND,       EXC_TEMP+0x6
                   2090: set    DDQUOTIENT,     EXC_TEMP+0x8
                   2091: set    DDNORMAL,       EXC_TEMP+0xc
                   2092:
                   2093:        global          _div64
                   2094: #############
                   2095: # div(u,s)l #
                   2096: #############
                   2097: _div64:
                   2098:        mov.b           EXC_OPWORD+1(%a6), %d0
                   2099:        andi.b          &0x38, %d0              # extract src mode
                   2100:
                   2101:        bne.w           dcontrolmodel_s         # %dn dest or control mode?
                   2102:
                   2103:        mov.b           EXC_OPWORD+1(%a6), %d0  # extract Dn from opcode
                   2104:        andi.w          &0x7, %d0
                   2105:        mov.l           (EXC_DREGS,%a6,%d0.w*4), %d7 # fetch divisor from register
                   2106:
                   2107: dgotsrcl:
                   2108:        beq.w           div64eq0                # divisor is = 0!!!
                   2109:
                   2110:        mov.b           EXC_EXTWORD+1(%a6), %d0 # extract Dr from extword
                   2111:        mov.b           EXC_EXTWORD(%a6), %d1   # extract Dq from extword
                   2112:        and.w           &0x7, %d0
                   2113:        lsr.b           &0x4, %d1
                   2114:        and.w           &0x7, %d1
                   2115:        mov.w           %d0, NDRSAVE(%a6)       # save Dr for later
                   2116:        mov.w           %d1, NDQSAVE(%a6)       # save Dq for later
                   2117:
                   2118: # fetch %dr and %dq directly off stack since all regs are saved there
                   2119:        mov.l           (EXC_DREGS,%a6,%d0.w*4), %d5 # get dividend hi
                   2120:        mov.l           (EXC_DREGS,%a6,%d1.w*4), %d6 # get dividend lo
                   2121:
                   2122: # separate signed and unsigned divide
                   2123:        btst            &0x3, EXC_EXTWORD(%a6)  # signed or unsigned?
                   2124:        beq.b           dspecialcases           # use positive divide
                   2125:
                   2126: # save the sign of the divisor
                   2127: # make divisor unsigned if it's negative
                   2128:        tst.l           %d7                     # chk sign of divisor
                   2129:        slt             NDIVISOR(%a6)           # save sign of divisor
                   2130:        bpl.b           dsgndividend
                   2131:        neg.l           %d7                     # complement negative divisor
                   2132:
                   2133: # save the sign of the dividend
                   2134: # make dividend unsigned if it's negative
                   2135: dsgndividend:
                   2136:        tst.l           %d5                     # chk sign of hi(dividend)
                   2137:        slt             NDIVIDEND(%a6)          # save sign of dividend
                   2138:        bpl.b           dspecialcases
                   2139:
                   2140:        mov.w           &0x0, %cc               # clear 'X' cc bit
                   2141:        negx.l          %d6                     # complement signed dividend
                   2142:        negx.l          %d5
                   2143:
                   2144: # extract some special cases:
                   2145: #      - is (dividend == 0) ?
                   2146: #      - is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div)
                   2147: dspecialcases:
                   2148:        tst.l           %d5                     # is (hi(dividend) == 0)
                   2149:        bne.b           dnormaldivide           # no, so try it the long way
                   2150:
                   2151:        tst.l           %d6                     # is (lo(dividend) == 0), too
                   2152:        beq.w           ddone                   # yes, so (dividend == 0)
                   2153:
                   2154:        cmp.l           %d7,%d6                 # is (divisor <= lo(dividend))
                   2155:        bls.b           d32bitdivide            # yes, so use 32 bit divide
                   2156:
                   2157:        exg             %d5,%d6                 # q = 0, r = dividend
                   2158:        bra.w           divfinish               # can't divide, we're done.
                   2159:
                   2160: d32bitdivide:
                   2161:        tdivu.l         %d7, %d5:%d6            # it's only a 32/32 bit div!
                   2162:
                   2163:        bra.b           divfinish
                   2164:
                   2165: dnormaldivide:
                   2166: # last special case:
                   2167: #      - is hi(dividend) >= divisor ? if yes, then overflow
                   2168:        cmp.l           %d7,%d5
                   2169:        bls.b           ddovf                   # answer won't fit in 32 bits
                   2170:
                   2171: # perform the divide algorithm:
                   2172:        bsr.l           dclassical              # do int divide
                   2173:
                   2174: # separate into signed and unsigned finishes.
                   2175: divfinish:
                   2176:        btst            &0x3, EXC_EXTWORD(%a6)  # do divs, divu separately
                   2177:        beq.b           ddone                   # divu has no processing!!!
                   2178:
                   2179: # it was a divs.l, so ccode setting is a little more complicated...
                   2180:        tst.b           NDIVIDEND(%a6)          # remainder has same sign
                   2181:        beq.b           dcc                     # as dividend.
                   2182:        neg.l           %d5                     # sgn(rem) = sgn(dividend)
                   2183: dcc:
                   2184:        mov.b           NDIVISOR(%a6), %d0
                   2185:        eor.b           %d0, NDIVIDEND(%a6)     # chk if quotient is negative
                   2186:        beq.b           dqpos                   # branch to quot positive
                   2187:
                   2188: # 0x80000000 is the largest number representable as a 32-bit negative
                   2189: # number. the negative of 0x80000000 is 0x80000000.
                   2190:        cmpi.l          %d6, &0x80000000        # will (-quot) fit in 32 bits?
                   2191:        bhi.b           ddovf
                   2192:
                   2193:        neg.l           %d6                     # make (-quot) 2's comp
                   2194:
                   2195:        bra.b           ddone
                   2196:
                   2197: dqpos:
                   2198:        btst            &0x1f, %d6              # will (+quot) fit in 32 bits?
                   2199:        bne.b           ddovf
                   2200:
                   2201: ddone:
                   2202: # at this point, result is normal so ccodes are set based on result.
                   2203:        mov.w           EXC_CC(%a6), %cc
                   2204:        tst.l           %d6                     # set %ccode bits
                   2205:        mov.w           %cc, EXC_CC(%a6)
                   2206:
                   2207:        mov.w           NDRSAVE(%a6), %d0       # get Dr off stack
                   2208:        mov.w           NDQSAVE(%a6), %d1       # get Dq off stack
                   2209:
                   2210: # if the register numbers are the same, only the quotient gets saved.
                   2211: # so, if we always save the quotient second, we save ourselves a cmp&beq
                   2212:        mov.l           %d5, (EXC_DREGS,%a6,%d0.w*4) # save remainder
                   2213:        mov.l           %d6, (EXC_DREGS,%a6,%d1.w*4) # save quotient
                   2214:
                   2215:        rts
                   2216:
                   2217: ddovf:
                   2218:        bset            &0x1, EXC_CC+1(%a6)     # 'V' set on overflow
                   2219:        bclr            &0x0, EXC_CC+1(%a6)     # 'C' cleared on overflow
                   2220:
                   2221:        rts
                   2222:
                   2223: div64eq0:
                   2224:        andi.b          &0x1e, EXC_CC+1(%a6)    # clear 'C' bit on divbyzero
                   2225:        ori.b           &idbyz_flg,SPCOND_FLG(%a6) # set "special case" flag
                   2226:        rts
                   2227:
                   2228: ###########################################################################
                   2229: #########################################################################
                   2230: # This routine uses the 'classical' Algorithm D from Donald Knuth's    #
                   2231: # Art of Computer Programming, vol II, Seminumerical Algorithms.       #
                   2232: # For this implementation b=2**16, and the target is U1U2U3U4/V1V2,    #
                   2233: # where U,V are words of the quadword dividend and longword divisor,   #
                   2234: # and U1, V1 are the most significant words.                           #
                   2235: #                                                                      #
                   2236: # The most sig. longword of the 64 bit dividend must be in %d5, least  #
                   2237: # in %d6. The divisor must be in the variable ddivisor, and the                #
                   2238: # signed/unsigned flag ddusign must be set (0=unsigned,1=signed).      #
                   2239: # The quotient is returned in %d6, remainder in %d5, unless the                #
                   2240: # v (overflow) bit is set in the saved %ccr. If overflow, the dividend #
                   2241: # is unchanged.                                                                #
                   2242: #########################################################################
                   2243: dclassical:
                   2244: # if the divisor msw is 0, use simpler algorithm then the full blown
                   2245: # one at ddknuth:
                   2246:
                   2247:        cmpi.l          %d7, &0xffff
                   2248:        bhi.b           ddknuth                 # go use D. Knuth algorithm
                   2249:
                   2250: # Since the divisor is only a word (and larger than the mslw of the dividend),
                   2251: # a simpler algorithm may be used :
                   2252: # In the general case, four quotient words would be created by
                   2253: # dividing the divisor word into each dividend word. In this case,
                   2254: # the first two quotient words must be zero, or overflow would occur.
                   2255: # Since we already checked this case above, we can treat the most significant
                   2256: # longword of the dividend as (0) remainder (see Knuth) and merely complete
                   2257: # the last two divisions to get a quotient longword and word remainder:
                   2258:
                   2259:        clr.l           %d1
                   2260:        swap            %d5                     # same as r*b if previous step rqd
                   2261:        swap            %d6                     # get u3 to lsw position
                   2262:        mov.w           %d6, %d5                # rb + u3
                   2263:
                   2264:        divu.w          %d7, %d5
                   2265:
                   2266:        mov.w           %d5, %d1                # first quotient word
                   2267:        swap            %d6                     # get u4
                   2268:        mov.w           %d6, %d5                # rb + u4
                   2269:
                   2270:        divu.w          %d7, %d5
                   2271:
                   2272:        swap            %d1
                   2273:        mov.w           %d5, %d1                # 2nd quotient 'digit'
                   2274:        clr.w           %d5
                   2275:        swap            %d5                     # now remainder
                   2276:        mov.l           %d1, %d6                # and quotient
                   2277:
                   2278:        rts
                   2279:
                   2280: ddknuth:
                   2281: # In this algorithm, the divisor is treated as a 2 digit (word) number
                   2282: # which is divided into a 3 digit (word) dividend to get one quotient
                   2283: # digit (word). After subtraction, the dividend is shifted and the
                   2284: # process repeated. Before beginning, the divisor and quotient are
                   2285: # 'normalized' so that the process of estimating the quotient digit
                   2286: # will yield verifiably correct results..
                   2287:
                   2288:        clr.l           DDNORMAL(%a6)           # count of shifts for normalization
                   2289:        clr.b           DDSECOND(%a6)           # clear flag for quotient digits
                   2290:        clr.l           %d1                     # %d1 will hold trial quotient
                   2291: ddnchk:
                   2292:        btst            &31, %d7                # must we normalize? first word of
                   2293:        bne.b           ddnormalized            # divisor (V1) must be >= 65536/2
                   2294:        addq.l          &0x1, DDNORMAL(%a6)     # count normalization shifts
                   2295:        lsl.l           &0x1, %d7               # shift the divisor
                   2296:        lsl.l           &0x1, %d6               # shift u4,u3 with overflow to u2
                   2297:        roxl.l          &0x1, %d5               # shift u1,u2
                   2298:        bra.w           ddnchk
                   2299: ddnormalized:
                   2300:
                   2301: # Now calculate an estimate of the quotient words (msw first, then lsw).
                   2302: # The comments use subscripts for the first quotient digit determination.
                   2303:        mov.l           %d7, %d3                # divisor
                   2304:        mov.l           %d5, %d2                # dividend mslw
                   2305:        swap            %d2
                   2306:        swap            %d3
                   2307:        cmp.w           %d2, %d3                # V1 = U1 ?
                   2308:        bne.b           ddqcalc1
                   2309:        mov.w           &0xffff, %d1            # use max trial quotient word
                   2310:        bra.b           ddadj0
                   2311: ddqcalc1:
                   2312:        mov.l           %d5, %d1
                   2313:
                   2314:        divu.w          %d3, %d1                # use quotient of mslw/msw
                   2315:
                   2316:        andi.l          &0x0000ffff, %d1        # zero any remainder
                   2317: ddadj0:
                   2318:
                   2319: # now test the trial quotient and adjust. This step plus the
                   2320: # normalization assures (according to Knuth) that the trial
                   2321: # quotient will be at worst 1 too large.
                   2322:        mov.l           %d6, -(%sp)
                   2323:        clr.w           %d6                     # word u3 left
                   2324:        swap            %d6                     # in lsw position
                   2325: ddadj1: mov.l          %d7, %d3
                   2326:        mov.l           %d1, %d2
                   2327:        mulu.w          %d7, %d2                # V2q
                   2328:        swap            %d3
                   2329:        mulu.w          %d1, %d3                # V1q
                   2330:        mov.l           %d5, %d4                # U1U2
                   2331:        sub.l           %d3, %d4                # U1U2 - V1q
                   2332:
                   2333:        swap            %d4
                   2334:
                   2335:        mov.w           %d4,%d0
                   2336:        mov.w           %d6,%d4                 # insert lower word (U3)
                   2337:
                   2338:        tst.w           %d0                     # is upper word set?
                   2339:        bne.w           ddadjd1
                   2340:
                   2341: #      add.l           %d6, %d4                # (U1U2 - V1q) + U3
                   2342:
                   2343:        cmp.l           %d2, %d4
                   2344:        bls.b           ddadjd1                 # is V2q > (U1U2-V1q) + U3 ?
                   2345:        subq.l          &0x1, %d1               # yes, decrement and recheck
                   2346:        bra.b           ddadj1
                   2347: ddadjd1:
                   2348: # now test the word by multiplying it by the divisor (V1V2) and comparing
                   2349: # the 3 digit (word) result with the current dividend words
                   2350:        mov.l           %d5, -(%sp)             # save %d5 (%d6 already saved)
                   2351:        mov.l           %d1, %d6
                   2352:        swap            %d6                     # shift answer to ms 3 words
                   2353:        mov.l           %d7, %d5
                   2354:        bsr.l           dmm2
                   2355:        mov.l           %d5, %d2                # now %d2,%d3 are trial*divisor
                   2356:        mov.l           %d6, %d3
                   2357:        mov.l           (%sp)+, %d5             # restore dividend
                   2358:        mov.l           (%sp)+, %d6
                   2359:        sub.l           %d3, %d6
                   2360:        subx.l          %d2, %d5                # subtract double precision
                   2361:        bcc             dd2nd                   # no carry, do next quotient digit
                   2362:        subq.l          &0x1, %d1               # q is one too large
                   2363: # need to add back divisor longword to current ms 3 digits of dividend
                   2364: # - according to Knuth, this is done only 2 out of 65536 times for random
                   2365: # divisor, dividend selection.
                   2366:        clr.l           %d2
                   2367:        mov.l           %d7, %d3
                   2368:        swap            %d3
                   2369:        clr.w           %d3                     # %d3 now ls word of divisor
                   2370:        add.l           %d3, %d6                # aligned with 3rd word of dividend
                   2371:        addx.l          %d2, %d5
                   2372:        mov.l           %d7, %d3
                   2373:        clr.w           %d3                     # %d3 now ms word of divisor
                   2374:        swap            %d3                     # aligned with 2nd word of dividend
                   2375:        add.l           %d3, %d5
                   2376: dd2nd:
                   2377:        tst.b           DDSECOND(%a6)           # both q words done?
                   2378:        bne.b           ddremain
                   2379: # first quotient digit now correct. store digit and shift the
                   2380: # (subtracted) dividend
                   2381:        mov.w           %d1, DDQUOTIENT(%a6)
                   2382:        clr.l           %d1
                   2383:        swap            %d5
                   2384:        swap            %d6
                   2385:        mov.w           %d6, %d5
                   2386:        clr.w           %d6
                   2387:        st              DDSECOND(%a6)           # second digit
                   2388:        bra.w           ddnormalized
                   2389: ddremain:
                   2390: # add 2nd word to quotient, get the remainder.
                   2391:        mov.w           %d1, DDQUOTIENT+2(%a6)
                   2392: # shift down one word/digit to renormalize remainder.
                   2393:        mov.w           %d5, %d6
                   2394:        swap            %d6
                   2395:        swap            %d5
                   2396:        mov.l           DDNORMAL(%a6), %d7      # get norm shift count
                   2397:        beq.b           ddrn
                   2398:        subq.l          &0x1, %d7               # set for loop count
                   2399: ddnlp:
                   2400:        lsr.l           &0x1, %d5               # shift into %d6
                   2401:        roxr.l          &0x1, %d6
                   2402:        dbf             %d7, ddnlp
                   2403: ddrn:
                   2404:        mov.l           %d6, %d5                # remainder
                   2405:        mov.l           DDQUOTIENT(%a6), %d6    # quotient
                   2406:
                   2407:        rts
                   2408: dmm2:
                   2409: # factors for the 32X32->64 multiplication are in %d5 and %d6.
                   2410: # returns 64 bit result in %d5 (hi) %d6(lo).
                   2411: # destroys %d2,%d3,%d4.
                   2412:
                   2413: # multiply hi,lo words of each factor to get 4 intermediate products
                   2414:        mov.l           %d6, %d2
                   2415:        mov.l           %d6, %d3
                   2416:        mov.l           %d5, %d4
                   2417:        swap            %d3
                   2418:        swap            %d4
                   2419:        mulu.w          %d5, %d6                # %d6 <- lsw*lsw
                   2420:        mulu.w          %d3, %d5                # %d5 <- msw-dest*lsw-source
                   2421:        mulu.w          %d4, %d2                # %d2 <- msw-source*lsw-dest
                   2422:        mulu.w          %d4, %d3                # %d3 <- msw*msw
                   2423: # now use swap and addx to consolidate to two longwords
                   2424:        clr.l           %d4
                   2425:        swap            %d6
                   2426:        add.w           %d5, %d6                # add msw of l*l to lsw of m*l product
                   2427:        addx.w          %d4, %d3                # add any carry to m*m product
                   2428:        add.w           %d2, %d6                # add in lsw of other m*l product
                   2429:        addx.w          %d4, %d3                # add any carry to m*m product
                   2430:        swap            %d6                     # %d6 is low 32 bits of final product
                   2431:        clr.w           %d5
                   2432:        clr.w           %d2                     # lsw of two mixed products used,
                   2433:        swap            %d5                     # now use msws of longwords
                   2434:        swap            %d2
                   2435:        add.l           %d2, %d5
                   2436:        add.l           %d3, %d5                # %d5 now ms 32 bits of final product
                   2437:        rts
                   2438:
                   2439: ##########
                   2440: dcontrolmodel_s:
                   2441:        movq.l          &LONG,%d0
                   2442:        bsr.l           _calc_ea                # calc <ea>
                   2443:
                   2444:        cmpi.b          SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
                   2445:        beq.b           dimmed                  # yes
                   2446:
                   2447:        mov.l           %a0,%a2
                   2448:        bsr.l           _dmem_read_long         # fetch divisor from <ea>
                   2449:
                   2450:        tst.l           %d1                     # dfetch error?
                   2451:        bne.b           div64_err               # yes
                   2452:
                   2453:        mov.l           %d0, %d7
                   2454:        bra.w           dgotsrcl
                   2455:
                   2456: # we have to split out immediate data here because it must be read using
                   2457: # imem_read() instead of dmem_read(). this becomes especially important
                   2458: # if the fetch runs into some deadly fault.
                   2459: dimmed:
                   2460:        addq.l          &0x4,EXC_EXTWPTR(%a6)
                   2461:        bsr.l           _imem_read_long         # read immediate value
                   2462:
                   2463:        tst.l           %d1                     # ifetch error?
                   2464:        bne.l           isp_iacc                # yes
                   2465:
                   2466:        mov.l           %d0,%d7
                   2467:        bra.w           dgotsrcl
                   2468:
                   2469: ##########
                   2470:
                   2471: # if dmem_read_long() returns a fail message in d1, the package
                   2472: # must create an access error frame. here, we pass a skeleton fslw
                   2473: # and the failing address to the routine that creates the new frame.
                   2474: # also, we call isp_restore in case the effective addressing mode was
                   2475: # (an)+ or -(an) in which case the previous "an" value must be restored.
                   2476: # FSLW:
                   2477: #      read = true
                   2478: #      size = longword
                   2479: #      TM = data
                   2480: #      software emulation error = true
                   2481: div64_err:
                   2482:        bsr.l           isp_restore             # restore addr reg
                   2483:        mov.l           %a2,%a0                 # pass failing address
                   2484:        mov.l           &0x01010001,%d0         # pass fslw
                   2485:        bra.l           isp_dacc
                   2486:
                   2487: #########################################################################
                   2488: # XDEF ****************************************************************        #
                   2489: #      _mul64(): routine to emulate mul{u,s}.l <ea>,Dh:Dl 32x32->64    #
                   2490: #                                                                      #
                   2491: # XREF ****************************************************************        #
                   2492: #      _calc_ea() - calculate effective address                        #
                   2493: #      isp_iacc() - handle instruction access error exception          #
                   2494: #      isp_dacc() - handle data access error exception                 #
                   2495: #      isp_restore() - restore An on access error w/ -() or ()+        #
                   2496: #                                                                      #
                   2497: # INPUT ***************************************************************        #
                   2498: #      none                                                            #
                   2499: #                                                                      #
                   2500: # OUTPUT **************************************************************        #
                   2501: #      If exiting through isp_dacc...                                  #
                   2502: #              a0 = failing address                                    #
                   2503: #              d0 = FSLW                                               #
                   2504: #      else                                                            #
                   2505: #              none                                                    #
                   2506: #                                                                      #
                   2507: # ALGORITHM ***********************************************************        #
                   2508: #      First, decode the operand location. If it's in Dn, fetch from   #
                   2509: # the stack. If it's in memory, use _calc_ea() to calculate the                #
                   2510: # effective address. Use _dmem_read_long() to fetch at that address.   #
                   2511: # Unless the operand is immediate data. Then use _imem_read_long().    #
                   2512: # Send failures to isp_dacc() or isp_iacc() as appropriate.            #
                   2513: #      If the operands are signed, make them unsigned and save the     #
                   2514: # sign info for later. Perform the multiplication using 16x16->32      #
                   2515: # unsigned multiplies and "add" instructions. Store the high and low   #
                   2516: # portions of the result in the appropriate data registers on the      #
                   2517: # stack. Calculate the condition codes, also.                          #
                   2518: #                                                                      #
                   2519: #########################################################################
                   2520:
                   2521: #############
                   2522: # mul(u,s)l #
                   2523: #############
                   2524:        global          _mul64
                   2525: _mul64:
                   2526:        mov.b           EXC_OPWORD+1(%a6), %d0  # extract src {mode,reg}
                   2527:        cmpi.b          %d0, &0x7               # is src mode Dn or other?
                   2528:        bgt.w           mul64_memop             # src is in memory
                   2529:
                   2530: # multiplier operand in the data register file.
                   2531: # must extract the register number and fetch the operand from the stack.
                   2532: mul64_regop:
                   2533:        andi.w          &0x7, %d0               # extract Dn
                   2534:        mov.l           (EXC_DREGS,%a6,%d0.w*4), %d3 # fetch multiplier
                   2535:
                   2536: # multiplier is in %d3. now, extract Dl and Dh fields and fetch the
                   2537: # multiplicand from the data register specified by Dl.
                   2538: mul64_multiplicand:
                   2539:        mov.w           EXC_EXTWORD(%a6), %d2   # fetch ext word
                   2540:        clr.w           %d1                     # clear Dh reg
                   2541:        mov.b           %d2, %d1                # grab Dh
                   2542:        rol.w           &0x4, %d2               # align Dl byte
                   2543:        andi.w          &0x7, %d2               # extract Dl
                   2544:
                   2545:        mov.l           (EXC_DREGS,%a6,%d2.w*4), %d4 # get multiplicand
                   2546:
                   2547: # check for the case of "zero" result early
                   2548:        tst.l           %d4                     # test multiplicand
                   2549:        beq.w           mul64_zero              # handle zero separately
                   2550:        tst.l           %d3                     # test multiplier
                   2551:        beq.w           mul64_zero              # handle zero separately
                   2552:
                   2553: # multiplier is in %d3 and multiplicand is in %d4.
                   2554: # if the operation is to be signed, then the operands are converted
                   2555: # to unsigned and the result sign is saved for the end.
                   2556:        clr.b           EXC_TEMP(%a6)           # clear temp space
                   2557:        btst            &0x3, EXC_EXTWORD(%a6)  # signed or unsigned?
                   2558:        beq.b           mul64_alg               # unsigned; skip sgn calc
                   2559:
                   2560:        tst.l           %d3                     # is multiplier negative?
                   2561:        bge.b           mul64_chk_md_sgn        # no
                   2562:        neg.l           %d3                     # make multiplier positive
                   2563:        ori.b           &0x1, EXC_TEMP(%a6)     # save multiplier sgn
                   2564:
                   2565: # the result sign is the exclusive or of the operand sign bits.
                   2566: mul64_chk_md_sgn:
                   2567:        tst.l           %d4                     # is multiplicand negative?
                   2568:        bge.b           mul64_alg               # no
                   2569:        neg.l           %d4                     # make multiplicand positive
                   2570:        eori.b          &0x1, EXC_TEMP(%a6)     # calculate correct sign
                   2571:
                   2572: #########################################################################
                   2573: #      63                         32                           0       #
                   2574: #      ----------------------------                                    #
                   2575: #      | hi(mplier) * hi(mplicand)|                                    #
                   2576: #      ----------------------------                                    #
                   2577: #                   -----------------------------                      #
                   2578: #                   | hi(mplier) * lo(mplicand) |                      #
                   2579: #                   -----------------------------                      #
                   2580: #                   -----------------------------                      #
                   2581: #                   | lo(mplier) * hi(mplicand) |                      #
                   2582: #                   -----------------------------                      #
                   2583: #        |                        -----------------------------        #
                   2584: #      --|--                      | lo(mplier) * lo(mplicand) |        #
                   2585: #        |                        -----------------------------        #
                   2586: #      ========================================================        #
                   2587: #      --------------------------------------------------------        #
                   2588: #      |       hi(result)         |        lo(result)         |        #
                   2589: #      --------------------------------------------------------        #
                   2590: #########################################################################
                   2591: mul64_alg:
                   2592: # load temp registers with operands
                   2593:        mov.l           %d3, %d5                # mr in %d5
                   2594:        mov.l           %d3, %d6                # mr in %d6
                   2595:        mov.l           %d4, %d7                # md in %d7
                   2596:        swap            %d6                     # hi(mr) in lo %d6
                   2597:        swap            %d7                     # hi(md) in lo %d7
                   2598:
                   2599: # complete necessary multiplies:
                   2600:        mulu.w          %d4, %d3                # [1] lo(mr) * lo(md)
                   2601:        mulu.w          %d6, %d4                # [2] hi(mr) * lo(md)
                   2602:        mulu.w          %d7, %d5                # [3] lo(mr) * hi(md)
                   2603:        mulu.w          %d7, %d6                # [4] hi(mr) * hi(md)
                   2604:
                   2605: # add lo portions of [2],[3] to hi portion of [1].
                   2606: # add carries produced from these adds to [4].
                   2607: # lo([1]) is the final lo 16 bits of the result.
                   2608:        clr.l           %d7                     # load %d7 w/ zero value
                   2609:        swap            %d3                     # hi([1]) <==> lo([1])
                   2610:        add.w           %d4, %d3                # hi([1]) + lo([2])
                   2611:        addx.l          %d7, %d6                #    [4]  + carry
                   2612:        add.w           %d5, %d3                # hi([1]) + lo([3])
                   2613:        addx.l          %d7, %d6                #    [4]  + carry
                   2614:        swap            %d3                     # lo([1]) <==> hi([1])
                   2615:
                   2616: # lo portions of [2],[3] have been added in to final result.
                   2617: # now, clear lo, put hi in lo reg, and add to [4]
                   2618:        clr.w           %d4                     # clear lo([2])
                   2619:        clr.w           %d5                     # clear hi([3])
                   2620:        swap            %d4                     # hi([2]) in lo %d4
                   2621:        swap            %d5                     # hi([3]) in lo %d5
                   2622:        add.l           %d5, %d4                #    [4]  + hi([2])
                   2623:        add.l           %d6, %d4                #    [4]  + hi([3])
                   2624:
                   2625: # unsigned result is now in {%d4,%d3}
                   2626:        tst.b           EXC_TEMP(%a6)           # should result be signed?
                   2627:        beq.b           mul64_done              # no
                   2628:
                   2629: # result should be a signed negative number.
                   2630: # compute 2's complement of the unsigned number:
                   2631: #   -negate all bits and add 1
                   2632: mul64_neg:
                   2633:        not.l           %d3                     # negate lo(result) bits
                   2634:        not.l           %d4                     # negate hi(result) bits
                   2635:        addq.l          &1, %d3                 # add 1 to lo(result)
                   2636:        addx.l          %d7, %d4                # add carry to hi(result)
                   2637:
                   2638: # the result is saved to the register file.
                   2639: # for '040 compatibility, if Dl == Dh then only the hi(result) is
                   2640: # saved. so, saving hi after lo accomplishes this without need to
                   2641: # check Dl,Dh equality.
                   2642: mul64_done:
                   2643:        mov.l           %d3, (EXC_DREGS,%a6,%d2.w*4) # save lo(result)
                   2644:        mov.w           &0x0, %cc
                   2645:        mov.l           %d4, (EXC_DREGS,%a6,%d1.w*4) # save hi(result)
                   2646:
                   2647: # now, grab the condition codes. only one that can be set is 'N'.
                   2648: # 'N' CAN be set if the operation is unsigned if bit 63 is set.
                   2649:        mov.w           %cc, %d7                # fetch %ccr to see if 'N' set
                   2650:        andi.b          &0x8, %d7               # extract 'N' bit
                   2651:
                   2652: mul64_ccode_set:
                   2653:        mov.b           EXC_CC+1(%a6), %d6      # fetch previous %ccr
                   2654:        andi.b          &0x10, %d6              # all but 'X' bit changes
                   2655:
                   2656:        or.b            %d7, %d6                # group 'X' and 'N'
                   2657:        mov.b           %d6, EXC_CC+1(%a6)      # save new %ccr
                   2658:
                   2659:        rts
                   2660:
                   2661: # one or both of the operands is zero so the result is also zero.
                   2662: # save the zero result to the register file and set the 'Z' ccode bit.
                   2663: mul64_zero:
                   2664:        clr.l           (EXC_DREGS,%a6,%d2.w*4) # save lo(result)
                   2665:        clr.l           (EXC_DREGS,%a6,%d1.w*4) # save hi(result)
                   2666:
                   2667:        movq.l          &0x4, %d7               # set 'Z' ccode bit
                   2668:        bra.b           mul64_ccode_set         # finish ccode set
                   2669:
                   2670: ##########
                   2671:
                   2672: # multiplier operand is in memory at the effective address.
                   2673: # must calculate the <ea> and go fetch the 32-bit operand.
                   2674: mul64_memop:
                   2675:        movq.l          &LONG, %d0              # pass # of bytes
                   2676:        bsr.l           _calc_ea                # calculate <ea>
                   2677:
                   2678:        cmpi.b          SPCOND_FLG(%a6),&immed_flg # immediate addressing mode?
                   2679:        beq.b           mul64_immed             # yes
                   2680:
                   2681:        mov.l           %a0,%a2
                   2682:        bsr.l           _dmem_read_long         # fetch src from addr (%a0)
                   2683:
                   2684:        tst.l           %d1                     # dfetch error?
                   2685:        bne.w           mul64_err               # yes
                   2686:
                   2687:        mov.l           %d0, %d3                # store multiplier in %d3
                   2688:
                   2689:        bra.w           mul64_multiplicand
                   2690:
                   2691: # we have to split out immediate data here because it must be read using
                   2692: # imem_read() instead of dmem_read(). this becomes especially important
                   2693: # if the fetch runs into some deadly fault.
                   2694: mul64_immed:
                   2695:        addq.l          &0x4,EXC_EXTWPTR(%a6)
                   2696:        bsr.l           _imem_read_long         # read immediate value
                   2697:
                   2698:        tst.l           %d1                     # ifetch error?
                   2699:        bne.l           isp_iacc                # yes
                   2700:
                   2701:        mov.l           %d0,%d3
                   2702:        bra.w           mul64_multiplicand
                   2703:
                   2704: ##########
                   2705:
                   2706: # if dmem_read_long() returns a fail message in d1, the package
                   2707: # must create an access error frame. here, we pass a skeleton fslw
                   2708: # and the failing address to the routine that creates the new frame.
                   2709: # also, we call isp_restore in case the effective addressing mode was
                   2710: # (an)+ or -(an) in which case the previous "an" value must be restored.
                   2711: # FSLW:
                   2712: #      read = true
                   2713: #      size = longword
                   2714: #      TM = data
                   2715: #      software emulation error = true
                   2716: mul64_err:
                   2717:        bsr.l           isp_restore             # restore addr reg
                   2718:        mov.l           %a2,%a0                 # pass failing address
                   2719:        mov.l           &0x01010001,%d0         # pass fslw
                   2720:        bra.l           isp_dacc
                   2721:
                   2722: #########################################################################
                   2723: # XDEF ****************************************************************        #
                   2724: #      _compandset2(): routine to emulate cas2()                       #
                   2725: #                      (internal to package)                           #
                   2726: #                                                                      #
                   2727: #      _isp_cas2_finish(): store ccodes, store compare regs            #
                   2728: #                          (external to package)                       #
                   2729: #                                                                      #
                   2730: # XREF ****************************************************************        #
                   2731: #      _real_lock_page() - "callout" to lock op's page from page-outs  #
                   2732: #      _cas_terminate2() - access error exit                           #
                   2733: #      _real_cas2() - "callout" to core cas2 emulation code            #
                   2734: #      _real_unlock_page() - "callout" to unlock page                  #
                   2735: #                                                                      #
                   2736: # INPUT ***************************************************************        #
                   2737: # _compandset2():                                                      #
                   2738: #      d0 = instruction extension word                                 #
                   2739: #                                                                      #
                   2740: # _isp_cas2_finish():                                                  #
                   2741: #      see cas2 core emulation code                                    #
                   2742: #                                                                      #
                   2743: # OUTPUT **************************************************************        #
                   2744: # _compandset2():                                                      #
                   2745: #      see cas2 core emulation code                                    #
                   2746: #                                                                      #
                   2747: # _isp_cas_finish():                                                   #
                   2748: #      None (register file or memroy changed as appropriate)           #
                   2749: #                                                                      #
                   2750: # ALGORITHM ***********************************************************        #
                   2751: # compandset2():                                                       #
                   2752: #      Decode the instruction and fetch the appropriate Update and     #
                   2753: # Compare operands. Then call the "callout" _real_lock_page() for each #
                   2754: # memory operand address so that the operating system can keep these   #
                   2755: # pages from being paged out. If either _real_lock_page() fails, exit  #
                   2756: # through _cas_terminate2(). Don't forget to unlock the 1st locked page        #
                   2757: # using _real_unlock_paged() if the 2nd lock-page fails.               #
                   2758: # Finally, branch to the core cas2 emulation code by calling the       #
                   2759: # "callout" _real_cas2().                                              #
                   2760: #                                                                      #
                   2761: # _isp_cas2_finish():                                                  #
                   2762: #      Re-perform the comparison so we can determine the condition     #
                   2763: # codes which were too much trouble to keep around during the locked   #
                   2764: # emulation. Then unlock each operands page by calling the "callout"   #
                   2765: # _real_unlock_page().                                                 #
                   2766: #                                                                      #
                   2767: #########################################################################
                   2768:
                   2769: set ADDR1,     EXC_TEMP+0xc
                   2770: set ADDR2,     EXC_TEMP+0x0
                   2771: set DC2,       EXC_TEMP+0xa
                   2772: set DC1,       EXC_TEMP+0x8
                   2773:
                   2774:        global          _compandset2
                   2775: _compandset2:
                   2776:        mov.l           %d0,EXC_TEMP+0x4(%a6)           # store for possible restart
                   2777:        mov.l           %d0,%d1                 # extension word in d0
                   2778:
                   2779:        rol.w           &0x4,%d0
                   2780:        andi.w          &0xf,%d0                # extract Rn2
                   2781:        mov.l           (EXC_DREGS,%a6,%d0.w*4),%a1 # fetch ADDR2
                   2782:        mov.l           %a1,ADDR2(%a6)
                   2783:
                   2784:        mov.l           %d1,%d0
                   2785:
                   2786:        lsr.w           &0x6,%d1
                   2787:        andi.w          &0x7,%d1                # extract Du2
                   2788:        mov.l           (EXC_DREGS,%a6,%d1.w*4),%d5 # fetch Update2 Op
                   2789:
                   2790:        andi.w          &0x7,%d0                # extract Dc2
                   2791:        mov.l           (EXC_DREGS,%a6,%d0.w*4),%d3 # fetch Compare2 Op
                   2792:        mov.w           %d0,DC2(%a6)
                   2793:
                   2794:        mov.w           EXC_EXTWORD(%a6),%d0
                   2795:        mov.l           %d0,%d1
                   2796:
                   2797:        rol.w           &0x4,%d0
                   2798:        andi.w          &0xf,%d0                # extract Rn1
                   2799:        mov.l           (EXC_DREGS,%a6,%d0.w*4),%a0 # fetch ADDR1
                   2800:        mov.l           %a0,ADDR1(%a6)
                   2801:
                   2802:        mov.l           %d1,%d0
                   2803:
                   2804:        lsr.w           &0x6,%d1
                   2805:        andi.w          &0x7,%d1                # extract Du1
                   2806:        mov.l           (EXC_DREGS,%a6,%d1.w*4),%d4 # fetch Update1 Op
                   2807:
                   2808:        andi.w          &0x7,%d0                # extract Dc1
                   2809:        mov.l           (EXC_DREGS,%a6,%d0.w*4),%d2 # fetch Compare1 Op
                   2810:        mov.w           %d0,DC1(%a6)
                   2811:
                   2812:        btst            &0x1,EXC_OPWORD(%a6)    # word or long?
                   2813:        sne             %d7
                   2814:
                   2815:        btst            &0x5,EXC_ISR(%a6)       # user or supervisor?
                   2816:        sne             %d6
                   2817:
                   2818:        mov.l           %a0,%a2
                   2819:        mov.l           %a1,%a3
                   2820:
                   2821:        mov.l           %d7,%d1                 # pass size
                   2822:        mov.l           %d6,%d0                 # pass mode
                   2823:        bsr.l           _real_lock_page         # lock page
                   2824:        mov.l           %a2,%a0
                   2825:        tst.l           %d0                     # error?
                   2826:        bne.l           _cas_terminate2         # yes
                   2827:
                   2828:        mov.l           %d7,%d1                 # pass size
                   2829:        mov.l           %d6,%d0                 # pass mode
                   2830:        mov.l           %a3,%a0                 # pass addr
                   2831:        bsr.l           _real_lock_page         # lock page
                   2832:        mov.l           %a3,%a0
                   2833:        tst.l           %d0                     # error?
                   2834:        bne.b           cas_preterm             # yes
                   2835:
                   2836:        mov.l           %a2,%a0
                   2837:        mov.l           %a3,%a1
                   2838:
                   2839:        bra.l           _real_cas2
                   2840:
                   2841: # if the 2nd lock attempt fails, then we must still unlock the
                   2842: # first page(s).
                   2843: cas_preterm:
                   2844:        mov.l           %d0,-(%sp)              # save FSLW
                   2845:        mov.l           %d7,%d1                 # pass size
                   2846:        mov.l           %d6,%d0                 # pass mode
                   2847:        mov.l           %a2,%a0                 # pass ADDR1
                   2848:        bsr.l           _real_unlock_page       # unlock first page(s)
                   2849:        mov.l           (%sp)+,%d0              # restore FSLW
                   2850:        mov.l           %a3,%a0                 # pass failing addr
                   2851:        bra.l           _cas_terminate2
                   2852:
                   2853: #############################################################
                   2854:
                   2855:        global          _isp_cas2_finish
                   2856: _isp_cas2_finish:
                   2857:        btst            &0x1,EXC_OPWORD(%a6)
                   2858:        bne.b           cas2_finish_l
                   2859:
                   2860:        mov.w           EXC_CC(%a6),%cc         # load old ccodes
                   2861:        cmp.w           %d0,%d2
                   2862:        bne.b           cas2_finish_w_save
                   2863:        cmp.w           %d1,%d3
                   2864: cas2_finish_w_save:
                   2865:        mov.w           %cc,EXC_CC(%a6)         # save new ccodes
                   2866:
                   2867:        tst.b           %d4                     # update compare reg?
                   2868:        bne.b           cas2_finish_w_done      # no
                   2869:
                   2870:        mov.w           DC2(%a6),%d3            # fetch Dc2
                   2871:        mov.w           %d1,(2+EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
                   2872:
                   2873:        mov.w           DC1(%a6),%d2            # fetch Dc1
                   2874:        mov.w           %d0,(2+EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
                   2875:
                   2876: cas2_finish_w_done:
                   2877:        btst            &0x5,EXC_ISR(%a6)
                   2878:        sne             %d2
                   2879:        mov.l           %d2,%d0                 # pass mode
                   2880:        sf              %d1                     # pass size
                   2881:        mov.l           ADDR1(%a6),%a0          # pass ADDR1
                   2882:        bsr.l           _real_unlock_page       # unlock page
                   2883:
                   2884:        mov.l           %d2,%d0                 # pass mode
                   2885:        sf              %d1                     # pass size
                   2886:        mov.l           ADDR2(%a6),%a0          # pass ADDR2
                   2887:        bsr.l           _real_unlock_page       # unlock page
                   2888:        rts
                   2889:
                   2890: cas2_finish_l:
                   2891:        mov.w           EXC_CC(%a6),%cc         # load old ccodes
                   2892:        cmp.l           %d0,%d2
                   2893:        bne.b           cas2_finish_l_save
                   2894:        cmp.l           %d1,%d3
                   2895: cas2_finish_l_save:
                   2896:        mov.w           %cc,EXC_CC(%a6)         # save new ccodes
                   2897:
                   2898:        tst.b           %d4                     # update compare reg?
                   2899:        bne.b           cas2_finish_l_done      # no
                   2900:
                   2901:        mov.w           DC2(%a6),%d3            # fetch Dc2
                   2902:        mov.l           %d1,(EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op
                   2903:
                   2904:        mov.w           DC1(%a6),%d2            # fetch Dc1
                   2905:        mov.l           %d0,(EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op
                   2906:
                   2907: cas2_finish_l_done:
                   2908:        btst            &0x5,EXC_ISR(%a6)
                   2909:        sne             %d2
                   2910:        mov.l           %d2,%d0                 # pass mode
                   2911:        st              %d1                     # pass size
                   2912:        mov.l           ADDR1(%a6),%a0          # pass ADDR1
                   2913:        bsr.l           _real_unlock_page       # unlock page
                   2914:
                   2915:        mov.l           %d2,%d0                 # pass mode
                   2916:        st              %d1                     # pass size
                   2917:        mov.l           ADDR2(%a6),%a0          # pass ADDR2
                   2918:        bsr.l           _real_unlock_page       # unlock page
                   2919:        rts
                   2920:
                   2921: ########
                   2922:        global          cr_cas2
                   2923: cr_cas2:
                   2924:        mov.l           EXC_TEMP+0x4(%a6),%d0
                   2925:        bra.w           _compandset2
                   2926:
                   2927: #########################################################################
                   2928: # XDEF ****************************************************************        #
                   2929: #      _compandset(): routine to emulate cas w/ misaligned <ea>        #
                   2930: #                     (internal to package)                            #
                   2931: #      _isp_cas_finish(): routine called when cas emulation completes  #
                   2932: #                         (external and internal to package)           #
                   2933: #      _isp_cas_restart(): restart cas emulation after a fault         #
                   2934: #                          (external to package)                       #
                   2935: #      _isp_cas_terminate(): create access error stack frame on fault  #
                   2936: #                            (external and internal to package)        #
                   2937: #      _isp_cas_inrange(): checks whether instr addr is within range   #
                   2938: #                          of core cas/cas2emulation code              #
                   2939: #                          (external to package)                       #
                   2940: #                                                                      #
                   2941: # XREF ****************************************************************        #
                   2942: #      _calc_ea(): calculate effective address                         #
                   2943: #                                                                      #
                   2944: # INPUT ***************************************************************        #
                   2945: # compandset():                                                                #
                   2946: #      none                                                            #
                   2947: # _isp_cas_restart():                                                  #
                   2948: #      d6 = previous sfc/dfc                                           #
                   2949: # _isp_cas_finish():                                                   #
                   2950: # _isp_cas_terminate():                                                        #
                   2951: #      a0 = failing address                                            #
                   2952: #      d0 = FSLW                                                       #
                   2953: #      d6 = previous sfc/dfc                                           #
                   2954: # _isp_cas_inrange():                                                  #
                   2955: #      a0 = instruction address to be checked                          #
                   2956: #                                                                      #
                   2957: # OUTPUT **************************************************************        #
                   2958: # compandset():                                                                #
                   2959: #              none                                                    #
                   2960: # _isp_cas_restart():                                                  #
                   2961: #      a0 = effective address                                          #
                   2962: #      d7 = word or longword flag                                      #
                   2963: # _isp_cas_finish():                                                   #
                   2964: #      a0 = effective address                                          #
                   2965: # _isp_cas_terminate():                                                        #
                   2966: #      initial register set before emulation exception                 #
                   2967: # _isp_cas_inrange():                                                  #
                   2968: #      d0 = 0 => in range; -1 => out of range                          #
                   2969: #                                                                      #
                   2970: # ALGORITHM ***********************************************************        #
                   2971: #                                                                      #
                   2972: # compandset():                                                                #
                   2973: #      First, calculate the effective address. Then, decode the        #
                   2974: # instruction word and fetch the "compare" (DC) and "update" (Du)      #
                   2975: # operands.                                                            #
                   2976: #      Next, call the external routine _real_lock_page() so that the   #
                   2977: # operating system can keep this page from being paged out while we're #
                   2978: # in this routine. If this call fails, jump to _cas_terminate2().      #
                   2979: #      The routine then branches to _real_cas(). This external routine #
                   2980: # that actually emulates cas can be supplied by the external os or     #
                   2981: # made to point directly back into the 060ISP which has a routine for  #
                   2982: # this purpose.                                                                #
                   2983: #                                                                      #
                   2984: # _isp_cas_finish():                                                   #
                   2985: #      Either way, after emulation, the package is re-entered at       #
                   2986: # _isp_cas_finish(). This routine re-compares the operands in order to #
                   2987: # set the condition codes. Finally, these routines will call           #
                   2988: # _real_unlock_page() in order to unlock the pages that were previously        #
                   2989: # locked.                                                              #
                   2990: #                                                                      #
                   2991: # _isp_cas_restart():                                                  #
                   2992: #      This routine can be entered from an access error handler where  #
                   2993: # the emulation sequence should be re-started from the beginning.      #
                   2994: #                                                                      #
                   2995: # _isp_cas_terminate():                                                        #
                   2996: #      This routine can be entered from an access error handler where  #
                   2997: # an emulation operand access failed and the operating system would    #
                   2998: # like an access error stack frame created instead of the current      #
                   2999: # unimplemented integer instruction frame.                             #
                   3000: #      Also, the package enters here if a call to _real_lock_page()    #
                   3001: # fails.                                                               #
                   3002: #                                                                      #
                   3003: # _isp_cas_inrange():                                                  #
                   3004: #      Checks to see whether the instruction address passed to it in   #
                   3005: # a0 is within the software package cas/cas2 emulation routines. This  #
                   3006: # can be helpful for an operating system to determine whether an access        #
                   3007: # error during emulation was due to a cas/cas2 emulation access.       #
                   3008: #                                                                      #
                   3009: #########################################################################
                   3010:
                   3011: set DC,                EXC_TEMP+0x8
                   3012: set ADDR,      EXC_TEMP+0x4
                   3013:
                   3014:        global          _compandset
                   3015: _compandset:
                   3016:        btst            &0x1,EXC_OPWORD(%a6)    # word or long operation?
                   3017:        bne.b           compandsetl             # long
                   3018:
                   3019: compandsetw:
                   3020:        movq.l          &0x2,%d0                # size = 2 bytes
                   3021:        bsr.l           _calc_ea                # a0 = calculated <ea>
                   3022:        mov.l           %a0,ADDR(%a6)           # save <ea> for possible restart
                   3023:        sf              %d7                     # clear d7 for word size
                   3024:        bra.b           compandsetfetch
                   3025:
                   3026: compandsetl:
                   3027:        movq.l          &0x4,%d0                # size = 4 bytes
                   3028:        bsr.l           _calc_ea                # a0 = calculated <ea>
                   3029:        mov.l           %a0,ADDR(%a6)           # save <ea> for possible restart
                   3030:        st              %d7                     # set d7 for longword size
                   3031:
                   3032: compandsetfetch:
                   3033:        mov.w           EXC_EXTWORD(%a6),%d0    # fetch cas extension word
                   3034:        mov.l           %d0,%d1                 # make a copy
                   3035:
                   3036:        lsr.w           &0x6,%d0
                   3037:        andi.w          &0x7,%d0                # extract Du
                   3038:        mov.l           (EXC_DREGS,%a6,%d0.w*4),%d2 # get update operand
                   3039:
                   3040:        andi.w          &0x7,%d1                # extract Dc
                   3041:        mov.l           (EXC_DREGS,%a6,%d1.w*4),%d4 # get compare operand
                   3042:        mov.w           %d1,DC(%a6)             # save Dc
                   3043:
                   3044:        btst            &0x5,EXC_ISR(%a6)       # which mode for exception?
                   3045:        sne             %d6                     # set on supervisor mode
                   3046:
                   3047:        mov.l           %a0,%a2                 # save temporarily
                   3048:        mov.l           %d7,%d1                 # pass size
                   3049:        mov.l           %d6,%d0                 # pass mode
                   3050:        bsr.l           _real_lock_page         # lock page
                   3051:        tst.l           %d0                     # did error occur?
                   3052:        bne.w           _cas_terminate2         # yes, clean up the mess
                   3053:        mov.l           %a2,%a0                 # pass addr in a0
                   3054:
                   3055:        bra.l           _real_cas
                   3056:
                   3057: ########
                   3058:        global          _isp_cas_finish
                   3059: _isp_cas_finish:
                   3060:        btst            &0x1,EXC_OPWORD(%a6)
                   3061:        bne.b           cas_finish_l
                   3062:
                   3063: # just do the compare again since it's faster than saving the ccodes
                   3064: # from the locked routine...
                   3065: cas_finish_w:
                   3066:        mov.w           EXC_CC(%a6),%cc         # restore cc
                   3067:        cmp.w           %d0,%d4                 # do word compare
                   3068:        mov.w           %cc,EXC_CC(%a6)         # save cc
                   3069:
                   3070:        tst.b           %d1                     # update compare reg?
                   3071:        bne.b           cas_finish_w_done       # no
                   3072:
                   3073:        mov.w           DC(%a6),%d3
                   3074:        mov.w           %d0,(EXC_DREGS+2,%a6,%d3.w*4) # Dc = destination
                   3075:
                   3076: cas_finish_w_done:
                   3077:        mov.l           ADDR(%a6),%a0           # pass addr
                   3078:        sf              %d1                     # pass size
                   3079:        btst            &0x5,EXC_ISR(%a6)
                   3080:        sne             %d0                     # pass mode
                   3081:        bsr.l           _real_unlock_page       # unlock page
                   3082:        rts
                   3083:
                   3084: # just do the compare again since it's faster than saving the ccodes
                   3085: # from the locked routine...
                   3086: cas_finish_l:
                   3087:        mov.w           EXC_CC(%a6),%cc         # restore cc
                   3088:        cmp.l           %d0,%d4                 # do longword compare
                   3089:        mov.w           %cc,EXC_CC(%a6)         # save cc
                   3090:
                   3091:        tst.b           %d1                     # update compare reg?
                   3092:        bne.b           cas_finish_l_done       # no
                   3093:
                   3094:        mov.w           DC(%a6),%d3
                   3095:        mov.l           %d0,(EXC_DREGS,%a6,%d3.w*4) # Dc = destination
                   3096:
                   3097: cas_finish_l_done:
                   3098:        mov.l           ADDR(%a6),%a0           # pass addr
                   3099:        st              %d1                     # pass size
                   3100:        btst            &0x5,EXC_ISR(%a6)
                   3101:        sne             %d0                     # pass mode
                   3102:        bsr.l           _real_unlock_page       # unlock page
                   3103:        rts
                   3104:
                   3105: ########
                   3106:
                   3107:        global          _isp_cas_restart
                   3108: _isp_cas_restart:
                   3109:        mov.l           %d6,%sfc                # restore previous sfc
                   3110:        mov.l           %d6,%dfc                # restore previous dfc
                   3111:
                   3112:        cmpi.b          EXC_OPWORD+1(%a6),&0xfc # cas or cas2?
                   3113:        beq.l           cr_cas2                 # cas2
                   3114: cr_cas:
                   3115:        mov.l           ADDR(%a6),%a0           # load <ea>
                   3116:        btst            &0x1,EXC_OPWORD(%a6)    # word or long operation?
                   3117:        sne             %d7                     # set d7 accordingly
                   3118:        bra.w           compandsetfetch
                   3119:
                   3120: ########
                   3121:
                   3122: # At this stage, it would be nice if d0 held the FSLW.
                   3123:        global          _isp_cas_terminate
                   3124: _isp_cas_terminate:
                   3125:        mov.l           %d6,%sfc                # restore previous sfc
                   3126:        mov.l           %d6,%dfc                # restore previous dfc
                   3127:
                   3128:        global          _cas_terminate2
                   3129: _cas_terminate2:
                   3130:        mov.l           %a0,%a2                 # copy failing addr to a2
                   3131:
                   3132:        mov.l           %d0,-(%sp)
                   3133:        bsr.l           isp_restore             # restore An (if ()+ or -())
                   3134:        mov.l           (%sp)+,%d0
                   3135:
                   3136:        addq.l          &0x4,%sp                # remove sub return addr
                   3137:        subq.l          &0x8,%sp                # make room for bigger stack
                   3138:        subq.l          &0x8,%a6                # shift frame ptr down, too
                   3139:        mov.l           &26,%d1                 # want to move 51 longwords
                   3140:        lea             0x8(%sp),%a0            # get address of old stack
                   3141:        lea             0x0(%sp),%a1            # get address of new stack
                   3142: cas_term_cont:
                   3143:        mov.l           (%a0)+,(%a1)+           # move a longword
                   3144:        dbra.w          %d1,cas_term_cont       # keep going
                   3145:
                   3146:        mov.w           &0x4008,EXC_IVOFF(%a6)  # put new stk fmt, voff
                   3147:        mov.l           %a2,EXC_IVOFF+0x2(%a6)  # put faulting addr on stack
                   3148:        mov.l           %d0,EXC_IVOFF+0x6(%a6)  # put FSLW on stack
                   3149:        movm.l          EXC_DREGS(%a6),&0x3fff  # restore user regs
                   3150:        unlk            %a6                     # unlink stack frame
                   3151:        bra.l           _real_access
                   3152:
                   3153: ########
                   3154:
                   3155:        global          _isp_cas_inrange
                   3156: _isp_cas_inrange:
                   3157:        clr.l           %d0                     # clear return result
                   3158:        lea             _CASHI(%pc),%a1         # load end of CAS core code
                   3159:        cmp.l           %a1,%a0                 # is PC in range?
                   3160:        blt.b           cin_no                  # no
                   3161:        lea             _CASLO(%pc),%a1         # load begin of CAS core code
                   3162:        cmp.l           %a0,%a1                 # is PC in range?
                   3163:        blt.b           cin_no                  # no
                   3164:        rts                                     # yes; return d0 = 0
                   3165: cin_no:
                   3166:        mov.l           &-0x1,%d0               # out of range; return d0 = -1
                   3167:        rts
                   3168:
                   3169: #################################################################
                   3170: #################################################################
                   3171: #################################################################
                   3172: # This is the start of the cas and cas2 "core" emulation code. #
                   3173: # This is the section that may need to be replaced by the host #
                   3174: # OS if it is too operating system-specific.                   #
                   3175: # Please refer to the package documentation to see how to      #
                   3176: # "replace" this section, if necessary.                                #
                   3177: #################################################################
                   3178: #################################################################
                   3179: #################################################################
                   3180:
                   3181: #       ######      ##      ######     ####
                   3182: #       #         #  #     #         #    #
                   3183: #      #         ######    ######        #
                   3184: #      #         #    #         #      #
                   3185: #       ######    #    #    ######    ######
                   3186:
                   3187: #########################################################################
                   3188: # XDEF ****************************************************************        #
                   3189: #      _isp_cas2(): "core" emulation code for the cas2 instruction     #
                   3190: #                                                                      #
                   3191: # XREF ****************************************************************        #
                   3192: #      _isp_cas2_finish() - only exit point for this emulation code;   #
                   3193: #                           do clean-up; calculate ccodes; store       #
                   3194: #                           Compare Ops if appropriate.                #
                   3195: #                                                                      #
                   3196: # INPUT ***************************************************************        #
                   3197: #      *see chart below*                                               #
                   3198: #                                                                      #
                   3199: # OUTPUT **************************************************************        #
                   3200: #      *see chart below*                                               #
                   3201: #                                                                      #
                   3202: # ALGORITHM ***********************************************************        #
                   3203: #      (1) Make several copies of the effective address.               #
                   3204: #      (2) Save current SR; Then mask off all maskable interrupts.     #
                   3205: #      (3) Save current SFC/DFC (ASSUMED TO BE EQUAL!!!); Then set     #
                   3206: #          according to whether exception occurred in user or          #
                   3207: #          supervisor mode.                                            #
                   3208: #      (4) Use "plpaw" instruction to pre-load ATC with effective      #
                   3209: #          address pages(s). THIS SHOULD NOT FAULT!!! The relevant     #
                   3210: #          page(s) should have already been made resident prior to     #
                   3211: #          entering this routine.                                      #
                   3212: #      (5) Push the operand lines from the cache w/ "cpushl".          #
                   3213: #          In the 68040, this was done within the locked region. In    #
                   3214: #          the 68060, it is done outside of the locked region.         #
                   3215: #      (6) Use "plpar" instruction to do a re-load of ATC entries for  #
                   3216: #          ADDR1 since ADDR2 entries may have pushed ADDR1 out of the  #
                   3217: #          ATC.                                                        #
                   3218: #      (7) Pre-fetch the core emulation instructions by executing      #
                   3219: #          one branch within each physical line (16 bytes) of the code #
                   3220: #          before actually executing the code.                         #
                   3221: #      (8) Load the BUSCR w/ the bus lock value.                       #
                   3222: #      (9) Fetch the source operands using "moves".                    #
                   3223: #      (10)Do the compares. If both equal, go to step (13).            #
                   3224: #      (11)Unequal. No update occurs. But, we do write the DST1 op     #
                   3225: #          back to itself (as w/ the '040) so we can gracefully unlock #
                   3226: #          the bus (and assert LOCKE*) using BUSCR and the final move. #
                   3227: #      (12)Exit.                                                       #
                   3228: #      (13)Write update operand to the DST locations. Use BUSCR to     #
                   3229: #          assert LOCKE* for the final write operation.                #
                   3230: #      (14)Exit.                                                       #
                   3231: #                                                                      #
                   3232: #      The algorithm is actually implemented slightly differently      #
                   3233: # depending on the size of the operation and the misalignment of the   #
                   3234: # operands. A misaligned operand must be written in aligned chunks or  #
                   3235: # else the BUSCR register control gets confused.                       #
                   3236: #                                                                      #
                   3237: #########################################################################
                   3238:
                   3239: #################################################################
                   3240: # THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON          #
                   3241: # ENTERING _isp_cas2().                                                #
                   3242: #                                                              #
                   3243: # D0 = xxxxxxxx                                                        #
                   3244: # D1 = xxxxxxxx                                                        #
                   3245: # D2 = cmp operand 1                                           #
                   3246: # D3 = cmp operand 2                                           #
                   3247: # D4 = update oper 1                                           #
                   3248: # D5 = update oper 2                                           #
                   3249: # D6 = 'xxxxxxff if supervisor mode; 'xxxxxx00 if user mode    #
                   3250: # D7 = 'xxxxxxff if longword operation; 'xxxxxx00 if word      #
                   3251: # A0 = ADDR1                                                   #
                   3252: # A1 = ADDR2                                                   #
                   3253: # A2 = xxxxxxxx                                                        #
                   3254: # A3 = xxxxxxxx                                                        #
                   3255: # A4 = xxxxxxxx                                                        #
                   3256: # A5 = xxxxxxxx                                                        #
                   3257: # A6 = frame pointer                                           #
                   3258: # A7 = stack pointer                                           #
                   3259: #################################################################
                   3260:
                   3261: #      align           0x1000
                   3262: # beginning label used by _isp_cas_inrange()
                   3263:        global          _CASLO
                   3264: _CASLO:
                   3265:
                   3266:        global          _isp_cas2
                   3267: _isp_cas2:
                   3268:        tst.b           %d6                     # user or supervisor mode?
                   3269:        bne.b           cas2_supervisor         # supervisor
                   3270: cas2_user:
                   3271:        movq.l          &0x1,%d0                # load user data fc
                   3272:        bra.b           cas2_cont
                   3273: cas2_supervisor:
                   3274:        movq.l          &0x5,%d0                # load supervisor data fc
                   3275: cas2_cont:
                   3276:        tst.b           %d7                     # word or longword?
                   3277:        beq.w           cas2w                   # word
                   3278:
                   3279: ####
                   3280: cas2l:
                   3281:        mov.l           %a0,%a2                 # copy ADDR1
                   3282:        mov.l           %a1,%a3                 # copy ADDR2
                   3283:        mov.l           %a0,%a4                 # copy ADDR1
                   3284:        mov.l           %a1,%a5                 # copy ADDR2
                   3285:
                   3286:        addq.l          &0x3,%a4                # ADDR1+3
                   3287:        addq.l          &0x3,%a5                # ADDR2+3
                   3288:        mov.l           %a2,%d1                 # ADDR1
                   3289:
                   3290: # mask interrupts levels 0-6. save old mask value.
                   3291:        mov.w           %sr,%d7                 # save current SR
                   3292:        ori.w           &0x0700,%sr             # inhibit interrupts
                   3293:
                   3294: # load the SFC and DFC with the appropriate mode.
                   3295:        movc            %sfc,%d6                # save old SFC/DFC
                   3296:        movc            %d0,%sfc                # store new SFC
                   3297:        movc            %d0,%dfc                # store new DFC
                   3298:
                   3299: # pre-load the operand ATC. no page faults should occur here because
                   3300: # _real_lock_page() should have taken care of this.
                   3301:        plpaw           (%a2)                   # load atc for ADDR1
                   3302:        plpaw           (%a4)                   # load atc for ADDR1+3
                   3303:        plpaw           (%a3)                   # load atc for ADDR2
                   3304:        plpaw           (%a5)                   # load atc for ADDR2+3
                   3305:
                   3306: # push the operand lines from the cache if they exist.
                   3307:        cpushl          %dc,(%a2)               # push line for ADDR1
                   3308:        cpushl          %dc,(%a4)               # push line for ADDR1+3
                   3309:        cpushl          %dc,(%a3)               # push line for ADDR2
                   3310:        cpushl          %dc,(%a5)               # push line for ADDR2+2
                   3311:
                   3312:        mov.l           %d1,%a2                 # ADDR1
                   3313:        addq.l          &0x3,%d1
                   3314:        mov.l           %d1,%a4                 # ADDR1+3
                   3315: # if ADDR1 was ATC resident before the above "plpaw" and was executed
                   3316: # and it was the next entry scheduled for replacement and ADDR2
                   3317: # shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
                   3318: # entries from the ATC. so, we do a second set of "plpa"s.
                   3319:        plpar           (%a2)                   # load atc for ADDR1
                   3320:        plpar           (%a4)                   # load atc for ADDR1+3
                   3321:
                   3322: # load the BUSCR values.
                   3323:        mov.l           &0x80000000,%a2         # assert LOCK* buscr value
                   3324:        mov.l           &0xa0000000,%a3         # assert LOCKE* buscr value
                   3325:        mov.l           &0x00000000,%a4         # buscr unlock value
                   3326:
                   3327: # there are three possible mis-aligned cases for longword cas. they
                   3328: # are separated because the final write which asserts LOCKE* must
                   3329: # be aligned.
                   3330:        mov.l           %a0,%d0                 # is ADDR1 misaligned?
                   3331:        andi.b          &0x3,%d0
                   3332:        beq.b           CAS2L_ENTER             # no
                   3333:        cmpi.b          %d0,&0x2
                   3334:        beq.w           CAS2L2_ENTER            # yes; word misaligned
                   3335:        bra.w           CAS2L3_ENTER            # yes; byte misaligned
                   3336:
                   3337: #
                   3338: # D0 = dst operand 1 <-
                   3339: # D1 = dst operand 2 <-
                   3340: # D2 = cmp operand 1
                   3341: # D3 = cmp operand 2
                   3342: # D4 = update oper 1
                   3343: # D5 = update oper 2
                   3344: # D6 = old SFC/DFC
                   3345: # D7 = old SR
                   3346: # A0 = ADDR1
                   3347: # A1 = ADDR2
                   3348: # A2 = bus LOCK*  value
                   3349: # A3 = bus LOCKE* value
                   3350: # A4 = bus unlock value
                   3351: # A5 = xxxxxxxx
                   3352: #
                   3353:        align           0x10
                   3354: CAS2L_START:
                   3355:        movc            %a2,%buscr              # assert LOCK*
                   3356:        movs.l          (%a1),%d1               # fetch Dest2[31:0]
                   3357:        movs.l          (%a0),%d0               # fetch Dest1[31:0]
                   3358:        bra.b           CAS2L_CONT
                   3359: CAS2L_ENTER:
                   3360:        bra.b           ~+16
                   3361:
                   3362: CAS2L_CONT:
                   3363:        cmp.l           %d0,%d2                 # Dest1 - Compare1
                   3364:        bne.b           CAS2L_NOUPDATE
                   3365:        cmp.l           %d1,%d3                 # Dest2 - Compare2
                   3366:        bne.b           CAS2L_NOUPDATE
                   3367:        movs.l          %d5,(%a1)               # Update2[31:0] -> DEST2
                   3368:        bra.b           CAS2L_UPDATE
                   3369:        bra.b           ~+16
                   3370:
                   3371: CAS2L_UPDATE:
                   3372:        movc            %a3,%buscr              # assert LOCKE*
                   3373:        movs.l          %d4,(%a0)               # Update1[31:0] -> DEST1
                   3374:        movc            %a4,%buscr              # unlock the bus
                   3375:        bra.b           cas2l_update_done
                   3376:        bra.b           ~+16
                   3377:
                   3378: CAS2L_NOUPDATE:
                   3379:        movc            %a3,%buscr              # assert LOCKE*
                   3380:        movs.l          %d0,(%a0)               # Dest1[31:0] -> DEST1
                   3381:        movc            %a4,%buscr              # unlock the bus
                   3382:        bra.b           cas2l_noupdate_done
                   3383:        bra.b           ~+16
                   3384:
                   3385: CAS2L_FILLER:
                   3386:        nop
                   3387:        nop
                   3388:        nop
                   3389:        nop
                   3390:        nop
                   3391:        nop
                   3392:        nop
                   3393:        bra.b           CAS2L_START
                   3394:
                   3395: ####
                   3396:
                   3397: #################################################################
                   3398: # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON     #
                   3399: # ENTERING _isp_cas2().                                                #
                   3400: #                                                              #
                   3401: # D0 = destination[31:0] operand 1                             #
                   3402: # D1 = destination[31:0] operand 2                             #
                   3403: # D2 = cmp[31:0] operand 1                                     #
                   3404: # D3 = cmp[31:0] operand 2                                     #
                   3405: # D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required        #
                   3406: # D5 = xxxxxxxx                                                        #
                   3407: # D6 = xxxxxxxx                                                        #
                   3408: # D7 = xxxxxxxx                                                        #
                   3409: # A0 = xxxxxxxx                                                        #
                   3410: # A1 = xxxxxxxx                                                        #
                   3411: # A2 = xxxxxxxx                                                        #
                   3412: # A3 = xxxxxxxx                                                        #
                   3413: # A4 = xxxxxxxx                                                        #
                   3414: # A5 = xxxxxxxx                                                        #
                   3415: # A6 = frame pointer                                           #
                   3416: # A7 = stack pointer                                           #
                   3417: #################################################################
                   3418:
                   3419: cas2l_noupdate_done:
                   3420:
                   3421: # restore previous SFC/DFC value.
                   3422:        movc            %d6,%sfc                # restore old SFC
                   3423:        movc            %d6,%dfc                # restore old DFC
                   3424:
                   3425: # restore previous interrupt mask level.
                   3426:        mov.w           %d7,%sr                 # restore old SR
                   3427:
                   3428:        sf              %d4                     # indicate no update was done
                   3429:        bra.l           _isp_cas2_finish
                   3430:
                   3431: cas2l_update_done:
                   3432:
                   3433: # restore previous SFC/DFC value.
                   3434:        movc            %d6,%sfc                # restore old SFC
                   3435:        movc            %d6,%dfc                # restore old DFC
                   3436:
                   3437: # restore previous interrupt mask level.
                   3438:        mov.w           %d7,%sr                 # restore old SR
                   3439:
                   3440:        st              %d4                     # indicate update was done
                   3441:        bra.l           _isp_cas2_finish
                   3442: ####
                   3443:
                   3444:        align           0x10
                   3445: CAS2L2_START:
                   3446:        movc            %a2,%buscr              # assert LOCK*
                   3447:        movs.l          (%a1),%d1               # fetch Dest2[31:0]
                   3448:        movs.l          (%a0),%d0               # fetch Dest1[31:0]
                   3449:        bra.b           CAS2L2_CONT
                   3450: CAS2L2_ENTER:
                   3451:        bra.b           ~+16
                   3452:
                   3453: CAS2L2_CONT:
                   3454:        cmp.l           %d0,%d2                 # Dest1 - Compare1
                   3455:        bne.b           CAS2L2_NOUPDATE
                   3456:        cmp.l           %d1,%d3                 # Dest2 - Compare2
                   3457:        bne.b           CAS2L2_NOUPDATE
                   3458:        movs.l          %d5,(%a1)               # Update2[31:0] -> Dest2
                   3459:        bra.b           CAS2L2_UPDATE
                   3460:        bra.b           ~+16
                   3461:
                   3462: CAS2L2_UPDATE:
                   3463:        swap            %d4                     # get Update1[31:16]
                   3464:        movs.w          %d4,(%a0)+              # Update1[31:16] -> DEST1
                   3465:        movc            %a3,%buscr              # assert LOCKE*
                   3466:        swap            %d4                     # get Update1[15:0]
                   3467:        bra.b           CAS2L2_UPDATE2
                   3468:        bra.b           ~+16
                   3469:
                   3470: CAS2L2_UPDATE2:
                   3471:        movs.w          %d4,(%a0)               # Update1[15:0] -> DEST1+0x2
                   3472:        movc            %a4,%buscr              # unlock the bus
                   3473:        bra.w           cas2l_update_done
                   3474:        nop
                   3475:        bra.b           ~+16
                   3476:
                   3477: CAS2L2_NOUPDATE:
                   3478:        swap            %d0                     # get Dest1[31:16]
                   3479:        movs.w          %d0,(%a0)+              # Dest1[31:16] -> DEST1
                   3480:        movc            %a3,%buscr              # assert LOCKE*
                   3481:        swap            %d0                     # get Dest1[15:0]
                   3482:        bra.b           CAS2L2_NOUPDATE2
                   3483:        bra.b           ~+16
                   3484:
                   3485: CAS2L2_NOUPDATE2:
                   3486:        movs.w          %d0,(%a0)               # Dest1[15:0] -> DEST1+0x2
                   3487:        movc            %a4,%buscr              # unlock the bus
                   3488:        bra.w           cas2l_noupdate_done
                   3489:        nop
                   3490:        bra.b           ~+16
                   3491:
                   3492: CAS2L2_FILLER:
                   3493:        nop
                   3494:        nop
                   3495:        nop
                   3496:        nop
                   3497:        nop
                   3498:        nop
                   3499:        nop
                   3500:        bra.b           CAS2L2_START
                   3501:
                   3502: #################################
                   3503:
                   3504:        align           0x10
                   3505: CAS2L3_START:
                   3506:        movc            %a2,%buscr              # assert LOCK*
                   3507:        movs.l          (%a1),%d1               # fetch Dest2[31:0]
                   3508:        movs.l          (%a0),%d0               # fetch Dest1[31:0]
                   3509:        bra.b           CAS2L3_CONT
                   3510: CAS2L3_ENTER:
                   3511:        bra.b           ~+16
                   3512:
                   3513: CAS2L3_CONT:
                   3514:        cmp.l           %d0,%d2                 # Dest1 - Compare1
                   3515:        bne.b           CAS2L3_NOUPDATE
                   3516:        cmp.l           %d1,%d3                 # Dest2 - Compare2
                   3517:        bne.b           CAS2L3_NOUPDATE
                   3518:        movs.l          %d5,(%a1)               # Update2[31:0] -> DEST2
                   3519:        bra.b           CAS2L3_UPDATE
                   3520:        bra.b           ~+16
                   3521:
                   3522: CAS2L3_UPDATE:
                   3523:        rol.l           &0x8,%d4                # get Update1[31:24]
                   3524:        movs.b          %d4,(%a0)+              # Update1[31:24] -> DEST1
                   3525:        swap            %d4                     # get Update1[23:8]
                   3526:        movs.w          %d4,(%a0)+              # Update1[23:8] -> DEST1+0x1
                   3527:        bra.b           CAS2L3_UPDATE2
                   3528:        bra.b           ~+16
                   3529:
                   3530: CAS2L3_UPDATE2:
                   3531:        rol.l           &0x8,%d4                # get Update1[7:0]
                   3532:        movc            %a3,%buscr              # assert LOCKE*
                   3533:        movs.b          %d4,(%a0)               # Update1[7:0] -> DEST1+0x3
                   3534:        bra.b           CAS2L3_UPDATE3
                   3535:        nop
                   3536:        bra.b           ~+16
                   3537:
                   3538: CAS2L3_UPDATE3:
                   3539:        movc            %a4,%buscr              # unlock the bus
                   3540:        bra.w           cas2l_update_done
                   3541:        nop
                   3542:        nop
                   3543:        nop
                   3544:        bra.b           ~+16
                   3545:
                   3546: CAS2L3_NOUPDATE:
                   3547:        rol.l           &0x8,%d0                # get Dest1[31:24]
                   3548:        movs.b          %d0,(%a0)+              # Dest1[31:24] -> DEST1
                   3549:        swap            %d0                     # get Dest1[23:8]
                   3550:        movs.w          %d0,(%a0)+              # Dest1[23:8] -> DEST1+0x1
                   3551:        bra.b           CAS2L3_NOUPDATE2
                   3552:        bra.b           ~+16
                   3553:
                   3554: CAS2L3_NOUPDATE2:
                   3555:        rol.l           &0x8,%d0                # get Dest1[7:0]
                   3556:        movc            %a3,%buscr              # assert LOCKE*
                   3557:        movs.b          %d0,(%a0)               # Update1[7:0] -> DEST1+0x3
                   3558:        bra.b           CAS2L3_NOUPDATE3
                   3559:        nop
                   3560:        bra.b           ~+16
                   3561:
                   3562: CAS2L3_NOUPDATE3:
                   3563:        movc            %a4,%buscr              # unlock the bus
                   3564:        bra.w           cas2l_noupdate_done
                   3565:        nop
                   3566:        nop
                   3567:        nop
                   3568:        bra.b           ~+14
                   3569:
                   3570: CAS2L3_FILLER:
                   3571:        nop
                   3572:        nop
                   3573:        nop
                   3574:        nop
                   3575:        nop
                   3576:        nop
                   3577:        bra.w           CAS2L3_START
                   3578:
                   3579: #############################################################
                   3580: #############################################################
                   3581:
                   3582: cas2w:
                   3583:        mov.l           %a0,%a2                 # copy ADDR1
                   3584:        mov.l           %a1,%a3                 # copy ADDR2
                   3585:        mov.l           %a0,%a4                 # copy ADDR1
                   3586:        mov.l           %a1,%a5                 # copy ADDR2
                   3587:
                   3588:        addq.l          &0x1,%a4                # ADDR1+1
                   3589:        addq.l          &0x1,%a5                # ADDR2+1
                   3590:        mov.l           %a2,%d1                 # ADDR1
                   3591:
                   3592: # mask interrupt levels 0-6. save old mask value.
                   3593:        mov.w           %sr,%d7                 # save current SR
                   3594:        ori.w           &0x0700,%sr             # inhibit interrupts
                   3595:
                   3596: # load the SFC and DFC with the appropriate mode.
                   3597:        movc            %sfc,%d6                # save old SFC/DFC
                   3598:        movc            %d0,%sfc                # store new SFC
                   3599:        movc            %d0,%dfc                # store new DFC
                   3600:
                   3601: # pre-load the operand ATC. no page faults should occur because
                   3602: # _real_lock_page() should have taken care of this.
                   3603:        plpaw           (%a2)                   # load atc for ADDR1
                   3604:        plpaw           (%a4)                   # load atc for ADDR1+1
                   3605:        plpaw           (%a3)                   # load atc for ADDR2
                   3606:        plpaw           (%a5)                   # load atc for ADDR2+1
                   3607:
                   3608: # push the operand cache lines from the cache if they exist.
                   3609:        cpushl          %dc,(%a2)               # push line for ADDR1
                   3610:        cpushl          %dc,(%a4)               # push line for ADDR1+1
                   3611:        cpushl          %dc,(%a3)               # push line for ADDR2
                   3612:        cpushl          %dc,(%a5)               # push line for ADDR2+1
                   3613:
                   3614:        mov.l           %d1,%a2                 # ADDR1
                   3615:        addq.l          &0x3,%d1
                   3616:        mov.l           %d1,%a4                 # ADDR1+3
                   3617: # if ADDR1 was ATC resident before the above "plpaw" and was executed
                   3618: # and it was the next entry scheduled for replacement and ADDR2
                   3619: # shares the same set, then the "plpaw" for ADDR2 can push the ADDR1
                   3620: # entries from the ATC. so, we do a second set of "plpa"s.
                   3621:        plpar           (%a2)                   # load atc for ADDR1
                   3622:        plpar           (%a4)                   # load atc for ADDR1+3
                   3623:
                   3624: # load the BUSCR values.
                   3625:        mov.l           &0x80000000,%a2         # assert LOCK* buscr value
                   3626:        mov.l           &0xa0000000,%a3         # assert LOCKE* buscr value
                   3627:        mov.l           &0x00000000,%a4         # buscr unlock value
                   3628:
                   3629: # there are two possible mis-aligned cases for word cas. they
                   3630: # are separated because the final write which asserts LOCKE* must
                   3631: # be aligned.
                   3632:        mov.l           %a0,%d0                 # is ADDR1 misaligned?
                   3633:        btst            &0x0,%d0
                   3634:        bne.w           CAS2W2_ENTER            # yes
                   3635:        bra.b           CAS2W_ENTER             # no
                   3636:
                   3637: #
                   3638: # D0 = dst operand 1 <-
                   3639: # D1 = dst operand 2 <-
                   3640: # D2 = cmp operand 1
                   3641: # D3 = cmp operand 2
                   3642: # D4 = update oper 1
                   3643: # D5 = update oper 2
                   3644: # D6 = old SFC/DFC
                   3645: # D7 = old SR
                   3646: # A0 = ADDR1
                   3647: # A1 = ADDR2
                   3648: # A2 = bus LOCK*  value
                   3649: # A3 = bus LOCKE* value
                   3650: # A4 = bus unlock value
                   3651: # A5 = xxxxxxxx
                   3652: #
                   3653:        align           0x10
                   3654: CAS2W_START:
                   3655:        movc            %a2,%buscr              # assert LOCK*
                   3656:        movs.w          (%a1),%d1               # fetch Dest2[15:0]
                   3657:        movs.w          (%a0),%d0               # fetch Dest1[15:0]
                   3658:        bra.b           CAS2W_CONT2
                   3659: CAS2W_ENTER:
                   3660:        bra.b           ~+16
                   3661:
                   3662: CAS2W_CONT2:
                   3663:        cmp.w           %d0,%d2                 # Dest1 - Compare1
                   3664:        bne.b           CAS2W_NOUPDATE
                   3665:        cmp.w           %d1,%d3                 # Dest2 - Compare2
                   3666:        bne.b           CAS2W_NOUPDATE
                   3667:        movs.w          %d5,(%a1)               # Update2[15:0] -> DEST2
                   3668:        bra.b           CAS2W_UPDATE
                   3669:        bra.b           ~+16
                   3670:
                   3671: CAS2W_UPDATE:
                   3672:        movc            %a3,%buscr              # assert LOCKE*
                   3673:        movs.w          %d4,(%a0)               # Update1[15:0] -> DEST1
                   3674:        movc            %a4,%buscr              # unlock the bus
                   3675:        bra.b           cas2w_update_done
                   3676:        bra.b           ~+16
                   3677:
                   3678: CAS2W_NOUPDATE:
                   3679:        movc            %a3,%buscr              # assert LOCKE*
                   3680:        movs.w          %d0,(%a0)               # Dest1[15:0] -> DEST1
                   3681:        movc            %a4,%buscr              # unlock the bus
                   3682:        bra.b           cas2w_noupdate_done
                   3683:        bra.b           ~+16
                   3684:
                   3685: CAS2W_FILLER:
                   3686:        nop
                   3687:        nop
                   3688:        nop
                   3689:        nop
                   3690:        nop
                   3691:        nop
                   3692:        nop
                   3693:        bra.b           CAS2W_START
                   3694:
                   3695: ####
                   3696:
                   3697: #################################################################
                   3698: # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON     #
                   3699: # ENTERING _isp_cas2().                                                #
                   3700: #                                                              #
                   3701: # D0 = destination[15:0] operand 1                             #
                   3702: # D1 = destination[15:0] operand 2                             #
                   3703: # D2 = cmp[15:0] operand 1                                     #
                   3704: # D3 = cmp[15:0] operand 2                                     #
                   3705: # D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required        #
                   3706: # D5 = xxxxxxxx                                                        #
                   3707: # D6 = xxxxxxxx                                                        #
                   3708: # D7 = xxxxxxxx                                                        #
                   3709: # A0 = xxxxxxxx                                                        #
                   3710: # A1 = xxxxxxxx                                                        #
                   3711: # A2 = xxxxxxxx                                                        #
                   3712: # A3 = xxxxxxxx                                                        #
                   3713: # A4 = xxxxxxxx                                                        #
                   3714: # A5 = xxxxxxxx                                                        #
                   3715: # A6 = frame pointer                                           #
                   3716: # A7 = stack pointer                                           #
                   3717: #################################################################
                   3718:
                   3719: cas2w_noupdate_done:
                   3720:
                   3721: # restore previous SFC/DFC value.
                   3722:        movc            %d6,%sfc                # restore old SFC
                   3723:        movc            %d6,%dfc                # restore old DFC
                   3724:
                   3725: # restore previous interrupt mask level.
                   3726:        mov.w           %d7,%sr                 # restore old SR
                   3727:
                   3728:        sf              %d4                     # indicate no update was done
                   3729:        bra.l           _isp_cas2_finish
                   3730:
                   3731: cas2w_update_done:
                   3732:
                   3733: # restore previous SFC/DFC value.
                   3734:        movc            %d6,%sfc                # restore old SFC
                   3735:        movc            %d6,%dfc                # restore old DFC
                   3736:
                   3737: # restore previous interrupt mask level.
                   3738:        mov.w           %d7,%sr                 # restore old SR
                   3739:
                   3740:        st              %d4                     # indicate update was done
                   3741:        bra.l           _isp_cas2_finish
                   3742: ####
                   3743:
                   3744:        align           0x10
                   3745: CAS2W2_START:
                   3746:        movc            %a2,%buscr              # assert LOCK*
                   3747:        movs.w          (%a1),%d1               # fetch Dest2[15:0]
                   3748:        movs.w          (%a0),%d0               # fetch Dest1[15:0]
                   3749:        bra.b           CAS2W2_CONT2
                   3750: CAS2W2_ENTER:
                   3751:        bra.b           ~+16
                   3752:
                   3753: CAS2W2_CONT2:
                   3754:        cmp.w           %d0,%d2                 # Dest1 - Compare1
                   3755:        bne.b           CAS2W2_NOUPDATE
                   3756:        cmp.w           %d1,%d3                 # Dest2 - Compare2
                   3757:        bne.b           CAS2W2_NOUPDATE
                   3758:        movs.w          %d5,(%a1)               # Update2[15:0] -> DEST2
                   3759:        bra.b           CAS2W2_UPDATE
                   3760:        bra.b           ~+16
                   3761:
                   3762: CAS2W2_UPDATE:
                   3763:        ror.l           &0x8,%d4                # get Update1[15:8]
                   3764:        movs.b          %d4,(%a0)+              # Update1[15:8] -> DEST1
                   3765:        movc            %a3,%buscr              # assert LOCKE*
                   3766:        rol.l           &0x8,%d4                # get Update1[7:0]
                   3767:        bra.b           CAS2W2_UPDATE2
                   3768:        bra.b           ~+16
                   3769:
                   3770: CAS2W2_UPDATE2:
                   3771:        movs.b          %d4,(%a0)               # Update1[7:0] -> DEST1+0x1
                   3772:        movc            %a4,%buscr              # unlock the bus
                   3773:        bra.w           cas2w_update_done
                   3774:        nop
                   3775:        bra.b           ~+16
                   3776:
                   3777: CAS2W2_NOUPDATE:
                   3778:        ror.l           &0x8,%d0                # get Dest1[15:8]
                   3779:        movs.b          %d0,(%a0)+              # Dest1[15:8] -> DEST1
                   3780:        movc            %a3,%buscr              # assert LOCKE*
                   3781:        rol.l           &0x8,%d0                # get Dest1[7:0]
                   3782:        bra.b           CAS2W2_NOUPDATE2
                   3783:        bra.b           ~+16
                   3784:
                   3785: CAS2W2_NOUPDATE2:
                   3786:        movs.b          %d0,(%a0)               # Dest1[7:0] -> DEST1+0x1
                   3787:        movc            %a4,%buscr              # unlock the bus
                   3788:        bra.w           cas2w_noupdate_done
                   3789:        nop
                   3790:        bra.b           ~+16
                   3791:
                   3792: CAS2W2_FILLER:
                   3793:        nop
                   3794:        nop
                   3795:        nop
                   3796:        nop
                   3797:        nop
                   3798:        nop
                   3799:        nop
                   3800:        bra.b           CAS2W2_START
                   3801:
                   3802: #       ######      ##      ######
                   3803: #       #         #  #     #
                   3804: #      #         ######    ######
                   3805: #      #         #    #         #
                   3806: #       ######    #    #    ######
                   3807:
                   3808: #########################################################################
                   3809: # XDEF ****************************************************************        #
                   3810: #      _isp_cas(): "core" emulation code for the cas instruction       #
                   3811: #                                                                      #
                   3812: # XREF ****************************************************************        #
                   3813: #      _isp_cas_finish() - only exit point for this emulation code;    #
                   3814: #                          do clean-up                                 #
                   3815: #                                                                      #
                   3816: # INPUT ***************************************************************        #
                   3817: #      *see entry chart below*                                         #
                   3818: #                                                                      #
                   3819: # OUTPUT **************************************************************        #
                   3820: #      *see exit chart below*                                          #
                   3821: #                                                                      #
                   3822: # ALGORITHM ***********************************************************        #
                   3823: #      (1) Make several copies of the effective address.               #
                   3824: #      (2) Save current SR; Then mask off all maskable interrupts.     #
                   3825: #      (3) Save current DFC/SFC (ASSUMED TO BE EQUAL!!!); Then set     #
                   3826: #          SFC/DFC according to whether exception occurred in user or  #
                   3827: #          supervisor mode.                                            #
                   3828: #      (4) Use "plpaw" instruction to pre-load ATC with effective      #
                   3829: #          address page(s). THIS SHOULD NOT FAULT!!! The relevant      #
                   3830: #          page(s) should have been made resident prior to entering    #
                   3831: #          this routine.                                               #
                   3832: #      (5) Push the operand lines from the cache w/ "cpushl".          #
                   3833: #          In the 68040, this was done within the locked region. In    #
                   3834: #          the 68060, it is done outside of the locked region.         #
                   3835: #      (6) Pre-fetch the core emulation instructions by executing one  #
                   3836: #          branch within each physical line (16 bytes) of the code     #
                   3837: #          before actually executing the code.                         #
                   3838: #      (7) Load the BUSCR with the bus lock value.                     #
                   3839: #      (8) Fetch the source operand.                                   #
                   3840: #      (9) Do the compare. If equal, go to step (12).                  #
                   3841: #      (10)Unequal. No update occurs. But, we do write the DST op back #
                   3842: #          to itself (as w/ the '040) so we can gracefully unlock      #
                   3843: #          the bus (and assert LOCKE*) using BUSCR and the final move. #
                   3844: #      (11)Exit.                                                       #
                   3845: #      (12)Write update operand to the DST location. Use BUSCR to      #
                   3846: #          assert LOCKE* for the final write operation.                #
                   3847: #      (13)Exit.                                                       #
                   3848: #                                                                      #
                   3849: #      The algorithm is actually implemented slightly differently      #
                   3850: # depending on the size of the operation and the misalignment of the   #
                   3851: # operand. A misaligned operand must be written in aligned chunks or   #
                   3852: # else the BUSCR register control gets confused.                       #
                   3853: #                                                                      #
                   3854: #########################################################################
                   3855:
                   3856: #########################################################
                   3857: # THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON  #
                   3858: # ENTERING _isp_cas().                                 #
                   3859: #                                                      #
                   3860: # D0 = xxxxxxxx                                                #
                   3861: # D1 = xxxxxxxx                                                #
                   3862: # D2 = update operand                                  #
                   3863: # D3 = xxxxxxxx                                                #
                   3864: # D4 = compare operand                                 #
                   3865: # D5 = xxxxxxxx                                                #
                   3866: # D6 = supervisor ('xxxxxxff) or user mode ('xxxxxx00) #
                   3867: # D7 = longword ('xxxxxxff) or word size ('xxxxxx00)   #
                   3868: # A0 = ADDR                                            #
                   3869: # A1 = xxxxxxxx                                                #
                   3870: # A2 = xxxxxxxx                                                #
                   3871: # A3 = xxxxxxxx                                                #
                   3872: # A4 = xxxxxxxx                                                #
                   3873: # A5 = xxxxxxxx                                                #
                   3874: # A6 = frame pointer                                   #
                   3875: # A7 = stack pointer                                   #
                   3876: #########################################################
                   3877:
                   3878:        global          _isp_cas
                   3879: _isp_cas:
                   3880:        tst.b           %d6                     # user or supervisor mode?
                   3881:        bne.b           cas_super               # supervisor
                   3882: cas_user:
                   3883:        movq.l          &0x1,%d0                # load user data fc
                   3884:        bra.b           cas_cont
                   3885: cas_super:
                   3886:        movq.l          &0x5,%d0                # load supervisor data fc
                   3887:
                   3888: cas_cont:
                   3889:        tst.b           %d7                     # word or longword?
                   3890:        bne.w           casl                    # longword
                   3891:
                   3892: ####
                   3893: casw:
                   3894:        mov.l           %a0,%a1                 # make copy for plpaw1
                   3895:        mov.l           %a0,%a2                 # make copy for plpaw2
                   3896:        addq.l          &0x1,%a2                # plpaw2 points to end of word
                   3897:
                   3898:        mov.l           %d2,%d3                 # d3 = update[7:0]
                   3899:        lsr.w           &0x8,%d2                # d2 = update[15:8]
                   3900:
                   3901: # mask interrupt levels 0-6. save old mask value.
                   3902:        mov.w           %sr,%d7                 # save current SR
                   3903:        ori.w           &0x0700,%sr             # inhibit interrupts
                   3904:
                   3905: # load the SFC and DFC with the appropriate mode.
                   3906:        movc            %sfc,%d6                # save old SFC/DFC
                   3907:        movc            %d0,%sfc                # load new sfc
                   3908:        movc            %d0,%dfc                # load new dfc
                   3909:
                   3910: # pre-load the operand ATC. no page faults should occur here because
                   3911: # _real_lock_page() should have taken care of this.
                   3912:        plpaw           (%a1)                   # load atc for ADDR
                   3913:        plpaw           (%a2)                   # load atc for ADDR+1
                   3914:
                   3915: # push the operand lines from the cache if they exist.
                   3916:        cpushl          %dc,(%a1)               # push dirty data
                   3917:        cpushl          %dc,(%a2)               # push dirty data
                   3918:
                   3919: # load the BUSCR values.
                   3920:        mov.l           &0x80000000,%a1         # assert LOCK* buscr value
                   3921:        mov.l           &0xa0000000,%a2         # assert LOCKE* buscr value
                   3922:        mov.l           &0x00000000,%a3         # buscr unlock value
                   3923:
                   3924: # pre-load the instruction cache for the following algorithm.
                   3925: # this will minimize the number of cycles that LOCK* will be asserted.
                   3926:        bra.b           CASW_ENTER              # start pre-loading icache
                   3927:
                   3928: #
                   3929: # D0 = dst operand <-
                   3930: # D1 = update[15:8] operand
                   3931: # D2 = update[7:0]  operand
                   3932: # D3 = xxxxxxxx
                   3933: # D4 = compare[15:0] operand
                   3934: # D5 = xxxxxxxx
                   3935: # D6 = old SFC/DFC
                   3936: # D7 = old SR
                   3937: # A0 = ADDR
                   3938: # A1 = bus LOCK*  value
                   3939: # A2 = bus LOCKE* value
                   3940: # A3 = bus unlock value
                   3941: # A4 = xxxxxxxx
                   3942: # A5 = xxxxxxxx
                   3943: #
                   3944:        align           0x10
                   3945: CASW_START:
                   3946:        movc            %a1,%buscr              # assert LOCK*
                   3947:        movs.w          (%a0),%d0               # fetch Dest[15:0]
                   3948:        cmp.w           %d0,%d4                 # Dest - Compare
                   3949:        bne.b           CASW_NOUPDATE
                   3950:        bra.b           CASW_UPDATE
                   3951: CASW_ENTER:
                   3952:        bra.b           ~+16
                   3953:
                   3954: CASW_UPDATE:
                   3955:        movs.b          %d2,(%a0)+              # Update[15:8] -> DEST
                   3956:        movc            %a2,%buscr              # assert LOCKE*
                   3957:        movs.b          %d3,(%a0)               # Update[7:0] -> DEST+0x1
                   3958:        bra.b           CASW_UPDATE2
                   3959:        bra.b           ~+16
                   3960:
                   3961: CASW_UPDATE2:
                   3962:        movc            %a3,%buscr              # unlock the bus
                   3963:        bra.b           casw_update_done
                   3964:        nop
                   3965:        nop
                   3966:        nop
                   3967:        nop
                   3968:        bra.b           ~+16
                   3969:
                   3970: CASW_NOUPDATE:
                   3971:        ror.l           &0x8,%d0                # get Dest[15:8]
                   3972:        movs.b          %d0,(%a0)+              # Dest[15:8] -> DEST
                   3973:        movc            %a2,%buscr              # assert LOCKE*
                   3974:        rol.l           &0x8,%d0                # get Dest[7:0]
                   3975:        bra.b           CASW_NOUPDATE2
                   3976:        bra.b           ~+16
                   3977:
                   3978: CASW_NOUPDATE2:
                   3979:        movs.b          %d0,(%a0)               # Dest[7:0] -> DEST+0x1
                   3980:        movc            %a3,%buscr              # unlock the bus
                   3981:        bra.b           casw_noupdate_done
                   3982:        nop
                   3983:        nop
                   3984:        bra.b           ~+16
                   3985:
                   3986: CASW_FILLER:
                   3987:        nop
                   3988:        nop
                   3989:        nop
                   3990:        nop
                   3991:        nop
                   3992:        nop
                   3993:        nop
                   3994:        bra.b           CASW_START
                   3995:
                   3996: #################################################################
                   3997: # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON     #
                   3998: # CALLING _isp_cas_finish().                                   #
                   3999: #                                                              #
                   4000: # D0 = destination[15:0] operand                               #
                   4001: # D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required        #
                   4002: # D2 = xxxxxxxx                                                        #
                   4003: # D3 = xxxxxxxx                                                        #
                   4004: # D4 = compare[15:0] operand                                   #
                   4005: # D5 = xxxxxxxx                                                        #
                   4006: # D6 = xxxxxxxx                                                        #
                   4007: # D7 = xxxxxxxx                                                        #
                   4008: # A0 = xxxxxxxx                                                        #
                   4009: # A1 = xxxxxxxx                                                        #
                   4010: # A2 = xxxxxxxx                                                        #
                   4011: # A3 = xxxxxxxx                                                        #
                   4012: # A4 = xxxxxxxx                                                        #
                   4013: # A5 = xxxxxxxx                                                        #
                   4014: # A6 = frame pointer                                           #
                   4015: # A7 = stack pointer                                           #
                   4016: #################################################################
                   4017:
                   4018: casw_noupdate_done:
                   4019:
                   4020: # restore previous SFC/DFC value.
                   4021:        movc            %d6,%sfc                # restore old SFC
                   4022:        movc            %d6,%dfc                # restore old DFC
                   4023:
                   4024: # restore previous interrupt mask level.
                   4025:        mov.w           %d7,%sr                 # restore old SR
                   4026:
                   4027:        sf              %d1                     # indicate no update was done
                   4028:        bra.l           _isp_cas_finish
                   4029:
                   4030: casw_update_done:
                   4031:
                   4032: # restore previous SFC/DFC value.
                   4033:        movc            %d6,%sfc                # restore old SFC
                   4034:        movc            %d6,%dfc                # restore old DFC
                   4035:
                   4036: # restore previous interrupt mask level.
                   4037:        mov.w           %d7,%sr                 # restore old SR
                   4038:
                   4039:        st              %d1                     # indicate update was done
                   4040:        bra.l           _isp_cas_finish
                   4041:
                   4042: ################
                   4043:
                   4044: # there are two possible mis-aligned cases for longword cas. they
                   4045: # are separated because the final write which asserts LOCKE* must
                   4046: # be an aligned write.
                   4047: casl:
                   4048:        mov.l           %a0,%a1                 # make copy for plpaw1
                   4049:        mov.l           %a0,%a2                 # make copy for plpaw2
                   4050:        addq.l          &0x3,%a2                # plpaw2 points to end of longword
                   4051:
                   4052:        mov.l           %a0,%d1                 # byte or word misaligned?
                   4053:        btst            &0x0,%d1
                   4054:        bne.w           casl2                   # byte misaligned
                   4055:
                   4056:        mov.l           %d2,%d3                 # d3 = update[15:0]
                   4057:        swap            %d2                     # d2 = update[31:16]
                   4058:
                   4059: # mask interrupts levels 0-6. save old mask value.
                   4060:        mov.w           %sr,%d7                 # save current SR
                   4061:        ori.w           &0x0700,%sr             # inhibit interrupts
                   4062:
                   4063: # load the SFC and DFC with the appropriate mode.
                   4064:        movc            %sfc,%d6                # save old SFC/DFC
                   4065:        movc            %d0,%sfc                # load new sfc
                   4066:        movc            %d0,%dfc                # load new dfc
                   4067:
                   4068: # pre-load the operand ATC. no page faults should occur here because
                   4069: # _real_lock_page() should have taken care of this.
                   4070:        plpaw           (%a1)                   # load atc for ADDR
                   4071:        plpaw           (%a2)                   # load atc for ADDR+3
                   4072:
                   4073: # push the operand lines from the cache if they exist.
                   4074:        cpushl          %dc,(%a1)               # push dirty data
                   4075:        cpushl          %dc,(%a2)               # push dirty data
                   4076:
                   4077: # load the BUSCR values.
                   4078:        mov.l           &0x80000000,%a1         # assert LOCK* buscr value
                   4079:        mov.l           &0xa0000000,%a2         # assert LOCKE* buscr value
                   4080:        mov.l           &0x00000000,%a3         # buscr unlock value
                   4081:
                   4082:        bra.b           CASL_ENTER              # start pre-loading icache
                   4083:
                   4084: #
                   4085: # D0 = dst operand <-
                   4086: # D1 = xxxxxxxx
                   4087: # D2 = update[31:16] operand
                   4088: # D3 = update[15:0]  operand
                   4089: # D4 = compare[31:0] operand
                   4090: # D5 = xxxxxxxx
                   4091: # D6 = old SFC/DFC
                   4092: # D7 = old SR
                   4093: # A0 = ADDR
                   4094: # A1 = bus LOCK*  value
                   4095: # A2 = bus LOCKE* value
                   4096: # A3 = bus unlock value
                   4097: # A4 = xxxxxxxx
                   4098: # A5 = xxxxxxxx
                   4099: #
                   4100:        align           0x10
                   4101: CASL_START:
                   4102:        movc            %a1,%buscr              # assert LOCK*
                   4103:        movs.l          (%a0),%d0               # fetch Dest[31:0]
                   4104:        cmp.l           %d0,%d4                 # Dest - Compare
                   4105:        bne.b           CASL_NOUPDATE
                   4106:        bra.b           CASL_UPDATE
                   4107: CASL_ENTER:
                   4108:        bra.b           ~+16
                   4109:
                   4110: CASL_UPDATE:
                   4111:        movs.w          %d2,(%a0)+              # Update[31:16] -> DEST
                   4112:        movc            %a2,%buscr              # assert LOCKE*
                   4113:        movs.w          %d3,(%a0)               # Update[15:0] -> DEST+0x2
                   4114:        bra.b           CASL_UPDATE2
                   4115:        bra.b           ~+16
                   4116:
                   4117: CASL_UPDATE2:
                   4118:        movc            %a3,%buscr              # unlock the bus
                   4119:        bra.b           casl_update_done
                   4120:        nop
                   4121:        nop
                   4122:        nop
                   4123:        nop
                   4124:        bra.b           ~+16
                   4125:
                   4126: CASL_NOUPDATE:
                   4127:        swap            %d0                     # get Dest[31:16]
                   4128:        movs.w          %d0,(%a0)+              # Dest[31:16] -> DEST
                   4129:        swap            %d0                     # get Dest[15:0]
                   4130:        movc            %a2,%buscr              # assert LOCKE*
                   4131:        bra.b           CASL_NOUPDATE2
                   4132:        bra.b           ~+16
                   4133:
                   4134: CASL_NOUPDATE2:
                   4135:        movs.w          %d0,(%a0)               # Dest[15:0] -> DEST+0x2
                   4136:        movc            %a3,%buscr              # unlock the bus
                   4137:        bra.b           casl_noupdate_done
                   4138:        nop
                   4139:        nop
                   4140:        bra.b           ~+16
                   4141:
                   4142: CASL_FILLER:
                   4143:        nop
                   4144:        nop
                   4145:        nop
                   4146:        nop
                   4147:        nop
                   4148:        nop
                   4149:        nop
                   4150:        bra.b           CASL_START
                   4151:
                   4152: #################################################################
                   4153: # THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON     #
                   4154: # CALLING _isp_cas_finish().                                   #
                   4155: #                                                              #
                   4156: # D0 = destination[31:0] operand                               #
                   4157: # D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required        #
                   4158: # D2 = xxxxxxxx                                                        #
                   4159: # D3 = xxxxxxxx                                                        #
                   4160: # D4 = compare[31:0] operand                                   #
                   4161: # D5 = xxxxxxxx                                                        #
                   4162: # D6 = xxxxxxxx                                                        #
                   4163: # D7 = xxxxxxxx                                                        #
                   4164: # A0 = xxxxxxxx                                                        #
                   4165: # A1 = xxxxxxxx                                                        #
                   4166: # A2 = xxxxxxxx                                                        #
                   4167: # A3 = xxxxxxxx                                                        #
                   4168: # A4 = xxxxxxxx                                                        #
                   4169: # A5 = xxxxxxxx                                                        #
                   4170: # A6 = frame pointer                                           #
                   4171: # A7 = stack pointer                                           #
                   4172: #################################################################
                   4173:
                   4174: casl_noupdate_done:
                   4175:
                   4176: # restore previous SFC/DFC value.
                   4177:        movc            %d6,%sfc                # restore old SFC
                   4178:        movc            %d6,%dfc                # restore old DFC
                   4179:
                   4180: # restore previous interrupt mask level.
                   4181:        mov.w           %d7,%sr                 # restore old SR
                   4182:
                   4183:        sf              %d1                     # indicate no update was done
                   4184:        bra.l           _isp_cas_finish
                   4185:
                   4186: casl_update_done:
                   4187:
                   4188: # restore previous SFC/DFC value.
                   4189:        movc            %d6,%sfc                # restore old SFC
                   4190:        movc            %d6,%dfc                # restore old DFC
                   4191:
                   4192: # restore previous interrupts mask level.
                   4193:        mov.w           %d7,%sr                 # restore old SR
                   4194:
                   4195:        st              %d1                     # indicate update was done
                   4196:        bra.l           _isp_cas_finish
                   4197:
                   4198: #######################################
                   4199: casl2:
                   4200:        mov.l           %d2,%d5                 # d5 = Update[7:0]
                   4201:        lsr.l           &0x8,%d2
                   4202:        mov.l           %d2,%d3                 # d3 = Update[23:8]
                   4203:        swap            %d2                     # d2 = Update[31:24]
                   4204:
                   4205: # mask interrupts levels 0-6. save old mask value.
                   4206:        mov.w           %sr,%d7                 # save current SR
                   4207:        ori.w           &0x0700,%sr             # inhibit interrupts
                   4208:
                   4209: # load the SFC and DFC with the appropriate mode.
                   4210:        movc            %sfc,%d6                # save old SFC/DFC
                   4211:        movc            %d0,%sfc                # load new sfc
                   4212:        movc            %d0,%dfc                # load new dfc
                   4213:
                   4214: # pre-load the operand ATC. no page faults should occur here because
                   4215: # _real_lock_page() should have taken care of this already.
                   4216:        plpaw           (%a1)                   # load atc for ADDR
                   4217:        plpaw           (%a2)                   # load atc for ADDR+3
                   4218:
                   4219: # puch the operand lines from the cache if they exist.
                   4220:        cpushl          %dc,(%a1)               # push dirty data
                   4221:        cpushl          %dc,(%a2)               # push dirty data
                   4222:
                   4223: # load the BUSCR values.
                   4224:        mov.l           &0x80000000,%a1         # assert LOCK* buscr value
                   4225:        mov.l           &0xa0000000,%a2         # assert LOCKE* buscr value
                   4226:        mov.l           &0x00000000,%a3         # buscr unlock value
                   4227:
                   4228: # pre-load the instruction cache for the following algorithm.
                   4229: # this will minimize the number of cycles that LOCK* will be asserted.
                   4230:        bra.b           CASL2_ENTER             # start pre-loading icache
                   4231:
                   4232: #
                   4233: # D0 = dst operand <-
                   4234: # D1 = xxxxxxxx
                   4235: # D2 = update[31:24] operand
                   4236: # D3 = update[23:8]  operand
                   4237: # D4 = compare[31:0] operand
                   4238: # D5 = update[7:0]  operand
                   4239: # D6 = old SFC/DFC
                   4240: # D7 = old SR
                   4241: # A0 = ADDR
                   4242: # A1 = bus LOCK*  value
                   4243: # A2 = bus LOCKE* value
                   4244: # A3 = bus unlock value
                   4245: # A4 = xxxxxxxx
                   4246: # A5 = xxxxxxxx
                   4247: #
                   4248:        align           0x10
                   4249: CASL2_START:
                   4250:        movc            %a1,%buscr              # assert LOCK*
                   4251:        movs.l          (%a0),%d0               # fetch Dest[31:0]
                   4252:        cmp.l           %d0,%d4                 # Dest - Compare
                   4253:        bne.b           CASL2_NOUPDATE
                   4254:        bra.b           CASL2_UPDATE
                   4255: CASL2_ENTER:
                   4256:        bra.b           ~+16
                   4257:
                   4258: CASL2_UPDATE:
                   4259:        movs.b          %d2,(%a0)+              # Update[31:24] -> DEST
                   4260:        movs.w          %d3,(%a0)+              # Update[23:8] -> DEST+0x1
                   4261:        movc            %a2,%buscr              # assert LOCKE*
                   4262:        bra.b           CASL2_UPDATE2
                   4263:        bra.b           ~+16
                   4264:
                   4265: CASL2_UPDATE2:
                   4266:        movs.b          %d5,(%a0)               # Update[7:0] -> DEST+0x3
                   4267:        movc            %a3,%buscr              # unlock the bus
                   4268:        bra.w           casl_update_done
                   4269:        nop
                   4270:        bra.b           ~+16
                   4271:
                   4272: CASL2_NOUPDATE:
                   4273:        rol.l           &0x8,%d0                # get Dest[31:24]
                   4274:        movs.b          %d0,(%a0)+              # Dest[31:24] -> DEST
                   4275:        swap            %d0                     # get Dest[23:8]
                   4276:        movs.w          %d0,(%a0)+              # Dest[23:8] -> DEST+0x1
                   4277:        bra.b           CASL2_NOUPDATE2
                   4278:        bra.b           ~+16
                   4279:
                   4280: CASL2_NOUPDATE2:
                   4281:        rol.l           &0x8,%d0                # get Dest[7:0]
                   4282:        movc            %a2,%buscr              # assert LOCKE*
                   4283:        movs.b          %d0,(%a0)               # Dest[7:0] -> DEST+0x3
                   4284:        bra.b           CASL2_NOUPDATE3
                   4285:        nop
                   4286:        bra.b           ~+16
                   4287:
                   4288: CASL2_NOUPDATE3:
                   4289:        movc            %a3,%buscr              # unlock the bus
                   4290:        bra.w           casl_noupdate_done
                   4291:        nop
                   4292:        nop
                   4293:        nop
                   4294:        bra.b           ~+16
                   4295:
                   4296: CASL2_FILLER:
                   4297:        nop
                   4298:        nop
                   4299:        nop
                   4300:        nop
                   4301:        nop
                   4302:        nop
                   4303:        nop
                   4304:        bra.b           CASL2_START
                   4305:
                   4306: ####
                   4307: ####
                   4308: # end label used by _isp_cas_inrange()
                   4309:        global          _CASHI
                   4310: _CASHI:

CVSweb