#!/usr/bin/perl -w
#===============================================================================
#
# d/wilson_d500/tr.pl 
#
#-------------------------------------------------------------------------------
#
# Copyright (C) 2006 Thomas Streuer 
#
# This file is part of BQCD -- Berlin Quantum ChromoDynamics program
#
# BQCD 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 3 of the License, or
# (at your option) any later version.
#
# BQCD 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 BQCD.  If not, see <http://www.gnu.org/licenses/>.
#
#-------------------------------------------------------------------------------


$jupp=0;
$stack_offs = 111;
my $dummy;

sub sec_offs
{
    my $r=shift;
    return $stack_offs+8*($r+8);
}

sub scratch_offs
{
    my $n=shift;
    return $stack_offs+8*$n;
}


while (<STDIN>) {
    if (/JUPP/) {
	($stack_offs)=/JUPP(.*)/;
	$jupp=1;
	next;
    }
    unless ($jupp) {
	print;
	next;
    }
    if (($c, $t, $a, $b)=/(stfpdux|stfpdx)(.*),(.*),(.*)/) {
	$c=~s/stfpd/stfd/g;
	printf "stfd    $t, %i(1)\n", scratch_offs(0);
	printf "lfd     $t, %i(1)\n", sec_offs($t);
	printf "addi    $b, $b, 8\n";
	printf "stfdx   $t, $a, $b\n";
	printf "addi    $b, $b, -8\n";
	printf "lfd     $t, %i(1)\n", scratch_offs(0);
	printf "$c      $t, $a, $b\n";
	next;
    }
    if (($c, $t, $a, $b)=/(lfpdux|lfpdx)(.*),(.*),(.*)/) {
	$c=~s/lfpd/lfd/g;
	printf "addi    $b, $b, 8\n";
	printf "lfdx    $t, $a, $b\n";
	printf "addi    $b, $b, -8\n";
	printf "stfd    $t, %i(1)\n", sec_offs($t);
	printf "$c      $t, $a, $b\n";
	next;
    }	
    if (($c, $t, $a, $b)=/(lfxdux|lfxdx)(.*),(.*),(.*)/) {
#	$c=~s/lfxd/lfd/g;
	printf "lfdx    $t, $a, $b\n";
	printf "stfd    $t, %i(1)\n", sec_offs($t);
	printf "addi    $b, $b, 8\n";
	printf "lfdx    $t, $a, $b\n";
	printf "addi    $b, $b, -8\n";
	printf "add     $a, $a, $b\n" if $c eq "lfxdux";
	
	next;
    }	

    if (($cmd, $t, $a, $c, $dummy, $b)=/(fxcpmadd|fxcpnmadd|fxpmul)([^,]*),([^,]*),([^,]*)(,([^,]*))?/) {

#	print " >>> $_\n";
#printf "$cmd - $t - $a - $c - $dummy - $b\n";
	printf "stfd    0, %i(1)\n", scratch_offs(0);
	printf "stfd    1, %i(1)\n", scratch_offs(1);
	printf "stfd    2, %i(1)\n", scratch_offs(2);
	printf "stfd    3, %i(1)\n", scratch_offs(3);
	printf "fmr     0, $a\n";
	printf "lfd     1, %i(1)\n", sec_offs($b) if $b;
	printf "lfd     2, %i(1)\n", sec_offs($c);
	printf "fma     3, 0, 2, 1\n"   if $cmd eq "fxcpmadd";
	printf "fnma    3, 0, 2, 1\n"   if $cmd eq "fxcpnmadd";
	printf "fmul    3, 0, 2\n"      if $cmd eq "fxpmul";
	printf "stfd    3, %i(1)\n", sec_offs($t);
	printf "lfd     0, %i(1)\n", scratch_offs(0);
	printf "lfd     1, %i(1)\n", scratch_offs(1);
	printf "lfd     2, %i(1)\n", scratch_offs(2);
	printf "lfd     3, %i(1)\n", scratch_offs(3);
	printf "fma     $t, $a, $c, $b\n"    if $cmd eq "fxcpmadd";
	printf "fnma    $t, $a, $c, $b\n"    if $cmd eq "fxcpnmadd";
	printf "fmul    $t, $a, $c\n"        if $cmd eq "fxpmul";
	next;
    }


    if (($cmd, $t, $a, $c, $b)=/(fxcxnpma|fxcxnsma)(.*),(.*),(.*),(.*)/) {
	printf "stfd    0, %i(1)\n", scratch_offs(0);
	printf "stfd    1, %i(1)\n", scratch_offs(1);
	printf "stfd    2, %i(1)\n", scratch_offs(2);
	printf "stfd    3, %i(1)\n", scratch_offs(3);
	printf "stfd    $b, %i(1)\n", scratch_offs(4);
	printf "fmr     2, $c\n";
	printf "lfd     0, %i(1)\n", sec_offs($c);
	printf "stfd    0, %i(1)\n", scratch_offs(5);


	printf "lfd     1, %i(1)\n", sec_offs($b);
	printf "lfd     0, %i(1)\n", sec_offs($a);
	printf "fma     3, 0, 2, 1\n" if $cmd eq "fxcxnpma";
	printf "fnmsub  3, 0, 2, 1\n" if $cmd eq "fxcxnsma";
	printf "stfd    3, %i(1)\n", sec_offs($t);
	printf "lfd     2, %i(1)\n", scratch_offs(5);
	printf "lfd     1, %i(1)\n", scratch_offs(4);
	printf "fnmsub  3, 0, 2, 1\n" if $cmd eq "fxcxnpma";
	printf "fma     3, 0, 2, 1\n" if $cmd eq "fxcxnsma";
	printf "stfd    3, %i(1)\n", scratch_offs(5);

	printf "lfd     0, %i(1)\n", scratch_offs(0);
	printf "lfd     1, %i(1)\n", scratch_offs(1);
	printf "lfd     2, %i(1)\n", scratch_offs(2);
	printf "lfd     3, %i(1)\n", scratch_offs(3);
	printf "lfd     $t, %i(1)\n", scratch_offs(5);
	next;
    }


    if (($cmd, $t, $a, $b)=/(fpadd|fpsub)(.*),(.*),(.*)/) {
	$cmd=~s/fp/f/g;
	printf "stfd    0, %i(1)\n", scratch_offs(0);
	printf "stfd    1, %i(1)\n", scratch_offs(1);
	printf "stfd    2, %i(1)\n", scratch_offs(2);
	printf "lfd     1, %i(1)\n", sec_offs($a);
	printf "lfd     2, %i(1)\n", sec_offs($b);
	printf "$cmd    0, 1, 2\n";
	printf "stfd    0, %i(1)\n", sec_offs($t);
	printf "lfd     0, %i(1)\n", scratch_offs(0);
	printf "lfd     1, %i(1)\n", scratch_offs(1);
	printf "lfd     2, %i(1)\n", scratch_offs(2);
	
	printf "$cmd    $t, $a, $b\n";
	next;
    }

    if (($cmd, $t, $a, $b, $c)=/(fxmadd|fxnmsub)(.*),(.*),(.*),(.*)/) {
	$cmd=~s/fx/f/g;
	printf "stfd    0, %i(1)\n", scratch_offs(0);
	printf "stfd    1, %i(1)\n", scratch_offs(1);
	printf "stfd    2, %i(1)\n", scratch_offs(2);
	printf "stfd    3, %i(1)\n", scratch_offs(3);

	printf "stfd    $a, %i(1)\n", scratch_offs(4);
	printf "stfd    $b, %i(1)\n", scratch_offs(5);
	printf "stfd    $c, %i(1)\n", scratch_offs(6);


	printf "lfd     0, %i(1)\n", scratch_offs(4);
	printf "lfd     1, %i(1)\n", sec_offs($b);
	printf "lfd     2, %i(1)\n", sec_offs($c);
	printf "$cmd    3, 0, 1, 2\n";

	printf "lfd     0, %i(1)\n", sec_offs($a);

	printf "stfd    3, %i(1)\n", sec_offs($t);

	printf "lfd     1, %i(1)\n", scratch_offs(5);
	printf "lfd     2, %i(1)\n", scratch_offs(6);

	printf "$cmd    3, 0, 1, 2\n";
	printf "stfd    3, %i(1)\n", scratch_offs(6);

	printf "lfd     0, %i(1)\n", scratch_offs(0);
	printf "lfd     1, %i(1)\n", scratch_offs(1);
	printf "lfd     2, %i(1)\n", scratch_offs(2);
	printf "lfd     3, %i(1)\n", scratch_offs(3);
	printf "lfd     $t, %i(1)\n", scratch_offs(6);

	next;
    }
    if (($cmd, $a, $b)=/(fsneg)(.*),(.*)/) {
	printf "stfd    0, %i(1)\n", scratch_offs(0);
	printf "stfd    1, %i(1)\n", scratch_offs(1);
	printf "lfd     1, %i(1)\n", sec_offs($b);
	printf "fneg    0, 1\n";
	printf "stfd    0, %i(1)\n", sec_offs($a);
	printf "lfd     0, %i(1)\n", scratch_offs(0);
	printf "lfd     1, %i(1)\n", scratch_offs(1);
	next;
    }
    if (($cmd, $a, $b)=/(fpmr)(.*),(.*)/) {
	printf "stfd    0, %i(1)\n", scratch_offs(0);
	printf "stfd    1, %i(1)\n", scratch_offs(1);
	printf "lfd     1, %i(1)\n", sec_offs($b);
	printf "fmr     0, 1\n";
	printf "stfd    0, %i(1)\n", sec_offs($a);
	printf "lfd     0, %i(1)\n", scratch_offs(0);
	printf "lfd     1, %i(1)\n", scratch_offs(1);
	printf "fmr     $a, $b\n";
	next;
    }
    print;
}
