URL
https://opencores.org/ocsvn/nanoblaze/nanoblaze/trunk
Subversion Repositories nanoblaze
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 6 to Rev 7
- ↔ Reverse comparison
Rev 6 → Rev 7
/nanoblaze/trunk/Tools/nanoasm.pl
0,0 → 1,557
#!/usr/bin/env perl |
|
my $indent = ' ' x 2; |
my $separator = '-' x 80; |
|
################################################################################ |
# Input arguments |
# |
use Getopt::Std; |
my %opts; |
getopts('hva:d:r:k', \%opts); |
|
die("\n". |
"Usage: $0 [options] fileSpec\n". |
"\n". |
"Options:\n". |
"${indent}-h display this help message\n". |
"${indent}-v verbose\n". |
"${indent}-a bitNb the number of program address bits\n". |
"${indent}-d bitNb the number of data bits\n". |
"${indent}-r bitNb the number of register address bits\n". |
"${indent}-k keep source comments in VHDL code\n". |
"\n". |
"Assemble code to VHDL for the nanoBlaze processor.\n". |
"\n". |
"More information with: perldoc $0\n". |
"\n". |
"" |
) if ($opts{h}); |
|
my $verbose = $opts{v}; |
my $keepComments = $opts{k}; |
my $addressBitNb = $opts{a} || 10; |
my $registerBitNb = $opts{d} || 8; |
my $registerAddressBitNb = $opts{r} || 4; |
|
my $asmFileSpec = $ARGV[0] || 'nanoTest.asm'; |
my $outFileSpec = $ARGV[1] || 'rom_mapped.vhd'; |
|
#------------------------------------------------------------------------------- |
# System constants |
# |
my $binaryOpCodeLength = 6; |
my $binaryBranchLength = 5; |
my $binaryBranchConditionLength = 3; |
|
my $opCodeBaseLength = 10; |
my $vhdlAddressLength = 14; |
|
#------------------------------------------------------------------------------- |
# Derived values |
# |
# file specs |
my $baseFileSpec = $asmFileSpec; |
$baseFileSpec =~ s/\..*//i; |
my $asm1FileSpec = "$baseFileSpec.asm1"; # formatted assembly code |
my $asm2FileSpec = "$baseFileSpec.asm2"; # code with addresses replaced |
my $vhdlFileSpec = "$baseFileSpec.vhd"; |
# instruction length |
my $binaryOperationInstructionLength = |
$binaryOpCodeLength + |
$registerAddressBitNb + |
$registerBitNb; |
my $binaryBranchInstructionLength = |
$binaryBranchLength + |
$binaryBranchConditionLength + |
$addressBitNb; |
my $binaryInstructionLength = $binaryOperationInstructionLength; |
if ($binaryBranchInstructionLength > $binaryInstructionLength) { |
$binaryInstructionLength = $binaryBranchInstructionLength |
} |
# assembler string lengths |
my $registerCharNb = int( ($registerBitNb-1)/4 ) + 1; |
my $addressCharNb = int( ($addressBitNb-1)/4 ) + 1; |
# vhdl string lengths |
my $vhdlOpCodeLength = $binaryOpCodeLength + 4; |
my $opCodeTotalLength = 22 + $registerCharNb; |
my $vhdlOperand1Length = $registerAddressBitNb + 3; |
my $vhdlOperand2Length = $registerBitNb + 4; |
if ($addressBitNb + 3 > $vhdlOperand2Length) { |
$vhdlOperand2Length = $addressBitNb + 3 |
} |
my $vhdlTotalLength = $vhdlOpCodeLength; |
$vhdlTotalLength = $vhdlTotalLength + $vhdlOperand1Length + $vhdlOperand2Length; |
$vhdlTotalLength = $vhdlTotalLength + 2*2; # '& ' |
$vhdlTotalLength = $vhdlTotalLength + 1; # ',' |
|
#------------------------------------------------------------------------------- |
# System variables |
# |
my %constants = (); |
my %addresses = (); |
|
################################################################################ |
# Functions |
# |
|
#------------------------------------------------------------------------------- |
# Find constant from "CONSTANT" statement |
# |
sub findNewConstant { |
my ($codeLine) = @_; |
|
$codeLine =~ s/CONSTANT\s+//; |
my ($name, $value) = split(/,\s*/, $codeLine); |
$value = hex($value); |
|
return ($name, $value); |
} |
|
#------------------------------------------------------------------------------- |
# Find address from "ADDRESS" statement |
# |
sub findNewAddress { |
my ($codeLine) = @_; |
|
$codeLine =~ s/ADDRESS\s*//; |
my $address = hex($codeLine); |
|
return $address; |
} |
|
#------------------------------------------------------------------------------- |
# Format opcodes |
# |
sub prettyPrint { |
my ($codeLine) = @_; |
|
my ($opcode, $arguments) = split(/ /, $codeLine, 2); |
$opcode = $opcode . ' ' x ($opCodeBaseLength - length($opcode)); |
$arguments =~ s/,*\s+/, /; |
$codeLine = $opcode . $arguments; |
|
return $codeLine; |
} |
|
#------------------------------------------------------------------------------- |
# Format to binary |
# |
sub toBinary { |
my ($operand, $bitNb) = @_; |
|
#$operand = sprintf("%0${bitNb}b", $operand); |
|
my $hexCharNb = int($bitNb/4) + 1; |
$operand = sprintf("%0${hexCharNb}X", $operand); |
$operand =~ s/0/0000/g; |
$operand =~ s/1/0001/g; |
$operand =~ s/2/0010/g; |
$operand =~ s/3/0011/g; |
$operand =~ s/4/0100/g; |
$operand =~ s/5/0101/g; |
$operand =~ s/6/0110/g; |
$operand =~ s/7/0111/g; |
$operand =~ s/8/1000/g; |
$operand =~ s/9/1001/g; |
$operand =~ s/A/1010/g; |
$operand =~ s/B/1011/g; |
$operand =~ s/C/1100/g; |
$operand =~ s/D/1101/g; |
$operand =~ s/E/1110/g; |
$operand =~ s/F/1111/g; |
$operand = substr($operand, length($operand)-$bitNb, $bitNb); |
|
return $operand; |
} |
|
################################################################################ |
# Program start |
# |
|
#------------------------------------------------------------------------------- |
# Display information |
# |
if ($verbose > 0) { |
print "$separator\n"; |
print "Assembling $asmFileSpec to $vhdlFileSpec\n"; |
} |
|
#------------------------------------------------------------------------------- |
# Calculate adresses, store address labels |
# |
if ($verbose > 0) { |
print "${indent}Pass 1: from $asmFileSpec to $asm1FileSpec\n"; |
} |
|
my $romAddress = 0; |
open(asm1File, ">$asm1FileSpec") or die "Unable to open file, $!"; |
open(asmFile, "<$asmFileSpec") or die "Unable to open file, $!"; |
while(my $line = <asmFile>) { |
chomp($line); |
# split code and comment |
my ($codeLine, $comment) = split(/;/, $line, 2); |
# handle address label |
if ($codeLine =~ m/:/) { |
(my $label, $codeLine) = split(/:/, $codeLine); |
$label =~ s/\s*//; |
print asm1File "; _${label}_:\n"; |
$addresses{$label} = sprintf("%0${addressCharNb}X", $romAddress); |
} |
# cleanup code |
$codeLine =~ s/\s+/ /g; |
$codeLine =~ s/\A\s//; |
$codeLine =~ s/\s\Z//; |
$codeLine =~ s/\s,/,/; |
if ($codeLine) { |
# handle ADDRESS declaration |
if ($codeLine =~ m/ADDRESS/) { |
$romAddress = findNewAddress($codeLine); |
} |
# handle CONSTANT declaration |
elsif ($codeLine =~ m/CONSTANT/) { |
($name, $value) = findNewConstant($codeLine); |
$constants{$name} = sprintf("%0${registerCharNb}X", $value); |
} |
# print cleaned-up code |
else { |
$codeLine = prettyPrint($codeLine); |
print asm1File sprintf("%0${addressCharNb}X", $romAddress), ": $codeLine"; |
if ($comment) { |
print asm1File " ;$comment"; |
} |
print asm1File "\n"; |
$romAddress = $romAddress + 1; |
} |
} |
else { |
print asm1File ";$comment\n"; |
} |
} |
close(asmFile); |
close(asm1File); |
|
#------------------------------------------------------------------------------- |
# Replace constant values and address labels |
# |
if ($verbose > 0) { |
print "${indent}Pass 2: from $asm1FileSpec to $asm2FileSpec\n"; |
} |
|
open(asm2File, ">$asm2FileSpec") or die "Unable to open file, $!"; |
open(asm1File, "<$asm1FileSpec") or die "Unable to open file, $!"; |
while(my $line = <asm1File>) { |
chomp($line); |
# split code and comment |
my ($opcode, $comment) = split(/;/, $line, 2); |
if ( ($line =~ m/;/) and ($comment eq '') ) { |
$comment = ' '; |
} |
# cleanup code |
$opcode =~ s/\s+\Z//; |
# replace constants |
foreach my $name (keys %constants) { |
$opcode =~ s/$name/$constants{$name}/g; |
} |
# replace addresses |
foreach my $label (keys %addresses) { |
$opcode =~ s/$label/$addresses{$label}/g; |
} |
# cleanup code |
$opcode = uc($opcode); |
$opcode =~ s/\sS([0-9A-F])/ s$1/g; |
# print cleaned-up code |
if ($comment) { |
if ($opcode) { |
$opcode = $opcode . ' ' x ($opCodeTotalLength - length($opcode)); |
} |
$comment =~ s/\s+\Z//; |
print asm2File "$opcode;$comment\n"; |
} |
else { |
print asm2File "$opcode\n"; |
} |
} |
close(asm1File); |
close(asm2File); |
|
#------------------------------------------------------------------------------- |
# Write VHDL ROM code |
# |
if ($verbose > 0) { |
print "${indent}Pass 3: from $asm2FileSpec to $vhdlFileSpec\n"; |
} |
open(vhdlFile, ">$vhdlFileSpec") or die "Unable to open file, $!"; |
print vhdlFile <<DONE; |
ARCHITECTURE mapped OF programRom IS |
|
subtype opCodeType is std_ulogic_vector(5 downto 0); |
constant opLoadC : opCodeType := "000000"; |
constant opLoadR : opCodeType := "000001"; |
constant opInputC : opCodeType := "000100"; |
constant opInputR : opCodeType := "000101"; |
constant opFetchC : opCodeType := "000110"; |
constant opFetchR : opCodeType := "000111"; |
constant opAndC : opCodeType := "001010"; |
constant opAndR : opCodeType := "001011"; |
constant opOrC : opCodeType := "001100"; |
constant opOrR : opCodeType := "001101"; |
constant opXorC : opCodeType := "001110"; |
constant opXorR : opCodeType := "001111"; |
constant opTestC : opCodeType := "010010"; |
constant opTestR : opCodeType := "010011"; |
constant opCompC : opCodeType := "010100"; |
constant opCompR : opCodeType := "010101"; |
constant opAddC : opCodeType := "011000"; |
constant opAddR : opCodeType := "011001"; |
constant opAddCyC : opCodeType := "011010"; |
constant opAddCyR : opCodeType := "011011"; |
constant opSubC : opCodeType := "011100"; |
constant opSubR : opCodeType := "011101"; |
constant opSubCyC : opCodeType := "011110"; |
constant opSubCyR : opCodeType := "011111"; |
constant opShRot : opCodeType := "100000"; |
constant opOutputC : opCodeType := "101100"; |
constant opOutputR : opCodeType := "101101"; |
constant opStoreC : opCodeType := "101110"; |
constant opStoreR : opCodeType := "101111"; |
|
subtype shRotCinType is std_ulogic_vector(2 downto 0); |
constant shRotLdC : shRotCinType := "00-"; |
constant shRotLdM : shRotCinType := "01-"; |
constant shRotLdL : shRotCinType := "10-"; |
constant shRotLd0 : shRotCinType := "110"; |
constant shRotLd1 : shRotCinType := "111"; |
|
constant registerAddressBitNb : positive := $registerAddressBitNb; |
constant shRotPadLength : positive |
:= dataOut'length - opCodeType'length - registerAddressBitNb |
- 1 - shRotCinType'length; |
subtype shRotDirType is std_ulogic_vector(1+shRotPadLength-1 downto 0); |
constant shRotL : shRotDirType := (0 => '0', others => '-'); |
constant shRotR : shRotDirType := (0 => '1', others => '-'); |
|
subtype branchCodeType is std_ulogic_vector(4 downto 0); |
constant brRet : branchCodeType := "10101"; |
constant brCall : branchCodeType := "11000"; |
constant brJump : branchCodeType := "11010"; |
constant brReti : branchCodeType := "11100"; |
constant brEni : branchCodeType := "11110"; |
|
subtype branchConditionType is std_ulogic_vector(2 downto 0); |
constant brDo : branchConditionType := "000"; |
constant brZ : branchConditionType := "100"; |
constant brNZ : branchConditionType := "101"; |
constant brC : branchConditionType := "110"; |
constant brNC : branchConditionType := "111"; |
|
subtype memoryWordType is std_ulogic_vector(dataOut'range); |
type memoryArrayType is array (0 to 2**address'length-1) of memoryWordType; |
|
signal memoryArray : memoryArrayType := ( |
DONE |
open(asm2File, "<$asm2FileSpec") or die "Unable to open file, $!"; |
while(my $line = <asm2File>) { |
chomp($line); |
# split code and comment |
my ($opcode, $comment) = split(/;/, $line, 2); |
if ( ($line =~ m/;/) and ($comment eq '') ) { |
$comment = ' '; |
} |
# addresses to VHDL |
my $address; |
if ($opcode) { |
($address, $opcode) = split(/:\s+/, $opcode, 2); |
$address = '16#' . $address . '# =>'; |
$address = ' ' x ($vhdlAddressLength - length($address)) . $address; |
} |
# opcode to VHDL |
if ($opcode) { |
if ($comment eq '') { |
$comment = ' ' . $opcode; |
} |
else { |
$comment = ' ' . $opcode . ';' . $comment; |
} |
# replace NOP |
$opcode =~ s/\ANOP/LOAD s0, s0/; |
# split opcodes and operands |
$opcode =~ s/\s+/ /; |
$opcode =~ s/\s+\Z//; |
($opcode, my $operand1, my $operand2) = split(/\s/, $opcode); |
$operand1 =~ s/,//; |
$operand1 =~ s/S/s/; |
$operand2 =~ s/S/s/; |
if ( ($opcode =~ m/\ASL/) or ($opcode =~ m/\ASR/) ) { |
$operand2 = substr($opcode, 0, 3); |
$opcode = 'SHIFT'; |
} |
if ( ($opcode =~ m/\ARL/) or ($opcode =~ m/\ARR/) ) { |
$operand2 = substr($opcode, 0, 2); |
$opcode = 'ROT'; |
} |
if ( ($opcode eq 'JUMP') or ($opcode eq 'CALL') or ($opcode eq 'RETURN') ) { |
unless ($operand2) { |
unless ($opcode eq 'RETURN') { |
$operand2 = $operand1; |
} |
$operand1 = 'AW'; # AlWays |
} |
} |
#........................................................................... |
# opcodes to VHDL |
$opcode =~ s/LOAD/opLoadC/; |
$opcode =~ s/AND/opAndC/; |
$opcode =~ s/XOR/opXorC/; |
$opcode =~ s/ADDCY/opAddCyC/; |
$opcode =~ s/SUBCY/opSubCyC/; |
$opcode =~ s/ADD/opAddC/; |
$opcode =~ s/SUB/opSubC/; |
$opcode =~ s/SHIFT/opShRot/; |
$opcode =~ s/ROT/opShRot/; |
$opcode =~ s/COMPARE/opCompC/; |
$opcode =~ s/TEST/opTestC/; |
$opcode =~ s/FETCH/opFetchC/; |
$opcode =~ s/STORE/opStoreC/; |
$opcode =~ s/OR/opOrC/; |
$opcode =~ s/INPUT/opInputC/; |
$opcode =~ s/OUTPUT/opOutputC/; |
$opcode =~ s/JUMP/brJump/; |
$opcode =~ s/CALL/brCall/; |
$opcode =~ s/RETURN/brRet/; |
if ($operand2 =~ m/s[0-9A-F]/) { |
$opcode =~ s/C\Z/R/; |
} |
$opcode = $opcode . ' ' x ($vhdlOpCodeLength - length($opcode)) . '& '; |
#........................................................................... |
# register as first operand |
if ($operand1 =~ m/s[0-9A-F]/) { |
$operand1 =~ s/\As//; |
$operand1 = '"' . toBinary($operand1, $registerAddressBitNb) . '"'; |
} |
# test condition |
$operand1 =~ s/NC/brNC/; |
$operand1 =~ s/NZ/brNZ/; |
$operand1 =~ s/\AC/brC/; |
$operand1 =~ s/\AZ/brZ/; |
$operand1 =~ s/AW/brDo/; |
if ($opcode =~ m/brRet/) { |
$operand2 = 0; |
} |
if ($operand2 eq '') { |
$operand1 = $operand1 . ','; |
} |
$operand1 = $operand1 . ' ' x ($vhdlOperand1Length - length($operand1)); |
unless ($operand2 eq '') { |
$operand1 = $operand1 . '& '; |
} |
#print "|$opcode| |$operand1| |$operand2|\n"; |
#........................................................................... |
# register as second operand |
$operand2 =~ s/\A\((.*)\)\Z/$1/; |
if ($operand2 =~ m/s[0-9A-F]/) { |
$operand2 =~ s/\As//; |
$operand2 = toBinary($operand2, $registerAddressBitNb); |
if ($registerBitNb > $registerAddressBitNb) { |
$operand2 = $operand2 . '-' x ($registerBitNb - $registerAddressBitNb); |
} |
} |
# address as second operand |
elsif ($opcode =~ m/\Abr/) { |
my $fill = ''; |
if ($binaryBranchInstructionLength < $binaryInstructionLength) { |
$fill = '-' x ($binaryInstructionLength - $binaryBranchInstructionLength); |
} |
if ( ($opcode =~ m/Ret/) ) { |
$operand2 = $fill . '-' x $addressBitNb; |
} |
else { |
$operand2 = $fill . toBinary(hex($operand2), $addressBitNb); |
} |
} |
# shift and rotate operators |
elsif ($opcode =~ m/opShRot/) { |
$operand2 =~ s/SL0/shRotL & shRotLd0/; |
$operand2 =~ s/SL1/shRotL & shRotLd1/; |
$operand2 =~ s/SLX/shRotL & shRotLdL/; |
$operand2 =~ s/SLA/shRotL & shRotLdC/; |
$operand2 =~ s/SR0/shRotR & shRotLd0/; |
$operand2 =~ s/SR1/shRotR & shRotLd1/; |
$operand2 =~ s/SRX/shRotR & shRotLdM/; |
$operand2 =~ s/SRA/shRotR & shRotLdC/; |
$operand2 =~ s/RL/shRotL & shRotLdH/; |
$operand2 =~ s/RR/shRotR & shRotLdL/; |
} |
# constant as second operand |
else { |
$operand2 = toBinary(hex($operand2), $registerBitNb); |
if ($registerAddressBitNb > $registerBitNb) { |
$operand2 = '-' x ($registerAddressBitNb - $registerBitNb) . $operand2; |
} |
} |
unless ($opcode =~ m/opShRot/) { |
$operand2 = '"' . $operand2 . '"'; |
} |
# add separator at end |
if ($operand2) { |
$operand2 = $operand2 . ','; |
} |
#........................................................................... |
# concatenate opcode and operands |
$opcode = $opcode . $operand1 . $operand2; |
} |
else { |
$address = ' ' x $vhdlAddressLength; |
} |
# print VHDL code |
if ($keepComments == 0) { |
if ($opcode) { |
print vhdlFile "$address $opcode\n"; |
} |
} |
else { |
$opcode = $opcode . ' ' x ($vhdlTotalLength - length($opcode)); |
if ($comment) { |
$comment =~ s/\s+\Z//; |
print vhdlFile "$address $opcode--$comment\n"; |
} |
else { |
print vhdlFile "$address $opcode\n"; |
} |
} |
} |
close(asm2File); |
print vhdlFile <<DONE; |
others => (others => '0') |
); |
|
BEGIN |
|
process (clock) |
begin |
if rising_edge(clock) then |
if en = '1' then |
dataOut <= memoryArray(to_integer(address)); |
end if; |
end if; |
end process; |
|
END ARCHITECTURE mapped; |
DONE |
close(vhdlFile); |
|
#------------------------------------------------------------------------------- |
# Delete original file and copy VHDL file |
# |
if ($verbose > 0) { |
print "Copying $vhdlFileSpec to $outFileSpec\n"; |
} |
|
use File::Copy; |
unlink($outFileSpec); |
copy($vhdlFileSpec, $outFileSpec) or die "File cannot be copied."; |
#rename($vhdlFileSpec, $outFileSpec); |
|
if ($verbose > 0) { |
print "$separator\n"; |
} |
nanoblaze/trunk/Tools/nanoasm.pl
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: nanoblaze/trunk/Tools/nanoTest.asm
===================================================================
--- nanoblaze/trunk/Tools/nanoTest.asm (nonexistent)
+++ nanoblaze/trunk/Tools/nanoTest.asm (revision 7)
@@ -0,0 +1,342 @@
+ ;===============================================================
+ ; nanoTest.asm
+ ; Used for checking the NanoBlaze instruction set
+ ;===============================================================
+ ; 1) Test logical operations with direct values
+ ;---------------------------------------------------------------
+ LOAD s7, 01
+ CONSTANT testPattern, 0F
+ ;---------------------------------------------------------------
+ ; Test "LOAD", "AND"
+ ;---------------------------------------------------------------
+ LOAD s0, testPattern
+ AND s0, 33
+ COMPARE s0, 03
+ JUMP NZ, error
+ ;---------------------------------------------------------------
+ ; Test "OR"
+ ;---------------------------------------------------------------
+ LOAD s1, testPattern
+ OR s1, 33
+ COMPARE s1, 3F
+ JUMP NZ, error
+ ;---------------------------------------------------------------
+ ; Test "XOR"
+ ;---------------------------------------------------------------
+ LOAD s2, testPattern
+ XOR s2, 33
+ COMPARE s2, 3C
+ JUMP NZ, error
+ ;===============================================================
+ ; 2) Test logical operations with registers
+ ;---------------------------------------------------------------
+ ADD s7, 01
+ ;---------------------------------------------------------------
+ ; Test "LOAD"
+ ;---------------------------------------------------------------
+ LOAD s0, 33
+ LOAD s3, s0
+ COMPARE s3, 33
+ JUMP NZ, error
+ ;---------------------------------------------------------------
+ ; Test "AND"
+ ;---------------------------------------------------------------
+ LOAD s0, 0F
+ AND s0, s3
+ COMPARE s0, 03
+ JUMP NZ, error
+ ;---------------------------------------------------------------
+ ; Test "OR"
+ ;---------------------------------------------------------------
+ LOAD s1, 0F
+ OR s1, s3
+ COMPARE s1, 3F
+ JUMP NZ, error
+ ;---------------------------------------------------------------
+ ; Test "XOR"
+ ;---------------------------------------------------------------
+ LOAD s2, 0F
+ XOR s2, s3
+ COMPARE s2, 3C
+ JUMP NZ, error
+ ;===============================================================
+ ; 3) Test arithmetic operations with constants
+ ;---------------------------------------------------------------
+ ADD s7, 01
+ ;---------------------------------------------------------------
+ ; Test "ADD" and "ADDCY"
+ ;---------------------------------------------------------------
+ LOAD s0, 0F
+ ADD s0, 31 ; 40
+ ADDCY s0, F0 ; 130
+ ADDCY s0, F0 ; 121
+ ADD s0, 0F ; 30
+ COMPARE s0, 30
+ JUMP NZ, error
+ ;---------------------------------------------------------------
+ ; Test "SUB" and "SUBCY"
+ ;---------------------------------------------------------------
+ LOAD s1, 0F
+ SUB s1, 0C ; 03
+ SUBCY s1, F0 ; 113
+ SUBCY s1, F0 ; 22
+ SUB s1, 01 ; 21
+ COMPARE s1, 21
+ JUMP NZ, error
+ ;===============================================================
+ ; 4) Test arithmetic operations with registers
+ ;---------------------------------------------------------------
+ ADD s7, 01
+ ;---------------------------------------------------------------
+ ; Test "ADD" and "ADDCY"
+ ;---------------------------------------------------------------
+ LOAD s0, 0F
+ LOAD s1, 31
+ LOAD s2, F0
+ LOAD s3, 0F
+ ADD s0, s1 ; 40
+ ADDCY s0, s2 ; 130
+ ADDCY s0, s2 ; 121
+ ADD s0, s3 ; 30
+ COMPARE s0, 30
+ JUMP NZ, error
+ ;---------------------------------------------------------------
+ ; Test "SUB" and "SUBCY"
+ ;---------------------------------------------------------------
+ LOAD s1, 0F
+ LOAD s0, 0C
+ LOAD s2, F0
+ LOAD s3, 01
+ SUB s1, s0 ; 03
+ SUBCY s1, s2 ; 113
+ SUBCY s1, s2 ; 22
+ SUB s1, s3 ; 21
+ COMPARE s1, 21
+ JUMP NZ, error
+ ;===============================================================
+ ; 5) Test shifts
+ ;---------------------------------------------------------------
+ ADD s7, 01
+ ;---------------------------------------------------------------
+ ; Test shift right
+ ;---------------------------------------------------------------
+ LOAD s0, 0F ; 0F
+ SR0 s0 ; 07
+ SRX s0 ; 03
+ SR1 s0 ; 81
+ SRX s0 ; C0, C=1
+ SRA s0 ; E0, C=0
+ SRA s0 ; 70
+ COMPARE s0, 70
+ JUMP NZ, error
+ ;---------------------------------------------------------------
+ ; Test shift left
+ ;---------------------------------------------------------------
+ LOAD s1, F0 ; FO
+ SL0 s1 ; E0
+ SLX s1 ; C0
+ SL1 s1 ; 81
+ SLX s1 ; 03, C=1
+ SLA s1 ; 07, C=0
+ SLA s1 ; 0E
+ COMPARE s1, 0E
+ JUMP NZ, error
+ ;===============================================================
+ ; 6) Test comparison operators
+ ;---------------------------------------------------------------
+ ADD s7, 01
+ ;---------------------------------------------------------------
+ ; Test "COMPARE"
+ ;---------------------------------------------------------------
+ LOAD s0, 0F
+ COMPARE s0, F0 ; A < B => C=1
+ JUMP NC, error
+ COMPARE s0, F0 ; A < B => Z=0
+ JUMP Z, error
+ COMPARE s0, s0 ; A = B => Z=1
+ JUMP NZ, error
+ COMPARE s0, 08 ; A > B => C=0
+ JUMP C, error
+ COMPARE s0, 08 ; A > B => Z=0
+ JUMP Z, error
+ ;---------------------------------------------------------------
+ ; Test "TEST"
+ ;---------------------------------------------------------------
+ LOAD s0, 0F
+ TEST s0, F0 ; AND is 00 => Z=1
+ JUMP NZ, error
+ TEST s0, FF ; AND is 0F => Z=0
+ JUMP Z, error
+ ;===============================================================
+ ; 7) Test INPUT and OUTPUT operators
+ ;---------------------------------------------------------------
+ ADD s7, 01
+ ;---------------------------------------------------------------
+ ; Test "INPUT" and "OUTPUT" direct
+ ;
+ ; The testbench should invert the word written at address FC.
+ ;---------------------------------------------------------------
+ LOAD s0, AA
+ OUTPUT s0, FC
+ INPUT s1, FC
+ COMPARE s1, 55
+ JUMP NZ, error
+ ;---------------------------------------------------------------
+ ; Test "INPUT" and "OUTPUT" indexed
+ ;---------------------------------------------------------------
+ LOAD s0, CC
+ LOAD s2, FC
+ OUTPUT s0, (s2)
+ INPUT s1, (s2)
+ COMPARE s1, 33
+ JUMP NZ, error
+ ;===============================================================
+ ; 8) Test STORE and FETCH operators
+ ;---------------------------------------------------------------
+ ADD s7, 01
+ ;---------------------------------------------------------------
+ ; Test "STORE" and "FETCH" direct
+ ;---------------------------------------------------------------
+ LOAD s0, 0F
+ STORE s0, 03
+ FETCH s1, 03
+ COMPARE s1, 0F
+ JUMP NZ, error
+ ;---------------------------------------------------------------
+ ; Test "STORE" and "FETCH" indexed
+ ;---------------------------------------------------------------
+ LOAD s0, F0
+ LOAD s2, 04
+ STORE s0, (s2)
+ FETCH s1, (s2)
+ COMPARE s1, F0
+ JUMP NZ, error
+ ;===============================================================
+ ; 9) Test JUMP instructions
+ ;---------------------------------------------------------------
+ ADD s7, 01
+ ;---------------------------------------------------------------
+ ; Test "JUMP NC"
+ ;---------------------------------------------------------------
+ LOAD s0, F0
+ ADD s0, 00 ; s0=F0, C=0, Z=0
+ JUMP NC, continue1
+ JUMP error
+ ;---------------------------------------------------------------
+ ; Test "JUMP NZ"
+ ;---------------------------------------------------------------
+ continue1: ADD s0, 00 ; s0=F0, C=0, Z=0
+ JUMP NZ, continue2
+ JUMP error
+ ;---------------------------------------------------------------
+ ; Test "JUMP C"
+ ;---------------------------------------------------------------
+ continue2: ADD s0, F0 ; s0=E0, C=1, Z=0
+ JUMP C, continue3
+ JUMP error
+ ;---------------------------------------------------------------
+ ; Test "JUMP Z"
+ ;---------------------------------------------------------------
+ continue3: SUB s0, E0 ; s0=00, C=0, Z=1
+ JUMP Z, continue4
+ JUMP error
+ continue4: NOP
+ ;===============================================================
+ ; 10) Test call instructions
+ ;---------------------------------------------------------------
+ ADD s7, 01
+ ;---------------------------------------------------------------
+ ; define subroutine
+ ;---------------------------------------------------------------
+ JUMP continue5
+ subRetDo: ADD s0, 01
+ RETURN
+ JUMP error
+ ;---------------------------------------------------------------
+ ; Test "CALL"
+ ;---------------------------------------------------------------
+ continue5: LOAD s0, 00
+ LOAD s1, F0
+ CALL subRetDo ; s0=01
+ ;---------------------------------------------------------------
+ ; Test "CALL NC"
+ ;---------------------------------------------------------------
+ ADD s1, 00 ; s1=F0, C=0, Z=0
+ CALL NC, subRetDo ; s0=02
+ ;---------------------------------------------------------------
+ ; Test "CALL NZ"
+ ;---------------------------------------------------------------
+ ADD s1, 00 ; s1=F0, C=0, Z=0
+ CALL NZ, subRetDo ; s0=03
+ ;---------------------------------------------------------------
+ ; Test "CALL C"
+ ;---------------------------------------------------------------
+ ADD s1, F0 ; s0=E0, C=1, Z=0
+ CALL C, subRetDo ; s0=04
+ ;---------------------------------------------------------------
+ ; Test "CALL Z"
+ ;---------------------------------------------------------------
+ SUB s1, E0 ; s0=00, C=0, Z=1
+ CALL Z, subRetDo ; s0=05
+ COMPARE s0, 05
+ jump nz, error
+ ;===============================================================
+ ; 11) Test call return instructions
+ ;---------------------------------------------------------------
+ ADD s7, 01
+ ;---------------------------------------------------------------
+ ; define subroutines
+ ;---------------------------------------------------------------
+ JUMP continue6
+ subRetNC: ADD s0, 01
+ RETURN NC
+ JUMP error
+ subRetNZ: ADD s0, 01
+ RETURN NZ
+ JUMP error
+ subRetC: ADD s0, 01
+ RETURN C
+ JUMP error
+ subRetZ: ADD s0, 01
+ RETURN Z
+ JUMP error
+ ;---------------------------------------------------------------
+ ; Test "RETURN NC"
+ ;---------------------------------------------------------------
+ continue6: LOAD s0, 00 ; increment will give C=0, Z=0
+ CALL NC, subRetNC
+ ;---------------------------------------------------------------
+ ; Test "RETURN NZ"
+ ;---------------------------------------------------------------
+ LOAD s0, 00 ; increment will give C=0, Z=0
+ CALL NZ, subRetNZ
+ ;---------------------------------------------------------------
+ ; Test "RETURN C"
+ ;---------------------------------------------------------------
+ LOAD s0, FF ; increment will give C=1, Z=1
+ CALL C, subRetC
+ ;---------------------------------------------------------------
+ ; Test "RETURN Z"
+ ;---------------------------------------------------------------
+ LOAD s0, FF ; increment will give C=1, Z=1
+ CALL Z, subRetZ
+ ;===============================================================
+ ; End of tests
+ ;
+ ; The testbench should react if value 1 is written to address 00.
+ ;---------------------------------------------------------------
+ LOAD s0, 01
+ OUTPUT s0, 00
+ JUMP endOfMemory
+ ;===============================================================
+ ; Assert error
+ ;
+ ; The testbench should react if value 0 is written to address 00.
+ ;---------------------------------------------------------------
+ADDRESS 3FD
+ error: LOAD s0, 00
+ OUTPUT s0, 00
+ ;===============================================================
+ ; End of instruction memory
+ ;---------------------------------------------------------------
+ endOfMemory: JUMP endOfMemory
nanoblaze/trunk/Tools/nanoTest.asm
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property