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

Subversion Repositories blue

[/] [blue/] [trunk/] [blue8/] [blue.pl] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 wd5gnr
#!/usr/bin/perl
2 3 wd5gnr
# Part of Blue 8 by Al Williams http://blue.hotsolder.com
3 2 wd5gnr
# V2 supports # constant syntax
4
# we used to support multiple files on command line
5
# but now that the driver script uses cpp, assume 1 file only
6
 
7
 
8
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
9
    if $running_under_some_shell;
10
                        # this emulates #! processing on NIH machines.
11
                        # (remove #! line above if indigestible)
12
 
13
eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_0-9]+=)(.*)/ && shift;
14
                        # process any FOO=bar switches
15
 
16
 
17
 
18
 
19
$[ = 1;                 # set array base to 1
20
$, = ' ';               # set output field separator
21
$\ = "\n";              # set output record separator
22
 
23
$pass = 1;
24
$location = 0;
25
 
26
 
27
%opmap = ('dw', 0, 'hlt', 0, 'nop', 1,
28
  'add' ,0x1000,'xor',0x2000, 'and', 0x3000,
29
  'ior', 0x4000, 'not', 2,'lda', 0x6000, 'sta', 0x7000,
30
  'call', 0x8000, 'jmp', 0xa000, 'ldx', 0xb000,
31
  'ral', 3, 'org', -1,
32
  'equ', -1, 'end', -1, 'inca', 5, 'deca', 6, 'sz', 0x12, 'snz', 0x1a,
33
  "spos", 0x21, "sneg", 0x20, "qon", 0x23, "qoff", 0x22, "qtog", 0x24,
34
  'sub', 0x9000, 'cmp', 0x5000, 'ldi', 0x25,
35
  'so', 0x0011, 'sz',0x0012, 'szo', 0x0013, 'sc', 0x0014, 'sco', 0x0015,
36
  'scz', 0x0016, 'sczo', 0x0017, 'sno', 0x0019, 'snz', 0x001a, 'snzo', 0x001b,
37
  'snc', 0x001c, 'snco', 0x001d, 'sncz', 0x001e, 'snczo', 0x001f,
38
  'ldax', 0xe000, 'stax', 0xf000, 'incx', 0x0030, 'decx', 0x0031,
39
  'stx', 0x0032, 'jmpa', 0x0033, 'swap', 0x0034, 'lds', 0xc000,
40
  'push', 0x0050, 'pop', 0x0040, 'ret', 0x0041, 'popx', 0x0042, 'pushx', 0x52,
41
  'pushf', 0x0053, 'popf', 0x0043, 'frame', 0x0008, 'rar', 0x0007, 'ldxa', 0x0009
42
);
43
 
44
%adda = ( 'dw', 1, 'hlt',0, 'nop', 0,
45
  'add', 1, 'and',1, 'ior',1,
46
  'not', 0, 'lda', 1, 'sta', 1, 'call', 1, 'jmp', 1,
47
  'ldx', 1, 'ral', 0, 'inca', 0, 'deca', 0,
48
  'sz', 0, 'snz', 0, "spos", 0, "sneg", 0, "qon", 0, "qoff", 0, "qtog", 0,
49
  'sub', 1, 'cmp', 1, 'ldi', 2,
50
  'so', 0, 'sz',0, 'szo', 0, 'sc', 0, 'sco', 0,
51
  'scz', 0, 'sczo', 0, 'sno', 0, 'snz', 0, 'snzo', 0,
52
  'snc', 0, 'snco', 0, 'sncz', 0, 'snczo', 0,
53
  'ldax', 1, 'stax', 1, 'incx', 0, 'decx', 0, 'stx', 0, 'jmpa', 0, 'swap', 0,
54
  'lds', 1, 'push', 0, 'pop', 0, 'ret', 0, 'popx', 0, 'pushx', 0, 'pushf', 0,
55
  'popf', 0, 'frame', 0, 'rar', 0, 'ldxa', 0
56
);
57
 
58
 
59
floop: while (@ARGV) {
60
   $file=shift;
61
   &procfile($file);
62
}
63
print '// Symbols';
64
foreach $v (keys %symtab) {
65
    if ($v ne '_location_') { printf( "// %s: %04x\n", $v, $symtab{$v}); }
66
}
67
print '// End Symbols';
68
 
69
 
70
# need to localize 
71
# so we can call recursively (for INCLUDE)
72
sub procfile {
73
    local ($file)=@_;
74
    local($base);
75
     unless (open(F,$file)) {  # may have to close and reopen before recurse?
76
     print STDERR "Can't open $file.\n";
77
     exit(1);
78
     }
79
    $base=$location;
80
line: while (<F>) {
81
line0:
82
    @lines=split(/\|/);
83
    foreach (@lines) {
84
    $f=&procline($_);
85
    if ($f==0) { return; }
86
    if ($f==2) { seek(F,0,0); next; }
87
}
88
    if (eof(F)) {
89
      if ($pass==1) {
90
          print STDERR "Warning: Missing end in $file";
91
          print "//! Warning: Missing end in $file";
92
      }
93
      $_=" END";
94
      goto line0;
95
      }
96
 
97
    }
98
# the only way to get here is if no end, so warn and fake the end
99
#  if ($pass==1) { 
100
#    print STDERR "warning: Missing end in $file"; 
101
#    &procline(" END");
102
#    seek(F,0,0);
103
#    goto line;
104
#    }
105
#  if ($pass==2) {&procline("  END"); }
106
}
107
 
108
sub procline {
109
    chomp;      # strip record separator
110
 
111
pline:
112
   s/;.*$//g;
113
 
114
    $theLine = $_;
115
    if (/^[ \t]*$/) {
116
        return 1;
117
    }
118
    @Fld = split(' ', $_, 9999);
119
 
120
 
121
    $clabel = '';
122
 
123
    if (/^[a-zA-Z_][a-zA-Z_0-9]*[:]/) {
124
        $t=$Fld[1];
125
        $s = ':', $Fld[1] =~ s/$s//;
126
        $clabel = &toLOWER($Fld[1]);
127
        $s = $t, s/$s//g;
128
        $lvalue = $location;
129
        @Fld = split(' ', $_, 9999);
130
    }
131
 
132
# must resolve in 1st pass!
133
    if ($pass == 1) {
134
        $opcode = &toLOWER($Fld[1]);
135
        if ($Fld[2]!~/['"]/) { $afield = &toLOWER($Fld[2]); }
136
         else {
137
          s/^[^'"#]*(['"#])/\1/;  # get whole string
138
          $afield=$_;
139
         }
140
        # we need to check for psuedo op
141
        # end, org, equ
142
        if ($opcode eq 'org') {
143
            $location = &xeval($afield);
144
        }
145
# must resolve in 1st pass!
146
        if ($opcode eq 'equ') {
147
            $lvalue = &xeval($afield);
148
        }
149
        if ($clabel =~ /^[a-zA-Z_]/ && $symtab{$clabel} ne '') {
150
            print STDERR $clabel . ': Multiple definition';
151
            print "//!" .  $clabel . ': Multiple definition';
152
        }
153
#       if ($lvalue eq "\$") {
154
#           $lvalue = $location;
155
#       }
156
        if ($clabel =~ /^[a-zA-Z_]/) {
157
            $symtab{$clabel} = $lvalue;
158
        }
159
        if ($opcode eq 'ds') {
160
            &dostring($_);
161
            return 1;
162
        }
163
 
164
        if ($opcode eq 'end') {
165
            foreach $c (keys %con) {
166
                if ($symtab{$c} eq '') {
167
                  $symtab{$c} = $location;
168
                  $con2{$location}=$c;
169
                  &emit(0,-1);  #placeholder
170
              }
171
            }
172
            $pass = 2;
173
            $location = $base;
174
            return 2;
175
        }
176
        if ($opcode eq '') { } else {
177
# need to process afield in case of constant
178
           if ($opmap{$opcode}>=0) { $location=$location+1; &xeval($afield); }
179
           if ($adda{$opcode}==2) { $location=$location+1; }
180
        }
181
        return 1;  # end pass 1
182
    }
183
 
184
    if ($pass == 2) {
185
        $opcode = &toLOWER($Fld[1]);
186
        if ($Fld[2]!~/['"]/) {
187
          $afield = &toLOWER($Fld[2]);
188
          }
189
        else {
190
          s/^[^'"#]*(['"#])/\1/;  # get whole string
191
          $afield=$_;
192
          }
193
        $afield = &xeval($afield);
194
    if ($opcode eq 'org') {
195
        $location = &xeval($afield);
196
        printf("@ %03x\n",$location);
197
        return 1;
198
    }
199
 
200
    if ($opcode eq 'ds') {
201
        &dostring($_);
202
        return 1;
203
    }
204
        if ($opcode eq 'end') {
205
            while ($con2{$location} ne '') {
206
                &emit($con{$con2{$location}},-1);
207
            }
208
            $pass=1;
209
            close F;
210
 
211
              return 0;
212
        }
213
        if ($opcode ne '') {
214
          $v=$opmap{$opcode};
215
          if ($v eq "") {
216
              print STDERR ("Bad opcode $opcode");
217
              print "//! Bad opcode $opcode";
218
          }
219
          if ($adda{$opcode}==1) {  $v+=$afield; }
220
          if ($v ne -1)  { &emit($v); }
221
          if ($adda{$opcode}==2) { &emit($afield,-1); }
222
      }
223
    return 1;
224
   }
225
 
226
 
227
 
228
 
229
 
230
sub emit {
231
    local($n,$flag) = @_;
232
    if ($pass == 2) {
233
        if ($flag==-1) {
234
            printf("%04x    // (%03x)\n",$n,$location);
235
        } else {
236
            printf("%04x    // (%03x)%s\n",$n,$location,$theLine);
237
        }
238
    }
239
    $location = $location + 1;
240
}
241
 
242
 
243
sub toLOWER {
244
    local ($s)=@_;
245
    $s=~s/([^\W0-9_])/\l$1/g;
246
    return $s;
247
}
248
 
249
sub xeval {
250
    local ($S)=@_;
251
    $SERR=$S;
252
    $symtab{'_location_'}=$location;
253
# handle immediate constant '#xxx'
254
   if ($S=~/^#/) {
255
     $S=~s/#(.*)/\1/;
256
     $sv=&xeval($S);
257
     $con{"_con_" . $sv}=$sv;
258
     return $symtab{"_con_" . $sv};
259
   }
260
# need to interpret string literals
261
    if ($S=~/'/) {
262
        $S=~s/'(.*)'/\$tstr="\1"/;
263
        eval($S);
264
        if (length($tstr)==1) { $S=sprintf("%d",ord($tstr)); }
265
        else { $S=sprintf("%d",ord(substr($tstr,1,1))*256+ord(substr($tstr,2,1))); }
266
 
267
    } elsif ($S=~/"/) {
268
        $S=~s/"(.*)"/\$tstr="\1"/;
269
        eval($S);
270
        if (length($tstr)==1) { $S=sprintf("%d",ord($tstr)); }
271
        else { $S=sprintf("%d",ord(substr($tstr,1,1))*256+ord(substr($tstr,2,1))); }
272
    } else {
273
        $S=~s/(^|\W)([A-zA-Z_][a-zA-Z_0-9]*)/\1\$symtab{'\2'}/g;
274
   }
275
    $rv= eval($S);
276
# Would like to detect undefined symbols here but tough to do
277
    if ($pass==2 && $rv eq "" & $S ne "") {
278
       print STDERR "Undefined: " . $SERR;
279
       print "//! Undefined: $SERR";
280
    }
281
    return $rv;
282
  }
283
}
284
 
285
 
286
sub dostring {
287
    local ($S)=@_;
288
    $S=~s/^[^'"]*(['"])/\1/;
289
    $type=substr($S,1,1);  # ' or "
290
    $S=~s/['"](.*)['"]/\$tstr="\1"/;
291
    eval($S);
292
            $l=length($tstr);
293
            $j=1;
294
            if ($type eq '"') { $j=2; }
295
            $tstr="$tstr ";  # space pad odd string
296
            for ($i=1;$i<=$l;$i=$i+$j) {
297
                $c=ord(substr($tstr,$i,1));
298
                if ($j==2) { $c=$c*256+ord(substr($tstr,$i+1,1)); }
299
                &emit($c,$i==1?0:-1);
300
            }
301
        }

powered by: WebSVN 2.1.0

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