-/* e09 OFFSET e09
- | SHORT e09
- | + e09
- | - e09
- | ~ e09
- | NOT e09
- | e10 e09'
-
- e09' PTR e10 e09'
- | : e10 e09'
- | Empty */
-static int
-intel_e09 (void)
-{
- int nregs = ~NUM_ADDRESS_REGS;
- int in_offset = 0;
-
- for (;;)
- {
- /* Don't consume constants here. */
- if (cur_token.code == '+' || cur_token.code == '-')
- {
- /* Need to look one token ahead - if the next token
- is a constant, the current token is its sign. */
- int next_code;
-
- intel_match_token (cur_token.code);
- next_code = cur_token.code;
- intel_putback_token ();
- if (next_code == T_CONST)
- break;
- }
-
- /* e09 OFFSET e09 */
- if (cur_token.code == T_OFFSET)
- {
- if (!in_offset++)
- ++intel_parser.in_offset;
- }
-
- /* e09 SHORT e09 */
- else if (cur_token.code == T_SHORT)
- intel_parser.op_modifier |= 1 << T_SHORT;
-
- /* e09 + e09 */
- else if (cur_token.code == '+')
- strcat (intel_parser.disp, "+");
-
- /* e09 - e09
- | ~ e09
- | NOT e09 */
- else if (cur_token.code == '-' || cur_token.code == '~')
- {
- char str[2];
-
- if (nregs < 0)
- nregs = ~nregs;
- str[0] = cur_token.code;
- str[1] = 0;
- strcat (intel_parser.disp, str);
- }
-
- /* e09 e10 e09' */
- else
- break;
-
- intel_match_token (cur_token.code);
- }
-
- for (;;)
- {
- if (!intel_e10 ())
- return 0;
-
- /* e09' PTR e10 e09' */
- if (cur_token.code == T_PTR)
- {
- char suffix;
-
- if (prev_token.code == T_BYTE)
- suffix = BYTE_MNEM_SUFFIX;
-
- else if (prev_token.code == T_WORD)
- {
- if (current_templates->start->name[0] == 'l'
- && current_templates->start->name[2] == 's'
- && current_templates->start->name[3] == 0)
- suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
- else if (intel_parser.got_a_float == 2) /* "fi..." */
- suffix = SHORT_MNEM_SUFFIX;
- else
- suffix = WORD_MNEM_SUFFIX;
- }
-
- else if (prev_token.code == T_DWORD)
- {
- if (current_templates->start->name[0] == 'l'
- && current_templates->start->name[2] == 's'
- && current_templates->start->name[3] == 0)
- suffix = WORD_MNEM_SUFFIX;
- else if (flag_code == CODE_16BIT
- && (current_templates->start->opcode_modifier.jump
- || current_templates->start->opcode_modifier.jumpdword))
- suffix = LONG_DOUBLE_MNEM_SUFFIX;
- else if (intel_parser.got_a_float == 1) /* "f..." */
- suffix = SHORT_MNEM_SUFFIX;
- else
- suffix = LONG_MNEM_SUFFIX;
- }
-
- else if (prev_token.code == T_FWORD)
- {
- if (current_templates->start->name[0] == 'l'
- && current_templates->start->name[2] == 's'
- && current_templates->start->name[3] == 0)
- suffix = LONG_MNEM_SUFFIX;
- else if (!intel_parser.got_a_float)
- {
- if (flag_code == CODE_16BIT)
- add_prefix (DATA_PREFIX_OPCODE);
- suffix = LONG_DOUBLE_MNEM_SUFFIX;
- }
- else
- suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
- }
-
- else if (prev_token.code == T_QWORD)
- {
- if (intel_parser.got_a_float == 1) /* "f..." */
- suffix = LONG_MNEM_SUFFIX;
- else
- suffix = QWORD_MNEM_SUFFIX;
- }
-
- else if (prev_token.code == T_TBYTE)
- {
- if (intel_parser.got_a_float == 1)
- suffix = LONG_DOUBLE_MNEM_SUFFIX;
- else
- suffix = BYTE_MNEM_SUFFIX; /* so it will cause an error */
- }
-
- else if (prev_token.code == T_XMMWORD)
- {
- /* XXX ignored for now, but accepted since gcc uses it */
- suffix = 0;
- }
-
- else
- {
- as_bad (_("Unknown operand modifier `%s'"), prev_token.str);
- return 0;
- }
-
- /* Operands for jump/call using 'ptr' notation denote absolute
- addresses. */
- if (current_templates->start->opcode_modifier.jump
- || current_templates->start->opcode_modifier.jumpdword)
- i.types[this_operand].bitfield.jumpabsolute = 1;
-
- if (current_templates->start->base_opcode == 0x8d /* lea */)
- ;
- else if (!i.suffix)
- i.suffix = suffix;
- else if (i.suffix != suffix)
- {
- as_bad (_("Conflicting operand modifiers"));
- return 0;
- }
-
- }
-
- /* e09' : e10 e09' */
- else if (cur_token.code == ':')
- {
- if (prev_token.code != T_REG)
- {
- /* While {call,jmp} SSSS:OOOO is MASM syntax only when SSSS is a
- segment/group identifier (which we don't have), using comma
- as the operand separator there is even less consistent, since
- there all branches only have a single operand. */
- if (this_operand != 0
- || intel_parser.in_offset
- || intel_parser.in_bracket
- || (!current_templates->start->opcode_modifier.jump
- && !current_templates->start->opcode_modifier.jumpdword
- && !current_templates->start->opcode_modifier.jumpintersegment
- && !current_templates->start->operand_types[0].bitfield.jumpabsolute))
- return intel_match_token (T_NIL);
- /* Remember the start of the 2nd operand and terminate 1st
- operand here.
- XXX This isn't right, yet (when SSSS:OOOO is right operand of
- another expression), but it gets at least the simplest case
- (a plain number or symbol on the left side) right. */
- intel_parser.next_operand = intel_parser.op_string;
- *--intel_parser.op_string = '\0';
- return intel_match_token (':');
- }
- }
-
- /* e09' Empty */
- else
- break;
-
- intel_match_token (cur_token.code);
-
- }
-
- if (in_offset)
- {
- --intel_parser.in_offset;
- if (nregs < 0)
- nregs = ~nregs;
- if (NUM_ADDRESS_REGS > nregs)
- {
- as_bad (_("Invalid operand to `OFFSET'"));
- return 0;
- }
- intel_parser.op_modifier |= 1 << T_OFFSET;
- }
-
- if (nregs >= 0 && NUM_ADDRESS_REGS > nregs)
- i.base_reg = i386_regtab + REGNAM_AL + 3; /* bl is invalid as base */
- return 1;
-}
-
-static int
-intel_bracket_expr (void)
-{
- int was_offset = intel_parser.op_modifier & (1 << T_OFFSET);
- const char *start = intel_parser.op_string;
- int len;
-
- if (i.op[this_operand].regs)
- return intel_match_token (T_NIL);
-
- intel_match_token ('[');
-
- /* Mark as a memory operand only if it's not already known to be an
- offset expression. If it's an offset expression, we need to keep
- the brace in. */
- if (!intel_parser.in_offset)
- {
- ++intel_parser.in_bracket;
-
- /* Operands for jump/call inside brackets denote absolute addresses. */
- if (current_templates->start->opcode_modifier.jump
- || current_templates->start->opcode_modifier.jumpdword)
- i.types[this_operand].bitfield.jumpabsolute = 1;
-
- /* Unfortunately gas always diverged from MASM in a respect that can't
- be easily fixed without risking to break code sequences likely to be
- encountered (the testsuite even check for this): MASM doesn't consider
- an expression inside brackets unconditionally as a memory reference.
- When that is e.g. a constant, an offset expression, or the sum of the
- two, this is still taken as a constant load. gas, however, always
- treated these as memory references. As a compromise, we'll try to make
- offset expressions inside brackets work the MASM way (since that's
- less likely to be found in real world code), but make constants alone
- continue to work the traditional gas way. In either case, issue a
- warning. */
- intel_parser.op_modifier &= ~was_offset;
- }
- else
- strcat (intel_parser.disp, "[");
-
- /* Add a '+' to the displacement string if necessary. */
- if (*intel_parser.disp != '\0'
- && *(intel_parser.disp + strlen (intel_parser.disp) - 1) != '+')
- strcat (intel_parser.disp, "+");
-
- if (intel_expr ()
- && (len = intel_parser.op_string - start - 1,
- intel_match_token (']')))
- {
- /* Preserve brackets when the operand is an offset expression. */
- if (intel_parser.in_offset)
- strcat (intel_parser.disp, "]");
- else
- {
- --intel_parser.in_bracket;
- if (i.base_reg || i.index_reg)
- intel_parser.is_mem = 1;
- if (!intel_parser.is_mem)
- {
- if (!(intel_parser.op_modifier & (1 << T_OFFSET)))
- /* Defer the warning until all of the operand was parsed. */
- intel_parser.is_mem = -1;
- else if (!quiet_warnings)
- as_warn (_("`[%.*s]' taken to mean just `%.*s'"),
- len, start, len, start);
- }
- }
- intel_parser.op_modifier |= was_offset;
-
- return 1;
- }
- return 0;
-}
-
-/* e10 e11 e10'
-
- e10' [ expr ] e10'
- | Empty */
-static int
-intel_e10 (void)
-{
- if (!intel_e11 ())
- return 0;
-
- while (cur_token.code == '[')
- {
- if (!intel_bracket_expr ())
- return 0;
- }
-
- return 1;
-}
-
-/* e11 ( expr )
- | [ expr ]
- | BYTE
- | WORD
- | DWORD
- | FWORD
- | QWORD
- | TBYTE
- | OWORD
- | XMMWORD
- | $
- | .
- | register
- | id
- | constant */
-static int
-intel_e11 (void)
-{
- switch (cur_token.code)
- {
- /* e11 ( expr ) */
- case '(':
- intel_match_token ('(');
- strcat (intel_parser.disp, "(");
-
- if (intel_expr () && intel_match_token (')'))
- {
- strcat (intel_parser.disp, ")");
- return 1;
- }
- return 0;
-
- /* e11 [ expr ] */
- case '[':
- return intel_bracket_expr ();
-
- /* e11 $
- | . */
- case '.':
- strcat (intel_parser.disp, cur_token.str);
- intel_match_token (cur_token.code);
-
- /* Mark as a memory operand only if it's not already known to be an
- offset expression. */
- if (!intel_parser.in_offset)
- intel_parser.is_mem = 1;
-
- return 1;
-
- /* e11 register */
- case T_REG:
- {
- const reg_entry *reg = intel_parser.reg = cur_token.reg;
-
- intel_match_token (T_REG);
-
- /* Check for segment change. */
- if (cur_token.code == ':')
- {
- if (!reg->reg_type.bitfield.sreg2
- && !reg->reg_type.bitfield.sreg3)
- {
- as_bad (_("`%s' is not a valid segment register"),
- reg->reg_name);
- return 0;
- }
- else if (i.seg[i.mem_operands])
- as_warn (_("Extra segment override ignored"));
- else
- {
- if (!intel_parser.in_offset)
- intel_parser.is_mem = 1;
- switch (reg->reg_num)
- {
- case 0:
- i.seg[i.mem_operands] = &es;
- break;
- case 1:
- i.seg[i.mem_operands] = &cs;
- break;
- case 2:
- i.seg[i.mem_operands] = &ss;
- break;
- case 3:
- i.seg[i.mem_operands] = &ds;
- break;
- case 4:
- i.seg[i.mem_operands] = &fs;
- break;
- case 5:
- i.seg[i.mem_operands] = &gs;
- break;
- }
- }
- }
-
- /* Not a segment register. Check for register scaling. */
- else if (cur_token.code == '*')
- {
- if (!intel_parser.in_bracket)
- {
- as_bad (_("Register scaling only allowed in memory operands"));
- return 0;
- }
-
- if (reg->reg_type.bitfield.reg16) /* Disallow things like [si*1]. */
- reg = i386_regtab + REGNAM_AX + 4; /* sp is invalid as index */
- else if (i.index_reg)
- reg = i386_regtab + REGNAM_EAX + 4; /* esp is invalid as index */
-
- /* What follows must be a valid scale. */
- intel_match_token ('*');
- i.index_reg = reg;
- i.types[this_operand].bitfield.baseindex = 1;
-
- /* Set the scale after setting the register (otherwise,
- i386_scale will complain) */
- if (cur_token.code == '+' || cur_token.code == '-')
- {
- char *str, sign = cur_token.code;
- intel_match_token (cur_token.code);
- if (cur_token.code != T_CONST)
- {
- as_bad (_("Syntax error: Expecting a constant, got `%s'"),
- cur_token.str);
- return 0;
- }
- str = (char *) xmalloc (strlen (cur_token.str) + 2);
- strcpy (str + 1, cur_token.str);
- *str = sign;
- if (!i386_scale (str))
- return 0;
- free (str);
- }
- else if (!i386_scale (cur_token.str))
- return 0;
- intel_match_token (cur_token.code);
- }
-
- /* No scaling. If this is a memory operand, the register is either a
- base register (first occurrence) or an index register (second
- occurrence). */
- else if (intel_parser.in_bracket)
- {
-
- if (!i.base_reg)
- i.base_reg = reg;
- else if (!i.index_reg)
- i.index_reg = reg;
- else
- {
- as_bad (_("Too many register references in memory operand"));
- return 0;
- }
-
- i.types[this_operand].bitfield.baseindex = 1;
- }
-
- /* It's neither base nor index. */
- else if (!intel_parser.in_offset && !intel_parser.is_mem)
- {
- i386_operand_type temp = reg->reg_type;
- temp.bitfield.baseindex = 0;
- i.types[this_operand] = operand_type_or (i.types[this_operand],
- temp);
- i.op[this_operand].regs = reg;
- i.reg_operands++;
- }
- else
- {
- as_bad (_("Invalid use of register"));
- return 0;
- }
-
- /* Since registers are not part of the displacement string (except
- when we're parsing offset operands), we may need to remove any
- preceding '+' from the displacement string. */
- if (*intel_parser.disp != '\0'
- && !intel_parser.in_offset)
- {
- char *s = intel_parser.disp;
- s += strlen (s) - 1;
- if (*s == '+')
- *s = '\0';
- }
-
- return 1;
- }
-
- /* e11 BYTE
- | WORD
- | DWORD
- | FWORD
- | QWORD
- | TBYTE
- | OWORD
- | XMMWORD */
- case T_BYTE:
- case T_WORD:
- case T_DWORD:
- case T_FWORD:
- case T_QWORD:
- case T_TBYTE:
- case T_XMMWORD:
- intel_match_token (cur_token.code);
-
- if (cur_token.code == T_PTR)
- return 1;
-
- /* It must have been an identifier. */
- intel_putback_token ();
- cur_token.code = T_ID;
- /* FALLTHRU */
-
- /* e11 id
- | constant */
- case T_ID:
- if (!intel_parser.in_offset && intel_parser.is_mem <= 0)
- {
- symbolS *symbolP;
-
- /* The identifier represents a memory reference only if it's not
- preceded by an offset modifier and if it's not an equate. */
- symbolP = symbol_find(cur_token.str);
- if (!symbolP || S_GET_SEGMENT(symbolP) != absolute_section)
- intel_parser.is_mem = 1;
- }
- /* FALLTHRU */
-
- case T_CONST:
- case '-':
- case '+':
- {
- char *save_str, sign = 0;
-
- /* Allow constants that start with `+' or `-'. */
- if (cur_token.code == '-' || cur_token.code == '+')
- {
- sign = cur_token.code;
- intel_match_token (cur_token.code);
- if (cur_token.code != T_CONST)
- {
- as_bad (_("Syntax error: Expecting a constant, got `%s'"),
- cur_token.str);
- return 0;
- }
- }
-
- save_str = (char *) xmalloc (strlen (cur_token.str) + 2);
- strcpy (save_str + !!sign, cur_token.str);
- if (sign)
- *save_str = sign;
-
- /* Get the next token to check for register scaling. */
- intel_match_token (cur_token.code);
-
- /* Check if this constant is a scaling factor for an
- index register. */
- if (cur_token.code == '*')
- {
- if (intel_match_token ('*') && cur_token.code == T_REG)
- {
- const reg_entry *reg = cur_token.reg;
-
- if (!intel_parser.in_bracket)
- {
- as_bad (_("Register scaling only allowed "
- "in memory operands"));
- return 0;
- }
-
- /* Disallow things like [1*si].
- sp and esp are invalid as index. */
- if (reg->reg_type.bitfield.reg16)
- reg = i386_regtab + REGNAM_AX + 4;
- else if (i.index_reg)
- reg = i386_regtab + REGNAM_EAX + 4;
-
- /* The constant is followed by `* reg', so it must be
- a valid scale. */
- i.index_reg = reg;
- i.types[this_operand].bitfield.baseindex = 1;
-
- /* Set the scale after setting the register (otherwise,
- i386_scale will complain) */
- if (!i386_scale (save_str))
- return 0;
- intel_match_token (T_REG);
-
- /* Since registers are not part of the displacement
- string, we may need to remove any preceding '+' from
- the displacement string. */
- if (*intel_parser.disp != '\0')
- {
- char *s = intel_parser.disp;
- s += strlen (s) - 1;
- if (*s == '+')
- *s = '\0';
- }
-
- free (save_str);
-
- return 1;
- }
-
- /* The constant was not used for register scaling. Since we have
- already consumed the token following `*' we now need to put it
- back in the stream. */
- intel_putback_token ();
- }
-
- /* Add the constant to the displacement string. */
- strcat (intel_parser.disp, save_str);
- free (save_str);
-
- return 1;
- }
- }
-
- as_bad (_("Unrecognized token '%s'"), cur_token.str);
- return 0;
-}
-
-/* Match the given token against cur_token. If they match, read the next
- token from the operand string. */
-static int
-intel_match_token (int code)
-{
- if (cur_token.code == code)
- {
- intel_get_token ();
- return 1;
- }
- else
- {
- as_bad (_("Unexpected token `%s'"), cur_token.str);
- return 0;
- }
-}
-
-/* Read a new token from intel_parser.op_string and store it in cur_token. */
-static void
-intel_get_token (void)
-{
- char *end_op;
- const reg_entry *reg;
- struct intel_token new_token;
-
- new_token.code = T_NIL;
- new_token.reg = NULL;
- new_token.str = NULL;
-
- /* Free the memory allocated to the previous token and move
- cur_token to prev_token. */
- if (prev_token.str)
- free (prev_token.str);
-
- prev_token = cur_token;
-
- /* Skip whitespace. */
- while (is_space_char (*intel_parser.op_string))
- intel_parser.op_string++;
-
- /* Return an empty token if we find nothing else on the line. */
- if (*intel_parser.op_string == '\0')
- {
- cur_token = new_token;
- return;
- }
-
- /* The new token cannot be larger than the remainder of the operand
- string. */
- new_token.str = (char *) xmalloc (strlen (intel_parser.op_string) + 1);
- new_token.str[0] = '\0';
-
- if (strchr ("0123456789", *intel_parser.op_string))
- {
- char *p = new_token.str;
- char *q = intel_parser.op_string;
- new_token.code = T_CONST;
-
- /* Allow any kind of identifier char to encompass floating point and
- hexadecimal numbers. */
- while (is_identifier_char (*q))
- *p++ = *q++;
- *p = '\0';
-
- /* Recognize special symbol names [0-9][bf]. */
- if (strlen (intel_parser.op_string) == 2
- && (intel_parser.op_string[1] == 'b'
- || intel_parser.op_string[1] == 'f'))
- new_token.code = T_ID;
- }
-
- else if ((reg = parse_register (intel_parser.op_string, &end_op)) != NULL)
- {
- size_t len = end_op - intel_parser.op_string;
-
- new_token.code = T_REG;
- new_token.reg = reg;
-
- memcpy (new_token.str, intel_parser.op_string, len);
- new_token.str[len] = '\0';
- }
-
- else if (is_identifier_char (*intel_parser.op_string))
- {
- char *p = new_token.str;
- char *q = intel_parser.op_string;
-
- /* A '.' or '$' followed by an identifier char is an identifier.
- Otherwise, it's operator '.' followed by an expression. */
- if ((*q == '.' || *q == '$') && !is_identifier_char (*(q + 1)))
- {
- new_token.code = '.';
- new_token.str[0] = '.';
- new_token.str[1] = '\0';
- }
- else
- {
- while (is_identifier_char (*q) || *q == '@')
- *p++ = *q++;
- *p = '\0';
-
- if (strcasecmp (new_token.str, "NOT") == 0)
- new_token.code = '~';
-
- else if (strcasecmp (new_token.str, "MOD") == 0)
- new_token.code = '%';
-
- else if (strcasecmp (new_token.str, "AND") == 0)
- new_token.code = '&';
-
- else if (strcasecmp (new_token.str, "OR") == 0)
- new_token.code = '|';
-
- else if (strcasecmp (new_token.str, "XOR") == 0)
- new_token.code = '^';
-
- else if (strcasecmp (new_token.str, "SHL") == 0)
- new_token.code = T_SHL;
-
- else if (strcasecmp (new_token.str, "SHR") == 0)
- new_token.code = T_SHR;
-
- else if (strcasecmp (new_token.str, "BYTE") == 0)
- new_token.code = T_BYTE;
-
- else if (strcasecmp (new_token.str, "WORD") == 0)
- new_token.code = T_WORD;
-
- else if (strcasecmp (new_token.str, "DWORD") == 0)
- new_token.code = T_DWORD;
-
- else if (strcasecmp (new_token.str, "FWORD") == 0)
- new_token.code = T_FWORD;
-
- else if (strcasecmp (new_token.str, "QWORD") == 0)
- new_token.code = T_QWORD;
-
- else if (strcasecmp (new_token.str, "TBYTE") == 0
- /* XXX remove (gcc still uses it) */
- || strcasecmp (new_token.str, "XWORD") == 0)
- new_token.code = T_TBYTE;
-
- else if (strcasecmp (new_token.str, "XMMWORD") == 0
- || strcasecmp (new_token.str, "OWORD") == 0)
- new_token.code = T_XMMWORD;
-
- else if (strcasecmp (new_token.str, "PTR") == 0)
- new_token.code = T_PTR;
-
- else if (strcasecmp (new_token.str, "SHORT") == 0)
- new_token.code = T_SHORT;
-
- else if (strcasecmp (new_token.str, "OFFSET") == 0)
- {
- new_token.code = T_OFFSET;
-
- /* ??? This is not mentioned in the MASM grammar but gcc
- makes use of it with -mintel-syntax. OFFSET may be
- followed by FLAT: */
- if (strncasecmp (q, " FLAT:", 6) == 0)
- strcat (new_token.str, " FLAT:");
- }
-
- /* ??? This is not mentioned in the MASM grammar. */
- else if (strcasecmp (new_token.str, "FLAT") == 0)
- {
- new_token.code = T_OFFSET;
- if (*q == ':')
- strcat (new_token.str, ":");
- else
- as_bad (_("`:' expected"));
- }
-
- else
- new_token.code = T_ID;
- }
- }
-
- else if (strchr ("+-/*%|&^:[]()~", *intel_parser.op_string))
- {
- new_token.code = *intel_parser.op_string;
- new_token.str[0] = *intel_parser.op_string;
- new_token.str[1] = '\0';
- }
-
- else if (strchr ("<>", *intel_parser.op_string)
- && *intel_parser.op_string == *(intel_parser.op_string + 1))
- {
- new_token.code = *intel_parser.op_string == '<' ? T_SHL : T_SHR;
- new_token.str[0] = *intel_parser.op_string;
- new_token.str[1] = *intel_parser.op_string;
- new_token.str[2] = '\0';
- }
-
- else
- as_bad (_("Unrecognized token `%s'"), intel_parser.op_string);
-
- intel_parser.op_string += strlen (new_token.str);
- cur_token = new_token;
-}
-
-/* Put cur_token back into the token stream and make cur_token point to
- prev_token. */
-static void
-intel_putback_token (void)
-{
- if (cur_token.code != T_NIL)
- {
- intel_parser.op_string -= strlen (cur_token.str);
- free (cur_token.str);
- }
- cur_token = prev_token;
-
- /* Forget prev_token. */
- prev_token.code = T_NIL;
- prev_token.reg = NULL;
- prev_token.str = NULL;
-}
-
-int
-tc_x86_regname_to_dw2regnum (char *regname)
-{
- unsigned int regnum;
- unsigned int regnames_count;
- static const char *const regnames_32[] =
- {
- "eax", "ecx", "edx", "ebx",
- "esp", "ebp", "esi", "edi",
- "eip", "eflags", NULL,
- "st0", "st1", "st2", "st3",
- "st4", "st5", "st6", "st7",
- NULL, NULL,
- "xmm0", "xmm1", "xmm2", "xmm3",
- "xmm4", "xmm5", "xmm6", "xmm7",
- "mm0", "mm1", "mm2", "mm3",
- "mm4", "mm5", "mm6", "mm7",
- "fcw", "fsw", "mxcsr",
- "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,
- "tr", "ldtr"
- };
- static const char *const regnames_64[] =
- {
- "rax", "rdx", "rcx", "rbx",
- "rsi", "rdi", "rbp", "rsp",
- "r8", "r9", "r10", "r11",
- "r12", "r13", "r14", "r15",
- "rip",
- "xmm0", "xmm1", "xmm2", "xmm3",
- "xmm4", "xmm5", "xmm6", "xmm7",
- "xmm8", "xmm9", "xmm10", "xmm11",
- "xmm12", "xmm13", "xmm14", "xmm15",
- "st0", "st1", "st2", "st3",
- "st4", "st5", "st6", "st7",
- "mm0", "mm1", "mm2", "mm3",
- "mm4", "mm5", "mm6", "mm7",
- "rflags",
- "es", "cs", "ss", "ds", "fs", "gs", NULL, NULL,
- "fs.base", "gs.base", NULL, NULL,
- "tr", "ldtr",
- "mxcsr", "fcw", "fsw"
- };
- const char *const *regnames;
-
- if (flag_code == CODE_64BIT)
- {
- regnames = regnames_64;
- regnames_count = ARRAY_SIZE (regnames_64);
- }
- else
- {
- regnames = regnames_32;
- regnames_count = ARRAY_SIZE (regnames_32);
- }
-
- for (regnum = 0; regnum < regnames_count; regnum++)
- if (regnames[regnum] != NULL
- && strcmp (regname, regnames[regnum]) == 0)
- return regnum;
-
- return -1;
-}
-
-void
-tc_x86_frame_initial_instructions (void)
-{
- static unsigned int sp_regno;
-
- if (!sp_regno)
- sp_regno = tc_x86_regname_to_dw2regnum (flag_code == CODE_64BIT
- ? "rsp" : "esp");
-
- cfi_add_CFA_def_cfa (sp_regno, -x86_cie_data_alignment);
- cfi_add_CFA_offset (x86_dwarf2_return_column, x86_cie_data_alignment);
-}
-
-int
-i386_elf_section_type (const char *str, size_t len)
-{
- if (flag_code == CODE_64BIT
- && len == sizeof ("unwind") - 1
- && strncmp (str, "unwind", 6) == 0)
- return SHT_X86_64_UNWIND;
-
- return -1;
-}
-
-#ifdef TE_PE
-void
-tc_pe_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
-{
- expressionS expr;
-
- expr.X_op = O_secrel;
- expr.X_add_symbol = symbol;
- expr.X_add_number = 0;
- emit_expr (&expr, size);
-}
-#endif
-
-#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
-/* For ELF on x86-64, add support for SHF_X86_64_LARGE. */
-
-int
-x86_64_section_letter (int letter, char **ptr_msg)
-{
- if (flag_code == CODE_64BIT)
- {
- if (letter == 'l')
- return SHF_X86_64_LARGE;
-
- *ptr_msg = _("Bad .section directive: want a,l,w,x,M,S,G,T in string");
- }
- else
- *ptr_msg = _("Bad .section directive: want a,w,x,M,S,G,T in string");
- return -1;
-}
-
-int