ZealOS/src/Compiler/OptPass789A.ZC
TomAwezome 3a33e6baaf Rename CosmiC to ZealC.
Rename all .CC files to .ZC extension.
2021-12-11 06:21:22 -05:00

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;
}