mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2025-06-07 08:14:48 +00:00
1344 lines
37 KiB
Plaintext
Executable File
1344 lines
37 KiB
Plaintext
Executable File
I64 OptPass789A(CCompCtrl *cc, COptReg *reg_offsets, U8 *buf, CDebugInfo **_debug)
|
|
{/*
|
|
cc->pass == 7 is first time
|
|
cc->pass == 8 is second time
|
|
cc->pass == 9 is third time
|
|
cc->pass == 9 is fourth time and repeated until size stops shrinking
|
|
size is now known
|
|
cc->pass == 10 is final pass, code is placed into buf.
|
|
*/
|
|
CIntermediateCode *tmpi, *tmpi_next;
|
|
I64 i, count,num_lines = cc->max_line + 1 - cc->min_line, rip = 0,rip2;
|
|
U8 *ptr, saved_arg1_arg2_r[3 * sizeof(CICArg)];
|
|
CCodeMisc *lb;
|
|
CAOT *tmpaot;
|
|
CAOTAbsAddr *tmpa;
|
|
CAOTImportExport *tmpie;
|
|
CAOTHeapGlobal *tmphg;
|
|
CAOTHeapGlobalRef *tmphgr;
|
|
CDebugInfo *debug_info;
|
|
CAOTCtrl *aotc = cc->aotc;
|
|
Bool short_jmp;
|
|
CHashClass *tmpc;
|
|
CHashFun *tmpf;
|
|
CHashGlobalVar *tmpg;
|
|
CExternUsage *tmpeu;
|
|
|
|
if (_debug)
|
|
{
|
|
*_debug = debug_info = CAlloc(offset(CDebugInfo.body) + sizeof(U32) * (num_lines + 1));
|
|
debug_info->min_line = cc->min_line;
|
|
debug_info->max_line = cc->max_line;
|
|
if (cc->flags & CCF_AOT_COMPILE)
|
|
debug_info->body[0] = aotc->rip;
|
|
else
|
|
debug_info->body[0] = buf;
|
|
}
|
|
else
|
|
debug_info = NULL;
|
|
|
|
if (Bt(&cc->flags, CCf_PASS_TRACE_PRESENT) && Bt(&cc->saved_pass_trace, cc->pass))
|
|
"$$BK,1$$$$LTRED$$$$IV,1$$This code gets merged together and patched.\n"
|
|
"$$FG$$$$IV,0$$$$BK,0$$";
|
|
|
|
cc->last_float_op_ic = NULL;
|
|
tmpi = &cc->coc.coc_head;
|
|
tmpi->ic_last_start = -1;
|
|
tmpi->ic_count = 0;
|
|
tmpi = tmpi->next;
|
|
while (tmpi->ic_code)
|
|
{
|
|
tmpi_next = tmpi->next;
|
|
if (tmpi->ic_flags & ICF_PASS_TRACE && Bt(&cc->saved_pass_trace, cc->pass))
|
|
ICPut(cc, tmpi);
|
|
rip2 = rip;
|
|
if (cc->flags & CCF_AOT_COMPILE)
|
|
rip2 += aotc->rip;
|
|
else
|
|
rip2 += buf;
|
|
cc->cur_ic_float_op_num = 0;
|
|
if (!(tmpi->ic_flags & ICF_CODE_FINAL))
|
|
{
|
|
tmpi->ic_flags = tmpi->ic_flags & ~(ICF_PREV_DELETED | ICF_DONT_RESTORE) | ICF_CODE_FINAL;
|
|
if (cc->pass == 7)
|
|
cc->dont_push_float = Btr(&tmpi->ic_flags, ICf_DONT_PUSH_FLOAT0);
|
|
MemCopy(saved_arg1_arg2_r, &tmpi->arg1, 3 * sizeof(CICArg));
|
|
tmpi->ic_count = 0;
|
|
tmpi->ic_last_start = -1;
|
|
if (tmpi->arg2.type.mode)
|
|
{
|
|
if (tmpi->ic_flags & ICF_ARG2_TO_F64)
|
|
{
|
|
ICFConvert(cc, tmpi, REG_RAX, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, FALSE, CN_A2, rip2);
|
|
tmpi->arg2.type = MDF_REG + RT_I64;
|
|
tmpi->arg2.reg = REG_RAX;
|
|
tmpi->arg2.disp = 0;
|
|
}
|
|
else if (tmpi->ic_flags & ICF_ARG2_TO_INT)
|
|
{
|
|
ICFConvert(cc, tmpi, REG_RAX, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, TRUE, CN_A2, rip2);
|
|
tmpi->arg2.type = MDF_REG + RT_I64;
|
|
tmpi->arg2.reg = REG_RAX;
|
|
tmpi->arg2.disp = 0;
|
|
}
|
|
}
|
|
if (tmpi->arg1.type.mode)
|
|
{
|
|
if (tmpi->ic_flags & ICF_ARG1_TO_F64)
|
|
{
|
|
ICFConvert(cc, tmpi, REG_RDX, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, FALSE, CN_A1, rip2);
|
|
tmpi->arg1.type = MDF_REG + RT_I64;
|
|
tmpi->arg1.reg = REG_RDX;
|
|
tmpi->arg1.disp = 0;
|
|
}
|
|
else if (tmpi->ic_flags & ICF_ARG1_TO_INT)
|
|
{
|
|
ICFConvert(cc,tmpi, REG_RDX, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, TRUE, CN_A1, rip2);
|
|
tmpi->arg1.type = MDF_REG+RT_I64;
|
|
tmpi->arg1.reg = REG_RDX;
|
|
tmpi->arg1.disp = 0;
|
|
}
|
|
}
|
|
|
|
switch [tmpi->ic_code]
|
|
{
|
|
start:
|
|
start:
|
|
case IC_ABS_ADDR:
|
|
ICU16(tmpi, 0xB848); // MOV U64 RAX, U64
|
|
ICU64(tmpi, tmpi->ic_data);
|
|
if (buf && cc->flags & CCF_AOT_COMPILE && !(cc->flags & (CCF_NO_ABSS | CCF_ASM_EXPRESSIONS)))
|
|
{
|
|
tmpa = CAlloc(sizeof(CAOTAbsAddr));
|
|
tmpa->next = aotc->abss;
|
|
tmpa->type = AAT_ADD_U64;
|
|
aotc->abss = tmpa;
|
|
tmpa->rip = rip2 + tmpi->ic_count - 8;
|
|
}
|
|
break;
|
|
|
|
case IC_HEAP_GLOBAL:
|
|
ICU16(tmpi, 0xB848); //
|
|
ICU64(tmpi, 0); // MOV U64 RAX, U64 0x0
|
|
tmphg = tmpi->ic_data;
|
|
if (buf && cc->flags & CCF_AOT_COMPILE && !(cc->flags & (CCF_NO_ABSS | CCF_ASM_EXPRESSIONS)))
|
|
{//TODO:is this necessary--flags?
|
|
tmphgr = CAlloc(sizeof(CAOTHeapGlobalRef));
|
|
tmphgr->next = tmphg->references;
|
|
tmphg->references = tmphgr;
|
|
tmphgr->rip = rip2 + tmpi->ic_count - 8;
|
|
}
|
|
break;
|
|
|
|
case IC_ADDR_IMPORT:
|
|
ICU8(tmpi, 0xB8);
|
|
ICU32(tmpi, 0);
|
|
if (buf && !(cc->flags & CCF_NO_ABSS))
|
|
{
|
|
tmpg = tmpi->ic_data;
|
|
tmpie = CAlloc(sizeof(CAOTImportExport));
|
|
tmpie->type = IET_IMM_U32;
|
|
tmpie->rip = rip2 + tmpi->ic_count - 4;
|
|
tmpie->next = tmpg->ie_list;
|
|
tmpg->ie_list = tmpie;
|
|
}
|
|
ICU24(tmpi, 0xC06348);
|
|
break;
|
|
|
|
case IC_RIP:
|
|
ICU16(tmpi, 0xB848); // MOV U64 RAX, U64
|
|
ICU64(tmpi, rip2 + tmpi->ic_count - 2);
|
|
if (cc->flags & CCF_AOT_COMPILE && buf &&!(cc->flags & CCF_NO_ABSS))
|
|
{
|
|
tmpa = CAlloc(sizeof(CAOTAbsAddr));
|
|
tmpa->next = aotc->abss;
|
|
tmpa->type = AAT_ADD_U64;
|
|
aotc->abss = tmpa;
|
|
tmpa->rip = rip2 + tmpi->ic_count - 8;
|
|
}
|
|
break;
|
|
end:
|
|
ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RAX, 0, rip2);
|
|
break;
|
|
|
|
case IC_BR_CARRY:
|
|
ICFlagBranch(tmpi, rip, 0x72820F, buf);
|
|
break;
|
|
|
|
case IC_BR_NOT_CARRY:
|
|
ICFlagBranch(tmpi, rip, 0x73830F, buf);
|
|
break;
|
|
|
|
case IC_BR_ZERO:
|
|
ICTestAndBranch(tmpi, rip, 0x74840F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_NOT_ZERO:
|
|
ICTestAndBranch(tmpi, rip, 0x75850F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_MM_ZERO:
|
|
ICPreIncDec(tmpi, SLASH_OP_DEC, rip2);
|
|
ICFlagBranch(tmpi, rip, 0x74840F, buf);
|
|
break;
|
|
|
|
case IC_BR_MM_NOT_ZERO:
|
|
ICPreIncDec(tmpi, SLASH_OP_DEC, rip2);
|
|
ICFlagBranch(tmpi, rip, 0x75850F, buf);
|
|
break;
|
|
|
|
case IC_BR_EQU_EQU:
|
|
ICCompAndBranch(tmpi, FALSE, rip, 0x74840F, 0x74840F, 0x74840F, 0x74840F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_EQU_EQU2:
|
|
ICCompAndBranch(tmpi, TRUE, rip, 0x74840F, 0x74840F, 0x74840F, 0x74840F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_NOT_EQU:
|
|
ICCompAndBranch(tmpi, FALSE, rip, 0x75850F, 0x75850F, 0x75850F, 0x75850F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_NOT_EQU2:
|
|
ICCompAndBranch(tmpi, TRUE, rip, 0x75850F, 0x75850F, 0x75850F, 0x75850F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_LESS:
|
|
if (tmpi->ic_flags & ICF_USE_F64)
|
|
ICFCmpAndBranch(cc, tmpi, rip, 0x72820F, 0x77870F, buf, rip2);
|
|
else
|
|
ICCompAndBranch(tmpi, FALSE, rip, 0x72820F, 0x7C8C0F, 0x77870F, 0x7F8F0F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_LESS2:
|
|
ICCompAndBranch(tmpi, TRUE, rip, 0x72820F, 0x7C8C0F, 0x77870F, 0x7F8F0F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_GREATER_EQU:
|
|
if (tmpi->ic_flags & ICF_USE_F64)
|
|
ICFCmpAndBranch(cc, tmpi, rip, 0x73830F, 0x76860F, buf, rip2);
|
|
else
|
|
ICCompAndBranch(tmpi, FALSE, rip, 0x73830F, 0x7D8D0F, 0x76860F, 0x7E8E0F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_GREATER_EQU2:
|
|
ICCompAndBranch(tmpi, TRUE, rip, 0x73830F, 0x7D8D0F, 0x76860F, 0x7E8E0F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_GREATER:
|
|
if (tmpi->ic_flags & ICF_USE_F64)
|
|
ICFCmpAndBranch(cc, tmpi, rip, 0x77870F, 0x72820F, buf, rip2);
|
|
else
|
|
ICCompAndBranch(tmpi, FALSE, rip, 0x77870F, 0x7F8F0F, 0x72820F, 0x7C8C0F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_GREATER2:
|
|
ICCompAndBranch(tmpi, TRUE, rip, 0x77870F, 0x7F8F0F, 0x72820F, 0x7C8C0F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_LESS_EQU:
|
|
if (tmpi->ic_flags & ICF_USE_F64)
|
|
ICFCmpAndBranch(cc, tmpi, rip, 0x76860F, 0x73830F, buf, rip2);
|
|
else
|
|
ICCompAndBranch(tmpi, FALSE, rip, 0x76860F, 0x7E8E0F, 0x73830F, 0x7D8D0F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_LESS_EQU2:
|
|
ICCompAndBranch(tmpi, TRUE, rip, 0x76860F, 0x7E8E0F, 0x73830F, 0x7D8D0F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_BT:
|
|
ICBrBitOps(tmpi, rip, 0xA30F, 0x20BA0F, 0x72820F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_BTS:
|
|
ICBrBitOps(tmpi, rip, 0xAB0F, 0x28BA0F, 0x72820F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_BTR:
|
|
ICBrBitOps(tmpi, rip, 0xB30F, 0x30BA0F, 0x72820F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_BTC:
|
|
ICBrBitOps(tmpi, rip, 0xBB0F, 0x38BA0F, 0x72820F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_NOT_BT:
|
|
ICBrBitOps(tmpi, rip, 0xA30F, 0x20BA0F, 0x73830F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_NOT_BTS:
|
|
ICBrBitOps(tmpi, rip, 0xAB0F, 0x28BA0F, 0x73830F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_NOT_BTR:
|
|
ICBrBitOps(tmpi, rip, 0xB30F, 0x30BA0F, 0x73830F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_NOT_BTC:
|
|
ICBrBitOps(tmpi, rip, 0xBB0F, 0x38BA0F, 0x73830F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_AND_ZERO:
|
|
ICAndBranch(tmpi, rip, 0x74840F, buf, rip2);
|
|
break;
|
|
|
|
case IC_BR_AND_NOT_ZERO:
|
|
ICAndBranch(tmpi, rip, 0x75850F, buf, rip2);
|
|
break;
|
|
|
|
case IC_SUB_CALL:
|
|
lb = OptLabelFwd(tmpi->ic_data);
|
|
ICU8(tmpi, 0xE8);
|
|
ICU32(tmpi, lb->addr - (rip + 5));
|
|
break;
|
|
|
|
case IC_JMP:
|
|
lb = OptLabelFwd(tmpi->ic_data);
|
|
short_jmp = ToBool(tmpi->ic_flags & ICF_SHORT_JMP);
|
|
if (!buf && lb->addr != INVALID_PTR && I8_MIN + 5 < lb->addr - rip < I8_MAX - 5)
|
|
short_jmp = TRUE;
|
|
if (short_jmp)
|
|
{
|
|
tmpi->ic_flags |= ICF_SHORT_JMP;
|
|
i = lb->addr - (rip + 2);
|
|
if (buf || i)
|
|
ICU16(tmpi, i << 8 + 0xEB);
|
|
else
|
|
tmpi->ic_code = IC_NOP1;
|
|
}
|
|
else
|
|
{
|
|
i = lb->addr - (rip + 5);
|
|
ICU8(tmpi, 0xE9);
|
|
ICU32(tmpi, i);
|
|
}
|
|
break;
|
|
|
|
case IC_LABEL:
|
|
lb = tmpi->ic_data;
|
|
lb->addr = rip;
|
|
if (lb->flags & CMF_POP_CMP)
|
|
{
|
|
ICAddRSP(tmpi, -8, FALSE);
|
|
ICAddRSP(tmpi, 8, FALSE);
|
|
}
|
|
if (lb->type == CMT_ASM_LABEL)
|
|
lb->addr += lb->rip;
|
|
break;
|
|
|
|
case IC_STR_CONST:
|
|
case IC_GET_LABEL:
|
|
lb = tmpi->ic_data;
|
|
if (cc->flags & CCF_AOT_COMPILE)
|
|
i = lb->addr + aotc->rip;
|
|
else
|
|
i = lb->addr + buf;
|
|
ICLea(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
MDF_RIP_DISP32 + RT_PTR, 0, i, cc, buf, rip2);
|
|
break;
|
|
|
|
case IC_ASM:
|
|
tmpaot = tmpi->ic_data;
|
|
tmpi->ic_count += tmpaot->aot_U8s;
|
|
if (buf)
|
|
{
|
|
MemCopy(buf + rip,tmpaot->buf, tmpaot->aot_U8s);
|
|
Free(tmpaot->buf);
|
|
tmpaot->buf = buf;
|
|
tmpaot->rip = rip;
|
|
tmpaot->rip2 = rip2;
|
|
if (cc->flags & CCF_AOT_COMPILE)
|
|
CompFixUpAOTAsm(cc, tmpaot);
|
|
else
|
|
CompFixUpJITAsm(cc, tmpaot);
|
|
count = tmpi->ic_count;
|
|
goto op789A_skip_copy;
|
|
}
|
|
break;
|
|
|
|
case IC_CALL:
|
|
i = tmpi->ic_data - (rip2 + 5);
|
|
if (!(I32_MIN <= i <= I32_MAX) && !(cc->flags & CCF_AOT_COMPILE))
|
|
{
|
|
ICU16(tmpi, 0xBB48); // MOV U64 RBX, U64
|
|
ICU64(tmpi, tmpi->ic_data);
|
|
ICU16(tmpi, 0xD3FF); // CALL U64 RBX
|
|
}
|
|
else
|
|
{
|
|
ICU8(tmpi, 0xE8); // CALL
|
|
ICU32(tmpi, i);
|
|
}
|
|
break;
|
|
|
|
case IC_CALL_EXTERN: //Only for static modules
|
|
ICU8(tmpi, 0xE8); //
|
|
ICU32(tmpi, 0); // CALL I32 0x5
|
|
if (buf)
|
|
{
|
|
tmpf = tmpi->ic_data;
|
|
tmpeu = CAlloc(sizeof(CExternUsage));
|
|
tmpeu->next = tmpf->ext_list;
|
|
tmpf->ext_list = tmpeu;
|
|
tmpeu->rip = rip2 + 1;
|
|
}
|
|
break;
|
|
|
|
case IC_CALL_INDIRECT2:
|
|
ICU16(tmpi, 0xBB48); // MOV U64 RBX, U64
|
|
if (cc->flags & CCF_AOT_COMPILE)
|
|
i = rip2 + tmpi->ic_count;
|
|
ICU64(tmpi, tmpi->ic_data);
|
|
ICU16(tmpi, 0x13FF); // CALL U64 [RBX]
|
|
if (buf && cc->flags & CCF_AOT_COMPILE && !(cc->flags & CCF_NO_ABSS))
|
|
{
|
|
tmpa = CAlloc(sizeof(CAOTAbsAddr));
|
|
tmpa->next = aotc->abss;
|
|
tmpa->type = AAT_ADD_U64;
|
|
aotc->abss = tmpa;
|
|
tmpa->rip = i;
|
|
}
|
|
break;
|
|
|
|
case IC_CALL_IMPORT:
|
|
if (OptionGet(OPTf_USE_IMM64))
|
|
{
|
|
ICU16(tmpi, 0xBB48); //
|
|
ICU64(tmpi, 0); // MOV U64 RBX, U64 0x0
|
|
if (buf)
|
|
{
|
|
tmpf = tmpi->ic_data;
|
|
tmpie = CAlloc(sizeof(CAOTImportExport));
|
|
tmpie->type = IET_IMM_I64;
|
|
tmpie->rip = rip2+tmpi->ic_count - 8;
|
|
tmpie->next = tmpf->ie_list;
|
|
tmpf->ie_list = tmpie;
|
|
}
|
|
ICU16(tmpi, 0xD3FF); // CALL U64 RBX
|
|
}
|
|
else
|
|
{
|
|
ICU8(tmpi, 0xE8); //
|
|
ICU32(tmpi, 0); // CALL I32 0x5
|
|
if (buf)
|
|
{
|
|
tmpf = tmpi->ic_data;
|
|
tmpie = CAlloc(sizeof(CAOTImportExport));
|
|
tmpie->type = IET_REL_I32;
|
|
tmpie->rip = rip2 + tmpi->ic_count - 4;
|
|
tmpie->next = tmpf->ie_list;
|
|
tmpf->ie_list = tmpie;
|
|
}
|
|
}
|
|
break;
|
|
end:
|
|
tmpi->ic_flags &= ~ICF_CODE_FINAL;
|
|
break;
|
|
|
|
case IC_LEAVE:
|
|
if (cc->htc.fun)
|
|
{
|
|
if (Bt(&cc->htc.fun->flags,Ff_INTERRUPT))
|
|
ICPopRegs(tmpi, REGG_CLOBBERED | cc->htc.fun->used_reg_mask &
|
|
(REGG_LOCAL_VARS | REGG_LOCAL_NON_PTR_VARS | REGG_STACK_TMP));
|
|
else
|
|
ICPopRegs(tmpi, cc->htc.fun->used_reg_mask & (REGG_LOCAL_VARS | REGG_LOCAL_NON_PTR_VARS));
|
|
}
|
|
if (tmpi->ic_data <= I16_MAX)
|
|
{
|
|
if (tmpi->ic_data)
|
|
ICU8(tmpi, 0xC9); //LEAVE
|
|
else
|
|
ICU8(tmpi, 0x5D); //POP RBP
|
|
}
|
|
else
|
|
{
|
|
ICAddRSP(tmpi, tmpi->ic_data);
|
|
ICU8(tmpi, 0x5D); //POP RBP
|
|
}
|
|
if (cc->htc.fun && Bt(&cc->htc.fun->flags, Ff_INTERRUPT))
|
|
{
|
|
if (Bt(&cc->htc.fun->flags, Ff_HASERRCODE))
|
|
ICAddRSP(tmpi, 8);
|
|
ICU16(tmpi, 0xCF48); // IRET
|
|
}
|
|
else if (cc->htc.fun && cc->htc.fun->arg_count &&
|
|
(Bt(&cc->htc.fun->flags, Ff_RET1) || Bt(&cc->htc.fun->flags, Ff_ARGPOP)) &&
|
|
!Bt(&cc->htc.fun->flags, Ff_NOARGPOP))
|
|
{
|
|
ICU8(tmpi, 0xC2); // RET1 I16
|
|
ICU16(tmpi, cc->htc.fun->arg_count << 3);
|
|
}
|
|
else
|
|
ICU8(tmpi, 0xC3); // RET
|
|
break;
|
|
|
|
case IC_RET:
|
|
ICU8(tmpi, 0xC3); // RET
|
|
break;
|
|
|
|
case IC_FS:
|
|
ICZero(tmpi, REG_RAX);
|
|
ICU32(tmpi, 0x8B4864); // MOV U64 RBP, U64 FS:RSP
|
|
break;
|
|
|
|
case IC_GS:
|
|
ICZero(tmpi, REG_RAX);
|
|
ICU32(tmpi, 0x8B4865); // MOV U64 RBP, U64 GS:RSP
|
|
break;
|
|
|
|
case IC_MOV_FS:
|
|
ICZero(tmpi, REG_RAX);
|
|
ICU8(tmpi, 0x64);
|
|
//It's ugly to use ic_class here
|
|
ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_DISP + CompRawType(tmpi->ic_class),
|
|
REG_RAX, tmpi->ic_data, rip2);
|
|
break;
|
|
|
|
case IC_MOV_GS:
|
|
ICZero(tmpi, REG_RAX);
|
|
ICU8(tmpi, 0x65);
|
|
//It's ugly to use ic_class here
|
|
ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_DISP + CompRawType(tmpi->ic_class),
|
|
REG_RAX, tmpi->ic_data, rip2);
|
|
break;
|
|
|
|
case IC_POSTFIX_TYPECAST:
|
|
ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
break;
|
|
|
|
case IC_COM:
|
|
ICUnaries(tmpi, SLASH_OP_NOT,rip2);
|
|
break;
|
|
|
|
case IC_NOT:
|
|
ICNot(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_UNARY_MINUS:
|
|
if (tmpi->res.type.raw_type == RT_F64)
|
|
ICFUnaryMinus(cc, tmpi, buf, rip2);
|
|
else
|
|
ICUnaries(tmpi, SLASH_OP_NEG, rip2);
|
|
break;
|
|
|
|
case IC_ADDR:
|
|
case IC_MOV:
|
|
ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
break;
|
|
|
|
case IC_DEREF:
|
|
ICDeref(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_DEREF_PP:
|
|
ICDerefPostIncDec(tmpi, SLASH_OP_INC, rip2);
|
|
break;
|
|
|
|
case IC_DEREF_MM:
|
|
ICDerefPostIncDec(tmpi, SLASH_OP_DEC, rip2);
|
|
break;
|
|
|
|
case IC__PP:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICPostIncDec(tmpi, SLASH_OP_INC, rip2);
|
|
else
|
|
ICFPostIncDec(cc, tmpi, CMP_TEMPLATE_INC, rip2);
|
|
break;
|
|
|
|
case IC__MM:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICPostIncDec(tmpi, SLASH_OP_DEC, rip2);
|
|
else
|
|
ICFPostIncDec(cc, tmpi, CMP_TEMPLATE_DEC, rip2);
|
|
break;
|
|
|
|
case IC_PP_:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICPreIncDec(tmpi, SLASH_OP_INC, rip2);
|
|
else
|
|
ICFPreIncDec(cc, tmpi, CMP_TEMPLATE_INC, rip2);
|
|
break;
|
|
|
|
case IC_MM_:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICPreIncDec(tmpi, SLASH_OP_DEC, rip2);
|
|
else
|
|
ICFPreIncDec(cc, tmpi, CMP_TEMPLATE_DEC, rip2);
|
|
break;
|
|
|
|
case IC_LEA:
|
|
ICLea(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, cc, buf, rip2);
|
|
break;
|
|
|
|
case IC_POWER:
|
|
ICFPow(cc, tmpi, buf, rip2);
|
|
break;
|
|
|
|
case IC_SHL:
|
|
ICShift(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp,
|
|
tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp,
|
|
0xE0D1E0D3E0C1, 0xE0D1E0D3E0C1, rip2);
|
|
break;
|
|
|
|
case IC_SHR:
|
|
ICShift(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp,
|
|
tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp,
|
|
0xE8D1E8D3E8C1, 0xF8D1F8D3F8C1, rip2);
|
|
break;
|
|
|
|
case IC_MUL:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICMul(tmpi, rip2);
|
|
else
|
|
ICFMul(cc, tmpi, buf, rip2);
|
|
break;
|
|
|
|
case IC_DIV:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICDiv(tmpi, rip2);
|
|
else
|
|
ICFDiv(cc, tmpi, buf, rip2);
|
|
break;
|
|
|
|
case IC_MOD:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICMod(tmpi, rip2);
|
|
else
|
|
ICFMod(cc, tmpi, rip2);
|
|
break;
|
|
|
|
case IC_AND:
|
|
ICAddEct(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp,
|
|
tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, 0x23, rip2);
|
|
break;
|
|
|
|
case IC_OR:
|
|
ICAddEct(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp,
|
|
tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, 0x0B, rip2);
|
|
break;
|
|
|
|
case IC_XOR:
|
|
ICAddEct(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp,
|
|
tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, 0x33, rip2);
|
|
break;
|
|
|
|
case IC_ADD:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICAddEct(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp,
|
|
tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, 0x03, rip2);
|
|
else
|
|
ICFAdd(cc, tmpi, buf, rip2);
|
|
break;
|
|
|
|
case IC_SUB:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICSub(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp,
|
|
tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip2);
|
|
else
|
|
ICFSub(cc, tmpi, buf, rip2);
|
|
break;
|
|
|
|
case IC_EQU_EQU:
|
|
ICComp(tmpi, 0x75, 0x75, rip2);
|
|
break;
|
|
|
|
case IC_NOT_EQU:
|
|
ICComp(tmpi, 0x74, 0x74, rip2);
|
|
break;
|
|
|
|
case IC_LESS:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICComp(tmpi, 0x73, 0x7D, rip2);
|
|
else
|
|
ICFCmp(cc, tmpi, CMP_TEMPLATE_LESS, rip2);
|
|
break;
|
|
|
|
case IC_GREATER_EQU:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICComp(tmpi, 0x72, 0x7C, rip2);
|
|
else
|
|
ICFCmp(cc, tmpi, CMP_TEMPLATE_GREATER_EQU, rip2);
|
|
break;
|
|
|
|
case IC_GREATER:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICComp(tmpi, 0x76, 0x7E, rip2);
|
|
else
|
|
ICFCmp(cc, tmpi, CMP_TEMPLATE_GREATER, rip2);
|
|
break;
|
|
|
|
case IC_LESS_EQU:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICComp(tmpi, 0x77, 0x7F, rip2);
|
|
else
|
|
ICFCmp(cc, tmpi, CMP_TEMPLATE_LESS_EQU, rip2);
|
|
break;
|
|
|
|
case IC_AND_AND:
|
|
ICAndAnd(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_OR_OR:
|
|
ICOrOr(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_XOR_XOR:
|
|
ICXorXor(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_ASSIGN:
|
|
ICAssign(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_ASSIGN_PP:
|
|
ICAssignPostIncDec(tmpi, SLASH_OP_INC, rip2);
|
|
break;
|
|
|
|
case IC_ASSIGN_MM:
|
|
ICAssignPostIncDec(tmpi, SLASH_OP_DEC, rip2);
|
|
break;
|
|
|
|
case IC_SHL_EQU:
|
|
ICShiftEqu(tmpi, tmpi->arg1_type_pointed_to,
|
|
tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp,
|
|
tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp,
|
|
0xE0D1E0D3E0C1, 0xE0D1E0D3E0C1, rip2);
|
|
break;
|
|
|
|
case IC_SHR_EQU:
|
|
ICShiftEqu(tmpi, tmpi->arg1_type_pointed_to,
|
|
tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp,
|
|
tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp,
|
|
0xE8D1E8D3E8C1, 0xF8D1F8D3F8C1, rip2);
|
|
break;
|
|
|
|
case IC_MUL_EQU:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICMulEqu(tmpi, rip2);
|
|
else
|
|
ICFOpEqu(cc, tmpi, SLASH_OP_FMUL, buf, rip2);
|
|
break;
|
|
|
|
case IC_DIV_EQU:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICDivEqu(tmpi, FALSE, rip2);
|
|
else
|
|
ICFOpEqu(cc, tmpi, SLASH_OP_FDIV, buf, rip2);
|
|
break;
|
|
|
|
case IC_MOD_EQU:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICDivEqu(tmpi, TRUE, rip2);
|
|
else
|
|
ICFModEqu(cc, tmpi, rip2);
|
|
break;
|
|
|
|
case IC_AND_EQU:
|
|
ICAndEqu(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_OR_EQU:
|
|
ICOrEqu(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_XOR_EQU:
|
|
ICXorEqu(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_ADD_EQU:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICAddSubEctEqu(tmpi, tmpi->arg1_type_pointed_to,
|
|
tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp,
|
|
tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp,
|
|
0x010000000003, rip2);
|
|
else
|
|
ICFOpEqu(cc, tmpi, SLASH_OP_FADD, buf, rip2);
|
|
break;
|
|
|
|
case IC_SUB_EQU:
|
|
if (tmpi->ic_flags & ICF_USE_INT)
|
|
ICAddSubEctEqu(tmpi, tmpi->arg1_type_pointed_to,
|
|
tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp,
|
|
tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp,
|
|
0x29000000052B, rip2);
|
|
else
|
|
ICFOpEqu(cc, tmpi, SLASH_OP_FSUB, buf, rip2);
|
|
break;
|
|
|
|
case IC_SHL_CONST:
|
|
ICShift(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp,
|
|
MDF_IMM + RT_I64, 0, tmpi->ic_data, 0xE0D1E0D3E0C1, 0xE0D1E0D3E0C1, rip2);
|
|
break;
|
|
|
|
case IC_SHR_CONST:
|
|
ICShift(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp,
|
|
MDF_IMM + RT_I64, 0, tmpi->ic_data, 0xE8D1E8D3E8C1, 0xF8D1F8D3F8C1, rip2);
|
|
break;
|
|
|
|
case IC_ADD_CONST:
|
|
ICAddSubEctImm(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, tmpi->ic_data, 0x0003, rip2);
|
|
break;
|
|
|
|
case IC_SUB_CONST:
|
|
ICAddSubEctImm(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp,
|
|
tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, tmpi->ic_data, 0x052B, rip2);
|
|
break;
|
|
|
|
case IC_ENTER:
|
|
ICU32(tmpi, 0xEC8B4855); // PUSH U64 RBP // MOV U64 RBP, U64 RSP
|
|
if (tmpi->ic_data)
|
|
ICAddRSP(tmpi, -tmpi->ic_data, FALSE);
|
|
if (cc->htc.fun)
|
|
{
|
|
if (Bt(&cc->htc.fun->flags, Ff_INTERRUPT))
|
|
ICPushRegs(tmpi, REGG_CLOBBERED | cc->htc.fun->used_reg_mask &
|
|
(REGG_LOCAL_VARS | REGG_LOCAL_NON_PTR_VARS | REGG_STACK_TMP));
|
|
else
|
|
{
|
|
if (sys_var_init_flag && i)
|
|
ICLocalVarInit(tmpi);
|
|
ICPushRegs(tmpi, cc->htc.fun->used_reg_mask & (REGG_LOCAL_VARS | REGG_LOCAL_NON_PTR_VARS));
|
|
}
|
|
for (i = 0; i < REG_REGS_NUM; i++)
|
|
if (reg_offsets[i] > 0 && reg_offsets[i].offset != I64_MAX)
|
|
{
|
|
tmpc = OptClassFwd(reg_offsets[i].m->member_class);
|
|
ICMov(tmpi, MDF_REG + RT_I64, i, 0, MDF_DISP + tmpc->raw_type,
|
|
REG_RBP, reg_offsets[i].offset, rip2);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IC_ADD_RSP:
|
|
ICAddRSP(tmpi, tmpi->ic_data);
|
|
break;
|
|
|
|
case IC_CALL_INDIRECT:
|
|
if (I8_MIN <= tmpi->ic_data <= I8_MAX)
|
|
{
|
|
ICU24(tmpi, 0x2454FF); // CALL disp[RSP]
|
|
ICU8(tmpi, tmpi->ic_data);
|
|
}
|
|
else
|
|
{
|
|
ICU24(tmpi, 0x2494FF); // CALL disp[RSP]
|
|
ICU32(tmpi, tmpi->ic_data);
|
|
}
|
|
break;
|
|
|
|
case IC_PUSH:
|
|
ICPush(tmpi, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
break;
|
|
|
|
case IC_POP:
|
|
ICU8(tmpi, 0x58); // POP U64 RAX
|
|
break;
|
|
|
|
case IC_INVLPG:
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICU24(tmpi, 0x38010F); // INVLPG U8 [RAX]
|
|
break;
|
|
|
|
case IC_CLFLUSH:
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICU24(tmpi, 0x38AE0F); // CLFLUSH U8 [RAX]
|
|
break;
|
|
|
|
case IC_RFLAGS_GET:
|
|
ICU8(tmpi, 0x9C);
|
|
ICPop(tmpi, MDF_REG + RT_I64, REG_RAX, 0, rip2);
|
|
break;
|
|
|
|
case IC_CARRY:
|
|
ICU24(tmpi, 0xC0920F); // SETB U8 AL
|
|
ICU24(tmpi, 0x01E083); // AND U32 EAX, I8 0x01
|
|
break;
|
|
|
|
case IC_RDTSC:
|
|
ICCopyTemplate(cc, tmpi, CMP_TEMPLATE_RDTSC, TRUE, FALSE, FALSE, CN_INST);
|
|
break;
|
|
|
|
case IC_RFLAGS_SET:
|
|
ICPush(tmpi, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICU8(tmpi, 0x9D);
|
|
break;
|
|
|
|
case IC_RBP_GET:
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, MDF_REG + RT_I64, REG_RBP, 0, rip2);
|
|
break;
|
|
|
|
case IC_RBP_SET:
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RBP, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
break;
|
|
|
|
case IC_RSP_GET:
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, MDF_REG + RT_I64, REG_RSP, 0, rip2);
|
|
break;
|
|
|
|
case IC_RSP_SET:
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RSP, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
break;
|
|
|
|
case IC_RETURN_VAL:
|
|
case IC_RAX_SET:
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
break;
|
|
|
|
case IC_RETURN_VAL2:
|
|
case IC_RAX_GET:
|
|
break;
|
|
|
|
case IC_BT:
|
|
ICBitOps(tmpi, &tmpi->arg1, &tmpi->arg2, tmpi->next, 0xA30F, 0x20BA0F, rip2);
|
|
break;
|
|
|
|
case IC_BTS:
|
|
case IC_LBTS:
|
|
ICBitOps(tmpi, &tmpi->arg1, &tmpi->arg2, tmpi->next, 0xAB0F, 0x28BA0F, rip2);
|
|
break;
|
|
|
|
case IC_BTR:
|
|
case IC_LBTR:
|
|
ICBitOps(tmpi, &tmpi->arg1, &tmpi->arg2, tmpi->next, 0xB30F, 0x30BA0F, rip2);
|
|
break;
|
|
|
|
case IC_BTC:
|
|
case IC_LBTC:
|
|
ICBitOps(tmpi, &tmpi->arg1, &tmpi->arg2, tmpi->next, 0xBB0F, 0x38BA0F, rip2);
|
|
break;
|
|
|
|
case IC_BSF:
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICU32(tmpi, 0xC0BC0F48); // BSF U64 RAX, U64 RAX
|
|
ICU16(tmpi, 0x0375); // JNE I8 0x9
|
|
ICU24(tmpi, 0xD0F748); // NOT U64 RAX
|
|
break;
|
|
|
|
case IC_BSR:
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICU32(tmpi, 0xC0BD0F48); // BSR U64 RAX, U64 RAX
|
|
ICU16(tmpi, 0x0375); // JNE I8 0x9
|
|
ICU24(tmpi, 0xD0F748); // NOT U64 RAX
|
|
break;
|
|
|
|
case IC_POPCNT:
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICU16(tmpi, 0xF348); //
|
|
ICU32(tmpi, 0xC0B80F48); // POPCNT U64 RAX, U64 RAX
|
|
break;
|
|
|
|
case IC_SIGN_I64:
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICCopyTemplate(cc, tmpi, CMP_TEMPLATE_SIGN_I64, TRUE, FALSE, FALSE, CN_INST);
|
|
break;
|
|
|
|
case IC_TOUPPER:
|
|
ICToUpper(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_TO_I64:
|
|
ICToI64(cc, tmpi, rip2);
|
|
break;
|
|
|
|
case IC_TO_F64:
|
|
ICToF64(cc, tmpi, rip2);
|
|
break;
|
|
|
|
case IC_TO_BOOL:
|
|
ICToBool(cc, tmpi, rip2);
|
|
break;
|
|
|
|
case IC_SQR:
|
|
ICFTemplateFun(cc, tmpi, CMP_TEMPLATE_SQR, rip2);
|
|
break;
|
|
|
|
case IC_ABS:
|
|
ICFTemplateFun(cc, tmpi, CMP_TEMPLATE_ABS, rip2);
|
|
break;
|
|
|
|
case IC_SQRT:
|
|
ICFTemplateFun(cc, tmpi, CMP_TEMPLATE_SQRT, rip2);
|
|
break;
|
|
|
|
case IC_SIN:
|
|
ICFTemplateFun(cc, tmpi, CMP_TEMPLATE_SIN, rip2);
|
|
break;
|
|
|
|
case IC_COS:
|
|
ICFTemplateFun(cc, tmpi, CMP_TEMPLATE_COS, rip2);
|
|
break;
|
|
|
|
case IC_TAN:
|
|
ICFTemplateFun(cc, tmpi, CMP_TEMPLATE_TAN, rip2);
|
|
break;
|
|
|
|
case IC_ATAN:
|
|
ICFTemplateFun(cc, tmpi, CMP_TEMPLATE_ATAN, rip2);
|
|
break;
|
|
|
|
case IC_ABS_I64:
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICU24(tmpi, 0xC08548); // TEST U64 RAX, U64 RAX
|
|
ICU16(tmpi, 0x0379); // JNS I8 0x8
|
|
ICU24(tmpi, 0xD8F748); // NEG U64 RAX
|
|
break;
|
|
|
|
case IC_MIN_I64:
|
|
ICMinMax(tmpi, 0x4F, rip2);
|
|
break;
|
|
|
|
case IC_MAX_I64:
|
|
ICMinMax(tmpi, 0x4C, rip2);
|
|
break;
|
|
|
|
case IC_MIN_U64:
|
|
ICMinMax(tmpi, 0x47, rip2);
|
|
break;
|
|
|
|
case IC_MAX_U64:
|
|
ICMinMax(tmpi, 0x42, rip2);
|
|
break;
|
|
|
|
case IC_MOD_U64:
|
|
ICModU64(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_SQR_I64:
|
|
ICSqr(tmpi, SLASH_OP_IMUL, rip2);
|
|
break;
|
|
|
|
case IC_SQR_U64:
|
|
ICSqr(tmpi, SLASH_OP_MUL, rip2);
|
|
break;
|
|
|
|
case IC_SWAP_U8:
|
|
case IC_SWAP_U16:
|
|
case IC_SWAP_U32:
|
|
case IC_SWAP_I64:
|
|
ICSwap(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_QUEUE_INIT:
|
|
ICQueueInit(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_QUEUE_INSERT:
|
|
ICQueueInsert(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_QUEUE_INSERT_REV:
|
|
ICQueueInsertRev(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_QUEUE_REMOVE:
|
|
ICQueueRemove(tmpi, rip2);
|
|
break;
|
|
|
|
case IC_STRLEN:
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICCopyTemplate(cc, tmpi, CMP_TEMPLATE_STRLEN, TRUE, FALSE, FALSE, CN_INST);
|
|
break;
|
|
|
|
case IC_IN_U32:
|
|
if (tmpi->arg1.type & MDF_IMM)
|
|
{
|
|
ICU16(tmpi, 0xC033);
|
|
if (tmpi->arg1.disp <= U8_MAX)
|
|
ICU16(tmpi, 0xE5 + tmpi->arg1.disp << 8);
|
|
else
|
|
{
|
|
ICU32(tmpi, 0xBA00 + OC_OP_SIZE_PREFIX + tmpi->arg1.disp << 16);
|
|
ICU8(tmpi, 0xED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICU16(tmpi, 0xC033);
|
|
ICU8(tmpi, 0xED);
|
|
}
|
|
break;
|
|
|
|
case IC_IN_U16:
|
|
if (tmpi->arg1.type & MDF_IMM)
|
|
{
|
|
ICU16(tmpi, 0xC033);
|
|
if (tmpi->arg1.disp <= U8_MAX)
|
|
ICU24(tmpi, 0xE500 + OC_OP_SIZE_PREFIX + tmpi->arg1.disp << 16);
|
|
else
|
|
{
|
|
ICU32(tmpi, 0xBA00 + OC_OP_SIZE_PREFIX + tmpi->arg1.disp << 16);
|
|
ICU16(tmpi, 0xED00 + OC_OP_SIZE_PREFIX);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICU16(tmpi, 0xC033);
|
|
ICU16(tmpi, 0xED00 + OC_OP_SIZE_PREFIX);
|
|
}
|
|
break;
|
|
|
|
case IC_IN_U8:
|
|
if (tmpi->arg1.type & MDF_IMM)
|
|
{
|
|
ICU16(tmpi, 0xC033);
|
|
if (tmpi->arg1.disp <= U8_MAX)
|
|
ICU16(tmpi, 0xE4 + tmpi->arg1.disp << 8);
|
|
else
|
|
{
|
|
ICU32(tmpi, 0xBA00 + OC_OP_SIZE_PREFIX + tmpi->arg1.disp << 16);
|
|
ICU8(tmpi, 0xEC);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICU16(tmpi, 0xC033);
|
|
ICU8(tmpi, 0xEC);
|
|
}
|
|
break;
|
|
|
|
case IC_OUT_U32:
|
|
if (tmpi->arg2.type & MDF_IMM)
|
|
{
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
if (tmpi->arg2.disp <= U8_MAX)
|
|
ICU16(tmpi, 0xE7 + tmpi->arg2.disp << 8);
|
|
else
|
|
{
|
|
ICU32(tmpi, 0xBA00 + OC_OP_SIZE_PREFIX + tmpi->arg2.disp << 16);
|
|
ICU8(tmpi, 0xEF);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip2);
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICU8(tmpi, 0xEF);
|
|
}
|
|
break;
|
|
|
|
case IC_OUT_U16:
|
|
if (tmpi->arg2.type & MDF_IMM)
|
|
{
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
if (tmpi->arg2.disp <= U8_MAX)
|
|
ICU24(tmpi, 0xE700 + OC_OP_SIZE_PREFIX + tmpi->arg2.disp << 16);
|
|
else
|
|
{
|
|
ICU32(tmpi, 0xBA00 + OC_OP_SIZE_PREFIX + tmpi->arg2.disp << 16);
|
|
ICU16(tmpi, 0xEF00 + OC_OP_SIZE_PREFIX);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip2);
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICU16(tmpi, 0xEF00 + OC_OP_SIZE_PREFIX);
|
|
}
|
|
break;
|
|
|
|
case IC_OUT_U8:
|
|
if (tmpi->arg2.type & MDF_IMM)
|
|
{
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
if (tmpi->arg2.disp <= U8_MAX)
|
|
ICU16(tmpi, 0xE6 + tmpi->arg2.disp << 8);
|
|
else
|
|
{
|
|
ICU32(tmpi, 0xBA00 + OC_OP_SIZE_PREFIX + tmpi->arg2.disp << 16);
|
|
ICU8(tmpi, 0xEE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip2);
|
|
ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2);
|
|
ICU8(tmpi, 0xEE);
|
|
}
|
|
break;
|
|
|
|
case IC_NOBOUND_SWITCH:
|
|
ICSwitch(tmpi, rip, TRUE, cc, buf, rip2);
|
|
break;
|
|
|
|
case IC_SWITCH:
|
|
ICSwitch(tmpi, rip, FALSE, cc, buf, rip2);
|
|
break;
|
|
|
|
case IC_NOP1:
|
|
case IC_NOP2:
|
|
OptFree(tmpi);
|
|
goto op789A_next;
|
|
|
|
case IC_CALL_START:
|
|
case IC_PUSH_REGS:
|
|
ICPushRegs(tmpi, tmpi->ic_data);
|
|
break;
|
|
|
|
case IC_CALL_END:
|
|
ICPopRegs(tmpi, tmpi->ic_data);
|
|
if (tmpi->res.type.mode)
|
|
ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RAX, 0, rip2);
|
|
break;
|
|
|
|
case IC_POP_REGS:
|
|
ICPopRegs(tmpi, tmpi->ic_data);
|
|
break;
|
|
|
|
case IC_PUSH_CMP:
|
|
case IC_CALL_END2:
|
|
case IC_END:
|
|
case IC_ADD_RSP1:
|
|
break;
|
|
|
|
default:
|
|
"Pass:%d Missing IC handler\n", cc->pass;
|
|
ICPut(cc, tmpi);
|
|
LexExcept(cc, "Compiler Optimization Error at ");
|
|
}
|
|
if (tmpi->res.type.mode)
|
|
{
|
|
if (tmpi->ic_flags & ICF_RES_TO_F64)
|
|
{
|
|
if (tmpi->ic_code == IC_PUSH_CMP)
|
|
{
|
|
ICU24(tmpi, 0x242CDF); // FILD U64 [RSP]
|
|
ICU24(tmpi, 0x241CDD); // FSTP U64 [RSP]
|
|
}
|
|
else
|
|
{
|
|
ICFConvert(cc, tmpi, REG_RAX, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, FALSE, CN_RES, rip2);
|
|
if (!Bt(&tmpi->ic_flags, ICf_DONT_POP_FLOAT0 + cc->cur_ic_float_op_num - 1))
|
|
ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RAX, 0, rip2);
|
|
}
|
|
}
|
|
else if (tmpi->ic_flags & ICF_RES_TO_INT)
|
|
{
|
|
ICFConvert(cc, tmpi, REG_RAX, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, TRUE, CN_RES, rip2);
|
|
ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RAX, 0, rip2);
|
|
}
|
|
}
|
|
}
|
|
count = tmpi->ic_count;
|
|
if (tmpi->ic_flags & ICF_DEL_PREV_INS)
|
|
{
|
|
if (cc->pass > 8)
|
|
count = tmpi->ic_last_start;
|
|
tmpi->ic_flags &= ~ICF_DEL_PREV_INS;
|
|
}
|
|
if (count && buf)
|
|
MemCopy(buf + rip, tmpi->ic_body, count);
|
|
op789A_skip_copy:
|
|
if (debug_info && cc->min_line <= tmpi->ic_line <= cc->max_line)
|
|
{
|
|
i = tmpi->ic_line-cc->min_line;
|
|
if (!debug_info->body[i])
|
|
debug_info->body[i] = rip2;
|
|
}
|
|
if (tmpi->ic_flags & ICF_PASS_TRACE && Bt(&cc->saved_pass_trace, cc->pass) && count)
|
|
{
|
|
"$$RED$$";
|
|
if (buf)
|
|
Un(buf + rip,count, 64);
|
|
else
|
|
Un(tmpi->ic_body, count, 64);
|
|
"$$FG$$";
|
|
}
|
|
if (!(tmpi->ic_flags & (ICF_CODE_FINAL | ICF_DONT_RESTORE)))
|
|
MemCopy(&tmpi->arg1, saved_arg1_arg2_r, 3 * sizeof(CICArg));
|
|
rip += count;
|
|
if (tmpi->ic_count >= IC_BODY_SIZE && tmpi->ic_code != IC_ASM)
|
|
throw('Compiler');
|
|
op789A_next:
|
|
tmpi = tmpi_next;
|
|
}
|
|
|
|
lb = cc->coc.coc_next_misc;
|
|
while (lb != &cc->coc.coc_next_misc)
|
|
{
|
|
switch (lb->type)
|
|
{
|
|
case CMT_STR_CONST:
|
|
lb->addr = rip;
|
|
if (buf)
|
|
MemCopy(buf + rip, lb->str, lb->st_len);
|
|
rip += lb->st_len;
|
|
break;
|
|
case CMT_JMP_TABLE:
|
|
lb->addr = rip;
|
|
ptr = buf + lb->addr;
|
|
if (lb->flags & (CMF_I8_JMP_TABLE | CMF_U8_JMP_TABLE))
|
|
{
|
|
if (buf)
|
|
for (i = 0; i < lb->range; i++)
|
|
*ptr++ = lb->jmp_table[i]->addr - lb->begin->addr;
|
|
rip += lb->range;
|
|
}
|
|
else if (lb->flags & (CMF_I16_JMP_TABLE | CMF_U16_JMP_TABLE))
|
|
{
|
|
if (buf)
|
|
for (i = 0; i < lb->range; i++)
|
|
*ptr(U16 *)++ = lb->jmp_table[i]->addr - lb->begin->addr;
|
|
rip += lb->range << 1;
|
|
}
|
|
else
|
|
{
|
|
if (buf)
|
|
for (i = 0; i < lb->range; i++)
|
|
{
|
|
if (cc->flags & CCF_AOT_COMPILE && !(cc->flags & CCF_NO_ABSS))
|
|
{
|
|
tmpa = CAlloc(sizeof(CAOTAbsAddr));
|
|
tmpa->next = aotc->abss;
|
|
tmpa->type = AAT_ADD_U32;
|
|
aotc->abss = tmpa;
|
|
tmpa->rip = aotc->rip + lb->addr + i << 2;
|
|
*ptr(U32 *)++ = lb->jmp_table[i]->addr + aotc->rip;
|
|
}
|
|
else
|
|
*ptr(U32 *)++ = lb->jmp_table[i]->addr + buf;
|
|
}
|
|
rip += lb->range << 2;
|
|
}
|
|
break;
|
|
case CMT_FLOAT_CONSTS:
|
|
lb->addr = rip;
|
|
if (buf)
|
|
MemCopy(buf + lb->addr, lb->float_consts, lb->num_consts * sizeof(F64));
|
|
rip += lb->num_consts * sizeof(F64);
|
|
break;
|
|
}
|
|
lb = lb->next;
|
|
}
|
|
if (debug_info)
|
|
{
|
|
if (cc->flags & CCF_AOT_COMPILE)
|
|
debug_info->body[num_lines] = rip + aotc->rip;
|
|
else
|
|
debug_info->body[num_lines] = rip + buf;
|
|
}
|
|
|
|
return rip;
|
|
}
|