U0 ICAndBranch(CIntermediateCode *tmpi, I64 rip, I64 is, U8 *buf, I64 rip2) { U64 i; I64 it, t1, r1, d1, r2; Bool short_jmp, swap, override; CCodeMisc *lb; CICArg *arg1, *arg2; if (tmpi->arg1.type & MDF_IMM) { swap = TRUE; arg1 = &tmpi->arg2; arg2 = &tmpi->arg1; } else { swap = FALSE; arg1 = &tmpi->arg1; arg2 = &tmpi->arg2; } if (arg2->type & MDF_IMM && arg2->disp > U32_MAX) override = TRUE; else override = FALSE; if (arg1->type.raw_type < arg2->type.raw_type) it = arg1->type.raw_type; else it = arg2->type.raw_type; i = arg2->disp; if (arg2->type & MDF_IMM && i <= U32_MAX) { ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, arg1->type, arg1->reg, arg1->disp, rip2); if (i <= U8_MAX) ICU16(tmpi, i << 8 + 0xA8); else if (i <= U16_MAX) ICU32(tmpi, i << 16 + 0xA900 + OC_OP_SIZE_PREFIX); else { ICU8(tmpi, 0xA9); ICU32(tmpi, i); } } else { t1 = MDF_REG + it; d1 = 0; if (swap && !override) { if (arg1->type & MDF_REG) { r1 = arg1->reg; swap = TRUE; } else { r1 = REG_RCX; swap = FALSE; } if (arg2->type & MDF_REG) { r2 = arg2->reg; swap = FALSE; } else r2 = REG_RDX; if (swap) { if (!(arg1->type & MDF_REG) || r1 != arg1->reg) ICMov(tmpi, MDF_REG + RT_I64, r1, 0, arg1->type, arg1->reg, arg1->disp, rip2); if (arg2->type & MDG_REG_DISP_SIB_RIP) { t1 = arg2->type & MDG_MASK + it; r2 = arg2->reg; d1 = arg2->disp; } else ICMov(tmpi, MDF_REG + RT_I64, r2, 0, arg2->type, arg2->reg, arg2->disp, rip2); i = ICModr1(r1, t1, r2, d1); } else { if (arg1->type & MDG_REG_DISP_SIB_RIP) { t1 = arg1->type & MDG_MASK + it; r1 = arg1->reg; d1 = arg1->disp; } else ICMov(tmpi, MDF_REG + RT_I64, r1, 0, arg1->type, arg1->reg, arg1->disp, rip2); if (!(arg2->type & MDF_REG) || r2 != arg2->reg) ICMov(tmpi, MDF_REG + RT_I64, r2, 0, arg2->type, arg2->reg, arg2->disp, rip2); i = ICModr1(r2, t1, r1, d1); } } else { if (arg2->type & MDF_REG) { r2 = arg2->reg; swap = FALSE; } else { r2 = REG_RDX; swap = TRUE; } if (arg1->type & MDF_REG) { r1 = arg1->reg; swap = TRUE; } else r1 = REG_RCX; if (override) swap = FALSE; if (swap) { if (arg2->type & MDG_REG_DISP_SIB_RIP) { t1 = arg2->type & MDG_MASK + it; r2 = arg2->reg; d1 = arg2->disp; } else ICMov(tmpi, MDF_REG + RT_I64, r2, 0, arg2->type, arg2->reg, arg2->disp, rip2); if (!(arg1->type & MDF_REG) || r1 != arg1->reg) ICMov(tmpi, MDF_REG + RT_I64, r1, 0, arg1->type, arg1->reg, arg1->disp, rip2); i = ICModr1(r1, t1, r2, d1); } else { if (!(arg2->type & MDF_REG) || r2 != arg2->reg) ICMov(tmpi, MDF_REG + RT_I64, r2, 0, arg2->type, arg2->reg, arg2->disp, rip2); if (arg1->type & MDG_REG_DISP_SIB_RIP) { t1 = arg1->type & MDG_MASK + it; r1 = arg1->reg; d1 = arg1->disp; } else ICMov(tmpi, MDF_REG + RT_I64, r1, 0, arg1->type, arg1->reg, arg1->disp, rip2); i = ICModr1(r2, t1, r1, d1); } } switch (it) { case RT_I8: case RT_U8: ICRex(tmpi, i.u8[1]); ICU16(tmpi, i.u8[2] << 8 + 0x84); break; case RT_U16: case RT_I16: ICOpSizeRex(tmpi, i.u8[1]); ICU16(tmpi, i.u8[2] << 8 + 0x85); break; default: ICRex(tmpi, i.u8[1]); ICU16(tmpi, i.u8[2] << 8 + 0x85); } ICModr2(tmpi, i,, d1, rip2); } rip += tmpi->ic_count; lb = OptLabelFwd(tmpi->ic_data); short_jmp = ToBool(tmpi->ic_flags & ICF_SHORT_JMP); if (!buf && lb->addr != INVALID_PTR) { i = lb->addr - (rip + 2); if (lb->flags & CMF_POP_CMP) i += 8; if (I8_MIN <= i <= I8_MAX) short_jmp = TRUE; } if (short_jmp) { tmpi->ic_flags |= ICF_SHORT_JMP; i = lb->addr - (rip + 2); if (lb->flags & CMF_POP_CMP) i += 8; ICU16(tmpi, i << 8 + is.u8[2]); } else { tmpi->ic_flags &= ~ICF_SHORT_JMP; i = lb->addr - (rip + 6); if (lb->flags & CMF_POP_CMP) i += 8; ICU16(tmpi, is.u16[0]); ICU32(tmpi, i); } } U0 ICAssign(CIntermediateCode *tmpi, I64 rip) { CIntermediateCode *tmpi1; if (tmpi->ic_flags & ICF_BY_VAL) { ICMov(tmpi, tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to, tmpi->arg1.reg, tmpi->arg1.disp, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip); if (tmpi->res.type.mode) ICMov(tmpi, tmpi->res.type & MDG_MASK + tmpi->arg1_type_pointed_to, tmpi->res.reg, tmpi->res.disp, tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to, tmpi->arg1.reg, tmpi->arg1.disp, rip); } else { if (tmpi->arg1.type & MDF_REG) { if (!(tmpi1 = OptLag1(tmpi)) || tmpi1->ic_code != IC_ADD_CONST || tmpi1->res.type != MDF_REG + RT_I64 || tmpi1->res.reg != tmpi->arg1.reg || tmpi1->arg1.type != MDF_REG + RT_I64 || tmpi1->arg1.reg != tmpi->arg1.reg || (tmpi->arg2.type & MDF_REG || tmpi->arg2.type & MDF_DISP) && tmpi->arg2.reg == tmpi->arg1.reg || tmpi->res.type.mode || tmpi1->ic_flags & ~ICG_NO_CONVERT_MASK) { ICMov(tmpi, MDF_DISP + tmpi->arg1_type_pointed_to, tmpi->arg1.reg, tmpi->arg1.disp, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip); if (tmpi->res.type.mode) ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip); } else { tmpi->ic_flags = (tmpi->ic_flags | tmpi1->ic_flags) & ~ICF_CODE_FINAL | ICF_DONT_RESTORE; tmpi->arg1.disp = tmpi1->ic_data; OptSetNOP1(tmpi1); //This better not be last pass! ICMov(tmpi, MDF_DISP + tmpi->arg1_type_pointed_to, tmpi->arg1.reg, tmpi->arg1.disp, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip); } } else { ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip); ICMov(tmpi, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RCX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip); if (tmpi->res.type.mode) ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip); } } } U0 ICBrBitOps(CIntermediateCode *tmpi, I64 rip, I64 op, I64 op_imm, I64 is, U8 *buf, I64 rip2) { I64 i, t, r1, r2, d1, d2, t1, t2; CICArg *arg1 = &tmpi->arg1, *arg2 = &tmpi->arg2; Bool short_jmp; CCodeMisc *lb; if (tmpi->ic_flags & ICF_BY_VAL) { if (tmpi->ic_flags & ICF_SWAP && !(arg2->type & MDF_REG) && (!(arg2->type & MDF_IMM) || arg2->disp > 63) || !(tmpi->ic_flags & ICF_SWAP) && arg2->type & MDF_IMM && arg2->disp < 64 || arg2->type & MDF_STACK) { ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, arg2->type, arg2->reg, arg2->disp, rip2); t2 = MDF_REG+RT_I64; r2 = REG_RCX; d2 = 0; } else { t2 = arg2->type; if (t2 & MDF_IMM && arg2->disp < 64) r2 = 0; else r2 = arg2->reg; d2 = arg2->disp; } if (!(tmpi->ic_flags & ICF_SWAP) && !(arg1->type & MDF_REG) && (!(arg1->type & MDF_IMM) || arg1->disp > 63) || tmpi->ic_flags & ICF_SWAP && arg1->type & MDF_IMM && arg1->disp < 64 || arg1->type & MDF_STACK) { ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, arg1->type, arg1->reg, arg1->disp, rip2); t1 = MDF_REG+RT_I64; r1 = REG_RDX; d1 = 0; } else { t1 = arg1->type; if (t1 & MDF_IMM && arg1->disp < 64) r1 = 0; else r1 = arg1->reg; d1 = arg1->disp; } } else { t1 = MDF_DISP + RT_I64; t2 = MDF_DISP + RT_I64; d1 = 0; d2 = 0; if (arg2->type & MDF_REG) r2 = arg2->reg; else if (!(tmpi->ic_flags & ICF_SWAP) || !(arg2->type & MDF_IMM) || arg2->disp > 63) { ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, arg2->type, arg2->reg, arg2->disp, rip2); r2 = REG_RCX; } else r2 = 0; if (arg1->type & MDF_REG) r1 = arg1->reg; else if (tmpi->ic_flags & ICF_SWAP || !(arg1->type & MDF_IMM) || arg1->disp > 63) { ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, arg1->type, arg1->reg, arg1->disp, rip2); r1 = REG_RDX; } else r1 = 0; } if (tmpi->ic_flags & ICF_LOCK && op != 0xA30F) ICU8(tmpi, OC_LOCK_PREFIX); if (tmpi->ic_flags & ICF_SWAP) { if (arg2->type & MDF_IMM && arg2->disp < 32) { if (op == 0xA30F && arg2->disp < 8) { t = t1 & MDG_MASK+RT_U8; op_imm = 0xF6; //TEST } else t = t1 & MDG_MASK + RT_U32; } else t = t1; i = ICModr1(r2, t, r1, d1); SwapI64(&arg1, &arg2); } else { if (arg1->type & MDF_IMM && arg1->disp < 32) { if (op == 0xA30F && arg1->disp < 8) { t = t2 & MDG_MASK + RT_U8; op_imm = 0xF6; //TEST } else t = t2 & MDG_MASK + RT_U32; } else t = t2; i = ICModr1(r1, t, r2, d2); } ICRex(tmpi, i.u8[1]); if (op_imm == 0xF6) {//TEST ICU16(tmpi, i.u8[2] << 8 + op_imm); ICModr2(tmpi, i,, arg2->disp, rip2 + 1); ICU8(tmpi, 1 << arg1->disp); if (is == 0x72820F) is = 0x75850F; else is = 0x74840F; } else if (arg1->type & MDF_IMM && arg1->disp < 64) { ICU24(tmpi, i.u8[2] << 16 + op_imm); ICModr2(tmpi, i,, arg2->disp, rip2 + 1); ICU8(tmpi, arg1->disp); } else { ICU24(tmpi, i.u8[2] << 16 + op); ICModr2(tmpi, i,, arg2->disp, rip2); } rip += tmpi->ic_count; lb = OptLabelFwd(tmpi->ic_data); short_jmp = ToBool(tmpi->ic_flags & ICF_SHORT_JMP); if (!buf && lb->addr != INVALID_PTR) { i = lb->addr - (rip + 2); if (lb->flags & CMF_POP_CMP) i += 8; if (I8_MIN <= i <= I8_MAX) short_jmp = TRUE; } if (short_jmp) { tmpi->ic_flags |= ICF_SHORT_JMP; i = lb->addr - (rip + 2); if (lb->flags & CMF_POP_CMP) i += 8; ICU16(tmpi, i << 8 + is.u8[2]); } else { tmpi->ic_flags &= ~ICF_SHORT_JMP; i = lb->addr - (rip + 6); if (lb->flags & CMF_POP_CMP) i += 8; ICU16(tmpi, is.u16[0]); ICU32(tmpi, i); } } U0 ICQueueInit(CIntermediateCode *tmpi, I64 rip2) { I64 r1; if (tmpi->arg1.type == MDF_REG + RT_I64) r1 = tmpi->arg1.reg; else { ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2); r1 = REG_RAX; } ICMov(tmpi, MDF_DISP + RT_I64, r1, 0, MDF_REG + RT_I64, r1, 0, rip2); ICMov(tmpi, MDF_DISP + RT_I64, r1, sizeof(U8 *), MDF_REG + RT_I64, r1, 0, rip2); } U0 ICQueueInsert(CIntermediateCode *tmpi, I64 rip2) { I64 r1, r2; if (tmpi->arg2.type == MDF_REG + RT_I64 && tmpi->arg2.reg != REG_RDX) r2 = tmpi->arg2.reg; else { ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip2); r2 = REG_RAX; } if (tmpi->arg1.type == MDF_REG + RT_I64) r1 = tmpi->arg1.reg; else { ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2); r1 = REG_RDX; } ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0, MDF_DISP + RT_I64, r1, 0, rip2); ICMov(tmpi, MDF_DISP + RT_I64, r1, 0, MDF_REG + RT_I64, r2, 0, rip2); ICMov(tmpi, MDF_DISP + RT_I64, r2, 0, MDF_REG + RT_I64, REG_RBX, 0, rip2); ICMov(tmpi, MDF_DISP + RT_I64, r2, sizeof(U8 *), MDF_REG + RT_I64, r1, 0, rip2); ICMov(tmpi, MDF_DISP + RT_I64, REG_RBX, sizeof(U8 *), MDF_REG + RT_I64, r2, 0, rip2); } U0 ICQueueInsertRev(CIntermediateCode *tmpi, I64 rip2) { I64 r1, r2; if (tmpi->arg2.type == MDF_REG + RT_I64 && tmpi->arg2.reg != REG_RDX) r2 = tmpi->arg2.reg; else { ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip2); r2 = REG_RAX; } if (tmpi->arg1.type == MDF_REG + RT_I64) r1 = tmpi->arg1.reg; else { ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2); r1 = REG_RDX; } ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0, MDF_DISP + RT_I64, r1, sizeof(U8 *), rip2); ICMov(tmpi, MDF_DISP + RT_I64, REG_RBX, 0, MDF_REG + RT_I64, r2, 0, rip2); ICMov(tmpi, MDF_DISP + RT_I64, r2, 0, MDF_REG + RT_I64, r1, 0, rip2); ICMov(tmpi, MDF_DISP + RT_I64, r2, sizeof(U8 *), MDF_REG + RT_I64, REG_RBX, 0, rip2); ICMov(tmpi, MDF_DISP + RT_I64, r1, sizeof(U8 *), MDF_REG + RT_I64, r2, 0, rip2); } U0 ICQueueRemove(CIntermediateCode *tmpi, I64 rip2) { I64 r1; if (tmpi->arg1.type == MDF_REG+RT_I64) r1 = tmpi->arg1.reg; else { ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2); r1 = REG_RAX; } ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0, MDF_DISP + RT_I64, r1, 0, rip2); ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, MDF_DISP + RT_I64, r1, sizeof(U8 *), rip2); ICU24(tmpi, 0x1A8948); ICU32(tmpi, sizeof(U8 *) << 24 + 0x538948); } U0 ICMinMax(CIntermediateCode *tmpi, I64 op, I64 rip2) { I64 r1, i1 = 0x48; if (tmpi->arg2.type == MDF_REG + RT_I64 && tmpi->arg2.reg != REG_RAX) { r1 = tmpi->arg2.reg; if (r1 > 7) { i1++; r1 &= 7; } ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2); } else { if (tmpi->arg1.reg == REG_RAX && tmpi->arg1.type & MDG_REG_DISP_SIB) { ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip2); r1 = REG_RDX; ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2); } else { ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip2); if (tmpi->arg1.type == MDF_REG + RT_I64) { r1 = tmpi->arg1.reg; if (r1 > 7) { i1++; r1 &= 7; } } else { r1 = REG_RDX; ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2); } } } ICU24(tmpi, 0xC03B00 + r1 << 16 + i1); ICU32(tmpi, 0xC0000F00 + op << 16 + r1 << 24 + i1); } U0 ICSqr(CIntermediateCode *tmpi, I64 op, I64 rip2) { ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2); ICSlashOp(tmpi, MDF_REG + RT_I64, REG_RAX, 0, op, rip2); } U0 ICModU64(CIntermediateCode *tmpi, I64 rip2) { CICType t1; I64 r1, d1; ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip2); if (tmpi->arg1.reg != REG_RAX && tmpi->arg1.reg != REG_RDX && tmpi->arg1.type & MDG_REG_DISP_SIB && tmpi->arg1.type.raw_type >= RT_I64) { t1 = tmpi->arg1.type; r1 = tmpi->arg1.reg; d1 = tmpi->arg1.disp; } else { t1 = MDF_REG + RT_I64; r1 = REG_RBX; d1 = 0; ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2); } ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, MDF_DISP + RT_I64, REG_RCX, 0, rip2); ICZero(tmpi, REG_RDX); ICSlashOp(tmpi, t1, r1, d1, SLASH_OP_DIV, rip2); ICMov(tmpi, MDF_DISP + RT_I64, REG_RCX, 0, MDF_REG + RT_I64, REG_RAX, 0, rip2); ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, MDF_REG + RT_I64, REG_RDX, 0, rip2); } U0 ICSwap(CIntermediateCode *tmpi, I64 rip2) { I64 r1, r2; if (tmpi->arg1.type & MDF_REG) r1 = tmpi->arg1.reg; else r1 = REG_RAX; if (tmpi->arg2.type & MDF_REG) r2 = tmpi->arg2.reg; else r2 = REG_RAX; if (r1 == r2) { if (r1 == REG_RAX) r1 = REG_RBX; else r2 = REG_RAX; } ICMov(tmpi, MDF_REG + RT_I64, r2, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip2); ICMov(tmpi, MDF_REG + RT_I64, r1, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2); switch (tmpi->ic_code) { case IC_SWAP_U8: ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, MDF_DISP + RT_U8, r1, 0, rip2); ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, MDF_DISP + RT_U8, r2, 0, rip2); ICMov(tmpi, MDF_DISP + RT_U8, r2, 0, MDF_REG + RT_I64, REG_RCX, 0, rip2); ICMov(tmpi, MDF_DISP + RT_U8, r1, 0, MDF_REG + RT_I64, REG_RDX, 0, rip2); break; case IC_SWAP_U16: ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, MDF_DISP + RT_U16, r1, 0, rip2); ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, MDF_DISP + RT_U16, r2, 0, rip2); ICMov(tmpi, MDF_DISP + RT_U16, r2, 0, MDF_REG + RT_I64, REG_RCX, 0, rip2); ICMov(tmpi, MDF_DISP + RT_U16, r1, 0, MDF_REG + RT_I64, REG_RDX, 0, rip2); break; case IC_SWAP_U32: ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, MDF_DISP + RT_U32, r1, 0, rip2); ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, MDF_DISP + RT_U32, r2, 0, rip2); ICMov(tmpi, MDF_DISP + RT_U32, r2, 0, MDF_REG + RT_I64, REG_RCX, 0, rip2); ICMov(tmpi, MDF_DISP + RT_U32, r1, 0, MDF_REG + RT_I64, REG_RDX, 0, rip2); break; case IC_SWAP_I64: ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, MDF_DISP + RT_U64, r1, 0, rip2); ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, MDF_DISP + RT_U64, r2, 0, rip2); ICMov(tmpi, MDF_DISP + RT_U64, r2, 0, MDF_REG + RT_I64, REG_RCX, 0, rip2); ICMov(tmpi, MDF_DISP + RT_U64, r1, 0, MDF_REG + RT_I64, REG_RDX, 0, rip2); break; } } U0 ICAndEqu(CIntermediateCode *tmpi, I64 rip2) { I64 i, bit; if (tmpi->arg2.type & MDF_IMM && !(tmpi->arg1.type & MDF_STACK) && tmpi->ic_flags & ICF_RES_NOT_USED) { i = ~tmpi->arg2.disp; bit = Bsf(i); if (0 <= bit == Bsr(i)) { tmpi->arg2.disp = bit; tmpi->arg2.reg = 0; tmpi->arg1.type = tmpi->arg1.type & MDG_MASK + RT_I64; ICBitOps(tmpi, &tmpi->arg2, &tmpi->arg1, tmpi, 0xB30F, 0x30BA0F, rip2); return; } } 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, 0x210425240423, rip2); } U0 ICOrEqu(CIntermediateCode *tmpi, I64 rip2) { I64 i, bit; if (tmpi->arg2.type & MDF_IMM && !(tmpi->arg1.type & MDF_STACK) && tmpi->ic_flags & ICF_RES_NOT_USED) { i = tmpi->arg2.disp; bit = Bsf(i); if (0 <= bit == Bsr(i) && i > I8_MAX) { tmpi->arg2.disp = bit; tmpi->arg2.reg = 0; tmpi->arg1.type = tmpi->arg1.type & MDG_MASK + RT_I64; ICBitOps(tmpi, &tmpi->arg2, &tmpi->arg1, tmpi, 0xAB0F, 0x28BA0F, rip2); return; } } 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, 0x09010D0C010B, rip2); } U0 ICXorEqu(CIntermediateCode *tmpi, I64 rip2) { I64 i, bit; if (tmpi->arg2.type & MDF_IMM && !(tmpi->arg1.type & MDF_STACK) && tmpi->ic_flags & ICF_RES_NOT_USED) { i = tmpi->arg2.disp; bit = Bsf(i); if (0 <= bit == Bsr(i)) { tmpi->arg2.disp = bit; tmpi->arg2.reg = 0; tmpi->arg1.type = tmpi->arg1.type & MDG_MASK + RT_I64; ICBitOps(tmpi, &tmpi->arg2, &tmpi->arg1, tmpi, 0xBB0F, 0x38BA0F, rip2); return; } } 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, 0x310635340633, rip2); } U0 ICSwitch(CIntermediateCode *tmpi, I64 rip, Bool nobound, CCompCtrl *cc, U8 *buf, I64 rip2) { I64 i, j, count, min, max, begin, r; CCodeMisc *lb; Bool short_jmp; CAOTAbsAddr *tmpa; if (!(tmpi->arg1.type & MDF_REG) || tmpi->arg1.reg & 7 == REG_RSP) r = REG_RDX; else r = tmpi->arg1.reg; if (nobound) ICMov(tmpi, MDF_REG + RT_I64, r, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2); else { if (tmpi->arg2.type & MDF_IMM) { j = tmpi->arg2.disp; ICMov(tmpi, MDF_REG + RT_I64, r, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2); if (I8_MIN <= j <= I8_MAX) { i = 0xF88348 + (r & 7) << 16; if (r > 7) i++; ICU24(tmpi, i); ICU8(tmpi, j); } else if (I32_MIN <= j <= I32_MAX) { i = 0xF88148 + (r & 7) << 16; if (r > 7) i++; ICU24(tmpi, i); ICU32(tmpi, j); } else { ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip2); i = 0xC13B48 + (r & 7) << 19; if (r > 7) i += 4; ICU24(tmpi, i); } } else { ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip2); ICMov(tmpi, MDF_REG + RT_I64, r, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip2); i = 0xC13B48 + (r & 7) << 19; if (r > 7) i += 4; ICU24(tmpi, i); } rip += tmpi->ic_count; lb = tmpi->ic_data(CCodeMisc *)->default; short_jmp = ToBool(tmpi->ic_flags & ICF_SHORT_JMP); if (!buf && lb->addr != INVALID_PTR) { i = lb->addr - (rip + 2); if (I8_MIN <= i <= I8_MAX) short_jmp = TRUE; } if (short_jmp) { tmpi->ic_flags |= ICF_SHORT_JMP; ICU16(tmpi, (lb->addr - (rip + 2)) << 8 + 0x73); } else { tmpi->ic_flags &= ~ICF_SHORT_JMP; ICU16(tmpi, 0x830F); ICU32(tmpi, lb->addr - (rip + 6)); } } lb = tmpi->ic_data; begin = lb->begin->addr; if (!buf && begin != INVALID_PTR) { min = I64_MAX; max = I64_MIN; for (i = 0; i < lb->range; i++) { if (lb->jmp_table[i]->addr == INVALID_PTR) { min = I64_MIN; max = I64_MAX; break; } else { j = lb->jmp_table[i]->addr-begin; min = MinI64(min, j); max = MaxI64(max, j); } } if (I8_MIN <= min <= max <= I8_MAX) lb->flags |= CMF_I8_JMP_TABLE; else if (U8_MIN <= min <= max <= U8_MAX) lb->flags |= CMF_U8_JMP_TABLE; else if (I16_MIN <= min <= max <= I16_MAX) lb->flags |= CMF_I16_JMP_TABLE; else if (U16_MIN <= min <= max <= U16_MAX) lb->flags |= CMF_U16_JMP_TABLE; } if (lb->flags & CMF_I8_JMP_TABLE) { if (r < 8) ICU8(tmpi, 0x48); else ICU8(tmpi, 0x49); ICU24(tmpi, 0x98BE0F + (r & 7) << 16); count = 1; } else if (lb->flags & CMF_U8_JMP_TABLE) { if (r < 8) count = 2; else { ICU8(tmpi, 0x49); count = 1; } ICU24(tmpi, 0x98B60F + (r & 7) << 16); } else if (lb->flags & CMF_I16_JMP_TABLE) { if (r < 8) ICU8(tmpi, 0x48); else ICU8(tmpi, 0x4A); ICU32(tmpi, 0x451CBF0F + (r & 7) << 27); count = 0; } else if (lb->flags & CMF_U16_JMP_TABLE) { if (r < 8) count = 1; else { ICU8(tmpi, 0x4A); count = 0; } ICU32(tmpi, 0x451CB70F + (r & 7) << 27); } else { if (r < 8) count = 2; else { ICU8(tmpi, 0x42); count = 1; } ICU24(tmpi, 0x851C8B + (r & 7) << 19); } if (buf && cc->flags & CCF_AOT_COMPILE) { tmpa = CAlloc(sizeof(CAOTAbsAddr)); tmpa->next = cc->aotc->abss; tmpa->type = AAT_ADD_U32; cc->aotc->abss = tmpa; tmpa->rip = rip2 + tmpi->ic_count; ICU32(tmpi, lb->addr + cc->aotc->rip); } else ICU32(tmpi, lb->addr+buf); if (lb->flags & (CMF_I8_JMP_TABLE | CMF_U8_JMP_TABLE | CMF_I16_JMP_TABLE | CMF_U16_JMP_TABLE)) { ICU16(tmpi, 0xC381); // ADD EBX, 0x######## if (buf && cc->flags & CCF_AOT_COMPILE) { tmpa = CAlloc(sizeof(CAOTAbsAddr)); tmpa->next = cc->aotc->abss; tmpa->type = AAT_ADD_U32; cc->aotc->abss = tmpa; tmpa->rip = rip2 + tmpi->ic_count; ICU32(tmpi, begin + cc->aotc->rip); } else ICU32(tmpi, begin + buf); } else count += 6; ICU16(tmpi, 0xE3FF); //JMP EBX for (i = 0; i < count; i++) //Code must always shrink, not expand ICU8(tmpi, OC_NOP); tmpi->ic_flags &= ~ICF_CODE_FINAL; } U0 ICLocalVarInit(CIntermediateCode *tmpi) { ICU24(tmpi, 0xC48B48); // MOV U64 RAX, U64 RSP ICU16(tmpi, 0x5748); // PUSH U64 RDI ICU24(tmpi, 0xF88B48); // MOV U64 RDI, U64 RAX ICU24(tmpi, 0xC1C748); // MOV U64 RCX, I32 0x######## ICU32(tmpi, tmpi->ic_data); ICU16(tmpi, sys_var_init_val << 8 + 0xB0); // MOV AL, sys_var_init_val ICU24(tmpi, 0xAA48F3); // REP_STOSB ICU16(tmpi, 0x5F48); // POP U64 RDI }