📄 tc-alpha.c
字号:
#define LITUSE_JSR 3static const struct alpha_reloc_op_tag { const char *name; /* string to lookup */ size_t length; /* size of the string */ bfd_reloc_code_real_type reloc; /* relocation before frob */ operatorT op; /* which operator to use */ int lituse; /* addened to specify lituse */} alpha_reloc_op[] = { { "literal", /* name */ sizeof ("literal")-1, /* length */ BFD_RELOC_ALPHA_USER_LITERAL, /* reloc */ O_literal, /* op */ 0, /* lituse */ }, { "lituse_base", /* name */ sizeof ("lituse_base")-1, /* length */ BFD_RELOC_ALPHA_USER_LITUSE_BASE, /* reloc */ O_lituse_base, /* op */ LITUSE_BASE, /* lituse */ }, { "lituse_bytoff", /* name */ sizeof ("lituse_bytoff")-1, /* length */ BFD_RELOC_ALPHA_USER_LITUSE_BYTOFF, /* reloc */ O_lituse_bytoff, /* op */ LITUSE_BYTOFF, /* lituse */ }, { "lituse_jsr", /* name */ sizeof ("lituse_jsr")-1, /* length */ BFD_RELOC_ALPHA_USER_LITUSE_JSR, /* reloc */ O_lituse_jsr, /* op */ LITUSE_JSR, /* lituse */ }, { "gpdisp", /* name */ sizeof ("gpdisp")-1, /* length */ BFD_RELOC_ALPHA_USER_GPDISP, /* reloc */ O_gpdisp, /* op */ 0, /* lituse */ }, { "gprelhigh", /* name */ sizeof ("gprelhigh")-1, /* length */ BFD_RELOC_ALPHA_USER_GPRELHIGH, /* reloc */ O_gprelhigh, /* op */ 0, /* lituse */ }, { "gprellow", /* name */ sizeof ("gprellow")-1, /* length */ BFD_RELOC_ALPHA_USER_GPRELLOW, /* reloc */ O_gprellow, /* op */ 0, /* lituse */ },};static const int alpha_num_reloc_op = sizeof (alpha_reloc_op) / sizeof (*alpha_reloc_op);/* Maximum # digits needed to hold the largest sequence # */#define ALPHA_RELOC_DIGITS 25/* Whether a sequence number is valid. */#define ALPHA_RELOC_SEQUENCE_OK(X) ((X) > 0 && ((unsigned) (X)) == (X))/* Structure to hold explict sequence information. */struct alpha_literal_tag{ fixS *lituse; /* head of linked list of !literals */ segT segment; /* segment relocs are in or undefined_section*/ int multi_section_p; /* True if more than one section was used */ unsigned sequence; /* sequence # */ unsigned n_literals; /* # of literals */ unsigned n_lituses; /* # of lituses */ char string[1]; /* printable form of sequence to hash with */};/* Hash table to link up literals with the appropriate lituse */static struct hash_control *alpha_literal_hash;#endif/* A table of CPU names and opcode sets. */static const struct cpu_type { const char *name; unsigned flags;} cpu_types[] = { /* Ad hoc convention: cpu number gets palcode, process code doesn't. This supports usage under DU 4.0b that does ".arch ev4", and usage in MILO that does -m21064. Probably something more specific like -m21064-pal should be used, but oh well. */ { "21064", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, { "21064a", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, { "21066", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, { "21068", AXP_OPCODE_BASE|AXP_OPCODE_EV4 }, { "21164", AXP_OPCODE_BASE|AXP_OPCODE_EV5 }, { "21164a", AXP_OPCODE_BASE|AXP_OPCODE_EV5|AXP_OPCODE_BWX }, { "21164pc", (AXP_OPCODE_BASE|AXP_OPCODE_EV5|AXP_OPCODE_BWX |AXP_OPCODE_MAX) }, { "21264", (AXP_OPCODE_BASE|AXP_OPCODE_EV6|AXP_OPCODE_BWX |AXP_OPCODE_MAX|AXP_OPCODE_CIX) }, { "ev4", AXP_OPCODE_BASE }, { "ev45", AXP_OPCODE_BASE }, { "lca45", AXP_OPCODE_BASE }, { "ev5", AXP_OPCODE_BASE }, { "ev56", AXP_OPCODE_BASE|AXP_OPCODE_BWX }, { "pca56", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX }, { "ev6", AXP_OPCODE_BASE|AXP_OPCODE_BWX|AXP_OPCODE_MAX|AXP_OPCODE_CIX }, { "all", AXP_OPCODE_BASE }, { 0, 0 }};/* The macro table */static const struct alpha_macro alpha_macros[] = {/* Load/Store macros */ { "lda", emit_lda, NULL, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_LITERAL, MACRO_BASE, MACRO_EOA } }, { "ldah", emit_ldah, NULL, { MACRO_IR, MACRO_EXP, MACRO_EOA } }, { "ldl", emit_ir_load, "ldl", { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ldl_l", emit_ir_load, "ldl_l", { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ldq", emit_ir_load, "ldq", { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_LITERAL, MACRO_EOA } }, { "ldq_l", emit_ir_load, "ldq_l", { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ldq_u", emit_ir_load, "ldq_u", { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ldf", emit_loadstore, "ldf", { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ldg", emit_loadstore, "ldg", { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "lds", emit_loadstore, "lds", { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ldt", emit_loadstore, "ldt", { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ldb", emit_ldX, (PTR) 0, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ldbu", emit_ldXu, (PTR) 0, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ldw", emit_ldX, (PTR) 1, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ldwu", emit_ldXu, (PTR) 1, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "uldw", emit_uldX, (PTR) 1, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "uldwu", emit_uldXu, (PTR) 1, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "uldl", emit_uldX, (PTR) 2, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "uldlu", emit_uldXu, (PTR) 2, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "uldq", emit_uldXu, (PTR) 3, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ldgp", emit_ldgp, NULL, { MACRO_IR, MACRO_EXP, MACRO_PIR, MACRO_EOA } }, { "ldi", emit_lda, NULL, { MACRO_IR, MACRO_EXP, MACRO_EOA } }, { "ldil", emit_ldil, NULL, { MACRO_IR, MACRO_EXP, MACRO_EOA } }, { "ldiq", emit_lda, NULL, { MACRO_IR, MACRO_EXP, MACRO_EOA } },#if 0 { "ldif" emit_ldiq, NULL, { MACRO_FPR, MACRO_EXP, MACRO_EOA } }, { "ldid" emit_ldiq, NULL, { MACRO_FPR, MACRO_EXP, MACRO_EOA } }, { "ldig" emit_ldiq, NULL, { MACRO_FPR, MACRO_EXP, MACRO_EOA } }, { "ldis" emit_ldiq, NULL, { MACRO_FPR, MACRO_EXP, MACRO_EOA } }, { "ldit" emit_ldiq, NULL, { MACRO_FPR, MACRO_EXP, MACRO_EOA } },#endif { "stl", emit_loadstore, "stl", { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "stl_c", emit_loadstore, "stl_c", { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "stq", emit_loadstore, "stq", { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "stq_c", emit_loadstore, "stq_c", { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "stq_u", emit_loadstore, "stq_u", { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "stf", emit_loadstore, "stf", { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "stg", emit_loadstore, "stg", { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "sts", emit_loadstore, "sts", { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "stt", emit_loadstore, "stt", { MACRO_FPR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "stb", emit_stX, (PTR) 0, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "stw", emit_stX, (PTR) 1, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ustw", emit_ustX, (PTR) 1, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ustl", emit_ustX, (PTR) 2, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } }, { "ustq", emit_ustX, (PTR) 3, { MACRO_IR, MACRO_EXP, MACRO_OPIR, MACRO_BASE, MACRO_EOA } },/* Arithmetic macros */#if 0 { "absl" emit_absl, 1, { IR } }, { "absl" emit_absl, 2, { IR, IR } }, { "absl" emit_absl, 2, { EXP, IR } }, { "absq" emit_absq, 1, { IR } }, { "absq" emit_absq, 2, { IR, IR } }, { "absq" emit_absq, 2, { EXP, IR } },#endif { "sextb", emit_sextX, (PTR) 0, { MACRO_IR, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_EOA, /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } }, { "sextw", emit_sextX, (PTR) 1, { MACRO_IR, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_EOA, /* MACRO_EXP, MACRO_IR, MACRO_EOA */ } }, { "divl", emit_division, "__divl", { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_IR, MACRO_EOA, /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, { "divlu", emit_division, "__divlu", { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_IR, MACRO_EOA, /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, { "divq", emit_division, "__divq", { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_IR, MACRO_EOA, /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, { "divqu", emit_division, "__divqu", { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_IR, MACRO_EOA, /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, { "reml", emit_division, "__reml", { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_IR, MACRO_EOA, /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, { "remlu", emit_division, "__remlu", { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_IR, MACRO_EOA, /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, { "remq", emit_division, "__remq", { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_IR, MACRO_EOA, /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, { "remqu", emit_division, "__remqu", { MACRO_IR, MACRO_IR, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_IR, MACRO_EOA, /* MACRO_IR, MACRO_EXP, MACRO_IR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_EOA */ } }, { "jsr", emit_jsrjmp, "jsr", { MACRO_PIR, MACRO_EXP, MACRO_JSR, MACRO_EOA, MACRO_PIR, MACRO_JSR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_JSR, MACRO_EOA, MACRO_EXP, MACRO_JSR, MACRO_EOA } }, { "jmp", emit_jsrjmp, "jmp", { MACRO_PIR, MACRO_EXP, MACRO_JSR, MACRO_EOA, MACRO_PIR, MACRO_JSR, MACRO_EOA, MACRO_IR, MACRO_EXP, MACRO_JSR, MACRO_EOA, MACRO_EXP, MACRO_JSR, MACRO_EOA } }, { "ret", emit_retjcr, "ret", { MACRO_IR, MACRO_EXP, MACRO_EOA, MACRO_IR, MACRO_EOA, MACRO_PIR, MACRO_EXP, MACRO_EOA, MACRO_PIR, MACRO_EOA, MACRO_EXP, MACRO_EOA, MACRO_EOA } }, { "jcr", emit_retjcr, "jcr", { MACRO_IR, MACRO_EXP, MACRO_EOA, MACRO_IR, MACRO_EOA, MACRO_PIR, MACRO_EXP, MACRO_EOA, MACRO_PIR, MACRO_EOA, MACRO_EXP, MACRO_EOA, MACRO_EOA } }, { "jsr_coroutine", emit_retjcr, "jcr", { MACRO_IR, MACRO_EXP, MACRO_EOA, MACRO_IR, MACRO_EOA, MACRO_PIR, MACRO_EXP, MACRO_EOA, MACRO_PIR, MACRO_EOA, MACRO_EXP, MACRO_EOA, MACRO_EOA } },};static const unsigned int alpha_num_macros = sizeof (alpha_macros) / sizeof (*alpha_macros);/* Public interface functions *//* This function is called once, at assembler startup time. It sets up all the tables, etc. that the MD part of the assembler will need, that can be determined before arguments are parsed. */voidmd_begin (){ unsigned int i; /* Verify that X_op field is wide enough. */ { expressionS e; e.X_op = O_max; assert (e.X_op == O_max); } /* Create the opcode hash table */ alpha_opcode_hash = hash_new (); for (i = 0; i < alpha_num_opcodes;) { const char *name, *retval, *slash; name = alpha_opcodes[i].name; retval = hash_insert (alpha_opcode_hash, name, (PTR) &alpha_opcodes[i]); if (retval) as_fatal (_("internal error: can't hash opcode `%s': %s"), name, retval); /* Some opcodes include modifiers of various sorts with a "/mod" syntax, like the architecture manual suggests. However, for use with gcc at least, we also need access to those same opcodes without the "/". */ if ((slash = strchr (name, '/')) != NULL) { char *p = xmalloc (strlen (name)); memcpy (p, name, slash - name); strcpy (p + (slash - name), slash + 1); (void) hash_insert (alpha_opcode_hash, p, (PTR) &alpha_opcodes[i]); /* Ignore failures -- the opcode table does duplicate some variants in different forms, like "hw_stq" and "hw_st/q". */ } while (++i < alpha_num_opcodes && (alpha_opcodes[i].name == name || !strcmp (alpha_opcodes[i].name, name))) continue; } /* Create the macro hash table */ alpha_macro_hash = hash_new (); for (i = 0; i < alpha_num_macros;) { const char *name, *retval; name = alpha_macros[i].name; retval = hash_insert (alpha_macro_hash, name, (PTR) &alpha_macros[i]); if (retval) as_fatal (_("internal error: can't hash macro `%s': %s"), name, retval); while (++i < alpha_num_macros && (alpha_macros[i].name == name || !strcmp (alpha_macros[i].name, name))) continue; } /* Construct symbols for each of the registers */ for (i = 0; i < 32; ++i) { char name[4]; sprintf (name, "$%d", i); alpha_register_table[i] = symbol_create (name, reg_section, i, &zero_address_frag); } for (; i < 64; ++i) { char name[5]; sprintf (name, "$f%d", i - 32); alpha_register_table[i] = symbol_create (name, reg_section, i, &zero_address_frag); } /* Create the special symbols and sections we'll be using */ /* So .sbss will get used for tiny objects. */ bfd_set_gp_size (stdoutput, g_switch_value);#ifdef OBJ_ECOFF create_literal_section (".lita", &alpha_lita_section, &alpha_lita_symbol); /* For handling the GP, create a symbol that won't be output in the symbol table. We'll edit it out of relocs later. */ alpha_gp_symbol = symbol_create ("<GP value>", alpha_lita_section, 0x8000, &zero_address_frag);#endif#ifdef OBJ_EVAX create_literal_section (".link", &alpha_link_section, &alpha_link_symbol);#endif#ifdef OBJ_ELF if (ECOFF_DEBUGGING) { segT sec = subseg_new (".mdebug", (subsegT) 0); bfd_set_section_flags (stdoutput, sec, SEC_HAS_CONTENTS | SEC_READONLY); bfd_set_section_alignment (stdoutput, sec, 3); }#endif /* OBJ_ELF */ subseg_set (text_section, 0);#ifdef RELOC_OP_P /* Create literal lookup hash table. */ alpha_literal_hash = hash_new ();#endif}/* The public interface to the instruction assembler. */voidmd_assemble (str) char *str;{ char opname[32]; /* current maximum is 13 */ expressionS tok[MAX_INSN_ARGS]; int ntok, trunclen; size_t opnamelen; /* split off the opcode */ opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_/46819"); trunclen = (opnamelen < sizeof (opname) - 1 ? opnamelen : sizeof (opname) - 1); memcpy (opname, str, trunclen); opname[trunclen] = '\0'; /* tokenize the rest of the line */ if ((ntok = tokenize_arguments (str + opnamelen, tok, MAX_INSN_ARGS)) < 0) { if (ntok != TOKENIZE_ERROR_REPORT) as_bad (_("syntax error")); return; } /* finish it off */ assemble_tokens (opname, tok, ntok, alpha_macros_on);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -