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]] );
71 debugBelch(" %s\n", ((CostCentre
*)(literals
[instrs
[pc
+3]]))->label
);
75 debugBelch("SWIZZLE stkoff %d by %d\n",
76 instrs
[pc
], (signed int)instrs
[pc
+1]);
79 debugBelch("CCALL marshaller at 0x%" FMT_Word
"\n",
80 literals
[instrs
[pc
]] );
83 StgWord stk_words_reqd
= BCO_GET_LARGE_ARG
+ 1;
84 debugBelch("STKCHECK %" FMT_Word
"\n", (W_
)stk_words_reqd
);
88 debugBelch("PUSH_L %d\n", instrs
[pc
] );
91 debugBelch("PUSH_LL %d %d\n", instrs
[pc
], instrs
[pc
+1] );
94 debugBelch("PUSH_LLL %d %d %d\n", instrs
[pc
], instrs
[pc
+1],
98 debugBelch("PUSH_G " ); printPtr( ptrs
[instrs
[pc
]] );
103 debugBelch("PUSH_ALTS " ); printPtr( ptrs
[instrs
[pc
]] );
106 case bci_PUSH_ALTS_P
:
107 debugBelch("PUSH_ALTS_P " ); printPtr( ptrs
[instrs
[pc
]] );
110 case bci_PUSH_ALTS_N
:
111 debugBelch("PUSH_ALTS_N " ); printPtr( ptrs
[instrs
[pc
]] );
114 case bci_PUSH_ALTS_F
:
115 debugBelch("PUSH_ALTS_F " ); printPtr( ptrs
[instrs
[pc
]] );
118 case bci_PUSH_ALTS_D
:
119 debugBelch("PUSH_ALTS_D " ); printPtr( ptrs
[instrs
[pc
]] );
122 case bci_PUSH_ALTS_L
:
123 debugBelch("PUSH_ALTS_L " ); printPtr( ptrs
[instrs
[pc
]] );
126 case bci_PUSH_ALTS_V
:
127 debugBelch("PUSH_ALTS_V " ); printPtr( ptrs
[instrs
[pc
]] );
132 debugBelch("PUSH_UBX ");
133 for (i
= 0; i
< instrs
[pc
+1]; i
++)
134 debugBelch("0x%" FMT_Word
" ", literals
[i
+ instrs
[pc
]] );
137 case bci_PUSH_APPLY_N
:
138 debugBelch("PUSH_APPLY_N\n");
140 case bci_PUSH_APPLY_V
:
141 debugBelch("PUSH_APPLY_V\n");
143 case bci_PUSH_APPLY_F
:
144 debugBelch("PUSH_APPLY_F\n");
146 case bci_PUSH_APPLY_D
:
147 debugBelch("PUSH_APPLY_D\n");
149 case bci_PUSH_APPLY_L
:
150 debugBelch("PUSH_APPLY_L\n");
152 case bci_PUSH_APPLY_P
:
153 debugBelch("PUSH_APPLY_P\n");
155 case bci_PUSH_APPLY_PP
:
156 debugBelch("PUSH_APPLY_PP\n");
158 case bci_PUSH_APPLY_PPP
:
159 debugBelch("PUSH_APPLY_PPP\n");
161 case bci_PUSH_APPLY_PPPP
:
162 debugBelch("PUSH_APPLY_PPPP\n");
164 case bci_PUSH_APPLY_PPPPP
:
165 debugBelch("PUSH_APPLY_PPPPP\n");
167 case bci_PUSH_APPLY_PPPPPP
:
168 debugBelch("PUSH_APPLY_PPPPPP\n");
171 debugBelch("SLIDE %d down by %d\n", instrs
[pc
], instrs
[pc
+1] );
174 debugBelch("ALLOC_AP %d words\n", instrs
[pc
] );
176 case bci_ALLOC_AP_NOUPD
:
177 debugBelch("ALLOC_AP_NOUPD %d words\n", instrs
[pc
] );
180 debugBelch("ALLOC_PAP %d arity, %d words\n",
181 instrs
[pc
], instrs
[pc
+1] );
184 debugBelch("MKAP %d words, %d stkoff\n", instrs
[pc
+1],
188 debugBelch("MKPAP %d words, %d stkoff\n", instrs
[pc
+1],
192 debugBelch("UNPACK %d\n", instrs
[pc
] );
195 debugBelch("PACK %d words with itbl ", instrs
[pc
+1] );
196 printPtr( (StgPtr
)literals
[instrs
[pc
]] );
201 unsigned int discr
= BCO_NEXT
;
202 int failto
= BCO_GET_LARGE_ARG
;
203 debugBelch("TESTLT_I %" FMT_Int
", fail to %d\n", literals
[discr
], failto
);
207 debugBelch("TESTEQ_I %" FMT_Int
", fail to %d\n", literals
[instrs
[pc
]],
212 debugBelch("TESTLT_F %" FMT_Int
", fail to %d\n", literals
[instrs
[pc
]],
216 debugBelch("TESTEQ_F %" FMT_Int
", fail to %d\n", literals
[instrs
[pc
]],
221 debugBelch("TESTLT_D %" FMT_Int
", fail to %d\n", literals
[instrs
[pc
]],
225 debugBelch("TESTEQ_D %" FMT_Int
", fail to %d\n", literals
[instrs
[pc
]],
230 debugBelch("TESTLT_P %d, fail to %d\n", instrs
[pc
],
234 debugBelch("TESTEQ_P %d, fail to %d\n", instrs
[pc
],
238 debugBelch("CASEFAIL\n" );
241 debugBelch("JMP to %d\n", instrs
[pc
]);
245 debugBelch("ENTER\n");
249 debugBelch("RETURN\n" );
252 debugBelch("RETURN_P\n" );
255 debugBelch("RETURN_N\n" );
258 debugBelch("RETURN_F\n" );
261 debugBelch("RETURN_D\n" );
264 debugBelch("RETURN_L\n" );
267 debugBelch("RETURN_V\n" );
271 barf("disInstr: unknown opcode %u", (unsigned int) instr
);
277 /* Something of a kludge .. how do we know where the end of the insn
278 array is, since it isn't recorded anywhere? Answer: the first
279 short is the number of bytecodes which follow it.
280 See ByteCodeGen.linkBCO.insns_arr for construction ...
282 void disassemble( StgBCO
*bco
)
285 StgWord16
* instrs
= (StgWord16
*)(bco
->instrs
->payload
);
286 StgMutArrPtrs
* ptrs
= bco
->ptrs
;
287 uint32_t nbcs
= (uint32_t)(bco
->instrs
->bytes
/ sizeof(StgWord16
));
290 debugBelch("BCO\n" );
293 debugBelch("\t%2d: ", pc
);
294 pc
= disInstr ( bco
, pc
);
297 debugBelch("INSTRS:\n " );
299 for (i
= 0; i
< nbcs
; i
++) {
300 debugBelch("%3d ", (int)instrs
[i
] );
302 if (j
== 0) { j
= 16; debugBelch("\n "); };
306 debugBelch("PTRS:\n " );
308 for (i
= 0; i
< ptrs
->ptrs
; i
++) {
309 debugBelch("%8p ", ptrs
->payload
[i
] );
311 if (j
== 0) { j
= 8; debugBelch("\n "); };