as_callfunc_xenon.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2011 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. //
  24. // as_callfunc_xenon.cpp
  25. //
  26. // These functions handle the actual calling of system functions
  27. //
  28. // This version is Xenon specific
  29. // Modified from as_callfunc_ppc.cpp by Laszlo Perneky Februar 2007
  30. //
  31. // Modified by Cyril Tissier March 2010:
  32. // various fixes in 'float' args passing / function return
  33. // properly handling 'double' type
  34. // various fixes in asm ppcFunc
  35. // fix for variable arguments
  36. //
  37. #include "as_config.h"
  38. #ifndef AS_MAX_PORTABILITY
  39. #if defined(AS_XENON)
  40. #include "as_callfunc.h"
  41. #include "as_scriptengine.h"
  42. #include "as_texts.h"
  43. #include "as_tokendef.h"
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <xtl.h>
  47. BEGIN_AS_NAMESPACE
  48. #define AS_PPC_MAX_ARGS 32
  49. #define AS_MAX_REG_FLOATS 13
  50. #define AS_MAX_REG_INTS 8
  51. #define AS_PPC_THISCALL_REG 1
  52. #define AS_PPC_RETURNINMEM_REG 1
  53. #define AS_PPC_ENDOFARGS 1
  54. // The array used to send values to the correct places.
  55. // Contains a byte of argTypes to indicate the register type to load, or zero if end of arguments
  56. extern "C" {
  57. enum argTypes
  58. {
  59. ppcENDARG = 0,
  60. ppcINTARG,
  61. ppcFLOATARG,
  62. ppcDOUBLEARG
  63. };
  64. static asBYTE ppcArgsType[AS_PPC_MAX_ARGS + AS_PPC_RETURNINMEM_REG + AS_PPC_THISCALL_REG + AS_PPC_ENDOFARGS];
  65. static asDWORD ppcArgs[AS_PPC_MAX_ARGS + AS_PPC_RETURNINMEM_REG + AS_PPC_THISCALL_REG];
  66. }
  67. #define PPC_LINKAGE_SIZE (0x14) // how big the PPC linkage area is in a stack frame
  68. // Loads all data into the correct places and calls the function.
  69. // ppcArgsType is an array containing a byte type (enum argTypes) for each argument.
  70. // iStackArgSize is the size in bytes for how much data to put on the stack frame
  71. //--------------------------------------------------------------------
  72. asQWORD __declspec( naked ) ppcFunc(const asDWORD* pArgs, int iStackArgSize, asDWORD dwFunc)
  73. {
  74. __asm
  75. {
  76. //////////////////////////////////////////////////////////////////////////
  77. // Prepare args
  78. //////////////////////////////////////////////////////////////////////////
  79. _ppcFunc:
  80. // setup stack
  81. // Read link register
  82. mflr r12
  83. // Stack the link register
  84. stw r12,-8(r1)
  85. // backup all registers we use in this fct
  86. std r31,-10h(r1)
  87. std r30,-18h(r1)
  88. std r29,-20h(r1)
  89. std r28,-28h(r1)
  90. std r27,-30h(r1)
  91. std r26,-38h(r1)
  92. std r25,-40h(r1)
  93. std r24,-48h(r1)
  94. std r23,-50h(r1)
  95. std r22,-58h(r1)
  96. std r21,-60h(r1)
  97. // Move stack pointer
  98. stwu r1,-0A0h(r1)
  99. mr r29, r3 //pArgs
  100. mr r30, r4 //iStackArgSize
  101. mr r27, r5 //dwFunc
  102. addi r31, r1, 14h // stack args for next function call
  103. // Clear some registers
  104. sub r0, r0, r0
  105. // Counting of used/assigned GPR's
  106. mr r23, r0
  107. // Counting of used/assigned Float Registers
  108. mr r22, r0
  109. // Counting extra stack size
  110. mr r21, r0
  111. // Fetch argument types array address
  112. lau r25, ppcArgsType
  113. lal r25, r25, ppcArgsType
  114. // Fetch arguments array address
  115. lau r26, ppcArgs
  116. lal r26, r26, ppcArgs
  117. // Begin loading and stacking registers
  118. subi r25, r25, 1
  119. //////////////////////////////////////////////////////////////////////////
  120. // Fetch the next argument
  121. //////////////////////////////////////////////////////////////////////////
  122. ppcNextArg:
  123. // Increment rArgTypePtr
  124. addi r25, r25, 1
  125. // Get data type
  126. lbz r24, 0(r25)
  127. // r24 holds the data type
  128. cmplwi cr6, r24, 0
  129. beq cr6, ppcArgsEnd
  130. cmplwi cr6, r24, 1
  131. beq cr6, ppcArgIsInteger
  132. cmplwi cr6, r24, 2
  133. beq cr6, ppcArgIsFloat
  134. cmplwi cr6, r24, 3
  135. beq cr6, ppcArgIsDouble
  136. //////////////////////////////////////////////////////////////////////////
  137. // Load and stack integer arguments
  138. //////////////////////////////////////////////////////////////////////////
  139. ppcArgIsInteger:
  140. // Get the arg from the stack
  141. lwz r12, 0(r26)
  142. // r23 holds the integer arg count so far
  143. cmplwi cr6, r23, 0
  144. beq cr6, ppcLoadIntReg0
  145. cmplwi cr6, r23, 1
  146. beq cr6, ppcLoadIntReg1
  147. cmplwi cr6, r23, 2
  148. beq cr6, ppcLoadIntReg2
  149. cmplwi cr6, r23, 3
  150. beq cr6, ppcLoadIntReg3
  151. cmplwi cr6, r23, 4
  152. beq cr6, ppcLoadIntReg4
  153. cmplwi cr6, r23, 5
  154. beq cr6, ppcLoadIntReg5
  155. cmplwi cr6, r23, 6
  156. beq cr6, ppcLoadIntReg6
  157. cmplwi cr6, r23, 7
  158. beq cr6, ppcLoadIntReg7
  159. // no more than 8 parameters
  160. b ppcLoadIntRegUpd
  161. ppcLoadIntReg0:
  162. mr r3, r12
  163. b ppcLoadIntRegUpd
  164. ppcLoadIntReg1:
  165. mr r4, r12
  166. b ppcLoadIntRegUpd
  167. ppcLoadIntReg2:
  168. mr r5, r12
  169. b ppcLoadIntRegUpd
  170. ppcLoadIntReg3:
  171. mr r6, r12
  172. b ppcLoadIntRegUpd
  173. ppcLoadIntReg4:
  174. mr r7, r12
  175. b ppcLoadIntRegUpd
  176. ppcLoadIntReg5:
  177. mr r8, r12
  178. b ppcLoadIntRegUpd
  179. ppcLoadIntReg6:
  180. mr r9, r12
  181. b ppcLoadIntRegUpd
  182. ppcLoadIntReg7:
  183. mr r10, r12
  184. b ppcLoadIntRegUpd
  185. ppcLoadIntRegUpd:
  186. stw r12, 0(r31) // push on the statck
  187. addi r31, r31, 8 // inc stack by 1 reg
  188. addi r23, r23, 1 // Increment used int register count
  189. addi r29, r29, 4 // Increment rArgsPtr
  190. addi r26, r26, 4 // Increment rStackPtr
  191. b ppcNextArg // Call next arg
  192. //////////////////////////////////////////////////////////////////////////
  193. // Load and stack float arguments
  194. //////////////////////////////////////////////////////////////////////////
  195. ppcArgIsFloat:
  196. // Get the arg from the stack
  197. lfs fr0, 0(r26)
  198. // r22 holds the float arg count so far
  199. cmplwi cr6, r22, 0
  200. beq cr6, ppcLoadFloatReg0
  201. cmplwi cr6, r22, 1
  202. beq cr6, ppcLoadFloatReg1
  203. cmplwi cr6, r22, 2
  204. beq cr6, ppcLoadFloatReg2
  205. cmplwi cr6, r22, 3
  206. beq cr6, ppcLoadFloatReg3
  207. cmplwi cr6, r22, 4
  208. beq cr6, ppcLoadFloatReg4
  209. cmplwi cr6, r22, 5
  210. beq cr6, ppcLoadFloatReg5
  211. cmplwi cr6, r22, 6
  212. beq cr6, ppcLoadFloatReg6
  213. cmplwi cr6, r22, 7
  214. beq cr6, ppcLoadFloatReg7
  215. cmplwi cr6, r22, 8
  216. beq cr6, ppcLoadFloatReg8
  217. cmplwi cr6, r22, 9
  218. beq cr6, ppcLoadFloatReg9
  219. cmplwi cr6, r22, 10
  220. beq cr6, ppcLoadFloatReg10
  221. cmplwi cr6, r22, 11
  222. beq cr6, ppcLoadFloatReg11
  223. cmplwi cr6, r22, 12
  224. beq cr6, ppcLoadFloatReg12
  225. // no more than 12 parameters
  226. b ppcLoadFloatRegUpd
  227. ppcLoadFloatReg0:
  228. fmr fr1, fr0
  229. b ppcLoadFloatRegUpd
  230. ppcLoadFloatReg1:
  231. fmr fr2, fr0
  232. b ppcLoadFloatRegUpd
  233. ppcLoadFloatReg2:
  234. fmr fr3, fr0
  235. b ppcLoadFloatRegUpd
  236. ppcLoadFloatReg3:
  237. fmr fr4, fr0
  238. b ppcLoadFloatRegUpd
  239. ppcLoadFloatReg4:
  240. fmr fr5, fr0
  241. b ppcLoadFloatRegUpd
  242. ppcLoadFloatReg5:
  243. fmr fr6, fr0
  244. b ppcLoadFloatRegUpd
  245. ppcLoadFloatReg6:
  246. fmr fr7, fr0
  247. b ppcLoadFloatRegUpd
  248. ppcLoadFloatReg7:
  249. fmr fr8, fr0
  250. b ppcLoadFloatRegUpd
  251. ppcLoadFloatReg8:
  252. fmr fr9, fr0
  253. b ppcLoadFloatRegUpd
  254. ppcLoadFloatReg9:
  255. fmr fr10, fr0
  256. b ppcLoadFloatRegUpd
  257. ppcLoadFloatReg10:
  258. fmr fr11, fr0
  259. b ppcLoadFloatRegUpd
  260. ppcLoadFloatReg11:
  261. fmr fr12, fr0
  262. b ppcLoadFloatRegUpd
  263. ppcLoadFloatReg12:
  264. fmr fr13, fr0
  265. b ppcLoadFloatRegUpd
  266. ppcLoadFloatRegUpd:
  267. stfs fr0, 0(r31) // push on the statck
  268. addi r31, r31, 8 // inc stack by 1 reg
  269. addi r22, r22, 1 // Increment used float register count
  270. addi r23, r23, 1 // Increment used int register count - a float reg eats up a GPR
  271. addi r29, r29, 4 // Increment rArgsPtr
  272. addi r26, r26, 4 // Increment rStackPtr
  273. b ppcNextArg // Call next arg
  274. //////////////////////////////////////////////////////////////////////////
  275. // Load and stack double float arguments
  276. //////////////////////////////////////////////////////////////////////////
  277. ppcArgIsDouble:
  278. // Get the arg from the stack
  279. lfd fr0, 0(r26)
  280. // r22 holds the float arg count so far
  281. cmplwi cr6, r22, 0
  282. beq cr6, ppcLoadDoubleReg0
  283. cmplwi cr6, r22, 1
  284. beq cr6, ppcLoadDoubleReg1
  285. cmplwi cr6, r22, 2
  286. beq cr6, ppcLoadDoubleReg2
  287. cmplwi cr6, r22, 3
  288. beq cr6, ppcLoadDoubleReg3
  289. cmplwi cr6, r22, 4
  290. beq cr6, ppcLoadDoubleReg4
  291. cmplwi cr6, r22, 5
  292. beq cr6, ppcLoadDoubleReg5
  293. cmplwi cr6, r22, 6
  294. beq cr6, ppcLoadDoubleReg6
  295. cmplwi cr6, r22, 7
  296. beq cr6, ppcLoadDoubleReg7
  297. cmplwi cr6, r22, 8
  298. beq cr6, ppcLoadDoubleReg8
  299. cmplwi cr6, r22, 9
  300. beq cr6, ppcLoadDoubleReg9
  301. cmplwi cr6, r22, 10
  302. beq cr6, ppcLoadDoubleReg10
  303. cmplwi cr6, r22, 11
  304. beq cr6, ppcLoadDoubleReg11
  305. cmplwi cr6, r22, 12
  306. beq cr6, ppcLoadDoubleReg12
  307. // no more than 12 parameters
  308. b ppcLoadDoubleRegUpd
  309. ppcLoadDoubleReg0:
  310. fmr fr1, fr0
  311. b ppcLoadDoubleRegUpd
  312. ppcLoadDoubleReg1:
  313. fmr fr2, fr0
  314. b ppcLoadDoubleRegUpd
  315. ppcLoadDoubleReg2:
  316. fmr fr3, fr0
  317. b ppcLoadDoubleRegUpd
  318. ppcLoadDoubleReg3:
  319. fmr fr4, fr0
  320. b ppcLoadDoubleRegUpd
  321. ppcLoadDoubleReg4:
  322. fmr fr5, fr0
  323. b ppcLoadDoubleRegUpd
  324. ppcLoadDoubleReg5:
  325. fmr fr6, fr0
  326. b ppcLoadDoubleRegUpd
  327. ppcLoadDoubleReg6:
  328. fmr fr7, fr0
  329. b ppcLoadDoubleRegUpd
  330. ppcLoadDoubleReg7:
  331. fmr fr8, fr0
  332. b ppcLoadDoubleRegUpd
  333. ppcLoadDoubleReg8:
  334. fmr fr9, fr0
  335. b ppcLoadDoubleRegUpd
  336. ppcLoadDoubleReg9:
  337. fmr fr10, fr0
  338. b ppcLoadDoubleRegUpd
  339. ppcLoadDoubleReg10:
  340. fmr fr11, fr0
  341. b ppcLoadDoubleRegUpd
  342. ppcLoadDoubleReg11:
  343. fmr fr12, fr0
  344. b ppcLoadDoubleRegUpd
  345. ppcLoadDoubleReg12:
  346. fmr fr13, fr0
  347. b ppcLoadDoubleRegUpd
  348. ppcLoadDoubleRegUpd:
  349. stfd fr0, 0(r31) // push on the statck
  350. addi r31, r31, 8 // inc stack by 1 reg
  351. addi r22, r22, 1 // Increment used float register count
  352. addi r23, r23, 1 // Increment used int register count
  353. addi r29, r29, 8 // Increment rArgsPtr
  354. addi r26, r26, 8 // Increment rStackPtr
  355. b ppcNextArg
  356. //////////////////////////////////////////////////////////////////////////
  357. // Finished
  358. //////////////////////////////////////////////////////////////////////////
  359. ppcArgsEnd:
  360. // Call the function
  361. mtctr r27
  362. bctrl
  363. // Function returned
  364. // Restore callers stack
  365. addi r1, r1, 0A0h
  366. // Fetch return link to caller
  367. lwz r12,-8(r1)
  368. mtlr r12
  369. // restore all registers we used in this fct
  370. ld r31,-10h(r1)
  371. ld r30,-18h(r1)
  372. ld r29,-20h(r1)
  373. ld r28,-28h(r1)
  374. ld r27,-30h(r1)
  375. ld r26,-38h(r1)
  376. ld r25,-40h(r1)
  377. ld r24,-48h(r1)
  378. ld r23,-50h(r1)
  379. ld r22,-58h(r1)
  380. ld r21,-60h(r1)
  381. blr
  382. }
  383. }
  384. // Puts the arguments in the correct place in the stack array.
  385. //-------------------------------------------------------------------
  386. void stackArgs(const asDWORD *pArgs, int& iNumIntArgs, int& iNumFloatArgs, int& iNumDoubleArgs)
  387. {
  388. asBYTE * pSrcArgs = (asBYTE *) pArgs; // pSrcArgs += (4*iArgWordPos);
  389. asBYTE * pDstArgs = (asBYTE *) ppcArgs; // pDstArgs += (4*iArgWordPos);
  390. for(int iArg = 0; iArg < AS_PPC_MAX_ARGS; iArg++)
  391. {
  392. if ( ppcArgsType[iArg] == ppcENDARG )
  393. break;
  394. if ( ppcArgsType[iArg] == ppcFLOATARG )
  395. {
  396. // stow float
  397. *((float*) pDstArgs) = *((float*) pSrcArgs);
  398. pSrcArgs += 4;
  399. pDstArgs += 4;
  400. iNumFloatArgs++;
  401. }
  402. else if ( ppcArgsType[iArg] == ppcDOUBLEARG )
  403. {
  404. // stow double
  405. *((double*) pDstArgs) = *((double*) pSrcArgs);
  406. pSrcArgs += 8;
  407. pDstArgs += 8;
  408. iNumDoubleArgs++;
  409. }
  410. else if ( ppcArgsType[iArg] == ppcINTARG )
  411. {
  412. // stow register
  413. *((int*) pDstArgs) = *((int*) pSrcArgs);
  414. pSrcArgs += 4;
  415. pDstArgs += 4;
  416. iNumIntArgs++;
  417. }
  418. }
  419. }
  420. // Prepare the arg list for a CDecl funtion and then call it
  421. //--------------------------------------------------------------------
  422. asQWORD CallCDeclFunction(const asDWORD* pArgs, int iArgSize, asDWORD dwFunc)
  423. {
  424. int iIntArgs = 0;
  425. int iFloatArgs = 0;
  426. int iDoubleArgs = 0;
  427. // Put the arguments in the correct places in the ppcArgs array
  428. if ( iArgSize > 0 )
  429. stackArgs( pArgs, iIntArgs, iFloatArgs, iDoubleArgs );
  430. return ppcFunc( ppcArgs, iArgSize, dwFunc);
  431. }
  432. // This function is identical to CallCDeclFunction, with the only difference that
  433. // the value in the first parameter is the object
  434. //--------------------------------------------------------------------
  435. asQWORD CallThisCallFunction(const void* pObj, const asDWORD* pArgs, int iArgSize, asDWORD dwFunc )
  436. {
  437. int iIntArgs = 0;
  438. int iFloatArgs = 0;
  439. int iDoubleArgs = 0;
  440. // Put the arguments in the correct places in the ppcArgs array /the this ptr is already in pArgs/
  441. if ( iArgSize > 0 )
  442. stackArgs( pArgs, iIntArgs, iFloatArgs, iDoubleArgs );
  443. return ppcFunc( ppcArgs, iArgSize, dwFunc);
  444. }
  445. // This function is identical to CallCDeclFunction, with the only difference that
  446. // the value in the last parameter is the object
  447. //--------------------------------------------------------------------
  448. asQWORD CallThisCallFunction_objLast(const void* pObj, const asDWORD* pArgs, int iArgSize, asDWORD dwFunc)
  449. {
  450. int iIntArgs = 0;
  451. int iFloatArgs = 0;
  452. int iDoubleArgs = 0;
  453. // Put the arguments in the correct places in the ppcArgs array /the this ptr is already in pArgs/
  454. if ( iArgSize > 0 )
  455. stackArgs( pArgs, iIntArgs, iFloatArgs, iDoubleArgs );
  456. int iNumArgs = iIntArgs + iFloatArgs + iDoubleArgs;
  457. int iDWordCount = (iIntArgs + iFloatArgs + 2*iDoubleArgs);
  458. if ( iDWordCount < AS_PPC_MAX_ARGS )
  459. {
  460. ppcArgs[iDWordCount] = (asDWORD)pObj;
  461. ppcArgsType[iNumArgs] = ppcINTARG;
  462. }
  463. return ppcFunc( ppcArgs, iArgSize + sizeof(pObj), dwFunc );
  464. }
  465. //--------------------------------------------------------------------
  466. asDWORD GetReturnedFloat()
  467. {
  468. asDWORD f;
  469. __asm
  470. {
  471. stfs fr1, f
  472. }
  473. return f;
  474. }
  475. asQWORD GetReturnedDouble()
  476. //--------------------------------------------------------------------
  477. {
  478. asQWORD f;
  479. __asm
  480. {
  481. stfd fr1, f
  482. }
  483. return f;
  484. }
  485. // returns true if the given parameter is a 'variable argument'
  486. inline bool IsVariableArgument( asCDataType type )
  487. {
  488. return (type.GetTokenType() == ttQuestion) ? true : false;
  489. }
  490. asQWORD CallSystemFunctionNative(asCContext *context, asCScriptFunction *descr, void *obj, asDWORD *args, void *retPointer, asQWORD &/*retQW2*/)
  491. {
  492. // TODO: optimize: This memset shouldn't be necessary
  493. memset( ppcArgsType, 0, sizeof(ppcArgsType));
  494. asCScriptEngine *engine = context->engine;
  495. asSSystemFunctionInterface *sysFunc = descr->sysFuncIntf;
  496. int callConv = sysFunc->callConv;
  497. asQWORD retQW = 0;
  498. void* func = (void*)sysFunc->func;
  499. int paramSize = sysFunc->paramSize;
  500. asDWORD* vftable;
  501. // We generate the parameter list to this, so it fits to teh callingconvention
  502. asDWORD fixedArgs[ AS_PPC_MAX_ARGS + AS_PPC_RETURNINMEM_REG + AS_PPC_THISCALL_REG ];
  503. memset(fixedArgs, 0, sizeof(fixedArgs));
  504. int argsPtr = 0;
  505. // If the function returns an object in memory, we allocate the memory and put the ptr to the front (will go to r3)
  506. if ( descr->returnType.IsObject() && !descr->returnType.IsReference() && !descr->returnType.IsObjectHandle() )
  507. {
  508. fixedArgs [ argsPtr ] = (asDWORD)retPointer;
  509. ppcArgsType[ argsPtr ] = ppcINTARG;
  510. argsPtr++;
  511. }
  512. // If we have an object and it's not objectlast, then we put it az the first arg
  513. if ( obj
  514. && callConv != ICC_CDECL_OBJLAST
  515. && callConv != ICC_CDECL_OBJLAST_RETURNINMEM )
  516. {
  517. fixedArgs [ argsPtr ] = (asDWORD)obj;
  518. ppcArgsType[ argsPtr ] = ppcINTARG;
  519. argsPtr++;
  520. }
  521. asASSERT(descr->parameterTypes.GetLength() <= AS_PPC_MAX_ARGS);
  522. // Parameter calculation magic
  523. asDWORD paramBuffer[64];
  524. if ( sysFunc->takesObjByVal )
  525. {
  526. paramSize = 0;
  527. int spos = 0;
  528. int dpos = 1;
  529. for ( asUINT n = 0; n < descr->parameterTypes.GetLength(); n++ )
  530. {
  531. // Parameter object by value
  532. if ( descr->parameterTypes[n].IsObject()
  533. && !descr->parameterTypes[n].IsObjectHandle()
  534. && !descr->parameterTypes[n].IsReference() )
  535. {
  536. #ifdef COMPLEX_OBJS_PASSED_BY_REF
  537. if( descr->parameterTypes[n].GetObjectType()->flags & COMPLEX_MASK )
  538. {
  539. paramBuffer[dpos++] = args[spos++];
  540. paramSize++;
  541. }
  542. else
  543. #endif
  544. {
  545. // Copy the object's memory to the buffer
  546. memcpy( &paramBuffer[dpos], *(void**)(args + spos), descr->parameterTypes[n].GetSizeInMemoryBytes() );
  547. // Delete the original memory
  548. engine->CallFree(*(char**)(args + spos) );
  549. spos++;
  550. dpos += descr->parameterTypes[n].GetSizeInMemoryDWords();
  551. paramSize += descr->parameterTypes[n].GetSizeInMemoryDWords();
  552. }
  553. }
  554. else
  555. {
  556. // Copy the value directly
  557. paramBuffer[dpos++] = args[spos++];
  558. if( descr->parameterTypes[n].GetSizeOnStackDWords() > 1 )
  559. paramBuffer[dpos++] = args[spos++];
  560. paramSize += descr->parameterTypes[n].GetSizeOnStackDWords();
  561. }
  562. // if this was a variable argument parameter, then account for the implicit typeID
  563. if( IsVariableArgument( descr->parameterTypes[n] ) )
  564. {
  565. // the TypeID is just a DWORD
  566. paramBuffer[dpos++] = args[spos++];
  567. ++paramSize;
  568. }
  569. }
  570. // Keep a free location at the beginning
  571. args = &paramBuffer[1];
  572. }
  573. const asUINT paramCount = (asUINT)descr->parameterTypes.GetLength();
  574. asBYTE * pCurArgType = (asBYTE*)&ppcArgsType[argsPtr];
  575. asBYTE * pCurFixedArgValue = (asBYTE*)&fixedArgs[argsPtr];
  576. asBYTE * pCurStackArgValue = (asBYTE*)args;
  577. for( asUINT n = 0; n < paramCount ; n++ )
  578. {
  579. argsPtr++;
  580. if (descr->parameterTypes[n].IsFloatType() && !descr->parameterTypes[n].IsReference())
  581. {
  582. *pCurArgType++ = ppcFLOATARG;
  583. *((float*) pCurFixedArgValue) = *((float*) pCurStackArgValue);
  584. pCurFixedArgValue += 4;
  585. pCurStackArgValue += 4;
  586. }
  587. else if (descr->parameterTypes[n].IsDoubleType() && !descr->parameterTypes[n].IsReference())
  588. {
  589. *pCurArgType++ = ppcDOUBLEARG;
  590. *((double*) pCurFixedArgValue) = *((double*) pCurStackArgValue);
  591. pCurFixedArgValue += 8;
  592. pCurStackArgValue += 8;
  593. }
  594. else
  595. {
  596. // TODO: How should int64 and uint64 be passed natively?
  597. // Currently the code doesn't handle these types
  598. // TODO: The code also ignore the fact that large objects
  599. // passed by value has been copied to the stack
  600. // in the above loop.
  601. *pCurArgType++ = ppcINTARG;
  602. *((int*) pCurFixedArgValue) = *((int*) pCurStackArgValue);
  603. if( !descr->parameterTypes[n].IsReference() )
  604. {
  605. // If the arg is less that 4 bytes, then move the
  606. // bytes to the higher bytes within the dword
  607. asUINT numBytes = descr->parameterTypes[n].GetSizeInMemoryBytes();
  608. if( numBytes == 1 )
  609. {
  610. pCurFixedArgValue[3] = pCurFixedArgValue[0];
  611. pCurFixedArgValue[0] = 0;
  612. }
  613. else if( numBytes == 2 )
  614. {
  615. *(asWORD*)&pCurFixedArgValue[2] = *(asWORD*)&pCurFixedArgValue[0];
  616. *(asWORD*)&pCurFixedArgValue[0] = 0;
  617. }
  618. }
  619. pCurFixedArgValue += 4;
  620. pCurStackArgValue += 4;
  621. }
  622. // if it is a variable argument, account for the typeID
  623. // implicitly add another parameter (AFTER the parameter above), for the TypeID
  624. if( IsVariableArgument(descr->parameterTypes[n]) )
  625. {
  626. argsPtr++;
  627. *pCurArgType++ = ppcINTARG;
  628. *((int*) pCurFixedArgValue) = *((int*) pCurStackArgValue);
  629. pCurFixedArgValue += 4;
  630. pCurStackArgValue += 4;
  631. }
  632. }
  633. context->isCallingSystemFunction = true;
  634. switch( callConv )
  635. {
  636. case ICC_CDECL:
  637. case ICC_CDECL_RETURNINMEM:
  638. case ICC_STDCALL:
  639. case ICC_STDCALL_RETURNINMEM:
  640. retQW = CallCDeclFunction( fixedArgs, argsPtr, (asDWORD)func );
  641. break;
  642. case ICC_THISCALL:
  643. case ICC_THISCALL_RETURNINMEM:
  644. retQW = CallThisCallFunction( obj, fixedArgs, argsPtr, (asDWORD)func );
  645. break;
  646. case ICC_VIRTUAL_THISCALL:
  647. case ICC_VIRTUAL_THISCALL_RETURNINMEM:
  648. // Get virtual function table from the object pointer
  649. vftable = *(asDWORD**)obj;
  650. retQW = CallThisCallFunction( obj, fixedArgs, argsPtr, vftable[asDWORD(func)>>2] );
  651. break;
  652. case ICC_CDECL_OBJLAST:
  653. case ICC_CDECL_OBJLAST_RETURNINMEM:
  654. retQW = CallThisCallFunction_objLast( obj, fixedArgs, argsPtr, (asDWORD)func );
  655. break;
  656. case ICC_CDECL_OBJFIRST:
  657. case ICC_CDECL_OBJFIRST_RETURNINMEM:
  658. retQW = CallThisCallFunction( obj, fixedArgs, argsPtr, (asDWORD)func );
  659. break;
  660. default:
  661. context->SetInternalException( TXT_INVALID_CALLING_CONVENTION );
  662. }
  663. context->isCallingSystemFunction = false;
  664. // If the return is a float value we need to get the value from the FP register
  665. if( sysFunc->hostReturnFloat )
  666. {
  667. if( sysFunc->hostReturnSize == 1 )
  668. *(asDWORD*)&retQW = GetReturnedFloat();
  669. else
  670. retQW = GetReturnedDouble();
  671. }
  672. else if( sysFunc->hostReturnSize == 1 )
  673. {
  674. // Move the bits to the higher value to compensate for the adjustment that the caller does
  675. retQW <<= 32;
  676. }
  677. return retQW;
  678. }
  679. END_AS_NAMESPACE
  680. #endif // AS_XENON
  681. #endif // AS_MAX_PORTABILITY
  682. //------------------------------------------------------------------