1 /* -----------------------------------------------------------------------------
2 * Bytecode disassembler
4 * Copyright (c) 1994-2002.
6 * $RCSfile: Disassembler.c,v $
8 * $Date: 2004/09/03 15:28:19 $
9 * ---------------------------------------------------------------------------*/
13 #include "PosixSource.h"
16 #include "rts/Bytecodes.h"
21 #include "Disassembler.h"
22 #include "Interpreter.h"
24 /* --------------------------------------------------------------------------
26 * ------------------------------------------------------------------------*/
29 disInstr ( StgBCO
*bco
, int pc
)
34 StgWord16
* instrs
= (StgWord16
*)(bco
->instrs
->payload
);
36 StgArrBytes
* literal_arr
= bco
->literals
;
37 StgWord
* literals
= (StgWord
*)(&literal_arr
->payload
[0]);
39 StgMutArrPtrs
* ptrs_arr
= bco
->ptrs
;
40 StgPtr
* ptrs
= (StgPtr
*)(&ptrs_arr
->payload
[0]);
43 if (instr
& bci_FLAG_LARGE_ARGS
) {
44 debugBelch ("LARGE ");
47 #define BCO_NEXT instrs[pc++]
48 #define BCO_NEXT_32 (pc += 2)
49 #define BCO_READ_NEXT_32 (BCO_NEXT_32, (((StgWord) instrs[pc-2]) << 16) \
50 + ( (StgWord) instrs[pc-1]))
51 #define BCO_NEXT_64 (pc += 4)
52 #define BCO_READ_NEXT_64 (BCO_NEXT_64, (((StgWord) instrs[pc-4]) << 48) \
53 + (((StgWord) instrs[pc-3]) << 32) \
54 + (((StgWord) instrs[pc-2]) << 16) \
55 + ( (StgWord) instrs[pc-1]))
56 #if WORD_SIZE_IN_BITS == 32
57 #define BCO_NEXT_WORD BCO_NEXT_32
58 #define BCO_READ_NEXT_WORD BCO_READ_NEXT_32
59 #elif WORD_SIZE_IN_BITS == 64
60 #define BCO_NEXT_WORD BCO_NEXT_64
61 #define BCO_READ_NEXT_WORD BCO_READ_NEXT_64
63 #error Cannot cope with WORD_SIZE_IN_BITS being nether 32 nor 64
65 #define BCO_GET_LARGE_ARG ((instr & bci_FLAG_LARGE_ARGS) ? BCO_READ_NEXT_WORD : BCO_NEXT)
67 switch (instr
& 0xff) {
69 debugBelch ("BRK_FUN " ); printPtr( ptrs
[instrs
[pc
]] );
70 debugBelch (" %d ", instrs
[pc
+1]); printPtr( ptrs
[instrs
[pc
+2]] ); debugBelch("\n" );
74 debugBelch("SWIZZLE stkoff %d by %d\n",
75 instrs
[pc
], (signed int)instrs
[pc
+1]);
78 debugBelch("CCALL marshaller at 0x%" FMT_Word
"\n",
79 literals
[instrs
[pc
]] );
82 StgWord stk_words_reqd
= BCO_GET_LARGE_ARG
+ 1;
83 debugBelch("STKCHECK %" FMT_Word
"\n", (W_
)stk_words_reqd
);
87 debugBelch("PUSH_L %d\n", instrs
[pc
] );
90 debugBelch("PUSH_LL %d %d\n", instrs
[pc
], instrs
[pc
+1] );
93 debugBelch("PUSH_LLL %d %d %d\n", instrs
[pc
], instrs
[pc
+1],
97 debugBelch("PUSH_G " ); printPtr( ptrs
[instrs
[pc
]] );
102 debugBelch("PUSH_ALTS " ); printPtr( ptrs
[instrs
[pc
]] );
105 case bci_PUSH_ALTS_P
:
106 debugBelch("PUSH_ALTS_P " ); printPtr( ptrs
[instrs
[pc
]] );
109 case bci_PUSH_ALTS_N
:
110 debugBelch("PUSH_ALTS_N " ); printPtr( ptrs
[instrs
[pc
]] );
113 case bci_PUSH_ALTS_F
:
114 debugBelch("PUSH_ALTS_F " ); printPtr( ptrs
[instrs
[pc
]] );
117 case bci_PUSH_ALTS_D
:
118 debugBelch("PUSH_ALTS_D " ); printPtr( ptrs
[instrs
[pc
]] );
121 case bci_PUSH_ALTS_L
:
122 debugBelch("PUSH_ALTS_L " ); printPtr( ptrs
[instrs
[pc
]] );
125 case bci_PUSH_ALTS_V
:
126 debugBelch("PUSH_ALTS_V " ); printPtr( ptrs
[instrs
[pc
]] );
131 debugBelch("PUSH_UBX ");
132 for (i
= 0; i
< instrs
[pc
+1]; i
++)
133 debugBelch("0x%" FMT_Word
" ", literals
[i
+ instrs
[pc
]] );
136 case bci_PUSH_APPLY_N
:
137 debugBelch("PUSH_APPLY_N\n");
139 case bci_PUSH_APPLY_V
:
140 debugBelch("PUSH_APPLY_V\n");
142 case bci_PUSH_APPLY_F
:
143 debugBelch("PUSH_APPLY_F\n");
145 case bci_PUSH_APPLY_D
:
146 debugBelch("PUSH_APPLY_D\n");
148 case bci_PUSH_APPLY_L
:
149 debugBelch("PUSH_APPLY_L\n");
151 case bci_PUSH_APPLY_P
:
152 debugBelch("PUSH_APPLY_P\n");
154 case bci_PUSH_APPLY_PP
:
155 debugBelch("PUSH_APPLY_PP\n");
157 case bci_PUSH_APPLY_PPP
:
158 debugBelch("PUSH_APPLY_PPP\n");
160 case bci_PUSH_APPLY_PPPP
:
161 debugBelch("PUSH_APPLY_PPPP\n");
163 case bci_PUSH_APPLY_PPPPP
:
164 debugBelch("PUSH_APPLY_PPPPP\n");
166 case bci_PUSH_APPLY_PPPPPP
:
167 debugBelch("PUSH_APPLY_PPPPPP\n");
170 debugBelch("SLIDE %d down by %d\n", instrs
[pc
], instrs
[pc
+1] );
173 debugBelch("ALLOC_AP %d words\n", instrs
[pc
] );
175 case bci_ALLOC_AP_NOUPD
:
176 debugBelch("ALLOC_AP_NOUPD %d words\n", instrs
[pc
] );
179 debugBelch("ALLOC_PAP %d arity, %d words\n",
180 instrs
[pc
], instrs
[pc
+1] );
183 debugBelch("MKAP %d words, %d stkoff\n", instrs
[pc
+1],
187 debugBelch("MKPAP %d words, %d stkoff\n", instrs
[pc
+1],
191 debugBelch("UNPACK %d\n", instrs
[pc
] );
194 debugBelch("PACK %d words with itbl ", instrs
[pc
+1] );
195 printPtr( (StgPtr
)literals
[instrs
[pc
]] );
200 unsigned int discr
= BCO_NEXT
;
201 int failto
= BCO_GET_LARGE_ARG
;
202 debugBelch("TESTLT_I %" FMT_Int
", fail to %d\n", literals
[discr
], failto
);
206 debugBelch("TESTEQ_I %" FMT_Int
", fail to %d\n", literals
[instrs
[pc
]],
211 debugBelch("TESTLT_F %" FMT_Int
", fail to %d\n", literals
[instrs
[pc
]],
215 debugBelch("TESTEQ_F %" FMT_Int
", fail to %d\n", literals
[instrs
[pc
]],
220 debugBelch("TESTLT_D %" FMT_Int
", fail to %d\n", literals
[instrs
[pc
]],
224 debugBelch("TESTEQ_D %" FMT_Int
", fail to %d\n", literals
[instrs
[pc
]],
229 debugBelch("TESTLT_P %d, fail to %d\n", instrs
[pc
],
233 debugBelch("TESTEQ_P %d, fail to %d\n", instrs
[pc
],
237 debugBelch("CASEFAIL\n" );
240 debugBelch("JMP to %d\n", instrs
[pc
]);
244 debugBelch("ENTER\n");
248 debugBelch("RETURN\n" );
251 debugBelch("RETURN_P\n" );
254 debugBelch("RETURN_N\n" );
257 debugBelch("RETURN_F\n" );
260 debugBelch("RETURN_D\n" );
263 debugBelch("RETURN_L\n" );
266 debugBelch("RETURN_V\n" );
270 barf("disInstr: unknown opcode %u", (unsigned int) instr
);
276 /* Something of a kludge .. how do we know where the end of the insn
277 array is, since it isn't recorded anywhere? Answer: the first
278 short is the number of bytecodes which follow it.
279 See ByteCodeGen.linkBCO.insns_arr for construction ...
281 void disassemble( StgBCO
*bco
)
284 StgWord16
* instrs
= (StgWord16
*)(bco
->instrs
->payload
);
285 StgMutArrPtrs
* ptrs
= bco
->ptrs
;
286 nat nbcs
= (int)(bco
->instrs
->bytes
/ sizeof(StgWord16
));
289 debugBelch("BCO\n" );
292 debugBelch("\t%2d: ", pc
);
293 pc
= disInstr ( bco
, pc
);
296 debugBelch("INSTRS:\n " );
298 for (i
= 0; i
< nbcs
; i
++) {
299 debugBelch("%3d ", (int)instrs
[i
] );
301 if (j
== 0) { j
= 16; debugBelch("\n "); };
305 debugBelch("PTRS:\n " );
307 for (i
= 0; i
< ptrs
->ptrs
; i
++) {
308 debugBelch("%8p ", ptrs
->payload
[i
] );
310 if (j
== 0) { j
= 8; debugBelch("\n "); };