📄 tc-i370.c
字号:
case 'K': /* Recognize -K PIC */ if (strcmp (arg, "PIC") == 0 || strcmp (arg, "pic") == 0) { shlib = SHLIB_PIC; i370_flags |= EF_I370_RELOCATABLE_LIB; } else return 0; break;#endif case 'm': /* -m360 mean to assemble for the ancient 360 architecture */ if (strcmp (arg, "360") == 0 || strcmp (arg, "i360") == 0) i370_cpu = I370_OPCODE_360; /* -mxa means to assemble for the IBM 370 XA */ else if (strcmp (arg, "xa") == 0) i370_cpu = I370_OPCODE_370_XA; /* -many means to assemble for any architecture (370/XA). */ else if (strcmp (arg, "any") == 0) i370_cpu = I370_OPCODE_370; else if (strcmp (arg, "regnames") == 0) reg_names_p = true; else if (strcmp (arg, "no-regnames") == 0) reg_names_p = false;#ifdef OBJ_ELF /* -mrelocatable/-mrelocatable-lib -- warn about initializations that require relocation */ else if (strcmp (arg, "relocatable") == 0) { shlib = SHILB_MRELOCATABLE; i370_flags |= EF_I370_RELOCATABLE; } else if (strcmp (arg, "relocatable-lib") == 0) { shlib = SHILB_MRELOCATABLE; i370_flags |= EF_I370_RELOCATABLE_LIB; }#endif else { as_bad ("invalid switch -m%s", arg); return 0; } break;#ifdef OBJ_ELF /* -V: SVR4 argument to print version ID. */ case 'V': print_version_id (); break; /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section should be emitted or not. FIXME: Not implemented. */ case 'Q': break;#endif default: return 0; } return 1;}/* Set i370_cpu if it is not already set. Currently defaults to the reasonable superset; but can be made more fine grained if desred. */static voidi370_set_cpu (){ const char *default_os = TARGET_OS; const char *default_cpu = TARGET_CPU; /* override with the superset for the moment. */ i370_cpu = I370_OPCODE_ESA390_SUPERSET; if (i370_cpu == 0) { if (strcmp (default_cpu, "i360") == 0) i370_cpu = I370_OPCODE_360; else if (strcmp (default_cpu, "i370") == 0) i370_cpu = I370_OPCODE_370; else if (strcmp (default_cpu, "XA") == 0) i370_cpu = I370_OPCODE_370_XA; else as_fatal ("Unknown default cpu = %s, os = %s", default_cpu, default_os); }}/* Figure out the BFD architecture to use. *//* hack alert -- specify the different 370 architectures */enum bfd_architecturei370_arch (){ return bfd_arch_i370;}/* This function is called when the assembler starts up. It is called after the options have been parsed and the output file has been opened. */voidmd_begin (){ register const struct i370_opcode *op; const struct i370_opcode *op_end; const struct i370_macro *macro; const struct i370_macro *macro_end; boolean dup_insn = false; i370_set_cpu ();#ifdef OBJ_ELF /* Set the ELF flags if desired. */ if (i370_flags) bfd_set_private_flags (stdoutput, i370_flags);#endif /* Insert the opcodes into a hash table. */ i370_hash = hash_new (); op_end = i370_opcodes + i370_num_opcodes; for (op = i370_opcodes; op < op_end; op++) { know ((op->opcode & op->mask) == op->opcode); if ((op->flags & i370_cpu) != 0) { const char *retval; retval = hash_insert (i370_hash, op->name, (PTR) op); if (retval != (const char *) NULL) { as_bad ("Internal assembler error for instruction %s", op->name); dup_insn = true; } } } /* Insert the macros into a hash table. */ i370_macro_hash = hash_new (); macro_end = i370_macros + i370_num_macros; for (macro = i370_macros; macro < macro_end; macro++) { if ((macro->flags & i370_cpu) != 0) { const char *retval; retval = hash_insert (i370_macro_hash, macro->name, (PTR) macro); if (retval != (const char *) NULL) { as_bad ("Internal assembler error for macro %s", macro->name); dup_insn = true; } } } if (dup_insn) abort ();}/* Insert an operand value into an instruction. */static i370_insn_ti370_insert_operand (insn, operand, val) i370_insn_t insn; const struct i370_operand *operand; offsetT val;{ if (operand->insert) { const char *errmsg; /* used for 48-bit insn's */ errmsg = NULL; insn = (*operand->insert) (insn, (long) val, &errmsg); if (errmsg) as_bad ("%s", errmsg); } else { /* this is used only for 16, 32 bit insn's */ insn.i[0] |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift); } return insn;}#ifdef OBJ_ELF/* Parse @got, etc. and return the desired relocation. Currently, i370 does not support (don't really need to support) any of these fancier markups ... for example, no one is going to write 'L 6,=V(bogus)@got' it just doesn't make sense (at least to me). So basically, we could get away with this routine returning BFD_RELOC_UNUSED in all circumstances. However, I'll leave in for now in case someone ambitious finds a good use for this stuff ... this routine was pretty much just copied from the powerpc code ... */static bfd_reloc_code_real_typei370_elf_suffix (str_p, exp_p) char **str_p; expressionS *exp_p;{ struct map_bfd { char *string; int length; bfd_reloc_code_real_type reloc; }; char ident[20]; char *str = *str_p; char *str2; int ch; int len; struct map_bfd *ptr;#define MAP(str,reloc) { str, sizeof (str)-1, reloc } static struct map_bfd mapping[] = {#if 0 MAP ("l", BFD_RELOC_LO16), MAP ("h", BFD_RELOC_HI16), MAP ("ha", BFD_RELOC_HI16_S),#endif /* warnings with -mrelocatable. */ MAP ("fixup", BFD_RELOC_CTOR), { (char *)0, 0, BFD_RELOC_UNUSED } }; if (*str++ != '@') return BFD_RELOC_UNUSED; for (ch = *str, str2 = ident; (str2 < ident + sizeof (ident) - 1 && (isalnum (ch) || ch == '@')); ch = *++str) { *str2++ = (islower (ch)) ? ch : tolower (ch); } *str2 = '\0'; len = str2 - ident; ch = ident[0]; for (ptr = &mapping[0]; ptr->length > 0; ptr++) if (ch == ptr->string[0] && len == ptr->length && memcmp (ident, ptr->string, ptr->length) == 0) { if (exp_p->X_add_number != 0 && (ptr->reloc == BFD_RELOC_16_GOTOFF || ptr->reloc == BFD_RELOC_LO16_GOTOFF || ptr->reloc == BFD_RELOC_HI16_GOTOFF || ptr->reloc == BFD_RELOC_HI16_S_GOTOFF)) as_warn ("identifier+constant@got means identifier@got+constant"); /* Now check for identifier@suffix+constant */ if (*str == '-' || *str == '+') { char *orig_line = input_line_pointer; expressionS new_exp; input_line_pointer = str; expression (&new_exp); if (new_exp.X_op == O_constant) { exp_p->X_add_number += new_exp.X_add_number; str = input_line_pointer; } if (&input_line_pointer != str_p) input_line_pointer = orig_line; } *str_p = str; return ptr->reloc; } return BFD_RELOC_UNUSED;}/* Like normal .long/.short/.word, except support @got, etc. *//* clobbers input_line_pointer, checks end-of-line. */static voidi370_elf_cons (nbytes) register int nbytes; /* 1=.byte, 2=.word, 4=.long */{ expressionS exp; bfd_reloc_code_real_type reloc; if (is_it_end_of_statement ()) { demand_empty_rest_of_line (); return; } do { expression (&exp); if (exp.X_op == O_symbol && *input_line_pointer == '@' && (reloc = i370_elf_suffix (&input_line_pointer, &exp)) != BFD_RELOC_UNUSED) { reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc); int size = bfd_get_reloc_size (reloc_howto); if (size > nbytes) as_bad ("%s relocations do not fit in %d bytes\n", reloc_howto->name, nbytes); else { register char *p = frag_more ((int) nbytes); int offset = nbytes - size; fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size, &exp, 0, reloc); } } else emit_expr (&exp, (unsigned int) nbytes); } while (*input_line_pointer++ == ','); input_line_pointer--; /* Put terminator back into stream. */ demand_empty_rest_of_line ();}/* ASCII to EBCDIC conversion table. */static unsigned char ascebc[256] ={ /*00 NL SH SX EX ET NQ AK BL */ 0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F, /*08 BS HT LF VT FF CR SO SI */ 0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /*10 DL D1 D2 D3 D4 NK SN EB */ 0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26, /*18 CN EM SB EC FS GS RS US */ 0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F, /*20 SP ! " # $ % & ' */ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, /*28 ( ) * + , - . / */ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61, /*30 0 1 2 3 4 5 6 7 */ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, /*38 8 9 : ; < = > ? */ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F, /*40 @ A B C D E F G */ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, /*48 H I J K L M N O */ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, /*50 P Q R S T U V W */ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, /*58 X Y Z [ \ ] ^ _ */ 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D, /*60 ` a b c d e f g */ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /*68 h i j k l m n o */ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /*70 p q r s t u v w */ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, /*78 x y z { | } ~ DL */ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF};/* EBCDIC to ASCII conversion table. */unsigned char ebcasc[256] ={ /*00 NU SH SX EX PF HT LC DL */ 0x00, 0x01, 0x02, 0x03, 0x00, 0x09, 0x00, 0x7F, /*08 SM VT FF CR SO SI */ 0x00, 0x00, 0x00, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /*10 DE D1 D2 TM RS NL BS IL */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x0A, 0x08, 0x00, /*18 CN EM CC C1 FS GS RS US */ 0x18, 0x19, 0x00, 0x00, 0x1C, 0x1D, 0x1E, 0x1F, /*20 DS SS FS BP LF EB EC */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x17, 0x1B, /*28 SM C2 EQ AK BL */ 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07, 0x00, /*30 SY PN RS UC ET */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, /*38 C3 D4 NK SU */ 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x00, 0x1A, /*40 SP */ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*48 . < ( + | */ 0x00, 0x00, 0x00, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, /*50 & */ 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*58 ! $ * ) ; ^ */ 0x00, 0x00, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E, /*60 - / */ 0x2D, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*68 , % _ > ? */ 0x00, 0x00, 0x00, 0x2C, 0x25, 0x5F, 0x3E, 0x3F, /*70 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*78 ` : # @ ' = " */ 0x00, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, /*80 a b c d e f g */ 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /*88 h i { */ 0x68, 0x69, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x00, /*90 j k l m n o p */ 0x00, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, /*98 q r } */ 0x71, 0x72, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00, /*A0 ~ s t u v w x */ 0x00, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, /*A8 y z [ */ 0x79, 0x7A, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, /*B0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*B8 ] */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x00, /*C0 { A B C D E F G */ 0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /*C8 H I */ 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*D0 } J K L M N O P */ 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, /*D8 Q R */ 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*E0 \ S T U V W X */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -