start = statement [';'] $; statement = 'if' expr0 'then' statement {'else' statement} | "UNPREDICTABLE" | "UNDEFINED" | "NOT_PERMITTED" | "NOP" | "nop" | "SEE" whatever | tuple '=' expr0 | ident '=' 'if' expr0 'then' expr0 'else' expr0 | expr0 '=' expr0; # tuples tuple = '(' ('-'|expr0) { ',' ('-'|expr0) }+ ')'; # could use kleen star here instead of alternative rule, but I don't # want to get back empty closures expr0 = expr1 {('EOR' | '+' | '-' | '&&' | '||') expr1}+ | expr1; expr1 = expr2 {('*'|'/'|'<<'|'>>'|'DIV'|'XOR') expr2}+ | expr2 {('==' | '!=' | '<=' | '>=' | '<' | '>') expr2}+ | expr2; expr2 = func_call | expr3; expr3 = builtin_value | sliceable | (ident|number|bits) {':'(ident|number|bits)}* | tuple | '(' expr0 ')' | '!' expr0; number = /\d+/; bits = /'[01]+'/; ident = /[a-zA-Z][\.\w]*/; whatever = /.*/; # the variables that can have bit slices ... these are made separate # because the intersect with the greater-than, less-than comparisons sliceable = 'index_align<' number ':' number '>' | 'index_align<' number '>' | 'align<' number '>' | 'mask<' number '>' | 'imod<' number '>' | 'imm6<' number '>' | 'imm6<' number ':' number '>' | 'imm8<' number '>' | 'Vd<' number '>' | 'Vn<' number '>' | 'Vm<' number '>' | 'Vm<' number ':' number '>' | 'cc<' number '>' | 'cmode<' number '>' | 'cmode<' number ':' number '>'; builtin_value = 'TRUE' | 'FALSE' | 'registers<' (number|ident) '>' | 'list<' (number|ident) '>' | 'cond<' number ':' number '>' | 'cond<' expr0 '>' | 'SRType_LSL' | 'SRType_LSR' | 'SRType_ASR' | 'SRType_ROR' | 'SRType_RRX' | 'InstrSet_ThumbEE' | 'ARM_GRP_INVALID' | 'ARM_GRP_JUMP' | 'ARM_GRP_CRYPT' | 'ARM_GRP_DATABARRIER' | 'ARM_GRP_DIVIDE' | 'ARM_GRP_FPARMV8' | 'ARM_GRP_MULTPRO' | 'ARM_GRP_NEON' | 'ARM_GRP_T2EXTRACTPACK' | 'ARM_GRP_THUMB2DSP' | 'ARM_GRP_TRUSTZONE' | 'ARM_GRP_V4T' | 'ARM_GRP_V5T' | 'ARM_GRP_V5TE' | 'ARM_GRP_V6' | 'ARM_GRP_V6T2' | 'ARM_GRP_V7' | 'ARM_GRP_V8' | 'ARM_GRP_VFP2' | 'ARM_GRP_VFP3' | 'ARM_GRP_VFP4' | 'ARM_GRP_ARM' | 'ARM_GRP_MCLASS' | 'ARM_GRP_NOTMCLASS' | 'ARM_GRP_THUMB' | 'ARM_GRP_THUMB1ONLY' | 'ARM_GRP_THUMB2' | 'ARM_GRP_PREV8' | 'ARM_GRP_FPVMLX' | 'ARM_GRP_MULOPS' | 'ARM_GRP_CRC' | 'ARM_GRP_DPVFP' | 'ARM_GRP_V6M'; # function calls func_call = bitcount | badreg | consistent | decodeimmshift | thumbexpandimm | thumbexpandimm_c | advsimdexpandimm | vfpexpandimm | uint | zeroextend | zeros | initblock | lastinitblock | archversion | currentinstrset | signextend | not | issecure; bitcount = 'BitCount(' expr0 ')'; badreg = 'BadReg(' expr0 ')'; consistent = 'Consistent(' expr0 ')'; decodeimmshift = 'DecodeImmShift(' expr0 ',' expr0 ')'; thumbexpandimm = 'ThumbExpandImm(' expr0 ')'; thumbexpandimm_c = 'ThumbExpandImm_C(' expr0 ',' expr0 ')'; advsimdexpandimm = 'AdvSIMDExpandImm(' expr0 ',' expr0 ',' expr0 ',' expr0 ')'; vfpexpandimm = 'VFPExpandImm(' expr0 ',' expr0 ',' expr0 ')'; uint = 'UInt(' expr0 ')'; zeroextend = 'ZeroExtend(' expr0 ',' expr0 ')'; zeros = 'Zeros(' expr0 ')'; initblock = 'InITBlock()'; lastinitblock = 'LastInITBlock()'; archversion = 'ArchVersion()'; currentinstrset = 'CurrentInstrSet()'; signextend = 'SignExtend(' expr3 ', 32)'; not = 'NOT(' expr0 ')'; issecure = 'IsSecure()';