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