📄 tc-w65.c
字号:
for (; opcode->code == ocode; opcode++) { if (opcode->amode == amode) return opcode; } return 0;}intcheck (operand, low, high) expressionS *operand; int low; int high;{ if (operand->X_op != O_constant || operand->X_add_number < low || operand->X_add_number > high) { as_bad ("operand must be absolute in range %d..%d", low, high); } return operand->X_add_number;}static int log2[] = { 0, 0, 1, 0, 2 };/* Now we know what sort of opcodes it is, let's build the bytes. */static voidbuild_Mytes (opcode) struct opinfo *opcode;{ int size; int type; int pcrel; char *output; if (opcode->amode == ADDR_IMPLIED) { output = frag_more (1); } else if (opcode->amode == ADDR_PC_REL) { int type; /* This is a relaxable insn, so we do some special handling. */ type = opcode->val == OP_BRA ? UNCOND_BRANCH : COND_BRANCH; output = frag_var (rs_machine_dependent, md_relax_table[C (type, WORD_DISP)].rlx_length, md_relax_table[C (type, BYTE_DISP)].rlx_length, C (type, UNDEF_BYTE_DISP), immediate.X_add_symbol, immediate.X_add_number, 0); } else { switch (opcode->amode) { GETINFO (size, type, pcrel); } /* If something special was done in the expression modify the reloc type. */ if (tc_cons_reloc) type = tc_cons_reloc; /* 1 byte for the opcode + the bytes for the addrmode. */ output = frag_more (size + 1); if (opcode->amode == ADDR_BLOCK_MOVE) { /* Two relocs for this one. */ fix_new_exp (frag_now, output + 1 - frag_now->fr_literal, 1, &immediate, 0, R_W65_ABS8S16); fix_new_exp (frag_now, output + 2 - frag_now->fr_literal, 1, &immediate1, 0, R_W65_ABS8S16); } else if (type >= 0 && opcode->amode != ADDR_IMPLIED && opcode->amode != ADDR_ACC && opcode->amode != ADDR_STACK) { fix_new_exp (frag_now, output + 1 - frag_now->fr_literal, size, &immediate, pcrel, type); } } output[0] = opcode->val;}/* This is the guts of the machine-dependent assembler. STR points to a machine dependent instruction. This function is supposed to emit the frags/bytes it assembles to. */voidmd_assemble (str) char *str;{ unsigned char *op_start; unsigned char *op_end; struct opinfo *opcode; char name[20]; int nlen = 0; char *p; /* Drop leading whitespace */ while (*str == ' ') str++; /* all opcodes are three letters */ name[0] = str[0]; name[1] = str[1]; name[2] = str[2]; name[3] = 0; tc_cons_reloc = 0; str += 3; opcode = (struct opinfo *) hash_find (opcode_hash_control, name); if (opcode == NULL) { as_bad (_("unknown opcode")); return; } if (opcode->amode != ADDR_IMPLIED && opcode->amode != ADDR_STACK) { get_operands (opcode, str); opcode = get_specific (opcode); } if (opcode == 0) { /* Couldn't find an opcode which matched the operands. */ char *where = frag_more (1); where[0] = 0x0; where[1] = 0x0; as_bad (_("invalid operands for opcode")); return; } build_Mytes (opcode);}voidtc_crawl_symbol_chain (headers) object_headers *headers;{ printf (_("call to tc_crawl_symbol_chain \n"));}symbolS *md_undefined_symbol (name) char *name;{ return 0;}voidtc_headers_hook (headers) object_headers *headers;{ printf (_("call to tc_headers_hook \n"));}/* Various routines to kill one day. *//* Equal to MAX_PRECISION in atof-ieee.c. */#define MAX_LITTLENUMS 6/* Turn a string in input_line_pointer into a floating point constant of type TYPE, and store the appropriate bytes in *LITP. 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': case 's': case 'S': prec = 2; break; case 'd': case 'D': case 'r': case 'R': prec = 4; break; case 'x': case 'X': prec = 6; break; case 'p': case 'P': prec = 6; break; default: *sizeP = 0; return _("Bad call to MD_NTOF()"); } t = atof_ieee (input_line_pointer, type, words); if (t) input_line_pointer = t; *sizeP = prec * sizeof (LITTLENUM_TYPE); for (wordP = words + prec - 1; prec--;) { md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE)); litP += sizeof (LITTLENUM_TYPE); } return 0;}intmd_parse_option (c, a) int c; char *a;{ return 1;}voidtc_Nout_fix_to_chars (){ printf (_("call to tc_Nout_fix_to_chars \n")); abort ();}/* Called after relaxing, change the frags so they know how big they are. */voidmd_convert_frag (headers, seg, fragP) object_headers *headers; segT seg; fragS *fragP;{ int disp_size = 0; int inst_size = 0; unsigned char *buffer = (unsigned char *) (fragP->fr_fix + fragP->fr_literal); switch (fragP->fr_subtype) { case C (COND_BRANCH, BYTE_DISP): case C (UNCOND_BRANCH, BYTE_DISP): disp_size = 1; inst_size = 1; break; /* Conditional branches to a known 16 bit displacement. */ case C (COND_BRANCH, WORD_DISP): switch (buffer[0]) { case OP_BCC: case OP_BCS: case OP_BEQ: case OP_BMI: case OP_BNE: case OP_BPL: case OP_BVS: case OP_BVC: /* Invert the sense of the test */ buffer[0] ^= 0x20; buffer[1] = 3; /* Jump over following brl */ buffer[2] = OP_BRL; buffer[3] = 0; buffer[4] = 0; disp_size = 2; inst_size = 3; break; default: abort (); } break; case C (UNCOND_BRANCH, WORD_DISP): /* Unconditional branches to a known 16 bit displacement. */ switch (buffer[0]) { case OP_BRA: buffer[0] = OP_BRL; disp_size = 2; inst_size = 1; break; default: abort (); } break; /* Got to create a branch over a reloc here. */ case C (COND_BRANCH, UNDEF_WORD_DISP): buffer[0] ^= 0x20; /* invert test */ buffer[1] = 3; buffer[2] = OP_BRL; buffer[3] = 0; buffer[4] = 0; fix_new (fragP, fragP->fr_fix + 3, 4, fragP->fr_symbol, fragP->fr_offset, 0, R_W65_PCR16); fragP->fr_fix += disp_size + inst_size; fragP->fr_var = 0; break; case C (UNCOND_BRANCH, UNDEF_WORD_DISP): buffer[0] = OP_BRL; buffer[1] = 0; buffer[2] = 0; fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol, fragP->fr_offset, 0, R_W65_PCR16); fragP->fr_fix += disp_size + inst_size; fragP->fr_var = 0; break; default: abort (); } if (inst_size) { /* Get the address of the end of the instruction. */ int next_inst = (fragP->fr_fix + fragP->fr_address + disp_size + inst_size); int targ_addr = (S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset); int disp = targ_addr - next_inst; md_number_to_chars (buffer + inst_size, disp, disp_size); fragP->fr_fix += disp_size + inst_size; fragP->fr_var = 0; }}valueTmd_section_align (seg, size) segT seg; valueT size;{ return ((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg]));}voidmd_apply_fix (fixP, val) fixS *fixP; long val;{ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; int addr = fixP->fx_frag->fr_address + fixP->fx_where; if (fixP->fx_r_type == 0) { if (fixP->fx_size == 1) fixP->fx_r_type = R_W65_ABS8; else fixP->fx_r_type = R_W65_ABS16; } switch (fixP->fx_r_type) { case R_W65_ABS8S16: val >>= 8; case R_W65_ABS8S8: val >>= 8; case R_W65_ABS8: *buf++ = val; break; case R_W65_ABS16S16: val >>= 8; case R_W65_ABS16S8: val >>= 8; case R_W65_ABS16: *buf++ = val >> 0; *buf++ = val >> 8; break; case R_W65_ABS24: *buf++ = val >> 0; *buf++ = val >> 8; *buf++ = val >> 16; break; case R_W65_PCR8: *buf++ = val - addr - 1; break; case R_W65_PCR16: val = val - addr - 1; *buf++ = val; *buf++ = val >> 8; break; case R_W65_DP: *buf++ = val; break; default: abort (); }}/* Put number into target byte order */voidmd_number_to_chars (ptr, use, nbytes) char *ptr; valueT use; int nbytes;{ number_to_chars_littleendian (ptr, use, nbytes);}longmd_pcrel_from (fixP) fixS *fixP;{ int gap = fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address - 1; return gap;}voidtc_coff_symbol_emit_hook (x) symbolS *x;{}shorttc_coff_fix2rtype (fix_ptr) fixS *fix_ptr;{ return fix_ptr->fx_r_type;}voidtc_reloc_mangle (fix_ptr, intr, base) fixS *fix_ptr; struct internal_reloc *intr; bfd_vma base;{ symbolS *symbol_ptr; symbol_ptr = fix_ptr->fx_addsy; /* If this relocation is attached to a symbol then it's ok to output it */ if (fix_ptr->fx_r_type == RELOC_32) { /* cons likes to create reloc32's whatever the size of the reloc.. */ switch (fix_ptr->fx_size) { case 2: intr->r_type = R_IMM16; break; case 1: intr->r_type = R_IMM8; break; default: abort (); } } else { if (fix_ptr->fx_size == 4) intr->r_type = R_W65_ABS24; else intr->r_type = fix_ptr->fx_r_type; } intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base; intr->r_offset = fix_ptr->fx_offset; /* Turn the segment of the symbol into an offset. */ if (symbol_ptr) { symbolS *dot; dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot; if (dot) { intr->r_offset += S_GET_VALUE (symbol_ptr); intr->r_symndx = dot->sy_number; } else { intr->r_symndx = symbol_ptr->sy_number; } } else { intr->r_symndx = -1; }}inttc_coff_sizemachdep (frag) fragS *frag;{ return md_relax_table[frag->fr_subtype].rlx_length;}/* Called just before address relaxation, return the length by which a fragment must grow to reach it's destination. */intmd_estimate_size_before_relax (fragP, segment_type) register fragS *fragP; register segT segment_type;{ int what; switch (fragP->fr_subtype) { default: abort (); case C (COND_BRANCH, UNDEF_BYTE_DISP): case C (UNCOND_BRANCH, UNDEF_BYTE_DISP): what = GET_WHAT (fragP->fr_subtype); /* Used to be a branch to somewhere which was unknown. */ if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type) { /* Got a symbol and it's defined in this segment, become byte sized - maybe it will fix up. */ fragP->fr_subtype = C (what, BYTE_DISP); } else { /* Its got a segment, but its not ours, so it will always be long. */ fragP->fr_subtype = C (what, UNDEF_WORD_DISP); } break; case C (COND_BRANCH, BYTE_DISP): case C (COND_BRANCH, WORD_DISP): case C (COND_BRANCH, UNDEF_WORD_DISP): case C (UNCOND_BRANCH, BYTE_DISP): case C (UNCOND_BRANCH, WORD_DISP): case C (UNCOND_BRANCH, UNDEF_WORD_DISP): /* When relaxing a section for the second time, we don't need to do anything besides return the current size. */ break; } fragP->fr_var = md_relax_table[fragP->fr_subtype].rlx_length; return fragP->fr_var;}CONST char *md_shortopts = "";struct option md_longopts[] = {#define OPTION_RELAX (OPTION_MD_BASE) {NULL, no_argument, NULL, 0}};voidmd_show_usage (stream) FILE *stream;{}size_t md_longopts_size = sizeof (md_longopts);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -