U0 ICAddEct(CIntermediateCode *tmpi,
            CICType t1, I64 r1, I64 d1,
            CICType t2, I64 r2, I64 d2,
            CICType t3, I64 r3, I64 d3,
            I64 op, I64 rip)
{
    I64  i, tmp,res_reg = REG_RAX;
    Bool swap = FALSE;

    if (r3 != res_reg)
    {
        swap ^= TRUE;
        SwapI64(&t2, &t3);
        SwapI64(&r2, &r3);
        SwapI64(&d2, &d3);
    }
    if (t2.raw_type >= RT_I64 && r2 != res_reg && t2 & MDG_REG_DISP_SIB_RIP)
    {
        if (t1 & MDF_REG && !(r2 == r1 && t2 & MDG_REG_DISP_SIB))
            res_reg = r1;
        ICMov(tmpi, MDF_REG + RT_I64, res_reg, 0, t3, r3, d3, rip);
        i=ICModr1(res_reg, t2, r2, d2);
        if (tmpi->ic_flags & ICF_LOCK)
            ICU8(tmpi, OC_LOCK_PREFIX);
        ICRex(tmpi, i.u8[1]);
        ICU16(tmpi, i.u8[2] << 8 + op);
        ICModr2(tmpi, i,, d2, rip);
    }
    else
    {
        if (t2 & MDF_REG)
            tmp = r2;
        else
            tmp = REG_RCX;

        if (t1 & MDF_REG)
            res_reg = r1;

        if (tmp == res_reg)
            res_reg = REG_RDX;
        if (swap)
        {
            if (r3 == tmp && t3 & MDG_REG_DISP_SIB)
                tmp = REG_RCX;
            ICMov(tmpi, MDF_REG + RT_I64, tmp, 0, t2, r2, d2, rip);
            ICMov(tmpi, MDF_REG + RT_I64, res_reg, 0, t3, r3, d3, rip);
        }
        else
        {
            if (r2 == res_reg && t2 & MDG_REG_DISP_SIB)
                res_reg = REG_RDX;
            ICMov(tmpi, MDF_REG + RT_I64, res_reg, 0, t3, r3, d3, rip);
            ICMov(tmpi, MDF_REG + RT_I64, tmp, 0, t2, r2, d2, rip);
        }
        i = 0x48;
        if (res_reg > 7)
            i += 4;
        if (tmp > 7)
            i++;
        if (tmpi->ic_flags & ICF_LOCK)
            ICU8(tmpi, OC_LOCK_PREFIX);
        ICU24(tmpi, 0xC00000 + i + (tmp & 7) << 16 + (res_reg & 7) << 19 + op << 8);
    }
    ICMov(tmpi, t1, r1, d1, MDF_REG + RT_I64, res_reg, 0, rip);
}

U0 ICAddSubEctImm(CIntermediateCode *tmpi,
                  CICType t1, I64 r1, I64 d1,
                  CICType t2, I64 r2, I64 d2,
                  I64 d, I64 op, I64 rip)
{
    I64 i;

    if (op.u8[0] == 0x2B)
    {
        op = 0x0003;
        d = -d;
    }
    if (t1 & MDF_REG)
    {
        if (!(t2 & MDF_REG))
        {
            ICMov(tmpi, t1, r1, d1, t2, r2, d2, rip);
            t2 = t1;
            r2 = r1;
            d2 = d1;
        }
        if (r1 == r2)
        {
            if (r1 > 7)
                i = 0x49;
            else
                i = 0x48;
            if (!d && (op.u8[0] == 0x03 || op.u8[0] == 0x2B || op.u8[0] == 0x33 || op.u8[0] == 0x0B))
                return;
            else if (d == 1 && op.u8[0] == 0x03)
            {
                ICU24(tmpi, 0xC0FF00 + op.u8[1] << 19 + i + (r1 & 7) << 16);
                return;
            }
            else if (d == -1 && op.u8[0] == 0x03)
            {
                ICU24(tmpi, 0xC8FF00 + i + (r1 & 7) << 16);
                return;
            }
            else if (I8_MIN <= d <= I8_MAX)
            {
                ICU24(tmpi, 0xC08300 + op.u8[1] << 19 + i + (r1 & 7) << 16);
                ICU8(tmpi, d);
                return;
            }
            else if (I32_MIN <= d <= I32_MAX)
            {
                ICU24(tmpi, 0xC08100 + op.u8[1] << 19 + i + (r1 & 7) << 16);
                ICU32(tmpi, d);
                return;
            }
        }
        if (op.u8[0] == 0x03 && I32_MIN <= d <= I32_MAX && !Bt(&cmp.non_ptr_vars_mask, r2))
        {
            i = ICModr1(r1, MDF_DISP + RT_I64, r2, d);
            i.u8[1] |= 0x48;
            ICU24(tmpi, i.u8[2] << 16 + 0x8D00 + i.u8[1]);
            ICModr2(tmpi, i,, d, rip);
            return;
        }
    }
    switch (Bsr(t1))
    {
        case MDf_REG:
        case MDf_DISP:
        case MDf_SIB:
        case MDf_RIP_DISP32:
            if (t1 != t2 || r1 != r2 || d1 != d2)
            {
                ICMov(tmpi, t1, r1, d1, t2, r2, d2, rip);
                t2 = t1;
                r2 = r1;
                d2 = d1;
            }

            if (!d &&(op.u8[0] == 0x03 || op.u8[0] == 0x2B || op.u8[0] == 0x33 || op.u8[0] == 0x0B))
                return;

            if (op.u8[0] == 0x03 && d == -1) //add -1
                op.u8[1] = 1; //Decrement slash val

            if (op.u8[0] == 0x03 && (d == 1 || d == -1)) { //Add
                i = ICModr1(op.u8[1], t1, r1, d1);
                if (!(t1 & MDF_REG) && tmpi->ic_flags & ICF_LOCK)
                    ICU8(tmpi, OC_LOCK_PREFIX);
                switch (t1.raw_type)
                {
                    case RT_I8:
                    case RT_U8:
                        ICRex(tmpi, i.u8[1]);
                        ICU16(tmpi, i.u8[2] << 8 + 0xFE);
                        break;

                    case RT_I16:
                    case RT_U16:
                        ICOpSizeRex(tmpi, i.u8[1]);
                        ICU16(tmpi, i.u8[2] << 8 + 0xFF);
                        break;

                    default:
                        ICRex(tmpi, i.u8[1]);
                        ICU16(tmpi, i.u8[2] << 8 + 0xFF);
                }
                ICModr2(tmpi, i,, d1, rip);
                return;
            }
            if (I8_MIN <= d <= I8_MAX || t1 & (RTG_MASK - RTF_UNSIGNED) == RT_I8)
            {
                ICSlashOp(tmpi, t1, r1, d1, SLASH_OP_IMM_U8 + op.u8[1], rip + 1);
                ICU8(tmpi, d);
                return;
            }
            if (I32_MIN <= d <= I32_MAX || t1.raw_type < RT_I64)
            {
                ICSlashOp(tmpi, t1, r1, d1, SLASH_OP_IMM_U32 + op.u8[1], rip);
                if (t1 & (RTG_MASK - RTF_UNSIGNED) == RT_I16)
                    ICU16(tmpi, d);
                else
                    ICU32(tmpi, d);
                return;
            }
            break;

        case MDf_STACK:
            ICAddSubEctImm(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t2, r2, d2, d, op, rip);
            ICPushRegs(tmpi, 1 << REG_RAX);
            return;
    }
    ICAddEct(tmpi, t1, r1, d1, MDF_IMM + RT_I64, 0, d, t2, r2, d2, op.u8[0], rip);
}

U0 ICSub(CIntermediateCode *tmpi,
         CICType t1, I64 r1, I64 d1,
         CICType t2, I64 r2, I64 d2,
         CICType t3, I64 r3, I64 d3,
         I64 rip)
{
    I64  i = 0x48, op = 0x2B;
    Bool swap = FALSE;

    if (r3 != REG_RAX)
    {
        swap = TRUE;
        SwapI64(&t2, &t3);
        SwapI64(&r2, &r3);
        SwapI64(&d2, &d3);
    }
    if (t2.raw_type >= RT_I64 && r2.u8[0] != REG_RAX &&
        (!(t2 & MDF_SIB) || r2.u8[1] & 15 != REG_RAX) &&
        t2 & MDG_REG_DISP_SIB_RIP)
    {
        ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t3, r3, d3, rip);
        if (!swap)
        {
            op = 0x03;
            ICU24(tmpi, 0xD8F748); // NEG RAX
        }
        i = ICModr1(REG_RAX, t2, r2, d2);
        if (tmpi->ic_flags & ICF_LOCK)
            ICU8(tmpi, OC_LOCK_PREFIX);
        ICRex(tmpi, i.u8[1]);
        ICU16(tmpi, i.u8[2] << 8 + op);
        ICModr2(tmpi, i,, d2, rip);
        ICMov(tmpi, t1, r1, d1, MDF_REG + RT_I64, REG_RAX, 0, rip);
    }
    else
    {
        if (!(t3 & MDF_REG) || t3.raw_type < RT_I64)
        {
            if (swap)
            {
                swap = FALSE;
                ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t3, r3, d3, rip);
                ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
                r2 = REG_RAX;
                r3 = REG_RCX;
            }
            else
            {
                ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t3, r3, d3, rip);
                ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
                r3 = REG_RAX;
                r2 = REG_RCX;
            }
        }
        else
        {
            ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
            r2 = REG_RCX;
        }
        if (swap)
        {
            op = 0x03;
            ICU24(tmpi, 0xD9F748); // NEG   U64 RCX
        }
        if (r3 > 7)
            i++;
        if (r2 > 7)
            i += 4;
        if (tmpi->ic_flags & ICF_LOCK)
            ICU8(tmpi, OC_LOCK_PREFIX);
        ICU24(tmpi, 0xC00000 + i + (r3 & 7) << 16 + (r2 & 7) << 19 + op << 8);
        ICMov(tmpi, t1, r1, d1, MDF_REG + RT_I64, r2, 0, rip);
    }
}

U0 ICMul(CIntermediateCode *tmpi, I64 rip)
{
    I64      i, r2, r = REG_RAX, j;
    CICArg  *arg1, *arg2;
    Bool     alt;

    if (tmpi->arg1.type & MDF_IMM)
    {
        arg1 = &tmpi->arg2;
        arg2 = &tmpi->arg1;
        alt = TRUE;
    }
    else
    {
        arg1 = &tmpi->arg1;
        arg2 = &tmpi->arg2;
        alt = FALSE;
    }
    i = arg2->disp;
    if (!(tmpi->ic_class->raw_type & RTF_UNSIGNED) && arg2->type & MDF_IMM && I32_MIN <= i <= I32_MAX)
    {
        if (tmpi->res.type == MDF_REG + RT_I64)
        {
            ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, arg1->type, arg1->reg, arg1->disp, rip);
            r = tmpi->res.reg;
        }
        else
            ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, arg1->type, arg1->reg, arg1->disp, rip);
        if (r > 7)
            j = 0xC0004D;
        else
            j = 0xC00048;
        if (I8_MIN <= i <= I8_MAX)
            ICU32(tmpi, i << 24 + 0x6B00 + j + (r & 7) << 16 + (r & 7) << 19);
        else
        {
            ICU24(tmpi, 0x6900 + j + (r & 7) << 16 + (r & 7) << 19);
            ICU32(tmpi, i);
        }
    }
    else
    {
        if (tmpi->ic_class->raw_type & RTF_UNSIGNED)
            i = 0xE0F748;
        else
            i = 0xE8F748;
        if (alt)
        {
            ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, arg1->type, arg1->reg, arg1->disp, rip);
            r2 = REG_RCX;
            ICMov(tmpi, MDF_REG + RT_I64,REG_RAX, 0, arg2->type, arg2->reg, arg2->disp, rip);
        }
        else
        {
            ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, arg2->type, arg2->reg, arg2->disp, rip);
            if (!(arg1->type & MDF_REG) || arg1->type.raw_type < RT_I64)
            {
                ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, arg1->type, arg1->reg, arg1->disp, rip);
                r2 = REG_RCX;
            }
            else
                r2 = arg1->reg;
        }
        if (r2 > 7)
        {
            i++;
            r2 &= 7;
        }
        ICU24(tmpi, i + r2 << 16);
    }
    ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, r, 0, rip);
}

U0 ICMulEqu(CIntermediateCode *tmpi, I64 rip)
{
    I64 i = tmpi->arg2.disp, r = REG_RAX, j;

    if (!(tmpi->ic_class->raw_type & RTF_UNSIGNED) && tmpi->arg2.type & MDF_IMM && I32_MIN <= i <= I32_MAX)
    {
        if (tmpi->ic_flags & ICF_BY_VAL)
        {
            if (tmpi->arg1.type == MDF_REG + RT_I64)
                r = tmpi->arg1.reg;
            else
                ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0,
                      tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
                      tmpi->arg1.reg, tmpi->arg1.disp, rip);
            if (r > 7)
                j = 0xC0004D;
            else
                j = 0xC00048;
            if (I8_MIN <= i <= I8_MAX)
                ICU32(tmpi, i << 24 + 0x6B00 + j + (r & 7) << 16 + (r & 7) << 19);
            else
            {
                ICU24(tmpi, 0x6900 + j + (r & 7) << 16 + (r & 7) << 19);
                ICU32(tmpi, i);
            }
            ICMov(tmpi, tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
                  tmpi->arg1.reg, tmpi->arg1.disp, MDF_REG + RT_I64, r, 0, rip);
        }
        else
        {
            ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0,
                  tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
            ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0,
                  MDF_DISP + tmpi->arg1_type_pointed_to, REG_RCX, 0, rip);
            r = REG_RBX;
            if (I8_MIN <= i <= I8_MAX)
                ICU32(tmpi, i << 24 + 0xDB6B48); // IMUL2 U64 RBX, I8 i
            else
            {
                ICU24(tmpi, 0xDB6948);  //
                ICU32(tmpi, i);         // IMUL2    U64 RBX, U32 i
            }
            ICMov(tmpi, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RCX, 0, MDF_REG + RT_I64, REG_RBX, 0, rip);
        }
    }
    else
    {
        if (tmpi->ic_class->raw_type & RTF_UNSIGNED)
            i = 0xE3F748;
        else
            i = 0xEBF748;
        if (tmpi->ic_flags & ICF_BY_VAL)
        {
            ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
            ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0,
                  tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
                  tmpi->arg1.reg, tmpi->arg1.disp, rip);
            ICU24(tmpi, i);
            ICMov(tmpi, tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
                  tmpi->arg1.reg, tmpi->arg1.disp, MDF_REG + RT_I64, REG_RAX, 0, rip);
        }
        else
        {
            ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
            ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
            ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RCX, 0, rip);
            ICU24(tmpi, i);
            ICMov(tmpi, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RCX, 0, MDF_REG + RT_I64, REG_RAX, 0, rip);
        }
    }
    if (tmpi->res.type.mode)
        ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, r, 0, rip);
}

U0 ICDiv(CIntermediateCode *tmpi, I64 rip)
{
    ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
    ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
    if (tmpi->ic_class->raw_type & RTF_UNSIGNED)
    {
        ICZero(tmpi, REG_RDX);
        ICU24(tmpi, 0xF1F748); // DIV   U64 RCX
    }
    else
    {
        ICU16(tmpi, 0x9948);    // CQO
        ICU24(tmpi, 0xF9F748);  // IDIV     U64 RAX
    }
    ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RAX, 0, rip);
}

U0 ICDivEqu(CIntermediateCode *tmpi, Bool is_mod, I64 rip)
{
    if (tmpi->ic_flags & ICF_BY_VAL)
    {
        ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
        ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0,
              tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
              tmpi->arg1.reg, tmpi->arg1.disp, rip);
        if (tmpi->ic_class->raw_type & RTF_UNSIGNED)
        {
            ICZero(tmpi, REG_RDX);
            ICU24(tmpi, 0xF1F748); // DIV   U64 RCX
        }
        else
        {
            ICU16(tmpi, 0x9948);    // CQO
            ICU24(tmpi, 0xF9F748);  // IDIV     U64 RAX
        }
        if (is_mod)
            ICMov(tmpi, tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
                  tmpi->arg1.reg, tmpi->arg1.disp, MDF_REG + RT_I64, REG_RDX, 0, rip);
        else
            ICMov(tmpi, tmpi->arg1.type & MDG_MASK + tmpi->arg1_type_pointed_to,
                  tmpi->arg1.reg, tmpi->arg1.disp, MDF_REG + RT_I64, REG_RAX, 0, rip);
    }
    else
    {
        ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
        ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
//dangerous might clobber RBX in Mov, but it doesn't
        ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RBX, 0, rip);
        if (tmpi->ic_class->raw_type & RTF_UNSIGNED)
        {
            ICZero(tmpi, REG_RDX);
            ICU24(tmpi, 0xF1F748); // DIV   U64 RCX
        }
        else
        {
            ICU16(tmpi, 0x9948);    // CQO
            ICU24(tmpi, 0xF9F748);  // IDIV     U64 RAX
        }
        if (is_mod)
            ICMov(tmpi, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RBX, 0, MDF_REG + RT_I64, REG_RDX, 0, rip);
        else
            ICMov(tmpi, MDF_DISP + tmpi->arg1_type_pointed_to, REG_RBX, 0, MDF_REG + RT_I64, REG_RAX, 0, rip);
    }
    if (tmpi->res.type.mode)
    {
        if (is_mod)
            ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RDX, 0, rip);
        else
            ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RAX, 0, rip);
    }
}

U0 ICMod(CIntermediateCode *tmpi, I64 rip)
{
    ICMov(tmpi, MDF_REG +RT_I64, REG_RCX, 0, tmpi->arg2.type, tmpi->arg2.reg, tmpi->arg2.disp, rip);
    ICMov(tmpi, MDF_REG +RT_I64, REG_RAX, 0, tmpi->arg1.type, tmpi->arg1.reg, tmpi->arg1.disp, rip);
    if (tmpi->ic_class->raw_type & RTF_UNSIGNED)
    {
        ICZero(tmpi, REG_RDX);
        ICU24(tmpi, 0xF1F748); // DIV   U64 RCX
    }
    else
    {
        ICU16(tmpi, 0x9948);    // CQO
        ICU24(tmpi, 0xF9F748);  // IDIV     U64 RAX
    }
    ICMov(tmpi, tmpi->res.type, tmpi->res.reg, tmpi->res.disp, MDF_REG + RT_I64, REG_RDX, 0, rip);
}

U0 ICAddSubEctEqu(CIntermediateCode *tmpi, U8 type_pointed_to,
                  CICType t1, I64 r1, I64 d1,
                  CICType t2, I64 r2, I64 d2,
                  CICType t3, I64 r3, I64 d3,
                  I64 op, I64 rip)
{
    Bool done;
    I64  res_reg, tmp, i;

    if (tmpi->ic_flags & ICF_BY_VAL)
    {
        if (t3 & MDF_IMM)
        {
            ICAddSubEctImm(tmpi, t2 & MDG_MASK + type_pointed_to, r2, d2,
                           t2 & MDG_MASK + type_pointed_to, r2, d2, d3, op, rip);
            if (t1.mode)
                ICMov(tmpi, t1, r1, d1, t2 & MDG_MASK + type_pointed_to, r2, d2, rip);
            return;
        }
        else
        {
            done = FALSE;
            if (type_pointed_to >= RT_I64)
            {
                if (!t1.mode && t2 & MDG_REG_DISP_SIB_RIP)
                {
                    if (t3 & MDF_REG)
                        tmp = r3;
                    else
                    {
                        tmp = REG_RCX;
                        ICMov(tmpi, MDF_REG + RT_I64, tmp, 0, t3, r3, d3, rip);
                    }
                    i = ICModr1(tmp, t2 & MDG_MASK + type_pointed_to, r2, d2);
                    if (tmpi->ic_flags & ICF_LOCK)
                        ICU8(tmpi, OC_LOCK_PREFIX);
                    ICRex(tmpi, i.u8[1]);
                    ICU16(tmpi, i.u8[2] << 8 + op.u8[5]);
                    ICModr2(tmpi, i,, d2, rip);
                    return;
                }
                if (t3.raw_type >= RT_I64 && t3 & MDG_REG_DISP_SIB_RIP)
                {
                    if (t2 & MDF_REG)
                        res_reg = r2;
                    else
                    {
                        res_reg = REG_RCX;
                        ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
                    }
                    i = ICModr1(res_reg, t3 & MDG_MASK + type_pointed_to, r3, d3);
                    if (tmpi->ic_flags & ICF_LOCK)
                        ICU8(tmpi, OC_LOCK_PREFIX);
                    ICRex(tmpi, i.u8[1]);
                    ICU16(tmpi, i.u8[2] << 8 + op.u8[0]);
                    ICModr2(tmpi, i,, d3, rip);
                    ICMov(tmpi, t2 & MDG_MASK + type_pointed_to, r2, d2, MDF_REG + RT_I64, res_reg, 0, rip);
                    done = TRUE;
                }
            }
            if (!done)
            {
                ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t3, r3, d3, rip);
                if (t2 & MDF_REG && r2 != REG_RAX)
                    res_reg = r2;
                else
                {
                    res_reg = REG_RCX;
                    ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2 & MDG_MASK + type_pointed_to, r2, d2, rip);
                }
                if (tmpi->ic_flags & ICF_LOCK)
                    ICU8(tmpi, OC_LOCK_PREFIX);
                if (res_reg > 7)
                    ICU8(tmpi, 0x4C);
                else
                    ICU8(tmpi, 0x48);
                ICU16(tmpi, 0xC000 + op.u8[0] + (res_reg & 7) << 11);
                ICMov(tmpi, t2 & MDG_MASK + type_pointed_to, r2, d2, MDF_REG + RT_I64, res_reg, 0, rip);
            }
        }
    }
    else
    {
        done = FALSE;
        if (t3 & MDF_IMM && op.u8[2])
        {
            if (!d3.u32[1])
            {
                if (tmpi->ic_flags & ICF_RES_NOT_USED && t2 & MDF_REG && d3(U64) <= I8_MAX)
                {
                    ICSlashOp(tmpi, MDF_DISP + type_pointed_to, r2, 0, 0x838000 + op.u8[4], rip);
                    ICU8(tmpi, d3);
                    done = TRUE;
                }
                else if (op.u8[2] == 0x24)
                { // AND
                    ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
                    ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, MDF_DISP + type_pointed_to, REG_RCX, 0, rip);
                    res_reg = REG_RAX;
                    if (tmpi->ic_flags & ICF_LOCK)
                        ICU8(tmpi, OC_LOCK_PREFIX);
                    ICU16(tmpi, op.u8[3] << 8 + 0x40);
                    ICU32(tmpi, d3);
                    ICMov(tmpi, MDF_DISP + type_pointed_to, REG_RCX, 0, MDF_REG + RT_I64, res_reg, 0, rip);
                    done = TRUE;
                }
                else if (type_pointed_to < RT_I64)
                { // OR/XOR
                    ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
                    ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, MDF_DISP + type_pointed_to, REG_RCX, 0, rip);
                    res_reg = REG_RAX;
                    if (tmpi->ic_flags & ICF_LOCK)
                        ICU8(tmpi, OC_LOCK_PREFIX);
                    if (d3.u16[1])
                    {
                        ICU16(tmpi, op.u8[3] << 8 + 0x40);
                        ICU32(tmpi, d3);
                    }
                    else if (d3.u8[1])
                    {
                        ICU24(tmpi, op.u8[3] << 16 + 0x4000 + OC_OP_SIZE_PREFIX);
                        ICU16(tmpi, d3);
                    }
                    else
                    {
                        ICU16(tmpi, op.u8[2] << 8 + 0x40);
                        ICU8(tmpi, d3);
                    }
                    ICMov(tmpi, MDF_DISP + type_pointed_to, REG_RCX, 0, MDF_REG + RT_I64, res_reg, 0, rip);
                    done = TRUE;
                }
            }
        }
        if (!done)
        {
            ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t3, r3, d3, rip);
            ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t2, r2, d2, rip);
            ICMov(tmpi, MDF_REG + RT_I64, REG_RBX, 0, MDF_DISP + type_pointed_to, REG_RCX, 0, rip);
            res_reg = REG_RBX;
            if (tmpi->ic_flags & ICF_LOCK)
                ICU8(tmpi, OC_LOCK_PREFIX);
            ICU8(tmpi, 0x48);
            ICU16(tmpi, 0xC000 + op.u8[0] + (res_reg & 7) << 11);
            ICMov(tmpi, MDF_DISP + type_pointed_to, REG_RCX, 0, MDF_REG + RT_I64, res_reg, 0, rip);
        }
    }
    if (t1.mode)
        ICMov(tmpi, t1, r1, d1, MDF_REG + RT_I64, res_reg, 0, rip);
}

U0 ICShift(CIntermediateCode *tmpi,
           CICType t1, I64 r1, I64 d1,
           CICType t2, I64 r2, I64 d2,
           CICType t3, I64 r3, I64 d3,
           I64 us, I64 is, I64 rip)
{
    I64 i = 0x48, res_reg;

    if (tmpi->ic_class->raw_type & RTF_UNSIGNED || tmpi->ic_flags & ICF_USE_UNSIGNED)
        is = us;
    if (t1 & MDF_REG)
    {
        res_reg = r1;
        if (res_reg > 7)
            i++;
    }
    else
        res_reg = REG_RAX;
    if (t3 & MDF_IMM)
    {
        ICMov(tmpi, MDF_REG + RT_I64, res_reg, 0, t2, r2, d2, rip);
        if (d3 == 1)
            ICU24(tmpi, i + is.u16[2] << 8 + (res_reg & 7) << 16);
        else
        {
            ICU24(tmpi, i + is.u16[0] << 8 + (res_reg & 7) << 16);
            ICU8(tmpi, d3);
        }
    }
    else
    {
        ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t3, r3, d3, rip);
        ICMov(tmpi, MDF_REG + RT_I64, res_reg, 0, t2, r2, d2, rip);
        ICU24(tmpi, i + is.u16[1] << 8 + (res_reg & 7) << 16);
    }
    ICMov(tmpi, t1, r1, d1, MDF_REG + RT_I64, res_reg, 0, rip);
}

U0 ICShiftEqu(CIntermediateCode *tmpi,U8 type_pointed_to,
              CICType t1, I64 r1, I64 d1,
              CICType t2, I64 r2, I64 d2,
              CICType t3, I64 r3, I64 d3,
              I64 us, I64 is, I64 rip)
{
    I64 res_reg;

    if (tmpi->ic_class->raw_type & RTF_UNSIGNED || tmpi->ic_flags & ICF_USE_UNSIGNED)
        is = us;
    if (tmpi->ic_flags & ICF_BY_VAL)
    {
        if (!(t3 & MDF_IMM))
            ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t3, r3, d3, rip);
        if (t2 & MDF_REG)
            res_reg = r2;
        else
        {
            res_reg = REG_RAX;
            ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, t2 & MDG_MASK + type_pointed_to, r2, d2, rip);
        }
        if (res_reg > 7)
            ICU8(tmpi, 0x49);
        else
            ICU8(tmpi, 0x48);
        if (t3 & MDF_IMM)
        {
            if (d3 == 1)
                ICU16(tmpi, is.u16[2] + (res_reg & 7) << 8);
            else
            {
                ICU16(tmpi, is.u16[0] + (res_reg & 7) << 8);
                ICU8(tmpi, d3);
            }
        }
        else
            ICU16(tmpi, is.u16[1] + (res_reg & 7) << 8);
        ICMov(tmpi, t2 & MDG_MASK + type_pointed_to, r2, d2, MDF_REG + RT_I64, res_reg, 0, rip);
    }
    else
    {
        if (!(t3 & MDF_IMM))
            ICMov(tmpi, MDF_REG + RT_I64, REG_RCX, 0, t3, r3, d3, rip);
        ICMov(tmpi, MDF_REG + RT_I64, REG_RDX, 0, t2, r2, d2, rip);
        ICMov(tmpi, MDF_REG + RT_I64, REG_RAX, 0, MDF_DISP + type_pointed_to, REG_RDX, 0, rip);
        res_reg = REG_RAX;
        ICU8(tmpi, 0x48);
        if (t3 & MDF_IMM)
        {
            if (d3 == 1)
                ICU16(tmpi, is.u16[2] + (res_reg & 7) << 8);
            else
            {
                ICU16(tmpi, is.u16[0] + (res_reg & 7) << 8);
                ICU8(tmpi, d3);
            }
        }
        else
            ICU16(tmpi, is.u16[1] + (res_reg & 7) << 8);
        ICMov(tmpi, MDF_DISP + type_pointed_to, REG_RDX, 0, MDF_REG + RT_I64, res_reg, 0, rip);
    }
    if (t1.mode)
        ICMov(tmpi, t1, r1, d1, MDF_REG + RT_I64, res_reg, 0, rip);
}