Update of /cvsroot/pure-data/externals/pdp/scaf/compiler In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6756/scaf/compiler
Added Files: Makefile kernel.scaf optim.rules scafc scafc.pl scafmacro.s Log Message: checking in pdp 0.12.4 from http://zwizwa.fartit.com/pd/pdp/pdp-0.12.4.tar.gz
--- NEW FILE: scafmacro.s --- # Pure Data Packet - scaf assembler macros. # Copyright (c) by Tom Schouten pdp@zzz.kotnet.org # # This program 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 of the License, or # (at your option) any later version. # # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
# this file contains pure asm macros. it is to be included before assembly # after scaforth.pl has processed the .scaf file
# *************************** JMP CALL RET ************************************** # j c r .macro j address jmp \address .endm
.macro c address call \address .endm
.macro r ret .endm
# *************************** CA CELL ACCESS MACROS ***************************** # dropldTL - dropldBR
# shift / load rectangle macros:
# shift rectangle horizontal # result is in reg1 .macro shift reg1 reg2 count psllq $(16-\count), \reg1 psrlq $(16+\count), \reg2 psrlq $32, \reg1 psllq $32, \reg2 por \reg2, \reg1 .endm
.macro ldtop reg1 reg2 movq (%edi), \reg1 movq 8(%edi), \reg2 .endm
.macro ldcenter reg1 reg2 movq 8(%edi), \reg1 movq 16(%edi), \reg2 .endm
.macro ldbottom reg1 reg2 movq 16(%edi), \reg1 movq 24(%edi), \reg2 .endm
# dropld from top row
# dropld the top left square .macro dropldTL ldtop %mm0, %mm1 shift %mm0, %mm1, -1 .endm
# dropld the top mid square .macro dropldTM ldtop %mm0, %mm1 shift %mm0, %mm1, 0 .endm
# dropld the top right square .macro dropldTR ldtop %mm0, %mm1 shift %mm0, %mm1, 1 .endm
# dropld from center row
# dropld the mid left square .macro dropldML ldcenter %mm0, %mm1 shift %mm0, %mm1, -1 .endm
# dropld the mid mid square .macro dropldMM ldcenter %mm0, %mm1 shift %mm0, %mm1, 0 .endm
# dropld the mid right square .macro dropldMR ldcenter %mm0, %mm1 shift %mm0, %mm1, 1 .endm
# dropld from bottom row
# dropld the bottom left square .macro dropldBL ldbottom %mm0, %mm1 shift %mm0, %mm1, -1 .endm
# dropld the bottom mid square .macro dropldBM ldbottom %mm0, %mm1 shift %mm0, %mm1, 0 .endm
# dropld the bottom right square .macro dropldBR ldbottom %mm0, %mm1 shift %mm0, %mm1, 1 .endm
# *************************** CA STACK MANIP MACROS ***************************** # these are the only asm macros that have a stack effect other than # just replacing the TOS # # dup drop dropdup swap nip dropover
.macro dup lea -8(%esi), %esi movq %mm0, (%esi) .endm
.macro drop movq (%esi), %mm0 lea 8(%esi), %esi .endm
.macro dropdup movq (%esi), %mm0 .endm
.macro nipdup movq %mm0, (%esi) .endm
.macro swap movq (%esi), %mm1 movq %mm0, (%esi) movq %mm1, %mm0 .endm
.macro nip lea 8(%esi), %esi .endm
.macro dropover movq 8(%esi), %mm0 .endm
# *************************** CA BOOLEAN LOGIC MACROS ***************************** # overxor overand overor not .macro overxor pxor (%esi), %mm0 .endm
.macro overand pand (%esi), %mm0 .endm
.macro overor por (%esi), %mm0 .endm
.macro not pxor %mm3, %mm0 .endm
# *************************** CONSTANTS ***************************** # dropzero dropone
.macro dropzero pxor %mm0, %mm0 .endm
.macro dropone pcmpeqw %mm0, %mm0 .endm # *************************** 4 BIT REG ACCESS ****************************** # dupsta0 - dupsta4 droplda0 - droplda4 # store bit in accumulator
# bit store .macro dupsta0 movq %mm0, %mm4 .endm
.macro dupsta1 movq %mm0, %mm5 .endm .macro dupsta2 movq %mm0, %mm6 .endm .macro dupsta3 movq %mm0, %mm7 .endm
# load bit from accumulator
.macro droplda0 movq %mm4, %mm0 .endm
.macro droplda1 movq %mm5, %mm0 .endm .macro droplda2 movq %mm6, %mm0 .endm
.macro droplda3 movq %mm7, %mm0 .endm
# *************************** LOAD 4 BIT CONSTANT IN REG ****************************** # a0000 - a1111 .macro ldbit0 value .ifeq \value movq %mm1, %mm4 .else movq %mm3, %mm4 .endif .endm
.macro ldbit1 value .ifeq \value movq %mm1, %mm5 .else movq %mm3, %mm5 .endif .endm
.macro ldbit2 value .ifeq \value movq %mm1, %mm6 .else movq %mm3, %mm6 .endif .endm
.macro ldbit3 value .ifeq \value movq %mm1, %mm7 .else movq %mm3, %mm7 .endif .endm
.macro ldbin b3 b2 b1 b0 pxor %mm1, %mm1 ldbit0 \b0 ldbit1 \b1 ldbit2 \b2 ldbit3 \b3 .endm .macro a0000 ldbin 0 0 0 0 .endm
.macro a0001 ldbin 0 0 0 1 .endm
.macro a0010 ldbin 0 0 1 0 .endm
.macro a0011 ldbin 0 0 1 1 .endm
.macro a0100 ldbin 0 1 0 0 .endm
.macro a0101 ldbin 0 1 0 1 .endm
.macro a0110 ldbin 0 1 1 0 .endm
.macro a0111 ldbin 0 1 1 1 .endm
.macro a1000 ldbin 1 0 0 0 .endm
.macro a1001 ldbin 1 0 0 1 .endm
.macro a1010 ldbin 1 0 1 0 .endm
.macro a1011 ldbin 1 0 1 1 .endm
.macro a1100 ldbin 1 1 0 0 .endm
.macro a1101 ldbin 1 1 0 1 .endm
.macro a1110 ldbin 1 1 1 0 .endm
.macro a1111 ldbin 1 1 1 1 .endm
# *************************** 4 BIT COUNTER ****************************** # adds TOS to bit of counter and returns carry in TOS # # adb0 - adb3
.macro adb0 movq %mm4, %mm2 pxor %mm0, %mm4 pand %mm2, %mm0 .endm
.macro adb1 movq %mm5, %mm2 pxor %mm0, %mm5 pand %mm2, %mm0 .endm
.macro adb2 movq %mm6, %mm2 pxor %mm0, %mm6 pand %mm2, %mm0 .endm
.macro adb3 movq %mm7, %mm2 pxor %mm0, %mm7 pand %mm2, %mm0 .endm
# *************************** ACCUMULATOR TESTS *************************** # dropisnonzero4 - dropisnonzero1
.macro dropisnonzero4 movq %mm4, %mm0 por %mm5, %mm0 por %mm6, %mm0 por %mm7, %mm0 .endm .macro dropisnonzero3 movq %mm4, %mm0 por %mm5, %mm0 por %mm6, %mm0 .endm .macro dropisnonzero2 movq %mm4, %mm0 por %mm5, %mm0 .endm .macro dropisnonzero1 movq %mm4, %mm0 .endm
# *************************** REGISTER SHIFT OPERATIONS ********************** # shift and leave shifted out byte on stack # rotate trough top of stack
.macro dropshiftright movq %mm4, %mm0 movq %mm5, %mm4 movq %mm6, %mm5 movq %mm7, %mm6 pxor %mm7, %mm7 .endm
.macro dropshiftleft movq %mm7, %mm0 movq %mm6, %mm7 movq %mm5, %mm6 movq %mm4, %mm5 pxor %mm4, %mm4 .endm
.macro dropshiftrighta movq %mm4, %mm0 movq %mm5, %mm4 movq %mm6, %mm5 movq %mm7, %mm6 .endm
.macro rotateright movq %mm4, %mm1 movq %mm5, %mm4 movq %mm6, %mm5 movq %mm7, %mm6 movq %mm1, %mm7 .endm
.macro rotateleft movq %mm7, %mm1 movq %mm6, %mm7 movq %mm5, %mm6 movq %mm4, %mm5 movq %mm1, %mm4 .endm
.macro rotaterightstack movq %mm0, %mm1 movq %mm4, %mm0 movq %mm5, %mm4 movq %mm6, %mm5 movq %mm7, %mm6 movq %mm1, %mm7 .endm
.macro rotateleftstack movq %mm0, %mm1 movq %mm7, %mm0 movq %mm6, %mm7 movq %mm5, %mm6 movq %mm4, %mm5 movq %mm1, %mm4 .endm
# *************************** OTHER REGISTER OPERATIONS ********************** # anot : complement reg (can be used to implement subtraction)
.macro anot pxor %mm3, %mm4 pxor %mm3, %mm5 pxor %mm3, %mm6 pxor %mm3, %mm7 .endm
--- NEW FILE: kernel.scaf --- ( Pure Data Packet - scaforth kernel. ) ( Copyright (c) by Tom Schouten pdp@zzz.kotnet.org ) ( ) ( This program 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 of the License, or ) ( [at your option] any later version. ) ( ) ( This program 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 this program; if not, write to the Free Software ) ( Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. )
( this file contains the inline words in the scaforth kernel. ) ( when a file is compiled to asm, it will consist of word ) ( definition asm routines, macros and jmp call ret instructions. ) ( ) ( all words in this file are defined in terms of asm macros ) ( defined in scafmacros.s )
( stack manip words )
: over dup dropover ;
( neighbourhood cell fetch words )
: @-+ dup dropldTL ; : @0+ dup dropldTM ; : @++ dup dropldTR ; : @-0 dup dropldML ; : @00 dup dropldMM ; : @+0 dup dropldMR ; : @-- dup dropldBL ; : @0- dup dropldBM ; : @+- dup dropldBR ;
( boolean logic )
: or overor nip ; : xor overxor nip ; : and overand nip ;
( binary constant loading )
: 1 dup dropone ; : 0 dup dropzero ;
( 4,3,2,1 bit add stack to register, leave carry on stack )
: ++++ adb0 adb1 adb2 adb3 ; : +++ adb0 adb1 adb2 ; : ++ adb0 adb1 ; : + adb0 ;
( 4,3,2 bit shifted 1 add )
: ++++<<1 adb1 adb2 adb3 ; : +++<<1 adb1 adb2 ; : ++<<1 adb1 ;
( 4,3 bit shifted 2 add )
: ++++<<2 adb2 adb3 ; : +++<<2 adb2 ;
( 4 bit shifted 3 add )
: ++++<<3 adb3 ;
( 4 bit accumulator access )
: !a0 dupsta0 drop ; : !a1 dupsta1 drop ; : !a2 dupsta2 drop ; : !a3 dupsta3 drop ;
: @a0 dup droplda0 ; : @a1 dup droplda1 ; : @a2 dup droplda2 ; : @a3 dup droplda3 ;
( 4,3,2,1 bit accumulator zero tests )
: ?anz dup dropisnonzero4 ; : ?anz4 dup dropisnonzero4 ; : ?anz3 dup dropisnonzero3 ; : ?anz2 dup dropisnonzero2 ; : ?anz1 dup dropisnonzero1 ;
( load constants into accumulator )
: a0 a0000 ; : a-0 a0000 ; : a+0 a0000 ; : a+1 a0001 ; : a+2 a0010 ; : a+3 a0011 ; : a+4 a0100 ; : a+5 a0101 ; : a+6 a0110 ; : a+7 a0111 ;
: a+8 a1000 ; : a+9 a1001 ; : a+10 a1010 ; : a+11 a1011 ; : a+12 a1100 ; : a+13 a1101 ; : a+14 a1110 ; : a+15 a1111 ;
: a-8 a1000 ; : a-7 a1001 ; : a-6 a1010 ; : a-5 a1011 ; : a-4 a1100 ; : a-3 a1101 ; : a-2 a1110 ; : a-1 a1111 ;
--- NEW FILE: scafc --- #!/bin/sh #scaf->scafo compiler
if test "xx$1" == "xx" then echo echo "scaf rules compiler" echo "usage:" echo " scafc source [dest]" echo exit 0 fi
if test "xx$2" == "xx" then DEST=$1o else DEST=$2 fi
if ! test -f $1 then echo "source module $1 not found." exit 1 fi
SCAFDIR=`dirname $0` if ! test -f $SCAFDIR/scafc.pl; then SCAFDIR=`dirname $SCAFDIR` SCAFDIR="$SCAFDIR/lib/scaf" if ! test -f $SCAFDIR/scafc.pl then echo "scaf library not found in $SCAFDIR" exit 1 fi fi
TMP_S=`tempfile -s .s` $SCAFDIR/scafc.pl -I$SCAFDIR $1 > $TMP_S \ && gcc -export_dynamic -shared -o $DEST $TMP_S \ && strip --strip-unneeded $DEST \ && rm $TMP_S \ || exit 1
--- NEW FILE: Makefile --- all:
clean: rm -f *~ rm -f *.o
--- NEW FILE: scafc.pl --- #!/usr/bin/perl
# Pure Data Packet - scafc: scaf compiler. # Copyright (c) by Tom Schouten pdp@zzz.kotnet.org # # This program 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 of the License, or # (at your option) any later version. # # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
# set this if you want to enable/disable optimizing
$optimize = 1;
# this parses a single scaf line # it is not very intelligent. only looks for 1 def on a line # todo: change later so it can read multiple lines
sub remove_illegal_characters { my $line = shift; $$line =~ s/+/_PLUS_/g; $$line =~ s/-/_MINUS_/g; $$line =~ s/@/_AT_/g; $$line =~ s/:/_COLON_/g; $$line =~ s/?/_QMARK_/g; $$line =~ s/<</_SHIFT_/g; $$line =~ s/</_ST_/g; $$line =~ s/>/_GT_/g; $$line =~ s/=/_EQ_/g; $$line =~ s/(/_OPEN_/g; $$line =~ s/)/_CLOSE_/g; }
sub parse_scaf_line { my $word, $def, $sub; shift;
# this transforms the source into a parsed assembly like form # a word label: "<word>:<ret>" # a word definition line "<tab><word><ret>" # last def = <ret><ret>
# dont process if line doesn't have a def
# first remove comments s/(\s+(\S+\s+)*?)//g;
if (m/:\s+/){
# separate word and definition m/:\s+(\S+)\s+(.*)/; $word = $1; $def = $2;
# remove illegal characters; remove_illegal_characters $word; remove_illegal_characters $def;
# format definition in asm style $def =~ s/(\S+)(\s*)/\t$1\n/g;
# replace ; by r $def =~ s/\s+;\s*/\n\tr\n/;
# put word: def into one string $sub = "$word:\n$def\n";
# debug #$sub =~ s/\t/<tab>/g; #$sub =~ s/\n/<ret>\n/g; #print "$sub";
return $sub;
}
};
# load and parse scaf source file sub load_source { my $filename = shift; open(SOURCE, $filename) or die "Can't locate source module $filename\n"; my @parsedsource; while (<SOURCE>){ my $sub = parse_scaf_line $_; if ($sub) { push @parsedsource, ($sub); }
} close(SOURCE); return @parsedsource;
}
# this routine parses the optimization rules sub load_optim { my $filename = shift; open(OPTIM, $filename) or die "Can't locate optimization rule file $filename\n"; my @parsedoptim; while (<OPTIM>){ unless (m/\A#/){
if (m/"\s*(.*?)\s*".*?"\s*(.*?)\s*"/) { my $source = $1; my $dest = $2;
$source =~ s/\s+/\n\t/; $dest =~ s/\s+/\n\t/; $source = "\t$source\n"; $dest = "\t$dest\n";
remove_illegal_characters $source; remove_illegal_characters $dest;
push @parsedoptim, ("$source:$dest"); } } } close(OPTIM);
return @parsedoptim;
}
# inline one parsed source's definitions into another parsed source's sub inline_defs { my $dest = shift; my $source = shift;
#print @$dest; #print @$source;
# loop over file with inline defs foreach (@$source) { #print "<SUB>$_</SUB>\n"; m/(\S+):\n(.*)\tr\n/s;
my $def = "\t$1\n"; my $body = $2;
#print "<DEF>$def</DEF>\n"; #print "<BODY>$body</BODY>\n";
foreach (@$dest) { s/$def/$body/g; } }
}
# this changes <WORD> to c <WORD> or j <WORD> all defined words # the undefined words are supposed to be asm macros sub call_defs { my $dest = shift;
foreach (@$dest){ m/(\S+):\n/s; my $word = $1; foreach (@$dest){ s/\t$word\n\tr\n/\tj $word\n/sg; s/\t$word\n/\tc $word\n/sg; } } }
# substitue word sequences in dest using optim table sub subst_optim { my $dest = shift; my $optim = shift; foreach (@$optim){ m/(.*?):(.*)/s; my $key = $1; my $subst = $2; foreach (@$dest){ s/$key/$subst/sg; } } } # add directives to produce global symbols # global symbols need to start with carule_ sub global_syms { my $source = shift; foreach (@$source){ s/rule_(\S+):\n/.globl\trule_$1\n.type\trule_$1,@function\nrule_$1:\n/sg; } }
# create an array with names for bookkeeping sub name_array { my @namearray; my $source = shift; push @namearray, (".globl rulenames\nrulenames:\n"); foreach (@$source){ if (m/rule_(\S+):/s){ push @namearray, (".asciz\t"$1"\n"); } } push @namearray, (".byte\t0\n"); return @namearray;
}
# main program body
$dir=".";
$source = "-";
# parse command line foreach (@ARGV){ if (m/-I(.*)/) { $dir = $1; } else { $source = $_; } }
$kernel = "$dir/kernel.scaf"; $macro = "$dir/scafmacro.s"; $rules = "$dir/optim.rules";
# load files @psource = load_source $source; @pkernel = load_source $kernel; @poptim = load_optim $rules;
# substitute kernel defs in source if ($optimize) {subst_optim @psource, @poptim;} inline_defs @psource, @pkernel;
if ($optimize) {subst_optim @psource, @poptim;}
call_defs @psource; global_syms @psource; @pnames = name_array @psource;
# print out asm file print ".include "$macro"\n\n"; print @psource; print @pnames;
--- NEW FILE: optim.rules --- # Pure Data Packet - scaf optimization rules. # Copyright (c) by Tom Schouten pdp@zzz.kotnet.org # # This program 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 of the License, or # (at your option) any later version. # # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# this file contains scaf source optimization rules for scaf compiler # applied after kernel word inlining and before compilation to asm
# one rule that's not in here, and is the responsability for the # final compilation step: "word ;" is "jmp word" instead of "call word ret"
# TODO: think about order!
# no discrimination between pre inline and post inline optimization ops yet
# pre inline optimizations
"over xor" -> "overxor" "over and" -> "overand" "over or" -> "overor"
"drop 1" -> "dropone" "drop 0" -> "dropzero" "over add" -> "overadd" "over addc" -> "overaddc"
"dup !a0" -> "dupsta0" "dup !a1" -> "dupsta1" "dup !a2" -> "dupsta2" "dup !a3" -> "dupsta3"
"drop @a0" -> "droplda0" "drop @a1" -> "droplda1" "drop @a2" -> "droplda2" "drop @a3" -> "droplda3"
"drop ?anz" -> "dropisnonzero4" "drop ?anz4" -> "dropisnonzero4" "drop ?anz3" -> "dropisnonzero3" "drop ?anz2" -> "dropisnonzero2" "drop ?anz1" -> "dropisnonzero1"
"drop @-+" -> "dropldTL" "drop @0+" -> "dropldTM" "drop @++" -> "dropldTR" "drop @-0" -> "dropldML" "drop @00" -> "dropldMM" "drop @+0" -> "dropldMR" "drop @--" -> "dropldBL" "drop @0-" -> "dropldBM" "drop @+-" -> "dropldBR"
# post inline optimizations
"dup drop" -> "" "swap drop" -> "nip" "dup swap" -> "dup" "drop dup" -> "dropdup" "drop over" -> "dropover" "nip dup" -> "nipdup"