This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


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

Named asm operands patch (resubmit)


About a month ago I submitted some patches for having asm operands
with symbolic names.  From the documentation of the new feature:

---------------- snip ----------------
   As of GCC version 3.1, it is also possible to specify input and
output operands using symbolic names which can be referenced within the
assembler code.  These names are specified inside square brackets
preceding the constraint string, and can be referenced inside the
assembler code using `%[NAME]' instead of a percentage sign followed by
the operand number.  Using named operands the above example could look
like:

     asm ("fsinx %[angle],%[output]"
          : [output] "=f" (result)
          : [angle] "f" (angle));

Note that the symbolic operand names have no relation whatsoever to C
expressions.  You may use any name you like, even those of existing C
symbols, but must ensure that no two operands within the same assembler
construct use the same symbolic name.
---------------- snip ----------------

I'm resubmitting the patches now which applies to the current CVS.
There's also some additions to the RTL documentation and a new
c-compile test.  (I'm a bit confused about the naming convention in
the testsuite, so I just named the file `named-asmop.c'.)

The patch bootstraps on i386-unknown-freebsd4.2 and passes `make dvi'.

	eSk



2001-06-12  Espen Skoglund  <esk@ira.uka.de>

	* gcc.c-torture/compile/named-asmop.c: New.

---------------- snip ----------------
f ()
{
  int v;
  asm ("/* %0 %1 %2 %[in] %[out] */"
       : [out] "=r" (v)
       : [in] "i" (1), "i" (2));
}
---------------- snip ----------------

2001-06-12  Espen Skoglund  <esk@ira.uka.de>

	* genconfig.c (main): Increased max_recog_operands.
	* rtl.def: Added new operands output-operand-name and
	opname-vector to ASM_OPERANDS.
	* rtl.h: Added arg to decode_asm_operands().
	(ASM_OPERANDS_OUTPUT_NAME): New macro.
	(ASM_OPERANDS_INPUT_NAME_VEC): New macro.
	(ASM_OPERANDS_INPUT_NAME_EXP): New macro.
	(ASM_OPERANDS_INPUT_NAME): New macro.
	(ASM_OPERANDS_*): Modified field indexes.
 	* c-parse.in: Added possibility of prepending asm constraint with
	operanad name.
	* cp/parse.y: Ditto.
	* stmt.c (expand_asm_operands): Handle named asm operands.
	* final.c: Added variable `operand_names'.
	(asm_insn_count): Add arg to decode_asm_entry().
	(output_asm_insn): Handle named operands in asm input.
	* recog.h (struct recog_data): Added opnames array.
	* recog.c (decode_asm_operands): Put operands names into new
	argument OPNAMES if OPNAMES is nonzero.
	(extract_insn): Extraxct operand names into recog_data.
	* reload1.c (maybe_fix_stack_asms): Added arg to
	decode_asm_operands().
	* config/sh/sh.c (sh_insn_length_adjustment): Ditto.
	* cse.c (canon_hash): Take operand names into account when
	generating hashes.
	(exp_equiv_p): Take operand names into account when comparing asm
	insns.
	* gcse.c (hash_expr_1): Take operand names into account when
	generating hashes.
	(expr_equiv_p): Take operand names into account when comparing asm
	insns.
	* integrate.c (copy_rtx_and_substitute): Copy output_name and
	input_name_vec when copying asm insn.
	* integrate.h (struct inline_remap): Added
	`copy_asm_opnames_vector'.
	* emit-rtl.c: New variables {orig,copy}_asm_opnames_vector.
	(copy_insn): Zero out *_asm_opnames_vector before copying insn.
	(copy_insn_1): Make copy of operand names vector.
	* doc/extend.texi (Extended Asm): Added documentation for named
	assembler operands.
	* doc/rtl.texi (Assembler): Added documentation on asm_operands
	RTX extensions.

Index: c-parse.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parse.in,v
retrieving revision 1.94
diff -u -c -3 -p -r1.94 c-parse.in
*** c-parse.in	2001/06/10 13:47:54	1.94
--- c-parse.in	2001/06/12 13:48:12
*************** end ifc
*** 187,192 ****
--- 187,193 ----
  %type <ttype> initdecls notype_initdecls initdcl notype_initdcl
  %type <ttype> init maybeasm
  %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
+ %type <ttype> maybe_asm_operand_name
  %type <ttype> maybe_attribute attributes attribute attribute_list attrib
  %type <ttype> maybe_setattrs
  %type <ttype> any_word extension
*************** nonnull_asm_operands:
*** 2492,2499 ****
  	;
  
  asm_operand:
! 	  STRING '(' expr ')'
! 		{ $$ = build_tree_list ($1, $3); }
  	;
  
  asm_clobbers:
--- 2493,2500 ----
  	;
  
  asm_operand:
! 	  maybe_asm_operand_name STRING '(' expr ')'
! 		{ $$ = build_tree_list (build_tree_list ($1, $2), $4); }
  	;
  
  asm_clobbers:
*************** asm_clobbers:
*** 2502,2507 ****
--- 2503,2515 ----
  	| asm_clobbers ',' string
  		{ $$ = tree_cons (NULL_TREE, combine_strings ($3), $1); }
  	;
+ 
+ maybe_asm_operand_name: /* empty */
+ 		{ $$ = NULL_TREE; }
+ 	| '[' any_word ']'
+ 		{ $$ = $2; }
+ 	;
+ 
  
  /* This is what appears inside the parens in a function declarator.
     Its value is a list of ..._TYPE nodes.  Attributes must appear here
Index: cse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.186
diff -u -c -3 -p -r1.186 cse.c
*** cse.c	2001/05/17 18:46:57	1.186
--- cse.c	2001/06/12 13:48:58
*************** canon_hash (x, mode)
*** 2404,2409 ****
--- 2404,2410 ----
  	  hash += (unsigned) code + (unsigned) GET_MODE (x)
  	    + canon_hash_string (ASM_OPERANDS_TEMPLATE (x))
  	    + canon_hash_string (ASM_OPERANDS_OUTPUT_CONSTRAINT (x))
+ 	    + canon_hash_string (ASM_OPERANDS_OUTPUT_NAME (x))
  	    + (unsigned) ASM_OPERANDS_OUTPUT_IDX (x);
  
  	  if (ASM_OPERANDS_INPUT_LENGTH (x))
*************** canon_hash (x, mode)
*** 2413,2418 ****
--- 2414,2421 ----
  		  hash += (canon_hash (ASM_OPERANDS_INPUT (x, i),
  				       GET_MODE (ASM_OPERANDS_INPUT (x, i)))
  			   + canon_hash_string (ASM_OPERANDS_INPUT_CONSTRAINT
+ 						(x, i))
+ 			   + canon_hash_string (ASM_OPERANDS_INPUT_NAME
  						(x, i)));
  		}
  
*************** exp_equiv_p (x, y, validate, equal_value
*** 2619,2624 ****
--- 2622,2629 ----
  	  || strcmp (ASM_OPERANDS_TEMPLATE (x), ASM_OPERANDS_TEMPLATE (y))
  	  || strcmp (ASM_OPERANDS_OUTPUT_CONSTRAINT (x),
  		     ASM_OPERANDS_OUTPUT_CONSTRAINT (y))
+ 	  || strcmp (ASM_OPERANDS_OUTPUT_NAME (x),
+ 		     ASM_OPERANDS_OUTPUT_NAME (y))
  	  || ASM_OPERANDS_OUTPUT_IDX (x) != ASM_OPERANDS_OUTPUT_IDX (y)
  	  || ASM_OPERANDS_INPUT_LENGTH (x) != ASM_OPERANDS_INPUT_LENGTH (y))
  	return 0;
*************** exp_equiv_p (x, y, validate, equal_value
*** 2630,2636 ****
  			       ASM_OPERANDS_INPUT (y, i),
  			       validate, equal_values)
  		|| strcmp (ASM_OPERANDS_INPUT_CONSTRAINT (x, i),
! 			   ASM_OPERANDS_INPUT_CONSTRAINT (y, i)))
  	      return 0;
  	}
  
--- 2635,2643 ----
  			       ASM_OPERANDS_INPUT (y, i),
  			       validate, equal_values)
  		|| strcmp (ASM_OPERANDS_INPUT_CONSTRAINT (x, i),
! 			   ASM_OPERANDS_INPUT_CONSTRAINT (y, i))
! 		|| strcmp (ASM_OPERANDS_INPUT_NAME (x, i),
! 			   ASM_OPERANDS_INPUT_NAME (y, i)))
  	      return 0;
  	}
  
Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.181
diff -u -c -3 -p -r1.181 emit-rtl.c
*** emit-rtl.c	2001/06/10 22:49:40	1.181
--- emit-rtl.c	2001/06/12 13:49:05
*************** static rtvec copy_asm_operands_vector;
*** 3779,3784 ****
--- 3779,3788 ----
  static rtvec orig_asm_constraints_vector;
  static rtvec copy_asm_constraints_vector;
  
+ /* Likewise for the operand names vector.  */
+ static rtvec orig_asm_opnames_vector;
+ static rtvec copy_asm_opnames_vector;
+ 
  /* Recursively create a new copy of an rtx for copy_insn.
     This function differs from copy_rtx in that it handles SCRATCHes and
     ASM_OPERANDs properly.
*************** copy_insn_1 (orig)
*** 3869,3875 ****
  
  	case 'E':
  	case 'V':
! 	  if (XVEC (orig, i) == orig_asm_constraints_vector)
  	    XVEC (copy, i) = copy_asm_constraints_vector;
  	  else if (XVEC (orig, i) == orig_asm_operands_vector)
  	    XVEC (copy, i) = copy_asm_operands_vector;
--- 3873,3881 ----
  
  	case 'E':
  	case 'V':
! 	  if (XVEC (orig, i) == orig_asm_opnames_vector)
! 	    XVEC (copy, i) = copy_asm_opnames_vector;
! 	  else if (XVEC (orig, i) == orig_asm_constraints_vector)
  	    XVEC (copy, i) = copy_asm_constraints_vector;
  	  else if (XVEC (orig, i) == orig_asm_operands_vector)
  	    XVEC (copy, i) = copy_asm_operands_vector;
*************** copy_insn_1 (orig)
*** 3910,3915 ****
--- 3916,3923 ----
        copy_asm_operands_vector = ASM_OPERANDS_INPUT_VEC (copy);
        orig_asm_constraints_vector = ASM_OPERANDS_INPUT_CONSTRAINT_VEC (orig);
        copy_asm_constraints_vector = ASM_OPERANDS_INPUT_CONSTRAINT_VEC (copy);
+       orig_asm_opnames_vector = ASM_OPERANDS_INPUT_NAME_VEC (orig);
+       copy_asm_opnames_vector = ASM_OPERANDS_INPUT_NAME_VEC (copy);
      }
  
    return copy;
*************** copy_insn (insn)
*** 3927,3934 ****
--- 3935,3944 ----
    copy_insn_n_scratches = 0;
    orig_asm_operands_vector = 0;
    orig_asm_constraints_vector = 0;
+   orig_asm_opnames_vector = 0;
    copy_asm_operands_vector = 0;
    copy_asm_constraints_vector = 0;
+   copy_asm_opnames_vector = 0;
    return copy_insn_1 (insn);
  }
  
Index: final.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/final.c,v
retrieving revision 1.176
diff -u -c -3 -p -r1.176 final.c
*** final.c	2001/06/08 19:52:06	1.176
--- final.c	2001/06/12 13:49:09
*************** extern int length_unit_log; /* This is d
*** 136,141 ****
--- 136,146 ----
     The precise value is the insn being output, to pass to error_for_asm.  */
  static rtx this_is_asm_operands;
  
+ /* While outputting an `asm' with operands (i.e., if
+    this_is_asm_operands is nonzero), this array will contain the names
+    of the output and input operands.  */
+ static const char **operand_names;
+ 
  /* Number of operands of this insn, for an `asm' with operands.  */
  static unsigned int insn_noperands;
  
*************** asm_insn_count (body)
*** 1512,1518 ****
    if (GET_CODE (body) == ASM_INPUT)
      template = XSTR (body, 0);
    else
!     template = decode_asm_operands (body, NULL, NULL, NULL, NULL);
  
    for (; *template; template++)
      if (IS_ASM_LOGICAL_LINE_SEPARATOR (*template) || *template == '\n')
--- 1517,1523 ----
    if (GET_CODE (body) == ASM_INPUT)
      template = XSTR (body, 0);
    else
!     template = decode_asm_operands (body, NULL, NULL, NULL, NULL, NULL);
  
    for (; *template; template++)
      if (IS_ASM_LOGICAL_LINE_SEPARATOR (*template) || *template == '\n')
*************** final_scan_insn (insn, file, optimize, p
*** 2510,2517 ****
  		app_on = 1;
  	      }
  
  	    /* Get out the operand values.  */
! 	    string = decode_asm_operands (body, ops, NULL, NULL, NULL);
  	    /* Inhibit aborts on what would otherwise be compiler bugs.  */
  	    insn_noperands = noperands;
  	    this_is_asm_operands = insn;
--- 2515,2527 ----
  		app_on = 1;
  	      }
  
+ 	    operand_names = (const char **) alloca
+ 	      (noperands * sizeof (const char *));
+ 
  	    /* Get out the operand values.  */
! 	    string = decode_asm_operands (body, ops, NULL, NULL,
! 					  operand_names, NULL);
! 
  	    /* Inhibit aborts on what would otherwise be compiler bugs.  */
  	    insn_noperands = noperands;
  	    this_is_asm_operands = insn;
*************** output_asm_insn (template, operands)
*** 3425,3445 ****
  	    p++;
  	    fprintf (asm_out_file, "%d", insn_counter);
  	  }
! 	/* % followed by a letter and some digits
! 	   outputs an operand in a special way depending on the letter.
  	   Letters `acln' are implemented directly.
  	   Other letters are passed to `output_operand' so that
  	   the PRINT_OPERAND macro can define them.  */
  	else if (ISLOWER (*p) || ISUPPER (*p))
  	  {
  	    int letter = *p++;
- 	    c = atoi (p);
  
! 	    if (! (*p >= '0' && *p <= '9'))
! 	      output_operand_lossage ("operand number missing after %-letter");
! 	    else if (this_is_asm_operands && (c < 0 || (unsigned int) c >= insn_noperands))
! 	      output_operand_lossage ("operand number out of range");
! 	    else if (letter == 'l')
  	      output_asm_label (operands[c]);
  	    else if (letter == 'a')
  	      output_address (operands[c]);
--- 3435,3486 ----
  	    p++;
  	    fprintf (asm_out_file, "%d", insn_counter);
  	  }
! 	/* % followed by a letter and some digits (or a named operand
! 	   in brackets) outputs an operand in a special way depending on
! 	   the letter.
  	   Letters `acln' are implemented directly.
  	   Other letters are passed to `output_operand' so that
  	   the PRINT_OPERAND macro can define them.  */
  	else if (ISLOWER (*p) || ISUPPER (*p))
  	  {
  	    int letter = *p++;
  
! 	    if (*p == '[')
! 	      {
! 		const char *opname = ++p;
! 		int oplen;
! 
! 		if (ISIDST (*p))
! 		  while (ISIDNUM (*++p))
! 		    ;
! 		oplen = p - opname;
! 
! 		for (c = 0; c < insn_noperands; c++)
! 		  if (strncmp (opname, operand_names[c], oplen) == 0)
! 		    break;
! 
! 		if (*p != ']' || oplen == 0)
! 		  output_operand_lossage ("invalid named operand name");
! 		if (this_is_asm_operands && c == insn_noperands)
! 		  output_operand_lossage ("unknown named operand");
! 
! 		p++;
! 	      }
! 	    else
! 	      {
! 		c = atoi (p);
! 		if (! (*p >= '0' && *p <= '9'))
! 		  output_operand_lossage
! 		    ("operand number missing after %-letter");
! 		else if (this_is_asm_operands
! 			 && (c < 0 || (unsigned int) c >= insn_noperands))
! 		  output_operand_lossage ("operand number out of range");
! 
! 		while (*p >= '0' && *p <= '9')
! 		  p++;
! 	      }
! 
! 	    if (letter == 'l')
  	      output_asm_label (operands[c]);
  	    else if (letter == 'a')
  	      output_address (operands[c]);
*************** output_asm_insn (template, operands)
*** 3463,3471 ****
  	      }
  	    else
  	      output_operand (operands[c], letter);
- 
- 	    while ((c = *p) >= '0' && c <= '9')
- 	      p++;
  	  }
  	/* % followed by a digit outputs an operand the default way.  */
  	else if (*p >= '0' && *p <= '9')
--- 3504,3509 ----
*************** output_asm_insn (template, operands)
*** 3478,3483 ****
--- 3516,3545 ----
  	      output_operand (operands[c], 0);
  	    while ((c = *p) >= '0' && c <= '9')
  	      p++;
+ 	  }
+ 	/* %[name] outputs the named operand.  */
+ 	else if (*p == '[')
+ 	  {
+ 	    const char *opname = ++p;
+ 	    int oplen, opnum;
+ 
+ 	    if (ISIDST (*p))
+ 	      while (ISIDNUM (*++p))
+ 		;
+ 	    oplen = p - opname;
+ 
+ 	    for (opnum = 0; opnum < insn_noperands; opnum++)
+ 		if (strncmp (opname, operand_names[opnum], oplen) == 0)
+ 		  break;
+ 
+ 	    if (*p != ']' || oplen == 0)
+ 	      output_operand_lossage ("invalid named operand name");
+ 	    if (this_is_asm_operands && opnum == insn_noperands)
+ 	      output_operand_lossage ("unknown named operand");
+ 	    else
+ 	      output_operand (operands[opnum], 0);
+ 
+ 	    p++;
  	  }
  	/* % followed by punctuation: output something for that
  	   punctuation character alone, with no operand.
Index: gcse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcse.c,v
retrieving revision 1.132
diff -u -c -3 -p -r1.132 gcse.c
*** gcse.c	2001/06/04 18:04:35	1.132
--- gcse.c	2001/06/12 13:49:18
*************** hash_expr_1 (x, mode, do_not_record_p)
*** 1729,1734 ****
--- 1729,1735 ----
  	  hash += (unsigned) code + (unsigned) GET_MODE (x)
  	    + hash_string_1 (ASM_OPERANDS_TEMPLATE (x))
  	    + hash_string_1 (ASM_OPERANDS_OUTPUT_CONSTRAINT (x))
+ 	    + hash_string_1 (ASM_OPERANDS_OUTPUT_NAME (x))
  	    + (unsigned) ASM_OPERANDS_OUTPUT_IDX (x);
  
  	  if (ASM_OPERANDS_INPUT_LENGTH (x))
*************** hash_expr_1 (x, mode, do_not_record_p)
*** 1739,1748 ****
--- 1740,1752 ----
  					GET_MODE (ASM_OPERANDS_INPUT (x, i)),
  					do_not_record_p)
  			   + hash_string_1 (ASM_OPERANDS_INPUT_CONSTRAINT
+ 					    (x, i))
+ 			   + hash_string_1 (ASM_OPERANDS_INPUT_NAME
  					    (x, i)));
  		}
  
  	      hash += hash_string_1 (ASM_OPERANDS_INPUT_CONSTRAINT (x, 0));
+ 	      hash += hash_string_1 (ASM_OPERANDS_INPUT_NAME (x, 0));
  	      x = ASM_OPERANDS_INPUT (x, 0);
  	      mode = GET_MODE (x);
  	      goto repeat;
*************** expr_equiv_p (x, y)
*** 1886,1891 ****
--- 1890,1897 ----
  	  || strcmp (ASM_OPERANDS_TEMPLATE (x), ASM_OPERANDS_TEMPLATE (y))
  	  || strcmp (ASM_OPERANDS_OUTPUT_CONSTRAINT (x),
  		     ASM_OPERANDS_OUTPUT_CONSTRAINT (y))
+ 	  || strcmp (ASM_OPERANDS_OUTPUT_NAME (x),
+ 		     ASM_OPERANDS_OUTPUT_NAME (y))
  	  || ASM_OPERANDS_OUTPUT_IDX (x) != ASM_OPERANDS_OUTPUT_IDX (y)
  	  || ASM_OPERANDS_INPUT_LENGTH (x) != ASM_OPERANDS_INPUT_LENGTH (y))
  	return 0;
*************** expr_equiv_p (x, y)
*** 1896,1902 ****
  	    if (! expr_equiv_p (ASM_OPERANDS_INPUT (x, i),
  				ASM_OPERANDS_INPUT (y, i))
  		|| strcmp (ASM_OPERANDS_INPUT_CONSTRAINT (x, i),
! 			   ASM_OPERANDS_INPUT_CONSTRAINT (y, i)))
  	      return 0;
  	}
  
--- 1902,1910 ----
  	    if (! expr_equiv_p (ASM_OPERANDS_INPUT (x, i),
  				ASM_OPERANDS_INPUT (y, i))
  		|| strcmp (ASM_OPERANDS_INPUT_CONSTRAINT (x, i),
! 			   ASM_OPERANDS_INPUT_CONSTRAINT (y, i))
! 		|| strcmp (ASM_OPERANDS_INPUT_NAME (x, i),
! 			   ASM_OPERANDS_INPUT_NAME (y, i)))
  	      return 0;
  	}
  
Index: genconfig.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/genconfig.c,v
retrieving revision 1.40
diff -u -c -3 -p -r1.40 genconfig.c
*** genconfig.c	2001/04/02 16:29:31	1.40
--- genconfig.c	2001/06/12 13:49:18
*************** main (argc, argv)
*** 285,292 ****
    puts ("#ifndef GCC_INSN_CONFIG_H");
    puts ("#define GCC_INSN_CONFIG_H\n");
  
!   /* Allow at least 10 operands for the sake of asm constructs.  */
!   max_recog_operands = 9;  /* We will add 1 later.  */
    max_dup_operands = 1;
  
    /* Read the machine description.  */
--- 285,292 ----
    puts ("#ifndef GCC_INSN_CONFIG_H");
    puts ("#define GCC_INSN_CONFIG_H\n");
  
!   /* Allow at least 30 operands for the sake of asm constructs.  */
!   max_recog_operands = 29;  /* We will add 1 later.  */
    max_dup_operands = 1;
  
    /* Read the machine description.  */
Index: integrate.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/integrate.c,v
retrieving revision 1.147
diff -u -c -3 -p -r1.147 integrate.c
*** integrate.c	2001/06/08 22:57:23	1.147
--- integrate.c	2001/06/12 13:49:20
*************** copy_rtx_and_substitute (orig, map, for_
*** 2098,2107 ****
--- 2098,2109 ----
  	  ASM_OPERANDS_TEMPLATE (copy) = ASM_OPERANDS_TEMPLATE (orig);
  	  ASM_OPERANDS_OUTPUT_CONSTRAINT (copy)
  	    = ASM_OPERANDS_OUTPUT_CONSTRAINT (orig);
+ 	  ASM_OPERANDS_OUTPUT_NAME (copy) = ASM_OPERANDS_OUTPUT_NAME (orig);
  	  ASM_OPERANDS_OUTPUT_IDX (copy) = ASM_OPERANDS_OUTPUT_IDX (orig);
  	  ASM_OPERANDS_INPUT_VEC (copy) = map->copy_asm_operands_vector;
  	  ASM_OPERANDS_INPUT_CONSTRAINT_VEC (copy)
  	    = map->copy_asm_constraints_vector;
+ 	  ASM_OPERANDS_INPUT_NAME_VEC (copy) = map->copy_asm_opnames_vector;
  	  ASM_OPERANDS_SOURCE_FILE (copy) = ASM_OPERANDS_SOURCE_FILE (orig);
  	  ASM_OPERANDS_SOURCE_LINE (copy) = ASM_OPERANDS_SOURCE_LINE (orig);
  	  return copy;
*************** copy_rtx_and_substitute (orig, map, for_
*** 2266,2271 ****
--- 2268,2274 ----
        map->copy_asm_operands_vector = ASM_OPERANDS_INPUT_VEC (copy);
        map->copy_asm_constraints_vector
  	= ASM_OPERANDS_INPUT_CONSTRAINT_VEC (copy);
+       map->copy_asm_opnames_vector = ASM_OPERANDS_INPUT_NAME_VEC (copy);
      }
  
    return copy;
Index: integrate.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/integrate.h,v
retrieving revision 1.18
diff -u -c -3 -p -r1.18 integrate.h
*** integrate.h	2001/05/03 16:14:34	1.18
--- integrate.h	2001/06/12 13:49:20
*************** struct inline_remap
*** 94,101 ****
       this is nonzero if we have copied an ASM_OPERANDS.
       In that case, it is the copied input-operand vector.  */
    rtvec copy_asm_operands_vector;
!   /* Likewise, this is the copied constraints vector.  */
    rtvec copy_asm_constraints_vector;
  
    /* Target of a return insn, if needed and inlining.  */
    rtx local_return_label;
--- 94,102 ----
       this is nonzero if we have copied an ASM_OPERANDS.
       In that case, it is the copied input-operand vector.  */
    rtvec copy_asm_operands_vector;
!   /* Likewise, this is the copied constraints vector and opname vector.  */
    rtvec copy_asm_constraints_vector;
+   rtvec copy_asm_opnames_vector;
  
    /* Target of a return insn, if needed and inlining.  */
    rtx local_return_label;
Index: recog.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/recog.c,v
retrieving revision 1.106
diff -u -c -3 -p -r1.106 recog.c
*** recog.c	2001/06/08 12:19:12	1.106
--- recog.c	2001/06/12 13:49:23
*************** check_asm_operands (x)
*** 150,156 ****
    operands = (rtx *) alloca (noperands * sizeof (rtx));
    constraints = (const char **) alloca (noperands * sizeof (char *));
  
!   decode_asm_operands (x, operands, NULL, constraints, NULL);
  
    for (i = 0; i < noperands; i++)
      {
--- 150,156 ----
    operands = (rtx *) alloca (noperands * sizeof (rtx));
    constraints = (const char **) alloca (noperands * sizeof (char *));
  
!   decode_asm_operands (x, operands, NULL, constraints, NULL, NULL);
  
    for (i = 0; i < noperands; i++)
      {
*************** asm_noperands (body)
*** 1486,1504 ****
  /* Assuming BODY is an insn body that uses ASM_OPERANDS,
     copy its operands (both input and output) into the vector OPERANDS,
     the locations of the operands within the insn into the vector OPERAND_LOCS,
!    and the constraints for the operands into CONSTRAINTS.
     Write the modes of the operands into MODES.
     Return the assembler-template.
  
!    If MODES, OPERAND_LOCS, CONSTRAINTS or OPERANDS is 0,
     we don't store that info.  */
  
  const char *
! decode_asm_operands (body, operands, operand_locs, constraints, modes)
       rtx body;
       rtx *operands;
       rtx **operand_locs;
       const char **constraints;
       enum machine_mode *modes;
  {
    register int i;
--- 1486,1506 ----
  /* Assuming BODY is an insn body that uses ASM_OPERANDS,
     copy its operands (both input and output) into the vector OPERANDS,
     the locations of the operands within the insn into the vector OPERAND_LOCS,
!    the constraints for the operands into CONSTRAINTS, and the operand names
!    into OPNAMES.
     Write the modes of the operands into MODES.
     Return the assembler-template.
  
!    If MODES, OPERAND_LOCS, CONSTRAINTS, OPNAMES or OPERANDS is 0,
     we don't store that info.  */
  
  const char *
! decode_asm_operands (body, operands, operand_locs, constraints, opnames, modes)
       rtx body;
       rtx *operands;
       rtx **operand_locs;
       const char **constraints;
+      const char **opnames;
       enum machine_mode *modes;
  {
    register int i;
*************** decode_asm_operands (body, operands, ope
*** 1520,1525 ****
--- 1522,1529 ----
  	    operands[i] = ASM_OPERANDS_INPUT (asmop, i - 1);
  	  if (constraints)
  	    constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i - 1);
+ 	  if (opnames)
+ 	    opnames[i] = ASM_OPERANDS_INPUT_NAME (asmop, i - 1);
  	  if (modes)
  	    modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i - 1);
  	}
*************** decode_asm_operands (body, operands, ope
*** 1532,1537 ****
--- 1536,1543 ----
  	operand_locs[0] = &SET_DEST (body);
        if (constraints)
  	constraints[0] = ASM_OPERANDS_OUTPUT_CONSTRAINT (asmop);
+       if (opnames)
+ 	opnames[0] = ASM_OPERANDS_OUTPUT_NAME (asmop);
        if (modes)
  	modes[0] = GET_MODE (SET_DEST (body));
        template = ASM_OPERANDS_TEMPLATE (asmop);
*************** decode_asm_operands (body, operands, ope
*** 1553,1558 ****
--- 1559,1566 ----
  	    operands[i] = ASM_OPERANDS_INPUT (asmop, i);
  	  if (constraints)
  	    constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
+ 	  if (opnames)
+ 	    opnames[i] = ASM_OPERANDS_INPUT_NAME (asmop, i);
  	  if (modes)
  	    modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
  	}
*************** decode_asm_operands (body, operands, ope
*** 1581,1586 ****
--- 1589,1596 ----
  	    operand_locs[i] = &SET_DEST (XVECEXP (body, 0, i));
  	  if (constraints)
  	    constraints[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 1);
+ 	  if (opnames)
+ 	    opnames[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 2);
  	  if (modes)
  	    modes[i] = GET_MODE (SET_DEST (XVECEXP (body, 0, i)));
  	  nout++;
*************** decode_asm_operands (body, operands, ope
*** 1594,1599 ****
--- 1604,1611 ----
  	    operands[i + nout] = ASM_OPERANDS_INPUT (asmop, i);
  	  if (constraints)
  	    constraints[i + nout] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
+ 	  if (opnames)
+ 	    opnames[i + nout] = ASM_OPERANDS_INPUT_NAME (asmop, i);
  	  if (modes)
  	    modes[i + nout] = ASM_OPERANDS_INPUT_MODE (asmop, i);
  	}
*************** decode_asm_operands (body, operands, ope
*** 1616,1621 ****
--- 1628,1635 ----
  	    operands[i] = ASM_OPERANDS_INPUT (asmop, i);
  	  if (constraints)
  	    constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
+ 	  if (opnames)
+ 	    opnames[i] = ASM_OPERANDS_INPUT_NAME (asmop, i);
  	  if (modes)
  	    modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
  	}
*************** extract_insn (insn)
*** 2151,2156 ****
--- 2165,2171 ----
  	  decode_asm_operands (body, recog_data.operand,
  			       recog_data.operand_loc,
  			       recog_data.constraints,
+ 			       recog_data.opnames,
  			       recog_data.operand_mode);
  	  if (noperands > 0)
  	    {
Index: recog.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/recog.h,v
retrieving revision 1.38
diff -u -c -3 -p -r1.38 recog.h
*** recog.h	2001/02/18 23:56:34	1.38
--- recog.h	2001/06/12 13:49:23
*************** struct recog_data
*** 163,168 ****
--- 163,171 ----
    /* Gives the constraint string for operand N.  */
    const char *constraints[MAX_RECOG_OPERANDS];
  
+   /* Gives the operand name for operand N.  */
+   const char *opnames[MAX_RECOG_OPERANDS];
+ 
    /* Gives the mode of operand N.  */
    enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
  
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.270
diff -u -c -3 -p -r1.270 reload1.c
*** reload1.c	2001/06/06 03:32:54	1.270
--- reload1.c	2001/06/12 13:49:31
*************** maybe_fix_stack_asms ()
*** 1314,1320 ****
  
        /* Get the operand values and constraints out of the insn.  */
        decode_asm_operands (pat, recog_data.operand, recog_data.operand_loc,
! 			   constraints, operand_mode);
  
        /* For every operand, see what registers are allowed.  */
        for (i = 0; i < noperands; i++)
--- 1314,1320 ----
  
        /* Get the operand values and constraints out of the insn.  */
        decode_asm_operands (pat, recog_data.operand, recog_data.operand_loc,
! 			   constraints, recog_data.opnames, operand_mode);
  
        /* For every operand, see what registers are allowed.  */
        for (i = 0; i < noperands; i++)
Index: rtl.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.def,v
retrieving revision 1.44
diff -u -c -3 -p -r1.44 rtl.def
*** rtl.def	2001/03/28 11:03:56	1.44
--- rtl.def	2001/06/12 13:49:32
*************** DEF_RTL_EXPR(ASM_INPUT, "asm_input", "s"
*** 455,470 ****
  /* An assembler instruction with operands.
     1st operand is the instruction template.
     2nd operand is the constraint for the output.
!    3rd operand is the number of the output this expression refers to.
       When an insn stores more than one value, a separate ASM_OPERANDS
       is made for each output; this integer distinguishes them.
!    4th is a vector of values of input operands.
!    5th is a vector of modes and constraints for the input operands.
!      Each element is an ASM_INPUT containing a constraint string
!      and whose mode indicates the mode of the input operand.
!    6th is the name of the containing source file.
!    7th is the source line number.  */
! DEF_RTL_EXPR(ASM_OPERANDS, "asm_operands", "ssiEEsi", 'x')
  
  /* A machine-specific operation.
     1st operand is a vector of operands being used by the operation so that
--- 455,472 ----
  /* An assembler instruction with operands.
     1st operand is the instruction template.
     2nd operand is the constraint for the output.
!    3rd operand is the operand name for the output.
!    4rd operand is the number of the output this expression refers to.
       When an insn stores more than one value, a separate ASM_OPERANDS
       is made for each output; this integer distinguishes them.
!    5th is a vector of values of input operands.
!    6th is a vector of modes and constraints for the input operands.  Each
!      element is an ASM_INPUT containing a constraint and whose mode
!      indicates the mode of the input operand.
!    7th is a vector of input operands names.
!    8th is the name of the containing source file.
!    9th is the source line number.  */
! DEF_RTL_EXPR(ASM_OPERANDS, "asm_operands", "sssiEEEsi", 'x')
  
  /* A machine-specific operation.
     1st operand is a vector of operands being used by the operation so that
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.264
diff -u -c -3 -p -r1.264 rtl.h
*** rtl.h	2001/06/09 22:39:23	1.264
--- rtl.h	2001/06/12 13:49:34
*************** extern unsigned int subreg_regno 	PARAMS
*** 819,837 ****
  
  #define ASM_OPERANDS_TEMPLATE(RTX) XCSTR ((RTX), 0, ASM_OPERANDS)
  #define ASM_OPERANDS_OUTPUT_CONSTRAINT(RTX) XCSTR ((RTX), 1, ASM_OPERANDS)
! #define ASM_OPERANDS_OUTPUT_IDX(RTX) XCINT ((RTX), 2, ASM_OPERANDS)
! #define ASM_OPERANDS_INPUT_VEC(RTX) XCVEC ((RTX), 3, ASM_OPERANDS)
! #define ASM_OPERANDS_INPUT_CONSTRAINT_VEC(RTX) XCVEC ((RTX), 4, ASM_OPERANDS)
! #define ASM_OPERANDS_INPUT(RTX, N) XCVECEXP ((RTX), 3, (N), ASM_OPERANDS)
! #define ASM_OPERANDS_INPUT_LENGTH(RTX) XCVECLEN ((RTX), 3, ASM_OPERANDS)
  #define ASM_OPERANDS_INPUT_CONSTRAINT_EXP(RTX, N) \
! 			XCVECEXP ((RTX), 4, (N), ASM_OPERANDS)
  #define ASM_OPERANDS_INPUT_CONSTRAINT(RTX, N) \
! 			XSTR (XCVECEXP ((RTX), 4, (N), ASM_OPERANDS), 0)
  #define ASM_OPERANDS_INPUT_MODE(RTX, N)  \
! 			GET_MODE (XCVECEXP ((RTX), 4, (N), ASM_OPERANDS))
! #define ASM_OPERANDS_SOURCE_FILE(RTX) XCSTR ((RTX), 5, ASM_OPERANDS)
! #define ASM_OPERANDS_SOURCE_LINE(RTX) XCINT ((RTX), 6, ASM_OPERANDS)
  
  /* For a MEM rtx, 1 if it's a volatile reference.
     Also in an ASM_OPERANDS rtx.  */
--- 819,843 ----
  
  #define ASM_OPERANDS_TEMPLATE(RTX) XCSTR ((RTX), 0, ASM_OPERANDS)
  #define ASM_OPERANDS_OUTPUT_CONSTRAINT(RTX) XCSTR ((RTX), 1, ASM_OPERANDS)
! #define ASM_OPERANDS_OUTPUT_NAME(RTX) XCSTR ((RTX), 2, ASM_OPERANDS)
! #define ASM_OPERANDS_OUTPUT_IDX(RTX) XCINT ((RTX), 3, ASM_OPERANDS)
! #define ASM_OPERANDS_INPUT_VEC(RTX) XCVEC ((RTX), 4, ASM_OPERANDS)
! #define ASM_OPERANDS_INPUT_CONSTRAINT_VEC(RTX) XCVEC ((RTX), 5, ASM_OPERANDS)
! #define ASM_OPERANDS_INPUT_NAME_VEC(RTX) XCVEC ((RTX), 6, ASM_OPERANDS)
! #define ASM_OPERANDS_INPUT(RTX, N) XCVECEXP ((RTX), 4, (N), ASM_OPERANDS)
! #define ASM_OPERANDS_INPUT_LENGTH(RTX) XCVECLEN ((RTX), 4, ASM_OPERANDS)
  #define ASM_OPERANDS_INPUT_CONSTRAINT_EXP(RTX, N) \
! 			XCVECEXP ((RTX), 5, (N), ASM_OPERANDS)
  #define ASM_OPERANDS_INPUT_CONSTRAINT(RTX, N) \
! 			XSTR (XCVECEXP ((RTX), 5, (N), ASM_OPERANDS), 0)
  #define ASM_OPERANDS_INPUT_MODE(RTX, N)  \
! 			GET_MODE (XCVECEXP ((RTX), 5, (N), ASM_OPERANDS))
! #define ASM_OPERANDS_INPUT_NAME_EXP(RTX, N) \
! 			XCVECEXP ((RTX), 6, (N), ASM_OPERANDS)
! #define ASM_OPERANDS_INPUT_NAME(RTX, N) \
! 			XSTR (XCVECEXP ((RTX), 6, (N), ASM_OPERANDS), 0)
! #define ASM_OPERANDS_SOURCE_FILE(RTX) XCSTR ((RTX), 7, ASM_OPERANDS)
! #define ASM_OPERANDS_SOURCE_LINE(RTX) XCINT ((RTX), 8, ASM_OPERANDS)
  
  /* For a MEM rtx, 1 if it's a volatile reference.
     Also in an ASM_OPERANDS rtx.  */
*************** extern void free_reg_info		PARAMS ((void
*** 1448,1453 ****
--- 1454,1460 ----
  /* recog.c */
  extern int asm_noperands		PARAMS ((rtx));
  extern const char *decode_asm_operands	PARAMS ((rtx, rtx *, rtx **,
+ 					       const char **,
  					       const char **,
  					       enum machine_mode *));
  
Index: stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.199
diff -u -c -3 -p -r1.199 stmt.c
*** stmt.c	2001/06/08 18:12:54	1.199
--- stmt.c	2001/06/12 13:50:02
*************** expand_asm_operands (string, outputs, in
*** 1314,1320 ****
       const char *filename;
       int line;
  {
!   rtvec argvec, constraints;
    rtx body;
    int ninputs = list_length (inputs);
    int noutputs = list_length (outputs);
--- 1314,1320 ----
       const char *filename;
       int line;
  {
!   rtvec argvec, constraints, opnames;
    rtx body;
    int ninputs = list_length (inputs);
    int noutputs = list_length (outputs);
*************** expand_asm_operands (string, outputs, in
*** 1330,1335 ****
--- 1330,1336 ----
      = (enum machine_mode *) alloca (noutputs * sizeof (enum machine_mode));
    const char **output_constraints
      = alloca (noutputs * sizeof (const char *));
+   const char **output_names = alloca (noutputs * sizeof (const char *));
    /* The insn we have emitted.  */
    rtx insn;
    int old_generating_concat_p = generating_concat_p;
*************** expand_asm_operands (string, outputs, in
*** 1379,1385 ****
    if (outputs || inputs)
      {
        tree tmp = TREE_PURPOSE (outputs ? outputs : inputs);
!       int nalternatives = n_occurrences (',', TREE_STRING_POINTER (tmp));
        tree next = inputs;
  
        if (nalternatives + 1 > MAX_RECOG_ALTERNATIVES)
--- 1380,1387 ----
    if (outputs || inputs)
      {
        tree tmp = TREE_PURPOSE (outputs ? outputs : inputs);
!       int nalternatives = n_occurrences
! 	(',', TREE_STRING_POINTER (TREE_VALUE (tmp)));
        tree next = inputs;
  
        if (nalternatives + 1 > MAX_RECOG_ALTERNATIVES)
*************** expand_asm_operands (string, outputs, in
*** 1391,1397 ****
        tmp = outputs;
        while (tmp)
  	{
! 	  const char *constraint = TREE_STRING_POINTER (TREE_PURPOSE (tmp));
  
  	  if (n_occurrences (',', constraint) != nalternatives)
  	    {
--- 1393,1400 ----
        tmp = outputs;
        while (tmp)
  	{
! 	  const char *constraint = TREE_STRING_POINTER
! 	    (TREE_VALUE (TREE_PURPOSE (tmp)));
  
  	  if (n_occurrences (',', constraint) != nalternatives)
  	    {
*************** expand_asm_operands (string, outputs, in
*** 1427,1433 ****
  	 the worst that happens if we get it wrong is we issue an error
  	 message.  */
  
!       constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail));
        output_constraints[i] = constraint;
        c_len = strlen (constraint);
  
--- 1430,1447 ----
  	 the worst that happens if we get it wrong is we issue an error
  	 message.  */
  
!       if (TREE_PURPOSE (TREE_PURPOSE (tail)) == NULL_TREE)
! 	output_names[i] = empty_string;
!       else
! 	{
! 	  output_names[i] = IDENTIFIER_POINTER
! 	    (TREE_PURPOSE (TREE_PURPOSE (tail)));
! 	  for (j = 0; j < i; j++)
! 	    if (strcmp (output_names[j], output_names[i]) == 0)
! 	      error ("identical `asm' operand names: `%s'", output_names[i]);
! 	}
! 
!       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
        output_constraints[i] = constraint;
        c_len = strlen (constraint);
  
*************** expand_asm_operands (string, outputs, in
*** 1600,1620 ****
        return;
      }
  
!   /* Make vectors for the expression-rtx and constraint strings.  */
  
    argvec = rtvec_alloc (ninputs);
    constraints = rtvec_alloc (ninputs);
  
    body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
  				: GET_MODE (output_rtx[0])),
  			       TREE_STRING_POINTER (string), 
! 			       empty_string, 0, argvec, constraints,
  			       filename, line);
  
    MEM_VOLATILE_P (body) = vol;
  
    /* Eval the inputs and put them into ARGVEC.
!      Put their constraints into ASM_INPUTs and store in CONSTRAINTS.  */
  
    i = 0;
    for (tail = inputs; tail; tail = TREE_CHAIN (tail))
--- 1614,1638 ----
        return;
      }
  
!   /* Make vectors for the expression-rtx, constraint strings and named
!      operands.  */
  
    argvec = rtvec_alloc (ninputs);
    constraints = rtvec_alloc (ninputs);
+   opnames = rtvec_alloc (ninputs);
  
    body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
  				: GET_MODE (output_rtx[0])),
  			       TREE_STRING_POINTER (string), 
! 			       empty_string, empty_string, 0,
! 			       argvec, constraints, opnames,
  			       filename, line);
  
    MEM_VOLATILE_P (body) = vol;
  
    /* Eval the inputs and put them into ARGVEC.
!      Put their constraints into ASM_INPUTs and store in CONSTRAINTS.
!      Store operand names in OPNAMES.  */
  
    i = 0;
    for (tail = inputs; tail; tail = TREE_CHAIN (tail))
*************** expand_asm_operands (string, outputs, in
*** 1622,1627 ****
--- 1640,1646 ----
        int j;
        int allows_reg = 0, allows_mem = 0;
        const char *constraint, *orig_constraint;
+       const char *opname;
        int c_len;
        rtx op;
  
*************** expand_asm_operands (string, outputs, in
*** 1639,1645 ****
  	  return;
  	}
  
!       constraint = TREE_STRING_POINTER (TREE_PURPOSE (tail));
        c_len = strlen (constraint);
        orig_constraint = constraint;
  
--- 1658,1677 ----
  	  return;
  	}
  
!       if (TREE_PURPOSE (TREE_PURPOSE (tail)) == NULL_TREE)
! 	opname = empty_string;
!       else
! 	{
! 	  opname = IDENTIFIER_POINTER (TREE_PURPOSE (TREE_PURPOSE (tail)));
! 	  for (j = 0; j < noutputs; j++)
! 	    if (strcmp (output_names[j], opname) == 0)
! 	      error ("identical `asm' operand names: `%s'", opname);
! 	  for (j = 0; j < i; j++)
! 	    if (strcmp (ASM_OPERANDS_INPUT_NAME (body, j), opname) == 0)
! 	      error ("identical `asm' operand names: `%s'", opname);
! 	}
! 
!       constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
        c_len = strlen (constraint);
        orig_constraint = constraint;
  
*************** expand_asm_operands (string, outputs, in
*** 1701,1707 ****
  		for (j = constraint[j] - '0'; j > 0; --j)
  		  o = TREE_CHAIN (o);
  
! 		constraint = TREE_STRING_POINTER (TREE_PURPOSE (o));
  		c_len = strlen (constraint);
  		j = 0;
  		break;
--- 1733,1740 ----
  		for (j = constraint[j] - '0'; j > 0; --j)
  		  o = TREE_CHAIN (o);
  
! 		constraint = TREE_STRING_POINTER
! 		  (TREE_VALUE (TREE_PURPOSE (o)));
  		c_len = strlen (constraint);
  		j = 0;
  		break;
*************** expand_asm_operands (string, outputs, in
*** 1792,1797 ****
--- 1825,1834 ----
        ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, i)
  	= gen_rtx_ASM_INPUT (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
  			     orig_constraint);
+ 
+       ASM_OPERANDS_INPUT_NAME_EXP (body, i)
+ 	= gen_rtx_ASM_INPUT (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
+ 			     opname);
        i++;
      }
  
*************** expand_asm_operands (string, outputs, in
*** 1816,1834 ****
  	= output_rtx[j];
        ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, ninputs - ninout + i)
  	= gen_rtx_ASM_INPUT (inout_mode[i], digit_string (j));
      }
  
    generating_concat_p = old_generating_concat_p;
  
    /* Now, for each output, construct an rtx
!      (set OUTPUT (asm_operands INSN OUTPUTNUMBER OUTPUTCONSTRAINT
! 			       ARGVEC CONSTRAINTS))
       If there is more than one, put them inside a PARALLEL.  */
  
    if (noutputs == 1 && nclobbers == 0)
      {
!       ASM_OPERANDS_OUTPUT_CONSTRAINT (body)
! 	= output_constraints[0];
        insn = emit_insn (gen_rtx_SET (VOIDmode, output_rtx[0], body));
      }
  
--- 1853,1873 ----
  	= output_rtx[j];
        ASM_OPERANDS_INPUT_CONSTRAINT_EXP (body, ninputs - ninout + i)
  	= gen_rtx_ASM_INPUT (inout_mode[i], digit_string (j));
+       ASM_OPERANDS_INPUT_NAME_EXP (body, ninputs - ninout + i)
+ 	= gen_rtx_ASM_INPUT (inout_mode[i], output_names[j]);
      }
  
    generating_concat_p = old_generating_concat_p;
  
    /* Now, for each output, construct an rtx
!      (set OUTPUT (asm_operands INSN OUTPUTCONSTRAINT OUTPUTNAME OUTPUTNUMBER
! 			       ARGVEC CONSTRAINTS OPNAMES))
       If there is more than one, put them inside a PARALLEL.  */
  
    if (noutputs == 1 && nclobbers == 0)
      {
!       ASM_OPERANDS_OUTPUT_CONSTRAINT (body) = output_constraints[0];
!       ASM_OPERANDS_OUTPUT_NAME (body) = output_names[0];
        insn = emit_insn (gen_rtx_SET (VOIDmode, output_rtx[0], body));
      }
  
*************** expand_asm_operands (string, outputs, in
*** 1857,1864 ****
  			   gen_rtx_ASM_OPERANDS
  			   (GET_MODE (output_rtx[i]),
  			    TREE_STRING_POINTER (string),
! 			    output_constraints[i],
! 			    i, argvec, constraints,
  			    filename, line));
  
  	  MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;
--- 1896,1903 ----
  			   gen_rtx_ASM_OPERANDS
  			   (GET_MODE (output_rtx[i]),
  			    TREE_STRING_POINTER (string),
! 			    output_constraints[i], output_names[i],
! 			    i, argvec, constraints, opnames,
  			    filename, line));
  
  	  MEM_VOLATILE_P (SET_SRC (XVECEXP (body, 0, i))) = vol;
Index: config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.97
diff -u -c -3 -p -r1.97 sh.c
*** sh.c	2001/06/04 00:20:45	1.97
--- sh.c	2001/06/12 13:50:26
*************** sh_insn_length_adjustment (insn)
*** 5326,5332 ****
  	template = XSTR (body, 0);
        else if (asm_noperands (body) >= 0)
  	template
! 	  = decode_asm_operands (body, NULL, NULL, NULL, NULL);
        else
  	return 0;
        do
--- 5326,5332 ----
  	template = XSTR (body, 0);
        else if (asm_noperands (body) >= 0)
  	template
! 	  = decode_asm_operands (body, NULL, NULL, NULL, NULL, NULL);
        else
  	return 0;
        do
Index: cp/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parse.y,v
retrieving revision 1.221
diff -u -c -3 -p -r1.221 parse.y
*** parse.y	2001/05/22 17:58:43	1.221
--- parse.y	2001/06/12 13:50:33
*************** cp_parse_init ()
*** 339,344 ****
--- 339,345 ----
  %type <ttype> SCSPEC TYPESPEC CV_QUALIFIER maybe_cv_qualifier
  %type <ttype> init initlist maybeasm maybe_init defarg defarg1
  %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
+ %type <ttype> maybe_asm_operand_name
  %type <ttype> maybe_attribute attributes attribute attribute_list attrib
  %type <ttype> any_word
  
*************** nonnull_asm_operands:
*** 3607,3614 ****
  	;
  
  asm_operand:
! 	  STRING '(' expr ')'
! 		{ $$ = build_tree_list ($$, $3); }
  	;
  
  asm_clobbers:
--- 3608,3615 ----
  	;
  
  asm_operand:
! 	  maybe_asm_operand_name STRING '(' expr ')'
! 		{ $$ = build_tree_list (build_tree_list ($1, $2), $4); }
  	;
  
  asm_clobbers:
*************** asm_clobbers:
*** 3616,3621 ****
--- 3617,3628 ----
  		{ $$ = tree_cons (NULL_TREE, combine_strings ($1), NULL_TREE);}
  	| asm_clobbers ',' string
  		{ $$ = tree_cons (NULL_TREE, combine_strings ($3), $1); }
+ 	;
+ 
+ maybe_asm_operand_name: /* empty */
+ 		{ $$ = NULL_TREE; }
+ 	| '[' any_word ']'
+ 		{ $$ = $2; }
  	;
  
  /* This is what appears inside the parens in a function declarator.
Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.1
diff -u -c -3 -p -r1.1 extend.texi
*** extend.texi	2001/06/01 16:51:18	1.1
--- extend.texi	2001/06/12 13:50:38
*************** the C expression in parentheses.  A colo
*** 2934,2945 ****
  template from the first output operand and another separates the last
  output operand from the first input, if any.  Commas separate the
  operands within each group.  The total number of operands is limited to
! ten or to the maximum number of operands in any instruction pattern in
! the machine description, whichever is greater.
  
  If there are no output operands but there are input operands, you must
  place two consecutive colons surrounding the place where the output
  operands would go.
  
  Output operand expressions must be lvalues; the compiler can check this.
  The input operands need not be lvalues.  The compiler cannot check
--- 2934,2965 ----
  template from the first output operand and another separates the last
  output operand from the first input, if any.  Commas separate the
  operands within each group.  The total number of operands is limited to
! thirty or to the maximum number of operands in any instruction pattern
! in the machine description, whichever is greater.
  
  If there are no output operands but there are input operands, you must
  place two consecutive colons surrounding the place where the output
  operands would go.
+ 
+ As of GCC version 3.1, it is also possible to specify input and output
+ operands using symbolic names which can be referenced within the
+ assembler code.  These names are specified inside square brackets
+ preceding the constraint string, and can be referenced inside the
+ assembler code using @code{%[@var{name}]} instead of a percentage sign
+ followed by the operand number.  Using named operands the above example
+ could look like:
+ 
+ @example
+ asm ("fsinx %[angle],%[output]"
+      : [output] "=f" (result)
+      : [angle] "f" (angle));
+ @end example
+ 
+ @noindent
+ Note that the symbolic operand names have no relation whatsoever to C
+ expressions.  You may use any name you like, even those of existing C
+ symbols, but must ensure that no two operands within the same assembler
+ construct use the same symbolic name.
  
  Output operand expressions must be lvalues; the compiler can check this.
  The input operands need not be lvalues.  The compiler cannot check
Index: doc/rtl.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/rtl.texi,v
retrieving revision 1.3
diff -u -c -3 -p -r1.3 rtl.texi
*** rtl.texi	2001/06/11 20:47:35	1.3
--- rtl.texi	2001/06/12 13:50:41
*************** an @code{asm} statement with arguments. 
*** 2385,2391 ****
  a single output operand, like this:
  
  @smallexample
! asm ("foo %1,%2,%0" : "=a" (outputvar) : "g" (x + y), "di" (*z));
  @end smallexample
  
  @noindent
--- 2385,2393 ----
  a single output operand, like this:
  
  @smallexample
! asm ("foo %[sum],%2,%[out]"
!      : [out] "=a" (outputvar)
!      : [sum] "g" (x + y), "di" (*z));
  @end smallexample
  
  @noindent
*************** the value that is stored in @code{output
*** 2394,2412 ****
  
  @smallexample
  (set @var{rtx-for-outputvar}
!      (asm_operands "foo %1,%2,%0" "a" 0
                     [@var{rtx-for-addition-result} @var{rtx-for-*z}]
                     [(asm_input:@var{m1} "g")
!                     (asm_input:@var{m2} "di")]))
  @end smallexample
  
  @noindent
  Here the operands of the @code{asm_operands} RTX are the assembler
! template string, the output-operand's constraint, the index-number of the
! output operand among the output operands specified, a vector of input
! operand RTX's, and a vector of input-operand modes and constraints.  The
! mode @var{m1} is the mode of the sum @code{x+y}; @var{m2} is that of
! @code{*z}.
  
  When an @code{asm} statement has multiple output values, its insn has
  several such @code{set} RTX's inside of a @code{parallel}.  Each @code{set}
--- 2396,2418 ----
  
  @smallexample
  (set @var{rtx-for-outputvar}
!      (asm_operands "foo %[sum],%2,%[out]" "a" "out" 0
                     [@var{rtx-for-addition-result} @var{rtx-for-*z}]
                     [(asm_input:@var{m1} "g")
!                     (asm_input:@var{m2} "di")]
!                    [(asm_input:@var{m1} "sum")
!                     (asm_input:@var{m2} "")]))
  @end smallexample
  
  @noindent
  Here the operands of the @code{asm_operands} RTX are the assembler
! template string, the output-operand's constraint, the symbolic name of
! the output operand, the index-number of the output operand among the
! output operands specified, a vector of input operand RTX's, a vector of
! input-operand modes and constraints, and a vector of input-operand modes
! and symbolic names.  The mode @var{m1} is the mode of the sum
! @code{x+y}; @var{m2} is that of @code{*z}.  Operands not having a
! symbolic name will have an empty string in place of the operand name.
  
  When an @code{asm} statement has multiple output values, its insn has
  several such @code{set} RTX's inside of a @code{parallel}.  Each @code{set}


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