Add support for M340
authorNick Clifton <nickc@redhat.com>
Thu, 10 Feb 2000 21:31:13 +0000 (21:31 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 10 Feb 2000 21:31:13 +0000 (21:31 +0000)
gas/ChangeLog
gas/config/tc-mcore.c
gas/config/tc-mcore.h

index f12ee84060074d6023f59c98732b48b0226503f5..4dd895b0ba332e1f3d2ced2769a9bde6a2ccda88 100644 (file)
@@ -1,3 +1,21 @@
+2000-02-10  Nick Clifton  <nickc@cygnus.com>
+
+       * config/tc-mcore.c (INST_BYTE0): Redefine to handle big and
+        little endian targets.
+       (INST_BYTE1): Redefine to handle big and little endian
+        targets.
+       (cpu_type): New type: Select between M340 and M210.
+       (parse_psrmod): New function: Parse the PSRCLR and PSRSET
+        instructions of the M340.
+       (md_assemble): Add support for the MULSH and OPSR classes of
+        instructions.
+       (md_atof): Add support for little endian targets.
+       (md_parse_option): Add support for -EL, -EB and -mcpu command
+        line switches.
+       (md_convert_frag): Add support for little endian targets.
+       (md_apply_fix3): Add support for little endian targets.
+       (md_number_to_chars): Add support for little endian targets.
+
 2000-02-10  Timothy Wall  <twall@redhat.com>
 
        * read.c (read_a_source_file): If TC_START_LABEL_WITHOUT_COLON is
index 4accf980bc9e48e4b3c0f52ae947c565103ec993..d072f032381e51acde6f790de6f17e335e2c8614 100644 (file)
@@ -48,6 +48,7 @@ static char * parse_exp    PARAMS ((char *, expressionS *));
 static char * parse_rt     PARAMS ((char *, char **, int, expressionS *));
 static char * parse_imm    PARAMS ((char *, unsigned *, unsigned, unsigned));
 static char * parse_mem    PARAMS ((char *, unsigned *, unsigned *, unsigned));
+static char * parse_psrmod PARAMS ((char *, unsigned *));
 static void   make_name PARAMS ((char *, char *, int));
 static int    enter_literal PARAMS ((expressionS *, int));
 static void   dump_literals PARAMS ((int));
@@ -64,8 +65,8 @@ static void   mcore_s_comm    PARAMS ((int));
    object. They should use MCORE_INST_XXX macros to get the opcodes
    and then use these two macros to crack the MCORE_INST value into
    the appropriate byte values.  */
-#define        INST_BYTE0(x)  (((x) >> 8) & 0xFF)
-#define        INST_BYTE1(x)  ((x) & 0xFF)
+#define        INST_BYTE0(x)  (target_big_endian ? (((x) >> 8) & 0xFF) : ((x) & 0xFF))
+#define        INST_BYTE1(x)  (target_big_endian ? ((x) & 0xFF) : (((x) >> 8) & 0xFF))
 
 const char comment_chars[] = "#/";
 const char line_separator_chars[] = ";";
@@ -103,6 +104,14 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP";
 #define U12_LEN                2
 #define U32_LEN                8       /* allow for align */
 
+typedef enum
+{
+  M210,
+  M340
+}
+cpu_type;
+
+cpu_type cpu = M340;
 
 /* Initialize the relax table */
 const relax_typeS md_relax_table[] =
@@ -586,6 +595,46 @@ parse_creg (s, reg)
   return s;
 }
 
+static char *
+parse_psrmod (s, reg)
+  char *     s;
+  unsigned * reg;
+{
+  int  i;
+  char buf[10];
+  static struct psrmods
+  {
+    char *       name;
+    unsigned int value;
+  }
+  psrmods[] =
+  {
+    { "ie", 1 },
+    { "fe", 2 },
+    { "ee", 4 },
+    { "af", 8 }        /* Really 0 and non-combinable.  */
+  };
+  
+  for (i = 0; i < 2; i++)
+    buf[i] = isascii (s[i]) ? tolower (s[i]) : 0;
+  
+  for (i = sizeof (psrmods) / sizeof (psrmods[0]); i--;)
+    {
+      if (! strncmp (psrmods[i].name, buf, 2))
+       {
+          * reg = psrmods[i].value;
+         
+          return s + 2;
+       }
+    }
+  
+  as_bad (_("bad/missing psr specifier"));
+  
+  * reg = 0;
+  
+  return s;
+}
+
 static char *
 parse_exp (s, e)
      char * s;
@@ -1032,6 +1081,13 @@ md_assemble (str)
       output = frag_more (2);
       break;
 
+    case MULSH:
+      if (cpu == M210)
+       {
+         as_bad (_("M340 specific opcode used when assembling for M210"));
+         break;
+       }
+      /* drop through... */
     case O2:
       op_end = parse_reg (op_end + 1, & reg);
       inst |= reg;
@@ -1601,6 +1657,35 @@ md_assemble (str)
       output = frag_more (2);
       break;
 
+    case OPSR:
+      if (cpu == M210)
+       {
+         as_bad (_("M340 specific opcode used when assembling for M210"));
+         break;
+       }
+      
+      op_end = parse_psrmod (op_end + 1, & reg);
+      
+      /* Look for further selectors.  */
+      while (* op_end == ',')
+       {
+         unsigned value;
+           
+         op_end = parse_psrmod (op_end + 1, & value);
+         
+         if (value & reg)
+           as_bad (_("duplicated psr bit specifier"));
+         
+         reg |= value;
+       }
+      
+      if (reg > 8)
+       as_bad (_("`af' must appear alone"));
+       
+      inst |= (reg & 0x7);
+      output = frag_more (2);
+      break;
     default:
       as_bad (_("unimplemented opcode \"%s\""), name);
     }
@@ -1690,6 +1775,16 @@ md_atof (type, litP, sizeP)
 
   *sizeP = prec * sizeof (LITTLENUM_TYPE);
   
+  if (! target_big_endian)
+    {
+      for (i = prec - 1; i >= 0; i--)
+       {
+         md_number_to_chars (litP, (valueT) words[i],
+                             sizeof (LITTLENUM_TYPE));
+         litP += sizeof (LITTLENUM_TYPE);
+       }
+    }
+  else
     for (i = 0; i < prec; i++)
       {
        md_number_to_chars (litP, (valueT) words[i],
@@ -1706,6 +1801,9 @@ CONST char * md_shortopts = "";
 #define OPTION_JSRI2BSR_OFF    (OPTION_MD_BASE + 1)
 #define OPTION_SIFILTER_ON     (OPTION_MD_BASE + 2)
 #define OPTION_SIFILTER_OFF    (OPTION_MD_BASE + 3)
+#define OPTION_CPU             (OPTION_MD_BASE + 4)
+#define OPTION_EB              (OPTION_MD_BASE + 5)
+#define OPTION_EL              (OPTION_MD_BASE + 6)
 
 struct option md_longopts[] =
 {
@@ -1713,6 +1811,9 @@ struct option md_longopts[] =
   { "jsri2bsr",    no_argument, NULL, OPTION_JSRI2BSR_ON},
   { "sifilter",    no_argument, NULL, OPTION_SIFILTER_ON},
   { "no-sifilter", no_argument, NULL, OPTION_SIFILTER_OFF},
+  { "cpu",         required_argument, NULL, OPTION_CPU},
+  { "EB",          no_argument, NULL, OPTION_EB},
+  { "EL",          no_argument, NULL, OPTION_EL},
   { NULL,          no_argument, NULL, 0}
 };
 
@@ -1728,7 +1829,20 @@ md_parse_option (c, arg)
 
   switch (c)
     {
+    case OPTION_CPU:
+      if (streq (arg, "210"))
+       {
+         cpu = M210;
+         target_big_endian = 1;
+       }
+      else if (streq (arg, "340"))
+       cpu = M340;
+      else
+        as_warn (_("unrecognised cpu type '%s'"), arg);
+      break;
       
+    case OPTION_EB: target_big_endian = 1; break;
+    case OPTION_EL: target_big_endian = 0; cpu = M340; break;
     case OPTION_JSRI2BSR_ON:  do_jsri2bsr = 1;   break;
     case OPTION_JSRI2BSR_OFF: do_jsri2bsr = 0;   break;
     case OPTION_SIFILTER_ON:  sifilter_mode = 1; break;
@@ -1746,7 +1860,10 @@ md_show_usage (stream)
   fprintf (stream, _("\
 MCORE specific options:\n\
   -{no-}jsri2bsr         {dis}able jsri to bsr transformation (def: dis)\n\
-  -{no-}sifilter         {dis}able silicon filter behavior (def: dis)"));
+  -{no-}sifilter         {dis}able silicon filter behavior (def: dis)\n\
+  -cpu=[210|340]          select CPU type\n\
+  -EB                     assemble for a big endian system (default)\n\
+  -EL                     assemble for a little endian system\n"));
 }
 \f
 int md_short_jump_size;
@@ -1800,6 +1917,16 @@ md_convert_frag (abfd, sec, fragP)
          as_bad (_("odd displacement at %x"), next_inst - 2);
        
        disp >>= 1;
+       
+       if (! target_big_endian)
+         {
+           t0 = buffer[1] & 0xF8;
+       
+           md_number_to_chars (buffer, disp, 2);
+       
+           buffer[1] = (buffer[1] & 0x07) | t0;
+         }
+       else
          {
            t0 = buffer[0] & 0xF8;
        
@@ -1829,6 +1956,9 @@ md_convert_frag (abfd, sec, fragP)
        int first_inst = fragP->fr_fix + fragP->fr_address;
        int needpad = (first_inst & 3);
 
+       if (! target_big_endian)
+         buffer[1] ^= 0x08;
+       else
          buffer[0] ^= 0x08;    /* Toggle T/F bit */
 
        buffer[2] = INST_BYTE0 (MCORE_INST_JMPI);       /* Build jmpi */
@@ -1836,6 +1966,12 @@ md_convert_frag (abfd, sec, fragP)
  
        if (needpad)
          {
+           if (! target_big_endian)
+             {
+               buffer[0] = 4;  /* branch over jmpi, pad, and ptr */
+               buffer[2] = 1;  /* jmpi offset of 1 gets the pointer */
+             }
+           else
              {
                buffer[1] = 4;  /* branch over jmpi, pad, and ptr */
                buffer[3] = 1;  /* jmpi offset of 1 gets the pointer */
@@ -1860,6 +1996,12 @@ md_convert_frag (abfd, sec, fragP)
               shrinking the fragment. '3' is the amount of code that
               we inserted here, but '4' is right for the space we reserved
               for this fragment. */
+           if (! target_big_endian)
+             {
+               buffer[0] = 3;  /* branch over jmpi, and ptr */
+               buffer[2] = 0;  /* jmpi offset of 0 gets the pointer */
+             }
+           else
              {
                buffer[1] = 3;  /* branch over jmpi, and ptr */
                buffer[3] = 0;  /* jmpi offset of 0 gets the pointer */
@@ -1880,6 +2022,9 @@ md_convert_frag (abfd, sec, fragP)
               the branch displacement so that it goes beyond the 
               full length of the fragment, not just what we actually
               filled in.  */
+           if (! target_big_endian)
+             buffer[0] = 4;    /* jmpi, ptr, and the 'tail pad' */
+           else
              buffer[1] = 4;    /* jmpi, ptr, and the 'tail pad' */
          }
        
@@ -1905,6 +2050,9 @@ md_convert_frag (abfd, sec, fragP)
 
        if (needpad)
          {
+           if (! target_big_endian)
+             buffer[0] = 1;    /* jmpi offset of 1 since padded */
+           else
              buffer[1] = 1;    /* jmpi offset of 1 since padded */
            buffer[2] = 0;      /* alignment */
            buffer[3] = 0;
@@ -1921,6 +2069,9 @@ md_convert_frag (abfd, sec, fragP)
          }
        else
          {
+           if (! target_big_endian)
+             buffer[0] = 0;    /* jmpi offset of 0 if no pad */
+           else
              buffer[1] = 0;    /* jmpi offset of 0 if no pad */
            buffer[2] = 0;      /* space for 32 bit address */
            buffer[3] = 0;
@@ -1988,8 +2139,16 @@ md_apply_fix3 (fixP, valp, segment)
        as_bad_where (file, fixP->fx_line,
                      _("pcrel for branch to %s too far (0x%x)"),
                      symname, val);
+      if (target_big_endian)
+       {
          buf[0] |= ((val >> 8) & 0x7);
          buf[1] |= (val & 0xff);
+       }
+      else
+       {
+         buf[0] |= ((val >> 8) & 0x7);
+         buf[1] |= (val & 0xff);
+       }
       break;
 
     case BFD_RELOC_MCORE_PCREL_IMM8BY4:        /* lower 8 bits of 2 byte opcode */
@@ -1999,6 +2158,8 @@ md_apply_fix3 (fixP, valp, segment)
        as_bad_where (file, fixP->fx_line,
                      _("pcrel for lrw/jmpi/jsri to %s too far (0x%x)"),
                      symname, val);
+      else if (! target_big_endian)
+       buf[0] |= (val & 0xff);
       else
        buf[1] |= (val & 0xff);
       break;
@@ -2008,6 +2169,9 @@ md_apply_fix3 (fixP, valp, segment)
        as_bad_where (file, fixP->fx_line,
                      _("pcrel for loopt too far (0x%x)"), val);
       val /= 2;
+      if (! target_big_endian)
+       buf[0] |= (val & 0xf);
+      else
        buf[1] |= (val & 0xf);
       break;
 
@@ -2144,6 +2308,16 @@ md_number_to_chars (ptr, use, nbytes)
      valueT use;
      int nbytes;
 {
+  if (! target_big_endian)
+    switch (nbytes)
+      {
+      case 4: ptr[3] = (use >> 24) & 0xff; /* fall through */
+      case 3: ptr[2] = (use >> 16) & 0xff; /* fall through */
+      case 2: ptr[1] = (use >>  8) & 0xff; /* fall through */
+      case 1: ptr[0] = (use >>  0) & 0xff;    break;
+      default: abort ();
+      }
+  else
     switch (nbytes)
       {
       case 4: *ptr++ = (use >> 24) & 0xff; /* fall through */
index eff1322ae09aa267a1436285c1177724b2bb4c12..b0a29abff0b578790ec94d1cfe061893c6a69fb6 100644 (file)
@@ -1,6 +1,6 @@
 /* This file is tc-mcore.h
 
-   Copyright (C) 1999 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -15,8 +15,8 @@
    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
+   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.  */
 
 #ifndef        TC_MCORE