Class: AArch64::Parser

Inherits:
Racc::Parser
  • Object
show all
Defined in:
lib/aarch64/parser.rb,
lib/aarch64/parser.tab.rb

Defined Under Namespace

Classes: FourArg, RegRegShift, RegsWithShift, ThreeArg, ThreeWithExtend, ThreeWithLsl, TwoArg, TwoWithExtend, TwoWithLsl, TwoWithShift

Constant Summary collapse

SYS_REG_SCAN =
Regexp.new(AArch64::SystemRegisters.constants.join("|"), true)
SYS_REG_MAP =
KEYWORDS =

Created with: puts File.read(‘./lib/aarch64/parser.y’).scan(/b[A-Zd]+b/).sort.uniq - [‘LABEL’, ‘LABEL_CREATE’]

%w[
  ADC
  ADCS
  ADD
  ADDS
  ADR
  ADRP
  ALLE1
  ALLE1IS
  ALLE1OS
  ALLE2
  ALLE2IS
  ALLE2OS
  ALLE3
  ALLE3IS
  ALLE3OS
  AND
  ANDS
  ASIDE1
  ASIDE1IS
  ASIDE1OS
  ASR
  AT
  AUTDA
  B
  BANG
  BFI
  BFXIL
  BIC
  BICS
  BL
  BLR
  BR
  BRK
  CBNZ
  CBZ
  CCMN
  CCMP
  CGDSW
  CGDVAC
  CGDVADP
  CGDVAP
  CGSW
  CGVAC
  CGVADP
  CGVAP
  CIGDSW
  CIGDVAC
  CIGSW
  CIGVAC
  CINC
  CINV
  CISW
  CIVAC
  CLREX
  CLS
  CLZ
  CMN
  CMP
  CNEG
  COMMA
  CRC32B
  CRC32CB
  CRC32CH
  CRC32CW
  CRC32CX
  CRC32H
  CRC32W
  CRC32X
  CSEL
  CSET
  CSETM
  CSINC
  CSINV
  CSNEG
  CSW
  CVAC
  CVADP
  CVAP
  CVAU
  DC
  DCPS1
  DCPS2
  DCPS3
  DMB
  DOT
  DRPS
  DSB
  EOL
  EON
  EOR
  EQ
  ERET
  EXTR
  GE
  GT
  GVA
  GZVA
  HI
  HINT
  HLT
  HS
  HVC
  IALLU
  IALLUIS
  IC
  IGDSW
  IGDVAC
  IGSW
  IGVAC
  IPAS2E1
  IPAS2E1IS
  IPAS2E1OS
  IPAS2LE1
  IPAS2LE1IS
  IPAS2LE1OS
  ISB
  ISH
  ISHLD
  ISHST
  ISW
  IVAC
  IVAU
  LD
  LDAR
  LDARB
  LDARH
  LDAXP
  LDAXR
  LDAXRB
  LDAXRH
  LDNP
  LDP
  LDPSW
  LDR
  LDRB
  LDRH
  LDRSB
  LDRSH
  LDRSW
  LDTR
  LDTRB
  LDTRH
  LDTRSB
  LDTRSH
  LDTRSW
  LDUR
  LDURB
  LDURH
  LDURSB
  LDURSH
  LDURSW
  LDXP
  LDXR
  LDXRB
  LDXRH
  LE
  LO
  LS
  LSL
  LSQ
  LSR
  LT
  MADD
  MI
  MNEG
  MOV
  MOVK
  MOVN
  MOVZ
  MRS
  MSR
  MSUB
  MUL
  MVN
  NE
  NEG
  NEGS
  NGC
  NGCS
  NOP
  NSH
  NSHLD
  NSHST
  NUMBER
  ORN
  ORR
  OSH
  OSHLD
  OSHST
  PL
  PRFM
  PRFOP
  PRFUM
  PSSBB
  RBIT
  RET
  REV
  REV16
  REV32
  RIPAS2E1
  RIPAS2E1IS
  RIPAS2E1OS
  RIPAS2LE1
  RIPAS2LE1IS
  RIPAS2LE1OS
  ROR
  RSQ
  RVAAE1
  RVAAE1IS
  RVAAE1OS
  RVAALE1
  RVAALE1IS
  RVAALE1OS
  RVAE1
  RVAE1IS
  RVAE1OS
  RVAE2
  RVAE2IS
  RVAE2OS
  RVAE3
  RVAE3IS
  RVAE3OS
  RVALE1
  RVALE1IS
  RVALE1OS
  RVALE2
  RVALE2IS
  RVALE2OS
  RVALE3
  RVALE3IS
  RVALE3OS
  S12E0R
  S12E0W
  S12E1R
  S12E1W
  S1E0R
  S1E0W
  S1E1R
  S1E1RP
  S1E1W
  S1E1WP
  S1E2R
  S1E2W
  S1E3R
  S1E3W
  SBC
  SBCS
  SBFIZ
  SBFX
  SDIV
  SEV
  SEVL
  SMADDL
  SMC
  SMNEGL
  SMSUBL
  SMULH
  SMULL
  SP
  SSBB
  ST
  STLR
  STLRB
  STLRH
  STLXP
  STLXR
  STLXRB
  STLXRH
  STNP
  STP
  STR
  STRB
  STRH
  STTR
  STTRB
  STTRH
  STUR
  STURB
  STURH
  STXP
  STXR
  STXRB
  STXRH
  SUB
  SUBS
  SVC
  SXTB
  SXTH
  SXTW
  SXTX
  SY
  SYS
  SYSL
  SYSTEMREG
  TBNZ
  TBZ
  TLBI
  TST
  UBFIZ
  UBFX
  UDIV
  UMADDL
  UMNEGL
  UMSUBL
  UMULH
  UMULL
  UXTB
  UXTH
  UXTW
  UXTX
  VAAE1
  VAAE1IS
  VAAE1OS
  VAALE1
  VAALE1IS
  VAALE1OS
  VAE1
  VAE1IS
  VAE1OS
  VAE2
  VAE2IS
  VAE2OS
  VAE3
  VAE3IS
  VAE3OS
  VALE1
  VALE1IS
  VALE1OS
  VALE2
  VALE2IS
  VALE2OS
  VALE3
  VALE3IS
  VALE3OS
  VC
  VMALLE1
  VMALLE1IS
  VMALLE1OS
  VMALLS12E1
  VMALLS12E1IS
  VMALLS12E1OS
  VS
  WFE
  WFI
  WSP
  XZR
  YIELD
  ZVA
].freeze
KEYWORDS_SCAN =
/(#{Regexp.union(KEYWORDS.sort).source})\b/i
LABEL_SCAN =
/[a-zA-Z_]\w+/
LABEL_CREATE_SCAN =
/#{LABEL_SCAN}:/
Racc_arg =
[
racc_action_table,
racc_action_check,
racc_action_default,
racc_action_pointer,
racc_goto_table,
racc_goto_check,
racc_goto_default,
racc_goto_pointer,
racc_nt_base,
racc_reduce_table,
racc_token_table,
racc_shift_n,
racc_reduce_n,
racc_use_result_var ]
Racc_token_to_s_table =
[
"$end",
"error",
"EOL",
"ADD",
"ADDS",
"ADR",
"Xd",
"COMMA",
"ADRP",
"AND",
"ANDS",
"BRK",
"CBNZ",
"CBZ",
"CLS",
"CLZ",
"DCPS1",
"DCPS2",
"DCPS3",
"DRPS",
"ERET",
"HINT",
"HLT",
"HVC",
"MADD",
"MNEG",
"MOVN",
"MOVK",
"MOVZ",
"MSUB",
"MUL",
"NGC",
"NGCS",
"NOP",
"PSSBB",
"RBIT",
"REV",
"REV16",
"REV32",
"SBC",
"SBCS",
"SBFIZ",
"SBFX",
"SDIV",
"SEV",
"SEVL",
"SMADDL",
"SMC",
"SMNEGL",
"SMSUBL",
"SMULH",
"SMULL",
"SSBB",
"STLXP",
"STLXR",
"STLXRB",
"STLXRH",
"SUB",
"SUBS",
"SVC",
"SXTB",
"SXTH",
"SXTW",
"TBZ",
"TBNZ",
"UBFIZ",
"UBFX",
"UDIV",
"UMADDL",
"UMNEGL",
"UMSUBL",
"UMULH",
"UMULL",
"UXTB",
"UXTH",
"WFE",
"WFI",
"YIELD",
"LABEL_CREATE",
"ADC",
"ADCS",
"WSP",
"Wd",
"LSL",
"SP",
"ASR",
"AT",
"B",
"DOT",
"BFI",
"BFXIL",
"BIC",
"BICS",
"AUTDA",
"BL",
"BLR",
"BR",
"CINC",
"CINV",
"CLREX",
"CMN",
"CMP",
"CNEG",
"CRC32B",
"CRC32H",
"CRC32W",
"CRC32X",
"CRC32CB",
"CRC32CH",
"CRC32CW",
"CRC32CX",
"CSINV",
"CSINC",
"CSEL",
"CCMN",
"CCMP",
"CSNEG",
"CSET",
"CSETM",
"DC",
"DMB",
"DSB",
"EOR",
"EON",
"EXTR",
"IC",
"ISB",
"RSQ",
"LDARB",
"LDARH",
"LDAR",
"LDAXR",
"LDAXRB",
"LDAXRH",
"LSQ",
"LDAXP",
"LDNP",
"LDP",
"LDPSW",
"BANG",
"LDR",
"LDRSB",
"LDRSH",
"LDRSW",
"LDRB",
"LDRH",
"LDTR",
"LDTRB",
"LDTRH",
"LDTRSB",
"LDTRSH",
"LDUR",
"LDURB",
"LDURSB",
"LDURSH",
"LDURH",
"LDTRSW",
"LDURSW",
"LDXP",
"LDXR",
"LDXRB",
"LDXRH",
"LSR",
"MOV",
"MSR",
"SYSTEMREG",
"MRS",
"MVN",
"NEG",
"NEGS",
"ORN",
"ORR",
"PRFOP",
"PRFM",
"PRFUM",
"RET",
"ROR",
"STLR",
"STLRB",
"STLRH",
"STNP",
"STP",
"STR",
"STRB",
"STRH",
"STTR",
"STTRB",
"STTRH",
"STUR",
"STURH",
"STURB",
"STXP",
"STXR",
"STXRB",
"STXRH",
"SYS",
"Cd",
"SYSL",
"TLBI",
"TST",
"\"#\"",
"NUMBER",
"LABEL",
"XZR",
"EQ",
"LO",
"LT",
"HS",
"GT",
"LE",
"NE",
"MI",
"GE",
"PL",
"LS",
"HI",
"VC",
"VS",
"UXTW",
"UXTX",
"SXTX",
"IVAC",
"ISW",
"IGVAC",
"IGSW",
"IGDVAC",
"IGDSW",
"CSW",
"CGSW",
"CGDSW",
"CISW",
"CIGSW",
"CIGDSW",
"ZVA",
"GVA",
"GZVA",
"CVAC",
"CGVAC",
"CGDVAC",
"CVAU",
"CVAP",
"CGVAP",
"CGDVAP",
"CVADP",
"CGVADP",
"CGDVADP",
"CIVAC",
"CIGVAC",
"CIGDVAC",
"IALLUIS",
"IALLU",
"IVAU",
"S1E1R",
"S1E1W",
"S1E0R",
"S1E0W",
"S1E1RP",
"S1E1WP",
"S1E2R",
"S1E2W",
"S12E1R",
"S12E1W",
"S12E0R",
"S12E0W",
"S1E3R",
"S1E3W",
"OSHLD",
"OSHST",
"OSH",
"NSHLD",
"NSHST",
"NSH",
"ISHLD",
"ISHST",
"ISH",
"LD",
"ST",
"SY",
"VMALLE1OS",
"VAE1OS",
"ASIDE1OS",
"VAAE1OS",
"VALE1OS",
"VAALE1OS",
"RVAE1IS",
"RVAAE1IS",
"RVALE1IS",
"RVAALE1IS",
"VMALLE1IS",
"VAE1IS",
"ASIDE1IS",
"VAAE1IS",
"VALE1IS",
"VAALE1IS",
"RVAE1OS",
"RVAAE1OS",
"RVALE1OS",
"RVAALE1OS",
"RVAE1",
"RVAAE1",
"RVALE1",
"RVAALE1",
"VMALLE1",
"VAE1",
"ASIDE1",
"VAAE1",
"VALE1",
"VAALE1",
"IPAS2E1IS",
"RIPAS2E1IS",
"IPAS2LE1IS",
"RIPAS2LE1IS",
"ALLE2OS",
"VAE2OS",
"ALLE1OS",
"VALE2OS",
"VMALLS12E1OS",
"RVAE2IS",
"RVALE2IS",
"ALLE2IS",
"VAE2IS",
"ALLE1IS",
"VALE2IS",
"VMALLS12E1IS",
"IPAS2E1OS",
"IPAS2E1",
"RIPAS2E1",
"RIPAS2E1OS",
"IPAS2LE1OS",
"IPAS2LE1",
"RIPAS2LE1",
"RIPAS2LE1OS",
"RVAE2OS",
"RVALE2OS",
"RVAE2",
"RVALE2",
"ALLE2",
"VAE2",
"ALLE1",
"VALE2",
"VMALLS12E1",
"ALLE3OS",
"VAE3OS",
"VALE3OS",
"RVAE3IS",
"RVALE3IS",
"ALLE3IS",
"VAE3IS",
"VALE3IS",
"RVAE3OS",
"RVALE3OS",
"RVAE3",
"RVALE3",
"ALLE3",
"VAE3",
"VALE3",
"$start",
"instructions",
"instruction",
"insn",
"adc",
"adcs",
"add_body",
"imm_or_label",
"and_body",
"asr",
"at",
"autda",
"b",
"bfi",
"bfxil",
"bic",
"bics",
"bl",
"blr",
"br",
"imm",
"reg_imm_or_label",
"cinc",
"cinv",
"clrex",
"reg_reg",
"cmn",
"cmp",
"cneg",
"crc32",
"crc32c",
"cset",
"csetm",
"dc",
"dmb",
"dsb",
"eor",
"eon",
"extr",
"ic",
"isb",
"cond_fours",
"loads",
"lsl",
"lsr",
"reg_reg_reg_reg",
"reg_reg_reg",
"mov",
"movz_body",
"mrs",
"msr",
"mvn",
"neg",
"negs",
"orn",
"orr",
"prfm",
"prfum",
"ret",
"xd_xd",
"ror",
"reg_reg_imm_imm",
"smaddl_params",
"xd_wd_wd",
"xd_xd_xd",
"stlr",
"stlrb",
"stlrh",
"stlxp_body",
"stlxr_body",
"wd_wd_read_reg",
"stnp",
"stp",
"str",
"strb",
"strh",
"sttr",
"sttrb",
"sttrh",
"stur",
"stxp",
"stxr",
"stxrb",
"stxrh",
"sxtb_body",
"xd_wd",
"sys",
"sysl",
"reg_imm_imm_or_label",
"tlbi",
"tst",
"ubfiz_body",
"xd_wd_wd_xd",
"wd_wd",
"add_immediate",
"add_extended",
"add_extend",
"extend",
"add_extend_with_sp",
"add_extend_without_sp",
"shifted",
"reg_reg_imm",
"reg_reg_shift",
"shift",
"reg_reg_reg_shift",
"at_op",
"cond",
"cond_four",
"cond_three",
"cond_two",
"cmn_immediate",
"cmn_extend_with_sp",
"cmn_extend_without_sp",
"cmn_extended",
"cmn_shift",
"cmn_body",
"crc32w_insns",
"wd_wd_wd",
"wd_wd_xd",
"crc32c_insns",
"cond_four_instructions",
"dc_op",
"xt",
"dmb_option",
"reg_reg_reg_imm",
"ic_op",
"ldaxp",
"ldnp",
"ldp",
"ldpsw",
"ldr",
"ldtr",
"ldxp",
"ldxr",
"ldxrb",
"ldxrh",
"w_loads",
"x_loads",
"load_to_w",
"read_reg",
"load_to_x",
"w_load_insns",
"x_load_insns",
"read_reg_imm",
"w_w_load",
"x_x_load",
"reg_reg_load",
"reg_reg_load_offset",
"ldp_body",
"ldp_signed_offset",
"read_reg_reg",
"read_reg_reg_extend_amount",
"ldr_extend",
"ldr_32",
"ldr_64",
"ldr_64s",
"ldr_32s",
"ldtr_32",
"ldtr_64",
"ldtr_32s",
"ldtr_64s",
"mov_sp",
"reg_imm",
"register",
"prfm_register",
"prfm_imm",
"reg_reg_read_reg_imm",
"reg_reg_read_reg",
"str_body",
"strb_body",
"strr_32",
"strr_64",
"wd_xd_xd",
"wd_xd",
"tlbi_op",
"wd_wd_read_reg_imm",
"xd_xd_read_reg_imm" ]
Racc_debug_parser =
false

Instance Method Summary collapse

Instance Method Details

#_next_tokenObject



560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
# File 'lib/aarch64/parser.rb', line 560

def _next_token
  return _next_token if @scan.scan(/[\t ]+/) # skip whitespace
  return if @scan.eos?

  if str = @scan.scan(/\n/)
    return [:EOL, :EOL]
  elsif str = @scan.scan(LABEL_CREATE_SCAN)
    [:LABEL_CREATE, str[0...-1]]
  elsif str = @scan.scan(/x\d+/i)
    [:Xd, AArch64::Registers.const_get(str.upcase)]
  elsif str = @scan.scan(/w\d+/i)
    [:Wd, AArch64::Registers.const_get(str.upcase)]
  elsif str = @scan.scan(/c\d+/i)
    [:Cd, AArch64::Names.const_get(str.upcase)]
  elsif str = @scan.scan(/sp/i)
    [:SP, AArch64::Registers.const_get(str.upcase)]
  elsif str = @scan.scan(/xzr/i)
    [:Xd, AArch64::Registers.const_get(str.upcase)]
  elsif str = @scan.scan(/wzr/i)
    [:Wd, AArch64::Registers.const_get(str.upcase)]
  elsif str = @scan.scan(/wsp/i)
    [:WSP, AArch64::Registers.const_get(str.upcase)]
  elsif @scan.scan(/,/)
    [:COMMA, ","]
  elsif @scan.scan(/\./)
    [:DOT, "."]
  elsif @scan.scan(/\[/)
    [:LSQ, "["]
  elsif @scan.scan(/\]/)
    [:RSQ, "]"]
  elsif @scan.scan(/!/)
    [:BANG, "!"]
  elsif str = @scan.scan(/(?:pld|pli|pst)(?:l1|l2|l3)(?:keep|strm)/)
    [:PRFOP, str]
  elsif str = @scan.scan(/-?0x[0-9A-F]+/i)
    [:NUMBER, Integer(str)]
  elsif str = @scan.scan(/-?(?:0|[1-9][0-9]*)/i)
    [:NUMBER, Integer(str)]
  elsif str = @scan.scan(/LSL/i)
    [:LSL, str]
  elsif str = @scan.scan(/#/)
    ["#", "#"]
  elsif str = @scan.scan(/s\d_\d_c\d+_c\d+_\d/i)
    if str =~ /s(\d)_(\d)_(c\d+)_(c\d+)_(\d)/i
      [:SYSTEMREG, SystemRegisters::MRS_MSR_64.new($1.to_i,
                                                   $2.to_i,
                                                   Names.const_get($3.upcase),
                                                   Names.const_get($4.upcase),
                                                   $5.to_i)]
    else
      raise
    end
  elsif str = @scan.scan(SYS_REG_SCAN)
    [:SYSTEMREG, SYS_REG_MAP[str.downcase]]
  elsif str = @scan.scan(KEYWORDS_SCAN)
    [str.upcase.to_sym, str]
  elsif str = @scan.scan(LABEL_SCAN)
    [:LABEL, str]
  else
    [:UNKNOWN_CHAR, @scan.getch]
  end
end

#_reduce_none(val, _values, result) ⇒ Object

reduce 687 omitted



5943
5944
5945
# File 'lib/aarch64/parser.tab.rb', line 5943

def _reduce_none(val, _values, result)
  val[0]
end

#label_for(str) ⇒ Object



549
550
551
552
553
554
555
556
557
558
# File 'lib/aarch64/parser.rb', line 549

def label_for str
  # In the first pass, all valid labels are not known yet i.e. forward references
  # Return a placeholder value instead.
  if @state == :first_pass
    @asm.make_label(str)
  else
    raise("Label #{str.inspect} not defined") unless @labels.key?(str)
    @labels[str]
  end
end

#next_tokenObject



172
173
174
# File 'lib/aarch64/parser.rb', line 172

def next_token
  _next_token
end

#on_error(token_id, val, vstack) ⇒ Object

Raises:

  • (ParseError)


623
624
625
626
627
628
# File 'lib/aarch64/parser.rb', line 623

def on_error(token_id, val, vstack)
  token_str = token_to_str(token_id) || '?'
  string = @scan.string
  line_number = string.byteslice(0, @scan.pos).count("\n") + 1
  raise ParseError, "parse error on value #{val.inspect} (#{token_str}) on line #{line_number} at pos #{@scan.pos}/#{string.bytesize}"
end

#parse(str) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/aarch64/parser.rb', line 153

def parse str
  str += "\n" unless str.end_with?("\n")
  parse_states = [
    # First pass: Label parsing
    :first_pass,
    # Second pass: Code generation
    :second_pass
  ]
  @labels = {}
  parse_states.each do |state|
    @scan = StringScanner.new str
    @asm  = AArch64::Assembler.new
    @state = state
    do_parse
  end

  @asm
end

#register_label(str) ⇒ Object



535
536
537
538
539
540
541
542
543
544
545
546
547
# File 'lib/aarch64/parser.rb', line 535

def register_label str
  return unless @state == :first_pass

  if @labels.include?(str)
    raise "symbol '#{str}' is already defined"
  end

  label = @asm.make_label(str)
  @asm.put_label(label)
  @labels[str] = label

  nil
end