📄 tc-m68k.c
字号:
/* tc-m68k.c -- Assemble for the m68k family Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. 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. */#include <ctype.h>#include "as.h"#include "obstack.h"#include "subsegs.h"#include "opcode/m68k.h"#include "m68k-parse.h"#if defined (OBJ_ELF)#include "elf/m68k.h"#endif/* This string holds the chars that always start a comment. If the pre-processor is disabled, these aren't very useful. The macro tc_comment_chars points to this. We use this, rather than the usual comment_chars, so that the --bitwise-or option will work. */#if defined (TE_SVR4) || defined (TE_DELTA)const char *m68k_comment_chars = "|#";#elseconst char *m68k_comment_chars = "|";#endif/* This array holds the chars that only start a comment at the beginning of a line. If the line seems to have the form '# 123 filename' .line and .file directives will appear in the pre-processed output *//* Note that input_file.c hand checks for '#' at the beginning of the first line of the input file. This is because the compiler outputs #NO_APP at the beginning of its output. *//* Also note that comments like this one will always work. */const char line_comment_chars[] = "#*";const char line_separator_chars[] = ";";/* Chars that can be used to separate mant from exp in floating point nums */CONST char EXP_CHARS[] = "eE";/* Chars that mean this number is a floating point constant, as in "0f12.456" or "0d1.2345e12". */CONST char FLT_CHARS[] = "rRsSfFdDxXeEpP";/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be changed in read.c . Ideally it shouldn't have to know about it at all, but nothing is ideal around here. */const int md_reloc_size = 8; /* Size of relocation record *//* Are we trying to generate PIC code? If so, absolute references ought to be made into linkage table references or pc-relative references. Not implemented. For ELF there are other means to denote pic relocations. */int flag_want_pic;static int flag_short_refs; /* -l option */static int flag_long_jumps; /* -S option */static int flag_keep_pcrel; /* --pcrel option. */#ifdef REGISTER_PREFIX_OPTIONALint flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL;#elseint flag_reg_prefix_optional;#endif/* Whether --register-prefix-optional was used on the command line. */static int reg_prefix_optional_seen;/* The floating point coprocessor to use by default. */static enum m68k_register m68k_float_copnum = COP1;/* If this is non-zero, then references to number(%pc) will be taken to refer to number, rather than to %pc + number. */static int m68k_abspcadd;/* If this is non-zero, then the quick forms of the move, add, and sub instructions are used when possible. */static int m68k_quick = 1;/* If this is non-zero, then if the size is not specified for a base or outer displacement, the assembler assumes that the size should be 32 bits. */static int m68k_rel32 = 1;/* This is non-zero if m68k_rel32 was set from the command line. */static int m68k_rel32_from_cmdline;/* The default width to use for an index register when using a base displacement. */static enum m68k_size m68k_index_width_default = SIZE_LONG;/* We want to warn if any text labels are misaligned. In order to get the right line number, we need to record the line number for each label. */struct label_line{ struct label_line *next; symbolS *label; char *file; unsigned int line; int text;};/* The list of labels. */static struct label_line *labels;/* The current label. */static struct label_line *current_label;/* Its an arbitrary name: This means I don't approve of it *//* See flames below */static struct obstack robyn;struct m68k_incant { const char *m_operands; unsigned long m_opcode; short m_opnum; short m_codenum; int m_arch; struct m68k_incant *m_next; };#define getone(x) ((((x)->m_opcode)>>16)&0xffff)#define gettwo(x) (((x)->m_opcode)&0xffff)static const enum m68k_register m68000_control_regs[] = { 0 };static const enum m68k_register m68010_control_regs[] = { SFC, DFC, USP, VBR, 0};static const enum m68k_register m68020_control_regs[] = { SFC, DFC, USP, VBR, CACR, CAAR, MSP, ISP, 0};static const enum m68k_register m68040_control_regs[] = { SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1, USP, VBR, MSP, ISP, MMUSR, URP, SRP, 0};static const enum m68k_register m68060_control_regs[] = { SFC, DFC, CACR, TC, ITT0, ITT1, DTT0, DTT1, BUSCR, USP, VBR, URP, SRP, PCR, 0};static const enum m68k_register mcf_control_regs[] = { CACR, TC, ITT0, ITT1, DTT0, DTT1, VBR, ROMBAR, RAMBAR0, RAMBAR1, MBAR, 0};#define cpu32_control_regs m68010_control_regsstatic const enum m68k_register *control_regs;/* internal form of a 68020 instruction */struct m68k_it{ const char *error; const char *args; /* list of opcode info */ int numargs; int numo; /* Number of shorts in opcode */ short opcode[11]; struct m68k_op operands[6]; int nexp; /* number of exprs in use */ struct m68k_exp exprs[4]; int nfrag; /* Number of frags we have to produce */ struct { int fragoff; /* Where in the current opcode the frag ends */ symbolS *fadd; offsetT foff; int fragty; } fragb[4]; int nrel; /* Num of reloc strucs in use */ struct { int n; expressionS exp; char wid; char pcrel; /* In a pc relative address the difference between the address of the offset and the address that the offset is relative to. This depends on the addressing mode. Basically this is the value to put in the offset field to address the first byte of the offset, without regarding the special significance of some values (in the branch instruction, for example). */ int pcrel_fix;#ifdef OBJ_ELF /* Whether this expression needs special pic relocation, and if so, which. */ enum pic_relocation pic_reloc;#endif } reloc[5]; /* Five is enough??? */};#define cpu_of_arch(x) ((x) & (m68000up|mcf))#define float_of_arch(x) ((x) & mfloat)#define mmu_of_arch(x) ((x) & mmmu)#define arch_coldfire_p(x) (((x) & mcf) != 0)/* Macros for determining if cpu supports a specific addressing mode */#define HAVE_LONG_BRANCH(x) ((x) & (m68020|m68030|m68040|m68060|cpu32|mcf5407))static struct m68k_it the_ins; /* the instruction being assembled */#define op(ex) ((ex)->exp.X_op)#define adds(ex) ((ex)->exp.X_add_symbol)#define subs(ex) ((ex)->exp.X_op_symbol)#define offs(ex) ((ex)->exp.X_add_number)/* Macros for adding things to the m68k_it struct */#define addword(w) the_ins.opcode[the_ins.numo++]=(w)/* Static functions. */static void insop PARAMS ((int, const struct m68k_incant *));static void add_fix PARAMS ((int, struct m68k_exp *, int, int));static void add_frag PARAMS ((symbolS *, offsetT, int));/* Like addword, but goes BEFORE general operands */static voidinsop (w, opcode) int w; const struct m68k_incant *opcode;{ int z; for(z=the_ins.numo;z>opcode->m_codenum;--z) the_ins.opcode[z]=the_ins.opcode[z-1]; for(z=0;z<the_ins.nrel;z++) the_ins.reloc[z].n+=2; for (z = 0; z < the_ins.nfrag; z++) the_ins.fragb[z].fragoff++; the_ins.opcode[opcode->m_codenum]=w; the_ins.numo++;}/* The numo+1 kludge is so we can hit the low order byte of the prev word. Blecch. */static voidadd_fix (width, exp, pc_rel, pc_fix) int width; struct m68k_exp *exp; int pc_rel; int pc_fix;{ the_ins.reloc[the_ins.nrel].n = ((width == 'B' || width == '3') ? (the_ins.numo*2-1) : (((width)=='b') ? (the_ins.numo*2+1) : (the_ins.numo*2))); the_ins.reloc[the_ins.nrel].exp = exp->exp; the_ins.reloc[the_ins.nrel].wid = width; the_ins.reloc[the_ins.nrel].pcrel_fix = pc_fix;#ifdef OBJ_ELF the_ins.reloc[the_ins.nrel].pic_reloc = exp->pic_reloc;#endif the_ins.reloc[the_ins.nrel++].pcrel = pc_rel;}/* Cause an extra frag to be generated here, inserting up to 10 bytes (that value is chosen in the frag_var call in md_assemble). TYPE is the subtype of the frag to be generated; its primary type is rs_machine_dependent. The TYPE parameter is also used by md_convert_frag_1 and md_estimate_size_before_relax. The appropriate type of fixup will be emitted by md_convert_frag_1. ADD becomes the FR_SYMBOL field of the frag, and OFF the FR_OFFSET. */static voidadd_frag (add, off, type) symbolS *add; offsetT off; int type;{ the_ins.fragb[the_ins.nfrag].fragoff=the_ins.numo; the_ins.fragb[the_ins.nfrag].fadd=add; the_ins.fragb[the_ins.nfrag].foff=off; the_ins.fragb[the_ins.nfrag++].fragty=type;}#define isvar(ex) \ (op (ex) != O_constant && op (ex) != O_big)static char *crack_operand PARAMS ((char *str, struct m68k_op *opP));static int get_num PARAMS ((struct m68k_exp *exp, int ok));static void m68k_ip PARAMS ((char *));static void insert_reg PARAMS ((const char *, int));static void select_control_regs PARAMS ((void));static void init_regtable PARAMS ((void));static int reverse_16_bits PARAMS ((int in));static int reverse_8_bits PARAMS ((int in));static void install_gen_operand PARAMS ((int mode, int val));static void install_operand PARAMS ((int mode, int val));static void s_bss PARAMS ((int));static void s_data1 PARAMS ((int));static void s_data2 PARAMS ((int));static void s_even PARAMS ((int));static void s_proc PARAMS ((int));static void mri_chip PARAMS ((void));static void s_chip PARAMS ((int));static void s_fopt PARAMS ((int));static void s_opt PARAMS ((int));static void s_reg PARAMS ((int));static void s_restore PARAMS ((int));static void s_save PARAMS ((int));static void s_mri_if PARAMS ((int));static void s_mri_else PARAMS ((int));static void s_mri_endi PARAMS ((int));static void s_mri_break PARAMS ((int));static void s_mri_next PARAMS ((int));static void s_mri_for PARAMS ((int));static void s_mri_endf PARAMS ((int));static void s_mri_repeat PARAMS ((int));static void s_mri_until PARAMS ((int));static void s_mri_while PARAMS ((int));static void s_mri_endw PARAMS ((int));static void md_apply_fix_2 PARAMS ((fixS *, offsetT));static void md_convert_frag_1 PARAMS ((fragS *));static int current_architecture;struct m68k_cpu { unsigned long arch; const char *name; int alias; };static const struct m68k_cpu archs[] = { { m68000, "68000", 0 }, { m68010, "68010", 0 }, { m68020, "68020", 0 }, { m68030, "68030", 0 }, { m68040, "68040", 0 }, { m68060, "68060", 0 }, { cpu32, "cpu32", 0 }, { m68881, "68881", 0 }, { m68851, "68851", 0 }, { mcf5200, "5200", 0 }, { mcf5206e, "5206e", 0 }, { mcf5307, "5307", 0}, { mcf5407, "5407", 0}, /* Aliases (effectively, so far as gas is concerned) for the above cpus. */ { m68020, "68k", 1 }, { m68000, "68008", 1 }, { m68000, "68302", 1 }, { m68000, "68306", 1 }, { m68000, "68307", 1 }, { m68000, "68322", 1 }, { m68000, "68356", 1 }, { m68000, "68ec000", 1 }, { m68000, "68hc000", 1 }, { m68000, "68hc001", 1 }, { m68020, "68ec020", 1 }, { m68030, "68ec030", 1 }, { m68040, "68ec040", 1 }, { m68060, "68ec060", 1 }, { cpu32, "68330", 1 }, { cpu32, "68331", 1 }, { cpu32, "68332", 1 }, { cpu32, "68333", 1 }, { cpu32, "68334", 1 }, { cpu32, "68336", 1 }, { cpu32, "68340", 1 }, { cpu32, "68341", 1 }, { cpu32, "68349", 1 }, { cpu32, "68360", 1 }, { m68881, "68882", 1 }, { mcf5200, "5202", 1 }, { mcf5200, "5204", 1 }, { mcf5200, "5206", 1 }, };static const int n_archs = sizeof (archs) / sizeof (archs[0]);/* This is the assembler relaxation table for m68k. m68k is a rich CISC architecture and we have a lot of relaxation modes. *//* Macros used in the relaxation code. */#define TAB(x,y) (((x) << 2) + (y))#define TABTYPE(x) ((x) >> 2)/* Relaxation states. */#define BYTE 0#define SHORT 1#define LONG 2#define SZ_UNDEF 3/* Here are all the relaxation modes we support. First we can relax ordinary branches. On 68020 and higher and on CPU32 all branch instructions take three forms, so on these CPUs all branches always remain as such. When we have to expand to the LONG form on a 68000, though, we substitute an absolute jump instead. This is a direct replacement for unconditional branches and a branch over a jump for conditional branches. However, if the user requires PIC and disables this with --pcrel, we can only relax between BYTE and SHORT forms, punting if that isn't enough. This gives us four different relaxation modes for branches: */#define BRANCHBWL 1 /* branch byte, word, or long */#define BRABSJUNC 2 /* absolute jump for LONG, unconditional */#define BRABSJCOND 3 /* absolute jump for LONG, conditional */#define BRANCHBW 4 /* branch byte or word *//* We also relax coprocessor branches and DBcc's. All CPUs that support coprocessor branches support them in word and long forms, so we have only one relaxation mode for them. DBcc's are word only on all CPUs. We can relax them to the LONG form with a branch-around sequence. This sequence can use a long branch (if available) or an absolute jump (if acceptable). This gives us two relaxation modes. If long branches are not available and absolute jumps are not acceptable, we don't relax DBcc's. */#define FBRANCH 5 /* coprocessor branch */#define DBCCLBR 6 /* DBcc relaxable with a long branch */#define DBCCABSJ 7 /* DBcc relaxable with an absolute jump *//* That's all for instruction relaxation. However, we also relax PC-relative operands. Specifically, we have three operand relaxation modes. On the 68000 PC-relative operands can only be 16-bit, but on 68020 and higher and on CPU32 they may be 16-bit or 32-bit. For the latter we relax between the two. Also PC+displacement+index operands in their simple form (with a non- suppressed index without memory indirection) are supported on all CPUs, but on the 68000 the displacement can be 8-bit only, whereas on 68020 and higher and on CPU32 we relax it to SHORT and LONG forms as well using the extended form of the PC+displacement+index operand. Finally, some absolute operands can be relaxed down to 16-bit PC-relative. */#define PCREL1632 8 /* 16-bit or 32-bit PC-relative */#define PCINDEX 9 /* PC+displacement+index */#define ABSTOPCREL 10 /* absolute relax down to 16-bit PC-relative *//* Note that calls to frag_var need to specify the maximum expansion needed; this is currently 10 bytes for DBCC. *//* The fields are: How far Forward this mode will reach: How far Backward this mode will reach: How many bytes this mode will add to the size of the frag Which mode to go to if the offset won't fit in this one */relax_typeS md_relax_table[] ={ {1, 1, 0, 0}, /* First entries aren't used */ {1, 1, 0, 0}, /* For no good reason except */ {1, 1, 0, 0}, /* that the VAX doesn't either */ {1, 1, 0, 0}, {(127), (-128), 0, TAB (BRANCHBWL, SHORT)}, {(32767), (-32768), 2, TAB (BRANCHBWL, LONG)}, {0, 0, 4, 0}, {1, 1, 0, 0}, {(127), (-128), 0, TAB (BRABSJUNC, SHORT)}, {(32767), (-32768), 2, TAB (BRABSJUNC, LONG)}, {0, 0, 4, 0}, {1, 1, 0, 0}, {(127), (-128), 0, TAB (BRABSJCOND, SHORT)}, {(32767), (-32768), 2, TAB (BRABSJCOND, LONG)}, {0, 0, 6, 0}, {1, 1, 0, 0}, {(127), (-128), 0, TAB (BRANCHBW, SHORT)}, {0, 0, 2, 0}, {1, 1, 0, 0}, {1, 1, 0, 0}, {1, 1, 0, 0}, /* FBRANCH doesn't come BYTE */ {(32767), (-32768), 2, TAB (FBRANCH, LONG)}, {0, 0, 4, 0}, {1, 1, 0, 0}, {1, 1, 0, 0}, /* DBCC doesn't come BYTE */ {(32767), (-32768), 2, TAB (DBCCLBR, LONG)}, {0, 0, 10, 0}, {1, 1, 0, 0}, {1, 1, 0, 0}, /* DBCC doesn't come BYTE */ {(32767), (-32768), 2, TAB (DBCCABSJ, LONG)}, {0, 0, 10, 0}, {1, 1, 0, 0}, {1, 1, 0, 0}, /* PCREL1632 doesn't come BYTE */ {32767, -32768, 2, TAB (PCREL1632, LONG)}, {0, 0, 6, 0}, {1, 1, 0, 0}, {125, -130, 0, TAB (PCINDEX, SHORT)}, {32765, -32770, 2, TAB (PCINDEX, LONG)}, {0, 0, 4, 0}, {1, 1, 0, 0}, {1, 1, 0, 0}, /* ABSTOPCREL doesn't come BYTE */ {(32767), (-32768), 2, TAB (ABSTOPCREL, LONG)}, {0, 0, 4, 0}, {1, 1, 0, 0},};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -