assembler-0.0.1: src/Text/Assembler/PPC64.hs
-----------------------------------------------------------------------------
--
-- Module : Text.Assembler.PPC64
-- Copyright : (c) Jeff Douglas
-- License : BSD3
--
-- Maintainer : Jeff Douglas
-- Stability : experimental
-- Portability : portable
--
-- |
--
-----------------------------------------------------------------------------
module Text.Assembler.PPC64 (instruction,parseInstructions) where
import Prelude hiding (and,or)
import Data.Bits hiding (xor)
import qualified Data.Map as Map
import Data.Word
import Text.Parsec
import Text.Parsec.String
import Text.Parsec.Combinator
import Control.Monad
import Control.Applicative hiding ((<|>))
parseInstructions = many1 instruction
-- parsing --
instruction :: Parser Word32
instruction = foldl1 (<|>) (fmap try instructions) <* char '\n'
instructions = [
b,ba,b,bla,bc,bca,bcl,bcla,bclr ,bclrl ,bcctr ,bcctrl ,
sc ,
crand ,cror ,crxor ,crnand ,crnor ,creqv ,crandc ,crorc ,
mcrf ,
lbz,lbzx,lbzu,lbzux,lhz,lhzx,lhzu,lhzux,lha,lhax,lhau,lhaux,lwz,lwzx,lwzu,lwzux,lwa,lwax,lwaux,ld,ldx,ldu,ldux,
stb ,stbx ,stbu ,stbux ,sth ,sthx ,sthu ,sthux ,stw ,stwx ,stwu ,stwux ,std ,stdx ,stdu ,stdux ,
lhbrx ,lwbrx ,sthbrx ,stwbrx ,
lmw,stmw,
lswi ,lswx ,stswi ,stswx ,
addi,addis,add,add_,addo,addo_,subf,subf_,subfo,subfo_,addic,addic_,subfic,addc,addc_,addco,addco_,subfc,subfc_,subfco,
subfco_,adde,adde_,addeo,addeo_,subfe,subfe_,subfeo,subfeo_,addme,addme_,addmeo,addmeo_,subfme,subfme_,
subfmeo,subfmeo_,addze,addze_,addzeo,addzeo_,subfze,subfze_,subfzeo,subfzeo_,neg,neg_,nego,nego_,mulli,mulld,
mulld_,mulldo,mulldo_,mullw,mullw_,mullwo,mullwo_,mulhd,mulhd_,mulhw,mulhw_,mulhdu,mulhdu_,mulhwu,
mulhwu_,divd,divd_,divdo,divdo_,divw,divw_,divwo,divwo_,divdu,divdu_,divduo,divduo_,divwu,divwu_,divwuo,divwuo_,
cmpi,cmp,cmpli,cmpl,
tdi,twi,td,tw,
andi_ ,andis_ ,ori ,oris ,xori ,xors ,and ,and_ ,or ,or_ ,xor ,xor_ ,nand ,nand_ ,nor ,nor_ ,eqv ,eqv_ ,andc ,andc_ ,orc ,orc_ ,extsb ,extsb_ ,extsh ,extsh_ ,extsw ,extsw_ ,cntlzd ,cntlzd_ ,popcntb ,cntlzw ,cntlzw_ ,
rldicl ,rldicl_ ,rldicr ,rldicr_ ,rldic ,rldic_ ,rlwinm ,rlwinm_ ,rldcl ,rldcl_ ,rldcr ,rldcr_ ,rlwnm ,rlwnm_ ,rldimi ,rldimi_ ,rlwimi ,rlwimi_ ,
sld ,sld_ ,slw ,slw_ ,srd ,srd_ ,srw ,srw_ ,sradi ,sradi_ ,srawi ,srawi_ ,srad ,srad_ ,sraw ,sraw_ ,
mtspr ,mfspr ,mtcrf ,
lfs
]
comma = char ','
mnem m = string m >> space
iLit :: Parser Word32
iLit = liftM read (many1 digit)
(<.>) p n = p<*comma<*>n
(<@>) p n = p<*char '('<*>n<*char ')'
infixl 1 <.>
infixl 1 <@>
-- branch instructions
b = ins "b" v1 $ iform 18 0 0
ba = ins "ba" v1 $ iform 18 1 0
bl = ins "bl" v1 $ iform 18 0 1
bla = ins "bla" v1 $ iform 18 1 1
bc = ins "bc" csv3 $ bform 16 0 0
bca = ins "bca" csv3 $ bform 16 1 0
bcl = ins "bcl" csv3 $ bform 16 0 1
bcla = ins "bcla" csv3 $ bform 16 1 1
bclr = ins "bclr" csv3 $ xlform'b 19 16 0
bclrl = ins "bclrl" csv3 $ xlform'b 19 16 1
bcctr = ins "bcctr" csv3 $ xlform'b 19 528 0
bcctrl = ins "bcctrl" csv3 $ xlform'b 19 528 1
-- system call instruction
sc = ins "sc" v1 $ scform 17
-- condition register logical instructions
crand = ins "crand" csv3 $ xlform'a 19 257
cror = ins "cror" csv3 $ xlform'a 19 449
crxor = ins "cxor" csv3 $ xlform'a 19 193
crnand = ins "crnand" csv3 $ xlform'a 19 225
crnor = ins "crnor" csv3 $ xlform'a 19 33
creqv = ins "creqv" csv3 $ xlform'a 19 289
crandc = ins "crandc" csv3 $ xlform'a 19 129
crorc = ins "crorc" csv3 $ xlform'a 19 417
-- condition register field instruction
mcrf = ins "mcrf" csv2 $ xlform'c 19 0
-- fixed point load instructions
lbz = ins "lbz" csv3 $ dform'a 34
lbzx = ins "lbzx" csv3 $ xform'a 31 87
lbzu = ins "lbzu" csv3 $ dform'a 35
lbzux = ins "lbzux" csv3 $ xform'a 31 119
lhz = ins "lhz" csv3 $ dform'a 40
lhzx = ins "lhz" csv3 $ xform'a 31 279
lhzu = ins "lhzu" csv3 $ dform'a 41
lhzux = ins "lhzux" csv3 $ xform'a 31 311
lha = ins "lha" csv3 $ dform'a 42
lhax = ins "lhax" csv3 $ xform'a 31 343
lhau = ins "lhau" csv3 $ dform'a 43
lhaux = ins "lhaux" csv3 $ xform'a 31 375
lwz = ins "lwz" csv3 $ dform'a 32
lwzx = ins "lwzx" csv3 $ xform'a 31 23
lwzu = ins "lwzu" csv3 $ dform'a 33
lwzux = ins "lwzux" csv3 $ xform'a 31 55
lwa = ins "lwa" csv3 $ dsform 58 2
lwax = ins "lwax" csv3 $ xform'a 31 341
lwaux = ins "lwaux" csv3 $ xform'a 31 373
ld = ins "ld" csv3 $ dsform 58 151
ldx = ins "ldx" csv3 $ xform'a 31 21
ldu = ins "ldu" csv3 $ dsform 58 1
ldux = ins "ldux" csv3 $ xform'a 31 53
-- fixed point store instructions
stb = ins "stb" csv3 $ dform'a 38
stbx = ins "stbx" csv3 $ xform'a 31 215
stbu = ins "stbu" csv3 $ dform'a 39
stbux = ins "stbux" csv3 $ xform'a 31 247
sth = ins "sth" csv3 $ dform'a 44
sthx = ins "sthx" csv3 $ xform'a 31 407
sthu = ins "sthu" csv3 $ dform'a 45
sthux = ins "sthux" csv3 $ xform'a 31 439
stw = ins "stw" csv3 $ dform'a 36
stwx = ins "stwx" csv3 $ xform'a 31 151
stwu = ins "stwu" csv3 $ dform'a 37
stwux = ins "stwux" csv3 $ xform'a 31 183
std = ins "std" csv3 $ dsform 62 0
stdx = ins "stdx" csv3 $ xform'a 31 149
stdu = ins "stdu" csv3 $ dsform 37 1
stdux = ins "stdux" csv3 $ xform'a 31 181
-- fixed-point load and store with byte reversal instructions
lhbrx = ins "lhbrx" csv3 $ xform'a 31 790
lwbrx = ins "lwbrx" csv3 $ xform'a 31 534
sthbrx = ins "sthbrx" csv3 $ xform'a 31 918
stwbrx = ins "stwbrx" csv3 $ xform'a 31 662
-- fixed point load and store multiple instructions
lmw = ins "lmw" csv3 $ dform'a 46
stmw = ins "stmw" csv3 $ dform'a 47
-- fixed point move assist instructions
lswi = ins "lswi" csv3 $ xform'a 31 597
lswx = ins "lswx" csv3 $ xform'a 31 533
stswi = ins "stswi" csv3 $ xform'a 31 725
stswx = ins "stswx" csv3 $ xform'a 31 661
--fixed point arithmetic instructions
addi = ins "addi" csv3 $ dform'a 14
addis = ins "addis" csv3 $ dform'a 15
add = ins "add" csv3 $ xoform 31 266 0 0
add_ = ins "add." csv3 $ xoform 31 266 0 1
addo = ins "addo" csv3 $ xoform 31 266 1 0
addo_ = ins "addo." csv3 $ xoform 31 266 1 1
subf = ins "subf" csv3 $ xoform 31 40 0 0
subf_ = ins "subf." csv3 $ xoform 31 40 0 1
subfo = ins "subfo" csv3 $ xoform 31 40 1 0
subfo_ = ins "subfo." csv3 $ xoform 31 40 1 1
addic = ins "addic" csv3 $ dform'a 12
addic_ = ins "addic." csv3 $ dform'a 13
subfic = ins "subfic" csv3 $ dform'a 8
addc = ins "addc" csv3 $ xoform 31 10 0 0
addc_ = ins "addc." csv3 $ xoform 31 10 0 1
addco = ins "addco" csv3 $ xoform 31 10 1 0
addco_ = ins "addco." csv3 $ xoform 31 10 1 1
subfc = ins "subfc" csv3 $ xoform 31 8 0 0
subfc_ = ins "subfc." csv3 $ xoform 31 8 0 1
subfco = ins "subfco" csv3 $ xoform 31 8 1 1
subfco_ = ins "subfco." csv3 $ xoform 31 8 1 1
adde = ins "adde" csv3 $ xoform 31 138 0 0
adde_ = ins "adde." csv3 $ xoform 31 138 0 1
addeo = ins "addeo" csv3 $ xoform 31 138 1 0
addeo_ = ins "addeo." csv3 $ xoform 31 138 1 1
subfe = ins "subfe" csv3 $ xoform 31 136 0 0
subfe_ = ins "subfe." csv3 $ xoform 31 136 0 1
subfeo = ins "subfeo" csv3 $ xoform 31 136 1 0
subfeo_ = ins "subfeo." csv3 $ xoform 31 136 1 1
addme = ins "addme" csv2 $ xoform' 31 234 0 0
addme_ = ins "addme." csv2 $ xoform' 31 234 0 1
addmeo = ins "addmeo" csv2 $ xoform' 31 234 1 0
addmeo_ = ins "addmeo." csv2 $ xoform' 31 234 1 1
subfme = ins "subfme" csv2 $ xoform' 31 232 0 0
subfme_ = ins "subfme." csv2 $ xoform' 31 232 0 1
subfmeo = ins "subfmeo" csv2 $ xoform' 31 232 1 0
subfmeo_ = ins "subfmeo." csv2 $ xoform' 31 232 1 1
addze = ins "addze" csv2 $ xoform' 31 202 0 0
addze_ = ins "addze." csv2 $ xoform' 31 202 0 1
addzeo = ins "addzeo" csv2 $ xoform' 31 202 1 0
addzeo_ = ins "addzeo." csv2 $ xoform' 31 202 1 1
subfze = ins "subfze" csv2 $ xoform' 31 202 0 0
subfze_ = ins "subfze." csv2 $ xoform' 31 202 0 1
subfzeo = ins "subfzeo" csv2 $ xoform' 31 202 1 0
subfzeo_ = ins "subfzeo." csv2 $ xoform' 31 202 1 1
neg = ins "neg" csv2 $ xoform' 31 104 0 0
neg_ = ins "neg." csv2 $ xoform' 31 104 0 1
nego = ins "nego" csv2 $ xoform' 31 104 1 0
nego_ = ins "nego." csv2 $ xoform' 31 104 1 1
mulli = ins "mulli" csv3 $ dform'a 7
mulld = ins "mulld" csv3 $ xoform 31 233 0 0
mulld_ = ins "mulld." csv3 $ xoform 31 233 0 1
mulldo = ins "mulldo" csv3 $ xoform 31 233 1 0
mulldo_ = ins "mulldo." csv3 $ xoform 31 233 1 1
mullw = ins "mullw" csv3 $ xoform 31 235 0 0
mullw_ = ins "mullw." csv3 $ xoform 31 235 0 1
mullwo = ins "mullwo" csv3 $ xoform 31 235 1 0
mullwo_ = ins "mullwo." csv3 $ xoform 31 235 1 1
mulhd = ins "mulhd" csv3 $ xoform 31 73 0 0
mulhd_ = ins "mulhd." csv3 $ xoform 31 73 0 1
mulhw = ins "mulhw" csv3 $ xoform 31 75 0 0
mulhw_ = ins "mulhw." csv3 $ xoform 31 75 0 1
mulhdu = ins "mulhdu" csv3 $ xoform 31 9 0 0
mulhdu_ = ins "mulhdu." csv3 $ xoform 31 9 0 1
mulhwu = ins "mulhwu" csv3 $ xoform 31 11 0 0
mulhwu_ = ins "mulhwu." csv3 $ xoform 31 11 0 1
divd = ins "divd" csv3 $ xoform 31 489 0 0
divd_ = ins "divd." csv3 $ xoform 31 489 0 1
divdo = ins "divdo" csv3 $ xoform 31 489 1 0
divdo_ = ins "divdo." csv3 $ xoform 31 489 1 1
divw = ins "divw" csv3 $ xoform 31 491 0 0
divw_ = ins "divw." csv3 $ xoform 31 491 0 1
divwo = ins "divwo" csv3 $ xoform 31 491 1 0
divwo_ = ins "divwo." csv3 $ xoform 31 491 1 1
divdu = ins "divdu" csv3 $ xoform 31 457 0 0
divdu_ = ins "divdu." csv3 $ xoform 31 457 0 1
divduo = ins "divduo" csv3 $ xoform 31 457 1 0
divduo_ = ins "divduo." csv3 $ xoform 31 457 1 1
divwu = ins "divwu" csv3 $ xoform 31 459 0 0
divwu_ = ins "divwu." csv3 $ xoform 31 459 0 1
divwuo = ins "divdwo" csv3 $ xoform 31 459 1 0
divwuo_ = ins "divdwo." csv3 $ xoform 31 459 1 1
-- fixed-point compare instructions
-- check out bit 9 in cmp
cmpi = ins "cmpi" csv3 $ dform'b 11 0
-- check out bit 9 in cmp
cmp = ins "cmp" csv3 $ xform'b 31 0 0
-- check out bit 9 in cmpli
cmpli = ins "cmpli" csv3 $ dform'b 10 0
-- check out bit 9 in cmpl
cmpl = ins "cmpl" csv3 $ xform'b 32 0 0
-- fixed-point trap instructions
tdi = ins "tdi" csv3 $ dform'a 2
twi = ins "twi" csv3 $ dform'a 3
td = ins "td" csv3 $ xform'a 31 68
tw = ins "tw" csv3 $ xform'a 31 4
-- fixed-point logical instructions
andi_ = ins "andi." csv3 $ dform'a 28
andis_ = ins "andis" csv3 $ dform'a 29
ori = ins "ori" csv3 $ dform'a 24
oris = ins "oris" csv3 $ dform'a 25
xori = ins "ori" csv3 $ dform'a 26
xors = ins "oris" csv3 $ dform'a 27
and = ins "and" csv3 $ xform'c 31 28 0
and_ = ins "and." csv3 $ xform'c 31 28 1
or = ins "or" csv3 $ xform'c 31 444 0
or_ = ins "or." csv3 $ xform'c 31 444 1
xor = ins "xor" csv3 $ xform'c 31 316 0
xor_ = ins "xor." csv3 $ xform'c 31 316 1
nand = ins "nand" csv3 $ xform'c 31 476 0
nand_ = ins "nand." csv3 $ xform'c 31 476 1
nor = ins "nor" csv3 $ xform'c 31 124 0
nor_ = ins "nor." csv3 $ xform'c 31 124 1
eqv = ins "eqv" csv3 $ xform'c 31 284 0
eqv_ = ins "eqv." csv3 $ xform'c 31 284 1
andc = ins "andc" csv3 $ xform'c 31 60 0
andc_ = ins "andc." csv3 $ xform'c 31 60 1
orc = ins "orc" csv3 $ xform'c 31 412 0
orc_ = ins "orc." csv3 $ xform'c 31 412 1
extsb = ins "extsb" csv2 $ xform'd 31 954 0
extsb_ = ins "extsb." csv2 $ xform'd 31 954 1
extsh = ins "extsh" csv2 $ xform'd 31 922 0
extsh_ = ins "extsh." csv2 $ xform'd 31 922 1
extsw = ins "extsw" csv2 $ xform'd 31 986 0
extsw_ = ins "extsw." csv2 $ xform'd 31 986 1
cntlzd = ins "cntlzd" csv2 $ xform'd 31 58 0
cntlzd_ = ins "cntlzd." csv2 $ xform'd 31 58 1
popcntb = ins "popcntb" csv2 $ xform'd 31 122 0
cntlzw = ins "cntlzw" csv2 $ xform'd 31 26 0
cntlzw_ = ins "cntlzw." csv2 $ xform'd 31 26 1
-- fixed-point rotate and shift instructions
rldicl = ins "rldicl" csv4 $ mdform 30 0 0
rldicl_ = ins "rldicl." csv4 $ mdform 30 0 1
rldicr = ins "rldicr" csv4 $ mdform 30 1 0
rldicr_ = ins "rldicr." csv4 $ mdform 30 1 1
rldic = ins "rldic" csv4 $ mdform 30 2 0
rldic_ = ins "rldic." csv4 $ mdform 30 2 1
rlwinm = ins "rlwinm" csv5 $ mform 21 0
rlwinm_ = ins "rlwinm." csv5 $ mform 21 1
rldcl = ins "rldcl" csv4 $ mdsform 30 8 0
rldcl_ = ins "rldcl." csv4 $ mdsform 30 8 1
rldcr = ins "rldcr" csv4 $ mdsform 30 9 0
rldcr_ = ins "rldcr." csv4 $ mdsform 30 9 1
rlwnm = ins "rlwnm" csv5 $ mform 23 0
rlwnm_ = ins "rlwnm." csv5 $ mform 23 1
rldimi = ins "rldimi" csv4 $ mdform 30 3 0
rldimi_ = ins "rldimi." csv4 $ mdform 30 3 1
rlwimi = ins "rlwimi" csv5 $ mform 20 0
rlwimi_ = ins "rlwimi." csv5 $ mform 20 1
-- fixed-point shift instructions
sld = ins "sld" csv3 $ xform'c 31 27 0
sld_ = ins "sld." csv3 $ xform'c 31 27 1
slw = ins "slw" csv3 $ xform'c 31 24 0
slw_ = ins "slw." csv3 $ xform'c 31 24 1
srd = ins "srd" csv3 $ xform'c 31 539 0
srd_ = ins "srd." csv3 $ xform'c 31 539 1
srw = ins "srw" csv3 $ xform'c 31 536 0
srw_ = ins "srw." csv3 $ xform'c 31 536 1
sradi = ins "sradi" csv3 $ xsform 31 413 0
sradi_ = ins "sradi." csv3 $ xsform 31 413 1
srawi = ins "srawi" csv3 $ xform'c 31 824 0
srawi_ = ins "srawi." csv3 $ xform'c 31 824 1
srad = ins "srad" csv3 $ xform'c 31 794 0
srad_ = ins "srad." csv3 $ xform'c 31 794 1
sraw = ins "sraw" csv3 $ xform'c 31 792 0
sraw_ = ins "sraw." csv3 $ xform'c 31 792 1
-- move to/from system register instructions
mtspr = ins "mtspr" csv2 $ xfxform 31 467
mfspr = ins "mfspr" csv2 $ xfxform 31 339
mtcrf = ins "mtcrf" csv2 $ xfxform'b 31 0 144
-- floating-point processor instructions --
-- floating-point load instructions
lfs = ins "lfs" csv3 $ dform'a 48
---
ins m form e = mnem m>>form e
v1 f = f<$>iLit
csv2 f =f<$>iLit<.>iLit
csv3 f = f<$>iLit<.>iLit<.>iLit
csv4 f = f<$>iLit<.>iLit<.>iLit<.>iLit
csv5 f = f<$>iLit<.>iLit<.>iLit<.>iLit<.>iLit
-- instruction fomats
iform opcd aa lk li = pack [(opcd,6),(li,30),(aa,31),(lk,0)]
bform opcd aa lk bo bi bd = pack [(opcd,6),(bo,11),(bi,16),(bd,30),(aa,31),(lk,0)]
scform opcd lev = pack [(opcd,6),(lev,27),(1,31)]
dform'a opcd rt ra d = pack [(opcd,6),(rt,11),(ra,16),(d,0)]
dform'b opcd bf l ra si = pack [(opcd,6),(bf,9),(0,10),(l,11),(ra,16),(si,0)]
dsform opcd rt ra ds xo = pack [(opcd,6),(rt,11),(ra,16),(ds,30),(xo,0)]
xform'a opcd rt ra rb xo = pack [(opcd,6),(rt,11),(ra,16),(rb,21),(xo,31)]
xform'b opcd xo bf l ra rb = pack [(opcd,6),(bf,9),(0,10),(l,11),(ra,16),(rb,21),(xo,31),(0,0)]
xform'c opcd xo rs ra rb rc = pack [(opcd,6),(rs,11),(ra,16),(rb,21),(xo,31),(rc,0)]
xform'd opcd xo rc rs ra = pack [(opcd,6),(rs,11),(ra,16),(0,21),(xo,31),(rc,0)]
xlform'a opcd xo bt ba bb = pack [(opcd,6),(bt,11),(ba,16),(bb,21),(xo,31)]
xlform'b opcd xo lk bo bi bh = pack [(opcd,6),(bo,11),(bi,16),(bh,21),(xo,31),(lk,0)]
xlform'c opcd xo bf bfa = pack [(opcd,6),(bf,9),(bfa,14),(xo,31)]
xfxform opcd xo rs spr = pack [(opcd,6),(rs,11),(spr,21),(xo,31)]
xfxform'b opcd h xo fxm rs = pack [(opcd,6),(rs,11),(h,12),(fxm,20),(xo,31)]
--xflform
-- fix xsform
xsform opcd xo rc ra rs sh = pack [(opcd,6),(rs,11),(ra,16),(sh,21),(xo,30),(sh,31),(rc,0)]
xoform opcd xo oe rc rt ra rb = pack [(opcd,6),(rt,11),(ra,16),(rb,21),(oe,22),(xo,31),(rc,0)]
xoform' opcd xo oe rc rt ra = pack [(opcd,6),(rt,11),(ra,16),(0,21),(oe,22),(xo,31),(rc,0)]
--aform
mform opcd rc ra rs sh mb me = pack [(opcd,6),(rs,11),(ra,16),(sh,21),(mb,26),(me,31),(rc,0)]
-- mdform needs to be fixed to handle sh correctly
mdform opcd h rc ra rs sh mb = pack [(opcd,6),(rs,11),(ra,16),(sh,21),(mb,27),(h,30),(sh,31),(rc,0)]
mdsform opcd h rc ra rs rb mb = pack [(opcd,6),(rs,11),(ra,16),(rb,21),(mb,27),(h,31),(rc,0)]
-- bit-packing --
pack bf = foldr1 (.|.) $ map (uncurry rotateR) bf