CSKY: Refine literals pool dump process and float register parser.
authorCooper Qu <cooper.qu@linux.alibaba.com>
Wed, 2 Sep 2020 06:04:52 +0000 (14:04 +0800)
committerLifang Xia <lifang_xia@c-sky.com>
Wed, 2 Sep 2020 06:21:02 +0000 (14:21 +0800)
gas/
* config/tc-csky.c (struct literal): New member bignum.
(dump_literals): Handle big constant.
(enter_literal): Likewise.
(parse_type_freg): Handle vector register.

gas/ChangeLog
gas/config/tc-csky.c

index 24320b3523ec7ad91e2a05ede20895e19afb225a..0e2434f98624626cf31d9113963efb6f2da6ab9e 100644 (file)
@@ -1,3 +1,10 @@
+2020-09-02  Cooper Qu  <cooper.qu@linux.alibaba.com>
+
+       * config/tc-csky.c (struct literal): New member bignum.
+       (dump_literals): Handle big constant.
+       (enter_literal): Likewise.
+       (parse_type_freg): Handle vector register.
+
 2020-09-01  H.J. Lu  <hongjiu.lu@intel.com>
 
        * doc/as.texi: Document the .tls_common directive.
index 01f1d516600d90b3523c7c1a14adc1d183298eb3..f85c44ddb051c239c0be81e275e05a3c806795a9 100644 (file)
@@ -302,6 +302,7 @@ struct literal
   struct tls_addend tls_addend;
   unsigned char   isdouble;
   uint64_t dbnum;
+  LITTLENUM_TYPE bignum[SIZE_OF_LARGE_NUMBER + 6];
 };
 
 static void csky_idly (void);
@@ -1660,7 +1661,7 @@ dump_literals (int isforce)
 
   colon (S_GET_NAME (poolsym));
 
-  for (i = 0, p = litpool; i < poolsize; i += (p->isdouble ? 2 : 1), p++)
+  for (i = 0, p = litpool; i < poolsize; p++)
     {
       insn_reloc = p->r_type;
       if (insn_reloc == BFD_RELOC_CKCORE_TLS_IE32
@@ -1684,8 +1685,18 @@ dump_literals (int isforce)
              emit_expr (& p->e, 4);
            }
        }
+      else if (p->e.X_op == O_big)
+       {
+         memcpy (generic_bignum, p->bignum, sizeof (p->bignum));
+         emit_expr (& p->e, p->e.X_add_number * CHARS_PER_LITTLENUM);
+       }
       else
        emit_expr (& p->e, 4);
+
+      if (p->e.X_op == O_big)
+       i += ((p->e.X_add_number  * CHARS_PER_LITTLENUM) >> 2);
+      else
+       i += (p->isdouble ? 2 : 1);
     }
 
   if (isforce && IS_CSKY_ARCH_V2 (mach_flag))
@@ -1739,7 +1750,7 @@ enter_literal (expressionS *e,
     }
 
   /* Search pool for value so we don't have duplicates.  */
-  for (p = litpool, i = 0; i < poolsize; i += (p->isdouble ? 2 : 1), p++)
+  for (p = litpool,i = 0; i < poolsize; p++)
     {
       if (e->X_op == p->e.X_op
          && e->X_add_symbol == p->e.X_add_symbol
@@ -1751,11 +1762,21 @@ enter_literal (expressionS *e,
          && insn_reloc != BFD_RELOC_CKCORE_TLS_LDM32
          && insn_reloc != BFD_RELOC_CKCORE_TLS_LDO32
          && insn_reloc != BFD_RELOC_CKCORE_TLS_IE32
-         && insn_reloc != BFD_RELOC_CKCORE_TLS_LE32)
+         && insn_reloc != BFD_RELOC_CKCORE_TLS_LE32
+         && (e->X_op != O_big
+             || (memcmp (generic_bignum, p->bignum,
+                         p->e.X_add_number * sizeof (LITTLENUM_TYPE)) == 0)))
        {
          p->refcnt ++;
          return i;
        }
+      if (p->e.X_op == O_big)
+       {
+         i += (p->e.X_add_number >> 1);
+         i += (p->e.X_add_number & 0x1);
+    }
+      else
+       i += (p->isdouble ? 2 : 1);
     }
   p->refcnt = 1;
   p->ispcrel = ispcrel;
@@ -1764,6 +1785,8 @@ enter_literal (expressionS *e,
   p->isdouble = isdouble;
   if (isdouble)
     p->dbnum = dbnum;
+  if (e->X_op == O_big)
+    memcpy (p->bignum, generic_bignum, sizeof (p->bignum));
 
   if (insn_reloc == BFD_RELOC_CKCORE_TLS_GD32
       || insn_reloc == BFD_RELOC_CKCORE_TLS_LDM32
@@ -1773,7 +1796,12 @@ enter_literal (expressionS *e,
       p->tls_addend.offset = csky_insn.output - frag_now->fr_literal;
       literal_insn_offset = p;
     }
+  if (p->e.X_op == O_big) {
+    poolsize += (p->e.X_add_number >> 1);
+    poolsize += (p->e.X_add_number & 0x1);
+  } else
   poolsize += (p->isdouble ? 2 : 1);
+
   return i;
 }
 
@@ -2956,6 +2984,26 @@ parse_type_freg (char** oper, int even)
       SET_ERROR_STRING (ERROR_EXP_EVEN_FREG, NULL);
       return FALSE;
     }
+
+  if (IS_CSKY_V2 (mach_flag)
+      && (csky_insn.opcode->isa_flag32 & CSKY_ISA_VDSP_2)
+      && reg > 15)
+    {
+      if ((csky_insn.opcode->isa_flag32 & CSKY_ISA_VDSP_2))
+       {
+         SET_ERROR_INTEGER (ERROR_VREG_OVER_RANGE, reg);
+       }
+      else
+       {
+         SET_ERROR_INTEGER (ERROR_FREG_OVER_RANGE, reg);
+       }
+      return FALSE;
+    }
+  /* TODO: recognize vreg or freg.  */
+  if (reg > 31)
+    {
+      SET_ERROR_INTEGER (ERROR_VREG_OVER_RANGE, reg);
+    }
   csky_insn.val[csky_insn.idx++] = reg;
   return TRUE;
 }