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