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