/ [mix] / trunk / mixal.y
To checkout: svn checkout http://svn.gnu.org.ua/sources/mix/trunk/mixal.y
Puszcza

Contents of /trunk/mixal.y

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations)
Wed Mar 30 16:43:11 2005 UTC (16 years, 10 months ago) by gray
File size: 16626 byte(s)
Initial revision

1 %{
2 #ifdef HAVE_CONFIG_H
3 # include <config.h>
4 #endif
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <stdarg.h>
9 #include <errno.h>
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <ctype.h>
13 #include "mix.h"
14 #include "mixasm.h"
15
16 #define MEMORYSIZE MEMSIZE
17 #define B1 (1<<BYTESIZE)
18 #define B2 B1*B1
19 #define B3 B2*B1
20 #define B5 B2*B3
21 #define SIGN(a) (a&(MINUS))
22 #define MAG(a) (a&(B5-1))
23 #define MINUS ((unsigned)2*B5)
24 #define PLUS 0
25 #define update_memory(A) \
26 memory[location_counter]=(A); lines[lineno]=location_counter++;
27 char version[] = "1.2";
28 char *progname;
29 char *source_file = NULL;
30 char *listfile = "mixal.lst";
31 FILE *lst;
32
33 int lineno = 1;
34 int location_counter = 0;
35 unsigned word;
36 struct Symbol *s;
37 struct ref *p;
38 char literal[13];
39 char opcode[6];
40 unsigned memory[MEMORYSIZE];
41 int lines[MEMORYSIZE];
42 extern Symbol *symlist;
43
44 int list = 0; /* Produce listing */
45 int xref = 0; /* Produce cross-reference listing */
46 int writeraw = 0; /* Write raw code */
47
48 FILE *create_temp(char *tmpl);
49 int eval_op(char *c);
50 int word_s(unsigned w);
51 void symbols(void);
52 void end_routine(int start);
53 int num(char *text);
54 int find_backward(char *name);
55 void find_forward(Symbol *f);
56 int eval_f(char *c);
57 void warning(char *s, char *t);
58 void listing();
59 void dumpsymtab(FILE *fp);
60
61 unsigned add_mix(), sub_mix(), div_mix(), mul_mix(), w_eval();
62
63 char alf[] =
64 " ABCDEFGHInJKLMNOPQRepSTUVWXYZ0123456789.,()+-*/=$<>@;:'abcdfghi";
65
66 %}
67
68 %union {
69 unsigned val; /* WATCH OUT FOR THIS */
70 struct Symbol *symp;
71 char *txt;
72 }
73 %token <symp> DEFINED_SYMBOL
74 %token <symp> LOCAL_SYMBOL
75 %token <symp> FUTURE_REFERENCE
76 %token <symp> LOC
77 %token <symp> END
78 %token <val> UNDEF
79 %token <val> DEF
80 %token <val> NUMBER
81 %token <val> ASTERISK
82 %token <txt> TEXT
83 %token <txt> OPCODE
84 %token <txt> PSEUDO
85 %token <txt> ALF
86 %left '-' '+'
87 %left '*' '/'
88 %left ':' SLASHES
89 %nonassoc UMINUS
90
91 %type <val> expression
92 %type <val> atomic_expression
93 %type <val> a_part i_part f_part w_value
94 %type <symp> literal_constant
95 %type <symp> label
96 %type <txt> op pseudo
97 %%
98
99 statement_list: statement comment '\n' { lineno++; }
100 | statement_list statement comment '\n' { lineno++; }
101 ;
102
103 statement : label op a_part i_part f_part
104 {
105 word = eval_op(opcode);
106 word |= SIGN($3) | MAG($3)*B3 | $4*B2 | $5*B1;
107 update_memory(word);
108 }
109 | label pseudo w_value
110 {
111 if (!strcmp(opcode,"EQU")) {
112 /* if no label wizard debug */
113 if ($1 == NULL)
114 dumpsymtab(stderr);
115 else
116 $1->value = $3;
117 } else if (!strcmp(opcode,"ORIG")) {
118 location_counter = word_s($3);
119 } else if (!strcmp(opcode,"CON")) {
120 update_memory($3);
121 } else if (!strcmp(opcode,"END")) {
122 if ($1 != NULL)
123 $1->type = END;
124 symbols();
125 end_routine(word_s($3));
126 }
127 }
128 | label ALF
129 {
130 update_memory(num($2));
131 }
132 | ASTERISK { ; }
133 ;
134
135 label : /* none */
136 {
137 $$ = NULL;
138 }
139 | LOC
140 {
141 if (localref($1)) {
142 yyerror("invalid label");
143 YYERROR;
144 }
145 $$ = $1;
146 $1->type = DEF;
147 $1->line = lineno;
148 $1->value = location_counter;
149 }
150 ;
151
152 comment : /* nothing */
153 | TEXT { ; }
154 ;
155
156 op : OPCODE
157 {
158 strcpy(opcode, $1);
159 }
160 ;
161
162 pseudo : PSEUDO
163 {
164 strcpy(opcode, $1);
165 }
166 ;
167
168 expression : atomic_expression
169 | '+' atomic_expression %prec UMINUS
170 {
171 $$ = $2;
172 }
173 | '-' atomic_expression %prec UMINUS
174 {
175 $$ = $2 ^ MINUS;
176 }
177 | expression '+' atomic_expression
178 {
179 $$ = add_mix($1, $3);
180 }
181 | expression '-' atomic_expression
182 {
183 $$ = sub_mix($1, $3);
184 }
185 | expression ASTERISK atomic_expression
186 {
187 $$ = mul_mix($1, $3);
188 }
189 | expression '/' atomic_expression
190 {
191 $$ = div_mix($1, $3);
192 }
193 | expression SLASHES atomic_expression
194 {
195 $$ = mul_mix($1, B5 / MAG($3));
196 }
197 | expression ':' atomic_expression
198 {
199 $$ = add_mix(mul_mix($1, 8), $3);
200 }
201 ;
202
203 atomic_expression: NUMBER
204 | ASTERISK
205 {
206 $$ = location_counter;
207 }
208 | DEFINED_SYMBOL
209 {
210 $$ = $1->value;
211 if (xref)
212 $1->xref = addref($1->xref, location_counter,
213 lineno);
214 }
215 | LOCAL_SYMBOL
216 {
217 $$ = $1->value = find_backward($1->name);
218 }
219 ;
220
221 a_part : /* empty */
222 {
223 $$ = 0;
224 }
225 | expression
226 | FUTURE_REFERENCE
227 {
228 $1->reflist = addref($1->reflist,location_counter,lineno);
229 if (xref)
230 $1->xref = addref($1->xref, location_counter,
231 lineno);
232 }
233 | literal_constant
234 { ; }
235 ;
236
237 i_part : /* empty */
238 {
239 $$ = 0;
240 }
241 | ',' expression
242 {
243 $$ = $2;
244 }
245 ;
246
247 f_part : /* empty */
248 {
249 $$ = eval_f(opcode);
250 }
251 | '(' expression ')'
252 {
253 $$ = $2;
254 }
255 ;
256
257 w_value : expression f_part
258 {
259 $$ = w_eval(0, $1, $2);
260 }
261 | w_value ',' expression f_part
262 {
263 $$ = w_eval($1, $3, $4);
264 }
265 ;
266
267 literal_constant: '=' w_value '='
268 {
269 sprintf(literal,"=%d=",word_s($2));
270 if (!(s = lookup(literal)))
271 s = install(literal,$2,lineno);
272 s->reflist = addref(s->reflist,location_counter,lineno);
273 if (xref)
274 s->xref = addref(s->xref, location_counter, lineno);
275 }
276
277 ;
278
279 %%
280
281 unsigned
282 add_mix(unsigned a, unsigned b)
283 {
284 unsigned s, t;
285
286 s = SIGN(a);
287 t = SIGN(b);
288 if (s != t) {
289 if (MAG(a) > MAG(b)) {
290 a = MAG(a) - MAG(b);
291 t = s;
292 } else
293 a = MAG(b) - MAG(a);
294 } else
295 a = MAG(a) + MAG(b);
296 if (a > B5-1)
297 yyerror("Arithmetic result greater than 1073741823");
298 return a|t;
299 }
300
301 unsigned
302 sub_mix(unsigned a, unsigned b)
303 {
304 b ^= MINUS;
305 return add_mix(a, b);
306 }
307
308
309 unsigned
310 mul_mix(unsigned a, unsigned b)
311 {
312 unsigned s;
313 long long w;
314 s = SIGN(a) == SIGN(b) ? PLUS : MINUS;
315 if ((w = MAG(a)*MAG(b)) > B5-1)
316 yyerror("Arithmetic result greater than 1073741823");
317 return s|MAG(w);
318 }
319
320 unsigned
321 div_mix(unsigned a, unsigned b)
322 {
323 unsigned s;
324 s = SIGN(a);
325 return s|MAG(MAG(a)/MAG(b));
326 }
327
328 unsigned
329 w_eval(unsigned x, unsigned y,int f)
330 {
331 int l, r;
332 unsigned sign, mask;
333
334 l = f/8;
335 r = f%8;
336 mask = B5 - 1;
337 if (l < 0 || l > r || r > 5)
338 yyerror("Invalid F-part");
339 if ( l == 0 ) { /* Is sign included ? */
340 sign = MINUS & y;
341 l = 1;
342 } else sign = MINUS & x; /* keep previous sign */
343 y <<= (4 - r + l) * BYTESIZE; /* take correct no of bytes from right
344 end */
345 y = MAG(y); /* truncate to 5 bytes */
346 y >>= (l - 1) * BYTESIZE; /* position within word */
347 mask <<= (4 - r + l) * BYTESIZE; /* do same for mask */
348 mask = MAG(mask); /* truncate to 5 bytes */
349 mask >>= (l - 1) * BYTESIZE;
350 x &= ~mask; /* mask off where y is to be inserted */
351 x = MAG(x); /* discard sign */
352 x |= y; /* insert y */
353 x |= sign; /* insert sign */
354 return x;
355 }
356
357 int
358 word_s(unsigned w) /* convert mix word into a signed integer */
359 {
360 if (w & MINUS) w = -MAG(w);
361 return w;
362 }
363
364 int
365 yyerror(char *s) /* called for yacc syntax error */
366 {
367 warning(s, (char *) 0);
368 }
369
370 void
371 warning(char *s, char *t)
372 {
373 fprintf(stderr, "%s: %s", progname, s);
374 if (t)
375 fprintf(stderr, " %s", t);
376 fprintf(stderr, " near line %d\n", lineno);
377 }
378
379 int
380 main(int argc, char *argv[])
381 {
382 extern FILE *yyin;
383 int i;
384
385 progname = argv[0];
386
387 for (i = 0; i < MEMORYSIZE; i++)
388 lines[i] = -1;
389 while ((i = getopt(argc, argv, "lrVx")) != EOF) {
390 switch (i) {
391 case 'l': /* produce a listing */
392 list = 1;
393 break;
394 case 'r':
395 writeraw = 1;
396 break;
397 case 'V': /* show version */
398 printf("%s: version %s\n", progname, version);
399 exit(0);
400 case 'x': /* produce cross-reference listing */
401 xref = 1;
402 break;
403 default:
404 fprintf(stderr, "usage: %s [-lnV] [filename]\n", progname);
405 exit(1);
406 }
407 }
408 if (argc > optind) {
409 source_file = argv[optind];
410 if ((yyin = fopen(source_file, "r")) == NULL) {
411 fprintf(stderr,"can't open %s: %s\n", argv[1], strerror(errno));
412 exit(1);
413 }
414 }
415 if (list)
416 lst = create_temp("lstXXXXXX");
417 yyparse();
418 sort_symbols();
419 if (list)
420 listing();
421 else if (xref)
422 dumpsymtab(stderr);
423 }
424
425 FILE *
426 create_temp(char *tmpl)
427 {
428 char *buf;
429 char *tmp;
430 int fd;
431 FILE *fp;
432
433 if ((tmp = getenv("TMP")) == NULL && (tmp = getenv("TEMP")) == NULL)
434 tmp = "/tmp";
435 buf = malloc(strlen(tmp) + 1 + strlen(tmpl) + 1);
436 if (!buf)
437 abort();
438 sprintf(buf, "%s/%s", tmp, tmpl);
439
440 #ifdef HAVE_MKSTEMP
441 {
442 int save_mask = umask (077);
443 fd = mkstemp (buf);
444 umask (save_mask);
445 }
446 #else
447 if (mktemp (buf))
448 fd = open (filename, O_CREAT|O_EXCL|O_RDWR, 0600);
449 else
450 fd = -1;
451 #endif
452
453 if (fd == -1) {
454 fprintf(stderr, "can't create temporary file %s: %s\n",
455 tmp, strerror(errno));
456 exit(1);
457 }
458
459 unlink(buf);
460 free(buf);
461 return fdopen(fd, "w+");
462 }
463
464 void
465 listing()
466 {
467 FILE *fp;
468 char buf[512];
469 int i, l;
470
471 rewind(lst);
472
473 fp = fopen(listfile, "w");
474 if (fp == NULL) {
475 fprintf(stderr, "can't open %s: %s\n", listfile, strerror(errno));
476 exit(1);
477 }
478
479 for (l = 1; l <= lineno; l++) {
480 if ((i = lines[l]) != -1) {
481 int Av, Iv, Fv, Cv, Sv;
482 Sv = (memory[i] & MINUS) ? '-' : '+';
483 Av = (memory[i] & (B5 - 1))>>3*BYTESIZE;
484 Iv = (memory[i] & (B3 - 1))>>2*BYTESIZE;
485 Fv = (memory[i] & (B2 - 1))>>BYTESIZE;
486 Cv = (memory[i] & (B1 - 1));
487 fprintf(fp, "%4d: %c %4d %2d %2d %2d %3d ",
488 i, Sv, Av, Iv, Fv, Cv, l);
489 } else
490 fprintf(fp, "%23s %3d ", " ", l);
491
492 if (fgets(buf, sizeof(buf), lst))
493 fputs(buf, fp);
494 else
495 fputs("\n", fp);
496 }
497 fputs("\n", fp);
498 dumpsymtab(fp);
499 fclose(fp);
500 }
501
502
503 void
504 dumpsymtab(FILE *fp)
505 {
506 Symbol *s;
507 ref *refp;
508
509 fprintf(fp, "\nSymbol Value Line");
510 if (xref) {
511 fprintf(fp, " Referenced on line");
512 }
513 fprintf(fp, "\n");
514 for (s = symlist; s; s = s->next) {
515 if (localref(s)) /* don't dump local symbol backward and forward
516 refs */
517 continue;
518
519 fprintf(fp, "%-10s %4d %4d",
520 s->name, word_s(s->value), s->line);
521 if (xref) {
522 sort_refs(s);
523 for (refp = s->xref; refp; refp = refp->next) {
524 if (refp->line != s->line)
525 fprintf(fp, " %4d", refp->line);
526 }
527 }
528 fprintf(fp, "\n");
529 }
530 }
531
532 void
533 tlist(char *fmt, ...)
534 {
535 va_list ap;
536
537 if (!lst)
538 return;
539 va_start(ap, fmt);
540 vfprintf(lst, fmt, ap);
541 va_end(ap);
542 }
543
544 /* dump literals and fix forward refs and undefined symbols */
545 void
546 symbols()
547 {
548 Symbol *s;
549 ref *p;
550
551 s = symlist;
552 while (s) {
553 if (s->name[0] == '=') {
554 memory[location_counter] = w_eval(0,s->value,5);
555 s->value = location_counter++;
556 }
557 if (s->type == UNDEF
558 && (strlen(s->name) != 2
559 || s->name[1] != 'F'
560 || s->name[0] < '0'
561 || s->name[0] > '9')) {
562 fprintf(stderr,"Warning: '%-10s CON 0' inserted at %d:\n",
563 s->name,location_counter);
564 memory[location_counter] = 0;
565 s->value = location_counter++;
566 s->type = DEF;
567 }
568 s = s->next;
569 }
570 s = symlist;
571 while (s) {
572 /* Now that the literal pool has been dumped we can
573 evaluate the location of the END statement */
574 if (s->type == END)
575 s->value = location_counter;
576 /* Now we can handle any forward references */
577 p = s->reflist;
578 while (p) {
579 memory[p->address] &= (B3 - 1);
580 memory[p->address] |= s->value<<(BYTESIZE*3);
581 p = p->next;
582 }
583 if (strlen(s->name) == 2 && s->name[1] == 'F' &&
584 s->name[0] >= '0' && s->name[0] <= '9') {
585 find_forward(s);
586 s->type = DEF;
587 }
588 s = s->next;
589 }
590 }
591
592 char loader[] =
593 " O O6 Z O6 I C O4 0 EH A F F CF 0 E EU 0 IH G BB EJ CA. Z EU EH E BA\n"
594 " EU 2A-H S BB C U 1AEH 2AEN V E CLU ABG Z EH E BB J B. A 9 \n";
595
596 void
597 end_routine(int start)
598 {
599 long address, loc, sign, value;
600 int i, j, flag;
601 char field[7][11];
602 char title[6];
603
604 if (source_file) {
605 char *p;
606 if (p = strrchr(source_file, '/'))
607 p++;
608 else
609 p = source_file;
610 for (i = 0; i < 5 && p[i]; i++)
611 title[i] = toupper(p[i]);
612 title[i] = '\0';
613 } else
614 strcpy(title, "MIXAL");
615
616 if (writeraw) {
617 int count = 0;
618 for (i = 0; i <= 32; i++) {
619 printf("%c%c%c%c%c",
620 alf[ ((memory[i] & (B5 - 1))>>4*BYTESIZE) & (B1-1) ],
621 alf[ ((memory[i] & (B5 - 1))>>3*BYTESIZE) & (B1-1) ],
622 alf[ ((memory[i] & (B3 - 1))>>2*BYTESIZE) & (B1-1) ],
623 alf[ ((memory[i] & (B2 - 1))>> BYTESIZE) & (B1-1) ],
624 alf[ (memory[i] & (B1 - 1)) ]);
625 count++;
626 if (count % 16 == 0)
627 printf("\n");
628 }
629 return;
630 }
631
632 /* The loading routine */
633 printf("%s", loader);
634
635 flag = i = 0;
636 for (address = 0; address < MEMORYSIZE; address++)
637 if (memory[address]) {
638 sign = memory[address] & MINUS ? -1 : 1;
639 value = MAG(memory[address]);
640 if (!flag)
641 flag=1, loc=address;
642 if (address != loc + i || i >= 7) {
643 printf("%-5s%1d%04ld", title, i, loc);
644 for (j = 0; j < i; j++)
645 printf("%10s", field[j]);
646 printf("\n");
647 loc = address;
648 i = 0;
649 }
650 sprintf(field[i], "%010ld", value);
651 if (sign < 0)
652 field[i][9] = "~JKLMNOPQR"[field[i][9]-'0'];
653 i++;
654 }
655 printf("%-5s%1d%04ld", title, i, loc);
656 for (j = 0; j < i; j++)
657 printf("%10s", field[j]);
658 printf("\n");
659 printf("TRANS0%04d\n", start);
660 }
661
662 int
663 num(char *text)
664 {
665 int i, n;
666 char *p;
667
668 n = 0;
669 for (i = 0; i < 5; i++)
670 if (!text[i])
671 n = n*B1;
672 else if (p = strchr(alf,text[i]))
673 n = n*B1 + (p - alf);
674 else
675 yyerror("bad character in ALF constant");
676 return n;
677 }
678
679 int
680 eval_op(char *c)
681 {
682 int i;
683 for (i = 0; i < op_count; i++)
684 if (!strcmp(c, mix_optab[i].name))
685 return mix_optab[i].c;
686 yyerror("invalid opcode.");
687 return -1; /* FIXME */
688 }
689
690 int
691 eval_f(char *c)
692 {
693 int i;
694 for (i = 0; i < op_count; i++)
695 if (!strcmp(c, mix_optab[i].name))
696 return mix_optab[i].f;
697 return 5;
698 }
699
700 int
701 find_backward(char *name)
702 {
703 char here[3] = "0H";
704 int location;
705 int line;
706
707 s = symlist;
708 here[0] = name[0];
709 line = 0;
710 while(s) {
711 if (!strcmp(s->name, here) && lineno > s->line &&
712 s->line > line) {
713 location = s->value;
714 line = s->line;
715 }
716 s = s->next;
717 }
718 if (line == 0)
719 yyerror("missing backward 'here'");
720 return location;
721 }
722
723 void
724 find_forward(Symbol *f)
725 {
726 Symbol *s;
727 ref *p;
728 char here[3] = "0H";
729 int location;
730 int line;
731
732 s = symlist;
733 here[0] = f->name[0];
734 p = f->reflist;
735 while (p) {
736 line = B5;
737 s = symlist;
738 while(s) {
739 if (!strcmp(s->name, here) && p->line < s->line &&
740 s->line < line) {
741 location = s->value;
742 line = s->line;
743 }
744 s = s->next;
745 }
746 f->value = location;
747 if (line == B5)
748 yyerror("missing 'forward here'");
749 memory[p->address] &= (B3 - 1);
750 memory[p->address] |= location<<(BYTESIZE*3);
751 p = p->next;
752 }
753 }

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

Send suggestions and bug reports to Sergey Poznyakoff
ViewVC Help
Powered by ViewVC 1.1.20