Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: cpu_interface.cc | |
4 | // Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
5 | // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
6 | // | |
7 | // The above named program is free software; you can redistribute it and/or | |
8 | // modify it under the terms of the GNU General Public | |
9 | // License version 2 as published by the Free Software Foundation. | |
10 | // | |
11 | // The above named program is distributed in the hope that it will be | |
12 | // useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | // General Public License for more details. | |
15 | // | |
16 | // You should have received a copy of the GNU General Public | |
17 | // License along with this work; if not, write to the Free Software | |
18 | // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
19 | // | |
20 | // ========== Copyright Header End ============================================ | |
21 | //////////////////////////////////////////////////////////// | |
22 | // | |
23 | // File: cpu_interface.cc | |
24 | // | |
25 | // Copyright (C) 2005 Sun Microsystems, Inc. | |
26 | // All rights reserved. | |
27 | // | |
28 | ||
29 | #include <dlfcn.h> | |
30 | #include <stdio.h> | |
31 | #include <stdlib.h> | |
32 | #include <ctype.h> | |
33 | #include "types.h" | |
34 | #include "blaze_globals.h" | |
35 | #include "cpu_interface.h" | |
36 | #include "spix_sparc.h" | |
37 | #include "system.h" | |
38 | #include "ui.h" | |
39 | #include "command_opts.h" | |
40 | ||
41 | ||
42 | // This file implements C++ interface for the | |
43 | // cpu shared library | |
44 | ||
45 | ||
46 | void *cpu_lib_handle = NULL; | |
47 | char cpu_lib_name[160] = "lib.unknown.cpu.type"; | |
48 | ||
49 | // global vcpu table | |
50 | Vcpu *g_vcpu[NCPU_MAX]; | |
51 | int g_nvcpu = 0; // total number of vcpu's | |
52 | int g_vcpu_id_max = 0; // max id of the vcpu | |
53 | ||
54 | VCPU_ExInterface g_cpu_ex_intf; | |
55 | ||
56 | extern int pselect_cpu_id; | |
57 | ||
58 | // parameter names | |
59 | #define INST_NAME "name" | |
60 | #define CPU_TYPE "cpu-type" | |
61 | #define MMU_TYPE "mmu-type" | |
62 | #define DTLB_SIZE "dtlb-entries" | |
63 | #define ITLB_SIZE "itlb-entries" | |
64 | #define CLOCK "clock-frequency" | |
65 | #define SCLOCK "system-frequency" | |
66 | #define LOOPTICKS "cpu-loopticks" | |
67 | #define STICKINCR "cpu-stickincr" | |
68 | #define NWINS "cpu-nwins" | |
69 | #define TLMAX "cpu-tlmax" | |
70 | #define CPU_ID "id" | |
71 | ||
72 | // cpu ui commands | |
73 | static int pregs_ui_cmd (void *, int argc, char **argv); | |
74 | static int fpregs_ui_cmd (void *, int argc, char **argv); | |
75 | static int cmpregs_ui_cmd (void *, int argc, char **argv); | |
76 | static int read_reg_ui_cmd (void *, int argc, char **argv); | |
77 | static int set_pc_ui_cmd (void *, int argc, char **argv); | |
78 | static int write_reg_ui_cmd (void *, int argc, char **argv); | |
79 | static int regs_ui_cmd (void *, int argc, char **argv); | |
80 | static int pc_ui_cmd (void *, int argc, char **argv); | |
81 | static int cpuregs_ui_cmd (void *, int argc, char **argv); | |
82 | ||
83 | ||
84 | static int pregs_cmd_usage (); | |
85 | static int fpregs_cmd_usage (); | |
86 | static int cmpregs_cmd_usage (); | |
87 | static int read_reg_cmd_usage (); | |
88 | static int set_pc_cmd_usage (); | |
89 | static int write_reg_cmd_usage(); | |
90 | static int print_reg_cmd_usage(); | |
91 | static int cpuregs_cmd_usage (); | |
92 | ||
93 | ////////////////////////////////////////////////////////////// | |
94 | // | |
95 | // set configuration parameter | |
96 | // | |
97 | // Configuration informaion is encoded in | |
98 | // name=<value> pairs | |
99 | // | |
100 | ||
101 | ||
102 | int set_param | |
103 | ( | |
104 | char * name_value, // parameter name=value string | |
105 | VCPU_Config *config // set value in this sructure | |
106 | ) | |
107 | { | |
108 | // get param name | |
109 | char *name = strtok ( name_value, " =" ); | |
110 | if (name == NULL) | |
111 | { | |
112 | ui->error("cannot read cpu param name %s\n", name_value); | |
113 | return 1; | |
114 | } | |
115 | ||
116 | // get param value | |
117 | char *param = strtok ( NULL, "\0" ); | |
118 | if (param == NULL) | |
119 | { | |
120 | ui->error("cannot read cpu param value %s\n", name_value); | |
121 | return 1; | |
122 | } | |
123 | ||
124 | ||
125 | if (strcmp ( name, CPU_TYPE) == 0 ) | |
126 | { | |
127 | config->type = strdup ( param ) ; | |
128 | } | |
129 | else if (strcmp ( name, INST_NAME) == 0 ) | |
130 | { | |
131 | config->name = strdup ( param ) ; | |
132 | } | |
133 | else if (strcmp ( name, MMU_TYPE) == 0 ) | |
134 | { | |
135 | config->mmu_type = strdup ( param ) ; | |
136 | } | |
137 | else if (strcmp ( name, NWINS) == 0 ) | |
138 | { | |
139 | config->reg_wins = (int)strtol(param, NULL, 0); | |
140 | } | |
141 | else if (strcmp ( name, TLMAX ) == 0 ) | |
142 | { | |
143 | config->tl_max = (int)strtol(param, NULL, 0); | |
144 | } | |
145 | else if (strcmp ( name, DTLB_SIZE ) == 0 ) | |
146 | { | |
147 | config->dtlb_size = (int)strtol(param, NULL, 0); | |
148 | } | |
149 | else if (strcmp ( name, ITLB_SIZE ) == 0 ) | |
150 | { | |
151 | config->itlb_size = (int)strtol(param, NULL, 0); | |
152 | } | |
153 | else if (strcmp ( name, CLOCK ) == 0 ) | |
154 | { | |
155 | config->cpufreq = (unsigned long long)strtoull(param, NULL, 0); | |
156 | } | |
157 | else if (strcmp ( name, SCLOCK ) == 0 ) | |
158 | { | |
159 | ui->warning("param %s %s is not supported \n", name, param); | |
160 | } | |
161 | else if (strcmp ( name, STICKINCR ) == 0 ) | |
162 | { | |
163 | config->stickincr = (int)strtol(param, NULL, 0); | |
164 | } | |
165 | else if (strcmp ( name, LOOPTICKS ) == 0 ) | |
166 | { | |
167 | config->loopticks = (int)strtol(param, NULL, 0); | |
168 | } | |
169 | else if(strcmp(name ,CPU_ID) == 0) | |
170 | { | |
171 | config->id = (int)strtol(param,NULL,0); | |
172 | if (config->id >= NCPU_MAX) | |
173 | { | |
174 | ui->error("cpu id %d cannot exceed %d\n", config->id, NCPU_MAX ); | |
175 | return 1; | |
176 | } | |
177 | } | |
178 | else | |
179 | { | |
180 | ui->error("unknown cpu param: %s\n", name); | |
181 | return 1; | |
182 | } | |
183 | ||
184 | return 0; | |
185 | } | |
186 | ||
187 | /////////////////////////////////////////////////////////// | |
188 | // | |
189 | // get cpu config parameter string based on param name | |
190 | // | |
191 | static char *get_param ( char *name, VCPU_Config *config ) | |
192 | { | |
193 | static char param_value[40]; | |
194 | ||
195 | sprintf ( param_value, "unknown parameter" ); | |
196 | ||
197 | if (strcmp ( name, CPU_TYPE ) == 0 ) | |
198 | { | |
199 | sprintf ( param_value, "%s", config->type ); | |
200 | } | |
201 | else if (strcmp ( name, INST_NAME) == 0 ) | |
202 | { | |
203 | sprintf ( param_value, "%s", config->name ); | |
204 | } | |
205 | else if (strcmp ( name, MMU_TYPE) == 0 ) | |
206 | { | |
207 | sprintf ( param_value, "%s", config->mmu_type ); | |
208 | } | |
209 | else if (strcmp ( name, NWINS) == 0 ) | |
210 | { | |
211 | sprintf ( param_value, "%i", config->reg_wins ); | |
212 | } | |
213 | else if (strcmp ( name, TLMAX ) == 0 ) | |
214 | { | |
215 | sprintf ( param_value, "%i", config->tl_max ); | |
216 | } | |
217 | else if (strcmp ( name, DTLB_SIZE ) == 0 ) | |
218 | { | |
219 | sprintf ( param_value, "%i", config->dtlb_size ); | |
220 | } | |
221 | else if (strcmp ( name, ITLB_SIZE ) == 0 ) | |
222 | { | |
223 | sprintf ( param_value, "%i", config->itlb_size ); | |
224 | } | |
225 | else if (strcmp ( name, SCLOCK ) == 0 ) | |
226 | { | |
227 | sprintf ( param_value, "%i", config->stickfreq ); | |
228 | } | |
229 | else if (strcmp ( name, CLOCK ) == 0 ) | |
230 | { | |
231 | sprintf ( param_value, "%llu", config->cpufreq ); | |
232 | } | |
233 | else if (strcmp ( name, STICKINCR ) == 0 ) | |
234 | { | |
235 | sprintf ( param_value, "%i", config->stickincr ); | |
236 | } | |
237 | else if (strcmp ( name, LOOPTICKS ) == 0 ) | |
238 | { | |
239 | sprintf ( param_value, "%i", config->loopticks ); | |
240 | } | |
241 | else if(strcmp(name ,CPU_ID) == 0) | |
242 | { | |
243 | sprintf ( param_value, "%i", config->id ); | |
244 | } | |
245 | return param_value; | |
246 | } | |
247 | ||
248 | void set_default ( VCPU_Config &config ) | |
249 | { | |
250 | // set defaullt values | |
251 | config.name = NULL; | |
252 | config.type = NULL; //strdup("SUNW,UltraSPARC-II"); | |
253 | config.mmu_type = NULL; | |
254 | config.cpu_type = VCPU_IMPL_VER_NONE; // encoded cpu impl version | |
255 | config.reg_wins = 8; // number of reg windows | |
256 | config.tl_max = 7; // trap level max | |
257 | config.itlb_size = 64; // number of tlb entries | |
258 | config.dtlb_size = 64; | |
259 | config.stickincr= 1; // the amount stick has to be incremented | |
260 | ||
261 | // a person doing simulation ought to know these values | |
262 | // have to be initialized in the rc file ... Sreenivas | |
263 | ///* not to break the regression without changes available in rc file | |
264 | config.loopticks= 25; // number of instruction per one update of stick | |
265 | config.cpufreq = 1000000; // cpu clock | |
266 | config.stickfreq= 10000; // system clock | |
267 | //*/ | |
268 | config.cpi = 1; // cycles per instruction | |
269 | config.delay = 0; // delay this number of instructions | |
270 | config.mode = 1; // all cpu's on separate threads | |
271 | config.trace_on = 0; // tracing is off | |
272 | config.id = -1; | |
273 | ||
274 | config.execution_driven = 0; | |
275 | } | |
276 | ||
277 | ////////////////////////////////////////////////////////////// | |
278 | // | |
279 | // parse config string | |
280 | // | |
281 | static int process_config_cmd | |
282 | ( | |
283 | char *config_cmd, // config string: name=value pairs | |
284 | VCPU_Config *config // return config structure | |
285 | ) | |
286 | { | |
287 | ||
288 | char param_delimiter[] = " \0"; | |
289 | ||
290 | // make a copy because strtok() will write the termination chars | |
291 | char *cmd = strdup ( config_cmd ); | |
292 | ||
293 | int n_param = 0; // param counter | |
294 | int status = 0; | |
295 | ||
296 | for ( | |
297 | char *name_value = strtok ( cmd, param_delimiter ); | |
298 | name_value != NULL; | |
299 | name_value = strtok ( NULL, param_delimiter ) | |
300 | ) | |
301 | { | |
302 | if ( set_param ( name_value, config ) != 0 ) | |
303 | { | |
304 | ui->error("cannot set cpu param %s\n", name_value); | |
305 | status++; | |
306 | break; | |
307 | } | |
308 | ||
309 | n_param++; | |
310 | } | |
311 | ||
312 | free (cmd); | |
313 | ||
314 | if (n_param ==0) | |
315 | { | |
316 | ui->error("there are no cpu config params\n"); | |
317 | return 1; | |
318 | } | |
319 | ||
320 | ||
321 | return status; | |
322 | ||
323 | } | |
324 | ||
325 | ||
326 | int deprecated_read_cmd (void *, int argc, char **argv) | |
327 | { | |
328 | ui->error("This command is deprecated, use read-reg command instead.\n"); | |
329 | return 0; | |
330 | } | |
331 | ||
332 | int deprecated_write_cmd (void *, int argc, char **argv) | |
333 | { | |
334 | ui->error("This command is deprecated, use write-reg command instead.\n"); | |
335 | return 0; | |
336 | } | |
337 | ||
338 | ||
339 | ////////////////////////////////////////////////////////////// | |
340 | // | |
341 | // Create a new cpu instance | |
342 | // | |
343 | Vcpu* create_cpu | |
344 | ( | |
345 | char *path, // library path | |
346 | char *pconfig, // config line with name=value pairs | |
347 | VCPU_ImpIntf *intf, // cpu imported interface | |
348 | int version // cpu lib version number | |
349 | ) | |
350 | { | |
351 | VCPU_Config config_info; | |
352 | ||
353 | // process cpu config command | |
354 | // fill out config_info structure | |
355 | if ( process_config_cmd (pconfig, &config_info) != 0 ) | |
356 | { | |
357 | ui->error("Invalid Cpu config information \n"); | |
358 | exit (1); | |
359 | } | |
360 | ||
361 | ||
362 | return create_cpu ( path, config_info, intf, version ); | |
363 | ||
364 | } | |
365 | ||
366 | ////////////////// | |
367 | Vcpu* create_cpu | |
368 | ( | |
369 | char *path, // library path | |
370 | VCPU_Config &config_info, // cpu config params | |
371 | VCPU_ImpIntf *intf, // cpu imported interface | |
372 | int version // cpu lib version number | |
373 | ) | |
374 | { | |
375 | static bool id_from_sysconf = true; // expect id from sysconf | |
376 | ||
377 | if ( config_info.type == NULL ) | |
378 | { | |
379 | ui->error("missing cpu type information \n"); | |
380 | exit (1); | |
381 | } | |
382 | ||
383 | // either id is present on all lines, or its not present on any | |
384 | // sysconf line. no intermixing is allowed | |
385 | if(config_info.id == -1){ | |
386 | // sid is not provided on sysconf line. assign sid = vid | |
387 | config_info.id = g_nvcpu; | |
388 | if(g_nvcpu == 0) // first vcpu | |
389 | id_from_sysconf = false; | |
390 | if(id_from_sysconf){ | |
391 | ui->error("cpu id is being assigned implicitly. sysconf file error\n"); | |
392 | exit(1); | |
393 | } | |
394 | }else{ | |
395 | if(!id_from_sysconf){ | |
396 | ui->error("cpu id missing. sysconf file error\n"); | |
397 | exit(1); | |
398 | } | |
399 | } | |
400 | ||
401 | if (!cpu_lib_handle) // first cpu | |
402 | { | |
403 | // register cpu related ui commands | |
404 | UI_register_cmd_2 ("cpuregs", "print cpu register names", cpuregs_ui_cmd, cpuregs_cmd_usage ); | |
405 | UI_register_cmd_2 ("pregs", "print cpu architecture registers", pregs_ui_cmd, pregs_cmd_usage); | |
406 | UI_register_cmd_2 ("fpregs", "print floating-point registers", fpregs_ui_cmd, fpregs_cmd_usage); | |
407 | UI_register_cmd_2 ("cmpregs", "print cmp registers", cmpregs_ui_cmd, cmpregs_cmd_usage); | |
408 | UI_register_cmd_2 ("read-reg", "read a register by name", read_reg_ui_cmd, read_reg_cmd_usage); | |
409 | UI_register_cmd_2 ("write-reg","write value to a register", write_reg_ui_cmd, write_reg_cmd_usage); | |
410 | UI_register_cmd_2 ("set-pc", "set pc for current cpu", set_pc_ui_cmd, set_pc_cmd_usage); | |
411 | UI_register_cmd_2 ("pc", "print current pc for all cpus", pc_ui_cmd, NULL); | |
412 | UI_register_cmd_2 ("r", "print cpu regs", regs_ui_cmd, print_reg_cmd_usage); | |
413 | ||
414 | UI_register_cmd_2 ("read-fp-reg-i", "print floating point single register as integer", deprecated_read_cmd, NULL); | |
415 | UI_register_cmd_2 ("read-fp-reg-x", "print floating point double register as integer", deprecated_read_cmd, NULL); | |
416 | UI_register_cmd_2 ("read-th-ctl-reg", "print a control register value of a strand" , deprecated_read_cmd, NULL); | |
417 | UI_register_cmd_2 ("read-th-fp-reg-i", "print a single fp register value of a strand" , deprecated_read_cmd, NULL); | |
418 | UI_register_cmd_2 ("read-th-fp-reg-x", "print a double fp register value of a strand" , deprecated_read_cmd, NULL); | |
419 | UI_register_cmd_2 ("read-th-reg", "print an integer register value of a strand" , deprecated_read_cmd, NULL); | |
420 | ||
421 | UI_register_cmd_2 ("write-fp-reg-i", "write floating point single register as integer", deprecated_write_cmd, NULL); | |
422 | UI_register_cmd_2 ("write-fp-reg-x", "write floating point double register as integer", deprecated_write_cmd, NULL); | |
423 | UI_register_cmd_2 ("write-th-ctl-reg", "write a control register value of a strand" , deprecated_write_cmd, NULL); | |
424 | UI_register_cmd_2 ("write-th-fp-reg-i","write floating point single register as integer", deprecated_write_cmd, NULL); | |
425 | UI_register_cmd_2 ("write-th-fp-reg-x","write double fp register value of a strand" , deprecated_write_cmd, NULL); | |
426 | UI_register_cmd_2 ("write-th-reg", "write integer register value of a strand" , deprecated_write_cmd, NULL); | |
427 | ||
428 | } | |
429 | ||
430 | ||
431 | // generate cpu library name from the config info | |
432 | char lib_name[160]; | |
433 | sprintf(lib_name,"lib%s.so", config_info.type ); | |
434 | ||
435 | ||
436 | if (strcmp(lib_name, cpu_lib_name)!=0) // library was not loaded yet | |
437 | { | |
438 | // open shared library; | |
439 | extern void * mod_dlopen (char * pathp, char * name, int flags); | |
440 | cpu_lib_handle = mod_dlopen (path, lib_name, RTLD_LAZY|RTLD_GLOBAL|RTLD_PARENT); | |
441 | ||
442 | ||
443 | // remember last opened cpu library | |
444 | strlcpy ( cpu_lib_name, lib_name, 160 ); | |
445 | } | |
446 | ||
447 | if ( cpu_lib_handle == NULL ) | |
448 | { | |
449 | ui->error("Cannot find cpu library %s \n", lib_name ); | |
450 | exit (1); | |
451 | } | |
452 | ||
453 | // extract lib exported interface | |
454 | VCPU_GetIntfFn get_interface = (VCPU_GetIntfFn)dlsym ( cpu_lib_handle, "get_ex_interface" ); | |
455 | ||
456 | if (get_interface == NULL) | |
457 | { | |
458 | ui->error("Cannot find cpu exported interface \n"); | |
459 | exit (1); | |
460 | } | |
461 | ||
462 | // obtain cpu interface | |
463 | get_interface ( &g_cpu_ex_intf); | |
464 | ||
465 | ||
466 | ||
467 | // create cpu instance | |
468 | Vcpu * vcpu = (Vcpu*)g_cpu_ex_intf.create( &config_info, intf ); | |
469 | if ( vcpu == NULL ) | |
470 | { | |
471 | ui->error("Cannot create Cpu %s \n", config_info.name); | |
472 | exit (1); | |
473 | } | |
474 | ||
475 | int sid = vcpu->config.id; | |
476 | g_vcpu[sid] = vcpu; | |
477 | ||
478 | // total number of vcpu's | |
479 | g_nvcpu ++; | |
480 | ||
481 | // max id of the vcpu | |
482 | if (g_vcpu_id_max < sid) | |
483 | g_vcpu_id_max = sid; | |
484 | ||
485 | ||
486 | return vcpu; | |
487 | ||
488 | } | |
489 | ||
490 | ||
491 | ||
492 | // cofiguration parameters | |
493 | int set_param ( int cpu_id, char *param_name ) | |
494 | { | |
495 | Vcpu *vcpu = get_vcpu(cpu_id); | |
496 | if (!vcpu) | |
497 | return 0; | |
498 | ||
499 | return set_param (param_name, &(vcpu->config)); | |
500 | } | |
501 | char *get_param ( int cpu_id, char *param_name ) | |
502 | { | |
503 | Vcpu *vcpu = get_vcpu(cpu_id); | |
504 | if (!vcpu) | |
505 | return 0; | |
506 | ||
507 | return get_param (param_name, &(vcpu->config)); | |
508 | } | |
509 | ||
510 | // set a breakpoint from a remote debugger | |
511 | int cpu_set_breakpoint ( int cpu_id, VCPU_BpType type, uint64_t addr ) | |
512 | { | |
513 | int bp_id; | |
514 | extern int bp_action ( int bp_id, int vcpu_id ); | |
515 | Vcpu * vcpu = get_vcpu(cpu_id); | |
516 | if(!vcpu) | |
517 | return 0; | |
518 | return vcpu->set_breakpoint( &bp_id,type, addr, bp_action ); | |
519 | } | |
520 | ||
521 | // remove a breakpoint | |
522 | int cpu_remove_breakpoint ( int cpu_id, VCPU_BpType type, uint64_t addr ) | |
523 | { | |
524 | Vcpu * vcpu = get_vcpu(cpu_id); | |
525 | if(!vcpu) | |
526 | return 0; | |
527 | return vcpu->delete_breakpoint(); | |
528 | } | |
529 | ||
530 | ///////////////////////////////////////////////////////// | |
531 | // | |
532 | // Disassemble instruction | |
533 | // | |
534 | int disassemble (uint32_t iw, uint64_t pc, char *buf, int size ) | |
535 | { | |
536 | ||
537 | if ( | |
538 | ! spix_sparc_dis( buf, size, | |
539 | spix_sparc_iop(SPIX_SPARC_V9, &iw), | |
540 | &iw, pc ) | |
541 | ) | |
542 | { | |
543 | sprintf ( buf, "unknown" ); | |
544 | return 0; | |
545 | } | |
546 | return 1; | |
547 | } | |
548 | ||
549 | ||
550 | /////////////////////////////////////////////////////// | |
551 | // | |
552 | // Read vcpu regs from the ui | |
553 | // | |
554 | ||
555 | int print_reg_cmd_usage() | |
556 | { | |
557 | ui->output("usage: r [-cpu <id>] [-w [<wp>]|-g [<gwp>]|-f|df|-pr|-asr|-hpr|-tr <tr_level>|-asi <asi> <va>]\n"); | |
558 | return 0; | |
559 | } | |
560 | int regs_ui_cmd (void *, int argc, char **argv) | |
561 | { | |
562 | if (!IN_STOP_STATE (blaze_run_state)) | |
563 | { | |
564 | ui->error("not in stop state, use stop command first\n"); | |
565 | return 0; | |
566 | } | |
567 | ||
568 | int cpuid = 0; | |
569 | int greg = 0; | |
570 | int wreg = 0; | |
571 | int gl = -1; | |
572 | int wp = -1; | |
573 | int freg = 0; | |
574 | int dfreg = 0; | |
575 | int pr = 0; | |
576 | int asr = 0; | |
577 | int hpr = 0; | |
578 | int tr = 0; | |
579 | int tl = 1; | |
580 | ||
581 | int asi = 0; | |
582 | uint8_t asi_i = 0; | |
583 | uint64_t asi_va = 0; | |
584 | ||
585 | Vcpu *cpu = 0; | |
586 | ||
587 | for(int i=1; i<argc; i++) | |
588 | { | |
589 | // check reg type | |
590 | if (strcmp(argv[i], "-w")==0) | |
591 | { | |
592 | wreg = 1; | |
593 | if (((i+1)<argc) && isdigit(argv[i+1][0])) | |
594 | wp = int(strtol(argv[++i], NULL, 0)); | |
595 | continue; | |
596 | } | |
597 | else if (strcmp(argv[i], "-g")==0) | |
598 | { | |
599 | greg = 1; | |
600 | if ( ((i+1)<argc) && isdigit(argv[i+1][0]) ) | |
601 | gl = int(strtol(argv[++i], NULL, 0)); | |
602 | continue; | |
603 | } | |
604 | else if (strcmp(argv[i], "-f")==0) freg = 1; | |
605 | else if (strcmp(argv[i], "-df")==0) dfreg = 1; | |
606 | else if (strcmp(argv[i], "-pr")==0) pr = 1; | |
607 | else if (strcmp(argv[i], "-asr")==0) asr = 1; | |
608 | else if (strcmp(argv[i], "-hpr")==0) hpr = 1; | |
609 | else if ((strcmp(argv[i], "-asi")==0) && ((i+2)<argc)) | |
610 | { | |
611 | asi_i = uint8_t(strtol(argv[++i], NULL, 0)); | |
612 | asi_va = strtoll(argv[++i], NULL, 0); | |
613 | asi = 1; | |
614 | continue; | |
615 | } | |
616 | else if ((strcmp(argv[i], "-tr")==0) && ((i+1)<argc)) | |
617 | { | |
618 | tr = 1; | |
619 | tl = int(strtol(argv[++i], NULL, 0)); | |
620 | if (tl < 1) tl = 1; | |
621 | continue; | |
622 | } | |
623 | else if ((strcmp(argv[i], "-cpu")==0) && ((i+1)<argc)) | |
624 | { | |
625 | cpuid = int(strtol(argv[++i], NULL, 0)); | |
626 | if(cpuid<0) cpuid = 0; | |
627 | cpu = get_vcpu(cpuid); | |
628 | if(!cpu) | |
629 | ui->error("cpu[%d] is not available\n",cpuid); | |
630 | continue; | |
631 | } | |
632 | else if (strcmp(argv[i], "?")==0) | |
633 | { | |
634 | print_reg_cmd_usage(); | |
635 | return 0; | |
636 | } | |
637 | } | |
638 | ||
639 | if (!( greg||wreg||freg||dfreg||pr||asr||hpr||tr|asi) ) | |
640 | return print_reg_cmd_usage(); | |
641 | ||
642 | ||
643 | if(!cpu) // no cpu id was selected | |
644 | { | |
645 | cpu = get_vcpu(pselect_cpu_id); | |
646 | if(!cpu) | |
647 | { | |
648 | ui->error("cpu[%d] is not available\n",cpuid); | |
649 | return 0; | |
650 | } | |
651 | cpuid = pselect_cpu_id; | |
652 | } | |
653 | ||
654 | ui->output ( "cpu[%i]:",cpuid); | |
655 | ||
656 | if (asi) | |
657 | { | |
658 | uint64_t value = 0; | |
659 | ui->output ("asi 0x%x, va=0x%llx, ", asi_i, asi_va); | |
660 | if (cpu->get_asi(asi_i, asi_va, value) == 0) | |
661 | ui->output ("value = 0x%llx \n", value); | |
662 | else | |
663 | ui->error ("unknown \n"); | |
664 | } | |
665 | ||
666 | if (wreg) | |
667 | { | |
668 | uint64_t max_wp; | |
669 | uint64_t cur_wp; | |
670 | ||
671 | cpu->get_reg(VCPU_SIM_MAX_WP,&max_wp); | |
672 | cpu->get_reg(VCPU_PR_CWP,&cur_wp); | |
673 | ||
674 | ui->output ( "\nwindowed R registers,"); | |
675 | ||
676 | if (wp < 0) { | |
677 | wp = cur_wp; | |
678 | ui->output (" wp=%d (current)\n",wp); | |
679 | } else { | |
680 | if (wp > max_wp) | |
681 | wp = max_wp; | |
682 | ui->output (" wp=%d\n", wp); | |
683 | } | |
684 | ||
685 | cpu->set_reg(VCPU_PR_CWP,wp); | |
686 | ||
687 | for (int i=0; i<8; i++) | |
688 | { | |
689 | uint64_t value = 0; | |
690 | cpu->get_reg(VCPU_IRF_0 + i + 8, &value); // o regs | |
691 | ui->output ("%s=0x%016llx ", cpu->get_reg_name(VCPU_IRF_0 + i + 8), value); | |
692 | cpu->get_reg(VCPU_IRF_0 + i + 16, &value); // l regs | |
693 | ui->output ("%s=0x%016llx ", cpu->get_reg_name(VCPU_IRF_0 + i + 16), value); | |
694 | cpu->get_reg(VCPU_IRF_0 + i + 24, &value); // i regs | |
695 | ui->output ("%s=0x%016llx\n", cpu->get_reg_name(VCPU_IRF_0 + i + 24), value); | |
696 | } | |
697 | ||
698 | cpu->set_reg(VCPU_PR_CWP,cur_wp); | |
699 | } | |
700 | ||
701 | if (greg) | |
702 | { | |
703 | uint64_t max_gl; | |
704 | uint64_t cur_gl; | |
705 | ||
706 | cpu->get_reg(VCPU_SIM_MAX_GL,&max_gl); | |
707 | cpu->get_reg(VCPU_PR_GL,&cur_gl); | |
708 | ||
709 | ui->output ( "\nglobal R registers,"); | |
710 | ||
711 | if (gl < 0) { | |
712 | gl = cur_gl; | |
713 | ui->output (" gl=%d (current)\n",gl); | |
714 | } else { | |
715 | if (gl > max_gl) | |
716 | gl = max_gl; | |
717 | ui->output (" gl=%d\n", gl); | |
718 | } | |
719 | ||
720 | cpu->set_reg(VCPU_PR_GL,gl); | |
721 | ||
722 | for (int i=0; i<8; i++) | |
723 | { | |
724 | uint64_t value = 0; | |
725 | cpu->get_reg(VCPU_IRF_0 + i, &value); | |
726 | ui->output ("%s=0x%016llx\n", cpu->get_reg_name(VCPU_IRF_0 + i), value); | |
727 | } | |
728 | ||
729 | cpu->set_reg(VCPU_PR_GL,cur_gl); | |
730 | } | |
731 | ||
732 | ||
733 | if (freg) | |
734 | { | |
735 | ui->output ( "\nfloating point registers\n"); | |
736 | ||
737 | for (int i=0; i<32; i++) | |
738 | { | |
739 | uint64_t value = 0; | |
740 | cpu->get_reg(VCPU_FRF_0 + i, &value); | |
741 | uint32_t val32 = uint32(value); | |
742 | ui->output ( "f%-2i = %e\n", i, val32); | |
743 | } | |
744 | } | |
745 | ||
746 | if (dfreg) | |
747 | { | |
748 | ui->output ( "\ndouble floating point registers\n"); | |
749 | ||
750 | for (int i=0; i<63; i+=2) | |
751 | { | |
752 | uint64_t value = 0; | |
753 | if (cpu->get_reg(VCPU_DRF_0 + i/2, &value) == 0) | |
754 | ui->output ( "d%-2i = %e\n", i, value); | |
755 | } | |
756 | ||
757 | } | |
758 | ||
759 | if (pr) | |
760 | { | |
761 | ui->output ( "\nPR registers\n"); | |
762 | ||
763 | for (int i=0; i<32; i++) | |
764 | { | |
765 | uint64_t value = 0; | |
766 | if (cpu->get_reg(VCPU_PR_0 + i, &value) == Vcpu::REG_OK) | |
767 | { | |
768 | ui->output ( "pr%-2d %16s = 0x%llx\n", i, cpu->get_reg_name(VCPU_PR_0 + i), value); | |
769 | } | |
770 | } | |
771 | } | |
772 | ||
773 | if (asr) | |
774 | { | |
775 | ui->output ( "\nASR registers\n"); | |
776 | ||
777 | for (int i=0; i<32; i++) | |
778 | { | |
779 | uint64_t value = 0; | |
780 | if (cpu->get_reg(VCPU_ASR_0 + i, &value) == Vcpu::REG_OK) | |
781 | { | |
782 | ui->output ( "asr%-2d %16s = 0x%llx\n", i, cpu->get_reg_name(VCPU_ASR_0 + i), value); | |
783 | } | |
784 | } | |
785 | } | |
786 | ||
787 | if (hpr) | |
788 | { | |
789 | ui->output ( "\nHPR registers\n"); | |
790 | ||
791 | for (int i=0; i<32; i++) | |
792 | { | |
793 | uint64_t value = 0; | |
794 | if (cpu->get_reg(VCPU_HPR_0 + i, &value) == Vcpu::REG_OK) | |
795 | ui->output ( "hpr%-2d %16s = 0x%llx\n", i, cpu->get_reg_name(VCPU_HPR_0 + i), value); | |
796 | } | |
797 | ||
798 | } | |
799 | ||
800 | if (tr) | |
801 | { | |
802 | uint64_t max_tl; | |
803 | uint64_t cur_tl; | |
804 | ||
805 | cpu->get_reg(VCPU_SIM_MAX_TL,&max_tl); | |
806 | cpu->get_reg(VCPU_PR_TL,&cur_tl); | |
807 | ||
808 | ui->output ( "\ntrap registers, tl=%i\n", tl); | |
809 | ||
810 | if (tl < 0) { | |
811 | tl = cur_tl; | |
812 | ui->output (" tl=%d (current)\n",tl); | |
813 | } else { | |
814 | if (tl > max_tl) | |
815 | tl = max_tl; | |
816 | ui->output (" tl=%d\n", tl); | |
817 | } | |
818 | ||
819 | cpu->set_reg(VCPU_PR_TL,tl); | |
820 | ||
821 | uint64_t value = 0; | |
822 | cpu->get_reg(VCPU_PR_TPC,&value); | |
823 | ui->output ( "tpc = 0x%llx\n", value); | |
824 | cpu->get_reg(VCPU_PR_TNPC,&value); | |
825 | ui->output ( "tnpc = 0x%llx\n", value); | |
826 | cpu->get_reg(VCPU_PR_TSTATE,&value); | |
827 | ui->output ( "tstate = 0x%llx\n", value); | |
828 | cpu->get_reg(VCPU_PR_TT,&value); | |
829 | ui->output ( "tt = 0x%llx\n", value); | |
830 | if (cpu->get_reg(VCPU_HPR_HTSTATE,&value) == Vcpu::REG_OK) | |
831 | ui->output ( "htstate = 0x%llx\n", value); | |
832 | ||
833 | cpu->set_reg(VCPU_PR_TL,cur_tl); | |
834 | } | |
835 | ||
836 | ui->output("\n"); | |
837 | return 0; | |
838 | } | |
839 | ||
840 | ||
841 | ||
842 | /////////////////////////////////////////////////////// | |
843 | // | |
844 | // single step one vcpu only | |
845 | // | |
846 | int sstep_cmd (int cpu_id) | |
847 | { | |
848 | if (!IN_STOP_STATE (blaze_run_state)) | |
849 | { | |
850 | ui->error("not in stop state, use stop command first\n"); | |
851 | return 0; | |
852 | } | |
853 | ||
854 | Vcpu *vcpu = get_vcpu(cpu_id); | |
855 | if (!vcpu) | |
856 | return 0; | |
857 | ||
858 | vcpu->stepi(1); | |
859 | ||
860 | return 1; | |
861 | } | |
862 | ||
863 | ||
864 | ||
865 | ///////////////////////////////////////////////////////////////////// | |
866 | // | |
867 | int pc_ui_cmd (void *, int argc, char **argv) | |
868 | { | |
869 | for (int i=0; i<=g_vcpu_id_max; i++) | |
870 | { | |
871 | Vcpu *vcpu = get_vcpu(i); | |
872 | if (!vcpu) | |
873 | continue; | |
874 | ||
875 | uint64_t pc = 0xdead; | |
876 | vcpu->get_reg(VCPU_ASR_PC, &pc); | |
877 | ui->output ("cpu[%i]: pc=0x%llx \n", i, pc); | |
878 | } | |
879 | return 1; | |
880 | } | |
881 | ||
882 | ||
883 | ||
884 | //////////////////////////////////////////////////////////////////////// | |
885 | // | |
886 | // SAM FE command | |
887 | // | |
888 | ||
889 | // read register by name | |
890 | int cpu_read_register_name ( char *cmd ) | |
891 | { | |
892 | if (!IN_STOP_STATE(blaze_run_state)) | |
893 | { | |
894 | ui->error("not in stop state, use stop command first\n"); | |
895 | return 0; | |
896 | } | |
897 | ||
898 | Vcpu* vcpu = g_vcpu[pselect_cpu_id]; | |
899 | if (vcpu == 0) | |
900 | { | |
901 | ui->error("cpu[%d] is not available\n", pselect_cpu_id); | |
902 | return 0; | |
903 | } | |
904 | else | |
905 | { | |
906 | int index; | |
907 | uint64_t value; | |
908 | const int max_reg_name = 128; | |
909 | char reg_name[max_reg_name]; | |
910 | strlcpy(reg_name, cmd, max_reg_name); | |
911 | ||
912 | char *name = strtok ( reg_name, " \n\0" ); | |
913 | char *parm = strtok ( NULL, " \n\0" ); | |
914 | ||
915 | if (!name || parm) | |
916 | { | |
917 | ui->error("\nusage: %%reg_name , to list register names use 'cpuregs' command\n"); | |
918 | return 0; | |
919 | } | |
920 | if ( (vcpu->get_reg_index( reg_name, &index )==Vcpu::REG_OK) && | |
921 | (vcpu->get_reg( index, &value )==Vcpu::REG_OK)) | |
922 | { | |
923 | ui->output("0x%llx\n", value); | |
924 | } | |
925 | else | |
926 | { | |
927 | ui->error("cpu[%d] register %s is not available\n", pselect_cpu_id, reg_name); | |
928 | return 0; | |
929 | } | |
930 | } | |
931 | return 1; | |
932 | } | |
933 | ||
934 | //////////////////////////////////////////////////////////// | |
935 | // | |
936 | // pregs command | |
937 | // | |
938 | int pregs_cmd_usage() | |
939 | { | |
940 | ui->output("\nusage : pregs [-cpu cpu_set]]\n"); | |
941 | return 0; | |
942 | } | |
943 | int pregs_ui_cmd(void *, int argc, char **argv) | |
944 | { | |
945 | if (!IN_STOP_STATE (blaze_run_state)) | |
946 | { | |
947 | ui->error("not in stop state, use stop command first\n"); | |
948 | return 0; | |
949 | } | |
950 | ||
951 | char *cmd = "pregs"; | |
952 | CommandOptions option; | |
953 | CpuOption cpu_option(pselect_cpu_id,CpuOption::MULTITUDE); | |
954 | option.add(cpu_option); | |
955 | std::vector<std::string> args; | |
956 | if (!option.parse(argc-1,(const char**)&argv[1],args)) | |
957 | { | |
958 | ui->error("%s command parsing failed: %s\n",cmd,option.get_error_msg().c_str()); | |
959 | return 0; | |
960 | } | |
961 | if (args.size() != 0) | |
962 | return pregs_cmd_usage(); | |
963 | ||
964 | ||
965 | CpuSet& cpu_set = cpu_option.get_value(); | |
966 | ||
967 | for (CpuSet::iterator i=cpu_set.begin(); i != cpu_set.end(); ++i) | |
968 | { | |
969 | uint32_t cpu_id = *i; | |
970 | ui->output("cpu[%d]: \n",cpu_id); | |
971 | Vcpu* vcpu = g_vcpu[cpu_id]; | |
972 | if (vcpu == 0) | |
973 | { | |
974 | ui->error("cpu[%d] is not available\n", cpu_id); | |
975 | continue; | |
976 | } | |
977 | ||
978 | // pr | |
979 | for (int i=0; i<32; i++) | |
980 | { | |
981 | uint64_t value = 0; | |
982 | if (vcpu->get_reg(VCPU_PR_0 + i, &value) == Vcpu::REG_OK) | |
983 | { | |
984 | ui->output ( "pr%3d %16s = 0x%llx\n", i, vcpu->get_reg_name(VCPU_PR_0 + i), value); | |
985 | } | |
986 | } | |
987 | ||
988 | // asr | |
989 | for (int i=0; i<32; i++) | |
990 | { | |
991 | uint64_t value = 0; | |
992 | if (vcpu->get_reg(VCPU_ASR_0 + i, &value) == Vcpu::REG_OK) | |
993 | { | |
994 | ui->output ( "asr%2d %16s = 0x%llx\n", i, vcpu->get_reg_name(VCPU_ASR_0 + i), value); | |
995 | } | |
996 | } | |
997 | ||
998 | // hpr | |
999 | for (int i=0; i<32; i++) | |
1000 | { | |
1001 | uint64_t value = 0; | |
1002 | if (vcpu->get_reg(VCPU_HPR_0 + i, &value) == Vcpu::REG_OK) | |
1003 | ui->output ( "hpr%2d %16s = 0x%llx\n", i, vcpu->get_reg_name(VCPU_HPR_0 + i), value); | |
1004 | } | |
1005 | ||
1006 | } | |
1007 | ||
1008 | return 1; | |
1009 | } | |
1010 | ||
1011 | ///////////////////////////////////////////////////////////// | |
1012 | // | |
1013 | // fpregs command | |
1014 | // | |
1015 | int fpregs_cmd_usage() | |
1016 | { | |
1017 | ui->error("\nusage : fpregs [-cpu cpu_set]]\n"); | |
1018 | return 0; | |
1019 | } | |
1020 | int fpregs_ui_cmd(void *, int argc, char **argv) | |
1021 | { | |
1022 | if (!IN_STOP_STATE (blaze_run_state)) | |
1023 | { | |
1024 | ui->error("not in stop state, use stop command first\n"); | |
1025 | return 0; | |
1026 | } | |
1027 | ||
1028 | char *cmd = "fpregs"; | |
1029 | CommandOptions option; | |
1030 | CpuOption cpu_option(pselect_cpu_id,CpuOption::MULTITUDE); | |
1031 | option.add(cpu_option); | |
1032 | std::vector<std::string> args; | |
1033 | if (!option.parse(argc-1,(const char**)&argv[1],args)) | |
1034 | { | |
1035 | ui->error("%s command parsing failed: %s\n",cmd,option.get_error_msg().c_str()); | |
1036 | return 0; | |
1037 | } | |
1038 | if (args.size() != 0) | |
1039 | return fpregs_cmd_usage(); | |
1040 | ||
1041 | ||
1042 | CpuSet& cpu_set = cpu_option.get_value(); | |
1043 | ||
1044 | for (CpuSet::iterator i=cpu_set.begin(); i != cpu_set.end(); ++i) | |
1045 | { | |
1046 | uint32_t cpu_id = *i; | |
1047 | Vcpu* vcpu = g_vcpu[cpu_id]; | |
1048 | if (vcpu == 0) | |
1049 | { | |
1050 | ui->error("cpu[%d] is not available\n", cpu_id); | |
1051 | continue; | |
1052 | } | |
1053 | ui->output("cpu[%d]: ",cpu_id); | |
1054 | ||
1055 | int index; | |
1056 | uint64_t value = 0; | |
1057 | const char *fsr = "fsr"; | |
1058 | if ( (vcpu->get_reg_index( fsr, &index )==Vcpu::REG_OK) && | |
1059 | (vcpu->get_reg( index, &value )==Vcpu::REG_OK)) | |
1060 | ui->output("%s=0x%llx\n",fsr, value); | |
1061 | ||
1062 | for (int i=0; i<63; i+=2) | |
1063 | { | |
1064 | uint64_t value = 0; | |
1065 | if (vcpu->get_reg(VCPU_DRF_0 + i/2, &value) == 0) | |
1066 | ui->output ( "d%-2i=0x%016llx ", i, value); | |
1067 | ||
1068 | if (i < 32) | |
1069 | ui->output ( "f%-2i=0x%08llx f%-2i=0x%08llx\n", i, uint32(value), i+1, uint32(value>>32)); | |
1070 | else | |
1071 | ui->output("\n"); | |
1072 | } | |
1073 | } | |
1074 | ||
1075 | return 1; | |
1076 | } | |
1077 | ||
1078 | ///////////////////////////////////////////////////////////// | |
1079 | // | |
1080 | // cmpregs command | |
1081 | // | |
1082 | int cmpregs_cmd_usage() | |
1083 | { | |
1084 | ui->error("\nusage : cmpregs [-cpu cpu_set]]\n"); | |
1085 | return 0; | |
1086 | } | |
1087 | ||
1088 | int cmpregs_ui_cmd(void *, int argc, char **argv) | |
1089 | { | |
1090 | if (!IN_STOP_STATE(blaze_run_state)) | |
1091 | { | |
1092 | ui->error("not in stop state, use stop command first\n"); | |
1093 | return 0; | |
1094 | } | |
1095 | ||
1096 | char *cmd = "cmpregs"; | |
1097 | CommandOptions option; | |
1098 | CpuOption cpu_option(pselect_cpu_id,CpuOption::MULTITUDE); | |
1099 | option.add(cpu_option); | |
1100 | std::vector<std::string> args; | |
1101 | if (!option.parse(argc-1,(const char**)&argv[1],args)) | |
1102 | { | |
1103 | ui->error("%s command: %s\n",cmd,option.get_error_msg().c_str()); | |
1104 | return 0; | |
1105 | } | |
1106 | if (args.size() != 0) | |
1107 | return cmpregs_cmd_usage(); | |
1108 | ||
1109 | ||
1110 | CpuSet& cpu_set = cpu_option.get_value(); | |
1111 | ||
1112 | for (CpuSet::iterator i=cpu_set.begin(); i != cpu_set.end(); ++i) | |
1113 | { | |
1114 | uint32_t cpu_id = *i; | |
1115 | ui->output("cpu[%d]: \n",cpu_id); | |
1116 | Vcpu* vcpu = g_vcpu[cpu_id]; | |
1117 | if (vcpu == 0) | |
1118 | { | |
1119 | ui->error("cpu %d is not available\n", cpu_id); | |
1120 | continue; | |
1121 | } | |
1122 | ||
1123 | uint64_t value = 0; | |
1124 | if (vcpu->get_asi(0x41, 0x0 , value) == 0) ui->output ("STRAND_AVAILABLE 0x%016llx \n", value); | |
1125 | if (vcpu->get_asi(0x41, 0x10, value) == 0) ui->output ("STRAND_ENABLE_STATUS 0x%016llx \n", value); | |
1126 | if (vcpu->get_asi(0x41, 0x20, value) == 0) ui->output ("STRAND_ENABLE 0x%016llx \n", value); | |
1127 | if (vcpu->get_asi(0x41, 0x30, value) == 0) ui->output ("XIR_STEERING 0x%016llx \n", value); | |
1128 | if (vcpu->get_asi(0x41, 0x38, value) == 0) ui->output ("CMT_TICK_ENABLE 0x%016llx \n", value); | |
1129 | if (vcpu->get_asi(0x41, 0x50, value) == 0) ui->output ("STRAND_RUNNING 0x%016llx \n", value); | |
1130 | if (vcpu->get_asi(0x41, 0x58, value) == 0) ui->output ("STRAND_RUNNING_STATUS 0x%016llx \n", value); | |
1131 | ui->output ("\n"); | |
1132 | } | |
1133 | ||
1134 | return 1; | |
1135 | } | |
1136 | ||
1137 | ||
1138 | ////////////////////////////////////////////////// | |
1139 | // | |
1140 | // cpuregs command | |
1141 | // | |
1142 | int cpuregs_cmd_usage() | |
1143 | { | |
1144 | ui->error("\nusage : cpuregs \n"); | |
1145 | return 0; | |
1146 | } | |
1147 | int cpuregs_ui_cmd(void *, int argc, char **argv) | |
1148 | { | |
1149 | if (!IN_STOP_STATE (blaze_run_state)) | |
1150 | { | |
1151 | ui->error("not in stop state, use stop command first\n"); | |
1152 | return 0; | |
1153 | } | |
1154 | ||
1155 | Vcpu* vcpu = g_vcpu[pselect_cpu_id]; | |
1156 | if (!vcpu) | |
1157 | { | |
1158 | ui->error("cpu %d is not available\n", pselect_cpu_id); | |
1159 | return 0; | |
1160 | } | |
1161 | ||
1162 | for (int i=0; i<=VCPU_MAX_INDEX;i++) | |
1163 | { | |
1164 | const char *reg_name = vcpu->get_reg_name(i); | |
1165 | if (reg_name) | |
1166 | { | |
1167 | ui->output("%3d) %s\n", i, reg_name); | |
1168 | } | |
1169 | } | |
1170 | ||
1171 | return 1; | |
1172 | } | |
1173 | ||
1174 | ||
1175 | ||
1176 | ||
1177 | ////////////////////////////////////////////////// | |
1178 | // | |
1179 | // read-reg command | |
1180 | // | |
1181 | int read_reg_cmd_usage() | |
1182 | { | |
1183 | ui->error("\nusage : read-reg [-cpu cpu_set] reg-name\n"); | |
1184 | return 0; | |
1185 | } | |
1186 | int read_reg_ui_cmd(void *, int argc, char **argv) | |
1187 | { | |
1188 | if (!IN_STOP_STATE (blaze_run_state)) | |
1189 | { | |
1190 | ui->error("not in stop state, use stop command first\n"); | |
1191 | return 0; | |
1192 | } | |
1193 | ||
1194 | char *cmd = "read-reg"; | |
1195 | ||
1196 | CommandOptions option; | |
1197 | CpuOption cpu_option(pselect_cpu_id,CpuOption::MULTITUDE); | |
1198 | option.add(cpu_option); | |
1199 | std::vector<std::string> args; | |
1200 | if (!option.parse(argc-1,(const char**)&argv[1],args)) | |
1201 | { | |
1202 | ui->error("%s command parsing failed: %s\n",cmd,option.get_error_msg().c_str()); | |
1203 | return 0; | |
1204 | } | |
1205 | if (args.size() != 1) | |
1206 | { | |
1207 | ui->error("%s requires 1 positional argument - register name.\n",cmd); | |
1208 | return 0; | |
1209 | } | |
1210 | ||
1211 | CpuSet& cpu_set = cpu_option.get_value(); | |
1212 | ||
1213 | for (CpuSet::iterator i=cpu_set.begin(); i != cpu_set.end(); ++i) | |
1214 | { | |
1215 | uint32_t cpu_id = *i; | |
1216 | Vcpu* vcpu = g_vcpu[cpu_id]; | |
1217 | if (vcpu == 0) | |
1218 | { | |
1219 | ui->error("cpu[%d] is not available\n", cpu_id); | |
1220 | continue; | |
1221 | } | |
1222 | int index; | |
1223 | uint64_t value; | |
1224 | const char *reg_name = args[0].c_str(); | |
1225 | if ( (vcpu->get_reg_index( reg_name, &index )==Vcpu::REG_OK) && | |
1226 | (vcpu->get_reg( index, &value )==Vcpu::REG_OK)) | |
1227 | { | |
1228 | ui->output("cpu[%d]: %s=0x%llx\n",cpu_id, reg_name, value); | |
1229 | } | |
1230 | else | |
1231 | { | |
1232 | ui->error("cpu[%d] - register %s is not available\n", cpu_id, reg_name); | |
1233 | return 0; | |
1234 | } | |
1235 | } | |
1236 | ||
1237 | ||
1238 | return 1; | |
1239 | } | |
1240 | ||
1241 | ||
1242 | ////////////////////////////////////////////////// | |
1243 | // | |
1244 | // set-pc command | |
1245 | // | |
1246 | int set_pc_cmd_usage() | |
1247 | { | |
1248 | ui->error("\nusage : set-pc address\n"); | |
1249 | return 0; | |
1250 | } | |
1251 | int set_pc_ui_cmd(void *, int argc, char **argv) | |
1252 | { | |
1253 | if (!IN_STOP_STATE (blaze_run_state)) | |
1254 | { | |
1255 | ui->error("not in stop state, use stop command first\n"); | |
1256 | return 0; | |
1257 | } | |
1258 | ||
1259 | char *cmd = "set_pc"; | |
1260 | ||
1261 | CommandOptions option; | |
1262 | CpuOption cpu_option(pselect_cpu_id); | |
1263 | option.add(cpu_option); | |
1264 | std::vector<std::string> args; | |
1265 | if (!option.parse(argc-1,(const char**)&argv[1],args)) | |
1266 | { | |
1267 | ui->error("%s command parsing failed: %s\n",cmd,option.get_error_msg().c_str()); | |
1268 | return 0; | |
1269 | } | |
1270 | if (args.size() != 1) | |
1271 | { | |
1272 | ui->error("%s requires 1 positional argument - pc value.\n",cmd); | |
1273 | return 0; | |
1274 | } | |
1275 | ||
1276 | uint32_t cpu_id = *(cpu_option.get_value().begin()); | |
1277 | ||
1278 | Vcpu* vcpu = g_vcpu[cpu_id]; | |
1279 | if (vcpu == 0) | |
1280 | { | |
1281 | ui->error("cpu[%d] is not available\n", cpu_id); | |
1282 | return 0; | |
1283 | } | |
1284 | ||
1285 | uint64_t value = strtoull(args[0].c_str(), NULL, 0); | |
1286 | ||
1287 | if ( vcpu->set_reg( VCPU_ASR_PC, value )!=Vcpu::REG_OK) | |
1288 | { | |
1289 | ui->error(" cannot set pc value 0x%llx for cpu[%d]\n",value,cpu_id); | |
1290 | return 0; | |
1291 | } | |
1292 | ||
1293 | return 1; | |
1294 | } | |
1295 | ||
1296 | ||
1297 | ////////////////////////////////////////////////// | |
1298 | // | |
1299 | // write-reg command | |
1300 | // | |
1301 | ||
1302 | int write_reg_cmd_usage() | |
1303 | { | |
1304 | ui->output("\nusage : write-reg [-cpu cpu_set] reg-name value\n"); | |
1305 | return 0; | |
1306 | } | |
1307 | int write_reg_ui_cmd(void *, int argc, char **argv) | |
1308 | { | |
1309 | if (!IN_STOP_STATE (blaze_run_state)) | |
1310 | { | |
1311 | ui->error("not in stop state, use stop command first\n"); | |
1312 | return 0; | |
1313 | } | |
1314 | ||
1315 | char *cmd = "write-reg"; | |
1316 | ||
1317 | CommandOptions option; | |
1318 | CpuOption cpu_option(pselect_cpu_id); | |
1319 | option.add(cpu_option); | |
1320 | std::vector<std::string> args; | |
1321 | if (!option.parse(argc-1,(const char**)&argv[1],args)) | |
1322 | { | |
1323 | ui->error("%s command parsing failed: %s\n",cmd,option.get_error_msg().c_str()); | |
1324 | return 0; | |
1325 | } | |
1326 | if (args.size() != 2) | |
1327 | { | |
1328 | ui->error("%s requires 2 positional argument - reg name and value.\n",cmd); | |
1329 | return 0; | |
1330 | } | |
1331 | ||
1332 | uint32_t cpu_id = *(cpu_option.get_value().begin()); | |
1333 | ||
1334 | Vcpu* vcpu = g_vcpu[cpu_id]; | |
1335 | if (vcpu == 0) | |
1336 | { | |
1337 | ui->error("cpu[%d] is not available\n", cpu_id); | |
1338 | return 0; | |
1339 | } | |
1340 | ||
1341 | int index; | |
1342 | uint64_t value = strtoull(args[1].c_str(), NULL, 0); | |
1343 | ||
1344 | const char *reg_name = args[0].c_str(); | |
1345 | if ( (vcpu->get_reg_index( reg_name, &index )!=Vcpu::REG_OK) || | |
1346 | (vcpu->set_reg( index, value ) !=Vcpu::REG_OK) ) | |
1347 | { | |
1348 | ui->error("cannot set reg %s=0x%llx for cpu[%d]\n",reg_name,value,cpu_id); | |
1349 | return 0; | |
1350 | } | |
1351 | ||
1352 | return 1; | |
1353 | } | |
1354 |