⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 risc8_asm_pl.txt

📁 这是一篇关于8位RISC CPU设计的文章
💻 TXT
📖 第 1 页 / 共 2 页
字号:
#! /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 + -