X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-m68hc11.c;h=1c36d5d98cba01efd4ee0f38bca0d21cbf467fa5;hb=508559397632e046a1f734f27d2b1971b1d172d1;hp=c31496191d67f731c95029b6df037d0d3a6df7b0;hpb=87975d2a60adf249212c1c031abb4dd0dbb800ac;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-m68hc11.c b/gas/config/tc-m68hc11.c index c31496191d..1c36d5d98c 100644 --- a/gas/config/tc-m68hc11.c +++ b/gas/config/tc-m68hc11.c @@ -1,7 +1,7 @@ /* tc-m68hc11.c -- Assembler code for the Motorola 68HC11 & 68HC12. - Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 1999-2019 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. @@ -65,7 +65,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. */ @@ -116,7 +117,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, @@ -125,17 +127,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; @@ -147,18 +162,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); @@ -173,6 +200,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 *, @@ -185,6 +213,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 *); @@ -194,6 +223,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 +241,7 @@ static void s_m68hc11_mark_symbol (int); dbcc -> db!cc +3 jmp L - Setting the flag forbidds this. */ + Setting the flag forbids this. */ static short flag_fixed_branches = 0; /* Force to use long jumps (absolute) instead of relative branches. */ @@ -259,10 +291,12 @@ 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}, + {"fqb", cons, 4}, {"fcc", stringer, 8 + 1}, {"rmb", s_space, 0}, @@ -281,6 +315,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} }; @@ -288,14 +325,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-branches", no_argument, NULL, OPTION_FORCE_LONG_BRANCH}, - {"force-long-branchs", no_argument, NULL, OPTION_FORCE_LONG_BRANCH}, /* Misspelt version kept for backwards compatibility. */ + {"force-long-branchs", no_argument, NULL, OPTION_FORCE_LONG_BRANCH}, /* Misspelled version kept for backwards compatibility. */ #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. */ + {"short-branchs", no_argument, NULL, OPTION_SHORT_BRANCHES}, /* Misspelled version kept for backwards compatibility. */ #define OPTION_STRICT_DIRECT_MODE (OPTION_MD_BASE + 2) {"strict-direct-mode", no_argument, NULL, OPTION_STRICT_DIRECT_MODE}, @@ -321,6 +359,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); @@ -360,6 +401,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 "; } @@ -371,7 +416,8 @@ 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\ @@ -383,6 +429,7 @@ Motorola 68HC11/68HC12/68HCS12 options:\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); @@ -443,7 +490,7 @@ m68hc11_print_statistics (FILE *file) } int -md_parse_option (int c, char *arg) +md_parse_option (int c, const char *arg) { get_default_target (); switch (c) @@ -490,13 +537,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 compatibility */ + current_architecture = cpuxgate; else as_bad (_("Option `%s' is not recognized."), arg); break; @@ -514,7 +574,7 @@ md_undefined_symbol (char *name ATTRIBUTE_UNUSED) return 0; } -char * +const char * md_atof (int type, char *litP, int *sizeP) { return ieee_md_atof (type, litP, sizeP, TRUE); @@ -523,8 +583,8 @@ md_atof (int type, char *litP, int *sizeP) valueT md_section_align (asection *seg, valueT addr) { - int align = bfd_get_section_alignment (stdoutput, seg); - return ((addr + (1 << align) - 1) & (-1 << align)); + int align = bfd_section_alignment (seg); + return ((addr + (1 << align) - 1) & -(1 << align)); } static int @@ -543,7 +603,7 @@ cmp_opcode (struct m68hc11_opcode *op1, struct m68hc11_opcode *op2) void md_begin (void) { - char *prev_name = ""; + const char *prev_name = ""; struct m68hc11_opcode *opcodes; struct m68hc11_opcode_def *opc = 0; int i, j; @@ -553,9 +613,7 @@ md_begin (void) m68hc11_hash = hash_new (); /* Get a writable copy of the opcode table and sort it on the names. */ - opcodes = (struct m68hc11_opcode *) xmalloc (m68hc11_num_opcodes * - sizeof (struct - m68hc11_opcode)); + opcodes = XNEWVEC (struct m68hc11_opcode, m68hc11_num_opcodes); m68hc11_sorted_opcodes = opcodes; num_opcodes = 0; for (i = 0; i < m68hc11_num_opcodes; i++) @@ -584,8 +642,7 @@ md_begin (void) qsort (opcodes, num_opcodes, sizeof (struct m68hc11_opcode), (int (*) (const void*, const void*)) cmp_opcode); - opc = (struct m68hc11_opcode_def *) - xmalloc (num_opcodes * sizeof (struct m68hc11_opcode_def)); + opc = XNEWVEC (struct m68hc11_opcode_def, num_opcodes); m68hc11_opcode_defs = opc--; /* Insert unique names into hash table. The M6811 instruction set @@ -614,23 +671,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; } @@ -654,6 +727,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) { @@ -663,111 +737,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, _("