Thu Mar 26 23:07:18 1998 Alan Modra <alan@spri.levels.unisa.edu.au>

* config/tc-i386.c (md_assemble): Swap template arguments to
	CONSISTENT_REGISTER_MATCH macro in reverse direction test.
	This macro is currently symmetric, so passing them the wrong
	way didn't cause any problem, but may if the macro is changed
	in the future.
	After copying template to i.tm, use i.tm. rather than t-> to
	access fields, and make t a const*
	Move i.tm.operand_types[] swap to immediately after the copy.
This commit is contained in:
Ian Lance Taylor
1998-03-27 04:10:05 +00:00
parent 411589588a
commit 227b6b55fa
2 changed files with 84 additions and 76 deletions

View File

@ -1,3 +1,14 @@
Thu Mar 26 23:07:18 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
* config/tc-i386.c (md_assemble): Swap template arguments to
CONSISTENT_REGISTER_MATCH macro in reverse direction test.
This macro is currently symmetric, so passing them the wrong
way didn't cause any problem, but may if the macro is changed
in the future.
After copying template to i.tm, use i.tm. rather than t-> to
access fields, and make t a const*
Move i.tm.operand_types[] swap to immediately after the copy.
start-sanitize-sky start-sanitize-sky
Thu Mar 26 13:29:59 1998 Doug Evans <devans@canuck.cygnus.com> Thu Mar 26 13:29:59 1998 Doug Evans <devans@canuck.cygnus.com>

View File

@ -834,8 +834,8 @@ void
md_assemble (line) md_assemble (line)
char *line; char *line;
{ {
/* Holds template once we've found it. */ /* Points to template once we've found it. */
template *t; const template *t;
/* Count the size of the instruction generated. */ /* Count the size of the instruction generated. */
int insn_size = 0; int insn_size = 0;
@ -853,7 +853,7 @@ md_assemble (line)
memset (im_expressions, '\0', sizeof (im_expressions)); memset (im_expressions, '\0', sizeof (im_expressions));
save_stack_p = save_stack; /* reset stack pointer */ save_stack_p = save_stack; /* reset stack pointer */
/* Fist parse an opcode & call i386_operand for the operands. /* First parse an opcode & call i386_operand for the operands.
We assume that the scrubber has arranged it so that line[0] is the valid We assume that the scrubber has arranged it so that line[0] is the valid
start of a (possibly prefixed) opcode. */ start of a (possibly prefixed) opcode. */
{ {
@ -1132,8 +1132,8 @@ md_assemble (line)
if (!MATCH (overlap0, i.types[0]) || if (!MATCH (overlap0, i.types[0]) ||
!MATCH (overlap1, i.types[1]) || !MATCH (overlap1, i.types[1]) ||
!CONSISTENT_REGISTER_MATCH (overlap0, overlap1, !CONSISTENT_REGISTER_MATCH (overlap0, overlap1,
t->operand_types[0], t->operand_types[1],
t->operand_types[1])) t->operand_types[0]))
{ {
/* does not match either direction */ /* does not match either direction */
continue; continue;
@ -1168,18 +1168,23 @@ md_assemble (line)
/* Copy the template we found (we may change it!). */ /* Copy the template we found (we may change it!). */
i.tm = *t; i.tm = *t;
t = &i.tm; /* alter new copy of template */
if (found_reverse_match)
{
i.tm.operand_types[0] = t->operand_types[1];
i.tm.operand_types[1] = t->operand_types[0];
}
/* If the matched instruction specifies an explicit opcode suffix, /* If the matched instruction specifies an explicit opcode suffix,
use it - and make sure none has already been specified. */ use it - and make sure none has already been specified. */
if (t->opcode_modifier & (Data16|Data32)) if (i.tm.opcode_modifier & (Data16|Data32))
{ {
if (i.suffix) if (i.suffix)
{ {
as_bad ("extraneous opcode suffix given"); as_bad ("extraneous opcode suffix given");
return; return;
} }
if (t->opcode_modifier & Data16) if (i.tm.opcode_modifier & Data16)
i.suffix = WORD_OPCODE_SUFFIX; i.suffix = WORD_OPCODE_SUFFIX;
else else
i.suffix = DWORD_OPCODE_SUFFIX; i.suffix = DWORD_OPCODE_SUFFIX;
@ -1276,19 +1281,11 @@ md_assemble (line)
if (overlap0 & Imm1) if (overlap0 & Imm1)
i.imm_operands = 0; /* kludge for shift insns */ i.imm_operands = 0; /* kludge for shift insns */
if (found_reverse_match)
{
unsigned int save;
save = t->operand_types[0];
t->operand_types[0] = t->operand_types[1];
t->operand_types[1] = save;
}
/* Finalize opcode. First, we change the opcode based on the operand /* Finalize opcode. First, we change the opcode based on the operand
size given by i.suffix: we never have to change things for byte insns, size given by i.suffix: we never have to change things for byte insns,
or when no opcode suffix is need to size the operands. */ or when no opcode suffix is need to size the operands. */
if (!i.suffix && (t->opcode_modifier & W)) if (!i.suffix && (i.tm.opcode_modifier & W))
{ {
as_bad ("no opcode suffix given and no register operands; can't size instruction"); as_bad ("no opcode suffix given and no register operands; can't size instruction");
return; return;
@ -1297,15 +1294,15 @@ md_assemble (line)
if (i.suffix && i.suffix != BYTE_OPCODE_SUFFIX) if (i.suffix && i.suffix != BYTE_OPCODE_SUFFIX)
{ {
/* Select between byte and word/dword operations. */ /* Select between byte and word/dword operations. */
if (t->opcode_modifier & W) if (i.tm.opcode_modifier & W)
t->base_opcode |= W; i.tm.base_opcode |= W;
/* Now select between word & dword operations via the /* Now select between word & dword operations via the
operand size prefix. */ operand size prefix. */
if ((i.suffix == WORD_OPCODE_SUFFIX) ^ flag_16bit_code) if ((i.suffix == WORD_OPCODE_SUFFIX) ^ flag_16bit_code)
{ {
if (i.prefixes == MAX_PREFIXES) if (i.prefixes == MAX_PREFIXES)
{ {
as_bad ("%d prefixes given and 'w' opcode suffix gives too many prefixes", as_bad ("%d prefixes given and data size prefix gives too many prefixes",
MAX_PREFIXES); MAX_PREFIXES);
return; return;
} }
@ -1332,12 +1329,12 @@ md_assemble (line)
if (found_reverse_match) if (found_reverse_match)
{ {
t->base_opcode |= found_reverse_match; i.tm.base_opcode |= found_reverse_match;
} }
/* The imul $imm, %reg instruction is converted into /* The imul $imm, %reg instruction is converted into
imul $imm, %reg, %reg. */ imul $imm, %reg, %reg. */
if (t->opcode_modifier & imulKludge) if (i.tm.opcode_modifier & imulKludge)
{ {
/* Pretend we saw the 3 operand case. */ /* Pretend we saw the 3 operand case. */
i.regs[2] = i.regs[1]; i.regs[2] = i.regs[1];
@ -1345,7 +1342,7 @@ md_assemble (line)
} }
/* The clr %reg instruction is converted into xor %reg, %reg. */ /* The clr %reg instruction is converted into xor %reg, %reg. */
if (t->opcode_modifier & iclrKludge) if (i.tm.opcode_modifier & iclrKludge)
{ {
i.regs[1] = i.regs[0]; i.regs[1] = i.regs[0];
i.reg_operands = 2; i.reg_operands = 2;
@ -1356,7 +1353,7 @@ md_assemble (line)
instructions, if the source operand is a register, we must reverse instructions, if the source operand is a register, we must reverse
the i.rm.reg and i.rm.regmem fields. We accomplish this by faking the i.rm.reg and i.rm.regmem fields. We accomplish this by faking
that the two register operands were given in the reverse order. */ that the two register operands were given in the reverse order. */
if ((t->opcode_modifier & ReverseRegRegmem) && i.reg_operands == 2) if ((i.tm.opcode_modifier & ReverseRegRegmem) && i.reg_operands == 2)
{ {
unsigned int first_reg_operand = (i.types[0] & Reg) ? 0 : 1; unsigned int first_reg_operand = (i.types[0] & Reg) ? 0 : 1;
unsigned int second_reg_operand = first_reg_operand + 1; unsigned int second_reg_operand = first_reg_operand + 1;
@ -1365,40 +1362,40 @@ md_assemble (line)
i.regs[second_reg_operand] = tmp; i.regs[second_reg_operand] = tmp;
} }
if (t->opcode_modifier & ShortForm) if (i.tm.opcode_modifier & ShortForm)
{ {
/* The register or float register operand is in operand 0 or 1. */ /* The register or float register operand is in operand 0 or 1. */
unsigned int op = (i.types[0] & (Reg | FloatReg)) ? 0 : 1; unsigned int op = (i.types[0] & (Reg | FloatReg)) ? 0 : 1;
/* Register goes in low 3 bits of opcode. */ /* Register goes in low 3 bits of opcode. */
t->base_opcode |= i.regs[op]->reg_num; i.tm.base_opcode |= i.regs[op]->reg_num;
} }
else if (t->opcode_modifier & ShortFormW) else if (i.tm.opcode_modifier & ShortFormW)
{ {
/* Short form with 0x8 width bit. Register is always dest. operand */ /* Short form with 0x8 width bit. Register is always dest. operand */
t->base_opcode |= i.regs[1]->reg_num; i.tm.base_opcode |= i.regs[1]->reg_num;
if (i.suffix == WORD_OPCODE_SUFFIX || if (i.suffix == WORD_OPCODE_SUFFIX ||
i.suffix == DWORD_OPCODE_SUFFIX) i.suffix == DWORD_OPCODE_SUFFIX)
t->base_opcode |= 0x8; i.tm.base_opcode |= 0x8;
} }
else if (t->opcode_modifier & Seg2ShortForm) else if (i.tm.opcode_modifier & Seg2ShortForm)
{ {
if (t->base_opcode == POP_SEG_SHORT && i.regs[0]->reg_num == 1) if (i.tm.base_opcode == POP_SEG_SHORT && i.regs[0]->reg_num == 1)
{ {
as_bad ("you can't 'pop cs' on the 386."); as_bad ("you can't 'pop cs' on the 386.");
return; return;
} }
t->base_opcode |= (i.regs[0]->reg_num << 3); i.tm.base_opcode |= (i.regs[0]->reg_num << 3);
} }
else if (t->opcode_modifier & Seg3ShortForm) else if (i.tm.opcode_modifier & Seg3ShortForm)
{ {
/* 'push %fs' is 0x0fa0; 'pop %fs' is 0x0fa1. /* 'push %fs' is 0x0fa0; 'pop %fs' is 0x0fa1.
'push %gs' is 0x0fa8; 'pop %fs' is 0x0fa9. 'push %gs' is 0x0fa8; 'pop %fs' is 0x0fa9.
So, only if i.regs[0]->reg_num == 5 (%gs) do we need So, only if i.regs[0]->reg_num == 5 (%gs) do we need
to change the opcode. */ to change the opcode. */
if (i.regs[0]->reg_num == 5) if (i.regs[0]->reg_num == 5)
t->base_opcode |= 0x08; i.tm.base_opcode |= 0x08;
} }
else if ((t->base_opcode & ~DW) == MOV_AX_DISP32) else if ((i.tm.base_opcode & ~DW) == MOV_AX_DISP32)
{ {
/* This is a special non-modrm instruction /* This is a special non-modrm instruction
that addresses memory with a 32-bit displacement mode anyway, that addresses memory with a 32-bit displacement mode anyway,
@ -1406,12 +1403,12 @@ md_assemble (line)
uses_mem_addrmode = 1; uses_mem_addrmode = 1;
default_seg = &ds; default_seg = &ds;
} }
else if (t->opcode_modifier & Modrm) else if (i.tm.opcode_modifier & Modrm)
{ {
/* The opcode is completed (modulo t->extension_opcode which must /* The opcode is completed (modulo i.tm.extension_opcode which
be put into the modrm byte. must be put into the modrm byte).
Now, we make the modrm & index base bytes based on all the info Now, we make the modrm & index base bytes based on all the
we've collected. */ info we've collected. */
/* i.reg_operands MUST be the number of real register operands; /* i.reg_operands MUST be the number of real register operands;
implicit registers do not count. */ implicit registers do not count. */
@ -1564,10 +1561,10 @@ md_assemble (line)
} }
/* Fill in i.rm.reg or i.rm.regmem field with register /* Fill in i.rm.reg or i.rm.regmem field with register
operand (if any) based on operand (if any) based on i.tm.extension_opcode.
t->extension_opcode. Again, we must be careful to Again, we must be careful to make sure that
make sure that segment/control/debug/test/MMX segment/control/debug/test/MMX registers are coded
registers are coded into the i.rm.reg field. */ into the i.rm.reg field. */
if (i.reg_operands) if (i.reg_operands)
{ {
unsigned int op = unsigned int op =
@ -1582,7 +1579,7 @@ md_assemble (line)
: 2)); : 2));
/* If there is an extension opcode to put here, the /* If there is an extension opcode to put here, the
register number must be put into the regmem field. */ register number must be put into the regmem field. */
if (t->extension_opcode != None) if (i.tm.extension_opcode != None)
i.rm.regmem = i.regs[op]->reg_num; i.rm.regmem = i.regs[op]->reg_num;
else else
i.rm.reg = i.regs[op]->reg_num; i.rm.reg = i.regs[op]->reg_num;
@ -1595,8 +1592,8 @@ md_assemble (line)
} }
/* Fill in i.rm.reg field with extension opcode (if any). */ /* Fill in i.rm.reg field with extension opcode (if any). */
if (t->extension_opcode != None) if (i.tm.extension_opcode != None)
i.rm.reg = t->extension_opcode; i.rm.reg = i.tm.extension_opcode;
} }
if (i.rm.mode != 3) if (i.rm.mode != 3)
@ -1637,9 +1634,9 @@ md_assemble (line)
} }
/* Handle conversion of 'int $3' --> special int3 insn. */ /* Handle conversion of 'int $3' --> special int3 insn. */
if (t->base_opcode == INT_OPCODE && i.imms[0]->X_add_number == 3) if (i.tm.base_opcode == INT_OPCODE && i.imms[0]->X_add_number == 3)
{ {
t->base_opcode = INT3_OPCODE; i.tm.base_opcode = INT3_OPCODE;
i.imm_operands = 0; i.imm_operands = 0;
} }
@ -1648,7 +1645,7 @@ md_assemble (line)
register char *p; register char *p;
/* Output jumps. */ /* Output jumps. */
if (t->opcode_modifier & Jump) if (i.tm.opcode_modifier & Jump)
{ {
unsigned long n = i.disps[0]->X_add_number; unsigned long n = i.disps[0]->X_add_number;
@ -1658,7 +1655,7 @@ md_assemble (line)
{ {
p = frag_more (2); p = frag_more (2);
insn_size += 2; insn_size += 2;
p[0] = t->base_opcode; p[0] = i.tm.base_opcode;
p[1] = n; p[1] = n;
} }
else else
@ -1675,7 +1672,7 @@ md_assemble (line)
return; return;
} }
if (t->base_opcode == JUMP_PC_RELATIVE) if (i.tm.base_opcode == JUMP_PC_RELATIVE)
{ /* pace */ { /* pace */
/* unconditional jump */ /* unconditional jump */
p = frag_more (1 + jmp_size); p = frag_more (1 + jmp_size);
@ -1689,7 +1686,7 @@ md_assemble (line)
p = frag_more (2 + jmp_size); p = frag_more (2 + jmp_size);
insn_size += 2 + jmp_size; insn_size += 2 + jmp_size;
p[0] = TWO_BYTE_OPCODE_ESCAPE; p[0] = TWO_BYTE_OPCODE_ESCAPE;
p[1] = t->base_opcode + 0x10; p[1] = i.tm.base_opcode + 0x10;
md_number_to_chars (&p[2], (valueT) n, jmp_size); md_number_to_chars (&p[2], (valueT) n, jmp_size);
} }
} }
@ -1708,7 +1705,7 @@ md_assemble (line)
frag_grow (7); frag_grow (7);
p = frag_more (1); p = frag_more (1);
insn_size += 1; insn_size += 1;
p[0] = t->base_opcode; p[0] = i.tm.base_opcode;
frag_var (rs_machine_dependent, frag_var (rs_machine_dependent,
6, /* 2 opcode/prefix + 4 displacement */ 6, /* 2 opcode/prefix + 4 displacement */
1, 1,
@ -1719,9 +1716,9 @@ md_assemble (line)
(offsetT) n, p); (offsetT) n, p);
} }
} }
else if (t->opcode_modifier & (JumpByte | JumpDword)) else if (i.tm.opcode_modifier & (JumpByte | JumpDword))
{ {
int size = (t->opcode_modifier & JumpByte) ? 1 : 4; int size = (i.tm.opcode_modifier & JumpByte) ? 1 : 4;
unsigned long n = i.disps[0]->X_add_number; unsigned long n = i.disps[0]->X_add_number;
unsigned char *q; unsigned char *q;
@ -1748,8 +1745,8 @@ md_assemble (line)
want to emit WORD_PREFIX_OPCODE, but I am keeping want to emit WORD_PREFIX_OPCODE, but I am keeping
the old behaviour for safety. */ the old behaviour for safety. */
if (IS_JUMP_ON_CX_ZERO (t->base_opcode) if (IS_JUMP_ON_CX_ZERO (i.tm.base_opcode)
|| IS_LOOP_ECX_TIMES (t->base_opcode)) || IS_LOOP_ECX_TIMES (i.tm.base_opcode))
FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE); FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE);
else else
FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE); FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE);
@ -1764,9 +1761,9 @@ md_assemble (line)
insn_size += 1; insn_size += 1;
} }
if (fits_in_unsigned_byte (t->base_opcode)) if (fits_in_unsigned_byte (i.tm.base_opcode))
{ {
FRAG_APPEND_1_CHAR (t->base_opcode); FRAG_APPEND_1_CHAR (i.tm.base_opcode);
insn_size += 1; insn_size += 1;
} }
else else
@ -1774,8 +1771,8 @@ md_assemble (line)
p = frag_more (2); /* opcode can be at most two bytes */ p = frag_more (2); /* opcode can be at most two bytes */
insn_size += 2; insn_size += 2;
/* put out high byte first: can't use md_number_to_chars! */ /* put out high byte first: can't use md_number_to_chars! */
*p++ = (t->base_opcode >> 8) & 0xff; *p++ = (i.tm.base_opcode >> 8) & 0xff;
*p = t->base_opcode & 0xff; *p = i.tm.base_opcode & 0xff;
} }
p = frag_more (size); p = frag_more (size);
@ -1796,7 +1793,7 @@ md_assemble (line)
} }
} }
else if (t->opcode_modifier & JumpInterSegment) else if (i.tm.opcode_modifier & JumpInterSegment)
{ {
if (flag_16bit_code) if (flag_16bit_code)
{ {
@ -1806,7 +1803,7 @@ md_assemble (line)
p = frag_more (1 + 2 + 4); /* 1 opcode; 2 segment; 4 offset */ p = frag_more (1 + 2 + 4); /* 1 opcode; 2 segment; 4 offset */
insn_size += 1 + 2 + 4; insn_size += 1 + 2 + 4;
p[0] = t->base_opcode; p[0] = i.tm.base_opcode;
if (i.imms[1]->X_op == O_constant) if (i.imms[1]->X_op == O_constant)
md_number_to_chars (p + 1, (valueT) i.imms[1]->X_add_number, 4); md_number_to_chars (p + 1, (valueT) i.imms[1]->X_add_number, 4);
else else
@ -1830,39 +1827,39 @@ md_assemble (line)
} }
/* Now the opcode; be careful about word order here! */ /* Now the opcode; be careful about word order here! */
if (fits_in_unsigned_byte (t->base_opcode)) if (fits_in_unsigned_byte (i.tm.base_opcode))
{ {
FRAG_APPEND_1_CHAR (t->base_opcode); FRAG_APPEND_1_CHAR (i.tm.base_opcode);
insn_size += 1; insn_size += 1;
} }
else if (fits_in_unsigned_word (t->base_opcode)) else if (fits_in_unsigned_word (i.tm.base_opcode))
{ {
p = frag_more (2); p = frag_more (2);
insn_size += 2; insn_size += 2;
/* put out high byte first: can't use md_number_to_chars! */ /* put out high byte first: can't use md_number_to_chars! */
*p++ = (t->base_opcode >> 8) & 0xff; *p++ = (i.tm.base_opcode >> 8) & 0xff;
*p = t->base_opcode & 0xff; *p = i.tm.base_opcode & 0xff;
} }
else else
{ /* opcode is either 3 or 4 bytes */ { /* opcode is either 3 or 4 bytes */
if (t->base_opcode & 0xff000000) if (i.tm.base_opcode & 0xff000000)
{ {
p = frag_more (4); p = frag_more (4);
insn_size += 4; insn_size += 4;
*p++ = (t->base_opcode >> 24) & 0xff; *p++ = (i.tm.base_opcode >> 24) & 0xff;
} }
else else
{ {
p = frag_more (3); p = frag_more (3);
insn_size += 3; insn_size += 3;
} }
*p++ = (t->base_opcode >> 16) & 0xff; *p++ = (i.tm.base_opcode >> 16) & 0xff;
*p++ = (t->base_opcode >> 8) & 0xff; *p++ = (i.tm.base_opcode >> 8) & 0xff;
*p = (t->base_opcode) & 0xff; *p = (i.tm.base_opcode) & 0xff;
} }
/* Now the modrm byte and base index byte (if present). */ /* Now the modrm byte and base index byte (if present). */
if (t->opcode_modifier & Modrm) if (i.tm.opcode_modifier & Modrm)
{ {
p = frag_more (1); p = frag_more (1);
insn_size += 1; insn_size += 1;