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

Subversion Repositories tinyvliw8

[/] [tinyvliw8/] [trunk/] [tools/] [asm/] [src/] [parser.y] - Rev 6

Compare with Previous | Blame | View Log

/**
 * \file   parser.y
 * \author Oliver Stecklina <stecklina@ihp-microelectronics.com>
 * \date   12.12.2015
 * 
 * \brief  Yacc parser file
 *
 * <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 <stdio.h>
        #include <string.h>

        #include "instr.h"

        static instr_t _instr[2];
        static unsigned char _instr_num = 0;

    extern int yylex();
        extern int get_linenum();

        unsigned char _sign;

    void yyerror(const char *s) {
                printf("ERROR: %s near line %d\n", s, get_linenum());
        }

        void _instr_clean(void)
        {
                memset((char *) &_instr[0], 0x00, 2 * sizeof(instr_t));

                _instr[0].source.next = &_instr[0].source;
                _instr[0].source.prev = &_instr[0].source;
                _instr[1].source.next = &_instr[1].source;
                _instr[1].source.prev = &_instr[1].source;

                _instr_num = 0;
        }
%}

%union {
        char* str;
        int   num;
}

%start PROGRAM

%token CONSTSEC
%token RESSEC
%token CODESEC
%token <num> IRQSEC
%token LOADI
%token LOAD
%token STOREI
%token STORE
%token RLA
%token RLC
%token RRA
%token RRC
%token MOVE
%token ADDI
%token ADD
%token OR
%token XOR
%token XNOR
%token NOR
%token AND
%token NAND
%token JMP
%token JNZ
%token JZ
%token JC
%token COLON
%token PLUS
%token MINUS
%token TILDE
%token PIPE
%token DOLLAR
%token HASH
%token AT
%token <num> REG
%token <num> HEXNUM
%token <num> HEXADDR
%token <str> NAME
%token <str> UNAME
%token NEWLINE
%token SEMICOLON
%token COMMA

   %%

PROGRAM:
        constseq resseq codeseq irqseq

empty:

constseq:
          CONSTSEC linebreak consts
        | empty

resseq:
        RESSEC linebreak ress
        | empty

codeseq:
          CODESEC { _instr_clean(); } linebreak code 
        | empty

irqseq:
          irq irq irq irq
        | irq irq irq
        | irq irq
        | irq
        | empty

irq:
          IRQSEC linebreak instr { instr_irq($1); instr_add(&_instr[0], _instr_num); _instr_clean(); }

ress:
          res ress
        | res

res:
        NAME HEXNUM SEMICOLON linebreak

consts:
          cvar consts
        | cvar
        
cvar:
        UNAME HEXNUM SEMICOLON linebreak

linebreak:
          linebreak NEWLINE
        | NEWLINE

code:
          cinstr code
        | cinstr

cinstr:
          NAME COLON linebreak instr { instr_label($1); instr_add(&_instr[0], _instr_num); _instr_clean(); }
        | instr                      { instr_add(&_instr[0], _instr_num); _instr_clean(); }

instr:
          cmd SEMICOLON linebreak
        | cmd PIPE cmd SEMICOLON linebreak

cmd:
          ldsti REG COMMA src     { instr_add_dest(&_instr[_instr_num].dest, $2); _instr_num++; }
        | logici REG COMMA alusrc { instr_add_dest(&_instr[_instr_num].dest, $2); _instr_num++; }
        | alui REG COMMA alusrc   { instr_add_dest(&_instr[_instr_num].dest, $2); _instr_num++; }
        | sh                      { _instr_num++; }
        | jmpi jmpdst             { _instr_num++; }

sh:
          shi REG COMMA srcreg  { instr_add_dest(&_instr[_instr_num].dest, $2); }
        | MOVE REG COMMA movsrc { instr_add_dest(&_instr[_instr_num].dest, $2); _instr[_instr_num].opcode = instr_opcode_mov; }

shi:
          RLA { _instr[_instr_num].opcode = instr_opcode_rla; }
        | RLC { _instr[_instr_num].opcode = instr_opcode_rlc; }
        | RRA { _instr[_instr_num].opcode = instr_opcode_rra; }
        | RRC { _instr[_instr_num].opcode = instr_opcode_rrc; }

movsrc:
          srcreg
        | HASH HEXNUM { instr_add_source(&_instr[_instr_num].source, instr_operand_type_const, &($2)); }

jmpi:
          JMP { _instr[_instr_num].opcode = instr_opcode_jmp; }
        | JZ  { _instr[_instr_num].opcode = instr_opcode_jz; }
        | JC  { _instr[_instr_num].opcode = instr_opcode_jc; }
        | JNZ { _instr[_instr_num].opcode = instr_opcode_jnz; }

alui:
          ADD  { _instr[_instr_num].opcode = instr_opcode_add; }
        | ADDI { _instr[_instr_num].opcode = instr_opcode_addi; }

jmpdst:
          DOLLAR NAME { instr_add_source(&_instr[_instr_num].source, instr_operand_type_label, $2); }
        | sign HEXADDR { instr_add_source(&_instr[_instr_num].source, instr_operand_type_const, &($2)); instr_source_flag(&_instr[_instr_num].source, _sign);}

ldsti:
          LOAD   { _instr[_instr_num].opcode = instr_opcode_ld; }
        | LOADI  { _instr[_instr_num].opcode = instr_opcode_ldi; }
        | STORE  { _instr[_instr_num].opcode = instr_opcode_st; }
        | STOREI { _instr[_instr_num].opcode = instr_opcode_sti; }
        
sign:
          PLUS  { _sign = 0x00; }
        | MINUS { _sign = INSTR_FLAG_MINUS; }

src:
          AT REG { instr_add_source(&_instr[_instr_num].source, instr_operand_type_reg, &($2)); }
        | HASH HEXNUM { instr_add_source(&_instr[_instr_num].source, instr_operand_type_const, &($2)); }
        | DOLLAR UNAME { instr_add_source(&_instr[_instr_num].source, instr_operand_type_label, $2); }
        | DOLLAR NAME { instr_add_source(&_instr[_instr_num].source, instr_operand_type_label, $2); }

logici:
          OR   { _instr[_instr_num].opcode = instr_opcode_or; }
        | NOR  { _instr[_instr_num].opcode = instr_opcode_nor; }
        | AND  { _instr[_instr_num].opcode = instr_opcode_and; }
        | NAND { _instr[_instr_num].opcode = instr_opcode_nand; }
        | XOR  { _instr[_instr_num].opcode = instr_opcode_xor; }
        | XNOR { _instr[_instr_num].opcode = instr_opcode_xnor; }

alusrc:
          HASH HEXNUM { instr_add_source(&_instr[_instr_num].source, instr_operand_type_const, &($2)); }
        | srcreg
        | srcreg COMMA srcreg

srcreg:
          REG { instr_add_source(&_instr[_instr_num].source, instr_operand_type_reg, &($1)); }
        | TILDE REG { instr_add_source(&_instr[_instr_num].source, instr_operand_type_reg, &($2)); instr_source_flag(&_instr[_instr_num].source, INSTR_FLAG_TILDE);}

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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