tc-ns32k.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,407 行 · 第 1/4 页
C
2,407 行
__LINE__, __FILE__); }}/* Fast bitfiddling support. *//* Mask used to zero bitfield before oring in the true field. */static unsigned long l_mask[] ={ 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8, 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800, 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000, 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000, 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,};static unsigned long r_mask[] ={ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,};#define MASK_BITS 31/* Insert bitfield described by field_ptr and val at buf This routine is written for modification of the first 4 bytes pointed to by buf, to yield speed. The ifdef stuff is for selection between a ns32k-dependent routine and a general version. (My advice: use the general version!). */static voidmd_number_to_field (buf, val, field_ptr) register char *buf; register long val; register bit_fixS *field_ptr;{ register unsigned long object; register unsigned long mask; /* define ENDIAN on a ns32k machine */#ifdef ENDIAN register unsigned long *mem_ptr;#else register char *mem_ptr;#endif if (field_ptr->fx_bit_min <= val && val <= field_ptr->fx_bit_max) {#ifdef ENDIAN if (field_ptr->fx_bit_base) /* Override buf. */ mem_ptr = (unsigned long *) field_ptr->fx_bit_base; else mem_ptr = (unsigned long *) buf; mem_ptr = ((unsigned long *) ((char *) mem_ptr + field_ptr->fx_bit_base_adj));#else if (field_ptr->fx_bit_base) mem_ptr = (char *) field_ptr->fx_bit_base; else mem_ptr = buf; mem_ptr += field_ptr->fx_bit_base_adj;#endif#ifdef ENDIAN /* We have a nice ns32k machine with lowbyte at low-physical mem. */ object = *mem_ptr; /* get some bytes */#else /* OVE Goof! the machine is a m68k or dito */ /* That takes more byte fiddling. */ object = 0; object |= mem_ptr[3] & 0xff; object <<= 8; object |= mem_ptr[2] & 0xff; object <<= 8; object |= mem_ptr[1] & 0xff; object <<= 8; object |= mem_ptr[0] & 0xff;#endif mask = 0; mask |= (r_mask[field_ptr->fx_bit_offset]); mask |= (l_mask[field_ptr->fx_bit_offset + field_ptr->fx_bit_size]); object &= mask; val += field_ptr->fx_bit_add; object |= ((val << field_ptr->fx_bit_offset) & (mask ^ 0xffffffff));#ifdef ENDIAN *mem_ptr = object;#else mem_ptr[0] = (char) object; object >>= 8; mem_ptr[1] = (char) object; object >>= 8; mem_ptr[2] = (char) object; object >>= 8; mem_ptr[3] = (char) object;#endif } else { as_warn (_("Bit field out of range")); }}intmd_pcrel_adjust (fragP) fragS *fragP;{ fragS *opcode_frag; addressT opcode_address; unsigned int offset; opcode_frag = frag_opcode_frag (fragP); if (opcode_frag == 0) return 0; offset = frag_opcode_offset (fragP); opcode_address = offset + opcode_frag->fr_address; return fragP->fr_address + fragP->fr_fix - opcode_address;}intmd_fix_pcrel_adjust (fixP) fixS *fixP;{ fragS *fragP = fixP->fx_frag; fragS *opcode_frag; addressT opcode_address; unsigned int offset; opcode_frag = fix_opcode_frag (fixP); if (opcode_frag == 0) return 0; offset = fix_opcode_offset (fixP); opcode_address = offset + opcode_frag->fr_address; return fixP->fx_where + fixP->fx_frag->fr_address - opcode_address;}/* Apply a fixS (fixup of an instruction or data that we didn't have enough info to complete immediately) to the data in a frag. On the ns32k, everything is in a different format, so we have broken out separate functions for each kind of thing we could be fixing. They all get called from here. */#ifdef BFD_ASSEMBLERintmd_apply_fix (fixP, valp) fixS *fixP; valueT *valp;#elsevoidmd_apply_fix (fixP, val) fixS *fixP; long val;#endif{#ifdef BFD_ASSEMBLER long val = *valp;#endif fragS *fragP = fixP->fx_frag; char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; if (fix_bit_fixP (fixP)) { /* Bitfields to fix, sigh. */ md_number_to_field (buf, val, fix_bit_fixP (fixP)); } else switch (fix_im_disp (fixP)) { case 0: /* Immediate field. */ md_number_to_imm (buf, val, fixP->fx_size); break; case 1: /* Displacement field. */ /* Calculate offset */ { md_number_to_disp (buf, (fixP->fx_pcrel ? val + md_fix_pcrel_adjust (fixP) : val), fixP->fx_size); } break; case 2: /* Pointer in a data object. */ md_number_to_chars (buf, val, fixP->fx_size); break; }#ifdef BSD_ASSEMBLER return 1;#endif}/* Convert a relaxed displacement to ditto in final output */#ifndef BFD_ASSEMBLERvoidmd_convert_frag (headers, sec, fragP) object_headers *headers; segT sec; register fragS *fragP;#elsevoidmd_convert_frag (abfd, sec, fragP) bfd *abfd; segT sec; register fragS *fragP;#endif{ long disp; long ext = 0; /* Address in gas core of the place to store the displacement. */ register char *buffer_address = fragP->fr_fix + fragP->fr_literal; /* Address in object code of the displacement. */ int object_address; fragS *opcode_frag; switch (fragP->fr_subtype) { case IND (BRANCH, BYTE): ext = 1; break; case IND (BRANCH, WORD): ext = 2; break; case IND (BRANCH, DOUBLE): ext = 4; break; } if (ext == 0) return; know (fragP->fr_symbol); object_address = fragP->fr_fix + fragP->fr_address; /* The displacement of the address, from current location. */ disp = (S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset) - object_address;#ifdef BFD_ASSEMBLER disp += symbol_get_frag (fragP->fr_symbol)->fr_address;#endif disp += md_pcrel_adjust (fragP); md_number_to_disp (buffer_address, (long) disp, (int) ext); fragP->fr_fix += ext;}/* This function returns the estimated size a variable object will occupy, one can say that we tries to guess the size of the objects before we actually know it. */intmd_estimate_size_before_relax (fragP, segment) register fragS *fragP; segT segment;{ if (fragP->fr_subtype == IND (BRANCH, UNDEF)) { if (S_GET_SEGMENT (fragP->fr_symbol) != segment) { /* We don't relax symbols defined in another segment. The thing to do is to assume the object will occupy 4 bytes. */ fix_new_ns32k (fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol, fragP->fr_offset, 1, 1, 0, frag_bsr(fragP), /*sequent hack */ frag_opcode_frag (fragP), frag_opcode_offset (fragP)); fragP->fr_fix += 4;#if 0 fragP->fr_opcode[1] = 0xff;#endif frag_wane (fragP); return 4; } /* Relaxable case. Set up the initial guess for the variable part of the frag. */ fragP->fr_subtype = IND (BRANCH, BYTE); } if (fragP->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0])) abort (); /* Return the size of the variable part of the frag. */ return md_relax_table[fragP->fr_subtype].rlx_length;}int md_short_jump_size = 3;int md_long_jump_size = 5;const int md_reloc_size = 8; /* Size of relocation record. */voidmd_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; addressT from_addr, to_addr; fragS *frag; symbolS *to_symbol;{ valueT offset; offset = to_addr - from_addr; md_number_to_chars (ptr, (valueT) 0xEA, 1); md_number_to_disp (ptr + 1, (valueT) offset, 2);}voidmd_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol) char *ptr; addressT from_addr, to_addr; fragS *frag; symbolS *to_symbol;{ valueT offset; offset = to_addr - from_addr; md_number_to_chars (ptr, (valueT) 0xEA, 1); md_number_to_disp (ptr + 1, (valueT) offset, 4);}CONST char *md_shortopts = "m:";struct option md_longopts[] ={ {NULL, no_argument, NULL, 0}};size_t md_longopts_size = sizeof (md_longopts);intmd_parse_option (c, arg) int c; char *arg;{ switch (c) { case 'm': if (!strcmp (arg, "32032")) { cpureg = cpureg_032; mmureg = mmureg_032; } else if (!strcmp (arg, "32532")) { cpureg = cpureg_532; mmureg = mmureg_532; } else { as_bad (_("invalid architecture option -m%s"), arg); return 0; } break; default: return 0; } return 1;}voidmd_show_usage (stream) FILE *stream;{ fprintf (stream, _("\NS32K options:\n\-m32032 | -m32532 select variant of NS32K architecture\n"));}/* Create a bit_fixS in obstack 'notes'. This struct is used to profile the normal fix. If the bit_fixP is a valid pointer (not NULL) the bit_fix data will be used to format the fix. */bit_fixS *bit_fix_new (size, offset, min, max, add, base_type, base_adj) char size; /* Length of bitfield */ char offset; /* Bit offset to bitfield */ long min; /* Signextended min for bitfield */ long max; /* Signextended max for bitfield */ long add; /* Add mask, used for huffman prefix */ long base_type; /* 0 or 1, if 1 it's exploded to opcode ptr */ long base_adj;{ register bit_fixS *bit_fixP; bit_fixP = (bit_fixS *) obstack_alloc (¬es, sizeof (bit_fixS)); bit_fixP->fx_bit_size = size; bit_fixP->fx_bit_offset = offset; bit_fixP->fx_bit_base = base_type; bit_fixP->fx_bit_base_adj = base_adj; bit_fixP->fx_bit_max = max; bit_fixP->fx_bit_min = min; bit_fixP->fx_bit_add = add; return (bit_fixP);}voidfix_new_ns32k (frag, where, size, add_symbol, offset, pcrel, im_disp, bit_fixP, bsr, opcode_frag, opcode_offset) fragS *frag; /* Which frag? */ int where; /* Where in that frag? */ int size; /* 1, 2 or 4 usually. */ symbolS *add_symbol; /* X_add_symbol. */ long offset; /* X_add_number. */ int pcrel; /* TRUE if PC-relative relocation. */ char im_disp; /* true if the value to write is a displacement */ bit_fixS *bit_fixP; /* pointer at struct of bit_fix's, ignored if NULL */ char bsr; /* sequent-linker-hack: 1 when relocobject is a bsr */ fragS *opcode_frag; unsigned int opcode_offset;{ fixS *fixP = fix_new (frag, where, size, add_symbol, offset, pcrel,#ifdef BFD_ASSEMBLER bit_fixP ? NO_RELOC : reloc (size, pcrel, im_disp)#else NO_RELOC#endif ); fix_opcode_frag (fixP) = opcode_frag; fix_opcode_offset (fixP) = opcode_offset; fix_im_disp (fixP) = im_disp; fix_bsr (fixP) = bsr; fix_bit_fixP (fixP) = bit_fixP;}voidfix_new_ns32k_exp (frag, where, size, exp, pcrel, im_disp, bit_fixP, bsr, opcode_frag, opcode_offset) fragS *frag; /* Which frag? */ int where; /* Where in that frag? */ int size; /* 1, 2 or 4 usually. */ expressionS *exp; /* Expression. */ int pcrel; /* TRUE if PC-relative relocation. */ char im_disp; /* true if the value to write is a displacement */ bit_fixS *bit_fixP; /* pointer at struct of bit_fix's, ignored if NULL */ char bsr; /* sequent-linker-hack: 1 when relocobject is a bsr */ fragS *opcode_frag; unsigned int opcode_offset;{ fixS *fixP = fix_new_exp (frag, where, size, exp, pcrel,#ifdef BFD_ASSEMBLER bit_fixP ? NO_RELOC : reloc (size, pcrel, im_disp)#else NO_RELOC#endif ); fix_opcode_frag (fixP) = opcode_frag; fix_opcode_offset (fixP) = opcode_offset; fix_im_disp (fixP) = im_disp; fix_bsr (fixP) = bsr; fix_bit_fixP (fixP) = bit_fixP;}/* This is TC_CONS_FIX_NEW, called by emit_expr in read.c. */voidcons_fix_new_ns32k (frag, where, size, exp) fragS *frag; /* Which frag? */ int where; /* Where in that frag? */ int size; /* 1, 2 or 4 usually. */ expressionS *exp; /* Expression. */{ fix_new_ns32k_exp (frag, where, size, exp, 0, 2, 0, 0, 0, 0);}/* We have no need to default values of symbols. */symbolS *md_undefined_symbol (name) char *name;{ return 0;}/* Round up a section size to the appropriate boundary. */valueTmd_section_align (segment, size) segT segment; valueT size;{ return size; /* Byte alignment is fine. */}/* Exactly what point is a PC-relative offset relative TO? On the ns32k, they're relative to the start of the instruction. */longmd_pcrel_from (fixP) fixS *fixP;{ long res; res = fixP->fx_where + fixP->fx_frag->fr_address;#ifdef SEQUENT_COMPATABILITY if (frag_bsr (fixP->fx_frag)) res += 0x12 /* FOO Kludge alert! */#endif return res;}#ifdef BFD_ASSEMBLERarelent *tc_gen_reloc (section, fixp) asection *section; fixS *fixp;{ arelent *rel; bfd_reloc_code_real_type code; code = reloc (fixp->fx_size, fixp->fx_pcrel, fix_im_disp (fixp)); rel = (arelent *) xmalloc (sizeof (arelent)); rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); rel->address = fixp->fx_frag->fr_address + fixp->fx_where; if (fixp->fx_pcrel) rel->addend = fixp->fx_addnumber; else rel->addend = 0; rel->howto = bfd_reloc_type_lookup (stdoutput, code); if (!rel->howto) { const char *name; name = S_GET_NAME (fixp->fx_addsy); if (name == NULL) name = _("<unknown>"); as_fatal (_("Cannot find relocation type for symbol %s, code %d"), name, (int) code); } return rel;}#else /* BFD_ASSEMBLER */#ifdef OBJ_AOUTvoidcons_fix_new_ns32k (where, fixP, segment_address_in_file) char *where; struct fix *fixP; relax_addressT segment_address_in_file;{ /* In: Length of relocation (or of address) in chars: 1, 2 or 4. Out: GNU LD relocation length code: 0, 1, or 2. */ static unsigned char nbytes_r_length[] = { 42, 0, 1, 42, 2 }; long r_symbolnum; know (fixP->fx_addsy != NULL); md_number_to_chars (where, fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file, 4); r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy) ? S_GET_TYPE (fixP->fx_addsy) : fixP->fx_addsy->sy_number); md_number_to_chars (where + 4, ((long) (r_symbolnum) | (long) (fixP->fx_pcrel << 24) | (long) (nbytes_r_length[fixP->fx_size] << 25) | (long) ((!S_IS_DEFINED (fixP->fx_addsy)) << 27) | (long) (fix_bsr (fixP) << 28) | (long) (fix_im_disp (fixP) << 29)), 4);}#endif /* OBJ_AOUT */#endif /* BFD_ASSMEBLER */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?