⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cacheann.hs

📁 深入理解计算机系统(computer system:a programmer s perpective)是一本非常经典的教材
💻 HS
📖 第 1 页 / 共 4 页
字号:
{------------------------------------------------------------------------}{--- An assembly code annotator for gcc >= 2.7.X on x86-linux-2.X     ---}{---                                                      CacheAnn.hs ---}{------------------------------------------------------------------------}{-    This file is part of Cacheprof, a profiling tool for finding   sources of cache misses in programs.   Copyright (C) 1999 Julian Seward (jseward@acm.org)   Home page: http://www.cacheprof.org   This program is free software; you can redistribute it and/or   modify it under the terms of the GNU General Public License as   published by the Free Software Foundation; either version 2 of the   License, or (at your option) any later version.   This program is distributed in the hope that it will be useful, but   WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307, USA.   The GNU General Public License is contained in the file LICENSE.-}module Main ( main ) whereimport Charimport Listimport IOimport Systemimport Arch_x86import Generics{-----------------------------------------------------------}{--- Stage 1.  Break input string into pre-parsed lines  ---}{-----------------------------------------------------------}-- This stage is separated from instruction parsing-- proper mostly for conceptual cleanliness.-- Lines can either be:--    a label definition, on its own (Label)--    an instruction (Real)--    anything else (Pseudo)-- If instruction counting is to work properly,-- labels should not be concealed inside Pseudos. data PreLine   = PrePseudo Int String   | PreLabel  Int String   | PreReal   Int String     deriving Showinstance PP PreLine where   pp m (PrePseudo ln s)  = "preP: " ++ s   pp m (PreLabel  ln s)  = "preL: " ++ s   pp m (PreReal   ln s)  = "preR: " ++ s-- section-mainpreparse :: String -> [PreLine]preparse     = concatMap preparseLine . zip [1..] . linespreparseLine :: (Int, String) -> [PreLine]preparseLine (line_number,s)   | null cleaned    = []   | looks_like_label cleaned   = case span isLabelIsh cleaned of        (label_name, rest)            -> (PreLabel line_number (label_name ++ [head rest]))              : preparseLine (line_number, tail rest)   | head cleaned `elem` ".#"   = [PrePseudo line_number s]   | otherwise   = case span (/= ';') cleaned of        (presemi, postsemi)           -> (PreReal line_number presemi)              : preparseLine (line_number, drop 1 postsemi)     where        cleaned    = dropWhile isSpace s        untabbed x = not (null x) && head x /= '\t'        looks_like_label :: String -> Bool        looks_like_label x            = case span isLabelIsh x of                (label_name, rest)                    -> not (null label_name)                       && take 1 rest == ":"                      && (null (tail rest)                           || isSpace (head (tail rest))){-----------------------------------------------------------}{--- Stage 2.  Parse instructions.                       ---}{-----------------------------------------------------------}-- Turn the list of PreLines into Lines by parsing-- the instructions.data PPM    = PPM_Debug | PPM_User     deriving Eqclass PP a where   pp  :: PPM -> a -> String   ppu :: a -> String   ppd :: a -> String   ppl :: PPM -> [a] -> String   ppu = pp PPM_User   ppd = pp PPM_Debug   ppl m = concat . intersperse "," . map (pp m)data Line    = Pseudo Int String   | Label  Int String   | Real   Int CC Insn     deriving (Show, Eq)instance PP Line where   pp PPM_User  (Pseudo ln s)     = s   pp PPM_Debug (Pseudo ln s)     = "P: " ++ s   pp PPM_User  (Label ln s)      = s   pp PPM_Debug (Label ln s)      = "L: " ++ s   pp PPM_User  (Real ln cc insn)       = "\t" ++ pp PPM_User insn   pp PPM_Debug (Real ln cc insn)       = "R:        " ++ pp PPM_Debug insn ++       if   isNoCC cc        then ""       else "\n             CC = " ++ pp PPM_Debug ccgetLineNo (Pseudo ln s)    = lngetLineNo (Label  ln s)    = lngetLineNo (Real   ln cc i) = lninsnOfLine (Real ln cc i) = iinsnOfLine other          = internal "insnOfLine"isReal (Real ln cc i) = TrueisReal other          = FalseisPseudo (Pseudo ln s) = TrueisPseudo other         = Falsedata CC   = NoCC   | CC String Int String  -- file name, line no, fn name     deriving (Show, Eq)instance PP CC where   pp ppm NoCC = "NoCC"   pp ppm (CC filename lineno fnname)      = filename ++ ":" ++ show lineno ++ " " ++ fnnamesetCC (Real ln oldcc i) cc = Real ln cc isetCC other             cc = internal "setCC"getCC (Real ln cc i) = ccgetCC other          = NoCCisNoCC NoCC       = TrueisNoCC (CC _ _ _) = FalseccGetFileNm (CC filenm ln funcnm) = filenmccGetLineNo (CC filenm ln funcnm) = lnccGetFuncNm (CC filenm ln funcnm) = funcnm-- section-mainparse :: [PreLine] -> [Line]parse    = map f     where         f (PrePseudo ln s) = Pseudo ln s        f (PreLabel  ln s) = Label  ln s        f (PreReal   ln s)           = case pInsn (olex s) of                POk i [] -> Real ln NoCC i                _        -> bomb ln s           bomb ln s           = inputerr ("(stdin):" ++ show ln                       ++ ": syntax error on `" ++ s ++ "'\n" ) {-------------------------------------------}{--- an lexer for x86,                   ---}{--- using the AT&T syntax               ---}{-------------------------------------------}olex :: String -> [Lex]olex [] = []olex (c:cs)   | isSpace c = olex cs   | c == '('  = LLParen : olex cs   | c == ')'  = LRParen : olex cs   | c == ','  = LComma  : olex cs   | c == '+'  = LPlus   : olex cs   | c == '-'  = LMinus  : olex cs   | c == '*'  = LStar   : olex cs   | c == '$'  = LDollar : olex cs   | c == '#'  = []   -- comment; arch specific   | c == '%'   = case span isAlpha cs of         (rname, rest)           | rname == "st" && not (null rest)              && head rest == '('           -> case span (`elem` "(01234567)") rest of                 (frname,rest2) -> (LReg (c:rname++frname)) : olex rest2           | (c:rname) `elem` reg_names           -> (LReg (c:rname)) : olex rest           | otherwise           -> barf (c:cs)   | isDigit c   = case span isDigitish cs of         (num, rest) -> (LNum (c:num)) : olex rest   | isAlpha c || c == '_'   = case span isNameIsh cs of        (nmcs, rest) -> (LName (c:nmcs)) : olex rest   | c == '.'   = case span isLabelIsh cs of        (lbcs, rest) -> (LLabel (c:lbcs)) : olex rest   | otherwise   = barf (c:cs)isDigitish c = isDigit c || c `elem` "xabcdefABCDEF"isNameIsh c  = isAlpha c || isDigit c || c == '_' || c == '.'isLabelIsh c = isAlpha c || isDigit c || c == '.' || c == '_'isRegChar c  = isAlpha c || c `elem` "(0)"barf s = inputerr ( "lexical error on: `" ++ s ++ "'"){-------------------------------------------}{--- an instruction parser for x86,      ---}{--- using the AT&T syntax               ---}{-------------------------------------------}{- operand ::= reg             | $ const             | const             | const amode             | amode   amode ::= (reg)          -- B           | (reg,reg)      -- B I           | (,reg,num)     -- I S           | (reg,reg,num)  -- B I S    const  ::= (OPTIONAL '-') const_factor                              (ZEROORMORE signed_const_factor)   signed_const_factor ::=   + const_factor                         |   - const_factor   const_factor ::= const_atom                  | const_atom '*' const_factor                  | '(' const_factor ')'   const_atom ::= number                | label                | name   reg ::=  %eax | %ebx | %ecx | %edx | %esi | %edi | %ebp | %esp ...-}data Annot   = AnnR Int Operand   | AnnM Int Operand   | AnnW Int Operand   | AnnC String        -- just a comment     deriving (Show, Eq)getAnnOp (AnnR w o) = ogetAnnOp (AnnM w o) = ogetAnnOp (AnnW w o) = oisAnnC (AnnC _) = TrueisAnnC _        = FalsemkAnnC comment = SomeAnns [AnnC comment]mkNoAnns = SomeAnns []hasRealAnns (Insn ann _ _)   = (not . null . filter (not.isAnnC) . getAnns) anndata Anns   = DontAnnMe   | SomeAnns [Annot]     deriving (Show, Eq)getAnns DontAnnMe       = []getAnns (SomeAnns anns) = annsisDontAnnMe DontAnnMe = TrueisDontAnnMe _         = Falsedata Insn    = Insn Anns Opcode [Operand]     deriving (Show, Eq)annsOfInsn   (Insn anns opcode operand) = annsopcodeOfInsn (Insn anns opcode operand) = opcodedata Operand   = OP_REG   Reg   | OP_LIT   Const   | OP_D     Const   | OP_DA    Const AMode   | OP_A     AMode   | OP_STAR  Operand     deriving (Show, Eq)data AMode   = AM_B   Reg     | AM_BI  Reg Reg   | AM_IS  Reg String   | AM_BIS Reg Reg String     deriving (Show, Eq)newtype Const    = Const [SignedFactor]     deriving (Show, Eq)data SignedFactor  = Neg UnsignedFactor | Pos UnsignedFactor     deriving (Show, Eq)data UnsignedFactor   = UF_NUM String     | UF_NAME String    | UF_LABEL String   | UF_TIMES UnsignedFactor UnsignedFactor     deriving (Show, Eq)data Reg    = EAX | EBX | ECX | EDX | EDI | ESI | EBP | ESP   | AX | BX | CX | DX | SI | DI | BP   | AL | BL | CL | DL   | AH | BH | CH | DH   | ST_0 | ST_1 | ST_2 | ST_3    | ST_4 | ST_5 | ST_6 | ST_7     deriving (Show, Eq)pOpcode :: Parser OpcodepOpcode   = pAlts (map (\o -> pName (drop 2 (show (fst o))) (fst o)) x86info)pInsn :: Parser InsnpInsn    = p2 (Insn (SomeAnns [])) pOpcode (pStarComma pOperand)pOperand :: Parser OperandpOperand   = pAlts [        pApply OP_REG pReg,        p2 (\_ c -> OP_LIT c) pLDollar pConst,        p2 (\c a -> OP_DA c a) pConst pAMode,        pApply (\c -> OP_D c) pConst,        pApply (\a -> OP_A a) pAMode,        p2 (\_ operand -> OP_STAR operand) pLStar pOperand

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -