// MMIXAL Grammar for Pest Parser
// Based on TAOCP Vol 1 Fascicle 1 - MMIX Assembly Language
WHITESPACE = _{ " " | "\t" | "\r" }
COMMENT = _{ (";" | "%") ~ (!"\n" ~ ANY)* }
// Symbols/identifiers for labels and symbolic names
symbol = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }
// Numeric literals: decimal, hex (#... or 0x...), octal (0...)
// @ represents current location
at_symbol = @{ "@" }
hex_literal = @{ ("#" | "0x" | "0X") ~ ASCII_HEX_DIGIT+ }
oct_literal = @{ "0" ~ ASCII_OCT_DIGIT+ }
dec_literal = @{ ASCII_DIGIT+ }
number_literal = { at_symbol | hex_literal | oct_literal | dec_literal }
// Expression value: can be a numeric literal or a symbol (label/constant)
expr_value = { number_literal | symbol }
// Registers: $0-$255 or symbolic names from IS directive
register_num = @{ "$" ~ ASCII_DIGIT+ }
register = { register_num | symbol }
// Identifiers (kept for backward compatibility in some contexts)
identifier = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }
// Label definition: symbol optionally followed by colon
// In standard MMIXAL, labels can appear with or without colons
label_def = { symbol ~ ":"? }
// String literal for BYTE directive
string_literal = @{ "\"" ~ (!"\"" ~ ANY)* ~ "\"" }
// Data directives (with or without leading dot) - must be complete words
directive_byte = @{ (^"BYTE" | ^".BYTE") ~ !ASCII_ALPHANUMERIC }
directive_wyde = @{ (^"WYDE" | ^".WYDE") ~ !ASCII_ALPHANUMERIC }
directive_tetra = @{ (^"TETRA" | ^".TETRA") ~ !ASCII_ALPHANUMERIC }
directive_octa = @{ (^"OCTA" | ^".OCTA" | ^"QUAD" | ^".QUAD") ~ !ASCII_ALPHANUMERIC }
// Control directives - must be complete words, not prefixes
directive_loc = @{ ^"LOC" ~ !ASCII_ALPHANUMERIC }
directive_is = @{ ^"IS" ~ !ASCII_ALPHANUMERIC }
directive_greg = @{ ^"GREG" ~ !ASCII_ALPHANUMERIC }
// BYTE can take strings or comma-separated values
byte_value = { string_literal | expr_value }
byte_values = { byte_value ~ ("," ~ byte_value)* }
data_directive = {
directive_byte ~ byte_values |
directive_wyde ~ expr_value |
directive_tetra ~ expr_value |
directive_octa ~ expr_value
}
greg_directive = { directive_greg ~ expr_value }
loc_directive = { directive_loc ~ expr_value }
is_directive = { symbol ~ directive_is ~ (register | expr_value) }
// Group all directives under a single rule
// Note: debug directives are handled by preprocessor, not grammar
directive = {
is_directive
| loc_directive
| greg_directive
| data_directive
}
// A line can have: [label] [instruction|directive]
// Labels may optionally end with colon
// IS directive is special - identifier IS value (no label separator)
// Order matters: try directive first (which includes is_directive), then label+content
statement = {
directive
| instruction
| label_def ~ (instruction | directive)?
}
mnemonic_setmh = { ^"SETMH" }
mnemonic_setml = { ^"SETML" }
mnemonic_setl = { ^"SETL" }
mnemonic_seth = { ^"SETH" }
mnemonic_seti = { ^"SETI" }
mnemonic_set = { ^"SET" }
mnemonic_incl = { ^"INCL" }
mnemonic_inch = { ^"INCH" }
mnemonic_incmh = { ^"INCMH" }
mnemonic_incml = { ^"INCML" }
mnemonic_orh = { ^"ORH" }
mnemonic_ormh = { ^"ORMH" }
mnemonic_orml = { ^"ORML" }
mnemonic_orl = { ^"ORL" }
mnemonic_andnh = { ^"ANDNH" }
mnemonic_andnmh = { ^"ANDNMH" }
mnemonic_andnml = { ^"ANDNML" }
mnemonic_andnl = { ^"ANDNL" }
// Load/Store instructions - ordered longest first
mnemonic_ldbui = { ^"LDBUI" }
mnemonic_ldbu = { ^"LDBU" }
mnemonic_ldbi = { ^"LDBI" }
mnemonic_ldb = { ^"LDB" }
mnemonic_ldwui = { ^"LDWUI" }
mnemonic_ldwu = { ^"LDWU" }
mnemonic_ldwi = { ^"LDWI" }
mnemonic_ldw = { ^"LDW" }
mnemonic_ldtui = { ^"LDTUI" }
mnemonic_ldtu = { ^"LDTU" }
mnemonic_ldti = { ^"LDTI" }
mnemonic_ldt = { ^"LDT" }
mnemonic_ldoui = { ^"LDOUI" }
mnemonic_ldou = { ^"LDOU" }
mnemonic_ldoi = { ^"LDOI" }
mnemonic_ldo = { ^"LDO" }
mnemonic_ldai = { ^"LDAI" }
mnemonic_lda = { ^"LDA" }
mnemonic_stbui = { ^"STBUI" }
mnemonic_stbu = { ^"STBU" }
mnemonic_stbi = { ^"STBI" }
mnemonic_stb = { ^"STB" }
mnemonic_stwui = { ^"STWUI" }
mnemonic_stwu = { ^"STWU" }
mnemonic_stwi = { ^"STWI" }
mnemonic_stw = { ^"STW" }
mnemonic_sttui = { ^"STTUI" }
mnemonic_sttu = { ^"STTU" }
mnemonic_stti = { ^"STTI" }
mnemonic_stt = { ^"STT" }
mnemonic_stoui = { ^"STOUI" }
mnemonic_stou = { ^"STOU" }
mnemonic_stoi = { ^"STOI" }
mnemonic_sto = { ^"STO" }
// Arithmetic instructions - ordered longest first
mnemonic_16addui = { ^"16ADDUI" }
mnemonic_16addu = { ^"16ADDU" }
mnemonic_8addui = { ^"8ADDUI" }
mnemonic_8addu = { ^"8ADDU" }
mnemonic_4addui = { ^"4ADDUI" }
mnemonic_4addu = { ^"4ADDU" }
mnemonic_2addui = { ^"2ADDUI" }
mnemonic_2addu = { ^"2ADDU" }
mnemonic_addui = { ^"ADDUI" }
mnemonic_addu = { ^"ADDU" }
mnemonic_addi = { ^"ADDI" }
mnemonic_add = { ^"ADD" }
mnemonic_subui = { ^"SUBUI" }
mnemonic_subu = { ^"SUBU" }
mnemonic_subi = { ^"SUBI" }
mnemonic_sub = { ^"SUB" }
mnemonic_negui = { ^"NEGUI" }
mnemonic_negu = { ^"NEGU" }
mnemonic_negi = { ^"NEGI" }
mnemonic_neg = { ^"NEG" }
mnemonic_mului = { ^"MULUI" }
mnemonic_mulu = { ^"MULU" }
mnemonic_muli = { ^"MULI" }
mnemonic_mul = { ^"MUL" }
mnemonic_divui = { ^"DIVUI" }
mnemonic_divu = { ^"DIVU" }
mnemonic_divi = { ^"DIVI" }
mnemonic_div = { ^"DIV" }
// Comparison instructions - ordered longest first
mnemonic_cmpui = { ^"CMPUI" }
mnemonic_cmpu = { ^"CMPU" }
mnemonic_cmpi = { ^"CMPI" }
mnemonic_cmp = { ^"CMP" }
// Floating point instructions - ordered longest first
mnemonic_sflotui = { ^"SFLOTUI" }
mnemonic_sflotu = { ^"SFLOTU" }
mnemonic_sfloti = { ^"SFLOTI" }
mnemonic_sflot = { ^"SFLOT" }
mnemonic_flotui = { ^"FLOTUI" }
mnemonic_flotu = { ^"FLOTU" }
mnemonic_floti = { ^"FLOTI" }
mnemonic_flot = { ^"FLOT" }
mnemonic_fixu = { ^"FIXU" }
mnemonic_fix = { ^"FIX" }
mnemonic_fsqrt = { ^"FSQRT" }
mnemonic_fint = { ^"FINT" }
mnemonic_frem = { ^"FREM" }
mnemonic_fmul = { ^"FMUL" }
mnemonic_fdiv = { ^"FDIV" }
mnemonic_fadd = { ^"FADD" }
mnemonic_fsub = { ^"FSUB" }
mnemonic_fcmp = { ^"FCMP" }
mnemonic_feql = { ^"FEQL" }
mnemonic_fun = { ^"FUN" }
// Bitwise operations (§10) - ordered longest first for exact matching
mnemonic_andni = { ^"ANDNI" }
mnemonic_andn = { ^"ANDN" }
mnemonic_andi = { ^"ANDI" }
mnemonic_and = { ^"AND" }
mnemonic_orni = { ^"ORNI" }
mnemonic_orn = { ^"ORN" }
mnemonic_ori = { ^"ORI" }
mnemonic_or = { ^"OR" }
mnemonic_xori = { ^"XORI" }
mnemonic_xor = { ^"XOR" }
mnemonic_nandi = { ^"NANDI" }
mnemonic_nand = { ^"NAND" }
mnemonic_nxori = { ^"NXORI" }
mnemonic_nxor = { ^"NXOR" }
mnemonic_nori = { ^"NORI" }
mnemonic_nor = { ^"NOR" }
mnemonic_muxi = { ^"MUXI" }
mnemonic_mux = { ^"MUX" }
// Conditional set instructions - ordered longest first
mnemonic_csnni = { ^"CSNNI" }
mnemonic_csnzi = { ^"CSNZI" }
mnemonic_csnpi = { ^"CSNPI" }
mnemonic_csodi = { ^"CSODI" }
mnemonic_csevi = { ^"CSEVI" }
mnemonic_csni = { ^"CSNI" }
mnemonic_cszi = { ^"CSZI" }
mnemonic_cspi = { ^"CSPI" }
mnemonic_csnn = { ^"CSNN" }
mnemonic_csnz = { ^"CSNZ" }
mnemonic_csnp = { ^"CSNP" }
mnemonic_csod = { ^"CSOD" }
mnemonic_csev = { ^"CSEV" }
mnemonic_csn = { ^"CSN" }
mnemonic_csz = { ^"CSZ" }
mnemonic_csp = { ^"CSP" }
// Zero or set instructions - ordered longest first
mnemonic_zsnni = { ^"ZSNNI" }
mnemonic_zsnzi = { ^"ZSNZI" }
mnemonic_zsnpi = { ^"ZSNPI" }
mnemonic_zsodi = { ^"ZSODI" }
mnemonic_zsevi = { ^"ZSEVI" }
mnemonic_zsni = { ^"ZSNI" }
mnemonic_zszi = { ^"ZSZI" }
mnemonic_zspi = { ^"ZSPI" }
mnemonic_zsnn = { ^"ZSNN" }
mnemonic_zsnz = { ^"ZSNZ" }
mnemonic_zsnp = { ^"ZSNP" }
mnemonic_zsod = { ^"ZSOD" }
mnemonic_zsev = { ^"ZSEV" }
mnemonic_zsn = { ^"ZSN" }
mnemonic_zsz = { ^"ZSZ" }
mnemonic_zsp = { ^"ZSP" }
// Bit fiddling operations (§11-12) - ordered longest first
mnemonic_bdifi = { ^"BDIFI" }
mnemonic_bdif = { ^"BDIF" }
mnemonic_wdifi = { ^"WDIFI" }
mnemonic_wdif = { ^"WDIF" }
mnemonic_tdifi = { ^"TDIFI" }
mnemonic_tdif = { ^"TDIF" }
mnemonic_odifi = { ^"ODIFI" }
mnemonic_odif = { ^"ODIF" }
mnemonic_saddi = { ^"SADDI" }
mnemonic_sadd = { ^"SADD" }
mnemonic_mxori = { ^"MXORI" }
mnemonic_mxor = { ^"MXOR" }
mnemonic_mori = { ^"MORI" }
mnemonic_mor = { ^"MOR" }
// Shift instructions (§14) - ordered longest first
mnemonic_slui = { ^"SLUI" }
mnemonic_slu = { ^"SLU" }
mnemonic_sli = { ^"SLI" }
mnemonic_sl = { ^"SL" }
mnemonic_srui = { ^"SRUI" }
mnemonic_sru = { ^"SRU" }
mnemonic_sri = { ^"SRI" }
mnemonic_sr = { ^"SR" }
// Branch/Jump instructions - ordered longest first
mnemonic_pbodb = { ^"PBODB" }
mnemonic_pbnnb = { ^"PBNNB" }
mnemonic_pbnzb = { ^"PBNZB" }
mnemonic_pbnpb = { ^"PBNPB" }
mnemonic_pbevb = { ^"PBEVB" }
mnemonic_pbnb = { ^"PBNB" }
mnemonic_pbzb = { ^"PBZB" }
mnemonic_pbpb = { ^"PBPB" }
mnemonic_pbod = { ^"PBOD" }
mnemonic_pbnn = { ^"PBNN" }
mnemonic_pbnz = { ^"PBNZ" }
mnemonic_pbnp = { ^"PBNP" }
mnemonic_pbev = { ^"PBEV" }
mnemonic_pbn = { ^"PBN" }
mnemonic_pbz = { ^"PBZ" }
mnemonic_pbp = { ^"PBP" }
mnemonic_bodb = { ^"BODB" }
mnemonic_bnnb = { ^"BNNB" }
mnemonic_bnzb = { ^"BNZB" }
mnemonic_bnpb = { ^"BNPB" }
mnemonic_bevb = { ^"BEVB" }
mnemonic_bnb = { ^"BNB" }
mnemonic_bzb = { ^"BZB" }
mnemonic_bpb = { ^"BPB" }
mnemonic_bod = { ^"BOD" }
mnemonic_bnn = { ^"BNN" }
mnemonic_bnz = { ^"BNZ" }
mnemonic_bnp = { ^"BNP" }
mnemonic_bev = { ^"BEV" }
mnemonic_bn = { ^"BN" }
mnemonic_bz = { ^"BZ" }
mnemonic_bp = { ^"BP" }
mnemonic_jne = { ^"JNE" }
mnemonic_jmp = { ^"JMP" }
mnemonic_je = { ^"JE" }
mnemonic_jl = { ^"JL" }
mnemonic_jg = { ^"JG" }
// Subroutine and control flow instructions
mnemonic_pushj = { ^"PUSHJ" }
mnemonic_pushjb = { ^"PUSHJB" }
mnemonic_pushgo = { ^"PUSHGO" }
mnemonic_pushgoi = { ^"PUSHGOI" }
mnemonic_pop = { ^"POP" }
mnemonic_go = { ^"GO" }
mnemonic_goi = { ^"GOI" }
mnemonic_save = { ^"SAVE" }
mnemonic_unsave = { ^"UNSAVE" }
mnemonic_resume = { ^"RESUME" }
mnemonic_trip = { ^"TRIP" }
mnemonic_swym = { ^"SWYM" }
mnemonic_sync = { ^"SYNC" }
// Special register access
mnemonic_get = { ^"GET" }
mnemonic_put = { ^"PUT" }
mnemonic_puti = { ^"PUTI" }
// Prefetch and cache instructions
mnemonic_prego = { ^"PREGO" }
mnemonic_pregoi = { ^"PREGOI" }
mnemonic_preld = { ^"PRELD" }
mnemonic_preldi = { ^"PRELDI" }
mnemonic_prest = { ^"PREST" }
mnemonic_presti = { ^"PRESTI" }
mnemonic_syncd = { ^"SYNCD" }
mnemonic_syncdi = { ^"SYNCDI" }
mnemonic_syncid = { ^"SYNCID" }
mnemonic_syncidi = { ^"SYNCIDI" }
// Additional load/store instructions
mnemonic_ldunci = { ^"LDUNCI" }
mnemonic_ldunc = { ^"LDUNC" }
mnemonic_stunci = { ^"STUNCI" }
mnemonic_stunc = { ^"STUNC" }
mnemonic_ldhti = { ^"LDHTI" }
mnemonic_ldht = { ^"LDHT" }
mnemonic_sthti = { ^"STHTI" }
mnemonic_stht = { ^"STHT" }
mnemonic_ldsfi = { ^"LDSFI" }
mnemonic_ldsf = { ^"LDSF" }
mnemonic_stsfi = { ^"STSFI" }
mnemonic_stsf = { ^"STSF" }
mnemonic_ldvtsi = { ^"LDVTSI" }
mnemonic_ldvts = { ^"LDVTS" }
mnemonic_cswapi = { ^"CSWAPI" }
mnemonic_cswap = { ^"CSWAP" }
mnemonic_stcoi = { ^"STCOI" }
mnemonic_stco = { ^"STCO" }
// Other instructions
mnemonic_geta = { ^"GETA" }
mnemonic_getab = { ^"GETAB" }
mnemonic_trap = { ^"TRAP" }
mnemonic_halt = { ^"HALT" }
// Instruction operands
comma = _{ "," }
operand_reg_reg_reg = { register ~ comma ~ register ~ comma ~ register }
operand_reg_reg_imm = { register ~ comma ~ register ~ comma ~ expr_value }
operand_reg_reg = { register ~ comma ~ register }
operand_reg_imm = { register ~ comma ~ expr_value }
operand_reg = { register }
operand_imm = { expr_value }
// Instructions with different operand patterns
// SET/SETI follow MMIX convention: SET for register, SETI for immediate
inst_set = { mnemonic_set ~ operand_reg_reg } // SET $X,$Y -> ORI $X,$Y,0
inst_seti = { mnemonic_seti ~ operand_reg_imm } // SETI $X,IMM -> SETL/INCML/etc
inst_setl_ri = { mnemonic_setl ~ operand_reg_imm }
inst_seth_ri = { mnemonic_seth ~ operand_reg_imm }
inst_setmh_ri = { mnemonic_setmh ~ operand_reg_imm }
inst_setml_ri = { mnemonic_setml ~ operand_reg_imm }
inst_incl_rrr = { mnemonic_incl ~ operand_reg_reg_reg }
inst_inch_ri = { mnemonic_inch ~ operand_reg_imm }
inst_incmh_ri = { mnemonic_incmh ~ operand_reg_imm }
inst_incml_ri = { mnemonic_incml ~ operand_reg_imm }
inst_orh_ri = { mnemonic_orh ~ operand_reg_imm }
inst_ormh_ri = { mnemonic_ormh ~ operand_reg_imm }
inst_orml_ri = { mnemonic_orml ~ operand_reg_imm }
inst_orl_ri = { mnemonic_orl ~ operand_reg_imm }
inst_andnh_ri = { mnemonic_andnh ~ operand_reg_imm }
inst_andnmh_ri = { mnemonic_andnmh ~ operand_reg_imm }
inst_andnml_ri = { mnemonic_andnml ~ operand_reg_imm }
inst_andnl_ri = { mnemonic_andnl ~ operand_reg_imm }
// Load/Store (can take reg+reg or reg+imm) - ordered longest first
inst_load_store_rrr = {
(mnemonic_ldbui | mnemonic_ldbu | mnemonic_ldbi | mnemonic_ldb |
mnemonic_ldwui | mnemonic_ldwu | mnemonic_ldwi | mnemonic_ldw |
mnemonic_ldtui | mnemonic_ldtu | mnemonic_ldti | mnemonic_ldt |
mnemonic_ldoui | mnemonic_ldou | mnemonic_ldoi | mnemonic_ldo |
mnemonic_stbui | mnemonic_stbu | mnemonic_stbi | mnemonic_stb |
mnemonic_stwui | mnemonic_stwu | mnemonic_stwi | mnemonic_stw |
mnemonic_sttui | mnemonic_sttu | mnemonic_stti | mnemonic_stt |
mnemonic_stoui | mnemonic_stou | mnemonic_stoi | mnemonic_sto) ~
operand_reg_reg_reg
}
inst_load_store_rri = {
(mnemonic_ldbui | mnemonic_ldbi | mnemonic_ldwui | mnemonic_ldwi |
mnemonic_ldtui | mnemonic_ldti | mnemonic_ldoui | mnemonic_ldoi |
mnemonic_stbui | mnemonic_stbi | mnemonic_stwui | mnemonic_stwi |
mnemonic_sttui | mnemonic_stti | mnemonic_stoui | mnemonic_stoi) ~
operand_reg_reg_imm
}
// LDA can take 2 or 3 operands: LDA $X,Label or LDA $X,$Y,Z
inst_lda_rri = { (mnemonic_ldai | mnemonic_lda) ~ operand_reg_reg_imm }
inst_lda_ri = { (mnemonic_ldai | mnemonic_lda) ~ operand_reg_imm }
// Arithmetic (3 operands) - ordered longest first
inst_arith_rrr = {
(mnemonic_16addu | mnemonic_8addu | mnemonic_4addu | mnemonic_2addu |
mnemonic_addu | mnemonic_subu |
mnemonic_mulu | mnemonic_divu |
mnemonic_cmpu | mnemonic_add | mnemonic_sub | mnemonic_mul | mnemonic_div | mnemonic_cmp) ~
operand_reg_reg_reg
}
inst_arith_rri = {
(mnemonic_16addui | mnemonic_8addui | mnemonic_4addui | mnemonic_2addui |
mnemonic_addui | mnemonic_subui | mnemonic_mului | mnemonic_divui | mnemonic_cmpui |
mnemonic_addi | mnemonic_subi | mnemonic_muli | mnemonic_divi | mnemonic_cmpi) ~
operand_reg_reg_imm
}
// NEG is special: NEG $X, Y, $Z (Y is immediate/literal) - ordered longest first
inst_neg_rrr = {
(mnemonic_negui | mnemonic_negi | mnemonic_negu | mnemonic_neg) ~
register ~ comma ~ expr_value ~ comma ~ register
}
inst_neg_rri = {
(mnemonic_negui | mnemonic_negi) ~
register ~ comma ~ expr_value ~ comma ~ expr_value
}
// Floating point instructions (3 operands) - ordered longest first
inst_float_rrr = {
(mnemonic_fcmp | mnemonic_feql | mnemonic_fun |
mnemonic_fadd | mnemonic_fsub | mnemonic_fmul | mnemonic_fdiv |
mnemonic_frem | mnemonic_fsqrt | mnemonic_fint |
mnemonic_fixu | mnemonic_fix |
mnemonic_sflotu | mnemonic_sflot |
mnemonic_flotu | mnemonic_flot) ~
operand_reg_reg_reg
}
inst_float_rri = {
(mnemonic_sflotui | mnemonic_sfloti |
mnemonic_flotui | mnemonic_floti) ~
operand_reg_reg_imm
}
// Bitwise operations (3 operands) - ordered longest first
inst_bitwise_rrr = {
(mnemonic_andn | mnemonic_nand |
mnemonic_nxor | mnemonic_and |
mnemonic_orn | mnemonic_nor |
mnemonic_or | mnemonic_xor |
mnemonic_mux) ~
operand_reg_reg_reg
}
inst_bitwise_rri = {
(mnemonic_andni | mnemonic_nandi | mnemonic_nxori | mnemonic_andi |
mnemonic_orni | mnemonic_nori | mnemonic_ori |
mnemonic_xori | mnemonic_muxi) ~
operand_reg_reg_imm
}
// Bit fiddling operations (§11-12) - ordered longest first
inst_bitfiddle_rrr = {
(mnemonic_bdif | mnemonic_wdif | mnemonic_tdif | mnemonic_odif | mnemonic_sadd | mnemonic_mxor | mnemonic_mor) ~
operand_reg_reg_reg
}
inst_bitfiddle_rri = {
(mnemonic_bdifi | mnemonic_wdifi | mnemonic_tdifi | mnemonic_odifi | mnemonic_saddi | mnemonic_mxori | mnemonic_mori) ~
operand_reg_reg_imm
}
// Shift instructions (§14) - ordered longest first
inst_shift_rrr = {
(mnemonic_slu | mnemonic_sru |
mnemonic_sl | mnemonic_sr) ~
operand_reg_reg_reg
}
inst_shift_rri = {
(mnemonic_slui | mnemonic_srui | mnemonic_sli | mnemonic_sri) ~
operand_reg_reg_imm
}
// Conditional set instructions - 3 operands - ordered longest first
inst_conditional_set_rrr = {
(mnemonic_csnn | mnemonic_csnz | mnemonic_csnp | mnemonic_csod | mnemonic_csev |
mnemonic_csn | mnemonic_csz | mnemonic_csp) ~
operand_reg_reg_reg
}
inst_conditional_set_rri = {
(mnemonic_csnni | mnemonic_csnzi | mnemonic_csnpi | mnemonic_csodi | mnemonic_csevi |
mnemonic_csni | mnemonic_cszi | mnemonic_cspi) ~
operand_reg_reg_imm
}
// Zero or set instructions - 3 operands - ordered longest first
inst_zero_or_set_rrr = {
(mnemonic_zsnn | mnemonic_zsnz | mnemonic_zsnp | mnemonic_zsod | mnemonic_zsev |
mnemonic_zsn | mnemonic_zsz | mnemonic_zsp) ~
operand_reg_reg_reg
}
inst_zero_or_set_rri = {
(mnemonic_zsnni | mnemonic_zsnzi | mnemonic_zsnpi | mnemonic_zsodi | mnemonic_zsevi |
mnemonic_zsni | mnemonic_zszi | mnemonic_zspi) ~
operand_reg_reg_imm
}
// Branch instructions - ordered longest first
inst_branch = {
(mnemonic_bnnb | mnemonic_bnzb | mnemonic_bnpb | mnemonic_bevb |
mnemonic_bnn | mnemonic_bnz | mnemonic_bnp | mnemonic_bev |
mnemonic_bnb | mnemonic_bzb | mnemonic_bpb | mnemonic_bodb |
mnemonic_bn | mnemonic_bz | mnemonic_bp | mnemonic_bod |
mnemonic_jne | mnemonic_je | mnemonic_jl | mnemonic_jg) ~
operand_reg_imm
}
inst_pbranch = {
(mnemonic_pbnnb | mnemonic_pbnzb | mnemonic_pbnpb | mnemonic_pbevb |
mnemonic_pbodb | mnemonic_pbnb | mnemonic_pbzb | mnemonic_pbpb |
mnemonic_pbod | mnemonic_pbnn | mnemonic_pbnz | mnemonic_pbnp |
mnemonic_pbev | mnemonic_pbn | mnemonic_pbz | mnemonic_pbp) ~
operand_reg_imm
}
inst_jmp = { mnemonic_jmp ~ operand_imm }
// TRAP instruction: TRAP X, Y, Z (where X, Y, Z can be numbers or identifiers)
inst_trap = { mnemonic_trap ~ expr_value ~ comma ~ expr_value ~ comma ~ expr_value }
// GETA instructions: GETA $X, addr
inst_geta = { mnemonic_geta ~ operand_reg_imm }
inst_getab = { mnemonic_getab ~ operand_reg_imm }
// Subroutine instructions
inst_pushj = { mnemonic_pushj ~ operand_reg_imm }
inst_pushjb = { mnemonic_pushjb ~ operand_reg_imm }
inst_pushgo_rrr = { mnemonic_pushgo ~ operand_reg_reg_reg }
inst_pushgo_rri = { mnemonic_pushgoi ~ operand_reg_reg_imm }
inst_pop = { mnemonic_pop ~ expr_value ~ comma ~ expr_value }
inst_go_rrr = { mnemonic_go ~ operand_reg_reg_reg }
inst_go_rri = { mnemonic_goi ~ operand_reg_reg_imm }
// Special register access
inst_get = { mnemonic_get ~ register ~ comma ~ expr_value }
inst_put = { mnemonic_put ~ expr_value ~ comma ~ register }
inst_puti = { mnemonic_puti ~ expr_value ~ comma ~ expr_value }
// Context management
inst_save = { mnemonic_save ~ register ~ comma ~ expr_value }
inst_unsave = { mnemonic_unsave ~ expr_value ~ comma ~ register }
// Prefetch and cache control
inst_preld_rrr = { mnemonic_preld ~ operand_reg_reg_reg }
inst_preld_rri = { mnemonic_preldi ~ operand_reg_reg_imm }
inst_prego_rrr = { mnemonic_prego ~ operand_reg_reg_reg }
inst_prego_rri = { mnemonic_pregoi ~ operand_reg_reg_imm }
inst_prest_rrr = { mnemonic_prest ~ operand_reg_reg_reg }
inst_prest_rri = { mnemonic_presti ~ operand_reg_reg_imm }
inst_syncd_rrr = { mnemonic_syncd ~ operand_reg_reg_reg }
inst_syncd_rri = { mnemonic_syncdi ~ operand_reg_reg_imm }
inst_syncid_rrr = { mnemonic_syncid ~ operand_reg_reg_reg }
inst_syncid_rri = { mnemonic_syncidi ~ operand_reg_reg_imm }
// Additional load/store
inst_ldunc_rrr = { mnemonic_ldunc ~ operand_reg_reg_reg }
inst_ldunc_rri = { mnemonic_ldunci ~ operand_reg_reg_imm }
inst_stunc_rrr = { mnemonic_stunc ~ operand_reg_reg_reg }
inst_stunc_rri = { mnemonic_stunci ~ operand_reg_reg_imm }
inst_ldht_rrr = { mnemonic_ldht ~ operand_reg_reg_reg }
inst_ldht_rri = { mnemonic_ldhti ~ operand_reg_reg_imm }
inst_stht_rrr = { mnemonic_stht ~ operand_reg_reg_reg }
inst_stht_rri = { mnemonic_sthti ~ operand_reg_reg_imm }
inst_ldsf_rrr = { mnemonic_ldsf ~ operand_reg_reg_reg }
inst_ldsf_rri = { mnemonic_ldsfi ~ operand_reg_reg_imm }
inst_stsf_rrr = { mnemonic_stsf ~ operand_reg_reg_reg }
inst_stsf_rri = { mnemonic_stsfi ~ operand_reg_reg_imm }
inst_ldvts_rrr = { mnemonic_ldvts ~ operand_reg_reg_reg }
inst_ldvts_rri = { mnemonic_ldvtsi ~ operand_reg_reg_imm }
inst_cswap_rrr = { mnemonic_cswap ~ operand_reg_reg_reg }
inst_cswap_rri = { mnemonic_cswapi ~ operand_reg_reg_imm }
inst_stco_rrr = { mnemonic_stco ~ expr_value ~ comma ~ register ~ comma ~ register }
inst_stco_rri = { mnemonic_stcoi ~ expr_value ~ comma ~ register ~ comma ~ expr_value }
// System instructions
inst_resume = { mnemonic_resume ~ operand_imm }
inst_trip = { mnemonic_trip ~ expr_value ~ comma ~ expr_value ~ comma ~ expr_value }
inst_swym = { mnemonic_swym }
inst_sync = { mnemonic_sync ~ operand_imm }
// Operand patterns
operand_num_num_num = { expr_value ~ comma ~ expr_value ~ comma ~ expr_value }
// Simple instructions
inst_halt = { mnemonic_halt }
// Combined instruction rule
// PEG requires longest match first: rrr before rri
instruction = {
inst_seti | inst_set | inst_setl_ri | inst_seth_ri | inst_setmh_ri | inst_setml_ri | inst_incl_rrr |
inst_inch_ri | inst_incmh_ri | inst_incml_ri |
inst_orh_ri | inst_ormh_ri | inst_orml_ri | inst_orl_ri |
inst_andnh_ri | inst_andnmh_ri | inst_andnml_ri | inst_andnl_ri |
inst_load_store_rrr | inst_load_store_rri |
inst_ldunc_rrr | inst_ldunc_rri | inst_stunc_rrr | inst_stunc_rri |
inst_ldht_rrr | inst_ldht_rri | inst_stht_rrr | inst_stht_rri |
inst_ldsf_rrr | inst_ldsf_rri | inst_stsf_rrr | inst_stsf_rri |
inst_ldvts_rrr | inst_ldvts_rri | inst_cswap_rrr | inst_cswap_rri |
inst_stco_rrr | inst_stco_rri |
inst_lda_rri | inst_lda_ri |
inst_arith_rrr | inst_arith_rri |
inst_float_rrr | inst_float_rri |
inst_neg_rrr | inst_neg_rri |
inst_bitwise_rrr | inst_bitwise_rri |
inst_bitfiddle_rrr | inst_bitfiddle_rri |
inst_shift_rrr | inst_shift_rri |
inst_conditional_set_rrr | inst_conditional_set_rri |
inst_zero_or_set_rrr | inst_zero_or_set_rri |
inst_pbranch | inst_branch | inst_jmp |
inst_pushj | inst_pushjb | inst_pushgo_rrr | inst_pushgo_rri | inst_pop |
inst_go_rrr | inst_go_rri |
inst_preld_rrr | inst_preld_rri | inst_prego_rrr | inst_prego_rri |
inst_prest_rrr | inst_prest_rri |
inst_syncd_rrr | inst_syncd_rri | inst_syncid_rrr | inst_syncid_rri |
inst_get | inst_put | inst_puti |
inst_save | inst_unsave |
inst_geta | inst_getab |
inst_resume | inst_trip | inst_swym | inst_sync |
inst_trap | inst_halt
}
// One logical line: optional statement on this line
line = { statement? }
// Program is zero or more lines separated by newlines
// This allows blank lines, comment-only lines, and empty files
program = {
SOI ~
NEWLINE* ~ // allow leading blank lines / comment lines
line ~ (NEWLINE+ ~ line)* // lines separated by 1+ newlines
~ NEWLINE* ~ // allow trailing blank lines
EOI
}
NEWLINE = _{ "\n" }