extensions/bintools/jit_call.cpp
author Scott Ehlert <ds@alliedmods.net>
Sun May 06 06:44:18 2007 +0000 (2007-05-06)
changeset 744 8786ac96ef66
parent 742 afc8caafe7c2
child 757 b799caa9a190
permissions -rw-r--r--
Oh, I forgot about this
faluco@739
     1
/**
faluco@739
     2
 * vim: set ts=4 :
faluco@739
     3
 * ===============================================================
faluco@739
     4
 * SourceMod, Copyright (C) 2004-2007 AlliedModders LLC. 
faluco@739
     5
 * All rights reserved.
faluco@739
     6
 * ===============================================================
faluco@739
     7
 *
faluco@739
     8
 *  This file is part of the SourceMod/SourcePawn SDK.  This file may only be 
faluco@739
     9
 * used or modified under the Terms and Conditions of its License Agreement, 
faluco@739
    10
 * which is found in public/licenses/LICENSE.txt.  As of this notice, derivative 
faluco@739
    11
 * works must be licensed under the GNU General Public License (version 2 or 
faluco@739
    12
 * greater).  A copy of the GPL is included under public/licenses/GPL.txt.
faluco@739
    13
 * 
faluco@739
    14
 * To view the latest information, see: http://www.sourcemod.net/license.php
faluco@739
    15
 *
faluco@739
    16
 * Version: $Id$
faluco@739
    17
 */
faluco@739
    18
faluco@739
    19
#include <sm_platform.h>
faluco@739
    20
#include "extension.h"
faluco@739
    21
#include <jit_helpers.h>
faluco@739
    22
#include <x86_macros.h>
faluco@739
    23
#include "jit_call.h"
faluco@739
    24
faluco@739
    25
jit_uint32_t g_StackUsage = 0;
faluco@739
    26
jit_uint32_t g_RegDecoder = 0;
faluco@739
    27
faluco@739
    28
/********************
faluco@739
    29
 * Assembly Helpers *
faluco@739
    30
 ********************/
faluco@739
    31
faluco@739
    32
inline jit_uint8_t _DecodeRegister3(jit_uint32_t val)
faluco@739
    33
{
faluco@739
    34
	switch (val % 3)
faluco@739
    35
	{
faluco@739
    36
	case 0:
faluco@739
    37
		{
faluco@739
    38
			return REG_EAX;
faluco@739
    39
		}
faluco@739
    40
	case 1:
faluco@739
    41
		{
faluco@739
    42
			return REG_EDX;
faluco@739
    43
		}
faluco@739
    44
	case 2:
faluco@739
    45
		{
faluco@739
    46
			return REG_ECX;
faluco@739
    47
		}
faluco@739
    48
	}
faluco@739
    49
faluco@739
    50
	/* Should never happen */
faluco@739
    51
	return 0xFF;
faluco@739
    52
}
faluco@739
    53
faluco@739
    54
/********************
faluco@739
    55
 * Assembly Opcodes *
faluco@739
    56
 ********************/
faluco@739
    57
faluco@739
    58
inline void Write_Execution_Prologue(JitWriter *jit, bool is_void, bool has_params)
faluco@739
    59
{
faluco@739
    60
	//push ebp
faluco@739
    61
	//mov ebp, esp
faluco@739
    62
	//if !is_void
faluco@739
    63
	// push edi
faluco@739
    64
	// mov edi, [ebp+12]
faluco@739
    65
	//if has_params
faluco@739
    66
	// push ebx
faluco@739
    67
	// mov ebx, [ebp+8]
faluco@739
    68
	IA32_Push_Reg(jit, REG_EBP);
faluco@739
    69
	IA32_Mov_Reg_Rm(jit, REG_EBP, REG_ESP, MOD_REG);
faluco@739
    70
	if (!is_void)
faluco@739
    71
	{
faluco@739
    72
		IA32_Push_Reg(jit, REG_EDI);
faluco@739
    73
		IA32_Mov_Reg_Rm_Disp8(jit, REG_EDI, REG_EBP, 12);
faluco@739
    74
	}
faluco@739
    75
	if (has_params)
faluco@739
    76
	{
faluco@739
    77
		IA32_Push_Reg(jit, REG_EBX);
faluco@739
    78
		IA32_Mov_Reg_Rm_Disp8(jit, REG_EBX, REG_EBP, 8);
faluco@739
    79
	}
faluco@739
    80
}
faluco@739
    81
faluco@739
    82
inline void Write_Function_Epilogue(JitWriter *jit, bool is_void, bool has_params)
faluco@739
    83
{
faluco@739
    84
	//if has_params
faluco@739
    85
	// pop ebx
faluco@739
    86
	//if !is_void
faluco@739
    87
	// pop edi
faluco@739
    88
	//mov esp, ebp
faluco@739
    89
	//pop ebp
faluco@739
    90
	//ret
faluco@739
    91
	if (has_params)
faluco@739
    92
	{
faluco@739
    93
		IA32_Pop_Reg(jit, REG_EBX);
faluco@739
    94
	}
faluco@739
    95
	if (!is_void)
faluco@739
    96
	{
faluco@739
    97
		IA32_Pop_Reg(jit, REG_EDI);
faluco@739
    98
	}
faluco@739
    99
	IA32_Mov_Reg_Rm(jit, REG_ESP, REG_EBP, MOD_REG);
faluco@739
   100
	IA32_Pop_Reg(jit, REG_EBP);
faluco@739
   101
	IA32_Return(jit);
faluco@739
   102
}
faluco@739
   103
faluco@739
   104
inline void Write_PushPOD(JitWriter *jit, const PassEncode *pEnc)
faluco@739
   105
{
faluco@739
   106
	jit_uint8_t reg = _DecodeRegister3(g_RegDecoder++);
faluco@739
   107
faluco@739
   108
	if (pEnc->info.flags & PASSFLAG_BYVAL)
faluco@739
   109
	{
faluco@739
   110
		switch (pEnc->info.size)
faluco@739
   111
		{
faluco@739
   112
		case 1:
faluco@739
   113
			{
faluco@739
   114
				//xor reg, reg
faluco@739
   115
				//mov reg, BYTE PTR [ebx+<offset>]
faluco@739
   116
				//push reg
faluco@739
   117
				IA32_Xor_Reg_Rm(jit, reg, reg, MOD_REG);
faluco@739
   118
				if (pEnc->offset < SCHAR_MAX)
faluco@739
   119
				{
faluco@739
   120
					IA32_Mov_Reg8_Rm8_Disp8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset);
faluco@739
   121
				} else if (!pEnc->offset) {
faluco@739
   122
					IA32_Mov_Reg8_Rm8(jit, reg, REG_EBX, MOD_MEM_REG);
faluco@739
   123
				} else {
faluco@739
   124
					IA32_Mov_Reg8_Rm8_Disp32(jit, reg, REG_EBX, pEnc->offset);
faluco@739
   125
				}
faluco@739
   126
				IA32_Push_Reg(jit, reg);
faluco@739
   127
faluco@739
   128
				g_StackUsage += 4;
faluco@739
   129
				break;
faluco@739
   130
			}
faluco@739
   131
		case 2:
faluco@739
   132
			{
faluco@739
   133
				//xor reg, reg
faluco@739
   134
				//mov reg, WORD PTR [ebx+<offset>]
faluco@739
   135
				//push reg
faluco@739
   136
				IA32_Xor_Reg_Rm(jit, reg, reg, MOD_REG);
faluco@739
   137
				jit->write_ubyte(IA32_16BIT_PREFIX);
faluco@739
   138
				if (pEnc->offset < SCHAR_MAX)
faluco@739
   139
				{
faluco@739
   140
					IA32_Mov_Reg_Rm_Disp8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset);
faluco@739
   141
				} else if (!pEnc->offset) {
faluco@739
   142
					IA32_Mov_Reg_Rm(jit, reg, REG_EBX, MOD_MEM_REG);
faluco@739
   143
				} else {
faluco@739
   144
					IA32_Mov_Reg_Rm_Disp32(jit, reg, REG_EBX, pEnc->offset);
faluco@739
   145
				}
faluco@739
   146
				IA32_Push_Reg(jit, reg);
faluco@739
   147
faluco@739
   148
				g_StackUsage += 4;
faluco@739
   149
				break;
faluco@739
   150
			}
faluco@739
   151
		case 4:
faluco@739
   152
			{
faluco@739
   153
				//mov reg, DWORD PTR [ebx+<offset>]
faluco@739
   154
				//push reg
faluco@739
   155
				if (pEnc->offset < SCHAR_MAX)
faluco@739
   156
				{
faluco@739
   157
					IA32_Mov_Reg_Rm_Disp8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset);
faluco@739
   158
				} else if (!pEnc->offset) {
faluco@739
   159
					IA32_Mov_Reg_Rm(jit, reg, REG_EBX, MOD_MEM_REG);
faluco@739
   160
				} else {
faluco@739
   161
					IA32_Mov_Reg_Rm_Disp32(jit, reg, REG_EBX, pEnc->offset);
faluco@739
   162
				}
faluco@739
   163
				IA32_Push_Reg(jit, reg);
faluco@739
   164
faluco@739
   165
				g_StackUsage += 4;
faluco@739
   166
				break;
faluco@739
   167
			}
faluco@739
   168
		case 8:
faluco@739
   169
			{
faluco@739
   170
				//mov reg, DWORD PTR [ebx+<offset>+4]
faluco@739
   171
				//mov reg2, DWORD PTR [ebx+<offset>]
faluco@739
   172
				//push reg
faluco@739
   173
				//push reg2
faluco@739
   174
				jit_uint8_t reg2 = _DecodeRegister3(g_RegDecoder++);
faluco@739
   175
faluco@739
   176
				if (pEnc->offset+4 < SCHAR_MAX)
faluco@739
   177
				{
faluco@739
   178
					IA32_Mov_Reg_Rm_Disp8(jit, reg, REG_EBX, (jit_int8_t)(pEnc->offset+4));
faluco@739
   179
				} else {
faluco@739
   180
					IA32_Mov_Reg_Rm_Disp32(jit, reg, REG_EBX, pEnc->offset+4);
faluco@739
   181
				}
faluco@739
   182
				if (pEnc->offset < SCHAR_MAX)
faluco@739
   183
				{
faluco@739
   184
					IA32_Mov_Reg_Rm_Disp8(jit, reg2, REG_EBX, (jit_int8_t)pEnc->offset);
faluco@739
   185
				} else if (!pEnc->offset) {
faluco@739
   186
					IA32_Mov_Reg_Rm(jit, reg, REG_EBX, MOD_MEM_REG);
faluco@739
   187
				} else {
faluco@739
   188
					IA32_Mov_Reg_Rm_Disp32(jit, reg2, REG_EBX, pEnc->offset);
faluco@739
   189
				}
faluco@739
   190
				IA32_Push_Reg(jit, reg);
faluco@739
   191
				IA32_Push_Reg(jit, reg2);
faluco@739
   192
faluco@739
   193
				g_StackUsage += 8;
faluco@739
   194
				break;
faluco@739
   195
			}
faluco@739
   196
		}
faluco@739
   197
	} else if (pEnc->info.flags & PASSFLAG_BYREF) {
faluco@739
   198
		//lea reg, [ebx+<offset>]
faluco@739
   199
		//push reg
faluco@739
   200
		if (!pEnc->offset)
faluco@739
   201
		{
faluco@739
   202
			IA32_Push_Reg(jit, REG_EBX);
faluco@739
   203
			g_StackUsage += 4;
faluco@739
   204
			return;
faluco@739
   205
		}
faluco@739
   206
		if (pEnc->offset < SCHAR_MAX)
faluco@739
   207
		{
faluco@739
   208
			IA32_Lea_DispRegImm8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset);
faluco@739
   209
		} else {
faluco@739
   210
			IA32_Lea_DispRegImm32(jit, reg, REG_EBX, pEnc->offset);
faluco@739
   211
		}
faluco@739
   212
		IA32_Push_Reg(jit, reg);
faluco@739
   213
faluco@739
   214
		g_StackUsage += 4;
faluco@739
   215
	}
faluco@739
   216
}
faluco@739
   217
faluco@739
   218
inline void Write_PushFloat(JitWriter *jit, const PassEncode *pEnc)
faluco@739
   219
{
faluco@739
   220
	if (pEnc->info.flags & PASSFLAG_BYVAL)
faluco@739
   221
	{
faluco@739
   222
		switch (pEnc->info.size)
faluco@739
   223
		{
faluco@739
   224
		case 4:
faluco@739
   225
			{
faluco@739
   226
				//fld DWORD PTR [ebx+<offset>]
faluco@739
   227
				//push reg
faluco@739
   228
				//fstp DWORD PTR [esp]
faluco@739
   229
				if (pEnc->offset < SCHAR_MAX)
faluco@739
   230
				{
faluco@739
   231
					IA32_Fld_Mem32_Disp8(jit, REG_EBX, (jit_int8_t)pEnc->offset);
faluco@739
   232
				} else {
faluco@739
   233
					IA32_Fld_Mem32_Disp32(jit, REG_EBX, pEnc->offset);
faluco@739
   234
				}
faluco@739
   235
				IA32_Push_Reg(jit, _DecodeRegister3(g_RegDecoder++));
faluco@739
   236
				IA32_Fstp_Mem32(jit, REG_ESP, REG_NOIDX, NOSCALE);
faluco@739
   237
				g_StackUsage += 4;
faluco@739
   238
				break;
faluco@739
   239
			}
faluco@739
   240
		case 8:
faluco@739
   241
			{
faluco@739
   242
				//fld QWORD PTR [ebx+<offset>]
faluco@739
   243
				//sub esp, 8
faluco@739
   244
				//fstp QWORD PTR [esp]
faluco@739
   245
				if (pEnc->offset < SCHAR_MAX)
faluco@739
   246
				{
faluco@739
   247
					IA32_Fld_Mem64_Disp8(jit, REG_EBX, (jit_int8_t)pEnc->offset);
faluco@739
   248
				} else {
faluco@739
   249
					IA32_Fld_Mem64_Disp32(jit, REG_EBX, pEnc->offset);
faluco@739
   250
				}
faluco@739
   251
				IA32_Sub_Rm_Imm8(jit, REG_ESP, 8, MOD_REG);
faluco@739
   252
				IA32_Fstp_Mem64(jit, REG_ESP, REG_NOIDX, NOSCALE);
faluco@739
   253
				g_StackUsage += 8;
faluco@739
   254
				break;
faluco@739
   255
			}
faluco@739
   256
		}
faluco@739
   257
	} else if (pEnc->info.flags & PASSFLAG_BYREF) {
faluco@739
   258
		//lea reg, [ebx+<offset>]
faluco@739
   259
		//push reg
faluco@739
   260
		if (!pEnc->offset)
faluco@739
   261
		{
faluco@739
   262
			IA32_Push_Reg(jit, REG_EBX);
faluco@739
   263
			g_StackUsage += 4;
faluco@739
   264
			return;
faluco@739
   265
		}
faluco@739
   266
faluco@739
   267
		jit_uint8_t reg = _DecodeRegister3(g_RegDecoder++);
faluco@739
   268
		if (pEnc->offset < SCHAR_MAX)
faluco@739
   269
		{
faluco@739
   270
			IA32_Lea_DispRegImm8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset);
faluco@739
   271
		} else {
faluco@739
   272
			IA32_Lea_DispRegImm32(jit, reg, REG_EBX, pEnc->offset);
faluco@739
   273
		}
faluco@739
   274
		IA32_Push_Reg(jit, reg);
faluco@739
   275
faluco@739
   276
		g_StackUsage += 4;
faluco@739
   277
	}
faluco@739
   278
}
faluco@739
   279
faluco@739
   280
inline void Write_PushObject(JitWriter *jit, const PassEncode *pEnc)
faluco@739
   281
{
faluco@739
   282
	if (pEnc->info.flags & PASSFLAG_BYVAL)
faluco@739
   283
	{
faluco@739
   284
#ifdef PLATFORM_POSIX
faluco@739
   285
		if (pEnc->info.flags & PASSFLAG_ODTOR)
faluco@739
   286
		{
faluco@739
   287
			goto push_byref;
faluco@739
   288
		}
faluco@739
   289
#endif
faluco@739
   290
		jit_uint32_t dwords = pEnc->info.size >> 2;
faluco@739
   291
		jit_uint32_t bytes = pEnc->info.size & 0x3;
faluco@739
   292
faluco@739
   293
		//sub esp, <size>
faluco@739
   294
		//cld
faluco@739
   295
		//push edi
faluco@739
   296
		//push esi
faluco@739
   297
		//lea edi, [esp+8]
faluco@739
   298
		//lea esi, [ebx+<offs>]
faluco@739
   299
		//if dwords
faluco@739
   300
		// mov ecx, <dwords>
faluco@739
   301
		// rep movsd
faluco@739
   302
		//if bytes
faluco@739
   303
		// mov ecx, <bytes>
faluco@739
   304
		// rep movsb
faluco@739
   305
		//pop esi
faluco@739
   306
		//pop edi
faluco@739
   307
		if (pEnc->info.size < SCHAR_MAX)
faluco@739
   308
		{
faluco@739
   309
			IA32_Sub_Rm_Imm8(jit, REG_ESP, (jit_int8_t)pEnc->info.size, MOD_REG);
faluco@739
   310
		} else {
faluco@739
   311
			IA32_Sub_Rm_Imm32(jit, REG_ESP, pEnc->info.size, MOD_REG);
faluco@739
   312
		}
faluco@739
   313
		IA32_Cld(jit);
faluco@739
   314
		IA32_Push_Reg(jit, REG_EDI);
faluco@739
   315
		IA32_Push_Reg(jit, REG_ESI);
faluco@739
   316
		IA32_Lea_Reg_DispRegMultImm8(jit, REG_EDI, REG_NOIDX, REG_ESP, NOSCALE, 8);
faluco@739
   317
		if (pEnc->offset < SCHAR_MAX)
faluco@739
   318
		{
faluco@739
   319
			IA32_Lea_DispRegImm8(jit, REG_ESI, REG_EBX, (jit_int8_t)pEnc->offset);
faluco@739
   320
		} else if (!pEnc->offset) {
faluco@739
   321
			IA32_Mov_Reg_Rm(jit, REG_ESI, REG_EBX, MOD_REG);
faluco@739
   322
		} else {
faluco@739
   323
			IA32_Lea_DispRegImm32(jit, REG_ESI, REG_EBX, pEnc->offset);
faluco@739
   324
		}
faluco@739
   325
		if (dwords)
faluco@739
   326
		{
faluco@739
   327
			IA32_Mov_Reg_Imm32(jit, REG_ECX, dwords);
faluco@739
   328
			IA32_Rep(jit);
faluco@739
   329
			IA32_Movsd(jit);
faluco@739
   330
		}
faluco@739
   331
		if (bytes)
faluco@739
   332
		{
faluco@739
   333
			IA32_Mov_Reg_Imm32(jit, REG_ECX, bytes);
faluco@739
   334
			IA32_Rep(jit);
faluco@739
   335
			IA32_Movsb(jit);
faluco@739
   336
		}
faluco@739
   337
		IA32_Pop_Reg(jit, REG_ESI);
faluco@739
   338
		IA32_Pop_Reg(jit, REG_EDI);
faluco@739
   339
faluco@739
   340
		g_StackUsage += pEnc->info.size;
faluco@739
   341
	} else if (pEnc->info.flags & PASSFLAG_BYREF) {
faluco@739
   342
#ifdef PLATFORM_POSIX
faluco@739
   343
push_byref:
faluco@739
   344
#endif
faluco@739
   345
		if (!pEnc->offset)
faluco@739
   346
		{
faluco@739
   347
			IA32_Push_Reg(jit, REG_EBX);
faluco@739
   348
			g_StackUsage += 4;
faluco@739
   349
			return;
faluco@739
   350
		}
faluco@739
   351
faluco@739
   352
		//lea reg, [ebx+<offset>]
faluco@739
   353
		//push reg
faluco@739
   354
		jit_uint8_t reg = _DecodeRegister3(g_RegDecoder++);
faluco@739
   355
		if (pEnc->offset < SCHAR_MAX)
faluco@739
   356
		{
faluco@739
   357
			IA32_Lea_DispRegImm8(jit, reg, REG_EBX, (jit_int8_t)pEnc->offset);
faluco@739
   358
		} else {
faluco@739
   359
			IA32_Lea_DispRegImm32(jit, reg, REG_EBX, pEnc->offset);
faluco@739
   360
		}
faluco@739
   361
		IA32_Push_Reg(jit, reg);
faluco@739
   362
faluco@739
   363
		g_StackUsage += 4;
faluco@739
   364
	}
faluco@739
   365
}
faluco@739
   366
faluco@739
   367
inline void Write_PushThisPtr(JitWriter *jit)
faluco@739
   368
{
faluco@739
   369
#ifdef PLATFORM_POSIX
faluco@739
   370
	//mov reg, [ebx]
faluco@739
   371
	//push reg
faluco@739
   372
	jit_uint8_t reg = _DecodeRegister3(g_RegDecoder++);
faluco@739
   373
faluco@739
   374
	IA32_Mov_Reg_Rm(jit, reg, REG_EBX, MOD_MEM_REG);
faluco@739
   375
	IA32_Push_Reg(jit, reg);
faluco@739
   376
faluco@739
   377
	g_StackUsage += 4;
faluco@739
   378
#elif defined PLATFORM_WINDOWS
faluco@739
   379
	//mov ecx, [ebx]
faluco@739
   380
	IA32_Mov_Reg_Rm(jit, REG_ECX, REG_EBX, MOD_MEM_REG);
faluco@739
   381
#endif
faluco@739
   382
}
faluco@739
   383
faluco@739
   384
inline void Write_PushRetBuffer(JitWriter *jit)
faluco@739
   385
{
faluco@739
   386
	//push edi
faluco@739
   387
	IA32_Push_Reg(jit, REG_EDI);
faluco@739
   388
}
faluco@739
   389
faluco@739
   390
inline void Write_CallFunction(JitWriter *jit, FuncAddrMethod method, CallWrapper *pWrapper)
faluco@739
   391
{
faluco@739
   392
	if (method == FuncAddr_Direct)
faluco@739
   393
	{
faluco@739
   394
		//call <addr>
faluco@739
   395
		jitoffs_t call = IA32_Call_Imm32(jit, 0);
faluco@739
   396
		IA32_Write_Jump32_Abs(jit, call, pWrapper->m_Addrs[ADDR_CALLEE]);
faluco@739
   397
	} else if (method == FuncAddr_VTable) {
faluco@739
   398
		//*(this + thisOffs + vtblOffs)[vtblIdx]
faluco@739
   399
		//mov edx, [ebx]
faluco@739
   400
		//mov eax, [edx+<thisOffs>+<vtblOffs>]
faluco@739
   401
		//mov edx, [eax+<vtblIdx>*4]
faluco@739
   402
		//call edx
faluco@739
   403
		jit_uint32_t total_offs = pWrapper->m_VtInfo.thisOffs + pWrapper->m_VtInfo.vtblOffs;
faluco@739
   404
		jit_uint32_t vfunc_pos = pWrapper->m_VtInfo.vtblIdx * 4;
faluco@739
   405
faluco@739
   406
		IA32_Mov_Reg_Rm(jit, REG_EDX, REG_EBX, MOD_MEM_REG);
faluco@739
   407
		if (total_offs < SCHAR_MAX)
faluco@739
   408
		{
faluco@739
   409
			IA32_Mov_Reg_Rm_Disp8(jit, REG_EAX, REG_EDX, (jit_int8_t)total_offs);
faluco@739
   410
		} else if (!total_offs) {
faluco@739
   411
			IA32_Mov_Reg_Rm(jit, REG_EAX, REG_EDX, MOD_MEM_REG);
faluco@739
   412
		} else {
faluco@739
   413
			IA32_Mov_Reg_Rm_Disp32(jit, REG_EAX, REG_EDX, total_offs);
faluco@739
   414
		}
faluco@739
   415
		if (vfunc_pos < SCHAR_MAX)
faluco@739
   416
		{
faluco@739
   417
			IA32_Mov_Reg_Rm_Disp8(jit, REG_EDX, REG_EAX, (jit_int8_t)vfunc_pos);
faluco@739
   418
		} else if (!vfunc_pos) {
faluco@739
   419
			IA32_Mov_Reg_Rm(jit, REG_EDX, REG_EAX, MOD_MEM_REG);
faluco@739
   420
		} else {
faluco@739
   421
			IA32_Mov_Reg_Rm_Disp32(jit, REG_EDX, REG_EAX, vfunc_pos);
faluco@739
   422
		}
faluco@739
   423
		IA32_Call_Reg(jit, REG_EDX);
faluco@739
   424
	}
faluco@739
   425
}
faluco@739
   426
faluco@739
   427
inline void Write_RectifyStack(JitWriter *jit, jit_uint32_t value)
faluco@739
   428
{
faluco@739
   429
	//add esp, <value>
faluco@739
   430
	if (value < SCHAR_MAX)
faluco@739
   431
	{
faluco@739
   432
		IA32_Add_Rm_Imm8(jit, REG_ESP, (jit_int8_t)value, MOD_REG);
faluco@739
   433
	} else {
faluco@739
   434
		IA32_Add_Rm_Imm32(jit, REG_ESP, value, MOD_REG);
faluco@739
   435
	}
faluco@739
   436
}
faluco@739
   437
faluco@739
   438
inline void Write_MovRet2Buf(JitWriter *jit, const PassInfo *pRet)
faluco@739
   439
{
faluco@739
   440
	if (pRet->type == PassType_Float)
faluco@739
   441
	{
faluco@739
   442
		switch (pRet->size)
faluco@739
   443
		{
faluco@739
   444
		case 4:
faluco@739
   445
			{
faluco@739
   446
				//fstp DWORD PTR [edi]
faluco@739
   447
				IA32_Fstp_Mem32(jit, REG_EDI, REG_NOIDX, NOSCALE);
faluco@739
   448
				break;
faluco@739
   449
			}
faluco@739
   450
		case 8:
faluco@739
   451
			{
faluco@739
   452
				//fstp QWORD PTR [edi]
faluco@739
   453
				IA32_Fstp_Mem64(jit, REG_EDI, REG_NOIDX, NOSCALE);
faluco@739
   454
				break;
faluco@739
   455
			}
faluco@739
   456
		}
faluco@739
   457
		return;
faluco@739
   458
	}
faluco@739
   459
faluco@739
   460
	switch (pRet->size)
faluco@739
   461
	{
faluco@739
   462
	case 1:
faluco@739
   463
		{
faluco@739
   464
			//mov BYTE PTR [edi], al
faluco@739
   465
			IA32_Mov_Rm8_Reg8(jit, REG_EDI, REG_EAX, MOD_MEM_REG);
faluco@739
   466
			break;
faluco@739
   467
		}
faluco@739
   468
	case 2:
faluco@739
   469
		{
faluco@739
   470
			//mov WORD PTR [edi], ax
faluco@739
   471
			jit->write_ubyte(IA32_16BIT_PREFIX);
faluco@739
   472
			IA32_Mov_Rm_Reg(jit, REG_EDI, REG_EAX, MOD_MEM_REG);
faluco@739
   473
			break;
faluco@739
   474
		}
faluco@739
   475
	case 4:
faluco@739
   476
		{
faluco@739
   477
			//mov DWORD PTR [edi], eax
faluco@739
   478
			IA32_Mov_Rm_Reg(jit, REG_EDI, REG_EAX, MOD_MEM_REG);
faluco@739
   479
			break;
faluco@739
   480
		}
faluco@739
   481
	case 8:
faluco@739
   482
		{
faluco@739
   483
			//mov DWORD PTR [edi], eax
faluco@739
   484
			//mov DWORD PTR [edi+4], edx
faluco@739
   485
			IA32_Mov_Rm_Reg(jit, REG_EDI, REG_EAX, MOD_MEM_REG);
faluco@739
   486
			IA32_Mov_Rm_Reg_Disp8(jit, REG_EDI, REG_EDX, 4);
faluco@739
   487
			break;
faluco@739
   488
		}
faluco@739
   489
	}
faluco@739
   490
}
faluco@739
   491
faluco@739
   492
/******************************
faluco@739
   493
 * Assembly Compiler Function *
faluco@739
   494
 ******************************/
faluco@739
   495
faluco@739
   496
void JIT_Compile(CallWrapper *pWrapper, FuncAddrMethod method)
faluco@739
   497
{
faluco@739
   498
	JitWriter writer;
faluco@739
   499
	JitWriter *jit = &writer;
faluco@739
   500
faluco@739
   501
	jit_uint32_t CodeSize = 0;
faluco@739
   502
	bool Needs_Retbuf = false;
faluco@739
   503
	CallConvention Convention = pWrapper->GetCallConvention();
faluco@739
   504
	jit_uint32_t ParamCount = pWrapper->GetParamCount();
faluco@739
   505
	const PassInfo *pRet = pWrapper->GetReturnInfo();
ds@744
   506
	bool hasParams = (ParamCount || Convention == CallConv_ThisCall);
faluco@739
   507
faluco@739
   508
	writer.outbase = NULL;
faluco@739
   509
	writer.outptr = NULL;
faluco@739
   510
faluco@739
   511
jit_rewind:
faluco@739
   512
	/* Write function prologue */
ds@744
   513
	Write_Execution_Prologue(jit, (pRet) ? false : true, hasParams);
faluco@739
   514
faluco@739
   515
	/* Write parameter push code */
faluco@739
   516
	for (jit_int32_t i=ParamCount-1; i>=0; i--)
faluco@739
   517
	{
faluco@739
   518
		const PassEncode *pEnc = pWrapper->GetParamInfo(i);
faluco@739
   519
		switch (pEnc->info.type)
faluco@739
   520
		{
faluco@739
   521
		case PassType_Basic:
faluco@739
   522
			{
faluco@739
   523
				Write_PushPOD(jit, pEnc);
faluco@739
   524
				break;
faluco@739
   525
			}
faluco@739
   526
		case PassType_Float:
faluco@739
   527
			{
faluco@739
   528
				Write_PushFloat(jit, pEnc);
faluco@739
   529
				break;
faluco@739
   530
			}
faluco@739
   531
		case PassType_Object:
faluco@739
   532
			{
faluco@739
   533
				Write_PushObject(jit, pEnc);
faluco@739
   534
				break;
faluco@739
   535
			}
faluco@739
   536
		}
faluco@739
   537
	}
faluco@739
   538
faluco@739
   539
	/* Prepare the this ptr if applicable */
faluco@739
   540
	if (Convention == CallConv_ThisCall)
faluco@739
   541
	{
faluco@739
   542
		Write_PushThisPtr(jit);
faluco@739
   543
	}
faluco@739
   544
faluco@739
   545
	/* Skip the return buffer stuff if this is a void function */
faluco@739
   546
	if (!pRet)
faluco@739
   547
	{
faluco@739
   548
		goto skip_retbuffer;
faluco@739
   549
	}
faluco@739
   550
faluco@739
   551
	if ((pRet->type == PassType_Object) && (pRet->flags & PASSFLAG_BYVAL))
faluco@739
   552
	{
faluco@739
   553
#ifdef PLATFORM_POSIX
faluco@739
   554
		Needs_Retbuf = true;
faluco@739
   555
#elif defined PLATFORM_WINDOWS
faluco@739
   556
		if ((Convention == CallConv_ThisCall) ||
faluco@739
   557
			((Convention == CallConv_Cdecl) &&
faluco@739
   558
			((pRet->size > 8) || (pRet->flags & PASSFLAG_ODTOR|PASSFLAG_OCTOR|PASSFLAG_OASSIGNOP))))
faluco@739
   559
		{
faluco@739
   560
			Needs_Retbuf = true;
faluco@739
   561
		}
faluco@739
   562
#endif
faluco@739
   563
	}
faluco@739
   564
faluco@739
   565
	/* Prepare the return buffer in case we are returning objects by value. */
faluco@739
   566
	if (Needs_Retbuf)
faluco@739
   567
	{
faluco@739
   568
		Write_PushRetBuffer(jit);
faluco@739
   569
	}
faluco@739
   570
faluco@739
   571
skip_retbuffer:
faluco@739
   572
	/* Write the calling code */
faluco@739
   573
	Write_CallFunction(jit, method, pWrapper);
faluco@739
   574
faluco@739
   575
	/* Clean up the calling stack */
faluco@739
   576
#ifdef PLATFORM_WINDOWS
faluco@739
   577
	if ((ParamCount || Needs_Retbuf) && (Convention == CallConv_Cdecl))
faluco@739
   578
	{
faluco@739
   579
		/* Pop all parameters from the stack + hidden return pointer */
faluco@739
   580
		jit_uint32_t total = (Needs_Retbuf) ? g_StackUsage + sizeof(void *) : g_StackUsage;
faluco@739
   581
		Write_RectifyStack(jit, total);
faluco@739
   582
#elif defined PLATFORM_POSIX
faluco@739
   583
	if (ParamCount)
faluco@739
   584
	{
faluco@739
   585
		/* Pop all parameters from the stack */
faluco@739
   586
		Write_RectifyStack(jit, g_StackUsage);
faluco@739
   587
#endif
faluco@739
   588
	}
faluco@739
   589
faluco@739
   590
	/* Copy the return type to the return buffer if the function is not void */
faluco@739
   591
	if (pRet && !Needs_Retbuf)
faluco@739
   592
	{
faluco@739
   593
		Write_MovRet2Buf(jit, pRet);
faluco@739
   594
	}
faluco@739
   595
faluco@739
   596
	/* Write Function Epilogue */
ds@744
   597
	Write_Function_Epilogue(jit, (pRet) ? false : true, hasParams);
faluco@739
   598
faluco@739
   599
	if (writer.outbase == NULL)
faluco@739
   600
	{
faluco@739
   601
		CodeSize = writer.get_outputpos();
faluco@739
   602
		writer.outbase = (jitcode_t)g_SPEngine->ExecAlloc(CodeSize);
faluco@739
   603
		writer.outptr = writer.outbase;
faluco@739
   604
		pWrapper->m_Addrs[ADDR_CODEBASE] = writer.outbase;
faluco@739
   605
		g_StackUsage = 0;
faluco@739
   606
		g_RegDecoder = 0;
faluco@739
   607
		Needs_Retbuf = false;
faluco@739
   608
		goto jit_rewind;
faluco@739
   609
	}
faluco@739
   610
}