# # QuickThreads -- Threads-building toolkit. # Copyright (c) 1993 by David Keppel # # Permission to use, copy, modify and distribute this software and # its documentation for any purpose and without fee is hereby # granted, provided that the above copyright notice and this notice # appear in all copies. This software is provided as a # proof-of-concept and for demonstration purposes# there is no # representation about the suitability of this software for any # purpose. # # axp.s -- assembly support. .text .align 4 .file 2 "axp.s" .globl qt_block .globl qt_blocki .globl qt_abort .globl qt_start .globl qt_vstart # # $16: ptr to function to call once curr is suspended # and control is on r19's stack. # $17: 1'th arg to (*$16)(...). # $18: 2'th arg to (*$16)(...). # $19: sp of thread to resume. # # The helper routine returns a value that is passed on as the # return value from the blocking routine. Since we don't # touch r0 between the helper's return and the end of # function, we get this behavior for free. # .ent qt_blocki qt_blocki: subq $30,80, $30 # Allocate save area. stq $26, 0($30) # Save registers. stq $9, 8($30) stq $10,16($30) stq $11,24($30) stq $12,32($30) stq $13,40($30) stq $14,48($30) stq $15,56($30) stq $29,64($30) .end qt_blocki .ent qt_abort qt_abort: addq $16,$31, $27 # Put argument function in PV. addq $30,$31, $16 # Save stack ptr in outgoing arg. addq $19,$31, $30 # Set new stack pointer. jsr $26,($27),0 # Call helper function. ldq $26, 0($30) # Restore registers. ldq $9, 8($30) ldq $10,16($30) ldq $11,24($30) ldq $12,32($30) ldq $13,40($30) ldq $14,48($30) ldq $15,56($30) ldq $29,64($30) addq $30,80, $30 # Deallocate save area. ret $31,($26),1 # Return, predict===RET. .end qt_abort # # Non-varargs thread startup. # .ent qt_start qt_start: addq $9,$31, $16 # Load up `qu'. addq $10,$31, $17 # ... user function's `pt'. addq $11,$31, $18 # ... user function's `userf'. addq $12,$31, $27 # ... set procedure value to `only'. jsr $26,($27),0 # Call `only'. jsr $26,qt_error # `only' erroniously returned. .end qt_start .ent qt_vstart qt_vstart: # Call startup function. addq $9,$31, $16 # Arg0 to `startup'. addq $12,$31, $27 # Set procedure value. jsr $26,($27),0 # Call `startup'. # Call user function. ldt $f16, 0($30) # Load fp arg regs. ldt $f17, 8($30) ldt $f18,16($30) ldt $f19,24($30) ldt $f20,32($30) ldt $f21,40($30) ldq $16,48($30) # And integer arg regs. ldq $17,56($30) ldq $18,64($30) ldq $19,72($30) ldq $20,80($30) ldq $21,88($30) addq $30,96, $30 # Pop 6*2*8 saved arg regs. addq $11,$31, $27 # Set procedure value. jsr $26,($27),0 # Call `vuserf'. # Call cleanup. addq $9,$31, $16 # Arg0 to `cleanup'. addq $0,$31, $17 # Users's return value is arg1. addq $10,$31, $27 # Set procedure value. jsr $26,($27),0 # Call `cleanup'. jsr $26,qt_error # Cleanup erroniously returned. .end qt_start # # Save calle-save floating-point regs $f2..$f9. # Also save return pc from whomever called us. # # Return value from `qt_block' is the same as the return from # `qt_blocki'. We get that for free since we don't touch $0 # between the return from `qt_blocki' and the return from # `qt_block'. # .ent qt_block qt_block: subq $30,80, $30 # Allocate a save space. stq $26, 0($30) # Save registers. stt $f2, 8($30) stt $f3,16($30) stt $f4,24($30) stt $f5,32($30) stt $f6,40($30) stt $f7,48($30) stt $f8,56($30) stt $f9,64($30) jsr $26,qt_blocki # Call helper. # .. who will also restore $gp. ldq $26, 0($30) # restore registers. ldt $f2, 8($30) ldt $f3,16($30) ldt $f4,24($30) ldt $f5,32($30) ldt $f6,40($30) ldt $f7,48($30) ldt $f8,56($30) ldt $f9,64($30) addq $30,80, $30 # Deallcate save space. ret $31,($26),1 # Return, predict===RET. .end qt_block