Rename jmprel->jmp, JMPREL->JMP, JR->JMP, and others, as FAR jumps are not

relative jumps.

svn path=/trunk/yasm/; revision=956
0.3
Peter Johnson 22 years ago
parent 05222986bc
commit 8422252781
  1. 28
      modules/arch/x86/x86arch.h
  2. 316
      modules/arch/x86/x86bc.c
  3. 44
      modules/arch/x86/x86id.re

@ -29,9 +29,9 @@
typedef enum {
X86_BC_INSN = YASM_BYTECODE_TYPE_BASE,
X86_BC_JMPREL
X86_BC_JMP
} x86_bytecode_type;
#define X86_BYTECODE_TYPE_MAX X86_BC_JMPREL+1
#define X86_BYTECODE_TYPE_MAX X86_BC_JMP+1
/* 0-15 (low 4 bits) used for register number, stored in same data area.
* Note 8-15 are only valid for some registers, and only in 64-bit mode.
@ -65,13 +65,13 @@ typedef enum {
} x86_parse_targetmod;
typedef enum {
JR_NONE,
JR_SHORT,
JR_NEAR,
JR_SHORT_FORCED,
JR_NEAR_FORCED,
JR_FAR /* not really relative, but fits here */
} x86_jmprel_opcode_sel;
JMP_NONE,
JMP_SHORT,
JMP_NEAR,
JMP_SHORT_FORCED,
JMP_NEAR_FORCED,
JMP_FAR /* not really relative, but fits here */
} x86_jmp_opcode_sel;
typedef enum {
X86_REX_W = 3,
@ -130,14 +130,14 @@ typedef struct x86_new_insn_data {
yasm_bytecode *yasm_x86__bc_new_insn(x86_new_insn_data *d);
/* Structure with *all* inputs passed to x86_bytecode_new_jmprel().
/* Structure with *all* inputs passed to x86_bytecode_new_jmp().
* Pass 0 for the opcode_len if that version of the opcode doesn't exist.
*/
typedef struct x86_new_jmprel_data {
typedef struct x86_new_jmp_data {
unsigned long lindex;
/*@keep@*/ yasm_expr *target;
/*@dependent@*/ yasm_symrec *origin;
x86_jmprel_opcode_sel op_sel;
x86_jmp_opcode_sel op_sel;
unsigned char short_op_len;
unsigned char short_op[3];
unsigned char near_op_len;
@ -146,9 +146,9 @@ typedef struct x86_new_jmprel_data {
unsigned char far_op[3];
unsigned char addrsize;
unsigned char opersize;
} x86_new_jmprel_data;
} x86_new_jmp_data;
yasm_bytecode *yasm_x86__bc_new_jmprel(x86_new_jmprel_data *d);
yasm_bytecode *yasm_x86__bc_new_jmp(x86_new_jmp_data *d);
extern unsigned char yasm_x86_LTX_mode_bits;

@ -94,7 +94,7 @@ typedef struct x86_insn {
unsigned char mode_bits;
} x86_insn;
typedef struct x86_jmprel {
typedef struct x86_jmp {
yasm_bytecode bc; /* base structure */
yasm_expr *target; /* target location */
@ -107,14 +107,14 @@ typedef struct x86_jmprel {
/* which opcode are we using? */
/* The *FORCED forms are specified in the source as such */
x86_jmprel_opcode_sel op_sel;
x86_jmp_opcode_sel op_sel;
unsigned char addrsize; /* 0 or =mode_bits => no override */
unsigned char opersize; /* 0 indicates no override */
unsigned char lockrep_pre; /* 0 indicates no prefix */
unsigned char mode_bits;
} x86_jmprel;
} x86_jmp;
int
@ -184,47 +184,46 @@ yasm_x86__bc_new_insn(x86_new_insn_data *d)
/*@-compmempass -mustfree@*/
yasm_bytecode *
yasm_x86__bc_new_jmprel(x86_new_jmprel_data *d)
yasm_x86__bc_new_jmp(x86_new_jmp_data *d)
{
x86_jmprel *jmprel;
x86_jmp *jmp;
jmprel = (x86_jmprel *)
yasm_bc_new_common((yasm_bytecode_type)X86_BC_JMPREL,
sizeof(x86_jmprel), d->lindex);
jmp = (x86_jmp *) yasm_bc_new_common((yasm_bytecode_type)X86_BC_JMP,
sizeof(x86_jmp), d->lindex);
jmprel->target = d->target;
jmprel->origin = d->origin;
jmprel->op_sel = d->op_sel;
jmp->target = d->target;
jmp->origin = d->origin;
jmp->op_sel = d->op_sel;
if ((d->op_sel == JR_SHORT_FORCED) && (d->near_op_len == 0))
if ((d->op_sel == JMP_SHORT_FORCED) && (d->near_op_len == 0))
yasm__error(d->lindex,
N_("no SHORT form of that jump instruction exists"));
if ((d->op_sel == JR_NEAR_FORCED) && (d->short_op_len == 0))
if ((d->op_sel == JMP_NEAR_FORCED) && (d->short_op_len == 0))
yasm__error(d->lindex,
N_("no NEAR form of that jump instruction exists"));
jmprel->shortop.opcode[0] = d->short_op[0];
jmprel->shortop.opcode[1] = d->short_op[1];
jmprel->shortop.opcode[2] = d->short_op[2];
jmprel->shortop.opcode_len = d->short_op_len;
jmp->shortop.opcode[0] = d->short_op[0];
jmp->shortop.opcode[1] = d->short_op[1];
jmp->shortop.opcode[2] = d->short_op[2];
jmp->shortop.opcode_len = d->short_op_len;
jmprel->nearop.opcode[0] = d->near_op[0];
jmprel->nearop.opcode[1] = d->near_op[1];
jmprel->nearop.opcode[2] = d->near_op[2];
jmprel->nearop.opcode_len = d->near_op_len;
jmp->nearop.opcode[0] = d->near_op[0];
jmp->nearop.opcode[1] = d->near_op[1];
jmp->nearop.opcode[2] = d->near_op[2];
jmp->nearop.opcode_len = d->near_op_len;
jmprel->farop.opcode[0] = d->far_op[0];
jmprel->farop.opcode[1] = d->far_op[1];
jmprel->farop.opcode[2] = d->far_op[2];
jmprel->farop.opcode_len = d->far_op_len;
jmp->farop.opcode[0] = d->far_op[0];
jmp->farop.opcode[1] = d->far_op[1];
jmp->farop.opcode[2] = d->far_op[2];
jmp->farop.opcode_len = d->far_op_len;
jmprel->addrsize = d->addrsize;
jmprel->opersize = d->opersize;
jmprel->lockrep_pre = 0;
jmp->addrsize = d->addrsize;
jmp->opersize = d->opersize;
jmp->lockrep_pre = 0;
jmprel->mode_bits = yasm_x86_LTX_mode_bits;
jmp->mode_bits = yasm_x86_LTX_mode_bits;
return (yasm_bytecode *)jmprel;
return (yasm_bytecode *)jmp;
}
/*@=compmempass =mustfree@*/
@ -343,7 +342,7 @@ void
yasm_x86__bc_insn_opersize_override(yasm_bytecode *bc, unsigned int opersize)
{
x86_insn *insn;
x86_jmprel *jmprel;
x86_jmp *jmp;
if (!bc)
return;
@ -353,9 +352,9 @@ yasm_x86__bc_insn_opersize_override(yasm_bytecode *bc, unsigned int opersize)
insn = (x86_insn *)bc;
insn->opersize = (unsigned char)opersize;
break;
case X86_BC_JMPREL:
jmprel = (x86_jmprel *)bc;
jmprel->opersize = (unsigned char)opersize;
case X86_BC_JMP:
jmp = (x86_jmp *)bc;
jmp->opersize = (unsigned char)opersize;
break;
default:
yasm_internal_error(
@ -367,7 +366,7 @@ void
yasm_x86__bc_insn_addrsize_override(yasm_bytecode *bc, unsigned int addrsize)
{
x86_insn *insn;
x86_jmprel *jmprel;
x86_jmp *jmp;
if (!bc)
return;
@ -377,9 +376,9 @@ yasm_x86__bc_insn_addrsize_override(yasm_bytecode *bc, unsigned int addrsize)
insn = (x86_insn *)bc;
insn->addrsize = (unsigned char)addrsize;
break;
case X86_BC_JMPREL:
jmprel = (x86_jmprel *)bc;
jmprel->addrsize = (unsigned char)addrsize;
case X86_BC_JMP:
jmp = (x86_jmp *)bc;
jmp->addrsize = (unsigned char)addrsize;
break;
default:
yasm_internal_error(
@ -392,7 +391,7 @@ yasm_x86__bc_insn_set_lockrep_prefix(yasm_bytecode *bc, unsigned int prefix,
unsigned long lindex)
{
x86_insn *insn;
x86_jmprel *jmprel;
x86_jmp *jmp;
unsigned char *lockrep_pre = (unsigned char *)NULL;
if (!bc)
@ -403,9 +402,9 @@ yasm_x86__bc_insn_set_lockrep_prefix(yasm_bytecode *bc, unsigned int prefix,
insn = (x86_insn *)bc;
lockrep_pre = &insn->lockrep_pre;
break;
case X86_BC_JMPREL:
jmprel = (x86_jmprel *)bc;
lockrep_pre = &jmprel->lockrep_pre;
case X86_BC_JMP:
jmp = (x86_jmp *)bc;
lockrep_pre = &jmp->lockrep_pre;
break;
default:
yasm_internal_error(
@ -423,7 +422,7 @@ void
yasm_x86__bc_delete(yasm_bytecode *bc)
{
x86_insn *insn;
x86_jmprel *jmprel;
x86_jmp *jmp;
switch ((x86_bytecode_type)bc->type) {
case X86_BC_INSN:
@ -435,9 +434,9 @@ yasm_x86__bc_delete(yasm_bytecode *bc)
yasm_xfree(insn->imm);
}
break;
case X86_BC_JMPREL:
jmprel = (x86_jmprel *)bc;
yasm_expr_delete(jmprel->target);
case X86_BC_JMP:
jmp = (x86_jmp *)bc;
yasm_expr_delete(jmp->target);
break;
}
}
@ -460,7 +459,7 @@ void
yasm_x86__bc_print(FILE *f, int indent_level, const yasm_bytecode *bc)
{
const x86_insn *insn;
const x86_jmprel *jmprel;
const x86_jmp *jmp;
switch ((x86_bytecode_type)bc->type) {
case X86_BC_INSN:
@ -504,49 +503,49 @@ yasm_x86__bc_print(FILE *f, int indent_level, const yasm_bytecode *bc)
(unsigned int)insn->shift_op,
(unsigned int)insn->mode_bits);
break;
case X86_BC_JMPREL:
jmprel = (const x86_jmprel *)bc;
case X86_BC_JMP:
jmp = (const x86_jmp *)bc;
fprintf(f, "%*s_Relative Jump_\n", indent_level, "");
fprintf(f, "%*sTarget=", indent_level, "");
yasm_expr_print(f, jmprel->target);
yasm_expr_print(f, jmp->target);
fprintf(f, "\n%*sShort Form:\n", indent_level, "");
if (jmprel->shortop.opcode_len == 0)
if (jmp->shortop.opcode_len == 0)
fprintf(f, "%*sNone\n", indent_level+1, "");
else
fprintf(f, "%*sOpcode: %02x %02x %02x OpLen=%u\n",
indent_level+1, "",
(unsigned int)jmprel->shortop.opcode[0],
(unsigned int)jmprel->shortop.opcode[1],
(unsigned int)jmprel->shortop.opcode[2],
(unsigned int)jmprel->shortop.opcode_len);
(unsigned int)jmp->shortop.opcode[0],
(unsigned int)jmp->shortop.opcode[1],
(unsigned int)jmp->shortop.opcode[2],
(unsigned int)jmp->shortop.opcode_len);
fprintf(f, "%*sNear Form:\n", indent_level, "");
if (jmprel->nearop.opcode_len == 0)
if (jmp->nearop.opcode_len == 0)
fprintf(f, "%*sNone\n", indent_level+1, "");
else
fprintf(f, "%*sOpcode: %02x %02x %02x OpLen=%u\n",
indent_level+1, "",
(unsigned int)jmprel->nearop.opcode[0],
(unsigned int)jmprel->nearop.opcode[1],
(unsigned int)jmprel->nearop.opcode[2],
(unsigned int)jmprel->nearop.opcode_len);
(unsigned int)jmp->nearop.opcode[0],
(unsigned int)jmp->nearop.opcode[1],
(unsigned int)jmp->nearop.opcode[2],
(unsigned int)jmp->nearop.opcode_len);
fprintf(f, "%*sOpSel=", indent_level, "");
switch (jmprel->op_sel) {
case JR_NONE:
switch (jmp->op_sel) {
case JMP_NONE:
fprintf(f, "None");
break;
case JR_SHORT:
case JMP_SHORT:
fprintf(f, "Short");
break;
case JR_NEAR:
case JMP_NEAR:
fprintf(f, "Near");
break;
case JR_SHORT_FORCED:
case JMP_SHORT_FORCED:
fprintf(f, "Forced Short");
break;
case JR_NEAR_FORCED:
case JMP_NEAR_FORCED:
fprintf(f, "Forced Near");
break;
case JR_FAR:
case JMP_FAR:
fprintf(f, "Far");
break;
default:
@ -555,11 +554,11 @@ yasm_x86__bc_print(FILE *f, int indent_level, const yasm_bytecode *bc)
}
fprintf(f, "\n%*sAddrSize=%u OperSize=%u LockRepPre=%02x\n",
indent_level, "",
(unsigned int)jmprel->addrsize,
(unsigned int)jmprel->opersize,
(unsigned int)jmprel->lockrep_pre);
(unsigned int)jmp->addrsize,
(unsigned int)jmp->opersize,
(unsigned int)jmp->lockrep_pre);
fprintf(f, "%*sBITS=%u\n", indent_level, "",
(unsigned int)jmprel->mode_bits);
(unsigned int)jmp->mode_bits);
break;
}
}
@ -678,32 +677,31 @@ x86_bc_resolve_insn(x86_insn *insn, unsigned long *len, int save,
}
static yasm_bc_resolve_flags
x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
const yasm_bytecode *bc, const yasm_section *sect,
yasm_calc_bc_dist_func calc_bc_dist)
x86_bc_resolve_jmp(x86_jmp *jmp, unsigned long *len, int save,
const yasm_bytecode *bc, const yasm_section *sect,
yasm_calc_bc_dist_func calc_bc_dist)
{
yasm_bc_resolve_flags retval = YASM_BC_RESOLVE_MIN_LEN;
/*@null@*/ yasm_expr *temp;
/*@dependent@*/ /*@null@*/ const yasm_intnum *num;
long rel;
unsigned char opersize;
x86_jmprel_opcode_sel jrtype = JR_NONE;
x86_jmp_opcode_sel jrtype = JMP_NONE;
/* As opersize may be 0, figure out its "real" value. */
opersize = (jmprel->opersize == 0) ? jmprel->mode_bits :
jmprel->opersize;
opersize = (jmp->opersize == 0) ? jmp->mode_bits : jmp->opersize;
/* We only check to see if forced forms are actually legal if we're in
* save mode. Otherwise we assume that they are legal.
*/
switch (jmprel->op_sel) {
case JR_SHORT_FORCED:
switch (jmp->op_sel) {
case JMP_SHORT_FORCED:
/* 1 byte relative displacement */
jrtype = JR_SHORT;
jrtype = JMP_SHORT;
if (save) {
temp = yasm_expr_copy(jmprel->target);
temp = yasm_expr_copy(jmp->target);
temp = yasm_expr_new(YASM_EXPR_SUB, yasm_expr_expr(temp),
yasm_expr_sym(jmprel->origin), bc->line);
yasm_expr_sym(jmp->origin), bc->line);
num = yasm_expr_get_intnum(&temp, calc_bc_dist);
if (!num) {
yasm__error(bc->line,
@ -712,10 +710,10 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
} else {
rel = yasm_intnum_get_int(num);
rel -= jmprel->shortop.opcode_len+1;
rel -= jmp->shortop.opcode_len+1;
yasm_expr_delete(temp);
/* does a short form exist? */
if (jmprel->shortop.opcode_len == 0) {
if (jmp->shortop.opcode_len == 0) {
yasm__error(bc->line, N_("short jump does not exist"));
return YASM_BC_RESOLVE_ERROR |
YASM_BC_RESOLVE_UNKNOWN_LEN;
@ -729,25 +727,25 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
}
}
break;
case JR_NEAR_FORCED:
case JMP_NEAR_FORCED:
/* 2/4 byte relative displacement (depending on operand size) */
jrtype = JR_NEAR;
jrtype = JMP_NEAR;
if (save) {
if (jmprel->nearop.opcode_len == 0) {
if (jmp->nearop.opcode_len == 0) {
yasm__error(bc->line, N_("near jump does not exist"));
return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
}
}
break;
default:
temp = yasm_expr_copy(jmprel->target);
temp = yasm_expr_copy(jmp->target);
temp = yasm_expr_simplify(temp, NULL);
/* Check for far displacement (seg:off). */
if (yasm_expr_is_op(temp, YASM_EXPR_SEGOFF)) {
jrtype = JR_FAR;
jrtype = JMP_FAR;
break; /* length handled below */
} else if (jmprel->op_sel == JR_FAR) {
} else if (jmp->op_sel == JMP_FAR) {
yasm__error(bc->line,
N_("far jump does not have a far displacement"));
return YASM_BC_RESOLVE_ERROR | YASM_BC_RESOLVE_UNKNOWN_LEN;
@ -759,22 +757,22 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
* this test to be valid.
*/
temp = yasm_expr_new(YASM_EXPR_SUB, yasm_expr_expr(temp),
yasm_expr_sym(jmprel->origin), bc->line);
yasm_expr_sym(jmp->origin), bc->line);
num = yasm_expr_get_intnum(&temp, calc_bc_dist);
if (num) {
rel = yasm_intnum_get_int(num);
rel -= jmprel->shortop.opcode_len+1;
rel -= jmp->shortop.opcode_len+1;
/* short displacement must fit within -128 <= rel <= +127 */
if (jmprel->shortop.opcode_len != 0 && rel >= -128 &&
if (jmp->shortop.opcode_len != 0 && rel >= -128 &&
rel <= 127) {
/* It fits into a short displacement. */
jrtype = JR_SHORT;
} else if (jmprel->nearop.opcode_len != 0) {
jrtype = JMP_SHORT;
} else if (jmp->nearop.opcode_len != 0) {
/* Near for now, but could get shorter in the future if
* there's a short form available.
*/
jrtype = JR_NEAR;
if (jmprel->shortop.opcode_len != 0)
jrtype = JMP_NEAR;
if (jmp->shortop.opcode_len != 0)
retval = YASM_BC_RESOLVE_NONE;
} else {
/* Doesn't fit into short, and there's no near opcode.
@ -788,17 +786,17 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
return YASM_BC_RESOLVE_ERROR |
YASM_BC_RESOLVE_UNKNOWN_LEN;
}
jrtype = JR_SHORT;
jrtype = JMP_SHORT;
}
} else {
/* It's unknown. Thus, assume near displacement. If a near
* opcode is not available, use a short opcode instead.
* If we're saving, error if a near opcode is not available.
*/
if (jmprel->nearop.opcode_len != 0) {
if (jmprel->shortop.opcode_len != 0)
if (jmp->nearop.opcode_len != 0) {
if (jmp->shortop.opcode_len != 0)
retval = YASM_BC_RESOLVE_NONE;
jrtype = JR_NEAR;
jrtype = JMP_NEAR;
} else {
if (save) {
yasm__error(bc->line,
@ -806,7 +804,7 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
return YASM_BC_RESOLVE_ERROR |
YASM_BC_RESOLVE_UNKNOWN_LEN;
}
jrtype = JR_SHORT;
jrtype = JMP_SHORT;
}
}
yasm_expr_delete(temp);
@ -814,41 +812,39 @@ x86_bc_resolve_jmprel(x86_jmprel *jmprel, unsigned long *len, int save,
}
switch (jrtype) {
case JR_SHORT:
case JMP_SHORT:
if (save)
jmprel->op_sel = JR_SHORT;
if (jmprel->shortop.opcode_len == 0)
jmp->op_sel = JMP_SHORT;
if (jmp->shortop.opcode_len == 0)
return YASM_BC_RESOLVE_UNKNOWN_LEN; /* size not available */
*len += jmprel->shortop.opcode_len + 1;
*len += jmp->shortop.opcode_len + 1;
break;
case JR_NEAR:
case JMP_NEAR:
if (save)
jmprel->op_sel = JR_NEAR;
if (jmprel->nearop.opcode_len == 0)
jmp->op_sel = JMP_NEAR;
if (jmp->nearop.opcode_len == 0)
return YASM_BC_RESOLVE_UNKNOWN_LEN; /* size not available */
*len += jmprel->nearop.opcode_len;
*len += jmp->nearop.opcode_len;
*len += (opersize == 32) ? 4 : 2;
break;
case JR_FAR:
case JMP_FAR:
if (save)
jmprel->op_sel = JR_FAR;
if (jmprel->farop.opcode_len == 0)
jmp->op_sel = JMP_FAR;
if (jmp->farop.opcode_len == 0)
return YASM_BC_RESOLVE_UNKNOWN_LEN; /* size not available */
*len += jmprel->farop.opcode_len;
*len += jmp->farop.opcode_len;
*len += 2; /* segment */
*len += (opersize == 32) ? 4 : 2;
break;
default:
yasm_internal_error(N_("unknown jump type"));
}
*len += (jmprel->addrsize != 0 && jmprel->addrsize != jmprel->mode_bits) ?
1:0;
*len += (jmprel->opersize != 0 && jmprel->opersize != jmprel->mode_bits) ?
1:0;
*len += (jmprel->lockrep_pre != 0) ? 1:0;
*len += (jmp->addrsize != 0 && jmp->addrsize != jmp->mode_bits) ? 1:0;
*len += (jmp->opersize != 0 && jmp->opersize != jmp->mode_bits) ? 1:0;
*len += (jmp->lockrep_pre != 0) ? 1:0;
return retval;
}
@ -861,9 +857,9 @@ yasm_x86__bc_resolve(yasm_bytecode *bc, int save, const yasm_section *sect,
case X86_BC_INSN:
return x86_bc_resolve_insn((x86_insn *)bc, &bc->len, save, sect,
calc_bc_dist);
case X86_BC_JMPREL:
return x86_bc_resolve_jmprel((x86_jmprel *)bc, &bc->len, save, bc,
sect, calc_bc_dist);
case X86_BC_JMP:
return x86_bc_resolve_jmp((x86_jmp *)bc, &bc->len, save, bc, sect,
calc_bc_dist);
default:
break;
}
@ -967,9 +963,9 @@ x86_bc_tobytes_insn(x86_insn *insn, unsigned char **bufp,
}
static int
x86_bc_tobytes_jmprel(x86_jmprel *jmprel, unsigned char **bufp,
const yasm_section *sect, yasm_bytecode *bc,
void *d, yasm_output_expr_func output_expr)
x86_bc_tobytes_jmp(x86_jmp *jmp, unsigned char **bufp,
const yasm_section *sect, yasm_bytecode *bc,
void *d, yasm_output_expr_func output_expr)
{
unsigned char opersize;
unsigned int i;
@ -977,76 +973,74 @@ x86_bc_tobytes_jmprel(x86_jmprel *jmprel, unsigned char **bufp,
/*@null@*/ yasm_expr *targetseg;
/* Prefixes */
if (jmprel->lockrep_pre != 0)
YASM_WRITE_8(*bufp, jmprel->lockrep_pre);
if (jmp->lockrep_pre != 0)
YASM_WRITE_8(*bufp, jmp->lockrep_pre);
/* FIXME: branch hints! */
if (jmprel->opersize != 0 && jmprel->opersize != jmprel->mode_bits)
if (jmp->opersize != 0 && jmp->opersize != jmp->mode_bits)
YASM_WRITE_8(*bufp, 0x66);
if (jmprel->addrsize != 0 && jmprel->addrsize != jmprel->mode_bits)
if (jmp->addrsize != 0 && jmp->addrsize != jmp->mode_bits)
YASM_WRITE_8(*bufp, 0x67);
/* As opersize may be 0, figure out its "real" value. */
opersize = (jmprel->opersize == 0) ? jmprel->mode_bits :
jmprel->opersize;
opersize = (jmp->opersize == 0) ? jmp->mode_bits : jmp->opersize;
/* Check here to see if forced forms are actually legal. */
switch (jmprel->op_sel) {
case JR_SHORT_FORCED:
case JR_SHORT:
switch (jmp->op_sel) {
case JMP_SHORT_FORCED:
case JMP_SHORT:
/* 1 byte relative displacement */
if (jmprel->shortop.opcode_len == 0)
if (jmp->shortop.opcode_len == 0)
yasm_internal_error(N_("short jump does not exist"));
/* Opcode */
for (i=0; i<jmprel->shortop.opcode_len; i++)
YASM_WRITE_8(*bufp, jmprel->shortop.opcode[i]);
for (i=0; i<jmp->shortop.opcode_len; i++)
YASM_WRITE_8(*bufp, jmp->shortop.opcode[i]);
/* Relative displacement */
jmprel->target =
yasm_expr_new(YASM_EXPR_SUB, yasm_expr_expr(jmprel->target),
yasm_expr_sym(jmprel->origin), bc->line);
if (output_expr(&jmprel->target, bufp, 1,
jmp->target =
yasm_expr_new(YASM_EXPR_SUB, yasm_expr_expr(jmp->target),
yasm_expr_sym(jmp->origin), bc->line);
if (output_expr(&jmp->target, bufp, 1,
(unsigned long)(*bufp-bufp_orig), sect, bc, 1, d))
return 1;
break;
case JR_NEAR_FORCED:
case JR_NEAR:
case JMP_NEAR_FORCED:
case JMP_NEAR:
/* 2/4 byte relative displacement (depending on operand size) */
if (jmprel->nearop.opcode_len == 0) {
if (jmp->nearop.opcode_len == 0) {
yasm__error(bc->line, N_("near jump does not exist"));
return 1;
}
/* Opcode */
for (i=0; i<jmprel->nearop.opcode_len; i++)
YASM_WRITE_8(*bufp, jmprel->nearop.opcode[i]);
for (i=0; i<jmp->nearop.opcode_len; i++)
YASM_WRITE_8(*bufp, jmp->nearop.opcode[i]);
/* Relative displacement */
jmprel->target =
yasm_expr_new(YASM_EXPR_SUB, yasm_expr_expr(jmprel->target),
yasm_expr_sym(jmprel->origin), bc->line);
if (output_expr(&jmprel->target, bufp,
(opersize == 32) ? 4UL : 2UL,
jmp->target =
yasm_expr_new(YASM_EXPR_SUB, yasm_expr_expr(jmp->target),
yasm_expr_sym(jmp->origin), bc->line);
if (output_expr(&jmp->target, bufp, (opersize == 32) ? 4UL : 2UL,
(unsigned long)(*bufp-bufp_orig), sect, bc, 1, d))
return 1;
break;
case JR_FAR:
case JMP_FAR:
/* far absolute (4/6 byte depending on operand size) */
if (jmprel->farop.opcode_len == 0) {
if (jmp->farop.opcode_len == 0) {
yasm__error(bc->line, N_("far jump does not exist"));
return 1;
}
/* Opcode */
for (i=0; i<jmprel->farop.opcode_len; i++)
YASM_WRITE_8(*bufp, jmprel->farop.opcode[i]);
for (i=0; i<jmp->farop.opcode_len; i++)
YASM_WRITE_8(*bufp, jmp->farop.opcode[i]);
/* Absolute displacement: segment and offset */
jmprel->target = yasm_expr_simplify(jmprel->target, NULL);
targetseg = yasm_expr_extract_segment(&jmprel->target);
jmp->target = yasm_expr_simplify(jmp->target, NULL);
targetseg = yasm_expr_extract_segment(&jmp->target);
if (!targetseg)
yasm_internal_error(N_("could not extract segment for far jump"));
if (output_expr(&jmprel->target, bufp,
if (output_expr(&jmp->target, bufp,
(opersize == 32) ? 4UL : 2UL,
(unsigned long)(*bufp-bufp_orig), sect, bc, 0, d))
return 1;
@ -1070,9 +1064,9 @@ yasm_x86__bc_tobytes(yasm_bytecode *bc, unsigned char **bufp,
case X86_BC_INSN:
return x86_bc_tobytes_insn((x86_insn *)bc, bufp, sect, bc, d,
output_expr);
case X86_BC_JMPREL:
return x86_bc_tobytes_jmprel((x86_jmprel *)bc, bufp, sect, bc, d,
output_expr);
case X86_BC_JMP:
return x86_bc_tobytes_jmp((x86_jmp *)bc, bufp, sect, bc, d,
output_expr);
default:
break;
}

@ -84,7 +84,7 @@ static unsigned long cpu_enabled = ~CPU_Any;
#define MOD_SpAdd (1UL<<5) /* Parameter adds to "spare" value */
#define MOD_OpSizeR (1UL<<6) /* Parameter replaces opersize */
#define MOD_Imm8 (1UL<<7) /* Parameter is included as immediate byte */
#define MOD_AdSizeR (1UL<<8) /* Parameter replaces addrsize (jmprel only) */
#define MOD_AdSizeR (1UL<<8) /* Parameter replaces addrsize (jmp only) */
/* Modifiers that aren't actually used as modifiers. Rather, if set, bits
* 20-27 in the modifier are used as an index into an array.
@ -155,8 +155,8 @@ static unsigned long cpu_enabled = ~CPU_Any;
* 6 = operand data is added to opcode byte 1
* 7 = operand data goes into BOTH ea and spare
* [special case for imul opcode]
* 8 = relative jump (outputs a jmprel instead of normal insn)
* 9 = operand size goes into address size (jmprel only)
* 8 = relative jump (outputs a jmp instead of normal insn)
* 9 = operand size goes into address size (jmp only)
* The below describes postponed actions: actions which can't be completed at
* parse-time due to things like EQU and complex expressions. For these, some
* additional data (stored in the second byte of the opcode with a one-byte
@ -1523,12 +1523,12 @@ static const x86_insn_info xbts_insn[] = {
static yasm_bytecode *
x86_new_jmprel(const unsigned long data[4], int num_operands,
yasm_insn_operandhead *operands, x86_insn_info *jrinfo,
yasm_section *cur_section, /*@null@*/ yasm_bytecode *prev_bc,
unsigned long lindex)
x86_new_jmp(const unsigned long data[4], int num_operands,
yasm_insn_operandhead *operands, x86_insn_info *jinfo,
yasm_section *cur_section, /*@null@*/ yasm_bytecode *prev_bc,
unsigned long lindex)
{
x86_new_jmprel_data d;
x86_new_jmp_data d;
int num_info = (int)(data[1]&0xFF);
x86_insn_info *info = (x86_insn_info *)data[0];
unsigned long mod_data = data[1] >> 8;
@ -1543,7 +1543,7 @@ x86_new_jmprel(const unsigned long data[4], int num_operands,
yasm_internal_error(N_("invalid operand conversion"));
/* Far target needs to become "seg imm:imm". */
if ((jrinfo->operands[0] & OPTM_MASK) == OPTM_Far)
if ((jinfo->operands[0] & OPTM_MASK) == OPTM_Far)
d.target = yasm_expr_new_tree(
yasm_expr_new_branch(YASM_EXPR_SEG, op->data.val, lindex),
YASM_EXPR_SEGOFF, yasm_expr_copy(op->data.val), lindex);
@ -1557,37 +1557,37 @@ x86_new_jmprel(const unsigned long data[4], int num_operands,
d.far_op_len = 0;
/* See if the user explicitly specified short/near/far. */
switch ((int)(jrinfo->operands[0] & OPTM_MASK)) {
switch ((int)(jinfo->operands[0] & OPTM_MASK)) {
case OPTM_Short:
d.op_sel = JR_SHORT_FORCED;
d.op_sel = JMP_SHORT_FORCED;
break;
case OPTM_Near:
d.op_sel = JR_NEAR_FORCED;
d.op_sel = JMP_NEAR_FORCED;
break;
case OPTM_Far:
d.op_sel = JR_FAR;
d.op_sel = JMP_FAR;
d.far_op_len = info->opcode_len;
d.far_op[0] = info->opcode[0];
d.far_op[1] = info->opcode[1];
d.far_op[2] = info->opcode[2];
break;
default:
d.op_sel = JR_NONE;
d.op_sel = JMP_NONE;
}
/* Set operand size */
d.opersize = jrinfo->opersize;
d.opersize = jinfo->opersize;
/* Check for address size setting in second operand, if present */
if (jrinfo->num_operands > 1 &&
(jrinfo->operands[1] & OPA_MASK) == OPA_AdSizeR)
d.addrsize = (unsigned char)size_lookup[(jrinfo->operands[1] &
if (jinfo->num_operands > 1 &&
(jinfo->operands[1] & OPA_MASK) == OPA_AdSizeR)
d.addrsize = (unsigned char)size_lookup[(jinfo->operands[1] &
OPS_MASK)>>OPS_SHIFT];
else
d.addrsize = 0;
/* Check for address size override */
if (jrinfo->modifiers & MOD_AdSizeR)
if (jinfo->modifiers & MOD_AdSizeR)
d.addrsize = (unsigned char)(mod_data & 0xFF);
/* Scan through other infos for this insn looking for short/near versions.
@ -1641,7 +1641,7 @@ x86_new_jmprel(const unsigned long data[4], int num_operands,
}
}
return yasm_x86__bc_new_jmprel(&d);
return yasm_x86__bc_new_jmp(&d);
}
yasm_bytecode *
@ -1943,8 +1943,8 @@ yasm_x86__parse_insn(const unsigned long data[4], int num_operands,
/* Shortcut to JmpRel */
if (operands && (info->operands[0] & OPA_MASK) == OPA_JmpRel)
return x86_new_jmprel(data, num_operands, operands, info, cur_section,
prev_bc, lindex);
return x86_new_jmp(data, num_operands, operands, info, cur_section,
prev_bc, lindex);
/* Copy what we can from info */
d.lindex = lindex;

Loading…
Cancel
Save