| 328 | } |
| 329 | |
| 330 | void JitCompiler::EmitNativeCall(VMNativeFunction *target) |
| 331 | { |
| 332 | using namespace asmjit; |
| 333 | |
| 334 | if (pc > sfunc->Code && (pc - 1)->op == OP_VTBL) |
| 335 | { |
| 336 | I_Error("Native direct member function calls not implemented\n"); |
| 337 | } |
| 338 | |
| 339 | if (target->ImplicitArgs > 0) |
| 340 | { |
| 341 | auto label = EmitThrowExceptionLabel(X_READ_NIL); |
| 342 | |
| 343 | assert(ParamOpcodes.Size() > 0); |
| 344 | const VMOP *param = ParamOpcodes[0]; |
| 345 | const int bc = param->i16u; |
| 346 | asmjit::X86Gp *reg = nullptr; |
| 347 | |
| 348 | switch (param->a & REGT_TYPE) |
| 349 | { |
| 350 | case REGT_STRING: reg = ®S[bc]; break; |
| 351 | case REGT_POINTER: reg = ®A[bc]; break; |
| 352 | default: |
| 353 | I_Error("Unexpected register type for self pointer\n"); |
| 354 | break; |
| 355 | } |
| 356 | |
| 357 | cc.test(*reg, *reg); |
| 358 | cc.jz(label); |
| 359 | } |
| 360 | |
| 361 | asmjit::CBNode *cursorBefore = cc.getCursor(); |
| 362 | auto call = cc.call(imm_ptr(target->DirectNativeCall), CreateFuncSignature()); |
| 363 | call->setInlineComment(target->PrintableName); |
| 364 | asmjit::CBNode *cursorAfter = cc.getCursor(); |
| 365 | cc.setCursor(cursorBefore); |
| 366 | |
| 367 | X86Gp tmp; |
| 368 | X86Xmm tmp2; |
| 369 | |
| 370 | int numparams = 0; |
| 371 | for (unsigned int i = 0; i < ParamOpcodes.Size(); i++) |
| 372 | { |
| 373 | int slot = numparams++; |
| 374 | |
| 375 | if (ParamOpcodes[i]->op == OP_PARAMI) |
| 376 | { |
| 377 | int abcs = ParamOpcodes[i]->i24; |
| 378 | call->setArg(slot, imm(abcs)); |
| 379 | } |
| 380 | else // OP_PARAM |
| 381 | { |
| 382 | int bc = ParamOpcodes[i]->i16u; |
| 383 | switch (ParamOpcodes[i]->a) |
| 384 | { |
| 385 | case REGT_NIL: |
| 386 | call->setArg(slot, imm(0)); |
| 387 | break; |