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);}