Implement Intel SMAP instructions
[deliverable/binutils-gdb.git] / gas / config / tc-rl78.c
index fe0f97724f5ba9185db36428c7355627bb447d64..bd964dc163003d9222a04c0499230ac3eee68d45 100644 (file)
@@ -38,7 +38,9 @@ const char comment_chars[]        = ";";
    first line of the input file.  This is because the compiler outputs
    #NO_APP at the beginning of its output.  */
 const char line_comment_chars[]   = "#";
-const char line_separator_chars[] = "|";
+/* Use something that isn't going to be needed by any expressions or
+   other syntax.  */
+const char line_separator_chars[] = "@";
 
 const char EXP_CHARS[]            = "eE";
 const char FLT_CHARS[]            = "dD";
@@ -81,6 +83,18 @@ typedef struct rl78_bytesT
 
 static rl78_bytesT rl78_bytes;
 
+void
+rl78_linkrelax_addr16 (void)
+{
+  rl78_bytes.link_relax |= RL78_RELAXA_ADDR16;
+}
+
+void
+rl78_linkrelax_branch (void)
+{
+  rl78_bytes.link_relax |= RL78_RELAXA_BRA;
+}
+
 static void
 rl78_fixup (expressionS exp, int offsetbits, int nbits, int type)
 {
@@ -240,19 +254,32 @@ rl78_field (int val, int pos, int sz)
 
 /*------------------------------------------------------------------*/
 
+enum options
+{
+  OPTION_RELAX = OPTION_MD_BASE,
+};
+
 #define RL78_SHORTOPTS ""
 const char * md_shortopts = RL78_SHORTOPTS;
 
 /* Assembler options.  */
 struct option md_longopts[] =
 {
+  {"relax", no_argument, NULL, OPTION_RELAX},
   {NULL, no_argument, NULL, 0}
 };
 size_t md_longopts_size = sizeof (md_longopts);
 
 int
-md_parse_option (int c ATTRIBUTE_UNUSED, char * arg ATTRIBUTE_UNUSED)
+md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
 {
+  switch (c)
+    {
+    case OPTION_RELAX:
+      linkrelax = 1;
+      return 1;
+
+    }
   return 0;
 }
 
@@ -348,7 +375,37 @@ md_operand (expressionS * exp ATTRIBUTE_UNUSED)
 void
 rl78_frag_init (fragS * fragP)
 {
-  fragP->tc_frag_data = 0;
+  if (rl78_bytes.n_relax || rl78_bytes.link_relax)
+    {
+      fragP->tc_frag_data = malloc (sizeof (rl78_bytesT));
+      memcpy (fragP->tc_frag_data, & rl78_bytes, sizeof (rl78_bytesT));
+    }
+  else
+    fragP->tc_frag_data = 0;
+}
+
+/* When relaxing, we need to output a reloc for any .align directive
+   so that we can retain this alignment as we adjust opcode sizes.  */
+void
+rl78_handle_align (fragS * frag)
+{
+  if (linkrelax
+      && (frag->fr_type == rs_align
+         || frag->fr_type == rs_align_code)
+      && frag->fr_address + frag->fr_fix > 0
+      && frag->fr_offset > 0
+      && now_seg != bss_section)
+    {
+      fix_new (frag, frag->fr_fix, 0,
+              &abs_symbol, RL78_RELAXA_ALIGN + frag->fr_offset,
+              0, BFD_RELOC_RL78_RELAX);
+      /* For the purposes of relaxation, this relocation is attached
+        to the byte *after* the alignment - i.e. the byte that must
+        remain aligned.  */
+      fix_new (frag->fr_next, 0, 0,
+              &abs_symbol, RL78_RELAXA_ELIGN + frag->fr_offset,
+              0, BFD_RELOC_RL78_RELAX);
+    }
 }
 
 char *
@@ -391,13 +448,50 @@ md_assemble (char * str)
 
   rl78_parse ();
 
-  bytes = frag_more (rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops);
-  frag_then = frag_now;
+  /* This simplifies the relaxation code.  */
+  if (rl78_bytes.link_relax)
+    {
+      int olen = rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops;
+      /* We do it this way because we want the frag to have the
+        rl78_bytes in it, which we initialize above.  */
+      bytes = frag_more (olen);
+      frag_then = frag_now;
+      frag_variant (rs_machine_dependent,
+                   olen /* max_chars */,
+                   0 /* var */,
+                   olen /* subtype */,
+                   0 /* symbol */,
+                   0 /* offset */,
+                   0 /* opcode */);
+      frag_then->fr_opcode = bytes;
+      frag_then->fr_fix = olen + (bytes - frag_then->fr_literal);
+      frag_then->fr_subtype = olen;
+      frag_then->fr_var = 0;
+    }
+  else
+    {
+      bytes = frag_more (rl78_bytes.n_prefix + rl78_bytes.n_base + rl78_bytes.n_ops);
+      frag_then = frag_now;
+    }
 
   APPEND (prefix, n_prefix);
   APPEND (base, n_base);
   APPEND (ops, n_ops);
 
+  if (rl78_bytes.link_relax)
+    {
+      fixS * f;
+
+      f = fix_new (frag_then,
+                  (char *) bytes - frag_then->fr_literal,
+                  0,
+                  abs_section_sym,
+                  rl78_bytes.link_relax | rl78_bytes.n_fixups,
+                  0,
+                  BFD_RELOC_RL78_RELAX);
+      frag_then->tc_frag_data->link_relax_fixP = f;
+    }
+
   for (i = 0; i < rl78_bytes.n_fixups; i ++)
     {
       /* index: [nbytes][type] */
@@ -460,6 +554,23 @@ rl78_cons_fix_new (fragS * frag,
       return;
     }
 
+  switch (exp->X_md)
+    {
+    case BFD_RELOC_RL78_LO16:
+    case BFD_RELOC_RL78_HI16:
+      if (size != 2)
+       as_bad (_("%%hi16/%%lo16 only applies to .short or .hword"));
+      type = exp->X_md;
+      break;
+    case BFD_RELOC_RL78_HI8:
+      if (size != 1)
+       as_bad (_("%%hi8 only applies to .byte"));
+      type = exp->X_md;
+      break;
+    default:
+      break;
+    }
+
   if (exp->X_op == O_subtract && exp->X_op_symbol)
     {
       if (size != 4 && size != 2 && size != 1)
@@ -477,6 +588,7 @@ md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTR
 {
   return 0;
 }
+
 arelent **
 tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
 {
@@ -648,6 +760,10 @@ md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
     case BFD_RELOC_NONE:
       break;
 
+    case BFD_RELOC_RL78_RELAX:
+      f->fx_done = 1;
+      break;
+
     case BFD_RELOC_8:
     case BFD_RELOC_8_PCREL:
       op[0] = val;
@@ -696,4 +812,5 @@ md_convert_frag (bfd *   abfd ATTRIBUTE_UNUSED,
                 fragS * fragP ATTRIBUTE_UNUSED)
 {
   /* No relaxation yet */
+  fragP->fr_var = 0;
 }
This page took 0.030732 seconds and 4 git commands to generate.