[Patch][binutils][arm] Armv8.6-A Matrix Multiply extension [9/10]
[deliverable/binutils-gdb.git] / gas / config / tc-pru.c
index 5bfd67632a8609e57116ab7bc56efe16315b86d9..2e2058c1debb81adf60dd9ddba744caee1d4577e 100644 (file)
@@ -1,5 +1,5 @@
 /* TI PRU assembler.
-   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   Copyright (C) 2014-2019 Free Software Foundation, Inc.
    Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
    Based on tc-nios2.c
 
@@ -148,7 +148,7 @@ static segT pru_current_align_seg;
 static int pru_auto_align_on = 1;
 
 /* The last seen label in the current section.  This is used to auto-align
-   labels preceeding instructions.  */
+   labels preceding instructions.  */
 static symbolS *pru_last_label;
 
 \f
@@ -296,9 +296,10 @@ typedef enum
 static PRU_MODE pru_mode = PRU_MODE_ASSEMBLE;
 
 /* This function is used to in self-checking mode
-   to check the assembled instruction
-   opcode should be the assembled opcode, and exp_opcode
+   to check the assembled instruction.
+   OPCODE should be the assembled opcode, and exp_opcode
    the parsed string representing the expected opcode.  */
+
 static void
 pru_check_assembly (unsigned int opcode, const char *exp_opcode)
 {
@@ -813,8 +814,11 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
              /* As the only 64-bit "insn", LDI32 needs special handling. */
              uint32_t insn1 = insn & 0xffffffff;
              uint32_t insn2 = insn >> 32;
-             SET_INSN_FIELD (IMM16, insn1, fixup & 0xffff);
-             SET_INSN_FIELD (IMM16, insn2, fixup >> 16);
+             SET_INSN_FIELD (IMM16, insn1, fixup >> 16);
+             SET_INSN_FIELD (IMM16, insn2, fixup & 0xffff);
+
+             SET_INSN_FIELD (RDSEL, insn1, RSEL_31_16);
+             SET_INSN_FIELD (RDSEL, insn2, RSEL_15_0);
 
              md_number_to_chars (buf, insn1, 4);
              md_number_to_chars (buf + 4, insn2, 4);
@@ -1085,6 +1089,8 @@ pru_assemble_arg_b (pru_insn_infoS *insn_info, const char *argstr)
   if (src2 == NULL)
     {
       unsigned long imm8 = pru_assemble_noreloc_expression (argstr);
+      if (imm8 >= 0x100)
+       as_bad (_("value %lu is too large for a byte operand"), imm8);
       SET_INSN_FIELD (IMM8, insn_info->insn_code, imm8);
       SET_INSN_FIELD (IO, insn_info->insn_code, 1);
     }
@@ -1140,7 +1146,8 @@ pru_assemble_arg_i (pru_insn_infoS *insn_info, const char *argstr)
 
   /* QUIRK: LDI must clear IO bit high, even though it has immediate arg. */
   SET_INSN_FIELD (IO, insn_info->insn_code, 0);
-  SET_INSN_FIELD (IMM16, insn_info->insn_code, imm32 & 0xffff);
+  SET_INSN_FIELD (RDSEL, insn_info->insn_code, RSEL_31_16);
+  SET_INSN_FIELD (IMM16, insn_info->insn_code, imm32 >> 16);
   insn_info->ldi32_imm32 = imm32;
 }
 
@@ -1474,11 +1481,13 @@ output_insn_ldi32 (pru_insn_infoS *insn)
   unsigned long insn2;
 
   f = frag_more (8);
+  SET_INSN_FIELD (IMM16, insn->insn_code, insn->ldi32_imm32 >> 16);
+  SET_INSN_FIELD (RDSEL, insn->insn_code, RSEL_31_16);
   md_number_to_chars (f, insn->insn_code, 4);
 
   insn2 = insn->insn_code;
-  SET_INSN_FIELD (IMM16, insn2, insn->ldi32_imm32 >> 16);
-  SET_INSN_FIELD (RDSEL, insn2, RSEL_31_16);
+  SET_INSN_FIELD (IMM16, insn2, insn->ldi32_imm32 & 0xffff);
+  SET_INSN_FIELD (RDSEL, insn2, RSEL_15_0);
   md_number_to_chars (f + 4, insn2, 4);
 
   /* Emit debug info.  */
@@ -1698,6 +1707,8 @@ md_assemble (char *op_str)
 
            case 'E':
              pru_check_assembly (insn->insn_code, *argtk++);
+             continue;
+
            default:
              BAD_CASE (*argp);
            }
@@ -1734,7 +1745,7 @@ md_assemble (char *op_str)
 valueT
 md_section_align (asection *seg, valueT addr)
 {
-  int align = bfd_get_section_alignment (stdoutput, seg);
+  int align = bfd_section_alignment (seg);
   return ((addr + (1 << align) - 1) & (-((valueT) 1 << align)));
 }
 
@@ -1909,14 +1920,28 @@ pru_cons_fix_new (fragS *frag, int where, unsigned int nbytes,
 }
 
 /* Implement tc_regname_to_dw2regnum, to convert REGNAME to a DWARF-2
-   register number.  */
+   register number.  Return the starting HW byte-register number.  */
+
 int
 pru_regname_to_dw2regnum (char *regname)
 {
+  static const unsigned int regstart[RSEL_NUM_ITEMS] =
+    {
+     [RSEL_7_0]          = 0,
+     [RSEL_15_8]  = 1,
+     [RSEL_23_16] = 2,
+     [RSEL_31_24] = 3,
+     [RSEL_15_0]  = 0,
+     [RSEL_23_8]  = 1,
+     [RSEL_31_16] = 2,
+     [RSEL_31_0]  = 0,
+    };
+
   struct pru_reg *r = pru_reg_lookup (regname);
-  if (r == NULL)
+
+  if (r == NULL || r->regsel >= RSEL_NUM_ITEMS)
     return -1;
-  return r->index;
+  return r->index * 4 + regstart[r->regsel];
 }
 
 /* Implement tc_cfi_frame_initial_instructions, to initialize the DWARF-2
@@ -1924,7 +1949,7 @@ pru_regname_to_dw2regnum (char *regname)
 void
 pru_frame_initial_instructions (void)
 {
-  const unsigned fp_regno = 4;
+  const unsigned fp_regno = 4 * 4;
   cfi_add_CFA_def_cfa (fp_regno, 0);
 }
 
This page took 0.025732 seconds and 4 git commands to generate.