parse.Transfs(''' applicable = ir.path.Applicable( ir.path.projectSelection => Function(_, _, _, _) ) input = ir.path.Input2( ir.path.projectSelection => Function(_, name, _, _) ; ui.Str(!"Add Function Argument", !"Argument Symbol?") => arg ; ![name, arg] ) apply = [root, [name, arg]] -> root ; type := !Int(32,Signed) ; ~Module(< One( ~Function(_, ?name, <Concat(id,![Arg(type,arg)])>, _) ) >) ; BottomUp(Try( ~Call(Sym(?name), <Concat(id,![Sym(arg)])>) )) testApply = ![ Module([ Function(Void,"main",[],[ Assign(Int(32,Signed),Sym("eax"),Lit(Int(32,Signed),1)), Ret(Void,NoExpr) ]), ]), ["main", "eax"] ] ; apply ; ?Module([ Function(Void,"main",[Arg(Int(32,Signed),"eax")],[ Assign(Int(32,Signed),Sym("eax"),Lit(Int(32,Signed),1)), Ret(Void,NoExpr) ]), ]) ''')
parse.Transfs(''' ####################################################################### # Types ppSign = Signed -> H([ <kw "signed">, " " ]) | Unsigned -> H([ <kw "unsigned"> , " " ]) | NoSign -> "" ppSize = switch id case 8: !<kw "char"> case 16: !H([ <kw "short">, " ", <kw "int"> ]) case 32: !<kw "int"> case 64: !H([ <kw "long">, " ", <kw "int"> ]) else !H([ "int", <strings.tostr> ]) end ppType = Void -> <kw "void"> | Bool -> <kw "bool"> | Int(size, sign) -> H([ <ppSign sign>, <ppSize size> ]) | Float(32) -> <kw "float"> | Float(64) -> <kw "double"> | Char(8) -> <kw "char"> | Char(16) -> <kw "wchar_t"> | Pointer(type) -> H([ <ppType type>, " ", <ppOp "*"> ]) | Array(type) -> H([ <ppType type>, "[", "]" ]) | Blob(size) -> H([ "blob", <strings.tostr size> ]) | _ -> "???" ####################################################################### # Operator precendence. # # See http://www.difranco.net/cop2220/op-prec.htm precUnaryOp = Not -> 1 | Neg -> 1 precBinaryOp = And(Bool) -> 10 | Or(Bool) -> 11 | And(_) -> 7 | Or(_) -> 9 | Xor(_) -> 8 | LShift -> 4 | RShift -> 4 | Plus -> 4 # force parenthesis inside shifts (was 3) | Minus -> 4 # force parenthesis inside shifts (was 3) | Mult -> 2 | Div -> 2 | Mod -> 2 | Eq -> 6 | NotEq -> 6 | Lt -> 5 | LtEq -> 5 | Gt -> 5 | GtEq -> 5 precExpr = Lit(_, _) -> 0 | Sym(_) -> 0 | Cast(_, _) -> 1 | Addr(_) -> 1 | Ref(_) -> 1 | Unary(op, _) -> <precUnaryOp op> | Binary(op, _, _) -> <precBinaryOp op> | Cond(_, _, _) -> 13 | Call(_, _) -> 0 ####################################################################### # Expressions ppUnaryOp = Not(Bool) -> "!" | Not(_) -> "~" | Neg -> "-" ppBinaryOp = And(Bool) -> "&&" | Or(Bool) -> "||" | And(_) -> "&" | Or(_) -> "|" | Xor(_) -> "^" | LShift -> "<<" | RShift -> ">>" | Plus -> "+" | Minus -> "-" | Mult -> "*" | Div -> "/" | Mod -> "%" | Eq -> "==" | NotEq -> "!=" | Lt -> "<" | LtEq -> "<=" | Gt -> ">" | GtEq -> ">=" SubExpr(Cmp) = ?[pprec, rest] ; prec := precExpr rest ; if Cmp(!prec, !pprec) then !H([ "(", <exprKern [prec,rest]>, ")" ]) else exprKern [prec,rest] end subExpr = SubExpr(arith.Gt) subExprEq = SubExpr(arith.Geq) exprKern = ( [prec,rest] -> rest ) ; Path(( Lit(Int(_,_), value) -> <intlit value> | Lit(Pointer(Char(8)), value) -> <strlit value> | Lit(type, value) -> <lit value> | Sym(name) -> <sym name> | Cast(type, expr) -> H([ "(", <ppType type>, ")", " ", <subExpr [prec,expr]> ]) | Unary(op, expr) -> H([ <ppUnaryOp op>, <subExpr [prec,expr]> ]) | Binary(op, lexpr, rexpr) -> H([ <subExpr [prec,lexpr]>, " ", <ppBinaryOp op>, " ", <subExprEq [prec,rexpr]> ]) | Cond(cond, texpr, fexpr) -> H([ <subExpr [prec,cond]>, " ", <ppOp "?">, " ", <subExpr [prec,texpr]>, " ", <ppOp ":">, " ", <subExpr [prec,fexpr]> ]) | Call(addr, args) -> H([ <subExpr [prec,addr]>, "(", <(Map(subExpr [prec,<id>]); commas) args>, ")" ]) | Addr(addr) -> H([ <ppOp "&">, <subExpr [prec,addr]> ]) | Ref(expr) -> H([ <ppOp "*">, <subExpr [prec,expr]> ]) )) ppExpr = exprKern [<precExpr>,<id>] ####################################################################### # Statements ppArg = Arg(type, name) -> H([ <ppType type>, " ", name ]) ppStmts = !V( <Map(ppStmt)> ) stmtKern = Assign(Void, NoExpr, src) -> H([ <ppExpr src> ]) | Assign(_, dst, src) -> H([ <ppExpr dst>, " ", <ppOp "=">, " ", <ppExpr src> ]) | If(cond, _, _) -> H([ <kw "if">, "(", <ppExpr cond>, ")" ]) | While(cond, _) -> H([ <kw "while">, "(", <ppExpr cond>, ")" ]) | DoWhile(cond, _) -> H([ <kw "while">, "(", <ppExpr cond>, ")" ]) | Var(type, name, NoExpr) -> H([ <ppType type>, " ", name ]) | Var(type, name, val) -> H([ <ppType type>, " ", name, " = ", <ppExpr val> ]) | Function(type, name, args, stmts) -> H([ <ppType type>, " ", name, "(", <(Map(ppArg);commas) args>, ")" ]) | Label(name) -> H([ name, ":" ]) | GoTo(label) -> H([ <kw "goto">, " ", <ppExpr label> ]) | Ret(_, NoExpr) -> H([ <kw "return"> ]) | Ret(_, value) -> H([ <kw "return">, " ", <ppExpr value> ]) | NoStmt -> "" | Asm(opcode, operands) -> H([ <kw "asm">, "(", <commas [<lit opcode>, *<Map(ppExpr) operands>]>, ")" ]) ppLabel = Label -> D( <stmtKern> ) ppBlock = Block( stmts ) -> V([ D("{"), <ppStmts stmts>, D("}") ]) ppIf = If(_, true, NoStmt) -> V([ <stmtKern>, I( <ppStmt true> ) ]) | If(_, true, false) -> V([ <stmtKern>, I( <ppStmt true> ), H([ <kw "else"> ]), I( <ppStmt false> ) ]) ppWhile = While(_, body) -> V([ <stmtKern>, I( <ppStmt body> ) ]) ppDoWhile = DoWhile(_, body) -> V([ H([ <kw "do"> ]), I( <ppStmt body> ), !H([ <stmtKern>, ";" ]) ]) ppFunction = Function(_, _, _, stmts) -> D(V([ <stmtKern>, "{", I(V([ <ppStmts stmts> ])), "}" ])) ppDefault = !H([ <stmtKern>, ";" ]) ppStmt = Path( switch project.name case "Label": ppLabel case "Block": ppBlock case "If": ppIf case "While": ppWhile case "DoWhile": ppDoWhile case "Function": ppFunction else ppDefault end ) module = Path(( Module(stmts) -> V([ I( <ppStmts stmts> ) ]) )) ''')
parse.Transfs(''' asmJMPL = [Ref(addr)] -> [GoTo(addr)] asmJMP = asmJMPL AsmJcc(cond) = [Ref(addr)] -> [If(<cond>,GoTo(addr),NoStmt)] asmJA = AsmJcc(ccA ) asmJAE = AsmJcc(ccAE ) asmJB = AsmJcc(ccB ) asmJBE = AsmJcc(ccBE ) asmJC = AsmJcc(ccC ) asmJCXZ = AsmJcc(ccCXZ ) asmJECXZ = AsmJcc(ccECXZ) asmJE = AsmJcc(ccE ) asmJG = AsmJcc(ccG ) asmJGE = AsmJcc(ccGE ) asmJL = AsmJcc(ccL ) asmJLE = AsmJcc(ccLE ) asmJNA = AsmJcc(ccNA ) asmJNAE = AsmJcc(ccNAE ) asmJNB = AsmJcc(ccNB ) asmJNBE = AsmJcc(ccNBE ) asmJNC = AsmJcc(ccNC ) asmJNE = AsmJcc(ccNE ) asmJNG = AsmJcc(ccNG ) asmJNGE = AsmJcc(ccNGE ) asmJNL = AsmJcc(ccNL ) asmJNLE = AsmJcc(ccNLE ) asmJNO = AsmJcc(ccNO ) asmJNP = AsmJcc(ccNP ) asmJNS = AsmJcc(ccNS ) asmJNZ = AsmJcc(ccNZ ) asmJO = AsmJcc(ccO ) asmJP = AsmJcc(ccP ) asmJPE = AsmJcc(ccPE ) asmJPO = AsmJcc(ccPO ) asmJS = AsmJcc(ccS ) asmJZ = AsmJcc(ccZ ) AsmLOOP(size, counter) = [Ref(addr)] -> [ Assign(type, <counter>, Binary(Minus(type),<counter>, Lit(type,1))), If(Binary(Eq(type),<counter>,Lit(type,0)), GoTo(addr), NoStmt) ] where type := UWord(size) asmLOOPW = AsmLOOP(!16, cx) asmLOOPL = AsmLOOP(!16, ecx) AsmLOOPcc(size, counter, cc) = [Ref(addr)] -> [ Assign(type, <counter>, Binary(Minus(type),<counter>, Lit(type,1))), If(Binary(And(Bool), Binary(Eq(type),<counter>,Lit(type,0)), <cc>), GoTo(addr), NoStmt ) ] where type := UWord(size) asmLOOPEW = AsmLOOPcc(!16, cx, ccE ) asmLOOPZW = AsmLOOPcc(!16, cx, ccZ ) asmLOOPNEW = AsmLOOPcc(!16, cx, ccNE) asmLOOPNZW = AsmLOOPcc(!16, cx, ccNZ) asmLOOPEL = AsmLOOPcc(!32, ecx, ccE ) asmLOOPZL = AsmLOOPcc(!32, ecx, ccZ ) asmLOOPNEL = AsmLOOPcc(!32, ecx, ccNE) asmLOOPNZL = AsmLOOPcc(!32, ecx, ccNZ) asmCALLL = [Ref(addr)] -> [Assign(Void, NoExpr, Call(addr,[]))] asmCALL = asmCALLL asmRETL = [] -> [Ret(Void, NoExpr)] | [size] -> [Ret(Void, NoExpr)] asmRET = asmRETL # FIXME: INT # FIXME: IRET # FIXME: INT # FIXME: INTO # FIXME: BOUND # FIXME: deal with level asmENTERL = [size, level] -> [ *<AsmPUSH(!32) [<ebp>]>, Assign(type, <ebp>, <esp>), Assign(type, <esp>, Binary(Minus(type), <esp>, size)) ] where type := UWord(!32) asmENTER = asmENTERL asmLEAVEL = [] -> [ Assign(type, <esp>, <ebp>), *<AsmPOP(!32) [<ebp>]> ] where type := UWord(!32) asmLEAVE = asmLEAVEL ''')
parse.Transfs(''' applicable = ir.path.Applicable( ir.path.projectSelection => Function(Void, _, _, _) ) input = ir.path.Input2( ir.path.projectSelection => Function(_, name, _, _) ; ui.Str(!"Set Function Return", !"Return Symbol?") => ret ; ![name, ret] ) apply = ( [root, [name, ret]] -> root ) ; ~Module(< One( ~Function(!type, ?name, _, < AllTD(~Ret(!type, !Sym(ret))) >) ) >) ; ir.traverse.AllStmtsBU(Try( ?Assign(Void, NoExpr, Call(Sym(?name), _)) ; ~Assign(!type, !Sym(ret), _) )) where type := !Int(32,Signed) testApply = !Module([ Function(Void,"main",[],[ Assign(Int(32,Signed),Sym("eax"),Lit(Int(32,Signed),1)), Ret(Void,NoExpr) ]), ]) ; apply [<id>, ["main","eax"] ] ; ?Module([ Function(Int(32,Signed),"main",[],[ Assign(Int(32,Signed),Sym("eax"),Lit(Int(32,Signed),1)), Ret(Int(32,Signed),Sym("eax")) ]), ]) ''')
parse.Transfs(''' applName = ?Rule(Appl(Str(_), Ident), _) + ?Anon(Rule(Appl(Str(_), Ident), _)) applNames = ?Choice(<Map(applName)>) simplifyRule = Rule(Appl(Str(name), Undef), build) -> SwitchCase([Str(name)], Build(build)) | Anon(Rule(Appl(Str(name), Undef), build)) -> SwitchCase([Str(name)], Build(build)) simplifyChoice = Choice(rules) -> Switch( Transf("project.name"), <Filter(simplifyRule) rules>, Choice(<Filter(Not(simplifyRule)) rules>) ) #if Some(simplifyRule) rules simplify = BottomUp(Try(simplifyChoice)) ''', simplify=False)
parse.Transfs(''' Goto(label) = ir.path.inSelection ; ?GoTo(Sym(label)) doReturn = with label, rest in Where( ir.path.projectSelection ; ?GoTo(Sym(label)) ) ; OnceTD( AtSuffix( Where( ~[Label(label), *<AtSuffix(~[?Ret, *<![]>])>] ; Filter(Not(?Label)) ; Map(?Assign + ?Ret) ; ? rest ) ) ) ; OnceTD(Goto(label); !Block(rest)) end gotoSelected = Where( ir.path.projectSelection => GoTo(Sym(_)) ) functionSelected = Where( ir.path.projectSelection => Function ) common = doReturn applicable = ir.path.Applicable( gotoSelected ; common ) input = ir.path.Input( ![] ) apply = ir.path.Apply( [root,[]] -> root ; common ; dle ) ''')
parse.Transfs(r''' simplify = Binary(Eq(t),Binary(Minus(t),x,y),Lit(t,0)) -> Binary(Eq(t),x,y) | Unary(Not(Bool),Binary(Eq(t),x,y)) -> Binary(NotEq(t),x,y) | Binary(And(_),x,x) -> x applicable = ir.path.Applicable( ir.path.projectSelection ; ir.match.expr ; OnceTD(simplify) ) input = ir.path.Input( ![] ) apply = ir.path.Apply( [root,[]] -> root ; OnceTD( ir.path.isSelected ; InnerMost(simplify) ) ) testAnd = simplify Binary(And(Int(32,Signed)),Sym("x"),Sym("x")) => Sym("x") ''')
parse.Transfs(''' BitMask(size, offset) = !Binary(LShift(type), Lit(type,1), Binary(Mod(type), <offset>, Lit(type,<size>))) where type := Word(size) Bit(size, base, offset) = !Binary(And(type), <base>, <BitMask(size, offset)>) where type := Word(size) AsmBT(size) = [dst, src] -> [Assign(Bool,<cf>,<Bit(size,!dst,!src)>)] asmBTW = AsmBT(!16) asmBTL = AsmBT(!32) AsmBTS(size) = [dst, src] -> [ Assign(Bool,<cf>,<Bit(size,!dst,!src)>), Assign(type,dst,Binary(Or(type),dst,<BitMask(size,!src)>)) ] where type := Word(size) asmBTSW = AsmBTS(!16) asmBTSL = AsmBTS(!32) AsmBTR(size) = [dst, src] -> [ Assign(Bool,<cf>,<Bit(size,!dst,!src)>), Assign(type,dst, Binary(And(type),dst, Unary(Not(type),<BitMask(size,!src)>))) ] where type := Word(size) asmBTRW = AsmBTR(!16) asmBTRL = AsmBTR(!32) AsmBTC(size) = [dst, src] -> [ Assign(Bool,<cf>,<Bit(size,!dst,!src)>), Assign(type,dst,Binary(Xor(type),dst,<BitMask(size,!src)>)) ] where type := Word(size) asmBTCW = AsmBTC(!16) asmBTCL = AsmBTC(!32) AsmBS(size, builtin) = [dst, src] -> [ Assign(Bool, <zf>, Binary(Eq(type), src, Lit(type,0))), Assign(type, dst, Call(Sym(<builtin>){Builtin},[src])), ] where type := Word(size) AsmBSF(size) = AsmBS(size, !"_bit_scan_reverse") AsmBSR(size) = AsmBS(size, !"_bit_scan_forward") asmBSFW = AsmBSF(!16) asmBSFL = AsmBSF(!32) asmBSRW = AsmBSR(!16) asmBSRL = AsmBSR(!32) AsmSETcc(cc) = [dst] -> [ Assign(type, dst, Cond(<cc>, Lit(type,1), Lit(type,0))) ] where type := Word(!8) asmSETA = AsmSETcc(ccA ) asmSETAE = AsmSETcc(ccAE ) asmSETB = AsmSETcc(ccB ) asmSETBE = AsmSETcc(ccBE ) asmSETC = AsmSETcc(ccC ) asmSETE = AsmSETcc(ccE ) asmSETG = AsmSETcc(ccG ) asmSETGE = AsmSETcc(ccGE ) asmSETL = AsmSETcc(ccL ) asmSETLE = AsmSETcc(ccLE ) asmSETNA = AsmSETcc(ccNA ) asmSETNAE = AsmSETcc(ccNAE) asmSETNB = AsmSETcc(ccNB ) asmSETNBE = AsmSETcc(ccNBE) asmSETNC = AsmSETcc(ccNC ) asmSETNE = AsmSETcc(ccNE ) asmSETNG = AsmSETcc(ccNG ) asmSETNGE = AsmSETcc(ccNGE) asmSETNL = AsmSETcc(ccNL ) asmSETNLE = AsmSETcc(ccNLE) asmSETNO = AsmSETcc(ccNO ) asmSETNP = AsmSETcc(ccNP ) asmSETNS = AsmSETcc(ccNS ) asmSETNZ = AsmSETcc(ccNZ ) asmSETO = AsmSETcc(ccO ) asmSETP = AsmSETcc(ccP ) asmSETPE = AsmSETcc(ccPE ) asmSETPO = AsmSETcc(ccPO ) asmSETS = AsmSETcc(ccS ) asmSETZ = AsmSETcc(ccZ ) AsmTEST(size) = [dst, src] -> [ Assign(type, tmp, Binary(And(type), dst, src)), *<LogFlags(size, !tmp)> ] where type := Word(size) ; tmp := temp asmTESTB = AsmTEST(!8) asmTESTW = AsmTEST(!16) asmTESTL = AsmTEST(!32) ''')
parse.Transfs(''' LogFlags(size,res) = ![ <ZeroFlag(size, res)>, <SignFlag(size, res)>, Assign(Bool, <cf>, <false>), Assign(Bool, <of>, <false>) ] AsmLog(size, op) = [dst,src] -> [ Assign(<Word(size)>, dst, Binary(<op>,dst,src)), *<LogFlags(size, !dst)> ] AsmAnd(size) = AsmLog(size, !And(<Word(size)>)) AsmOr(size) = AsmLog(size, !Or(<Word(size)>)) AsmXor(size) = AsmLog(size, !Xor(<Word(size)>)) asmANDB = AsmAnd(!8) asmANDW = AsmAnd(!16) asmANDL = AsmAnd(!32) asmORB = AsmOr(!8) asmORW = AsmOr(!16) asmORL = AsmOr(!32) asmXORB = AsmXor(!8) asmXORW = AsmXor(!16) asmXORL = AsmXor(!32) AsmNOT(size) = [dst] -> [Assign(type,dst,Unary(Not(type),dst))] where type := Word(size) asmNOTB = AsmNOT(!8) asmNOTW = AsmNOT(!16) asmNOTL = AsmNOT(!32) ''')
parse.Transfs(''' Goto(label) = ir.path.inSelection ; ?GoTo(Sym(label)) liftLoop = with label, rest in ~[Label(label), *<AtSuffix( ?[<Goto(label)>, *rest] ; ![] ) ; ![While(Lit(Bool,1), Block(<id>)), *rest] >] end gotoSelected = Where( ir.path.projectSelection => GoTo(Sym(_)) ) functionSelected = Where( ir.path.projectSelection => Function ) common = OnceTD(AtSuffix(liftLoop)) applicable = ir.path.Applicable( gotoSelected ; common ) input = ir.path.Input( ![] ) apply = ir.path.Apply( [root,[]] -> root ; common ; dle ) testApply = !Module([ Label("next"), Assign(Int(32,Signed), Sym("a"), Sym("b")), GoTo(Sym("next")) ]) ; ir.path.annotate ; apply [<id>, [[2,0]]] ; ?Module([ While(Lit(Bool,1), Assign(Int(32,Signed), Sym("a"), Sym("b")) ) ]) ''')
parse.Transfs(''' ####################################################################### # Labels shared needed_label as table updateNeededLabels = Where( ?GoTo(Sym(label)) ; needed_label.set [label,label] ) ####################################################################### # Statements dleLabel = Try( ?Label(<Not(~needed_label)>) ; !NoStmt ) elimBlock = Block([]) -> NoStmt | Block([stmt]) -> stmt dleBlock = ~Block(<dleStmts>) ; Try(elimBlock) elimIf = If(cond,NoStmt,NoStmt) -> Assign(Void,NoExpr,cond) | If(cond,NoStmt,false) -> If(Unary(Not,cond),false,NoStmt) dleIf = ~If(_, <dleStmt>, <dleStmt>) ; Try(elimIf) elimWhile = While(cond,NoStmt) -> Assign(Void,NoExpr,cond) dleWhile = ~While(_, <dleStmt>) ; Try(elimWhile) elimDoWhile = DoWhile(cond,NoStmt) -> Assign(Void,NoExpr,cond) dleDoWhile = ~DoWhile(_, <dleStmt>) ; Try(elimDoWhile) dleFunction = {needed_label: AllTD(updateNeededLabels) ; ~Function(_, _, _, <dleStmts>) } # If none of the above applies, assume all vars are needed dleDefault = id dleStmt = ?Label & dleLabel + ?Block & dleBlock + ?If & dleIf + ?While & dleWhile + ?DoWhile & dleDoWhile + ?Function & dleFunction + id dleStmts = MapR(dleStmt) ; Filter(Not(?NoStmt)) dleModule = ~Module(<dleStmts>) dle = {needed_label: AllTD(updateNeededLabels) ; dleModule } testUnusedLabel = !Module([ Label("A") ]) ; dle ; ?Module([]) testUsedLabel = !Module([ GoTo(Sym("A")), Label("A") ]) ; dle ; ?Module([ GoTo(Sym("A")), Label("A") ]) ''')
'''Miscellaneous instructions.''' from transf import parse from machine.pentium.common import * parse.Transfs(''' AsmLEA(size) = [dst,src] -> [Assign(<Word(size)>,dst,Addr(src))] asmLEAW = AsmLEA(!8) asmLEAL = AsmLEA(!16) asmNOP = [] -> [NoStmt] # FIXME: UD2 # FIXME: XLAT/XLATB # FIXME: CPUID ''')
parse.Transfs(''' Goto(label) = ir.path.inSelection ; ?GoTo(Sym(label)) liftIfElse = with cond, false_stmts, true_label, true_stmts, rest_label, rest_stmts in ~[If(cond, <ir.path.inSelection;?GoTo(Sym(true_label))>, NoStmt), *<AtSuffix( ~[GoTo(Sym(rest_label)), Label(true_label), *<AtSuffix( ?[Label(rest_label), *] => rest_stmts ; ![] )>] ; project.tail => true_stmts ; ![] )>] ; project.tail => false_stmts ; ![If(cond, Block(true_stmts), Block(false_stmts)), *rest_stmts] end gotoSelected = Where( ir.path.projectSelection => GoTo(Sym(_)) ) functionSelected = Where( ir.path.projectSelection => Function ) common = OnceTD(AtSuffix(liftIfElse)) applicable = ir.path.Applicable( gotoSelected ; common ) input = ir.path.Input( ![] ) apply = ir.path.Apply( [root,[]] -> root ; common ; dle ) ''')
parse.Transfs(''' AddFlags(size, op1, op2, res) = ![ <ZeroFlag(size, res)>, <SignFlag(size, res)>, Assign(Bool, <cf>, Binary(Or(Bool), Binary(And(Bool),<HsbOne(size,op1)>,<HsbOne(size,op2)>), Binary(And(Bool), <HsbZero(size,res)>, Binary(Or(Bool),<HsbOne(size,op1)>,<HsbOne(size,op2)>) ) ) ), Assign(Bool, <of>, Binary(Or(Bool), Binary(And(Bool), Binary(And(Bool),<Negative(size,op1)>,<Negative(size,op2)>), <NonNegative(size,res)> ), Binary(And(Bool), Binary(And(Bool),<NonNegative(size,op1)>,<NonNegative(size,op2)>), <Negative(size,res)> ) ) ) ] SubFlags(size, op1, op2, res) = ![ <ZeroFlag(size, res)>, <SignFlag(size, res)>, Assign(Bool, <cf>, Binary(Or(Bool), Binary(And(Bool),<HsbZero(size,op1)>,<HsbOne(size,op2)>), Binary(And(Bool), <HsbZero(size,res)>, Binary(Or(Bool),<HsbZero(size,op1)>,<HsbOne(size,op2)>) ) ) ), Assign(Bool, <of>, Binary(Or(Bool), Binary(And(Bool), Binary(And(Bool),<NonNegative(size,op1)>,<Negative(size,op2)>), <NonNegative(size,res)> ), Binary(And(Bool), Binary(And(Bool),<Negative(size,op1)>,<NonNegative(size,op2)>), <Negative(size,res)> ) ) ) ] AsmAdd(size) = [dst, src] -> [ Assign(type, tmp, dst), Assign(type, dst, Binary(Plus(type), dst, src)), *<AddFlags(size, !tmp, !src, !dst)> ] where type := Word(size) ; tmp := temp asmADDB = AsmAdd(!8) asmADDW = AsmAdd(!16) asmADDL = AsmAdd(!32) AsmADC(size) = [dst, src] -> [ Assign(type, tmp, dst), Assign(type, dst, Binary(Plus(type),dst, Binary(Plus(type),src, Cond(<cf>,Lit(type,1),Lit(type,0))))), *<AddFlags(size, !tmp, !src, !dst)> ] where type := Word(size) ; tmp := temp asmADCB = AsmADC(!8) asmADCW = AsmADC(!16) asmADCL = AsmADC(!32) AsmSub(size) = [dst, src] -> [ Assign(type, tmp, dst), Assign(type, dst, Binary(Minus(type), dst, src)), *<SubFlags(size, !tmp, !src, !dst)> ] where type := Word(size) ; tmp := temp asmSUBB = AsmSub(!8) asmSUBW = AsmSub(!16) asmSUBL = AsmSub(!32) AsmSBB(size) = [dst, src] -> [ Assign(type, tmp, dst), Assign(type, dst, Binary(Minus(type),dst, Binary(Plus(type),src, Cond(<cf>,Lit(type,1),Lit(type,0))))), *<SubFlags(size, !tmp, !src, !dst)> ] where type := Word(size) ; tmp := temp asmSBBB = AsmSBB(!8) asmSBBW = AsmSBB(!16) asmSBBL = AsmSBB(!32) AsmInc(size) = [dst] -> [ Assign(type, tmp, dst), Assign(type, dst, Binary(Plus(type), dst, Lit(type,1))), *<AddFlags(size, !tmp, !Lit(type,1), !dst)> ] where type := Word(size) ; tmp := temp asmINCB = AsmInc(!8) asmINCW = AsmInc(!16) asmINCL = AsmInc(!32) AsmDec(size) = [dst] -> [ Assign(type, tmp, dst), Assign(type, dst, Binary(Minus(type), dst, Lit(type,1))), *<SubFlags(size, !tmp, !Lit(type,1), !dst)> ] where type := Word(size) ; tmp := temp asmDECB = AsmDec(!8) asmDECW = AsmDec(!16) asmDECL = AsmDec(!32) HighLow(size) = switch size case 8: ![<ah>,<al>] case 16: ![<dx>,<ax>] case 32: ![<edx>,<eax>] end AsmMUL(size) = [src] -> < HighLow(size); ?[high,low] ; ![ Assign(type2, tmp, Binary(Mult(type2),Cast(type2,low),Cast(type2,src))), Assign(type, low, Cast(type,tmp)), Assign(type, high, Cast(type,Binary(RShift(type),tmp,Lit(type2,<size>)))), Assign(Bool, <cf>, Binary(NotEq(type),high,Lit(type2,0))), Assign(Bool, <of>, Binary(NotEq(type),high,Lit(type2,0))) ]> where type := Word(size) ; type2 := Word(arith.MulInt(size,!2)) ; tmp := temp asmMULB = AsmMUL(!8) asmMULW = AsmMUL(!16) asmMULL = AsmMUL(!32) AsmIMUL1(size,src) = HighLow(size); ?[high,low] ; ![ Assign(type2, tmp, Binary(Mult(type2),Cast(type2,low),Cast(type2,<src>))), Assign(type, low, Cast(type,tmp)), Assign(type, high, Cast(type,Binary(RShift(type),tmp,Lit(type2,<size>)))), Assign(Bool, <cf>, Binary(And(Bool),Binary(NotEq(type),high,Lit(type2,0)),Binary(NotEq(type),high,Lit(type2,-1)))), Assign(Bool, <of>, Binary(And(Bool),Binary(NotEq(type),high,Lit(type2,0)),Binary(NotEq(type),high,Lit(type2,-1)))) ] where type := SWord(size) ; type2 := SWord(arith.MulInt(size,!2)) ; tmp := temp AsmIMUL23(size,dst,src1,src2) = ![ Assign(type2, tmp, Binary(Mult(type2),Cast(type2,<src1>),Cast(type2,<src2>))), Assign(type, <dst>, Binary(Mult(type),<src1>,<src2>)), Assign(Bool, <cf>, Binary(NotEq(type2),tmp,Cast(type2,<dst>))), Assign(Bool, <of>, Binary(NotEq(type2),tmp,Cast(type2,<dst>))) ] where type := SWord(size) ; type2 := SWord(arith.MulInt(size,!2)) ; tmp := temp AsmIMUL(size) = [op1] -> <AsmIMUL1(size,!op1)> | [op1,op2] -> <AsmIMUL23(size,!op1,!op1,!op2)> | [op1,op2,op3] -> <AsmIMUL23(size,!op1,!op2,!op3)> asmIMULB = AsmIMUL(!8) asmIMULW = AsmIMUL(!16) asmIMULL = AsmIMUL(!32) # FIXME: handle 8 bit specially AsmDIV(size) = [src] -> < HighLow(size); ?[high,low] ; ![ Assign(type2, tmp1, Binary(And(type2), Cast(type2,low), Binary(LShift(type2),Cast(type2,high),Lit(type2,<size>)) ) ), Assign(type, tmp2, src), Assign(type, low, Cast(type,Binary(Div(type2),tmp1,Cast(type2,tmp2)))), Assign(type, high, Cast(type,Binary(Mod(type2),tmp1,Cast(type2,tmp2)))) # FIXME: undefine flags ]> where type := Word(size) ; type2 := Word(arith.MulInt(size,!2)) ; tmp1 := temp ; tmp2 := temp asmDIVB = AsmDIV(!8) asmDIVW = AsmDIV(!16) asmDIVL = AsmDIV(!32) AsmIDIV(size) = [src] -> < HighLow(size); ?[high,low] ; ![ Assign(type2, tmp1, Binary(And(type2), Cast(type2,low), Binary(LShift(type2),Cast(type2,high),Lit(type2,<size>)) ) ), Assign(type, tmp2, src), Assign(type, low, Cast(type,Binary(Div(type2),tmp1,Cast(type2,tmp2)))), Assign(type, high, Cast(type,Binary(Mod(type2),tmp1,Cast(type2,tmp2)))) # FIXME: undefine flags ]> where type := SWord(size) ; type2 := SWord(arith.MulInt(size,!2)) ; tmp1 := temp ; tmp2 := temp asmIDIVB = AsmIDIV(!8) asmIDIVW = AsmIDIV(!16) asmIDIVL = AsmIDIV(!32) AsmNEG(size) = [dst] -> [ Assign(type, tmp, dst), Assign(type, dst, Unary(Neg(type), dst)), *<SubFlags(size, !Lit(type,0), !tmp, !dst)> ] where type := Word(size) ; tmp := temp asmNEGB = AsmNEG(!8) asmNEGW = AsmNEG(!16) asmNEGL = AsmNEG(!32) AsmCmp(size) = [dst, src] -> [ Assign(type, tmp, Binary(Minus(type), dst, src)), *<SubFlags(size, !dst, !src, !tmp)> ] where type := Word(size) ; tmp := temp asmCMPB = AsmCmp(!8) asmCMPW = AsmCmp(!16) asmCMPL = AsmCmp(!32) ''')
parse.Transfs(''' asmSTC = [] -> [Assign(Bool, <cf>, Lit(Bool,1))] asmCLC = [] -> [Assign(Bool, <cf>, Lit(Bool,0))] asmCMC = [] -> [Assign(Bool, <cf>, Unary(Not(Bool),<cf>))] asmSTD = [] -> [Assign(Bool, <df>, Lit(Bool,1))] asmCLD = [] -> [Assign(Bool, <df>, Lit(Bool,0))] asmLAHF = [] -> [ Assign(type, <ah>, Binary(Or(type), Cond(<cf>, Lit(type,0x01), Lit(type,0)), Binary(Or(type), Lit(type,0x02), Binary(Or(type), Cond(<pf>, Lit(type,0x04), Lit(type,0)), Binary(Or(type), Cond(<af>, Lit(type,0x10), Lit(type,0)), Binary(Or(type), Cond(<zf>, Lit(type,0x40), Lit(type,0)), Cond(<sf>, Lit(type,0x80), Lit(type,0)) )))))) ] where type := UWord(!8) asmSAHF = [] -> [ Assign(type, <cf>, Binary(And(type), <ah>, Lit(type,0x01))), Assign(type, <pf>, Binary(And(type), <ah>, Lit(type,0x04))), Assign(type, <af>, Binary(And(type), <ah>, Lit(type,0x10))), Assign(type, <zf>, Binary(And(type), <ah>, Lit(type,0x40))), Assign(type, <sf>, Binary(And(type), <ah>, Lit(type,0x80))) ] where type := UWord(!8) asmPUSHFL = [] -> [ Binary(Or(type), Cond(<cf>, Lit(type,0x01), Lit(type,0)), Binary(Or(type), Lit(type,0x02), Binary(Or(type), Cond(<pf>, Lit(type,0x04), Lit(type,0)), Binary(Or(type), Cond(<af>, Lit(type,0x10), Lit(type,0)), Binary(Or(type), Cond(<zf>, Lit(type,0x40), Lit(type,0)), Cond(<sf>, Lit(type,0x80), Lit(type,0))))))) # FIXME: incomplete ] ; asmPUSHL where type := UWord(!32) asmPOPFL = [] -> [ <asmPOPL [tmp] >, Assign(type, <cf>, Binary(And(type), tmp, Lit(type,0x01))), Assign(type, <pf>, Binary(And(type), tmp, Lit(type,0x04))), Assign(type, <af>, Binary(And(type), tmp, Lit(type,0x10))), Assign(type, <zf>, Binary(And(type), tmp, Lit(type,0x40))), Assign(type, <sf>, Binary(And(type), tmp, Lit(type,0x80))) # FIXME: incomplete ] where type := UWord(!32) ; tmp := temp asmSTI = [] -> [Assign(Bool, <if_>, Lit(Bool,1))] asmCLI = [] -> [Assign(Bool, <if_>, Lit(Bool,0))] ''')
parse.Transfs(r''' ####################################################################### # Graph Generation shared stmtid shared this shared next shared retn shared brek shared cont shared nodes getNodeId = Label(label) -> label & box.escape + Count() makeNodeLabel = ( If(cond,_,_) -> <ir.pprint.ppExpr cond> | While(cond,_) -> <ir.pprint.ppExpr cond> | DoWhile(cond,_) -> <ir.pprint.ppExpr cond> | _ -> <ir.pprint.stmtKern> | n(*) -> n ) ; renderBox ; box.escape makeNodeShape = If -> "diamond" | While -> "diamond" | DoWhile -> "diamond" | Module -> "point" | Block -> "point" | NoStmt -> "point" | _ -> "box" makeNodeUrl = (path.get & box.reprz + !"" ) ; box.escape makeNodeAttrs = ![ !Attr("label", <makeNodeLabel>), !Attr("shape", <makeNodeShape>), !Attr("URL", <makeNodeUrl>) ] MakeEdge(dst) = !Edge(<dst>, []) MakeLabelledEdge(dst, label) = !Edge(<dst>, [Attr("label", <label ; box.escape>)]) AddNode(nodeid, attrs, edges) = Where( !Node( <nodeid>, <attrs>, <edges> ) ; nodes := ![_,*nodes] ) GetTerminalNodeId(nodeid) = NegInt(nodeid) hasTerminalNode = ?Function addTerminalNode = AddNode( !retn, ![ Attr("label", "\"\""), Attr("shape", "doublecircle"), Attr("style", "filled"), Attr("fillcolor", "black") ], ![] ) ####################################################################### # Flow Traversal doStmts = MapR(doStmt) MakeNode(edges) = AddNode(!this, makeNodeAttrs, edges) doDefault = MakeNode(![<MakeEdge(!next)>]) ; next := !this doIf = with true, false, oldnext in oldnext := !next ; ?If(_, <with next in next := !oldnext; doStmt; true := !next end>, <with next in next := !oldnext; doStmt; false := !next end> ) ; MakeNode(![ <MakeLabelledEdge(!true, !"True")>, <MakeLabelledEdge(!false, !"False")>, ]) ; next := !this end doNoStmt = id doWhile = with true in ?While(_, <with next in next := !this; doStmt; true := !next end> ); MakeNode(![ <MakeLabelledEdge(!true, !"True")>, <MakeLabelledEdge(!next, !"False")>, ]) ; next := !this end doDoWhile = with false in false := !next ; next := !this ; ?DoWhile(_, <doStmt> ); MakeNode(![ <MakeLabelledEdge(!next, !"True")>, <MakeLabelledEdge(!false, !"False")>, ]) end doBreak = MakeNode(![<MakeEdge(!brek)>]) ; next := !this doContinue = MakeNode(![<MakeEdge(!cont)>]) ; next := !this doRet = MakeNode(![<MakeEdge(!retn)>]) ; next := !this doGoTo = with label in ?GoTo(Sym(label)) & MakeNode(![<MakeEdge(!label ; box.escape)>]) + MakeNode(![]) end ; next := !this doBlock = ?Block(<doStmts>) doFunction = oldnext := !next ; with next, retn, brek, cont in next := !oldnext ; retn := GetTerminalNodeId(!this) ; brek := !0 ; cont := !0 ; ?Function(_, _, _, <doStmts>) ; MakeNode(![<MakeEdge(!next)>]) ; addTerminalNode end doModule = with next, retn, brek, cont in next := !0 ; retn := !0 ; brek := !0 ; cont := !0 ; ?Module(<doStmts>) ; addTerminalNode end doStmt = with this in this := getNodeId ; switch project.name case "If": doIf case "While": doWhile case "DoWhile": doDoWhile case "Break": doBreak case "GoTo": doGoTo case "Continue": doContinue case "NoStmt": doNoStmt case "Ret": doRet case "Block": doBlock case "Function": doFunction case "Module": doModule else doDefault end end makeGraph = with nodes, stmtid in nodes := ![] ; stmtid := !0 ; doModule ; AddNode(!"edge",![Attr("fontname","Arial")],![]) ; AddNode(!"node",![Attr("fontname","Arial")],![]) ; !Graph(nodes) end ####################################################################### # Graph Simplification shared point as table matchPointShapeAttr = ?Attr("shape", "point") findPointNode = ?Node(src, <One(matchPointShapeAttr)>, [Edge(dst, _)]) ; point.set [src, dst] findPointNodes = Map(Try(findPointNode)) replaceEdge = ~Edge(<~point>, _) removePointNode = ~Node(<Not(?point)>, _, <Map(Try(replaceEdge))>) removePointNodes = Filter(removePointNode) simplifyPoints = with point in ~Graph(<findPointNodes; removePointNodes>) end simplifyGraph = simplifyPoints ####################################################################### render = makeGraph ; simplifyGraph ''')
parse.Transfs(''' liftContinue = ~[Label(label), < ~While(_, < OnceTD( (GoTo(Sym(label)) -> Continue if ir.path.inSelection) ) >) + ~DoWhile(_, < OnceTD( (GoTo(Sym(label)) -> Continue if ir.path.inSelection) ) >) >, *] gotoSelected = Where( ir.path.projectSelection => GoTo(Sym(_)) ) functionSelected = Where( ir.path.projectSelection => Function ) common = OnceTD(AtSuffix(liftContinue)) applicable = ir.path.Applicable( gotoSelected ; common ) input = ir.path.Input( ![] ) apply = ir.path.Apply( [root,[]] -> root ; common ; dle ) xtestApply = !Module([ Label("continue"), While(Lit(Bool,1), Block([ Assign(Int(32,Signed), Sym("a"), Sym("b")), GoTo(Sym("continue")) ])) ]) ; ir.path.annotate ; apply [<id>, [[0,1,1,0,1]]] ; ?Module([ While(Lit(Bool,1), Block([ Assign(Int(32,Signed), Sym("a"), Sym("b")), Continue ])) ]) ''')
parse.Transfs(''' # FIXME: truncate src _AsmSxL(size, sign, dst, src) = ![ Assign(type, tmp, <dst>), Assign(type, <dst>, Binary(LShift(type), <dst>, <src>)), # FIXME: deal with zero count Assign(Bool, <cf>, Binary(And(type), tmp, Binary(LShift(type),Lit(type,1), Binary(Minus(type),Lit(type,<size>), <src>)) )), Assign(Bool, <of>, <LNotEq(HsbOne(size,dst),cf)>) ] where type := !Int(<size>,<sign>) ; tmp := temp AsmSxL(size, sign) = [dst] -> <_AsmSxL(size, sign, !dst, !Lit(Int(<size>,<sign>),1))> | [dst,src] -> <_AsmSxL(size, sign, !dst, !src)> asmSHLB = AsmSxL(!8, !Unsigned) asmSHLW = AsmSxL(!16, !Unsigned) asmSHLL = AsmSxL(!32, !Unsigned) asmSALB = AsmSxL(!8, !Signed) asmSALW = AsmSxL(!16, !Signed) asmSALL = AsmSxL(!32, !Signed) _AsmSxR(size, sign, dst, src) = ![ Assign(type, tmp, <dst>), Assign(type, <dst>, Binary(RShift(type), <dst>, <src>)), Assign(Bool, <cf>, Binary(And(type), tmp, Binary(RShift(type),Lit(type,1), Binary(Minus(type),<src>, Lit(type,1))) )), Assign(Bool, <of>, <switch sign case Unsigned: !Lit(Bool, 0) case Signed: HsbOne(size,!tmp) end> ) ] where type := !Int(<size>,<sign>) ; tmp := temp AsmSxR(size, sign) = [dst] -> <_AsmSxR(size, sign, !dst, !Lit(Int(<size>,<sign>),1))> | [dst,src] -> <_AsmSxR(size, sign, !dst, !src)> asmSHRB = AsmSxR(!8, !Unsigned) asmSHRW = AsmSxR(!16, !Unsigned) asmSHRL = AsmSxR(!32, !Unsigned) asmSARB = AsmSxR(!8, !Signed) asmSARW = AsmSxR(!16, !Signed) asmSARL = AsmSxR(!32, !Signed) # FIXME: SHRD # FIXME: SHLD # FIXME: ROR # FIXME: ROL # FIXME: RCR # FIXME: RCL ''')
parse.Transfs(''' Goto(label) = ir.path.inSelection ; ?GoTo(Sym(label)) liftDoWhile = with label, cond, rest in ~[Label(label), *<AtSuffix( ?[If(_,<Goto(label)>,NoStmt), *] ; ?[If(cond,_,_), *rest] ; ![] ) ; ![DoWhile(cond, Block(<id>)), *rest] >] end gotoSelected = Where( ir.path.projectSelection => GoTo(Sym(_)) ) functionSelected = Where( ir.path.projectSelection => Function ) common = OnceTD(AtSuffix(liftDoWhile)) applicable = ir.path.Applicable( gotoSelected ; common ) input = ir.path.Input( ![] ) apply = ir.path.Apply( [root,[]] -> root ; common ; dle ) testApply = !Module([ Label("next"), Assign(Int(32,Signed), Sym("a"), Sym("b")), If(Sym("a"),GoTo(Sym("next")),NoStmt) ]) ; ir.path.annotate ; apply [_, [[1,2,0]]] ; ?Module([ DoWhile(Sym("a"), Assign(Int(32,Signed), Sym("a"), Sym("b")) ) ]) ''')
parse.Transfs(''' # Equality conditions ccZ = zf ccNZ = LNot(zf) ccE = ccZ ccNE = ccNZ ccCXZ = LNot(cx) ccECXZ = LNot(ecx) # Unsigned conditions ccA = LAnd(LNot(cf),LNot(zf)) ccAE = LNot(cf) ccB = cf ccBE = LOr(cf, zf) ccNBE = ccA ccNB = ccNC ccNAE = ccB ccNA = ccBE ccC = cf ccNC = LNot(cf) # Signed conditions ccG = LOr(LNotEq(sf,of),LNot(zf)) ccGE = LNotEq(sf,of) ccL = LEq(sf,of) ccLE = LOr(LEq(sf,of),zf) ccNLE = ccG ccNL = ccGE ccNGE = ccL ccNG = ccLE ccO = of ccNO = LNot(of) ccS = sf ccNS = LNot(sf) # Miscellaneous ccP = pf ccNP = LNot(pf) ccPE = ccP ccPO = ccNP ''')
parse.Transfs(''' AsmMOV(size) = [dst,src] -> [Assign(<Word(size)>,dst,src)] asmMOVB = AsmMOV(!8) asmMOVW = AsmMOV(!16) asmMOVL = AsmMOV(!32) AsmCMOVcc(size,cond) = [dst,src] -> [If(<cond>,Assign(<Word(size)>,dst,src),NoStmt)] asmCMOVAW = AsmCMOVcc(!16, ccA ) asmCMOVAEW = AsmCMOVcc(!16, ccAE ) asmCMOVBW = AsmCMOVcc(!16, ccB ) asmCMOVBEW = AsmCMOVcc(!16, ccBE ) asmCMOVCW = AsmCMOVcc(!16, ccC ) asmCMOVEW = AsmCMOVcc(!16, ccE ) asmCMOVGW = AsmCMOVcc(!16, ccG ) asmCMOVGEW = AsmCMOVcc(!16, ccGE ) asmCMOVLW = AsmCMOVcc(!16, ccL ) asmCMOVLEW = AsmCMOVcc(!16, ccLE ) asmCMOVNAW = AsmCMOVcc(!16, ccNA ) asmCMOVNAEW = AsmCMOVcc(!16, ccNAE ) asmCMOVNBW = AsmCMOVcc(!16, ccNB ) asmCMOVNBEW = AsmCMOVcc(!16, ccNBE ) asmCMOVNCW = AsmCMOVcc(!16, ccNC ) asmCMOVNEW = AsmCMOVcc(!16, ccNE ) asmCMOVNGW = AsmCMOVcc(!16, ccNG ) asmCMOVNGEW = AsmCMOVcc(!16, ccNGE ) asmCMOVNLW = AsmCMOVcc(!16, ccNL ) asmCMOVNLEW = AsmCMOVcc(!16, ccNLE ) asmCMOVNOW = AsmCMOVcc(!16, ccNO ) asmCMOVNPW = AsmCMOVcc(!16, ccNP ) asmCMOVNSW = AsmCMOVcc(!16, ccNS ) asmCMOVNZW = AsmCMOVcc(!16, ccNZ ) asmCMOVOW = AsmCMOVcc(!16, ccO ) asmCMOVPW = AsmCMOVcc(!16, ccP ) asmCMOVPEW = AsmCMOVcc(!16, ccPE ) asmCMOVPOW = AsmCMOVcc(!16, ccPO ) asmCMOVSW = AsmCMOVcc(!16, ccS ) asmCMOVZW = AsmCMOVcc(!16, ccZ ) asmCMOVAL = AsmCMOVcc(!32, ccA ) asmCMOVAEL = AsmCMOVcc(!32, ccAE ) asmCMOVBL = AsmCMOVcc(!32, ccB ) asmCMOVBEL = AsmCMOVcc(!32, ccBE ) asmCMOVCL = AsmCMOVcc(!32, ccC ) asmCMOVEL = AsmCMOVcc(!32, ccE ) asmCMOVGL = AsmCMOVcc(!32, ccG ) asmCMOVGEL = AsmCMOVcc(!32, ccGE ) asmCMOVLL = AsmCMOVcc(!32, ccL ) asmCMOVLEL = AsmCMOVcc(!32, ccLE ) asmCMOVNAL = AsmCMOVcc(!32, ccNA ) asmCMOVNAEL = AsmCMOVcc(!32, ccNAE ) asmCMOVNBL = AsmCMOVcc(!32, ccNB ) asmCMOVNBEL = AsmCMOVcc(!32, ccNBE ) asmCMOVNCL = AsmCMOVcc(!32, ccNC ) asmCMOVNEL = AsmCMOVcc(!32, ccNE ) asmCMOVNGL = AsmCMOVcc(!32, ccNG ) asmCMOVNGEL = AsmCMOVcc(!32, ccNGE ) asmCMOVNLL = AsmCMOVcc(!32, ccNL ) asmCMOVNLEL = AsmCMOVcc(!32, ccNLE ) asmCMOVNOL = AsmCMOVcc(!32, ccNO ) asmCMOVNPL = AsmCMOVcc(!32, ccNP ) asmCMOVNSL = AsmCMOVcc(!32, ccNS ) asmCMOVNZL = AsmCMOVcc(!32, ccNZ ) asmCMOVOL = AsmCMOVcc(!32, ccO ) asmCMOVPL = AsmCMOVcc(!32, ccP ) asmCMOVPEL = AsmCMOVcc(!32, ccPE ) asmCMOVPOL = AsmCMOVcc(!32, ccPO ) asmCMOVSL = AsmCMOVcc(!32, ccS ) asmCMOVZL = AsmCMOVcc(!32, ccZ ) AsmXCHG(size) = [dst,src] -> [ Assign(type,tmp,dst), Assign(type,dst,src), Assign(type,src,tmp) ] where type := Word(size) ; tmp := temp asmXCHGB = AsmXCHG(!8) asmXCHGW = AsmXCHG(!16) asmXCHGL = AsmXCHG(!32) # FIXME: BSWAP AsmXADD(size) = [dst, src] -> [ Assign(type, tmp, Binary(Plus(type), dst, src)), Assign(type, src, dst), Assign(type, dst, tmp), *<AddFlags(size, !src, !dst, !tmp)> ] where type := Word(size) ; tmp := temp asmXADDB = AsmXADD(!8) asmXADDW = AsmXADD(!16) asmXADDL = AsmXADD(!32) AsmCMPXCHG(size,accum) = [dst, src] -> [ Assign(type, tmp, Binary(Minus(type), <accum>, dst)), *<SubFlags(size, accum, !src, !tmp)>, If(Binary(Eq(type),<accum>,dst), Assign(type, dst, src), Assign(type, <accum>, dst) ) ] where type := Word(size) ; tmp := temp asmCMPXCHGB = AsmCMPXCHG(!8, al) asmCMPXCHGW = AsmCMPXCHG(!16, ax) asmCMPXCHGL = AsmCMPXCHG(!32, eax) # FIXME: CMPXCHG8B AsmPUSH(size) = [src] -> [ Assign(type, <esp>, Binary(Minus(type), <esp>, Lit(type,4))), Assign(type, Ref(<esp>), src) ] where type := Word(size) asmPUSHW = AsmPUSH(!16) asmPUSHL = AsmPUSH(!32) AsmPOP(size) = [dst] -> [ Assign(type, dst, Ref(<esp>)), Assign(type, <esp>, Binary(Plus(type), <esp>, Lit(type,4))) ] where type := Word(size) asmPOPW = AsmPOP(!16) asmPOPL = AsmPOP(!32) asmPUSHAD = [] -> [ Assign(<Word(!32)>, tmp, <esp>), *<lists.MapConcat(asmPUSHL [_]) [<eax>, <ecx>, <edx>, <ebx>, tmp , <esi>, <edi>]> ] where tmp := temp asmPOPAD = [] -> [ *<lists.MapConcat(asmPOPL [_]) [<eax>, <ecx>, <edx>, <ebx>, tmp , <esi>, <edi>]> ] where tmp := temp AsmIN(size, builtin) = [dst, src] -> [Assign(<Word(size)>,dst,Call(Sym(<builtin>){Builtin},[src]))] asmINB = AsmIN(!8, !"_inp") asmINW = AsmIN(!8, !"_inpw") asmINL = AsmIN(!8, !"_inpd") AsmOUT(size, builtin) = [dst, src] -> [Assign(Void,NoExpr,Call(Sym(<builtin>){Builtin},[dst,src]))] asmOUTB = AsmOUT(!8, !"_outp") asmOUTW = AsmOUT(!8, !"_outpw") asmOUTL = AsmOUT(!8, !"_outpd") asmCWTD = [] -> [ If(Binary(Lt(type),<ax>,Lit(type,0)), Assign(type,<dx>,Lit(type,-1)), Assign(type,<dx>,Lit(type,0)) ) ] where type := SWord(!16) asmCLTD = [] -> [ If(Binary(Lt(type),<eax>,Lit(type,0)), Assign(type,<edx>,Lit(type,-1)), Assign(type,<edx>,Lit(type,0)) ) ] where type := SWord(!32) AsmMOVSX(size, dst, src) = ![Assign(Int(<size>,Signed), <dst>, Cast(Int(<size>,Signed),<src>))] asmCBTW = [] -> <AsmMOVSX(!16,ax,al)> asmCWTL = [] -> <AsmMOVSX(!16,eax,ax)> asmMOVSBW = [dst, src] -> <AsmMOVSX(!16, !dst, !src)> asmMOVSBL = [dst, src] -> <AsmMOVSX(!32, !dst, !src)> asmMOVSWL = [dst, src] -> <AsmMOVSX(!32, !dst, !src)> AsmMOVZX(size) = [dst, src] -> [Assign(Int(<size>,Unsigned), dst, Cast(Int(<size>,Unsigned),src))] asmMOVZBW = AsmMOVZX(!16) asmMOVZBL = AsmMOVZX(!32) asmMOVZWL = AsmMOVZX(!32) ''')
parse.Transfs(''' simplifyExpr = Not(Int(1,_)) -> Not(Bool) | Or(Int(1,_)) -> Or(Bool) | And(Int(1,_)) -> And(Bool) simplifyStmt = Assign(type, dst, Cond(cond, src, dst)) -> If(cond, Assign(type, dst, src), NoStmt) | Assign(type, dst, Cond(cond, src, dst)) -> If(Unary(Not, cond), Assign(type, dst, src), NoStmt) | Assign(_, Sym("pc"), expr) -> GoTo(Addr(expr)) | Cond(cond,Lit(Int(_,_),1),Lit(Int(_,_),0)) -> cond | Cond(cond,Lit(Int(_,_),0),Lit(Int(_,_),1)) -> Not(cond) | Ref(Addr(expr)) -> expr | Addr(Ref(expr)) -> expr simplify = traverse.InnerMost( simplifyExpr + simplifyStmt ) ''')
parse.Transfs(r''' ####################################################################### # Path annotation # Only annotate term applications annotate = path.Annotate( match.ApplNames(` ir.match.stmtNames + ir.match.exprNames + ir.match.typeNames `) ) deannotate = path.deannotate ####################################################################### # Selection shared selection Applicable(t) = with selection in ?[root, selection] ; !root ; t end Input(t) = with selection in ?[root, selection] ; !root ; # annotate ; t ; ![selection, *<id>] end Input2(t) = with selection in ?[root, selection] ; !root ; # annotate ; t end Apply(t) = with selection in ?[root, [selection, *args]] ; ![root, args] ; t ; deannotate end WithSelection(s, x) = with selection in x where selection := s end projectSelection = path.Project(!selection) MatchSelectionTo(s) = projectSelection ; s ####################################################################### # Selection context getSelection = !selection isSelected = Where( path.get ; path.Equals(getSelection) ) inSelection = Where( path.get ; path.Contained(getSelection) ) hasSelection = Where( path.get ; path.Contains(getSelection) ) ''')
trf = eval("asm" + opcode.upper()) except NameError: sys.stderr.write("warning: don't now how to translate opcode '%s'\n" % opcode) raise exception.Failure try: trm = trf.apply(operands, ctx) for stmt in trm: ir.check.stmt(stmt) return trm except KeyboardInterrupt, SystemExit: raise except: sys.stderr.write("warning: failed to translate opcode '%s'\n" % opcode) traceback.print_exc() raise exception.Failure parse.Transfs(''' doStmt = OpcodeDispatch() ; Try(simplify) + ![<id>] doModule = ~Module(<lists.MapConcat(doStmt)>) ''')
parse.Transfs(''' reduceStmts = ( Block(stmts) -> stmts | If(_, true, false) -> [true, false] | While(_, stmt) -> [stmt] | DoWhile(_, stmt) -> [stmt] | Function(_, _, _, stmts) -> stmts | Module(stmts) -> stmts ) + ![] reduceStmts = switch Try(project.name) case "Block": project.args ; project.first case "If": project.args ; project.tail case "While": project.args ; project.tail case "DoWhile": project.args ; project.tail case "Function": project.args ; project.fourth case "Module": project.args ; project.first else ![] end stopStmts = Not(aModule + aCompoundStmt + lib.match.aList) ''')
parse.Transfs(''' reg32Names = ![ "eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp" ] reg16Names = ![ "ax", "bx", "cx", "dx", "si", "di", "bp", "sp" ] reg8Names = ![ "ah", "bh", "ch", "dh", "al", "bl", "cl", "dl" ] flagNames = ![ "sf", "zf", "af", "pf", "cf", "of", "df", "if" ] declReg32 = !Var(Int(32,NoSign),<id>,NoExpr) declFlag = !Var(Bool,<id>,NoExpr) stmtsPreambule = Concat( reg32Names ; Map(declReg32) , flagNames ; Map(declFlag) ) ''')
parse.Transfs(''' ppId = strings.tostr ppAttr = Attr(name, value) -> H([ <ppId name>, "=", <ppId value> ]) ppAttrs = !H([ "[", <Map(ppAttr); box.commas>, "]" ]) ppNode = Node(nid, attrs, _) -> H([ <ppId nid>, <ppAttrs attrs> ]) ppNodes = lists.Map(ppNode) ppNodeEdge = Edge(dst, attrs) -> H([ <ppId src>, "->", <ppId dst>, <ppAttrs attrs> ]) ppNodeEdges = Node(src, _, edges) -> <Map(ppNodeEdge) edges> ppEdges = lists.MapConcat(ppNodeEdges) ppGraph = Graph(nodes) -> V([ H([ "digraph", " ", "{" ]), V( <ppNodes nodes> ), V( <ppEdges nodes> ), H([ "}" ]) ]) pprint = ppGraph ''')
parse.Transfs(''' Reg(reg) = !Sym(<reg>){Reg} eax = Reg(!"eax") ebx = Reg(!"ebx") ecx = Reg(!"ecx") edx = Reg(!"edx") esi = Reg(!"esi") edi = Reg(!"edi") ebp = Reg(!"ebp") esp = Reg(!"esp") ax = Reg(!"ax") bx = Reg(!"bx") cx = Reg(!"cx") dx = Reg(!"dx") si = Reg(!"si") di = Reg(!"di") bp = Reg(!"bp") sp = Reg(!"sp") ah = Reg(!"ah") bh = Reg(!"bh") ch = Reg(!"ch") dh = Reg(!"dh") al = Reg(!"al") bl = Reg(!"bl") cl = Reg(!"cl") dl = Reg(!"dl") af = Reg(!"af") cf = Reg(!"cf") sf = Reg(!"sf") of = Reg(!"of") pf = Reg(!"pf") zf = Reg(!"zf") df = Reg(!"df") if_ = Reg(!"if") ''')
parse.Transfs(''' applicable = ir.path.Applicable( ~Module(< lists.One(ir.path.isSelected ; ?Label(_) ) >) ) input = ir.path.Input2( ir.path.projectSelection => Label(label) ; ![label] ) apply = [root, [label]] -> root ; ~Module(<AtSuffix( {rest: ~[Label(?label), *<AtSuffix( ~[Ret(_,_), *<?rest ; ![]>] )>] ; ![Function(Void, label, [], <project.tail>), *rest] } )>) testApply = !Module([ Asm("pre",[]), Label("main"), Assign(Int(32,Signed),Sym("eax"),Lit(Int(32,Signed),1)), Ret(Int(32,Signed),Sym("eax")), Asm("post",[]), ]) ; apply [<id>, ["main"]] ; ?Module([ Asm("pre",[]), Function(Void,"main",[],[ Assign(Int(32,Signed),Sym("eax"),Lit(Int(32,Signed),1)), Ret(Int(32,Signed),Sym("eax")) ]), Asm("post",[]), ]) ''')
parse.Transfs(''' ####################################################################### # Local variable table shared local as table # TODO: detect local variables from scope rules isReg = annotation.Has(?Reg) isTmp = annotation.Has(?Tmp) isLocalVar = ir.match.aSym ; (isReg + isTmp) updateLocalVar = isLocalVar ; Where(local.set [_,_] ) updateLocalVars = local.clear ; traverse.AllTD(updateLocalVar) EnterFunction(operand) = with local in updateLocalVars ; operand end EnterModule(operand) = EnterFunction(operand) ''')