📄 risc8_asm_pl.txt
字号:
#! /usr/local/bin/perl5 #-------------------------------------------------------------------------------## (C) COPYRIGHT 2000 S.Aravindhan ## This program is free software; you can redistribute it and/or# modify it provided this header is preserved on all copies.# 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.# # Author : S.Aravindhan# File : risc8_asm.pl# Abstract : Assemble for risc8 processor.## History:# ============================================================================# 02/06/2000 arvind 1.0 Initial Release# ============================================================================ printf("Risc8 Assembler Version 1.0\n"); $usage = " Usage: risc8_asm.pl -f asm_file_name[.asm] <-cpp> <-i directory>\n "; $Examples = "Examples: risc8_asm.pl -h risc8_asm.pl -f math risc8_asm.pl -f math.asm risc8_asm.pl -f math -cpp risc8_asm.pl -f math -cpp -i ../include_files \n"; $error1 = " Usage: Missing assembly file \n"; $error2 = " Usage: Missing include directory \n"; #---------------------------- # Parse the arguments #---------------------------- if($ARGV[0] =~ /-h|-help/i || $#ARGV > 4) { die ($usage.$Examples);} $mem_init_value = "xx"; $invoke_preprocessor = 0; $found_include = 0; $found_asm = 0; $k = 0; while($k <= $#ARGV) { if($ARGV[$k] eq "-f") { if($#ARGV < ($k +1)) { die ($error1.$usage.$Examples);} $asm1 = $ARGV[$k +1 ]; $k=$k+2; $found_asm = 1;} elsif($ARGV[$k] eq "-cpp") { $invoke_preprocessor = 1; $k = $k +1; } elsif($ARGV[$k] eq "-i") { if($#ARGV < ($k +1)) { die ($error2.$usage.$Examples);} $include_dir = $ARGV[$k +1 ]; $k=$k+2; $found_include = 1;} else { die ($usage.$Examples);} } if($found_asm == 0) {die ($error1.$usage.$Examples);} $asm = $asm1; # strip .asm, if specified $asm =~ s/\.asm$//g; # strip .asm, if specified $asm_file = $asm . '.asm'; $lst_file = $asm . '.lst'; $hex_file = $asm . '.hex'; $mem_file = $asm . '.mem'; $tmp_file = $asm . '.tmppp'; if($invoke_preprocessor == 1) { $asm_file = $asm1 . "_cpped"; if($found_include == 0) { system("cpp -i $asm1 -o $asm_file");} else { system("cpp -i $asm1 -I $include_dir -o $asm_file"); } } # Open the Files open (ASM_F, "$asm_file") or die ("Can't open $asm_file: $!\n"); open (MEM_F, ">$mem_file") or die ("Can't open $mem_file: $!\n"); open (TMP_F, ">$tmp_file") or die ("Can't open $tmp_file: $!\n"); open (HEX_F, ">$hex_file") or die ("Can't open $hex_file: $!\n"); #open (LST_F, ">$lst_file") or die ("Can't open $lst_file: $!\n"); #---------------------------------------------------------- # hash table to group instructions according to operands #---------------------------------------------------------- %opcode_type = ( # Type 1: OP Rn "add" => 1, "adc" => 1, "sub" => 1, "sbc" => 1, "inc" => 1, "dec" => 1, "cmp" => 1, "and" => 1, "or" => 1, "xor" => 1, "not" => 1, "shl" => 1, "shr" => 1, "subr" => 1, "psh" => 1, "pop" => 1, "umul" => 1, "udiv" => "1", # Type 2: OP An "ldr" => 2, "str" => 2, "inca" => 2, "deca" => 2, "jmp" => 2, # Type 3: OP "ret" => 3, "ror" => 3, "rorc" => 3, "asr" => 3, "nop" => "3", "rdps" => "3", "wrps" => "3", # Type 4: OP xx yy "mov" => 4, # Type 5: OP An #offset8 "ldo" => 5, "sto" => 5, # Type 6: OP Rn #imm8 "ldi" => 6, # Type 7: OP CON #offset8 "jmpr" => 7, # Type 8: OP CON #addr16 "jmpa" => 8, "jmps" => 8, # Type 9: OP Rn #addr16 "lda" => 9, "sta" => 9, # Type 10: Special assembler directives "end" => 10, "org" => 10, "dcb" => 10, "dmem" => 10, "define" => 10, # Type 11: Pseudo instructions "pmov" => 11, ); #---------------------------------------------------- # Hash table for the nemonics to opcode translation #---------------------------------------------------- %opcode_value = ( # Type 1: OP Rn "add" => "00000", "adc" => "00001", "sub" => "00010", "sbc" => "00011", "inc" => "00100", "dec" => "00101", "cmp" => "00110", "and" => "01000", "or" => "01001", "xor" => "01010", "not" => "01011", "shl" => "01100", "shr" => "01101", "udiv" => "01110", "psh" => "10010", "pop" => "10011", "umul" => "11000", "subr" => "00111", # Type 2: OP An "ldr" => "101000", "str" => "101001", "inca" => "101100", "deca" => "101101", "jmp" => "101110", # Type 3: OP "ret" => "10111100", "ror" => "10111101", "rorc" => "10111110", "asr" => "10111111", "rdps" => "01111001", "wrps" => "01111000", "nop" => "01111010", # Type 4: OP xx yy "mov_R0_Rn" => "10000", "mov_Rn_R0" => "10001", "mov_sp_An" => "101010", "mov_An_sp" => "101011", # Type 5: OP An #offset8 "ldo" => "110010", "sto" => "110011", # Type 6: OP Rn #imm8 "ldi" => "11010", # Type 7: OP CON #offset8 "jmpr" => "11011", # Type 8: OP CON #addr16 "jmpa" => "11100", "jmps" => "11101", # Type 9: OP Rn #addr16 "lda" => "11110", "sta" => "11111", ); #--------------------------------------- # Hash table for register translation #---------------------------------------- %reg_map = ( "r0" => "000", "r1" => "001", "r2" => "010", "r3" => "011", "r4" => "100", "r5" => "101", "r6" => "110", "r7" => "111", "a0" => "00", "a1" => "01", "a2" => "10", "a3" => "11", ); #------------------------------------------ # Hash table for jmp condition translation #------------------------------------------- %condition_map = ( "eq" => "000", "ne" => "001", "gt" => "010", "lt" => "011", "cs" => "100", "cc" => "101", "ns" => "110", "al" => "111", ); #------------------------------------------ # Hash table for binary to hex translation #------------------------------------------ %bin2_hex = ( "0000" => "0", "0001" => "1", "0010" => "2", "0011" => "3", "0100" => "4", "0101" => "5", "0110" => "6", "0111" => "7", "1000" => "8", "1001" => "9", "1010" => "a", "1011" => "b", "1100" => "c", "1101" => "d", "1110" => "e", "1111" => "f", ); #------------------------------------------------------------------- # First pass: Parse the assembly file and generate a temp. file #------------------------------------------------------------------- $error = 0; $address = 0; $line_no = 0; while ($line = <ASM_F>) { chop $line; $line_o = $line; # save the original line $line =~ s/;.*//; # strip the comments $line_org = $line; $line =~ tr/A-Z/a-z/; # convert to lowercase $line_no = $line_no + 1; $opcode = ""; $start = 0; @word = split " ", $line; if($#word == -1) {next;} # empty line # process the defines for($i=0; $i <= $#word; $i = $i+1) { if($valid_subs{$word[$i]} == 1) { #print $word[$i], $subs_value{$word[$i]}; $word[$i] = $subs_value{$word[$i]}; } } # check for label if($word[0] =~ /:$/) { $label = $word[0]; $label =~ s/://g; $addr_label{$label} = $address; $valid_label{$label} = 1; #printf("LAB= %x %x\n", $addr_label{$label}, $address); if($#word == 0) { next;} else {$start = 1;} if($opcode_type{$word[$start]} < 1 and $opcode_type{$word[$start]} > 9) { printf("Error: Syntax error \"%s\" at line %d: %s\n", $word[$start], $line_no, $line_o); $error = $error + 1; } } # else it should match a key word if($opcode_type{$word[$start]} == 0) { printf("Error: Syntax error \"%s\" at line %d: %s\n", $word[0], $line_no, $line_o); $error = $error + 1; } #---------------- # Type 1: Op Rn #---------------- elsif($opcode_type{$word[$start]} == 1) { check_argument_count($#word, ($start+1)); check_data_register($word[$start+1]); $opcode = $opcode_value{$word[$start]} . $reg_map{$word[$start+1]}; printf TMP_F ("opcode=%s\n", $opcode); $address = $address + 1; } #---------------- # Type 2; OP An #---------------- elsif($opcode_type{$word[$start]} == 2) { check_argument_count($#word, ($start+1)); check_address_register($word[$start+1]); $opcode = $opcode_value{$word[$start]} . $reg_map{$word[$start+1]}; printf TMP_F ("opcode=%s\n", $opcode); $address = $address + 1; } #---------------- # Type 3; OP #---------------- elsif($opcode_type{$word[$start]} == 3) { check_argument_count($#word, $start); $opcode = $opcode_value{$word[$start]}; printf TMP_F ("opcode=%s\n", $opcode); $address = $address + 1; } #-------------------------------------------------------------------------- # Type 4; Mov ; Special case, since MOV doesn't produce one unique opcode #-------------------------------------------------------------------------- elsif($opcode_type{$word[$start]} == 4) { check_argument_count($#word, ($start+2)); check_mov_registers($word[$start+1]); check_mov_registers($word[$start+2]); if($word[$start+1] eq "sp") { # mov sp An check_address_register($word[$start+2]); $opcode = $opcode_value{mov_sp_An} . $reg_map{$word[$start+2]}; } elsif($word[$start+1] =~ /^(a0|a1|a2|a3)$/) { # mov An sp if($word[$start+2] ne "sp") { printf("Error: Invalid move argument \"%s\" at line %d: %s\n", $word[$start+2], $line_no, $line_o); $error = $error + 1; } else { $opcode = $opcode_value{mov_An_sp} . $reg_map{$word[$start+1]};} } elsif(($word[$start+1] =~ /^(r0|r1|r2|r3|r4|r5|r6|r7)$/) and # mov Rn, R0 ($word[$start+2] eq "r0")) { $opcode = $opcode_value{"mov_Rn_R0"} . $reg_map{$word[$start+1]}; } elsif(($word[$start+2] =~ /^(r0|r1|r2|r3|r4|r5|r6|r7)$/) and # mov R0 Rn ($word[$start+1] eq "r0")) { $opcode = $opcode_value{"mov_R0_Rn"} . $reg_map{$word[$start+2]}; } else { printf("Error: Invalid mov arguments at line %d: %s\n", $line_no, $line_o); $error = $error + 1; } printf TMP_F ("opcode=%s\n", $opcode); $address = $address + 1; } #-------------------------- # Type 5; OP An #offset8 #-------------------------- elsif($opcode_type{$word[$start]} == 5) { check_argument_count($#word, ($start+2)); check_address_register($word[$start+1]); $opcode = $opcode_value{$word[$start]} . $reg_map{$word[$start+1]}; printf TMP_F ("opcode=%s\n", $opcode); ($status, $off) = extract_byte($word[$start+2]); if($status == 0) { printf TMP_F ("byte=%x\n", $off); } else { $error = $error + 1; printf("Error: Invalid argument \"%s\" at line %d\n", $off, $line_no);} $address = $address + 2; } #----------------------- # Type 6; OP Rn #imm8 #----------------------- elsif($opcode_type{$word[$start]} == 6) { check_argument_count($#word, ($start+2)); check_data_register($word[$start+1]); $opcode = $opcode_value{$word[$start]} . $reg_map{$word[$start+1]}; printf TMP_F ("opcode=%s\n", $opcode); ($status, $imm) = extract_byte($word[$start+2]); if($status == 0) {printf TMP_F ("byte=%x\n", $imm);} else { $error = $error + 1; printf("Error: Invalid ldi argument \"%s\" at line %d\n", $imm, $line_no);} #elsif($status == 2) { # printf TMP_F ("b_label=%s#4#%d#5#%d\n", $imm, $line_no, ($address + 1));} $address = $address + 2; } #--------------------------- # Type 7; OP Con #offset8 #--------------------------- elsif($opcode_type{$word[$start]} == 7) { check_argument_count($#word, ($start+2)); check_condition($word[$start+1]); $opcode = $opcode_value{$word[$start]} . $condition_map{$word[$start+1]}; printf TMP_F ("opcode=%s\n", $opcode); ($status, $off) = extract_byte($word[$start+2]); if($status == 0) { printf TMP_F ("byte=%x\n", $off);} elsif($status == 2) { printf TMP_F ("b_label=%s#4#%d#5#%d\n", $off,$line_no, ($address + 1));} $address = $address + 2; } #-------------------------- # Type 8; OP Con #addr16 #-------------------------- elsif($opcode_type{$word[$start]} == 8) { check_argument_count($#word, ($start+2)); check_condition($word[$start+1]); $opcode = $opcode_value{$word[$start]} . $condition_map{$word[$start+1]}; printf TMP_F ("opcode=%s\n", $opcode); ($status, $off) = extract_word($word[$start+2]); if($status == 0) { printf TMP_F ("word=%x\n", $off);} elsif($status == 2) { printf TMP_F ("w_label=%s#4#%d#5#%d\n", $off,$line_no, ($address + 2));} $address = $address + 3; } #-------------------------- # Type 9; OP Rn #addr16 #-------------------------- elsif($opcode_type{$word[$start]} == 9) { check_argument_count($#word, ($start+2)); check_data_register($word[$start+1]); $opcode = $opcode_value{$word[$start]} . $reg_map{$word[$start+1]}; printf TMP_F ("opcode=%s\n", $opcode); ($status, $off) = extract_word($word[$start+2]); if($status == 0) { printf TMP_F ("word=%x\n", $off);} elsif($status == 2) { printf TMP_F ("w_label=%s#4#%d#5#%d\n", $off,$line_no, ($address + 2));} $address = $address + 3; } #----------------------------------- # Type 10: assembler directives #----------------------------------- elsif($opcode_type{$word[0]} == 10) { if($word[$start] eq "org") { # org check_argument_count($#word, 1); $address = extract_addr($word[1]); printf TMP_F ("@%x\n", $address); } elsif($word[$start] eq "end") {last;} elsif($word[$start] eq "define") { # define check_argument_count($#word, 2); $subs_value{$word[$start+1]} = $word[$start+2]; $valid_subs{$word[$start+1]} = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -