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

📄 script_asm.pl

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 PL
📖 第 1 页 / 共 2 页
字号:
	    $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 "/* DO NOT EDIT - Generated automatically by ".$0." */\n";print OUTPUT "static 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 "static u32 A_".$i."_used\[\] __attribute((unused)) = {\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 "static u32 ".$prefix."LABELPATCHES[] __attribute((unused)) = {\n";for $patch (sort {$a <=> $b} @label_patches) {    printf OUTPUT "\t0x%08x,\n", $patch;}printf OUTPUT "};\n\n";$num_external_patches = 0;printf OUTPUT "static struct {\n\tu32\toffset;\n\tvoid\t\t*address;\n".    "} ".$prefix."EXTERNAL_PATCHES[] __attribute((unused)) = {\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 "static u32 ".$prefix."INSTRUCTIONS __attribute((unused))\t= %d;\n",     $instructions;printf OUTPUT "static u32 ".$prefix."PATCHES __attribute((unused))\t= %d;\n",     $#label_patches+1;printf OUTPUT "static u32 ".$prefix."EXTERNAL_PATCHES_LEN __attribute((unused))\t= %d;\n",    $num_external_patches;close OUTPUT;close OUTPUTU;

⌨️ 快捷键说明

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