| @@ -33,8 +33,12 @@ const register_init, align=3 | |||||
| .quad 0x249214109d5d1c88 | .quad 0x249214109d5d1c88 | ||||
| endconst | endconst | ||||
| const error_message | |||||
| .asciz "failed to preserve register" | |||||
| const error_message_fpscr | |||||
| .asciz "failed to preserve register FPSCR" | |||||
| const error_message_gpr | |||||
| .asciz "failed to preserve register r%d" | |||||
| const error_message_vfp | |||||
| .asciz "failed to preserve register d%d" | |||||
| endconst | endconst | ||||
| @ max number of args used by any asm function. | @ max number of args used by any asm function. | ||||
| @@ -79,39 +83,42 @@ function checkasm_checked_call_\variant, export=1 | |||||
| push {r0, r1} | push {r0, r1} | ||||
| movrel r12, register_init | movrel r12, register_init | ||||
| mov r3, #0 | |||||
| .ifc \variant, vfp | .ifc \variant, vfp | ||||
| .macro check_reg_vfp, dreg, inc=8 | |||||
| ldrd r0, r1, [r12], #\inc | |||||
| vmov r2, lr, \dreg | |||||
| eor r0, r0, r2 | |||||
| eor r1, r1, lr | |||||
| orr r3, r3, r0 | |||||
| orr r3, r3, r1 | |||||
| .macro check_reg_vfp, dreg, offset | |||||
| vldr d0, [r12, #8 * (\offset)] | |||||
| veor d0, d0, \dreg | |||||
| vmov r2, r3, d0 | |||||
| orrs r2, r2, r3 | |||||
| bne 4f | |||||
| .endm | .endm | ||||
| .irp n, 8, 9, 10, 11, 12, 13, 14 | |||||
| check_reg_vfp d\n | |||||
| .irp n, 8, 9, 10, 11, 12, 13, 14, 15 | |||||
| @ keep track of the checked double/SIMD register | |||||
| mov r1, #\n | |||||
| check_reg_vfp d\n, \n-8 | |||||
| .endr | .endr | ||||
| check_reg_vfp d15, -56 | |||||
| .purgem check_reg_vfp | .purgem check_reg_vfp | ||||
| fmrx r0, FPSCR | fmrx r0, FPSCR | ||||
| ldr r1, [sp, #8] | |||||
| eor r0, r0, r1 | |||||
| ldr r3, [sp, #8] | |||||
| eor r0, r0, r3 | |||||
| @ Ignore changes in the topmost 5 bits | @ Ignore changes in the topmost 5 bits | ||||
| lsl r0, r0, #5 | |||||
| orr r3, r3, r0 | |||||
| lsls r0, r0, #5 | |||||
| bne 3f | |||||
| .endif | .endif | ||||
| @ keep track of the checked GPR | |||||
| mov r1, #4 | |||||
| .macro check_reg reg1, reg2= | .macro check_reg reg1, reg2= | ||||
| ldrd r0, r1, [r12], #8 | |||||
| eor r0, r0, \reg1 | |||||
| orrs r3, r3, r0 | |||||
| ldrd r2, r3, [r12], #8 | |||||
| eors r2, r2, \reg1 | |||||
| bne 2f | |||||
| add r1, r1, #1 | |||||
| .ifnb \reg2 | .ifnb \reg2 | ||||
| eor r1, r1, \reg2 | |||||
| orrs r3, r3, r1 | |||||
| eors r3, r3, \reg2 | |||||
| bne 2f | |||||
| .endif | .endif | ||||
| add r1, r1, #1 | |||||
| .endm | .endm | ||||
| check_reg r4, r5 | check_reg r4, r5 | ||||
| check_reg r6, r7 | check_reg r6, r7 | ||||
| @@ -124,9 +131,16 @@ function checkasm_checked_call_\variant, export=1 | |||||
| check_reg r10, r11 | check_reg r10, r11 | ||||
| .purgem check_reg | .purgem check_reg | ||||
| beq 0f | |||||
| movrel r0, error_message | |||||
| b 0f | |||||
| 4: | |||||
| movrel r0, error_message_vfp | |||||
| b 1f | |||||
| 3: | |||||
| movrel r0, error_message_fpscr | |||||
| b 1f | |||||
| 2: | |||||
| movrel r0, error_message_gpr | |||||
| 1: | |||||
| blx X(checkasm_fail_func) | blx X(checkasm_fail_func) | ||||
| 0: | 0: | ||||
| pop {r0, r1} | pop {r0, r1} | ||||