[kaffe] CVS kaffe (stack): Merge the "mnemonicizer.awk" from the JanosVM. Basically, it is a
Kaffe CVS
cvs-commits at kaffe.org
Tue Sep 28 09:30:06 PDT 2004
PatchSet 5226
Date: 2004/09/28 16:26:20
Author: stack
Branch: HEAD
Tag: (none)
Log:
Merge the "mnemonicizer.awk" from the JanosVM. Basically, it is a
tool that converts an instruction set description into a header file
containing macros that can be used to generate code at run time.
Currently, it is geared towards the PowerPC (see
config/powerpc/ppc_isa.defs), and most likely won't "just work" for
other architectures.
Members:
ChangeLog:1.2780->1.2781
Makefile.am:1.80->1.81
Makefile.in:1.183->1.184
developers/mnemonicizer.awk:INITIAL->1.1
Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.2780 kaffe/ChangeLog:1.2781
--- kaffe/ChangeLog:1.2780 Tue Sep 28 15:42:59 2004
+++ kaffe/ChangeLog Tue Sep 28 16:26:20 2004
@@ -1,3 +1,8 @@
+2004-09-28 Timothy S. Stack <stack at cs.utah.edu>
+
+ * developers/mnemonicizer.awk:
+ Merge from JanosVM, used to convert ppc_isa.defs into ppc_isa.h.
+
2004-09-28 Dalibor Topic <robilad at kaffe.org>
* libraries/javalib/java/net/URL.java:
Index: kaffe/Makefile.am
diff -u kaffe/Makefile.am:1.80 kaffe/Makefile.am:1.81
--- kaffe/Makefile.am:1.80 Fri Aug 13 15:18:25 2004
+++ kaffe/Makefile.am Tue Sep 28 16:26:24 2004
@@ -111,6 +111,7 @@
developers/mauve-html-gen.pl \
developers/mauve-kaffe \
developers/mauve-results.sh \
+ developers/mnemonicizer.awk \
developers/patch-libtool-quote-sys_search_path.diff \
developers/rpm-kaffe.spec \
developers/sp_offset.c \
Index: kaffe/Makefile.in
diff -u kaffe/Makefile.in:1.183 kaffe/Makefile.in:1.184
--- kaffe/Makefile.in:1.183 Mon Sep 20 23:18:38 2004
+++ kaffe/Makefile.in Tue Sep 28 16:26:24 2004
@@ -474,6 +474,7 @@
developers/mauve-html-gen.pl \
developers/mauve-kaffe \
developers/mauve-results.sh \
+ developers/mnemonicizer.awk \
developers/patch-libtool-quote-sys_search_path.diff \
developers/rpm-kaffe.spec \
developers/sp_offset.c \
===================================================================
Checking out kaffe/developers/mnemonicizer.awk
RCS: /home/cvs/kaffe/kaffe/developers/mnemonicizer.awk,v
VERS: 1.1
***************
--- /dev/null Sun Aug 4 19:57:58 2002
+++ kaffe/developers/mnemonicizer.awk Tue Sep 28 16:30:06 2004
@@ -0,0 +1,472 @@
+#
+# mnemonicizer.awk
+# Interprets a "defs" file filled with definitions for a processor instruction
+# set architecture (ISA).
+#
+# Copyright (c) 2002 The University of Utah and the Flux Group.
+# All rights reserved.
+#
+# @JANOSVM_TOOL_LICENSE@
+#
+
+#
+# The mnemonicizer is a simple tool that is meant to ease the burden of
+# writing and reading jitter code. Instead of writing raw bits culled from
+# a programming reference or manually #defining a bunch of stuff we just write
+# a short defs file that can be automagically translated. Hopefully, this
+# eases the maintenance burden by making it trivial to change the generated
+# macros as well as making it easier for fresh eyes to understand the code.
+#
+# XXX This code probably very ppc specific at the moment...
+#
+
+BEGIN {
+ if( ARGC < 2 )
+ {
+ printf("Usage: awk -f %s <defs file>\n", ARGV[0]);
+ exit -1;
+ }
+}
+
+# A comment, just ignore it.
+#
+# Usage: # Foo bar
+# Result: [empty]
+/^\#/ {
+}
+
+# A C++ style comment that the user wishes to be included in the file.
+#
+# Usage: // Foo bar
+# Result: // Foo bar
+/^\/\// {
+ printf("%s\n", $0);
+}
+
+# Specify the prefix for all generated symbols.
+#
+# Usage: prefix <name>
+# Result: [empty] XXX
+/^prefix[\t ]/ {
+ prefix = $2;
+ tall_prefix = toupper(prefix);
+ printf("\n");
+ printf("#ifndef _%s_isa_h_\n", prefix);
+ printf("#define _%s_isa_h_\n", prefix);
+ printf("\n");
+ printf("#ifndef %s_op_debug\n", prefix);
+ printf("#define %s_op_ctxt 0\n", prefix);
+ printf("#define %s_op_debug(x) 0\n", prefix);
+ printf("#endif\n");
+ printf("\n");
+}
+
+# Specify the C type for instructions.
+#
+# Usage: prefix <type>
+# Result: typedef <type> <prefix>_code_t;
+/^opcode_type[\t ]/ {
+ printf("typedef ");
+ for( lpc = 2; lpc <= NF; lpc++ )
+ {
+ printf("%s ", $lpc);
+ }
+ printf("%s_code_t;\n\n", prefix);
+}
+
+# Specify a bit encoded value.
+#
+# Usage: bit <name> <value>
+# Result:
+# #define <tall prefix>_<tall name> <value>
+# or
+# #define <tall prefix>_<tall name>(<params>) <value> | <params>
+#
+# The value is made up of zero's, one's, y's, and z's. The zero's and one's
+# give a fixed value while the z's correspond to a reserved value that should
+# be zero for now, and the y's make the bitmask parameterized.
+#
+# XXX Only one y argument is allowed at the least significant bit position.
+/^bits[\t ]/ {
+ name = $2;
+ value = 0;
+ has_arg = 0;
+ for( lpc = 1; lpc < (length($3) + 1); lpc++ )
+ {
+ ch = substr($3, lpc, 1);
+ if( ch == "1" )
+ {
+ value += 2 ^ (length($3) - lpc);
+ }
+ else if( ch == "0" || ch == "z" )
+ {
+ }
+ else if( ch == "y" )
+ {
+ has_arg = 1;
+ }
+ }
+ bits[name] = value;
+ if( has_arg )
+ {
+ printf("#define %s_%s(y) (0x%x | !!(y))\n\n",
+ tall_prefix, toupper(name), value);
+ }
+ else
+ {
+ printf("#define %s_%s 0x%x\n\n", tall_prefix, toupper(name), value);
+ }
+}
+
+# Specify the number of registers.
+#
+# Usage: registers <int register count>
+# Result: enum {
+# <tall prefix>_R0,
+# <tall prefix>_R1,
+# <tall prefix>_R2,
+# ...
+# };
+/^registers[\t ]/ {
+ printf("enum {\n");
+ for( lpc = 0; lpc < $2; lpc++ )
+ {
+ printf("\t%s_R%d,\n", tall_prefix, lpc);
+ }
+ printf("};\n\n");
+
+ int_registers = int($2);
+}
+
+# Specify the number of floating point registers.
+#
+# Usage: float_registers <float register count>
+# Result: enum {
+# <tall prefix>_FPR = <int register count>
+# <tall prefix>_FPR0,
+# <tall prefix>_FPR1,
+# ...
+# };
+/^float_registers[\t ]/ {
+ printf("enum {\n");
+ printf("\t%s_FPR = %d,\n", tall_prefix, int_registers - 1);
+ for( lpc = 0; lpc < $2; lpc++ )
+ {
+ printf("\t%s_FPR%d,\n", tall_prefix, lpc);
+ }
+ printf("};\n\n");
+
+ float_registers = int($2);
+}
+
+# Specify the Kaffe-specific attributes for integer registers.
+#
+# Usage: register_attribute <start reg> <end reg> <reg type> <reg flags>
+# Result: The result of these aren't printed out till the end and have the
+# form:
+# #define REGISTER_SET \
+# { /* r0 */ 0, 0, <reg type>, <reg flags>, 0, 0, 0 }, \
+# { /* r1 */ 0, 0, <reg type>, <reg flags>, 0, 0, 1 }, \
+# { /* r2 */ 0, 0, <reg type>, <reg flags>, 0, 0, 2 }, \
+# ...
+# { /* rN */ 0, 0, <reg type>, <reg flags>, 0, 0, N }, \
+/^register_attribute[\t ]/ {
+ for( lpc = $2; lpc <= $3; lpc++ )
+ {
+ register_attributes[lpc] = $4;
+ if( NF >= 5 )
+ register_flags[lpc] = $5;
+ }
+}
+
+# Specify the Kaffe-specific attributes for floating point registers.
+#
+# Usage: float_register_attribute <start reg> <end reg> <reg type> <reg flags>
+# Result: Same as above, except the floating point registers are appended
+# to the end...
+# #define REGISTER_SET \
+# { /* r0 */ 0, 0, <reg type>, <reg flags>, 0, 0, 0 }, \
+# { /* r1 */ 0, 0, <reg type>, <reg flags>, 0, 0, 1 }, \
+# { /* r2 */ 0, 0, <reg type>, <reg flags>, 0, 0, 2 }, \
+# ...
+# { /* rN */ 0, 0, <reg type>, <reg flags>, 0, 0, N }, \
+/^float_register_attribute[\t ]/ {
+ for( lpc = $2; lpc <= $3; lpc++ )
+ {
+ float_register_attributes[lpc] = $4;
+ if( NF >= 5 )
+ float_register_flags[lpc] = $5;
+ }
+}
+
+# Define a register alias.
+#
+# Usage: register_alias <name> <register index>
+# Result: #define <tall prefix>_R<tall name> <tall prefix>_R<index>
+/^register_alias[\t ]/ {
+ printf("#define %s_R%s %s_R%d\n\n",
+ tall_prefix,
+ toupper($2),
+ tall_prefix,
+ $3);
+}
+
+# Define a floating point register alias.
+#
+# Usage: float_register_alias <name> <register index>
+# Result: #define <tall prefix>_FPR<tall name> <tall prefix>_FPR<index>
+/^float_register_alias[\t ]/ {
+ printf("#define %s_FPR%s %s_FPR%d\n\n",
+ tall_prefix,
+ toupper($2),
+ tall_prefix,
+ $3);
+}
+
+# Define an opcode field.
+#
+# Usage: op_field <name> <begin offset> <end offset>
+# Result:
+# #define <tall prefix>_<tall name>_OFFSET
+# #define <tall prefix>_<tall name>_MASK
+# #define <tall prefix>_SET_<tall name>(x)
+# #define <tall prefix>_GET_<tall name>(x)
+#
+# The begin and end offsets are inclusive and start at the most significant
+# bit (e.g. 2 ^ 31 is offset 0).
+/^op_field[\t ]/ {
+ name = $2;
+ offset = $3;
+ size = $4 - offset + 1;
+ op_fields[name] = offset;
+ printf("#define %s_%s_OFFSET %dUL\n",
+ tall_prefix,
+ toupper(name),
+ 32 - offset - size);
+ printf("#define %s_%s_MASK (0x%xUL << %s_%s_OFFSET)\n",
+ tall_prefix,
+ toupper(name),
+ sizemask(size),
+ tall_prefix,
+ toupper(name));
+ printf("#define %s_SET_%s(x) \\\n",
+ tall_prefix,
+ toupper(name));
+ printf("\t(((x) & 0x%x) << %s_%s_OFFSET)\n",
+ sizemask(size),
+ tall_prefix,
+ toupper(name));
+ printf("#define %s_GET_%s(x) \\\n",
+ tall_prefix,
+ toupper(name));
+ printf("\t(((x) >> %s_%s_OFFSET) & 0x%x)\n",
+ tall_prefix,
+ toupper(name),
+ sizemask(size));
+ printf("\n");
+}
+
+# Define a single bit opcode field.
+#
+# Usage: op_option <name> <offset>
+# Result:
+# #define <tall prefix>_<tall name>_OFFSET
+# #define <tall prefix>_OPTION_<tall name>
+/^op_option[\t ]/ {
+ name = $2;
+ offset = $3;
+ op_options[name] = offset;
+ op_fields[name] = offset;
+ printf("#define %s_%s_OFFSET %dUL\n",
+ tall_prefix,
+ toupper(name),
+ 31 - offset);
+ printf("#define %s_OPTION_%s (1L << %d)\n\n",
+ tall_prefix,
+ toupper(name),
+ 31 - offset);
+}
+
+# Define an opcode.
+#
+# Usage: op <name> <op_field|op_option|int> [...]
+# Result: #define <prefix>_op_<name>(...)
+#
+# Opcodes are defined using the op_fields and op_options that were previously
+# defined as well as raw integers. Any op_fields can be used with or without
+# an argument (e.g. ra(1) vs. ra) to specify whether the generated macro should
+# contain a parameter for the field. The op_option fields are ignored because
+# they are probably better served by or'ing the argument afterwards
+# (e.g. op_blr() | PPC_OPTION_LK). However, they must be given so that the
+# bits they use are accounted for and to ensure proper placement of raw integer
+# values. Otherwise, the script is unable to properly fill in the fields.
+#
+#
+# Example:
+#
+# prefix ppc
+#
+# # Define the opcode field.
+# op_field opcd 0 5
+# # Define the register fields.
+# op_field ra 11 15
+# op_field rb 16 20
+# op_field rd 6 10
+#
+# op_option oe 21
+# op_option rc 31
+#
+# # rd = ra + rb
+# op add opcd(31) rd ra rb oe 266 rc
+# # rd = r0 + rb
+# op addto0 opcd(31) rd ra(0) rb oe 266 rc
+#
+#
+# Example Output:
+#
+# ...
+# #define ppc_op_add(rd, ra, rb) \
+# (PPC_SET_OPCD(31) |
+# PPC_SET_RD(rd) |
+# PPC_SET_RA(ra) |
+# PPC_SET_RB(rb) |
+# (266 << 1))
+#
+# #define ppc_op_addto0(rd, rb) \
+# (PPC_SET_OPCD(31) |
+# PPC_SET_RD(rd) |
+# PPC_SET_RA(0) |
+# PPC_SET_RB(rb) |
+# (266 << 1))
+/^op[\t ]/ {
+ name = $2;
+ printf("#define %s_op_%s(", prefix, name);
+ first_field = 1;
+ for( lpc = 3; lpc <= NF; lpc++ )
+ {
+ if( $lpc in op_options )
+ {
+ }
+ else if( $lpc in op_fields )
+ {
+ printf("%s%s", (first_field ? "" : ", "), $lpc);
+ first_field = 0;
+ }
+ }
+ printf(") \\\n");
+ printf("\t((void)%s_op_debug((%s_op_ctxt, \"%s ", prefix, prefix, name);
+ for( lpc = 3; lpc <= NF; lpc++ )
+ {
+ if( $lpc in op_options )
+ {
+ }
+ else if( $lpc in op_fields )
+ {
+ printf("%s(%%d) ", $lpc);
+ }
+ }
+ printf("\"");
+ for( lpc = 3; lpc <= NF; lpc++ )
+ {
+ if( $lpc in op_options )
+ {
+ }
+ else if( $lpc in op_fields )
+ {
+ printf(", %s", $lpc);
+ }
+ }
+ printf(")), \\\n");
+ printf("\t (");
+ bar = "";
+ the_bar = " | \\\n\t ";
+ for( lpc = 3; lpc <= NF; lpc++ )
+ {
+ if( split($lpc, args, "[()]") == 3 )
+ {
+ if( args[2] in bits )
+ args[2] = bits[args[2]];
+ if( args[1] in op_options )
+ {
+ printf("%s%s_OPTION_%s",
+ bar, tall_prefix, toupper(args[1]));
+ }
+ else
+ {
+ printf("%s%s_SET_%s(%s)",
+ bar, tall_prefix, toupper(args[1]), args[2]);
+ }
+ bar = the_bar;
+ }
+ else if( $lpc in op_options )
+ {
+ }
+ else if( $lpc in op_fields )
+ {
+ printf("%s%s_SET_%s(%s)", bar, tall_prefix, toupper($lpc), $lpc);
+ bar = the_bar;
+ }
+ else if( lpc < NF )
+ {
+ if( split($(lpc + 1), args, "[()]") == 3 )
+ {
+ field_name = args[1];
+ }
+ else
+ {
+ field_name = $(lpc + 1);
+ }
+ printf("%s(%dUL << %d)", bar, $lpc, 32 - op_fields[field_name]);
+ bar = the_bar;
+ }
+ else
+ {
+ printf("%s%d", bar, $lpc);
+ bar = the_bar;
+ }
+ }
+ printf("))\n\n");
+}
+
+# Print out the REGISTER_SET define for Kaffe.
+END {
+ printf("#define REGISTER_SET \\\n");
+ for( lpc = 0; lpc < int_registers; lpc++ )
+ {
+ attr = "Rint|Rref";
+ flags = "0";
+ if( lpc in register_attributes )
+ attr = register_attributes[lpc];
+ if( lpc in register_flags )
+ flags = register_flags[lpc];
+ printf("\t{ /* r%d */\t0, 0, %s,\t%s, 0, %d }, \\\n",
+ lpc,
+ attr,
+ flags,
+ lpc);
+ }
+ for( lpc = 0; lpc < float_registers; lpc++ )
+ {
+ attr = "Rfloat|Rdouble";
+ flags = "0";
+ if( lpc in float_register_attributes )
+ attr = float_register_attributes[lpc];
+ if( lpc in float_register_flags )
+ flags = float_register_flags[lpc];
+ printf("\t{ /* fpr%d */\t0, 0, %s,\t%s, 0, %d }, \\\n",
+ lpc,
+ attr,
+ flags,
+ int_registers + lpc);
+ }
+ printf("\n");
+ printf("#define NR_REGISTERS %d\n", int_registers + float_registers);
+ printf("\n");
+ printf("#endif\n");
+}
+
+function sizemask(size, lpc, retval)
+{
+ retval = (2 ^ size) - 1;
+ return retval;
+}
More information about the kaffe
mailing list