This source file includes following definitions.
- printline
- getadr
- grword
- getliteral
- getliteralquote
- writememory
- writestr
- writedc
- assemble_start
- assemble_end
- assemble_ds
- assemble_dc
- assemble_in
- assemble_out
- assemble_rpush
- assemble_rpop
- casl2cmd
- assemble_comet2cmd
- assembletok
- assembleline
- assemblefile
- assemble
- addcerrlist_assemble
- outassemble
1 #include "assemble.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <assert.h>
7 #include <errno.h>
8
9
10
11
12
13
14
15
16
17 void printline(FILE *stream, const char *filename, int lineno, char *line);
18
19
20
21
22
23
24
25
26
27
28
29
30 WORD getadr(const char *prog, const char *str, PASS pass);
31
32
33
34
35
36
37
38
39
40
41
42 WORD grword(const char *str, bool is_x);
43
44
45
46
47
48
49
50
51
52 WORD getliteral(const char *str, PASS pass);
53
54
55
56
57
58
59
60
61
62 WORD getliteralquote(const char *str);
63
64
65
66
67
68
69
70
71 void writememory(WORD word, WORD adr, PASS pass);
72
73
74
75
76
77
78
79 void writestr(const char *str, PASS pass);
80
81
82
83
84
85
86
87 void writedc(const char *str, PASS pass);
88
89
90
91
92
93
94
95
96 void assemble_start(const CMDLINE *cmdl, PASS pass);
97
98
99
100
101
102
103
104
105 void assemble_ds(const CMDLINE *cmdl, PASS pass);
106
107
108
109
110
111
112
113
114 void assemble_end(const CMDLINE *cmdl, PASS pass);
115
116
117
118
119
120
121
122
123 void assemble_dc(const CMDLINE *cmdl, PASS pass);
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 void assemble_in(const CMDLINE *cmdl, PASS pass);
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165 void assemble_out(const CMDLINE *cmdl, PASS pass);
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184 void assemble_rpush(const CMDLINE *cmdl, PASS pass);
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 void assemble_rpop(const CMDLINE *cmdl, PASS pass);
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223 bool casl2cmd(CMD *cmdtbl, const CMDLINE *cmdl, PASS pass);
224
225
226
227
228
229
230
231
232
233 bool assemble_comet2cmd(const CMDLINE *cmdl, PASS pass);
234
235
236
237
238
239
240
241
242
243 bool assembletok(const CMDLINE *cmdl, PASS pass);
244
245
246
247
248
249
250
251
252
253
254
255 bool assembleline(const char *line, PASS pass);
256
257
258
259
260 static CERR cerr_assemble[] = {
261 { 106, "operand mismatch in CASL II command" },
262 { 107, "no label in START" },
263 { 108, "not command of operand \"r\"" },
264 { 109, "not command of operand \"r1,r2\"" },
265 { 110, "not command of operand \"r,adr[,x]\"" },
266 { 111, "not command of operand \"adr[,x]\"" },
267 { 112, "not command of no operand" },
268 { 113, "operand too many in COMET II command" },
269 { 119, "out of COMET II memory" },
270 { 120, "GR0 in operand x" },
271 { 122, "cannot create hash table" },
272 { 124, "more than one character in literal" },
273 { 125, "not GR in operand x" },
274 { 126, "syntax error in character constant. In CASL II, two consecutive apostrophes ('') represent a single apostrophe (')." },
275 { 127, "empty character constant" },
276 };
277
278
279
280
281 static CMD ascmd[] = {
282 { "START", assemble_start },
283 { "END", assemble_end },
284 { "DS", assemble_ds },
285 { "DC", assemble_dc },
286 { "", NULL }
287 };
288
289
290
291
292 static CMD macrocmd[] = {
293 { "OUT", assemble_out },
294 { "IN", assemble_in },
295 { "RPUSH", assemble_rpush },
296 { "RPOP", assemble_rpop },
297 { "", NULL }
298 };
299
300 ASPTR *asptr = NULL;
301
302 ASMODE asmode = {false, false, false, false, false};
303
304 void printline(FILE *stream, const char *filename, int lineno, char *line)
305 {
306 fprintf(stream, "%s:%5d:%s", filename, lineno, line);
307 }
308
309 WORD getadr(const char *prog, const char *str, PASS pass)
310 {
311 WORD adr = 0;
312
313 if(str[0] == '=') {
314 adr = getliteral(str, pass);
315 } else if(isdigit(str[0]) || str[0] == '-' || str[0] == '#') {
316 adr = nh2word(str);
317 } else {
318 if(pass == SECOND) {
319 if((adr = getlabel(prog, str)) == 0xFFFF) {
320 adr = getlabel("", str);
321 }
322 if(adr == 0xFFFF) {
323 setcerr(103, str);
324 }
325 }
326 }
327 return adr;
328 }
329
330 WORD grword(const char *str, bool is_x)
331 {
332 WORD r = 0;
333
334
335 if(strlen(str) != 3 ||
336 strncmp(str, "GR", 2) != 0 ||
337 str[2] < '0' || str[2] > '0' + (GRSIZE - 1))
338 {
339 return 0xFFFF;
340 }
341 r = (WORD)(str[2] - '0');
342
343 if(is_x == true && r == 0x0) {
344 setcerr(120, "");
345 return 0;
346 }
347 return r;
348 }
349
350 WORD getliteral(const char *str, PASS pass)
351 {
352 assert(str[0] == '=');
353 str++;
354 WORD val = 0;
355 WORD adr = 0;
356
357 if(str[0] == '\'') {
358 val = getliteralquote(str);
359 } else {
360 val = nh2word(str);
361 }
362 if(cerr->num == 0) {
363
364
365 if(pass == FIRST) {
366 adr = asptr->lptr;
367 writememory(val, (asptr->lptr)++, pass);
368 } else {
369
370 char llabel[LITERALSIZE + 1];
371 sprintf(llabel, "=%04X", val);
372 adr = getlabel("", llabel);
373 if(adr == 0xFFFF) {
374 adr = asptr->lptr;
375 writememory(val, (asptr->lptr)++, pass);
376 addlabel("", llabel, adr);
377 }
378 }
379 }
380 return adr;
381 }
382
383 WORD getliteralquote(const char *str)
384 {
385 assert(str[0] == '\'');
386 size_t len = strlen(str);
387 WORD val = 0;
388 if(str[1] == '\'' && len == 2) {
389 setcerr(127, str);
390 } else if (len == 1 || str[len - 1] != '\'') {
391 setcerr(123, str);
392 } else if((str[1] != '\'' && len > 3) || (str[1] == '\'' && len > 4)) {
393 setcerr(124, str);
394 } else if(str[1] == '\'' && len == 3 && str[2] == '\'') {
395 setcerr(126, str);
396 } else {
397 val = (WORD)str[1];
398 }
399 return val;
400 }
401
402 void writememory(WORD word, WORD adr, PASS pass)
403 {
404 char *n = NULL;
405
406
407 if(adr >= sys->memsize) {
408 setcerr(119, (n = word2n(adr)));
409 FREE(n);
410 return;
411 }
412 (sys->memory)[adr] = word;
413 if(pass == SECOND && asmode.asdetail == true) {
414 fprintf(stdout, "\t#%04X\t#%04X\n", adr, word);
415 }
416 }
417
418 void writestr(const char *str, PASS pass)
419 {
420 assert(str[0] == '\'');
421
422
423 if(str[1] == '\'' && str[2] == '\0') {
424 setcerr(127, str);
425 } else {
426 int i = 1;
427 do {
428 if(str[i] == '\0') {
429
430 setcerr(123, str);
431 break;
432 }
433 if(str[i] == '\'') {
434 if(str[i + 1] != '\0' && str[i + 1] != '\'') {
435 setcerr(126, str);
436 break;
437 } else if(str[i + 1] == '\0') {
438 break;
439 } else {
440
441 writememory('\'', (asptr->ptr)++, pass);
442 i += 2;
443 }
444 } else {
445 writememory(str[i++], (asptr->ptr)++, pass);
446 }
447 } while(1);
448 }
449 }
450
451 void writedc(const char *str, PASS pass)
452 {
453 WORD adr = 0;
454
455 if(*str == '\'') {
456 writestr(str, pass);
457 } else {
458 if(str[0] == '#' || isdigit(str[0]) || str[0] == '-') {
459 adr = nh2word(str);
460 } else {
461 if(pass == SECOND && (adr = getlabel(asptr->prog, str)) == 0xFFFF) {
462 adr = getlabel("", str);
463 }
464 if(pass == SECOND && adr == 0xFFFF) {
465 setcerr(103, str);
466 }
467 }
468 writememory(adr, (asptr->ptr)++, pass);
469 }
470 }
471
472 void assemble_start(const CMDLINE *cmdl, PASS pass)
473 {
474 if(cmdl->opd->opdc > 1) {
475 setcerr(106, "");
476 return;
477 }
478 if(!cmdl->label[0]) {
479 setcerr(107, "");
480 return;
481 }
482
483 strcpy(asptr->prog, cmdl->label);
484
485 if(cmdl->opd->opdv[0] != NULL) {
486 asptr->ptr = execptr->start = getadr(asptr->prog, cmdl->opd->opdv[0], pass);
487 }
488 }
489
490 void assemble_end(const CMDLINE *cmdl, PASS pass)
491 {
492 if(cmdl->opd->opdc > 0) {
493 setcerr(106, "");
494 return;
495 }
496
497 if(pass == FIRST) {
498 asptr->lptr = asptr->ptr;
499 }
500
501 else if(pass == SECOND) {
502 execptr->end = asptr->lptr;
503 }
504 strcpy(asptr->prog, "");
505 }
506
507 void assemble_ds(const CMDLINE *cmdl, PASS pass)
508 {
509 if(cmdl->opd->opdc != 1) {
510 setcerr(106, "");
511 return;
512 }
513 for(int i = 0; i < atoi(cmdl->opd->opdv[0]); i++) {
514 writememory(0x0, (asptr->ptr)++, pass);
515 if(cerr->num > 0) {
516 break;
517 }
518 }
519 }
520
521 void assemble_dc(const CMDLINE *cmdl, PASS pass)
522 {
523 if(cmdl->opd->opdc == 0 || cmdl->opd->opdc >= OPDSIZE) {
524 setcerr(106, "");
525 return;
526 }
527 for(int i = 0; i < cmdl->opd->opdc; i++) {
528 writedc(cmdl->opd->opdv[i], pass);
529 if(cerr->num > 0) {
530 break;
531 }
532 }
533 }
534
535 void assemble_in(const CMDLINE *cmdl, PASS pass)
536 {
537 char *line = malloc_chk(LINESIZE + 1, "assemble_in.line");
538
539 if(cmdl->opd->opdc == 0 || cmdl->opd->opdc > 2) {
540 setcerr(106, "");
541 return;
542 }
543 assembleline(" PUSH 0,GR1", pass);
544 assembleline(" PUSH 0,GR2", pass);
545 sprintf(line, " LAD GR1,%s", cmdl->opd->opdv[0]);
546 assembleline(line, pass);
547 sprintf(line, " LAD GR2,%s", cmdl->opd->opdv[1]);
548 assembleline(line, pass);
549 assembleline(" SVC 1", pass);
550 assembleline(" POP GR2", pass);
551 assembleline(" POP GR1", pass);
552 FREE(line);
553 }
554
555 void assemble_out(const CMDLINE *cmdl, PASS pass)
556 {
557 char *line = malloc_chk(LINESIZE + 1, "assemble_out.line");
558
559 if(cmdl->opd->opdc == 0 || cmdl->opd->opdc > 2) {
560 setcerr(106, "");
561 return;
562 }
563 assembleline(" PUSH 0,GR1", pass);
564 assembleline(" PUSH 0,GR2", pass);
565 sprintf(line, " LAD GR1,%s", cmdl->opd->opdv[0]);
566 assembleline(line, pass);
567 sprintf(line, " LAD GR2,%s", cmdl->opd->opdv[1]);
568 assembleline(line, pass);
569 assembleline(" SVC 2", pass);
570 assembleline(" LAD GR1,=#A", pass);
571 assembleline(" LAD GR2,=1", pass);
572 assembleline(" SVC 2", pass);
573 assembleline(" POP GR2", pass);
574 assembleline(" POP GR1", pass);
575 FREE(line);
576 }
577
578 void assemble_rpush(const CMDLINE *cmdl, PASS pass)
579 {
580 char *line = malloc_chk(LINESIZE + 1, "assemble_rpush.line");
581
582 if(cmdl->opd->opdc > 0) {
583 setcerr(106, "");
584 return;
585 }
586 for(int i = 1; i <= GRSIZE-1; i++) {
587 sprintf(line, " PUSH 0,GR%d", i);
588 assembleline(line, pass);
589 }
590 FREE(line);
591 }
592
593 void assemble_rpop(const CMDLINE *cmdl, PASS pass)
594 {
595 char *line = malloc_chk(LINESIZE + 1, "assemble_rpop.line");
596
597 if(cmdl->opd->opdc > 0) {
598 setcerr(106, "");
599 return;
600 }
601 for(int i = GRSIZE-1; i >= 1; i--) {
602 sprintf(line, " POP GR%d", i);
603 assembleline(line, pass);
604 }
605 FREE(line);
606 }
607
608 bool casl2cmd(CMD *cmdtbl, const CMDLINE *cmdl, PASS pass)
609 {
610 void (*cmdptr)(const CMDLINE *, PASS) = NULL;
611
612 for(int i = 0; cmdtbl[i].name[0]; i++) {
613 if(strcmp(cmdl->cmd, cmdtbl[i].name) == 0) {
614 cmdptr = cmdtbl[i].ptr;
615 (*cmdptr)(cmdl, pass);
616 return true;
617 }
618 }
619 return false;
620 }
621
622 bool assemble_comet2cmd(const CMDLINE *cmdl, PASS pass)
623 {
624 WORD cmd = 0;
625 WORD r_r1 = 0;
626 WORD x_r2 = 0;
627 WORD adr = 0;
628
629
630 if(cmdl->opd->opdc == 0) {
631 if((cmd = getcmdcode(cmdl->cmd, NONE)) == 0xFFFF) {
632 setcerr(112, cmdl->cmd);
633 return false;
634 }
635 writememory(cmd, (asptr->ptr)++, pass);
636 }
637
638 else if((r_r1 = grword(cmdl->opd->opdv[0], false)) != 0xFFFF) {
639
640 if(cmdl->opd->opdc == 1) {
641 if((cmd = getcmdcode(cmdl->cmd, R_)) == 0xFFFF) {
642 setcerr(108, cmdl->cmd);
643 return false;
644 }
645 cmd |= (r_r1 << 4);
646 writememory(cmd, (asptr->ptr)++, pass);
647 }
648
649 else if(cmdl->opd->opdc == 2 && (x_r2 = grword(cmdl->opd->opdv[1], false)) != 0xFFFF) {
650 if((cmd = getcmdcode(cmdl->cmd, R1_R2)) == 0xFFFF) {
651 setcerr(109, cmdl->cmd);
652 return false;
653 }
654 cmd |= ((r_r1 << 4) | x_r2);
655
656 writememory(cmd, (asptr->ptr)++, pass);
657 }
658
659 else if(cmdl->opd->opdc == 2 || cmdl->opd->opdc == 3) {
660 if((cmd = getcmdcode(cmdl->cmd, R_ADR_X)) == 0xFFFF) {
661 setcerr(110, cmdl->cmd);
662 return false;
663 }
664 cmd |= (r_r1 << 4);
665
666 if(cmdl->opd->opdc == 3) {
667 if((x_r2 = grword(cmdl->opd->opdv[2], true)) == 0xFFFF) {
668 setcerr(125, cmdl->cmd);
669 return false;
670 }
671 cmd |= x_r2;
672 }
673 adr = getadr(asptr->prog, cmdl->opd->opdv[1], pass);
674
675 writememory(cmd, (asptr->ptr)++, pass);
676 writememory(adr, (asptr->ptr)++, pass);
677 } else {
678 setcerr(113, cmdl->cmd);
679 return false;
680 }
681 }
682
683 else if(cmdl->opd->opdc == 1 || cmdl->opd->opdc == 2) {
684 if((cmd = getcmdcode(cmdl->cmd, ADR_X)) == 0xFFFF) {
685 setcerr(111, cmdl->cmd);
686 return false;
687 }
688
689 if(cmdl->opd->opdc == 2) {
690 x_r2 = grword(cmdl->opd->opdv[1], true);
691 if(cerr->num > 0) {
692 return false;
693 }
694 cmd |= x_r2;
695 }
696
697
698
699 if(pass == SECOND && cmd == 0x8000) {
700 adr = getlabel("", cmdl->opd->opdv[0]);
701 }
702 if(cmd != 0x8000 || (pass == SECOND && adr == 0xFFFF)) {
703 adr = getadr(asptr->prog, cmdl->opd->opdv[0], pass);
704 }
705
706 writememory(cmd, (asptr->ptr)++, pass);
707 writememory(adr, (asptr->ptr)++, pass);
708 }
709 return (cerr->num == 0) ? true : false;
710 }
711
712 bool assembletok(const CMDLINE *cmdl, PASS pass)
713 {
714
715 if(!cmdl->cmd[0]) {
716 return true;
717 }
718
719 if(casl2cmd(ascmd, cmdl, pass) == false && casl2cmd(macrocmd, cmdl, pass) == false) {
720
721 if(assemble_comet2cmd(cmdl, pass) == false) {
722 if(cerr->num == 0) {
723 setcerr(113, cmdl->cmd);
724 }
725 }
726 }
727 return (cerr->num == 0) ? true : false;
728 }
729
730 bool assembleline(const char *line, PASS pass)
731 {
732 CMDLINE *cmdl = NULL;
733 bool stat = true;
734
735 cmdl = linetok(line);
736 stat = (cerr->num == 0) ? true : false;
737 if(cmdl != NULL) {
738 if(stat == true) {
739 if(pass == FIRST && cmdl->label[0]) {
740 stat = addlabel(asptr->prog, cmdl->label, asptr->ptr);
741 }
742 }
743 if(stat == true) {
744 stat = assembletok(cmdl, pass);
745 }
746 FREE(cmdl->label);
747 if(cmdl->opd != NULL) {
748 for(int i = 0; i < cmdl->opd->opdc; i++) {
749 FREE(cmdl->opd->opdv[i]);
750 }
751 }
752 FREE(cmdl->opd);
753 FREE(cmdl->cmd);
754 }
755 FREE(cmdl);
756 return stat;
757 }
758
759
760
761
762
763
764 bool assemblefile(const char *file, PASS pass)
765 {
766 int lineno = 1;
767 char *line = NULL;
768 FILE *fp = NULL;
769
770 if((fp = fopen(file, "r")) == NULL) {
771 cerr->num = errno;
772 perror(file);
773 return false;
774 }
775 for(line = malloc_chk(LINESIZE + 1, "assemble.line"); fgets(line, LINESIZE, fp); lineno++) {
776 if((pass == FIRST && asmode.src == true) || (pass == SECOND && asmode.asdetail == true)) {
777 printline(stdout, file, lineno, line);
778 }
779 if(assembleline(line, pass) == false) {
780 break;
781 }
782 }
783 if(cerr->num > 0) {
784 fprintf(stderr, "Assemble error - %d: %s\n", cerr->num, cerr->msg);
785 printline(stderr, file, lineno, line);
786 }
787 FREE(line);
788 fclose(fp);
789 return (cerr->num == 0) ? true : false;
790 }
791
792 bool assemble(int filec, char *filev[], WORD adr)
793 {
794 int i;
795 PASS pass;
796 WORD bp[filec];
797 bool stat = false;
798
799 asptr = malloc_chk(sizeof(ASPTR), "asptr");
800 asptr->prog = malloc_chk(LABELSIZE + 1, "asptr.prog");
801 asptr->ptr = adr;
802
803 for(pass = FIRST; pass <= SECOND; pass++) {
804 for(i = 0; i < filec; i++) {
805
806 if(pass == FIRST) {
807 bp[i] = asptr->ptr;
808 } else if(pass == SECOND) {
809 asptr->ptr = bp[i];
810 }
811 if(execmode.trace == true || execmode.dump == true ||
812 asmode.src == true || asmode.label == true || asmode.asdetail == true)
813 {
814 fprintf(stdout, "\nAssemble %s (%d)\n", filev[i], pass);
815 }
816
817 stat = assemblefile(filev[i], pass);
818 if(stat == false) {
819 goto asfin;
820 }
821 }
822 if(asmode.label == true) {
823 if(pass == FIRST) {
824 printlabel();
825 if(asmode.onlylabel == true) {
826 break;
827 }
828 }
829 if(pass == SECOND) {
830 printliteral();
831 }
832 }
833 }
834 asfin:
835 freelabel();
836 FREE(asptr->prog);
837 FREE(asptr);
838 return stat;
839 }
840
841
842 void addcerrlist_assemble()
843 {
844 addcerrlist_tok();
845 addcerrlist_word();
846 addcerrlist_label();
847 addcerrlist(ARRAYSIZE(cerr_assemble), cerr_assemble);
848 }
849
850 void outassemble(const char *file)
851 {
852 FILE *fp = NULL;
853
854 if((fp = fopen(file, "w")) == NULL) {
855 perror(file);
856 exit(1);
857 }
858 fwrite(sys->memory, sizeof(WORD), execptr->end, fp);
859 fclose(fp);
860 }