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

Subversion Repositories zipcpu

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

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
| expr COMMA wordlist {
132
        if ($1->isdefined())
133
                $$ = new DLINE($1->eval());
134
        else {
135
                $$ = new VLINE();
136
                yyerror("ERROR: word list undefined\n");
137
        }}
138
;
139
 
140
fillist:
141
  expr COMMA expr {
142
                if (($1->isdefined())&&($3->isdefined())) {
143
                        int     ntimes = $1->eval(),
144
                                val = $3->eval();
145
                        LLINE   *ln = new LLINE();
146
                        for(int i=0; i
147
                                ln->addline(new DLINE(val));
148
                        $$ = ln;
149
                } else {
150
                        yyerror("Fill list undefined\n");
151
                        $$ = new VLINE();
152
                }
153
        }
154
;
155
 
156
instruction:
157
  dualop  opb COMMA REG {
158
                $$ = $1;
159
                ((TLINE*)$1)->m_imm = ((TLINE*)$2)->m_imm; ((TLINE*)$2)->m_imm = NULL;
160
                ((TLINE*)$1)->m_opb = ((TLINE*)$2)->m_opb;
161
                ((TLINE*)$1)->m_opa = $4;
162
                if ($1->isdefined()) {
163
                        $$ = ((TLINE*)$1)->eval();
164
                        delete $1;
165
                        delete $2;
166
                }
167
        }
168
| dualop  opb COMMA multident {
169
                char    buf[256];
170
                sprintf(buf, "%s is not a register", ((AST_IDENTIFIER *)$4)->m_id.c_str());
171
                yyerror(buf);
172
                $$ = new VLINE();
173
                delete $1;
174
                delete $2;
175
                delete $4;
176
        }
177
| singlop opb   {
178
                $$ = $1;
179
                ((TLINE*)$1)->m_imm = ((TLINE*)$2)->m_imm; ((TLINE*)$2)->m_imm = NULL;
180
                ((TLINE*)$1)->m_opb = ((TLINE*)$2)->m_opb;
181
                if ($1->isdefined()) {
182
                        $$ = ((TLINE *)$1)->eval();
183
                        delete $1;
184
                }
185
        }
186
| bareop        { $$ = $1; }
187
| LDHLOP  opcond expr COMMA REG {
188
                TLINE *tln = new TLINE;
189
                tln->m_opcode = $1;
190
                tln->m_cond   = $2;
191
                tln->m_imm    = $3;
192
                tln->m_opa    = $5;
193
 
194
                if (tln->isdefined()) {
195
                        $$ = tln->eval();
196
                        delete tln;
197
                } else
198
                        $$ = tln;
199
        }
200
| LDHLOP  opcond expr COMMA multident {
201
                char    buf[256];
202
                sprintf(buf, "%s is not a register", ((AST_IDENTIFIER *)$5)->m_id.c_str());
203
                yyerror(buf);
204
                $$ = new VLINE();
205
                delete $3;
206
                delete $5;
207
        }
208
| LDIOP          expr COMMA REG {
209
                TLINE *tln = new TLINE;
210
                tln->m_opcode = OP_LDI;
211
                tln->m_cond   = ZPARSER::ZIPC_ALWAYS;
212
                tln->m_imm    = $2;
213
                tln->m_opa    = $4;
214
 
215
                if (tln->isdefined()) {
216
                        $$ = tln->eval();
217
                        delete tln;
218
                } else
219
                        $$ = tln;
220
        }
221
| LDIOP  expr COMMA multident {
222
                char    buf[256];
223
                sprintf(buf, "%s is not a register", ((AST_IDENTIFIER *)$4)->m_id.c_str());
224
                yyerror(buf);
225
                $$ = new VLINE();
226
                delete $2;
227
                delete $4;
228
        }
229
| BRANCHOP  expr        {
230
                TLINE *tln = new TLINE;
231
                tln->m_opcode = $1;
232
                tln->m_imm    = $2;
233
 
234
                if (tln->isdefined()) {
235
                        $$ = tln->eval();
236
                        delete tln;
237
                } else
238
                        $$ = tln;
239
        }
240
| loadop opb COMMA REG {
241
                TLINE *tln = new TLINE;
242
                ((TLINE*)$2)->m_opcode = OP_LOD;
243
                ((TLINE*)$2)->m_cond   = ((TLINE*)$1)->m_cond;
244
                ((TLINE*)$2)->m_opa    = $4;
245
 
246
                delete $1;
247
 
248
                if (((TLINE *)$2)->isdefined()) {
249
                        $$ = ((TLINE *)$2)->eval();
250
                        delete $2;
251
                } else
252
                        $$ = $2;
253
        }
254
| loadop opb COMMA multident {
255
                char    buf[256];
256
                sprintf(buf, "%s is not a register", ((AST_IDENTIFIER *)$4)->m_id.c_str());
257
                yyerror(buf);
258
                $$ = new VLINE();
259
                delete $1;
260
                delete $2;
261
                delete $4;
262
        }
263
| storop REG COMMA opb {
264
                TLINE *tln = new TLINE;
265
                tln->m_opcode = OP_STO;
266
                tln->m_cond   = ((TLINE*)$1)->m_cond;
267
                tln->m_imm    = ((TLINE*)$4)->m_imm;
268
                tln->m_opb    = ((TLINE*)$4)->m_opb;
269
                tln->m_opa    = $2;
270
 
271
                delete $1;
272
 
273
                if (tln->isdefined()) {
274
                        $$ = tln->eval();
275
                        delete tln;
276
                } else
277
                        $$ = tln;
278
        }
279
| storop multident COMMA opb {
280
                char    buf[256];
281
                sprintf(buf, "%s is not a register", ((AST_IDENTIFIER *)$2)->m_id.c_str());
282
                yyerror(buf);
283
                $$ = new VLINE();
284
                delete $1;
285
                delete $2;
286
                delete $4;
287
        }
288
;
289
 
290
dualop: DUALOP  opcond {
291
        TLINE *tln = new TLINE();
292
        tln->m_opcode = $1;
293
        tln->m_cond   = $2;
294
        $$ = tln;
295
        }
296
;
297
 
298
singlop: SINGLOP opcond {
299
        TLINE *tln = new TLINE();
300
        tln->m_opcode = $1;
301
        tln->m_cond   = $2;
302
        $$ = tln;
303
        }
304
;
305
 
306
storop: STOROP opcond {
307
        TLINE *tln = new TLINE();
308
        tln->m_opcode = OP_STO;
309
        tln->m_cond   = $2;
310
        $$ = tln;
311
        }
312
;
313
 
314
loadop: LOADOP opcond {
315
        TLINE *tln = new TLINE();
316
        tln->m_opcode = OP_LOD;
317
        tln->m_cond   = $2;
318
        $$ = tln;
319
        }
320
;
321
 
322
bareop: BAREOP  opcond {
323
        TLINE *tln = new TLINE();
324
        tln->m_opcode = $1;
325
        tln->m_cond   = $2;
326
        $$ = tln;
327
        }
328
;
329
 
330
opcond:
331
        COND    { $$ = $1; }
332
|       %empty  { $$ = ZPARSER::ZIPC_ALWAYS; }
333
;
334
 
335
opb:
336
        expr    {
337
                TLINE *tln = new TLINE();
338
                tln->m_imm = $1;
339
                $$ = tln;
340
        }
341
|       expr PLUS REG {
342
                TLINE *tln = new TLINE();
343
                tln->m_imm = $1;
344
                tln->m_opb = $3;
345
                $$ = tln;
346
        }
347
|       expr '(' REG ')' {
348
                TLINE *tln = new TLINE();
349
                tln->m_imm = $1;
350
                tln->m_opb = $3;
351
                $$ = tln;
352
        }
353
|       '(' REG ')' {
354
                TLINE *tln = new TLINE();
355
                tln->m_imm = new AST_NUMBER(0);
356
                tln->m_opb = $2;
357
                $$ = tln;
358
        }
359
|       REG {
360
                TLINE *tln = new TLINE();
361
                tln->m_imm = new AST_NUMBER(0);
362
                tln->m_opb = $1;
363
                $$ = tln;
364
        }
365
;
366
 
367
expr:
368
        value                   { $$ = $1; }
369
|       MINUS value             { $$ = new AST_BRANCH('-',new AST_NUMBER(0), $2); }
370
|       expr PLUS value         { $$ = new AST_BRANCH('+',$1,$3); }
371
|       expr MINUS value        { $$ = new AST_BRANCH('-',$1,$3); }
372
|       expr TIMES value        { $$ = new AST_BRANCH('*',$1,$3); }
373
|       expr BOOLEANOR value    { $$ = new AST_BRANCH('o',$1,$3); }
374
|       expr BITWISEOR value    { $$ = new AST_BRANCH('|',$1,$3); }
375
|       expr BOOLEANAND value   { $$ = new AST_BRANCH('a',$1,$3); }
376
|       expr BITWISEAND value   { $$ = new AST_BRANCH('&',$1,$3); }
377
|       expr BITWISEXOR value   { $$ = new AST_BRANCH('^',$1,$3); }
378
|       '(' expr ')'            { $$ = $2; }
379
;
380
        /* expr OR  (|) value */
381
        /* expr XOR (^) value */
382
        /* expr AND (&) value */
383
 
384
value:
385
        INT     { $$ = new AST_NUMBER($1); }
386
| multident     { $$ = $1; }
387
| HERE          { $$ = new AST_NUMBER(global_parser_pc); }
388
;
389
 
390
multident:
391
        IDENTIFIER              { $$ = new AST_IDENTIFIER($1); delete $1; }
392
| multident DOT IDENTIFIER      { $$ = new AST_IDENTIFIER($1,$3); delete $3; }
393
;
394
%%
395
 
396
#include 
397
#include 
398
#include 
399
#include 
400
#include 
401
 
402
OBJFILE objcode;
403
 
404
void    yyerror(const char *str) {
405
        fprintf(stderr, "%s:%d: ERROR: %s\n", master_input_filename, yylineno, str);
406
        if (linecp) fprintf(stderr, "Offending line was: %s\n", linecp);
407
}
408
 
409
FILE    *run_preprocessor(const char *zname = NULL) {
410
        int     pipefd[2];
411
        int     pid;
412
 
413
        if (pipe(pipefd)!=0) {
414
                fprintf(stderr, "PIPE FAILED!\n");
415
                perror("O/S Err:");
416
                exit(-2);
417
        } if ((zname)&&(access(zname, R_OK)!=0)) { // if !zname, then use stdin
418
                fprintf(stderr, "Cannot open %s\n", zname);
419
                perror("O/S Err:");
420
                exit(-2);
421
        }
422
 
423
 
424
        if (0 == (pid = fork())) {
425
                int     fdin, fdout;
426
 
427
                // Child process -- run the preprocessor
428
                if (zname) {
429
                        fdin = open(zname, O_RDONLY);
430
                        close(STDIN_FILENO);
431
                        dup2(fdin, STDIN_FILENO);
432
                } // else use stdin, already set up
433
 
434
                close(pipefd[0]);
435
 
436
                fdout = pipefd[1];
437
                close(STDOUT_FILENO);
438
                dup2(fdout, STDOUT_FILENO);
439
 
440
                // This call should never return
441
                execlp("./zpp", "zpp", NULL);
442
 
443
                fprintf(stderr, "Could not start pre-processor!\n");
444
                perror("O/S Err:");
445
 
446
                exit(-5);
447
        }
448
 
449
        close(pipefd[1]);
450
        return fdopen(pipefd[0], "r");
451
}
452
 
453
int     main(int argc, char **argv) {
454
        int     skp = 0;
455
        const char      *zout_fname = NULL;
456
        master_input_filename = NULL;
457
 
458
        skp=1;
459
        for(int argn=0; argn+skp
460
                if (argv[argn+skp][0] == '-') {
461
                        if (argv[argn+skp][1] == 'o') {
462
                                if (zout_fname)
463
                                        free((void *)zout_fname);
464
                                zout_fname = strdup(argv[argn+skp+1]);
465
                                skp++;
466
                        }
467
 
468
                        skp++;
469
                } argv[argn] = argv[argn+skp];
470
        } argc -= skp;
471
 
472
        if (!zout_fname)
473
                zout_fname = "z.out";
474
 
475
        objcode.open(zout_fname);
476
 
477
        master_input_filename = NULL;
478
 
479
        if (argc > 0) {
480
                for(int argn=0; argn
481
                        extern  FILE    *yyin;
482
                        extern  void    yyrestart(FILE *);
483
                        FILE    *tst;
484
 
485
                        create_new_context();
486
                        if (master_input_filename)
487
                                free(master_input_filename);
488
                        master_input_filename = strdup(argv[argn]);
489
                        yyrestart(run_preprocessor(master_input_filename));
490
                        yylineno = 1;
491
                        yyparse();
492
                }
493
        } else { // Run from Stdin
494
                extern  FILE    *yyin;
495
                extern  void    yyrestart(FILE *);
496
 
497
                create_new_context();
498
                master_input_filename = strdup("(stdin)");
499
                yyin = run_preprocessor(NULL);
500
                yyrestart(yyin);
501
                yyparse();
502
        }
503
 
504
        if (!objcode.reduce())
505
                fprintf(stderr, "Not all symbols defined!\n");
506
}
507
 
508
 

powered by: WebSVN 2.1.0

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