%option noyywrap noinput nounput %option 8bit reentrant bison-bridge %option warn nodefault %option bison-locations %{ /* * Copyright(c) 2019-2022 rev.ng Labs Srl. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #include #include "hex_regs.h" #include "idef-parser.h" #include "idef-parser.tab.h" /* Keep track of scanner position for error message printout */ #define YY_USER_ACTION yylloc->first_column = yylloc->last_column; \ for (int i = 0; yytext[i] != '\0'; i++) { \ yylloc->last_column++; \ } /* Global Error Counter */ int error_count; %} /* Definitions */ DIGIT [0-9] LOWER_ID [a-z] UPPER_ID [A-Z] ID LOWER_ID|UPPER_ID INST_NAME [A-Z]+[0-9]_([A-Za-z]|[0-9]|_)+ HEX_DIGIT [0-9a-fA-F] REG_ID_32 e|s|d|t|u|v|x|y REG_ID_64 ee|ss|dd|tt|uu|vv|xx|yy SYS_ID_32 s|d SYS_ID_64 ss|dd PRED_ID d|s|t|u|v|e|x|x IMM_ID r|s|S|u|U VAR_ID [a-zA-Z_][a-zA-Z0-9_]* SIGN_ID s|u STRING_LIT \"(\\.|[^"\\])*\" /* Tokens */ %% [ \t\f\v]+ { /* Ignore whitespaces. */ } [\n\r]+ { /* Ignore newlines. */ } ^#.*$ { /* Ignore linemarkers. */ } {INST_NAME} { yylval->string = g_string_new(yytext); return INAME; } "fFLOAT" | "fUNFLOAT" | "fDOUBLE" | "fUNDOUBLE" | "0.0" | "0x1.0p52" | "0x1.0p-52" { return FAIL; } "in" { return IN; } "R"{REG_ID_32}"V" { yylval->rvalue.type = REGISTER_ARG; yylval->rvalue.reg.type = GENERAL_PURPOSE; yylval->rvalue.reg.id = yytext[1]; yylval->rvalue.reg.bit_width = 32; yylval->rvalue.bit_width = 32; yylval->rvalue.is_dotnew = false; yylval->rvalue.signedness = SIGNED; return REG; } "R"{REG_ID_64}"V" { yylval->rvalue.type = REGISTER_ARG; yylval->rvalue.reg.type = GENERAL_PURPOSE; yylval->rvalue.reg.id = yytext[1]; yylval->rvalue.reg.bit_width = 64; yylval->rvalue.bit_width = 64; yylval->rvalue.is_dotnew = false; yylval->rvalue.signedness = SIGNED; return REG; } "MuV" { yylval->rvalue.type = REGISTER_ARG; yylval->rvalue.reg.type = MODIFIER; yylval->rvalue.reg.id = 'u'; yylval->rvalue.reg.bit_width = 32; yylval->rvalue.bit_width = 32; yylval->rvalue.signedness = SIGNED; return REG; } "C"{REG_ID_32}"V" { yylval->rvalue.type = REGISTER_ARG; yylval->rvalue.reg.type = CONTROL; yylval->rvalue.reg.id = yytext[1]; yylval->rvalue.reg.bit_width = 32; yylval->rvalue.bit_width = 32; yylval->rvalue.is_dotnew = false; yylval->rvalue.signedness = SIGNED; return REG; } "C"{REG_ID_64}"V" { yylval->rvalue.type = REGISTER_ARG; yylval->rvalue.reg.type = CONTROL; yylval->rvalue.reg.id = yytext[1]; yylval->rvalue.reg.bit_width = 64; yylval->rvalue.bit_width = 64; yylval->rvalue.is_dotnew = false; yylval->rvalue.signedness = SIGNED; return REG; } {IMM_ID}"iV" { yylval->rvalue.type = IMMEDIATE; yylval->rvalue.signedness = SIGNED; yylval->rvalue.imm.type = VARIABLE; yylval->rvalue.imm.id = yytext[0]; yylval->rvalue.bit_width = 32; yylval->rvalue.is_dotnew = false; return IMM; } "P"{PRED_ID}"V" { yylval->rvalue.type = PREDICATE; yylval->rvalue.pred.id = yytext[1]; yylval->rvalue.bit_width = 32; yylval->rvalue.is_dotnew = false; yylval->rvalue.signedness = SIGNED; return PRED; } "P"{PRED_ID}"N" { yylval->rvalue.type = PREDICATE; yylval->rvalue.pred.id = yytext[1]; yylval->rvalue.bit_width = 32; yylval->rvalue.is_dotnew = true; yylval->rvalue.signedness = SIGNED; return PRED; } "IV1DEAD()" | "fPAUSE(uiV);" { return ';'; } "+=" { return INC; } "-=" { return DEC; } "++" { return PLUSPLUS; } "&=" { return ANDA; } "|=" { return ORA; } "^=" { return XORA; } "<<" { return ASL; } ">>" { return ASR; } ">>>" { return LSR; } "==" { return EQ; } "!=" { return NEQ; } "<=" { return LTE; } ">=" { return GTE; } "&&" { return ANDL; } "else" { return ELSE; } "for" { return FOR; } "fREAD_IREG" { return ICIRC; } "fPART1" { return PART1; } "if" { return IF; } "fFRAME_SCRAMBLE" { return FSCR; } "fFRAME_UNSCRAMBLE" { return FSCR; } "fFRAMECHECK" { return FCHK; } "Constant_extended" { return CONSTEXT; } "fCL1_"{DIGIT} { return LOCNT; } "fbrev" { return BREV; } "fSXTN" { return SXT; } "fZXTN" { return ZXT; } "fDF_MAX" | "fSF_MAX" | "fMAX" { return MAX; } "fDF_MIN" | "fSF_MIN" | "fMIN" { return MIN; } "fABS" { return ABS; } "fRNDN" { return ROUND; } "fCRND" { return CROUND; } "fCRNDN" { return CROUND; } "fPM_CIRI" { return CIRCADD; } "fPM_CIRR" { return CIRCADD; } "fCOUNTONES_"{DIGIT} { return COUNTONES; } "fSATN" { yylval->sat.signedness = SIGNED; return SAT; } "fSATUN" { yylval->sat.signedness = UNSIGNED; return SAT; } "fCONSTLL" { yylval->cast.bit_width = 64; yylval->cast.signedness = SIGNED; return CAST; } "fSE32_64" { yylval->cast.bit_width = 64; yylval->cast.signedness = SIGNED; return CAST; } "fCAST4_4u" { yylval->cast.bit_width = 32; yylval->cast.signedness = UNSIGNED; return CAST; } "fCAST4_8s" { yylval->cast.bit_width = 64; yylval->cast.signedness = SIGNED; return CAST; } "fCAST4_8u" { return CAST4_8U; } "fCAST4u" { yylval->cast.bit_width = 32; yylval->cast.signedness = UNSIGNED; return CAST; } "fNEWREG" | "fCAST4_4s" | "fCAST4s" { yylval->cast.bit_width = 32; yylval->cast.signedness = SIGNED; return CAST; } "fCAST8_8u" { yylval->cast.bit_width = 64; yylval->cast.signedness = UNSIGNED; return CAST; } "fCAST8u" { yylval->cast.bit_width = 64; yylval->cast.signedness = UNSIGNED; return CAST; } "fCAST8_8s" | "fCAST8s" { yylval->cast.bit_width = 64; yylval->cast.signedness = SIGNED; return CAST; } "fGETBIT" { yylval->extract.bit_width = 1; yylval->extract.storage_bit_width = 1; yylval->extract.signedness = UNSIGNED; return EXTRACT; } "fGETBYTE" { yylval->extract.bit_width = 8; yylval->extract.storage_bit_width = 8; yylval->extract.signedness = SIGNED; return EXTRACT; } "fGETUBYTE" { yylval->extract.bit_width = 8; yylval->extract.storage_bit_width = 8; yylval->extract.signedness = UNSIGNED; return EXTRACT; } "fGETHALF" { yylval->extract.bit_width = 16; yylval->extract.storage_bit_width = 16; yylval->extract.signedness = SIGNED; return EXTRACT; } "fGETUHALF" { yylval->extract.bit_width = 16; yylval->extract.storage_bit_width = 16; yylval->extract.signedness = UNSIGNED; return EXTRACT; } "fGETWORD" { yylval->extract.bit_width = 32; yylval->extract.storage_bit_width = 64; yylval->extract.signedness = SIGNED; return EXTRACT; } "fGETUWORD" { yylval->extract.bit_width = 32; yylval->extract.storage_bit_width = 64; yylval->extract.signedness = UNSIGNED; return EXTRACT; } "fEXTRACTU_RANGE" { return EXTRANGE; } "fSETBIT" { yylval->cast.bit_width = 1; yylval->cast.signedness = SIGNED; return DEPOSIT; } "fSETBYTE" { yylval->cast.bit_width = 8; yylval->cast.signedness = SIGNED; return DEPOSIT; } "fSETHALF" { yylval->cast.bit_width = 16; yylval->cast.signedness = SIGNED; return SETHALF; } "fSETWORD" { yylval->cast.bit_width = 32; yylval->cast.signedness = SIGNED; return DEPOSIT; } "fINSERT_BITS" { return INSBITS; } "fSETBITS" { return SETBITS; } "fMPY16UU" { yylval->mpy.first_bit_width = 16; yylval->mpy.second_bit_width = 16; yylval->mpy.first_signedness = UNSIGNED; yylval->mpy.second_signedness = UNSIGNED; return MPY; } "fMPY16SU" { yylval->mpy.first_bit_width = 16; yylval->mpy.second_bit_width = 16; yylval->mpy.first_signedness = SIGNED; yylval->mpy.second_signedness = UNSIGNED; return MPY; } "fMPY16SS" { yylval->mpy.first_bit_width = 16; yylval->mpy.second_bit_width = 16; yylval->mpy.first_signedness = SIGNED; yylval->mpy.second_signedness = SIGNED; return MPY; } "fMPY32UU" { yylval->mpy.first_bit_width = 32; yylval->mpy.second_bit_width = 32; yylval->mpy.first_signedness = UNSIGNED; yylval->mpy.second_signedness = UNSIGNED; return MPY; } "fMPY32SU" { yylval->mpy.first_bit_width = 32; yylval->mpy.second_bit_width = 32; yylval->mpy.first_signedness = SIGNED; yylval->mpy.second_signedness = UNSIGNED; return MPY; } "fSFMPY" | "fMPY32SS" { yylval->mpy.first_bit_width = 32; yylval->mpy.second_bit_width = 32; yylval->mpy.first_signedness = SIGNED; yylval->mpy.second_signedness = SIGNED; return MPY; } "fMPY3216SS" { yylval->mpy.first_bit_width = 32; yylval->mpy.second_bit_width = 16; yylval->mpy.first_signedness = SIGNED; yylval->mpy.second_signedness = SIGNED; return MPY; } "fMPY3216SU" { yylval->mpy.first_bit_width = 32; yylval->mpy.second_bit_width = 16; yylval->mpy.first_signedness = SIGNED; yylval->mpy.second_signedness = UNSIGNED; return MPY; } "fNEWREG_ST" | "fIMMEXT" | "fMUST_IMMEXT" | "fPASS" | "fECHO" { return IDENTITY; } "(size8u_t)" { yylval->cast.bit_width = 64; yylval->cast.signedness = UNSIGNED; return CAST; } "(unsigned int)" { yylval->cast.bit_width = 32; yylval->cast.signedness = UNSIGNED; return CAST; } "fREAD_PC()" | "PC" { return PC; } "fREAD_NPC()" | "NPC" { return NPC; } "fGET_LPCFG" | "USR.LPCFG" { return LPCFG; } "LOAD_CANCEL(EA)" { return LOAD_CANCEL; } "STORE_CANCEL(EA)" | "CANCEL" { return CANCEL; } "N"{LOWER_ID}"N" { yylval->rvalue.type = REGISTER_ARG; yylval->rvalue.reg.type = DOTNEW; yylval->rvalue.reg.id = yytext[1]; yylval->rvalue.reg.bit_width = 32; yylval->rvalue.bit_width = 32; yylval->rvalue.signedness = UNSIGNED; return REG; } "fREAD_SP()" | "SP" { yylval->rvalue.type = REGISTER; yylval->rvalue.reg.type = GENERAL_PURPOSE; yylval->rvalue.reg.id = HEX_REG_SP; yylval->rvalue.reg.bit_width = 32; yylval->rvalue.bit_width = 32; yylval->rvalue.signedness = UNSIGNED; return REG; } "fREAD_FP()" | "FP" { yylval->rvalue.type = REGISTER; yylval->rvalue.reg.type = GENERAL_PURPOSE; yylval->rvalue.reg.id = HEX_REG_FP; yylval->rvalue.reg.bit_width = 32; yylval->rvalue.bit_width = 32; yylval->rvalue.signedness = UNSIGNED; return REG; } "fREAD_LR()" | "LR" { yylval->rvalue.type = REGISTER; yylval->rvalue.reg.type = GENERAL_PURPOSE; yylval->rvalue.reg.id = HEX_REG_LR; yylval->rvalue.reg.bit_width = 32; yylval->rvalue.bit_width = 32; yylval->rvalue.signedness = UNSIGNED; return REG; } "fREAD_GP()" | "GP" { yylval->rvalue.type = REGISTER; yylval->rvalue.reg.type = CONTROL; yylval->rvalue.reg.id = HEX_REG_GP; yylval->rvalue.reg.bit_width = 32; yylval->rvalue.bit_width = 32; yylval->rvalue.signedness = UNSIGNED; return REG; } "fREAD_LC"[01] { yylval->rvalue.type = REGISTER; yylval->rvalue.reg.type = CONTROL; yylval->rvalue.reg.id = HEX_REG_LC0 + (yytext[8] - '0') * 2; yylval->rvalue.reg.bit_width = 32; yylval->rvalue.bit_width = 32; yylval->rvalue.signedness = UNSIGNED; return REG; } "LC"[01] { yylval->rvalue.type = REGISTER; yylval->rvalue.reg.type = CONTROL; yylval->rvalue.reg.id = HEX_REG_LC0 + (yytext[2] - '0') * 2; yylval->rvalue.reg.bit_width = 32; yylval->rvalue.bit_width = 32; yylval->rvalue.signedness = UNSIGNED; return REG; } "fREAD_SA"[01] { yylval->rvalue.type = REGISTER; yylval->rvalue.reg.type = CONTROL; yylval->rvalue.reg.id = HEX_REG_SA0 + (yytext[8] - '0') * 2; yylval->rvalue.reg.bit_width = 32; yylval->rvalue.bit_width = 32; yylval->rvalue.signedness = UNSIGNED; return REG; } "SA"[01] { yylval->rvalue.type = REGISTER; yylval->rvalue.reg.type = CONTROL; yylval->rvalue.reg.id = HEX_REG_SA0 + (yytext[2] - '0') * 2; yylval->rvalue.reg.bit_width = 32; yylval->rvalue.bit_width = 32; yylval->rvalue.signedness = UNSIGNED; return REG; } "fREAD_P0()" { yylval->rvalue.type = PREDICATE; yylval->rvalue.pred.id = '0'; yylval->rvalue.bit_width = 32; return PRED; } [pP]{DIGIT} { yylval->rvalue.type = PREDICATE; yylval->rvalue.pred.id = yytext[1]; yylval->rvalue.bit_width = 32; yylval->rvalue.is_dotnew = false; return PRED; } [pP]{DIGIT}[nN] { yylval->rvalue.type = PREDICATE; yylval->rvalue.pred.id = yytext[1]; yylval->rvalue.bit_width = 32; yylval->rvalue.is_dotnew = true; return PRED; } "fLSBNEW" { return LSBNEW; } "N" { yylval->rvalue.type = IMMEDIATE; yylval->rvalue.bit_width = 32; yylval->rvalue.imm.type = VARIABLE; yylval->rvalue.imm.id = 'N'; return IMM; } "i" { yylval->rvalue.type = IMMEDIATE; yylval->rvalue.bit_width = 32; yylval->rvalue.signedness = SIGNED; yylval->rvalue.imm.type = I; return IMM; } {SIGN_ID} { if (yytext[0] == 'u') { yylval->signedness = UNSIGNED; } else { yylval->signedness = SIGNED; } return SIGN; } "0x"{HEX_DIGIT}+ | {DIGIT}+ { yylval->rvalue.type = IMMEDIATE; yylval->rvalue.bit_width = 32; yylval->rvalue.signedness = SIGNED; yylval->rvalue.imm.type = VALUE; yylval->rvalue.imm.value = strtoull(yytext, NULL, 0); return IMM; } "0x"{HEX_DIGIT}+"ULL" | {DIGIT}+"ULL" { yylval->rvalue.type = IMMEDIATE; yylval->rvalue.bit_width = 64; yylval->rvalue.signedness = UNSIGNED; yylval->rvalue.imm.type = VALUE; yylval->rvalue.imm.value = strtoull(yytext, NULL, 0); return IMM; } "fLOAD" { return LOAD; } "fSTORE" { return STORE; } "fROTL" { return ROTL; } "fCARRY_FROM_ADD" { return CARRY_FROM_ADD; } "fADDSAT64" { return ADDSAT64; } "size"[1248][us]"_t" { /* Handles "size_t" variants of int types */ const unsigned int bits_per_byte = 8; const unsigned int bytes = yytext[4] - '0'; yylval->rvalue.bit_width = bits_per_byte * bytes; if (yytext[5] == 'u') { yylval->rvalue.signedness = UNSIGNED; } else { yylval->rvalue.signedness = SIGNED; } return TYPE_SIZE_T; } "unsigned" { return TYPE_UNSIGNED; } "long" { return TYPE_LONG; } "int" { return TYPE_INT; } "const" { /* Emit no token */ } {VAR_ID} { /* Variable name, we adopt the C names convention */ yylval->rvalue.type = VARID; yylval->rvalue.var.name = g_string_new(yytext); /* Default to an unknown signedness and 0 width. */ yylval->rvalue.bit_width = 0; yylval->rvalue.signedness = UNKNOWN_SIGNEDNESS; return VAR; } "fatal("{STRING_LIT}")" { /* Emit no token */ } "fHINTJR(RsV)" { /* Emit no token */ } . { return yytext[0]; } %%