]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/binutils-tumbl.git/blobdiff - gas/config/tc-microblaze.c
MBTumbl: Implement support for conditional execution
[fpga/lx-cpu1/binutils-tumbl.git] / gas / config / tc-microblaze.c
index 80bfebb0d3d64e22a8a44f2d92677d2c63ef7dd5..560215f936a47d3298efae550c1c4c2b055312d3 100644 (file)
@@ -104,6 +104,11 @@ static segT sdata_segment = 0;     /* Small data section.  */
 static segT sdata2_segment = 0; /* Small read-only section.  */
 static segT rodata_segment = 0; /* read-only section.  */
 
+/* Previous instruction (for pseudo instructions) */
+static char * last_output;
+static int last_inst;
+static int last_pseudo;
+
 /* Generate a symbol for stabs information.  */
 
 void
@@ -562,6 +567,53 @@ parse_reg (char * s, unsigned * reg)
   return s;
 }
 
+/* Try to parse a cond name.  */
+
+static char *
+parse_cond (char * s, unsigned * cond)
+{
+  /* Strip leading whitespace.  */
+  while (ISSPACE (* s))
+    ++ s;
+
+  if (strncasecmp (s, "eq", 2) == 0)
+    {
+      *cond = COND_EQ;
+      return s + 2;
+    }
+  else if (strncasecmp (s, "ne", 2) == 0)
+    {
+      *cond = COND_NE;
+      return s + 2;
+    }
+  else if (strncasecmp (s, "lt", 2) == 0)
+    {
+      *cond = COND_LT;
+      return s + 2;
+    }
+  else if (strncasecmp (s, "le", 2) == 0)
+    {
+      *cond = COND_LE;
+      return s + 2;
+    }
+  else if (strncasecmp (s, "gt", 2) == 0)
+    {
+      *cond = COND_GT;
+      return s + 2;
+    }
+  else if (strncasecmp (s, "ge", 2) == 0)
+    {
+      *cond = COND_GE;
+      return s + 2;
+    }
+  else 
+    {
+      as_bad (_("condition expected, but saw '%.6s'"), s);
+      *cond = 0;
+      return s;
+    }
+}
+
 static char *
 parse_exp (char *s, expressionS *e)
 {
@@ -796,6 +848,7 @@ md_assemble (char * str)
   struct op_code_struct * opcode, *opcode1;
   char * output = NULL;
   int nlen = 0;
+  int pseudo = 0;
   int i;
   unsigned long inst, inst1;
   unsigned reg1;
@@ -1250,6 +1303,45 @@ md_assemble (char * str)
       inst |= (reg1 << RD_LOW) & RD_MASK;
       output = frag_more (isize);
       break;
+#else
+
+    case INST_TYPE_COND:
+      if (strcmp (op_end, ""))
+        op_end = parse_cond (op_end + 1, &reg1);  /* Get cond.  */
+      else
+      {
+        as_fatal (_("Error in statement syntax"));
+        reg1 = 0;
+      }
+
+      if (last_pseudo != 0 || last_output == NULL)
+      {
+        as_fatal (_("IT, ITT, ITE pseudo instructions must follow CMP or CMPU isntructions"));
+        return;
+      }
+
+      opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "cmp");
+      if ((opcode1 == NULL) || ((last_inst & opcode1->opcode_mask) != opcode1->bit_sequence))
+      {
+        opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "cmpu");
+        if ((opcode1 == NULL) || ((last_inst & opcode1->opcode_mask) != opcode1->bit_sequence))
+        {
+          as_fatal (_("IT, ITT, ITE pseudo instructions must follow CMP or CMPU isntructions"));
+          return;
+        }
+      }
+
+      /* Modify last instruction */
+      last_inst |= (reg1 << COND_LOW) & COND_MASK;
+      last_inst |= opcode->bit_sequence;
+      last_output[0] = INST_BYTE0 (last_inst);
+      last_output[1] = INST_BYTE1 (last_inst);
+      last_output[2] = INST_BYTE2 (last_inst);
+      last_output[3] = INST_BYTE3 (last_inst);
+
+      /* Only one pseudo instruction follows */
+      pseudo = 1;
+      break;
 #endif
 
     case INST_TYPE_RD_SPECIAL:
@@ -1643,10 +1735,17 @@ md_assemble (char * str)
   if (strcmp (op_end, opcode->name) && strcmp (op_end, ""))
     as_warn (_("ignoring operands: %s "), op_end);
 
-  output[0] = INST_BYTE0 (inst);
-  output[1] = INST_BYTE1 (inst);
-  output[2] = INST_BYTE2 (inst);
-  output[3] = INST_BYTE3 (inst);
+  if (!pseudo)
+  {
+    output[0] = INST_BYTE0 (inst);
+    output[1] = INST_BYTE1 (inst);
+    output[2] = INST_BYTE2 (inst);
+    output[3] = INST_BYTE3 (inst);
+
+    last_output = output;
+    last_inst = inst;
+  }
+  last_pseudo = pseudo;
 
 #ifdef OBJ_ELF
   dwarf2_emit_insn (4);