⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 x86expr.c

📁 支持AMD64的汇编编译器源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* Figure out what size displacement we will have. */	if (*displen != 0xff && dispval == 0) {	    /* if we know that the displacement is 0 right now,	     * go ahead and delete the expr (making it so no	     * displacement value is included in the output).	     * The Mod bits of ModRM are set to 0 above, and	     * we're done with the ModRM byte!	     *	     * Don't do this if we came from dispreq check above, so	     * check *displen.	     */	    yasm_expr_destroy(e);	    *ep = (yasm_expr *)NULL;	} else if (dispval >= -128 && dispval <= 127) {	    /* It fits into a signed byte */	    *displen = 1;	    *modrm |= 0100;	} else {	    /* It's a 16/32-bit displacement */	    *displen = wordsize;	    *modrm |= 0200;	}	*v_modrm = 1;	/* We're done with ModRM */    }    return 0;}/*@=nullstate@*/static intx86_expr_checkea_getregsize_callback(yasm_expr__item *ei, void *d){    unsigned char *addrsize = (unsigned char *)d;    if (ei->type == YASM_EXPR_REG) {	switch ((x86_expritem_reg_size)(ei->data.reg & ~0xFUL)) {	    case X86_REG16:		*addrsize = 16;		break;	    case X86_REG32:		*addrsize = 32;		break;	    case X86_REG64:	    case X86_RIP:		*addrsize = 64;		break;	    default:		return 0;	}	return 1;    } else	return 0;}intyasm_x86__expr_checkea(yasm_expr **ep, unsigned char *addrsize,		       unsigned int bits, unsigned int nosplit,		       unsigned char *displen, unsigned char *modrm,		       unsigned char *v_modrm, unsigned char *n_modrm,		       unsigned char *sib, unsigned char *v_sib,		       unsigned char *n_sib, unsigned char *pcrel,		       unsigned char *rex,		       yasm_calc_bc_dist_func calc_bc_dist){    yasm_expr *e, *wrt;    int retval;    /* First split off any top-level WRT.  We'll add it back in at the end */    wrt = yasm_expr_extract_wrt(ep);    e = *ep;    if (*addrsize == 0) {	/* we need to figure out the address size from what we know about:	 * - the displacement length	 * - what registers are used in the expression	 * - the bits setting	 */	switch (*displen) {	    case 2:		/* must be 16-bit */		*addrsize = 16;		break;	    case 8:		/* We have to support this for the MemOffs case, but it's		 * otherwise illegal.  It's also illegal in non-64-bit mode.		 */		if (*n_modrm || *n_sib) {		    yasm__error(e->line,			N_("invalid effective address (displacement size)"));		    return 1;		}		*addrsize = 64;		break;	    case 4:		/* Must be 32-bit in 16-bit or 32-bit modes.  In 64-bit mode,		 * we don't know unless we look at the registers, except in the		 * MemOffs case (see the end of this function).		 */		if (bits != 64 || (!*n_modrm && !*n_sib)) {		    *addrsize = 32;		    break;		}		/*@fallthrough@*/	    default:		/* check for use of 16 or 32-bit registers; if none are used		 * default to bits setting.		 */		if (!yasm_expr__traverse_leaves_in(e, addrsize,			x86_expr_checkea_getregsize_callback))		    *addrsize = bits;		/* TODO: Add optional warning here if switched address size		 * from bits setting just by register use.. eg [ax] in		 * 32-bit mode would generate a warning.		 */	}    }    if ((*addrsize == 32 || *addrsize == 64) &&	((*n_modrm && !*v_modrm) || (*n_sib && !*v_sib))) {	int i;	unsigned char low3;	typedef enum {	    REG3264_NONE = -1,	    REG3264_EAX = 0,	    REG3264_ECX,	    REG3264_EDX,	    REG3264_EBX,	    REG3264_ESP,	    REG3264_EBP,	    REG3264_ESI,	    REG3264_EDI,	    REG64_R8,	    REG64_R9,	    REG64_R10,	    REG64_R11,	    REG64_R12,	    REG64_R13,	    REG64_R14,	    REG64_R15,	    REG64_RIP	} reg3264type;	int reg3264mult[17] = {0, 0, 0, 0, 0, 0, 0, 0,			       0, 0, 0, 0, 0, 0, 0, 0, 0};	x86_checkea_reg3264_data reg3264_data;	int basereg = REG3264_NONE;	/* "base" register (for SIB) */	int indexreg = REG3264_NONE;	/* "index" register (for SIB) */	/* We can only do 64-bit addresses in 64-bit mode. */	if (*addrsize == 64 && bits != 64) {	    yasm__error(e->line,		N_("invalid effective address (64-bit in non-64-bit mode)"));	    return 1;	}	reg3264_data.regs = reg3264mult;	reg3264_data.bits = bits;	reg3264_data.addrsize = *addrsize;	switch (x86_expr_checkea_getregusage(ep, &wrt, &indexreg, pcrel, bits,					     &reg3264_data,					     x86_expr_checkea_get_reg3264,					     calc_bc_dist)) {	    case 1:		e = *ep;		yasm__error(e->line, N_("invalid effective address"));		return 1;	    case 2:		if (wrt)		    *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt,						(*ep)->line);		return 2;	    default:		e = *ep;		break;	}	/* If indexreg mult is 0, discard it.	 * This is possible because of the way indexreg is found in	 * expr_checkea_getregusage().	 */	if (indexreg != REG3264_NONE && reg3264mult[indexreg] == 0)	    indexreg = REG3264_NONE;	/* Find a basereg (*1, but not indexreg), if there is one.	 * Also, if an indexreg hasn't been assigned, try to find one.	 * Meanwhile, check to make sure there's no negative register mults.	 */	for (i=0; i<17; i++) {	    if (reg3264mult[i] < 0) {		yasm__error(e->line, N_("invalid effective address"));		return 1;	    }	    if (i != indexreg && reg3264mult[i] == 1 &&		basereg == REG3264_NONE)		basereg = i;	    else if (indexreg == REG3264_NONE && reg3264mult[i] > 0)		indexreg = i;	}	/* Handle certain special cases of indexreg mults when basereg is	 * empty.	 */	if (indexreg != REG3264_NONE && basereg == REG3264_NONE)	    switch (reg3264mult[indexreg]) {		case 1:		    /* Only optimize this way if nosplit wasn't specified */		    if (!nosplit) {			basereg = indexreg;			indexreg = -1;		    }		    break;		case 2:		    /* Only split if nosplit wasn't specified */		    if (!nosplit) {			basereg = indexreg;			reg3264mult[indexreg] = 1;		    }		    break;		case 3:		case 5:		case 9:		    basereg = indexreg;		    reg3264mult[indexreg]--;		    break;	    }	/* Make sure there's no other registers than the basereg and indexreg	 * we just found.	 */	for (i=0; i<17; i++)	    if (i != basereg && i != indexreg && reg3264mult[i] != 0) {		yasm__error(e->line, N_("invalid effective address"));		return 1;	    }	/* Check the index multiplier value for validity if present. */	if (indexreg != REG3264_NONE && reg3264mult[indexreg] != 1 &&	    reg3264mult[indexreg] != 2 && reg3264mult[indexreg] != 4 &&	    reg3264mult[indexreg] != 8) {	    yasm__error(e->line, N_("invalid effective address"));	    return 1;	}	/* ESP is not a legal indexreg. */	if (indexreg == REG3264_ESP) {	    /* If mult>1 or basereg is ESP also, there's no way to make it	     * legal.	     */	    if (reg3264mult[REG3264_ESP] > 1 || basereg == REG3264_ESP) {		yasm__error(e->line, N_("invalid effective address"));		return 1;	    }	    /* If mult==1 and basereg is not ESP, swap indexreg w/basereg. */	    indexreg = basereg;	    basereg = REG3264_ESP;	}	/* RIP is only legal if it's the ONLY register used. */	if (indexreg == REG64_RIP ||	    (basereg == REG64_RIP && indexreg != REG3264_NONE)) {	    yasm__error(e->line, N_("invalid effective address"));	    return 1;	}	/* At this point, we know the base and index registers and that the	 * memory expression is (essentially) valid.  Now build the ModRM and	 * (optional) SIB bytes.	 */	/* First determine R/M (Mod is later determined from disp size) */	*n_modrm = 1;	/* we always need ModRM */	if (basereg == REG3264_NONE && indexreg == REG3264_NONE) {	    /* Just a disp32: in 64-bit mode the RM encoding is used for RIP	     * offset addressing, so we need to use the SIB form instead.	     */	    if (bits == 64) {		*modrm |= 4;		*n_sib = 1;	    } else {		*modrm |= 5;		*sib = 0;		*v_sib = 0;		*n_sib = 0;	    }	} else if (basereg == REG64_RIP) {	    *modrm |= 5;	    *sib = 0;	    *v_sib = 0;	    *n_sib = 0;	    /* RIP always requires a 32-bit displacement */	    *v_modrm = 1;	    *displen = 4;	    if (wrt)		*ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt,					    (*ep)->line);	    return 0;	} else if (indexreg == REG3264_NONE) {	    /* basereg only */	    /* Don't need to go to the full effort of determining what type	     * of register basereg is, as x86_set_rex_from_reg doesn't pay	     * much attention.	     */	    if (yasm_x86__set_rex_from_reg(rex, &low3,					   (unsigned int)(X86_REG64 | basereg),					   bits, X86_REX_B)) {		yasm__error(e->line,		    N_("invalid combination of operands and effective address"));		return 1;	    }	    *modrm |= low3;	    /* we don't need an SIB *unless* basereg is ESP or R12 */	    if (basereg == REG3264_ESP || basereg == REG64_R12)		*n_sib = 1;	    else {		*sib = 0;		*v_sib = 0;		*n_sib = 0;	    }	} else {	    /* index or both base and index */	    *modrm |= 4;	    *n_sib = 1;	}	/* Determine SIB if needed */	if (*n_sib == 1) {	    *sib = 0;	/* start with 0 */	    /* Special case: no basereg */	    if (basereg == REG3264_NONE)		*sib |= 5;	    else {		if (yasm_x86__set_rex_from_reg(rex, &low3, (unsigned int)					       (X86_REG64 | basereg), bits,					       X86_REX_B)) {		    yasm__error(e->line,			N_("invalid combination of operands and effective address"));		    return 1;		}		*sib |= low3;	    }	    	    /* Put in indexreg, checking for none case */	    if (indexreg == REG3264_NONE)		*sib |= 040;		/* Any scale field is valid, just leave at 0. */	    else {		if (yasm_x86__set_rex_from_reg(rex, &low3, (unsigned int)					       (X86_REG64 | indexreg), bits,					       X86_REX_X)) {		    yasm__error(e->line,			N_("invalid combination of operands and effective address"));		    return 1;		}		*sib |= low3 << 3;		/* Set scale field, 1 case -> 0, so don't bother. */		switch (reg3264mult[indexreg]) {		    case 2:			*sib |= 0100;			break;		    case 4:			*sib |= 0200;			break;		    case 8:			*sib |= 0300;			break;		}	    }	    *v_sib = 1;	/* Done with SIB */	}	/* Calculate displacement length (if possible) */	retval = x86_checkea_calc_displen(ep, 4, basereg == REG3264_NONE,	    basereg == REG3264_EBP || basereg == REG64_R13, displen, modrm,	    v_modrm);	if (wrt)	    *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt, (*ep)->line);	return retval;    } else if (*addrsize == 16 && *n_modrm && !*v_modrm) {	static const unsigned char modrm16[16] = {	    0006 /* disp16  */, 0007 /* [BX]    */, 0004 /* [SI]    */,	    0000 /* [BX+SI] */, 0005 /* [DI]    */, 0001 /* [BX+DI] */,	    0377 /* invalid */, 0377 /* invalid */, 0006 /* [BP]+d  */,	    0377 /* invalid */, 0002 /* [BP+SI] */, 0377 /* invalid */,	    0003 /* [BP+DI] */, 0377 /* invalid */, 0377 /* invalid */,	    0377 /* invalid */	};	x86_checkea_reg16_data reg16mult = {0, 0, 0, 0};	enum {	    HAVE_NONE = 0,	    HAVE_BX = 1<<0,	    HAVE_SI = 1<<1,	    HAVE_DI = 1<<2,	    HAVE_BP = 1<<3	} havereg = HAVE_NONE;	/* 64-bit mode does not allow 16-bit addresses */	if (bits == 64) {	    yasm__error(e->line,		N_("16-bit addresses not supported in 64-bit mode"));	    return 1;	}	/* 16-bit cannot have SIB */	*sib = 0;	*v_sib = 0;	*n_sib = 0;	switch (x86_expr_checkea_getregusage(ep, &wrt, (int *)NULL, pcrel,					     bits, &reg16mult,					     x86_expr_checkea_get_reg16,					     calc_bc_dist)) {	    case 1:		e = *ep;		yasm__error(e->line, N_("invalid effective address"));		return 1;	    case 2:		if (wrt)		    *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt,						(*ep)->line);		return 2;	    default:		e = *ep;		break;	}	/* reg multipliers not 0 or 1 are illegal. */	if (reg16mult.bx & ~1 || reg16mult.si & ~1 || reg16mult.di & ~1 ||	    reg16mult.bp & ~1) {	    yasm__error(e->line, N_("invalid effective address"));	    return 1;	}	/* Set havereg appropriately */	if (reg16mult.bx > 0)	    havereg |= HAVE_BX;	if (reg16mult.si > 0)	    havereg |= HAVE_SI;	if (reg16mult.di > 0)	    havereg |= HAVE_DI;	if (reg16mult.bp > 0)	    havereg |= HAVE_BP;	/* Check the modrm value for invalid combinations. */	if (modrm16[havereg] & 0070) {	    yasm__error(e->line, N_("invalid effective address"));	    return 1;	}	/* Set ModRM byte for registers */	*modrm |= modrm16[havereg];	/* Calculate displacement length (if possible) */	retval = x86_checkea_calc_displen(ep, 2, havereg == HAVE_NONE,					  havereg == HAVE_BP, displen, modrm,					  v_modrm);	if (wrt)	    *ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt, (*ep)->line);	return retval;    } else if (!*n_modrm && !*n_sib) {	/* Special case for MOV MemOffs opcode: displacement but no modrm. */	switch (*addrsize) {	    case 64:		if (bits != 64) {		    yasm__error(e->line,			N_("invalid effective address (64-bit in non-64-bit mode)"));		    return 1;		}		*displen = 8;		break;	    case 32:		*displen = 4;		break;	    case 16:		/* 64-bit mode does not allow 16-bit addresses */		if (bits == 64) {		    yasm__error(e->line,			N_("16-bit addresses not supported in 64-bit mode"));		    return 1;		}		*displen = 2;		break;	}    }    if (wrt)	*ep = yasm_expr_create_tree(*ep, YASM_EXPR_WRT, wrt, (*ep)->line);    return 0;}intyasm_x86__floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt,			   unsigned char *buf, size_t destsize, size_t valsize,			   size_t shift, int warn, unsigned long line){    if (!yasm_floatnum_check_size(flt, valsize)) {	yasm__error(line, N_("invalid floating point constant size"));	return 1;    }    yasm_floatnum_get_sized(flt, buf, destsize, valsize, shift, 0, warn, line);    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -