17ec681f3Smrg/*
27ec681f3Smrg * Copyright (c) 2013 Rob Clark <robclark@freedesktop.org>
37ec681f3Smrg *
47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
57ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
67ec681f3Smrg * to deal in the Software without restriction, including without limitation
77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
97ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
107ec681f3Smrg *
117ec681f3Smrg * The above copyright notice and this permission notice (including the next
127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
137ec681f3Smrg * Software.
147ec681f3Smrg *
157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
207ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
217ec681f3Smrg * SOFTWARE.
227ec681f3Smrg */
237ec681f3Smrg
247ec681f3Smrg%{
257ec681f3Smrg#define YYDEBUG 0
267ec681f3Smrg
277ec681f3Smrg#include <stdlib.h>
287ec681f3Smrg#include <stdio.h>
297ec681f3Smrg#include <string.h>
307ec681f3Smrg#include <math.h>
317ec681f3Smrg#include "asm.h"
327ec681f3Smrg
337ec681f3Smrg
347ec681f3Smrgint yyget_lineno(void);
357ec681f3Smrg
367ec681f3Smrg#ifdef YYDEBUG
377ec681f3Smrgint yydebug;
387ec681f3Smrg#endif
397ec681f3Smrg
407ec681f3Smrgextern int yylex(void);
417ec681f3Smrgtypedef void *YY_BUFFER_STATE;
427ec681f3Smrgextern YY_BUFFER_STATE yy_scan_string(const char *);
437ec681f3Smrgextern void yy_delete_buffer(YY_BUFFER_STATE);
447ec681f3Smrg
457ec681f3Smrgint yyparse(void);
467ec681f3Smrg
477ec681f3Smrgvoid yyerror(const char *error);
487ec681f3Smrgvoid yyerror(const char *error)
497ec681f3Smrg{
507ec681f3Smrg	fprintf(stderr, "error at line %d: %s\n", yyget_lineno(), error);
517ec681f3Smrg}
527ec681f3Smrg
537ec681f3Smrgstatic struct asm_instruction *instr;   /* current instruction */
547ec681f3Smrg
557ec681f3Smrgstatic void
567ec681f3Smrgnew_instr(int tok)
577ec681f3Smrg{
587ec681f3Smrg	instr = next_instr(tok);
597ec681f3Smrg}
607ec681f3Smrg
617ec681f3Smrgstatic void
627ec681f3Smrgdst(int num)
637ec681f3Smrg{
647ec681f3Smrg	instr->dst = num;
657ec681f3Smrg}
667ec681f3Smrg
677ec681f3Smrgstatic void
687ec681f3Smrgsrc1(int num)
697ec681f3Smrg{
707ec681f3Smrg	instr->src1 = num;
717ec681f3Smrg}
727ec681f3Smrg
737ec681f3Smrgstatic void
747ec681f3Smrgsrc2(int num)
757ec681f3Smrg{
767ec681f3Smrg	instr->src2 = num;
777ec681f3Smrg}
787ec681f3Smrg
797ec681f3Smrgstatic void
807ec681f3Smrgimmed(int num)
817ec681f3Smrg{
827ec681f3Smrg	instr->immed = num;
837ec681f3Smrg	instr->has_immed = true;
847ec681f3Smrg}
857ec681f3Smrg
867ec681f3Smrgstatic void
877ec681f3Smrgshift(int num)
887ec681f3Smrg{
897ec681f3Smrg	instr->shift = num;
907ec681f3Smrg	instr->has_shift = true;
917ec681f3Smrg}
927ec681f3Smrg
937ec681f3Smrgstatic void
947ec681f3Smrgbit(int num)
957ec681f3Smrg{
967ec681f3Smrg	instr->bit = num;
977ec681f3Smrg	instr->has_bit = true;
987ec681f3Smrg}
997ec681f3Smrg
1007ec681f3Smrgstatic void
1017ec681f3Smrgliteral(uint32_t num)
1027ec681f3Smrg{
1037ec681f3Smrg	instr->literal = num;
1047ec681f3Smrg	instr->is_literal = true;
1057ec681f3Smrg}
1067ec681f3Smrg
1077ec681f3Smrgstatic void
1087ec681f3Smrglabel(const char *str)
1097ec681f3Smrg{
1107ec681f3Smrg	instr->label = str;
1117ec681f3Smrg}
1127ec681f3Smrg
1137ec681f3Smrg%}
1147ec681f3Smrg
1157ec681f3Smrg%union {
1167ec681f3Smrg	int tok;
1177ec681f3Smrg	uint32_t num;
1187ec681f3Smrg	const char *str;
1197ec681f3Smrg}
1207ec681f3Smrg
1217ec681f3Smrg%token <num> T_INT
1227ec681f3Smrg%token <num> T_HEX
1237ec681f3Smrg%token <num> T_CONTROL_REG
1247ec681f3Smrg%token <str> T_LABEL_DECL
1257ec681f3Smrg%token <str> T_LABEL_REF
1267ec681f3Smrg%token <num> T_LITERAL
1277ec681f3Smrg%token <num> T_BIT
1287ec681f3Smrg%token <num> T_REGISTER
1297ec681f3Smrg
1307ec681f3Smrg%token <tok> T_OP_NOP
1317ec681f3Smrg%token <tok> T_OP_ADD
1327ec681f3Smrg%token <tok> T_OP_ADDHI
1337ec681f3Smrg%token <tok> T_OP_SUB
1347ec681f3Smrg%token <tok> T_OP_SUBHI
1357ec681f3Smrg%token <tok> T_OP_AND
1367ec681f3Smrg%token <tok> T_OP_OR
1377ec681f3Smrg%token <tok> T_OP_XOR
1387ec681f3Smrg%token <tok> T_OP_NOT
1397ec681f3Smrg%token <tok> T_OP_SHL
1407ec681f3Smrg%token <tok> T_OP_USHR
1417ec681f3Smrg%token <tok> T_OP_ISHR
1427ec681f3Smrg%token <tok> T_OP_ROT
1437ec681f3Smrg%token <tok> T_OP_MUL8
1447ec681f3Smrg%token <tok> T_OP_MIN
1457ec681f3Smrg%token <tok> T_OP_MAX
1467ec681f3Smrg%token <tok> T_OP_CMP
1477ec681f3Smrg%token <tok> T_OP_MSB
1487ec681f3Smrg%token <tok> T_OP_MOV
1497ec681f3Smrg%token <tok> T_OP_CWRITE
1507ec681f3Smrg%token <tok> T_OP_CREAD
1517ec681f3Smrg%token <tok> T_OP_STORE
1527ec681f3Smrg%token <tok> T_OP_LOAD
1537ec681f3Smrg%token <tok> T_OP_BRNE
1547ec681f3Smrg%token <tok> T_OP_BREQ
1557ec681f3Smrg%token <tok> T_OP_RET
1567ec681f3Smrg%token <tok> T_OP_IRET
1577ec681f3Smrg%token <tok> T_OP_CALL
1587ec681f3Smrg%token <tok> T_OP_JUMP
1597ec681f3Smrg%token <tok> T_OP_WAITIN
1607ec681f3Smrg%token <tok> T_OP_PREEMPTLEAVE
1617ec681f3Smrg%token <tok> T_OP_SETSECURE
1627ec681f3Smrg%token <tok> T_LSHIFT
1637ec681f3Smrg%token <tok> T_REP
1647ec681f3Smrg%token <num> T_XMOV
1657ec681f3Smrg
1667ec681f3Smrg%type <num> reg
1677ec681f3Smrg%type <num> immediate
1687ec681f3Smrg
1697ec681f3Smrg%error-verbose
1707ec681f3Smrg
1717ec681f3Smrg%start instrs
1727ec681f3Smrg
1737ec681f3Smrg%%
1747ec681f3Smrg
1757ec681f3Smrginstrs:            instr_or_label instrs
1767ec681f3Smrg|                  instr_or_label
1777ec681f3Smrg
1787ec681f3Smrginstr_or_label:    instr_r
1797ec681f3Smrg|                  T_REP instr_r    { instr->rep = true; }
1807ec681f3Smrg|                  branch_instr
1817ec681f3Smrg|                  other_instr
1827ec681f3Smrg|                  T_LABEL_DECL   { decl_label($1); }
1837ec681f3Smrg
1847ec681f3Smrg/* instructions that can optionally have (rep) flag: */
1857ec681f3Smrginstr_r:           alu_instr
1867ec681f3Smrg|                  T_XMOV alu_instr { instr->xmov = $1; }
1877ec681f3Smrg|                  config_instr
1887ec681f3Smrg
1897ec681f3Smrg/* need to special case:
1907ec681f3Smrg * - not (single src, possibly an immediate)
1917ec681f3Smrg * - msb (single src, must be reg)
1927ec681f3Smrg * - mov (single src, plus possibly a shift)
1937ec681f3Smrg * from the other ALU instructions:
1947ec681f3Smrg */
1957ec681f3Smrg
1967ec681f3Smrgalu_msb_instr:     T_OP_MSB reg ',' reg        { new_instr($1); dst($2); src2($4); }
1977ec681f3Smrg
1987ec681f3Smrgalu_not_instr:     T_OP_NOT reg ',' reg        { new_instr($1); dst($2); src2($4); }
1997ec681f3Smrg|                  T_OP_NOT reg ',' immediate  { new_instr($1); dst($2); immed($4); }
2007ec681f3Smrg
2017ec681f3Smrgalu_mov_instr:     T_OP_MOV reg ',' reg        { new_instr($1); dst($2); src1($4); }
2027ec681f3Smrg|                  T_OP_MOV reg ',' immediate T_LSHIFT immediate {
2037ec681f3Smrg                       new_instr($1); dst($2); immed($4); shift($6);
2047ec681f3Smrg}
2057ec681f3Smrg|                  T_OP_MOV reg ',' immediate  { new_instr($1); dst($2); immed($4); }
2067ec681f3Smrg|                  T_OP_MOV reg ',' T_LABEL_REF T_LSHIFT immediate {
2077ec681f3Smrg                       new_instr($1); dst($2); label($4); shift($6);
2087ec681f3Smrg}
2097ec681f3Smrg|                  T_OP_MOV reg ',' T_LABEL_REF { new_instr($1); dst($2); label($4); }
2107ec681f3Smrg
2117ec681f3Smrgalu_2src_op:       T_OP_ADD       { new_instr($1); }
2127ec681f3Smrg|                  T_OP_ADDHI     { new_instr($1); }
2137ec681f3Smrg|                  T_OP_SUB       { new_instr($1); }
2147ec681f3Smrg|                  T_OP_SUBHI     { new_instr($1); }
2157ec681f3Smrg|                  T_OP_AND       { new_instr($1); }
2167ec681f3Smrg|                  T_OP_OR        { new_instr($1); }
2177ec681f3Smrg|                  T_OP_XOR       { new_instr($1); }
2187ec681f3Smrg|                  T_OP_SHL       { new_instr($1); }
2197ec681f3Smrg|                  T_OP_USHR      { new_instr($1); }
2207ec681f3Smrg|                  T_OP_ISHR      { new_instr($1); }
2217ec681f3Smrg|                  T_OP_ROT       { new_instr($1); }
2227ec681f3Smrg|                  T_OP_MUL8      { new_instr($1); }
2237ec681f3Smrg|                  T_OP_MIN       { new_instr($1); }
2247ec681f3Smrg|                  T_OP_MAX       { new_instr($1); }
2257ec681f3Smrg|                  T_OP_CMP       { new_instr($1); }
2267ec681f3Smrg
2277ec681f3Smrgalu_2src_instr:    alu_2src_op reg ',' reg ',' reg { dst($2); src1($4); src2($6); }
2287ec681f3Smrg|                  alu_2src_op reg ',' reg ',' immediate { dst($2); src1($4); immed($6); }
2297ec681f3Smrg
2307ec681f3Smrgalu_instr:         alu_2src_instr
2317ec681f3Smrg|                  alu_msb_instr
2327ec681f3Smrg|                  alu_not_instr
2337ec681f3Smrg|                  alu_mov_instr
2347ec681f3Smrg
2357ec681f3Smrgconfig_op:         T_OP_CWRITE    { new_instr($1); }
2367ec681f3Smrg|                  T_OP_CREAD     { new_instr($1); }
2377ec681f3Smrg|                  T_OP_LOAD      { new_instr($1); }
2387ec681f3Smrg|                  T_OP_STORE     { new_instr($1); }
2397ec681f3Smrg
2407ec681f3Smrgconfig_instr:      config_op reg ',' '[' reg '+' immediate ']' ',' immediate {
2417ec681f3Smrg                       src1($2); src2($5); immed($7); bit($10);
2427ec681f3Smrg}
2437ec681f3Smrg
2447ec681f3Smrgbranch_op:         T_OP_BRNE      { new_instr($1); }
2457ec681f3Smrg|                  T_OP_BREQ      { new_instr($1); }
2467ec681f3Smrg
2477ec681f3Smrgbranch_instr:      branch_op reg ',' T_BIT ',' T_LABEL_REF     { src1($2); bit($4); label($6); }
2487ec681f3Smrg|                  branch_op reg ',' immediate ',' T_LABEL_REF { src1($2); immed($4); label($6); }
2497ec681f3Smrg
2507ec681f3Smrgother_instr:       T_OP_CALL T_LABEL_REF { new_instr($1); label($2); }
2517ec681f3Smrg|                  T_OP_PREEMPTLEAVE T_LABEL_REF { new_instr($1); label($2); }
2527ec681f3Smrg|                  T_OP_SETSECURE reg ',' T_LABEL_REF { new_instr($1); src1($2); label($4); }
2537ec681f3Smrg|                  T_OP_RET              { new_instr($1); }
2547ec681f3Smrg|                  T_OP_IRET             { new_instr($1); }
2557ec681f3Smrg|                  T_OP_JUMP T_LABEL_REF { new_instr($1); label($2); }
2567ec681f3Smrg|                  T_OP_WAITIN           { new_instr($1); }
2577ec681f3Smrg|                  T_OP_NOP              { new_instr($1); }
2587ec681f3Smrg|                  T_LITERAL             { new_instr($1); literal($1); }
2597ec681f3Smrg
2607ec681f3Smrgreg:               T_REGISTER
2617ec681f3Smrg
2627ec681f3Smrgimmediate:         T_HEX
2637ec681f3Smrg|                  T_INT
2647ec681f3Smrg|                  T_CONTROL_REG
2657ec681f3Smrg|                  T_CONTROL_REG '+' immediate { $$ = $1 + $3; }
2667ec681f3Smrg
267