[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