162306a36Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 262306a36Sopenharmony_ciMOTOROLA MICROPROCESSOR & MEMORY TECHNOLOGY GROUP 362306a36Sopenharmony_ciM68000 Hi-Performance Microprocessor Division 462306a36Sopenharmony_ciM68060 Software Package 562306a36Sopenharmony_ciProduction Release P1.00 -- October 10, 1994 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciM68060 Software Package Copyright © 1993, 1994 Motorola Inc. All rights reserved. 862306a36Sopenharmony_ci 962306a36Sopenharmony_ciTHE SOFTWARE is provided on an "AS IS" basis and without warranty. 1062306a36Sopenharmony_ciTo the maximum extent permitted by applicable law, 1162306a36Sopenharmony_ciMOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, 1262306a36Sopenharmony_ciINCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 1362306a36Sopenharmony_ciand any warranty against infringement with regard to the SOFTWARE 1462306a36Sopenharmony_ci(INCLUDING ANY MODIFIED VERSIONS THEREOF) and any accompanying written materials. 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ciTo the maximum extent permitted by applicable law, 1762306a36Sopenharmony_ciIN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 1862306a36Sopenharmony_ci(INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, 1962306a36Sopenharmony_ciBUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) 2062306a36Sopenharmony_ciARISING OF THE USE OR INABILITY TO USE THE SOFTWARE. 2162306a36Sopenharmony_ciMotorola assumes no responsibility for the maintenance and support of the SOFTWARE. 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ciYou are hereby granted a copyright license to use, modify, and distribute the SOFTWARE 2462306a36Sopenharmony_ciso long as this entire notice is retained without alteration in any modified and/or 2562306a36Sopenharmony_ciredistributed versions, and that such modified versions are clearly identified as such. 2662306a36Sopenharmony_ciNo licenses are granted by implication, estoppel or otherwise under any patents 2762306a36Sopenharmony_cior trademarks of Motorola, Inc. 2862306a36Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2962306a36Sopenharmony_ci# ireal.s: 3062306a36Sopenharmony_ci# This file is appended to the top of the 060ISP package 3162306a36Sopenharmony_ci# and contains the entry points into the package. The user, in 3262306a36Sopenharmony_ci# effect, branches to one of the branch table entries located 3362306a36Sopenharmony_ci# after _060ISP_TABLE. 3462306a36Sopenharmony_ci# Also, subroutine stubs exist in this file (_isp_done for 3562306a36Sopenharmony_ci# example) that are referenced by the ISP package itself in order 3662306a36Sopenharmony_ci# to call a given routine. The stub routine actually performs the 3762306a36Sopenharmony_ci# callout. The ISP code does a "bsr" to the stub routine. This 3862306a36Sopenharmony_ci# extra layer of hierarchy adds a slight performance penalty but 3962306a36Sopenharmony_ci# it makes the ISP code easier to read and more mainatinable. 4062306a36Sopenharmony_ci# 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ciset _off_chk, 0x00 4362306a36Sopenharmony_ciset _off_divbyzero, 0x04 4462306a36Sopenharmony_ciset _off_trace, 0x08 4562306a36Sopenharmony_ciset _off_access, 0x0c 4662306a36Sopenharmony_ciset _off_done, 0x10 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ciset _off_cas, 0x14 4962306a36Sopenharmony_ciset _off_cas2, 0x18 5062306a36Sopenharmony_ciset _off_lock, 0x1c 5162306a36Sopenharmony_ciset _off_unlock, 0x20 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ciset _off_imr, 0x40 5462306a36Sopenharmony_ciset _off_dmr, 0x44 5562306a36Sopenharmony_ciset _off_dmw, 0x48 5662306a36Sopenharmony_ciset _off_irw, 0x4c 5762306a36Sopenharmony_ciset _off_irl, 0x50 5862306a36Sopenharmony_ciset _off_drb, 0x54 5962306a36Sopenharmony_ciset _off_drw, 0x58 6062306a36Sopenharmony_ciset _off_drl, 0x5c 6162306a36Sopenharmony_ciset _off_dwb, 0x60 6262306a36Sopenharmony_ciset _off_dww, 0x64 6362306a36Sopenharmony_ciset _off_dwl, 0x68 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci_060ISP_TABLE: 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci# Here's the table of ENTRY POINTS for those linking the package. 6862306a36Sopenharmony_ci bra.l _isp_unimp 6962306a36Sopenharmony_ci short 0x0000 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci bra.l _isp_cas 7262306a36Sopenharmony_ci short 0x0000 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci bra.l _isp_cas2 7562306a36Sopenharmony_ci short 0x0000 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci bra.l _isp_cas_finish 7862306a36Sopenharmony_ci short 0x0000 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci bra.l _isp_cas2_finish 8162306a36Sopenharmony_ci short 0x0000 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci bra.l _isp_cas_inrange 8462306a36Sopenharmony_ci short 0x0000 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci bra.l _isp_cas_terminate 8762306a36Sopenharmony_ci short 0x0000 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci bra.l _isp_cas_restart 9062306a36Sopenharmony_ci short 0x0000 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci space 64 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci############################################################# 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci global _real_chk 9762306a36Sopenharmony_ci_real_chk: 9862306a36Sopenharmony_ci mov.l %d0,-(%sp) 9962306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_chk,%pc),%d0 10062306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 10162306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 10262306a36Sopenharmony_ci rtd &0x4 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci global _real_divbyzero 10562306a36Sopenharmony_ci_real_divbyzero: 10662306a36Sopenharmony_ci mov.l %d0,-(%sp) 10762306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_divbyzero,%pc),%d0 10862306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 10962306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 11062306a36Sopenharmony_ci rtd &0x4 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci global _real_trace 11362306a36Sopenharmony_ci_real_trace: 11462306a36Sopenharmony_ci mov.l %d0,-(%sp) 11562306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_trace,%pc),%d0 11662306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 11762306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 11862306a36Sopenharmony_ci rtd &0x4 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci global _real_access 12162306a36Sopenharmony_ci_real_access: 12262306a36Sopenharmony_ci mov.l %d0,-(%sp) 12362306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_access,%pc),%d0 12462306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 12562306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 12662306a36Sopenharmony_ci rtd &0x4 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci global _isp_done 12962306a36Sopenharmony_ci_isp_done: 13062306a36Sopenharmony_ci mov.l %d0,-(%sp) 13162306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_done,%pc),%d0 13262306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 13362306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 13462306a36Sopenharmony_ci rtd &0x4 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci####################################### 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci global _real_cas 13962306a36Sopenharmony_ci_real_cas: 14062306a36Sopenharmony_ci mov.l %d0,-(%sp) 14162306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_cas,%pc),%d0 14262306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 14362306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 14462306a36Sopenharmony_ci rtd &0x4 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci global _real_cas2 14762306a36Sopenharmony_ci_real_cas2: 14862306a36Sopenharmony_ci mov.l %d0,-(%sp) 14962306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_cas2,%pc),%d0 15062306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 15162306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 15262306a36Sopenharmony_ci rtd &0x4 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci global _real_lock_page 15562306a36Sopenharmony_ci_real_lock_page: 15662306a36Sopenharmony_ci mov.l %d0,-(%sp) 15762306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_lock,%pc),%d0 15862306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 15962306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 16062306a36Sopenharmony_ci rtd &0x4 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci global _real_unlock_page 16362306a36Sopenharmony_ci_real_unlock_page: 16462306a36Sopenharmony_ci mov.l %d0,-(%sp) 16562306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_unlock,%pc),%d0 16662306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 16762306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 16862306a36Sopenharmony_ci rtd &0x4 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci####################################### 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci global _imem_read 17362306a36Sopenharmony_ci_imem_read: 17462306a36Sopenharmony_ci mov.l %d0,-(%sp) 17562306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_imr,%pc),%d0 17662306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 17762306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 17862306a36Sopenharmony_ci rtd &0x4 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci global _dmem_read 18162306a36Sopenharmony_ci_dmem_read: 18262306a36Sopenharmony_ci mov.l %d0,-(%sp) 18362306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_dmr,%pc),%d0 18462306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 18562306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 18662306a36Sopenharmony_ci rtd &0x4 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci global _dmem_write 18962306a36Sopenharmony_ci_dmem_write: 19062306a36Sopenharmony_ci mov.l %d0,-(%sp) 19162306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_dmw,%pc),%d0 19262306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 19362306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 19462306a36Sopenharmony_ci rtd &0x4 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci global _imem_read_word 19762306a36Sopenharmony_ci_imem_read_word: 19862306a36Sopenharmony_ci mov.l %d0,-(%sp) 19962306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_irw,%pc),%d0 20062306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 20162306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 20262306a36Sopenharmony_ci rtd &0x4 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci global _imem_read_long 20562306a36Sopenharmony_ci_imem_read_long: 20662306a36Sopenharmony_ci mov.l %d0,-(%sp) 20762306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_irl,%pc),%d0 20862306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 20962306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 21062306a36Sopenharmony_ci rtd &0x4 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci global _dmem_read_byte 21362306a36Sopenharmony_ci_dmem_read_byte: 21462306a36Sopenharmony_ci mov.l %d0,-(%sp) 21562306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_drb,%pc),%d0 21662306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 21762306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 21862306a36Sopenharmony_ci rtd &0x4 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci global _dmem_read_word 22162306a36Sopenharmony_ci_dmem_read_word: 22262306a36Sopenharmony_ci mov.l %d0,-(%sp) 22362306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_drw,%pc),%d0 22462306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 22562306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 22662306a36Sopenharmony_ci rtd &0x4 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci global _dmem_read_long 22962306a36Sopenharmony_ci_dmem_read_long: 23062306a36Sopenharmony_ci mov.l %d0,-(%sp) 23162306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_drl,%pc),%d0 23262306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 23362306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 23462306a36Sopenharmony_ci rtd &0x4 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci global _dmem_write_byte 23762306a36Sopenharmony_ci_dmem_write_byte: 23862306a36Sopenharmony_ci mov.l %d0,-(%sp) 23962306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_dwb,%pc),%d0 24062306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 24162306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 24262306a36Sopenharmony_ci rtd &0x4 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci global _dmem_write_word 24562306a36Sopenharmony_ci_dmem_write_word: 24662306a36Sopenharmony_ci mov.l %d0,-(%sp) 24762306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_dww,%pc),%d0 24862306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 24962306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 25062306a36Sopenharmony_ci rtd &0x4 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci global _dmem_write_long 25362306a36Sopenharmony_ci_dmem_write_long: 25462306a36Sopenharmony_ci mov.l %d0,-(%sp) 25562306a36Sopenharmony_ci mov.l (_060ISP_TABLE-0x80+_off_dwl,%pc),%d0 25662306a36Sopenharmony_ci pea.l (_060ISP_TABLE-0x80,%pc,%d0) 25762306a36Sopenharmony_ci mov.l 0x4(%sp),%d0 25862306a36Sopenharmony_ci rtd &0x4 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci# 26162306a36Sopenharmony_ci# This file contains a set of define statements for constants 26262306a36Sopenharmony_ci# in oreder to promote readability within the core code itself. 26362306a36Sopenharmony_ci# 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ciset LOCAL_SIZE, 96 # stack frame size(bytes) 26662306a36Sopenharmony_ciset LV, -LOCAL_SIZE # stack offset 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ciset EXC_ISR, 0x4 # stack status register 26962306a36Sopenharmony_ciset EXC_IPC, 0x6 # stack pc 27062306a36Sopenharmony_ciset EXC_IVOFF, 0xa # stacked vector offset 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ciset EXC_AREGS, LV+64 # offset of all address regs 27362306a36Sopenharmony_ciset EXC_DREGS, LV+32 # offset of all data regs 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ciset EXC_A7, EXC_AREGS+(7*4) # offset of a7 27662306a36Sopenharmony_ciset EXC_A6, EXC_AREGS+(6*4) # offset of a6 27762306a36Sopenharmony_ciset EXC_A5, EXC_AREGS+(5*4) # offset of a5 27862306a36Sopenharmony_ciset EXC_A4, EXC_AREGS+(4*4) # offset of a4 27962306a36Sopenharmony_ciset EXC_A3, EXC_AREGS+(3*4) # offset of a3 28062306a36Sopenharmony_ciset EXC_A2, EXC_AREGS+(2*4) # offset of a2 28162306a36Sopenharmony_ciset EXC_A1, EXC_AREGS+(1*4) # offset of a1 28262306a36Sopenharmony_ciset EXC_A0, EXC_AREGS+(0*4) # offset of a0 28362306a36Sopenharmony_ciset EXC_D7, EXC_DREGS+(7*4) # offset of d7 28462306a36Sopenharmony_ciset EXC_D6, EXC_DREGS+(6*4) # offset of d6 28562306a36Sopenharmony_ciset EXC_D5, EXC_DREGS+(5*4) # offset of d5 28662306a36Sopenharmony_ciset EXC_D4, EXC_DREGS+(4*4) # offset of d4 28762306a36Sopenharmony_ciset EXC_D3, EXC_DREGS+(3*4) # offset of d3 28862306a36Sopenharmony_ciset EXC_D2, EXC_DREGS+(2*4) # offset of d2 28962306a36Sopenharmony_ciset EXC_D1, EXC_DREGS+(1*4) # offset of d1 29062306a36Sopenharmony_ciset EXC_D0, EXC_DREGS+(0*4) # offset of d0 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ciset EXC_TEMP, LV+16 # offset of temp stack space 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ciset EXC_SAVVAL, LV+12 # offset of old areg value 29562306a36Sopenharmony_ciset EXC_SAVREG, LV+11 # offset of old areg index 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ciset SPCOND_FLG, LV+10 # offset of spc condition flg 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ciset EXC_CC, LV+8 # offset of cc register 30062306a36Sopenharmony_ciset EXC_EXTWPTR, LV+4 # offset of current PC 30162306a36Sopenharmony_ciset EXC_EXTWORD, LV+2 # offset of current ext opword 30262306a36Sopenharmony_ciset EXC_OPWORD, LV+0 # offset of current opword 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci########################### 30562306a36Sopenharmony_ci# SPecial CONDition FLaGs # 30662306a36Sopenharmony_ci########################### 30762306a36Sopenharmony_ciset mia7_flg, 0x04 # (a7)+ flag 30862306a36Sopenharmony_ciset mda7_flg, 0x08 # -(a7) flag 30962306a36Sopenharmony_ciset ichk_flg, 0x10 # chk exception flag 31062306a36Sopenharmony_ciset idbyz_flg, 0x20 # divbyzero flag 31162306a36Sopenharmony_ciset restore_flg, 0x40 # restore -(an)+ flag 31262306a36Sopenharmony_ciset immed_flg, 0x80 # immediate data flag 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ciset mia7_bit, 0x2 # (a7)+ bit 31562306a36Sopenharmony_ciset mda7_bit, 0x3 # -(a7) bit 31662306a36Sopenharmony_ciset ichk_bit, 0x4 # chk exception bit 31762306a36Sopenharmony_ciset idbyz_bit, 0x5 # divbyzero bit 31862306a36Sopenharmony_ciset restore_bit, 0x6 # restore -(a7)+ bit 31962306a36Sopenharmony_ciset immed_bit, 0x7 # immediate data bit 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci######### 32262306a36Sopenharmony_ci# Misc. # 32362306a36Sopenharmony_ci######### 32462306a36Sopenharmony_ciset BYTE, 1 # len(byte) == 1 byte 32562306a36Sopenharmony_ciset WORD, 2 # len(word) == 2 bytes 32662306a36Sopenharmony_ciset LONG, 4 # len(longword) == 4 bytes 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci######################################################################### 32962306a36Sopenharmony_ci# XDEF **************************************************************** # 33062306a36Sopenharmony_ci# _isp_unimp(): 060ISP entry point for Unimplemented Instruction # 33162306a36Sopenharmony_ci# # 33262306a36Sopenharmony_ci# This handler should be the first code executed upon taking the # 33362306a36Sopenharmony_ci# "Unimplemented Integer Instruction" exception in an operating # 33462306a36Sopenharmony_ci# system. # 33562306a36Sopenharmony_ci# # 33662306a36Sopenharmony_ci# XREF **************************************************************** # 33762306a36Sopenharmony_ci# _imem_read_{word,long}() - read instruction word/longword # 33862306a36Sopenharmony_ci# _mul64() - emulate 64-bit multiply # 33962306a36Sopenharmony_ci# _div64() - emulate 64-bit divide # 34062306a36Sopenharmony_ci# _moveperipheral() - emulate "movep" # 34162306a36Sopenharmony_ci# _compandset() - emulate misaligned "cas" # 34262306a36Sopenharmony_ci# _compandset2() - emulate "cas2" # 34362306a36Sopenharmony_ci# _chk2_cmp2() - emulate "cmp2" and "chk2" # 34462306a36Sopenharmony_ci# _isp_done() - "callout" for normal final exit # 34562306a36Sopenharmony_ci# _real_trace() - "callout" for Trace exception # 34662306a36Sopenharmony_ci# _real_chk() - "callout" for Chk exception # 34762306a36Sopenharmony_ci# _real_divbyzero() - "callout" for DZ exception # 34862306a36Sopenharmony_ci# _real_access() - "callout" for access error exception # 34962306a36Sopenharmony_ci# # 35062306a36Sopenharmony_ci# INPUT *************************************************************** # 35162306a36Sopenharmony_ci# - The system stack contains the Unimp Int Instr stack frame # 35262306a36Sopenharmony_ci# # 35362306a36Sopenharmony_ci# OUTPUT ************************************************************** # 35462306a36Sopenharmony_ci# If Trace exception: # 35562306a36Sopenharmony_ci# - The system stack changed to contain Trace exc stack frame # 35662306a36Sopenharmony_ci# If Chk exception: # 35762306a36Sopenharmony_ci# - The system stack changed to contain Chk exc stack frame # 35862306a36Sopenharmony_ci# If DZ exception: # 35962306a36Sopenharmony_ci# - The system stack changed to contain DZ exc stack frame # 36062306a36Sopenharmony_ci# If access error exception: # 36162306a36Sopenharmony_ci# - The system stack changed to contain access err exc stk frame # 36262306a36Sopenharmony_ci# Else: # 36362306a36Sopenharmony_ci# - Results saved as appropriate # 36462306a36Sopenharmony_ci# # 36562306a36Sopenharmony_ci# ALGORITHM *********************************************************** # 36662306a36Sopenharmony_ci# This handler fetches the first instruction longword from # 36762306a36Sopenharmony_ci# memory and decodes it to determine which of the unimplemented # 36862306a36Sopenharmony_ci# integer instructions caused this exception. This handler then calls # 36962306a36Sopenharmony_ci# one of _mul64(), _div64(), _moveperipheral(), _compandset(), # 37062306a36Sopenharmony_ci# _compandset2(), or _chk2_cmp2() as appropriate. # 37162306a36Sopenharmony_ci# Some of these instructions, by their nature, may produce other # 37262306a36Sopenharmony_ci# types of exceptions. "div" can produce a divide-by-zero exception, # 37362306a36Sopenharmony_ci# and "chk2" can cause a "Chk" exception. In both cases, the current # 37462306a36Sopenharmony_ci# exception stack frame must be converted to an exception stack frame # 37562306a36Sopenharmony_ci# of the correct exception type and an exit must be made through # 37662306a36Sopenharmony_ci# _real_divbyzero() or _real_chk() as appropriate. In addition, all # 37762306a36Sopenharmony_ci# instructions may be executing while Trace is enabled. If so, then # 37862306a36Sopenharmony_ci# a Trace exception stack frame must be created and an exit made # 37962306a36Sopenharmony_ci# through _real_trace(). # 38062306a36Sopenharmony_ci# Meanwhile, if any read or write to memory using the # 38162306a36Sopenharmony_ci# _mem_{read,write}() "callout"s returns a failing value, then an # 38262306a36Sopenharmony_ci# access error frame must be created and an exit made through # 38362306a36Sopenharmony_ci# _real_access(). # 38462306a36Sopenharmony_ci# If none of these occur, then a normal exit is made through # 38562306a36Sopenharmony_ci# _isp_done(). # 38662306a36Sopenharmony_ci# # 38762306a36Sopenharmony_ci# This handler, upon entry, saves almost all user-visible # 38862306a36Sopenharmony_ci# address and data registers to the stack. Although this may seem to # 38962306a36Sopenharmony_ci# cause excess memory traffic, it was found that due to having to # 39062306a36Sopenharmony_ci# access these register files for things like data retrieval and <ea> # 39162306a36Sopenharmony_ci# calculations, it was more efficient to have them on the stack where # 39262306a36Sopenharmony_ci# they could be accessed by indexing rather than to make subroutine # 39362306a36Sopenharmony_ci# calls to retrieve a register of a particular index. # 39462306a36Sopenharmony_ci# # 39562306a36Sopenharmony_ci######################################################################### 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci global _isp_unimp 39862306a36Sopenharmony_ci_isp_unimp: 39962306a36Sopenharmony_ci link.w %a6,&-LOCAL_SIZE # create room for stack frame 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci movm.l &0x3fff,EXC_DREGS(%a6) # store d0-d7/a0-a5 40262306a36Sopenharmony_ci mov.l (%a6),EXC_A6(%a6) # store a6 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci btst &0x5,EXC_ISR(%a6) # from s or u mode? 40562306a36Sopenharmony_ci bne.b uieh_s # supervisor mode 40662306a36Sopenharmony_ciuieh_u: 40762306a36Sopenharmony_ci mov.l %usp,%a0 # fetch user stack pointer 40862306a36Sopenharmony_ci mov.l %a0,EXC_A7(%a6) # store a7 40962306a36Sopenharmony_ci bra.b uieh_cont 41062306a36Sopenharmony_ciuieh_s: 41162306a36Sopenharmony_ci lea 0xc(%a6),%a0 41262306a36Sopenharmony_ci mov.l %a0,EXC_A7(%a6) # store corrected sp 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci############################################################################### 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ciuieh_cont: 41762306a36Sopenharmony_ci clr.b SPCOND_FLG(%a6) # clear "special case" flag 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci mov.w EXC_ISR(%a6),EXC_CC(%a6) # store cc copy on stack 42062306a36Sopenharmony_ci mov.l EXC_IPC(%a6),EXC_EXTWPTR(%a6) # store extwptr on stack 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci# 42362306a36Sopenharmony_ci# fetch the opword and first extension word pointed to by the stacked pc 42462306a36Sopenharmony_ci# and store them to the stack for now 42562306a36Sopenharmony_ci# 42662306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 42762306a36Sopenharmony_ci addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 42862306a36Sopenharmony_ci bsr.l _imem_read_long # fetch opword & extword 42962306a36Sopenharmony_ci mov.l %d0,EXC_OPWORD(%a6) # store extword on stack 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci######################################################################### 43362306a36Sopenharmony_ci# muls.l 0100 1100 00 |<ea>| 0*** 1100 0000 0*** # 43462306a36Sopenharmony_ci# mulu.l 0100 1100 00 |<ea>| 0*** 0100 0000 0*** # 43562306a36Sopenharmony_ci# # 43662306a36Sopenharmony_ci# divs.l 0100 1100 01 |<ea>| 0*** 1100 0000 0*** # 43762306a36Sopenharmony_ci# divu.l 0100 1100 01 |<ea>| 0*** 0100 0000 0*** # 43862306a36Sopenharmony_ci# # 43962306a36Sopenharmony_ci# movep.w m2r 0000 ***1 00 001*** | <displacement> | # 44062306a36Sopenharmony_ci# movep.l m2r 0000 ***1 01 001*** | <displacement> | # 44162306a36Sopenharmony_ci# movep.w r2m 0000 ***1 10 001*** | <displacement> | # 44262306a36Sopenharmony_ci# movep.l r2m 0000 ***1 11 001*** | <displacement> | # 44362306a36Sopenharmony_ci# # 44462306a36Sopenharmony_ci# cas.w 0000 1100 11 |<ea>| 0000 000* **00 0*** # 44562306a36Sopenharmony_ci# cas.l 0000 1110 11 |<ea>| 0000 000* **00 0*** # 44662306a36Sopenharmony_ci# # 44762306a36Sopenharmony_ci# cas2.w 0000 1100 11 111100 **** 000* **00 0*** # 44862306a36Sopenharmony_ci# **** 000* **00 0*** # 44962306a36Sopenharmony_ci# cas2.l 0000 1110 11 111100 **** 000* **00 0*** # 45062306a36Sopenharmony_ci# **** 000* **00 0*** # 45162306a36Sopenharmony_ci# # 45262306a36Sopenharmony_ci# chk2.b 0000 0000 11 |<ea>| **** 1000 0000 0000 # 45362306a36Sopenharmony_ci# chk2.w 0000 0010 11 |<ea>| **** 1000 0000 0000 # 45462306a36Sopenharmony_ci# chk2.l 0000 0100 11 |<ea>| **** 1000 0000 0000 # 45562306a36Sopenharmony_ci# # 45662306a36Sopenharmony_ci# cmp2.b 0000 0000 11 |<ea>| **** 0000 0000 0000 # 45762306a36Sopenharmony_ci# cmp2.w 0000 0010 11 |<ea>| **** 0000 0000 0000 # 45862306a36Sopenharmony_ci# cmp2.l 0000 0100 11 |<ea>| **** 0000 0000 0000 # 45962306a36Sopenharmony_ci######################################################################### 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci# 46262306a36Sopenharmony_ci# using bit 14 of the operation word, separate into 2 groups: 46362306a36Sopenharmony_ci# (group1) mul64, div64 46462306a36Sopenharmony_ci# (group2) movep, chk2, cmp2, cas2, cas 46562306a36Sopenharmony_ci# 46662306a36Sopenharmony_ci btst &0x1e,%d0 # group1 or group2 46762306a36Sopenharmony_ci beq.b uieh_group2 # go handle group2 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci# 47062306a36Sopenharmony_ci# now, w/ group1, make mul64's decode the fastest since it will 47162306a36Sopenharmony_ci# most likely be used the most. 47262306a36Sopenharmony_ci# 47362306a36Sopenharmony_ciuieh_group1: 47462306a36Sopenharmony_ci btst &0x16,%d0 # test for div64 47562306a36Sopenharmony_ci bne.b uieh_div64 # go handle div64 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ciuieh_mul64: 47862306a36Sopenharmony_ci# mul64() may use ()+ addressing and may, therefore, alter a7 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci bsr.l _mul64 # _mul64() 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci btst &0x5,EXC_ISR(%a6) # supervisor mode? 48362306a36Sopenharmony_ci beq.w uieh_done 48462306a36Sopenharmony_ci btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed? 48562306a36Sopenharmony_ci beq.w uieh_done # no 48662306a36Sopenharmony_ci btst &0x7,EXC_ISR(%a6) # is trace enabled? 48762306a36Sopenharmony_ci bne.w uieh_trace_a7 # yes 48862306a36Sopenharmony_ci bra.w uieh_a7 # no 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ciuieh_div64: 49162306a36Sopenharmony_ci# div64() may use ()+ addressing and may, therefore, alter a7. 49262306a36Sopenharmony_ci# div64() may take a divide by zero exception. 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci bsr.l _div64 # _div64() 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci# here, we sort out all of the special cases that may have happened. 49762306a36Sopenharmony_ci btst &mia7_bit,SPCOND_FLG(%a6) # was a7 changed? 49862306a36Sopenharmony_ci bne.b uieh_div64_a7 # yes 49962306a36Sopenharmony_ciuieh_div64_dbyz: 50062306a36Sopenharmony_ci btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur? 50162306a36Sopenharmony_ci bne.w uieh_divbyzero # yes 50262306a36Sopenharmony_ci bra.w uieh_done # no 50362306a36Sopenharmony_ciuieh_div64_a7: 50462306a36Sopenharmony_ci btst &0x5,EXC_ISR(%a6) # supervisor mode? 50562306a36Sopenharmony_ci beq.b uieh_div64_dbyz # no 50662306a36Sopenharmony_ci# here, a7 has been incremented by 4 bytes in supervisor mode. we still 50762306a36Sopenharmony_ci# may have the following 3 cases: 50862306a36Sopenharmony_ci# (i) (a7)+ 50962306a36Sopenharmony_ci# (ii) (a7)+; trace 51062306a36Sopenharmony_ci# (iii) (a7)+; divide-by-zero 51162306a36Sopenharmony_ci# 51262306a36Sopenharmony_ci btst &idbyz_bit,SPCOND_FLG(%a6) # did divide-by-zero occur? 51362306a36Sopenharmony_ci bne.w uieh_divbyzero_a7 # yes 51462306a36Sopenharmony_ci tst.b EXC_ISR(%a6) # no; is trace enabled? 51562306a36Sopenharmony_ci bmi.w uieh_trace_a7 # yes 51662306a36Sopenharmony_ci bra.w uieh_a7 # no 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci# 51962306a36Sopenharmony_ci# now, w/ group2, make movep's decode the fastest since it will 52062306a36Sopenharmony_ci# most likely be used the most. 52162306a36Sopenharmony_ci# 52262306a36Sopenharmony_ciuieh_group2: 52362306a36Sopenharmony_ci btst &0x18,%d0 # test for not movep 52462306a36Sopenharmony_ci beq.b uieh_not_movep 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci bsr.l _moveperipheral # _movep() 52862306a36Sopenharmony_ci bra.w uieh_done 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ciuieh_not_movep: 53162306a36Sopenharmony_ci btst &0x1b,%d0 # test for chk2,cmp2 53262306a36Sopenharmony_ci beq.b uieh_chk2cmp2 # go handle chk2,cmp2 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci swap %d0 # put opword in lo word 53562306a36Sopenharmony_ci cmpi.b %d0,&0xfc # test for cas2 53662306a36Sopenharmony_ci beq.b uieh_cas2 # go handle cas2 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ciuieh_cas: 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci bsr.l _compandset # _cas() 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci# the cases of "cas Dc,Du,(a7)+" and "cas Dc,Du,-(a7)" used from supervisor 54362306a36Sopenharmony_ci# mode are simply not considered valid and therefore are not handled. 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci bra.w uieh_done 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ciuieh_cas2: 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 55062306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 55162306a36Sopenharmony_ci bsr.l _imem_read_word # read extension word 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci tst.l %d1 # ifetch error? 55462306a36Sopenharmony_ci bne.w isp_iacc # yes 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci bsr.l _compandset2 # _cas2() 55762306a36Sopenharmony_ci bra.w uieh_done 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ciuieh_chk2cmp2: 56062306a36Sopenharmony_ci# chk2 may take a chk exception 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci bsr.l _chk2_cmp2 # _chk2_cmp2() 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci# here we check to see if a chk trap should be taken 56562306a36Sopenharmony_ci cmpi.b SPCOND_FLG(%a6),&ichk_flg 56662306a36Sopenharmony_ci bne.w uieh_done 56762306a36Sopenharmony_ci bra.b uieh_chk_trap 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci########################################################################### 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci# 57262306a36Sopenharmony_ci# the required emulation has been completed. now, clean up the necessary stack 57362306a36Sopenharmony_ci# info and prepare for rte 57462306a36Sopenharmony_ci# 57562306a36Sopenharmony_ciuieh_done: 57662306a36Sopenharmony_ci mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci# if exception occurred in user mode, then we have to restore a7 in case it 57962306a36Sopenharmony_ci# changed. we don't have to update a7 for supervisor mose because that case 58062306a36Sopenharmony_ci# doesn't flow through here 58162306a36Sopenharmony_ci btst &0x5,EXC_ISR(%a6) # user or supervisor? 58262306a36Sopenharmony_ci bne.b uieh_finish # supervisor 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci mov.l EXC_A7(%a6),%a0 # fetch user stack pointer 58562306a36Sopenharmony_ci mov.l %a0,%usp # restore it 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ciuieh_finish: 58862306a36Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci btst &0x7,EXC_ISR(%a6) # is trace mode on? 59162306a36Sopenharmony_ci bne.b uieh_trace # yes;go handle trace mode 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),EXC_IPC(%a6) # new pc on stack frame 59462306a36Sopenharmony_ci mov.l EXC_A6(%a6),(%a6) # prepare new a6 for unlink 59562306a36Sopenharmony_ci unlk %a6 # unlink stack frame 59662306a36Sopenharmony_ci bra.l _isp_done 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci# 59962306a36Sopenharmony_ci# The instruction that was just emulated was also being traced. The trace 60062306a36Sopenharmony_ci# trap for this instruction will be lost unless we jump to the trace handler. 60162306a36Sopenharmony_ci# So, here we create a Trace Exception format number two exception stack 60262306a36Sopenharmony_ci# frame from the Unimplemented Integer Intruction Exception stack frame 60362306a36Sopenharmony_ci# format number zero and jump to the user supplied hook "_real_trace()". 60462306a36Sopenharmony_ci# 60562306a36Sopenharmony_ci# UIEH FRAME TRACE FRAME 60662306a36Sopenharmony_ci# ***************** ***************** 60762306a36Sopenharmony_ci# * 0x0 * 0x0f4 * * Current * 60862306a36Sopenharmony_ci# ***************** * PC * 60962306a36Sopenharmony_ci# * Current * ***************** 61062306a36Sopenharmony_ci# * PC * * 0x2 * 0x024 * 61162306a36Sopenharmony_ci# ***************** ***************** 61262306a36Sopenharmony_ci# * SR * * Next * 61362306a36Sopenharmony_ci# ***************** * PC * 61462306a36Sopenharmony_ci# ->* Old * ***************** 61562306a36Sopenharmony_ci# from link -->* A6 * * SR * 61662306a36Sopenharmony_ci# ***************** ***************** 61762306a36Sopenharmony_ci# /* A7 * * New * <-- for final unlink 61862306a36Sopenharmony_ci# / * * * A6 * 61962306a36Sopenharmony_ci# link frame < ***************** ***************** 62062306a36Sopenharmony_ci# \ ~ ~ ~ ~ 62162306a36Sopenharmony_ci# \***************** ***************** 62262306a36Sopenharmony_ci# 62362306a36Sopenharmony_ciuieh_trace: 62462306a36Sopenharmony_ci mov.l EXC_A6(%a6),-0x4(%a6) 62562306a36Sopenharmony_ci mov.w EXC_ISR(%a6),0x0(%a6) 62662306a36Sopenharmony_ci mov.l EXC_IPC(%a6),0x8(%a6) 62762306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),0x2(%a6) 62862306a36Sopenharmony_ci mov.w &0x2024,0x6(%a6) 62962306a36Sopenharmony_ci sub.l &0x4,%a6 63062306a36Sopenharmony_ci unlk %a6 63162306a36Sopenharmony_ci bra.l _real_trace 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci# 63462306a36Sopenharmony_ci# UIEH FRAME CHK FRAME 63562306a36Sopenharmony_ci# ***************** ***************** 63662306a36Sopenharmony_ci# * 0x0 * 0x0f4 * * Current * 63762306a36Sopenharmony_ci# ***************** * PC * 63862306a36Sopenharmony_ci# * Current * ***************** 63962306a36Sopenharmony_ci# * PC * * 0x2 * 0x018 * 64062306a36Sopenharmony_ci# ***************** ***************** 64162306a36Sopenharmony_ci# * SR * * Next * 64262306a36Sopenharmony_ci# ***************** * PC * 64362306a36Sopenharmony_ci# (4 words) ***************** 64462306a36Sopenharmony_ci# * SR * 64562306a36Sopenharmony_ci# ***************** 64662306a36Sopenharmony_ci# (6 words) 64762306a36Sopenharmony_ci# 64862306a36Sopenharmony_ci# the chk2 instruction should take a chk trap. so, here we must create a 64962306a36Sopenharmony_ci# chk stack frame from an unimplemented integer instruction exception frame 65062306a36Sopenharmony_ci# and jump to the user supplied entry point "_real_chk()". 65162306a36Sopenharmony_ci# 65262306a36Sopenharmony_ciuieh_chk_trap: 65362306a36Sopenharmony_ci mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 65462306a36Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci mov.w EXC_ISR(%a6),(%a6) # put new SR on stack 65762306a36Sopenharmony_ci mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack 65862306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack 65962306a36Sopenharmony_ci mov.w &0x2018,0x6(%a6) # put Vector Offset on stack 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci mov.l EXC_A6(%a6),%a6 # restore a6 66262306a36Sopenharmony_ci add.l &LOCAL_SIZE,%sp # clear stack frame 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci bra.l _real_chk 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci# 66762306a36Sopenharmony_ci# UIEH FRAME DIVBYZERO FRAME 66862306a36Sopenharmony_ci# ***************** ***************** 66962306a36Sopenharmony_ci# * 0x0 * 0x0f4 * * Current * 67062306a36Sopenharmony_ci# ***************** * PC * 67162306a36Sopenharmony_ci# * Current * ***************** 67262306a36Sopenharmony_ci# * PC * * 0x2 * 0x014 * 67362306a36Sopenharmony_ci# ***************** ***************** 67462306a36Sopenharmony_ci# * SR * * Next * 67562306a36Sopenharmony_ci# ***************** * PC * 67662306a36Sopenharmony_ci# (4 words) ***************** 67762306a36Sopenharmony_ci# * SR * 67862306a36Sopenharmony_ci# ***************** 67962306a36Sopenharmony_ci# (6 words) 68062306a36Sopenharmony_ci# 68162306a36Sopenharmony_ci# the divide instruction should take an integer divide by zero trap. so, here 68262306a36Sopenharmony_ci# we must create a divbyzero stack frame from an unimplemented integer 68362306a36Sopenharmony_ci# instruction exception frame and jump to the user supplied entry point 68462306a36Sopenharmony_ci# "_real_divbyzero()". 68562306a36Sopenharmony_ci# 68662306a36Sopenharmony_ciuieh_divbyzero: 68762306a36Sopenharmony_ci mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 68862306a36Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci mov.w EXC_ISR(%a6),(%a6) # put new SR on stack 69162306a36Sopenharmony_ci mov.l EXC_IPC(%a6),0x8(%a6) # put "Current PC" on stack 69262306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),0x2(%a6) # put "Next PC" on stack 69362306a36Sopenharmony_ci mov.w &0x2014,0x6(%a6) # put Vector Offset on stack 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci mov.l EXC_A6(%a6),%a6 # restore a6 69662306a36Sopenharmony_ci add.l &LOCAL_SIZE,%sp # clear stack frame 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci bra.l _real_divbyzero 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci# 70162306a36Sopenharmony_ci# DIVBYZERO FRAME 70262306a36Sopenharmony_ci# ***************** 70362306a36Sopenharmony_ci# * Current * 70462306a36Sopenharmony_ci# UIEH FRAME * PC * 70562306a36Sopenharmony_ci# ***************** ***************** 70662306a36Sopenharmony_ci# * 0x0 * 0x0f4 * * 0x2 * 0x014 * 70762306a36Sopenharmony_ci# ***************** ***************** 70862306a36Sopenharmony_ci# * Current * * Next * 70962306a36Sopenharmony_ci# * PC * * PC * 71062306a36Sopenharmony_ci# ***************** ***************** 71162306a36Sopenharmony_ci# * SR * * SR * 71262306a36Sopenharmony_ci# ***************** ***************** 71362306a36Sopenharmony_ci# (4 words) (6 words) 71462306a36Sopenharmony_ci# 71562306a36Sopenharmony_ci# the divide instruction should take an integer divide by zero trap. so, here 71662306a36Sopenharmony_ci# we must create a divbyzero stack frame from an unimplemented integer 71762306a36Sopenharmony_ci# instruction exception frame and jump to the user supplied entry point 71862306a36Sopenharmony_ci# "_real_divbyzero()". 71962306a36Sopenharmony_ci# 72062306a36Sopenharmony_ci# However, we must also deal with the fact that (a7)+ was used from supervisor 72162306a36Sopenharmony_ci# mode, thereby shifting the stack frame up 4 bytes. 72262306a36Sopenharmony_ci# 72362306a36Sopenharmony_ciuieh_divbyzero_a7: 72462306a36Sopenharmony_ci mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 72562306a36Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack 72862306a36Sopenharmony_ci mov.w &0x2014,0xa(%a6) # put Vector Offset on stack 72962306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci mov.l EXC_A6(%a6),%a6 # restore a6 73262306a36Sopenharmony_ci add.l &4+LOCAL_SIZE,%sp # clear stack frame 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci bra.l _real_divbyzero 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci# 73762306a36Sopenharmony_ci# TRACE FRAME 73862306a36Sopenharmony_ci# ***************** 73962306a36Sopenharmony_ci# * Current * 74062306a36Sopenharmony_ci# UIEH FRAME * PC * 74162306a36Sopenharmony_ci# ***************** ***************** 74262306a36Sopenharmony_ci# * 0x0 * 0x0f4 * * 0x2 * 0x024 * 74362306a36Sopenharmony_ci# ***************** ***************** 74462306a36Sopenharmony_ci# * Current * * Next * 74562306a36Sopenharmony_ci# * PC * * PC * 74662306a36Sopenharmony_ci# ***************** ***************** 74762306a36Sopenharmony_ci# * SR * * SR * 74862306a36Sopenharmony_ci# ***************** ***************** 74962306a36Sopenharmony_ci# (4 words) (6 words) 75062306a36Sopenharmony_ci# 75162306a36Sopenharmony_ci# 75262306a36Sopenharmony_ci# The instruction that was just emulated was also being traced. The trace 75362306a36Sopenharmony_ci# trap for this instruction will be lost unless we jump to the trace handler. 75462306a36Sopenharmony_ci# So, here we create a Trace Exception format number two exception stack 75562306a36Sopenharmony_ci# frame from the Unimplemented Integer Intruction Exception stack frame 75662306a36Sopenharmony_ci# format number zero and jump to the user supplied hook "_real_trace()". 75762306a36Sopenharmony_ci# 75862306a36Sopenharmony_ci# However, we must also deal with the fact that (a7)+ was used from supervisor 75962306a36Sopenharmony_ci# mode, thereby shifting the stack frame up 4 bytes. 76062306a36Sopenharmony_ci# 76162306a36Sopenharmony_ciuieh_trace_a7: 76262306a36Sopenharmony_ci mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 76362306a36Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci mov.l EXC_IPC(%a6),0xc(%a6) # put "Current PC" on stack 76662306a36Sopenharmony_ci mov.w &0x2024,0xa(%a6) # put Vector Offset on stack 76762306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),0x6(%a6) # put "Next PC" on stack 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci mov.l EXC_A6(%a6),%a6 # restore a6 77062306a36Sopenharmony_ci add.l &4+LOCAL_SIZE,%sp # clear stack frame 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci bra.l _real_trace 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci# 77562306a36Sopenharmony_ci# UIEH FRAME 77662306a36Sopenharmony_ci# ***************** 77762306a36Sopenharmony_ci# * 0x0 * 0x0f4 * 77862306a36Sopenharmony_ci# UIEH FRAME ***************** 77962306a36Sopenharmony_ci# ***************** * Next * 78062306a36Sopenharmony_ci# * 0x0 * 0x0f4 * * PC * 78162306a36Sopenharmony_ci# ***************** ***************** 78262306a36Sopenharmony_ci# * Current * * SR * 78362306a36Sopenharmony_ci# * PC * ***************** 78462306a36Sopenharmony_ci# ***************** (4 words) 78562306a36Sopenharmony_ci# * SR * 78662306a36Sopenharmony_ci# ***************** 78762306a36Sopenharmony_ci# (4 words) 78862306a36Sopenharmony_ciuieh_a7: 78962306a36Sopenharmony_ci mov.b EXC_CC+1(%a6),EXC_ISR+1(%a6) # insert new ccodes 79062306a36Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci mov.w &0x00f4,0xe(%a6) # put Vector Offset on stack 79362306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),0xa(%a6) # put "Next PC" on stack 79462306a36Sopenharmony_ci mov.w EXC_ISR(%a6),0x8(%a6) # put SR on stack 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci mov.l EXC_A6(%a6),%a6 # restore a6 79762306a36Sopenharmony_ci add.l &8+LOCAL_SIZE,%sp # clear stack frame 79862306a36Sopenharmony_ci bra.l _isp_done 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci########## 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci# this is the exit point if a data read or write fails. 80362306a36Sopenharmony_ci# a0 = failing address 80462306a36Sopenharmony_ci# d0 = fslw 80562306a36Sopenharmony_ciisp_dacc: 80662306a36Sopenharmony_ci mov.l %a0,(%a6) # save address 80762306a36Sopenharmony_ci mov.l %d0,-0x4(%a6) # save partial fslw 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci lea -64(%a6),%sp 81062306a36Sopenharmony_ci movm.l (%sp)+,&0x7fff # restore d0-d7/a0-a6 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci mov.l 0xc(%sp),-(%sp) # move voff,hi(pc) 81362306a36Sopenharmony_ci mov.l 0x4(%sp),0x10(%sp) # store fslw 81462306a36Sopenharmony_ci mov.l 0xc(%sp),0x4(%sp) # store sr,lo(pc) 81562306a36Sopenharmony_ci mov.l 0x8(%sp),0xc(%sp) # store address 81662306a36Sopenharmony_ci mov.l (%sp)+,0x4(%sp) # store voff,hi(pc) 81762306a36Sopenharmony_ci mov.w &0x4008,0x6(%sp) # store new voff 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci bra.b isp_acc_exit 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci# this is the exit point if an instruction word read fails. 82262306a36Sopenharmony_ci# FSLW: 82362306a36Sopenharmony_ci# misaligned = true 82462306a36Sopenharmony_ci# read = true 82562306a36Sopenharmony_ci# size = word 82662306a36Sopenharmony_ci# instruction = true 82762306a36Sopenharmony_ci# software emulation error = true 82862306a36Sopenharmony_ciisp_iacc: 82962306a36Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore d0-d7/a0-a5 83062306a36Sopenharmony_ci unlk %a6 # unlink frame 83162306a36Sopenharmony_ci sub.w &0x8,%sp # make room for acc frame 83262306a36Sopenharmony_ci mov.l 0x8(%sp),(%sp) # store sr,lo(pc) 83362306a36Sopenharmony_ci mov.w 0xc(%sp),0x4(%sp) # store hi(pc) 83462306a36Sopenharmony_ci mov.w &0x4008,0x6(%sp) # store new voff 83562306a36Sopenharmony_ci mov.l 0x2(%sp),0x8(%sp) # store address (=pc) 83662306a36Sopenharmony_ci mov.l &0x09428001,0xc(%sp) # store fslw 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ciisp_acc_exit: 83962306a36Sopenharmony_ci btst &0x5,(%sp) # user or supervisor? 84062306a36Sopenharmony_ci beq.b isp_acc_exit2 # user 84162306a36Sopenharmony_ci bset &0x2,0xd(%sp) # set supervisor TM bit 84262306a36Sopenharmony_ciisp_acc_exit2: 84362306a36Sopenharmony_ci bra.l _real_access 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci# if the addressing mode was (an)+ or -(an), the address register must 84662306a36Sopenharmony_ci# be restored to its pre-exception value before entering _real_access. 84762306a36Sopenharmony_ciisp_restore: 84862306a36Sopenharmony_ci cmpi.b SPCOND_FLG(%a6),&restore_flg # do we need a restore? 84962306a36Sopenharmony_ci bne.b isp_restore_done # no 85062306a36Sopenharmony_ci clr.l %d0 85162306a36Sopenharmony_ci mov.b EXC_SAVREG(%a6),%d0 # regno to restore 85262306a36Sopenharmony_ci mov.l EXC_SAVVAL(%a6),(EXC_AREGS,%a6,%d0.l*4) # restore value 85362306a36Sopenharmony_ciisp_restore_done: 85462306a36Sopenharmony_ci rts 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci######################################################################### 85762306a36Sopenharmony_ci# XDEF **************************************************************** # 85862306a36Sopenharmony_ci# _calc_ea(): routine to calculate effective address # 85962306a36Sopenharmony_ci# # 86062306a36Sopenharmony_ci# XREF **************************************************************** # 86162306a36Sopenharmony_ci# _imem_read_word() - read instruction word # 86262306a36Sopenharmony_ci# _imem_read_long() - read instruction longword # 86362306a36Sopenharmony_ci# _dmem_read_long() - read data longword (for memory indirect) # 86462306a36Sopenharmony_ci# isp_iacc() - handle instruction access error exception # 86562306a36Sopenharmony_ci# isp_dacc() - handle data access error exception # 86662306a36Sopenharmony_ci# # 86762306a36Sopenharmony_ci# INPUT *************************************************************** # 86862306a36Sopenharmony_ci# d0 = number of bytes related to effective address (w,l) # 86962306a36Sopenharmony_ci# # 87062306a36Sopenharmony_ci# OUTPUT ************************************************************** # 87162306a36Sopenharmony_ci# If exiting through isp_dacc... # 87262306a36Sopenharmony_ci# a0 = failing address # 87362306a36Sopenharmony_ci# d0 = FSLW # 87462306a36Sopenharmony_ci# elsif exiting though isp_iacc... # 87562306a36Sopenharmony_ci# none # 87662306a36Sopenharmony_ci# else # 87762306a36Sopenharmony_ci# a0 = effective address # 87862306a36Sopenharmony_ci# # 87962306a36Sopenharmony_ci# ALGORITHM *********************************************************** # 88062306a36Sopenharmony_ci# The effective address type is decoded from the opword residing # 88162306a36Sopenharmony_ci# on the stack. A jump table is used to vector to a routine for the # 88262306a36Sopenharmony_ci# appropriate mode. Since none of the emulated integer instructions # 88362306a36Sopenharmony_ci# uses byte-sized operands, only handle word and long operations. # 88462306a36Sopenharmony_ci# # 88562306a36Sopenharmony_ci# Dn,An - shouldn't enter here # 88662306a36Sopenharmony_ci# (An) - fetch An value from stack # 88762306a36Sopenharmony_ci# -(An) - fetch An value from stack; return decr value; # 88862306a36Sopenharmony_ci# place decr value on stack; store old value in case of # 88962306a36Sopenharmony_ci# future access error; if -(a7), set mda7_flg in # 89062306a36Sopenharmony_ci# SPCOND_FLG # 89162306a36Sopenharmony_ci# (An)+ - fetch An value from stack; return value; # 89262306a36Sopenharmony_ci# place incr value on stack; store old value in case of # 89362306a36Sopenharmony_ci# future access error; if (a7)+, set mia7_flg in # 89462306a36Sopenharmony_ci# SPCOND_FLG # 89562306a36Sopenharmony_ci# (d16,An) - fetch An value from stack; read d16 using # 89662306a36Sopenharmony_ci# _imem_read_word(); fetch may fail -> branch to # 89762306a36Sopenharmony_ci# isp_iacc() # 89862306a36Sopenharmony_ci# (xxx).w,(xxx).l - use _imem_read_{word,long}() to fetch # 89962306a36Sopenharmony_ci# address; fetch may fail # 90062306a36Sopenharmony_ci# #<data> - return address of immediate value; set immed_flg # 90162306a36Sopenharmony_ci# in SPCOND_FLG # 90262306a36Sopenharmony_ci# (d16,PC) - fetch stacked PC value; read d16 using # 90362306a36Sopenharmony_ci# _imem_read_word(); fetch may fail -> branch to # 90462306a36Sopenharmony_ci# isp_iacc() # 90562306a36Sopenharmony_ci# everything else - read needed displacements as appropriate w/ # 90662306a36Sopenharmony_ci# _imem_read_{word,long}(); read may fail; if memory # 90762306a36Sopenharmony_ci# indirect, read indirect address using # 90862306a36Sopenharmony_ci# _dmem_read_long() which may also fail # 90962306a36Sopenharmony_ci# # 91062306a36Sopenharmony_ci######################################################################### 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci global _calc_ea 91362306a36Sopenharmony_ci_calc_ea: 91462306a36Sopenharmony_ci mov.l %d0,%a0 # move # bytes to a0 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci# MODE and REG are taken from the EXC_OPWORD. 91762306a36Sopenharmony_ci mov.w EXC_OPWORD(%a6),%d0 # fetch opcode word 91862306a36Sopenharmony_ci mov.w %d0,%d1 # make a copy 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci andi.w &0x3f,%d0 # extract mode field 92162306a36Sopenharmony_ci andi.l &0x7,%d1 # extract reg field 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci# jump to the corresponding function for each {MODE,REG} pair. 92462306a36Sopenharmony_ci mov.w (tbl_ea_mode.b,%pc,%d0.w*2), %d0 # fetch jmp distance 92562306a36Sopenharmony_ci jmp (tbl_ea_mode.b,%pc,%d0.w*1) # jmp to correct ea mode 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci swbeg &64 92862306a36Sopenharmony_citbl_ea_mode: 92962306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 93062306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 93162306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 93262306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 93362306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 93462306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 93562306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 93662306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 93962306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 94062306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 94162306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 94262306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 94362306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 94462306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 94562306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci short addr_ind_a0 - tbl_ea_mode 94862306a36Sopenharmony_ci short addr_ind_a1 - tbl_ea_mode 94962306a36Sopenharmony_ci short addr_ind_a2 - tbl_ea_mode 95062306a36Sopenharmony_ci short addr_ind_a3 - tbl_ea_mode 95162306a36Sopenharmony_ci short addr_ind_a4 - tbl_ea_mode 95262306a36Sopenharmony_ci short addr_ind_a5 - tbl_ea_mode 95362306a36Sopenharmony_ci short addr_ind_a6 - tbl_ea_mode 95462306a36Sopenharmony_ci short addr_ind_a7 - tbl_ea_mode 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci short addr_ind_p_a0 - tbl_ea_mode 95762306a36Sopenharmony_ci short addr_ind_p_a1 - tbl_ea_mode 95862306a36Sopenharmony_ci short addr_ind_p_a2 - tbl_ea_mode 95962306a36Sopenharmony_ci short addr_ind_p_a3 - tbl_ea_mode 96062306a36Sopenharmony_ci short addr_ind_p_a4 - tbl_ea_mode 96162306a36Sopenharmony_ci short addr_ind_p_a5 - tbl_ea_mode 96262306a36Sopenharmony_ci short addr_ind_p_a6 - tbl_ea_mode 96362306a36Sopenharmony_ci short addr_ind_p_a7 - tbl_ea_mode 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci short addr_ind_m_a0 - tbl_ea_mode 96662306a36Sopenharmony_ci short addr_ind_m_a1 - tbl_ea_mode 96762306a36Sopenharmony_ci short addr_ind_m_a2 - tbl_ea_mode 96862306a36Sopenharmony_ci short addr_ind_m_a3 - tbl_ea_mode 96962306a36Sopenharmony_ci short addr_ind_m_a4 - tbl_ea_mode 97062306a36Sopenharmony_ci short addr_ind_m_a5 - tbl_ea_mode 97162306a36Sopenharmony_ci short addr_ind_m_a6 - tbl_ea_mode 97262306a36Sopenharmony_ci short addr_ind_m_a7 - tbl_ea_mode 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci short addr_ind_disp_a0 - tbl_ea_mode 97562306a36Sopenharmony_ci short addr_ind_disp_a1 - tbl_ea_mode 97662306a36Sopenharmony_ci short addr_ind_disp_a2 - tbl_ea_mode 97762306a36Sopenharmony_ci short addr_ind_disp_a3 - tbl_ea_mode 97862306a36Sopenharmony_ci short addr_ind_disp_a4 - tbl_ea_mode 97962306a36Sopenharmony_ci short addr_ind_disp_a5 - tbl_ea_mode 98062306a36Sopenharmony_ci short addr_ind_disp_a6 - tbl_ea_mode 98162306a36Sopenharmony_ci short addr_ind_disp_a7 - tbl_ea_mode 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 98462306a36Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 98562306a36Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 98662306a36Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 98762306a36Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 98862306a36Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 98962306a36Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 99062306a36Sopenharmony_ci short _addr_ind_ext - tbl_ea_mode 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci short abs_short - tbl_ea_mode 99362306a36Sopenharmony_ci short abs_long - tbl_ea_mode 99462306a36Sopenharmony_ci short pc_ind - tbl_ea_mode 99562306a36Sopenharmony_ci short pc_ind_ext - tbl_ea_mode 99662306a36Sopenharmony_ci short immediate - tbl_ea_mode 99762306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 99862306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 99962306a36Sopenharmony_ci short tbl_ea_mode - tbl_ea_mode 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci################################### 100262306a36Sopenharmony_ci# Address register indirect: (An) # 100362306a36Sopenharmony_ci################################### 100462306a36Sopenharmony_ciaddr_ind_a0: 100562306a36Sopenharmony_ci mov.l EXC_A0(%a6),%a0 # Get current a0 100662306a36Sopenharmony_ci rts 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ciaddr_ind_a1: 100962306a36Sopenharmony_ci mov.l EXC_A1(%a6),%a0 # Get current a1 101062306a36Sopenharmony_ci rts 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ciaddr_ind_a2: 101362306a36Sopenharmony_ci mov.l EXC_A2(%a6),%a0 # Get current a2 101462306a36Sopenharmony_ci rts 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ciaddr_ind_a3: 101762306a36Sopenharmony_ci mov.l EXC_A3(%a6),%a0 # Get current a3 101862306a36Sopenharmony_ci rts 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ciaddr_ind_a4: 102162306a36Sopenharmony_ci mov.l EXC_A4(%a6),%a0 # Get current a4 102262306a36Sopenharmony_ci rts 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ciaddr_ind_a5: 102562306a36Sopenharmony_ci mov.l EXC_A5(%a6),%a0 # Get current a5 102662306a36Sopenharmony_ci rts 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ciaddr_ind_a6: 102962306a36Sopenharmony_ci mov.l EXC_A6(%a6),%a0 # Get current a6 103062306a36Sopenharmony_ci rts 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ciaddr_ind_a7: 103362306a36Sopenharmony_ci mov.l EXC_A7(%a6),%a0 # Get current a7 103462306a36Sopenharmony_ci rts 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci##################################################### 103762306a36Sopenharmony_ci# Address register indirect w/ postincrement: (An)+ # 103862306a36Sopenharmony_ci##################################################### 103962306a36Sopenharmony_ciaddr_ind_p_a0: 104062306a36Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 104162306a36Sopenharmony_ci mov.l EXC_A0(%a6),%a0 # load current value 104262306a36Sopenharmony_ci add.l %a0,%d0 # increment 104362306a36Sopenharmony_ci mov.l %d0,EXC_A0(%a6) # save incremented value 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 104662306a36Sopenharmony_ci mov.b &0x0,EXC_SAVREG(%a6) # save regno, too 104762306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 104862306a36Sopenharmony_ci rts 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ciaddr_ind_p_a1: 105162306a36Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 105262306a36Sopenharmony_ci mov.l EXC_A1(%a6),%a0 # load current value 105362306a36Sopenharmony_ci add.l %a0,%d0 # increment 105462306a36Sopenharmony_ci mov.l %d0,EXC_A1(%a6) # save incremented value 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 105762306a36Sopenharmony_ci mov.b &0x1,EXC_SAVREG(%a6) # save regno, too 105862306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 105962306a36Sopenharmony_ci rts 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ciaddr_ind_p_a2: 106262306a36Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 106362306a36Sopenharmony_ci mov.l EXC_A2(%a6),%a0 # load current value 106462306a36Sopenharmony_ci add.l %a0,%d0 # increment 106562306a36Sopenharmony_ci mov.l %d0,EXC_A2(%a6) # save incremented value 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 106862306a36Sopenharmony_ci mov.b &0x2,EXC_SAVREG(%a6) # save regno, too 106962306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 107062306a36Sopenharmony_ci rts 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ciaddr_ind_p_a3: 107362306a36Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 107462306a36Sopenharmony_ci mov.l EXC_A3(%a6),%a0 # load current value 107562306a36Sopenharmony_ci add.l %a0,%d0 # increment 107662306a36Sopenharmony_ci mov.l %d0,EXC_A3(%a6) # save incremented value 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 107962306a36Sopenharmony_ci mov.b &0x3,EXC_SAVREG(%a6) # save regno, too 108062306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 108162306a36Sopenharmony_ci rts 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ciaddr_ind_p_a4: 108462306a36Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 108562306a36Sopenharmony_ci mov.l EXC_A4(%a6),%a0 # load current value 108662306a36Sopenharmony_ci add.l %a0,%d0 # increment 108762306a36Sopenharmony_ci mov.l %d0,EXC_A4(%a6) # save incremented value 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 109062306a36Sopenharmony_ci mov.b &0x4,EXC_SAVREG(%a6) # save regno, too 109162306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 109262306a36Sopenharmony_ci rts 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ciaddr_ind_p_a5: 109562306a36Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 109662306a36Sopenharmony_ci mov.l EXC_A5(%a6),%a0 # load current value 109762306a36Sopenharmony_ci add.l %a0,%d0 # increment 109862306a36Sopenharmony_ci mov.l %d0,EXC_A5(%a6) # save incremented value 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 110162306a36Sopenharmony_ci mov.b &0x5,EXC_SAVREG(%a6) # save regno, too 110262306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 110362306a36Sopenharmony_ci rts 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ciaddr_ind_p_a6: 110662306a36Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 110762306a36Sopenharmony_ci mov.l EXC_A6(%a6),%a0 # load current value 110862306a36Sopenharmony_ci add.l %a0,%d0 # increment 110962306a36Sopenharmony_ci mov.l %d0,EXC_A6(%a6) # save incremented value 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci mov.l %a0,EXC_SAVVAL(%a6) # save in case of access error 111262306a36Sopenharmony_ci mov.b &0x6,EXC_SAVREG(%a6) # save regno, too 111362306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 111462306a36Sopenharmony_ci rts 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ciaddr_ind_p_a7: 111762306a36Sopenharmony_ci mov.b &mia7_flg,SPCOND_FLG(%a6) # set "special case" flag 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci mov.l %a0,%d0 # copy no. bytes 112062306a36Sopenharmony_ci mov.l EXC_A7(%a6),%a0 # load current value 112162306a36Sopenharmony_ci add.l %a0,%d0 # increment 112262306a36Sopenharmony_ci mov.l %d0,EXC_A7(%a6) # save incremented value 112362306a36Sopenharmony_ci rts 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci#################################################### 112662306a36Sopenharmony_ci# Address register indirect w/ predecrement: -(An) # 112762306a36Sopenharmony_ci#################################################### 112862306a36Sopenharmony_ciaddr_ind_m_a0: 112962306a36Sopenharmony_ci mov.l EXC_A0(%a6),%d0 # Get current a0 113062306a36Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 113162306a36Sopenharmony_ci sub.l %a0,%d0 # Decrement 113262306a36Sopenharmony_ci mov.l %d0,EXC_A0(%a6) # Save decr value 113362306a36Sopenharmony_ci mov.l %d0,%a0 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_ci mov.b &0x0,EXC_SAVREG(%a6) # save regno, too 113662306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 113762306a36Sopenharmony_ci rts 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ciaddr_ind_m_a1: 114062306a36Sopenharmony_ci mov.l EXC_A1(%a6),%d0 # Get current a1 114162306a36Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 114262306a36Sopenharmony_ci sub.l %a0,%d0 # Decrement 114362306a36Sopenharmony_ci mov.l %d0,EXC_A1(%a6) # Save decr value 114462306a36Sopenharmony_ci mov.l %d0,%a0 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci mov.b &0x1,EXC_SAVREG(%a6) # save regno, too 114762306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 114862306a36Sopenharmony_ci rts 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ciaddr_ind_m_a2: 115162306a36Sopenharmony_ci mov.l EXC_A2(%a6),%d0 # Get current a2 115262306a36Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 115362306a36Sopenharmony_ci sub.l %a0,%d0 # Decrement 115462306a36Sopenharmony_ci mov.l %d0,EXC_A2(%a6) # Save decr value 115562306a36Sopenharmony_ci mov.l %d0,%a0 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci mov.b &0x2,EXC_SAVREG(%a6) # save regno, too 115862306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 115962306a36Sopenharmony_ci rts 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ciaddr_ind_m_a3: 116262306a36Sopenharmony_ci mov.l EXC_A3(%a6),%d0 # Get current a3 116362306a36Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 116462306a36Sopenharmony_ci sub.l %a0,%d0 # Decrement 116562306a36Sopenharmony_ci mov.l %d0,EXC_A3(%a6) # Save decr value 116662306a36Sopenharmony_ci mov.l %d0,%a0 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci mov.b &0x3,EXC_SAVREG(%a6) # save regno, too 116962306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 117062306a36Sopenharmony_ci rts 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ciaddr_ind_m_a4: 117362306a36Sopenharmony_ci mov.l EXC_A4(%a6),%d0 # Get current a4 117462306a36Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 117562306a36Sopenharmony_ci sub.l %a0,%d0 # Decrement 117662306a36Sopenharmony_ci mov.l %d0,EXC_A4(%a6) # Save decr value 117762306a36Sopenharmony_ci mov.l %d0,%a0 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci mov.b &0x4,EXC_SAVREG(%a6) # save regno, too 118062306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 118162306a36Sopenharmony_ci rts 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ciaddr_ind_m_a5: 118462306a36Sopenharmony_ci mov.l EXC_A5(%a6),%d0 # Get current a5 118562306a36Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 118662306a36Sopenharmony_ci sub.l %a0,%d0 # Decrement 118762306a36Sopenharmony_ci mov.l %d0,EXC_A5(%a6) # Save decr value 118862306a36Sopenharmony_ci mov.l %d0,%a0 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci mov.b &0x5,EXC_SAVREG(%a6) # save regno, too 119162306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 119262306a36Sopenharmony_ci rts 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ciaddr_ind_m_a6: 119562306a36Sopenharmony_ci mov.l EXC_A6(%a6),%d0 # Get current a6 119662306a36Sopenharmony_ci mov.l %d0,EXC_SAVVAL(%a6) # save in case of access error 119762306a36Sopenharmony_ci sub.l %a0,%d0 # Decrement 119862306a36Sopenharmony_ci mov.l %d0,EXC_A6(%a6) # Save decr value 119962306a36Sopenharmony_ci mov.l %d0,%a0 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci mov.b &0x6,EXC_SAVREG(%a6) # save regno, too 120262306a36Sopenharmony_ci mov.b &restore_flg,SPCOND_FLG(%a6) # set flag 120362306a36Sopenharmony_ci rts 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ciaddr_ind_m_a7: 120662306a36Sopenharmony_ci mov.b &mda7_flg,SPCOND_FLG(%a6) # set "special case" flag 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci mov.l EXC_A7(%a6),%d0 # Get current a7 120962306a36Sopenharmony_ci sub.l %a0,%d0 # Decrement 121062306a36Sopenharmony_ci mov.l %d0,EXC_A7(%a6) # Save decr value 121162306a36Sopenharmony_ci mov.l %d0,%a0 121262306a36Sopenharmony_ci rts 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci######################################################## 121562306a36Sopenharmony_ci# Address register indirect w/ displacement: (d16, An) # 121662306a36Sopenharmony_ci######################################################## 121762306a36Sopenharmony_ciaddr_ind_disp_a0: 121862306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 121962306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 122062306a36Sopenharmony_ci bsr.l _imem_read_word 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_ci tst.l %d1 # ifetch error? 122362306a36Sopenharmony_ci bne.l isp_iacc # yes 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 122662306a36Sopenharmony_ci add.l EXC_A0(%a6),%a0 # a0 + d16 122762306a36Sopenharmony_ci rts 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ciaddr_ind_disp_a1: 123062306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 123162306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 123262306a36Sopenharmony_ci bsr.l _imem_read_word 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci tst.l %d1 # ifetch error? 123562306a36Sopenharmony_ci bne.l isp_iacc # yes 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 123862306a36Sopenharmony_ci add.l EXC_A1(%a6),%a0 # a1 + d16 123962306a36Sopenharmony_ci rts 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ciaddr_ind_disp_a2: 124262306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 124362306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 124462306a36Sopenharmony_ci bsr.l _imem_read_word 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci tst.l %d1 # ifetch error? 124762306a36Sopenharmony_ci bne.l isp_iacc # yes 124862306a36Sopenharmony_ci 124962306a36Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 125062306a36Sopenharmony_ci add.l EXC_A2(%a6),%a0 # a2 + d16 125162306a36Sopenharmony_ci rts 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ciaddr_ind_disp_a3: 125462306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 125562306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 125662306a36Sopenharmony_ci bsr.l _imem_read_word 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci tst.l %d1 # ifetch error? 125962306a36Sopenharmony_ci bne.l isp_iacc # yes 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 126262306a36Sopenharmony_ci add.l EXC_A3(%a6),%a0 # a3 + d16 126362306a36Sopenharmony_ci rts 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ciaddr_ind_disp_a4: 126662306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 126762306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 126862306a36Sopenharmony_ci bsr.l _imem_read_word 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci tst.l %d1 # ifetch error? 127162306a36Sopenharmony_ci bne.l isp_iacc # yes 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 127462306a36Sopenharmony_ci add.l EXC_A4(%a6),%a0 # a4 + d16 127562306a36Sopenharmony_ci rts 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ciaddr_ind_disp_a5: 127862306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 127962306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 128062306a36Sopenharmony_ci bsr.l _imem_read_word 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci tst.l %d1 # ifetch error? 128362306a36Sopenharmony_ci bne.l isp_iacc # yes 128462306a36Sopenharmony_ci 128562306a36Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 128662306a36Sopenharmony_ci add.l EXC_A5(%a6),%a0 # a5 + d16 128762306a36Sopenharmony_ci rts 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ciaddr_ind_disp_a6: 129062306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 129162306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 129262306a36Sopenharmony_ci bsr.l _imem_read_word 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci tst.l %d1 # ifetch error? 129562306a36Sopenharmony_ci bne.l isp_iacc # yes 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 129862306a36Sopenharmony_ci add.l EXC_A6(%a6),%a0 # a6 + d16 129962306a36Sopenharmony_ci rts 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ciaddr_ind_disp_a7: 130262306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 130362306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 130462306a36Sopenharmony_ci bsr.l _imem_read_word 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci tst.l %d1 # ifetch error? 130762306a36Sopenharmony_ci bne.l isp_iacc # yes 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 131062306a36Sopenharmony_ci add.l EXC_A7(%a6),%a0 # a7 + d16 131162306a36Sopenharmony_ci rts 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci######################################################################## 131462306a36Sopenharmony_ci# Address register indirect w/ index(8-bit displacement): (dn, An, Xn) # 131562306a36Sopenharmony_ci# " " " w/ " (base displacement): (bd, An, Xn) # 131662306a36Sopenharmony_ci# Memory indirect postindexed: ([bd, An], Xn, od) # 131762306a36Sopenharmony_ci# Memory indirect preindexed: ([bd, An, Xn], od) # 131862306a36Sopenharmony_ci######################################################################## 131962306a36Sopenharmony_ci_addr_ind_ext: 132062306a36Sopenharmony_ci mov.l %d1,-(%sp) 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 132362306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 132462306a36Sopenharmony_ci bsr.l _imem_read_word # fetch extword in d0 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci tst.l %d1 # ifetch error? 132762306a36Sopenharmony_ci bne.l isp_iacc # yes 132862306a36Sopenharmony_ci 132962306a36Sopenharmony_ci mov.l (%sp)+,%d1 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_ci mov.l (EXC_AREGS,%a6,%d1.w*4),%a0 # put base in a0 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci btst &0x8,%d0 133462306a36Sopenharmony_ci beq.b addr_ind_index_8bit # for ext word or not? 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci movm.l &0x3c00,-(%sp) # save d2-d5 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci mov.l %d0,%d5 # put extword in d5 133962306a36Sopenharmony_ci mov.l %a0,%d3 # put base in d3 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci bra.l calc_mem_ind # calc memory indirect 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ciaddr_ind_index_8bit: 134462306a36Sopenharmony_ci mov.l %d2,-(%sp) # save old d2 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci mov.l %d0,%d1 134762306a36Sopenharmony_ci rol.w &0x4,%d1 134862306a36Sopenharmony_ci andi.w &0xf,%d1 # extract index regno 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci btst &0xb,%d0 # is it word or long? 135362306a36Sopenharmony_ci bne.b aii8_long 135462306a36Sopenharmony_ci ext.l %d1 # sign extend word index 135562306a36Sopenharmony_ciaii8_long: 135662306a36Sopenharmony_ci mov.l %d0,%d2 135762306a36Sopenharmony_ci rol.w &0x7,%d2 135862306a36Sopenharmony_ci andi.l &0x3,%d2 # extract scale value 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci lsl.l %d2,%d1 # shift index by scale 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci extb.l %d0 # sign extend displacement 136362306a36Sopenharmony_ci add.l %d1,%d0 # index + disp 136462306a36Sopenharmony_ci add.l %d0,%a0 # An + (index + disp) 136562306a36Sopenharmony_ci 136662306a36Sopenharmony_ci mov.l (%sp)+,%d2 # restore old d2 136762306a36Sopenharmony_ci rts 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci###################### 137062306a36Sopenharmony_ci# Immediate: #<data> # 137162306a36Sopenharmony_ci######################################################################### 137262306a36Sopenharmony_ci# word, long: <ea> of the data is the current extension word # 137362306a36Sopenharmony_ci# pointer value. new extension word pointer is simply the old # 137462306a36Sopenharmony_ci# plus the number of bytes in the data type(2 or 4). # 137562306a36Sopenharmony_ci######################################################################### 137662306a36Sopenharmony_ciimmediate: 137762306a36Sopenharmony_ci mov.b &immed_flg,SPCOND_FLG(%a6) # set immediate flag 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch extension word ptr 138062306a36Sopenharmony_ci rts 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci########################### 138362306a36Sopenharmony_ci# Absolute short: (XXX).W # 138462306a36Sopenharmony_ci########################### 138562306a36Sopenharmony_ciabs_short: 138662306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 138762306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 138862306a36Sopenharmony_ci bsr.l _imem_read_word # fetch short address 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci tst.l %d1 # ifetch error? 139162306a36Sopenharmony_ci bne.l isp_iacc # yes 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci mov.w %d0,%a0 # return <ea> in a0 139462306a36Sopenharmony_ci rts 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci########################## 139762306a36Sopenharmony_ci# Absolute long: (XXX).L # 139862306a36Sopenharmony_ci########################## 139962306a36Sopenharmony_ciabs_long: 140062306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 140162306a36Sopenharmony_ci addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 140262306a36Sopenharmony_ci bsr.l _imem_read_long # fetch long address 140362306a36Sopenharmony_ci 140462306a36Sopenharmony_ci tst.l %d1 # ifetch error? 140562306a36Sopenharmony_ci bne.l isp_iacc # yes 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci mov.l %d0,%a0 # return <ea> in a0 140862306a36Sopenharmony_ci rts 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci####################################################### 141162306a36Sopenharmony_ci# Program counter indirect w/ displacement: (d16, PC) # 141262306a36Sopenharmony_ci####################################################### 141362306a36Sopenharmony_cipc_ind: 141462306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 141562306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 141662306a36Sopenharmony_ci bsr.l _imem_read_word # fetch word displacement 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci tst.l %d1 # ifetch error? 141962306a36Sopenharmony_ci bne.l isp_iacc # yes 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci mov.w %d0,%a0 # sign extend displacement 142262306a36Sopenharmony_ci 142362306a36Sopenharmony_ci add.l EXC_EXTWPTR(%a6),%a0 # pc + d16 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_ci# _imem_read_word() increased the extwptr by 2. need to adjust here. 142662306a36Sopenharmony_ci subq.l &0x2,%a0 # adjust <ea> 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci rts 142962306a36Sopenharmony_ci 143062306a36Sopenharmony_ci########################################################## 143162306a36Sopenharmony_ci# PC indirect w/ index(8-bit displacement): (d8, PC, An) # 143262306a36Sopenharmony_ci# " " w/ " (base displacement): (bd, PC, An) # 143362306a36Sopenharmony_ci# PC memory indirect postindexed: ([bd, PC], Xn, od) # 143462306a36Sopenharmony_ci# PC memory indirect preindexed: ([bd, PC, Xn], od) # 143562306a36Sopenharmony_ci########################################################## 143662306a36Sopenharmony_cipc_ind_ext: 143762306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 143862306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 143962306a36Sopenharmony_ci bsr.l _imem_read_word # fetch ext word 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci tst.l %d1 # ifetch error? 144262306a36Sopenharmony_ci bne.l isp_iacc # yes 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # put base in a0 144562306a36Sopenharmony_ci subq.l &0x2,%a0 # adjust base 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_ci btst &0x8,%d0 # is disp only 8 bits? 144862306a36Sopenharmony_ci beq.b pc_ind_index_8bit # yes 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci# the indexed addressing mode uses a base displacement of size 145162306a36Sopenharmony_ci# word or long 145262306a36Sopenharmony_ci movm.l &0x3c00,-(%sp) # save d2-d5 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci mov.l %d0,%d5 # put extword in d5 145562306a36Sopenharmony_ci mov.l %a0,%d3 # put base in d3 145662306a36Sopenharmony_ci 145762306a36Sopenharmony_ci bra.l calc_mem_ind # calc memory indirect 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_cipc_ind_index_8bit: 146062306a36Sopenharmony_ci mov.l %d2,-(%sp) # create a temp register 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ci mov.l %d0,%d1 # make extword copy 146362306a36Sopenharmony_ci rol.w &0x4,%d1 # rotate reg num into place 146462306a36Sopenharmony_ci andi.w &0xf,%d1 # extract register number 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d1.w*4),%d1 # fetch index reg value 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci btst &0xb,%d0 # is index word or long? 146962306a36Sopenharmony_ci bne.b pii8_long # long 147062306a36Sopenharmony_ci ext.l %d1 # sign extend word index 147162306a36Sopenharmony_cipii8_long: 147262306a36Sopenharmony_ci mov.l %d0,%d2 # make extword copy 147362306a36Sopenharmony_ci rol.w &0x7,%d2 # rotate scale value into place 147462306a36Sopenharmony_ci andi.l &0x3,%d2 # extract scale value 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci lsl.l %d2,%d1 # shift index by scale 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_ci extb.l %d0 # sign extend displacement 147962306a36Sopenharmony_ci add.l %d1,%d0 # index + disp 148062306a36Sopenharmony_ci add.l %d0,%a0 # An + (index + disp) 148162306a36Sopenharmony_ci 148262306a36Sopenharmony_ci mov.l (%sp)+,%d2 # restore temp register 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci rts 148562306a36Sopenharmony_ci 148662306a36Sopenharmony_ci# a5 = exc_extwptr (global to uaeh) 148762306a36Sopenharmony_ci# a4 = exc_opword (global to uaeh) 148862306a36Sopenharmony_ci# a3 = exc_dregs (global to uaeh) 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci# d2 = index (internal " " ) 149162306a36Sopenharmony_ci# d3 = base (internal " " ) 149262306a36Sopenharmony_ci# d4 = od (internal " " ) 149362306a36Sopenharmony_ci# d5 = extword (internal " " ) 149462306a36Sopenharmony_cicalc_mem_ind: 149562306a36Sopenharmony_ci btst &0x6,%d5 # is the index suppressed? 149662306a36Sopenharmony_ci beq.b calc_index 149762306a36Sopenharmony_ci clr.l %d2 # yes, so index = 0 149862306a36Sopenharmony_ci bra.b base_supp_ck 149962306a36Sopenharmony_cicalc_index: 150062306a36Sopenharmony_ci bfextu %d5{&16:&4},%d2 150162306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d2.w*4),%d2 150262306a36Sopenharmony_ci btst &0xb,%d5 # is index word or long? 150362306a36Sopenharmony_ci bne.b no_ext 150462306a36Sopenharmony_ci ext.l %d2 150562306a36Sopenharmony_cino_ext: 150662306a36Sopenharmony_ci bfextu %d5{&21:&2},%d0 150762306a36Sopenharmony_ci lsl.l %d0,%d2 150862306a36Sopenharmony_cibase_supp_ck: 150962306a36Sopenharmony_ci btst &0x7,%d5 # is the bd suppressed? 151062306a36Sopenharmony_ci beq.b no_base_sup 151162306a36Sopenharmony_ci clr.l %d3 151262306a36Sopenharmony_cino_base_sup: 151362306a36Sopenharmony_ci bfextu %d5{&26:&2},%d0 # get bd size 151462306a36Sopenharmony_ci# beq.l _error # if (size == 0) it's reserved 151562306a36Sopenharmony_ci cmpi.b %d0,&2 151662306a36Sopenharmony_ci blt.b no_bd 151762306a36Sopenharmony_ci beq.b get_word_bd 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 152062306a36Sopenharmony_ci addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 152162306a36Sopenharmony_ci bsr.l _imem_read_long 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_ci tst.l %d1 # ifetch error? 152462306a36Sopenharmony_ci bne.l isp_iacc # yes 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci bra.b chk_ind 152762306a36Sopenharmony_ciget_word_bd: 152862306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 152962306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 153062306a36Sopenharmony_ci bsr.l _imem_read_word 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci tst.l %d1 # ifetch error? 153362306a36Sopenharmony_ci bne.l isp_iacc # yes 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci ext.l %d0 # sign extend bd 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_cichk_ind: 153862306a36Sopenharmony_ci add.l %d0,%d3 # base += bd 153962306a36Sopenharmony_cino_bd: 154062306a36Sopenharmony_ci bfextu %d5{&30:&2},%d0 # is od suppressed? 154162306a36Sopenharmony_ci beq.w aii_bd 154262306a36Sopenharmony_ci cmpi.b %d0,&0x2 154362306a36Sopenharmony_ci blt.b null_od 154462306a36Sopenharmony_ci beq.b word_od 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 154762306a36Sopenharmony_ci addq.l &0x4,EXC_EXTWPTR(%a6) # incr instruction ptr 154862306a36Sopenharmony_ci bsr.l _imem_read_long 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci tst.l %d1 # ifetch error? 155162306a36Sopenharmony_ci bne.l isp_iacc # yes 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci bra.b add_them 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ciword_od: 155662306a36Sopenharmony_ci mov.l EXC_EXTWPTR(%a6),%a0 # fetch instruction addr 155762306a36Sopenharmony_ci addq.l &0x2,EXC_EXTWPTR(%a6) # incr instruction ptr 155862306a36Sopenharmony_ci bsr.l _imem_read_word 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci tst.l %d1 # ifetch error? 156162306a36Sopenharmony_ci bne.l isp_iacc # yes 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci ext.l %d0 # sign extend od 156462306a36Sopenharmony_ci bra.b add_them 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_cinull_od: 156762306a36Sopenharmony_ci clr.l %d0 156862306a36Sopenharmony_ciadd_them: 156962306a36Sopenharmony_ci mov.l %d0,%d4 157062306a36Sopenharmony_ci btst &0x2,%d5 # pre or post indexing? 157162306a36Sopenharmony_ci beq.b pre_indexed 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci mov.l %d3,%a0 157462306a36Sopenharmony_ci bsr.l _dmem_read_long 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci tst.l %d1 # dfetch error? 157762306a36Sopenharmony_ci bne.b calc_ea_err # yes 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci add.l %d2,%d0 # <ea> += index 158062306a36Sopenharmony_ci add.l %d4,%d0 # <ea> += od 158162306a36Sopenharmony_ci bra.b done_ea 158262306a36Sopenharmony_ci 158362306a36Sopenharmony_cipre_indexed: 158462306a36Sopenharmony_ci add.l %d2,%d3 # preindexing 158562306a36Sopenharmony_ci mov.l %d3,%a0 158662306a36Sopenharmony_ci bsr.l _dmem_read_long 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci tst.l %d1 # ifetch error? 158962306a36Sopenharmony_ci bne.b calc_ea_err # yes 159062306a36Sopenharmony_ci 159162306a36Sopenharmony_ci add.l %d4,%d0 # ea += od 159262306a36Sopenharmony_ci bra.b done_ea 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ciaii_bd: 159562306a36Sopenharmony_ci add.l %d2,%d3 # ea = (base + bd) + index 159662306a36Sopenharmony_ci mov.l %d3,%d0 159762306a36Sopenharmony_cidone_ea: 159862306a36Sopenharmony_ci mov.l %d0,%a0 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci movm.l (%sp)+,&0x003c # restore d2-d5 160162306a36Sopenharmony_ci rts 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci# if dmem_read_long() returns a fail message in d1, the package 160462306a36Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw 160562306a36Sopenharmony_ci# and the failing address to the routine that creates the new frame. 160662306a36Sopenharmony_ci# FSLW: 160762306a36Sopenharmony_ci# read = true 160862306a36Sopenharmony_ci# size = longword 160962306a36Sopenharmony_ci# TM = data 161062306a36Sopenharmony_ci# software emulation error = true 161162306a36Sopenharmony_cicalc_ea_err: 161262306a36Sopenharmony_ci mov.l %d3,%a0 # pass failing address 161362306a36Sopenharmony_ci mov.l &0x01010001,%d0 # pass fslw 161462306a36Sopenharmony_ci bra.l isp_dacc 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci######################################################################### 161762306a36Sopenharmony_ci# XDEF **************************************************************** # 161862306a36Sopenharmony_ci# _moveperipheral(): routine to emulate movep instruction # 161962306a36Sopenharmony_ci# # 162062306a36Sopenharmony_ci# XREF **************************************************************** # 162162306a36Sopenharmony_ci# _dmem_read_byte() - read byte from memory # 162262306a36Sopenharmony_ci# _dmem_write_byte() - write byte to memory # 162362306a36Sopenharmony_ci# isp_dacc() - handle data access error exception # 162462306a36Sopenharmony_ci# # 162562306a36Sopenharmony_ci# INPUT *************************************************************** # 162662306a36Sopenharmony_ci# none # 162762306a36Sopenharmony_ci# # 162862306a36Sopenharmony_ci# OUTPUT ************************************************************** # 162962306a36Sopenharmony_ci# If exiting through isp_dacc... # 163062306a36Sopenharmony_ci# a0 = failing address # 163162306a36Sopenharmony_ci# d0 = FSLW # 163262306a36Sopenharmony_ci# else # 163362306a36Sopenharmony_ci# none # 163462306a36Sopenharmony_ci# # 163562306a36Sopenharmony_ci# ALGORITHM *********************************************************** # 163662306a36Sopenharmony_ci# Decode the movep instruction words stored at EXC_OPWORD and # 163762306a36Sopenharmony_ci# either read or write the required bytes from/to memory. Use the # 163862306a36Sopenharmony_ci# _dmem_{read,write}_byte() routines. If one of the memory routines # 163962306a36Sopenharmony_ci# returns a failing value, we must pass the failing address and a FSLW # 164062306a36Sopenharmony_ci# to the _isp_dacc() routine. # 164162306a36Sopenharmony_ci# Since this instruction is used to access peripherals, make sure # 164262306a36Sopenharmony_ci# to only access the required bytes. # 164362306a36Sopenharmony_ci# # 164462306a36Sopenharmony_ci######################################################################### 164562306a36Sopenharmony_ci 164662306a36Sopenharmony_ci########################### 164762306a36Sopenharmony_ci# movep.(w,l) Dx,(d,Ay) # 164862306a36Sopenharmony_ci# movep.(w,l) (d,Ay),Dx # 164962306a36Sopenharmony_ci########################### 165062306a36Sopenharmony_ci global _moveperipheral 165162306a36Sopenharmony_ci_moveperipheral: 165262306a36Sopenharmony_ci mov.w EXC_OPWORD(%a6),%d1 # fetch the opcode word 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci mov.b %d1,%d0 165562306a36Sopenharmony_ci and.w &0x7,%d0 # extract Ay from opcode word 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci mov.l (EXC_AREGS,%a6,%d0.w*4),%a0 # fetch ay 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci add.w EXC_EXTWORD(%a6),%a0 # add: an + sgn_ext(disp) 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci btst &0x7,%d1 # (reg 2 mem) or (mem 2 reg) 166262306a36Sopenharmony_ci beq.w mem2reg 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci# reg2mem: fetch dx, then write it to memory 166562306a36Sopenharmony_cireg2mem: 166662306a36Sopenharmony_ci mov.w %d1,%d0 166762306a36Sopenharmony_ci rol.w &0x7,%d0 166862306a36Sopenharmony_ci and.w &0x7,%d0 # extract Dx from opcode word 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4), %d0 # fetch dx 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci btst &0x6,%d1 # word or long operation? 167362306a36Sopenharmony_ci beq.b r2mwtrans 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_ci# a0 = dst addr 167662306a36Sopenharmony_ci# d0 = Dx 167762306a36Sopenharmony_cir2mltrans: 167862306a36Sopenharmony_ci mov.l %d0,%d2 # store data 167962306a36Sopenharmony_ci mov.l %a0,%a2 # store addr 168062306a36Sopenharmony_ci rol.l &0x8,%d2 168162306a36Sopenharmony_ci mov.l %d2,%d0 168262306a36Sopenharmony_ci 168362306a36Sopenharmony_ci bsr.l _dmem_write_byte # os : write hi 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci tst.l %d1 # dfetch error? 168662306a36Sopenharmony_ci bne.w movp_write_err # yes 168762306a36Sopenharmony_ci 168862306a36Sopenharmony_ci add.w &0x2,%a2 # incr addr 168962306a36Sopenharmony_ci mov.l %a2,%a0 169062306a36Sopenharmony_ci rol.l &0x8,%d2 169162306a36Sopenharmony_ci mov.l %d2,%d0 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci bsr.l _dmem_write_byte # os : write lo 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_ci tst.l %d1 # dfetch error? 169662306a36Sopenharmony_ci bne.w movp_write_err # yes 169762306a36Sopenharmony_ci 169862306a36Sopenharmony_ci add.w &0x2,%a2 # incr addr 169962306a36Sopenharmony_ci mov.l %a2,%a0 170062306a36Sopenharmony_ci rol.l &0x8,%d2 170162306a36Sopenharmony_ci mov.l %d2,%d0 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_ci bsr.l _dmem_write_byte # os : write lo 170462306a36Sopenharmony_ci 170562306a36Sopenharmony_ci tst.l %d1 # dfetch error? 170662306a36Sopenharmony_ci bne.w movp_write_err # yes 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_ci add.w &0x2,%a2 # incr addr 170962306a36Sopenharmony_ci mov.l %a2,%a0 171062306a36Sopenharmony_ci rol.l &0x8,%d2 171162306a36Sopenharmony_ci mov.l %d2,%d0 171262306a36Sopenharmony_ci 171362306a36Sopenharmony_ci bsr.l _dmem_write_byte # os : write lo 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci tst.l %d1 # dfetch error? 171662306a36Sopenharmony_ci bne.w movp_write_err # yes 171762306a36Sopenharmony_ci 171862306a36Sopenharmony_ci rts 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci# a0 = dst addr 172162306a36Sopenharmony_ci# d0 = Dx 172262306a36Sopenharmony_cir2mwtrans: 172362306a36Sopenharmony_ci mov.l %d0,%d2 # store data 172462306a36Sopenharmony_ci mov.l %a0,%a2 # store addr 172562306a36Sopenharmony_ci lsr.w &0x8,%d0 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci bsr.l _dmem_write_byte # os : write hi 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci tst.l %d1 # dfetch error? 173062306a36Sopenharmony_ci bne.w movp_write_err # yes 173162306a36Sopenharmony_ci 173262306a36Sopenharmony_ci add.w &0x2,%a2 173362306a36Sopenharmony_ci mov.l %a2,%a0 173462306a36Sopenharmony_ci mov.l %d2,%d0 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_ci bsr.l _dmem_write_byte # os : write lo 173762306a36Sopenharmony_ci 173862306a36Sopenharmony_ci tst.l %d1 # dfetch error? 173962306a36Sopenharmony_ci bne.w movp_write_err # yes 174062306a36Sopenharmony_ci 174162306a36Sopenharmony_ci rts 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ci# mem2reg: read bytes from memory. 174462306a36Sopenharmony_ci# determines the dest register, and then writes the bytes into it. 174562306a36Sopenharmony_cimem2reg: 174662306a36Sopenharmony_ci btst &0x6,%d1 # word or long operation? 174762306a36Sopenharmony_ci beq.b m2rwtrans 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_ci# a0 = dst addr 175062306a36Sopenharmony_cim2rltrans: 175162306a36Sopenharmony_ci mov.l %a0,%a2 # store addr 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ci bsr.l _dmem_read_byte # read first byte 175462306a36Sopenharmony_ci 175562306a36Sopenharmony_ci tst.l %d1 # dfetch error? 175662306a36Sopenharmony_ci bne.w movp_read_err # yes 175762306a36Sopenharmony_ci 175862306a36Sopenharmony_ci mov.l %d0,%d2 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci add.w &0x2,%a2 # incr addr by 2 bytes 176162306a36Sopenharmony_ci mov.l %a2,%a0 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci bsr.l _dmem_read_byte # read second byte 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci tst.l %d1 # dfetch error? 176662306a36Sopenharmony_ci bne.w movp_read_err # yes 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_ci lsl.w &0x8,%d2 176962306a36Sopenharmony_ci mov.b %d0,%d2 # append bytes 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci add.w &0x2,%a2 # incr addr by 2 bytes 177262306a36Sopenharmony_ci mov.l %a2,%a0 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci bsr.l _dmem_read_byte # read second byte 177562306a36Sopenharmony_ci 177662306a36Sopenharmony_ci tst.l %d1 # dfetch error? 177762306a36Sopenharmony_ci bne.w movp_read_err # yes 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci lsl.l &0x8,%d2 178062306a36Sopenharmony_ci mov.b %d0,%d2 # append bytes 178162306a36Sopenharmony_ci 178262306a36Sopenharmony_ci add.w &0x2,%a2 # incr addr by 2 bytes 178362306a36Sopenharmony_ci mov.l %a2,%a0 178462306a36Sopenharmony_ci 178562306a36Sopenharmony_ci bsr.l _dmem_read_byte # read second byte 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci tst.l %d1 # dfetch error? 178862306a36Sopenharmony_ci bne.w movp_read_err # yes 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci lsl.l &0x8,%d2 179162306a36Sopenharmony_ci mov.b %d0,%d2 # append bytes 179262306a36Sopenharmony_ci 179362306a36Sopenharmony_ci mov.b EXC_OPWORD(%a6),%d1 179462306a36Sopenharmony_ci lsr.b &0x1,%d1 179562306a36Sopenharmony_ci and.w &0x7,%d1 # extract Dx from opcode word 179662306a36Sopenharmony_ci 179762306a36Sopenharmony_ci mov.l %d2,(EXC_DREGS,%a6,%d1.w*4) # store dx 179862306a36Sopenharmony_ci 179962306a36Sopenharmony_ci rts 180062306a36Sopenharmony_ci 180162306a36Sopenharmony_ci# a0 = dst addr 180262306a36Sopenharmony_cim2rwtrans: 180362306a36Sopenharmony_ci mov.l %a0,%a2 # store addr 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_ci bsr.l _dmem_read_byte # read first byte 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci tst.l %d1 # dfetch error? 180862306a36Sopenharmony_ci bne.w movp_read_err # yes 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_ci mov.l %d0,%d2 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci add.w &0x2,%a2 # incr addr by 2 bytes 181362306a36Sopenharmony_ci mov.l %a2,%a0 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_ci bsr.l _dmem_read_byte # read second byte 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci tst.l %d1 # dfetch error? 181862306a36Sopenharmony_ci bne.w movp_read_err # yes 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci lsl.w &0x8,%d2 182162306a36Sopenharmony_ci mov.b %d0,%d2 # append bytes 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci mov.b EXC_OPWORD(%a6),%d1 182462306a36Sopenharmony_ci lsr.b &0x1,%d1 182562306a36Sopenharmony_ci and.w &0x7,%d1 # extract Dx from opcode word 182662306a36Sopenharmony_ci 182762306a36Sopenharmony_ci mov.w %d2,(EXC_DREGS+2,%a6,%d1.w*4) # store dx 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_ci rts 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ci# if dmem_{read,write}_byte() returns a fail message in d1, the package 183262306a36Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw 183362306a36Sopenharmony_ci# and the failing address to the routine that creates the new frame. 183462306a36Sopenharmony_ci# FSLW: 183562306a36Sopenharmony_ci# write = true 183662306a36Sopenharmony_ci# size = byte 183762306a36Sopenharmony_ci# TM = data 183862306a36Sopenharmony_ci# software emulation error = true 183962306a36Sopenharmony_cimovp_write_err: 184062306a36Sopenharmony_ci mov.l %a2,%a0 # pass failing address 184162306a36Sopenharmony_ci mov.l &0x00a10001,%d0 # pass fslw 184262306a36Sopenharmony_ci bra.l isp_dacc 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_ci# FSLW: 184562306a36Sopenharmony_ci# read = true 184662306a36Sopenharmony_ci# size = byte 184762306a36Sopenharmony_ci# TM = data 184862306a36Sopenharmony_ci# software emulation error = true 184962306a36Sopenharmony_cimovp_read_err: 185062306a36Sopenharmony_ci mov.l %a2,%a0 # pass failing address 185162306a36Sopenharmony_ci mov.l &0x01210001,%d0 # pass fslw 185262306a36Sopenharmony_ci bra.l isp_dacc 185362306a36Sopenharmony_ci 185462306a36Sopenharmony_ci######################################################################### 185562306a36Sopenharmony_ci# XDEF **************************************************************** # 185662306a36Sopenharmony_ci# _chk2_cmp2(): routine to emulate chk2/cmp2 instructions # 185762306a36Sopenharmony_ci# # 185862306a36Sopenharmony_ci# XREF **************************************************************** # 185962306a36Sopenharmony_ci# _calc_ea(): calculate effective address # 186062306a36Sopenharmony_ci# _dmem_read_long(): read operands # 186162306a36Sopenharmony_ci# _dmem_read_word(): read operands # 186262306a36Sopenharmony_ci# isp_dacc(): handle data access error exception # 186362306a36Sopenharmony_ci# # 186462306a36Sopenharmony_ci# INPUT *************************************************************** # 186562306a36Sopenharmony_ci# none # 186662306a36Sopenharmony_ci# # 186762306a36Sopenharmony_ci# OUTPUT ************************************************************** # 186862306a36Sopenharmony_ci# If exiting through isp_dacc... # 186962306a36Sopenharmony_ci# a0 = failing address # 187062306a36Sopenharmony_ci# d0 = FSLW # 187162306a36Sopenharmony_ci# else # 187262306a36Sopenharmony_ci# none # 187362306a36Sopenharmony_ci# # 187462306a36Sopenharmony_ci# ALGORITHM *********************************************************** # 187562306a36Sopenharmony_ci# First, calculate the effective address, then fetch the byte, # 187662306a36Sopenharmony_ci# word, or longword sized operands. Then, in the interest of # 187762306a36Sopenharmony_ci# simplicity, all operands are converted to longword size whether the # 187862306a36Sopenharmony_ci# operation is byte, word, or long. The bounds are sign extended # 187962306a36Sopenharmony_ci# accordingly. If Rn is a data register, Rn is also sign extended. If # 188062306a36Sopenharmony_ci# Rn is an address register, it need not be sign extended since the # 188162306a36Sopenharmony_ci# full register is always used. # 188262306a36Sopenharmony_ci# The comparisons are made and the condition codes calculated. # 188362306a36Sopenharmony_ci# If the instruction is chk2 and the Rn value is out-of-bounds, set # 188462306a36Sopenharmony_ci# the ichk_flg in SPCOND_FLG. # 188562306a36Sopenharmony_ci# If the memory fetch returns a failing value, pass the failing # 188662306a36Sopenharmony_ci# address and FSLW to the isp_dacc() routine. # 188762306a36Sopenharmony_ci# # 188862306a36Sopenharmony_ci######################################################################### 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci global _chk2_cmp2 189162306a36Sopenharmony_ci_chk2_cmp2: 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_ci# passing size parameter doesn't matter since chk2 & cmp2 can't do 189462306a36Sopenharmony_ci# either predecrement, postincrement, or immediate. 189562306a36Sopenharmony_ci bsr.l _calc_ea # calculate <ea> 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci mov.b EXC_EXTWORD(%a6), %d0 # fetch hi extension word 189862306a36Sopenharmony_ci rol.b &0x4, %d0 # rotate reg bits into lo 189962306a36Sopenharmony_ci and.w &0xf, %d0 # extract reg bits 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4), %d2 # get regval 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_ci cmpi.b EXC_OPWORD(%a6), &0x2 # what size is operation? 190462306a36Sopenharmony_ci blt.b chk2_cmp2_byte # size == byte 190562306a36Sopenharmony_ci beq.b chk2_cmp2_word # size == word 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci# the bounds are longword size. call routine to read the lower 190862306a36Sopenharmony_ci# bound into d0 and the higher bound into d1. 190962306a36Sopenharmony_cichk2_cmp2_long: 191062306a36Sopenharmony_ci mov.l %a0,%a2 # save copy of <ea> 191162306a36Sopenharmony_ci bsr.l _dmem_read_long # fetch long lower bound 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_ci tst.l %d1 # dfetch error? 191462306a36Sopenharmony_ci bne.w chk2_cmp2_err_l # yes 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ci mov.l %d0,%d3 # save long lower bound 191762306a36Sopenharmony_ci addq.l &0x4,%a2 191862306a36Sopenharmony_ci mov.l %a2,%a0 # pass <ea> of long upper bound 191962306a36Sopenharmony_ci bsr.l _dmem_read_long # fetch long upper bound 192062306a36Sopenharmony_ci 192162306a36Sopenharmony_ci tst.l %d1 # dfetch error? 192262306a36Sopenharmony_ci bne.w chk2_cmp2_err_l # yes 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci mov.l %d0,%d1 # long upper bound in d1 192562306a36Sopenharmony_ci mov.l %d3,%d0 # long lower bound in d0 192662306a36Sopenharmony_ci bra.w chk2_cmp2_compare # go do the compare emulation 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci# the bounds are word size. fetch them in one subroutine call by 192962306a36Sopenharmony_ci# reading a longword. sign extend both. if it's a data operation, 193062306a36Sopenharmony_ci# sign extend Rn to long, also. 193162306a36Sopenharmony_cichk2_cmp2_word: 193262306a36Sopenharmony_ci mov.l %a0,%a2 193362306a36Sopenharmony_ci bsr.l _dmem_read_long # fetch 2 word bounds 193462306a36Sopenharmony_ci 193562306a36Sopenharmony_ci tst.l %d1 # dfetch error? 193662306a36Sopenharmony_ci bne.w chk2_cmp2_err_l # yes 193762306a36Sopenharmony_ci 193862306a36Sopenharmony_ci mov.w %d0, %d1 # place hi in %d1 193962306a36Sopenharmony_ci swap %d0 # place lo in %d0 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_ci ext.l %d0 # sign extend lo bnd 194262306a36Sopenharmony_ci ext.l %d1 # sign extend hi bnd 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci btst &0x7, EXC_EXTWORD(%a6) # address compare? 194562306a36Sopenharmony_ci bne.w chk2_cmp2_compare # yes; don't sign extend 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_ci# operation is a data register compare. 194862306a36Sopenharmony_ci# sign extend word to long so we can do simple longword compares. 194962306a36Sopenharmony_ci ext.l %d2 # sign extend data word 195062306a36Sopenharmony_ci bra.w chk2_cmp2_compare # go emulate compare 195162306a36Sopenharmony_ci 195262306a36Sopenharmony_ci# the bounds are byte size. fetch them in one subroutine call by 195362306a36Sopenharmony_ci# reading a word. sign extend both. if it's a data operation, 195462306a36Sopenharmony_ci# sign extend Rn to long, also. 195562306a36Sopenharmony_cichk2_cmp2_byte: 195662306a36Sopenharmony_ci mov.l %a0,%a2 195762306a36Sopenharmony_ci bsr.l _dmem_read_word # fetch 2 byte bounds 195862306a36Sopenharmony_ci 195962306a36Sopenharmony_ci tst.l %d1 # dfetch error? 196062306a36Sopenharmony_ci bne.w chk2_cmp2_err_w # yes 196162306a36Sopenharmony_ci 196262306a36Sopenharmony_ci mov.b %d0, %d1 # place hi in %d1 196362306a36Sopenharmony_ci lsr.w &0x8, %d0 # place lo in %d0 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_ci extb.l %d0 # sign extend lo bnd 196662306a36Sopenharmony_ci extb.l %d1 # sign extend hi bnd 196762306a36Sopenharmony_ci 196862306a36Sopenharmony_ci btst &0x7, EXC_EXTWORD(%a6) # address compare? 196962306a36Sopenharmony_ci bne.b chk2_cmp2_compare # yes; don't sign extend 197062306a36Sopenharmony_ci 197162306a36Sopenharmony_ci# operation is a data register compare. 197262306a36Sopenharmony_ci# sign extend byte to long so we can do simple longword compares. 197362306a36Sopenharmony_ci extb.l %d2 # sign extend data byte 197462306a36Sopenharmony_ci 197562306a36Sopenharmony_ci# 197662306a36Sopenharmony_ci# To set the ccodes correctly: 197762306a36Sopenharmony_ci# (1) save 'Z' bit from (Rn - lo) 197862306a36Sopenharmony_ci# (2) save 'Z' and 'N' bits from ((hi - lo) - (Rn - hi)) 197962306a36Sopenharmony_ci# (3) keep 'X', 'N', and 'V' from before instruction 198062306a36Sopenharmony_ci# (4) combine ccodes 198162306a36Sopenharmony_ci# 198262306a36Sopenharmony_cichk2_cmp2_compare: 198362306a36Sopenharmony_ci sub.l %d0, %d2 # (Rn - lo) 198462306a36Sopenharmony_ci mov.w %cc, %d3 # fetch resulting ccodes 198562306a36Sopenharmony_ci andi.b &0x4, %d3 # keep 'Z' bit 198662306a36Sopenharmony_ci sub.l %d0, %d1 # (hi - lo) 198762306a36Sopenharmony_ci cmp.l %d1,%d2 # ((hi - lo) - (Rn - hi)) 198862306a36Sopenharmony_ci 198962306a36Sopenharmony_ci mov.w %cc, %d4 # fetch resulting ccodes 199062306a36Sopenharmony_ci or.b %d4, %d3 # combine w/ earlier ccodes 199162306a36Sopenharmony_ci andi.b &0x5, %d3 # keep 'Z' and 'N' 199262306a36Sopenharmony_ci 199362306a36Sopenharmony_ci mov.w EXC_CC(%a6), %d4 # fetch old ccodes 199462306a36Sopenharmony_ci andi.b &0x1a, %d4 # keep 'X','N','V' bits 199562306a36Sopenharmony_ci or.b %d3, %d4 # insert new ccodes 199662306a36Sopenharmony_ci mov.w %d4, EXC_CC(%a6) # save new ccodes 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_ci btst &0x3, EXC_EXTWORD(%a6) # separate chk2,cmp2 199962306a36Sopenharmony_ci bne.b chk2_finish # it's a chk2 200062306a36Sopenharmony_ci 200162306a36Sopenharmony_ci rts 200262306a36Sopenharmony_ci 200362306a36Sopenharmony_ci# this code handles the only difference between chk2 and cmp2. chk2 would 200462306a36Sopenharmony_ci# have trapped out if the value was out of bounds. we check this by seeing 200562306a36Sopenharmony_ci# if the 'N' bit was set by the operation. 200662306a36Sopenharmony_cichk2_finish: 200762306a36Sopenharmony_ci btst &0x0, %d4 # is 'N' bit set? 200862306a36Sopenharmony_ci bne.b chk2_trap # yes;chk2 should trap 200962306a36Sopenharmony_ci rts 201062306a36Sopenharmony_cichk2_trap: 201162306a36Sopenharmony_ci mov.b &ichk_flg,SPCOND_FLG(%a6) # set "special case" flag 201262306a36Sopenharmony_ci rts 201362306a36Sopenharmony_ci 201462306a36Sopenharmony_ci# if dmem_read_{long,word}() returns a fail message in d1, the package 201562306a36Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw 201662306a36Sopenharmony_ci# and the failing address to the routine that creates the new frame. 201762306a36Sopenharmony_ci# FSLW: 201862306a36Sopenharmony_ci# read = true 201962306a36Sopenharmony_ci# size = longword 202062306a36Sopenharmony_ci# TM = data 202162306a36Sopenharmony_ci# software emulation error = true 202262306a36Sopenharmony_cichk2_cmp2_err_l: 202362306a36Sopenharmony_ci mov.l %a2,%a0 # pass failing address 202462306a36Sopenharmony_ci mov.l &0x01010001,%d0 # pass fslw 202562306a36Sopenharmony_ci bra.l isp_dacc 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_ci# FSLW: 202862306a36Sopenharmony_ci# read = true 202962306a36Sopenharmony_ci# size = word 203062306a36Sopenharmony_ci# TM = data 203162306a36Sopenharmony_ci# software emulation error = true 203262306a36Sopenharmony_cichk2_cmp2_err_w: 203362306a36Sopenharmony_ci mov.l %a2,%a0 # pass failing address 203462306a36Sopenharmony_ci mov.l &0x01410001,%d0 # pass fslw 203562306a36Sopenharmony_ci bra.l isp_dacc 203662306a36Sopenharmony_ci 203762306a36Sopenharmony_ci######################################################################### 203862306a36Sopenharmony_ci# XDEF **************************************************************** # 203962306a36Sopenharmony_ci# _div64(): routine to emulate div{u,s}.l <ea>,Dr:Dq # 204062306a36Sopenharmony_ci# 64/32->32r:32q # 204162306a36Sopenharmony_ci# # 204262306a36Sopenharmony_ci# XREF **************************************************************** # 204362306a36Sopenharmony_ci# _calc_ea() - calculate effective address # 204462306a36Sopenharmony_ci# isp_iacc() - handle instruction access error exception # 204562306a36Sopenharmony_ci# isp_dacc() - handle data access error exception # 204662306a36Sopenharmony_ci# isp_restore() - restore An on access error w/ -() or ()+ # 204762306a36Sopenharmony_ci# # 204862306a36Sopenharmony_ci# INPUT *************************************************************** # 204962306a36Sopenharmony_ci# none # 205062306a36Sopenharmony_ci# # 205162306a36Sopenharmony_ci# OUTPUT ************************************************************** # 205262306a36Sopenharmony_ci# If exiting through isp_dacc... # 205362306a36Sopenharmony_ci# a0 = failing address # 205462306a36Sopenharmony_ci# d0 = FSLW # 205562306a36Sopenharmony_ci# else # 205662306a36Sopenharmony_ci# none # 205762306a36Sopenharmony_ci# # 205862306a36Sopenharmony_ci# ALGORITHM *********************************************************** # 205962306a36Sopenharmony_ci# First, decode the operand location. If it's in Dn, fetch from # 206062306a36Sopenharmony_ci# the stack. If it's in memory, use _calc_ea() to calculate the # 206162306a36Sopenharmony_ci# effective address. Use _dmem_read_long() to fetch at that address. # 206262306a36Sopenharmony_ci# Unless the operand is immediate data. Then use _imem_read_long(). # 206362306a36Sopenharmony_ci# Send failures to isp_dacc() or isp_iacc() as appropriate. # 206462306a36Sopenharmony_ci# If the operands are signed, make them unsigned and save the # 206562306a36Sopenharmony_ci# sign info for later. Separate out special cases like divide-by-zero # 206662306a36Sopenharmony_ci# or 32-bit divides if possible. Else, use a special math algorithm # 206762306a36Sopenharmony_ci# to calculate the result. # 206862306a36Sopenharmony_ci# Restore sign info if signed instruction. Set the condition # 206962306a36Sopenharmony_ci# codes. Set idbyz_flg in SPCOND_FLG if divisor was zero. Store the # 207062306a36Sopenharmony_ci# quotient and remainder in the appropriate data registers on the stack.# 207162306a36Sopenharmony_ci# # 207262306a36Sopenharmony_ci######################################################################### 207362306a36Sopenharmony_ci 207462306a36Sopenharmony_ciset NDIVISOR, EXC_TEMP+0x0 207562306a36Sopenharmony_ciset NDIVIDEND, EXC_TEMP+0x1 207662306a36Sopenharmony_ciset NDRSAVE, EXC_TEMP+0x2 207762306a36Sopenharmony_ciset NDQSAVE, EXC_TEMP+0x4 207862306a36Sopenharmony_ciset DDSECOND, EXC_TEMP+0x6 207962306a36Sopenharmony_ciset DDQUOTIENT, EXC_TEMP+0x8 208062306a36Sopenharmony_ciset DDNORMAL, EXC_TEMP+0xc 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_ci global _div64 208362306a36Sopenharmony_ci############# 208462306a36Sopenharmony_ci# div(u,s)l # 208562306a36Sopenharmony_ci############# 208662306a36Sopenharmony_ci_div64: 208762306a36Sopenharmony_ci mov.b EXC_OPWORD+1(%a6), %d0 208862306a36Sopenharmony_ci andi.b &0x38, %d0 # extract src mode 208962306a36Sopenharmony_ci 209062306a36Sopenharmony_ci bne.w dcontrolmodel_s # %dn dest or control mode? 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_ci mov.b EXC_OPWORD+1(%a6), %d0 # extract Dn from opcode 209362306a36Sopenharmony_ci andi.w &0x7, %d0 209462306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4), %d7 # fetch divisor from register 209562306a36Sopenharmony_ci 209662306a36Sopenharmony_cidgotsrcl: 209762306a36Sopenharmony_ci beq.w div64eq0 # divisor is = 0!!! 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci mov.b EXC_EXTWORD+1(%a6), %d0 # extract Dr from extword 210062306a36Sopenharmony_ci mov.b EXC_EXTWORD(%a6), %d1 # extract Dq from extword 210162306a36Sopenharmony_ci and.w &0x7, %d0 210262306a36Sopenharmony_ci lsr.b &0x4, %d1 210362306a36Sopenharmony_ci and.w &0x7, %d1 210462306a36Sopenharmony_ci mov.w %d0, NDRSAVE(%a6) # save Dr for later 210562306a36Sopenharmony_ci mov.w %d1, NDQSAVE(%a6) # save Dq for later 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_ci# fetch %dr and %dq directly off stack since all regs are saved there 210862306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4), %d5 # get dividend hi 210962306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d1.w*4), %d6 # get dividend lo 211062306a36Sopenharmony_ci 211162306a36Sopenharmony_ci# separate signed and unsigned divide 211262306a36Sopenharmony_ci btst &0x3, EXC_EXTWORD(%a6) # signed or unsigned? 211362306a36Sopenharmony_ci beq.b dspecialcases # use positive divide 211462306a36Sopenharmony_ci 211562306a36Sopenharmony_ci# save the sign of the divisor 211662306a36Sopenharmony_ci# make divisor unsigned if it's negative 211762306a36Sopenharmony_ci tst.l %d7 # chk sign of divisor 211862306a36Sopenharmony_ci slt NDIVISOR(%a6) # save sign of divisor 211962306a36Sopenharmony_ci bpl.b dsgndividend 212062306a36Sopenharmony_ci neg.l %d7 # complement negative divisor 212162306a36Sopenharmony_ci 212262306a36Sopenharmony_ci# save the sign of the dividend 212362306a36Sopenharmony_ci# make dividend unsigned if it's negative 212462306a36Sopenharmony_cidsgndividend: 212562306a36Sopenharmony_ci tst.l %d5 # chk sign of hi(dividend) 212662306a36Sopenharmony_ci slt NDIVIDEND(%a6) # save sign of dividend 212762306a36Sopenharmony_ci bpl.b dspecialcases 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci mov.w &0x0, %cc # clear 'X' cc bit 213062306a36Sopenharmony_ci negx.l %d6 # complement signed dividend 213162306a36Sopenharmony_ci negx.l %d5 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ci# extract some special cases: 213462306a36Sopenharmony_ci# - is (dividend == 0) ? 213562306a36Sopenharmony_ci# - is (hi(dividend) == 0 && (divisor <= lo(dividend))) ? (32-bit div) 213662306a36Sopenharmony_cidspecialcases: 213762306a36Sopenharmony_ci tst.l %d5 # is (hi(dividend) == 0) 213862306a36Sopenharmony_ci bne.b dnormaldivide # no, so try it the long way 213962306a36Sopenharmony_ci 214062306a36Sopenharmony_ci tst.l %d6 # is (lo(dividend) == 0), too 214162306a36Sopenharmony_ci beq.w ddone # yes, so (dividend == 0) 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_ci cmp.l %d7,%d6 # is (divisor <= lo(dividend)) 214462306a36Sopenharmony_ci bls.b d32bitdivide # yes, so use 32 bit divide 214562306a36Sopenharmony_ci 214662306a36Sopenharmony_ci exg %d5,%d6 # q = 0, r = dividend 214762306a36Sopenharmony_ci bra.w divfinish # can't divide, we're done. 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_cid32bitdivide: 215062306a36Sopenharmony_ci tdivu.l %d7, %d5:%d6 # it's only a 32/32 bit div! 215162306a36Sopenharmony_ci 215262306a36Sopenharmony_ci bra.b divfinish 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_cidnormaldivide: 215562306a36Sopenharmony_ci# last special case: 215662306a36Sopenharmony_ci# - is hi(dividend) >= divisor ? if yes, then overflow 215762306a36Sopenharmony_ci cmp.l %d7,%d5 215862306a36Sopenharmony_ci bls.b ddovf # answer won't fit in 32 bits 215962306a36Sopenharmony_ci 216062306a36Sopenharmony_ci# perform the divide algorithm: 216162306a36Sopenharmony_ci bsr.l dclassical # do int divide 216262306a36Sopenharmony_ci 216362306a36Sopenharmony_ci# separate into signed and unsigned finishes. 216462306a36Sopenharmony_cidivfinish: 216562306a36Sopenharmony_ci btst &0x3, EXC_EXTWORD(%a6) # do divs, divu separately 216662306a36Sopenharmony_ci beq.b ddone # divu has no processing!!! 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci# it was a divs.l, so ccode setting is a little more complicated... 216962306a36Sopenharmony_ci tst.b NDIVIDEND(%a6) # remainder has same sign 217062306a36Sopenharmony_ci beq.b dcc # as dividend. 217162306a36Sopenharmony_ci neg.l %d5 # sgn(rem) = sgn(dividend) 217262306a36Sopenharmony_cidcc: 217362306a36Sopenharmony_ci mov.b NDIVISOR(%a6), %d0 217462306a36Sopenharmony_ci eor.b %d0, NDIVIDEND(%a6) # chk if quotient is negative 217562306a36Sopenharmony_ci beq.b dqpos # branch to quot positive 217662306a36Sopenharmony_ci 217762306a36Sopenharmony_ci# 0x80000000 is the largest number representable as a 32-bit negative 217862306a36Sopenharmony_ci# number. the negative of 0x80000000 is 0x80000000. 217962306a36Sopenharmony_ci cmpi.l %d6, &0x80000000 # will (-quot) fit in 32 bits? 218062306a36Sopenharmony_ci bhi.b ddovf 218162306a36Sopenharmony_ci 218262306a36Sopenharmony_ci neg.l %d6 # make (-quot) 2's comp 218362306a36Sopenharmony_ci 218462306a36Sopenharmony_ci bra.b ddone 218562306a36Sopenharmony_ci 218662306a36Sopenharmony_cidqpos: 218762306a36Sopenharmony_ci btst &0x1f, %d6 # will (+quot) fit in 32 bits? 218862306a36Sopenharmony_ci bne.b ddovf 218962306a36Sopenharmony_ci 219062306a36Sopenharmony_ciddone: 219162306a36Sopenharmony_ci# at this point, result is normal so ccodes are set based on result. 219262306a36Sopenharmony_ci mov.w EXC_CC(%a6), %cc 219362306a36Sopenharmony_ci tst.l %d6 # set %ccode bits 219462306a36Sopenharmony_ci mov.w %cc, EXC_CC(%a6) 219562306a36Sopenharmony_ci 219662306a36Sopenharmony_ci mov.w NDRSAVE(%a6), %d0 # get Dr off stack 219762306a36Sopenharmony_ci mov.w NDQSAVE(%a6), %d1 # get Dq off stack 219862306a36Sopenharmony_ci 219962306a36Sopenharmony_ci# if the register numbers are the same, only the quotient gets saved. 220062306a36Sopenharmony_ci# so, if we always save the quotient second, we save ourselves a cmp&beq 220162306a36Sopenharmony_ci mov.l %d5, (EXC_DREGS,%a6,%d0.w*4) # save remainder 220262306a36Sopenharmony_ci mov.l %d6, (EXC_DREGS,%a6,%d1.w*4) # save quotient 220362306a36Sopenharmony_ci 220462306a36Sopenharmony_ci rts 220562306a36Sopenharmony_ci 220662306a36Sopenharmony_ciddovf: 220762306a36Sopenharmony_ci bset &0x1, EXC_CC+1(%a6) # 'V' set on overflow 220862306a36Sopenharmony_ci bclr &0x0, EXC_CC+1(%a6) # 'C' cleared on overflow 220962306a36Sopenharmony_ci 221062306a36Sopenharmony_ci rts 221162306a36Sopenharmony_ci 221262306a36Sopenharmony_cidiv64eq0: 221362306a36Sopenharmony_ci andi.b &0x1e, EXC_CC+1(%a6) # clear 'C' bit on divbyzero 221462306a36Sopenharmony_ci ori.b &idbyz_flg,SPCOND_FLG(%a6) # set "special case" flag 221562306a36Sopenharmony_ci rts 221662306a36Sopenharmony_ci 221762306a36Sopenharmony_ci########################################################################### 221862306a36Sopenharmony_ci######################################################################### 221962306a36Sopenharmony_ci# This routine uses the 'classical' Algorithm D from Donald Knuth's # 222062306a36Sopenharmony_ci# Art of Computer Programming, vol II, Seminumerical Algorithms. # 222162306a36Sopenharmony_ci# For this implementation b=2**16, and the target is U1U2U3U4/V1V2, # 222262306a36Sopenharmony_ci# where U,V are words of the quadword dividend and longword divisor, # 222362306a36Sopenharmony_ci# and U1, V1 are the most significant words. # 222462306a36Sopenharmony_ci# # 222562306a36Sopenharmony_ci# The most sig. longword of the 64 bit dividend must be in %d5, least # 222662306a36Sopenharmony_ci# in %d6. The divisor must be in the variable ddivisor, and the # 222762306a36Sopenharmony_ci# signed/unsigned flag ddusign must be set (0=unsigned,1=signed). # 222862306a36Sopenharmony_ci# The quotient is returned in %d6, remainder in %d5, unless the # 222962306a36Sopenharmony_ci# v (overflow) bit is set in the saved %ccr. If overflow, the dividend # 223062306a36Sopenharmony_ci# is unchanged. # 223162306a36Sopenharmony_ci######################################################################### 223262306a36Sopenharmony_cidclassical: 223362306a36Sopenharmony_ci# if the divisor msw is 0, use simpler algorithm then the full blown 223462306a36Sopenharmony_ci# one at ddknuth: 223562306a36Sopenharmony_ci 223662306a36Sopenharmony_ci cmpi.l %d7, &0xffff 223762306a36Sopenharmony_ci bhi.b ddknuth # go use D. Knuth algorithm 223862306a36Sopenharmony_ci 223962306a36Sopenharmony_ci# Since the divisor is only a word (and larger than the mslw of the dividend), 224062306a36Sopenharmony_ci# a simpler algorithm may be used : 224162306a36Sopenharmony_ci# In the general case, four quotient words would be created by 224262306a36Sopenharmony_ci# dividing the divisor word into each dividend word. In this case, 224362306a36Sopenharmony_ci# the first two quotient words must be zero, or overflow would occur. 224462306a36Sopenharmony_ci# Since we already checked this case above, we can treat the most significant 224562306a36Sopenharmony_ci# longword of the dividend as (0) remainder (see Knuth) and merely complete 224662306a36Sopenharmony_ci# the last two divisions to get a quotient longword and word remainder: 224762306a36Sopenharmony_ci 224862306a36Sopenharmony_ci clr.l %d1 224962306a36Sopenharmony_ci swap %d5 # same as r*b if previous step rqd 225062306a36Sopenharmony_ci swap %d6 # get u3 to lsw position 225162306a36Sopenharmony_ci mov.w %d6, %d5 # rb + u3 225262306a36Sopenharmony_ci 225362306a36Sopenharmony_ci divu.w %d7, %d5 225462306a36Sopenharmony_ci 225562306a36Sopenharmony_ci mov.w %d5, %d1 # first quotient word 225662306a36Sopenharmony_ci swap %d6 # get u4 225762306a36Sopenharmony_ci mov.w %d6, %d5 # rb + u4 225862306a36Sopenharmony_ci 225962306a36Sopenharmony_ci divu.w %d7, %d5 226062306a36Sopenharmony_ci 226162306a36Sopenharmony_ci swap %d1 226262306a36Sopenharmony_ci mov.w %d5, %d1 # 2nd quotient 'digit' 226362306a36Sopenharmony_ci clr.w %d5 226462306a36Sopenharmony_ci swap %d5 # now remainder 226562306a36Sopenharmony_ci mov.l %d1, %d6 # and quotient 226662306a36Sopenharmony_ci 226762306a36Sopenharmony_ci rts 226862306a36Sopenharmony_ci 226962306a36Sopenharmony_ciddknuth: 227062306a36Sopenharmony_ci# In this algorithm, the divisor is treated as a 2 digit (word) number 227162306a36Sopenharmony_ci# which is divided into a 3 digit (word) dividend to get one quotient 227262306a36Sopenharmony_ci# digit (word). After subtraction, the dividend is shifted and the 227362306a36Sopenharmony_ci# process repeated. Before beginning, the divisor and quotient are 227462306a36Sopenharmony_ci# 'normalized' so that the process of estimating the quotient digit 227562306a36Sopenharmony_ci# will yield verifiably correct results.. 227662306a36Sopenharmony_ci 227762306a36Sopenharmony_ci clr.l DDNORMAL(%a6) # count of shifts for normalization 227862306a36Sopenharmony_ci clr.b DDSECOND(%a6) # clear flag for quotient digits 227962306a36Sopenharmony_ci clr.l %d1 # %d1 will hold trial quotient 228062306a36Sopenharmony_ciddnchk: 228162306a36Sopenharmony_ci btst &31, %d7 # must we normalize? first word of 228262306a36Sopenharmony_ci bne.b ddnormalized # divisor (V1) must be >= 65536/2 228362306a36Sopenharmony_ci addq.l &0x1, DDNORMAL(%a6) # count normalization shifts 228462306a36Sopenharmony_ci lsl.l &0x1, %d7 # shift the divisor 228562306a36Sopenharmony_ci lsl.l &0x1, %d6 # shift u4,u3 with overflow to u2 228662306a36Sopenharmony_ci roxl.l &0x1, %d5 # shift u1,u2 228762306a36Sopenharmony_ci bra.w ddnchk 228862306a36Sopenharmony_ciddnormalized: 228962306a36Sopenharmony_ci 229062306a36Sopenharmony_ci# Now calculate an estimate of the quotient words (msw first, then lsw). 229162306a36Sopenharmony_ci# The comments use subscripts for the first quotient digit determination. 229262306a36Sopenharmony_ci mov.l %d7, %d3 # divisor 229362306a36Sopenharmony_ci mov.l %d5, %d2 # dividend mslw 229462306a36Sopenharmony_ci swap %d2 229562306a36Sopenharmony_ci swap %d3 229662306a36Sopenharmony_ci cmp.w %d2, %d3 # V1 = U1 ? 229762306a36Sopenharmony_ci bne.b ddqcalc1 229862306a36Sopenharmony_ci mov.w &0xffff, %d1 # use max trial quotient word 229962306a36Sopenharmony_ci bra.b ddadj0 230062306a36Sopenharmony_ciddqcalc1: 230162306a36Sopenharmony_ci mov.l %d5, %d1 230262306a36Sopenharmony_ci 230362306a36Sopenharmony_ci divu.w %d3, %d1 # use quotient of mslw/msw 230462306a36Sopenharmony_ci 230562306a36Sopenharmony_ci andi.l &0x0000ffff, %d1 # zero any remainder 230662306a36Sopenharmony_ciddadj0: 230762306a36Sopenharmony_ci 230862306a36Sopenharmony_ci# now test the trial quotient and adjust. This step plus the 230962306a36Sopenharmony_ci# normalization assures (according to Knuth) that the trial 231062306a36Sopenharmony_ci# quotient will be at worst 1 too large. 231162306a36Sopenharmony_ci mov.l %d6, -(%sp) 231262306a36Sopenharmony_ci clr.w %d6 # word u3 left 231362306a36Sopenharmony_ci swap %d6 # in lsw position 231462306a36Sopenharmony_ciddadj1: mov.l %d7, %d3 231562306a36Sopenharmony_ci mov.l %d1, %d2 231662306a36Sopenharmony_ci mulu.w %d7, %d2 # V2q 231762306a36Sopenharmony_ci swap %d3 231862306a36Sopenharmony_ci mulu.w %d1, %d3 # V1q 231962306a36Sopenharmony_ci mov.l %d5, %d4 # U1U2 232062306a36Sopenharmony_ci sub.l %d3, %d4 # U1U2 - V1q 232162306a36Sopenharmony_ci 232262306a36Sopenharmony_ci swap %d4 232362306a36Sopenharmony_ci 232462306a36Sopenharmony_ci mov.w %d4,%d0 232562306a36Sopenharmony_ci mov.w %d6,%d4 # insert lower word (U3) 232662306a36Sopenharmony_ci 232762306a36Sopenharmony_ci tst.w %d0 # is upper word set? 232862306a36Sopenharmony_ci bne.w ddadjd1 232962306a36Sopenharmony_ci 233062306a36Sopenharmony_ci# add.l %d6, %d4 # (U1U2 - V1q) + U3 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_ci cmp.l %d2, %d4 233362306a36Sopenharmony_ci bls.b ddadjd1 # is V2q > (U1U2-V1q) + U3 ? 233462306a36Sopenharmony_ci subq.l &0x1, %d1 # yes, decrement and recheck 233562306a36Sopenharmony_ci bra.b ddadj1 233662306a36Sopenharmony_ciddadjd1: 233762306a36Sopenharmony_ci# now test the word by multiplying it by the divisor (V1V2) and comparing 233862306a36Sopenharmony_ci# the 3 digit (word) result with the current dividend words 233962306a36Sopenharmony_ci mov.l %d5, -(%sp) # save %d5 (%d6 already saved) 234062306a36Sopenharmony_ci mov.l %d1, %d6 234162306a36Sopenharmony_ci swap %d6 # shift answer to ms 3 words 234262306a36Sopenharmony_ci mov.l %d7, %d5 234362306a36Sopenharmony_ci bsr.l dmm2 234462306a36Sopenharmony_ci mov.l %d5, %d2 # now %d2,%d3 are trial*divisor 234562306a36Sopenharmony_ci mov.l %d6, %d3 234662306a36Sopenharmony_ci mov.l (%sp)+, %d5 # restore dividend 234762306a36Sopenharmony_ci mov.l (%sp)+, %d6 234862306a36Sopenharmony_ci sub.l %d3, %d6 234962306a36Sopenharmony_ci subx.l %d2, %d5 # subtract double precision 235062306a36Sopenharmony_ci bcc dd2nd # no carry, do next quotient digit 235162306a36Sopenharmony_ci subq.l &0x1, %d1 # q is one too large 235262306a36Sopenharmony_ci# need to add back divisor longword to current ms 3 digits of dividend 235362306a36Sopenharmony_ci# - according to Knuth, this is done only 2 out of 65536 times for random 235462306a36Sopenharmony_ci# divisor, dividend selection. 235562306a36Sopenharmony_ci clr.l %d2 235662306a36Sopenharmony_ci mov.l %d7, %d3 235762306a36Sopenharmony_ci swap %d3 235862306a36Sopenharmony_ci clr.w %d3 # %d3 now ls word of divisor 235962306a36Sopenharmony_ci add.l %d3, %d6 # aligned with 3rd word of dividend 236062306a36Sopenharmony_ci addx.l %d2, %d5 236162306a36Sopenharmony_ci mov.l %d7, %d3 236262306a36Sopenharmony_ci clr.w %d3 # %d3 now ms word of divisor 236362306a36Sopenharmony_ci swap %d3 # aligned with 2nd word of dividend 236462306a36Sopenharmony_ci add.l %d3, %d5 236562306a36Sopenharmony_cidd2nd: 236662306a36Sopenharmony_ci tst.b DDSECOND(%a6) # both q words done? 236762306a36Sopenharmony_ci bne.b ddremain 236862306a36Sopenharmony_ci# first quotient digit now correct. store digit and shift the 236962306a36Sopenharmony_ci# (subtracted) dividend 237062306a36Sopenharmony_ci mov.w %d1, DDQUOTIENT(%a6) 237162306a36Sopenharmony_ci clr.l %d1 237262306a36Sopenharmony_ci swap %d5 237362306a36Sopenharmony_ci swap %d6 237462306a36Sopenharmony_ci mov.w %d6, %d5 237562306a36Sopenharmony_ci clr.w %d6 237662306a36Sopenharmony_ci st DDSECOND(%a6) # second digit 237762306a36Sopenharmony_ci bra.w ddnormalized 237862306a36Sopenharmony_ciddremain: 237962306a36Sopenharmony_ci# add 2nd word to quotient, get the remainder. 238062306a36Sopenharmony_ci mov.w %d1, DDQUOTIENT+2(%a6) 238162306a36Sopenharmony_ci# shift down one word/digit to renormalize remainder. 238262306a36Sopenharmony_ci mov.w %d5, %d6 238362306a36Sopenharmony_ci swap %d6 238462306a36Sopenharmony_ci swap %d5 238562306a36Sopenharmony_ci mov.l DDNORMAL(%a6), %d7 # get norm shift count 238662306a36Sopenharmony_ci beq.b ddrn 238762306a36Sopenharmony_ci subq.l &0x1, %d7 # set for loop count 238862306a36Sopenharmony_ciddnlp: 238962306a36Sopenharmony_ci lsr.l &0x1, %d5 # shift into %d6 239062306a36Sopenharmony_ci roxr.l &0x1, %d6 239162306a36Sopenharmony_ci dbf %d7, ddnlp 239262306a36Sopenharmony_ciddrn: 239362306a36Sopenharmony_ci mov.l %d6, %d5 # remainder 239462306a36Sopenharmony_ci mov.l DDQUOTIENT(%a6), %d6 # quotient 239562306a36Sopenharmony_ci 239662306a36Sopenharmony_ci rts 239762306a36Sopenharmony_cidmm2: 239862306a36Sopenharmony_ci# factors for the 32X32->64 multiplication are in %d5 and %d6. 239962306a36Sopenharmony_ci# returns 64 bit result in %d5 (hi) %d6(lo). 240062306a36Sopenharmony_ci# destroys %d2,%d3,%d4. 240162306a36Sopenharmony_ci 240262306a36Sopenharmony_ci# multiply hi,lo words of each factor to get 4 intermediate products 240362306a36Sopenharmony_ci mov.l %d6, %d2 240462306a36Sopenharmony_ci mov.l %d6, %d3 240562306a36Sopenharmony_ci mov.l %d5, %d4 240662306a36Sopenharmony_ci swap %d3 240762306a36Sopenharmony_ci swap %d4 240862306a36Sopenharmony_ci mulu.w %d5, %d6 # %d6 <- lsw*lsw 240962306a36Sopenharmony_ci mulu.w %d3, %d5 # %d5 <- msw-dest*lsw-source 241062306a36Sopenharmony_ci mulu.w %d4, %d2 # %d2 <- msw-source*lsw-dest 241162306a36Sopenharmony_ci mulu.w %d4, %d3 # %d3 <- msw*msw 241262306a36Sopenharmony_ci# now use swap and addx to consolidate to two longwords 241362306a36Sopenharmony_ci clr.l %d4 241462306a36Sopenharmony_ci swap %d6 241562306a36Sopenharmony_ci add.w %d5, %d6 # add msw of l*l to lsw of m*l product 241662306a36Sopenharmony_ci addx.w %d4, %d3 # add any carry to m*m product 241762306a36Sopenharmony_ci add.w %d2, %d6 # add in lsw of other m*l product 241862306a36Sopenharmony_ci addx.w %d4, %d3 # add any carry to m*m product 241962306a36Sopenharmony_ci swap %d6 # %d6 is low 32 bits of final product 242062306a36Sopenharmony_ci clr.w %d5 242162306a36Sopenharmony_ci clr.w %d2 # lsw of two mixed products used, 242262306a36Sopenharmony_ci swap %d5 # now use msws of longwords 242362306a36Sopenharmony_ci swap %d2 242462306a36Sopenharmony_ci add.l %d2, %d5 242562306a36Sopenharmony_ci add.l %d3, %d5 # %d5 now ms 32 bits of final product 242662306a36Sopenharmony_ci rts 242762306a36Sopenharmony_ci 242862306a36Sopenharmony_ci########## 242962306a36Sopenharmony_cidcontrolmodel_s: 243062306a36Sopenharmony_ci movq.l &LONG,%d0 243162306a36Sopenharmony_ci bsr.l _calc_ea # calc <ea> 243262306a36Sopenharmony_ci 243362306a36Sopenharmony_ci cmpi.b SPCOND_FLG(%a6),&immed_flg # immediate addressing mode? 243462306a36Sopenharmony_ci beq.b dimmed # yes 243562306a36Sopenharmony_ci 243662306a36Sopenharmony_ci mov.l %a0,%a2 243762306a36Sopenharmony_ci bsr.l _dmem_read_long # fetch divisor from <ea> 243862306a36Sopenharmony_ci 243962306a36Sopenharmony_ci tst.l %d1 # dfetch error? 244062306a36Sopenharmony_ci bne.b div64_err # yes 244162306a36Sopenharmony_ci 244262306a36Sopenharmony_ci mov.l %d0, %d7 244362306a36Sopenharmony_ci bra.w dgotsrcl 244462306a36Sopenharmony_ci 244562306a36Sopenharmony_ci# we have to split out immediate data here because it must be read using 244662306a36Sopenharmony_ci# imem_read() instead of dmem_read(). this becomes especially important 244762306a36Sopenharmony_ci# if the fetch runs into some deadly fault. 244862306a36Sopenharmony_cidimmed: 244962306a36Sopenharmony_ci addq.l &0x4,EXC_EXTWPTR(%a6) 245062306a36Sopenharmony_ci bsr.l _imem_read_long # read immediate value 245162306a36Sopenharmony_ci 245262306a36Sopenharmony_ci tst.l %d1 # ifetch error? 245362306a36Sopenharmony_ci bne.l isp_iacc # yes 245462306a36Sopenharmony_ci 245562306a36Sopenharmony_ci mov.l %d0,%d7 245662306a36Sopenharmony_ci bra.w dgotsrcl 245762306a36Sopenharmony_ci 245862306a36Sopenharmony_ci########## 245962306a36Sopenharmony_ci 246062306a36Sopenharmony_ci# if dmem_read_long() returns a fail message in d1, the package 246162306a36Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw 246262306a36Sopenharmony_ci# and the failing address to the routine that creates the new frame. 246362306a36Sopenharmony_ci# also, we call isp_restore in case the effective addressing mode was 246462306a36Sopenharmony_ci# (an)+ or -(an) in which case the previous "an" value must be restored. 246562306a36Sopenharmony_ci# FSLW: 246662306a36Sopenharmony_ci# read = true 246762306a36Sopenharmony_ci# size = longword 246862306a36Sopenharmony_ci# TM = data 246962306a36Sopenharmony_ci# software emulation error = true 247062306a36Sopenharmony_cidiv64_err: 247162306a36Sopenharmony_ci bsr.l isp_restore # restore addr reg 247262306a36Sopenharmony_ci mov.l %a2,%a0 # pass failing address 247362306a36Sopenharmony_ci mov.l &0x01010001,%d0 # pass fslw 247462306a36Sopenharmony_ci bra.l isp_dacc 247562306a36Sopenharmony_ci 247662306a36Sopenharmony_ci######################################################################### 247762306a36Sopenharmony_ci# XDEF **************************************************************** # 247862306a36Sopenharmony_ci# _mul64(): routine to emulate mul{u,s}.l <ea>,Dh:Dl 32x32->64 # 247962306a36Sopenharmony_ci# # 248062306a36Sopenharmony_ci# XREF **************************************************************** # 248162306a36Sopenharmony_ci# _calc_ea() - calculate effective address # 248262306a36Sopenharmony_ci# isp_iacc() - handle instruction access error exception # 248362306a36Sopenharmony_ci# isp_dacc() - handle data access error exception # 248462306a36Sopenharmony_ci# isp_restore() - restore An on access error w/ -() or ()+ # 248562306a36Sopenharmony_ci# # 248662306a36Sopenharmony_ci# INPUT *************************************************************** # 248762306a36Sopenharmony_ci# none # 248862306a36Sopenharmony_ci# # 248962306a36Sopenharmony_ci# OUTPUT ************************************************************** # 249062306a36Sopenharmony_ci# If exiting through isp_dacc... # 249162306a36Sopenharmony_ci# a0 = failing address # 249262306a36Sopenharmony_ci# d0 = FSLW # 249362306a36Sopenharmony_ci# else # 249462306a36Sopenharmony_ci# none # 249562306a36Sopenharmony_ci# # 249662306a36Sopenharmony_ci# ALGORITHM *********************************************************** # 249762306a36Sopenharmony_ci# First, decode the operand location. If it's in Dn, fetch from # 249862306a36Sopenharmony_ci# the stack. If it's in memory, use _calc_ea() to calculate the # 249962306a36Sopenharmony_ci# effective address. Use _dmem_read_long() to fetch at that address. # 250062306a36Sopenharmony_ci# Unless the operand is immediate data. Then use _imem_read_long(). # 250162306a36Sopenharmony_ci# Send failures to isp_dacc() or isp_iacc() as appropriate. # 250262306a36Sopenharmony_ci# If the operands are signed, make them unsigned and save the # 250362306a36Sopenharmony_ci# sign info for later. Perform the multiplication using 16x16->32 # 250462306a36Sopenharmony_ci# unsigned multiplies and "add" instructions. Store the high and low # 250562306a36Sopenharmony_ci# portions of the result in the appropriate data registers on the # 250662306a36Sopenharmony_ci# stack. Calculate the condition codes, also. # 250762306a36Sopenharmony_ci# # 250862306a36Sopenharmony_ci######################################################################### 250962306a36Sopenharmony_ci 251062306a36Sopenharmony_ci############# 251162306a36Sopenharmony_ci# mul(u,s)l # 251262306a36Sopenharmony_ci############# 251362306a36Sopenharmony_ci global _mul64 251462306a36Sopenharmony_ci_mul64: 251562306a36Sopenharmony_ci mov.b EXC_OPWORD+1(%a6), %d0 # extract src {mode,reg} 251662306a36Sopenharmony_ci cmpi.b %d0, &0x7 # is src mode Dn or other? 251762306a36Sopenharmony_ci bgt.w mul64_memop # src is in memory 251862306a36Sopenharmony_ci 251962306a36Sopenharmony_ci# multiplier operand in the data register file. 252062306a36Sopenharmony_ci# must extract the register number and fetch the operand from the stack. 252162306a36Sopenharmony_cimul64_regop: 252262306a36Sopenharmony_ci andi.w &0x7, %d0 # extract Dn 252362306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4), %d3 # fetch multiplier 252462306a36Sopenharmony_ci 252562306a36Sopenharmony_ci# multiplier is in %d3. now, extract Dl and Dh fields and fetch the 252662306a36Sopenharmony_ci# multiplicand from the data register specified by Dl. 252762306a36Sopenharmony_cimul64_multiplicand: 252862306a36Sopenharmony_ci mov.w EXC_EXTWORD(%a6), %d2 # fetch ext word 252962306a36Sopenharmony_ci clr.w %d1 # clear Dh reg 253062306a36Sopenharmony_ci mov.b %d2, %d1 # grab Dh 253162306a36Sopenharmony_ci rol.w &0x4, %d2 # align Dl byte 253262306a36Sopenharmony_ci andi.w &0x7, %d2 # extract Dl 253362306a36Sopenharmony_ci 253462306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d2.w*4), %d4 # get multiplicand 253562306a36Sopenharmony_ci 253662306a36Sopenharmony_ci# check for the case of "zero" result early 253762306a36Sopenharmony_ci tst.l %d4 # test multiplicand 253862306a36Sopenharmony_ci beq.w mul64_zero # handle zero separately 253962306a36Sopenharmony_ci tst.l %d3 # test multiplier 254062306a36Sopenharmony_ci beq.w mul64_zero # handle zero separately 254162306a36Sopenharmony_ci 254262306a36Sopenharmony_ci# multiplier is in %d3 and multiplicand is in %d4. 254362306a36Sopenharmony_ci# if the operation is to be signed, then the operands are converted 254462306a36Sopenharmony_ci# to unsigned and the result sign is saved for the end. 254562306a36Sopenharmony_ci clr.b EXC_TEMP(%a6) # clear temp space 254662306a36Sopenharmony_ci btst &0x3, EXC_EXTWORD(%a6) # signed or unsigned? 254762306a36Sopenharmony_ci beq.b mul64_alg # unsigned; skip sgn calc 254862306a36Sopenharmony_ci 254962306a36Sopenharmony_ci tst.l %d3 # is multiplier negative? 255062306a36Sopenharmony_ci bge.b mul64_chk_md_sgn # no 255162306a36Sopenharmony_ci neg.l %d3 # make multiplier positive 255262306a36Sopenharmony_ci ori.b &0x1, EXC_TEMP(%a6) # save multiplier sgn 255362306a36Sopenharmony_ci 255462306a36Sopenharmony_ci# the result sign is the exclusive or of the operand sign bits. 255562306a36Sopenharmony_cimul64_chk_md_sgn: 255662306a36Sopenharmony_ci tst.l %d4 # is multiplicand negative? 255762306a36Sopenharmony_ci bge.b mul64_alg # no 255862306a36Sopenharmony_ci neg.l %d4 # make multiplicand positive 255962306a36Sopenharmony_ci eori.b &0x1, EXC_TEMP(%a6) # calculate correct sign 256062306a36Sopenharmony_ci 256162306a36Sopenharmony_ci######################################################################### 256262306a36Sopenharmony_ci# 63 32 0 # 256362306a36Sopenharmony_ci# ---------------------------- # 256462306a36Sopenharmony_ci# | hi(mplier) * hi(mplicand)| # 256562306a36Sopenharmony_ci# ---------------------------- # 256662306a36Sopenharmony_ci# ----------------------------- # 256762306a36Sopenharmony_ci# | hi(mplier) * lo(mplicand) | # 256862306a36Sopenharmony_ci# ----------------------------- # 256962306a36Sopenharmony_ci# ----------------------------- # 257062306a36Sopenharmony_ci# | lo(mplier) * hi(mplicand) | # 257162306a36Sopenharmony_ci# ----------------------------- # 257262306a36Sopenharmony_ci# | ----------------------------- # 257362306a36Sopenharmony_ci# --|-- | lo(mplier) * lo(mplicand) | # 257462306a36Sopenharmony_ci# | ----------------------------- # 257562306a36Sopenharmony_ci# ======================================================== # 257662306a36Sopenharmony_ci# -------------------------------------------------------- # 257762306a36Sopenharmony_ci# | hi(result) | lo(result) | # 257862306a36Sopenharmony_ci# -------------------------------------------------------- # 257962306a36Sopenharmony_ci######################################################################### 258062306a36Sopenharmony_cimul64_alg: 258162306a36Sopenharmony_ci# load temp registers with operands 258262306a36Sopenharmony_ci mov.l %d3, %d5 # mr in %d5 258362306a36Sopenharmony_ci mov.l %d3, %d6 # mr in %d6 258462306a36Sopenharmony_ci mov.l %d4, %d7 # md in %d7 258562306a36Sopenharmony_ci swap %d6 # hi(mr) in lo %d6 258662306a36Sopenharmony_ci swap %d7 # hi(md) in lo %d7 258762306a36Sopenharmony_ci 258862306a36Sopenharmony_ci# complete necessary multiplies: 258962306a36Sopenharmony_ci mulu.w %d4, %d3 # [1] lo(mr) * lo(md) 259062306a36Sopenharmony_ci mulu.w %d6, %d4 # [2] hi(mr) * lo(md) 259162306a36Sopenharmony_ci mulu.w %d7, %d5 # [3] lo(mr) * hi(md) 259262306a36Sopenharmony_ci mulu.w %d7, %d6 # [4] hi(mr) * hi(md) 259362306a36Sopenharmony_ci 259462306a36Sopenharmony_ci# add lo portions of [2],[3] to hi portion of [1]. 259562306a36Sopenharmony_ci# add carries produced from these adds to [4]. 259662306a36Sopenharmony_ci# lo([1]) is the final lo 16 bits of the result. 259762306a36Sopenharmony_ci clr.l %d7 # load %d7 w/ zero value 259862306a36Sopenharmony_ci swap %d3 # hi([1]) <==> lo([1]) 259962306a36Sopenharmony_ci add.w %d4, %d3 # hi([1]) + lo([2]) 260062306a36Sopenharmony_ci addx.l %d7, %d6 # [4] + carry 260162306a36Sopenharmony_ci add.w %d5, %d3 # hi([1]) + lo([3]) 260262306a36Sopenharmony_ci addx.l %d7, %d6 # [4] + carry 260362306a36Sopenharmony_ci swap %d3 # lo([1]) <==> hi([1]) 260462306a36Sopenharmony_ci 260562306a36Sopenharmony_ci# lo portions of [2],[3] have been added in to final result. 260662306a36Sopenharmony_ci# now, clear lo, put hi in lo reg, and add to [4] 260762306a36Sopenharmony_ci clr.w %d4 # clear lo([2]) 260862306a36Sopenharmony_ci clr.w %d5 # clear hi([3]) 260962306a36Sopenharmony_ci swap %d4 # hi([2]) in lo %d4 261062306a36Sopenharmony_ci swap %d5 # hi([3]) in lo %d5 261162306a36Sopenharmony_ci add.l %d5, %d4 # [4] + hi([2]) 261262306a36Sopenharmony_ci add.l %d6, %d4 # [4] + hi([3]) 261362306a36Sopenharmony_ci 261462306a36Sopenharmony_ci# unsigned result is now in {%d4,%d3} 261562306a36Sopenharmony_ci tst.b EXC_TEMP(%a6) # should result be signed? 261662306a36Sopenharmony_ci beq.b mul64_done # no 261762306a36Sopenharmony_ci 261862306a36Sopenharmony_ci# result should be a signed negative number. 261962306a36Sopenharmony_ci# compute 2's complement of the unsigned number: 262062306a36Sopenharmony_ci# -negate all bits and add 1 262162306a36Sopenharmony_cimul64_neg: 262262306a36Sopenharmony_ci not.l %d3 # negate lo(result) bits 262362306a36Sopenharmony_ci not.l %d4 # negate hi(result) bits 262462306a36Sopenharmony_ci addq.l &1, %d3 # add 1 to lo(result) 262562306a36Sopenharmony_ci addx.l %d7, %d4 # add carry to hi(result) 262662306a36Sopenharmony_ci 262762306a36Sopenharmony_ci# the result is saved to the register file. 262862306a36Sopenharmony_ci# for '040 compatibility, if Dl == Dh then only the hi(result) is 262962306a36Sopenharmony_ci# saved. so, saving hi after lo accomplishes this without need to 263062306a36Sopenharmony_ci# check Dl,Dh equality. 263162306a36Sopenharmony_cimul64_done: 263262306a36Sopenharmony_ci mov.l %d3, (EXC_DREGS,%a6,%d2.w*4) # save lo(result) 263362306a36Sopenharmony_ci mov.w &0x0, %cc 263462306a36Sopenharmony_ci mov.l %d4, (EXC_DREGS,%a6,%d1.w*4) # save hi(result) 263562306a36Sopenharmony_ci 263662306a36Sopenharmony_ci# now, grab the condition codes. only one that can be set is 'N'. 263762306a36Sopenharmony_ci# 'N' CAN be set if the operation is unsigned if bit 63 is set. 263862306a36Sopenharmony_ci mov.w %cc, %d7 # fetch %ccr to see if 'N' set 263962306a36Sopenharmony_ci andi.b &0x8, %d7 # extract 'N' bit 264062306a36Sopenharmony_ci 264162306a36Sopenharmony_cimul64_ccode_set: 264262306a36Sopenharmony_ci mov.b EXC_CC+1(%a6), %d6 # fetch previous %ccr 264362306a36Sopenharmony_ci andi.b &0x10, %d6 # all but 'X' bit changes 264462306a36Sopenharmony_ci 264562306a36Sopenharmony_ci or.b %d7, %d6 # group 'X' and 'N' 264662306a36Sopenharmony_ci mov.b %d6, EXC_CC+1(%a6) # save new %ccr 264762306a36Sopenharmony_ci 264862306a36Sopenharmony_ci rts 264962306a36Sopenharmony_ci 265062306a36Sopenharmony_ci# one or both of the operands is zero so the result is also zero. 265162306a36Sopenharmony_ci# save the zero result to the register file and set the 'Z' ccode bit. 265262306a36Sopenharmony_cimul64_zero: 265362306a36Sopenharmony_ci clr.l (EXC_DREGS,%a6,%d2.w*4) # save lo(result) 265462306a36Sopenharmony_ci clr.l (EXC_DREGS,%a6,%d1.w*4) # save hi(result) 265562306a36Sopenharmony_ci 265662306a36Sopenharmony_ci movq.l &0x4, %d7 # set 'Z' ccode bit 265762306a36Sopenharmony_ci bra.b mul64_ccode_set # finish ccode set 265862306a36Sopenharmony_ci 265962306a36Sopenharmony_ci########## 266062306a36Sopenharmony_ci 266162306a36Sopenharmony_ci# multiplier operand is in memory at the effective address. 266262306a36Sopenharmony_ci# must calculate the <ea> and go fetch the 32-bit operand. 266362306a36Sopenharmony_cimul64_memop: 266462306a36Sopenharmony_ci movq.l &LONG, %d0 # pass # of bytes 266562306a36Sopenharmony_ci bsr.l _calc_ea # calculate <ea> 266662306a36Sopenharmony_ci 266762306a36Sopenharmony_ci cmpi.b SPCOND_FLG(%a6),&immed_flg # immediate addressing mode? 266862306a36Sopenharmony_ci beq.b mul64_immed # yes 266962306a36Sopenharmony_ci 267062306a36Sopenharmony_ci mov.l %a0,%a2 267162306a36Sopenharmony_ci bsr.l _dmem_read_long # fetch src from addr (%a0) 267262306a36Sopenharmony_ci 267362306a36Sopenharmony_ci tst.l %d1 # dfetch error? 267462306a36Sopenharmony_ci bne.w mul64_err # yes 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_ci mov.l %d0, %d3 # store multiplier in %d3 267762306a36Sopenharmony_ci 267862306a36Sopenharmony_ci bra.w mul64_multiplicand 267962306a36Sopenharmony_ci 268062306a36Sopenharmony_ci# we have to split out immediate data here because it must be read using 268162306a36Sopenharmony_ci# imem_read() instead of dmem_read(). this becomes especially important 268262306a36Sopenharmony_ci# if the fetch runs into some deadly fault. 268362306a36Sopenharmony_cimul64_immed: 268462306a36Sopenharmony_ci addq.l &0x4,EXC_EXTWPTR(%a6) 268562306a36Sopenharmony_ci bsr.l _imem_read_long # read immediate value 268662306a36Sopenharmony_ci 268762306a36Sopenharmony_ci tst.l %d1 # ifetch error? 268862306a36Sopenharmony_ci bne.l isp_iacc # yes 268962306a36Sopenharmony_ci 269062306a36Sopenharmony_ci mov.l %d0,%d3 269162306a36Sopenharmony_ci bra.w mul64_multiplicand 269262306a36Sopenharmony_ci 269362306a36Sopenharmony_ci########## 269462306a36Sopenharmony_ci 269562306a36Sopenharmony_ci# if dmem_read_long() returns a fail message in d1, the package 269662306a36Sopenharmony_ci# must create an access error frame. here, we pass a skeleton fslw 269762306a36Sopenharmony_ci# and the failing address to the routine that creates the new frame. 269862306a36Sopenharmony_ci# also, we call isp_restore in case the effective addressing mode was 269962306a36Sopenharmony_ci# (an)+ or -(an) in which case the previous "an" value must be restored. 270062306a36Sopenharmony_ci# FSLW: 270162306a36Sopenharmony_ci# read = true 270262306a36Sopenharmony_ci# size = longword 270362306a36Sopenharmony_ci# TM = data 270462306a36Sopenharmony_ci# software emulation error = true 270562306a36Sopenharmony_cimul64_err: 270662306a36Sopenharmony_ci bsr.l isp_restore # restore addr reg 270762306a36Sopenharmony_ci mov.l %a2,%a0 # pass failing address 270862306a36Sopenharmony_ci mov.l &0x01010001,%d0 # pass fslw 270962306a36Sopenharmony_ci bra.l isp_dacc 271062306a36Sopenharmony_ci 271162306a36Sopenharmony_ci######################################################################### 271262306a36Sopenharmony_ci# XDEF **************************************************************** # 271362306a36Sopenharmony_ci# _compandset2(): routine to emulate cas2() # 271462306a36Sopenharmony_ci# (internal to package) # 271562306a36Sopenharmony_ci# # 271662306a36Sopenharmony_ci# _isp_cas2_finish(): store ccodes, store compare regs # 271762306a36Sopenharmony_ci# (external to package) # 271862306a36Sopenharmony_ci# # 271962306a36Sopenharmony_ci# XREF **************************************************************** # 272062306a36Sopenharmony_ci# _real_lock_page() - "callout" to lock op's page from page-outs # 272162306a36Sopenharmony_ci# _cas_terminate2() - access error exit # 272262306a36Sopenharmony_ci# _real_cas2() - "callout" to core cas2 emulation code # 272362306a36Sopenharmony_ci# _real_unlock_page() - "callout" to unlock page # 272462306a36Sopenharmony_ci# # 272562306a36Sopenharmony_ci# INPUT *************************************************************** # 272662306a36Sopenharmony_ci# _compandset2(): # 272762306a36Sopenharmony_ci# d0 = instruction extension word # 272862306a36Sopenharmony_ci# # 272962306a36Sopenharmony_ci# _isp_cas2_finish(): # 273062306a36Sopenharmony_ci# see cas2 core emulation code # 273162306a36Sopenharmony_ci# # 273262306a36Sopenharmony_ci# OUTPUT ************************************************************** # 273362306a36Sopenharmony_ci# _compandset2(): # 273462306a36Sopenharmony_ci# see cas2 core emulation code # 273562306a36Sopenharmony_ci# # 273662306a36Sopenharmony_ci# _isp_cas_finish(): # 273762306a36Sopenharmony_ci# None (register file or memroy changed as appropriate) # 273862306a36Sopenharmony_ci# # 273962306a36Sopenharmony_ci# ALGORITHM *********************************************************** # 274062306a36Sopenharmony_ci# compandset2(): # 274162306a36Sopenharmony_ci# Decode the instruction and fetch the appropriate Update and # 274262306a36Sopenharmony_ci# Compare operands. Then call the "callout" _real_lock_page() for each # 274362306a36Sopenharmony_ci# memory operand address so that the operating system can keep these # 274462306a36Sopenharmony_ci# pages from being paged out. If either _real_lock_page() fails, exit # 274562306a36Sopenharmony_ci# through _cas_terminate2(). Don't forget to unlock the 1st locked page # 274662306a36Sopenharmony_ci# using _real_unlock_paged() if the 2nd lock-page fails. # 274762306a36Sopenharmony_ci# Finally, branch to the core cas2 emulation code by calling the # 274862306a36Sopenharmony_ci# "callout" _real_cas2(). # 274962306a36Sopenharmony_ci# # 275062306a36Sopenharmony_ci# _isp_cas2_finish(): # 275162306a36Sopenharmony_ci# Re-perform the comparison so we can determine the condition # 275262306a36Sopenharmony_ci# codes which were too much trouble to keep around during the locked # 275362306a36Sopenharmony_ci# emulation. Then unlock each operands page by calling the "callout" # 275462306a36Sopenharmony_ci# _real_unlock_page(). # 275562306a36Sopenharmony_ci# # 275662306a36Sopenharmony_ci######################################################################### 275762306a36Sopenharmony_ci 275862306a36Sopenharmony_ciset ADDR1, EXC_TEMP+0xc 275962306a36Sopenharmony_ciset ADDR2, EXC_TEMP+0x0 276062306a36Sopenharmony_ciset DC2, EXC_TEMP+0xa 276162306a36Sopenharmony_ciset DC1, EXC_TEMP+0x8 276262306a36Sopenharmony_ci 276362306a36Sopenharmony_ci global _compandset2 276462306a36Sopenharmony_ci_compandset2: 276562306a36Sopenharmony_ci mov.l %d0,EXC_TEMP+0x4(%a6) # store for possible restart 276662306a36Sopenharmony_ci mov.l %d0,%d1 # extension word in d0 276762306a36Sopenharmony_ci 276862306a36Sopenharmony_ci rol.w &0x4,%d0 276962306a36Sopenharmony_ci andi.w &0xf,%d0 # extract Rn2 277062306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4),%a1 # fetch ADDR2 277162306a36Sopenharmony_ci mov.l %a1,ADDR2(%a6) 277262306a36Sopenharmony_ci 277362306a36Sopenharmony_ci mov.l %d1,%d0 277462306a36Sopenharmony_ci 277562306a36Sopenharmony_ci lsr.w &0x6,%d1 277662306a36Sopenharmony_ci andi.w &0x7,%d1 # extract Du2 277762306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d1.w*4),%d5 # fetch Update2 Op 277862306a36Sopenharmony_ci 277962306a36Sopenharmony_ci andi.w &0x7,%d0 # extract Dc2 278062306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4),%d3 # fetch Compare2 Op 278162306a36Sopenharmony_ci mov.w %d0,DC2(%a6) 278262306a36Sopenharmony_ci 278362306a36Sopenharmony_ci mov.w EXC_EXTWORD(%a6),%d0 278462306a36Sopenharmony_ci mov.l %d0,%d1 278562306a36Sopenharmony_ci 278662306a36Sopenharmony_ci rol.w &0x4,%d0 278762306a36Sopenharmony_ci andi.w &0xf,%d0 # extract Rn1 278862306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4),%a0 # fetch ADDR1 278962306a36Sopenharmony_ci mov.l %a0,ADDR1(%a6) 279062306a36Sopenharmony_ci 279162306a36Sopenharmony_ci mov.l %d1,%d0 279262306a36Sopenharmony_ci 279362306a36Sopenharmony_ci lsr.w &0x6,%d1 279462306a36Sopenharmony_ci andi.w &0x7,%d1 # extract Du1 279562306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d1.w*4),%d4 # fetch Update1 Op 279662306a36Sopenharmony_ci 279762306a36Sopenharmony_ci andi.w &0x7,%d0 # extract Dc1 279862306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4),%d2 # fetch Compare1 Op 279962306a36Sopenharmony_ci mov.w %d0,DC1(%a6) 280062306a36Sopenharmony_ci 280162306a36Sopenharmony_ci btst &0x1,EXC_OPWORD(%a6) # word or long? 280262306a36Sopenharmony_ci sne %d7 280362306a36Sopenharmony_ci 280462306a36Sopenharmony_ci btst &0x5,EXC_ISR(%a6) # user or supervisor? 280562306a36Sopenharmony_ci sne %d6 280662306a36Sopenharmony_ci 280762306a36Sopenharmony_ci mov.l %a0,%a2 280862306a36Sopenharmony_ci mov.l %a1,%a3 280962306a36Sopenharmony_ci 281062306a36Sopenharmony_ci mov.l %d7,%d1 # pass size 281162306a36Sopenharmony_ci mov.l %d6,%d0 # pass mode 281262306a36Sopenharmony_ci bsr.l _real_lock_page # lock page 281362306a36Sopenharmony_ci mov.l %a2,%a0 281462306a36Sopenharmony_ci tst.l %d0 # error? 281562306a36Sopenharmony_ci bne.l _cas_terminate2 # yes 281662306a36Sopenharmony_ci 281762306a36Sopenharmony_ci mov.l %d7,%d1 # pass size 281862306a36Sopenharmony_ci mov.l %d6,%d0 # pass mode 281962306a36Sopenharmony_ci mov.l %a3,%a0 # pass addr 282062306a36Sopenharmony_ci bsr.l _real_lock_page # lock page 282162306a36Sopenharmony_ci mov.l %a3,%a0 282262306a36Sopenharmony_ci tst.l %d0 # error? 282362306a36Sopenharmony_ci bne.b cas_preterm # yes 282462306a36Sopenharmony_ci 282562306a36Sopenharmony_ci mov.l %a2,%a0 282662306a36Sopenharmony_ci mov.l %a3,%a1 282762306a36Sopenharmony_ci 282862306a36Sopenharmony_ci bra.l _real_cas2 282962306a36Sopenharmony_ci 283062306a36Sopenharmony_ci# if the 2nd lock attempt fails, then we must still unlock the 283162306a36Sopenharmony_ci# first page(s). 283262306a36Sopenharmony_cicas_preterm: 283362306a36Sopenharmony_ci mov.l %d0,-(%sp) # save FSLW 283462306a36Sopenharmony_ci mov.l %d7,%d1 # pass size 283562306a36Sopenharmony_ci mov.l %d6,%d0 # pass mode 283662306a36Sopenharmony_ci mov.l %a2,%a0 # pass ADDR1 283762306a36Sopenharmony_ci bsr.l _real_unlock_page # unlock first page(s) 283862306a36Sopenharmony_ci mov.l (%sp)+,%d0 # restore FSLW 283962306a36Sopenharmony_ci mov.l %a3,%a0 # pass failing addr 284062306a36Sopenharmony_ci bra.l _cas_terminate2 284162306a36Sopenharmony_ci 284262306a36Sopenharmony_ci############################################################# 284362306a36Sopenharmony_ci 284462306a36Sopenharmony_ci global _isp_cas2_finish 284562306a36Sopenharmony_ci_isp_cas2_finish: 284662306a36Sopenharmony_ci btst &0x1,EXC_OPWORD(%a6) 284762306a36Sopenharmony_ci bne.b cas2_finish_l 284862306a36Sopenharmony_ci 284962306a36Sopenharmony_ci mov.w EXC_CC(%a6),%cc # load old ccodes 285062306a36Sopenharmony_ci cmp.w %d0,%d2 285162306a36Sopenharmony_ci bne.b cas2_finish_w_save 285262306a36Sopenharmony_ci cmp.w %d1,%d3 285362306a36Sopenharmony_cicas2_finish_w_save: 285462306a36Sopenharmony_ci mov.w %cc,EXC_CC(%a6) # save new ccodes 285562306a36Sopenharmony_ci 285662306a36Sopenharmony_ci tst.b %d4 # update compare reg? 285762306a36Sopenharmony_ci bne.b cas2_finish_w_done # no 285862306a36Sopenharmony_ci 285962306a36Sopenharmony_ci mov.w DC2(%a6),%d3 # fetch Dc2 286062306a36Sopenharmony_ci mov.w %d1,(2+EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op 286162306a36Sopenharmony_ci 286262306a36Sopenharmony_ci mov.w DC1(%a6),%d2 # fetch Dc1 286362306a36Sopenharmony_ci mov.w %d0,(2+EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op 286462306a36Sopenharmony_ci 286562306a36Sopenharmony_cicas2_finish_w_done: 286662306a36Sopenharmony_ci btst &0x5,EXC_ISR(%a6) 286762306a36Sopenharmony_ci sne %d2 286862306a36Sopenharmony_ci mov.l %d2,%d0 # pass mode 286962306a36Sopenharmony_ci sf %d1 # pass size 287062306a36Sopenharmony_ci mov.l ADDR1(%a6),%a0 # pass ADDR1 287162306a36Sopenharmony_ci bsr.l _real_unlock_page # unlock page 287262306a36Sopenharmony_ci 287362306a36Sopenharmony_ci mov.l %d2,%d0 # pass mode 287462306a36Sopenharmony_ci sf %d1 # pass size 287562306a36Sopenharmony_ci mov.l ADDR2(%a6),%a0 # pass ADDR2 287662306a36Sopenharmony_ci bsr.l _real_unlock_page # unlock page 287762306a36Sopenharmony_ci rts 287862306a36Sopenharmony_ci 287962306a36Sopenharmony_cicas2_finish_l: 288062306a36Sopenharmony_ci mov.w EXC_CC(%a6),%cc # load old ccodes 288162306a36Sopenharmony_ci cmp.l %d0,%d2 288262306a36Sopenharmony_ci bne.b cas2_finish_l_save 288362306a36Sopenharmony_ci cmp.l %d1,%d3 288462306a36Sopenharmony_cicas2_finish_l_save: 288562306a36Sopenharmony_ci mov.w %cc,EXC_CC(%a6) # save new ccodes 288662306a36Sopenharmony_ci 288762306a36Sopenharmony_ci tst.b %d4 # update compare reg? 288862306a36Sopenharmony_ci bne.b cas2_finish_l_done # no 288962306a36Sopenharmony_ci 289062306a36Sopenharmony_ci mov.w DC2(%a6),%d3 # fetch Dc2 289162306a36Sopenharmony_ci mov.l %d1,(EXC_DREGS,%a6,%d3.w*4) # store new Compare2 Op 289262306a36Sopenharmony_ci 289362306a36Sopenharmony_ci mov.w DC1(%a6),%d2 # fetch Dc1 289462306a36Sopenharmony_ci mov.l %d0,(EXC_DREGS,%a6,%d2.w*4) # store new Compare1 Op 289562306a36Sopenharmony_ci 289662306a36Sopenharmony_cicas2_finish_l_done: 289762306a36Sopenharmony_ci btst &0x5,EXC_ISR(%a6) 289862306a36Sopenharmony_ci sne %d2 289962306a36Sopenharmony_ci mov.l %d2,%d0 # pass mode 290062306a36Sopenharmony_ci st %d1 # pass size 290162306a36Sopenharmony_ci mov.l ADDR1(%a6),%a0 # pass ADDR1 290262306a36Sopenharmony_ci bsr.l _real_unlock_page # unlock page 290362306a36Sopenharmony_ci 290462306a36Sopenharmony_ci mov.l %d2,%d0 # pass mode 290562306a36Sopenharmony_ci st %d1 # pass size 290662306a36Sopenharmony_ci mov.l ADDR2(%a6),%a0 # pass ADDR2 290762306a36Sopenharmony_ci bsr.l _real_unlock_page # unlock page 290862306a36Sopenharmony_ci rts 290962306a36Sopenharmony_ci 291062306a36Sopenharmony_ci######## 291162306a36Sopenharmony_ci global cr_cas2 291262306a36Sopenharmony_cicr_cas2: 291362306a36Sopenharmony_ci mov.l EXC_TEMP+0x4(%a6),%d0 291462306a36Sopenharmony_ci bra.w _compandset2 291562306a36Sopenharmony_ci 291662306a36Sopenharmony_ci######################################################################### 291762306a36Sopenharmony_ci# XDEF **************************************************************** # 291862306a36Sopenharmony_ci# _compandset(): routine to emulate cas w/ misaligned <ea> # 291962306a36Sopenharmony_ci# (internal to package) # 292062306a36Sopenharmony_ci# _isp_cas_finish(): routine called when cas emulation completes # 292162306a36Sopenharmony_ci# (external and internal to package) # 292262306a36Sopenharmony_ci# _isp_cas_restart(): restart cas emulation after a fault # 292362306a36Sopenharmony_ci# (external to package) # 292462306a36Sopenharmony_ci# _isp_cas_terminate(): create access error stack frame on fault # 292562306a36Sopenharmony_ci# (external and internal to package) # 292662306a36Sopenharmony_ci# _isp_cas_inrange(): checks whether instr addess is within range # 292762306a36Sopenharmony_ci# of core cas/cas2emulation code # 292862306a36Sopenharmony_ci# (external to package) # 292962306a36Sopenharmony_ci# # 293062306a36Sopenharmony_ci# XREF **************************************************************** # 293162306a36Sopenharmony_ci# _calc_ea(): calculate effective address # 293262306a36Sopenharmony_ci# # 293362306a36Sopenharmony_ci# INPUT *************************************************************** # 293462306a36Sopenharmony_ci# compandset(): # 293562306a36Sopenharmony_ci# none # 293662306a36Sopenharmony_ci# _isp_cas_restart(): # 293762306a36Sopenharmony_ci# d6 = previous sfc/dfc # 293862306a36Sopenharmony_ci# _isp_cas_finish(): # 293962306a36Sopenharmony_ci# _isp_cas_terminate(): # 294062306a36Sopenharmony_ci# a0 = failing address # 294162306a36Sopenharmony_ci# d0 = FSLW # 294262306a36Sopenharmony_ci# d6 = previous sfc/dfc # 294362306a36Sopenharmony_ci# _isp_cas_inrange(): # 294462306a36Sopenharmony_ci# a0 = instruction address to be checked # 294562306a36Sopenharmony_ci# # 294662306a36Sopenharmony_ci# OUTPUT ************************************************************** # 294762306a36Sopenharmony_ci# compandset(): # 294862306a36Sopenharmony_ci# none # 294962306a36Sopenharmony_ci# _isp_cas_restart(): # 295062306a36Sopenharmony_ci# a0 = effective address # 295162306a36Sopenharmony_ci# d7 = word or longword flag # 295262306a36Sopenharmony_ci# _isp_cas_finish(): # 295362306a36Sopenharmony_ci# a0 = effective address # 295462306a36Sopenharmony_ci# _isp_cas_terminate(): # 295562306a36Sopenharmony_ci# initial register set before emulation exception # 295662306a36Sopenharmony_ci# _isp_cas_inrange(): # 295762306a36Sopenharmony_ci# d0 = 0 => in range; -1 => out of range # 295862306a36Sopenharmony_ci# # 295962306a36Sopenharmony_ci# ALGORITHM *********************************************************** # 296062306a36Sopenharmony_ci# # 296162306a36Sopenharmony_ci# compandset(): # 296262306a36Sopenharmony_ci# First, calculate the effective address. Then, decode the # 296362306a36Sopenharmony_ci# instruction word and fetch the "compare" (DC) and "update" (Du) # 296462306a36Sopenharmony_ci# operands. # 296562306a36Sopenharmony_ci# Next, call the external routine _real_lock_page() so that the # 296662306a36Sopenharmony_ci# operating system can keep this page from being paged out while we're # 296762306a36Sopenharmony_ci# in this routine. If this call fails, jump to _cas_terminate2(). # 296862306a36Sopenharmony_ci# The routine then branches to _real_cas(). This external routine # 296962306a36Sopenharmony_ci# that actually emulates cas can be supplied by the external os or # 297062306a36Sopenharmony_ci# made to point directly back into the 060ISP which has a routine for # 297162306a36Sopenharmony_ci# this purpose. # 297262306a36Sopenharmony_ci# # 297362306a36Sopenharmony_ci# _isp_cas_finish(): # 297462306a36Sopenharmony_ci# Either way, after emulation, the package is re-entered at # 297562306a36Sopenharmony_ci# _isp_cas_finish(). This routine re-compares the operands in order to # 297662306a36Sopenharmony_ci# set the condition codes. Finally, these routines will call # 297762306a36Sopenharmony_ci# _real_unlock_page() in order to unlock the pages that were previously # 297862306a36Sopenharmony_ci# locked. # 297962306a36Sopenharmony_ci# # 298062306a36Sopenharmony_ci# _isp_cas_restart(): # 298162306a36Sopenharmony_ci# This routine can be entered from an access error handler where # 298262306a36Sopenharmony_ci# the emulation sequence should be re-started from the beginning. # 298362306a36Sopenharmony_ci# # 298462306a36Sopenharmony_ci# _isp_cas_terminate(): # 298562306a36Sopenharmony_ci# This routine can be entered from an access error handler where # 298662306a36Sopenharmony_ci# an emulation operand access failed and the operating system would # 298762306a36Sopenharmony_ci# like an access error stack frame created instead of the current # 298862306a36Sopenharmony_ci# unimplemented integer instruction frame. # 298962306a36Sopenharmony_ci# Also, the package enters here if a call to _real_lock_page() # 299062306a36Sopenharmony_ci# fails. # 299162306a36Sopenharmony_ci# # 299262306a36Sopenharmony_ci# _isp_cas_inrange(): # 299362306a36Sopenharmony_ci# Checks to see whether the instruction address passed to it in # 299462306a36Sopenharmony_ci# a0 is within the software package cas/cas2 emulation routines. This # 299562306a36Sopenharmony_ci# can be helpful for an operating system to determine whether an access # 299662306a36Sopenharmony_ci# error during emulation was due to a cas/cas2 emulation access. # 299762306a36Sopenharmony_ci# # 299862306a36Sopenharmony_ci######################################################################### 299962306a36Sopenharmony_ci 300062306a36Sopenharmony_ciset DC, EXC_TEMP+0x8 300162306a36Sopenharmony_ciset ADDR, EXC_TEMP+0x4 300262306a36Sopenharmony_ci 300362306a36Sopenharmony_ci global _compandset 300462306a36Sopenharmony_ci_compandset: 300562306a36Sopenharmony_ci btst &0x1,EXC_OPWORD(%a6) # word or long operation? 300662306a36Sopenharmony_ci bne.b compandsetl # long 300762306a36Sopenharmony_ci 300862306a36Sopenharmony_cicompandsetw: 300962306a36Sopenharmony_ci movq.l &0x2,%d0 # size = 2 bytes 301062306a36Sopenharmony_ci bsr.l _calc_ea # a0 = calculated <ea> 301162306a36Sopenharmony_ci mov.l %a0,ADDR(%a6) # save <ea> for possible restart 301262306a36Sopenharmony_ci sf %d7 # clear d7 for word size 301362306a36Sopenharmony_ci bra.b compandsetfetch 301462306a36Sopenharmony_ci 301562306a36Sopenharmony_cicompandsetl: 301662306a36Sopenharmony_ci movq.l &0x4,%d0 # size = 4 bytes 301762306a36Sopenharmony_ci bsr.l _calc_ea # a0 = calculated <ea> 301862306a36Sopenharmony_ci mov.l %a0,ADDR(%a6) # save <ea> for possible restart 301962306a36Sopenharmony_ci st %d7 # set d7 for longword size 302062306a36Sopenharmony_ci 302162306a36Sopenharmony_cicompandsetfetch: 302262306a36Sopenharmony_ci mov.w EXC_EXTWORD(%a6),%d0 # fetch cas extension word 302362306a36Sopenharmony_ci mov.l %d0,%d1 # make a copy 302462306a36Sopenharmony_ci 302562306a36Sopenharmony_ci lsr.w &0x6,%d0 302662306a36Sopenharmony_ci andi.w &0x7,%d0 # extract Du 302762306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d0.w*4),%d2 # get update operand 302862306a36Sopenharmony_ci 302962306a36Sopenharmony_ci andi.w &0x7,%d1 # extract Dc 303062306a36Sopenharmony_ci mov.l (EXC_DREGS,%a6,%d1.w*4),%d4 # get compare operand 303162306a36Sopenharmony_ci mov.w %d1,DC(%a6) # save Dc 303262306a36Sopenharmony_ci 303362306a36Sopenharmony_ci btst &0x5,EXC_ISR(%a6) # which mode for exception? 303462306a36Sopenharmony_ci sne %d6 # set on supervisor mode 303562306a36Sopenharmony_ci 303662306a36Sopenharmony_ci mov.l %a0,%a2 # save temporarily 303762306a36Sopenharmony_ci mov.l %d7,%d1 # pass size 303862306a36Sopenharmony_ci mov.l %d6,%d0 # pass mode 303962306a36Sopenharmony_ci bsr.l _real_lock_page # lock page 304062306a36Sopenharmony_ci tst.l %d0 # did error occur? 304162306a36Sopenharmony_ci bne.w _cas_terminate2 # yes, clean up the mess 304262306a36Sopenharmony_ci mov.l %a2,%a0 # pass addr in a0 304362306a36Sopenharmony_ci 304462306a36Sopenharmony_ci bra.l _real_cas 304562306a36Sopenharmony_ci 304662306a36Sopenharmony_ci######## 304762306a36Sopenharmony_ci global _isp_cas_finish 304862306a36Sopenharmony_ci_isp_cas_finish: 304962306a36Sopenharmony_ci btst &0x1,EXC_OPWORD(%a6) 305062306a36Sopenharmony_ci bne.b cas_finish_l 305162306a36Sopenharmony_ci 305262306a36Sopenharmony_ci# just do the compare again since it's faster than saving the ccodes 305362306a36Sopenharmony_ci# from the locked routine... 305462306a36Sopenharmony_cicas_finish_w: 305562306a36Sopenharmony_ci mov.w EXC_CC(%a6),%cc # restore cc 305662306a36Sopenharmony_ci cmp.w %d0,%d4 # do word compare 305762306a36Sopenharmony_ci mov.w %cc,EXC_CC(%a6) # save cc 305862306a36Sopenharmony_ci 305962306a36Sopenharmony_ci tst.b %d1 # update compare reg? 306062306a36Sopenharmony_ci bne.b cas_finish_w_done # no 306162306a36Sopenharmony_ci 306262306a36Sopenharmony_ci mov.w DC(%a6),%d3 306362306a36Sopenharmony_ci mov.w %d0,(EXC_DREGS+2,%a6,%d3.w*4) # Dc = destination 306462306a36Sopenharmony_ci 306562306a36Sopenharmony_cicas_finish_w_done: 306662306a36Sopenharmony_ci mov.l ADDR(%a6),%a0 # pass addr 306762306a36Sopenharmony_ci sf %d1 # pass size 306862306a36Sopenharmony_ci btst &0x5,EXC_ISR(%a6) 306962306a36Sopenharmony_ci sne %d0 # pass mode 307062306a36Sopenharmony_ci bsr.l _real_unlock_page # unlock page 307162306a36Sopenharmony_ci rts 307262306a36Sopenharmony_ci 307362306a36Sopenharmony_ci# just do the compare again since it's faster than saving the ccodes 307462306a36Sopenharmony_ci# from the locked routine... 307562306a36Sopenharmony_cicas_finish_l: 307662306a36Sopenharmony_ci mov.w EXC_CC(%a6),%cc # restore cc 307762306a36Sopenharmony_ci cmp.l %d0,%d4 # do longword compare 307862306a36Sopenharmony_ci mov.w %cc,EXC_CC(%a6) # save cc 307962306a36Sopenharmony_ci 308062306a36Sopenharmony_ci tst.b %d1 # update compare reg? 308162306a36Sopenharmony_ci bne.b cas_finish_l_done # no 308262306a36Sopenharmony_ci 308362306a36Sopenharmony_ci mov.w DC(%a6),%d3 308462306a36Sopenharmony_ci mov.l %d0,(EXC_DREGS,%a6,%d3.w*4) # Dc = destination 308562306a36Sopenharmony_ci 308662306a36Sopenharmony_cicas_finish_l_done: 308762306a36Sopenharmony_ci mov.l ADDR(%a6),%a0 # pass addr 308862306a36Sopenharmony_ci st %d1 # pass size 308962306a36Sopenharmony_ci btst &0x5,EXC_ISR(%a6) 309062306a36Sopenharmony_ci sne %d0 # pass mode 309162306a36Sopenharmony_ci bsr.l _real_unlock_page # unlock page 309262306a36Sopenharmony_ci rts 309362306a36Sopenharmony_ci 309462306a36Sopenharmony_ci######## 309562306a36Sopenharmony_ci 309662306a36Sopenharmony_ci global _isp_cas_restart 309762306a36Sopenharmony_ci_isp_cas_restart: 309862306a36Sopenharmony_ci mov.l %d6,%sfc # restore previous sfc 309962306a36Sopenharmony_ci mov.l %d6,%dfc # restore previous dfc 310062306a36Sopenharmony_ci 310162306a36Sopenharmony_ci cmpi.b EXC_OPWORD+1(%a6),&0xfc # cas or cas2? 310262306a36Sopenharmony_ci beq.l cr_cas2 # cas2 310362306a36Sopenharmony_cicr_cas: 310462306a36Sopenharmony_ci mov.l ADDR(%a6),%a0 # load <ea> 310562306a36Sopenharmony_ci btst &0x1,EXC_OPWORD(%a6) # word or long operation? 310662306a36Sopenharmony_ci sne %d7 # set d7 accordingly 310762306a36Sopenharmony_ci bra.w compandsetfetch 310862306a36Sopenharmony_ci 310962306a36Sopenharmony_ci######## 311062306a36Sopenharmony_ci 311162306a36Sopenharmony_ci# At this stage, it would be nice if d0 held the FSLW. 311262306a36Sopenharmony_ci global _isp_cas_terminate 311362306a36Sopenharmony_ci_isp_cas_terminate: 311462306a36Sopenharmony_ci mov.l %d6,%sfc # restore previous sfc 311562306a36Sopenharmony_ci mov.l %d6,%dfc # restore previous dfc 311662306a36Sopenharmony_ci 311762306a36Sopenharmony_ci global _cas_terminate2 311862306a36Sopenharmony_ci_cas_terminate2: 311962306a36Sopenharmony_ci mov.l %a0,%a2 # copy failing addr to a2 312062306a36Sopenharmony_ci 312162306a36Sopenharmony_ci mov.l %d0,-(%sp) 312262306a36Sopenharmony_ci bsr.l isp_restore # restore An (if ()+ or -()) 312362306a36Sopenharmony_ci mov.l (%sp)+,%d0 312462306a36Sopenharmony_ci 312562306a36Sopenharmony_ci addq.l &0x4,%sp # remove sub return addr 312662306a36Sopenharmony_ci subq.l &0x8,%sp # make room for bigger stack 312762306a36Sopenharmony_ci subq.l &0x8,%a6 # shift frame ptr down, too 312862306a36Sopenharmony_ci mov.l &26,%d1 # want to move 51 longwords 312962306a36Sopenharmony_ci lea 0x8(%sp),%a0 # get address of old stack 313062306a36Sopenharmony_ci lea 0x0(%sp),%a1 # get address of new stack 313162306a36Sopenharmony_cicas_term_cont: 313262306a36Sopenharmony_ci mov.l (%a0)+,(%a1)+ # move a longword 313362306a36Sopenharmony_ci dbra.w %d1,cas_term_cont # keep going 313462306a36Sopenharmony_ci 313562306a36Sopenharmony_ci mov.w &0x4008,EXC_IVOFF(%a6) # put new stk fmt, voff 313662306a36Sopenharmony_ci mov.l %a2,EXC_IVOFF+0x2(%a6) # put faulting addr on stack 313762306a36Sopenharmony_ci mov.l %d0,EXC_IVOFF+0x6(%a6) # put FSLW on stack 313862306a36Sopenharmony_ci movm.l EXC_DREGS(%a6),&0x3fff # restore user regs 313962306a36Sopenharmony_ci unlk %a6 # unlink stack frame 314062306a36Sopenharmony_ci bra.l _real_access 314162306a36Sopenharmony_ci 314262306a36Sopenharmony_ci######## 314362306a36Sopenharmony_ci 314462306a36Sopenharmony_ci global _isp_cas_inrange 314562306a36Sopenharmony_ci_isp_cas_inrange: 314662306a36Sopenharmony_ci clr.l %d0 # clear return result 314762306a36Sopenharmony_ci lea _CASHI(%pc),%a1 # load end of CAS core code 314862306a36Sopenharmony_ci cmp.l %a1,%a0 # is PC in range? 314962306a36Sopenharmony_ci blt.b cin_no # no 315062306a36Sopenharmony_ci lea _CASLO(%pc),%a1 # load begin of CAS core code 315162306a36Sopenharmony_ci cmp.l %a0,%a1 # is PC in range? 315262306a36Sopenharmony_ci blt.b cin_no # no 315362306a36Sopenharmony_ci rts # yes; return d0 = 0 315462306a36Sopenharmony_cicin_no: 315562306a36Sopenharmony_ci mov.l &-0x1,%d0 # out of range; return d0 = -1 315662306a36Sopenharmony_ci rts 315762306a36Sopenharmony_ci 315862306a36Sopenharmony_ci################################################################# 315962306a36Sopenharmony_ci################################################################# 316062306a36Sopenharmony_ci################################################################# 316162306a36Sopenharmony_ci# This is the start of the cas and cas2 "core" emulation code. # 316262306a36Sopenharmony_ci# This is the section that may need to be replaced by the host # 316362306a36Sopenharmony_ci# OS if it is too operating system-specific. # 316462306a36Sopenharmony_ci# Please refer to the package documentation to see how to # 316562306a36Sopenharmony_ci# "replace" this section, if necessary. # 316662306a36Sopenharmony_ci################################################################# 316762306a36Sopenharmony_ci################################################################# 316862306a36Sopenharmony_ci################################################################# 316962306a36Sopenharmony_ci 317062306a36Sopenharmony_ci# ###### ## ###### #### 317162306a36Sopenharmony_ci# # # # # # # 317262306a36Sopenharmony_ci# # ###### ###### # 317362306a36Sopenharmony_ci# # # # # # 317462306a36Sopenharmony_ci# ###### # # ###### ###### 317562306a36Sopenharmony_ci 317662306a36Sopenharmony_ci######################################################################### 317762306a36Sopenharmony_ci# XDEF **************************************************************** # 317862306a36Sopenharmony_ci# _isp_cas2(): "core" emulation code for the cas2 instruction # 317962306a36Sopenharmony_ci# # 318062306a36Sopenharmony_ci# XREF **************************************************************** # 318162306a36Sopenharmony_ci# _isp_cas2_finish() - only exit point for this emulation code; # 318262306a36Sopenharmony_ci# do clean-up; calculate ccodes; store # 318362306a36Sopenharmony_ci# Compare Ops if appropriate. # 318462306a36Sopenharmony_ci# # 318562306a36Sopenharmony_ci# INPUT *************************************************************** # 318662306a36Sopenharmony_ci# *see chart below* # 318762306a36Sopenharmony_ci# # 318862306a36Sopenharmony_ci# OUTPUT ************************************************************** # 318962306a36Sopenharmony_ci# *see chart below* # 319062306a36Sopenharmony_ci# # 319162306a36Sopenharmony_ci# ALGORITHM *********************************************************** # 319262306a36Sopenharmony_ci# (1) Make several copies of the effective address. # 319362306a36Sopenharmony_ci# (2) Save current SR; Then mask off all maskable interrupts. # 319462306a36Sopenharmony_ci# (3) Save current SFC/DFC (ASSUMED TO BE EQUAL!!!); Then set # 319562306a36Sopenharmony_ci# according to whether exception occurred in user or # 319662306a36Sopenharmony_ci# supervisor mode. # 319762306a36Sopenharmony_ci# (4) Use "plpaw" instruction to pre-load ATC with effective # 319862306a36Sopenharmony_ci# address pages(s). THIS SHOULD NOT FAULT!!! The relevant # 319962306a36Sopenharmony_ci# page(s) should have already been made resident prior to # 320062306a36Sopenharmony_ci# entering this routine. # 320162306a36Sopenharmony_ci# (5) Push the operand lines from the cache w/ "cpushl". # 320262306a36Sopenharmony_ci# In the 68040, this was done within the locked region. In # 320362306a36Sopenharmony_ci# the 68060, it is done outside of the locked region. # 320462306a36Sopenharmony_ci# (6) Use "plpar" instruction to do a re-load of ATC entries for # 320562306a36Sopenharmony_ci# ADDR1 since ADDR2 entries may have pushed ADDR1 out of the # 320662306a36Sopenharmony_ci# ATC. # 320762306a36Sopenharmony_ci# (7) Pre-fetch the core emulation instructions by executing # 320862306a36Sopenharmony_ci# one branch within each physical line (16 bytes) of the code # 320962306a36Sopenharmony_ci# before actually executing the code. # 321062306a36Sopenharmony_ci# (8) Load the BUSCR w/ the bus lock value. # 321162306a36Sopenharmony_ci# (9) Fetch the source operands using "moves". # 321262306a36Sopenharmony_ci# (10)Do the compares. If both equal, go to step (13). # 321362306a36Sopenharmony_ci# (11)Unequal. No update occurs. But, we do write the DST1 op # 321462306a36Sopenharmony_ci# back to itself (as w/ the '040) so we can gracefully unlock # 321562306a36Sopenharmony_ci# the bus (and assert LOCKE*) using BUSCR and the final move. # 321662306a36Sopenharmony_ci# (12)Exit. # 321762306a36Sopenharmony_ci# (13)Write update operand to the DST locations. Use BUSCR to # 321862306a36Sopenharmony_ci# assert LOCKE* for the final write operation. # 321962306a36Sopenharmony_ci# (14)Exit. # 322062306a36Sopenharmony_ci# # 322162306a36Sopenharmony_ci# The algorithm is actually implemented slightly differently # 322262306a36Sopenharmony_ci# depending on the size of the operation and the misalignment of the # 322362306a36Sopenharmony_ci# operands. A misaligned operand must be written in aligned chunks or # 322462306a36Sopenharmony_ci# else the BUSCR register control gets confused. # 322562306a36Sopenharmony_ci# # 322662306a36Sopenharmony_ci######################################################################### 322762306a36Sopenharmony_ci 322862306a36Sopenharmony_ci################################################################# 322962306a36Sopenharmony_ci# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON # 323062306a36Sopenharmony_ci# ENTERING _isp_cas2(). # 323162306a36Sopenharmony_ci# # 323262306a36Sopenharmony_ci# D0 = xxxxxxxx # 323362306a36Sopenharmony_ci# D1 = xxxxxxxx # 323462306a36Sopenharmony_ci# D2 = cmp operand 1 # 323562306a36Sopenharmony_ci# D3 = cmp operand 2 # 323662306a36Sopenharmony_ci# D4 = update oper 1 # 323762306a36Sopenharmony_ci# D5 = update oper 2 # 323862306a36Sopenharmony_ci# D6 = 'xxxxxxff if supervisor mode; 'xxxxxx00 if user mode # 323962306a36Sopenharmony_ci# D7 = 'xxxxxxff if longword operation; 'xxxxxx00 if word # 324062306a36Sopenharmony_ci# A0 = ADDR1 # 324162306a36Sopenharmony_ci# A1 = ADDR2 # 324262306a36Sopenharmony_ci# A2 = xxxxxxxx # 324362306a36Sopenharmony_ci# A3 = xxxxxxxx # 324462306a36Sopenharmony_ci# A4 = xxxxxxxx # 324562306a36Sopenharmony_ci# A5 = xxxxxxxx # 324662306a36Sopenharmony_ci# A6 = frame pointer # 324762306a36Sopenharmony_ci# A7 = stack pointer # 324862306a36Sopenharmony_ci################################################################# 324962306a36Sopenharmony_ci 325062306a36Sopenharmony_ci# align 0x1000 325162306a36Sopenharmony_ci# beginning label used by _isp_cas_inrange() 325262306a36Sopenharmony_ci global _CASLO 325362306a36Sopenharmony_ci_CASLO: 325462306a36Sopenharmony_ci 325562306a36Sopenharmony_ci global _isp_cas2 325662306a36Sopenharmony_ci_isp_cas2: 325762306a36Sopenharmony_ci tst.b %d6 # user or supervisor mode? 325862306a36Sopenharmony_ci bne.b cas2_supervisor # supervisor 325962306a36Sopenharmony_cicas2_user: 326062306a36Sopenharmony_ci movq.l &0x1,%d0 # load user data fc 326162306a36Sopenharmony_ci bra.b cas2_cont 326262306a36Sopenharmony_cicas2_supervisor: 326362306a36Sopenharmony_ci movq.l &0x5,%d0 # load supervisor data fc 326462306a36Sopenharmony_cicas2_cont: 326562306a36Sopenharmony_ci tst.b %d7 # word or longword? 326662306a36Sopenharmony_ci beq.w cas2w # word 326762306a36Sopenharmony_ci 326862306a36Sopenharmony_ci#### 326962306a36Sopenharmony_cicas2l: 327062306a36Sopenharmony_ci mov.l %a0,%a2 # copy ADDR1 327162306a36Sopenharmony_ci mov.l %a1,%a3 # copy ADDR2 327262306a36Sopenharmony_ci mov.l %a0,%a4 # copy ADDR1 327362306a36Sopenharmony_ci mov.l %a1,%a5 # copy ADDR2 327462306a36Sopenharmony_ci 327562306a36Sopenharmony_ci addq.l &0x3,%a4 # ADDR1+3 327662306a36Sopenharmony_ci addq.l &0x3,%a5 # ADDR2+3 327762306a36Sopenharmony_ci mov.l %a2,%d1 # ADDR1 327862306a36Sopenharmony_ci 327962306a36Sopenharmony_ci# mask interrupts levels 0-6. save old mask value. 328062306a36Sopenharmony_ci mov.w %sr,%d7 # save current SR 328162306a36Sopenharmony_ci ori.w &0x0700,%sr # inhibit interrupts 328262306a36Sopenharmony_ci 328362306a36Sopenharmony_ci# load the SFC and DFC with the appropriate mode. 328462306a36Sopenharmony_ci movc %sfc,%d6 # save old SFC/DFC 328562306a36Sopenharmony_ci movc %d0,%sfc # store new SFC 328662306a36Sopenharmony_ci movc %d0,%dfc # store new DFC 328762306a36Sopenharmony_ci 328862306a36Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because 328962306a36Sopenharmony_ci# _real_lock_page() should have taken care of this. 329062306a36Sopenharmony_ci plpaw (%a2) # load atc for ADDR1 329162306a36Sopenharmony_ci plpaw (%a4) # load atc for ADDR1+3 329262306a36Sopenharmony_ci plpaw (%a3) # load atc for ADDR2 329362306a36Sopenharmony_ci plpaw (%a5) # load atc for ADDR2+3 329462306a36Sopenharmony_ci 329562306a36Sopenharmony_ci# push the operand lines from the cache if they exist. 329662306a36Sopenharmony_ci cpushl %dc,(%a2) # push line for ADDR1 329762306a36Sopenharmony_ci cpushl %dc,(%a4) # push line for ADDR1+3 329862306a36Sopenharmony_ci cpushl %dc,(%a3) # push line for ADDR2 329962306a36Sopenharmony_ci cpushl %dc,(%a5) # push line for ADDR2+2 330062306a36Sopenharmony_ci 330162306a36Sopenharmony_ci mov.l %d1,%a2 # ADDR1 330262306a36Sopenharmony_ci addq.l &0x3,%d1 330362306a36Sopenharmony_ci mov.l %d1,%a4 # ADDR1+3 330462306a36Sopenharmony_ci# if ADDR1 was ATC resident before the above "plpaw" and was executed 330562306a36Sopenharmony_ci# and it was the next entry scheduled for replacement and ADDR2 330662306a36Sopenharmony_ci# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1 330762306a36Sopenharmony_ci# entries from the ATC. so, we do a second set of "plpa"s. 330862306a36Sopenharmony_ci plpar (%a2) # load atc for ADDR1 330962306a36Sopenharmony_ci plpar (%a4) # load atc for ADDR1+3 331062306a36Sopenharmony_ci 331162306a36Sopenharmony_ci# load the BUSCR values. 331262306a36Sopenharmony_ci mov.l &0x80000000,%a2 # assert LOCK* buscr value 331362306a36Sopenharmony_ci mov.l &0xa0000000,%a3 # assert LOCKE* buscr value 331462306a36Sopenharmony_ci mov.l &0x00000000,%a4 # buscr unlock value 331562306a36Sopenharmony_ci 331662306a36Sopenharmony_ci# there are three possible mis-aligned cases for longword cas. they 331762306a36Sopenharmony_ci# are separated because the final write which asserts LOCKE* must 331862306a36Sopenharmony_ci# be aligned. 331962306a36Sopenharmony_ci mov.l %a0,%d0 # is ADDR1 misaligned? 332062306a36Sopenharmony_ci andi.b &0x3,%d0 332162306a36Sopenharmony_ci beq.b CAS2L_ENTER # no 332262306a36Sopenharmony_ci cmpi.b %d0,&0x2 332362306a36Sopenharmony_ci beq.w CAS2L2_ENTER # yes; word misaligned 332462306a36Sopenharmony_ci bra.w CAS2L3_ENTER # yes; byte misaligned 332562306a36Sopenharmony_ci 332662306a36Sopenharmony_ci# 332762306a36Sopenharmony_ci# D0 = dst operand 1 <- 332862306a36Sopenharmony_ci# D1 = dst operand 2 <- 332962306a36Sopenharmony_ci# D2 = cmp operand 1 333062306a36Sopenharmony_ci# D3 = cmp operand 2 333162306a36Sopenharmony_ci# D4 = update oper 1 333262306a36Sopenharmony_ci# D5 = update oper 2 333362306a36Sopenharmony_ci# D6 = old SFC/DFC 333462306a36Sopenharmony_ci# D7 = old SR 333562306a36Sopenharmony_ci# A0 = ADDR1 333662306a36Sopenharmony_ci# A1 = ADDR2 333762306a36Sopenharmony_ci# A2 = bus LOCK* value 333862306a36Sopenharmony_ci# A3 = bus LOCKE* value 333962306a36Sopenharmony_ci# A4 = bus unlock value 334062306a36Sopenharmony_ci# A5 = xxxxxxxx 334162306a36Sopenharmony_ci# 334262306a36Sopenharmony_ci align 0x10 334362306a36Sopenharmony_ciCAS2L_START: 334462306a36Sopenharmony_ci movc %a2,%buscr # assert LOCK* 334562306a36Sopenharmony_ci movs.l (%a1),%d1 # fetch Dest2[31:0] 334662306a36Sopenharmony_ci movs.l (%a0),%d0 # fetch Dest1[31:0] 334762306a36Sopenharmony_ci bra.b CAS2L_CONT 334862306a36Sopenharmony_ciCAS2L_ENTER: 334962306a36Sopenharmony_ci bra.b ~+16 335062306a36Sopenharmony_ci 335162306a36Sopenharmony_ciCAS2L_CONT: 335262306a36Sopenharmony_ci cmp.l %d0,%d2 # Dest1 - Compare1 335362306a36Sopenharmony_ci bne.b CAS2L_NOUPDATE 335462306a36Sopenharmony_ci cmp.l %d1,%d3 # Dest2 - Compare2 335562306a36Sopenharmony_ci bne.b CAS2L_NOUPDATE 335662306a36Sopenharmony_ci movs.l %d5,(%a1) # Update2[31:0] -> DEST2 335762306a36Sopenharmony_ci bra.b CAS2L_UPDATE 335862306a36Sopenharmony_ci bra.b ~+16 335962306a36Sopenharmony_ci 336062306a36Sopenharmony_ciCAS2L_UPDATE: 336162306a36Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 336262306a36Sopenharmony_ci movs.l %d4,(%a0) # Update1[31:0] -> DEST1 336362306a36Sopenharmony_ci movc %a4,%buscr # unlock the bus 336462306a36Sopenharmony_ci bra.b cas2l_update_done 336562306a36Sopenharmony_ci bra.b ~+16 336662306a36Sopenharmony_ci 336762306a36Sopenharmony_ciCAS2L_NOUPDATE: 336862306a36Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 336962306a36Sopenharmony_ci movs.l %d0,(%a0) # Dest1[31:0] -> DEST1 337062306a36Sopenharmony_ci movc %a4,%buscr # unlock the bus 337162306a36Sopenharmony_ci bra.b cas2l_noupdate_done 337262306a36Sopenharmony_ci bra.b ~+16 337362306a36Sopenharmony_ci 337462306a36Sopenharmony_ciCAS2L_FILLER: 337562306a36Sopenharmony_ci nop 337662306a36Sopenharmony_ci nop 337762306a36Sopenharmony_ci nop 337862306a36Sopenharmony_ci nop 337962306a36Sopenharmony_ci nop 338062306a36Sopenharmony_ci nop 338162306a36Sopenharmony_ci nop 338262306a36Sopenharmony_ci bra.b CAS2L_START 338362306a36Sopenharmony_ci 338462306a36Sopenharmony_ci#### 338562306a36Sopenharmony_ci 338662306a36Sopenharmony_ci################################################################# 338762306a36Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON # 338862306a36Sopenharmony_ci# ENTERING _isp_cas2(). # 338962306a36Sopenharmony_ci# # 339062306a36Sopenharmony_ci# D0 = destination[31:0] operand 1 # 339162306a36Sopenharmony_ci# D1 = destination[31:0] operand 2 # 339262306a36Sopenharmony_ci# D2 = cmp[31:0] operand 1 # 339362306a36Sopenharmony_ci# D3 = cmp[31:0] operand 2 # 339462306a36Sopenharmony_ci# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required # 339562306a36Sopenharmony_ci# D5 = xxxxxxxx # 339662306a36Sopenharmony_ci# D6 = xxxxxxxx # 339762306a36Sopenharmony_ci# D7 = xxxxxxxx # 339862306a36Sopenharmony_ci# A0 = xxxxxxxx # 339962306a36Sopenharmony_ci# A1 = xxxxxxxx # 340062306a36Sopenharmony_ci# A2 = xxxxxxxx # 340162306a36Sopenharmony_ci# A3 = xxxxxxxx # 340262306a36Sopenharmony_ci# A4 = xxxxxxxx # 340362306a36Sopenharmony_ci# A5 = xxxxxxxx # 340462306a36Sopenharmony_ci# A6 = frame pointer # 340562306a36Sopenharmony_ci# A7 = stack pointer # 340662306a36Sopenharmony_ci################################################################# 340762306a36Sopenharmony_ci 340862306a36Sopenharmony_cicas2l_noupdate_done: 340962306a36Sopenharmony_ci 341062306a36Sopenharmony_ci# restore previous SFC/DFC value. 341162306a36Sopenharmony_ci movc %d6,%sfc # restore old SFC 341262306a36Sopenharmony_ci movc %d6,%dfc # restore old DFC 341362306a36Sopenharmony_ci 341462306a36Sopenharmony_ci# restore previous interrupt mask level. 341562306a36Sopenharmony_ci mov.w %d7,%sr # restore old SR 341662306a36Sopenharmony_ci 341762306a36Sopenharmony_ci sf %d4 # indicate no update was done 341862306a36Sopenharmony_ci bra.l _isp_cas2_finish 341962306a36Sopenharmony_ci 342062306a36Sopenharmony_cicas2l_update_done: 342162306a36Sopenharmony_ci 342262306a36Sopenharmony_ci# restore previous SFC/DFC value. 342362306a36Sopenharmony_ci movc %d6,%sfc # restore old SFC 342462306a36Sopenharmony_ci movc %d6,%dfc # restore old DFC 342562306a36Sopenharmony_ci 342662306a36Sopenharmony_ci# restore previous interrupt mask level. 342762306a36Sopenharmony_ci mov.w %d7,%sr # restore old SR 342862306a36Sopenharmony_ci 342962306a36Sopenharmony_ci st %d4 # indicate update was done 343062306a36Sopenharmony_ci bra.l _isp_cas2_finish 343162306a36Sopenharmony_ci#### 343262306a36Sopenharmony_ci 343362306a36Sopenharmony_ci align 0x10 343462306a36Sopenharmony_ciCAS2L2_START: 343562306a36Sopenharmony_ci movc %a2,%buscr # assert LOCK* 343662306a36Sopenharmony_ci movs.l (%a1),%d1 # fetch Dest2[31:0] 343762306a36Sopenharmony_ci movs.l (%a0),%d0 # fetch Dest1[31:0] 343862306a36Sopenharmony_ci bra.b CAS2L2_CONT 343962306a36Sopenharmony_ciCAS2L2_ENTER: 344062306a36Sopenharmony_ci bra.b ~+16 344162306a36Sopenharmony_ci 344262306a36Sopenharmony_ciCAS2L2_CONT: 344362306a36Sopenharmony_ci cmp.l %d0,%d2 # Dest1 - Compare1 344462306a36Sopenharmony_ci bne.b CAS2L2_NOUPDATE 344562306a36Sopenharmony_ci cmp.l %d1,%d3 # Dest2 - Compare2 344662306a36Sopenharmony_ci bne.b CAS2L2_NOUPDATE 344762306a36Sopenharmony_ci movs.l %d5,(%a1) # Update2[31:0] -> Dest2 344862306a36Sopenharmony_ci bra.b CAS2L2_UPDATE 344962306a36Sopenharmony_ci bra.b ~+16 345062306a36Sopenharmony_ci 345162306a36Sopenharmony_ciCAS2L2_UPDATE: 345262306a36Sopenharmony_ci swap %d4 # get Update1[31:16] 345362306a36Sopenharmony_ci movs.w %d4,(%a0)+ # Update1[31:16] -> DEST1 345462306a36Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 345562306a36Sopenharmony_ci swap %d4 # get Update1[15:0] 345662306a36Sopenharmony_ci bra.b CAS2L2_UPDATE2 345762306a36Sopenharmony_ci bra.b ~+16 345862306a36Sopenharmony_ci 345962306a36Sopenharmony_ciCAS2L2_UPDATE2: 346062306a36Sopenharmony_ci movs.w %d4,(%a0) # Update1[15:0] -> DEST1+0x2 346162306a36Sopenharmony_ci movc %a4,%buscr # unlock the bus 346262306a36Sopenharmony_ci bra.w cas2l_update_done 346362306a36Sopenharmony_ci nop 346462306a36Sopenharmony_ci bra.b ~+16 346562306a36Sopenharmony_ci 346662306a36Sopenharmony_ciCAS2L2_NOUPDATE: 346762306a36Sopenharmony_ci swap %d0 # get Dest1[31:16] 346862306a36Sopenharmony_ci movs.w %d0,(%a0)+ # Dest1[31:16] -> DEST1 346962306a36Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 347062306a36Sopenharmony_ci swap %d0 # get Dest1[15:0] 347162306a36Sopenharmony_ci bra.b CAS2L2_NOUPDATE2 347262306a36Sopenharmony_ci bra.b ~+16 347362306a36Sopenharmony_ci 347462306a36Sopenharmony_ciCAS2L2_NOUPDATE2: 347562306a36Sopenharmony_ci movs.w %d0,(%a0) # Dest1[15:0] -> DEST1+0x2 347662306a36Sopenharmony_ci movc %a4,%buscr # unlock the bus 347762306a36Sopenharmony_ci bra.w cas2l_noupdate_done 347862306a36Sopenharmony_ci nop 347962306a36Sopenharmony_ci bra.b ~+16 348062306a36Sopenharmony_ci 348162306a36Sopenharmony_ciCAS2L2_FILLER: 348262306a36Sopenharmony_ci nop 348362306a36Sopenharmony_ci nop 348462306a36Sopenharmony_ci nop 348562306a36Sopenharmony_ci nop 348662306a36Sopenharmony_ci nop 348762306a36Sopenharmony_ci nop 348862306a36Sopenharmony_ci nop 348962306a36Sopenharmony_ci bra.b CAS2L2_START 349062306a36Sopenharmony_ci 349162306a36Sopenharmony_ci################################# 349262306a36Sopenharmony_ci 349362306a36Sopenharmony_ci align 0x10 349462306a36Sopenharmony_ciCAS2L3_START: 349562306a36Sopenharmony_ci movc %a2,%buscr # assert LOCK* 349662306a36Sopenharmony_ci movs.l (%a1),%d1 # fetch Dest2[31:0] 349762306a36Sopenharmony_ci movs.l (%a0),%d0 # fetch Dest1[31:0] 349862306a36Sopenharmony_ci bra.b CAS2L3_CONT 349962306a36Sopenharmony_ciCAS2L3_ENTER: 350062306a36Sopenharmony_ci bra.b ~+16 350162306a36Sopenharmony_ci 350262306a36Sopenharmony_ciCAS2L3_CONT: 350362306a36Sopenharmony_ci cmp.l %d0,%d2 # Dest1 - Compare1 350462306a36Sopenharmony_ci bne.b CAS2L3_NOUPDATE 350562306a36Sopenharmony_ci cmp.l %d1,%d3 # Dest2 - Compare2 350662306a36Sopenharmony_ci bne.b CAS2L3_NOUPDATE 350762306a36Sopenharmony_ci movs.l %d5,(%a1) # Update2[31:0] -> DEST2 350862306a36Sopenharmony_ci bra.b CAS2L3_UPDATE 350962306a36Sopenharmony_ci bra.b ~+16 351062306a36Sopenharmony_ci 351162306a36Sopenharmony_ciCAS2L3_UPDATE: 351262306a36Sopenharmony_ci rol.l &0x8,%d4 # get Update1[31:24] 351362306a36Sopenharmony_ci movs.b %d4,(%a0)+ # Update1[31:24] -> DEST1 351462306a36Sopenharmony_ci swap %d4 # get Update1[23:8] 351562306a36Sopenharmony_ci movs.w %d4,(%a0)+ # Update1[23:8] -> DEST1+0x1 351662306a36Sopenharmony_ci bra.b CAS2L3_UPDATE2 351762306a36Sopenharmony_ci bra.b ~+16 351862306a36Sopenharmony_ci 351962306a36Sopenharmony_ciCAS2L3_UPDATE2: 352062306a36Sopenharmony_ci rol.l &0x8,%d4 # get Update1[7:0] 352162306a36Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 352262306a36Sopenharmony_ci movs.b %d4,(%a0) # Update1[7:0] -> DEST1+0x3 352362306a36Sopenharmony_ci bra.b CAS2L3_UPDATE3 352462306a36Sopenharmony_ci nop 352562306a36Sopenharmony_ci bra.b ~+16 352662306a36Sopenharmony_ci 352762306a36Sopenharmony_ciCAS2L3_UPDATE3: 352862306a36Sopenharmony_ci movc %a4,%buscr # unlock the bus 352962306a36Sopenharmony_ci bra.w cas2l_update_done 353062306a36Sopenharmony_ci nop 353162306a36Sopenharmony_ci nop 353262306a36Sopenharmony_ci nop 353362306a36Sopenharmony_ci bra.b ~+16 353462306a36Sopenharmony_ci 353562306a36Sopenharmony_ciCAS2L3_NOUPDATE: 353662306a36Sopenharmony_ci rol.l &0x8,%d0 # get Dest1[31:24] 353762306a36Sopenharmony_ci movs.b %d0,(%a0)+ # Dest1[31:24] -> DEST1 353862306a36Sopenharmony_ci swap %d0 # get Dest1[23:8] 353962306a36Sopenharmony_ci movs.w %d0,(%a0)+ # Dest1[23:8] -> DEST1+0x1 354062306a36Sopenharmony_ci bra.b CAS2L3_NOUPDATE2 354162306a36Sopenharmony_ci bra.b ~+16 354262306a36Sopenharmony_ci 354362306a36Sopenharmony_ciCAS2L3_NOUPDATE2: 354462306a36Sopenharmony_ci rol.l &0x8,%d0 # get Dest1[7:0] 354562306a36Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 354662306a36Sopenharmony_ci movs.b %d0,(%a0) # Update1[7:0] -> DEST1+0x3 354762306a36Sopenharmony_ci bra.b CAS2L3_NOUPDATE3 354862306a36Sopenharmony_ci nop 354962306a36Sopenharmony_ci bra.b ~+16 355062306a36Sopenharmony_ci 355162306a36Sopenharmony_ciCAS2L3_NOUPDATE3: 355262306a36Sopenharmony_ci movc %a4,%buscr # unlock the bus 355362306a36Sopenharmony_ci bra.w cas2l_noupdate_done 355462306a36Sopenharmony_ci nop 355562306a36Sopenharmony_ci nop 355662306a36Sopenharmony_ci nop 355762306a36Sopenharmony_ci bra.b ~+14 355862306a36Sopenharmony_ci 355962306a36Sopenharmony_ciCAS2L3_FILLER: 356062306a36Sopenharmony_ci nop 356162306a36Sopenharmony_ci nop 356262306a36Sopenharmony_ci nop 356362306a36Sopenharmony_ci nop 356462306a36Sopenharmony_ci nop 356562306a36Sopenharmony_ci nop 356662306a36Sopenharmony_ci bra.w CAS2L3_START 356762306a36Sopenharmony_ci 356862306a36Sopenharmony_ci############################################################# 356962306a36Sopenharmony_ci############################################################# 357062306a36Sopenharmony_ci 357162306a36Sopenharmony_cicas2w: 357262306a36Sopenharmony_ci mov.l %a0,%a2 # copy ADDR1 357362306a36Sopenharmony_ci mov.l %a1,%a3 # copy ADDR2 357462306a36Sopenharmony_ci mov.l %a0,%a4 # copy ADDR1 357562306a36Sopenharmony_ci mov.l %a1,%a5 # copy ADDR2 357662306a36Sopenharmony_ci 357762306a36Sopenharmony_ci addq.l &0x1,%a4 # ADDR1+1 357862306a36Sopenharmony_ci addq.l &0x1,%a5 # ADDR2+1 357962306a36Sopenharmony_ci mov.l %a2,%d1 # ADDR1 358062306a36Sopenharmony_ci 358162306a36Sopenharmony_ci# mask interrupt levels 0-6. save old mask value. 358262306a36Sopenharmony_ci mov.w %sr,%d7 # save current SR 358362306a36Sopenharmony_ci ori.w &0x0700,%sr # inhibit interrupts 358462306a36Sopenharmony_ci 358562306a36Sopenharmony_ci# load the SFC and DFC with the appropriate mode. 358662306a36Sopenharmony_ci movc %sfc,%d6 # save old SFC/DFC 358762306a36Sopenharmony_ci movc %d0,%sfc # store new SFC 358862306a36Sopenharmony_ci movc %d0,%dfc # store new DFC 358962306a36Sopenharmony_ci 359062306a36Sopenharmony_ci# pre-load the operand ATC. no page faults should occur because 359162306a36Sopenharmony_ci# _real_lock_page() should have taken care of this. 359262306a36Sopenharmony_ci plpaw (%a2) # load atc for ADDR1 359362306a36Sopenharmony_ci plpaw (%a4) # load atc for ADDR1+1 359462306a36Sopenharmony_ci plpaw (%a3) # load atc for ADDR2 359562306a36Sopenharmony_ci plpaw (%a5) # load atc for ADDR2+1 359662306a36Sopenharmony_ci 359762306a36Sopenharmony_ci# push the operand cache lines from the cache if they exist. 359862306a36Sopenharmony_ci cpushl %dc,(%a2) # push line for ADDR1 359962306a36Sopenharmony_ci cpushl %dc,(%a4) # push line for ADDR1+1 360062306a36Sopenharmony_ci cpushl %dc,(%a3) # push line for ADDR2 360162306a36Sopenharmony_ci cpushl %dc,(%a5) # push line for ADDR2+1 360262306a36Sopenharmony_ci 360362306a36Sopenharmony_ci mov.l %d1,%a2 # ADDR1 360462306a36Sopenharmony_ci addq.l &0x3,%d1 360562306a36Sopenharmony_ci mov.l %d1,%a4 # ADDR1+3 360662306a36Sopenharmony_ci# if ADDR1 was ATC resident before the above "plpaw" and was executed 360762306a36Sopenharmony_ci# and it was the next entry scheduled for replacement and ADDR2 360862306a36Sopenharmony_ci# shares the same set, then the "plpaw" for ADDR2 can push the ADDR1 360962306a36Sopenharmony_ci# entries from the ATC. so, we do a second set of "plpa"s. 361062306a36Sopenharmony_ci plpar (%a2) # load atc for ADDR1 361162306a36Sopenharmony_ci plpar (%a4) # load atc for ADDR1+3 361262306a36Sopenharmony_ci 361362306a36Sopenharmony_ci# load the BUSCR values. 361462306a36Sopenharmony_ci mov.l &0x80000000,%a2 # assert LOCK* buscr value 361562306a36Sopenharmony_ci mov.l &0xa0000000,%a3 # assert LOCKE* buscr value 361662306a36Sopenharmony_ci mov.l &0x00000000,%a4 # buscr unlock value 361762306a36Sopenharmony_ci 361862306a36Sopenharmony_ci# there are two possible mis-aligned cases for word cas. they 361962306a36Sopenharmony_ci# are separated because the final write which asserts LOCKE* must 362062306a36Sopenharmony_ci# be aligned. 362162306a36Sopenharmony_ci mov.l %a0,%d0 # is ADDR1 misaligned? 362262306a36Sopenharmony_ci btst &0x0,%d0 362362306a36Sopenharmony_ci bne.w CAS2W2_ENTER # yes 362462306a36Sopenharmony_ci bra.b CAS2W_ENTER # no 362562306a36Sopenharmony_ci 362662306a36Sopenharmony_ci# 362762306a36Sopenharmony_ci# D0 = dst operand 1 <- 362862306a36Sopenharmony_ci# D1 = dst operand 2 <- 362962306a36Sopenharmony_ci# D2 = cmp operand 1 363062306a36Sopenharmony_ci# D3 = cmp operand 2 363162306a36Sopenharmony_ci# D4 = update oper 1 363262306a36Sopenharmony_ci# D5 = update oper 2 363362306a36Sopenharmony_ci# D6 = old SFC/DFC 363462306a36Sopenharmony_ci# D7 = old SR 363562306a36Sopenharmony_ci# A0 = ADDR1 363662306a36Sopenharmony_ci# A1 = ADDR2 363762306a36Sopenharmony_ci# A2 = bus LOCK* value 363862306a36Sopenharmony_ci# A3 = bus LOCKE* value 363962306a36Sopenharmony_ci# A4 = bus unlock value 364062306a36Sopenharmony_ci# A5 = xxxxxxxx 364162306a36Sopenharmony_ci# 364262306a36Sopenharmony_ci align 0x10 364362306a36Sopenharmony_ciCAS2W_START: 364462306a36Sopenharmony_ci movc %a2,%buscr # assert LOCK* 364562306a36Sopenharmony_ci movs.w (%a1),%d1 # fetch Dest2[15:0] 364662306a36Sopenharmony_ci movs.w (%a0),%d0 # fetch Dest1[15:0] 364762306a36Sopenharmony_ci bra.b CAS2W_CONT2 364862306a36Sopenharmony_ciCAS2W_ENTER: 364962306a36Sopenharmony_ci bra.b ~+16 365062306a36Sopenharmony_ci 365162306a36Sopenharmony_ciCAS2W_CONT2: 365262306a36Sopenharmony_ci cmp.w %d0,%d2 # Dest1 - Compare1 365362306a36Sopenharmony_ci bne.b CAS2W_NOUPDATE 365462306a36Sopenharmony_ci cmp.w %d1,%d3 # Dest2 - Compare2 365562306a36Sopenharmony_ci bne.b CAS2W_NOUPDATE 365662306a36Sopenharmony_ci movs.w %d5,(%a1) # Update2[15:0] -> DEST2 365762306a36Sopenharmony_ci bra.b CAS2W_UPDATE 365862306a36Sopenharmony_ci bra.b ~+16 365962306a36Sopenharmony_ci 366062306a36Sopenharmony_ciCAS2W_UPDATE: 366162306a36Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 366262306a36Sopenharmony_ci movs.w %d4,(%a0) # Update1[15:0] -> DEST1 366362306a36Sopenharmony_ci movc %a4,%buscr # unlock the bus 366462306a36Sopenharmony_ci bra.b cas2w_update_done 366562306a36Sopenharmony_ci bra.b ~+16 366662306a36Sopenharmony_ci 366762306a36Sopenharmony_ciCAS2W_NOUPDATE: 366862306a36Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 366962306a36Sopenharmony_ci movs.w %d0,(%a0) # Dest1[15:0] -> DEST1 367062306a36Sopenharmony_ci movc %a4,%buscr # unlock the bus 367162306a36Sopenharmony_ci bra.b cas2w_noupdate_done 367262306a36Sopenharmony_ci bra.b ~+16 367362306a36Sopenharmony_ci 367462306a36Sopenharmony_ciCAS2W_FILLER: 367562306a36Sopenharmony_ci nop 367662306a36Sopenharmony_ci nop 367762306a36Sopenharmony_ci nop 367862306a36Sopenharmony_ci nop 367962306a36Sopenharmony_ci nop 368062306a36Sopenharmony_ci nop 368162306a36Sopenharmony_ci nop 368262306a36Sopenharmony_ci bra.b CAS2W_START 368362306a36Sopenharmony_ci 368462306a36Sopenharmony_ci#### 368562306a36Sopenharmony_ci 368662306a36Sopenharmony_ci################################################################# 368762306a36Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON # 368862306a36Sopenharmony_ci# ENTERING _isp_cas2(). # 368962306a36Sopenharmony_ci# # 369062306a36Sopenharmony_ci# D0 = destination[15:0] operand 1 # 369162306a36Sopenharmony_ci# D1 = destination[15:0] operand 2 # 369262306a36Sopenharmony_ci# D2 = cmp[15:0] operand 1 # 369362306a36Sopenharmony_ci# D3 = cmp[15:0] operand 2 # 369462306a36Sopenharmony_ci# D4 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required # 369562306a36Sopenharmony_ci# D5 = xxxxxxxx # 369662306a36Sopenharmony_ci# D6 = xxxxxxxx # 369762306a36Sopenharmony_ci# D7 = xxxxxxxx # 369862306a36Sopenharmony_ci# A0 = xxxxxxxx # 369962306a36Sopenharmony_ci# A1 = xxxxxxxx # 370062306a36Sopenharmony_ci# A2 = xxxxxxxx # 370162306a36Sopenharmony_ci# A3 = xxxxxxxx # 370262306a36Sopenharmony_ci# A4 = xxxxxxxx # 370362306a36Sopenharmony_ci# A5 = xxxxxxxx # 370462306a36Sopenharmony_ci# A6 = frame pointer # 370562306a36Sopenharmony_ci# A7 = stack pointer # 370662306a36Sopenharmony_ci################################################################# 370762306a36Sopenharmony_ci 370862306a36Sopenharmony_cicas2w_noupdate_done: 370962306a36Sopenharmony_ci 371062306a36Sopenharmony_ci# restore previous SFC/DFC value. 371162306a36Sopenharmony_ci movc %d6,%sfc # restore old SFC 371262306a36Sopenharmony_ci movc %d6,%dfc # restore old DFC 371362306a36Sopenharmony_ci 371462306a36Sopenharmony_ci# restore previous interrupt mask level. 371562306a36Sopenharmony_ci mov.w %d7,%sr # restore old SR 371662306a36Sopenharmony_ci 371762306a36Sopenharmony_ci sf %d4 # indicate no update was done 371862306a36Sopenharmony_ci bra.l _isp_cas2_finish 371962306a36Sopenharmony_ci 372062306a36Sopenharmony_cicas2w_update_done: 372162306a36Sopenharmony_ci 372262306a36Sopenharmony_ci# restore previous SFC/DFC value. 372362306a36Sopenharmony_ci movc %d6,%sfc # restore old SFC 372462306a36Sopenharmony_ci movc %d6,%dfc # restore old DFC 372562306a36Sopenharmony_ci 372662306a36Sopenharmony_ci# restore previous interrupt mask level. 372762306a36Sopenharmony_ci mov.w %d7,%sr # restore old SR 372862306a36Sopenharmony_ci 372962306a36Sopenharmony_ci st %d4 # indicate update was done 373062306a36Sopenharmony_ci bra.l _isp_cas2_finish 373162306a36Sopenharmony_ci#### 373262306a36Sopenharmony_ci 373362306a36Sopenharmony_ci align 0x10 373462306a36Sopenharmony_ciCAS2W2_START: 373562306a36Sopenharmony_ci movc %a2,%buscr # assert LOCK* 373662306a36Sopenharmony_ci movs.w (%a1),%d1 # fetch Dest2[15:0] 373762306a36Sopenharmony_ci movs.w (%a0),%d0 # fetch Dest1[15:0] 373862306a36Sopenharmony_ci bra.b CAS2W2_CONT2 373962306a36Sopenharmony_ciCAS2W2_ENTER: 374062306a36Sopenharmony_ci bra.b ~+16 374162306a36Sopenharmony_ci 374262306a36Sopenharmony_ciCAS2W2_CONT2: 374362306a36Sopenharmony_ci cmp.w %d0,%d2 # Dest1 - Compare1 374462306a36Sopenharmony_ci bne.b CAS2W2_NOUPDATE 374562306a36Sopenharmony_ci cmp.w %d1,%d3 # Dest2 - Compare2 374662306a36Sopenharmony_ci bne.b CAS2W2_NOUPDATE 374762306a36Sopenharmony_ci movs.w %d5,(%a1) # Update2[15:0] -> DEST2 374862306a36Sopenharmony_ci bra.b CAS2W2_UPDATE 374962306a36Sopenharmony_ci bra.b ~+16 375062306a36Sopenharmony_ci 375162306a36Sopenharmony_ciCAS2W2_UPDATE: 375262306a36Sopenharmony_ci ror.l &0x8,%d4 # get Update1[15:8] 375362306a36Sopenharmony_ci movs.b %d4,(%a0)+ # Update1[15:8] -> DEST1 375462306a36Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 375562306a36Sopenharmony_ci rol.l &0x8,%d4 # get Update1[7:0] 375662306a36Sopenharmony_ci bra.b CAS2W2_UPDATE2 375762306a36Sopenharmony_ci bra.b ~+16 375862306a36Sopenharmony_ci 375962306a36Sopenharmony_ciCAS2W2_UPDATE2: 376062306a36Sopenharmony_ci movs.b %d4,(%a0) # Update1[7:0] -> DEST1+0x1 376162306a36Sopenharmony_ci movc %a4,%buscr # unlock the bus 376262306a36Sopenharmony_ci bra.w cas2w_update_done 376362306a36Sopenharmony_ci nop 376462306a36Sopenharmony_ci bra.b ~+16 376562306a36Sopenharmony_ci 376662306a36Sopenharmony_ciCAS2W2_NOUPDATE: 376762306a36Sopenharmony_ci ror.l &0x8,%d0 # get Dest1[15:8] 376862306a36Sopenharmony_ci movs.b %d0,(%a0)+ # Dest1[15:8] -> DEST1 376962306a36Sopenharmony_ci movc %a3,%buscr # assert LOCKE* 377062306a36Sopenharmony_ci rol.l &0x8,%d0 # get Dest1[7:0] 377162306a36Sopenharmony_ci bra.b CAS2W2_NOUPDATE2 377262306a36Sopenharmony_ci bra.b ~+16 377362306a36Sopenharmony_ci 377462306a36Sopenharmony_ciCAS2W2_NOUPDATE2: 377562306a36Sopenharmony_ci movs.b %d0,(%a0) # Dest1[7:0] -> DEST1+0x1 377662306a36Sopenharmony_ci movc %a4,%buscr # unlock the bus 377762306a36Sopenharmony_ci bra.w cas2w_noupdate_done 377862306a36Sopenharmony_ci nop 377962306a36Sopenharmony_ci bra.b ~+16 378062306a36Sopenharmony_ci 378162306a36Sopenharmony_ciCAS2W2_FILLER: 378262306a36Sopenharmony_ci nop 378362306a36Sopenharmony_ci nop 378462306a36Sopenharmony_ci nop 378562306a36Sopenharmony_ci nop 378662306a36Sopenharmony_ci nop 378762306a36Sopenharmony_ci nop 378862306a36Sopenharmony_ci nop 378962306a36Sopenharmony_ci bra.b CAS2W2_START 379062306a36Sopenharmony_ci 379162306a36Sopenharmony_ci# ###### ## ###### 379262306a36Sopenharmony_ci# # # # # 379362306a36Sopenharmony_ci# # ###### ###### 379462306a36Sopenharmony_ci# # # # # 379562306a36Sopenharmony_ci# ###### # # ###### 379662306a36Sopenharmony_ci 379762306a36Sopenharmony_ci######################################################################### 379862306a36Sopenharmony_ci# XDEF **************************************************************** # 379962306a36Sopenharmony_ci# _isp_cas(): "core" emulation code for the cas instruction # 380062306a36Sopenharmony_ci# # 380162306a36Sopenharmony_ci# XREF **************************************************************** # 380262306a36Sopenharmony_ci# _isp_cas_finish() - only exit point for this emulation code; # 380362306a36Sopenharmony_ci# do clean-up # 380462306a36Sopenharmony_ci# # 380562306a36Sopenharmony_ci# INPUT *************************************************************** # 380662306a36Sopenharmony_ci# *see entry chart below* # 380762306a36Sopenharmony_ci# # 380862306a36Sopenharmony_ci# OUTPUT ************************************************************** # 380962306a36Sopenharmony_ci# *see exit chart below* # 381062306a36Sopenharmony_ci# # 381162306a36Sopenharmony_ci# ALGORITHM *********************************************************** # 381262306a36Sopenharmony_ci# (1) Make several copies of the effective address. # 381362306a36Sopenharmony_ci# (2) Save current SR; Then mask off all maskable interrupts. # 381462306a36Sopenharmony_ci# (3) Save current DFC/SFC (ASSUMED TO BE EQUAL!!!); Then set # 381562306a36Sopenharmony_ci# SFC/DFC according to whether exception occurred in user or # 381662306a36Sopenharmony_ci# supervisor mode. # 381762306a36Sopenharmony_ci# (4) Use "plpaw" instruction to pre-load ATC with effective # 381862306a36Sopenharmony_ci# address page(s). THIS SHOULD NOT FAULT!!! The relevant # 381962306a36Sopenharmony_ci# page(s) should have been made resident prior to entering # 382062306a36Sopenharmony_ci# this routine. # 382162306a36Sopenharmony_ci# (5) Push the operand lines from the cache w/ "cpushl". # 382262306a36Sopenharmony_ci# In the 68040, this was done within the locked region. In # 382362306a36Sopenharmony_ci# the 68060, it is done outside of the locked region. # 382462306a36Sopenharmony_ci# (6) Pre-fetch the core emulation instructions by executing one # 382562306a36Sopenharmony_ci# branch within each physical line (16 bytes) of the code # 382662306a36Sopenharmony_ci# before actually executing the code. # 382762306a36Sopenharmony_ci# (7) Load the BUSCR with the bus lock value. # 382862306a36Sopenharmony_ci# (8) Fetch the source operand. # 382962306a36Sopenharmony_ci# (9) Do the compare. If equal, go to step (12). # 383062306a36Sopenharmony_ci# (10)Unequal. No update occurs. But, we do write the DST op back # 383162306a36Sopenharmony_ci# to itself (as w/ the '040) so we can gracefully unlock # 383262306a36Sopenharmony_ci# the bus (and assert LOCKE*) using BUSCR and the final move. # 383362306a36Sopenharmony_ci# (11)Exit. # 383462306a36Sopenharmony_ci# (12)Write update operand to the DST location. Use BUSCR to # 383562306a36Sopenharmony_ci# assert LOCKE* for the final write operation. # 383662306a36Sopenharmony_ci# (13)Exit. # 383762306a36Sopenharmony_ci# # 383862306a36Sopenharmony_ci# The algorithm is actually implemented slightly differently # 383962306a36Sopenharmony_ci# depending on the size of the operation and the misalignment of the # 384062306a36Sopenharmony_ci# operand. A misaligned operand must be written in aligned chunks or # 384162306a36Sopenharmony_ci# else the BUSCR register control gets confused. # 384262306a36Sopenharmony_ci# # 384362306a36Sopenharmony_ci######################################################################### 384462306a36Sopenharmony_ci 384562306a36Sopenharmony_ci######################################################### 384662306a36Sopenharmony_ci# THIS IS THE STATE OF THE INTEGER REGISTER FILE UPON # 384762306a36Sopenharmony_ci# ENTERING _isp_cas(). # 384862306a36Sopenharmony_ci# # 384962306a36Sopenharmony_ci# D0 = xxxxxxxx # 385062306a36Sopenharmony_ci# D1 = xxxxxxxx # 385162306a36Sopenharmony_ci# D2 = update operand # 385262306a36Sopenharmony_ci# D3 = xxxxxxxx # 385362306a36Sopenharmony_ci# D4 = compare operand # 385462306a36Sopenharmony_ci# D5 = xxxxxxxx # 385562306a36Sopenharmony_ci# D6 = supervisor ('xxxxxxff) or user mode ('xxxxxx00) # 385662306a36Sopenharmony_ci# D7 = longword ('xxxxxxff) or word size ('xxxxxx00) # 385762306a36Sopenharmony_ci# A0 = ADDR # 385862306a36Sopenharmony_ci# A1 = xxxxxxxx # 385962306a36Sopenharmony_ci# A2 = xxxxxxxx # 386062306a36Sopenharmony_ci# A3 = xxxxxxxx # 386162306a36Sopenharmony_ci# A4 = xxxxxxxx # 386262306a36Sopenharmony_ci# A5 = xxxxxxxx # 386362306a36Sopenharmony_ci# A6 = frame pointer # 386462306a36Sopenharmony_ci# A7 = stack pointer # 386562306a36Sopenharmony_ci######################################################### 386662306a36Sopenharmony_ci 386762306a36Sopenharmony_ci global _isp_cas 386862306a36Sopenharmony_ci_isp_cas: 386962306a36Sopenharmony_ci tst.b %d6 # user or supervisor mode? 387062306a36Sopenharmony_ci bne.b cas_super # supervisor 387162306a36Sopenharmony_cicas_user: 387262306a36Sopenharmony_ci movq.l &0x1,%d0 # load user data fc 387362306a36Sopenharmony_ci bra.b cas_cont 387462306a36Sopenharmony_cicas_super: 387562306a36Sopenharmony_ci movq.l &0x5,%d0 # load supervisor data fc 387662306a36Sopenharmony_ci 387762306a36Sopenharmony_cicas_cont: 387862306a36Sopenharmony_ci tst.b %d7 # word or longword? 387962306a36Sopenharmony_ci bne.w casl # longword 388062306a36Sopenharmony_ci 388162306a36Sopenharmony_ci#### 388262306a36Sopenharmony_cicasw: 388362306a36Sopenharmony_ci mov.l %a0,%a1 # make copy for plpaw1 388462306a36Sopenharmony_ci mov.l %a0,%a2 # make copy for plpaw2 388562306a36Sopenharmony_ci addq.l &0x1,%a2 # plpaw2 points to end of word 388662306a36Sopenharmony_ci 388762306a36Sopenharmony_ci mov.l %d2,%d3 # d3 = update[7:0] 388862306a36Sopenharmony_ci lsr.w &0x8,%d2 # d2 = update[15:8] 388962306a36Sopenharmony_ci 389062306a36Sopenharmony_ci# mask interrupt levels 0-6. save old mask value. 389162306a36Sopenharmony_ci mov.w %sr,%d7 # save current SR 389262306a36Sopenharmony_ci ori.w &0x0700,%sr # inhibit interrupts 389362306a36Sopenharmony_ci 389462306a36Sopenharmony_ci# load the SFC and DFC with the appropriate mode. 389562306a36Sopenharmony_ci movc %sfc,%d6 # save old SFC/DFC 389662306a36Sopenharmony_ci movc %d0,%sfc # load new sfc 389762306a36Sopenharmony_ci movc %d0,%dfc # load new dfc 389862306a36Sopenharmony_ci 389962306a36Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because 390062306a36Sopenharmony_ci# _real_lock_page() should have taken care of this. 390162306a36Sopenharmony_ci plpaw (%a1) # load atc for ADDR 390262306a36Sopenharmony_ci plpaw (%a2) # load atc for ADDR+1 390362306a36Sopenharmony_ci 390462306a36Sopenharmony_ci# push the operand lines from the cache if they exist. 390562306a36Sopenharmony_ci cpushl %dc,(%a1) # push dirty data 390662306a36Sopenharmony_ci cpushl %dc,(%a2) # push dirty data 390762306a36Sopenharmony_ci 390862306a36Sopenharmony_ci# load the BUSCR values. 390962306a36Sopenharmony_ci mov.l &0x80000000,%a1 # assert LOCK* buscr value 391062306a36Sopenharmony_ci mov.l &0xa0000000,%a2 # assert LOCKE* buscr value 391162306a36Sopenharmony_ci mov.l &0x00000000,%a3 # buscr unlock value 391262306a36Sopenharmony_ci 391362306a36Sopenharmony_ci# pre-load the instruction cache for the following algorithm. 391462306a36Sopenharmony_ci# this will minimize the number of cycles that LOCK* will be asserted. 391562306a36Sopenharmony_ci bra.b CASW_ENTER # start pre-loading icache 391662306a36Sopenharmony_ci 391762306a36Sopenharmony_ci# 391862306a36Sopenharmony_ci# D0 = dst operand <- 391962306a36Sopenharmony_ci# D1 = update[15:8] operand 392062306a36Sopenharmony_ci# D2 = update[7:0] operand 392162306a36Sopenharmony_ci# D3 = xxxxxxxx 392262306a36Sopenharmony_ci# D4 = compare[15:0] operand 392362306a36Sopenharmony_ci# D5 = xxxxxxxx 392462306a36Sopenharmony_ci# D6 = old SFC/DFC 392562306a36Sopenharmony_ci# D7 = old SR 392662306a36Sopenharmony_ci# A0 = ADDR 392762306a36Sopenharmony_ci# A1 = bus LOCK* value 392862306a36Sopenharmony_ci# A2 = bus LOCKE* value 392962306a36Sopenharmony_ci# A3 = bus unlock value 393062306a36Sopenharmony_ci# A4 = xxxxxxxx 393162306a36Sopenharmony_ci# A5 = xxxxxxxx 393262306a36Sopenharmony_ci# 393362306a36Sopenharmony_ci align 0x10 393462306a36Sopenharmony_ciCASW_START: 393562306a36Sopenharmony_ci movc %a1,%buscr # assert LOCK* 393662306a36Sopenharmony_ci movs.w (%a0),%d0 # fetch Dest[15:0] 393762306a36Sopenharmony_ci cmp.w %d0,%d4 # Dest - Compare 393862306a36Sopenharmony_ci bne.b CASW_NOUPDATE 393962306a36Sopenharmony_ci bra.b CASW_UPDATE 394062306a36Sopenharmony_ciCASW_ENTER: 394162306a36Sopenharmony_ci bra.b ~+16 394262306a36Sopenharmony_ci 394362306a36Sopenharmony_ciCASW_UPDATE: 394462306a36Sopenharmony_ci movs.b %d2,(%a0)+ # Update[15:8] -> DEST 394562306a36Sopenharmony_ci movc %a2,%buscr # assert LOCKE* 394662306a36Sopenharmony_ci movs.b %d3,(%a0) # Update[7:0] -> DEST+0x1 394762306a36Sopenharmony_ci bra.b CASW_UPDATE2 394862306a36Sopenharmony_ci bra.b ~+16 394962306a36Sopenharmony_ci 395062306a36Sopenharmony_ciCASW_UPDATE2: 395162306a36Sopenharmony_ci movc %a3,%buscr # unlock the bus 395262306a36Sopenharmony_ci bra.b casw_update_done 395362306a36Sopenharmony_ci nop 395462306a36Sopenharmony_ci nop 395562306a36Sopenharmony_ci nop 395662306a36Sopenharmony_ci nop 395762306a36Sopenharmony_ci bra.b ~+16 395862306a36Sopenharmony_ci 395962306a36Sopenharmony_ciCASW_NOUPDATE: 396062306a36Sopenharmony_ci ror.l &0x8,%d0 # get Dest[15:8] 396162306a36Sopenharmony_ci movs.b %d0,(%a0)+ # Dest[15:8] -> DEST 396262306a36Sopenharmony_ci movc %a2,%buscr # assert LOCKE* 396362306a36Sopenharmony_ci rol.l &0x8,%d0 # get Dest[7:0] 396462306a36Sopenharmony_ci bra.b CASW_NOUPDATE2 396562306a36Sopenharmony_ci bra.b ~+16 396662306a36Sopenharmony_ci 396762306a36Sopenharmony_ciCASW_NOUPDATE2: 396862306a36Sopenharmony_ci movs.b %d0,(%a0) # Dest[7:0] -> DEST+0x1 396962306a36Sopenharmony_ci movc %a3,%buscr # unlock the bus 397062306a36Sopenharmony_ci bra.b casw_noupdate_done 397162306a36Sopenharmony_ci nop 397262306a36Sopenharmony_ci nop 397362306a36Sopenharmony_ci bra.b ~+16 397462306a36Sopenharmony_ci 397562306a36Sopenharmony_ciCASW_FILLER: 397662306a36Sopenharmony_ci nop 397762306a36Sopenharmony_ci nop 397862306a36Sopenharmony_ci nop 397962306a36Sopenharmony_ci nop 398062306a36Sopenharmony_ci nop 398162306a36Sopenharmony_ci nop 398262306a36Sopenharmony_ci nop 398362306a36Sopenharmony_ci bra.b CASW_START 398462306a36Sopenharmony_ci 398562306a36Sopenharmony_ci################################################################# 398662306a36Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON # 398762306a36Sopenharmony_ci# CALLING _isp_cas_finish(). # 398862306a36Sopenharmony_ci# # 398962306a36Sopenharmony_ci# D0 = destination[15:0] operand # 399062306a36Sopenharmony_ci# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required # 399162306a36Sopenharmony_ci# D2 = xxxxxxxx # 399262306a36Sopenharmony_ci# D3 = xxxxxxxx # 399362306a36Sopenharmony_ci# D4 = compare[15:0] operand # 399462306a36Sopenharmony_ci# D5 = xxxxxxxx # 399562306a36Sopenharmony_ci# D6 = xxxxxxxx # 399662306a36Sopenharmony_ci# D7 = xxxxxxxx # 399762306a36Sopenharmony_ci# A0 = xxxxxxxx # 399862306a36Sopenharmony_ci# A1 = xxxxxxxx # 399962306a36Sopenharmony_ci# A2 = xxxxxxxx # 400062306a36Sopenharmony_ci# A3 = xxxxxxxx # 400162306a36Sopenharmony_ci# A4 = xxxxxxxx # 400262306a36Sopenharmony_ci# A5 = xxxxxxxx # 400362306a36Sopenharmony_ci# A6 = frame pointer # 400462306a36Sopenharmony_ci# A7 = stack pointer # 400562306a36Sopenharmony_ci################################################################# 400662306a36Sopenharmony_ci 400762306a36Sopenharmony_cicasw_noupdate_done: 400862306a36Sopenharmony_ci 400962306a36Sopenharmony_ci# restore previous SFC/DFC value. 401062306a36Sopenharmony_ci movc %d6,%sfc # restore old SFC 401162306a36Sopenharmony_ci movc %d6,%dfc # restore old DFC 401262306a36Sopenharmony_ci 401362306a36Sopenharmony_ci# restore previous interrupt mask level. 401462306a36Sopenharmony_ci mov.w %d7,%sr # restore old SR 401562306a36Sopenharmony_ci 401662306a36Sopenharmony_ci sf %d1 # indicate no update was done 401762306a36Sopenharmony_ci bra.l _isp_cas_finish 401862306a36Sopenharmony_ci 401962306a36Sopenharmony_cicasw_update_done: 402062306a36Sopenharmony_ci 402162306a36Sopenharmony_ci# restore previous SFC/DFC value. 402262306a36Sopenharmony_ci movc %d6,%sfc # restore old SFC 402362306a36Sopenharmony_ci movc %d6,%dfc # restore old DFC 402462306a36Sopenharmony_ci 402562306a36Sopenharmony_ci# restore previous interrupt mask level. 402662306a36Sopenharmony_ci mov.w %d7,%sr # restore old SR 402762306a36Sopenharmony_ci 402862306a36Sopenharmony_ci st %d1 # indicate update was done 402962306a36Sopenharmony_ci bra.l _isp_cas_finish 403062306a36Sopenharmony_ci 403162306a36Sopenharmony_ci################ 403262306a36Sopenharmony_ci 403362306a36Sopenharmony_ci# there are two possible mis-aligned cases for longword cas. they 403462306a36Sopenharmony_ci# are separated because the final write which asserts LOCKE* must 403562306a36Sopenharmony_ci# be an aligned write. 403662306a36Sopenharmony_cicasl: 403762306a36Sopenharmony_ci mov.l %a0,%a1 # make copy for plpaw1 403862306a36Sopenharmony_ci mov.l %a0,%a2 # make copy for plpaw2 403962306a36Sopenharmony_ci addq.l &0x3,%a2 # plpaw2 points to end of longword 404062306a36Sopenharmony_ci 404162306a36Sopenharmony_ci mov.l %a0,%d1 # byte or word misaligned? 404262306a36Sopenharmony_ci btst &0x0,%d1 404362306a36Sopenharmony_ci bne.w casl2 # byte misaligned 404462306a36Sopenharmony_ci 404562306a36Sopenharmony_ci mov.l %d2,%d3 # d3 = update[15:0] 404662306a36Sopenharmony_ci swap %d2 # d2 = update[31:16] 404762306a36Sopenharmony_ci 404862306a36Sopenharmony_ci# mask interrupts levels 0-6. save old mask value. 404962306a36Sopenharmony_ci mov.w %sr,%d7 # save current SR 405062306a36Sopenharmony_ci ori.w &0x0700,%sr # inhibit interrupts 405162306a36Sopenharmony_ci 405262306a36Sopenharmony_ci# load the SFC and DFC with the appropriate mode. 405362306a36Sopenharmony_ci movc %sfc,%d6 # save old SFC/DFC 405462306a36Sopenharmony_ci movc %d0,%sfc # load new sfc 405562306a36Sopenharmony_ci movc %d0,%dfc # load new dfc 405662306a36Sopenharmony_ci 405762306a36Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because 405862306a36Sopenharmony_ci# _real_lock_page() should have taken care of this. 405962306a36Sopenharmony_ci plpaw (%a1) # load atc for ADDR 406062306a36Sopenharmony_ci plpaw (%a2) # load atc for ADDR+3 406162306a36Sopenharmony_ci 406262306a36Sopenharmony_ci# push the operand lines from the cache if they exist. 406362306a36Sopenharmony_ci cpushl %dc,(%a1) # push dirty data 406462306a36Sopenharmony_ci cpushl %dc,(%a2) # push dirty data 406562306a36Sopenharmony_ci 406662306a36Sopenharmony_ci# load the BUSCR values. 406762306a36Sopenharmony_ci mov.l &0x80000000,%a1 # assert LOCK* buscr value 406862306a36Sopenharmony_ci mov.l &0xa0000000,%a2 # assert LOCKE* buscr value 406962306a36Sopenharmony_ci mov.l &0x00000000,%a3 # buscr unlock value 407062306a36Sopenharmony_ci 407162306a36Sopenharmony_ci bra.b CASL_ENTER # start pre-loading icache 407262306a36Sopenharmony_ci 407362306a36Sopenharmony_ci# 407462306a36Sopenharmony_ci# D0 = dst operand <- 407562306a36Sopenharmony_ci# D1 = xxxxxxxx 407662306a36Sopenharmony_ci# D2 = update[31:16] operand 407762306a36Sopenharmony_ci# D3 = update[15:0] operand 407862306a36Sopenharmony_ci# D4 = compare[31:0] operand 407962306a36Sopenharmony_ci# D5 = xxxxxxxx 408062306a36Sopenharmony_ci# D6 = old SFC/DFC 408162306a36Sopenharmony_ci# D7 = old SR 408262306a36Sopenharmony_ci# A0 = ADDR 408362306a36Sopenharmony_ci# A1 = bus LOCK* value 408462306a36Sopenharmony_ci# A2 = bus LOCKE* value 408562306a36Sopenharmony_ci# A3 = bus unlock value 408662306a36Sopenharmony_ci# A4 = xxxxxxxx 408762306a36Sopenharmony_ci# A5 = xxxxxxxx 408862306a36Sopenharmony_ci# 408962306a36Sopenharmony_ci align 0x10 409062306a36Sopenharmony_ciCASL_START: 409162306a36Sopenharmony_ci movc %a1,%buscr # assert LOCK* 409262306a36Sopenharmony_ci movs.l (%a0),%d0 # fetch Dest[31:0] 409362306a36Sopenharmony_ci cmp.l %d0,%d4 # Dest - Compare 409462306a36Sopenharmony_ci bne.b CASL_NOUPDATE 409562306a36Sopenharmony_ci bra.b CASL_UPDATE 409662306a36Sopenharmony_ciCASL_ENTER: 409762306a36Sopenharmony_ci bra.b ~+16 409862306a36Sopenharmony_ci 409962306a36Sopenharmony_ciCASL_UPDATE: 410062306a36Sopenharmony_ci movs.w %d2,(%a0)+ # Update[31:16] -> DEST 410162306a36Sopenharmony_ci movc %a2,%buscr # assert LOCKE* 410262306a36Sopenharmony_ci movs.w %d3,(%a0) # Update[15:0] -> DEST+0x2 410362306a36Sopenharmony_ci bra.b CASL_UPDATE2 410462306a36Sopenharmony_ci bra.b ~+16 410562306a36Sopenharmony_ci 410662306a36Sopenharmony_ciCASL_UPDATE2: 410762306a36Sopenharmony_ci movc %a3,%buscr # unlock the bus 410862306a36Sopenharmony_ci bra.b casl_update_done 410962306a36Sopenharmony_ci nop 411062306a36Sopenharmony_ci nop 411162306a36Sopenharmony_ci nop 411262306a36Sopenharmony_ci nop 411362306a36Sopenharmony_ci bra.b ~+16 411462306a36Sopenharmony_ci 411562306a36Sopenharmony_ciCASL_NOUPDATE: 411662306a36Sopenharmony_ci swap %d0 # get Dest[31:16] 411762306a36Sopenharmony_ci movs.w %d0,(%a0)+ # Dest[31:16] -> DEST 411862306a36Sopenharmony_ci swap %d0 # get Dest[15:0] 411962306a36Sopenharmony_ci movc %a2,%buscr # assert LOCKE* 412062306a36Sopenharmony_ci bra.b CASL_NOUPDATE2 412162306a36Sopenharmony_ci bra.b ~+16 412262306a36Sopenharmony_ci 412362306a36Sopenharmony_ciCASL_NOUPDATE2: 412462306a36Sopenharmony_ci movs.w %d0,(%a0) # Dest[15:0] -> DEST+0x2 412562306a36Sopenharmony_ci movc %a3,%buscr # unlock the bus 412662306a36Sopenharmony_ci bra.b casl_noupdate_done 412762306a36Sopenharmony_ci nop 412862306a36Sopenharmony_ci nop 412962306a36Sopenharmony_ci bra.b ~+16 413062306a36Sopenharmony_ci 413162306a36Sopenharmony_ciCASL_FILLER: 413262306a36Sopenharmony_ci nop 413362306a36Sopenharmony_ci nop 413462306a36Sopenharmony_ci nop 413562306a36Sopenharmony_ci nop 413662306a36Sopenharmony_ci nop 413762306a36Sopenharmony_ci nop 413862306a36Sopenharmony_ci nop 413962306a36Sopenharmony_ci bra.b CASL_START 414062306a36Sopenharmony_ci 414162306a36Sopenharmony_ci################################################################# 414262306a36Sopenharmony_ci# THIS MUST BE THE STATE OF THE INTEGER REGISTER FILE UPON # 414362306a36Sopenharmony_ci# CALLING _isp_cas_finish(). # 414462306a36Sopenharmony_ci# # 414562306a36Sopenharmony_ci# D0 = destination[31:0] operand # 414662306a36Sopenharmony_ci# D1 = 'xxxxxx11 -> no reg update; 'xxxxxx00 -> update required # 414762306a36Sopenharmony_ci# D2 = xxxxxxxx # 414862306a36Sopenharmony_ci# D3 = xxxxxxxx # 414962306a36Sopenharmony_ci# D4 = compare[31:0] operand # 415062306a36Sopenharmony_ci# D5 = xxxxxxxx # 415162306a36Sopenharmony_ci# D6 = xxxxxxxx # 415262306a36Sopenharmony_ci# D7 = xxxxxxxx # 415362306a36Sopenharmony_ci# A0 = xxxxxxxx # 415462306a36Sopenharmony_ci# A1 = xxxxxxxx # 415562306a36Sopenharmony_ci# A2 = xxxxxxxx # 415662306a36Sopenharmony_ci# A3 = xxxxxxxx # 415762306a36Sopenharmony_ci# A4 = xxxxxxxx # 415862306a36Sopenharmony_ci# A5 = xxxxxxxx # 415962306a36Sopenharmony_ci# A6 = frame pointer # 416062306a36Sopenharmony_ci# A7 = stack pointer # 416162306a36Sopenharmony_ci################################################################# 416262306a36Sopenharmony_ci 416362306a36Sopenharmony_cicasl_noupdate_done: 416462306a36Sopenharmony_ci 416562306a36Sopenharmony_ci# restore previous SFC/DFC value. 416662306a36Sopenharmony_ci movc %d6,%sfc # restore old SFC 416762306a36Sopenharmony_ci movc %d6,%dfc # restore old DFC 416862306a36Sopenharmony_ci 416962306a36Sopenharmony_ci# restore previous interrupt mask level. 417062306a36Sopenharmony_ci mov.w %d7,%sr # restore old SR 417162306a36Sopenharmony_ci 417262306a36Sopenharmony_ci sf %d1 # indicate no update was done 417362306a36Sopenharmony_ci bra.l _isp_cas_finish 417462306a36Sopenharmony_ci 417562306a36Sopenharmony_cicasl_update_done: 417662306a36Sopenharmony_ci 417762306a36Sopenharmony_ci# restore previous SFC/DFC value. 417862306a36Sopenharmony_ci movc %d6,%sfc # restore old SFC 417962306a36Sopenharmony_ci movc %d6,%dfc # restore old DFC 418062306a36Sopenharmony_ci 418162306a36Sopenharmony_ci# restore previous interrupts mask level. 418262306a36Sopenharmony_ci mov.w %d7,%sr # restore old SR 418362306a36Sopenharmony_ci 418462306a36Sopenharmony_ci st %d1 # indicate update was done 418562306a36Sopenharmony_ci bra.l _isp_cas_finish 418662306a36Sopenharmony_ci 418762306a36Sopenharmony_ci####################################### 418862306a36Sopenharmony_cicasl2: 418962306a36Sopenharmony_ci mov.l %d2,%d5 # d5 = Update[7:0] 419062306a36Sopenharmony_ci lsr.l &0x8,%d2 419162306a36Sopenharmony_ci mov.l %d2,%d3 # d3 = Update[23:8] 419262306a36Sopenharmony_ci swap %d2 # d2 = Update[31:24] 419362306a36Sopenharmony_ci 419462306a36Sopenharmony_ci# mask interrupts levels 0-6. save old mask value. 419562306a36Sopenharmony_ci mov.w %sr,%d7 # save current SR 419662306a36Sopenharmony_ci ori.w &0x0700,%sr # inhibit interrupts 419762306a36Sopenharmony_ci 419862306a36Sopenharmony_ci# load the SFC and DFC with the appropriate mode. 419962306a36Sopenharmony_ci movc %sfc,%d6 # save old SFC/DFC 420062306a36Sopenharmony_ci movc %d0,%sfc # load new sfc 420162306a36Sopenharmony_ci movc %d0,%dfc # load new dfc 420262306a36Sopenharmony_ci 420362306a36Sopenharmony_ci# pre-load the operand ATC. no page faults should occur here because 420462306a36Sopenharmony_ci# _real_lock_page() should have taken care of this already. 420562306a36Sopenharmony_ci plpaw (%a1) # load atc for ADDR 420662306a36Sopenharmony_ci plpaw (%a2) # load atc for ADDR+3 420762306a36Sopenharmony_ci 420862306a36Sopenharmony_ci# puch the operand lines from the cache if they exist. 420962306a36Sopenharmony_ci cpushl %dc,(%a1) # push dirty data 421062306a36Sopenharmony_ci cpushl %dc,(%a2) # push dirty data 421162306a36Sopenharmony_ci 421262306a36Sopenharmony_ci# load the BUSCR values. 421362306a36Sopenharmony_ci mov.l &0x80000000,%a1 # assert LOCK* buscr value 421462306a36Sopenharmony_ci mov.l &0xa0000000,%a2 # assert LOCKE* buscr value 421562306a36Sopenharmony_ci mov.l &0x00000000,%a3 # buscr unlock value 421662306a36Sopenharmony_ci 421762306a36Sopenharmony_ci# pre-load the instruction cache for the following algorithm. 421862306a36Sopenharmony_ci# this will minimize the number of cycles that LOCK* will be asserted. 421962306a36Sopenharmony_ci bra.b CASL2_ENTER # start pre-loading icache 422062306a36Sopenharmony_ci 422162306a36Sopenharmony_ci# 422262306a36Sopenharmony_ci# D0 = dst operand <- 422362306a36Sopenharmony_ci# D1 = xxxxxxxx 422462306a36Sopenharmony_ci# D2 = update[31:24] operand 422562306a36Sopenharmony_ci# D3 = update[23:8] operand 422662306a36Sopenharmony_ci# D4 = compare[31:0] operand 422762306a36Sopenharmony_ci# D5 = update[7:0] operand 422862306a36Sopenharmony_ci# D6 = old SFC/DFC 422962306a36Sopenharmony_ci# D7 = old SR 423062306a36Sopenharmony_ci# A0 = ADDR 423162306a36Sopenharmony_ci# A1 = bus LOCK* value 423262306a36Sopenharmony_ci# A2 = bus LOCKE* value 423362306a36Sopenharmony_ci# A3 = bus unlock value 423462306a36Sopenharmony_ci# A4 = xxxxxxxx 423562306a36Sopenharmony_ci# A5 = xxxxxxxx 423662306a36Sopenharmony_ci# 423762306a36Sopenharmony_ci align 0x10 423862306a36Sopenharmony_ciCASL2_START: 423962306a36Sopenharmony_ci movc %a1,%buscr # assert LOCK* 424062306a36Sopenharmony_ci movs.l (%a0),%d0 # fetch Dest[31:0] 424162306a36Sopenharmony_ci cmp.l %d0,%d4 # Dest - Compare 424262306a36Sopenharmony_ci bne.b CASL2_NOUPDATE 424362306a36Sopenharmony_ci bra.b CASL2_UPDATE 424462306a36Sopenharmony_ciCASL2_ENTER: 424562306a36Sopenharmony_ci bra.b ~+16 424662306a36Sopenharmony_ci 424762306a36Sopenharmony_ciCASL2_UPDATE: 424862306a36Sopenharmony_ci movs.b %d2,(%a0)+ # Update[31:24] -> DEST 424962306a36Sopenharmony_ci movs.w %d3,(%a0)+ # Update[23:8] -> DEST+0x1 425062306a36Sopenharmony_ci movc %a2,%buscr # assert LOCKE* 425162306a36Sopenharmony_ci bra.b CASL2_UPDATE2 425262306a36Sopenharmony_ci bra.b ~+16 425362306a36Sopenharmony_ci 425462306a36Sopenharmony_ciCASL2_UPDATE2: 425562306a36Sopenharmony_ci movs.b %d5,(%a0) # Update[7:0] -> DEST+0x3 425662306a36Sopenharmony_ci movc %a3,%buscr # unlock the bus 425762306a36Sopenharmony_ci bra.w casl_update_done 425862306a36Sopenharmony_ci nop 425962306a36Sopenharmony_ci bra.b ~+16 426062306a36Sopenharmony_ci 426162306a36Sopenharmony_ciCASL2_NOUPDATE: 426262306a36Sopenharmony_ci rol.l &0x8,%d0 # get Dest[31:24] 426362306a36Sopenharmony_ci movs.b %d0,(%a0)+ # Dest[31:24] -> DEST 426462306a36Sopenharmony_ci swap %d0 # get Dest[23:8] 426562306a36Sopenharmony_ci movs.w %d0,(%a0)+ # Dest[23:8] -> DEST+0x1 426662306a36Sopenharmony_ci bra.b CASL2_NOUPDATE2 426762306a36Sopenharmony_ci bra.b ~+16 426862306a36Sopenharmony_ci 426962306a36Sopenharmony_ciCASL2_NOUPDATE2: 427062306a36Sopenharmony_ci rol.l &0x8,%d0 # get Dest[7:0] 427162306a36Sopenharmony_ci movc %a2,%buscr # assert LOCKE* 427262306a36Sopenharmony_ci movs.b %d0,(%a0) # Dest[7:0] -> DEST+0x3 427362306a36Sopenharmony_ci bra.b CASL2_NOUPDATE3 427462306a36Sopenharmony_ci nop 427562306a36Sopenharmony_ci bra.b ~+16 427662306a36Sopenharmony_ci 427762306a36Sopenharmony_ciCASL2_NOUPDATE3: 427862306a36Sopenharmony_ci movc %a3,%buscr # unlock the bus 427962306a36Sopenharmony_ci bra.w casl_noupdate_done 428062306a36Sopenharmony_ci nop 428162306a36Sopenharmony_ci nop 428262306a36Sopenharmony_ci nop 428362306a36Sopenharmony_ci bra.b ~+16 428462306a36Sopenharmony_ci 428562306a36Sopenharmony_ciCASL2_FILLER: 428662306a36Sopenharmony_ci nop 428762306a36Sopenharmony_ci nop 428862306a36Sopenharmony_ci nop 428962306a36Sopenharmony_ci nop 429062306a36Sopenharmony_ci nop 429162306a36Sopenharmony_ci nop 429262306a36Sopenharmony_ci nop 429362306a36Sopenharmony_ci bra.b CASL2_START 429462306a36Sopenharmony_ci 429562306a36Sopenharmony_ci#### 429662306a36Sopenharmony_ci#### 429762306a36Sopenharmony_ci# end label used by _isp_cas_inrange() 429862306a36Sopenharmony_ci global _CASHI 429962306a36Sopenharmony_ci_CASHI: 4300