Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / legion / src / procs / sunsparc / debug / trace.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: trace.c
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23/*
24 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27#pragma ident "@(#)trace.c 1.8 07/01/09 SMI"
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <sys/types.h>
33#include <sys/ipc.h>
34#include <sys/shm.h>
35#include <assert.h>
36#include <string.h>
37
38#include "ss_common.h"
39#include "niagara.h"
40
41#if 1
42#define DBGP(s) do { s } while (0)
43#endif
44
45void dbg_trace(simcpu_t *sp, uint32_t rawi);
46void dbg_trace_parse(void);
47void dbg_trace_dump(void);
48
49static void dump_intregs(uint64_t *data);
50
51/*
52 * Trace modes
53 * ALL = trace all instns for all values of %pc
54 * PC = start trace when "start" %pc is encountered
55 * stop when 'end' %pc is encountered.
56 * INSTN = only trace when instn count is within start-end range
57 */
58enum trace_modes { ALL, PC, INSTN };
59
60/* start/end for pc,instn tracing */
61uint32_t trace_mode;
62char trace_mode_str[64];
63uint64_t start_trace = 0x0;
64uint64_t end_trace = 0x0;
65bool_t dump_regs = false;
66
67 /*
68 * This will be called while parsing the conf file
69 * to allow this hook to parse specific options from
70 * the conf file.
71 *
72 * Format of trace directive is:
73 * debug_hook [trace] [mode] [regs] [start] [end];
74 *
75 * [trace] - we've already parsed this. That's how we got here.
76 * [mode] - is one of [all, pc, instn]
77 * all : traces all instns (no start, end values)
78 * pc : just trace when %pc is withing start-end range
79 * instn : just trace when instn count is within start-end
80 * [regs] - if defined, we dump the %g,%o,%l,%i regs with each sample.
81 * [start]
82 * [end] - only trace when %pc or inst_cnt is within [start]-[end]
83 * range
84 *
85 * examples:
86 * trace all;
87 * trace all regs;
88 * trace pc 0x123 0x456;
89 * trace pc regs 0x123 0x456;
90 * trace instn 0x123 0x456;
91 * trace instn regs 0x123 0x456;
92 */
93void
94dbg_trace_parse(void)
95{
96 lexer_tok_t tok;
97
98 DBGP(printf("\nInside dbg_trace_parse()"););
99
100 tok = lex_get_token(); /* trace mode */
101 strcpy(trace_mode_str, lex.strp);
102
103 if (streq(lex.strp, "all"))
104 trace_mode = ALL;
105 else if (streq(lex.strp, "pc"))
106 trace_mode = PC;
107 else if (streq(lex.strp, "instn"))
108 trace_mode = INSTN;
109 else
110 lex_fatal("unknown trace_mode [%s] parsing config", lex.strp);
111
112 /* parse optional regs token */
113 tok = lex_get_token();
114 if (streq(lex.strp, "regs")) {
115 dump_regs = true;
116 } else {
117 lex_unget(); /* no regs option, continue */
118 }
119
120 /*
121 * continue parsing conf file
122 */
123 switch (trace_mode) {
124 case ALL:
125 break; /* no more parsing for 'all' mode */
126 case PC:
127 case INSTN:
128 lex_get(T_Number); /* start pc/instn */
129 start_trace = lex.val;
130 lex_get(T_Number); /* end pc/instn */
131 end_trace = lex.val;
132 break;
133 }
134
135 DBGP(printf("\ndbg_trace_parse: mode=%s, start=0x%llx, end=0x%llx",
136 trace_mode_str, start_trace, end_trace););
137
138 /*
139 * return to parse_debug_hook() which will take care
140 * of parsing the last semi colon.
141 */
142}
143
144 /*
145 * This function will get called before each instruction
146 * gets executed. For performance reasons, we may want to
147 * store the data in a buffer and post-process it later.
148 */
149void
150dbg_trace(simcpu_t *sp, uint32_t rawi)
151{
152 sparcv9_cpu_t *v9p;
153 char trace_buf[64];
154 static bool_t first_time = true;
155
156 /*
157 * If a trace range is given, we only trace within that
158 * range
159 */
160 switch (trace_mode) {
161 case ALL:
162 break; /* trace everything */
163 case PC:
164 if ((sp->pc < start_trace) || (sp->pc > end_trace)) {
165 return; /* only trace when %pc is in range */
166 }
167 break;
168 case INSTN:
169 if ((sp->cycle < start_trace) ||
170 (sp->cycle > end_trace)) {
171 return; /* only trace when instn count is in range */
172 }
173 break;
174 }
175
176 v9p = (sparcv9_cpu_t *)sp->specificp;
177 sparcv9_idis(trace_buf, sizeof (trace_buf),
178 FE_INSTN(rawi), sp->pc);
179
180 if (first_time) {
181 printf("\n[cpu] Instn_# tl:tt/gl state %%pc [raw_instn]"
182 "\tinstn\n");
183 first_time = false;
184 }
185
186 /*
187 * When printing registers, we print them in their state prior to
188 * executing the instruction in question.
189 */
190 if (dump_regs)
191 dump_intregs(sp->intreg);
192
193 printf("\n[0x%llx] 0x%llx %x:%x/%x 0x%x 0x%llx [0x%08x]\t%s",
194 sp->gid, sp->cycle,
195 v9p->tl,
196 (v9p->tl == 0) ? 0 : N_TT(v9p, v9p->tl),
197 v9p->gl,
198 v9p->state,
199 sp->pc,
200 FE_INSTN(rawi),
201 trace_buf);
202}
203
204static void
205dump_intregs(uint64_t *intreg)
206{
207 int i;
208
209 for (i = 0; i < 8; i++) {
210 printf("\ng%d=0x%016llx o%d=0x%016llx l%d=0x%016llx i%d=0x%016llx",
211 i, intreg[i],
212 i, intreg[i+8],
213 i, intreg[i+16],
214 i, intreg[i+24]);
215 }
216}
217
218void
219dbg_trace_dump(void)
220{
221 printf("\ndbg_trace_dump: caled with mode=%s, start=0x%llx, "\
222 "end=0x%llx\n", trace_mode_str, start_trace, end_trace);
223}