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


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

PATCH: string-expansion macros


I have been sitting on this for almost 8 weeks now, waiting for some
spare time to submit it.  Well, I still have no spare time, but can't
in good conscience delay any longer.

I have several weeks experience using it in my port, and it works
fine.

A possibly controversial change is this:
	* opcodes/cgen-asm.c (build_asm_hash_table): Try to match hard
	insns before macros & aliases.
I'd like to know why the old code tried to match macros before hard
insns?  The reason I need to try hard insns before macros is that for
my MIPS-like port, string macros catch cases that can't be handled by
one insn, and implement a "virtual insn" that do things in 2 or 3 hard
insns.  E.g., hard insn for set-register accepts a 16-bit immediate
operand.  As a fallback, I have a string-macro that accepts a 32-bit
immediate and expands to two hard insns to set upper and lower
16-bits.  If the macro were tried first, a small constant actual
operand would certainly match the constraint of a 32-bit operand and
the 2-insn macro would expand before we tried the hard insn which
should match.  The only way that trying macros before hard insns could
work for me is with a more sophisticated 32-bit operand constraint
that only matches quantities that don't fit in 16 bits.

As an example of use, here are the "mov" insns for copying an
immediate into a register:

(dnmi moviwu "Move Immediate Word Unsigned" (NO-DIS)
      "mov $dest2,$uimm32"
      ("movhi %0,%1@h"
       "or %0,%1@l"))

(dnmi moviws "Move Immediate Word Signed" (NO-DIS)
      "mov $dest2,$simm32"
      ("movhi %0 %1@h"
       "or %0,%1@l"))

Here's a double-word add macro.  (I defined general register keywords
with `_next' suffix for making register pairs: $2 is register 2,
$2_next is register 3.)

(dnmi daddu "Add Double-word Unsigned" (NO-DIS)
      "daddu $dest,$src1,$src2"
      ("addu %0,%1,%2"
       "setltu %0_next,%0,%1"
       "addu %0_next,%0_next,%1_next"
       "addu %0_next,%0_next,%2_next"))

Comments?

Greg

This ChangeLog is unified.  At checkin time, I'll split it up among
the ChangeLog files in each of the component directories.

2001-03-02  Greg McGary  <greg@mcgary.org>

	* cgen/attr.scm (attr-builtin!): Add MACRO & STRING
	* cgen/minsn.scm (-minsn-parse-expansion): Allow list of strings.
	(-minsn-parse): Likewise.
	(define-full-minsn): Affix MACRO attr and STRING or ALIAS attr
	depending on type of expansion.
	* cgen/opc-itab.scm (-gen-ifield-decls) [cgen_fields]:
	New members op_starts and op_lengths.
	(opc-insert-handlers): New handler: insn-macro-string.
	(-gen-insn-opcode-entry): Wrap curlies around field which is now a union.
	(-gen-minsn-table-entry): Print proper string-macro entry.
	(-gen-minsn-macro-string-expansion): New function.
	(-gen-minsn-opcode-entry): Handle STRING macros.
	(-gen-macro-insn-table): Invert condition.  Test for STRING explicitly.
	* gas/read.c (read_a_source_file): Repackage macro-listing code.
	Handle CGEN string macro expansion.
	(maybe_print_macro_listing): New function.
	* gas/tc.h (md_assemble): Conditionalize return value on MD_ASSEMBLE_MACRO.
	* include/opcode/cgen.h (CGEN_OPCODE): wrap union around
	member `format', and add member `string' alongside.
	(CGEN_OPCODE_FORMAT): Traverse enclosing union.
	(CGEN_OPCODE_MACRO_STRING, CGEN_INSN_MACRO_STRING): New macros.
	* opcodes/cgen-asm.c (build_asm_hash_table): Try to match hard
	insns before macros & aliases.
	* opcodes/cgen-asm.in (parse_insn_normal): Remember starts &
	lengths of actual operands.
	* opcodes/cgen-ibld.in (insert_insn_normal): Return NULL if no errors.
	(insert_insn_macro_string): New function.

Index: cgen/attr.scm
===================================================================
RCS file: /cvs/src/src/cgen/attr.scm,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 attr.scm
--- attr.scm	2000/07/28 04:11:52	1.1.1.1
+++ attr.scm	2001/03/02 23:25:24
@@ -1,5 +1,5 @@
 ; Attributes.
-; Copyright (C) 2000 Red Hat, Inc.
+; Copyright (C) 2000, 2001 Red Hat, Inc.
 ; This file is part of CGEN.
 ; See file COPYING.CGEN for details.
 
@@ -893,11 +893,20 @@ Define an attribute, name/value pair lis
   (define-attr '(for keyword) '(type boolean) '(name PRIVATE))
 
   ; Attributes requiring fixed indices.
-  ; ALIAS is used for instructions that are aliases of more general insns.
-  ; ALIAS insns are ignored by the simulator.
+  ; MACRO insns are ignored by the simulator.
+  ; ALIAS is a 1:1 renaming (possibly omitting operands) of a real insn
+  ; STRING is an expansion into which we insert textual representation
+  ;   of operands and then reparse.
+  ; if neither ALIAS or STRING, expansion is a builder function.
   (define-attr '(for attr) '(type boolean) '(name INDEX) '(attrs META))
+  (define-attr '(for insn) '(type boolean) '(name MACRO)
+    '(comment "insn expands into something else")
+    '(attrs INDEX))
   (define-attr '(for insn) '(type boolean) '(name ALIAS)
-    '(comment "insn is an alias of another")
+    '(comment "insn is a macro that's a simple an alias of a real insn")
+    '(attrs INDEX))
+  (define-attr '(for insn) '(type boolean) '(name STRING)
+    '(comment "insn is a macro that expands into a string to be reparsed")
     '(attrs INDEX))
 
   *UNSPECIFIED*
Index: cgen/minsn.scm
===================================================================
RCS file: /cvs/src/src/cgen/minsn.scm,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 minsn.scm
--- minsn.scm	2000/07/28 04:11:52	1.1.1.1
+++ minsn.scm	2001/03/02 23:25:24
@@ -1,5 +1,5 @@
 ; Macro instruction definitions.
-; Copyright (C) 2000 Red Hat, Inc.
+; Copyright (C) 2000, 2001 Red Hat, Inc.
 ; This file is part of CGEN.
 ; See file COPYING.CGEN for details.
 
@@ -18,7 +18,10 @@
 ; description in the .cpu file.
 ; All arguments are in raw (non-evaluated) form.
 
-; ??? At present we only support macros that are aliases of one real insn.
+; ??? At present we only support macros that are
+;     1) aliases of one real insn
+;     2) and string-expansion.
+;     someday we might support a general insn builder mechanmsim as well.
 
 ; Object to describe a macro-insn.
 
@@ -57,13 +60,15 @@
 )
 
 ; Parse a macro-insn expansion description.
-; ??? At present we only support unconditional simple expansion.
 
 (define (-minsn-parse-expansion errtxt expn)
-  (if (not (form? expn))
-      (parse-error errtxt "invalid macro expansion" expn))
-  (if (not (eq? 'emit (car expn)))
-      (parse-error errtxt "invalid macro expansion, must be `(emit ...)'" expn))
+  (cond ((null? expn)
+	 (parse-error errtxt "empty macro expansion" expn))
+	((not (list? expn))
+	 (parse-error errtxt "invalid macro expansion" expn))
+	((not (or (eq? 'emit (car expn))
+		  (string? (car expn))))
+	 (parse-error errtxt "invalid macro expansion" expn)))
   expn
 )
 
@@ -76,26 +81,37 @@
 (define (-minsn-parse errtxt name comment attrs syntax expansions)
   (logit 2 "Processing macro-insn " name " ...\n")
 
-  (if (not (list? expansions))
-      (parse-error errtxt "invalid macro expansion list" expansions))
-
-  (let ((name (parse-name name errtxt))
-	(atlist-obj (atlist-parse attrs "cgen_minsn" errtxt)))
-
-    (if (keep-atlist? atlist-obj #f)
-
-	(let ((result (make <macro-insn>
-			name
-			(parse-comment comment errtxt)
-			atlist-obj
-			(parse-syntax syntax errtxt)
-			(map (lambda (e) (-minsn-parse-expansion errtxt e))
-			     expansions))))
-	  result)
-
-	(begin
-	  (logit 2 "Ignoring " name ".\n")
-	  #f)))
+  (if (cond ((not (list? expansions))
+	     (parse-error errtxt "invalid macro expansion: not a list" expansions)
+	     #f)
+	    ((not (list? (car expansions)))
+	     (parse-error errtxt "invalid macro expansion: not a list" expansions)
+	     #f)
+	    ((string? (caar expansions))
+	     (logit 2 "Parsing " name " as list-of-strings expansion.\n")
+	     #t)
+	    ((eq? 'emit (caar expansions))
+	     (logit 2 "Parsing " name " as emit expansion.\n")
+	     #t)
+	    (else
+	     (logit 2 "Ignoring " name ": unknown expansion.\n")
+	     #f))
+      (let ((name (parse-name name errtxt))
+	    (atlist-obj (atlist-parse attrs "cgen_minsn" errtxt)))
+
+	(if (keep-atlist? atlist-obj #f)
+	    (let ((result (make <macro-insn>
+			    name
+			    (parse-comment comment errtxt)
+			    atlist-obj
+			    (parse-syntax syntax errtxt)
+			    (map (lambda (e) (-minsn-parse-expansion errtxt e))
+				 expansions))))
+	      result)
+	    (begin
+	      (logit 2 "Ignoring " name ".\n")
+	      #f)))
+      #f)
 )
 
 ; Read a macro-insn description
@@ -152,7 +168,10 @@
   (if (eq? APPLICATION 'SIMULATOR)
       #f ; don't waste time if simulator
       (let ((m (-minsn-parse "define-full-minsn" name comment
-			     (cons 'ALIAS attrs)
+			     (cons 'MACRO
+				   (if (string? (car expansion))
+				       (cons 'STRING attrs)
+				       (cons 'ALIAS attrs)))
 			     syntax (list expansion))))
 	(if m
 	    (current-minsn-add! m))
Index: cgen/opc-itab.scm
===================================================================
RCS file: /cvs/src/src/cgen/opc-itab.scm,v
retrieving revision 1.2
diff -u -p -r1.2 opc-itab.scm
--- opc-itab.scm	2000/11/20 19:03:33	1.2
+++ opc-itab.scm	2001/03/02 23:25:25
@@ -1,5 +1,5 @@
 ; Opcode table support.
-; Copyright (C) 2000 Red Hat, Inc.
+; Copyright (C) 2000, 2001 Red Hat, Inc.
 ; This file is part of CGEN.
 
 ; Append code here to be run before insn parsing/etc.
@@ -47,6 +47,10 @@
    "struct cgen_fields\n{\n"
    ; A special member `length' is used to record the length.
    "  int length;\n"
+   ; Special members to hold operand strings for macro string expansion.
+   "  const char *op_starts[10];\n"
+   "  int op_lengths[10];\n"
+   "  const char *macro_string_expansion;\n"
    (string-map gen-ifield-value-decl (non-derived-ifields (current-ifld-list)))
    "};\n\n"
    )
@@ -237,7 +241,7 @@
 ; ??? It might be useful to define the handler in Scheme.  Later.
 
 (define opc-parse-handlers '((insn-normal)))
-(define opc-insert-handlers '((insn-normal)))
+(define opc-insert-handlers '((insn-normal) (insn-macro-string)))
 (define opc-extract-handlers '((insn-normal)))
 (define opc-print-handlers '((insn-normal)))
 
@@ -337,7 +341,7 @@
     "    " (gen-insn-handlers insn) ",\n"
     "    " (gen-syntax-entry "MNEM" "OP" (insn-syntax insn)) ",\n"
     ; ??? 'twould save space to put a pointer here and record format separately
-    "    " (gen-ifmt-entry insn) ", "
+    "    { " (gen-ifmt-entry insn) " }, "
     ;"0x" (number->string (insn-value insn) 16) ",\n"
     (gen-ivalue-entry insn) "\n"
     "  },\n"))
@@ -363,7 +367,7 @@ static const CGEN_OPCODE @arch@_cgen_ins
   /* Special null first entry.
      A `num' value of zero is thus invalid.
      Also, the special `invalid' insn resides here.  */
-  { { 0, 0, 0, 0 }, {{0}}, 0, {0}},\n"
+  { { 0, 0, 0, 0 }, {{0}}, {0}, {0}},\n"
 
      (lambda ()
        (string-write-map (lambda (insn)
@@ -494,18 +498,36 @@ static unsigned int dis_hash_insn PARAMS
   (gen-obj-sanitize
    minsn
    (string-list
-    "  /* " (minsn-syntax minsn) " */\n"
+    "/* " (minsn-syntax minsn) " */\n"
     "  {\n"
     "    "
     "-1, " ; macro-insns are not currently enumerated, no current need to
     "\"" (obj:name minsn) "\", "
-    "\"" (minsn-mnemonic minsn) "\",\n"
-    "    " (gen-syntax-entry "MNEM" "OP" (minsn-syntax minsn)) ",\n"
-    "    (PTR) & macro_" (gen-sym minsn) "_expansions[0],\n"
+    "\"" (minsn-mnemonic minsn) "\", -1,\n"
     "    "
-    (gen-obj-attr-defn 'minsn minsn all-attrs num-non-bools gen-insn-attr-mask)
-    "\n"
-    "  },\n"))
+    (gen-obj-attr-defn 'minsn minsn all-attrs num-non-bools gen-A-attr-mask)
+;;; (gen-bool-attrs (obj-atlist minsn) gen-A-attr-mask)
+    "\n  },\n"))
+)
+
+;;; macro string expansion is a list of strings, each representing
+;;; an assembler insn.  Combine them into a single C string with
+;;; newline separators and TAB prefixes, except that insns strings
+;;; beginning with "*" don't get TAB (this is used for labels that
+;;; want to begin in the first column).
+(define (-gen-minsn-macro-string-expansion expans)
+  (cond ((null? expans)
+	 "")
+	((string? expans)
+	 (string-append "\\\n"
+			(if (char=? (string-ref expans 0) #\*)
+			    (substring expans 1 (string-length expans))
+			    (string-append "\t" expans))
+			"\\n"))
+	((and (list? expans)
+	      (string? (car expans)))
+	 (string-append (-gen-minsn-macro-string-expansion (car expans))
+			(-gen-minsn-macro-string-expansion (cdr expans)))))
 )
 
 ; Return a macro-insn opcode table entry.
@@ -515,17 +537,21 @@ static unsigned int dis_hash_insn PARAMS
   (gen-obj-sanitize
    minsn
    (string-list
-    "  /* " (minsn-syntax minsn) " */\n"
+    "/* " (minsn-syntax minsn) " */\n"
     "  {\n"
-    "    "
-    "-1, " ; macro-insns are not currently enumerated, no current need to
-    "\"" (obj:name minsn) "\", "
-    "\"" (minsn-mnemonic minsn) "\",\n"
-    "    " (gen-syntax-entry "MNEM" "OP" (minsn-syntax minsn)) ",\n"
-    "    (PTR) & macro_" (gen-sym minsn) "_expansions[0],\n"
-    "    "
-    (gen-obj-attr-defn 'minsn minsn all-attrs num-non-bools gen-insn-attr-mask)
-    "\n"
+    "    { 0, 1, 0, 0 },\n"
+    ;; macro-insns are not currently enumerated, no current need to
+    "    " (gen-syntax-entry "MNEM" "OP" (minsn-syntax minsn)) ",\n    { "
+    (cond ((multi-insn? minsn)
+	   (string-append "& macro_" (gen-sym minsn) "_expansions[0]"))
+	  ((has-attr? minsn 'STRING)
+	   (string-append " \""
+			  (-gen-minsn-macro-string-expansion
+			   (car (minsn-expansions minsn)))
+			  "\""))
+	  (else
+	   (logit 2 "Unknown expansion type in -gen-minsn-opcode-entry\n")))
+    " }, { 0 }\n"
     "  },\n"))
 )
 
@@ -557,16 +583,17 @@ static unsigned int dis_hash_insn PARAMS
 					      minsn-list))))
      "#undef F\n\n"
      "/* Each non-simple macro entry points to an array of expansion possibilities.  */\n\n"
-     (lambda () 
+     (lambda ()
        (string-write-map (lambda (minsn)
-			   (if (has-attr? minsn 'ALIAS)
-			       ""
+			   ;; GKM FIXME: can a multi insn appear here???
+			   (if (multi-insn? minsn)
 			       (string-append
 				"static const CGEN_MINSN_EXPANSION macro_" (gen-sym minsn) "_expansions[] =\n"
 				"{\n"
 				(string-map -gen-miexpn-entry
 					    (minsn-expansions minsn))
-				"  { 0, 0 }\n};\n\n")))
+				"  { 0, 0 }\n};\n\n")
+			       ""))
 			 minsn-list))
      (gen-define-with-symcat "A(a) (1 << CGEN_INSN_" "a)")
      (gen-define-with-symcat "OPERAND(op) @ARCH@_OPERAND_" "op")
@@ -583,9 +610,11 @@ static const CGEN_IBASE @arch@_cgen_macr
        (string-write-map (lambda (minsn)
 			   (logit 3 "Generating macro-insn table entry for " (obj:name minsn) " ...\n")
 			   ; Simple macro-insns are emitted as aliases of real insns.
-			   (if (has-attr? minsn 'ALIAS)
-			       (gen-insn-table-entry minsn all-attrs num-non-bools)
-			       (-gen-minsn-table-entry minsn all-attrs num-non-bools)))
+			   (cond ((has-attr? minsn 'ALIAS)
+				  (gen-insn-table-entry minsn all-attrs num-non-bools))
+				 ((has-attr? minsn 'STRING)
+				  (-gen-minsn-table-entry minsn all-attrs num-non-bools))
+				 (else "")))
 			 minsn-list))
      "\
 };
Index: cgen/sim-decode.scm
===================================================================
RCS file: /cvs/src/src/cgen/sim-decode.scm,v
retrieving revision 1.4
diff -u -p -r1.4 sim-decode.scm
--- sim-decode.scm	2001/01/06 12:11:09	1.4
+++ sim-decode.scm	2001/03/02 23:25:25
@@ -433,7 +433,7 @@ void
    " extract_" (gen-sym sfmt) ":\n"
    "  {\n"
    "    const IDESC *idesc = &" IDESC-TABLE-VAR "[itype];\n"
-   (if (< (length (sfmt-iflds sfmt)) 0)
+   (if (> (length (sfmt-iflds sfmt)) 0)
        (string-append
 	"    CGEN_INSN_INT insn = "
 	(if (adata-integral-insn? CURRENT-ARCH)
Index: gas/read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.32
diff -u -p -r1.32 read.c
--- read.c	2000/12/28 10:07:55	1.32
+++ read.c	2001/03/02 23:25:27
@@ -219,6 +219,7 @@ static int dwarf_file_string;
 #endif
 #endif
 
+static void maybe_print_macro_listing PARAMS ((void));
 static void cons_worker PARAMS ((int, int));
 static int scrub_from_string PARAMS ((char *, int));
 static void do_align PARAMS ((int, char *, int, int));
@@ -638,37 +639,7 @@ read_a_source_file (name)
 
 	  know (c != ' ');	/* No further leading whitespace.  */
 
-#ifndef NO_LISTING
-	  /* If listing is on, and we are expanding a macro, then give
-	     the listing code the contents of the expanded line.  */
-	  if (listing)
-	    {
-	      if ((listing & LISTING_MACEXP) && macro_nest > 0)
-		{
-		  char *copy;
-		  int len;
-
-		  /* Find the end of the current expanded macro line.  */
-		  for (s = input_line_pointer - 1; *s; ++s)
-		    if (is_end_of_line[(unsigned char) *s])
-		      break;
-
-		  /* Copy it for safe keeping.  Also give an indication of
-		     how much macro nesting is involved at this point.  */
-		  len = s - (input_line_pointer - 1);
-		  copy = (char *) xmalloc (len + macro_nest + 2);
-		  memset (copy, '>', macro_nest);
-		  copy[macro_nest] = ' ';
-		  memcpy (copy + macro_nest + 1, input_line_pointer - 1, len);
-		  copy[macro_nest + 1 + len] = '\0';
-
-		  /* Install the line with the listing facility.  */
-		  listing_newline (copy);
-		}
-	      else
-		listing_newline (NULL);
-	    }
-#endif
+	  maybe_print_macro_listing ();
 	  /* C is the 1st significant character.
 	     Input_line_pointer points after that character.  */
 	  if (is_name_beginner (c))
@@ -891,10 +862,29 @@ read_a_source_file (name)
 			    }
 			}
 
-		      md_assemble (s);	/* Assemble 1 instruction.  */
+#if MD_ASSEMBLE_MACRO
+		      {
+			/* Assemble 1 instruction, or if a macro-insn,
+			   expand it and return the expansion.  */
+			const char *expand_str = md_assemble (s);
+			*input_line_pointer++ = c;
+			if (expand_str)
+			  {
+			    sb expand_sb;
+			    sb_new (&expand_sb);
+			    sb_add_string (&expand_sb, expand_str);
+			    free (expand_str);
+			    input_scrub_include_sb (&expand_sb, input_line_pointer, 1);
+			    sb_kill (&expand_sb);
+			    buffer_limit = input_scrub_next_buffer (&input_line_pointer);
 
+			    maybe_print_macro_listing ();
+			  }
+		      }
+#else
+		      md_assemble (s);	/* Assemble 1 instruction.  */
 		      *input_line_pointer++ = c;
-
+#endif
 		      /* We resume loop AFTER the end-of-line from
 			 this instruction.  */
 		    }
@@ -1091,6 +1081,44 @@ read_a_source_file (name)
   }
 #endif
 }
+
+static void
+maybe_print_macro_listing ()
+{
+#ifndef NO_LISTING
+  /* If listing is on, and we are expanding a macro, then give
+     the listing code the contents of the expanded line.  */
+  if (listing)
+    {
+      if ((listing & LISTING_MACEXP) && macro_nest > 0)
+	{
+	  char *copy;
+	  int len;
+	  char *s;
+
+	  /* Find the end of the current expanded macro line.  */
+	  for (s = input_line_pointer - 1; *s; ++s)
+	    if (is_end_of_line[(unsigned char) *s])
+	      break;
+
+	  /* Copy it for safe keeping.  Also give an indication of
+	     how much macro nesting is involved at this point.  */
+	  len = s - (input_line_pointer - 1);
+	  copy = (char *) xmalloc (len + macro_nest + 2);
+	  memset (copy, '>', macro_nest);
+	  copy[macro_nest] = ' ';
+	  memcpy (copy + macro_nest + 1, input_line_pointer - 1, len);
+	  copy[macro_nest + 1 + len] = '\0';
+
+	  /* Install the line with the listing facility.  */
+	  listing_newline (copy);
+	}
+      else
+	listing_newline (NULL);
+    }
+#endif
+}
+
 
 /* For most MRI pseudo-ops, the line actually ends at the first
    nonquoted space.  This function looks for that point, stuffs a null
Index: gas/tc.h
===================================================================
RCS file: /cvs/src/src/gas/tc.h,v
retrieving revision 1.2
diff -u -p -r1.2 tc.h
--- tc.h	2000/09/12 20:57:14	1.2
+++ tc.h	2001/03/02 23:25:28
@@ -1,6 +1,6 @@
 /* tc.h - target cpu dependent
 
-   Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1990, 1991, 1992, 2001 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -52,7 +52,11 @@ int md_parse_option PARAMS ((int c, char
 void md_show_usage PARAMS ((FILE *));
 long md_pcrel_from PARAMS ((fixS * fixP));
 short tc_coff_fix2rtype PARAMS ((fixS * fixP));
+#if MD_ASSEMBLE_MACRO
+const char *md_assemble PARAMS ((char *str));
+#else
 void md_assemble PARAMS ((char *str));
+#endif
 void md_begin PARAMS ((void));
 #ifndef md_create_long_jump
 void md_create_long_jump PARAMS ((char *ptr, addressT from_addr,
Index: include/opcode/cgen.h
===================================================================
RCS file: /cvs/src/src/include/opcode/cgen.h,v
retrieving revision 1.9
diff -u -p -r1.9 cgen.h
--- cgen.h	2001/02/02 23:04:39	1.9
+++ cgen.h	2001/03/02 23:25:28
@@ -904,13 +904,19 @@ typedef struct
 #define CGEN_OPCODE_SYNTAX(opc) (& (opc)->syntax)
 
   /* Format entry.  */
-  const CGEN_IFMT *format;
-#define CGEN_OPCODE_FORMAT(opc) ((opc)->format)
+  union {
+    /* hard insn.  */
+    const CGEN_IFMT *format;
+#define CGEN_OPCODE_FORMAT(opc) ((opc)->u.format)
 #define CGEN_OPCODE_MASK_BITSIZE(opc) CGEN_IFMT_MASK_LENGTH (CGEN_OPCODE_FORMAT (opc))
 #define CGEN_OPCODE_BITSIZE(opc) CGEN_IFMT_LENGTH (CGEN_OPCODE_FORMAT (opc))
 #define CGEN_OPCODE_IFLDS(opc) CGEN_IFMT_IFLDS (CGEN_OPCODE_FORMAT (opc))
+    /* 1:n macro insn.  */
+    const char *string;
+#define CGEN_OPCODE_MACRO_STRING(opc) ((opc)->u.string)
+  } u;
 
-  /* Instruction opcode value.  */
+  /* Instruction opcode value for hard insn.  */
   CGEN_IVALUE value;
 #define CGEN_OPCODE_VALUE(opc) (& (opc)->value)
 #define CGEN_OPCODE_BASE_VALUE(opc) (CGEN_OPCODE_VALUE (opc)->base_value)
@@ -1054,6 +1060,10 @@ extern int cgen_macro_insn_count PARAMS 
 /* Return value of base part of INSN.  */
 #define CGEN_INSN_BASE_VALUE(insn) \
   CGEN_OPCODE_BASE_VALUE (CGEN_INSN_OPCODE (insn))
+
+/* Return macro string expansion of INSN.  */
+#define CGEN_INSN_MACRO_STRING(insn) \
+  CGEN_OPCODE_MACRO_STRING (CGEN_INSN_OPCODE (insn))
 
 /* Standard way to test whether INSN is supported by MACH.
    MACH is one of enum mach_attr.
Index: opcodes/cgen-asm.c
===================================================================
RCS file: /cvs/src/src/opcodes/cgen-asm.c,v
retrieving revision 1.2
diff -u -p -r1.2 cgen-asm.c
--- cgen-asm.c	2000/07/26 22:45:49	1.2
+++ cgen-asm.c	2001/03/02 23:25:28
@@ -1,6 +1,6 @@
 /* CGEN generic assembler support code.
 
-   Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
 
    This file is part of the GNU Binutils and GDB, the GNU debugger.
 
@@ -139,6 +139,13 @@ build_asm_hash_table (cd)
   asm_hash_table_entries = hash_entry_buf = (CGEN_INSN_LIST *)
     xmalloc (count * sizeof (CGEN_INSN_LIST));
 
+  /* Add compiled in macro-insns.  */
+
+  hash_entry_buf = hash_insn_array (cd, macro_insn_table->init_entries,
+				    macro_insn_table->num_init_entries,
+				    macro_insn_table->entry_size,
+				    asm_hash_table, hash_entry_buf);
+
   /* Add compiled in insns.
      Don't include the first one as it is a reserved entry.  */
   /* ??? It was the end of all hash chains, and also the special
@@ -150,23 +157,16 @@ build_asm_hash_table (cd)
 				    insn_table->entry_size,
 				    asm_hash_table, hash_entry_buf);
 
-  /* Add compiled in macro-insns.  */
+  /* Add runtime added macro-insns.  */
 
-  hash_entry_buf = hash_insn_array (cd, macro_insn_table->init_entries,
-				    macro_insn_table->num_init_entries,
-				    macro_insn_table->entry_size,
-				    asm_hash_table, hash_entry_buf);
+  hash_insn_list (cd, macro_insn_table->new_entries,
+		  asm_hash_table, hash_entry_buf);
 
   /* Add runtime added insns.
      Later added insns will be prefered over earlier ones.  */
 
   hash_entry_buf = hash_insn_list (cd, insn_table->new_entries,
 				   asm_hash_table, hash_entry_buf);
-
-  /* Add runtime added macro-insns.  */
-
-  hash_insn_list (cd, macro_insn_table->new_entries,
-		  asm_hash_table, hash_entry_buf);
 
   cd->asm_hash_table = asm_hash_table;
   cd->asm_hash_table_entries = asm_hash_table_entries;
Index: opcodes/cgen-asm.in
===================================================================
RCS file: /cvs/src/src/opcodes/cgen-asm.in,v
retrieving revision 1.4
diff -u -p -r1.4 cgen-asm.in
--- cgen-asm.in	2001/01/09 17:00:21	1.4
+++ cgen-asm.in	2001/03/02 23:25:29
@@ -70,6 +70,8 @@ parse_insn_normal (cd, insn, strp, field
   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
   const char *str = *strp;
   const char *errmsg;
+  const char **op_starts = fields->op_starts;
+  int *op_lengths = fields->op_lengths;
   const char *p;
   const CGEN_SYNTAX_CHAR_TYPE * syn;
 #ifdef CGEN_MNEMONIC_OPERANDS
@@ -149,14 +151,19 @@ parse_insn_normal (cd, insn, strp, field
 	}
 
       /* We have an operand of some sort.  */
+      *op_starts = str;
       errmsg = @arch@_cgen_parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
 					  &str, fields);
+      *op_lengths++ = (str - *op_starts++);
       if (errmsg)
 	return errmsg;
 
       /* Done with this operand, continue with next one.  */
       ++ syn;
     }
+
+  *op_starts = NULL;
+  *op_lengths = 0;
 
   /* If we're at the end of the syntax string, we're done.  */
   if (* syn == 0)
Index: opcodes/cgen-ibld.in
===================================================================
RCS file: /cvs/src/src/opcodes/cgen-ibld.in,v
retrieving revision 1.4
diff -u -p -r1.4 cgen-ibld.in
--- cgen-ibld.in	2001/01/09 17:00:21	1.4
+++ cgen-ibld.in	2001/03/02 23:25:29
@@ -34,6 +34,7 @@ along with this program; if not, write t
 #include "@prefix@-desc.h"
 #include "@prefix@-opc.h"
 #include "opintl.h"
+#include "libiberty.h"
 
 #undef min
 #define min(a,b) ((a) < (b) ? (a) : (b))
@@ -49,6 +50,9 @@ static const char * insert_normal
 static const char * insert_insn_normal
      PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *,
 	      CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
+static const char * insert_insn_macro_string
+     PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *,
+	      CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
 
 static int extract_normal
      PARAMS ((CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
@@ -255,6 +259,86 @@ insert_insn_normal (cd, insn, fields, bu
 				       fields, buffer, pc);
       if (errmsg)
 	return errmsg;
+    }
+
+  return NULL;
+}
+
+/* Builder for string-expansion insn macros.
+   The result is an error message or NULL if success.  */
+
+static const char *
+insert_insn_macro_string (cd, insn, fields, buffer, pc)
+     CGEN_CPU_DESC cd;
+     const CGEN_INSN * insn;
+     CGEN_FIELDS * fields;
+     CGEN_INSN_BYTES_PTR buffer;
+     bfd_vma pc;
+{
+  const char *template = CGEN_INSN_MACRO_STRING (insn);
+  const char **op_starts = fields->op_starts;
+  int *op_lengths = fields->op_lengths;
+  char *expansion;
+  int length = 0;
+  const char *errmsg;
+
+  /* Use normal insertion in order to check operand constraints.  */
+  errmsg = insert_insn_normal (cd, insn, fields, buffer, pc);
+  if (errmsg)
+    return errmsg;
+  
+  for (;;)
+    {
+      char *insertion = strchr (template, '%');
+      if (insertion)
+	{
+	  int ic = insertion[1];
+	  length += insertion++ - template;
+	  if (ic == '%')
+	    length++;
+	  else if (isdigit (ic))
+	    length += op_lengths[ic - '0'];
+	  else
+	    return _("invalid positional parameter in macro string expansion");
+	  template = ++insertion;
+	}
+      else
+	{
+	  length += strlen (template);
+	  break;
+	}
+    }
+
+  fields->macro_string_expansion = expansion = xmalloc (length + 1);
+  template = CGEN_INSN_MACRO_STRING (insn);
+  for (;;)
+    {
+      char *insertion = strchr (template, '%');
+      if (insertion)
+	{
+	  int ic = insertion[1];
+	  int length = insertion++ - template;
+
+	  memcpy (expansion, template, length);
+	  expansion += length;
+	  template += length;
+	  if (ic == '%')
+	    *expansion++ = '%';
+	  else if (isdigit (ic))
+	    {
+	      ic -= '0';
+	      memcpy (expansion, op_starts[ic], op_lengths[ic]);
+	      expansion += op_lengths[ic];
+	    }
+	  else
+	    return _("invalid positional parameter in macro string expansion");
+	  template = ++insertion;
+	}
+      else
+	{
+	  strcpy (expansion, template);
+	  break;
+	}
     }
 
   return NULL;


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