📄 i386.c
字号:
switch (num) { /* must be 1 digit scale */ case 1: i.log2_scale_factor = 0; break; case 2: i.log2_scale_factor = 1; break; case 4: i.log2_scale_factor = 2; break; case 8: i.log2_scale_factor = 3; break; default: as_bad ("expecting scale factor of 1, 2, 4, 8; got %d", num); return 0; } } else { if (! i.index_reg && *base_string == ',') { as_bad ("expecting index register or scale factor after ','; got '%c'", *(base_string+1)); return 0; } } } /* If there's an expression begining the operand, parse it, 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; 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); if(*input_line_pointer) as_bad("Ignoring junk '%s' after expression",input_line_pointer); RESTORE_END_STRING (displacement_string_end); input_line_pointer = save_input_line_pointer; switch (exp_seg) { case SEG_NONE: /* missing expr becomes absolute 0 */ as_bad ("missing or invalid displacement '%s' taken as 0", operand_string); i.types[this_operand] |= (Disp|Abs); exp->X_seg = SEG_ABSOLUTE; exp->X_add_number = 0; exp->X_add_symbol = (symbolS *) 0; exp->X_subtract_symbol = (symbolS *) 0; break; case SEG_ABSOLUTE: i.types[this_operand] |= SMALLEST_DISP_TYPE (exp->X_add_number); break; case SEG_TEXT: case SEG_DATA: case SEG_BSS: case SEG_UNKNOWN: /* must be 32 bit displacement (i.e. address) */ i.types[this_operand] |= Disp32; break; default: goto seg_unimplemented; } } /* Make sure the memory operand we've been dealt is valid. */ if (i.base_reg && i.index_reg && ! (i.base_reg->reg_type & i.index_reg->reg_type & Reg)) { as_bad ("register size mismatch in (base,index,scale) expression"); return 0; } if ((i.base_reg && (i.base_reg->reg_type & Reg32) == 0) || (i.index_reg && (i.index_reg->reg_type & Reg32) == 0)) { as_bad ("base/index register must be 32 bit register"); return 0; } if (i.index_reg && i.index_reg == esp) { as_bad ("%s may not be used as an index register", esp->reg_name); return 0; } } else { /* it's not a memory operand; argh! */ as_bad ("invalid char %s begining %s operand '%s'", output_invalid(*op_string), ordinal_names[this_operand], op_string); return 0; } return 1; /* normal return */}/* * md_estimate_size_before_relax() * * Called just before relax(). * Any symbol that is now undefined will not become defined. * Return the correct fr_subtype in the frag. * Return the initial "guess for fr_var" to caller. * The guess for fr_var is ACTUALLY the growth beyond fr_fix. * Whatever we do to grow fr_fix or fr_var contributes to our returned value. * Although it may not be explicit in the frag, pretend fr_var starts with a * 0 value. */intmd_estimate_size_before_relax (fragP, segment_type) register fragS * fragP; register int segment_type; /* N_DATA or N_TEXT. */{ register uchar * opcode; register int old_fr_fix; old_fr_fix = fragP -> fr_fix; opcode = (uchar *) fragP -> fr_opcode; /* We've already got fragP->fr_subtype right; all we have to do is check for un-relaxable symbols. */ if ((fragP -> fr_symbol -> sy_type & N_TYPE) != segment_type) { /* symbol is undefined in this segment */ switch (opcode[0]) { case JUMP_PC_RELATIVE: /* make jmp (0xeb) a dword displacement jump */ opcode[0] = 0xe9; /* dword disp jmp */ fragP -> fr_fix += 4; fix_new (fragP, old_fr_fix, 4, fragP -> fr_symbol, (symbolS *) 0, fragP -> fr_offset, 1); break; default: /* This changes the byte-displacement jump 0x7N --> the dword-displacement jump 0x0f8N */ opcode[1] = opcode[0] + 0x10; opcode[0] = TWO_BYTE_OPCODE_ESCAPE; /* two-byte escape */ fragP -> fr_fix += 1 + 4; /* we've added an opcode byte */ fix_new (fragP, old_fr_fix + 1, 4, fragP -> fr_symbol, (symbolS *) 0, fragP -> fr_offset, 1); break; } frag_wane (fragP); } return (fragP -> fr_var + fragP -> fr_fix - old_fr_fix);} /* md_estimate_size_before_relax() *//* * md_convert_frag(); * * Called after relax() is finished. * In: Address of frag. * fr_type == rs_machine_dependent. * fr_subtype is what the address relaxed to. * * Out: Any fixSs and constants are set up. * Caller will turn frag into a ".space 0". */voidmd_convert_frag (fragP) register fragS * fragP;{ register uchar * opcode; uchar * where_to_put_displacement; uint target_address, opcode_address; uint extension; int displacement_from_opcode_start; opcode = (uchar *) fragP -> fr_opcode; /* Address we want to reach in file space. */ target_address = fragP->fr_symbol->sy_value + fragP->fr_offset; /* Address opcode resides at in file space. */ opcode_address = fragP->fr_address + fragP->fr_fix; /* Displacement from opcode start to fill into instruction. */ displacement_from_opcode_start = target_address - opcode_address; switch (fragP->fr_subtype) { case ENCODE_RELAX_STATE (COND_JUMP, BYTE): case ENCODE_RELAX_STATE (UNCOND_JUMP, BYTE): /* don't have to change opcode */ extension = 1; /* 1 opcode + 1 displacement */ where_to_put_displacement = &opcode[1]; break; case ENCODE_RELAX_STATE (COND_JUMP, WORD): opcode[1] = TWO_BYTE_OPCODE_ESCAPE; opcode[2] = opcode[0] + 0x10; opcode[0] = WORD_PREFIX_OPCODE; extension = 4; /* 3 opcode + 2 displacement */ where_to_put_displacement = &opcode[3]; break; case ENCODE_RELAX_STATE (UNCOND_JUMP, WORD): opcode[1] = 0xe9; opcode[0] = WORD_PREFIX_OPCODE; extension = 3; /* 2 opcode + 2 displacement */ where_to_put_displacement = &opcode[2]; break; case ENCODE_RELAX_STATE (COND_JUMP, DWORD): opcode[1] = opcode[0] + 0x10; opcode[0] = TWO_BYTE_OPCODE_ESCAPE; extension = 5; /* 2 opcode + 4 displacement */ where_to_put_displacement = &opcode[2]; break; case ENCODE_RELAX_STATE (UNCOND_JUMP, DWORD): opcode[0] = 0xe9; extension = 4; /* 1 opcode + 4 displacement */ where_to_put_displacement = &opcode[1]; break; default: BAD_CASE(fragP -> fr_subtype); break; } /* now put displacement after opcode */ md_number_to_chars (where_to_put_displacement, displacement_from_opcode_start - extension, SIZE_FROM_RELAX_STATE (fragP->fr_subtype)); fragP -> fr_fix += extension;}int md_short_jump_size = 2; /* size of byte displacement jmp */int md_long_jump_size = 5; /* size of dword displacement jmp */void md_create_short_jump(ptr, from_addr, to_addr) char *ptr; long from_addr, to_addr;{ long offset; offset = to_addr - (from_addr + 2); md_number_to_chars (ptr, (long) 0xeb, 1); /* opcode for byte-disp jump */ md_number_to_chars (ptr + 1, offset, 1);}void md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; long from_addr, to_addr; fragS *frag; symbolS *to_symbol;{ long offset; if (flagseen['m']) { offset = to_addr - to_symbol->sy_value; md_number_to_chars (ptr, 0xe9, 1); /* opcode for long jmp */ md_number_to_chars (ptr + 1, offset, 4); fix_new (frag, (ptr+1) - frag->fr_literal, 4, to_symbol, (symbolS *) 0, (long int) 0, 0); } else { offset = to_addr - (from_addr + 5); md_number_to_chars(ptr, (long) 0xe9, 1); md_number_to_chars(ptr + 1, offset, 4); }}intmd_parse_option(argP,cntP,vecP)char **argP;int *cntP;char ***vecP;{ return 1;}void /* Knows about order of bytes in address. */md_number_to_chars (con, value, nbytes) char con []; /* Return 'nbytes' of chars here. */ long int value; /* The value of the bits. */ int nbytes; /* Number of bytes in the output. */{ register char * p = con; switch (nbytes) { case 1: p[0] = value & 0xff; break; case 2: p[0] = value & 0xff; p[1] = (value >> 8) & 0xff; break; case 4: p[0] = value & 0xff; p[1] = (value>>8) & 0xff; p[2] = (value>>16) & 0xff; p[3] = (value>>24) & 0xff; break; default: BAD_CASE (nbytes); }}void /* Knows about order of bytes in address. */md_number_to_disp (con, value, nbytes) char con []; /* Return 'nbytes' of chars here. */ long int value; /* The value of the bits. */ int nbytes; /* Number of bytes in the output. */{ char * answer = alloca (nbytes); register char * p = answer; switch (nbytes) { case 1: *p = value; break; case 2: *p++ = value; *p = (value>>8); break; case 4: *p++ = value; *p++ = (value>>8); *p++ = (value>>16); *p = (value>>24); break; default: BAD_CASE (nbytes); } bcopy (answer, con, nbytes);}void /* Knows about order of bytes in address. */md_number_to_imm (con, value, nbytes) char con []; /* Return 'nbytes' of chars here. */ long int value; /* The value of the bits. */ int nbytes; /* Number of bytes in the output. */{ char * answer = alloca (nbytes); register char * p = answer; switch (nbytes) { case 1: *p = value; break; case 2: *p++ = value; *p = (value>>8); break; case 4: *p++ = value; *p++ = (value>>8); *p++ = (value>>16); *p = (value>>24); break; default: BAD_CASE (nbytes); } bcopy (answer, con, nbytes);}void /* Knows about order of bytes in address. */md_number_to_field (con, value, nbytes) char con []; /* Return 'nbytes' of chars here. */ long int value; /* The value of the bits. */ int nbytes; /* Number of bytes in the output. */{ char * answer = alloca (nbytes); register char * p = answer; switch (nbytes) { case 1: *p = value; break; case 2: *p++ = value; *p = (value>>8); break; case 4: *p++ = value; *p++ = (value>>8); *p++ = (value>>16); *p = (value>>24); break; default: BAD_CASE (nbytes); } bcopy (answer, con, nbytes);}long int /* Knows about the byte order in a word. */md_chars_to_number (con, nbytes)unsigned char con[]; /* Low order byte 1st. */ int nbytes; /* Number of bytes in the input. */{ long int retval; for (retval=0, con+=nbytes-1; nbytes--; con--) { retval <<= BITS_PER_CHAR; retval |= *con; } return retval;}void md_ri_to_chars(ri_p, ri) struct relocation_info *ri_p, ri;{ unsigned char the_bytes[8]; /* this is easy */ md_number_to_chars(the_bytes, ri.r_address, sizeof(ri.r_address)); /* now the fun stuff */ the_bytes[6] = (ri.r_symbolnum >> 16) & 0x0ff; the_bytes[5] = (ri.r_symbolnum >> 8) & 0x0ff; the_bytes[4] = ri.r_symbolnum & 0x0ff; the_bytes[7] = (((ri.r_extern << 3) & 0x08) | ((ri.r_length << 1) & 0x06) | ((ri.r_pcrel << 0) & 0x01)) & 0x0F; /* now put it back where you found it */ bcopy (the_bytes, (char *)ri_p, sizeof(struct relocation_info));}#define MAX_LITTLENUMS 6/* Turn the string pointed to by litP into a floating point constant of type type, and emit the appropriate bytes. The number of LITTLENUMS emitted is stored in *sizeP . An error message is returned, or NULL on OK. */char *md_atof(type,litP,sizeP) char type; char *litP; int *sizeP;{ int prec; LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE *wordP; char *t; char *atof_ieee(); switch(type) { case 'f': case 'F': prec = 2; break; case 'd': case 'D': prec = 4; break; case 'x': case 'X': prec = 5; break; default: *sizeP=0; return "Bad call to md_atof ()"; } t = atof_ieee (input_line_pointer,type,words); if(t) input_line_pointer=t; *sizeP = prec * sizeof(LITTLENUM_TYPE); /* this loops outputs the LITTLENUMs in REVERSE order; in accord with the bigendian 386 */ for(wordP = words + prec - 1;prec--;) { md_number_to_chars (litP, (long) (*wordP--), sizeof(LITTLENUM_TYPE)); litP += sizeof(LITTLENUM_TYPE); } return ""; /* Someone should teach Dean about null pointers */}char output_invalid_buf[8];char * output_invalid (c) char c;{ if (isprint(c)) sprintf (output_invalid_buf, "'%c'", c); else sprintf (output_invalid_buf, "(0x%x)", c); return output_invalid_buf;}reg_entry *parse_register (reg_string) char *reg_string; /* reg_string starts *before* REGISTER_PREFIX */{ register char *s = reg_string; register char *p; char reg_name_given[MAX_REG_NAME_SIZE]; s++; /* skip REGISTER_PREFIX */ for (p = reg_name_given; is_register_char (*s); p++, s++) { *p = register_chars [*s]; if (p >= reg_name_given + MAX_REG_NAME_SIZE) return (reg_entry *) 0; } *p = '\0'; return (reg_entry *) hash_find (reg_hash, reg_name_given);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -