Mercurial > pub > dyncall > dyncall
comparison dyncallback/dyncall_callback_mips_o32_gas.s @ 104:dbca6763f2be
- complete, working mips o32 callback (using hardware fp); fixes error from last commit, which ignored first 2 float args
* currently tested on little endian, only
* todo update, manual update, cleanups
author | cslag |
---|---|
date | Thu, 09 Jun 2016 15:13:53 +0200 |
parents | b15d814ba274 |
children | d595eb90efdd |
comparison
equal
deleted
inserted
replaced
103:b15d814ba274 | 104:dbca6763f2be |
---|---|
35 .align 2 | 35 .align 2 |
36 .globl dcCallbackThunkEntry | 36 .globl dcCallbackThunkEntry |
37 .ent dcCallbackThunkEntry | 37 .ent dcCallbackThunkEntry |
38 .type dcCallbackThunkEntry, @function | 38 .type dcCallbackThunkEntry, @function |
39 | 39 |
40 /* Called by thunk - thunk stores pointer to DCCallback in $12 ($t4), and pointer to called function in $25 ($t9, required for PIC) */ | 40 /* Called by thunk - thunk stores pointer to DCCallback in $12 ($t4), and */ |
41 /* pointer to called function in $25 ($t9, required for PIC) */ | |
41 dcCallbackThunkEntry: | 42 dcCallbackThunkEntry: |
42 .set noreorder | 43 .set noreorder |
43 .set nomacro | 44 .set nomacro |
44 | 45 |
45 /* Prolog. Just store the minimum, return address, frame pointer, spill area. */ | 46 /* Prolog. Just store the minimum, return address, spill area. */ |
46 subu $sp, 32 /* open frame: 32b for 8b aligned frame (retval+ra+fp+spill) */ | 47 /* Frame size of 48b comes from following areas (each 8b aligned); */ |
48 /* local: fpregs:16 + retval:8 + DCArgs:8 */ | |
49 /* save: ra:4 (+ pad:4) */ | |
50 /* param: spill:16 */ | |
51 subu $sp, 56 /* open frame */ | |
47 sw $ra, 20($sp) /* save link register */ | 52 sw $ra, 20($sp) /* save link register */ |
48 | 53 |
49 .frame $fp,32,$31 /* specify our frame: fp,size,lr; creates virt $fp */ | 54 .frame $fp,56,$31 /* specify our frame: fp,size,lr; creates virt $fp */ |
50 | 55 |
51 /* Init return value */ | 56 /* Init return value */ |
57 sw $zero, 32($sp) | |
58 sw $zero, 36($sp) | |
59 | |
60 /* Store the arguments passed via registers somewhere for dcArg* to access. */ | |
61 /* For $4-$7 ($a0-$a3), use dedicated spill area (caller doesn't spill, but */ | |
62 /* provides it at end of _caller's_ frame, so $fp points right to it). */ | |
63 /* For $f12 and $f14 use our space (in local data), which is adjacent. */ | |
64 s.d $f12, 40($sp) /* -16($fp) */ | |
65 s.d $f14, 48($sp) /* -8($fp) */ | |
66 sw $4, 0($fp) | |
67 sw $5, 4($fp) | |
68 sw $6, 8($fp) | |
69 sw $7, 12($fp) | |
70 | |
71 /* Init DCArg, which contains reg_count and stackptr* to the args. Point */ | |
72 /* stackptr to the area where the non-float args start (which is at $fp). */ | |
52 sw $zero, 24($sp) | 73 sw $zero, 24($sp) |
53 sw $zero, 28($sp) | 74 sw $fp, 28($sp) |
54 | |
55 /* If we spill the first four, all arguments will be in one out in consecutive block */ | |
56 /* Caller doesn't and it's up to us to spill, so let's write $4-$7 ($a0-$a3) to the */ | |
57 /* dedicated spill area, first (at end of _caller's_ frame, so $fp points right to it). */ | |
58 sw $7, 12($fp) | |
59 sw $6, 8($fp) | |
60 sw $5, 4($fp) | |
61 sw $4, 0($fp) | |
62 | |
63 /* Init DCArg, which contains stackptr* to the args, which is $fp. Use padding between */ | |
64 /* stored return address and parameter area as place to store it (hacky, but saves 8b) */ | |
65 sw $fp, 16($sp) | |
66 | 75 |
67 /* Prepare callback handler call. */ | 76 /* Prepare callback handler call. */ |
68 move $4, $12 /* Param 0 = DCCallback*, $12 ($t4) holds pointer to thunk */ | 77 move $4, $12 /* Param 0 = DCCallback*, $12 ($t4) holds pointer to thunk */ |
69 addiu $5, $sp, 16 /* Param 1 = DCArgs*, pointer to where pointer to args is stored */ | 78 addiu $5, $sp, 24 /* Param 1 = DCArgs*, pointer to where pointer to args is stored */ |
70 addiu $6, $sp, 24 /* Param 2 = results pointer to 8b of local data on stack */ | 79 addiu $6, $sp, 32 /* Param 2 = results pointer to 8b of local data on stack */ |
71 lw $7, 24($12) /* Param 3 = userdata pointer */ | 80 lw $7, 24($12) /* Param 3 = userdata pointer */ |
72 | 81 |
73 lw $25, 20($12) /* store handler entry in $25 ($t9), required for PIC */ | 82 lw $25, 20($12) /* store handler entry in $25 ($t9), required for PIC */ |
74 jalr $25 /* jump */ | 83 jalr $25 /* jump */ |
75 nop | 84 nop /* branch delay nop */ |
76 | 85 |
77 /* Copy result in corresponding registers $2-$3 ($v0-$v1) */ | 86 /* Copy result in corresponding registers $2-$3 ($v0-$v1) and $f0 */ |
78 lw $2, 24($sp) | 87 lw $2, 32($sp) |
79 lw $3, 28($sp) | 88 lw $3, 36($sp) |
89 l.d $f0, 32($sp) | |
80 | 90 |
81 /* Epilog. Tear down frame and return. */ | 91 /* Epilog. Tear down frame and return. */ |
82 lw $ra, 20($sp) /* restore return address */ | 92 lw $ra, 20($sp) /* restore return address */ |
83 addiu $sp, $sp, 32 /* close frame */ | 93 addiu $sp, $sp, 56 /* close frame */ |
84 j $ra /* return */ | 94 j $ra /* return */ |
85 nop | 95 nop /* branch delay nop */ |
86 | 96 |
87 .set macro | 97 .set macro |
88 .set reorder | 98 .set reorder |
89 .end dcCallbackThunkEntry | 99 .end dcCallbackThunkEntry |
90 .ident "handwritten" | 100 .ident "handwritten" |