/* paragon.s -- assembly language code for the i860 architecture * * A i860 context array is laid out like this: * * saved code address 4 * saved r2 - r15 14 * 4 = 56 + 4 = 60 * saved f2 - f6 6 * 4 = 20 + 60 = 84 * magic word for checking integrity 84 + 4 = 88 * arguments for call to code 4 * 4 = 16 + 88 = 104 * unused stack space * * For further information see the i860 Microprocessor Family * Programmer's Reference Manual */ /* mpd_build_context(code,buf,bufsize,a1,a2,a3,a4) -- create a new context. * * args passed in: r16 r17 r18 r19 r20 r21 r22 * * code entry point of the code to be executed in the context * buf buffer for holding the context array * bufsize size of the buffer * a1 - a4 four int-sized arguments to be passed to the code */ .text .globl _mpd_build_context .align 32 _mpd_build_context: st.l r16,0(r17) /* save entry point of code */ addu r18,r17,r18 /* calculate stack pointer */ and -15,r18,r18 /* enforce 16 byte boundary rule */ st.l r18,4(r17) /* save stack pointer */ st.l r18,8(r17) /* save frame pointer */ mov 31,r16 st.l r16,84(r17) /* save magic word */ st.l r19,88(r17) /* save a1 - a4 */ st.l r20,92(r17) st.l r21,96(r17) st.l r22,100(r17) mov r18,r16 bri r1 nop /* mpd_chg_context(newctx,oldctx) -- switch to the specified context * * args passed in: r16 r17 */ .globl _mpd_chg_context .align 32 _mpd_chg_context: bte 0,r17,loadnew /* jump if new context to loadnew */ nop ld.l 84(r17),r18 /* check magic word */ btne 31,r18,bad nop st.l r1,0(r17) /* save register (incl return addr SP etc.) */ st.l r2,4(r17) st.l r3,8(r17) st.l r4,12(r17) st.l r5,16(r17) st.l r6,20(r17) st.l r7,24(r17) st.l r8,28(r17) st.l r9,32(r17) st.l r10,36(r17) st.l r11,40(r17) st.l r12,44(r17) st.l r13,48(r17) st.l r14,52(r17) st.l r15,56(r17) fst.l f2,60(r17) /* save float register */ fst.l f3,64(r17) fst.l f4,68(r17) fst.l f5,72(r17) fst.l f6,76(r17) fst.l f7,80(r17) loadnew: ld.l 0(r16),r21 /* load return address to r21 */ ld.l 4(r16),r2 /* load register */ ld.l 8(r16),r3 ld.l 12(r16),r4 ld.l 16(r16),r5 ld.l 20(r16),r6 ld.l 24(r16),r7 ld.l 28(r16),r8 ld.l 32(r16),r9 ld.l 36(r16),r10 ld.l 40(r16),r11 ld.l 44(r16),r12 ld.l 48(r16),r13 ld.l 52(r16),r14 ld.l 56(r16),r15 fld.l 60(r16),f2 /* load float register */ fld.l 64(r16),f3 fld.l 68(r16),f4 fld.l 72(r16),f5 fld.l 76(r16),f6 fld.l 80(r16),f7 mov r16,r20 /* load parameters */ ld.l 88(r20),r16 ld.l 92(r20),r17 ld.l 96(r20),r18 ld.l 100(r20),r19 nop calli r21 /* return to new context */ nop br under /* should be never reached (underflow error) */ nop /* mpd_check_stk(context) -- check that the stack is not overflowing * * arg passed in r16 */ .globl _mpd_check_stk .align 32 _mpd_check_stk: addu 88,r16,r16 /* checks stack pointer for overflow */ subs r16,r2,r0 bnc over /* if overflow error */ nop bri r1 /* else return */ nop /* stack problem handlers (these calls do not return) */ .align 32 over: br _mpd_stk_overflow nop .align 32 under: br _mpd_stk_underflow nop .align 32 bad: br _mpd_stk_corrupted nop