; Test harness for vfpmath library
; Provides utility functions to assist testing from C

             AREA |C$$code|,CODE,READONLY

; swapend converts an array of dp values between FPE and VFP format
; C prototype: double *swapend(double *array, int n)

             EXPORT swapend
swapend      ldmia r0!,{r2,r3}
             str r2,[r0,#-4]
             str r3,[r0,#-8]
             subs r1,r1,#1
             bne swapend
             mov pc,r14

; fntable computes a table of values of a given funcion
; C prototype: double *(double *array, int n, double (*fn))

             EXPORT fntable
fntable      mov ip,sp
             stmdb sp!,{r4-r6,fp,ip,lr,pc}
             sub fp,ip,#4
             mov r4,r0
             bic r5,r2,#1
             mov r6,r1
10           ldmia r4,{r0,r1}
             blx r5
             DCD 0xECA48102 ; stfd f0,[r4],#8
             subs r6,r6,#1
             bne %BT10
             mov r0,r4
             ldmdb fp,{r4-r6,fp,sp,pc}

; fnotable computes a table of values of a given funcion
; placing the results in the specified output table
; C prototype: double *(double *inarray, double *outarray,
;                                      int n, double (*fn))

             EXPORT fnotable
fnotable     mov ip,sp
             stmdb sp!,{r4-r6,fp,ip,lr,pc}
             sub fp,ip,#4
             mov r4,r1
10           ldmia r0!,{r5,r6}
             stmia r1!,{r5,r6}
             subs r2,r2,#1
             bne %BT10
             mov r0,r4
             sub r6,r1,r4
             mov r6,r6,lsr #3
             mov r5,r3
20           ldmia r4,{r0,r1}
             blx r5
             DCD 0xECA48102 ; stfd f0,[r4],#8
             subs r6,r6,#1
             bne %BT20
             mov r0,r4
             ldmdb fp,{r4-r6,fp,sp,pc}

; Fills the specified array with a range of n dp values
; starting at x and increasing by h with each value
; C prototype double *(double * array, int n, double x,
;                                               double h);

             EXPORT steprange
steprange    vmov.F64 d0,r3,r2
             ldmia sp,{r2,r3}
             vmov.F64 d1,r3,r2
             cmp r1,#2
             movlt r1,#2
10           vmov.F64 r3,r2,d0
             stmia r0!,{r2,r3}
             vadd.F64 d0,d0,d1
             subs r1,r1,#1
             bne %BT10
             mov pc,r14

; Fills the specified array with a range of n dp values
; including and equally spaced between x and y 
; C prototype double *(double * array, int n, double x,
;                                               double y);

             EXPORT linrange
linrange     vmov.F64 d0,r3,r2
             ldmia sp,{r2,r3}
             vmov.F64 d1,r3,r2
             vsub.F64 d1,d1,d0
             cmp r1,#2
             movlt r1,#2
             sub r1,r1,#1
             vmov.S32 s4,r1
             vcvt.F64.S32 d3,s4
             vdiv.F64 d1,d1,d3
             add r1,r1,#1
10           vmov.F64 r3,r2,d0
             stmia r0!,{r2,r3}
             vadd.F64 d0,d0,d1
             subs r1,r1,#1
             bne %BT10
             mov pc,r14

; Computes the difference between an array of n values
; and the corresponding expected value
; C prototype double *(double *array, double *exptd, int n);

             EXPORT fnerror
fnerror      mov ip,sp
             stmdb sp!,{r4,fp,ip,lr,pc}
             sub fp,ip,#4
10           ldmia r0,{r3,r4}
             vmov.F64 d0,r4,r3
             ldmia r1!,{r3,r4}
             vmov.F64 d1,r4,r3
             vsub.F64 d0,d1,d0
             vmov.F64 r4,r3,d0
             stmia r0!,{r3,r4}
             subs r2,r2,#1
             bne %BT10
             ldmdb fp,{r4,fp,sp,pc}

             END
