URL
https://opencores.org/ocsvn/tinyvliw8/tinyvliw8/trunk
Subversion Repositories tinyvliw8
[/] [tinyvliw8/] [trunk/] [tools/] [asm/] [src/] [asm.c] - Rev 6
Compare with Previous | Blame | View Log
/** * \file asm.c * \author Oliver Stecklina <stecklina@ihp-microelectronics.com> * \date 12.12.2015 * * \brief main program file of the tinyVLIW8 assembler * * <p> * Copyright (C) 2015 IHP GmbH, Frankfurt (Oder), Germany * * This code is free software. It is licensed under the EUPL, Version 1.1 * or - as soon they will be approved by the European Commission - subsequent * versions of the EUPL (the "License"). * You may redistribute this code and/or modify it under the terms of this * License. * You may not use this work except in compliance with the License. * You may obtain a copy of the License at: * * http://joinup.ec.europa.eu/software/page/eupl/licence-eupl * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * </p> */ #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include "instr.h" #include "list.h" static unsigned int _linenum; static unsigned int _instr_addr; extern FILE *yyin; extern int yyparse(); static list_t _label = {&_label, &_label}; static list_t _instr = {&_instr, &_instr}; void instr_irq(unsigned char num) { _instr_addr = 0x07fc + num; } void instr_add(const instr_t *instr, const unsigned char num) { instr_vliw_t *ninstr; ninstr = malloc(sizeof(instr_vliw_t)); if (NULL != ninstr) { unsigned int i; ninstr->addr = _instr_addr; ninstr->num = num; for (i = 0; i < num; i++) { memcpy((char *) &ninstr->instr[i], (char *) &instr[i], sizeof(instr_t)); /* copy source list */ ninstr->instr[i].source.next->prev = &ninstr->instr[i].source; ninstr->instr[i].source.prev->next = &ninstr->instr[i].source; } list_add_last(&_instr, &ninstr->list); } _instr_addr++; } void instr_label(const char *name) { instr_label_t *n; n = malloc(sizeof(instr_label_t) + strlen(name) + 1); if (n) { LIST_INIT(&n->list); n->offset = _instr_addr; snprintf(n->name, 64, "%s", name); list_add(&_label, &n->list); } return; } void instr_add_source(list_t *head, instr_operand_type_t type, const void *data) { instr_operand_t *op; op = (instr_operand_t *) malloc(sizeof(instr_operand_t)); if (NULL != op) { op->type = type; switch (type) { case instr_operand_type_reg: case instr_operand_type_const: op->value = *((int *) data); break; case instr_operand_type_label: op->label = malloc(strlen((char *) data) + 1); if (NULL != op->label) { sprintf(op->label, "%s", (char *) data); } break; } list_add(head, &op->list); } } void instr_source_flag(list_t *source, unsigned char flag) { if (source->prev != source) { instr_operand_t *op = LIST_ENTRY(source->prev, instr_operand_t, list); op->flags |= flag; } } void instr_add_dest(instr_operand_t *op, const unsigned char num) { op->type = instr_operand_type_reg; op->value = num; } static unsigned int _get_symbol(const char *name) { return 0x00; } static unsigned int _get_label(const char *name) { if (NULL != name) { list_t *h; for (h = _label.next; h != &_label; h = h->next) { instr_label_t *l; l = LIST_ENTRY(h, instr_label_t, list); if (0 == strcmp(l->name, name)) return l->offset; } } return 0x00; } static void _write_jmp(unsigned char *iw, instr_opcode_t opcode, const instr_operand_t *op) { unsigned int addr; iw[0] = (0x07 << 5); switch (opcode) { case instr_opcode_jz: iw[0] |= (0x01 << 3); break; case instr_opcode_jc: iw[0] |= (0x02 << 3); break; case instr_opcode_jnz: iw[0] |= (0x03 << 3); break; default: /* nothing to do */; } addr = 0; if (instr_operand_type_const == op->type) { addr = op->value; } else if (instr_operand_type_label == op->type) { addr = _get_label(op->label); } iw[0] |= ((addr & 0x07ff) >> 8); iw[1] = addr & 0x00ff; } static void _write_ldst(unsigned char *iw, instr_opcode_t opcode, const instr_operand_t *dst, const instr_operand_t *src) { switch (opcode) { case instr_opcode_ldi: iw[0] = (0x01 << 4); break; case instr_opcode_st: iw[0] = (0x02 << 4); break; case instr_opcode_sti: iw[0] = (0x03 << 4); break; default: iw[0] = 0x00; break; } if (instr_operand_type_reg == src->type) { iw[0] |= (0x01 << 3); } iw[0] |= dst->value & 0x07; switch (src->type) { case instr_operand_type_reg: iw[0] |= (0x01 << 3); iw[1] = src->value & 0x07; break; case instr_operand_type_const: iw[1] = src->value; break; case instr_operand_type_label: iw[1] = _get_symbol(src->label); break; } } static void _write_sh(unsigned char *iw, instr_opcode_t opcode, const instr_operand_t *dst, const instr_operand_t *src) { iw[0] = (0x03 << 5); iw[1] = 0x00; switch (opcode) { case instr_opcode_rlc: iw[1] |= (0x01 << 3); break; case instr_opcode_rrc: iw[1] |= (0x01 << 3); case instr_opcode_rra: iw[0] |= (0x01 << 3); break; default: /* nothing to do */; } iw[0] |= dst->value & 0x07; iw[1] |= src->value & 0x07; } #define _SRC_FIRST(src) (src)->next != src ? LIST_ENTRY((src)->next, instr_operand_t, list) : NULL static void _write_src(unsigned char *iw, const instr_operand_t *dst, const list_t *src_l) { instr_operand_t *src = _SRC_FIRST(src_l); if (instr_operand_type_const == src->type) { iw[0] |= (0x01 << 3); iw[1] = src->value & 0x00ff; } else if (instr_operand_type_reg == src->type) { iw[1] = src->value & 0x07; if (0 != (src->flags & INSTR_FLAG_TILDE)) iw[1] |= (0x01 << 3); if (src->list.next != src_l) { src = LIST_ENTRY(src->list.next, instr_operand_t, list); iw[1] |= (src->value & 0x07) << 4; if (0 != (src->flags & INSTR_FLAG_TILDE)) iw[1] |= (0x01 << 7); } else { iw[1] |= (dst->value & 0x07) << 4; } } } static void _write_add(unsigned char *iw, unsigned char carry, const instr_operand_t *dst, const list_t *src_l) { iw[0] = (0x02 << 5); if (0 != carry) iw[0] |= (0x02 << 3); iw[0] |= dst->value & 0x07; _write_src(iw, dst, src_l); } static void _write_mov(unsigned char *iw, const instr_operand_t *dst, const instr_operand_t *src) { iw[0] = (0x03 << 5); iw[0] |= (0x02 << 3); iw[0] |= dst->value & 0x07; if (instr_operand_type_const == src->type) { iw[0] |= (0x01 << 3); iw[1] = src->value & 0x00ff; } else if (instr_operand_type_reg == src->type) { iw[1] = src->value & 0x07; if (0 != (src->flags & INSTR_FLAG_TILDE)) iw[1] |= (0x01 << 3); } } static void _write_logic(unsigned char *iw, instr_opcode_t opcode, const instr_operand_t *dst, const list_t *src_l) { iw[0] = 0x00; switch (opcode) { case instr_opcode_nand: iw[0] |= (0x02 << 3); case instr_opcode_and: iw[0] |= (0x04 << 5); break; case instr_opcode_nor: iw[0] |= (0x02 << 3); case instr_opcode_or: iw[0] |= (0x05 << 5); break; case instr_opcode_xnor: iw[0] |= (0x02 << 3); case instr_opcode_xor: iw[0] |= (0x06 << 5); break; default: /* nothing to do */; } iw[0] |= dst->value & 0x07; _write_src(iw, dst, src_l); } static void _gen_code(unsigned char *iw, const instr_t *i) { switch (i->opcode) { case instr_opcode_ld: case instr_opcode_ldi: case instr_opcode_st: case instr_opcode_sti: _write_ldst(iw, i->opcode, &i->dest, _SRC_FIRST(&i->source)); break; case instr_opcode_add: case instr_opcode_addi: _write_add(iw, i->opcode == instr_opcode_addi ? 1 : 0, &i->dest, &i->source); break; case instr_opcode_rla: case instr_opcode_rlc: case instr_opcode_rra: case instr_opcode_rrc: _write_sh(iw, i->opcode, &i->dest, _SRC_FIRST(&i->source)); break; case instr_opcode_mov: _write_mov(iw, &i->dest, _SRC_FIRST(&i->source)); break; case instr_opcode_and: case instr_opcode_nand: case instr_opcode_or: case instr_opcode_nor: case instr_opcode_xor: case instr_opcode_xnor: _write_logic(iw, i->opcode, &i->dest, &i->source); break; case instr_opcode_jmp: case instr_opcode_jc: case instr_opcode_jz: case instr_opcode_jnz: _write_jmp(iw, i->opcode, _SRC_FIRST(&i->source)); break; } } void instr_out(const char *filename) { list_t *head; int f; f = open(filename, O_WRONLY | O_CREAT | O_TRUNC #ifdef __MINGW32__ | O_BINARY, S_IRUSR | S_IWUSR #else , S_IRUSR | S_IWUSR | S_IRGRP #endif ); if (0 <= f) { unsigned int addr; addr = 0; for (head = _instr.next; head != &_instr; head = head->next) { instr_vliw_t *i = LIST_ENTRY(head, instr_vliw_t, list); unsigned char iw[4]; int err; memset(&iw[0], 0x00, sizeof(iw)); while (addr < 0x7ff && addr < i->addr) { err = write(f, &iw[0], 4); if (err != 4) { fprintf(stderr, "write failed\n"); break; } addr++; } _gen_code(&iw[0], &i->instr[0]); _gen_code(&iw[2], &i->instr[1 < i->num ? 1 : 0]); err = write(f, &iw[0], 4); if (err != 4) { fprintf(stderr, "write failed\n"); break; } addr++; } close(f); } else fprintf(stderr, "unable to open output\n"); } int execute(int arg) { return arg; } void nextline() { _linenum++; } int get_linenum() { return _linenum; } int main(int argc, char *argv[]) { _linenum = 0; _instr_addr = 0; if (1 < argc) { fprintf(stderr, "parse file %s\n", argv[1]); yyin = fopen(argv[1], "r"); } else yyin = stdin; yyparse(); instr_out("out.a"); return 0; }