Bool ParseAsmImm(CCompCtrl *cc, CAsmArg *arg)
{
        if (arg->imm_or_off_present)
                LexExcept(cc, "Already one immediate at ");
        arg->imm_or_off_present = TRUE;
        arg->num.local_asm_undef_hash = NULL;
        arg->num.global_asm_undef_hash = NULL;
        cc->asm_undef_hash = NULL;
        cc->abs_counts = 0;
        cc->flags &= ~(CCF_UNRESOLVED + CCF_LOCAL);
        if (!IsLexExpression2Bin(cc, &arg->num.machine_code))
                LexSkipEol(cc);
        else
        {
                if (cc->abs_counts.externs)
                        LexExcept(cc, "Extern Not Allowed at ");
                if (cc->flags & CCF_UNRESOLVED)
                {
                        if (cc->flags & CCF_LOCAL)
                                arg->num.local_asm_undef_hash = cc->asm_undef_hash;
                        else
                                arg->num.global_asm_undef_hash = cc->asm_undef_hash;

                        cc->asm_undef_hash = NULL;
                } 
                else
                {
                        arg->num.i = Call(arg->num.machine_code);
                        arg->num.global_asm_undef_hash = cc->asm_undef_hash;
                        cc->asm_undef_hash = NULL;
                        Free(arg->num.machine_code);
                        arg->num.machine_code = NULL;
                }
        }
        return TRUE;
}

U0 ParseAsmArg(CCompCtrl *cc, CAsmArg *arg, Bool rel)
{
        CHashGeneric *tmph, *tmph1;
        CHashReg         *tmpr;

        MemSet(arg, 0, sizeof(CAsmArg));
        arg->seg  = REG_NONE;
        arg->reg1 = REG_NONE;
        arg->reg2 = REG_NONE;
        arg->scale = 1;
        while (TRUE)
        {
                if (cc->token == TK_IDENT)
                {
                        if (tmph = cc->hash_entry)
                        {
                                if (tmph->type & HTG_TYPE_MASK == HTT_REG)
                                {
                                        tmpr = tmph;
                                        arg->reg1_type = tmpr->reg_type;
                                        switch (tmpr->reg_type)
                                        {
                                                start:
                                                        case REGT_R8:
                                                                arg->size = 1;
                                                                break;

                                                        case REGT_R16:
                                                                arg->size = 2;
                                                                break;

                                                        case REGT_R32:
                                                                arg->size = 4;
                                                                break;

                                                        case REGT_R64:
                                                        case REGT_FSTACK:
                                                        case REGT_MM:
                                                                arg->size = 8;
                                                                break;

                                                        case REGT_XMM:
                                                                arg->size = 16;
                                                end:
                                                        arg->reg1 = tmpr->reg_num;
                                                        Lex(cc);
                                                        return;

                                                case REGT_SEG:
                                                        arg->seg = tmpr->reg_num;
                                                        if (Lex(cc) != ':')
                                                        {
                                                                arg->just_seg = TRUE;
                                                                return;
                                                        }
                                                        else
                                                                Lex(cc); //skip ":"
                                                        break;
                                        }
                                }
                                else
                                {
                                        if ((tmph->type & HTG_TYPE_MASK == HTT_CLASS || tmph->type & HTG_TYPE_MASK == HTT_INTERNAL_TYPE) &&
                                                        (tmph1 = HashFind(cc->cur_str, cmp.asm_hash, HTT_ASM_KEYWORD)))
                                                tmph = tmph1;
                                        if (tmph->type & HTG_TYPE_MASK == HTT_ASM_KEYWORD)
                                        {
                                                switch (tmph->user_data0)
                                                {
                                                        case AKW_I8:
                                                        case AKW_U8:
                                                                arg->size = 1;
                                                                break;

                                                        case AKW_I16:
                                                        case AKW_U16:
                                                                arg->size = 2;
                                                                break;

                                                        case AKW_I32:
                                                        case AKW_U32:
                                                                arg->size = 4;
                                                                break;

                                                        case AKW_I64:
                                                        case AKW_U64:
                                                                arg->size = 8;
                                                                break;

                                                        default:
                                                                LexExcept(cc, "syntax error at ");
                                                }
                                                Lex(cc); //skip keyword
                                        }
                                        else
                                                goto pa_asm_direct_imm;
                                }
                        }
                        else
                        {
pa_asm_direct_imm:
                                ParseAsmImm(cc, arg);
                                arg->num.abs_counts = cc->abs_counts;
                                if (arg->size <= 1 && !rel && arg->num.abs_counts & 1)
                                {
                                        if (cc->aotc->seg_size == 16)
                                                arg->size = 2;
                                        else
                                                arg->size = 4;
                                }
                                if (cc->token != '[')
                                        return;
                        }
                }
                else if (cc->token == '[')
                {
                        arg->indirect = TRUE;
                        Lex(cc); // skip [
                        while (cc->token && cc->token != ']')
                        {
                                if (cc->token == TK_IDENT)
                                {
                                        if (tmph = cc->hash_entry)
                                        {
                                                if (tmph->type & HTG_TYPE_MASK == HTT_REG && REGT_R16 <= tmph(CHashReg *)->reg_type <= REGT_R64)
                                                {
                                                        tmpr = tmph;
                                                        arg->reg2_type = tmpr->reg_type;
                                                        if (arg->reg1 == REG_NONE)
                                                        {
                                                                if (tmpr->reg_num & 7 == REG_RSP)
                                                                {
                                                                        arg->reg1 = 4;
                                                                        arg->reg2 = tmpr->reg_num;
                                                                }
                                                                else
                                                                        arg->reg1 = tmpr->reg_num;
                                                        }
                                                        else
                                                                arg->reg2 = tmpr->reg_num;
                                                        Lex(cc);
                                                }
                                                else
                                                        goto pa_asm_indirect_imm;
                                        }
                                        else
                                                goto pa_asm_indirect_imm;
                                }
                                else if (cc->token == '*')
                                {
                                        Lex(cc);
                                        if (cc->token != TK_I64)
                                                LexExcept(cc, "Expecting scale factor at ");
                                        arg->scale = cc->cur_i64;
                                        Lex(cc); //skip scale
                                        if (arg->reg2 != REG_NONE)
                                        {
                                                SwapI64(&arg->reg1, &arg->reg2);
                                                SwapI64(&arg->reg1_type, &arg->reg2_type);
                                        }
                                }
                                else if (cc->token == '+')
                                {
                                        Lex(cc); //skip '+'
                                }
                                else
                                {
pa_asm_indirect_imm:
                                        ParseAsmImm(cc, arg);
                                        arg->num.abs_counts = cc->abs_counts;
                                }
                        }
                        if (cc->token != ']')
                                LexExcept(cc, "Missing ']' at ");
                        Lex(cc); //skip ]
                        return;
                }
                else
                        goto pa_asm_direct_imm;
        }
}

I64 AsmMakeArgMask(CCompCtrl *cc, CAsmArg *arg)
{
        CAOTCtrl        *aotc = cc->aotc;
        I64                      res;

        if (arg->just_seg)
        {
                switch (arg->seg)
                {
                        case 0:
                                res = 1 << ARGT_ES | 1 << ARGT_SREG;
                                break;

                        case 1:
                                res = 1 << ARGT_CS | 1 << ARGT_SREG;
                                break;

                        case 2:
                                res = 1 << ARGT_SS | 1 << ARGT_SREG;
                                break;

                        case 3:
                                res = 1 << ARGT_DS | 1 << ARGT_SREG;
                                break;

                        case 4:
                                res = 1 << ARGT_FS | 1 << ARGT_SREG;
                                break;

                        case 5:
                                res = 1 << ARGT_GS | 1 << ARGT_SREG;
                                break;
                }
                goto mm_done;
        }
        if (arg->reg1_type == REGT_FSTACK)
        {
                if (arg->reg1)
                        res = 1 << ARGT_STI;
                else
                        res = 1 << ARGT_ST0 | 1 << ARGT_STI;
                goto mm_done;
        }
        res = cmp.size_arg_mask[arg->size];
        if (aotc->seg_size == 64)
                res &= 0xFF0FFFFFFF;

        if (arg->reg1 != REG_NONE && arg->imm_or_off_present && !arg->num.i &&
                        !arg->num.global_asm_undef_hash && !arg->num.local_asm_undef_hash)
                arg->imm_or_off_present = FALSE;        //Zero displacement

        if (arg->reg2 != REG_NONE || arg->scale != 1)
        {
                res &= 0x0000FF0000;
                goto mm_done;
        }

        if (arg->indirect)
        {
                if (arg->imm_or_off_present)
                        res &= 0x00FFFF0000;
                else
                        res &= 0x000FFF0000;
        }
        else
        {
                if (arg->imm_or_off_present)
                        res &= 0x000F000FFE;
                else
                        res &= 0x3F0FFFF000;
        }
        if (arg->seg != REG_NONE)
                res &= 0x00FFFF0000;
        if (arg->reg1 == REG_NONE)
        {
                if (arg->indirect)
                        res &= 0x00FFFF0000;
                else if (arg->num.i < 0)
                {
                        if (arg->num.i >= I8_MIN)
                                res &= 0x8FE;
                        else if (arg->num.i >= I16_MIN)
                                res &= 0x8EE;
                        else if (arg->num.i >= I32_MIN)
                                res &= 0x8CE;
                        else
                                res &= 0x88E;
                }
                else
                {
                        if (arg->num.i <= I8_MAX)
                                res &= 0xFFE;
                        else if (arg->num.i <= U8_MAX)
                                res &= 0xFEE;
                        else if (arg->num.i <= I16_MAX)
                                res &= 0xEEE;
                        else if (arg->num.i <= U16_MAX)
                                res &= 0xECE;
                        else if (arg->num.i <= I32_MAX)
                                res &= 0xCCE;
                        else if (arg->num.i <= U32_MAX)
                                res &= 0xC8E;
                        else
                                res &= 0x88E;
                }
        }
        else
        {
                res &= 0x3F00FFF000;
                if (!arg->indirect) //M8-M64
                        res &= 0xFFFF0FFFFF;
        }
        switch (arg->reg1)
        {
                case REG_RAX:
                        res &= ~0x3000000000;
                        break;

                case REG_RCX:
                        res &= ~0x2F00000000;
                        break;

                case REG_RDX:
                        res &= ~0x1F00000000;
                        break;

                default:
                        res &= ~0x3F00000000;
        }
mm_done:
        return res;
}

Bool AsmStoreNum(CCompCtrl *cc, CAsmNum2 *num2, I64 count, Bool U8_avail)
{
        CAOTCtrl        *aotc = cc->aotc;
        I64                      i;
        CAOTAbsAddr     *tmpa;

        if (!num2->imm_flag)
                num2->num.i -= num2->rel;
        for (i = 0; i < count; i++)
        {
                if (num2->U8_count == 1)
                {
                        if (num2->num.local_asm_undef_hash || num2->num.global_asm_undef_hash)
                                AsmUnresolvedAdd(cc, num2->num.machine_code, IET_REL_I8 + num2->imm_flag, aotc->rip, num2->rel,
                                        num2->num.local_asm_undef_hash, num2->num.global_asm_undef_hash,
                                        cc->lex_include_stack->line_num, U8_avail);
                        else if (!num2->imm_flag && !(I8_MIN <= num2->num.i <= I8_MAX))
                                LexExcept(cc,"Branch out of range at ");
                        if (num2->imm_flag)
                        {
                                if (num2->num.abs_counts.abs_addres & 1)
                                {
                                        tmpa = CAlloc(sizeof(CAOTAbsAddr));
                                        tmpa->next = aotc->abss;
                                        aotc->abss = tmpa;
                                        tmpa->rip = aotc->rip;
                                        tmpa->type = AAT_ADD_U8;
                                }
                        }
                        else
                        {
                                if (num2->num.abs_counts.c_addres & 1)
                                {
                                        tmpa = CAlloc(sizeof(CAOTAbsAddr));
                                        tmpa->next = aotc->abss;
                                        aotc->abss = tmpa;
                                        tmpa->rip = aotc->rip;
                                        tmpa->type = AAT_SUB_U8;
                                }
                        }
                        AOTStoreCodeU8(cc, num2->num.i);
                }
                else
                {
                        if (num2->U8_count == 2)
                        {
                                if (num2->num.local_asm_undef_hash || num2->num.global_asm_undef_hash)
                                        AsmUnresolvedAdd(cc, num2->num.machine_code, IET_REL_I16 + num2->imm_flag, aotc->rip, num2->rel,
                                                num2->num.local_asm_undef_hash, num2->num.global_asm_undef_hash,
                                                cc->lex_include_stack->line_num, U8_avail);
                                else if (!num2->imm_flag && !(I16_MIN <= num2->num.i <= I16_MAX))
                                        LexExcept(cc,"Branch out of range at ");
                                if (num2->imm_flag)
                                {
                                        if (num2->num.abs_counts.abs_addres & 1)
                                        {
                                                tmpa = CAlloc(sizeof(CAOTAbsAddr));
                                                tmpa->next = aotc->abss;
                                                aotc->abss = tmpa;
                                                tmpa->rip = aotc->rip;
                                                tmpa->type = AAT_ADD_U16;
                                        }
                                }
                                else
                                {
                                        if (num2->num.abs_counts.c_addres & 1)
                                        {
                                                tmpa = CAlloc(sizeof(CAOTAbsAddr));
                                                tmpa->next = aotc->abss;
                                                aotc->abss = tmpa;
                                                tmpa->rip = aotc->rip;
                                                tmpa->type = AAT_SUB_U16;
                                        }
                                }
                                AOTStoreCodeU8(cc, num2->num.i.u8[0]);
                                AOTStoreCodeU8(cc, num2->num.i.u8[1]);
                        }
                        else if (num2->U8_count == 4)
                        {
                                if (num2->num.local_asm_undef_hash || num2->num.global_asm_undef_hash)
                                        AsmUnresolvedAdd(cc, num2->num.machine_code, IET_REL_I32 + num2->imm_flag, aotc->rip, num2->rel,
                                                num2->num.local_asm_undef_hash, num2->num.global_asm_undef_hash,
                                                cc->lex_include_stack->line_num, U8_avail);
                                else if (!num2->imm_flag && !(I32_MIN <= num2->num.i <= I32_MAX))
                                        LexExcept(cc,"Branch out of range at ");
                                if (num2->imm_flag)
                                {
                                        if (num2->num.abs_counts.abs_addres & 1)
                                        {
                                                tmpa = CAlloc(sizeof(CAOTAbsAddr));
                                                tmpa->next = aotc->abss;
                                                aotc->abss = tmpa;
                                                tmpa->rip = aotc->rip;
                                                tmpa->type = AAT_ADD_U32;
                                        }
                                }
                                else
                                {
                                        if (num2->num.abs_counts.c_addres & 1)
                                        {
                                                tmpa = CAlloc(sizeof(CAOTAbsAddr));
                                                tmpa->next = aotc->abss;
                                                aotc->abss = tmpa;
                                                tmpa->rip = aotc->rip;
                                                tmpa->type = AAT_SUB_U32;
                                        }
                                }
                                AOTStoreCodeU32(cc, num2->num.i);
                        }
                        else if (num2->U8_count == 8)
                        {
                                if (num2->num.local_asm_undef_hash || num2->num.global_asm_undef_hash)
                                        AsmUnresolvedAdd(cc, num2->num.machine_code, IET_REL_I64 + num2->imm_flag, aotc->rip, num2->rel,
                                                num2->num.local_asm_undef_hash, num2->num.global_asm_undef_hash,
                                                cc->lex_include_stack->line_num, U8_avail);
                                if (num2->imm_flag)
                                {
                                        if (num2->num.abs_counts.abs_addres & 1)
                                        {
                                                tmpa = CAlloc(sizeof(CAOTAbsAddr));
                                                tmpa->next = aotc->abss;
                                                aotc->abss = tmpa;
                                                tmpa->rip = aotc->rip;
                                                tmpa->type = AAT_ADD_U64;
                                        }
                                }
                                else
                                {
                                        if (num2->num.abs_counts.c_addres & 1)
                                        {
                                                tmpa = CAlloc(sizeof(CAOTAbsAddr));
                                                tmpa->next = aotc->abss;
                                                aotc->abss = tmpa;
                                                tmpa->rip = aotc->rip;
                                                tmpa->type = AAT_SUB_U64;
                                        }
                                }
                                AOTStoreCodeU64(cc, num2->num.i);
                        }
                        if (U8_avail && !num2->num.local_asm_undef_hash && !num2->num.global_asm_undef_hash &&
                                !num2->imm_flag && -124 <= num2->num.i <= 123)
                        {
                                LexWarn(cc, "could use I8 displacement at ");
                                return FALSE;
                        }
                }
        }

        return TRUE;
}

U8 asm_seg_prefixes[6] = {0x26, 0x2E, 0x36, 0x3E, 0x64, 0x65};

Bool ParseAsmInst(CCompCtrl *cc, CHashOpcode *tmpo, I64 argcount)
{
        CAOTCtrl        *aotc = cc->aotc;
        I64                      i, j, arg1, arg2, om, seg, arg1mask, arg2mask;
        CAsmArg         *tmpa1, *tmpa2;
        Bool             ModrM_complete, U8_avail = FALSE, found_second_possible = FALSE;
        CInst           *tmpins;
        CAsmIns          cur, best;

        best.U8_count = 255;
        if (argcount > 0)
                arg1mask = AsmMakeArgMask(cc, &aotc->arg1);
        else
                arg1mask = 1;
        if (argcount > 1)
                arg2mask = AsmMakeArgMask(cc, &aotc->arg2);
        else
                arg2mask = 1;
        for (i = 0; i < tmpo->inst_entry_count; i++)
        {
                tmpins = &tmpo->ins[i];
                if (tmpins->arg1 == ARGT_REL8 || tmpins->arg2 == ARGT_REL8)
                        U8_avail = TRUE;
                if (Bt(&arg1mask, tmpins->arg1) && Bt(&arg2mask, tmpins->arg2) &&
                                        (!(tmpins->flags & IEF_NOT_IN_64_BIT) || aotc->seg_size != 64))
                {
                        MemSet(&cur, 0, sizeof(CAsmIns));
                        cur.tmpins = tmpins;
                        ModrM_complete = FALSE;
                        cur.is_default = ToBool(tmpins->flags & IEF_DEFAULT);
                        if (aotc->seg_size == 64)
                        {
                                if (tmpins->flags & IEF_48_REX)
                                        cur.REX = 0x48;
                                else
                                        cur.REX = 0x40;
                        }
                        cur.disp.imm_flag = TRUE;
                        cur.imm.imm_flag = TRUE;
                        om = tmpins->opcode_modifier;
                        arg1 = tmpins->arg1;
                        arg2 = tmpins->arg2;
                        tmpa1 = &aotc->arg1;
                        tmpa2 = &aotc->arg2;
                        cur.last_opcode_U8 = tmpins->opcode[tmpins->opcode_count - 1];

                        if (tmpins->slash_val < 8)
                        {
                                cur.ModrM |= tmpins->slash_val << 3;
                                cur.has_ModrM = TRUE;
                        }

                        if (aotc->seg_size == 16 && tmpins->flags & IEF_OP_SIZE32 || aotc->seg_size != 16 && tmpins->flags & IEF_OP_SIZE16)
                                cur.has_operand_prefix = TRUE;

                        if (om == OM_IB)
                                cur.imm.U8_count = 1;
                        else if (om == OM_IW)
                                cur.imm.U8_count = 2;
                        else if (om == OM_ID)
                                cur.imm.U8_count = 4;

                        if (om == OM_CB)
                        {
                                cur.imm.U8_count = 1;
                                cur.imm.imm_flag = FALSE;
                        }
                        else if (om == OM_CW)
                        {
                                cur.imm.U8_count = 2;
                                cur.imm.imm_flag = FALSE;
                        }
                        else if (om==OM_CD)
                        {
                                cur.imm.U8_count = 4;
                                cur.imm.imm_flag = FALSE;
                        }

                        if (argcount == 1)
                        {
                                if (best.U8_count != 255 && !found_second_possible && !best.is_default)
                                {
                                        found_second_possible = TRUE;
                                        if (!aotc->arg1.size)
                                                PrintWarn("no size specified at %s,%04d\n",
                                                                        cc->lex_include_stack->full_name,
                                                                        cc->lex_include_stack->line_num - 1);
                                }
                                if (tmpins->flags & IEF_PLUS_OPCODE)
                                {
                                        if (tmpins->slash_val == SV_R_REG)
                                        {
                                                cur.last_opcode_U8 |= tmpa1->reg1 & 7;
                                                if (tmpa1->reg1 & 15 > 7)
                                                        cur.REX |= 1;
                                                if (tmpa1->reg1 >= 20) //RBPu8, RSPu8, RSIu8, RDIu8?
                                                        cur.has_REX = TRUE;
                                        }
                                        else
                                        {//SV_I_REG
                                                if (tmpa1->reg1_type == REGT_FSTACK)
                                                        cur.last_opcode_U8 += tmpa1->reg1;
                                        }
                                }
                                if (arg1 == ARGT_R64 || arg1 == ARGT_RM64 || arg1 == ARGT_M64)
                                        cur.REX |= 8;
                                if (ARGT_RM8 <= arg1 <= ARGT_RM64 || ARGT_M8 <= arg1 <= ARGT_M64)
                                {
                                        if (aotc->seg_size == 16)
                                                cur.has_addr_prefix = TRUE;

                                        cur.has_ModrM = TRUE;
                                        if (tmpa1->imm_or_off_present && tmpa1->indirect && tmpa1->reg1 == REG_NONE)
                                        {
                                                cur.ModrM = cur.ModrM + 5;
                                                MemCopy(&cur.disp.num, &tmpa1->num, sizeof(CAsmNum));
                                                cur.disp.U8_count = 4;
                                                if (aotc->seg_size == 64)
                                                        cur.disp.imm_flag = FALSE;
                                        }
                                        else
                                        {
                                                if (tmpa1->reg2 == REG_NONE && tmpa1->scale == 1)
                                                {
                                                        cur.ModrM |= tmpa1->reg1 & 7;
                                                        if (tmpa1->reg1 & 15 > 7)
                                                                cur.REX |= 1;
                                                        if (tmpa1->reg1 >= 20) //RBPu8, RSPu8, RSIu8, RDIu8?
                                                                cur.has_REX = TRUE;
                                                }
                                                else
                                                {
                                                        cur.ModrM |= 4;
                                                        cur.has_SIB = TRUE;
                                                        if (tmpa1->scale == 1)
                                                                cur.SIB = 0;
                                                        else if (tmpa1->scale == 2)
                                                                cur.SIB = 0x40;
                                                        else if (tmpa1->scale == 4)
                                                                cur.SIB = 0x80;
                                                        else if (tmpa1->scale == 8)
                                                                cur.SIB = 0xC0;
                                                        if (tmpa1->reg2 == REG_NONE)
                                                        {
                                                                ModrM_complete = TRUE;
                                                                cur.SIB |= (tmpa1->reg1 & 7) << 3 + REG_RBP;
                                                                if (tmpa1->reg1 & 15 > 7)
                                                                        cur.REX |= 2;
                                                                if (tmpa1->reg1 >= 20) //RBPu8, RSPu8, RSIu8, RDIu8?
                                                                        cur.has_REX = TRUE;
                                                                MemCopy(&cur.disp.num, &tmpa1->num, sizeof(CAsmNum));
                                                                cur.disp.U8_count = 4;
                                                        }
                                                        else
                                                        {
                                                                cur.SIB |= (tmpa1->reg1 & 7) << 3 + tmpa1->reg2 & 7;
                                                                if (tmpa1->reg1 & 15 > 7)
                                                                        cur.REX |= 2;
                                                                if (tmpa1->reg1 >= 20) //RBPu8, RSPu8, RSIu8, RDIu8?
                                                                        cur.has_REX = TRUE;
                                                                if (tmpa1->reg2 & 15 > 7)
                                                                        cur.REX |= 1;
                                                                if (tmpa1->reg2 >= 20) //RBPu8, RSPu8, RSIu8, RDIu8?
                                                                        cur.has_REX = TRUE;
                                                                if (tmpa1->reg2&7 == REG_RBP && !tmpa1->imm_or_off_present && tmpa1->indirect)
                                                                {
                                                                        cur.ModrM |= 0x40;
                                                                        cur.disp.U8_count = 1;
                                                                        ModrM_complete = TRUE;
                                                                }
                                                        }
                                                }
                                                if (!ModrM_complete)
                                                {
                                                        if (tmpa1->imm_or_off_present)
                                                        {
                                                                MemCopy(&cur.disp.num, &tmpa1->num, sizeof(CAsmNum));
                                                                if (!cur.disp.num.machine_code && I8_MIN <= cur.disp.num.i <= I8_MAX)
                                                                {
                                                                        cur.ModrM |= 0x40;
                                                                        cur.disp.U8_count = 1;
                                                                }
                                                                else if (aotc->seg_size == 16)
                                                                {
                                                                        cur.ModrM |= 0x80;
                                                                        cur.disp.U8_count = 2;
                                                                }
                                                                else
                                                                {
                                                                        cur.ModrM |= 0x80;
                                                                        cur.disp.U8_count = 4;
                                                                }
                                                        }
                                                        else if (!tmpa1->indirect)
                                                        {
                                                                cur.has_addr_prefix = FALSE;
                                                                cur.ModrM |= 0xC0;
                                                        }
                                                        else
                                                        {
                                                                if (tmpa1->reg1 & 7 == REG_RBP)
                                                                {
                                                                        cur.ModrM |= 0x40;
                                                                        cur.disp.U8_count = 1;
                                                                }
                                                        }
                                                }
                                        }
                                }
                                else if (ARGT_REL8  <= arg1 <= ARGT_REL32 ||
                                                 ARGT_IMM8  <= arg1 <= ARGT_IMM64 ||
                                                 ARGT_UIMM8 <= arg1 <= ARGT_UIMM64)
                                {
                                        if (arg1 == ARGT_IMM64 || arg2 == ARGT_UIMM64)
                                                cur.REX |= 8;
                                        MemCopy(&cur.imm.num, &tmpa1->num, sizeof(CAsmNum));
                                }
                        }
                        else if (argcount == 2)
                        {
                                if (best.U8_count != 255 && !found_second_possible && !best.is_default)
                                {
                                        found_second_possible = TRUE;
                                        if (!aotc->arg1.size && !aotc->arg2.size)
                                                PrintWarn("no size specified at %s,%04d\n",
                                                                        cc->lex_include_stack->full_name,
                                                                        cc->lex_include_stack->line_num - 1);
                                }
                                if (tmpins->flags & IEF_PLUS_OPCODE)
                                {
                                        if (tmpins->slash_val == SV_R_REG)
                                        {
                                                if (ARGT_AL <= arg1 <= ARGT_RAX)
                                                {
                                                        cur.last_opcode_U8 |= tmpa2->reg1 & 7;
                                                        if (tmpa2->reg1 & 15 > 7)
                                                                cur.REX |= 1;
                                                        if (tmpa2->reg1 >= 20) //RBPu8, RSPu8, RSIu8, RDIu8?
                                                                cur.has_REX = TRUE;
                                                }
                                                else
                                                {
                                                        cur.last_opcode_U8 |= tmpa1->reg1 & 7;
                                                        if (tmpa1->reg1 & 15 > 7)
                                                                cur.REX |= 1;
                                                        if (tmpa1->reg1 >= 20) //RBPu8, RSPu8, RSIu8, RDIu8?
                                                                cur.has_REX = TRUE;
                                                }
                                        }
                                        else
                                        {//SV_I_REG
                                                if (tmpa1->reg1_type == REGT_FSTACK)
                                                        cur.last_opcode_U8 |= tmpa1->reg1;
                                                if (tmpa2->reg1_type == REGT_FSTACK)
                                                        cur.last_opcode_U8 |= tmpa2->reg1;
                                        }
                                }
                                if (arg1 == ARGT_RM64 || arg2 == ARGT_RM64 ||
                                        arg1 == ARGT_M64  || arg2 == ARGT_M64 ||
                                        arg1 == ARGT_R64  || arg2 == ARGT_R64)

                                        cur.REX |= 8;
                                if (ARGT_RM8 <= arg1 <= ARGT_RM64 ||
                                        ARGT_RM8 <= arg2 <= ARGT_RM64 ||
                                        ARGT_M8  <= arg1 <= ARGT_M64  ||
                                        ARGT_M8  <= arg2 <= ARGT_M64)
                                {
                                        if (aotc->seg_size == 16)
                                                cur.has_addr_prefix = TRUE;
                                        cur.has_ModrM = TRUE;
                                        if (ARGT_RM8 <= arg2 <= ARGT_RM64 || ARGT_M8 <= arg2 <= ARGT_M64)
                                        {
                                                tmpa1 = &aotc->arg2;
                                                tmpa2 = &aotc->arg1;
                                        }
                                        if (tmpins->slash_val == SV_R_REG)
                                        {
                                                if (tmpa2->just_seg)
                                                        cur.ModrM |= tmpa2->seg << 3;
                                                else
                                                {
                                                        if (tmpa2->reg1 == REG_NONE)
                                                        {
                                                                cur.ModrM |= (tmpa1->reg1 & 7) << 3;
                                                                if (tmpa1->reg1 & 15 > 7)
                                                                        cur.REX |= 4;
                                                                if (tmpa1->reg1 >= 20) //RBPu8, RSPu8, RSIu8, RDIu8?
                                                                        cur.has_REX = TRUE;
                                                        }
                                                        else
                                                        {
                                                                cur.ModrM |= (tmpa2->reg1 & 7) << 3;
                                                                if (tmpa2->reg1 & 15 >7)
                                                                        cur.REX |= 4;
                                                                if (tmpa2->reg1 >= 20) //RBPu8, RSPu8, RSIu8, RDIu8?
                                                                        cur.has_REX = TRUE;
                                                        }
                                                }
                                        }
                                        if (tmpa1->reg2 == REG_NONE && tmpa1->scale == 1)
                                        {
                                                if (tmpa1->reg1 != REG_NONE)
                                                {
                                                        cur.ModrM |= tmpa1->reg1 & 7;
                                                        if (tmpa1->reg1 & 15 > 7)
                                                                cur.REX |= 1;
                                                        if (tmpa1->reg1 >= 20) //RBPu8, RSPu8, RSIu8, RDIu8?
                                                                cur.has_REX = TRUE;
                                                }
                                        }
                                        else
                                        {
                                                cur.ModrM |= 4;
                                                cur.has_SIB = TRUE;
                                                if (tmpa1->scale == 1)
                                                        cur.SIB = 0;
                                                else if (tmpa1->scale == 2)
                                                        cur.SIB = 0x40;
                                                else if (tmpa1->scale == 4)
                                                        cur.SIB = 0x80;
                                                else if (tmpa1->scale == 8)
                                                        cur.SIB = 0xC0;
                                                if (tmpa1->reg2 == REG_NONE)
                                                {
                                                        ModrM_complete = TRUE;
                                                        cur.SIB |= (tmpa1->reg1 & 7) << 3 + 5;
                                                        if (tmpa1->reg1 & 15 > 7)
                                                                cur.REX |= 2;
                                                        if (tmpa1->reg1 >= 20) //RBPu8, RSPu8, RSIu8, RDIu8?
                                                                cur.has_REX = TRUE;
                                                        MemCopy(&cur.disp.num, &tmpa1->num, sizeof(CAsmNum));
                                                        cur.disp.U8_count = 4;
                                                }
                                                else
                                                {
                                                        cur.SIB |= (tmpa1->reg1 & 7) << 3 + tmpa1->reg2 & 7;
                                                        if (tmpa1->reg1 & 15 > 7)
                                                                cur.REX |= 2;
                                                        if (tmpa1->reg1 >= 20) //RBPu8, RSPu8, RSIu8, RDIu8?
                                                                cur.has_REX = TRUE;
                                                        if (tmpa1->reg2 & 15 > 7)
                                                                cur.REX |= 1;
                                                        if (tmpa1->reg2 >= 20) //RBPu8, RSPu8, RSIu8, RDIu8?
                                                                cur.has_REX = TRUE;
                                                        if (tmpa1->reg2 & 7 == REG_RBP && !tmpa1->imm_or_off_present && tmpa1->indirect)
                                                        {
                                                                cur.ModrM |= 0x40;
                                                                cur.disp.U8_count = 1;
                                                                ModrM_complete = TRUE;
                                                        }
                                                }
                                        }
                                        if (!ModrM_complete)
                                        {
                                                if (tmpa1->imm_or_off_present && tmpa1->indirect && tmpa1->reg1 == REG_NONE)
                                                {
                                                        cur.ModrM = cur.ModrM & 0xF8 + 5;
                                                        MemCopy(&cur.disp.num, &tmpa1->num, sizeof(CAsmNum));
                                                        cur.disp.U8_count = 4;
                                                        if (aotc->seg_size == 64)
                                                                cur.disp.imm_flag = FALSE;
                                                }
                                                else
                                                {
                                                        if (tmpa1->imm_or_off_present)
                                                        {
                                                                MemCopy(&cur.disp.num, &tmpa1->num, sizeof(CAsmNum));
                                                                if (!cur.disp.num.machine_code && I8_MIN <= cur.disp.num.i <= I8_MAX)
                                                                {
                                                                        cur.ModrM |= 0x40;
                                                                        cur.disp.U8_count = 1;
                                                                }
                                                                else if (aotc->seg_size == 16)
                                                                {
                                                                        cur.ModrM |= 0x80;
                                                                        cur.disp.U8_count = 2;
                                                                }
                                                                else
                                                                {
                                                                        cur.ModrM |= 0x80;
                                                                        cur.disp.U8_count = 4;
                                                                }
                                                        }
                                                        else if (!tmpa1->indirect)
                                                        {
                                                                cur.has_addr_prefix = FALSE;
                                                                cur.ModrM |= 0xC0;
                                                        }
                                                        else
                                                        {
                                                                if (tmpa1->reg1 & 7 == REG_RBP)
                                                                {
                                                                        cur.ModrM |= 0x40;
                                                                        cur.disp.U8_count = 1;
                                                                }
                                                        }
                                                }
                                        }
                                }
                                else if (ARGT_MOFFS8 <= arg1 <= ARGT_MOFFS64)
                                {
                                        MemCopy(&cur.disp.num, &tmpa1->num, sizeof(CAsmNum));
                                        if (aotc->seg_size == 16)
                                                cur.disp.U8_count = 2;
                                        else
                                                cur.disp.U8_count = 4;
                                        cur.has_addr_prefix = FALSE;
                                }
                                else if (ARGT_MOFFS8 <= arg2 <= ARGT_MOFFS64)
                                {
                                        MemCopy(&cur.disp.num, &tmpa2->num, sizeof(CAsmNum));
                                        if (aotc->seg_size == 16)
                                                cur.disp.U8_count = 2;
                                        else
                                                cur.disp.U8_count = 4;
                                        cur.has_addr_prefix = FALSE;
                                }
                                else if (ARGT_IMM8  <= arg1 <= ARGT_IMM64 ||
                                                 ARGT_UIMM8 <= arg1 <= ARGT_UIMM64)
                                {
                                        MemCopy(&cur.imm.num, &tmpa1->num, sizeof(CAsmNum));
                                        if (arg1 == ARGT_IMM8 || arg1 == ARGT_UIMM8)
                                                cur.imm.U8_count = 1;
                                        else if (arg1 == ARGT_IMM16 || arg1 == ARGT_UIMM16)
                                                cur.imm.U8_count = 2;
                                        else if (arg1 == ARGT_IMM32 || arg1 == ARGT_UIMM32)
                                                cur.imm.U8_count = 4;
                                        else
                                        {
                                                cur.imm.U8_count = 8;
                                                cur.REX |= 8;
                                        }
                                }
                                if (ARGT_IMM8 <= arg2 <= ARGT_IMM64 || ARGT_UIMM8 <= arg2 <= ARGT_UIMM64)
                                {
                                        MemCopy(&cur.imm.num, &tmpa2->num, sizeof(CAsmNum));
                                        if (arg2 == ARGT_IMM8 || arg2 == ARGT_UIMM8)
                                                cur.imm.U8_count = 1;
                                        else if (arg2 == ARGT_IMM16 || arg2 == ARGT_UIMM16)
                                                cur.imm.U8_count = 2;
                                        else if (arg2 == ARGT_IMM32 || arg2 == ARGT_UIMM32)
                                        {
                                                cur.imm.U8_count = 4;
                                                if (tmpins->flags & IEF_REX_ONLY_R8_R15 && arg2 == ARGT_UIMM32)
                                                        cur.REX &= ~8;
                                        }
                                        else
                                        {
                                                cur.imm.U8_count = 8;
                                                cur.REX |= 8;
                                        }
                                }
                        }
                        cur.U8_count = tmpins->opcode_count + cur.disp.U8_count + cur.imm.U8_count;
                        if (cur.has_ModrM)
                                cur.U8_count++;
                        if (cur.has_SIB)
                                cur.U8_count++;
                        if (aotc->seg_size == 64 && cur.REX & 0x40 == 0x40 && (cur.REX != 0x40 || cur.has_REX) &&
                                        (cur.REX & 7 || !(tmpins->flags & IEF_REX_ONLY_R8_R15 ||
                                        tmpins->flags & IEF_REX_XOR_LIKE && tmpa1->reg1 == tmpa2->reg1 && cur.ModrM & 0xC0 == 0xC0)))
                                cur.U8_count++;
                        if (cur.U8_count < best.U8_count && !(tmpins->flags & IEF_DONT_SWITCH_MODES &&
                                        (cur.has_addr_prefix || cur.has_operand_prefix)))
                                MemCopy(&best, &cur, sizeof(CAsmIns));
                }
        }
        if (best.U8_count < 255)
        {
                tmpins = best.tmpins;
                seg = REG_NONE;
                if (argcount > 1 && aotc->arg2.seg != REG_NONE && !aotc->arg2.just_seg)
                        seg = aotc->arg2.seg;
                else if (argcount > 0 && aotc->arg1.seg != REG_NONE && !aotc->arg1.just_seg)
                        seg = aotc->arg1.seg;
                if (seg != REG_NONE)
                        AOTStoreCodeU8(cc, asm_seg_prefixes[seg]);
                if (best.has_operand_prefix)
                        AOTStoreCodeU8(cc, OC_OP_SIZE_PREFIX); //Operand size override
                if (best.has_addr_prefix || aotc->seg_size == 16 && cur.has_SIB)
                        AOTStoreCodeU8(cc, OC_ADDR_SIZE_PREFIX); //Operand size override
                if (aotc->seg_size == 64 && best.REX & 0x40 == 0x40 && (best.REX != 0x40 || best.has_REX) &&
                                (best.REX & 7 || !(tmpins->flags & IEF_REX_ONLY_R8_R15 ||
                                tmpins->flags & IEF_REX_XOR_LIKE && tmpa1->reg1 == tmpa2->reg1 && best.ModrM & 0xC0 == 0xC0)))
                        AOTStoreCodeU8(cc, best.REX);
                for (j = 0; j < tmpins->opcode_count - 1; j++)
                        AOTStoreCodeU8(cc, tmpins->opcode[j]);
                AOTStoreCodeU8(cc, best.last_opcode_U8);

                if (best.has_ModrM)
                        AOTStoreCodeU8(cc, best.ModrM);
                if (best.has_SIB)
                        AOTStoreCodeU8(cc, best.SIB);

                if (best.disp.U8_count)
                {
                        best.disp.rel = aotc->rip + best.disp.U8_count + best.imm.U8_count;
                        if (!AsmStoreNum(cc, &best.disp, 1, U8_avail))
                                return FALSE;
                }

                if (best.imm.U8_count)
                {
                        best.imm.rel = aotc->rip + best.imm.U8_count;
                        if (!AsmStoreNum(cc, &best.imm, 1, U8_avail))
                                return FALSE;
                }
                if (tmpins->flags & IEF_ENDING_ZERO) //ENTER inst
                        AOTStoreCodeU8(cc, 0);
                return TRUE;
        }
        LexExcept(cc, "Invalid inst at ");
}

U0 ParseAsmDefine(CCompCtrl *cc, I64 U8_count)
{
        Bool             is_dup;
        I64                      i, dup_val;
        U8                      *ptr;
        CAsmNum2         num2;

        num2.U8_count = U8_count;

        while (cc->token && cc->token != ';')
        {
                num2.num.local_asm_undef_hash = NULL;
                num2.num.global_asm_undef_hash = NULL;
                if (cc->token == TK_STR)
                {
                        ptr = cc->cur_str;
                        i = cc->cur_str_len - 1;
                        while (i--)
                                AOTStoreCodeU8(cc, *ptr++);
                        Lex(cc);        //Skip Str
                }
                else
                {
                        is_dup = FALSE;
                        cc->abs_counts = 0;
                        cc->asm_undef_hash = NULL;
                        cc->flags &= ~(CCF_UNRESOLVED + CCF_LOCAL);
                        if (!IsLexExpression2Bin(cc, &num2.num.machine_code))
                                LexSkipEol(cc);
                        else
                        {
                                if (cc->abs_counts.externs)
                                        LexExcept(cc, "Extern Not Allowed at ");
                                if (cc->flags & CCF_UNRESOLVED)
                                {
                                        if (cc->flags & CCF_LOCAL)
                                        {
                                                num2.num.local_asm_undef_hash = cc->asm_undef_hash;
                                                cc->asm_undef_hash = NULL;
                                        }
                                        else
                                        {
                                                num2.num.global_asm_undef_hash = cc->asm_undef_hash;
                                                cc->asm_undef_hash = NULL;
                                        }
                                }
                                else
                                {
                                        i = Call(num2.num.machine_code);
                                        Free(num2.num.machine_code);
                                }
                        }
                        if (cc->token == TK_IDENT && cc->hash_entry)
                        {
                                if (cc->hash_entry->type & HTT_ASM_KEYWORD && cc->hash_entry->user_data0 == AKW_DUP)
                                {
                                        is_dup = TRUE;
                                        if (Lex(cc) != '(')
                                                LexExcept(cc, "Expecting '(' at ");
                                        Lex(cc); //skip (
                                        dup_val = AsmLexExpression(cc);
                                        if (cc->token != ')')
                                                LexExcept(cc, "Expecting ')' at ");
                                        Lex(cc); //SKIP )
                                }
                        }
                        num2.rel = 0;
                        num2.imm_flag = TRUE;
                        num2.num.abs_counts = cc->abs_counts;
                        if (is_dup)
                        {
                                if (num2.num.local_asm_undef_hash || num2.num.global_asm_undef_hash)
                                        LexExcept(cc, "Undefined DUP count at ");
                                num2.num.i = dup_val;
                                AsmStoreNum(cc, &num2, i, FALSE);
                        }
                        else
                        {
                                num2.num.i = i;
                                AsmStoreNum(cc, &num2, 1, FALSE);
                        }
                }
                if (cc->token == ',')
                        Lex(cc);
        }
        if (cc->token != ';')
                LexExcept(cc, "Missing ';' at");
        Lex(cc);
}

U0 ParseBinFile(CCompCtrl *cc)
{
        I64 i, size;
        U8 *buf, *st;

        if (cc->token != TK_STR)
                LexExcept(cc, "Expecting string at ");
        st = ExtDefault(cc->cur_str, "BIN");
        buf = FileRead(st, &size);
        Free(st);
        for (i = 0; i < size; i++)
                AOTStoreCodeU8(cc, buf[i]);
        if (Lex(cc) != ';')
                LexExcept(cc, "Missing ';' at");
        Lex(cc);
}

U0 ParseAsmBlk(CCompCtrl *cc,I64 comp_flags)
{
        CAOTCtrl *aotc = cc->aotc;
        I64 i, j, k, argcount, old_flags = cc->flags & CCF_ASM_EXPRESSIONS;
        CHashOpcode *tmpo;
        CHashExport *tmpex;
        U8 *next_last_label;
        CCodeMisc *g_lb;

        aotc->seg_size = 64;
        cc->flags |= CCF_ASM_EXPRESSIONS;
        if (!(comp_flags & CMPF_ONE_ASM_INS))
        {
                if (cc->token != '{')
                        LexExcept(cc, "Expecting '{' at ");
                Lex(cc);
        }
        while (cc->token && cc->token != '}')
        {
                AsmLineList(cc);
                if (cc->token == TK_IDENT && cc->hash_entry)
                {
                        if (cc->hash_entry->type & HTT_ASM_KEYWORD)
                        {
                                i = cc->hash_entry->user_data0;
                                Lex(cc); //skip keyword
                                switch (i)
                                {
                                        case AKW_IMPORT:
                                                while (cc->token && cc->token != ';')
                                                {
                                                        if (cc->token != TK_IDENT)
                                                                LexExcept(cc, "Expecting identifier at ");
                                                        else
                                                        {
                                                                tmpex = NULL;
                                                                tmpex = CAlloc(sizeof(CHashExport));
                                                                tmpex->str = cc->cur_str;
                                                                cc->cur_str = 0;
                                                                tmpex->type = HTT_EXPORT_SYS_SYM | HTF_UNRESOLVED;
                                                                HashAdd(tmpex, cc->htc.global_hash_table);
                                                                tmpex->type |= HTF_IMPORT;
                                                                if (Lex(cc) == ',')
                                                                        Lex(cc); //skip ','
                                                        }
                                                }
                                                if (cc->token != ';')
                                                        LexExcept(cc, "Missing ';' at");
                                                Lex(cc); //skip ';';
                                                break;

                                        case AKW_ORG:
                                                if (cc->htc.local_var_list)
                                                        LexExcept(cc, "ORG not allowed in fun asm blk ");
                                                if (aotc->org != INVALID_PTR)
                                                        LexExcept(cc, "Just one org allowed ");
                                                if (aotc->rip)
                                                        LexExcept(cc, "ORG must be at beginning ");
                                                aotc->org = AsmLexExpression(cc);
                                                break;

                                        case AKW_ALIGN:
                                                if (cc->htc.local_var_list)
                                                        LexExcept(cc, "ALIGN not allowed in fun asm blk ");
                                                i = AsmLexExpression(cc);
                                                j = Bsf(i);
                                                if (!i || j != Bsr(i))
                                                        LexExcept(cc, "ALIGN must be power of two at ");
                                                if (!(cc->flags & CCF_AOT_COMPILE) && i > 8)
                                                        LexExcept(cc, "In JIT mode, max ALIGN is 8 ");
                                                if (j > aotc->max_align_bits)
                                                        aotc->max_align_bits = j;
                                                i = CeilU64(aotc->rip, i);
                                                if (cc->token != ',')
                                                        LexExcept(cc, "Expecting ',' at ");
                                                Lex(cc);
                                                k = AsmLexExpression(cc);
                                                for (j = aotc->rip; j < i; j++)
                                                        AOTStoreCodeU8(cc, k);
                                                break;

                                        case AKW_DU8:
                                                ParseAsmDefine(cc, 1);
                                                break;

                                        case AKW_DU16:
                                                ParseAsmDefine(cc, 2);
                                                break;

                                        case AKW_DU32:
                                                ParseAsmDefine(cc, 4);
                                                break;

                                        case AKW_DU64:
                                                ParseAsmDefine(cc, 8);
                                                break;

                                        case AKW_BINFILE:
                                                ParseBinFile(cc);
                                                break;

                                        case AKW_LIST:
                                                aotc->list = TRUE;
                                                break;

                                        case AKW_NOLIST:
                                                aotc->list = FALSE;
                                                break;

                                        case AKW_USE16:
                                                aotc->seg_size = 16;
                                                break;

                                        case AKW_USE32:
                                                aotc->seg_size = 32;
                                                break;

                                        case AKW_USE64:
                                                aotc->seg_size = 64;
                                                break;

                                        default:
                                                LexExcept(cc, "Syntax error at ");
                                }
                        }
                        else if (cc->hash_entry->type & HTT_OPCODE)
                        {
                                tmpo = cc->hash_entry;
                                Lex(cc); //skip opcode
                                argcount = 0;
                                if (tmpo->ins[0].arg1)
                                {
                                        argcount++;
                                        if (ARGT_REL8 <= tmpo->ins[0].arg1 <= ARGT_REL32)
                                                ParseAsmArg(cc, &aotc->arg1, TRUE);
                                        else
                                                ParseAsmArg(cc, &aotc->arg1, FALSE);
                                        if (tmpo->ins[0].arg2)
                                        {
                                                argcount++;
                                                if (cc->token != ',')
                                                        LexExcept(cc, "Expecting ',' at ");
                                                else
                                                {
                                                        Lex(cc); //skip ','
                                                        if (ARGT_REL8 <= tmpo->ins[0].arg2 <= ARGT_REL32)
                                                                ParseAsmArg(cc, &aotc->arg2, TRUE);
                                                        else
                                                                ParseAsmArg(cc, &aotc->arg2, FALSE);
                                                }
                                        }
                                }
                                ParseAsmInst(cc, tmpo,argcount);
                        }
                        else if (cc->hash_entry->type & HTT_EXPORT_SYS_SYM)
                        {
                                if (Btr(&cc->hash_entry->type, HTf_UNRESOLVED))
                                {
                                        if (cc->hash_entry->type & HTF_LOCAL)
                                        {
                                                cc->hash_entry(CHashExport *)->val = aotc->rip;
                                                if (Lex(cc) != ':')
                                                        LexExcept(cc, "Expecting ':' at ");
                                                Lex(cc);
                                        }
                                        else
                                        {
                                                if (cc->hash_entry->type & HTF_IMPORT)
                                                        LexExcept(cc, "attempt to define import at ");
                                                cc->hash_entry(CHashExport *)->val = aotc->rip;
                                                next_last_label = cc->hash_entry->str;
                                                Lex(cc); //Skip cur_str
                                                if (cc->token != ':' && cc->token != TK_DBL_COLON)
                                                        LexExcept(cc, "Expecting ':' at ");
                                                if (cc->token == TK_DBL_COLON)
                                                {
                                                        cc->hash_entry->type |= HTF_EXPORT;
                                                        HashSrcFileSet(cc, cc->hash_entry);

                                                        AOTLocalsResolve(cc);
                                                        aotc->last_label = next_last_label;
                                                }
                                                Lex(cc);
                                        }
                                }
                                else if (cc->hash_entry(CHashExport *)->val == aotc->rip)
                                {
                                        Lex(cc); //Skip cur_str
                                        if (cc->token != ':' && cc->token != TK_DBL_COLON)
                                                LexExcept(cc, "Expecting ':' at ");
                                        Lex(cc);
                                }
                                else
                                        LexExcept(cc, "Redefinition at ");
                        }
                        else
                                LexExcept(cc, "Syntax error at ");
                }
                else if (cc->token == TK_IDENT)
                {
                        tmpex = CAlloc(sizeof(CHashExport));
                        tmpex->str = cc->cur_str;
                        cc->cur_str = 0;
                        tmpex->type = HTT_EXPORT_SYS_SYM;
                        tmpex->val = aotc->rip;
                        Lex(cc);        //Skip cur_str
                        if (cc->token != ':' && cc->token != TK_DBL_COLON)
                                LexExcept(cc, "Expecting ':' at ");
                        else
                        {
                                if (*tmpex->str == '@' && tmpex->str[1] == '@')
                                {
                                        if (cc->token == TK_DBL_COLON)
                                                LexExcept(cc, "No local global exports at ");
                                        HashAdd(tmpex, cc->htc.local_hash_table);
                                }
                                else
                                        HashAdd(tmpex,cc->htc.global_hash_table);
                                if (cc->htc.local_var_list)
                                {//AsmBlk in fun? Also add goto-like label.
                                        if (!(g_lb = COCGoToLabelFind(cc, tmpex->str)))
                                        {
                                                g_lb = COCMiscNew(cc, CMT_ASM_LABEL);
                                                g_lb->str = StrNew(tmpex->str);
                                        }
                                        else if (g_lb->flags & CMF_DEFINED)
                                                LexExcept(cc, "Duplicate goto label at ");
                                        g_lb->type = CMT_ASM_LABEL;
                                        g_lb->flags |= CMF_DEFINED;
                                        g_lb->rip = aotc->rip;
                                        g_lb->use_count++; //Disable warning on unused labels.
                                        ICAdd(cc, IC_LABEL, g_lb, 0);
                                }
                                if (cc->token == TK_DBL_COLON)
                                {
                                        tmpex->type |= HTF_EXPORT;
                                        HashSrcFileSet(cc, tmpex);

                                        AOTLocalsResolve(cc);
                                        aotc->last_label = tmpex->str;
                                }
                                Lex(cc);
                        }
                }
                else if (cc->token == ';')
                        Lex(cc);
                else
                        LexExcept(cc, "Syntax error at ");
                if (comp_flags & CMPF_ONE_ASM_INS && (cc->token != TK_IDENT || !(tmpo=cc->hash_entry) ||
                                !(tmpo->type & (HTT_OPCODE | HTT_ASM_KEYWORD))))
                        break;
        }
        AOTLocalsResolve(cc);
        aotc->list = FALSE;
        cc->flags &= cc->flags & ~CCF_ASM_EXPRESSIONS | old_flags;
}