! rtmisc.s ! unsigned char _ThreadF__inSystemCritical ! void to_host( int code, int data ); .text .globl _RTMisc__Success _RTMisc__Success: mov #0,imr ! turn off interrupts jsr WaitForSend,r7 ! wait for completion of any current send mov #0,r0 mov r0,@--sp ! push 'param' mov r0,@--sp ! push 'last_pc' mov #1,@--sp ! push 'code' of success mov _System__procID,@--sp ! push 'pid' mov sp,msp add #3,sp mov sp,msl mov #inf_loop,r7 jmp StartSend .globl _RTMisc__FatalError _RTMisc__FatalError: mov 1[sp],r0 add #200,r0 mov r0,@--sp jmp Fault .globl _RTMisc__AssertFault _RTMisc__AssertFault: mov #100,r0 jmp RegFault .globl _RTMisc__ReturnFault _RTMisc__ReturnFault: mov #101,r0 jmp RegFault .globl _RTMisc__CaseFault _RTMisc__CaseFault: mov #102,r0 jmp RegFault .globl _RTMisc__TypecaseFault _RTMisc__TypecaseFault: mov #103,r0 jmp RegFault .globl _RTMisc__RangeFault _RTMisc__RangeFault: mov #104,r0 jmp RegFault .globl _RTMisc__NarrowFault _RTMisc__NarrowFault: mov #105,r0 jmp RegFault .globl _RTMisc__NilFault _RTMisc__NilFault: mov #106,r0 jmp RegFault .globl _RTMisc__RemoteDerefFault _RTMisc__RemoteDerefFault: mov #107,r0 jmp RegFault .globl _RTMisc__StackOverflow _RTMisc__StackOverflow: mov #108,r0 jmp RegFault .globl _RTMisc__RaisesFault _RTMisc__RaisesFault: ! params: ret.val. exceptionName mov #150,@--sp jmp Fault .globl _RTMisc__HandlerFault _RTMisc__HandlerFault: ! params: ret.val. exceptionName mov #151,@--sp jmp Fault RegFault: ! on entry: r7 = last_pc, r0 = code ! params on stack: int param (if any, ! or undefined otherwise) mov r7,@--sp mov r0,@--sp ! fall through to Fault Fault: ! params: int code, int last_pc, int param mov #0,imr ! turn off interrupts mov #0x8000,r4 ! r4 := ADR( buf[ FIRST(buf) ] ) mov r4,r5 ! r5 := ADR( buf[ FIRST(buf) ] ) mov r4,r6 ! r6 := ADR( add #100,r6 ! buf[ LAST(buf) ] ) mov _System__procID,@r4++ ! buf[0] := pid mov @sp++,@r4++ ! buf[1] := code mov @sp++,@r4++ ! buf[2] := last_pc mov @sp,@r4++ ! buf[3] := param ! Fill rest of buffer with rest of stack trace. ! Stack trace is terminated with a 0, unless it can't fit ! into the buffer, in which case it is terminated with a 1 trace_loop: cmp #0,bp jeq end_trace cmp r4,r6 jeq buf_full mov 1[bp],@r4++ ! buf[r4] := ret.addr. of current frame mov @bp,bp ! bp := bp of next frame jmp trace_loop end_trace: mov #0,@r4 jmp send_rterr buf_full: mov #1,@r4 send_rterr: jsr WaitForSend,r7 mov r5,msp mov r4,msl jsr StartSend,r7 ! fall through to infinite loop inf_loop: mov isr,r0 and #5,r0 jeq inf_loop mov #0x1000,mrp mov #0x1fff,mrl mov r0,isr jmp inf_loop ! StartSend ! This procedure moves the relative processor offset of the root processor ! into the dxdy register. ! The return address of this procedure should be stored in r7 on entry. ! One way to achieve this is to call the procedure with "jsr StartSend,r7". ! This procedure uses and destroys r0, r5, and r6. StartSend: mov _System__procHostConnection,r0 jsr PidToDxdy,r5 mov r0,dxdy jmp @r7 ! PidToDxdy is called by ! mov pid,r0 ! jsr PidToDxdy,r5 ! It uses and destroys registers r0 and r6. ! The return value is placed in r0. ! ! VAR diff: INTEGER; ! dxdy: Word.T; ! BEGIN ! (* BUG. Assumes one dimension. *) ! diff := pid - System.procID; ! dxdy := ABS( diff ) * 16_100; ! IF diff < 0 THEN dxdy := Word.Or( dxdy, 16_8000 ) END; ! RETURN dxdy ! END PidToDxdy: mov _System__procID,r6 ; r6 := System.procID sub r6,r0 ; r0 := pid (* r0 *) - System.procID (* r6 *) jneg $1f mov r0,r6 ; r6 := r0 (* r0 >= 0 *) jmp $2f $: com r0,r6 ; r6 := Word.OR( ABS( r0 ), (* r0 < 0 *) or #0x80,r6 ; 16_80 ) $: rnr r6,r6 ; r0 := Word.Shift( r6, rnr r6,r0 ; 8 ) jmp @r5 ! PROCEDURE Processor.PidToDxdy( pid: INTEGER ): Word.T; ! This procedure assumes all processors are on the x-axis. ! Subroutine PidToDxdy performs the work in _PidToDxdy. The difference ! is that PidToDxdy works without using the stack--instead, it uses ! only registers. (See above.) .globl _Processor__PidToDxdy _Processor__PidToDxdy: mov 1[sp],r0 ; r0 := pid (* needed for call to PidToDxdy *) mov r5,@--sp ; save registers mov r6,@--sp jsr PidToDxdy,r5 mov @sp++,r6 ; restore registers mov @sp++,r5 jmp @@sp++ ! WaitForSend ! This procedure waits until any current send has completed, and ! then returns. ! This procedure is called using "jsr WaitForSend,r7". ! This procedure uses and destroys r0. ! REQUIRES interrupts are turned off WaitForSend: mov _IPC__sendInProgress,r0 ! IF NOT IPC.sendInProgress cmp #0,r0 jne WFS_loop ! THEN mov isr,r0 and #2,r0 ! IF Word.And( isr, ISR_Send ) = 0 jeq WFS_exit ! THEN jmp WFS_acknowledge_send ! ELSE ! ELSE WFS_loop: ! LOOP mov isr,r0 and #5,r0 jeq $1f ! IF Word.And(isr,ISR_BufRec) # 0 mov #0x1000,mrp ! THEN mov #0x1fff,mrl ! set up new receive buffer and mov r0,isr ! acknowledge receive $: ! END mov isr,r0 ! IF Word.And(isr,ISR_Send)#0 and #2,r0 ! THEN EXIT END jeq WFS_loop ! END WFS_acknowledge_send: ! END mov #2,isr WFS_exit: jmp @r7 ! end of rtmisc.s