This is the mail archive of the
cgen@sources.redhat.com
mailing list for the CGEN project.
PATCH: string-expansion macros
- To: cgen at sourceware dot cygnus dot com
- Subject: PATCH: string-expansion macros
- From: Greg McGary <greg at mcgary dot org>
- Date: Fri, 2 Mar 2001 16:58:54 -0700
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;