11da177e4SLinus Torvalds~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21da177e4SLinus TorvaldsMOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 31da177e4SLinus TorvaldsM68000 Hi-Performance Microprocessor Division 41da177e4SLinus TorvaldsM68060 Software Package 51da177e4SLinus TorvaldsProduction Release P1.00 -- October 10, 1994 61da177e4SLinus Torvalds 796de0e25SJan EngelhardtM68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved. 81da177e4SLinus Torvalds 91da177e4SLinus TorvaldsTHE SOFTWARE is provided on an "AS IS" basis and without warranty. 101da177e4SLinus TorvaldsTo the maximum extent permitted by applicable law, 111da177e4SLinus TorvaldsMOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 121da177e4SLinus TorvaldsINCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 131da177e4SLinus Torvaldsand any warranty against infringement with regard to the SOFTWARE 141da177e4SLinus Torvalds(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials. 151da177e4SLinus Torvalds 161da177e4SLinus TorvaldsTo the maximum extent permitted by applicable law, 171da177e4SLinus TorvaldsIN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 181da177e4SLinus Torvalds(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, 191da177e4SLinus TorvaldsBUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) 201da177e4SLinus TorvaldsARISING OF THE USE OR INABILITY TO USE THE SOFTWARE. 211da177e4SLinus TorvaldsMotorola assumes no responsibility for the maintenance and support of the SOFTWARE. 221da177e4SLinus Torvalds 231da177e4SLinus TorvaldsYou are hereby granted a copyright license to use, modify, and distribute the SOFTWARE 241da177e4SLinus Torvaldsso long as this entire notice is retained without alteration in any modified and/or 251da177e4SLinus Torvaldsredistributed versions, and that such modified versions are clearly identified as such. 261da177e4SLinus TorvaldsNo licenses are granted by implication, estoppel or otherwise under any patents 271da177e4SLinus Torvaldsor trademarks of Motorola, Inc. 281da177e4SLinus Torvalds~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 291da177e4SLinus Torvalds# ireal.s: 301da177e4SLinus Torvalds# This file is appended to the top of the 060ISP package 311da177e4SLinus Torvalds# and contains the entry points into the package. The user, in 321da177e4SLinus Torvalds# effect, branches to one of the branch table entries located 331da177e4SLinus Torvalds# after _060ISP_TABLE. 341da177e4SLinus Torvalds# Also, subroutine stubs exist in this file (_isp_done for 351da177e4SLinus Torvalds# example) that are referenced by the ISP package itself in order 361da177e4SLinus Torvalds# to call a given routine. The stub routine actually performs the 371da177e4SLinus Torvalds# callout. The ISP code does a "bsr" to the stub routine. This 381da177e4SLinus Torvalds# extra layer of hierarchy adds a slight performance penalty but 391da177e4SLinus Torvalds# it makes the ISP code easier to read and more mainatinable. 401da177e4SLinus Torvalds# 411da177e4SLinus Torvalds 421da177e4SLinus Torvaldsset _off_chk, 0x00 431da177e4SLinus Torvaldsset _off_divbyzero, 0x04 441da177e4SLinus Torvaldsset _off_trace, 0x08 451da177e4SLinus Torvaldsset _off_access, 0x0c 461da177e4SLinus Torvaldsset _off_done, 0x10 471da177e4SLinus Torvalds 481da177e4SLinus Torvaldsset _off_cas, 0x14 491da177e4SLinus Torvaldsset _off_cas2, 0x18 501da177e4SLinus Torvaldsset _off_lock, 0x1c 511da177e4SLinus Torvaldsset _off_unlock, 0x20 521da177e4SLinus Torvalds 531da177e4SLinus Torvaldsset _off_imr, 0x40 541da177e4SLinus Torvaldsset _off_dmr, 0x44 551da177e4SLinus Torvaldsset _off_dmw, 0x48 561da177e4SLinus Torvaldsset _off_irw, 0x4c 571da177e4SLinus Torvaldsset _off_irl, 0x50 581da177e4SLinus Torvaldsset _off_drb, 0x54 591da177e4SLinus Torvaldsset _off_drw, 0x58 601da177e4SLinus Torvaldsset _off_drl, 0x5c 611da177e4SLinus Torvaldsset _off_dwb, 0x60 621da177e4SLinus Torvaldsset _off_dww, 0x64 631da177e4SLinus Torvaldsset _off_dwl, 0x68 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds_060ISP_TABLE: 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds# Here's the table of ENTRY POINTS for those linking the package. 681da177e4SLinus Torvalds bra.l _isp_unimp 691da177e4SLinus Torvalds short 0x0000 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds bra.l _isp_cas 721da177e4SLinus Torvalds short 0x0000 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds bra.l _isp_cas2 751da177e4SLinus Torvalds short 0x0000 761da177e4SLinus Torvalds 771da177e4SLinus Torvalds bra.l _isp_cas_finish 781da177e4SLinus Torvalds short 0x0000 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds bra.l _isp_cas2_finish 811da177e4SLinus Torvalds short 0x0000 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds bra.l _isp_cas_inrange 841da177e4SLinus Torvalds short 0x0000 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds bra.l _isp_cas_terminate 871da177e4SLinus Torvalds short 0x0000 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds bra.l _isp_cas_restart 901da177e4SLinus Torvalds short 0x0000 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds space 64 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds############################################################# 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds global _real_chk 971da177e4SLinus Torvalds_real_chk: 981da177e4SLinus Torvalds mov.l %d0,-(%sp) 991da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_chk,%pc),%d0 1001da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1011da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 1021da177e4SLinus Torvalds rtd &0x4 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds global _real_divbyzero 1051da177e4SLinus Torvalds_real_divbyzero: 1061da177e4SLinus Torvalds mov.l %d0,-(%sp) 1071da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_divbyzero,%pc),%d0 1081da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1091da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 1101da177e4SLinus Torvalds rtd &0x4 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds global _real_trace 1131da177e4SLinus Torvalds_real_trace: 1141da177e4SLinus Torvalds mov.l %d0,-(%sp) 1151da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_trace,%pc),%d0 1161da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1171da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 1181da177e4SLinus Torvalds rtd &0x4 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds global _real_access 1211da177e4SLinus Torvalds_real_access: 1221da177e4SLinus Torvalds mov.l %d0,-(%sp) 1231da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_access,%pc),%d0 1241da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1251da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 1261da177e4SLinus Torvalds rtd &0x4 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds global _isp_done 1291da177e4SLinus Torvalds_isp_done: 1301da177e4SLinus Torvalds mov.l %d0,-(%sp) 1311da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_done,%pc),%d0 1321da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1331da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 1341da177e4SLinus Torvalds rtd &0x4 1351da177e4SLinus Torvalds 1361da177e4SLinus Torvalds####################################### 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds global _real_cas 1391da177e4SLinus Torvalds_real_cas: 1401da177e4SLinus Torvalds mov.l %d0,-(%sp) 1411da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_cas,%pc),%d0 1421da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1431da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 1441da177e4SLinus Torvalds rtd &0x4 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds global _real_cas2 1471da177e4SLinus Torvalds_real_cas2: 1481da177e4SLinus Torvalds mov.l %d0,-(%sp) 1491da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_cas2,%pc),%d0 1501da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1511da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 1521da177e4SLinus Torvalds rtd &0x4 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds global _real_lock_page 1551da177e4SLinus Torvalds_real_lock_page: 1561da177e4SLinus Torvalds mov.l %d0,-(%sp) 1571da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_lock,%pc),%d0 1581da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1591da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 1601da177e4SLinus Torvalds rtd &0x4 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds global _real_unlock_page 1631da177e4SLinus Torvalds_real_unlock_page: 1641da177e4SLinus Torvalds mov.l %d0,-(%sp) 1651da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_unlock,%pc),%d0 1661da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1671da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 1681da177e4SLinus Torvalds rtd &0x4 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds####################################### 1711da177e4SLinus Torvalds 1721da177e4SLinus Torvalds global _imem_read 1731da177e4SLinus Torvalds_imem_read: 1741da177e4SLinus Torvalds mov.l %d0,-(%sp) 1751da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_imr,%pc),%d0 1761da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1771da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 1781da177e4SLinus Torvalds rtd &0x4 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds global _dmem_read 1811da177e4SLinus Torvalds_dmem_read: 1821da177e4SLinus Torvalds mov.l %d0,-(%sp) 1831da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_dmr,%pc),%d0 1841da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1851da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 1861da177e4SLinus Torvalds rtd &0x4 1871da177e4SLinus Torvalds 1881da177e4SLinus Torvalds global _dmem_write 1891da177e4SLinus Torvalds_dmem_write: 1901da177e4SLinus Torvalds mov.l %d0,-(%sp) 1911da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_dmw,%pc),%d0 1921da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1931da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 1941da177e4SLinus Torvalds rtd &0x4 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvalds global _imem_read_word 1971da177e4SLinus Torvalds_imem_read_word: 1981da177e4SLinus Torvalds mov.l %d0,-(%sp) 1991da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_irw,%pc),%d0 2001da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2011da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 2021da177e4SLinus Torvalds rtd &0x4 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds global _imem_read_long 2051da177e4SLinus Torvalds_imem_read_long: 2061da177e4SLinus Torvalds mov.l %d0,-(%sp) 2071da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_irl,%pc),%d0 2081da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2091da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 2101da177e4SLinus Torvalds rtd &0x4 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds global _dmem_read_byte 2131da177e4SLinus Torvalds_dmem_read_byte: 2141da177e4SLinus Torvalds mov.l %d0,-(%sp) 2151da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_drb,%pc),%d0 2161da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2171da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 2181da177e4SLinus Torvalds rtd &0x4 2191da177e4SLinus Torvalds 2201da177e4SLinus Torvalds global _dmem_read_word 2211da177e4SLinus Torvalds_dmem_read_word: 2221da177e4SLinus Torvalds mov.l %d0,-(%sp) 2231da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_drw,%pc),%d0 2241da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2251da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 2261da177e4SLinus Torvalds rtd &0x4 2271da177e4SLinus Torvalds 2281da177e4SLinus Torvalds global _dmem_read_long 2291da177e4SLinus Torvalds_dmem_read_long: 2301da177e4SLinus Torvalds mov.l %d0,-(%sp) 2311da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_drl,%pc),%d0 2321da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2331da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 2341da177e4SLinus Torvalds rtd &0x4 2351da177e4SLinus Torvalds 2361da177e4SLinus Torvalds global _dmem_write_byte 2371da177e4SLinus Torvalds_dmem_write_byte: 2381da177e4SLinus Torvalds mov.l %d0,-(%sp) 2391da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_dwb,%pc),%d0 2401da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2411da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 2421da177e4SLinus Torvalds rtd &0x4 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds global _dmem_write_word 2451da177e4SLinus Torvalds_dmem_write_word: 2461da177e4SLinus Torvalds mov.l %d0,-(%sp) 2471da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_dww,%pc),%d0 2481da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2491da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 2501da177e4SLinus Torvalds rtd &0x4 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds global _dmem_write_long 2531da177e4SLinus Torvalds_dmem_write_long: 2541da177e4SLinus Torvalds mov.l %d0,-(%sp) 2551da177e4SLinus Torvalds mov.l (_060ISP_TABLE-0x80+_off_dwl,%pc),%d0 2561da177e4SLinus Torvalds pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2571da177e4SLinus Torvalds mov.l 0x4(%sp),%d0 2581da177e4SLinus Torvalds rtd &0x4 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds# 2611da177e4SLinus Torvalds# This file contains a set of define statements for constants 2621da177e4SLinus Torvalds# in oreder to promote readability within the core code itself. 2631da177e4SLinus Torvalds# 2641da177e4SLinus Torvalds 2651da177e4SLinus Torvaldsset LOCAL_SIZE, 96 # stack frame size(bytes) 2661da177e4SLinus Torvaldsset LV, -LOCAL_SIZE # stack offset 2671da177e4SLinus Torvalds 2681da177e4SLinus Torvaldsset EXC_ISR, 0x4 # stack status register 2691da177e4SLinus Torvaldsset EXC_IPC, 0x6 # stack pc 2701da177e4SLinus Torvaldsset EXC_IVOFF, 0xa # stacked vector offset 2711da177e4SLinus Torvalds 2721da177e4SLinus Torvaldsset EXC_AREGS, LV+64 # offset of all address regs 2731da177e4SLinus Torvaldsset EXC_DREGS, LV+32 # offset of all data regs 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvaldsset EXC_A7, EXC_AREGS+(7*4) # offset of a7 2761da177e4SLinus Torvaldsset EXC_A6, EXC_AREGS+(6*4) # offset of a6 2771da177e4SLinus Torvaldsset EXC_A5, EXC_AREGS+(5*4) # offset of a5 2781da177e4SLinus Torvaldsset EXC_A4, EXC_AREGS+(4*4) # offset of a4 2791da177e4SLinus Torvaldsset EXC_A3, EXC_AREGS+(3*4) # offset of a3 2801da177e4SLinus Torvaldsset EXC_A2, EXC_AREGS+(2*4) # offset of a2 2811da177e4SLinus Torvaldsset EXC_A1, EXC_AREGS+(1*4) # offset of a1 2821da177e4SLinus Torvaldsset EXC_A0, EXC_AREGS+(0*4) # offset of a0 2831da177e4SLinus Torvaldsset EXC_D7, EXC_DREGS+(7*4) # offset of d7 2841da177e4SLinus Torvaldsset EXC_D6, EXC_DREGS+(6*4) # offset of d6 2851da177e4SLinus Torvaldsset EXC_D5, EXC_DREGS+(5*4) # offset of d5 2861da177e4SLinus Torvaldsset EXC_D4, EXC_DREGS+(4*4) # offset of d4 2871da177e4SLinus Torvaldsset EXC_D3, EXC_DREGS+(3*4) # offset of d3 2881da177e4SLinus Torvaldsset EXC_D2, EXC_DREGS+(2*4) # offset of d2 2891da177e4SLinus Torvaldsset EXC_D1, EXC_DREGS+(1*4) # offset of d1 2901da177e4SLinus Torvaldsset EXC_D0, EXC_DREGS+(0*4) # offset of d0 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvaldsset EXC_TEMP, LV+16 # offset of temp stack space 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvaldsset EXC_SAVVAL, LV+12 # offset of old areg value 2951da177e4SLinus Torvaldsset EXC_SAVREG, LV+11 # offset of old areg index 2961da177e4SLinus Torvalds 2971da177e4SLinus Torvaldsset SPCOND_FLG, LV+10 # offset of spc condition flg 2981da177e4SLinus Torvalds 2991da177e4SLinus Torvaldsset EXC_CC, LV+8 # offset of cc register 3001da177e4SLinus Torvaldsset EXC_EXTWPTR, LV+4 # offset of current PC 3011da177e4SLinus Torvaldsset EXC_EXTWORD, LV+2 # offset of current ext opword 3021da177e4SLinus Torvaldsset EXC_OPWORD, LV+0 # offset of current opword 3031da177e4SLinus Torvalds 3041da177e4SLinus Torvalds########################### 3051da177e4SLinus Torvalds# SPecial CONDition FLaGs # 3061da177e4SLinus Torvalds########################### 3071da177e4SLinus Torvaldsset mia7_flg, 0x04 # (a7)+ flag 3081da177e4SLinus Torvaldsset mda7_flg, 0x08 # -(a7) flag 3091da177e4SLinus Torvaldsset ichk_flg, 0x10 # chk exception flag 3101da177e4SLinus Torvaldsset idbyz_flg, 0x20 # divbyzero flag 3111da177e4SLinus Torvaldsset restore_flg, 0x40 # restore -(an)+ flag 3121da177e4SLinus Torvaldsset immed_flg, 0x80 # immediate data flag 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvaldsset mia7_bit, 0x2 # (a7)+ bit 3151da177e4SLinus Torvaldsset mda7_bit, 0x3 # -(a7) bit 3161da177e4SLinus Torvaldsset ichk_bit, 0x4 # chk exception bit 3171da177e4SLinus Torvaldsset idbyz_bit, 0x5 # divbyzero bit 3181da177e4SLinus Torvaldsset restore_bit, 0x6 # restore -(a7)+ bit 3191da177e4SLinus Torvaldsset immed_bit, 0x7 # immediate data bit 3201da177e4SLinus Torvalds 3211da177e4SLinus Torvalds######### 3221da177e4SLinus Torvalds# Misc. # 3231da177e4SLinus Torvalds######### 3241da177e4SLinus Torvaldsset BYTE, 1 # len(byte) == 1 byte 3251da177e4SLinus Torvaldsset WORD, 2 # len(word) == 2 bytes 3261da177e4SLinus Torvaldsset LONG, 4 # len(longword) == 4 bytes 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds######################################################################### 3291da177e4SLinus Torvalds# XDEF **************************************************************** # 3301da177e4SLinus Torvalds# _isp_unimp(): 060ISP entry point for Unimplemented Instruction # 3311da177e4SLinus Torvalds# # 3321da177e4SLinus Torvalds# This handler should be the first code executed upon taking the # 3331da177e4SLinus Torvalds# "Unimplemented Integer Instruction" exception in an operating # 3341da177e4SLinus Torvalds# system. # 3351da177e4SLinus Torvalds# # 3361da177e4SLinus Torvalds# XREF **************************************************************** # 3371da177e4SLinus Torvalds# _imem_read_{word,long}() - read instruction word/longword # 3381da177e4SLinus Torvalds# _mul64() - emulate 64-bit multiply # 3391da177e4SLinus Torvalds# _div64() - emulate 64-bit divide # 3401da177e4SLinus Torvalds# _moveperipheral() - emulate "movep" # 3411da177e4SLinus Torvalds# _compandset() - emulate misaligned "cas" # 3421da177e4SLinus Torvalds# _compandset2() - emulate "cas2" # 3431da177e4SLinus Torvalds# _chk2_cmp2() - emulate "cmp2" and "chk2" # 3441da177e4SLinus Torvalds# _isp_done() - "callout" for normal final exit # 3451da177e4SLinus Torvalds# _real_trace() - "callout" for Trace exception # 3461da177e4SLinus Torvalds# _real_chk() - "callout" for Chk exception # 3471da177e4SLinus Torvalds# _real_divbyzero() - "callout" for DZ exception # 3481da177e4SLinus Torvalds# _real_access() - "callout" for access error exception # 3491da177e4SLinus Torvalds# # 3501da177e4SLinus Torvalds# INPUT *************************************************************** # 3511da177e4SLinus Torvalds# - The system stack contains the Unimp Int Instr stack frame # 3521da177e4SLinus Torvalds# # 3531da177e4SLinus Torvalds# OUTPUT ************************************************************** # 3541da177e4SLinus Torvalds# If Trace exception: # 3551da177e4SLinus Torvalds# - The system stack changed to contain Trace exc stack frame # 3561da177e4SLinus Torvalds# If Chk exception: # 3571da177e4SLinus Torvalds# - The system stack changed to contain Chk exc stack frame # 3581da177e4SLinus Torvalds# If DZ exception: # 3591da177e4SLinus Torvalds# - The system stack changed to contain DZ exc stack frame # 3601da177e4SLinus Torvalds# If access error exception: # 3611da177e4SLinus Torvalds# - The system stack changed to contain access err exc stk frame # 3621da177e4SLinus Torvalds# Else: # 3631da177e4SLinus Torvalds# - Results saved as appropriate # 3641da177e4SLinus Torvalds# # 3651da177e4SLinus Torvalds# ALGORITHM *********************************************************** # 3661da177e4SLinus Torvalds# This handler fetches the first instruction longword from # 3671da177e4SLinus Torvalds# memory and decodes it to determine which of the unimplemented # 3681da177e4SLinus Torvalds# integer instructions caused this exception. This handler then calls # 3691da177e4SLinus Torvalds# one of _mul64(), _div64(), _moveperipheral(), _compandset(), # 3701da177e4SLinus Torvalds# _compandset2(), or _chk2_cmp2() as appropriate. # 3711da177e4SLinus Torvalds# Some of these instructions, by their nature, may produce other # 3721da177e4SLinus Torvalds# types of exceptions. "div" can produce a divide-by-zero exception, # 3731da177e4SLinus Torvalds# and "chk2" can cause a "Chk" exception. In both cases, the current # 3741da177e4SLinus Torvalds# exception stack frame must be converted to an exception stack frame # 3751da177e4SLinus Torvalds# of the correct exception type and an exit must be made through # 3761da177e4SLinus Torvalds# _real_divbyzero() or _real_chk() as appropriate. In addition, all # 3771da177e4SLinus Torvalds# instructions may be executing while Trace is enabled. If so, then # 3781da177e4SLinus Torvalds# a Trace exception stack frame must be created and an exit made # 3791da177e4SLinus Torvalds# through _real_trace(). # 3801da177e4SLinus Torvalds# Meanwhile, if any read or write to memory using the # 3811da177e4SLinus Torvalds# _mem_{read,write}() "callout"s returns a failing value, then an # 3821da177e4SLinus Torvalds# access error frame must be created and an exit made through # 3831da177e4SLinus Torvalds# _real_access(). # 3841da177e4SLinus Torvalds# If none of these occur, then a normal exit is made through # 3851da177e4SLinus Torvalds# _isp_done(). # 3861da177e4SLinus Torvalds# # 3871da177e4SLinus Torvalds# This handler, upon entry, saves almost all user-visible # 3881da177e4SLinus Torvalds# address and data registers to the stack. Although this may seem to # 3891da177e4SLinus Torvalds# cause excess memory traffic, it was found that due to having to # 3901da177e4SLinus Torvalds# access these register files for things like data retrieval and <ea> # 3911da177e4SLinus Torvalds# calculations, it was more efficient to have them on the stack where # 3921da177e4SLinus Torvalds# they could be accessed by indexing rather than to make subroutine # 3931da177e4SLinus Torvalds# calls to retrieve a register of a particular index. # 3941da177e4SLinus Torvalds# # 3951da177e4SLinus Torvalds######################################################################### 3961da177e4SLinus Torvalds 3971da177e4SLinus Torvalds global _isp_unimp 3981da177e4SLinus Torvalds_isp_unimp: 3991da177e4SLinus Torvalds link.w %a6,&-LOCAL_SIZE # create room for stack frame 4001da177e4SLinus Torvalds 4011da177e4SLinus Torvalds movm.l &0x3fff,EXC_DREGS(%a6) # store d0-d7/a0-a5 4021da177e4SLinus Torvalds mov.l (%a6),EXC_A6(%a6) # store a6 4031da177e4SLinus Torvalds 4041da177e4SLinus Torvalds btst &0x5,EXC_ISR(%a6) # from s or u mode? 4051da177e4SLinus Torvalds bne.b uieh_s # supervisor mode 4061da177e4SLinus Torvaldsuieh_u: 4071da177e4SLinus Torvalds mov.l %usp,%a0 # fetch user stack pointer 4081da177e4SLinus Torvalds mov.l %a0,EXC_A7(%a6) # store a7 4091da177e4SLinus Torvalds bra.b uieh_cont 4101da177e4SLinus Torvaldsuieh_s: 4111da177e4SLinus Torvalds lea 0xc(%a6),%a0 4121da177e4SLinus Torvalds mov.l %a0,EXC_A7(%a6) # store corrected sp 4131da177e4SLinus Torvalds 4141da177e4SLinus Torvalds############################################################################### 4151da177e4SLinus Torvalds 4161da177e4SLinus Torvaldsuieh_cont: 4171da177e4SLinus Torvalds clr.b SPCOND_FLG(%a6) # clear "special case" flag 4181da177e4SLinus Torvalds 4191da177e4SLinus Torvalds mov.w EXC_ISR(%a6),EXC_CC(%a6) # store cc copy on stack 4201da177e4SLinus Torvalds mov.l EXC_IPC(%a6),EXC_EXTWPTR(%a6) # store extwptr on stack 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds# 4231da177e4SLinus Torvalds# fetch the opword and first extension word pointed to by the stacked pc 4241da177e4SLinus Torvalds# and store them to the stack for now 4251da177e4SLinus Torvalds# 4261da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 4271da177e4SLinus Torvalds addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 4281da177e4SLinus Torvalds bsr.l _imem_read_long # fetch opword & extword 4291da177e4SLinus Torvalds mov.l %d0,EXC_OPWORD(%a6) # store extword on stack 4301da177e4SLinus Torvalds 4311da177e4SLinus Torvalds 4321da177e4SLinus Torvalds######################################################################### 4331da177e4SLinus Torvalds# muls.l 0100 1100 00 |<ea>| 0*** 1100 0000 0*** # 4341da177e4SLinus Torvalds# mulu.l 0100 1100 00 |<ea>| 0*** 0100 0000 0*** # 4351da177e4SLinus Torvalds# # 4361da177e4SLinus Torvalds# divs.l 0100 1100 01 |<ea>| 0*** 1100 0000 0*** # 4371da177e4SLinus Torvalds# divu.l 0100 1100 01 |<ea>| 0*** 0100 0000 0*** # 4381da177e4SLinus Torvalds# # 4391da177e4SLinus Torvalds# movep.w m2r 0000 ***1 00 001*** | <displacement> | # 4401da177e4SLinus Torvalds# movep.l m2r 0000 ***1 01 001*** | <displacement> | # 4411da177e4SLinus Torvalds# movep.w r2m 0000 ***1 10 001*** | <displacement> | # 4421da177e4SLinus Torvalds# movep.l r2m 0000 ***1 11 001*** | <displacement> | # 4431da177e4SLinus Torvalds# # 4441da177e4SLinus Torvalds# cas.w 0000 1100 11 |<ea>| 0000 000* **00 0*** # 4451da177e4SLinus Torvalds# cas.l 0000 1110 11 |<ea>| 0000 000* **00 0*** # 4461da177e4SLinus Torvalds# # 4471da177e4SLinus Torvalds# cas2.w 0000 1100 11 111100 **** 000* **00 0*** # 4481da177e4SLinus Torvalds# **** 000* **00 0*** # 4491da177e4SLinus Torvalds# cas2.l 0000 1110 11 111100 **** 000* **00 0*** # 4501da177e4SLinus Torvalds# **** 000* **00 0*** # 4511da177e4SLinus Torvalds# # 4521da177e4SLinus Torvalds# chk2.b 0000 0000 11 |<ea>| **** 1000 0000 0000 # 4531da177e4SLinus Torvalds# chk2.w 0000 0010 11 |<ea>| **** 1000 0000 0000 # 4541da177e4SLinus Torvalds# chk2.l 0000 0100 11 |<ea>| **** 1000 0000 0000 # 4551da177e4SLinus Torvalds# # 4561da177e4SLinus Torvalds# cmp2.b 0000 0000 11 |<ea>| **** 0000 0000 0000 # 4571da177e4SLinus Torvalds# cmp2.w 0000 0010 11 |<ea>| **** 0000 0000 0000 # 4581da177e4SLinus Torvalds# cmp2.l 0000 0100 11 |<ea>| **** 0000 0000 0000 # 4591da177e4SLinus Torvalds######################################################################### 4601da177e4SLinus Torvalds 4611da177e4SLinus Torvalds# 4621da177e4SLinus Torvalds# using bit 14 of the operation word, separate into 2 groups: 4631da177e4SLinus Torvalds# (group1) mul64, div64 4641da177e4SLinus Torvalds# (group2) movep, chk2, cmp2, cas2, cas 4651da177e4SLinus Torvalds# 4661da177e4SLinus Torvalds btst &0x1e,%d0 # group1 or group2 4671da177e4SLinus Torvalds beq.b uieh_group2 # go handle group2 4681da177e4SLinus Torvalds 4691da177e4SLinus Torvalds# 4701da177e4SLinus Torvalds# now, w/ group1, make mul64's decode the fastest since it will 4711da177e4SLinus Torvalds# most likely be used the most. 4721da177e4SLinus Torvalds# 4731da177e4SLinus Torvaldsuieh_group1: 4741da177e4SLinus Torvalds btst &0x16,%d0 # test for div64 4751da177e4SLinus Torvalds bne.b uieh_div64 # go handle div64 4761da177e4SLinus Torvalds 4771da177e4SLinus Torvaldsuieh_mul64: 4781da177e4SLinus Torvalds# mul64() may use ()+ addressing and may, therefore, alter a7 4791da177e4SLinus Torvalds 4801da177e4SLinus Torvalds bsr.l _mul64 # _mul64() 4811da177e4SLinus Torvalds 4821da177e4SLinus Torvalds btst &0x5,EXC_ISR(%a6) # supervisor mode? 4831da177e4SLinus Torvalds beq.w uieh_done 4841da177e4SLinus Torvalds btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed? 4851da177e4SLinus Torvalds beq.w uieh_done # no 4861da177e4SLinus Torvalds btst &0x7,EXC_ISR(%a6) # is trace enabled? 4871da177e4SLinus Torvalds bne.w uieh_trace_a7 # yes 4881da177e4SLinus Torvalds bra.w uieh_a7 # no 4891da177e4SLinus Torvalds 4901da177e4SLinus Torvaldsuieh_div64: 4911da177e4SLinus Torvalds# div64() may use ()+ addressing and may, therefore, alter a7. 4921da177e4SLinus Torvalds# div64() may take a divide by zero exception. 4931da177e4SLinus Torvalds 4941da177e4SLinus Torvalds bsr.l _div64 # _div64() 4951da177e4SLinus Torvalds 4961da177e4SLinus Torvalds# here, we sort out all of the special cases that may have happened. 4971da177e4SLinus Torvalds btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed? 4981da177e4SLinus Torvalds bne.b uieh_div64_a7 # yes 4991da177e4SLinus Torvaldsuieh_div64_dbyz: 5001da177e4SLinus Torvalds btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur? 5011da177e4SLinus Torvalds bne.w uieh_divbyzero # yes 5021da177e4SLinus Torvalds bra.w uieh_done # no 5031da177e4SLinus Torvaldsuieh_div64_a7: 5041da177e4SLinus Torvalds btst &0x5,EXC_ISR(%a6) # supervisor mode? 5051da177e4SLinus Torvalds beq.b uieh_div64_dbyz # no 5061da177e4SLinus Torvalds# here, a7 has been incremented by 4 bytes in supervisor mode. we still 5071da177e4SLinus Torvalds# may have the following 3 cases: 5081da177e4SLinus Torvalds# (i) (a7)+ 5091da177e4SLinus Torvalds# (ii) (a7)+; trace 5101da177e4SLinus Torvalds# (iii) (a7)+; divide-by-zero 5111da177e4SLinus Torvalds# 5121da177e4SLinus Torvalds btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur? 5131da177e4SLinus Torvalds bne.w uieh_divbyzero_a7 # yes 5141da177e4SLinus Torvalds tst.b EXC_ISR(%a6) # no; is trace enabled? 5151da177e4SLinus Torvalds bmi.w uieh_trace_a7 # yes 5161da177e4SLinus Torvalds bra.w uieh_a7 # no 5171da177e4SLinus Torvalds 5181da177e4SLinus Torvalds# 5191da177e4SLinus Torvalds# now, w/ group2, make movep's decode the fastest since it will 5201da177e4SLinus Torvalds# most likely be used the most. 5211da177e4SLinus Torvalds# 5221da177e4SLinus Torvaldsuieh_group2: 5231da177e4SLinus Torvalds btst &0x18,%d0 # test for not movep 5241da177e4SLinus Torvalds beq.b uieh_not_movep 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds 5271da177e4SLinus Torvalds bsr.l _moveperipheral # _movep() 5281da177e4SLinus Torvalds bra.w uieh_done 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvaldsuieh_not_movep: 5311da177e4SLinus Torvalds btst &0x1b,%d0 # test for chk2,cmp2 5321da177e4SLinus Torvalds beq.b uieh_chk2cmp2 # go handle chk2,cmp2 5331da177e4SLinus Torvalds 5341da177e4SLinus Torvalds swap %d0 # put opword in lo word 5351da177e4SLinus Torvalds cmpi.b %d0,&0xfc # test for cas2 5361da177e4SLinus Torvalds beq.b uieh_cas2 # go handle cas2 5371da177e4SLinus Torvalds 5381da177e4SLinus Torvaldsuieh_cas: 5391da177e4SLinus Torvalds 5401da177e4SLinus Torvalds bsr.l _compandset # _cas() 5411da177e4SLinus Torvalds 5421da177e4SLinus Torvalds# the cases of "cas Dc,Du,(a7)+" and "cas Dc,Du,-(a7)" used from supervisor 5431da177e4SLinus Torvalds# mode are simply not considered valid and therefore are not handled. 5441da177e4SLinus Torvalds 5451da177e4SLinus Torvalds bra.w uieh_done 5461da177e4SLinus Torvalds 5471da177e4SLinus Torvaldsuieh_cas2: 5481da177e4SLinus Torvalds 5491da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 5501da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 5511da177e4SLinus Torvalds bsr.l _imem_read_word # read extension word 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds tst.l %d1 # ifetch error? 5541da177e4SLinus Torvalds bne.w isp_iacc # yes 5551da177e4SLinus Torvalds 5561da177e4SLinus Torvalds bsr.l _compandset2 # _cas2() 5571da177e4SLinus Torvalds bra.w uieh_done 5581da177e4SLinus Torvalds 5591da177e4SLinus Torvaldsuieh_chk2cmp2: 5601da177e4SLinus Torvalds# chk2 may take a chk exception 5611da177e4SLinus Torvalds 5621da177e4SLinus Torvalds bsr.l _chk2_cmp2 # _chk2_cmp2() 5631da177e4SLinus Torvalds 5641da177e4SLinus Torvalds# here we check to see if a chk trap should be taken 5651da177e4SLinus Torvalds cmpi.b SPCOND_FLG(%a6),&ichk_flg 5661da177e4SLinus Torvalds bne.w uieh_done 5671da177e4SLinus Torvalds bra.b uieh_chk_trap 5681da177e4SLinus Torvalds 5691da177e4SLinus Torvalds########################################################################### 5701da177e4SLinus Torvalds 5711da177e4SLinus Torvalds# 5721da177e4SLinus Torvalds# the required emulation has been completed. now, clean up the necessary stack 5731da177e4SLinus Torvalds# info and prepare for rte 5741da177e4SLinus Torvalds# 5751da177e4SLinus Torvaldsuieh_done: 5761da177e4SLinus Torvalds mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 5771da177e4SLinus Torvalds 5781da177e4SLinus Torvalds# if exception occurred in user mode, then we have to restore a7 in case it 5791da177e4SLinus Torvalds# changed. we don't have to update a7 for supervisor mose because that case 5801da177e4SLinus Torvalds# doesn't flow through here 5811da177e4SLinus Torvalds btst &0x5,EXC_ISR(%a6) # user or supervisor? 5821da177e4SLinus Torvalds bne.b uieh_finish # supervisor 5831da177e4SLinus Torvalds 5841da177e4SLinus Torvalds mov.l EXC_A7(%a6),%a0 # fetch user stack pointer 5851da177e4SLinus Torvalds mov.l %a0,%usp # restore it 5861da177e4SLinus Torvalds 5871da177e4SLinus Torvaldsuieh_finish: 5881da177e4SLinus Torvalds movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 5891da177e4SLinus Torvalds 5901da177e4SLinus Torvalds btst &0x7,EXC_ISR(%a6) # is trace mode on? 5911da177e4SLinus Torvalds bne.b uieh_trace # yes;go handle trace mode 5921da177e4SLinus Torvalds 5931da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),EXC_IPC(%a6) # new pc on stack frame 5941da177e4SLinus Torvalds mov.l EXC_A6(%a6),(%a6) # prepare new a6 for unlink 5951da177e4SLinus Torvalds unlk %a6 # unlink stack frame 5961da177e4SLinus Torvalds bra.l _isp_done 5971da177e4SLinus Torvalds 5981da177e4SLinus Torvalds# 5991da177e4SLinus Torvalds# The instruction that was just emulated was also being traced. The trace 6001da177e4SLinus Torvalds# trap for this instruction will be lost unless we jump to the trace handler. 6011da177e4SLinus Torvalds# So, here we create a Trace Exception format number two exception stack 6021da177e4SLinus Torvalds# frame from the Unimplemented Integer Intruction Exception stack frame 6031da177e4SLinus Torvalds# format number zero and jump to the user supplied hook "_real_trace()". 6041da177e4SLinus Torvalds# 6051da177e4SLinus Torvalds# UIEH FRAME TRACE FRAME 6061da177e4SLinus Torvalds# ***************** ***************** 6071da177e4SLinus Torvalds# * 0x0 * 0x0f4 * * Current * 6081da177e4SLinus Torvalds# ***************** * PC * 6091da177e4SLinus Torvalds# * Current * ***************** 6101da177e4SLinus Torvalds# * PC * * 0x2 * 0x024 * 6111da177e4SLinus Torvalds# ***************** ***************** 6121da177e4SLinus Torvalds# * SR * * Next * 6131da177e4SLinus Torvalds# ***************** * PC * 6141da177e4SLinus Torvalds# ->* Old * ***************** 6151da177e4SLinus Torvalds# from link -->* A6 * * SR * 6161da177e4SLinus Torvalds# ***************** ***************** 6171da177e4SLinus Torvalds# /* A7 * * New * <-- for final unlink 6181da177e4SLinus Torvalds# / * * * A6 * 6191da177e4SLinus Torvalds# link frame < ***************** ***************** 6201da177e4SLinus Torvalds# \ ~ ~ ~ ~ 6211da177e4SLinus Torvalds# \***************** ***************** 6221da177e4SLinus Torvalds# 6231da177e4SLinus Torvaldsuieh_trace: 6241da177e4SLinus Torvalds mov.l EXC_A6(%a6),-0x4(%a6) 6251da177e4SLinus Torvalds mov.w EXC_ISR(%a6),0x0(%a6) 6261da177e4SLinus Torvalds mov.l EXC_IPC(%a6),0x8(%a6) 6271da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),0x2(%a6) 6281da177e4SLinus Torvalds mov.w &0x2024,0x6(%a6) 6291da177e4SLinus Torvalds sub.l &0x4,%a6 6301da177e4SLinus Torvalds unlk %a6 6311da177e4SLinus Torvalds bra.l _real_trace 6321da177e4SLinus Torvalds 6331da177e4SLinus Torvalds# 6341da177e4SLinus Torvalds# UIEH FRAME CHK FRAME 6351da177e4SLinus Torvalds# ***************** ***************** 6361da177e4SLinus Torvalds# * 0x0 * 0x0f4 * * Current * 6371da177e4SLinus Torvalds# ***************** * PC * 6381da177e4SLinus Torvalds# * Current * ***************** 6391da177e4SLinus Torvalds# * PC * * 0x2 * 0x018 * 6401da177e4SLinus Torvalds# ***************** ***************** 6411da177e4SLinus Torvalds# * SR * * Next * 6421da177e4SLinus Torvalds# ***************** * PC * 6431da177e4SLinus Torvalds# (4 words) ***************** 6441da177e4SLinus Torvalds# * SR * 6451da177e4SLinus Torvalds# ***************** 6461da177e4SLinus Torvalds# (6 words) 6471da177e4SLinus Torvalds# 6481da177e4SLinus Torvalds# the chk2 instruction should take a chk trap. so, here we must create a 6491da177e4SLinus Torvalds# chk stack frame from an unimplemented integer instruction exception frame 6501da177e4SLinus Torvalds# and jump to the user supplied entry point "_real_chk()". 6511da177e4SLinus Torvalds# 6521da177e4SLinus Torvaldsuieh_chk_trap: 6531da177e4SLinus Torvalds mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 6541da177e4SLinus Torvalds movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 6551da177e4SLinus Torvalds 6561da177e4SLinus Torvalds mov.w EXC_ISR(%a6),(%a6) # put new SR on stack 6571da177e4SLinus Torvalds mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack 6581da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack 6591da177e4SLinus Torvalds mov.w &0x2018,0x6(%a6) # put Vector Offset on stack 6601da177e4SLinus Torvalds 6611da177e4SLinus Torvalds mov.l EXC_A6(%a6),%a6 # restore a6 6621da177e4SLinus Torvalds add.l &LOCAL_SIZE,%sp # clear stack frame 6631da177e4SLinus Torvalds 6641da177e4SLinus Torvalds bra.l _real_chk 6651da177e4SLinus Torvalds 6661da177e4SLinus Torvalds# 6671da177e4SLinus Torvalds# UIEH FRAME DIVBYZERO FRAME 6681da177e4SLinus Torvalds# ***************** ***************** 6691da177e4SLinus Torvalds# * 0x0 * 0x0f4 * * Current * 6701da177e4SLinus Torvalds# ***************** * PC * 6711da177e4SLinus Torvalds# * Current * ***************** 6721da177e4SLinus Torvalds# * PC * * 0x2 * 0x014 * 6731da177e4SLinus Torvalds# ***************** ***************** 6741da177e4SLinus Torvalds# * SR * * Next * 6751da177e4SLinus Torvalds# ***************** * PC * 6761da177e4SLinus Torvalds# (4 words) ***************** 6771da177e4SLinus Torvalds# * SR * 6781da177e4SLinus Torvalds# ***************** 6791da177e4SLinus Torvalds# (6 words) 6801da177e4SLinus Torvalds# 6811da177e4SLinus Torvalds# the divide instruction should take an integer divide by zero trap. so, here 6821da177e4SLinus Torvalds# we must create a divbyzero stack frame from an unimplemented integer 6831da177e4SLinus Torvalds# instruction exception frame and jump to the user supplied entry point 6841da177e4SLinus Torvalds# "_real_divbyzero()". 6851da177e4SLinus Torvalds# 6861da177e4SLinus Torvaldsuieh_divbyzero: 6871da177e4SLinus Torvalds mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 6881da177e4SLinus Torvalds movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 6891da177e4SLinus Torvalds 6901da177e4SLinus Torvalds mov.w EXC_ISR(%a6),(%a6) # put new SR on stack 6911da177e4SLinus Torvalds mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack 6921da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack 6931da177e4SLinus Torvalds mov.w &0x2014,0x6(%a6) # put Vector Offset on stack 6941da177e4SLinus Torvalds 6951da177e4SLinus Torvalds mov.l EXC_A6(%a6),%a6 # restore a6 6961da177e4SLinus Torvalds add.l &LOCAL_SIZE,%sp # clear stack frame 6971da177e4SLinus Torvalds 6981da177e4SLinus Torvalds bra.l _real_divbyzero 6991da177e4SLinus Torvalds 7001da177e4SLinus Torvalds# 7011da177e4SLinus Torvalds# DIVBYZERO FRAME 7021da177e4SLinus Torvalds# ***************** 7031da177e4SLinus Torvalds# * Current * 7041da177e4SLinus Torvalds# UIEH FRAME * PC * 7051da177e4SLinus Torvalds# ***************** ***************** 7061da177e4SLinus Torvalds# * 0x0 * 0x0f4 * * 0x2 * 0x014 * 7071da177e4SLinus Torvalds# ***************** ***************** 7081da177e4SLinus Torvalds# * Current * * Next * 7091da177e4SLinus Torvalds# * PC * * PC * 7101da177e4SLinus Torvalds# ***************** ***************** 7111da177e4SLinus Torvalds# * SR * * SR * 7121da177e4SLinus Torvalds# ***************** ***************** 7131da177e4SLinus Torvalds# (4 words) (6 words) 7141da177e4SLinus Torvalds# 7151da177e4SLinus Torvalds# the divide instruction should take an integer divide by zero trap. so, here 7161da177e4SLinus Torvalds# we must create a divbyzero stack frame from an unimplemented integer 7171da177e4SLinus Torvalds# instruction exception frame and jump to the user supplied entry point 7181da177e4SLinus Torvalds# "_real_divbyzero()". 7191da177e4SLinus Torvalds# 7201da177e4SLinus Torvalds# However, we must also deal with the fact that (a7)+ was used from supervisor 7211da177e4SLinus Torvalds# mode, thereby shifting the stack frame up 4 bytes. 7221da177e4SLinus Torvalds# 7231da177e4SLinus Torvaldsuieh_divbyzero_a7: 7241da177e4SLinus Torvalds mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 7251da177e4SLinus Torvalds movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 7261da177e4SLinus Torvalds 7271da177e4SLinus Torvalds mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack 7281da177e4SLinus Torvalds mov.w &0x2014,0xa(%a6) # put Vector Offset on stack 7291da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack 7301da177e4SLinus Torvalds 7311da177e4SLinus Torvalds mov.l EXC_A6(%a6),%a6 # restore a6 7321da177e4SLinus Torvalds add.l &4+LOCAL_SIZE,%sp # clear stack frame 7331da177e4SLinus Torvalds 7341da177e4SLinus Torvalds bra.l _real_divbyzero 7351da177e4SLinus Torvalds 7361da177e4SLinus Torvalds# 7371da177e4SLinus Torvalds# TRACE FRAME 7381da177e4SLinus Torvalds# ***************** 7391da177e4SLinus Torvalds# * Current * 7401da177e4SLinus Torvalds# UIEH FRAME * PC * 7411da177e4SLinus Torvalds# ***************** ***************** 7421da177e4SLinus Torvalds# * 0x0 * 0x0f4 * * 0x2 * 0x024 * 7431da177e4SLinus Torvalds# ***************** ***************** 7441da177e4SLinus Torvalds# * Current * * Next * 7451da177e4SLinus Torvalds# * PC * * PC * 7461da177e4SLinus Torvalds# ***************** ***************** 7471da177e4SLinus Torvalds# * SR * * SR * 7481da177e4SLinus Torvalds# ***************** ***************** 7491da177e4SLinus Torvalds# (4 words) (6 words) 7501da177e4SLinus Torvalds# 7511da177e4SLinus Torvalds# 7521da177e4SLinus Torvalds# The instruction that was just emulated was also being traced. The trace 7531da177e4SLinus Torvalds# trap for this instruction will be lost unless we jump to the trace handler. 7541da177e4SLinus Torvalds# So, here we create a Trace Exception format number two exception stack 7551da177e4SLinus Torvalds# frame from the Unimplemented Integer Intruction Exception stack frame 7561da177e4SLinus Torvalds# format number zero and jump to the user supplied hook "_real_trace()". 7571da177e4SLinus Torvalds# 7581da177e4SLinus Torvalds# However, we must also deal with the fact that (a7)+ was used from supervisor 7591da177e4SLinus Torvalds# mode, thereby shifting the stack frame up 4 bytes. 7601da177e4SLinus Torvalds# 7611da177e4SLinus Torvaldsuieh_trace_a7: 7621da177e4SLinus Torvalds mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 7631da177e4SLinus Torvalds movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 7641da177e4SLinus Torvalds 7651da177e4SLinus Torvalds mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack 7661da177e4SLinus Torvalds mov.w &0x2024,0xa(%a6) # put Vector Offset on stack 7671da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack 7681da177e4SLinus Torvalds 7691da177e4SLinus Torvalds mov.l EXC_A6(%a6),%a6 # restore a6 7701da177e4SLinus Torvalds add.l &4+LOCAL_SIZE,%sp # clear stack frame 7711da177e4SLinus Torvalds 7721da177e4SLinus Torvalds bra.l _real_trace 7731da177e4SLinus Torvalds 7741da177e4SLinus Torvalds# 7751da177e4SLinus Torvalds# UIEH FRAME 7761da177e4SLinus Torvalds# ***************** 7771da177e4SLinus Torvalds# * 0x0 * 0x0f4 * 7781da177e4SLinus Torvalds# UIEH FRAME ***************** 7791da177e4SLinus Torvalds# ***************** * Next * 7801da177e4SLinus Torvalds# * 0x0 * 0x0f4 * * PC * 7811da177e4SLinus Torvalds# ***************** ***************** 7821da177e4SLinus Torvalds# * Current * * SR * 7831da177e4SLinus Torvalds# * PC * ***************** 7841da177e4SLinus Torvalds# ***************** (4 words) 7851da177e4SLinus Torvalds# * SR * 7861da177e4SLinus Torvalds# ***************** 7871da177e4SLinus Torvalds# (4 words) 7881da177e4SLinus Torvaldsuieh_a7: 7891da177e4SLinus Torvalds mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 7901da177e4SLinus Torvalds movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 7911da177e4SLinus Torvalds 7921da177e4SLinus Torvalds mov.w &0x00f4,0xe(%a6) # put Vector Offset on stack 7931da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),0xa(%a6) # put "Next PC" on stack 7941da177e4SLinus Torvalds mov.w EXC_ISR(%a6),0x8(%a6) # put SR on stack 7951da177e4SLinus Torvalds 7961da177e4SLinus Torvalds mov.l EXC_A6(%a6),%a6 # restore a6 7971da177e4SLinus Torvalds add.l &8+LOCAL_SIZE,%sp # clear stack frame 7981da177e4SLinus Torvalds bra.l _isp_done 7991da177e4SLinus Torvalds 8001da177e4SLinus Torvalds########## 8011da177e4SLinus Torvalds 8021da177e4SLinus Torvalds# this is the exit point if a data read or write fails. 8031da177e4SLinus Torvalds# a0 = failing address 8041da177e4SLinus Torvalds# d0 = fslw 8051da177e4SLinus Torvaldsisp_dacc: 8061da177e4SLinus Torvalds mov.l %a0,(%a6) # save address 8071da177e4SLinus Torvalds mov.l %d0,-0x4(%a6) # save partial fslw 8081da177e4SLinus Torvalds 8091da177e4SLinus Torvalds lea -64(%a6),%sp 8101da177e4SLinus Torvalds movm.l (%sp)+,&0x7fff # restore d0-d7/a0-a6 8111da177e4SLinus Torvalds 8121da177e4SLinus Torvalds mov.l 0xc(%sp),-(%sp) # move voff,hi(pc) 8131da177e4SLinus Torvalds mov.l 0x4(%sp),0x10(%sp) # store fslw 8141da177e4SLinus Torvalds mov.l 0xc(%sp),0x4(%sp) # store sr,lo(pc) 8151da177e4SLinus Torvalds mov.l 0x8(%sp),0xc(%sp) # store address 8161da177e4SLinus Torvalds mov.l (%sp)+,0x4(%sp) # store voff,hi(pc) 8171da177e4SLinus Torvalds mov.w &0x4008,0x6(%sp) # store new voff 8181da177e4SLinus Torvalds 8191da177e4SLinus Torvalds bra.b isp_acc_exit 8201da177e4SLinus Torvalds 8211da177e4SLinus Torvalds# this is the exit point if an instruction word read fails. 8221da177e4SLinus Torvalds# FSLW: 8231da177e4SLinus Torvalds# misaligned = true 8241da177e4SLinus Torvalds# read = true 8251da177e4SLinus Torvalds# size = word 8261da177e4SLinus Torvalds# instruction = true 8271da177e4SLinus Torvalds# software emulation error = true 8281da177e4SLinus Torvaldsisp_iacc: 8291da177e4SLinus Torvalds movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 8301da177e4SLinus Torvalds unlk %a6 # unlink frame 8311da177e4SLinus Torvalds sub.w &0x8,%sp # make room for acc frame 8321da177e4SLinus Torvalds mov.l 0x8(%sp),(%sp) # store sr,lo(pc) 8331da177e4SLinus Torvalds mov.w 0xc(%sp),0x4(%sp) # store hi(pc) 8341da177e4SLinus Torvalds mov.w &0x4008,0x6(%sp) # store new voff 8351da177e4SLinus Torvalds mov.l 0x2(%sp),0x8(%sp) # store address (=pc) 8361da177e4SLinus Torvalds mov.l &0x09428001,0xc(%sp) # store fslw 8371da177e4SLinus Torvalds 8381da177e4SLinus Torvaldsisp_acc_exit: 8391da177e4SLinus Torvalds btst &0x5,(%sp) # user or supervisor? 8401da177e4SLinus Torvalds beq.b isp_acc_exit2 # user 8411da177e4SLinus Torvalds bset &0x2,0xd(%sp) # set supervisor TM bit 8421da177e4SLinus Torvaldsisp_acc_exit2: 8431da177e4SLinus Torvalds bra.l _real_access 8441da177e4SLinus Torvalds 8451da177e4SLinus Torvalds# if the addressing mode was (an)+ or -(an), the address register must 8461da177e4SLinus Torvalds# be restored to its pre-exception value before entering _real_access. 8471da177e4SLinus Torvaldsisp_restore: 8481da177e4SLinus Torvalds cmpi.b SPCOND_FLG(%a6),&restore_flg # do we need a restore? 8491da177e4SLinus Torvalds bne.b isp_restore_done # no 8501da177e4SLinus Torvalds clr.l %d0 8511da177e4SLinus Torvalds mov.b EXC_SAVREG(%a6),%d0 # regno to restore 8521da177e4SLinus Torvalds mov.l EXC_SAVVAL(%a6),(EXC_AREGS,%a6,%d0.l*4) # restore value 8531da177e4SLinus Torvaldsisp_restore_done: 8541da177e4SLinus Torvalds rts 8551da177e4SLinus Torvalds 8561da177e4SLinus Torvalds######################################################################### 8571da177e4SLinus Torvalds# XDEF **************************************************************** # 8581da177e4SLinus Torvalds# _calc_ea(): routine to calculate effective address # 8591da177e4SLinus Torvalds# # 8601da177e4SLinus Torvalds# XREF **************************************************************** # 8611da177e4SLinus Torvalds# _imem_read_word() - read instruction word # 8621da177e4SLinus Torvalds# _imem_read_long() - read instruction longword # 8631da177e4SLinus Torvalds# _dmem_read_long() - read data longword (for memory indirect) # 8641da177e4SLinus Torvalds# isp_iacc() - handle instruction access error exception # 8651da177e4SLinus Torvalds# isp_dacc() - handle data access error exception # 8661da177e4SLinus Torvalds# # 8671da177e4SLinus Torvalds# INPUT *************************************************************** # 8681da177e4SLinus Torvalds# d0 = number of bytes related to effective address (w,l) # 8691da177e4SLinus Torvalds# # 8701da177e4SLinus Torvalds# OUTPUT ************************************************************** # 8711da177e4SLinus Torvalds# If exiting through isp_dacc... # 8721da177e4SLinus Torvalds# a0 = failing address # 8731da177e4SLinus Torvalds# d0 = FSLW # 8741da177e4SLinus Torvalds# elsif exiting though isp_iacc... # 8751da177e4SLinus Torvalds# none # 8761da177e4SLinus Torvalds# else # 8771da177e4SLinus Torvalds# a0 = effective address # 8781da177e4SLinus Torvalds# # 8791da177e4SLinus Torvalds# ALGORITHM *********************************************************** # 8801da177e4SLinus Torvalds# The effective address type is decoded from the opword residing # 8811da177e4SLinus Torvalds# on the stack. A jump table is used to vector to a routine for the # 8821da177e4SLinus Torvalds# appropriate mode. Since none of the emulated integer instructions # 8831da177e4SLinus Torvalds# uses byte-sized operands, only handle word and long operations. # 8841da177e4SLinus Torvalds# # 8851da177e4SLinus Torvalds# Dn,An - shouldn't enter here # 8861da177e4SLinus Torvalds# (An) - fetch An value from stack # 8871da177e4SLinus Torvalds# -(An) - fetch An value from stack; return decr value; # 8881da177e4SLinus Torvalds# place decr value on stack; store old value in case of # 8891da177e4SLinus Torvalds# future access error; if -(a7), set mda7_flg in # 8901da177e4SLinus Torvalds# SPCOND_FLG # 8911da177e4SLinus Torvalds# (An)+ - fetch An value from stack; return value; # 8921da177e4SLinus Torvalds# place incr value on stack; store old value in case of # 8931da177e4SLinus Torvalds# future access error; if (a7)+, set mia7_flg in # 8941da177e4SLinus Torvalds# SPCOND_FLG # 8951da177e4SLinus Torvalds# (d16,An) - fetch An value from stack; read d16 using # 8961da177e4SLinus Torvalds# _imem_read_word(); fetch may fail -> branch to # 8971da177e4SLinus Torvalds# isp_iacc() # 8981da177e4SLinus Torvalds# (xxx).w,(xxx).l - use _imem_read_{word,long}() to fetch # 8991da177e4SLinus Torvalds# address; fetch may fail # 9001da177e4SLinus Torvalds# #<data> - return address of immediate value; set immed_flg # 9011da177e4SLinus Torvalds# in SPCOND_FLG # 9021da177e4SLinus Torvalds# (d16,PC) - fetch stacked PC value; read d16 using # 9031da177e4SLinus Torvalds# _imem_read_word(); fetch may fail -> branch to # 9041da177e4SLinus Torvalds# isp_iacc() # 9051da177e4SLinus Torvalds# everything else - read needed displacements as appropriate w/ # 9061da177e4SLinus Torvalds# _imem_read_{word,long}(); read may fail; if memory # 9071da177e4SLinus Torvalds# indirect, read indirect address using # 9081da177e4SLinus Torvalds# _dmem_read_long() which may also fail # 9091da177e4SLinus Torvalds# # 9101da177e4SLinus Torvalds######################################################################### 9111da177e4SLinus Torvalds 9121da177e4SLinus Torvalds global _calc_ea 9131da177e4SLinus Torvalds_calc_ea: 9141da177e4SLinus Torvalds mov.l %d0,%a0 # move # bytes to a0 9151da177e4SLinus Torvalds 9161da177e4SLinus Torvalds# MODE and REG are taken from the EXC_OPWORD. 9171da177e4SLinus Torvalds mov.w EXC_OPWORD(%a6),%d0 # fetch opcode word 9181da177e4SLinus Torvalds mov.w %d0,%d1 # make a copy 9191da177e4SLinus Torvalds 9201da177e4SLinus Torvalds andi.w &0x3f,%d0 # extract mode field 9211da177e4SLinus Torvalds andi.l &0x7,%d1 # extract reg field 9221da177e4SLinus Torvalds 9231da177e4SLinus Torvalds# jump to the corresponding function for each {MODE,REG} pair. 9241da177e4SLinus Torvalds mov.w (tbl_ea_mode.b,%pc,%d0.w*2), %d0 # fetch jmp distance 9251da177e4SLinus Torvalds jmp (tbl_ea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode 9261da177e4SLinus Torvalds 9271da177e4SLinus Torvalds swbeg &64 9281da177e4SLinus Torvaldstbl_ea_mode: 9291da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9301da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9311da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9321da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9331da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9341da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9351da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9361da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9371da177e4SLinus Torvalds 9381da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9391da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9401da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9411da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9421da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9431da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9441da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9451da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9461da177e4SLinus Torvalds 9471da177e4SLinus Torvalds short addr_ind_a0 - tbl_ea_mode 9481da177e4SLinus Torvalds short addr_ind_a1 - tbl_ea_mode 9491da177e4SLinus Torvalds short addr_ind_a2 - tbl_ea_mode 9501da177e4SLinus Torvalds short addr_ind_a3 - tbl_ea_mode 9511da177e4SLinus Torvalds short addr_ind_a4 - tbl_ea_mode 9521da177e4SLinus Torvalds short addr_ind_a5 - tbl_ea_mode 9531da177e4SLinus Torvalds short addr_ind_a6 - tbl_ea_mode 9541da177e4SLinus Torvalds short addr_ind_a7 - tbl_ea_mode 9551da177e4SLinus Torvalds 9561da177e4SLinus Torvalds short addr_ind_p_a0 - tbl_ea_mode 9571da177e4SLinus Torvalds short addr_ind_p_a1 - tbl_ea_mode 9581da177e4SLinus Torvalds short addr_ind_p_a2 - tbl_ea_mode 9591da177e4SLinus Torvalds short addr_ind_p_a3 - tbl_ea_mode 9601da177e4SLinus Torvalds short addr_ind_p_a4 - tbl_ea_mode 9611da177e4SLinus Torvalds short addr_ind_p_a5 - tbl_ea_mode 9621da177e4SLinus Torvalds short addr_ind_p_a6 - tbl_ea_mode 9631da177e4SLinus Torvalds short addr_ind_p_a7 - tbl_ea_mode 9641da177e4SLinus Torvalds 9651da177e4SLinus Torvalds short addr_ind_m_a0 - tbl_ea_mode 9661da177e4SLinus Torvalds short addr_ind_m_a1 - tbl_ea_mode 9671da177e4SLinus Torvalds short addr_ind_m_a2 - tbl_ea_mode 9681da177e4SLinus Torvalds short addr_ind_m_a3 - tbl_ea_mode 9691da177e4SLinus Torvalds short addr_ind_m_a4 - tbl_ea_mode 9701da177e4SLinus Torvalds short addr_ind_m_a5 - tbl_ea_mode 9711da177e4SLinus Torvalds short addr_ind_m_a6 - tbl_ea_mode 9721da177e4SLinus Torvalds short addr_ind_m_a7 - tbl_ea_mode 9731da177e4SLinus Torvalds 9741da177e4SLinus Torvalds short addr_ind_disp_a0 - tbl_ea_mode 9751da177e4SLinus Torvalds short addr_ind_disp_a1 - tbl_ea_mode 9761da177e4SLinus Torvalds short addr_ind_disp_a2 - tbl_ea_mode 9771da177e4SLinus Torvalds short addr_ind_disp_a3 - tbl_ea_mode 9781da177e4SLinus Torvalds short addr_ind_disp_a4 - tbl_ea_mode 9791da177e4SLinus Torvalds short addr_ind_disp_a5 - tbl_ea_mode 9801da177e4SLinus Torvalds short addr_ind_disp_a6 - tbl_ea_mode 9811da177e4SLinus Torvalds short addr_ind_disp_a7 - tbl_ea_mode 9821da177e4SLinus Torvalds 9831da177e4SLinus Torvalds short _addr_ind_ext - tbl_ea_mode 9841da177e4SLinus Torvalds short _addr_ind_ext - tbl_ea_mode 9851da177e4SLinus Torvalds short _addr_ind_ext - tbl_ea_mode 9861da177e4SLinus Torvalds short _addr_ind_ext - tbl_ea_mode 9871da177e4SLinus Torvalds short _addr_ind_ext - tbl_ea_mode 9881da177e4SLinus Torvalds short _addr_ind_ext - tbl_ea_mode 9891da177e4SLinus Torvalds short _addr_ind_ext - tbl_ea_mode 9901da177e4SLinus Torvalds short _addr_ind_ext - tbl_ea_mode 9911da177e4SLinus Torvalds 9921da177e4SLinus Torvalds short abs_short - tbl_ea_mode 9931da177e4SLinus Torvalds short abs_long - tbl_ea_mode 9941da177e4SLinus Torvalds short pc_ind - tbl_ea_mode 9951da177e4SLinus Torvalds short pc_ind_ext - tbl_ea_mode 9961da177e4SLinus Torvalds short immediate - tbl_ea_mode 9971da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9981da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 9991da177e4SLinus Torvalds short tbl_ea_mode - tbl_ea_mode 10001da177e4SLinus Torvalds 10011da177e4SLinus Torvalds################################### 10021da177e4SLinus Torvalds# Address register indirect: (An) # 10031da177e4SLinus Torvalds################################### 10041da177e4SLinus Torvaldsaddr_ind_a0: 10051da177e4SLinus Torvalds mov.l EXC_A0(%a6),%a0 # Get current a0 10061da177e4SLinus Torvalds rts 10071da177e4SLinus Torvalds 10081da177e4SLinus Torvaldsaddr_ind_a1: 10091da177e4SLinus Torvalds mov.l EXC_A1(%a6),%a0 # Get current a1 10101da177e4SLinus Torvalds rts 10111da177e4SLinus Torvalds 10121da177e4SLinus Torvaldsaddr_ind_a2: 10131da177e4SLinus Torvalds mov.l EXC_A2(%a6),%a0 # Get current a2 10141da177e4SLinus Torvalds rts 10151da177e4SLinus Torvalds 10161da177e4SLinus Torvaldsaddr_ind_a3: 10171da177e4SLinus Torvalds mov.l EXC_A3(%a6),%a0 # Get current a3 10181da177e4SLinus Torvalds rts 10191da177e4SLinus Torvalds 10201da177e4SLinus Torvaldsaddr_ind_a4: 10211da177e4SLinus Torvalds mov.l EXC_A4(%a6),%a0 # Get current a4 10221da177e4SLinus Torvalds rts 10231da177e4SLinus Torvalds 10241da177e4SLinus Torvaldsaddr_ind_a5: 10251da177e4SLinus Torvalds mov.l EXC_A5(%a6),%a0 # Get current a5 10261da177e4SLinus Torvalds rts 10271da177e4SLinus Torvalds 10281da177e4SLinus Torvaldsaddr_ind_a6: 10291da177e4SLinus Torvalds mov.l EXC_A6(%a6),%a0 # Get current a6 10301da177e4SLinus Torvalds rts 10311da177e4SLinus Torvalds 10321da177e4SLinus Torvaldsaddr_ind_a7: 10331da177e4SLinus Torvalds mov.l EXC_A7(%a6),%a0 # Get current a7 10341da177e4SLinus Torvalds rts 10351da177e4SLinus Torvalds 10361da177e4SLinus Torvalds##################################################### 10371da177e4SLinus Torvalds# Address register indirect w/ postincrement: (An)+ # 10381da177e4SLinus Torvalds##################################################### 10391da177e4SLinus Torvaldsaddr_ind_p_a0: 10401da177e4SLinus Torvalds mov.l %a0,%d0 # copy no. bytes 10411da177e4SLinus Torvalds mov.l EXC_A0(%a6),%a0 # load current value 10421da177e4SLinus Torvalds add.l %a0,%d0 # increment 10431da177e4SLinus Torvalds mov.l %d0,EXC_A0(%a6) # save incremented value 10441da177e4SLinus Torvalds 10451da177e4SLinus Torvalds mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 10461da177e4SLinus Torvalds mov.b &0x0,EXC_SAVREG(%a6) # save regno, too 10471da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 10481da177e4SLinus Torvalds rts 10491da177e4SLinus Torvalds 10501da177e4SLinus Torvaldsaddr_ind_p_a1: 10511da177e4SLinus Torvalds mov.l %a0,%d0 # copy no. bytes 10521da177e4SLinus Torvalds mov.l EXC_A1(%a6),%a0 # load current value 10531da177e4SLinus Torvalds add.l %a0,%d0 # increment 10541da177e4SLinus Torvalds mov.l %d0,EXC_A1(%a6) # save incremented value 10551da177e4SLinus Torvalds 10561da177e4SLinus Torvalds mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 10571da177e4SLinus Torvalds mov.b &0x1,EXC_SAVREG(%a6) # save regno, too 10581da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 10591da177e4SLinus Torvalds rts 10601da177e4SLinus Torvalds 10611da177e4SLinus Torvaldsaddr_ind_p_a2: 10621da177e4SLinus Torvalds mov.l %a0,%d0 # copy no. bytes 10631da177e4SLinus Torvalds mov.l EXC_A2(%a6),%a0 # load current value 10641da177e4SLinus Torvalds add.l %a0,%d0 # increment 10651da177e4SLinus Torvalds mov.l %d0,EXC_A2(%a6) # save incremented value 10661da177e4SLinus Torvalds 10671da177e4SLinus Torvalds mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 10681da177e4SLinus Torvalds mov.b &0x2,EXC_SAVREG(%a6) # save regno, too 10691da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 10701da177e4SLinus Torvalds rts 10711da177e4SLinus Torvalds 10721da177e4SLinus Torvaldsaddr_ind_p_a3: 10731da177e4SLinus Torvalds mov.l %a0,%d0 # copy no. bytes 10741da177e4SLinus Torvalds mov.l EXC_A3(%a6),%a0 # load current value 10751da177e4SLinus Torvalds add.l %a0,%d0 # increment 10761da177e4SLinus Torvalds mov.l %d0,EXC_A3(%a6) # save incremented value 10771da177e4SLinus Torvalds 10781da177e4SLinus Torvalds mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 10791da177e4SLinus Torvalds mov.b &0x3,EXC_SAVREG(%a6) # save regno, too 10801da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 10811da177e4SLinus Torvalds rts 10821da177e4SLinus Torvalds 10831da177e4SLinus Torvaldsaddr_ind_p_a4: 10841da177e4SLinus Torvalds mov.l %a0,%d0 # copy no. bytes 10851da177e4SLinus Torvalds mov.l EXC_A4(%a6),%a0 # load current value 10861da177e4SLinus Torvalds add.l %a0,%d0 # increment 10871da177e4SLinus Torvalds mov.l %d0,EXC_A4(%a6) # save incremented value 10881da177e4SLinus Torvalds 10891da177e4SLinus Torvalds mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 10901da177e4SLinus Torvalds mov.b &0x4,EXC_SAVREG(%a6) # save regno, too 10911da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 10921da177e4SLinus Torvalds rts 10931da177e4SLinus Torvalds 10941da177e4SLinus Torvaldsaddr_ind_p_a5: 10951da177e4SLinus Torvalds mov.l %a0,%d0 # copy no. bytes 10961da177e4SLinus Torvalds mov.l EXC_A5(%a6),%a0 # load current value 10971da177e4SLinus Torvalds add.l %a0,%d0 # increment 10981da177e4SLinus Torvalds mov.l %d0,EXC_A5(%a6) # save incremented value 10991da177e4SLinus Torvalds 11001da177e4SLinus Torvalds mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 11011da177e4SLinus Torvalds mov.b &0x5,EXC_SAVREG(%a6) # save regno, too 11021da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11031da177e4SLinus Torvalds rts 11041da177e4SLinus Torvalds 11051da177e4SLinus Torvaldsaddr_ind_p_a6: 11061da177e4SLinus Torvalds mov.l %a0,%d0 # copy no. bytes 11071da177e4SLinus Torvalds mov.l EXC_A6(%a6),%a0 # load current value 11081da177e4SLinus Torvalds add.l %a0,%d0 # increment 11091da177e4SLinus Torvalds mov.l %d0,EXC_A6(%a6) # save incremented value 11101da177e4SLinus Torvalds 11111da177e4SLinus Torvalds mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 11121da177e4SLinus Torvalds mov.b &0x6,EXC_SAVREG(%a6) # save regno, too 11131da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11141da177e4SLinus Torvalds rts 11151da177e4SLinus Torvalds 11161da177e4SLinus Torvaldsaddr_ind_p_a7: 11171da177e4SLinus Torvalds mov.b &mia7_flg,SPCOND_FLG(%a6) # set "special case" flag 11181da177e4SLinus Torvalds 11191da177e4SLinus Torvalds mov.l %a0,%d0 # copy no. bytes 11201da177e4SLinus Torvalds mov.l EXC_A7(%a6),%a0 # load current value 11211da177e4SLinus Torvalds add.l %a0,%d0 # increment 11221da177e4SLinus Torvalds mov.l %d0,EXC_A7(%a6) # save incremented value 11231da177e4SLinus Torvalds rts 11241da177e4SLinus Torvalds 11251da177e4SLinus Torvalds#################################################### 11261da177e4SLinus Torvalds# Address register indirect w/ predecrement: -(An) # 11271da177e4SLinus Torvalds#################################################### 11281da177e4SLinus Torvaldsaddr_ind_m_a0: 11291da177e4SLinus Torvalds mov.l EXC_A0(%a6),%d0 # Get current a0 11301da177e4SLinus Torvalds mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11311da177e4SLinus Torvalds sub.l %a0,%d0 # Decrement 11321da177e4SLinus Torvalds mov.l %d0,EXC_A0(%a6) # Save decr value 11331da177e4SLinus Torvalds mov.l %d0,%a0 11341da177e4SLinus Torvalds 11351da177e4SLinus Torvalds mov.b &0x0,EXC_SAVREG(%a6) # save regno, too 11361da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11371da177e4SLinus Torvalds rts 11381da177e4SLinus Torvalds 11391da177e4SLinus Torvaldsaddr_ind_m_a1: 11401da177e4SLinus Torvalds mov.l EXC_A1(%a6),%d0 # Get current a1 11411da177e4SLinus Torvalds mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11421da177e4SLinus Torvalds sub.l %a0,%d0 # Decrement 11431da177e4SLinus Torvalds mov.l %d0,EXC_A1(%a6) # Save decr value 11441da177e4SLinus Torvalds mov.l %d0,%a0 11451da177e4SLinus Torvalds 11461da177e4SLinus Torvalds mov.b &0x1,EXC_SAVREG(%a6) # save regno, too 11471da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11481da177e4SLinus Torvalds rts 11491da177e4SLinus Torvalds 11501da177e4SLinus Torvaldsaddr_ind_m_a2: 11511da177e4SLinus Torvalds mov.l EXC_A2(%a6),%d0 # Get current a2 11521da177e4SLinus Torvalds mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11531da177e4SLinus Torvalds sub.l %a0,%d0 # Decrement 11541da177e4SLinus Torvalds mov.l %d0,EXC_A2(%a6) # Save decr value 11551da177e4SLinus Torvalds mov.l %d0,%a0 11561da177e4SLinus Torvalds 11571da177e4SLinus Torvalds mov.b &0x2,EXC_SAVREG(%a6) # save regno, too 11581da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11591da177e4SLinus Torvalds rts 11601da177e4SLinus Torvalds 11611da177e4SLinus Torvaldsaddr_ind_m_a3: 11621da177e4SLinus Torvalds mov.l EXC_A3(%a6),%d0 # Get current a3 11631da177e4SLinus Torvalds mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11641da177e4SLinus Torvalds sub.l %a0,%d0 # Decrement 11651da177e4SLinus Torvalds mov.l %d0,EXC_A3(%a6) # Save decr value 11661da177e4SLinus Torvalds mov.l %d0,%a0 11671da177e4SLinus Torvalds 11681da177e4SLinus Torvalds mov.b &0x3,EXC_SAVREG(%a6) # save regno, too 11691da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11701da177e4SLinus Torvalds rts 11711da177e4SLinus Torvalds 11721da177e4SLinus Torvaldsaddr_ind_m_a4: 11731da177e4SLinus Torvalds mov.l EXC_A4(%a6),%d0 # Get current a4 11741da177e4SLinus Torvalds mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11751da177e4SLinus Torvalds sub.l %a0,%d0 # Decrement 11761da177e4SLinus Torvalds mov.l %d0,EXC_A4(%a6) # Save decr value 11771da177e4SLinus Torvalds mov.l %d0,%a0 11781da177e4SLinus Torvalds 11791da177e4SLinus Torvalds mov.b &0x4,EXC_SAVREG(%a6) # save regno, too 11801da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11811da177e4SLinus Torvalds rts 11821da177e4SLinus Torvalds 11831da177e4SLinus Torvaldsaddr_ind_m_a5: 11841da177e4SLinus Torvalds mov.l EXC_A5(%a6),%d0 # Get current a5 11851da177e4SLinus Torvalds mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11861da177e4SLinus Torvalds sub.l %a0,%d0 # Decrement 11871da177e4SLinus Torvalds mov.l %d0,EXC_A5(%a6) # Save decr value 11881da177e4SLinus Torvalds mov.l %d0,%a0 11891da177e4SLinus Torvalds 11901da177e4SLinus Torvalds mov.b &0x5,EXC_SAVREG(%a6) # save regno, too 11911da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11921da177e4SLinus Torvalds rts 11931da177e4SLinus Torvalds 11941da177e4SLinus Torvaldsaddr_ind_m_a6: 11951da177e4SLinus Torvalds mov.l EXC_A6(%a6),%d0 # Get current a6 11961da177e4SLinus Torvalds mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11971da177e4SLinus Torvalds sub.l %a0,%d0 # Decrement 11981da177e4SLinus Torvalds mov.l %d0,EXC_A6(%a6) # Save decr value 11991da177e4SLinus Torvalds mov.l %d0,%a0 12001da177e4SLinus Torvalds 12011da177e4SLinus Torvalds mov.b &0x6,EXC_SAVREG(%a6) # save regno, too 12021da177e4SLinus Torvalds mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 12031da177e4SLinus Torvalds rts 12041da177e4SLinus Torvalds 12051da177e4SLinus Torvaldsaddr_ind_m_a7: 12061da177e4SLinus Torvalds mov.b &mda7_flg,SPCOND_FLG(%a6) # set "special case" flag 12071da177e4SLinus Torvalds 12081da177e4SLinus Torvalds mov.l EXC_A7(%a6),%d0 # Get current a7 12091da177e4SLinus Torvalds sub.l %a0,%d0 # Decrement 12101da177e4SLinus Torvalds mov.l %d0,EXC_A7(%a6) # Save decr value 12111da177e4SLinus Torvalds mov.l %d0,%a0 12121da177e4SLinus Torvalds rts 12131da177e4SLinus Torvalds 12141da177e4SLinus Torvalds######################################################## 12151da177e4SLinus Torvalds# Address register indirect w/ displacement: (d16, An) # 12161da177e4SLinus Torvalds######################################################## 12171da177e4SLinus Torvaldsaddr_ind_disp_a0: 12181da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12191da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12201da177e4SLinus Torvalds bsr.l _imem_read_word 12211da177e4SLinus Torvalds 12221da177e4SLinus Torvalds tst.l %d1 # ifetch error? 12231da177e4SLinus Torvalds bne.l isp_iacc # yes 12241da177e4SLinus Torvalds 12251da177e4SLinus Torvalds mov.w %d0,%a0 # sign extend displacement 12261da177e4SLinus Torvalds add.l EXC_A0(%a6),%a0 # a0 + d16 12271da177e4SLinus Torvalds rts 12281da177e4SLinus Torvalds 12291da177e4SLinus Torvaldsaddr_ind_disp_a1: 12301da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12311da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12321da177e4SLinus Torvalds bsr.l _imem_read_word 12331da177e4SLinus Torvalds 12341da177e4SLinus Torvalds tst.l %d1 # ifetch error? 12351da177e4SLinus Torvalds bne.l isp_iacc # yes 12361da177e4SLinus Torvalds 12371da177e4SLinus Torvalds mov.w %d0,%a0 # sign extend displacement 12381da177e4SLinus Torvalds add.l EXC_A1(%a6),%a0 # a1 + d16 12391da177e4SLinus Torvalds rts 12401da177e4SLinus Torvalds 12411da177e4SLinus Torvaldsaddr_ind_disp_a2: 12421da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12431da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12441da177e4SLinus Torvalds bsr.l _imem_read_word 12451da177e4SLinus Torvalds 12461da177e4SLinus Torvalds tst.l %d1 # ifetch error? 12471da177e4SLinus Torvalds bne.l isp_iacc # yes 12481da177e4SLinus Torvalds 12491da177e4SLinus Torvalds mov.w %d0,%a0 # sign extend displacement 12501da177e4SLinus Torvalds add.l EXC_A2(%a6),%a0 # a2 + d16 12511da177e4SLinus Torvalds rts 12521da177e4SLinus Torvalds 12531da177e4SLinus Torvaldsaddr_ind_disp_a3: 12541da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12551da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12561da177e4SLinus Torvalds bsr.l _imem_read_word 12571da177e4SLinus Torvalds 12581da177e4SLinus Torvalds tst.l %d1 # ifetch error? 12591da177e4SLinus Torvalds bne.l isp_iacc # yes 12601da177e4SLinus Torvalds 12611da177e4SLinus Torvalds mov.w %d0,%a0 # sign extend displacement 12621da177e4SLinus Torvalds add.l EXC_A3(%a6),%a0 # a3 + d16 12631da177e4SLinus Torvalds rts 12641da177e4SLinus Torvalds 12651da177e4SLinus Torvaldsaddr_ind_disp_a4: 12661da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12671da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12681da177e4SLinus Torvalds bsr.l _imem_read_word 12691da177e4SLinus Torvalds 12701da177e4SLinus Torvalds tst.l %d1 # ifetch error? 12711da177e4SLinus Torvalds bne.l isp_iacc # yes 12721da177e4SLinus Torvalds 12731da177e4SLinus Torvalds mov.w %d0,%a0 # sign extend displacement 12741da177e4SLinus Torvalds add.l EXC_A4(%a6),%a0 # a4 + d16 12751da177e4SLinus Torvalds rts 12761da177e4SLinus Torvalds 12771da177e4SLinus Torvaldsaddr_ind_disp_a5: 12781da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12791da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12801da177e4SLinus Torvalds bsr.l _imem_read_word 12811da177e4SLinus Torvalds 12821da177e4SLinus Torvalds tst.l %d1 # ifetch error? 12831da177e4SLinus Torvalds bne.l isp_iacc # yes 12841da177e4SLinus Torvalds 12851da177e4SLinus Torvalds mov.w %d0,%a0 # sign extend displacement 12861da177e4SLinus Torvalds add.l EXC_A5(%a6),%a0 # a5 + d16 12871da177e4SLinus Torvalds rts 12881da177e4SLinus Torvalds 12891da177e4SLinus Torvaldsaddr_ind_disp_a6: 12901da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12911da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12921da177e4SLinus Torvalds bsr.l _imem_read_word 12931da177e4SLinus Torvalds 12941da177e4SLinus Torvalds tst.l %d1 # ifetch error? 12951da177e4SLinus Torvalds bne.l isp_iacc # yes 12961da177e4SLinus Torvalds 12971da177e4SLinus Torvalds mov.w %d0,%a0 # sign extend displacement 12981da177e4SLinus Torvalds add.l EXC_A6(%a6),%a0 # a6 + d16 12991da177e4SLinus Torvalds rts 13001da177e4SLinus Torvalds 13011da177e4SLinus Torvaldsaddr_ind_disp_a7: 13021da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 13031da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 13041da177e4SLinus Torvalds bsr.l _imem_read_word 13051da177e4SLinus Torvalds 13061da177e4SLinus Torvalds tst.l %d1 # ifetch error? 13071da177e4SLinus Torvalds bne.l isp_iacc # yes 13081da177e4SLinus Torvalds 13091da177e4SLinus Torvalds mov.w %d0,%a0 # sign extend displacement 13101da177e4SLinus Torvalds add.l EXC_A7(%a6),%a0 # a7 + d16 13111da177e4SLinus Torvalds rts 13121da177e4SLinus Torvalds 13131da177e4SLinus Torvalds######################################################################## 13141da177e4SLinus Torvalds# Address register indirect w/ index(8-bit displacement): (dn, An, Xn) # 13151da177e4SLinus Torvalds# " " " w/ " (base displacement): (bd, An, Xn) # 13161da177e4SLinus Torvalds# Memory indirect postindexed: ([bd, An], Xn, od) # 13171da177e4SLinus Torvalds# Memory indirect preindexed: ([bd, An, Xn], od) # 13181da177e4SLinus Torvalds######################################################################## 13191da177e4SLinus Torvalds_addr_ind_ext: 13201da177e4SLinus Torvalds mov.l %d1,-(%sp) 13211da177e4SLinus Torvalds 13221da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 13231da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 13241da177e4SLinus Torvalds bsr.l _imem_read_word # fetch extword in d0 13251da177e4SLinus Torvalds 13261da177e4SLinus Torvalds tst.l %d1 # ifetch error? 13271da177e4SLinus Torvalds bne.l isp_iacc # yes 13281da177e4SLinus Torvalds 13291da177e4SLinus Torvalds mov.l (%sp)+,%d1 13301da177e4SLinus Torvalds 13311da177e4SLinus Torvalds mov.l (EXC_AREGS,%a6,%d1.w*4),%a0 # put base in a0 13321da177e4SLinus Torvalds 13331da177e4SLinus Torvalds btst &0x8,%d0 13341da177e4SLinus Torvalds beq.b addr_ind_index_8bit # for ext word or not? 13351da177e4SLinus Torvalds 13361da177e4SLinus Torvalds movm.l &0x3c00,-(%sp) # save d2-d5 13371da177e4SLinus Torvalds 13381da177e4SLinus Torvalds mov.l %d0,%d5 # put extword in d5 13391da177e4SLinus Torvalds mov.l %a0,%d3 # put base in d3 13401da177e4SLinus Torvalds 13411da177e4SLinus Torvalds bra.l calc_mem_ind # calc memory indirect 13421da177e4SLinus Torvalds 13431da177e4SLinus Torvaldsaddr_ind_index_8bit: 13441da177e4SLinus Torvalds mov.l %d2,-(%sp) # save old d2 13451da177e4SLinus Torvalds 13461da177e4SLinus Torvalds mov.l %d0,%d1 13471da177e4SLinus Torvalds rol.w &0x4,%d1 13481da177e4SLinus Torvalds andi.w &0xf,%d1 # extract index regno 13491da177e4SLinus Torvalds 13501da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value 13511da177e4SLinus Torvalds 13521da177e4SLinus Torvalds btst &0xb,%d0 # is it word or long? 13531da177e4SLinus Torvalds bne.b aii8_long 13541da177e4SLinus Torvalds ext.l %d1 # sign extend word index 13551da177e4SLinus Torvaldsaii8_long: 13561da177e4SLinus Torvalds mov.l %d0,%d2 13571da177e4SLinus Torvalds rol.w &0x7,%d2 13581da177e4SLinus Torvalds andi.l &0x3,%d2 # extract scale value 13591da177e4SLinus Torvalds 13601da177e4SLinus Torvalds lsl.l %d2,%d1 # shift index by scale 13611da177e4SLinus Torvalds 13621da177e4SLinus Torvalds extb.l %d0 # sign extend displacement 13631da177e4SLinus Torvalds add.l %d1,%d0 # index + disp 13641da177e4SLinus Torvalds add.l %d0,%a0 # An + (index + disp) 13651da177e4SLinus Torvalds 13661da177e4SLinus Torvalds mov.l (%sp)+,%d2 # restore old d2 13671da177e4SLinus Torvalds rts 13681da177e4SLinus Torvalds 13691da177e4SLinus Torvalds###################### 13701da177e4SLinus Torvalds# Immediate: #<data> # 13711da177e4SLinus Torvalds######################################################################### 13721da177e4SLinus Torvalds# word, long: <ea> of the data is the current extension word # 13731da177e4SLinus Torvalds# pointer value. new extension word pointer is simply the old # 13741da177e4SLinus Torvalds# plus the number of bytes in the data type(2 or 4). # 13751da177e4SLinus Torvalds######################################################################### 13761da177e4SLinus Torvaldsimmediate: 13771da177e4SLinus Torvalds mov.b &immed_flg,SPCOND_FLG(%a6) # set immediate flag 13781da177e4SLinus Torvalds 13791da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch extension word ptr 13801da177e4SLinus Torvalds rts 13811da177e4SLinus Torvalds 13821da177e4SLinus Torvalds########################### 13831da177e4SLinus Torvalds# Absolute short: (XXX).W # 13841da177e4SLinus Torvalds########################### 13851da177e4SLinus Torvaldsabs_short: 13861da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 13871da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 13881da177e4SLinus Torvalds bsr.l _imem_read_word # fetch short address 13891da177e4SLinus Torvalds 13901da177e4SLinus Torvalds tst.l %d1 # ifetch error? 13911da177e4SLinus Torvalds bne.l isp_iacc # yes 13921da177e4SLinus Torvalds 13931da177e4SLinus Torvalds mov.w %d0,%a0 # return <ea> in a0 13941da177e4SLinus Torvalds rts 13951da177e4SLinus Torvalds 13961da177e4SLinus Torvalds########################## 13971da177e4SLinus Torvalds# Absolute long: (XXX).L # 13981da177e4SLinus Torvalds########################## 13991da177e4SLinus Torvaldsabs_long: 14001da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 14011da177e4SLinus Torvalds addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 14021da177e4SLinus Torvalds bsr.l _imem_read_long # fetch long address 14031da177e4SLinus Torvalds 14041da177e4SLinus Torvalds tst.l %d1 # ifetch error? 14051da177e4SLinus Torvalds bne.l isp_iacc # yes 14061da177e4SLinus Torvalds 14071da177e4SLinus Torvalds mov.l %d0,%a0 # return <ea> in a0 14081da177e4SLinus Torvalds rts 14091da177e4SLinus Torvalds 14101da177e4SLinus Torvalds####################################################### 14111da177e4SLinus Torvalds# Program counter indirect w/ displacement: (d16, PC) # 14121da177e4SLinus Torvalds####################################################### 14131da177e4SLinus Torvaldspc_ind: 14141da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 14151da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 14161da177e4SLinus Torvalds bsr.l _imem_read_word # fetch word displacement 14171da177e4SLinus Torvalds 14181da177e4SLinus Torvalds tst.l %d1 # ifetch error? 14191da177e4SLinus Torvalds bne.l isp_iacc # yes 14201da177e4SLinus Torvalds 14211da177e4SLinus Torvalds mov.w %d0,%a0 # sign extend displacement 14221da177e4SLinus Torvalds 14231da177e4SLinus Torvalds add.l EXC_EXTWPTR(%a6),%a0 # pc + d16 14241da177e4SLinus Torvalds 14251da177e4SLinus Torvalds# _imem_read_word() increased the extwptr by 2. need to adjust here. 14261da177e4SLinus Torvalds subq.l &0x2,%a0 # adjust <ea> 14271da177e4SLinus Torvalds 14281da177e4SLinus Torvalds rts 14291da177e4SLinus Torvalds 14301da177e4SLinus Torvalds########################################################## 14311da177e4SLinus Torvalds# PC indirect w/ index(8-bit displacement): (d8, PC, An) # 14321da177e4SLinus Torvalds# " " w/ " (base displacement): (bd, PC, An) # 14331da177e4SLinus Torvalds# PC memory indirect postindexed: ([bd, PC], Xn, od) # 14341da177e4SLinus Torvalds# PC memory indirect preindexed: ([bd, PC, Xn], od) # 14351da177e4SLinus Torvalds########################################################## 14361da177e4SLinus Torvaldspc_ind_ext: 14371da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 14381da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 14391da177e4SLinus Torvalds bsr.l _imem_read_word # fetch ext word 14401da177e4SLinus Torvalds 14411da177e4SLinus Torvalds tst.l %d1 # ifetch error? 14421da177e4SLinus Torvalds bne.l isp_iacc # yes 14431da177e4SLinus Torvalds 14441da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # put base in a0 14451da177e4SLinus Torvalds subq.l &0x2,%a0 # adjust base 14461da177e4SLinus Torvalds 14471da177e4SLinus Torvalds btst &0x8,%d0 # is disp only 8 bits? 14481da177e4SLinus Torvalds beq.b pc_ind_index_8bit # yes 14491da177e4SLinus Torvalds 14501da177e4SLinus Torvalds# the indexed addressing mode uses a base displacement of size 14511da177e4SLinus Torvalds# word or long 14521da177e4SLinus Torvalds movm.l &0x3c00,-(%sp) # save d2-d5 14531da177e4SLinus Torvalds 14541da177e4SLinus Torvalds mov.l %d0,%d5 # put extword in d5 14551da177e4SLinus Torvalds mov.l %a0,%d3 # put base in d3 14561da177e4SLinus Torvalds 14571da177e4SLinus Torvalds bra.l calc_mem_ind # calc memory indirect 14581da177e4SLinus Torvalds 14591da177e4SLinus Torvaldspc_ind_index_8bit: 14601da177e4SLinus Torvalds mov.l %d2,-(%sp) # create a temp register 14611da177e4SLinus Torvalds 14621da177e4SLinus Torvalds mov.l %d0,%d1 # make extword copy 14631da177e4SLinus Torvalds rol.w &0x4,%d1 # rotate reg num into place 14641da177e4SLinus Torvalds andi.w &0xf,%d1 # extract register number 14651da177e4SLinus Torvalds 14661da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value 14671da177e4SLinus Torvalds 14681da177e4SLinus Torvalds btst &0xb,%d0 # is index word or long? 14691da177e4SLinus Torvalds bne.b pii8_long # long 14701da177e4SLinus Torvalds ext.l %d1 # sign extend word index 14711da177e4SLinus Torvaldspii8_long: 14721da177e4SLinus Torvalds mov.l %d0,%d2 # make extword copy 14731da177e4SLinus Torvalds rol.w &0x7,%d2 # rotate scale value into place 14741da177e4SLinus Torvalds andi.l &0x3,%d2 # extract scale value 14751da177e4SLinus Torvalds 14761da177e4SLinus Torvalds lsl.l %d2,%d1 # shift index by scale 14771da177e4SLinus Torvalds 14781da177e4SLinus Torvalds extb.l %d0 # sign extend displacement 14791da177e4SLinus Torvalds add.l %d1,%d0 # index + disp 14801da177e4SLinus Torvalds add.l %d0,%a0 # An + (index + disp) 14811da177e4SLinus Torvalds 14821da177e4SLinus Torvalds mov.l (%sp)+,%d2 # restore temp register 14831da177e4SLinus Torvalds 14841da177e4SLinus Torvalds rts 14851da177e4SLinus Torvalds 14861da177e4SLinus Torvalds# a5 = exc_extwptr (global to uaeh) 14871da177e4SLinus Torvalds# a4 = exc_opword (global to uaeh) 14881da177e4SLinus Torvalds# a3 = exc_dregs (global to uaeh) 14891da177e4SLinus Torvalds 14901da177e4SLinus Torvalds# d2 = index (internal " " ) 14911da177e4SLinus Torvalds# d3 = base (internal " " ) 14921da177e4SLinus Torvalds# d4 = od (internal " " ) 14931da177e4SLinus Torvalds# d5 = extword (internal " " ) 14941da177e4SLinus Torvaldscalc_mem_ind: 14951da177e4SLinus Torvalds btst &0x6,%d5 # is the index suppressed? 14961da177e4SLinus Torvalds beq.b calc_index 14971da177e4SLinus Torvalds clr.l %d2 # yes, so index = 0 14981da177e4SLinus Torvalds bra.b base_supp_ck 14991da177e4SLinus Torvaldscalc_index: 15001da177e4SLinus Torvalds bfextu %d5{&16:&4},%d2 15011da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d2.w*4),%d2 15021da177e4SLinus Torvalds btst &0xb,%d5 # is index word or long? 15031da177e4SLinus Torvalds bne.b no_ext 15041da177e4SLinus Torvalds ext.l %d2 15051da177e4SLinus Torvaldsno_ext: 15061da177e4SLinus Torvalds bfextu %d5{&21:&2},%d0 15071da177e4SLinus Torvalds lsl.l %d0,%d2 15081da177e4SLinus Torvaldsbase_supp_ck: 15091da177e4SLinus Torvalds btst &0x7,%d5 # is the bd suppressed? 15101da177e4SLinus Torvalds beq.b no_base_sup 15111da177e4SLinus Torvalds clr.l %d3 15121da177e4SLinus Torvaldsno_base_sup: 15131da177e4SLinus Torvalds bfextu %d5{&26:&2},%d0 # get bd size 15141da177e4SLinus Torvalds# beq.l _error # if (size == 0) it's reserved 15151da177e4SLinus Torvalds cmpi.b %d0,&2 15161da177e4SLinus Torvalds blt.b no_bd 15171da177e4SLinus Torvalds beq.b get_word_bd 15181da177e4SLinus Torvalds 15191da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 15201da177e4SLinus Torvalds addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 15211da177e4SLinus Torvalds bsr.l _imem_read_long 15221da177e4SLinus Torvalds 15231da177e4SLinus Torvalds tst.l %d1 # ifetch error? 15241da177e4SLinus Torvalds bne.l isp_iacc # yes 15251da177e4SLinus Torvalds 15261da177e4SLinus Torvalds bra.b chk_ind 15271da177e4SLinus Torvaldsget_word_bd: 15281da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 15291da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 15301da177e4SLinus Torvalds bsr.l _imem_read_word 15311da177e4SLinus Torvalds 15321da177e4SLinus Torvalds tst.l %d1 # ifetch error? 15331da177e4SLinus Torvalds bne.l isp_iacc # yes 15341da177e4SLinus Torvalds 15351da177e4SLinus Torvalds ext.l %d0 # sign extend bd 15361da177e4SLinus Torvalds 15371da177e4SLinus Torvaldschk_ind: 15381da177e4SLinus Torvalds add.l %d0,%d3 # base += bd 15391da177e4SLinus Torvaldsno_bd: 15401da177e4SLinus Torvalds bfextu %d5{&30:&2},%d0 # is od suppressed? 15411da177e4SLinus Torvalds beq.w aii_bd 15421da177e4SLinus Torvalds cmpi.b %d0,&0x2 15431da177e4SLinus Torvalds blt.b null_od 15441da177e4SLinus Torvalds beq.b word_od 15451da177e4SLinus Torvalds 15461da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 15471da177e4SLinus Torvalds addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 15481da177e4SLinus Torvalds bsr.l _imem_read_long 15491da177e4SLinus Torvalds 15501da177e4SLinus Torvalds tst.l %d1 # ifetch error? 15511da177e4SLinus Torvalds bne.l isp_iacc # yes 15521da177e4SLinus Torvalds 15531da177e4SLinus Torvalds bra.b add_them 15541da177e4SLinus Torvalds 15551da177e4SLinus Torvaldsword_od: 15561da177e4SLinus Torvalds mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 15571da177e4SLinus Torvalds addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 15581da177e4SLinus Torvalds bsr.l _imem_read_word 15591da177e4SLinus Torvalds 15601da177e4SLinus Torvalds tst.l %d1 # ifetch error? 15611da177e4SLinus Torvalds bne.l isp_iacc # yes 15621da177e4SLinus Torvalds 15631da177e4SLinus Torvalds ext.l %d0 # sign extend od 15641da177e4SLinus Torvalds bra.b add_them 15651da177e4SLinus Torvalds 15661da177e4SLinus Torvaldsnull_od: 15671da177e4SLinus Torvalds clr.l %d0 15681da177e4SLinus Torvaldsadd_them: 15691da177e4SLinus Torvalds mov.l %d0,%d4 15701da177e4SLinus Torvalds btst &0x2,%d5 # pre or post indexing? 15711da177e4SLinus Torvalds beq.b pre_indexed 15721da177e4SLinus Torvalds 15731da177e4SLinus Torvalds mov.l %d3,%a0 15741da177e4SLinus Torvalds bsr.l _dmem_read_long 15751da177e4SLinus Torvalds 15761da177e4SLinus Torvalds tst.l %d1 # dfetch error? 15771da177e4SLinus Torvalds bne.b calc_ea_err # yes 15781da177e4SLinus Torvalds 15791da177e4SLinus Torvalds add.l %d2,%d0 # <ea> += index 15801da177e4SLinus Torvalds add.l %d4,%d0 # <ea> += od 15811da177e4SLinus Torvalds bra.b done_ea 15821da177e4SLinus Torvalds 15831da177e4SLinus Torvaldspre_indexed: 15841da177e4SLinus Torvalds add.l %d2,%d3 # preindexing 15851da177e4SLinus Torvalds mov.l %d3,%a0 15861da177e4SLinus Torvalds bsr.l _dmem_read_long 15871da177e4SLinus Torvalds 15881da177e4SLinus Torvalds tst.l %d1 # ifetch error? 15891da177e4SLinus Torvalds bne.b calc_ea_err # yes 15901da177e4SLinus Torvalds 15911da177e4SLinus Torvalds add.l %d4,%d0 # ea += od 15921da177e4SLinus Torvalds bra.b done_ea 15931da177e4SLinus Torvalds 15941da177e4SLinus Torvaldsaii_bd: 15951da177e4SLinus Torvalds add.l %d2,%d3 # ea = (base + bd) + index 15961da177e4SLinus Torvalds mov.l %d3,%d0 15971da177e4SLinus Torvaldsdone_ea: 15981da177e4SLinus Torvalds mov.l %d0,%a0 15991da177e4SLinus Torvalds 16001da177e4SLinus Torvalds movm.l (%sp)+,&0x003c # restore d2-d5 16011da177e4SLinus Torvalds rts 16021da177e4SLinus Torvalds 16031da177e4SLinus Torvalds# if dmem_read_long() returns a fail message in d1, the package 16041da177e4SLinus Torvalds# must create an access error frame. here, we pass a skeleton fslw 16051da177e4SLinus Torvalds# and the failing address to the routine that creates the new frame. 16061da177e4SLinus Torvalds# FSLW: 16071da177e4SLinus Torvalds# read = true 16081da177e4SLinus Torvalds# size = longword 16091da177e4SLinus Torvalds# TM = data 16101da177e4SLinus Torvalds# software emulation error = true 16111da177e4SLinus Torvaldscalc_ea_err: 16121da177e4SLinus Torvalds mov.l %d3,%a0 # pass failing address 16131da177e4SLinus Torvalds mov.l &0x01010001,%d0 # pass fslw 16141da177e4SLinus Torvalds bra.l isp_dacc 16151da177e4SLinus Torvalds 16161da177e4SLinus Torvalds######################################################################### 16171da177e4SLinus Torvalds# XDEF **************************************************************** # 16181da177e4SLinus Torvalds# _moveperipheral(): routine to emulate movep instruction # 16191da177e4SLinus Torvalds# # 16201da177e4SLinus Torvalds# XREF **************************************************************** # 16211da177e4SLinus Torvalds# _dmem_read_byte() - read byte from memory # 16221da177e4SLinus Torvalds# _dmem_write_byte() - write byte to memory # 16231da177e4SLinus Torvalds# isp_dacc() - handle data access error exception # 16241da177e4SLinus Torvalds# # 16251da177e4SLinus Torvalds# INPUT *************************************************************** # 16261da177e4SLinus Torvalds# none # 16271da177e4SLinus Torvalds# # 16281da177e4SLinus Torvalds# OUTPUT ************************************************************** # 16291da177e4SLinus Torvalds# If exiting through isp_dacc... # 16301da177e4SLinus Torvalds# a0 = failing address # 16311da177e4SLinus Torvalds# d0 = FSLW # 16321da177e4SLinus Torvalds# else # 16331da177e4SLinus Torvalds# none # 16341da177e4SLinus Torvalds# # 16351da177e4SLinus Torvalds# ALGORITHM *********************************************************** # 16361da177e4SLinus Torvalds# Decode the movep instruction words stored at EXC_OPWORD and # 16371da177e4SLinus Torvalds# either read or write the required bytes from/to memory. Use the # 16381da177e4SLinus Torvalds# _dmem_{read,write}_byte() routines. If one of the memory routines # 16391da177e4SLinus Torvalds# returns a failing value, we must pass the failing address and a FSLW # 16401da177e4SLinus Torvalds# to the _isp_dacc() routine. # 16411da177e4SLinus Torvalds# Since this instruction is used to access peripherals, make sure # 16421da177e4SLinus Torvalds# to only access the required bytes. # 16431da177e4SLinus Torvalds# # 16441da177e4SLinus Torvalds######################################################################### 16451da177e4SLinus Torvalds 16461da177e4SLinus Torvalds########################### 16471da177e4SLinus Torvalds# movep.(w,l) Dx,(d,Ay) # 16481da177e4SLinus Torvalds# movep.(w,l) (d,Ay),Dx # 16491da177e4SLinus Torvalds########################### 16501da177e4SLinus Torvalds global _moveperipheral 16511da177e4SLinus Torvalds_moveperipheral: 16521da177e4SLinus Torvalds mov.w EXC_OPWORD(%a6),%d1 # fetch the opcode word 16531da177e4SLinus Torvalds 16541da177e4SLinus Torvalds mov.b %d1,%d0 16551da177e4SLinus Torvalds and.w &0x7,%d0 # extract Ay from opcode word 16561da177e4SLinus Torvalds 16571da177e4SLinus Torvalds mov.l (EXC_AREGS,%a6,%d0.w*4),%a0 # fetch ay 16581da177e4SLinus Torvalds 16591da177e4SLinus Torvalds add.w EXC_EXTWORD(%a6),%a0 # add: an + sgn_ext(disp) 16601da177e4SLinus Torvalds 16611da177e4SLinus Torvalds btst &0x7,%d1 # (reg 2 mem) or (mem 2 reg) 16621da177e4SLinus Torvalds beq.w mem2reg 16631da177e4SLinus Torvalds 16641da177e4SLinus Torvalds# reg2mem: fetch dx, then write it to memory 16651da177e4SLinus Torvaldsreg2mem: 16661da177e4SLinus Torvalds mov.w %d1,%d0 16671da177e4SLinus Torvalds rol.w &0x7,%d0 16681da177e4SLinus Torvalds and.w &0x7,%d0 # extract Dx from opcode word 16691da177e4SLinus Torvalds 16701da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d0.w*4), %d0 # fetch dx 16711da177e4SLinus Torvalds 16721da177e4SLinus Torvalds btst &0x6,%d1 # word or long operation? 16731da177e4SLinus Torvalds beq.b r2mwtrans 16741da177e4SLinus Torvalds 16751da177e4SLinus Torvalds# a0 = dst addr 16761da177e4SLinus Torvalds# d0 = Dx 16771da177e4SLinus Torvaldsr2mltrans: 16781da177e4SLinus Torvalds mov.l %d0,%d2 # store data 16791da177e4SLinus Torvalds mov.l %a0,%a2 # store addr 16801da177e4SLinus Torvalds rol.l &0x8,%d2 16811da177e4SLinus Torvalds mov.l %d2,%d0 16821da177e4SLinus Torvalds 16831da177e4SLinus Torvalds bsr.l _dmem_write_byte # os : write hi 16841da177e4SLinus Torvalds 16851da177e4SLinus Torvalds tst.l %d1 # dfetch error? 16861da177e4SLinus Torvalds bne.w movp_write_err # yes 16871da177e4SLinus Torvalds 16881da177e4SLinus Torvalds add.w &0x2,%a2 # incr addr 16891da177e4SLinus Torvalds mov.l %a2,%a0 16901da177e4SLinus Torvalds rol.l &0x8,%d2 16911da177e4SLinus Torvalds mov.l %d2,%d0 16921da177e4SLinus Torvalds 16931da177e4SLinus Torvalds bsr.l _dmem_write_byte # os : write lo 16941da177e4SLinus Torvalds 16951da177e4SLinus Torvalds tst.l %d1 # dfetch error? 16961da177e4SLinus Torvalds bne.w movp_write_err # yes 16971da177e4SLinus Torvalds 16981da177e4SLinus Torvalds add.w &0x2,%a2 # incr addr 16991da177e4SLinus Torvalds mov.l %a2,%a0 17001da177e4SLinus Torvalds rol.l &0x8,%d2 17011da177e4SLinus Torvalds mov.l %d2,%d0 17021da177e4SLinus Torvalds 17031da177e4SLinus Torvalds bsr.l _dmem_write_byte # os : write lo 17041da177e4SLinus Torvalds 17051da177e4SLinus Torvalds tst.l %d1 # dfetch error? 17061da177e4SLinus Torvalds bne.w movp_write_err # yes 17071da177e4SLinus Torvalds 17081da177e4SLinus Torvalds add.w &0x2,%a2 # incr addr 17091da177e4SLinus Torvalds mov.l %a2,%a0 17101da177e4SLinus Torvalds rol.l &0x8,%d2 17111da177e4SLinus Torvalds mov.l %d2,%d0 17121da177e4SLinus Torvalds 17131da177e4SLinus Torvalds bsr.l _dmem_write_byte # os : write lo 17141da177e4SLinus Torvalds 17151da177e4SLinus Torvalds tst.l %d1 # dfetch error? 17161da177e4SLinus Torvalds bne.w movp_write_err # yes 17171da177e4SLinus Torvalds 17181da177e4SLinus Torvalds rts 17191da177e4SLinus Torvalds 17201da177e4SLinus Torvalds# a0 = dst addr 17211da177e4SLinus Torvalds# d0 = Dx 17221da177e4SLinus Torvaldsr2mwtrans: 17231da177e4SLinus Torvalds mov.l %d0,%d2 # store data 17241da177e4SLinus Torvalds mov.l %a0,%a2 # store addr 17251da177e4SLinus Torvalds lsr.w &0x8,%d0 17261da177e4SLinus Torvalds 17271da177e4SLinus Torvalds bsr.l _dmem_write_byte # os : write hi 17281da177e4SLinus Torvalds 17291da177e4SLinus Torvalds tst.l %d1 # dfetch error? 17301da177e4SLinus Torvalds bne.w movp_write_err # yes 17311da177e4SLinus Torvalds 17321da177e4SLinus Torvalds add.w &0x2,%a2 17331da177e4SLinus Torvalds mov.l %a2,%a0 17341da177e4SLinus Torvalds mov.l %d2,%d0 17351da177e4SLinus Torvalds 17361da177e4SLinus Torvalds bsr.l _dmem_write_byte # os : write lo 17371da177e4SLinus Torvalds 17381da177e4SLinus Torvalds tst.l %d1 # dfetch error? 17391da177e4SLinus Torvalds bne.w movp_write_err # yes 17401da177e4SLinus Torvalds 17411da177e4SLinus Torvalds rts 17421da177e4SLinus Torvalds 17431da177e4SLinus Torvalds# mem2reg: read bytes from memory. 17441da177e4SLinus Torvalds# determines the dest register, and then writes the bytes into it. 17451da177e4SLinus Torvaldsmem2reg: 17461da177e4SLinus Torvalds btst &0x6,%d1 # word or long operation? 17471da177e4SLinus Torvalds beq.b m2rwtrans 17481da177e4SLinus Torvalds 17491da177e4SLinus Torvalds# a0 = dst addr 17501da177e4SLinus Torvaldsm2rltrans: 17511da177e4SLinus Torvalds mov.l %a0,%a2 # store addr 17521da177e4SLinus Torvalds 17531da177e4SLinus Torvalds bsr.l _dmem_read_byte # read first byte 17541da177e4SLinus Torvalds 17551da177e4SLinus Torvalds tst.l %d1 # dfetch error? 17561da177e4SLinus Torvalds bne.w movp_read_err # yes 17571da177e4SLinus Torvalds 17581da177e4SLinus Torvalds mov.l %d0,%d2 17591da177e4SLinus Torvalds 17601da177e4SLinus Torvalds add.w &0x2,%a2 # incr addr by 2 bytes 17611da177e4SLinus Torvalds mov.l %a2,%a0 17621da177e4SLinus Torvalds 17631da177e4SLinus Torvalds bsr.l _dmem_read_byte # read second byte 17641da177e4SLinus Torvalds 17651da177e4SLinus Torvalds tst.l %d1 # dfetch error? 17661da177e4SLinus Torvalds bne.w movp_read_err # yes 17671da177e4SLinus Torvalds 17681da177e4SLinus Torvalds lsl.w &0x8,%d2 17691da177e4SLinus Torvalds mov.b %d0,%d2 # append bytes 17701da177e4SLinus Torvalds 17711da177e4SLinus Torvalds add.w &0x2,%a2 # incr addr by 2 bytes 17721da177e4SLinus Torvalds mov.l %a2,%a0 17731da177e4SLinus Torvalds 17741da177e4SLinus Torvalds bsr.l _dmem_read_byte # read second byte 17751da177e4SLinus Torvalds 17761da177e4SLinus Torvalds tst.l %d1 # dfetch error? 17771da177e4SLinus Torvalds bne.w movp_read_err # yes 17781da177e4SLinus Torvalds 17791da177e4SLinus Torvalds lsl.l &0x8,%d2 17801da177e4SLinus Torvalds mov.b %d0,%d2 # append bytes 17811da177e4SLinus Torvalds 17821da177e4SLinus Torvalds add.w &0x2,%a2 # incr addr by 2 bytes 17831da177e4SLinus Torvalds mov.l %a2,%a0 17841da177e4SLinus Torvalds 17851da177e4SLinus Torvalds bsr.l _dmem_read_byte # read second byte 17861da177e4SLinus Torvalds 17871da177e4SLinus Torvalds tst.l %d1 # dfetch error? 17881da177e4SLinus Torvalds bne.w movp_read_err # yes 17891da177e4SLinus Torvalds 17901da177e4SLinus Torvalds lsl.l &0x8,%d2 17911da177e4SLinus Torvalds mov.b %d0,%d2 # append bytes 17921da177e4SLinus Torvalds 17931da177e4SLinus Torvalds mov.b EXC_OPWORD(%a6),%d1 17941da177e4SLinus Torvalds lsr.b &0x1,%d1 17951da177e4SLinus Torvalds and.w &0x7,%d1 # extract Dx from opcode word 17961da177e4SLinus Torvalds 17971da177e4SLinus Torvalds mov.l %d2,(EXC_DREGS,%a6,%d1.w*4) # store dx 17981da177e4SLinus Torvalds 17991da177e4SLinus Torvalds rts 18001da177e4SLinus Torvalds 18011da177e4SLinus Torvalds# a0 = dst addr 18021da177e4SLinus Torvaldsm2rwtrans: 18031da177e4SLinus Torvalds mov.l %a0,%a2 # store addr 18041da177e4SLinus Torvalds 18051da177e4SLinus Torvalds bsr.l _dmem_read_byte # read first byte 18061da177e4SLinus Torvalds 18071da177e4SLinus Torvalds tst.l %d1 # dfetch error? 18081da177e4SLinus Torvalds bne.w movp_read_err # yes 18091da177e4SLinus Torvalds 18101da177e4SLinus Torvalds mov.l %d0,%d2 18111da177e4SLinus Torvalds 18121da177e4SLinus Torvalds add.w &0x2,%a2 # incr addr by 2 bytes 18131da177e4SLinus Torvalds mov.l %a2,%a0 18141da177e4SLinus Torvalds 18151da177e4SLinus Torvalds bsr.l _dmem_read_byte # read second byte 18161da177e4SLinus Torvalds 18171da177e4SLinus Torvalds tst.l %d1 # dfetch error? 18181da177e4SLinus Torvalds bne.w movp_read_err # yes 18191da177e4SLinus Torvalds 18201da177e4SLinus Torvalds lsl.w &0x8,%d2 18211da177e4SLinus Torvalds mov.b %d0,%d2 # append bytes 18221da177e4SLinus Torvalds 18231da177e4SLinus Torvalds mov.b EXC_OPWORD(%a6),%d1 18241da177e4SLinus Torvalds lsr.b &0x1,%d1 18251da177e4SLinus Torvalds and.w &0x7,%d1 # extract Dx from opcode word 18261da177e4SLinus Torvalds 18271da177e4SLinus Torvalds mov.w %d2,(EXC_DREGS+2,%a6,%d1.w*4) # store dx 18281da177e4SLinus Torvalds 18291da177e4SLinus Torvalds rts 18301da177e4SLinus Torvalds 18311da177e4SLinus Torvalds# if dmem_{read,write}_byte() returns a fail message in d1, the package 18321da177e4SLinus Torvalds# must create an access error frame. here, we pass a skeleton fslw 18331da177e4SLinus Torvalds# and the failing address to the routine that creates the new frame. 18341da177e4SLinus Torvalds# FSLW: 18351da177e4SLinus Torvalds# write = true 18361da177e4SLinus Torvalds# size = byte 18371da177e4SLinus Torvalds# TM = data 18381da177e4SLinus Torvalds# software emulation error = true 18391da177e4SLinus Torvaldsmovp_write_err: 18401da177e4SLinus Torvalds mov.l %a2,%a0 # pass failing address 18411da177e4SLinus Torvalds mov.l &0x00a10001,%d0 # pass fslw 18421da177e4SLinus Torvalds bra.l isp_dacc 18431da177e4SLinus Torvalds 18441da177e4SLinus Torvalds# FSLW: 18451da177e4SLinus Torvalds# read = true 18461da177e4SLinus Torvalds# size = byte 18471da177e4SLinus Torvalds# TM = data 18481da177e4SLinus Torvalds# software emulation error = true 18491da177e4SLinus Torvaldsmovp_read_err: 18501da177e4SLinus Torvalds mov.l %a2,%a0 # pass failing address 18511da177e4SLinus Torvalds mov.l &0x01210001,%d0 # pass fslw 18521da177e4SLinus Torvalds bra.l isp_dacc 18531da177e4SLinus Torvalds 18541da177e4SLinus Torvalds######################################################################### 18551da177e4SLinus Torvalds# XDEF **************************************************************** # 18561da177e4SLinus Torvalds# _chk2_cmp2(): routine to emulate chk2/cmp2 instructions # 18571da177e4SLinus Torvalds# # 18581da177e4SLinus Torvalds# XREF **************************************************************** # 18591da177e4SLinus Torvalds# _calc_ea(): calculate effective address # 18601da177e4SLinus Torvalds# _dmem_read_long(): read operands # 18611da177e4SLinus Torvalds# _dmem_read_word(): read operands # 18621da177e4SLinus Torvalds# isp_dacc(): handle data access error exception # 18631da177e4SLinus Torvalds# # 18641da177e4SLinus Torvalds# INPUT *************************************************************** # 18651da177e4SLinus Torvalds# none # 18661da177e4SLinus Torvalds# # 18671da177e4SLinus Torvalds# OUTPUT ************************************************************** # 18681da177e4SLinus Torvalds# If exiting through isp_dacc... # 18691da177e4SLinus Torvalds# a0 = failing address # 18701da177e4SLinus Torvalds# d0 = FSLW # 18711da177e4SLinus Torvalds# else # 18721da177e4SLinus Torvalds# none # 18731da177e4SLinus Torvalds# # 18741da177e4SLinus Torvalds# ALGORITHM *********************************************************** # 18751da177e4SLinus Torvalds# First, calculate the effective address, then fetch the byte, # 18761da177e4SLinus Torvalds# word, or longword sized operands. Then, in the interest of # 18771da177e4SLinus Torvalds# simplicity, all operands are converted to longword size whether the # 18781da177e4SLinus Torvalds# operation is byte, word, or long. The bounds are sign extended # 1879*ad61dd30SStephen Boyd# accordingly. If Rn is a data register, Rn is also sign extended. If # 18801da177e4SLinus Torvalds# Rn is an address register, it need not be sign extended since the # 18811da177e4SLinus Torvalds# full register is always used. # 18821da177e4SLinus Torvalds# The comparisons are made and the condition codes calculated. # 18831da177e4SLinus Torvalds# If the instruction is chk2 and the Rn value is out-of-bounds, set # 18841da177e4SLinus Torvalds# the ichk_flg in SPCOND_FLG. # 18851da177e4SLinus Torvalds# If the memory fetch returns a failing value, pass the failing # 18861da177e4SLinus Torvalds# address and FSLW to the isp_dacc() routine. # 18871da177e4SLinus Torvalds# # 18881da177e4SLinus Torvalds######################################################################### 18891da177e4SLinus Torvalds 18901da177e4SLinus Torvalds global _chk2_cmp2 18911da177e4SLinus Torvalds_chk2_cmp2: 18921da177e4SLinus Torvalds 18931da177e4SLinus Torvalds# passing size parameter doesn't matter since chk2 & cmp2 can't do 18941da177e4SLinus Torvalds# either predecrement, postincrement, or immediate. 18951da177e4SLinus Torvalds bsr.l _calc_ea # calculate <ea> 18961da177e4SLinus Torvalds 18971da177e4SLinus Torvalds mov.b EXC_EXTWORD(%a6), %d0 # fetch hi extension word 18981da177e4SLinus Torvalds rol.b &0x4, %d0 # rotate reg bits into lo 18991da177e4SLinus Torvalds and.w &0xf, %d0 # extract reg bits 19001da177e4SLinus Torvalds 19011da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d0.w*4), %d2 # get regval 19021da177e4SLinus Torvalds 19031da177e4SLinus Torvalds cmpi.b EXC_OPWORD(%a6), &0x2 # what size is operation? 19041da177e4SLinus Torvalds blt.b chk2_cmp2_byte # size == byte 19051da177e4SLinus Torvalds beq.b chk2_cmp2_word # size == word 19061da177e4SLinus Torvalds 19071da177e4SLinus Torvalds# the bounds are longword size. call routine to read the lower 19081da177e4SLinus Torvalds# bound into d0 and the higher bound into d1. 19091da177e4SLinus Torvaldschk2_cmp2_long: 19101da177e4SLinus Torvalds mov.l %a0,%a2 # save copy of <ea> 19111da177e4SLinus Torvalds bsr.l _dmem_read_long # fetch long lower bound 19121da177e4SLinus Torvalds 19131da177e4SLinus Torvalds tst.l %d1 # dfetch error? 19141da177e4SLinus Torvalds bne.w chk2_cmp2_err_l # yes 19151da177e4SLinus Torvalds 19161da177e4SLinus Torvalds mov.l %d0,%d3 # save long lower bound 19171da177e4SLinus Torvalds addq.l &0x4,%a2 19181da177e4SLinus Torvalds mov.l %a2,%a0 # pass <ea> of long upper bound 19191da177e4SLinus Torvalds bsr.l _dmem_read_long # fetch long upper bound 19201da177e4SLinus Torvalds 19211da177e4SLinus Torvalds tst.l %d1 # dfetch error? 19221da177e4SLinus Torvalds bne.w chk2_cmp2_err_l # yes 19231da177e4SLinus Torvalds 19241da177e4SLinus Torvalds mov.l %d0,%d1 # long upper bound in d1 19251da177e4SLinus Torvalds mov.l %d3,%d0 # long lower bound in d0 19261da177e4SLinus Torvalds bra.w chk2_cmp2_compare # go do the compare emulation 19271da177e4SLinus Torvalds 19281da177e4SLinus Torvalds# the bounds are word size. fetch them in one subroutine call by 19291da177e4SLinus Torvalds# reading a longword. sign extend both. if it's a data operation, 19301da177e4SLinus Torvalds# sign extend Rn to long, also. 19311da177e4SLinus Torvaldschk2_cmp2_word: 19321da177e4SLinus Torvalds mov.l %a0,%a2 19331da177e4SLinus Torvalds bsr.l _dmem_read_long # fetch 2 word bounds 19341da177e4SLinus Torvalds 19351da177e4SLinus Torvalds tst.l %d1 # dfetch error? 19361da177e4SLinus Torvalds bne.w chk2_cmp2_err_l # yes 19371da177e4SLinus Torvalds 19381da177e4SLinus Torvalds mov.w %d0, %d1 # place hi in %d1 19391da177e4SLinus Torvalds swap %d0 # place lo in %d0 19401da177e4SLinus Torvalds 19411da177e4SLinus Torvalds ext.l %d0 # sign extend lo bnd 19421da177e4SLinus Torvalds ext.l %d1 # sign extend hi bnd 19431da177e4SLinus Torvalds 19441da177e4SLinus Torvalds btst &0x7, EXC_EXTWORD(%a6) # address compare? 19451da177e4SLinus Torvalds bne.w chk2_cmp2_compare # yes; don't sign extend 19461da177e4SLinus Torvalds 19471da177e4SLinus Torvalds# operation is a data register compare. 19481da177e4SLinus Torvalds# sign extend word to long so we can do simple longword compares. 19491da177e4SLinus Torvalds ext.l %d2 # sign extend data word 19501da177e4SLinus Torvalds bra.w chk2_cmp2_compare # go emulate compare 19511da177e4SLinus Torvalds 19521da177e4SLinus Torvalds# the bounds are byte size. fetch them in one subroutine call by 19531da177e4SLinus Torvalds# reading a word. sign extend both. if it's a data operation, 19541da177e4SLinus Torvalds# sign extend Rn to long, also. 19551da177e4SLinus Torvaldschk2_cmp2_byte: 19561da177e4SLinus Torvalds mov.l %a0,%a2 19571da177e4SLinus Torvalds bsr.l _dmem_read_word # fetch 2 byte bounds 19581da177e4SLinus Torvalds 19591da177e4SLinus Torvalds tst.l %d1 # dfetch error? 19601da177e4SLinus Torvalds bne.w chk2_cmp2_err_w # yes 19611da177e4SLinus Torvalds 19621da177e4SLinus Torvalds mov.b %d0, %d1 # place hi in %d1 19631da177e4SLinus Torvalds lsr.w &0x8, %d0 # place lo in %d0 19641da177e4SLinus Torvalds 19651da177e4SLinus Torvalds extb.l %d0 # sign extend lo bnd 19661da177e4SLinus Torvalds extb.l %d1 # sign extend hi bnd 19671da177e4SLinus Torvalds 19681da177e4SLinus Torvalds btst &0x7, EXC_EXTWORD(%a6) # address compare? 19691da177e4SLinus Torvalds bne.b chk2_cmp2_compare # yes; don't sign extend 19701da177e4SLinus Torvalds 19711da177e4SLinus Torvalds# operation is a data register compare. 19721da177e4SLinus Torvalds# sign extend byte to long so we can do simple longword compares. 19731da177e4SLinus Torvalds extb.l %d2 # sign extend data byte 19741da177e4SLinus Torvalds 19751da177e4SLinus Torvalds# 19761da177e4SLinus Torvalds# To set the ccodes correctly: 19771da177e4SLinus Torvalds# (1) save 'Z' bit from (Rn - lo) 19781da177e4SLinus Torvalds# (2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi)) 19791da177e4SLinus Torvalds# (3) keep 'X', 'N', and 'V' from before instruction 19801da177e4SLinus Torvalds# (4) combine ccodes 19811da177e4SLinus Torvalds# 19821da177e4SLinus Torvaldschk2_cmp2_compare: 19831da177e4SLinus Torvalds sub.l %d0, %d2 # (Rn - lo) 19841da177e4SLinus Torvalds mov.w %cc, %d3 # fetch resulting ccodes 19851da177e4SLinus Torvalds andi.b &0x4, %d3 # keep 'Z' bit 19861da177e4SLinus Torvalds sub.l %d0, %d1 # (hi - lo) 19871da177e4SLinus Torvalds cmp.l %d1,%d2 # ((hi - lo) - (Rn - hi)) 19881da177e4SLinus Torvalds 19891da177e4SLinus Torvalds mov.w %cc, %d4 # fetch resulting ccodes 19901da177e4SLinus Torvalds or.b %d4, %d3 # combine w/ earlier ccodes 19911da177e4SLinus Torvalds andi.b &0x5, %d3 # keep 'Z' and 'N' 19921da177e4SLinus Torvalds 19931da177e4SLinus Torvalds mov.w EXC_CC(%a6), %d4 # fetch old ccodes 19941da177e4SLinus Torvalds andi.b &0x1a, %d4 # keep 'X','N','V' bits 19951da177e4SLinus Torvalds or.b %d3, %d4 # insert new ccodes 19961da177e4SLinus Torvalds mov.w %d4, EXC_CC(%a6) # save new ccodes 19971da177e4SLinus Torvalds 19981da177e4SLinus Torvalds btst &0x3, EXC_EXTWORD(%a6) # separate chk2,cmp2 19991da177e4SLinus Torvalds bne.b chk2_finish # it's a chk2 20001da177e4SLinus Torvalds 20011da177e4SLinus Torvalds rts 20021da177e4SLinus Torvalds 20031da177e4SLinus Torvalds# this code handles the only difference between chk2 and cmp2. chk2 would 20041da177e4SLinus Torvalds# have trapped out if the value was out of bounds. we check this by seeing 20051da177e4SLinus Torvalds# if the 'N' bit was set by the operation. 20061da177e4SLinus Torvaldschk2_finish: 20071da177e4SLinus Torvalds btst &0x0, %d4 # is 'N' bit set? 20081da177e4SLinus Torvalds bne.b chk2_trap # yes;chk2 should trap 20091da177e4SLinus Torvalds rts 20101da177e4SLinus Torvaldschk2_trap: 20111da177e4SLinus Torvalds mov.b &ichk_flg,SPCOND_FLG(%a6) # set "special case" flag 20121da177e4SLinus Torvalds rts 20131da177e4SLinus Torvalds 20141da177e4SLinus Torvalds# if dmem_read_{long,word}() returns a fail message in d1, the package 20151da177e4SLinus Torvalds# must create an access error frame. here, we pass a skeleton fslw 20161da177e4SLinus Torvalds# and the failing address to the routine that creates the new frame. 20171da177e4SLinus Torvalds# FSLW: 20181da177e4SLinus Torvalds# read = true 20191da177e4SLinus Torvalds# size = longword 20201da177e4SLinus Torvalds# TM = data 20211da177e4SLinus Torvalds# software emulation error = true 20221da177e4SLinus Torvaldschk2_cmp2_err_l: 20231da177e4SLinus Torvalds mov.l %a2,%a0 # pass failing address 20241da177e4SLinus Torvalds mov.l &0x01010001,%d0 # pass fslw 20251da177e4SLinus Torvalds bra.l isp_dacc 20261da177e4SLinus Torvalds 20271da177e4SLinus Torvalds# FSLW: 20281da177e4SLinus Torvalds# read = true 20291da177e4SLinus Torvalds# size = word 20301da177e4SLinus Torvalds# TM = data 20311da177e4SLinus Torvalds# software emulation error = true 20321da177e4SLinus Torvaldschk2_cmp2_err_w: 20331da177e4SLinus Torvalds mov.l %a2,%a0 # pass failing address 20341da177e4SLinus Torvalds mov.l &0x01410001,%d0 # pass fslw 20351da177e4SLinus Torvalds bra.l isp_dacc 20361da177e4SLinus Torvalds 20371da177e4SLinus Torvalds######################################################################### 20381da177e4SLinus Torvalds# XDEF **************************************************************** # 20391da177e4SLinus Torvalds# _div64(): routine to emulate div{u,s}.l <ea>,Dr:Dq # 20401da177e4SLinus Torvalds# 64/32->32r:32q # 20411da177e4SLinus Torvalds# # 20421da177e4SLinus Torvalds# XREF **************************************************************** # 20431da177e4SLinus Torvalds# _calc_ea() - calculate effective address # 20441da177e4SLinus Torvalds# isp_iacc() - handle instruction access error exception # 20451da177e4SLinus Torvalds# isp_dacc() - handle data access error exception # 20461da177e4SLinus Torvalds# isp_restore() - restore An on access error w/ -() or ()+ # 20471da177e4SLinus Torvalds# # 20481da177e4SLinus Torvalds# INPUT *************************************************************** # 20491da177e4SLinus Torvalds# none # 20501da177e4SLinus Torvalds# # 20511da177e4SLinus Torvalds# OUTPUT ************************************************************** # 20521da177e4SLinus Torvalds# If exiting through isp_dacc... # 20531da177e4SLinus Torvalds# a0 = failing address # 20541da177e4SLinus Torvalds# d0 = FSLW # 20551da177e4SLinus Torvalds# else # 20561da177e4SLinus Torvalds# none # 20571da177e4SLinus Torvalds# # 20581da177e4SLinus Torvalds# ALGORITHM *********************************************************** # 20591da177e4SLinus Torvalds# First, decode the operand location. If it's in Dn, fetch from # 20601da177e4SLinus Torvalds# the stack. If it's in memory, use _calc_ea() to calculate the # 20611da177e4SLinus Torvalds# effective address. Use _dmem_read_long() to fetch at that address. # 20621da177e4SLinus Torvalds# Unless the operand is immediate data. Then use _imem_read_long(). # 20631da177e4SLinus Torvalds# Send failures to isp_dacc() or isp_iacc() as appropriate. # 20641da177e4SLinus Torvalds# If the operands are signed, make them unsigned and save the # 20651da177e4SLinus Torvalds# sign info for later. Separate out special cases like divide-by-zero # 20661da177e4SLinus Torvalds# or 32-bit divides if possible. Else, use a special math algorithm # 20671da177e4SLinus Torvalds# to calculate the result. # 20681da177e4SLinus Torvalds# Restore sign info if signed instruction. Set the condition # 20691da177e4SLinus Torvalds# codes. Set idbyz_flg in SPCOND_FLG if divisor was zero. Store the # 20701da177e4SLinus Torvalds# quotient and remainder in the appropriate data registers on the stack.# 20711da177e4SLinus Torvalds# # 20721da177e4SLinus Torvalds######################################################################### 20731da177e4SLinus Torvalds 20741da177e4SLinus Torvaldsset NDIVISOR, EXC_TEMP+0x0 20751da177e4SLinus Torvaldsset NDIVIDEND, EXC_TEMP+0x1 20761da177e4SLinus Torvaldsset NDRSAVE, EXC_TEMP+0x2 20771da177e4SLinus Torvaldsset NDQSAVE, EXC_TEMP+0x4 20781da177e4SLinus Torvaldsset DDSECOND, EXC_TEMP+0x6 20791da177e4SLinus Torvaldsset DDQUOTIENT, EXC_TEMP+0x8 20801da177e4SLinus Torvaldsset DDNORMAL, EXC_TEMP+0xc 20811da177e4SLinus Torvalds 20821da177e4SLinus Torvalds global _div64 20831da177e4SLinus Torvalds############# 20841da177e4SLinus Torvalds# div(u,s)l # 20851da177e4SLinus Torvalds############# 20861da177e4SLinus Torvalds_div64: 20871da177e4SLinus Torvalds mov.b EXC_OPWORD+1(%a6), %d0 20881da177e4SLinus Torvalds andi.b &0x38, %d0 # extract src mode 20891da177e4SLinus Torvalds 20901da177e4SLinus Torvalds bne.w dcontrolmodel_s # %dn dest or control mode? 20911da177e4SLinus Torvalds 20921da177e4SLinus Torvalds mov.b EXC_OPWORD+1(%a6), %d0 # extract Dn from opcode 20931da177e4SLinus Torvalds andi.w &0x7, %d0 20941da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d0.w*4), %d7 # fetch divisor from register 20951da177e4SLinus Torvalds 20961da177e4SLinus Torvaldsdgotsrcl: 20971da177e4SLinus Torvalds beq.w div64eq0 # divisor is = 0!!! 20981da177e4SLinus Torvalds 20991da177e4SLinus Torvalds mov.b EXC_EXTWORD+1(%a6), %d0 # extract Dr from extword 21001da177e4SLinus Torvalds mov.b EXC_EXTWORD(%a6), %d1 # extract Dq from extword 21011da177e4SLinus Torvalds and.w &0x7, %d0 21021da177e4SLinus Torvalds lsr.b &0x4, %d1 21031da177e4SLinus Torvalds and.w &0x7, %d1 21041da177e4SLinus Torvalds mov.w %d0, NDRSAVE(%a6) # save Dr for later 21051da177e4SLinus Torvalds mov.w %d1, NDQSAVE(%a6) # save Dq for later 21061da177e4SLinus Torvalds 21071da177e4SLinus Torvalds# fetch %dr and %dq directly off stack since all regs are saved there 21081da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d0.w*4), %d5 # get dividend hi 21091da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d1.w*4), %d6 # get dividend lo 21101da177e4SLinus Torvalds 21111da177e4SLinus Torvalds# separate signed and unsigned divide 21121da177e4SLinus Torvalds btst &0x3, EXC_EXTWORD(%a6) # signed or unsigned? 21131da177e4SLinus Torvalds beq.b dspecialcases # use positive divide 21141da177e4SLinus Torvalds 21151da177e4SLinus Torvalds# save the sign of the divisor 21161da177e4SLinus Torvalds# make divisor unsigned if it's negative 21171da177e4SLinus Torvalds tst.l %d7 # chk sign of divisor 21181da177e4SLinus Torvalds slt NDIVISOR(%a6) # save sign of divisor 21191da177e4SLinus Torvalds bpl.b dsgndividend 21201da177e4SLinus Torvalds neg.l %d7 # complement negative divisor 21211da177e4SLinus Torvalds 21221da177e4SLinus Torvalds# save the sign of the dividend 21231da177e4SLinus Torvalds# make dividend unsigned if it's negative 21241da177e4SLinus Torvaldsdsgndividend: 21251da177e4SLinus Torvalds tst.l %d5 # chk sign of hi(dividend) 21261da177e4SLinus Torvalds slt NDIVIDEND(%a6) # save sign of dividend 21271da177e4SLinus Torvalds bpl.b dspecialcases 21281da177e4SLinus Torvalds 21291da177e4SLinus Torvalds mov.w &0x0, %cc # clear 'X' cc bit 21301da177e4SLinus Torvalds negx.l %d6 # complement signed dividend 21311da177e4SLinus Torvalds negx.l %d5 21321da177e4SLinus Torvalds 21331da177e4SLinus Torvalds# extract some special cases: 21341da177e4SLinus Torvalds# - is (dividend == 0) ? 21351da177e4SLinus Torvalds# - is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div) 21361da177e4SLinus Torvaldsdspecialcases: 21371da177e4SLinus Torvalds tst.l %d5 # is (hi(dividend) == 0) 21381da177e4SLinus Torvalds bne.b dnormaldivide # no, so try it the long way 21391da177e4SLinus Torvalds 21401da177e4SLinus Torvalds tst.l %d6 # is (lo(dividend) == 0), too 21411da177e4SLinus Torvalds beq.w ddone # yes, so (dividend == 0) 21421da177e4SLinus Torvalds 21431da177e4SLinus Torvalds cmp.l %d7,%d6 # is (divisor <= lo(dividend)) 21441da177e4SLinus Torvalds bls.b d32bitdivide # yes, so use 32 bit divide 21451da177e4SLinus Torvalds 21461da177e4SLinus Torvalds exg %d5,%d6 # q = 0, r = dividend 21471da177e4SLinus Torvalds bra.w divfinish # can't divide, we're done. 21481da177e4SLinus Torvalds 21491da177e4SLinus Torvaldsd32bitdivide: 21501da177e4SLinus Torvalds tdivu.l %d7, %d5:%d6 # it's only a 32/32 bit div! 21511da177e4SLinus Torvalds 21521da177e4SLinus Torvalds bra.b divfinish 21531da177e4SLinus Torvalds 21541da177e4SLinus Torvaldsdnormaldivide: 21551da177e4SLinus Torvalds# last special case: 21561da177e4SLinus Torvalds# - is hi(dividend) >= divisor ? if yes, then overflow 21571da177e4SLinus Torvalds cmp.l %d7,%d5 21581da177e4SLinus Torvalds bls.b ddovf # answer won't fit in 32 bits 21591da177e4SLinus Torvalds 21601da177e4SLinus Torvalds# perform the divide algorithm: 21611da177e4SLinus Torvalds bsr.l dclassical # do int divide 21621da177e4SLinus Torvalds 21631da177e4SLinus Torvalds# separate into signed and unsigned finishes. 21641da177e4SLinus Torvaldsdivfinish: 21651da177e4SLinus Torvalds btst &0x3, EXC_EXTWORD(%a6) # do divs, divu separately 21661da177e4SLinus Torvalds beq.b ddone # divu has no processing!!! 21671da177e4SLinus Torvalds 21681da177e4SLinus Torvalds# it was a divs.l, so ccode setting is a little more complicated... 21691da177e4SLinus Torvalds tst.b NDIVIDEND(%a6) # remainder has same sign 21701da177e4SLinus Torvalds beq.b dcc # as dividend. 21711da177e4SLinus Torvalds neg.l %d5 # sgn(rem) = sgn(dividend) 21721da177e4SLinus Torvaldsdcc: 21731da177e4SLinus Torvalds mov.b NDIVISOR(%a6), %d0 21741da177e4SLinus Torvalds eor.b %d0, NDIVIDEND(%a6) # chk if quotient is negative 21751da177e4SLinus Torvalds beq.b dqpos # branch to quot positive 21761da177e4SLinus Torvalds 21771da177e4SLinus Torvalds# 0x80000000 is the largest number representable as a 32-bit negative 21781da177e4SLinus Torvalds# number. the negative of 0x80000000 is 0x80000000. 21791da177e4SLinus Torvalds cmpi.l %d6, &0x80000000 # will (-quot) fit in 32 bits? 21801da177e4SLinus Torvalds bhi.b ddovf 21811da177e4SLinus Torvalds 21821da177e4SLinus Torvalds neg.l %d6 # make (-quot) 2's comp 21831da177e4SLinus Torvalds 21841da177e4SLinus Torvalds bra.b ddone 21851da177e4SLinus Torvalds 21861da177e4SLinus Torvaldsdqpos: 21871da177e4SLinus Torvalds btst &0x1f, %d6 # will (+quot) fit in 32 bits? 21881da177e4SLinus Torvalds bne.b ddovf 21891da177e4SLinus Torvalds 21901da177e4SLinus Torvaldsddone: 21911da177e4SLinus Torvalds# at this point, result is normal so ccodes are set based on result. 21921da177e4SLinus Torvalds mov.w EXC_CC(%a6), %cc 21931da177e4SLinus Torvalds tst.l %d6 # set %ccode bits 21941da177e4SLinus Torvalds mov.w %cc, EXC_CC(%a6) 21951da177e4SLinus Torvalds 21961da177e4SLinus Torvalds mov.w NDRSAVE(%a6), %d0 # get Dr off stack 21971da177e4SLinus Torvalds mov.w NDQSAVE(%a6), %d1 # get Dq off stack 21981da177e4SLinus Torvalds 21991da177e4SLinus Torvalds# if the register numbers are the same, only the quotient gets saved. 22001da177e4SLinus Torvalds# so, if we always save the quotient second, we save ourselves a cmp&beq 22011da177e4SLinus Torvalds mov.l %d5, (EXC_DREGS,%a6,%d0.w*4) # save remainder 22021da177e4SLinus Torvalds mov.l %d6, (EXC_DREGS,%a6,%d1.w*4) # save quotient 22031da177e4SLinus Torvalds 22041da177e4SLinus Torvalds rts 22051da177e4SLinus Torvalds 22061da177e4SLinus Torvaldsddovf: 22071da177e4SLinus Torvalds bset &0x1, EXC_CC+1(%a6) # 'V' set on overflow 22081da177e4SLinus Torvalds bclr &0x0, EXC_CC+1(%a6) # 'C' cleared on overflow 22091da177e4SLinus Torvalds 22101da177e4SLinus Torvalds rts 22111da177e4SLinus Torvalds 22121da177e4SLinus Torvaldsdiv64eq0: 22131da177e4SLinus Torvalds andi.b &0x1e, EXC_CC+1(%a6) # clear 'C' bit on divbyzero 22141da177e4SLinus Torvalds ori.b &idbyz_flg,SPCOND_FLG(%a6) # set "special case" flag 22151da177e4SLinus Torvalds rts 22161da177e4SLinus Torvalds 22171da177e4SLinus Torvalds########################################################################### 22181da177e4SLinus Torvalds######################################################################### 22191da177e4SLinus Torvalds# This routine uses the 'classical' Algorithm D from Donald Knuth's # 22201da177e4SLinus Torvalds# Art of Computer Programming, vol II, Seminumerical Algorithms. # 22211da177e4SLinus Torvalds# For this implementation b=2**16, and the target is U1U2U3U4/V1V2, # 22221da177e4SLinus Torvalds# where U,V are words of the quadword dividend and longword divisor, # 22231da177e4SLinus Torvalds# and U1, V1 are the most significant words. # 22241da177e4SLinus Torvalds# # 22251da177e4SLinus Torvalds# The most sig. longword of the 64 bit dividend must be in %d5, least # 22261da177e4SLinus Torvalds# in %d6. The divisor must be in the variable ddivisor, and the # 22271da177e4SLinus Torvalds# signed/unsigned flag ddusign must be set (0=unsigned,1=signed). # 22281da177e4SLinus Torvalds# The quotient is returned in %d6, remainder in %d5, unless the # 22291da177e4SLinus Torvalds# v (overflow) bit is set in the saved %ccr. If overflow, the dividend # 22301da177e4SLinus Torvalds# is unchanged. # 22311da177e4SLinus Torvalds######################################################################### 22321da177e4SLinus Torvaldsdclassical: 22331da177e4SLinus Torvalds# if the divisor msw is 0, use simpler algorithm then the full blown 22341da177e4SLinus Torvalds# one at ddknuth: 22351da177e4SLinus Torvalds 22361da177e4SLinus Torvalds cmpi.l %d7, &0xffff 22371da177e4SLinus Torvalds bhi.b ddknuth # go use D. Knuth algorithm 22381da177e4SLinus Torvalds 22391da177e4SLinus Torvalds# Since the divisor is only a word (and larger than the mslw of the dividend), 22401da177e4SLinus Torvalds# a simpler algorithm may be used : 22411da177e4SLinus Torvalds# In the general case, four quotient words would be created by 22421da177e4SLinus Torvalds# dividing the divisor word into each dividend word. In this case, 22431da177e4SLinus Torvalds# the first two quotient words must be zero, or overflow would occur. 22441da177e4SLinus Torvalds# Since we already checked this case above, we can treat the most significant 22451da177e4SLinus Torvalds# longword of the dividend as (0) remainder (see Knuth) and merely complete 22461da177e4SLinus Torvalds# the last two divisions to get a quotient longword and word remainder: 22471da177e4SLinus Torvalds 22481da177e4SLinus Torvalds clr.l %d1 22491da177e4SLinus Torvalds swap %d5 # same as r*b if previous step rqd 22501da177e4SLinus Torvalds swap %d6 # get u3 to lsw position 22511da177e4SLinus Torvalds mov.w %d6, %d5 # rb + u3 22521da177e4SLinus Torvalds 22531da177e4SLinus Torvalds divu.w %d7, %d5 22541da177e4SLinus Torvalds 22551da177e4SLinus Torvalds mov.w %d5, %d1 # first quotient word 22561da177e4SLinus Torvalds swap %d6 # get u4 22571da177e4SLinus Torvalds mov.w %d6, %d5 # rb + u4 22581da177e4SLinus Torvalds 22591da177e4SLinus Torvalds divu.w %d7, %d5 22601da177e4SLinus Torvalds 22611da177e4SLinus Torvalds swap %d1 22621da177e4SLinus Torvalds mov.w %d5, %d1 # 2nd quotient 'digit' 22631da177e4SLinus Torvalds clr.w %d5 22641da177e4SLinus Torvalds swap %d5 # now remainder 22651da177e4SLinus Torvalds mov.l %d1, %d6 # and quotient 22661da177e4SLinus Torvalds 22671da177e4SLinus Torvalds rts 22681da177e4SLinus Torvalds 22691da177e4SLinus Torvaldsddknuth: 22701da177e4SLinus Torvalds# In this algorithm, the divisor is treated as a 2 digit (word) number 22711da177e4SLinus Torvalds# which is divided into a 3 digit (word) dividend to get one quotient 22721da177e4SLinus Torvalds# digit (word). After subtraction, the dividend is shifted and the 22731da177e4SLinus Torvalds# process repeated. Before beginning, the divisor and quotient are 22741da177e4SLinus Torvalds# 'normalized' so that the process of estimating the quotient digit 22751da177e4SLinus Torvalds# will yield verifiably correct results.. 22761da177e4SLinus Torvalds 22771da177e4SLinus Torvalds clr.l DDNORMAL(%a6) # count of shifts for normalization 22781da177e4SLinus Torvalds clr.b DDSECOND(%a6) # clear flag for quotient digits 22791da177e4SLinus Torvalds clr.l %d1 # %d1 will hold trial quotient 22801da177e4SLinus Torvaldsddnchk: 22811da177e4SLinus Torvalds btst &31, %d7 # must we normalize? first word of 22821da177e4SLinus Torvalds bne.b ddnormalized # divisor (V1) must be >= 65536/2 22831da177e4SLinus Torvalds addq.l &0x1, DDNORMAL(%a6) # count normalization shifts 22841da177e4SLinus Torvalds lsl.l &0x1, %d7 # shift the divisor 22851da177e4SLinus Torvalds lsl.l &0x1, %d6 # shift u4,u3 with overflow to u2 22861da177e4SLinus Torvalds roxl.l &0x1, %d5 # shift u1,u2 22871da177e4SLinus Torvalds bra.w ddnchk 22881da177e4SLinus Torvaldsddnormalized: 22891da177e4SLinus Torvalds 22901da177e4SLinus Torvalds# Now calculate an estimate of the quotient words (msw first, then lsw). 22911da177e4SLinus Torvalds# The comments use subscripts for the first quotient digit determination. 22921da177e4SLinus Torvalds mov.l %d7, %d3 # divisor 22931da177e4SLinus Torvalds mov.l %d5, %d2 # dividend mslw 22941da177e4SLinus Torvalds swap %d2 22951da177e4SLinus Torvalds swap %d3 22961da177e4SLinus Torvalds cmp.w %d2, %d3 # V1 = U1 ? 22971da177e4SLinus Torvalds bne.b ddqcalc1 22981da177e4SLinus Torvalds mov.w &0xffff, %d1 # use max trial quotient word 22991da177e4SLinus Torvalds bra.b ddadj0 23001da177e4SLinus Torvaldsddqcalc1: 23011da177e4SLinus Torvalds mov.l %d5, %d1 23021da177e4SLinus Torvalds 23031da177e4SLinus Torvalds divu.w %d3, %d1 # use quotient of mslw/msw 23041da177e4SLinus Torvalds 23051da177e4SLinus Torvalds andi.l &0x0000ffff, %d1 # zero any remainder 23061da177e4SLinus Torvaldsddadj0: 23071da177e4SLinus Torvalds 23081da177e4SLinus Torvalds# now test the trial quotient and adjust. This step plus the 23091da177e4SLinus Torvalds# normalization assures (according to Knuth) that the trial 23101da177e4SLinus Torvalds# quotient will be at worst 1 too large. 23111da177e4SLinus Torvalds mov.l %d6, -(%sp) 23121da177e4SLinus Torvalds clr.w %d6 # word u3 left 23131da177e4SLinus Torvalds swap %d6 # in lsw position 23141da177e4SLinus Torvaldsddadj1: mov.l %d7, %d3 23151da177e4SLinus Torvalds mov.l %d1, %d2 23161da177e4SLinus Torvalds mulu.w %d7, %d2 # V2q 23171da177e4SLinus Torvalds swap %d3 23181da177e4SLinus Torvalds mulu.w %d1, %d3 # V1q 23191da177e4SLinus Torvalds mov.l %d5, %d4 # U1U2 23201da177e4SLinus Torvalds sub.l %d3, %d4 # U1U2 - V1q 23211da177e4SLinus Torvalds 23221da177e4SLinus Torvalds swap %d4 23231da177e4SLinus Torvalds 23241da177e4SLinus Torvalds mov.w %d4,%d0 23251da177e4SLinus Torvalds mov.w %d6,%d4 # insert lower word (U3) 23261da177e4SLinus Torvalds 23271da177e4SLinus Torvalds tst.w %d0 # is upper word set? 23281da177e4SLinus Torvalds bne.w ddadjd1 23291da177e4SLinus Torvalds 23301da177e4SLinus Torvalds# add.l %d6, %d4 # (U1U2 - V1q) + U3 23311da177e4SLinus Torvalds 23321da177e4SLinus Torvalds cmp.l %d2, %d4 23331da177e4SLinus Torvalds bls.b ddadjd1 # is V2q > (U1U2-V1q) + U3 ? 23341da177e4SLinus Torvalds subq.l &0x1, %d1 # yes, decrement and recheck 23351da177e4SLinus Torvalds bra.b ddadj1 23361da177e4SLinus Torvaldsddadjd1: 23371da177e4SLinus Torvalds# now test the word by multiplying it by the divisor (V1V2) and comparing 23381da177e4SLinus Torvalds# the 3 digit (word) result with the current dividend words 23391da177e4SLinus Torvalds mov.l %d5, -(%sp) # save %d5 (%d6 already saved) 23401da177e4SLinus Torvalds mov.l %d1, %d6 23411da177e4SLinus Torvalds swap %d6 # shift answer to ms 3 words 23421da177e4SLinus Torvalds mov.l %d7, %d5 23431da177e4SLinus Torvalds bsr.l dmm2 23441da177e4SLinus Torvalds mov.l %d5, %d2 # now %d2,%d3 are trial*divisor 23451da177e4SLinus Torvalds mov.l %d6, %d3 23461da177e4SLinus Torvalds mov.l (%sp)+, %d5 # restore dividend 23471da177e4SLinus Torvalds mov.l (%sp)+, %d6 23481da177e4SLinus Torvalds sub.l %d3, %d6 23491da177e4SLinus Torvalds subx.l %d2, %d5 # subtract double precision 23501da177e4SLinus Torvalds bcc dd2nd # no carry, do next quotient digit 23511da177e4SLinus Torvalds subq.l &0x1, %d1 # q is one too large 23521da177e4SLinus Torvalds# need to add back divisor longword to current ms 3 digits of dividend 23531da177e4SLinus Torvalds# - according to Knuth, this is done only 2 out of 65536 times for random 23541da177e4SLinus Torvalds# divisor, dividend selection. 23551da177e4SLinus Torvalds clr.l %d2 23561da177e4SLinus Torvalds mov.l %d7, %d3 23571da177e4SLinus Torvalds swap %d3 23581da177e4SLinus Torvalds clr.w %d3 # %d3 now ls word of divisor 23591da177e4SLinus Torvalds add.l %d3, %d6 # aligned with 3rd word of dividend 23601da177e4SLinus Torvalds addx.l %d2, %d5 23611da177e4SLinus Torvalds mov.l %d7, %d3 23621da177e4SLinus Torvalds clr.w %d3 # %d3 now ms word of divisor 23631da177e4SLinus Torvalds swap %d3 # aligned with 2nd word of dividend 23641da177e4SLinus Torvalds add.l %d3, %d5 23651da177e4SLinus Torvaldsdd2nd: 23661da177e4SLinus Torvalds tst.b DDSECOND(%a6) # both q words done? 23671da177e4SLinus Torvalds bne.b ddremain 23681da177e4SLinus Torvalds# first quotient digit now correct. store digit and shift the 23691da177e4SLinus Torvalds# (subtracted) dividend 23701da177e4SLinus Torvalds mov.w %d1, DDQUOTIENT(%a6) 23711da177e4SLinus Torvalds clr.l %d1 23721da177e4SLinus Torvalds swap %d5 23731da177e4SLinus Torvalds swap %d6 23741da177e4SLinus Torvalds mov.w %d6, %d5 23751da177e4SLinus Torvalds clr.w %d6 23761da177e4SLinus Torvalds st DDSECOND(%a6) # second digit 23771da177e4SLinus Torvalds bra.w ddnormalized 23781da177e4SLinus Torvaldsddremain: 23791da177e4SLinus Torvalds# add 2nd word to quotient, get the remainder. 23801da177e4SLinus Torvalds mov.w %d1, DDQUOTIENT+2(%a6) 23811da177e4SLinus Torvalds# shift down one word/digit to renormalize remainder. 23821da177e4SLinus Torvalds mov.w %d5, %d6 23831da177e4SLinus Torvalds swap %d6 23841da177e4SLinus Torvalds swap %d5 23851da177e4SLinus Torvalds mov.l DDNORMAL(%a6), %d7 # get norm shift count 23861da177e4SLinus Torvalds beq.b ddrn 23871da177e4SLinus Torvalds subq.l &0x1, %d7 # set for loop count 23881da177e4SLinus Torvaldsddnlp: 23891da177e4SLinus Torvalds lsr.l &0x1, %d5 # shift into %d6 23901da177e4SLinus Torvalds roxr.l &0x1, %d6 23911da177e4SLinus Torvalds dbf %d7, ddnlp 23921da177e4SLinus Torvaldsddrn: 23931da177e4SLinus Torvalds mov.l %d6, %d5 # remainder 23941da177e4SLinus Torvalds mov.l DDQUOTIENT(%a6), %d6 # quotient 23951da177e4SLinus Torvalds 23961da177e4SLinus Torvalds rts 23971da177e4SLinus Torvaldsdmm2: 23981da177e4SLinus Torvalds# factors for the 32X32->64 multiplication are in %d5 and %d6. 23991da177e4SLinus Torvalds# returns 64 bit result in %d5 (hi) %d6(lo). 24001da177e4SLinus Torvalds# destroys %d2,%d3,%d4. 24011da177e4SLinus Torvalds 24021da177e4SLinus Torvalds# multiply hi,lo words of each factor to get 4 intermediate products 24031da177e4SLinus Torvalds mov.l %d6, %d2 24041da177e4SLinus Torvalds mov.l %d6, %d3 24051da177e4SLinus Torvalds mov.l %d5, %d4 24061da177e4SLinus Torvalds swap %d3 24071da177e4SLinus Torvalds swap %d4 24081da177e4SLinus Torvalds mulu.w %d5, %d6 # %d6 <- lsw*lsw 24091da177e4SLinus Torvalds mulu.w %d3, %d5 # %d5 <- msw-dest*lsw-source 24101da177e4SLinus Torvalds mulu.w %d4, %d2 # %d2 <- msw-source*lsw-dest 24111da177e4SLinus Torvalds mulu.w %d4, %d3 # %d3 <- msw*msw 24121da177e4SLinus Torvalds# now use swap and addx to consolidate to two longwords 24131da177e4SLinus Torvalds clr.l %d4 24141da177e4SLinus Torvalds swap %d6 24151da177e4SLinus Torvalds add.w %d5, %d6 # add msw of l*l to lsw of m*l product 24161da177e4SLinus Torvalds addx.w %d4, %d3 # add any carry to m*m product 24171da177e4SLinus Torvalds add.w %d2, %d6 # add in lsw of other m*l product 24181da177e4SLinus Torvalds addx.w %d4, %d3 # add any carry to m*m product 24191da177e4SLinus Torvalds swap %d6 # %d6 is low 32 bits of final product 24201da177e4SLinus Torvalds clr.w %d5 24211da177e4SLinus Torvalds clr.w %d2 # lsw of two mixed products used, 24221da177e4SLinus Torvalds swap %d5 # now use msws of longwords 24231da177e4SLinus Torvalds swap %d2 24241da177e4SLinus Torvalds add.l %d2, %d5 24251da177e4SLinus Torvalds add.l %d3, %d5 # %d5 now ms 32 bits of final product 24261da177e4SLinus Torvalds rts 24271da177e4SLinus Torvalds 24281da177e4SLinus Torvalds########## 24291da177e4SLinus Torvaldsdcontrolmodel_s: 24301da177e4SLinus Torvalds movq.l &LONG,%d0 24311da177e4SLinus Torvalds bsr.l _calc_ea # calc <ea> 24321da177e4SLinus Torvalds 24331da177e4SLinus Torvalds cmpi.b SPCOND_FLG(%a6),&immed_flg # immediate addressing mode? 24341da177e4SLinus Torvalds beq.b dimmed # yes 24351da177e4SLinus Torvalds 24361da177e4SLinus Torvalds mov.l %a0,%a2 24371da177e4SLinus Torvalds bsr.l _dmem_read_long # fetch divisor from <ea> 24381da177e4SLinus Torvalds 24391da177e4SLinus Torvalds tst.l %d1 # dfetch error? 24401da177e4SLinus Torvalds bne.b div64_err # yes 24411da177e4SLinus Torvalds 24421da177e4SLinus Torvalds mov.l %d0, %d7 24431da177e4SLinus Torvalds bra.w dgotsrcl 24441da177e4SLinus Torvalds 24451da177e4SLinus Torvalds# we have to split out immediate data here because it must be read using 24461da177e4SLinus Torvalds# imem_read() instead of dmem_read(). this becomes especially important 24471da177e4SLinus Torvalds# if the fetch runs into some deadly fault. 24481da177e4SLinus Torvaldsdimmed: 24491da177e4SLinus Torvalds addq.l &0x4,EXC_EXTWPTR(%a6) 24501da177e4SLinus Torvalds bsr.l _imem_read_long # read immediate value 24511da177e4SLinus Torvalds 24521da177e4SLinus Torvalds tst.l %d1 # ifetch error? 24531da177e4SLinus Torvalds bne.l isp_iacc # yes 24541da177e4SLinus Torvalds 24551da177e4SLinus Torvalds mov.l %d0,%d7 24561da177e4SLinus Torvalds bra.w dgotsrcl 24571da177e4SLinus Torvalds 24581da177e4SLinus Torvalds########## 24591da177e4SLinus Torvalds 24601da177e4SLinus Torvalds# if dmem_read_long() returns a fail message in d1, the package 24611da177e4SLinus Torvalds# must create an access error frame. here, we pass a skeleton fslw 24621da177e4SLinus Torvalds# and the failing address to the routine that creates the new frame. 24631da177e4SLinus Torvalds# also, we call isp_restore in case the effective addressing mode was 24641da177e4SLinus Torvalds# (an)+ or -(an) in which case the previous "an" value must be restored. 24651da177e4SLinus Torvalds# FSLW: 24661da177e4SLinus Torvalds# read = true 24671da177e4SLinus Torvalds# size = longword 24681da177e4SLinus Torvalds# TM = data 24691da177e4SLinus Torvalds# software emulation error = true 24701da177e4SLinus Torvaldsdiv64_err: 24711da177e4SLinus Torvalds bsr.l isp_restore # restore addr reg 24721da177e4SLinus Torvalds mov.l %a2,%a0 # pass failing address 24731da177e4SLinus Torvalds mov.l &0x01010001,%d0 # pass fslw 24741da177e4SLinus Torvalds bra.l isp_dacc 24751da177e4SLinus Torvalds 24761da177e4SLinus Torvalds######################################################################### 24771da177e4SLinus Torvalds# XDEF **************************************************************** # 24781da177e4SLinus Torvalds# _mul64(): routine to emulate mul{u,s}.l <ea>,Dh:Dl 32x32->64 # 24791da177e4SLinus Torvalds# # 24801da177e4SLinus Torvalds# XREF **************************************************************** # 24811da177e4SLinus Torvalds# _calc_ea() - calculate effective address # 24821da177e4SLinus Torvalds# isp_iacc() - handle instruction access error exception # 24831da177e4SLinus Torvalds# isp_dacc() - handle data access error exception # 24841da177e4SLinus Torvalds# isp_restore() - restore An on access error w/ -() or ()+ # 24851da177e4SLinus Torvalds# # 24861da177e4SLinus Torvalds# INPUT *************************************************************** # 24871da177e4SLinus Torvalds# none # 24881da177e4SLinus Torvalds# # 24891da177e4SLinus Torvalds# OUTPUT ************************************************************** # 24901da177e4SLinus Torvalds# If exiting through isp_dacc... # 24911da177e4SLinus Torvalds# a0 = failing address # 24921da177e4SLinus Torvalds# d0 = FSLW # 24931da177e4SLinus Torvalds# else # 24941da177e4SLinus Torvalds# none # 24951da177e4SLinus Torvalds# # 24961da177e4SLinus Torvalds# ALGORITHM *********************************************************** # 24971da177e4SLinus Torvalds# First, decode the operand location. If it's in Dn, fetch from # 24981da177e4SLinus Torvalds# the stack. If it's in memory, use _calc_ea() to calculate the # 24991da177e4SLinus Torvalds# effective address. Use _dmem_read_long() to fetch at that address. # 25001da177e4SLinus Torvalds# Unless the operand is immediate data. Then use _imem_read_long(). # 25011da177e4SLinus Torvalds# Send failures to isp_dacc() or isp_iacc() as appropriate. # 25021da177e4SLinus Torvalds# If the operands are signed, make them unsigned and save the # 25031da177e4SLinus Torvalds# sign info for later. Perform the multiplication using 16x16->32 # 25041da177e4SLinus Torvalds# unsigned multiplies and "add" instructions. Store the high and low # 25051da177e4SLinus Torvalds# portions of the result in the appropriate data registers on the # 25061da177e4SLinus Torvalds# stack. Calculate the condition codes, also. # 25071da177e4SLinus Torvalds# # 25081da177e4SLinus Torvalds######################################################################### 25091da177e4SLinus Torvalds 25101da177e4SLinus Torvalds############# 25111da177e4SLinus Torvalds# mul(u,s)l # 25121da177e4SLinus Torvalds############# 25131da177e4SLinus Torvalds global _mul64 25141da177e4SLinus Torvalds_mul64: 25151da177e4SLinus Torvalds mov.b EXC_OPWORD+1(%a6), %d0 # extract src {mode,reg} 25161da177e4SLinus Torvalds cmpi.b %d0, &0x7 # is src mode Dn or other? 25171da177e4SLinus Torvalds bgt.w mul64_memop # src is in memory 25181da177e4SLinus Torvalds 25191da177e4SLinus Torvalds# multiplier operand in the data register file. 25201da177e4SLinus Torvalds# must extract the register number and fetch the operand from the stack. 25211da177e4SLinus Torvaldsmul64_regop: 25221da177e4SLinus Torvalds andi.w &0x7, %d0 # extract Dn 25231da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d0.w*4), %d3 # fetch multiplier 25241da177e4SLinus Torvalds 25251da177e4SLinus Torvalds# multiplier is in %d3. now, extract Dl and Dh fields and fetch the 25261da177e4SLinus Torvalds# multiplicand from the data register specified by Dl. 25271da177e4SLinus Torvaldsmul64_multiplicand: 25281da177e4SLinus Torvalds mov.w EXC_EXTWORD(%a6), %d2 # fetch ext word 25291da177e4SLinus Torvalds clr.w %d1 # clear Dh reg 25301da177e4SLinus Torvalds mov.b %d2, %d1 # grab Dh 25311da177e4SLinus Torvalds rol.w &0x4, %d2 # align Dl byte 25321da177e4SLinus Torvalds andi.w &0x7, %d2 # extract Dl 25331da177e4SLinus Torvalds 25341da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d2.w*4), %d4 # get multiplicand 25351da177e4SLinus Torvalds 25361da177e4SLinus Torvalds# check for the case of "zero" result early 25371da177e4SLinus Torvalds tst.l %d4 # test multiplicand 25381da177e4SLinus Torvalds beq.w mul64_zero # handle zero separately 25391da177e4SLinus Torvalds tst.l %d3 # test multiplier 25401da177e4SLinus Torvalds beq.w mul64_zero # handle zero separately 25411da177e4SLinus Torvalds 25421da177e4SLinus Torvalds# multiplier is in %d3 and multiplicand is in %d4. 25431da177e4SLinus Torvalds# if the operation is to be signed, then the operands are converted 25441da177e4SLinus Torvalds# to unsigned and the result sign is saved for the end. 25451da177e4SLinus Torvalds clr.b EXC_TEMP(%a6) # clear temp space 25461da177e4SLinus Torvalds btst &0x3, EXC_EXTWORD(%a6) # signed or unsigned? 25471da177e4SLinus Torvalds beq.b mul64_alg # unsigned; skip sgn calc 25481da177e4SLinus Torvalds 25491da177e4SLinus Torvalds tst.l %d3 # is multiplier negative? 25501da177e4SLinus Torvalds bge.b mul64_chk_md_sgn # no 25511da177e4SLinus Torvalds neg.l %d3 # make multiplier positive 25521da177e4SLinus Torvalds ori.b &0x1, EXC_TEMP(%a6) # save multiplier sgn 25531da177e4SLinus Torvalds 25541da177e4SLinus Torvalds# the result sign is the exclusive or of the operand sign bits. 25551da177e4SLinus Torvaldsmul64_chk_md_sgn: 25561da177e4SLinus Torvalds tst.l %d4 # is multiplicand negative? 25571da177e4SLinus Torvalds bge.b mul64_alg # no 25581da177e4SLinus Torvalds neg.l %d4 # make multiplicand positive 25591da177e4SLinus Torvalds eori.b &0x1, EXC_TEMP(%a6) # calculate correct sign 25601da177e4SLinus Torvalds 25611da177e4SLinus Torvalds######################################################################### 25621da177e4SLinus Torvalds# 63 32 0 # 25631da177e4SLinus Torvalds# ---------------------------- # 25641da177e4SLinus Torvalds# | hi(mplier) * hi(mplicand)| # 25651da177e4SLinus Torvalds# ---------------------------- # 25661da177e4SLinus Torvalds# ----------------------------- # 25671da177e4SLinus Torvalds# | hi(mplier) * lo(mplicand) | # 25681da177e4SLinus Torvalds# ----------------------------- # 25691da177e4SLinus Torvalds# ----------------------------- # 25701da177e4SLinus Torvalds# | lo(mplier) * hi(mplicand) | # 25711da177e4SLinus Torvalds# ----------------------------- # 25721da177e4SLinus Torvalds# | ----------------------------- # 25731da177e4SLinus Torvalds# --|-- | lo(mplier) * lo(mplicand) | # 25741da177e4SLinus Torvalds# | ----------------------------- # 25751da177e4SLinus Torvalds# ======================================================== # 25761da177e4SLinus Torvalds# -------------------------------------------------------- # 25771da177e4SLinus Torvalds# | hi(result) | lo(result) | # 25781da177e4SLinus Torvalds# -------------------------------------------------------- # 25791da177e4SLinus Torvalds######################################################################### 25801da177e4SLinus Torvaldsmul64_alg: 25811da177e4SLinus Torvalds# load temp registers with operands 25821da177e4SLinus Torvalds mov.l %d3, %d5 # mr in %d5 25831da177e4SLinus Torvalds mov.l %d3, %d6 # mr in %d6 25841da177e4SLinus Torvalds mov.l %d4, %d7 # md in %d7 25851da177e4SLinus Torvalds swap %d6 # hi(mr) in lo %d6 25861da177e4SLinus Torvalds swap %d7 # hi(md) in lo %d7 25871da177e4SLinus Torvalds 25881da177e4SLinus Torvalds# complete necessary multiplies: 25891da177e4SLinus Torvalds mulu.w %d4, %d3 # [1] lo(mr) * lo(md) 25901da177e4SLinus Torvalds mulu.w %d6, %d4 # [2] hi(mr) * lo(md) 25911da177e4SLinus Torvalds mulu.w %d7, %d5 # [3] lo(mr) * hi(md) 25921da177e4SLinus Torvalds mulu.w %d7, %d6 # [4] hi(mr) * hi(md) 25931da177e4SLinus Torvalds 25941da177e4SLinus Torvalds# add lo portions of [2],[3] to hi portion of [1]. 25951da177e4SLinus Torvalds# add carries produced from these adds to [4]. 25961da177e4SLinus Torvalds# lo([1]) is the final lo 16 bits of the result. 25971da177e4SLinus Torvalds clr.l %d7 # load %d7 w/ zero value 25981da177e4SLinus Torvalds swap %d3 # hi([1]) <==> lo([1]) 25991da177e4SLinus Torvalds add.w %d4, %d3 # hi([1]) + lo([2]) 26001da177e4SLinus Torvalds addx.l %d7, %d6 # [4] + carry 26011da177e4SLinus Torvalds add.w %d5, %d3 # hi([1]) + lo([3]) 26021da177e4SLinus Torvalds addx.l %d7, %d6 # [4] + carry 26031da177e4SLinus Torvalds swap %d3 # lo([1]) <==> hi([1]) 26041da177e4SLinus Torvalds 26051da177e4SLinus Torvalds# lo portions of [2],[3] have been added in to final result. 26061da177e4SLinus Torvalds# now, clear lo, put hi in lo reg, and add to [4] 26071da177e4SLinus Torvalds clr.w %d4 # clear lo([2]) 26081da177e4SLinus Torvalds clr.w %d5 # clear hi([3]) 26091da177e4SLinus Torvalds swap %d4 # hi([2]) in lo %d4 26101da177e4SLinus Torvalds swap %d5 # hi([3]) in lo %d5 26111da177e4SLinus Torvalds add.l %d5, %d4 # [4] + hi([2]) 26121da177e4SLinus Torvalds add.l %d6, %d4 # [4] + hi([3]) 26131da177e4SLinus Torvalds 26141da177e4SLinus Torvalds# unsigned result is now in {%d4,%d3} 26151da177e4SLinus Torvalds tst.b EXC_TEMP(%a6) # should result be signed? 26161da177e4SLinus Torvalds beq.b mul64_done # no 26171da177e4SLinus Torvalds 26181da177e4SLinus Torvalds# result should be a signed negative number. 26191da177e4SLinus Torvalds# compute 2's complement of the unsigned number: 26201da177e4SLinus Torvalds# -negate all bits and add 1 26211da177e4SLinus Torvaldsmul64_neg: 26221da177e4SLinus Torvalds not.l %d3 # negate lo(result) bits 26231da177e4SLinus Torvalds not.l %d4 # negate hi(result) bits 26241da177e4SLinus Torvalds addq.l &1, %d3 # add 1 to lo(result) 26251da177e4SLinus Torvalds addx.l %d7, %d4 # add carry to hi(result) 26261da177e4SLinus Torvalds 26271da177e4SLinus Torvalds# the result is saved to the register file. 26281da177e4SLinus Torvalds# for '040 compatibility, if Dl == Dh then only the hi(result) is 26291da177e4SLinus Torvalds# saved. so, saving hi after lo accomplishes this without need to 26301da177e4SLinus Torvalds# check Dl,Dh equality. 26311da177e4SLinus Torvaldsmul64_done: 26321da177e4SLinus Torvalds mov.l %d3, (EXC_DREGS,%a6,%d2.w*4) # save lo(result) 26331da177e4SLinus Torvalds mov.w &0x0, %cc 26341da177e4SLinus Torvalds mov.l %d4, (EXC_DREGS,%a6,%d1.w*4) # save hi(result) 26351da177e4SLinus Torvalds 26361da177e4SLinus Torvalds# now, grab the condition codes. only one that can be set is 'N'. 26371da177e4SLinus Torvalds# 'N' CAN be set if the operation is unsigned if bit 63 is set. 26381da177e4SLinus Torvalds mov.w %cc, %d7 # fetch %ccr to see if 'N' set 26391da177e4SLinus Torvalds andi.b &0x8, %d7 # extract 'N' bit 26401da177e4SLinus Torvalds 26411da177e4SLinus Torvaldsmul64_ccode_set: 26421da177e4SLinus Torvalds mov.b EXC_CC+1(%a6), %d6 # fetch previous %ccr 26431da177e4SLinus Torvalds andi.b &0x10, %d6 # all but 'X' bit changes 26441da177e4SLinus Torvalds 26451da177e4SLinus Torvalds or.b %d7, %d6 # group 'X' and 'N' 26461da177e4SLinus Torvalds mov.b %d6, EXC_CC+1(%a6) # save new %ccr 26471da177e4SLinus Torvalds 26481da177e4SLinus Torvalds rts 26491da177e4SLinus Torvalds 26501da177e4SLinus Torvalds# one or both of the operands is zero so the result is also zero. 26511da177e4SLinus Torvalds# save the zero result to the register file and set the 'Z' ccode bit. 26521da177e4SLinus Torvaldsmul64_zero: 26531da177e4SLinus Torvalds clr.l (EXC_DREGS,%a6,%d2.w*4) # save lo(result) 26541da177e4SLinus Torvalds clr.l (EXC_DREGS,%a6,%d1.w*4) # save hi(result) 26551da177e4SLinus Torvalds 26561da177e4SLinus Torvalds movq.l &0x4, %d7 # set 'Z' ccode bit 26571da177e4SLinus Torvalds bra.b mul64_ccode_set # finish ccode set 26581da177e4SLinus Torvalds 26591da177e4SLinus Torvalds########## 26601da177e4SLinus Torvalds 26611da177e4SLinus Torvalds# multiplier operand is in memory at the effective address. 26621da177e4SLinus Torvalds# must calculate the <ea> and go fetch the 32-bit operand. 26631da177e4SLinus Torvaldsmul64_memop: 26641da177e4SLinus Torvalds movq.l &LONG, %d0 # pass # of bytes 26651da177e4SLinus Torvalds bsr.l _calc_ea # calculate <ea> 26661da177e4SLinus Torvalds 26671da177e4SLinus Torvalds cmpi.b SPCOND_FLG(%a6),&immed_flg # immediate addressing mode? 26681da177e4SLinus Torvalds beq.b mul64_immed # yes 26691da177e4SLinus Torvalds 26701da177e4SLinus Torvalds mov.l %a0,%a2 26711da177e4SLinus Torvalds bsr.l _dmem_read_long # fetch src from addr (%a0) 26721da177e4SLinus Torvalds 26731da177e4SLinus Torvalds tst.l %d1 # dfetch error? 26741da177e4SLinus Torvalds bne.w mul64_err # yes 26751da177e4SLinus Torvalds 26761da177e4SLinus Torvalds mov.l %d0, %d3 # store multiplier in %d3 26771da177e4SLinus Torvalds 26781da177e4SLinus Torvalds bra.w mul64_multiplicand 26791da177e4SLinus Torvalds 26801da177e4SLinus Torvalds# we have to split out immediate data here because it must be read using 26811da177e4SLinus Torvalds# imem_read() instead of dmem_read(). this becomes especially important 26821da177e4SLinus Torvalds# if the fetch runs into some deadly fault. 26831da177e4SLinus Torvaldsmul64_immed: 26841da177e4SLinus Torvalds addq.l &0x4,EXC_EXTWPTR(%a6) 26851da177e4SLinus Torvalds bsr.l _imem_read_long # read immediate value 26861da177e4SLinus Torvalds 26871da177e4SLinus Torvalds tst.l %d1 # ifetch error? 26881da177e4SLinus Torvalds bne.l isp_iacc # yes 26891da177e4SLinus Torvalds 26901da177e4SLinus Torvalds mov.l %d0,%d3 26911da177e4SLinus Torvalds bra.w mul64_multiplicand 26921da177e4SLinus Torvalds 26931da177e4SLinus Torvalds########## 26941da177e4SLinus Torvalds 26951da177e4SLinus Torvalds# if dmem_read_long() returns a fail message in d1, the package 26961da177e4SLinus Torvalds# must create an access error frame. here, we pass a skeleton fslw 26971da177e4SLinus Torvalds# and the failing address to the routine that creates the new frame. 26981da177e4SLinus Torvalds# also, we call isp_restore in case the effective addressing mode was 26991da177e4SLinus Torvalds# (an)+ or -(an) in which case the previous "an" value must be restored. 27001da177e4SLinus Torvalds# FSLW: 27011da177e4SLinus Torvalds# read = true 27021da177e4SLinus Torvalds# size = longword 27031da177e4SLinus Torvalds# TM = data 27041da177e4SLinus Torvalds# software emulation error = true 27051da177e4SLinus Torvaldsmul64_err: 27061da177e4SLinus Torvalds bsr.l isp_restore # restore addr reg 27071da177e4SLinus Torvalds mov.l %a2,%a0 # pass failing address 27081da177e4SLinus Torvalds mov.l &0x01010001,%d0 # pass fslw 27091da177e4SLinus Torvalds bra.l isp_dacc 27101da177e4SLinus Torvalds 27111da177e4SLinus Torvalds######################################################################### 27121da177e4SLinus Torvalds# XDEF **************************************************************** # 27131da177e4SLinus Torvalds# _compandset2(): routine to emulate cas2() # 27141da177e4SLinus Torvalds# (internal to package) # 27151da177e4SLinus Torvalds# # 27161da177e4SLinus Torvalds# _isp_cas2_finish(): store ccodes, store compare regs # 27171da177e4SLinus Torvalds# (external to package) # 27181da177e4SLinus Torvalds# # 27191da177e4SLinus Torvalds# XREF **************************************************************** # 27201da177e4SLinus Torvalds# _real_lock_page() - "callout" to lock op's page from page-outs # 27211da177e4SLinus Torvalds# _cas_terminate2() - access error exit # 27221da177e4SLinus Torvalds# _real_cas2() - "callout" to core cas2 emulation code # 27231da177e4SLinus Torvalds# _real_unlock_page() - "callout" to unlock page # 27241da177e4SLinus Torvalds# # 27251da177e4SLinus Torvalds# INPUT *************************************************************** # 27261da177e4SLinus Torvalds# _compandset2(): # 27271da177e4SLinus Torvalds# d0 = instruction extension word # 27281da177e4SLinus Torvalds# # 27291da177e4SLinus Torvalds# _isp_cas2_finish(): # 27301da177e4SLinus Torvalds# see cas2 core emulation code # 27311da177e4SLinus Torvalds# # 27321da177e4SLinus Torvalds# OUTPUT ************************************************************** # 27331da177e4SLinus Torvalds# _compandset2(): # 27341da177e4SLinus Torvalds# see cas2 core emulation code # 27351da177e4SLinus Torvalds# # 27361da177e4SLinus Torvalds# _isp_cas_finish(): # 27371da177e4SLinus Torvalds# None (register file or memroy changed as appropriate) # 27381da177e4SLinus Torvalds# # 27391da177e4SLinus Torvalds# ALGORITHM *********************************************************** # 27401da177e4SLinus Torvalds# compandset2(): # 27411da177e4SLinus Torvalds# Decode the instruction and fetch the appropriate Update and # 27421da177e4SLinus Torvalds# Compare operands. Then call the "callout" _real_lock_page() for each # 27431da177e4SLinus Torvalds# memory operand address so that the operating system can keep these # 27441da177e4SLinus Torvalds# pages from being paged out. If either _real_lock_page() fails, exit # 27451da177e4SLinus Torvalds# through _cas_terminate2(). Don't forget to unlock the 1st locked page # 27461da177e4SLinus Torvalds# using _real_unlock_paged() if the 2nd lock-page fails. # 27471da177e4SLinus Torvalds# Finally, branch to the core cas2 emulation code by calling the # 27481da177e4SLinus Torvalds# "callout" _real_cas2(). # 27491da177e4SLinus Torvalds# # 27501da177e4SLinus Torvalds# _isp_cas2_finish(): # 27511da177e4SLinus Torvalds# Re-perform the comparison so we can determine the condition # 27521da177e4SLinus Torvalds# codes which were too much trouble to keep around during the locked # 27531da177e4SLinus Torvalds# emulation. Then unlock each operands page by calling the "callout" # 27541da177e4SLinus Torvalds# _real_unlock_page(). # 27551da177e4SLinus Torvalds# # 27561da177e4SLinus Torvalds######################################################################### 27571da177e4SLinus Torvalds 27581da177e4SLinus Torvaldsset ADDR1, EXC_TEMP+0xc 27591da177e4SLinus Torvaldsset ADDR2, EXC_TEMP+0x0 27601da177e4SLinus Torvaldsset DC2, EXC_TEMP+0xa 27611da177e4SLinus Torvaldsset DC1, EXC_TEMP+0x8 27621da177e4SLinus Torvalds 27631da177e4SLinus Torvalds global _compandset2 27641da177e4SLinus Torvalds_compandset2: 27651da177e4SLinus Torvalds mov.l %d0,EXC_TEMP+0x4(%a6) # store for possible restart 27661da177e4SLinus Torvalds mov.l %d0,%d1 # extension word in d0 27671da177e4SLinus Torvalds 27681da177e4SLinus Torvalds rol.w &0x4,%d0 27691da177e4SLinus Torvalds andi.w &0xf,%d0 # extract Rn2 27701da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d0.w*4),%a1 # fetch ADDR2 27711da177e4SLinus Torvalds mov.l %a1,ADDR2(%a6) 27721da177e4SLinus Torvalds 27731da177e4SLinus Torvalds mov.l %d1,%d0 27741da177e4SLinus Torvalds 27751da177e4SLinus Torvalds lsr.w &0x6,%d1 27761da177e4SLinus Torvalds andi.w &0x7,%d1 # extract Du2 27771da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d1.w*4),%d5 # fetch Update2 Op 27781da177e4SLinus Torvalds 27791da177e4SLinus Torvalds andi.w &0x7,%d0 # extract Dc2 27801da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d0.w*4),%d3 # fetch Compare2 Op 27811da177e4SLinus Torvalds mov.w %d0,DC2(%a6) 27821da177e4SLinus Torvalds 27831da177e4SLinus Torvalds mov.w EXC_EXTWORD(%a6),%d0 27841da177e4SLinus Torvalds mov.l %d0,%d1 27851da177e4SLinus Torvalds 27861da177e4SLinus Torvalds rol.w &0x4,%d0 27871da177e4SLinus Torvalds andi.w &0xf,%d0 # extract Rn1 27881da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d0.w*4),%a0 # fetch ADDR1 27891da177e4SLinus Torvalds mov.l %a0,ADDR1(%a6) 27901da177e4SLinus Torvalds 27911da177e4SLinus Torvalds mov.l %d1,%d0 27921da177e4SLinus Torvalds 27931da177e4SLinus Torvalds lsr.w &0x6,%d1 27941da177e4SLinus Torvalds andi.w &0x7,%d1 # extract Du1 27951da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d1.w*4),%d4 # fetch Update1 Op 27961da177e4SLinus Torvalds 27971da177e4SLinus Torvalds andi.w &0x7,%d0 # extract Dc1 27981da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d0.w*4),%d2 # fetch Compare1 Op 27991da177e4SLinus Torvalds mov.w %d0,DC1(%a6) 28001da177e4SLinus Torvalds 28011da177e4SLinus Torvalds btst &0x1,EXC_OPWORD(%a6) # word or long? 28021da177e4SLinus Torvalds sne %d7 28031da177e4SLinus Torvalds 28041da177e4SLinus Torvalds btst &0x5,EXC_ISR(%a6) # user or supervisor? 28051da177e4SLinus Torvalds sne %d6 28061da177e4SLinus Torvalds 28071da177e4SLinus Torvalds mov.l %a0,%a2 28081da177e4SLinus Torvalds mov.l %a1,%a3 28091da177e4SLinus Torvalds 28101da177e4SLinus Torvalds mov.l %d7,%d1 # pass size 28111da177e4SLinus Torvalds mov.l %d6,%d0 # pass mode 28121da177e4SLinus Torvalds bsr.l _real_lock_page # lock page 28131da177e4SLinus Torvalds mov.l %a2,%a0 28141da177e4SLinus Torvalds tst.l %d0 # error? 28151da177e4SLinus Torvalds bne.l _cas_terminate2 # yes 28161da177e4SLinus Torvalds 28171da177e4SLinus Torvalds mov.l %d7,%d1 # pass size 28181da177e4SLinus Torvalds mov.l %d6,%d0 # pass mode 28191da177e4SLinus Torvalds mov.l %a3,%a0 # pass addr 28201da177e4SLinus Torvalds bsr.l _real_lock_page # lock page 28211da177e4SLinus Torvalds mov.l %a3,%a0 28221da177e4SLinus Torvalds tst.l %d0 # error? 28231da177e4SLinus Torvalds bne.b cas_preterm # yes 28241da177e4SLinus Torvalds 28251da177e4SLinus Torvalds mov.l %a2,%a0 28261da177e4SLinus Torvalds mov.l %a3,%a1 28271da177e4SLinus Torvalds 28281da177e4SLinus Torvalds bra.l _real_cas2 28291da177e4SLinus Torvalds 28301da177e4SLinus Torvalds# if the 2nd lock attempt fails, then we must still unlock the 28311da177e4SLinus Torvalds# first page(s). 28321da177e4SLinus Torvaldscas_preterm: 28331da177e4SLinus Torvalds mov.l %d0,-(%sp) # save FSLW 28341da177e4SLinus Torvalds mov.l %d7,%d1 # pass size 28351da177e4SLinus Torvalds mov.l %d6,%d0 # pass mode 28361da177e4SLinus Torvalds mov.l %a2,%a0 # pass ADDR1 28371da177e4SLinus Torvalds bsr.l _real_unlock_page # unlock first page(s) 28381da177e4SLinus Torvalds mov.l (%sp)+,%d0 # restore FSLW 28391da177e4SLinus Torvalds mov.l %a3,%a0 # pass failing addr 28401da177e4SLinus Torvalds bra.l _cas_terminate2 28411da177e4SLinus Torvalds 28421da177e4SLinus Torvalds############################################################# 28431da177e4SLinus Torvalds 28441da177e4SLinus Torvalds global _isp_cas2_finish 28451da177e4SLinus Torvalds_isp_cas2_finish: 28461da177e4SLinus Torvalds btst &0x1,EXC_OPWORD(%a6) 28471da177e4SLinus Torvalds bne.b cas2_finish_l 28481da177e4SLinus Torvalds 28491da177e4SLinus Torvalds mov.w EXC_CC(%a6),%cc # load old ccodes 28501da177e4SLinus Torvalds cmp.w %d0,%d2 28511da177e4SLinus Torvalds bne.b cas2_finish_w_save 28521da177e4SLinus Torvalds cmp.w %d1,%d3 28531da177e4SLinus Torvaldscas2_finish_w_save: 28541da177e4SLinus Torvalds mov.w %cc,EXC_CC(%a6) # save new ccodes 28551da177e4SLinus Torvalds 28561da177e4SLinus Torvalds tst.b %d4 # update compare reg? 28571da177e4SLinus Torvalds bne.b cas2_finish_w_done # no 28581da177e4SLinus Torvalds 28591da177e4SLinus Torvalds mov.w DC2(%a6),%d3 # fetch Dc2 28601da177e4SLinus Torvalds mov.w %d1,(2+EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op 28611da177e4SLinus Torvalds 28621da177e4SLinus Torvalds mov.w DC1(%a6),%d2 # fetch Dc1 28631da177e4SLinus Torvalds mov.w %d0,(2+EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op 28641da177e4SLinus Torvalds 28651da177e4SLinus Torvaldscas2_finish_w_done: 28661da177e4SLinus Torvalds btst &0x5,EXC_ISR(%a6) 28671da177e4SLinus Torvalds sne %d2 28681da177e4SLinus Torvalds mov.l %d2,%d0 # pass mode 28691da177e4SLinus Torvalds sf %d1 # pass size 28701da177e4SLinus Torvalds mov.l ADDR1(%a6),%a0 # pass ADDR1 28711da177e4SLinus Torvalds bsr.l _real_unlock_page # unlock page 28721da177e4SLinus Torvalds 28731da177e4SLinus Torvalds mov.l %d2,%d0 # pass mode 28741da177e4SLinus Torvalds sf %d1 # pass size 28751da177e4SLinus Torvalds mov.l ADDR2(%a6),%a0 # pass ADDR2 28761da177e4SLinus Torvalds bsr.l _real_unlock_page # unlock page 28771da177e4SLinus Torvalds rts 28781da177e4SLinus Torvalds 28791da177e4SLinus Torvaldscas2_finish_l: 28801da177e4SLinus Torvalds mov.w EXC_CC(%a6),%cc # load old ccodes 28811da177e4SLinus Torvalds cmp.l %d0,%d2 28821da177e4SLinus Torvalds bne.b cas2_finish_l_save 28831da177e4SLinus Torvalds cmp.l %d1,%d3 28841da177e4SLinus Torvaldscas2_finish_l_save: 28851da177e4SLinus Torvalds mov.w %cc,EXC_CC(%a6) # save new ccodes 28861da177e4SLinus Torvalds 28871da177e4SLinus Torvalds tst.b %d4 # update compare reg? 28881da177e4SLinus Torvalds bne.b cas2_finish_l_done # no 28891da177e4SLinus Torvalds 28901da177e4SLinus Torvalds mov.w DC2(%a6),%d3 # fetch Dc2 28911da177e4SLinus Torvalds mov.l %d1,(EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op 28921da177e4SLinus Torvalds 28931da177e4SLinus Torvalds mov.w DC1(%a6),%d2 # fetch Dc1 28941da177e4SLinus Torvalds mov.l %d0,(EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op 28951da177e4SLinus Torvalds 28961da177e4SLinus Torvaldscas2_finish_l_done: 28971da177e4SLinus Torvalds btst &0x5,EXC_ISR(%a6) 28981da177e4SLinus Torvalds sne %d2 28991da177e4SLinus Torvalds mov.l %d2,%d0 # pass mode 29001da177e4SLinus Torvalds st %d1 # pass size 29011da177e4SLinus Torvalds mov.l ADDR1(%a6),%a0 # pass ADDR1 29021da177e4SLinus Torvalds bsr.l _real_unlock_page # unlock page 29031da177e4SLinus Torvalds 29041da177e4SLinus Torvalds mov.l %d2,%d0 # pass mode 29051da177e4SLinus Torvalds st %d1 # pass size 29061da177e4SLinus Torvalds mov.l ADDR2(%a6),%a0 # pass ADDR2 29071da177e4SLinus Torvalds bsr.l _real_unlock_page # unlock page 29081da177e4SLinus Torvalds rts 29091da177e4SLinus Torvalds 29101da177e4SLinus Torvalds######## 29111da177e4SLinus Torvalds global cr_cas2 29121da177e4SLinus Torvaldscr_cas2: 29131da177e4SLinus Torvalds mov.l EXC_TEMP+0x4(%a6),%d0 29141da177e4SLinus Torvalds bra.w _compandset2 29151da177e4SLinus Torvalds 29161da177e4SLinus Torvalds######################################################################### 29171da177e4SLinus Torvalds# XDEF **************************************************************** # 29181da177e4SLinus Torvalds# _compandset(): routine to emulate cas w/ misaligned <ea> # 29191da177e4SLinus Torvalds# (internal to package) # 29201da177e4SLinus Torvalds# _isp_cas_finish(): routine called when cas emulation completes # 29211da177e4SLinus Torvalds# (external and internal to package) # 29221da177e4SLinus Torvalds# _isp_cas_restart(): restart cas emulation after a fault # 29231da177e4SLinus Torvalds# (external to package) # 29241da177e4SLinus Torvalds# _isp_cas_terminate(): create access error stack frame on fault # 29251da177e4SLinus Torvalds# (external and internal to package) # 29261da177e4SLinus Torvalds# _isp_cas_inrange(): checks whether instr addess is within range # 29271da177e4SLinus Torvalds# of core cas/cas2emulation code # 29281da177e4SLinus Torvalds# (external to package) # 29291da177e4SLinus Torvalds# # 29301da177e4SLinus Torvalds# XREF **************************************************************** # 29311da177e4SLinus Torvalds# _calc_ea(): calculate effective address # 29321da177e4SLinus Torvalds# # 29331da177e4SLinus Torvalds# INPUT *************************************************************** # 29341da177e4SLinus Torvalds# compandset(): # 29351da177e4SLinus Torvalds# none # 29361da177e4SLinus Torvalds# _isp_cas_restart(): # 29371da177e4SLinus Torvalds# d6 = previous sfc/dfc # 29381da177e4SLinus Torvalds# _isp_cas_finish(): # 29391da177e4SLinus Torvalds# _isp_cas_terminate(): # 29401da177e4SLinus Torvalds# a0 = failing address # 29411da177e4SLinus Torvalds# d0 = FSLW # 29421da177e4SLinus Torvalds# d6 = previous sfc/dfc # 29431da177e4SLinus Torvalds# _isp_cas_inrange(): # 29441da177e4SLinus Torvalds# a0 = instruction address to be checked # 29451da177e4SLinus Torvalds# # 29461da177e4SLinus Torvalds# OUTPUT ************************************************************** # 29471da177e4SLinus Torvalds# compandset(): # 29481da177e4SLinus Torvalds# none # 29491da177e4SLinus Torvalds# _isp_cas_restart(): # 29501da177e4SLinus Torvalds# a0 = effective address # 29511da177e4SLinus Torvalds# d7 = word or longword flag # 29521da177e4SLinus Torvalds# _isp_cas_finish(): # 29531da177e4SLinus Torvalds# a0 = effective address # 29541da177e4SLinus Torvalds# _isp_cas_terminate(): # 29551da177e4SLinus Torvalds# initial register set before emulation exception # 29561da177e4SLinus Torvalds# _isp_cas_inrange(): # 29571da177e4SLinus Torvalds# d0 = 0 => in range; -1 => out of range # 29581da177e4SLinus Torvalds# # 29591da177e4SLinus Torvalds# ALGORITHM *********************************************************** # 29601da177e4SLinus Torvalds# # 29611da177e4SLinus Torvalds# compandset(): # 29621da177e4SLinus Torvalds# First, calculate the effective address. Then, decode the # 29631da177e4SLinus Torvalds# instruction word and fetch the "compare" (DC) and "update" (Du) # 29641da177e4SLinus Torvalds# operands. # 29651da177e4SLinus Torvalds# Next, call the external routine _real_lock_page() so that the # 29661da177e4SLinus Torvalds# operating system can keep this page from being paged out while we're # 29671da177e4SLinus Torvalds# in this routine. If this call fails, jump to _cas_terminate2(). # 29681da177e4SLinus Torvalds# The routine then branches to _real_cas(). This external routine # 29691da177e4SLinus Torvalds# that actually emulates cas can be supplied by the external os or # 29701da177e4SLinus Torvalds# made to point directly back into the 060ISP which has a routine for # 29711da177e4SLinus Torvalds# this purpose. # 29721da177e4SLinus Torvalds# # 29731da177e4SLinus Torvalds# _isp_cas_finish(): # 29741da177e4SLinus Torvalds# Either way, after emulation, the package is re-entered at # 29751da177e4SLinus Torvalds# _isp_cas_finish(). This routine re-compares the operands in order to # 29761da177e4SLinus Torvalds# set the condition codes. Finally, these routines will call # 29771da177e4SLinus Torvalds# _real_unlock_page() in order to unlock the pages that were previously # 29781da177e4SLinus Torvalds# locked. # 29791da177e4SLinus Torvalds# # 29801da177e4SLinus Torvalds# _isp_cas_restart(): # 29811da177e4SLinus Torvalds# This routine can be entered from an access error handler where # 29821da177e4SLinus Torvalds# the emulation sequence should be re-started from the beginning. # 29831da177e4SLinus Torvalds# # 29841da177e4SLinus Torvalds# _isp_cas_terminate(): # 29851da177e4SLinus Torvalds# This routine can be entered from an access error handler where # 29861da177e4SLinus Torvalds# an emulation operand access failed and the operating system would # 29871da177e4SLinus Torvalds# like an access error stack frame created instead of the current # 29881da177e4SLinus Torvalds# unimplemented integer instruction frame. # 29891da177e4SLinus Torvalds# Also, the package enters here if a call to _real_lock_page() # 29901da177e4SLinus Torvalds# fails. # 29911da177e4SLinus Torvalds# # 29921da177e4SLinus Torvalds# _isp_cas_inrange(): # 29931da177e4SLinus Torvalds# Checks to see whether the instruction address passed to it in # 29941da177e4SLinus Torvalds# a0 is within the software package cas/cas2 emulation routines. This # 29951da177e4SLinus Torvalds# can be helpful for an operating system to determine whether an access # 29961da177e4SLinus Torvalds# error during emulation was due to a cas/cas2 emulation access. # 29971da177e4SLinus Torvalds# # 29981da177e4SLinus Torvalds######################################################################### 29991da177e4SLinus Torvalds 30001da177e4SLinus Torvaldsset DC, EXC_TEMP+0x8 30011da177e4SLinus Torvaldsset ADDR, EXC_TEMP+0x4 30021da177e4SLinus Torvalds 30031da177e4SLinus Torvalds global _compandset 30041da177e4SLinus Torvalds_compandset: 30051da177e4SLinus Torvalds btst &0x1,EXC_OPWORD(%a6) # word or long operation? 30061da177e4SLinus Torvalds bne.b compandsetl # long 30071da177e4SLinus Torvalds 30081da177e4SLinus Torvaldscompandsetw: 30091da177e4SLinus Torvalds movq.l &0x2,%d0 # size = 2 bytes 30101da177e4SLinus Torvalds bsr.l _calc_ea # a0 = calculated <ea> 30111da177e4SLinus Torvalds mov.l %a0,ADDR(%a6) # save <ea> for possible restart 30121da177e4SLinus Torvalds sf %d7 # clear d7 for word size 30131da177e4SLinus Torvalds bra.b compandsetfetch 30141da177e4SLinus Torvalds 30151da177e4SLinus Torvaldscompandsetl: 30161da177e4SLinus Torvalds movq.l &0x4,%d0 # size = 4 bytes 30171da177e4SLinus Torvalds bsr.l _calc_ea # a0 = calculated <ea> 30181da177e4SLinus Torvalds mov.l %a0,ADDR(%a6) # save <ea> for possible restart 30191da177e4SLinus Torvalds st %d7 # set d7 for longword size 30201da177e4SLinus Torvalds 30211da177e4SLinus Torvaldscompandsetfetch: 30221da177e4SLinus Torvalds mov.w EXC_EXTWORD(%a6),%d0 # fetch cas extension word 30231da177e4SLinus Torvalds mov.l %d0,%d1 # make a copy 30241da177e4SLinus Torvalds 30251da177e4SLinus Torvalds lsr.w &0x6,%d0 30261da177e4SLinus Torvalds andi.w &0x7,%d0 # extract Du 30271da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d0.w*4),%d2 # get update operand 30281da177e4SLinus Torvalds 30291da177e4SLinus Torvalds andi.w &0x7,%d1 # extract Dc 30301da177e4SLinus Torvalds mov.l (EXC_DREGS,%a6,%d1.w*4),%d4 # get compare operand 30311da177e4SLinus Torvalds mov.w %d1,DC(%a6) # save Dc 30321da177e4SLinus Torvalds 30331da177e4SLinus Torvalds btst &0x5,EXC_ISR(%a6) # which mode for exception? 30341da177e4SLinus Torvalds sne %d6 # set on supervisor mode 30351da177e4SLinus Torvalds 30361da177e4SLinus Torvalds mov.l %a0,%a2 # save temporarily 30371da177e4SLinus Torvalds mov.l %d7,%d1 # pass size 30381da177e4SLinus Torvalds mov.l %d6,%d0 # pass mode 30391da177e4SLinus Torvalds bsr.l _real_lock_page # lock page 30401da177e4SLinus Torvalds tst.l %d0 # did error occur? 30411da177e4SLinus Torvalds bne.w _cas_terminate2 # yes, clean up the mess 30421da177e4SLinus Torvalds mov.l %a2,%a0 # pass addr in a0 30431da177e4SLinus Torvalds 30441da177e4SLinus Torvalds bra.l _real_cas 30451da177e4SLinus Torvalds 30461da177e4SLinus Torvalds######## 30471da177e4SLinus Torvalds global _isp_cas_finish 30481da177e4SLinus Torvalds_isp_cas_finish: 30491da177e4SLinus Torvalds btst &0x1,EXC_OPWORD(%a6) 30501da177e4SLinus Torvalds bne.b cas_finish_l 30511da177e4SLinus Torvalds 30521da177e4SLinus Torvalds# just do the compare again since it's faster than saving the ccodes 30531da177e4SLinus Torvalds# from the locked routine... 30541da177e4SLinus Torvaldscas_finish_w: 30551da177e4SLinus Torvalds mov.w EXC_CC(%a6),%cc # restore cc 30561da177e4SLinus Torvalds cmp.w %d0,%d4 # do word compare 30571da177e4SLinus Torvalds mov.w %cc,EXC_CC(%a6) # save cc 30581da177e4SLinus Torvalds 30591da177e4SLinus Torvalds tst.b %d1 # update compare reg? 30601da177e4SLinus Torvalds bne.b cas_finish_w_done # no 30611da177e4SLinus Torvalds 30621da177e4SLinus Torvalds mov.w DC(%a6),%d3 30631da177e4SLinus Torvalds mov.w %d0,(EXC_DREGS+2,%a6,%d3.w*4) # Dc = destination 30641da177e4SLinus Torvalds 30651da177e4SLinus Torvaldscas_finish_w_done: 30661da177e4SLinus Torvalds mov.l ADDR(%a6),%a0 # pass addr 30671da177e4SLinus Torvalds sf %d1 # pass size 30681da177e4SLinus Torvalds btst &0x5,EXC_ISR(%a6) 30691da177e4SLinus Torvalds sne %d0 # pass mode 30701da177e4SLinus Torvalds bsr.l _real_unlock_page # unlock page 30711da177e4SLinus Torvalds rts 30721da177e4SLinus Torvalds 30731da177e4SLinus Torvalds# just do the compare again since it's faster than saving the ccodes 30741da177e4SLinus Torvalds# from the locked routine... 30751da177e4SLinus Torvaldscas_finish_l: 30761da177e4SLinus Torvalds mov.w EXC_CC(%a6),%cc # restore cc 30771da177e4SLinus Torvalds cmp.l %d0,%d4 # do longword compare 30781da177e4SLinus Torvalds mov.w %cc,EXC_CC(%a6) # save cc 30791da177e4SLinus Torvalds 30801da177e4SLinus Torvalds tst.b %d1 # update compare reg? 30811da177e4SLinus Torvalds bne.b cas_finish_l_done # no 30821da177e4SLinus Torvalds 30831da177e4SLinus Torvalds mov.w DC(%a6),%d3 30841da177e4SLinus Torvalds mov.l %d0,(EXC_DREGS,%a6,%d3.w*4) # Dc = destination 30851da177e4SLinus Torvalds 30861da177e4SLinus Torvaldscas_finish_l_done: 30871da177e4SLinus Torvalds mov.l ADDR(%a6),%a0 # pass addr 30881da177e4SLinus Torvalds st %d1 # pass size 30891da177e4SLinus Torvalds btst &0x5,EXC_ISR(%a6) 30901da177e4SLinus Torvalds sne %d0 # pass mode 30911da177e4SLinus Torvalds bsr.l _real_unlock_page # unlock page 30921da177e4SLinus Torvalds rts 30931da177e4SLinus Torvalds 30941da177e4SLinus Torvalds######## 30951da177e4SLinus Torvalds 30961da177e4SLinus Torvalds global _isp_cas_restart 30971da177e4SLinus Torvalds_isp_cas_restart: 30981da177e4SLinus Torvalds mov.l %d6,%sfc # restore previous sfc 30991da177e4SLinus Torvalds mov.l %d6,%dfc # restore previous dfc 31001da177e4SLinus Torvalds 31011da177e4SLinus Torvalds cmpi.b EXC_OPWORD+1(%a6),&0xfc # cas or cas2? 31021da177e4SLinus Torvalds beq.l cr_cas2 # cas2 31031da177e4SLinus Torvaldscr_cas: 31041da177e4SLinus Torvalds mov.l ADDR(%a6),%a0 # load <ea> 31051da177e4SLinus Torvalds btst &0x1,EXC_OPWORD(%a6) # word or long operation? 31061da177e4SLinus Torvalds sne %d7 # set d7 accordingly 31071da177e4SLinus Torvalds bra.w compandsetfetch 31081da177e4SLinus Torvalds 31091da177e4SLinus Torvalds######## 31101da177e4SLinus Torvalds 31111da177e4SLinus Torvalds# At this stage, it would be nice if d0 held the FSLW. 31121da177e4SLinus Torvalds global _isp_cas_terminate 31131da177e4SLinus Torvalds_isp_cas_terminate: 31141da177e4SLinus Torvalds mov.l %d6,%sfc # restore previous sfc 31151da177e4SLinus Torvalds mov.l %d6,%dfc # restore previous dfc 31161da177e4SLinus Torvalds 31171da177e4SLinus Torvalds global _cas_terminate2 31181da177e4SLinus Torvalds_cas_terminate2: 31191da177e4SLinus Torvalds mov.l %a0,%a2 # copy failing addr to a2 31201da177e4SLinus Torvalds 31211da177e4SLinus Torvalds mov.l %d0,-(%sp) 31221da177e4SLinus Torvalds bsr.l isp_restore # restore An (if ()+ or -()) 31231da177e4SLinus Torvalds mov.l (%sp)+,%d0 31241da177e4SLinus Torvalds 31251da177e4SLinus Torvalds addq.l &0x4,%sp # remove sub return addr 31261da177e4SLinus Torvalds subq.l &0x8,%sp # make room for bigger stack 31271da177e4SLinus Torvalds subq.l &0x8,%a6 # shift frame ptr down, too 31281da177e4SLinus Torvalds mov.l &26,%d1 # want to move 51 longwords 31291da177e4SLinus Torvalds lea 0x8(%sp),%a0 # get address of old stack 31301da177e4SLinus Torvalds lea 0x0(%sp),%a1 # get address of new stack 31311da177e4SLinus Torvaldscas_term_cont: 31321da177e4SLinus Torvalds mov.l (%a0)+,(%a1)+ # move a longword 31331da177e4SLinus Torvalds dbra.w %d1,cas_term_cont # keep going 31341da177e4SLinus Torvalds 31351da177e4SLinus Torvalds mov.w &0x4008,EXC_IVOFF(%a6) # put new stk fmt, voff 31361da177e4SLinus Torvalds mov.l %a2,EXC_IVOFF+0x2(%a6) # put faulting addr on stack 31371da177e4SLinus Torvalds mov.l %d0,EXC_IVOFF+0x6(%a6) # put FSLW on stack 31381da177e4SLinus Torvalds movm.l EXC_DREGS(%a6),&0x3fff # restore user regs 31391da177e4SLinus Torvalds unlk %a6 # unlink stack frame 31401da177e4SLinus Torvalds bra.l _real_access 31411da177e4SLinus Torvalds 31421da177e4SLinus Torvalds######## 31431da177e4SLinus Torvalds 31441da177e4SLinus Torvalds global _isp_cas_inrange 31451da177e4SLinus Torvalds_isp_cas_inrange: 31461da177e4SLinus Torvalds clr.l %d0 # clear return result 31471da177e4SLinus Torvalds lea _CASHI(%pc),%a1 # load end of CAS core code 31481da177e4SLinus Torvalds cmp.l %a1,%a0 # is PC in range? 31491da177e4SLinus Torvalds blt.b cin_no # no 31501da177e4SLinus Torvalds lea _CASLO(%pc),%a1 # load begin of CAS core code 31511da177e4SLinus Torvalds cmp.l %a0,%a1 # is PC in range? 31521da177e4SLinus Torvalds blt.b cin_no # no 31531da177e4SLinus Torvalds rts # yes; return d0 = 0 31541da177e4SLinus Torvaldscin_no: 31551da177e4SLinus Torvalds mov.l &-0x1,%d0 # out of range; return d0 = -1 31561da177e4SLinus Torvalds rts 31571da177e4SLinus Torvalds 31581da177e4SLinus Torvalds################################################################# 31591da177e4SLinus Torvalds################################################################# 31601da177e4SLinus Torvalds################################################################# 31611da177e4SLinus Torvalds# This is the start of the cas and cas2 "core" emulation code. # 31621da177e4SLinus Torvalds# This is the section that may need to be replaced by the host # 31631da177e4SLinus Torvalds# OS if it is too operating system-specific. # 31641da177e4SLinus Torvalds# Please refer to the package documentation to see how to # 31651da177e4SLinus Torvalds# "replace" this section, if necessary. # 31661da177e4SLinus Torvalds################################################################# 31671da177e4SLinus Torvalds################################################################# 31681da177e4SLinus Torvalds################################################################# 31691da177e4SLinus Torvalds 31701da177e4SLinus Torvalds# ###### ## ###### #### 31711da177e4SLinus Torvalds# # # # # # # 31721da177e4SLinus Torvalds# # ###### ###### # 31731da177e4SLinus Torvalds# # # # # # 31741da177e4SLinus Torvalds# ###### # # ###### ###### 31751da177e4SLinus Torvalds 31761da177e4SLinus Torvalds######################################################################### 31771da177e4SLinus Torvalds# XDEF **************************************************************** # 31781da177e4SLinus Torvalds# _isp_cas2(): "core" emulation code for the cas2 instruction # 31791da177e4SLinus Torvalds# # 31801da177e4SLinus Torvalds# XREF **************************************************************** # 31811da177e4SLinus Torvalds# _isp_cas2_finish() - only exit point for this emulation code; # 31821da177e4SLinus Torvalds# do clean-up; calculate ccodes; store # 31831da177e4SLinus Torvalds# Compare Ops if appropriate. # 31841da177e4SLinus Torvalds# # 31851da177e4SLinus Torvalds# INPUT *************************************************************** # 31861da177e4SLinus Torvalds# *see chart below* # 31871da177e4SLinus Torvalds# # 31881da177e4SLinus Torvalds# OUTPUT ************************************************************** # 31891da177e4SLinus Torvalds# *see chart below* # 31901da177e4SLinus Torvalds# # 31911da177e4SLinus Torvalds# ALGORITHM *********************************************************** # 31921da177e4SLinus Torvalds# (1) Make several copies of the effective address. # 31931da177e4SLinus Torvalds# (2) Save current SR; Then mask off all maskable interrupts. # 31941da177e4SLinus Torvalds# (3) Save current SFC/DFC (ASSUMED TO BE EQUAL!!!); Then set # 31951da177e4SLinus Torvalds# according to whether exception occurred in user or # 31961da177e4SLinus Torvalds# supervisor mode. # 31971da177e4SLinus Torvalds# (4) Use "plpaw" instruction to pre-load ATC with effective # 31981da177e4SLinus Torvalds# address pages(s). THIS SHOULD NOT FAULT!!! The relevant # 31991da177e4SLinus Torvalds# page(s) should have already been made resident prior to # 32001da177e4SLinus Torvalds# entering this routine. # 32011da177e4SLinus Torvalds# (5) Push the operand lines from the cache w/ "cpushl". # 32021da177e4SLinus Torvalds# In the 68040, this was done within the locked region. In # 32031da177e4SLinus Torvalds# the 68060, it is done outside of the locked region. # 32041da177e4SLinus Torvalds# (6) Use "plpar" instruction to do a re-load of ATC entries for # 32051da177e4SLinus Torvalds# ADDR1 since ADDR2 entries may have pushed ADDR1 out of the # 32061da177e4SLinus Torvalds# ATC. # 32071da177e4SLinus Torvalds# (7) Pre-fetch the core emulation instructions by executing # 32081da177e4SLinus Torvalds# one branch within each physical line (16 bytes) of the code # 32091da177e4SLinus Torvalds# before actually executing the code. # 32101da177e4SLinus Torvalds# (8) Load the BUSCR w/ the bus lock value. # 32111da177e4SLinus Torvalds# (9) Fetch the source operands using "moves". # 32121da177e4SLinus Torvalds# (10)Do the compares. If both equal, go to step (13). # 32131da177e4SLinus Torvalds# (11)Unequal. No update occurs. But, we do write the DST1 op # 32141da177e4SLinus Torvalds# back to itself (as w/ the '040) so we can gracefully unlock # 32151da177e4SLinus Torvalds# the bus (and assert LOCKE*) using BUSCR and the final move. # 32161da177e4SLinus Torvalds# (12)Exit. # 32171da177e4SLinus Torvalds# (13)Write update operand to the DST locations. Use BUSCR to # 32181da177e4SLinus Torvalds# assert LOCKE* for the final write operation. # 32191da177e4SLinus Torvalds# (14)Exit. # 32201da177e4SLinus Torvalds# # 32211da177e4SLinus Torvalds# The algorithm is actually implemented slightly differently # 32221da177e4SLinus Torvalds# depending on the size of the operation and the misalignment of the # 32231da177e4SLinus Torvalds# operands. A misaligned operand must be written in aligned chunks or # 32241da177e4SLinus Torvalds# else the BUSCR register control gets confused. # 32251da177e4SLinus Torvalds# # 32261da177e4SLinus Torvalds######################################################################### 32271da177e4SLinus Torvalds 32281da177e4SLinus Torvalds################################################################# 32291da177e4SLinus Torvalds# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON # 32301da177e4SLinus Torvalds# ENTERING _isp_cas2(). # 32311da177e4SLinus Torvalds# # 32321da177e4SLinus Torvalds# D0 = xxxxxxxx # 32331da177e4SLinus Torvalds# D1 = xxxxxxxx # 32341da177e4SLinus Torvalds# D2 = cmp operand 1 # 32351da177e4SLinus Torvalds# D3 = cmp operand 2 # 32361da177e4SLinus Torvalds# D4 = update oper 1 # 32371da177e4SLinus Torvalds# D5 = update oper 2 # 32381da177e4SLinus Torvalds# D6 = 'xxxxxxff if supervisor mode; 'xxxxxx00 if user mode # 32391da177e4SLinus Torvalds# D7 = 'xxxxxxff if longword operation; 'xxxxxx00 if word # 32401da177e4SLinus Torvalds# A0 = ADDR1 # 32411da177e4SLinus Torvalds# A1 = ADDR2 # 32421da177e4SLinus Torvalds# A2 = xxxxxxxx # 32431da177e4SLinus Torvalds# A3 = xxxxxxxx # 32441da177e4SLinus Torvalds# A4 = xxxxxxxx # 32451da177e4SLinus Torvalds# A5 = xxxxxxxx # 32461da177e4SLinus Torvalds# A6 = frame pointer # 32471da177e4SLinus Torvalds# A7 = stack pointer # 32481da177e4SLinus Torvalds################################################################# 32491da177e4SLinus Torvalds 32501da177e4SLinus Torvalds# align 0x1000 32511da177e4SLinus Torvalds# beginning label used by _isp_cas_inrange() 32521da177e4SLinus Torvalds global _CASLO 32531da177e4SLinus Torvalds_CASLO: 32541da177e4SLinus Torvalds 32551da177e4SLinus Torvalds global _isp_cas2 32561da177e4SLinus Torvalds_isp_cas2: 32571da177e4SLinus Torvalds tst.b %d6 # user or supervisor mode? 32581da177e4SLinus Torvalds bne.b cas2_supervisor # supervisor 32591da177e4SLinus Torvaldscas2_user: 32601da177e4SLinus Torvalds movq.l &0x1,%d0 # load user data fc 32611da177e4SLinus Torvalds bra.b cas2_cont 32621da177e4SLinus Torvaldscas2_supervisor: 32631da177e4SLinus Torvalds movq.l &0x5,%d0 # load supervisor data fc 32641da177e4SLinus Torvaldscas2_cont: 32651da177e4SLinus Torvalds tst.b %d7 # word or longword? 32661da177e4SLinus Torvalds beq.w cas2w # word 32671da177e4SLinus Torvalds 32681da177e4SLinus Torvalds#### 32691da177e4SLinus Torvaldscas2l: 32701da177e4SLinus Torvalds mov.l %a0,%a2 # copy ADDR1 32711da177e4SLinus Torvalds mov.l %a1,%a3 # copy ADDR2 32721da177e4SLinus Torvalds mov.l %a0,%a4 # copy ADDR1 32731da177e4SLinus Torvalds mov.l %a1,%a5 # copy ADDR2 32741da177e4SLinus Torvalds 32751da177e4SLinus Torvalds addq.l &0x3,%a4 # ADDR1+3 32761da177e4SLinus Torvalds addq.l &0x3,%a5 # ADDR2+3 32771da177e4SLinus Torvalds mov.l %a2,%d1 # ADDR1 32781da177e4SLinus Torvalds 32791da177e4SLinus Torvalds# mask interrupts levels 0-6. save old mask value. 32801da177e4SLinus Torvalds mov.w %sr,%d7 # save current SR 32811da177e4SLinus Torvalds ori.w &0x0700,%sr # inhibit interrupts 32821da177e4SLinus Torvalds 32831da177e4SLinus Torvalds# load the SFC and DFC with the appropriate mode. 32841da177e4SLinus Torvalds movc %sfc,%d6 # save old SFC/DFC 32851da177e4SLinus Torvalds movc %d0,%sfc # store new SFC 32861da177e4SLinus Torvalds movc %d0,%dfc # store new DFC 32871da177e4SLinus Torvalds 32881da177e4SLinus Torvalds# pre-load the operand ATC. no page faults should occur here because 32891da177e4SLinus Torvalds# _real_lock_page() should have taken care of this. 32901da177e4SLinus Torvalds plpaw (%a2) # load atc for ADDR1 32911da177e4SLinus Torvalds plpaw (%a4) # load atc for ADDR1+3 32921da177e4SLinus Torvalds plpaw (%a3) # load atc for ADDR2 32931da177e4SLinus Torvalds plpaw (%a5) # load atc for ADDR2+3 32941da177e4SLinus Torvalds 32951da177e4SLinus Torvalds# push the operand lines from the cache if they exist. 32961da177e4SLinus Torvalds cpushl %dc,(%a2) # push line for ADDR1 32971da177e4SLinus Torvalds cpushl %dc,(%a4) # push line for ADDR1+3 32981da177e4SLinus Torvalds cpushl %dc,(%a3) # push line for ADDR2 32991da177e4SLinus Torvalds cpushl %dc,(%a5) # push line for ADDR2+2 33001da177e4SLinus Torvalds 33011da177e4SLinus Torvalds mov.l %d1,%a2 # ADDR1 33021da177e4SLinus Torvalds addq.l &0x3,%d1 33031da177e4SLinus Torvalds mov.l %d1,%a4 # ADDR1+3 33041da177e4SLinus Torvalds# if ADDR1 was ATC resident before the above "plpaw" and was executed 33051da177e4SLinus Torvalds# and it was the next entry scheduled for replacement and ADDR2 33061da177e4SLinus Torvalds# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1 33071da177e4SLinus Torvalds# entries from the ATC. so, we do a second set of "plpa"s. 33081da177e4SLinus Torvalds plpar (%a2) # load atc for ADDR1 33091da177e4SLinus Torvalds plpar (%a4) # load atc for ADDR1+3 33101da177e4SLinus Torvalds 33111da177e4SLinus Torvalds# load the BUSCR values. 33121da177e4SLinus Torvalds mov.l &0x80000000,%a2 # assert LOCK* buscr value 33131da177e4SLinus Torvalds mov.l &0xa0000000,%a3 # assert LOCKE* buscr value 33141da177e4SLinus Torvalds mov.l &0x00000000,%a4 # buscr unlock value 33151da177e4SLinus Torvalds 33161da177e4SLinus Torvalds# there are three possible mis-aligned cases for longword cas. they 33171da177e4SLinus Torvalds# are separated because the final write which asserts LOCKE* must 33181da177e4SLinus Torvalds# be aligned. 33191da177e4SLinus Torvalds mov.l %a0,%d0 # is ADDR1 misaligned? 33201da177e4SLinus Torvalds andi.b &0x3,%d0 33211da177e4SLinus Torvalds beq.b CAS2L_ENTER # no 33221da177e4SLinus Torvalds cmpi.b %d0,&0x2 33231da177e4SLinus Torvalds beq.w CAS2L2_ENTER # yes; word misaligned 33241da177e4SLinus Torvalds bra.w CAS2L3_ENTER # yes; byte misaligned 33251da177e4SLinus Torvalds 33261da177e4SLinus Torvalds# 33271da177e4SLinus Torvalds# D0 = dst operand 1 <- 33281da177e4SLinus Torvalds# D1 = dst operand 2 <- 33291da177e4SLinus Torvalds# D2 = cmp operand 1 33301da177e4SLinus Torvalds# D3 = cmp operand 2 33311da177e4SLinus Torvalds# D4 = update oper 1 33321da177e4SLinus Torvalds# D5 = update oper 2 33331da177e4SLinus Torvalds# D6 = old SFC/DFC 33341da177e4SLinus Torvalds# D7 = old SR 33351da177e4SLinus Torvalds# A0 = ADDR1 33361da177e4SLinus Torvalds# A1 = ADDR2 33371da177e4SLinus Torvalds# A2 = bus LOCK* value 33381da177e4SLinus Torvalds# A3 = bus LOCKE* value 33391da177e4SLinus Torvalds# A4 = bus unlock value 33401da177e4SLinus Torvalds# A5 = xxxxxxxx 33411da177e4SLinus Torvalds# 33421da177e4SLinus Torvalds align 0x10 33431da177e4SLinus TorvaldsCAS2L_START: 33441da177e4SLinus Torvalds movc %a2,%buscr # assert LOCK* 33451da177e4SLinus Torvalds movs.l (%a1),%d1 # fetch Dest2[31:0] 33461da177e4SLinus Torvalds movs.l (%a0),%d0 # fetch Dest1[31:0] 33471da177e4SLinus Torvalds bra.b CAS2L_CONT 33481da177e4SLinus TorvaldsCAS2L_ENTER: 33491da177e4SLinus Torvalds bra.b ~+16 33501da177e4SLinus Torvalds 33511da177e4SLinus TorvaldsCAS2L_CONT: 33521da177e4SLinus Torvalds cmp.l %d0,%d2 # Dest1 - Compare1 33531da177e4SLinus Torvalds bne.b CAS2L_NOUPDATE 33541da177e4SLinus Torvalds cmp.l %d1,%d3 # Dest2 - Compare2 33551da177e4SLinus Torvalds bne.b CAS2L_NOUPDATE 33561da177e4SLinus Torvalds movs.l %d5,(%a1) # Update2[31:0] -> DEST2 33571da177e4SLinus Torvalds bra.b CAS2L_UPDATE 33581da177e4SLinus Torvalds bra.b ~+16 33591da177e4SLinus Torvalds 33601da177e4SLinus TorvaldsCAS2L_UPDATE: 33611da177e4SLinus Torvalds movc %a3,%buscr # assert LOCKE* 33621da177e4SLinus Torvalds movs.l %d4,(%a0) # Update1[31:0] -> DEST1 33631da177e4SLinus Torvalds movc %a4,%buscr # unlock the bus 33641da177e4SLinus Torvalds bra.b cas2l_update_done 33651da177e4SLinus Torvalds bra.b ~+16 33661da177e4SLinus Torvalds 33671da177e4SLinus TorvaldsCAS2L_NOUPDATE: 33681da177e4SLinus Torvalds movc %a3,%buscr # assert LOCKE* 33691da177e4SLinus Torvalds movs.l %d0,(%a0) # Dest1[31:0] -> DEST1 33701da177e4SLinus Torvalds movc %a4,%buscr # unlock the bus 33711da177e4SLinus Torvalds bra.b cas2l_noupdate_done 33721da177e4SLinus Torvalds bra.b ~+16 33731da177e4SLinus Torvalds 33741da177e4SLinus TorvaldsCAS2L_FILLER: 33751da177e4SLinus Torvalds nop 33761da177e4SLinus Torvalds nop 33771da177e4SLinus Torvalds nop 33781da177e4SLinus Torvalds nop 33791da177e4SLinus Torvalds nop 33801da177e4SLinus Torvalds nop 33811da177e4SLinus Torvalds nop 33821da177e4SLinus Torvalds bra.b CAS2L_START 33831da177e4SLinus Torvalds 33841da177e4SLinus Torvalds#### 33851da177e4SLinus Torvalds 33861da177e4SLinus Torvalds################################################################# 33871da177e4SLinus Torvalds# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON # 33881da177e4SLinus Torvalds# ENTERING _isp_cas2(). # 33891da177e4SLinus Torvalds# # 33901da177e4SLinus Torvalds# D0 = destination[31:0] operand 1 # 33911da177e4SLinus Torvalds# D1 = destination[31:0] operand 2 # 33921da177e4SLinus Torvalds# D2 = cmp[31:0] operand 1 # 33931da177e4SLinus Torvalds# D3 = cmp[31:0] operand 2 # 33941da177e4SLinus Torvalds# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required # 33951da177e4SLinus Torvalds# D5 = xxxxxxxx # 33961da177e4SLinus Torvalds# D6 = xxxxxxxx # 33971da177e4SLinus Torvalds# D7 = xxxxxxxx # 33981da177e4SLinus Torvalds# A0 = xxxxxxxx # 33991da177e4SLinus Torvalds# A1 = xxxxxxxx # 34001da177e4SLinus Torvalds# A2 = xxxxxxxx # 34011da177e4SLinus Torvalds# A3 = xxxxxxxx # 34021da177e4SLinus Torvalds# A4 = xxxxxxxx # 34031da177e4SLinus Torvalds# A5 = xxxxxxxx # 34041da177e4SLinus Torvalds# A6 = frame pointer # 34051da177e4SLinus Torvalds# A7 = stack pointer # 34061da177e4SLinus Torvalds################################################################# 34071da177e4SLinus Torvalds 34081da177e4SLinus Torvaldscas2l_noupdate_done: 34091da177e4SLinus Torvalds 34101da177e4SLinus Torvalds# restore previous SFC/DFC value. 34111da177e4SLinus Torvalds movc %d6,%sfc # restore old SFC 34121da177e4SLinus Torvalds movc %d6,%dfc # restore old DFC 34131da177e4SLinus Torvalds 34141da177e4SLinus Torvalds# restore previous interrupt mask level. 34151da177e4SLinus Torvalds mov.w %d7,%sr # restore old SR 34161da177e4SLinus Torvalds 34171da177e4SLinus Torvalds sf %d4 # indicate no update was done 34181da177e4SLinus Torvalds bra.l _isp_cas2_finish 34191da177e4SLinus Torvalds 34201da177e4SLinus Torvaldscas2l_update_done: 34211da177e4SLinus Torvalds 34221da177e4SLinus Torvalds# restore previous SFC/DFC value. 34231da177e4SLinus Torvalds movc %d6,%sfc # restore old SFC 34241da177e4SLinus Torvalds movc %d6,%dfc # restore old DFC 34251da177e4SLinus Torvalds 34261da177e4SLinus Torvalds# restore previous interrupt mask level. 34271da177e4SLinus Torvalds mov.w %d7,%sr # restore old SR 34281da177e4SLinus Torvalds 34291da177e4SLinus Torvalds st %d4 # indicate update was done 34301da177e4SLinus Torvalds bra.l _isp_cas2_finish 34311da177e4SLinus Torvalds#### 34321da177e4SLinus Torvalds 34331da177e4SLinus Torvalds align 0x10 34341da177e4SLinus TorvaldsCAS2L2_START: 34351da177e4SLinus Torvalds movc %a2,%buscr # assert LOCK* 34361da177e4SLinus Torvalds movs.l (%a1),%d1 # fetch Dest2[31:0] 34371da177e4SLinus Torvalds movs.l (%a0),%d0 # fetch Dest1[31:0] 34381da177e4SLinus Torvalds bra.b CAS2L2_CONT 34391da177e4SLinus TorvaldsCAS2L2_ENTER: 34401da177e4SLinus Torvalds bra.b ~+16 34411da177e4SLinus Torvalds 34421da177e4SLinus TorvaldsCAS2L2_CONT: 34431da177e4SLinus Torvalds cmp.l %d0,%d2 # Dest1 - Compare1 34441da177e4SLinus Torvalds bne.b CAS2L2_NOUPDATE 34451da177e4SLinus Torvalds cmp.l %d1,%d3 # Dest2 - Compare2 34461da177e4SLinus Torvalds bne.b CAS2L2_NOUPDATE 34471da177e4SLinus Torvalds movs.l %d5,(%a1) # Update2[31:0] -> Dest2 34481da177e4SLinus Torvalds bra.b CAS2L2_UPDATE 34491da177e4SLinus Torvalds bra.b ~+16 34501da177e4SLinus Torvalds 34511da177e4SLinus TorvaldsCAS2L2_UPDATE: 34521da177e4SLinus Torvalds swap %d4 # get Update1[31:16] 34531da177e4SLinus Torvalds movs.w %d4,(%a0)+ # Update1[31:16] -> DEST1 34541da177e4SLinus Torvalds movc %a3,%buscr # assert LOCKE* 34551da177e4SLinus Torvalds swap %d4 # get Update1[15:0] 34561da177e4SLinus Torvalds bra.b CAS2L2_UPDATE2 34571da177e4SLinus Torvalds bra.b ~+16 34581da177e4SLinus Torvalds 34591da177e4SLinus TorvaldsCAS2L2_UPDATE2: 34601da177e4SLinus Torvalds movs.w %d4,(%a0) # Update1[15:0] -> DEST1+0x2 34611da177e4SLinus Torvalds movc %a4,%buscr # unlock the bus 34621da177e4SLinus Torvalds bra.w cas2l_update_done 34631da177e4SLinus Torvalds nop 34641da177e4SLinus Torvalds bra.b ~+16 34651da177e4SLinus Torvalds 34661da177e4SLinus TorvaldsCAS2L2_NOUPDATE: 34671da177e4SLinus Torvalds swap %d0 # get Dest1[31:16] 34681da177e4SLinus Torvalds movs.w %d0,(%a0)+ # Dest1[31:16] -> DEST1 34691da177e4SLinus Torvalds movc %a3,%buscr # assert LOCKE* 34701da177e4SLinus Torvalds swap %d0 # get Dest1[15:0] 34711da177e4SLinus Torvalds bra.b CAS2L2_NOUPDATE2 34721da177e4SLinus Torvalds bra.b ~+16 34731da177e4SLinus Torvalds 34741da177e4SLinus TorvaldsCAS2L2_NOUPDATE2: 34751da177e4SLinus Torvalds movs.w %d0,(%a0) # Dest1[15:0] -> DEST1+0x2 34761da177e4SLinus Torvalds movc %a4,%buscr # unlock the bus 34771da177e4SLinus Torvalds bra.w cas2l_noupdate_done 34781da177e4SLinus Torvalds nop 34791da177e4SLinus Torvalds bra.b ~+16 34801da177e4SLinus Torvalds 34811da177e4SLinus TorvaldsCAS2L2_FILLER: 34821da177e4SLinus Torvalds nop 34831da177e4SLinus Torvalds nop 34841da177e4SLinus Torvalds nop 34851da177e4SLinus Torvalds nop 34861da177e4SLinus Torvalds nop 34871da177e4SLinus Torvalds nop 34881da177e4SLinus Torvalds nop 34891da177e4SLinus Torvalds bra.b CAS2L2_START 34901da177e4SLinus Torvalds 34911da177e4SLinus Torvalds################################# 34921da177e4SLinus Torvalds 34931da177e4SLinus Torvalds align 0x10 34941da177e4SLinus TorvaldsCAS2L3_START: 34951da177e4SLinus Torvalds movc %a2,%buscr # assert LOCK* 34961da177e4SLinus Torvalds movs.l (%a1),%d1 # fetch Dest2[31:0] 34971da177e4SLinus Torvalds movs.l (%a0),%d0 # fetch Dest1[31:0] 34981da177e4SLinus Torvalds bra.b CAS2L3_CONT 34991da177e4SLinus TorvaldsCAS2L3_ENTER: 35001da177e4SLinus Torvalds bra.b ~+16 35011da177e4SLinus Torvalds 35021da177e4SLinus TorvaldsCAS2L3_CONT: 35031da177e4SLinus Torvalds cmp.l %d0,%d2 # Dest1 - Compare1 35041da177e4SLinus Torvalds bne.b CAS2L3_NOUPDATE 35051da177e4SLinus Torvalds cmp.l %d1,%d3 # Dest2 - Compare2 35061da177e4SLinus Torvalds bne.b CAS2L3_NOUPDATE 35071da177e4SLinus Torvalds movs.l %d5,(%a1) # Update2[31:0] -> DEST2 35081da177e4SLinus Torvalds bra.b CAS2L3_UPDATE 35091da177e4SLinus Torvalds bra.b ~+16 35101da177e4SLinus Torvalds 35111da177e4SLinus TorvaldsCAS2L3_UPDATE: 35121da177e4SLinus Torvalds rol.l &0x8,%d4 # get Update1[31:24] 35131da177e4SLinus Torvalds movs.b %d4,(%a0)+ # Update1[31:24] -> DEST1 35141da177e4SLinus Torvalds swap %d4 # get Update1[23:8] 35151da177e4SLinus Torvalds movs.w %d4,(%a0)+ # Update1[23:8] -> DEST1+0x1 35161da177e4SLinus Torvalds bra.b CAS2L3_UPDATE2 35171da177e4SLinus Torvalds bra.b ~+16 35181da177e4SLinus Torvalds 35191da177e4SLinus TorvaldsCAS2L3_UPDATE2: 35201da177e4SLinus Torvalds rol.l &0x8,%d4 # get Update1[7:0] 35211da177e4SLinus Torvalds movc %a3,%buscr # assert LOCKE* 35221da177e4SLinus Torvalds movs.b %d4,(%a0) # Update1[7:0] -> DEST1+0x3 35231da177e4SLinus Torvalds bra.b CAS2L3_UPDATE3 35241da177e4SLinus Torvalds nop 35251da177e4SLinus Torvalds bra.b ~+16 35261da177e4SLinus Torvalds 35271da177e4SLinus TorvaldsCAS2L3_UPDATE3: 35281da177e4SLinus Torvalds movc %a4,%buscr # unlock the bus 35291da177e4SLinus Torvalds bra.w cas2l_update_done 35301da177e4SLinus Torvalds nop 35311da177e4SLinus Torvalds nop 35321da177e4SLinus Torvalds nop 35331da177e4SLinus Torvalds bra.b ~+16 35341da177e4SLinus Torvalds 35351da177e4SLinus TorvaldsCAS2L3_NOUPDATE: 35361da177e4SLinus Torvalds rol.l &0x8,%d0 # get Dest1[31:24] 35371da177e4SLinus Torvalds movs.b %d0,(%a0)+ # Dest1[31:24] -> DEST1 35381da177e4SLinus Torvalds swap %d0 # get Dest1[23:8] 35391da177e4SLinus Torvalds movs.w %d0,(%a0)+ # Dest1[23:8] -> DEST1+0x1 35401da177e4SLinus Torvalds bra.b CAS2L3_NOUPDATE2 35411da177e4SLinus Torvalds bra.b ~+16 35421da177e4SLinus Torvalds 35431da177e4SLinus TorvaldsCAS2L3_NOUPDATE2: 35441da177e4SLinus Torvalds rol.l &0x8,%d0 # get Dest1[7:0] 35451da177e4SLinus Torvalds movc %a3,%buscr # assert LOCKE* 35461da177e4SLinus Torvalds movs.b %d0,(%a0) # Update1[7:0] -> DEST1+0x3 35471da177e4SLinus Torvalds bra.b CAS2L3_NOUPDATE3 35481da177e4SLinus Torvalds nop 35491da177e4SLinus Torvalds bra.b ~+16 35501da177e4SLinus Torvalds 35511da177e4SLinus TorvaldsCAS2L3_NOUPDATE3: 35521da177e4SLinus Torvalds movc %a4,%buscr # unlock the bus 35531da177e4SLinus Torvalds bra.w cas2l_noupdate_done 35541da177e4SLinus Torvalds nop 35551da177e4SLinus Torvalds nop 35561da177e4SLinus Torvalds nop 35571da177e4SLinus Torvalds bra.b ~+14 35581da177e4SLinus Torvalds 35591da177e4SLinus TorvaldsCAS2L3_FILLER: 35601da177e4SLinus Torvalds nop 35611da177e4SLinus Torvalds nop 35621da177e4SLinus Torvalds nop 35631da177e4SLinus Torvalds nop 35641da177e4SLinus Torvalds nop 35651da177e4SLinus Torvalds nop 35661da177e4SLinus Torvalds bra.w CAS2L3_START 35671da177e4SLinus Torvalds 35681da177e4SLinus Torvalds############################################################# 35691da177e4SLinus Torvalds############################################################# 35701da177e4SLinus Torvalds 35711da177e4SLinus Torvaldscas2w: 35721da177e4SLinus Torvalds mov.l %a0,%a2 # copy ADDR1 35731da177e4SLinus Torvalds mov.l %a1,%a3 # copy ADDR2 35741da177e4SLinus Torvalds mov.l %a0,%a4 # copy ADDR1 35751da177e4SLinus Torvalds mov.l %a1,%a5 # copy ADDR2 35761da177e4SLinus Torvalds 35771da177e4SLinus Torvalds addq.l &0x1,%a4 # ADDR1+1 35781da177e4SLinus Torvalds addq.l &0x1,%a5 # ADDR2+1 35791da177e4SLinus Torvalds mov.l %a2,%d1 # ADDR1 35801da177e4SLinus Torvalds 35811da177e4SLinus Torvalds# mask interrupt levels 0-6. save old mask value. 35821da177e4SLinus Torvalds mov.w %sr,%d7 # save current SR 35831da177e4SLinus Torvalds ori.w &0x0700,%sr # inhibit interrupts 35841da177e4SLinus Torvalds 35851da177e4SLinus Torvalds# load the SFC and DFC with the appropriate mode. 35861da177e4SLinus Torvalds movc %sfc,%d6 # save old SFC/DFC 35871da177e4SLinus Torvalds movc %d0,%sfc # store new SFC 35881da177e4SLinus Torvalds movc %d0,%dfc # store new DFC 35891da177e4SLinus Torvalds 35901da177e4SLinus Torvalds# pre-load the operand ATC. no page faults should occur because 35911da177e4SLinus Torvalds# _real_lock_page() should have taken care of this. 35921da177e4SLinus Torvalds plpaw (%a2) # load atc for ADDR1 35931da177e4SLinus Torvalds plpaw (%a4) # load atc for ADDR1+1 35941da177e4SLinus Torvalds plpaw (%a3) # load atc for ADDR2 35951da177e4SLinus Torvalds plpaw (%a5) # load atc for ADDR2+1 35961da177e4SLinus Torvalds 35971da177e4SLinus Torvalds# push the operand cache lines from the cache if they exist. 35981da177e4SLinus Torvalds cpushl %dc,(%a2) # push line for ADDR1 35991da177e4SLinus Torvalds cpushl %dc,(%a4) # push line for ADDR1+1 36001da177e4SLinus Torvalds cpushl %dc,(%a3) # push line for ADDR2 36011da177e4SLinus Torvalds cpushl %dc,(%a5) # push line for ADDR2+1 36021da177e4SLinus Torvalds 36031da177e4SLinus Torvalds mov.l %d1,%a2 # ADDR1 36041da177e4SLinus Torvalds addq.l &0x3,%d1 36051da177e4SLinus Torvalds mov.l %d1,%a4 # ADDR1+3 36061da177e4SLinus Torvalds# if ADDR1 was ATC resident before the above "plpaw" and was executed 36071da177e4SLinus Torvalds# and it was the next entry scheduled for replacement and ADDR2 36081da177e4SLinus Torvalds# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1 36091da177e4SLinus Torvalds# entries from the ATC. so, we do a second set of "plpa"s. 36101da177e4SLinus Torvalds plpar (%a2) # load atc for ADDR1 36111da177e4SLinus Torvalds plpar (%a4) # load atc for ADDR1+3 36121da177e4SLinus Torvalds 36131da177e4SLinus Torvalds# load the BUSCR values. 36141da177e4SLinus Torvalds mov.l &0x80000000,%a2 # assert LOCK* buscr value 36151da177e4SLinus Torvalds mov.l &0xa0000000,%a3 # assert LOCKE* buscr value 36161da177e4SLinus Torvalds mov.l &0x00000000,%a4 # buscr unlock value 36171da177e4SLinus Torvalds 36181da177e4SLinus Torvalds# there are two possible mis-aligned cases for word cas. they 36191da177e4SLinus Torvalds# are separated because the final write which asserts LOCKE* must 36201da177e4SLinus Torvalds# be aligned. 36211da177e4SLinus Torvalds mov.l %a0,%d0 # is ADDR1 misaligned? 36221da177e4SLinus Torvalds btst &0x0,%d0 36231da177e4SLinus Torvalds bne.w CAS2W2_ENTER # yes 36241da177e4SLinus Torvalds bra.b CAS2W_ENTER # no 36251da177e4SLinus Torvalds 36261da177e4SLinus Torvalds# 36271da177e4SLinus Torvalds# D0 = dst operand 1 <- 36281da177e4SLinus Torvalds# D1 = dst operand 2 <- 36291da177e4SLinus Torvalds# D2 = cmp operand 1 36301da177e4SLinus Torvalds# D3 = cmp operand 2 36311da177e4SLinus Torvalds# D4 = update oper 1 36321da177e4SLinus Torvalds# D5 = update oper 2 36331da177e4SLinus Torvalds# D6 = old SFC/DFC 36341da177e4SLinus Torvalds# D7 = old SR 36351da177e4SLinus Torvalds# A0 = ADDR1 36361da177e4SLinus Torvalds# A1 = ADDR2 36371da177e4SLinus Torvalds# A2 = bus LOCK* value 36381da177e4SLinus Torvalds# A3 = bus LOCKE* value 36391da177e4SLinus Torvalds# A4 = bus unlock value 36401da177e4SLinus Torvalds# A5 = xxxxxxxx 36411da177e4SLinus Torvalds# 36421da177e4SLinus Torvalds align 0x10 36431da177e4SLinus TorvaldsCAS2W_START: 36441da177e4SLinus Torvalds movc %a2,%buscr # assert LOCK* 36451da177e4SLinus Torvalds movs.w (%a1),%d1 # fetch Dest2[15:0] 36461da177e4SLinus Torvalds movs.w (%a0),%d0 # fetch Dest1[15:0] 36471da177e4SLinus Torvalds bra.b CAS2W_CONT2 36481da177e4SLinus TorvaldsCAS2W_ENTER: 36491da177e4SLinus Torvalds bra.b ~+16 36501da177e4SLinus Torvalds 36511da177e4SLinus TorvaldsCAS2W_CONT2: 36521da177e4SLinus Torvalds cmp.w %d0,%d2 # Dest1 - Compare1 36531da177e4SLinus Torvalds bne.b CAS2W_NOUPDATE 36541da177e4SLinus Torvalds cmp.w %d1,%d3 # Dest2 - Compare2 36551da177e4SLinus Torvalds bne.b CAS2W_NOUPDATE 36561da177e4SLinus Torvalds movs.w %d5,(%a1) # Update2[15:0] -> DEST2 36571da177e4SLinus Torvalds bra.b CAS2W_UPDATE 36581da177e4SLinus Torvalds bra.b ~+16 36591da177e4SLinus Torvalds 36601da177e4SLinus TorvaldsCAS2W_UPDATE: 36611da177e4SLinus Torvalds movc %a3,%buscr # assert LOCKE* 36621da177e4SLinus Torvalds movs.w %d4,(%a0) # Update1[15:0] -> DEST1 36631da177e4SLinus Torvalds movc %a4,%buscr # unlock the bus 36641da177e4SLinus Torvalds bra.b cas2w_update_done 36651da177e4SLinus Torvalds bra.b ~+16 36661da177e4SLinus Torvalds 36671da177e4SLinus TorvaldsCAS2W_NOUPDATE: 36681da177e4SLinus Torvalds movc %a3,%buscr # assert LOCKE* 36691da177e4SLinus Torvalds movs.w %d0,(%a0) # Dest1[15:0] -> DEST1 36701da177e4SLinus Torvalds movc %a4,%buscr # unlock the bus 36711da177e4SLinus Torvalds bra.b cas2w_noupdate_done 36721da177e4SLinus Torvalds bra.b ~+16 36731da177e4SLinus Torvalds 36741da177e4SLinus TorvaldsCAS2W_FILLER: 36751da177e4SLinus Torvalds nop 36761da177e4SLinus Torvalds nop 36771da177e4SLinus Torvalds nop 36781da177e4SLinus Torvalds nop 36791da177e4SLinus Torvalds nop 36801da177e4SLinus Torvalds nop 36811da177e4SLinus Torvalds nop 36821da177e4SLinus Torvalds bra.b CAS2W_START 36831da177e4SLinus Torvalds 36841da177e4SLinus Torvalds#### 36851da177e4SLinus Torvalds 36861da177e4SLinus Torvalds################################################################# 36871da177e4SLinus Torvalds# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON # 36881da177e4SLinus Torvalds# ENTERING _isp_cas2(). # 36891da177e4SLinus Torvalds# # 36901da177e4SLinus Torvalds# D0 = destination[15:0] operand 1 # 36911da177e4SLinus Torvalds# D1 = destination[15:0] operand 2 # 36921da177e4SLinus Torvalds# D2 = cmp[15:0] operand 1 # 36931da177e4SLinus Torvalds# D3 = cmp[15:0] operand 2 # 36941da177e4SLinus Torvalds# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required # 36951da177e4SLinus Torvalds# D5 = xxxxxxxx # 36961da177e4SLinus Torvalds# D6 = xxxxxxxx # 36971da177e4SLinus Torvalds# D7 = xxxxxxxx # 36981da177e4SLinus Torvalds# A0 = xxxxxxxx # 36991da177e4SLinus Torvalds# A1 = xxxxxxxx # 37001da177e4SLinus Torvalds# A2 = xxxxxxxx # 37011da177e4SLinus Torvalds# A3 = xxxxxxxx # 37021da177e4SLinus Torvalds# A4 = xxxxxxxx # 37031da177e4SLinus Torvalds# A5 = xxxxxxxx # 37041da177e4SLinus Torvalds# A6 = frame pointer # 37051da177e4SLinus Torvalds# A7 = stack pointer # 37061da177e4SLinus Torvalds################################################################# 37071da177e4SLinus Torvalds 37081da177e4SLinus Torvaldscas2w_noupdate_done: 37091da177e4SLinus Torvalds 37101da177e4SLinus Torvalds# restore previous SFC/DFC value. 37111da177e4SLinus Torvalds movc %d6,%sfc # restore old SFC 37121da177e4SLinus Torvalds movc %d6,%dfc # restore old DFC 37131da177e4SLinus Torvalds 37141da177e4SLinus Torvalds# restore previous interrupt mask level. 37151da177e4SLinus Torvalds mov.w %d7,%sr # restore old SR 37161da177e4SLinus Torvalds 37171da177e4SLinus Torvalds sf %d4 # indicate no update was done 37181da177e4SLinus Torvalds bra.l _isp_cas2_finish 37191da177e4SLinus Torvalds 37201da177e4SLinus Torvaldscas2w_update_done: 37211da177e4SLinus Torvalds 37221da177e4SLinus Torvalds# restore previous SFC/DFC value. 37231da177e4SLinus Torvalds movc %d6,%sfc # restore old SFC 37241da177e4SLinus Torvalds movc %d6,%dfc # restore old DFC 37251da177e4SLinus Torvalds 37261da177e4SLinus Torvalds# restore previous interrupt mask level. 37271da177e4SLinus Torvalds mov.w %d7,%sr # restore old SR 37281da177e4SLinus Torvalds 37291da177e4SLinus Torvalds st %d4 # indicate update was done 37301da177e4SLinus Torvalds bra.l _isp_cas2_finish 37311da177e4SLinus Torvalds#### 37321da177e4SLinus Torvalds 37331da177e4SLinus Torvalds align 0x10 37341da177e4SLinus TorvaldsCAS2W2_START: 37351da177e4SLinus Torvalds movc %a2,%buscr # assert LOCK* 37361da177e4SLinus Torvalds movs.w (%a1),%d1 # fetch Dest2[15:0] 37371da177e4SLinus Torvalds movs.w (%a0),%d0 # fetch Dest1[15:0] 37381da177e4SLinus Torvalds bra.b CAS2W2_CONT2 37391da177e4SLinus TorvaldsCAS2W2_ENTER: 37401da177e4SLinus Torvalds bra.b ~+16 37411da177e4SLinus Torvalds 37421da177e4SLinus TorvaldsCAS2W2_CONT2: 37431da177e4SLinus Torvalds cmp.w %d0,%d2 # Dest1 - Compare1 37441da177e4SLinus Torvalds bne.b CAS2W2_NOUPDATE 37451da177e4SLinus Torvalds cmp.w %d1,%d3 # Dest2 - Compare2 37461da177e4SLinus Torvalds bne.b CAS2W2_NOUPDATE 37471da177e4SLinus Torvalds movs.w %d5,(%a1) # Update2[15:0] -> DEST2 37481da177e4SLinus Torvalds bra.b CAS2W2_UPDATE 37491da177e4SLinus Torvalds bra.b ~+16 37501da177e4SLinus Torvalds 37511da177e4SLinus TorvaldsCAS2W2_UPDATE: 37521da177e4SLinus Torvalds ror.l &0x8,%d4 # get Update1[15:8] 37531da177e4SLinus Torvalds movs.b %d4,(%a0)+ # Update1[15:8] -> DEST1 37541da177e4SLinus Torvalds movc %a3,%buscr # assert LOCKE* 37551da177e4SLinus Torvalds rol.l &0x8,%d4 # get Update1[7:0] 37561da177e4SLinus Torvalds bra.b CAS2W2_UPDATE2 37571da177e4SLinus Torvalds bra.b ~+16 37581da177e4SLinus Torvalds 37591da177e4SLinus TorvaldsCAS2W2_UPDATE2: 37601da177e4SLinus Torvalds movs.b %d4,(%a0) # Update1[7:0] -> DEST1+0x1 37611da177e4SLinus Torvalds movc %a4,%buscr # unlock the bus 37621da177e4SLinus Torvalds bra.w cas2w_update_done 37631da177e4SLinus Torvalds nop 37641da177e4SLinus Torvalds bra.b ~+16 37651da177e4SLinus Torvalds 37661da177e4SLinus TorvaldsCAS2W2_NOUPDATE: 37671da177e4SLinus Torvalds ror.l &0x8,%d0 # get Dest1[15:8] 37681da177e4SLinus Torvalds movs.b %d0,(%a0)+ # Dest1[15:8] -> DEST1 37691da177e4SLinus Torvalds movc %a3,%buscr # assert LOCKE* 37701da177e4SLinus Torvalds rol.l &0x8,%d0 # get Dest1[7:0] 37711da177e4SLinus Torvalds bra.b CAS2W2_NOUPDATE2 37721da177e4SLinus Torvalds bra.b ~+16 37731da177e4SLinus Torvalds 37741da177e4SLinus TorvaldsCAS2W2_NOUPDATE2: 37751da177e4SLinus Torvalds movs.b %d0,(%a0) # Dest1[7:0] -> DEST1+0x1 37761da177e4SLinus Torvalds movc %a4,%buscr # unlock the bus 37771da177e4SLinus Torvalds bra.w cas2w_noupdate_done 37781da177e4SLinus Torvalds nop 37791da177e4SLinus Torvalds bra.b ~+16 37801da177e4SLinus Torvalds 37811da177e4SLinus TorvaldsCAS2W2_FILLER: 37821da177e4SLinus Torvalds nop 37831da177e4SLinus Torvalds nop 37841da177e4SLinus Torvalds nop 37851da177e4SLinus Torvalds nop 37861da177e4SLinus Torvalds nop 37871da177e4SLinus Torvalds nop 37881da177e4SLinus Torvalds nop 37891da177e4SLinus Torvalds bra.b CAS2W2_START 37901da177e4SLinus Torvalds 37911da177e4SLinus Torvalds# ###### ## ###### 37921da177e4SLinus Torvalds# # # # # 37931da177e4SLinus Torvalds# # ###### ###### 37941da177e4SLinus Torvalds# # # # # 37951da177e4SLinus Torvalds# ###### # # ###### 37961da177e4SLinus Torvalds 37971da177e4SLinus Torvalds######################################################################### 37981da177e4SLinus Torvalds# XDEF **************************************************************** # 37991da177e4SLinus Torvalds# _isp_cas(): "core" emulation code for the cas instruction # 38001da177e4SLinus Torvalds# # 38011da177e4SLinus Torvalds# XREF **************************************************************** # 38021da177e4SLinus Torvalds# _isp_cas_finish() - only exit point for this emulation code; # 38031da177e4SLinus Torvalds# do clean-up # 38041da177e4SLinus Torvalds# # 38051da177e4SLinus Torvalds# INPUT *************************************************************** # 38061da177e4SLinus Torvalds# *see entry chart below* # 38071da177e4SLinus Torvalds# # 38081da177e4SLinus Torvalds# OUTPUT ************************************************************** # 38091da177e4SLinus Torvalds# *see exit chart below* # 38101da177e4SLinus Torvalds# # 38111da177e4SLinus Torvalds# ALGORITHM *********************************************************** # 38121da177e4SLinus Torvalds# (1) Make several copies of the effective address. # 38131da177e4SLinus Torvalds# (2) Save current SR; Then mask off all maskable interrupts. # 38141da177e4SLinus Torvalds# (3) Save current DFC/SFC (ASSUMED TO BE EQUAL!!!); Then set # 38151da177e4SLinus Torvalds# SFC/DFC according to whether exception occurred in user or # 38161da177e4SLinus Torvalds# supervisor mode. # 38174e0385ddSMasahiro Yamada# (4) Use "plpaw" instruction to pre-load ATC with effective # 38181da177e4SLinus Torvalds# address page(s). THIS SHOULD NOT FAULT!!! The relevant # 38191da177e4SLinus Torvalds# page(s) should have been made resident prior to entering # 38201da177e4SLinus Torvalds# this routine. # 38211da177e4SLinus Torvalds# (5) Push the operand lines from the cache w/ "cpushl". # 38221da177e4SLinus Torvalds# In the 68040, this was done within the locked region. In # 38231da177e4SLinus Torvalds# the 68060, it is done outside of the locked region. # 38241da177e4SLinus Torvalds# (6) Pre-fetch the core emulation instructions by executing one # 38251da177e4SLinus Torvalds# branch within each physical line (16 bytes) of the code # 38261da177e4SLinus Torvalds# before actually executing the code. # 38271da177e4SLinus Torvalds# (7) Load the BUSCR with the bus lock value. # 38281da177e4SLinus Torvalds# (8) Fetch the source operand. # 38291da177e4SLinus Torvalds# (9) Do the compare. If equal, go to step (12). # 38301da177e4SLinus Torvalds# (10)Unequal. No update occurs. But, we do write the DST op back # 38311da177e4SLinus Torvalds# to itself (as w/ the '040) so we can gracefully unlock # 38321da177e4SLinus Torvalds# the bus (and assert LOCKE*) using BUSCR and the final move. # 38331da177e4SLinus Torvalds# (11)Exit. # 38341da177e4SLinus Torvalds# (12)Write update operand to the DST location. Use BUSCR to # 38351da177e4SLinus Torvalds# assert LOCKE* for the final write operation. # 38361da177e4SLinus Torvalds# (13)Exit. # 38371da177e4SLinus Torvalds# # 38381da177e4SLinus Torvalds# The algorithm is actually implemented slightly differently # 38391da177e4SLinus Torvalds# depending on the size of the operation and the misalignment of the # 38401da177e4SLinus Torvalds# operand. A misaligned operand must be written in aligned chunks or # 38411da177e4SLinus Torvalds# else the BUSCR register control gets confused. # 38421da177e4SLinus Torvalds# # 38431da177e4SLinus Torvalds######################################################################### 38441da177e4SLinus Torvalds 38451da177e4SLinus Torvalds######################################################### 38461da177e4SLinus Torvalds# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON # 38471da177e4SLinus Torvalds# ENTERING _isp_cas(). # 38481da177e4SLinus Torvalds# # 38491da177e4SLinus Torvalds# D0 = xxxxxxxx # 38501da177e4SLinus Torvalds# D1 = xxxxxxxx # 38511da177e4SLinus Torvalds# D2 = update operand # 38521da177e4SLinus Torvalds# D3 = xxxxxxxx # 38531da177e4SLinus Torvalds# D4 = compare operand # 38541da177e4SLinus Torvalds# D5 = xxxxxxxx # 38551da177e4SLinus Torvalds# D6 = supervisor ('xxxxxxff) or user mode ('xxxxxx00) # 38561da177e4SLinus Torvalds# D7 = longword ('xxxxxxff) or word size ('xxxxxx00) # 38571da177e4SLinus Torvalds# A0 = ADDR # 38581da177e4SLinus Torvalds# A1 = xxxxxxxx # 38591da177e4SLinus Torvalds# A2 = xxxxxxxx # 38601da177e4SLinus Torvalds# A3 = xxxxxxxx # 38611da177e4SLinus Torvalds# A4 = xxxxxxxx # 38621da177e4SLinus Torvalds# A5 = xxxxxxxx # 38631da177e4SLinus Torvalds# A6 = frame pointer # 38641da177e4SLinus Torvalds# A7 = stack pointer # 38651da177e4SLinus Torvalds######################################################### 38661da177e4SLinus Torvalds 38671da177e4SLinus Torvalds global _isp_cas 38681da177e4SLinus Torvalds_isp_cas: 38691da177e4SLinus Torvalds tst.b %d6 # user or supervisor mode? 38701da177e4SLinus Torvalds bne.b cas_super # supervisor 38711da177e4SLinus Torvaldscas_user: 38721da177e4SLinus Torvalds movq.l &0x1,%d0 # load user data fc 38731da177e4SLinus Torvalds bra.b cas_cont 38741da177e4SLinus Torvaldscas_super: 38751da177e4SLinus Torvalds movq.l &0x5,%d0 # load supervisor data fc 38761da177e4SLinus Torvalds 38771da177e4SLinus Torvaldscas_cont: 38781da177e4SLinus Torvalds tst.b %d7 # word or longword? 38791da177e4SLinus Torvalds bne.w casl # longword 38801da177e4SLinus Torvalds 38811da177e4SLinus Torvalds#### 38821da177e4SLinus Torvaldscasw: 38831da177e4SLinus Torvalds mov.l %a0,%a1 # make copy for plpaw1 38841da177e4SLinus Torvalds mov.l %a0,%a2 # make copy for plpaw2 38851da177e4SLinus Torvalds addq.l &0x1,%a2 # plpaw2 points to end of word 38861da177e4SLinus Torvalds 38871da177e4SLinus Torvalds mov.l %d2,%d3 # d3 = update[7:0] 38881da177e4SLinus Torvalds lsr.w &0x8,%d2 # d2 = update[15:8] 38891da177e4SLinus Torvalds 38901da177e4SLinus Torvalds# mask interrupt levels 0-6. save old mask value. 38911da177e4SLinus Torvalds mov.w %sr,%d7 # save current SR 38921da177e4SLinus Torvalds ori.w &0x0700,%sr # inhibit interrupts 38931da177e4SLinus Torvalds 38941da177e4SLinus Torvalds# load the SFC and DFC with the appropriate mode. 38951da177e4SLinus Torvalds movc %sfc,%d6 # save old SFC/DFC 38961da177e4SLinus Torvalds movc %d0,%sfc # load new sfc 38971da177e4SLinus Torvalds movc %d0,%dfc # load new dfc 38981da177e4SLinus Torvalds 38991da177e4SLinus Torvalds# pre-load the operand ATC. no page faults should occur here because 39001da177e4SLinus Torvalds# _real_lock_page() should have taken care of this. 39011da177e4SLinus Torvalds plpaw (%a1) # load atc for ADDR 39021da177e4SLinus Torvalds plpaw (%a2) # load atc for ADDR+1 39031da177e4SLinus Torvalds 39041da177e4SLinus Torvalds# push the operand lines from the cache if they exist. 39051da177e4SLinus Torvalds cpushl %dc,(%a1) # push dirty data 39061da177e4SLinus Torvalds cpushl %dc,(%a2) # push dirty data 39071da177e4SLinus Torvalds 39081da177e4SLinus Torvalds# load the BUSCR values. 39091da177e4SLinus Torvalds mov.l &0x80000000,%a1 # assert LOCK* buscr value 39101da177e4SLinus Torvalds mov.l &0xa0000000,%a2 # assert LOCKE* buscr value 39111da177e4SLinus Torvalds mov.l &0x00000000,%a3 # buscr unlock value 39121da177e4SLinus Torvalds 39131da177e4SLinus Torvalds# pre-load the instruction cache for the following algorithm. 39141da177e4SLinus Torvalds# this will minimize the number of cycles that LOCK* will be asserted. 39151da177e4SLinus Torvalds bra.b CASW_ENTER # start pre-loading icache 39161da177e4SLinus Torvalds 39171da177e4SLinus Torvalds# 39181da177e4SLinus Torvalds# D0 = dst operand <- 39191da177e4SLinus Torvalds# D1 = update[15:8] operand 39201da177e4SLinus Torvalds# D2 = update[7:0] operand 39211da177e4SLinus Torvalds# D3 = xxxxxxxx 39221da177e4SLinus Torvalds# D4 = compare[15:0] operand 39231da177e4SLinus Torvalds# D5 = xxxxxxxx 39241da177e4SLinus Torvalds# D6 = old SFC/DFC 39251da177e4SLinus Torvalds# D7 = old SR 39261da177e4SLinus Torvalds# A0 = ADDR 39271da177e4SLinus Torvalds# A1 = bus LOCK* value 39281da177e4SLinus Torvalds# A2 = bus LOCKE* value 39291da177e4SLinus Torvalds# A3 = bus unlock value 39301da177e4SLinus Torvalds# A4 = xxxxxxxx 39311da177e4SLinus Torvalds# A5 = xxxxxxxx 39321da177e4SLinus Torvalds# 39331da177e4SLinus Torvalds align 0x10 39341da177e4SLinus TorvaldsCASW_START: 39351da177e4SLinus Torvalds movc %a1,%buscr # assert LOCK* 39361da177e4SLinus Torvalds movs.w (%a0),%d0 # fetch Dest[15:0] 39371da177e4SLinus Torvalds cmp.w %d0,%d4 # Dest - Compare 39381da177e4SLinus Torvalds bne.b CASW_NOUPDATE 39391da177e4SLinus Torvalds bra.b CASW_UPDATE 39401da177e4SLinus TorvaldsCASW_ENTER: 39411da177e4SLinus Torvalds bra.b ~+16 39421da177e4SLinus Torvalds 39431da177e4SLinus TorvaldsCASW_UPDATE: 39441da177e4SLinus Torvalds movs.b %d2,(%a0)+ # Update[15:8] -> DEST 39451da177e4SLinus Torvalds movc %a2,%buscr # assert LOCKE* 39461da177e4SLinus Torvalds movs.b %d3,(%a0) # Update[7:0] -> DEST+0x1 39471da177e4SLinus Torvalds bra.b CASW_UPDATE2 39481da177e4SLinus Torvalds bra.b ~+16 39491da177e4SLinus Torvalds 39501da177e4SLinus TorvaldsCASW_UPDATE2: 39511da177e4SLinus Torvalds movc %a3,%buscr # unlock the bus 39521da177e4SLinus Torvalds bra.b casw_update_done 39531da177e4SLinus Torvalds nop 39541da177e4SLinus Torvalds nop 39551da177e4SLinus Torvalds nop 39561da177e4SLinus Torvalds nop 39571da177e4SLinus Torvalds bra.b ~+16 39581da177e4SLinus Torvalds 39591da177e4SLinus TorvaldsCASW_NOUPDATE: 39601da177e4SLinus Torvalds ror.l &0x8,%d0 # get Dest[15:8] 39611da177e4SLinus Torvalds movs.b %d0,(%a0)+ # Dest[15:8] -> DEST 39621da177e4SLinus Torvalds movc %a2,%buscr # assert LOCKE* 39631da177e4SLinus Torvalds rol.l &0x8,%d0 # get Dest[7:0] 39641da177e4SLinus Torvalds bra.b CASW_NOUPDATE2 39651da177e4SLinus Torvalds bra.b ~+16 39661da177e4SLinus Torvalds 39671da177e4SLinus TorvaldsCASW_NOUPDATE2: 39681da177e4SLinus Torvalds movs.b %d0,(%a0) # Dest[7:0] -> DEST+0x1 39691da177e4SLinus Torvalds movc %a3,%buscr # unlock the bus 39701da177e4SLinus Torvalds bra.b casw_noupdate_done 39711da177e4SLinus Torvalds nop 39721da177e4SLinus Torvalds nop 39731da177e4SLinus Torvalds bra.b ~+16 39741da177e4SLinus Torvalds 39751da177e4SLinus TorvaldsCASW_FILLER: 39761da177e4SLinus Torvalds nop 39771da177e4SLinus Torvalds nop 39781da177e4SLinus Torvalds nop 39791da177e4SLinus Torvalds nop 39801da177e4SLinus Torvalds nop 39811da177e4SLinus Torvalds nop 39821da177e4SLinus Torvalds nop 39831da177e4SLinus Torvalds bra.b CASW_START 39841da177e4SLinus Torvalds 39851da177e4SLinus Torvalds################################################################# 39861da177e4SLinus Torvalds# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON # 39871da177e4SLinus Torvalds# CALLING _isp_cas_finish(). # 39881da177e4SLinus Torvalds# # 39891da177e4SLinus Torvalds# D0 = destination[15:0] operand # 39901da177e4SLinus Torvalds# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required # 39911da177e4SLinus Torvalds# D2 = xxxxxxxx # 39921da177e4SLinus Torvalds# D3 = xxxxxxxx # 39931da177e4SLinus Torvalds# D4 = compare[15:0] operand # 39941da177e4SLinus Torvalds# D5 = xxxxxxxx # 39951da177e4SLinus Torvalds# D6 = xxxxxxxx # 39961da177e4SLinus Torvalds# D7 = xxxxxxxx # 39971da177e4SLinus Torvalds# A0 = xxxxxxxx # 39981da177e4SLinus Torvalds# A1 = xxxxxxxx # 39991da177e4SLinus Torvalds# A2 = xxxxxxxx # 40001da177e4SLinus Torvalds# A3 = xxxxxxxx # 40011da177e4SLinus Torvalds# A4 = xxxxxxxx # 40021da177e4SLinus Torvalds# A5 = xxxxxxxx # 40031da177e4SLinus Torvalds# A6 = frame pointer # 40041da177e4SLinus Torvalds# A7 = stack pointer # 40051da177e4SLinus Torvalds################################################################# 40061da177e4SLinus Torvalds 40071da177e4SLinus Torvaldscasw_noupdate_done: 40081da177e4SLinus Torvalds 40091da177e4SLinus Torvalds# restore previous SFC/DFC value. 40101da177e4SLinus Torvalds movc %d6,%sfc # restore old SFC 40111da177e4SLinus Torvalds movc %d6,%dfc # restore old DFC 40121da177e4SLinus Torvalds 40131da177e4SLinus Torvalds# restore previous interrupt mask level. 40141da177e4SLinus Torvalds mov.w %d7,%sr # restore old SR 40151da177e4SLinus Torvalds 40161da177e4SLinus Torvalds sf %d1 # indicate no update was done 40171da177e4SLinus Torvalds bra.l _isp_cas_finish 40181da177e4SLinus Torvalds 40191da177e4SLinus Torvaldscasw_update_done: 40201da177e4SLinus Torvalds 40211da177e4SLinus Torvalds# restore previous SFC/DFC value. 40221da177e4SLinus Torvalds movc %d6,%sfc # restore old SFC 40231da177e4SLinus Torvalds movc %d6,%dfc # restore old DFC 40241da177e4SLinus Torvalds 40251da177e4SLinus Torvalds# restore previous interrupt mask level. 40261da177e4SLinus Torvalds mov.w %d7,%sr # restore old SR 40271da177e4SLinus Torvalds 40281da177e4SLinus Torvalds st %d1 # indicate update was done 40291da177e4SLinus Torvalds bra.l _isp_cas_finish 40301da177e4SLinus Torvalds 40311da177e4SLinus Torvalds################ 40321da177e4SLinus Torvalds 40331da177e4SLinus Torvalds# there are two possible mis-aligned cases for longword cas. they 40341da177e4SLinus Torvalds# are separated because the final write which asserts LOCKE* must 40351da177e4SLinus Torvalds# be an aligned write. 40361da177e4SLinus Torvaldscasl: 40371da177e4SLinus Torvalds mov.l %a0,%a1 # make copy for plpaw1 40381da177e4SLinus Torvalds mov.l %a0,%a2 # make copy for plpaw2 40391da177e4SLinus Torvalds addq.l &0x3,%a2 # plpaw2 points to end of longword 40401da177e4SLinus Torvalds 40411da177e4SLinus Torvalds mov.l %a0,%d1 # byte or word misaligned? 40421da177e4SLinus Torvalds btst &0x0,%d1 40431da177e4SLinus Torvalds bne.w casl2 # byte misaligned 40441da177e4SLinus Torvalds 40451da177e4SLinus Torvalds mov.l %d2,%d3 # d3 = update[15:0] 40461da177e4SLinus Torvalds swap %d2 # d2 = update[31:16] 40471da177e4SLinus Torvalds 40481da177e4SLinus Torvalds# mask interrupts levels 0-6. save old mask value. 40491da177e4SLinus Torvalds mov.w %sr,%d7 # save current SR 40501da177e4SLinus Torvalds ori.w &0x0700,%sr # inhibit interrupts 40511da177e4SLinus Torvalds 40521da177e4SLinus Torvalds# load the SFC and DFC with the appropriate mode. 40531da177e4SLinus Torvalds movc %sfc,%d6 # save old SFC/DFC 40541da177e4SLinus Torvalds movc %d0,%sfc # load new sfc 40551da177e4SLinus Torvalds movc %d0,%dfc # load new dfc 40561da177e4SLinus Torvalds 40571da177e4SLinus Torvalds# pre-load the operand ATC. no page faults should occur here because 40581da177e4SLinus Torvalds# _real_lock_page() should have taken care of this. 40591da177e4SLinus Torvalds plpaw (%a1) # load atc for ADDR 40601da177e4SLinus Torvalds plpaw (%a2) # load atc for ADDR+3 40611da177e4SLinus Torvalds 40621da177e4SLinus Torvalds# push the operand lines from the cache if they exist. 40631da177e4SLinus Torvalds cpushl %dc,(%a1) # push dirty data 40641da177e4SLinus Torvalds cpushl %dc,(%a2) # push dirty data 40651da177e4SLinus Torvalds 40661da177e4SLinus Torvalds# load the BUSCR values. 40671da177e4SLinus Torvalds mov.l &0x80000000,%a1 # assert LOCK* buscr value 40681da177e4SLinus Torvalds mov.l &0xa0000000,%a2 # assert LOCKE* buscr value 40691da177e4SLinus Torvalds mov.l &0x00000000,%a3 # buscr unlock value 40701da177e4SLinus Torvalds 40711da177e4SLinus Torvalds bra.b CASL_ENTER # start pre-loading icache 40721da177e4SLinus Torvalds 40731da177e4SLinus Torvalds# 40741da177e4SLinus Torvalds# D0 = dst operand <- 40751da177e4SLinus Torvalds# D1 = xxxxxxxx 40761da177e4SLinus Torvalds# D2 = update[31:16] operand 40771da177e4SLinus Torvalds# D3 = update[15:0] operand 40781da177e4SLinus Torvalds# D4 = compare[31:0] operand 40791da177e4SLinus Torvalds# D5 = xxxxxxxx 40801da177e4SLinus Torvalds# D6 = old SFC/DFC 40811da177e4SLinus Torvalds# D7 = old SR 40821da177e4SLinus Torvalds# A0 = ADDR 40831da177e4SLinus Torvalds# A1 = bus LOCK* value 40841da177e4SLinus Torvalds# A2 = bus LOCKE* value 40851da177e4SLinus Torvalds# A3 = bus unlock value 40861da177e4SLinus Torvalds# A4 = xxxxxxxx 40871da177e4SLinus Torvalds# A5 = xxxxxxxx 40881da177e4SLinus Torvalds# 40891da177e4SLinus Torvalds align 0x10 40901da177e4SLinus TorvaldsCASL_START: 40911da177e4SLinus Torvalds movc %a1,%buscr # assert LOCK* 40921da177e4SLinus Torvalds movs.l (%a0),%d0 # fetch Dest[31:0] 40931da177e4SLinus Torvalds cmp.l %d0,%d4 # Dest - Compare 40941da177e4SLinus Torvalds bne.b CASL_NOUPDATE 40951da177e4SLinus Torvalds bra.b CASL_UPDATE 40961da177e4SLinus TorvaldsCASL_ENTER: 40971da177e4SLinus Torvalds bra.b ~+16 40981da177e4SLinus Torvalds 40991da177e4SLinus TorvaldsCASL_UPDATE: 41001da177e4SLinus Torvalds movs.w %d2,(%a0)+ # Update[31:16] -> DEST 41011da177e4SLinus Torvalds movc %a2,%buscr # assert LOCKE* 41021da177e4SLinus Torvalds movs.w %d3,(%a0) # Update[15:0] -> DEST+0x2 41031da177e4SLinus Torvalds bra.b CASL_UPDATE2 41041da177e4SLinus Torvalds bra.b ~+16 41051da177e4SLinus Torvalds 41061da177e4SLinus TorvaldsCASL_UPDATE2: 41071da177e4SLinus Torvalds movc %a3,%buscr # unlock the bus 41081da177e4SLinus Torvalds bra.b casl_update_done 41091da177e4SLinus Torvalds nop 41101da177e4SLinus Torvalds nop 41111da177e4SLinus Torvalds nop 41121da177e4SLinus Torvalds nop 41131da177e4SLinus Torvalds bra.b ~+16 41141da177e4SLinus Torvalds 41151da177e4SLinus TorvaldsCASL_NOUPDATE: 41161da177e4SLinus Torvalds swap %d0 # get Dest[31:16] 41171da177e4SLinus Torvalds movs.w %d0,(%a0)+ # Dest[31:16] -> DEST 41181da177e4SLinus Torvalds swap %d0 # get Dest[15:0] 41191da177e4SLinus Torvalds movc %a2,%buscr # assert LOCKE* 41201da177e4SLinus Torvalds bra.b CASL_NOUPDATE2 41211da177e4SLinus Torvalds bra.b ~+16 41221da177e4SLinus Torvalds 41231da177e4SLinus TorvaldsCASL_NOUPDATE2: 41241da177e4SLinus Torvalds movs.w %d0,(%a0) # Dest[15:0] -> DEST+0x2 41251da177e4SLinus Torvalds movc %a3,%buscr # unlock the bus 41261da177e4SLinus Torvalds bra.b casl_noupdate_done 41271da177e4SLinus Torvalds nop 41281da177e4SLinus Torvalds nop 41291da177e4SLinus Torvalds bra.b ~+16 41301da177e4SLinus Torvalds 41311da177e4SLinus TorvaldsCASL_FILLER: 41321da177e4SLinus Torvalds nop 41331da177e4SLinus Torvalds nop 41341da177e4SLinus Torvalds nop 41351da177e4SLinus Torvalds nop 41361da177e4SLinus Torvalds nop 41371da177e4SLinus Torvalds nop 41381da177e4SLinus Torvalds nop 41391da177e4SLinus Torvalds bra.b CASL_START 41401da177e4SLinus Torvalds 41411da177e4SLinus Torvalds################################################################# 41421da177e4SLinus Torvalds# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON # 41431da177e4SLinus Torvalds# CALLING _isp_cas_finish(). # 41441da177e4SLinus Torvalds# # 41451da177e4SLinus Torvalds# D0 = destination[31:0] operand # 41461da177e4SLinus Torvalds# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required # 41471da177e4SLinus Torvalds# D2 = xxxxxxxx # 41481da177e4SLinus Torvalds# D3 = xxxxxxxx # 41491da177e4SLinus Torvalds# D4 = compare[31:0] operand # 41501da177e4SLinus Torvalds# D5 = xxxxxxxx # 41511da177e4SLinus Torvalds# D6 = xxxxxxxx # 41521da177e4SLinus Torvalds# D7 = xxxxxxxx # 41531da177e4SLinus Torvalds# A0 = xxxxxxxx # 41541da177e4SLinus Torvalds# A1 = xxxxxxxx # 41551da177e4SLinus Torvalds# A2 = xxxxxxxx # 41561da177e4SLinus Torvalds# A3 = xxxxxxxx # 41571da177e4SLinus Torvalds# A4 = xxxxxxxx # 41581da177e4SLinus Torvalds# A5 = xxxxxxxx # 41591da177e4SLinus Torvalds# A6 = frame pointer # 41601da177e4SLinus Torvalds# A7 = stack pointer # 41611da177e4SLinus Torvalds################################################################# 41621da177e4SLinus Torvalds 41631da177e4SLinus Torvaldscasl_noupdate_done: 41641da177e4SLinus Torvalds 41651da177e4SLinus Torvalds# restore previous SFC/DFC value. 41661da177e4SLinus Torvalds movc %d6,%sfc # restore old SFC 41671da177e4SLinus Torvalds movc %d6,%dfc # restore old DFC 41681da177e4SLinus Torvalds 41691da177e4SLinus Torvalds# restore previous interrupt mask level. 41701da177e4SLinus Torvalds mov.w %d7,%sr # restore old SR 41711da177e4SLinus Torvalds 41721da177e4SLinus Torvalds sf %d1 # indicate no update was done 41731da177e4SLinus Torvalds bra.l _isp_cas_finish 41741da177e4SLinus Torvalds 41751da177e4SLinus Torvaldscasl_update_done: 41761da177e4SLinus Torvalds 41771da177e4SLinus Torvalds# restore previous SFC/DFC value. 41781da177e4SLinus Torvalds movc %d6,%sfc # restore old SFC 41791da177e4SLinus Torvalds movc %d6,%dfc # restore old DFC 41801da177e4SLinus Torvalds 41811da177e4SLinus Torvalds# restore previous interrupts mask level. 41821da177e4SLinus Torvalds mov.w %d7,%sr # restore old SR 41831da177e4SLinus Torvalds 41841da177e4SLinus Torvalds st %d1 # indicate update was done 41851da177e4SLinus Torvalds bra.l _isp_cas_finish 41861da177e4SLinus Torvalds 41871da177e4SLinus Torvalds####################################### 41881da177e4SLinus Torvaldscasl2: 41891da177e4SLinus Torvalds mov.l %d2,%d5 # d5 = Update[7:0] 41901da177e4SLinus Torvalds lsr.l &0x8,%d2 41911da177e4SLinus Torvalds mov.l %d2,%d3 # d3 = Update[23:8] 41921da177e4SLinus Torvalds swap %d2 # d2 = Update[31:24] 41931da177e4SLinus Torvalds 41941da177e4SLinus Torvalds# mask interrupts levels 0-6. save old mask value. 41951da177e4SLinus Torvalds mov.w %sr,%d7 # save current SR 41961da177e4SLinus Torvalds ori.w &0x0700,%sr # inhibit interrupts 41971da177e4SLinus Torvalds 41981da177e4SLinus Torvalds# load the SFC and DFC with the appropriate mode. 41991da177e4SLinus Torvalds movc %sfc,%d6 # save old SFC/DFC 42001da177e4SLinus Torvalds movc %d0,%sfc # load new sfc 42011da177e4SLinus Torvalds movc %d0,%dfc # load new dfc 42021da177e4SLinus Torvalds 42031da177e4SLinus Torvalds# pre-load the operand ATC. no page faults should occur here because 42041da177e4SLinus Torvalds# _real_lock_page() should have taken care of this already. 42051da177e4SLinus Torvalds plpaw (%a1) # load atc for ADDR 42061da177e4SLinus Torvalds plpaw (%a2) # load atc for ADDR+3 42071da177e4SLinus Torvalds 42081da177e4SLinus Torvalds# puch the operand lines from the cache if they exist. 42091da177e4SLinus Torvalds cpushl %dc,(%a1) # push dirty data 42101da177e4SLinus Torvalds cpushl %dc,(%a2) # push dirty data 42111da177e4SLinus Torvalds 42121da177e4SLinus Torvalds# load the BUSCR values. 42131da177e4SLinus Torvalds mov.l &0x80000000,%a1 # assert LOCK* buscr value 42141da177e4SLinus Torvalds mov.l &0xa0000000,%a2 # assert LOCKE* buscr value 42151da177e4SLinus Torvalds mov.l &0x00000000,%a3 # buscr unlock value 42161da177e4SLinus Torvalds 42171da177e4SLinus Torvalds# pre-load the instruction cache for the following algorithm. 42181da177e4SLinus Torvalds# this will minimize the number of cycles that LOCK* will be asserted. 42191da177e4SLinus Torvalds bra.b CASL2_ENTER # start pre-loading icache 42201da177e4SLinus Torvalds 42211da177e4SLinus Torvalds# 42221da177e4SLinus Torvalds# D0 = dst operand <- 42231da177e4SLinus Torvalds# D1 = xxxxxxxx 42241da177e4SLinus Torvalds# D2 = update[31:24] operand 42251da177e4SLinus Torvalds# D3 = update[23:8] operand 42261da177e4SLinus Torvalds# D4 = compare[31:0] operand 42271da177e4SLinus Torvalds# D5 = update[7:0] operand 42281da177e4SLinus Torvalds# D6 = old SFC/DFC 42291da177e4SLinus Torvalds# D7 = old SR 42301da177e4SLinus Torvalds# A0 = ADDR 42311da177e4SLinus Torvalds# A1 = bus LOCK* value 42321da177e4SLinus Torvalds# A2 = bus LOCKE* value 42331da177e4SLinus Torvalds# A3 = bus unlock value 42341da177e4SLinus Torvalds# A4 = xxxxxxxx 42351da177e4SLinus Torvalds# A5 = xxxxxxxx 42361da177e4SLinus Torvalds# 42371da177e4SLinus Torvalds align 0x10 42381da177e4SLinus TorvaldsCASL2_START: 42391da177e4SLinus Torvalds movc %a1,%buscr # assert LOCK* 42401da177e4SLinus Torvalds movs.l (%a0),%d0 # fetch Dest[31:0] 42411da177e4SLinus Torvalds cmp.l %d0,%d4 # Dest - Compare 42421da177e4SLinus Torvalds bne.b CASL2_NOUPDATE 42431da177e4SLinus Torvalds bra.b CASL2_UPDATE 42441da177e4SLinus TorvaldsCASL2_ENTER: 42451da177e4SLinus Torvalds bra.b ~+16 42461da177e4SLinus Torvalds 42471da177e4SLinus TorvaldsCASL2_UPDATE: 42481da177e4SLinus Torvalds movs.b %d2,(%a0)+ # Update[31:24] -> DEST 42491da177e4SLinus Torvalds movs.w %d3,(%a0)+ # Update[23:8] -> DEST+0x1 42501da177e4SLinus Torvalds movc %a2,%buscr # assert LOCKE* 42511da177e4SLinus Torvalds bra.b CASL2_UPDATE2 42521da177e4SLinus Torvalds bra.b ~+16 42531da177e4SLinus Torvalds 42541da177e4SLinus TorvaldsCASL2_UPDATE2: 42551da177e4SLinus Torvalds movs.b %d5,(%a0) # Update[7:0] -> DEST+0x3 42561da177e4SLinus Torvalds movc %a3,%buscr # unlock the bus 42571da177e4SLinus Torvalds bra.w casl_update_done 42581da177e4SLinus Torvalds nop 42591da177e4SLinus Torvalds bra.b ~+16 42601da177e4SLinus Torvalds 42611da177e4SLinus TorvaldsCASL2_NOUPDATE: 42621da177e4SLinus Torvalds rol.l &0x8,%d0 # get Dest[31:24] 42631da177e4SLinus Torvalds movs.b %d0,(%a0)+ # Dest[31:24] -> DEST 42641da177e4SLinus Torvalds swap %d0 # get Dest[23:8] 42651da177e4SLinus Torvalds movs.w %d0,(%a0)+ # Dest[23:8] -> DEST+0x1 42661da177e4SLinus Torvalds bra.b CASL2_NOUPDATE2 42671da177e4SLinus Torvalds bra.b ~+16 42681da177e4SLinus Torvalds 42691da177e4SLinus TorvaldsCASL2_NOUPDATE2: 42701da177e4SLinus Torvalds rol.l &0x8,%d0 # get Dest[7:0] 42711da177e4SLinus Torvalds movc %a2,%buscr # assert LOCKE* 42721da177e4SLinus Torvalds movs.b %d0,(%a0) # Dest[7:0] -> DEST+0x3 42731da177e4SLinus Torvalds bra.b CASL2_NOUPDATE3 42741da177e4SLinus Torvalds nop 42751da177e4SLinus Torvalds bra.b ~+16 42761da177e4SLinus Torvalds 42771da177e4SLinus TorvaldsCASL2_NOUPDATE3: 42781da177e4SLinus Torvalds movc %a3,%buscr # unlock the bus 42791da177e4SLinus Torvalds bra.w casl_noupdate_done 42801da177e4SLinus Torvalds nop 42811da177e4SLinus Torvalds nop 42821da177e4SLinus Torvalds nop 42831da177e4SLinus Torvalds bra.b ~+16 42841da177e4SLinus Torvalds 42851da177e4SLinus TorvaldsCASL2_FILLER: 42861da177e4SLinus Torvalds nop 42871da177e4SLinus Torvalds nop 42881da177e4SLinus Torvalds nop 42891da177e4SLinus Torvalds nop 42901da177e4SLinus Torvalds nop 42911da177e4SLinus Torvalds nop 42921da177e4SLinus Torvalds nop 42931da177e4SLinus Torvalds bra.b CASL2_START 42941da177e4SLinus Torvalds 42951da177e4SLinus Torvalds#### 42961da177e4SLinus Torvalds#### 42971da177e4SLinus Torvalds# end label used by _isp_cas_inrange() 42981da177e4SLinus Torvalds global _CASHI 42991da177e4SLinus Torvalds_CASHI: 4300