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