1 /* SPIM S20 MIPS simulator.
2 Utilities for displaying machine contents.
3
4 Copyright (c) 1990-2010, James R. Larus.
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without modification,
8 are permitted provided that the following conditions are met:
9
10 Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12
13 Redistributions in binary form must reproduce the above copyright notice,
14 this list of conditions and the following disclaimer in the documentation and/or
15 other materials provided with the distribution.
16
17 Neither the name of the James R. Larus nor the names of its contributors may be
18 used to endorse or promote products derived from this software without specific
19 prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33
34 #include "spim.h"
35 #include "string-stream.h"
36 #include "spim-utils.h"
37 #include "inst.h"
38 #include "data.h"
39 #include "reg.h"
40 #include "mem.h"
41 #include "run.h"
42 #include "sym-tbl.h"
43
44
45 static mem_addr format_partial_line (str_stream *ss, mem_addr addr);
46
47
48 /* Write to the stream the contents of the machine's registers, in a wide
49 variety of formats. */
50
51 void
format_registers(str_stream * ss,int print_gpr_hex,int print_fpr_hex)52 format_registers (str_stream *ss, int print_gpr_hex, int print_fpr_hex)
53 {
54 int i;
55 char *grstr, *fpstr;
56 char *grfill, *fpfill;
57 static char *reg_names[] =
58 {"r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
59 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
60 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
61 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"};
62
63 ss_printf (ss, " PC = %08x ", PC);
64 ss_printf (ss, "EPC = %08x ", CP0_EPC);
65 ss_printf (ss, " Cause = %08x ", CP0_Cause);
66 ss_printf (ss, " BadVAddr= %08x\n", CP0_BadVAddr);
67 ss_printf (ss, " Status = %08x ", CP0_Status);
68 ss_printf (ss, "HI = %08x ", HI);
69 ss_printf (ss, " LO = %08x\n", LO);
70
71 if (print_gpr_hex)
72 grstr = "R%-2d (%2s) = %08x", grfill = " ";
73 else
74 grstr = "R%-2d (%2s) = %-10d", grfill = " ";
75
76 ss_printf (ss, "\t\t\t\t General Registers\n");
77 for (i = 0; i < 8; i++)
78 {
79 ss_printf (ss, grstr, i, reg_names[i], R[i]);
80 ss_printf (ss, grfill);
81 ss_printf (ss, grstr, i+8, reg_names[i+8], R[i+8]);
82 ss_printf (ss, grfill);
83 ss_printf (ss, grstr, i+16, reg_names[i+16], R[i+16]);
84 ss_printf (ss, grfill);
85 ss_printf (ss, grstr, i+24, reg_names[i+24], R[i+24]);
86 ss_printf (ss, "\n");
87 }
88
89 ss_printf (ss, "\n FIR = %08x ", FIR);
90 ss_printf (ss, " FCSR = %08x ", FCSR);
91 ss_printf (ss, " FCCR = %08x ", FCCR);
92 ss_printf (ss, " FEXR = %08x\n", FEXR);
93 ss_printf (ss, " FENR = %08x\n", FENR);
94
95 ss_printf (ss, "\t\t\t Double Floating Point Registers\n");
96
97 if (print_fpr_hex)
98 fpstr = "FP%-2d=%08x,%08x", fpfill = " ";
99 else
100 fpstr = "FP%-2d = %#-13.6g", fpfill = " ";
101
102 if (print_fpr_hex)
103 for (i = 0; i < 4; i += 1)
104 {
105 int *r1, *r2;
106
107 /* Use pointers to cast to ints without invoking float->int conversion
108 so we can just print the bits. */
109 r1 = (int *)&FPR[i]; r2 = r1 + 1;
110 ss_printf (ss, fpstr, 2*i, *r1, *r2);
111 ss_printf (ss, fpfill);
112
113 r1 = (int *)&FPR[i+4]; r2 = r1 + 1;
114 ss_printf (ss, fpstr, 2*i+8, *r1, *r2);
115 ss_printf (ss, fpfill);
116
117 r1 = (int *)&FPR[i+8]; r2 = r1 + 1;
118 ss_printf (ss, fpstr, 2*i+16, *r1, *r2);
119 ss_printf (ss, fpfill);
120
121 r1 = (int *)&FPR[i+12]; r2 = r1 + 1;
122 ss_printf (ss, fpstr, 2*i+24, *r1, *r2);
123 ss_printf (ss, "\n");
124 }
125 else for (i = 0; i < 4; i += 1)
126 {
127 ss_printf (ss, fpstr, 2*i, FPR[i]);
128 ss_printf (ss, fpfill);
129 ss_printf (ss, fpstr, 2*i+8, FPR[i+4]);
130 ss_printf (ss, fpfill);
131 ss_printf (ss, fpstr, 2*i+16, FPR[i+8]);
132 ss_printf (ss, fpfill);
133 ss_printf (ss, fpstr, 2*i+24, FPR[i+12]);
134 ss_printf (ss, "\n");
135 }
136
137 if (print_fpr_hex)
138 fpstr = "FP%-2d=%08x", fpfill = " ";
139 else
140 fpstr = "FP%-2d = %#-13.6g", fpfill = " ";
141
142 ss_printf (ss, "\t\t\t Single Floating Point Registers\n");
143
144 if (print_fpr_hex)
145 for (i = 0; i < 8; i += 1)
146 {
147 /* Use pointers to cast to ints without invoking float->int conversion
148 so we can just print the bits. */
149 ss_printf (ss, fpstr, i, *(int *)&FPR_S(i));
150 ss_printf (ss, fpfill);
151
152 ss_printf (ss, fpstr, i+8, *(int *)&FPR_S(i+8));
153 ss_printf (ss, fpfill);
154
155 ss_printf (ss, fpstr, i+16, *(int *)&FPR_S(i+16));
156 ss_printf (ss, fpfill);
157
158 ss_printf (ss, fpstr, i+24, *(int *)&FPR_S(i+24));
159 ss_printf (ss, "\n");
160 }
161 else for (i = 0; i < 8; i += 1)
162 {
163 ss_printf (ss, fpstr, i, FPR_S(i));
164 ss_printf (ss, fpfill);
165 ss_printf (ss, fpstr, i+8, FPR_S(i+8));
166 ss_printf (ss, fpfill);
167 ss_printf (ss, fpstr, i+16, FPR_S(i+16));
168 ss_printf (ss, fpfill);
169 ss_printf (ss, fpstr, i+24, FPR_S(i+24));
170 ss_printf (ss, "\n");
171 }
172 }
173
174
175
176 /* Write to the stream a printable representation of the instructions in
177 memory addresses: FROM...TO. */
178
179 void
format_insts(str_stream * ss,mem_addr from,mem_addr to)180 format_insts (str_stream *ss, mem_addr from, mem_addr to)
181 {
182 instruction *inst;
183 mem_addr i;
184
185 for (i = from; i < to; i += 4)
186 {
187 inst = read_mem_inst (i);
188 if (inst != NULL)
189 {
190 format_an_inst (ss, inst, i);
191 }
192 }
193 }
194
195
196 /* Write to the stream a printable representation of the data and stack
197 segments. */
198
199 void
format_data_segs(str_stream * ss)200 format_data_segs (str_stream *ss)
201 {
202 ss_printf (ss, "\tDATA\n");
203 format_mem (ss, DATA_BOT, data_top);
204
205 ss_printf (ss, "\n\tSTACK\n");
206 format_mem (ss, ROUND_DOWN (R[29], BYTES_PER_WORD), STACK_TOP - 4096);
207
208 ss_printf (ss, "\n\tKERNEL DATA\n");
209 format_mem (ss, K_DATA_BOT, k_data_top);
210 }
211
212
213 #define BYTES_PER_LINE (4*BYTES_PER_WORD)
214
215
216 /* Write to the stream a printable representation of the data in memory
217 address: FROM...TO. */
218
219 void
format_mem(str_stream * ss,mem_addr from,mem_addr to)220 format_mem (str_stream *ss, mem_addr from, mem_addr to)
221 {
222 mem_word val;
223 mem_addr i = ROUND_UP (from, BYTES_PER_WORD);
224 int j;
225
226 i = format_partial_line (ss, i);
227
228 for ( ; i < to; )
229 {
230 /* Count consecutive zero words */
231 for (j = 0; (i + (uint32) j * BYTES_PER_WORD) < to; j += 1)
232 {
233 val = read_mem_word (i + (uint32) j * BYTES_PER_WORD);
234 if (val != 0)
235 {
236 break;
237 }
238 }
239
240 if (j >= 4)
241 {
242 /* Block of 4 or more zero memory words: */
243 ss_printf (ss, "[0x%08x]...[0x%08x] 0x00000000\n",
244 i,
245 i + (uint32) j * BYTES_PER_WORD);
246
247 i = i + (uint32) j * BYTES_PER_WORD;
248 i = format_partial_line (ss, i);
249 }
250 else
251 {
252 /* Fewer than 4 zero words, print them on a single line: */
253 ss_printf (ss, "[0x%08x] ", i);
254 do
255 {
256 val = read_mem_word (i);
257 ss_printf (ss, " 0x%08x", (unsigned int)val);
258 i += BYTES_PER_WORD;
259 }
260 while (i % BYTES_PER_LINE != 0);
261
262 ss_printf (ss, "\n");
263 }
264 }
265 }
266
267
268 /* Write to the stream a text line containing a fraction of a
269 quadword. Return the address after the last one written. */
270
271 static mem_addr
format_partial_line(str_stream * ss,mem_addr addr)272 format_partial_line (str_stream *ss, mem_addr addr)
273 {
274 if ((addr % BYTES_PER_LINE) != 0)
275 {
276 ss_printf (ss, "[0x%08x] ", addr);
277
278 for (; (addr % BYTES_PER_LINE) != 0; addr += BYTES_PER_WORD)
279 {
280 mem_word val = read_mem_word (addr);
281 ss_printf (ss, " 0x%08x", (unsigned int)val);
282 }
283
284 ss_printf (ss, "\n");
285 }
286
287 return addr;
288 }
289