📄 script_asm.pl
字号:
$rest = $1; $code[$address] = 0xc0_00_00_00; if ($rest =~ /^($value)\s*,\s*($value)\s*,\s*($value)\s*$/) { $count = $1; $source = $2; $dest = $3;print STDERR "Parsing MOVE MEMORY $count, $source, $dest\n" if ($debug); &parse_value ($count, 0, 0, 3); &parse_value ($source, 1, 0, 4); &parse_value ($dest, 2, 0, 4);printf STDERR "Move memory instruction = %08x,%08x,%08x\n", $code[$address], $code[$address+1], $code[$address +2] if ($debug); $address += 3; } else { die "$0 : syntax error in line $lineno : $_ expected <count>, <source>, <destination>" } } elsif ($1 =~ /^(.*)\s+(TO|SHL|SHR)\s+(.*)/i) {print STDERR "Parsing register to register move\n" if ($debug); $src = $1; $op = "\U$2\E"; $rest = $3; $code[$address] = 0x40_00_00_00; $force = ($op !~ /TO/i); print STDERR "Forcing register source \n" if ($force && $debug); if (!$force && $src =~ /^($register)\s+(-|$operator)\s+($value)\s*$/i) {print STDERR "register operand data8 source\n" if ($debug); $src_reg = "\U$1\E"; $op = "\U$2\E"; if ($op ne '-') { $data8 = $3; } else { die "- is not implemented yet.\n" } } elsif ($src =~ /^($register)\s*$/i) {print STDERR "register source\n" if ($debug); $src_reg = "\U$1\E"; # Encode register to register move as a register | 0 # move to register. if (!$force) { $op = '|'; } $data8 = 0; } elsif (!$force && $src =~ /^($value)\s*$/i) {print STDERR "data8 source\n" if ($debug); $src_reg = undef; $op = 'NONE'; $data8 = $1; } else { if (!$force) { die "$0 : syntax error in line $lineno : $_ expected <register> <data8> <register> <operand> <data8>"; } else { die"$0 : syntax error in line $lineno : $_ expected <register>"; } } if ($rest =~ /^($register)\s*(.*)$/i) { $dst_reg = "\U$1\E"; $rest = $2; } else { die "$0 : syntax error in $lineno : $_ expected <register>, got $rest"; } if ($rest =~ /^WITH\s+CARRY\s*(.*)/i) { $rest = $1; if ($op eq '+') { $code[$address] |= 0x01_00_00_00; } else { die"$0 : syntax error in $lineno : $_ WITH CARRY option is incompatible with the $op operator."; } } if ($rest !~ /^\s*$/) { die"$0 : syntax error in $lineno : $_ Expected end of line, got $rest"; } print STDERR "source = $src_reg, data = $data8 , destination = $dst_reg\n" if ($debug); # Note that Move data8 to reg is encoded as a read-modify-write # instruction. if (($src_reg eq undef) || ($src_reg eq $dst_reg)) { $code[$address] |= 0x38_00_00_00 | ($registers{$dst_reg} << 16); } elsif ($dst_reg =~ /SFBR/i) { $code[$address] |= 0x30_00_00_00 | ($registers{$src_reg} << 16); } elsif ($src_reg =~ /SFBR/i) { $code[$address] |= 0x28_00_00_00 | ($registers{$dst_reg} << 16); } else { die"$0 : Illegal combination of registers in line $lineno : $_ Either source and destination registers must be the same, or either source or destination register must be SFBR."; } $code[$address] |= $operators{$op}; &parse_value ($data8, 0, 1, 1); $code[$address] |= $operators{$op}; $code[$address + 1] = 0x00_00_00_00;# Reserved $address += 2; } else { die "$0 : syntax error in line $lineno : $_ expected (initiator) <length>, <address>, WHEN <phase> (target) <length>, <address>, WITH <phase> MEMORY <length>, <source>, <destination> <expression> TO <register>"; }# Process SELECT {ATN|} id, fail_address } elsif (/^\s*(SELECT|RESELECT)\s+(.*)/i) { $rest = $2; if ($rest =~ /^(ATN|)\s*($value)\s*,\s*($identifier)\s*$/i) { $atn = $1; $id = $2; $alt_addr = $3; $code[$address] = 0x40_00_00_00 | (($atn =~ /ATN/i) ? 0x01_00_00_00 : 0); $code[$address + 1] = 0x00_00_00_00; &parse_value($id, 0, 2, 1); &parse_value($alt_addr, 1, 0, 4); $address += 2; } elsif ($rest =~ /^(ATN|)\s*FROM\s+($value)\s*,\s*($identifier)\s*$/i) { $atn = $1; $addr = $2; $alt_addr = $3; $code[$address] = 0x42_00_00_00 | (($atn =~ /ATN/i) ? 0x01_00_00_00 : 0); $code[$address + 1] = 0x00_00_00_00; &parse_value($addr, 0, 0, 3); &parse_value($alt_addr, 1, 0, 4); $address += 2; } else { die "$0 : syntax error in line $lineno : $_ expected SELECT id, alternate_address or SELECT FROM address, alternate_address or RESELECT id, alternate_address or RESELECT FROM address, alternate_address"; } } elsif (/^\s*WAIT\s+(.*)/i) { $rest = $1;print STDERR "Parsing WAIT $rest\n" if ($debug); if ($rest =~ /^DISCONNECT\s*$/i) { $code[$address] = 0x48_00_00_00; $code[$address + 1] = 0x00_00_00_00; $address += 2; } elsif ($rest =~ /^(RESELECT|SELECT)\s+($identifier)\s*$/i) { $alt_addr = $2; $code[$address] = 0x50_00_00_00; &parse_value ($alt_addr, 1, 0, 4); $address += 2; } else { die"$0 : syntax error in line $lineno : $_ expected (initiator) WAIT DISCONNECT or (initiator) WAIT RESELECT alternate_address or (target) WAIT SELECT alternate_address"; }# Handle SET and CLEAR instructions. Note that we should also do something# with this syntax to set target mode. } elsif (/^\s*(SET|CLEAR)\s+(.*)/i) { $set = $1; $list = $2; $code[$address] = ($set =~ /SET/i) ? 0x58_00_00_00 : 0x60_00_00_00; foreach $arg (split (/\s+AND\s+/i,$list)) { if ($arg =~ /ATN/i) { $code[$address] |= 0x00_00_00_08; } elsif ($arg =~ /ACK/i) { $code[$address] |= 0x00_00_00_40; } elsif ($arg =~ /TARGET/i) { $code[$address] |= 0x00_00_02_00; } elsif ($arg =~ /CARRY/i) { $code[$address] |= 0x00_00_04_00; } else { die "$0 : syntax error in line $lineno : $_ expected $set followed by a AND delimited list of one or more strings from the list ACK, ATN, CARRY, TARGET."; } } $code[$address + 1] = 0x00_00_00_00; $address += 2; } elsif (/^\s*(JUMP|CALL|INT)\s+(.*)/i) { $instruction = $1; $rest = $2; if ($instruction =~ /JUMP/i) { $code[$address] = 0x80_00_00_00; } elsif ($instruction =~ /CALL/i) { $code[$address] = 0x88_00_00_00; } else { $code[$address] = 0x98_00_00_00; }print STDERR "parsing JUMP, rest = $rest\n" if ($debug);# Relative jump. if ($rest =~ /^(REL\s*\(\s*$identifier\s*\))\s*(.*)/i) { $addr = $1; $rest = $2;print STDERR "parsing JUMP REL, addr = $addr, rest = $rest\n" if ($debug); $code[$address] |= 0x00_80_00_00; &parse_value($addr, 1, 0, 4);# Absolute jump, requires no more gunk } elsif ($rest =~ /^($value)\s*(.*)/) { $addr = $1; $rest = $2; &parse_value($addr, 1, 0, 4); } else { die"$0 : syntax error in line $lineno : $_ expected <address> or REL (address)"; } if ($rest =~ /^,\s*(.*)/) { &parse_conditional($1); } elsif ($rest =~ /^\s*$/) { $code[$address] |= (1 << 19); } else { die"$0 : syntax error in line $lineno : $_ expected , <conditional> or end of line, got $1"; } $address += 2; } elsif (/^\s*(RETURN|INTFLY)\s*(.*)/i) { $instruction = $1; $conditional = $2; print STDERR "Parsing $instruction\n" if ($debug); $code[$address] = ($instruction =~ /RETURN/i) ? 0x90_00_00_00 : 0x98_10_00_00; if ($conditional =~ /^,\s*(.*)/) { $conditional = $1; &parse_conditional ($conditional); } elsif ($conditional !~ /^\s*$/) { die"$0 : syntax error in line $lineno : $_ expected , <conditional> "; } else { $code[$address] |= 0x00_08_00_00; } $code[$address + 1] = 0x00_00_00_00; $address += 2; } elsif (/^\s*DISCONNECT\s*$/) { $code[$address] = 0x48_00_00_00; $code[$address + 1] = 0x00_00_00_00; $address += 2;# I'm not sure that I should be including this extension, but # what the hell? } elsif (/^\s*NOP\s*$/i) { $code[$address] = 0x80_88_00_00; $code[$address + 1] = 0x00_00_00_00; $address += 2;# Ignore lines consisting entirely of white space } elsif (/^\s*$/) { } else { die "$0 : syntax error in line $lineno: $_ expected label:, ABSOLUTE, CLEAR, DISCONNECT, EXTERNAL, MOVE, RESELECT, SELECT SET, or WAIT"; }}# Fill in label references@undefined = keys %forward;if ($#undefined >= 0) { print STDERR "Undefined symbols : \n"; foreach $undef (@undefined) { print STDERR "$undef in $forward{$undef}\n"; } exit 1;}@label_patches = ();@external_patches = ();@absolute = sort @absolute;foreach $i (@absolute) { foreach $j (split (/\s+/,$symbol_references{$i})) { $j =~ /(REL|ABS),(.*),(.*)/; $type = $1; $address = $2; $length = $3; die "$0 : $symbol $i has illegal relative reference at address $address, size $length\n" if ($type eq 'REL'); &patch ($address / 4, $address % 4, $length, $symbol_values{$i}); }}foreach $external (@external) {print STDERR "checking external $external \n" if ($debug_external); if ($symbol_references{$external} ne undef) { for $reference (split(/\s+/,$symbol_references{$external})) { $reference =~ /(REL|ABS),(.*),(.*)/; $type = $1; $address = $2; $length = $3; die "$0 : symbol $label is external, has illegal relative reference at $address, size $length\n" if ($type eq 'REL'); die "$0 : symbol $label has illegal reference at $address, size $length\n" if ((($address % 4) !=0) || ($length != 4)); $symbol = $symbol_values{$external}; $add = $code[$address / 4]; if ($add eq 0) { $code[$address / 4] = $symbol; } else { $add = sprintf ("0x%08x", $add); $code[$address / 4] = "$symbol + $add"; } print STDERR "referenced external $external at $1\n" if ($debug_external); } }}foreach $label (@label) { if ($symbol_references{$label} ne undef) { for $reference (split(/\s+/,$symbol_references{$label})) { $reference =~ /(REL|ABS),(.*),(.*)/; $type = $1; $address = $2; $length = $3; if ((($address % 4) !=0) || ($length != 4)) { die "$0 : symbol $label has illegal reference at $1, size $2\n"; } if ($type eq 'ABS') { $code[$address / 4] += $symbol_values{$label}; push (@label_patches, $address / 4); } else {# # - The address of the reference should be in the second and last word# of an instruction# - Relative jumps, etc. are relative to the DSP of the _next_ instruction## So, we need to add four to the address of the reference, to get # the address of the next instruction, when computing the reference. $tmp = $symbol_values{$label} - ($address + 4); die # Relative addressing is limited to 24 bits."$0 : symbol $label is too far ($tmp) from $address to reference as relative/\n" if (($tmp >= 0x80_00_00) || ($tmp < -0x80_00_00)); $code[$address / 4] = $tmp & 0x00_ff_ff_ff; } } }}# Output SCRIPT[] array, one instruction per line. Optionally # print the original code too.open (OUTPUT, ">$output") || die "$0 : can't open $output for writing\n";open (OUTPUTU, ">$outputu") || die "$0 : can't open $outputu for writing\n";print OUTPUT "u32 ".$prefix."SCRIPT[] = {\n";$instructions = 0;for ($i = 0; $i < $#code; ) { if ($list_in_array) { printf OUTPUT "/*\n$list[$i]\nat 0x%08x : */", $i; } printf OUTPUT "\t0x%08x,", $code[$i]; printf STDERR "Address $i = %x\n", $code[$i] if ($debug); if ($code[$i + 1] =~ /\s*($identifier)(.*)$/) { push (@external_patches, $i+1, $1); printf OUTPUT "0%s,", $2 } else { printf OUTPUT "0x%08x,",$code[$i+1]; } if (($code[$i] & 0xff_00_00_00) == 0xc0_00_00_00) { if ($code[$i + 2] =~ /$identifier/) { push (@external_patches, $i+2, $code[$i+2]); printf OUTPUT "0,\n"; } else { printf OUTPUT "0x%08x,\n",$code[$i+2]; } $i += 3; } else { printf OUTPUT "\n"; $i += 2; } $instructions += 1;}print OUTPUT "};\n\n";foreach $i (@absolute) { printf OUTPUT "#define A_$i\t0x%08x\n", $symbol_values{$i}; if (defined($prefix) && $prefix ne '') { printf OUTPUT "#define A_".$i."_used ".$prefix."A_".$i."_used\n"; printf OUTPUTU "#undef A_".$i."_used\n"; } printf OUTPUTU "#undef A_$i\n"; printf OUTPUT "u32 A_".$i."_used\[\] = {\n";printf STDERR "$i is used $symbol_references{$i}\n" if ($debug); foreach $j (split (/\s+/,$symbol_references{$i})) { $j =~ /(ABS|REL),(.*),(.*)/; if ($1 eq 'ABS') { $address = $2; $length = $3; printf OUTPUT "\t0x%08x,\n", $address / 4; } } printf OUTPUT "};\n\n";}foreach $i (sort @entry) { printf OUTPUT "#define Ent_$i\t0x%08x\n", $symbol_values{$i}; printf OUTPUTU "#undef Ent_$i\n", $symbol_values{$i};}## NCR assembler outputs label patches in the form of indices into # the code.#printf OUTPUT "u32 ".$prefix."LABELPATCHES[] = {\n";for $patch (sort {$a <=> $b} @label_patches) { printf OUTPUT "\t0x%08x,\n", $patch;}printf OUTPUT "};\n\n";$num_external_patches = 0;printf OUTPUT "struct {\n\tu32\toffset;\n\tvoid\t\t*address;\n". "} ".$prefix."EXTERNAL_PATCHES[] = {\n";while ($ident = pop(@external_patches)) { $off = pop(@external_patches); printf OUTPUT "\t{0x%08x, &%s},\n", $off, $ident; ++$num_external_patches;}printf OUTPUT "};\n\n";printf OUTPUT "u32 ".$prefix."INSTRUCTIONS\t= %d;\n", $instructions;printf OUTPUT "u32 ".$prefix."PATCHES\t= %d;\n", $#label_patches+1;printf OUTPUT "u32 ".$prefix."EXTERNAL_PATCHES_LEN\t= %d;\n", $num_external_patches;close OUTPUT;close OUTPUTU;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -