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