#!/usr/bin/perl
#################################################################################
#										#
# rudimentary dump disassembler for PowerPC-VLE					#
# copyright (c) 2015-2016 Joerg Wolfram (joerg@jcwolfram.de)			#
#										#
# 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 3		#
# 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 library; if not, write to the				#
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,			#
# Boston, MA 02111-1307, USA.							#
#										#
#################################################################################
use POSIX;
use Fcntl;

$dumpfile="main.dump";
$disfile=">result.vleasm";

$code_size=0;
$write_addr=0;
$write_data=1;
$max_size=32768;
$max_addr=0;


for($i=0;$i<$max_size;$i++)
{
	$data[$i]=0xff;
}



#read dumpfile
open (DREAD, $dumpfile);
open (DASS, $disfile);
$mode=0;
while (<DREAD>)
{
	chomp();
	$line=$_;
	if(substr($line,0,13) eq "SYMBOL TABLE:")
	{
		printf("#symbol table found\n");
		$tmode=1;
	}
	if((substr($line,0,11) eq "Disassembly") && ($tmode > 0))
	{
		printf("#code section found\n");
		$tmode=2;
	}

	if(($line=~ /apuinfo/g) && ($tmode == 2))
	{
		printf("#code section end\n");
		$tmode=0;
	}
	
	if($mode==1)
	{
		$addr=uc(substr($line,0,8));
		$type=substr($line,15,1);
		$rel=substr($line,17,5);
		if($rel eq ".text")
		{
			$name=substr($line,32,length($line)-32);
#			printf "CODE: $addr ($name)\n";
			$code_symbols{$addr}=$name;
		}

		if(($rel eq "*ABS*") && ($addr ne "00000000"))
		{
			$name=substr($line,32,length($line)-32);
#			printf "ADDR: $addr ($name)\n";
			if($name=~ /_BASE/)
			{
				$addrh_symbols{$addr}=$name;
			}
			else
			{
				$addrl_symbols{$addr}=$name;
			}			
		}

		if($type eq "O")
		{
			$name=substr($line,32,length($line)-32);
#			printf "SBSS: $addr ($name)\n";
			$bss_symbols{$addr}=$name;
		}
	}
	
	if($mode==2)
	{
		if(substr($line,1,1) eq "0")	#we start a new segment
		{
			$aktaddr=sprintf("%u",hex(substr($line,0,8)));
#			printf $aktaddr."\n";
		}
		if(($line=~ /\t/) && (!($line=~ /\.\.\./)))
		{
			$line=$';
			$byte=sprintf("%u",hex(substr($line,0,2)));
			if($aktaddr < $max_size)
			{
#				printf "$aktaddr -> $byte ";
				$data[$aktaddr++]=$byte;
				
			}

			$byte=sprintf("%u",hex(substr($line,3,2)));
			if($aktaddr < $max_size)
			{
#				printf "$byte ";
				$data[$aktaddr++]=$byte;
				
			}

			$byte=sprintf("%u",hex(substr($line,6,2)));
			if($aktaddr < $max_size)
			{
#				printf "$byte ";
				$data[$aktaddr++]=$byte;
				
			}
			$byte=sprintf("%u",hex(substr($line,9,2)));
			
			if($aktaddr < $max_size)
			{
#				printf "$byte\n";
				$data[$aktaddr++]=$byte;
				if($aktaddr > $max_addr)
				{
					$max_addr=$aktaddr-1;
				}
			}		
		}
	
	}
	$mode=$tmode;
}

print "# $max_addr bytes read\n";

$addr=0;

do
{
	if($write_addr == 1)
	{
		printf DASS "%08X\t",$addr
	}

	$taddr=sprintf "%08X",$addr;
	$label=$code_symbols{$taddr};
	$label.=":";
	if($label ne ":")
	{
		printf DASS $label."\n";
	}
	printf DASS $taddr.":    ";

	&disass_code();
	
	print DASS "\n";

}while($addr < $max_addr);



close(DREAD);
close(DASS);


printf "Test: ".$code_symbols{"000024D0"}."\n";

sub disass_code
{
	$byte1=$data[$addr+0];
	$byte2=$data[$addr+1];
	$byte3=$data[$addr+2];
	$byte4=$data[$addr+3];
	$word1=256*$byte1+$byte2;
	$word2=256*$byte3+$byte4;

	if($addr==0)
	{
		w32();
		printf DASS (".dc 0x%02X%02X,0x%02X%02x\t\t;RHW",$data[$addr],$data[$addr+1],$data[$addr+2],$data[$addr+3]);
		$addr+=2;
	}
	elsif($addr==4)
	{
		w32();
		printf DASS (".dc 0x%02X%02X,0x%02X%02x\t\t;Reset vector",$data[$addr],$data[$addr+1],$data[$addr+2],$data[$addr+3]);
		$addr+=2;
	}
	elsif(($data[$addr+0]==0xff) && ($data[$addr+1]==0xff))
 	{
		w16();
		printf DASS (".dc 0xFFFF\t\t\t;no data");
		$addr+=2
	}
	elsif(($data[$addr+0]==0x00) && ($data[$addr+1]==0x00))
 	{
		w16();
		printf DASS (".dc 0x0000\t\t\t;illegal, padding");
		$addr+=2
	}

	else
	{

		#-----------------------------------------------------------------------------------------
		# add group
		#-----------------------------------------------------------------------------------------
		if(($word1 & 0xff00) == 0x0400)
		{
			&addcmd1("se_add    ");
		}
		if(($word1 & 0xfc00) == 0x1c00)
		{
			&addcmd2("e_add16i  ");
		}
		if((($word1 & 0xfc00) == 0x7000) && (($word2 & 0xF800) == 0x8800))
		{
			&addcmd3("e_add2i.  ");
		}
		if((($word1 & 0xfc00) == 0x7000) && (($word2 & 0xF800) == 0x9000))
		{
			&addcmd3("e_add2is  ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xF800) == 0x8000))
		{
			&addcmd4("e_addi    ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xF800) == 0x8800))
		{
			&addcmd4("e_addi.   ");
		}
		if((($word1 & 0xfc00) == 0x2000) && (($word1 & 0x0200) == 0x0000))
		{
			&addcmd5("se_addi   ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xF800) == 0x9000))
		{
			&addcmd4("e_addic   ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xF800) == 0x9800))
		{
			&addcmd4("e_addic.  ");
		}

		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x0214))
		{
			&addcmd22("add       ");
		}

		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x0215))
		{
			&addcmd22("add.      ");
		}

		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x0614))
		{
			&addcmd22("addo      ");
		}

		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x0615))
		{
			&addcmd22("addo.     ");
		}


		#-----------------------------------------------------------------------------------------
		# and group
		#-----------------------------------------------------------------------------------------
		if(($word1 & 0xff00) == 0x4600)
		{
			&addcmd1("se_and    ");
		}
		if(($word1 & 0xff00) == 0x4700)
		{
			&addcmd1("se_and.   ");
		}
		if((($word1 & 0xfc00) == 0x7000) && (($word2 & 0xF800) == 0xC800))
		{
			&addcmd3("e_and2i.  ");
		}
		if((($word1 & 0xfc00) == 0x7000) && (($word2 & 0xF800) == 0xE800))
		{
			&addcmd3("e_and2is  ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xF800) == 0xC000))
		{
			&addcmd4("e_andi    ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xF800) == 0xC800))
		{
			&addcmd4("e_andi.   ");
		}
		if(($word1 & 0xFE00) == 0x2E00)
		{
			&addcmd6("se_andi   ");
		}
		if(($word1 & 0xfF00) == 0x2500)
		{
			&addcmd1("se_and    ");
		}


		#-----------------------------------------------------------------------------------------
		# branch group
		#-----------------------------------------------------------------------------------------
		if((($word1 & 0xfe00) == 0x7800) && (($word2 & 0x0001) == 0x0000))
		{
			&addcmd7("e_b       ");
			print DASS "\n";
		}
		if((($word1 & 0xfe00) == 0x7800) && (($word2 & 0x0001) == 0x0001))
		{
			&addcmd7("e_bl      ");
		}
		if(($word1 & 0xff00) == 0xE800)
		{
			&addcmd8("se_b      ");
			print DASS "\n";
		}
		if(($word1 & 0xff00) == 0xE900)
		{
			&addcmd8("se_bl     ");
		}
		if((($word1 & 0xfff0) == 0x7A00) && (($word2 & 0x0001) == 0x0000))
		{
			&addcmd9("e_bne    ");
		}
		if((($word1 & 0xfff0) == 0x7A00) && (($word2 & 0x0001) == 0x0001))
		{
			&addcmd9("e_bnel    ");
		}
		if((($word1 & 0xfff0) == 0x7A10) && (($word2 & 0x0001) == 0x0000))
		{
			&addcmd9("e_beq    ");
		}
		if((($word1 & 0xfff0) == 0x7A10) && (($word2 & 0x0001) == 0x0001))
		{
			&addcmd9("e_beql    ");
		}
		if(($word1 & 0xff00) == 0xE200)
		{
			&addcmd8("se_bne    ");
		}
		if(($word1 & 0xff00) == 0xE600)
		{
			&addcmd8("se_beq    ");
		}


		#-----------------------------------------------------------------------------------------
		# bittest group
		#-----------------------------------------------------------------------------------------

		if(($word1 & 0xfe00) == 0x6000)
		{
			&addcmd24("se_bclri  ");
		}

		if(($word1 & 0xfe00) == 0x6200)
		{
			&addcmd24("se_bgeni  ");
		}

		if(($word1 & 0xfe00) == 0x6400)
		{
			&addcmd24("se_bseti  ");
		}

		if(($word1 & 0xfe00) == 0x6600)
		{
			&addcmd24("se_btsti  ");
		}


		#-----------------------------------------------------------------------------------------
		# compare group
		#-----------------------------------------------------------------------------------------
		if((($word1 & 0xfc00) == 0x7000) && (($word2 & 0xF800) == 0x9800))
		{
			&addcmd3("e_cmp16i  ");
		}

		if((($word1 & 0xff80) == 0x1800) && (($word2 & 0xF800) == 0xA800))
		{
			&addcmd25("e_cmpi    ");
		}

		if((($word1 & 0xff80) == 0x1880) && (($word2 & 0xF800) == 0xA800))
		{
			&addcmd25("e_cmpli   ");
		}

		if(($word1 & 0xff00) == 0x0C00)
		{
			&addcmd8("se_cmp    ");
		}

		if(($word1 & 0xff00) == 0x0E00)
		{
			&addcmd8("se_cmph   ");
		}

		if(($word1 & 0xff00) == 0x0F00)
		{
			&addcmd8("se_cmphl  ");
		}

		if(($word1 & 0xff00) == 0x0D00)
		{
			&addcmd8("se_cmpl   ");
		}



		#-----------------------------------------------------------------------------------------
		# extsb group
		#-----------------------------------------------------------------------------------------
		if(($word1 & 0xFFF0) == 0x00D0)
		{
			&addcmd19("se_extsb  ");
		}

		if(($word1 & 0xFFF0) == 0x00F0)
		{
			&addcmd19("se_extsh  ");
		}

		if(($word1 & 0xFFF0) == 0x00C0)
		{
			&addcmd19("se_extzb  ");
		}

		if(($word1 & 0xFFF0) == 0x00E0)
		{
			&addcmd19("se_extzh  ");
		}


		#-----------------------------------------------------------------------------------------
		# load immediate group
		#-----------------------------------------------------------------------------------------
		if((($word1 & 0xfc00) == 0x7000) && (($word2 & 0x8000) == 0x0000))
		{
			&addcmd10("e_li      ");
		}
		if((($word1 & 0xfc00) == 0x7000) && (($word2 & 0xF800) == 0xE000))
		{
			&addcmd11("e_lis     ");
		}
		if(($word1 & 0xf800) == 0x4800)
		{
			&addcmd12("se_li     ");
		}

		#-----------------------------------------------------------------------------------------
		# lbz group
		#-----------------------------------------------------------------------------------------
		if(($word1 & 0xfc00) == 0x3000)
		{
			&addcmd13("e_lbz     ");
		}
		if(($word1 & 0xf000) == 0x8000)
		{
			&addcmd14("se_lbz    ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xFF00) == 0x0000))
		{
			&addcmd15("e_lbzu    ");
		}


		#-----------------------------------------------------------------------------------------
		# lhz group
		#-----------------------------------------------------------------------------------------
		if(($word1 & 0xfc00) == 0x5800)
		{
			&addcmd13("e_lhz     ");
		}
		if(($word1 & 0xf000) == 0xA000)
		{
			&addcmd14("se_lhz    ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xFF00) == 0x0100))
		{
			&addcmd15("e_lhzu    ");
		}


		#-----------------------------------------------------------------------------------------
		# lwz group
		#-----------------------------------------------------------------------------------------
		if(($word1 & 0xfc00) == 0x5000)
		{
			&addcmd13("e_lwz     ");
		}
		if(($word1 & 0xf000) == 0xC000)
		{
			&addcmd14("se_lwz    ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xFF00) == 0x0200))
		{
			&addcmd15("e_lwzu    ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xFF00) == 0x0800))
		{
			&addcmd15("e_lmw     ");
		}

		#-----------------------------------------------------------------------------------------
		# lxxx group
		#-----------------------------------------------------------------------------------------
		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x00EE))
		{
			&addcmd22("lbzux     ");
		}

		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x00AE))
		{
			&addcmd22("lbzx      ");
		}

		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x026E))
		{
			&addcmd22("lhzux     ");
		}

		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x022E))
		{
			&addcmd22("lhzx      ");
		}


		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x006E))
		{
			&addcmd22("lwzux     ");
		}

		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x002E))
		{
			&addcmd22("lwzx      ");
		}


		#-----------------------------------------------------------------------------------------
		# mfsr group
		#-----------------------------------------------------------------------------------------
		if((($word1 & 0xfc1f) == 0x7C08) && (($word2 & 0xFFFF) == 0x02A6))
		{
			&addcmd17("mflr      ");
		}
		if((($word1 & 0xfc1f) == 0x7C09) && (($word2 & 0xFFFF) == 0x02A6))
		{
			&addcmd17("mfctr     ");
		}
		if((($word1 & 0xfc1f) == 0x7C1A) && (($word2 & 0xFFFF) == 0x02A6))
		{
			&addcmd17("mfsrr0    ");
		}
		if((($word1 & 0xfc1f) == 0x7C1B) && (($word2 & 0xFFFF) == 0x02A6))
		{
			&addcmd17("mfsrr1    ");
		}
		if((($word1 & 0xfc1f) == 0x7C00) && (($word2 & 0xFFFF) == 0x0026))
		{
			&addcmd17("mfcr      ");
		}
		if((($word1 & 0xfc1f) == 0x7C01) && (($word2 & 0xFFFF) == 0x02A6))
		{
			&addcmd17("mfxer     ");
		}


		#-----------------------------------------------------------------------------------------
		# mtsr group
		#-----------------------------------------------------------------------------------------
		if((($word1 & 0xfc1f) == 0x7C08) && (($word2 & 0xFFFF) == 0x03A6))
		{
			&addcmd17("mtlr      ");
		}
		if((($word1 & 0xfc1f) == 0x7C09) && (($word2 & 0xFFFF) == 0x03A6))
		{
			&addcmd17("mtctr     ");
		}
		if((($word1 & 0xfc1f) == 0x7C1A) && (($word2 & 0xFFFF) == 0x03A6))
		{
			&addcmd17("mtsrr0    ");
		}
		if((($word1 & 0xfc1f) == 0x7C1B) && (($word2 & 0xFFFF) == 0x03A6))
		{
			&addcmd17("mtsrr1    ");
		}
		if((($word1 & 0xfc1f) == 0x7C00) && (($word2 & 0xFFFF) == 0x0126))
		{
			&addcmd17("mtcr      ");
		}
		if((($word1 & 0xfc1f) == 0x7C01) && (($word2 & 0xFFFF) == 0x03A6))
		{
			&addcmd17("mtxer     ");
		}


		#-----------------------------------------------------------------------------------------
		# mult group
		#-----------------------------------------------------------------------------------------
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xF800) == 0xA000))
		{
			&addcmd4("e_mulli   ");
		}

		if((($word1 & 0xfc00) == 0x7000) && (($word2 & 0xF800) == 0xA000))
		{
			&addcmd4("e_mull2i  ");
		}



		#-----------------------------------------------------------------------------------------
		# neg/not group
		#-----------------------------------------------------------------------------------------
		if(($word1 & 0xFFF0) == 0x0030)
		{
			&addcmd19("se_neg    ");
		}

		if(($word1 & 0xFFF0) == 0x0020)
		{
			&addcmd19("se_not    ");
		}

		#-----------------------------------------------------------------------------------------
		# shift group
		#-----------------------------------------------------------------------------------------
		if((($word1 & 0xFC00) == 0x7C00) && (($word2 & 0x07FF) == 0x0230))
		{
			&addcmd22("e_rlw     ");
		}

		if((($word1 & 0xFC00) == 0x7C00) && (($word2 & 0x07FF) == 0x0231))
		{
			&addcmd22("e_rlw.    ");
		}

		if((($word1 & 0xFC00) == 0x7C00) && (($word2 & 0x07FF) == 0x0270))
		{
			&addcmd23("e_rlwi    ");
		}

		if((($word1 & 0xFC00) == 0x7C00) && (($word2 & 0x07FF) == 0x0271))
		{
			&addcmd23("e_rlwi.   ");
		}

		if((($word1 & 0xFC00) == 0x7C00) && (($word2 & 0x07FF) == 0x0070))
		{
			&addcmd23("e_slwi    ");
		}

		if((($word1 & 0xFC00) == 0x7C00) && (($word2 & 0x07FF) == 0x0071))
		{
			&addcmd23("e_slwi.   ");
		}

		if((($word1 & 0xFC00) == 0x7C00) && (($word2 & 0x07FF) == 0x0470))
		{
			&addcmd23("e_srwi    ");
		}

		if((($word1 & 0xFC00) == 0x7C00) && (($word2 & 0x07FF) == 0x0471))
		{
			&addcmd23("e_srwi.   ");
		}

		if(($word1 & 0xff00) == 0x4200)
		{
			&addcmd1("se_slw     ");
		}

		if(($word1 & 0xff00) == 0x4100)
		{
			&addcmd1("se_sraw    ");
		}

		if(($word1 & 0xff00) == 0x4000)
		{
			&addcmd1("se_srw     ");
		}

		if(($word1 & 0xfe00) == 0x6C00)
		{
			&addcmd24("se_slwi    ");
		}

		if(($word1 & 0xfe00) == 0x6A00)
		{
			&addcmd24("se_srawi   ");
		}

		if(($word1 & 0xfe00) == 0x6800)
		{
			&addcmd24("se_srwi    ");
		}

		if(($word1 & 0xfe00) == 0x2C00)
		{
			&addcmd24("se_bmaski  ");
		}

		if(($word1 & 0xfe00) == 0x6400)
		{
			&addcmd24("se_bseti   ");
		}


		#-----------------------------------------------------------------------------------------
		# or group
		#-----------------------------------------------------------------------------------------
		if(($word1 & 0xff00) == 0x4400)
		{
			&addcmd1("se_or     ");
		}
		if((($word1 & 0xfc00) == 0x7000) && (($word2 & 0xF800) == 0xC000))
		{
			&addcmd11("e_or2i    ");
		}
		if((($word1 & 0xfc00) == 0x7000) && (($word2 & 0xF800) == 0xD000))
		{
			&addcmd11("e_or2is   ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xF800) == 0xD000))
		{
			&addcmd4("e_ori     ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xF800) == 0xD800))
		{
			&addcmd4("e_ori.    ");
		}


		#-----------------------------------------------------------------------------------------
		# rlwinm group
		#-----------------------------------------------------------------------------------------
		if((($word1 & 0xfc00) == 0x7400) && (($word2 & 0x0001) == 0x0000))
		{
			&addcmd16("e_rlwimi  ");
		}

		if((($word1 & 0xfc00) == 0x7400) && (($word2 & 0x0001) == 0x0001))
		{
			&addcmd16("e_rlwinm  ");
		}

		#-----------------------------------------------------------------------------------------
		#stb group
		#-----------------------------------------------------------------------------------------
		if(($word1 & 0xfc00) == 0x3400)
		{
			&addcmd13("e_stb     ");
		}
		if(($word1 & 0xf000) == 0x9000)
		{
			&addcmd14("se_stb    ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xFF00) == 0x0400))
		{
			&addcmd15("e_stbu    ");
		}

		#-----------------------------------------------------------------------------------------
		#sth group
		#-----------------------------------------------------------------------------------------
		if(($word1 & 0xfc00) == 0x5c00)
		{
			&addcmd13("e_sth     ");
		}
		if(($word1 & 0xf000) == 0xb000)
		{
			&addcmd14("se_sth    ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xFF00) == 0x0500))
		{
			&addcmd15("e_sthu    ");
		}

		#-----------------------------------------------------------------------------------------
		#stw group
		#-----------------------------------------------------------------------------------------
		if(($word1 & 0xfc00) == 0x5400)
		{
			&addcmd13("e_stw     ");
		}
		if(($word1 & 0xf000) == 0xD000)
		{
			&addcmd14("se_stw    ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xFF00) == 0x0600))
		{
			&addcmd15("e_stwu    ");
		}
		if((($word1 & 0xfc00) == 0x1800) && (($word2 & 0xFF00) == 0x0900))
		{
			&addcmd15("e_stmw    ");
		}

		#-----------------------------------------------------------------------------------------
		# stxx group
		#-----------------------------------------------------------------------------------------
		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x01EE))
		{
			&addcmd22("stbux     ");
		}

		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x01AE))
		{
			&addcmd22("stbx      ");
		}

		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x036E))
		{
			&addcmd22("sthux     ");
		}

		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x032E))
		{
			&addcmd22("sthx      ");
		}

		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x016E))
		{
			&addcmd22("stwux     ");
		}

		if((($word1 & 0xfc00) == 0x7c00) && (($word2 & 0x07FF) == 0x012E))
		{
			&addcmd22("stwx      ");
		}



		#-----------------------------------------------------------------------------------------
		# sub group
		#-----------------------------------------------------------------------------------------
		if(($word1 & 0xff00) == 0x0600)
		{
			&addcmd1("se_sub    ");
		}

		if(($word1 & 0xfe00) == 0x2400)
		{
			&addcmd5("se_subi   ");
		}

		if(($word1 & 0xfe00) == 0x2600)
		{
			&addcmd5("se_subi.  ");
		}
		
		

		if((($word1 & 0xFFFF) == 0x7C00) && (($word2 & 0xFFFF) == 0x8146))
		{
			&addcmd18("wrteei 1  ");
		}

		if((($word1 & 0xFFFF) == 0x7C00) && (($word2 & 0xFFFF) == 0x0146))
		{
			&addcmd18("wrteei 0  ");
		}

		if((($word1 & 0xFFFF) == 0x7C00) && (($word2 & 0xFFFF) == 0x06AC))
		{
			&addcmd18("mbar 0    ");
		}

		if(($word1 & 0xFFF0) == 0x0080)
		{
			&addcmd19("se_mflr   ");
		}

		if(($word1 & 0xFFF0) == 0x0090)
		{
			&addcmd19("se_mtlr   ");
		}

		if(($word1 & 0xFFF0) == 0x00A0)
		{
			&addcmd19("se_mfctr  ");
		}

		if(($word1 & 0xFFF0) == 0x00B0)
		{
			&addcmd19("se_mtctr  ");
		}

		if(($word1 & 0xFFFF) == 0x0004)
		{
			&addcmd20("se_blr    \n");
		}

		if(($word1 & 0xFFFF) == 0x0005)
		{
			&addcmd20("se_blrl   \n");
		}

		if(($word1 & 0xFFFF) == 0x0006)
		{
			&addcmd20("se_bctr   \n");
		}

		if(($word1 & 0xFFFF) == 0x0007)
		{
			&addcmd20("se_bctrl  \n");
		}


		if(($word1 & 0xFFFF) == 0x0008)
		{
			&addcmd20("se_rfi    ");
		}

		if(($word1 & 0xFFFF) == 0x0009)
		{
			&addcmd20("se_rfci   ");
		}

		
		if((($word1 & 0xFF00) == 0x7C00) && (($word2 & 0x0FFF) == 0x0120))
		{
			&addcmd21("mtcr      ");
		}

		if(($word1 & 0xFF00) == 0x0300)
		{
			&addcmd26("se_mfar   ");
		}

		if(($word1 & 0xFF00) == 0x0200)
		{
			&addcmd26("se_mtar   ");
		}




		$addr+=2
	}
}
#------------------------------------------------------------------------------------------
# se_add se_and
#------------------------------------------------------------------------------------------
sub addcmd1
{
	$r1=$byte2 & 0x0f;
	if($r1 > 7) {$r1+=16;}
	$r2=($byte2 & 0xf0) >> 4;
	if($r2 > 7) {$r2+=16;}
	&w16();print DASS $_[0]."\tr$r1,r$r2";
}

#------------------------------------------------------------------------------------------
# e_add16i
#------------------------------------------------------------------------------------------
sub addcmd2
{
	$r1=($word1 & 0x03E0) >> 5;
	$r2=($word1 & 0x001F);
	$val=sprintf("0x%04X",$word2);
	&w32();print DASS $_[0]."\tr$r1,r$r2,$val";
}

#------------------------------------------------------------------------------------------
# e_add2i. e_add2is
#------------------------------------------------------------------------------------------
sub addcmd3
{
	$r1=($word1 & 0x001F);
	$vval=($word1 & 0x03E0) << 6;
	$vval+=($word2 & 0x07FF);
	$val=sprintf("0x%04X",$vval);
	&w32();print DASS $_[0]."\tr$r1,$val";
}

#------------------------------------------------------------------------------------------
# e_addi e_add2i. e_addic e_addic.
#------------------------------------------------------------------------------------------
sub addcmd4
{
	$r1=($word1 & 0x03E0) >> 5;
	$r2=($word1 & 0x001F);
	$val=sprintf("0x%02X",$byte4);
	&w32();print DASS $_[0]."\tr$r1,r$r2,$val";
}

#------------------------------------------------------------------------------------------
# se_addi
#------------------------------------------------------------------------------------------
sub addcmd5
{
	$r1=($word1 & 0x000F);
	$val=sprintf("0x%02X",(($word1 >> 4) & 0x1f) + 1);
	if($r1 > 7) {$r1+=16;}
	&w16();print DASS $_[0]."\tr$r1,$val";
}

#------------------------------------------------------------------------------------------
# e_andi (imm5)
#------------------------------------------------------------------------------------------
sub addcmd6
{
	$r1=($word1 & 0x000F);
	$val=sprintf("0x%02X",(($word1 >> 4) & 0x1f));
	if($r1 > 7) {$r1+=16;}
	&w16();print DASS $_[0]."\tr$r1,$val";
}

#------------------------------------------------------------------------------------------
# long branch
#------------------------------------------------------------------------------------------
sub addcmd7
{
	$vval=($word2 & 0xFFFE) + (($word1 & 0x1FF) << 16)+$addr;
	if(($word1 & 0x0100) == 0x0100)
	{
		$vval += 0xFE000000;
	}
	if($vval > 0xFFFFFFFF)
	{
		$vval-= 0x100000000;
	}
	$val=sprintf("%08X",$vval);
	$jlabel=$code_symbols{$val};
	if($jlabel ne "")
	{
		&w32();print DASS $_[0]."\t$jlabel";
	}
	else
	{
		&w32();print DASS $_[0]."\t0x$val";	
	}
}

#------------------------------------------------------------------------------------------
# short branch
#------------------------------------------------------------------------------------------
sub addcmd8
{
	$vval=(($word1 & 0x00FF) << 1)+$addr;
	if(($word1 & 0x0080) == 0x0080)
	{
		$vval += 0xFFFFFE00;
	}
	if($vval > 0xFFFFFFFF)
	{
		$vval-= 0x100000000;
	}
	$val=sprintf("%08X",$vval);
	$jlabel=$code_symbols{$val};
	if($jlabel ne "")
	{
		&w16();print DASS $_[0]."\t$jlabel";
	}
	else
	{
		&w16();print DASS $_[0]."\t0x$val";	
	}
}

#------------------------------------------------------------------------------------------
# conditional branch
#------------------------------------------------------------------------------------------
sub addcmd9
{
	$cr=($word1 & 0x0030) >> 4;
	$vval=($word2 & 0xFFFE)+$addr;
	if(($word2 & 0x8000) == 0x8000)
	{
		$vval += 0xFFFF0000;
	}
	if($vval > 0xFFFFFFFF)
	{
		$vval-= 0x100000000;
	}
	$val=sprintf("%08X",$vval);
	$jlabel=$code_symbols{$val};
	if($jlabel ne "")
	{
		&w32();print DASS $_[0]."\t$jlabel";
	}
	else
	{
		&w32();print DASS $_[0]."\t0x$val";	
	}
}

#------------------------------------------------------------------------------------------
# e_li
#------------------------------------------------------------------------------------------
sub addcmd10
{
	$r1=($word1 & 0x03E0) >> 5;
	$vval=($word2 & 0x07ff);
	$vval+=($word1 & 0x001f) << 11;
	$vval+=($word2 & 0x7800) << 5;
	$val=sprintf("0x%08X",$vval);
	&w32();print DASS $_[0]."\tr$r1,$val";
}

#------------------------------------------------------------------------------------------
# e_lis
#------------------------------------------------------------------------------------------
sub addcmd11
{
	$r1=($word1 & 0x03E0) >> 5;
	$vval=($word1 & 0x001f) << 11;
	$vval+=($word2 & 0x07ff);
	$val=sprintf("0x%04X",$vval);
	&w32();print DASS $_[0]."\tr$r1,$val";
}

#------------------------------------------------------------------------------------------
# se_li
#------------------------------------------------------------------------------------------
sub addcmd12
{
	$r1=($word1 & 0x000F);
	$val=sprintf("0x%02X",(($word1 >> 4) & 0x7F));
	if($r1 > 7) {$r1+=16;}
	&w16();print DASS $_[0]."\tr$r1,$val";
}

#------------------------------------------------------------------------------------------
# e_stb e_sth e_stw
#------------------------------------------------------------------------------------------
sub addcmd13
{
	$r1=($word1 & 0x03E0) >> 5;
	$r2=($word1 & 0x001F);
	$val=sprintf("0x%04X",$word2);
	&w32();print DASS $_[0]."\tr$r1,$val(r$r2)";
}

#------------------------------------------------------------------------------------------
# se_stb se_sth se_stw
#------------------------------------------------------------------------------------------
sub addcmd14
{
	$r1=$word1 & 0x000f;
	if($r1 > 7) {$r1+=16;}
	$r2=($word1 & 0x00f0) >> 4;
	if($r2 > 7) {$r2+=16;}
	$vval=($word1 & 0x0f00) >> 6;
	$val=sprintf("0x%02X",$vval);
	&w16();print DASS $_[0]."\tr$r2,$val(r$r1)";
}

#------------------------------------------------------------------------------------------
# e_stbu e_sthu e_stwu
#------------------------------------------------------------------------------------------
sub addcmd15
{
	$r1=($word1 & 0x03E0) >> 5;
	$r2=($word1 & 0x001F);
	$val=sprintf("0x%02X",($word2 & 0xff));
	&w32();print DASS $_[0]."\tr$r1,$val(r$r2)";
}


#------------------------------------------------------------------------------------------
# e_rlwinm
#------------------------------------------------------------------------------------------
sub addcmd16
{
	$r1=($word1 & 0x03E0) >> 5;
	$r2=($word1 & 0x001F);
	$sh=($word2 & 0xF800) >> 11;
	$mb=($word2 & 0x07C0) >> 6;
	$me=($word2 & 0x003E) >> 1;
	&w32();print DASS $_[0]."\tr$r2,r$r1,$sh,$mb,$me";
}


#------------------------------------------------------------------------------------------
# e_rlwinm
#------------------------------------------------------------------------------------------
sub addcmd16
{
	$r1=($word1 & 0x03E0) >> 5;
	$r2=($word1 & 0x001F);
	$sh=($word2 & 0xF800) >> 11;
	$mb=($word2 & 0x07C0) >> 6;
	$me=($word2 & 0x003E) >> 1;
	&w32();print DASS $_[0]."\tr$r2,r$r1,$sh,$mb,$me";
}

#------------------------------------------------------------------------------------------
# mfsrr/mtsrr
#------------------------------------------------------------------------------------------
sub addcmd17
{
	$r1=($word1 & 0x03E0) >> 5;
	&w32();print DASS $_[0]."\tr$r1";
}

#------------------------------------------------------------------------------------------
# direct 32 bit
#------------------------------------------------------------------------------------------
sub addcmd18
{
	&w32();print DASS $_[0];
}


#------------------------------------------------------------------------------------------
# se_mflr
#------------------------------------------------------------------------------------------
sub addcmd19
{
	$r1=$word1 & 0x000f;
	if($r1 > 7) {$r1+=16;}
	&w16();print DASS $_[0]."\tr$r1";
}

#------------------------------------------------------------------------------------------
# direct 16 bit
#------------------------------------------------------------------------------------------
sub addcmd20
{
	&w16();print DASS $_[0];
}


#------------------------------------------------------------------------------------------
# mtcr
#------------------------------------------------------------------------------------------
sub addcmd21
{
	$r1=($word1 & 0x03E0) >> 5;
	$vval=($word1 & 0x000f) << 4;
	$vval+=($word2 & 0xF000) >> 12;
	$val=sprintf("0x%02X",$vval);
	&w32();print DASS $_[0]."\t$val,r$r1";
}


#------------------------------------------------------------------------------------------
# shift reg
#------------------------------------------------------------------------------------------
sub addcmd22
{
	$ra=($word1 & 0x001f);
	$rs=($word1 & 0x03E0) >> 5;
	$rb=($word2 & 0xf800) >> 11;
	&w32();print DASS $_[0]."\tr$ra,r$rs,r$rb";
}


#------------------------------------------------------------------------------------------
# shift imm
#------------------------------------------------------------------------------------------
sub addcmd23
{
	$ra=($word1 & 0x001f);
	$rs=($word1 & 0x03E0) >> 5;
	$rb=($word2 & 0xf800) >> 11;
	&w32();print DASS $_[0]."\tr$ra,r$rs,$rb";
}

#------------------------------------------------------------------------------------------
# shift imm short
#------------------------------------------------------------------------------------------
sub addcmd24
{
	$r1=$word1 & 0x000f;
	if($r1 > 7) {$r1+=16;}
	$val=($word1 & 0x01F0) >> 4;
	&w16();print DASS $_[0]."\tr$r1,$val";
}


#------------------------------------------------------------------------------------------
# cmpi
#------------------------------------------------------------------------------------------
sub addcmd25
{
	$ra=($word1 & 0x001f);
	$cr=($word1 & 0x0060) >> 5;
	$rb=($word2 & 0x00FF);
	&w32();print DASS $_[0]."\tcr$cr,r$ra,$rb";
}

#------------------------------------------------------------------------------------------
# se_add se_and
#------------------------------------------------------------------------------------------
sub addcmd26
{
	$r1=$word1 & 0x000f;
	if($r1 > 7) {$r1+=16;}
	$r2=(($word1 & 0x00f0) >> 4 )+ 8;
	&w16();print DASS $_[0]."\tr$r1,r$r2";
}

#------------------------------------------------------------------------------------------
# data output
#------------------------------------------------------------------------------------------
sub w16
{
	if($write_data ==1){printf DASS "%04X\t\t",$word1;};
}

sub w32
{
	if($write_data ==1){printf DASS "%04X %04X\t\t",$word1,$word2;};
	$addr+=2
}
