X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-m68hc11.c;h=3189121c423923dafd11d58b771c70190710735a;hb=fcdc4d0c03aa2f0476c72d900c5ced87d423a427;hp=c6a4dd5acb5c37497c164b372ca19f8167147647;hpb=ca43c8544a9faf03dbce493c10d0b679da2e97b9;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-m68hc11.c b/gas/config/tc-m68hc11.c index c6a4dd5acb..3189121c42 100644 --- a/gas/config/tc-m68hc11.c +++ b/gas/config/tc-m68hc11.c @@ -1,12 +1,15 @@ /* tc-m68hc11.c -- Assembler code for the Motorola 68HC11 & 68HC12. - Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, + 2011, 2012 + Free Software Foundation, Inc. Written by Stephane Carrez (stcarrez@nerim.fr) + XGATE and S12X added by James Murray (jsm@jsm-net.demon.co.uk) 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) + the Free Software Foundation; either version 3, or (at your option) any later version. GAS is distributed in the hope that it will be useful, @@ -16,8 +19,8 @@ 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. */ + the Free Software Foundation, 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ #include "as.h" #include "safe-ctype.h" @@ -64,7 +67,8 @@ const char FLT_CHARS[] = "dD"; 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[] = { +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. */ @@ -115,7 +119,8 @@ relax_typeS md_relax_table[] = { }; /* 68HC11 and 68HC12 registers. They are numbered according to the 68HC12. */ -typedef enum register_id { +typedef enum register_id +{ REG_NONE = -1, REG_A = 0, REG_B = 1, @@ -124,17 +129,30 @@ typedef enum register_id { REG_X = 5, REG_Y = 6, REG_SP = 7, - REG_PC = 8 + REG_PC = 8, + REG_R0 = 0, + REG_R1 = 1, + REG_R2 = 2, + REG_R3 = 3, + REG_R4 = 4, + REG_R5 = 5, + REG_R6 = 6, + REG_R7 = 7, + REG_SP_XG = 8, + REG_PC_XG = 9, + REG_CCR_XG = 10 } register_id; -typedef struct operand { +typedef struct operand +{ expressionS exp; register_id reg1; register_id reg2; int mode; } operand; -struct m68hc11_opcode_def { +struct m68hc11_opcode_def +{ long format; int min_operands; int max_operands; @@ -146,18 +164,30 @@ struct m68hc11_opcode_def { static struct m68hc11_opcode_def *m68hc11_opcode_defs = 0; static int m68hc11_nb_opcode_defs = 0; -typedef struct alias { +typedef struct alias +{ const char *name; const char *alias; } alias; -static alias alias_opcodes[] = { +static alias alias_opcodes[] = +{ {"cpd", "cmpd"}, {"cpx", "cmpx"}, {"cpy", "cmpy"}, {0, 0} }; +struct m9s12xg_opcode_def +{ + long format; + int min_operands; + int max_operands; + int nb_modes; + int used; + struct m9s12xg_opcode *opcode; +}; + /* Local functions. */ static register_id reg_name_search (char *); static register_id register_name (void); @@ -172,6 +202,7 @@ static int get_operand (operand *, int, long); static void fixup8 (expressionS *, int, int); static void fixup16 (expressionS *, int, int); static void fixup24 (expressionS *, int, int); +static void fixup8_xg (expressionS *, int, int); static unsigned char convert_branch (unsigned char); static char *m68hc11_new_insn (int); static void build_dbranch_insn (struct m68hc11_opcode *, @@ -184,6 +215,7 @@ static struct m68hc11_opcode *find (struct m68hc11_opcode_def *, static struct m68hc11_opcode *find_opcode (struct m68hc11_opcode_def *, operand *, int *); static void build_jump_insn (struct m68hc11_opcode *, operand *, int, int); +static void build_insn_xg (struct m68hc11_opcode *, operand *, int); static void build_insn (struct m68hc11_opcode *, operand *, int); static int relaxable_symbol (symbolS *); @@ -193,6 +225,9 @@ static void s_m68hc11_relax (int); /* Pseudo op to control the ELF flags. */ static void s_m68hc11_mode (int); +/* Process directives specified via pseudo ops. */ +static void s_m68hc11_parse_pseudo_instruction (int); + /* Mark the symbols with STO_M68HC12_FAR to indicate the functions are using 'rtc' for returning. It is necessary to use 'call' to invoke them. This is also used by the debugger to correctly @@ -209,7 +244,7 @@ static void s_m68hc11_mark_symbol (int); jmp L Setting the flag forbidds this. */ -static short flag_fixed_branchs = 0; +static short flag_fixed_branches = 0; /* Force to use long jumps (absolute) instead of relative branches. */ static short flag_force_long_jumps = 0; @@ -233,7 +268,7 @@ static short flag_print_opcodes = 0; static struct hash_control *m68hc11_hash; /* Current cpu (either cpu6811 or cpu6812). This is determined automagically - by 'get_default_target' by looking at default BFD vector. This is overriden + by 'get_default_target' by looking at default BFD vector. This is overridden with the -m option. */ static int current_architecture = 0; @@ -258,11 +293,13 @@ static int elf_flags = E_M68HC11_F64; pseudo-op name without dot function to call to execute this pseudo-op Integer arg to pass to the function. */ -const pseudo_typeS md_pseudo_table[] = { +const pseudo_typeS md_pseudo_table[] = +{ /* The following pseudo-ops are supported for MRI compatibility. */ {"fcb", cons, 1}, {"fdb", cons, 2}, - {"fcc", stringer, 1}, + {"fqb", cons, 4}, + {"fcc", stringer, 8 + 1}, {"rmb", s_space, 0}, /* Motorola ALIS. */ @@ -280,6 +317,9 @@ const pseudo_typeS md_pseudo_table[] = { /* .interrupt instruction. */ {"interrupt", s_m68hc11_mark_symbol, STO_M68HC12_INTERRUPT}, + /* .nobankwarning instruction. */ + {"nobankwarning", s_m68hc11_parse_pseudo_instruction, E_M68HC11_NO_BANK_WARNING}, + {0, 0, 0} }; @@ -287,12 +327,15 @@ const pseudo_typeS md_pseudo_table[] = { const char *md_shortopts = "Sm:"; -struct option md_longopts[] = { +struct option md_longopts[] = +{ #define OPTION_FORCE_LONG_BRANCH (OPTION_MD_BASE) - {"force-long-branchs", no_argument, NULL, OPTION_FORCE_LONG_BRANCH}, + {"force-long-branches", no_argument, NULL, OPTION_FORCE_LONG_BRANCH}, + {"force-long-branchs", no_argument, NULL, OPTION_FORCE_LONG_BRANCH}, /* Misspelt version kept for backwards compatibility. */ -#define OPTION_SHORT_BRANCHS (OPTION_MD_BASE + 1) - {"short-branchs", no_argument, NULL, OPTION_SHORT_BRANCHS}, +#define OPTION_SHORT_BRANCHES (OPTION_MD_BASE + 1) + {"short-branches", no_argument, NULL, OPTION_SHORT_BRANCHES}, + {"short-branchs", no_argument, NULL, OPTION_SHORT_BRANCHES}, /* Misspelt version kept for backwards compatibility. */ #define OPTION_STRICT_DIRECT_MODE (OPTION_MD_BASE + 2) {"strict-direct-mode", no_argument, NULL, OPTION_STRICT_DIRECT_MODE}, @@ -318,6 +361,9 @@ struct option md_longopts[] = { #define OPTION_MLONG_DOUBLE (OPTION_MD_BASE + 9) {"mlong-double", no_argument, NULL, OPTION_MLONG_DOUBLE}, +#define OPTION_XGATE_RAMOFFSET (OPTION_MD_BASE + 10) + {"xgate-ramoffset", no_argument, NULL, OPTION_XGATE_RAMOFFSET}, + {NULL, no_argument, NULL, 0} }; size_t md_longopts_size = sizeof (md_longopts); @@ -357,6 +403,10 @@ m68hc11_listing_header (void) { if (current_architecture & cpu6811) return "M68HC11 GAS "; + else if (current_architecture & cpuxgate) + return "XGATE GAS "; + else if (current_architecture & cpu9s12x) + return "S12X GAS "; else return "M68HC12 GAS "; } @@ -368,18 +418,20 @@ md_show_usage (FILE *stream) fprintf (stream, _("\ Motorola 68HC11/68HC12/68HCS12 options:\n\ -m68hc11 | -m68hc12 |\n\ - -m68hcs12 specify the processor [default %s]\n\ + -m68hcs12 | -mm9s12x |\n\ + -mm9s12xg specify the processor [default %s]\n\ -mshort use 16-bit int ABI (default)\n\ -mlong use 32-bit int ABI\n\ -mshort-double use 32-bit double ABI\n\ -mlong-double use 64-bit double ABI (default)\n\ - --force-long-branchs always turn relative branchs into absolute ones\n\ - -S,--short-branchs do not turn relative branchs into absolute ones\n\ + --force-long-branches always turn relative branches into absolute ones\n\ + -S,--short-branches do not turn relative branches into absolute ones\n\ when the offset is out of range\n\ --strict-direct-mode do not turn the direct mode into extended mode\n\ when the instruction does not support direct mode\n\ --print-insn-syntax print the syntax of instruction in case of error\n\ --print-opcodes print the list of instructions with syntax\n\ + --xgate-ramoffset offset ram addresses by 0xc000\n\ --generate-example generate an example of each instruction\n\ (used for testing)\n"), default_cpu); @@ -446,9 +498,9 @@ md_parse_option (int c, char *arg) switch (c) { /* -S means keep external to 2 bit offset rather than 16 bit one. */ - case OPTION_SHORT_BRANCHS: + case OPTION_SHORT_BRANCHES: case 'S': - flag_fixed_branchs = 1; + flag_fixed_branches = 1; break; case OPTION_FORCE_LONG_BRANCH: @@ -487,13 +539,26 @@ md_parse_option (int c, char *arg) elf_flags |= E_M68HC11_F64; break; + case OPTION_XGATE_RAMOFFSET: + elf_flags |= E_M68HC11_XGATE_RAMOFFSET; + break; + case 'm': - if (strcasecmp (arg, "68hc11") == 0) + if ((strcasecmp (arg, "68hc11") == 0) + || (strcasecmp (arg, "m68hc11") == 0)) current_architecture = cpu6811; - else if (strcasecmp (arg, "68hc12") == 0) + else if ((strcasecmp (arg, "68hc12") == 0) + || (strcasecmp (arg, "m68hc12") == 0)) current_architecture = cpu6812; - else if (strcasecmp (arg, "68hcs12") == 0) + else if ((strcasecmp (arg, "68hcs12") == 0) + || (strcasecmp (arg, "m68hcs12") == 0)) current_architecture = cpu6812 | cpu6812s; + else if (strcasecmp (arg, "m9s12x") == 0) + current_architecture = cpu6812 | cpu6812s | cpu9s12x; + else if ((strcasecmp (arg, "m9s12xg") == 0) + || (strcasecmp (arg, "xgate") == 0)) + /* xgate for backwards compatability */ + current_architecture = cpuxgate; else as_bad (_("Option `%s' is not recognized."), arg); break; @@ -511,62 +576,10 @@ md_undefined_symbol (char *name ATTRIBUTE_UNUSED) return 0; } -/* Equal to MAX_PRECISION in atof-ieee.c. */ -#define MAX_LITTLENUMS 6 - -/* Turn a string in input_line_pointer into a floating point constant - of type TYPE, and store the appropriate bytes in *LITP. The number - of LITTLENUMS emitted is stored in *SIZEP. An error message is - returned, or NULL on OK. */ char * md_atof (int type, char *litP, int *sizeP) { - int prec; - LITTLENUM_TYPE words[MAX_LITTLENUMS]; - LITTLENUM_TYPE *wordP; - char *t; - - switch (type) - { - case 'f': - case 'F': - case 's': - case 'S': - prec = 2; - break; - - case 'd': - case 'D': - case 'r': - case 'R': - prec = 4; - break; - - case 'x': - case 'X': - prec = 6; - break; - - case 'p': - case 'P': - prec = 6; - 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--;) - { - md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE)); - litP += sizeof (LITTLENUM_TYPE); - } - return 0; + return ieee_md_atof (type, litP, sizeP, TRUE); } valueT @@ -663,23 +676,39 @@ md_begin (void) /* See how many operands this opcode needs. */ expect = 0; - if (opcodes->format & M6811_OP_MASK) - expect++; - if (opcodes->format & M6811_OP_BITMASK) - expect++; - if (opcodes->format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16)) - expect++; - if (opcodes->format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2)) - expect++; - /* Special case for call instruction. */ - if ((opcodes->format & M6812_OP_PAGE) - && !(opcodes->format & M6811_OP_IND16)) - expect++; + if (opcodes->arch == cpuxgate) + { + if (opcodes->format & (M68XG_OP_IMM3 | M68XG_OP_R | M68XG_OP_REL9 + | M68XG_OP_REL10 )) + expect = 1; + else if (opcodes->format & (M68XG_OP_R_R | M68XG_OP_R_IMM4 + | M68XG_OP_R_IMM8 | M68XG_OP_R_IMM8)) + expect = 2; + else if (opcodes->format & (M68XG_OP_R_R_R | M68XG_OP_R_R_OFFS5 + | M68XG_OP_RD_RB_RI | M68XG_OP_RD_RB_RIp + | M68XG_OP_RD_RB_mRI)) + expect = 3; + } + else + { + if (opcodes->format & M6811_OP_MASK) + expect++; + if (opcodes->format & M6811_OP_BITMASK) + expect++; + if (opcodes->format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16)) + expect++; + if (opcodes->format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2)) + expect++; + /* Special case for call instruction. */ + if ((opcodes->format & M6812_OP_PAGE) + && !(opcodes->format & M6811_OP_IND16)) + expect++; + } if (expect < opc->min_operands) opc->min_operands = expect; if (IS_CALL_SYMBOL (opcodes->format)) - expect++; + expect++; if (expect > opc->max_operands) opc->max_operands = expect; } @@ -703,6 +732,7 @@ m68hc11_init_after_args (void) /* Return a string that represents the operand format for the instruction. When example is true, this generates an example of operand. This is used to give an example and also to generate a test. */ + static char * print_opcode_format (struct m68hc11_opcode *opcode, int example) { @@ -712,111 +742,222 @@ print_opcode_format (struct m68hc11_opcode *opcode, int example) p = buf; buf[0] = 0; - if (format & M6811_OP_IMM8) - { - if (example) - sprintf (p, "#%d", rand () & 0x0FF); - else - strcpy (p, _("#")); - p = &p[strlen (p)]; - } - if (format & M6811_OP_IMM16) + if (current_architecture == cpuxgate) { - if (example) - sprintf (p, "#%d", rand () & 0x0FFFF); - else - strcpy (p, _("#")); - p = &p[strlen (p)]; + if (format & M68XG_OP_IMM3) + { + if (example) + sprintf (p, "#%d", rand () & 0x007); + else + strcpy (p, _("imm3")); + p = &p[strlen (p)]; + } + else if (format & M68XG_OP_R) + { + if (example) + sprintf (p, "R%d", rand () & 0x07); + else + strcpy (p, _("RD")); + p = &p[strlen (p)]; + } + else if (format & M68XG_OP_R_R) + { + if (example) + sprintf (p, "R%d,R%d", rand () & 0x07, rand () & 0x07); + else + strcpy (p, _("RD,RS")); + p = &p[strlen (p)]; + } + else if (format & M68XG_OP_R_IMM4) + { + if (example) + sprintf (p, "R%d,#%d", rand () & 0x07, rand () & 0x0f); + else + strcpy (p, _("RI, #imm4")); + p = &p[strlen (p)]; + } + else if (format & M68XG_OP_R_R_R) + { + if (example) + sprintf (p, "R%d,R%d,R%d", rand () & 0x07, rand () & 0x07, rand () & 0x07); + else + strcpy (p, "RD,RS1,RS2"); + p = &p[strlen (p)]; + } + else if (format & M68XG_OP_REL9) + { + if (example) + sprintf (p, "%d", rand () & 0x1FF); + else + strcpy (p, ""); + p = &p[strlen (p)]; + } + else if (format & M68XG_OP_REL10) + { + if (example) + sprintf (p, "%d", rand () & 0x3FF); + else + strcpy (p, ""); + p = &p[strlen (p)]; + } + else if (format & M68XG_OP_R_R_OFFS5) + { + if (example) + sprintf (p, "R%d, (R%d, #0x%x)", rand () & 0x07, rand () & 0x07, rand () & 0x1f); + else + strcpy (p, _("RD, (RI,#offs5)")); + p = &p[strlen (p)]; + } + else if (format & M68XG_OP_RD_RB_RI) + { + if (example) + sprintf (p, "R%d, (R%d, R%d)", rand () & 0x07, rand () & 0x07, rand () & 0x07); + else + strcpy (p, "RD, (RB, RI)"); + p = &p[strlen (p)]; + } + else if (format & M68XG_OP_RD_RB_RIp) + { + if (example) + sprintf (p, "R%d, (R%d, R%d+)", rand () & 0x07, rand () & 0x07, rand () & 0x07); + else + strcpy (p, "RD, (RB, RI+)"); + p = &p[strlen (p)]; + } + else if (format & M68XG_OP_RD_RB_mRI) + { + if (example) + sprintf (p, "R%d, (R%d, -R%d)", rand () & 0x07, rand () & 0x07, rand () & 0x07); + else + strcpy (p, "RD, (RB, -RI)"); + p = &p[strlen (p)]; + } + else if (format & M68XG_OP_R_IMM8) + { + if (example) + sprintf (p, "R%d, #0x%x", rand () & 0x07, rand () & 0xff); + else + strcpy (p, "RD, #imm8"); + p = &p[strlen (p)]; + } + else if (format & M68XG_OP_R_IMM16) + { + if (example) + sprintf (p, "R%d, #0x%x", rand () & 0x07, rand () & 0xffff); + else + strcpy (p, "RD, #imm16"); + p = &p[strlen (p)]; + } } - - if (format & M6811_OP_IX) + else { - if (example) - sprintf (p, "%d,X", rand () & 0x0FF); - else - strcpy (p, _(",X")); - p = &p[strlen (p)]; - } - if (format & M6811_OP_IY) - { - if (example) - sprintf (p, "%d,X", rand () & 0x0FF); - else - strcpy (p, _(",X")); - p = &p[strlen (p)]; - } + if (format & M6811_OP_IMM8) + { + if (example) + sprintf (p, "#%d", rand () & 0x0FF); + else + strcpy (p, _("#")); + p = &p[strlen (p)]; + } - if (format & M6812_OP_IDX) - { - if (example) - sprintf (p, "%d,X", rand () & 0x0FF); - else - strcpy (p, "n,r"); - p = &p[strlen (p)]; - } + if (format & M6811_OP_IMM16) + { + if (example) + sprintf (p, "#%d", rand () & 0x0FFFF); + else + strcpy (p, _("#")); + p = &p[strlen (p)]; + } - if (format & M6812_OP_PAGE) - { - if (example) - sprintf (p, ", %d", rand () & 0x0FF); - else - strcpy (p, ", "); - p = &p[strlen (p)]; - } + if (format & M6811_OP_IX) + { + if (example) + sprintf (p, "%d,X", rand () & 0x0FF); + else + strcpy (p, _(",X")); + p = &p[strlen (p)]; + } - if (format & M6811_OP_DIRECT) - { - if (example) - sprintf (p, "*Z%d", rand () & 0x0FF); - else - strcpy (p, _("*")); - p = &p[strlen (p)]; - } + if (format & M6811_OP_IY) + { + if (example) + sprintf (p, "%d,X", rand () & 0x0FF); + else + strcpy (p, _(",X")); + p = &p[strlen (p)]; + } - if (format & M6811_OP_BITMASK) - { - if (buf[0]) - *p++ = ' '; + if (format & M6812_OP_IDX) + { + if (example) + sprintf (p, "%d,X", rand () & 0x0FF); + else + strcpy (p, "n,r"); + p = &p[strlen (p)]; + } - if (example) - sprintf (p, "#$%02x", rand () & 0x0FF); - else - strcpy (p, _("#")); + if (format & M6812_OP_PAGE) + { + if (example) + sprintf (p, ", %d", rand () & 0x0FF); + else + strcpy (p, ", "); + p = &p[strlen (p)]; + } - p = &p[strlen (p)]; - if (format & M6811_OP_JUMP_REL) - *p++ = ' '; - } + if (format & M6811_OP_DIRECT) + { + if (example) + sprintf (p, "*Z%d", rand () & 0x0FF); + else + strcpy (p, _("*")); + p = &p[strlen (p)]; + } - if (format & M6811_OP_IND16) - { - if (example) - sprintf (p, _("symbol%d"), rand () & 0x0FF); - else - strcpy (p, _("")); + if (format & M6811_OP_BITMASK) + { + if (buf[0]) + *p++ = ' '; - p = &p[strlen (p)]; - } + if (example) + sprintf (p, "#$%02x", rand () & 0x0FF); + else + strcpy (p, _("#")); - if (format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16)) - { - if (example) + p = &p[strlen (p)]; + if (format & M6811_OP_JUMP_REL) + *p++ = ' '; + } + + if (format & M6811_OP_IND16) { - if (format & M6811_OP_BITMASK) - { - sprintf (p, ".+%d", rand () & 0x7F); - } + if (example) + sprintf (p, _("symbol%d"), rand () & 0x0FF); else + strcpy (p, _("")); + + p = &p[strlen (p)]; + } + + if (format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16)) + { + if (example) { - sprintf (p, "L%d", rand () & 0x0FF); + if (format & M6811_OP_BITMASK) + { + sprintf (p, ".+%d", rand () & 0x7F); + } + else + { + sprintf (p, "L%d", rand () & 0x0FF); + } } + else + strcpy (p, _("