/* This array holds the chars that always start a comment. If the
pre-processor is disabled, these aren't very useful. */
-#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD))
+#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD) && !defined(TE_NetBSD))
/* Putting '/' here makes it impossible to use the divide operator.
However, we need it for compatibility with SVR4 systems. */
const char comment_chars[] = "#/";
#NO_APP at the beginning of its output.
Also note that comments started like this one will always work if
'/' isn't otherwise defined. */
-#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD))
+#if defined (TE_I386AIX) || ((defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && ! defined (TE_LINUX) && !defined(TE_FreeBSD) && !defined(TE_NetBSD))
const char line_comment_chars[] = "";
#else
const char line_comment_chars[] = "/";
figuring out what sort of jump to choose to reach a given label. */
/* Types. */
-#define UNCOND_JUMP 1
-#define COND_JUMP 2
-#define COND_JUMP86 3
+#define UNCOND_JUMP 0
+#define COND_JUMP 1
+#define COND_JUMP86 2
/* Sizes. */
#define CODE16 1
/* The fields are:
1) most positive reach of this state,
2) most negative reach of this state,
- 3) how many bytes this mode will add to the size of the current frag
+ 3) how many bytes this mode will have in the variable part of the frag
4) which index into the table to try if we can't fit into this one. */
- {1, 1, 0, 0},
- {1, 1, 0, 0},
- {1, 1, 0, 0},
- {1, 1, 0, 0},
/* UNCOND_JUMP states. */
- {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG)},
- {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16)},
- /* dword jmp adds 3 bytes to frag:
- 0 extra opcode bytes, 3 extra displacement bytes. */
- {0, 0, 3, 0},
- /* word jmp adds 1 byte to frag:
- 0 extra opcode bytes, 1 extra displacement byte. */
- {0, 0, 1, 0},
-
- /* COND_JUMP states. */
- {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (COND_JUMP, BIG)},
- {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (COND_JUMP, BIG16)},
- /* dword conditionals adds 4 bytes to frag:
- 1 extra opcode byte, 3 extra displacement bytes. */
+ {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG)},
+ {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (UNCOND_JUMP, BIG16)},
+ /* dword jmp adds 4 bytes to frag:
+ 0 extra opcode bytes, 4 displacement bytes. */
{0, 0, 4, 0},
- /* word conditionals add 2 bytes to frag:
- 1 extra opcode byte, 1 extra displacement byte. */
+ /* word jmp adds 2 byte2 to frag:
+ 0 extra opcode bytes, 2 displacement bytes. */
{0, 0, 2, 0},
- /* COND_JUMP86 states. */
- {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (COND_JUMP86, BIG)},
- {127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE (COND_JUMP86, BIG16)},
- /* dword conditionals adds 4 bytes to frag:
- 1 extra opcode byte, 3 extra displacement bytes. */
- {0, 0, 4, 0},
+ /* COND_JUMP states. */
+ {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG)},
+ {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP, BIG16)},
+ /* dword conditionals adds 5 bytes to frag:
+ 1 extra opcode byte, 4 displacement bytes. */
+ {0, 0, 5, 0},
/* word conditionals add 3 bytes to frag:
- 1 extra opcode byte, 2 extra displacement bytes. */
- {0, 0, 3, 0}
+ 1 extra opcode byte, 2 displacement bytes. */
+ {0, 0, 3, 0},
+
+ /* COND_JUMP86 states. */
+ {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG)},
+ {127 + 1, -128 + 1, 1, ENCODE_RELAX_STATE (COND_JUMP86, BIG16)},
+ /* dword conditionals adds 5 bytes to frag:
+ 1 extra opcode byte, 4 displacement bytes. */
+ {0, 0, 5, 0},
+ /* word conditionals add 4 bytes to frag:
+ 1 displacement byte and a 3 byte long branch insn. */
+ {0, 0, 4, 0}
};
static const arch_entry cpu_arch[] = {
/* Points to template once we've found it. */
const template *t;
- /* Count the size of the instruction generated. Does not include
- variable part of jump insns before relax. */
- int insn_size = 0;
-
int j;
char mnemonic[MAX_MNEM_SIZE];
}
if (!is_space_char (*l)
&& *l != END_OF_INSN
- && *l != PREFIX_SEPARATOR)
+ && *l != PREFIX_SEPARATOR
+ && *l != ',')
{
as_bad (_("invalid character %s in mnemonic"),
output_invalid (*l));
}
}
+ if (current_templates->start->opcode_modifier & (Jump | JumpByte))
+ {
+ /* Check for a branch hint. We allow ",pt" and ",pn" for
+ predict taken and predict not taken respectively.
+ I'm not sure that branch hints actually do anything on loop
+ and jcxz insns (JumpByte) for current Pentium4 chips. They
+ may work in the future and it doesn't hurt to accept them
+ now. */
+ if (l[0] == ',' && l[1] == 'p')
+ {
+ if (l[2] == 't')
+ {
+ if (! add_prefix (DS_PREFIX_OPCODE))
+ return;
+ l += 3;
+ }
+ else if (l[2] == 'n')
+ {
+ if (! add_prefix (CS_PREFIX_OPCODE))
+ return;
+ l += 3;
+ }
+ }
+ }
+ /* Any other comma loses. */
+ if (*l == ',')
+ {
+ as_bad (_("invalid character %s in mnemonic"),
+ output_invalid (*l));
+ return;
+ }
+
/* Check if instruction is supported on specified architecture. */
if (cpu_arch_flags != 0)
{
{
register char *p;
+ /* Tie dwarf2 debug info to the address at the start of the insn.
+ We can't do this after the insn has been output as the current
+ frag may have been closed off. eg. by frag_var. */
+ dwarf2_emit_insn (0);
+
/* Output jumps. */
if (i.tm.opcode_modifier & Jump)
{
i.prefixes -= 1;
code16 ^= CODE16;
}
+ /* Pentium4 branch hints. */
+ if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */
+ || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */)
+ {
+ prefix++;
+ i.prefixes--;
+ }
if (i.prefix[REX_PREFIX])
{
prefix++;
bytes for the opcode and room for the prefix and largest
displacement. */
frag_grow (prefix + 2 + 4);
- insn_size += prefix + 1;
/* Prefix and 1 opcode byte go in fr_fix. */
p = frag_more (prefix + 1);
if (i.prefix[DATA_PREFIX])
*p++ = DATA_PREFIX_OPCODE;
+ if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE
+ || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE)
+ *p++ = i.prefix[SEG_PREFIX];
if (i.prefix[REX_PREFIX])
*p++ = i.prefix[REX_PREFIX];
*p = i.tm.base_opcode;
size = 1;
if (i.prefix[ADDR_PREFIX])
{
- insn_size += 1;
FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE);
i.prefixes -= 1;
}
+ /* Pentium4 branch hints. */
+ if (i.prefix[SEG_PREFIX] == CS_PREFIX_OPCODE /* not taken */
+ || i.prefix[SEG_PREFIX] == DS_PREFIX_OPCODE /* taken */)
+ {
+ FRAG_APPEND_1_CHAR (i.prefix[SEG_PREFIX]);
+ i.prefixes--;
+ }
}
else
{
if (i.prefix[DATA_PREFIX])
{
- insn_size += 1;
FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE);
i.prefixes -= 1;
code16 ^= CODE16;
if (i.prefix[REX_PREFIX])
{
FRAG_APPEND_1_CHAR (i.prefix[REX_PREFIX]);
- insn_size++;
i.prefixes -= 1;
}
if (i.prefixes != 0 && !intel_syntax)
as_warn (_("skipping prefixes on this instruction"));
- if (fits_in_unsigned_byte (i.tm.base_opcode))
- {
- insn_size += 1 + size;
- p = frag_more (1 + size);
- }
- else
- {
- /* Opcode can be at most two bytes. */
- insn_size += 2 + size;
- p = frag_more (2 + size);
- *p++ = (i.tm.base_opcode >> 8) & 0xff;
- }
- *p++ = i.tm.base_opcode & 0xff;
+ p = frag_more (1 + size);
+ *p++ = i.tm.base_opcode;
fix_new_exp (frag_now, p - frag_now->fr_literal, size,
i.op[0].disps, 1, reloc (size, 1, 1, i.reloc[0]));
as_warn (_("skipping prefixes on this instruction"));
/* 1 opcode; 2 segment; offset */
- insn_size += prefix + 1 + 2 + size;
p = frag_more (prefix + 1 + 2 + size);
if (i.prefix[DATA_PREFIX])
{
if (*q)
{
- insn_size += 1;
p = frag_more (1);
md_number_to_chars (p, (valueT) *q, 1);
}
/* Now the opcode; be careful about word order here! */
if (fits_in_unsigned_byte (i.tm.base_opcode))
{
- insn_size += 1;
FRAG_APPEND_1_CHAR (i.tm.base_opcode);
}
else
{
- insn_size += 2;
p = frag_more (2);
/* Put out high byte first: can't use md_number_to_chars! */
*p++ = (i.tm.base_opcode >> 8) & 0xff;
/* Now the modrm byte and sib byte (if present). */
if (i.tm.opcode_modifier & Modrm)
{
- insn_size += 1;
p = frag_more (1);
md_number_to_chars (p,
(valueT) (i.rm.regmem << 0
&& i.rm.mode != 3
&& !(i.base_reg && (i.base_reg->reg_type & Reg16) != 0))
{
- insn_size += 1;
p = frag_more (1);
md_number_to_chars (p,
(valueT) (i.sib.base << 0
}
val = offset_in_range (i.op[n].disps->X_add_number,
size);
- insn_size += size;
p = frag_more (size);
md_number_to_chars (p, val, size);
}
size = 8;
}
- insn_size += size;
p = frag_more (size);
fix_new_exp (frag_now, p - frag_now->fr_literal, size,
i.op[n].disps, pcrel,
}
val = offset_in_range (i.op[n].imms->X_add_number,
size);
- insn_size += size;
p = frag_more (size);
md_number_to_chars (p, val, size);
}
size = 8;
}
- insn_size += size;
p = frag_more (size);
reloc_type = reloc (size, 0, sign, i.reloc[n]);
#ifdef BFD_ASSEMBLER
}
}
- dwarf2_emit_insn (insn_size);
-
#ifdef DEBUG386
if (flag_debug)
{
int len;
len = strlen (gotrel[j].str);
- if (strncmp (cp + 1, gotrel[j].str, len) == 0)
+ if (strncasecmp (cp + 1, gotrel[j].str, len) == 0)
{
if (gotrel[j].rel[(unsigned int) flag_code] != 0)
{
- int first;
- char *tmpbuf;
+ int first, second;
+ char *tmpbuf, *past_reloc;
*reloc = gotrel[j].rel[(unsigned int) flag_code];
+ if (adjust)
+ *adjust = len;
if (GOT_symbol == NULL)
GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
/* Replace the relocation token with ' ', so that
errors like foo@GOTOFF1 will be detected. */
+
+ /* The length of the first part of our input line. */
first = cp - input_line_pointer;
- tmpbuf = xmalloc (strlen (input_line_pointer));
+
+ /* The second part goes from after the reloc token until
+ (and including) an end_of_line char. Don't use strlen
+ here as the end_of_line char may not be a NUL. */
+ past_reloc = cp + 1 + len;
+ for (cp = past_reloc; !is_end_of_line[(unsigned char) *cp++]; )
+ ;
+ second = cp - past_reloc;
+
+ /* Allocate and copy string. The trailing NUL shouldn't
+ be necessary, but be safe. */
+ tmpbuf = xmalloc (first + second + 2);
memcpy (tmpbuf, input_line_pointer, first);
tmpbuf[first] = ' ';
- strcpy (tmpbuf + first + 1, cp + 1 + len);
- if (adjust)
- *adjust = len;
+ memcpy (tmpbuf + first + 1, past_reloc, second);
+ tmpbuf[first + second + 1] = '\0';
return tmpbuf;
}
exp_seg = expression (exp);
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer)
+ as_bad (_("junk `%s' after expression"), input_line_pointer);
+#if GCC_ASM_O_HACK
+ RESTORE_END_STRING (disp_end + 1);
+#endif
+ RESTORE_END_STRING (disp_end);
+ input_line_pointer = save_input_line_pointer;
+#ifndef LEX_AT
+ if (gotfree_input_line)
+ free (gotfree_input_line);
+#endif
+
#ifdef BFD_ASSEMBLER
/* We do this to make sure that the section symbol is in
the symbol table. We will ultimately change the relocation
if (i.reloc[this_operand] == BFD_RELOC_386_GOTOFF
|| i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL)
{
+ if (exp->X_op != O_symbol)
+ {
+ as_bad (_("bad expression used with @%s"),
+ (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL
+ ? "GOTPCREL"
+ : "GOTOFF"));
+ return 0;
+ }
+
if (S_IS_LOCAL (exp->X_add_symbol)
&& S_GET_SEGMENT (exp->X_add_symbol) != undefined_section)
section_symbol (S_GET_SEGMENT (exp->X_add_symbol));
- assert (exp->X_op == O_symbol);
exp->X_op = O_subtract;
exp->X_op_symbol = GOT_symbol;
if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL)
}
#endif
- SKIP_WHITESPACE ();
- if (*input_line_pointer)
- as_bad (_("junk `%s' after expression"), input_line_pointer);
-#if GCC_ASM_O_HACK
- RESTORE_END_STRING (disp_end + 1);
-#endif
- RESTORE_END_STRING (disp_end);
- input_line_pointer = save_input_line_pointer;
-#ifndef LEX_AT
- if (gotfree_input_line)
- free (gotfree_input_line);
-#endif
-
if (exp->X_op == O_absent || exp->X_op == O_big)
{
/* Missing or bad expr becomes absolute 0. */
case COND_JUMP86:
if (no_cond_jump_promotion)
- return 1;
+ goto relax_guess;
+
if (size == 2)
{
/* Negate the condition, and branch past an
case COND_JUMP:
if (no_cond_jump_promotion)
- return 1;
+ goto relax_guess;
+
/* This changes the byte-displacement jump 0x7N
to the (d)word-displacement jump 0x0f,0x8N. */
opcode[1] = opcode[0] + 0x10;
frag_wane (fragP);
return fragP->fr_fix - old_fr_fix;
}
- /* Guess a short jump. */
- return 1;
+
+ relax_guess:
+ /* Guess size depending on current relax state. Initially the relax
+ state will correspond to a short jump and we return 1, because
+ the variable part of the frag (the branch offset) is one byte
+ long. However, we can relax a section more than once and in that
+ case we must either set fr_subtype back to the unrelaxed state,
+ or return the value for the appropriate branch. */
+ return md_relax_table[fragP->fr_subtype].rlx_length;
}
/* Called after relax() is finished.
/* Address we want to reach in file space. */
target_address = S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset;
-#ifdef BFD_ASSEMBLER
- /* Not needed otherwise? */
- target_address += symbol_get_frag (fragP->fr_symbol)->fr_address;
-#endif
/* Address opcode resides at in file space. */
opcode_address = fragP->fr_address + fragP->fr_fix;
switch (fixp->fx_size)
{
default:
- as_bad (_("can not do %d byte pc-relative relocation"),
- fixp->fx_size);
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("can not do %d byte pc-relative relocation"),
+ fixp->fx_size);
code = BFD_RELOC_32_PCREL;
break;
case 1: code = BFD_RELOC_8_PCREL; break;
switch (fixp->fx_size)
{
default:
- as_bad (_("can not do %d byte relocation"), fixp->fx_size);
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("can not do %d byte relocation"),
+ fixp->fx_size);
code = BFD_RELOC_32;
break;
case 1: code = BFD_RELOC_8; break;