18c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 28c2ecf20Sopenharmony_ciMOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 38c2ecf20Sopenharmony_ciM68000 Hi-Performance Microprocessor Division 48c2ecf20Sopenharmony_ciM68060 Software Package 58c2ecf20Sopenharmony_ciProduction Release P1.00 -- October 10, 1994 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ciM68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved. 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ciTHE SOFTWARE is provided on an "AS IS" basis and without warranty. 108c2ecf20Sopenharmony_ciTo the maximum extent permitted by applicable law, 118c2ecf20Sopenharmony_ciMOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 128c2ecf20Sopenharmony_ciINCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 138c2ecf20Sopenharmony_ciand any warranty against infringement with regard to the SOFTWARE 148c2ecf20Sopenharmony_ci(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials. 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ciTo the maximum extent permitted by applicable law, 178c2ecf20Sopenharmony_ciIN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 188c2ecf20Sopenharmony_ci(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, 198c2ecf20Sopenharmony_ciBUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) 208c2ecf20Sopenharmony_ciARISING OF THE USE OR INABILITY TO USE THE SOFTWARE. 218c2ecf20Sopenharmony_ciMotorola assumes no responsibility for the maintenance and support of the SOFTWARE. 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ciYou are hereby granted a copyright license to use, modify, and distribute the SOFTWARE 248c2ecf20Sopenharmony_ciso long as this entire notice is retained without alteration in any modified and/or 258c2ecf20Sopenharmony_ciredistributed versions, and that such modified versions are clearly identified as such. 268c2ecf20Sopenharmony_ciNo licenses are granted by implication, estoppel or otherwise under any patents 278c2ecf20Sopenharmony_cior trademarks of Motorola, Inc. 288c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 298c2ecf20Sopenharmony_ci# ireal.s: 308c2ecf20Sopenharmony_ci# This file is appended to the top of the 060ISP package 318c2ecf20Sopenharmony_ci# and contains the entry points into the package. The user, in 328c2ecf20Sopenharmony_ci# effect, branches to one of the branch table entries located 338c2ecf20Sopenharmony_ci# after _060ISP_TABLE. 348c2ecf20Sopenharmony_ci# Also, subroutine stubs exist in this file (_isp_done for 358c2ecf20Sopenharmony_ci# example) that are referenced by the ISP package itself in order 368c2ecf20Sopenharmony_ci# to call a given routine. The stub routine actually performs the 378c2ecf20Sopenharmony_ci# callout. The ISP code does a "bsr" to the stub routine. This 388c2ecf20Sopenharmony_ci# extra layer of hierarchy adds a slight performance penalty but 398c2ecf20Sopenharmony_ci# it makes the ISP code easier to read and more mainatinable. 408c2ecf20Sopenharmony_ci# 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ciset _off_chk, 0x00 438c2ecf20Sopenharmony_ciset _off_divbyzero, 0x04 448c2ecf20Sopenharmony_ciset _off_trace, 0x08 458c2ecf20Sopenharmony_ciset _off_access, 0x0c 468c2ecf20Sopenharmony_ciset _off_done, 0x10 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ciset _off_cas, 0x14 498c2ecf20Sopenharmony_ciset _off_cas2, 0x18 508c2ecf20Sopenharmony_ciset _off_lock, 0x1c 518c2ecf20Sopenharmony_ciset _off_unlock, 0x20 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ciset _off_imr, 0x40 548c2ecf20Sopenharmony_ciset _off_dmr, 0x44 558c2ecf20Sopenharmony_ciset _off_dmw, 0x48 568c2ecf20Sopenharmony_ciset _off_irw, 0x4c 578c2ecf20Sopenharmony_ciset _off_irl, 0x50 588c2ecf20Sopenharmony_ciset _off_drb, 0x54 598c2ecf20Sopenharmony_ciset _off_drw, 0x58 608c2ecf20Sopenharmony_ciset _off_drl, 0x5c 618c2ecf20Sopenharmony_ciset _off_dwb, 0x60 628c2ecf20Sopenharmony_ciset _off_dww, 0x64 638c2ecf20Sopenharmony_ciset _off_dwl, 0x68 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci_060ISP_TABLE: 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci# Here's the table of ENTRY POINTS for those linking the package. 688c2ecf20Sopenharmony_ci bra.l _isp_unimp 698c2ecf20Sopenharmony_ci short 0x0000 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci bra.l _isp_cas 728c2ecf20Sopenharmony_ci short 0x0000 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci bra.l _isp_cas2 758c2ecf20Sopenharmony_ci short 0x0000 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci bra.l _isp_cas_finish 788c2ecf20Sopenharmony_ci short 0x0000 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci bra.l _isp_cas2_finish 818c2ecf20Sopenharmony_ci short 0x0000 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci bra.l _isp_cas_inrange 848c2ecf20Sopenharmony_ci short 0x0000 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci bra.l _isp_cas_terminate 878c2ecf20Sopenharmony_ci short 0x0000 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci bra.l _isp_cas_restart 908c2ecf20Sopenharmony_ci short 0x0000 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci space 64 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci############################################################# 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci global _real_chk 978c2ecf20Sopenharmony_ci_real_chk: 988c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 998c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_chk,%pc),%d0 1008c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1018c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 1028c2ecf20Sopenharmony_ci rtd &0x4 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci global _real_divbyzero 1058c2ecf20Sopenharmony_ci_real_divbyzero: 1068c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 1078c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_divbyzero,%pc),%d0 1088c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1098c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 1108c2ecf20Sopenharmony_ci rtd &0x4 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci global _real_trace 1138c2ecf20Sopenharmony_ci_real_trace: 1148c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 1158c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_trace,%pc),%d0 1168c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1178c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 1188c2ecf20Sopenharmony_ci rtd &0x4 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci global _real_access 1218c2ecf20Sopenharmony_ci_real_access: 1228c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 1238c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_access,%pc),%d0 1248c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1258c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 1268c2ecf20Sopenharmony_ci rtd &0x4 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci global _isp_done 1298c2ecf20Sopenharmony_ci_isp_done: 1308c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 1318c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_done,%pc),%d0 1328c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1338c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 1348c2ecf20Sopenharmony_ci rtd &0x4 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci####################################### 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci global _real_cas 1398c2ecf20Sopenharmony_ci_real_cas: 1408c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 1418c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_cas,%pc),%d0 1428c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1438c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 1448c2ecf20Sopenharmony_ci rtd &0x4 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci global _real_cas2 1478c2ecf20Sopenharmony_ci_real_cas2: 1488c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 1498c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_cas2,%pc),%d0 1508c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1518c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 1528c2ecf20Sopenharmony_ci rtd &0x4 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci global _real_lock_page 1558c2ecf20Sopenharmony_ci_real_lock_page: 1568c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 1578c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_lock,%pc),%d0 1588c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1598c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 1608c2ecf20Sopenharmony_ci rtd &0x4 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci global _real_unlock_page 1638c2ecf20Sopenharmony_ci_real_unlock_page: 1648c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 1658c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_unlock,%pc),%d0 1668c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1678c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 1688c2ecf20Sopenharmony_ci rtd &0x4 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci####################################### 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci global _imem_read 1738c2ecf20Sopenharmony_ci_imem_read: 1748c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 1758c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_imr,%pc),%d0 1768c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1778c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 1788c2ecf20Sopenharmony_ci rtd &0x4 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci global _dmem_read 1818c2ecf20Sopenharmony_ci_dmem_read: 1828c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 1838c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_dmr,%pc),%d0 1848c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1858c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 1868c2ecf20Sopenharmony_ci rtd &0x4 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci global _dmem_write 1898c2ecf20Sopenharmony_ci_dmem_write: 1908c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 1918c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_dmw,%pc),%d0 1928c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 1938c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 1948c2ecf20Sopenharmony_ci rtd &0x4 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci global _imem_read_word 1978c2ecf20Sopenharmony_ci_imem_read_word: 1988c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 1998c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_irw,%pc),%d0 2008c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2018c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 2028c2ecf20Sopenharmony_ci rtd &0x4 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci global _imem_read_long 2058c2ecf20Sopenharmony_ci_imem_read_long: 2068c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 2078c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_irl,%pc),%d0 2088c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2098c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 2108c2ecf20Sopenharmony_ci rtd &0x4 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci global _dmem_read_byte 2138c2ecf20Sopenharmony_ci_dmem_read_byte: 2148c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 2158c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_drb,%pc),%d0 2168c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2178c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 2188c2ecf20Sopenharmony_ci rtd &0x4 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci global _dmem_read_word 2218c2ecf20Sopenharmony_ci_dmem_read_word: 2228c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 2238c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_drw,%pc),%d0 2248c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2258c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 2268c2ecf20Sopenharmony_ci rtd &0x4 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci global _dmem_read_long 2298c2ecf20Sopenharmony_ci_dmem_read_long: 2308c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 2318c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_drl,%pc),%d0 2328c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2338c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 2348c2ecf20Sopenharmony_ci rtd &0x4 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci global _dmem_write_byte 2378c2ecf20Sopenharmony_ci_dmem_write_byte: 2388c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 2398c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_dwb,%pc),%d0 2408c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2418c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 2428c2ecf20Sopenharmony_ci rtd &0x4 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci global _dmem_write_word 2458c2ecf20Sopenharmony_ci_dmem_write_word: 2468c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 2478c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_dww,%pc),%d0 2488c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2498c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 2508c2ecf20Sopenharmony_ci rtd &0x4 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci global _dmem_write_long 2538c2ecf20Sopenharmony_ci_dmem_write_long: 2548c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 2558c2ecf20Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_dwl,%pc),%d0 2568c2ecf20Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 2578c2ecf20Sopenharmony_ci mov.l 0x4(%sp),%d0 2588c2ecf20Sopenharmony_ci rtd &0x4 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci# 2618c2ecf20Sopenharmony_ci# This file contains a set of define statements for constants 2628c2ecf20Sopenharmony_ci# in oreder to promote readability within the core code itself. 2638c2ecf20Sopenharmony_ci# 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ciset LOCAL_SIZE, 96 # stack frame size(bytes) 2668c2ecf20Sopenharmony_ciset LV, -LOCAL_SIZE # stack offset 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ciset EXC_ISR, 0x4 # stack status register 2698c2ecf20Sopenharmony_ciset EXC_IPC, 0x6 # stack pc 2708c2ecf20Sopenharmony_ciset EXC_IVOFF, 0xa # stacked vector offset 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ciset EXC_AREGS, LV+64 # offset of all address regs 2738c2ecf20Sopenharmony_ciset EXC_DREGS, LV+32 # offset of all data regs 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ciset EXC_A7, EXC_AREGS+(7*4) # offset of a7 2768c2ecf20Sopenharmony_ciset EXC_A6, EXC_AREGS+(6*4) # offset of a6 2778c2ecf20Sopenharmony_ciset EXC_A5, EXC_AREGS+(5*4) # offset of a5 2788c2ecf20Sopenharmony_ciset EXC_A4, EXC_AREGS+(4*4) # offset of a4 2798c2ecf20Sopenharmony_ciset EXC_A3, EXC_AREGS+(3*4) # offset of a3 2808c2ecf20Sopenharmony_ciset EXC_A2, EXC_AREGS+(2*4) # offset of a2 2818c2ecf20Sopenharmony_ciset EXC_A1, EXC_AREGS+(1*4) # offset of a1 2828c2ecf20Sopenharmony_ciset EXC_A0, EXC_AREGS+(0*4) # offset of a0 2838c2ecf20Sopenharmony_ciset EXC_D7, EXC_DREGS+(7*4) # offset of d7 2848c2ecf20Sopenharmony_ciset EXC_D6, EXC_DREGS+(6*4) # offset of d6 2858c2ecf20Sopenharmony_ciset EXC_D5, EXC_DREGS+(5*4) # offset of d5 2868c2ecf20Sopenharmony_ciset EXC_D4, EXC_DREGS+(4*4) # offset of d4 2878c2ecf20Sopenharmony_ciset EXC_D3, EXC_DREGS+(3*4) # offset of d3 2888c2ecf20Sopenharmony_ciset EXC_D2, EXC_DREGS+(2*4) # offset of d2 2898c2ecf20Sopenharmony_ciset EXC_D1, EXC_DREGS+(1*4) # offset of d1 2908c2ecf20Sopenharmony_ciset EXC_D0, EXC_DREGS+(0*4) # offset of d0 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ciset EXC_TEMP, LV+16 # offset of temp stack space 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ciset EXC_SAVVAL, LV+12 # offset of old areg value 2958c2ecf20Sopenharmony_ciset EXC_SAVREG, LV+11 # offset of old areg index 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ciset SPCOND_FLG, LV+10 # offset of spc condition flg 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ciset EXC_CC, LV+8 # offset of cc register 3008c2ecf20Sopenharmony_ciset EXC_EXTWPTR, LV+4 # offset of current PC 3018c2ecf20Sopenharmony_ciset EXC_EXTWORD, LV+2 # offset of current ext opword 3028c2ecf20Sopenharmony_ciset EXC_OPWORD, LV+0 # offset of current opword 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci########################### 3058c2ecf20Sopenharmony_ci# SPecial CONDition FLaGs # 3068c2ecf20Sopenharmony_ci########################### 3078c2ecf20Sopenharmony_ciset mia7_flg, 0x04 # (a7)+ flag 3088c2ecf20Sopenharmony_ciset mda7_flg, 0x08 # -(a7) flag 3098c2ecf20Sopenharmony_ciset ichk_flg, 0x10 # chk exception flag 3108c2ecf20Sopenharmony_ciset idbyz_flg, 0x20 # divbyzero flag 3118c2ecf20Sopenharmony_ciset restore_flg, 0x40 # restore -(an)+ flag 3128c2ecf20Sopenharmony_ciset immed_flg, 0x80 # immediate data flag 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ciset mia7_bit, 0x2 # (a7)+ bit 3158c2ecf20Sopenharmony_ciset mda7_bit, 0x3 # -(a7) bit 3168c2ecf20Sopenharmony_ciset ichk_bit, 0x4 # chk exception bit 3178c2ecf20Sopenharmony_ciset idbyz_bit, 0x5 # divbyzero bit 3188c2ecf20Sopenharmony_ciset restore_bit, 0x6 # restore -(a7)+ bit 3198c2ecf20Sopenharmony_ciset immed_bit, 0x7 # immediate data bit 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci######### 3228c2ecf20Sopenharmony_ci# Misc. # 3238c2ecf20Sopenharmony_ci######### 3248c2ecf20Sopenharmony_ciset BYTE, 1 # len(byte) == 1 byte 3258c2ecf20Sopenharmony_ciset WORD, 2 # len(word) == 2 bytes 3268c2ecf20Sopenharmony_ciset LONG, 4 # len(longword) == 4 bytes 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci######################################################################### 3298c2ecf20Sopenharmony_ci# XDEF **************************************************************** # 3308c2ecf20Sopenharmony_ci# _isp_unimp(): 060ISP entry point for Unimplemented Instruction # 3318c2ecf20Sopenharmony_ci# # 3328c2ecf20Sopenharmony_ci# This handler should be the first code executed upon taking the # 3338c2ecf20Sopenharmony_ci# "Unimplemented Integer Instruction" exception in an operating # 3348c2ecf20Sopenharmony_ci# system. # 3358c2ecf20Sopenharmony_ci# # 3368c2ecf20Sopenharmony_ci# XREF **************************************************************** # 3378c2ecf20Sopenharmony_ci# _imem_read_{word,long}() - read instruction word/longword # 3388c2ecf20Sopenharmony_ci# _mul64() - emulate 64-bit multiply # 3398c2ecf20Sopenharmony_ci# _div64() - emulate 64-bit divide # 3408c2ecf20Sopenharmony_ci# _moveperipheral() - emulate "movep" # 3418c2ecf20Sopenharmony_ci# _compandset() - emulate misaligned "cas" # 3428c2ecf20Sopenharmony_ci# _compandset2() - emulate "cas2" # 3438c2ecf20Sopenharmony_ci# _chk2_cmp2() - emulate "cmp2" and "chk2" # 3448c2ecf20Sopenharmony_ci# _isp_done() - "callout" for normal final exit # 3458c2ecf20Sopenharmony_ci# _real_trace() - "callout" for Trace exception # 3468c2ecf20Sopenharmony_ci# _real_chk() - "callout" for Chk exception # 3478c2ecf20Sopenharmony_ci# _real_divbyzero() - "callout" for DZ exception # 3488c2ecf20Sopenharmony_ci# _real_access() - "callout" for access error exception # 3498c2ecf20Sopenharmony_ci# # 3508c2ecf20Sopenharmony_ci# INPUT *************************************************************** # 3518c2ecf20Sopenharmony_ci# - The system stack contains the Unimp Int Instr stack frame # 3528c2ecf20Sopenharmony_ci# # 3538c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** # 3548c2ecf20Sopenharmony_ci# If Trace exception: # 3558c2ecf20Sopenharmony_ci# - The system stack changed to contain Trace exc stack frame # 3568c2ecf20Sopenharmony_ci# If Chk exception: # 3578c2ecf20Sopenharmony_ci# - The system stack changed to contain Chk exc stack frame # 3588c2ecf20Sopenharmony_ci# If DZ exception: # 3598c2ecf20Sopenharmony_ci# - The system stack changed to contain DZ exc stack frame # 3608c2ecf20Sopenharmony_ci# If access error exception: # 3618c2ecf20Sopenharmony_ci# - The system stack changed to contain access err exc stk frame # 3628c2ecf20Sopenharmony_ci# Else: # 3638c2ecf20Sopenharmony_ci# - Results saved as appropriate # 3648c2ecf20Sopenharmony_ci# # 3658c2ecf20Sopenharmony_ci# ALGORITHM *********************************************************** # 3668c2ecf20Sopenharmony_ci# This handler fetches the first instruction longword from # 3678c2ecf20Sopenharmony_ci# memory and decodes it to determine which of the unimplemented # 3688c2ecf20Sopenharmony_ci# integer instructions caused this exception. This handler then calls # 3698c2ecf20Sopenharmony_ci# one of _mul64(), _div64(), _moveperipheral(), _compandset(), # 3708c2ecf20Sopenharmony_ci# _compandset2(), or _chk2_cmp2() as appropriate. # 3718c2ecf20Sopenharmony_ci# Some of these instructions, by their nature, may produce other # 3728c2ecf20Sopenharmony_ci# types of exceptions. "div" can produce a divide-by-zero exception, # 3738c2ecf20Sopenharmony_ci# and "chk2" can cause a "Chk" exception. In both cases, the current # 3748c2ecf20Sopenharmony_ci# exception stack frame must be converted to an exception stack frame # 3758c2ecf20Sopenharmony_ci# of the correct exception type and an exit must be made through # 3768c2ecf20Sopenharmony_ci# _real_divbyzero() or _real_chk() as appropriate. In addition, all # 3778c2ecf20Sopenharmony_ci# instructions may be executing while Trace is enabled. If so, then # 3788c2ecf20Sopenharmony_ci# a Trace exception stack frame must be created and an exit made # 3798c2ecf20Sopenharmony_ci# through _real_trace(). # 3808c2ecf20Sopenharmony_ci# Meanwhile, if any read or write to memory using the # 3818c2ecf20Sopenharmony_ci# _mem_{read,write}() "callout"s returns a failing value, then an # 3828c2ecf20Sopenharmony_ci# access error frame must be created and an exit made through # 3838c2ecf20Sopenharmony_ci# _real_access(). # 3848c2ecf20Sopenharmony_ci# If none of these occur, then a normal exit is made through # 3858c2ecf20Sopenharmony_ci# _isp_done(). # 3868c2ecf20Sopenharmony_ci# # 3878c2ecf20Sopenharmony_ci# This handler, upon entry, saves almost all user-visible # 3888c2ecf20Sopenharmony_ci# address and data registers to the stack. Although this may seem to # 3898c2ecf20Sopenharmony_ci# cause excess memory traffic, it was found that due to having to # 3908c2ecf20Sopenharmony_ci# access these register files for things like data retrieval and <ea> # 3918c2ecf20Sopenharmony_ci# calculations, it was more efficient to have them on the stack where # 3928c2ecf20Sopenharmony_ci# they could be accessed by indexing rather than to make subroutine # 3938c2ecf20Sopenharmony_ci# calls to retrieve a register of a particular index. # 3948c2ecf20Sopenharmony_ci# # 3958c2ecf20Sopenharmony_ci######################################################################### 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci global _isp_unimp 3988c2ecf20Sopenharmony_ci_isp_unimp: 3998c2ecf20Sopenharmony_ci link.w %a6,&-LOCAL_SIZE # create room for stack frame 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci movm.l &0x3fff,EXC_DREGS(%a6) # store d0-d7/a0-a5 4028c2ecf20Sopenharmony_ci mov.l (%a6),EXC_A6(%a6) # store a6 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci btst &0x5,EXC_ISR(%a6) # from s or u mode? 4058c2ecf20Sopenharmony_ci bne.b uieh_s # supervisor mode 4068c2ecf20Sopenharmony_ciuieh_u: 4078c2ecf20Sopenharmony_ci mov.l %usp,%a0 # fetch user stack pointer 4088c2ecf20Sopenharmony_ci mov.l %a0,EXC_A7(%a6) # store a7 4098c2ecf20Sopenharmony_ci bra.b uieh_cont 4108c2ecf20Sopenharmony_ciuieh_s: 4118c2ecf20Sopenharmony_ci lea 0xc(%a6),%a0 4128c2ecf20Sopenharmony_ci mov.l %a0,EXC_A7(%a6) # store corrected sp 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci############################################################################### 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ciuieh_cont: 4178c2ecf20Sopenharmony_ci clr.b SPCOND_FLG(%a6) # clear "special case" flag 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci mov.w EXC_ISR(%a6),EXC_CC(%a6) # store cc copy on stack 4208c2ecf20Sopenharmony_ci mov.l EXC_IPC(%a6),EXC_EXTWPTR(%a6) # store extwptr on stack 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci# 4238c2ecf20Sopenharmony_ci# fetch the opword and first extension word pointed to by the stacked pc 4248c2ecf20Sopenharmony_ci# and store them to the stack for now 4258c2ecf20Sopenharmony_ci# 4268c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 4278c2ecf20Sopenharmony_ci addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 4288c2ecf20Sopenharmony_ci bsr.l _imem_read_long # fetch opword & extword 4298c2ecf20Sopenharmony_ci mov.l %d0,EXC_OPWORD(%a6) # store extword on stack 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci######################################################################### 4338c2ecf20Sopenharmony_ci# muls.l 0100 1100 00 |<ea>| 0*** 1100 0000 0*** # 4348c2ecf20Sopenharmony_ci# mulu.l 0100 1100 00 |<ea>| 0*** 0100 0000 0*** # 4358c2ecf20Sopenharmony_ci# # 4368c2ecf20Sopenharmony_ci# divs.l 0100 1100 01 |<ea>| 0*** 1100 0000 0*** # 4378c2ecf20Sopenharmony_ci# divu.l 0100 1100 01 |<ea>| 0*** 0100 0000 0*** # 4388c2ecf20Sopenharmony_ci# # 4398c2ecf20Sopenharmony_ci# movep.w m2r 0000 ***1 00 001*** | <displacement> | # 4408c2ecf20Sopenharmony_ci# movep.l m2r 0000 ***1 01 001*** | <displacement> | # 4418c2ecf20Sopenharmony_ci# movep.w r2m 0000 ***1 10 001*** | <displacement> | # 4428c2ecf20Sopenharmony_ci# movep.l r2m 0000 ***1 11 001*** | <displacement> | # 4438c2ecf20Sopenharmony_ci# # 4448c2ecf20Sopenharmony_ci# cas.w 0000 1100 11 |<ea>| 0000 000* **00 0*** # 4458c2ecf20Sopenharmony_ci# cas.l 0000 1110 11 |<ea>| 0000 000* **00 0*** # 4468c2ecf20Sopenharmony_ci# # 4478c2ecf20Sopenharmony_ci# cas2.w 0000 1100 11 111100 **** 000* **00 0*** # 4488c2ecf20Sopenharmony_ci# **** 000* **00 0*** # 4498c2ecf20Sopenharmony_ci# cas2.l 0000 1110 11 111100 **** 000* **00 0*** # 4508c2ecf20Sopenharmony_ci# **** 000* **00 0*** # 4518c2ecf20Sopenharmony_ci# # 4528c2ecf20Sopenharmony_ci# chk2.b 0000 0000 11 |<ea>| **** 1000 0000 0000 # 4538c2ecf20Sopenharmony_ci# chk2.w 0000 0010 11 |<ea>| **** 1000 0000 0000 # 4548c2ecf20Sopenharmony_ci# chk2.l 0000 0100 11 |<ea>| **** 1000 0000 0000 # 4558c2ecf20Sopenharmony_ci# # 4568c2ecf20Sopenharmony_ci# cmp2.b 0000 0000 11 |<ea>| **** 0000 0000 0000 # 4578c2ecf20Sopenharmony_ci# cmp2.w 0000 0010 11 |<ea>| **** 0000 0000 0000 # 4588c2ecf20Sopenharmony_ci# cmp2.l 0000 0100 11 |<ea>| **** 0000 0000 0000 # 4598c2ecf20Sopenharmony_ci######################################################################### 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci# 4628c2ecf20Sopenharmony_ci# using bit 14 of the operation word, separate into 2 groups: 4638c2ecf20Sopenharmony_ci# (group1) mul64, div64 4648c2ecf20Sopenharmony_ci# (group2) movep, chk2, cmp2, cas2, cas 4658c2ecf20Sopenharmony_ci# 4668c2ecf20Sopenharmony_ci btst &0x1e,%d0 # group1 or group2 4678c2ecf20Sopenharmony_ci beq.b uieh_group2 # go handle group2 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci# 4708c2ecf20Sopenharmony_ci# now, w/ group1, make mul64's decode the fastest since it will 4718c2ecf20Sopenharmony_ci# most likely be used the most. 4728c2ecf20Sopenharmony_ci# 4738c2ecf20Sopenharmony_ciuieh_group1: 4748c2ecf20Sopenharmony_ci btst &0x16,%d0 # test for div64 4758c2ecf20Sopenharmony_ci bne.b uieh_div64 # go handle div64 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ciuieh_mul64: 4788c2ecf20Sopenharmony_ci# mul64() may use ()+ addressing and may, therefore, alter a7 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci bsr.l _mul64 # _mul64() 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci btst &0x5,EXC_ISR(%a6) # supervisor mode? 4838c2ecf20Sopenharmony_ci beq.w uieh_done 4848c2ecf20Sopenharmony_ci btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed? 4858c2ecf20Sopenharmony_ci beq.w uieh_done # no 4868c2ecf20Sopenharmony_ci btst &0x7,EXC_ISR(%a6) # is trace enabled? 4878c2ecf20Sopenharmony_ci bne.w uieh_trace_a7 # yes 4888c2ecf20Sopenharmony_ci bra.w uieh_a7 # no 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ciuieh_div64: 4918c2ecf20Sopenharmony_ci# div64() may use ()+ addressing and may, therefore, alter a7. 4928c2ecf20Sopenharmony_ci# div64() may take a divide by zero exception. 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci bsr.l _div64 # _div64() 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci# here, we sort out all of the special cases that may have happened. 4978c2ecf20Sopenharmony_ci btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed? 4988c2ecf20Sopenharmony_ci bne.b uieh_div64_a7 # yes 4998c2ecf20Sopenharmony_ciuieh_div64_dbyz: 5008c2ecf20Sopenharmony_ci btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur? 5018c2ecf20Sopenharmony_ci bne.w uieh_divbyzero # yes 5028c2ecf20Sopenharmony_ci bra.w uieh_done # no 5038c2ecf20Sopenharmony_ciuieh_div64_a7: 5048c2ecf20Sopenharmony_ci btst &0x5,EXC_ISR(%a6) # supervisor mode? 5058c2ecf20Sopenharmony_ci beq.b uieh_div64_dbyz # no 5068c2ecf20Sopenharmony_ci# here, a7 has been incremented by 4 bytes in supervisor mode. we still 5078c2ecf20Sopenharmony_ci# may have the following 3 cases: 5088c2ecf20Sopenharmony_ci# (i) (a7)+ 5098c2ecf20Sopenharmony_ci# (ii) (a7)+; trace 5108c2ecf20Sopenharmony_ci# (iii) (a7)+; divide-by-zero 5118c2ecf20Sopenharmony_ci# 5128c2ecf20Sopenharmony_ci btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur? 5138c2ecf20Sopenharmony_ci bne.w uieh_divbyzero_a7 # yes 5148c2ecf20Sopenharmony_ci tst.b EXC_ISR(%a6) # no; is trace enabled? 5158c2ecf20Sopenharmony_ci bmi.w uieh_trace_a7 # yes 5168c2ecf20Sopenharmony_ci bra.w uieh_a7 # no 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci# 5198c2ecf20Sopenharmony_ci# now, w/ group2, make movep's decode the fastest since it will 5208c2ecf20Sopenharmony_ci# most likely be used the most. 5218c2ecf20Sopenharmony_ci# 5228c2ecf20Sopenharmony_ciuieh_group2: 5238c2ecf20Sopenharmony_ci btst &0x18,%d0 # test for not movep 5248c2ecf20Sopenharmony_ci beq.b uieh_not_movep 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci bsr.l _moveperipheral # _movep() 5288c2ecf20Sopenharmony_ci bra.w uieh_done 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ciuieh_not_movep: 5318c2ecf20Sopenharmony_ci btst &0x1b,%d0 # test for chk2,cmp2 5328c2ecf20Sopenharmony_ci beq.b uieh_chk2cmp2 # go handle chk2,cmp2 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci swap %d0 # put opword in lo word 5358c2ecf20Sopenharmony_ci cmpi.b %d0,&0xfc # test for cas2 5368c2ecf20Sopenharmony_ci beq.b uieh_cas2 # go handle cas2 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ciuieh_cas: 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci bsr.l _compandset # _cas() 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci# the cases of "cas Dc,Du,(a7)+" and "cas Dc,Du,-(a7)" used from supervisor 5438c2ecf20Sopenharmony_ci# mode are simply not considered valid and therefore are not handled. 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci bra.w uieh_done 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ciuieh_cas2: 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 5508c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 5518c2ecf20Sopenharmony_ci bsr.l _imem_read_word # read extension word 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 5548c2ecf20Sopenharmony_ci bne.w isp_iacc # yes 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci bsr.l _compandset2 # _cas2() 5578c2ecf20Sopenharmony_ci bra.w uieh_done 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ciuieh_chk2cmp2: 5608c2ecf20Sopenharmony_ci# chk2 may take a chk exception 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci bsr.l _chk2_cmp2 # _chk2_cmp2() 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci# here we check to see if a chk trap should be taken 5658c2ecf20Sopenharmony_ci cmpi.b SPCOND_FLG(%a6),&ichk_flg 5668c2ecf20Sopenharmony_ci bne.w uieh_done 5678c2ecf20Sopenharmony_ci bra.b uieh_chk_trap 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci########################################################################### 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci# 5728c2ecf20Sopenharmony_ci# the required emulation has been completed. now, clean up the necessary stack 5738c2ecf20Sopenharmony_ci# info and prepare for rte 5748c2ecf20Sopenharmony_ci# 5758c2ecf20Sopenharmony_ciuieh_done: 5768c2ecf20Sopenharmony_ci mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci# if exception occurred in user mode, then we have to restore a7 in case it 5798c2ecf20Sopenharmony_ci# changed. we don't have to update a7 for supervisor mose because that case 5808c2ecf20Sopenharmony_ci# doesn't flow through here 5818c2ecf20Sopenharmony_ci btst &0x5,EXC_ISR(%a6) # user or supervisor? 5828c2ecf20Sopenharmony_ci bne.b uieh_finish # supervisor 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci mov.l EXC_A7(%a6),%a0 # fetch user stack pointer 5858c2ecf20Sopenharmony_ci mov.l %a0,%usp # restore it 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ciuieh_finish: 5888c2ecf20Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci btst &0x7,EXC_ISR(%a6) # is trace mode on? 5918c2ecf20Sopenharmony_ci bne.b uieh_trace # yes;go handle trace mode 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),EXC_IPC(%a6) # new pc on stack frame 5948c2ecf20Sopenharmony_ci mov.l EXC_A6(%a6),(%a6) # prepare new a6 for unlink 5958c2ecf20Sopenharmony_ci unlk %a6 # unlink stack frame 5968c2ecf20Sopenharmony_ci bra.l _isp_done 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci# 5998c2ecf20Sopenharmony_ci# The instruction that was just emulated was also being traced. The trace 6008c2ecf20Sopenharmony_ci# trap for this instruction will be lost unless we jump to the trace handler. 6018c2ecf20Sopenharmony_ci# So, here we create a Trace Exception format number two exception stack 6028c2ecf20Sopenharmony_ci# frame from the Unimplemented Integer Intruction Exception stack frame 6038c2ecf20Sopenharmony_ci# format number zero and jump to the user supplied hook "_real_trace()". 6048c2ecf20Sopenharmony_ci# 6058c2ecf20Sopenharmony_ci# UIEH FRAME TRACE FRAME 6068c2ecf20Sopenharmony_ci# ***************** ***************** 6078c2ecf20Sopenharmony_ci# * 0x0 * 0x0f4 * * Current * 6088c2ecf20Sopenharmony_ci# ***************** * PC * 6098c2ecf20Sopenharmony_ci# * Current * ***************** 6108c2ecf20Sopenharmony_ci# * PC * * 0x2 * 0x024 * 6118c2ecf20Sopenharmony_ci# ***************** ***************** 6128c2ecf20Sopenharmony_ci# * SR * * Next * 6138c2ecf20Sopenharmony_ci# ***************** * PC * 6148c2ecf20Sopenharmony_ci# ->* Old * ***************** 6158c2ecf20Sopenharmony_ci# from link -->* A6 * * SR * 6168c2ecf20Sopenharmony_ci# ***************** ***************** 6178c2ecf20Sopenharmony_ci# /* A7 * * New * <-- for final unlink 6188c2ecf20Sopenharmony_ci# / * * * A6 * 6198c2ecf20Sopenharmony_ci# link frame < ***************** ***************** 6208c2ecf20Sopenharmony_ci# \ ~ ~ ~ ~ 6218c2ecf20Sopenharmony_ci# \***************** ***************** 6228c2ecf20Sopenharmony_ci# 6238c2ecf20Sopenharmony_ciuieh_trace: 6248c2ecf20Sopenharmony_ci mov.l EXC_A6(%a6),-0x4(%a6) 6258c2ecf20Sopenharmony_ci mov.w EXC_ISR(%a6),0x0(%a6) 6268c2ecf20Sopenharmony_ci mov.l EXC_IPC(%a6),0x8(%a6) 6278c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),0x2(%a6) 6288c2ecf20Sopenharmony_ci mov.w &0x2024,0x6(%a6) 6298c2ecf20Sopenharmony_ci sub.l &0x4,%a6 6308c2ecf20Sopenharmony_ci unlk %a6 6318c2ecf20Sopenharmony_ci bra.l _real_trace 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci# 6348c2ecf20Sopenharmony_ci# UIEH FRAME CHK FRAME 6358c2ecf20Sopenharmony_ci# ***************** ***************** 6368c2ecf20Sopenharmony_ci# * 0x0 * 0x0f4 * * Current * 6378c2ecf20Sopenharmony_ci# ***************** * PC * 6388c2ecf20Sopenharmony_ci# * Current * ***************** 6398c2ecf20Sopenharmony_ci# * PC * * 0x2 * 0x018 * 6408c2ecf20Sopenharmony_ci# ***************** ***************** 6418c2ecf20Sopenharmony_ci# * SR * * Next * 6428c2ecf20Sopenharmony_ci# ***************** * PC * 6438c2ecf20Sopenharmony_ci# (4 words) ***************** 6448c2ecf20Sopenharmony_ci# * SR * 6458c2ecf20Sopenharmony_ci# ***************** 6468c2ecf20Sopenharmony_ci# (6 words) 6478c2ecf20Sopenharmony_ci# 6488c2ecf20Sopenharmony_ci# the chk2 instruction should take a chk trap. so, here we must create a 6498c2ecf20Sopenharmony_ci# chk stack frame from an unimplemented integer instruction exception frame 6508c2ecf20Sopenharmony_ci# and jump to the user supplied entry point "_real_chk()". 6518c2ecf20Sopenharmony_ci# 6528c2ecf20Sopenharmony_ciuieh_chk_trap: 6538c2ecf20Sopenharmony_ci mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 6548c2ecf20Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci mov.w EXC_ISR(%a6),(%a6) # put new SR on stack 6578c2ecf20Sopenharmony_ci mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack 6588c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack 6598c2ecf20Sopenharmony_ci mov.w &0x2018,0x6(%a6) # put Vector Offset on stack 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci mov.l EXC_A6(%a6),%a6 # restore a6 6628c2ecf20Sopenharmony_ci add.l &LOCAL_SIZE,%sp # clear stack frame 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci bra.l _real_chk 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci# 6678c2ecf20Sopenharmony_ci# UIEH FRAME DIVBYZERO FRAME 6688c2ecf20Sopenharmony_ci# ***************** ***************** 6698c2ecf20Sopenharmony_ci# * 0x0 * 0x0f4 * * Current * 6708c2ecf20Sopenharmony_ci# ***************** * PC * 6718c2ecf20Sopenharmony_ci# * Current * ***************** 6728c2ecf20Sopenharmony_ci# * PC * * 0x2 * 0x014 * 6738c2ecf20Sopenharmony_ci# ***************** ***************** 6748c2ecf20Sopenharmony_ci# * SR * * Next * 6758c2ecf20Sopenharmony_ci# ***************** * PC * 6768c2ecf20Sopenharmony_ci# (4 words) ***************** 6778c2ecf20Sopenharmony_ci# * SR * 6788c2ecf20Sopenharmony_ci# ***************** 6798c2ecf20Sopenharmony_ci# (6 words) 6808c2ecf20Sopenharmony_ci# 6818c2ecf20Sopenharmony_ci# the divide instruction should take an integer divide by zero trap. so, here 6828c2ecf20Sopenharmony_ci# we must create a divbyzero stack frame from an unimplemented integer 6838c2ecf20Sopenharmony_ci# instruction exception frame and jump to the user supplied entry point 6848c2ecf20Sopenharmony_ci# "_real_divbyzero()". 6858c2ecf20Sopenharmony_ci# 6868c2ecf20Sopenharmony_ciuieh_divbyzero: 6878c2ecf20Sopenharmony_ci mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 6888c2ecf20Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci mov.w EXC_ISR(%a6),(%a6) # put new SR on stack 6918c2ecf20Sopenharmony_ci mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack 6928c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack 6938c2ecf20Sopenharmony_ci mov.w &0x2014,0x6(%a6) # put Vector Offset on stack 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci mov.l EXC_A6(%a6),%a6 # restore a6 6968c2ecf20Sopenharmony_ci add.l &LOCAL_SIZE,%sp # clear stack frame 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci bra.l _real_divbyzero 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci# 7018c2ecf20Sopenharmony_ci# DIVBYZERO FRAME 7028c2ecf20Sopenharmony_ci# ***************** 7038c2ecf20Sopenharmony_ci# * Current * 7048c2ecf20Sopenharmony_ci# UIEH FRAME * PC * 7058c2ecf20Sopenharmony_ci# ***************** ***************** 7068c2ecf20Sopenharmony_ci# * 0x0 * 0x0f4 * * 0x2 * 0x014 * 7078c2ecf20Sopenharmony_ci# ***************** ***************** 7088c2ecf20Sopenharmony_ci# * Current * * Next * 7098c2ecf20Sopenharmony_ci# * PC * * PC * 7108c2ecf20Sopenharmony_ci# ***************** ***************** 7118c2ecf20Sopenharmony_ci# * SR * * SR * 7128c2ecf20Sopenharmony_ci# ***************** ***************** 7138c2ecf20Sopenharmony_ci# (4 words) (6 words) 7148c2ecf20Sopenharmony_ci# 7158c2ecf20Sopenharmony_ci# the divide instruction should take an integer divide by zero trap. so, here 7168c2ecf20Sopenharmony_ci# we must create a divbyzero stack frame from an unimplemented integer 7178c2ecf20Sopenharmony_ci# instruction exception frame and jump to the user supplied entry point 7188c2ecf20Sopenharmony_ci# "_real_divbyzero()". 7198c2ecf20Sopenharmony_ci# 7208c2ecf20Sopenharmony_ci# However, we must also deal with the fact that (a7)+ was used from supervisor 7218c2ecf20Sopenharmony_ci# mode, thereby shifting the stack frame up 4 bytes. 7228c2ecf20Sopenharmony_ci# 7238c2ecf20Sopenharmony_ciuieh_divbyzero_a7: 7248c2ecf20Sopenharmony_ci mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 7258c2ecf20Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack 7288c2ecf20Sopenharmony_ci mov.w &0x2014,0xa(%a6) # put Vector Offset on stack 7298c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci mov.l EXC_A6(%a6),%a6 # restore a6 7328c2ecf20Sopenharmony_ci add.l &4+LOCAL_SIZE,%sp # clear stack frame 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci bra.l _real_divbyzero 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci# 7378c2ecf20Sopenharmony_ci# TRACE FRAME 7388c2ecf20Sopenharmony_ci# ***************** 7398c2ecf20Sopenharmony_ci# * Current * 7408c2ecf20Sopenharmony_ci# UIEH FRAME * PC * 7418c2ecf20Sopenharmony_ci# ***************** ***************** 7428c2ecf20Sopenharmony_ci# * 0x0 * 0x0f4 * * 0x2 * 0x024 * 7438c2ecf20Sopenharmony_ci# ***************** ***************** 7448c2ecf20Sopenharmony_ci# * Current * * Next * 7458c2ecf20Sopenharmony_ci# * PC * * PC * 7468c2ecf20Sopenharmony_ci# ***************** ***************** 7478c2ecf20Sopenharmony_ci# * SR * * SR * 7488c2ecf20Sopenharmony_ci# ***************** ***************** 7498c2ecf20Sopenharmony_ci# (4 words) (6 words) 7508c2ecf20Sopenharmony_ci# 7518c2ecf20Sopenharmony_ci# 7528c2ecf20Sopenharmony_ci# The instruction that was just emulated was also being traced. The trace 7538c2ecf20Sopenharmony_ci# trap for this instruction will be lost unless we jump to the trace handler. 7548c2ecf20Sopenharmony_ci# So, here we create a Trace Exception format number two exception stack 7558c2ecf20Sopenharmony_ci# frame from the Unimplemented Integer Intruction Exception stack frame 7568c2ecf20Sopenharmony_ci# format number zero and jump to the user supplied hook "_real_trace()". 7578c2ecf20Sopenharmony_ci# 7588c2ecf20Sopenharmony_ci# However, we must also deal with the fact that (a7)+ was used from supervisor 7598c2ecf20Sopenharmony_ci# mode, thereby shifting the stack frame up 4 bytes. 7608c2ecf20Sopenharmony_ci# 7618c2ecf20Sopenharmony_ciuieh_trace_a7: 7628c2ecf20Sopenharmony_ci mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 7638c2ecf20Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack 7668c2ecf20Sopenharmony_ci mov.w &0x2024,0xa(%a6) # put Vector Offset on stack 7678c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci mov.l EXC_A6(%a6),%a6 # restore a6 7708c2ecf20Sopenharmony_ci add.l &4+LOCAL_SIZE,%sp # clear stack frame 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci bra.l _real_trace 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci# 7758c2ecf20Sopenharmony_ci# UIEH FRAME 7768c2ecf20Sopenharmony_ci# ***************** 7778c2ecf20Sopenharmony_ci# * 0x0 * 0x0f4 * 7788c2ecf20Sopenharmony_ci# UIEH FRAME ***************** 7798c2ecf20Sopenharmony_ci# ***************** * Next * 7808c2ecf20Sopenharmony_ci# * 0x0 * 0x0f4 * * PC * 7818c2ecf20Sopenharmony_ci# ***************** ***************** 7828c2ecf20Sopenharmony_ci# * Current * * SR * 7838c2ecf20Sopenharmony_ci# * PC * ***************** 7848c2ecf20Sopenharmony_ci# ***************** (4 words) 7858c2ecf20Sopenharmony_ci# * SR * 7868c2ecf20Sopenharmony_ci# ***************** 7878c2ecf20Sopenharmony_ci# (4 words) 7888c2ecf20Sopenharmony_ciuieh_a7: 7898c2ecf20Sopenharmony_ci mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 7908c2ecf20Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci mov.w &0x00f4,0xe(%a6) # put Vector Offset on stack 7938c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),0xa(%a6) # put "Next PC" on stack 7948c2ecf20Sopenharmony_ci mov.w EXC_ISR(%a6),0x8(%a6) # put SR on stack 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci mov.l EXC_A6(%a6),%a6 # restore a6 7978c2ecf20Sopenharmony_ci add.l &8+LOCAL_SIZE,%sp # clear stack frame 7988c2ecf20Sopenharmony_ci bra.l _isp_done 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci########## 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci# this is the exit point if a data read or write fails. 8038c2ecf20Sopenharmony_ci# a0 = failing address 8048c2ecf20Sopenharmony_ci# d0 = fslw 8058c2ecf20Sopenharmony_ciisp_dacc: 8068c2ecf20Sopenharmony_ci mov.l %a0,(%a6) # save address 8078c2ecf20Sopenharmony_ci mov.l %d0,-0x4(%a6) # save partial fslw 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci lea -64(%a6),%sp 8108c2ecf20Sopenharmony_ci movm.l (%sp)+,&0x7fff # restore d0-d7/a0-a6 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci mov.l 0xc(%sp),-(%sp) # move voff,hi(pc) 8138c2ecf20Sopenharmony_ci mov.l 0x4(%sp),0x10(%sp) # store fslw 8148c2ecf20Sopenharmony_ci mov.l 0xc(%sp),0x4(%sp) # store sr,lo(pc) 8158c2ecf20Sopenharmony_ci mov.l 0x8(%sp),0xc(%sp) # store address 8168c2ecf20Sopenharmony_ci mov.l (%sp)+,0x4(%sp) # store voff,hi(pc) 8178c2ecf20Sopenharmony_ci mov.w &0x4008,0x6(%sp) # store new voff 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci bra.b isp_acc_exit 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci# this is the exit point if an instruction word read fails. 8228c2ecf20Sopenharmony_ci# FSLW: 8238c2ecf20Sopenharmony_ci# misaligned = true 8248c2ecf20Sopenharmony_ci# read = true 8258c2ecf20Sopenharmony_ci# size = word 8268c2ecf20Sopenharmony_ci# instruction = true 8278c2ecf20Sopenharmony_ci# software emulation error = true 8288c2ecf20Sopenharmony_ciisp_iacc: 8298c2ecf20Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 8308c2ecf20Sopenharmony_ci unlk %a6 # unlink frame 8318c2ecf20Sopenharmony_ci sub.w &0x8,%sp # make room for acc frame 8328c2ecf20Sopenharmony_ci mov.l 0x8(%sp),(%sp) # store sr,lo(pc) 8338c2ecf20Sopenharmony_ci mov.w 0xc(%sp),0x4(%sp) # store hi(pc) 8348c2ecf20Sopenharmony_ci mov.w &0x4008,0x6(%sp) # store new voff 8358c2ecf20Sopenharmony_ci mov.l 0x2(%sp),0x8(%sp) # store address (=pc) 8368c2ecf20Sopenharmony_ci mov.l &0x09428001,0xc(%sp) # store fslw 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ciisp_acc_exit: 8398c2ecf20Sopenharmony_ci btst &0x5,(%sp) # user or supervisor? 8408c2ecf20Sopenharmony_ci beq.b isp_acc_exit2 # user 8418c2ecf20Sopenharmony_ci bset &0x2,0xd(%sp) # set supervisor TM bit 8428c2ecf20Sopenharmony_ciisp_acc_exit2: 8438c2ecf20Sopenharmony_ci bra.l _real_access 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci# if the addressing mode was (an)+ or -(an), the address register must 8468c2ecf20Sopenharmony_ci# be restored to its pre-exception value before entering _real_access. 8478c2ecf20Sopenharmony_ciisp_restore: 8488c2ecf20Sopenharmony_ci cmpi.b SPCOND_FLG(%a6),&restore_flg # do we need a restore? 8498c2ecf20Sopenharmony_ci bne.b isp_restore_done # no 8508c2ecf20Sopenharmony_ci clr.l %d0 8518c2ecf20Sopenharmony_ci mov.b EXC_SAVREG(%a6),%d0 # regno to restore 8528c2ecf20Sopenharmony_ci mov.l EXC_SAVVAL(%a6),(EXC_AREGS,%a6,%d0.l*4) # restore value 8538c2ecf20Sopenharmony_ciisp_restore_done: 8548c2ecf20Sopenharmony_ci rts 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci######################################################################### 8578c2ecf20Sopenharmony_ci# XDEF **************************************************************** # 8588c2ecf20Sopenharmony_ci# _calc_ea(): routine to calculate effective address # 8598c2ecf20Sopenharmony_ci# # 8608c2ecf20Sopenharmony_ci# XREF **************************************************************** # 8618c2ecf20Sopenharmony_ci# _imem_read_word() - read instruction word # 8628c2ecf20Sopenharmony_ci# _imem_read_long() - read instruction longword # 8638c2ecf20Sopenharmony_ci# _dmem_read_long() - read data longword (for memory indirect) # 8648c2ecf20Sopenharmony_ci# isp_iacc() - handle instruction access error exception # 8658c2ecf20Sopenharmony_ci# isp_dacc() - handle data access error exception # 8668c2ecf20Sopenharmony_ci# # 8678c2ecf20Sopenharmony_ci# INPUT *************************************************************** # 8688c2ecf20Sopenharmony_ci# d0 = number of bytes related to effective address (w,l) # 8698c2ecf20Sopenharmony_ci# # 8708c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** # 8718c2ecf20Sopenharmony_ci# If exiting through isp_dacc... # 8728c2ecf20Sopenharmony_ci# a0 = failing address # 8738c2ecf20Sopenharmony_ci# d0 = FSLW # 8748c2ecf20Sopenharmony_ci# elsif exiting though isp_iacc... # 8758c2ecf20Sopenharmony_ci# none # 8768c2ecf20Sopenharmony_ci# else # 8778c2ecf20Sopenharmony_ci# a0 = effective address # 8788c2ecf20Sopenharmony_ci# # 8798c2ecf20Sopenharmony_ci# ALGORITHM *********************************************************** # 8808c2ecf20Sopenharmony_ci# The effective address type is decoded from the opword residing # 8818c2ecf20Sopenharmony_ci# on the stack. A jump table is used to vector to a routine for the # 8828c2ecf20Sopenharmony_ci# appropriate mode. Since none of the emulated integer instructions # 8838c2ecf20Sopenharmony_ci# uses byte-sized operands, only handle word and long operations. # 8848c2ecf20Sopenharmony_ci# # 8858c2ecf20Sopenharmony_ci# Dn,An - shouldn't enter here # 8868c2ecf20Sopenharmony_ci# (An) - fetch An value from stack # 8878c2ecf20Sopenharmony_ci# -(An) - fetch An value from stack; return decr value; # 8888c2ecf20Sopenharmony_ci# place decr value on stack; store old value in case of # 8898c2ecf20Sopenharmony_ci# future access error; if -(a7), set mda7_flg in # 8908c2ecf20Sopenharmony_ci# SPCOND_FLG # 8918c2ecf20Sopenharmony_ci# (An)+ - fetch An value from stack; return value; # 8928c2ecf20Sopenharmony_ci# place incr value on stack; store old value in case of # 8938c2ecf20Sopenharmony_ci# future access error; if (a7)+, set mia7_flg in # 8948c2ecf20Sopenharmony_ci# SPCOND_FLG # 8958c2ecf20Sopenharmony_ci# (d16,An) - fetch An value from stack; read d16 using # 8968c2ecf20Sopenharmony_ci# _imem_read_word(); fetch may fail -> branch to # 8978c2ecf20Sopenharmony_ci# isp_iacc() # 8988c2ecf20Sopenharmony_ci# (xxx).w,(xxx).l - use _imem_read_{word,long}() to fetch # 8998c2ecf20Sopenharmony_ci# address; fetch may fail # 9008c2ecf20Sopenharmony_ci# #<data> - return address of immediate value; set immed_flg # 9018c2ecf20Sopenharmony_ci# in SPCOND_FLG # 9028c2ecf20Sopenharmony_ci# (d16,PC) - fetch stacked PC value; read d16 using # 9038c2ecf20Sopenharmony_ci# _imem_read_word(); fetch may fail -> branch to # 9048c2ecf20Sopenharmony_ci# isp_iacc() # 9058c2ecf20Sopenharmony_ci# everything else - read needed displacements as appropriate w/ # 9068c2ecf20Sopenharmony_ci# _imem_read_{word,long}(); read may fail; if memory # 9078c2ecf20Sopenharmony_ci# indirect, read indirect address using # 9088c2ecf20Sopenharmony_ci# _dmem_read_long() which may also fail # 9098c2ecf20Sopenharmony_ci# # 9108c2ecf20Sopenharmony_ci######################################################################### 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci global _calc_ea 9138c2ecf20Sopenharmony_ci_calc_ea: 9148c2ecf20Sopenharmony_ci mov.l %d0,%a0 # move # bytes to a0 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci# MODE and REG are taken from the EXC_OPWORD. 9178c2ecf20Sopenharmony_ci mov.w EXC_OPWORD(%a6),%d0 # fetch opcode word 9188c2ecf20Sopenharmony_ci mov.w %d0,%d1 # make a copy 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci andi.w &0x3f,%d0 # extract mode field 9218c2ecf20Sopenharmony_ci andi.l &0x7,%d1 # extract reg field 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci# jump to the corresponding function for each {MODE,REG} pair. 9248c2ecf20Sopenharmony_ci mov.w (tbl_ea_mode.b,%pc,%d0.w*2), %d0 # fetch jmp distance 9258c2ecf20Sopenharmony_ci jmp (tbl_ea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci swbeg &64 9288c2ecf20Sopenharmony_citbl_ea_mode: 9298c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9308c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9318c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9328c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9338c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9348c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9358c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9368c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9398c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9408c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9418c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9428c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9438c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9448c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9458c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci short addr_ind_a0 - tbl_ea_mode 9488c2ecf20Sopenharmony_ci short addr_ind_a1 - tbl_ea_mode 9498c2ecf20Sopenharmony_ci short addr_ind_a2 - tbl_ea_mode 9508c2ecf20Sopenharmony_ci short addr_ind_a3 - tbl_ea_mode 9518c2ecf20Sopenharmony_ci short addr_ind_a4 - tbl_ea_mode 9528c2ecf20Sopenharmony_ci short addr_ind_a5 - tbl_ea_mode 9538c2ecf20Sopenharmony_ci short addr_ind_a6 - tbl_ea_mode 9548c2ecf20Sopenharmony_ci short addr_ind_a7 - tbl_ea_mode 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci short addr_ind_p_a0 - tbl_ea_mode 9578c2ecf20Sopenharmony_ci short addr_ind_p_a1 - tbl_ea_mode 9588c2ecf20Sopenharmony_ci short addr_ind_p_a2 - tbl_ea_mode 9598c2ecf20Sopenharmony_ci short addr_ind_p_a3 - tbl_ea_mode 9608c2ecf20Sopenharmony_ci short addr_ind_p_a4 - tbl_ea_mode 9618c2ecf20Sopenharmony_ci short addr_ind_p_a5 - tbl_ea_mode 9628c2ecf20Sopenharmony_ci short addr_ind_p_a6 - tbl_ea_mode 9638c2ecf20Sopenharmony_ci short addr_ind_p_a7 - tbl_ea_mode 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci short addr_ind_m_a0 - tbl_ea_mode 9668c2ecf20Sopenharmony_ci short addr_ind_m_a1 - tbl_ea_mode 9678c2ecf20Sopenharmony_ci short addr_ind_m_a2 - tbl_ea_mode 9688c2ecf20Sopenharmony_ci short addr_ind_m_a3 - tbl_ea_mode 9698c2ecf20Sopenharmony_ci short addr_ind_m_a4 - tbl_ea_mode 9708c2ecf20Sopenharmony_ci short addr_ind_m_a5 - tbl_ea_mode 9718c2ecf20Sopenharmony_ci short addr_ind_m_a6 - tbl_ea_mode 9728c2ecf20Sopenharmony_ci short addr_ind_m_a7 - tbl_ea_mode 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci short addr_ind_disp_a0 - tbl_ea_mode 9758c2ecf20Sopenharmony_ci short addr_ind_disp_a1 - tbl_ea_mode 9768c2ecf20Sopenharmony_ci short addr_ind_disp_a2 - tbl_ea_mode 9778c2ecf20Sopenharmony_ci short addr_ind_disp_a3 - tbl_ea_mode 9788c2ecf20Sopenharmony_ci short addr_ind_disp_a4 - tbl_ea_mode 9798c2ecf20Sopenharmony_ci short addr_ind_disp_a5 - tbl_ea_mode 9808c2ecf20Sopenharmony_ci short addr_ind_disp_a6 - tbl_ea_mode 9818c2ecf20Sopenharmony_ci short addr_ind_disp_a7 - tbl_ea_mode 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 9848c2ecf20Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 9858c2ecf20Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 9868c2ecf20Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 9878c2ecf20Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 9888c2ecf20Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 9898c2ecf20Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 9908c2ecf20Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci short abs_short - tbl_ea_mode 9938c2ecf20Sopenharmony_ci short abs_long - tbl_ea_mode 9948c2ecf20Sopenharmony_ci short pc_ind - tbl_ea_mode 9958c2ecf20Sopenharmony_ci short pc_ind_ext - tbl_ea_mode 9968c2ecf20Sopenharmony_ci short immediate - tbl_ea_mode 9978c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9988c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 9998c2ecf20Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci################################### 10028c2ecf20Sopenharmony_ci# Address register indirect: (An) # 10038c2ecf20Sopenharmony_ci################################### 10048c2ecf20Sopenharmony_ciaddr_ind_a0: 10058c2ecf20Sopenharmony_ci mov.l EXC_A0(%a6),%a0 # Get current a0 10068c2ecf20Sopenharmony_ci rts 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ciaddr_ind_a1: 10098c2ecf20Sopenharmony_ci mov.l EXC_A1(%a6),%a0 # Get current a1 10108c2ecf20Sopenharmony_ci rts 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ciaddr_ind_a2: 10138c2ecf20Sopenharmony_ci mov.l EXC_A2(%a6),%a0 # Get current a2 10148c2ecf20Sopenharmony_ci rts 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ciaddr_ind_a3: 10178c2ecf20Sopenharmony_ci mov.l EXC_A3(%a6),%a0 # Get current a3 10188c2ecf20Sopenharmony_ci rts 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ciaddr_ind_a4: 10218c2ecf20Sopenharmony_ci mov.l EXC_A4(%a6),%a0 # Get current a4 10228c2ecf20Sopenharmony_ci rts 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ciaddr_ind_a5: 10258c2ecf20Sopenharmony_ci mov.l EXC_A5(%a6),%a0 # Get current a5 10268c2ecf20Sopenharmony_ci rts 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ciaddr_ind_a6: 10298c2ecf20Sopenharmony_ci mov.l EXC_A6(%a6),%a0 # Get current a6 10308c2ecf20Sopenharmony_ci rts 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ciaddr_ind_a7: 10338c2ecf20Sopenharmony_ci mov.l EXC_A7(%a6),%a0 # Get current a7 10348c2ecf20Sopenharmony_ci rts 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci##################################################### 10378c2ecf20Sopenharmony_ci# Address register indirect w/ postincrement: (An)+ # 10388c2ecf20Sopenharmony_ci##################################################### 10398c2ecf20Sopenharmony_ciaddr_ind_p_a0: 10408c2ecf20Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 10418c2ecf20Sopenharmony_ci mov.l EXC_A0(%a6),%a0 # load current value 10428c2ecf20Sopenharmony_ci add.l %a0,%d0 # increment 10438c2ecf20Sopenharmony_ci mov.l %d0,EXC_A0(%a6) # save incremented value 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 10468c2ecf20Sopenharmony_ci mov.b &0x0,EXC_SAVREG(%a6) # save regno, too 10478c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 10488c2ecf20Sopenharmony_ci rts 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ciaddr_ind_p_a1: 10518c2ecf20Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 10528c2ecf20Sopenharmony_ci mov.l EXC_A1(%a6),%a0 # load current value 10538c2ecf20Sopenharmony_ci add.l %a0,%d0 # increment 10548c2ecf20Sopenharmony_ci mov.l %d0,EXC_A1(%a6) # save incremented value 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 10578c2ecf20Sopenharmony_ci mov.b &0x1,EXC_SAVREG(%a6) # save regno, too 10588c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 10598c2ecf20Sopenharmony_ci rts 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ciaddr_ind_p_a2: 10628c2ecf20Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 10638c2ecf20Sopenharmony_ci mov.l EXC_A2(%a6),%a0 # load current value 10648c2ecf20Sopenharmony_ci add.l %a0,%d0 # increment 10658c2ecf20Sopenharmony_ci mov.l %d0,EXC_A2(%a6) # save incremented value 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 10688c2ecf20Sopenharmony_ci mov.b &0x2,EXC_SAVREG(%a6) # save regno, too 10698c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 10708c2ecf20Sopenharmony_ci rts 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ciaddr_ind_p_a3: 10738c2ecf20Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 10748c2ecf20Sopenharmony_ci mov.l EXC_A3(%a6),%a0 # load current value 10758c2ecf20Sopenharmony_ci add.l %a0,%d0 # increment 10768c2ecf20Sopenharmony_ci mov.l %d0,EXC_A3(%a6) # save incremented value 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 10798c2ecf20Sopenharmony_ci mov.b &0x3,EXC_SAVREG(%a6) # save regno, too 10808c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 10818c2ecf20Sopenharmony_ci rts 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ciaddr_ind_p_a4: 10848c2ecf20Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 10858c2ecf20Sopenharmony_ci mov.l EXC_A4(%a6),%a0 # load current value 10868c2ecf20Sopenharmony_ci add.l %a0,%d0 # increment 10878c2ecf20Sopenharmony_ci mov.l %d0,EXC_A4(%a6) # save incremented value 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 10908c2ecf20Sopenharmony_ci mov.b &0x4,EXC_SAVREG(%a6) # save regno, too 10918c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 10928c2ecf20Sopenharmony_ci rts 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ciaddr_ind_p_a5: 10958c2ecf20Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 10968c2ecf20Sopenharmony_ci mov.l EXC_A5(%a6),%a0 # load current value 10978c2ecf20Sopenharmony_ci add.l %a0,%d0 # increment 10988c2ecf20Sopenharmony_ci mov.l %d0,EXC_A5(%a6) # save incremented value 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 11018c2ecf20Sopenharmony_ci mov.b &0x5,EXC_SAVREG(%a6) # save regno, too 11028c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11038c2ecf20Sopenharmony_ci rts 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ciaddr_ind_p_a6: 11068c2ecf20Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 11078c2ecf20Sopenharmony_ci mov.l EXC_A6(%a6),%a0 # load current value 11088c2ecf20Sopenharmony_ci add.l %a0,%d0 # increment 11098c2ecf20Sopenharmony_ci mov.l %d0,EXC_A6(%a6) # save incremented value 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 11128c2ecf20Sopenharmony_ci mov.b &0x6,EXC_SAVREG(%a6) # save regno, too 11138c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11148c2ecf20Sopenharmony_ci rts 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ciaddr_ind_p_a7: 11178c2ecf20Sopenharmony_ci mov.b &mia7_flg,SPCOND_FLG(%a6) # set "special case" flag 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 11208c2ecf20Sopenharmony_ci mov.l EXC_A7(%a6),%a0 # load current value 11218c2ecf20Sopenharmony_ci add.l %a0,%d0 # increment 11228c2ecf20Sopenharmony_ci mov.l %d0,EXC_A7(%a6) # save incremented value 11238c2ecf20Sopenharmony_ci rts 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci#################################################### 11268c2ecf20Sopenharmony_ci# Address register indirect w/ predecrement: -(An) # 11278c2ecf20Sopenharmony_ci#################################################### 11288c2ecf20Sopenharmony_ciaddr_ind_m_a0: 11298c2ecf20Sopenharmony_ci mov.l EXC_A0(%a6),%d0 # Get current a0 11308c2ecf20Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11318c2ecf20Sopenharmony_ci sub.l %a0,%d0 # Decrement 11328c2ecf20Sopenharmony_ci mov.l %d0,EXC_A0(%a6) # Save decr value 11338c2ecf20Sopenharmony_ci mov.l %d0,%a0 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci mov.b &0x0,EXC_SAVREG(%a6) # save regno, too 11368c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11378c2ecf20Sopenharmony_ci rts 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ciaddr_ind_m_a1: 11408c2ecf20Sopenharmony_ci mov.l EXC_A1(%a6),%d0 # Get current a1 11418c2ecf20Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11428c2ecf20Sopenharmony_ci sub.l %a0,%d0 # Decrement 11438c2ecf20Sopenharmony_ci mov.l %d0,EXC_A1(%a6) # Save decr value 11448c2ecf20Sopenharmony_ci mov.l %d0,%a0 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci mov.b &0x1,EXC_SAVREG(%a6) # save regno, too 11478c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11488c2ecf20Sopenharmony_ci rts 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ciaddr_ind_m_a2: 11518c2ecf20Sopenharmony_ci mov.l EXC_A2(%a6),%d0 # Get current a2 11528c2ecf20Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11538c2ecf20Sopenharmony_ci sub.l %a0,%d0 # Decrement 11548c2ecf20Sopenharmony_ci mov.l %d0,EXC_A2(%a6) # Save decr value 11558c2ecf20Sopenharmony_ci mov.l %d0,%a0 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci mov.b &0x2,EXC_SAVREG(%a6) # save regno, too 11588c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11598c2ecf20Sopenharmony_ci rts 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ciaddr_ind_m_a3: 11628c2ecf20Sopenharmony_ci mov.l EXC_A3(%a6),%d0 # Get current a3 11638c2ecf20Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11648c2ecf20Sopenharmony_ci sub.l %a0,%d0 # Decrement 11658c2ecf20Sopenharmony_ci mov.l %d0,EXC_A3(%a6) # Save decr value 11668c2ecf20Sopenharmony_ci mov.l %d0,%a0 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci mov.b &0x3,EXC_SAVREG(%a6) # save regno, too 11698c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11708c2ecf20Sopenharmony_ci rts 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ciaddr_ind_m_a4: 11738c2ecf20Sopenharmony_ci mov.l EXC_A4(%a6),%d0 # Get current a4 11748c2ecf20Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11758c2ecf20Sopenharmony_ci sub.l %a0,%d0 # Decrement 11768c2ecf20Sopenharmony_ci mov.l %d0,EXC_A4(%a6) # Save decr value 11778c2ecf20Sopenharmony_ci mov.l %d0,%a0 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci mov.b &0x4,EXC_SAVREG(%a6) # save regno, too 11808c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11818c2ecf20Sopenharmony_ci rts 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ciaddr_ind_m_a5: 11848c2ecf20Sopenharmony_ci mov.l EXC_A5(%a6),%d0 # Get current a5 11858c2ecf20Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11868c2ecf20Sopenharmony_ci sub.l %a0,%d0 # Decrement 11878c2ecf20Sopenharmony_ci mov.l %d0,EXC_A5(%a6) # Save decr value 11888c2ecf20Sopenharmony_ci mov.l %d0,%a0 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci mov.b &0x5,EXC_SAVREG(%a6) # save regno, too 11918c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 11928c2ecf20Sopenharmony_ci rts 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ciaddr_ind_m_a6: 11958c2ecf20Sopenharmony_ci mov.l EXC_A6(%a6),%d0 # Get current a6 11968c2ecf20Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 11978c2ecf20Sopenharmony_ci sub.l %a0,%d0 # Decrement 11988c2ecf20Sopenharmony_ci mov.l %d0,EXC_A6(%a6) # Save decr value 11998c2ecf20Sopenharmony_ci mov.l %d0,%a0 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci mov.b &0x6,EXC_SAVREG(%a6) # save regno, too 12028c2ecf20Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 12038c2ecf20Sopenharmony_ci rts 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ciaddr_ind_m_a7: 12068c2ecf20Sopenharmony_ci mov.b &mda7_flg,SPCOND_FLG(%a6) # set "special case" flag 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci mov.l EXC_A7(%a6),%d0 # Get current a7 12098c2ecf20Sopenharmony_ci sub.l %a0,%d0 # Decrement 12108c2ecf20Sopenharmony_ci mov.l %d0,EXC_A7(%a6) # Save decr value 12118c2ecf20Sopenharmony_ci mov.l %d0,%a0 12128c2ecf20Sopenharmony_ci rts 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci######################################################## 12158c2ecf20Sopenharmony_ci# Address register indirect w/ displacement: (d16, An) # 12168c2ecf20Sopenharmony_ci######################################################## 12178c2ecf20Sopenharmony_ciaddr_ind_disp_a0: 12188c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12198c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12208c2ecf20Sopenharmony_ci bsr.l _imem_read_word 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 12238c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 12268c2ecf20Sopenharmony_ci add.l EXC_A0(%a6),%a0 # a0 + d16 12278c2ecf20Sopenharmony_ci rts 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ciaddr_ind_disp_a1: 12308c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12318c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12328c2ecf20Sopenharmony_ci bsr.l _imem_read_word 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 12358c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 12388c2ecf20Sopenharmony_ci add.l EXC_A1(%a6),%a0 # a1 + d16 12398c2ecf20Sopenharmony_ci rts 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ciaddr_ind_disp_a2: 12428c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12438c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12448c2ecf20Sopenharmony_ci bsr.l _imem_read_word 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 12478c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 12508c2ecf20Sopenharmony_ci add.l EXC_A2(%a6),%a0 # a2 + d16 12518c2ecf20Sopenharmony_ci rts 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ciaddr_ind_disp_a3: 12548c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12558c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12568c2ecf20Sopenharmony_ci bsr.l _imem_read_word 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 12598c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 12628c2ecf20Sopenharmony_ci add.l EXC_A3(%a6),%a0 # a3 + d16 12638c2ecf20Sopenharmony_ci rts 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ciaddr_ind_disp_a4: 12668c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12678c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12688c2ecf20Sopenharmony_ci bsr.l _imem_read_word 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 12718c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 12748c2ecf20Sopenharmony_ci add.l EXC_A4(%a6),%a0 # a4 + d16 12758c2ecf20Sopenharmony_ci rts 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ciaddr_ind_disp_a5: 12788c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12798c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12808c2ecf20Sopenharmony_ci bsr.l _imem_read_word 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 12838c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 12868c2ecf20Sopenharmony_ci add.l EXC_A5(%a6),%a0 # a5 + d16 12878c2ecf20Sopenharmony_ci rts 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ciaddr_ind_disp_a6: 12908c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 12918c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 12928c2ecf20Sopenharmony_ci bsr.l _imem_read_word 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 12958c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 12988c2ecf20Sopenharmony_ci add.l EXC_A6(%a6),%a0 # a6 + d16 12998c2ecf20Sopenharmony_ci rts 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ciaddr_ind_disp_a7: 13028c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 13038c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 13048c2ecf20Sopenharmony_ci bsr.l _imem_read_word 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 13078c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 13108c2ecf20Sopenharmony_ci add.l EXC_A7(%a6),%a0 # a7 + d16 13118c2ecf20Sopenharmony_ci rts 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci######################################################################## 13148c2ecf20Sopenharmony_ci# Address register indirect w/ index(8-bit displacement): (dn, An, Xn) # 13158c2ecf20Sopenharmony_ci# " " " w/ " (base displacement): (bd, An, Xn) # 13168c2ecf20Sopenharmony_ci# Memory indirect postindexed: ([bd, An], Xn, od) # 13178c2ecf20Sopenharmony_ci# Memory indirect preindexed: ([bd, An, Xn], od) # 13188c2ecf20Sopenharmony_ci######################################################################## 13198c2ecf20Sopenharmony_ci_addr_ind_ext: 13208c2ecf20Sopenharmony_ci mov.l %d1,-(%sp) 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 13238c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 13248c2ecf20Sopenharmony_ci bsr.l _imem_read_word # fetch extword in d0 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 13278c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci mov.l (%sp)+,%d1 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci mov.l (EXC_AREGS,%a6,%d1.w*4),%a0 # put base in a0 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci btst &0x8,%d0 13348c2ecf20Sopenharmony_ci beq.b addr_ind_index_8bit # for ext word or not? 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci movm.l &0x3c00,-(%sp) # save d2-d5 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_ci mov.l %d0,%d5 # put extword in d5 13398c2ecf20Sopenharmony_ci mov.l %a0,%d3 # put base in d3 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci bra.l calc_mem_ind # calc memory indirect 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ciaddr_ind_index_8bit: 13448c2ecf20Sopenharmony_ci mov.l %d2,-(%sp) # save old d2 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci mov.l %d0,%d1 13478c2ecf20Sopenharmony_ci rol.w &0x4,%d1 13488c2ecf20Sopenharmony_ci andi.w &0xf,%d1 # extract index regno 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci btst &0xb,%d0 # is it word or long? 13538c2ecf20Sopenharmony_ci bne.b aii8_long 13548c2ecf20Sopenharmony_ci ext.l %d1 # sign extend word index 13558c2ecf20Sopenharmony_ciaii8_long: 13568c2ecf20Sopenharmony_ci mov.l %d0,%d2 13578c2ecf20Sopenharmony_ci rol.w &0x7,%d2 13588c2ecf20Sopenharmony_ci andi.l &0x3,%d2 # extract scale value 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci lsl.l %d2,%d1 # shift index by scale 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci extb.l %d0 # sign extend displacement 13638c2ecf20Sopenharmony_ci add.l %d1,%d0 # index + disp 13648c2ecf20Sopenharmony_ci add.l %d0,%a0 # An + (index + disp) 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci mov.l (%sp)+,%d2 # restore old d2 13678c2ecf20Sopenharmony_ci rts 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci###################### 13708c2ecf20Sopenharmony_ci# Immediate: #<data> # 13718c2ecf20Sopenharmony_ci######################################################################### 13728c2ecf20Sopenharmony_ci# word, long: <ea> of the data is the current extension word # 13738c2ecf20Sopenharmony_ci# pointer value. new extension word pointer is simply the old # 13748c2ecf20Sopenharmony_ci# plus the number of bytes in the data type(2 or 4). # 13758c2ecf20Sopenharmony_ci######################################################################### 13768c2ecf20Sopenharmony_ciimmediate: 13778c2ecf20Sopenharmony_ci mov.b &immed_flg,SPCOND_FLG(%a6) # set immediate flag 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch extension word ptr 13808c2ecf20Sopenharmony_ci rts 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci########################### 13838c2ecf20Sopenharmony_ci# Absolute short: (XXX).W # 13848c2ecf20Sopenharmony_ci########################### 13858c2ecf20Sopenharmony_ciabs_short: 13868c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 13878c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 13888c2ecf20Sopenharmony_ci bsr.l _imem_read_word # fetch short address 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 13918c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci mov.w %d0,%a0 # return <ea> in a0 13948c2ecf20Sopenharmony_ci rts 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci########################## 13978c2ecf20Sopenharmony_ci# Absolute long: (XXX).L # 13988c2ecf20Sopenharmony_ci########################## 13998c2ecf20Sopenharmony_ciabs_long: 14008c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 14018c2ecf20Sopenharmony_ci addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 14028c2ecf20Sopenharmony_ci bsr.l _imem_read_long # fetch long address 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 14058c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci mov.l %d0,%a0 # return <ea> in a0 14088c2ecf20Sopenharmony_ci rts 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci####################################################### 14118c2ecf20Sopenharmony_ci# Program counter indirect w/ displacement: (d16, PC) # 14128c2ecf20Sopenharmony_ci####################################################### 14138c2ecf20Sopenharmony_cipc_ind: 14148c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 14158c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 14168c2ecf20Sopenharmony_ci bsr.l _imem_read_word # fetch word displacement 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 14198c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci add.l EXC_EXTWPTR(%a6),%a0 # pc + d16 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci# _imem_read_word() increased the extwptr by 2. need to adjust here. 14268c2ecf20Sopenharmony_ci subq.l &0x2,%a0 # adjust <ea> 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci rts 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci########################################################## 14318c2ecf20Sopenharmony_ci# PC indirect w/ index(8-bit displacement): (d8, PC, An) # 14328c2ecf20Sopenharmony_ci# " " w/ " (base displacement): (bd, PC, An) # 14338c2ecf20Sopenharmony_ci# PC memory indirect postindexed: ([bd, PC], Xn, od) # 14348c2ecf20Sopenharmony_ci# PC memory indirect preindexed: ([bd, PC, Xn], od) # 14358c2ecf20Sopenharmony_ci########################################################## 14368c2ecf20Sopenharmony_cipc_ind_ext: 14378c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 14388c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 14398c2ecf20Sopenharmony_ci bsr.l _imem_read_word # fetch ext word 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 14428c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # put base in a0 14458c2ecf20Sopenharmony_ci subq.l &0x2,%a0 # adjust base 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci btst &0x8,%d0 # is disp only 8 bits? 14488c2ecf20Sopenharmony_ci beq.b pc_ind_index_8bit # yes 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci# the indexed addressing mode uses a base displacement of size 14518c2ecf20Sopenharmony_ci# word or long 14528c2ecf20Sopenharmony_ci movm.l &0x3c00,-(%sp) # save d2-d5 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci mov.l %d0,%d5 # put extword in d5 14558c2ecf20Sopenharmony_ci mov.l %a0,%d3 # put base in d3 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci bra.l calc_mem_ind # calc memory indirect 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_cipc_ind_index_8bit: 14608c2ecf20Sopenharmony_ci mov.l %d2,-(%sp) # create a temp register 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ci mov.l %d0,%d1 # make extword copy 14638c2ecf20Sopenharmony_ci rol.w &0x4,%d1 # rotate reg num into place 14648c2ecf20Sopenharmony_ci andi.w &0xf,%d1 # extract register number 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci btst &0xb,%d0 # is index word or long? 14698c2ecf20Sopenharmony_ci bne.b pii8_long # long 14708c2ecf20Sopenharmony_ci ext.l %d1 # sign extend word index 14718c2ecf20Sopenharmony_cipii8_long: 14728c2ecf20Sopenharmony_ci mov.l %d0,%d2 # make extword copy 14738c2ecf20Sopenharmony_ci rol.w &0x7,%d2 # rotate scale value into place 14748c2ecf20Sopenharmony_ci andi.l &0x3,%d2 # extract scale value 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci lsl.l %d2,%d1 # shift index by scale 14778c2ecf20Sopenharmony_ci 14788c2ecf20Sopenharmony_ci extb.l %d0 # sign extend displacement 14798c2ecf20Sopenharmony_ci add.l %d1,%d0 # index + disp 14808c2ecf20Sopenharmony_ci add.l %d0,%a0 # An + (index + disp) 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci mov.l (%sp)+,%d2 # restore temp register 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_ci rts 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci# a5 = exc_extwptr (global to uaeh) 14878c2ecf20Sopenharmony_ci# a4 = exc_opword (global to uaeh) 14888c2ecf20Sopenharmony_ci# a3 = exc_dregs (global to uaeh) 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci# d2 = index (internal " " ) 14918c2ecf20Sopenharmony_ci# d3 = base (internal " " ) 14928c2ecf20Sopenharmony_ci# d4 = od (internal " " ) 14938c2ecf20Sopenharmony_ci# d5 = extword (internal " " ) 14948c2ecf20Sopenharmony_cicalc_mem_ind: 14958c2ecf20Sopenharmony_ci btst &0x6,%d5 # is the index suppressed? 14968c2ecf20Sopenharmony_ci beq.b calc_index 14978c2ecf20Sopenharmony_ci clr.l %d2 # yes, so index = 0 14988c2ecf20Sopenharmony_ci bra.b base_supp_ck 14998c2ecf20Sopenharmony_cicalc_index: 15008c2ecf20Sopenharmony_ci bfextu %d5{&16:&4},%d2 15018c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d2.w*4),%d2 15028c2ecf20Sopenharmony_ci btst &0xb,%d5 # is index word or long? 15038c2ecf20Sopenharmony_ci bne.b no_ext 15048c2ecf20Sopenharmony_ci ext.l %d2 15058c2ecf20Sopenharmony_cino_ext: 15068c2ecf20Sopenharmony_ci bfextu %d5{&21:&2},%d0 15078c2ecf20Sopenharmony_ci lsl.l %d0,%d2 15088c2ecf20Sopenharmony_cibase_supp_ck: 15098c2ecf20Sopenharmony_ci btst &0x7,%d5 # is the bd suppressed? 15108c2ecf20Sopenharmony_ci beq.b no_base_sup 15118c2ecf20Sopenharmony_ci clr.l %d3 15128c2ecf20Sopenharmony_cino_base_sup: 15138c2ecf20Sopenharmony_ci bfextu %d5{&26:&2},%d0 # get bd size 15148c2ecf20Sopenharmony_ci# beq.l _error # if (size == 0) it's reserved 15158c2ecf20Sopenharmony_ci cmpi.b %d0,&2 15168c2ecf20Sopenharmony_ci blt.b no_bd 15178c2ecf20Sopenharmony_ci beq.b get_word_bd 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 15208c2ecf20Sopenharmony_ci addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 15218c2ecf20Sopenharmony_ci bsr.l _imem_read_long 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 15248c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci bra.b chk_ind 15278c2ecf20Sopenharmony_ciget_word_bd: 15288c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 15298c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 15308c2ecf20Sopenharmony_ci bsr.l _imem_read_word 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 15338c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ci ext.l %d0 # sign extend bd 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_cichk_ind: 15388c2ecf20Sopenharmony_ci add.l %d0,%d3 # base += bd 15398c2ecf20Sopenharmony_cino_bd: 15408c2ecf20Sopenharmony_ci bfextu %d5{&30:&2},%d0 # is od suppressed? 15418c2ecf20Sopenharmony_ci beq.w aii_bd 15428c2ecf20Sopenharmony_ci cmpi.b %d0,&0x2 15438c2ecf20Sopenharmony_ci blt.b null_od 15448c2ecf20Sopenharmony_ci beq.b word_od 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 15478c2ecf20Sopenharmony_ci addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 15488c2ecf20Sopenharmony_ci bsr.l _imem_read_long 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 15518c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci bra.b add_them 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ciword_od: 15568c2ecf20Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 15578c2ecf20Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 15588c2ecf20Sopenharmony_ci bsr.l _imem_read_word 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 15618c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_ci ext.l %d0 # sign extend od 15648c2ecf20Sopenharmony_ci bra.b add_them 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_cinull_od: 15678c2ecf20Sopenharmony_ci clr.l %d0 15688c2ecf20Sopenharmony_ciadd_them: 15698c2ecf20Sopenharmony_ci mov.l %d0,%d4 15708c2ecf20Sopenharmony_ci btst &0x2,%d5 # pre or post indexing? 15718c2ecf20Sopenharmony_ci beq.b pre_indexed 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_ci mov.l %d3,%a0 15748c2ecf20Sopenharmony_ci bsr.l _dmem_read_long 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 15778c2ecf20Sopenharmony_ci bne.b calc_ea_err # yes 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci add.l %d2,%d0 # <ea> += index 15808c2ecf20Sopenharmony_ci add.l %d4,%d0 # <ea> += od 15818c2ecf20Sopenharmony_ci bra.b done_ea 15828c2ecf20Sopenharmony_ci 15838c2ecf20Sopenharmony_cipre_indexed: 15848c2ecf20Sopenharmony_ci add.l %d2,%d3 # preindexing 15858c2ecf20Sopenharmony_ci mov.l %d3,%a0 15868c2ecf20Sopenharmony_ci bsr.l _dmem_read_long 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 15898c2ecf20Sopenharmony_ci bne.b calc_ea_err # yes 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_ci add.l %d4,%d0 # ea += od 15928c2ecf20Sopenharmony_ci bra.b done_ea 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ciaii_bd: 15958c2ecf20Sopenharmony_ci add.l %d2,%d3 # ea = (base + bd) + index 15968c2ecf20Sopenharmony_ci mov.l %d3,%d0 15978c2ecf20Sopenharmony_cidone_ea: 15988c2ecf20Sopenharmony_ci mov.l %d0,%a0 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci movm.l (%sp)+,&0x003c # restore d2-d5 16018c2ecf20Sopenharmony_ci rts 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci# if dmem_read_long() returns a fail message in d1, the package 16048c2ecf20Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw 16058c2ecf20Sopenharmony_ci# and the failing address to the routine that creates the new frame. 16068c2ecf20Sopenharmony_ci# FSLW: 16078c2ecf20Sopenharmony_ci# read = true 16088c2ecf20Sopenharmony_ci# size = longword 16098c2ecf20Sopenharmony_ci# TM = data 16108c2ecf20Sopenharmony_ci# software emulation error = true 16118c2ecf20Sopenharmony_cicalc_ea_err: 16128c2ecf20Sopenharmony_ci mov.l %d3,%a0 # pass failing address 16138c2ecf20Sopenharmony_ci mov.l &0x01010001,%d0 # pass fslw 16148c2ecf20Sopenharmony_ci bra.l isp_dacc 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci######################################################################### 16178c2ecf20Sopenharmony_ci# XDEF **************************************************************** # 16188c2ecf20Sopenharmony_ci# _moveperipheral(): routine to emulate movep instruction # 16198c2ecf20Sopenharmony_ci# # 16208c2ecf20Sopenharmony_ci# XREF **************************************************************** # 16218c2ecf20Sopenharmony_ci# _dmem_read_byte() - read byte from memory # 16228c2ecf20Sopenharmony_ci# _dmem_write_byte() - write byte to memory # 16238c2ecf20Sopenharmony_ci# isp_dacc() - handle data access error exception # 16248c2ecf20Sopenharmony_ci# # 16258c2ecf20Sopenharmony_ci# INPUT *************************************************************** # 16268c2ecf20Sopenharmony_ci# none # 16278c2ecf20Sopenharmony_ci# # 16288c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** # 16298c2ecf20Sopenharmony_ci# If exiting through isp_dacc... # 16308c2ecf20Sopenharmony_ci# a0 = failing address # 16318c2ecf20Sopenharmony_ci# d0 = FSLW # 16328c2ecf20Sopenharmony_ci# else # 16338c2ecf20Sopenharmony_ci# none # 16348c2ecf20Sopenharmony_ci# # 16358c2ecf20Sopenharmony_ci# ALGORITHM *********************************************************** # 16368c2ecf20Sopenharmony_ci# Decode the movep instruction words stored at EXC_OPWORD and # 16378c2ecf20Sopenharmony_ci# either read or write the required bytes from/to memory. Use the # 16388c2ecf20Sopenharmony_ci# _dmem_{read,write}_byte() routines. If one of the memory routines # 16398c2ecf20Sopenharmony_ci# returns a failing value, we must pass the failing address and a FSLW # 16408c2ecf20Sopenharmony_ci# to the _isp_dacc() routine. # 16418c2ecf20Sopenharmony_ci# Since this instruction is used to access peripherals, make sure # 16428c2ecf20Sopenharmony_ci# to only access the required bytes. # 16438c2ecf20Sopenharmony_ci# # 16448c2ecf20Sopenharmony_ci######################################################################### 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci########################### 16478c2ecf20Sopenharmony_ci# movep.(w,l) Dx,(d,Ay) # 16488c2ecf20Sopenharmony_ci# movep.(w,l) (d,Ay),Dx # 16498c2ecf20Sopenharmony_ci########################### 16508c2ecf20Sopenharmony_ci global _moveperipheral 16518c2ecf20Sopenharmony_ci_moveperipheral: 16528c2ecf20Sopenharmony_ci mov.w EXC_OPWORD(%a6),%d1 # fetch the opcode word 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci mov.b %d1,%d0 16558c2ecf20Sopenharmony_ci and.w &0x7,%d0 # extract Ay from opcode word 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci mov.l (EXC_AREGS,%a6,%d0.w*4),%a0 # fetch ay 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci add.w EXC_EXTWORD(%a6),%a0 # add: an + sgn_ext(disp) 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci btst &0x7,%d1 # (reg 2 mem) or (mem 2 reg) 16628c2ecf20Sopenharmony_ci beq.w mem2reg 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_ci# reg2mem: fetch dx, then write it to memory 16658c2ecf20Sopenharmony_cireg2mem: 16668c2ecf20Sopenharmony_ci mov.w %d1,%d0 16678c2ecf20Sopenharmony_ci rol.w &0x7,%d0 16688c2ecf20Sopenharmony_ci and.w &0x7,%d0 # extract Dx from opcode word 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4), %d0 # fetch dx 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci btst &0x6,%d1 # word or long operation? 16738c2ecf20Sopenharmony_ci beq.b r2mwtrans 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ci# a0 = dst addr 16768c2ecf20Sopenharmony_ci# d0 = Dx 16778c2ecf20Sopenharmony_cir2mltrans: 16788c2ecf20Sopenharmony_ci mov.l %d0,%d2 # store data 16798c2ecf20Sopenharmony_ci mov.l %a0,%a2 # store addr 16808c2ecf20Sopenharmony_ci rol.l &0x8,%d2 16818c2ecf20Sopenharmony_ci mov.l %d2,%d0 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci bsr.l _dmem_write_byte # os : write hi 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 16868c2ecf20Sopenharmony_ci bne.w movp_write_err # yes 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci add.w &0x2,%a2 # incr addr 16898c2ecf20Sopenharmony_ci mov.l %a2,%a0 16908c2ecf20Sopenharmony_ci rol.l &0x8,%d2 16918c2ecf20Sopenharmony_ci mov.l %d2,%d0 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci bsr.l _dmem_write_byte # os : write lo 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 16968c2ecf20Sopenharmony_ci bne.w movp_write_err # yes 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci add.w &0x2,%a2 # incr addr 16998c2ecf20Sopenharmony_ci mov.l %a2,%a0 17008c2ecf20Sopenharmony_ci rol.l &0x8,%d2 17018c2ecf20Sopenharmony_ci mov.l %d2,%d0 17028c2ecf20Sopenharmony_ci 17038c2ecf20Sopenharmony_ci bsr.l _dmem_write_byte # os : write lo 17048c2ecf20Sopenharmony_ci 17058c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 17068c2ecf20Sopenharmony_ci bne.w movp_write_err # yes 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci add.w &0x2,%a2 # incr addr 17098c2ecf20Sopenharmony_ci mov.l %a2,%a0 17108c2ecf20Sopenharmony_ci rol.l &0x8,%d2 17118c2ecf20Sopenharmony_ci mov.l %d2,%d0 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_ci bsr.l _dmem_write_byte # os : write lo 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 17168c2ecf20Sopenharmony_ci bne.w movp_write_err # yes 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci rts 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci# a0 = dst addr 17218c2ecf20Sopenharmony_ci# d0 = Dx 17228c2ecf20Sopenharmony_cir2mwtrans: 17238c2ecf20Sopenharmony_ci mov.l %d0,%d2 # store data 17248c2ecf20Sopenharmony_ci mov.l %a0,%a2 # store addr 17258c2ecf20Sopenharmony_ci lsr.w &0x8,%d0 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci bsr.l _dmem_write_byte # os : write hi 17288c2ecf20Sopenharmony_ci 17298c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 17308c2ecf20Sopenharmony_ci bne.w movp_write_err # yes 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ci add.w &0x2,%a2 17338c2ecf20Sopenharmony_ci mov.l %a2,%a0 17348c2ecf20Sopenharmony_ci mov.l %d2,%d0 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_ci bsr.l _dmem_write_byte # os : write lo 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 17398c2ecf20Sopenharmony_ci bne.w movp_write_err # yes 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci rts 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci# mem2reg: read bytes from memory. 17448c2ecf20Sopenharmony_ci# determines the dest register, and then writes the bytes into it. 17458c2ecf20Sopenharmony_cimem2reg: 17468c2ecf20Sopenharmony_ci btst &0x6,%d1 # word or long operation? 17478c2ecf20Sopenharmony_ci beq.b m2rwtrans 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_ci# a0 = dst addr 17508c2ecf20Sopenharmony_cim2rltrans: 17518c2ecf20Sopenharmony_ci mov.l %a0,%a2 # store addr 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci bsr.l _dmem_read_byte # read first byte 17548c2ecf20Sopenharmony_ci 17558c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 17568c2ecf20Sopenharmony_ci bne.w movp_read_err # yes 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_ci mov.l %d0,%d2 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_ci add.w &0x2,%a2 # incr addr by 2 bytes 17618c2ecf20Sopenharmony_ci mov.l %a2,%a0 17628c2ecf20Sopenharmony_ci 17638c2ecf20Sopenharmony_ci bsr.l _dmem_read_byte # read second byte 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 17668c2ecf20Sopenharmony_ci bne.w movp_read_err # yes 17678c2ecf20Sopenharmony_ci 17688c2ecf20Sopenharmony_ci lsl.w &0x8,%d2 17698c2ecf20Sopenharmony_ci mov.b %d0,%d2 # append bytes 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci add.w &0x2,%a2 # incr addr by 2 bytes 17728c2ecf20Sopenharmony_ci mov.l %a2,%a0 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_ci bsr.l _dmem_read_byte # read second byte 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 17778c2ecf20Sopenharmony_ci bne.w movp_read_err # yes 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ci lsl.l &0x8,%d2 17808c2ecf20Sopenharmony_ci mov.b %d0,%d2 # append bytes 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci add.w &0x2,%a2 # incr addr by 2 bytes 17838c2ecf20Sopenharmony_ci mov.l %a2,%a0 17848c2ecf20Sopenharmony_ci 17858c2ecf20Sopenharmony_ci bsr.l _dmem_read_byte # read second byte 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 17888c2ecf20Sopenharmony_ci bne.w movp_read_err # yes 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_ci lsl.l &0x8,%d2 17918c2ecf20Sopenharmony_ci mov.b %d0,%d2 # append bytes 17928c2ecf20Sopenharmony_ci 17938c2ecf20Sopenharmony_ci mov.b EXC_OPWORD(%a6),%d1 17948c2ecf20Sopenharmony_ci lsr.b &0x1,%d1 17958c2ecf20Sopenharmony_ci and.w &0x7,%d1 # extract Dx from opcode word 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci mov.l %d2,(EXC_DREGS,%a6,%d1.w*4) # store dx 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_ci rts 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci# a0 = dst addr 18028c2ecf20Sopenharmony_cim2rwtrans: 18038c2ecf20Sopenharmony_ci mov.l %a0,%a2 # store addr 18048c2ecf20Sopenharmony_ci 18058c2ecf20Sopenharmony_ci bsr.l _dmem_read_byte # read first byte 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 18088c2ecf20Sopenharmony_ci bne.w movp_read_err # yes 18098c2ecf20Sopenharmony_ci 18108c2ecf20Sopenharmony_ci mov.l %d0,%d2 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci add.w &0x2,%a2 # incr addr by 2 bytes 18138c2ecf20Sopenharmony_ci mov.l %a2,%a0 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci bsr.l _dmem_read_byte # read second byte 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 18188c2ecf20Sopenharmony_ci bne.w movp_read_err # yes 18198c2ecf20Sopenharmony_ci 18208c2ecf20Sopenharmony_ci lsl.w &0x8,%d2 18218c2ecf20Sopenharmony_ci mov.b %d0,%d2 # append bytes 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci mov.b EXC_OPWORD(%a6),%d1 18248c2ecf20Sopenharmony_ci lsr.b &0x1,%d1 18258c2ecf20Sopenharmony_ci and.w &0x7,%d1 # extract Dx from opcode word 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_ci mov.w %d2,(EXC_DREGS+2,%a6,%d1.w*4) # store dx 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_ci rts 18308c2ecf20Sopenharmony_ci 18318c2ecf20Sopenharmony_ci# if dmem_{read,write}_byte() returns a fail message in d1, the package 18328c2ecf20Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw 18338c2ecf20Sopenharmony_ci# and the failing address to the routine that creates the new frame. 18348c2ecf20Sopenharmony_ci# FSLW: 18358c2ecf20Sopenharmony_ci# write = true 18368c2ecf20Sopenharmony_ci# size = byte 18378c2ecf20Sopenharmony_ci# TM = data 18388c2ecf20Sopenharmony_ci# software emulation error = true 18398c2ecf20Sopenharmony_cimovp_write_err: 18408c2ecf20Sopenharmony_ci mov.l %a2,%a0 # pass failing address 18418c2ecf20Sopenharmony_ci mov.l &0x00a10001,%d0 # pass fslw 18428c2ecf20Sopenharmony_ci bra.l isp_dacc 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci# FSLW: 18458c2ecf20Sopenharmony_ci# read = true 18468c2ecf20Sopenharmony_ci# size = byte 18478c2ecf20Sopenharmony_ci# TM = data 18488c2ecf20Sopenharmony_ci# software emulation error = true 18498c2ecf20Sopenharmony_cimovp_read_err: 18508c2ecf20Sopenharmony_ci mov.l %a2,%a0 # pass failing address 18518c2ecf20Sopenharmony_ci mov.l &0x01210001,%d0 # pass fslw 18528c2ecf20Sopenharmony_ci bra.l isp_dacc 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci######################################################################### 18558c2ecf20Sopenharmony_ci# XDEF **************************************************************** # 18568c2ecf20Sopenharmony_ci# _chk2_cmp2(): routine to emulate chk2/cmp2 instructions # 18578c2ecf20Sopenharmony_ci# # 18588c2ecf20Sopenharmony_ci# XREF **************************************************************** # 18598c2ecf20Sopenharmony_ci# _calc_ea(): calculate effective address # 18608c2ecf20Sopenharmony_ci# _dmem_read_long(): read operands # 18618c2ecf20Sopenharmony_ci# _dmem_read_word(): read operands # 18628c2ecf20Sopenharmony_ci# isp_dacc(): handle data access error exception # 18638c2ecf20Sopenharmony_ci# # 18648c2ecf20Sopenharmony_ci# INPUT *************************************************************** # 18658c2ecf20Sopenharmony_ci# none # 18668c2ecf20Sopenharmony_ci# # 18678c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** # 18688c2ecf20Sopenharmony_ci# If exiting through isp_dacc... # 18698c2ecf20Sopenharmony_ci# a0 = failing address # 18708c2ecf20Sopenharmony_ci# d0 = FSLW # 18718c2ecf20Sopenharmony_ci# else # 18728c2ecf20Sopenharmony_ci# none # 18738c2ecf20Sopenharmony_ci# # 18748c2ecf20Sopenharmony_ci# ALGORITHM *********************************************************** # 18758c2ecf20Sopenharmony_ci# First, calculate the effective address, then fetch the byte, # 18768c2ecf20Sopenharmony_ci# word, or longword sized operands. Then, in the interest of # 18778c2ecf20Sopenharmony_ci# simplicity, all operands are converted to longword size whether the # 18788c2ecf20Sopenharmony_ci# operation is byte, word, or long. The bounds are sign extended # 18798c2ecf20Sopenharmony_ci# accordingly. If Rn is a data register, Rn is also sign extended. If # 18808c2ecf20Sopenharmony_ci# Rn is an address register, it need not be sign extended since the # 18818c2ecf20Sopenharmony_ci# full register is always used. # 18828c2ecf20Sopenharmony_ci# The comparisons are made and the condition codes calculated. # 18838c2ecf20Sopenharmony_ci# If the instruction is chk2 and the Rn value is out-of-bounds, set # 18848c2ecf20Sopenharmony_ci# the ichk_flg in SPCOND_FLG. # 18858c2ecf20Sopenharmony_ci# If the memory fetch returns a failing value, pass the failing # 18868c2ecf20Sopenharmony_ci# address and FSLW to the isp_dacc() routine. # 18878c2ecf20Sopenharmony_ci# # 18888c2ecf20Sopenharmony_ci######################################################################### 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci global _chk2_cmp2 18918c2ecf20Sopenharmony_ci_chk2_cmp2: 18928c2ecf20Sopenharmony_ci 18938c2ecf20Sopenharmony_ci# passing size parameter doesn't matter since chk2 & cmp2 can't do 18948c2ecf20Sopenharmony_ci# either predecrement, postincrement, or immediate. 18958c2ecf20Sopenharmony_ci bsr.l _calc_ea # calculate <ea> 18968c2ecf20Sopenharmony_ci 18978c2ecf20Sopenharmony_ci mov.b EXC_EXTWORD(%a6), %d0 # fetch hi extension word 18988c2ecf20Sopenharmony_ci rol.b &0x4, %d0 # rotate reg bits into lo 18998c2ecf20Sopenharmony_ci and.w &0xf, %d0 # extract reg bits 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4), %d2 # get regval 19028c2ecf20Sopenharmony_ci 19038c2ecf20Sopenharmony_ci cmpi.b EXC_OPWORD(%a6), &0x2 # what size is operation? 19048c2ecf20Sopenharmony_ci blt.b chk2_cmp2_byte # size == byte 19058c2ecf20Sopenharmony_ci beq.b chk2_cmp2_word # size == word 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci# the bounds are longword size. call routine to read the lower 19088c2ecf20Sopenharmony_ci# bound into d0 and the higher bound into d1. 19098c2ecf20Sopenharmony_cichk2_cmp2_long: 19108c2ecf20Sopenharmony_ci mov.l %a0,%a2 # save copy of <ea> 19118c2ecf20Sopenharmony_ci bsr.l _dmem_read_long # fetch long lower bound 19128c2ecf20Sopenharmony_ci 19138c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 19148c2ecf20Sopenharmony_ci bne.w chk2_cmp2_err_l # yes 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci mov.l %d0,%d3 # save long lower bound 19178c2ecf20Sopenharmony_ci addq.l &0x4,%a2 19188c2ecf20Sopenharmony_ci mov.l %a2,%a0 # pass <ea> of long upper bound 19198c2ecf20Sopenharmony_ci bsr.l _dmem_read_long # fetch long upper bound 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 19228c2ecf20Sopenharmony_ci bne.w chk2_cmp2_err_l # yes 19238c2ecf20Sopenharmony_ci 19248c2ecf20Sopenharmony_ci mov.l %d0,%d1 # long upper bound in d1 19258c2ecf20Sopenharmony_ci mov.l %d3,%d0 # long lower bound in d0 19268c2ecf20Sopenharmony_ci bra.w chk2_cmp2_compare # go do the compare emulation 19278c2ecf20Sopenharmony_ci 19288c2ecf20Sopenharmony_ci# the bounds are word size. fetch them in one subroutine call by 19298c2ecf20Sopenharmony_ci# reading a longword. sign extend both. if it's a data operation, 19308c2ecf20Sopenharmony_ci# sign extend Rn to long, also. 19318c2ecf20Sopenharmony_cichk2_cmp2_word: 19328c2ecf20Sopenharmony_ci mov.l %a0,%a2 19338c2ecf20Sopenharmony_ci bsr.l _dmem_read_long # fetch 2 word bounds 19348c2ecf20Sopenharmony_ci 19358c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 19368c2ecf20Sopenharmony_ci bne.w chk2_cmp2_err_l # yes 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci mov.w %d0, %d1 # place hi in %d1 19398c2ecf20Sopenharmony_ci swap %d0 # place lo in %d0 19408c2ecf20Sopenharmony_ci 19418c2ecf20Sopenharmony_ci ext.l %d0 # sign extend lo bnd 19428c2ecf20Sopenharmony_ci ext.l %d1 # sign extend hi bnd 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci btst &0x7, EXC_EXTWORD(%a6) # address compare? 19458c2ecf20Sopenharmony_ci bne.w chk2_cmp2_compare # yes; don't sign extend 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci# operation is a data register compare. 19488c2ecf20Sopenharmony_ci# sign extend word to long so we can do simple longword compares. 19498c2ecf20Sopenharmony_ci ext.l %d2 # sign extend data word 19508c2ecf20Sopenharmony_ci bra.w chk2_cmp2_compare # go emulate compare 19518c2ecf20Sopenharmony_ci 19528c2ecf20Sopenharmony_ci# the bounds are byte size. fetch them in one subroutine call by 19538c2ecf20Sopenharmony_ci# reading a word. sign extend both. if it's a data operation, 19548c2ecf20Sopenharmony_ci# sign extend Rn to long, also. 19558c2ecf20Sopenharmony_cichk2_cmp2_byte: 19568c2ecf20Sopenharmony_ci mov.l %a0,%a2 19578c2ecf20Sopenharmony_ci bsr.l _dmem_read_word # fetch 2 byte bounds 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 19608c2ecf20Sopenharmony_ci bne.w chk2_cmp2_err_w # yes 19618c2ecf20Sopenharmony_ci 19628c2ecf20Sopenharmony_ci mov.b %d0, %d1 # place hi in %d1 19638c2ecf20Sopenharmony_ci lsr.w &0x8, %d0 # place lo in %d0 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci extb.l %d0 # sign extend lo bnd 19668c2ecf20Sopenharmony_ci extb.l %d1 # sign extend hi bnd 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_ci btst &0x7, EXC_EXTWORD(%a6) # address compare? 19698c2ecf20Sopenharmony_ci bne.b chk2_cmp2_compare # yes; don't sign extend 19708c2ecf20Sopenharmony_ci 19718c2ecf20Sopenharmony_ci# operation is a data register compare. 19728c2ecf20Sopenharmony_ci# sign extend byte to long so we can do simple longword compares. 19738c2ecf20Sopenharmony_ci extb.l %d2 # sign extend data byte 19748c2ecf20Sopenharmony_ci 19758c2ecf20Sopenharmony_ci# 19768c2ecf20Sopenharmony_ci# To set the ccodes correctly: 19778c2ecf20Sopenharmony_ci# (1) save 'Z' bit from (Rn - lo) 19788c2ecf20Sopenharmony_ci# (2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi)) 19798c2ecf20Sopenharmony_ci# (3) keep 'X', 'N', and 'V' from before instruction 19808c2ecf20Sopenharmony_ci# (4) combine ccodes 19818c2ecf20Sopenharmony_ci# 19828c2ecf20Sopenharmony_cichk2_cmp2_compare: 19838c2ecf20Sopenharmony_ci sub.l %d0, %d2 # (Rn - lo) 19848c2ecf20Sopenharmony_ci mov.w %cc, %d3 # fetch resulting ccodes 19858c2ecf20Sopenharmony_ci andi.b &0x4, %d3 # keep 'Z' bit 19868c2ecf20Sopenharmony_ci sub.l %d0, %d1 # (hi - lo) 19878c2ecf20Sopenharmony_ci cmp.l %d1,%d2 # ((hi - lo) - (Rn - hi)) 19888c2ecf20Sopenharmony_ci 19898c2ecf20Sopenharmony_ci mov.w %cc, %d4 # fetch resulting ccodes 19908c2ecf20Sopenharmony_ci or.b %d4, %d3 # combine w/ earlier ccodes 19918c2ecf20Sopenharmony_ci andi.b &0x5, %d3 # keep 'Z' and 'N' 19928c2ecf20Sopenharmony_ci 19938c2ecf20Sopenharmony_ci mov.w EXC_CC(%a6), %d4 # fetch old ccodes 19948c2ecf20Sopenharmony_ci andi.b &0x1a, %d4 # keep 'X','N','V' bits 19958c2ecf20Sopenharmony_ci or.b %d3, %d4 # insert new ccodes 19968c2ecf20Sopenharmony_ci mov.w %d4, EXC_CC(%a6) # save new ccodes 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci btst &0x3, EXC_EXTWORD(%a6) # separate chk2,cmp2 19998c2ecf20Sopenharmony_ci bne.b chk2_finish # it's a chk2 20008c2ecf20Sopenharmony_ci 20018c2ecf20Sopenharmony_ci rts 20028c2ecf20Sopenharmony_ci 20038c2ecf20Sopenharmony_ci# this code handles the only difference between chk2 and cmp2. chk2 would 20048c2ecf20Sopenharmony_ci# have trapped out if the value was out of bounds. we check this by seeing 20058c2ecf20Sopenharmony_ci# if the 'N' bit was set by the operation. 20068c2ecf20Sopenharmony_cichk2_finish: 20078c2ecf20Sopenharmony_ci btst &0x0, %d4 # is 'N' bit set? 20088c2ecf20Sopenharmony_ci bne.b chk2_trap # yes;chk2 should trap 20098c2ecf20Sopenharmony_ci rts 20108c2ecf20Sopenharmony_cichk2_trap: 20118c2ecf20Sopenharmony_ci mov.b &ichk_flg,SPCOND_FLG(%a6) # set "special case" flag 20128c2ecf20Sopenharmony_ci rts 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_ci# if dmem_read_{long,word}() returns a fail message in d1, the package 20158c2ecf20Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw 20168c2ecf20Sopenharmony_ci# and the failing address to the routine that creates the new frame. 20178c2ecf20Sopenharmony_ci# FSLW: 20188c2ecf20Sopenharmony_ci# read = true 20198c2ecf20Sopenharmony_ci# size = longword 20208c2ecf20Sopenharmony_ci# TM = data 20218c2ecf20Sopenharmony_ci# software emulation error = true 20228c2ecf20Sopenharmony_cichk2_cmp2_err_l: 20238c2ecf20Sopenharmony_ci mov.l %a2,%a0 # pass failing address 20248c2ecf20Sopenharmony_ci mov.l &0x01010001,%d0 # pass fslw 20258c2ecf20Sopenharmony_ci bra.l isp_dacc 20268c2ecf20Sopenharmony_ci 20278c2ecf20Sopenharmony_ci# FSLW: 20288c2ecf20Sopenharmony_ci# read = true 20298c2ecf20Sopenharmony_ci# size = word 20308c2ecf20Sopenharmony_ci# TM = data 20318c2ecf20Sopenharmony_ci# software emulation error = true 20328c2ecf20Sopenharmony_cichk2_cmp2_err_w: 20338c2ecf20Sopenharmony_ci mov.l %a2,%a0 # pass failing address 20348c2ecf20Sopenharmony_ci mov.l &0x01410001,%d0 # pass fslw 20358c2ecf20Sopenharmony_ci bra.l isp_dacc 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci######################################################################### 20388c2ecf20Sopenharmony_ci# XDEF **************************************************************** # 20398c2ecf20Sopenharmony_ci# _div64(): routine to emulate div{u,s}.l <ea>,Dr:Dq # 20408c2ecf20Sopenharmony_ci# 64/32->32r:32q # 20418c2ecf20Sopenharmony_ci# # 20428c2ecf20Sopenharmony_ci# XREF **************************************************************** # 20438c2ecf20Sopenharmony_ci# _calc_ea() - calculate effective address # 20448c2ecf20Sopenharmony_ci# isp_iacc() - handle instruction access error exception # 20458c2ecf20Sopenharmony_ci# isp_dacc() - handle data access error exception # 20468c2ecf20Sopenharmony_ci# isp_restore() - restore An on access error w/ -() or ()+ # 20478c2ecf20Sopenharmony_ci# # 20488c2ecf20Sopenharmony_ci# INPUT *************************************************************** # 20498c2ecf20Sopenharmony_ci# none # 20508c2ecf20Sopenharmony_ci# # 20518c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** # 20528c2ecf20Sopenharmony_ci# If exiting through isp_dacc... # 20538c2ecf20Sopenharmony_ci# a0 = failing address # 20548c2ecf20Sopenharmony_ci# d0 = FSLW # 20558c2ecf20Sopenharmony_ci# else # 20568c2ecf20Sopenharmony_ci# none # 20578c2ecf20Sopenharmony_ci# # 20588c2ecf20Sopenharmony_ci# ALGORITHM *********************************************************** # 20598c2ecf20Sopenharmony_ci# First, decode the operand location. If it's in Dn, fetch from # 20608c2ecf20Sopenharmony_ci# the stack. If it's in memory, use _calc_ea() to calculate the # 20618c2ecf20Sopenharmony_ci# effective address. Use _dmem_read_long() to fetch at that address. # 20628c2ecf20Sopenharmony_ci# Unless the operand is immediate data. Then use _imem_read_long(). # 20638c2ecf20Sopenharmony_ci# Send failures to isp_dacc() or isp_iacc() as appropriate. # 20648c2ecf20Sopenharmony_ci# If the operands are signed, make them unsigned and save the # 20658c2ecf20Sopenharmony_ci# sign info for later. Separate out special cases like divide-by-zero # 20668c2ecf20Sopenharmony_ci# or 32-bit divides if possible. Else, use a special math algorithm # 20678c2ecf20Sopenharmony_ci# to calculate the result. # 20688c2ecf20Sopenharmony_ci# Restore sign info if signed instruction. Set the condition # 20698c2ecf20Sopenharmony_ci# codes. Set idbyz_flg in SPCOND_FLG if divisor was zero. Store the # 20708c2ecf20Sopenharmony_ci# quotient and remainder in the appropriate data registers on the stack.# 20718c2ecf20Sopenharmony_ci# # 20728c2ecf20Sopenharmony_ci######################################################################### 20738c2ecf20Sopenharmony_ci 20748c2ecf20Sopenharmony_ciset NDIVISOR, EXC_TEMP+0x0 20758c2ecf20Sopenharmony_ciset NDIVIDEND, EXC_TEMP+0x1 20768c2ecf20Sopenharmony_ciset NDRSAVE, EXC_TEMP+0x2 20778c2ecf20Sopenharmony_ciset NDQSAVE, EXC_TEMP+0x4 20788c2ecf20Sopenharmony_ciset DDSECOND, EXC_TEMP+0x6 20798c2ecf20Sopenharmony_ciset DDQUOTIENT, EXC_TEMP+0x8 20808c2ecf20Sopenharmony_ciset DDNORMAL, EXC_TEMP+0xc 20818c2ecf20Sopenharmony_ci 20828c2ecf20Sopenharmony_ci global _div64 20838c2ecf20Sopenharmony_ci############# 20848c2ecf20Sopenharmony_ci# div(u,s)l # 20858c2ecf20Sopenharmony_ci############# 20868c2ecf20Sopenharmony_ci_div64: 20878c2ecf20Sopenharmony_ci mov.b EXC_OPWORD+1(%a6), %d0 20888c2ecf20Sopenharmony_ci andi.b &0x38, %d0 # extract src mode 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci bne.w dcontrolmodel_s # %dn dest or control mode? 20918c2ecf20Sopenharmony_ci 20928c2ecf20Sopenharmony_ci mov.b EXC_OPWORD+1(%a6), %d0 # extract Dn from opcode 20938c2ecf20Sopenharmony_ci andi.w &0x7, %d0 20948c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4), %d7 # fetch divisor from register 20958c2ecf20Sopenharmony_ci 20968c2ecf20Sopenharmony_cidgotsrcl: 20978c2ecf20Sopenharmony_ci beq.w div64eq0 # divisor is = 0!!! 20988c2ecf20Sopenharmony_ci 20998c2ecf20Sopenharmony_ci mov.b EXC_EXTWORD+1(%a6), %d0 # extract Dr from extword 21008c2ecf20Sopenharmony_ci mov.b EXC_EXTWORD(%a6), %d1 # extract Dq from extword 21018c2ecf20Sopenharmony_ci and.w &0x7, %d0 21028c2ecf20Sopenharmony_ci lsr.b &0x4, %d1 21038c2ecf20Sopenharmony_ci and.w &0x7, %d1 21048c2ecf20Sopenharmony_ci mov.w %d0, NDRSAVE(%a6) # save Dr for later 21058c2ecf20Sopenharmony_ci mov.w %d1, NDQSAVE(%a6) # save Dq for later 21068c2ecf20Sopenharmony_ci 21078c2ecf20Sopenharmony_ci# fetch %dr and %dq directly off stack since all regs are saved there 21088c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4), %d5 # get dividend hi 21098c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d1.w*4), %d6 # get dividend lo 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci# separate signed and unsigned divide 21128c2ecf20Sopenharmony_ci btst &0x3, EXC_EXTWORD(%a6) # signed or unsigned? 21138c2ecf20Sopenharmony_ci beq.b dspecialcases # use positive divide 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_ci# save the sign of the divisor 21168c2ecf20Sopenharmony_ci# make divisor unsigned if it's negative 21178c2ecf20Sopenharmony_ci tst.l %d7 # chk sign of divisor 21188c2ecf20Sopenharmony_ci slt NDIVISOR(%a6) # save sign of divisor 21198c2ecf20Sopenharmony_ci bpl.b dsgndividend 21208c2ecf20Sopenharmony_ci neg.l %d7 # complement negative divisor 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ci# save the sign of the dividend 21238c2ecf20Sopenharmony_ci# make dividend unsigned if it's negative 21248c2ecf20Sopenharmony_cidsgndividend: 21258c2ecf20Sopenharmony_ci tst.l %d5 # chk sign of hi(dividend) 21268c2ecf20Sopenharmony_ci slt NDIVIDEND(%a6) # save sign of dividend 21278c2ecf20Sopenharmony_ci bpl.b dspecialcases 21288c2ecf20Sopenharmony_ci 21298c2ecf20Sopenharmony_ci mov.w &0x0, %cc # clear 'X' cc bit 21308c2ecf20Sopenharmony_ci negx.l %d6 # complement signed dividend 21318c2ecf20Sopenharmony_ci negx.l %d5 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci# extract some special cases: 21348c2ecf20Sopenharmony_ci# - is (dividend == 0) ? 21358c2ecf20Sopenharmony_ci# - is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div) 21368c2ecf20Sopenharmony_cidspecialcases: 21378c2ecf20Sopenharmony_ci tst.l %d5 # is (hi(dividend) == 0) 21388c2ecf20Sopenharmony_ci bne.b dnormaldivide # no, so try it the long way 21398c2ecf20Sopenharmony_ci 21408c2ecf20Sopenharmony_ci tst.l %d6 # is (lo(dividend) == 0), too 21418c2ecf20Sopenharmony_ci beq.w ddone # yes, so (dividend == 0) 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_ci cmp.l %d7,%d6 # is (divisor <= lo(dividend)) 21448c2ecf20Sopenharmony_ci bls.b d32bitdivide # yes, so use 32 bit divide 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_ci exg %d5,%d6 # q = 0, r = dividend 21478c2ecf20Sopenharmony_ci bra.w divfinish # can't divide, we're done. 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_cid32bitdivide: 21508c2ecf20Sopenharmony_ci tdivu.l %d7, %d5:%d6 # it's only a 32/32 bit div! 21518c2ecf20Sopenharmony_ci 21528c2ecf20Sopenharmony_ci bra.b divfinish 21538c2ecf20Sopenharmony_ci 21548c2ecf20Sopenharmony_cidnormaldivide: 21558c2ecf20Sopenharmony_ci# last special case: 21568c2ecf20Sopenharmony_ci# - is hi(dividend) >= divisor ? if yes, then overflow 21578c2ecf20Sopenharmony_ci cmp.l %d7,%d5 21588c2ecf20Sopenharmony_ci bls.b ddovf # answer won't fit in 32 bits 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci# perform the divide algorithm: 21618c2ecf20Sopenharmony_ci bsr.l dclassical # do int divide 21628c2ecf20Sopenharmony_ci 21638c2ecf20Sopenharmony_ci# separate into signed and unsigned finishes. 21648c2ecf20Sopenharmony_cidivfinish: 21658c2ecf20Sopenharmony_ci btst &0x3, EXC_EXTWORD(%a6) # do divs, divu separately 21668c2ecf20Sopenharmony_ci beq.b ddone # divu has no processing!!! 21678c2ecf20Sopenharmony_ci 21688c2ecf20Sopenharmony_ci# it was a divs.l, so ccode setting is a little more complicated... 21698c2ecf20Sopenharmony_ci tst.b NDIVIDEND(%a6) # remainder has same sign 21708c2ecf20Sopenharmony_ci beq.b dcc # as dividend. 21718c2ecf20Sopenharmony_ci neg.l %d5 # sgn(rem) = sgn(dividend) 21728c2ecf20Sopenharmony_cidcc: 21738c2ecf20Sopenharmony_ci mov.b NDIVISOR(%a6), %d0 21748c2ecf20Sopenharmony_ci eor.b %d0, NDIVIDEND(%a6) # chk if quotient is negative 21758c2ecf20Sopenharmony_ci beq.b dqpos # branch to quot positive 21768c2ecf20Sopenharmony_ci 21778c2ecf20Sopenharmony_ci# 0x80000000 is the largest number representable as a 32-bit negative 21788c2ecf20Sopenharmony_ci# number. the negative of 0x80000000 is 0x80000000. 21798c2ecf20Sopenharmony_ci cmpi.l %d6, &0x80000000 # will (-quot) fit in 32 bits? 21808c2ecf20Sopenharmony_ci bhi.b ddovf 21818c2ecf20Sopenharmony_ci 21828c2ecf20Sopenharmony_ci neg.l %d6 # make (-quot) 2's comp 21838c2ecf20Sopenharmony_ci 21848c2ecf20Sopenharmony_ci bra.b ddone 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_cidqpos: 21878c2ecf20Sopenharmony_ci btst &0x1f, %d6 # will (+quot) fit in 32 bits? 21888c2ecf20Sopenharmony_ci bne.b ddovf 21898c2ecf20Sopenharmony_ci 21908c2ecf20Sopenharmony_ciddone: 21918c2ecf20Sopenharmony_ci# at this point, result is normal so ccodes are set based on result. 21928c2ecf20Sopenharmony_ci mov.w EXC_CC(%a6), %cc 21938c2ecf20Sopenharmony_ci tst.l %d6 # set %ccode bits 21948c2ecf20Sopenharmony_ci mov.w %cc, EXC_CC(%a6) 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci mov.w NDRSAVE(%a6), %d0 # get Dr off stack 21978c2ecf20Sopenharmony_ci mov.w NDQSAVE(%a6), %d1 # get Dq off stack 21988c2ecf20Sopenharmony_ci 21998c2ecf20Sopenharmony_ci# if the register numbers are the same, only the quotient gets saved. 22008c2ecf20Sopenharmony_ci# so, if we always save the quotient second, we save ourselves a cmp&beq 22018c2ecf20Sopenharmony_ci mov.l %d5, (EXC_DREGS,%a6,%d0.w*4) # save remainder 22028c2ecf20Sopenharmony_ci mov.l %d6, (EXC_DREGS,%a6,%d1.w*4) # save quotient 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_ci rts 22058c2ecf20Sopenharmony_ci 22068c2ecf20Sopenharmony_ciddovf: 22078c2ecf20Sopenharmony_ci bset &0x1, EXC_CC+1(%a6) # 'V' set on overflow 22088c2ecf20Sopenharmony_ci bclr &0x0, EXC_CC+1(%a6) # 'C' cleared on overflow 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci rts 22118c2ecf20Sopenharmony_ci 22128c2ecf20Sopenharmony_cidiv64eq0: 22138c2ecf20Sopenharmony_ci andi.b &0x1e, EXC_CC+1(%a6) # clear 'C' bit on divbyzero 22148c2ecf20Sopenharmony_ci ori.b &idbyz_flg,SPCOND_FLG(%a6) # set "special case" flag 22158c2ecf20Sopenharmony_ci rts 22168c2ecf20Sopenharmony_ci 22178c2ecf20Sopenharmony_ci########################################################################### 22188c2ecf20Sopenharmony_ci######################################################################### 22198c2ecf20Sopenharmony_ci# This routine uses the 'classical' Algorithm D from Donald Knuth's # 22208c2ecf20Sopenharmony_ci# Art of Computer Programming, vol II, Seminumerical Algorithms. # 22218c2ecf20Sopenharmony_ci# For this implementation b=2**16, and the target is U1U2U3U4/V1V2, # 22228c2ecf20Sopenharmony_ci# where U,V are words of the quadword dividend and longword divisor, # 22238c2ecf20Sopenharmony_ci# and U1, V1 are the most significant words. # 22248c2ecf20Sopenharmony_ci# # 22258c2ecf20Sopenharmony_ci# The most sig. longword of the 64 bit dividend must be in %d5, least # 22268c2ecf20Sopenharmony_ci# in %d6. The divisor must be in the variable ddivisor, and the # 22278c2ecf20Sopenharmony_ci# signed/unsigned flag ddusign must be set (0=unsigned,1=signed). # 22288c2ecf20Sopenharmony_ci# The quotient is returned in %d6, remainder in %d5, unless the # 22298c2ecf20Sopenharmony_ci# v (overflow) bit is set in the saved %ccr. If overflow, the dividend # 22308c2ecf20Sopenharmony_ci# is unchanged. # 22318c2ecf20Sopenharmony_ci######################################################################### 22328c2ecf20Sopenharmony_cidclassical: 22338c2ecf20Sopenharmony_ci# if the divisor msw is 0, use simpler algorithm then the full blown 22348c2ecf20Sopenharmony_ci# one at ddknuth: 22358c2ecf20Sopenharmony_ci 22368c2ecf20Sopenharmony_ci cmpi.l %d7, &0xffff 22378c2ecf20Sopenharmony_ci bhi.b ddknuth # go use D. Knuth algorithm 22388c2ecf20Sopenharmony_ci 22398c2ecf20Sopenharmony_ci# Since the divisor is only a word (and larger than the mslw of the dividend), 22408c2ecf20Sopenharmony_ci# a simpler algorithm may be used : 22418c2ecf20Sopenharmony_ci# In the general case, four quotient words would be created by 22428c2ecf20Sopenharmony_ci# dividing the divisor word into each dividend word. In this case, 22438c2ecf20Sopenharmony_ci# the first two quotient words must be zero, or overflow would occur. 22448c2ecf20Sopenharmony_ci# Since we already checked this case above, we can treat the most significant 22458c2ecf20Sopenharmony_ci# longword of the dividend as (0) remainder (see Knuth) and merely complete 22468c2ecf20Sopenharmony_ci# the last two divisions to get a quotient longword and word remainder: 22478c2ecf20Sopenharmony_ci 22488c2ecf20Sopenharmony_ci clr.l %d1 22498c2ecf20Sopenharmony_ci swap %d5 # same as r*b if previous step rqd 22508c2ecf20Sopenharmony_ci swap %d6 # get u3 to lsw position 22518c2ecf20Sopenharmony_ci mov.w %d6, %d5 # rb + u3 22528c2ecf20Sopenharmony_ci 22538c2ecf20Sopenharmony_ci divu.w %d7, %d5 22548c2ecf20Sopenharmony_ci 22558c2ecf20Sopenharmony_ci mov.w %d5, %d1 # first quotient word 22568c2ecf20Sopenharmony_ci swap %d6 # get u4 22578c2ecf20Sopenharmony_ci mov.w %d6, %d5 # rb + u4 22588c2ecf20Sopenharmony_ci 22598c2ecf20Sopenharmony_ci divu.w %d7, %d5 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_ci swap %d1 22628c2ecf20Sopenharmony_ci mov.w %d5, %d1 # 2nd quotient 'digit' 22638c2ecf20Sopenharmony_ci clr.w %d5 22648c2ecf20Sopenharmony_ci swap %d5 # now remainder 22658c2ecf20Sopenharmony_ci mov.l %d1, %d6 # and quotient 22668c2ecf20Sopenharmony_ci 22678c2ecf20Sopenharmony_ci rts 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_ciddknuth: 22708c2ecf20Sopenharmony_ci# In this algorithm, the divisor is treated as a 2 digit (word) number 22718c2ecf20Sopenharmony_ci# which is divided into a 3 digit (word) dividend to get one quotient 22728c2ecf20Sopenharmony_ci# digit (word). After subtraction, the dividend is shifted and the 22738c2ecf20Sopenharmony_ci# process repeated. Before beginning, the divisor and quotient are 22748c2ecf20Sopenharmony_ci# 'normalized' so that the process of estimating the quotient digit 22758c2ecf20Sopenharmony_ci# will yield verifiably correct results.. 22768c2ecf20Sopenharmony_ci 22778c2ecf20Sopenharmony_ci clr.l DDNORMAL(%a6) # count of shifts for normalization 22788c2ecf20Sopenharmony_ci clr.b DDSECOND(%a6) # clear flag for quotient digits 22798c2ecf20Sopenharmony_ci clr.l %d1 # %d1 will hold trial quotient 22808c2ecf20Sopenharmony_ciddnchk: 22818c2ecf20Sopenharmony_ci btst &31, %d7 # must we normalize? first word of 22828c2ecf20Sopenharmony_ci bne.b ddnormalized # divisor (V1) must be >= 65536/2 22838c2ecf20Sopenharmony_ci addq.l &0x1, DDNORMAL(%a6) # count normalization shifts 22848c2ecf20Sopenharmony_ci lsl.l &0x1, %d7 # shift the divisor 22858c2ecf20Sopenharmony_ci lsl.l &0x1, %d6 # shift u4,u3 with overflow to u2 22868c2ecf20Sopenharmony_ci roxl.l &0x1, %d5 # shift u1,u2 22878c2ecf20Sopenharmony_ci bra.w ddnchk 22888c2ecf20Sopenharmony_ciddnormalized: 22898c2ecf20Sopenharmony_ci 22908c2ecf20Sopenharmony_ci# Now calculate an estimate of the quotient words (msw first, then lsw). 22918c2ecf20Sopenharmony_ci# The comments use subscripts for the first quotient digit determination. 22928c2ecf20Sopenharmony_ci mov.l %d7, %d3 # divisor 22938c2ecf20Sopenharmony_ci mov.l %d5, %d2 # dividend mslw 22948c2ecf20Sopenharmony_ci swap %d2 22958c2ecf20Sopenharmony_ci swap %d3 22968c2ecf20Sopenharmony_ci cmp.w %d2, %d3 # V1 = U1 ? 22978c2ecf20Sopenharmony_ci bne.b ddqcalc1 22988c2ecf20Sopenharmony_ci mov.w &0xffff, %d1 # use max trial quotient word 22998c2ecf20Sopenharmony_ci bra.b ddadj0 23008c2ecf20Sopenharmony_ciddqcalc1: 23018c2ecf20Sopenharmony_ci mov.l %d5, %d1 23028c2ecf20Sopenharmony_ci 23038c2ecf20Sopenharmony_ci divu.w %d3, %d1 # use quotient of mslw/msw 23048c2ecf20Sopenharmony_ci 23058c2ecf20Sopenharmony_ci andi.l &0x0000ffff, %d1 # zero any remainder 23068c2ecf20Sopenharmony_ciddadj0: 23078c2ecf20Sopenharmony_ci 23088c2ecf20Sopenharmony_ci# now test the trial quotient and adjust. This step plus the 23098c2ecf20Sopenharmony_ci# normalization assures (according to Knuth) that the trial 23108c2ecf20Sopenharmony_ci# quotient will be at worst 1 too large. 23118c2ecf20Sopenharmony_ci mov.l %d6, -(%sp) 23128c2ecf20Sopenharmony_ci clr.w %d6 # word u3 left 23138c2ecf20Sopenharmony_ci swap %d6 # in lsw position 23148c2ecf20Sopenharmony_ciddadj1: mov.l %d7, %d3 23158c2ecf20Sopenharmony_ci mov.l %d1, %d2 23168c2ecf20Sopenharmony_ci mulu.w %d7, %d2 # V2q 23178c2ecf20Sopenharmony_ci swap %d3 23188c2ecf20Sopenharmony_ci mulu.w %d1, %d3 # V1q 23198c2ecf20Sopenharmony_ci mov.l %d5, %d4 # U1U2 23208c2ecf20Sopenharmony_ci sub.l %d3, %d4 # U1U2 - V1q 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci swap %d4 23238c2ecf20Sopenharmony_ci 23248c2ecf20Sopenharmony_ci mov.w %d4,%d0 23258c2ecf20Sopenharmony_ci mov.w %d6,%d4 # insert lower word (U3) 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_ci tst.w %d0 # is upper word set? 23288c2ecf20Sopenharmony_ci bne.w ddadjd1 23298c2ecf20Sopenharmony_ci 23308c2ecf20Sopenharmony_ci# add.l %d6, %d4 # (U1U2 - V1q) + U3 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci cmp.l %d2, %d4 23338c2ecf20Sopenharmony_ci bls.b ddadjd1 # is V2q > (U1U2-V1q) + U3 ? 23348c2ecf20Sopenharmony_ci subq.l &0x1, %d1 # yes, decrement and recheck 23358c2ecf20Sopenharmony_ci bra.b ddadj1 23368c2ecf20Sopenharmony_ciddadjd1: 23378c2ecf20Sopenharmony_ci# now test the word by multiplying it by the divisor (V1V2) and comparing 23388c2ecf20Sopenharmony_ci# the 3 digit (word) result with the current dividend words 23398c2ecf20Sopenharmony_ci mov.l %d5, -(%sp) # save %d5 (%d6 already saved) 23408c2ecf20Sopenharmony_ci mov.l %d1, %d6 23418c2ecf20Sopenharmony_ci swap %d6 # shift answer to ms 3 words 23428c2ecf20Sopenharmony_ci mov.l %d7, %d5 23438c2ecf20Sopenharmony_ci bsr.l dmm2 23448c2ecf20Sopenharmony_ci mov.l %d5, %d2 # now %d2,%d3 are trial*divisor 23458c2ecf20Sopenharmony_ci mov.l %d6, %d3 23468c2ecf20Sopenharmony_ci mov.l (%sp)+, %d5 # restore dividend 23478c2ecf20Sopenharmony_ci mov.l (%sp)+, %d6 23488c2ecf20Sopenharmony_ci sub.l %d3, %d6 23498c2ecf20Sopenharmony_ci subx.l %d2, %d5 # subtract double precision 23508c2ecf20Sopenharmony_ci bcc dd2nd # no carry, do next quotient digit 23518c2ecf20Sopenharmony_ci subq.l &0x1, %d1 # q is one too large 23528c2ecf20Sopenharmony_ci# need to add back divisor longword to current ms 3 digits of dividend 23538c2ecf20Sopenharmony_ci# - according to Knuth, this is done only 2 out of 65536 times for random 23548c2ecf20Sopenharmony_ci# divisor, dividend selection. 23558c2ecf20Sopenharmony_ci clr.l %d2 23568c2ecf20Sopenharmony_ci mov.l %d7, %d3 23578c2ecf20Sopenharmony_ci swap %d3 23588c2ecf20Sopenharmony_ci clr.w %d3 # %d3 now ls word of divisor 23598c2ecf20Sopenharmony_ci add.l %d3, %d6 # aligned with 3rd word of dividend 23608c2ecf20Sopenharmony_ci addx.l %d2, %d5 23618c2ecf20Sopenharmony_ci mov.l %d7, %d3 23628c2ecf20Sopenharmony_ci clr.w %d3 # %d3 now ms word of divisor 23638c2ecf20Sopenharmony_ci swap %d3 # aligned with 2nd word of dividend 23648c2ecf20Sopenharmony_ci add.l %d3, %d5 23658c2ecf20Sopenharmony_cidd2nd: 23668c2ecf20Sopenharmony_ci tst.b DDSECOND(%a6) # both q words done? 23678c2ecf20Sopenharmony_ci bne.b ddremain 23688c2ecf20Sopenharmony_ci# first quotient digit now correct. store digit and shift the 23698c2ecf20Sopenharmony_ci# (subtracted) dividend 23708c2ecf20Sopenharmony_ci mov.w %d1, DDQUOTIENT(%a6) 23718c2ecf20Sopenharmony_ci clr.l %d1 23728c2ecf20Sopenharmony_ci swap %d5 23738c2ecf20Sopenharmony_ci swap %d6 23748c2ecf20Sopenharmony_ci mov.w %d6, %d5 23758c2ecf20Sopenharmony_ci clr.w %d6 23768c2ecf20Sopenharmony_ci st DDSECOND(%a6) # second digit 23778c2ecf20Sopenharmony_ci bra.w ddnormalized 23788c2ecf20Sopenharmony_ciddremain: 23798c2ecf20Sopenharmony_ci# add 2nd word to quotient, get the remainder. 23808c2ecf20Sopenharmony_ci mov.w %d1, DDQUOTIENT+2(%a6) 23818c2ecf20Sopenharmony_ci# shift down one word/digit to renormalize remainder. 23828c2ecf20Sopenharmony_ci mov.w %d5, %d6 23838c2ecf20Sopenharmony_ci swap %d6 23848c2ecf20Sopenharmony_ci swap %d5 23858c2ecf20Sopenharmony_ci mov.l DDNORMAL(%a6), %d7 # get norm shift count 23868c2ecf20Sopenharmony_ci beq.b ddrn 23878c2ecf20Sopenharmony_ci subq.l &0x1, %d7 # set for loop count 23888c2ecf20Sopenharmony_ciddnlp: 23898c2ecf20Sopenharmony_ci lsr.l &0x1, %d5 # shift into %d6 23908c2ecf20Sopenharmony_ci roxr.l &0x1, %d6 23918c2ecf20Sopenharmony_ci dbf %d7, ddnlp 23928c2ecf20Sopenharmony_ciddrn: 23938c2ecf20Sopenharmony_ci mov.l %d6, %d5 # remainder 23948c2ecf20Sopenharmony_ci mov.l DDQUOTIENT(%a6), %d6 # quotient 23958c2ecf20Sopenharmony_ci 23968c2ecf20Sopenharmony_ci rts 23978c2ecf20Sopenharmony_cidmm2: 23988c2ecf20Sopenharmony_ci# factors for the 32X32->64 multiplication are in %d5 and %d6. 23998c2ecf20Sopenharmony_ci# returns 64 bit result in %d5 (hi) %d6(lo). 24008c2ecf20Sopenharmony_ci# destroys %d2,%d3,%d4. 24018c2ecf20Sopenharmony_ci 24028c2ecf20Sopenharmony_ci# multiply hi,lo words of each factor to get 4 intermediate products 24038c2ecf20Sopenharmony_ci mov.l %d6, %d2 24048c2ecf20Sopenharmony_ci mov.l %d6, %d3 24058c2ecf20Sopenharmony_ci mov.l %d5, %d4 24068c2ecf20Sopenharmony_ci swap %d3 24078c2ecf20Sopenharmony_ci swap %d4 24088c2ecf20Sopenharmony_ci mulu.w %d5, %d6 # %d6 <- lsw*lsw 24098c2ecf20Sopenharmony_ci mulu.w %d3, %d5 # %d5 <- msw-dest*lsw-source 24108c2ecf20Sopenharmony_ci mulu.w %d4, %d2 # %d2 <- msw-source*lsw-dest 24118c2ecf20Sopenharmony_ci mulu.w %d4, %d3 # %d3 <- msw*msw 24128c2ecf20Sopenharmony_ci# now use swap and addx to consolidate to two longwords 24138c2ecf20Sopenharmony_ci clr.l %d4 24148c2ecf20Sopenharmony_ci swap %d6 24158c2ecf20Sopenharmony_ci add.w %d5, %d6 # add msw of l*l to lsw of m*l product 24168c2ecf20Sopenharmony_ci addx.w %d4, %d3 # add any carry to m*m product 24178c2ecf20Sopenharmony_ci add.w %d2, %d6 # add in lsw of other m*l product 24188c2ecf20Sopenharmony_ci addx.w %d4, %d3 # add any carry to m*m product 24198c2ecf20Sopenharmony_ci swap %d6 # %d6 is low 32 bits of final product 24208c2ecf20Sopenharmony_ci clr.w %d5 24218c2ecf20Sopenharmony_ci clr.w %d2 # lsw of two mixed products used, 24228c2ecf20Sopenharmony_ci swap %d5 # now use msws of longwords 24238c2ecf20Sopenharmony_ci swap %d2 24248c2ecf20Sopenharmony_ci add.l %d2, %d5 24258c2ecf20Sopenharmony_ci add.l %d3, %d5 # %d5 now ms 32 bits of final product 24268c2ecf20Sopenharmony_ci rts 24278c2ecf20Sopenharmony_ci 24288c2ecf20Sopenharmony_ci########## 24298c2ecf20Sopenharmony_cidcontrolmodel_s: 24308c2ecf20Sopenharmony_ci movq.l &LONG,%d0 24318c2ecf20Sopenharmony_ci bsr.l _calc_ea # calc <ea> 24328c2ecf20Sopenharmony_ci 24338c2ecf20Sopenharmony_ci cmpi.b SPCOND_FLG(%a6),&immed_flg # immediate addressing mode? 24348c2ecf20Sopenharmony_ci beq.b dimmed # yes 24358c2ecf20Sopenharmony_ci 24368c2ecf20Sopenharmony_ci mov.l %a0,%a2 24378c2ecf20Sopenharmony_ci bsr.l _dmem_read_long # fetch divisor from <ea> 24388c2ecf20Sopenharmony_ci 24398c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 24408c2ecf20Sopenharmony_ci bne.b div64_err # yes 24418c2ecf20Sopenharmony_ci 24428c2ecf20Sopenharmony_ci mov.l %d0, %d7 24438c2ecf20Sopenharmony_ci bra.w dgotsrcl 24448c2ecf20Sopenharmony_ci 24458c2ecf20Sopenharmony_ci# we have to split out immediate data here because it must be read using 24468c2ecf20Sopenharmony_ci# imem_read() instead of dmem_read(). this becomes especially important 24478c2ecf20Sopenharmony_ci# if the fetch runs into some deadly fault. 24488c2ecf20Sopenharmony_cidimmed: 24498c2ecf20Sopenharmony_ci addq.l &0x4,EXC_EXTWPTR(%a6) 24508c2ecf20Sopenharmony_ci bsr.l _imem_read_long # read immediate value 24518c2ecf20Sopenharmony_ci 24528c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 24538c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 24548c2ecf20Sopenharmony_ci 24558c2ecf20Sopenharmony_ci mov.l %d0,%d7 24568c2ecf20Sopenharmony_ci bra.w dgotsrcl 24578c2ecf20Sopenharmony_ci 24588c2ecf20Sopenharmony_ci########## 24598c2ecf20Sopenharmony_ci 24608c2ecf20Sopenharmony_ci# if dmem_read_long() returns a fail message in d1, the package 24618c2ecf20Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw 24628c2ecf20Sopenharmony_ci# and the failing address to the routine that creates the new frame. 24638c2ecf20Sopenharmony_ci# also, we call isp_restore in case the effective addressing mode was 24648c2ecf20Sopenharmony_ci# (an)+ or -(an) in which case the previous "an" value must be restored. 24658c2ecf20Sopenharmony_ci# FSLW: 24668c2ecf20Sopenharmony_ci# read = true 24678c2ecf20Sopenharmony_ci# size = longword 24688c2ecf20Sopenharmony_ci# TM = data 24698c2ecf20Sopenharmony_ci# software emulation error = true 24708c2ecf20Sopenharmony_cidiv64_err: 24718c2ecf20Sopenharmony_ci bsr.l isp_restore # restore addr reg 24728c2ecf20Sopenharmony_ci mov.l %a2,%a0 # pass failing address 24738c2ecf20Sopenharmony_ci mov.l &0x01010001,%d0 # pass fslw 24748c2ecf20Sopenharmony_ci bra.l isp_dacc 24758c2ecf20Sopenharmony_ci 24768c2ecf20Sopenharmony_ci######################################################################### 24778c2ecf20Sopenharmony_ci# XDEF **************************************************************** # 24788c2ecf20Sopenharmony_ci# _mul64(): routine to emulate mul{u,s}.l <ea>,Dh:Dl 32x32->64 # 24798c2ecf20Sopenharmony_ci# # 24808c2ecf20Sopenharmony_ci# XREF **************************************************************** # 24818c2ecf20Sopenharmony_ci# _calc_ea() - calculate effective address # 24828c2ecf20Sopenharmony_ci# isp_iacc() - handle instruction access error exception # 24838c2ecf20Sopenharmony_ci# isp_dacc() - handle data access error exception # 24848c2ecf20Sopenharmony_ci# isp_restore() - restore An on access error w/ -() or ()+ # 24858c2ecf20Sopenharmony_ci# # 24868c2ecf20Sopenharmony_ci# INPUT *************************************************************** # 24878c2ecf20Sopenharmony_ci# none # 24888c2ecf20Sopenharmony_ci# # 24898c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** # 24908c2ecf20Sopenharmony_ci# If exiting through isp_dacc... # 24918c2ecf20Sopenharmony_ci# a0 = failing address # 24928c2ecf20Sopenharmony_ci# d0 = FSLW # 24938c2ecf20Sopenharmony_ci# else # 24948c2ecf20Sopenharmony_ci# none # 24958c2ecf20Sopenharmony_ci# # 24968c2ecf20Sopenharmony_ci# ALGORITHM *********************************************************** # 24978c2ecf20Sopenharmony_ci# First, decode the operand location. If it's in Dn, fetch from # 24988c2ecf20Sopenharmony_ci# the stack. If it's in memory, use _calc_ea() to calculate the # 24998c2ecf20Sopenharmony_ci# effective address. Use _dmem_read_long() to fetch at that address. # 25008c2ecf20Sopenharmony_ci# Unless the operand is immediate data. Then use _imem_read_long(). # 25018c2ecf20Sopenharmony_ci# Send failures to isp_dacc() or isp_iacc() as appropriate. # 25028c2ecf20Sopenharmony_ci# If the operands are signed, make them unsigned and save the # 25038c2ecf20Sopenharmony_ci# sign info for later. Perform the multiplication using 16x16->32 # 25048c2ecf20Sopenharmony_ci# unsigned multiplies and "add" instructions. Store the high and low # 25058c2ecf20Sopenharmony_ci# portions of the result in the appropriate data registers on the # 25068c2ecf20Sopenharmony_ci# stack. Calculate the condition codes, also. # 25078c2ecf20Sopenharmony_ci# # 25088c2ecf20Sopenharmony_ci######################################################################### 25098c2ecf20Sopenharmony_ci 25108c2ecf20Sopenharmony_ci############# 25118c2ecf20Sopenharmony_ci# mul(u,s)l # 25128c2ecf20Sopenharmony_ci############# 25138c2ecf20Sopenharmony_ci global _mul64 25148c2ecf20Sopenharmony_ci_mul64: 25158c2ecf20Sopenharmony_ci mov.b EXC_OPWORD+1(%a6), %d0 # extract src {mode,reg} 25168c2ecf20Sopenharmony_ci cmpi.b %d0, &0x7 # is src mode Dn or other? 25178c2ecf20Sopenharmony_ci bgt.w mul64_memop # src is in memory 25188c2ecf20Sopenharmony_ci 25198c2ecf20Sopenharmony_ci# multiplier operand in the data register file. 25208c2ecf20Sopenharmony_ci# must extract the register number and fetch the operand from the stack. 25218c2ecf20Sopenharmony_cimul64_regop: 25228c2ecf20Sopenharmony_ci andi.w &0x7, %d0 # extract Dn 25238c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4), %d3 # fetch multiplier 25248c2ecf20Sopenharmony_ci 25258c2ecf20Sopenharmony_ci# multiplier is in %d3. now, extract Dl and Dh fields and fetch the 25268c2ecf20Sopenharmony_ci# multiplicand from the data register specified by Dl. 25278c2ecf20Sopenharmony_cimul64_multiplicand: 25288c2ecf20Sopenharmony_ci mov.w EXC_EXTWORD(%a6), %d2 # fetch ext word 25298c2ecf20Sopenharmony_ci clr.w %d1 # clear Dh reg 25308c2ecf20Sopenharmony_ci mov.b %d2, %d1 # grab Dh 25318c2ecf20Sopenharmony_ci rol.w &0x4, %d2 # align Dl byte 25328c2ecf20Sopenharmony_ci andi.w &0x7, %d2 # extract Dl 25338c2ecf20Sopenharmony_ci 25348c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d2.w*4), %d4 # get multiplicand 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci# check for the case of "zero" result early 25378c2ecf20Sopenharmony_ci tst.l %d4 # test multiplicand 25388c2ecf20Sopenharmony_ci beq.w mul64_zero # handle zero separately 25398c2ecf20Sopenharmony_ci tst.l %d3 # test multiplier 25408c2ecf20Sopenharmony_ci beq.w mul64_zero # handle zero separately 25418c2ecf20Sopenharmony_ci 25428c2ecf20Sopenharmony_ci# multiplier is in %d3 and multiplicand is in %d4. 25438c2ecf20Sopenharmony_ci# if the operation is to be signed, then the operands are converted 25448c2ecf20Sopenharmony_ci# to unsigned and the result sign is saved for the end. 25458c2ecf20Sopenharmony_ci clr.b EXC_TEMP(%a6) # clear temp space 25468c2ecf20Sopenharmony_ci btst &0x3, EXC_EXTWORD(%a6) # signed or unsigned? 25478c2ecf20Sopenharmony_ci beq.b mul64_alg # unsigned; skip sgn calc 25488c2ecf20Sopenharmony_ci 25498c2ecf20Sopenharmony_ci tst.l %d3 # is multiplier negative? 25508c2ecf20Sopenharmony_ci bge.b mul64_chk_md_sgn # no 25518c2ecf20Sopenharmony_ci neg.l %d3 # make multiplier positive 25528c2ecf20Sopenharmony_ci ori.b &0x1, EXC_TEMP(%a6) # save multiplier sgn 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_ci# the result sign is the exclusive or of the operand sign bits. 25558c2ecf20Sopenharmony_cimul64_chk_md_sgn: 25568c2ecf20Sopenharmony_ci tst.l %d4 # is multiplicand negative? 25578c2ecf20Sopenharmony_ci bge.b mul64_alg # no 25588c2ecf20Sopenharmony_ci neg.l %d4 # make multiplicand positive 25598c2ecf20Sopenharmony_ci eori.b &0x1, EXC_TEMP(%a6) # calculate correct sign 25608c2ecf20Sopenharmony_ci 25618c2ecf20Sopenharmony_ci######################################################################### 25628c2ecf20Sopenharmony_ci# 63 32 0 # 25638c2ecf20Sopenharmony_ci# ---------------------------- # 25648c2ecf20Sopenharmony_ci# | hi(mplier) * hi(mplicand)| # 25658c2ecf20Sopenharmony_ci# ---------------------------- # 25668c2ecf20Sopenharmony_ci# ----------------------------- # 25678c2ecf20Sopenharmony_ci# | hi(mplier) * lo(mplicand) | # 25688c2ecf20Sopenharmony_ci# ----------------------------- # 25698c2ecf20Sopenharmony_ci# ----------------------------- # 25708c2ecf20Sopenharmony_ci# | lo(mplier) * hi(mplicand) | # 25718c2ecf20Sopenharmony_ci# ----------------------------- # 25728c2ecf20Sopenharmony_ci# | ----------------------------- # 25738c2ecf20Sopenharmony_ci# --|-- | lo(mplier) * lo(mplicand) | # 25748c2ecf20Sopenharmony_ci# | ----------------------------- # 25758c2ecf20Sopenharmony_ci# ======================================================== # 25768c2ecf20Sopenharmony_ci# -------------------------------------------------------- # 25778c2ecf20Sopenharmony_ci# | hi(result) | lo(result) | # 25788c2ecf20Sopenharmony_ci# -------------------------------------------------------- # 25798c2ecf20Sopenharmony_ci######################################################################### 25808c2ecf20Sopenharmony_cimul64_alg: 25818c2ecf20Sopenharmony_ci# load temp registers with operands 25828c2ecf20Sopenharmony_ci mov.l %d3, %d5 # mr in %d5 25838c2ecf20Sopenharmony_ci mov.l %d3, %d6 # mr in %d6 25848c2ecf20Sopenharmony_ci mov.l %d4, %d7 # md in %d7 25858c2ecf20Sopenharmony_ci swap %d6 # hi(mr) in lo %d6 25868c2ecf20Sopenharmony_ci swap %d7 # hi(md) in lo %d7 25878c2ecf20Sopenharmony_ci 25888c2ecf20Sopenharmony_ci# complete necessary multiplies: 25898c2ecf20Sopenharmony_ci mulu.w %d4, %d3 # [1] lo(mr) * lo(md) 25908c2ecf20Sopenharmony_ci mulu.w %d6, %d4 # [2] hi(mr) * lo(md) 25918c2ecf20Sopenharmony_ci mulu.w %d7, %d5 # [3] lo(mr) * hi(md) 25928c2ecf20Sopenharmony_ci mulu.w %d7, %d6 # [4] hi(mr) * hi(md) 25938c2ecf20Sopenharmony_ci 25948c2ecf20Sopenharmony_ci# add lo portions of [2],[3] to hi portion of [1]. 25958c2ecf20Sopenharmony_ci# add carries produced from these adds to [4]. 25968c2ecf20Sopenharmony_ci# lo([1]) is the final lo 16 bits of the result. 25978c2ecf20Sopenharmony_ci clr.l %d7 # load %d7 w/ zero value 25988c2ecf20Sopenharmony_ci swap %d3 # hi([1]) <==> lo([1]) 25998c2ecf20Sopenharmony_ci add.w %d4, %d3 # hi([1]) + lo([2]) 26008c2ecf20Sopenharmony_ci addx.l %d7, %d6 # [4] + carry 26018c2ecf20Sopenharmony_ci add.w %d5, %d3 # hi([1]) + lo([3]) 26028c2ecf20Sopenharmony_ci addx.l %d7, %d6 # [4] + carry 26038c2ecf20Sopenharmony_ci swap %d3 # lo([1]) <==> hi([1]) 26048c2ecf20Sopenharmony_ci 26058c2ecf20Sopenharmony_ci# lo portions of [2],[3] have been added in to final result. 26068c2ecf20Sopenharmony_ci# now, clear lo, put hi in lo reg, and add to [4] 26078c2ecf20Sopenharmony_ci clr.w %d4 # clear lo([2]) 26088c2ecf20Sopenharmony_ci clr.w %d5 # clear hi([3]) 26098c2ecf20Sopenharmony_ci swap %d4 # hi([2]) in lo %d4 26108c2ecf20Sopenharmony_ci swap %d5 # hi([3]) in lo %d5 26118c2ecf20Sopenharmony_ci add.l %d5, %d4 # [4] + hi([2]) 26128c2ecf20Sopenharmony_ci add.l %d6, %d4 # [4] + hi([3]) 26138c2ecf20Sopenharmony_ci 26148c2ecf20Sopenharmony_ci# unsigned result is now in {%d4,%d3} 26158c2ecf20Sopenharmony_ci tst.b EXC_TEMP(%a6) # should result be signed? 26168c2ecf20Sopenharmony_ci beq.b mul64_done # no 26178c2ecf20Sopenharmony_ci 26188c2ecf20Sopenharmony_ci# result should be a signed negative number. 26198c2ecf20Sopenharmony_ci# compute 2's complement of the unsigned number: 26208c2ecf20Sopenharmony_ci# -negate all bits and add 1 26218c2ecf20Sopenharmony_cimul64_neg: 26228c2ecf20Sopenharmony_ci not.l %d3 # negate lo(result) bits 26238c2ecf20Sopenharmony_ci not.l %d4 # negate hi(result) bits 26248c2ecf20Sopenharmony_ci addq.l &1, %d3 # add 1 to lo(result) 26258c2ecf20Sopenharmony_ci addx.l %d7, %d4 # add carry to hi(result) 26268c2ecf20Sopenharmony_ci 26278c2ecf20Sopenharmony_ci# the result is saved to the register file. 26288c2ecf20Sopenharmony_ci# for '040 compatibility, if Dl == Dh then only the hi(result) is 26298c2ecf20Sopenharmony_ci# saved. so, saving hi after lo accomplishes this without need to 26308c2ecf20Sopenharmony_ci# check Dl,Dh equality. 26318c2ecf20Sopenharmony_cimul64_done: 26328c2ecf20Sopenharmony_ci mov.l %d3, (EXC_DREGS,%a6,%d2.w*4) # save lo(result) 26338c2ecf20Sopenharmony_ci mov.w &0x0, %cc 26348c2ecf20Sopenharmony_ci mov.l %d4, (EXC_DREGS,%a6,%d1.w*4) # save hi(result) 26358c2ecf20Sopenharmony_ci 26368c2ecf20Sopenharmony_ci# now, grab the condition codes. only one that can be set is 'N'. 26378c2ecf20Sopenharmony_ci# 'N' CAN be set if the operation is unsigned if bit 63 is set. 26388c2ecf20Sopenharmony_ci mov.w %cc, %d7 # fetch %ccr to see if 'N' set 26398c2ecf20Sopenharmony_ci andi.b &0x8, %d7 # extract 'N' bit 26408c2ecf20Sopenharmony_ci 26418c2ecf20Sopenharmony_cimul64_ccode_set: 26428c2ecf20Sopenharmony_ci mov.b EXC_CC+1(%a6), %d6 # fetch previous %ccr 26438c2ecf20Sopenharmony_ci andi.b &0x10, %d6 # all but 'X' bit changes 26448c2ecf20Sopenharmony_ci 26458c2ecf20Sopenharmony_ci or.b %d7, %d6 # group 'X' and 'N' 26468c2ecf20Sopenharmony_ci mov.b %d6, EXC_CC+1(%a6) # save new %ccr 26478c2ecf20Sopenharmony_ci 26488c2ecf20Sopenharmony_ci rts 26498c2ecf20Sopenharmony_ci 26508c2ecf20Sopenharmony_ci# one or both of the operands is zero so the result is also zero. 26518c2ecf20Sopenharmony_ci# save the zero result to the register file and set the 'Z' ccode bit. 26528c2ecf20Sopenharmony_cimul64_zero: 26538c2ecf20Sopenharmony_ci clr.l (EXC_DREGS,%a6,%d2.w*4) # save lo(result) 26548c2ecf20Sopenharmony_ci clr.l (EXC_DREGS,%a6,%d1.w*4) # save hi(result) 26558c2ecf20Sopenharmony_ci 26568c2ecf20Sopenharmony_ci movq.l &0x4, %d7 # set 'Z' ccode bit 26578c2ecf20Sopenharmony_ci bra.b mul64_ccode_set # finish ccode set 26588c2ecf20Sopenharmony_ci 26598c2ecf20Sopenharmony_ci########## 26608c2ecf20Sopenharmony_ci 26618c2ecf20Sopenharmony_ci# multiplier operand is in memory at the effective address. 26628c2ecf20Sopenharmony_ci# must calculate the <ea> and go fetch the 32-bit operand. 26638c2ecf20Sopenharmony_cimul64_memop: 26648c2ecf20Sopenharmony_ci movq.l &LONG, %d0 # pass # of bytes 26658c2ecf20Sopenharmony_ci bsr.l _calc_ea # calculate <ea> 26668c2ecf20Sopenharmony_ci 26678c2ecf20Sopenharmony_ci cmpi.b SPCOND_FLG(%a6),&immed_flg # immediate addressing mode? 26688c2ecf20Sopenharmony_ci beq.b mul64_immed # yes 26698c2ecf20Sopenharmony_ci 26708c2ecf20Sopenharmony_ci mov.l %a0,%a2 26718c2ecf20Sopenharmony_ci bsr.l _dmem_read_long # fetch src from addr (%a0) 26728c2ecf20Sopenharmony_ci 26738c2ecf20Sopenharmony_ci tst.l %d1 # dfetch error? 26748c2ecf20Sopenharmony_ci bne.w mul64_err # yes 26758c2ecf20Sopenharmony_ci 26768c2ecf20Sopenharmony_ci mov.l %d0, %d3 # store multiplier in %d3 26778c2ecf20Sopenharmony_ci 26788c2ecf20Sopenharmony_ci bra.w mul64_multiplicand 26798c2ecf20Sopenharmony_ci 26808c2ecf20Sopenharmony_ci# we have to split out immediate data here because it must be read using 26818c2ecf20Sopenharmony_ci# imem_read() instead of dmem_read(). this becomes especially important 26828c2ecf20Sopenharmony_ci# if the fetch runs into some deadly fault. 26838c2ecf20Sopenharmony_cimul64_immed: 26848c2ecf20Sopenharmony_ci addq.l &0x4,EXC_EXTWPTR(%a6) 26858c2ecf20Sopenharmony_ci bsr.l _imem_read_long # read immediate value 26868c2ecf20Sopenharmony_ci 26878c2ecf20Sopenharmony_ci tst.l %d1 # ifetch error? 26888c2ecf20Sopenharmony_ci bne.l isp_iacc # yes 26898c2ecf20Sopenharmony_ci 26908c2ecf20Sopenharmony_ci mov.l %d0,%d3 26918c2ecf20Sopenharmony_ci bra.w mul64_multiplicand 26928c2ecf20Sopenharmony_ci 26938c2ecf20Sopenharmony_ci########## 26948c2ecf20Sopenharmony_ci 26958c2ecf20Sopenharmony_ci# if dmem_read_long() returns a fail message in d1, the package 26968c2ecf20Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw 26978c2ecf20Sopenharmony_ci# and the failing address to the routine that creates the new frame. 26988c2ecf20Sopenharmony_ci# also, we call isp_restore in case the effective addressing mode was 26998c2ecf20Sopenharmony_ci# (an)+ or -(an) in which case the previous "an" value must be restored. 27008c2ecf20Sopenharmony_ci# FSLW: 27018c2ecf20Sopenharmony_ci# read = true 27028c2ecf20Sopenharmony_ci# size = longword 27038c2ecf20Sopenharmony_ci# TM = data 27048c2ecf20Sopenharmony_ci# software emulation error = true 27058c2ecf20Sopenharmony_cimul64_err: 27068c2ecf20Sopenharmony_ci bsr.l isp_restore # restore addr reg 27078c2ecf20Sopenharmony_ci mov.l %a2,%a0 # pass failing address 27088c2ecf20Sopenharmony_ci mov.l &0x01010001,%d0 # pass fslw 27098c2ecf20Sopenharmony_ci bra.l isp_dacc 27108c2ecf20Sopenharmony_ci 27118c2ecf20Sopenharmony_ci######################################################################### 27128c2ecf20Sopenharmony_ci# XDEF **************************************************************** # 27138c2ecf20Sopenharmony_ci# _compandset2(): routine to emulate cas2() # 27148c2ecf20Sopenharmony_ci# (internal to package) # 27158c2ecf20Sopenharmony_ci# # 27168c2ecf20Sopenharmony_ci# _isp_cas2_finish(): store ccodes, store compare regs # 27178c2ecf20Sopenharmony_ci# (external to package) # 27188c2ecf20Sopenharmony_ci# # 27198c2ecf20Sopenharmony_ci# XREF **************************************************************** # 27208c2ecf20Sopenharmony_ci# _real_lock_page() - "callout" to lock op's page from page-outs # 27218c2ecf20Sopenharmony_ci# _cas_terminate2() - access error exit # 27228c2ecf20Sopenharmony_ci# _real_cas2() - "callout" to core cas2 emulation code # 27238c2ecf20Sopenharmony_ci# _real_unlock_page() - "callout" to unlock page # 27248c2ecf20Sopenharmony_ci# # 27258c2ecf20Sopenharmony_ci# INPUT *************************************************************** # 27268c2ecf20Sopenharmony_ci# _compandset2(): # 27278c2ecf20Sopenharmony_ci# d0 = instruction extension word # 27288c2ecf20Sopenharmony_ci# # 27298c2ecf20Sopenharmony_ci# _isp_cas2_finish(): # 27308c2ecf20Sopenharmony_ci# see cas2 core emulation code # 27318c2ecf20Sopenharmony_ci# # 27328c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** # 27338c2ecf20Sopenharmony_ci# _compandset2(): # 27348c2ecf20Sopenharmony_ci# see cas2 core emulation code # 27358c2ecf20Sopenharmony_ci# # 27368c2ecf20Sopenharmony_ci# _isp_cas_finish(): # 27378c2ecf20Sopenharmony_ci# None (register file or memroy changed as appropriate) # 27388c2ecf20Sopenharmony_ci# # 27398c2ecf20Sopenharmony_ci# ALGORITHM *********************************************************** # 27408c2ecf20Sopenharmony_ci# compandset2(): # 27418c2ecf20Sopenharmony_ci# Decode the instruction and fetch the appropriate Update and # 27428c2ecf20Sopenharmony_ci# Compare operands. Then call the "callout" _real_lock_page() for each # 27438c2ecf20Sopenharmony_ci# memory operand address so that the operating system can keep these # 27448c2ecf20Sopenharmony_ci# pages from being paged out. If either _real_lock_page() fails, exit # 27458c2ecf20Sopenharmony_ci# through _cas_terminate2(). Don't forget to unlock the 1st locked page # 27468c2ecf20Sopenharmony_ci# using _real_unlock_paged() if the 2nd lock-page fails. # 27478c2ecf20Sopenharmony_ci# Finally, branch to the core cas2 emulation code by calling the # 27488c2ecf20Sopenharmony_ci# "callout" _real_cas2(). # 27498c2ecf20Sopenharmony_ci# # 27508c2ecf20Sopenharmony_ci# _isp_cas2_finish(): # 27518c2ecf20Sopenharmony_ci# Re-perform the comparison so we can determine the condition # 27528c2ecf20Sopenharmony_ci# codes which were too much trouble to keep around during the locked # 27538c2ecf20Sopenharmony_ci# emulation. Then unlock each operands page by calling the "callout" # 27548c2ecf20Sopenharmony_ci# _real_unlock_page(). # 27558c2ecf20Sopenharmony_ci# # 27568c2ecf20Sopenharmony_ci######################################################################### 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ciset ADDR1, EXC_TEMP+0xc 27598c2ecf20Sopenharmony_ciset ADDR2, EXC_TEMP+0x0 27608c2ecf20Sopenharmony_ciset DC2, EXC_TEMP+0xa 27618c2ecf20Sopenharmony_ciset DC1, EXC_TEMP+0x8 27628c2ecf20Sopenharmony_ci 27638c2ecf20Sopenharmony_ci global _compandset2 27648c2ecf20Sopenharmony_ci_compandset2: 27658c2ecf20Sopenharmony_ci mov.l %d0,EXC_TEMP+0x4(%a6) # store for possible restart 27668c2ecf20Sopenharmony_ci mov.l %d0,%d1 # extension word in d0 27678c2ecf20Sopenharmony_ci 27688c2ecf20Sopenharmony_ci rol.w &0x4,%d0 27698c2ecf20Sopenharmony_ci andi.w &0xf,%d0 # extract Rn2 27708c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4),%a1 # fetch ADDR2 27718c2ecf20Sopenharmony_ci mov.l %a1,ADDR2(%a6) 27728c2ecf20Sopenharmony_ci 27738c2ecf20Sopenharmony_ci mov.l %d1,%d0 27748c2ecf20Sopenharmony_ci 27758c2ecf20Sopenharmony_ci lsr.w &0x6,%d1 27768c2ecf20Sopenharmony_ci andi.w &0x7,%d1 # extract Du2 27778c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d1.w*4),%d5 # fetch Update2 Op 27788c2ecf20Sopenharmony_ci 27798c2ecf20Sopenharmony_ci andi.w &0x7,%d0 # extract Dc2 27808c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4),%d3 # fetch Compare2 Op 27818c2ecf20Sopenharmony_ci mov.w %d0,DC2(%a6) 27828c2ecf20Sopenharmony_ci 27838c2ecf20Sopenharmony_ci mov.w EXC_EXTWORD(%a6),%d0 27848c2ecf20Sopenharmony_ci mov.l %d0,%d1 27858c2ecf20Sopenharmony_ci 27868c2ecf20Sopenharmony_ci rol.w &0x4,%d0 27878c2ecf20Sopenharmony_ci andi.w &0xf,%d0 # extract Rn1 27888c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4),%a0 # fetch ADDR1 27898c2ecf20Sopenharmony_ci mov.l %a0,ADDR1(%a6) 27908c2ecf20Sopenharmony_ci 27918c2ecf20Sopenharmony_ci mov.l %d1,%d0 27928c2ecf20Sopenharmony_ci 27938c2ecf20Sopenharmony_ci lsr.w &0x6,%d1 27948c2ecf20Sopenharmony_ci andi.w &0x7,%d1 # extract Du1 27958c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d1.w*4),%d4 # fetch Update1 Op 27968c2ecf20Sopenharmony_ci 27978c2ecf20Sopenharmony_ci andi.w &0x7,%d0 # extract Dc1 27988c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4),%d2 # fetch Compare1 Op 27998c2ecf20Sopenharmony_ci mov.w %d0,DC1(%a6) 28008c2ecf20Sopenharmony_ci 28018c2ecf20Sopenharmony_ci btst &0x1,EXC_OPWORD(%a6) # word or long? 28028c2ecf20Sopenharmony_ci sne %d7 28038c2ecf20Sopenharmony_ci 28048c2ecf20Sopenharmony_ci btst &0x5,EXC_ISR(%a6) # user or supervisor? 28058c2ecf20Sopenharmony_ci sne %d6 28068c2ecf20Sopenharmony_ci 28078c2ecf20Sopenharmony_ci mov.l %a0,%a2 28088c2ecf20Sopenharmony_ci mov.l %a1,%a3 28098c2ecf20Sopenharmony_ci 28108c2ecf20Sopenharmony_ci mov.l %d7,%d1 # pass size 28118c2ecf20Sopenharmony_ci mov.l %d6,%d0 # pass mode 28128c2ecf20Sopenharmony_ci bsr.l _real_lock_page # lock page 28138c2ecf20Sopenharmony_ci mov.l %a2,%a0 28148c2ecf20Sopenharmony_ci tst.l %d0 # error? 28158c2ecf20Sopenharmony_ci bne.l _cas_terminate2 # yes 28168c2ecf20Sopenharmony_ci 28178c2ecf20Sopenharmony_ci mov.l %d7,%d1 # pass size 28188c2ecf20Sopenharmony_ci mov.l %d6,%d0 # pass mode 28198c2ecf20Sopenharmony_ci mov.l %a3,%a0 # pass addr 28208c2ecf20Sopenharmony_ci bsr.l _real_lock_page # lock page 28218c2ecf20Sopenharmony_ci mov.l %a3,%a0 28228c2ecf20Sopenharmony_ci tst.l %d0 # error? 28238c2ecf20Sopenharmony_ci bne.b cas_preterm # yes 28248c2ecf20Sopenharmony_ci 28258c2ecf20Sopenharmony_ci mov.l %a2,%a0 28268c2ecf20Sopenharmony_ci mov.l %a3,%a1 28278c2ecf20Sopenharmony_ci 28288c2ecf20Sopenharmony_ci bra.l _real_cas2 28298c2ecf20Sopenharmony_ci 28308c2ecf20Sopenharmony_ci# if the 2nd lock attempt fails, then we must still unlock the 28318c2ecf20Sopenharmony_ci# first page(s). 28328c2ecf20Sopenharmony_cicas_preterm: 28338c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) # save FSLW 28348c2ecf20Sopenharmony_ci mov.l %d7,%d1 # pass size 28358c2ecf20Sopenharmony_ci mov.l %d6,%d0 # pass mode 28368c2ecf20Sopenharmony_ci mov.l %a2,%a0 # pass ADDR1 28378c2ecf20Sopenharmony_ci bsr.l _real_unlock_page # unlock first page(s) 28388c2ecf20Sopenharmony_ci mov.l (%sp)+,%d0 # restore FSLW 28398c2ecf20Sopenharmony_ci mov.l %a3,%a0 # pass failing addr 28408c2ecf20Sopenharmony_ci bra.l _cas_terminate2 28418c2ecf20Sopenharmony_ci 28428c2ecf20Sopenharmony_ci############################################################# 28438c2ecf20Sopenharmony_ci 28448c2ecf20Sopenharmony_ci global _isp_cas2_finish 28458c2ecf20Sopenharmony_ci_isp_cas2_finish: 28468c2ecf20Sopenharmony_ci btst &0x1,EXC_OPWORD(%a6) 28478c2ecf20Sopenharmony_ci bne.b cas2_finish_l 28488c2ecf20Sopenharmony_ci 28498c2ecf20Sopenharmony_ci mov.w EXC_CC(%a6),%cc # load old ccodes 28508c2ecf20Sopenharmony_ci cmp.w %d0,%d2 28518c2ecf20Sopenharmony_ci bne.b cas2_finish_w_save 28528c2ecf20Sopenharmony_ci cmp.w %d1,%d3 28538c2ecf20Sopenharmony_cicas2_finish_w_save: 28548c2ecf20Sopenharmony_ci mov.w %cc,EXC_CC(%a6) # save new ccodes 28558c2ecf20Sopenharmony_ci 28568c2ecf20Sopenharmony_ci tst.b %d4 # update compare reg? 28578c2ecf20Sopenharmony_ci bne.b cas2_finish_w_done # no 28588c2ecf20Sopenharmony_ci 28598c2ecf20Sopenharmony_ci mov.w DC2(%a6),%d3 # fetch Dc2 28608c2ecf20Sopenharmony_ci mov.w %d1,(2+EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op 28618c2ecf20Sopenharmony_ci 28628c2ecf20Sopenharmony_ci mov.w DC1(%a6),%d2 # fetch Dc1 28638c2ecf20Sopenharmony_ci mov.w %d0,(2+EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op 28648c2ecf20Sopenharmony_ci 28658c2ecf20Sopenharmony_cicas2_finish_w_done: 28668c2ecf20Sopenharmony_ci btst &0x5,EXC_ISR(%a6) 28678c2ecf20Sopenharmony_ci sne %d2 28688c2ecf20Sopenharmony_ci mov.l %d2,%d0 # pass mode 28698c2ecf20Sopenharmony_ci sf %d1 # pass size 28708c2ecf20Sopenharmony_ci mov.l ADDR1(%a6),%a0 # pass ADDR1 28718c2ecf20Sopenharmony_ci bsr.l _real_unlock_page # unlock page 28728c2ecf20Sopenharmony_ci 28738c2ecf20Sopenharmony_ci mov.l %d2,%d0 # pass mode 28748c2ecf20Sopenharmony_ci sf %d1 # pass size 28758c2ecf20Sopenharmony_ci mov.l ADDR2(%a6),%a0 # pass ADDR2 28768c2ecf20Sopenharmony_ci bsr.l _real_unlock_page # unlock page 28778c2ecf20Sopenharmony_ci rts 28788c2ecf20Sopenharmony_ci 28798c2ecf20Sopenharmony_cicas2_finish_l: 28808c2ecf20Sopenharmony_ci mov.w EXC_CC(%a6),%cc # load old ccodes 28818c2ecf20Sopenharmony_ci cmp.l %d0,%d2 28828c2ecf20Sopenharmony_ci bne.b cas2_finish_l_save 28838c2ecf20Sopenharmony_ci cmp.l %d1,%d3 28848c2ecf20Sopenharmony_cicas2_finish_l_save: 28858c2ecf20Sopenharmony_ci mov.w %cc,EXC_CC(%a6) # save new ccodes 28868c2ecf20Sopenharmony_ci 28878c2ecf20Sopenharmony_ci tst.b %d4 # update compare reg? 28888c2ecf20Sopenharmony_ci bne.b cas2_finish_l_done # no 28898c2ecf20Sopenharmony_ci 28908c2ecf20Sopenharmony_ci mov.w DC2(%a6),%d3 # fetch Dc2 28918c2ecf20Sopenharmony_ci mov.l %d1,(EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op 28928c2ecf20Sopenharmony_ci 28938c2ecf20Sopenharmony_ci mov.w DC1(%a6),%d2 # fetch Dc1 28948c2ecf20Sopenharmony_ci mov.l %d0,(EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op 28958c2ecf20Sopenharmony_ci 28968c2ecf20Sopenharmony_cicas2_finish_l_done: 28978c2ecf20Sopenharmony_ci btst &0x5,EXC_ISR(%a6) 28988c2ecf20Sopenharmony_ci sne %d2 28998c2ecf20Sopenharmony_ci mov.l %d2,%d0 # pass mode 29008c2ecf20Sopenharmony_ci st %d1 # pass size 29018c2ecf20Sopenharmony_ci mov.l ADDR1(%a6),%a0 # pass ADDR1 29028c2ecf20Sopenharmony_ci bsr.l _real_unlock_page # unlock page 29038c2ecf20Sopenharmony_ci 29048c2ecf20Sopenharmony_ci mov.l %d2,%d0 # pass mode 29058c2ecf20Sopenharmony_ci st %d1 # pass size 29068c2ecf20Sopenharmony_ci mov.l ADDR2(%a6),%a0 # pass ADDR2 29078c2ecf20Sopenharmony_ci bsr.l _real_unlock_page # unlock page 29088c2ecf20Sopenharmony_ci rts 29098c2ecf20Sopenharmony_ci 29108c2ecf20Sopenharmony_ci######## 29118c2ecf20Sopenharmony_ci global cr_cas2 29128c2ecf20Sopenharmony_cicr_cas2: 29138c2ecf20Sopenharmony_ci mov.l EXC_TEMP+0x4(%a6),%d0 29148c2ecf20Sopenharmony_ci bra.w _compandset2 29158c2ecf20Sopenharmony_ci 29168c2ecf20Sopenharmony_ci######################################################################### 29178c2ecf20Sopenharmony_ci# XDEF **************************************************************** # 29188c2ecf20Sopenharmony_ci# _compandset(): routine to emulate cas w/ misaligned <ea> # 29198c2ecf20Sopenharmony_ci# (internal to package) # 29208c2ecf20Sopenharmony_ci# _isp_cas_finish(): routine called when cas emulation completes # 29218c2ecf20Sopenharmony_ci# (external and internal to package) # 29228c2ecf20Sopenharmony_ci# _isp_cas_restart(): restart cas emulation after a fault # 29238c2ecf20Sopenharmony_ci# (external to package) # 29248c2ecf20Sopenharmony_ci# _isp_cas_terminate(): create access error stack frame on fault # 29258c2ecf20Sopenharmony_ci# (external and internal to package) # 29268c2ecf20Sopenharmony_ci# _isp_cas_inrange(): checks whether instr addess is within range # 29278c2ecf20Sopenharmony_ci# of core cas/cas2emulation code # 29288c2ecf20Sopenharmony_ci# (external to package) # 29298c2ecf20Sopenharmony_ci# # 29308c2ecf20Sopenharmony_ci# XREF **************************************************************** # 29318c2ecf20Sopenharmony_ci# _calc_ea(): calculate effective address # 29328c2ecf20Sopenharmony_ci# # 29338c2ecf20Sopenharmony_ci# INPUT *************************************************************** # 29348c2ecf20Sopenharmony_ci# compandset(): # 29358c2ecf20Sopenharmony_ci# none # 29368c2ecf20Sopenharmony_ci# _isp_cas_restart(): # 29378c2ecf20Sopenharmony_ci# d6 = previous sfc/dfc # 29388c2ecf20Sopenharmony_ci# _isp_cas_finish(): # 29398c2ecf20Sopenharmony_ci# _isp_cas_terminate(): # 29408c2ecf20Sopenharmony_ci# a0 = failing address # 29418c2ecf20Sopenharmony_ci# d0 = FSLW # 29428c2ecf20Sopenharmony_ci# d6 = previous sfc/dfc # 29438c2ecf20Sopenharmony_ci# _isp_cas_inrange(): # 29448c2ecf20Sopenharmony_ci# a0 = instruction address to be checked # 29458c2ecf20Sopenharmony_ci# # 29468c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** # 29478c2ecf20Sopenharmony_ci# compandset(): # 29488c2ecf20Sopenharmony_ci# none # 29498c2ecf20Sopenharmony_ci# _isp_cas_restart(): # 29508c2ecf20Sopenharmony_ci# a0 = effective address # 29518c2ecf20Sopenharmony_ci# d7 = word or longword flag # 29528c2ecf20Sopenharmony_ci# _isp_cas_finish(): # 29538c2ecf20Sopenharmony_ci# a0 = effective address # 29548c2ecf20Sopenharmony_ci# _isp_cas_terminate(): # 29558c2ecf20Sopenharmony_ci# initial register set before emulation exception # 29568c2ecf20Sopenharmony_ci# _isp_cas_inrange(): # 29578c2ecf20Sopenharmony_ci# d0 = 0 => in range; -1 => out of range # 29588c2ecf20Sopenharmony_ci# # 29598c2ecf20Sopenharmony_ci# ALGORITHM *********************************************************** # 29608c2ecf20Sopenharmony_ci# # 29618c2ecf20Sopenharmony_ci# compandset(): # 29628c2ecf20Sopenharmony_ci# First, calculate the effective address. Then, decode the # 29638c2ecf20Sopenharmony_ci# instruction word and fetch the "compare" (DC) and "update" (Du) # 29648c2ecf20Sopenharmony_ci# operands. # 29658c2ecf20Sopenharmony_ci# Next, call the external routine _real_lock_page() so that the # 29668c2ecf20Sopenharmony_ci# operating system can keep this page from being paged out while we're # 29678c2ecf20Sopenharmony_ci# in this routine. If this call fails, jump to _cas_terminate2(). # 29688c2ecf20Sopenharmony_ci# The routine then branches to _real_cas(). This external routine # 29698c2ecf20Sopenharmony_ci# that actually emulates cas can be supplied by the external os or # 29708c2ecf20Sopenharmony_ci# made to point directly back into the 060ISP which has a routine for # 29718c2ecf20Sopenharmony_ci# this purpose. # 29728c2ecf20Sopenharmony_ci# # 29738c2ecf20Sopenharmony_ci# _isp_cas_finish(): # 29748c2ecf20Sopenharmony_ci# Either way, after emulation, the package is re-entered at # 29758c2ecf20Sopenharmony_ci# _isp_cas_finish(). This routine re-compares the operands in order to # 29768c2ecf20Sopenharmony_ci# set the condition codes. Finally, these routines will call # 29778c2ecf20Sopenharmony_ci# _real_unlock_page() in order to unlock the pages that were previously # 29788c2ecf20Sopenharmony_ci# locked. # 29798c2ecf20Sopenharmony_ci# # 29808c2ecf20Sopenharmony_ci# _isp_cas_restart(): # 29818c2ecf20Sopenharmony_ci# This routine can be entered from an access error handler where # 29828c2ecf20Sopenharmony_ci# the emulation sequence should be re-started from the beginning. # 29838c2ecf20Sopenharmony_ci# # 29848c2ecf20Sopenharmony_ci# _isp_cas_terminate(): # 29858c2ecf20Sopenharmony_ci# This routine can be entered from an access error handler where # 29868c2ecf20Sopenharmony_ci# an emulation operand access failed and the operating system would # 29878c2ecf20Sopenharmony_ci# like an access error stack frame created instead of the current # 29888c2ecf20Sopenharmony_ci# unimplemented integer instruction frame. # 29898c2ecf20Sopenharmony_ci# Also, the package enters here if a call to _real_lock_page() # 29908c2ecf20Sopenharmony_ci# fails. # 29918c2ecf20Sopenharmony_ci# # 29928c2ecf20Sopenharmony_ci# _isp_cas_inrange(): # 29938c2ecf20Sopenharmony_ci# Checks to see whether the instruction address passed to it in # 29948c2ecf20Sopenharmony_ci# a0 is within the software package cas/cas2 emulation routines. This # 29958c2ecf20Sopenharmony_ci# can be helpful for an operating system to determine whether an access # 29968c2ecf20Sopenharmony_ci# error during emulation was due to a cas/cas2 emulation access. # 29978c2ecf20Sopenharmony_ci# # 29988c2ecf20Sopenharmony_ci######################################################################### 29998c2ecf20Sopenharmony_ci 30008c2ecf20Sopenharmony_ciset DC, EXC_TEMP+0x8 30018c2ecf20Sopenharmony_ciset ADDR, EXC_TEMP+0x4 30028c2ecf20Sopenharmony_ci 30038c2ecf20Sopenharmony_ci global _compandset 30048c2ecf20Sopenharmony_ci_compandset: 30058c2ecf20Sopenharmony_ci btst &0x1,EXC_OPWORD(%a6) # word or long operation? 30068c2ecf20Sopenharmony_ci bne.b compandsetl # long 30078c2ecf20Sopenharmony_ci 30088c2ecf20Sopenharmony_cicompandsetw: 30098c2ecf20Sopenharmony_ci movq.l &0x2,%d0 # size = 2 bytes 30108c2ecf20Sopenharmony_ci bsr.l _calc_ea # a0 = calculated <ea> 30118c2ecf20Sopenharmony_ci mov.l %a0,ADDR(%a6) # save <ea> for possible restart 30128c2ecf20Sopenharmony_ci sf %d7 # clear d7 for word size 30138c2ecf20Sopenharmony_ci bra.b compandsetfetch 30148c2ecf20Sopenharmony_ci 30158c2ecf20Sopenharmony_cicompandsetl: 30168c2ecf20Sopenharmony_ci movq.l &0x4,%d0 # size = 4 bytes 30178c2ecf20Sopenharmony_ci bsr.l _calc_ea # a0 = calculated <ea> 30188c2ecf20Sopenharmony_ci mov.l %a0,ADDR(%a6) # save <ea> for possible restart 30198c2ecf20Sopenharmony_ci st %d7 # set d7 for longword size 30208c2ecf20Sopenharmony_ci 30218c2ecf20Sopenharmony_cicompandsetfetch: 30228c2ecf20Sopenharmony_ci mov.w EXC_EXTWORD(%a6),%d0 # fetch cas extension word 30238c2ecf20Sopenharmony_ci mov.l %d0,%d1 # make a copy 30248c2ecf20Sopenharmony_ci 30258c2ecf20Sopenharmony_ci lsr.w &0x6,%d0 30268c2ecf20Sopenharmony_ci andi.w &0x7,%d0 # extract Du 30278c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4),%d2 # get update operand 30288c2ecf20Sopenharmony_ci 30298c2ecf20Sopenharmony_ci andi.w &0x7,%d1 # extract Dc 30308c2ecf20Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d1.w*4),%d4 # get compare operand 30318c2ecf20Sopenharmony_ci mov.w %d1,DC(%a6) # save Dc 30328c2ecf20Sopenharmony_ci 30338c2ecf20Sopenharmony_ci btst &0x5,EXC_ISR(%a6) # which mode for exception? 30348c2ecf20Sopenharmony_ci sne %d6 # set on supervisor mode 30358c2ecf20Sopenharmony_ci 30368c2ecf20Sopenharmony_ci mov.l %a0,%a2 # save temporarily 30378c2ecf20Sopenharmony_ci mov.l %d7,%d1 # pass size 30388c2ecf20Sopenharmony_ci mov.l %d6,%d0 # pass mode 30398c2ecf20Sopenharmony_ci bsr.l _real_lock_page # lock page 30408c2ecf20Sopenharmony_ci tst.l %d0 # did error occur? 30418c2ecf20Sopenharmony_ci bne.w _cas_terminate2 # yes, clean up the mess 30428c2ecf20Sopenharmony_ci mov.l %a2,%a0 # pass addr in a0 30438c2ecf20Sopenharmony_ci 30448c2ecf20Sopenharmony_ci bra.l _real_cas 30458c2ecf20Sopenharmony_ci 30468c2ecf20Sopenharmony_ci######## 30478c2ecf20Sopenharmony_ci global _isp_cas_finish 30488c2ecf20Sopenharmony_ci_isp_cas_finish: 30498c2ecf20Sopenharmony_ci btst &0x1,EXC_OPWORD(%a6) 30508c2ecf20Sopenharmony_ci bne.b cas_finish_l 30518c2ecf20Sopenharmony_ci 30528c2ecf20Sopenharmony_ci# just do the compare again since it's faster than saving the ccodes 30538c2ecf20Sopenharmony_ci# from the locked routine... 30548c2ecf20Sopenharmony_cicas_finish_w: 30558c2ecf20Sopenharmony_ci mov.w EXC_CC(%a6),%cc # restore cc 30568c2ecf20Sopenharmony_ci cmp.w %d0,%d4 # do word compare 30578c2ecf20Sopenharmony_ci mov.w %cc,EXC_CC(%a6) # save cc 30588c2ecf20Sopenharmony_ci 30598c2ecf20Sopenharmony_ci tst.b %d1 # update compare reg? 30608c2ecf20Sopenharmony_ci bne.b cas_finish_w_done # no 30618c2ecf20Sopenharmony_ci 30628c2ecf20Sopenharmony_ci mov.w DC(%a6),%d3 30638c2ecf20Sopenharmony_ci mov.w %d0,(EXC_DREGS+2,%a6,%d3.w*4) # Dc = destination 30648c2ecf20Sopenharmony_ci 30658c2ecf20Sopenharmony_cicas_finish_w_done: 30668c2ecf20Sopenharmony_ci mov.l ADDR(%a6),%a0 # pass addr 30678c2ecf20Sopenharmony_ci sf %d1 # pass size 30688c2ecf20Sopenharmony_ci btst &0x5,EXC_ISR(%a6) 30698c2ecf20Sopenharmony_ci sne %d0 # pass mode 30708c2ecf20Sopenharmony_ci bsr.l _real_unlock_page # unlock page 30718c2ecf20Sopenharmony_ci rts 30728c2ecf20Sopenharmony_ci 30738c2ecf20Sopenharmony_ci# just do the compare again since it's faster than saving the ccodes 30748c2ecf20Sopenharmony_ci# from the locked routine... 30758c2ecf20Sopenharmony_cicas_finish_l: 30768c2ecf20Sopenharmony_ci mov.w EXC_CC(%a6),%cc # restore cc 30778c2ecf20Sopenharmony_ci cmp.l %d0,%d4 # do longword compare 30788c2ecf20Sopenharmony_ci mov.w %cc,EXC_CC(%a6) # save cc 30798c2ecf20Sopenharmony_ci 30808c2ecf20Sopenharmony_ci tst.b %d1 # update compare reg? 30818c2ecf20Sopenharmony_ci bne.b cas_finish_l_done # no 30828c2ecf20Sopenharmony_ci 30838c2ecf20Sopenharmony_ci mov.w DC(%a6),%d3 30848c2ecf20Sopenharmony_ci mov.l %d0,(EXC_DREGS,%a6,%d3.w*4) # Dc = destination 30858c2ecf20Sopenharmony_ci 30868c2ecf20Sopenharmony_cicas_finish_l_done: 30878c2ecf20Sopenharmony_ci mov.l ADDR(%a6),%a0 # pass addr 30888c2ecf20Sopenharmony_ci st %d1 # pass size 30898c2ecf20Sopenharmony_ci btst &0x5,EXC_ISR(%a6) 30908c2ecf20Sopenharmony_ci sne %d0 # pass mode 30918c2ecf20Sopenharmony_ci bsr.l _real_unlock_page # unlock page 30928c2ecf20Sopenharmony_ci rts 30938c2ecf20Sopenharmony_ci 30948c2ecf20Sopenharmony_ci######## 30958c2ecf20Sopenharmony_ci 30968c2ecf20Sopenharmony_ci global _isp_cas_restart 30978c2ecf20Sopenharmony_ci_isp_cas_restart: 30988c2ecf20Sopenharmony_ci mov.l %d6,%sfc # restore previous sfc 30998c2ecf20Sopenharmony_ci mov.l %d6,%dfc # restore previous dfc 31008c2ecf20Sopenharmony_ci 31018c2ecf20Sopenharmony_ci cmpi.b EXC_OPWORD+1(%a6),&0xfc # cas or cas2? 31028c2ecf20Sopenharmony_ci beq.l cr_cas2 # cas2 31038c2ecf20Sopenharmony_cicr_cas: 31048c2ecf20Sopenharmony_ci mov.l ADDR(%a6),%a0 # load <ea> 31058c2ecf20Sopenharmony_ci btst &0x1,EXC_OPWORD(%a6) # word or long operation? 31068c2ecf20Sopenharmony_ci sne %d7 # set d7 accordingly 31078c2ecf20Sopenharmony_ci bra.w compandsetfetch 31088c2ecf20Sopenharmony_ci 31098c2ecf20Sopenharmony_ci######## 31108c2ecf20Sopenharmony_ci 31118c2ecf20Sopenharmony_ci# At this stage, it would be nice if d0 held the FSLW. 31128c2ecf20Sopenharmony_ci global _isp_cas_terminate 31138c2ecf20Sopenharmony_ci_isp_cas_terminate: 31148c2ecf20Sopenharmony_ci mov.l %d6,%sfc # restore previous sfc 31158c2ecf20Sopenharmony_ci mov.l %d6,%dfc # restore previous dfc 31168c2ecf20Sopenharmony_ci 31178c2ecf20Sopenharmony_ci global _cas_terminate2 31188c2ecf20Sopenharmony_ci_cas_terminate2: 31198c2ecf20Sopenharmony_ci mov.l %a0,%a2 # copy failing addr to a2 31208c2ecf20Sopenharmony_ci 31218c2ecf20Sopenharmony_ci mov.l %d0,-(%sp) 31228c2ecf20Sopenharmony_ci bsr.l isp_restore # restore An (if ()+ or -()) 31238c2ecf20Sopenharmony_ci mov.l (%sp)+,%d0 31248c2ecf20Sopenharmony_ci 31258c2ecf20Sopenharmony_ci addq.l &0x4,%sp # remove sub return addr 31268c2ecf20Sopenharmony_ci subq.l &0x8,%sp # make room for bigger stack 31278c2ecf20Sopenharmony_ci subq.l &0x8,%a6 # shift frame ptr down, too 31288c2ecf20Sopenharmony_ci mov.l &26,%d1 # want to move 51 longwords 31298c2ecf20Sopenharmony_ci lea 0x8(%sp),%a0 # get address of old stack 31308c2ecf20Sopenharmony_ci lea 0x0(%sp),%a1 # get address of new stack 31318c2ecf20Sopenharmony_cicas_term_cont: 31328c2ecf20Sopenharmony_ci mov.l (%a0)+,(%a1)+ # move a longword 31338c2ecf20Sopenharmony_ci dbra.w %d1,cas_term_cont # keep going 31348c2ecf20Sopenharmony_ci 31358c2ecf20Sopenharmony_ci mov.w &0x4008,EXC_IVOFF(%a6) # put new stk fmt, voff 31368c2ecf20Sopenharmony_ci mov.l %a2,EXC_IVOFF+0x2(%a6) # put faulting addr on stack 31378c2ecf20Sopenharmony_ci mov.l %d0,EXC_IVOFF+0x6(%a6) # put FSLW on stack 31388c2ecf20Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore user regs 31398c2ecf20Sopenharmony_ci unlk %a6 # unlink stack frame 31408c2ecf20Sopenharmony_ci bra.l _real_access 31418c2ecf20Sopenharmony_ci 31428c2ecf20Sopenharmony_ci######## 31438c2ecf20Sopenharmony_ci 31448c2ecf20Sopenharmony_ci global _isp_cas_inrange 31458c2ecf20Sopenharmony_ci_isp_cas_inrange: 31468c2ecf20Sopenharmony_ci clr.l %d0 # clear return result 31478c2ecf20Sopenharmony_ci lea _CASHI(%pc),%a1 # load end of CAS core code 31488c2ecf20Sopenharmony_ci cmp.l %a1,%a0 # is PC in range? 31498c2ecf20Sopenharmony_ci blt.b cin_no # no 31508c2ecf20Sopenharmony_ci lea _CASLO(%pc),%a1 # load begin of CAS core code 31518c2ecf20Sopenharmony_ci cmp.l %a0,%a1 # is PC in range? 31528c2ecf20Sopenharmony_ci blt.b cin_no # no 31538c2ecf20Sopenharmony_ci rts # yes; return d0 = 0 31548c2ecf20Sopenharmony_cicin_no: 31558c2ecf20Sopenharmony_ci mov.l &-0x1,%d0 # out of range; return d0 = -1 31568c2ecf20Sopenharmony_ci rts 31578c2ecf20Sopenharmony_ci 31588c2ecf20Sopenharmony_ci################################################################# 31598c2ecf20Sopenharmony_ci################################################################# 31608c2ecf20Sopenharmony_ci################################################################# 31618c2ecf20Sopenharmony_ci# This is the start of the cas and cas2 "core" emulation code. # 31628c2ecf20Sopenharmony_ci# This is the section that may need to be replaced by the host # 31638c2ecf20Sopenharmony_ci# OS if it is too operating system-specific. # 31648c2ecf20Sopenharmony_ci# Please refer to the package documentation to see how to # 31658c2ecf20Sopenharmony_ci# "replace" this section, if necessary. # 31668c2ecf20Sopenharmony_ci################################################################# 31678c2ecf20Sopenharmony_ci################################################################# 31688c2ecf20Sopenharmony_ci################################################################# 31698c2ecf20Sopenharmony_ci 31708c2ecf20Sopenharmony_ci# ###### ## ###### #### 31718c2ecf20Sopenharmony_ci# # # # # # # 31728c2ecf20Sopenharmony_ci# # ###### ###### # 31738c2ecf20Sopenharmony_ci# # # # # # 31748c2ecf20Sopenharmony_ci# ###### # # ###### ###### 31758c2ecf20Sopenharmony_ci 31768c2ecf20Sopenharmony_ci######################################################################### 31778c2ecf20Sopenharmony_ci# XDEF **************************************************************** # 31788c2ecf20Sopenharmony_ci# _isp_cas2(): "core" emulation code for the cas2 instruction # 31798c2ecf20Sopenharmony_ci# # 31808c2ecf20Sopenharmony_ci# XREF **************************************************************** # 31818c2ecf20Sopenharmony_ci# _isp_cas2_finish() - only exit point for this emulation code; # 31828c2ecf20Sopenharmony_ci# do clean-up; calculate ccodes; store # 31838c2ecf20Sopenharmony_ci# Compare Ops if appropriate. # 31848c2ecf20Sopenharmony_ci# # 31858c2ecf20Sopenharmony_ci# INPUT *************************************************************** # 31868c2ecf20Sopenharmony_ci# *see chart below* # 31878c2ecf20Sopenharmony_ci# # 31888c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** # 31898c2ecf20Sopenharmony_ci# *see chart below* # 31908c2ecf20Sopenharmony_ci# # 31918c2ecf20Sopenharmony_ci# ALGORITHM *********************************************************** # 31928c2ecf20Sopenharmony_ci# (1) Make several copies of the effective address. # 31938c2ecf20Sopenharmony_ci# (2) Save current SR; Then mask off all maskable interrupts. # 31948c2ecf20Sopenharmony_ci# (3) Save current SFC/DFC (ASSUMED TO BE EQUAL!!!); Then set # 31958c2ecf20Sopenharmony_ci# according to whether exception occurred in user or # 31968c2ecf20Sopenharmony_ci# supervisor mode. # 31978c2ecf20Sopenharmony_ci# (4) Use "plpaw" instruction to pre-load ATC with effective # 31988c2ecf20Sopenharmony_ci# address pages(s). THIS SHOULD NOT FAULT!!! The relevant # 31998c2ecf20Sopenharmony_ci# page(s) should have already been made resident prior to # 32008c2ecf20Sopenharmony_ci# entering this routine. # 32018c2ecf20Sopenharmony_ci# (5) Push the operand lines from the cache w/ "cpushl". # 32028c2ecf20Sopenharmony_ci# In the 68040, this was done within the locked region. In # 32038c2ecf20Sopenharmony_ci# the 68060, it is done outside of the locked region. # 32048c2ecf20Sopenharmony_ci# (6) Use "plpar" instruction to do a re-load of ATC entries for # 32058c2ecf20Sopenharmony_ci# ADDR1 since ADDR2 entries may have pushed ADDR1 out of the # 32068c2ecf20Sopenharmony_ci# ATC. # 32078c2ecf20Sopenharmony_ci# (7) Pre-fetch the core emulation instructions by executing # 32088c2ecf20Sopenharmony_ci# one branch within each physical line (16 bytes) of the code # 32098c2ecf20Sopenharmony_ci# before actually executing the code. # 32108c2ecf20Sopenharmony_ci# (8) Load the BUSCR w/ the bus lock value. # 32118c2ecf20Sopenharmony_ci# (9) Fetch the source operands using "moves". # 32128c2ecf20Sopenharmony_ci# (10)Do the compares. If both equal, go to step (13). # 32138c2ecf20Sopenharmony_ci# (11)Unequal. No update occurs. But, we do write the DST1 op # 32148c2ecf20Sopenharmony_ci# back to itself (as w/ the '040) so we can gracefully unlock # 32158c2ecf20Sopenharmony_ci# the bus (and assert LOCKE*) using BUSCR and the final move. # 32168c2ecf20Sopenharmony_ci# (12)Exit. # 32178c2ecf20Sopenharmony_ci# (13)Write update operand to the DST locations. Use BUSCR to # 32188c2ecf20Sopenharmony_ci# assert LOCKE* for the final write operation. # 32198c2ecf20Sopenharmony_ci# (14)Exit. # 32208c2ecf20Sopenharmony_ci# # 32218c2ecf20Sopenharmony_ci# The algorithm is actually implemented slightly differently # 32228c2ecf20Sopenharmony_ci# depending on the size of the operation and the misalignment of the # 32238c2ecf20Sopenharmony_ci# operands. A misaligned operand must be written in aligned chunks or # 32248c2ecf20Sopenharmony_ci# else the BUSCR register control gets confused. # 32258c2ecf20Sopenharmony_ci# # 32268c2ecf20Sopenharmony_ci######################################################################### 32278c2ecf20Sopenharmony_ci 32288c2ecf20Sopenharmony_ci################################################################# 32298c2ecf20Sopenharmony_ci# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON # 32308c2ecf20Sopenharmony_ci# ENTERING _isp_cas2(). # 32318c2ecf20Sopenharmony_ci# # 32328c2ecf20Sopenharmony_ci# D0 = xxxxxxxx # 32338c2ecf20Sopenharmony_ci# D1 = xxxxxxxx # 32348c2ecf20Sopenharmony_ci# D2 = cmp operand 1 # 32358c2ecf20Sopenharmony_ci# D3 = cmp operand 2 # 32368c2ecf20Sopenharmony_ci# D4 = update oper 1 # 32378c2ecf20Sopenharmony_ci# D5 = update oper 2 # 32388c2ecf20Sopenharmony_ci# D6 = 'xxxxxxff if supervisor mode; 'xxxxxx00 if user mode # 32398c2ecf20Sopenharmony_ci# D7 = 'xxxxxxff if longword operation; 'xxxxxx00 if word # 32408c2ecf20Sopenharmony_ci# A0 = ADDR1 # 32418c2ecf20Sopenharmony_ci# A1 = ADDR2 # 32428c2ecf20Sopenharmony_ci# A2 = xxxxxxxx # 32438c2ecf20Sopenharmony_ci# A3 = xxxxxxxx # 32448c2ecf20Sopenharmony_ci# A4 = xxxxxxxx # 32458c2ecf20Sopenharmony_ci# A5 = xxxxxxxx # 32468c2ecf20Sopenharmony_ci# A6 = frame pointer # 32478c2ecf20Sopenharmony_ci# A7 = stack pointer # 32488c2ecf20Sopenharmony_ci################################################################# 32498c2ecf20Sopenharmony_ci 32508c2ecf20Sopenharmony_ci# align 0x1000 32518c2ecf20Sopenharmony_ci# beginning label used by _isp_cas_inrange() 32528c2ecf20Sopenharmony_ci global _CASLO 32538c2ecf20Sopenharmony_ci_CASLO: 32548c2ecf20Sopenharmony_ci 32558c2ecf20Sopenharmony_ci global _isp_cas2 32568c2ecf20Sopenharmony_ci_isp_cas2: 32578c2ecf20Sopenharmony_ci tst.b %d6 # user or supervisor mode? 32588c2ecf20Sopenharmony_ci bne.b cas2_supervisor # supervisor 32598c2ecf20Sopenharmony_cicas2_user: 32608c2ecf20Sopenharmony_ci movq.l &0x1,%d0 # load user data fc 32618c2ecf20Sopenharmony_ci bra.b cas2_cont 32628c2ecf20Sopenharmony_cicas2_supervisor: 32638c2ecf20Sopenharmony_ci movq.l &0x5,%d0 # load supervisor data fc 32648c2ecf20Sopenharmony_cicas2_cont: 32658c2ecf20Sopenharmony_ci tst.b %d7 # word or longword? 32668c2ecf20Sopenharmony_ci beq.w cas2w # word 32678c2ecf20Sopenharmony_ci 32688c2ecf20Sopenharmony_ci#### 32698c2ecf20Sopenharmony_cicas2l: 32708c2ecf20Sopenharmony_ci mov.l %a0,%a2 # copy ADDR1 32718c2ecf20Sopenharmony_ci mov.l %a1,%a3 # copy ADDR2 32728c2ecf20Sopenharmony_ci mov.l %a0,%a4 # copy ADDR1 32738c2ecf20Sopenharmony_ci mov.l %a1,%a5 # copy ADDR2 32748c2ecf20Sopenharmony_ci 32758c2ecf20Sopenharmony_ci addq.l &0x3,%a4 # ADDR1+3 32768c2ecf20Sopenharmony_ci addq.l &0x3,%a5 # ADDR2+3 32778c2ecf20Sopenharmony_ci mov.l %a2,%d1 # ADDR1 32788c2ecf20Sopenharmony_ci 32798c2ecf20Sopenharmony_ci# mask interrupts levels 0-6. save old mask value. 32808c2ecf20Sopenharmony_ci mov.w %sr,%d7 # save current SR 32818c2ecf20Sopenharmony_ci ori.w &0x0700,%sr # inhibit interrupts 32828c2ecf20Sopenharmony_ci 32838c2ecf20Sopenharmony_ci# load the SFC and DFC with the appropriate mode. 32848c2ecf20Sopenharmony_ci movc %sfc,%d6 # save old SFC/DFC 32858c2ecf20Sopenharmony_ci movc %d0,%sfc # store new SFC 32868c2ecf20Sopenharmony_ci movc %d0,%dfc # store new DFC 32878c2ecf20Sopenharmony_ci 32888c2ecf20Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because 32898c2ecf20Sopenharmony_ci# _real_lock_page() should have taken care of this. 32908c2ecf20Sopenharmony_ci plpaw (%a2) # load atc for ADDR1 32918c2ecf20Sopenharmony_ci plpaw (%a4) # load atc for ADDR1+3 32928c2ecf20Sopenharmony_ci plpaw (%a3) # load atc for ADDR2 32938c2ecf20Sopenharmony_ci plpaw (%a5) # load atc for ADDR2+3 32948c2ecf20Sopenharmony_ci 32958c2ecf20Sopenharmony_ci# push the operand lines from the cache if they exist. 32968c2ecf20Sopenharmony_ci cpushl %dc,(%a2) # push line for ADDR1 32978c2ecf20Sopenharmony_ci cpushl %dc,(%a4) # push line for ADDR1+3 32988c2ecf20Sopenharmony_ci cpushl %dc,(%a3) # push line for ADDR2 32998c2ecf20Sopenharmony_ci cpushl %dc,(%a5) # push line for ADDR2+2 33008c2ecf20Sopenharmony_ci 33018c2ecf20Sopenharmony_ci mov.l %d1,%a2 # ADDR1 33028c2ecf20Sopenharmony_ci addq.l &0x3,%d1 33038c2ecf20Sopenharmony_ci mov.l %d1,%a4 # ADDR1+3 33048c2ecf20Sopenharmony_ci# if ADDR1 was ATC resident before the above "plpaw" and was executed 33058c2ecf20Sopenharmony_ci# and it was the next entry scheduled for replacement and ADDR2 33068c2ecf20Sopenharmony_ci# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1 33078c2ecf20Sopenharmony_ci# entries from the ATC. so, we do a second set of "plpa"s. 33088c2ecf20Sopenharmony_ci plpar (%a2) # load atc for ADDR1 33098c2ecf20Sopenharmony_ci plpar (%a4) # load atc for ADDR1+3 33108c2ecf20Sopenharmony_ci 33118c2ecf20Sopenharmony_ci# load the BUSCR values. 33128c2ecf20Sopenharmony_ci mov.l &0x80000000,%a2 # assert LOCK* buscr value 33138c2ecf20Sopenharmony_ci mov.l &0xa0000000,%a3 # assert LOCKE* buscr value 33148c2ecf20Sopenharmony_ci mov.l &0x00000000,%a4 # buscr unlock value 33158c2ecf20Sopenharmony_ci 33168c2ecf20Sopenharmony_ci# there are three possible mis-aligned cases for longword cas. they 33178c2ecf20Sopenharmony_ci# are separated because the final write which asserts LOCKE* must 33188c2ecf20Sopenharmony_ci# be aligned. 33198c2ecf20Sopenharmony_ci mov.l %a0,%d0 # is ADDR1 misaligned? 33208c2ecf20Sopenharmony_ci andi.b &0x3,%d0 33218c2ecf20Sopenharmony_ci beq.b CAS2L_ENTER # no 33228c2ecf20Sopenharmony_ci cmpi.b %d0,&0x2 33238c2ecf20Sopenharmony_ci beq.w CAS2L2_ENTER # yes; word misaligned 33248c2ecf20Sopenharmony_ci bra.w CAS2L3_ENTER # yes; byte misaligned 33258c2ecf20Sopenharmony_ci 33268c2ecf20Sopenharmony_ci# 33278c2ecf20Sopenharmony_ci# D0 = dst operand 1 <- 33288c2ecf20Sopenharmony_ci# D1 = dst operand 2 <- 33298c2ecf20Sopenharmony_ci# D2 = cmp operand 1 33308c2ecf20Sopenharmony_ci# D3 = cmp operand 2 33318c2ecf20Sopenharmony_ci# D4 = update oper 1 33328c2ecf20Sopenharmony_ci# D5 = update oper 2 33338c2ecf20Sopenharmony_ci# D6 = old SFC/DFC 33348c2ecf20Sopenharmony_ci# D7 = old SR 33358c2ecf20Sopenharmony_ci# A0 = ADDR1 33368c2ecf20Sopenharmony_ci# A1 = ADDR2 33378c2ecf20Sopenharmony_ci# A2 = bus LOCK* value 33388c2ecf20Sopenharmony_ci# A3 = bus LOCKE* value 33398c2ecf20Sopenharmony_ci# A4 = bus unlock value 33408c2ecf20Sopenharmony_ci# A5 = xxxxxxxx 33418c2ecf20Sopenharmony_ci# 33428c2ecf20Sopenharmony_ci align 0x10 33438c2ecf20Sopenharmony_ciCAS2L_START: 33448c2ecf20Sopenharmony_ci movc %a2,%buscr # assert LOCK* 33458c2ecf20Sopenharmony_ci movs.l (%a1),%d1 # fetch Dest2[31:0] 33468c2ecf20Sopenharmony_ci movs.l (%a0),%d0 # fetch Dest1[31:0] 33478c2ecf20Sopenharmony_ci bra.b CAS2L_CONT 33488c2ecf20Sopenharmony_ciCAS2L_ENTER: 33498c2ecf20Sopenharmony_ci bra.b ~+16 33508c2ecf20Sopenharmony_ci 33518c2ecf20Sopenharmony_ciCAS2L_CONT: 33528c2ecf20Sopenharmony_ci cmp.l %d0,%d2 # Dest1 - Compare1 33538c2ecf20Sopenharmony_ci bne.b CAS2L_NOUPDATE 33548c2ecf20Sopenharmony_ci cmp.l %d1,%d3 # Dest2 - Compare2 33558c2ecf20Sopenharmony_ci bne.b CAS2L_NOUPDATE 33568c2ecf20Sopenharmony_ci movs.l %d5,(%a1) # Update2[31:0] -> DEST2 33578c2ecf20Sopenharmony_ci bra.b CAS2L_UPDATE 33588c2ecf20Sopenharmony_ci bra.b ~+16 33598c2ecf20Sopenharmony_ci 33608c2ecf20Sopenharmony_ciCAS2L_UPDATE: 33618c2ecf20Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 33628c2ecf20Sopenharmony_ci movs.l %d4,(%a0) # Update1[31:0] -> DEST1 33638c2ecf20Sopenharmony_ci movc %a4,%buscr # unlock the bus 33648c2ecf20Sopenharmony_ci bra.b cas2l_update_done 33658c2ecf20Sopenharmony_ci bra.b ~+16 33668c2ecf20Sopenharmony_ci 33678c2ecf20Sopenharmony_ciCAS2L_NOUPDATE: 33688c2ecf20Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 33698c2ecf20Sopenharmony_ci movs.l %d0,(%a0) # Dest1[31:0] -> DEST1 33708c2ecf20Sopenharmony_ci movc %a4,%buscr # unlock the bus 33718c2ecf20Sopenharmony_ci bra.b cas2l_noupdate_done 33728c2ecf20Sopenharmony_ci bra.b ~+16 33738c2ecf20Sopenharmony_ci 33748c2ecf20Sopenharmony_ciCAS2L_FILLER: 33758c2ecf20Sopenharmony_ci nop 33768c2ecf20Sopenharmony_ci nop 33778c2ecf20Sopenharmony_ci nop 33788c2ecf20Sopenharmony_ci nop 33798c2ecf20Sopenharmony_ci nop 33808c2ecf20Sopenharmony_ci nop 33818c2ecf20Sopenharmony_ci nop 33828c2ecf20Sopenharmony_ci bra.b CAS2L_START 33838c2ecf20Sopenharmony_ci 33848c2ecf20Sopenharmony_ci#### 33858c2ecf20Sopenharmony_ci 33868c2ecf20Sopenharmony_ci################################################################# 33878c2ecf20Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON # 33888c2ecf20Sopenharmony_ci# ENTERING _isp_cas2(). # 33898c2ecf20Sopenharmony_ci# # 33908c2ecf20Sopenharmony_ci# D0 = destination[31:0] operand 1 # 33918c2ecf20Sopenharmony_ci# D1 = destination[31:0] operand 2 # 33928c2ecf20Sopenharmony_ci# D2 = cmp[31:0] operand 1 # 33938c2ecf20Sopenharmony_ci# D3 = cmp[31:0] operand 2 # 33948c2ecf20Sopenharmony_ci# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required # 33958c2ecf20Sopenharmony_ci# D5 = xxxxxxxx # 33968c2ecf20Sopenharmony_ci# D6 = xxxxxxxx # 33978c2ecf20Sopenharmony_ci# D7 = xxxxxxxx # 33988c2ecf20Sopenharmony_ci# A0 = xxxxxxxx # 33998c2ecf20Sopenharmony_ci# A1 = xxxxxxxx # 34008c2ecf20Sopenharmony_ci# A2 = xxxxxxxx # 34018c2ecf20Sopenharmony_ci# A3 = xxxxxxxx # 34028c2ecf20Sopenharmony_ci# A4 = xxxxxxxx # 34038c2ecf20Sopenharmony_ci# A5 = xxxxxxxx # 34048c2ecf20Sopenharmony_ci# A6 = frame pointer # 34058c2ecf20Sopenharmony_ci# A7 = stack pointer # 34068c2ecf20Sopenharmony_ci################################################################# 34078c2ecf20Sopenharmony_ci 34088c2ecf20Sopenharmony_cicas2l_noupdate_done: 34098c2ecf20Sopenharmony_ci 34108c2ecf20Sopenharmony_ci# restore previous SFC/DFC value. 34118c2ecf20Sopenharmony_ci movc %d6,%sfc # restore old SFC 34128c2ecf20Sopenharmony_ci movc %d6,%dfc # restore old DFC 34138c2ecf20Sopenharmony_ci 34148c2ecf20Sopenharmony_ci# restore previous interrupt mask level. 34158c2ecf20Sopenharmony_ci mov.w %d7,%sr # restore old SR 34168c2ecf20Sopenharmony_ci 34178c2ecf20Sopenharmony_ci sf %d4 # indicate no update was done 34188c2ecf20Sopenharmony_ci bra.l _isp_cas2_finish 34198c2ecf20Sopenharmony_ci 34208c2ecf20Sopenharmony_cicas2l_update_done: 34218c2ecf20Sopenharmony_ci 34228c2ecf20Sopenharmony_ci# restore previous SFC/DFC value. 34238c2ecf20Sopenharmony_ci movc %d6,%sfc # restore old SFC 34248c2ecf20Sopenharmony_ci movc %d6,%dfc # restore old DFC 34258c2ecf20Sopenharmony_ci 34268c2ecf20Sopenharmony_ci# restore previous interrupt mask level. 34278c2ecf20Sopenharmony_ci mov.w %d7,%sr # restore old SR 34288c2ecf20Sopenharmony_ci 34298c2ecf20Sopenharmony_ci st %d4 # indicate update was done 34308c2ecf20Sopenharmony_ci bra.l _isp_cas2_finish 34318c2ecf20Sopenharmony_ci#### 34328c2ecf20Sopenharmony_ci 34338c2ecf20Sopenharmony_ci align 0x10 34348c2ecf20Sopenharmony_ciCAS2L2_START: 34358c2ecf20Sopenharmony_ci movc %a2,%buscr # assert LOCK* 34368c2ecf20Sopenharmony_ci movs.l (%a1),%d1 # fetch Dest2[31:0] 34378c2ecf20Sopenharmony_ci movs.l (%a0),%d0 # fetch Dest1[31:0] 34388c2ecf20Sopenharmony_ci bra.b CAS2L2_CONT 34398c2ecf20Sopenharmony_ciCAS2L2_ENTER: 34408c2ecf20Sopenharmony_ci bra.b ~+16 34418c2ecf20Sopenharmony_ci 34428c2ecf20Sopenharmony_ciCAS2L2_CONT: 34438c2ecf20Sopenharmony_ci cmp.l %d0,%d2 # Dest1 - Compare1 34448c2ecf20Sopenharmony_ci bne.b CAS2L2_NOUPDATE 34458c2ecf20Sopenharmony_ci cmp.l %d1,%d3 # Dest2 - Compare2 34468c2ecf20Sopenharmony_ci bne.b CAS2L2_NOUPDATE 34478c2ecf20Sopenharmony_ci movs.l %d5,(%a1) # Update2[31:0] -> Dest2 34488c2ecf20Sopenharmony_ci bra.b CAS2L2_UPDATE 34498c2ecf20Sopenharmony_ci bra.b ~+16 34508c2ecf20Sopenharmony_ci 34518c2ecf20Sopenharmony_ciCAS2L2_UPDATE: 34528c2ecf20Sopenharmony_ci swap %d4 # get Update1[31:16] 34538c2ecf20Sopenharmony_ci movs.w %d4,(%a0)+ # Update1[31:16] -> DEST1 34548c2ecf20Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 34558c2ecf20Sopenharmony_ci swap %d4 # get Update1[15:0] 34568c2ecf20Sopenharmony_ci bra.b CAS2L2_UPDATE2 34578c2ecf20Sopenharmony_ci bra.b ~+16 34588c2ecf20Sopenharmony_ci 34598c2ecf20Sopenharmony_ciCAS2L2_UPDATE2: 34608c2ecf20Sopenharmony_ci movs.w %d4,(%a0) # Update1[15:0] -> DEST1+0x2 34618c2ecf20Sopenharmony_ci movc %a4,%buscr # unlock the bus 34628c2ecf20Sopenharmony_ci bra.w cas2l_update_done 34638c2ecf20Sopenharmony_ci nop 34648c2ecf20Sopenharmony_ci bra.b ~+16 34658c2ecf20Sopenharmony_ci 34668c2ecf20Sopenharmony_ciCAS2L2_NOUPDATE: 34678c2ecf20Sopenharmony_ci swap %d0 # get Dest1[31:16] 34688c2ecf20Sopenharmony_ci movs.w %d0,(%a0)+ # Dest1[31:16] -> DEST1 34698c2ecf20Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 34708c2ecf20Sopenharmony_ci swap %d0 # get Dest1[15:0] 34718c2ecf20Sopenharmony_ci bra.b CAS2L2_NOUPDATE2 34728c2ecf20Sopenharmony_ci bra.b ~+16 34738c2ecf20Sopenharmony_ci 34748c2ecf20Sopenharmony_ciCAS2L2_NOUPDATE2: 34758c2ecf20Sopenharmony_ci movs.w %d0,(%a0) # Dest1[15:0] -> DEST1+0x2 34768c2ecf20Sopenharmony_ci movc %a4,%buscr # unlock the bus 34778c2ecf20Sopenharmony_ci bra.w cas2l_noupdate_done 34788c2ecf20Sopenharmony_ci nop 34798c2ecf20Sopenharmony_ci bra.b ~+16 34808c2ecf20Sopenharmony_ci 34818c2ecf20Sopenharmony_ciCAS2L2_FILLER: 34828c2ecf20Sopenharmony_ci nop 34838c2ecf20Sopenharmony_ci nop 34848c2ecf20Sopenharmony_ci nop 34858c2ecf20Sopenharmony_ci nop 34868c2ecf20Sopenharmony_ci nop 34878c2ecf20Sopenharmony_ci nop 34888c2ecf20Sopenharmony_ci nop 34898c2ecf20Sopenharmony_ci bra.b CAS2L2_START 34908c2ecf20Sopenharmony_ci 34918c2ecf20Sopenharmony_ci################################# 34928c2ecf20Sopenharmony_ci 34938c2ecf20Sopenharmony_ci align 0x10 34948c2ecf20Sopenharmony_ciCAS2L3_START: 34958c2ecf20Sopenharmony_ci movc %a2,%buscr # assert LOCK* 34968c2ecf20Sopenharmony_ci movs.l (%a1),%d1 # fetch Dest2[31:0] 34978c2ecf20Sopenharmony_ci movs.l (%a0),%d0 # fetch Dest1[31:0] 34988c2ecf20Sopenharmony_ci bra.b CAS2L3_CONT 34998c2ecf20Sopenharmony_ciCAS2L3_ENTER: 35008c2ecf20Sopenharmony_ci bra.b ~+16 35018c2ecf20Sopenharmony_ci 35028c2ecf20Sopenharmony_ciCAS2L3_CONT: 35038c2ecf20Sopenharmony_ci cmp.l %d0,%d2 # Dest1 - Compare1 35048c2ecf20Sopenharmony_ci bne.b CAS2L3_NOUPDATE 35058c2ecf20Sopenharmony_ci cmp.l %d1,%d3 # Dest2 - Compare2 35068c2ecf20Sopenharmony_ci bne.b CAS2L3_NOUPDATE 35078c2ecf20Sopenharmony_ci movs.l %d5,(%a1) # Update2[31:0] -> DEST2 35088c2ecf20Sopenharmony_ci bra.b CAS2L3_UPDATE 35098c2ecf20Sopenharmony_ci bra.b ~+16 35108c2ecf20Sopenharmony_ci 35118c2ecf20Sopenharmony_ciCAS2L3_UPDATE: 35128c2ecf20Sopenharmony_ci rol.l &0x8,%d4 # get Update1[31:24] 35138c2ecf20Sopenharmony_ci movs.b %d4,(%a0)+ # Update1[31:24] -> DEST1 35148c2ecf20Sopenharmony_ci swap %d4 # get Update1[23:8] 35158c2ecf20Sopenharmony_ci movs.w %d4,(%a0)+ # Update1[23:8] -> DEST1+0x1 35168c2ecf20Sopenharmony_ci bra.b CAS2L3_UPDATE2 35178c2ecf20Sopenharmony_ci bra.b ~+16 35188c2ecf20Sopenharmony_ci 35198c2ecf20Sopenharmony_ciCAS2L3_UPDATE2: 35208c2ecf20Sopenharmony_ci rol.l &0x8,%d4 # get Update1[7:0] 35218c2ecf20Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 35228c2ecf20Sopenharmony_ci movs.b %d4,(%a0) # Update1[7:0] -> DEST1+0x3 35238c2ecf20Sopenharmony_ci bra.b CAS2L3_UPDATE3 35248c2ecf20Sopenharmony_ci nop 35258c2ecf20Sopenharmony_ci bra.b ~+16 35268c2ecf20Sopenharmony_ci 35278c2ecf20Sopenharmony_ciCAS2L3_UPDATE3: 35288c2ecf20Sopenharmony_ci movc %a4,%buscr # unlock the bus 35298c2ecf20Sopenharmony_ci bra.w cas2l_update_done 35308c2ecf20Sopenharmony_ci nop 35318c2ecf20Sopenharmony_ci nop 35328c2ecf20Sopenharmony_ci nop 35338c2ecf20Sopenharmony_ci bra.b ~+16 35348c2ecf20Sopenharmony_ci 35358c2ecf20Sopenharmony_ciCAS2L3_NOUPDATE: 35368c2ecf20Sopenharmony_ci rol.l &0x8,%d0 # get Dest1[31:24] 35378c2ecf20Sopenharmony_ci movs.b %d0,(%a0)+ # Dest1[31:24] -> DEST1 35388c2ecf20Sopenharmony_ci swap %d0 # get Dest1[23:8] 35398c2ecf20Sopenharmony_ci movs.w %d0,(%a0)+ # Dest1[23:8] -> DEST1+0x1 35408c2ecf20Sopenharmony_ci bra.b CAS2L3_NOUPDATE2 35418c2ecf20Sopenharmony_ci bra.b ~+16 35428c2ecf20Sopenharmony_ci 35438c2ecf20Sopenharmony_ciCAS2L3_NOUPDATE2: 35448c2ecf20Sopenharmony_ci rol.l &0x8,%d0 # get Dest1[7:0] 35458c2ecf20Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 35468c2ecf20Sopenharmony_ci movs.b %d0,(%a0) # Update1[7:0] -> DEST1+0x3 35478c2ecf20Sopenharmony_ci bra.b CAS2L3_NOUPDATE3 35488c2ecf20Sopenharmony_ci nop 35498c2ecf20Sopenharmony_ci bra.b ~+16 35508c2ecf20Sopenharmony_ci 35518c2ecf20Sopenharmony_ciCAS2L3_NOUPDATE3: 35528c2ecf20Sopenharmony_ci movc %a4,%buscr # unlock the bus 35538c2ecf20Sopenharmony_ci bra.w cas2l_noupdate_done 35548c2ecf20Sopenharmony_ci nop 35558c2ecf20Sopenharmony_ci nop 35568c2ecf20Sopenharmony_ci nop 35578c2ecf20Sopenharmony_ci bra.b ~+14 35588c2ecf20Sopenharmony_ci 35598c2ecf20Sopenharmony_ciCAS2L3_FILLER: 35608c2ecf20Sopenharmony_ci nop 35618c2ecf20Sopenharmony_ci nop 35628c2ecf20Sopenharmony_ci nop 35638c2ecf20Sopenharmony_ci nop 35648c2ecf20Sopenharmony_ci nop 35658c2ecf20Sopenharmony_ci nop 35668c2ecf20Sopenharmony_ci bra.w CAS2L3_START 35678c2ecf20Sopenharmony_ci 35688c2ecf20Sopenharmony_ci############################################################# 35698c2ecf20Sopenharmony_ci############################################################# 35708c2ecf20Sopenharmony_ci 35718c2ecf20Sopenharmony_cicas2w: 35728c2ecf20Sopenharmony_ci mov.l %a0,%a2 # copy ADDR1 35738c2ecf20Sopenharmony_ci mov.l %a1,%a3 # copy ADDR2 35748c2ecf20Sopenharmony_ci mov.l %a0,%a4 # copy ADDR1 35758c2ecf20Sopenharmony_ci mov.l %a1,%a5 # copy ADDR2 35768c2ecf20Sopenharmony_ci 35778c2ecf20Sopenharmony_ci addq.l &0x1,%a4 # ADDR1+1 35788c2ecf20Sopenharmony_ci addq.l &0x1,%a5 # ADDR2+1 35798c2ecf20Sopenharmony_ci mov.l %a2,%d1 # ADDR1 35808c2ecf20Sopenharmony_ci 35818c2ecf20Sopenharmony_ci# mask interrupt levels 0-6. save old mask value. 35828c2ecf20Sopenharmony_ci mov.w %sr,%d7 # save current SR 35838c2ecf20Sopenharmony_ci ori.w &0x0700,%sr # inhibit interrupts 35848c2ecf20Sopenharmony_ci 35858c2ecf20Sopenharmony_ci# load the SFC and DFC with the appropriate mode. 35868c2ecf20Sopenharmony_ci movc %sfc,%d6 # save old SFC/DFC 35878c2ecf20Sopenharmony_ci movc %d0,%sfc # store new SFC 35888c2ecf20Sopenharmony_ci movc %d0,%dfc # store new DFC 35898c2ecf20Sopenharmony_ci 35908c2ecf20Sopenharmony_ci# pre-load the operand ATC. no page faults should occur because 35918c2ecf20Sopenharmony_ci# _real_lock_page() should have taken care of this. 35928c2ecf20Sopenharmony_ci plpaw (%a2) # load atc for ADDR1 35938c2ecf20Sopenharmony_ci plpaw (%a4) # load atc for ADDR1+1 35948c2ecf20Sopenharmony_ci plpaw (%a3) # load atc for ADDR2 35958c2ecf20Sopenharmony_ci plpaw (%a5) # load atc for ADDR2+1 35968c2ecf20Sopenharmony_ci 35978c2ecf20Sopenharmony_ci# push the operand cache lines from the cache if they exist. 35988c2ecf20Sopenharmony_ci cpushl %dc,(%a2) # push line for ADDR1 35998c2ecf20Sopenharmony_ci cpushl %dc,(%a4) # push line for ADDR1+1 36008c2ecf20Sopenharmony_ci cpushl %dc,(%a3) # push line for ADDR2 36018c2ecf20Sopenharmony_ci cpushl %dc,(%a5) # push line for ADDR2+1 36028c2ecf20Sopenharmony_ci 36038c2ecf20Sopenharmony_ci mov.l %d1,%a2 # ADDR1 36048c2ecf20Sopenharmony_ci addq.l &0x3,%d1 36058c2ecf20Sopenharmony_ci mov.l %d1,%a4 # ADDR1+3 36068c2ecf20Sopenharmony_ci# if ADDR1 was ATC resident before the above "plpaw" and was executed 36078c2ecf20Sopenharmony_ci# and it was the next entry scheduled for replacement and ADDR2 36088c2ecf20Sopenharmony_ci# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1 36098c2ecf20Sopenharmony_ci# entries from the ATC. so, we do a second set of "plpa"s. 36108c2ecf20Sopenharmony_ci plpar (%a2) # load atc for ADDR1 36118c2ecf20Sopenharmony_ci plpar (%a4) # load atc for ADDR1+3 36128c2ecf20Sopenharmony_ci 36138c2ecf20Sopenharmony_ci# load the BUSCR values. 36148c2ecf20Sopenharmony_ci mov.l &0x80000000,%a2 # assert LOCK* buscr value 36158c2ecf20Sopenharmony_ci mov.l &0xa0000000,%a3 # assert LOCKE* buscr value 36168c2ecf20Sopenharmony_ci mov.l &0x00000000,%a4 # buscr unlock value 36178c2ecf20Sopenharmony_ci 36188c2ecf20Sopenharmony_ci# there are two possible mis-aligned cases for word cas. they 36198c2ecf20Sopenharmony_ci# are separated because the final write which asserts LOCKE* must 36208c2ecf20Sopenharmony_ci# be aligned. 36218c2ecf20Sopenharmony_ci mov.l %a0,%d0 # is ADDR1 misaligned? 36228c2ecf20Sopenharmony_ci btst &0x0,%d0 36238c2ecf20Sopenharmony_ci bne.w CAS2W2_ENTER # yes 36248c2ecf20Sopenharmony_ci bra.b CAS2W_ENTER # no 36258c2ecf20Sopenharmony_ci 36268c2ecf20Sopenharmony_ci# 36278c2ecf20Sopenharmony_ci# D0 = dst operand 1 <- 36288c2ecf20Sopenharmony_ci# D1 = dst operand 2 <- 36298c2ecf20Sopenharmony_ci# D2 = cmp operand 1 36308c2ecf20Sopenharmony_ci# D3 = cmp operand 2 36318c2ecf20Sopenharmony_ci# D4 = update oper 1 36328c2ecf20Sopenharmony_ci# D5 = update oper 2 36338c2ecf20Sopenharmony_ci# D6 = old SFC/DFC 36348c2ecf20Sopenharmony_ci# D7 = old SR 36358c2ecf20Sopenharmony_ci# A0 = ADDR1 36368c2ecf20Sopenharmony_ci# A1 = ADDR2 36378c2ecf20Sopenharmony_ci# A2 = bus LOCK* value 36388c2ecf20Sopenharmony_ci# A3 = bus LOCKE* value 36398c2ecf20Sopenharmony_ci# A4 = bus unlock value 36408c2ecf20Sopenharmony_ci# A5 = xxxxxxxx 36418c2ecf20Sopenharmony_ci# 36428c2ecf20Sopenharmony_ci align 0x10 36438c2ecf20Sopenharmony_ciCAS2W_START: 36448c2ecf20Sopenharmony_ci movc %a2,%buscr # assert LOCK* 36458c2ecf20Sopenharmony_ci movs.w (%a1),%d1 # fetch Dest2[15:0] 36468c2ecf20Sopenharmony_ci movs.w (%a0),%d0 # fetch Dest1[15:0] 36478c2ecf20Sopenharmony_ci bra.b CAS2W_CONT2 36488c2ecf20Sopenharmony_ciCAS2W_ENTER: 36498c2ecf20Sopenharmony_ci bra.b ~+16 36508c2ecf20Sopenharmony_ci 36518c2ecf20Sopenharmony_ciCAS2W_CONT2: 36528c2ecf20Sopenharmony_ci cmp.w %d0,%d2 # Dest1 - Compare1 36538c2ecf20Sopenharmony_ci bne.b CAS2W_NOUPDATE 36548c2ecf20Sopenharmony_ci cmp.w %d1,%d3 # Dest2 - Compare2 36558c2ecf20Sopenharmony_ci bne.b CAS2W_NOUPDATE 36568c2ecf20Sopenharmony_ci movs.w %d5,(%a1) # Update2[15:0] -> DEST2 36578c2ecf20Sopenharmony_ci bra.b CAS2W_UPDATE 36588c2ecf20Sopenharmony_ci bra.b ~+16 36598c2ecf20Sopenharmony_ci 36608c2ecf20Sopenharmony_ciCAS2W_UPDATE: 36618c2ecf20Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 36628c2ecf20Sopenharmony_ci movs.w %d4,(%a0) # Update1[15:0] -> DEST1 36638c2ecf20Sopenharmony_ci movc %a4,%buscr # unlock the bus 36648c2ecf20Sopenharmony_ci bra.b cas2w_update_done 36658c2ecf20Sopenharmony_ci bra.b ~+16 36668c2ecf20Sopenharmony_ci 36678c2ecf20Sopenharmony_ciCAS2W_NOUPDATE: 36688c2ecf20Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 36698c2ecf20Sopenharmony_ci movs.w %d0,(%a0) # Dest1[15:0] -> DEST1 36708c2ecf20Sopenharmony_ci movc %a4,%buscr # unlock the bus 36718c2ecf20Sopenharmony_ci bra.b cas2w_noupdate_done 36728c2ecf20Sopenharmony_ci bra.b ~+16 36738c2ecf20Sopenharmony_ci 36748c2ecf20Sopenharmony_ciCAS2W_FILLER: 36758c2ecf20Sopenharmony_ci nop 36768c2ecf20Sopenharmony_ci nop 36778c2ecf20Sopenharmony_ci nop 36788c2ecf20Sopenharmony_ci nop 36798c2ecf20Sopenharmony_ci nop 36808c2ecf20Sopenharmony_ci nop 36818c2ecf20Sopenharmony_ci nop 36828c2ecf20Sopenharmony_ci bra.b CAS2W_START 36838c2ecf20Sopenharmony_ci 36848c2ecf20Sopenharmony_ci#### 36858c2ecf20Sopenharmony_ci 36868c2ecf20Sopenharmony_ci################################################################# 36878c2ecf20Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON # 36888c2ecf20Sopenharmony_ci# ENTERING _isp_cas2(). # 36898c2ecf20Sopenharmony_ci# # 36908c2ecf20Sopenharmony_ci# D0 = destination[15:0] operand 1 # 36918c2ecf20Sopenharmony_ci# D1 = destination[15:0] operand 2 # 36928c2ecf20Sopenharmony_ci# D2 = cmp[15:0] operand 1 # 36938c2ecf20Sopenharmony_ci# D3 = cmp[15:0] operand 2 # 36948c2ecf20Sopenharmony_ci# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required # 36958c2ecf20Sopenharmony_ci# D5 = xxxxxxxx # 36968c2ecf20Sopenharmony_ci# D6 = xxxxxxxx # 36978c2ecf20Sopenharmony_ci# D7 = xxxxxxxx # 36988c2ecf20Sopenharmony_ci# A0 = xxxxxxxx # 36998c2ecf20Sopenharmony_ci# A1 = xxxxxxxx # 37008c2ecf20Sopenharmony_ci# A2 = xxxxxxxx # 37018c2ecf20Sopenharmony_ci# A3 = xxxxxxxx # 37028c2ecf20Sopenharmony_ci# A4 = xxxxxxxx # 37038c2ecf20Sopenharmony_ci# A5 = xxxxxxxx # 37048c2ecf20Sopenharmony_ci# A6 = frame pointer # 37058c2ecf20Sopenharmony_ci# A7 = stack pointer # 37068c2ecf20Sopenharmony_ci################################################################# 37078c2ecf20Sopenharmony_ci 37088c2ecf20Sopenharmony_cicas2w_noupdate_done: 37098c2ecf20Sopenharmony_ci 37108c2ecf20Sopenharmony_ci# restore previous SFC/DFC value. 37118c2ecf20Sopenharmony_ci movc %d6,%sfc # restore old SFC 37128c2ecf20Sopenharmony_ci movc %d6,%dfc # restore old DFC 37138c2ecf20Sopenharmony_ci 37148c2ecf20Sopenharmony_ci# restore previous interrupt mask level. 37158c2ecf20Sopenharmony_ci mov.w %d7,%sr # restore old SR 37168c2ecf20Sopenharmony_ci 37178c2ecf20Sopenharmony_ci sf %d4 # indicate no update was done 37188c2ecf20Sopenharmony_ci bra.l _isp_cas2_finish 37198c2ecf20Sopenharmony_ci 37208c2ecf20Sopenharmony_cicas2w_update_done: 37218c2ecf20Sopenharmony_ci 37228c2ecf20Sopenharmony_ci# restore previous SFC/DFC value. 37238c2ecf20Sopenharmony_ci movc %d6,%sfc # restore old SFC 37248c2ecf20Sopenharmony_ci movc %d6,%dfc # restore old DFC 37258c2ecf20Sopenharmony_ci 37268c2ecf20Sopenharmony_ci# restore previous interrupt mask level. 37278c2ecf20Sopenharmony_ci mov.w %d7,%sr # restore old SR 37288c2ecf20Sopenharmony_ci 37298c2ecf20Sopenharmony_ci st %d4 # indicate update was done 37308c2ecf20Sopenharmony_ci bra.l _isp_cas2_finish 37318c2ecf20Sopenharmony_ci#### 37328c2ecf20Sopenharmony_ci 37338c2ecf20Sopenharmony_ci align 0x10 37348c2ecf20Sopenharmony_ciCAS2W2_START: 37358c2ecf20Sopenharmony_ci movc %a2,%buscr # assert LOCK* 37368c2ecf20Sopenharmony_ci movs.w (%a1),%d1 # fetch Dest2[15:0] 37378c2ecf20Sopenharmony_ci movs.w (%a0),%d0 # fetch Dest1[15:0] 37388c2ecf20Sopenharmony_ci bra.b CAS2W2_CONT2 37398c2ecf20Sopenharmony_ciCAS2W2_ENTER: 37408c2ecf20Sopenharmony_ci bra.b ~+16 37418c2ecf20Sopenharmony_ci 37428c2ecf20Sopenharmony_ciCAS2W2_CONT2: 37438c2ecf20Sopenharmony_ci cmp.w %d0,%d2 # Dest1 - Compare1 37448c2ecf20Sopenharmony_ci bne.b CAS2W2_NOUPDATE 37458c2ecf20Sopenharmony_ci cmp.w %d1,%d3 # Dest2 - Compare2 37468c2ecf20Sopenharmony_ci bne.b CAS2W2_NOUPDATE 37478c2ecf20Sopenharmony_ci movs.w %d5,(%a1) # Update2[15:0] -> DEST2 37488c2ecf20Sopenharmony_ci bra.b CAS2W2_UPDATE 37498c2ecf20Sopenharmony_ci bra.b ~+16 37508c2ecf20Sopenharmony_ci 37518c2ecf20Sopenharmony_ciCAS2W2_UPDATE: 37528c2ecf20Sopenharmony_ci ror.l &0x8,%d4 # get Update1[15:8] 37538c2ecf20Sopenharmony_ci movs.b %d4,(%a0)+ # Update1[15:8] -> DEST1 37548c2ecf20Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 37558c2ecf20Sopenharmony_ci rol.l &0x8,%d4 # get Update1[7:0] 37568c2ecf20Sopenharmony_ci bra.b CAS2W2_UPDATE2 37578c2ecf20Sopenharmony_ci bra.b ~+16 37588c2ecf20Sopenharmony_ci 37598c2ecf20Sopenharmony_ciCAS2W2_UPDATE2: 37608c2ecf20Sopenharmony_ci movs.b %d4,(%a0) # Update1[7:0] -> DEST1+0x1 37618c2ecf20Sopenharmony_ci movc %a4,%buscr # unlock the bus 37628c2ecf20Sopenharmony_ci bra.w cas2w_update_done 37638c2ecf20Sopenharmony_ci nop 37648c2ecf20Sopenharmony_ci bra.b ~+16 37658c2ecf20Sopenharmony_ci 37668c2ecf20Sopenharmony_ciCAS2W2_NOUPDATE: 37678c2ecf20Sopenharmony_ci ror.l &0x8,%d0 # get Dest1[15:8] 37688c2ecf20Sopenharmony_ci movs.b %d0,(%a0)+ # Dest1[15:8] -> DEST1 37698c2ecf20Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 37708c2ecf20Sopenharmony_ci rol.l &0x8,%d0 # get Dest1[7:0] 37718c2ecf20Sopenharmony_ci bra.b CAS2W2_NOUPDATE2 37728c2ecf20Sopenharmony_ci bra.b ~+16 37738c2ecf20Sopenharmony_ci 37748c2ecf20Sopenharmony_ciCAS2W2_NOUPDATE2: 37758c2ecf20Sopenharmony_ci movs.b %d0,(%a0) # Dest1[7:0] -> DEST1+0x1 37768c2ecf20Sopenharmony_ci movc %a4,%buscr # unlock the bus 37778c2ecf20Sopenharmony_ci bra.w cas2w_noupdate_done 37788c2ecf20Sopenharmony_ci nop 37798c2ecf20Sopenharmony_ci bra.b ~+16 37808c2ecf20Sopenharmony_ci 37818c2ecf20Sopenharmony_ciCAS2W2_FILLER: 37828c2ecf20Sopenharmony_ci nop 37838c2ecf20Sopenharmony_ci nop 37848c2ecf20Sopenharmony_ci nop 37858c2ecf20Sopenharmony_ci nop 37868c2ecf20Sopenharmony_ci nop 37878c2ecf20Sopenharmony_ci nop 37888c2ecf20Sopenharmony_ci nop 37898c2ecf20Sopenharmony_ci bra.b CAS2W2_START 37908c2ecf20Sopenharmony_ci 37918c2ecf20Sopenharmony_ci# ###### ## ###### 37928c2ecf20Sopenharmony_ci# # # # # 37938c2ecf20Sopenharmony_ci# # ###### ###### 37948c2ecf20Sopenharmony_ci# # # # # 37958c2ecf20Sopenharmony_ci# ###### # # ###### 37968c2ecf20Sopenharmony_ci 37978c2ecf20Sopenharmony_ci######################################################################### 37988c2ecf20Sopenharmony_ci# XDEF **************************************************************** # 37998c2ecf20Sopenharmony_ci# _isp_cas(): "core" emulation code for the cas instruction # 38008c2ecf20Sopenharmony_ci# # 38018c2ecf20Sopenharmony_ci# XREF **************************************************************** # 38028c2ecf20Sopenharmony_ci# _isp_cas_finish() - only exit point for this emulation code; # 38038c2ecf20Sopenharmony_ci# do clean-up # 38048c2ecf20Sopenharmony_ci# # 38058c2ecf20Sopenharmony_ci# INPUT *************************************************************** # 38068c2ecf20Sopenharmony_ci# *see entry chart below* # 38078c2ecf20Sopenharmony_ci# # 38088c2ecf20Sopenharmony_ci# OUTPUT ************************************************************** # 38098c2ecf20Sopenharmony_ci# *see exit chart below* # 38108c2ecf20Sopenharmony_ci# # 38118c2ecf20Sopenharmony_ci# ALGORITHM *********************************************************** # 38128c2ecf20Sopenharmony_ci# (1) Make several copies of the effective address. # 38138c2ecf20Sopenharmony_ci# (2) Save current SR; Then mask off all maskable interrupts. # 38148c2ecf20Sopenharmony_ci# (3) Save current DFC/SFC (ASSUMED TO BE EQUAL!!!); Then set # 38158c2ecf20Sopenharmony_ci# SFC/DFC according to whether exception occurred in user or # 38168c2ecf20Sopenharmony_ci# supervisor mode. # 38178c2ecf20Sopenharmony_ci# (4) Use "plpaw" instruction to pre-load ATC with effective # 38188c2ecf20Sopenharmony_ci# address page(s). THIS SHOULD NOT FAULT!!! The relevant # 38198c2ecf20Sopenharmony_ci# page(s) should have been made resident prior to entering # 38208c2ecf20Sopenharmony_ci# this routine. # 38218c2ecf20Sopenharmony_ci# (5) Push the operand lines from the cache w/ "cpushl". # 38228c2ecf20Sopenharmony_ci# In the 68040, this was done within the locked region. In # 38238c2ecf20Sopenharmony_ci# the 68060, it is done outside of the locked region. # 38248c2ecf20Sopenharmony_ci# (6) Pre-fetch the core emulation instructions by executing one # 38258c2ecf20Sopenharmony_ci# branch within each physical line (16 bytes) of the code # 38268c2ecf20Sopenharmony_ci# before actually executing the code. # 38278c2ecf20Sopenharmony_ci# (7) Load the BUSCR with the bus lock value. # 38288c2ecf20Sopenharmony_ci# (8) Fetch the source operand. # 38298c2ecf20Sopenharmony_ci# (9) Do the compare. If equal, go to step (12). # 38308c2ecf20Sopenharmony_ci# (10)Unequal. No update occurs. But, we do write the DST op back # 38318c2ecf20Sopenharmony_ci# to itself (as w/ the '040) so we can gracefully unlock # 38328c2ecf20Sopenharmony_ci# the bus (and assert LOCKE*) using BUSCR and the final move. # 38338c2ecf20Sopenharmony_ci# (11)Exit. # 38348c2ecf20Sopenharmony_ci# (12)Write update operand to the DST location. Use BUSCR to # 38358c2ecf20Sopenharmony_ci# assert LOCKE* for the final write operation. # 38368c2ecf20Sopenharmony_ci# (13)Exit. # 38378c2ecf20Sopenharmony_ci# # 38388c2ecf20Sopenharmony_ci# The algorithm is actually implemented slightly differently # 38398c2ecf20Sopenharmony_ci# depending on the size of the operation and the misalignment of the # 38408c2ecf20Sopenharmony_ci# operand. A misaligned operand must be written in aligned chunks or # 38418c2ecf20Sopenharmony_ci# else the BUSCR register control gets confused. # 38428c2ecf20Sopenharmony_ci# # 38438c2ecf20Sopenharmony_ci######################################################################### 38448c2ecf20Sopenharmony_ci 38458c2ecf20Sopenharmony_ci######################################################### 38468c2ecf20Sopenharmony_ci# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON # 38478c2ecf20Sopenharmony_ci# ENTERING _isp_cas(). # 38488c2ecf20Sopenharmony_ci# # 38498c2ecf20Sopenharmony_ci# D0 = xxxxxxxx # 38508c2ecf20Sopenharmony_ci# D1 = xxxxxxxx # 38518c2ecf20Sopenharmony_ci# D2 = update operand # 38528c2ecf20Sopenharmony_ci# D3 = xxxxxxxx # 38538c2ecf20Sopenharmony_ci# D4 = compare operand # 38548c2ecf20Sopenharmony_ci# D5 = xxxxxxxx # 38558c2ecf20Sopenharmony_ci# D6 = supervisor ('xxxxxxff) or user mode ('xxxxxx00) # 38568c2ecf20Sopenharmony_ci# D7 = longword ('xxxxxxff) or word size ('xxxxxx00) # 38578c2ecf20Sopenharmony_ci# A0 = ADDR # 38588c2ecf20Sopenharmony_ci# A1 = xxxxxxxx # 38598c2ecf20Sopenharmony_ci# A2 = xxxxxxxx # 38608c2ecf20Sopenharmony_ci# A3 = xxxxxxxx # 38618c2ecf20Sopenharmony_ci# A4 = xxxxxxxx # 38628c2ecf20Sopenharmony_ci# A5 = xxxxxxxx # 38638c2ecf20Sopenharmony_ci# A6 = frame pointer # 38648c2ecf20Sopenharmony_ci# A7 = stack pointer # 38658c2ecf20Sopenharmony_ci######################################################### 38668c2ecf20Sopenharmony_ci 38678c2ecf20Sopenharmony_ci global _isp_cas 38688c2ecf20Sopenharmony_ci_isp_cas: 38698c2ecf20Sopenharmony_ci tst.b %d6 # user or supervisor mode? 38708c2ecf20Sopenharmony_ci bne.b cas_super # supervisor 38718c2ecf20Sopenharmony_cicas_user: 38728c2ecf20Sopenharmony_ci movq.l &0x1,%d0 # load user data fc 38738c2ecf20Sopenharmony_ci bra.b cas_cont 38748c2ecf20Sopenharmony_cicas_super: 38758c2ecf20Sopenharmony_ci movq.l &0x5,%d0 # load supervisor data fc 38768c2ecf20Sopenharmony_ci 38778c2ecf20Sopenharmony_cicas_cont: 38788c2ecf20Sopenharmony_ci tst.b %d7 # word or longword? 38798c2ecf20Sopenharmony_ci bne.w casl # longword 38808c2ecf20Sopenharmony_ci 38818c2ecf20Sopenharmony_ci#### 38828c2ecf20Sopenharmony_cicasw: 38838c2ecf20Sopenharmony_ci mov.l %a0,%a1 # make copy for plpaw1 38848c2ecf20Sopenharmony_ci mov.l %a0,%a2 # make copy for plpaw2 38858c2ecf20Sopenharmony_ci addq.l &0x1,%a2 # plpaw2 points to end of word 38868c2ecf20Sopenharmony_ci 38878c2ecf20Sopenharmony_ci mov.l %d2,%d3 # d3 = update[7:0] 38888c2ecf20Sopenharmony_ci lsr.w &0x8,%d2 # d2 = update[15:8] 38898c2ecf20Sopenharmony_ci 38908c2ecf20Sopenharmony_ci# mask interrupt levels 0-6. save old mask value. 38918c2ecf20Sopenharmony_ci mov.w %sr,%d7 # save current SR 38928c2ecf20Sopenharmony_ci ori.w &0x0700,%sr # inhibit interrupts 38938c2ecf20Sopenharmony_ci 38948c2ecf20Sopenharmony_ci# load the SFC and DFC with the appropriate mode. 38958c2ecf20Sopenharmony_ci movc %sfc,%d6 # save old SFC/DFC 38968c2ecf20Sopenharmony_ci movc %d0,%sfc # load new sfc 38978c2ecf20Sopenharmony_ci movc %d0,%dfc # load new dfc 38988c2ecf20Sopenharmony_ci 38998c2ecf20Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because 39008c2ecf20Sopenharmony_ci# _real_lock_page() should have taken care of this. 39018c2ecf20Sopenharmony_ci plpaw (%a1) # load atc for ADDR 39028c2ecf20Sopenharmony_ci plpaw (%a2) # load atc for ADDR+1 39038c2ecf20Sopenharmony_ci 39048c2ecf20Sopenharmony_ci# push the operand lines from the cache if they exist. 39058c2ecf20Sopenharmony_ci cpushl %dc,(%a1) # push dirty data 39068c2ecf20Sopenharmony_ci cpushl %dc,(%a2) # push dirty data 39078c2ecf20Sopenharmony_ci 39088c2ecf20Sopenharmony_ci# load the BUSCR values. 39098c2ecf20Sopenharmony_ci mov.l &0x80000000,%a1 # assert LOCK* buscr value 39108c2ecf20Sopenharmony_ci mov.l &0xa0000000,%a2 # assert LOCKE* buscr value 39118c2ecf20Sopenharmony_ci mov.l &0x00000000,%a3 # buscr unlock value 39128c2ecf20Sopenharmony_ci 39138c2ecf20Sopenharmony_ci# pre-load the instruction cache for the following algorithm. 39148c2ecf20Sopenharmony_ci# this will minimize the number of cycles that LOCK* will be asserted. 39158c2ecf20Sopenharmony_ci bra.b CASW_ENTER # start pre-loading icache 39168c2ecf20Sopenharmony_ci 39178c2ecf20Sopenharmony_ci# 39188c2ecf20Sopenharmony_ci# D0 = dst operand <- 39198c2ecf20Sopenharmony_ci# D1 = update[15:8] operand 39208c2ecf20Sopenharmony_ci# D2 = update[7:0] operand 39218c2ecf20Sopenharmony_ci# D3 = xxxxxxxx 39228c2ecf20Sopenharmony_ci# D4 = compare[15:0] operand 39238c2ecf20Sopenharmony_ci# D5 = xxxxxxxx 39248c2ecf20Sopenharmony_ci# D6 = old SFC/DFC 39258c2ecf20Sopenharmony_ci# D7 = old SR 39268c2ecf20Sopenharmony_ci# A0 = ADDR 39278c2ecf20Sopenharmony_ci# A1 = bus LOCK* value 39288c2ecf20Sopenharmony_ci# A2 = bus LOCKE* value 39298c2ecf20Sopenharmony_ci# A3 = bus unlock value 39308c2ecf20Sopenharmony_ci# A4 = xxxxxxxx 39318c2ecf20Sopenharmony_ci# A5 = xxxxxxxx 39328c2ecf20Sopenharmony_ci# 39338c2ecf20Sopenharmony_ci align 0x10 39348c2ecf20Sopenharmony_ciCASW_START: 39358c2ecf20Sopenharmony_ci movc %a1,%buscr # assert LOCK* 39368c2ecf20Sopenharmony_ci movs.w (%a0),%d0 # fetch Dest[15:0] 39378c2ecf20Sopenharmony_ci cmp.w %d0,%d4 # Dest - Compare 39388c2ecf20Sopenharmony_ci bne.b CASW_NOUPDATE 39398c2ecf20Sopenharmony_ci bra.b CASW_UPDATE 39408c2ecf20Sopenharmony_ciCASW_ENTER: 39418c2ecf20Sopenharmony_ci bra.b ~+16 39428c2ecf20Sopenharmony_ci 39438c2ecf20Sopenharmony_ciCASW_UPDATE: 39448c2ecf20Sopenharmony_ci movs.b %d2,(%a0)+ # Update[15:8] -> DEST 39458c2ecf20Sopenharmony_ci movc %a2,%buscr # assert LOCKE* 39468c2ecf20Sopenharmony_ci movs.b %d3,(%a0) # Update[7:0] -> DEST+0x1 39478c2ecf20Sopenharmony_ci bra.b CASW_UPDATE2 39488c2ecf20Sopenharmony_ci bra.b ~+16 39498c2ecf20Sopenharmony_ci 39508c2ecf20Sopenharmony_ciCASW_UPDATE2: 39518c2ecf20Sopenharmony_ci movc %a3,%buscr # unlock the bus 39528c2ecf20Sopenharmony_ci bra.b casw_update_done 39538c2ecf20Sopenharmony_ci nop 39548c2ecf20Sopenharmony_ci nop 39558c2ecf20Sopenharmony_ci nop 39568c2ecf20Sopenharmony_ci nop 39578c2ecf20Sopenharmony_ci bra.b ~+16 39588c2ecf20Sopenharmony_ci 39598c2ecf20Sopenharmony_ciCASW_NOUPDATE: 39608c2ecf20Sopenharmony_ci ror.l &0x8,%d0 # get Dest[15:8] 39618c2ecf20Sopenharmony_ci movs.b %d0,(%a0)+ # Dest[15:8] -> DEST 39628c2ecf20Sopenharmony_ci movc %a2,%buscr # assert LOCKE* 39638c2ecf20Sopenharmony_ci rol.l &0x8,%d0 # get Dest[7:0] 39648c2ecf20Sopenharmony_ci bra.b CASW_NOUPDATE2 39658c2ecf20Sopenharmony_ci bra.b ~+16 39668c2ecf20Sopenharmony_ci 39678c2ecf20Sopenharmony_ciCASW_NOUPDATE2: 39688c2ecf20Sopenharmony_ci movs.b %d0,(%a0) # Dest[7:0] -> DEST+0x1 39698c2ecf20Sopenharmony_ci movc %a3,%buscr # unlock the bus 39708c2ecf20Sopenharmony_ci bra.b casw_noupdate_done 39718c2ecf20Sopenharmony_ci nop 39728c2ecf20Sopenharmony_ci nop 39738c2ecf20Sopenharmony_ci bra.b ~+16 39748c2ecf20Sopenharmony_ci 39758c2ecf20Sopenharmony_ciCASW_FILLER: 39768c2ecf20Sopenharmony_ci nop 39778c2ecf20Sopenharmony_ci nop 39788c2ecf20Sopenharmony_ci nop 39798c2ecf20Sopenharmony_ci nop 39808c2ecf20Sopenharmony_ci nop 39818c2ecf20Sopenharmony_ci nop 39828c2ecf20Sopenharmony_ci nop 39838c2ecf20Sopenharmony_ci bra.b CASW_START 39848c2ecf20Sopenharmony_ci 39858c2ecf20Sopenharmony_ci################################################################# 39868c2ecf20Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON # 39878c2ecf20Sopenharmony_ci# CALLING _isp_cas_finish(). # 39888c2ecf20Sopenharmony_ci# # 39898c2ecf20Sopenharmony_ci# D0 = destination[15:0] operand # 39908c2ecf20Sopenharmony_ci# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required # 39918c2ecf20Sopenharmony_ci# D2 = xxxxxxxx # 39928c2ecf20Sopenharmony_ci# D3 = xxxxxxxx # 39938c2ecf20Sopenharmony_ci# D4 = compare[15:0] operand # 39948c2ecf20Sopenharmony_ci# D5 = xxxxxxxx # 39958c2ecf20Sopenharmony_ci# D6 = xxxxxxxx # 39968c2ecf20Sopenharmony_ci# D7 = xxxxxxxx # 39978c2ecf20Sopenharmony_ci# A0 = xxxxxxxx # 39988c2ecf20Sopenharmony_ci# A1 = xxxxxxxx # 39998c2ecf20Sopenharmony_ci# A2 = xxxxxxxx # 40008c2ecf20Sopenharmony_ci# A3 = xxxxxxxx # 40018c2ecf20Sopenharmony_ci# A4 = xxxxxxxx # 40028c2ecf20Sopenharmony_ci# A5 = xxxxxxxx # 40038c2ecf20Sopenharmony_ci# A6 = frame pointer # 40048c2ecf20Sopenharmony_ci# A7 = stack pointer # 40058c2ecf20Sopenharmony_ci################################################################# 40068c2ecf20Sopenharmony_ci 40078c2ecf20Sopenharmony_cicasw_noupdate_done: 40088c2ecf20Sopenharmony_ci 40098c2ecf20Sopenharmony_ci# restore previous SFC/DFC value. 40108c2ecf20Sopenharmony_ci movc %d6,%sfc # restore old SFC 40118c2ecf20Sopenharmony_ci movc %d6,%dfc # restore old DFC 40128c2ecf20Sopenharmony_ci 40138c2ecf20Sopenharmony_ci# restore previous interrupt mask level. 40148c2ecf20Sopenharmony_ci mov.w %d7,%sr # restore old SR 40158c2ecf20Sopenharmony_ci 40168c2ecf20Sopenharmony_ci sf %d1 # indicate no update was done 40178c2ecf20Sopenharmony_ci bra.l _isp_cas_finish 40188c2ecf20Sopenharmony_ci 40198c2ecf20Sopenharmony_cicasw_update_done: 40208c2ecf20Sopenharmony_ci 40218c2ecf20Sopenharmony_ci# restore previous SFC/DFC value. 40228c2ecf20Sopenharmony_ci movc %d6,%sfc # restore old SFC 40238c2ecf20Sopenharmony_ci movc %d6,%dfc # restore old DFC 40248c2ecf20Sopenharmony_ci 40258c2ecf20Sopenharmony_ci# restore previous interrupt mask level. 40268c2ecf20Sopenharmony_ci mov.w %d7,%sr # restore old SR 40278c2ecf20Sopenharmony_ci 40288c2ecf20Sopenharmony_ci st %d1 # indicate update was done 40298c2ecf20Sopenharmony_ci bra.l _isp_cas_finish 40308c2ecf20Sopenharmony_ci 40318c2ecf20Sopenharmony_ci################ 40328c2ecf20Sopenharmony_ci 40338c2ecf20Sopenharmony_ci# there are two possible mis-aligned cases for longword cas. they 40348c2ecf20Sopenharmony_ci# are separated because the final write which asserts LOCKE* must 40358c2ecf20Sopenharmony_ci# be an aligned write. 40368c2ecf20Sopenharmony_cicasl: 40378c2ecf20Sopenharmony_ci mov.l %a0,%a1 # make copy for plpaw1 40388c2ecf20Sopenharmony_ci mov.l %a0,%a2 # make copy for plpaw2 40398c2ecf20Sopenharmony_ci addq.l &0x3,%a2 # plpaw2 points to end of longword 40408c2ecf20Sopenharmony_ci 40418c2ecf20Sopenharmony_ci mov.l %a0,%d1 # byte or word misaligned? 40428c2ecf20Sopenharmony_ci btst &0x0,%d1 40438c2ecf20Sopenharmony_ci bne.w casl2 # byte misaligned 40448c2ecf20Sopenharmony_ci 40458c2ecf20Sopenharmony_ci mov.l %d2,%d3 # d3 = update[15:0] 40468c2ecf20Sopenharmony_ci swap %d2 # d2 = update[31:16] 40478c2ecf20Sopenharmony_ci 40488c2ecf20Sopenharmony_ci# mask interrupts levels 0-6. save old mask value. 40498c2ecf20Sopenharmony_ci mov.w %sr,%d7 # save current SR 40508c2ecf20Sopenharmony_ci ori.w &0x0700,%sr # inhibit interrupts 40518c2ecf20Sopenharmony_ci 40528c2ecf20Sopenharmony_ci# load the SFC and DFC with the appropriate mode. 40538c2ecf20Sopenharmony_ci movc %sfc,%d6 # save old SFC/DFC 40548c2ecf20Sopenharmony_ci movc %d0,%sfc # load new sfc 40558c2ecf20Sopenharmony_ci movc %d0,%dfc # load new dfc 40568c2ecf20Sopenharmony_ci 40578c2ecf20Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because 40588c2ecf20Sopenharmony_ci# _real_lock_page() should have taken care of this. 40598c2ecf20Sopenharmony_ci plpaw (%a1) # load atc for ADDR 40608c2ecf20Sopenharmony_ci plpaw (%a2) # load atc for ADDR+3 40618c2ecf20Sopenharmony_ci 40628c2ecf20Sopenharmony_ci# push the operand lines from the cache if they exist. 40638c2ecf20Sopenharmony_ci cpushl %dc,(%a1) # push dirty data 40648c2ecf20Sopenharmony_ci cpushl %dc,(%a2) # push dirty data 40658c2ecf20Sopenharmony_ci 40668c2ecf20Sopenharmony_ci# load the BUSCR values. 40678c2ecf20Sopenharmony_ci mov.l &0x80000000,%a1 # assert LOCK* buscr value 40688c2ecf20Sopenharmony_ci mov.l &0xa0000000,%a2 # assert LOCKE* buscr value 40698c2ecf20Sopenharmony_ci mov.l &0x00000000,%a3 # buscr unlock value 40708c2ecf20Sopenharmony_ci 40718c2ecf20Sopenharmony_ci bra.b CASL_ENTER # start pre-loading icache 40728c2ecf20Sopenharmony_ci 40738c2ecf20Sopenharmony_ci# 40748c2ecf20Sopenharmony_ci# D0 = dst operand <- 40758c2ecf20Sopenharmony_ci# D1 = xxxxxxxx 40768c2ecf20Sopenharmony_ci# D2 = update[31:16] operand 40778c2ecf20Sopenharmony_ci# D3 = update[15:0] operand 40788c2ecf20Sopenharmony_ci# D4 = compare[31:0] operand 40798c2ecf20Sopenharmony_ci# D5 = xxxxxxxx 40808c2ecf20Sopenharmony_ci# D6 = old SFC/DFC 40818c2ecf20Sopenharmony_ci# D7 = old SR 40828c2ecf20Sopenharmony_ci# A0 = ADDR 40838c2ecf20Sopenharmony_ci# A1 = bus LOCK* value 40848c2ecf20Sopenharmony_ci# A2 = bus LOCKE* value 40858c2ecf20Sopenharmony_ci# A3 = bus unlock value 40868c2ecf20Sopenharmony_ci# A4 = xxxxxxxx 40878c2ecf20Sopenharmony_ci# A5 = xxxxxxxx 40888c2ecf20Sopenharmony_ci# 40898c2ecf20Sopenharmony_ci align 0x10 40908c2ecf20Sopenharmony_ciCASL_START: 40918c2ecf20Sopenharmony_ci movc %a1,%buscr # assert LOCK* 40928c2ecf20Sopenharmony_ci movs.l (%a0),%d0 # fetch Dest[31:0] 40938c2ecf20Sopenharmony_ci cmp.l %d0,%d4 # Dest - Compare 40948c2ecf20Sopenharmony_ci bne.b CASL_NOUPDATE 40958c2ecf20Sopenharmony_ci bra.b CASL_UPDATE 40968c2ecf20Sopenharmony_ciCASL_ENTER: 40978c2ecf20Sopenharmony_ci bra.b ~+16 40988c2ecf20Sopenharmony_ci 40998c2ecf20Sopenharmony_ciCASL_UPDATE: 41008c2ecf20Sopenharmony_ci movs.w %d2,(%a0)+ # Update[31:16] -> DEST 41018c2ecf20Sopenharmony_ci movc %a2,%buscr # assert LOCKE* 41028c2ecf20Sopenharmony_ci movs.w %d3,(%a0) # Update[15:0] -> DEST+0x2 41038c2ecf20Sopenharmony_ci bra.b CASL_UPDATE2 41048c2ecf20Sopenharmony_ci bra.b ~+16 41058c2ecf20Sopenharmony_ci 41068c2ecf20Sopenharmony_ciCASL_UPDATE2: 41078c2ecf20Sopenharmony_ci movc %a3,%buscr # unlock the bus 41088c2ecf20Sopenharmony_ci bra.b casl_update_done 41098c2ecf20Sopenharmony_ci nop 41108c2ecf20Sopenharmony_ci nop 41118c2ecf20Sopenharmony_ci nop 41128c2ecf20Sopenharmony_ci nop 41138c2ecf20Sopenharmony_ci bra.b ~+16 41148c2ecf20Sopenharmony_ci 41158c2ecf20Sopenharmony_ciCASL_NOUPDATE: 41168c2ecf20Sopenharmony_ci swap %d0 # get Dest[31:16] 41178c2ecf20Sopenharmony_ci movs.w %d0,(%a0)+ # Dest[31:16] -> DEST 41188c2ecf20Sopenharmony_ci swap %d0 # get Dest[15:0] 41198c2ecf20Sopenharmony_ci movc %a2,%buscr # assert LOCKE* 41208c2ecf20Sopenharmony_ci bra.b CASL_NOUPDATE2 41218c2ecf20Sopenharmony_ci bra.b ~+16 41228c2ecf20Sopenharmony_ci 41238c2ecf20Sopenharmony_ciCASL_NOUPDATE2: 41248c2ecf20Sopenharmony_ci movs.w %d0,(%a0) # Dest[15:0] -> DEST+0x2 41258c2ecf20Sopenharmony_ci movc %a3,%buscr # unlock the bus 41268c2ecf20Sopenharmony_ci bra.b casl_noupdate_done 41278c2ecf20Sopenharmony_ci nop 41288c2ecf20Sopenharmony_ci nop 41298c2ecf20Sopenharmony_ci bra.b ~+16 41308c2ecf20Sopenharmony_ci 41318c2ecf20Sopenharmony_ciCASL_FILLER: 41328c2ecf20Sopenharmony_ci nop 41338c2ecf20Sopenharmony_ci nop 41348c2ecf20Sopenharmony_ci nop 41358c2ecf20Sopenharmony_ci nop 41368c2ecf20Sopenharmony_ci nop 41378c2ecf20Sopenharmony_ci nop 41388c2ecf20Sopenharmony_ci nop 41398c2ecf20Sopenharmony_ci bra.b CASL_START 41408c2ecf20Sopenharmony_ci 41418c2ecf20Sopenharmony_ci################################################################# 41428c2ecf20Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON # 41438c2ecf20Sopenharmony_ci# CALLING _isp_cas_finish(). # 41448c2ecf20Sopenharmony_ci# # 41458c2ecf20Sopenharmony_ci# D0 = destination[31:0] operand # 41468c2ecf20Sopenharmony_ci# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required # 41478c2ecf20Sopenharmony_ci# D2 = xxxxxxxx # 41488c2ecf20Sopenharmony_ci# D3 = xxxxxxxx # 41498c2ecf20Sopenharmony_ci# D4 = compare[31:0] operand # 41508c2ecf20Sopenharmony_ci# D5 = xxxxxxxx # 41518c2ecf20Sopenharmony_ci# D6 = xxxxxxxx # 41528c2ecf20Sopenharmony_ci# D7 = xxxxxxxx # 41538c2ecf20Sopenharmony_ci# A0 = xxxxxxxx # 41548c2ecf20Sopenharmony_ci# A1 = xxxxxxxx # 41558c2ecf20Sopenharmony_ci# A2 = xxxxxxxx # 41568c2ecf20Sopenharmony_ci# A3 = xxxxxxxx # 41578c2ecf20Sopenharmony_ci# A4 = xxxxxxxx # 41588c2ecf20Sopenharmony_ci# A5 = xxxxxxxx # 41598c2ecf20Sopenharmony_ci# A6 = frame pointer # 41608c2ecf20Sopenharmony_ci# A7 = stack pointer # 41618c2ecf20Sopenharmony_ci################################################################# 41628c2ecf20Sopenharmony_ci 41638c2ecf20Sopenharmony_cicasl_noupdate_done: 41648c2ecf20Sopenharmony_ci 41658c2ecf20Sopenharmony_ci# restore previous SFC/DFC value. 41668c2ecf20Sopenharmony_ci movc %d6,%sfc # restore old SFC 41678c2ecf20Sopenharmony_ci movc %d6,%dfc # restore old DFC 41688c2ecf20Sopenharmony_ci 41698c2ecf20Sopenharmony_ci# restore previous interrupt mask level. 41708c2ecf20Sopenharmony_ci mov.w %d7,%sr # restore old SR 41718c2ecf20Sopenharmony_ci 41728c2ecf20Sopenharmony_ci sf %d1 # indicate no update was done 41738c2ecf20Sopenharmony_ci bra.l _isp_cas_finish 41748c2ecf20Sopenharmony_ci 41758c2ecf20Sopenharmony_cicasl_update_done: 41768c2ecf20Sopenharmony_ci 41778c2ecf20Sopenharmony_ci# restore previous SFC/DFC value. 41788c2ecf20Sopenharmony_ci movc %d6,%sfc # restore old SFC 41798c2ecf20Sopenharmony_ci movc %d6,%dfc # restore old DFC 41808c2ecf20Sopenharmony_ci 41818c2ecf20Sopenharmony_ci# restore previous interrupts mask level. 41828c2ecf20Sopenharmony_ci mov.w %d7,%sr # restore old SR 41838c2ecf20Sopenharmony_ci 41848c2ecf20Sopenharmony_ci st %d1 # indicate update was done 41858c2ecf20Sopenharmony_ci bra.l _isp_cas_finish 41868c2ecf20Sopenharmony_ci 41878c2ecf20Sopenharmony_ci####################################### 41888c2ecf20Sopenharmony_cicasl2: 41898c2ecf20Sopenharmony_ci mov.l %d2,%d5 # d5 = Update[7:0] 41908c2ecf20Sopenharmony_ci lsr.l &0x8,%d2 41918c2ecf20Sopenharmony_ci mov.l %d2,%d3 # d3 = Update[23:8] 41928c2ecf20Sopenharmony_ci swap %d2 # d2 = Update[31:24] 41938c2ecf20Sopenharmony_ci 41948c2ecf20Sopenharmony_ci# mask interrupts levels 0-6. save old mask value. 41958c2ecf20Sopenharmony_ci mov.w %sr,%d7 # save current SR 41968c2ecf20Sopenharmony_ci ori.w &0x0700,%sr # inhibit interrupts 41978c2ecf20Sopenharmony_ci 41988c2ecf20Sopenharmony_ci# load the SFC and DFC with the appropriate mode. 41998c2ecf20Sopenharmony_ci movc %sfc,%d6 # save old SFC/DFC 42008c2ecf20Sopenharmony_ci movc %d0,%sfc # load new sfc 42018c2ecf20Sopenharmony_ci movc %d0,%dfc # load new dfc 42028c2ecf20Sopenharmony_ci 42038c2ecf20Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because 42048c2ecf20Sopenharmony_ci# _real_lock_page() should have taken care of this already. 42058c2ecf20Sopenharmony_ci plpaw (%a1) # load atc for ADDR 42068c2ecf20Sopenharmony_ci plpaw (%a2) # load atc for ADDR+3 42078c2ecf20Sopenharmony_ci 42088c2ecf20Sopenharmony_ci# puch the operand lines from the cache if they exist. 42098c2ecf20Sopenharmony_ci cpushl %dc,(%a1) # push dirty data 42108c2ecf20Sopenharmony_ci cpushl %dc,(%a2) # push dirty data 42118c2ecf20Sopenharmony_ci 42128c2ecf20Sopenharmony_ci# load the BUSCR values. 42138c2ecf20Sopenharmony_ci mov.l &0x80000000,%a1 # assert LOCK* buscr value 42148c2ecf20Sopenharmony_ci mov.l &0xa0000000,%a2 # assert LOCKE* buscr value 42158c2ecf20Sopenharmony_ci mov.l &0x00000000,%a3 # buscr unlock value 42168c2ecf20Sopenharmony_ci 42178c2ecf20Sopenharmony_ci# pre-load the instruction cache for the following algorithm. 42188c2ecf20Sopenharmony_ci# this will minimize the number of cycles that LOCK* will be asserted. 42198c2ecf20Sopenharmony_ci bra.b CASL2_ENTER # start pre-loading icache 42208c2ecf20Sopenharmony_ci 42218c2ecf20Sopenharmony_ci# 42228c2ecf20Sopenharmony_ci# D0 = dst operand <- 42238c2ecf20Sopenharmony_ci# D1 = xxxxxxxx 42248c2ecf20Sopenharmony_ci# D2 = update[31:24] operand 42258c2ecf20Sopenharmony_ci# D3 = update[23:8] operand 42268c2ecf20Sopenharmony_ci# D4 = compare[31:0] operand 42278c2ecf20Sopenharmony_ci# D5 = update[7:0] operand 42288c2ecf20Sopenharmony_ci# D6 = old SFC/DFC 42298c2ecf20Sopenharmony_ci# D7 = old SR 42308c2ecf20Sopenharmony_ci# A0 = ADDR 42318c2ecf20Sopenharmony_ci# A1 = bus LOCK* value 42328c2ecf20Sopenharmony_ci# A2 = bus LOCKE* value 42338c2ecf20Sopenharmony_ci# A3 = bus unlock value 42348c2ecf20Sopenharmony_ci# A4 = xxxxxxxx 42358c2ecf20Sopenharmony_ci# A5 = xxxxxxxx 42368c2ecf20Sopenharmony_ci# 42378c2ecf20Sopenharmony_ci align 0x10 42388c2ecf20Sopenharmony_ciCASL2_START: 42398c2ecf20Sopenharmony_ci movc %a1,%buscr # assert LOCK* 42408c2ecf20Sopenharmony_ci movs.l (%a0),%d0 # fetch Dest[31:0] 42418c2ecf20Sopenharmony_ci cmp.l %d0,%d4 # Dest - Compare 42428c2ecf20Sopenharmony_ci bne.b CASL2_NOUPDATE 42438c2ecf20Sopenharmony_ci bra.b CASL2_UPDATE 42448c2ecf20Sopenharmony_ciCASL2_ENTER: 42458c2ecf20Sopenharmony_ci bra.b ~+16 42468c2ecf20Sopenharmony_ci 42478c2ecf20Sopenharmony_ciCASL2_UPDATE: 42488c2ecf20Sopenharmony_ci movs.b %d2,(%a0)+ # Update[31:24] -> DEST 42498c2ecf20Sopenharmony_ci movs.w %d3,(%a0)+ # Update[23:8] -> DEST+0x1 42508c2ecf20Sopenharmony_ci movc %a2,%buscr # assert LOCKE* 42518c2ecf20Sopenharmony_ci bra.b CASL2_UPDATE2 42528c2ecf20Sopenharmony_ci bra.b ~+16 42538c2ecf20Sopenharmony_ci 42548c2ecf20Sopenharmony_ciCASL2_UPDATE2: 42558c2ecf20Sopenharmony_ci movs.b %d5,(%a0) # Update[7:0] -> DEST+0x3 42568c2ecf20Sopenharmony_ci movc %a3,%buscr # unlock the bus 42578c2ecf20Sopenharmony_ci bra.w casl_update_done 42588c2ecf20Sopenharmony_ci nop 42598c2ecf20Sopenharmony_ci bra.b ~+16 42608c2ecf20Sopenharmony_ci 42618c2ecf20Sopenharmony_ciCASL2_NOUPDATE: 42628c2ecf20Sopenharmony_ci rol.l &0x8,%d0 # get Dest[31:24] 42638c2ecf20Sopenharmony_ci movs.b %d0,(%a0)+ # Dest[31:24] -> DEST 42648c2ecf20Sopenharmony_ci swap %d0 # get Dest[23:8] 42658c2ecf20Sopenharmony_ci movs.w %d0,(%a0)+ # Dest[23:8] -> DEST+0x1 42668c2ecf20Sopenharmony_ci bra.b CASL2_NOUPDATE2 42678c2ecf20Sopenharmony_ci bra.b ~+16 42688c2ecf20Sopenharmony_ci 42698c2ecf20Sopenharmony_ciCASL2_NOUPDATE2: 42708c2ecf20Sopenharmony_ci rol.l &0x8,%d0 # get Dest[7:0] 42718c2ecf20Sopenharmony_ci movc %a2,%buscr # assert LOCKE* 42728c2ecf20Sopenharmony_ci movs.b %d0,(%a0) # Dest[7:0] -> DEST+0x3 42738c2ecf20Sopenharmony_ci bra.b CASL2_NOUPDATE3 42748c2ecf20Sopenharmony_ci nop 42758c2ecf20Sopenharmony_ci bra.b ~+16 42768c2ecf20Sopenharmony_ci 42778c2ecf20Sopenharmony_ciCASL2_NOUPDATE3: 42788c2ecf20Sopenharmony_ci movc %a3,%buscr # unlock the bus 42798c2ecf20Sopenharmony_ci bra.w casl_noupdate_done 42808c2ecf20Sopenharmony_ci nop 42818c2ecf20Sopenharmony_ci nop 42828c2ecf20Sopenharmony_ci nop 42838c2ecf20Sopenharmony_ci bra.b ~+16 42848c2ecf20Sopenharmony_ci 42858c2ecf20Sopenharmony_ciCASL2_FILLER: 42868c2ecf20Sopenharmony_ci nop 42878c2ecf20Sopenharmony_ci nop 42888c2ecf20Sopenharmony_ci nop 42898c2ecf20Sopenharmony_ci nop 42908c2ecf20Sopenharmony_ci nop 42918c2ecf20Sopenharmony_ci nop 42928c2ecf20Sopenharmony_ci nop 42938c2ecf20Sopenharmony_ci bra.b CASL2_START 42948c2ecf20Sopenharmony_ci 42958c2ecf20Sopenharmony_ci#### 42968c2ecf20Sopenharmony_ci#### 42978c2ecf20Sopenharmony_ci# end label used by _isp_cas_inrange() 42988c2ecf20Sopenharmony_ci global _CASHI 42998c2ecf20Sopenharmony_ci_CASHI: 4300