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