1 /////////////////////////////////////////////////////////////////////////
2 // $Id: paramtree.cc 14206 2021-03-28 06:31:03Z vruppert $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2010-2021 The Bochs Project
6 //
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 2 of the License, or (at your option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Lesser General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this library; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 //
21 /////////////////////////////////////////////////////////////////////////
22
23 #include "bochs.h"
24 #include "siminterface.h"
25 #include "paramtree.h"
26
27 /////////////////////////////////////////////////////////////////////////
28 // define methods of bx_param_* and family
29 /////////////////////////////////////////////////////////////////////////
30
31 extern bx_simulator_interface_c *SIM;
32 extern logfunctions *siminterface_log;
33 extern bx_list_c *root_param;
34 #define LOG_THIS siminterface_log->
35
36 const char* bx_param_c::default_text_format = NULL;
37
bx_param_c(Bit32u id,const char * param_name,const char * param_desc)38 bx_param_c::bx_param_c(Bit32u id, const char *param_name, const char *param_desc)
39 : bx_object_c(id),
40 parent(NULL),
41 description(NULL),
42 label(NULL),
43 ask_format(NULL),
44 group_name(NULL)
45 {
46 set_type(BXT_PARAM);
47 this->name = new char[strlen(param_name)+1];
48 strcpy(this->name, param_name);
49 set_description(param_desc);
50 this->text_format = default_text_format;
51 this->long_text_format = default_text_format;
52 this->runtime_param = 0;
53 this->enabled = 1;
54 this->options = 0;
55 // dependent_list must be initialized before the set(),
56 // because set calls update_dependents().
57 dependent_list = NULL;
58 }
59
bx_param_c(Bit32u id,const char * param_name,const char * param_label,const char * param_desc)60 bx_param_c::bx_param_c(Bit32u id, const char *param_name, const char *param_label, const char *param_desc)
61 : bx_object_c(id),
62 parent(NULL),
63 description(NULL),
64 label(NULL),
65 ask_format(NULL),
66 group_name(NULL)
67 {
68 set_type(BXT_PARAM);
69 this->name = new char[strlen(param_name)+1];
70 strcpy(this->name, param_name);
71 set_description(param_desc);
72 set_label(param_label);
73 this->text_format = default_text_format;
74 this->long_text_format = default_text_format;
75 this->runtime_param = 0;
76 this->enabled = 1;
77 this->options = 0;
78 // dependent_list must be initialized before the set(),
79 // because set calls update_dependents().
80 dependent_list = NULL;
81 }
82
~bx_param_c()83 bx_param_c::~bx_param_c()
84 {
85 delete [] name;
86 delete [] label;
87 delete [] description;
88 delete [] ask_format;
89 delete [] group_name;
90 delete dependent_list;
91 }
92
set_description(const char * text)93 void bx_param_c::set_description(const char *text)
94 {
95 delete [] this->description;
96 if (text) {
97 this->description = new char[strlen(text)+1];
98 strcpy(this->description, text);
99 } else {
100 this->description = NULL;
101 }
102 }
103
set_label(const char * text)104 void bx_param_c::set_label(const char *text)
105 {
106 delete [] label;
107 if (text) {
108 label = new char[strlen(text)+1];
109 strcpy(label, text);
110 } else {
111 label = NULL;
112 }
113 }
114
set_ask_format(const char * format)115 void bx_param_c::set_ask_format(const char *format)
116 {
117 delete [] ask_format;
118 if (format) {
119 ask_format = new char[strlen(format)+1];
120 strcpy(ask_format, format);
121 } else {
122 ask_format = NULL;
123 }
124 }
125
set_group(const char * group)126 void bx_param_c::set_group(const char *group)
127 {
128 delete [] group_name;
129 if (group) {
130 group_name = new char[strlen(group)+1];
131 strcpy(group_name, group);
132 } else {
133 group_name = NULL;
134 }
135 }
136
get_param_path(char * path_out,int maxlen)137 int bx_param_c::get_param_path(char *path_out, int maxlen)
138 {
139 if ((get_parent() == NULL) || (get_parent() == root_param)) {
140 // Start with an empty string.
141 // Never print the name of the root param.
142 path_out[0] = 0;
143 } else {
144 // build path of the parent, add a period, add path of this node
145 if (get_parent()->get_param_path(path_out, maxlen) > 0) {
146 strncat(path_out, ".", maxlen);
147 }
148 }
149 strncat(path_out, name, maxlen);
150 return strlen(path_out);
151 }
152
set_default_format(const char * f)153 const char* bx_param_c::set_default_format(const char *f)
154 {
155 const char *old = default_text_format;
156 default_text_format = f;
157 return old;
158 }
159
bx_param_num_c(bx_param_c * parent,const char * name,const char * label,const char * description,Bit64s min,Bit64s max,Bit64s initial_val,bool is_shadow)160 bx_param_num_c::bx_param_num_c(bx_param_c *parent,
161 const char *name,
162 const char *label,
163 const char *description,
164 Bit64s min, Bit64s max, Bit64s initial_val,
165 bool is_shadow)
166 : bx_param_c(SIM->gen_param_id(), name, label, description)
167 {
168 set_type(BXT_PARAM_NUM);
169 this->min = min;
170 this->max = max;
171 this->initial_val = initial_val;
172 this->val.number = initial_val;
173 this->handler = NULL;
174 this->save_handler = NULL;
175 this->restore_handler = NULL;
176 this->enable_handler = NULL;
177 this->base = default_base;
178 this->is_shadow = is_shadow;
179 if (!is_shadow) {
180 set(initial_val);
181 }
182 if (parent) {
183 BX_ASSERT(parent->get_type() == BXT_LIST);
184 this->parent = (bx_list_c *)parent;
185 this->parent->add(this);
186 }
187 }
188
189 Bit32u bx_param_num_c::default_base = BASE_DEC;
190
set_default_base(Bit32u val)191 Bit32u bx_param_num_c::set_default_base(Bit32u val)
192 {
193 Bit32u old = default_base;
194 default_base = val;
195 return old;
196 }
197
set_handler(param_event_handler handler)198 void bx_param_num_c::set_handler(param_event_handler handler)
199 {
200 this->handler = handler;
201 // now that there's a handler, call set once to run the handler immediately
202 //set (get ());
203 }
204
set_sr_handlers(void * devptr,param_save_handler save,param_restore_handler restore)205 void bx_param_num_c::set_sr_handlers(void *devptr, param_save_handler save, param_restore_handler restore)
206 {
207 sr_devptr = devptr;
208 save_handler = save;
209 restore_handler = restore;
210 }
211
set_dependent_list(bx_list_c * l)212 void bx_param_num_c::set_dependent_list(bx_list_c *l)
213 {
214 dependent_list = l;
215 update_dependents();
216 }
217
get64()218 Bit64s bx_param_num_c::get64()
219 {
220 if (save_handler) {
221 return (*save_handler)(sr_devptr, this);
222 }
223 if (handler) {
224 // the handler can decide what value to return and/or do some side effect
225 return (*handler)(this, 0, val.number);
226 } else {
227 // just return the value
228 return val.number;
229 }
230 }
231
set(Bit64s newval)232 void bx_param_num_c::set(Bit64s newval)
233 {
234 if (!enabled) return;
235
236 if (handler) {
237 // the handler can override the new value and/or perform some side effect
238 val.number = (*handler)(this, 1, newval);
239 } else {
240 // just set the value. This code does not check max/min.
241 val.number = newval;
242 }
243 if (restore_handler) {
244 val.number = newval;
245 (*restore_handler)(sr_devptr, this, newval);
246 }
247 if ((val.number < min || val.number > max) && (Bit64u)max != BX_MAX_BIT64U)
248 BX_PANIC(("numerical parameter '%s' was set to " FMT_LL "d, which is out of range " FMT_LL "d to " FMT_LL "d", get_name (), val.number, min, max));
249 if (dependent_list != NULL) update_dependents();
250 }
251
set_range(Bit64u min,Bit64u max)252 void bx_param_num_c::set_range(Bit64u min, Bit64u max)
253 {
254 this->min = min;
255 this->max = max;
256 }
257
set_initial_val(Bit64s initial_val)258 void bx_param_num_c::set_initial_val(Bit64s initial_val)
259 {
260 this->val.number = this->initial_val = initial_val;
261 }
262
update_dependents()263 void bx_param_num_c::update_dependents()
264 {
265 if (dependent_list) {
266 int en = val.number && enabled;
267 for (int i=0; i<dependent_list->get_size(); i++) {
268 bx_param_c *param = dependent_list->get(i);
269 if (param != this)
270 param->set_enabled(en);
271 }
272 }
273 }
274
set_enabled(bool en)275 void bx_param_num_c::set_enabled(bool en)
276 {
277 // The enable handler may wish to allow/disallow the action
278 if (enable_handler) {
279 en = (*enable_handler)(this, en);
280 }
281 bx_param_c::set_enabled(en);
282 update_dependents();
283 }
284
parse_param(const char * ptr)285 int bx_param_num_c::parse_param(const char *ptr)
286 {
287 if (ptr != NULL) {
288 Bit64u value;
289 if (get_base() == BASE_DOUBLE) {
290 double f2value = strtod(ptr, NULL);
291 memcpy(&value, &f2value, sizeof(double));
292 set(value);
293 } else if (get_base() == BASE_FLOAT) {
294 float f1value = (float)strtod(ptr, NULL);
295 memcpy(&value, &f1value, sizeof(float));
296 set(value);
297 } else if ((ptr[0] == '0') && (ptr[1] == 'x')) {
298 set(strtoull(ptr, NULL, 16));
299 } else {
300 if (ptr[strlen(ptr)-1] == 'K') {
301 set(1000 * strtoull(ptr, NULL, 10));
302 }
303 else if (ptr[strlen(ptr)-1] == 'M') {
304 set(1000000 * strtoull(ptr, NULL, 10));
305 }
306 else {
307 set(strtoull(ptr, NULL, 10));
308 }
309 }
310 return 1;
311 }
312
313 return 0;
314 }
315
dump_param(FILE * fp)316 void bx_param_num_c::dump_param(FILE *fp)
317 {
318 char tmpstr[BX_PATHNAME_LEN+1];
319 dump_param(tmpstr, BX_PATHNAME_LEN, 0);
320 fputs(tmpstr, fp);
321 }
322
dump_param(char * buf,int len,bool dquotes)323 int bx_param_num_c::dump_param(char *buf, int len, bool dquotes)
324 {
325 Bit64s value = get64();
326 if (get_base() == BASE_DOUBLE) {
327 double f2value;
328 memcpy(&f2value, &value, sizeof(double));
329 snprintf(buf, len, "%f", f2value);
330 } else if (get_base() == BASE_FLOAT) {
331 float f1value;
332 memcpy(&f1value, &value, sizeof(float));
333 snprintf(buf, len, "%f", f1value);
334 } else if (get_base() == BASE_DEC) {
335 if (get_min() >= BX_MIN_BIT64U) {
336 if ((Bit64u) get_max() > BX_MAX_BIT32U) {
337 snprintf(buf, len, FMT_LL"u", value);
338 } else {
339 snprintf(buf, len, "%u", (Bit32u) value);
340 }
341 } else {
342 snprintf(buf, len, "%d", (Bit32s) value);
343 }
344 } else {
345 if (get_format()) {
346 snprintf(buf, len, get_format(), value);
347 } else {
348 if ((Bit64u)get_max() > BX_MAX_BIT32U) {
349 snprintf(buf, len, "0x" FMT_LL "x", (Bit64u) value);
350 } else {
351 snprintf(buf, len, "0x%x", (Bit32u) value);
352 }
353 }
354 }
355
356 return strlen(buf);
357 }
358
359 // Signed 64 bit
bx_shadow_num_c(bx_param_c * parent,const char * name,Bit64s * ptr_to_real_val,int base,Bit8u highbit,Bit8u lowbit)360 bx_shadow_num_c::bx_shadow_num_c(bx_param_c *parent,
361 const char *name,
362 Bit64s *ptr_to_real_val,
363 int base,
364 Bit8u highbit,
365 Bit8u lowbit)
366 : bx_param_num_c(parent, name, NULL, NULL, BX_MIN_BIT64S, BX_MAX_BIT64S, *ptr_to_real_val, 1)
367 {
368 this->varsize = 64;
369 this->lowbit = lowbit;
370 this->mask = ((BX_MAX_BIT64S >> (63 - (highbit - lowbit))) << lowbit);
371 val.p64bit = ptr_to_real_val;
372 if (base == BASE_HEX) {
373 this->base = base;
374 this->text_format = "0x" FMT_LL "x";
375 }
376 }
377
378 // Unsigned 64 bit
bx_shadow_num_c(bx_param_c * parent,const char * name,Bit64u * ptr_to_real_val,int base,Bit8u highbit,Bit8u lowbit)379 bx_shadow_num_c::bx_shadow_num_c(bx_param_c *parent,
380 const char *name,
381 Bit64u *ptr_to_real_val,
382 int base,
383 Bit8u highbit,
384 Bit8u lowbit)
385 : bx_param_num_c(parent, name, NULL, NULL, BX_MIN_BIT64U, BX_MAX_BIT64U, *ptr_to_real_val, 1)
386 {
387 this->varsize = 64;
388 this->lowbit = lowbit;
389 this->mask = ((BX_MAX_BIT64U >> (63 - (highbit - lowbit))) << lowbit);
390 val.p64bit = (Bit64s*) ptr_to_real_val;
391 if (base == BASE_HEX) {
392 this->base = base;
393 this->text_format = "0x" FMT_LL "x";
394 }
395 }
396
397 // Signed 32 bit
bx_shadow_num_c(bx_param_c * parent,const char * name,Bit32s * ptr_to_real_val,int base,Bit8u highbit,Bit8u lowbit)398 bx_shadow_num_c::bx_shadow_num_c(bx_param_c *parent,
399 const char *name,
400 Bit32s *ptr_to_real_val,
401 int base,
402 Bit8u highbit,
403 Bit8u lowbit)
404 : bx_param_num_c(parent, name, NULL, NULL, BX_MIN_BIT32S, BX_MAX_BIT32S, *ptr_to_real_val, 1)
405 {
406 this->varsize = 32;
407 this->lowbit = lowbit;
408 this->mask = ((BX_MAX_BIT32S >> (31 - (highbit - lowbit))) << lowbit);
409 val.p32bit = ptr_to_real_val;
410 if (base == BASE_HEX) {
411 this->base = base;
412 this->text_format = "0x%08x";
413 }
414 }
415
416 // Unsigned 32 bit
bx_shadow_num_c(bx_param_c * parent,const char * name,Bit32u * ptr_to_real_val,int base,Bit8u highbit,Bit8u lowbit)417 bx_shadow_num_c::bx_shadow_num_c(bx_param_c *parent,
418 const char *name,
419 Bit32u *ptr_to_real_val,
420 int base,
421 Bit8u highbit,
422 Bit8u lowbit)
423 : bx_param_num_c(parent, name, NULL, NULL, BX_MIN_BIT32U, BX_MAX_BIT32U, *ptr_to_real_val, 1)
424 {
425 this->varsize = 32;
426 this->lowbit = lowbit;
427 this->mask = ((BX_MAX_BIT32U >> (31 - (highbit - lowbit))) << lowbit);
428 val.p32bit = (Bit32s*) ptr_to_real_val;
429 if (base == BASE_HEX) {
430 this->base = base;
431 this->text_format = "0x%08x";
432 }
433 }
434
435 // Signed 16 bit
bx_shadow_num_c(bx_param_c * parent,const char * name,Bit16s * ptr_to_real_val,int base,Bit8u highbit,Bit8u lowbit)436 bx_shadow_num_c::bx_shadow_num_c(bx_param_c *parent,
437 const char *name,
438 Bit16s *ptr_to_real_val,
439 int base,
440 Bit8u highbit,
441 Bit8u lowbit)
442 : bx_param_num_c(parent, name, NULL, NULL, BX_MIN_BIT16S, BX_MAX_BIT16S, *ptr_to_real_val, 1)
443 {
444 this->varsize = 16;
445 this->lowbit = lowbit;
446 this->mask = ((BX_MAX_BIT16S >> (15 - (highbit - lowbit))) << lowbit);
447 val.p16bit = ptr_to_real_val;
448 if (base == BASE_HEX) {
449 this->base = base;
450 this->text_format = "0x%04x";
451 }
452 }
453
454 // Unsigned 16 bit
bx_shadow_num_c(bx_param_c * parent,const char * name,Bit16u * ptr_to_real_val,int base,Bit8u highbit,Bit8u lowbit)455 bx_shadow_num_c::bx_shadow_num_c(bx_param_c *parent,
456 const char *name,
457 Bit16u *ptr_to_real_val,
458 int base,
459 Bit8u highbit,
460 Bit8u lowbit)
461 : bx_param_num_c(parent, name, NULL, NULL, BX_MIN_BIT16U, BX_MAX_BIT16U, *ptr_to_real_val, 1)
462 {
463 this->varsize = 16;
464 this->lowbit = lowbit;
465 this->mask = ((BX_MAX_BIT16U >> (15 - (highbit - lowbit))) << lowbit);
466 val.p16bit = (Bit16s*) ptr_to_real_val;
467 if (base == BASE_HEX) {
468 this->base = base;
469 this->text_format = "0x%04x";
470 }
471 }
472
473 // Signed 8 bit
bx_shadow_num_c(bx_param_c * parent,const char * name,Bit8s * ptr_to_real_val,int base,Bit8u highbit,Bit8u lowbit)474 bx_shadow_num_c::bx_shadow_num_c(bx_param_c *parent,
475 const char *name,
476 Bit8s *ptr_to_real_val,
477 int base,
478 Bit8u highbit,
479 Bit8u lowbit)
480 : bx_param_num_c(parent, name, NULL, NULL, BX_MIN_BIT8S, BX_MAX_BIT8S, *ptr_to_real_val, 1)
481 {
482 this->varsize = 8;
483 this->lowbit = lowbit;
484 this->mask = ((BX_MAX_BIT8S >> (7 - (highbit - lowbit))) << lowbit);
485 this->mask = (1 << (highbit - lowbit)) - 1;
486 val.p8bit = ptr_to_real_val;
487 if (base == BASE_HEX) {
488 this->base = base;
489 this->text_format = "0x%02x";
490 }
491 }
492
493 // Unsigned 8 bit
bx_shadow_num_c(bx_param_c * parent,const char * name,Bit8u * ptr_to_real_val,int base,Bit8u highbit,Bit8u lowbit)494 bx_shadow_num_c::bx_shadow_num_c(bx_param_c *parent,
495 const char *name,
496 Bit8u *ptr_to_real_val,
497 int base,
498 Bit8u highbit,
499 Bit8u lowbit)
500 : bx_param_num_c(parent, name, NULL, NULL, BX_MIN_BIT8U, BX_MAX_BIT8U, *ptr_to_real_val, 1)
501 {
502 this->varsize = 8;
503 this->lowbit = lowbit;
504 this->mask = ((BX_MAX_BIT8U >> (7 - (highbit - lowbit))) << lowbit);
505 val.p8bit = (Bit8s*) ptr_to_real_val;
506 if (base == BASE_HEX) {
507 this->base = base;
508 this->text_format = "0x%02x";
509 }
510 }
511
512 // Float (floating point)
bx_shadow_num_c(bx_param_c * parent,const char * name,float * ptr_to_real_val)513 bx_shadow_num_c::bx_shadow_num_c(bx_param_c *parent,
514 const char *name,
515 float *ptr_to_real_val)
516 : bx_param_num_c(parent, name, NULL, NULL, BX_MIN_BIT64U, BX_MAX_BIT64U, 0, 1)
517 {
518 this->varsize = 32;
519 this->lowbit = 0;
520 this->mask = BX_MAX_BIT32U;
521 val.pfloat = ptr_to_real_val;
522 this->base = BASE_FLOAT;
523 }
524
525 // Double (floating point)
bx_shadow_num_c(bx_param_c * parent,const char * name,double * ptr_to_real_val)526 bx_shadow_num_c::bx_shadow_num_c(bx_param_c *parent,
527 const char *name,
528 double *ptr_to_real_val)
529 : bx_param_num_c(parent, name, NULL, NULL, BX_MIN_BIT64U, BX_MAX_BIT64U, 0, 1)
530 {
531 this->varsize = 64;
532 this->lowbit = 0;
533 this->mask = BX_MAX_BIT64U;
534 val.pdouble = ptr_to_real_val;
535 this->base = BASE_DOUBLE;
536 }
537
get64()538 Bit64s bx_shadow_num_c::get64()
539 {
540 Bit64u current = 0;
541 switch (varsize) {
542 case 8: current = *(val.p8bit); break;
543 case 16: current = *(val.p16bit); break;
544 case 32: current = *(val.p32bit); break;
545 case 64: current = *(val.p64bit); break;
546 default: BX_PANIC(("unsupported varsize %d", varsize));
547 }
548 current = (current >> lowbit) & mask;
549 if (handler) {
550 // the handler can decide what value to return and/or do some side effect
551 return (*handler)(this, 0, current) & mask;
552 } else {
553 // just return the value
554 return current;
555 }
556 }
557
set(Bit64s newval)558 void bx_shadow_num_c::set(Bit64s newval)
559 {
560 Bit64u tmp = 0;
561 if (((newval < min) || (newval > max)) && (min != BX_MIN_BIT64S) && ((Bit64u)max != BX_MAX_BIT64U))
562 BX_PANIC(("numerical parameter %s was set to " FMT_LL "d, which is out of range " FMT_LL "d to " FMT_LL "d", get_name (), newval, min, max));
563 switch (varsize) {
564 case 8:
565 tmp = *(val.p8bit) & ~(mask << lowbit);
566 tmp |= (newval & mask) << lowbit;
567 *(val.p8bit) = (Bit8s)tmp;
568 break;
569 case 16:
570 tmp = *(val.p16bit) & ~(mask << lowbit);
571 tmp |= (newval & mask) << lowbit;
572 *(val.p16bit) = (Bit16s)tmp;
573 break;
574 case 32:
575 tmp = *(val.p32bit) & ~(mask << lowbit);
576 tmp |= (newval & mask) << lowbit;
577 *(val.p32bit) = (Bit32s)tmp;
578 break;
579 case 64:
580 tmp = *(val.p64bit) & ~(mask << lowbit);
581 tmp |= (newval & mask) << lowbit;
582 *(val.p64bit) = (Bit64s)tmp;
583 break;
584 default:
585 BX_PANIC(("unsupported varsize %d", varsize));
586 }
587 if (handler) {
588 // the handler can override the new value and/or perform some side effect
589 (*handler)(this, 1, tmp);
590 }
591 }
592
reset()593 void bx_shadow_num_c::reset()
594 {
595 BX_PANIC(("reset not supported on bx_shadow_num_c yet"));
596 }
597
bx_param_bool_c(bx_param_c * parent,const char * name,const char * label,const char * description,Bit64s initial_val,bool is_shadow)598 bx_param_bool_c::bx_param_bool_c(bx_param_c *parent,
599 const char *name,
600 const char *label,
601 const char *description,
602 Bit64s initial_val,
603 bool is_shadow)
604 : bx_param_num_c(parent, name, label, description, 0, 1, initial_val, is_shadow)
605 {
606 set_type(BXT_PARAM_BOOL);
607 }
608
parse_param(const char * ptr)609 int bx_param_bool_c::parse_param(const char *ptr)
610 {
611 if (ptr != NULL) {
612 if (!strcmp(ptr, "0") || !stricmp(ptr, "false")) {
613 set(0); return 1;
614 }
615 if (!strcmp(ptr, "1") || !stricmp(ptr, "true")) {
616 set(1); return 1;
617 }
618 }
619
620 return 0;
621 }
622
dump_param(FILE * fp)623 void bx_param_bool_c::dump_param(FILE *fp)
624 {
625 fprintf(fp, "%s", get()?"true":"false");
626 }
627
dump_param(char * buf,int len,bool dquotes)628 int bx_param_bool_c::dump_param(char *buf, int len, bool dquotes)
629 {
630 snprintf(buf, len, "%s", get()?"true":"false");
631 return strlen(buf);
632 }
633
bx_shadow_bool_c(bx_param_c * parent,const char * name,const char * label,bool * ptr_to_real_val)634 bx_shadow_bool_c::bx_shadow_bool_c(bx_param_c *parent,
635 const char *name,
636 const char *label,
637 bool *ptr_to_real_val)
638 : bx_param_bool_c(parent, name, label, NULL, (Bit64s) *ptr_to_real_val, 1)
639 {
640 val.pbool = ptr_to_real_val;
641 }
642
bx_shadow_bool_c(bx_param_c * parent,const char * name,bool * ptr_to_real_val)643 bx_shadow_bool_c::bx_shadow_bool_c(bx_param_c *parent,
644 const char *name,
645 bool *ptr_to_real_val)
646 : bx_param_bool_c(parent, name, NULL, NULL, (Bit64s) *ptr_to_real_val, 1)
647 {
648 val.pbool = ptr_to_real_val;
649 }
650
get64()651 Bit64s bx_shadow_bool_c::get64()
652 {
653 if (handler) {
654 // the handler can decide what value to return and/or do some side effect
655 return (*handler)(this, 0, (Bit64s) *(val.pbool));
656 } else {
657 // just return the value
658 return (Bit64s)*(val.pbool);
659 }
660 }
661
set(Bit64s newval)662 void bx_shadow_bool_c::set(Bit64s newval)
663 {
664 *(val.pbool) = (newval != 0);
665 if (handler) {
666 // the handler can override the new value and/or perform some side effect
667 (*handler)(this, 1, (Bit64s)newval);
668 }
669 }
670
bx_param_enum_c(bx_param_c * parent,const char * name,const char * label,const char * description,const char ** choices,Bit64s initial_val,Bit64s value_base)671 bx_param_enum_c::bx_param_enum_c(bx_param_c *parent,
672 const char *name,
673 const char *label,
674 const char *description,
675 const char **choices,
676 Bit64s initial_val,
677 Bit64s value_base)
678 : bx_param_num_c(parent, name, label, description, value_base, BX_MAX_BIT64S, initial_val)
679 {
680 set_type(BXT_PARAM_ENUM);
681 this->choices = choices;
682 // count number of choices, set max
683 const char **p = choices;
684 while (*p != NULL) p++;
685 this->min = value_base;
686 // now that the max is known, replace the BX_MAX_BIT64S sent to the parent
687 // class constructor with the real max.
688 this->max = value_base + (p - choices - 1);
689 this->deps_bitmap = NULL;
690 set(initial_val);
691 }
692
~bx_param_enum_c()693 bx_param_enum_c::~bx_param_enum_c()
694 {
695 delete [] deps_bitmap;
696 }
697
698
set(Bit64s val)699 void bx_param_enum_c::set(Bit64s val)
700 {
701 bx_param_num_c::set(val);
702 update_dependents();
703 }
704
find_by_name(const char * s)705 int bx_param_enum_c::find_by_name(const char *s)
706 {
707 const char **p;
708 for (p=&choices[0]; *p; p++) {
709 if (!strcmp(s, *p))
710 return p-choices;
711 }
712 return -1;
713 }
714
set_by_name(const char * s)715 bool bx_param_enum_c::set_by_name(const char *s)
716 {
717 int n = find_by_name(s);
718 if (n<0) return 0;
719 set(n + min);
720 return 1;
721 }
722
set_dependent_list(bx_list_c * l,bool enable_all)723 void bx_param_enum_c::set_dependent_list(bx_list_c *l, bool enable_all)
724 {
725 dependent_list = l;
726 deps_bitmap = new Bit64u[(unsigned)(max - min + 1)];
727 for (int i=0; i<(max-min+1); i++) {
728 if (enable_all) {
729 deps_bitmap[i] = (1 << (l->get_size())) - 1;
730 } else {
731 deps_bitmap[i] = 0;
732 }
733 }
734 update_dependents();
735 }
736
set_dependent_bitmap(Bit64s value,Bit64u bitmap)737 void bx_param_enum_c::set_dependent_bitmap(Bit64s value, Bit64u bitmap)
738 {
739 if (deps_bitmap != NULL) {
740 deps_bitmap[value - min] = bitmap;
741 }
742 update_dependents();
743 }
744
get_dependent_bitmap(Bit64s value)745 Bit64u bx_param_enum_c::get_dependent_bitmap(Bit64s value)
746 {
747 if (deps_bitmap != NULL) {
748 return deps_bitmap[value - min];
749 }
750 return 0;
751 }
752
update_dependents()753 void bx_param_enum_c::update_dependents()
754 {
755 if ((dependent_list != NULL) && (deps_bitmap != NULL)) {
756 Bit64u en_bmap = deps_bitmap[val.number - min];
757 Bit64u mask = 0x1;
758 for (int i=0; i<dependent_list->get_size(); i++) {
759 int en = (en_bmap & mask) && enabled;
760 bx_param_c *param = dependent_list->get(i);
761 if (param != this)
762 param->set_enabled(en);
763 mask <<= 1;
764 }
765 }
766 }
767
set_enabled(bool en)768 void bx_param_enum_c::set_enabled(bool en)
769 {
770 // The enable handler may wish to allow/disallow the action
771 if (enable_handler) {
772 en = (*enable_handler)(this, en);
773 }
774 bx_param_c::set_enabled(en);
775 update_dependents();
776 }
777
parse_param(const char * ptr)778 int bx_param_enum_c::parse_param(const char *ptr)
779 {
780 if (ptr != NULL) {
781 return set_by_name(ptr);
782 }
783
784 return 0;
785 }
786
dump_param(FILE * fp)787 void bx_param_enum_c::dump_param(FILE *fp)
788 {
789 fprintf(fp, "%s", get_selected());
790 }
791
dump_param(char * buf,int len,bool dquotes)792 int bx_param_enum_c::dump_param(char *buf, int len, bool dquotes)
793 {
794 snprintf(buf, len, "%s", get_selected());
795 return strlen(buf);
796 }
797
bx_param_string_c(bx_param_c * parent,const char * name,const char * label,const char * description,const char * initial_val,int maxsize)798 bx_param_string_c::bx_param_string_c(bx_param_c *parent,
799 const char *name,
800 const char *label,
801 const char *description,
802 const char *initial_val,
803 int maxsize)
804 : bx_param_c(SIM->gen_param_id(), name, label, description)
805 {
806 set_type(BXT_PARAM_STRING);
807 int initial_val_size = strlen(initial_val) + 1;
808 if (maxsize < 0) {
809 maxsize = initial_val_size;
810 } else if (initial_val_size > maxsize) {
811 initial_val_size = maxsize;
812 }
813 this->val = new char[maxsize];
814 this->initial_val = new char[maxsize];
815 this->handler = NULL;
816 this->enable_handler = NULL;
817 this->maxsize = maxsize;
818 strncpy(this->val, initial_val, initial_val_size);
819 if (maxsize > initial_val_size)
820 memset(this->val + initial_val_size, 0, maxsize - initial_val_size);
821 strncpy(this->initial_val, initial_val, maxsize);
822 this->options = 0;
823 set(initial_val);
824 if (parent) {
825 BX_ASSERT(parent->get_type() == BXT_LIST);
826 this->parent = (bx_list_c *)parent;
827 this->parent->add(this);
828 }
829 }
830
~bx_param_string_c()831 bx_param_string_c::~bx_param_string_c()
832 {
833 delete [] val;
834 delete [] initial_val;
835 }
836
reset()837 void bx_param_string_c::reset()
838 {
839 set(initial_val);
840 }
841
set_handler(param_string_event_handler handler)842 void bx_param_string_c::set_handler(param_string_event_handler handler)
843 {
844 this->handler = handler;
845 }
846
set_enable_handler(param_enable_handler handler)847 void bx_param_string_c::set_enable_handler(param_enable_handler handler)
848 {
849 this->enable_handler = handler;
850 }
851
update_dependents()852 void bx_param_string_c::update_dependents()
853 {
854 if (dependent_list) {
855 int en = (strlen(val) > 0) && (strcmp(val, "none")) && enabled;
856 for (int i=0; i<dependent_list->get_size(); i++) {
857 bx_param_c *param = dependent_list->get(i);
858 if (param != this)
859 param->set_enabled(en);
860 }
861 }
862 }
863
set_enabled(bool en)864 void bx_param_string_c::set_enabled(bool en)
865 {
866 // The enable handler may wish to allow/disallow the action
867 if (enable_handler) {
868 en = (*enable_handler)(this, en);
869 }
870 bx_param_c::set_enabled(en);
871 if (dependent_list != NULL) update_dependents();
872 }
873
set_dependent_list(bx_list_c * l)874 void bx_param_string_c::set_dependent_list(bx_list_c *l)
875 {
876 dependent_list = l;
877 update_dependents();
878 }
879
get(char * buf,int len)880 Bit32s bx_param_string_c::get(char *buf, int len)
881 {
882 strncpy(buf, val, len);
883 if (handler) {
884 // the handler can choose to replace the value in val/len. Also its
885 // return value is passed back as the return value of get.
886 (*handler)(this, 0, buf, buf, len);
887 }
888 return 0;
889 }
890
set(const char * buf)891 void bx_param_string_c::set(const char *buf)
892 {
893 char *oldval = new char[maxsize];
894
895 strncpy(oldval, val, maxsize);
896 oldval[maxsize - 1] = 0;
897 if (handler) {
898 // the handler can return a different char* to be copied into the value
899 buf = (*handler)(this, 1, oldval, buf, -1);
900 }
901 strncpy(val, buf, maxsize);
902 val[maxsize - 1] = 0;
903 delete [] oldval;
904 if (dependent_list != NULL) update_dependents();
905 }
906
equals(const char * buf) const907 bool bx_param_string_c::equals(const char *buf) const
908 {
909 return (strncmp(val, buf, maxsize) == 0);
910 }
911
set_initial_val(const char * buf)912 void bx_param_string_c::set_initial_val(const char *buf)
913 {
914 strncpy(initial_val, buf, maxsize);
915 set(initial_val);
916 }
917
isempty() const918 bool bx_param_string_c::isempty() const
919 {
920 return (strlen(val) == 0) || !strcmp(val, "none");
921 }
922
parse_param(const char * ptr)923 int bx_param_string_c::parse_param(const char *ptr)
924 {
925 if (ptr != NULL) {
926 set(ptr);
927 } else {
928 set("");
929 }
930
931 return 1;
932 }
933
dump_param(FILE * fp)934 void bx_param_string_c::dump_param(FILE *fp)
935 {
936 char tmpstr[BX_PATHNAME_LEN+1];
937 dump_param(tmpstr, BX_PATHNAME_LEN, 0);
938 fputs(tmpstr, fp);
939 }
940
dump_param(char * buf,int len,bool dquotes)941 int bx_param_string_c::dump_param(char *buf, int len, bool dquotes)
942 {
943 if (!isempty()) {
944 if (dquotes) {
945 snprintf(buf, len, "\"%s\"", val);
946 } else {
947 snprintf(buf, len, "%s", val);
948 }
949 } else {
950 strcpy(buf, "none");
951 }
952 return strlen(buf);
953 }
954
get(char * buf,int len)955 Bit32s bx_param_bytestring_c::get(char *buf, int len)
956 {
957 memcpy(buf, val, len);
958 if (handler) {
959 // the handler can choose to replace the value in val/len. Also its
960 // return value is passed back as the return value of get.
961 (*handler)(this, 0, buf, buf, len);
962 }
963 return 0;
964 }
965
set(const char * buf)966 void bx_param_bytestring_c::set(const char *buf)
967 {
968 char *oldval = new char[maxsize];
969
970 memcpy(oldval, val, maxsize);
971 if (handler) {
972 // the handler can return a different char* to be copied into the value
973 buf = (*handler)(this, 1, oldval, buf, -1);
974 }
975 memcpy(val, buf, maxsize);
976 delete [] oldval;
977 if (dependent_list != NULL) update_dependents();
978 }
979
equals(const char * buf) const980 bool bx_param_bytestring_c::equals(const char *buf) const
981 {
982 return (memcmp(val, buf, maxsize) == 0);
983 }
984
set_initial_val(const char * buf)985 void bx_param_bytestring_c::set_initial_val(const char *buf)
986 {
987 memcpy(initial_val, buf, maxsize);
988 set(initial_val);
989 }
990
isempty() const991 bool bx_param_bytestring_c::isempty() const
992 {
993 return (memcmp(val, initial_val, maxsize) == 0);
994 }
995
parse_param(const char * ptr)996 int bx_param_bytestring_c::parse_param(const char *ptr)
997 {
998 int j, p = 0, ret = 1;
999 unsigned n;
1000 char buf[512];
1001
1002 memset(buf, 0, get_maxsize());
1003 for (j = 0; j < get_maxsize(); j++) {
1004 if (ptr[p] == get_separator()) {
1005 p++;
1006 }
1007 if (sscanf(ptr+p, "%02x", &n) == 1) {
1008 buf[j] = n;
1009 p += 2;
1010 } else {
1011 ret = 0;
1012 }
1013 }
1014 if (!equals(buf)) set(buf);
1015
1016 return ret;
1017 }
1018
dump_param(char * buf,int len,bool dquotes)1019 int bx_param_bytestring_c::dump_param(char *buf, int len, bool dquotes)
1020 {
1021 buf[0] = 0;
1022 for (int j = 0; j < maxsize; j++) {
1023 char tmpbyte[4];
1024 if (j > 0) {
1025 tmpbyte[0] = separator;
1026 tmpbyte[1] = 0;
1027 strcat(buf, tmpbyte);
1028 }
1029 sprintf(tmpbyte, "%02x", (Bit8u)val[j]);
1030 strcat(buf, tmpbyte);
1031 }
1032 return strlen(buf);
1033 }
1034
bx_param_filename_c(bx_param_c * parent,const char * name,const char * label,const char * description,const char * initial_val,int maxsize)1035 bx_param_filename_c::bx_param_filename_c(bx_param_c *parent,
1036 const char *name,
1037 const char *label,
1038 const char *description,
1039 const char *initial_val,
1040 int maxsize)
1041 : bx_param_string_c(parent, name, label, description, initial_val, maxsize)
1042 {
1043 set_options(IS_FILENAME);
1044 int len = strlen(initial_val);
1045 if ((len > 4) && (initial_val[len - 4] == '.')) {
1046 ext = &initial_val[len - 3];
1047 } else {
1048 ext = NULL;
1049 }
1050 }
1051
bx_shadow_data_c(bx_param_c * parent,const char * name,Bit8u * ptr_to_data,Bit32u data_size,bool is_text)1052 bx_shadow_data_c::bx_shadow_data_c(bx_param_c *parent,
1053 const char *name,
1054 Bit8u *ptr_to_data,
1055 Bit32u data_size,
1056 bool is_text)
1057 : bx_param_c(SIM->gen_param_id(), name, "")
1058 {
1059 set_type(BXT_PARAM_DATA);
1060 this->data_ptr = ptr_to_data;
1061 this->data_size = data_size;
1062 this->is_text = is_text;
1063 if (parent) {
1064 BX_ASSERT(parent->get_type() == BXT_LIST);
1065 this->parent = (bx_list_c *)parent;
1066 this->parent->add(this);
1067 }
1068 }
1069
get(Bit32u index)1070 Bit8u bx_shadow_data_c::get(Bit32u index)
1071 {
1072 if (index < data_size) {
1073 return data_ptr[index];
1074 } else {
1075 return 0;
1076 }
1077 }
1078
set(Bit32u index,Bit8u value)1079 void bx_shadow_data_c::set(Bit32u index, Bit8u value)
1080 {
1081 if (index < data_size) {
1082 data_ptr[index] = value;
1083 }
1084 }
1085
bx_shadow_filedata_c(bx_param_c * parent,const char * name,FILE ** scratch_file_ptr_ptr)1086 bx_shadow_filedata_c::bx_shadow_filedata_c(bx_param_c *parent,
1087 const char *name, FILE **scratch_file_ptr_ptr)
1088 : bx_param_c(SIM->gen_param_id(), name, "")
1089 {
1090 set_type(BXT_PARAM_FILEDATA);
1091 this->scratch_fpp = scratch_file_ptr_ptr;
1092 this->save_handler = NULL;
1093 this->restore_handler = NULL;
1094 if (parent) {
1095 BX_ASSERT(parent->get_type() == BXT_LIST);
1096 this->parent = (bx_list_c *)parent;
1097 this->parent->add(this);
1098 }
1099 }
1100
1101 // Save handler: called before file save, Restore handler: called after file restore
set_sr_handlers(void * devptr,filedata_save_handler save,filedata_restore_handler restore)1102 void bx_shadow_filedata_c::set_sr_handlers(void *devptr, filedata_save_handler save, filedata_restore_handler restore)
1103 {
1104 this->sr_devptr = devptr;
1105 this->save_handler = save;
1106 this->restore_handler = restore;
1107 }
1108
save(FILE * save_fp)1109 void bx_shadow_filedata_c::save(FILE *save_fp)
1110 {
1111 if (save_handler)
1112 (*save_handler)(sr_devptr, save_fp);
1113 }
1114
restore(FILE * save_fp)1115 void bx_shadow_filedata_c::restore(FILE *save_fp)
1116 {
1117 if (restore_handler)
1118 (*restore_handler)(sr_devptr, save_fp);
1119 }
1120
bx_list_c(bx_param_c * parent)1121 bx_list_c::bx_list_c(bx_param_c *parent)
1122 : bx_param_c(SIM->gen_param_id(), "list", "")
1123 {
1124 set_type(BXT_LIST);
1125 this->size = 0;
1126 this->list = NULL;
1127 this->parent = NULL;
1128 if (parent) {
1129 BX_ASSERT(parent->get_type() == BXT_LIST);
1130 this->parent = (bx_list_c *)parent;
1131 this->parent->add(this);
1132 }
1133 init("");
1134 }
1135
bx_list_c(bx_param_c * parent,const char * name)1136 bx_list_c::bx_list_c(bx_param_c *parent, const char *name)
1137 : bx_param_c(SIM->gen_param_id(), name, "")
1138 {
1139 set_type (BXT_LIST);
1140 this->size = 0;
1141 this->list = NULL;
1142 this->parent = NULL;
1143 if (parent) {
1144 BX_ASSERT(parent->get_type() == BXT_LIST);
1145 this->parent = (bx_list_c *)parent;
1146 this->parent->add(this);
1147 }
1148 this->restore_handler = NULL;
1149 init("");
1150 }
1151
bx_list_c(bx_param_c * parent,const char * name,const char * title)1152 bx_list_c::bx_list_c(bx_param_c *parent, const char *name, const char *title)
1153 : bx_param_c(SIM->gen_param_id(), name, "")
1154 {
1155 set_type (BXT_LIST);
1156 this->size = 0;
1157 this->list = NULL;
1158 this->parent = NULL;
1159 if (parent) {
1160 BX_ASSERT(parent->get_type() == BXT_LIST);
1161 this->parent = (bx_list_c *)parent;
1162 this->parent->add(this);
1163 }
1164 this->restore_handler = NULL;
1165 init(title);
1166 }
1167
bx_list_c(bx_param_c * parent,const char * name,const char * title,bx_param_c ** init_list)1168 bx_list_c::bx_list_c(bx_param_c *parent, const char *name, const char *title, bx_param_c **init_list)
1169 : bx_param_c(SIM->gen_param_id(), name, "")
1170 {
1171 set_type(BXT_LIST);
1172 this->size = 0;
1173 this->list = NULL;
1174 while (init_list[this->size] != NULL)
1175 add(init_list[this->size]);
1176 this->parent = NULL;
1177 if (parent) {
1178 BX_ASSERT(parent->get_type() == BXT_LIST);
1179 this->parent = (bx_list_c *)parent;
1180 this->parent->add(this);
1181 }
1182 this->restore_handler = NULL;
1183 init(title);
1184 }
1185
~bx_list_c()1186 bx_list_c::~bx_list_c()
1187 {
1188 if (list != NULL) {
1189 clear();
1190 }
1191 delete [] title;
1192 }
1193
init(const char * list_title)1194 void bx_list_c::init(const char *list_title)
1195 {
1196 if (list_title) {
1197 this->title = new char[strlen(list_title)+1];
1198 strcpy(this->title, list_title);
1199 } else {
1200 this->title = new char[1];
1201 this->title[0] = 0;
1202 }
1203 this->options = 0;
1204 this->choice = 1;
1205 }
1206
set_parent(bx_param_c * newparent)1207 void bx_list_c::set_parent(bx_param_c *newparent)
1208 {
1209 if (parent) {
1210 // if this object already had a parent, the correct thing
1211 // to do would be to remove this object from the parent's
1212 // list of children. Deleting children is currently
1213 // not supported.
1214 BX_PANIC(("bx_list_c::set_parent: changing from one parent to another is not supported"));
1215 }
1216 if (newparent) {
1217 BX_ASSERT(newparent->get_type() == BXT_LIST);
1218 parent = (bx_list_c *)newparent;
1219 parent->add(this);
1220 }
1221 }
1222
clone()1223 bx_list_c* bx_list_c::clone()
1224 {
1225 bx_list_c *newlist = new bx_list_c(NULL, name, title);
1226 for (int i=0; i<get_size(); i++)
1227 newlist->add(get(i));
1228 newlist->set_options(options);
1229 return newlist;
1230 }
1231
add(bx_param_c * param)1232 void bx_list_c::add(bx_param_c *param)
1233 {
1234 if ((get_by_name(param->get_name()) != NULL) && (param->get_parent() == this)) {
1235 BX_PANIC(("parameter '%s' already exists in list '%s'", param->get_name(), this->get_name()));
1236 return;
1237 }
1238 bx_listitem_t *item = new bx_listitem_t;
1239 item->param = param;
1240 item->next = NULL;
1241 if (list == NULL) {
1242 list = item;
1243 } else {
1244 bx_listitem_t *temp = list;
1245 while (temp->next)
1246 temp = temp->next;
1247 temp->next = item;
1248 }
1249 if (runtime_param) {
1250 param->set_runtime_param(1);
1251 }
1252 size++;
1253 }
1254
get(int index)1255 bx_param_c* bx_list_c::get(int index)
1256 {
1257 BX_ASSERT(index >= 0 && index < size);
1258 int i = 0;
1259 bx_listitem_t *temp = list;
1260 while (temp != NULL) {
1261 if (i == index) {
1262 return temp->param;
1263 }
1264 temp = temp->next;
1265 i++;
1266 }
1267 return NULL;
1268 }
1269
get_by_name(const char * name)1270 bx_param_c* bx_list_c::get_by_name(const char *name)
1271 {
1272 bx_listitem_t *temp = list;
1273 while (temp != NULL) {
1274 bx_param_c *p = temp->param;
1275 if (!stricmp(name, p->get_name())) {
1276 return p;
1277 }
1278 temp = temp->next;
1279 }
1280 return NULL;
1281 }
1282
reset()1283 void bx_list_c::reset()
1284 {
1285 bx_listitem_t *temp = list;
1286 while (temp != NULL) {
1287 temp->param->reset();
1288 temp = temp->next;
1289 }
1290 }
1291
clear()1292 void bx_list_c::clear()
1293 {
1294 bx_listitem_t *temp = list, *next;
1295 while (temp != NULL) {
1296 if (temp->param->get_parent() == this) {
1297 delete temp->param;
1298 }
1299 next = temp->next;
1300 delete temp;
1301 temp = next;
1302 }
1303 list = NULL;
1304 size = 0;
1305 }
1306
remove(const char * name)1307 void bx_list_c::remove(const char *name)
1308 {
1309 bx_listitem_t *item, *prev = NULL;
1310
1311 for (item = list; item; item = item->next) {
1312 bx_param_c *p = item->param;
1313 if (!stricmp(name, p->get_name())) {
1314 if (p->get_parent() == this) {
1315 delete p;
1316 }
1317 if (prev == NULL) {
1318 list = item->next;
1319 } else {
1320 prev->next = item->next;
1321 }
1322 delete item;
1323 size--;
1324 break;
1325 } else {
1326 prev = item;
1327 }
1328 }
1329 }
1330
set_runtime_param(bool val)1331 void bx_list_c::set_runtime_param(bool val)
1332 {
1333 runtime_param = val;
1334 if (runtime_param) {
1335 for (bx_listitem_t * item = list; item; item = item->next) {
1336 item->param->set_runtime_param(1);
1337 }
1338 }
1339 }
1340
set_restore_handler(void * devptr,list_restore_handler restore)1341 void bx_list_c::set_restore_handler(void *devptr, list_restore_handler restore)
1342 {
1343 sr_devptr = devptr;
1344 restore_handler = restore;
1345 }
1346
restore()1347 void bx_list_c::restore()
1348 {
1349 if (restore_handler)
1350 (*restore_handler)(sr_devptr, this);
1351 }
1352