12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061 |
- /*
- * x86 expression handling
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
- #include <util.h>
- #include <libyasm.h>
- #include "x86arch.h"
- typedef struct x86_checkea_reg3264_data {
- int *regs; /* total multiplier for each reg */
- unsigned char vsib_mode;
- unsigned char bits;
- unsigned char addrsize;
- } x86_checkea_reg3264_data;
- /* Only works if ei->type == EXPR_REG (doesn't check).
- * Overwrites ei with intnum of 0 (to eliminate regs from the final expr).
- */
- static /*@null@*/ /*@dependent@*/ int *
- x86_expr_checkea_get_reg3264(yasm_expr__item *ei, int *regnum,
- /*returned*/ void *d)
- {
- x86_checkea_reg3264_data *data = d;
- switch ((x86_expritem_reg_size)(ei->data.reg & ~0xFUL)) {
- case X86_REG32:
- if (data->addrsize != 32)
- return 0;
- *regnum = (unsigned int)(ei->data.reg & 0xF);
- break;
- case X86_REG64:
- if (data->addrsize != 64)
- return 0;
- *regnum = (unsigned int)(ei->data.reg & 0xF);
- break;
- case X86_XMMREG:
- if (data->vsib_mode != 1)
- return 0;
- if (data->bits != 64 && (ei->data.reg & 0x8) == 0x8)
- return 0;
- *regnum = 17+(unsigned int)(ei->data.reg & 0xF);
- break;
- case X86_YMMREG:
- if (data->vsib_mode != 2)
- return 0;
- if (data->bits != 64 && (ei->data.reg & 0x8) == 0x8)
- return 0;
- *regnum = 17+(unsigned int)(ei->data.reg & 0xF);
- break;
- case X86_RIP:
- if (data->bits != 64)
- return 0;
- *regnum = 16;
- break;
- default:
- return 0;
- }
- /* overwrite with 0 to eliminate register from displacement expr */
- ei->type = YASM_EXPR_INT;
- ei->data.intn = yasm_intnum_create_uint(0);
- /* we're okay */
- return &data->regs[*regnum];
- }
- typedef struct x86_checkea_reg16_data {
- int bx, si, di, bp; /* total multiplier for each reg */
- } x86_checkea_reg16_data;
- /* Only works if ei->type == EXPR_REG (doesn't check).
- * Overwrites ei with intnum of 0 (to eliminate regs from the final expr).
- */
- static /*@null@*/ int *
- x86_expr_checkea_get_reg16(yasm_expr__item *ei, int *regnum, void *d)
- {
- x86_checkea_reg16_data *data = d;
- /* in order: ax,cx,dx,bx,sp,bp,si,di */
- /*@-nullassign@*/
- static int *reg16[8] = {0,0,0,0,0,0,0,0};
- /*@=nullassign@*/
- reg16[3] = &data->bx;
- reg16[5] = &data->bp;
- reg16[6] = &data->si;
- reg16[7] = &data->di;
- /* don't allow 32-bit registers */
- if ((ei->data.reg & ~0xFUL) != X86_REG16)
- return 0;
- /* & 7 for sanity check */
- *regnum = (unsigned int)(ei->data.reg & 0x7);
- /* only allow BX, SI, DI, BP */
- if (!reg16[*regnum])
- return 0;
- /* overwrite with 0 to eliminate register from displacement expr */
- ei->type = YASM_EXPR_INT;
- ei->data.intn = yasm_intnum_create_uint(0);
- /* we're okay */
- return reg16[*regnum];
- }
- /* Distribute over registers to help bring them to the topmost level of e.
- * Also check for illegal operations against registers.
- * Returns 0 if something was illegal, 1 if legal and nothing in e changed,
- * and 2 if legal and e needs to be simplified.
- *
- * Only half joking: Someday make this/checkea able to accept crazy things
- * like: (bx+di)*(bx+di)-bx*bx-2*bx*di-di*di+di? Probably not: NASM never
- * accepted such things, and it's doubtful such an expn is valid anyway
- * (even though the above one is). But even macros would be hard-pressed
- * to generate something like this.
- *
- * e must already have been simplified for this function to work properly
- * (as it doesn't think things like SUB are valid).
- *
- * IMPLEMENTATION NOTE: About the only thing this function really needs to
- * "distribute" is: (non-float-expn or intnum) * (sum expn of registers).
- *
- * TODO: Clean up this code, make it easier to understand.
- */
- static int
- x86_expr_checkea_distcheck_reg(yasm_expr **ep, unsigned int bits)
- {
- yasm_expr *e = *ep;
- int i;
- int havereg = -1, havereg_expr = -1;
- int retval = 1; /* default to legal, no changes */
- for (i=0; i<e->numterms; i++) {
- switch (e->terms[i].type) {
- case YASM_EXPR_REG:
- /* Check op to make sure it's valid to use w/register. */
- switch (e->op) {
- case YASM_EXPR_MUL:
- /* Check for reg*reg */
- if (havereg != -1)
- return 0;
- break;
- case YASM_EXPR_ADD:
- case YASM_EXPR_IDENT:
- break;
- default:
- return 0;
- }
- havereg = i;
- break;
- case YASM_EXPR_FLOAT:
- /* Floats not allowed. */
- return 0;
- case YASM_EXPR_EXPR:
- if (yasm_expr__contains(e->terms[i].data.expn,
- YASM_EXPR_REG)) {
- int ret2;
- /* Check op to make sure it's valid to use w/register. */
- if (e->op != YASM_EXPR_ADD && e->op != YASM_EXPR_MUL)
- return 0;
- /* Check for reg*reg */
- if (e->op == YASM_EXPR_MUL && havereg != -1)
- return 0;
- havereg = i;
- havereg_expr = i;
- /* Recurse to check lower levels */
- ret2 =
- x86_expr_checkea_distcheck_reg(&e->terms[i].data.expn,
- bits);
- if (ret2 == 0)
- return 0;
- if (ret2 == 2)
- retval = 2;
- } else if (yasm_expr__contains(e->terms[i].data.expn,
- YASM_EXPR_FLOAT))
- return 0; /* Disallow floats */
- break;
- default:
- break;
- }
- }
- /* just exit if no registers were used */
- if (havereg == -1)
- return retval;
- /* Distribute */
- if (e->op == YASM_EXPR_MUL && havereg_expr != -1) {
- yasm_expr *ne;
- retval = 2; /* we're going to change it */
- /* The reg expn *must* be EXPR_ADD at this point. Sanity check. */
- if (e->terms[havereg_expr].type != YASM_EXPR_EXPR ||
- e->terms[havereg_expr].data.expn->op != YASM_EXPR_ADD)
- yasm_internal_error(N_("Register expression not ADD or EXPN"));
- /* Iterate over each term in reg expn */
- for (i=0; i<e->terms[havereg_expr].data.expn->numterms; i++) {
- /* Copy everything EXCEPT havereg_expr term into new expression */
- ne = yasm_expr__copy_except(e, havereg_expr);
- assert(ne != NULL);
- /* Copy reg expr term into uncopied (empty) term in new expn */
- ne->terms[havereg_expr] =
- e->terms[havereg_expr].data.expn->terms[i]; /* struct copy */
- /* Overwrite old reg expr term with new expn */
- e->terms[havereg_expr].data.expn->terms[i].type = YASM_EXPR_EXPR;
- e->terms[havereg_expr].data.expn->terms[i].data.expn = ne;
- }
- /* Replace e with expanded reg expn */
- ne = e->terms[havereg_expr].data.expn;
- e->terms[havereg_expr].type = YASM_EXPR_NONE; /* don't delete it! */
- yasm_expr_destroy(e); /* but everything else */
- e = ne;
- /*@-onlytrans@*/
- *ep = ne;
- /*@=onlytrans@*/
- }
- return retval;
- }
- /* Simplify and determine if expression is superficially valid:
- * Valid expr should be [(int-equiv expn)]+[reg*(int-equiv expn)+...]
- * where the [...] parts are optional.
- *
- * Don't simplify out constant identities if we're looking for an indexreg: we
- * may need the multiplier for determining what the indexreg is!
- *
- * Returns 1 if invalid register usage, 2 if unable to determine all values,
- * and 0 if all values successfully determined and saved in data.
- */
- static int
- x86_expr_checkea_getregusage(yasm_expr **ep, /*@null@*/ int *indexreg,
- int *pcrel, unsigned int bits, void *data,
- int *(*get_reg)(yasm_expr__item *ei, int *regnum, void *d))
- {
- int i;
- int *reg;
- int regnum;
- int indexval = 0;
- int indexmult = 0;
- yasm_expr *e, *wrt;
- /*@-unqualifiedtrans@*/
- *ep = yasm_expr__level_tree(*ep, 1, 1, indexreg == 0, 0, NULL, NULL);
- /* Check for WRT rip first */
- wrt = yasm_expr_extract_wrt(ep);
- if (wrt && wrt->op == YASM_EXPR_IDENT &&
- wrt->terms[0].type == YASM_EXPR_REG) {
- if (bits != 64) { /* only valid in 64-bit mode */
- yasm_expr_destroy(wrt);
- return 1;
- }
- reg = get_reg(&wrt->terms[0], ®num, data);
- if (!reg || regnum != 16) { /* only accept rip */
- yasm_expr_destroy(wrt);
- return 1;
- }
- (*reg)++;
- /* Delete WRT. Set pcrel to 1 to indicate to x86
- * bytecode code to do PC-relative displacement transform.
- */
- *pcrel = 1;
- yasm_expr_destroy(wrt);
- } else if (wrt) {
- yasm_expr_destroy(wrt);
- return 1;
- }
- /*@=unqualifiedtrans@*/
- assert(*ep != NULL);
- e = *ep;
- switch (x86_expr_checkea_distcheck_reg(ep, bits)) {
- case 0:
- return 1;
- case 2:
- /* Need to simplify again */
- *ep = yasm_expr__level_tree(*ep, 1, 1, indexreg == 0, 0, NULL,
- NULL);
- e = *ep;
- break;
- default:
- break;
- }
- switch (e->op) {
- case YASM_EXPR_ADD:
- /* Prescan for non-int multipliers against a reg.
- * This is invalid due to the optimizer structure.
- */
- for (i=0; i<e->numterms; i++)
- if (e->terms[i].type == YASM_EXPR_EXPR) {
- yasm_expr__order_terms(e->terms[i].data.expn);
- if (e->terms[i].data.expn->terms[0].type ==
- YASM_EXPR_REG) {
- if (e->terms[i].data.expn->numterms > 2)
- return 1;
- if (e->terms[i].data.expn->terms[1].type !=
- YASM_EXPR_INT)
- return 1;
- }
- }
- /*@fallthrough@*/
- case YASM_EXPR_IDENT:
- /* Check each term for register (and possible multiplier). */
- for (i=0; i<e->numterms; i++) {
- if (e->terms[i].type == YASM_EXPR_REG) {
- reg = get_reg(&e->terms[i], ®num, data);
- if (!reg)
- return 1;
- (*reg)++;
- /* Let last, largest multipler win indexreg */
- if (indexreg && *reg > 0 && indexval <= *reg &&
- !indexmult) {
- *indexreg = regnum;
- indexval = *reg;
- }
- } else if (e->terms[i].type == YASM_EXPR_EXPR) {
- /* Already ordered from ADD above, just grab the value.
- * Sanity check for EXPR_INT.
- */
- if (e->terms[i].data.expn->terms[0].type ==
- YASM_EXPR_REG) {
- long delta;
- if (e->terms[i].data.expn->terms[1].type !=
- YASM_EXPR_INT)
- yasm_internal_error(
- N_("Non-integer value in reg expn"));
- reg = get_reg(&e->terms[i].data.expn->terms[0],
- ®num, data);
- if (!reg)
- return 1;
- delta = yasm_intnum_get_int(
- e->terms[i].data.expn->terms[1].data.intn);
- (*reg) += delta;
- /* Let last, largest multipler win indexreg */
- if (indexreg && delta > 0 && indexval <= *reg) {
- *indexreg = regnum;
- indexval = *reg;
- indexmult = 1;
- } else if (indexreg && *indexreg == regnum &&
- delta < 0 && *reg <= 1) {
- *indexreg = -1;
- indexval = 0;
- indexmult = 0;
- }
- }
- }
- }
- break;
- case YASM_EXPR_MUL:
- /* Here, too, check for non-int multipliers against a reg. */
- yasm_expr__order_terms(e);
- if (e->terms[0].type == YASM_EXPR_REG) {
- long delta;
- if (e->numterms > 2)
- return 1;
- if (e->terms[1].type != YASM_EXPR_INT)
- return 1;
- reg = get_reg(&e->terms[0], ®num, data);
- if (!reg)
- return 1;
- delta = yasm_intnum_get_int(e->terms[1].data.intn);
- (*reg) += delta;
- if (indexreg)
- {
- if (delta < 0 && *reg <= 1)
- {
- *indexreg = -1;
- indexval = 0;
- indexmult = 0;
- }
- else
- *indexreg = regnum;
- }
- }
- break;
- case YASM_EXPR_SEGOFF:
- /* No registers are allowed on either side. */
- if (yasm_expr__contains(e, YASM_EXPR_REG))
- return 1;
- break;
- default:
- /* Should never get here! */
- yasm_internal_error(N_("unexpected expr op"));
- }
- /* Simplify expr, which is now really just the displacement. This
- * should get rid of the 0's we put in for registers in the callback.
- */
- *ep = yasm_expr_simplify(*ep, 0);
- /* e = *ep; */
- return 0;
- }
- /* Calculate the displacement length, if possible.
- * Takes several extra inputs so it can be used by both 32-bit and 16-bit
- * expressions:
- * wordsize=16 for 16-bit, =32 for 32-bit.
- * noreg=1 if the *ModRM byte* has no registers used.
- * dispreq=1 if a displacement value is *required* (even if =0).
- * Returns 0 if successfully calculated, 1 if not.
- */
- /*@-nullstate@*/
- static int
- x86_checkea_calc_displen(x86_effaddr *x86_ea, unsigned int wordsize, int noreg,
- int dispreq)
- {
- /*@null@*/ /*@only@*/ yasm_intnum *num;
- x86_ea->valid_modrm = 0; /* default to not yet valid */
- switch (x86_ea->ea.disp.size) {
- case 0:
- break;
- /* If not 0, the displacement length was forced; set the Mod bits
- * appropriately and we're done with the ModRM byte.
- */
- case 8:
- /* Byte is only a valid override if there are registers in the
- * EA. With no registers, we must have a 16/32 value.
- */
- if (noreg) {
- yasm_warn_set(YASM_WARN_IMPLICIT_SIZE_OVERRIDE,
- N_("invalid displacement size; fixed"));
- x86_ea->ea.disp.size = wordsize;
- } else
- x86_ea->modrm |= 0100;
- x86_ea->valid_modrm = 1;
- return 0;
- case 16:
- case 32:
- /* Don't allow changing displacement different from BITS setting
- * directly; require an address-size override to change it.
- */
- if (wordsize != x86_ea->ea.disp.size) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("invalid effective address (displacement size)"));
- return 1;
- }
- if (!noreg)
- x86_ea->modrm |= 0200;
- x86_ea->valid_modrm = 1;
- return 0;
- default:
- /* we shouldn't ever get any other size! */
- yasm_internal_error(N_("strange EA displacement size"));
- }
- /* The displacement length hasn't been forced (or the forcing wasn't
- * valid), try to determine what it is.
- */
- if (noreg) {
- /* No register in ModRM expression, so it must be disp16/32,
- * and as the Mod bits are set to 0 by the caller, we're done
- * with the ModRM byte.
- */
- x86_ea->ea.disp.size = wordsize;
- x86_ea->valid_modrm = 1;
- return 0;
- }
- if (dispreq) {
- /* for BP/EBP, there *must* be a displacement value, but we
- * may not know the size (8 or 16/32) for sure right now.
- */
- x86_ea->ea.need_nonzero_len = 1;
- }
- if (x86_ea->ea.disp.rel) {
- /* Relative displacement; basically all object formats need non-byte
- * for relocation here, so just do that. (TODO: handle this
- * differently?)
- */
- x86_ea->ea.disp.size = wordsize;
- x86_ea->modrm |= 0200;
- x86_ea->valid_modrm = 1;
- return 0;
- }
- /* At this point there's 3 possibilities for the displacement:
- * - None (if =0)
- * - signed 8 bit (if in -128 to 127 range)
- * - 16/32 bit (word size)
- * For now, check intnum value right now; if it's not 0,
- * assume 8 bit and set up for allowing 16 bit later.
- * FIXME: The complex expression equaling zero is probably a rare case,
- * so we ignore it for now.
- */
- num = yasm_value_get_intnum(&x86_ea->ea.disp, NULL, 0);
- if (!num) {
- /* Still has unknown values. */
- x86_ea->ea.need_nonzero_len = 1;
- x86_ea->modrm |= 0100;
- x86_ea->valid_modrm = 1;
- return 0;
- }
- /* Figure out what size displacement we will have. */
- if (yasm_intnum_is_zero(num) && !x86_ea->ea.need_nonzero_len) {
- /* If we know that the displacement is 0 right now,
- * go ahead and delete the expr and make 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!
- */
- yasm_value_delete(&x86_ea->ea.disp);
- x86_ea->ea.need_disp = 0;
- } else if (yasm_intnum_in_range(num, -128, 127)) {
- /* It fits into a signed byte */
- x86_ea->ea.disp.size = 8;
- x86_ea->modrm |= 0100;
- } else {
- /* It's a 16/32-bit displacement */
- x86_ea->ea.disp.size = wordsize;
- x86_ea->modrm |= 0200;
- }
- x86_ea->valid_modrm = 1; /* We're done with ModRM */
- yasm_intnum_destroy(num);
- return 0;
- }
- /*@=nullstate@*/
- static int
- x86_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;
- }
- int
- yasm_x86__expr_checkea(x86_effaddr *x86_ea, unsigned char *addrsize,
- unsigned int bits, int address16_op, unsigned char *rex,
- yasm_bytecode *bc)
- {
- int retval;
- 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 (x86_ea->ea.disp.size) {
- case 16:
- /* must be 16-bit */
- *addrsize = 16;
- break;
- case 64:
- /* We have to support this for the MemOffs case, but it's
- * otherwise illegal. It's also illegal in non-64-bit mode.
- */
- if (x86_ea->need_modrm || x86_ea->need_sib) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("invalid effective address (displacement size)"));
- return 1;
- }
- *addrsize = 64;
- break;
- case 32:
- /* 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 || (!x86_ea->need_modrm && !x86_ea->need_sib)) {
- *addrsize = 32;
- break;
- }
- /*@fallthrough@*/
- default:
- /* If SIB is required, but we're in 16-bit mode, set to 32. */
- if (bits == 16 && x86_ea->need_sib == 1) {
- *addrsize = 32;
- break;
- }
- /* check for use of 16 or 32-bit registers; if none are used
- * default to bits setting.
- */
- if (!x86_ea->ea.disp.abs ||
- !yasm_expr__traverse_leaves_in(x86_ea->ea.disp.abs,
- 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) &&
- ((x86_ea->need_modrm && !x86_ea->valid_modrm) ||
- (x86_ea->need_sib && !x86_ea->valid_sib))) {
- int i;
- unsigned char low3;
- 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,
- SIMDREGS
- };
- int reg3264mult[33] =
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 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) */
- int regcount = 17; /* normally don't check SIMD regs */
- if (x86_ea->vsib_mode != 0)
- regcount = 33;
- /* We can only do 64-bit addresses in 64-bit mode. */
- if (*addrsize == 64 && bits != 64) {
- yasm_error_set(YASM_ERROR_TYPE,
- N_("invalid effective address (64-bit in non-64-bit mode)"));
- return 1;
- }
- if (x86_ea->ea.pc_rel && bits != 64) {
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("RIP-relative directive ignored in non-64-bit mode"));
- x86_ea->ea.pc_rel = 0;
- }
- reg3264_data.regs = reg3264mult;
- reg3264_data.vsib_mode = x86_ea->vsib_mode;
- reg3264_data.bits = bits;
- reg3264_data.addrsize = *addrsize;
- if (x86_ea->ea.disp.abs) {
- int pcrel = 0;
- switch (x86_expr_checkea_getregusage
- (&x86_ea->ea.disp.abs, &indexreg, &pcrel, bits,
- ®3264_data, x86_expr_checkea_get_reg3264)) {
- case 1:
- yasm_error_set(YASM_ERROR_VALUE,
- N_("invalid effective address"));
- return 1;
- case 2:
- if (pcrel)
- yasm_value_set_curpos_rel(&x86_ea->ea.disp, bc, 1);
- return 2;
- default:
- if (pcrel)
- yasm_value_set_curpos_rel(&x86_ea->ea.disp, bc, 1);
- 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<regcount; i++) {
- if (reg3264mult[i] < 0) {
- yasm_error_set(YASM_ERROR_VALUE,
- 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;
- }
- if (x86_ea->vsib_mode != 0) {
- /* For VSIB, the SIMD register needs to go into the indexreg.
- * Also check basereg (must be a GPR if present) and indexreg
- * (must be a SIMD register).
- */
- if (basereg >= SIMDREGS &&
- (indexreg == REG3264_NONE || reg3264mult[indexreg] == 1)) {
- int temp = basereg;
- basereg = indexreg;
- indexreg = temp;
- }
- if (basereg >= REG64_RIP || indexreg < SIMDREGS) {
- yasm_error_set(YASM_ERROR_VALUE,
- N_("invalid effective address"));
- return 1;
- }
- } else if (indexreg != REG3264_NONE && basereg == REG3264_NONE)
- /* Handle certain special cases of indexreg mults when basereg is
- * empty.
- */
- switch (reg3264mult[indexreg]) {
- case 1:
- /* Only optimize this way if nosplit wasn't specified */
- if (!x86_ea->ea.nosplit) {
- basereg = indexreg;
- indexreg = -1;
- }
- break;
- case 2:
- /* Only split if nosplit wasn't specified */
- if (!x86_ea->ea.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<regcount; i++)
- if (i != basereg && i != indexreg && reg3264mult[i] != 0) {
- yasm_error_set(YASM_ERROR_VALUE,
- 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_set(YASM_ERROR_VALUE, 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_set(YASM_ERROR_VALUE,
- 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_set(YASM_ERROR_VALUE, 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.
- */
- /* If we're supposed to be RIP-relative and there's no register
- * usage, change to RIP-relative.
- */
- if (basereg == REG3264_NONE && indexreg == REG3264_NONE &&
- x86_ea->ea.pc_rel) {
- basereg = REG64_RIP;
- yasm_value_set_curpos_rel(&x86_ea->ea.disp, bc, 1);
- }
- /* First determine R/M (Mod is later determined from disp size) */
- x86_ea->need_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) {
- x86_ea->modrm |= 4;
- x86_ea->need_sib = 1;
- } else {
- x86_ea->modrm |= 5;
- x86_ea->sib = 0;
- x86_ea->valid_sib = 0;
- x86_ea->need_sib = 0;
- }
- } else if (basereg == REG64_RIP) {
- x86_ea->modrm |= 5;
- x86_ea->sib = 0;
- x86_ea->valid_sib = 0;
- x86_ea->need_sib = 0;
- /* RIP always requires a 32-bit displacement */
- x86_ea->valid_modrm = 1;
- x86_ea->ea.disp.size = 32;
- 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))
- return 1;
- x86_ea->modrm |= low3;
- /* we don't need an SIB *unless* basereg is ESP or R12 */
- if (basereg == REG3264_ESP || basereg == REG64_R12)
- x86_ea->need_sib = 1;
- else {
- x86_ea->sib = 0;
- x86_ea->valid_sib = 0;
- x86_ea->need_sib = 0;
- }
- } else {
- /* index or both base and index */
- x86_ea->modrm |= 4;
- x86_ea->need_sib = 1;
- }
- /* Determine SIB if needed */
- if (x86_ea->need_sib == 1) {
- x86_ea->sib = 0; /* start with 0 */
- /* Special case: no basereg */
- if (basereg == REG3264_NONE)
- x86_ea->sib |= 5;
- else {
- if (yasm_x86__set_rex_from_reg(rex, &low3, (unsigned int)
- (X86_REG64 | basereg), bits,
- X86_REX_B))
- return 1;
- x86_ea->sib |= low3;
- }
-
- /* Put in indexreg, checking for none case */
- if (indexreg == REG3264_NONE)
- x86_ea->sib |= 040;
- /* Any scale field is valid, just leave at 0. */
- else {
- if (indexreg >= SIMDREGS) {
- if (yasm_x86__set_rex_from_reg(rex, &low3,
- (unsigned int)(X86_XMMREG | (indexreg-SIMDREGS)),
- bits, X86_REX_X))
- return 1;
- } else {
- if (yasm_x86__set_rex_from_reg(rex, &low3,
- (unsigned int)(X86_REG64 | indexreg),
- bits, X86_REX_X))
- return 1;
- }
- x86_ea->sib |= low3 << 3;
- /* Set scale field, 1 case -> 0, so don't bother. */
- switch (reg3264mult[indexreg]) {
- case 2:
- x86_ea->sib |= 0100;
- break;
- case 4:
- x86_ea->sib |= 0200;
- break;
- case 8:
- x86_ea->sib |= 0300;
- break;
- }
- }
- x86_ea->valid_sib = 1; /* Done with SIB */
- }
- /* Calculate displacement length (if possible) */
- retval = x86_checkea_calc_displen
- (x86_ea, 32, basereg == REG3264_NONE,
- basereg == REG3264_EBP || basereg == REG64_R13);
- return retval;
- } else if (*addrsize == 16 && x86_ea->need_modrm && !x86_ea->valid_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 && !address16_op) {
- yasm_error_set(YASM_ERROR_TYPE,
- N_("16-bit addresses not supported in 64-bit mode"));
- return 1;
- }
- /* 16-bit cannot have SIB */
- x86_ea->sib = 0;
- x86_ea->valid_sib = 0;
- x86_ea->need_sib = 0;
- if (x86_ea->ea.disp.abs) {
- int pcrel = 0;
- switch (x86_expr_checkea_getregusage
- (&x86_ea->ea.disp.abs, (int *)NULL, &pcrel, bits,
- ®16mult, x86_expr_checkea_get_reg16)) {
- case 1:
- yasm_error_set(YASM_ERROR_VALUE,
- N_("invalid effective address"));
- return 1;
- case 2:
- if (pcrel)
- yasm_value_set_curpos_rel(&x86_ea->ea.disp, bc, 1);
- return 2;
- default:
- if (pcrel)
- yasm_value_set_curpos_rel(&x86_ea->ea.disp, bc, 1);
- break;
- }
- }
- /* reg multipliers not 0 or 1 are illegal. */
- if (reg16mult.bx & ~1 || reg16mult.si & ~1 || reg16mult.di & ~1 ||
- reg16mult.bp & ~1) {
- yasm_error_set(YASM_ERROR_VALUE, 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_set(YASM_ERROR_VALUE, N_("invalid effective address"));
- return 1;
- }
- /* Set ModRM byte for registers */
- x86_ea->modrm |= modrm16[havereg];
- /* Calculate displacement length (if possible) */
- retval = x86_checkea_calc_displen
- (x86_ea, 16, havereg == HAVE_NONE, havereg == HAVE_BP);
- return retval;
- } else if (!x86_ea->need_modrm && !x86_ea->need_sib) {
- /* Special case for MOV MemOffs opcode: displacement but no modrm. */
- switch (*addrsize) {
- case 64:
- if (bits != 64) {
- yasm_error_set(YASM_ERROR_TYPE,
- N_("invalid effective address (64-bit in non-64-bit mode)"));
- return 1;
- }
- x86_ea->ea.disp.size = 64;
- break;
- case 32:
- x86_ea->ea.disp.size = 32;
- break;
- case 16:
- /* 64-bit mode does not allow 16-bit addresses */
- if (bits == 64 && !address16_op) {
- yasm_error_set(YASM_ERROR_TYPE,
- N_("16-bit addresses not supported in 64-bit mode"));
- return 1;
- }
- x86_ea->ea.disp.size = 16;
- break;
- }
- }
- return 0;
- }
- int
- yasm_x86__floatnum_tobytes(yasm_arch *arch, const yasm_floatnum *flt,
- unsigned char *buf, size_t destsize, size_t valsize,
- size_t shift, int warn)
- {
- if (!yasm_floatnum_check_size(flt, valsize)) {
- yasm_error_set(YASM_ERROR_FLOATING_POINT,
- N_("invalid floating point constant size"));
- return 1;
- }
- yasm_floatnum_get_sized(flt, buf, destsize, valsize, shift, 0, warn);
- return 0;
- }
|