From 538d56bb75ad00b1841398e10e6563035bfde442 Mon Sep 17 00:00:00 2001 From: Jan Brittenson Date: Wed, 22 Sep 1993 08:48:59 -0700 Subject: [PATCH] Initial revision From-SVN: r5389 --- gcc/bi-defs.h | 47 ++++++++ gcc/bi-opname.c | 35 ++++++ gcc/bi-reverse.c | 61 +++++++++++ gcc/bytecode.def | 322 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 465 insertions(+) create mode 100644 gcc/bi-defs.h create mode 100644 gcc/bi-opname.c create mode 100644 gcc/bi-reverse.c create mode 100644 gcc/bytecode.def diff --git a/gcc/bi-defs.h b/gcc/bi-defs.h new file mode 100644 index 0000000..dbf32b8 --- /dev/null +++ b/gcc/bi-defs.h @@ -0,0 +1,47 @@ +/* Definitions for Bytecode Interpreter. + Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +struct node +{ + char *text; + struct node *next; +}; + +struct variation +{ + char *name; + int code; + struct node *inputs; + struct node *outputs; + struct node *literals; + struct variation *next; +}; + +struct def +{ + char *basename; + char *template; + struct variation *variations; + struct def *next; +}; + +extern struct def *defs; +extern int ndefs; +extern void reverse(); diff --git a/gcc/bi-opname.c b/gcc/bi-opname.c new file mode 100644 index 0000000..ac2d84a --- /dev/null +++ b/gcc/bi-opname.c @@ -0,0 +1,35 @@ +/* Utility to generate opcode name list from bytecode definition file. + Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "bi-defs.h" + +int +main() +{ + struct def *d; + struct variation *v; + + yyparse(); + reverse(); + + for (d = defs; d; d = d->next) + for (v = d->variations; v; v = v->next) + printf("\"%s%s\",\n", d->basename, v->name); + return 0; +} diff --git a/gcc/bi-reverse.c b/gcc/bi-reverse.c new file mode 100644 index 0000000..30eecba --- /dev/null +++ b/gcc/bi-reverse.c @@ -0,0 +1,61 @@ +/* Reverse order of definitions obtained from bytecode definition file. + Copyright (C) 1993 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +#include "bi-defs.h" + +#define NULL 0 + +void +reverse() +{ + struct def *dp, *d, *dn; + struct variation *vp, *v, *vn; + + dp = defs; + if (dp) + { + vp = dp->variations; + if (vp) + { + for (v = vp->next, vp->next = NULL; v; vp = v, v = vn) + { + vn = v->next; + v->next = vp; + } + dp->variations = vp; + } + for (d = dp->next, dp->next = NULL; d; dp = d, d = dn) + { + vp = d->variations; + if (vp) + { + for (v = vp->next, vp->next = NULL; v; vp = v, v = vn) + { + vn = v->next; + v->next = vp; + } + d->variations = vp; + } + dn = d->next; + d->next = dp; + } + defs = dp; + } +} diff --git a/gcc/bytecode.def b/gcc/bytecode.def new file mode 100644 index 0000000..5ac7284 --- /dev/null +++ b/gcc/bytecode.def @@ -0,0 +1,322 @@ +# -*- C -*- +# bytecode.def - definitions of bytecodes for the stack machine. + +# The production of the bytecode interpreter and compiler is +# heavily automated by using this file creatively. + +# Various elementary data types are understood by the bytecode interpreter. +# Q[IU] - quarter word (byte) signed and unsigned integers (char). +# H[IU] - half word signed and unsigned integers (short int, maybe int). +# S[IU] - single word signed and unsigned integers (maybe int, long int). +# D[IU] - double word signed and unsigned integers (long long int). +# SF - single precision floating point (float). +# DF - double precision floating point (double). +# XF - extended precision floating point (long double). +# P - pointer type for address arithmetic and other purposes. + +# The bytecode specification consists of a series of define_operator +# forms, that are parsed by preprocessors to automatically build +# various switch statements. +# define_operator(name, +# , +# ) +# The is self explanatory. +# The consists of a (parenthesized list) of +# variation items, each of which is in itself a list. A variation +# item consists of a name suffix, the types of the input arguments +# expected on the stack (shallowest item first) and (optionally) the +# types of the output arguments (similarly ordered). Finally, the +# types of the literal arguments (if any) may appear. + +# Substitution in the C prototype code is as follows: +# Substitution happens only after a dollar sign. To get a literal +# dollar sign (why would you ever want one anyway?) use $$. +# $R1 means "result 1" $TR1 means "type name of result one" +# $S1 means "source 1" and similarly with $TS1. +# $L1 means "literal (inline) argument 1" and $TL1 means type thereof. +# + +# Notice that the number following $R doesn't affect the push order; +# it's used only for clarity and orthogonality, although it's checked +# to make sure it doesn't exceed the number of outputs. A $R reference +# results in a push, and represents the result lvalue. E.g. + +# $R1 = 2\, $R2 = 17 +# will expand to: +# INTERP_PUSH($TR1) = 2, INTERP_PUSH($TR2) = 17 +# + +# Opcode 0 should never happen. +define_operator(neverneverland, abort\(\), (())) + +# Stack manipulations. +define_operator(drop, 0, ((, (SI)))) +define_operator(dup, 0, ((, (SI), (SI, SI)))) +define_operator(over, 0, ((, (SI), (SI, SI)))) + +# Adjust stack pointer + +define_operator(setstack, 0, ((SI,,,(SI)))) +define_operator(adjstack, 0, ((SI,,,(SI)))) + +# Constants, loads, and stores. +define_operator(const, + $R1 = $L1, + ((QI,, (QI), (QI)), (HI,, (HI), (HI)), + (SI,, (SI), (SI)), (DI,, (DI), (DI)), + (SF,, (SF), (SF)), (DF,, (DF), (DF)), + (XF,, (XF), (XF)), (P,, (P), (P)))) +define_operator(load, + $R1 = *\($TR1 *\) $S1, + ((QI, (P), (QI)), (HI, (P), (HI)), + (SI, (P), (SI)), (DI, (P), (DI)), + (SF, (P), (SF)), (DF, (P), (DF)), + (XF, (P), (XF)), (P, (P), (P)))) +define_operator(store, + *\($TS2 *\) $S1 = $S2, + ((QI, (P, QI)), (HI, (P, HI)), + (SI, (P, SI)), (DI, (P, DI)), + (SF, (P, SF)), (DF, (P, DF)), + (XF, (P, XF)), (P, (P, P)), + (BLK, (SI, BLK, BLK)))) + +# Clear memory block + +define_operator(clear, $S1 + $S2, ((BLK, (SI, BLK)))) + + +# Advance pointer by SI constant + +define_operator(addconst, $R1 = $S1, ((PSI, (P), (P), (SI)))) + + +# newlocalSI is used for creating variable-sized storage during function +# initialization. + +# Create local space, return pointer to block + +define_operator(newlocal, $R1 = $S1, ((SI, (SI), (P)))) + + +# Push the address of a local variable. +define_operator(local, $R1 = locals + $L1, ((P,, (P), (SI)))) + +# Push the address of an argument variable. +define_operator(arg, $R1 = args + $L1, ((P,, (P), (SI)))) + +# Arithmetic conversions. +define_operator(convert, + $R1 = \($TR1\) $S1, + (# Signed integral promotions (sign extensions). + (QIHI, (QI), (HI)), (HISI, (HI), (SI)), (SIDI, (SI), (DI)), + (QISI, (QI), (SI)), + # Unsigned integral promotions (zero extensions). + (QUHU, (QU), (HU)), (HUSU, (HU), (SU)), (SUDU, (SU), (DU)), + (QUSU, (QU), (SU)), + # Floating promotions. + (SFDF, (SF), (DF)), (DFXF, (DF), (XF)), + # Integral truncation. + (HIQI, (HI), (QI)), (SIHI, (SI), (HI)), (DISI, (DI), (SI)), + (SIQI, (SI), (QI)), + # Unsigned truncation. + (SUQU, (SU), (QU)), + # Floating truncation. + (DFSF, (DF), (SF)), (XFDF, (XF), (DF)), + # Integral conversions to floating types. + (SISF, (SI), (SF)), (SIDF, (SI), (DF)), (SIXF, (SI), (XF)), + (SUSF, (SU), (SF)), (SUDF, (SU), (DF)), (SUXF, (SU), (XF)), + (DISF, (DI), (SF)), (DIDF, (DI), (DF)), (DIXF, (DI), (XF)), + (DUSF, (DU), (SF)), (DUDF, (DU), (DF)), (DUXF, (DU), (XF)), + # Floating conversions to integral types. + (SFSI, (SF), (SI)), (DFSI, (DF), (SI)), (XFSI, (XF), (SI)), + (SFSU, (SF), (SU)), (DFSU, (DF), (SU)), (XFSU, (XF), (SU)), + (SFDI, (SF), (DI)), (DFDI, (DF), (DI)), (XFDI, (XF), (DI)), + (SFDU, (SF), (DU)), (DFDU, (DF), (DU)), (XFDU, (XF), (DU)), + # Pointer/integer conversions. + (PSI, (P), (SI)), (SIP, (SI), (P)))) + +# Truth value conversion. These are necessary because conversions of, e.g., +# floating types to integers may not function correctly for large values. +define_operator(convert, + $R1 = !!$S1, + ((SIT, (SI), (T)), (DIT, (DI), (T)), + (SFT, (SF), (T)), (DFT, (DF), (T)), + (XFT, (XF), (T)), (PT, (P), (T)))) + +# Bit field load/store. + +# Load and zero-extend bitfield + +define_operator(zxload, $R1 = $S1, ((BI, (SU, SU, P), (SU)))) + +# Load and sign-extend bitfield + +define_operator(sxload, $R1 = $S1, ((BI, (SU, SU, P), (SI)))) + +# Store integer in bitfield + +define_operator(sstore, $R1 = $S1, ((BI, (SU, SU, P, SI)))) + + +# Binary operations. +define_operator(add, + $R1 = $S1 + $S2, + ((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)), + (SF, (SF, SF), (SF)), (DF, (DF, DF), (DF)), + (XF, (XF, XF), (XF)), + (PSI, (P, SI), (P)))) +define_operator(sub, + $R1 = $S1 - $S2, + ((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)), + (SF, (SF, SF), (SF)), (DF, (DF, DF), (DF)), + (XF, (XF, XF), (XF)), + (PP, (P, P), (SI)))) +define_operator(mul, + $R1 = $S1 * $S2, + ((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)), + (SU, (SU, SU), (SU)), (DU, (DU, DU), (DU)), + (SF, (SF, SF), (SF)), (DF, (DF, DF), (DF)), + (XF, (XF, XF), (XF)))) +define_operator(div, + $R1 = $S1 / $S2, + ((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)), + (SU, (SU, SU), (SU)), (DU, (DU, DU), (DU)), + (SF, (SF, SF), (SF)), (DF, (DF, DF), (DF)), + (XF, (XF, XF), (XF)))) +define_operator(mod, + $R1 = $S1 % $S2, + ((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)), + (SU, (SU, SU), (SU)), (DU, (DU, DU), (DU)))) +define_operator(and, + $R1 = $S1 & $S2, + ((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)))) +define_operator(ior, + $R1 = $S1 | $S2, + ((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)))) +define_operator(xor, + $R1 = $S1 ^ $S2, + ((SI, (SI, SI), (SI)), (DI, (DI, DI), (DI)))) +define_operator(lshift, + $R1 = $S1 << $S2, + ((SI, (SI, SI), (SI)), (SU, (SU, SI), (SU)), + (DI, (DI, SI), (DI)), (DU, (DU, SI), (DU)))) +define_operator(rshift, + $R1 = $S1 >> $S2, + ((SI, (SI, SI), (SI)), (SU, (SU, SI), (SU)), + (DI, (DI, SI), (DI)), (DU, (DU, SI), (DU)))) +define_operator(lt, + $R1 = $S1 < $S2, + ((SI, (SI, SI), (T)), (SU, (SU, SU), (T)), + (DI, (DI, DI), (T)), (DU, (DU, DU), (T)), + (SF, (SF, SF), (T)), (DF, (DF, DF), (T)), + (XF, (XF, XF), (T)), (P, (P, P), (T)))) +define_operator(le, + $R1 = $S1 <= $S2, + ((SI, (SI, SI), (T)), (SU, (SU, SU), (T)), + (DI, (DI, DI), (T)), (DU, (DU, DU), (T)), + (SF, (SF, SF), (T)), (DF, (DF, DF), (T)), + (XF, (XF, XF), (T)), (P, (P, P), (T)))) +define_operator(ge, + $R1 = $S1 >= $S2, + ((SI, (SI, SI), (T)), (SU, (SU, SU), (T)), + (DI, (DI, DI), (T)), (DU, (DU, DU), (T)), + (SF, (SF, SF), (T)), (DF, (DF, DF), (T)), + (XF, (XF, XF), (T)), (P, (P, P), (T)))) +define_operator(gt, + $R1 = $S1 > $S2, + ((SI, (SI, SI), (T)), (SU, (SU, SU), (T)), + (DI, (DI, DI), (T)), (DU, (DU, DU), (T)), + (SF, (SF, SF), (T)), (DF, (DF, DF), (T)), + (XF, (XF, XF), (T)), (P, (P, P), (T)))) +define_operator(eq, + $R1 = $S1 == $S2, + ((SI, (SI, SI), (T)), (DI, (DI, DI), (T)), + (SF, (SF, SF), (T)), (DF, (DF, DF), (T)), + (XF, (XF, XF), (T)), (P, (P, P), (T)))) +define_operator(ne, + $R1 = $S1 != $S2, + ((SI, (SI, SI), (T)), (DI, (DI, DI), (T)), + (SF, (SF, SF), (T)), (DF, (DF, DF), (T)), + (XF, (XF, XF), (T)), (P, (P, P), (T)))) + +# Unary operations. +define_operator(neg, + $R1 = -$S1, + ((SI, (SI), (SI)), (DI, (DI), (DI)), + (SF, (SF), (SF)), (DF, (DF), (DF)), + (XF, (XF), (XF)))) +define_operator(not, + $R1 = ~$S1, + ((SI, (SI), (SI)), (DI, (DI), (DI)))) +define_operator(not, + $R1 = !$S1, + ((T, (SI), (SI)))) + +# Increment operations. +define_operator(predec, + $R1 = *\($TR1 *\) $S1 -= $S2, + ((QI, (P, QI), (QI)), (HI, (P, HI), (HI)), + (SI, (P, SI), (SI)), (DI, (P, DI), (DI)), + (P, (P, SI), (P)), (SF, (P, SF), (SF)), + (DF, (P, DF), (DF)), (XF, (P, XF), (XF)), + (BI, (SU, SU, P, SI), (SI)))) + +define_operator(preinc, + $R1 = *\($TR1 *\) $S1 += $S2, + ((QI, (P, QI), (QI)), (HI, (P, HI), (HI)), + (SI, (P, SI), (SI)), (DI, (P, DI), (DI)), + (P, (P, SI), (P)), (SF, (P, SF), (SF)), + (DF, (P, DF), (DF)), (XF, (P, XF), (XF)), + (BI, (SU, SU, P, SI), (SI)))) + +define_operator(postdec, + $R1 = *\($TR1 *\) $S1\, *\($TR1 *\) $S1 -= $S2, + ((QI, (P, QI), (QI)), (HI, (P, HI), (HI)), + (SI, (P, SI), (SI)), (DI, (P, DI), (DI)), + (P, (P, SI), (P)), (SF, (P, SF), (SF)), + (DF, (P, DF), (DF)), (XF, (P, XF), (XF)), + (BI, (SU, SU, P, SI), (SI)))) + +define_operator(postinc, + $R1 = *\($TR1 *\) $S1\, *\($TR1 *\) $S1 += $S2, + ((QI, (P, QI), (QI)), (HI, (P, HI), (HI)), + (SI, (P, SI), (SI)), (DI, (P, DI), (DI)), + (P, (P, SI), (P)), (SF, (P, SF), (SF)), + (DF, (P, DF), (DF)), (XF, (P, XF), (XF)), + (BI, (SU, SU, P, SI), (SI)))) + +# Jumps. +define_operator(jumpif, if \($S1\) pc = code->pc0 + $L1, ((, (T),, (SI)))) +define_operator(jumpifnot, if \(! $S1\) pc = code->pc0 + $L1, ((, (T),, (SI)))) +define_operator(jump, pc = code->pc0 + $L1, ((,,,(SI)))) + +# This is for GCC2. It jumps to the address on the stack. +define_operator(jump, pc = \(void *\) $S1, ((P,,))) + +# Switches. In order to (eventually) support ranges we provide four different +# varieties of switches. Arguments are the switch index from the stack, the +# bytecode offset of the switch table, the size of the switch table, and +# the default label. +define_operator(caseSI, CASESI\($S1\, $L1\, $L2\, $L3\), ((, (SI),, (SI, SI, SI)))) +define_operator(caseSU, CASESU\($S1\, $L1\, $L2\, $L3\), ((, (SU),, (SI, SI, SI)))) +define_operator(caseDI, CASEDI\($S1\, $L1\, $L2\, $L3\), ((, (DI),, (SI, SI, SI)))) +define_operator(caseDU, CASEDU\($S1\, $L1\, $L2\, $L3\), ((, (DU),, (SI, SI, SI)))) + +# Procedure call. +# Stack arguments are (deepest first): +# procedure arguments in reverse order. +# pointer to the place to hold the return value. +# address of the call description vector. +# pointer to the procedure to be called. +define_operator(call, CALL\($S1\, $S2\, $S3\, sp\), ((, (P, P, P)))) + +# Procedure return. +# Pushes on interpreter stack: +# value of retptr (pointer to return value storage slot) +define_operator(return, $R1 = retptr, ((P,,(P)))) + +# Really return. +define_operator(ret, return, (())) + +# Print an obnoxious line number. +define_operator(linenote, fprintf\(stderr\, "%d\\n"\, $L1\), ((,,,(SI)))) -- 2.7.4