Alien-TinyCC

 view release on metacpan or  search on metacpan

src/i386-asm.c  view on Meta::CPAN

                reg2 = 4; /* indicate no index */
            g((op->shift << 6) + (reg2 << 3) + sib_reg1);
        }
#ifdef I386_ASM_16
        } else if (tcc_state->seg_size == 16) {
            /* edi = 7, esi = 6 --> di = 5, si = 4 */
            if ((reg1 == 6) || (reg1 == 7)) {
                reg1 -= 2;
            /* ebx = 3 --> bx = 7 */
            } else if (reg1 == 3) {
                reg1 = 7;
            /* o32 = 5 --> o16 = 6 */
            } else if (reg1 == 5) {
                reg1 = 6;
            /* sib not valid in 16-bit mode */
            } else if (reg1 == 4) {
                reg2 = op->reg2;
		/* bp + si + offset */
		if ((sib_reg1 == 5) && (reg2 == 6)) {
		    reg1 = 2;
		/* bp + di + offset */
		} else if ((sib_reg1 == 5) && (reg2 == 7)) {
		    reg1 = 3;
		/* bx + si + offset */
		} else if ((sib_reg1 == 3) && (reg2 == 6)) {
		    reg1 = 0;
		/* bx + di + offset */
		} else if ((sib_reg1 == 3) && (reg2 == 7)) {
		    reg1 = 1;
		} else {
		    tcc_error("invalid effective address");
		}
		if (op->e.v == 0)
		    mod = 0;
            } else {
                tcc_error("invalid register");
            }
            g(mod + (reg << 3) + reg1);
        }
#endif
        /* add offset */
        if (mod == 0x40) {
            g(op->e.v);
        } else if (mod == 0x80 || op->reg == -1) {
#ifdef I386_ASM_16
            if (tcc_state->seg_size == 16)
                gen_expr16(&op->e);
            else if (tcc_state->seg_size == 32)
#endif
                gen_expr32(&op->e);
        }
    }
}

ST_FUNC void asm_opcode(TCCState *s1, int opcode)
{
    const ASMInstr *pa;
    int i, modrm_index, reg, v, op1, is_short_jmp, seg_prefix;
    int nb_ops, s;
    Operand ops[MAX_OPERANDS], *pop;
    int op_type[3]; /* decoded op type */
#ifdef I386_ASM_16
    static int a32 = 0, o32 = 0, addr32 = 0, data32 = 0;
#endif

    /* force synthetic ';' after prefix instruction, so we can handle */
    /* one-line things like "rep stosb" instead of only "rep\nstosb" */
    if (opcode >= TOK_ASM_wait && opcode <= TOK_ASM_repnz)
        unget_tok(';');

    /* get operands */
    pop = ops;
    nb_ops = 0;
    seg_prefix = 0;
    for(;;) {
        if (tok == ';' || tok == TOK_LINEFEED)
            break;
        if (nb_ops >= MAX_OPERANDS) {
            tcc_error("incorrect number of operands");
        }
        parse_operand(s1, pop);
        if (tok == ':') {
           if (pop->type != OP_SEG || seg_prefix)
               tcc_error("incorrect prefix");
           seg_prefix = segment_prefixes[pop->reg];
           next();
           parse_operand(s1, pop);
#ifndef I386_ASM_16
           if (!(pop->type & OP_EA)) {
               tcc_error("segment prefix must be followed by memory reference");
           }
#endif
        }
        pop++;
        nb_ops++;
        if (tok != ',')
            break;
        next();
    }

    is_short_jmp = 0;
    s = 0; /* avoid warning */

    /* optimize matching by using a lookup table (no hashing is needed
       !) */
    for(pa = asm_instrs; pa->sym != 0; pa++) {
        s = 0;
        if (pa->instr_type & OPC_FARITH) {
            v = opcode - pa->sym;
            if (!((unsigned)v < 8 * 6 && (v % 6) == 0))
                continue;
        } else if (pa->instr_type & OPC_ARITH) {
            if (!(opcode >= pa->sym && opcode < pa->sym + 8*NBWLX))
                continue;
            s = (opcode - pa->sym) % NBWLX;
        } else if (pa->instr_type & OPC_SHIFT) {
            if (!(opcode >= pa->sym && opcode < pa->sym + 7*NBWLX))
                continue;
            s = (opcode - pa->sym) % NBWLX;
        } else if (pa->instr_type & OPC_TEST) {
            if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))



( run in 0.346 second using v1.01-cache-2.11-cpan-70e19b8f4f1 )