📄 tc-alpha.c
字号:
/* tc-alpha.c - Processor-specific code for the DEC Alpha AXP CPU. Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. Contributed by Carnegie Mellon University, 1993. Written by Alessandro Forin, based on earlier gas-1.38 target CPU files. Modified by Ken Raeburn for gas-2.x and ECOFF support. Modified by Richard Henderson for ELF support. Modified by Klaus K"ampf for EVAX (OpenVMS/Alpha) support. This file is part of GAS, the GNU Assembler. GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GAS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GAS; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* * Mach Operating System * Copyright (c) 1993 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */#include "as.h"#include "subsegs.h"#include "struc-symbol.h"#include "ecoff.h"#include "opcode/alpha.h"#ifdef OBJ_ELF#include "elf/alpha.h"#include "dwarf2dbg.h"#endif#include <ctype.h>/* Local types */#define TOKENIZE_ERROR -1#define TOKENIZE_ERROR_REPORT -2#define MAX_INSN_FIXUPS 2#define MAX_INSN_ARGS 5struct alpha_fixup { expressionS exp; bfd_reloc_code_real_type reloc;};struct alpha_insn { unsigned insn; int nfixups; struct alpha_fixup fixups[MAX_INSN_FIXUPS]; unsigned sequence[MAX_INSN_FIXUPS];};enum alpha_macro_arg { MACRO_EOA = 1, MACRO_IR, MACRO_PIR, MACRO_OPIR, MACRO_CPIR, MACRO_FPR, MACRO_EXP, MACRO_LITERAL, MACRO_BASE, MACRO_BYTOFF, MACRO_JSR};struct alpha_macro { const char *name; void (*emit) PARAMS ((const expressionS *, int, const PTR)); const PTR arg; enum alpha_macro_arg argsets[16];};/* Extra expression types. */#define O_pregister O_md1 /* O_register, in parentheses */#define O_cpregister O_md2 /* + a leading comma */#ifdef RELOC_OP_P/* Note, the alpha_reloc_op table below depends on the ordering of O_literal .. O_gprelow. */#define O_literal O_md3 /* !literal relocation */#define O_lituse_base O_md4 /* !lituse_base relocation */#define O_lituse_bytoff O_md5 /* !lituse_bytoff relocation */#define O_lituse_jsr O_md6 /* !lituse_jsr relocation */#define O_gpdisp O_md7 /* !gpdisp relocation */#define O_gprelhigh O_md8 /* !gprelhigh relocation */#define O_gprellow O_md9 /* !gprellow relocation */#define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_gprellow)#endif/* Macros for extracting the type and number of encoded register tokens */#define is_ir_num(x) (((x) & 32) == 0)#define is_fpr_num(x) (((x) & 32) != 0)#define regno(x) ((x) & 31)/* Something odd inherited from the old assembler */#define note_gpreg(R) (alpha_gprmask |= (1 << (R)))#define note_fpreg(R) (alpha_fprmask |= (1 << (R)))/* Predicates for 16- and 32-bit ranges *//* XXX: The non-shift version appears to trigger a compiler bug when cross-assembling from x86 w/ gcc 2.7.2. */#if 1#define range_signed_16(x) \ (((offsetT) (x) >> 15) == 0 || ((offsetT) (x) >> 15) == -1)#define range_signed_32(x) \ (((offsetT) (x) >> 31) == 0 || ((offsetT) (x) >> 31) == -1)#else#define range_signed_16(x) ((offsetT) (x) >= -(offsetT) 0x8000 && \ (offsetT) (x) <= (offsetT) 0x7FFF)#define range_signed_32(x) ((offsetT) (x) >= -(offsetT) 0x80000000 && \ (offsetT) (x) <= (offsetT) 0x7FFFFFFF)#endif/* Macros for sign extending from 16- and 32-bits. *//* XXX: The cast macros will work on all the systems that I care about, but really a predicate should be found to use the non-cast forms. */#if 1#define sign_extend_16(x) ((short) (x))#define sign_extend_32(x) ((int) (x))#else#define sign_extend_16(x) ((offsetT) (((x) & 0xFFFF) ^ 0x8000) - 0x8000)#define sign_extend_32(x) ((offsetT) (((x) & 0xFFFFFFFF) \ ^ 0x80000000) - 0x80000000)#endif/* Macros to build tokens */#define set_tok_reg(t, r) (memset (&(t), 0, sizeof (t)), \ (t).X_op = O_register, \ (t).X_add_number = (r))#define set_tok_preg(t, r) (memset (&(t), 0, sizeof (t)), \ (t).X_op = O_pregister, \ (t).X_add_number = (r))#define set_tok_cpreg(t, r) (memset (&(t), 0, sizeof (t)), \ (t).X_op = O_cpregister, \ (t).X_add_number = (r))#define set_tok_freg(t, r) (memset (&(t), 0, sizeof (t)), \ (t).X_op = O_register, \ (t).X_add_number = (r) + 32)#define set_tok_sym(t, s, a) (memset (&(t), 0, sizeof (t)), \ (t).X_op = O_symbol, \ (t).X_add_symbol = (s), \ (t).X_add_number = (a))#define set_tok_const(t, n) (memset (&(t), 0, sizeof (t)), \ (t).X_op = O_constant, \ (t).X_add_number = (n))/* Prototypes for all local functions */static int tokenize_arguments PARAMS ((char *, expressionS *, int));static const struct alpha_opcode *find_opcode_match PARAMS ((const struct alpha_opcode *, const expressionS *, int *, int *));static const struct alpha_macro *find_macro_match PARAMS ((const struct alpha_macro *, const expressionS *, int *));static unsigned insert_operand PARAMS ((unsigned, const struct alpha_operand *, offsetT, char *, unsigned));static void assemble_insn PARAMS ((const struct alpha_opcode *, const expressionS *, int, struct alpha_insn *));static void emit_insn PARAMS ((struct alpha_insn *));static void assemble_tokens_to_insn PARAMS ((const char *, const expressionS *, int, struct alpha_insn *));static void assemble_tokens PARAMS ((const char *, const expressionS *, int, int));static int load_expression PARAMS ((int, const expressionS *, int *, expressionS *, const expressionS *));static void emit_ldgp PARAMS ((const expressionS *, int, const PTR));static void emit_division PARAMS ((const expressionS *, int, const PTR));static void emit_lda PARAMS ((const expressionS *, int, const PTR));static void emit_ldah PARAMS ((const expressionS *, int, const PTR));static void emit_ir_load PARAMS ((const expressionS *, int, const PTR));static void emit_loadstore PARAMS ((const expressionS *, int, const PTR));static void emit_jsrjmp PARAMS ((const expressionS *, int, const PTR));static void emit_ldX PARAMS ((const expressionS *, int, const PTR));static void emit_ldXu PARAMS ((const expressionS *, int, const PTR));static void emit_uldX PARAMS ((const expressionS *, int, const PTR));static void emit_uldXu PARAMS ((const expressionS *, int, const PTR));static void emit_ldil PARAMS ((const expressionS *, int, const PTR));static void emit_stX PARAMS ((const expressionS *, int, const PTR));static void emit_ustX PARAMS ((const expressionS *, int, const PTR));static void emit_sextX PARAMS ((const expressionS *, int, const PTR));static void emit_retjcr PARAMS ((const expressionS *, int, const PTR));static void s_alpha_text PARAMS ((int));static void s_alpha_data PARAMS ((int));#ifndef OBJ_ELFstatic void s_alpha_comm PARAMS ((int));static void s_alpha_rdata PARAMS ((int));#endif#ifdef OBJ_ECOFFstatic void s_alpha_sdata PARAMS ((int));#endif#ifdef OBJ_ELFstatic void s_alpha_section PARAMS ((int));static void s_alpha_ent PARAMS ((int));static void s_alpha_end PARAMS ((int));static void s_alpha_mask PARAMS ((int));static void s_alpha_frame PARAMS ((int));static void s_alpha_prologue PARAMS ((int));static void s_alpha_file PARAMS ((int));static void s_alpha_loc PARAMS ((int));static void s_alpha_stab PARAMS ((int));static void s_alpha_coff_wrapper PARAMS ((int));#endif#ifdef OBJ_EVAXstatic void s_alpha_section PARAMS ((int));#endifstatic void s_alpha_gprel32 PARAMS ((int));static void s_alpha_float_cons PARAMS ((int));static void s_alpha_proc PARAMS ((int));static void s_alpha_set PARAMS ((int));static void s_alpha_base PARAMS ((int));static void s_alpha_align PARAMS ((int));static void s_alpha_stringer PARAMS ((int));static void s_alpha_space PARAMS ((int));static void create_literal_section PARAMS ((const char *, segT *, symbolS **));#ifndef OBJ_ELFstatic void select_gp_value PARAMS ((void));#endifstatic void alpha_align PARAMS ((int, char *, symbolS *, int));#ifdef RELOC_OP_Pstatic void alpha_adjust_symtab_relocs PARAMS ((bfd *, asection *, PTR));#endif/* Generic assembler global variables which must be defined by all targets. *//* Characters which always start a comment. */const char comment_chars[] = "#";/* Characters which start a comment at the beginning of a line. */const char line_comment_chars[] = "#";/* Characters which may be used to separate multiple commands on a single line. */const char line_separator_chars[] = ";";/* Characters which are used to indicate an exponent in a floating point number. */const char EXP_CHARS[] = "eE";/* Characters which mean that a number is a floating point constant, as in 0d1.0. */#if 0const char FLT_CHARS[] = "dD";#else/* XXX: Do all of these really get used on the alpha?? */char FLT_CHARS[] = "rRsSfFdDxXpP";#endif#ifdef OBJ_EVAXconst char *md_shortopts = "Fm:g+1h:HG:";#elseconst char *md_shortopts = "Fm:gG:";#endifstruct option md_longopts[] = {#define OPTION_32ADDR (OPTION_MD_BASE) { "32addr", no_argument, NULL, OPTION_32ADDR },#define OPTION_RELAX (OPTION_32ADDR + 1) { "relax", no_argument, NULL, OPTION_RELAX },#ifdef OBJ_ELF#define OPTION_MDEBUG (OPTION_RELAX + 1)#define OPTION_NO_MDEBUG (OPTION_MDEBUG + 1) { "mdebug", no_argument, NULL, OPTION_MDEBUG }, { "no-mdebug", no_argument, NULL, OPTION_NO_MDEBUG },#endif { NULL, no_argument, NULL, 0 }};size_t md_longopts_size = sizeof (md_longopts);#ifdef OBJ_EVAX#define AXP_REG_R0 0#define AXP_REG_R16 16#define AXP_REG_R17 17#undef AXP_REG_T9#define AXP_REG_T9 22#undef AXP_REG_T10#define AXP_REG_T10 23#undef AXP_REG_T11#define AXP_REG_T11 24#undef AXP_REG_T12#define AXP_REG_T12 25#define AXP_REG_AI 25#undef AXP_REG_FP#define AXP_REG_FP 29#undef AXP_REG_GP#define AXP_REG_GP AXP_REG_PV#endif /* OBJ_EVAX *//* The cpu for which we are generating code */static unsigned alpha_target = AXP_OPCODE_BASE;static const char *alpha_target_name = "<all>";/* The hash table of instruction opcodes */static struct hash_control *alpha_opcode_hash;/* The hash table of macro opcodes */static struct hash_control *alpha_macro_hash;#ifdef OBJ_ECOFF/* The $gp relocation symbol */static symbolS *alpha_gp_symbol;/* XXX: what is this, and why is it exported? */valueT alpha_gp_value;#endif/* The current $gp register */static int alpha_gp_register = AXP_REG_GP;/* A table of the register symbols */static symbolS *alpha_register_table[64];/* Constant sections, or sections of constants */#ifdef OBJ_ECOFFstatic segT alpha_lita_section;static segT alpha_lit4_section;#endif#ifdef OBJ_EVAXstatic segT alpha_link_section;static segT alpha_ctors_section;static segT alpha_dtors_section;#endifstatic segT alpha_lit8_section;/* Symbols referring to said sections. */#ifdef OBJ_ECOFFstatic symbolS *alpha_lita_symbol;static symbolS *alpha_lit4_symbol;#endif#ifdef OBJ_EVAXstatic symbolS *alpha_link_symbol;static symbolS *alpha_ctors_symbol;static symbolS *alpha_dtors_symbol;#endifstatic symbolS *alpha_lit8_symbol;/* Literal for .litX+0x8000 within .lita */#ifdef OBJ_ECOFFstatic offsetT alpha_lit4_literal;static offsetT alpha_lit8_literal;#endif#ifdef OBJ_ELF/* The active .ent symbol. */static symbolS *alpha_cur_ent_sym;#endif/* Is the assembler not allowed to use $at? */static int alpha_noat_on = 0;/* Are macros enabled? */static int alpha_macros_on = 1;/* Are floats disabled? */static int alpha_nofloats_on = 0;/* Are addresses 32 bit? */static int alpha_addr32_on = 0;/* Symbol labelling the current insn. When the Alpha gas sees foo: .quad 0 and the section happens to not be on an eight byte boundary, it will align both the symbol and the .quad to an eight byte boundary. */static symbolS *alpha_insn_label;/* Whether we should automatically align data generation pseudo-ops. .align 0 will turn this off. */static int alpha_auto_align_on = 1;/* The known current alignment of the current section. */static int alpha_current_align;/* These are exported to ECOFF code. */unsigned long alpha_gprmask, alpha_fprmask;/* Whether the debugging option was seen. */static int alpha_debug;#ifdef OBJ_ELF/* Whether we are emitting an mdebug section. */int alpha_flag_mdebug = -1;#endif/* Don't fully resolve relocations, allowing code movement in the linker. */static int alpha_flag_relax;/* What value to give to bfd_set_gp_size. */static int g_switch_value = 8;#ifdef OBJ_EVAX/* Collect information about current procedure here. */static struct { symbolS *symbol; /* proc pdesc symbol */ int pdsckind; int framereg; /* register for frame pointer */ int framesize; /* size of frame */ int rsa_offset; int ra_save; int fp_save; long imask; long fmask; int type; int prologue;} alpha_evax_proc;static int alpha_flag_hash_long_names = 0; /* -+ */static int alpha_flag_show_after_trunc = 0; /* -H *//* If the -+ switch is given, then a hash is appended to any name that is * longer than 64 characters, else longer symbol names are truncated. */#endif#ifdef RELOC_OP_P/* A table to map the spelling of a relocation operand into an appropriate bfd_reloc_code_real_type type. The table is assumed to be ordered such that op-O_literal indexes into it. */#define ALPHA_RELOC_TABLE(op) \&alpha_reloc_op[ ((!USER_RELOC_P (op)) \ ? (abort (), 0) \ : (int) (op) - (int) O_literal) ]#define LITUSE_BASE 1#define LITUSE_BYTOFF 2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -