OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [scsi/] [script_asm.pl] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
#! /usr/local/bin/perl
2
 
3
# NCR 53c810 script assembler
4
# Sponsored by 
5
#       iX Multiuser Multitasking Magazine
6
#
7
# Copyright 1993, Drew Eckhardt
8
#      Visionary Computing 
9
#      (Unix and Linux consulting and custom programming)
10
#      drew@Colorado.EDU
11
#      +1 (303) 786-7975 
12
#
13
#   This program is free software; you can redistribute it and/or modify
14
#   it under the terms of the GNU General Public License as published by
15
#   the Free Software Foundation; either version 2 of the License, or
16
#   (at your option) any later version.
17
#
18
#   This program is distributed in the hope that it will be useful,
19
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
20
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
#   GNU General Public License for more details.
22
#
23
#   You should have received a copy of the GNU General Public License
24
#   along with this program; if not, write to the Free Software
25
#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
#
27
# TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
28
#
29
 
30
# 
31
# Basically, I follow the NCR syntax documented in the NCR53c710 
32
# Programmer's guide, with the new instructions, registers, etc.
33
# from the NCR53c810.
34
#
35
# Differences between this assembler and NCR's are that 
36
# 1.  PASS, REL (data, JUMPs work fine), and the option to start a new 
37
#       script,  are unimplemented, since I didn't use them in my scripts.
38
# 
39
# 2.  I also emit a script_u.h file, which will undefine all of 
40
#       the A_*, E_*, etc. symbols defined in the script.  This 
41
#       makes including multiple scripts in one program easier
42
#       
43
# 3.  This is a single pass assembler, which only emits 
44
#       .h files.
45
#
46
 
47
 
48
# XXX - set these with command line options
49
$debug = 0;              # Print general debugging messages
50
$debug_external = 0;     # Print external/forward reference messages
51
$list_in_array = 1;     # Emit original SCRIPTS assembler in comments in
52
                        # script.h
53
$prefix = '';           # define all arrays having this prefix so we 
54
                        # don't have name space collisions after 
55
                        # assembling this file in different ways for
56
                        # different host adapters
57
 
58
# Constants
59
 
60
 
61
# Table of the SCSI phase encodings
62
%scsi_phases = (
63
    'DATA_OUT', 0x00_00_00_00, 'DATA_IN', 0x01_00_00_00, 'CMD', 0x02_00_00_00,
64
    'STATUS', 0x03_00_00_00, 'MSG_OUT', 0x06_00_00_00, 'MSG_IN', 0x07_00_00_00
65
);
66
 
67
# XXX - replace references to the *_810 constants with general constants
68
# assigned at compile time based on chip type.
69
 
70
# Table of operator encodings
71
# XXX - NCR53c710 only implements 
72
#       move (nop) = 0x00_00_00_00
73
#       or = 0x02_00_00_00
74
#       and = 0x04_00_00_00
75
#       add = 0x06_00_00_00
76
 
77
%operators_810 = (
78
    'SHL',  0x01_00_00_00,
79
    '|', 0x02_00_00_00, 'OR', 0x02_00_00_00,
80
    'XOR', 0x03_00_00_00,
81
    '&', 0x04_00_00_00, 'AND', 0x04_00_00_00,
82
    'SHR', 0x05_00_00_00,
83
    # Note : low bit of the operator bit should be set for add with 
84
    # carry.
85
    '+', 0x06_00_00_00
86
);
87
 
88
 
89
# Table of register addresses
90
%registers_810 = (
91
    'SCNTL0', 0, 'SCNTL1', 1, 'SCNTL2', 2, 'SCNTL3', 3,
92
    'SCID', 4, 'SXFER', 5, 'SDID', 6, 'GPREG', 7,
93
    'SFBR', 8, 'SOCL', 9, 'SSID', 10, 'SBCL', 11,
94
    'DSTAT', 12, 'SSTAT0', 13, 'SSTAT1', 14, 'SSTAT2', 15,
95
    'DSA0', 16, 'DSA1', 17, 'DSA2', 18, 'DSA3', 19,
96
    'ISTAT', 20,
97
    'CTEST0', 24, 'CTEST1', 25, 'CTEST2', 26, 'CTEST3', 27,
98
    'TEMP0', 28, 'TEMP1', 29, 'TEMP2', 30, 'TEMP3', 31,
99
    'DFIFO', 32, 'CTEST4', 33, 'CTEST5', 34, 'CTEST6', 35,
100
    'DBC0', 36, 'DBC1', 37, 'DBC2', 38, 'DCMD', 39,
101
    'DNAD0', 40, 'DNAD1', 41, 'DNAD2', 42, 'DNAD3', 43,
102
    'DSP0', 44, 'DSP1', 45, 'DSP2', 46, 'DSP3', 47,
103
    'DSPS0', 48, 'DSPS1', 49, 'DSPS2', 50, 'DSPS3', 51,
104
    'SCRATCH0', 52, 'SCRATCH1', 53, 'SCRATCH2', 54, 'SCRATCH3', 55,
105
    'SCRATCHA0', 52, 'SCRATCHA1', 53, 'SCRATCHA2', 54, 'SCRATCHA3', 55,
106
    'DMODE', 56, 'DIEN', 57, 'DWT', 58, 'DCNTL', 59,
107
    'ADDER0', 60, 'ADDER1', 61, 'ADDER2', 62, 'ADDER3', 63,
108
    'SIEN0', 64, 'SIEN1', 65, 'SIST0', 66, 'SIST1', 67,
109
    'SLPAR', 68,              'MACNTL', 70, 'GPCNTL', 71,
110
    'STIME0', 72, 'STIME1', 73, 'RESPID', 74,
111
    'STEST0', 76, 'STEST1', 77, 'STEST2', 78, 'STEST3', 79,
112
    'SIDL', 80,
113
    'SODL', 84,
114
    'SBDL', 88,
115
    'SCRATCHB0', 92, 'SCRATCHB1', 93, 'SCRATCHB2', 94, 'SCRATCHB3', 95
116
);
117
 
118
# Parsing regular expressions
119
$identifier = '[A-Za-z_][A-Za-z_0-9]*';
120
$decnum = '-?\\d+';
121
$hexnum = '0[xX][0-9A-Fa-f]+';
122
$constant = "$hexnum|$decnum";
123
 
124
# yucky - since we can't control grouping of # $constant, we need to 
125
# expand out each alternative for $value.
126
 
127
$value = "$identifier|$identifier\\s*[+\-]\\s*$decnum|".
128
    "$identifier\\s*[+-]\s*$hexnum|$constant";
129
 
130
print STDERR "value regex = $value\n" if ($debug);
131
 
132
$phase = join ('|', keys %scsi_phases);
133
print STDERR "phase regex = $phase\n" if ($debug);
134
$register = join ('|', keys %registers_810);
135
 
136
# yucky - since %operators_810 includes meta-characters which must
137
# be escaped, I can't use the join() trick I used for the register
138
# regex
139
 
140
$operator = '\||OR|AND|XOR|\&|\+';
141
 
142
# Global variables
143
 
144
%symbol_values = (%registers_810) ;     # Traditional symbol table
145
 
146
%symbol_references = () ;               # Table of symbol references, where
147
                                        # the index is the symbol name, 
148
                                        # and the contents a white space 
149
                                        # delimited list of address,size
150
                                        # tuples where size is in bytes.
151
 
152
@code = ();                             # Array of 32 bit words for SIOP 
153
 
154
@entry = ();                            # Array of entry point names
155
 
156
@label = ();                            # Array of label names
157
 
158
@absolute = ();                         # Array of absolute names
159
 
160
@relative = ();                         # Array of relative names
161
 
162
@external = ();                         # Array of external names
163
 
164
$address = 0;                            # Address of current instruction
165
 
166
$lineno = 0;                             # Line number we are parsing
167
 
168
$output = 'script.h';                   # Output file
169
$outputu = 'scriptu.h';
170
 
171
# &patch ($address, $offset, $length, $value) patches $code[$address]
172
#       so that the $length bytes at $offset have $value added to
173
#       them.  
174
 
175
@inverted_masks = (0x00_00_00_00, 0x00_00_00_ff, 0x00_00_ff_ff, 0x00_ff_ff_ff,
176
    0xff_ff_ff_ff);
177
 
178
sub patch {
179
    local ($address, $offset, $length, $value) = @_;
180
    if ($debug) {
181
        print STDERR "Patching $address at offset $offset, length $length to $value\n";
182
        printf STDERR "Old code : %08x\n", $code[$address];
183
     }
184
 
185
    $mask = ($inverted_masks[$length] << ($offset * 8));
186
 
187
    $code[$address] = ($code[$address] & ~$mask) |
188
        (($code[$address] & $mask) + ($value << ($offset * 8)) &
189
        $mask);
190
 
191
    printf STDERR "New code : %08x\n", $code[$address] if ($debug);
192
}
193
 
194
# &parse_value($value, $word, $offset, $length) where $value is 
195
#       an identifier or constant, $word is the word offset relative to 
196
#       $address, $offset is the starting byte within that word, and 
197
#       $length is the length of the field in bytes.
198
#
199
# Side effects are that the bytes are combined into the @code array
200
#       relative to $address, and that the %symbol_references table is 
201
#       updated as appropriate.
202
 
203
sub parse_value {
204
    local ($value, $word, $offset, $length) = @_;
205
    local ($tmp);
206
 
207
    $symbol = '';
208
 
209
    if ($value =~ /^REL\s*\(\s*($identifier)\s*\)\s*(.*)/i) {
210
        $relative = 'REL';
211
        $symbol = $1;
212
        $value = $2;
213
print STDERR "Relative reference $symbol\n" if ($debug);
214
    } elsif ($value =~ /^($identifier)\s*(.*)/) {
215
        $relative = 'ABS';
216
        $symbol = $1;
217
        $value = $2;
218
print STDERR "Absolute reference $symbol\n" if ($debug);
219
    }
220
 
221
    if ($symbol ne '') {
222
print STDERR "Referencing symbol $1, length = $length in $_\n" if ($debug);
223
        $tmp = ($address + $word) * 4 + $offset;
224
        if ($symbol_references{$symbol} ne undef) {
225
            $symbol_references{$symbol} =
226
                "$symbol_references{$symbol} $relative,$tmp,$length";
227
        } else {
228
            if (!defined($symbol_values{$symbol})) {
229
print STDERR "forward $1\n" if ($debug_external);
230
                $forward{$symbol} = "line $lineno : $_";
231
            }
232
            $symbol_references{$symbol} = "$relative,$tmp,$length";
233
        }
234
    }
235
 
236
    $value = eval $value;
237
    &patch ($address + $word, $offset, $length, $value);
238
}
239
 
240
# &parse_conditional ($conditional) where $conditional is the conditional
241
# clause from a transfer control instruction (RETURN, CALL, JUMP, INT).
242
 
243
sub parse_conditional {
244
    local ($conditional) = @_;
245
    if ($conditional =~ /^\s*(IF|WHEN)\s*(.*)/i) {
246
        $if = $1;
247
        $conditional = $2;
248
        if ($if =~ /WHEN/i) {
249
            $allow_atn = 0;
250
            $code[$address] |= 0x00_01_00_00;
251
            $allow_atn = 0;
252
            print STDERR "$0 : parsed WHEN\n" if ($debug);
253
        } else {
254
            $allow_atn = 1;
255
            print STDERR "$0 : parsed IF\n" if ($debug);
256
        }
257
    } else {
258
            die "$0 : syntax error in line $lineno : $_
259
        expected IF or WHEN
260
";
261
    }
262
 
263
    if ($conditional =~ /^NOT\s+(.*)$/i) {
264
        $not = 'NOT ';
265
        $other = 'OR';
266
        $conditional = $1;
267
        print STDERR "$0 : parsed NOT\n" if ($debug);
268
    } else {
269
        $code[$address] |= 0x00_08_00_00;
270
        $not = '';
271
        $other = 'AND'
272
    }
273
 
274
    $need_data = 0;
275
    if ($conditional =~ /^ATN\s*(.*)/i) {#
276
        die "$0 : syntax error in line $lineno : $_
277
        WHEN conditional is incompatible with ATN
278
" if (!$allow_atn);
279
        $code[$address] |= 0x00_02_00_00;
280
        $conditional = $1;
281
        print STDERR "$0 : parsed ATN\n" if ($debug);
282
    } elsif ($conditional =~ /^($phase)\s*(.*)/i) {
283
        $phase_index = "\U$1\E";
284
        $p = $scsi_phases{$phase_index};
285
        $code[$address] |= $p | 0x00_02_00_00;
286
        $conditional = $2;
287
        print STDERR "$0 : parsed phase $phase_index\n" if ($debug);
288
    } else {
289
        $other = '';
290
        $need_data = 1;
291
    }
292
 
293
print STDERR "Parsing conjunction, expecting $other\n" if ($debug);
294
    if ($conditional =~ /^(AND|OR)\s*(.*)/i) {
295
        $conjunction = $1;
296
        $conditional = $2;
297
        $need_data = 1;
298
        die "$0 : syntax error in line $lineno : $_
299
            Illegal use of $1.  Valid uses are
300
            ".$not."<phase> $1 data
301
            ".$not."ATN $1 data
302
" if ($other eq '');
303
        die "$0 : syntax error in line $lineno : $_
304
        Illegal use of $conjunction.  Valid syntaxes are
305
                NOT <phase>|ATN OR data
306
                <phase>|ATN AND data
307
" if ($conjunction !~ /\s*$other\s*/i);
308
        print STDERR "$0 : parsed $1\n" if ($debug);
309
    }
310
 
311
    if ($need_data) {
312
print STDERR "looking for data in $conditional\n" if ($debug);
313
        if ($conditional=~ /^($value)\s*(.*)/i) {
314
            $code[$address] |= 0x00_04_00_00;
315
            $conditional = $2;
316
            &parse_value($1, 0, 0, 1);
317
            print STDERR "$0 : parsed data\n" if ($debug);
318
        } else {
319
        die "$0 : syntax error in line $lineno : $_
320
        expected <data>.
321
";
322
        }
323
    }
324
 
325
    if ($conditional =~ /^\s*,\s*(.*)/) {
326
        $conditional = $1;
327
        if ($conditional =~ /^AND\s\s*MASK\s\s*($value)\s*(.*)/i) {
328
            &parse_value ($1, 0, 1, 1);
329
            print STDERR "$0 parsed AND MASK $1\n" if ($debug);
330
            die "$0 : syntax error in line $lineno : $_
331
        expected end of line, not \"$2\"
332
" if ($2 ne '');
333
        } else {
334
            die "$0 : syntax error in line $lineno : $_
335
        expected \",AND MASK <data>\", not \"$2\"
336
";
337
        }
338
    } elsif ($conditional !~ /^\s*$/) {
339
        die "$0 : syntax error in line $lineno : $_
340
        expected end of line" . (($need_data) ? " or \"AND MASK <data>\"" : "") . "
341
        not \"$conditional\"
342
";
343
    }
344
}
345
 
346
# Parse command line 
347
foreach $arg (@argv) {
348
    if ($arg =~ /^-prefix\s*=\s*([_a-zA-Z][_a-zA-Z0-9]*)$/i) {
349
        $prefix = $1
350
    }
351
}
352
 
353
# Main loop
354
while (<STDIN>) {
355
    $lineno = $lineno + 1;
356
    $list[$address] = $list[$address].$_;
357
    s/;.*$//;                           # Strip comments
358
 
359
 
360
    chop;                               # Leave new line out of error messages
361
 
362
# Handle symbol definitions of the form label:
363
    if (/^\s*($identifier)\s*:(.*)/) {
364
        if (!defined($symbol_values{$1})) {
365
            $symbol_values{$1} = $address * 4;  # Address is an index into
366
            delete $forward{$1};                # an array of longs
367
            push (@label, $1);
368
            $_ = $2;
369
        } else {
370
            die "$0 : redefinition of symbol $1 in line $lineno : $_\n";
371
        }
372
    }
373
 
374
# Handle symbol definitions of the form ABSOLUTE or RELATIVE identifier = 
375
# value
376
    if (/^\s*(ABSOLUTE|RELATIVE)\s+(.*)/i) {
377
        $is_absolute = $1;
378
        $rest = $2;
379
        foreach $rest (split (/\s*,\s*/, $rest)) {
380
            if ($rest =~ /^($identifier)\s*=\s*($constant)\s*$/) {
381
                local ($id, $cnst) = ($1, $2);
382
                if ($symbol_values{$id} eq undef) {
383
                    $symbol_values{$id} = eval $cnst;
384
                    delete $forward{$id};
385
                    if ($is_absolute =~ /ABSOLUTE/i) {
386
                        push (@absolute , $id);
387
                    } else {
388
                        push (@relative, $id);
389
                    }
390
                } else {
391
                    die "$0 : redefinition of symbol $id in line $lineno : $_\n";
392
                }
393
            } else {
394
                die
395
"$0 : syntax error in line $lineno : $_
396
            expected <identifier> = <value>
397
";
398
            }
399
        }
400
    } elsif (/^\s*EXTERNAL\s+(.*)/i) {
401
        $externals = $1;
402
        foreach $external (split (/,/,$externals)) {
403
            if ($external =~ /\s*($identifier)\s*$/) {
404
                $external = $1;
405
                push (@external, $external);
406
                delete $forward{$external};
407
                if (defined($symbol_values{$external})) {
408
                        die "$0 : redefinition of symbol $1 in line $lineno : $_\n";
409
                }
410
                $symbol_values{$external} = $external;
411
print STDERR "defined external $1 to $external\n" if ($debug_external);
412
            } else {
413
                die
414
"$0 : syntax error in line $lineno : $_
415
        expected <identifier>, got $external
416
";
417
            }
418
        }
419
# Process ENTRY identifier declarations
420
    } elsif (/^\s*ENTRY\s+(.*)/i) {
421
        if ($1 =~ /^($identifier)\s*$/) {
422
            push (@entry, $1);
423
        } else {
424
"$0 : syntax error in line $lineno : $_
425
        expected ENTRY <identifier>
426
";
427
        }
428
# Process MOVE length, address, WITH|WHEN phase instruction
429
    } elsif (/^\s*MOVE\s+(.*)/i) {
430
        $rest = $1;
431
        if ($rest =~ /^FROM\s+($value)\s*,\s*(WITH|WHEN)\s+($phase)\s*$/i) {
432
            $transfer_addr = $1;
433
            $with_when = $2;
434
            $scsi_phase = $3;
435
print STDERR "Parsing MOVE FROM $transfer_addr, $with_when $3\n" if ($debug);
436
            $code[$address] = 0x18_00_00_00 | (($with_when =~ /WITH/i) ?
437
                0x00_00_00_00 : 0x08_00_00_00) | $scsi_phases{$scsi_phase};
438
            &parse_value ($transfer_addr, 1, 0, 4);
439
            $address += 2;
440
        } elsif ($rest =~ /^($value)\s*,\s*(PTR\s+|)($value)\s*,\s*(WITH|WHEN)\s+($phase)\s*$/i) {
441
            $transfer_len = $1;
442
            $ptr = $2;
443
            $transfer_addr = $3;
444
            $with_when = $4;
445
            $scsi_phase = $5;
446
            $code[$address] = (($with_when =~ /WITH/i) ? 0x00_00_00_00 :
447
                0x08_00_00_00)  | (($ptr =~ /PTR/i) ? (1 << 29) : 0) |
448
                $scsi_phases{$scsi_phase};
449
            &parse_value ($transfer_len, 0, 0, 3);
450
            &parse_value ($transfer_addr, 1, 0, 4);
451
            $address += 2;
452
        } elsif ($rest =~ /^MEMORY\s+(.*)/i) {
453
            $rest = $1;
454
            $code[$address] = 0xc0_00_00_00;
455
            if ($rest =~ /^($value)\s*,\s*($value)\s*,\s*($value)\s*$/) {
456
                $count = $1;
457
                $source = $2;
458
                $dest =  $3;
459
print STDERR "Parsing MOVE MEMORY $count, $source, $dest\n" if ($debug);
460
                &parse_value ($count, 0, 0, 3);
461
                &parse_value ($source, 1, 0, 4);
462
                &parse_value ($dest, 2, 0, 4);
463
printf STDERR "Move memory instruction = %08x,%08x,%08x\n",
464
                $code[$address], $code[$address+1], $code[$address +2] if
465
                ($debug);
466
                $address += 3;
467
 
468
            } else {
469
                die
470
"$0 : syntax error in line $lineno : $_
471
        expected <count>, <source>, <destination>
472
"
473
            }
474
        } elsif ($1 =~ /^(.*)\s+(TO|SHL|SHR)\s+(.*)/i) {
475
print STDERR "Parsing register to register move\n" if ($debug);
476
            $src = $1;
477
            $op = "\U$2\E";
478
            $rest = $3;
479
 
480
            $code[$address] = 0x40_00_00_00;
481
 
482
            $force = ($op !~ /TO/i);
483
 
484
 
485
print STDERR "Forcing register source \n" if ($force && $debug);
486
 
487
            if (!$force && $src =~
488
                /^($register)\s+(-|$operator)\s+($value)\s*$/i) {
489
print STDERR "register operand  data8 source\n" if ($debug);
490
                $src_reg = "\U$1\E";
491
                $op = "\U$2\E";
492
                if ($op ne '-') {
493
                    $data8 = $3;
494
                } else {
495
                    die "- is not implemented yet.\n"
496
                }
497
            } elsif ($src =~ /^($register)\s*$/i) {
498
print STDERR "register source\n" if ($debug);
499
                $src_reg = "\U$1\E";
500
                # Encode register to register move as a register | 0 
501
                # move to register.
502
                if (!$force) {
503
                    $op = '|';
504
                }
505
                $data8 = 0;
506
            } elsif (!$force && $src =~ /^($value)\s*$/i) {
507
print STDERR "data8 source\n" if ($debug);
508
                $src_reg = undef;
509
                $op = 'NONE';
510
                $data8 = $1;
511
            } else {
512
                if (!$force) {
513
                    die
514
"$0 : syntax error in line $lineno : $_
515
        expected <register>
516
                <data8>
517
                <register> <operand> <data8>
518
";
519
                } else {
520
                    die
521
"$0 : syntax error in line $lineno : $_
522
        expected <register>
523
";
524
                }
525
            }
526
            if ($rest =~ /^($register)\s*(.*)$/i) {
527
                $dst_reg = "\U$1\E";
528
                $rest = $2;
529
            } else {
530
            die
531
"$0 : syntax error in $lineno : $_
532
        expected <register>, got $rest
533
";
534
            }
535
 
536
            if ($rest =~ /^WITH\s+CARRY\s*(.*)/i) {
537
                $rest = $1;
538
                if ($op eq '+') {
539
                    $code[$address] |= 0x01_00_00_00;
540
                } else {
541
                    die
542
"$0 : syntax error in $lineno : $_
543
        WITH CARRY option is incompatible with the $op operator.
544
";
545
                }
546
            }
547
 
548
            if ($rest !~ /^\s*$/) {
549
                die
550
"$0 : syntax error in $lineno : $_
551
        Expected end of line, got $rest
552
";
553
            }
554
 
555
            print STDERR "source = $src_reg, data = $data8 , destination = $dst_reg\n"
556
                if ($debug);
557
            # Note that Move data8 to reg is encoded as a read-modify-write
558
            # instruction.
559
            if (($src_reg eq undef) || ($src_reg eq $dst_reg)) {
560
                $code[$address] |= 0x38_00_00_00 |
561
                    ($registers_810{$dst_reg} << 16);
562
            } elsif ($dst_reg =~ /SFBR/i) {
563
                $code[$address] |= 0x30_00_00_00 |
564
                    ($registers_810{$src_reg} << 16);
565
            } elsif ($src_reg =~ /SFBR/i) {
566
                $code[$address] |= 0x28_00_00_00 |
567
                    ($registers_810{$dst_reg} << 16);
568
            } else {
569
                die
570
"$0 : Illegal combination of registers in line $lineno : $_
571
        Either source and destination registers must be the same,
572
        or either source or destination register must be SFBR.
573
";
574
            }
575
 
576
            $code[$address] |= $operators_810{$op};
577
 
578
            &parse_value ($data8, 0, 1, 1);
579
            $code[$address] |= $operators_810{$op};
580
            $code[$address + 1] = 0x00_00_00_00;# Reserved
581
            $address += 2;
582
        } else {
583
            die
584
"$0 : syntax error in line $lineno : $_
585
        expected (initiator) <length>, <address>, WHEN <phase>
586
                 (target) <length>, <address>, WITH <phase>
587
                 MEMORY <length>, <source>, <destination>
588
                 <expression> TO <register>
589
";
590
        }
591
# Process SELECT {ATN|} id, fail_address
592
    } elsif (/^\s*(SELECT|RESELECT)\s+(.*)/i) {
593
        $rest = $2;
594
        if ($rest =~ /^(ATN|)\s*($value)\s*,\s*($identifier)\s*$/i) {
595
            $atn = $1;
596
            $id = $2;
597
            $alt_addr = $3;
598
            $code[$address] = 0x40_00_00_00 |
599
                (($atn =~ /ATN/i) ? 0x01_00_00_00 : 0);
600
            $code[$address + 1] = 0x00_00_00_00;
601
            &parse_value($id, 0, 2, 1);
602
            &parse_value($alt_addr, 1, 0, 4);
603
            $address += 2;
604
        } elsif ($rest =~ /^(ATN|)\s*FROM\s+($value)\s*,\s*($identifier)\s*$/i) {
605
            $atn = $1;
606
            $addr = $2;
607
            $alt_addr = $3;
608
            $code[$address] = 0x42_00_00_00 |
609
                (($atn =~ /ATN/i) ? 0x01_00_00_00 : 0);
610
            $code[$address + 1] = 0x00_00_00_00;
611
            &parse_value($addr, 0, 0, 3);
612
            &parse_value($alt_addr, 1, 0, 4);
613
            $address += 2;
614
        } else {
615
            die
616
"$0 : syntax error in line $lineno : $_
617
        expected SELECT id, alternate_address or
618
                SELECT FROM address, alternate_address or
619
                RESELECT id, alternate_address or
620
                RESELECT FROM address, alternate_address
621
";
622
        }
623
    } elsif (/^\s*WAIT\s+(.*)/i) {
624
            $rest = $1;
625
print STDERR "Parsing WAIT $rest\n" if ($debug);
626
        if ($rest =~ /^DISCONNECT\s*$/i) {
627
            $code[$address] = 0x48_00_00_00;
628
            $code[$address + 1] = 0x00_00_00_00;
629
            $address += 2;
630
        } elsif ($rest =~ /^(RESELECT|SELECT)\s+($identifier)\s*$/i) {
631
            $alt_addr = $2;
632
            $code[$address] = 0x50_00_00_00;
633
            &parse_value ($alt_addr, 1, 0, 4);
634
            $address += 2;
635
        } else {
636
            die
637
"$0 : syntax error in line $lineno : $_
638
        expected (initiator) WAIT DISCONNECT or
639
                 (initiator) WAIT RESELECT alternate_address or
640
                 (target) WAIT SELECT alternate_address
641
";
642
        }
643
# Handle SET and CLEAR instructions.  Note that we should also do something
644
# with this syntax to set target mode.
645
    } elsif (/^\s*(SET|CLEAR)\s+(.*)/i) {
646
        $set = $1;
647
        $list = $2;
648
        $code[$address] = ($set =~ /SET/i) ?  0x58_00_00_00 :
649
            0x60_00_00_00;
650
        foreach $arg (split (/\s+AND\s+/i,$list)) {
651
            if ($arg =~ /ATN/i) {
652
                $code[$address] |= 0x00_00_00_08;
653
            } elsif ($arg =~ /ACK/i) {
654
                $code[$address] |= 0x00_00_00_40;
655
            } elsif ($arg =~ /TARGET/i) {
656
                $code[$address] |= 0x00_00_02_00;
657
            } elsif ($arg =~ /CARRY/i) {
658
                $code[$address] |= 0x00_00_04_00;
659
            } else {
660
                die
661
"$0 : syntax error in line $lineno : $_
662
        expected $set followed by a AND delimited list of one or
663
        more strings from the list ACK, ATN, CARRY, TARGET.
664
";
665
            }
666
        }
667
        $code[$address + 1] = 0x00_00_00_00;
668
        $address += 2;
669
    } elsif (/^\s*(JUMP|CALL|INT)\s+(.*)/i) {
670
        $instruction = $1;
671
        $rest = $2;
672
        if ($instruction =~ /JUMP/i) {
673
            $code[$address] = 0x80_00_00_00;
674
        } elsif ($instruction =~ /CALL/i) {
675
            $code[$address] = 0x88_00_00_00;
676
        } else {
677
            $code[$address] = 0x98_00_00_00;
678
        }
679
print STDERR "parsing JUMP, rest = $rest\n" if ($debug);
680
 
681
# Relative jump. 
682
        if ($rest =~ /^(REL\s*\(\s*$identifier\s*\))\s*(.*)/i) {
683
            $addr = $1;
684
            $rest = $2;
685
print STDERR "parsing JUMP REL, addr = $addr, rest = $rest\n" if ($debug);
686
            $code[$address]  |= 0x00_80_00_00;
687
            &parse_value($addr, 1, 0, 4);
688
# Absolute jump, requires no more gunk
689
        } elsif ($rest =~ /^($value)\s*(.*)/) {
690
            $addr = $1;
691
            $rest = $2;
692
            &parse_value($addr, 1, 0, 4);
693
        } else {
694
            die
695
"$0 : syntax error in line $lineno : $_
696
        expected <address> or REL (address)
697
";
698
        }
699
 
700
        if ($rest =~ /^,\s*(.*)/) {
701
            &parse_conditional($1);
702
        } elsif ($rest =~ /^\s*$/) {
703
            $code[$address] |= (1 << 19);
704
        } else {
705
            die
706
"$0 : syntax error in line $lineno : $_
707
        expected , <conditional> or end of line, got $1
708
";
709
        }
710
 
711
        $address += 2;
712
    } elsif (/^\s*(RETURN|INTFLY)\s*(.*)/i) {
713
        $instruction = $1;
714
        $conditional = $2;
715
print STDERR "Parsing $instruction\n" if ($debug);
716
        $code[$address] = ($instruction =~ /RETURN/i) ? 0x90_00_00_00 :
717
            0x98_10_00_00;
718
        if ($conditional =~ /^,\s*(.*)/) {
719
            $conditional = $1;
720
            &parse_conditional ($conditional);
721
        } elsif ($conditional !~ /^\s*$/) {
722
            die
723
"$0 : syntax error in line $lineno : $_
724
        expected , <conditional>
725
";
726
        } else {
727
            $code[$address] |= 0x00_08_00_00;
728
        }
729
 
730
        $code[$address + 1] = 0x00_00_00_00;
731
        $address += 2;
732
    } elsif (/^\s*DISCONNECT\s*$/) {
733
        $code[$address] = 0x48_00_00_00;
734
        $code[$address + 1] = 0x00_00_00_00;
735
        $address += 2;
736
# I'm not sure that I should be including this extension, but 
737
# what the hell?
738
    } elsif (/^\s*NOP\s*$/i) {
739
        $code[$address] = 0x80_88_00_00;
740
        $code[$address + 1] = 0x00_00_00_00;
741
        $address += 2;
742
# Ignore lines consisting entirely of white space
743
    } elsif (/^\s*$/) {
744
    } else {
745
        die
746
"$0 : syntax error in line $lineno: $_
747
        expected label:, ABSOLUTE, CLEAR, DISCONNECT, EXTERNAL, MOVE, RESELECT,
748
            SELECT SET, or WAIT
749
";
750
    }
751
}
752
 
753
# Fill in label references
754
 
755
@undefined = keys %forward;
756
if ($#undefined >= 0) {
757
    print STDERR "Undefined symbols : \n";
758
    foreach $undef (@undefined) {
759
        print STDERR "$undef in $forward{$undef}\n";
760
    }
761
    exit 1;
762
}
763
 
764
@label_patches = ();
765
 
766
@external_patches = ();
767
 
768
@absolute = sort @absolute;
769
 
770
foreach $i (@absolute) {
771
    foreach $j (split (/\s+/,$symbol_references{$i})) {
772
        $j =~ /(REL|ABS),(.*),(.*)/;
773
        $type = $1;
774
        $address = $2;
775
        $length = $3;
776
        die
777
"$0 : $symbol $i has illegal relative reference at address $address,
778
    size $length\n"
779
        if ($type eq 'REL');
780
 
781
        &patch ($address / 4, $address % 4, $length, $symbol_values{$i});
782
    }
783
}
784
 
785
foreach $external (@external) {
786
print STDERR "checking external $external \n" if ($debug_external);
787
    if ($symbol_references{$external} ne undef) {
788
        for $reference (split(/\s+/,$symbol_references{$external})) {
789
            $reference =~ /(REL|ABS),(.*),(.*)/;
790
            $type = $1;
791
            $address = $2;
792
            $length = $3;
793
 
794
            die
795
"$0 : symbol $label is external, has illegal relative reference at $address,
796
    size $length\n"
797
                if ($type eq 'REL');
798
 
799
            die
800
"$0 : symbol $label has illegal reference at $address, size $length\n"
801
                if ((($address % 4) !=0) || ($length != 4));
802
 
803
            $symbol = $symbol_values{$external};
804
            $add = $code[$address / 4];
805
            if ($add eq 0) {
806
                $code[$address / 4] = $symbol;
807
            } else {
808
                $add = sprintf ("0x%08x", $add);
809
                $code[$address / 4] = "$symbol + $add";
810
            }
811
 
812
print STDERR "referenced external $external at $1\n" if ($debug_external);
813
        }
814
    }
815
}
816
 
817
foreach $label (@label) {
818
    if ($symbol_references{$label} ne undef) {
819
        for $reference (split(/\s+/,$symbol_references{$label})) {
820
            $reference =~ /(REL|ABS),(.*),(.*)/;
821
            $type = $1;
822
            $address = $2;
823
            $length = $3;
824
 
825
            if ((($address % 4) !=0) || ($length != 4)) {
826
                die "$0 : symbol $label has illegal reference at $1, size $2\n";
827
            }
828
 
829
            if ($type eq 'ABS') {
830
                $code[$address / 4] += $symbol_values{$label};
831
                push (@label_patches, $address / 4);
832
            } else {
833
# 
834
# - The address of the reference should be in the second and last word
835
#       of an instruction
836
# - Relative jumps, etc. are relative to the DSP of the _next_ instruction
837
#
838
# So, we need to add four to the address of the reference, to get 
839
# the address of the next instruction, when computing the reference.
840
 
841
                $tmp = $symbol_values{$label} -
842
                    ($address + 4);
843
                die
844
# Relative addressing is limited to 24 bits.
845
"$0 : symbol $label is too far ($tmp) from $address to reference as
846
    relative/\n" if (($tmp >= 0x80_00_00) || ($tmp < -0x80_00_00));
847
                $code[$address / 4] = $tmp & 0x00_ff_ff_ff;
848
            }
849
        }
850
    }
851
}
852
 
853
# Output SCRIPT[] array, one instruction per line.  Optionally 
854
# print the original code too.
855
 
856
open (OUTPUT, ">$output") || die "$0 : can't open $output for writing\n";
857
open (OUTPUTU, ">$outputu") || die "$0 : can't open $outputu for writing\n";
858
 
859
print OUTPUT "u32 ".$prefix."SCRIPT[] = {\n";
860
$instructions = 0;
861
for ($i = 0; $i < $#code; ) {
862
    if ($list_in_array) {
863
        printf OUTPUT "/*\n$list[$i]\nat 0x%08x : */", $i;
864
    }
865
    printf OUTPUT "\t0x%08x,", $code[$i];
866
    printf STDERR "Address $i = %x\n", $code[$i] if ($debug);
867
    if ($code[$i + 1] =~ /\s*($identifier)(.*)$/) {
868
        push (@external_patches, $i+1, $1);
869
        printf OUTPUT "0%s,", $2
870
    } else {
871
        printf OUTPUT "0x%08x,",$code[$i+1];
872
    }
873
 
874
    if (($code[$i] & 0xff_00_00_00) == 0xc0_00_00_00) {
875
        if ($code[$i + 2] =~ /$identifier/) {
876
            push (@external_patches, $i+2, $code[$i+2]);
877
            printf OUTPUT "0,\n";
878
        } else {
879
            printf OUTPUT "0x%08x,\n",$code[$i+2];
880
        }
881
        $i += 3;
882
    } else {
883
        printf OUTPUT "\n";
884
        $i += 2;
885
    }
886
    $instructions += 1;
887
}
888
print OUTPUT "};\n\n";
889
 
890
foreach $i (@absolute) {
891
    printf OUTPUT "#define A_$i\t0x%08x\n", $symbol_values{$i};
892
    if (defined($prefix) && $prefix ne '') {
893
        printf OUTPUT "#define A_".$i."_used ".$prefix."A_".$i."_used\n";
894
        printf OUTPUTU "#undef A_".$i."_used\n";
895
    }
896
    printf OUTPUTU "#undef A_$i\n";
897
 
898
    printf OUTPUT "u32 A_".$i."_used\[\] = {\n";
899
printf STDERR "$i is used $symbol_references{$i}\n" if ($debug);
900
    foreach $j (split (/\s+/,$symbol_references{$i})) {
901
        $j =~ /(ABS|REL),(.*),(.*)/;
902
        if ($1 eq 'ABS') {
903
            $address = $2;
904
            $length = $3;
905
            printf OUTPUT "\t0x%08x,\n", $address / 4;
906
        }
907
    }
908
    printf OUTPUT "};\n\n";
909
}
910
 
911
foreach $i (sort @entry) {
912
    printf OUTPUT "#define Ent_$i\t0x%08x\n", $symbol_values{$i};
913
    printf OUTPUTU "#undef Ent_$i\n", $symbol_values{$i};
914
}
915
 
916
#
917
# NCR assembler outputs label patches in the form of indices into 
918
# the code.
919
#
920
printf OUTPUT "u32 ".$prefix."LABELPATCHES[] = {\n";
921
for $patch (sort {$a <=> $b} @label_patches) {
922
    printf OUTPUT "\t0x%08x,\n", $patch;
923
}
924
printf OUTPUT "};\n\n";
925
 
926
$num_external_patches = 0;
927
printf OUTPUT "struct {\n\tu32\toffset;\n\tvoid\t\t*address;\n".
928
    "} ".$prefix."EXTERNAL_PATCHES[] = {\n";
929
while ($ident = pop(@external_patches)) {
930
    $off = pop(@external_patches);
931
    printf OUTPUT "\t{0x%08x, &%s},\n", $off, $ident;
932
    ++$num_external_patches;
933
}
934
printf OUTPUT "};\n\n";
935
 
936
printf OUTPUT "u32 ".$prefix."INSTRUCTIONS\t= %d;\n",
937
    $instructions;
938
printf OUTPUT "u32 ".$prefix."PATCHES\t= %d;\n",
939
    $#label_patches+1;
940
printf OUTPUT "u32 ".$prefix."EXTERNAL_PATCHES_LEN\t= %d;\n",
941
    $num_external_patches;
942
close OUTPUT;
943
close OUTPUTU;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.