#! /usr/bin/perl

#
# Convert MAL to TAL. Note: This parser does NOT do label parsing!!
# It's output is intended to be passed to mipsasm.
#
#
# These pseudos are expanded as follows
#
# nop => 
#  sll $0 $0 0
#
# la $reg label => 
#  lui $reg label
#  ori $reg $reg label
#
#
#
# move $r1 $r2 =>
#  or $r1 $r2 $0
#
 

use Getopt::Long;

$USAGE = '  Command Line Options:
    -v[erbose]             -- Optional; Print helpful info to stdout
    -h[elp]                -- Optional; Print help on assembly
    -i[nputfile]           -- File that contains MIPS assembly
    -o[outputfile]         -- File in which to write machine code
  Usage:
    mal2tal [-v] -i <filename> -o <filename>
';

do_get_args();
do_open_files();
do_parse_input();
print "[*] mal2tal has finished successfully. $replacements replacement(s) made.\n";
exit(0);

###############################################

sub do_get_args() {
    #defaults
    $verbose = 0;
    $in_file = "";
    $out_file = "";
    $need_help = "";

    $num_args = $#ARGV;
    $ops = GetOptions("verbose" => \$verbose,
		      "help" => \$need_help,
		      "inputfile=s" => \$in_file,
		      "outputfile=s" => \$out_file);

    if ($need_help ne "") {
	print "Sorry, help not written yet!\n\n";
	print "$USAGE";
	exit(0);
    } elsif ($in_file eq "") {
	print "You must specify an input file with -i\n\n";
	print "$USAGE";
	exit(1);
    } elsif ($out_file eq "") {
	print "You must specify an output file with -o\n\n";
	print "$USAGE";
	exit(1);
    }

    print "[*] Starting mal2tal:\n" if $verbose;
    print "     Options: verbose=$verbose" .
	  "inputfile=$in_file outputfile=$out_file\n" if $verbose;

}

sub do_open_files() {
    if (!(-e $in_file)) {
	print "FATAL ERROR: Cannot find input file \"$in_file\"\n";
	exit(1);
    } elsif (!open(IN, "<$in_file")) {
	print "FATAL ERROR: Cannot open input file \"$in_file\": $!\n";
	exit(1);
    }
    if (!open(OUT, ">$out_file")) {
	print "Cannot open output file \"$out_file\": $!\n";	
    }
}

sub do_parse_input() {
    $line_counter = 0;
    $replacements = 0;
    while ($line = <IN>) {
	$line_counter++;
	chomp $line;
	$line_orig = $line;

	$line =~ s/\#.*$//; #Get rid of comments
	$line =~ s/,/ /g;   #I hate commas!
	$line =~ s/\s+/ /g; #Make all whitespace one character
	
	if ($line =~ /nop\s*$/) {
	    $replacements++;
	    print "     Line $line_counter: Replacing \"nop\" with \"sll \$0 \$0 0\"\n"
		if $verbose;
	    $line_orig =~ s/nop/sll \$0 \$0 0/;
	    print OUT $line_orig . "\n";
	} elsif ($line =~ /la\s+\$(\S+)\s+(\S+)\s*$/) {
	    $reg = $1; $label = $2;
	    $replacements++;
	    print "     Line $line_counter: Replacing " . 
		  "\"la \$$1 $2\" with \"lui \$$1; ori \$$1 \$$1 $2\"\n" if $verbose;
	    $temp = $line_orig;
	    $line_orig =~ s/la/lui/;
	    print OUT $line_orig . "\n";
	    $temp =~ /^(.*)la/;
	    $whitespace = $1;
	    $whitespace =~ s/\S/ /g;
	    print OUT "${whitespace}ori \$$reg \$$reg $label # Pseudoexpansion of la\n";
	} elsif ($line =~ /move\s+\$(\S+)\s+\$(\S+)\s*$/) {
	    $reg1 = $1; $reg2 = $2;
	    $replacements++;
	    print "     Line $line_counter: Replacing " . 
		  "\"move \$$reg1 \$$reg2\" with \"or \$$reg1 \$$reg2 \$0\"\n" if $verbose;
	    $line =~ /^(.*)move/;
	    $leader = $1;
	    print OUT "${leader}or \$$reg1 \$$reg2 \$0 # Pseudoexpansion of move\n";
	} else {
	    print OUT $line_orig . "\n";
	}
    }
}

	    

