f141389d5f10b7c234f03aa9bb8538eaf79983af
[hs-java.git] / JVM / Assembler.hs
1 {-# LANGUAGE TypeFamilies, StandaloneDeriving, FlexibleInstances,
2    FlexibleContexts, UndecidableInstances, RecordWildCards, OverloadedStrings,
3    TypeSynonymInstances, MultiParamTypeClasses #-}
4 -- | This module declares data type for JVM instructions, and BinaryState
5 -- instances to read/write them.
6 module JVM.Assembler 
7   (Instruction (..),
8    ArrayType (..),
9    CodeException (..),
10    Code (..),
11    IMM (..),
12    CMP (..),
13    encodeMethod,
14    decodeMethod
15   )
16   where
17
18 import Control.Monad
19 import Control.Applicative
20 import Data.Word
21 import qualified Data.Binary as Binary
22 import qualified Data.ByteString.Lazy as B
23 import Data.Array
24
25 import Data.BinaryState
26 import JVM.ClassFile
27
28 -- | Immediate constant. Corresponding value will be added to base opcode.
29 data IMM =
30     I0     -- ^ 0
31   | I1     -- ^ 1
32   | I2     -- ^ 2
33   | I3     -- ^ 3
34   deriving (Eq, Ord, Enum, Show)
35
36 -- | Comparation operation type. Not all CMP instructions support all operations.
37 data CMP =
38     C_EQ
39   | C_NE
40   | C_LT
41   | C_GE
42   | C_GT
43   | C_LE
44   deriving (Eq, Ord, Enum, Show)
45
46 -- | Format of Code method attribute.
47 data Code = Code {
48     codeStackSize :: Word16,
49     codeMaxLocals :: Word16,
50     codeLength :: Word32,
51     codeInstructions :: [Instruction],
52     codeExceptionsN :: Word16,
53     codeExceptions :: [CodeException],
54     codeAttrsN :: Word16,
55     codeAttributes :: [AttributeInfo] }
56   deriving (Eq, Show)
57
58 -- | Exception descriptor
59 data CodeException = CodeException {
60     eStartPC :: Word16,
61     eEndPC :: Word16,
62     eHandlerPC :: Word16,
63     eCatchType :: Word16 }
64   deriving (Eq, Show)
65
66 instance BinaryState Integer CodeException where
67   put (CodeException {..}) = do
68     put eStartPC
69     put eEndPC
70     put eHandlerPC
71     put eCatchType
72
73   get = CodeException <$> get <*> get <*> get <*> get
74
75 instance BinaryState Integer AttributeInfo where
76   put a = do
77     let sz = 6 + attributeLength a      -- full size of AttributeInfo structure
78     liftOffset (fromIntegral sz) Binary.put a
79
80   get = getZ
81
82 instance BinaryState Integer Code where
83   put (Code {..}) = do
84     put codeStackSize
85     put codeMaxLocals
86     put codeLength
87     forM_ codeInstructions put
88     put codeExceptionsN
89     forM_ codeExceptions put
90     put codeAttrsN
91     forM_ codeAttributes put
92
93   get = do
94     stackSz <- get
95     locals <- get
96     len <- get
97     bytes <- replicateM (fromIntegral len) get
98     let bytecode = B.pack bytes
99         code = decodeWith readInstructions 0 bytecode
100     excn <- get
101     excs <- replicateM (fromIntegral excn) get
102     nAttrs <- get
103     attrs <- replicateM (fromIntegral nAttrs) get
104     return $ Code stackSz locals len code excn excs nAttrs attrs
105
106 -- | Read sequence of instructions (to end of stream)
107 readInstructions :: GetState Integer [Instruction]
108 readInstructions = do
109    end <- isEmpty
110    if end
111      then return []
112      else do
113           x <- get
114           next <- readInstructions
115           return (x: next)
116
117 -- | JVM instruction set
118 data Instruction =
119     NOP            -- ^ 0
120   | ACONST_NULL    -- ^ 1
121   | ICONST_M1      -- ^ 2
122   | ICONST_0       -- ^ 3
123   | ICONST_1       -- ^ 4
124   | ICONST_2       -- ^ 5
125   | ICONST_3       -- ^ 6
126   | ICONST_4       -- ^ 7
127   | ICONST_5       -- ^ 8
128   | LCONST_0       -- ^ 9
129   | LCONST_1       -- ^ 10
130   | FCONST_0       -- ^ 11
131   | FCONST_1       -- ^ 12
132   | FCONST_2       -- ^ 13
133   | DCONST_0       -- ^ 14
134   | DCONST_1       -- ^ 15
135   | BIPUSH Word8   -- ^ 16
136   | SIPUSH Word16  -- ^ 17
137   | LDC1 Word8     -- ^ 18
138   | LDC2 Word16    -- ^ 19
139   | LDC2W Word16   -- ^ 20
140   | ILOAD Word8    -- ^ 21
141   | LLOAD Word8    -- ^ 22
142   | FLOAD Word8    -- ^ 23
143   | DLOAD Word8    -- ^ 24
144   | ALOAD Word8    -- ^ 25
145   | ILOAD_ IMM     -- ^ 26, 27, 28, 29
146   | LLOAD_ IMM     -- ^ 30, 31, 32, 33
147   | FLOAD_ IMM     -- ^ 34, 35, 36, 37
148   | DLOAD_ IMM     -- ^ 38, 39, 40, 41
149   | ALOAD_ IMM     -- ^ 42, 43, 44, 45
150   | IALOAD         -- ^ 46
151   | LALOAD         -- ^ 47
152   | FALOAD         -- ^ 48
153   | DALOAD         -- ^ 49
154   | AALOAD         -- ^ 50
155   | BALOAD         -- ^ 51
156   | CALOAD         -- ^ 52
157   | SALOAD         -- ^ 53
158   | ISTORE Word8   -- ^ 54
159   | LSTORE Word8   -- ^ 55
160   | FSTORE Word8   -- ^ 56
161   | DSTORE Word8   -- ^ 57
162   | ASTORE Word8   -- ^ 58
163   | ISTORE_ IMM    -- ^ 59, 60, 61, 62
164   | LSTORE_ IMM    -- ^ 63, 64, 65, 66
165   | FSTORE_ IMM    -- ^ 67, 68, 69, 70
166   | DSTORE_ IMM    -- ^ 71, 72, 73, 74
167   | ASTORE_ IMM    -- ^ 75, 76, 77, 78
168   | IASTORE        -- ^ 79
169   | LASTORE        -- ^ 80
170   | FASTORE        -- ^ 81
171   | DASTORE        -- ^ 82
172   | AASTORE        -- ^ 83
173   | BASTORE        -- ^ 84
174   | CASTORE        -- ^ 85
175   | SASTORE        -- ^ 86
176   | POP            -- ^ 87
177   | POP2           -- ^ 88
178   | DUP            -- ^ 89
179   | DUP_X1         -- ^ 90
180   | DUP_X2         -- ^ 91
181   | DUP2           -- ^ 92
182   | DUP2_X1        -- ^ 93 
183   | DUP2_X2        -- ^ 94
184   | SWAP           -- ^ 95
185   | IADD           -- ^ 96
186   | LADD           -- ^ 97
187   | FADD           -- ^ 98
188   | DADD           -- ^ 99
189   | ISUB           -- ^ 100
190   | LSUB           -- ^ 101
191   | FSUB           -- ^ 102
192   | DSUB           -- ^ 103
193   | IMUL           -- ^ 104
194   | LMUL           -- ^ 105
195   | FMUL           -- ^ 106
196   | DMUL           -- ^ 107
197   | IDIV           -- ^ 108
198   | LDIV           -- ^ 109
199   | FDIV           -- ^ 110
200   | DDIV           -- ^ 111
201   | IREM           -- ^ 112
202   | LREM           -- ^ 113
203   | FREM           -- ^ 114
204   | DREM           -- ^ 115
205   | INEG           -- ^ 116
206   | LNEG           -- ^ 117
207   | FNEG           -- ^ 118
208   | DNEG           -- ^ 119
209   | ISHL           -- ^ 120
210   | LSHL           -- ^ 121
211   | ISHR           -- ^ 122
212   | LSHR           -- ^ 123
213   | IUSHR          -- ^ 124
214   | LUSHR          -- ^ 125
215   | IAND           -- ^ 126
216   | LAND           -- ^ 127
217   | IOR            -- ^ 128
218   | LOR            -- ^ 129
219   | IXOR           -- ^ 130
220   | LXOR           -- ^ 131
221   | IINC Word8 Word8       -- ^ 132
222   | I2L                    -- ^ 133
223   | I2F                    -- ^ 134
224   | I2D                    -- ^ 135
225   | L2I                    -- ^ 136
226   | L2F                    -- ^ 137
227   | L2D                    -- ^ 138
228   | F2I                    -- ^ 139
229   | F2L                    -- ^ 140
230   | F2D                    -- ^ 141
231   | D2I                    -- ^ 142
232   | D2L                    -- ^ 143
233   | D2F                    -- ^ 144
234   | I2B                    -- ^ 145
235   | I2C                    -- ^ 146
236   | I2S                    -- ^ 147
237   | LCMP                   -- ^ 148
238   | FCMP CMP               -- ^ 149, 150
239   | DCMP CMP               -- ^ 151, 152
240   | IF CMP                 -- ^ 153, 154, 155, 156, 157, 158
241   | IF_ICMP CMP Word16     -- ^ 159, 160, 161, 162, 163, 164
242   | IF_ACMP CMP Word16     -- ^ 165, 166
243   | GOTO                   -- ^ 167
244   | JSR Word16             -- ^ 168
245   | RET                    -- ^ 169
246   | TABLESWITCH Word32 Word32 Word32 [Word32]     -- ^ 170
247   | LOOKUPSWITCH Word32 Word32 [(Word32, Word32)] -- ^ 171
248   | IRETURN                -- ^ 172
249   | LRETURN                -- ^ 173
250   | FRETURN                -- ^ 174
251   | DRETURN                -- ^ 175
252   | RETURN                 -- ^ 177
253   | GETSTATIC Word16       -- ^ 178
254   | PUTSTATIC Word16       -- ^ 179
255   | GETFIELD Word16        -- ^ 180
256   | PUTFIELD Word16        -- ^ 181
257   | INVOKEVIRTUAL Word16   -- ^ 182
258   | INVOKESPECIAL Word16   -- ^ 183
259   | INVOKESTATIC Word16    -- ^ 184
260   | INVOKEINTERFACE Word16 Word8 -- ^ 185
261   | NEW Word16             -- ^ 187
262   | NEWARRAY Word8         -- ^ 188, see @ArrayType@
263   | ANEWARRAY Word16       -- ^ 189
264   | ARRAYLENGTH            -- ^ 190
265   | ATHROW                 -- ^ 191
266   | CHECKCAST Word16       -- ^ 192
267   | INSTANCEOF Word16      -- ^ 193
268   | MONITORENTER           -- ^ 194
269   | MONITOREXIT            -- ^ 195
270   | WIDE Word8 Instruction -- ^ 196
271   | MULTINANEWARRAY Word16 Word8 -- ^ 197
272   | IFNULL Word16          -- ^ 198
273   | IFNONNULL Word16       -- ^ 199
274   | GOTO_W Word32          -- ^ 200
275   | JSR_W Word32           -- ^ 201
276   deriving (Eq, Show)
277
278 -- | JVM array type (primitive types)
279 data ArrayType =
280     T_BOOLEAN  -- ^ 4
281   | T_CHAR     -- ^ 5
282   | T_FLOAT    -- ^ 6
283   | T_DOUBLE   -- ^ 7
284   | T_BYTE     -- ^ 8
285   | T_SHORT    -- ^ 9
286   | T_INT      -- ^ 10
287   | T_LONG     -- ^ 11
288   deriving (Eq, Show, Enum)
289
290 -- | Parse opcode with immediate constant
291 imm :: Word8                   -- ^ Base opcode
292     -> (IMM -> Instruction)    -- ^ Instruction constructor
293     -> Word8                   -- ^ Opcode to parse
294     -> GetState s Instruction
295 imm base constr x = return $ constr $ toEnum $ fromIntegral (x-base)
296
297 -- | Put opcode with immediate constant
298 putImm :: Word8                -- ^ Base opcode
299        -> IMM                  -- ^ Constant to add to opcode
300        -> PutState Integer ()
301 putImm base i = putByte $ base + (fromIntegral $ fromEnum i)
302
303 atype2byte :: ArrayType -> Word8
304 atype2byte T_BOOLEAN  = 4
305 atype2byte T_CHAR     = 5
306 atype2byte T_FLOAT    = 6
307 atype2byte T_DOUBLE   = 7
308 atype2byte T_BYTE     = 8
309 atype2byte T_SHORT    = 9
310 atype2byte T_INT      = 10
311 atype2byte T_LONG     = 11
312
313 byte2atype :: Word8 -> GetState s ArrayType
314 byte2atype 4  = return T_BOOLEAN
315 byte2atype 5  = return T_CHAR
316 byte2atype 6  = return T_FLOAT
317 byte2atype 7  = return T_DOUBLE
318 byte2atype 8  = return T_BYTE
319 byte2atype 9  = return T_SHORT
320 byte2atype 10 = return T_INT
321 byte2atype 11 = return T_LONG
322 byte2atype x  = fail $ "Unknown array type byte: " ++ show x
323
324 instance BinaryState Integer ArrayType where
325   get = do
326     x <- getByte
327     byte2atype x
328
329   put t = putByte (atype2byte t)
330
331 -- | Put opcode with one argument
332 put1 :: (BinaryState Integer a)
333       => Word8                  -- ^ Opcode
334       -> a                      -- ^ First argument
335       -> PutState Integer ()
336 put1 code x = do
337   putByte code
338   put x
339
340 put2 :: (BinaryState Integer a, BinaryState Integer b)
341      => Word8                   -- ^ Opcode
342      -> a                       -- ^ First argument
343      -> b                       -- ^ Second argument
344      -> PutState Integer ()
345 put2 code x y = do
346   putByte code
347   put x
348   put y
349
350 instance BinaryState Integer Instruction where
351   put  NOP         = putByte 0
352   put  ACONST_NULL = putByte 1
353   put  ICONST_M1   = putByte 2
354   put  ICONST_0    = putByte 3
355   put  ICONST_1    = putByte 4
356   put  ICONST_2    = putByte 5
357   put  ICONST_3    = putByte 6
358   put  ICONST_4    = putByte 7
359   put  ICONST_5    = putByte 8
360   put  LCONST_0    = putByte 9
361   put  LCONST_1    = putByte 10
362   put  FCONST_0    = putByte 11
363   put  FCONST_1    = putByte 12
364   put  FCONST_2    = putByte 13
365   put  DCONST_0    = putByte 14
366   put  DCONST_1    = putByte 15
367   put (BIPUSH x)   = put1 16 x
368   put (SIPUSH x)   = put1 17 x
369   put (LDC1 x)     = put1 18 x
370   put (LDC2 x)     = put1 19 x
371   put (LDC2W x)    = put1 20 x
372   put (ILOAD x)    = put1 21 x
373   put (LLOAD x)    = put1 22 x
374   put (FLOAD x)    = put1 23 x
375   put (DLOAD x)    = put1 24 x
376   put (ALOAD x)    = put1 25 x
377   put (ILOAD_ i)   = putImm 26 i
378   put (LLOAD_ i)   = putImm 30 i
379   put (FLOAD_ i)   = putImm 34 i
380   put (DLOAD_ i)   = putImm 38 i
381   put (ALOAD_ i)   = putImm 42 i
382   put  IALOAD      = putByte 46
383   put  LALOAD      = putByte 47
384   put  FALOAD      = putByte 48
385   put  DALOAD      = putByte 49
386   put  AALOAD      = putByte 50
387   put  BALOAD      = putByte 51
388   put  CALOAD      = putByte 52
389   put  SALOAD      = putByte 53
390   put (ISTORE x)   = put1  54 x
391   put (LSTORE x)   = put1  55 x
392   put (FSTORE x)   = put1  56 x
393   put (DSTORE x)   = put1  57 x
394   put (ASTORE x)   = put1  58 x
395   put (ISTORE_ i)  = putImm 59 i
396   put (LSTORE_ i)  = putImm 63 i
397   put (FSTORE_ i)  = putImm 67 i
398   put (DSTORE_ i)  = putImm 71 i
399   put (ASTORE_ i)  = putImm 75 i
400   put  IASTORE     = putByte 79
401   put  LASTORE     = putByte 80
402   put  FASTORE     = putByte 81
403   put  DASTORE     = putByte 82
404   put  AASTORE     = putByte 83
405   put  BASTORE     = putByte 84
406   put  CASTORE     = putByte 85
407   put  SASTORE     = putByte 86
408   put  POP         = putByte 87
409   put  POP2        = putByte 88
410   put  DUP         = putByte 89
411   put  DUP_X1      = putByte 90
412   put  DUP_X2      = putByte 91
413   put  DUP2        = putByte 92
414   put  DUP2_X1     = putByte 93 
415   put  DUP2_X2     = putByte 94
416   put  SWAP        = putByte 95
417   put  IADD        = putByte 96
418   put  LADD        = putByte 97
419   put  FADD        = putByte 98
420   put  DADD        = putByte 99
421   put  ISUB        = putByte 100
422   put  LSUB        = putByte 101
423   put  FSUB        = putByte 102
424   put  DSUB        = putByte 103
425   put  IMUL        = putByte 104
426   put  LMUL        = putByte 105
427   put  FMUL        = putByte 106
428   put  DMUL        = putByte 107
429   put  IDIV        = putByte 108
430   put  LDIV        = putByte 109
431   put  FDIV        = putByte 110
432   put  DDIV        = putByte 111
433   put  IREM        = putByte 112
434   put  LREM        = putByte 113
435   put  FREM        = putByte 114
436   put  DREM        = putByte 115
437   put  INEG        = putByte 116
438   put  LNEG        = putByte 117
439   put  FNEG        = putByte 118
440   put  DNEG        = putByte 119
441   put  ISHL        = putByte 120
442   put  LSHL        = putByte 121
443   put  ISHR        = putByte 122
444   put  LSHR        = putByte 123
445   put  IUSHR       = putByte 124
446   put  LUSHR       = putByte 125
447   put  IAND        = putByte 126
448   put  LAND        = putByte 127
449   put  IOR         = putByte 128
450   put  LOR         = putByte 129
451   put  IXOR        = putByte 130
452   put  LXOR        = putByte 131
453   put (IINC x y)      = put2 132 x y
454   put  I2L            = putByte 133
455   put  I2F            = putByte 134
456   put  I2D            = putByte 135
457   put  L2I            = putByte 136
458   put  L2F            = putByte 137
459   put  L2D            = putByte 138
460   put  F2I            = putByte 139
461   put  F2L            = putByte 140
462   put  F2D            = putByte 141
463   put  D2I            = putByte 142
464   put  D2L            = putByte 143
465   put  D2F            = putByte 144
466   put  I2B            = putByte 145
467   put  I2C            = putByte 146
468   put  I2S            = putByte 147
469   put  LCMP           = putByte 148
470   put (FCMP C_LT)     = putByte 149
471   put (FCMP C_GT)     = putByte 150
472   put (FCMP c)        = fail $ "No such instruction: FCMP " ++ show c
473   put (DCMP C_LT)     = putByte 151
474   put (DCMP C_GT)     = putByte 152
475   put (DCMP c)        = fail $ "No such instruction: DCMP " ++ show c
476   put (IF c)          = putByte (fromIntegral $ 153 + fromEnum c)
477   put (IF_ACMP C_EQ x) = put1 165 x
478   put (IF_ACMP C_NE x) = put1 166 x
479   put (IF_ACMP c _)   = fail $ "No such instruction: IF_ACMP " ++ show c
480   put (IF_ICMP c x)   = putByte (fromIntegral $ 159 + fromEnum c) >> put x
481   put  GOTO           = putByte 167
482   put (JSR x)         = put1 168 x
483   put  RET            = putByte 169
484   put (TABLESWITCH def low high offs) = do
485                                    putByte 170
486                                    offset <- getOffset
487                                    let pads = 4 - (offset `mod` 4)
488                                    replicateM (fromIntegral pads) (putByte 0)
489                                    put low
490                                    put high
491                                    forM_ offs put
492   put (LOOKUPSWITCH def n pairs) = do
493                                    putByte 171
494                                    offset <- getOffset
495                                    let pads = 4 - (offset `mod` 4)
496                                    replicateM (fromIntegral pads) (putByte 0)
497                                    put def
498                                    put n
499                                    forM_ pairs put
500   put  IRETURN        = putByte 172
501   put  LRETURN        = putByte 173
502   put  FRETURN        = putByte 174
503   put  DRETURN        = putByte 175
504   put  RETURN         = putByte 177
505   put (GETSTATIC x)   = put1 178 x
506   put (PUTSTATIC x)   = put1 179 x
507   put (GETFIELD x)    = put1 180 x
508   put (PUTFIELD x)    = put1 181 x
509   put (INVOKEVIRTUAL x)     = put1 182 x
510   put (INVOKESPECIAL x)     = put1 183 x
511   put (INVOKESTATIC x)      = put1 184 x
512   put (INVOKEINTERFACE x c) = put2 185 x c >> putByte 0
513   put (NEW x)         = put1 187 x
514   put (NEWARRAY x)    = put1 188 x
515   put (ANEWARRAY x)   = put1 189 x
516   put  ARRAYLENGTH    = putByte 190
517   put  ATHROW         = putByte 191
518   put (CHECKCAST x)   = put1 192 x
519   put (INSTANCEOF x)  = put1 193 x
520   put  MONITORENTER   = putByte 194
521   put  MONITOREXIT    = putByte 195
522   put (WIDE x inst)   = put2 196 x inst
523   put (MULTINANEWARRAY x y) = put2 197 x y
524   put (IFNULL x)      = put1 198 x
525   put (IFNONNULL x)   = put1 199 x
526   put (GOTO_W x)      = put1 200 x
527   put (JSR_W x)       = put1 201 x
528
529   get = do
530     c <- getByte
531     case c of
532       0 -> return NOP
533       1 -> return ACONST_NULL
534       2 -> return ICONST_M1
535       3 -> return ICONST_0
536       4 -> return ICONST_1
537       5 -> return ICONST_2
538       6 -> return ICONST_3
539       7 -> return ICONST_4
540       8 -> return ICONST_5
541       9 -> return LCONST_0
542       10 -> return LCONST_1
543       11 -> return FCONST_0
544       12 -> return FCONST_1
545       13 -> return FCONST_2
546       14 -> return DCONST_0
547       15 -> return DCONST_1
548       16 -> BIPUSH <$> get
549       17 -> SIPUSH <$> get
550       18 -> LDC1 <$> get
551       19 -> LDC2 <$> get
552       20 -> LDC2W <$> get
553       21 -> ILOAD <$> get
554       22 -> LLOAD <$> get
555       23 -> FLOAD <$> get
556       24 -> DLOAD <$> get
557       25 -> ALOAD <$> get
558       46 -> return IALOAD
559       47 -> return LALOAD
560       48 -> return FALOAD
561       49 -> return DALOAD
562       50 -> return AALOAD
563       51 -> return BALOAD
564       52 -> return CALOAD
565       53 -> return SALOAD
566       54 -> ISTORE <$> get
567       55 -> LSTORE <$> get
568       56 -> FSTORE <$> get
569       57 -> DSTORE <$> get
570       58 -> ASTORE <$> get
571       79 -> return IASTORE
572       80 -> return LASTORE
573       81 -> return FASTORE
574       82 -> return DASTORE
575       83 -> return AASTORE
576       84 -> return BASTORE
577       85 -> return CASTORE
578       86 -> return SASTORE
579       87 -> return POP
580       88 -> return POP2
581       89 -> return DUP
582       90 -> return DUP_X1
583       91 -> return DUP_X2
584       92 -> return DUP2
585       93 -> return DUP2_X1 
586       94 -> return DUP2_X2
587       95 -> return SWAP
588       96 -> return IADD
589       97 -> return LADD
590       98 -> return FADD
591       99 -> return DADD
592       100 -> return ISUB
593       101 -> return LSUB
594       102 -> return FSUB
595       103 -> return DSUB
596       104 -> return IMUL
597       105 -> return LMUL
598       106 -> return FMUL
599       107 -> return DMUL
600       108 -> return IDIV
601       109 -> return LDIV
602       110 -> return FDIV
603       111 -> return DDIV
604       112 -> return IREM
605       113 -> return LREM
606       114 -> return FREM
607       115 -> return DREM
608       116 -> return INEG
609       117 -> return LNEG
610       118 -> return FNEG
611       119 -> return DNEG
612       120 -> return ISHL
613       121 -> return LSHL
614       122 -> return ISHR
615       123 -> return LSHR
616       124 -> return IUSHR
617       125 -> return LUSHR
618       126 -> return IAND
619       127 -> return LAND
620       128 -> return IOR
621       129 -> return LOR
622       130 -> return IXOR
623       131 -> return LXOR
624       132 -> IINC <$> get <*> get
625       133 -> return I2L
626       134 -> return I2F
627       135 -> return I2D
628       136 -> return L2I
629       137 -> return L2F
630       138 -> return L2D
631       139 -> return F2I
632       140 -> return F2L
633       141 -> return F2D
634       142 -> return D2I
635       143 -> return D2L
636       144 -> return D2F
637       145 -> return I2B
638       146 -> return I2C
639       147 -> return I2S
640       148 -> return LCMP
641       149 -> return $ FCMP C_LT
642       150 -> return $ FCMP C_GT
643       151 -> return $ DCMP C_LT
644       152 -> return $ DCMP C_GT
645       165 -> IF_ACMP C_EQ <$> get
646       166 -> IF_ACMP C_NE <$> get
647       167 -> return GOTO
648       168 -> JSR <$> get
649       169 -> return RET
650       170 -> do
651              offset <- bytesRead
652              let pads = 4 - (offset `mod` 4)
653              skip (fromIntegral pads)
654              def <- get
655              low <- get
656              high <- get
657              offs <- replicateM (fromIntegral $ high - low + 1) get
658              return $ TABLESWITCH def low high offs
659       171 -> do
660              offset <- bytesRead
661              let pads = 4 - (offset `mod` 4)
662              skip (fromIntegral pads)
663              def <- get
664              n <- get
665              pairs <- replicateM (fromIntegral n) get
666              return $ LOOKUPSWITCH def n pairs
667       172 -> return IRETURN
668       173 -> return LRETURN
669       174 -> return FRETURN
670       175 -> return DRETURN
671       177 -> return RETURN
672       178 -> GETSTATIC <$> get
673       179 -> PUTSTATIC <$> get
674       180 -> GETFIELD <$> get
675       181 -> PUTFIELD <$> get
676       182 -> INVOKEVIRTUAL <$> get
677       183 -> INVOKESPECIAL <$> get
678       184 -> INVOKESTATIC <$> get
679       185 -> (INVOKEINTERFACE <$> get <*> get) <* skip 1
680       187 -> NEW <$> get
681       188 -> NEWARRAY <$> get
682       189 -> ANEWARRAY <$> get
683       190 -> return ARRAYLENGTH
684       191 -> return ATHROW
685       192 -> CHECKCAST <$> get
686       193 -> INSTANCEOF <$> get
687       194 -> return MONITORENTER
688       195 -> return MONITOREXIT
689       196 -> WIDE <$> get <*> get
690       197 -> MULTINANEWARRAY <$> get <*> get
691       198 -> IFNULL <$> get
692       199 -> IFNONNULL <$> get
693       200 -> GOTO_W <$> get
694       201 -> JSR_W <$> get
695       _ | inRange (59, 62) c -> imm 59 ISTORE_ c
696         | inRange (63, 66) c -> imm 63 LSTORE_ c
697         | inRange (67, 70) c -> imm 67 FSTORE_ c
698         | inRange (71, 74) c -> imm 71 DSTORE_ c
699         | inRange (75, 78) c -> imm 75 ASTORE_ c
700         | inRange (26, 29) c -> imm 26 ILOAD_ c
701         | inRange (30, 33) c -> imm 30 LLOAD_ c
702         | inRange (34, 37) c -> imm 34 FLOAD_ c
703         | inRange (38, 41) c -> imm 38 DLOAD_ c
704         | inRange (42, 45) c -> imm 42 ALOAD_ c
705         | inRange (153, 158) c -> return $ IF (toEnum $ fromIntegral $ c-153)
706         | inRange (159, 164) c -> IF_ICMP (toEnum $ fromIntegral $ c-159) <$> get
707         | otherwise -> fail $ "Unknown instruction byte code: " ++ show c
708   
709 -- | Decode Java method
710 decodeMethod :: B.ByteString -> Code
711 decodeMethod str = decodeS (0 :: Integer) str
712
713 -- | Encode Java method
714 encodeMethod :: Code -> B.ByteString
715 encodeMethod code = encodeS (0 :: Integer) code
716