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

Subversion Repositories tinyvliw8

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

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

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

powered by: WebSVN 2.1.0

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