1 -----------------------------------------------------------------------------
3 -- Module : Text.Assembler.PPC64
4 -- Copyright : (c) Jeff Douglas
7 -- Maintainer : Jeff Douglas
8 -- Stability : experimental
9 -- Portability : portable
13 -----------------------------------------------------------------------------
15 module PPC64 (instruction,parseInstructions) where
17 import Prelude hiding (and,or)
19 import Data.Bits hiding (xor)
20 import qualified Data.Map as Map
23 import Text.Parsec.String
24 import Text.Parsec.Combinator
26 import Control.Applicative hiding ((<|>))
28 parseInstructions = many1 instruction
31 instruction :: Parser Word32
32 instruction = foldl1 (<|>) (fmap try instructions) <* char '\n'
35 b,ba,b,bla,bc,bca,bcl,bcla,bclr ,bclrl ,bcctr ,bcctrl ,
37 crand ,cror ,crxor ,crnand ,crnor ,creqv ,crandc ,crorc ,
39 lbz,lbzx,lbzu,lbzux,lhz,lhzx,lhzu,lhzux,lha,lhax,lhau,lhaux,lwz,lwzx,lwzu,lwzux,lwa,lwax,lwaux,ld,ldx,ldu,ldux,
40 stb ,stbx ,stbu ,stbux ,sth ,sthx ,sthu ,sthux ,stw ,stwx ,stwu ,stwux ,std ,stdx ,stdu ,stdux ,
41 lhbrx ,lwbrx ,sthbrx ,stwbrx ,
43 lswi ,lswx ,stswi ,stswx ,
44 addi,addis,add,add_,addo,addo_,subf,subf_,subfo,subfo_,addic,addic_,subfic,addc,addc_,addco,addco_,subfc,subfc_,subfco,
45 subfco_,adde,adde_,addeo,addeo_,subfe,subfe_,subfeo,subfeo_,addme,addme_,addmeo,addmeo_,subfme,subfme_,
46 subfmeo,subfmeo_,addze,addze_,addzeo,addzeo_,subfze,subfze_,subfzeo,subfzeo_,neg,neg_,nego,nego_,mulli,mulld,
47 mulld_,mulldo,mulldo_,mullw,mullw_,mullwo,mullwo_,mulhd,mulhd_,mulhw,mulhw_,mulhdu,mulhdu_,mulhwu,
48 mulhwu_,divd,divd_,divdo,divdo_,divw,divw_,divwo,divwo_,divdu,divdu_,divduo,divduo_,divwu,divwu_,divwuo,divwuo_,
51 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_ ,
52 rldicl ,rldicl_ ,rldicr ,rldicr_ ,rldic ,rldic_ ,rlwinm ,rlwinm_ ,rldcl ,rldcl_ ,rldcr ,rldcr_ ,rlwnm ,rlwnm_ ,rldimi ,rldimi_ ,rlwimi ,rlwimi_ ,
53 sld ,sld_ ,slw ,slw_ ,srd ,srd_ ,srw ,srw_ ,sradi ,sradi_ ,srawi ,srawi_ ,srad ,srad_ ,sraw ,sraw_ ,
59 mnem m = string m >> space
62 iLit = liftM read (many1 digit)
64 (<.>) p n = p<*comma<*>n
65 (<@>) p n = p<*char '('<*>n<*char ')'
69 -- branch instructions
70 b = ins "b" v1 $ iform 18 0 0
71 ba = ins "ba" v1 $ iform 18 1 0
72 bl = ins "bl" v1 $ iform 18 0 1
73 bla = ins "bla" v1 $ iform 18 1 1
75 bc = ins "bc" csv3 $ bform 16 0 0
76 bca = ins "bca" csv3 $ bform 16 1 0
77 bcl = ins "bcl" csv3 $ bform 16 0 1
78 bcla = ins "bcla" csv3 $ bform 16 1 1
80 bclr = ins "bclr" csv3 $ xlform'b 19 16 0
81 bclrl = ins "bclrl" csv3 $ xlform'b 19 16 1
83 bcctr = ins "bcctr" csv3 $ xlform'b 19 528 0
84 bcctrl = ins "bcctrl" csv3 $ xlform'b 19 528 1
86 -- system call instruction
87 sc = ins "sc" v1 $ scform 17
89 -- condition register logical instructions
90 crand = ins "crand" csv3 $ xlform'a 19 257
91 cror = ins "cror" csv3 $ xlform'a 19 449
92 crxor = ins "cxor" csv3 $ xlform'a 19 193
93 crnand = ins "crnand" csv3 $ xlform'a 19 225
94 crnor = ins "crnor" csv3 $ xlform'a 19 33
95 creqv = ins "creqv" csv3 $ xlform'a 19 289
96 crandc = ins "crandc" csv3 $ xlform'a 19 129
97 crorc = ins "crorc" csv3 $ xlform'a 19 417
99 -- condition register field instruction
100 mcrf = ins "mcrf" csv2 $ xlform'c 19 0
102 -- fixed point load instructions
103 lbz = ins "lbz" csv3 $ dform'a 34
104 lbzx = ins "lbzx" csv3 $ xform'a 31 87
105 lbzu = ins "lbzu" csv3 $ dform'a 35
106 lbzux = ins "lbzux" csv3 $ xform'a 31 119
107 lhz = ins "lhz" csv3 $ dform'a 40
108 lhzx = ins "lhz" csv3 $ xform'a 31 279
109 lhzu = ins "lhzu" csv3 $ dform'a 41
110 lhzux = ins "lhzux" csv3 $ xform'a 31 311
111 lha = ins "lha" csv3 $ dform'a 42
112 lhax = ins "lhax" csv3 $ xform'a 31 343
113 lhau = ins "lhau" csv3 $ dform'a 43
114 lhaux = ins "lhaux" csv3 $ xform'a 31 375
115 lwz = ins "lwz" csv3 $ dform'a 32
116 lwzx = ins "lwzx" csv3 $ xform'a 31 23
117 lwzu = ins "lwzu" csv3 $ dform'a 33
118 lwzux = ins "lwzux" csv3 $ xform'a 31 55
119 lwa = ins "lwa" csv3 $ dsform 58 2
120 lwax = ins "lwax" csv3 $ xform'a 31 341
121 lwaux = ins "lwaux" csv3 $ xform'a 31 373
122 ld = ins "ld" csv3 $ dsform 58 151
123 ldx = ins "ldx" csv3 $ xform'a 31 21
124 ldu = ins "ldu" csv3 $ dsform 58 1
125 ldux = ins "ldux" csv3 $ xform'a 31 53
127 -- fixed point store instructions
128 stb = ins "stb" csv3 $ dform'a 38
129 stbx = ins "stbx" csv3 $ xform'a 31 215
130 stbu = ins "stbu" csv3 $ dform'a 39
131 stbux = ins "stbux" csv3 $ xform'a 31 247
132 sth = ins "sth" csv3 $ dform'a 44
133 sthx = ins "sthx" csv3 $ xform'a 31 407
134 sthu = ins "sthu" csv3 $ dform'a 45
135 sthux = ins "sthux" csv3 $ xform'a 31 439
136 stw = ins "stw" csv3 $ dform'a 36
137 stwx = ins "stwx" csv3 $ xform'a 31 151
138 stwu = ins "stwu" csv3 $ dform'a 37
139 stwux = ins "stwux" csv3 $ xform'a 31 183
140 std = ins "std" csv3 $ dsform 62 0
141 stdx = ins "stdx" csv3 $ xform'a 31 149
142 stdu = ins "stdu" csv3 $ dsform 37 1
143 stdux = ins "stdux" csv3 $ xform'a 31 181
145 -- fixed-point load and store with byte reversal instructions
146 lhbrx = ins "lhbrx" csv3 $ xform'a 31 790
147 lwbrx = ins "lwbrx" csv3 $ xform'a 31 534
148 sthbrx = ins "sthbrx" csv3 $ xform'a 31 918
149 stwbrx = ins "stwbrx" csv3 $ xform'a 31 662
151 -- fixed point load and store multiple instructions
152 lmw = ins "lmw" csv3 $ dform'a 46
153 stmw = ins "stmw" csv3 $ dform'a 47
155 -- fixed point move assist instructions
156 lswi = ins "lswi" csv3 $ xform'a 31 597
157 lswx = ins "lswx" csv3 $ xform'a 31 533
158 stswi = ins "stswi" csv3 $ xform'a 31 725
159 stswx = ins "stswx" csv3 $ xform'a 31 661
161 --fixed point arithmetic instructions
162 addi = ins "addi" csv3 $ dform'a 14
163 addis = ins "addis" csv3 $ dform'a 15
165 add = ins "add" csv3 $ xoform 31 266 0 0
166 add_ = ins "add." csv3 $ xoform 31 266 0 1
167 addo = ins "addo" csv3 $ xoform 31 266 1 0
168 addo_ = ins "addo." csv3 $ xoform 31 266 1 1
169 subf = ins "subf" csv3 $ xoform 31 40 0 0
170 subf_ = ins "subf." csv3 $ xoform 31 40 0 1
171 subfo = ins "subfo" csv3 $ xoform 31 40 1 0
172 subfo_ = ins "subfo." csv3 $ xoform 31 40 1 1
174 addic = ins "addic" csv3 $ dform'a 12
175 addic_ = ins "addic." csv3 $ dform'a 13
176 subfic = ins "subfic" csv3 $ dform'a 8
178 addc = ins "addc" csv3 $ xoform 31 10 0 0
179 addc_ = ins "addc." csv3 $ xoform 31 10 0 1
180 addco = ins "addco" csv3 $ xoform 31 10 1 0
181 addco_ = ins "addco." csv3 $ xoform 31 10 1 1
183 subfc = ins "subfc" csv3 $ xoform 31 8 0 0
184 subfc_ = ins "subfc." csv3 $ xoform 31 8 0 1
185 subfco = ins "subfco" csv3 $ xoform 31 8 1 1
186 subfco_ = ins "subfco." csv3 $ xoform 31 8 1 1
188 adde = ins "adde" csv3 $ xoform 31 138 0 0
189 adde_ = ins "adde." csv3 $ xoform 31 138 0 1
190 addeo = ins "addeo" csv3 $ xoform 31 138 1 0
191 addeo_ = ins "addeo." csv3 $ xoform 31 138 1 1
193 subfe = ins "subfe" csv3 $ xoform 31 136 0 0
194 subfe_ = ins "subfe." csv3 $ xoform 31 136 0 1
195 subfeo = ins "subfeo" csv3 $ xoform 31 136 1 0
196 subfeo_ = ins "subfeo." csv3 $ xoform 31 136 1 1
198 addme = ins "addme" csv2 $ xoform' 31 234 0 0
199 addme_ = ins "addme." csv2 $ xoform' 31 234 0 1
200 addmeo = ins "addmeo" csv2 $ xoform' 31 234 1 0
201 addmeo_ = ins "addmeo." csv2 $ xoform' 31 234 1 1
203 subfme = ins "subfme" csv2 $ xoform' 31 232 0 0
204 subfme_ = ins "subfme." csv2 $ xoform' 31 232 0 1
205 subfmeo = ins "subfmeo" csv2 $ xoform' 31 232 1 0
206 subfmeo_ = ins "subfmeo." csv2 $ xoform' 31 232 1 1
208 addze = ins "addze" csv2 $ xoform' 31 202 0 0
209 addze_ = ins "addze." csv2 $ xoform' 31 202 0 1
210 addzeo = ins "addzeo" csv2 $ xoform' 31 202 1 0
211 addzeo_ = ins "addzeo." csv2 $ xoform' 31 202 1 1
213 subfze = ins "subfze" csv2 $ xoform' 31 202 0 0
214 subfze_ = ins "subfze." csv2 $ xoform' 31 202 0 1
215 subfzeo = ins "subfzeo" csv2 $ xoform' 31 202 1 0
216 subfzeo_ = ins "subfzeo." csv2 $ xoform' 31 202 1 1
218 neg = ins "neg" csv2 $ xoform' 31 104 0 0
219 neg_ = ins "neg." csv2 $ xoform' 31 104 0 1
220 nego = ins "nego" csv2 $ xoform' 31 104 1 0
221 nego_ = ins "nego." csv2 $ xoform' 31 104 1 1
223 mulli = ins "mulli" csv3 $ dform'a 7
225 mulld = ins "mulld" csv3 $ xoform 31 233 0 0
226 mulld_ = ins "mulld." csv3 $ xoform 31 233 0 1
227 mulldo = ins "mulldo" csv3 $ xoform 31 233 1 0
228 mulldo_ = ins "mulldo." csv3 $ xoform 31 233 1 1
230 mullw = ins "mullw" csv3 $ xoform 31 235 0 0
231 mullw_ = ins "mullw." csv3 $ xoform 31 235 0 1
232 mullwo = ins "mullwo" csv3 $ xoform 31 235 1 0
233 mullwo_ = ins "mullwo." csv3 $ xoform 31 235 1 1
235 mulhd = ins "mulhd" csv3 $ xoform 31 73 0 0
236 mulhd_ = ins "mulhd." csv3 $ xoform 31 73 0 1
238 mulhw = ins "mulhw" csv3 $ xoform 31 75 0 0
239 mulhw_ = ins "mulhw." csv3 $ xoform 31 75 0 1
241 mulhdu = ins "mulhdu" csv3 $ xoform 31 9 0 0
242 mulhdu_ = ins "mulhdu." csv3 $ xoform 31 9 0 1
244 mulhwu = ins "mulhwu" csv3 $ xoform 31 11 0 0
245 mulhwu_ = ins "mulhwu." csv3 $ xoform 31 11 0 1
247 divd = ins "divd" csv3 $ xoform 31 489 0 0
248 divd_ = ins "divd." csv3 $ xoform 31 489 0 1
249 divdo = ins "divdo" csv3 $ xoform 31 489 1 0
250 divdo_ = ins "divdo." csv3 $ xoform 31 489 1 1
252 divw = ins "divw" csv3 $ xoform 31 491 0 0
253 divw_ = ins "divw." csv3 $ xoform 31 491 0 1
254 divwo = ins "divwo" csv3 $ xoform 31 491 1 0
255 divwo_ = ins "divwo." csv3 $ xoform 31 491 1 1
257 divdu = ins "divdu" csv3 $ xoform 31 457 0 0
258 divdu_ = ins "divdu." csv3 $ xoform 31 457 0 1
259 divduo = ins "divduo" csv3 $ xoform 31 457 1 0
260 divduo_ = ins "divduo." csv3 $ xoform 31 457 1 1
262 divwu = ins "divwu" csv3 $ xoform 31 459 0 0
263 divwu_ = ins "divwu." csv3 $ xoform 31 459 0 1
264 divwuo = ins "divdwo" csv3 $ xoform 31 459 1 0
265 divwuo_ = ins "divdwo." csv3 $ xoform 31 459 1 1
267 -- fixed-point compare instructions
268 -- check out bit 9 in cmp
269 cmpi = ins "cmpi" csv3 $ dform'b 11 0
270 -- check out bit 9 in cmp
271 cmp = ins "cmp" csv3 $ xform'b 31 0 0
272 -- check out bit 9 in cmpli
273 cmpli = ins "cmpli" csv3 $ dform'b 10 0
274 -- check out bit 9 in cmpl
275 cmpl = ins "cmpl" csv3 $ xform'b 32 0 0
277 -- fixed-point trap instructions
278 tdi = ins "tdi" csv3 $ dform'a 2
279 twi = ins "twi" csv3 $ dform'a 3
280 td = ins "td" csv3 $ xform'a 31 68
281 tw = ins "tw" csv3 $ xform'a 31 4
283 -- fixed-point logical instructions
284 andi_ = ins "andi." csv3 $ dform'a 28
285 andis_ = ins "andis" csv3 $ dform'a 29
286 ori = ins "ori" csv3 $ dform'a 24
287 oris = ins "oris" csv3 $ dform'a 25
288 xori = ins "ori" csv3 $ dform'a 26
289 xors = ins "oris" csv3 $ dform'a 27
290 and = ins "and" csv3 $ xform'c 31 28 0
291 and_ = ins "and." csv3 $ xform'c 31 28 1
292 or = ins "or" csv3 $ xform'c 31 444 0
293 or_ = ins "or." csv3 $ xform'c 31 444 1
294 xor = ins "xor" csv3 $ xform'c 31 316 0
295 xor_ = ins "xor." csv3 $ xform'c 31 316 1
296 nand = ins "nand" csv3 $ xform'c 31 476 0
297 nand_ = ins "nand." csv3 $ xform'c 31 476 1
298 nor = ins "nor" csv3 $ xform'c 31 124 0
299 nor_ = ins "nor." csv3 $ xform'c 31 124 1
300 eqv = ins "eqv" csv3 $ xform'c 31 284 0
301 eqv_ = ins "eqv." csv3 $ xform'c 31 284 1
302 andc = ins "andc" csv3 $ xform'c 31 60 0
303 andc_ = ins "andc." csv3 $ xform'c 31 60 1
304 orc = ins "orc" csv3 $ xform'c 31 412 0
305 orc_ = ins "orc." csv3 $ xform'c 31 412 1
306 extsb = ins "extsb" csv2 $ xform'd 31 954 0
307 extsb_ = ins "extsb." csv2 $ xform'd 31 954 1
308 extsh = ins "extsh" csv2 $ xform'd 31 922 0
309 extsh_ = ins "extsh." csv2 $ xform'd 31 922 1
310 extsw = ins "extsw" csv2 $ xform'd 31 986 0
311 extsw_ = ins "extsw." csv2 $ xform'd 31 986 1
312 cntlzd = ins "cntlzd" csv2 $ xform'd 31 58 0
313 cntlzd_ = ins "cntlzd." csv2 $ xform'd 31 58 1
314 popcntb = ins "popcntb" csv2 $ xform'd 31 122 0
315 cntlzw = ins "cntlzw" csv2 $ xform'd 31 26 0
316 cntlzw_ = ins "cntlzw." csv2 $ xform'd 31 26 1
318 -- fixed-point rotate and shift instructions
319 rldicl = ins "rldicl" csv4 $ mdform 30 0 0
320 rldicl_ = ins "rldicl." csv4 $ mdform 30 0 1
321 rldicr = ins "rldicr" csv4 $ mdform 30 1 0
322 rldicr_ = ins "rldicr." csv4 $ mdform 30 1 1
323 rldic = ins "rldic" csv4 $ mdform 30 2 0
324 rldic_ = ins "rldic." csv4 $ mdform 30 2 1
325 rlwinm = ins "rlwinm" csv5 $ mform 21 0
326 rlwinm_ = ins "rlwinm." csv5 $ mform 21 1
327 rldcl = ins "rldcl" csv4 $ mdsform 30 8 0
328 rldcl_ = ins "rldcl." csv4 $ mdsform 30 8 1
329 rldcr = ins "rldcr" csv4 $ mdsform 30 9 0
330 rldcr_ = ins "rldcr." csv4 $ mdsform 30 9 1
331 rlwnm = ins "rlwnm" csv5 $ mform 23 0
332 rlwnm_ = ins "rlwnm." csv5 $ mform 23 1
333 rldimi = ins "rldimi" csv4 $ mdform 30 3 0
334 rldimi_ = ins "rldimi." csv4 $ mdform 30 3 1
335 rlwimi = ins "rlwimi" csv5 $ mform 20 0
336 rlwimi_ = ins "rlwimi." csv5 $ mform 20 1
338 -- fixed-point shift instructions
339 sld = ins "sld" csv3 $ xform'c 31 27 0
340 sld_ = ins "sld." csv3 $ xform'c 31 27 1
341 slw = ins "slw" csv3 $ xform'c 31 24 0
342 slw_ = ins "slw." csv3 $ xform'c 31 24 1
343 srd = ins "srd" csv3 $ xform'c 31 539 0
344 srd_ = ins "srd." csv3 $ xform'c 31 539 1
345 srw = ins "srw" csv3 $ xform'c 31 536 0
346 srw_ = ins "srw." csv3 $ xform'c 31 536 1
347 sradi = ins "sradi" csv3 $ xsform 31 413 0
348 sradi_ = ins "sradi." csv3 $ xsform 31 413 1
349 srawi = ins "srawi" csv3 $ xform'c 31 824 0
350 srawi_ = ins "srawi." csv3 $ xform'c 31 824 1
351 srad = ins "srad" csv3 $ xform'c 31 794 0
352 srad_ = ins "srad." csv3 $ xform'c 31 794 1
353 sraw = ins "sraw" csv3 $ xform'c 31 792 0
354 sraw_ = ins "sraw." csv3 $ xform'c 31 792 1
356 -- move to/from system register instructions
357 mtspr = ins "mtspr" csv2 $ xfxform 31 467
358 mfspr = ins "mfspr" csv2 $ xfxform 31 339
359 mtcrf = ins "mtcrf" csv2 $ xfxform'b 31 0 144
361 -- floating-point processor instructions --
362 -- floating-point load instructions
363 lfs = ins "lfs" csv3 $ dform'a 48
367 ins m form e = mnem m>>form e
369 csv2 f =f<$>iLit<.>iLit
370 csv3 f = f<$>iLit<.>iLit<.>iLit
371 csv4 f = f<$>iLit<.>iLit<.>iLit<.>iLit
372 csv5 f = f<$>iLit<.>iLit<.>iLit<.>iLit<.>iLit
374 -- instruction fomats
375 iform opcd aa lk li = pack [(opcd,6),(li,30),(aa,31),(lk,0)]
376 bform opcd aa lk bo bi bd = pack [(opcd,6),(bo,11),(bi,16),(bd,30),(aa,31),(lk,0)]
377 scform opcd lev = pack [(opcd,6),(lev,27),(1,31)]
378 dform'a opcd rt ra d = pack [(opcd,6),(rt,11),(ra,16),(d,0)]
379 dform'b opcd bf l ra si = pack [(opcd,6),(bf,9),(0,10),(l,11),(ra,16),(si,0)]
380 dsform opcd rt ra ds xo = pack [(opcd,6),(rt,11),(ra,16),(ds,30),(xo,0)]
381 xform'a opcd rt ra rb xo = pack [(opcd,6),(rt,11),(ra,16),(rb,21),(xo,31)]
382 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)]
383 xform'c opcd xo rs ra rb rc = pack [(opcd,6),(rs,11),(ra,16),(rb,21),(xo,31),(rc,0)]
384 xform'd opcd xo rc rs ra = pack [(opcd,6),(rs,11),(ra,16),(0,21),(xo,31),(rc,0)]
385 xlform'a opcd xo bt ba bb = pack [(opcd,6),(bt,11),(ba,16),(bb,21),(xo,31)]
386 xlform'b opcd xo lk bo bi bh = pack [(opcd,6),(bo,11),(bi,16),(bh,21),(xo,31),(lk,0)]
387 xlform'c opcd xo bf bfa = pack [(opcd,6),(bf,9),(bfa,14),(xo,31)]
388 xfxform opcd xo rs spr = pack [(opcd,6),(rs,11),(spr,21),(xo,31)]
389 xfxform'b opcd h xo fxm rs = pack [(opcd,6),(rs,11),(h,12),(fxm,20),(xo,31)]
392 xsform opcd xo rc ra rs sh = pack [(opcd,6),(rs,11),(ra,16),(sh,21),(xo,30),(sh,31),(rc,0)]
393 xoform opcd xo oe rc rt ra rb = pack [(opcd,6),(rt,11),(ra,16),(rb,21),(oe,22),(xo,31),(rc,0)]
394 xoform' opcd xo oe rc rt ra = pack [(opcd,6),(rt,11),(ra,16),(0,21),(oe,22),(xo,31),(rc,0)]
396 mform opcd rc ra rs sh mb me = pack [(opcd,6),(rs,11),(ra,16),(sh,21),(mb,26),(me,31),(rc,0)]
397 -- mdform needs to be fixed to handle sh correctly
398 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)]
399 mdsform opcd h rc ra rs rb mb = pack [(opcd,6),(rs,11),(ra,16),(rb,21),(mb,27),(h,31),(rc,0)]
402 pack bf = foldr1 (.|.) $ map (uncurry rotateR) bf