1changecom(`;');;; -*-Midas-*- 2;;; 3;;; Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 4;;; 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 5;;; 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 6;;; 2014 Massachusetts Institute of Technology 7;;; 8;;; This file is part of MIT/GNU Scheme. 9;;; 10;;; MIT/GNU Scheme is free software; you can redistribute it and/or 11;;; modify it under the terms of the GNU General Public License as 12;;; published by the Free Software Foundation; either version 2 of the 13;;; License, or (at your option) any later version. 14;;; 15;;; MIT/GNU Scheme is distributed in the hope that it will be useful, 16;;; but WITHOUT ANY WARRANTY; without even the implied warranty of 17;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18;;; General Public License for more details. 19;;; 20;;; You should have received a copy of the GNU General Public License 21;;; along with MIT/GNU Scheme; if not, write to the Free Software 22;;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 23;;; 02110-1301, USA. 24 25;;;; HP Precision Architecture assembly language part of the compiled 26;;;; code interface. See cmpint.txt, cmpint.c, cmpint-hppa.h, and 27;;;; cmpgc.h for more documentation. 28;;;; 29;;;; NOTE: 30;;;; Assumptions: 31;;;; 32;;;; 1) All registers (except double floating point registers) and 33;;;; stack locations hold a C long object. 34;;;; 35;;;; 2) The C compiler divides registers into three groups: 36;;;; - Linkage registers, used for procedure calls and global 37;;;; references. On HPPA: gr0 (always 0), gr2 (return address), 38;;;; gr27 (global data pointer), and gr30 (stack pointer). 39;;;; - super temporaries, not preserved accross procedure calls and 40;;;; always usable. On HPPA: gr1, gr19-gr26, gr28-29, gr31. 41;;;; gr26-23 are argument registers, gr28-29 are return registers. 42;;;; - preserved registers saved by the callee if they are written. 43;;;; On HPPA: gr3-gr18 44;;;; 45;;;; 3) Arguments, if passed on a stack, are popped by the caller 46;;;; or by the procedure return instruction (as on the VAX). Thus 47;;;; most "leaf" procedures need not worry about them. On HPPA: All 48;;;; arguments have slots in the stack, allocated and popped by the 49;;;; caller, but the first four words are actually passed in gr26, 50;;;; gr25, gr24, gr23, unless they are floating point arguments, in 51;;;; which case they are passed in floating point registers. 52;;;; 53;;;; 4) There is a hardware or software maintained stack for 54;;;; control. The procedure calling sequence may leave return 55;;;; addresses in registers, but they must be saved somewhere for 56;;;; nested calls and recursive procedures. On HPPA: Passed in a 57;;;; register, but a slot on the stack exists, allocated by the 58;;;; caller. The return link is in gr2 and immediately saved in 59;;;; -20(0,30) if the procedure makes further calls. The stack 60;;;; pointer is in gr30. 61;;;; 62;;;; 5) C procedures return long values in a super temporary 63;;;; register. Two word structures are returned in super temporary 64;;;; registers as well. On HPPA: gr28 is used for long returns, 65;;;; gr28/gr29 are used for two word structure returns. 66;;;; GCC returns two word structures differently: It passes 67;;;; the address of the structure in gr28! 68;;;; 69;;;; 6) Floating point registers are not preserved by this 70;;;; interface. The interface is only called from the Scheme 71;;;; interpreter, which does not use floating point data. Thus 72;;;; although the calling convention would require us to preserve 73;;;; them, they contain garbage. On HPPA: fr12-fr15 are 74;;;; callee-saves registers, fr4-fr7 are parameter registers, and 75;;;; fr8-fr11 are caller-saves registers. fr0-fr3 are status 76;;;; registers. 77;;;; 78;;;; Compiled Scheme code uses the following register convention. 79;;;; Note that scheme_to_interface_ble and the register block are 80;;;; preserved by C calls, but the others are not, since they change 81;;;; dynamically. scheme_to_interface and trampoline_to_interface can 82;;;; be reached at fixed offsets from scheme_to_interface_ble. 83;;;; - gr22 contains the Scheme stack pointer. 84;;;; - gr21 contains the Scheme free pointer. 85;;;; - gr20 contains a cached version of MemTop. 86;;;; - gr19 contains the dynamic link when needed. 87;;;; - gr5 contains the quad mask for machine pointers. 88;;;; - gr4 contains a pointer to the Scheme interpreter's 89;;;; "register" block. This block contains the compiler's copy of 90;;;; MemTop, the interpreter's registers (val, env, exp, etc), 91;;;; temporary locations for compiled code. 92;;;; - gr3 contains the address of scheme_to_interface_ble. 93;;;; 94;;;; All other registers are available to the compiler. A 95;;;; caller-saves convention is used, so the registers need not be 96;;;; preserved by subprocedures. 97;;;; 98;;;; ADB mnemonics: 99;;;; arg3 = gr23; arg2 = gr24; arg1 = gr25; arg0 = gr26 100;;;; dp = gr27; ret0 = gr28; ret1 = gr29; sp = gr30; rp = gr02 101 102changequote(",") 103define(HEX, "0x$1") 104define(ASM_DEBUG, 0) 105define(TC_LENGTH, ifdef("TYPE_CODE_LENGTH", TYPE_CODE_LENGTH, 6)) 106define(QUAD_MASK, eval(2 ** (TC_LENGTH - 2))) 107define(LOW_TC_BIT, eval(TC_LENGTH - 1)) 108define(DATUM_LENGTH, eval(32 - TC_LENGTH)) 109define(FIXNUM_LENGTH, DATUM_LENGTH) 110define(FIXNUM_POS, eval(FIXNUM_LENGTH - 1)) 111define(FIXNUM_BIT, eval(TC_LENGTH + 1)) 112define(TC_START, eval(TC_LENGTH - 1)) 113define(TC_FLONUM, 0x6) 114define(TC_VECTOR, 0xa) 115define(TC_FIXNUM, 0x1a) 116define(TC_STRING, 0x1e) 117define(TC_NMV, 0x27) 118define(TC_CCENTRY, 0x28) 119define(FLONUM_VECTOR_HEADER, eval((TC_NMV * (2 ** DATUM_LENGTH)) + 2)) 120define(TC_FALSE, 0) 121define(TC_TRUE, 0x8) 122define(SHARP_F, eval(TC_FALSE * (2 ** DATUM_LENGTH))) 123define(SHARP_T, eval(TC_TRUE * (2 ** DATUM_LENGTH))) 124define(C_FRAME_SIZE, 125 ifdef("HPC", 112, 126 ifdef("GCC", 120, 127 `Unknown C compiler: bad frame size'))) 128define(INT_BIT_STACK_OVERFLOW, 31) 129 130 .SPACE $TEXT$ 131 .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY 132C_to_interface 133 .PROC 134 .CALLINFO CALLER,FRAME=28,SAVE_RP 135 .ENTRY 136 STW 2,-20(0,30) ; Save return address 137 STWM 3,eval(C_FRAME_SIZE)(30) ; Save first reg, 138 STW 4,-108(30) ; and allocate frame 139 STW 5,-104(30) ; Save the other regs 140 STW 6,-100(30) 141 STW 7,-96(30) 142 STW 8,-92(30) 143 STW 9,-88(30) 144 STW 10,-84(30) 145 STW 11,-80(30) 146 STW 12,-76(30) 147 STW 13,-72(30) 148 STW 14,-68(30) 149 STW 15,-64(30) 150 STW 16,-60(30) 151 STW 17,-56(30) 152 STW 18,-52(30) 153 ADDIL L'Registers-$global$,27 154 LDO R'Registers-$global$(1),4 ; Setup Regs 155 LDI QUAD_MASK,5 156 157ep_interface_to_scheme 158 LDW 8(0,4),2 ; Move interpreter reg to val 159 COPY 2,19 ; Restore dynamic link if any 160 DEP 5,LOW_TC_BIT,TC_LENGTH,19 161 ADDIL L'sp_register-$global$,27 162 LDW R'sp_register-$global$(1),22 ; Setup stack pointer 163 164ep_interface_to_scheme_2 165 LDW 0(0,4),20 ; Setup memtop 166 ADDIL L'Free-$global$,27 167 LDW R'Free-$global$(1),21 ; Setup free 168 .CALL RTNVAL=GR ; out=28 169 BLE 0(5,26) ; Invoke entry point 170 COPY 31,3 ; Setup scheme_to_interface_ble 171 172scheme_to_interface_ble 173 ADDI 4,31,31 ; Skip over format word ... 174trampoline_to_interface 175 COPY 31,26 176 DEP 0,31,2,26 177scheme_to_interface 178 STW 2,8(0,4) ; Move val to interpreter reg 179 ADDIL L'hppa_utility_table-$global$,27 180 LDW R'hppa_utility_table-$global$(1),29 181 ADDIL L'sp_register-$global$,27 182 LDWX,S 28(0,29),29 ; Find handler 183 STW 22,R'sp_register-$global$(1) ; Update stack pointer 184 ADDIL L'Free-$global$,27 185 STW 21,R'Free-$global$(1) ; Update free 186 ifelse(ASM_DEBUG,1,"ADDIL L'interface_counter-$global$,27 187 LDW R'interface_counter-$global$(1),21 188 LDO 1(21),21 189 STW 21,R'interface_counter-$global$(1) 190 ADDIL L'interface_limit-$global$,27 191 LDW R'interface_limit-$global$(1),22 192 COMB,=,N 21,22,interface_break 193interface_proceed") 194 ifdef("GCC", "LDO -116(30),28") 195 .CALL ARGW0=GR,ARGW1=GR,ARGW2=GR,ARGW3=GR,RTNVAL=GR 196 BLE 0(4,29) ; Call handler 197 COPY 31,2 ; Setup return address 198 ifdef("GCC", "LDW -116(30),28 199 LDW -112(30),29") 200 BV 0(28) ; Call receiver 201 COPY 29,26 ; Setup entry point 202 203;; This sequence of NOPs is provided to allow for modification of 204;; the sequence that appears above without having to recompile the 205;; world. The compiler "knows" the distance between 206;; scheme_to_interface_ble and hook_jump_table (100 bytes) 207 208 ifelse(ASM_DEBUG,1,"","NOP 209 NOP 210 NOP 211 NOP 212 NOP 213 NOP 214 NOP") 215 ifdef("GCC","","NOP 216 NOP 217 NOP") 218 219;; This label is used by the trap handler 220 221ep_scheme_hooks_low 222hook_jump_table ; scheme_to_interface + 100 223store_closure_code_hook 224 B store_closure_code+4 225 LDIL L'0x23400000,20 ; LDIL opcode and register 226 227store_closure_entry_hook 228 B store_closure_entry+4 229 DEP 0,31,2,1 ; clear PC protection bits 230 231multiply_fixnum_hook 232 B multiply_fixnum+4 233 EXTRS 26,FIXNUM_POS,FIXNUM_LENGTH,26 ; arg1 234 235fixnum_quotient_hook 236 B fixnum_quotient+4 237 EXTRS 26,FIXNUM_POS,FIXNUM_LENGTH,26 ; arg1 238 239fixnum_remainder_hook 240 B fixnum_remainder+4 241 EXTRS 26,FIXNUM_POS,FIXNUM_LENGTH,26 ; arg1 242 243fixnum_lsh_hook 244 B fixnum_lsh+4 245 EXTRS 25,FIXNUM_POS,FIXNUM_LENGTH,25 ; arg2 246 247generic_plus_hook 248 B generic_plus+4 249 LDW 0(0,22),6 ; arg1 250 251generic_subtract_hook 252 B generic_subtract+4 253 LDW 0(0,22),6 ; arg1 254 255generic_times_hook 256 B generic_times+4 257 LDW 0(0,22),6 ; arg1 258 259generic_divide_hook 260 B generic_divide+4 261 LDW 0(0,22),6 ; arg1 262 263generic_equal_hook 264 B generic_equal+4 265 LDW 0(0,22),6 ; arg1 266 267generic_less_hook 268 B generic_less+4 269 LDW 0(0,22),6 ; arg1 270 271generic_greater_hook 272 B generic_greater+4 273 LDW 0(0,22),6 ; arg1 274 275generic_increment_hook 276 B generic_increment+4 277 LDW 0(0,22),6 ; arg1 278 279generic_decrement_hook 280 B generic_decrement+4 281 LDW 0(0,22),6 ; arg1 282 283generic_zero_hook 284 B generic_zero+4 285 LDW 0(0,22),6 ; arg1 286 287generic_positive_hook 288 B generic_positive+4 289 LDW 0(0,22),6 ; arg1 290 291generic_negative_hook 292 B generic_negative+4 293 LDW 0(0,22),6 ; arg1 294 295shortcircuit_apply_hook 296 B shortcircuit_apply+4 297 EXTRU 26,5,6,24 ; procedure type -> 24 298 299shortcircuit_apply_1_hook 300 B shortcircuit_apply_1+4 301 EXTRU 26,5,6,24 ; procedure type -> 24 302 303shortcircuit_apply_2_hook 304 B shortcircuit_apply_2+4 305 EXTRU 26,5,6,24 ; procedure type -> 24 306 307shortcircuit_apply_3_hook 308 B shortcircuit_apply_3+4 309 EXTRU 26,5,6,24 ; procedure type -> 24 310 311shortcircuit_apply_4_hook 312 B shortcircuit_apply_4+4 313 EXTRU 26,5,6,24 ; procedure type -> 24 314 315shortcircuit_apply_5_hook 316 B shortcircuit_apply_5+4 317 EXTRU 26,5,6,24 ; procedure type -> 24 318 319shortcircuit_apply_6_hook 320 B shortcircuit_apply_6+4 321 EXTRU 26,5,6,24 ; procedure type -> 24 322 323shortcircuit_apply_7_hook 324 B shortcircuit_apply_7+4 325 EXTRU 26,5,6,24 ; procedure type -> 24 326 327shortcircuit_apply_8_hook 328 B shortcircuit_apply_8+4 329 EXTRU 26,5,6,24 ; procedure type -> 24 330 331stack_and_interrupt_check_hook 332 B stack_and_interrupt_check+4 333 LDW 44(0,4),25 ; Stack_Guard -> r25 334 335invoke_primitive_hook 336 B invoke_primitive+4 337 DEPI 0,31,2,31 ; clear privilege bits 338 339vector_cons_hook 340 B vector_cons+4 341 LDW 0(0,22),26 ; length as fixnum 342 343string_allocate_hook 344 B string_allocate+4 345 LDW 0(0,22),26 ; length as fixnum 346 347floating_vector_cons_hook 348 B floating_vector_cons+4 349 LDW 0(0,22),26 ; length as fixnum 350 351flonum_sin_hook 352 B flonum_sin+4 353 COPY 22,18 354 355flonum_cos_hook 356 B flonum_cos+4 357 COPY 22,18 358 359flonum_tan_hook 360 B flonum_tan+4 361 COPY 22,18 362 363flonum_asin_hook 364 B flonum_asin+4 365 COPY 22,18 366 367flonum_acos_hook 368 B flonum_acos+4 369 COPY 22,18 370 371flonum_atan_hook 372 B flonum_atan+4 373 COPY 22,18 374 375flonum_exp_hook 376 B flonum_exp+4 377 COPY 22,18 378 379flonum_log_hook 380 B flonum_log+4 381 COPY 22,18 382 383flonum_truncate_hook 384 B flonum_truncate+4 385 COPY 22,18 386 387flonum_ceiling_hook 388 B flonum_ceiling+4 389 COPY 22,18 390 391flonum_floor_hook 392 B flonum_floor+4 393 COPY 22,18 394 395flonum_atan2_hook 396 B flonum_atan2+4 397 COPY 22,18 398 399compiled_code_bkpt_hook ; hook 44 (offset 451 + 1) 400 B compiled_code_bkpt+4 401 LDO -8(31),31 402 403compiled_closure_bkpt_hook ; hook 45 (offset 451 + 9) 404 B compiled_closure_bkpt+4 405 LDO -12(31),31 406 407copy_closure_pattern_hook 408 B copy_closure_pattern+4 409 LDW -3(0,31),29 ; offset 410 411copy_multiclosure_pattern_hook 412 B copy_multiclosure_pattern+4 413 LDW -3(0,31),29 ; offset 414 415closure_entry_bkpt_hook ; hook 48 (offset 451 + 33) 416 B closure_entry_bkpt+4 417 LDO -8(31),31 ; bump back to entry point 418 419;; 420;; Provide dummy trapping hooks in case a newer version of compiled 421;; code that expects more hooks is run. 422;; 423 424no_hook 425 BREAK 0,49 426 NOP 427 BREAK 0,50 428 NOP 429 BREAK 0,51 430 NOP 431 BREAK 0,52 432 NOP 433 BREAK 0,53 434 NOP 435 BREAK 0,54 436 NOP 437 BREAK 0,55 438 NOP 439 BREAK 0,56 440 NOP 441 BREAK 0,57 442 NOP 443 BREAK 0,58 444 NOP 445 BREAK 0,59 446 NOP 447 BREAK 0,60 448 NOP 449 BREAK 0,61 450 NOP 451 BREAK 0,62 452 NOP 453 BREAK 0,63 454 NOP 455 456ifelse(ASM_DEBUG,1,"interface_break 457 COMB,= 21,22,interface_break 458 NOP 459 B,N interface_proceed") 460 461store_closure_entry 462;; 463;; On arrival, 31 has a return address and 1 contains the address to 464;; which the closure should jump with pc protection bits. 465;; 26 contains the format/gc-offset word for this entry. 466;; 467 DEP 0,31,2,1 ; clear PC protection bits 468 STWM 26,4(0,21) ; move format long to heap 469;; fall through to store_closure_code 470 471store_closure_code 472;; 473;; On arrival, 31 has a return address and 1 contains the address to 474;; which the closure should jump. The appropriate instructions (LDIL 475;; and BLE and SUBI) are pushed on the heap. 476;; Important: 477;; 3 words in memory are modified, but only 2 FDC instructions and one FIC 478;; instruction are issued. The PDC_CACHE description in the I/O Architecture 479;; manual specifies that each flush will flush a multiple of 16 bytes, thus 480;; a flush of the first data word and a flush of the last data word suffice to 481;; flush all three. A single FIC of the first instruction word suffices since 482;; the space is newly allocated and the whole I-cache was flushed at 483;; exec and relocation(GC) time. 484;; The SYNC is assumed to be separated by at least 7 instructions from 485;; the first execution of the new instructions. 486;; 487 LDIL L'0x23400000,20 ; LDIL opcode and register 488 EXTRU 1,0,1,5 489 DEP 5,31,1,20 490 EXTRU 1,11,11,5 491 DEP 5,30,11,20 492 EXTRU 1,13,2,5 493 DEP 5,17,2,20 494 EXTRU 1,18,5,5 495 DEP 5,15,5,20 496 STW 20,0(0,21) ; Store LDIL instruction 497 LDIL L'0xe7406000,20 ; BLE opcode, register 498 LDO R'0xe7406000(20),20 ; and nullify 499 EXTRU 1,19,1,5 500 DEP 5,29,1,20 501 EXTRU 1,29,10,5 502 DEP 5,28,10,20 503 STW 20,4(0,21) ; Store BLE instruction 504 LDIL L'0xb7ff07e9,20 505 LDO R'0xb7ff07e9(20),20 506 STW 20,8(0,21) ; Store ADDI instruction 507 LDI 12,20 508 FDC 0(0,21) ; flush 1st inst. from D-cache 509 FDC 20(0,21) ; flush last inst. from D-cache 510 SYNC 511 FIC,M 20(5,21) ; flush 1st inst. from I-cache 512 SYNC 513 LDW 0(0,4),20 ; Reload memtop 514 BE 0(5,31) ; Return 515 LDI QUAD_MASK,5 ; Restore register 5 516 517multiply_fixnum 518;; 519;; On arrival, 31 has a return address and 26 and 25 have the fixnum arguments. 520;; 521 EXTRS 26,FIXNUM_POS,FIXNUM_LENGTH,26 ; arg1 522 STW 26,0(0,21) 523 EXTRS 25,FIXNUM_POS,FIXNUM_LENGTH,25 ; arg2 524 STW 25,4(0,21) 525 ZDEPI 1,TC_LENGTH,1,26 ; FIXNUM_LIMIT 526 FLDWS 0(0,21),4 527 FLDWS 4(0,21),5 528 STW 26,8(0,21) ; FIXNUM_LIMIT 529 FCNVXF,SGL,DBL 4,4 ; arg1 530 FCNVXF,SGL,DBL 5,5 ; arg2 531 FMPY,DBL 4,5,4 532 FLDWS 8(0,21),5 ; FIXNUM_LIMIT 533 FCNVXF,SGL,DBL 5,5 ; FIXNUM_LIMIT 534 COPY 0,25 ; signal no overflow 535 FCMP,DBL,!>= 4,5 ; result too large? 536 FTEST 537 B,N multiply_fixnum_ovflw 538 FSUB,DBL 0,5,5 539 FCMP,DBL,!< 4,5 ; result too small? 540 FTEST 541 B,N multiply_fixnum_ovflw 542 FCNVFXT,DBL,SGL 4,5 543 FSTWS 5,0(0,21) ; result 544 LDW 0(0,21),26 545 BE 0(5,31) ; return 546 ZDEP 26,FIXNUM_POS,FIXNUM_LENGTH,26 ; make into fixnum 547;; 548multiply_fixnum_ovflw 549 COPY 0,26 550 LDO 1(0),25 ; signal overflow 551 BE 0(5,31) ; return 552 ZDEP 26,FIXNUM_POS,FIXNUM_LENGTH,26 ; make into fixnum 553 554fixnum_quotient 555;; 556;; On arrival, 31 has a return address and 26 and 25 have the fixnum arguments. 557;; Note that quotient only overflows when dividing by 0 and when the 558;; divisor is -1 and the dividend is the most negative fixnum, 559;; producing the most positive fixnum plus 1. 560;; 561 EXTRS 26,FIXNUM_POS,FIXNUM_LENGTH,26 ; arg1 562 COMB,= 0,25,fixnum_quotient_ovflw 563 STW 26,0(0,21) 564 EXTRS 25,FIXNUM_POS,FIXNUM_LENGTH,25 ; arg2 565 STW 25,4(0,21) 566 ZDEPI 1,TC_LENGTH,1,26 ; FIXNUM_LIMIT 567 FLDWS 0(0,21),4 568 FLDWS 4(0,21),5 569 FCNVXF,SGL,DBL 4,4 ; arg1 570 FCNVXF,SGL,DBL 5,5 ; arg2 571 FDIV,DBL 4,5,4 572 STW 26,0(0,21) ; FIXNUM_LIMIT 573 FCNVFXT,DBL,SGL 4,5 574 FSTWS 5,4(0,21) ; result 575 FLDWS 0(0,21),5 ; FIXNUM_LIMIT 576 FCNVXF,SGL,DBL 5,5 577 FCMP,DBL,!>= 4,5 ; result too large? 578 LDW 4(0,21),26 579 COPY 0,25 ; signal no overflow 580 FTEST 581;; 582fixnum_quotient_ovflw 583 LDO 1(0),25 ; signal overflow 584 BE 0(5,31) ; return 585 ZDEP 26,FIXNUM_POS,FIXNUM_LENGTH,26 ; make into fixnum 586 587;; fixnum_remainder 588;; 589;; NOTE: The following code is disabled because the FREM instruction 590;; has been dropped from the architecture and has never been 591;; implemented in hardware. 592;; 593;; On arrival, 31 has a return address and 26 and 25 have the fixnum arguments. 594;; Note that remainder only overflows when dividing by 0. 595;; Note also that the FREM instruction does not compute the same as 596;; the Scheme remainder operation. The sign of the result must 597;; sometimes be adjusted. 598;; 599;; EXTRS 26,FIXNUM_POS,FIXNUM_LENGTH,26 ; arg1 600;; COMB,=,N 0,25,fixnum_remainder_ovflw 601;; STW 26,0(0,21) 602;; EXTRS 25,FIXNUM_POS,FIXNUM_LENGTH,25 ; arg2 603;; STW 25,4(0,21) 604;; FLDWS 0(0,21),4 605;; FLDWS 4(0,21),5 606;; FCNVXF,SGL,DBL 4,4 ; arg1 607;; FCNVXF,SGL,DBL 5,5 ; arg2 608;; FREM,DBL 4,5,4 609;; FCNVFXT,DBL,SGL 4,5 610;; FSTWS 5,4(0,21) ; result 611;; LDW 4(0,21),1 612;; XOR,< 26,1,0 ; skip if signs != 613;; B,N fixnum_remainder_done 614;; COMB,=,N 0,1,fixnum_remainder_done 615;; XOR,< 26,25,0 ; skip if signs != 616;; ADD,TR 1,25,1 ; result += arg2 617;; SUB 1,25,1 ; result -= arg2 618;;;; 619;;fixnum_remainder_done 620;; ZDEP 1,FIXNUM_POS,FIXNUM_LENGTH,26 ; make into fixnum 621;; BE 0(5,31) ; return 622;; COPY 0,25 ; signal no overflow 623;;;; 624;;fixnum_remainder_ovflw 625;; BE 0(5,31) ; return 626;; LDO 1(0),25 ; signal overflow 627 628fixnum_remainder 629;; 630;; On arrival, 31 has a return address and 26 and 25 have the fixnum 631;; arguments. 632;; Remainder can overflow only if arg2 = 0. 633;; 634 EXTRS 26,FIXNUM_POS,FIXNUM_LENGTH,26 ; arg1 635 STWM 29,-4(0,22) ; Preserve gr29 636 COMB,=,N 0,25,fixnum_remainder_ovflw 637 STWM 31,-4(0,22) ; Preserve ret. add. 638 EXTRS 25,FIXNUM_POS,FIXNUM_LENGTH,25 ; arg2 639 STWM 26,-4(0,22) ; Preserve arg1 640 .CALL ;in=25,26;out=29; (MILLICALL) 641 BL $$remI,31 642 STWM 25,-4(0,22) ; Preserve arg2 643;; 644 LDWM 4(0,22),25 ; Restore arg2 645 LDWM 4(0,22),26 ; Restore arg1 646 XOR,< 26,29,0 ; Skip if signs != 647 B,N fixnum_remainder_done 648 COMB,=,N 0,29,fixnum_remainder_done 649 XOR,< 26,25,0 650 ADD,TR 29,25,29 ; setup result 651 SUB 29,25,29 652;; 653fixnum_remainder_done 654 ZDEP 29,FIXNUM_POS,FIXNUM_LENGTH,26 ; make into fixnum 655 LDWM 4(0,22),31 ; Restore ret. add. 656 COPY 0,25 ; signal no overflow 657 BE 0(5,31) ; return 658 LDWM 4(0,22),29 ; Restore gr29 659;; 660fixnum_remainder_ovflw 661 LDO 1(0),25 ; signal overflow 662 COPY 0,26 ; bogus return value 663 BE 0(5,31) ; return 664 LDWM 4(0,22),29 ; Restore gr29 665 666fixnum_lsh 667;; 668;; On arrival, 31 has a return address and 26 and 25 have the fixnum arguments. 669;; If arg2 is negative, it is a right shift, otherwise a left shift. 670;; 671 EXTRS 25,FIXNUM_POS,FIXNUM_LENGTH,25 ; arg2 672 COMB,<,N 0,25,fixnum_lsh_positive 673 SUB 0,25,25 ; negate, for right shift 674 COMICLR,> FIXNUM_LENGTH,25,0 675 LDI 31,25 ; shift right completely 676 MTSAR 25 677 VSHD 0,26,26 ; shift right 678 DEP 0,31,TC_LENGTH,26 ; normalize fixnum 679 BE 0(5,31) ; return 680 COPY 0,25 ; signal no overflow 681;; 682fixnum_lsh_positive 683 SUBI,> 32,25,25 ; shift amount for right shift 684 COPY 0,25 ; shift left completely 685 MTSAR 25 686 VSHD 26,0,26 ; shift right (32 - arg2) 687 BE 0(5,31) ; return 688 COPY 0,25 ; signal no overflow 689 690;;;; Generic arithmetic utilities. 691;;; On entry the arguments are on the Scheme stack, and the return 692;;; address immediately above them. 693 694define(define_generic_binary, 695"generic_$1 696 LDW 0(0,22),6 ; arg1 697 LDW 4(0,22),8 ; arg2 698 EXTRU 6,TC_START,TC_LENGTH,7 ; type of arg1 699 EXTRU 8,TC_START,TC_LENGTH,9 ; type of arg2 700 COMIB,<>,N TC_FLONUM,7,generic_$1_fail 701 COMIB,<>,N TC_FLONUM,9,generic_$1_fail 702 DEP 5,TC_START,TC_LENGTH,6 ; data segment quadrant bits 703 FLDDS 4(0,6),4 ; arg1 -> fr4 704 DEP 5,TC_START,TC_LENGTH,8 ; data segment quadrant bits 705 FLDDS 4(0,8),5 ; arg2 -> fr5 706 B binary_flonum_result ; cons flonum and return 707 $3,DBL 4,5,4 ; operate 708 709generic_$1_fail ; ?? * ??, out of line 710 B scheme_to_interface 711 LDI HEX($2),28 ; operation code") 712 713flonum_result 714unary_flonum_result 715 ADDI,TR 4,22,6 ; ret. add. location 716 717binary_flonum_result ; expects data in fr4. 718 LDO 8(22),6 ; ret. add. location 719 DEPI 4,31,3,21 ; align free 720 COPY 21,2 ; result (untagged) 721 LDW 0(0,6),8 ; return address 722 LDIL L'FLONUM_VECTOR_HEADER,7 723 ; LDO R'FLONUM_VECTOR_HEADER(7),7 ; Assembler bug! 724 ADDI R'FLONUM_VECTOR_HEADER,7,7 725 STWM 7,4(0,21) ; vector header 726 DEPI TC_FLONUM,TC_START,TC_LENGTH,2 ; tag flonum 727 DEP 5,TC_START,TC_LENGTH,8 ; data segment quadrant bits 728 FSTDS,MA 4,8(0,21) ; store floating data 729 BLE 0(5,8) ; return! 730 LDO 4(6),22 ; pop frame 731 732define(define_generic_binary_predicate, 733"generic_$1 734 LDW 0(0,22),6 ; arg1 735 LDW 4(0,22),8 ; arg2 736 EXTRU 6,TC_START,TC_LENGTH,7 ; type of arg1 737 EXTRU 8,TC_START,TC_LENGTH,9 ; type of arg2 738 COMIB,<>,N TC_FLONUM,7,generic_$1_one_unk 739 COMIB,<>,N TC_FLONUM,9,generic_$1_two_unk 740 DEP 5,TC_START,TC_LENGTH,6 ; data segment quadrant bits 741 FLDDS 4(0,6),4 ; arg1 -> fr4 742 DEP 5,TC_START,TC_LENGTH,8 ; data segment quadrant bits 743 FLDDS 4(0,8),5 ; arg2 -> fr5 744 LDO 8(22),22 ; pop args from stack 745 B generic_boolean_result ; cons answer and return 746 FCMP,DBL,$3 4,5 ; compare 747 748generic_$1_one_unk ; ~FLO * ?? 749 COMIB,<>,N TC_FLONUM,9,generic_$1_fail 750 COMICLR,= TC_FIXNUM,7,0 751 B,N generic_$1_fail 752 EXTRS 6,31,FIXNUM_LENGTH,6 ; sign extend arg1 753 STW 6,0(0,21) ; through memory into fpcp 754 LDO 8(22),22 ; pop args from stack 755 DEP 5,TC_START,TC_LENGTH,8 ; data segment quadrant bits 756 FLDWS 0(0,21),4 ; single int arg1 -> fr4 757 FLDDS 4(0,8),5 ; arg2 -> fr5 758 FCNVXF,SGL,DBL 4,4 ; convert to double float 759 B generic_boolean_result ; cons answer and return 760 FCMP,DBL,$3 4,5 ; compare 761 762generic_$1_two_unk ; FLO * ~FLO 763 COMICLR,= TC_FIXNUM,9,0 764 B,N generic_$1_fail 765 EXTRS 8,31,FIXNUM_LENGTH,8 ; sign extend arg2 766 STW 8,0(0,21) ; through memory into fpcp 767 LDO 8(22),22 ; pop args from stack 768 DEP 5,TC_START,TC_LENGTH,6 ; data segment quadrant bits 769 FLDWS 0(0,21),5 ; single int arg2 -> fr5 770 FLDDS 4(0,6),4 ; arg1 -> fr4 771 FCNVXF,SGL,DBL 5,5 ; convert to double float 772 B generic_boolean_result ; cons answer and return 773 FCMP,DBL,$3 4,5 ; compare 774 775generic_$1_fail ; ?? * ??, out of line 776 B scheme_to_interface 777 LDI HEX($2),28 ; operation code") 778 779generic_boolean_result 780 LDWM 4(0,22),8 ; return address 781 LDIL L'SHARP_T,2 782 FTEST 783 LDIL L'SHARP_F,2 784 DEP 5,TC_START,TC_LENGTH,8 ; data segment quadrant bits 785 BLE,N 0(5,8) ; return! 786 787define(define_generic_unary, 788"generic_$1 789 LDW 0(0,22),6 ; arg 790 EXTRU 6,TC_START,TC_LENGTH,7 ; type of arg 791 COMIB,<>,N TC_FLONUM,7,generic_$1_fail 792 LDI 1,7 ; constant 1 793 STW 7,0(0,21) ; into memory 794 DEP 5,TC_START,TC_LENGTH,6 ; data segment quadrant bits 795 FLDWS 0(0,21),5 ; 1 -> fr5 796 FLDDS 4(0,6),4 ; arg -> fr4 797 FCNVXF,SGL,DBL 5,5 ; convert to double float 798 B unary_flonum_result ; cons flonum and return 799 $3,DBL 4,5,4 ; operate 800 801generic_$1_fail 802 B scheme_to_interface 803 LDI HEX($2),28 ; operation code") 804 805define(define_generic_unary_predicate, 806"generic_$1 807 LDW 0(0,22),6 ; arg 808 EXTRU 6,TC_START,TC_LENGTH,7 ; type of arg 809 COMIB,<>,N TC_FLONUM,7,generic_$1_fail 810 DEP 5,TC_START,TC_LENGTH,6 ; data segment quadrant bits 811 FLDDS 4(0,6),4 ; arg -> fr4 812 LDO 4(22),22 ; pop arg from stack 813 B generic_boolean_result ; cons answer and return 814 FCMP,DBL,$3 4,0 ; compare 815 816generic_$1_fail 817 B scheme_to_interface 818 LDI HEX($2),28 ; operation code") 819 820define_generic_unary(decrement,22,FSUB) 821define_generic_binary(divide,23,FDIV) 822define_generic_binary_predicate(equal,24,=) 823define_generic_binary_predicate(greater,25,>) 824define_generic_unary(increment,26,FADD) 825define_generic_binary_predicate(less,27,<) 826define_generic_binary(subtract,28,FSUB) 827define_generic_binary(times,29,FMPY) 828define_generic_unary_predicate(negative,2a,<) 829define_generic_binary(plus,2b,FADD) 830define_generic_unary_predicate(positive,2c,>) 831define_generic_unary_predicate(zero,2d,=) 832 833;;;; Optimized procedure application for unknown procedures. 834;;; Procedure in r26, arity (for shortcircuit-apply) in r25. 835 836shortcircuit_apply 837 EXTRU 26,5,6,24 ; procedure type -> 24 838 COMICLR,= TC_CCENTRY,24,0 839 B,N shortcircuit_apply_lose 840 DEP 5,5,6,26 ; procedure -> address 841 LDB -3(0,26),23 ; procedure's frame-size 842 COMB,<>,N 25,23,shortcircuit_apply_lose 843 BLE,N 0(5,26) ; invoke procedure 844 845define(define_shortcircuit_fixed, 846"shortcircuit_apply_$1 847 EXTRU 26,5,6,24 ; procedure type -> 24 848 COMICLR,= TC_CCENTRY,24,0 849 B shortcircuit_apply_lose 850 LDI $1,25 851 DEP 5,5,6,26 ; procedure -> address 852 LDB -3(0,26),23 ; procedure's frame-size 853 COMB,<>,N 25,23,shortcircuit_apply_lose 854 BLE,N 0(5,26) ; invoke procedure") 855 856define_shortcircuit_fixed(1) 857define_shortcircuit_fixed(2) 858define_shortcircuit_fixed(3) 859define_shortcircuit_fixed(4) 860define_shortcircuit_fixed(5) 861define_shortcircuit_fixed(6) 862define_shortcircuit_fixed(7) 863define_shortcircuit_fixed(8) 864 865shortcircuit_apply_lose 866 DEP 24,5,6,26 ; insert type back 867 B scheme_to_interface 868 LDI 0x14,28 869 870;;; Return address in r31. r26 contains the offset from the return 871;;; address to the interrupt invocation label. 872 873stack_and_interrupt_check 874 LDW 44(0,4),25 ; Stack_Guard -> r25 875 LDW 0(0,4),20 ; MemTop -> r20 876;;; 877;;; If the Scheme stack pointer is <= Stack_Guard, then the stack has 878;;; overflowed -- in which case we must signal a stack-overflow interrupt. 879 COMB,<=,N 22,25,stack_and_interrupt_check_stack_overflow 880;;; 881;;; If (Free >= MemTop), signal an interrupt. 882 COMB,>=,N 21,20,stack_and_interrupt_check_signal_interrupt 883;;; 884;;; Otherwise, return normally -- there's nothing to do. 885 BE 0(5,31) 886 NOP 887 888stack_and_interrupt_check_stack_overflow 889 LDW 48(0,4),25 ; IntCode -> r25 890 LDW 4(0,4),24 ; IntEnb -> r24 891;;; 892;;; Set the stack-overflow interrupt bit and write the interrupt word 893;;; back out to memory. If the stack-overflow interrupt is disabled, 894;;; skip forward to gc test. Otherwise, set MemTop to -1 and signal 895;;; the interrupt. 896 DEPI 1,INT_BIT_STACK_OVERFLOW,1,25 897 BB,>= 24,INT_BIT_STACK_OVERFLOW,stack_and_interrupt_check_no_overflow 898 STW 25,48(0,4) ; r25 -> IntCode 899 ADDI -1,0,20 ; -1 -> r20 900 STW 20,0(0,4) ; r20 -> MemTop 901;;; 902;;; If (Free >= MemTop), signal an interrupt. 903stack_and_interrupt_check_no_overflow 904 SUB,< 21,20,0 ; skip next inst. 905 ; if (Free < MemTop) 906;;; 907;;; To signal the interrupt, add the interrupt invocation offset to 908;;; the return address, then return normally. 909stack_and_interrupt_check_signal_interrupt 910 ADD 26,31,31 911 BE 0(5,31) ; return 912 NOP 913 914;;; invoke_primitive and *cons all have the same interface: 915;;; The "return address" in r31 points to a word containing 916;;; the distance between itself and the word in memory containing 917;;; the primitive object. 918;;; All arguments are passed on the stack, ready for the primitive. 919 920invoke_primitive 921 DEPI 0,31,2,31 ; clear privilege bits 922 LDW 0(0,31),26 ; get offset 923 ADDIL L'hppa_primitive_table-$global$,27 924 LDWX 26(0,31),26 ; get primitive 925 LDW R'hppa_primitive_table-$global$(1),25 926 EXTRU 26,31,DATUM_LENGTH,24 ; get primitive index 927 STW 26,32(0,4) ; store primitive 928 ADDIL L'Primitive_Arity_Table-$global$,27 929 LDW R'Primitive_Arity_Table-$global$(1),18 930 LDWX,S 24(0,25),25 ; find primitive entry point 931 ADDIL L'sp_register-$global$,27 932 STW 22,R'sp_register-$global$(1) ; Update stack pointer 933 ADDIL L'Free-$global$,27 934 LDWX,S 24(0,18),18 ; primitive arity 935 STW 21,R'Free-$global$(1) ; Update free 936 .CALL RTNVAL=GR ; out=28 937 BLE 0(4,25) ; Call primitive 938 COPY 31,2 ; Setup return address 939 940 ADDIL L'sp_register-$global$,27 941 LDW R'sp_register-$global$(1),22 ; Setup stack pointer 942 COPY 28,2 ; Move result to val 943 SH2ADD 18,22,22 ; pop frame 944 LDWM 4(0,22),26 ; return address as object 945 STW 0,32(0,4) ; clear primitive 946 B ep_interface_to_scheme_2 947 DEP 5,TC_START,TC_LENGTH,26 ; return address as address 948 949;;; The BLE in invoke_primitive can jump here. 950;;; The primitive index is in gr24 951 952cross_segment_call 953 ADDIL L'Primitive_Procedure_Table-$global$,27 954 LDW R'Primitive_Procedure_Table-$global$(1),22 955 LDWX,S 24(0,22),22 956 B,N $$dyncall ; ignore the return address 957 958vector_cons 959 LDW 0(0,22),26 ; length as fixnum 960 COPY 21,2 961 ZDEP 26,31,DATUM_LENGTH,26 ; length as machine word 962 SH2ADD 26,21,25 ; end of data (-1) 963 COMBF,< 25,20,invoke_primitive ; no space, use primitive 964 LDW 4(0,22),24 ; fill value 965 LDO 4(25),21 ; allocate! 966 STW 26,0(0,2) ; vector length (0-tagged) 967 LDO 4(2),23 ; start location 968 969vector_cons_loop 970 COMBT,<,N 23,21,vector_cons_loop 971 STWM 24,4(0,23) ; initialize 972 973 LDW 8(0,22),25 ; return address as object 974 DEPI TC_VECTOR,TC_START,TC_LENGTH,2 ; tag result 975 DEP 5,TC_START,TC_LENGTH,25 ; return address as address 976 BLE 0(5,25) ; return! 977 LDO 12(22),22 ; pop stack frame 978 979string_allocate 980 LDW 0(0,22),26 ; length as fixnum 981 COPY 21,2 ; return value 982 ZDEP 26,31,DATUM_LENGTH,26 ; length as machine word 983 ADD 26,21,25 ; end of data (-(9+round)) 984 COMBF,< 25,20,invoke_primitive ; no space, use primitive 985 SHD 0,26,2,24 ; scale down to word 986 STB 0,8(0,25) ; end-of-string #\NUL 987 LDO 2(24),24 ; total word size (-1) 988 STWS,MB 26,4(0,21) ; store string length 989 LDI TC_NMV,1 990 SH2ADD 24,21,21 ; allocate! 991 DEP 1,TC_START,TC_LENGTH,24 ; tag header 992 LDW 4(0,22),25 ; return address as object 993 STW 24,0(0,2) ; store nmv header 994 LDI TC_STRING,1 995 DEP 5,TC_START,TC_LENGTH,25 ; return address as address 996 DEP 1,TC_START,TC_LENGTH,2 ; tag result 997 BLE 0(5,25) ; return! 998 LDO 8(22),22 ; pop stack frame 999 1000floating_vector_cons 1001 LDW 0(0,22),26 ; length as fixnum 1002 ; STW 0,0(0,21) ; make heap parseable 1003 DEPI 4,31,3,21 ; bump free past header 1004 COPY 21,2 ; return value 1005 ZDEP 26,31,DATUM_LENGTH,26 ; length as machine word 1006 SH3ADD 26,21,25 ; end of data (-1) 1007 COMBF,< 25,20,invoke_primitive ; no space, use primitive 1008 SHD 26,0,31,26 ; scale, harmless in delay slot 1009 LDO 4(25),21 ; allocate! 1010 LDI TC_NMV,1 1011 DEP 1,TC_START,TC_LENGTH,26 ; tag header 1012 LDW 4(0,22),25 ; return address as object 1013 STW 26,0(0,2) ; store nmv header 1014 DEPI TC_FLONUM,TC_START,TC_LENGTH,2 ; tag result 1015 DEP 5,TC_START,TC_LENGTH,25 ; return address as address 1016 BLE 0(5,25) ; return! 1017 LDO 8(22),22 ; pop stack frame 1018 1019define(define_floating_point_util, 1020"flonum_$1 1021 STW 2,8(0,4) ; preserve val 1022 COPY 22,18 ; preserve regs 1023 COPY 21,17 1024 COPY 19,16 1025 .CALL ARGW0=FR,ARGW1=FU,RTNVAL=FU ;fpin=105;fpout=104; 1026 BL $2,2 1027 COPY 31,15 1028 COPY 16,19 1029 COPY 17,21 1030 COPY 18,22 1031 LDW 8(0,4),2 ; restore val 1032 BE 0(5,15) 1033 LDW 0(0,4),20") 1034 1035define_floating_point_util(sin,sin) 1036define_floating_point_util(cos,cos) 1037define_floating_point_util(tan,tan) 1038define_floating_point_util(asin,asin) 1039define_floating_point_util(acos,acos) 1040define_floating_point_util(atan,atan) 1041define_floating_point_util(exp,exp) 1042define_floating_point_util(log,log) 1043define_floating_point_util(truncate,double_truncate) 1044define_floating_point_util(ceiling,ceil) 1045define_floating_point_util(floor,floor) 1046 1047flonum_atan2 1048 STW 2,8(0,4) ; preserve val 1049 COPY 22,18 ; preserve regs 1050 COPY 21,17 1051 COPY 19,16 1052 .CALL ARGW0=FR,ARGW1=FU,ARGW2=FR,ARGW3=FU,RTNVAL=FU ;fpin=105,107;fpout=104; 1053 BL atan2,2 1054 COPY 31,15 1055 COPY 16,19 1056 COPY 17,21 1057 COPY 18,22 1058 LDW 8(0,4),2 ; restore val 1059 BE 0(5,15) 1060 LDW 0(0,4),20 1061 1062compiled_code_bkpt 1063 LDO -4(31),31 ; bump back to entry point 1064 COPY 19,25 ; Preserve Dynamic link 1065 B trampoline_to_interface 1066 LDI 0x3c,28 1067 1068compiled_closure_bkpt 1069 LDO -12(31),31 ; bump back to entry point 1070 B trampoline_to_interface 1071 LDI 0x3d,28 1072 1073closure_entry_bkpt 1074 LDO -4(31),31 ; bump back to entry point 1075 B trampoline_to_interface 1076 LDI 0x3c,28 1077 1078;; On arrival, 31 has a return address. The word at the return 1079;; address has the offset between the return address and the 1080;; closure pattern. 1081;; Returns the address of the entry point in 25 1082;; Used: 29, 28, 26, 25, fp11, fp10 [31] 1083 1084copy_closure_pattern 1085 LDW -3(0,31),29 ; offset 1086 DEPI 4,31,3,21 ; quad align 1087 ADD 29,31,29 ; addr of pattern 1088 LDWS,MA 4(0,29),28 ; load pattern header 1089 LDO 8(21),25 ; preserve for FDC & FIC 1090 STWS,MA 28,4(0,21) ; store pattern header 1091 FLDDS,MA 8(0,29),10 ; load entry 1092 FLDDS,MA 8(0,29),11 1093 FSTDS,MA 10,8(0,21) ; store entry 1094 FSTDS,MA 11,8(0,21) 1095 FDC 0(0,25) 1096 FDC 0(0,21) 1097 SYNC 1098 FIC 0(5,25) 1099 BE 4(5,31) 1100 SYNC 1101 1102;; On arrival, 31 has a return address and 1 contains the number of 1103;; entries in the closure. The word at the return address has the 1104;; offset between the return address and the closure pattern. 1105;; Returns the address of the entry point in 25 1106;; Used: 29, 28, 26, 25, fp11, fp10 [31, 1] 1107 1108copy_multiclosure_pattern 1109 LDW -3(0,31),29 ; offset 1110 DEPI 4,31,3,21 ; quad align 1111 ADD 29,31,29 ; addr of pattern 1112 LDWS,MA 4(0,29),28 ; load pattern header 1113 LDO 12(21),25 ; preserve for FIC 1114 STWS,MA 28,4(0,21) ; store pattern header 1115 LDI -16,26 ; FDC index 1116 1117copy_multiclosure_pattern_loop 1118 FLDDS,MA 8(0,29),10 ; load entry 1119 FLDDS,MA 8(0,29),11 1120 FSTDS,MA 10,8(0,21) ; store entry 1121 FSTDS,MA 11,8(0,21) 1122 ADDIB,> -1,1,copy_multiclosure_pattern_loop 1123 FDC 26(0,21) 1124 1125 LDWS,MA 4(0,29),28 ; load pattern tail 1126 COPY 21,26 1127 STWS,MA 28,4(0,21) ; store pattern tail 1128 FDC 0(0,26) 1129 SYNC 1130 FIC 0(5,25) 1131 BE 4(5,31) ; return 1132 SYNC 1133 1134;; This label is used by the trap handler 1135 1136ep_scheme_hooks_high 1137 1138;;;; Assembly language entry point used by utilities in cmpint.c 1139;;; to return to the interpreter. 1140;;; It returns from C_to_interface. 1141 1142ep_interface_to_C 1143 COPY 29,28 ; Setup C value 1144 LDW -eval(C_FRAME_SIZE+20)(0,30),2 ; Restore return address 1145 LDW -52(0,30),18 ; Restore saved registers 1146 LDW -56(0,30),17 1147 LDW -60(0,30),16 1148 LDW -64(0,30),15 1149 LDW -68(0,30),14 1150 LDW -72(0,30),13 1151 LDW -76(0,30),12 1152 LDW -80(0,30),11 1153 LDW -84(0,30),10 1154 LDW -88(0,30),9 1155 LDW -92(0,30),8 1156 LDW -96(0,30),7 1157 LDW -100(0,30),6 1158 LDW -104(0,30),5 1159 LDW -108(0,30),4 1160 BV 0(2) ; Return 1161 .EXIT 1162 LDWM -eval(C_FRAME_SIZE)(0,30),3 ; Restore last reg, pop frame 1163 .PROCEND ;in=26;out=28; 1164 1165;;;; Procedure to initialize this interface. 1166;;; 1167;;; C signature: 1168;;; 1169;;; void initialize_interface (void); 1170 1171interface_initialize 1172 .PROC 1173 .CALLINFO CALLER,FRAME=4,SAVE_RP 1174 .ENTRY 1175 STW 2,-20(0,30) ; Preserve return address 1176 LDO 64(30),30 ; Allocate stack frame 1177 STW 3,-64(30) ; Preserve gr3 1178 FSTWS 0,-4(30) 1179 LDW -4(30),22 1180 LDI 30,21 ; enable V, Z, O, U traps 1181 OR 21,22,22 1182 STW 22,-4(30) 1183 FLDWS -4(30),0 1184 ; Prepare entry points 1185 BL known_pc,3 ; get pc 1186 NOP 1187known_pc 1188 1189define(store_entry_point,"ADDIL L'ep_$1-known_pc,3 1190 LDO R'ep_$1-known_pc(1),29 1191 ADDIL L'$1-$global$,27 1192 STW 29,R'$1-$global$(1)") 1193 1194 store_entry_point(interface_to_scheme) 1195 store_entry_point(interface_to_C) 1196 1197changequote([,]) 1198define(builtin,[ADDIL L'$1-known_pc,3 1199 LDO R'$1-known_pc(1),26 1200 ADDIL L'$1_string-$global$,27 1201 .CALL ARGW0=GR 1202 BL declare_builtin,2 1203 LDO R'$1_string-$global$(1),25 divert(1) 1204$1_string 1205 .ALIGN 8 1206 .STRINGZ "$1" divert(0)]) 1207 1208 builtin(scheme_to_interface_ble) 1209 builtin(ep_scheme_hooks_low) 1210 builtin(store_closure_entry) 1211 builtin(store_closure_code) 1212 builtin(multiply_fixnum) 1213 builtin(fixnum_quotient) 1214 builtin(fixnum_remainder) 1215 builtin(fixnum_lsh) 1216 builtin(flonum_result) 1217 builtin(generic_boolean_result) 1218 builtin(generic_decrement) 1219 builtin(generic_divide) 1220 builtin(generic_equal) 1221 builtin(generic_greater) 1222 builtin(generic_increment) 1223 builtin(generic_less) 1224 builtin(generic_subtract) 1225 builtin(generic_times) 1226 builtin(generic_negative) 1227 builtin(generic_plus) 1228 builtin(generic_positive) 1229 builtin(generic_zero) 1230 builtin(shortcircuit_apply) 1231 builtin(shortcircuit_apply_1) 1232 builtin(shortcircuit_apply_2) 1233 builtin(shortcircuit_apply_3) 1234 builtin(shortcircuit_apply_4) 1235 builtin(shortcircuit_apply_5) 1236 builtin(shortcircuit_apply_6) 1237 builtin(shortcircuit_apply_7) 1238 builtin(shortcircuit_apply_8) 1239 builtin(stack_and_interrupt_check) 1240 builtin(invoke_primitive) 1241 builtin(cross_segment_call) 1242 builtin(vector_cons) 1243 builtin(string_allocate) 1244 builtin(floating_vector_cons) 1245 builtin(flonum_sin) 1246 builtin(flonum_cos) 1247 builtin(flonum_tan) 1248 builtin(flonum_asin) 1249 builtin(flonum_acos) 1250 builtin(flonum_atan) 1251 builtin(flonum_exp) 1252 builtin(flonum_log) 1253 builtin(flonum_truncate) 1254 builtin(flonum_ceiling) 1255 builtin(flonum_floor) 1256 builtin(flonum_atan2) 1257 builtin(compiled_code_bkpt) 1258 builtin(compiled_closure_bkpt) 1259 builtin(copy_closure_pattern) 1260 builtin(copy_multiclosure_pattern) 1261 builtin(ep_scheme_hooks_high) 1262changequote(",") 1263 ; Return 1264 LDW -84(30),2 ; Restore return address 1265 LDW -64(30),3 ; Restore gr3 1266 BV 0(2) 1267 .EXIT 1268 LDO -64(30),30 ; De-allocate stack frame 1269 .PROCEND 1270 1271;;;; Routine to flush some locations from the processor cache. 1272;;; 1273;;; Its C signature is 1274;;; 1275;;; void 1276;;; cache_flush_region (address, count, cache_set) 1277;;; void *address; 1278;;; long count; /* in long words */ 1279;;; unsigned int cache_set; 1280;;; 1281;;; cache_set is a bit mask of the flags I_CACHE (1) and D_CACHE (2). 1282;;; the requested cache (or both) is flushed. 1283;;; 1284;;; We only need to flush every 16 bytes, since cache lines are 1285;;; architecturally required to have cache line sizes that are 1286;;; multiples of 16 bytes. This is wasteful on processors with cache 1287;;; line sizes greater than 16 bytes, but this routine is typically 1288;;; called to flush very small ranges. 1289;;; We flush an additional time after flushing every 16 bytes since 1290;;; the start address may not be aligned with a cache line, and thus 1291;;; the end address may fall in a different cache line from the 1292;;; expected one. The extra flush is harmless when not necessary. 1293 1294cache_flush_region 1295 .PROC 1296 .CALLINFO CALLER,FRAME=0 1297 .ENTRY 1298 LDO 3(25),25 ; add 3 to round up 1299 SHD 0,25,2,25 ; divide count (in longs) by 4 1300 COPY 25,28 ; save for FIC loop 1301 COPY 26,29 ; save for FIC loop 1302 LDI 16,1 ; increment 1303 BB,>=,N 24,30,process_i_cache ; if D_CACHE is not set, 1304 ; skip d-cache 1305;;; 1306flush_cache_fdc_loop 1307 ADDIB,>= -1,25,flush_cache_fdc_loop 1308 FDC,M 1(0,26) 1309 SYNC 1310;;; 1311process_i_cache 1312 BB,>=,N 24,31,L$exit2 ; if I_CACHE is not set, return 1313;;; 1314flush_cache_fic_loop 1315 ADDIB,>= -1,28,flush_cache_fic_loop 1316 FIC,M 1(5,29) 1317;;; 1318L$exit2 1319 BV 0(2) 1320 .EXIT 1321 SYNC 1322 .PROCEND ;in=25,26; 1323 1324;;;; Routine to flush the processor cache. 1325;;; 1326;;; Its C signature is 1327;;; 1328;;; void 1329;;; cache_flush_all (cache_set, cache_info) 1330;;; unsigned int cache_set; 1331;;; struct pdc_cache_rtn_block *cache_info; 1332;;; 1333;;; cache_set is a bit mask of the flags I_CACHE (1) and D_CACHE (2). 1334;;; the requested cache (or both) is flushed. 1335;;; 1336;;; struct pdc_cache_rtn_block is defined in <machine/pdc_rqsts.h> and 1337;;; is the structure returned by the PDC_CACHE 1338;;; processor-dependent-code call, and stored in the kernel variable 1339;;; (HP-UX) "cache_tlb_parms". Only the cache parameters (and not the 1340;;; TLB parameters) are used. 1341 1342cache_flush_all 1343 .PROC 1344 .CALLINFO CALLER,FRAME=24 1345 .ENTRY 1346 1347do_d_cache 1348 BB,>=,N 26,30,do_i_cache ; if D_CACHE is not set, 1349 ; skip d-cache 1350 1351 LDW 32(0,25),31 ; 31 <- address (init. base) 1352 LDW 44(0,25),29 ; 29 <- loop 1353 LDW 36(0,25),23 ; 23 <- stride 1354 LDW 40(0,25),19 ; 19 <- count 1355 1356 LDO -1(19),19 ; decrement count 1357 COMIB,>,N 0,19,d_sync ; if (count < 0), no flush 1358 COMIB,=,N 1,29,d_direct_l 1359 COMIB,=,N 2,29,d_assoc2_l 1360 COMIB,=,N 4,29,d_assoc4_l 1361 1362d_assoc_l ; set-associative flush-loop 1363 COPY 29,20 ; 20 (lcount) <- loop 1364 1365d_set_l ; set flush-loop 1366 LDO -1(20),20 ; decrement lcount 1367 COMIB,<=,N 0,20,d_set_l ; if (lcount >= 0), set loop 1368 FDCE 0(0,31) ; flush entry at (address) 1369 1370 LDO -1(19),19 ; decrement count 1371 COMIB,<= 0,19,d_assoc_l ; if (count >= 0), loop 1372 ADD 31,23,31 ; address++ 1373 1374 B do_i_cache ; next 1375 SYNC ; synchronize after flush 1376 1377d_assoc4_l ; 4-way set-associative loop 1378 FDCE 0(0,31) ; flush entry at (*address) 1379 FDCE 0(0,31) ; flush entry at (*address) 1380 FDCE 0(0,31) ; flush entry at (*address) 1381 FDCE,M 23(0,31) ; flush entry at (*address++) 1382 COMIB,< 0,19,d_assoc4_l ; if (count > 0), loop 1383 LDO -1(19),19 ; decrement count 1384 1385 B do_i_cache ; next 1386 SYNC ; synchronize after flush 1387 1388d_assoc2_l ; 2-way set-associative loop 1389 FDCE 0(0,31) ; flush entry at (*address) 1390 FDCE,M 23(0,31) ; flush entry at (*address++) 1391 COMIB,< 0,19,d_assoc2_l ; if (count > 0), loop 1392 LDO -1(19),19 ; decrement count 1393 1394 B do_i_cache ; next 1395 SYNC ; synchronize after flush 1396 1397d_direct_l ; direct-mapped flush loop 1398 FDCE,M 23(0,31) ; flush entry at (*address++) 1399 COMIB,< 0,19,d_direct_l ; if (count > 0), loop 1400 LDO -1(19),19 ; decrement count 1401 1402d_sync 1403 SYNC ; synchronize after flush 1404 1405do_i_cache 1406 BB,>=,N 26,31,L$exit1 ; if I_CACHE is not set, return 1407 1408 LDW 8(0,25),31 ; 31 <- address (init. base) 1409 LDW 20(0,25),29 ; 29 <- loop 1410 LDW 12(0,25),23 ; 23 <- stride 1411 LDW 16(0,25),19 ; 19 <- count 1412 1413 LDO -1(19),19 ; decrement count 1414 COMIB,>,N 0,19,i_sync ; if (count < 0), no flush 1415 COMIB,=,N 1,29,i_direct_l 1416 COMIB,=,N 2,29,i_assoc2_l 1417 COMIB,=,N 4,29,i_assoc4_l 1418 1419i_assoc_l ; set-associative flush-loop 1420 COPY 29,20 ; 20 (lcount) <- loop 1421 1422i_set_l ; set flush-loop 1423 LDO -1(20),20 ; decrement lcount 1424 COMIB,<=,N 0,20,i_set_l ; if (lcount >= 0), set loop 1425 FICE 0(5,31) ; flush entry at (address) 1426 1427 LDO -1(19),19 ; decrement count 1428 COMIB,<= 0,19,i_assoc_l ; if (count >= 0), loop 1429 ADD 31,23,31 ; address++ 1430 1431 B i_skips ; next 1432 SYNC ; synchronize after flush 1433 1434i_assoc4_l ; 4-way set-associative loop 1435 FICE 0(5,31) ; flush entry at (*address) 1436 FICE 0(5,31) ; flush entry at (*address) 1437 FICE 0(5,31) ; flush entry at (*address) 1438 FICE,M 23(5,31) ; flush entry at (*address++) 1439 COMIB,< 0,19,i_assoc4_l ; if (count > 0), loop 1440 LDO -1(19),19 ; decrement count 1441 1442 B i_skips ; next 1443 SYNC ; synchronize after flush 1444 1445i_assoc2_l ; 2-way set-associative loop 1446 FICE 0(5,31) ; flush entry at (*address) 1447 FICE,M 23(5,31) ; flush entry at (*address++) 1448 COMIB,< 0,19,i_assoc2_l ; if (count > 0), loop 1449 LDO -1(19),19 ; decrement count 1450 1451 B i_skips ; next 1452 SYNC ; synchronize after flush 1453 1454i_direct_l ; direct-mapped flush loop 1455 FICE,M 23(5,31) ; flush entry at (*address++) 1456 COMIB,< 0,19,i_direct_l ; if (count > 0), loop 1457 LDO -1(19),19 ; decrement count 1458 1459i_sync 1460 SYNC ; synchronize after flush 1461 1462i_skips 1463 NOP ; 7 instructionss as prescribed 1464 NOP ; by the programming note in 1465 NOP ; the description for SYNC. 1466 NOP 1467 NOP 1468 1469L$exit1 1470 BV 0(2) 1471 .EXIT 1472 NOP 1473 .PROCEND ;in=25,26; 1474 1475bkpt_normal_proceed 1476 BL bkpt_normal_cont,1 ; Get PC 1477 DEP 0,31,2,1 1478bkpt_normal_cont 1479 LDW bkpt_normal_ep-bkpt_normal_cont(0,1),1 ; entry point 1480 BV 0(1) ; Invoke 1481 NOP ; Slot for first instruction 1482bkpt_normal_ep 1483 NOP ; Slot for fall through 1484 1485bkpt_plus_proceed 1486 COMB,= 1,1,bkpt_plus_t ; Slot for first instruction 1487 NOP ; Slot for second instruction 1488 STWM 1,-4(0,22) ; Preserve 1 1489 BL bkpt_plus_cont_f,1 ; Get PC 1490 DEP 0,31,2,1 1491bkpt_plus_cont_f 1492 LDW bkpt_plus_ep-bkpt_plus_cont_f(0,1),1 ; entry point 1493 BV 0(1) ; Invoke 1494 LDWM 4(0,22),1 1495bkpt_plus_t 1496 STWM 1,-4(0,22) ; Preserve 1 1497 BL bkpt_plus_cont_t,1 ; Get PC 1498 DEP 0,31,2,1 1499bkpt_plus_cont_t 1500 LDW bkpt_plus_bt-bkpt_plus_cont_t(0,1),1 ; entry point 1501 BV 0(1) ; Invoke 1502 LDWM 4(0,22),1 1503bkpt_plus_ep 1504 NOP ; Slot for fall through 1505bkpt_plus_bt 1506 NOP ; Slot for branch target 1507 1508bkpt_minus_proceed_start 1509bkpt_minus_t 1510 STWM 1,-4(0,22) ; Preserve 1 1511 BL bkpt_minus_cont_t,1 ; Get PC 1512 DEP 0,31,2,1 1513bkpt_minus_cont_t 1514 LDW bkpt_minus_bt-bkpt_minus_cont_t(0,1),1 ; entry point 1515 BV 0(1) ; Invoke 1516 LDWM 4(0,22),1 1517bkpt_minus_proceed 1518 COMB,= 1,1,bkpt_minus_t ; Slot for first instruction 1519 NOP ; Slot for second instruction 1520 STWM 1,-4(0,22) ; Preserve 1 1521 BL bkpt_minus_cont_f,1 ; Get PC 1522 DEP 0,31,2,1 1523bkpt_minus_cont_f 1524 LDW bkpt_minus_ep-bkpt_minus_cont_f(0,1),1 ; entry point 1525 BV 0(1) ; Invoke 1526 LDWM 4(0,22),1 1527bkpt_minus_ep 1528 NOP ; Slot for fall through 1529bkpt_minus_bt 1530 NOP ; Slot for branch target 1531 1532bkpt_closure_proceed 1533 BL bkpt_closure_cont,1 1534 DEP 0,31,2,1 1535bkpt_closure_cont 1536 LDW bkpt_closure_entry-bkpt_closure_cont(0,1),25 1537 LDW bkpt_closure_closure-bkpt_closure_cont(0,1),31 1538 BV 0(25) 1539 COPY 31,25 1540bkpt_closure_closure 1541 NOP ; Closure object pointer 1542bkpt_closure_entry 1543 NOP ; Eventual entry point 1544bkpt_closure_proceed_end 1545 NOP 1546 1547 .SPACE $TEXT$ 1548 .SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44 1549; .SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY 1550 .SUBSPA $UNWIND$,QUAD=0,ALIGN=8,ACCESS=44 1551 .SUBSPA $CODE$ 1552 .SPACE $PRIVATE$ 1553 .SUBSPA $SHORTBSS$ 1554interface_to_scheme .COMM 4 1555interface_to_C .COMM 4 1556scheme_hooks_low .COMM 4 1557scheme_hooks_high .COMM 4 1558 .SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31 1559$THISMODULE$ 1560ifelse(ASM_DEBUG,1,"interface_counter 1561 .ALIGN 8 1562 .WORD 0 1563interface_limit 1564 .WORD 0") 1565undivert(1) 1566 .SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO 1567 .IMPORT $global$,DATA 1568 .IMPORT Registers,DATA 1569 .IMPORT sp_register,DATA 1570 .IMPORT Free,DATA 1571 .IMPORT hppa_utility_table,DATA 1572 .IMPORT hppa_primitive_table,DATA 1573 .IMPORT Primitive_Arity_Table,DATA 1574 .IMPORT Primitive_Procedure_Table,DATA 1575 .SPACE $TEXT$ 1576 .SUBSPA $CODE$ 1577 .IMPORT $$dyncall,MILLICODE 1578 .IMPORT $$remI,MILLICODE 1579 .IMPORT declare_builtin,CODE 1580 .IMPORT sin,CODE 1581 .IMPORT cos,CODE 1582 .IMPORT tan,CODE 1583 .IMPORT asin,CODE 1584 .IMPORT acos,CODE 1585 .IMPORT atan,CODE 1586 .IMPORT exp,CODE 1587 .IMPORT log,CODE 1588 .IMPORT double_truncate,CODE 1589 .IMPORT ceil,CODE 1590 .IMPORT floor,CODE 1591 .IMPORT atan2,CODE 1592 .EXPORT C_to_interface,PRIV_LEV=3,ARGW0=GR,RTNVAL=GR 1593 .EXPORT ep_interface_to_scheme,PRIV_LEV=3 1594 .EXPORT scheme_to_interface_ble,PRIV_LEV=3 1595 .EXPORT trampoline_to_interface,PRIV_LEV=3 1596 .EXPORT scheme_to_interface,PRIV_LEV=3 1597 .EXPORT hook_jump_table,PRIV_LEV=3 1598 .EXPORT cross_segment_call,PRIV_LEV=3 1599 .EXPORT flonum_atan2,PRIV_LEV=3 1600 .EXPORT ep_interface_to_C,PRIV_LEV=3 1601 .EXPORT interface_initialize,PRIV_LEV=3 1602 .EXPORT cache_flush_region,PRIV_LEV=3 1603 .EXPORT cache_flush_all,PRIV_LEV=3 1604 .EXPORT bkpt_normal_proceed,PRIV_LEV=3 1605 .EXPORT bkpt_plus_proceed,PRIV_LEV=3 1606 .EXPORT bkpt_minus_proceed_start,PRIV_LEV=3 1607 .EXPORT bkpt_minus_proceed,PRIV_LEV=3 1608 .EXPORT bkpt_closure_proceed,PRIV_LEV=3 1609 .EXPORT bkpt_closure_proceed_end,PRIV_LEV=3 1610 .END 1611