1/* 2 * Copyright (c) 2013 Rob Clark <robclark@freedesktop.org> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24%{ 25#define YYDEBUG 0 26 27#include <stdlib.h> 28#include <stdio.h> 29#include <string.h> 30#include <math.h> 31#include "asm.h" 32 33 34int yyget_lineno(void); 35 36#ifdef YYDEBUG 37int yydebug; 38#endif 39 40extern int yylex(void); 41typedef void *YY_BUFFER_STATE; 42extern YY_BUFFER_STATE yy_scan_string(const char *); 43extern void yy_delete_buffer(YY_BUFFER_STATE); 44 45int yyparse(void); 46 47void yyerror(const char *error); 48void yyerror(const char *error) 49{ 50 fprintf(stderr, "error at line %d: %s\n", yyget_lineno(), error); 51} 52 53static struct asm_instruction *instr; /* current instruction */ 54 55static void 56new_instr(int tok) 57{ 58 instr = next_instr(tok); 59} 60 61static void 62dst(int num) 63{ 64 instr->dst = num; 65} 66 67static void 68src1(int num) 69{ 70 instr->src1 = num; 71} 72 73static void 74src2(int num) 75{ 76 instr->src2 = num; 77} 78 79static void 80immed(int num) 81{ 82 instr->immed = num; 83 instr->has_immed = true; 84} 85 86static void 87shift(int num) 88{ 89 instr->shift = num; 90 instr->has_shift = true; 91} 92 93static void 94bit(int num) 95{ 96 instr->bit = num; 97 instr->has_bit = true; 98} 99 100static void 101literal(uint32_t num) 102{ 103 instr->literal = num; 104 instr->is_literal = true; 105} 106 107static void 108label(const char *str) 109{ 110 instr->label = str; 111} 112 113%} 114 115%union { 116 int tok; 117 uint32_t num; 118 const char *str; 119} 120 121%token <num> T_INT 122%token <num> T_HEX 123%token <num> T_CONTROL_REG 124%token <str> T_LABEL_DECL 125%token <str> T_LABEL_REF 126%token <num> T_LITERAL 127%token <num> T_BIT 128%token <num> T_REGISTER 129 130%token <tok> T_OP_NOP 131%token <tok> T_OP_ADD 132%token <tok> T_OP_ADDHI 133%token <tok> T_OP_SUB 134%token <tok> T_OP_SUBHI 135%token <tok> T_OP_AND 136%token <tok> T_OP_OR 137%token <tok> T_OP_XOR 138%token <tok> T_OP_NOT 139%token <tok> T_OP_SHL 140%token <tok> T_OP_USHR 141%token <tok> T_OP_ISHR 142%token <tok> T_OP_ROT 143%token <tok> T_OP_MUL8 144%token <tok> T_OP_MIN 145%token <tok> T_OP_MAX 146%token <tok> T_OP_CMP 147%token <tok> T_OP_MSB 148%token <tok> T_OP_MOV 149%token <tok> T_OP_CWRITE 150%token <tok> T_OP_CREAD 151%token <tok> T_OP_STORE 152%token <tok> T_OP_LOAD 153%token <tok> T_OP_BRNE 154%token <tok> T_OP_BREQ 155%token <tok> T_OP_RET 156%token <tok> T_OP_IRET 157%token <tok> T_OP_CALL 158%token <tok> T_OP_JUMP 159%token <tok> T_OP_WAITIN 160%token <tok> T_OP_PREEMPTLEAVE 161%token <tok> T_OP_SETSECURE 162%token <tok> T_LSHIFT 163%token <tok> T_REP 164%token <num> T_XMOV 165 166%type <num> reg 167%type <num> immediate 168 169%error-verbose 170 171%start instrs 172 173%% 174 175instrs: instr_or_label instrs 176| instr_or_label 177 178instr_or_label: instr_r 179| T_REP instr_r { instr->rep = true; } 180| branch_instr 181| other_instr 182| T_LABEL_DECL { decl_label($1); } 183 184/* instructions that can optionally have (rep) flag: */ 185instr_r: alu_instr 186| T_XMOV alu_instr { instr->xmov = $1; } 187| config_instr 188 189/* need to special case: 190 * - not (single src, possibly an immediate) 191 * - msb (single src, must be reg) 192 * - mov (single src, plus possibly a shift) 193 * from the other ALU instructions: 194 */ 195 196alu_msb_instr: T_OP_MSB reg ',' reg { new_instr($1); dst($2); src2($4); } 197 198alu_not_instr: T_OP_NOT reg ',' reg { new_instr($1); dst($2); src2($4); } 199| T_OP_NOT reg ',' immediate { new_instr($1); dst($2); immed($4); } 200 201alu_mov_instr: T_OP_MOV reg ',' reg { new_instr($1); dst($2); src1($4); } 202| T_OP_MOV reg ',' immediate T_LSHIFT immediate { 203 new_instr($1); dst($2); immed($4); shift($6); 204} 205| T_OP_MOV reg ',' immediate { new_instr($1); dst($2); immed($4); } 206| T_OP_MOV reg ',' T_LABEL_REF T_LSHIFT immediate { 207 new_instr($1); dst($2); label($4); shift($6); 208} 209| T_OP_MOV reg ',' T_LABEL_REF { new_instr($1); dst($2); label($4); } 210 211alu_2src_op: T_OP_ADD { new_instr($1); } 212| T_OP_ADDHI { new_instr($1); } 213| T_OP_SUB { new_instr($1); } 214| T_OP_SUBHI { new_instr($1); } 215| T_OP_AND { new_instr($1); } 216| T_OP_OR { new_instr($1); } 217| T_OP_XOR { new_instr($1); } 218| T_OP_SHL { new_instr($1); } 219| T_OP_USHR { new_instr($1); } 220| T_OP_ISHR { new_instr($1); } 221| T_OP_ROT { new_instr($1); } 222| T_OP_MUL8 { new_instr($1); } 223| T_OP_MIN { new_instr($1); } 224| T_OP_MAX { new_instr($1); } 225| T_OP_CMP { new_instr($1); } 226 227alu_2src_instr: alu_2src_op reg ',' reg ',' reg { dst($2); src1($4); src2($6); } 228| alu_2src_op reg ',' reg ',' immediate { dst($2); src1($4); immed($6); } 229 230alu_instr: alu_2src_instr 231| alu_msb_instr 232| alu_not_instr 233| alu_mov_instr 234 235config_op: T_OP_CWRITE { new_instr($1); } 236| T_OP_CREAD { new_instr($1); } 237| T_OP_LOAD { new_instr($1); } 238| T_OP_STORE { new_instr($1); } 239 240config_instr: config_op reg ',' '[' reg '+' immediate ']' ',' immediate { 241 src1($2); src2($5); immed($7); bit($10); 242} 243 244branch_op: T_OP_BRNE { new_instr($1); } 245| T_OP_BREQ { new_instr($1); } 246 247branch_instr: branch_op reg ',' T_BIT ',' T_LABEL_REF { src1($2); bit($4); label($6); } 248| branch_op reg ',' immediate ',' T_LABEL_REF { src1($2); immed($4); label($6); } 249 250other_instr: T_OP_CALL T_LABEL_REF { new_instr($1); label($2); } 251| T_OP_PREEMPTLEAVE T_LABEL_REF { new_instr($1); label($2); } 252| T_OP_SETSECURE reg ',' T_LABEL_REF { new_instr($1); src1($2); label($4); } 253| T_OP_RET { new_instr($1); } 254| T_OP_IRET { new_instr($1); } 255| T_OP_JUMP T_LABEL_REF { new_instr($1); label($2); } 256| T_OP_WAITIN { new_instr($1); } 257| T_OP_NOP { new_instr($1); } 258| T_LITERAL { new_instr($1); literal($1); } 259 260reg: T_REGISTER 261 262immediate: T_HEX 263| T_INT 264| T_CONTROL_REG 265| T_CONTROL_REG '+' immediate { $$ = $1 + $3; } 266 267