{ module Bindings.Bfd.Disasm.I386.Parse where import Data.Array import qualified Data.IntMap as IntMap import qualified Data.Map as Map import Data.Maybe import Data.Word import Bindings.Bfd.Disasm.I386.Lex as L import Bindings.Bfd.Disasm.I386.Insn import Bindings.Bfd.Disasm.I386.Insn.EffectiveAddr import Bindings.Bfd.Disasm.I386.Insn.Mnemonic as R import Bindings.Bfd.Disasm.I386.Insn.Operand as O import Bindings.Bfd.Disasm.I386.Insn.Prefix } %name parse %tokentype { Token } %token OFFSET { Offset $$ } CONSTANT { Constant $$ } ADDRESS { Address $$ } PREFIXEDMNEMONIC { PrefixedMnemonic $$ } MNEMONIC { L.Mnemonic $$ } REGISTER { Register $$ } '(' { ParensL } ')' { ParensR } ',' { Comma } ':' { Colon } '#' { Hash } '*' { Star } %% insn :: { Insn } : PREFIXEDMNEMONIC operands { Insn (Prefix $ head $1) (R.Mnemonic $ head $ tail $1) $2 } | MNEMONIC operands { Insn (Prefix "" ) (R.Mnemonic $1) $2 } operands :: { [Operand] } : {- empty -} { [ ]} -- nop | absolute { [$1 ]} -- jle 12345 | immed { [$1 ]} -- pushq $12345 | directD { [$1 ]} -- inc %rax | directJ { [$1 ]} -- callq *%rdx | indirD address { [$1 { O.address = $2 } ]} -- inc 12345(%rax) | indirJ address { [$1 { O.address = $2 } ]} -- callq *12345(%rbx) | directD ',' directD { [$1 , $3 ]} -- mov %rax,%rbx | directD ',' indirD address { [$1 , $3 { O.address = $4 } ]} -- mov %rax,12345(%rbx) | directD ',' immed { [$1 , $3 ]} -- out %ax,$0x12 | indirD ',' directD address { [$1 { O.address = $4 }, $3 ]} -- mov 12345(%rbx),%rax | indirD ',' indirD { [$1 , $3 ]} -- rep movsq %ds:(%rsi),%es:(%rdi) | immed ',' directD { [$1 , $3 ]} -- mov $12345,%rax | immed ',' indirD address { [$1 , $3 { O.address = $4 } ]} -- mov $12345,12345(%rax) | immed ',' directD ',' directD { [$1 , $3 , $5]} -- imul $12345,%rax,%rbx | immed ',' indirD ',' directD address { [$1 , $3 , $5]} -- imul $12345,12345(%rbp),%eax address :: { Maybe Int } : {- empty -} { Nothing } | '#' ADDRESS { Just $2 } absolute :: { Operand } : ADDRESS { Abs $1 } immed :: { Operand } : CONSTANT { Imm $1 } directD :: { Operand } : REGISTER { DirD $1 } directJ :: { Operand } : '*' REGISTER { DirJ $2 } indirD :: { Operand } : indir1 { IndD "" (fst $1) (snd $1) Nothing } | REGISTER ':' indir1 { IndD $1 (fst $3) (snd $3) Nothing } indirJ :: { Operand } : '*' indir1 { IndJ (fst $2) (snd $2) Nothing } indir1 :: { (EffectiveAddr, Maybe Int) } : OFFSET effAddr { ($2 , Just $1) } | effAddr { ($1 , Nothing) } | OFFSET { (NoEA, Just $1) } effAddr :: { EffectiveAddr } : '(' REGISTER ')' { EA $2 "" 1 } | '(' ',' REGISTER ',' OFFSET ')' { EA "" $3 $5 } | '(' REGISTER ',' REGISTER ',' OFFSET ')' { EA $2 $4 $6 } { happyError :: [Token] -> a happyError tks = error $ "Parse.y: parse error at: " ++ (show $ take 10 tks) }