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

Subversion Repositories tinyvliw8

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 steckol
/**
2
 * \file   asm.c
3
 * \author Oliver Stecklina <stecklina@ihp-microelectronics.com>
4
 * \date   12.12.2015
5
 *
6
 * \brief  main program file of the tinyVLIW8 assembler
7
 *
8
 * <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
 */
28
 
29 5 steckol
#include <sys/types.h>
30
#include <sys/stat.h>
31
#include <stdio.h>
32
#include <stdlib.h>
33
#include <string.h>
34
#include <fcntl.h>
35
#include <unistd.h>
36
 
37
#include "instr.h"
38
#include "list.h"
39
 
40
static unsigned int _linenum;
41
static unsigned int _instr_addr;
42
 
43
extern FILE *yyin;
44
extern int yyparse();
45
 
46
static list_t _label = {&_label, &_label};
47
static list_t _instr = {&_instr, &_instr};
48
 
49
void instr_irq(unsigned char num)
50
{
51
        _instr_addr = 0x07fc + num;
52
}
53
 
54
void instr_add(const instr_t *instr, const unsigned char num)
55
{
56
        instr_vliw_t *ninstr;
57
 
58
        ninstr = malloc(sizeof(instr_vliw_t));
59
        if (NULL != ninstr) {
60
                unsigned int i;
61
 
62
                ninstr->addr = _instr_addr;
63
 
64
                ninstr->num = num;
65
                for (i = 0; i < num; i++) {
66
                        memcpy((char *) &ninstr->instr[i], (char *) &instr[i], sizeof(instr_t));
67
 
68
                        /* copy source list */
69
                        ninstr->instr[i].source.next->prev = &ninstr->instr[i].source;
70
                        ninstr->instr[i].source.prev->next = &ninstr->instr[i].source;
71
                }
72
 
73
                list_add_last(&_instr, &ninstr->list);
74
        }
75
 
76
        _instr_addr++;
77
}
78
 
79
void instr_label(const char *name)
80
{
81
        instr_label_t *n;
82
 
83
        n = malloc(sizeof(instr_label_t) + strlen(name) + 1);
84
        if (n) {
85
                LIST_INIT(&n->list);
86
                n->offset = _instr_addr;
87
 
88
                snprintf(n->name, 64, "%s", name);
89
 
90
                list_add(&_label, &n->list);
91
        }
92
 
93
        return;
94
}
95
 
96
void instr_add_source(list_t *head, instr_operand_type_t type, const void *data)
97
{
98
        instr_operand_t *op;
99
 
100
        op = (instr_operand_t *) malloc(sizeof(instr_operand_t));
101
        if (NULL != op) {
102
                op->type = type;
103
                switch (type) {
104
                  case instr_operand_type_reg:
105
                  case instr_operand_type_const:
106
                        op->value = *((int *) data);
107
                        break;
108
                  case instr_operand_type_label:
109
                        op->label = malloc(strlen((char *) data) + 1);
110
                        if (NULL != op->label) {
111
                                sprintf(op->label, "%s", (char *) data);
112
                        }
113
 
114
                        break;
115
                }
116
 
117
                list_add(head, &op->list);
118
        }
119
}
120
 
121
void instr_source_flag(list_t *source, unsigned char flag)
122
{
123
        if (source->prev != source) {
124
                instr_operand_t *op = LIST_ENTRY(source->prev, instr_operand_t, list);
125
 
126
                op->flags |= flag;
127
        }
128
}
129
 
130
void instr_add_dest(instr_operand_t *op, const unsigned char num)
131
{
132
        op->type = instr_operand_type_reg;
133
        op->value = num;
134
}
135
 
136
static unsigned int _get_symbol(const char *name)
137
{
138
        return 0x00;
139
}
140
 
141
static unsigned int _get_label(const char *name)
142
{
143
        if (NULL != name) {
144
                list_t *h;
145
 
146
                for (h = _label.next; h != &_label; h = h->next) {
147
                        instr_label_t *l;
148
 
149
                        l = LIST_ENTRY(h, instr_label_t, list);
150
 
151
                        if (0 == strcmp(l->name, name))
152
                                return l->offset;
153
                }
154
        }
155
 
156
        return 0x00;
157
}
158
 
159
static void _write_jmp(unsigned char *iw, instr_opcode_t opcode, const instr_operand_t *op)
160
{
161
        unsigned int addr;
162
 
163
        iw[0] = (0x07 << 5);
164
 
165
        switch (opcode) {
166
        case instr_opcode_jz:
167
                iw[0] |= (0x01 << 3);
168
                break;
169
        case instr_opcode_jc:
170
                iw[0] |= (0x02 << 3);
171
                break;
172
        case instr_opcode_jnz:
173
                iw[0] |= (0x03 << 3);
174
                break;
175
        default:
176
                /* nothing to do */;
177
        }
178
 
179
        addr = 0;
180
        if (instr_operand_type_const == op->type) {
181
                addr = op->value;
182
        } else if (instr_operand_type_label == op->type) {
183
                addr = _get_label(op->label);
184
        }
185
 
186
        iw[0] |= ((addr & 0x07ff) >> 8);
187
        iw[1] = addr & 0x00ff;
188
}
189
 
190
static void _write_ldst(unsigned char *iw, instr_opcode_t opcode, const instr_operand_t *dst, const instr_operand_t *src)
191
{
192
        switch (opcode) {
193
        case instr_opcode_ldi:
194
                iw[0] = (0x01 << 4);
195
                break;
196
        case instr_opcode_st:
197
                iw[0] = (0x02 << 4);
198
                break;
199
        case instr_opcode_sti:
200
                iw[0] = (0x03 << 4);
201
                break;
202
        default:
203
                iw[0] = 0x00;
204
                break;
205
        }
206
 
207
        if (instr_operand_type_reg == src->type) {
208
                iw[0] |= (0x01 << 3);
209
        }
210
 
211
        iw[0] |= dst->value & 0x07;
212
 
213
        switch (src->type) {
214
        case instr_operand_type_reg:
215
                iw[0] |= (0x01 << 3);
216
                iw[1] = src->value & 0x07;
217
 
218
                break;
219
        case instr_operand_type_const:
220
                iw[1] = src->value;
221
                break;
222
        case instr_operand_type_label:
223
                iw[1] = _get_symbol(src->label);
224
                break;
225
        }
226
}
227
 
228
static void _write_sh(unsigned char *iw, instr_opcode_t opcode, const instr_operand_t *dst, const instr_operand_t *src)
229
{
230
        iw[0] = (0x03 << 5);
231
        iw[1] = 0x00;
232
 
233
        switch (opcode) {
234
        case instr_opcode_rlc:
235
                iw[1] |= (0x01 << 3);
236
                break;
237
        case instr_opcode_rrc:
238
                iw[1] |= (0x01 << 3);
239
        case instr_opcode_rra:
240
                iw[0] |= (0x01 << 3);
241
                break;
242
        default:
243
                /* nothing to do */;
244
        }
245
 
246
        iw[0] |= dst->value & 0x07;
247
        iw[1] |= src->value & 0x07;
248
}
249
 
250
#define _SRC_FIRST(src)  (src)->next != src ? LIST_ENTRY((src)->next, instr_operand_t, list) : NULL
251
 
252
static void _write_src(unsigned char *iw, const instr_operand_t *dst, const list_t *src_l)
253
{
254
        instr_operand_t *src = _SRC_FIRST(src_l);
255
 
256
        if (instr_operand_type_const == src->type) {
257
                iw[0] |= (0x01 << 3);
258
                iw[1] = src->value & 0x00ff;
259
        } else if (instr_operand_type_reg == src->type) {
260
                iw[1] = src->value & 0x07;
261
                if (0 != (src->flags & INSTR_FLAG_TILDE))
262
                        iw[1] |= (0x01 << 3);
263
 
264
                if (src->list.next != src_l) {
265
                        src = LIST_ENTRY(src->list.next, instr_operand_t, list);
266
 
267
                        iw[1] |= (src->value & 0x07) << 4;
268
                        if (0 != (src->flags & INSTR_FLAG_TILDE))
269
                                iw[1] |= (0x01 << 7);
270
                } else {
271
                        iw[1] |= (dst->value & 0x07) << 4;
272
                }
273
        }
274
}
275
 
276
static void _write_add(unsigned char *iw, unsigned char carry, const instr_operand_t *dst, const list_t *src_l)
277
{
278
        iw[0] = (0x02 << 5);
279
        if (0 != carry)
280
                iw[0] |= (0x02 << 3);
281
 
282
        iw[0] |= dst->value & 0x07;
283
 
284
        _write_src(iw, dst, src_l);
285
}
286
 
287
static void _write_mov(unsigned char *iw, const instr_operand_t *dst, const instr_operand_t *src)
288
{
289
        iw[0] = (0x03 << 5);
290
        iw[0] |= (0x02 << 3);
291
 
292
        iw[0] |= dst->value & 0x07;
293
 
294
        if (instr_operand_type_const == src->type) {
295
                iw[0] |= (0x01 << 3);
296
                iw[1] = src->value & 0x00ff;
297
        } else if (instr_operand_type_reg == src->type) {
298
                iw[1] = src->value & 0x07;
299
                if (0 != (src->flags & INSTR_FLAG_TILDE))
300
                        iw[1] |= (0x01 << 3);
301
        }
302
}
303
 
304
static void _write_logic(unsigned char *iw, instr_opcode_t opcode, const instr_operand_t *dst, const list_t *src_l)
305
{
306
        iw[0] = 0x00;
307
 
308
        switch (opcode) {
309
        case instr_opcode_nand:
310
                iw[0] |= (0x02 << 3);
311
        case instr_opcode_and:
312
                iw[0] |= (0x04 << 5);
313
                break;
314
        case instr_opcode_nor:
315
                iw[0] |= (0x02 << 3);
316
        case instr_opcode_or:
317
                iw[0] |= (0x05 << 5);
318
                break;
319
        case instr_opcode_xnor:
320
                iw[0] |= (0x02 << 3);
321
        case instr_opcode_xor:
322
                iw[0] |= (0x06 << 5);
323
                break;
324
        default:
325
                /* nothing to do */;
326
        }
327
 
328
        iw[0] |= dst->value & 0x07;
329
 
330
        _write_src(iw, dst, src_l);
331
}
332
 
333
static void _gen_code(unsigned char *iw, const instr_t *i)
334
{
335
        switch (i->opcode) {
336
        case instr_opcode_ld:
337
        case instr_opcode_ldi:
338
        case instr_opcode_st:
339
        case instr_opcode_sti:
340
                _write_ldst(iw, i->opcode, &i->dest, _SRC_FIRST(&i->source));
341
                break;
342
        case instr_opcode_add:
343
        case instr_opcode_addi:
344
                _write_add(iw, i->opcode == instr_opcode_addi ? 1 : 0, &i->dest, &i->source);
345
                break;
346
        case instr_opcode_rla:
347
        case instr_opcode_rlc:
348
        case instr_opcode_rra:
349
        case instr_opcode_rrc:
350
                _write_sh(iw, i->opcode, &i->dest, _SRC_FIRST(&i->source));
351
                break;
352
        case instr_opcode_mov:
353
                _write_mov(iw, &i->dest, _SRC_FIRST(&i->source));
354
                break;
355
        case instr_opcode_and:
356
        case instr_opcode_nand:
357
        case instr_opcode_or:
358
        case instr_opcode_nor:
359
        case instr_opcode_xor:
360
        case instr_opcode_xnor:
361
                _write_logic(iw, i->opcode, &i->dest, &i->source);
362
                break;
363
        case instr_opcode_jmp:
364
        case instr_opcode_jc:
365
        case instr_opcode_jz:
366
        case instr_opcode_jnz:
367
                _write_jmp(iw, i->opcode, _SRC_FIRST(&i->source));
368
                break;
369
        }
370
}
371
 
372
void instr_out(const char *filename)
373
{
374
        list_t *head;
375
        int f;
376
 
377
        f = open(filename, O_WRONLY | O_CREAT | O_TRUNC
378
#ifdef __MINGW32__
379
                        | O_BINARY,  S_IRUSR | S_IWUSR
380
#else
381
                        , S_IRUSR | S_IWUSR | S_IRGRP
382
#endif
383
                        );
384
 
385
        if (0 <= f) {
386
                unsigned int addr;
387
 
388
                addr = 0;
389
                for (head = _instr.next; head != &_instr; head = head->next) {
390
                        instr_vliw_t *i = LIST_ENTRY(head, instr_vliw_t, list);
391
                        unsigned char iw[4];
392
                        int err;
393
 
394
                        memset(&iw[0], 0x00, sizeof(iw));
395
 
396
                        while (addr < 0x7ff && addr < i->addr) {
397
                                err = write(f, &iw[0], 4);
398
                                if (err != 4) {
399
                                        fprintf(stderr, "write failed\n");
400
                                        break;
401
                                }
402
 
403
                                addr++;
404
                        }
405
 
406
                        _gen_code(&iw[0], &i->instr[0]);
407
                        _gen_code(&iw[2], &i->instr[1 < i->num ? 1 : 0]);
408
 
409
                        err = write(f, &iw[0], 4);
410
                        if (err != 4) {
411
                                fprintf(stderr, "write failed\n");
412
                                break;
413
                        }
414
 
415
                        addr++;
416
                }
417
 
418
                close(f);
419
        } else
420
                fprintf(stderr, "unable to open output\n");
421
}
422
 
423
int execute(int arg)
424
{
425
        return arg;
426
}
427
 
428
void nextline()
429
{
430
        _linenum++;
431
}
432
 
433
int get_linenum()
434
{
435
        return _linenum;
436
}
437
 
438
int main(int argc, char *argv[])
439
{
440
        _linenum = 0;
441
        _instr_addr = 0;
442
 
443
        if (1 < argc) {
444
                fprintf(stderr, "parse file %s\n", argv[1]);
445
                yyin = fopen(argv[1], "r");
446
        } else
447
                yyin = stdin;
448
 
449
        yyparse();
450
 
451
        instr_out("out.a");
452
 
453
        return 0;
454
}
455
 

powered by: WebSVN 2.1.0

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