This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] h8300 assembler


These are a couple of recent changes for h8300-elf-as:
2003-05-23  Michael Snyder  <msnyder@redhat.com>

	* config/tc-h8300.c (get_specific): Distinguish h8h from h8s ops.
	(build_bytes): Ditto.

2003-05-23  Richard Sandiford  <rsandifo@redhat.com>

	* config/tc-h8300.c (DMODE): Remove.
	(colonmod24): Don't choose a default if the operand is a 16-bit
	constant integer.
	(fix_operand_size): New function.
	(md_assemble): Use it to choose between @(d:2, ERn) and @(d:16,ERn).
	Adjust @(d:2,ERn) operands before choosing the specific opcodes.

Index: tc-h8300.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-h8300.c,v
retrieving revision 1.29
diff -p -r1.29 tc-h8300.c
*** tc-h8300.c	3 Jun 2003 21:29:08 -0000	1.29
--- tc-h8300.c	3 Jun 2003 22:54:29 -0000
*************** int Nmode;
*** 58,64 ****
  int SXmode;
  
  #define PSIZE (Hmode ? L_32 : L_16)
- #define DMODE (L_16)
  #define DSYMMODE (Hmode ? L_24 : L_16)
  
  int bsize = L_8;		/* Default branch displacement.  */
--- 58,63 ----
*************** struct h8_op
*** 320,325 ****
--- 319,325 ----
  };
  
  static void clever_message PARAMS ((const struct h8_instruction *, struct h8_op *));
+ static void fix_operand_size PARAMS ((struct h8_op *, int));
  static void build_bytes    PARAMS ((const struct h8_instruction *, struct h8_op *));
  static void do_a_fix_imm   PARAMS ((int, int, struct h8_op *, int));
  static void check_operand  PARAMS ((struct h8_op *, unsigned int, char *));
*************** colonmod24 (op, src)
*** 536,542 ****
  
    if (!mode)
      {
!       /* Choose a default mode.  */
        if (op->exp.X_add_number < -32768
  	  || op->exp.X_add_number > 32767)
  	{
--- 536,543 ----
  
    if (!mode)
      {
!       /* If the operand is a 16-bit constant integer, leave fix_operand_size
! 	 to calculate its size.  Otherwise choose a default here.  */
        if (op->exp.X_add_number < -32768
  	  || op->exp.X_add_number > 32767)
  	{
*************** colonmod24 (op, src)
*** 548,555 ****
        else if (op->exp.X_add_symbol
  	       || op->exp.X_op_symbol)
  	mode = DSYMMODE;
-       else
- 	mode = DMODE;
      }
  
    op->mode |= mode;
--- 549,554 ----
*************** get_specific (instruction, operands, siz
*** 1316,1321 ****
--- 1315,1321 ----
        if (found)
  	{
  	  if ((this_try->opcode->available == AV_H8SX && ! SXmode)
+ 	      || (this_try->opcode->available == AV_H8S && ! Smode)
  	      || (this_try->opcode->available == AV_H8H && ! Hmode))
  	    found = 0, found_other = this_try;
  	  else if (this_size != size && (this_size != SN && size != SN))
*************** build_bytes (this_try, operand)
*** 1524,1532 ****
    char *p = asnibbles;
    int high, low;
  
!   if (!(this_try->opcode->available == AV_H8 || Hmode))
      as_warn (_("Opcode `%s' with these operand types not available in H8/300 mode"),
  	     this_try->opcode->name);
  
    while (*nibble_ptr != (op_type) E)
      {
--- 1524,1543 ----
    char *p = asnibbles;
    int high, low;
  
!   if (!Hmode && this_try->opcode->available != AV_H8)
      as_warn (_("Opcode `%s' with these operand types not available in H8/300 mode"),
  	     this_try->opcode->name);
+   else if (!Smode 
+ 	   && this_try->opcode->available != AV_H8 
+ 	   && this_try->opcode->available != AV_H8H)
+     as_warn (_("Opcode `%s' with these operand types not available in H8/300H mode"),
+ 	     this_try->opcode->name);
+   else if (!SXmode 
+ 	   && this_try->opcode->available != AV_H8
+ 	   && this_try->opcode->available != AV_H8H
+ 	   && this_try->opcode->available != AV_H8S)
+     as_warn (_("Opcode `%s' with these operand types not available in H8/300S mode"),
+ 	     this_try->opcode->name);
  
    while (*nibble_ptr != (op_type) E)
      {
*************** clever_message (instruction, operand)
*** 1857,1862 ****
--- 1868,1923 ----
    as_bad (_("invalid operands"));
  }
  
+ 
+ /* Adjust OPERAND's value and size given that it is accessing a field
+    of SIZE bytes.
+ 
+    This function handles the choice between @(d:2,ERn) and @(d:16,ERn)
+    when no size is explicitly given.  It also scales down the assembly-level
+    displacement in an @(d:2,ERn) operand.  */
+ 
+ static void
+ fix_operand_size (operand, size)
+      struct h8_op *operand;
+      int size;
+ {
+   if ((operand->mode & MODE) == DISP)
+     {
+       /* If the user didn't specify an operand width, see if we
+ 	 can use @(d:2,ERn).  */
+       if (SXmode
+ 	  && (operand->mode & SIZE) == 0
+ 	  && (operand->exp.X_add_number == size
+ 	      || operand->exp.X_add_number == size * 2
+ 	      || operand->exp.X_add_number == size * 3))
+ 	operand->mode |= L_2;
+ 
+       /* Scale down the displacement in an @(d:2,ERn) operand.
+ 	 X_add_number then contains the desired field value.  */
+       if ((operand->mode & SIZE) == L_2)
+ 	{
+ 	  if (operand->exp.X_add_number % size != 0)
+ 	    as_warn (_("operand/size mis-match"));
+ 	  operand->exp.X_add_number /= size;
+ 	}
+     }
+ 
+   /* If the operand needs a size but doesn't have one yet, it must be
+      a 16-bit integer (see colonmod24).  */
+   if ((operand->mode & SIZE) == 0)
+     switch (operand->mode & MODE)
+       {
+       case DISP:
+       case INDEXB:
+       case INDEXW:
+       case INDEXL:
+       case ABS:
+ 	operand->mode |= L_16;
+ 	break;
+       }
+ }
+ 
+ 
  /* This is the guts of the machine-dependent assembler.  STR points to
     a machine dependent instruction.  This function is supposed to emit
     the frags/bytes it assembles.  */
*************** md_assemble (str)
*** 1948,2014 ****
  	  break;
  	}
      }
-   instruction = get_specific (instruction, operand, size);
- 
-   if (instruction == 0)
-     {
-       /* Couldn't find an opcode which matched the operands.  */
-       char *where = frag_more (2);
- 
-       where[0] = 0x0;
-       where[1] = 0x0;
-       clever_message (prev_instruction, operand);
- 
-       return;
-     }
- 
-   /* This is the earliest point at which we can do this:
-      any DISP2 operands need to be fixed-up according to 
-      the size of the operation.  */
-   /* MOVA is a whole different set of rules...  */
    if (OP_KIND (instruction->opcode->how) == O_MOVAB ||
        OP_KIND (instruction->opcode->how) == O_MOVAW ||
        OP_KIND (instruction->opcode->how) == O_MOVAL)
      {
!       if ((operand[1].mode & MODE) == DISP &&
! 	  (operand[1].mode & SIZE) == L_2)
! 	switch (operand[0].mode & MODE) {
  	case INDEXB:
  	default:
  	  break;
  	case INDEXW:
! 	  if (operand[1].exp.X_add_number % 2)
! 	    as_warn (_("operand/size mis-match"));
! 	  operand[1].exp.X_add_number /= 2;
  	  break;
  	case INDEXL:
! 	  if (operand[1].exp.X_add_number % 4)
! 	    as_warn (_("operand/size mis-match"));
! 	  operand[1].exp.X_add_number /= 4;
  	  break;
  	}
      }
    else
      {
!       for (i = 0; i < instruction->noperands; i++)
! 	if ((operand[i].mode & MODE) == DISP &&
! 	    (operand[i].mode & SIZE) == L_2)
! 	  switch (size) {
  	  case SN:
  	  case SB:
  	  default:
  	    break;
  	  case SW:
! 	    if (operand[i].exp.X_add_number % 2)
! 	      as_warn (_("operand/size mis-match"));
! 	    operand[i].exp.X_add_number /= 2;
  	    break;
  	  case SL:
! 	    if (operand[i].exp.X_add_number % 4)
! 	      as_warn (_("operand/size mis-match"));
! 	    operand[i].exp.X_add_number /= 4;
  	    break;
  	  }
      }
  
    build_bytes (instruction, operand);
--- 2009,2063 ----
  	  break;
  	}
      }
    if (OP_KIND (instruction->opcode->how) == O_MOVAB ||
        OP_KIND (instruction->opcode->how) == O_MOVAW ||
        OP_KIND (instruction->opcode->how) == O_MOVAL)
      {
!       switch (operand[0].mode & MODE)
! 	{
  	case INDEXB:
  	default:
+ 	  fix_operand_size (&operand[1], 1);
  	  break;
  	case INDEXW:
! 	  fix_operand_size (&operand[1], 2);
  	  break;
  	case INDEXL:
! 	  fix_operand_size (&operand[1], 4);
  	  break;
  	}
      }
    else
      {
!       for (i = 0; i < 3 && operand[i].mode != 0; i++)
! 	switch (size)
! 	  {
  	  case SN:
  	  case SB:
  	  default:
+ 	    fix_operand_size (&operand[i], 1);
  	    break;
  	  case SW:
! 	    fix_operand_size (&operand[i], 2);
  	    break;
  	  case SL:
! 	    fix_operand_size (&operand[i], 4);
  	    break;
  	  }
+     }
+ 
+   instruction = get_specific (instruction, operand, size);
+ 
+   if (instruction == 0)
+     {
+       /* Couldn't find an opcode which matched the operands.  */
+       char *where = frag_more (2);
+ 
+       where[0] = 0x0;
+       where[1] = 0x0;
+       clever_message (prev_instruction, operand);
+ 
+       return;
      }
  
    build_bytes (instruction, operand);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]