X-Git-Url: http://drtracing.org/?a=blobdiff_plain;ds=sidebyside;f=gas%2Fconfig%2Ftc-i386-intel.c;h=418b930c0822c0ce70e03fd70a91bbf5619defad;hb=9dfa3e63479d3c3106c7e5e86764a0ed8e22aa7f;hp=163634405307e0cd77c45d121ffe34c6056bab2a;hpb=253036079bf570cff18d8e627c769795e1c6c286;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-i386-intel.c b/gas/config/tc-i386-intel.c index 1636344053..418b930c08 100644 --- a/gas/config/tc-i386-intel.c +++ b/gas/config/tc-i386-intel.c @@ -1,6 +1,5 @@ /* tc-i386.c -- Assemble Intel syntax code for ix86/x86-64 - Copyright 2009 - Free Software Foundation, Inc. + Copyright (C) 2009-2016 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -63,6 +62,8 @@ intel_state; #define O_xmmword_ptr O_md21 /* ymmword ptr X_add_symbol */ #define O_ymmword_ptr O_md20 +/* zmmword ptr X_add_symbol */ +#define O_zmmword_ptr O_md19 static struct { @@ -108,6 +109,7 @@ const i386_types[] = I386_TYPE(oword, 16), I386_TYPE(xmmword, 16), I386_TYPE(ymmword, 32), + I386_TYPE(zmmword, 64), #undef I386_TYPE { "near", O_near_ptr, { 0xff04, 0xff02, 0xff08 } }, { "far", O_far_ptr, { 0xff06, 0xff05, 0xff06 } }, @@ -166,13 +168,18 @@ operatorT i386_operator (const char *name, unsigned int operands, char *pc) for (j = 0; i386_types[j].name; ++j) if (strcasecmp (i386_types[j].name, name) == 0) break; + if (i386_types[j].name && *pc == ' ') { - char *pname = ++input_line_pointer; - char c = get_symbol_end (); + char *pname; + char c; + + ++input_line_pointer; + c = get_symbol_name (&pname); if (strcasecmp (pname, "ptr") == 0) { + /* FIXME: What if c == '"' ? */ pname[-1] = *pc; *pc = c; if (intel_syntax > 0 || operands != 1) @@ -180,7 +187,7 @@ operatorT i386_operator (const char *name, unsigned int operands, char *pc) return i386_types[j].op; } - *input_line_pointer = c; + (void) restore_line_pointer (c); input_line_pointer = pname - 1; } @@ -191,6 +198,12 @@ static int i386_intel_parse_name (const char *name, expressionS *e) { unsigned int j; + if (! strcmp (name, "$")) + { + current_location (e); + return 1; + } + for (j = 0; i386_types[j].name; ++j) if (strcasecmp(i386_types[j].name, name) == 0) { @@ -208,8 +221,10 @@ static INLINE int i386_intel_check (const reg_entry *rreg, const reg_entry *base, const reg_entry *iindex) { - if ((this_operand >= 0 && rreg != i.op[this_operand].regs) - || base != intel_state.base || iindex != intel_state.index) + if ((this_operand >= 0 + && rreg != i.op[this_operand].regs) + || base != intel_state.base + || iindex != intel_state.index) { as_bad (_("invalid use of register")); return 0; @@ -219,15 +234,20 @@ static INLINE int i386_intel_check (const reg_entry *rreg, static INLINE void i386_intel_fold (expressionS *e, symbolS *sym) { + expressionS *exp = symbol_get_value_expression (sym); if (S_GET_SEGMENT (sym) == absolute_section) { offsetT val = e->X_add_number; - *e = *symbol_get_value_expression (sym); + *e = *exp; e->X_add_number += val; } else { + if (exp->X_op == O_symbol + && strcmp (S_GET_NAME (exp->X_add_symbol), + GLOBAL_OFFSET_TABLE_NAME) == 0) + sym = exp->X_add_symbol; e->X_add_symbol = sym; e->X_op_symbol = NULL; e->X_op = O_symbol; @@ -265,14 +285,31 @@ i386_intel_simplify_register (expressionS *e) } i.op[this_operand].regs = i386_regtab + reg_num; } + else if (!intel_state.index + && (i386_regtab[reg_num].reg_type.bitfield.regxmm + || i386_regtab[reg_num].reg_type.bitfield.regymm + || i386_regtab[reg_num].reg_type.bitfield.regzmm)) + intel_state.index = i386_regtab + reg_num; else if (!intel_state.base && !intel_state.in_scale) intel_state.base = i386_regtab + reg_num; else if (!intel_state.index) - intel_state.index = i386_regtab + reg_num; + { + if (intel_state.in_scale + || current_templates->start->base_opcode == 0xf30f1b /* bndmk */ + || (current_templates->start->base_opcode & ~1) == 0x0f1a /* bnd{ld,st}x */ + || i386_regtab[reg_num].reg_type.bitfield.baseindex) + intel_state.index = i386_regtab + reg_num; + else + { + /* Convert base to index and make ESP/RSP the base. */ + intel_state.index = intel_state.base; + intel_state.base = i386_regtab + reg_num; + } + } else { /* esp is invalid as index */ - intel_state.index = i386_regtab + REGNAM_EAX + 4; + intel_state.index = i386_regtab + REGNAM_EAX + ESP_REG_NUM; } return 2; } @@ -293,7 +330,8 @@ static INLINE int i386_intel_simplify_symbol(symbolS *sym) static int i386_intel_simplify (expressionS *e) { - const reg_entry *the_reg = this_operand >= 0 ? i.op[this_operand].regs : NULL; + const reg_entry *the_reg = (this_operand >= 0 + ? i.op[this_operand].regs : NULL); const reg_entry *base = intel_state.base; const reg_entry *state_index = intel_state.index; int ret; @@ -307,8 +345,9 @@ static int i386_intel_simplify (expressionS *e) if (e->X_add_symbol) { if (!i386_intel_simplify_symbol (e->X_add_symbol) - || !i386_intel_check(the_reg, intel_state.base, intel_state.index)) - return 0;; + || !i386_intel_check(the_reg, intel_state.base, + intel_state.index)) + return 0; } if (!intel_state.in_offset) ++intel_state.in_bracket; @@ -342,13 +381,15 @@ static int i386_intel_simplify (expressionS *e) case O_oword_ptr: case O_xmmword_ptr: case O_ymmword_ptr: + case O_zmmword_ptr: case O_near_ptr: case O_far_ptr: if (intel_state.op_modifier == O_absent) intel_state.op_modifier = e->X_op; /* FALLTHROUGH */ case O_short: - if (symbol_get_value_expression (e->X_add_symbol)->X_op == O_register) + if (symbol_get_value_expression (e->X_add_symbol)->X_op + == O_register) { as_bad (_("invalid use of register")); return 0; @@ -359,13 +400,15 @@ static int i386_intel_simplify (expressionS *e) break; case O_full_ptr: - if (symbol_get_value_expression (e->X_op_symbol)->X_op == O_register) + if (symbol_get_value_expression (e->X_op_symbol)->X_op + == O_register) { as_bad (_("invalid use of register")); return 0; } if (!i386_intel_simplify_symbol (e->X_op_symbol) - || !i386_intel_check(the_reg, intel_state.base, intel_state.index)) + || !i386_intel_check(the_reg, intel_state.base, + intel_state.index)) return 0; if (!intel_state.in_offset) intel_state.seg = e->X_add_symbol; @@ -376,23 +419,21 @@ static int i386_intel_simplify (expressionS *e) if (this_operand >= 0 && intel_state.in_bracket) { expressionS *scale = NULL; - - if (intel_state.index) - --scale; + int has_index = (intel_state.index != NULL); if (!intel_state.in_scale++) intel_state.scale_factor = 1; ret = i386_intel_simplify_symbol (e->X_add_symbol); - if (ret && !scale && intel_state.index) + if (ret && !has_index && intel_state.index) scale = symbol_get_value_expression (e->X_op_symbol); if (ret) ret = i386_intel_simplify_symbol (e->X_op_symbol); - if (ret && !scale && intel_state.index) + if (ret && !scale && !has_index && intel_state.index) scale = symbol_get_value_expression (e->X_add_symbol); - if (ret && scale && (scale + 1)) + if (ret && scale) { resolve_expression (scale); if (scale->X_op != O_constant @@ -422,12 +463,13 @@ static int i386_intel_simplify (expressionS *e) break; default: /* esp is invalid as index */ - intel_state.index = i386_regtab + REGNAM_EAX + 4; + intel_state.index = i386_regtab + REGNAM_EAX + ESP_REG_NUM; break; } break; } + goto fallthrough; case O_register: ret = i386_intel_simplify_register (e); @@ -446,7 +488,9 @@ static int i386_intel_simplify (expressionS *e) /* FALLTHROUGH */ default: - if (e->X_add_symbol && !i386_intel_simplify_symbol (e->X_add_symbol)) +fallthrough: + if (e->X_add_symbol + && !i386_intel_simplify_symbol (e->X_add_symbol)) return 0; if (e->X_op == O_add || e->X_op == O_subtract) { @@ -454,15 +498,20 @@ static int i386_intel_simplify (expressionS *e) state_index = intel_state.index; } if (!i386_intel_check (the_reg, base, state_index) - || (e->X_op_symbol && !i386_intel_simplify_symbol (e->X_op_symbol)) + || (e->X_op_symbol + && !i386_intel_simplify_symbol (e->X_op_symbol)) || !i386_intel_check (the_reg, - e->X_op != O_add ? base : intel_state.base, - e->X_op != O_add ? state_index : intel_state.index)) + (e->X_op != O_add + ? base : intel_state.base), + (e->X_op != O_add + ? state_index : intel_state.index))) return 0; break; } - if (this_operand >= 0 && e->X_op == O_symbol && !intel_state.in_offset) + if (this_operand >= 0 + && e->X_op == O_symbol + && !intel_state.in_offset) { segT seg = S_GET_SEGMENT (e->X_add_symbol); @@ -489,6 +538,10 @@ i386_intel_operand (char *operand_string, int got_a_float) char suffix = 0; int ret; + /* Handle vector immediates. */ + if (RC_SAE_immediate (operand_string)) + return 1; + /* Initialize state structure. */ intel_state.op_modifier = O_absent; intel_state.is_mem = 0; @@ -505,11 +558,6 @@ i386_intel_operand (char *operand_string, int got_a_float) saved_input_line_pointer = input_line_pointer; input_line_pointer = buf = xstrdup (operand_string); - /* A '$' followed by an identifier char is an identifier. Otherwise, - it's operator '.' followed by an expression. */ - if (*buf == '$' && !is_identifier_char (buf[1])) - *buf = '.'; - intel_syntax = -1; memset (&exp, 0, sizeof(exp)); exp_seg = expression (&exp); @@ -517,6 +565,17 @@ i386_intel_operand (char *operand_string, int got_a_float) intel_syntax = 1; SKIP_WHITESPACE (); + + /* Handle vector operations. */ + if (*input_line_pointer == '{') + { + char *end = check_VecOperations (input_line_pointer, NULL); + if (end) + input_line_pointer = end; + else + ret = 0; + } + if (!is_end_of_line[(unsigned char) *input_line_pointer]) { as_bad (_("junk `%s' after expression"), input_line_pointer); @@ -631,6 +690,11 @@ i386_intel_operand (char *operand_string, int got_a_float) suffix = YMMWORD_MNEM_SUFFIX; break; + case O_zmmword_ptr: + i.types[this_operand].bitfield.zmmword = 1; + suffix = ZMMWORD_MNEM_SUFFIX; + break; + case O_far_ptr: suffix = LONG_DOUBLE_MNEM_SUFFIX; /* FALLTHROUGH */ @@ -661,7 +725,9 @@ i386_intel_operand (char *operand_string, int got_a_float) || current_templates->start->opcode_modifier.jumpdword || current_templates->start->opcode_modifier.jumpintersegment) { - if (i.op[this_operand].regs || intel_state.base || intel_state.index + if (i.op[this_operand].regs + || intel_state.base + || intel_state.index || intel_state.is_mem > 1) i.types[this_operand].bitfield.jumpabsolute = 1; else @@ -744,15 +810,18 @@ i386_intel_operand (char *operand_string, int got_a_float) temp = i.op[this_operand].regs->reg_type; temp.bitfield.baseindex = 0; - i.types[this_operand] = operand_type_or (i.types[this_operand], temp); + i.types[this_operand] = operand_type_or (i.types[this_operand], + temp); i.types[this_operand].bitfield.unspecified = 0; ++i.reg_operands; } - else if (intel_state.base || intel_state.index || intel_state.seg + else if (intel_state.base + || intel_state.index + || intel_state.seg || intel_state.is_mem) { /* Memory operand. */ - if (i.mem_operands + if ((int) i.mem_operands >= 2 - !current_templates->start->opcode_modifier.isstring) { /* Handle @@ -809,8 +878,10 @@ i386_intel_operand (char *operand_string, int got_a_float) memcpy (expP, &exp, sizeof(exp)); resolve_expression (expP); - if (expP->X_op != O_constant || expP->X_add_number - || (!intel_state.base && !intel_state.index)) + if (expP->X_op != O_constant + || expP->X_add_number + || (!intel_state.base + && !intel_state.index)) { i.op[this_operand].disps = expP; i.disp_operands++;