tc-m88k.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,462 行 · 第 1/2 页
C
1,462 行
unsigned offset = 0; unsigned width = 0; char *xp; char *save_ptr; xp = get_bf2 (param, '<'); save_ptr = input_line_pointer; input_line_pointer = param; if (*xp == 0) { /* We did not find '<'. We have an offset (width implicitly 32). */ param = get_bf_offset_expression (param, &offset); input_line_pointer = save_ptr; if (param == NULL) return NULL; } else { *xp++ = 0; /* Overwrite the '<' */ param = get_bf2 (xp, '>'); if (*param == 0) return NULL; *param++ = 0; /* Overwrite the '>' */ width = get_absolute_expression (); xp = get_bf_offset_expression (xp, &offset); input_line_pointer = save_ptr; if (xp + 1 != param) return NULL; } *valp = ((width % 32) << 5) | (offset % 32); return param;}static char *get_cr (param, regnop) char *param; unsigned *regnop;{ unsigned regno; unsigned c; if (!strncmp (param, "cr", 2)) { param += 2; regno = *param++ - '0'; if (regno < 10) { if (regno == 0) { *regnop = 0; return param; } c = *param - '0'; if (c < 10) { regno = regno * 10 + c; if (c < 64) { *regnop = regno; return param + 1; } } else { *regnop = regno; return param; } } return NULL; } param = match_name (param, cr_regs, regnop); return param;}static char *get_fcr (param, regnop) char *param; unsigned *regnop;{ unsigned regno; unsigned c; if (!strncmp (param, "fcr", 3)) { param += 3; regno = *param++ - '0'; if (regno < 10) { if (regno == 0) { *regnop = 0; return param; } c = *param - '0'; if (c < 10) { regno = regno * 10 + c; if (c < 64) { *regnop = regno; return param + 1; } } else { *regnop = regno; return param; } } return NULL; } param = match_name (param, fcr_regs, regnop); return param;}static char *get_vec9 (param, valp) char *param; unsigned *valp;{ unsigned val; char *save_ptr; save_ptr = input_line_pointer; input_line_pointer = param; val = get_absolute_expression (); param = input_line_pointer; input_line_pointer = save_ptr; if (val >= 1 << 9) as_warn (_("Expression truncated to 9 bits")); *valp = val % (1 << 9); return param;}static char *get_o6 (param, valp) char *param; unsigned *valp;{ unsigned val; char *save_ptr; save_ptr = input_line_pointer; input_line_pointer = param; val = get_absolute_expression (); param = input_line_pointer; input_line_pointer = save_ptr; if (val & 0x3) as_warn (_("Removed lower 2 bits of expression")); *valp = val; return(param);}#define hexval(z) \ (isdigit (z) ? (z) - '0' : \ islower (z) ? (z) - 'a' + 10 : \ isupper (z) ? (z) - 'A' + 10 : -1)static char *getval (param, valp) char *param; unsigned int *valp;{ unsigned int val = 0; unsigned int c; c = *param++; if (c == '0') { c = *param++; if (c == 'x' || c == 'X') { c = *param++; c = hexval (c); while (c < 16) { val = val * 16 + c; c = *param++; c = hexval (c); } } else { c -= '0'; while (c < 8) { val = val * 8 + c; c = *param++ - '0'; } } } else { c -= '0'; while (c < 10) { val = val * 10 + c; c = *param++ - '0'; } } *valp = val; return param - 1;}voidmd_number_to_chars (buf, val, nbytes) char *buf; valueT val; int nbytes;{ number_to_chars_bigendian (buf, val, nbytes);}#if 0/* This routine is never called. What is it for? Ian Taylor, Cygnus Support 13 Jul 1993 */voidmd_number_to_imm (buf, val, nbytes, fixP, seg_type) unsigned char *buf; unsigned int val; int nbytes; fixS *fixP; int seg_type;{ if (seg_type != N_TEXT || fixP->fx_r_type == NO_RELOC) { switch (nbytes) { case 4: *buf++ = val >> 24; *buf++ = val >> 16; case 2: *buf++ = val >> 8; case 1: *buf = val; break; default: abort (); } return; } switch (fixP->fx_r_type) { case RELOC_IW16: buf[2] = val >> 8; buf[3] = val; break; case RELOC_LO16: buf[0] = val >> 8; buf[1] = val; break; case RELOC_HI16: buf[0] = val >> 24; buf[1] = val >> 16; break; case RELOC_PC16: val += 4; buf[0] = val >> 10; buf[1] = val >> 2; break; case RELOC_PC26: val += 4; buf[0] |= (val >> 26) & 0x03; buf[1] = val >> 18; buf[2] = val >> 10; buf[3] = val >> 2; break; case RELOC_32: buf[0] = val >> 24; buf[1] = val >> 16; buf[2] = val >> 8; buf[3] = val; break; default: as_fatal (_("Bad relocation type")); break; }}#endif /* 0 */voidmd_number_to_disp (buf, val, nbytes) char *buf; int val; int nbytes;{ as_fatal (_("md_number_to_disp not defined")); md_number_to_chars (buf, val, nbytes);}voidmd_number_to_field (buf, val, nbytes) char *buf; int val; int nbytes;{ as_fatal (_("md_number_to_field not defined")); md_number_to_chars (buf, val, nbytes);}#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; 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_ATOF()"); } t = atof_ieee (input_line_pointer, type, words); if (t) input_line_pointer = t; *sizeP = prec * sizeof (LITTLENUM_TYPE); for (wordP = words; prec--;) { md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE)); litP += sizeof (LITTLENUM_TYPE); } return 0;}int md_short_jump_size = 4;voidmd_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; addressT from_addr, to_addr; fragS *frag; symbolS *to_symbol;{ ptr[0] = (char) 0xc0; ptr[1] = 0x00; ptr[2] = 0x00; ptr[3] = 0x00; fix_new (frag, ptr - frag->fr_literal, 4, to_symbol, (offsetT) 0, 0, RELOC_PC26); /* Botch: Shouldn't this be RELOC_PC16? */}int md_long_jump_size = 4;voidmd_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; addressT from_addr, to_addr; fragS *frag; symbolS *to_symbol;{ ptr[0] = (char) 0xc0; ptr[1] = 0x00; ptr[2] = 0x00; ptr[3] = 0x00; fix_new (frag, ptr - frag->fr_literal, 4, to_symbol, (offsetT) 0, 0, RELOC_PC26);}intmd_estimate_size_before_relax (fragP, segment_type) fragS *fragP; segT segment_type;{ as_fatal (_("Relaxation should never occur")); return (-1);}#if 0/* As far as I can tell, this routine is never called. What is it doing here? Ian Taylor, Cygnus Support 13 Jul 1993 *//* * Risc relocations are completely different, so it needs * this machine dependent routine to emit them. */voidemit_relocations (fixP, segment_address_in_file) fixS *fixP; relax_addressT segment_address_in_file;{ struct reloc_info_m88k ri; symbolS *symbolP; extern char *next_object_file_charP; bzero ((char *) &ri, sizeof (ri)); for (; fixP; fixP = fixP->fx_next) { if (fixP->fx_r_type >= NO_RELOC) { fprintf (stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type); abort (); } if ((symbolP = fixP->fx_addsy) != NULL) { ri.r_address = fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file; if ((symbolP->sy_type & N_TYPE) == N_UNDF) { ri.r_extern = 1; ri.r_symbolnum = symbolP->sy_number; } else { ri.r_extern = 0; ri.r_symbolnum = symbolP->sy_type & N_TYPE; } if (symbolP && symbol_get_frag (symbolP)) { ri.r_addend = symbol_get_frag (symbolP)->fr_address; } ri.r_type = fixP->fx_r_type; if (fixP->fx_pcrel) { ri.r_addend -= ri.r_address; } else { ri.r_addend = fixP->fx_addnumber; } append (&next_object_file_charP, (char *) &ri, sizeof (ri)); } }}#endif /* 0 */#if 0/* This routine can be subsumed by s_lcomm in read.c. Ian Taylor, Cygnus Support 13 Jul 1993 */static voids_bss (){ char *name; char c; char *p; int temp, bss_align; symbolS *symbolP; name = input_line_pointer; c = get_symbol_end (); p = input_line_pointer; *p = c; SKIP_WHITESPACE (); if (*input_line_pointer != ',') { as_warn (_("Expected comma after name")); ignore_rest_of_line (); return; } input_line_pointer++; if ((temp = get_absolute_expression ()) < 0) { as_warn (_("BSS length (%d.) <0! Ignored."), temp); ignore_rest_of_line (); return; } *p = 0; symbolP = symbol_find_or_make (name); *p = c; if (*input_line_pointer == ',') { input_line_pointer++; bss_align = get_absolute_expression (); } else bss_align = 0; if (!S_IS_DEFINED(symbolP) || S_GET_SEGMENT(symbolP) == SEG_BSS) { if (! need_pass_2) { char *p; segT current_seg = now_seg; subsegT current_subseg = now_subseg; subseg_set (SEG_BSS, 1); /* switch to bss */ if (bss_align) frag_align (bss_align, 0, 0); /* detach from old frag */ if (symbolP->sy_type == N_BSS && symbol_get_frag (symbolP) != NULL) symbol_get_frag (symbolP)->fr_symbol = NULL; symbol_set_frag (symbolP, frag_now); p = frag_var (rs_org, 1, 1, (relax_substateT)0, symbolP, (offsetT) temp, (char *)0); *p = 0; S_SET_SEGMENT (symbolP, SEG_BSS); subseg_set (current_seg, current_subseg); } } else { as_warn (_("Ignoring attempt to re-define symbol %s."), name); } while (!is_end_of_line[(unsigned char) *input_line_pointer]) { input_line_pointer++; }}#endif /* 0 */#ifdef M88KCOFF/* These functions are needed if we are linking with obj-coffbfd.c. That file may be replaced by a more BFD oriented version at some point. If that happens, these functions should be rexamined. Ian Lance Taylor, Cygnus Support, 13 July 1993. *//* Given a fixS structure (created by a call to fix_new, above), return the BFD relocation type to use for it. */shorttc_coff_fix2rtype (fixp) fixS *fixp;{ switch (fixp->fx_r_type) { case RELOC_LO16: return R_LVRT16; case RELOC_HI16: return R_HVRT16; case RELOC_PC16: return R_PCR16L; case RELOC_PC26: return R_PCR26L; case RELOC_32: return R_VRT32; case RELOC_IW16: return R_VRT16; default: abort (); }}/* Apply a fixS to the object file. Since COFF does not use addends in relocs, the addend is actually stored directly in the object file itself. */voidmd_apply_fix (fixp, val) fixS *fixp; long val;{ char *buf; buf = fixp->fx_frag->fr_literal + fixp->fx_where; fixp->fx_offset = 0; switch (fixp->fx_r_type) { case RELOC_IW16: fixp->fx_offset = val >> 16; buf[2] = val >> 8; buf[3] = val; break; case RELOC_LO16: fixp->fx_offset = val >> 16; buf[0] = val >> 8; buf[1] = val; break; case RELOC_HI16: fixp->fx_offset = val >> 16; buf[0] = val >> 8; buf[1] = val; break; case RELOC_PC16: buf[0] = val >> 10; buf[1] = val >> 2; break; case RELOC_PC26: buf[0] |= (val >> 26) & 0x03; buf[1] = val >> 18; buf[2] = val >> 10; buf[3] = val >> 2; break; case RELOC_32: buf[0] = val >> 24; buf[1] = val >> 16; buf[2] = val >> 8; buf[3] = val; break; default: abort (); }}/* Where a PC relative offset is calculated from. On the m88k they are calculated from just after the instruction. */longmd_pcrel_from (fixp) fixS *fixp;{ switch (fixp->fx_r_type) { case RELOC_PC16: return fixp->fx_frag->fr_address + fixp->fx_where - 2; case RELOC_PC26: return fixp->fx_frag->fr_address + fixp->fx_where; default: abort (); } /*NOTREACHED*/}/* Fill in rs_align_code fragments. */voidm88k_handle_align (fragp) fragS *fragp;{ static const unsigned char nop_pattern[] = { 0xf4, 0x00, 0x58, 0x00 }; int bytes; char *p; if (fragp->fr_type != rs_align_code) return; bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; p = fragp->fr_literal + fragp->fr_fix; if (bytes & 3) { int fix = bytes & 3; memset (p, 0, fix); p += fix; bytes -= fix; fragp->fr_fix += fix; } memcpy (p, nop_pattern, 4); fragp->fr_var = 4;}#endif /* M88KCOFF */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?