tc-ns32k.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,407 行 · 第 1/4 页
C
2,407 行
/* We can apply default, don't goof. */ if (parse (desc->default_args, 1) != 1) /* Check error in default. */ as_fatal (_("Wrong numbers of operands in default, check ns32k-opcodes.h")); } else { as_fatal (_("Wrong number of operands")); } } for (i = 0; i < IIF_ENTRIES; i++) /* Mark all entries as void. */ iif.iifP[i].type = 0; /* Build opcode iif-entry. */ iif.instr_size = desc->opcode_size / 8; IIF (1, 1, iif.instr_size, desc->opcode_seed, 0, 0, 0, 0, 0, 0, -1, 0); /* This call encodes operands to iif format. */ if (argc) { encode_operand (argc, argv, &desc->operands[0], &suffix[0], desc->im_size, desc->opcode_size); } return recursive_level;}/* Convert iif to fragments. From this point we start to dribble with functions in other files than this one.(Except hash.c) So, if it's possible to make an iif for an other CPU, you don't need to know what frags, relax, obstacks, etc is in order to port this assembler. You only need to know if it's possible to reduce your cpu-instruction to iif-format (takes some work) and adopt the other md_? parts according to given instructions Note that iif was invented for the clean ns32k`s architecure. *//* GAS for the ns32k has a problem. PC relative displacements are relative to the address of the opcode, not the address of the operand. We used to keep track of the offset between the operand and the opcode in pcrel_adjust for each frag and each fix. However, we get into trouble where there are two or more pc-relative operands and the size of the first one can't be determined. Then in the relax phase, the size of the first operand will change and pcrel_adjust will no longer be correct. The current solution is keep a pointer to the frag with the opcode in it and the offset in that frag for each frag and each fix. Then, when needed, we can always figure out how far it is between the opcode and the pcrel object. See also md_pcrel_adjust and md_fix_pcrel_adjust. For objects not part of an instruction, the pointer to the opcode frag is always zero. */voidconvert_iif (){ int i; bit_fixS *j; fragS *inst_frag; unsigned int inst_offset; char *inst_opcode; char *memP; int l; int k; char type; char size = 0; int size_so_far; memP = frag_more (0); inst_opcode = memP; inst_offset = (memP - frag_now->fr_literal); inst_frag = frag_now; for (i = 0; i < IIF_ENTRIES; i++) { if (type = iif.iifP[i].type) { /* The object exist, so handle it. */ switch (size = iif.iifP[i].size) { case 42: size = 0; /* It's a bitfix that operates on an existing object. */ if (iif.iifP[i].bit_fixP->fx_bit_base) /* Expand fx_bit_base to point at opcode. */ iif.iifP[i].bit_fixP->fx_bit_base = (long) inst_opcode; /* Fall through. */ case 8: /* bignum or doublefloat */ case 1: case 2: case 3: case 4: /* The final size in objectmemory is known. */ memP = frag_more(size); j = iif.iifP[i].bit_fixP; switch (type) { case 1: /* The object is pure binary. */ if (j || iif.iifP[i].pcrel) { fix_new_ns32k (frag_now, (long) (memP - frag_now->fr_literal), size, 0, iif.iifP[i].object, iif.iifP[i].pcrel, iif.iifP[i].im_disp, j, iif.iifP[i].bsr, /* sequent hack */ inst_frag, inst_offset); } else { /* Good, just put them bytes out. */ switch (iif.iifP[i].im_disp) { case 0: md_number_to_chars (memP, iif.iifP[i].object, size); break; case 1: md_number_to_disp (memP, iif.iifP[i].object, size); break; default: as_fatal (_("iif convert internal pcrel/binary")); } } break; case 2: /* The object is a pointer at an expression, so unpack it, note that bignums may result from the expression. */ evaluate_expr (&exprP, (char *) iif.iifP[i].object); if (exprP.X_op == O_big || size == 8) { if ((k = exprP.X_add_number) > 0) { /* We have a bignum ie a quad. This can only happens in a long suffixed instruction. */ if (k * 2 > size) as_warn (_("Bignum too big for long")); if (k == 3) memP += 2; for (l = 0; k > 0; k--, l += 2) { md_number_to_chars (memP + l, generic_bignum[l >> 1], sizeof (LITTLENUM_TYPE)); } } else { /* flonum. */ LITTLENUM_TYPE words[4]; switch (size) { case 4: gen_to_words (words, 2, 8); md_number_to_imm (memP, (long) words[0], sizeof (LITTLENUM_TYPE)); md_number_to_imm (memP + sizeof (LITTLENUM_TYPE), (long) words[1], sizeof (LITTLENUM_TYPE)); break; case 8: gen_to_words (words, 4, 11); md_number_to_imm (memP, (long) words[0], sizeof (LITTLENUM_TYPE)); md_number_to_imm (memP + sizeof (LITTLENUM_TYPE), (long) words[1], sizeof (LITTLENUM_TYPE)); md_number_to_imm ((memP + 2 * sizeof (LITTLENUM_TYPE)), (long) words[2], sizeof (LITTLENUM_TYPE)); md_number_to_imm ((memP + 3 * sizeof (LITTLENUM_TYPE)), (long) words[3], sizeof (LITTLENUM_TYPE)); break; } } break; } if (j || exprP.X_add_symbol || exprP.X_op_symbol || iif.iifP[i].pcrel) { /* The expression was undefined due to an undefined label. Create a fix so we can fix the object later. */ exprP.X_add_number += iif.iifP[i].object_adjust; fix_new_ns32k_exp (frag_now, (long) (memP - frag_now->fr_literal), size, &exprP, iif.iifP[i].pcrel, iif.iifP[i].im_disp, j, iif.iifP[i].bsr, inst_frag, inst_offset); } else { /* Good, just put them bytes out. */ switch (iif.iifP[i].im_disp) { case 0: md_number_to_imm (memP, exprP.X_add_number, size); break; case 1: md_number_to_disp (memP, exprP.X_add_number, size); break; default: as_fatal (_("iif convert internal pcrel/pointer")); } } break; default: as_fatal (_("Internal logic error in iif.iifP[n].type")); } break; case 0: /* Too bad, the object may be undefined as far as its final nsize in object memory is concerned. The size of the object in objectmemory is not explicitly given. If the object is defined its length can be determined and a fix can replace the frag. */ { evaluate_expr (&exprP, (char *) iif.iifP[i].object); if ((exprP.X_add_symbol || exprP.X_op_symbol) && !iif.iifP[i].pcrel) { /* Size is unknown until link time so have to allow 4 bytes. */ size = 4; memP = frag_more(size); fix_new_ns32k_exp (frag_now, (long) (memP - frag_now->fr_literal), size, &exprP, 0, /* never iif.iifP[i].pcrel, */ 1, /* always iif.iifP[i].im_disp */ (bit_fixS *) 0, 0, inst_frag, inst_offset); break; /* exit this absolute hack */ } if (exprP.X_add_symbol || exprP.X_op_symbol) { /* Frag it. */ if (exprP.X_op_symbol) { /* We cant relax this case. */ as_fatal (_("Can't relax difference")); } else { /* Size is not important. This gets fixed by relax, but we assume 0 in what follows. */ memP = frag_more(4); /* Max size. */ size = 0; { fragS *old_frag = frag_now; frag_variant (rs_machine_dependent, 4, /* Max size. */ 0, /* Size. */ IND (BRANCH, UNDEF), /* Expecting the worst. */ exprP.X_add_symbol, exprP.X_add_number, inst_opcode); frag_opcode_frag (old_frag) = inst_frag; frag_opcode_offset (old_frag) = inst_offset; frag_bsr (old_frag) = iif.iifP[i].bsr; } } } else { /* This duplicates code in md_number_to_disp. */ if (-64 <= exprP.X_add_number && exprP.X_add_number <= 63) { size = 1; } else { if (-8192 <= exprP.X_add_number && exprP.X_add_number <= 8191) { size = 2; } else { if (-0x20000000 <= exprP.X_add_number && exprP.X_add_number<=0x1fffffff) { size = 4; } else { as_warn (_("Displacement to large for :d")); size = 4; } } } memP = frag_more (size); md_number_to_disp (memP, exprP.X_add_number, size); } } break; default: as_fatal (_("Internal logic error in iif.iifP[].type")); } } }}#ifdef BFD_ASSEMBLER/* This functionality should really be in the bfd library. */static bfd_reloc_code_real_typereloc (int size, int pcrel, int type){ int length, index; bfd_reloc_code_real_type relocs[] = { BFD_RELOC_NS32K_IMM_8, BFD_RELOC_NS32K_IMM_16, BFD_RELOC_NS32K_IMM_32, BFD_RELOC_NS32K_IMM_8_PCREL, BFD_RELOC_NS32K_IMM_16_PCREL, BFD_RELOC_NS32K_IMM_32_PCREL, /* ns32k displacements. */ BFD_RELOC_NS32K_DISP_8, BFD_RELOC_NS32K_DISP_16, BFD_RELOC_NS32K_DISP_32, BFD_RELOC_NS32K_DISP_8_PCREL, BFD_RELOC_NS32K_DISP_16_PCREL, BFD_RELOC_NS32K_DISP_32_PCREL, /* Normal 2's complement. */ BFD_RELOC_8, BFD_RELOC_16, BFD_RELOC_32, BFD_RELOC_8_PCREL, BFD_RELOC_16_PCREL, BFD_RELOC_32_PCREL }; switch (size) { case 1: length = 0; break; case 2: length = 1; break; case 4: length = 2; break; default: length = -1; break; } index = length + 3 * pcrel + 6 * type; if (index >= 0 && index < sizeof (relocs) / sizeof (relocs[0])) return relocs[index]; if (pcrel) as_bad (_("Can not do %d byte pc-relative relocation for storage type %d"), size, type); else as_bad (_("Can not do %d byte relocation for storage type %d"), size, type); return BFD_RELOC_NONE;}#endifvoidmd_assemble (line) char *line;{ freeptr = freeptr_static; parse (line, 0); /* Explode line to more fix form in iif. */ convert_iif (); /* Convert iif to frags, fix's etc. */#ifdef SHOW_NUM printf (" \t\t\t%s\n", line);#endif}voidmd_begin (){ /* Build a hashtable of the instructions. */ const struct ns32k_opcode *ptr; const char *stat; inst_hash_handle = hash_new (); for (ptr = ns32k_opcodes; ptr < endop; ptr++) { if ((stat = hash_insert (inst_hash_handle, ptr->name, (char *) ptr))) /* Fatal. */ as_fatal (_("Can't hash %s: %s"), ptr->name, stat); } /* Some private space please! */ freeptr_static = (char *) malloc (PRIVATE_SIZE);}/* Must be equal to MAX_PRECISON in atof-ieee.c. */#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; switch (type) { case 'f': prec = 2; break; case 'd': prec = 4; 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; prec--;) { md_number_to_chars (litP, (long) (*--wordP), sizeof (LITTLENUM_TYPE)); litP += sizeof (LITTLENUM_TYPE); } return 0;}/* Convert number to chars in correct order. */voidmd_number_to_chars (buf, value, nbytes) char *buf; valueT value; int nbytes;{ number_to_chars_littleendian (buf, value, nbytes);}/* This is a variant of md_numbers_to_chars. The reason for its' existence is the fact that ns32k uses Huffman coded displacements. This implies that the bit order is reversed in displacements and that they are prefixed with a size-tag. binary: msb -> lsb 0xxxxxxx byte 10xxxxxx xxxxxxxx word 11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx double word This must be taken care of and we do it here! */static voidmd_number_to_disp (buf, val, n) char *buf; long val; char n;{ switch (n) { case 1: if (val < -64 || val > 63) as_warn (_("Byte displacement out of range. line number not valid")); val &= 0x7f;#ifdef SHOW_NUM printf ("%x ", val & 0xff);#endif *buf++ = val; break; case 2: if (val < -8192 || val > 8191) as_warn (_("Word displacement out of range. line number not valid")); val &= 0x3fff; val |= 0x8000;#ifdef SHOW_NUM printf ("%x ", val >> 8 & 0xff);#endif *buf++ = (val >> 8);#ifdef SHOW_NUM printf ("%x ", val & 0xff);#endif *buf++ = val; break; case 4: if (val < -0x20000000 || val >= 0x20000000) as_warn (_("Double word displacement out of range")); val |= 0xc0000000;#ifdef SHOW_NUM printf ("%x ", val >> 24 & 0xff);#endif *buf++ = (val >> 24);#ifdef SHOW_NUM printf ("%x ", val >> 16 & 0xff);#endif *buf++ = (val >> 16);#ifdef SHOW_NUM printf ("%x ", val >> 8 & 0xff);#endif *buf++ = (val >> 8);#ifdef SHOW_NUM printf ("%x ", val & 0xff);#endif *buf++ = val; break; default: as_fatal (_("Internal logic error. line %s, file \"%s\""), __LINE__, __FILE__); }}static voidmd_number_to_imm (buf, val, n) char *buf; long val; char n;{ switch (n) { case 1:#ifdef SHOW_NUM printf ("%x ", val & 0xff);#endif *buf++ = val; break; case 2:#ifdef SHOW_NUM printf ("%x ", val >> 8 & 0xff);#endif *buf++ = (val >> 8);#ifdef SHOW_NUM printf ("%x ", val & 0xff);#endif *buf++ = val; break; case 4:#ifdef SHOW_NUM printf ("%x ", val >> 24 & 0xff);#endif *buf++ = (val >> 24);#ifdef SHOW_NUM printf ("%x ", val >> 16 & 0xff);#endif *buf++ = (val >> 16);#ifdef SHOW_NUM printf ("%x ", val >> 8 & 0xff);#endif *buf++ = (val >> 8);#ifdef SHOW_NUM printf ("%x ", val & 0xff);#endif *buf++ = val; break; default: as_fatal (_("Internal logic error. line %s, file \"%s\""),
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?