;****************************************************************************
;* This source file was written by Acorn Computers Limited. It is part of   *
;* the "cwimp" library for writing applications in C for RISC OS. It may be *
;* used freely in the creation of programs for Archimedes. It should be     *
;* used with Acorn's objasm assembler.                                      *
;*                                                                          *
;* No support can be given to programmers using this code and, while we     *
;* believe that it is correct, no correspondence can be entered into        *
;* concerning behaviour or bugs.                                            *
;*                                                                          *
;* Upgrades of this code may or may not appear, and while every effort will *
;* be made to keep such upgrades upwards compatible, no guarantees can be   *
;* given.                                                                   *
;****************************************************************************

;
; Title  : s.poll
; Purpose: interface to wimp poll for C programs
; Version: 0.1
;

a1 RN 0
a2 RN 1
a3 RN 2
a4 RN 3
v1 RN 4
v2 RN 5
v3 RN 6
v4 RN 7
v5 RN 8
v6 RN 9
fp RN 10
ip RN 11
sp RN 12
sl RN 13
lk RN 14
lr RN 14
pc RN 15

f0 FN 0
f1 FN 1
f2 FN 2
f3 FN 3
f4 FN 4
f5 FN 5
f6 FN 6
f7 FN 7

Poll     * &400C7
PollIdle * &400c0+33

        AREA |C$$code|, CODE, READONLY

|x$codeseg|

        IMPORT  |_kernel_fpavailable|
        EXPORT  wimp_poll

; os_error * wimp_poll(wimp_emask mask, wimp_eventstr * result) ;
; a1 is poll mask, a2 is pointer to event structure

wimp_poll
        MOV     ip, sp
        STMFD   sp!, {v1,v2,fp,ip,lk,pc}
        SUB     fp, ip, #4
        MOV     v2, a1
        MOV     v1, a2

        LDR     a1, =poll_preserve_fp
        LDR     a1, [a1]
        CMP     a1, #0
        BLNE    |_kernel_fpavailable|
        CMPNE   a1, #0
        BLNE    save_fp_state
        MOV     lk, a1

        MOV     a1, v2                    ; restore mask
        ADD     a2, v1, #4                ; point at eventstr->data
        SWI     Poll

        CMP     lk, #0
        BLNE    restore_fp_state

        SUB     a2, a2, #4                ; point back at eventstr
        STR     a1, [a2, #0]              ; set reason code
        MOVVC   a1, #0                    ; no error
        LDMEA   fp, {v1,v2,fp,sp,pc}^


; os_error *wimp_pollidle(wimp_emask mask, wimp_eventstr *result, int earliest)
; a1 mask, a2 eventstr, a3 earliest

        EXPORT  wimp_pollidle
wimp_pollidle
        MOV     ip, sp
        STMFD   sp!, {v1,v2,v3,fp,ip,lk,pc}
        SUB     fp, ip, #4
        MOV     v2, a1
        MOV     v1, a2
        MOV     v3, a3

        LDR     a1, =poll_preserve_fp
        LDR     a1, [a1]
        CMP     a1, #0
        BLNE    |_kernel_fpavailable|
        CMPNE   a1, #0
        BLNE    save_fp_state
        MOV     lk, a1

        MOV     a1, v2                    ; restore mask
        ADD     a2, v1, #4                ; point at eventstr->data
        MOV     a3, v3                    ; restore time
        SWI     Poll

        CMP     lk, #0
        BLNE    restore_fp_state

        SUB     a2, a2, #4                ; point back at eventstr
        STR     a1, [a2, #0]              ; set reason code
        MOVVC   a1, #0                    ; no error
        LDMEA   fp, {v1,v2,v3,fp,sp,pc}^

; Only f4..f7 defined preserved over procedure call
; can corrupt a2-a4
save_fp_state
        RFS     a2                      ; read FP status
        STMFD   sp!, {a2}
        MOV     a2, #0
        WFS     a2
        SUB     sp, sp, #4*12           ; emulated a lot faster than writeback
        STFE    f4, [sp, #0*12]
        STFE    f5, [sp, #1*12]
        STFE    f6, [sp, #2*12]
        STFE    f7, [sp, #3*12]
        MOVS    pc, lr

; v1, v2 trashable
restore_fp_state
        MOV     v1, #0
        WFS     v1
        LDFE    f4, [sp, #0*12]
        LDFE    f5, [sp, #1*12]
        LDFE    f6, [sp, #2*12]
        LDFE    f7, [sp, #3*12]
        ADD     sp, sp, #4*12           ; emulated a lot faster than writeback
        LDMFD   sp!, {v1}
        WFS     v1
        MOVS    pc, lr


        EXPORT  wimp_save_fp_state_on_poll
wimp_save_fp_state_on_poll
        LDR   a1, =poll_preserve_fp
        MOV   a2, #1
        STR   a2, [a1]
        MOVS  pc, lr

        EXPORT  wimp_corrupt_fp_state_on_poll
wimp_corrupt_fp_state_on_poll
        LDR   a1, =poll_preserve_fp
        MOV   a2, #0
        STR   a2, [a1]
        MOVS  pc, lr

        LTORG

    AREA |C$$data|
|x$dataseg|

poll_preserve_fp  DCD  1

    END
