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

Subversion Repositories zipcpu

[/] [zipcpu/] [trunk/] [sw/] [zasm/] [zasm.y] - Blame information for rev 17

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 13 dgisselq
/*******************************************************************************
2
**
3
** Filename:    zasm.y
4
**
5
** Project:     Zip CPU -- a small, lightweight, RISC CPU core
6
**
7
** Purpose:     The parser for the Zip Assembler.  This is actually not just
8
**              the parser, but the main program as well.
9
**
10
** Creator:     Dan Gisselquist, Ph.D.
11
**              Gisselquist Tecnology, LLC
12
**
13
********************************************************************************
14
**
15
** Copyright (C) 2015, Gisselquist Technology, LLC
16
**
17
** This program is free software (firmware): you can redistribute it and/or
18
** modify it under the terms of  the GNU General Public License as published
19
** by the Free Software Foundation, either version 3 of the License, or (at
20
** your option) any later version.
21
**
22
** This program is distributed in the hope that it will be useful, but WITHOUT
23
** ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
24
** FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25
** for more details.
26
**
27
** You should have received a copy of the GNU General Public License along
28
** with this program.  (It's in the $(ROOT)/doc directory, run make with no
29
** target there if the PDF file isn't present.)  If not, see
30
**  for a copy.
31
**
32
** License:     GPL, v3, as defined and found on www.gnu.org,
33
**              http://www.gnu.org/licenses/gpl.html
34
**
35
**
36
*******************************************************************************/
37
 
38
%{
39
 #include 
40
 #include 
41
 #include "asmdata.h"
42
 
43
  extern "C" int yylex(void);
44
  extern "C" int yyparse(void);
45
  // extern "C" FILE *yyin;
46
  void yyerror(const char *);
47
  unsigned int global_parser_pc;
48
  char *master_input_filename = NULL;
49
  extern int yylineno;
50
  char  *linecp = NULL; // A copy of the input line
51
%}
52
 
53
%token COMMA EQU PLUS MINUS TIMES HERE DOLLAR COLON
54
%token BOOLEANOR BITWISEOR BOOLEANAND BITWISEAND BITWISEXOR DOT
55
%token WORD FILL
56
%token LOADOP STOROP LDIOP
57
%token BAREOP BRANCHOP COND DUALOP IDENTIFIER INT LDHLOP REG SINGLOP
58
 
59
%union {
60
        ZPARSER::ZIPREG         u_reg;
61
        ZPARSER::ZIPCOND        u_cond;
62
        int                     u_ival;
63
        LEXOPCODE               u_op;
64
        char                    *u_id;
65
        ASMLINE                 *u_ln;
66
        AST                     *u_ast;
67
}
68
 
69
%type                   REG
70
%type           COND opcond
71
%type           INT
72
%type                   IDENTIFIER
73
%type                   BAREOP SINGLOP DUALOP BRANCHOP LDHLOP
74
%type                   unlabeledline instruction wordlist fillist opb
75
%type                   bareop singlop dualop loadop storop line
76
%type                   expr value multident
77
 
78
%% /* The grammar follows */
79
 
80
input:
81
  %empty
82
| input line { if ($2) {objcode += $2; global_parser_pc += $2->nlines(); if ($2->isdefined()) delete $2; } }
83
;
84
 
85
line:
86
   '\n' { $$ = NULL; }
87
| unlabeledline '\n' { $$ = $1; }
88
| multident COLON unlabeledline '\n' {
89
        if ($1->m_node_type == 'I') {
90
                if (((AST_IDENTIFIER*)$1)->m_id[0] == 'L')
91
                        stb_define(((AST_IDENTIFIER *)$1)->m_id, new AST_NUMBER(global_parser_pc));
92
                else
93
                        gbl_define(((AST_IDENTIFIER *)$1)->m_id, new AST_NUMBER(global_parser_pc));
94
                delete $1;
95
                }
96
        $$ = $3;
97
        }
98
| multident COLON '\n' {
99
        if ($1->m_node_type == 'I') {
100
                if (((AST_IDENTIFIER*)$1)->m_id[0] == 'L')
101
                        stb_define(((AST_IDENTIFIER *)$1)->m_id, new AST_NUMBER(global_parser_pc));
102
                else
103
                        gbl_define(((AST_IDENTIFIER *)$1)->m_id, new AST_NUMBER(global_parser_pc));
104
                delete $1;
105
        }
106
        $$ = new VLINE();
107
        }
108
| multident EQU expr '\n' {
109
        if ($1->m_node_type == 'I') {
110
                stb_define(((AST_IDENTIFIER *)$1)->m_id, $3);
111
                delete $1;
112
        }
113
        $$ = new VLINE();
114
        }
115
;
116
 
117
unlabeledline:
118
  instruction   { $$ = $1; }
119
| WORD wordlist { $$ = $2; }
120
| FILL fillist { $$ = $2; }
121
;
122
 
123
wordlist:
124
  expr  {
125
        if ($1->isdefined())
126
                $$ = new DLINE($1->eval());
127
        else {
128
                $$ = new VLINE();
129
                yyerror("ERROR: word list undefined");
130
        }}
131 16 dgisselq
| wordlist COMMA expr {
132
        if ($3->isdefined()) {
133
                LLINE   *ln;
134
                if ($1->m_state == 'L') {
135
                        ln = ((LLINE *)$1);
136
                } else {
137
                        ln = new LLINE();
138
                        ln->addline($1);
139
                } ln->addline(new DLINE($3->eval()));
140
                $$ = ln;
141
        } else {
142 13 dgisselq
                $$ = new VLINE();
143
                yyerror("ERROR: word list undefined\n");
144
        }}
145
;
146
 
147
fillist:
148
  expr COMMA expr {
149
                if (($1->isdefined())&&($3->isdefined())) {
150
                        int     ntimes = $1->eval(),
151
                                val = $3->eval();
152
                        LLINE   *ln = new LLINE();
153
                        for(int i=0; i
154
                                ln->addline(new DLINE(val));
155
                        $$ = ln;
156
                } else {
157
                        yyerror("Fill list undefined\n");
158
                        $$ = new VLINE();
159
                }
160
        }
161
;
162
 
163
instruction:
164
  dualop  opb COMMA REG {
165
                $$ = $1;
166
                ((TLINE*)$1)->m_imm = ((TLINE*)$2)->m_imm; ((TLINE*)$2)->m_imm = NULL;
167
                ((TLINE*)$1)->m_opb = ((TLINE*)$2)->m_opb;
168
                ((TLINE*)$1)->m_opa = $4;
169
                if ($1->isdefined()) {
170
                        $$ = ((TLINE*)$1)->eval();
171
                        delete $1;
172
                        delete $2;
173
                }
174
        }
175
| dualop  opb COMMA multident {
176
                char    buf[256];
177
                sprintf(buf, "%s is not a register", ((AST_IDENTIFIER *)$4)->m_id.c_str());
178
                yyerror(buf);
179
                $$ = new VLINE();
180
                delete $1;
181
                delete $2;
182
                delete $4;
183
        }
184
| singlop opb   {
185
                $$ = $1;
186
                ((TLINE*)$1)->m_imm = ((TLINE*)$2)->m_imm; ((TLINE*)$2)->m_imm = NULL;
187
                ((TLINE*)$1)->m_opb = ((TLINE*)$2)->m_opb;
188
                if ($1->isdefined()) {
189
                        $$ = ((TLINE *)$1)->eval();
190
                        delete $1;
191
                }
192
        }
193
| bareop        { $$ = $1; }
194
| LDHLOP  opcond expr COMMA REG {
195
                TLINE *tln = new TLINE;
196
                tln->m_opcode = $1;
197
                tln->m_cond   = $2;
198
                tln->m_imm    = $3;
199
                tln->m_opa    = $5;
200
 
201
                if (tln->isdefined()) {
202
                        $$ = tln->eval();
203
                        delete tln;
204
                } else
205
                        $$ = tln;
206
        }
207
| LDHLOP  opcond expr COMMA multident {
208
                char    buf[256];
209
                sprintf(buf, "%s is not a register", ((AST_IDENTIFIER *)$5)->m_id.c_str());
210
                yyerror(buf);
211
                $$ = new VLINE();
212
                delete $3;
213
                delete $5;
214
        }
215
| LDIOP          expr COMMA REG {
216
                TLINE *tln = new TLINE;
217
                tln->m_opcode = OP_LDI;
218
                tln->m_cond   = ZPARSER::ZIPC_ALWAYS;
219
                tln->m_imm    = $2;
220
                tln->m_opa    = $4;
221
 
222
                if (tln->isdefined()) {
223
                        $$ = tln->eval();
224
                        delete tln;
225
                } else
226
                        $$ = tln;
227
        }
228
| LDIOP  expr COMMA multident {
229
                char    buf[256];
230
                sprintf(buf, "%s is not a register", ((AST_IDENTIFIER *)$4)->m_id.c_str());
231
                yyerror(buf);
232
                $$ = new VLINE();
233
                delete $2;
234
                delete $4;
235
        }
236
| BRANCHOP  expr        {
237
                TLINE *tln = new TLINE;
238
                tln->m_opcode = $1;
239
                tln->m_imm    = $2;
240
 
241
                if (tln->isdefined()) {
242
                        $$ = tln->eval();
243
                        delete tln;
244
                } else
245
                        $$ = tln;
246
        }
247
| loadop opb COMMA REG {
248
                TLINE *tln = new TLINE;
249
                ((TLINE*)$2)->m_opcode = OP_LOD;
250
                ((TLINE*)$2)->m_cond   = ((TLINE*)$1)->m_cond;
251
                ((TLINE*)$2)->m_opa    = $4;
252
 
253
                delete $1;
254
 
255
                if (((TLINE *)$2)->isdefined()) {
256
                        $$ = ((TLINE *)$2)->eval();
257
                        delete $2;
258
                } else
259
                        $$ = $2;
260
        }
261
| loadop opb COMMA multident {
262
                char    buf[256];
263
                sprintf(buf, "%s is not a register", ((AST_IDENTIFIER *)$4)->m_id.c_str());
264
                yyerror(buf);
265
                $$ = new VLINE();
266
                delete $1;
267
                delete $2;
268
                delete $4;
269
        }
270
| storop REG COMMA opb {
271
                TLINE *tln = new TLINE;
272
                tln->m_opcode = OP_STO;
273
                tln->m_cond   = ((TLINE*)$1)->m_cond;
274
                tln->m_imm    = ((TLINE*)$4)->m_imm;
275
                tln->m_opb    = ((TLINE*)$4)->m_opb;
276
                tln->m_opa    = $2;
277
 
278
                delete $1;
279
 
280
                if (tln->isdefined()) {
281
                        $$ = tln->eval();
282
                        delete tln;
283
                } else
284
                        $$ = tln;
285
        }
286
| storop multident COMMA opb {
287
                char    buf[256];
288
                sprintf(buf, "%s is not a register", ((AST_IDENTIFIER *)$2)->m_id.c_str());
289
                yyerror(buf);
290
                $$ = new VLINE();
291
                delete $1;
292
                delete $2;
293
                delete $4;
294
        }
295
;
296
 
297
dualop: DUALOP  opcond {
298
        TLINE *tln = new TLINE();
299
        tln->m_opcode = $1;
300
        tln->m_cond   = $2;
301
        $$ = tln;
302
        }
303
;
304
 
305
singlop: SINGLOP opcond {
306
        TLINE *tln = new TLINE();
307
        tln->m_opcode = $1;
308
        tln->m_cond   = $2;
309
        $$ = tln;
310
        }
311
;
312
 
313
storop: STOROP opcond {
314
        TLINE *tln = new TLINE();
315
        tln->m_opcode = OP_STO;
316
        tln->m_cond   = $2;
317
        $$ = tln;
318
        }
319
;
320
 
321
loadop: LOADOP opcond {
322
        TLINE *tln = new TLINE();
323
        tln->m_opcode = OP_LOD;
324
        tln->m_cond   = $2;
325
        $$ = tln;
326
        }
327
;
328
 
329
bareop: BAREOP  opcond {
330
        TLINE *tln = new TLINE();
331
        tln->m_opcode = $1;
332
        tln->m_cond   = $2;
333
        $$ = tln;
334
        }
335
;
336
 
337
opcond:
338
        COND    { $$ = $1; }
339
|       %empty  { $$ = ZPARSER::ZIPC_ALWAYS; }
340
;
341
 
342
opb:
343
        expr    {
344
                TLINE *tln = new TLINE();
345
                tln->m_imm = $1;
346
                $$ = tln;
347
        }
348
|       expr PLUS REG {
349
                TLINE *tln = new TLINE();
350
                tln->m_imm = $1;
351
                tln->m_opb = $3;
352
                $$ = tln;
353
        }
354
|       expr '(' REG ')' {
355
                TLINE *tln = new TLINE();
356
                tln->m_imm = $1;
357
                tln->m_opb = $3;
358
                $$ = tln;
359
        }
360
|       '(' REG ')' {
361
                TLINE *tln = new TLINE();
362
                tln->m_imm = new AST_NUMBER(0);
363
                tln->m_opb = $2;
364
                $$ = tln;
365
        }
366
|       REG {
367
                TLINE *tln = new TLINE();
368
                tln->m_imm = new AST_NUMBER(0);
369
                tln->m_opb = $1;
370
                $$ = tln;
371
        }
372
;
373
 
374
expr:
375
        value                   { $$ = $1; }
376
|       MINUS value             { $$ = new AST_BRANCH('-',new AST_NUMBER(0), $2); }
377
|       expr PLUS value         { $$ = new AST_BRANCH('+',$1,$3); }
378
|       expr MINUS value        { $$ = new AST_BRANCH('-',$1,$3); }
379
|       expr TIMES value        { $$ = new AST_BRANCH('*',$1,$3); }
380
|       expr BOOLEANOR value    { $$ = new AST_BRANCH('o',$1,$3); }
381
|       expr BITWISEOR value    { $$ = new AST_BRANCH('|',$1,$3); }
382
|       expr BOOLEANAND value   { $$ = new AST_BRANCH('a',$1,$3); }
383
|       expr BITWISEAND value   { $$ = new AST_BRANCH('&',$1,$3); }
384
|       expr BITWISEXOR value   { $$ = new AST_BRANCH('^',$1,$3); }
385
|       '(' expr ')'            { $$ = $2; }
386
;
387
        /* expr OR  (|) value */
388
        /* expr XOR (^) value */
389
        /* expr AND (&) value */
390
 
391
value:
392
        INT     { $$ = new AST_NUMBER($1); }
393
| multident     { $$ = $1; }
394
| HERE          { $$ = new AST_NUMBER(global_parser_pc); }
395
;
396
 
397
multident:
398
        IDENTIFIER              { $$ = new AST_IDENTIFIER($1); delete $1; }
399
| multident DOT IDENTIFIER      { $$ = new AST_IDENTIFIER($1,$3); delete $3; }
400
;
401
%%
402
 
403
#include 
404
#include 
405
#include 
406
#include 
407
#include 
408
 
409
OBJFILE objcode;
410
 
411
void    yyerror(const char *str) {
412
        fprintf(stderr, "%s:%d: ERROR: %s\n", master_input_filename, yylineno, str);
413
        if (linecp) fprintf(stderr, "Offending line was: %s\n", linecp);
414
}
415
 
416 16 dgisselq
FILE    *run_preprocessor(const char *path = NULL, const char *zname = NULL) {
417 13 dgisselq
        int     pipefd[2];
418
        int     pid;
419
 
420
        if (pipe(pipefd)!=0) {
421
                fprintf(stderr, "PIPE FAILED!\n");
422
                perror("O/S Err:");
423
                exit(-2);
424
        } if ((zname)&&(access(zname, R_OK)!=0)) { // if !zname, then use stdin
425
                fprintf(stderr, "Cannot open %s\n", zname);
426
                perror("O/S Err:");
427
                exit(-2);
428
        }
429
 
430
 
431
        if (0 == (pid = fork())) {
432
                int     fdin, fdout;
433
 
434
                // Child process -- run the preprocessor
435
 
436 16 dgisselq
                // Close the reader: we write only
437 13 dgisselq
                close(pipefd[0]);
438
 
439 16 dgisselq
                // Adjust stdout to write to our pipe instead of anywhere else
440 13 dgisselq
                fdout = pipefd[1];
441
                close(STDOUT_FILENO);
442
                dup2(fdout, STDOUT_FILENO);
443
 
444 16 dgisselq
                char    *zpp_path;
445
                if (path != NULL) {
446
                        zpp_path = new char[strlen(path+1+strlen("/zpp"))];
447
                        strcpy(zpp_path, path);
448
                        strcat(zpp_path, "/zpp");
449
                } else zpp_path = strdup("zpp");
450
 
451 13 dgisselq
                // This call should never return
452 16 dgisselq
                //      We have to pass the name here, rather than an open file,
453
                // since zpp needs to mark for us what file it is in at all
454
                // times.
455
                if (zname)
456
                        execlp(zpp_path, "zpp", zname, NULL);
457
                else
458
                        execlp(zpp_path, "zpp", NULL);
459 13 dgisselq
 
460
                fprintf(stderr, "Could not start pre-processor!\n");
461
                perror("O/S Err:");
462
 
463
                exit(-5);
464
        }
465
 
466
        close(pipefd[1]);
467
        return fdopen(pipefd[0], "r");
468
}
469
 
470
int     main(int argc, char **argv) {
471
        int     skp = 0;
472
        const char      *zout_fname = NULL;
473 16 dgisselq
        char            *path_to_zasm = NULL;
474
        bool    preprocess_only = false;
475 13 dgisselq
        master_input_filename = NULL;
476
 
477 16 dgisselq
        // Find what directory zasm is in, so that we can find zpp when
478
        // necessary.
479
        path_to_zasm = NULL;
480
        if (strchr(argv[0], '/')) {
481
                path_to_zasm = strdup(argv[0]);
482
                char *ptr = strrchr(path_to_zasm,'/');
483
                *ptr = '\0';
484
        }
485
 
486 13 dgisselq
        skp=1;
487
        for(int argn=0; argn+skp
488
                if (argv[argn+skp][0] == '-') {
489
                        if (argv[argn+skp][1] == 'o') {
490
                                if (zout_fname)
491
                                        free((void *)zout_fname);
492
                                zout_fname = strdup(argv[argn+skp+1]);
493
                                skp++;
494 16 dgisselq
                        } else if (argv[argn+skp][1] == 'E')
495
                                preprocess_only = true;
496 13 dgisselq
 
497
                        skp++;
498
                } argv[argn] = argv[argn+skp];
499
        } argc -= skp;
500
 
501 16 dgisselq
        if (preprocess_only) {
502
                objcode.open("/dev/null");
503
        } else {
504
                if (!zout_fname)
505
                        zout_fname = "z.out";
506 13 dgisselq
 
507 16 dgisselq
                objcode.open(zout_fname);
508
        }
509 13 dgisselq
 
510
        master_input_filename = NULL;
511
 
512
        if (argc > 0) {
513
                for(int argn=0; argn
514
                        extern  FILE    *yyin;
515
                        extern  void    yyrestart(FILE *);
516
                        FILE    *tst;
517
 
518
                        create_new_context();
519
                        if (master_input_filename)
520
                                free(master_input_filename);
521
                        master_input_filename = strdup(argv[argn]);
522 16 dgisselq
                        if (preprocess_only) {
523
                                FILE    *fp = run_preprocessor(path_to_zasm, master_input_filename);
524
                                int     ch;
525
                                while(EOF != (ch = fgetc(fp)))
526
                                        fputc(ch, stdout);
527
                        } else {
528
                                yyrestart(run_preprocessor(path_to_zasm, master_input_filename));
529
                                yylineno = 1;
530
                                yyparse();
531
                        }
532 13 dgisselq
                }
533
        } else { // Run from Stdin
534
                extern  FILE    *yyin;
535
                extern  void    yyrestart(FILE *);
536
 
537
                create_new_context();
538
                master_input_filename = strdup("(stdin)");
539 16 dgisselq
                if (preprocess_only) {
540
                        int     ch;
541
                                FILE    *fp = run_preprocessor(path_to_zasm, master_input_filename);
542
                        while(EOF != (ch = fgetc(fp)))
543
                                fputc(ch, stdout);
544
                } else {
545
                        yyin = run_preprocessor(NULL);
546
                        yyrestart(yyin);
547
                        yyparse();
548
                }
549 13 dgisselq
        }
550
 
551
        if (!objcode.reduce())
552
                fprintf(stderr, "Not all symbols defined!\n");
553
}
554
 
555
 

powered by: WebSVN 2.1.0

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