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

Subversion Repositories tinyvliw8

[/] [tinyvliw8/] [trunk/] [tools/] [asm/] [src/] [main.c] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 steckol
/**
2
 * \file   main.c
3
 * \author Oliver Stecklina <stecklina@ihp-microelectronics.com>
4 6 steckol
 * \date   20.10.2013
5
 *
6
 * \brief  IHPvliw8 assembler main program file.
7 5 steckol
 *
8 6 steckol
 * <p>
9
 *    Copyright (C) 2015 IHP GmbH, Frankfurt (Oder), Germany
10
 *
11
 * This code is free software. It is licensed under the EUPL, Version 1.1
12
 * or - as soon they will be approved by the European Commission - subsequent
13
 * versions of the EUPL (the "License").
14
 * You may redistribute this code and/or modify it under the terms of this
15
 * License.
16
 * You may not use this work except in compliance with the License.
17
 * You may obtain a copy of the License at:
18
 *
19
 * http://joinup.ec.europa.eu/software/page/eupl/licence-eupl
20
 *
21
 * Unless required by applicable law or agreed to in writing, software
22
 * distributed under the License is distributed on an "AS IS" basis,
23
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
 * See the License for the specific language governing permissions and
25
 * limitations under the License.
26
 * </p>
27 5 steckol
 */
28
 
29
#include <sys/types.h>
30
#include <sys/stat.h>
31
#include <fcntl.h>
32
#include <unistd.h>
33
#include <stdlib.h>
34
#include <stdio.h>
35
#include <string.h>
36
#include <ctype.h>
37
#include <errno.h>
38
 
39
#include "config.h"
40
 
41
#define _VARNAME_LEN   8
42
#define _LABEL_LEN     8
43
 
44
typedef struct _label_s {
45
        char             name[_LABEL_LEN];
46
        unsigned short   addr;
47
 
48
        struct _label_s *next;
49
} _label_t;
50
 
51
typedef struct _var_s {
52
        char           name[_VARNAME_LEN];
53
        unsigned char  value;
54
        unsigned char  addr;
55
 
56
        struct _var_s *next;
57
} _var_t;
58
 
59
typedef enum _section_e {
60
        _section_data = 0,
61
        _section_code
62
} _section_t;
63
 
64
static char         *_infile     = NULL;
65
static char         *_outfile    = "out";
66
 
67
static _var_t       *_var   = NULL;
68
static _label_t     *_label = NULL;
69
 
70
static unsigned short _code_addr = 0x0000;
71
 
72
static int _parse_args(int argc, char *argv[])
73
{
74
        int err, i;
75
 
76
        err = 0;
77
        for (i = 1; 0 == err && i < argc; i++) {
78
                if ('-' != *argv[i]) {
79
                        if ((i + 1) == argc) {
80
                                _infile = argv[i];
81
                                break;
82
                        }
83
 
84
                        fprintf(stderr, "\tERROR! bad option <%s>\n", argv[i]);
85
                        err = -EINVAL;
86
 
87
                        break;
88
                }
89
 
90
                switch (*(argv[i] + 1)) {
91
                case 'o':
92
                        if ((i + 1) < argc) {
93
                                i++;
94
                                _outfile = argv[i];
95
 
96
                                break;
97
                        }
98
 
99
                        fprintf(stderr, "\tERROR! option <%s> requires an argument\n",
100
                                argv[i]);
101
                        err = -EINVAL;
102
 
103
                        break;
104
                case 'h':
105
                        printf("%s [option] <input>\n", argv[0]);
106
                        printf("\t-o <file>    output filename (default: out.bin)\n");
107
                        printf("\t-h           useful help\n");
108
 
109
                        exit(0);
110
                }
111
        }
112
 
113
        if (0 == err && NULL == _infile) {
114
                fprintf(stderr, "\tERROR! no input file given\n");
115
                err = -EINVAL;
116
        }
117
 
118
        return err;
119
}
120
 
121
static int _shrink_line(char *line, unsigned int size)
122
{
123
        unsigned int s, i;
124
        int len;
125
 
126
        len = 0;
127
        s = 0;
128
 
129
        for (i = 0; i < size; i++) {
130
                int out;
131
 
132
                out = 0;
133
 
134
                switch (line[i]) {
135
                case '\0':
136
                        out = 1;
137
                        break;
138
                case '/':                 /* comment */
139
                        out = 1;
140
 
141
                        if (0 == len)
142
                                break;
143
 
144
                        line[len] = '\n';
145
                        len++;
146
                        line[len] = '\0';
147
 
148
                        break;
149
                case ';':                 /* line finished */
150
                        line[len] = '\n';
151
                        len++;
152
 
153
                        line[len] = '\0';
154
 
155
                        out = 1;
156
                        break;
157
                case '|':                /* instruction delimiter - jmp #0x08 | ld R0, #0x01 */
158
                case ',':                /* operand delimiter     - add r1, r3 */
159
                        switch (s) {
160
                        case 1:              /* leading blank, kick it */
161
                                line[len - 1] = line[i];
162
                                break;
163
                        case 0:
164
                                line[len] = line[i];
165
                                len++;
166
 
167
                                break;
168
                        }
169
 
170
                        s = 2;
171
 
172
                        break;
173
                case ' ':
174
                case '\t':
175
                        if (0 < i) {
176
                                if (0 == s) {
177
                                        line[len] = ' ';
178
                                        len++;
179
                                }
180
                        }
181
 
182
                        if (0 == s)
183
                                s = 1;
184
 
185
                        break;
186
                case '\r':
187
                case '\n':
188
                        break;
189
                default:
190
                        if (len != (int) i)
191
                                line[len] = line[i];
192
 
193
                        len++;
194
                        s = 0;
195
                }
196
 
197
                if (0 != out)
198
                        break;
199
        }
200
 
201
        return len;
202
}
203
 
204
typedef struct _token_s {
205
        struct {
206
                unsigned char num;
207
                char **data;
208
        } inst[2];
209
} _token_t;
210
 
211
static _token_t *_tokenize(char *line)
212
{
213
        _token_t *t;
214
 
215
        t = (_token_t *) malloc(sizeof(_token_t));
216
        if (t) {
217
                unsigned char inst;
218
 
219
                memset((char *) t, 0x00, sizeof(_token_t));
220
 
221
                inst = 0;
222
                t->inst[inst].num = 1;
223
 
224
                t->inst[inst].data = (char **) malloc(sizeof(char*) * (t->inst[inst].num + 1));
225
                if (NULL != t->inst[inst].data) {
226
                        unsigned char state;
227
                        int i;
228
 
229
                        t->inst[inst].data[0] = line;
230
                        t->inst[inst].data[1] = NULL;
231
 
232
                        i = 0;
233
                        state = 0;
234
                        while ('\0' != line[i]) {
235
                                unsigned char add;
236
 
237
                                add = 0;
238
                                switch (line[i]) {
239
                                case ' ':
240
                                        if (0 == state) {
241
                                                add = 1;
242
                                                state = 1;
243
                                }
244
 
245
                                        break;
246
                                case ',':
247
                                        add = 1;
248
                                        break;
249
                                case '|':
250
                                        inst++;
251
 
252
                                        add = 1;
253
                                        state = 0;
254
 
255
                                        break;
256
                                }
257
 
258
                                if (0 != add && '\0' != line[i + 1]) {
259
                                        line[i] = '\0';
260
                                        t->inst[inst].data = (char **) realloc(t->inst[inst].data, sizeof(char*) * (t->inst[inst].num + 2));
261
                                        if (NULL != t->inst[inst].data) {
262
                                                i++;
263
 
264
                                                t->inst[inst].data[t->inst[inst].num] = &line[i];
265
                                                t->inst[inst].data[t->inst[inst].num + 1] = NULL;
266
 
267
                                                t->inst[inst].num++;
268
                                        } else {
269
                                                /* error, no more memory, cleaning up */
270
                                                if (0 < inst)
271
                                                        free(t->inst[0].data);
272
 
273
                                                free(t);
274
                                                t = NULL;
275
 
276
                                                break;
277
                                        }
278
                                }
279
 
280
                                i++;
281
                        }
282
                }
283
        }
284
 
285
        return t;
286
}
287
 
288
static int _add_data_item(char *line)
289
{
290
        _token_t *tok;
291
        int err;
292
 
293
        tok = _tokenize(line);
294
        if (NULL != tok) {
295
                if (NULL != tok->inst[0].data[0] && NULL != tok->inst[0].data[1]) {
296
                        int namelen;
297
                        unsigned char addr;
298
                        long value;
299
 
300
                        namelen = strlen(tok->inst[0].data[0]);
301
                        if (_VARNAME_LEN < namelen) {
302
                                err = -ENAMETOOLONG;
303
                                goto out;
304
                        }
305
 
306
                        addr = 0x00;
307
                        if (NULL != _var) {
308
                                if (CONFIG_DATA_ADDR_MAX == _var->addr) {
309
                                        err = -ENOSPC;
310
                                        goto out;
311
                                }
312
 
313
                                addr = _var->addr + 1;
314
                        }
315
 
316
                        value = strtol(tok->inst[0].data[1], NULL, 0);
317
                        if (0 <= value && 256 > value) {
318
                                _var_t *nv;
319
 
320
                                nv = (_var_t *) malloc(sizeof(_var_t));
321
                                if (NULL != nv) {
322
                                        memset((char *) nv, 0, sizeof(_var_t));
323
 
324
                                        memcpy(&nv->name[0], tok->inst[0].data[0], namelen);
325
 
326
                                        nv->addr = addr;
327
                                        nv->value = 0xff & value;
328
 
329
                                        nv->next = _var;
330
                                        _var = nv;
331
 
332
                                        err = 0;
333
                                }
334
                        } else
335
                                err = -ERANGE;
336
                } else
337
                        err = -EINVAL;
338
 
339
out:
340
                if (NULL != tok->inst[0].data)
341
                        free(tok->inst[0].data);
342
                if (NULL != tok->inst[1].data)
343
                        free(tok->inst[1].data);
344
 
345
                free(tok);
346
        } else
347
                err = -ENOMEM;
348
 
349
        return err;
350
}
351
 
352
typedef enum _opcode_e {
353
        _opcode_ld = 0,
354
        _opcode_ldi,
355
        _opcode_st,
356
        _opcode_sti,
357
        _opcode_jmp,
358
        _opcode_jc,
359
        _opcode_jz,
360
        _opcode_jnz,
361
        _opcode_add,
362
        _opcode_addi,
363
        _opcode_shl,
364
        _opcode_shli,
365
        _opcode_shr,
366
        _opcode_shri,
367
        _opcode_or,
368
        _opcode_nor,
369
        _opcode_and,
370
        _opcode_nand,
371
        _opcode_xor,
372
        _opcode_xnor,
373
        _opcode_unknown
374
} _opcode_t;
375
 
376
static _opcode_t _opcode_get(char *token)
377
{
378
        unsigned int i;
379
 
380
        for (i = 0; '\0' != token[i]; i++)
381
                token[i] = tolower(token[i]);
382
 
383
        if (0 == strcmp("ldi", token))
384
                return _opcode_ldi;
385
        if (0 == strcmp("ld", token))
386
                return _opcode_ld;
387
        if (0 == strcmp("sti", token))
388
                return _opcode_sti;
389
        if (0 == strcmp("st", token))
390
                return _opcode_st;
391
 
392
        if (0 == strcmp("jmp", token))
393
                return _opcode_jmp;
394
        if (0 == strcmp("jc", token))
395
                return _opcode_jc;
396
        if (0 == strcmp("jz", token))
397
                return _opcode_jz;
398
        if (0 == strcmp("jnz", token))
399
                return _opcode_jnz;
400
 
401
        if (0 == strcmp("addi", token))
402
                return _opcode_addi;
403
        if (0 == strcmp("add", token))
404
                return _opcode_add;
405
        if (0 == strcmp("shli", token))
406
                return _opcode_shli;
407
        if (0 == strcmp("shl", token))
408
                return _opcode_shl;
409
        if (0 == strcmp("shri", token))
410
                return _opcode_shri;
411
        if (0 == strcmp("shr", token))
412
                return _opcode_shr;
413
        if (0 == strcmp("nor", token))
414
                return _opcode_nor;
415
        if (0 == strcmp("or", token))
416
                return _opcode_or;
417
        if (0 == strcmp("nand", token))
418
                return _opcode_nand;
419
        if (0 == strcmp("and", token))
420
                return _opcode_and;
421
        if (0 == strcmp("xnor", token))
422
                return _opcode_xnor;
423
        if (0 == strcmp("xor", token))
424
                return _opcode_xor;
425
 
426
        return _opcode_unknown;
427
}
428
 
429
static unsigned char _get_reg(char *token)
430
{
431
        if ('r' == tolower(*token))
432
                return (*(token + 1) - '0');
433
 
434
        return 0xff;
435
}
436
 
437
typedef enum _ldst_vtype_e {
438
        _ldst_vtype_addr = 0,
439
        _ldst_vtype_reg
440
} _ldst_vtype_t;
441
 
442
typedef struct _ldst_op_s {
443
        _opcode_t       opcode;
444
        unsigned char   reg;
445
 
446
        _ldst_vtype_t   vtype;
447
        union {
448
                unsigned char reg;
449
                unsigned char addr;
450
                unsigned char raw;
451
        } vt;
452
} _ldst_op_t;
453
 
454
typedef struct _alu_op_s {
455
        _opcode_t       opcode;
456
        unsigned char   reg;
457
 
458
        struct {
459
                unsigned char prefix;
460
                unsigned char type;
461
                union {
462
                        unsigned char reg;
463
                        unsigned char value;
464
                } data;
465
        } op[2];
466
} _alu_op_t;
467
 
468
typedef struct _jmp_op_s {
469
        _opcode_t       opcode;
470
        unsigned short  addr;
471
 
472
        _label_t       *label;
473
} _jmp_op_t;
474
 
475
typedef enum _op_type_e {
476
        _op_type_ldst = 0,
477
        _op_type_alu,
478
        _op_type_jmp
479
} _op_type_t;
480
 
481
typedef struct _op_s {
482
        unsigned short addr;
483
 
484
        _op_type_t     opt[2];
485
        union {
486
                _ldst_op_t *ldst;
487
                _alu_op_t  *alu;
488
                _jmp_op_t  *jmp;
489
                void       *raw;
490
        } op[2];
491
 
492
        struct _op_s  *next;
493
} _op_t;
494
 
495
static _op_t *_op = NULL;
496
 
497
static _label_t *_label_get_by_name(const char *name)
498
{
499
        _label_t *v;
500
 
501
        for (v = _label; v != NULL; v = v->next) {
502
                if (0 == strcmp(v->name, name))
503
                        break;
504
        }
505
 
506
        return v;
507
}
508
 
509
static int _add_label(char *label, unsigned short addr)
510
{
511
        int err;
512
 
513
        err = strlen(label);
514
        if (_LABEL_LEN > err) {
515
                _label_t *l;
516
 
517
                l = _label_get_by_name(label);
518
                if (NULL != l) {
519
                        if (0xffff != l->addr) {
520
                                fprintf(stderr, "label %s defined twice\n", label);
521
                                return -EBUSY;
522
                        }
523
 
524
                        l->addr = addr;
525
                        return 0;
526
                }
527
 
528
                l = (_label_t *) malloc(sizeof(_label_t));
529
                if (NULL != l) {
530
                        memset((char *) l, 0x00, sizeof(_label_t));
531
 
532
                        memcpy(&l->name[0], label, err);
533
                        l->addr = addr;
534
 
535
                        l->next = _label;
536
                        _label = l;
537
 
538
                        err = 0;
539
                } else
540
                        err = -ENOMEM;
541
        } else
542
                err = -ENAMETOOLONG;
543
 
544
        return err;
545
}
546
 
547
static _var_t *_get_var_by_name(const char *name)
548
{
549
        _var_t *v;
550
 
551
        for (v = _var; v != NULL; v = v->next) {
552
                if (0 == strcmp(v->name, name))
553
                        break;
554
        }
555
 
556
        return v;
557
}
558
 
559
static _jmp_op_t *_jmp_gen_item(_opcode_t opcode, char *value)
560
{
561
        _jmp_op_t *op;
562
        int err;
563
 
564
        if (NULL == value)
565
                return NULL;
566
 
567
        op = (_jmp_op_t *) malloc(sizeof(_jmp_op_t));
568
        if (NULL == op)
569
                return NULL;
570
 
571
        memset((char *) op, 0x00, sizeof(_jmp_op_t));
572
 
573
        op->opcode = opcode;
574
        err = 0;
575
 
576
        switch (*value) {
577
        _label_t *label;
578
        long v;
579
 
580
        case '$':
581
                label = _label_get_by_name(&value[1]);
582
                if (NULL != label) {
583
                        op->addr = label->addr;
584
                        op->label = label;
585
                } else {
586
                        op->addr = 0xffff;
587
 
588
                        err = _add_label(&value[1], 0xffff);
589
                        if (0 == err) {
590
                                op->label = _label_get_by_name(&value[1]);
591
                                if (NULL == op->label) {
592
                                        fprintf(stderr, "error while adding virtual label <%s>\n",
593
                                                &value[1]);
594
                                }
595
                        } else
596
                                fprintf(stderr, "add virtual label <%s> failed, error %d\n",
597
                                        &value[1], err);
598
                }
599
 
600
                break;
601
        case '-':
602
                v = strtol(value + 1, NULL, 0);
603
                if (0 > v || CONFIG_CODE_SIZE <= v) {
604
                        err = -ERANGE;
605
                        break;
606
                }
607
 
608
                if (v > _code_addr) {
609
                        err = -EINVAL;
610
                        break;
611
                }
612
 
613
                op->addr = _code_addr - v;
614
                break;
615
        case '+':
616
                v = strtol(value + 1, NULL, 0);
617
                if (0 > v || CONFIG_CODE_SIZE <= v) {
618
                        err = -ERANGE;
619
                        break;
620
                }
621
 
622
                if (CONFIG_CODE_SIZE <= (v + _code_addr)) {
623
                        err = -EINVAL;
624
                        break;
625
                }
626
 
627
                op->addr = _code_addr + v;
628
                break;
629
        case '#':
630
                v = strtol(value + 1, NULL, 0);
631
                if (0 <= v && CONFIG_CODE_SIZE > v) {
632
                        op->addr = v;
633
                } else
634
                        err = -ERANGE;
635
 
636
                break;
637
        default:
638
                fprintf(stderr, "syntax error at label\n");
639
                err = -EINVAL;
640
        }
641
 
642
        if (0 != err) {
643
                free(op);
644
                op = NULL;
645
        }
646
 
647
        return op;
648
}
649
 
650
static _ldst_op_t *_ldst_gen_item(_opcode_t opcode, char *reg_str, char *value)
651
{
652
        unsigned char reg;
653
        _ldst_op_t *op;
654
        int err;
655
 
656
        if (NULL == reg_str || NULL == value)
657
                return NULL;
658
 
659
        reg = _get_reg(reg_str);
660
        if (CONFIG_MAX_REG_NUM < reg)
661
                return NULL;
662
 
663
        op = (_ldst_op_t *) malloc(sizeof(_ldst_op_t));
664
        if (NULL == op)
665
                return NULL;
666
 
667
        memset((char *) op, 0x00, sizeof(_ldst_op_t));
668
 
669
        op->opcode = opcode;
670
        op->reg = reg;
671
 
672
        err = 0;
673
        switch (*value) {
674
        _var_t *var;
675
        long v;
676
 
677
        case '@':
678
                op->vtype = _ldst_vtype_reg;
679
 
680
                reg = _get_reg(&value[1]);
681
                if (CONFIG_MAX_REG_NUM >= reg) {
682
                        op->vt.reg = reg;
683
                } else
684
                        err = -EINVAL;
685
 
686
                break;
687
        case '%':
688
                op->vtype = _ldst_vtype_addr;
689
 
690
                var = _get_var_by_name(&value[1]);
691
                if (var) {
692
                        op->vt.addr = var->addr;
693
                } else {
694
                        fprintf(stderr, "undefined variable %s\n", &value[1]);
695
                        err = -EINVAL;
696
                }
697
 
698
                break;
699
        case '#':
700
                op->vtype = _ldst_vtype_addr;
701
 
702
                v = strtol(value + 1, NULL, 0);
703
                if (0 <= v && 0xff >= v) {
704
                        op->vt.addr = 0xff & v;
705
                } else
706
                        err = -ERANGE;
707
 
708
                break;
709
        default:
710
                err = -EINVAL;
711
        }
712
 
713
        if (0 != err) {
714
                free(op);
715
                op = NULL;
716
        }
717
 
718
        return op;
719
}
720
 
721
static _alu_op_t *_alu_gen_item(_opcode_t opcode, char *reg_str, char *op1, char *op2)
722
{
723
        _alu_op_t *op;
724
        unsigned char i, reg;
725
        char *operand[] = {op1, op2};
726
        int err;
727
 
728
        if (NULL == reg_str || NULL == op1) {
729
                fprintf(stderr, "parse error \n");
730
                return NULL;
731
        }
732
 
733
        reg = _get_reg(reg_str);
734
        if (CONFIG_MAX_REG_NUM < reg) {
735
                fprintf(stderr, "invalid destination register %s\n", reg_str);
736
                return NULL;
737
        }
738
 
739
        op = (_alu_op_t *) malloc(sizeof(_alu_op_t));
740
        if (NULL == op)
741
                return NULL;
742
 
743
        memset((char *) op, 0x00, sizeof(_alu_op_t));
744
 
745
        op->opcode = opcode;
746
        op->reg = reg;
747
 
748
        for (i = 0; i< 2; i++) {
749
                if (NULL == operand[i]) {
750
                        if (0 == i) {
751
                                err = -EINVAL;
752
                                break;
753
                        }
754
 
755
                        /* copy operand 0 to operand 1 */
756
                        memcpy((char *) &op->op[1], (char *) &op->op[0], sizeof(op->op[0]));
757
 
758
                        /* set operand 0 to destination register */
759
                        op->op[0].prefix = 0;
760
                        op->op[0].type = 0;
761
 
762
                        op->op[0].data.reg = op->reg;
763
 
764
                        break;
765
                }
766
 
767
                switch (*operand[i]) {
768
                long v;
769
 
770
                case '-':     /* two's complement */
771
                case '~':     /* invert */
772
                        op->op[i].prefix = 1;
773
                        op->op[i].type = 0;
774
 
775
                        reg = _get_reg(operand[i] + 1);
776
                        if (CONFIG_MAX_REG_NUM >= reg) {
777
                                op->op[i].data.reg = reg;
778
                        } else
779
                                err = -EINVAL;
780
 
781
                        break;
782
                case '#':     /* constant value */
783
                        op->op[i].prefix = 0;
784
                        op->op[i].type = 1;
785
 
786
                        v = strtol(operand[i] + 1, NULL, 0);
787
                        if (0 <= v && 0xff >= v) {
788
                                op->op[i].data.value = 0xff & v;
789
                        } else
790
                                err = -ERANGE;
791
 
792
                        break;
793
                default:      /* register */
794
                        op->op[i].prefix = 0;
795
                        op->op[i].type = 0;
796
 
797
                        reg = _get_reg(operand[i]);
798
                        if (CONFIG_MAX_REG_NUM >= reg) {
799
                                op->op[i].data.reg = reg;
800
                        } else
801
                                err = -EINVAL;
802
 
803
                        break;
804
                }
805
        }
806
 
807
        if (0 != err) {
808
                fprintf(stderr, "error %d at 0x%02x %s %s %s failed\n",
809
                        err, opcode, reg_str, op1, op2);
810
 
811
                free(op);
812
                op = NULL;
813
        }
814
 
815
        return op;
816
}
817
 
818
static int _add_code_item(char *line)
819
{
820
        _token_t *tok;
821
        int err;
822
 
823
        for (err = 0; err < (int) strlen(line); err++)
824
                if ('\n' == line[err] || '\r' == line[err]) {
825
                        line[err] = '\0';
826
                        break;
827
                }
828
 
829
        if (0 < err && ':' == line[err - 1]) {
830
                line[err - 1] = '\0';
831
 
832
                return _add_label(line, (NULL == _op) ? 0x00 : _op->addr + 1);
833
        }
834
 
835
        tok = _tokenize(line);
836
        if (NULL != tok) {
837
                unsigned char inst;
838
                _opcode_t opcode;
839
                unsigned short addr;
840
                _op_t *op;
841
 
842
                if (NULL == tok->inst[0].data[0]) {
843
                        err = -EINVAL;
844
                        goto out;
845
                }
846
 
847
                if (CONFIG_CODE_ADDR_MAX < _code_addr) {
848
                        err = -ENOSPC;
849
                        goto out;
850
                }
851
 
852
                addr = _code_addr;
853
                _code_addr += 1;
854
 
855
                op = malloc(sizeof(_op_t));
856
                if (NULL == op) {
857
                        err = -ENOMEM;
858
                        goto out;
859
                }
860
 
861
                err = 0;
862
                for (inst = 0; 0 == err && inst < 2; inst++) {
863
                        if (0 == tok->inst[inst].num)
864
                                continue;
865
 
866
                        opcode = _opcode_get(tok->inst[inst].data[0]);
867
 
868
                        switch (opcode) {
869
                        case _opcode_jmp:
870
                        case _opcode_jz:
871
                        case _opcode_jc:
872
                        case _opcode_jnz:
873
                                op->op[inst].jmp = _jmp_gen_item(opcode, tok->inst[inst].data[1]);
874
                                op->opt[inst] = _op_type_jmp;
875
 
876
                                break;
877
                        case _opcode_ld:
878
                        case _opcode_ldi:
879
                        case _opcode_st:
880
                        case _opcode_sti:
881
                                op->op[inst].ldst = _ldst_gen_item(opcode, tok->inst[inst].data[1], tok->inst[inst].data[2]);
882
                                op->opt[inst] = _op_type_ldst;
883
 
884
                                break;
885
                        case _opcode_add:
886
                        case _opcode_addi:
887
                        case _opcode_shl:
888
                        case _opcode_shli:
889
                        case _opcode_shr:
890
                        case _opcode_shri:
891
                        case _opcode_or:
892
                        case _opcode_nor:
893
                        case _opcode_and:
894
                        case _opcode_nand:
895
                        case _opcode_xor:
896
                        case _opcode_xnor:
897
                                if (4 == tok->inst[inst].num)
898
                                        op->op[inst].alu = _alu_gen_item(opcode, tok->inst[inst].data[1], tok->inst[inst].data[2], tok->inst[inst].data[3]);
899
                                else
900
                                        op->op[inst].alu = _alu_gen_item(opcode, tok->inst[inst].data[1], tok->inst[inst].data[2], NULL);
901
 
902
                                op->opt[inst] = _op_type_alu;
903
 
904
                                break;
905
                        default:
906
                                op->op[inst].raw = NULL;
907
                                err = -EINVAL;
908
                        }
909
 
910
                        if (NULL == op->op[inst].raw) {
911
                                err = -EINVAL;
912
                                break;
913
                        }
914
 
915
                        op->addr = addr;
916
                }
917
 
918
                if (NULL == op->op[1].raw) {
919
                        op->op[1].raw = op->op[0].raw;
920
                        op->opt[1] = op->opt[0];
921
                }
922
 
923
                if (0 == err) {
924
                        op->next = _op;
925
                        _op = op;
926
                } else
927
                        free(op);
928
 
929
out:
930
                if (NULL != tok->inst[0].data)
931
                        free(tok->inst[0].data);
932
                if (NULL != tok->inst[1].data)
933
                        free(tok->inst[1].data);
934
 
935
                free(tok);
936
        } else
937
                err = -ENOMEM;
938
 
939
        return err;
940
}
941
 
942
static int _parse_line(char *line, _section_t *sec_ptr)
943
{
944
        int err;
945
 
946
        if ('.' == *line) {
947
                /* section definition */
948
                if ('d' == *(line + 1)) {
949
                        *sec_ptr = _section_data;
950
                        return 0;
951
                }
952
 
953
                if ('c' == *(line + 1)) {
954
                        *sec_ptr = _section_code;
955
                        return 0;
956
                }
957
 
958
                if ('i' == *(line + 1)) {
959
                        unsigned char inum;
960
 
961
                        inum = *(line + 4) - '0';
962
                        if (CONFIG_IRQ_NUM >= inum) {
963
                                _code_addr = CONFIG_IRQ_START + inum;
964
                                return 0;
965
                        } else
966
                                return -EINVAL;
967
                }
968
 
969
                return -EINVAL;
970
        }
971
 
972
        err = 0;
973
        switch (*sec_ptr) {
974
        case _section_data:
975
                err = _add_data_item(line);
976
                break;
977
        case _section_code:
978
                err = _add_code_item(line);
979
                break;
980
        }
981
 
982
        return err;
983
}
984
 
985
static int _jmp_dump(unsigned char *dst, _jmp_op_t *op)
986
{
987
        int err;
988
 
989
        err = 0;
990
 
991
        switch (op->opcode) {
992
        case _opcode_jmp:
993
                dst[0] = 0xe0;
994
                break;
995
        case _opcode_jz:
996
                dst[0] = 0xe8;
997
                break;
998
        case _opcode_jc:
999
                dst[0] = 0xf0;
1000
                break;
1001
        case _opcode_jnz:
1002
                dst[0] = 0xf8;
1003
                break;
1004
        default:
1005
                err = -EINVAL;
1006
        }
1007
 
1008
        if (0xffff == op->addr) {
1009
                if (NULL == op->label) {
1010
                        fprintf(stderr, "error, unresolved label at %p\n", op);
1011
                        return -ENOENT;
1012
                }
1013
 
1014
                op->addr = op->label->addr;
1015
        }
1016
 
1017
        dst[0] |= (op->addr >> 8) & 0x07;
1018
        dst[1] = op->addr & 0x00ff;
1019
 
1020
        return err;
1021
}
1022
 
1023
static int _ldst_dump(unsigned char *dst, _ldst_op_t *op)
1024
{
1025
        int err;
1026
 
1027
        err = 0;
1028
        switch (op->opcode) {
1029
        case _opcode_ld:
1030
                dst[0] = 0x00;
1031
                break;
1032
        case _opcode_ldi:
1033
                dst[0] = 0x10;
1034
                break;
1035
        case _opcode_st:
1036
                dst[0] = 0x20;
1037
                break;
1038
        case _opcode_sti:
1039
                dst[0] = 0x30;
1040
                break;
1041
        default:
1042
                err = -EINVAL;
1043
        }
1044
 
1045
        if (_ldst_vtype_reg == op->vtype)
1046
                dst[0] |= 0x08;
1047
 
1048
        dst[0] |= op->reg;
1049
        dst[1] = op->vt.raw;
1050
 
1051
        return err;
1052
}
1053
 
1054
static void _alu_dump_operand(unsigned char *dst, _alu_op_t *op)
1055
{
1056
        if (1 == op->op[1].type) {
1057
                dst[1] = op->op[1].data.value;
1058
                dst[0] |= 0x08;
1059
 
1060
                return;
1061
        }
1062
 
1063
        dst[1] = ((0 != op->op[0].prefix) ? 0x08 : 0x00) | (op->op[0].data.reg & 0x07);
1064
        dst[1] <<= 4;
1065
        dst[1] |= ((0 != op->op[1].prefix) ? 0x08 : 0x00) | (op->op[1].data.reg & 0x07);
1066
}
1067
 
1068
static int _alu_dump(unsigned char *dst, _alu_op_t *op)
1069
{
1070
        int err;
1071
 
1072
        dst[0] = op->reg & 0x07;
1073
        dst[1] = 0x00;
1074
 
1075
        err = 0;
1076
        switch (op->opcode) {
1077
        case _opcode_addi:
1078
                dst[0] |= 0x10;
1079
                /* no break */
1080
        case _opcode_add:
1081
                dst[0] |= 0x02 << 5;
1082
                _alu_dump_operand(dst, op);
1083
 
1084
                break;
1085
        case _opcode_shli:
1086
        case _opcode_shri:
1087
                dst[0] |= 0x08;
1088
                /* no break */
1089
        case _opcode_shr:
1090
                dst[0] |= 0x10;
1091
                /* no break */
1092
        case _opcode_shl:
1093
                dst[0] |= 0x03 << 5;
1094
                dst[1] = op->op[0].data.reg & 0x07;
1095
 
1096
                break;
1097
        case _opcode_nor:
1098
                dst[0] |= 0x10;
1099
                /* no break */
1100
        case _opcode_or:
1101
                dst[0] |= 0x05 << 5;
1102
                _alu_dump_operand(dst, op);
1103
 
1104
                break;
1105
        case _opcode_nand:
1106
                dst[0] |= 0x10;
1107
                /* no break */
1108
        case _opcode_and:
1109
                dst[0] |= 0x04 << 5;
1110
                _alu_dump_operand(dst, op);
1111
 
1112
                break;
1113
        case _opcode_xnor:
1114
                dst[0] |= 0x10;
1115
                /* no break */
1116
        case _opcode_xor:
1117
                dst[0] |= 0x06 << 5;
1118
                _alu_dump_operand(dst, op);
1119
 
1120
                break;
1121
        default:
1122
                err = -EINVAL;
1123
        }
1124
 
1125
        return err;
1126
}
1127
 
1128
static int _write_code(char *name, _op_t *op)
1129
{
1130
        char filename[64];
1131
        int err;
1132
 
1133
        err = snprintf(filename, 64, "%s.bin", name);
1134
        if (64 <= err) {
1135
                return -ENAMETOOLONG;
1136
        }
1137
 
1138
        err = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0644);
1139
        if (0 <= err) {
1140
                unsigned int i, max_addr;
1141
                _op_t *t;
1142
                int fd;
1143
 
1144
                fd = err;
1145
                err = 0;
1146
 
1147
                max_addr = 0;
1148
                for (t = op; NULL != t; t = t->next) {
1149
                        if (t->addr > max_addr)
1150
                                max_addr = t->addr;
1151
                }
1152
 
1153
                for (i = 0; 0 == err && i <= max_addr; i++) {
1154
                        unsigned short value[2];
1155
                        int k;
1156
 
1157
                        for (t = op; 0 == err && NULL != t; t = t->next) {
1158
                                if (i == t->addr) {
1159
                                        break;
1160
                                }
1161
                        }
1162
 
1163
                        value[0] = value[1] = 0;
1164
                        if (NULL != t) {
1165
                                for (k = 0; 0 == err && k < 2; k++) {
1166
                                        switch (t->opt[k]) {
1167
                                        case _op_type_jmp:
1168
                                                err = _jmp_dump((unsigned char *) &value[k], t->op[k].jmp);
1169
                                                break;
1170
                                        case _op_type_ldst:
1171
                                                err = _ldst_dump((unsigned char *) &value[k], t->op[k].ldst);
1172
                                                break;
1173
                                        case _op_type_alu:
1174
                                                err = _alu_dump((unsigned char *) &value[k], t->op[k].alu);
1175
                                                break;
1176
                                        }
1177
 
1178
                                        if (0 != err)
1179
                                                break;
1180
 
1181
                                        if (t->opt[0] == t->opt[1]) {
1182
                                                value[1] = value[0];
1183
                                                break;
1184
                                        }
1185
                                }
1186
                        }
1187
 
1188
                        while (0 == err) {
1189
                                err = write(fd, &value[0], sizeof(value));
1190
                                if (sizeof(value) == err) {
1191
                                        err = 0;
1192
                                        break;
1193
                                }
1194
 
1195
                                err = -errno;
1196
                                if (-EINTR == err)
1197
                                        err = 0;
1198
                        }
1199
                }
1200
 
1201
                close(fd);
1202
        } else
1203
                err = -errno;
1204
 
1205
        return err;
1206
}
1207
 
1208
 
1209
static int _parse_file(const char *filename)
1210
{
1211
        FILE *f;
1212
        int err;
1213
 
1214
        f = fopen(filename, "r");
1215
        if (NULL != f) {
1216
                _section_t sec;
1217
                int line;
1218
                char l[80];
1219
 
1220
                sec = _section_code;
1221
 
1222
                err = 0;
1223
                line = 0;
1224
 
1225
                while (0 == err && NULL != fgets(&l[0], 80, f)) {
1226
                        int len;
1227
 
1228
                        line++;
1229
 
1230
                        len = _shrink_line(&l[0], 80);
1231
                        if (0 > len) {
1232
                                err = len;
1233
                                fprintf(stderr, "parse error (%d) near line %d\n", err, line);
1234
 
1235
                                break;
1236
                        }
1237
 
1238
                        if (0 == len)
1239
                                continue;
1240
 
1241
                        err = _parse_line(&l[0], &sec);
1242
                        if (0 != err) {
1243
                                fprintf(stderr, "parse error (%d) near line %d\n", err, line);
1244
                        }
1245
                }
1246
 
1247
                fclose(f);
1248
 
1249
                if (0 == err) {
1250
                        err = _write_code(_outfile, _op);
1251
                        if (0 != err) {
1252
                                fprintf(stderr, "write data failed, error %d\n", err);
1253
                        }
1254
                }
1255
 
1256
                while (NULL != _op) {
1257
                        _op_t *op;
1258
 
1259
                        op = _op->next;
1260
                        if (_op->op[0].raw != _op->op[1].raw)
1261
                                free(_op->op[1].raw);
1262
                        free(_op->op[0].raw);
1263
                        free(_op);
1264
 
1265
                        _op = op;
1266
                }
1267
 
1268
                while (NULL != _var) {
1269
                        _var_t *t;
1270
 
1271
                        t = _var->next;
1272
                        free(_var);
1273
                        _var = t;
1274
                }
1275
        } else {
1276
                fprintf(stderr, "failed to open file %s\n", filename);
1277
                err = -errno;
1278
        }
1279
 
1280
        return err;
1281
}
1282
 
1283
int main(int argc, char *argv[])
1284
{
1285
        int err;
1286
 
1287
        err = _parse_args(argc, argv);
1288
        if (0 == err) {
1289
                err = _parse_file(_infile);
1290
        }
1291
 
1292
        return err;
1293
}
1294
 

powered by: WebSVN 2.1.0

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