Mercurial > pub > dyncall > dyncall
comparison dyncallback/dyncall_args_mips_o32.c @ 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 | b7a9b524f0c3 |
children | 9e677d4c0b6b |
comparison
equal
deleted
inserted
replaced
103:b15d814ba274 | 104:dbca6763f2be |
---|---|
27 #include "dyncall_args_mips.h" | 27 #include "dyncall_args_mips.h" |
28 | 28 |
29 DCint dcbArgInt(DCArgs* p) | 29 DCint dcbArgInt(DCArgs* p) |
30 { | 30 { |
31 DCint value; | 31 DCint value; |
32 p->freg_count = 2; // first int will disable float reg use. | |
32 value = *((int*)p->stackptr); | 33 value = *((int*)p->stackptr); |
33 p->stackptr += sizeof(int); | 34 p->stackptr += sizeof(int); |
34 return value; | 35 return value; |
35 } | 36 } |
36 DCuint dcbArgUInt(DCArgs* p) { return (DCuint)dcbArgInt(p); } | 37 DCuint dcbArgUInt(DCArgs* p) { return (DCuint)dcbArgInt(p); } |
60 DCpointer dcbArgPointer(DCArgs* p) { return (DCpointer)dcbArgUInt(p); } | 61 DCpointer dcbArgPointer(DCArgs* p) { return (DCpointer)dcbArgUInt(p); } |
61 | 62 |
62 DCfloat dcbArgFloat(DCArgs* p) | 63 DCfloat dcbArgFloat(DCArgs* p) |
63 { | 64 { |
64 DCfloat result; | 65 DCfloat result; |
65 result = *((float*)p->stackptr); | 66 if(p->freg_count < 2) { |
66 p->stackptr += sizeof(float); | 67 // Stored float regs (max 2) are always 8b aligned. The way we look them up, |
68 // relative to a diverging p->stackptr, we need consider this. Only works | |
69 // with up to two float args, which is all we need. Hacky, but saves us | |
70 // from one more variable and more bookkeeping in DCArgs. | |
71 result = ((DCfloat*)(p->stackptr + ((int)p->stackptr & 4)) - 4) // '-4' b/c those regs are stored right before the args | |
72 #if defined(DC__Endian_LITTLE) | |
73 [0]; | |
74 #else | |
75 [1]; | |
76 #endif | |
77 ++p->freg_count; | |
78 } else { | |
79 result = *((DCfloat*)p->stackptr); | |
80 } | |
81 p->stackptr += sizeof(DCfloat); | |
67 return result; | 82 return result; |
68 } | 83 } |
69 DCdouble dcbArgDouble(DCArgs* p) | 84 DCdouble dcbArgDouble(DCArgs* p) |
70 { | 85 { |
71 union { | 86 union { |
72 DCdouble result; | 87 DCdouble result; |
73 DCfloat f[2]; | 88 DCfloat f[2]; |
74 } d; | 89 } d; |
75 p->stackptr += ((int)p->stackptr & 4); // Skip one slot if not aligned. | 90 p->stackptr += ((int)p->stackptr & 4); // Skip one slot if not aligned. |
76 #if defined(DC__Endian_LITTLE) | 91 if(p->freg_count < 2) { |
77 d.f[0] = dcbArgFloat(p); | 92 //result = *((DCdouble*)p->stackptr-2); this changes the value, slightly |
78 d.f[1] = dcbArgFloat(p); | 93 d.f[0] = ((DCfloat*)p->stackptr-4)[0]; // '-4' b/c those regs are stored right before the args |
79 #else | 94 d.f[1] = ((DCfloat*)p->stackptr-4)[1]; |
80 d.f[1] = dcbArgFloat(p); | 95 ++p->freg_count; |
81 d.f[0] = dcbArgFloat(p); | 96 } else { |
82 #endif | 97 //result = *((DCdouble*)p->stackptr); this changes the value, slightly |
98 d.f[0] = ((DCfloat*)p->stackptr)[0]; | |
99 d.f[1] = ((DCfloat*)p->stackptr)[1]; | |
100 } | |
101 p->stackptr += sizeof(DCdouble); | |
83 return d.result; | 102 return d.result; |
84 } | 103 } |
85 | 104 |