0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 $debug = 0;
0040 $debug_external = 0;
0041 $list_in_array = 1;
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 %scsi_phases = (
0054 'DATA_OUT', 0x00_00_00_00, 'DATA_IN', 0x01_00_00_00, 'CMD', 0x02_00_00_00,
0055 'STATUS', 0x03_00_00_00, 'MSG_OUT', 0x06_00_00_00, 'MSG_IN', 0x07_00_00_00
0056 );
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 if ($ncr7x0_family) {
0069 %operators = (
0070 '|', 0x02_00_00_00, 'OR', 0x02_00_00_00,
0071 '&', 0x04_00_00_00, 'AND', 0x04_00_00_00,
0072 '+', 0x06_00_00_00
0073 );
0074 }
0075 else {
0076 %operators = (
0077 'SHL', 0x01_00_00_00,
0078 '|', 0x02_00_00_00, 'OR', 0x02_00_00_00,
0079 'XOR', 0x03_00_00_00,
0080 '&', 0x04_00_00_00, 'AND', 0x04_00_00_00,
0081 'SHR', 0x05_00_00_00,
0082
0083
0084 '+', 0x06_00_00_00
0085 );
0086 }
0087
0088
0089
0090 if ($ncr7x0_family) {
0091 %registers = (
0092 'SCNTL0', 0, 'SCNTL1', 1, 'SDID', 2, 'SIEN', 3,
0093 'SCID', 4, 'SXFER', 5, 'SODL', 6, 'SOCL', 7,
0094 'SFBR', 8, 'SIDL', 9, 'SBDL', 10, 'SBCL', 11,
0095 'DSTAT', 12, 'SSTAT0', 13, 'SSTAT1', 14, 'SSTAT2', 15,
0096 'DSA0', 16, 'DSA1', 17, 'DSA2', 18, 'DSA3', 19,
0097 'CTEST0', 20, 'CTEST1', 21, 'CTEST2', 22, 'CTEST3', 23,
0098 'CTEST4', 24, 'CTEST5', 25, 'CTEST6', 26, 'CTEST7', 27,
0099 'TEMP0', 28, 'TEMP1', 29, 'TEMP2', 30, 'TEMP3', 31,
0100 'DFIFO', 32, 'ISTAT', 33, 'CTEST8', 34, 'LCRC', 35,
0101 'DBC0', 36, 'DBC1', 37, 'DBC2', 38, 'DCMD', 39,
0102 'DNAD0', 40, 'DNAD1', 41, 'DNAD2', 42, 'DNAD3', 43,
0103 'DSP0', 44, 'DSP1', 45, 'DSP2', 46, 'DSP3', 47,
0104 'DSPS0', 48, 'DSPS1', 49, 'DSPS2', 50, 'DSPS3', 51,
0105 'SCRATCH0', 52, 'SCRATCH1', 53, 'SCRATCH2', 54, 'SCRATCH3', 55,
0106 'DMODE', 56, 'DIEN', 57, 'DWT', 58, 'DCNTL', 59,
0107 'ADDER0', 60, 'ADDER1', 61, 'ADDER2', 62, 'ADDER3', 63,
0108 );
0109 }
0110 else {
0111 %registers = (
0112 'SCNTL0', 0, 'SCNTL1', 1, 'SCNTL2', 2, 'SCNTL3', 3,
0113 'SCID', 4, 'SXFER', 5, 'SDID', 6, 'GPREG', 7,
0114 'SFBR', 8, 'SOCL', 9, 'SSID', 10, 'SBCL', 11,
0115 'DSTAT', 12, 'SSTAT0', 13, 'SSTAT1', 14, 'SSTAT2', 15,
0116 'DSA0', 16, 'DSA1', 17, 'DSA2', 18, 'DSA3', 19,
0117 'ISTAT', 20,
0118 'CTEST0', 24, 'CTEST1', 25, 'CTEST2', 26, 'CTEST3', 27,
0119 'TEMP0', 28, 'TEMP1', 29, 'TEMP2', 30, 'TEMP3', 31,
0120 'DFIFO', 32, 'CTEST4', 33, 'CTEST5', 34, 'CTEST6', 35,
0121 'DBC0', 36, 'DBC1', 37, 'DBC2', 38, 'DCMD', 39,
0122 'DNAD0', 40, 'DNAD1', 41, 'DNAD2', 42, 'DNAD3', 43,
0123 'DSP0', 44, 'DSP1', 45, 'DSP2', 46, 'DSP3', 47,
0124 'DSPS0', 48, 'DSPS1', 49, 'DSPS2', 50, 'DSPS3', 51,
0125 'SCRATCH0', 52, 'SCRATCH1', 53, 'SCRATCH2', 54, 'SCRATCH3', 55,
0126 'SCRATCHA0', 52, 'SCRATCHA1', 53, 'SCRATCHA2', 54, 'SCRATCHA3', 55,
0127 'DMODE', 56, 'DIEN', 57, 'DWT', 58, 'DCNTL', 59,
0128 'ADDER0', 60, 'ADDER1', 61, 'ADDER2', 62, 'ADDER3', 63,
0129 'SIEN0', 64, 'SIEN1', 65, 'SIST0', 66, 'SIST1', 67,
0130 'SLPAR', 68, 'MACNTL', 70, 'GPCNTL', 71,
0131 'STIME0', 72, 'STIME1', 73, 'RESPID', 74,
0132 'STEST0', 76, 'STEST1', 77, 'STEST2', 78, 'STEST3', 79,
0133 'SIDL', 80,
0134 'SODL', 84,
0135 'SBDL', 88,
0136 'SCRATCHB0', 92, 'SCRATCHB1', 93, 'SCRATCHB2', 94, 'SCRATCHB3', 95
0137 );
0138 }
0139
0140
0141 $identifier = '[A-Za-z_][A-Za-z_0-9]*';
0142 $decnum = '-?\\d+';
0143 $hexnum = '0[xX][0-9A-Fa-f]+';
0144 $constant = "$hexnum|$decnum";
0145
0146
0147
0148
0149 $value = "$identifier|$identifier\\s*[+\-]\\s*$decnum|".
0150 "$identifier\\s*[+-]\s*$hexnum|$constant";
0151
0152 print STDERR "value regex = $value\n" if ($debug);
0153
0154 $phase = join ('|', keys %scsi_phases);
0155 print STDERR "phase regex = $phase\n" if ($debug);
0156 $register = join ('|', keys %registers);
0157
0158
0159
0160
0161
0162 if ($ncr7x0_family) {
0163 $operator = '\||OR|AND|\&|\+';
0164 }
0165 else {
0166 $operator = '\||OR|AND|XOR|\&|\+';
0167 }
0168
0169
0170
0171 %symbol_values = (%registers) ;
0172
0173 %symbol_references = () ;
0174
0175
0176
0177
0178
0179 @code = ();
0180
0181 @entry = ();
0182
0183 @label = ();
0184
0185 @absolute = ();
0186
0187 @relative = ();
0188
0189 @external = ();
0190
0191 $address = 0;
0192
0193 $lineno = 0;
0194
0195 $output = 'script.h';
0196 $outputu = 'scriptu.h';
0197
0198
0199
0200
0201
0202 @inverted_masks = (0x00_00_00_00, 0x00_00_00_ff, 0x00_00_ff_ff, 0x00_ff_ff_ff,
0203 0xff_ff_ff_ff);
0204
0205 sub patch {
0206 local ($address, $offset, $length, $value) = @_;
0207 if ($debug) {
0208 print STDERR "Patching $address at offset $offset, length $length to $value\n";
0209 printf STDERR "Old code : %08x\n", $code[$address];
0210 }
0211
0212 $mask = ($inverted_masks[$length] << ($offset * 8));
0213
0214 $code[$address] = ($code[$address] & ~$mask) |
0215 (($code[$address] & $mask) + ($value << ($offset * 8)) &
0216 $mask);
0217
0218 printf STDERR "New code : %08x\n", $code[$address] if ($debug);
0219 }
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230 sub parse_value {
0231 local ($value, $word, $offset, $length) = @_;
0232 local ($tmp);
0233
0234 $symbol = '';
0235
0236 if ($value =~ /^REL\s*\(\s*($identifier)\s*\)\s*(.*)/i) {
0237 $relative = 'REL';
0238 $symbol = $1;
0239 $value = $2;
0240 print STDERR "Relative reference $symbol\n" if ($debug);
0241 } elsif ($value =~ /^($identifier)\s*(.*)/) {
0242 $relative = 'ABS';
0243 $symbol = $1;
0244 $value = $2;
0245 print STDERR "Absolute reference $symbol\n" if ($debug);
0246 }
0247
0248 if ($symbol ne '') {
0249 print STDERR "Referencing symbol $1, length = $length in $_\n" if ($debug);
0250 $tmp = ($address + $word) * 4 + $offset;
0251 if ($symbol_references{$symbol} ne undef) {
0252 $symbol_references{$symbol} =
0253 "$symbol_references{$symbol} $relative,$tmp,$length";
0254 } else {
0255 if (!defined($symbol_values{$symbol})) {
0256 print STDERR "forward $1\n" if ($debug_external);
0257 $forward{$symbol} = "line $lineno : $_";
0258 }
0259 $symbol_references{$symbol} = "$relative,$tmp,$length";
0260 }
0261 }
0262
0263 $value = eval $value;
0264 &patch ($address + $word, $offset, $length, $value);
0265 }
0266
0267
0268
0269
0270 sub parse_conditional {
0271 local ($conditional) = @_;
0272 if ($conditional =~ /^\s*(IF|WHEN)\s*(.*)/i) {
0273 $if = $1;
0274 $conditional = $2;
0275 if ($if =~ /WHEN/i) {
0276 $allow_atn = 0;
0277 $code[$address] |= 0x00_01_00_00;
0278 $allow_atn = 0;
0279 print STDERR "$0 : parsed WHEN\n" if ($debug);
0280 } else {
0281 $allow_atn = 1;
0282 print STDERR "$0 : parsed IF\n" if ($debug);
0283 }
0284 } else {
0285 die "$0 : syntax error in line $lineno : $_
0286 expected IF or WHEN
0287 ";
0288 }
0289
0290 if ($conditional =~ /^NOT\s+(.*)$/i) {
0291 $not = 'NOT ';
0292 $other = 'OR';
0293 $conditional = $1;
0294 print STDERR "$0 : parsed NOT\n" if ($debug);
0295 } else {
0296 $code[$address] |= 0x00_08_00_00;
0297 $not = '';
0298 $other = 'AND'
0299 }
0300
0301 $need_data = 0;
0302 if ($conditional =~ /^ATN\s*(.*)/i) {
0303 die "$0 : syntax error in line $lineno : $_
0304 WHEN conditional is incompatible with ATN
0305 " if (!$allow_atn);
0306 $code[$address] |= 0x00_02_00_00;
0307 $conditional = $1;
0308 print STDERR "$0 : parsed ATN\n" if ($debug);
0309 } elsif ($conditional =~ /^($phase)\s*(.*)/i) {
0310 $phase_index = "\U$1\E";
0311 $p = $scsi_phases{$phase_index};
0312 $code[$address] |= $p | 0x00_02_00_00;
0313 $conditional = $2;
0314 print STDERR "$0 : parsed phase $phase_index\n" if ($debug);
0315 } else {
0316 $other = '';
0317 $need_data = 1;
0318 }
0319
0320 print STDERR "Parsing conjunction, expecting $other\n" if ($debug);
0321 if ($conditional =~ /^(AND|OR)\s*(.*)/i) {
0322 $conjunction = $1;
0323 $conditional = $2;
0324 $need_data = 1;
0325 die "$0 : syntax error in line $lineno : $_
0326 Illegal use of $1. Valid uses are
0327 ".$not."<phase> $1 data
0328 ".$not."ATN $1 data
0329 " if ($other eq '');
0330 die "$0 : syntax error in line $lineno : $_
0331 Illegal use of $conjunction. Valid syntaxes are
0332 NOT <phase>|ATN OR data
0333 <phase>|ATN AND data
0334 " if ($conjunction !~ /\s*$other\s*/i);
0335 print STDERR "$0 : parsed $1\n" if ($debug);
0336 }
0337
0338 if ($need_data) {
0339 print STDERR "looking for data in $conditional\n" if ($debug);
0340 if ($conditional=~ /^($value)\s*(.*)/i) {
0341 $code[$address] |= 0x00_04_00_00;
0342 $conditional = $2;
0343 &parse_value($1, 0, 0, 1);
0344 print STDERR "$0 : parsed data\n" if ($debug);
0345 } else {
0346 die "$0 : syntax error in line $lineno : $_
0347 expected <data>.
0348 ";
0349 }
0350 }
0351
0352 if ($conditional =~ /^\s*,\s*(.*)/) {
0353 $conditional = $1;
0354 if ($conditional =~ /^AND\s\s*MASK\s\s*($value)\s*(.*)/i) {
0355 &parse_value ($1, 0, 1, 1);
0356 print STDERR "$0 parsed AND MASK $1\n" if ($debug);
0357 die "$0 : syntax error in line $lineno : $_
0358 expected end of line, not \"$2\"
0359 " if ($2 ne '');
0360 } else {
0361 die "$0 : syntax error in line $lineno : $_
0362 expected \",AND MASK <data>\", not \"$2\"
0363 ";
0364 }
0365 } elsif ($conditional !~ /^\s*$/) {
0366 die "$0 : syntax error in line $lineno : $_
0367 expected end of line" . (($need_data) ? " or \"AND MASK <data>\"" : "") . "
0368 not \"$conditional\"
0369 ";
0370 }
0371 }
0372
0373
0374 $output = shift;
0375 $outputu = shift;
0376
0377
0378
0379 while (<STDIN>) {
0380 $lineno = $lineno + 1;
0381 $list[$address] = $list[$address].$_;
0382 s/;.*$//;
0383
0384
0385 chop;
0386
0387
0388 if (/^\s*($identifier)\s*:(.*)/) {
0389 if (!defined($symbol_values{$1})) {
0390 $symbol_values{$1} = $address * 4;
0391 delete $forward{$1};
0392 push (@label, $1);
0393 $_ = $2;
0394 } else {
0395 die "$0 : redefinition of symbol $1 in line $lineno : $_\n";
0396 }
0397 }
0398
0399
0400
0401 if (/^\s*(ABSOLUTE|RELATIVE)\s+(.*)/i) {
0402 $is_absolute = $1;
0403 $rest = $2;
0404 foreach $rest (split (/\s*,\s*/, $rest)) {
0405 if ($rest =~ /^($identifier)\s*=\s*($constant)\s*$/) {
0406 local ($id, $cnst) = ($1, $2);
0407 if ($symbol_values{$id} eq undef) {
0408 $symbol_values{$id} = eval $cnst;
0409 delete $forward{$id};
0410 if ($is_absolute =~ /ABSOLUTE/i) {
0411 push (@absolute , $id);
0412 } else {
0413 push (@relative, $id);
0414 }
0415 } else {
0416 die "$0 : redefinition of symbol $id in line $lineno : $_\n";
0417 }
0418 } else {
0419 die
0420 "$0 : syntax error in line $lineno : $_
0421 expected <identifier> = <value>
0422 ";
0423 }
0424 }
0425 } elsif (/^\s*EXTERNAL\s+(.*)/i) {
0426 $externals = $1;
0427 foreach $external (split (/,/,$externals)) {
0428 if ($external =~ /\s*($identifier)\s*$/) {
0429 $external = $1;
0430 push (@external, $external);
0431 delete $forward{$external};
0432 if (defined($symbol_values{$external})) {
0433 die "$0 : redefinition of symbol $1 in line $lineno : $_\n";
0434 }
0435 $symbol_values{$external} = $external;
0436 print STDERR "defined external $1 to $external\n" if ($debug_external);
0437 } else {
0438 die
0439 "$0 : syntax error in line $lineno : $_
0440 expected <identifier>, got $external
0441 ";
0442 }
0443 }
0444
0445 } elsif (/^\s*ENTRY\s+(.*)/i) {
0446 if ($1 =~ /^($identifier)\s*$/) {
0447 push (@entry, $1);
0448 } else {
0449 die
0450 "$0 : syntax error in line $lineno : $_
0451 expected ENTRY <identifier>
0452 ";
0453 }
0454
0455 } elsif (/^\s*MOVE\s+(.*)/i) {
0456 $rest = $1;
0457 if ($rest =~ /^FROM\s+($value)\s*,\s*(WITH|WHEN)\s+($phase)\s*$/i) {
0458 $transfer_addr = $1;
0459 $with_when = $2;
0460 $scsi_phase = $3;
0461 print STDERR "Parsing MOVE FROM $transfer_addr, $with_when $3\n" if ($debug);
0462 $code[$address] = 0x18_00_00_00 | (($with_when =~ /WITH/i) ?
0463 0x00_00_00_00 : 0x08_00_00_00) | $scsi_phases{$scsi_phase};
0464 &parse_value ($transfer_addr, 1, 0, 4);
0465 $address += 2;
0466 } elsif ($rest =~ /^($value)\s*,\s*(PTR\s+|)($value)\s*,\s*(WITH|WHEN)\s+($phase)\s*$/i) {
0467 $transfer_len = $1;
0468 $ptr = $2;
0469 $transfer_addr = $3;
0470 $with_when = $4;
0471 $scsi_phase = $5;
0472 $code[$address] = (($with_when =~ /WITH/i) ? 0x00_00_00_00 :
0473 0x08_00_00_00) | (($ptr =~ /PTR/i) ? (1 << 29) : 0) |
0474 $scsi_phases{$scsi_phase};
0475 &parse_value ($transfer_len, 0, 0, 3);
0476 &parse_value ($transfer_addr, 1, 0, 4);
0477 $address += 2;
0478 } elsif ($rest =~ /^MEMORY\s+(.*)/i) {
0479 $rest = $1;
0480 $code[$address] = 0xc0_00_00_00;
0481 if ($rest =~ /^($value)\s*,\s*($value)\s*,\s*($value)\s*$/) {
0482 $count = $1;
0483 $source = $2;
0484 $dest = $3;
0485 print STDERR "Parsing MOVE MEMORY $count, $source, $dest\n" if ($debug);
0486 &parse_value ($count, 0, 0, 3);
0487 &parse_value ($source, 1, 0, 4);
0488 &parse_value ($dest, 2, 0, 4);
0489 printf STDERR "Move memory instruction = %08x,%08x,%08x\n",
0490 $code[$address], $code[$address+1], $code[$address +2] if
0491 ($debug);
0492 $address += 3;
0493
0494 } else {
0495 die
0496 "$0 : syntax error in line $lineno : $_
0497 expected <count>, <source>, <destination>
0498 "
0499 }
0500 } elsif ($1 =~ /^(.*)\s+(TO|SHL|SHR)\s+(.*)/i) {
0501 print STDERR "Parsing register to register move\n" if ($debug);
0502 $src = $1;
0503 $op = "\U$2\E";
0504 $rest = $3;
0505
0506 $code[$address] = 0x40_00_00_00;
0507
0508 $force = ($op !~ /TO/i);
0509
0510
0511 print STDERR "Forcing register source \n" if ($force && $debug);
0512
0513 if (!$force && $src =~
0514 /^($register)\s+(-|$operator)\s+($value)\s*$/i) {
0515 print STDERR "register operand data8 source\n" if ($debug);
0516 $src_reg = "\U$1\E";
0517 $op = "\U$2\E";
0518 if ($op ne '-') {
0519 $data8 = $3;
0520 } else {
0521 die "- is not implemented yet.\n"
0522 }
0523 } elsif ($src =~ /^($register)\s*$/i) {
0524 print STDERR "register source\n" if ($debug);
0525 $src_reg = "\U$1\E";
0526
0527
0528 if (!$force) {
0529 $op = '|';
0530 }
0531 $data8 = 0;
0532 } elsif (!$force && $src =~ /^($value)\s*$/i) {
0533 print STDERR "data8 source\n" if ($debug);
0534 $src_reg = undef;
0535 $op = 'NONE';
0536 $data8 = $1;
0537 } else {
0538 if (!$force) {
0539 die
0540 "$0 : syntax error in line $lineno : $_
0541 expected <register>
0542 <data8>
0543 <register> <operand> <data8>
0544 ";
0545 } else {
0546 die
0547 "$0 : syntax error in line $lineno : $_
0548 expected <register>
0549 ";
0550 }
0551 }
0552 if ($rest =~ /^($register)\s*(.*)$/i) {
0553 $dst_reg = "\U$1\E";
0554 $rest = $2;
0555 } else {
0556 die
0557 "$0 : syntax error in $lineno : $_
0558 expected <register>, got $rest
0559 ";
0560 }
0561
0562 if ($rest =~ /^WITH\s+CARRY\s*(.*)/i) {
0563 $rest = $1;
0564 if ($op eq '+') {
0565 $code[$address] |= 0x01_00_00_00;
0566 } else {
0567 die
0568 "$0 : syntax error in $lineno : $_
0569 WITH CARRY option is incompatible with the $op operator.
0570 ";
0571 }
0572 }
0573
0574 if ($rest !~ /^\s*$/) {
0575 die
0576 "$0 : syntax error in $lineno : $_
0577 Expected end of line, got $rest
0578 ";
0579 }
0580
0581 print STDERR "source = $src_reg, data = $data8 , destination = $dst_reg\n"
0582 if ($debug);
0583
0584
0585 if (($src_reg eq undef) || ($src_reg eq $dst_reg)) {
0586 $code[$address] |= 0x38_00_00_00 |
0587 ($registers{$dst_reg} << 16);
0588 } elsif ($dst_reg =~ /SFBR/i) {
0589 $code[$address] |= 0x30_00_00_00 |
0590 ($registers{$src_reg} << 16);
0591 } elsif ($src_reg =~ /SFBR/i) {
0592 $code[$address] |= 0x28_00_00_00 |
0593 ($registers{$dst_reg} << 16);
0594 } else {
0595 die
0596 "$0 : Illegal combination of registers in line $lineno : $_
0597 Either source and destination registers must be the same,
0598 or either source or destination register must be SFBR.
0599 ";
0600 }
0601
0602 $code[$address] |= $operators{$op};
0603
0604 &parse_value ($data8, 0, 1, 1);
0605 $code[$address] |= $operators{$op};
0606 $code[$address + 1] = 0x00_00_00_00;
0607 $address += 2;
0608 } else {
0609 die
0610 "$0 : syntax error in line $lineno : $_
0611 expected (initiator) <length>, <address>, WHEN <phase>
0612 (target) <length>, <address>, WITH <phase>
0613 MEMORY <length>, <source>, <destination>
0614 <expression> TO <register>
0615 ";
0616 }
0617
0618 } elsif (/^\s*(SELECT|RESELECT)\s+(.*)/i) {
0619 $rest = $2;
0620 if ($rest =~ /^(ATN|)\s*($value)\s*,\s*($identifier)\s*$/i) {
0621 $atn = $1;
0622 $id = $2;
0623 $alt_addr = $3;
0624 $code[$address] = 0x40_00_00_00 |
0625 (($atn =~ /ATN/i) ? 0x01_00_00_00 : 0);
0626 $code[$address + 1] = 0x00_00_00_00;
0627 &parse_value($id, 0, 2, 1);
0628 &parse_value($alt_addr, 1, 0, 4);
0629 $address += 2;
0630 } elsif ($rest =~ /^(ATN|)\s*FROM\s+($value)\s*,\s*($identifier)\s*$/i) {
0631 $atn = $1;
0632 $addr = $2;
0633 $alt_addr = $3;
0634 $code[$address] = 0x42_00_00_00 |
0635 (($atn =~ /ATN/i) ? 0x01_00_00_00 : 0);
0636 $code[$address + 1] = 0x00_00_00_00;
0637 &parse_value($addr, 0, 0, 3);
0638 &parse_value($alt_addr, 1, 0, 4);
0639 $address += 2;
0640 } else {
0641 die
0642 "$0 : syntax error in line $lineno : $_
0643 expected SELECT id, alternate_address or
0644 SELECT FROM address, alternate_address or
0645 RESELECT id, alternate_address or
0646 RESELECT FROM address, alternate_address
0647 ";
0648 }
0649 } elsif (/^\s*WAIT\s+(.*)/i) {
0650 $rest = $1;
0651 print STDERR "Parsing WAIT $rest\n" if ($debug);
0652 if ($rest =~ /^DISCONNECT\s*$/i) {
0653 $code[$address] = 0x48_00_00_00;
0654 $code[$address + 1] = 0x00_00_00_00;
0655 $address += 2;
0656 } elsif ($rest =~ /^(RESELECT|SELECT)\s+($identifier)\s*$/i) {
0657 $alt_addr = $2;
0658 $code[$address] = 0x50_00_00_00;
0659 &parse_value ($alt_addr, 1, 0, 4);
0660 $address += 2;
0661 } else {
0662 die
0663 "$0 : syntax error in line $lineno : $_
0664 expected (initiator) WAIT DISCONNECT or
0665 (initiator) WAIT RESELECT alternate_address or
0666 (target) WAIT SELECT alternate_address
0667 ";
0668 }
0669
0670
0671 } elsif (/^\s*(SET|CLEAR)\s+(.*)/i) {
0672 $set = $1;
0673 $list = $2;
0674 $code[$address] = ($set =~ /SET/i) ? 0x58_00_00_00 :
0675 0x60_00_00_00;
0676 foreach $arg (split (/\s+AND\s+/i,$list)) {
0677 if ($arg =~ /ATN/i) {
0678 $code[$address] |= 0x00_00_00_08;
0679 } elsif ($arg =~ /ACK/i) {
0680 $code[$address] |= 0x00_00_00_40;
0681 } elsif ($arg =~ /TARGET/i) {
0682 $code[$address] |= 0x00_00_02_00;
0683 } elsif ($arg =~ /CARRY/i) {
0684 $code[$address] |= 0x00_00_04_00;
0685 } else {
0686 die
0687 "$0 : syntax error in line $lineno : $_
0688 expected $set followed by a AND delimited list of one or
0689 more strings from the list ACK, ATN, CARRY, TARGET.
0690 ";
0691 }
0692 }
0693 $code[$address + 1] = 0x00_00_00_00;
0694 $address += 2;
0695 } elsif (/^\s*(JUMP|CALL|INT)\s+(.*)/i) {
0696 $instruction = $1;
0697 $rest = $2;
0698 if ($instruction =~ /JUMP/i) {
0699 $code[$address] = 0x80_00_00_00;
0700 } elsif ($instruction =~ /CALL/i) {
0701 $code[$address] = 0x88_00_00_00;
0702 } else {
0703 $code[$address] = 0x98_00_00_00;
0704 }
0705 print STDERR "parsing JUMP, rest = $rest\n" if ($debug);
0706
0707
0708 if ($rest =~ /^(REL\s*\(\s*$identifier\s*\))\s*(.*)/i) {
0709 $addr = $1;
0710 $rest = $2;
0711 print STDERR "parsing JUMP REL, addr = $addr, rest = $rest\n" if ($debug);
0712 $code[$address] |= 0x00_80_00_00;
0713 &parse_value($addr, 1, 0, 4);
0714
0715 } elsif ($rest =~ /^($value)\s*(.*)/) {
0716 $addr = $1;
0717 $rest = $2;
0718 &parse_value($addr, 1, 0, 4);
0719 } else {
0720 die
0721 "$0 : syntax error in line $lineno : $_
0722 expected <address> or REL (address)
0723 ";
0724 }
0725
0726 if ($rest =~ /^,\s*(.*)/) {
0727 &parse_conditional($1);
0728 } elsif ($rest =~ /^\s*$/) {
0729 $code[$address] |= (1 << 19);
0730 } else {
0731 die
0732 "$0 : syntax error in line $lineno : $_
0733 expected , <conditional> or end of line, got $1
0734 ";
0735 }
0736
0737 $address += 2;
0738 } elsif (/^\s*(RETURN|INTFLY)\s*(.*)/i) {
0739 $instruction = $1;
0740 $conditional = $2;
0741 print STDERR "Parsing $instruction\n" if ($debug);
0742 $code[$address] = ($instruction =~ /RETURN/i) ? 0x90_00_00_00 :
0743 0x98_10_00_00;
0744 if ($conditional =~ /^,\s*(.*)/) {
0745 $conditional = $1;
0746 &parse_conditional ($conditional);
0747 } elsif ($conditional !~ /^\s*$/) {
0748 die
0749 "$0 : syntax error in line $lineno : $_
0750 expected , <conditional>
0751 ";
0752 } else {
0753 $code[$address] |= 0x00_08_00_00;
0754 }
0755
0756 $code[$address + 1] = 0x00_00_00_00;
0757 $address += 2;
0758 } elsif (/^\s*DISCONNECT\s*$/) {
0759 $code[$address] = 0x48_00_00_00;
0760 $code[$address + 1] = 0x00_00_00_00;
0761 $address += 2;
0762
0763
0764 } elsif (/^\s*NOP\s*$/i) {
0765 $code[$address] = 0x80_88_00_00;
0766 $code[$address + 1] = 0x00_00_00_00;
0767 $address += 2;
0768
0769 } elsif (/^\s*$/) {
0770 } else {
0771 die
0772 "$0 : syntax error in line $lineno: $_
0773 expected label:, ABSOLUTE, CLEAR, DISCONNECT, EXTERNAL, MOVE, RESELECT,
0774 SELECT SET, or WAIT
0775 ";
0776 }
0777 }
0778
0779
0780
0781 @undefined = keys %forward;
0782 if ($#undefined >= 0) {
0783 print STDERR "Undefined symbols : \n";
0784 foreach $undef (@undefined) {
0785 print STDERR "$undef in $forward{$undef}\n";
0786 }
0787 exit 1;
0788 }
0789
0790 @label_patches = ();
0791
0792 @external_patches = ();
0793
0794 @absolute = sort @absolute;
0795
0796 foreach $i (@absolute) {
0797 foreach $j (split (/\s+/,$symbol_references{$i})) {
0798 $j =~ /(REL|ABS),(.*),(.*)/;
0799 $type = $1;
0800 $address = $2;
0801 $length = $3;
0802 die
0803 "$0 : $symbol $i has invalid relative reference at address $address,
0804 size $length\n"
0805 if ($type eq 'REL');
0806
0807 &patch ($address / 4, $address % 4, $length, $symbol_values{$i});
0808 }
0809 }
0810
0811 foreach $external (@external) {
0812 print STDERR "checking external $external \n" if ($debug_external);
0813 if ($symbol_references{$external} ne undef) {
0814 for $reference (split(/\s+/,$symbol_references{$external})) {
0815 $reference =~ /(REL|ABS),(.*),(.*)/;
0816 $type = $1;
0817 $address = $2;
0818 $length = $3;
0819
0820 die
0821 "$0 : symbol $label is external, has invalid relative reference at $address,
0822 size $length\n"
0823 if ($type eq 'REL');
0824
0825 die
0826 "$0 : symbol $label has invalid reference at $address, size $length\n"
0827 if ((($address % 4) !=0) || ($length != 4));
0828
0829 $symbol = $symbol_values{$external};
0830 $add = $code[$address / 4];
0831 if ($add eq 0) {
0832 $code[$address / 4] = $symbol;
0833 } else {
0834 $add = sprintf ("0x%08x", $add);
0835 $code[$address / 4] = "$symbol + $add";
0836 }
0837
0838 print STDERR "referenced external $external at $1\n" if ($debug_external);
0839 }
0840 }
0841 }
0842
0843 foreach $label (@label) {
0844 if ($symbol_references{$label} ne undef) {
0845 for $reference (split(/\s+/,$symbol_references{$label})) {
0846 $reference =~ /(REL|ABS),(.*),(.*)/;
0847 $type = $1;
0848 $address = $2;
0849 $length = $3;
0850
0851 if ((($address % 4) !=0) || ($length != 4)) {
0852 die "$0 : symbol $label has invalid reference at $1, size $2\n";
0853 }
0854
0855 if ($type eq 'ABS') {
0856 $code[$address / 4] += $symbol_values{$label};
0857 push (@label_patches, $address / 4);
0858 } else {
0859
0860
0861
0862
0863
0864
0865
0866
0867 $tmp = $symbol_values{$label} -
0868 ($address + 4);
0869 die
0870
0871 "$0 : symbol $label is too far ($tmp) from $address to reference as
0872 relative/\n" if (($tmp >= 0x80_00_00) || ($tmp < -0x80_00_00));
0873 $code[$address / 4] = $tmp & 0x00_ff_ff_ff;
0874 }
0875 }
0876 }
0877 }
0878
0879
0880
0881
0882 open (OUTPUT, ">$output") || die "$0 : can't open $output for writing\n";
0883 open (OUTPUTU, ">$outputu") || die "$0 : can't open $outputu for writing\n";
0884
0885 ($_ = $0) =~ s:.*/::;
0886 print OUTPUT "/* DO NOT EDIT - Generated automatically by ".$_." */\n";
0887 print OUTPUT "static u32 ".$prefix."SCRIPT[] = {\n";
0888 $instructions = 0;
0889 for ($i = 0; $i < $#code; ) {
0890 if ($list_in_array) {
0891 printf OUTPUT "/*\n$list[$i]\nat 0x%08x : */", $i;
0892 }
0893 printf OUTPUT "\t0x%08x,", $code[$i];
0894 printf STDERR "Address $i = %x\n", $code[$i] if ($debug);
0895 if ($code[$i + 1] =~ /\s*($identifier)(.*)$/) {
0896 push (@external_patches, $i+1, $1);
0897 printf OUTPUT "0%s,", $2
0898 } else {
0899 printf OUTPUT "0x%08x,",$code[$i+1];
0900 }
0901
0902 if (($code[$i] & 0xff_00_00_00) == 0xc0_00_00_00) {
0903 if ($code[$i + 2] =~ /$identifier/) {
0904 push (@external_patches, $i+2, $code[$i+2]);
0905 printf OUTPUT "0,\n";
0906 } else {
0907 printf OUTPUT "0x%08x,\n",$code[$i+2];
0908 }
0909 $i += 3;
0910 } else {
0911 printf OUTPUT "\n";
0912 $i += 2;
0913 }
0914 $instructions += 1;
0915 }
0916 print OUTPUT "};\n\n";
0917
0918 foreach $i (@absolute) {
0919 printf OUTPUT "#define A_$i\t0x%08x\n", $symbol_values{$i};
0920 if (defined($prefix) && $prefix ne '') {
0921 printf OUTPUT "#define A_".$i."_used ".$prefix."A_".$i."_used\n";
0922 printf OUTPUTU "#undef A_".$i."_used\n";
0923 }
0924 printf OUTPUTU "#undef A_$i\n";
0925
0926 printf OUTPUT "static u32 A_".$i."_used\[\] __attribute((unused)) = {\n";
0927 printf STDERR "$i is used $symbol_references{$i}\n" if ($debug);
0928 foreach $j (split (/\s+/,$symbol_references{$i})) {
0929 $j =~ /(ABS|REL),(.*),(.*)/;
0930 if ($1 eq 'ABS') {
0931 $address = $2;
0932 $length = $3;
0933 printf OUTPUT "\t0x%08x,\n", $address / 4;
0934 }
0935 }
0936 printf OUTPUT "};\n\n";
0937 }
0938
0939 foreach $i (sort @entry) {
0940 printf OUTPUT "#define Ent_$i\t0x%08x\n", $symbol_values{$i};
0941 printf OUTPUTU "#undef Ent_$i\n", $symbol_values{$i};
0942 }
0943
0944
0945
0946
0947
0948 printf OUTPUT "static u32 ".$prefix."LABELPATCHES[] __attribute((unused)) = {\n";
0949 for $patch (sort {$a <=> $b} @label_patches) {
0950 printf OUTPUT "\t0x%08x,\n", $patch;
0951 }
0952 printf OUTPUT "};\n\n";
0953
0954 $num_external_patches = 0;
0955 printf OUTPUT "static struct {\n\tu32\toffset;\n\tvoid\t\t*address;\n".
0956 "} ".$prefix."EXTERNAL_PATCHES[] __attribute((unused)) = {\n";
0957 while ($ident = pop(@external_patches)) {
0958 $off = pop(@external_patches);
0959 printf OUTPUT "\t{0x%08x, &%s},\n", $off, $ident;
0960 ++$num_external_patches;
0961 }
0962 printf OUTPUT "};\n\n";
0963
0964 printf OUTPUT "static u32 ".$prefix."INSTRUCTIONS __attribute((unused))\t= %d;\n",
0965 $instructions;
0966 printf OUTPUT "static u32 ".$prefix."PATCHES __attribute((unused))\t= %d;\n",
0967 $#label_patches+1;
0968 printf OUTPUT "static u32 ".$prefix."EXTERNAL_PATCHES_LEN __attribute((unused))\t= %d;\n",
0969 $num_external_patches;
0970 close OUTPUT;
0971 close OUTPUTU;