diff options
author | K. Richard Pixley <rich@cygnus> | 1992-02-17 15:54:49 +0000 |
---|---|---|
committer | K. Richard Pixley <rich@cygnus> | 1992-02-17 15:54:49 +0000 |
commit | 542e1629fdd4df8920511c4eb2df15bb83feb13b (patch) | |
tree | f1b70b61ce3707e08b2f43081adfd3b4850654f3 /gas/config/tc-i386.c | |
parent | af2136245013fad2f72249258452d5f7154d5719 (diff) | |
download | gdb-542e1629fdd4df8920511c4eb2df15bb83feb13b.zip gdb-542e1629fdd4df8920511c4eb2df15bb83feb13b.tar.gz gdb-542e1629fdd4df8920511c4eb2df15bb83feb13b.tar.bz2 |
fighting bitrot in a major way
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r-- | gas/config/tc-i386.c | 219 |
1 files changed, 148 insertions, 71 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 42398ae..92b4b4a 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -34,46 +34,47 @@ typedef struct { /* TM holds the template for the insn were currently assembling. */ - template tm; + template tm; /* SUFFIX holds the opcode suffix (e.g. 'l' for 'movl') if given. */ - char suffix; + char suffix; /* Operands are coded with OPERANDS, TYPES, DISPS, IMMS, and REGS. */ /* OPERANDS gives the number of given operands. */ - unsigned int operands; + unsigned int operands; /* REG_OPERANDS, DISP_OPERANDS, MEM_OPERANDS, IMM_OPERANDS give the number of given register, displacement, memory operands and immediate operands. */ - unsigned int reg_operands, disp_operands, mem_operands, imm_operands; + unsigned int reg_operands, disp_operands, mem_operands, imm_operands; /* TYPES [i] is the type (see above #defines) which tells us how to search through DISPS [i] & IMMS [i] & REGS [i] for the required operand. */ - unsigned int types [MAX_OPERANDS]; + unsigned int types[MAX_OPERANDS]; /* Displacements (if given) for each operand. */ - expressionS * disps [MAX_OPERANDS]; + expressionS *disps[MAX_OPERANDS]; /* Immediate operands (if given) for each operand. */ - expressionS * imms [MAX_OPERANDS]; + expressionS *imms[MAX_OPERANDS]; /* Register operands (if given) for each operand. */ - reg_entry * regs [MAX_OPERANDS]; + reg_entry *regs[MAX_OPERANDS]; /* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode the base index byte below. */ - reg_entry * base_reg; - reg_entry * index_reg; - unsigned int log2_scale_factor; + reg_entry *base_reg; + reg_entry *index_reg; + unsigned int log2_scale_factor; /* SEG gives the seg_entry of this insn. It is equal to zero unless an explicit segment override is given. */ - seg_entry * seg; /* segment for memory operands (if given) */ + const seg_entry *seg; /* segment for memory operands (if given) */ /* PREFIX holds all the given prefix opcodes (usually null). PREFIXES is the size of PREFIX. */ - char prefix [MAX_PREFIXES]; - unsigned int prefixes; + /* richfix: really unsigned? */ + unsigned char prefix[MAX_PREFIXES]; + unsigned int prefixes; /* RM and IB are the modrm byte and the base index byte where the addressing modes of this insn are encoded. */ @@ -203,14 +204,28 @@ const relax_typeS md_relax_table[] = { #if __STDC__ == 1 static char *output_invalid(int c); +static int fits_in_signed_byte(long num); +static int fits_in_signed_word(long num); +static int fits_in_unsigned_byte(long num); +static int fits_in_unsigned_word(long num); static int i386_operand(char *operand_string); +static int smallest_imm_type(long num); static reg_entry *parse_register(char *reg_string); +static unsigned long mode_from_disp_size(unsigned long t); +static unsigned long opcode_suffix_to_type(unsigned long s); #else /* not __STDC__ */ static char *output_invalid(); +static int fits_in_signed_byte(); +static int fits_in_signed_word(); +static int fits_in_unsigned_byte(); +static int fits_in_unsigned_word(); static int i386_operand(); +static int smallest_imm_type(); static reg_entry *parse_register(); +static unsigned long mode_from_disp_size(); +static unsigned long opcode_suffix_to_type(); #endif /* not __STDC__ */ @@ -317,11 +332,11 @@ void md_begin () { register unsigned int c; - bzero (opcode_chars, sizeof(opcode_chars)); - bzero (operand_chars, sizeof(operand_chars)); - bzero (space_chars, sizeof(space_chars)); - bzero (identifier_chars, sizeof(identifier_chars)); - bzero (digit_chars, sizeof(digit_chars)); + memset(opcode_chars, '\0', sizeof(opcode_chars)); + memset(operand_chars, '\0', sizeof(operand_chars)); + memset(space_chars, '\0', sizeof(space_chars)); + memset(identifier_chars, '\0', sizeof(identifier_chars)); + memset(digit_chars, '\0', sizeof(digit_chars)); for (c = 0; c < 256; c++) { if (islower(c) || isdigit(c)) { @@ -473,15 +488,15 @@ void md_assemble (line) char *line; { /* Holds temlate once we've found it. */ - register template * t; + register template *t; /* Possible templates for current insn */ templates *current_templates = (templates *) 0; /* Initialize globals. */ - bzero (&i, sizeof(i)); - bzero (disp_expressions, sizeof(disp_expressions)); - bzero (im_expressions, sizeof(im_expressions)); + memset(&i, '\0', sizeof(i)); + memset(disp_expressions, '\0', sizeof(disp_expressions)); + memset(im_expressions, '\0', sizeof(im_expressions)); save_stack_p = save_stack; /* reset stack pointer */ /* Fist parse an opcode & call i386_operand for the operands. @@ -638,12 +653,12 @@ char *line; /* now *l must be either ',' or END_OF_INSN */ if (*l == ',') { - if (*++l == END_OF_INSN) { /* just skip it, if it's \n complain */ + if (*++l == END_OF_INSN) { /* just skip it, if it's \n complain */ goto expecting_operand_after_comma; } expecting_operand = 1; } - } while (*l != END_OF_INSN); /* until we get end of insn */ + } while (*l != END_OF_INSN); /* until we get end of insn */ } } @@ -676,7 +691,7 @@ char *line; ( ((t0 & t1 & (Reg)) == 0 && (m0 & m1 & (Reg)) == 0) || \ ((t0 & t1) & (m0 & m1) & (Reg)) \ ) : 1) - { + { register unsigned int overlap0, overlap1; expressionS * exp; unsigned int overlap2; @@ -746,7 +761,7 @@ char *line; } /* Copy the template we found (we may change it!). */ - bcopy (t, &i.tm, sizeof (template)); + memcpy(&i.tm, t, sizeof(template)); t = &i.tm; /* alter new copy of template */ /* If there's no opcode suffix we try to invent one based on register @@ -917,7 +932,7 @@ char *line; if (i.base_reg == esp && ! i.index_reg) { /* <disp>(%esp) becomes two byte modrm with no index register. */ i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; - i.rm.mode = MODE_FROM_DISP_SIZE (i.types[o]); + i.rm.mode = mode_from_disp_size(i.types[o]); i.bi.base = ESP_REG_NUM; i.bi.index = NO_INDEX_REGISTER; i.bi.scale = 0; /* Must be zero! */ @@ -929,7 +944,7 @@ char *line; /* fake_zero_displacement code does not set this. */ i.types[o] |= Disp8; } - i.rm.mode = MODE_FROM_DISP_SIZE (i.types[o]); + i.rm.mode = mode_from_disp_size(i.types[o]); i.rm.regmem = EBP_REG_NUM; } else if (! i.base_reg && (i.types[o] & BaseIndex)) { /* There are three cases here. @@ -961,7 +976,7 @@ char *line; } else { /* It's not a special case; rev'em up. */ i.rm.regmem = i.base_reg->reg_num; - i.rm.mode = MODE_FROM_DISP_SIZE (i.types[o]); + i.rm.mode = mode_from_disp_size(i.types[o]); if (i.index_reg) { i.rm.regmem = ESCAPE_TO_TWO_BYTE_ADDRESSING; i.bi.base = i.base_reg->reg_num; @@ -970,7 +985,7 @@ char *line; if (i.base_reg == ebp && i.disp_operands == 0) { /* pace */ fake_zero_displacement = 1; i.types[o] |= Disp8; - i.rm.mode = MODE_FROM_DISP_SIZE (i.types[o]); + i.rm.mode = mode_from_disp_size(i.types[o]); } } } @@ -987,15 +1002,15 @@ char *line; /* Select the correct segment for the memory operand. */ if (i.seg) { - const unsigned int seg_index; - const seg_entry * default_seg; + unsigned int seg_index; + const seg_entry *default_seg; if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING) { seg_index = (i.rm.mode<<3) | i.bi.base; - default_seg = two_byte_segment_defaults [seg_index]; + default_seg = two_byte_segment_defaults[seg_index]; } else { seg_index = (i.rm.mode<<3) | i.rm.regmem; - default_seg = one_byte_segment_defaults [seg_index]; + default_seg = one_byte_segment_defaults[seg_index]; } /* If the specified segment is not the default, use an opcode prefix to select it */ @@ -1054,12 +1069,12 @@ char *line; switch (i.disps[0]->X_seg) { case SEG_ABSOLUTE: - if (FITS_IN_SIGNED_BYTE (n)) { + if (fits_in_signed_byte(n)) { p = frag_more (2); p[0] = t->base_opcode; p[1] = n; #if 0 /* leave out 16 bit jumps - pace */ - } else if (FITS_IN_SIGNED_WORD (n)) { + } else if (fits_in_signed_word(n)) { p = frag_more (4); p[0] = WORD_PREFIX_OPCODE; p[1] = t->base_opcode; @@ -1106,7 +1121,7 @@ char *line; int size = (t->opcode_modifier & JumpByte) ? 1 : 4; int n = i.disps[0]->X_add_number; - if (FITS_IN_UNSIGNED_BYTE(t->base_opcode)) { + if (fits_in_unsigned_byte(t->base_opcode)) { FRAG_APPEND_1_CHAR (t->base_opcode); } else { p = frag_more (2); /* opcode can be at most two bytes */ @@ -1119,7 +1134,7 @@ char *line; switch (i.disps[0]->X_seg) { case SEG_ABSOLUTE: md_number_to_chars (p, n, size); - if (size == 1 && ! FITS_IN_SIGNED_BYTE (n)) { + if (size == 1 && ! fits_in_signed_byte(n)) { as_bad("loop/jecx only takes byte displacement; %d shortened to %d", n, *p); } @@ -1145,7 +1160,7 @@ char *line; md_number_to_chars (p + 5, i.imms[0]->X_add_number, 2); } else { /* Output normal instructions here. */ - register char *q; + unsigned char *q; /* First the prefix bytes. */ for (q = i.prefix; q < i.prefix + i.prefixes; q++) { @@ -1154,9 +1169,9 @@ char *line; } /* Now the opcode; be careful about word order here! */ - if (FITS_IN_UNSIGNED_BYTE(t->base_opcode)) { + if (fits_in_unsigned_byte(t->base_opcode)) { FRAG_APPEND_1_CHAR (t->base_opcode); - } else if (FITS_IN_UNSIGNED_WORD(t->base_opcode)) { + } else if (fits_in_unsigned_word(t->base_opcode)) { p = frag_more (2); /* put out high byte first: can't use md_number_to_chars! */ *p++ = (t->base_opcode >> 8) & 0xff; @@ -1271,8 +1286,8 @@ char *operand_string; char * end_of_operand_string = operand_string + strlen(operand_string); /* Start and end of displacement string expression (if found). */ - char * displacement_string_start = 0; - char * displacement_string_end; + char *displacement_string_start = NULL; + char *displacement_string_end = NULL; /* We check for an absolute prefix (differentiating, for example, 'jmp pc_relative_label' from 'jmp *absolute_label'. */ @@ -1283,8 +1298,8 @@ char *operand_string; /* Check if operand is a register. */ if (*op_string == REGISTER_PREFIX) { - register reg_entry * r; - if (! (r = parse_register (op_string))) { + register reg_entry *r; + if (!(r = parse_register (op_string))) { as_bad("bad register name ('%s')", op_string); return 0; } @@ -1323,19 +1338,22 @@ char *operand_string; i.regs[this_operand] = r; i.reg_operands++; } else if (*op_string == IMMEDIATE_PREFIX) { /* ... or an immediate */ - char * save_input_line_pointer; - register expressionS *exp; - segT exp_seg; + char *save_input_line_pointer; + segT exp_seg = SEG_GOOF; + expressionS *exp; + if (i.imm_operands == MAX_IMMEDIATE_OPERANDS) { as_bad("only 1 or 2 immediate operands are allowed"); return 0; } + exp = &im_expressions[i.imm_operands++]; - i.imms [this_operand] = exp; + i.imms[this_operand] = exp; save_input_line_pointer = input_line_pointer; input_line_pointer = ++op_string; /* must advance op_string! */ - exp_seg = expression (exp); + exp_seg = expression(exp); input_line_pointer = save_input_line_pointer; + switch (exp_seg) { case SEG_ABSENT: /* missing or bad expr becomes absolute 0 */ as_bad("missing or invalid immediate expression '%s' taken as 0", @@ -1347,7 +1365,7 @@ char *operand_string; i.types[this_operand] |= Imm; break; case SEG_ABSOLUTE: - i.types[this_operand] |= SMALLEST_IMM_TYPE (exp->X_add_number); + i.types[this_operand] |= smallest_imm_type(exp->X_add_number); break; case SEG_TEXT: case SEG_DATA: case SEG_BSS: case SEG_UNKNOWN: i.types[this_operand] |= Imm32; /* this is an address ==> 32bit */ @@ -1511,16 +1529,16 @@ char *operand_string; assuming displacement_string_start and displacement_string_end are meaningful. */ if (displacement_string_start) { - register expressionS * exp; - segT exp_seg; - char * save_input_line_pointer; + register expressionS *exp; + segT exp_seg = SEG_GOOF; + char *save_input_line_pointer; exp = &disp_expressions[i.disp_operands]; i.disps [this_operand] = exp; i.disp_operands++; save_input_line_pointer = input_line_pointer; input_line_pointer = displacement_string_start; END_STRING_AND_SAVE (displacement_string_end); - exp_seg = expression (exp); + exp_seg = expression(exp); if(*input_line_pointer) as_bad("Ignoring junk '%s' after expression",input_line_pointer); RESTORE_END_STRING (displacement_string_end); @@ -1641,10 +1659,11 @@ void object_headers *headers; register fragS * fragP; { - register unsigned char * opcode; - unsigned char * where_to_put_displacement; - unsigned int target_address, opcode_address; - unsigned int extension; + register unsigned char *opcode; + unsigned char *where_to_put_displacement = NULL; + unsigned int target_address; + unsigned int opcode_address; + unsigned int extension = 0; int displacement_from_opcode_start; opcode = (unsigned char *) fragP -> fr_opcode; @@ -1860,26 +1879,24 @@ relax_addressT segment_address_in_file; */ static unsigned char nbytes_r_length [] = { 42, 0, 1, 42, 2 }; - long r_index; + long r_symbolnum; know(fixP->fx_addsy != NULL); - r_index = (S_IS_DEFINED(fixP->fx_addsy) - ? S_GET_TYPE(fixP->fx_addsy) - : fixP->fx_addsy->sy_number); - - /* this is easy */ md_number_to_chars(where, fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file, 4); - /* now the fun stuff */ - where[4] = r_index & 0x0ff; - where[5] = (r_index >> 8) & 0x0ff; - where[6] = (r_index >> 16) & 0x0ff; + r_symbolnum = (S_IS_DEFINED(fixP->fx_addsy) + ? S_GET_TYPE(fixP->fx_addsy) + : fixP->fx_addsy->sy_number); + + where[6] = (r_symbolnum >> 16) & 0x0ff; + where[5] = (r_symbolnum >> 8) & 0x0ff; + where[4] = r_symbolnum & 0x0ff; where[7] = ((((!S_IS_DEFINED(fixP->fx_addsy)) << 3) & 0x08) | ((nbytes_r_length[fixP->fx_size] << 1) & 0x06) - | ((fixP->fx_pcrel << 0) & 0x01) & 0x0f); + | (((fixP->fx_pcrel << 0) & 0x01) & 0x0f)); return; } /* tc_aout_fix_to_chars() */ @@ -2006,6 +2023,66 @@ fixS *fixP; return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address; } + /* these were macros, but I don't trust macros that eval their + arguments more than once. Besides, gcc can static inline them. + xoxorich. */ + +static unsigned long mode_from_disp_size(t) +unsigned long t; +{ + return((t & (Disp8)) + ? 1 + : ((t & (Disp32)) ? 2 : 0)); +} /* mode_from_disp_size() */ + +/* convert opcode suffix ('b' 'w' 'l' typically) into type specifyer */ + +static unsigned long opcode_suffix_to_type(s) +unsigned long s; +{ + return(s == BYTE_OPCODE_SUFFIX + ? Byte : (s == WORD_OPCODE_SUFFIX + ? Word : DWord)); +} /* opcode_suffix_to_type() */ + +static int fits_in_signed_byte(num) +long num; +{ + return((num >= -128) && (num <= 127)); +} /* fits_in_signed_byte() */ + +static int fits_in_unsigned_byte(num) +long num; +{ + return((num & 0xff) == num); +} /* fits_in_unsigned_byte() */ + +static int fits_in_unsigned_word(num) +long num; +{ + return((num & 0xffff) == num); +} /* fits_in_unsigned_word() */ + +static int fits_in_signed_word(num) +long num; +{ + return((-32768 <= num) && (num <= 32767)); +} /* fits_in_signed_word() */ + +static int smallest_imm_type(num) +long num; +{ + return((num == 1) + ? (Imm1|Imm8|Imm8S|Imm16|Imm32) + : (fits_in_signed_byte(num) + ? (Imm8S|Imm8|Imm16|Imm32) + : (fits_in_unsigned_byte(num) + ? (Imm8|Imm16|Imm32) + : ((fits_in_signed_word(num) || fits_in_unsigned_word(num)) + ? (Imm16|Imm32) + : (Imm32))))); +} /* smallest_imm_type() */ + /* * Local Variables: * comment-column: 0 |