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

📄 script_asm.pl

📁 基于组件方式开发操作系统的OSKIT源代码
💻 PL
📖 第 1 页 / 共 2 页
字号:
#!/usr/bin/perl -s# NCR 53c810 script assembler# Sponsored by #       iX Multiuser Multitasking Magazine## Copyright 1993, Drew Eckhardt#      Visionary Computing #      (Unix and Linux consulting and custom programming)#      drew@Colorado.EDU#      +1 (303) 786-7975 ##   Support for 53c710 (via -ncr7x0_family switch) added by Richard#   Hirst <richard@sleepie.demon.co.uk> - 15th March 1997##   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 2 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 program; if not, write to the Free Software#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.## TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.## # Basically, I follow the NCR syntax documented in the NCR53c710 # Programmer's guide, with the new instructions, registers, etc.# from the NCR53c810.## Differences between this assembler and NCR's are that # 1.  PASS, REL (data, JUMPs work fine), and the option to start a new #	script,  are unimplemented, since I didn't use them in my scripts.# # 2.  I also emit a script_u.h file, which will undefine all of # 	the A_*, E_*, etc. symbols defined in the script.  This #	makes including multiple scripts in one program easier# 	# 3.  This is a single pass assembler, which only emits #	.h files.## XXX - set these with command line options$debug = 0;		# Print general debugging messages$debug_external = 0;	# Print external/forward reference messages$list_in_array = 1;	# Emit original SCRIPTS assembler in comments in			# script.h$prefix = '';		# define all arrays having this prefix so we 			# don't have name space collisions after 			# assembling this file in different ways for			# different host adapters# Constants# Table of the SCSI phase encodings%scsi_phases = ( 			    'DATA_OUT', 0x00_00_00_00, 'DATA_IN', 0x01_00_00_00, 'CMD', 0x02_00_00_00,    'STATUS', 0x03_00_00_00, 'MSG_OUT', 0x06_00_00_00, 'MSG_IN', 0x07_00_00_00);# XXX - replace references to the *_810 constants with general constants# assigned at compile time based on chip type.# Table of operator encodings# XXX - NCR53c710 only implements # 	move (nop) = 0x00_00_00_00#	or = 0x02_00_00_00# 	and = 0x04_00_00_00# 	add = 0x06_00_00_00if ($ncr7x0_family) {  %operators = (    '|', 0x02_00_00_00, 'OR', 0x02_00_00_00,    '&', 0x04_00_00_00, 'AND', 0x04_00_00_00,    '+', 0x06_00_00_00  );}else {  %operators = (    'SHL',  0x01_00_00_00,     '|', 0x02_00_00_00, 'OR', 0x02_00_00_00,     'XOR', 0x03_00_00_00,     '&', 0x04_00_00_00, 'AND', 0x04_00_00_00,     'SHR', 0x05_00_00_00,     # Note : low bit of the operator bit should be set for add with     # carry.    '+', 0x06_00_00_00   );}# Table of register addressesif ($ncr7x0_family) {  %registers = (    'SCNTL0', 0, 'SCNTL1', 1, 'SDID', 2, 'SIEN', 3,    'SCID', 4, 'SXFER', 5, 'SODL', 6, 'SOCL', 7,    'SFBR', 8, 'SIDL', 9, 'SBDL', 10, 'SBCL', 11,    'DSTAT', 12, 'SSTAT0', 13, 'SSTAT1', 14, 'SSTAT2', 15,    'DSA0', 16, 'DSA1', 17, 'DSA2', 18, 'DSA3', 19,    'CTEST0', 20, 'CTEST1', 21, 'CTEST2', 22, 'CTEST3', 23,    'CTEST4', 24, 'CTEST5', 25, 'CTEST6', 26, 'CTEST7', 27,    'TEMP0', 28, 'TEMP1', 29, 'TEMP2', 30, 'TEMP3', 31,    'DFIFO', 32, 'ISTAT', 33, 'CTEST8', 34, 'LCRC', 35,    'DBC0', 36, 'DBC1', 37, 'DBC2', 38, 'DCMD', 39,    'DNAD0', 40, 'DNAD1', 41, 'DNAD2', 42, 'DNAD3', 43,    'DSP0', 44, 'DSP1', 45, 'DSP2', 46, 'DSP3', 47,    'DSPS0', 48, 'DSPS1', 49, 'DSPS2', 50, 'DSPS3', 51,    'SCRATCH0', 52, 'SCRATCH1', 53, 'SCRATCH2', 54, 'SCRATCH3', 55,    'DMODE', 56, 'DIEN', 57, 'DWT', 58, 'DCNTL', 59,    'ADDER0', 60, 'ADDER1', 61, 'ADDER2', 62, 'ADDER3', 63,  );}else {  %registers = (    'SCNTL0', 0, 'SCNTL1', 1, 'SCNTL2', 2, 'SCNTL3', 3,    'SCID', 4, 'SXFER', 5, 'SDID', 6, 'GPREG', 7,    'SFBR', 8, 'SOCL', 9, 'SSID', 10, 'SBCL', 11,    'DSTAT', 12, 'SSTAT0', 13, 'SSTAT1', 14, 'SSTAT2', 15,    'DSA0', 16, 'DSA1', 17, 'DSA2', 18, 'DSA3', 19,    'ISTAT', 20,    'CTEST0', 24, 'CTEST1', 25, 'CTEST2', 26, 'CTEST3', 27,    'TEMP0', 28, 'TEMP1', 29, 'TEMP2', 30, 'TEMP3', 31,    'DFIFO', 32, 'CTEST4', 33, 'CTEST5', 34, 'CTEST6', 35,    'DBC0', 36, 'DBC1', 37, 'DBC2', 38, 'DCMD', 39,    'DNAD0', 40, 'DNAD1', 41, 'DNAD2', 42, 'DNAD3', 43,    'DSP0', 44, 'DSP1', 45, 'DSP2', 46, 'DSP3', 47,    'DSPS0', 48, 'DSPS1', 49, 'DSPS2', 50, 'DSPS3', 51,    'SCRATCH0', 52, 'SCRATCH1', 53, 'SCRATCH2', 54, 'SCRATCH3', 55,    'SCRATCHA0', 52, 'SCRATCHA1', 53, 'SCRATCHA2', 54, 'SCRATCHA3', 55,    'DMODE', 56, 'DIEN', 57, 'DWT', 58, 'DCNTL', 59,    'ADDER0', 60, 'ADDER1', 61, 'ADDER2', 62, 'ADDER3', 63,    'SIEN0', 64, 'SIEN1', 65, 'SIST0', 66, 'SIST1', 67,    'SLPAR', 68, 	      'MACNTL', 70, 'GPCNTL', 71,    'STIME0', 72, 'STIME1', 73, 'RESPID', 74,     'STEST0', 76, 'STEST1', 77, 'STEST2', 78, 'STEST3', 79,    'SIDL', 80,    'SODL', 84,    'SBDL', 88,    'SCRATCHB0', 92, 'SCRATCHB1', 93, 'SCRATCHB2', 94, 'SCRATCHB3', 95  );}# Parsing regular expressions$identifier = '[A-Za-z_][A-Za-z_0-9]*';		$decnum = '-?\\d+';$hexnum = '0[xX][0-9A-Fa-f]+';		$constant = "$hexnum|$decnum";# yucky - since we can't control grouping of # $constant, we need to # expand out each alternative for $value.$value = "$identifier|$identifier\\s*[+\-]\\s*$decnum|".    "$identifier\\s*[+-]\s*$hexnum|$constant";print STDERR "value regex = $value\n" if ($debug);$phase = join ('|', keys %scsi_phases);print STDERR "phase regex = $phase\n" if ($debug);$register = join ('|', keys %registers);# yucky - since %operators includes meta-characters which must# be escaped, I can't use the join() trick I used for the register# regexif ($ncr7x0_family) {  $operator = '\||OR|AND|\&|\+';}else {  $operator = '\||OR|AND|XOR|\&|\+';}# Global variables%symbol_values = (%registers) ;		# Traditional symbol table%symbol_references = () ;		# Table of symbol references, where					# the index is the symbol name, 					# and the contents a white space 					# delimited list of address,size					# tuples where size is in bytes.@code = ();				# Array of 32 bit words for SIOP @entry = ();				# Array of entry point names@label = ();				# Array of label names@absolute = ();				# Array of absolute names@relative = ();				# Array of relative names@external = ();				# Array of external names$address = 0;				# Address of current instruction$lineno = 0;				# Line number we are parsing$output = 'script.h';			# Output file$outputu = 'scriptu.h';# &patch ($address, $offset, $length, $value) patches $code[$address]# 	so that the $length bytes at $offset have $value added to# 	them.  @inverted_masks = (0x00_00_00_00, 0x00_00_00_ff, 0x00_00_ff_ff, 0x00_ff_ff_ff,     0xff_ff_ff_ff);sub patch {    local ($address, $offset, $length, $value) = @_;    if ($debug) {	print STDERR "Patching $address at offset $offset, length $length to $value\n";	printf STDERR "Old code : %08x\n", $code[$address];     }    $mask = ($inverted_masks[$length] << ($offset * 8));       $code[$address] = ($code[$address] & ~$mask) | 	(($code[$address] & $mask) + ($value << ($offset * 8)) & 	$mask);        printf STDERR "New code : %08x\n", $code[$address] if ($debug);}# &parse_value($value, $word, $offset, $length) where $value is # 	an identifier or constant, $word is the word offset relative to #	$address, $offset is the starting byte within that word, and #	$length is the length of the field in bytes.## Side effects are that the bytes are combined into the @code array#	relative to $address, and that the %symbol_references table is # 	updated as appropriate.sub parse_value {    local ($value, $word, $offset, $length) = @_;    local ($tmp);    $symbol = '';    if ($value =~ /^REL\s*\(\s*($identifier)\s*\)\s*(.*)/i) {	$relative = 'REL';	$symbol = $1;	$value = $2;print STDERR "Relative reference $symbol\n" if ($debug);    } elsif ($value =~ /^($identifier)\s*(.*)/) {	$relative = 'ABS';	$symbol = $1;	$value = $2;print STDERR "Absolute reference $symbol\n" if ($debug);    }     if ($symbol ne '') {print STDERR "Referencing symbol $1, length = $length in $_\n" if ($debug);     	$tmp = ($address + $word) * 4 + $offset;	if ($symbol_references{$symbol} ne undef) {	    $symbol_references{$symbol} = 		"$symbol_references{$symbol} $relative,$tmp,$length";	} else {	    if (!defined($symbol_values{$symbol})) {print STDERR "forward $1\n" if ($debug_external);		$forward{$symbol} = "line $lineno : $_";	    } 	    $symbol_references{$symbol} = "$relative,$tmp,$length";	}    }     $value = eval $value;    &patch ($address + $word, $offset, $length, $value);}# &parse_conditional ($conditional) where $conditional is the conditional# clause from a transfer control instruction (RETURN, CALL, JUMP, INT).sub parse_conditional {    local ($conditional) = @_;    if ($conditional =~ /^\s*(IF|WHEN)\s*(.*)/i) {	$if = $1;	$conditional = $2;	if ($if =~ /WHEN/i) {	    $allow_atn = 0;	    $code[$address] |= 0x00_01_00_00;	    $allow_atn = 0;	    print STDERR "$0 : parsed WHEN\n" if ($debug);	} else {	    $allow_atn = 1;	    print STDERR "$0 : parsed IF\n" if ($debug);	}    } else {	    die "$0 : syntax error in line $lineno : $_	expected IF or WHEN";    }    if ($conditional =~ /^NOT\s+(.*)$/i) {	$not = 'NOT ';	$other = 'OR';	$conditional = $1;	print STDERR "$0 : parsed NOT\n" if ($debug);    } else {	$code[$address] |= 0x00_08_00_00;	$not = '';	$other = 'AND'    }    $need_data = 0;    if ($conditional =~ /^ATN\s*(.*)/i) {#	die "$0 : syntax error in line $lineno : $_	WHEN conditional is incompatible with ATN " if (!$allow_atn);	$code[$address] |= 0x00_02_00_00;	$conditional = $1;	print STDERR "$0 : parsed ATN\n" if ($debug);    } elsif ($conditional =~ /^($phase)\s*(.*)/i) {	$phase_index = "\U$1\E";	$p = $scsi_phases{$phase_index};	$code[$address] |= $p | 0x00_02_00_00;	$conditional = $2;	print STDERR "$0 : parsed phase $phase_index\n" if ($debug);    } else {	$other = '';	$need_data = 1;    }print STDERR "Parsing conjunction, expecting $other\n" if ($debug);    if ($conditional =~ /^(AND|OR)\s*(.*)/i) {	$conjunction = $1;	$conditional = $2;	$need_data = 1;	die "$0 : syntax error in line $lineno : $_	    Illegal use of $1.  Valid uses are 	    ".$not."<phase> $1 data	    ".$not."ATN $1 data" if ($other eq '');	die "$0 : syntax error in line $lineno : $_	Illegal use of $conjunction.  Valid syntaxes are 		NOT <phase>|ATN OR data		<phase>|ATN AND data" if ($conjunction !~ /\s*$other\s*/i);	print STDERR "$0 : parsed $1\n" if ($debug);    }    if ($need_data) {print STDERR "looking for data in $conditional\n" if ($debug);	if ($conditional=~ /^($value)\s*(.*)/i) {	    $code[$address] |= 0x00_04_00_00;	    $conditional = $2;	    &parse_value($1, 0, 0, 1);	    print STDERR "$0 : parsed data\n" if ($debug);	} else {	die "$0 : syntax error in line $lineno : $_	expected <data>.";	}    }    if ($conditional =~ /^\s*,\s*(.*)/) {	$conditional = $1;	if ($conditional =~ /^AND\s\s*MASK\s\s*($value)\s*(.*)/i) {	    &parse_value ($1, 0, 1, 1);	    print STDERR "$0 parsed AND MASK $1\n" if ($debug);	    die "$0 : syntax error in line $lineno : $_	expected end of line, not \"$2\"" if ($2 ne '');	} else {	    die "$0 : syntax error in line $lineno : $_	expected \",AND MASK <data>\", not \"$2\"";	}    } elsif ($conditional !~ /^\s*$/) { 	die "$0 : syntax error in line $lineno : $_	expected end of line" . (($need_data) ? " or \"AND MASK <data>\"" : "") . "	not \"$conditional\"";    }}# Parse command line foreach $arg (@argv) {    if ($arg =~ /^-prefix\s*=\s*([_a-zA-Z][_a-zA-Z0-9]*)$/i) {	$prefix = $1    }}    # Main loopwhile (<STDIN>) {    $lineno = $lineno + 1;    $list[$address] = $list[$address].$_;    s/;.*$//;				# Strip comments    chop;				# Leave new line out of error messages# Handle symbol definitions of the form label:    if (/^\s*($identifier)\s*:(.*)/) {	if (!defined($symbol_values{$1})) {	    $symbol_values{$1} = $address * 4;	# Address is an index into	    delete $forward{$1};		# an array of longs	    push (@label, $1);	    $_ = $2;	} else {	    die "$0 : redefinition of symbol $1 in line $lineno : $_\n";	}    }# Handle symbol definitions of the form ABSOLUTE or RELATIVE identifier = # value    if (/^\s*(ABSOLUTE|RELATIVE)\s+(.*)/i) {	$is_absolute = $1;	$rest = $2;	foreach $rest (split (/\s*,\s*/, $rest)) {	    if ($rest =~ /^($identifier)\s*=\s*($constant)\s*$/) {	        local ($id, $cnst) = ($1, $2);		if ($symbol_values{$id} eq undef) {		    $symbol_values{$id} = eval $cnst;		    delete $forward{$id};		    if ($is_absolute =~ /ABSOLUTE/i) {			push (@absolute , $id);		    } else {			push (@relative, $id);		    }		} else {		    die "$0 : redefinition of symbol $id in line $lineno : $_\n";		}	    } else {		die "$0 : syntax error in line $lineno : $_	    expected <identifier> = <value>";	    }	}    } elsif (/^\s*EXTERNAL\s+(.*)/i) {	$externals = $1;	foreach $external (split (/,/,$externals)) {	    if ($external =~ /\s*($identifier)\s*$/) {		$external = $1;		push (@external, $external);		delete $forward{$external};		if (defined($symbol_values{$external})) {			die "$0 : redefinition of symbol $1 in line $lineno : $_\n";		}		$symbol_values{$external} = $external;print STDERR "defined external $1 to $external\n" if ($debug_external);	    } else {		die "$0 : syntax error in line $lineno : $_	expected <identifier>, got $external";	    }	}# Process ENTRY identifier declarations    } elsif (/^\s*ENTRY\s+(.*)/i) {	if ($1 =~ /^($identifier)\s*$/) {	    push (@entry, $1);	} else {	    die"$0 : syntax error in line $lineno : $_	expected ENTRY <identifier>";	}# Process MOVE length, address, WITH|WHEN phase instruction    } elsif (/^\s*MOVE\s+(.*)/i) {	$rest = $1;	if ($rest =~ /^FROM\s+($value)\s*,\s*(WITH|WHEN)\s+($phase)\s*$/i) {	    $transfer_addr = $1;	    $with_when = $2;	    $scsi_phase = $3;print STDERR "Parsing MOVE FROM $transfer_addr, $with_when $3\n" if ($debug);	    $code[$address] = 0x18_00_00_00 | (($with_when =~ /WITH/i) ? 		0x00_00_00_00 : 0x08_00_00_00) | $scsi_phases{$scsi_phase};	    &parse_value ($transfer_addr, 1, 0, 4);	    $address += 2;	} elsif ($rest =~ /^($value)\s*,\s*(PTR\s+|)($value)\s*,\s*(WITH|WHEN)\s+($phase)\s*$/i) {	    $transfer_len = $1;	    $ptr = $2;	    $transfer_addr = $3;	    $with_when = $4;	    $scsi_phase = $5;	    $code[$address] = (($with_when =~ /WITH/i) ? 0x00_00_00_00 : 		0x08_00_00_00)  | (($ptr =~ /PTR/i) ? (1 << 29) : 0) | 		$scsi_phases{$scsi_phase};	    &parse_value ($transfer_len, 0, 0, 3);	    &parse_value ($transfer_addr, 1, 0, 4);	    $address += 2;	} elsif ($rest =~ /^MEMORY\s+(.*)/i) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -